#!/bin/sh
# The following line is a tcl comment, while sh executes it \
exec wish -f $0 $*

#! /usr/local/bin/wish -f
#
# tkpostit 1.4 - A tk-based replacement of xpostit
#
# Copyright 1993 - A Rubini - DIS - Universita` di Pavia - Italy
#
#########

# A LITTLE CODE TO SAVE TYPING

proc Set  {name value} {global cfg; set cfg($name) $value}
proc Bind {name value} {global bnd; set bnd($name) $value}
proc Menu {name value} {global mnu; set mnu($name) $value}

# DEFAULT SETTINGS FOLLOW
# You can edit this section here, or copy it to your
#   init file and configure it  (this will ease upgrading)
 
# tkPostit-1.4 begin_editable

#	The pathnames of cfg files must be known
Set system_config      /usr/local/etc/tkpostitrc
Set user_config        $env(HOME)/.tkpostit

#### Anything for this point on can be overriden by system or user cfg files

#	I need my name, in order to reconfigure
#	If missing, it is extracted from $env(PATH)
#Set my_name		./tkpostit

#	the main window is a rectangle tiled with bitmaps, you can
#	choose the bitmap and where individual bitmaps are laid down
Set canvas_width     66
Set canvas_height    66
Set canvas_bitmap    /usr/local/lib/tkpostit.bm
Set canvas_x_pos     "11 33 55"
Set canvas_y_pos     "11 33 55"

#	you can change some fonts - fixed is plain but seems ok most times.
#	Some more fonts are configured in command-bar specific cfg below
Set button_font      "fixed"

#	the directory for the notes
Set data_dir           $env(HOME)/.tkNotes

#	the chmod for your files
Set data_file_mode    640

#	a new session can remember the geometry of last session
Set remember_geometry   1

#	when a menu is invoked, the grab can be either global or local
Set grab_type        local

#    backups are made later, if allowed, to ease the workstation.
#	There can be 0,1,2 or 3 backups 
#	   (time in milliseconds)
Set backups_allowed         2
Set initial_delay       20000
Set incremental_delay    2000

#    saving of notes can be automatic, each time the mouse
#	leaves a modified text widget. Saving can also be made
#	at regular intervals. Zero means "no", otherwise is minutes.
Set save_on_modified    1
Set save_regularly     30

#	destroyed notes can be kept for one or two times (or zero)
Set keep_destroyed      0

#       text frame config:
#	width and height are different wether editing a note or a file.
Set note_init_width     20
Set note_init_height    10
Set file_init_width     80
Set file_init_height    25
Set text_wrap_mode      word
Set text_font           fixed
Set scrollbar_side      left

#	scrolling can be constrained not to go past end-of-note
Set constrained_scroll   1

#	a different color for file editing is _really_ suggested
Set text_editor_background   bisque3
Set text_editor_foreground   black

#	choose your backup suffix for file editing
Set file_backup_suff ~

#       emacs bindings or mac bindings (either emacs or mac or none)
Set emacs_bindings    1
Set mac_bindings      0

#       verbose mode? (prints to stdout some logging info)
Set verbose_mode    0

#	configure menu borders
Set menu_bg 	black
Set menu_border 1

#	are menus to be correctely positined (though they flash)
Set reposition_menu		1

#	will you pipe your note to some filter?
Set pipeout_print   {a2ps -H$name | lp >& /dev/console}

#	some note_manager features
Set manager_withdrawn ""
Set manager_iconified ""
Set manager_normal ""
Set manager_check_relief flat
Set manager_frame_relief ridge
Set manager_frame_border 2

#	configure your command bar (the thing on top of your note)
Set cmdbar_border               4
Set cmdbar_relief               groove
Set cmdbar_background_note      default
Set cmdbar_background_file      bisque3

Set cmdbar_cfg_note {
        {button .p "Print " "PipeOut print"
                {-font $cfg(button_font) -relief raised} 
                {-side left}}
        {button .d "Kill" Destroy 
                {-font $cfg(button_font) -relief raised}
                {-side right}}
        {name_entry
                {-width 12 -relief groove -font fixed}
                {-side left}}
        {button .w "Hide" "ChangeState withdraw"
                {-font $cfg(button_font) -relief raised} 
                {-side left}}
        {menu .m "Eval-menu" eval
                {-font $cfg(button_font)}
                {-side left}}
}

