|
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.