# Cupcake - a multi-platform text editor written using Tcl/Tk.
# Rick Smereka, Copyright (C) 2004-2007.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, get a copy via the Internet at
# http://gnu.org/copyleft/gpl.html or write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA

# You can contact the author via email at rsmereka@future-lab.com

# Initial version Feb/2004, Rick Smereka

# Adapted from a sample editor in pages 319-335 of Eric
# Foster-Johnson's book Graphical Applications with
# Tcl & Tk Second Edition.

# Corrected situation where file is loaded upon launch (argv) and the
# file name is not put into the window title, not put into the 
# 'textedit' array and the directory name is not put into the 'prefs'
# array. May/2006, Rick Smereka

# Placed an 'update' command before the call to 'prefs_load' since,
# in my testing, on Max OSX 10.4.8 an error is flagged if the preference
# file does not exist instead of the warning dialog. This happens
# because, for some reason, on the Mac, the main editor window has not
# appeared at this point. Jan/2007, Rick Smereka

# required path to library modules
set TCLDIR /home/rick/gpl/tcl

# include font dialog
source $TCLDIR/lib/tk/fontdlg.tcl

# include find dialog
source $TCLDIR/lib/tk/finddlg.tcl

# include cut, copy and paste features
source $TCLDIR/lib/tk/cutcopy.tcl

# include user prefrence save/load
source $TCLDIR/lib/prefs.tcl

# include parse module
source $TCLDIR/lib/parse.tcl

# constant support
source $TCLDIR/lib/spec.tcl

# path dialog
source $TCLDIR/lib/tk/pathdlg.tcl

# preferences dialog
source $TCLDIR/apps/cupcake/prefsdlg.tcl

# text widget procedures
source $TCLDIR/lib/tk/tw.tcl

# goto line dialog
source $TCLDIR/lib/tk/gotodlg.tcl

# print feature (Windoze only)
if {$tcl_platform(platform) == "windows"} {
   source $TCLDIR/lib/tk/winprint.tcl
}

# global option defaults
# start in current dir
set prefs(lastdirectory) [pwd]

# default save name
set textedit(save_name) "Untitled"

# application name
set textedit(appname) cupcake

# program version
set textedit(version) "1.09.02-2007.01.20"

# modified indicator
set textedit(file_changed) 0

# word wrap
set prefs(wordwrap) 1

# window geometry
set prefs(geometry) 0

# save/restore window position? (0=no,1=yes)
set prefs(srwinpos) 1

# save/restore window size? (0=no,1=yes)
set prefs(srwinsize) 1

# save/restore open/save path (0=no,1=last,2=specific dir)
set prefs(sropensave) 0

# save/restore font (0=no,1=last,2=specific font)
set prefs(srfont) 0

# font details
set prefs(fontfamily) 0
set prefs(fontsize) 0
set prefs(fontunderline) 0
set prefs(fontoverstrike) 0
set prefs(fontslant) 0
set prefs(fontweight) 0

# save/restore word wrap (0=no,1=yes)
set prefs(srwordwrap) 1

# status line
set prefs(statusline) 1

# save/restore status line (0=no,1=yes)
set prefs(srstatusline) 0

# preference file location (you must create this directory)
set textedit(pref_file) $TCLDIR/prefs/cupcake_prefs.tcl

# preference save/restore constants
const SR_NO 0
const SR_LAST 1
const SR_SPEC 2

# status line constants
const STAT_MES1 9
const STAT_MES2 40

global textedit
global prefs
global SR_NO SR_LAST SR_SPEC
global STAT_MES1 STAT_MES2

proc set_title {} {
   # Set the window title.
   global textedit

   if {$textedit(file_changed)} {
      set title "$textedit(appname) - *$textedit(save_name)"
   } else {
      set title "$textedit(appname) - $textedit(save_name)"
   }

   wm title .edit $title
}

proc setstatus {} {
   # Update the status line.
   global textedit STAT_MES1 STAT_MES2

   set frm .edit.status
   set row 0
   set col 0
   set lines 0

   # area 1 is the file changed status
   if {$textedit(file_changed)} {
      $frm.mes1 configure -text [rpad "Modified" " " $STAT_MES1]
   } else {
      $frm.mes1 configure -text [rpad "Unchanged" " " $STAT_MES1]
   }

   set mes [.edit.main.text index insert]

   if {![ll_word $mes row 1 .]} {
      return
   }

   if {![ll_word $mes col 2 .]} {
      return
   }

   incr col
   set mes [.edit.main.text index {end - 1 char}]

   if {![ll_word $mes lines 1 .]} {
      return
   }

   set mes "Line: $row  Column: $col  Total Lines: $lines"
   $frm.mes2 configure -text [rpad $mes " " $STAT_MES2]
}

