|
|
1.1 ! root 1: ! 2: Elvis 1.4 INTERNAL Page 8-1 ! 3: ! 4: ! 5: E8. INTERNALF ! 6: ! 7: You don't need to know the material in this section to use ! 8: elvis. You only need it if you intend to modify elvis. ! 9: ! 10: ! 11: E8.1 The temporary fileF ! 12: ! 13: The temporary file is divided into blocks of 1024 bytes each. ! 14: ! 15: When elvis starts up, the file is copied into the temporary ! 16: file. Small amounts of extra space are inserted into the temporary ! 17: file to insure that no text lines cross block boundaries; this ! 18: speeds up processing and simplifies storage management. The "extra ! 19: space" is filled with NUL characters; the input file must not ! 20: contain any NULs, to avoid confusion. ! 21: ! 22: The first block of the temporary file is an array of shorts ! 23: which describe the order of the blocks; i.e. header[1] is the ! 24: block number of the first block, and so on. This limits the ! 25: temporary file to 512 active blocks, so the largest file you can ! 26: edit is about 400K bytes long. I hope that's enough! ! 27: ! 28: When blocks are altered, they are rewritten to a -1different-0 block ! 29: in the file, and the in-core version of the header block is updated ! 30: accordingly. The in-core header block will be copied to the temp ! 31: file immediately before the next change... or, to undo this ! 32: change, swap the old header (from the temp file) with the new ! 33: (in-core) header. ! 34: ! 35: Elvis maintains another in-core array which contains the ! 36: line-number of the last line in every block. This allows you to go ! 37: directly to a line, given its line number. ! 38: ! 39: ! 40: E8.2 Implementation of EditingF ! 41: ! 42: There are three basic operations which affect text: ! 43: ! 44: * delete text - delete(from, to) ! 45: * add text - add(at, text) ! 46: * yank text - cut(from, to) ! 47: ! 48: To yank text, all text between two text positions is copied into ! 49: a cut buffer. The original text is not changed. To copy the text ! 50: into a cut buffer, you need only remember which physical blocks ! 51: that contain the cut text, the offset into the first block of the ! 52: start of the cut, the offset into the last block of the end of the ! 53: cut, and what kind of cut it was. (Cuts may be either character ! 54: cuts or line cuts; the kind of a cut affects the way it is later ! 55: "put".) This is implemented in the function cut(). ! 56: ! 57: To delete text, you must modify the first and last blocks, and ! 58: remove any reference to the intervening blocks in the header's ! 59: list. The text to be deleted is specified by two marks. This is ! 60: implemented in the function delete(). ! 61: ! 62: ! 63: ! 64: ! 65: ! 66: ! 67: ! 68: Elvis 1.4 INTERNAL Page 8-2 ! 69: ! 70: ! 71: To add text, you must specify the text to insert (as a ! 72: NUL-terminated string) and the place to insert it (as a mark). The ! 73: block into which the text is to be inserted may need to be split ! 74: into as many as four blocks, with new intervening blocks needed as ! 75: well... or it could be as simple as modifying a single block. ! 76: This is implemented in the function add(). ! 77: ! 78: Other interesting functions are paste() (to copy text from a cut ! 79: buffer into the file), modify() (for an efficient way to implement ! 80: a combined delete/add sequence), and input() (to get text from the ! 81: user & insert it into the file). ! 82: ! 83: When text is modified, an internal file-revision counter, called ! 84: "changes", is incremented. This counter is used to detect when ! 85: certain caches are out of date. (The "changes" counter is also ! 86: incremented when we switch to a different file, and also in one or ! 87: two similar situations -- all related to invalidating caches.) ! 88: ! 89: ! 90: E8.3 Marks and the CursorF ! 91: ! 92: Marks are places within the text. They are represented ! 93: internally as a long variable which is split into two bitfields: a ! 94: line number and a character index. Line numbers start with 1, and ! 95: character indexes start with 0. ! 96: ! 97: Since line numbers start with 1, it is impossible for a set mark ! 98: to have a value of 0L. 0L is therefore used to represent unset ! 99: marks. ! 100: ! 101: When you do the "delete text" change, any marks that were part ! 102: of the deleted text are unset, and any marks that were set to ! 103: points after it are adjusted. Similarly, marks are adjusted after ! 104: new text is inserted. ! 105: ! 106: The cursor is represented as a mark. ! 107: ! 108: ! 109: E8.4 Colon Command InterpretationF ! 110: ! 111: Colon commands are parsed, and the command name is looked up in ! 112: an array of structures which also contain a pointer to the function ! 113: that implements the command, and a description of the arguments ! 114: that the command can take. If the command is recognized and its ! 115: arguments are legal, then the function is called. ! 116: ! 117: Each function performs its task; this may cause the cursor to be ! 118: moved to a different line, or whatever. ! 119: ! 120: ! 121: E8.5 Screen ControlF ! 122: ! 123: The screen is updated via a package which looks like the ! 124: "curses" library, but isn't. It is actually much simpler. Most ! 125: curses operations are implemented as macros which copy characters ! 126: into a large I/O buffer, which is then written with a single large ! 127: write() call as part of the refresh() operation. ! 128: ! 129: ! 130: ! 131: ! 132: ! 133: ! 134: Elvis 1.4 INTERNAL Page 8-3 ! 135: ! 136: ! 137: The functions which modify text (namely add() and delete()) ! 138: remember where text has been modified. They do this by calling the ! 139: function redrawrange(). The screen redrawing function, redraw(), ! 140: uses these clues to help it reduce the amount of text that is ! 141: redrawn each time. ! 142: ! 143: ! 144: E8.6 PortabilityF ! 145: ! 146: To improve portability, Elvis collects as much of the ! 147: system-dependent definitions as possible into the config.h file. ! 148: This file begins with some preprocessor instructions which attempt ! 149: to determine which compiler and operating system you have. After ! 150: that, it conditionally defines some macros and constants for your ! 151: system. ! 152: ! 153: One of the more significant macros is ttyread(buf,n). This ! 154: macro is used to read raw characters from the keyboard. An attempt ! 155: to read may be cut short by a SIGALRM signal. For UNIX systems, ! 156: this simply reads bytes from stdin. For MSDOS, TOS, and OS9, ! 157: ttyread() is a function defined in curses.c. There is also a ! 158: ttywrite() macro. ! 159: ! 160: The tread() and twrite() macros are versions of read() and ! 161: write() that are used for text files. On UNIX systems, these are ! 162: equivelent to read() and write(). On MS-DOS, these are also ! 163: equivelent to read() and write(), since DOS libraries are generally ! 164: clever enough to convert newline characters automatically. For ! 165: Atari TOS, though, the MWC library is too stupid to do this, so we ! 166: had to do the conversion explicitly. ! 167: ! 168: Other macros may substitute index() for strchr(), or bcopy() for ! 169: memcpy(), or map the "void" data type to "int", or whatever. ! 170: ! 171: The file "tinytcap.c" contains a set of functions that emulate ! 172: the termcap library for a small set of terminal types. The ! 173: terminal-specific info is hard-coded into this file. It is only ! 174: used for systems that don't support real termcap. Another ! 175: alternative for screen control can be seen in the "curses.h" and ! 176: "pc.c" files. Here, macros named VOIDBIOS and CHECKBIOS are used ! 177: to indirectly call functions which perform low-level screen ! 178: manipulation via BIOS calls. ! 179: ! 180: The stat() function must be able to come up with UNIX-style ! 181: major/minor/inode numbers that uniquely identify a file or ! 182: directory. ! 183: ! 184: Please try to keep you changes localized, and wrap them in ! 185: #if/#endif pairs, so that elvis can still be compiled on other ! 186: systems. And PLEASE let me know about it, so I can incorporate ! 187: your changes into my latest-and-greatest version of elvis. ! 188: ! 189: ! 190: ! 191: ! 192: ! 193: ! 194: ! 195: ! 196: ! 197: ! 198:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.