[Date Prev][Date Next][Subject Prev][Subject Next][ Date Index][ Subject Index]

Re: Programming challenge: Undo -- Try it out!



** Reply to message from Harry Binswanger  on
Wed, 02 Jul 2008 21:23:25 -0700

For the brave of heart, attached, UnDo.ZIP with all the
requisite files.

The underlying thinking behind this UnDo|ReDo program:

You can't reliably capture keystrokes in memory, and you
can't reverse the logic of commands in XPL (SORT command
etc). Even if you could do all this, you'd be OOM (Out-Of-
Memory) in 3 seconds flat. In short, it can't be a "smart"
Undo a la Word, which un-does individual keystrokes.

The only reliable method is file backups. So here are my
two schemes: 1) Timed, and 2) Keystroke-Generated, backups.
The user can choose either method. Theoretically, you could
use both methods concurrently, but I do not advise it.
Windows NT+ ONLY for the Timed method (that means NT4, 2000,
XP, Server, or Vista); 9x can be used with the Keystroke-
Generated method.

Installation
============
The Title of XyWrite's window *must* (MUST!) begin with the
seven letters "XYWRITE" -- case-INsensitive!! So
XyWrite=xywrite=XYWRITE=XYWrite etc. Adjust your XyWrite
window's Properties accordingly.

Required external programs:
 UnDo.exe - locate in Editor's directory
 KillNB.exe - locate in Editor's dir
 kmd.exe - locate in DOS Path (e.g. .\system32) or Editor's
  dir. If you don't already have kmd.exe, download it from
  XyWWWeb:
  
http://users.datarealm.com/xywwweb/dwnload.cgi?download=WIN95CMD.ZIP

UnDo.exe does all the work (KillNB just kills UnDo.exe if
you want to stop making Timed backups -- no other purpose).

UnDo requires a dedicated subdirectory of Editor's dir, \UD
(e.g. C:\XY4\UD), which contains the backups. Frame
UNDO.INT makes this subdirectory automatically if it does
not yet exist -- you do NOT need to make it.

You'll require PLENTY of unused disk space for backups!

Backups bear the "8" part of the 8.3 filename in your
current window, plus EXTensions numbered 001-999, e.g. if
the document is named "MYFILE.TXT" then the first backup
will be named "MYFILE.001". NOTE: A potential flaw here is
if you are editing files named e.g. MYFILE.A and MYFILE.B,
then no distinction between them will be made in the backups
(they'll all be called MYFILE.001, MYFILE.002, etc, and they
will overwrite each other, and get all bumbled up). So...
ummm... just don't DO that -- caveat user!

[UNTITLED] windows are handled as e.g. "UNTITLE5.001" for
the first backup of the [UNTITLED] document in Window #5.

If the current file hasn't changed since the last backup,
then no backup is made.

Add a new stanza "[UnDo]" to XyWWWeb.REG, per different
instructions for each method, below.

Install 6 new frames in XyWWWeb.U2 (CoPy from file UNDO.FRM
into U2, then LOADHELP:

1) undo.int,rud - UNDO.INT provides INiTialization. You
MUST run UNDO.INT in STARTUP.INT: edit STARTUP and enter a
separate line in STARTUP as follows, *after* XyWWWeb.U2 is
LOADed:
...
JM 2.undo.intQ2 ;*;
...
UNDO.INT creates subdir .\UD if it doesn't already exist, or
erases any existing files in .\UD

RUD restarts UnDo under the Timed method after UnDo is
turned off with KUD, described below (KUD="Kill UnDo",
RUD="Restart UnDo").

2) $T - creates Timed UnDo backups. This is constructed as
a XyWrite function, for ease of use in the KBDfile -- just
two characters, "$T".

3) $K - ditto, except $K creates Keystroke-Triggered UnDo
backups.

4) undo,redo - Write the appropriate backup over the
current file, then RECAll it. When you want to UnDo or
ReDo, you just issue one of those commands+ on the
CMline (or could put on a key), and it "happens". Make some
changes to a document, then try it!

5) cud[/nv] - Clear the UnDo backups for the current file.
/NV optionally clears *all* files in .\UD, creating an empty
directory.

6) kud - Kill UnDo.exe with the Timed method (stop UnDo.exe
from running).