proc toggle_wrap {} {
   # Set word wrap on if off and off if on.
   global prefs

   if {$prefs(wordwrap)} {
      set prefs(wordwrap) 0
   } else {
      set prefs(wordwrap) 1
   }

   set_wrap
}

proc set_wrap {} {
   # Modify word wrap
   global prefs

   set frm .edit.main.text
   
   if {$prefs(wordwrap)} {
      $frm configure -wrap word
   } else {
      $frm configure -wrap none
   }
}

proc toggle_status {} {
   # Set stat line on if off and off if on.
   global prefs

   if {$prefs(statusline)} {
      set prefs(statusline) 0
   } else {
      set prefs(statusline) 1
   }

   set_status
}

proc set_status {} {
   # Turn status line on or off.
   global prefs

   set frm .edit.status

   if {$prefs(statusline)} {
      pack $frm -fill x -side bottom
   } else {
      pack forget $frm
   }
}

proc menubar_create {toplevel menubar} {
   # Create an old-style menubar.
   frame $menubar -borderwidth 2 -relief raised
   pack $menubar -side top -fill x
}

proc menu_create {menubar menu button text mnemonic} {
   # Creates a menubutton and its associated menu.
   global tk_version

   if {$mnemonic >= 0} {
      menubutton $button -text $text \
         -menu $menu -underline $mnemonic
   } else {
      menubutton $button -text $text -menu $menu
   }

   pack $button -side left
   menu $menu
}

proc file_read {filename} {
   # Read a text file.
   # default value
   set data ""

   if {[file readable $filename]} {
      set fd [open $filename "r"]
      set data [read $fd]
      close $fd
   }

   return $data
}

proc file_write {filename data} {
   # Write a file to disk. Returns 1 upon success,
   # 0 otherwise.
   set ret [catch {
      set fileid [open $filename "w"]
      puts -nonewline $fileid $data
      close $fileid
      }]

   if {$ret} {
      tk_messageBox -default ok -icon error -message \
      "Error saving the file
$filename
(invalid file name or disk full)." \
      -parent .edit -title "Write Error" \
      -type ok
   }

   if {$ret} {
      return 0
   } else {
      return 1
   }
}

proc file_load {toplevel textwidget filename} {
   # Load a file into the text widget.
   set data [file_read $filename]

   if {$data != ""} {
      # delete all existing text
      file_new $toplevel $textwidget

      # store text in textwidget
      $textwidget insert end $data
   }
}

proc file_new {toplevel textwidget} {
   # Prepare for a new file.
   global textedit

   # check for existing unsaved file
   set result [save_check $textwidget]

   if {$result == 0} {
      return
   }

   # delete all tags
   set names [$textwidget tag names]

   foreach tagname $names {
      $textwidget tag delete $tagname
   }

   #delete all text
   $textwidget delete 1.0 end

   # set title
   set textedit(save_name) "Untitled"
   set textedit(file_changed) 0
   set_title
   setstatus
   focus $textwidget
}

proc file_open_get {mode} {
   # Get the name of a text file to open.
   global textedit prefs SR_SPEC

   set file_types {
      {"ALL Files" *}
      {"TCL files" { .tcl .TCL .tk .TK}}
      {"Text files" {.txt .TXT}}
   }

   set filename [tk_getOpenFile -initialdir \
      $prefs(lastdirectory) \
      -filetypes $file_types \
      -title "Select a file to $mode" \
      -parent .]

   # exit upon empty filename
   if {$filename == ""} {
      return ""
   }

   # store last dir for loading next time
   if {$prefs(sropensave) != $SR_SPEC} {
      set prefs(lastdirectory) [file dirname $filename]
   }

   # store file name
   set textedit(save_name) $filename
   return $filename
}

proc file_open {toplevel textwidget} {
   # Open a text file.
   global textedit

   # check for existing unsaved file
   set result [save_check $textwidget]

   if {$result == 0} {
      return
   }

   set filename [file_open_get open]

   if {$filename != ""} {
      file_load $toplevel $textwidget $filename
      set textedit(file_changed) 0
      set textedit(save_name) $filename
      set_title
   }

   focus $textwidget
   $textwidget mark set insert 1.0
   setstatus
} 
      
