#!/bin/sh #\ exec wish8.4 "$0" # ====================================================================== # Simple text editor built with [incr Widgets] # ---------------------------------------------------------------------- # AUTHOR: Michael J. McLennan # CLASS: Object-Oriented Programming with [incr Tcl] # ====================================================================== package require Iwidgets 4.0 option add *edit.width 5i startupFile option add *edit.height 4i startupFile option add *Fileselectiondialog.width 4i startupFile option add *Fileselectiondialog.height 5i startupFile # ---------------------------------------------------------------------- set FileWindows 0 # ---------------------------------------------------------------------- # Dialog boxes # ---------------------------------------------------------------------- iwidgets::messagedialog .notice -title "itkedit: Notice" \ -bitmap info -buttonboxpos e -modality application .notice hide OK .notice hide Help .notice buttonconfigure Cancel -text "Dismiss" iwidgets::messagedialog .confirm -title "itkedit: Confirm" \ -bitmap questhead -modality application .confirm hide Help .confirm buttonconfigure OK -text "Yes" .confirm buttonconfigure Cancel -text "No" iwidgets::fileselectiondialog .files -title "itkedit: Files" \ -childsitepos s -modality application .files hide Help set PaneMenu "[.files childsite].panes" iwidgets::optionmenu $PaneMenu -labeltext "Edit Window:" pack $PaneMenu -pady 6 # ---------------------------------------------------------------------- # USAGE: file_load # # Initiates the process of loading a new text file for editing. # Pops up a Fileselectiondialog, allowing the user to select a # file for editing. If the user pushes the "load" button, the # file is loaded. # ---------------------------------------------------------------------- proc file_load {} { global FileName PaneMenu .files buttonconfigure OK -text "Load" if {[.files activate]} { set fname [.files get] set cmd { set fid [open $fname r] set text [read $fid] close $fid } if {[catch $cmd err] != 0} { .notice configure -bitmap error \ -text "Cannot load file \"$fname\":\n$err" .notice activate return } set pane [$PaneMenu get] set win [.edit childsite $pane] clear_text $win $win.text insert end $text $win.text configure -labeltext "file: $fname" set FileName($win) $fname } } # ---------------------------------------------------------------------- # USAGE: file_save_as # # Initiates the process of saving the current text into a particular # file. Pops up a Fileselectiondialog, allowing the user to select # a file for saving. If the user pushes the "save" button, the # file is saved. # ---------------------------------------------------------------------- proc file_save_as {} { global FileName PaneMenu .files buttonconfigure OK -text "Save" if {[.files activate]} { set pane [$PaneMenu get] set win [.edit childsite $pane] set FileName($win) [.files get] file_save $win } } # ---------------------------------------------------------------------- # USAGE: file_save # # Saves the context of into its associated file. Does the # dirty work to finish the file_save_as operation. # ---------------------------------------------------------------------- proc file_save {win} { global FileName FileChanged set cmd { set fid [open $FileName($win) w] puts $fid [$win.text get 1.0 end] close $fid set FileChanged($win) 0 $win.text configure -labeltext "file: $FileName($win)" } if {[catch $cmd err] != 0} { .notice configure -bitmap error \ -text "Cannot save file \"$FileName($win)\":\n$err" .notice activate } } # ---------------------------------------------------------------------- # USAGE: clear_text ?? # # Clears the text area associated with , making sure to save # any pending changes. If no is specified, then all text # areas are cleared. # ---------------------------------------------------------------------- proc clear_text {{areas ""}} { global FileName FileChanged FileWindows if {$areas == ""} { for {set i 0} {$i < $FileWindows} {incr i} { set pane "area #[expr $i+1]" lappend areas [.edit childsite $pane] } } foreach win $areas { if {$FileChanged($win)} { set fname [file tail $FileName($win)] .confirm configure -text "File \"$fname\" has changed.\nSave changes?" if {[.confirm activate]} { file_save $win } } $win.text delete 1.0 end set FileChanged($win) 0 } } # ---------------------------------------------------------------------- # USAGE: split_view # # Adds another editing pane to the current editor. # ---------------------------------------------------------------------- proc split_view {} { global FileName FileChanged FileWindows PaneMenu set pane "area #[incr FileWindows]" .edit add $pane -minimum 100 $PaneMenu insert end $pane set win [.edit childsite $pane] set FileName($win) untitled.txt set FileChanged($win) 0 iwidgets::scrolledtext $win.text -wrap none -labeltext "file: $FileName($win)" \ -hscrollmode none -vscrollmode dynamic -visibleitems 1x1 pack $win.text -expand yes -fill both bind [$win.text component text] " set FileChanged($win) 1 " } frame .mbar -borderwidth 2 -relief raised pack .mbar -side top -fill x # ---------------------------------------------------------------------- # FILE menu # ---------------------------------------------------------------------- menubutton .mbar.file -text "File" -underline 0 -menu .mbar.file.menu pack .mbar.file -side left -padx 4 menu .mbar.file.menu .mbar.file.menu add command -label "Load..." \ -accelerator " ^L" -underline 0 -command file_load bind . { .mbar.file.menu invoke "Load..." } .mbar.file.menu add command -label "Save As..." \ -accelerator " ^S" -underline 0 -command file_save_as bind . { .mbar.file.menu invoke "Save As..." } .mbar.file.menu add separator .mbar.file.menu add command -label "Quit" \ -accelerator " ^Q" -underline 0 -command {clear_text; exit} bind . { .mbar.file.menu invoke Quit } # ---------------------------------------------------------------------- # VIEW menu # ---------------------------------------------------------------------- menubutton .mbar.view -text "View" -underline 0 -menu .mbar.view.menu pack .mbar.view -side left -padx 4 menu .mbar.view.menu .mbar.view.menu add command -label "Split" \ -underline 0 -command split_view # ---------------------------------------------------------------------- # Editor # ---------------------------------------------------------------------- iwidgets::panedwindow .edit -orient horizontal pack .edit -expand yes -fill both split_view wm title . "itkedit" wm protocol . WM_DELETE_WINDOW { .mbar.file.menu invoke Quit } after idle { update idletasks wm minsize . [winfo reqwidth .] [winfo reqheight .] }