Description of the "Timed" method:
=================================
Principles: You assign frame $T to a keystroke in KBD file.
Theoretically, it can be any keystroke, but I would pick a
simple one, with only one or two or (best!) NO standard
toggling keys like Alt or Ctrl or Shift (do NOT use NumLock
or CapsLock!) -- for example, I have been using
LeftAlt+LeftShift+U, and also ScrollLock. ScrollLock works
best for me. UnDo.exe knows what keystroke or keystroke
combo you've picked, and IF (only if) XyWrite is the current
foreground process then UnDo pokes that keystroke into
XyWrite's keyboard buffer every X seconds (the user should
NOT manually use this keystroke!). Poking the keystroke into
the keyboard buffer EXECUTES it! You determine the value
of X seconds: 10, 20, 30, 60, whatever. You also determine
how many levels of backup you want to maintain (Tip: Do NOT
use the full 998 maximum, because UnDo will be RENaming ALL
your backups EVERY time you make a new one! use a
reasonable number, like 20 or 100 or 300). UnDo.exe gets
these three pieces of information from three REG Variables
(respectively, UnDoKeys, UnDoFreq, UnDoDepth) when you
initialize UnDo (via frame UNDO.INT): UNDO.INT passes an
argument to UnDo.exe like "A4A055 10 100", which means:
 A4A055 are the hex XXh scan codes for
LeftAlt(A4)+LeftShift(A0)+U(55), in my example. A table of
scan codes, SCANCODE.TBL, is included in UnDo.ZIP. Don't
get confused: scancodes are NOT the same as XyWrite key
numbers in the KBDfile! You MUST consult SCANCODE.TBL to
get the correct scancodes for the keystroke you've selected!
 10 = make a backup every 10 seconds
 100 = maintain 100 levels of backup

New Stanza in REG ("Timed" method):
---------------
[UnDo]
UnDoKeys=91  <==ScanCode of key used to trigger backups, e.g.
91=ScrollLock
UnDoFreq=10  <==check document status every X seconds, e.g. 10
seconds
UnDoDepth=100 <==number of backups to maintain, e.g. 100
;
---------------

You can *test* that you've written the correct scancodes in
REG Variable "UnDoKeys" by starting UnDo.exe and then
running IDKEY. Every X seconds IDKEY should jump
to your $T key. Hit an ordinary alpha key A-Z to move IDKEY
off the $T key, then watch IDKEY pop back to $T again X
seconds later...

When picking a key, you need to consider several things.
Keystrokes are additive. Real and poked keystrokes are not
distinguished by the system. If you are manually holding
down the Shift key, and UnDo pokes a ScrollLock, what
XyWrite sees is Shift-ScrollLock. That's fine, because you
can map $T to Shift-ScrollLock too in your KBD file -- in
fact, you can and *should* map $T to key #70 (the ScrollLock
key) in each Table of your KBD file. But what if $T is
mapped to Alt-Shift-U in KBDfile? If you're manually
holding down the Shift key, and UnDo pokes Alt-Shift-U, the
system sees Alt-U (because two shifts cancel the shift).
UnDo tries to determine what keys you are holding down, but
the fact is that XyWrite is a lot faster than the Windows
operating system, and it isn't foolproof.

ScrollLock (key #70 in the KBD file) works particularly well
for me, because it is basically a useless key (i.e., the
ToggleScrollLock function TS mapped to key #70 by the
factory is an odorous function that I never use), and
ScrollLock isn't affected by the various shifting keys.
Simply tell UnDo (via REG Variable "UndoKeys") to use the
unshifted key (scancode 91); if you've mapped $T to key #70
in each Table of your KBD file then any manually-additive
shifting keys will also generate $T. This way, UnDo never
interferes with your keystrokes. (The only downside is if
your keyboard has a ScrollLock light: it will turn on and
off every X seconds.)

If the current file hasn't changed since the last backup,
then no backup is made. UnDo.exe _checks_ every X seconds,
but if the file hasn't changed, then nothing happens.

The Timed method will probably screw up in Vista if UAC
(User Access Control) is enabled; on my machine UAC is
disabled, and everything works. UAC users will need to run
Xy with "elevated privileges" (UAC is a total PITA, in my
opinion...)

The Timed method is similar to Xy's native AOT method, which
however keeps only ONE(!) level of backup, and operates only on
whole minutes: 1, 5, 50 (you can't specify, e.g., "d aot=.5"
for every 30 seconds). Pretty sad.

Description of the "Keystroke-Generated" method:
===============================================
This is an UNtimed procedure (no poking into keyboard
buffer).

The user decides what constitutes an "undo-able" action, and
codes KBDfile appropriately, inserting function $K (_not_
$T) before keystrokes that do "big things" -- copy, paste,
delete block, copy block, move block,  maybe, etc
etc. The user decides what actions rise to the level of an
UnDo. UnDo.exe monitors subdir .\UD for file changes.

New Stanza in REG ("Keystroke-Generated" method):
---------------
[UnDo]
UnDoKeys=K  <==MUST be the single letter "k"
UnDoFreq=   <==you may leave this empty - it is ignored
UnDoDepth=50 <==number of backups to maintain, e.g. 50
;
---------------

The "Keystroke-Generated" method is very simple to
implement, and works like a charm.

Let me know what you think...

[End]

-----------------------------
Robert Holmgren
holmgren@xxxxxxxx
-----------------------------

Attachment: UnDo.ZIP
Description: Binary data