proc file_insert {toplevel textwidget} {
   # Insert a file at current cursor position.
   global textedit

   # save current file name
   set cname $textedit(save_name)
   set filename [file_open_get insert]

   if {$filename != ""} {
      set data [file_read $filename]
      set textedit(save_name) $cname

      if {$data != ""} {
         $textwidget insert insert $data
         set textedit(file_changed) 1
         set_title
         setstatus
         focus $textwidget
         $textwidget mark set insert 1.0
      }
   }
}

proc file_save {textwidget} {
   # Obtain text, strip any ending newlines and save.
   # Returns 1 upon success, 0 otherwise.
   global textedit

   # if file name is "Untitled", do save as
   if {[string compare $textedit(save_name) "Untitled"] == 0} {
      return [file_save_as .edit $textwidget]
   }

   set data [$textwidget get 1.0 end]

   # remove any ending newlines
   #set text [string trimright $data]
   set ret [file_write $textedit(save_name) $data]

   if {$ret} {
      set textedit(file_changed) 0
      set_title
   }

   return $ret
}

proc file_save_get {} {
   # Get save file name.
   global prefs SR_SPEC

   set file_types {
      {"ALL Files" *}
      {"TCL files" { .tcl .TCL .tk .TK}}
      {"Text files" {.txt .TXT}}
   }

   set filename [tk_getSaveFile -initialdir \
      $prefs(lastdirectory) \
      -filetypes $file_types \
      -title "Select file name to save" \
      -parent .]

   # store last dir for next time
   if {$prefs(sropensave) != $SR_SPEC} {
      set prefs(lastdirectory) [file dirname $filename]
   }

   return $filename
}

proc file_save_as {toplevel textwidget} {
   # Returns one (1) upon success, zero upon
   # cancel request
   global textedit
   set filename [file_save_get]

   if {$filename != ""} {
      # store file name
      set textedit(save_name) $filename

      # save file
      file_save $textwidget

      # change window title
      set_title
      return 1
   }

   return 0
}

proc file_exit {textwidget} {
   # Exit routine
   # check for existing unsaved file
   set result [save_check $textwidget]

   if {$result == 0} {
      return
   }

   prefs_save
   exit
}

proc file_print {textwidget} {
   # Print a file (Windows only).
   global textedit

   # check for existing unsaved file
   set result [save_check $textwidget]

   if {$result == 0} {
      return
   }

   PrintText $textedit(save_name)
}

proc save_check {textwidget} {
   # Ask to save file and save it if the file
   # has changed. Returns zero (0) if user cancelled
   # operation, one (1) otherwise.
   global textedit
   
   set mes "The contents of file $textedit(save_name) "
   append mes "have changed\n\nDo you want to save "
   append mes "the changes?"

   if {$textedit(file_changed)} {
      set result [tk_messageBox -parent .edit \
         -title $textedit(appname) -type yesnocancel \
         -icon warning \
         -message $mes]

      if {$result == "cancel"} {
         focus $textwidget
         return 0
      }

      if {$result == "yes"} {
         if {[file_save $textwidget] == 0} {
            focus $textwidget
            return 0
         }            
      }
   }

   # lower changed flag
   set textedit(file_changed) 0
   return 1
}

proc edit_undo {textwidget} {
   # Undo. Only available in TCL
   # 8.4 or higher
   catch {
      $textwidget edit undo
   }
}

proc edit_redo {textwidget} {
   # Redo. Only available in TCL
   # 8.4 or higher
   catch {
      $textwidget edit redo
   }
}

proc edit_cut {textwidget} {
   # text cut
   global textedit

   cut_text $textwidget
   set textedit(file_changed) 1
   set_title
   setstatus
}

proc edit_copy {textwidget} {
   # text copy
   copy_text $textwidget
}

proc edit_paste {textwidget} {
   # text paste
   global textedit

   paste_text $textwidget
   set textedit(file_changed) 1
   set_title
   setstatus
}

proc edit_font {} {
   # select font
   fontdialog editfont
}

proc select_all {textwidget} {
   # Select all text.
   set data [$textwidget get 1.0 end]
   set length [string length $data]
   set idx [$textwidget index 1.0]

   # clear tag for any text that was selected
   catch {
      $textwidget tag remove sel sel.first sel.last
   }

   # select entire file
   $textwidget tag add sel $idx "$idx + $length chars"

   # place insertion cursor at end of file
   $textwidget mark set insert "$idx + $length chars"
}