Set cmdbar_cfg_file {
	{button .s "Save" Save
		{-font $cfg(button_font) -relief raised} 
		{-side left}}
	{label .l "File" 
		{-font fixed}
		{-side left}}
	{button .d "Close" Destroy 
		{-font $cfg(button_font) -relief raised}
		{-side right}}
	{name_entry
		{-width 16 -relief groove -font fixed}
		{-side left}}
}

#	now choose your bindings for the main window,
#	by setting variables, to be processed later.
#	keyboard bindings can be added as well

Bind main:<1>	"MkNewWin new"
Bind main:<2>	"MkMenu main %X %Y"
Bind main:<3>	"ChangeState iconify"
Bind main:<Control-1> "MkMenu eval %X %Y"
Bind main:<Control-3> "MkMenu eval %X %Y"

Bind main:<q>   "SaveAllNotes; exit"
Bind main:<m>	"MkMenu main %X %Y"

Bind main:<Control-c> "exit"

#	These one are the bindings for the note window
#	and follow the same rules as for the main window

Bind note:<Control-1> "MkMenu window %X %Y"
Bind note:<Control-2> "MkMenu sleep %X %Y"
Bind note:<Control-3> "MkMenu eval %X %Y"

#	now build your menus
#	in a manner similar to twm and friends

Menu main {
	{ label "tkPostit-1.4" }
	{ button "save all"  SaveAllNotes }
	{ button "withdraw all" "ChangeState withdraw" }
	{ button "iconify all" "ChangeState iconify"}
	{ button "show all" "ChangeState deiconify" }
	{ button "manage them" NoteManager}
	{ button "restart"  Restart }
	{ button "quit"      "SaveAllNotes; exit" }
}

Menu sleep {
	{ label "Sleep menu"}
	{ button "1 minute" "MkSleeper 1" }
	{ button "5 minutes" "MkSleeper 5" }
	{ button "15 minutes" "MkSleeper 15" }
	{ button "30 minutes" "MkSleeper 30" }
	{ button "45 minutes" "MkSleeper 45" }
	{ button "60 minutes" "MkSleeper 60" }
}

Menu window {
	{ label "Window opions"}
	{ button "withdraw" "ChangeState withdraw me" }
	{ button "iconify" "ChangeState iconify me"}
	{ button "quit"      "SaveAllNotes; exit" }
	{ button "restart"  Restart }
}

Menu eval {
	{ label "Evaluate commands"}
	{ button "cd [selection get]" "MkEval {cd [selection get]}" }
	{ button "tcl_eval [selection get]" "MkEval {eval [selection get]}" }
	{ button "csh -c [selection get]"
				"MkEval {exec csh -c [selection get]}" }
	{ button "sh -c [selection get]"
				"MkEval {exec sh -c [selection get]}" }
	{ button "edit [selection get]" "MkNewWin -file [selection get]" }
	{ button "eval-current-buffer" 
				"MkEval {eval [$cfg(current).t get 0.0 end]}"}
}


# tkPostit-1.4 end_editable
############################# NO MORE EDITING AFTER THIS LINE

#------------------------------  load user-defined overrides

if [file isfile $cfg(system_config)] {source $cfg(system_config)}
if [file isfile $cfg(user_config)] {source $cfg(user_config)}

#------------------------------ provide default empty procedures
#				and an empty array

foreach n {Say SleepMinutes} {
	eval proc $n args \{\}
}

#------------------------------ some fixing

set top_wins(foo) bar
if ![string compare $cfg(grab_type) global] {
	Set grab_type -global} else {Set grab_type set}

bind Text <Right> {%W mark set insert {insert +1c}}
bind Text <Left> {%W mark set insert {insert -1c}}
bind Text <Up> {%W mark set insert {insert -1l}}
bind Text <Down> {%W mark set insert {insert +1l}}

#------------------------------ make emacs bindings

