Version 17 of A change-sensitive text widget

Updated 2003-06-08 20:03:52

Morten Skaarup Jensen asked in news:comp.lang.tcl : I am writing an editor and would like to know a simple way to find out if the text widget has been edited since the file was loaded so that so that one knows whether or not to save. Bryan Oakley replied:

Override the text widget command, and look for insert and delete subcommands. Here's a quick hack off the top of my head. Don't take this as an example of particularly good coding style, but it does illustrate the point.

(If using 8.4 there is also the modified flag in the text widget --Ro)

To run it through its paces, just run the following code. Type and/or delete something in the text widget and notice how the save button becomes enabled. Click the save button to simulate saving the data and note how it becomes disabled. Also notice how this works even if you cut or paste data into the widget.

    frame .toolbar
    pack .toolbar -side top -fill x -expand no
    button .toolbar.save -text "save" -command doSave -bd 1
    pack .toolbar.save -side left

    text .text
    pack .text -side top -fill both -expand yes

    rename .text .text_
    proc .text {command args} {
        global textModified

        # let the real text widget do all the real work
        set result [uplevel .text_ $command $args]

        if {[string equal $command "insert"] \
            || [string equal $command "delete"]} {
            set textModified 1
        }

        return $result

    }

    proc doSave {} {
        global textModified

        # pretend we've saved the text...

        # reset the state
        set textModified 0
    }

    proc updateUI {args} {
        global textModified
        if {$textModified} {
            .toolbar.save configure -state normal
        } else {
            .toolbar.save configure -state disabled
        }
    }

    trace variable textModified w updateUI
    set textModified 0

Man, I love writing tcl, but sure do miss writing Tk. Tk is just sooooo nice! I literally haven't written this much tk code in a year :-(


See also ANSI color control for a value-added text widget - Arts and crafts of Tcl-Tk programming


Here's another way to find out whether a text widget contains unsaved text. This procedure ("savecheck") is part of my simple text and HTML editor, WISH Supernotepad <http://www.geocities.com/pa_mcclamrock/supernotepad.tar.gz >. The name of the text widget is ".textinhere." The "Save Changes?" indicator is displayed on the title bar when unsaved text exists.

# Procedure to check whether unsaved text exists

proc savecheck {} {

 global bytesnow savedbytes currentfile savechanges

 # Find out number of bytes in text widget
 # (minus one undeletable newline at end):
 set textnow [.textinhere get 1.0 {end -1c}]
 set x [catch {string length $textnow} bytesnow]
 if { $x } {
  set bytesnow [string length $textnow]
 }

 # Check every half second to find out when text in widget changes;
 # then indicate that unsaved text exists:
 if { [string match $savedbytes $bytesnow] == 1 } {
        after 500 savecheck
 } else {
  set savechanges "(Save changes?)"
  wm title . "WISH Supernotepad:  $currentfile  $savechanges"
 }

}

David McClamrock


MDD: A much simpler approach:

   set changed 0
   bind .your.text.widget <Any-KeyRelease> {set changed 1}

   ...

   if {$changed == 1}{Save_File_Proc; set changed 0}

Of course, this will give a false positive if you use non-editing keys in the text widget, such as moving the cursor with the arrow keys, but it's not a bad quick-and-dirty solution.

It also doesn't catch instances where your code adds text to the widget via some other means, such as selecting "paste" from a pulldown menu.

MDD: Right. That's the "dirty" part. ;-)


Ctext provides an edit modified command; which can be used to tell if data has been inserted/deleted. It also works with the 8.3 and possibly 8.1 Tcl/Tk releases.


Category GUI