a simple editor based on text widget 
Author Message
 a simple editor based on text widget

Hello! We use Tk8.0 here, and are writing a little specialized editor
based around the text widget.

Almost everything works, except for "Undo" and "Would you like to
save changes":

        * undo: short of saving the whole buffer over and over,
          any tricks known?

        * save prompt: any ideas on how to figure out if the buffer
          was changed? There are too many ways the buffer can be altered
          to try to rebind all the bindings and still have a nice code :)
          Ideally, I'd envision a new subcommand:

                pathName changed index1 ?index2?

          which would return a True if the there were any changes
          since the previous

                pathName get index1 ?index2?

          Or, if this is too expensive may be only support this for
          indices 1.0 through ``end''

Thanks for any ideas!

--
                         |\__-----__/|
                    _____/ :::::  :::\_____  
                   '__--( ::::::::..::)--__`    -mi
If you have a      /  _- \/  :::::::\/ -_  
serious knowledge    /   / :.   .::::\   \
about computers --      | ::::::::::::|         Ok, let's say you broke
keep it in a secret!   _|/ ::::____::\|_        the wall with your head
"Rules of dating",   /  /:::::/:_::\::\:.\      What are you going to
'Playboy', ? 1994   | :|  ..:(_/ \::|::|::|     do in the next cell?
                    | :|:::::. ::|: |::|.:|           Stanislaw J. Lec
                     \ |::  :::_/::/: :|:/
                   ((___\____\____/___/___))



Mon, 28 Aug 2000 03:00:00 GMT  
 a simple editor based on text widget

Quote:

> Hello! We use Tk8.0 here, and are writing a little specialized editor
> based around the text widget.

> Almost everything works, except for "Undo" and "Would you like to
> save changes":

>         * undo: short of saving the whole buffer over and over,
>           any tricks known?

Piece of cake. Relatively speaking. Took me perhaps one full day to
figure out and do. The basics are this: After creating the widget,
rename the widget command to something else (ie: rename .textwidget
.textwidget_original). Then, write your own widget command (ie: proc
.textwidget (args) ...) that, initially, just passes all the commands
back to the original. Make sure that part works.

Then, simply catch all text widget commands that modify the buffer
(notably, insert and delete, though there are others...). Each time an
insert happens, record the position and text that was inserted. For each
deletion, record the start position and the text that was deleted. Keep
a bit list. Or a small list if instead of unlimited undoes you just have
a single undo.

Then, when they press the undo key, just take the top item from the list
and reverse it.

Its not that difficult. I was able to implement a fully functioning
unlimited undo feature using this technique. One of these days, if I can
find the time, I'll reimplement it (the original code belongs to my old
employer...) and make it public. Its not rocket science, though. Any
decent tcl programmer can do it.

Quote:

>         * save prompt: any ideas on how to figure out if the buffer
>           was changed? There are too many ways the buffer can be altered
>           to try to rebind all the bindings and still have a nice code :)

Using the technique above for writing your own widget proc, anytime you
add something to the undo buffer (ie: any time there is an insertion or
deletion) you can set a flag internally. Then you can implement your own
"changed" command to query this flag. Works like a charm. With the added
benefit that you can turn the flag back off if they undo all the way
back to the beginning of the undo buffer.

Sorry for the lack of details -- I haven't written tcl code in over six
months and don't even have tcl loaded on my current machine (oh, the
shame!)

--
Bryan Oakley
ChannelPoint, Inc.



Mon, 28 Aug 2000 03:00:00 GMT  
 a simple editor based on text widget



Quote:
> Hello! We use Tk8.0 here, and are writing a little specialized editor
> based around the text widget.

> Almost everything works, except for "Undo" and "Would you like to
> save changes":

>    * undo: short of saving the whole buffer over and over,
>      any tricks known?

>    * save prompt: any ideas on how to figure out if the buffer
>      was changed? There are too many ways the buffer can be altered
>      to try to rebind all the bindings and still have a nice code :)
>      Ideally, I'd envision a new subcommand:

>            pathName changed index1 ?index2?