if $cfg(emacs_bindings) {

    bind Text <Control-w> {
        if [llength [%W tag ranges sel]] {
            %W delete sel.first sel.last; incr cfg(modified)}
        }
    bind Text <Control-d> {%W delete insert; incr cfg(modified)}
    bind Text <2> {
        %W mark set insert @%x,%y
        %W insert insert [selection get]
        %W yview -pickplace insert
        incr cfg(modified)
        }
    bind Text <3> {
        %W mark set anchor insert
	if [%W compare insert < @%x,%y] {
	    %W tag add sel insert @%x,%y
	} else {
            %W tag add sel @%x,%y insert
	}
	set tkp_sel [%W tag ranges sel]
	%W tag remove sel 0.0 end
	%W tag add sel [lindex $tkp_sel 0] \
		[lindex $tkp_sel [expr [llength $tkp_sel]-1]]
        }
    bind Text <Control-k> {
        if ![string compare [%W get insert] "\n"] {
            %W delete insert} else {
            %W delete insert {insert lineend}
        incr cfg(modified)
        }
    }
    bind Text <Control-a> {%W mark set insert {insert linestart}}
    bind Text <Control-e> {%W mark set insert {insert lineend}}
    bind Text <Control-f> {%W mark set insert {insert +1c}}
    bind Text <Control-b> {%W mark set insert {insert -1c}}
    bind Text <Control-n> {%W mark set insert {insert +1l}}
    bind Text <Control-p> {%W mark set insert {insert -1l}}
}

#------------------------------ make mac bindings
#		 code by Hoshi Takanori (hoshi@sras31.sra.co.jp)

if $cfg(mac_bindings) {

    proc Mac_del_selection {win} {
	set result 0
	set sel [$win tag nextrange sel 1.0]
	if {$sel != ""} {
            if {[$win compare insert >= sel.first] && \
        	[$win compare insert <= sel.last]} {
        	$win delete sel.first sel.last
        	set result 1
            }
	}
	return $result
    }
    proc Mac_ins_char {win c} {
	if {$c == "\n" || $c == "\t" || $c >= " "} {
    	    Mac_del_selection $win
            $win insert insert $c
            $win yview -pickplace insert
	}
    }
    proc Mac_del_char {win} {
	if {[Mac_del_selection $win] == 0} { tk_textBackspace $win }
	$win yview -pickplace insert
    }
    proc Mac_mv_caret {win state dir} {
	set mod [case $dir in {
            up              { format "- 1 lines" }
            down            { format "+ 1 lines" }
            left            { format "- 1 chars" }
            right           { format "+ 1 chars" }
            linestart       { format "linestart" }
            lineend         { format "lineend" }
            wordstart       { format "- 1 chars wordstart" }
            wordend         { format "wordend" }
	}]
	if {$mod != ""} {
            if {$state & 1} {
        	tk_textResetAnchor $win insert
        	tk_textSelectTo $win [$win index "insert $mod"]
            }
            $win mark set insert [$win index "insert $mod"]
	}

	$win yview -pickplace insert
    }
    proc Mac_clr_selection win {
	global tk_priv
	set tk_priv(selectMode) char
	$win mark set anchor insert
	tk_textSelectTo $win insert
    }

    bind Text <3> {tk_textResetAnchor %W @%x,%y; tk_textSelectTo %W @%x,%y}
    bind Text <B3-Motion> {tk_textSelectTo %W @%x,%y}

    bind Text <Any-KeyPress>        { Mac_ins_char %W "%A" }
    bind Text <Return>              { Mac_ins_char %W "\n" }
    bind Text <BackSpace>           { Mac_del_char %W }
    bind Text <Delete>              { Mac_del_char %W }
    bind Text <Control-h>           { Mac_del_char %W }
    bind Text <Shift-space>         { Mac_clr_selection %W }

    bind Text <Up>                  { Mac_mv_caret %W %s up }
    bind Text <Down>                { Mac_mv_caret %W %s down }
    bind Text <Left>                { Mac_mv_caret %W %s left }
    bind Text <Right>               { Mac_mv_caret %W %s right }

    bind Text <Control-p>           { Mac_mv_caret %W %s up }
    bind Text <Control-n>           { Mac_mv_caret %W %s down }
    bind Text <Control-b>           { Mac_mv_caret %W %s left }
    bind Text <Control-f>           { Mac_mv_caret %W %s right }

    bind Text <Escape><b>           { Mac_mv_caret %W %s wordstart }
    bind Text <Escape><B>           { Mac_mv_caret %W %s wordstart }
    bind Text <Escape><f>           { Mac_mv_caret %W %s wordend }
    bind Text <Escape><F>           { Mac_mv_caret %W %s wordend }
    bind Text <Control-a>           { Mac_mv_caret %W %s linestart }
    bind Text <Control-e>           { Mac_mv_caret %W %s lineend }

    bind Text <Control-v> {
	%W insert insert [selection get]
	%W yview -pickplace insert
    }
    tk_bindForTraversal Text
}

