! System dependent stuff for IE
! APM version - RMM and GDMR March 84

%option "-NOCHECK-NODIAG-FORCE"

%external %string (255) Copyright %alias "SYSDEP_(C)_RMM" = %c
                  "Copyright (C) Richard M. Marshall and George D. M. Ross 1984"

%include "SYSDEP.INC"
%include "IE.INC"

%include "Inc:Util.Imp"

! Heap stuff

%own %integer Times Marked

%external %routine Initialise Heap Space %alias "IE_INIT_HEAP"
   Mark
   Times Marked = 1
%end

%external %routine Reset Heap Space %alias "IE_RESET_HEAP"
   %integer I

   Release %for I = 1, 1, Times Marked
%end

%external %record (Line fm) %map New Line fm %alias "IE_NEW_LINE" %c
                                             (%integer Characters)
   %record (Line fm) %name L

   Characters = (Characters + 3)&(\3)
   L == Record (Heap Get (Characters + Size Of Line FM))
   L_Max Length = Characters
   %result == L
%end

%external %routine Dispose Line FM %alias "IE_DISPOSE_LINE" %c
                                   (%record (Line fm) %name L)
   Heap Put (Addr (L))
%end {Dispose Line fm}

%include "Inc:FS.Imp"
!!!%include "Inc:Ether.Imp"

%ownbytearray buffer(0 : 512)
%ownbytename  ch
%ownbytename  end
%owninteger   finished = -1

%routine grab file(%string(127) file)
   %integer x
      x = fcomm('Z' << 8, file)
      end == buffer(512)
      ch == end
      finished = 0
%end

%routine get next block
   %integer b
      b = ether read(fs port, buffer(0), 512)
      end == buffer(b)
      ch == buffer(0)
      finished = -1 %if b # 512
%end

! File loading & unloading

%external %routine load buffer %alias "IE_LOAD_BUFFER" %c
                               (%record (buffer fm) %name buffer,
                                %string (127) file name)
   %record(line fm)%name current == nil, previous == nil, first == nil
   %integer N
   %byte %name In
   %integer Saved
   %byte %array Line Buffer (0 : 1023)

      %on 9, 2 %start
         -> EOF %if Event_Event = 9
         Get Next Block %while Finished = 0
         -> Fails
      %finish

      buffer_source file = file name

      Mark
      Times Marked = Times Marked + 1
      Grab File (File Name)
      %cycle

         N = 0                {Length}
         In == Line Buffer (0)
         %cycle
            %if ch == end %start
               %signal 9 %if finished # 0
               get next block
               %signal 9 %if ch == end
            %finish
            In = ch
            ch == ch[1]
            %exit %if In = NL
            N = N + 1
            In == In [1]
         %repeat

         Current == New Line fm (N)

         Bulk Move (N, Line Buffer (0), Current_Text (1))

         Current_Length = N
         current_bits =  untouched

         %if previous == nil %start
            current_last == nil
            first == current
         %else
            previous_next == current
            current_last == previous
         %finish
         current_next == nil
         previous == current
      %repeat
   EOF:
      Current == New Line fm (0)
      %if previous == nil %start
         current_last == nil
         first == current
      %else
         previous_next == current
         current_last == previous
      %finish
      current_next == nil
      current_bits  =  pseudo line;  ! the end marker, really...
      current_max Length = 0
      current_length = 0
      current_last  == previous
      buffer_first  == first
      buffer_last   == current
      buffer_changed = 0
      %return

   Fails:
      Release
      Times Marked = Times Marked - 1
      %signal 10, 0, 0, Event_Message
%end


%external %routine unload buffer %alias "IE_UNLOAD_BUFFER" %c
                                 (%record (buffer fm) %name buffer,
                                  %string (127) file name)
   %record(line fm)%name line
   %integer N,
            Save = Out Stream

      Open Output (3, File Name)
      Select Output (3)
      line == buffer_first
      %while line ## nil %and line_bits & pseudo line = 0 %cycle
         %if Line_Length > 0 %start
            %for N = 1, 1, Line_Length %cycle
               Print Symbol (Line_Text (N))
            %repeat
         %finish
         New Line
         line == line_next
      %repeat
      Close Output
      Select Output (Save)
%end


! Journal file stuff comes here.....

%external %string (31) Actual Journal File %alias "IE_J_FILE" = "IE_JOURNAL"

