TerminalMultiplex.mesa
Last edited by Levin: August 30, 1982 11:18 am
TerminalMultiplex: DEFINITIONS =
BEGIN

This interface provides a facility for multiplexing virtual terminals on a single physical terminal. The interface is designed for an arbitrary (but fixed) number of virtual terminals and is intended to be used to support debugging of new versions of terminal-handling code. This multiplexing facility has the following primary features:
1) The human user at the keyboard can swap between two particular virtual terminals (the "primary" and the "alternate") by a particular key combination (control-shift-shift). (This is equivalent to an implicit call of SelectTerminal[]; see below.)
2) A client program can select which virtual terminal is to be connected to the physical terminal, and can prevent a change of virtual terminal by clients or the user.
3) Clients may register procedures that the multiplexor will invoke whenever the virtual-to-physical terminal correspondance changes.
TerminalDesired: TYPE = {primary, alternate, special, swap};
Terminal: TYPE = TerminalDesired[primary..special];
SelectTerminal: PROC [terminal: TerminalDesired ← swap, lock: BOOLFALSE]
RETURNS [worked: BOOL];
This procedure causes the indicated virtual terminal to be "connected" to the physical terminal. "swap" means "IF CurrentTerminal[].terminal = primary THEN alternate ELSE primary". If "lock" is TRUE, SelectTerminal executes an implicit PreventSwaps (see below) after connecting the requested virtual terminal to the physical terminal. If the lock count (see PreventSwaps, below) is positive, SelectTerminal has no effect (and "lock" is ignored). In this case, the return value is FALSE; otherwise, it is TRUE.
CurrentTerminal: PROC RETURNS[terminal: Terminal, lockCount: NAT, debuggerLockCount: NAT];
This procedure returns the current terminal state (lockCount is described under PreventSwaps, below). The initial state (i.e., the value returned if CurrentTerminal is the first procedure called in this interface) is terminal: primary, lockCount: 1. Consequently, SelectTerminal is disabled initially (i.e., will return worked: FALSE) and will remain so until PermitSwaps is called (see below). The debuggerLockCount value is discussed under PreventDebuggerSwap, below.
PreventSwaps, PermitSwaps: PROC;
These procedures increment and decrement a "lock count". If the count is positive, SelectTerminal and control-shift-shift are disabled (i.e., have no effect). If PermitSwaps is called when the lock count is zero, it has no effect.
PreventDebuggerSwaps, PermitDebuggerSwaps: PROC;
These procedures increment and decrement a "debugging lock count". If the count is positive, control-swat and control-shift-swat are disabled. If PermitDebuggerSwap is called when the lock count is zero, it has no effect. The lock count is global; all virtual terminals see the same value. Its initial value is 1.
InputAction: TYPE = {enable, disable};
InputController: TYPE = PROC [action: InputAction];
RegisterInputController: PROC [InputController];
The display state of the virtual terminal is held in state variables and multiplexed by the implementation of this interface. However, the keyboard state is maintained by polling the hardware, and confusion will result if more than one virtual terminal is polling the physical hardware at a time. An InputController is a procedure associated with a virtual terminal that is informed when a terminal swap is occurring and can therefore enable or disable the polling activity, as appropriate. When RegisterInputController is called, the argument InputController is registered with the current virtual terminal (only one InputController per virtual terminal is permitted). When the virtual terminal with which the procedure is registered is connected to the physical terminal, the procedure is invoked with parameter InputAction[enable], and this call occurs AFTER the actual terminal swap takes place. Similarly, when the virtual terminal with which the procedure is registered is disconnected from the physical terminal, the procedure is invoked with parameter InputAction[disable], and this call occurs BEFORE the actual terminal swap takes place.
UnregisterInputController: PROC RETURNS [InputController];
The input controller, if any, is disassociated from the present virtual terminal and returned. If none exists, NIL is returned.
SwapAction: TYPE = {coming, going};
TerminalSwapNotifier: TYPE = PROC [action: SwapAction];
RegisterNotifier: PROC [TerminalSwapNotifier];
This procedure registers a client procedure with the current terminal. The registered procedure will be invoked whenever a swap of virtual terminals occurs. When the virtual terminal with which the procedure is registered is connected to the physical terminal, the procedure is invoked with parameter SwapAction[coming], and this call occurs BEFORE the actual terminal swap takes place. Similarly, when the virtual terminal with which the procedure is registered is disconnected from the physical terminal, the procedure is invoked with parameter SwapAction[going], and this call occurs AFTER the actual terminal swap takes place. In both cases, the InputControllers for both virtual terminals are disabled when the TerminalSwapNotifier is invoked. Note: The TerminalSwapNotifiers are invoked in the order of their registration when the parameter is SwapAction[coming] and in the reverse order when the paramter is SwapAction[going].
UnregisterNotifier: PROC [TerminalSwapNotifier];
The specified TerminalSwapNotifier is disassociated from the present virtual terminal. If it is not presently registered, UnregisterNotifier has no effect.
END.