Victor R. Volkman received a BS in Computer Science from Michigan Technological University. He has been a frequent contributor to The C User Journal since 1987. He is currently employed as Senior Analyst at H.C.I.A of Ann Arbor, Michigan. He can be reached directly at the HAL 9000 BBS (313) 663-4173 or as sysop@hal9k.ann-arbor.mi.us on Usenet.
The C Users Group (CUG) Library offers several complete text editors with full source code supplied, including STEVIE (CUG313), RED (CUG318), and SE (CUG331). Each of these editors has been released into the public domain without any licensing or usage requirements. As such, you can use them in their original condition, modify them as the basis of your own text editor, or embed them into your existing applications where you need text-editing capabilities. I'll discuss the benefits and limitations of each editor and how you can take advantage of them. For a quick overview of their basic statistics and advanced features, see Table 1 and Table 2.
STEVIE (CUG313)
The STEVIE editor by Tony Andrews (Boulder, CO) is a highly-portable clone of the popular UNIX vi editor. STEVIE first appeared on the Atari ST platform and its name stands for "ST Editor for VI Enthusiasts." However, the current version of STEVIE can be compiled for the Atari ST running TOS or Minix, UNIX System V or BSD, and PCs running MS-DOS or OS/2. Others have reported success in porting STEVIE to the Amiga and Data General machines, although platform-specific code for those ports is not included in this release. My own testing covered STEVIE implementations in MS-DOS v5.0 and OS/2 v2.0.I received STEVIE v3.71 (released 06/08/89) from CUG on a single 5-1/4 inch 360K diskette for the PC. CUG can also supply releases on a 3-1/2 inch diskette. In any case, CUG distribution does not include any binary executables so you must compile it yourself before you can run it.
STEVIE displays text with ANSI terminal emulation escape sequences. These escape sequences were popularized by the DEC VT-100 series of terminals. Ideally, ANSI terminal support provides maximum display portability with minimum programming effort. However, the MS-DOS implementation (ANSI.SYS) is notoriously slow and impedes the performance of STEVIE. I found STEVIE to be incompatible with both ANSI.SYS in MS-DOS v5.0 and DVANSI.COM in DESQview/386. Specifically, scroll-down (CTRL-D) and scroll-up (CTRL-U) (keystrokes fail to refresh about half the screen. Although the STEVIE documentation does not mention this problem, it does suggest NANSI.SYS by Daniel Kegel (Altadena, CA) for ANSI emulation. Accordingly, I tested NANSI.SYS v3.3 which worked without problems and clocked screen refreshes 40 percent faster than ANSI.SYS.
STEVIE does not check for the presence of ANSI emulation, and will render an illegible set of escape strings if it is missing. If STEVIE had used the ANSI Device Status Report (ESC[6n), then it could have reported the absence of ANSI support and recommended corrective action.
STEVIE indirectly supports the EGA/VGA 43- and 50-line display mode because of its configurability. However, you will need both an ANSI.SYS that supports 43-line mode (like NANSI.SYS) and a utility to switch your graphics card into 43-line mode. After setting up the display mode while still in DOS, you must start STEVIE and then issue the command :set lines=43. Scrolling and refreshing worked smoothly on my ATI VGA/Wonder+ (1024K RAM) using L43.COM and NANSI.SYS. I also tried the proprietary ATI 132-column x 44-line mode and found it usable although STEVIE still enforced line wrapping at 80 columns.
Because STEVIE v3.71 was released in 1989, the documentation only claims compatability with Microsoft C v5.1 in the MS-DOS environment. However, I compiled the STEVIE source code without errors using the Microsoft C v6.00A. The quality of the source code could be improved with the addition of ANSI function prototypes.
The source code ships configured for UNIX and must be modified to build under other platforms. The documentation omits the exact procedure for building on MS-DOS, so I'll describe it here. Specifically, you must comment out both the #define UNIX and #define TERMCAP and uncomment #define DOS in the file ENV.H. Once built, the Microsoft EXEHDR utility reported that STEVIE.EXE was 105K in length and required 129K to run.
Building STEVIE for OS/2 v2.0 required more modification. Around the time STEVIE was released, OS/2 v1.1 was current, so some incompatiblities with v2.0 were to be expected. Kevin Nickerson (Ann Arbor, MI) lent me his expertise in porting STEVIE to OS/2 v2.0 using the C/2 compiler. Specificially, he reported the following changes required to correctly build STEVIE:
Once built, STEVIE for OS/2 v2.0 behaved well in an OS/2 command window.STEVIE was friendly in its CPU usage and had no noticeable impact when idle.
- Uncomment #define OS2 in ENV.H
- Remove declarations like extern char *malloc; which collided with the ANSI headers in all files.
- Add STDLIB.H to ANSI headers included in STEVIE.H
- Change inchar to call KbdCharln instead of getch in OS2.C
- Add handling for EOF case to inchar
- Change the write and read calls to fwrite and fread in OS2.C
The main STEVIE documentation consists of the 12-page User Reference in both plain ASCII and nroff text formats. The ASCII version of the manual is formatted to exactly 66 lines per page with no formfeeds. The documentation clearly states that it is intended for users already familiar with the vi editor. Since vi is already well-documented both in print and online tutorials, this seems reasonable. (See bibliography.) For an idea of which advanced features STEVIE supports, see Table 2. The User Reference does provide brief one-line descriptions of all :set commands, and single and double-letter commands (e.g. yy). Additionally, an online listing of these commands appears when you issue the :help command in STEVIE.
The STEVIE documentation also provides a few additional pages of information in Porting Notes and Source Notes. The Porting Notes provide general tips on how to move STEVIE to an unsupported environment. However, specific instructions for compiling in each individual supported environment are missing. The Source Notes cover the most important data structure in STEVIE the doubly-linked list of text line structures. STEVIE allocates to each line buffer the exact number of characters needed to hold it.
Since STEVIE is freeware, without any remuneration to the author, one normally does not expect extensive support. In the documentation, Andrews concedes that since STEVIE is stable, new releases may not be forthcoming. He goes on to say that he will accept bug reports and enhancements to the source code from time to time. Nevertheless, since three years have elapsed since the last release, it may be unrealistic to expect active support at this time.
RED (CUG318)
The RED editor by Edward Ream (Madison, WI) is an extremely compact editor that uses virtual memory techniques to handle files bigger than memory alone would allow. RED is also notable for its interrupt-driven displays and pattern-matching search and replace. RED first appeared in an article in the January 1983 issue of Dr. Dobb's Journal. CUG318 contains RED v7.0 as released on January 26th, 1990. This version claims compatability with both Microsoft C and Borland Turbo C.
RED can edit very large files, yet only needs 56K of memory to run. The secret behind this is the work file that RED creates as it loads your file. The work file is an indexed set of doubly-linked 1K blocks. Each block contains the actual text associated with lines in the edit file. The resulting temporary file is at least as big as the original file. RED keeps at least 10 of these 1K blocks in memory at any time. When the user scrolls out of the region of the file that is in memory, RED swaps out the least recently used blocks.
In an attempt to push RED to its limits, I asked it to load a 691K file containing 32,767 lines of text. Although it required several seconds to load up, RED was then able to rapidly traverse the file. Next, I increased the file up to 34,000 lines of text and tried RED again. RED reported several internal errors in building the temporary file and refused to load the file. This problem is due to RED using 16-bit signed integers rather than 32-bit longs to represent line numbers.
Although RED will handle very long text files well, none of the lines can be longer than 79 characters. RED simply reports line truncated after feeding it a file with lines up to 255 characters wide. RED will prevent you from entering a line longer than 79 characters as well. If you enable line wrap, then it will move the last word on a line as a word processor would.
Another technical innovation of RED is its interrupt-driven screen refresh. Screen refreshes most often occur when you scroll up or down an entire page of text. Rather than simply allowing MS-DOS to buffer keystrokes while the screen is refreshing, RED reads each keystroke and interrupts the refresh. The main benefit is that you can traverse the file much quicker than if you had to wait for every single screenful of text to be painted. Many commercial word processors use such a scheme to defer the reformatting of paragraphs until you are done typing, for example.
Since RED is so compact, its command set is quite limited. (See Table 2 and Table 3. ) The block move, copy, and delete functions are cumbersome because they require you to keyboard the actual line numbers affected. The undo handling is limited to the current line and disappears if you leave the line. However, RED does provide pattern matching search and replace. The patterns supported are a small subset of regular expressions. Specifically, you can set up patterns with ? for single character matches, ^ to match only at the beginning of a line, and $ to match only at the end of a line. Since RED does not have a Kleene * operator to match zero or more characters, it falls short of complete regular expression handling.
I found RED to be in good working order with the exception of the quit command. The quit command, which is supposed to exit to MS-DOS, would report the error Too many ?s in mask and hang the system. I tried running it on both MS-DOS v3.3 and v5.0 and achieved identical results. With some detective work, I discovered #ifdefs and comments indicating that the quit command was only an experimental alternative to the exit command. As such, I only needed to comment out the #ifdef SUSPEND to remove the quit command.
Since rebuilding RED.EXE correctly took some additional effort, I will report on the process. I first had to remove many hardcoded pathnames from the makefile and some of the #includes. The makefile expects a particular subdirectory structure but the files on the distribution disk were all in one flat directory. I corrected the makefiles and continued to build.
Compiling RED with Microsoft C v6.00A uncovered numerous warnings about trying to use the NULL constant (OL) in conjunction with 16-bit int variables. I had to edit REDMAIN.C to prevent an error message where NULL was used as a case in an int switch statement. I encountered many long/short mismatch warnings where the compiler was forced to do a type promotion. Microsoft MASM v5.1 warned that the symbol NEAR in REDOUTA.ASM duplicated a reserved word. I changed the symbol NEAR to USENEAR to avoid the conflict.
Upon completing the build, I soon discovered runtime stack errors on exiting RED. I eventually increased the stack from its initial value of 3,000 bytes up to 8,000 bytes to prevent stack overflows. After this final fix, RED performed all functions without complaint.
The documentation for RED consists mainly of the 15-page Reference Guide provided in plain ASCII format. The Reference Guide covers each command and special keystroke in detail. The manual is organized well enough for even a novice to understand the behavior of the editor. The supplementary four page Technical Notes provide some porting hints, commentary on programming styles, and a description of how to use the SHERLOCK debugging macros.
Since RED is freeware, one normally would not expect a formal support program. Rather than requiring a fee for support, Ream offers a bounty of $5.12 that is "cheerfully paid to the first person who finds any bug." He also offers a bounty of $1.28 for each typographical error found in documentation or source code.
SE (CUG331)
The Stack Editor (SE) by Gary Osborn (Yorba Linda, CA) provides complete command and text stacking rivalling commercial products such as Brief. SE also contains a powerful built-in virtual memory manager for editing files up to 3MB long. SE buffers very large files with as little as 6K additional RAM and as much as 500K RAM depending on available memory. SE also includes an embedded nroff dot command processor for added word processing functionality. CUG331 contains SE vl.0 as released on June 12th, 1990.The SE editor originates from a distinguished lineage of editors with a decade of development behind it. It all began with G. Nigel Gilbert's groundbreaking E editor for CP/M released between 1981 and 1983 (CUG133). In the days of CP/M, which had a 64K memory limit, the virtual-memory aspect was even more important than today. James W. Haefner built on Gilbert's initial design and eventually released Q.E.D. v4.6b for PCs in 1985 (CUG157). Mel Tearle in turn built on Haefner's code to produce GED vl.05 in 1986 (CUG199). The GED editor was the first of the line that could run on the new PC clones, such as Compaq. Last, Gary Osborn put his mark on the code in 1990 to produce the advanced command and text stacking capabilities comprising SE.
SE provides a complete set of block editing operations: move, copy, delete, shift (indent/outdent), and print. SE is notable in that it actually highlights the block of text as you define it by moving the cursor. The block of text must begin and end on line boundaries. The shift operation is especially nice in that you move the block left and right with each keystroke. All block operations can be undone and redone in accordance with the stack metaphor.
SE's stack operations provide an easy way of moving a line of code, of transposing lines, and of duplicating lines. Pushing several lines, then popping them elsewhere is a convenient way to move a small block. The text stack shares the same area as the command stack (used for undo and redo). Pops can be undone, but if the editing operation that did the push is undone, then the associated pop will find the stack empty. You can either pop directly from the stack or pop a copy of the top of the stack. A few editing operations other than delete (such as line concatenation) affect the stack also and can result in unexpected items on the stack. Don't do too much editing if items are to be popped from the stack.
The nroff (or runoff) commands provide simple directives for basic word processing functions. You can imbed these commands in your plain ASCII text file or ignore them completely. These commands always start with a dot in column one and are abbreviated to two letters. Specifically, SE supports left margin (.in), right margin (.rm), top margin (.m1), disabled formatting (.nf), lines per page (.pl), page headers (.he), page footers (.fo), page breaks (.bp), page break override (.ne), center text (.ce), underline text (.ul), and line spacing (.ls). Many of these commands can be run from within SE, rather than requiring you to generate an output file to activate them.
Building SE required some additional effort, as I will describe. Since SE was last released for Microsoft C v4.0, I had to adjust the BUILD.BAT file to call CL.EXE rather than MSC.EXE. Compiling the 15 source files produced more than 118 warning messages at the lowest warning level (/W1). Fortunately, about 100 warnings were due to implicitly defined int functions which returned no particular value. There were three warnings regarding case values of more than 1,000 being compared in a switch statement where the operand was an unsigned char. An unsigned char can only assume values from 0 to 255, so 1,000 is clearly out of range.
Once compiled, I needed to adjust the linker response file to handle the format of Microsoft Linker v5.10. I quickly discovered a multiply-defined external called clock. The MSC run-time library provides a function called clock which returns the amount of time the application has been running. This clock function conflicted with a global int called clock defined in GED.H. The variable clock serves as a counter for the LRU paging mechanism in SE. I resolved the situation by renaming the clock variable to se_clock in GED.H, SWAP.C, and STORE.C. After resolving this conflict, I encountered no further problems. The Microsoft EXEHDR reported that SE.EXE was 43K in length and required 64K to run. All editing functions worked just as well as in the executable distributed on diskette.
The SE documentation consists of two separate eight-page overviews entitled simply The SE Editor and SE Stack Editor. Both documents are formatted with some nroff dot commands, but are still quite readable in source form. The first document discusses the architectual tradeoffs taken in the virtual memory and screen refresh implementation. Other topics include the motivation for stack-based editing, handling partially binary files, and embedded nroff commands. The second document provides a keyboard quick reference, detailed dot command reference, and command-line parameters. Although there are no detailed discussions of algorithms or data structures, the C source code is fairly well documented.
Since SE has been released into the public domain without compensation to the author, the absence of a formal support plan should not be surprising. Even though Osborn devotes several paragraphs to outlining ideas for future work, there is no release schedule attached. The documentation does not mention a host where the latest version may be found nor is there an e-mail address for the author.
The Best Editor for the Job
Choosing between the STEVIE (CUG313), RED (CUG318), and SE (CUG331) can be difficult. If you need cross-platform compatibility or prefer the vi command set, then STEVIE is your best choice. If you need a very compact editor that can handle reasonably large files (~700K) or require interrupt-driven screen refresh, then RED is your best choice. If you need a small editor with strong block operations, the ability to handle very large files (3,000K), or nroff support, then SE is your best choice. All are public domain with full source code and available at minimal cost directly from the C Users Group Library.
Reference
Lamb, Linda. 1988. Learning the vi editor. Sebastopol, CA: O'Reilly & Associates. Contact nuts@ora.uu.corn or uunet!ora!nuts.