packages feed

language-Modula2-0.1: examples/Modula-2_Libraries/andrea-m2/lib/eth-hamburg/getcharac.mod

IMPLEMENTATION MODULE GetCharacter;

(* GET a single character from the terminal ,
   without first setting the proper mode, ordinary non-GET mode is used.

   Use StartGet and StopGet to enter and exit single-character-mode.

   Set character modes on and off with the SET procedures,
   both PASSALL (all control characters passed to GET) and
      NOPASSALL (control characters not trapped) modes are available,

*)
(* bastardization of M. Mall's TTIO from ETH by Jaa, 1985 *)
(* This code may be freely used and distributed, it may not be sold. *)
  
FROM SYSTEM                      IMPORT WORD, ADDRESS, ADR;
FROM VMS                         IMPORT SYS$ASSIGN, SYS$ALLOC, SYS$QIOW;
FROM ConditionHandlingProcedures IMPORT LIB$SIGNAL;
FROM IODefinitions               IMPORT IO$_TTYREADALL, IO$_READVBLK;

CONST
    IO$M_NOFILTR = 200H;
    IO$M_NOECHO  = 40H;
    IO$_WRITEVBLK= 30H;
    IO$_SENSEMODE= 27H;
    IO$M_TYPEAHDCNT=40H;
     
VAR 
    usegetln:    BOOLEAN;   (* read in complete lines        *)
    mustagain:   BOOLEAN;  (* procedure readagain was called*)
    bufferempty: BOOLEAN; 
    lfpending:   BOOLEAN;  (* a line feed must next be output*)
    oldch:       CHAR;	   (* last character read           *)
    buffer:      ARRAY [0..255] OF CHAR; (* holds one line of input *)
    size:        CARDINAL;      (* number of chars in buffer     *)
    pos:         CARDINAL;       (* next char to read from buffer *)
    inChannel,           (* input channel assigned by VMS *)
    outChannel:  CARDINAL;(* output channel assigned by VMS*)
    PhysDevNam:  ARRAY [0..29] OF CHAR; (* physical device name *)
    mode:        CARDINAL;      (* mode bits for input operations*)
    Result:      CARDINAL;    (* status code returned from VMS *)
    iosb:        RECORD c1, c2: CARDINAL END;
                           (* input/output status block     *)
                           (* filled by QIO system service  *)
                  

  (* --------------------------------------------------------------- *)
  PROCEDURE Get(VAR ch: CHAR);

  BEGIN (* Get *)

    IF mustagain THEN
      ch := oldch;
      mustagain := FALSE
    ELSIF bufferempty THEN

      IF usegetln THEN 
        (* note - MODE only as the qualifier on the read *)
        Result := SYS$QIOW(0,inChannel,mode,ADR(iosb),ADDRESS(0),
		           0,ADR(buffer),256,0,0,0,0);
        IF NOT ODD(Result) THEN LIB$SIGNAL(Result) END;
        pos := 1;
        bufferempty := FALSE;
        size := iosb.c1 DIV 10000H + iosb.c2 DIV 10000H - 1;
        ch := buffer[0];
        IF size < pos THEN
          bufferempty := TRUE
        END
      ELSE 
        Result := SYS$QIOW(0,inChannel,mode,ADR(iosb),ADDRESS(0),
		           0,ADR(ch),1,0,0,0,0);
        IF NOT ODD(Result) THEN LIB$SIGNAL(Result) END;
      END
    ELSE
      ch := buffer[pos]; INC(pos);
      IF size < pos THEN
        bufferempty := TRUE;
      END;
    END;

    oldch := ch;
    lfpending := ch = 15C;

  END Get;
 
  (* --------------------------------------------------------------- *)
  PROCEDURE GetNoWait(VAR ch: CHAR);

  VAR
     getln : BOOLEAN;

  BEGIN (* GetNoWait *)

    IF mustagain OR NOT bufferempty THEN
       Get(ch);
    ELSE 
        Result := SYS$QIOW(0,inChannel,
                           IO$M_TYPEAHDCNT+IO$_SENSEMODE,
                           ADDRESS(0),ADDRESS(0),
                           0,ADR(iosb),0,0,0,0,0);
        IF NOT ODD(Result) THEN LIB$SIGNAL(Result) END;
        IF iosb.c1 MOD 10000H > 0 THEN
           (* there is a character in the type ahead buffer *)
           getln := usegetln;
           usegetln := FALSE;
           Get(ch);
           usegetln := getln;
        ELSE
           ch := 0C;
        END;
    END;

  END GetNoWait;
 
  (* --------------------------------------------------------------- *)
  PROCEDURE StartGet;
  (* Turn on single character mode *)
  BEGIN
     SetNoPassallCharacterMode;
  END StartGet;

  (* --------------------------------------------------------------- *)
  PROCEDURE StopGet;
  (* Turn off single character mode *)
  BEGIN
     UnSetNoPassallCharacterMode;
  END StopGet;

  (* --------------------------------------------------------------- *)
  PROCEDURE SetMode(m: CARDINAL; getln: BOOLEAN);
    (* m= modifier bits from VMS *)

  BEGIN (* SetMode *)

    mode := m;
    usegetln := getln;

  END SetMode;

  (* ------------------------------------------------------------ *)
  PROCEDURE SetPassallCharacterMode;

  BEGIN (* SetCharacterMode *)
 
    SetMode(IO$M_NOECHO + IO$_TTYREADALL , FALSE );

  END SetPassallCharacterMode;

  (* ------------------------------------------------------------ *)
  PROCEDURE UnSetPassallCharacterMode;

  BEGIN (* UnSetPassallCharacterMode *)
 
    SetMode( 0 , TRUE );

  END UnSetPassallCharacterMode;

  (* ------------------------------------------------------------ *)
  PROCEDURE SetNoPassallCharacterMode;

  BEGIN (* SetNoPassallCharacterMode *)

    SetMode(IO$M_NOECHO + IO$_READVBLK , FALSE );

  END SetNoPassallCharacterMode;

  (* ------------------------------------------------------------ *)
  PROCEDURE UnSetNoPassallCharacterMode;

  BEGIN (* UnSetNopassallCharacterMode *)

    SetMode( 0 , TRUE );

  END UnSetNoPassallCharacterMode;


BEGIN (* GetCharacter *)

  Result := SYS$ASSIGN("TT",outChannel,0,ADDRESS(0));
  IF NOT ODD(Result) THEN LIB$SIGNAL(Result) END;
  inChannel := outChannel;
  mustagain := FALSE;
  oldch := 0C;
  usegetln := FALSE;
  bufferempty := TRUE;
  lfpending := TRUE;
  SetMode(0,TRUE);

END GetCharacter.