proc help_about {toplevel} {
   # Display about box.
   global textedit
   tk_messageBox -default ok -icon info -message \
      "$textedit(appname) Version $textedit(version)

A text editor
by Rick Smereka
Copyright (c) 2004-2007" \
          -parent $toplevel -title "About $textedit(appname)" \
          -type ok
}

proc textedit_create {height} {
   # Startup application.
   global argc argv textedit prefs tk_version tcl_platform SR_SPEC

   # create toplevel widget
   toplevel .edit

   # text widget name that is used
   set textname .edit.main.text

   # trap close other than menu
   wm protocol .edit WM_DELETE_WINDOW "file_exit $textname"

   # create menubar
   menubar_create .edit .edit.menubar
   menu_create .edit.menubar .edit.menubar.file.filemenu \
      .edit.menubar.file "File" 0
   menu_create .edit.menubar .edit.menubar.edit.editmenu \
      .edit.menubar.edit "Edit" 0
   menu_create .edit.menubar .edit.menubar.search.searchmenu \
      .edit.menubar.search "Search" 0
   menu_create .edit.menubar .edit.menubar.options.optionsmenu \
      .edit.menubar.options "Options" 0
   menu_create .edit.menubar .edit.menubar.window.windowmenu \
      .edit.menubar.window "Window" 0
   menu_create .edit.menubar .edit.menubar.help.helpmenu \
      .edit.menubar.help "Help" 0

   # file menu
   set men .edit.menubar.file.filemenu
   $men add command -label "New" -underline 0 \
      -command "file_new .edit $textname" \
      -accelerator "Ctrl+N"
   $men add command -label "Open..." -underline 0 \
      -command "file_open .edit $textname" \
      -accelerator "Ctrl+O"
   $men add command -label "Insert..." -underline 0 \
      -command "file_insert .edit $textname"
   $men add separator
   $men add command -label "Save" -underline 0 \
      -command "file_save $textname" \
      -accelerator "Ctrl+S"
   $men add command -label "Save As..." -underline 5 \
      -command "file_save_as .edit $textname"
   $men add separator
   
   # print feature (Windoze only)
   if {$tcl_platform(platform) == "windows"} {
      $men add command -label "Print" -underline 0 \
         -command "file_print $textname" \
         -accelerator "Ctrl+P"
      $men add separator
   }

   $men add command -label "Exit" -underline 1 \
      -command "file_exit $textname"

   # edit menu
   set men .edit.menubar.edit.editmenu

   # undo and redo only supported for text widget in
   # tk 8.4 or higher
   if {$tk_version >= 8.4} {
      $men add command -label "Undo" -underline 0 \
         -command "edit_undo $textname" \
         -accelerator "Ctrl+Z"
      $men add command -label "Redo" -underline 0 \
         -command "edit_redo $textname" \
         -accelerator "Ctrl+Y"
      $men add separator
   }

   $men add command -label "Cut" -underline 2 \
      -command "edit_cut $textname" \
      -accelerator "Ctrl+X"
   $men add command -label "Copy" -underline 0 \
      -command "edit_copy $textname" \
      -accelerator "Ctrl+C"
   $men add command -label "Paste" -underline 0 \
      -command "edit_paste $textname" \
      -accelerator "Ctrl+V"
   $men add separator
   $men add command -label "Font" -underline 3 \
      -command "edit_font" -accelerator "Ctrl-T"
   $men add separator
   $men add command -label "Select All" -underline 7 \
      -command "select_all $textname" \
      -accelerator "Ctrl-A"
   $men add separator
   $men add checkbutton -variable prefs(wordwrap) \
      -label "Word Wrap" -underline 0 \
      -onvalue 1 -offvalue 0 -accelerator "Ctrl-W" \
      -command "set_wrap"

   # search menu
   set men .edit.menubar.search.searchmenu
   $men add command -label "Find" -underline 0 \
      -command "finddialog $textname" \
      -accelerator "Ctrl-F"
   $men add command -label "Goto Line" -underline 0 \
      -command "gotodialog $textname" \
      -accelerator "Ctrl-G"

   # options menu
   set men .edit.menubar.options.optionsmenu
   $men add command -label "Preferences" -underline 1 \
      -command "prefsdialog" \
      -accelerator "Ctrl-R"

   # window menu
   set men .edit.menubar.window.windowmenu
   $men add checkbutton -variable prefs(statusline) \
      -label "Status Line" -underline 0 \
      -onvalue 1 -offvalue 0 -accelerator "Ctrl-U" \
      -command "set_status"

   # help menu
   set men .edit.menubar.help.helpmenu
   $men add command -label "About..." -underline 0 \
      -command "help_about .edit"

   # set initial font
   font create editfont -family courier -size 10

   # text widget in main area
   set frm .edit.main
   frame $frm -bd 4 -relief sunken

   text $frm.text -width 80 -height $height -wrap word \
      -yscrollcommand "$frm.vscroll set" \
      -xscrollcommand "$frm.hscroll set" \
      -font editfont

   # enable undo/redo if TCL 8.4 or higher
   if {$tk_version >= 8.4} {
      $frm.text configure -undo 1
   }

   scrollbar $frm.vscroll -command "$frm.text yview"
   scrollbar $frm.hscroll -command "$frm.text xview" \
      -orient horizontal
   pack $frm.vscroll -side right -fill y
   pack $frm.hscroll -side bottom -fill x
   pack $frm.text -side left -fill both -expand 1
   pack $frm -side right -fill both -expand 1

   # status line
   set frm .edit.status
   frame $frm -bd 0
   label $frm.mes1 -relief sunken -anchor w \
      -bd 1 -text "Unchanged"
   label $frm.mes2 -relief sunken -anchor w \
      -bd 1 -text "Line: 00  Column: 00  Total Lines: 000"
   pack $frm.mes1 -side left -fill x -padx 2 -pady 1
   pack $frm.mes2 -side left -fill x -padx 2 -pady 1 -expand 1
   pack $frm -fill x -side bottom

   # bind menu shortcut keys
   set frm .edit.main
   bind $frm.text <Control-Key-x> "edit_cut $frm.text; break"
   bind $frm.text <Control-Key-c> "edit_copy $frm.text; break"
   bind $frm.text <Control-Key-v> "edit_paste $frm.text; break"
   bind $frm.text <Control-Key-n> "file_new .edit $textname; break"
   bind $frm.text <Control-Key-o> "file_open .edit $textname; break"
   bind $frm.text <Control-Key-s> "file_save $textname; break"
   bind $frm.text <Control-Key-t> "edit_font; break"
   bind $frm.text <Control-Key-f> "finddialog $textname; break"
   bind $frm.text <Control-Key-g> "gotodialog $textname; break"
   bind $frm.text <Control-Key-w> "toggle_wrap"
   bind $frm.text <Control-Key-u> "toggle_status"
   bind $frm.text <Control-Key-a> "select_all $textname; break"
   bind $frm.text <Control-Key-r> "prefsdialog; break"

   # undo and redo only supported for text widget in
   # TCL 8.4 or higher
   if {$tk_version >= 8.4} {
      bind $frm.text <Control-Key-z> "edit_undo $textname; break"
      bind $frm.text <Control-Key-y> "edit_redo $textname; break"
   }

   # print feature (Windoze only)
   if {$tcl_platform(platform) == "windows"} {
      bind $frm.text <Control-Key-p> "file_print $textname; break"
   }

   # trap all keys for file change and status line update
   bind $frm.text <Key> {
      # any alphanumeric key will trigger a file change
      set keypress %N
      set changed 0

      if {$keypress > 31 && $keypress < 123} {
         set changed 1
      }

      if {$changed == 0} {
         set keypress %K

         # also trap delete, return and backspace keys
         if {[string compare $keypress "Delete"] == 0} {
            set changed 1
         }

         if {[string compare $keypress "BackSpace"] == 0} {
            set changed 1
         }

         if {[string compare $keypress "Return"] == 0} {
            set changed 1
         }
      }

      if {$changed} {
         set textedit(file_changed) 1
      }

      #puts "num=%N,key=%K"
      # refresh title
      set_title
   }

   # refresh status line
   bind $frm.text <KeyRelease> setstatus
   bind $frm.text <ButtonRelease> setstatus

   # popup edit menu on rightmost mouse button
   bind all <Button-3> {
      # get global X position of app
      set gx [winfo rootx %W]

      # get global Y position of app
      set gy [winfo rooty %W]

      # add to local mouse position
      set mx [expr $gx + %x]
      set my [expr $gy + %y]

      # display popup menu
      tk_popup .popup $mx $my
   }

   # create popup menu
   menu .popup
   .popup add command -label "Cut" \
      -command "edit_cut $frm.text"
   .popup add command -label "Copy" \
      -command "edit_copy $frm.text"
   .popup add command -label "Paste" \
      -command "edit_paste $frm.text"

   # print feature (Windoze only)
   if {$tcl_platform(platform) == "windows"} {
      .popup add separator
      .popup add command -label "Print" \
         -command "file_print $frm.text"
   }   

   # set initial title
   set_title

   # pack the main area
   pack $frm -side top -fill both -expand 1

   # load prefs
   update
   prefs_load

   # any command line parameter is assumed to be
   # the name of a file to load
   if {$argc > 0} {
      set filename [lindex $argv 0]
      file_load .edit $textname $filename
      set textedit(file_changed) 0
      set textedit(save_name) $filename
      set_title
      $textname mark set insert 1.0

      # store last dir for loading next time
      if {$prefs(sropensave) != $SR_SPEC} {
         set prefs(lastdirectory) [file dirname $filename]
      }
   }

   # update status line
   setstatus

   # wait for a while for all widgets to exist
   update

   # set focus to text widget
   focus $frm.text
}

