{Begin SubSec Terminal Tables} {Title Terminal Tables} {Text {Tag TerminalTables} {index *PRIMARY* Terminal tables} A read table ({PageRef Term read tables}) contains input/output information that is {it 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 {it 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 lower case 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{index *PRIMARY* Primary terminal table} via {fn SETTERMTABLE}. However, unlike read tables, terminal tables cannot be passed as arguments to input/output functions. {FnDef {FnName GETTERMTABLE} {FnArgs TTBL} {Text If {arg TTBL}={lisp NIL}, returns the primary (i.e., current) terminal table. If {arg TTBL} is a terminal table, return {arg TTBL}. Otherwise, generates an {lisp ILLEGAL TERMINAL TABLE}{index ILLEGAL TERMINAL TABLE Error} error. }} {FnDef {FnName COPYTERMTABLE} {FnArgs TTBL} {Text Returns a copy of {arg TTBL}. {arg TTBL} can be a real terminal table, {lisp NIL} (copies the primary terminal table), or {lisp ORIG} (returns a copy of the {it original} system terminal table). Note that {fn COPYTERMTABLE} is the only function that creates a terminal table. }} {FnDef {FnName SETTERMTABLE} {FnArgs TTBL} {Text Sets the primary terminal table to be {arg TTBL}. Returns the previous primary terminal table. Generates an {lisp ILLEGAL TERMINAL TABLE}{index ILLEGAL TERMINAL TABLE Error} error if {arg TTBL} is not a real terminal table. }} {FnDef {FnName RESETTERMTABLE} {FnArgs TTBL FROM} {Text Copies (smashes) {arg FROM} into {arg TTBL}. {arg FROM} and {arg TTBL} can be {lisp NIL} or a real terminal table. In addition, {arg FROM} can be {lisp ORIG}, meaning to use the system's original terminal table. }} {FnDef {FnName TERMTABLEP} {FnArgs TTBL} {Text Returns {arg TTBL}, if {arg TTBL} is a real terminal table, {lisp NIL} otherwise. }} {Begin SubSec Terminal Syntax Classes} {Title Terminal Syntax Classes} {Text {index *PRIMARY* Terminal syntax classes} A terminal table associates with each character a single "terminal syntax class", one of {lisp CHARDELETE}, {lisp LINEDELETE}, {lisp WORDDELETE}, {lisp RETYPE}, {lisp CTRLV}, {lisp EOL}, and {lisp 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 {lisp NONE}). When a new character is assigned one of these syntax classes by {fn SETSYNTAX} ({PageRef Fn SETSYNTAX}), the previous character is disabled (i.e., reassigned the syntax class {lisp NONE}), and the value of {fn SETSYNTAX} is the code for the previous character of that class, if any, otherwise {lisp NIL}. The terminal syntax classes are interpreted as follows: {Begin LabeledList terminal syntax classes} {Name {lisp CHARDELETE}{index CHARDELETE (syntax class)}} {Text (Initially {index *PRIMARY* Backspace}BackSpace and {index *PRIMARY* Control-A}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. } {Name {lisp LINEDELETE}{index LINEDELETE (syntax class)}} {Text (Initially control-Q{index *PRIMARY* Control-Q} in Interlisp-D) Typing this character deletes the whole line; it cannot be used repeatedly. } {Name {lisp WORDDELETE}{index WORDDELETE (syntax class)}} {Text (Initially control-W in Interlisp-D){index *PRIMARY* Control-W} Typing this character deletes the previous "word", i.e., sequence of non-separator characters. } {Name {lisp RETYPE}{index RETYPE (syntax class)}} {Text (Initially control-R){index *PRIMARY* Control-R} Causes the line to be retyped as Interlisp sees it (useful when repeated deletions make it difficult to see what remains). } {Name {lisp CTRLV}{index CTRLV (syntax class)}} {Name {lisp CNTRLV}{index CNTRLV (syntax class)}} {Text (Initially control-V){index *PRIMARY* Control-V} When followed by {lisp A}, {lisp B}, {ellipsis} {lisp Z}, inputs the corresponding control character control-A, control-B, {ellipsis} control-Z. This allows interrupt characters to be input without causing an interrupt. } {Name {lisp EOL}{index EOL (syntax class)}} {Text On input from a terminal, the {lisp 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 {fn READLINE} ({PageRef Fn READLINE}). In general, whenever the phrase carriage-return linefeed is used, what is meant is the character with terminal syntax class {lisp EOL}. } {Name {lisp NONE}{index NONE (syntax class)}} {Text The terminal syntax class of all other characters. } {End LabeledList terminal syntax classes} {note currently, DELETECHAR and DELETELINE are not accepted by Interlisp-D as valid terminal syntax classes, but CNTRLV is.} {fn GETSYNTAX}, {fn SETSYNTAX}, and {fn SYNTAXP} all work on terminal tables as well as read tables (see {PageRef Fn GETSYNTAX}). As with read tables, full sixteen-bit {index NS Characters}NS characters can be specified in terminal tables (see {PageRef Term NS Characters}). When given {lisp NIL} as a {arg TABLE} argument, {fn GETSYNTAX} and {fn SYNTAXP} use the primary read table{index primary read table} or primary terminal table{index Primary terminal table} depending on which table contains the indicated {arg CLASS} argument. For example, {lisp (SETSYNTAX {arg CH} 'BREAK)} refers to the primary read table, and {lisp (SETSYNTAX {arg 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., {lisp (SETSYNTAX '{lbracket} '%[)} refers to the primary read table. If given incompatible {arg CLASS} and table arguments, all three functions generate errors. For example, {lisp (SETSYNTAX {arg CH} 'BREAK {arg TTBL})}, where {arg TTBL} is a terminal table, generates an {lisp ILLEGAL READTABLE}{index ILLEGAL READTABLE Error} error, and {lisp (GETSYNTAX 'CHARDELETE {arg RDTBL})} generates an {lisp ILLEGAL TERMINAL TABLE}{index ILLEGAL TERMINAL TABLE Error} error. }{End SubSec Terminal Syntax Classes} {Begin SubSec Terminal Control Functions} {Title Terminal Control Functions} {Text {index *PRIMARY* Echoing characters} {index *PRIMARY* Control-character echoing} {index *PRIMARY* Meta-character echoing} {index *PRIMARY* Character echoing} {FnDef {FnName ECHOCHAR} {FnArgs CHARCODE MODE TTBL} {Text {fn ECHOCHAR} sets the "echo mode" of the character {arg CHARCODE} to {arg MODE} in the terminal table {arg 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 {it all} output of the character, both echoing of input and printing of output. {arg CHARCODE} should be a character code. {arg CHARCODE} can also be a list of characters, in which case {fn ECHOCHAR} is applied to each of them with arguments {arg MODE} and {arg TTBL}. Note that echo modes can be specified for full sixteen-bit {index NS Characters}NS characters (see {PageRef Term NS Characters}). {arg MODE} should be one of the litatoms {lisp IGNORE}, {lisp REAL}, {lisp SIMULATE}, or {lisp INDICATE} which specify how the character should be echoed or printed: {Begin LabeledList ECHOCONTROL MODE argument} {Name {lisp IGNORE}} {Text {arg CHARCODE} is never printed.} {Name {lisp REAL}} {Text {arg CHARCODE} itself is printed. Some terminals may respond to certain control and meta characters in interesting ways.} {Name {lisp SIMULATE}} {Text Output of {arg 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.} {Name {lisp INDICATE}} {Text For control or meta characters, {arg CHARCODE} is printed as {lisp #} and/or {lisp ^} followed by the corresponding alphabetic character. For example, control-A would echo as {lisp ^A}, and meta-control-W would echo as {lisp #^W}.} {End LabeledList ECHOCONTROL MODE argument} The value of {fn ECHOCHAR} is the previous echo mode for {arg CHARCODE}. If {arg MODE}={lisp NIL}, {fn 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 {lisp INDICATE} for these characters, they will not print out correctly. }} {FnDef {FnName ECHOCONTROL} {FnArgs CHAR MODE TTBL} {Text {fn ECHOCONTROL} is an old, limited version of {fn ECHOCHAR}, that can only specify the echo mode of control characters. {arg CHAR} is a character or character code. If {arg CHAR} is an alphabetic character (or code), it refers to the corresponding control character, e.g., {lisp (ECHOCONTROL 'Z 'INDICATE)} if equivalent to {lisp (ECHOCHAR (CHARCODE ^Z) 'INDICATE)}. }} {FnDef {FnName ECHOMODE} {FnArgs FLG TTBL} {Text If {arg FLG}={lisp T}, turns echoing for terminal table {arg TTBL} on. If {arg FLG}={lisp NIL}, turns echoing off. Returns the previous setting. Note: Unlike {fn ECHOCHAR}, this only affects echoing of typed-in characters, not printing of characters. }} {FnDef {FnName GETECHOMODE} {FnArgs TTBL} {Text Returns the current echo mode for {arg 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. {index *PRIMARY* Lower case input} {FnDef {FnName RAISE} {FnArgs FLG TTBL} {Text Sets the {fn RAISE} mode for terminal table {arg TTBL}. If {arg FLG}={lisp NIL}, all characters are passed as typed. If {arg FLG}={lisp T}, input is echoed as typed, but lowercase letters are converted to upper case. If {arg FLG}={lisp 0}, input is converted to upper case {it before} it is echoed. Returns the previous setting. }} {FnDef {FnName GETRAISE} {FnArgs TTBL} {Text Returns the current {fn RAISE} mode for {arg TTBL}. }} {FnDef {FnName DELETECONTROL} {FnArgs TYPE MESSAGE TTBL} {Text Specifies the output protocol when a {lisp CHARDELETE}{index CHARDELETE (syntax class)} or {lisp LINEDELETE}{index LINEDELETE (syntax class)} 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 {lisp \} and following the last by a {lisp \}, so that it is easy to see exactly what was deleted. Note: Interlisp-D is initially set up to physically erase the deleted characters from the display, so the {fn DELETECONTROL} strings are initialized to the null string. The various values of {arg TYPE} specify different phases of the deletion, as follows: {Begin LabeledList interpretations of TYPE} {Label {lisp 1STCHDEL}} {Text {arg MESSAGE} is the message printed the first time {lisp CHARDELETE} is typed. Initially "{lisp \}" in Interlisp-10. } {Label {lisp NTHCHDEL}} {Text {arg MESSAGE} is the message printed when the second and subsequent {lisp CHARDELETE} characters are typed (without intervening characters). Initially "" in Interlisp-10. } {Label {lisp POSTCHDEL}} {Text {arg MESSAGE} is the message printed when input is resumed following a sequence of one or more {lisp CHARDELETE} characters. Initially "{lisp \}" in Interlisp-10. } {Label {lisp EMPTYCHDEL}} {Text {arg MESSAGE} is the message printed when a {lisp CHARDELETE} is typed and there are no characters in the buffer. Initially "{lisp ##{CRsymbol}}" in Interlisp-10. } {Label {lisp ECHO}} {Text If {arg TYPE}={lisp ECHO}, the characters deleted by {lisp CHARDELETE} are echoed. {arg MESSAGE} is ignored. } {Label {lisp NOECHO}} {Text If {arg TYPE}={lisp NOECHO}, the characters deleted by {lisp CHARDELETE} are not echoed. {arg MESSAGE} is ignored. } {Label {lisp LINEDELETE}} {Text {arg MESSAGE} is the message printed when the {lisp LINEDELETE} character is typed. Initially "{lisp ##{CRsymbol}}". } {End LabeledList interpretations of TYPE} Note: In Interlisp-10, the {lisp LINEDELETE}, {lisp 1STCHDEL}, {lisp NTHCHDEL}, {lisp POSTCHDEL}, and {lisp EMPTYCHDEL} messages must be 4 characters or fewer in length. {fn DELETECONTROL} returns the previous message as a string. If {arg MESSAGE}={lisp NIL}, the value returned is the previous message without changing it. For {arg TYPE}={lisp ECHO} and {lisp NOECHO}, the value of {fn DELETECONTROL} is the previous echo mode, i.e., {lisp ECHO} or {lisp NOECHO}. {note which is lousy, because it means you can't do (RESETSAVE NIL (LIST 'DELETECONTROL type (DELETECONTROL type newvalue))) without regard to TYPE.} }} {FnDef {FnName GETDELETECONTROL} {FnArgs TYPE TTBL} {Text Returns the current {fn DELETECONTROL} mode for {arg TYPE} in {arg TTBL}. }} }{End SubSec Terminal Control Functions} {Begin SubSec Line-Buffering} {Title Line-Buffering} {Text {index *PRIMARY* Line-buffering} {index *PRIMARY* Line buffer} {index *PRIMARY* System buffer} 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 {lisp EOL} appears (or, for calls from {fn READ}, when the count of unbalanced open parentheses{index Parentheses counting by READ} reaches 0). Note that {fn PEEKC} is an exception; it returns the character immediately when its second argument is {lisp NIL}. Until this time, the user can delete characters one at a time from the line buffer by typing the current {lisp CHARDELETE} character, or delete the entire line buffer back to the last carriage-return by typing the current {lisp LINEDELETE}. Note that this line editing is {it not} performed by {fn READ} or {fn 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{index parentheses counting by READ} is observed. For example, if a program performs {lisp (PROGN (RATOM) (READ))} and the user types in "{lisp 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 {fn RATOM}. If the program had performed {lisp (PROGN (READ) (READ))}, the line-buffering would be under {fn 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, {lisp (LIST (RATOM) (READC) (RATOM))} when the input is "{lisp A B{CRsymbol}}" returns the three-element list {lisp (A % B)} and leaves the carriage-return in the buffer. If a carriage-return is typed when the input under {fn 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 {lisp CHARDELETE} or {lisp LINEDELETE}. The function {fn CONTROL} is available to defeat line-buffering: {FnDef {FnName CONTROL} {FnArgs MODE TTBL} {Text If {arg MODE}={lisp T}, eliminates Interlisp's normal line-buffering for the terminal table {arg TTBL}. If {arg MODE}={lisp NIL}, restores line-buffering (normal). When operating with a terminal table in which {lisp (CONTROL T)} has been performed, characters are returned to the calling function without line-buffering as described below. {fn CONTROL} returns its previous setting. }} {FnDef {FnName GETCONTROL} {FnArgs TTBL} {Text Returns the current control mode for {arg TTBL}. }} The function that initiates the request for input determines how the line is treated when {lisp (CONTROL T)} is in effect: {Begin LabeledList function that initiates the request} {Label {fn READ}{index READ FN}} {Text If the expression being typed is a list, the effect is the same as though done with {lisp (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{index break characters}{index separator characters} is encountered, e.g., {lisp (READ)} when the input is "{lisp ABC}" immediately returns {lisp ABC}. {lisp CHARDELETE} and {lisp LINEDELETE} are available on those characters still in the buffer. Thus, if a program is performing several reads under {lisp (CONTROL T)}, and the user types "{lisp NOW IS THE TIME}" followed by control-Q, only {lisp TIME} is deleted, since the rest of the line has already been transmitted to {fn 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 {lisp (READ)} is "{lisp ABC(}", the {lisp ABC} is not read until a carriage-return or matching parentheses is encountered. In this case the user could {lisp LINEDELETE} the entire line, since all of the characters are still in the buffer. } {Label {fn RATOM}{index RATOM FN}} {Text Characters are returned as soon as a break or separator character is encountered. Until then, {lisp LINEDELETE} and {lisp CHARDELETE} may be used as with {fn READ}. For example, {lisp (RATOM)} followed by "{lisp ABC}" returns {lisp AB}. {lisp (RATOM)} followed by "{lisp (}" returns {lisp (} and types {lisp ##}{index ## (Printed by System)} indicating that control-A was attempted with nothing in the buffer, since the {lisp (} is a break character and would therefore already have been read. } {Label {fn READC}{index READC FN}} {Label {fn PEEKC}{index PEEKC FN}} {Text The character is returned immediately; no line editing is possible. In particular, {lisp (READC)} is perfectly happy to return the {lisp CHARDELETE} or {lisp LINEDELETE} characters, or the {fn ESCAPE} character ({lisp %}){index %}. } {End LabeledList function that initiates the request} The system buffer and line buffer can be directly manipulated using the following functions. {index *PRIMARY* Input buffer} {FnDef {FnName CLEARBUF} {FnArgs FILE FLG} {Text Clears the input buffer for {arg FILE}. If {arg FILE} is {lisp T} and {arg FLG} is {lisp T}, the contents of Interlisp's system buffer{index system buffer} and line buffer{index line buffer} are saved (and can be obtained via {index SYSBUF FN}{fn SYSBUF} and {index LINBUF FN}{fn LINBUF} described below). When {index control-D (Interrupt Character)}control-D or {index control-E (Interrupt Character)}control-E is typed, or any of the interrupt characters that require terminal interaction is typed ({index control-G (Interrupt Character)}control-G, or {index control-P (Interrupt Character)}control-P), Interlisp automatically performs {lisp (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 {lisp (CLEARBUF T)}, i.e., clearing of typeahead, is also available as the {lisp RUBOUT} interrupt character, initially assigned to the delete key{index *PRIMARY* Delete} in Interlisp-D. Note that this interrupt clears both buffers at the time it is {it typed}, whereas the action of the {lisp CHARDELETE} and {lisp LINEDELETE} character occur at the time they are {it read}. }} {FnDef {FnName SYSBUF} {FnArgs FLG} {Text If {arg FLG}={lisp T}, returns the contents of the system buffer{index system buffer} (as a string) that was saved at the last {lisp (CLEARBUF T T)}. If {arg FLG}={lisp NIL}, clears this internal buffer. }} {FnDef {FnName LINBUF} {FnArgs FLG} {Text Same as {fn SYSBUF} for the line buffer{index line buffer}. }} If both the system buffer and Interlisp's line buffer are empty, the internal buffers associated with {fn LINBUF} and {fn SYSBUF} are not changed by a {lisp (CLEARBUF T T)}. {FnDef {FnName BKSYSBUF} {FnArgs X FLG RDTBL} {Text {fn BKSYSBUF} sets the system buffer to the {fn PRIN1}-name of {arg X}. The effect is the same as though the user typed {arg X}. Some implementations have a limit on the length of {arg X}, in which case characters in {arg X} beyond the limit are ignored. Returns {arg X}. If {arg FLG} is {arg T}, then the {fn PRIN2}-name of {arg X} is used, computed with respect to the read table {arg RDTBL}. Note that if the user is typing at the same time as the {fn BKSYSBUF} is being performed, the relative order of the type-in and the characters of {arg X} is unpredictable. Compatibility note: Some implementations of {fn BKSYSBUF} (Interlisp-10) use a "system" buffer, from which keyboard interrupts are also processed. In this case, {fn BKSYSBUF} of an interrupt character actually invokes the interrupt at some (asynchronous) time after the {fn BKSYSBUF} is initiated. In other implementations (Interlisp-D), the characters are not processed for interrupts, and it is possible to {fn BKSYSBUF} characters which would otherwise be impossible to type. }} {FnDef {FnName BKLINBUF} {FnArgs STR} {Text {arg STR} is a string. {fn BKLINBUF} sets Interlisp's line buffer to {arg STR}. Some implementations have a limit on the length of {arg STR}, in which case characters in {arg STR} beyond the limit are ignored. Returns {arg STR}. }} {index BKLINBUF FN}{fn BKLINBUF}, {index BKSYSBUF FN}{fn BKSYSBUF}, {index LINBUF FN}{fn LINBUF}, and {index SYSBUF FN}{fn SYSBUF} provide a way of "undoing" a {index CLEARBUF FN}{fn CLEARBUF}. Thus to "peek" at various characters in the buffer, one could perform {lisp (CLEARBUF T T)}, examine the buffers via {fn LINBUF} and {fn 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 {fn RESETBUFS} provides a convenient way of simply clearing the input buffer, performing an interaction with the user, and then restoring the input buffer. {FnDef {FnName RESETBUFS} {FnArgs FORM{SUB 1} FORM{SUB 2} {ellipsis} FORM{SUB N}} {Type NOSPREAD NLAMBDA} {Text Clears any typeahead (ringing the terminal's bell if there was, indeed, typeahead), evaluates {arg FORM{sub 1}}, {arg FORM{sub 2}},{ellipsis} {arg FORM{sub N}}, then restores the typeahead. Returns the value of {arg FORM{sub N}}. Compiles open. }} }{End SubSec Line-Buffering} }{End SubSec Terminal Tables} ?1(DEFAULTFONT 1 (GACHA 10) (GACHA 8) (TERMINAL 8)) ?1(DEFAULTFONT 1 (GACHA 10) (GACHA 8) (TERMINAL 8)) GACHA †v6Yt7[• zº