DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T s

⟦2854e8373⟧ TextFile

    Length: 8281 (0x2059)
    Types: TextFile
    Names: »screenio.mod«

Derivation

└─⟦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« 

TextFile

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.