home *** CD-ROM | disk | FTP | other *** search
- (*----------------------------------------------------------------------*)
- (* VT52.PAS --- Emulate Dec VT52 (Heath H19, Zenith Z19) for PIBTERM *)
- (*----------------------------------------------------------------------*)
- (* *)
- (* Author: Philip R. Burns *)
- (* Date: October, 1984 *)
- (* Version: 1.0 *)
- (* Systems: For MS-DOS on IBM PCs and close compatibles only. *)
- (* Note: I have checked these on Zenith 151s under *)
- (* MSDOS 2.1 and IBM PCs under PCDOS 2.0. *)
- (* *)
- (* Needs: The Menu routines from PIBMENUS.PAS and the communications *)
- (* routines from PIBASYNC.PAS. *)
- (* *)
- (* History: Original with me. *)
- (* *)
- (* Suggestions for improvements or corrections are welcome. *)
- (* Please leave messages on Gene Plantz's BBS (312) 882 4145 *)
- (* or Ron Fox's BBS (312) 940 6496. *)
- (* *)
- (* If you use this code in your own programs, please be nice *)
- (* and give proper credit. *)
- (* *)
- (*----------------------------------------------------------------------*)
- (* *)
- (* Routines: *)
- (* *)
- (* Get_Async_Integer *)
- (* Emulate_VT52 *)
- (* Convert_VT52_Kbd *)
- (* Convert_VT52_Comm *)
- (* *)
- (*----------------------------------------------------------------------*)
- (* *)
- (* Remarks: *)
- (* *)
- (* The VT52 keypad is mapped onto the function keys as follows: *)
- (* *)
- (* The left half of the keypad --> function keys F1 through F10. *)
- (* The right half of the keypad --> function keys Alt F1 thru *)
- (* Alt F10. *)
- (* *)
- (* For convenience, the arrow keys can also be used to generate *)
- (* the same codes as the arrows from the function keys. *)
- (* *)
- (* For those VT52 keypad keys which are double-sized, two adjacent *)
- (* function keys will send the same codes. *)
- (* *)
- (* Note that the function keys are always in keypad application *)
- (* mode. Numeric codes can be sent using the regular PC keypad. *)
- (* *)
- (*----------------------------------------------------------------------*)
-
- Procedure Get_Async_Integer( Var Integr: Integer );
-
- (*----------------------------------------------------------------------*)
- (* *)
- (* Procedure: Get_Async_Integer *)
- (* *)
- (* Purpose: Gets integer in biased VT52 form from COM port *)
- (* *)
- (* Calling sequence: *)
- (* *)
- (* Get_Async_Integer( Var Integr: Integer ); *)
- (* *)
- (* Integr: Returned integer value *)
- (* *)
- (* Calls: None *)
- (* *)
- (* Called by: Convert_VT52_Kbd *)
- (* Convert_VT52_Comm *)
- (* *)
- (* Remarks: *)
- (* *)
- (* The screen positions on the VT52 are expressed in excess 31 *)
- (* notation. That is, the value 31 is added to each row and *)
- (* column value. *)
- (* *)
- (*----------------------------------------------------------------------*)
-
- Var
- C : Char;
-
- Begin (* Get_Async_Integer *)
-
- Repeat
- Until( Async_Receive( C ) );
-
- Integr := ORD( C ) - 31;
-
- End (* Get_Async_Integer *);
-
-
- (*----------------------------------------------------------------------*)
- (* Emulate_VT52 -- Controls VT52 emulation *)
- (*----------------------------------------------------------------------*)
-
- Procedure Emulate_VT52;
-
- (* Routine: Emulate_VT52 *)
- (* *)
- (* Purpose: Controls VT52 terminal emulation *)
- (* *)
- (* Calling Sequence: *)
- (* *)
- (* Emulate_VT52; No arguments *)
- (* *)
- (* Calls: *)
- (* *)
- (* Convert_VT52_kbd Maps PC input to VT52 codes *)
- (* Convert_VT52_Comm Maps received VT52 codes to PC *)
- (* *)
- (* Called by: PIBTERM *)
- (* *)
- (* Remarks: *)
- (* *)
- (* (1) The graphics characters produced in graphics mode are *)
- (* VT100 graphics characters. This is what many VT100s *)
- (* and compatibles produce in VT52 mode. *)
- (* *)
- (* (2) Tab positions on the VT52 are located in fixed positions. *)
- (* Those are the positions used here. Some VT52-like *)
- (* terminals allow user-settable tabs. Those are not *)
- (* implemented here. *)
- (* *)
-
- Const
- ON = TRUE (* Convenient synonym for switches *);
- OFF = FALSE (* Likewise *);
-
- Var
- Comm_Ch : Char (* Character read from comm port *);
- Kbd_Ch : Char (* Character read from keyboard *);
- VT52_Graphics_Mode : Boolean (* TRUE if VT52 graphics mode on *);
- VT52_KeyPad : Boolean (* TRUE if alternate keypad in use *);
- Done : Boolean (* TRUE to stop PIBTERM *);
- B : Boolean (* General purpose flag *);
- Graph_Ch : Byte (* Graphics character *);
- Itab : Byte (* Tab stop *);
- Tabcol : Byte (* Tab column *);
- Curcol : Byte (* Current column in display *);
- Auto_Print_Mode : Boolean (* If auto print mode in effect *);
- Printer_Ctrl_Mode : Boolean (* If printer controller mode on *);
- Print_Line : String[80] (* Line to print if print mode on *);
-
- Const
- Graphics_Chars: Array[ 95 .. 126 ] Of Byte
- = ( 32, 4, 177, 9, 12, 13, 10, 248, 241,
- 10, 10, 217, 191, 218, 192, 197, 196, 196,
- 196, 196, 95, 195, 180, 193, 194, 179, 243,
- 242, 227, 168, 156, 250 );
-
- Number_VT52_Tabs = 16;
-
- VT52_Tabs: Array[ 1 .. Number_VT52_Tabs ] Of Byte
- = ( 9, 17, 25, 33, 41, 49, 57, 65, 73, 74, 75, 76, 77,
- 78, 79, 80 );
-
-
- Procedure Convert_VT52_Comm;
-
- (* *)
- (* Routine: Convert_VT52_Comm *)
- (* *)
- (* Purpose: Executes incoming VT52 escape sequences *)
- (* *)
- (* *)
- (* Calling Sequence: *)
- (* *)
- (* Convert_VT52_Comm; -- no parameters -- *)
- (* *)
- (* Calls: None *)
- (* *)
- (* Called by: Emulate_VT52 *)
- (* *)
- (* Remarks: *)
- (* *)
- (* This routine assumes that a CHR(27) (Escape) was just read. *)
- (* The following character is assumed to be a VT52 code. *)
- (* *)
-
- Var
- Ch: Char;
- X: Integer;
- Y: Integer;
- Y2: Integer;
- B: Boolean;
-
- Begin (* Convert_VT52_Comm *)
-
- Repeat
- Until( Async_Receive( Ch ) );
-
- Case CH Of
-
- 'A': Begin (* Move cursor up *)
- GoToXY( Wherex, Max( WhereY - 1 , 1 ) );
- End;
-
- 'B': Begin (* Move cursor down *)
- GoToXY( Wherex, Min( WhereY + 1 , 25 ) );
- End;
-
- 'C': Begin (* Move cursor left *)
- GoToXY( Max( Wherex - 1 , 1 ), WhereY );
- End;
-
- 'D': Begin (* Move cursor right *)
- GoToXY( Min( WhereX + 1 , 80 ), WhereY );
- End;
-
- 'F': VT52_Graphics_Mode := TRUE;
-
- 'G': VT52_Graphics_Mode := FALSE;
-
- 'H': GoToXY( 1 , 1 );
-
- 'I': Begin
- X := WhereX;
- Y := WhereY - 1;
- IF y > 0 Then
- GoToXY( X , Y )
- Else
- Scroll( 1, 25, 1, 80, -1 );
- End;
-
- 'J': Begin (* Clear to End of Screen *)
-
- X := WhereX;
- Y := WhereY;
-
- ClrEol;
-
- For Y2 := ( Y + 1 ) To 25 Do
- Begin
- GoToXY( 1 , Y2 );
- ClrEol;
- End;
-
- GoToXY( X , Y );
-
- End;
-
- 'K': ClrEol (* Clear to End of Line *);
-
- 'W': Printer_Ctrl_Mode := ON;
-
- 'X': Printer_Ctrl_Mode := OFF;
-
- 'Y': Begin (* Move to screen position *)
- Get_Async_Integer( Y );
- Get_Async_Integer( X );
-
- Y := MAX( 1 , MIN( Y , 25 ) );
- X := MAX( 1 , MIN( X , 80 ) );
-
- GoToXY( X , Y );
- End;
-
- 'Z': Async_Send_String( Chr(27) + '/Z' ) (* Identify *);
-
- '=': VT52_Keypad := ON (* Enter keypad mode *);
-
- '>': VT52_Keypad := OFF (* Exit keypad mode *);
-
- ']': Print_Screen;
-
- '-': Auto_Print_Mode := OFF;
-
- '^': Auto_Print_Mode := ON;
-
- Else
- ;
-
- End (* Case CH *);
-
-
- End (* Convert_VT52_Comm *);
-
- (*----------------------------------------------------------------------*)
- (* Convert_VT52_Kbd -- Controls VT52 keyboard emulation *)
- (*----------------------------------------------------------------------*)
-
- Procedure Convert_VT52_Kbd( Var Done : Boolean );
-
- (* *)
- (* Routine: Convert_VT52_Kbd *)
- (* *)
- (* Purpose: Convert PC keyboard codes to VT52 escape sequences *)
- (* *)
- (* Calling Sequence: *)
- (* *)
- (* Convert_VT52_Kbd( Var Done: Boolean ); *)
- (* *)
- (* Done --- set TRUE if ALtX encountered *)
- (* *)
- (* Calls: None *)
- (* *)
- (* Called by: Emulate_VT52 *)
- (* *)
- (* Remarks: *)
- (* *)
- (* A more efficient method of writing this routine would be to *)
- (* use a simple replace via table lookup of the PC code by the *)
- (* VT52 code. *)
- (* *)
-
- Const
- Esc_Ch = ^[;
- Esc_Ch_Q = ^['?';
-
- Var
- X: Integer;
- Y: Integer;
- Ch: Char;
-
- Begin (* Convert_VT52_Kbd *)
-
- Read( Kbd , Ch );
-
- Case ORD( Ch ) Of
-
- (* Arrows *)
-
- 72: Async_Send_String( Esc_Ch + 'A' ); (* Up Arrow *)
- 80: Async_Send_String( Esc_Ch + 'B' ); (* Down Arrow *)
- 77: Async_Send_String( Esc_Ch + 'C' ); (* Right Arrow *)
- 75: Async_Send_String( Esc_Ch + 'D' ); (* Left Arrow *)
-
- (* VT52_Keypad *)
-
- 59: Async_Send_String( Esc_Ch + 'P' ); (* Blue *)
- 60: Async_Send_String( Esc_Ch + 'Q' ); (* Red *)
- 104: Async_Send_String( Esc_Ch + 'R' ); (* Gray *)
- 105: Async_Send_String( Esc_Ch + 'A' ); (* Up Arrow *)
-
- 61: Async_Send_String( Esc_Ch_Q + 'w' ); (* 7 *)
- 62: Async_Send_String( Esc_Ch_Q + 'x' ); (* 8 *)
- 106: Async_Send_String( Esc_Ch_Q + 'y' ); (* 9 *)
- 107: Async_Send_String( Esc_Ch_Q + 'B' ); (* Down Arrow *)
-
- 63: Async_Send_String( Esc_Ch_Q + 't' ); (* 4 *)
- 64: Async_Send_String( Esc_Ch_Q + 'u' ); (* 5 *)
- 108: Async_Send_String( Esc_Ch_Q + 'v' ); (* 6 *)
- 109: Async_Send_String( Esc_Ch_Q + 'C' ); (* Right Arrow *)
-
- 65: Async_Send_String( Esc_Ch_Q + 'q' ); (* 1 *)
- 66: Async_Send_String( Esc_Ch_Q + 'r' ); (* 2 *)
- 110: Async_Send_String( Esc_Ch_Q + 's' ); (* 3 *)
- 111: Async_Send_String( Esc_Ch_Q + 'D' ); (* Left Arrow *)
-
- 67: Async_Send_String( Esc_Ch_Q + 'p' ); (* 0 *)
- 68: Async_Send_String( Esc_Ch_Q + 'p' ); (* 0 *)
- 112: Async_Send_String( Esc_Ch_Q + 'n' ); (* Period *)
- 113: Async_Send_String( Esc_Ch_Q + 'M' ); (* Enter *)
-
- (* Cursor Movement *)
-
- 79: Async_Send_String( Esc_Ch + 'K' ); (* Erase to EOL *)
- 117: Async_Send_String( Esc_Ch + 'J' ); (* Erase to EOS *)
-
- 71: Async_Send_String( Esc_Ch + 'H' ); (* Home cursor *)
-
- Else
- Process_Command( Done, Ch, TRUE );
-
- End (* Case CH *);
-
-
- End (* Convert_VT52_Kbd *);
-
-
-
- Begin (* Emulate_VT52 *)
- (* Indicate VT52 being simulated *)
- Writeln;
- Writeln('Emulating VT52 Terminal');
-
- (* Initialize terminal state *)
- Done := FALSE;
- VT52_Keypad := OFF;
- VT52_Graphics_Mode := OFF;
- Auto_Print_Mode := OFF;
- Printer_Ctrl_Mode := OFF;
-
- (* Loop over input until done *)
- While ( NOT Done ) DO
- Begin
-
- If KeyPressed Then
- Begin (* KeyPressed *)
-
- Read( Kbd , Comm_Ch );
-
- Case ORD( Comm_Ch ) Of
-
- ESC: Convert_VT52_Kbd( Done );
-
- BS: Begin
- Comm_Ch := BS_Char;
- If Local_Echo Then Write( Comm_Ch );
- Async_Send( Comm_Ch );
- End;
-
- DEL: Begin
- Comm_Ch := Ctrl_BS_Char;
- If Local_Echo Then Write( Comm_Ch );
- Async_Send( Comm_Ch );
- End;
-
- Else
- Begin
- If Local_Echo Then Write( Comm_Ch );
- Async_Send( Comm_Ch );
- End;
-
- End (* CASE ORD( Comm_Ch ) *);
-
- End (* KeyPressed *);
-
- If Async_Receive( Comm_Ch ) Then
-
- Case ORD( Comm_Ch ) Of
-
- ESC: Convert_VT52_Comm;
-
- LF,
- FF,
- VT: Begin (* go down one line *)
- Display_Character( CHR( LF ) );
- If Auto_Print_Mode Then
- Begin
- Get_Screen_Text_Line( Print_Line, WhereY - 1, 1 );
- Writeln( Lst , Print_Line );
- End;
- End (* go down one line *);
-
- HT: Begin (* Convert tabs to sequence of blanks *)
- Curcol := WhereX;
- Itab := 1;
- While( Curcol > VT52_Tabs[Itab] ) Do
- Itab := Itab + 1;
- Tabcol := VT52_Tabs[Itab];
- For Itab := Curcol To ( Tabcol - 1 ) Do
- Write(' ');
- End (* Tabs *);
-
- Else
- If NOT VT52_Graphics_Mode Then
- Display_Character( Comm_Ch )
- Else
- Begin (* Graphics Mode *)
- If ORD( Comm_Ch ) IN [ 95 .. 126 ] Then
- Begin
- Graph_Ch := Graphics_Chars[ ORD( Comm_Ch ) - 95 ];
- Display_Character( CHR( Graph_Ch ) );
- End
- Else
- Display_Character( Comm_Ch );
- End (* Graphics Mode *);
-
- End (* CASE ORD( Comm_Ch ) *);
-
- End (* NOT Done *);
-
- End (* Emulate_VT52 *);