INTERLISP-D REFERENCE MANUAL TERMINAL INPUT/OUTPUT "30"29. TERMINALINPUT/OUTPUT 2 Most input/output operations in Interlisp can be simply modeled as reading or writing on a linear stream of bytes. However, the situation is much more complex when it comes to controlling the user's "terminal," which includes the keyboard, the mouse, and the display screen. For example, Interlisp coordinates the operation of these separate I/O devices so that the cursor on the screen moves as the mouse moves, and any characters typed by the user appear in the window currently containing a flashing cursor. Most of the time, this system works correctly without need for user modification. The purpose of this chapter is to describe how to access the low-level controls for the terminal I/O devices. It documents the use of interrupt characters, the keyboard characters that generate interrupts. Then, it describes terminal tables, used to determine the meaning of the different editing characters (character delete, line delete, etc.). Then, the "dribble file" facility that allows terminal I/O to be saved onto a file is presented (see the Dribble Files section below). Finally, the low-level functions that control the mouse and cursor, the keyboard, and the screen are documented. Interrupt Characters 1 Errors and breaks can be caused by errors within functions, or by explicitly breaking a function. The user can also indicate his desire to go into a break while a program is running by typing certain control characters known as "interrupt characters". The following interrupt characters are currently enabled in Interlisp-D: Note: In Interlisp-D with multiple processes, it is not sufficient to say that "the computation" is broken, aborted, etc; it is necessary to specify which process is being acted upon. Usually, the user wants interrupts to occur in the TTY process, which is the one currently receiving keyboard input. However, sometimes the user wants to interrupt the mouse process, if it is currently busy executing a menu command or waiting for the user to specify a region on the screen. Most of the interrupt characters below take place in the mouse process if it is busy, otherwise the TTY process. Control-G can be used to break arbitrary processes. For more information, see Chapter 23. Control-B Causes a break within the mouse process (if busy) or the TTY process. Use Control-G to break a particular process. Control-D Aborts the mouse process (if busy) or the TTY process, and unwinds its stack to the top level. Calls RESET (see Chapter 14). Control-E Aborts the mouse process (if busy) or the TTY process, and unwinds its stack to the last ERRORSET. Calls ERROR! (see Chapter 14). Control-G Pops up a menu listing all of the currently-running processes. Selecting one of the processes will cause a break to take place in that process. Control-P This interrupt is no longer supported in Medley. Control-T Flashes the TTY process' window and prints status information for the TTY process. First it prints "IO wait," "Waiting", or "Running," depending on whether the TTY process is currently in waiting for characters to be typed, waiting for some other reason, or running. Next, it prints the names of the top three frames on the stack, to show what is running. Then, it prints a line describing the percentage of time (since the last control-T) that has been spent running a program, swapping, garbage collecting, doing local disk I/O, etc. For example: Running in TTWAITFORINPUT in TTBIN in TTYIN1 95% Util, 0% Swap, 4% GC DELETE Clears typeahead in all processes. The user can disable and/or redefine Interlisp interrupt characters, as well as define new interrupt characters. Interlisp-D is initialized with the following interrupt channels: RESET (Control-D), ERROR (Control-E), BREAK (Control-B), HELP (Control-G), PRINTLEVEL (Control-P), RUBOUT (DELETE), and RAID. Each of these channels independently can be disabled, or have a new interrupt character assigned to it via the function INTERRUPTCHAR described below. In addition, the user can enable new interrupt channels, and associate with each channel an interrupt character and an expression to be evaluated when that character is typed. (INTERRUPTCHAR(INTERRUPTCHAR (Function) NIL NIL ("30") 2) CHAR TYP/FORM HARDFLG %) [Function] Defines CHAR as an interrupt character. If CHAR was previously defined as an interrupt character, that interpretation is disabled. CHAR is either a character or a character code (see Chapter 2). Note that full sixteen-bit NS characters can be specified as interrupt characters (see Chapter 2). CHAR can also be a value returned from INTERRUPTCHAR, as described below. If TYP/FORM = NIL, CHAR is disabled. If TYP/FORM = T, the current state of CHAR is returned without changing or disabling it. If TYP/FORM is one of the literal atoms RESET, ERROR, BREAK, HELP, PRINTLEVEL, RUBOUT, or RAID, then INTERRUPTCHAR assigns CHAR to the indicated Interlisp interrupt channel, (reenabling the channel if previously disabled). If the argument TYP/FORM is a symbol designating a predefined system interrupt (RESET, ERROR, BREAK, etc), and HARDFLG is omitted or NIL, then the hardness defaults to the standard hardness of the system interrupt (e.g., MOUSE for the ERROR interrupt). If TYP/FORM is any other literal atom, CHAR is enabled as an interrupt character that when typed causes the atom TYP/FORM to be immediately set to T. If TYP/FORM is a list, CHAR is enabled as a user interrupt character, and TYP/FORM is the form that is evaluated when CHAR is typed. The interrupt will be hard if HARDFLG = T, otherwise soft. (INTERRUPTCHAR T) restores all Interlisp channels to their original state, and disables all user interrupts. HARDFLG determines what process the interrupt should run in. If HARDFLG is NIL, the interrupt will run in the TTY process, which is the process currently receiving keyboard input. If HARDFLG is T, the interrupt will occur in whichever process happens to be running. If HARDFLG is MOUSE, the interrupt will happen in the mouse process, if the mouse is busy, otherwise in the TTY process. INTERRUPTCHAR returns a value which, when given as the CHAR argument to INTERRUPTCHAR, will restore things as they were before the call to INTERRUPTCHAR. Therefore, INTERRUPTCHAR can be used in conjunction with RESETFORM or RESETLST (see Chapter 14). INTERRUPTCHAR is undoable. (RESET.INTERRUPTS(RESET.INTERRUPTS (Function) NIL NIL ("30") 3) PERMITTEDINTERRUPTS SAVECURRENT?) [Function] PERMITTEDINTERRUPTS is a list of interrupt character settings to be performed, each of the form (CHAR TYP/FORM HARDFLG). The effect of RESET.INTERRUPTS is as if (INTERRUPTCHAR CHAR TYP/FORM HARDFLG) were performed for each item on PERMITTEDINTERRUPTS, and (INTERRUPTCHAR OTHERCHAR NIL) were performed on every other existing interrupt character. If SAVECURRENT? is non-NIL, then RESET.INTERRUPTS returns the current state of the interrupts in a form that could be passed to RESET.INTERRUPTS, otherwise it returns NIL. This can be used with a RESET.INTERRUPTS that appears in a RESETFORM, so that the list is built at "entry", but not upon "exit". (LISPINTERRUPTS(LISPINTERRUPTS (Function) NIL NIL ("30") 3)) [Function] Returns the initial default interrupt character settings for Interlisp-D, as a list that RESET.INTERRUPTS would accept. (INTERRUPTABLE(INTERRUPTABLE (Function) NIL NIL ("30") 3) FLAG) [Function] if FLAG = NIL, turns interrupts off. If FLAG = T, turns interrupts on. Value is previous setting. INTERRUPTABLE compiles open. Any interrupt character typed while interrupts are off is treated the same as any other character, i.e., placed in the input buffer, and will not cause an interrupt when interrupts are turned back on. Terminal Tables 1 A read table (see Chapter 25) contains input/output information that is media-independent. For example, the action of parentheses is the same regardless of the device from which the input is being performed. A terminal table is an object that contains information that pertains to terminal input/output operations only, such as the character to type to delete the last character or to delete the last line. In addition, terminal tables contain such information as how line-buffering is to be performed, how control characters are to be echoed/printed, whether lowercase input is to be converted to upper case, etc. Using the functions below, the user may change, reset, or copy terminal tables, or create a new terminal table and install it as the primary terminal table via SETTERMTABLE. However, unlike read tables, terminal tables cannot be passed as arguments to input/output functions. (GETTERMTABLE(GETTERMTABLE (Function) NIL NIL ("30") 4) TTBL) [Function] If TTBL = NIL, returns the primary (i.e., current) terminal table. If TTBL is a terminal table, return TTBL. Otherwise, generates an ILLEGAL TERMINAL TABLE error. (COPYTERMTABLE(COPYTERMTABLE (Function) NIL NIL ("30") 4) TTBL) [Function] Returns a copy of TTBL. TTBL can be a real terminal table, NIL (copies the primary terminal table), or ORIG (returns a copy of the original system terminal table). Note that COPYTERMTABLE is the only function that creates a terminal table. (SETTERMTABLE(SETTERMTABLE (Function) NIL NIL ("30") 4) TTBL) [Function] Sets the primary terminal table to be TTBL. Returns the previous primary terminal table. Generates an ILLEGAL TERMINAL TABLE error if TTBL is not a real terminal table. (RESETTERMTABLE(RESETTERMTABLE (Function) NIL NIL ("30") 4) TTBL FROM) [Function] Copies (smashes) FROM into TTBL. FROM and TTBL can be NIL or a real terminal table. In addition, FROM can be ORIG, meaning to use the system's original terminal table. (TERMTABLEP(TERMTABLEP (Function) NIL NIL ("30") 4) TTBL) [Function] Returns TTBL, if TTBL is a real terminal table, NIL otherwise. Terminal Syntax Classes A terminal table associates with each character a single "terminal syntax class", one of CHARDELETE, LINEDELETE, WORDDELETE, RETYPE, CTRLV, EOL, and NONE. Unlike read table classes, only one character in a particular terminal table can belong to each of the classes (except for the default class NONE). When a new character is assigned one of these syntax classes by SETSYNTAX (see Chapter 25), the previous character is disabled (i.e., reassigned the syntax class NONE), and the value of SETSYNTAX is the code for the previous character of that class, if any, otherwise NIL. The terminal syntax classes are interpreted as follows: CHARDELETE (Initially BackSpace and Control-A in Interlisp-D) Typing this character deletes the previous character typed. Repeated use of this character deletes successive characters back to the beginning of the line. LINEDELETE (Initially Control-Q in Interlisp-D) Typing this character deletes the whole line; it cannot be used repeatedly. WORDDELETE (Initially Control-W in Interlisp-D) Typing this character deletes the previous "word", i.e., sequence of non-separator characters. RETYPE (Initially Control-R) Causes the line to be retyped as Interlisp sees it (useful when repeated deletions make it difficult to see what remains). CTRLV CNTRLV (Initially Control-V) When followed by A, B, ... Z, inputs the corresponding control character control-A, control-B, ... control-Z. This allows interrupt characters to be input without causing an interrupt. EOL On input from a terminal, the EOL character signals to the line buffering routine to pass the input back to the calling function. It also is used to terminate inputs to READLINE (see Chapter 13). In general, whenever the phrase carriage-return linefeed is used, what is meant is the character with terminal syntax class EOL. NONE The terminal syntax class of all other characters. GETSYNTAX, SETSYNTAX, and SYNTAXP all work on terminal tables as well as read tables (see page X.XX). As with read tables, full sixteen-bit NS characters can be specified in terminal tables (see Chapter 2). When given NIL as a TABLE argument, GETSYNTAX and SYNTAXP use the primary read table or primary terminal table depending on which table contains the indicated CLASS argument. For example, (SETSYNTAX CH 'BREAK) refers to the primary read table, and (SETSYNTAX CH 'CHARDELETE) refers to the primary terminal table. In the absence of such information, all three functions default to the primary read table; e.g., (SETSYNTAX '{ '%[) refers to the primary read table. If given incompatible CLASS and table arguments, all three functions generate errors. For example, (SETSYNTAX CH 'BREAK TTBL), where TTBL is a terminal table, generates an ILLEGAL READTABLE error, and (GETSYNTAX 'CHARDELETE RDTBL) generates an ILLEGAL TERMINAL TABLE error. Terminal Control Functions (ECHOCHAR(ECHOCHAR (Function) NIL NIL ("30") 5) CHARCODE MODE TTBL) [Function] ECHOCHAR sets the "echo mode" of the character CHARCODE to MODE in the terminal table TTBL. The "echo mode" determines how the character is to be echoed or printed. Note that although the name of this function suggests echoing only, it affects all output of the character, both echoing of input and printing of output. CHARCODE should be a character code. CHARCODE can also be a list of characters, in which case ECHOCHAR is applied to each of them with arguments MODE and TTBL. Note that echo modes can be specified for full sixteen-bit NS characters (see Chapter 2). MODE should be one of the litatoms IGNORE, REAL, SIMULATE, or INDICATE which specify how the character should be echoed or printed: IGNORE CHARCODE is never printed. REAL CHARCODE itself is printed. Some terminals may respond to certain control and meta characters in interesting ways. SIMULATE Output of CHARCODE is simulated. For example, control-I (tab) may be simulated by printing spaces. The simulation is machine-specific and beyond the control of the user. INDICATE For control or meta characters, CHARCODE is printed as # and/or followed by the corresponding alphabetic character. For example, Control-A would echo as A, and meta-Control-W would echo as #W. The value of ECHOCHAR is the previous echo mode for CHARCODE. If MODE = NIL, ECHOCHAR returns the current echo mode without changing it. Warning: In some fonts, control and meta characters may be used for printable characters. If the echomode is set to INDICATE for these characters, they will not print out correctly. (ECHOCONTROL(ECHOCONTROL (Function) NIL NIL ("30") 6) CHAR MODE TTBL) [Function] ECHOCONTROL is an old, limited version of ECHOCHAR, that can only specify the echo mode of control characters. CHAR is a character or character code. If CHAR is an alphabetic character (or code), it refers to the corresponding control character, e.g., (ECHOCONTROL 'Z 'INDICATE) if equivalent to (ECHOCHAR (CHARCODE Z) 'INDICATE). (ECHOMODE(ECHOMODE (Function) NIL NIL ("30") 6) FLG TTBL) [Function] If FLG = T, turns echoing for terminal table TTBL on. If FLG = NIL, turns echoing off. Returns the previous setting. Note: Unlike ECHOCHAR, this only affects echoing of typed-in characters, not printing of characters. (GETECHOMODE(GETECHOMODE (Function) NIL NIL ("30") 6) TTBL) [Function] Returns the current echo mode for TTBL. The following functions manipulate the "raise mode," which determines whether lower case characters are converted to upper case when input from the terminal. There is no "raise mode" for input from files. (RAISE(RAISE (Function) NIL NIL ("30") 6) FLG TTBL) [Function] Sets the RAISE mode for terminal table TTBL. If FLG = NIL, all characters are passed as typed. If FLG = T, input is echoed as typed, but lowercase letters are converted to upper case. If FLG = 0, input is converted to uppercase before it is echoed. Returns the previous setting. (GETRAISE(GETRAISE (Function) NIL NIL ("30") 6) TTBL) [Function] Returns the current RAISE mode for TTBL. (DELETECONTROL(DELETECONTROL (Function) NIL NIL ("30") 6) TYPE MESSAGE TTBL) [Function] Specifies the output protocol when a CHARDELETE or LINEDELETE is typed, by specifying character strings to print when characters are deleted. Interlisp-10 (designed for use on hardcopy terminals) echos the characters being deleted, preceding the first by a \ and following the last by a \, so that it is easy to see exactly what was deleted. Interlisp-D is initially set up to physically erase the deleted characters from the display, so the DELETECONTROL strings are initialized to the null string. The various values of TYPE specify different phases of the deletion, as follows: 1STCHDEL MESSAGE is the message printed the first time CHARDELETE is typed. Initially "\" in Interlisp-10. NTHCHDEL MESSAGE is the message printed when the second and subsequent CHARDELETE characters are typed (without intervening characters). Initially "" in Interlisp-10. POSTCHDEL MESSAGE is the message printed when input is resumed following a sequence of one or more CHARDELETE characters. Initially "\" in Interlisp-10. EMPTYCHDEL MESSAGE is the message printed when a CHARDELETE is typed and there are no characters in the buffer. Initially "##cr" in Interlisp-10. ECHO If TYPE = ECHO, the characters deleted by CHARDELETE are echoed. MESSAGE is ignored. NOECHO If TYPE = NOECHO, the characters deleted by CHARDELETE are not echoed. MESSAGE is ignored. LINEDELETE MESSAGE is the message printed when the LINEDELETE character is typed. Initially "##cr". Note: In Interlisp-10, the LINEDELETE, 1STCHDEL, NTHCHDEL, POSTCHDEL, and EMPTYCHDEL messages must be 4 characters or fewer in length. DELETECONTROL returns the previous message as a string. If MESSAGE = NIL, the value returned is the previous message without changing it. For TYPE = ECHO and NOECHO, the value of DELETECONTROL is the previous echo mode, i.e., ECHO or NOECHO. (GETDELETECONTROL(GETDELETECONTROL (Function) NIL NIL ("30") 7) TYPE TTBL) [Function] Returns the current DELETECONTROL mode for TYPE in TTBL. Line-Buffering Characters typed at the terminal are stored in two buffers before they are passed to an input function. All characters typed in are put into the low-level "system buffer", which allows type-ahead. When an input function is entered, characters are transferred to the "line buffer" until a character with terminal syntax class EOL appears (or, for calls from READ, when the count of unbalanced open parentheses reaches 0). Note that PEEKC is an exception; it returns the character immediately when its second argument is NIL. Until this time, the user can delete characters one at a time from the line buffer by typing the current CHARDELETE character, or delete the entire line buffer back to the last carriage-return by typing the current LINEDELETE. This line editing is not performed by READ or RATOM, but by Interlisp, i.e., it does not matter (nor is it necessarily known) which function will ultimately process the characters, only that they are still in the Interlisp line buffer. However, the function that is requesting input at the time the buffering starts does determine whether parentheses counting is observed. For example, if a program performs (PROGN (RATOM) (READ)) and the user types in "A (B C D)", the user must type in the carriage-return following the right parenthesis before any action is taken, because the line buffering is happening under RATOM. If the program had performed (PROGN (READ) (READ)), the line-buffering would be under READ, so that the right parenthesis would terminate line buffering, and no terminating carriage-return would be required. Once a carriage-return has been typed, the entire line is "available" even if not all of it is processed by the function initiating the request for input. If any characters are "left over", they are returned immediately on the next request for input. For example, (LIST (RATOM) (READC) (RATOM)) when the input is "A Bcr" returns the three-element list (A % B) and leaves the carriage-return in the buffer. If a carriage-return is typed when the input under READ is not "complete" (the parentheses are not balanced or a string is in progress), line buffering continues, but the lines completed so far are not available for editing with CHARDELETE or LINEDELETE. The function CONTROL is available to defeat line-buffering: (CONTROL(CONTROL (Function) NIL NIL ("30") 8) MODE TTBL) [Function] If MODE = T, eliminates Interlisp's normal line-buffering for the terminal table TTBL. If MODE = NIL, restores line-buffering (normal). When operating with a terminal table in which (CONTROL T) has been performed, characters are returned to the calling function without line-buffering as described below. CONTROL returns its previous setting. (GETCONTROL(GETCONTROL (Function) NIL NIL ("30") 8) TTBL) [Function] Returns the current control mode for TTBL. The function that initiates the request for input determines how the line is treated when (CONTROL T) is in effect: READ If the expression being typed is a list, the effect is the same as though done with (CONTROL NIL), i.e., line-buffering continues until a carriage-return or matching parentheses. If the expression being typed is not a list, it is returned as soon as a break or separator character is encountered, e.g., (READ) when the input is "ABC" immediately returns ABC. CHARDELETE and LINEDELETE are available on those characters still in the buffer. Thus, if a program is performing several reads under (CONTROL T), and the user types "NOW IS THE TIME" followed by Control-Q, only TIME is deleted, since the rest of the line has already been transmitted to READ and processed. An exception to the above occurs when the break or separator character is an opening parenthesis, bracket or double-quote, since returning at this point would leave the line buffer in a "funny" state. Thus if the input to (READ) is "ABC(", the ABC is not read until a carriage-return or matching parentheses is encountered. In this case the user could LINEDELETE the entire line, since all of the characters are still in the buffer. RATOM Characters are returned as soon as a break or separator character is encountered. Until then, LINEDELETE and CHARDELETE may be used as with READ. For example, (RATOM) followed by "ABC" returns AB. (RATOM) followed by "(" returns ( and types ## indicating that control-A was attempted with nothing in the buffer, since the ( is a break character and would therefore already have been read. READC PEEKC The character is returned immediately; no line editing is possible. In particular, (READC) is perfectly happy to return the CHARDELETE or LINEDELETE characters, or the ESCAPE character (%). The system buffer and line buffer can be directly manipulated using the following functions. (CLEARBUF(CLEARBUF (Function) NIL NIL ("30") 9) FILE FLG) [Function] Clears the input buffer for FILE. If FILE is T and FLG is T, the contents of Interlisp's system buffer and line buffer are saved (and can be obtained via SYSBUF and LINBUF described below). When you type Control-D or Control-E, or any of the interrupt characters that require terminal interaction (Control-G, or Control-P), Interlisp automatically performs (CLEARBUF T T). For Control-P and, when the break is exited normally, control-H, Interlisp restores the buffer after the interaction. The action of (CLEARBUF T), i.e., clearing of typeahead, is also available as the RUBOUT interrupt character, initially assigned to the delete key in Interlisp-D. Note that this interrupt clears both buffers at the time it is typed, whereas the action of the CHARDELETE and LINEDELETE character occur at the time they are read. (SYSBUF(SYSBUF (Function) NIL NIL ("30") 9) FLG) [Function] If FLG = T, returns the contents of the system buffer (as a string) that was saved at the last (CLEARBUF T T). If FLG = NIL, clears this internal buffer. (LINBUF(LINBUF (Function) NIL NIL ("30") 9) FLG) [Function] Same as SYSBUF for the line buffer. If both the system buffer and Interlisp's line buffer are empty, the internal buffers associated with LINBUF and SYSBUF are not changed by a (CLEARBUF T T). (BKSYSBUF(BKSYSBUF (Function) NIL NIL ("30") 9) X FLG RDTBL) [Function] BKSYSBUF appends the PRIN1-name of X to the system buffer. The effect is the same as though the user typed X. Some implementations have a limit on the length of X, in which case characters in X beyond the limit are ignored. Returns X. If FLG is T, then the PRIN2(PRIN2 NIL NIL NIL (4) NIL)-name of X is used, computed with respect to the readtable RDTBL. If RDTBL is NIL or omitted, the current readtable of the TTY process (which is to receive the characters) is used. Use this for copy selection functions that want their output to be a readable expression in an Exec. Note that if you are typing at the same time as the BKSYSBUF is being performed, the relative order of the typein and the characters of X is unpredictable. (BKLINBUF(BKLINBUF (Function) NIL NIL ("30") 9) STR) [Function] STR is a string. BKLINBUF sets Interlisp's line buffer to STR. Some implementations have a limit on the length of STR, in which case characters in STR beyond the limit are ignored. Returns STR. ((BKSYSCHARCODE (Function) NIL NIL (4) NIL)BKSYSCHARCODE CODE) [Function] This function appends the character code CODE to the system input buffer. The function BKSYSBUF(BKSYSBUF (Function) NIL NIL (4) NIL) is implemented by repeated calls to BKSYSCHARCODE. BKLINBUF, BKSYSBUF, LINBUF, and SYSBUF provide a way of "undoing" a CLEARBUF. Thus to "peek" at various characters in the buffer, one could perform (CLEARBUF T T), examine the buffers via LINBUF and SYSBUF, and then put them back. The more common use of these functions is in saving and restoring typeahead when a program requires some unanticipated (from the user's standpoint) input. The function RESETBUFS provides a convenient way of simply clearing the input buffer, performing an interaction with the user, and then restoring the input buffer. (RESETBUFS(RESETBUFS (Function) NIL NIL ("30") 10) FORM1, FORM2,... FORMN) [NLambda NoSpread Function] Clears any typeahead (ringing the terminal's bell if there was, indeed, typeahead), evaluates FORM1, FORM2,... FORMN, then restores the typeahead. Returns the value of FORMN. Compiles open. Dribble Files 1 A dribble file is a "transcript" of all of the input and output on a terminal. In Interlisp-D, DRIBBLE opens a dribble file for the current process, recording the terminal input and output for that process. Multiple processes can have separate dribble files open at the same time. (DRIBBLE(DRIBBLE (Function) NIL NIL ("30") 10) FILE APPENDFLG THAWEDFLG) [Function] Opens FILE and begins recording the typescript. Returns the old dribble file if any, otherwise NIL. If APPENDFLG = T, the typescript will be appended to the end of FILE. If THAWEDFLG = T, the file will be opened in "thawed" mode, for those implementations that support it. (DRIBBLE) closes the dribble file for the current process. Only one dribble file can be active for each process at any one time, so (DRIBBLE FILE1) followed by (DRIBBLE FILE2) will cause FILE1 to be closed. (DRIBBLEFILE(DRIBBLEFILE (Function) NIL NIL ("30") 10)) [Function] Returns the name of the current dribble file for the current process, if any, otherwise NIL. Terminal input is echoed to the dribble file a line buffer at a time. Thus, the typescript produced is somewhat neater than that appearing on the user's terminal, because it does not show characters that were erased via Control-A or Control-Q. Note that the typescript file is not included in the list of files returned by (OPENP), nor will it be closed by a call to CLOSEALL or CLOSEF. Only (DRIBBLE) closes the typescript file. Cursor and Mouse 1 A mouse is a small box connected to the computer keyboard by a long wire. On the top of the mouse are two or three buttons. On the bottom is a rolling ball or a set of photoreceptors, to detect when the mouse is moved. As the mouse is moved on a surface, a small image on the screen, called the cursor, moves to follow the movement of the mouse. By moving the mouse, the user can cause the cursor to point to any part of the display screen. The mouse and cursor are an important part of the Interlisp-D user interface. The Interlisp-D window system allows the user to create, move, and reshape windows, and to select items from displayed menus, all by moving the mouse and clicking the mouse buttons. This section describes the low-level functions used to control the mouse and cursor. Changing the Cursor Image Interlisp-D maintains the image of the cursor on the screen, moving it as the mouse is moved. The bitmap that becomes visible as the cursor can be accessed by the following function: (CURSORBITMAP(CURSORBITMAP (Function) NIL NIL ("30") 11)) [Function] Returns the cursor bitmap. CURSORWIDTH(CURSORWIDTH (Variable) NIL NIL ("30") 11) [Variable] CURSORHEIGHT(CURSORHEIGHT (Variable) NIL NIL ("30") 11) [Variable] Value is the width and height of the cursor bitmap, respectively. The cursor bitmap can be changed like any other bitmap by BITBLTing into it or pointing a display stream at it and printing or drawing curves. The CURSOR(CURSOR NIL NIL NIL (4) NIL) datatype has the following field names CUBITSPERPIXEL CUIMAGE(CUIMAGE NIL NIL NIL (4) NIL), CUMASK, CUHOTSPOTX(CUHOTSPOTX NIL NIL NIL (4) NIL), CUHOTSPOTY(CUHOTSPOTY NIL NIL NIL (4) NIL), CUDATA CURSOR objects can be saved on a file using the file package command CURSORS, or the UGLYVARS file package command. (CURSORCREATE(CURSORCREATE (Function) NIL NIL ("30") 11) BITMAP X Y) [Function] Returns a cursor object which has BITMAP as its image and the location (X,Y) as the hot spot. If X is a POSITION, it is used as the hot spot. If BITMAP has dimensions different from CURSORWIDTH by CURSORHEIGHT, the lesser of the widths and the lesser of the heights are used to determine the bits that actually get copied into the lower left corner of the cursor. If X is NIL, 0 is used. If Y is NIL, CURSORHEIGHT-1 is used. The default cursor is an uparrow with its tip in the upper left corner and its hot spot at (0,CURSORHEIGHT-1). (CURSOR(CURSOR (Function) NIL NIL ("30") 11) NEWCURSOR %) [Function] Returns a CURSOR record instance that contains (a copy of) the current cursor specification. If NEWCURSOR is a CURSOR record instance, the cursor will be set to the values in NEWCURSOR. If NEWCURSOR is T, the cursor will be set to the default cursor DEFAULTCURSOR, an upward left pointing arrow:  . (SETCURSOR(SETCURSOR (Function) NIL NIL ("30") 11) NEWCURSOR %) [Function] If NEWCURSOR is a CURSOR record instance, the cursor will be set to the values in NEWCURSOR. This does not return the old cursor, and therefore, provides a way of changing the cursor without using storage. (FLIPCURSOR(FLIPCURSOR (Function) NIL NIL ("30") 11)) [Function] Inverts the cursor. The following list describes the cursors used by the Interlisp-D system. Most of them are stored as the values of various variables.   In variable DEFAULTCURSOR. This is the default cursor. `=x `07g In variable WAITINGCURSOR. Represents an hourglass. Used during long computations.  ((((((( In variable MOUSECONFIRMCURSOR. Indicates that the system is waiting for the user to confirm an action by pressing the left mouse button, or aborting the action by pressing any other button. Used by the function MOUSECONFIRM (see Chapter 28). ta$b2\JHJHJHJH1 In variable SYSOUTCURSOR. Indicates that the system is saving the virtual memory in a sysout file. See SYSOUT, Chapter 12.  dʠ.@@ N R P \ In variable SAVINGCURSOR. Indicates that SAVEVM has been called automatically to save the virtual memory state after the system is idle for long enough. See SAVEVMWAIT, Chapter 12. p1a AAa 1p In variable CROSSHAIRS. Used by GETPOSITION (see Chapter 28) to indicate a position.  00000000 In variable BOXCURSOR. Used by GETBOXPOSITION (see Chapter 28) to indicate where to place the corner of a box.  9)@9p`` In variable FORCEPS. Used by GETREGION (see Chapter 28) when the user switches corners. $$  In variable EXPANDINGBOX. Used by GETREGION (see Chapter 28) when a box is first displayed.  @ In variable UpperRightCursor.   ```````` In variable LowerRightCursor.   In variable UpperLeftCursor.   In variable LowerLeftCursor. The previous four cursors are used by GETREGION (see Chapter 28) to indicate the four corners of a region.   In variable VertThumbCursor. Used during scrolling to indicate thumbing in a vertical scroll bar. 88||8888||88 In variable VertScrollCursor.  >> In variable ScrollUpCursor.  >> In variable ScrollDownCursor. The previous four cursors are used by SCROLL.HANDLER (see Chapter 28) during vertical scrolling.   *** In variable HorizThumbCursor. Used during scrolling to indicate thumbing in a horizontal scroll bar.   088xy  f':I"     &IM.INDEX.GETFNTITAN    ' 1+] >    l     !    4 v :  )IM.INDEX.GETFNTITAN    >'_ "   &IM.INDEX.GETFNTITAN    #  4  P  )IM.INDEX.GETFNTITAN   "  #IM.INDEX.GETFNTITAN     * S V  &IM.INDEX.GETFNTITAN      +IM.INDEX.GETFNTITAN    %  Q - - 7  ' +  7 W  R -   C            ! #      3 / G   "    .IM.INDEX.GETFNTITAN      G  G S l d &  g    $ v  q3     (  %IM.INDEX.GETFNTITAN     F S p    (IM.INDEX.GETFNTITAN    % Z   U  4   o   H 1} G _      T"   ]  &IM.INDEX.GETFNTITAN   _ y  8  ,  $IM.INDEX.GETFNTITAN   U  $IM.INDEX.GETFNTITAN   f  &IM.INDEX.GETFNTITAN     I6(  IM.INDEX.GETFNPALATINO 1* 4L  &IM.INDEX.GETFNTITAN     !6( *IM.INDEX.GETFNMODERN    )* %IM.INDEX.GETFNPALATINO %       I      (IM.INDEX.GETFNTITAN    ^5 HRULE.GETFNMODERN `   &IM.INDEX.GETFNMODERN   V   0  X |     *IM.INDEX.GETFNTITAN   X E %    HRULE.GETFNMODERN [   +IM.INDEX.GETFNTITAN    *IM.INDEX.GETFNMODERN  +IM.INDEX.GETFNMODERN  B: S IM.INDEX.GETFNPALATINO '  IM.INDEX.GETFN IM.INDEX.GETFN IM.INDEX.GETFNMODERN   ?    +IM.INDEX.GETFNTITAN    "  "     h   %IM.INDEX.GETFNCLASSIC     Q  :   / !, BMOBJ.GETFN3  (IM.INDEX.GETFNMODERN       : t  )IM.INDEX.GETFNTITAN    , BMOBJ.GETFN3  , BMOBJ.GETFN3  <, BMOBJ.GETFN3   ( BMOBJ.GETFN3  Q & BMOBJ.GETFN3   o * BMOBJ.GETFN3   *$ BMOBJ.GETFN3   B, BMOBJ.GETFN3   2( BMOBJ.GETFN3   1" BMOBJ.GETFN3  " BMOBJ.GETFN3  " BMOBJ.GETFN3  " BMOBJ.GETFN3   & <& BMOBJ.GETFN3  H, BMOBJ.GETFN3  , BMOBJ.GETFN3  , BMOBJ.GETFN3   & -& BMOBJ.GETFN3  J& BMOBJ.GETFN3  & BMOBJ.GETFN3  & BMOBJ.GETFN3   & /* BMOBJ.GETFN3 BMOBJ.GETFN3 BMOBJ.GETFN3 BMOBJ.GETFN3 BMOBJ.GETFN3 BMOBJ.GETFN3( BMOBJ.GETFN3 , BMOBJ.GETFN3~ , BMOBJ.GETFN3, BMOBJ.GETFN3, BMOBJ.GETFN3y # , BMOBJ.GETFN3{ m  -IM.INDEX.GETFNMODERN %  ? $    ?   + |   u # , U    3IM.INDEX.GETFNMODERN       o   M  &IM.INDEX.GETFNTITAN    2   "    (    #  1 ># X  *IM.INDEX.GETFNTITAN      b   +IM.INDEX.GETFNTITAN      *   .  I D  0 j  )IM.INDEX.GETFNTITAN    "     )IM.INDEX.GETFNTITAN    "    )IM.INDEX.GETFNTITAN   O   )IM.INDEX.GETFNTITAN   O   /IM.INDEX.GETFNTITAN  n ] +IM.INDEX.GETFNTITAN  _   ,IM.INDEX.GETFNTITAN   <    ,IM.INDEX.GETFNTITAN    ?  &> HRULE.GETFNMODERN   'IM.INDEX.GETFNMODERN    s 1 B               }             D      k       )IM.INDEX.GETFNCLASSIC     +        f   /        (IM.INDEX.GETFNCLASSIC  "    I  ` 2  v  1   b      # 6    Y     C  j .   3 Q. . - ,   , C  "   <  0IM.INDEX.GETFNMODERN    6   !     (    =  (IM.INDEX.GETFNMODERN     $  K     7 $ . HRULE.GETFNMODERN >  +IM.INDEX.GETFNTITAN    *IM.INDEX.GETFNTITAN  +IM.INDEX.GETFNTITAN  B +IM.INDEX.GETFNTITAN  8  /IM.INDEX.GETFNTITAN    4/B H 1 3 4IM.INDEX.GETFNTITAN  7  )IM.INDEX.GETFNMODERN    > U # <B  (IM.INDEX.GETFNMODERN    1    " A  /IM.INDEX.GETFNMODERN    &   M  *IM.INDEX.GETFNMODERN    , *7 ! HRULE.GETFNMODERN   (IM.INDEX.GETFNMODERN    $V  'IM.INDEX.GETFNMODERN     :# z c G M        %IM.INDEX.GETFNMODERN    OX   &IM.INDEX.GETFNTITAN   2  ,IM.INDEX.GETFNMODERN    { Ҽ z