proc prefs_save {} {
   # Store window and font details and save 'prefs'
   # array to a file.
   global textedit prefs SR_SPEC

   # save current window geometry (position and size)
   set prefs(geometry) [wm geometry .edit]   

   # put font details into 'prefs' array unless we are always using
   # the same specific font
   if {$prefs(srfont) != $SR_SPEC} {
      set prefs(fontfamily) [font actual editfont -family]
      set prefs(fontsize) [font actual editfont -size]
      set prefs(fontunderline) [font actual editfont -underline]
      set prefs(fontoverstrike) [font actual editfont -overstrike]
      set prefs(fontslant) [font actual editfont -slant]
      set prefs(fontweight) [font actual editfont -weight]
   }

   # save 'prefs' array to a file
   prefsave $textedit(pref_file) prefs
}

proc prefs_load {} {
   # Load user preferences from a file into the 'prefs' array
   # and set program values based on user desire. Returns 1
   # upon success, 0 otherwise.
   global textedit prefs SR_NO

   # abandon if 'prefs' file does not exist
   if {![prefload $textedit(pref_file)]} {
      tk_messageBox -default ok -icon warning -message \
         "Unable to load preference file.
Preferences not set." \
         -parent .edit -title "Preferences Not Set" \
         -type ok
      return 0
   }

   # set window geometry
   # set window size
   if {$prefs(srwinsize)} {
      set winspec ""

      # extract size spec (nnxnn)
      if {![ll_word $prefs(geometry) winspec 1 +]} {
         tk_messageBox -default ok -icon error -message \
            "Unable to obtain window size
from window geometry.
Preference load aborted." \
            -parent .edit -title "Preference Load Error" \
            -type ok

         return 0
      }
   
      wm geometry .edit $winspec
   }

   # set window position
   if {$prefs(srwinpos)} {
      set winspec ""

      # extract position spec (+xx+yy)
      # xx first
      if {![ll_word $prefs(geometry) winspec 2 +]} {
         tk_messageBox -default ok -icon error -message \
            "Unable to obtain window position
from window geometry.
Preference load aborted." \
            -parent .edit -title "Preference Load Error" \
            -type ok

         return 0
      }
   
      set xspec $winspec

      # then yy
      if {![ll_word $prefs(geometry) winspec 3 +]} {
         tk_messageBox -default ok -icon error -message \
            "Unable to obtain window position
from window geometry.
Preference load aborted." \
            -parent .edit -title "Preference Load Error" \
            -type ok

         return 0
      }
   
      set yspec $winspec

      # build complete spec
      set winspec +
      append winspec $xspec
      append winspec +
      append winspec $yspec
      wm geometry .edit $winspec
   }

   # set word wrap
   if {$prefs(srwordwrap)} {
      set_wrap
   } else {
      set prefs(wordwrap) 1
      set_wrap
   }

   # set status line
   if {$prefs(srstatusline)} {
      set_status
   } else {
      set prefs(statusline) 1
      set_status
   }

   # set 'open' path to current dir if we are not preserving
   # the stored path
   if {$prefs(sropensave) == $SR_NO} {
      set prefs(lastdirectory) [pwd]
   }

   # restore font unless not desired
   if {$prefs(srfont) != $SR_NO} {
      font configure editfont -family $prefs(fontfamily) \
      -size $prefs(fontsize) -underline $prefs(fontunderline) \
      -overstrike $prefs(fontoverstrike) -slant $prefs(fontslant) \
      -weight $prefs(fontweight)
   }

   return 1
}

# main line
tk appname $textedit(appname)
wm withdraw .
textedit_create 32









