From: PORTABLE 100, March 1989, pgs 8–13.
Get WordStar cursor control for TEXT.
By Stan Wong
Republication, bugfixes, and extensions by John R. Hogerhuis
I'm a WordStar addict. There is nothing flashy about the program. It's not even sexy. But I love WordStar and its arcane cursor movement and control commands. It was, and still is, one of the few word processing programs supported across many different machines and operating systems. I use it on a DEC Rainbow and a 386 PC at work. I use it on my IBM PC/XT. And I bought an NEC 8500 CP/M laptop because it had WordStar built in.
My fingers get cramps every time I use my trusty Model 100, and trying to remember the different cursor movement and editing commands drives me batty.
Well, no more!
A Diamond in the Rough
The Model 100 TEXT program already implements the famous WordStar cursor control-character "diamond" – ^S, ^E, ^D, ^X, where the caret (^) signifies holding down the CTRL key, as WordStar users know – but it doesn't go far enough.
So I've polished up the diamond a bit. I've written a small machine language program called TextStar (or Text* to its friends), which implements most of the WordStar cursor movement commands as well as some text deletion and other miscellaneous commands.
TextStar is not a complete program by itself. Instead, it enhances the operation of TEXT. Although TextStar's cursor control looks and feels like WordStar, it still retains a TEXT-like flavor. See the sidebar "Inside TextStar" for technical information on how it performs its magic.
TextStar extends the operation of TEXT by redefining the meaning of the control keys, where possible, to match those of WordStar (See Table 1). Even multiple-keystroke commands such as ^QD, are supported. Control keys that have not been redefined still retain their TEXT meanings. For instance, ^B still moves the cursor to the bottom of the screen. ^T will not, however move you to the top of the screen but will delete a word instead.
A simple change to TextStar could have made it ignore the TEXT control keys, but I felt it would be better to leave them in. The program owes its small size (381 bytes) to its method; it traps keyboard input and translates only WordStar control codes into their TEXT equivalents, passing all other keystrokes directly to TEXT for normal processing.
Vive La Difference
However, TextStar does not perform exactly like WordStar. Because it enhances the TEXT program, it is bound by certain TEXT conventions.
For instance, when moving up and down a line, WordStar moves the cursor to the end of a line if the destination line is shorter. But TextStar, like TEXT, leaves the cursor in the same column regardless of the destination line's length.
As a bonus, the text deletion commands ^T and ^Y store the deleted text in the paste buffer. So if you make a mistake you can recover the text by pressing the PASTE key. This gives you a simple UNDO facility.
A Star Is Born
Listing 1 is a relocating BASIC loader. It creates a machine language program, TXTSTR.CO, to run anywhere you specify in high memory, or it will default to loading just under the current HIMEM. It can thus coexist with your other .CO programs. (Thanks to Phil Wheeler for his BASBLD.PW3 program, which I used to create the loader.)
Listing 2 is the assembly language source code for TextStar. I used the ADSM assembler by James Yi, which you can find on the CompuServe Model 100 Forum. Minor syntax changes to the source code will also make it compatible with the ROM2 assembler from Traveling Software, which I used to do the initial program development.
You have no need to use the assembly language listing, however, other than to understand what TextStar is doing and how it does it.
A Rising Star
To run TextStar, place the widebar cursor over TXTSTR.CO on the main menu and press ENTER. You should then see TEXT's familiar File to edit? prompt. Specify the .DO file to edit, and you're on your way.
If the program doesn't start, go into BASIC and type CLEAR 0, nnnm (where nnnm is the load point) and then try again. If you don't know the load point, type LOADM "TXTSTR" and use the Top address returned by the LOADM command as the load point (nnnm) for the CLEAR statement above.
Where To Get TextStar
TextStar is also available on the P100-To-Go disk and on the Portable BBS (603-924-9770) as TXTSTR.100. If you need the program and listings on a cassette tape, send $6 to me at P.O. Box 28181, Santa Ana, CA 92799. You can also contact me via CompuServe user ID 70346,1267. I support the program on the M100SIG of CompuServe.
Those cramps in my fingers are finally starting to disappear. Happy typing!
The key to TextStar's operation is its ability to intercept keystrokes before TEXT sees them, by using a programming mechanism known as a RAM hook. Before I describe how TextStar uses RAM hooks, let's take a look at what TEXT does with your keystrokes.
The TEXT program is constructed as one big loop starting at ROM address 5DEEH. TEXT' waits for your keystroke, gets it, and takes the appropriate action.
It's interesting to note that near the beginning of TEXT, the program pushes the address of the top-of-the-TEXT loop onto the stack.
Normal loops end with a JMP nnnn instruction, where nnnn is the address of the top of the loop. But by pushing the top-of-the-loop address on the stack, the program can instead simply execute a RET instruction from anywhere to get back to the start.
This has two advantages. First, it saves memory for each loop return point. It needs only one byte for the RET instruction versus three for the JMP. Second, the code can be more easily relocated. If the code is, for some reason, changed and shifted in memory, then all the JMP instructions do not have to be recoded with the new top-of-the-loop address.
Give 'em the Hook, the Hook
TEXT uses a ROM routine known as CHGET (located at 12CBH) to wait for your next keystroke. The TEXT call to this "Tandy-documented" routine is at address 63F1H.
CHGET makes use of a RAM hook. What's a RAM hook? Is it related to Captain Hook? Not really.
A RAM hook is a programming mechanism by which the system designer provides a way for users to modify or replace certain system routines. RAM hooks are commonly provided for ROM routines, since code in ROM is fixed and cannot be changed.
Specifically, some ROM routines incorporate an RST 7 instruction to give users access to hooks, allowing them an opportunity to "splice in" their own code instead. It works like this.
At address FADAH is a "hook table," each table entry being a two-byte address. In effect, the RST 7 instruction in a CALL to one of these addresses. It finds the appropriate entry by adding an offset byte (which follows the RST 7 instruction in the ROM routine) to the start of the table, and then CALL's the address stored there.
For example, the CHGET routine incorporates an RST 7 instruction at the beginning of the routine. The value of the offset byte is 4. This means that the RAM hook at FADEH (FADAH + 4) is used for CHGET.
Since most entries in the hook table point to a RET instruction in ROM (at 7FF3H), the RST 7 normally CALL's 7FF3H, which simply returns back to the ROM routine, chewing up a few machine cycles and nothing more.
But since the hook table is in RAM, the user may change an entry to point to his own routine, in which case the RST 7 performs a CALL to the user's routine.
Once RST 7 locates the two-byte address in the table, it executes the routine located at that stored address. For routines like TextStar that use these hooks, RST 7 effectively CALL's TextStar, which does its business on a keystroke and then returns to CHGET.
Thus, a hook gives us a chance to sneak in and peek at a keystroke before it is processed and returned to TEXT.