%string(4)%fn itoh(%integer i)
   ! four hexit version
   %string(7) s
   %integer j, k, n
      s = ""
      %for n = 1, 1, 4 %cycle
         j = i // 16
         k = i - 16 * j
         s = tostring(k + '0') . s
         i = j
      %repeat
      %result = s
%end

%owninteger J Xno = 0
%owninteger journal frequency = 0
%owninteger next journal block = 0
%owninteger next journal byte = 0
%owninteger journal remaining = 0
%ownbytearray journal buffer(0 : 511) = 4(*)
%own %integer Created Old = 0

%routine open journal

   %on 9 %start
      Journal Frequency = 0
      -> Compiler Bug
   %finish

   %return %if J Xno # 0

   next journal block = 0
   next journal byte = 0
   journal remaining = 0
   %if Exists (Journal File) %start
      Delete (Old Journal) %if Exists (Old Journal)
      Rename (Journal File, Old Journal)
      Created Old = 1
   %else
      Created Old = 0
   %finish
   J Xno = fcomm('T' << 8, Journal File)
   %if J Xno <= 0 %start
      journal frequency = 0
   %else
      Rename (Journal File . "!", Journal File)
   %finish
   %return

Compiler Bug:
   %signal Abort
%end

%routine flush journal
   %integer i
      %return %if J Xno = 0
  !!  journal buffer(i) = 4 %for i = next journal byte, 1, 511
      fcommw('W0' + J Xno, itoh(next journal block) . ",",
             journal buffer(0), {512} next journal byte)
      journal remaining = journal frequency
      %if next journal byte = 512 %start
         next journal byte = 0
         next journal block = next journal block + 1
      %finish
%end

%external %routine put journal symbol %alias "IE_J_PUT" (%integer sym)
   %own %integer Prev = 0

   %return %if journal frequency = 0
   open journal %if J Xno = 0
   journal buffer(next journal byte) = sym
   next journal byte = next journal byte + 1
   %unless Sym = 27 {ESC} %or %c
           (Prev = 27 %and Sym = '?') %start
      journal remaining = journal remaining - 1
   %finish
   flush journal %if journal remaining = 0 %or next journal byte = 512
   Prev = Sym
%end

{PUT JOURNAL STRING}

%external %routine put journal string %alias "IE_J_STRING" (%string (255) S)
   %integer I, ch

   %for I = 1, 1, length (S) %cycle
      ch = char no (S, I)
      put journal symbol (ch) %if ch >= ' '
   %repeat
%end {of put journal string}

{PUT JOURNAL INTEGER}

%external %routine put journal integer %alias "IE_J_INT" (%integer i)
   put journal string (I to S (i, 0))
%end {put journal integer}

%externalroutine set journal frequency %alias "IE_J_SET" (%integer new)
   flush journal
   journal frequency = new
   journal remaining = new
%end

%externalroutine keep journal %alias "IE_J_KEEP"
   %integer junk
      %return %if J Xno = 0
      flush journal
      junk = fcomm('K0' + J Xno, "")
      J Xno = 0
      Delete (Old Journal) %if Created Old # 0
%end

%externalroutine scrap journal %alias "IE_J_SCRAP"
   %integer junk
      %return %if J Xno = 0
      junk = fcomm('U0' + J Xno, "0")
      junk = fcomm('H0' + J Xno, "")
      J Xno = 0
      Delete (Old Journal) %if Created Old # 0
%end

! Miscellaneous useful things:
! Bulk move, Find string

%external %routine bulk move %alias "IE_BULK_MOVE" %c
                             (%integer bytes, 
                              %bytename from, to)
   %return %if Bytes = 0 %or %c
               From == To
   %if Addr (To) < Addr (From) %start
      *Subq.l #1, d0
   f loop:
      *move.b (a0)+, (a1)+
      *dbra   d0, f loop
   %else
      *add.l  d0, a0
      *add.l  d0, a1
      *subq.l #1, d0
   b loop:
      *move.b -(a0), -(a1)
      *dbra   d0, b loop
   %finish
%end

