VEDIT -- Visual ASCII Editing 1) Usage | OBJECT ve[VEDIT]; The VEDIT class is a visual wrapper around the EDITOR class. Each instance of VEDIT must be initialized by sending it an INIT message. When it is no longer used, it should be shut down by sending it a FINI message. The VEDIT class is not a complete visual editor itself, but it provides only a set of routines commonly used in visual editors, like moving around the cursor, inserting and deleting text, displaying pages of text, loading and saving text, performing operations on regions of text, etc. Basically, VEDIT provides the same editing functions as the EDITOR class, but at the same time, it maintains a visual representation of the text being edited on the terminal screen. Unlike the EDITOR class, VEDIT imposes a restriction on the line length of the edited text: no line may exceed a limit of 255 characters. Since VEDIT instances are visually oriented, they employ a CURSOR rather than a POINT. The cursor is the visual representation of the POINT (as defined by the EDITOR class). Depending upon the implementation, the CURSOR may appear between two characters, resembling the position of the POINT, or it may be drawn 'around' the character on the righthand side of POINT. All VEDIT operations are performed by first performing the respective EDITOR operation and then updating the display. If the EDITOR operation fails, the display will not be updated. 2) Methods 2.1 Initialization and Shutdown | VE.INIT(x, y, width, height, buf, len) | ! Num,Num,Num,Num,Bvec,Num => 0|-1 | VE.RESET() ! => 0 | VE.FINI() ! => 0 VE.INIT initialzes the edit buffer and window. It places the cursor at the top of the file, switches the TTY, the process is connected to, to raw mode, and sets the internal editor flags to some compiled-in defaults. The arguments have the following meanings: X The column the editing window starts at Y The row the editing window starts at WIDTH The horizonatal size of the editing window in columns HEIGHT The vertical size of the editing window in rows BUF The editing buffer (at least LEN characters in size) LEN The length of the editing buffer VE.INIT returns a negative value, if the initialization failed, mostly due to an out of range width value (>128). The INIT method sets up the following defaults: C_TABSIZE 8 characters C_ASYNC enabled C_SHOWCTL enabled C_VBLOCKS enabled C_TEXTCOLOR grey/black C_HIGHCOLOR black/grey C_MARKCOLOR black/grey All other configuration values are set to values passed to VE.INIT as arguments. VE.RESET resets the editor buffer to initial (empty) state. It places the cursor at the beginning of the buffer. VE.RESET does not update the editing window. VE.FINI restores the TTY mode which was in effect before initialization and re-sets the color to grey on black. 2.2 SETUP | VE.SETUP(cv) ! Vec => 0|code VE.SETUP processes a configuration vector containing name/value pairs. Each pair contains a constant at the first position and a value at the second one. Each value is assigned to an internal variable associated with the constant. If an invalid constant is found in the pair list, the pair is skipped and a negative value is returned. When all pairs were valid, SETUP returns zero. The variables controlled by SETUP influence the layout and behaviour of the VEDIT instance the message is sent to. It is recommended to re-display the editing window after sending a SETUP message [using VE.DISPLAY]. The following variables exist: C_TABSIZE The maximum size of a TAB character. TAB characters . will be expanded in such a way that they end at . columns which are multiples of this value. C_ASYNC Enable asynchronous mode. In asynchronous mode, . processing key events has priority over window . refreshs. Screen refreshs are first completed when . no more keys are to be processed. This mode is faster . on slow TTYs, but may look confusing to users who are . not used to it. C_SHOWCTL Display control characters (0x00-0x1F, except for . 0x0A) in HIGHCOLOR. When SHOWCTL mode is disabled, . editing texts containing control characters may . lead to messed-up editing windows. C_VBLOCKS Display marked blocks in MARKCOLOR. When this mode . is disabled, marked blocks are invisible. C_TEXTCOLOR The color of unmarked, printable text inside the . editing window. C_HIGHCOLOR The color of unprintable text inside the editing . window, if C_SHOWCTL is enabled. C_MARKCOLOR The color of marked blocks inside the editing . window, if C_VBLOCKS is enabled. C_XBASE The column the editing window starts at. C_YBASE The row the editing window starts at. C_XMAX The horizontal size of the editing window. C_YMAX The vertical size of the editing window. Some significant speedup can be achieved by disabling both SHOWCTL and VBLOCKS (but at the cost of stability). 2.3 Display Functions | VE.DISPLAY() ! => 0 | VE.REFRESH(top, bottom) ! Num,Num => 0 | VE.SHOWMATCH(on) ! Num => 0 | VE.SYNC() ! => 0 | VE.TOTOP() ! => 0 VE.DISPLAY is equal to VE.REFRESH(0, YMAX-1) where YMAX is the number of rows in the editing window. VE.REFRESH redraws the lines TOP to BOTTOM in the editing window. The first line in the window is line #0. If the C_ASYNC flag is set [see VE.SETUP], the screen refresh will be interrupted, when a key is pressed on the TTY connected to the editor process. VE.SHOWMATCH(on) uses ED.FINDMATCH() to find a parenthesis which opens (closes) the one pointed to by the cursor. If a matching parenthesis exists AND is located in the editing window, it will be redrawn. C_HIGHCOLOR will be used to redraw the parenthesis, if ON=1 and C_TEXTCOLOR will be used, if ON=0. If the cursor does not point to a parenthesis, this method does nothing. VE.SYNC synchronizes the CURSOR position with the POINT position by moving the visual cursor. If the X-position of the cursor is outside of the window, the OFFSET of the window will be adjusted (by scrolling the window sideways) and the window will be redrawn. If the current line is not in the window, the effect of sending a VE.SYNC message is undefined. (In this case, use VE.GOTO() or VE.GOTOLN() instead.) VE.TOTOP makes the current line the top of the window and then sends SELF.DISPLAY. 2.4 Keyboard Input | VE.KEY() ! => K | VE.TTYMODE(M) ! Num => 0 VE.KEY waits for keyboard input and returns the character typed. When the C_ASYNC flag is set [see VE.SETUP()] and a screen refresh has been interrupted by pressing a key, VE.KEY will restart the refresh. VE.TTYMODE(m) is used to release or re-connect the keyboard by switching it to raw mode (M=1) or cooked mode (M=0). When an editor application spawns a shell process, the TTY should be released before and re-connected after running the process. 2.5 Moving the Cursor | VE.BOTTOM() ! => 0 | VE.DOWN() ! => 0|-1 | VE.EOL() ! => 0 | VE.HOME() ! => 0 | VE.LEFT() ! => 0|-1 | VE.NEXT() ! => 0 | VE.PREV() ! => 0 | VE.RIGHT() ! => 0|-1 | VE.TOP() ! => 0 | VE.UP() ! => 0|-1 VE.BOTTOM moves the cursor past the end of the text. The editing window will be redrawn, if necessary. VE.DOWN moves the cursor down one line. If no next line exists, an error code (-1) will be returned. When moving to the next line, the method will attempt to hold the cursor in the same column. If the cursor is moved past the last line of the editing window, the content of the window is scrolled up one line, keeping the cursor inside of the window. VE.EOL moves the cursor to the end of the current line. The screen will be scrolled sideways, if necessary. VE.HOME moves the cursor to the beginning of the current line. The screen will be scrolled sideways, if necessary. VE.LEFT moves the cursor to the left one character. At the beginning of a line, the cursor will move to the end of the previous line. The screen will be scrolled sideways, if necessary. At the beginning of the buffer, this method has no effect. In this case, it returns -1. VE.NEXT scrolls the content of the editing window down YMAX lines, where YMAX is the total number of lines in the editing window. If no YMAX lines exist between the cursor and the end of the buffer, NEXT behaves like BOTTOM. VE.PREV scrolls the content of the editing window up YMAX lines, where YMAX is the total number of lines in the editing window. If no YMAX lines exist between the cursor and the top of the buffer, PREV behaves like TOP. VE.RIGHT moves the cursor to the right one character. At the end of a line, the cursor will move to the beginnig of the next line. The screen will be scrolled sideways, if necessary. At the end of the buffer, this method has no effect. In this case, it returns -1. VE.TOP moves the cursor to the beginning of the text. The editing window will be redrawn, if necessary. VE.UP moves the cursor up one line. If no previous line exists, an error code (-1) will be returned. When moving to the previous line, the method will attempt to hold the cursor in the same column. If the cursor is moved past the first line of the editing window, the content of the window is scrolled down one line, keeping the cursor inside of the window. 2.6 Positioning the Cursor | VE.FIND(str, rs, re) ! Str,Num,Num => 0|-1 | VE.FINDMATCH() ! => 0|-1 | VE.GOTO(pos) ! Num => f | VE.GOTOLN(n) ! Num => 0|-1 | VE.RFIND(str, rs, re) ! Str,Num,Num => 0|-1 VE.FIND() searches the string STR inside the specified text region, beginning at the top of the region. RS specifies the beginning of the region to search and RE specifies the offset of the first character past the region. A string must be completely contained in the given region to be matched. FIND returns zero, if the string has been found and otherwise -1. When a match has been found, the cursor will be positioned at the first occurence of STR. VE.FINDMATCH searches the parenthesis which closes (opens, in case it is a closing one) the one pointed to by the cursor. If the cursor does not point to a parenthesis or no matching one exists, the method returns -1. Otherwise it moves the cursor to the matching parenthesis. VE.GOTO moves the cursor to the given position. It returns a flag indicating whether the editing window had to be redrawn for repositioning the cursor (0 = no redraw done). VE.GOTOLN positions the cursor at the beginning of the given line. The first line in the buffer has the number 0. VE.RFIND is like FIND but differs from FIND in the direction of the search. RFIND begins at the bottom of the region and moves toward the top. Hence it positions the cursor at the location of the last match, if any. All these methods redraw the screen, if necessary. 2.7 Inserting and Deleting Text | VE.BACKSPACE() ! => 0 | VE.DELETE() ! => 0 | VE.DELETELN() ! => 0 | VE.INDENT() ! => 0|-1 | VE.INSERT(k) ! Char => 0|-1 VE.BACKSPACE moves the cursor to the left one character [see VE.LEFT] and the deletes the character on the right [see VE.DELETE]. VE.DELETE deletes the character on the righthand side of the cursor. If the deleted character was a newline character, it redraws all lines from (and including) the current one up to the end of the editing window. Otherwise it just redraws the current line. VE.DELETELN removes the entire line the cursor currently is positioned in. It redraws the editing window from (and including) the current line up to the bottom of the window. VE.INDENT indents the current line by cloning any blank and TAB characters found at the beginning of the previous line and inserting them at the beginning of the current line. It redraws the current line. For some simple reasons, VE.INDENT cannot be applied to the first line in the buffer. Doing so will not have any effect but returning a code of -1. VE.INSERT(k) inserts the character K into the editing buffer and then advances the cursor using VE.RIGHT. A non-zero return code indicates a buffer overflow. 2.8 Block Operations | VE.APPENDBLOCK(filename) ! Str => N | VE.CLEARBLOCK() ! => 0 | VE.COPYBLOCK() ! => N | VE.DELETEBLOCK() ! => 0|-1 | VE.MARK() ! => 0 | VE.MARKLIST() ! => 0 | VE.MOVEBLOCK() ! => N | VE.READBLOCK(filename) ! Str => N | VE.SETBLOCK() ! => 0 | VE.WRITEBLOCK(filename) ! Str => N VE.APPENDBLOCK is equal to ED.APPENDBLOCK. VE.CLEARBLOCK clears a previously created block definition and redraws the editing window. If no block is defined, it does nothing. VE.COPYBLOCK inserts a copy of the currently defined block at the position of the cursor. The block definition is changed to describe the inserted block (leaving the inserted copy 'marked'). A block cannot be copied into itself. The return code of VE.COPYBLOCK is in fact the code returned by ED.COPYBLOCK(). VE.DELETEBLOCK removes the text contained in the currently defined block from the editing buffer. It returns a negative value, if no block is defined. VE.MARK defines the beginning of a block (at the current cursor position). When a block definition already exists when sending MARK, this definition is cleared and the editing window is redrawn. VE.MARKLIST uses ED.MARKLIST to mark the text between (and including) the innermost pair of parentheses surrounding the cursor. If the cursor points itself at a parenthesis, this character will be used to delimit the list. If no list can be found around the cursor, the BLOCK will be cleared. VE.MARKLIST always redraws the editing window. VE.MOVEBLOCK inserts a copy of the currently defined block at the position of the cursor and then deletes the original block. The block definition moves with the block (leaving the inserted copy 'marked'). A block cannot be moved into itself. The return code of VE.MOVEBLOCK is in fact the code returned by ED.MOVEBLOCK. VE.READBLOCK reads the specified file and inserts its content at the current cursor position. It defines a block describing the inserted text. VE.READBLOCK uses ED.READBLOCK to insert the text and returns the result code delivered by this method. VE.SETBLOCK defines the end of a block (at the current cursor position) and redraws the editing window. VE.WRITEBLOCK is equal to ED.WRITEBLOCK. Block definitions are automatically cleared by methods which insert or delete text. 2.9 I/O-Operations | VE.COPYLN(buf, len) ! Bvec,Num => N | VE.LOAD() ! => Num|error | VE.SAVE() ! => Num|error VE.COPYLN is equal to ED.COPYLN. VE.SAVE is equal to ED.SAVE. VE.LOAD first passes the LOAD message to an embedded instance of editor and then refreshes the editing window. Except for redrawing the window, it is equal to ED.LOAD. 2.10 Non-visual Operations | VE.NV_DELETE(n) ! Num => Num|code | VE.NV_FIND(s, rs, re) ! Str,Num,Num => pos|-1 | VE.NV_GOTO(pos) ! Num => code | VE.NV_INSERT(str) ! Str => code VE.NV_DELETE is equal to ED.DELETE. VE.NV_FIND is equal to ED.FIND. VE.NV_GOTO is equal to ED.GOTO. VE.NV_INSERT is equal to VE.INSERTS. These methods are used to perform 'invisible' changes to the text buffer. They are useful for implementing automatic search/replace operations, which do not require visual feedback or user interaction. 2.11 Variables | VE._BLOCK() ! => ED._BLOCK() | VE._CHAR() ! => ED._CHAR() | VE._EBLOCK() ! => ED._EBOCK() | VE._LENGTH() ! => ED._LENGTH() | VE._LINE() ! => ED._LINE() | VE._POINT() ! => ED._POINT() | VE._SIZE(sv) ! Vec => ED._SIZE(sv) | VE._XPOS() ! => column | VE._YPOS() ! => row Most of these methods are perfectly euqal to their counterparts of the EDITOR class. The VE._XPOS method returns the current column of the cursor on the screen, if synchronized with ED._POINT. The VE._YPOS method returns the current row of the cursor on the screen, if synchronized with ED._POINT.