>      which would return a True if the there were any changes
>      since the previous

>            pathName get index1 ?index2?

>      Or, if this is too expensive may be only support this for
>      indices 1.0 through ``end''

> Thanks for any ideas!

I solved both of these for an implementation of a Plan9 Acme style
editor by having an internal text widget manipulation language.
Everthing in the package built a list of actions out of a set
of three "atomic" text instuctions, viz insert, delete and read a file.

Then the atom list was passed to a routine which ran through it and
actually executed text widget calls. The atoms were also passed
to a routine which ran though it and inverted all the operations and
created a list of atoms to undo the changes.
i.e.
insert "hello" at line 12 char 15
becomes
delete 5 chars starting at line 12 char 15
The undo list can then be rolled backwards, undo of the undo happens
automatically because the undo function calls both the do and makeundo
routines.

Simple

# ----------------------------------------------------------------------
# Updates the text according to the atoms list it receives, so that
# addresses are not munged we do two passes: the first pass inserts
# marks into the text widget at the address in each atom, the second
# pass then apply each atom at the mark.
#
# NB, an alternative would be to read the list backwards if the list
#     is sorted in ascending order of index.
# ----------------------------------------------------------------------
proc :_do {atoms window} {

  set m 0
  foreach a $atoms {
    $window.body mark set colon_mark$m [lindex $a 0]
    if {[lindex $a 1] == "d"} {
      $window.body mark set colon_mark_delete$m [lindex $a 2]
    }
    incr m
  }

  set m 0
  foreach a $atoms {
    switch [lindex $a 1] {
      i {
          $window insert colon_mark$m [lindex $a 2]
        }

      d {
          $window delete colon_mark$m colon_mark_delete$m
          $window.body mark unset colon_mark_delete$m
        }

      r {
          set fid [open [lindex $a 2]]
          $window insert colon_mark$m [read -nonewline $fid]
          close $fid
        }
    }

    $window.body mark unset colon_mark$m
    incr m
  }

Quote:
}

# ----------------------------------------------------------------------
# Undo generator, takes an atom list and inverts it
# ----------------------------------------------------------------------
proc :_makeundo {atoms window} {

  global ha_colon_info

  foreach a $atoms {
    switch [lindex $a 1] {
      i {
          set undo [list \
            [lindex $a 0] \
            d \
            "[lindex $a 0] + [string length [lindex $a 2]] c" \
          ]
        }

      d {
          set undo [list \
            [lindex $a 0] \
            i \
            [$window get [lindex $a 0] [lindex $a 2]] \
          ]
        }
      r {
          set undo [list \
            [lindex $a 0] \
            d \
            [$window index "[lindex $a 0] + [file size [lindex $a 2]] c"] \
          ]
        }
    }
    lappend ha_colon_info(undo,$window) $undo
  }
puts ":_makeundo : $ha_colon_info(undo,$window)"

Quote:
}

--
________________________________________________________________________
Duncan Barclay          | God smiles upon the little children,

________________________________________________________________________


Mon, 28 Aug 2000 03:00:00 GMT  
 a simple editor based on text widget

Quote:

> Piece of cake. Relatively speaking. Took me perhaps one full day to
> figure out and do. The basics are this: After creating the widget,
> rename the widget command to something else (ie: rename .textwidget
> .textwidget_original). Then, write your own widget command (ie: proc
> .textwidget (args) ...) that, initially, just passes all the commands
> back to the original. Make sure that part works.

Hi

The same solution occured to me. The resulting code is fairly fast, but
pressing the delete with autorepeat hiccups a bit (keyword coloration
via regexp is also an accomplice).

The alternative is to change bindings delivered with Tk (text.tcl)
and implement undo & things directly, but I considered this too much
fiddling with the original distribution  as there may be maintenance
problems if the distributed tcl code changes). The regexp code may
be a bit slower owing to Unicode, and if this results in a slow editor,
the intercept procedure will have to be written in C.

We should consider asking the development team to implement
activating synthetic events or hook procedures when the text part
of the text widget is actually changed, and when the text displayed
changes. This would make undo and keyword coloration much easier
and quicker.

