Edit overview ============= This document provides an overview to the concepts, facilities, design and implementation of the Panos screen editor. As well as describing the current state of play, it also covers the original design aims (& subsequent changes thereto), as well as limitations & liabilities. In theory ... Edit is intended to be fully programable, consisting of :- - A simple LISP interpreter - An set of LISP primitives manipulating the basic built-in types (windows, buffers, markers, positions, characters, strings etc), and posssibly some user (guru) defined ones. Example primitives might be : * Create a new buffer of given size, returning the new buffer object * Interactively prompt for and read a string, returning that string object * Insert a character at a marked (defaulting ?) position of a buffer * Load a named file to a marked position in a buffer * Search for a pattern in a marked part of a buffer, returning the position * etc - A set of user-written LISP functions to perform things such as : * Put together primitives to build useful interactive commands * Provide last-search-string, default-extension etc type features * Define function/key binding * Provide customization for use with a particular language * etc - A user-written LISP control program, typically approximating to (LOOP ReadKey GetAction PerformAction ) - A display "null process", activated when the editor is waiting for input In reality ... The underlying language of Edit is List, not LISP. This is an overly simple Keith "the bastard" Rautenbach designed language, and supports function definition & invocation ONLY (no variables, looping, conditionals ... !!!). It has, however, been resourcefully (!) used to provide Modula-2 support, and is useful to alter start-up key bindings. The set of primitives is incomplete, and non-primitive. Some functions are implemented in-line, rather than out of primitive building blocks. All non-primitive commands, user-orientated features (E.g. default extension) and key bindings, as well as the (various) read,execute,display loops, are written in M2, and built into the editor. Edit suffers from some poor implementation of functions (E.g. markers - they require the insertion of a flag byte in the text), some obscure poorly structured code (E.g the DisplayPosition module), as well as the general results of massive growth, redesign, and idealistic (vs pragmatic) thinking. Hopefully Edit will be regarded as a thowaway copy (design exercise), and will be re-implemented from scratch, having noted the lessons learnt. However, for those hardy enough to venture in ... Edit as is ========== The display ----------- There is an important distinction to draw between the editor proper, and the display package. These two are extremeley loosly coupled; the display having the status of a "null process", being called when the editor is waiting for input. The display is given little, if any, hint as to what to display; its job is to make the screen reflect the current state of the editor. It has no qualms, in general, about abandoning its invocation when it realizes that the editor has work to do (E.g a key has been pressed) - it will surely be called again as soon as the editor is idle. There does, however, exist a flag, belonging to each window, to request the display to complete displaying that window, if it ever starts doing so. As an example of the (lack of) connection between the editor and the display, note that the ticking clock in the top right hand corner is achieved merely by inserting the current time into the appropiate buffer when the editor has nothing better to do (in fact when it's about to start the display process); when the editor is idle, the normal display call (Display.Something) will see the discrepency between buffer & screen, and provide the update. The display is itself split into two main sections (modules); that which decides what portion of a buffer to display where, and that which actually displays it. These are respectively the DisplayPosition & Display modules. DisplayPosition understands character widths, linebreaks, folded mode and indentation. It calculates the portions of the buffer to be displayed on each screen (window) line, and stores this information into an array belonging to the appropiate window. Display understands overlapping windows &&& The current display position module makes a feeble attempt to get things right when in folded mode. It normally fails. In the current implementation, the screen orientated commands (i.e. cursor movements) have their own limited knowledge about display positions. They assume each linebreak terminated line to occupy one (& only one) screen line. The resulting behaviour in folded mode is unattractive. A far cleaner, and more compact, method would be to have DisplayPosition calculate the screen layout, and the appropiate commands to move accordingly (1). (1) Note that DisplayPosition.Indent may be used to find the buffer position corresponding to a given screen offset (cursor column) from a calculated start of line buffer position. Special windows/buffers ----------------------- The display package, despite its weaknesses, is fairly flexible, and allows, for instance, the same character to be displayed differently if different windows. The support for this is provided via a set of procedure variables (initiallly assigned default values) in each window record. These are : * DisplayCh display given character at current display position * WidthDisplayCh determine width of given charater * DisplayMarker display given marker at current display position * ValidateRow determine what text to display at given window row The default values for the procedure values are exported from Display. Examples of the use of these include : - display of ctrl-B, ctrl-F as fat arrows in search parameter windows - display of prompt markers in plain text in parameter windows - use of validate row to dynamically generate text for help window - use of validate row as a hook to dynamically highlight search strings In the intended fully programmable version of Edit, these could conceivably be programmed in LISP, but a more efficient option might be to provide a useful set of preprogrammed variants. Markers ------- Key bindings ------------ The key binding mechanism (not the bindings themselves) in Edit is currently built in. It really should lie in the user domain (i.e. be programmable), however the current scheme is flexible, and has been found to work well. (Depending on the choice taken, input primitives might be either ReadKey, or ReadKeyAndAction). All Edit functions, predefined or programmed are named, and are accessed by textual name. Edit supports binding of any function to any key(s). A binding instance of a function may have associated with it a List (LISP) parameter list (thus, for example, Ctrl-Shift-LEFT/RIGHT normally have BufLeft/Right 20 bound to them). The bound function, parameter pair is internally refered to as an action. Bindings may either be global (via a globally defined key-indexed table), or local (to a buffer, via a linked list per buffer). Local bindings operate as a pushdown stack, with the topmost (per key) being taken taken as that prevalent. A key set is maintained along with each local binding list, to allow a quick determination of whether a key is locally bound, or not. If no local binding exists for a key, then the global binding is taken. Some limited demand has been had for the ability to bind actions to key SEQUENCES (a la emacs). This would be fairly simple to provide, via some sort of tree structure (nodes representing keystrokes), with a current position being maintained. A choices-for-sequence-completion menu could usefully be provided, although no support for such currently exists. Edit startup ------------ Historic/development features ----------------------------- During its early development period, various features have been tried in the editor, but subsequently removed; however a number of the data types still contain archaic fields (e.g. Cursor.Width, Cursor.Text in window records). These should really be removed, but are in practice little overhead, and not actually anoying if you accept them!. Artefacts left include : Edit hostcode ------------- Edit size --------- Edit is currently over 100K, but experience with previous text editors, as well as familiarity with M2 32000 code sizes, and knowledge of the source code would suggest it could be easily be implemented in 1/2 to 2/3 of this space. Obvious inefficiencies include : - Duplication of code between primitive & interactive versions of commands - Non structured coding (i.e. procedurization possibilities) - Sloppy coding (rewritten parts of the editor have invariably been smaller) - Inclusion of long winded Panic (before death) messages Edit could also be usefully be made into a known Panos facility, thus moving its error messages into the !Panos file. A brief description of the function of the modules comprising the current Edit implementation : Buffers-def ---------------- Characters-def ---------------- Commands-def ---------------- Deletions-def ---------------- Devices-def ---------------- Display-def ---------------- DisplayPos-def ---------------- Edit-def ---------------- Errors-def ---------------- Fast-def ---------------- Fast32000-def ---------------- HostCode-def ---------------- Installs and starts Edit 6502 hostcode on BBC machine. Interface-def ---------------- Low level interface to BBC/Hostcode functionality (E.g. Keyboard input, VDU output, OSBYTE, ... ). Includes Edit event handler. Owns disaster & escape flags (set by hostcode events). Records key history. List-def ---------------- Memory-def ---------------- Screen-def ---------------- Interface to editor virtual screen. Uses window "depths" & positions, plus current virtual screen contents to decide when to write to physical screen. The editor uses more character definitions than are avaliable, and thus has to define some on-the-fly, on request. These transiently defined characters are represented on the screen by a special character, which is deemed to never match anything written to that position. They are refered to internally as flexible characters. StringData-def ---------------- Universe-def ---------------- VDU-def ---------------- Procedureal interface to the functionality, and idiosycrasies, of the BBC VDU drivers (E.g. Window definition, mode changing, cursor moving, bottom right corner write fix, ...). Version-def ---------------- Windows-def ---------------- actions.Actions-def ---------------- actions.Bindings-def ---------------- actions.Compile-def ---------------- actions.Describe-def ---------------- actions.DoSearch-def ---------------- actions.Execute-def ---------------- actions.FileIO-def ---------------- actions.Help-def ---------------- actions.HelpAction-def ---------------- actions.HelpBuffer-def ---------------- actions.HelpKeys-def ---------------- actions.HelpWindow-def ---------------- actions.HighSearch-def ---------------- actions.InsertDele-def ---------------- actions.Movements-def ---------------- actions.Oblist-def ---------------- actions.Odds-def ---------------- actions.ReadSearch-def ---------------- actions.SearchBase-def ---------------- actions.Searches-def ---------------- actions.Sods-def ---------------- actions.Time-def ----------------