#------------------------------ verbose or not?

if $cfg(verbose_mode) {
    proc Say str {puts stderr $str}
}

#------------------------------ auto-save on leave

bind tkNote <Enter> {Set current %W; focus %W.t}
bind tkNoteFile <Enter> {Set current %W; focus %W.t}

if $cfg(save_on_modified) { 
    bind Text <Any-Key> "incr cfg(modified);[ bind Text <Any-Key>]"
    bind Text <Any-Button> "incr cfg(modified);[ bind Text <Any-Button>]"
    bind Text <Enter> {set cfg(modified) 0}
    bind Text <Leave> {
        if $cfg(modified) { Save [lindex [split %W .] 1] }
    }
}

#------------------------------ auto-save on regular basis

if $cfg(save_regularly) {

    proc SleepMinutes {} {
	global cfg
        if ![incr cfg(minutes_left) -1] {
	    SaveAllNotes
	    set cfg(minutes_left) $cfg(save_regularly) 
	}
	after 60000 SleepMinutes
    }
    set cfg(minutes_left) $cfg(save_regularly) 
    after 60000 SleepMinutes
}

#------------------------------ check directory and load previous geometry
#				 (but -geometry takes priority)

if ![file isdir $cfg(data_dir)] "exec mkdir -p $cfg(data_dir)"

if {$cfg(remember_geometry) && [string match "*+0+0" [wm geometry .] ]} {
    if [file isfile $cfg(data_dir)/geometry] {
        set F [open $cfg(data_dir)/geometry r]
        wm geometry . [gets $F]
        close $F
    }
}

###########################################################
#
# what follows now is a series of procedures


#------------------------------ create a new toplevel and its hierarchy

proc MkNewWin {name {detail ""}} {
    global cfg bnd top_wins

    if ![string compare $name new] {
        for {set n 0} {[info exists top_wins(note$n)]} {incr n} {}
        set name note$n
        }

    set is_file 0; set class tkNote
    if ![string compare $name "-file"] {
        for {set n 0} {[info exists top_wins(file$n)]} {incr n} {}
        set name file$n; set is_file 1; set class tkNoteEdit
	set top_wins(fname:$name) $detail
        }

    set top_wins($name) .$name
    set win [toplevel .$name -class $class]

    frame $win.f  -borderwidth $cfg(cmdbar_border) -relief $cfg(cmdbar_relief)
    set back $cfg(cmdbar_background_note)
    if $is_file {set back $cfg(cmdbar_background_file)}
    if [string compare $back default] {	$win.f configure -background $back}

    set struct $cfg(cmdbar_cfg_note)
    if $is_file {set struct $cfg(cmdbar_cfg_file)}

# now build the commandbar using the table

    foreach i $struct {
	#most times the first item is the name of the widget
	set w $win.f[lindex $i 1]
	#while the zeroth one is the type of widget
	switch [lindex $i 0] {
	    button {
		button $w -text [lindex $i 2] -command \
				[concat [lindex $i 3] $win]
		set indexes "4 5"
		}
	    label {
		label $w -text [lindex $i 2]
		set indexes "3 4"
		}
	    menu {
		button $w -text [lindex $i 2]
		bind $w <Any-Button> "MkMenu [lindex $i 3] \
			\[winfo rootx %W\] \
			\[expr \[winfo rooty %W\]+\[winfo height %W\]\] \
			exact"
		set indexes "4 5"
		}
	    name_entry {
		# entry management is hardwired
		set w $win.f.name_entry
		entry $w
		bind $w <Return> {MkNewName %W [%W get]}
	 	bind $w <Leave> {
                    if {![string compare [focus] %W]} {MkNewName %W [%W get]}
                    focus none
		    }
		set indexes "1 2"
		}
	    }
	eval $w configure [lindex $i [lindex $indexes 0]]
	eval pack $w [lindex $i [lindex $indexes 1]]
	}

        text $win.t -wrap $cfg(text_wrap_mode) -width $cfg(note_init_width) \
	    -height $cfg(note_init_height) -yscroll "CatchScroll $win"

    if $cfg(constrained_scroll) {
	set command "ConstrainedScroll $win"
    } else {
	set command "$win.t yview"
    }
    scrollbar $win.sb -command $command -orient vertical

    # now fill type-specific things

    if !$is_file {$win.f.name_entry insert 0 $name} else {
	$win.f.name_entry insert 0 $detail
	$win.f.name_entry config -state disabled
	$win.t configure -width $cfg(file_init_width) \
		-height $cfg(file_init_height) \
		-background $cfg(text_editor_background) \
		-foreground $cfg(text_editor_foreground)
	}
    pack $win.f -side top -fill x
    pack $win.sb -side $cfg(scrollbar_side) -fill y
    pack $win.t -side right -fill both -expand true
# make it resizable
    wm minsize $win 1 1

# If we're loading a file or note, do it now (and force a backup copy)

    if {$is_file && ![catch {set F [open $detail r]}]} {
	if [catch {exec cp -p $detail ${detail}$cfg(file_backup_suff)} res] {
	    tk_dialog .diag "Oops" \
		"can't write backup for \"$detail\":\n$res" "" 0 Ok
	    unset top_wins($name); destroy .$name; return ""}
        wm title $win $detail
	wm iconname $win [file tail $detail]
        while {[gets $F string] != -1} {
            $win.t insert end "$string\n"
            }
        close $F
	$win.t delete end-1c
        } \
    elseif [file isfile $cfg(data_dir)/$name] {
        set F [open $cfg(data_dir)/$name r]
        $win.f.name_entry delete 0 end
        $win.f.name_entry insert 0 [gets $F]
        wm title $win [$win.f.name_entry get]
        wm geometry $win [gets $F]
	gets $F str
        if ![string compare $str iconic] {wm iconify .$name}
	if ![string compare $str withdrawn] {wm withdraw .$name}
        while {[gets $F string] != -1} {
            $win.t insert end "$string\n"
            }
        close $F
	$win.t delete end-1c
        }

# we're done, just make bindings....

    foreach n [array names bnd] {
        if [string match note:* $n] {
            bind $win.t [string range $n 5 end] $bnd($n)
        }
    }
}

