EDITOR -- ASCII Editing 1) EDITOR Usage | OBJECT edt[EDITOR]; An editor object provides a large set of functions for loading, modifying, and saving text files. Although it is mostly used for editing ASCII text, it may be used to edit 'binary' data streams as well. The EDITOR class edits text in memory using a gap moving algorithm, which is one of the most efficient algorithms on low-memory systems, since it makes the entire buffer size available to text. A variable called the POINT is used to mark the position where the next editing operation will take place. It always points *between* two caracters. This variable is comparable to a 'cursor', but it is not visual. Text is edited using the EDITOR class by moving the POINT to a specific location and then performing some operation (like deleting or inserting characters). POINT is an offset into the editing buffer. The EDITOR class does implement the concept of 'lines'. A line is any number of characters terminated by either a newline character (Linefeed, LF, 0x0A) or the end of the buffer. There is no limit on the maximum length of a line except for the size of the buffer. Block operations are performed on a region of text called the BLOCK. The beginning of the block is called the MARK and its end is called EBLOCK. MARK points at (before) the first character in the BLOCK and EBLOCK point at (before) the first character not contained in the BLOCK. The size of the editing buffer is specified when initializing an EDITOR instance. The buffer must be supplied by the user program. All methods provided by the EDITOR class return either zero (indicating success) or a negative error code (which will be explained in a separate section). When an error code is returned, the state of the object is not altered. 2) Methods 2.1 Initialization and Reset | ED.INIT(buffer, size) ! Bvec,Num => 0 | ED.RESET() ! => 0 ED.INIT initializes an EDITOR object. 'Buffer' is a vector which will be used to hold text characters during the editing session. Its size determines the maximum number of characters which can be edited. 'Size' is used to specify the size of the buffer. A buffer may not be larger than 32767 characters. The text length will be set to zero and the POINT will be set to the beginning of the (empty) buffer. ED.RESET resets the editor buffer to initial (empty) state. 2.2 Absolute Point Movement | ED.BOTTOM() ! => 0 | ED.GOTO(pt) ! Num => 0 | ED.GOTOLN(n) ! Num => 0|error | ED.TOP() ! => 0 ED.BOTTOM() moves the POINT before the first unallocated character in the buffer (past the end of the text). ED.GOTO(pt) moves the POINT to the absolute location specified by the PT argument. PT must be a valid point position (0 <= pt <= length of text). ED.GOTOLN(n) moves the point to the beginning of the N'th line in the buffer (before the first character of that line). The first line is addressed using N=0. ED.TOP() moves the POINT before the first character of the entire text buffer. 2.3 Relative Point Movement | ED.ADVANCE(n) ! Num => m|error | ED.EOL() ! => 0 | ED.GOBACK(n) ! Num => m|error | ED.GOTOCOL(n) ! Num => 0|error | ED.HOME() ! => 0 | ED.NEXT(n) ! Num => 0|error | ED.PREV(n) ! Num => 0|error ED.ADVANCE(n) moves the POINT toward the end of the buffer by N character positions. Return value: see below. ED.EOL() moves the point before the newline character which separates the current line from the next one. If the current line is the last one in the text, move to the bottom of the text (as if ED.BOTTOM() had been applied). ED.GOBACK(n) moves the POINT toward the beginning of the buffer by N character positions. Return value: see below. ED.GOTOCOL(n) moves the POINT before the N'th character of the current line (where the first character is addressed using N=0). ED.HOME() moves the POINT before the first character of the current line. ED.NEXT(n) advances the POINT [see ED.ADVANCE()] until N line boundaries have been crossed. It places the cursor before the first character of the destination line. ED.PREV(n) backs up the POINT [see ED.GOBACK()] until N line boundaries have been crossed. It places the cursor before the first character of the destination line. Upon success, ADVANCE() and GOBACK() return the number of line boundaries crossed while moving the POINT. 2.4 Finding Text | ED.FIND(str, start, lim) ! Str,Num,Num => pt|error | ED.FINDMATCH() ! => pt|error | ED.RFIND(str, start, lim) ! Str,Num,Num => pt|error ED.FIND() and ED.RFIND() are used to locate text inside of a limited region of the text buffer. START and LIM are used to delimit the region. They must meet the following assertions: 0 <= Start <= ED._LENGTH() 0 <= Lim <= ED._LENGTH() Start < Lim STR is the string to be located. A string which is to be matched must be completely contained in the specified region. If only a single character of the potential match is located outside of the region, the match will not be recognized. RFIND() differs from FIND() in its search direction. FIND() begins at START and advances toward LIM, while and RFIND() (reverse find) begins at LIM and advances toward START. Therefore FIND() will find the first and RFIND() will find the last match in the given region. FINDMATCH() searches a matching parenthesis. If the point is before a left parenthesis ['('], it will search a matching right parenthesis between the point and the end of the buffer. If the point is before a right parenthesis [')'], it will search for a left one between the point and the beginning of the buffer. FINDMATCH() finds exactly the parenthesis which closes (opens) the one which is opened (closed) at the POINT. There may be any number of embedded pairs of parentheses between the opening and closing character. FINDMATCH() returns an error, if either the point does not point at a parenthesis or no match is found. Either method returns a valid POUNT value, if a match has been found. If no match exists in the region, a negative error code is returned. ED.GOTO() may be used to move the POINT to a match. 2.5 Changing Text | ED.DELETE(n) ! Num => 0|error | ED.DELETELN() ! => 0|error | ED.INSERTC(ch) ! Char => 0|error | ED.INSERTS(str) ! Str => 0|error | ED.REPLACEC(ch) ! Char => 0|error | ED.REPLECES(str) ! Str => 0|error ED.DELETE(n) deletes N characters located at the righthand side of the POINT. ED.DELETELN() deletes all characters from the beginning of the current line up to (and including) the newline character separating the current line from the next one. If no seperator exists (when deleting the last line), all characters up to the end of the buffer will be deleted. ED.INSERTC(ch) inserts the character CH at the current point position. The POINT will NOT be advanced by insertions. ED.INSERTS(str) inserts the string STR at the current point position. After the operation, POINT will point to the first character of the inserted string. ED.REPLACEC(ch) replaces the character following the POINT with the character CH. ED.REPLACES(str) replaces the characters at the righthand side of the POINT by the characters of the string STR. A sufficient number of characters must be present right of the POINT, since this function cannot change the text length. 2.6 Input/Output Operations | ED.COPY(off, buf, len) ! Num,Str,Num => n | ED.COPYLN(buf, len) ! Str,Num => n | ED.LOAD(path) ! Str => n|error | ED.LOAD_DOS(path) ! Str => n|error | ED.SAVE(path) ! Str => 0|error | ED.SAVE_DOS(path) ! Str => 0|error ED.COPY(off,buf,len) copies up to LEN-1 characters from the current line into the user-supplied buffer BUF. OFF specifies the offset (into the line) of the first character to be extracted. When a line separator is encountered before LEN characters have been copied, the method stops copying. ED.COPY() appends a terminating NUL character to the text in BUF and returns the number of characters copied. ED.COPYLN(buf, len) is equal to ED.COPY(0, buf, len) . ED.LOAD(path) re-initializes the editing buffer and then loads the file specified in PATH into the buffer. Upon success, it returns the number of characters read. NOTE: when the number of characters read is equal to the size of the editing buffer, the content may have been truncated. In this case, the buffer should not be saved at a later time! ED.LOAD_DOS(path) is like LOAD, but removes any CR characters found in the input file. It is used to load DOS text file. ED.SAVE(path) write the current content of the editing buffer to the file specified in PATH. ED.SAVE_DOS(path) is like SAVE, but write a CR,LF combination for each LF found in the buffer. It is used to write DOS compatible text files. 2.7 Block Operations | ED.APPENDBLOCK(path) ! Str => n|error | ED.CLEARBLOCK() ! => 0 | ED.COPYBLOCK() ! => 0|error | ED.DELETEBLOCK() ! => 0|error | ED.MARK(pt) ! Num => 0 | ED.MARKLIST() ! => 0|error | ED.MOVEBLOCK() ! => 0|error | ED.READBLOCK(path) ! Str => n|error | ED.SETBLOCK(pt) ! Num => 0 | ED.WRITEBLOCK(path) ! Str => n|error ED.APPENDBLOCK(path) writes the current block to the file specified in PATH. It does not overwrite the file, but appends the block to the content of the already existing file. ED.CLEARBLOCK() clears the block delimiters, thereby canceling a previously made block definition. ED.COPYBLOCK() copies the currently defined block and inserts the copy at the current POINT position. The POINT may not be located inside of the block. The POINT position will be changed to the beginning of the inserted block, MARK will be set to POINT, and EBLOCK will be set before the first character past the end of the inserted block. ED.DELETEBLOCK() sets the POINT to the beginning of the current block and then removes all characters contained in the block. ED.MARK(tp) sets the MARK to the position specified by PT. PT must be a valid POINT position. ED.MARKLIST() first moves the point to the left until it finds an opening parenthesis and then searches the matching closing parenthesis [see ED.FINDMATCH()]. It sets the MARK to the opening parenthesis and EBLOCK to the position after the closing parenthesis. If no opening parenthesis or no closing counterpart can be found, the method returns a negative error code. ED.MOVEBLOCK() moves the currently defined block to the current POINT position. The POINT may not be located inside of the BLOCK. The POINT position will be changed to the beginning of the moved block, MARK will be set to POINT, and EBLOCK will be set before the first character past the end of the moved block. NOTE: moving a block is done by first copying it and then deleting the original block. Consequently, sufficient space for two copies of the BLOCK must be avaliable. ED.READBLOCK() reads the file specified in PATH and inserts it at the current point position. MARK will be set to POINT and EBLOCK will point at the first character after the inserted BLOCK. ED.SETBLOCK(pt) sets the end of the BLOCK (EBLOCK) to PT, which must be a valid POINT position. A block is defined as the text starting at (and including) MARK and extending up to (but not including) EBLOCK. ED.WRITEBLOCK(PATH) writes the current BLOCK to the file specified in PATH. The file will be overwritten. 2.8 Variables | ED._BLOCK() ! => BLOCK | ED._CHAR() ! => ch | ED._EBLOCK() ! => EBLOCK | ED._LENGTH() ! => LENGTH | ED._LINE() ! => LINE | ED._OFFSET() ! => POINT-LINE | ED._POINT() ! => POINT | ED._SIZE(sv) ! Vec => LENGTH Method Returns ED._BLOCK() the current MARK position (beginning of BLOCK) ED._CHAR() the character right of the POINT ED._EBLOCK() the current EBLOCK (end of BLOCK) position ED._LENGTH() the number of characters in the buffer ED._LINE() the offset of the current line ED._OFFSET() the offset into the current line (POINT-LINE) ED._SIZE() queries various text sizes and stores them in the SIZES structure passed to it. It returns ED._LENGTH(). The SIZES structure has the following members: S_LENGTH the length of the text [ED._LENGTH()] S_TOTAL the total number of lines in the buffer S_LINE the number of the current line (first line = 0) 2.9 Error Codes These codes are returned by the EDITOR methods in case of an error. All error codes are negative and EDITOR methods never return negative values upon success. The following error codes exist: EDITOR.E_IO An I/O error has occured (like no space . left on a device or an unrecoverable read . error). EDITOR.E_NOBLK A block operation has been requested, but . no block is defined. EDITOR.E_NOMATCH No match has been found during a text . search operation. EDITOR.E_OPEN A requested file could not be opened or . created. EDITOR.E_SIZE There are not enough characters in the buffer . to perform the requested operation. This . error is caused by attempting to move . the POINT beyond the end of the file, . for example. EDITOR.E_SPACE The requested operation requires more . unallocated characters than present in the . editing buffer (buffer overflow). EDITOR.E_SRCDST Source/destination conflict while copying . or moving a BLOCK.