%external %integerfn find string %alias "IE_FIND_STRING" %c
                                 (%integer case mode,
                                  %string (*) %name Find, 
                                  %integer Start,
                                  %record (Line fm) %name Match)
   %bytename start match, current match, start find, current find
   %integer match length, current length, searches, start pos, it

      %result = 0 %if match_length < start

      start match == match_text(start)
      start find  == charno(find, 1)
      searches     = match_length - length(find) - start + 2
      start pos    = start
      %while searches > 0 %cycle
         current match == start match
         current find  == start find
         current length = length(find)
         %cycle
            it = current match
            it = it - 'a' + 'A' %if case mode = 0 %and 'a' <= it <= 'z'
            %exit %if it # current find
            current find  == current find  [1]
            current match == current match [1]
            current length = current length - 1
            %result = start pos %if current length = 0
         %repeat
         start match == start match [1]
         searches = searches - 1
         start pos = start pos + 1
      %repeat
      %result = 0
%end

%external %integer %function Reverse find string %alias "IE_REV_FIND" %c
                                 (%integer case mode,
                                  %string (*) %name Find, 
                                  %integer Start,
                                  %record (Line fm) %name Match)
   %bytename start match, current match, start find, current find
   %integer match length, current length, searches, start pos, it

      %if Start + Length (Find) > Match_Length %start
         Start = Match_Length - Length (Find) + 1
      %finish
      %result = 0 %if Start < 1
      start match == match_text(start)
      start find  == charno(find, 1)
      searches     = start
      start pos    = start
      %while searches > 0 %cycle
         current match == start match
         current find  == start find
         current length = length(find)
         %cycle
            it = current match
            it = it - 'a' + 'A' %if case mode = 0 %and 'a' <= it <= 'z'
            %exit %if it # current find
            current find  == current find  [1]
            current match == current match [1]
            current length = current length - 1
            %result = start pos %if current length = 0
         %repeat
         start match == start match [-1]
         searches = searches - 1
         start pos = start pos - 1
      %repeat
      %result = 0
%end

! Default Finders

%include "Terminal.Inc"
%include "Inc:Dict.Imp"
%include "Inc:FSUtil.Imp"

%record %format IE Stuff fm (%string (127) Memory,
                                           Last,
                                           Journal File,
                                           Profile File,
                                           Keyboard File,
                             %byte Terminal,
                             %integer Line, Position)

%own %record (IE Stuff fm) %name IE Stuff == Nil
%own %integer Stuff At

%external %string (127) %function Default Profile %alias "IE_DEF_PRO"
   %string (127) P = "",
                 S
   %constant %string (20) Profile File = "Profile.IE"

   %if IE Stuff == Nil %start
      Stuff At = Ref Name ("IE_Stuff", Sys Dict)
      IE Stuff == Record (Stuff At)
   %finish
   %if IE Stuff ## Nil %start
      P = IE Stuff_Profile File
   %finish
   %if P = "" %start
      %if Exists (Profile File) %start
         P = Profile File
      %else
         S = Current User . ":" . Profile File
         P = S %if Exists (S)
      %finish
   %finish
   %result = P
%end {Default Profile}

%external %string (127) %function Default Keyboard %alias "IE_DEF_KEY"
   %constant %string (20) %array Default Keyboards (Visual 200 : WY 75) = %c
      "IE:V200.KIE",
      "IE:V55.KIE",
      "IE:VT100.KIE",
      "IE:VT220.KIE",
      "IE:F100.KIE",
      "IE:WY50.KIE",
      "IE:WY75.KIE"

   %string (127) K, S
   %constant %string (20) Keyboard File = "Keyboard.KIE"


   K = Default Keyboards (Terminal Model)
   %if IE Stuff == Nil %start
      Stuff At = Ref Name ("IE_Stuff", Sys Dict)
      IE Stuff == Record (Stuff At)
   %finish
   %if IE Stuff ## Nil %and %c
       IE Stuff_Keyboard File # "" %start
      K = IE Stuff_Keyboard File
   %else
      %if Exists (Keyboard File) %start
         K = Keyboard File
      %else
         S = Current User . ":" . Keyboard File
         K = S %if Exists (S)
      %finish
   %finish
   %result = K
%end {Default Keyboard}

%external %string (127) %function Default Journal %alias "IE_DEF_JOU"
   %string (127) J = "IE_JOURNAL"

   %if IE Stuff == Nil %start
      Stuff At = Ref Name ("IE_Stuff", Sys Dict)
      IE Stuff == Record (Stuff At)
   %finish
   %if IE Stuff ## Nil %and %c
       IE Stuff_Journal File # "" %start
      J = IE Stuff_Journal File
   %finish
   %result = J
%end {Default Journal}

%end %of %file