#------------------------------ return the toplevel name

proc BaseName name {return .[lindex [split $name .] 1]}

#------------------------------ give a name to the toplevel

proc MkNewName {win name} {
  set base [BaseName $win]
  wm title $base $name
  wm iconname $base $name
}

#------------------------------ constrained scroll for text widget
#	thanks to Gregor Schmid (schmid@fb3-s7.math.tu-berlin.de)

proc CatchScroll {win a b c d} {
    global cfg
    Set _scroll_tot_$win $a
    Set _scroll_cur_$win $b
    $win.sb set $a $b $c $d
}

proc ConstrainedScroll {win start} {
    global cfg
    set total $cfg(_scroll_tot_$win)
    set current $cfg(_scroll_cur_$win)
    if {$total < $current} {
	$win.t yview 0
    } elseif {$total - $start < $current} {
	$win.t yview [expr $total-$current]
    } else {
	$win.t yview $start
    }
} 

#------------------------------ Save to file

proc Save name {
    global cfg top_wins
    if [string match note* $name] {
    	set F [open $cfg(data_dir)/$name w]
    	puts $F [wm title .$name]
    	puts $F [wm geometry .$name]
    	puts $F [wm state .$name]
    	puts $F [.$name.t get 0.0 end]
    	close $F
    	exec chmod $cfg(data_file_mode) $cfg(data_dir)/$name
	} else {

    # otherwise, it is a file
	if [catch {set F [open $top_wins(fname:$name) w]}] {
	    tk_dialog .diag "Oops" \
		"can't open $top_wins(fname:$name) for writing" "" 0 Ok
	    } else {puts $F [.$name.t get 0.0 end]; close $F}
	}
    Say "saved $name"
}

proc SaveAllNotes {} {
    global top_wins cfg
    foreach n [array names top_wins] {
        if [string match note* $n] {Save $n}
    }
# always save geometry
    set F [open $cfg(data_dir)/geometry w]
    puts $F [wm geometry .]
    close $F
}

#------------------------------  Modify the state of our notes

