Forth Stand-Alone Window System This window system is for ascii terminals. All coordinates are in terms of character positions. The entire screen is the coordinate space ( 0..(#columns-1 , 0..(#lines-1 ). For example, a common size for a terminal is 24 lines by 80 characters, in which case #columns is 80 and #lines is 24. A window is a rectangular region of the terminal screen. A window is described by the following data structure: struct ( window ) int line0 int col0 int #lines int #cols int w#line int w#out constant /window MY-WINDOW -- addr The address of a USER (task-local) variable which contains the address of the window data structure to which the task is currently sending output. All that a task need do to switch to a different window is to store a new value in this variable. The "current window" is the one whose address is contained in MY-WINDOW. The names LINE0 COL0 #LINES #COLS #LINE #OUT all reference the window data structure whose address is in MY-WINDOW . LINE0 -- addr The address of a variable containing the number of the line on the screen where the current window starts. {0..(#lines-1} COL0 -- addr The address of a variable containing the number of the column on the screen where the left-hand side of the current window is. {0..#columns-1} #LINES -- addr The address of a variable containing the number of lines in the current window. #COLS -- addr The address of a variable containing the number of columns in the current window. W#LINE -- addr The address of a variable containing the row number within the current window where the cursor is presently located. {0..#rows-1} W#LINE should be installed as the action performed bye the DEFER word #LINE , so that existing programs which keep track of the cursor position will continue to work. See INSTALL-WINDOWS W#OUT -- addr The address of a variable containing the column number within the current window where the cursor is presently located. {0..#cols-1} W#OUT should be installed as the action performed bye the DEFER word #OUT , so that existing programs which keep track of the cursor position will continue to work. See INSTALL-WINDOWS WINDOW: line0 col0 #lines #cols -- A defining word executed in the form: line0 col0 #lines #cols WINDOW: to create a new named window whose upper left-hand corner will be at (line,col) and whose size will be #lines by #cols. Later execution of leaves the address of the window data structure for this window on the stack. INPUT-WINDOW -- addr The address of a global variable which contains the address of the window data structure for the window which is to receive keyboard input. Only a task whose MY-WINDOW variable contains the same value as the global INPUT-WINDOW variable can receive characters typed at the keyboard. Any other task which calls KEY will be blocked until INPUT-WINDOW is changed to be the same as that task's MY-WINDOW variable. AT line column -- Move the cursor to line,column within the current window. For instance, if line,column is 5,10, and line0,col0 for the current window is 15,12 , then the cursor will be moved to absolute screen location 20,22 . 0 <= line < #lines , 0 <= column < #cols SELECT-WINDOW window -- Window is the address of a window data structure. The cursor is moved into that window to the last position that the cursor occupied within that window (#line,#out). KILL-LINE -- The current line (#line) within the current window is cleared from the cursor position (#out) to the right side of the window. ERASE-SCREEN -- The current window is erased and the cursor is moved to the upper left-hand corner (0,0). RIGHT -- The cursor is moved one position to the right within the current window. The movement is non-destructive, so that no characters are erased. LEFT -- The cursor is moved one position to the left within the current window. The movement is non-destructive, so that no characters are erased. DELETE-CHAR -- The character at the cursor position within the current window is deleted from the screen, and any characters to the right of the cursor position within the current window are moved over to fill in the vacated position. INSERT-CHAR char -- char is inserted into the current window at the cursor position, and and any characters to the right of the cursor position within the current window are moved over to make room. The character at the righmost end of the line drops off the edge of the window and is lost. SCROLL -- Used to advance the cursor to the next line when it is already at the bottom of the window. If the bottom of the window is at the bottom of the screen, and it is the full width of the screen, a true scroll is performed, i.e. the contents of the window move up and the cursor stays on the bottom line. If the window is either narrower than the screen or not at the bottom, the cursor wraps, i.e. it moves to the top of the window and the line at the top is cleared. The reason for this is practical; it is easy to scroll a full width window by doing a "delete-line" operation on the top line of the window, followed by an "insert-line" at the bottom of the window. If the window is narrower than the screen, this doesn't work. Even if the window is full width, if it is not at the bottom of the screen, the "delete/insert" scrolling method looks ugly because the rest of the screen "jumps" in the middle of the insert/delete sequence. Simulating true scrolling in software would require keeping an image of the current contents of every window, which is painful. Also, redisplaying the window during scrolling would be pretty slow over a serial line. +CHARS n -- Advances the cursor n positions to the right (n positive), or -n positions to the left (n negative). This is generally faster than executing RIGHT or LEFT n times. WEMIT char -- Display the character in the current window at the cursor position. In all cases, the #out and #line variables are updated to reflect the new position of the cursor. Various characters are displayed as follows: Printing characters Display in the usual fashion. If the cursor is already at the right-hand side of the screen, a is done before displaying the character. Moves the cursor to the left-hand side of the next line. Clears that line. If the cursor is already at the bottom line in the window, the window scrolls. See SCROLL . Moves the cursor to the left-hand side of the current line. Moves the cursor backwards to the previous position on the current line, unless it is already at the left-hand side. Moves the cursor forward on the current line to the next position which is a multiple of the value contained in the variable TAB-STOP Rings the bell on the terminal, or invokes whatever attention-getting mechanism the terminal has in place of a bell. Performs the equivalent of ERASE-SCREEN . MODE-LINE str -- str is the address of a packed string which is displayed just below the bottom line in the current window. If possible, the string is displayed in a reverse-video stripe which is the width of the window. BORDER -- A border is drawn around the window, in the lines and columns just outside the window. If a side of the border would be outside the extent of the screen, for instance if the window extends to an edge of the screen, that side of the border is not drawn. CONSOLE -- window Window is the address of window data structure for the window that is always present in the system. CONSOLE MY-WINDOW ! will select this window. The console window is usually placed so that it either covers the whole screen or is at the bottom of the screen and full screen width wide. INSTALL-WINDOWS -- Arranges the world so that existing Forth programs will behave properly within a window. This involves installing the actions WEMIT , W#OUT , and W#LINE into the DEFER words EMIT , #OUT , and #LINE . Window Input With the window package, several tasks can share access to one keyboard without stealing characters from one another. At any given time, only one task has control of the keyboard. When the user types ^X (control X), control of the keyboard is passed to another task that is waiting for input. Repeated ^X's will cycle through all the tasks that are waiting for input. As a special kludge, there is a distinguished task called MAIN-TASK which is assumed to be always requesting input. When a return is typed to any task other than the main one, control of the keyboard is given back to the main task. This prevents the situation where the user selects a task with ^X, types a command, and then loses control of the keyboard because the task did not request any more input. There really should be a separate task that handles the keyboard. MAIN-TASK -- addr addr is the task address of the distinguished task that is assumed to be in primary control of the system. That task is the one which is is in control when the Forth system is first started, before multitasking is initiated. INPUT-TASK -- addr addr is the address of a variable containing the task address of the task which is currently receiving keyboard input. TO-NEXT-INPUT -- Finds and gives control of the keyboard to the next task which is waiting for input. If no other task is waiting for input, keyboard control remains with the current task. (Invoked by typing ^X). TKEY -- char A replacement for the system KEY routine which implements the ^X processing for multiplexing the keyboard between tasks. TKEY may be installed with ' TKEY IS KEY The installation must be done for every task that will expect input. If the installation is done in the main task before the other tasks are forked, the other tasks will automatically inherit the TKEY replacement for KEY .