home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / os2pm / term.mod < prev   
Text File  |  2020-01-01  |  12KB  |  382 lines

  1. IMPLEMENTATION MODULE Term;   (* TVI950 Terminal Emulation for Kermit *)
  2.  
  3.    FROM Drives IMPORT
  4.       SetDrive;
  5.  
  6.    FROM Directories IMPORT
  7.       FileAttributes, AttributeSet, DirectoryEntry, FindFirst, FindNext;
  8.  
  9.    FROM SYSTEM IMPORT
  10.       ADR;
  11.  
  12.    FROM DosCalls IMPORT
  13.       DosChDir, DosSleep;
  14.  
  15.    FROM Screen IMPORT
  16.       ClrScr, ClrEol, GotoXY, GetXY,
  17.       Right, Left, Up, Down, WriteAtt, WriteString, WriteLn, Write,
  18.       attribute, NORMAL, HIGHLIGHT, REVERSE;
  19.  
  20.    FROM PMWIN IMPORT
  21.       MPARAM, WinPostMsg;
  22.  
  23.    FROM Shell IMPORT
  24.       comport, FrameWindow;
  25.  
  26.    FROM KH IMPORT
  27.       COM_OFF;
  28.  
  29.    FROM CommPort IMPORT
  30.       CommStatus, GetChar, SendChar;
  31.  
  32.    FROM Strings IMPORT
  33.       Length, Concat;
  34.  
  35.    IMPORT ASCII;
  36.  
  37.  
  38.    CONST
  39.       (* Key codes:  Note: F1 -- F12 are actually Shift-F1 -- Shift-F12 *)
  40.       F1 = 124C;
  41.       F2 = 125C;
  42.       F3 = 126C;
  43.       F4 = 127C;
  44.       F5 = 130C;
  45.       F6 = 131C;
  46.       F7 = 132C;
  47.       F8 = 133C;
  48.       F9 = 134C;
  49.       F10 = 135C;
  50.       F11 = 207C;
  51.       F12 = 210C;
  52.       AF1 = 150C;   (* Alt-F1 *)
  53.       AF2 = 151C;   (* Alt-F2 *)
  54.       INS = 122C;
  55.       DEL = 123C;
  56.       HOME = 107C;
  57.       PGDN = 121C;   (* synonym for PF10 *)
  58.       PGUP = 111C;   (* synonym for PF11 *)
  59.       ENDD = 117C;   (* synonym for PF12 *)
  60.       UPARROW = 110C;
  61.       DOWNARROW = 120C;
  62.       LEFTARROW = 113C;
  63.       RIGHTARROW = 115C;
  64.       CtrlX = 30C;
  65.       CtrlCaret = 36C;
  66.       CtrlZ = 32C;
  67.       CtrlL = 14C;
  68.       CtrlH = 10C;
  69.       CtrlK = 13C;
  70.       CtrlJ = 12C;
  71.       CtrlV = 26C;
  72.       ESC = 33C;
  73.       BUFSIZE = 4096;   (* character buffer used by term thread *)
  74.  
  75.  
  76.    VAR
  77.       commStat : CommStatus;
  78.       echo : (Off, Local, On);
  79.       newline: BOOLEAN;   (* translate <cr> to <cr><lf> *)
  80.       Insert : BOOLEAN;
  81.       MP1, MP2 : MPARAM;
  82.  
  83.  
  84.    PROCEDURE Dir (path : ARRAY OF CHAR);
  85.    (* Change drive and/or directory; display a directory (in wide format) *)
  86.  
  87.       VAR
  88.          gotFN : BOOLEAN;
  89.          filename : ARRAY [0..20] OF CHAR;
  90.          attr : AttributeSet;
  91.          ent : DirectoryEntry;
  92.          i, j, k : INTEGER;
  93.  
  94.       BEGIN
  95.          filename := "";   (* in case no directory change *)
  96.          i := Length (path);
  97.          IF (i > 2) AND (path[1] = ':') THEN   (* drive specifier *)
  98.             DEC (i, 2);
  99.             SetDrive (ORD (CAP (path[0])) - ORD ('A'));
  100.             FOR j := 0 TO i DO   (* strip off the drive specifier *)
  101.                path[j] := path[j + 2];
  102.             END;
  103.          END;
  104.          IF i # 0 THEN
  105.             gotFN := FALSE;
  106.             WHILE (i >= 0) AND (path[i] # '\') DO
  107.                IF path[i] = '.' THEN
  108.                   gotFN := TRUE;
  109.                END;
  110.                DEC (i);
  111.             END;
  112.             IF gotFN THEN
  113.                j := i + 1;
  114.                k := 0;
  115.                WHILE path[j] # 0C DO
  116.                   filename[k] := path[j];
  117.                   INC (k);       INC (j);
  118.                END;
  119.                filename[k] := 0C;
  120.                IF (i = -1) OR ((i = 0) AND (path[0] = '\')) THEN
  121.                   INC (i);
  122.                END;
  123.                path[i] := 0C;
  124.             END;
  125.          END;
  126.          IF Length (path) # 0 THEN
  127.             DosChDir (ADR (path), 0);
  128.          END;
  129.          IF Length (filename) = 0 THEN
  130.             filename := "*.*";
  131.          END;
  132.          attr := AttributeSet {ReadOnly, Directory, Archive};
  133.          i := 1;   (* keep track of position on line *)
  134.  
  135.          ClrScr;
  136.          gotFN := FindFirst (filename, attr, ent);
  137.          WHILE gotFN DO
  138.             WriteString (ent.name);
  139.             j := Length (ent.name);
  140.             WHILE j < 12 DO   (* 12 is maximum length for "filename.typ" *)
  141.                Write (' ');
  142.                INC (j);
  143.             END;
  144.             INC (i);   (* next position on this line *)
  145.             IF i > 5 THEN
  146.                i := 1;   (* start again on new line *)
  147.                WriteLn;
  148.             ELSE
  149.                WriteString (" | ");
  150.             END;
  151.             gotFN := FindNext (ent);
  152.          END;
  153.          WriteLn;
  154.       END Dir;
  155.  
  156.  
  157.    PROCEDURE InitTerm;
  158.    (* Clear Screen, Home Cursor, Get Ready For Terminal Emulation *)
  159.       BEGIN
  160.          ClrScr;
  161.          Insert := FALSE;
  162.          attribute := NORMAL;
  163.       END InitTerm;
  164.  
  165.  
  166.    PROCEDURE PutKbdChar (ch1, ch2 : CHAR);
  167.    (* Process a character received from the keyboard *)
  168.       BEGIN
  169.          IF ch1 = ASCII.enq THEN   (* Control-E *)
  170.             echo := On;
  171.          ELSIF ch1 = ASCII.ff THEN   (* Control-L *)
  172.             echo := Local;
  173.          ELSIF ch1 = ASCII.dc4 THEN   (* Control-T *)
  174.             echo := Off;
  175.          ELSIF ch1 = ASCII.so THEN   (* Control-N *)
  176.             newline := TRUE;
  177.          ELSIF ch1 = ASCII.si THEN   (* Control-O *)
  178.             newline := FALSE;
  179.          ELSIF (ch1 = ASCII.can) OR (ch1 = ESC) THEN
  180.             attribute := NORMAL;
  181.             WinPostMsg (FrameWindow, WM_TERMQUIT, MPARAM (0), MPARAM (0));
  182.          ELSIF ch1 = 0C THEN
  183.             Function (ch2);
  184.          ELSE
  185.             commStat := SendChar (comport - COM_OFF, ch1, FALSE);
  186.             IF (echo = On) OR (echo = Local) THEN
  187.                WriteAtt (ch1);
  188.             END;
  189.          END;
  190.       END PutKbdChar;
  191.  
  192.  
  193.    PROCEDURE Function (ch : CHAR);
  194.    (* handles the function keys -- including PF1 - PF12, etc. *)
  195.       BEGIN
  196.          CASE ch OF
  197.             F1 :  commStat := SendChar (comport - COM_OFF, ASCII.soh, FALSE);
  198.                   commStat := SendChar (comport - COM_OFF, '@', FALSE);
  199.                   commStat := SendChar (comport - COM_OFF, ASCII.cr, FALSE);
  200.          |  F2 :  commStat := SendChar (comport - COM_OFF, ASCII.soh, FALSE);
  201.                   commStat := SendChar (comport - COM_OFF, 'A', FALSE);
  202.                   commStat := SendChar (comport - COM_OFF, ASCII.cr, FALSE);
  203.          |  F3 :  commStat := SendChar (comport - COM_OFF, ASCII.soh, FALSE);
  204.                   commStat := SendChar (comport - COM_OFF, 'B', FALSE);
  205.                   commStat := SendChar (comport - COM_OFF, ASCII.cr, FALSE);
  206.          |  F4 :  commStat := SendChar (comport - COM_OFF, ASCII.soh, FALSE);
  207.                   commStat := SendChar (comport - COM_OFF, 'C', FALSE);
  208.                   commStat := SendChar (comport - COM_OFF, ASCII.cr, FALSE);
  209.          |  F5 :  commStat := SendChar (comport - COM_OFF, ASCII.soh, FALSE);
  210.                   commStat := SendChar (comport - COM_OFF, 'D', FALSE);
  211.                   commStat := SendChar (comport - COM_OFF, ASCII.cr, FALSE);
  212.          |  F6 :  commStat := SendChar (comport - COM_OFF, ASCII.soh, FALSE);
  213.                   commStat := SendChar (comport - COM_OFF, 'E', FALSE);
  214.                   commStat := SendChar (comport - COM_OFF, ASCII.cr, FALSE);
  215.          |  F7 :  commStat := SendChar (comport - COM_OFF, ASCII.soh, FALSE);
  216.                   commStat := SendChar (comport - COM_OFF, 'F', FALSE);
  217.                   commStat := SendChar (comport - COM_OFF, ASCII.cr, FALSE);
  218.          |  F8 :  commStat := SendChar (comport - COM_OFF, ASCII.soh, FALSE);
  219.                   commStat := SendChar (comport - COM_OFF, 'G', FALSE);
  220.                   commStat := SendChar (comport - COM_OFF, ASCII.cr, FALSE);
  221.          |  F9 :  commStat := SendChar (comport - COM_OFF, ASCII.soh, FALSE);
  222.                   commStat := SendChar (comport - COM_OFF, 'H', FALSE);
  223.                   commStat := SendChar (comport - COM_OFF, ASCII.cr, FALSE);
  224.          |  F10,
  225.             PGDN: commStat := SendChar (comport - COM_OFF, ASCII.soh, FALSE);
  226.                   commStat := SendChar (comport - COM_OFF, 'I', FALSE);
  227.                   commStat := SendChar (comport - COM_OFF, ASCII.cr, FALSE);
  228.          |  F11,
  229.             AF1,
  230.             PGUP: commStat := SendChar (comport - COM_OFF, ASCII.soh, FALSE);
  231.                   commStat := SendChar (comport - COM_OFF, 'J', FALSE);
  232.                   commStat := SendChar (comport - COM_OFF, ASCII.cr, FALSE);
  233.          |  F12,
  234.             AF2,
  235.             ENDD: commStat := SendChar (comport - COM_OFF, ESC, FALSE);
  236.                   commStat := SendChar (comport - COM_OFF, 'Q', FALSE);
  237.          |  INS : IF NOT Insert THEN
  238.                      commStat := SendChar (comport - COM_OFF, ESC, FALSE);
  239.                      commStat := SendChar (comport - COM_OFF, 'E', FALSE);
  240.                   END;
  241.          |  DEL : commStat := SendChar (comport - COM_OFF, ESC, FALSE);
  242.                   commStat := SendChar (comport - COM_OFF, 'R', FALSE);
  243.          |  HOME       : commStat := SendChar (comport - COM_OFF, CtrlZ, FALSE);
  244.          |  UPARROW    : commStat := SendChar (comport - COM_OFF, CtrlK, FALSE);
  245.          |  DOWNARROW  : commStat := SendChar (comport - COM_OFF, CtrlV, FALSE);
  246.          |  LEFTARROW  : commStat := SendChar (comport - COM_OFF, CtrlH, FALSE);
  247.          |  RIGHTARROW : commStat := SendChar (comport - COM_OFF, CtrlL, FALSE);
  248.          ELSE
  249.             (* do nothing *)
  250.          END;
  251.       END Function;
  252.  
  253.  
  254.    PROCEDURE TermThrProc;
  255.    (* Thread to get characters from port, put into buffer *)
  256.  
  257.       VAR
  258.          ch : CHAR;
  259.  
  260.       BEGIN
  261.          LOOP
  262.             IF GetChar (comport - COM_OFF, ch) = Success THEN
  263.                MP1.W1 := ORD (ch);   MP1.W2 := 0;
  264.                MP2.L := 0;
  265.                WinPostMsg (FrameWindow, WM_TERM, MP1, MP2);
  266.             ELSE
  267.                DosSleep (0);
  268.             END
  269.          END;
  270.       END TermThrProc;
  271.  
  272.  
  273.    VAR
  274.       EscState, CurState1, CurState2 : BOOLEAN;
  275.       CurChar1 : CHAR;
  276.  
  277.    PROCEDURE PutPortChar (ch : CHAR);
  278.    (* Process a character received from the port *)
  279.       BEGIN
  280.          IF EscState THEN
  281.             EscState := FALSE;
  282.             IF ch = '=' THEN
  283.                CurState1 := TRUE;
  284.             ELSE
  285.                Escape (ch);
  286.             END;
  287.          ELSIF CurState1 THEN
  288.             CurState1 := FALSE;
  289.             CurChar1 := ch;
  290.             CurState2 := TRUE;
  291.          ELSIF CurState2 THEN
  292.             CurState2 := FALSE;
  293.             Cursor (ch);
  294.          ELSE
  295.             CASE ch OF
  296.                CtrlCaret, CtrlZ : ClrScr;
  297.             |  CtrlL : Right;
  298.             |  CtrlH : Left;
  299.             |  CtrlK : Up;
  300.             |  CtrlJ : Down;
  301.             |  ESC   : EscState := TRUE;
  302.             ELSE
  303.                WriteAtt (ch);
  304.                IF newline AND (ch = ASCII.cr) THEN
  305.                   WriteLn;
  306.                END;
  307.             END;
  308.          END;
  309.          IF echo = On THEN
  310.             commStat := SendChar (comport - COM_OFF, ch, FALSE);
  311.          END;
  312.       END PutPortChar;
  313.  
  314.  
  315.    PROCEDURE Escape (ch : CHAR);
  316.    (* handles escape sequences *)
  317.       BEGIN
  318.          CASE ch OF
  319.             '*' : ClrScr;
  320.          |  'T', 'R' : ClrEol;
  321.          |  ')' : attribute := NORMAL;
  322.          |  '(' : attribute := HIGHLIGHT;
  323.          |  'f' : InsertMsg;
  324.          |  'g' : InsertOn;
  325.          ELSE
  326.             (* ignore *)
  327.          END;
  328.       END Escape;
  329.  
  330.  
  331.    PROCEDURE Cursor (ch : CHAR);
  332.    (* handles cursor positioning *)
  333.  
  334.       VAR
  335.          x, y : CARDINAL;
  336.  
  337.       BEGIN
  338.          y := ORD (CurChar1) - 20H;
  339.          x := ORD (ch) - 20H;
  340.          GotoXY (x, y);   (* adjust for HOME = (1, 1) *)
  341.       END Cursor;
  342.  
  343.  
  344.    VAR
  345.       cx, cy : CARDINAL;
  346.  
  347.    PROCEDURE InsertMsg;
  348.    (* get ready insert mode -- place a message at the bottom of the screen *)
  349.       BEGIN
  350.          IF NOT Insert THEN
  351.             GetXY (cx, cy);   (* record current position *)
  352.             GotoXY (1, 24);
  353.             ClrEol;
  354.             attribute := REVERSE;
  355.          ELSE   (* exit Insert mode *)
  356.             GetXY (cx, cy);
  357.             GotoXY (1, 24);
  358.             ClrEol;
  359.             GotoXY (cx, cy);
  360.             Insert := FALSE;
  361.          END;
  362.       END InsertMsg;
  363.  
  364.  
  365.    PROCEDURE InsertOn;
  366.    (* enter insert mode -- after INSERT MODE message is printed *)
  367.       BEGIN
  368.          attribute := NORMAL;
  369.          GotoXY (cx, cy);
  370.          Insert := TRUE;
  371.       END InsertOn;
  372.  
  373.  
  374. BEGIN   (* module initialization *)
  375.    echo := Off;
  376.    newline := FALSE;
  377.    Insert := FALSE;
  378.    EscState := FALSE;
  379.    CurState1 := FALSE;
  380.    CurState2 := FALSE;
  381. END Term.
  382.