You should also consider whether <<undo>> is applicable to tag
property changes.

Cheers

Smi



Tue, 29 Aug 2000 03:00:00 GMT  
 a simple editor based on text widget

Quote:


> > Piece of cake. Relatively speaking. Took me perhaps one full day to
> > figure out and do. The basics are this: After creating the widget,
> > rename the widget command to something else (ie: rename .textwidget
> > .textwidget_original). Then, write your own widget command (ie: proc
> > .textwidget (args) ...) that, initially, just passes all the commands
> > back to the original. Make sure that part works.

> Hi

> The same solution occured to me. The resulting code is fairly fast, but
> pressing the delete with autorepeat hiccups a bit (keyword coloration
> via regexp is also an accomplice).

You should be able to optimize your code to the point where it doesn't
"hiccup". I had the same problem at one time. I took the time to rewrite
portions of the code and the problem went away. And this was before
there was a byte compiler. Admittedly, I only ran this on unix boxes --
some PCs or Macs may be slow enough to still have a problem.

[small time passes]

testing a program I wrote yesterday to remimplement this feature (to
prove to myself it can, in fact, be done in less than a day) shows no
lag with holding the backspace key down and letting it autorepeat. I
tested this with maybe 200 characters in the buffer. Undoing it was
equally snappy.

Something that might make it possible is just to add one new option to
the text widget: -callback. Give it a proc and that proc is called
whenever something is inserted or deleted. The first parameter can tell
what happened (insert or delete) the next could be the index, and the
third could be the data added or deleted. Actually, it would be nice if
maybe it just passed the exact text widget command as-is, for all
commands. This would require no processing on the part of the text
widget -- it merely has to take what it has and pass it to a proc. Of
course, misbehaved callback procs could cause the text widget to
misbehave, but that's not something the text widget has to be concerned
with. Then, one could do all sorts of things without having to resort to
overriding the widget command.
--
Bryan Oakley
ChannelPoint, Inc.



Tue, 29 Aug 2000 03:00:00 GMT  
 a simple editor based on text widget

I have an editor which is based on the text widget and was written about a
year ago which has undo - if anyone would like a copy to examine they are
welcome.

Dominic Hibbs



Sun, 03 Sep 2000 03:00:00 GMT  
 a simple editor based on text widget

Quote:

> I have an editor which is based on the text widget and was written about a
> year ago which has undo - if anyone would like a copy to examine they are
> welcome.

> Dominic Hibbs

Out of curiosity, how did you implement undo? And, is it a single
undo/redo or unlimited undo?

--
Bryan Oakley
ChannelPoint, Inc.



Sun, 03 Sep 2000 03:00:00 GMT  
 a simple editor based on text widget

Quote:


> > I have an editor which is based on the text widget and was written about a
> > year ago which has undo - if anyone would like a copy to examine they are
> > welcome.

> > Dominic Hibbs

> Out of curiosity, how did you implement undo? And, is it a single
> undo/redo or unlimited undo?

It is unlimited undo back to the last save.
An array stores the location and type of change and if necessary the text
to replace.  Backward and forward deletions in the same place are combined
into a single change.  Insertions are also grouped into a single change
except at a newline which starts a new change.  I have not implemented a
'redo'.

Any further info required - just ask.

Dominic Hibbs



Mon, 04 Sep 2000 03:00:00 GMT  
 
 [ 8 post ] 

 Relevant Pages 

1. Text widgets as basic text editors?

2. Some questions on elided text in the text widget (and a few other text widget questions)

3. New scriptable Scintilla and QT based Text Editor

4. Motif Based Visual Text Editor

5. Customizable text editor based on Python?

6. Terminal-based text editor with color syntax hilighting

7. Customizable text editor based on Python?

8. Tcl/Tk based Text editor

9. Tk-3.2 based text editor ?

10. What widget for simple diagram editor

11. Source Code for a simple TEXT EDITOR

12. Source Code for a simple TEXT EDITOR

 

 
Powered by phpBB® Forum Software