! EDWIN Utility procedures for OPUS UNIX.
! Mostly IAY's work, with some JGH stuff added to the end.

%from Imp %include Lognames, Sys Specs, sgtty
          %include Device

%record %format Dev Fm ( %integer Channel,
                         %record(SG TTY B) Org Parm, Cur Parm,
                         %string(255) Device )

%own %record(Dev Fm) %name Device == 0

%routine Set Parm ( %record(Dev Fm) %name D, %integer Parm, OnOff )
   %integer Cur = D_Cur Parm_Flags & Parm
   %if OnOff = 0 {turn off} %start
      %return %if Cur = 0
      D_Cur Parm_Flags = D_Cur Parm_Flags&(\Parm)
   %else
      %return %if Cur # 0
      D_Cur Parm_Flags = D_Cur Parm_Flags ! Parm
   %finish
   Cur = Stty(D_Channel, D_Cur Parm)
%end

%own %string(255) Buffer = ""

%external %routine TT Mode %alias "EDWIN_TTMODE" ( %integer M )
   %integer Status
   %if M = 0 {returning to normal} %start
      %if Device ## Nil %and Device_Channel >= 0 %start
         %if Device_Cur Parm_Flags # Device_Org Parm_Flags %start
            Status = Stty(Device_Channel, Device_Org Parm)
            Device_Cur Parm = Device_Org Parm
         %finish
      %finish
   %finish
%end

%routine Shut Device ( %record(Dev Fm) %name D )
   %integer I
   %return %if D == Nil %or D_Channel < 0
   %if D_Org Parm_Flags # D_Cur Parm_Flags %start
      I = Stty(D_Channel, D_Org Parm)
   %finish
   D_Channel = -1
%end

%external %routine Set Device %alias "EDWIN_SET_DEVICE" (%string(255) Dev Name)
   %integer Status
   Dev Name = "/dev/tty" %if Dev Name = ""
   Dev Name = Translate (Dev Name) %if Dev Name -> ("_")
   %if Dev Name -> ("_") %start
       Oper Message ("Error opening graphics device ".dev name.nl)
       %signal 14,1
   %finish
   %if Device == Nil %start
      Device == New(Device) ; Device = 0
   %else %if Device_Device # Dev Name
      Shut Device(Device)
   %else
      %return
   %finish
   Device_Device = Dev Name
   %if length(Dev Name)<4 %or substring(Dev Name, 1, 4)#"/dev" %start
      Device_Channel = -1 { ie. not really a device }
      %begin
         %on 9 %start
            Oper Message ("Error opening file ".dev name." for graphics output")
            %signal 14,1
         %finish
         Viewing = 3 { since this is not the console! }
         Open Output (Viewing, dev name)
      %end
      %return
   %finish
   Device_Channel = Imp Open(Dev Name, 2)
   %if Device_Channel < 0 %start
      Oper Message ("Error opening graphics device ".dev name.-
                    " with error ".itos(errno,0))
      %signal 14, 1, Errno
   %finish
   Status = Gtty(Device_Channel, Device_Org Parm)
   Device_Cur Parm = Device_Org Parm
%end

%external %routine Flush Output %alias "EDWIN_FLUSH"
   %integer Len = Length(Buffer)
   %return %if Len = 0
   %if Viewing = 0 %start
      Set Device("") %if Device == Nil
      Len = Write(Device_Channel, Charno(Buffer, 1), Len )
      %signal 14, 1, Errno %if Len < 0
   %else
      Len = Output Stream
      Select Output (Viewing)
      Print String (Buffer)
      Select Output (Len)
   %finish
   Buffer = ""
%end

%routine Set Cbreak ( %integer OnOff )
   Set Parm(Device, CBREAK, OnOff)
%end

%routine Set Echo ( %integer OnOff )
   Set Parm(Device, ECHO, OnOff)
%end

%external %routine TT Put %alias "EDWIN_TTPUT" ( %integer Char )
   Flush Output %if Length(Buffer) = 255
   Buffer = Buffer . Char
%end

%external %integer %function TT Get %alias "EDWIN_TTGET"
   %integer Sym = 0
   Set Device("") %if Device == Nil
   Set Cbreak(1) ; Set Echo(0)
   %integer Status = Read(Device_Channel, Byte(Addr(Sym)), 1)
   Set Cbreak(0);  Set Echo(1)
   %result = Sym
%end

%external %integer %function TT Read %alias "EDWIN_TTREAD"
   %own %string (127) Input Buffer = ""
   %own %integer In Buffer = 0, Next Char = 1
   Set Device("") %if Device == Nil
   %if Next Char > In Buffer %start
      In buffer = Read(Device_Channel, Byte(Addr(Input Buffer)+1), 127)
      Length (Input Buffer) = In Buffer
      Next Char = 1
   %finish
   Next Char = Next Char + 1
   %result = Charno (Input Buffer, Next Char - 1)
%end

%integer %function Opt Read
   %integer Sym = 0
   %integer Status = Read(Device_Channel, Byte(Addr(Sym)), 1)
   %result = Sym
%end

%external %routine OPER MESSAGE %alias "EDWIN_OPER_MESSAGE" (%string (255) S)
   %integer OS
   OS = Output Stream
   Select output (0)
   Print string (S)
   Newline
   Select output (OS)
%end

%external %routine OPER INTERACT %alias "EDWIN_OPER_INTERACT" (%string (255) S)
   %string (127) OLD PROMPT = "Data: "
   %integer IS, REPLY
   %on 9 %start
       Prompt (OLD PROMPT)
       %signal 9
   %finish
   IS = Input Stream
   Select input (0)
!   OLD PROMPT = CURRENT PROMPT
   Prompt (S)
   Read symbol (REPLY) %until REPLY&95='Y'
   Read symbol (REPLY) %until REPLY=NL
   Select input (IS)
   Prompt (OLD PROMPT)
%end

%external %routine TEK INPUT %alias "EDWIN___TEK_INPUT" (%integer %name A, X, Y, %integer cursor)
   %integer b, c, d, e, f
   ttput (27);   ttput (cursor);   flush output
   Set Device ("") %if Device == Nil
   Set Cbreak (1);   Set Echo (1)
   A = opt read;   B = opt read;   C = opt read;   D = opt read;   E = opt read
   F = opt read
   Set Cbreak (0)
   X = (B&31)<<5!C&31
   Y = (D&31)<<5!E&31
%end

%external %integer %fn MUL DIV %alias "EDWIN___MUL_DIV" (%integer A, B, C)
   ! Calculates int(A*B/C) to double precision.
   %integer Sign
   %integer RES, REM

   %result = 0 %if A=0 %or B=0 %or C=0
   Sign = A!!B!!C
   A = |A| ; B = |B| ; C = |C|
   * MOVD _ B, 0
   * MEID _ A, 0
   * DEID _ C, 0
   * MOVD _ 1, RES
   * MOVD _ 0, REM
   RES = RES + 1 %if REM > C//2
   Res = -Res %if Sign < 0
   %result = RES
%end

%end %of %file