proc ChangeState {action args} {
    global top_wins cfg
    if [llength $args]==1 {set win $cfg(current)}
    if [llength $args]==2 {set win [lindex $args 1]}

    if [llength $args] {
	    wm positionfrom $win user
	    wm $action $win
	    wm positionfrom $win program
            return ""
    }    
    foreach n [array names top_wins]  {
        if [string match note* $n] {
	    wm positionfrom .$n user
	    wm $action .$n
	    wm positionfrom .$n program
        }
    }
}

# ------------------------------ PipeOut a note 

proc PipeOut {mode win} {
    global top_wins cfg
    set name [$win.f.name_entry get]
    eval exec $cfg(pipeout_$mode) << \{[$win.t get 0.0 end]\}
}
    
#------------------------------  Destroy note

proc Destroy name {
    global cfg win
    if {"[string index $name 0]"=="."} {set name [string range $name 1 end]}
    set q .$name.query
    catch {destroy $q}
    frame $q -borderwidth 4 -relief ridge -background gray
    label $q.l -text \
        "Destroy window \"[wm title .$name]\"?"
    frame $q.f
    button $q.f.yes -text Yes -font $cfg(button_font) -command "
	grab release $q
        unset top_wins($name)
        RemoveFile $cfg(data_dir)/$name
        destroy .$name
        "
    button $q.f.no -font $cfg(button_font) -text No -command "destroy $q"
    pack $q.f.yes  $q.f.no -side left -padx 5 -pady 5 \
        -fill both -expand true
    pack $q.l $q.f -ipadx 5 -ipady 5 -fill both -expand true
    place $q -in .$name.t -relx .5 -rely .5 -anchor center
    raise .$name
    update
    grab $cfg(grab_type) $q
    tkwait w $q
    grab release $q
#   ^^^^ it seems to be already released, but I'm not sure... 
}

#------------------------------ Remove a file (but optionally keep backup)

proc RemoveFile fname {
    global cfg
    if $cfg(keep_destroyed)<3 {catch {exec rm $fname.dd}}
    if $cfg(keep_destroyed)<2 {catch {exec rm $fname.d}}
    if $cfg(keep_destroyed)==0 {catch {exec rm $fname}}
    catch {exec mv $fname.d $fname.dd}
    catch {exec mv $fname $fname.d}
    Say "deleted $fname"
    }


#------------------------------ Post a menu

