|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T s
Length: 8281 (0x2059)
Types: TextFile
Names: »screenio.mod«
└─⟦060c9c824⟧ Bits:30007080 DKUUG TeX 2/12/89
└─⟦this⟧ »./DVIware/crt-viewers/others/dvitovdu/src/screenio.mod«
└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
└─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z«
└─⟦ca79c7339⟧
└─⟦this⟧ »DVIware/crt-viewers/others/dvitovdu/src/screenio.mod«
IMPLEMENTATION MODULE screenio;
(* Author: Andrew Trevorrow
Implementation: Modula-2 under VAX/UNIX 4.2 BSD
Date Started: June, 1986
Description:
Implements terminal i/o routines used by DVItoVDU. Highly SYSDEP!
*)
(* SYSDEP: we need to write a block of characters (including NULLs) *)
FROM unix IMPORT
write;
(* SYSDEP: C routines written by Alex Dickinson *)
FROM unixio IMPORT
savetty, restoretty,
singlecharon, singlecharoff, echoon, echooff,
buffercount, suspend;
FROM io IMPORT
input, terminal, Readc, Readf, Writec, Writef;
(* WARNING: To handle ^Z suspension properly, screenio needs to use some of
the vduinterface routines. But vduinterface imports screenio, so there
is a circular dependency.
Everything should be ok as long as the vduinterface routines
are only called in the reading routines. DVItoVDU calls
the first ReadString only AFTER calling InitVDUInterface.
*)
FROM vduinterface IMPORT
InitVDUInterface,
StartText, ClearScreen, ResetVDU;
CONST
maxbufsize = 128; (* size of output buffer *)
NULL = 0C; (* SYSDEP: used to terminate a string *)
EOL = 12C; (* SYSDEP: char read upon hitting RETURN *)
LF = 12C;
CR = 15C;
CTRLC = 0C; (* SYSDEP: interrupt, see unixio *)
CTRLZ = 1C; (* SYSDEP: suspend, see unixio *)
(* SYSDEP: unixio puts CTRLC and CTRLZ into input buffer (along with CR)
upon getting a ^C or ^Z interrupt. (It can't put 3C and 32C into buffer
because tty will detect another interrupt and we'll loop forever!)
*)
VAR
buffer : ARRAY [0..maxbufsize-1] OF CHAR; (* output buffer *)
buflen : [0..maxbufsize]; (* number of characters in output buffer *)
(******************************************************************************)
PROCEDURE Read (VAR ch : CHAR);
VAR dummy : INTEGER;
BEGIN
(* SYSDEP: Readc assumes singlecharon has been called *)
IF Readc(input,ch) < 0 THEN
(* DEBUG
Writef(terminal,'Readc failed in Read!\n');
GUBED *)
Abort;
ELSE
(* check for CTRLC or CTRLZ *)
IF ch = CTRLC THEN (* interrupt *)
dummy := Readc(input,ch); (* remove terminator *)
ch := EOL; (* return to Command: level *)
ELSIF ch = CTRLZ THEN (* suspend *)
dummy := Readc(input,ch); (* remove terminator *)
StartText; ClearScreen; WriteLn; ResetVDU;
RestoreTerminal;
suspend;
savetty; singlecharon; echooff;
InitVDUInterface; StartText;
ClearScreen;
ch := EOL; (* return to Command: level *)
ELSE
Writec(terminal,ch); (* echo ch since echooff has been called *)
END;
END;
END Read;
(******************************************************************************)
PROCEDURE ReadString (VAR s : ARRAY OF CHAR);
(* Read a string of characters.
The routine is terminated upon carriage return.
DEL can be used to erase the last character entered.
If s is not full then NULL will terminate the string.
*)
VAR ch : CHAR; i : CARDINAL;
BEGIN
singlecharoff; (* read string in cooked mode *)
echoon; (* echo characters *)
s[0] := NULL; (* we seem to need this in case user just hits return *)
IF Readf(input,'%[^\n]',s) < 0 THEN
(* SYSDEP: ^D will cause end of input file; no more reads are possible! *)
Abort;
ELSIF Readc(input,ch) < 0 THEN
(* we needed Readc to flush newline from input (fflush didn't work) *)
(* DEBUG
Writef(terminal,'Readc failed in ReadString!\n');
GUBED *)
Abort;
END;
i := 0;
LOOP
IF (i > HIGH(s)) OR (s[i] = NULL) THEN EXIT END;
IF s[i] = CTRLC THEN (* interrupt *)
s[0] := NULL; (* simply return an empty string *)
EXIT;
ELSIF s[i] = CTRLZ THEN (* suspend *)
StartText; ClearScreen; WriteLn; ResetVDU;
RestoreTerminal;
suspend;
savetty;
(* singlecharon and echooff are called below *)
InitVDUInterface; StartText;
ClearScreen;
s[0] := NULL; (* return an empty string *)
EXIT;
END;
INC(i);
END;
singlecharon; (* return to cbreak mode *)
echooff; (* and no echo *)
END ReadString;
(******************************************************************************)
PROCEDURE BusyRead (VAR ch : CHAR) : BOOLEAN;
(* Return TRUE if ch is waiting in input buffer, and read it with no echo.
If nothing in input buffer then ch is undefined and we return FALSE.
*)
VAR dummy : INTEGER;
BEGIN
(* SYSDEP: buffercount assumes singlecharon and echooff have been called *)
IF buffercount() = 0 THEN
RETURN FALSE;
ELSE
IF Readc(input,ch) < 0 THEN
Abort;
END;
IF ch = CTRLC THEN (* interrupt *)
dummy := Readc(input,ch); (* read terminator *)
ch := EOL; (* main module will return to Command: level *)
ELSIF ch = CTRLZ THEN (* suspend *)
dummy := Readc(input,ch); (* read terminator *)
StartText; ClearScreen; WriteLn; ResetVDU;
RestoreTerminal;
suspend;
savetty; singlecharon; echooff;
InitVDUInterface; StartText;
ClearScreen;
ch := EOL; (* after suspend, return to Command: level *)
END;
RETURN TRUE;
END;
END BusyRead;
(******************************************************************************)
PROCEDURE Abort;
(* HALT after restoring terminal to a nice clean state. *)
BEGIN
StartText; ClearScreen; WriteLn; ResetVDU;
RestoreTerminal; HALT;
END Abort;
(******************************************************************************)
PROCEDURE Write (ch : CHAR);
(* This is the only place where a character is put into the output buffer.*)
VAR dummy : INTEGER;
BEGIN
IF buflen = maxbufsize THEN
dummy := write(1,buffer,buflen); (* write entire buffer *)
buflen := 0;
END;
buffer[buflen] := ch;
INC(buflen);
END Write;
(******************************************************************************)
PROCEDURE WriteString (s: ARRAY OF CHAR);
VAR i : INTEGER;
BEGIN
(* SYSDEP: we assume end of string is first NULL, or string is full *)
i := 0;
WHILE (i <= HIGH(s)) AND (s[i] <> NULL) DO
Write(s[i]);
INC(i);
END;
END WriteString;
(******************************************************************************)
PROCEDURE WriteInt (i : INTEGER);
(* We call WriteCard after writing any '-' sign. *)
BEGIN
IF i < 0 THEN
Write('-');
i := ABS(i);
END;
WriteCard(CARDINAL(i));
END WriteInt;
(******************************************************************************)
PROCEDURE WriteCard (c : CARDINAL);
(* Since the vast majority of given values will be small numbers, we avoid
recursion until c >= 100.
*)
BEGIN
IF c < 10 THEN
Write( CHR(ORD('0') + c) );
ELSIF c < 100 THEN
Write( CHR(ORD('0') + (c DIV 10)) );
Write( CHR(ORD('0') + (c MOD 10)) );
ELSE
WriteCard(c DIV 100); (* recursive if c >= 100 *)
c := c MOD 100;
Write( CHR(ORD('0') + (c DIV 10)) );
Write( CHR(ORD('0') + (c MOD 10)) );
END;
END WriteCard;
(******************************************************************************)
PROCEDURE WriteLn;
BEGIN
Write(CR);
Write(LF);
WriteBuffer; (* WriteLn also updates terminal *)
END WriteLn;
(******************************************************************************)
PROCEDURE WriteBuffer;
(* Output the buffer; either buffer is full or client has explicitly
requested the terminal to be updated.
*)
VAR dummy : INTEGER;
BEGIN
IF buflen > 0 THEN
dummy := write(1,buffer,buflen);
buflen := 0;
END;
END WriteBuffer;
(******************************************************************************)
PROCEDURE RestoreTerminal;
(* RestoreTerminal should be called before any client module terminates. *)
BEGIN
WriteBuffer; (* make sure terminal is up-to-date *)
restoretty; (* SYSDEP: reset terminal characteristics saved below *)
END RestoreTerminal;
(******************************************************************************)
BEGIN
buflen := 0;
(* SYSDEP: we first save the current terminal characteristics.
savetty also sets up ^C/^Z interrupt handlers; see unixio.c.
*)
savetty;
singlecharon; (* cbreak mode for Read and BusyRead *)
echooff; (* no echo for BusyRead *)
END screenio.