home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / PIBTERM.ZIP / PIBVT52.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1987-11-25  |  20.5 KB  |  466 lines

  1. (*----------------------------------------------------------------------*)
  2. (*   VT52.PAS --- Emulate Dec VT52 (Heath H19, Zenith Z19) for PIBTERM  *)
  3. (*----------------------------------------------------------------------*)
  4. (*                                                                      *)
  5. (*  Author:  Philip R. Burns                                            *)
  6. (*  Date:    October, 1984                                              *)
  7. (*  Version: 1.0                                                        *)
  8. (*  Systems: For MS-DOS on IBM PCs and close compatibles only.          *)
  9. (*           Note:  I have checked these on Zenith 151s under           *)
  10. (*                  MSDOS 2.1 and IBM PCs under PCDOS 2.0.              *)
  11. (*                                                                      *)
  12. (*  Needs:   The Menu routines from PIBMENUS.PAS and the communications *)
  13. (*           routines from PIBASYNC.PAS.                                *)
  14. (*                                                                      *)
  15. (*  History: Original with me.                                          *)
  16. (*                                                                      *)
  17. (*           Suggestions for improvements or corrections are welcome.   *)
  18. (*           Please leave messages on Gene Plantz's BBS (312) 882 4145  *)
  19. (*           or Ron Fox's BBS (312) 940 6496.                           *)
  20. (*                                                                      *)
  21. (*           If you use this code in your own programs, please be nice  *)
  22. (*           and give proper credit.                                    *)
  23. (*                                                                      *)
  24. (*----------------------------------------------------------------------*)
  25. (*                                                                      *)
  26. (*  Routines:                                                           *)
  27. (*                                                                      *)
  28. (*      Get_Async_Integer                                               *)
  29. (*      Emulate_VT52                                                    *)
  30. (*      Convert_VT52_Kbd                                                *)
  31. (*      Convert_VT52_Comm                                               *)
  32. (*                                                                      *)
  33. (*----------------------------------------------------------------------*)
  34. (*                                                                      *)
  35. (*  Remarks:                                                            *)
  36. (*                                                                      *)
  37. (*     The VT52 keypad is mapped onto the function keys as follows:     *)
  38. (*                                                                      *)
  39. (*        The left half of the keypad --> function keys F1 through F10. *)
  40. (*        The right half of the keypad --> function keys Alt F1 thru    *)
  41. (*        Alt F10.                                                      *)
  42. (*                                                                      *)
  43. (*     For convenience, the arrow keys can also be used to generate     *)
  44. (*     the same codes as the arrows from the function keys.             *)
  45. (*                                                                      *)
  46. (*     For those VT52 keypad keys which are double-sized, two adjacent  *)
  47. (*     function keys will send the same codes.                          *)
  48. (*                                                                      *)
  49. (*     Note that the function keys are always in keypad application     *)
  50. (*     mode.  Numeric codes can be sent using the regular PC keypad.    *)
  51. (*                                                                      *)
  52. (*----------------------------------------------------------------------*)
  53.  
  54. Procedure Get_Async_Integer( Var Integr: Integer );
  55.  
  56. (*----------------------------------------------------------------------*)
  57. (*                                                                      *)
  58. (*   Procedure: Get_Async_Integer                                       *)
  59. (*                                                                      *)
  60. (*   Purpose:  Gets integer in biased VT52 form from COM port           *)
  61. (*                                                                      *)
  62. (*   Calling sequence:                                                  *)
  63. (*                                                                      *)
  64. (*      Get_Async_Integer( Var Integr: Integer );                       *)
  65. (*                                                                      *)
  66. (*         Integr: Returned integer value                               *)
  67. (*                                                                      *)
  68. (*   Calls:  None                                                       *)
  69. (*                                                                      *)
  70. (*   Called by:   Convert_VT52_Kbd                                      *)
  71. (*                Convert_VT52_Comm                                     *)
  72. (*                                                                      *)
  73. (*   Remarks:                                                           *)
  74. (*                                                                      *)
  75. (*      The screen positions on the VT52 are expressed in excess 31     *)
  76. (*      notation.  That is, the value 31 is added to each row and       *)
  77. (*      column value.                                                   *)
  78. (*                                                                      *)
  79. (*----------------------------------------------------------------------*)
  80.  
  81. Var
  82.    C  : Char;
  83.  
  84. Begin (* Get_Async_Integer *)
  85.  
  86.    Repeat
  87.    Until( Async_Receive( C ) );
  88.  
  89.    Integr := ORD( C ) - 31;
  90.  
  91. End   (* Get_Async_Integer *);
  92.  
  93.  
  94. (*----------------------------------------------------------------------*)
  95. (*                Emulate_VT52 -- Controls VT52 emulation               *)
  96. (*----------------------------------------------------------------------*)
  97.  
  98. Procedure Emulate_VT52;
  99.  
  100. (*    Routine:  Emulate_VT52                                            *)
  101. (*                                                                      *)
  102. (*    Purpose:  Controls VT52 terminal emulation                        *)
  103. (*                                                                      *)
  104. (*    Calling Sequence:                                                 *)
  105. (*                                                                      *)
  106. (*       Emulate_VT52;           No arguments                           *)
  107. (*                                                                      *)
  108. (*    Calls:                                                            *)
  109. (*                                                                      *)
  110. (*       Convert_VT52_kbd            Maps PC input to VT52 codes        *)
  111. (*       Convert_VT52_Comm           Maps received VT52 codes to PC     *)
  112. (*                                                                      *)
  113. (*    Called by:  PIBTERM                                               *)
  114. (*                                                                      *)
  115. (*    Remarks:                                                          *)
  116. (*                                                                      *)
  117. (*       (1)  The graphics characters produced in graphics mode are     *)
  118. (*            VT100 graphics characters.  This is what many VT100s      *)
  119. (*            and compatibles produce in VT52 mode.                     *)
  120. (*                                                                      *)
  121. (*       (2)  Tab positions on the VT52 are located in fixed positions. *)
  122. (*            Those are the positions used here.  Some VT52-like        *)
  123. (*            terminals allow user-settable tabs.  Those are not        *)
  124. (*            implemented here.                                         *)
  125. (*                                                                      *)
  126.  
  127. Const
  128.    ON   = TRUE                       (* Convenient synonym for switches *);
  129.    OFF  = FALSE                      (* Likewise                        *);
  130.  
  131. Var
  132.    Comm_Ch            : Char         (* Character read from comm port   *);
  133.    Kbd_Ch             : Char         (* Character read from keyboard    *);
  134.    VT52_Graphics_Mode : Boolean      (* TRUE if VT52 graphics mode on   *);
  135.    VT52_KeyPad        : Boolean      (* TRUE if alternate keypad in use *);
  136.    Done               : Boolean      (* TRUE to stop PIBTERM            *);
  137.    B                  : Boolean      (* General purpose flag            *);
  138.    Graph_Ch           : Byte         (* Graphics character              *);
  139.    Itab               : Byte         (* Tab stop                        *);
  140.    Tabcol             : Byte         (* Tab column                      *);
  141.    Curcol             : Byte         (* Current column in display       *);
  142.    Auto_Print_Mode    : Boolean      (* If auto print mode in effect    *);
  143.    Printer_Ctrl_Mode  : Boolean      (* If printer controller mode on   *);
  144.    Print_Line         : String[80]   (* Line to print if print mode on  *);
  145.  
  146. Const
  147.    Graphics_Chars: Array[ 95 .. 126 ] Of Byte
  148.                    = (  32,   4, 177,   9,  12,  13,  10, 248, 241,
  149.                         10,  10, 217, 191, 218, 192, 197, 196, 196,
  150.                        196, 196,  95, 195, 180, 193, 194, 179, 243,
  151.                        242, 227, 168, 156, 250 );
  152.  
  153.    Number_VT52_Tabs = 16;
  154.  
  155.    VT52_Tabs:  Array[ 1 .. Number_VT52_Tabs ] Of Byte
  156.                = (  9, 17, 25, 33, 41, 49, 57, 65, 73, 74, 75, 76, 77,
  157.                    78, 79, 80 );
  158.  
  159.  
  160. Procedure Convert_VT52_Comm;
  161.  
  162. (*                                                                      *)
  163. (*     Routine:  Convert_VT52_Comm                                      *)
  164. (*                                                                      *)
  165. (*     Purpose:  Executes incoming VT52 escape sequences                *)
  166. (*                                                                      *)
  167. (*                                                                      *)
  168. (*     Calling Sequence:                                                *)
  169. (*                                                                      *)
  170. (*        Convert_VT52_Comm;             -- no parameters --            *)
  171. (*                                                                      *)
  172. (*     Calls:  None                                                     *)
  173. (*                                                                      *)
  174. (*     Called by:  Emulate_VT52                                         *)
  175. (*                                                                      *)
  176. (*     Remarks:                                                         *)
  177. (*                                                                      *)
  178. (*        This routine assumes that a CHR(27) (Escape) was just read.   *)
  179. (*        The following character is assumed to be a VT52 code.         *)
  180. (*                                                                      *)
  181.  
  182. Var
  183.    Ch:  Char;
  184.    X:   Integer;
  185.    Y:   Integer;
  186.    Y2:  Integer;
  187.    B:   Boolean;
  188.  
  189. Begin (* Convert_VT52_Comm *)
  190.  
  191.    Repeat
  192.    Until( Async_Receive( Ch ) );
  193.  
  194.    Case  CH  Of
  195.  
  196.       'A':  Begin (* Move cursor up *)
  197.                GoToXY( Wherex, Max( WhereY - 1 , 1 ) );
  198.             End;
  199.  
  200.       'B':  Begin (* Move cursor down *)
  201.                GoToXY( Wherex, Min( WhereY + 1 , 25 ) );
  202.             End;
  203.  
  204.       'C':  Begin (* Move cursor left *)
  205.                GoToXY( Max( Wherex - 1 , 1 ), WhereY );
  206.             End;
  207.  
  208.       'D':  Begin (* Move cursor right *)
  209.                GoToXY( Min( WhereX + 1 , 80 ), WhereY );
  210.             End;
  211.  
  212.       'F':  VT52_Graphics_Mode := TRUE;
  213.  
  214.       'G':  VT52_Graphics_Mode := FALSE;
  215.  
  216.       'H':  GoToXY( 1 , 1 );
  217.  
  218.       'I':  Begin
  219.                X := WhereX;
  220.                Y := WhereY - 1;
  221.                IF y > 0 Then
  222.                   GoToXY( X , Y )
  223.                Else
  224.                   Scroll( 1, 25, 1, 80, -1 );
  225.             End;
  226.  
  227.       'J':  Begin (* Clear to End of Screen *)
  228.  
  229.                X := WhereX;
  230.                Y := WhereY;
  231.  
  232.                ClrEol;
  233.  
  234.                For Y2 := ( Y + 1 ) To 25 Do
  235.                   Begin
  236.                      GoToXY( 1 , Y2 );
  237.                      ClrEol;
  238.                   End;
  239.  
  240.               GoToXY( X , Y );
  241.  
  242.             End;
  243.  
  244.       'K':  ClrEol (* Clear to End of Line *);
  245.  
  246.       'W':  Printer_Ctrl_Mode := ON;
  247.  
  248.       'X':  Printer_Ctrl_Mode := OFF;
  249.  
  250.       'Y':  Begin  (* Move to screen position *)
  251.                Get_Async_Integer( Y );
  252.                Get_Async_Integer( X );
  253.  
  254.                Y := MAX( 1 , MIN( Y , 25 ) );
  255.                X := MAX( 1 , MIN( X , 80 ) );
  256.  
  257.                GoToXY( X , Y );
  258.             End;
  259.  
  260.       'Z':  Async_Send_String( Chr(27) + '/Z' )    (* Identify *);
  261.  
  262.       '=':  VT52_Keypad := ON    (* Enter keypad mode *);
  263.  
  264.       '>':  VT52_Keypad := OFF   (* Exit keypad mode *);
  265.  
  266.       ']':  Print_Screen;
  267.  
  268.       '-':  Auto_Print_Mode := OFF;
  269.  
  270.       '^':  Auto_Print_Mode := ON;
  271.  
  272.       Else
  273.             ;
  274.  
  275.    End (* Case CH *);
  276.  
  277.  
  278. End   (* Convert_VT52_Comm *);
  279.  
  280. (*----------------------------------------------------------------------*)
  281. (*            Convert_VT52_Kbd -- Controls VT52 keyboard emulation      *)
  282. (*----------------------------------------------------------------------*)
  283.  
  284. Procedure Convert_VT52_Kbd( Var Done : Boolean );
  285.  
  286. (*                                                                      *)
  287. (*     Routine:  Convert_VT52_Kbd                                       *)
  288. (*                                                                      *)
  289. (*     Purpose:  Convert PC keyboard codes to VT52 escape sequences     *)
  290. (*                                                                      *)
  291. (*     Calling Sequence:                                                *)
  292. (*                                                                      *)
  293. (*        Convert_VT52_Kbd( Var Done: Boolean );                        *)
  294. (*                                                                      *)
  295. (*           Done --- set TRUE if ALtX encountered                      *)
  296. (*                                                                      *)
  297. (*     Calls:  None                                                     *)
  298. (*                                                                      *)
  299. (*     Called by:  Emulate_VT52                                         *)
  300. (*                                                                      *)
  301. (*     Remarks:                                                         *)
  302. (*                                                                      *)
  303. (*        A more efficient method of writing this routine would be to   *)
  304. (*        use a simple replace via table lookup of the PC code by the   *)
  305. (*        VT52 code.                                                    *)
  306. (*                                                                      *)
  307.  
  308. Const
  309.    Esc_Ch   = ^[;
  310.    Esc_Ch_Q = ^['?';
  311.  
  312. Var
  313.    X:   Integer;
  314.    Y:   Integer;
  315.    Ch:  Char;
  316.  
  317. Begin (* Convert_VT52_Kbd *)
  318.  
  319.    Read( Kbd , Ch );
  320.  
  321.    Case  ORD( Ch )  Of
  322.  
  323.                    (* Arrows *)
  324.  
  325.       72:  Async_Send_String( Esc_Ch + 'A' );    (* Up Arrow     *)
  326.       80:  Async_Send_String( Esc_Ch + 'B' );    (* Down Arrow   *)
  327.       77:  Async_Send_String( Esc_Ch + 'C' );    (* Right Arrow  *)
  328.       75:  Async_Send_String( Esc_Ch + 'D' );    (* Left Arrow   *)
  329.  
  330.                    (* VT52_Keypad *)
  331.  
  332.       59:  Async_Send_String( Esc_Ch + 'P' );    (* Blue         *)
  333.       60:  Async_Send_String( Esc_Ch + 'Q' );    (* Red          *)
  334.      104:  Async_Send_String( Esc_Ch + 'R' );    (* Gray         *)
  335.      105:  Async_Send_String( Esc_Ch + 'A' );    (* Up Arrow     *)
  336.  
  337.       61:  Async_Send_String( Esc_Ch_Q + 'w' );  (* 7            *)
  338.       62:  Async_Send_String( Esc_Ch_Q + 'x' );  (* 8            *)
  339.      106:  Async_Send_String( Esc_Ch_Q + 'y' );  (* 9            *)
  340.      107:  Async_Send_String( Esc_Ch_Q + 'B' );  (* Down Arrow   *)
  341.  
  342.       63:  Async_Send_String( Esc_Ch_Q + 't' );  (* 4            *)
  343.       64:  Async_Send_String( Esc_Ch_Q + 'u' );  (* 5            *)
  344.      108:  Async_Send_String( Esc_Ch_Q + 'v' );  (* 6            *)
  345.      109:  Async_Send_String( Esc_Ch_Q + 'C' );  (* Right Arrow  *)
  346.  
  347.       65:  Async_Send_String( Esc_Ch_Q + 'q' );  (* 1            *)
  348.       66:  Async_Send_String( Esc_Ch_Q + 'r' );  (* 2            *)
  349.      110:  Async_Send_String( Esc_Ch_Q + 's' );  (* 3            *)
  350.      111:  Async_Send_String( Esc_Ch_Q + 'D' );  (* Left Arrow   *)
  351.  
  352.       67:  Async_Send_String( Esc_Ch_Q + 'p' );  (* 0            *)
  353.       68:  Async_Send_String( Esc_Ch_Q + 'p' );  (* 0            *)
  354.      112:  Async_Send_String( Esc_Ch_Q + 'n' );  (* Period       *)
  355.      113:  Async_Send_String( Esc_Ch_Q + 'M' );  (* Enter        *)
  356.  
  357.                    (* Cursor Movement *)
  358.  
  359.       79:  Async_Send_String( Esc_Ch + 'K' );    (* Erase to EOL *)
  360.      117:  Async_Send_String( Esc_Ch + 'J' );    (* Erase to EOS *)
  361.  
  362.       71:  Async_Send_String( Esc_Ch + 'H' );    (* Home cursor  *)
  363.  
  364.       Else
  365.          Process_Command( Done, Ch, TRUE );
  366.  
  367.    End (* Case CH *);
  368.  
  369.  
  370. End   (* Convert_VT52_Kbd *);
  371.  
  372.  
  373.  
  374. Begin (* Emulate_VT52 *)
  375.                                    (* Indicate VT52 being simulated *)
  376.    Writeln;
  377.    Writeln('Emulating VT52 Terminal');
  378.  
  379.                                    (* Initialize terminal state     *)
  380.    Done               := FALSE;
  381.    VT52_Keypad        := OFF;
  382.    VT52_Graphics_Mode := OFF;
  383.    Auto_Print_Mode    := OFF;
  384.    Printer_Ctrl_Mode  := OFF;
  385.  
  386.                                    (* Loop over input until done *)
  387.    While ( NOT Done ) DO
  388.       Begin
  389.  
  390.          If KeyPressed Then
  391.             Begin (* KeyPressed *)
  392.  
  393.                Read( Kbd , Comm_Ch );
  394.  
  395.                Case ORD( Comm_Ch ) Of
  396.  
  397.                   ESC:  Convert_VT52_Kbd( Done );
  398.  
  399.                   BS:   Begin
  400.                            Comm_Ch := BS_Char;
  401.                            If Local_Echo Then Write( Comm_Ch );
  402.                            Async_Send( Comm_Ch );
  403.                         End;
  404.  
  405.                   DEL:  Begin
  406.                            Comm_Ch := Ctrl_BS_Char;
  407.                            If Local_Echo Then Write( Comm_Ch );
  408.                            Async_Send( Comm_Ch );
  409.                         End;
  410.  
  411.                   Else
  412.                         Begin
  413.                            If Local_Echo Then Write( Comm_Ch );
  414.                            Async_Send( Comm_Ch );
  415.                         End;
  416.  
  417.                End (* CASE ORD( Comm_Ch ) *);
  418.  
  419.             End (* KeyPressed *);
  420.  
  421.          If Async_Receive( Comm_Ch ) Then
  422.  
  423.             Case ORD( Comm_Ch ) Of
  424.  
  425.                ESC:  Convert_VT52_Comm;
  426.  
  427.                LF,
  428.                FF,
  429.                VT:   Begin (* go down one line *)
  430.                         Display_Character( CHR( LF ) );
  431.                         If Auto_Print_Mode Then
  432.                            Begin
  433.                               Get_Screen_Text_Line( Print_Line, WhereY - 1, 1 );
  434.                               Writeln( Lst , Print_Line );
  435.                            End;
  436.                      End   (* go down one line *);
  437.  
  438.                HT:   Begin (* Convert tabs to sequence of blanks *)
  439.                         Curcol := WhereX;
  440.                         Itab   := 1;
  441.                         While( Curcol > VT52_Tabs[Itab] ) Do
  442.                            Itab := Itab + 1;
  443.                         Tabcol := VT52_Tabs[Itab];
  444.                         For Itab := Curcol To ( Tabcol - 1 ) Do
  445.                            Write(' ');
  446.                      End   (* Tabs *);
  447.  
  448.                Else
  449.                   If NOT VT52_Graphics_Mode Then
  450.                      Display_Character( Comm_Ch )
  451.                   Else
  452.                      Begin (* Graphics Mode *)
  453.                         If ORD( Comm_Ch ) IN [ 95 .. 126 ] Then
  454.                            Begin
  455.                               Graph_Ch := Graphics_Chars[ ORD( Comm_Ch ) - 95 ];
  456.                               Display_Character( CHR( Graph_Ch ) );
  457.                            End
  458.                         Else
  459.                            Display_Character( Comm_Ch );
  460.                      End   (* Graphics Mode *);
  461.  
  462.             End (* CASE ORD( Comm_Ch ) *);
  463.  
  464.       End  (* NOT Done *);
  465.  
  466. End   (* Emulate_VT52 *);