proc MkMenu {name x y {exact ""}} {
    global mnu cfg
    catch "destroy .t"
    toplevel .t -background $cfg(menu_bg)
    wm withdraw .t
    wm overrideredirect .t 1
    pack [frame .t.f] -padx $cfg(menu_border) -pady $cfg(menu_border)
# the old semantics is no more supported
    set i 0
    foreach item $mnu($name) {incr i; switch [lindex $item 0] {
	"button" {
	    pack [button .t.f.b$i -text [lindex $item 1] \
	      -command "grab release .t;  [lindex $item 2];
	       catch {destroy .t};" -font $cfg(button_font)] -fill x 
	    bind .t.f.b$i <Any-ButtonRelease> "%W invoke"}
	"label" {
	    pack [label .t.f.b$i  -text [lindex $item 1]] -fill x
	    bind .t.f.b$i <Any-ButtonRelease> "destroy .t"}
	default {
	    error "unknown tag in item \"$item\" (position $i of menu $name)"}
        }
    }
    wm geometry .t +$x+$y
    wm deiconify .t

# maybe I need updating
    if $cfg(reposition_menu) update

    if ![string length $exact] {
        incr x [expr -[winfo width .t.f.b1]/2]
        incr y [expr -[winfo height .t.f.b1]/2]

	if {$y+[winfo height .t]>$cfg(displ_height)} {
	    set y [expr $cfg(displ_height)-[winfo height .t]]
	    }
	if {$x+[winfo width .t]>$cfg(displ_width)} {
	    set x [expr $cfg(displ_width)-[winfo width .t]]
	    }
	}
    wm geometry .t +$x+$y
    update
    bind .t <Any-Button> "destroy .t"
    grab $cfg(grab_type) .t
    tkwait w .t
    grab release .t
}


#------------------------------ manage backups

proc MkBackup fname {
    global cfg
    if ![catch "exec cmp $fname $fname.o"] {
	Say "no need to backup $fname"
        return
    }
    if $cfg(backups_allowed)>2 {catch {exec rm $fname.ooo}}
    if $cfg(backups_allowed)==2 {catch {exec rm $fname.oo}}
    if $cfg(backups_allowed)==1 {catch {exec rm $fname.o}}
    catch {exec mv $fname.oo $fname.ooo}
    catch {exec mv $fname.o $fname.oo}
    catch {exec cp $fname $fname.o}
    Say "backups done for $fname"
}

#------------------------------ hide yourself for some times

proc MkSleeper time {
    global cfg
    wm positionfrom $cfg(current) user
    wm withdraw $cfg(current)
    eval after [expr $time*60000] \
	\{wm deiconify $cfg(current)\;wm positionfrom $cfg(current) program\}
}

#------------------------------ evaluate sth

proc MkEval program {
    global cfg
    catch "uplevel #0 $program" result_string
    $cfg(current).t insert insert $result_string
}

#------------------------------ manage the state of your notes

proc NoteManager {args} {
    global cfg top_wins state

    if {"$args"!="reconfig"} {
	catch {destroy .nm}
	toplevel .nm
	} else {eval destroy [winfo children .nm]}

    foreach n [lsort [array names top_wins]] {
	if [string match note* $n] {
	    set state($n) [wm state .$n]
	    pack [frame .nm.$n -relief $cfg(manager_frame_relief) \
		-borderwidth $cfg(manager_frame_border)] \
			 -side top -fill x -expand 1
	    pack [radiobutton .nm.$n.n -relief $cfg(manager_check_relief) \
		-command "ChangeState deiconify -win .$n" \
		-text  $cfg(manager_withdrawn)\
		-variable state($n) -value normal] -side right
	    pack [radiobutton .nm.$n.i -relief $cfg(manager_check_relief) \
		-command "ChangeState iconify -win .$n" \
		-text  $cfg(manager_iconified)\
		-variable state($n) -value iconic] -side right
	    pack [radiobutton .nm.$n.w -relief $cfg(manager_check_relief) \
		-command "ChangeState withdraw -win .$n" \
		-text  $cfg(manager_normal)\
		-variable state($n) -value withdrawn] -side right
	    pack [label .nm.$n.lab -text [.$n.f.name_entry get]] \
			-side left -expand 1 -fill x
	    }
	}

    pack [frame .nm.butt] -side bottom -fill x -ipady 2 -expand  1
    pack [button .nm.butt.again -text "Again" \
		 -command "NoteManager reconfig"] \
		-side left
    pack [button .nm.butt.done -text "Done" \
		-command "destroy .nm; unset state"] \
		-side right -expand 1 -fill x

MkNewName .nm "NoteManager"
}

#------------------------------ reconfigure yourself

proc Restart {} {
    global cfg env
# look for your name
    if ![info exists cfg(my_name)] {
	foreach n [split $env(PATH) :] {
	    if [file executable $n/tkpostit] {
		Set my_name $n/tkpostit; break;
    }	}   }
    SaveAllNotes
    foreach n [winfo children .] {
	destroy $n
	}
    after 1000 {source $cfg(my_name)}
}
#############################################################################
#           NO MORE PROCEDURES, THIS IS EXECUTED AT STARTUP

#>>> load files (and make backups some seconds later)

foreach n [glob -nocomplain $cfg(data_dir)/note*\[0-9\]] {
    MkNewWin [file tail $n]
    if $cfg(backups_allowed) {
        after [expr "$cfg(initial_delay) +\
	    $cfg(incremental_delay)*[string range [file tail $n] 4 end]"] \
            "MkBackup $n"
    }
}

#>>> build the main window

pack [canvas .c -height $cfg(canvas_height) -width $cfg(canvas_width)]

foreach x $cfg(canvas_x_pos) {foreach y $cfg(canvas_y_pos) {
    .c create bitmap $x $y -bitmap @$cfg(canvas_bitmap)}
}

bind .c <Enter> "focus .c"
bind .c <Leave> "focus none"

foreach n [array names bnd] {
    if [string match main:* $n] {bind .c [string range $n 5 end] $bnd($n)}
}

# now, in order for the wm to trace movements of windows, tell him
# position is program drive, but first sync the display...

update

foreach n [array names top_wins] {
    if [string match note* $n] {wm positionfrom .$n program}
}

Set displ_height [winfo screenheight .]
Set displ_width [winfo screenwidth .]



