home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckc190.zip / ckocon.c < prev    next >
C/C++ Source or Header  |  1994-10-28  |  180KB  |  5,792 lines

  1. char *connv = "OS/2 CONNECT command 5A(155), 4 Oct 94";
  2.  
  3. /* C K O C O N  --  Kermit connect command for OS/2 systems */
  4.  
  5. /*
  6.   Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
  7.   Columbia University Academic Information Systems, New York City.
  8.  
  9.   Copyright (C) 1985, 1994, Trustees of Columbia University in the City of New
  10.   York.  The C-Kermit software may not be, in whole or in part, licensed or
  11.   sold for profit as a software product itself, nor may it be included in or
  12.   distributed with commercial products or otherwise distributed by commercial
  13.   concerns to their clients or customers without written permission of the
  14.   Office of Kermit Development and Distribution, Columbia University.  This
  15.   copyright notice must not be removed, altered, or obscured.
  16.  
  17.   Originally adapted to OS/2 by Chris Adie of Edinburgh University, Scotland
  18.   (C.Adie@edinburgh.ac.uk), 1988, from UNIX C-Kermit CONNECT module by Frank
  19.   da Cruz, Columbia University.  VT102 terminal emulation originally by Chris
  20.   Adie, 1988 ("If the code looks a bit funny sometimes, it's because it was
  21.   machine translated to C.")
  22.  
  23.   Adapted to C-Kermit 5A by Kai Uwe Rommel (rommel@informatik.tu-muenchen.de),
  24.   1992-93 (present address: rommel@ars.muc.de).
  25.  
  26.   Many changes by Frank da Cruz (fdc@columbia.edu): numerous bug fixes (tabs,
  27.   cursor/attributes save/restore, scrolling, keypad modes, etc), new SET
  28.   TERMINAL commands, TCP/IP TELNET support, printer support, character-set
  29.   support, APC escape sequence handling, print/dump screen, complete rewrite
  30.   of character attribute handling & screen reversal and rollback, addition of
  31.   VT220 and ANSI emulations, keyboard verbs, Compose key, Hebrew features,
  32.   context-sensitive popup screens, cosmetic improvements, commentary, etc:
  33.   1992-present.  (Hopefully much of the funny-looking code looks less
  34.   funny now.)
  35.  
  36.   Additional code by Jeffrey Altman ( p00118@psilink.com ):
  37.   changes to keyboard handling, mouse support, ...: 1993 to present.
  38. */
  39.  
  40. /*
  41.  * =============================#includes=====================================
  42.  */
  43.  
  44. #include "ckcdeb.h"             /* Typedefs, debug formats, etc */
  45. #include "ckcker.h"             /* Kermit definitions */
  46. #include "ckcasc.h"             /* ASCII character symbols */
  47. #include "ckcxla.h"             /* Character set translation */
  48. #include "ckcnet.h"             /* Network support */
  49. #include "ckuusr.h"             /* For terminal type definitions, etc. */
  50. #include "ckocon.h"             /* Keyboard verb definitions */
  51.  
  52. #include <ctype.h>              /* Character types */
  53. #include <io.h>                 /* File io function declarations */
  54. #include <process.h>            /* Process-control function declarations */
  55. #include <stdlib.h>             /* Standard library declarations */
  56. #include <sys/types.h>
  57. #include <sys/stat.h>
  58. #include <stdio.h>
  59. #include <string.h>
  60. #include <assert.h>
  61.  
  62. #ifndef __32BIT__
  63. #define far _far
  64. #define near _near
  65. #define pascal _pascal
  66. #endif /* __32BIT__ */
  67.  
  68. #ifdef OS2MOUSE
  69. #define INCL_MOU
  70. #endif /* OS2MOUSE */
  71.  
  72. #define INCL_NOPM
  73. #define INCL_VIO
  74. #define INCL_ERRORS
  75. #define INCL_DOSPROCESS
  76. #define INCL_DOSSEMAPHORES
  77. #define INCL_DOSDEVIOCTL
  78. #define INCL_WINCLIPBOARD
  79. #include <os2.h>
  80. #undef COMMENT                /* COMMENT is defined in os2.h */
  81.  
  82. #ifdef CK_NETBIOS
  83. #include "ckonbi.h"
  84. extern UCHAR NetBiosRemote[] ;
  85. #endif /* CK_NETBIOS */
  86.  
  87. #ifndef min
  88. #define min(a,b) ((a) <= (b) ? (a) : (b))
  89. #endif /* min */
  90.  
  91. #define MAXCOL 132                      /* Maximum screen columns */
  92. #define MAXROW 255                      /* Maximum screen rows */
  93.  
  94. /*
  95.  * =============================#defines======================================
  96.  */
  97.   
  98. #ifdef TRUE
  99. #undef TRUE
  100. #endif /* TRUE */
  101. #define TRUE 1
  102.  
  103. #ifdef FALSE
  104. #undef FALSE
  105. #endif /* FALSE */
  106. #define FALSE 0
  107.  
  108. #define UPWARD   6            /* Scroll up */
  109. #define DOWNWARD 7            /* Scroll down */
  110. #define LBUFSIZE roll.bufsize        /* Maximum lines in rollback buffer */
  111. /*
  112.  *
  113.  * =============================typedefs======================================
  114.  */
  115. typedef int bool;
  116.  
  117. typedef struct ascreen_rec {    /* Structure for saving screen info */
  118.     unsigned char   ox;
  119.     unsigned char   oy;
  120.     unsigned char   att;
  121.     char            *scrncpy;
  122. } ascreen;
  123.  
  124. /* Key names */
  125.  
  126. static char *keynam[512];        /* Names of keys, by scan code */
  127.  
  128. static struct vik_rec {            /* Very Important Keys - */
  129.     KEY help;                /* We look these up once */
  130.     KEY exit;                /* and remember where they are... */
  131.     KEY upscn;
  132.     KEY dnscn;
  133.     KEY upone;
  134.     KEY dnone;
  135.     KEY homscn;
  136.     KEY endscn;
  137.     KEY hangup;
  138.     KEY xbreak;
  139.     KEY lbreak;
  140.     KEY dump;
  141.     KEY prtscn;
  142.     KEY os2;
  143.     KEY printff;
  144.     KEY flipscn;
  145.     KEY debug;
  146.     KEY reset;
  147.     KEY compose;
  148. } vik;
  149. /*
  150.  *
  151.  * =============================externals=====================================
  152.  */
  153. extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(CHAR);  /* Character set xlate */
  154. extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR);  /* functions. */
  155. extern int language;            /* Current language. */
  156. extern struct langinfo langs[]; /* Language info. */
  157. extern struct csinfo fcsinfo[]; /* File character set info */
  158. extern int tcsr, tcsl;          /* Terminal character sets, remote & local. */
  159.  
  160. extern int tnlm, tn_nlm;        /* Terminal newline mode, ditto for TELNET */
  161. extern int tt_crd;              /* Carriage-return display mode */
  162. extern int tt_bell;             /* How to handle incoming Ctrl-G characters */
  163. extern long     speed, vernum;
  164. extern int      local, escape, duplex, parity, flow, seslog, sessft,
  165.                 cmdmsk, cmask, sosi, xitsta, debses, mdmtyp, carrier, what;
  166. extern int    cflg, cnflg, stayflg;
  167. extern int      network, nettype, ttnproto;
  168.  
  169. #ifndef NOSPL
  170. extern struct mtab *mactab;        /* Main macro table */
  171. extern int nmac;            /* Number of macros */
  172. #endif /* NOSPL */
  173.  
  174. extern KEY      *keymap;
  175. extern MACRO    *macrotab;
  176. extern char     ttname[], sesfil[];
  177. extern void     cc_trap();
  178.  
  179. extern char     *printfile;
  180.  
  181. #ifdef __32BIT__
  182. extern HMTX hmtxScreenSem ;
  183. extern HMUX hmuxKeyStroke ;
  184. #endif /* __32BIT__ */
  185. #ifdef OS2MOUSE 
  186. extern HMTX hmtxMouseSem ;
  187. extern HMOU hMouse ;
  188. #endif /* OS2MOUSE */
  189. /*
  190.  * =============================variables==============================
  191.  */
  192.  
  193. /*
  194.   These are RGB bits for the fore- and background colors in the PC's video
  195.   adapter, 3 bits for each color.  These default values can be changed by the
  196.   SET TERMINAL COLOR command (in ckuus7.c) or by CSI3x;4xm escape sequences
  197.   from the host.
  198. */
  199. #ifdef MONO
  200. int     colornormal     = 0x07;
  201. int     colorunderline  = 0x01;
  202. int     colorreverse    = 0x70;
  203. int     colorstatus     = 0x70;
  204. int     colorhelp       = 0x70;
  205. #else
  206. int     colornormal     = 0x30;
  207. int     colorunderline  = 0x3E;
  208. int     colorreverse    = 0x70;
  209. int     colorstatus     = 0x74;
  210. int     colorhelp       = 0x27;
  211. #endif /* MONO */
  212. int     colorborder     = 0x00;
  213.  
  214. int     colorcmd;
  215. int     scrninitialised = 0;
  216.  
  217. /*
  218.   The video adapter stores each screen character in a two-byte cell.  The
  219.   first byte of each cell contains the 8-bit character value.  The second byte
  220.   contains the video attributes for the character, and looks like this:
  221.  
  222.          Background      Foreground
  223.          Color           Color
  224.     +---+---+---+---+---+---+---+---+
  225.     | b | R | G | B | i | R | G | B |
  226.     +---+---+---+---+---+---+---+---+
  227.       b = blink       i = intensity
  228.       0 = nonblinking 0 = normal
  229.       1 = blinking    1 = high
  230.  
  231.   The i bit applies to the foreground color.  The meaning of the b bit depends
  232.   on the VIO state; it can mean (a) the foreground character blinks, or (b) the
  233.   background color is high-intensity.  C-Kermit uses (b) because blinking only
  234.   works in a fullscreen session.  See the call to VioSetState().  The RGB
  235.   bits select the desired mixture of Red, Green, and Blue.
  236.  
  237.   The swapcolors macro exchanges the fore- and background colors (the RGB
  238.   bits) but leaves the intensity/blink bits where there are.  Thus if the
  239.   foreground color is bold and the background color is not bold, the same
  240.   will be true after swapcolors().
  241. */
  242. #define swapcolors(x) (((x)&(unsigned)0x88)|(((x)&0x70)>>4)|(((x)&0x07)<<4))
  243.  
  244. static int tn_bold = 0;            /* TELNET negotiation bold */
  245. int esc_exit = 0;            /* Escape back = exit */
  246. char * esc_msg;
  247.  
  248. static long waittime;            /* Timeout on CTS during CONNECT */
  249. #define INTERVAL 100L
  250.  
  251. static char termessage[MAXCOL];
  252. static FILE *lst = NULL;        /* List (print) device */
  253. static bool lstclosed = TRUE;        /* List device closed flag */
  254.  
  255. #ifdef CK_APC
  256. extern int apcactive;            /* Application Program Command (APC) */
  257. extern int apcstatus;            /* items ... */
  258. static int apclength = 0;          
  259. #ifdef DCMDBUF
  260. extern char *apcbuf;
  261. #else
  262. extern char apcbuf[];
  263. #endif /* DCMDBUF */
  264. static int apcbuflen = APCBUFLEN - 2;
  265. #endif /* CK_APC */
  266.  
  267. char * keydefptr = NULL;
  268. int keymac = 0;
  269. int keymacx = -1;
  270.  
  271. int
  272.   xsize = -1,                /* Screen width */
  273.   ysize = -1;                /* Screen height */
  274.   
  275. ascreen                    /* For saving screens: */
  276.   vt100screen,                /* terminal screen */
  277.   commandscreen,            /* OS/2 screen */
  278.   savedscreen,                /* (various uses) */
  279.   helpscreen;                /* Screen behind popup help */
  280. extern ascreen mousescreen; /* Screen during mouse actions */
  281.   
  282. static unsigned char            /* Video attribute bytes */
  283.   attribute = NUL,                      /* Current video attribute byte */
  284.   savedattribute = NUL,                 /* Saved video attribute byte */
  285.   defaultattribute = NUL;               /* Default video attribute byte */
  286.   
  287. /*
  288.   Note, the following are related to the VT terminal screen, not the PC video
  289.   adapter.  That is, 'attribute' (above) is the PC video attribute byte,
  290.   'attrib' (below) is the VT terminal attribute structure.  etc.
  291. */
  292. static struct {                         /* Character attributes, 1 bit each */
  293.     unsigned reversed:1;                /* Reverse video */
  294.     unsigned blinking:1;                /* Blinking */
  295.     unsigned underlined:1;              /* Underlined (simulated) */
  296.     unsigned bold:1;                    /* Bold (high intensity) */
  297.     unsigned invisible:1;               /* Invisible */
  298. } attrib, savedattrib;
  299.  
  300. /* Screen rollback buffer, circular... */
  301.  
  302. static struct paging_record {
  303.     int flag;                           /* Nonzero means we are rolled back */
  304.     int numlines;                       /* How many lines saved in buffer */
  305.     int topline;                        /* Index of top line */
  306.     int botline;                        /* Index of bottom line */
  307.     int current;                        /* Index of current line */
  308.     char *buffer;                       /* Pointer to buffer */
  309.     int bufsize;                        /* Size of buffer */
  310.     int linesleft;            /* How many lines above current line */
  311.     int nextline;            /* Next line in rollback buffer */
  312. } roll;
  313.  
  314. int wherex;                /* Screen column, 1-based */
  315. int wherey;                /* Screen row, 1-based */
  316. static int margintop = 1;               /* Top of scrolling region, 1-based */
  317. static int marginbot = 24;              /* Bottom of same, 1-based */
  318.  
  319. static int active, quitnow, hangnow, inshift, outshift, tcs, langsv;
  320.  
  321. static char answerback[81] = "OS/2 C-Kermit\r"; /* Default answerback */
  322. static char usertext[(MAXCOL) + 1];     /* Status line and its parts */
  323. static char statusline[MAXCOL + 1];
  324. static char exittext[(20) + 1];
  325. #define HLPTXTLEN 41
  326. static char helptext[HLPTXTLEN];
  327. static char filetext[(20) + 1];
  328. static char savefiletext[(20) + 1] = { NUL };
  329. #define HSTNAMLEN 41
  330. static char hostname[HSTNAMLEN];
  331.  
  332. static unsigned char graphicset[32] = { /* VT100/200 graphic characters */
  333.     0x20, 0x04, 0xB0, 0x1A, 0x17, 0x1B, 0x19, 0xF8,
  334.     0xF1, 0x15, 0x12, 0xD9, 0xBF, 0xDA, 0xC0, 0xC5,
  335.     0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC3, 0xB4, 0xC1,
  336.     0xC2, 0xB3, 0xF3, 0xF2, 0xE3, 0x9D, 0x9C, 0xFA
  337. };
  338.  
  339. #define DEFTABS \
  340. "0T0000000T0000000T0000000T0000000T0000000T0000000T0000000T0000000T0000000\
  341. T0000000T0000000T0000000T0000000T0000000T0000000T0000000T000";
  342.  
  343. static char htab[133] = DEFTABS         /* Default tab settings */
  344.  
  345. static VIOCURSORINFO crsr_command;
  346. static VIOCURSORINFO crsr_info;
  347.  
  348. static int row = 0;
  349. static int column = 0;
  350. static int achar;
  351.  
  352. static unsigned char g0 = 'B';          /* Default G0 charset is US ASCII. */
  353. static unsigned char g1 = 'B';          /* G1 also. */
  354. static unsigned char *g0g1 = &g0;
  355.  
  356. static bool     printon        = FALSE; /* Printer is on */
  357. static bool     printregion    = FALSE; /* Print extent = full screen */
  358. static bool     xprintff       = FALSE; /* Print formfeed */
  359. static bool     turnonprinter  = FALSE; /* Time to turn on printer */
  360. static bool     xprint         = FALSE; /* Transparent print in progress */
  361. static bool     turnoffprinter = FALSE; /* Time to turn it off */
  362.  
  363. static bool     wrapit    = FALSE;
  364. static bool     literal   = FALSE;
  365. static bool     screenon  = TRUE;
  366. static bool     cursoron  = TRUE;       /* For speed, turn off when busy */
  367. static bool     cursorena = TRUE;       /* Cursor enabled / disabled */
  368. static bool     relcursor = FALSE;
  369. static bool     keylock   = FALSE;
  370. static bool     vt52graphics = FALSE;
  371.  
  372. static unsigned char saveg0, saveg1, *saveg0g1;
  373. static bool     saverelcursor, saved=FALSE;
  374.  
  375. static bool     dwl[MAXROW];        /* Double-width line buffer */
  376. static bool     dwls = FALSE;           /* For optimisation */
  377. static bool     deccolm = FALSE;    /* 80/132-column mode */
  378. static bool     decscnm = FALSE;    /* Normal/reverse screen mode */
  379. static bool     insertmode = FALSE;    /* Insert/replace mode */
  380. /*
  381.   Terminal parameters that can also be set externally by SET commands.
  382.   Formerly they were declared and initialized here, and had different
  383.   names, as shown in the comments.  Now they are declared and
  384.   initialized in ckuus7.c.  - fdc
  385. */
  386. static int my_tt_type;                  /* Prevailing terminal type */
  387. static bool tt_hebrew = 0;        /* Keyboard is in Hebrew mode */
  388. static int c1controls;                  /* Flag for C1 controls allowed */
  389. static bool send_c1 = FALSE;        /* Flag for sending C1 controls */
  390.  
  391. /*
  392.   VT220 and higher Pn's for terminal ID string are (* = Not supported):
  393.   *  1 - 132 columns
  394.      2 - Printer port
  395.   *  3 - ReGIS graphics
  396.   *  4 - Sixel graphics
  397.   *  6 - DECSED - Selective erase
  398.   *  7 - DRCS - Soft character sets
  399.   *  8 - UDK - User-defined keys
  400.   *  9 - National Replacement Character Sets can be designated by host
  401.   * 13 - Local editing
  402.     15 - Technical character set
  403.   * 18 - Windowing Capability
  404.   * 19 - Dual sessions
  405. */
  406. struct tt_info_rec tt_info[] = {        /* Indexed by terminal type */
  407.   "NONE",      "",                      /* None */
  408.   "VT52",      "/Z",                    /* DEC VT52 */
  409.   "ANSI",      "",            /* "ANSI" (BBS) */
  410.   "VT100",     "[?1c",                  /* DEC VT100 */
  411.   "VT102",     "[?6c",                  /* DEC VT102 */
  412.   "VT220",     "[?62;2;15c"             /* DEC VT220 */
  413. #ifdef COMMENT
  414. , "VT320"      "[?63;2;15c",            /* DEC VT320 */
  415. #endif /* COMMENT */
  416. };
  417. int max_tt = TT_VT320;                  /* Highest terminal type */
  418.  
  419. /* SET TERMINAL values ... */
  420.  
  421. extern int tt_arrow;            /* Arrow-key mode */
  422. extern int tt_keypad;            /* Keypad mode */
  423. extern int tt_wrap;            /* Autowrap */
  424. extern int tt_type;            /* Terminal type */
  425. extern int tt_cursor;            /* Cursor type */
  426. extern int tt_answer;            /* Answerback enabled/disabled */
  427. extern int tt_scrsize;            /* Scrollback buffer size */
  428. extern int tt_roll;            /* Scrollback style */
  429. extern int tt_rows;            /* Screen rows */
  430. extern int tt_cols;            /* Screen columns */
  431. extern int tt_ctstmo;            /* CTS timeout */
  432. extern int tt_hide;            /* Hide-cursor */
  433. extern int tt_pacing;            /* Output-pacing */
  434. extern int tt_mouse;            /* Mouse */
  435.  
  436. /* Escape-sequence parser state definitions. */
  437. /* For explanation, see ckucon.c, where this code is copied from. */
  438.  
  439. #define ES_NORMAL 0                     /* Normal, not in escape sequence */
  440. #define ES_GOTESC 1                     /* Current character is ESC */
  441. #define ES_ESCSEQ 2                     /* Inside an escape sequence */
  442. #define ES_GOTCSI 3                     /* Inside a control sequence */
  443. #define ES_STRING 4                     /* Inside DCS,OSC,PM, or APC string */
  444. #define ES_TERMIN 5                     /* 1st char of string terminator */
  445.  
  446. #define ESCBUFLEN 128
  447.  
  448. static int      escstate = ES_NORMAL;
  449. static int      escnext = 1;
  450. static int      esclast = 0;
  451.  
  452. /* Escape-sequence processing buffer */
  453.  
  454. static unsigned char escbuffer[ESCBUFLEN+1];
  455.  
  456. /*
  457.    For pushing back input characters,
  458.    e.g. converting 8-bit controls to 7-bit escape sequences.
  459. */
  460. static int f_pushed = 0, c_pushed = 0, f_popped = 0;
  461.  
  462. static unsigned char sgrcols[8] = {0, 4, 2, 6, 1, 5, 3, 7};
  463.  
  464. /* Function prototypes */
  465.  
  466. static CHAR (*sxo)(CHAR); /* Character translation functions */
  467. static CHAR (*rxo)(CHAR); /* for output (sending) terminal chars */
  468. static CHAR (*sxi)(CHAR); /* and for input (receiving) terminal chars. */
  469. static CHAR (*rxi)(CHAR);
  470.  
  471. #ifndef NOTTOCI
  472. int ttoci(char c);
  473. #endif /* NOTTOCI */
  474.  
  475. static int popuphelp(int);        /* Pop-up help panel maker */
  476.  
  477. static void ipadl25(void);        /* Default status-line maker */
  478. static void line25(void);        /* General-purpose status-line maker */
  479. static void xline25(char *);
  480. static void save_status_line(void);
  481. static void restore_status_line(void);
  482. static void resethebrewmode(void);
  483. static int status_saved = -1;
  484.  
  485. int restorescreen(ascreen *);
  486. static int sendchar(unsigned char);
  487.  
  488. static void bleep(void);
  489. static void checkscreenmode(void);
  490. static void clearscreen(int, int);
  491. static void clrtoeoln(void);
  492. static void doesc(int c);
  493. static void esc25(int);
  494. static void flipscreen(void);
  495. static void helpline(char *);
  496. static void killcursor(void);
  497. static void lgotoxy(int, int);
  498. static void movetoscreen(char *, int, int, int);
  499. static void newcursor(void);
  500. static void printeron(void);
  501. static void printeroff(void);
  502. static void prtscreen(int, int);
  503. static void restorecursormode(void);
  504. void savescreen(ascreen *, int, int);
  505. static void scroll(int, int, int, int);
  506. static void scrollback(int);
  507. static void setcursormode(void);
  508. static void setmargins(int, int);
  509. static void strinsert(char *, char *);
  510. static void toplinetocyclicbuffer(void);
  511. static void wrtch(char);
  512. static int sendescseq(char *);
  513.  
  514. int ckcgetc(int);
  515. void cwrite(unsigned char);
  516.  
  517. extern int concooked(void);
  518. extern int conraw(void);
  519. extern int xxesc(char **);
  520.  
  521. /* Thread stuff... */
  522.  
  523. #ifdef __32BIT__
  524. HEV threadsem, threadsem2 ;
  525. ULONG semcount, semcount2;
  526. #define THRDSTKSIZ      131072  /* Needed for Mouse Thread */
  527. #else
  528. static long int threadsem, threadsem2;    /* Semaphore for thread running */
  529. #define THRDSTKSIZ      2048
  530. static char            stack[THRDSTKSIZ];       /* Stack for second thread */
  531. static char            stack2[THRDSTKSIZ];       /* Stack for third thread */
  532. #endif /* __32BIT__ */
  533. static TID             threadid,threadid2;
  534.  
  535. static int
  536. #ifdef COMMENT
  537.   iskipesc = 0,                         /* Skip over ANSI escape sequences */
  538.   inesc = ES_NORMAL,                    /* State of sequence recognizer */
  539. #endif /* COMMENT */
  540.   oskipesc = 0,                         /* Esc seq recognizer for keys... */
  541.   outesc = ES_NORMAL;
  542.  
  543. /*
  544.    C H K A E S  --  Check ANSI Escape Sequence state.
  545.    Previously used for both input and output, now (edit 190) used only
  546.    for output of keystrokes.  Input is handled in cwrite().
  547. */
  548. int
  549. chkaes(int esc, char c) {
  550.     if (c == CAN || c == SUB)           /* CAN and SUB cancel any sequence */
  551.       esc = ES_NORMAL;
  552.     else                                /* Otherwise */
  553.       switch (esc) {                    /* enter state switcher */
  554.  
  555.         case ES_NORMAL:                 /* NORMAL state */
  556.           if (c == ESC)                 /* Got an ESC */
  557.             esc = ES_GOTESC;            /* Change state to GOTESC */
  558.           break;                        /* Otherwise stay in NORMAL state */
  559.  
  560.         case ES_GOTESC:                 /* GOTESC state */
  561.           if (c == '[')                 /* Left bracket after ESC is CSI */
  562.             esc = ES_GOTCSI;            /* Change to GOTCSI state */
  563.           else if (c == 'P' || (c > 0134 && c < 0140)) /* P, ], ^, or _ */
  564.             esc = ES_STRING;            /* Switch to STRING-absorption state */
  565.           else if (c > 057 && c < 0177) /* Final character '0' thru '~' */
  566.             esc = ES_NORMAL;            /* Back to normal */
  567.           else if (c != ESC)            /* ESC in an escape sequence... */
  568.             esc = ES_ESCSEQ;            /* starts a new escape sequence */
  569.           break;                        /* Intermediate or ignored ctrl char */
  570.  
  571.         case ES_ESCSEQ:                 /* ESCSEQ -- in an escape sequence */
  572.           if (c > 057 && c < 0177)      /* Final character '0' thru '~' */
  573.             esc = ES_NORMAL;            /* Return to NORMAL state. */
  574.           else if (c == ESC)            /* ESC ... */
  575.             esc = ES_GOTESC;            /* starts a new escape sequence */
  576.           break;                        /* Intermediate or ignored ctrl char */
  577.  
  578.         case ES_GOTCSI:                 /* GOTCSI -- In a control sequence */
  579.           if (c > 077 && c < 0177)      /* Final character '@' thru '~' */
  580.             esc = ES_NORMAL;            /* Return to NORMAL. */
  581.           else if (c == ESC)            /* ESC ... */
  582.             esc = ES_GOTESC;            /* starts over. */
  583.           break;                        /* Intermediate or ignored ctrl char */
  584.  
  585.         case ES_STRING:                 /* Inside a string */
  586.           if (c == ESC)                 /* ESC may be 1st char of terminator */
  587.             esc = ES_TERMIN;            /* Go see. */
  588.           break;                        /* Absorb all other characters. */
  589.  
  590.         case ES_TERMIN:                 /* May have a string terminator */
  591.           if (c == '\\')                /* which must be backslash */
  592.             esc = ES_NORMAL;            /* If so, back to NORMAL */
  593.           else                          /* Otherwise */
  594.             esc = ES_STRING;            /* Back to string absorption. */
  595.       }
  596.     return(esc);
  597. }
  598.  
  599. /* ------------------------------------------------------------------ */
  600. /* ipadl25 - Make normal CONNECT-mode status line                     */
  601. /* ------------------------------------------------------------------ */
  602. static void
  603. ipadl25() {
  604.     int i, j, n;
  605.     char *s, *p;
  606.     strcpy(usertext," C-Kermit ");
  607.     if (debses)
  608.       strcat(usertext,"DEBUG");
  609.     else if (tt_type > -1 && tt_type <= max_tt)
  610.       strcat(usertext,tt_info[tt_type].x_name);
  611.     if (tt_hebrew)
  612.       strcat(usertext,"-H");
  613.     if (printon) {
  614.     strcpy(filetext,"PRINTER ON");
  615.     } else if ( !network )
  616.       sprintf(filetext, "Serial %ld", speed);
  617.     else
  618.       switch ( nettype ) {
  619.         case NET_DEC:
  620.           switch ( ttnproto ) {
  621.             case NP_LAT:
  622.               strcpy(filetext, "DECnet LAT");
  623.               break;
  624.             case NP_CTERM:
  625.               strcpy(filetext, "DECnet CTERM");
  626.               break;
  627.             default:
  628.               strcpy(filetext, "DECnet");
  629.               break;
  630.           }
  631.         break;
  632.       case NET_TCPB:
  633.         switch ( ttnproto ) {
  634.           case NP_TELNET:
  635.             strcpy(filetext, "TELNET");
  636.             break;
  637.           default:
  638.             strcpy(filetext, "TCP/IP");
  639.             break;
  640.         }
  641.         break;
  642.       case NET_PIPE:
  643.         strcpy(filetext, "Named Pipe");
  644.         break;
  645.       case NET_BIOS:
  646.         strcpy(filetext, "NetBIOS");
  647.         break;
  648.       }
  649.  
  650.     if (vik.help > 255 && keynam[vik.help - 256])
  651.       sprintf(helptext, "Help: %s", keynam[vik.help - 256]);
  652.     else
  653.       sprintf(helptext, "Help: ^%c?", ctl(escape));
  654.  
  655.     if (vik.exit > 255 && keynam[vik.exit - 256])
  656.       sprintf(exittext, "%s %s", esc_msg, keynam[vik.exit - 256]);
  657.     else
  658.       sprintf(exittext, "%s ^%c?", esc_msg, ctl(escape));
  659.  
  660.     strncpy(hostname, ttname, 40);
  661. #ifdef CK_NETBIOS
  662.     if ( ( nettype == NET_BIOS ) && ( *ttname == '*' ) )
  663.        strncpy(hostname+1, NetBiosRemote, NETBIOS_NAME_LEN ) ;
  664. #endif /* CK_NETBIOS */
  665.     if (!network)
  666.       strupr(hostname);
  667.     line25();
  668. }
  669.  
  670. /* ------------------------------------------------------------------ */
  671. /* CursorUp -                                                         */
  672. /* ------------------------------------------------------------------ */
  673. static void
  674. cursorup() {
  675.     if ((relcursor ? margintop : 1) != wherey)
  676.     lgotoxy(wherex, wherey - 1);
  677. }
  678.  
  679. /* ------------------------------------------------------------------ */
  680. /* CursorDown -                                                       */
  681. /* ------------------------------------------------------------------ */
  682. static void
  683. cursordown() {
  684.     if ((relcursor ? marginbot : ysize) != wherey)
  685.     lgotoxy(wherex, wherey + 1);
  686. }
  687.  
  688. /* ------------------------------------------------------------------ */
  689. /* CursorRight -                                                      */
  690. /* ------------------------------------------------------------------ */
  691. static void
  692. cursorright() {
  693.     if (wherex < (dwl[wherey - 1] ? xsize - 1 : xsize))
  694.     lgotoxy(wherex + 1, wherey);
  695. }
  696.  
  697. /* ------------------------------------------------------------------ */
  698. /* CursorLeft -                                                       */
  699. /* ------------------------------------------------------------------ */
  700. static void
  701. cursorleft() {
  702.     if (wherex > 1)
  703.     lgotoxy(wherex - 1, wherey);
  704. }
  705.  
  706. /* ------------------------------------------------------------------ */
  707. /* ReverseScreen                              */
  708. /* fixed by fdc, edit 190                          */
  709. /* ------------------------------------------------------------------ */
  710. static void
  711. reversescreen() {
  712.     int             i, r, c, x;
  713.     USHORT          n;
  714.     unsigned char   cell[MAXCOL * 2];
  715.  
  716. #ifdef OS2MOUSE
  717.    os2_mousehide() ;
  718. #endif /* OS2MOUSE */
  719.     n = xsize * 2;
  720.     for (r = 0; r < ysize; r++) {       /* Loop for each row */
  721.     VioReadCellStr(cell, &n, r, 0, 0); /* Read this row from the screen */
  722.     for (c = 0; c < xsize; c++) {       /* Loop for each character in row */
  723.         x = c + c + 1;           /* Location of attribute byte */
  724.         cell[x] = swapcolors(cell[x]);
  725.     }
  726.    VioWrtCellStr(cell, n, r, 0, 0); /* Write the row back. */
  727.     }
  728. #ifdef OS2MOUSE
  729.    os2_mouseshow() ;
  730. #endif
  731. }
  732.  
  733. void
  734. reverserange( SHORT fromrow, SHORT fromcol, SHORT torow, SHORT tocol ) {
  735.     int             r, c;
  736.     SHORT           temp;
  737.     USHORT          n;
  738.     unsigned char   cell[2];
  739.     unsigned char   D[80];
  740.  
  741. #ifdef OS2MOUSE
  742.     os2_mousehide() ;
  743. #endif /* OS2MOUSE */
  744.  
  745.     sprintf( D, "ReverseRange: from (%d,%d) to (%d,%d)",
  746.         fromrow,fromcol,torow,tocol);
  747.     debug(F100,D,"",0);
  748.  
  749.     if ( fromrow > torow || ( fromrow == torow && fromcol > tocol ) ) {
  750.     temp = fromcol ;
  751.     fromcol = tocol ;
  752.     tocol = temp ;
  753.     }
  754.     if ( fromrow > torow ) {
  755.     temp = fromrow ;
  756.     fromrow = torow ;
  757.     torow = temp ;
  758.     }
  759.     for ( r = fromrow ; r <= torow ; r++ ) {
  760.     for ( c = ( r==fromrow ? fromcol : 0 ) ;
  761.          c <= ( r == torow ? tocol : xsize -1 ) ;
  762.          c++ ) {
  763.         n = 2 ;
  764.         VioReadCellStr(cell, &n, r, c, 0 ) ;
  765.         cell[1] = swapcolors(cell[1]) ;
  766.         VioWrtCellStr( cell, n, r, c, 0 ) ;
  767.     }
  768.     }
  769. #ifdef OS2MOUSE
  770.     os2_mouseshow() ;
  771. #endif
  772. }
  773.  
  774. static void                /* Flip screen between */
  775. flipscreen() {                /* normal and reverse video */
  776.     unsigned char fg, bg;
  777.     reversescreen();
  778.     if (decscnm) {            /* Currently reverse-video? */
  779.         defaultattribute = colornormal;    /* Yes, go back to normal color */
  780.         decscnm = FALSE;        /* Change DECSCNM value */
  781.     } else {    
  782.         defaultattribute = swapcolors(colornormal);
  783.         decscnm = TRUE;
  784.     }
  785.     /* Subsequent chars are written with current attributes, colors swapped. */
  786.     attribute = swapcolors(attribute);
  787.     colorunderline = swapcolors(colorunderline);
  788. }
  789.  
  790. /* ----------------------------------------------------------------- */
  791. /* ClrScreen -                                                       */
  792. /* ----------------------------------------------------------------- */
  793. static void
  794. clrscreen() {
  795.     int             i, j;
  796.     int             nlines;
  797.     USHORT          n;
  798.     char            cells[MAXCOL * 2];
  799.  
  800. #ifdef OS2MOUSE
  801.     os2_mousehide() ;
  802. #endif
  803.     /* Copy lines on screen to extended display buffer */
  804.  
  805.     n = xsize * 2;            /* Size of screen-line buffer */
  806.     for (i = ysize - 1; i >= 0; i--) {    /* Start at screen bottom */
  807.     VioReadCellStr((char *) cells, &n, i, 0, 0); /* Get screen line */
  808.     for (j = 0; j < xsize; j++) {    /* Look at the characters in it */
  809.         if (cells[j * 2] != ' ')    /* Is this one nonblank? */
  810.           break;            /* Yes, stop looking at this line */
  811.     }
  812.     if (j < xsize)            /* If this is a nonblank line, */
  813.       break;            /* quit the big loop too. */
  814.     }
  815.  
  816.     /* Now we've located the lowest nonblank line */
  817.  
  818.     nlines = i;                /* Number of lines to clear, minus 1 */
  819.     for (i = 0; i <= nlines; ++i) {
  820.     roll.botline = (roll.botline + 1) % LBUFSIZE;
  821.     if (roll.numlines < LBUFSIZE)
  822.       roll.numlines++;
  823.     else
  824.       roll.topline = (roll.topline + 1) % LBUFSIZE;
  825.     VioReadCellStr((roll.buffer + xsize * 2 * roll.botline),&n, i, 0, 0);
  826.     }
  827.     for (i = 0; i < ysize; i++)
  828.       dwl[i] = FALSE;
  829.     dwls = FALSE;
  830.     clearscreen(0, defaultattribute);
  831. #ifdef OS2MOUSE
  832.     os2_mouseshow() ;
  833. #endif
  834. }
  835.  
  836. /* ----------------------------------------------------------------- */
  837. /* PrtScreen - Copy lines on screen to printer.                      */
  838. /* parameters = Top line to print, bottom line to print, 1-based.    */
  839. /* ----------------------------------------------------------------- */
  840. static void             
  841. prtscreen(int top, int bot) {
  842.     int    i, j, first, last;
  843.     USHORT n;
  844.     char   cells[MAXCOL * 2];
  845.     char   outbuf[MAXCOL + 1];       
  846.  
  847.     if (printon)            /* Printer already on? */
  848.       return;
  849.     if (top < 1 || bot > ysize)        /* Args out of bounds? */
  850.       return;
  851.  
  852.     printeron();            /* Turn on printer */
  853. #ifdef OS2MOUSE
  854.     os2_mousehide() ;
  855. #endif
  856.     if (lst) {                /* If printer on */
  857.     n = xsize * 2;            /* Line width, incl attributes */
  858.     for (i = top; i <= bot; i++) {  /* For each screen line, i... */
  859.         /* Internally, screen lines are 0-based, so "i-1". */
  860.         VioReadCellStr((char *) cells, &n, i-1, 0, 0); /* Get line i */
  861.         for (j = 0; j < xsize; j++)    /* Strip away the attribute bytes */
  862.           outbuf[j] = cells[j+j];
  863.             for (j = xsize - 1; j >= 0; j--) /* Strip trailing blanks */
  864.           if (outbuf[j] != SP) break;
  865.         outbuf[j+1] = NUL;        /* Terminate with NUL */
  866.         fprintf(lst,"%s\r\n",outbuf); /* Print the line */
  867.     }
  868.     if (xprintff /* && top == 1 && bot == ysize */ )
  869.       fprintf(lst,"%c",FF);
  870. #ifdef OS2MOUSE
  871.     os2_mouseshow() ;
  872. #endif
  873.     printeroff();
  874.     }
  875. }
  876.  
  877. static int
  878. pnumber(int *achar) {
  879.     int num = 0;
  880.     while (isdigit(*achar)) {        /* Get number */
  881.     num = (num * 10) + (*achar) - 48;
  882.     *achar = (escnext<=esclast)?escbuffer[escnext++]:0;
  883.     }
  884.     return (num);
  885. }
  886.  
  887. static void
  888. clreoscr_escape() {
  889.     char cell[2];
  890.     int i;
  891.  
  892.     if (wherex == 1 && wherey == 1) {
  893.     clrscreen();
  894.     return;
  895.     }
  896.     cell[0] = ' ';
  897. #ifdef COMMENT
  898. /* Wrong!  - fdc */
  899.     cell[1] = attribute;
  900. #else
  901.     cell[1] = defaultattribute;
  902. #endif /* COMMENT */
  903.     i = (xsize * ysize) - (((wherey - 1) * xsize) + (wherex - 1));
  904. #ifdef OS2MOUSE
  905.     os2_mousehide() ;
  906. #endif /* OS2MOUSE */
  907.     VioWrtNCell(cell, i, wherey - 1, wherex - 1, 0);
  908. #ifdef OS2MOUSE
  909.     os2_mouseshow() ;
  910. #endif
  911.     for (i = wherey - 1; i < ysize; i++)
  912.     dwl[i] = FALSE;
  913.     dwls = FALSE;
  914.     for (i = 0; i < ysize; i++)
  915.     if (dwl[i]) {
  916.         dwls = TRUE;
  917.         break;
  918.     }
  919. }
  920.  
  921. static void
  922. clrboscr_escape() {
  923.     char cell[2];
  924.     int i;
  925.  
  926.     cell[0] = ' ';
  927. #ifdef COMMENT
  928. /* Wrong!  - fdc */
  929.     cell[1] = attribute;
  930. #else
  931.     cell[1] = defaultattribute;
  932. #endif /* COMMENT */
  933.     i = ((wherey - 1) * xsize) + wherex;
  934. #ifdef OS2MOUSE
  935.     os2_mousehide() ;
  936. #endif /* OS2MOUSE */
  937.     VioWrtNCell(cell, i, 0, 0, 0);
  938. #ifdef OS2MOUSE
  939.     os2_mouseshow() ;
  940. #endif
  941.     for (i = 0; i < wherey; i++)
  942.       dwl[i] = FALSE;
  943.     dwls = FALSE;
  944.     for (i = 0; i < ysize; i++)
  945.       if (dwl[i]) {
  946.       dwls = TRUE;
  947.       break;
  948.       }
  949. }
  950.  
  951. static void
  952. clrbol_escape() {
  953.     char cell[2];
  954.  
  955.     cell[0] = ' ';
  956. #ifdef COMMENT
  957.     cell[1] = attribute;
  958. #else
  959.     cell[1] = defaultattribute;
  960. #endif /* COMMENT */
  961. #ifdef OS2MOUSE
  962.     os2_mousehide() ;
  963. #endif /* OS2MOUSE */
  964.     VioWrtNCell(cell, wherex, wherey - 1, 0, 0);
  965. #ifdef OS2MOUSE
  966.     os2_mouseshow() ;
  967. #endif
  968. }
  969.  
  970. static void
  971. clrline_escape() {
  972.     char cell[2];
  973.  
  974.     cell[0] = ' ';
  975. #ifdef COMMENT
  976.     cell[1] = attribute;
  977. #else
  978.     cell[1] = defaultattribute;
  979. #endif /* COMMENT */
  980. #ifdef OS2MOUSE
  981.     os2_mousehide() ;
  982. #endif /* OS2MOUSE */
  983.     VioWrtNCell(cell, xsize, wherey - 1, 0, 0);
  984. #ifdef OS2MOUSE
  985.     os2_mouseshow() ;
  986. #endif
  987. }
  988.  
  989. static void
  990. decdwl_escape(bool dwlflag) {
  991.     unsigned char   linenumber;
  992.     unsigned char   newx;
  993.     char            cells[MAXCOL * 2];
  994.     int             i;
  995.     USHORT          n;
  996.  
  997. #ifdef OS2MOUSE
  998.     os2_mousehide() ;
  999. #endif /* OS2MOUSE */
  1000.  
  1001.    /* DECDWL */
  1002.     linenumber = wherey - 1;
  1003.     if (dwlflag != dwl[linenumber]) {
  1004.     /* change size */
  1005.     n = xsize * 2;
  1006.     VioReadCellStr((char *) cells, &n, linenumber, 0, 0);
  1007.     if (dwlflag) {            /* Make this line double size */
  1008.         for (i = xsize / 2 - 1; i >= 0; --i) { /* Expand */
  1009.         cells[4 * i] = cells[2 * i];
  1010.         cells[4 * i + 2] = ' ';
  1011.         }
  1012.         newx = (wherex - 1) * 2 + 1;
  1013.         dwls = TRUE;
  1014.     } else {            /* Make this line single size */
  1015.         for (i = 0; i <= xsize / 2 - 1; ++i)
  1016.           cells[2 * i] = cells[4 * i];
  1017.         for (i = xsize / 2; i < xsize; ++i)
  1018.           cells[2 * i] = ' ';
  1019.         newx = (wherex - 1) / 2 + 1;
  1020.         dwls = FALSE;
  1021.         for (i = 0; i < ysize; i++)
  1022.           if (dwl[i]) {
  1023.           dwls = TRUE;
  1024.           break;
  1025.           }
  1026.     }
  1027.     VioWrtCellStr((char *) cells, n, linenumber, 0, 0);
  1028.     dwl[linenumber] = dwlflag;
  1029.     if (newx >= xsize)
  1030.       newx = xsize - 1;
  1031.     lgotoxy(newx, wherey);
  1032.     }
  1033. #ifdef OS2MOUSE
  1034.     os2_mouseshow() ;
  1035. #endif
  1036. }
  1037.  
  1038. static void
  1039. printeron() {
  1040.     if (printon)            /* It's already on. */
  1041.       return;
  1042.     if (lstclosed || !lst) {        /* Open printer device */
  1043.     if (!printfile)            /* If printer not redirected */
  1044.       lst = fopen("prn", "w");    /* open the PRN device */
  1045.     else                /* otherwise */
  1046.       lst = fopen(printfile, "ab"); /* open the file in append mode. */
  1047.     }
  1048.     if (lst) {                /* Open OK? */
  1049.     strcpy(savefiletext,filetext);
  1050.     strcpy(filetext,"PRINTER ON");
  1051.     line25();
  1052.     lstclosed = FALSE;        /* So not closed */
  1053.     printon = TRUE;            /* and printer is on. */
  1054.     }
  1055. }
  1056.  
  1057. static void
  1058. printeroff() {                /* Turn off printer */
  1059.     if (!printon)            /* It's already off. */
  1060.       return;
  1061.     if (lst && !lstclosed)
  1062.       fclose(lst);
  1063.     lstclosed = TRUE;
  1064.     printon = FALSE;
  1065.     if (savefiletext[0]) {        /* Fix status line */
  1066.     strcpy(filetext,savefiletext);
  1067.     savefiletext[0] = NUL;
  1068.     }
  1069.     line25();
  1070. }
  1071.  
  1072. #define CK_BORDER            /* Allow border colors */
  1073.  
  1074. static int cmd_border = -1;
  1075.  
  1076. static void
  1077. setborder() {
  1078. #ifdef CK_BORDER
  1079.     VIOOVERSCAN vo;            /* Set border (overscan) color */
  1080.     vo.cb = sizeof(vo);            /* for terminal emulation window */
  1081.     vo.type = 1;
  1082.     vo.color = colorborder; 
  1083.     VioSetState((PVOID) &vo, 0);
  1084. #endif /* CK_BORDER */
  1085. }
  1086.  
  1087. static void
  1088. saveborder() {                /* Save command-screen border */
  1089. #ifdef CK_BORDER
  1090.     VIOOVERSCAN vo;
  1091.     vo.cb = sizeof(vo);
  1092.     vo.type = 1;
  1093.     VioGetState((PVOID) &vo, 0);
  1094.     cmd_border = vo.color;
  1095. #endif /* CK_BORDER */
  1096. }
  1097.  
  1098. static void
  1099. restoreborder() {
  1100. #ifdef CK_BORDER
  1101.     VIOOVERSCAN vo;            /* Restore command-screen border */
  1102.     if (cmd_border < 0)            /* None saved. */
  1103.       return;
  1104.     vo.cb = sizeof(vo);
  1105.     vo.type = 1;
  1106.     vo.color = cmd_border;
  1107.     cmd_border = 0;
  1108.     VioSetState((PVOID) &vo, 0);
  1109. #endif /* CK_BORDER */
  1110. }
  1111.  
  1112. static void                /* Reset the terminal emulator */
  1113. doreset(int x) {            /* x = 0 (soft), nonzero (hard) */
  1114.     int i;
  1115.  
  1116.     defaultattribute = colornormal;    /* Normal colors */
  1117.     if (decscnm)
  1118.       colorunderline = swapcolors(colorunderline);
  1119.     attribute = defaultattribute;    /* Default attributes */
  1120.     attrib.blinking = FALSE;        /* No blink */
  1121.     attrib.bold = FALSE;        /* No bold */
  1122.     attrib.invisible = FALSE;        /* Not invisible */
  1123.     attrib.underlined = FALSE;        /* No underline */
  1124.     attrib.reversed = FALSE;        /* No reverse video */
  1125.     g0 = g1 = 'B';            /* ASCII (not UK) in G0 and G1 */
  1126.     g0g1 = &g0;                /* (sort of...) */
  1127.     printon = FALSE;            /* Printer is not on */
  1128.     printregion = FALSE;        /* Printer extent is full screen */
  1129.     screenon = TRUE;            /* The screen is turned on */
  1130. #ifdef CK_APC
  1131.     apcactive = 0;            /* An APC command is not active */
  1132.     apclength = 0;            /* ... */
  1133. #endif /* CK_APC */
  1134.     vt52graphics = FALSE;        /* Get out of VT52 graphics mode */
  1135.     saved = FALSE;            /* Nothing is saved */
  1136.     tnlm = tt_crd = FALSE;        /* We're not in newline mode */
  1137.     insertmode = FALSE;            /* Not in character-insert mode */
  1138.     tt_arrow = TTK_NORM;        /* Arrow keypad to cursor mode */
  1139.     tt_keypad = TTK_NORM;        /* Auxilliary keypad to numeric mode */
  1140.     tt_wrap = TRUE;            /* (FALSE for real VT terminal!) */
  1141.     tt_type = my_tt_type;        /* Terminal type back to original */
  1142.     send_c1 = FALSE;            /* Don't send C1 controls */
  1143.     keylock = FALSE;            /* Keyboard is not locked */
  1144.     deccolm = FALSE;            /* 80-column mode */
  1145.     decscnm = FALSE;            /* Screen is not in reverse video */
  1146.     for (i = 0; i < ysize; i++)        /* Not in double-width-line mode */
  1147.       dwl[i] = FALSE;
  1148.     dwls = FALSE;
  1149.     for (i = 1; i < xsize; i++)        /* Tab settings every 8 spaces */
  1150.       htab[i] = (i % 8) == 1 ? 'T' : '0'; /* was "== 0" */
  1151.     relcursor = FALSE;            /* Cursor position is absolute */
  1152.     setmargins(1, ysize);        /* Scrolling region is whole screen */
  1153.     escstate = ES_NORMAL;        /* In case we're stuck in a string */
  1154.     setborder();            /* Restore border color */
  1155.     cursorena = TRUE;            /* Cursor is enabled */
  1156.     resethebrewmode();            /* Leave Hebrew keyboard mode */
  1157.     setcursormode();            /* Get rid of any unwanted blinking */
  1158.     if (x) clrscreen();            /* Now clear the screen */
  1159.     newcursor();            /* Put up a cursor */
  1160.     if (roll.flag)            /* Were we rolled back? */
  1161.       roll.flag = 0;            /* Not any more ... */
  1162.     ipadl25();                /* Put back regular status line */
  1163. }
  1164.  
  1165. static void
  1166. savecurpos(int x) {            /* x: 0 = cursor only, 1 = all */
  1167.     saved = TRUE;            /* Remember they are saved */
  1168.     row = wherey;            /* Current row (absolute) */
  1169.     column = wherex;            /* Current column (absolute) */
  1170.     if (x) {
  1171.     savedattribute = attribute;    /* Current PC video attributes */
  1172.     savedattrib = attrib;        /* Current DEC character attributes */
  1173.     saverelcursor = relcursor;    /* Cursor addressing mode */
  1174.     saveg0 = g0;            /* Character sets */
  1175.     saveg1 = g1;
  1176.     saveg0g1 = g0g1;
  1177.     }
  1178. }
  1179.  
  1180. static void
  1181. restorecurpos(int x) {
  1182.     if (saved == FALSE) {        /* Nothing saved, home the cursor */
  1183.     lgotoxy(1, relcursor ? margintop : 1);
  1184.     return;
  1185.     }
  1186. #ifdef COMMENT
  1187. /*  Wrong!  Restoring the saved parameters does not unsave them.  -fdc  */
  1188.     saved = FALSE;
  1189. #endif /* COMMENT */
  1190.     lgotoxy(column, row);        /* Goto saved position */
  1191.     if (x) {
  1192.     attribute = savedattribute;    /* Restore saved attributes */
  1193.     attrib = savedattrib;
  1194.     relcursor = saverelcursor;    /* Restore cursor addressing mode */
  1195.     g0 = saveg0;            /* Restore character sets */
  1196.     g1 = saveg1;
  1197.     g0g1 = saveg0g1;
  1198.     }
  1199. }
  1200.  
  1201. /*
  1202.   Hebrew keyboard-mode support functions.  These are needed when using a
  1203.   non-Hebrew keyboard to enter Hebrew letters during CONNECT mode.  When
  1204.   the keyboard is in "English" mode, the main keypad acts normally.  When it
  1205.   is in Hebrew mode, the lowercase letters (and some punctuation marks) are
  1206.   mapped to Hebrew letters.  Keyboard mode is set via the keyboard verbs
  1207.   \KkbHebrew and \KkbHebrew, and also by DECHEBM escape sequences
  1208.   (CSI ? 35 h / l) from the host (handled in vtescape()).  Both methods
  1209.   invoke these routines. 
  1210. */
  1211. static void
  1212. sethebrewmode() {            /* Enter Hebrew keyboard mode */
  1213. /*
  1214.   This is the WordPerfect / Windows / Microsoft Word mapping.  If different
  1215.   mappings are needed, we can add them via a parameter to this function,
  1216.   settable by a SET TERMINAL HEBREW-KEYMAP command.  Note that we don't change
  1217.   the keymap by executing a macro (like MS-DOS Kermit's KEYBOARDS/KEYBOARDR
  1218.   macros) since that causes disconcerting and lengthy screen flashes as Kermit
  1219.   pops back and forth between CONNECT and command mode.
  1220. */
  1221.     keymap[ 39] =  44;            /* ' (Apostrophe) = , (Comma) */
  1222.     keymap[ 44] = 154;            /* , (Comma) = Taw */
  1223.     keymap[ 46] = 149;            /* . (Period) = Final Zade */
  1224.     keymap[ 47] =  46;            /* / (Slash) = . (Period) */
  1225.     keymap[ 59] = 147;            /* ; (Semicolon) = Terminal Pe */
  1226.     keymap[ 97] = 153;            /* a = Shin */
  1227.     keymap[ 98] = 144;            /* b = Nun */
  1228.     keymap[ 99] = 129;            /* c = Bet */
  1229.     keymap[100] = 130;            /* d = Gimel */
  1230.     keymap[101] = 151;            /* e = Qoph */
  1231.     keymap[102] = 139;            /* f = Kaph */
  1232.     keymap[103] = 146;            /* g = Ayin */
  1233.     keymap[104] = 137;            /* h = Yod */
  1234.     keymap[105] = 143;            /* i = Final Nun */
  1235.     keymap[106] = 135;            /* j = Chet */
  1236.     keymap[107] = 140;            /* k = Lamed */
  1237.     keymap[108] = 138;            /* l = Final Kaph */
  1238.     keymap[109] = 150;            /* m = Zade */
  1239.     keymap[110] = 142;            /* n = Mem */
  1240.     keymap[111] = 141;            /* o = Final Mem */
  1241.     keymap[112] = 148;            /* p = Pe */
  1242.     keymap[113] =  47;            /* q = / (slash) */
  1243.     keymap[114] = 152;            /* r = Resh */
  1244.     keymap[115] = 131;            /* s = Dalet */
  1245.     keymap[116] = 128;            /* t = Aleph */
  1246.     keymap[117] = 133;            /* u = Waw */
  1247.     keymap[118] = 132;            /* v = He */
  1248.     keymap[119] =  39;            /* w = ' (Apostrophe) */
  1249.     keymap[120] = 145;            /* x = Samech */
  1250.     keymap[121] = 136;            /* y = Tet */
  1251.     keymap[122] = 134;            /* z = Zain */
  1252.     tt_hebrew = TRUE;
  1253.     if (!roll.flag)
  1254.       ipadl25() ;
  1255. }
  1256.  
  1257. static void
  1258. resethebrewmode() {            /* Enter English keyboard mode */
  1259. /*
  1260.   Warning: This routine assumes that main keypad keys (lowercase Roman letters
  1261.   and punctuation marks) are normally mapped to themselves.
  1262. */
  1263.     KEY k;
  1264.     keymap[39] = 39;            /* Apostrophe */
  1265.     keymap[44] = 44;            /* Comma */
  1266.     keymap[46] = 46;            /* Period */
  1267.     keymap[47] = 47;            /* Slash */
  1268.     keymap[59] = 59;            /* Semicolon */
  1269.     for (k = 97; k < 123; k++)        /* Letters a-z */
  1270.       keymap[k] = k;
  1271.     tt_hebrew = FALSE;
  1272.     if (!roll.flag)
  1273.       ipadl25() ;
  1274. }
  1275.  
  1276. /*
  1277.   The flow of characters from the communication device to the screen is:
  1278.                              
  1279.                +---(debug)----+
  1280.                |              |
  1281.   rdcomwrtscr --> cwrite --+--> vt100 --> wrtch
  1282.                |              |
  1283.                +--> vtescape--+
  1284.  
  1285.   rdcomwrtscr() reads character from communication device via ttinc() and:
  1286.    - converts 8-bit controls to 7-bit ESC sequences
  1287.    - handles TELNET negotiations
  1288.    - handles SO/SI (NOTE: this prevents
  1289.    - handles charset translation
  1290.    - handles newline-mode and cr-display
  1291.    - handles connection loss
  1292.    - passes all output chars to cwrite()
  1293.  
  1294.   cwrite()
  1295.    - handles debug output, direct to wrtch().
  1296.    - detects and parses escape-sequences:
  1297.      . builds up escape sequence in buffer
  1298.      . when complete, calls vtescape(), or does APC.
  1299.    - when not debugging & not in esc seq, sends all other chars to vt100().
  1300.  
  1301.   vt100()
  1302.    - handles ctrl chars in straightforward, modeless way (ENQ, tab, BS, beep)
  1303.    - *thinks* it handles SO/SI, but never gets called for this (???)
  1304.    - handles graphic chars via mode (g0, g1, vtgraphics, etc) -> wrtch()
  1305.    - handles wraparound
  1306.  
  1307.   vtescape()
  1308.    - acts on escape sequences, changes state, moves cursor, etc.
  1309. */
  1310.  
  1311. /*  V T E S C A P E  --  Interpret a VT52/100/102/220 escape sequence  */
  1312. /*
  1313.   Called after an escape sequence has been received and collected
  1314.   into escbuffer[]. To be added:
  1315.  
  1316.   ISO 2022 Character-set designation
  1317.   DEC national vs multinational character-set (DECNRCM)
  1318.   Addition of G2, G3
  1319.   Single shifts
  1320.   Locking shifts beyond SO/SI (G2, G3)
  1321.   Soft character sets (DRCS)
  1322.   User Defined Keys (DECUDK)
  1323.  
  1324.   DECSTR    220   CSI ! p               Soft reset, keeps screen
  1325.   DECSCL    220   CSI Pl; Pc " p        Set conformance level + soft reset
  1326.   DECSCA    220   CSI Ps " q            Select erasable/not erasable
  1327.   DECSEL    220   CSI ? Pn K            Selective erase
  1328.   etc etc...
  1329. */
  1330. static void
  1331. vtescape() {
  1332.     unsigned char   j;
  1333.     unsigned char   k;
  1334.     unsigned char   l;
  1335.     unsigned char   blankcell[2];
  1336.     int             i;
  1337.     int             pn[11];
  1338.     bool            private;
  1339.     char            tempstr[20];
  1340.     int             fore, back;
  1341.  
  1342.     escstate = ES_NORMAL;        /* Set escape state back to normal */
  1343.     escnext = 1;            /* Point to beginning of esc seq buf */
  1344.     if (debses)                /* If TERMINAL DEBUG ON, */
  1345.       return;                /* we don't actually do anything. */
  1346.     achar = (escnext<=esclast)?escbuffer[escnext++]:0;
  1347.     if (screenon || (achar == '[')) {
  1348.     /* screen escape sequences  */
  1349.     switch (achar) {        /* First Level */
  1350.     case '[':            /* CSI */
  1351.         {
  1352.         achar = (escnext<=esclast)?escbuffer[escnext++]:0;
  1353.         switch (achar) {    /* Second level */
  1354.         case 'A':        /* Cursor up one line */
  1355.             cursorup();
  1356.             wrapit = FALSE;
  1357.             break;
  1358.         case 'B':        /* Cursor down one line */
  1359.             cursordown();
  1360.             wrapit = FALSE;
  1361.             break;
  1362.         case 'C':        /* Cursor forward, stay on same line */
  1363.             cursorright();
  1364.             if (dwl[wherey - 1])
  1365.               cursorright();
  1366.             break;
  1367.         case 'D':        /* Cursor back, stay on same line */
  1368.             cursorleft();
  1369.             if (dwl[wherey - 1])
  1370.               cursorleft();
  1371.             break;
  1372.         case 'J':        /* Erase from cursor to end of scrn */
  1373.             clreoscr_escape();
  1374.             break;
  1375.         case 'K':        /* Erase from cursor to end of line */
  1376.             clrtoeoln();
  1377.             break;
  1378.         case '?':        /* DEC private */
  1379.             private = TRUE;
  1380.             achar = (escnext<=esclast)?escbuffer[escnext++]:0;
  1381.             goto LB2001;
  1382.         case 'f':
  1383.         case 'H':    /* Cursor Home */
  1384.             lgotoxy(1, relcursor ? margintop : 1);
  1385.             break;
  1386.         case 'g':    /* Tab Clear at this position */
  1387.             htab[wherex] = '0';
  1388.             break;
  1389.         case '}':
  1390.         case 'm':    /* Normal Video - Exit all attribute modes */
  1391.             attribute = defaultattribute;
  1392.             attrib.blinking = FALSE;
  1393.             attrib.bold = FALSE;
  1394.             attrib.invisible = FALSE;
  1395.             attrib.underlined = FALSE;
  1396.             attrib.reversed = FALSE;
  1397.             break;
  1398.         case 'r':        /* Reset Margin */
  1399.             setmargins(1, ysize);
  1400.             lgotoxy(1, 1);
  1401.             break;
  1402.           case 's':        /* ANSI.SYS save cursor position */
  1403.             savecurpos(0);
  1404.             break;
  1405.           case 'u':        /* ANSI.SYS restore cursor position */
  1406.             restorecurpos(0);
  1407.             break;
  1408.         case 'c':
  1409.         case 'h':
  1410.         case 'l':
  1411.         case 'n':
  1412.         case 'x':
  1413.             pn[1] = 0;
  1414.             private = FALSE;
  1415.             k = 1;
  1416.             goto LB2003;
  1417.         case ';':        /* As in ESC [ ; 7 m */
  1418.             pn[1] = 0;
  1419.             private = FALSE;
  1420.             k = 1;
  1421.             goto LB2002;
  1422.         case 'L':
  1423.         case 'M':
  1424.         case '@':
  1425.         case 'P':
  1426.             pn[1] = 1;
  1427.             private = FALSE;
  1428.             k = 1;
  1429.             goto LB2002;
  1430.         default:    /* Pn - got a number */
  1431.             private = FALSE;
  1432.         LB2001:
  1433.             {        /* Esc [ Pn...Pn x   functions */
  1434.             pn[1] = pnumber(&achar);
  1435.             k = 1;
  1436.         LB2002:
  1437.             while (achar == ';') {    /* get Pn[k] */
  1438.                 achar = (escnext<=esclast)?escbuffer[escnext++]:0;
  1439.                 k++;
  1440.                 if (achar == '?')
  1441.                  achar = (escnext<=esclast)?escbuffer[escnext++]:0;
  1442.                 pn[k] = pnumber(&achar);
  1443.             }
  1444.             pn[k + 1] = 1;
  1445.         LB2003:
  1446.             switch (achar) { /* Third level */
  1447.             case 'A':    /* Cursor up Pn lines */
  1448.                 do {
  1449.                 cursorup();
  1450.                 wrapit = FALSE;
  1451.                 pn[1] = pn[1] - 1;
  1452.                 } while (!(pn[1] <= 0));
  1453.                 break;
  1454.             case 'B':    /* Cursor down pn lines */
  1455.                 do {
  1456.                 cursordown();
  1457.                 wrapit = FALSE;
  1458.                 pn[1] = pn[1] - 1;
  1459.                 } while (!(pn[1] <= 0));
  1460.                 break;
  1461.             case 'C':    /* Cursor right pn chars */
  1462.                 do {
  1463.                 cursorright();
  1464.                 if (dwl[wherey - 1])
  1465.                     cursorright();
  1466.                 pn[1] = pn[1] - 1;
  1467.                 } while (pn[1] > 0);
  1468.                 break;
  1469.             case 'D':    /* Cursor Left pn characters */
  1470.                 do {
  1471.                 cursorleft();
  1472.                 if (dwl[wherey - 1])
  1473.                     cursorleft();
  1474.                 pn[1] = pn[1] - 1;
  1475.                 } while (pn[1] > 0);
  1476.                 break;
  1477.             case 'f':    /* Direct cursor address */
  1478.             case 'H':
  1479.                 if (pn[1] == 0)
  1480.                 pn[1] = 1;
  1481.                 if (relcursor)
  1482.                 pn[1] += margintop - 1;
  1483.                 if (pn[1] > ysize)
  1484.                     pn[1] = ysize;
  1485.                 if (pn[2] == 0)
  1486.                 pn[2] = 1;
  1487.                 if (dwl[pn[1] - 1]) {
  1488.                 pn[2] = 2 * pn[2] - 1;
  1489.                 if (pn[2] > xsize)
  1490.                     pn[2] = xsize - 1;
  1491.                 } else if (pn[2] > xsize)
  1492.                 pn[2] = xsize;
  1493.                 wrapit = FALSE;
  1494.                 lgotoxy(pn[2], pn[1]);
  1495.                 break;
  1496.             case 'c':    /* Device Attributes */
  1497.                 if (pn[1] == 0)
  1498.                   if (tt_type >= 0 && tt_type <= max_tt) {
  1499.                   if (!network) msleep(100);
  1500.                   sendescseq(tt_info[tt_type].x_id);
  1501.                   }
  1502.                 break;
  1503.             case 'g':
  1504.                 if (pn[1] == 3) {
  1505.                 /* clear all tabs */
  1506.                 for (j = 1; j <=xsize; ++j)
  1507.                     htab[j] = '0';
  1508.                 } else if (pn[1] == 0)
  1509.                 /* clear tab at current position */
  1510.                 htab[wherex] = '0';
  1511.                 break;
  1512.             case 'h':    /* Set Mode */
  1513.                 for (j = 1; j <= k; ++j)
  1514.                 if (private)
  1515.                     switch (pn[j]) {    /* Field specs */
  1516.                     case 1:    /* DECCKM  */
  1517.                     tt_arrow = TTK_APPL;
  1518.                     break;
  1519.                     case 2:    /* DECANM : ANSI/VT52 */
  1520.                     tt_type = my_tt_type;
  1521.                     vt52graphics = FALSE;
  1522.                     break;
  1523.                     case 3:    /* DECCOLM = 132 Columns */
  1524.                     deccolm = TRUE;
  1525.                     clrscreen();
  1526.                     break;
  1527.                     case 4:    /* DECSCLM - Smooth scroll */
  1528.                     break;
  1529.                     case 5:    /* DECSCNM - Reverse screen */
  1530.                     if (decscnm) /* Already reverse */
  1531.                       break;
  1532.                     else
  1533.                       flipscreen();
  1534.                     break;
  1535.                     case 6:    /* DECOM - Relative origin */
  1536.                     relcursor = TRUE;
  1537.                     lgotoxy(1, margintop);
  1538.                     break;
  1539.                     case 7:    /* DECAWM - Auto Wrap mode */
  1540.                     tt_wrap = TRUE;
  1541.                     break;
  1542. #ifdef COMMENT
  1543.                     case 8:    /* DECARM - Autorepeat */
  1544.                     break;
  1545.                     case 9:    /* DECINLM - Interlace */
  1546.                     break;
  1547. #endif /* COMMENT */
  1548. #ifdef __32BIT__
  1549.                     case 18:    /* DECPFF - Print Form Feed */
  1550.                     xprintff = TRUE;
  1551.                     break;
  1552.                     case 19:    /* DECPEX - Printer extent */
  1553.                     printregion = FALSE; /* Full screen */
  1554.                     break;
  1555. #endif /* __32BIT__ */
  1556.                     case 25:   /* DECTCEM - Cursor On */
  1557.                     newcursor();
  1558.                     cursorena = TRUE;
  1559.                     break;
  1560.                     case 35: /* DECHEBM */
  1561.                     /* Enter Hebrew keyboard mode */
  1562.                     sethebrewmode();
  1563.                     break;
  1564. #ifdef COMMENT
  1565.                     case 38: /* DECTEK */
  1566.                     /* Enter Tektronix 4010/4014 mode */
  1567.                     break;
  1568.                     case 42: /* DECNRCM */
  1569.                     /* Use 7-bit NRC */
  1570.                     break;
  1571.                     case 43: /* DECGEPM */
  1572.                     /* Graphics Expanded Print mode */
  1573.                     case 44: /* DECGPCM */
  1574.                     /* Graphics Print Color mode */
  1575.                     case 45: /* DECGPCS */
  1576.                     /* Graphics Print Color syntax = RGB */
  1577.                     case 46: /* DECGPBM */
  1578.                     /* Graphics Print Background mode */
  1579.                     case 47: /* DECGRCM */
  1580.                     /* Graphics Rotated Print mode */
  1581.                     break;
  1582. #endif /* COMMENT */
  1583.                     default:
  1584.                     break;
  1585.                 } else    /* Not private */
  1586.                     switch (pn[j]) {
  1587.                     case 2: /* Keyboard locked */
  1588.                     keylock = TRUE;
  1589.                     break;
  1590.                     case 4: /* ANSI insert mode */
  1591.                     if (tt_type >= TT_VT102)
  1592.                       insertmode = TRUE;
  1593.                     break;
  1594.                     case 12:    /* SRM - Send Receive ON */
  1595.                     duplex = 0; /* Remote echo */
  1596.                     break;
  1597.                     case 20:
  1598.                     /* LNM - linefeed / newline mode */
  1599.                     tt_crd = tnlm = TRUE;
  1600.                     break;
  1601.                     default:
  1602.                     break;
  1603.                     }
  1604.                 break;
  1605.             case 'l':    /* Reset Mode */
  1606.                 for (j = 1; j <= k; ++j) /* Go thru all pn's */
  1607.                 if (private)
  1608.                     switch ((pn[j])) {    /* Field specs */
  1609.                     case 1:    /* DECCKM - Cursor key mode */
  1610.                     tt_arrow = TTK_NORM;
  1611.                     break;
  1612.                     case 2:    /* DECANM : ANSI/VT52 */
  1613.                     tt_type = TT_VT52;
  1614.                     vt52graphics = FALSE;
  1615.                     break;
  1616.                     case 3:    /* DECCOLM - 80 Columns */
  1617.                     deccolm = FALSE;
  1618.                     clrscreen();
  1619.                     break;
  1620.                     case 4:    /* DECSCLM - Jump scrolling */
  1621.                     break;
  1622.                     case 5:    /* DECSCNM - Normal screen */
  1623.                     if (!decscnm) /* Already normal? */
  1624.                       break;
  1625.                     else
  1626.                       flipscreen();
  1627.                     break;
  1628.                     case 6:    /* DECOM - Absolute origin */
  1629.                     relcursor = FALSE;
  1630.                     lgotoxy(1, 1);
  1631.                     break;
  1632.                     case 7:    /* DECAWM - Auto wrap */
  1633.                     tt_wrap = FALSE;
  1634.                     break;
  1635. #ifdef COMMENT
  1636.                     case 8:    /* DECARM - Auto repeat */
  1637.                     break;
  1638.                     case 9:    /* DECINLM - Interlace */
  1639.                     break;
  1640. #endif /* COMMENT */
  1641. #ifdef __32BIT__
  1642.                     case 18:    /* DECPFF - Print Form Feed */
  1643.                     xprintff = FALSE;
  1644.                     break;
  1645.                     case 19:    /* DECPEX - Print extent */
  1646.                     printregion = TRUE; /* Region */
  1647.                     break;
  1648. #endif /* __32BIT__ */
  1649.                     case 25:   /* DECTCEM - Cursor Off */
  1650.                     if (cursorena)
  1651.                       killcursor();
  1652.                     cursorena = FALSE;
  1653.                     break;
  1654.                     case 35: /* DECHEBM */
  1655.                     /* Enter English keyboard mode */
  1656.                     resethebrewmode();
  1657.                     break;
  1658. #ifdef COMMENT
  1659.                     case 38: /* DECTEK */
  1660.                     /* Exit Tektronix 4010/4014 mode */
  1661.                     break;
  1662.                     case 42: /* DECNRCM */
  1663.                     /* Use 8-bit multinational char set */
  1664.                     break;
  1665.                     case 43: /* DECGEPM */
  1666.                     /* Graphics Normal Print mode */
  1667.                     case 44: /* DECGPCM */
  1668.                     /* Graphics Print Monochrome mode */
  1669.                     case 45: /* DECGPCS */
  1670.                     /* Graphics Print Color syntax = HLS */
  1671.                     case 46: /* DECGPBM */
  1672.                     /* Graphics Print No-Background mode */
  1673.                     case 47: /* DECGRCM */
  1674.                     /* Graphics Unrotated Print mode */
  1675.                     break;
  1676. #endif /* COMMENT */
  1677.                     default:
  1678.                     break;
  1679.                 } else    /* Not private */
  1680.                     switch (pn[j]) {
  1681.                     case 2:    /* Keyboard unlocked */
  1682.                     keylock = FALSE;
  1683.                     break;
  1684.                     case 4:    /* ANSI insert mode */
  1685.                     insertmode = FALSE;
  1686.                     break;
  1687.                     case 12:    /* SRM - Send Receive OFF */
  1688.                     duplex = 1; /* Local echo */
  1689.                     break;
  1690.                     case 20:
  1691.                     /* LNM - linefeed / newline mode */
  1692.                     tt_crd = tnlm = FALSE;
  1693.                     break;
  1694.                     default:
  1695.                     break;
  1696.                     }
  1697.                 break;
  1698.             case 'i':    /* Media Copy */
  1699. #ifdef __32BIT__
  1700. /*
  1701.   This code crashes the 16-bit version with Stack Overflow.
  1702.   Print-Whole-Screen & Print-Cursor-Line support added in edit 190, fdc.
  1703. */
  1704.                 if (pn[1] == 0)  /* Print whole screen */
  1705.                   prtscreen(printregion?margintop:1,
  1706.                     printregion?marginbot:ysize);
  1707.                 else if (pn[1] == 1 &&  /* Print cursor line */
  1708.                          private == TRUE) /* Only if ESC [?1i */
  1709.                   prtscreen(wherey,wherey);
  1710. /* 
  1711.   For pn = 4 or 5, we should differentiate here between transparent print
  1712.   (private == FALSE) and autoprint (private == TRUE).  As presently coded,
  1713.   we always do transparent print.  Autoprint means that the current screen
  1714.   line is printed as soon as the cursor leaves it, i.e. when the terminal
  1715.   receives a linefeed, form feed, or vertical tab, or when it wraps.
  1716. */
  1717.                 else if (pn[1] == 4) {
  1718.                 turnoffprinter = TRUE;
  1719.                 xprint = FALSE;
  1720.                 } else if (pn[1] == 5)
  1721.                   turnonprinter = xprint = TRUE;
  1722.  
  1723. /*  6 and 7 are not in the VT102 manual.  Maybe in the Scottish version?  */
  1724.  
  1725.                 else if (pn[1] == 6) /* Turn off screen display */
  1726.                   screenon = FALSE;
  1727.                 else if (pn[1] == 7) /* Turn on screen display */
  1728.                   screenon = TRUE;
  1729. #endif /* __32BIT__ */
  1730.                 break;
  1731.             case 'q':        /* Load LEDs */
  1732.                 break;        /* (nothing) */
  1733.             case 'n':
  1734.                 /* Pages 103-104, VT220 manual */
  1735.                 if (pn[1] == 5)     /* Terminal Status Report */
  1736.                   sendescseq("[0n");     /* Terminal is OK */
  1737.                 else if (pn[1] == 6) { /* Cursor position report */
  1738. #ifndef __32BIT__
  1739. /*
  1740.   16-bit version must use a hand-coded in-line version of sprintf to avoid
  1741.   the function call that would crash the program with a stack overflow.
  1742.   Handles numbers 0 - 999.  No range checking.  - fdc
  1743. */
  1744.                 int i = 0, j;
  1745.                 tempstr[i++] = '[';
  1746.                 if ((j = wherey / 100) > 0)
  1747.                   tempstr[i++] = (char) (j + 48);
  1748.                 if ((j = (wherey % 100) / 10) > 0 ||
  1749.                     wherey > 99)
  1750.                   tempstr[i++] = (char) (j + 48);
  1751.                 if ((j = wherey % 10) > 0 ||
  1752.                     wherey > 9)
  1753.                   tempstr[i++] = (char) (j + 48);
  1754.                 tempstr[i++] = ';';
  1755.                 if ((j = wherex / 100) > 0)
  1756.                   tempstr[i++] = (char) (j + 48);
  1757.                 if ((j = (wherex % 100) / 10) > 0 ||
  1758.                     wherex > 99)
  1759.                   tempstr[i++] = (char) (j + 48);
  1760.                 if ((j = wherex % 10) > 0 ||
  1761.                     wherex > 9)
  1762.                   tempstr[i++] = (char) (j + 48);
  1763.                 tempstr[i++] = 'R';
  1764.                 tempstr[i] = '\0';
  1765.                 sendescseq(tempstr);
  1766. #else
  1767. /* 32-bit version can call sprintf() here.  */
  1768.                 sprintf(tempstr,"[%d;%dR", wherey, wherex);
  1769.                 sendescseq(tempstr);
  1770. #endif /* __32BIT__ */
  1771.                 } else if (pn[1] == 15) {
  1772.                 /* DECDSR Printer status */
  1773.                 sendescseq("[?10n"); /* Printer is ready */
  1774.                 } else if (pn[1] == 26) {
  1775.                 /* DECDSR Keyboard language, UK or US */
  1776.                 sendescseq((g0 == (CHAR) 'A') ?
  1777.                     "[?27;2n" :
  1778.                     "[?27;1n" );
  1779.                 } else if (pn[1] == 25) {
  1780.                 /* DECDSR UDK status; 20=unlocked, 21=locked */
  1781.                 sendescseq("[?21n");
  1782.                 }
  1783.                 break;
  1784.             case 'x': /* DECREQTPARM Request Terminal Parameters */
  1785.                 if (pn[1] > 1)
  1786.                 break;
  1787.                 tempstr[0] = '[';
  1788.                 tempstr[1] = (pn[1] == 0) ? '2' : '3';
  1789.                 tempstr[2] = ';';
  1790.                 tempstr[5] = '2'; /* Nbits = 7 */
  1791.                 switch (parity) {                
  1792.                   case 0:
  1793.                 tempstr[3] = '1'; /* Parity = None */
  1794.                 /* Nbits depends on TERMINAL BYTESIZE */
  1795.                 if (cmask == 0xFF)
  1796.                   tempstr[5] = '1'; /* Nbits = 8 */
  1797.                 break;
  1798.                   case 'e':
  1799.                 tempstr[3] = '5'; /* Parity = Even */
  1800.                 break;
  1801.                   case 'o':
  1802.                 tempstr[3] = '4'; /* Parity = Odd */
  1803.                 break;
  1804.                   case 'm':
  1805.                 tempstr[3] = '3'; /* Parity = Mark */
  1806.                 break;
  1807.                   default:
  1808.                 tempstr[3] = '2'; /* Parity = Space */
  1809.                 break;
  1810.                 }
  1811.                 tempstr[4] = ';';
  1812.                 switch (speed) {
  1813.                 case 50:
  1814.                 i = 0;
  1815.                 break;
  1816.                 case 75:
  1817.                 i = 8;
  1818.                 break;
  1819.                 case 110:
  1820.                 i = 16;
  1821.                 break;
  1822.                 case 133:
  1823.                 i = 14;
  1824.                 break;
  1825.                 case 150:
  1826.                 i = 32;
  1827.                 break;
  1828.                 case 200:
  1829.                 i = 40;
  1830.                 break;
  1831.                 case 300:
  1832.                 i = 48;
  1833.                 break;
  1834.                 case 600:
  1835.                 i = 56;
  1836.                 break;
  1837.                 case 1200:
  1838.                 i = 64;
  1839.                 break;
  1840.                 case 1800:
  1841.                 i = 72;
  1842.                 break;
  1843.                 case 2000:
  1844.                 i = 80;
  1845.                 break;
  1846.                 case 2400:
  1847.                 i = 88;
  1848.                 break;
  1849.                 case 3600:
  1850.                 i = 96;
  1851.                 break;
  1852.                 case 4800:
  1853.                 i = 104;
  1854.                 break;
  1855.                 case 9600:
  1856.                 i = 112;
  1857.                 break;
  1858.                 case 19200:
  1859.                 i = 120;
  1860.                 break;
  1861.                 default:
  1862.                 i = 128;
  1863.                 break;
  1864.                 }
  1865. #ifndef __32BIT__
  1866. /*
  1867.   Hand-coded sprintf() again.  - fdc.
  1868. */
  1869.                 {
  1870.                 int x, j;
  1871.                 x = i;
  1872.                 i = 6;
  1873.                 tempstr[i++] = ';';
  1874.                 if ((j = x / 100) > 0)
  1875.                   tempstr[i++] = (char) (j + 48);
  1876.                 if ((j = (wherey % 100) / 10) > 0 ||
  1877.                     wherey > 99)
  1878.                   tempstr[i++] = (char) (j + 48);
  1879.                 if ((j = wherey % 10) > 0 ||
  1880.                     wherey > 9)
  1881.                   tempstr[i++] = (char) (j + 48);
  1882.                 tempstr[i++] = ';';
  1883.                 if ((j = x / 100) > 0)
  1884.                   tempstr[i++] = (char) (j + 48);
  1885.                 if ((j = (wherey % 100) / 10) > 0 ||
  1886.                     wherey > 99)
  1887.                   tempstr[i++] = (char) (j + 48);
  1888.                 if ((j = wherey % 10) > 0 ||
  1889.                     wherey > 9)
  1890.                   tempstr[i++] = (char) (j + 48);
  1891.                 tempstr[i++] = ';';
  1892.                 tempstr[i++] = '1';
  1893.                 tempstr[i++] = ';';
  1894.                 tempstr[i++] = '0';
  1895.                 tempstr[i++] = 'x';
  1896.                 tempstr[i++] = '\0';
  1897.                 }
  1898. #else
  1899.                 sprintf(&tempstr[6], ";%d;%d;1;0x", i, i);
  1900. #endif /* __32BIT__ */
  1901.                 sendescseq(tempstr);
  1902.                 break;
  1903.             case 'm':    /* Select Graphic Rendition (SGR) */
  1904.             case '}':    /* (Why this?) */
  1905.                 for (j = 1; j <= k; ++j) /* Go thru all Pn's */
  1906.                 switch ((pn[j])) {   /* This one... */
  1907.                 case 0:    /* Set all attributes to normal */
  1908.                     attribute = defaultattribute;
  1909.                     attrib.blinking = FALSE;
  1910.                     attrib.bold = FALSE;
  1911.                     attrib.invisible = FALSE;
  1912.                     attrib.underlined = FALSE;
  1913.                     attrib.reversed = FALSE;
  1914.                     break;
  1915.                 case 1:    /* Turn on BOLD */
  1916.                     /* No colors involved. */
  1917.                     if (attrib.bold) /* Already bold? */
  1918.                       break;
  1919.                     attribute ^= 8;  /* No, flip the bit. */
  1920.                     attrib.bold = TRUE; /* Remember */
  1921.                     break;
  1922.                 case 4:    /* Turn on UNDERLINE */
  1923.                     /* Simulated by color */
  1924.                     if (attrib.underlined)
  1925.                       break;
  1926.                     attrib.underlined = TRUE;
  1927. #ifdef COMMENT
  1928.                     attribute = (attribute & (unsigned) 0x80) |
  1929.                       (colorunderline & 0x7F);
  1930. #else
  1931.                     attribute = colorunderline;
  1932.                     if (attrib.bold) /* If currently bold */
  1933.                       attribute ^= 0x08; /* flip bold bit */
  1934.                     if (attrib.blinking) /* If blinking */
  1935.                       attribute ^= 0x80; /* flip blink bit */
  1936. #endif /* COMMENT */
  1937.                     if (attrib.reversed)
  1938.                       attribute = swapcolors(attribute);
  1939.                     break;
  1940.                     case 5:    /* Turn on BLINK */
  1941.                     /* Simulated by background intensity) */
  1942.                     if (attrib.blinking)
  1943.                       break;
  1944.                     attrib.blinking = TRUE;
  1945.                     attribute ^= (unsigned) 0x80;
  1946.                     break;
  1947.                 case 7:    /* Turn on REVERSE VIDEO */
  1948.                     if (attrib.reversed)
  1949.                       break;
  1950.                     attrib.reversed = TRUE;
  1951.                     attribute = swapcolors(attribute);
  1952.                     break;
  1953.                 case 8:    /* Turn on INVISIBLE */
  1954.                     attrib.invisible = TRUE; /* (see wrtch) */
  1955.                     break;
  1956.  
  1957.                 /* 22-27 are VT220 extensions. */
  1958.  
  1959.                 case 22: /* Turn BOLD Off */
  1960.                         if (!attrib.bold)
  1961.                       break;
  1962.                     attrib.bold = FALSE;
  1963.                     attribute ^= 8;
  1964.                     break;
  1965.                 case 24: /* Turn UNDERLINE Off */
  1966.                     if (!attrib.underlined)
  1967.                       break;
  1968.                     attrib.underlined = FALSE;
  1969.                     /* Go back to normal coloring */
  1970. #ifdef COMMENT
  1971.                     attribute = (attribute & (unsigned)0x80) |
  1972.                       (colornormal & 0x7F);
  1973. #else
  1974.                     attribute = defaultattribute;
  1975.                     if (attrib.bold) /* If currently bold */
  1976.                       attribute ^= 0x08; /* flip bold bit */
  1977.                     if (attrib.blinking) /* If blinking */
  1978.                       attribute ^= 0x80; /* flip blink bit */
  1979. #endif /* COMMENT */
  1980.                     if (attrib.reversed)
  1981.                       attribute = swapcolors(attribute);
  1982.                       break;
  1983.                     case 25: /* Turn BLINK Off */
  1984.                     if (!attrib.blinking)
  1985.                       break;
  1986.                     attrib.blinking = FALSE;
  1987.                     attribute ^= (unsigned)0x80;
  1988.                     break;
  1989.                 case 27: /* Turn REVERSE VIDEO Off */
  1990.                     if (!attrib.reversed)
  1991.                       break;
  1992.                     attrib.reversed = FALSE;
  1993.                     attribute = swapcolors(attribute);
  1994.                     break;
  1995.                 case 28:/* Turn INVISIBLE Off */
  1996.                     attrib.invisible = FALSE;
  1997.                     break;
  1998.  
  1999.                 case 30: /* Colors */
  2000.                 case 31:
  2001.                 case 32:
  2002.                 case 33:
  2003.                 case 34:
  2004.                 case 35:
  2005.                 case 36:
  2006.                 case 37:
  2007.                     /* Select foreground color */
  2008.                     if (decscnm) {
  2009.                     i = (attribute & 0x8F);
  2010.                     l = sgrcols[pn[j] - 30];
  2011.                     attribute = (i | ((l << 4)));
  2012.                     } else {
  2013.                     i = (attribute & 0xF8);
  2014.                     attribute = (i | sgrcols[pn[j] - 30]);
  2015.                     }
  2016.                     break;
  2017.                 case 40:
  2018.                 case 41:
  2019.                 case 42:
  2020.                 case 43:
  2021.                 case 44:
  2022.                 case 45:
  2023.                 case 46:
  2024.                 case 47:
  2025.                     /* Select background color */
  2026.                     if (!decscnm) {
  2027.                     i = (attribute & 0x8F);
  2028.                     l = sgrcols[pn[j] - 40];
  2029.                     attribute = (i | ((l << 4)));
  2030.                     } else {
  2031.                     i = (attribute & 0xF8);
  2032.                     attribute = (i | sgrcols[pn[j] - 40]);
  2033.                     }
  2034.                     break;
  2035.                 default:
  2036.                     break;
  2037.                 }
  2038.                 break;
  2039.             case 'r':    /* Set margin (scrolling region) */
  2040.                 if ((k < 2) || (pn[2] == 0))
  2041.                 pn[2] = ysize;
  2042.                 if (pn[1] == 0)
  2043.                 pn[1] = 1;
  2044.                 if ((pn[1] > 0) &&
  2045.                 (pn[1] < pn[2]) &&
  2046.                 (pn[2] <= ysize)) {
  2047.                 setmargins(pn[1], pn[2]);
  2048.                 lgotoxy(1, relcursor ? margintop : 1);
  2049.                 }
  2050.                 break;
  2051.             case 'J':    /* Clear screen */
  2052.                 switch ((pn[1])) {
  2053.                 case 0:    /* Clear to end of screen */
  2054.                 clreoscr_escape();
  2055.                 break;
  2056.                 case 1:    /* Clear to beginning */
  2057.                 clrboscr_escape();
  2058.                 break;
  2059.                 case 2:    /* Clear whole screen */ 
  2060.                 if (tt_type != TT_ANSI) { /* DEC ... */
  2061.                     int sx, sy;
  2062.                     sx = wherex; sy = wherey;
  2063.                     clrscreen(); /* Cursor does not move */
  2064.                     lgotoxy(sx,sy);
  2065.                 } else { /* ANSI homes the cursor */
  2066.                     clrscreen();
  2067.                 }
  2068.                 break;
  2069.                 default:
  2070.                 break;
  2071.                 }
  2072.                 break;
  2073.             case 'K':    /* Clear line */
  2074.                 switch ((pn[1])) {
  2075.                 case 0:    /* Clear to end of line */
  2076.                 clrtoeoln();
  2077.                 break;
  2078.                 case 1:    /* Clear to beginning */
  2079.                 clrbol_escape();
  2080.                 break;
  2081.                 case 2:    /* Clear whole cursor line */
  2082.                 clrline_escape();
  2083.                 break;
  2084.                 default:
  2085.                 break;
  2086.                 }
  2087.                 break;
  2088.             case 'L':    /* Insert lines */
  2089.                 for (i = 1; i <= pn[1]; ++i)
  2090.                 scroll(DOWNWARD, wherey - 1, marginbot - 1, 1);
  2091.                 break;
  2092.             case 'M':    /* Delete lines */
  2093.                 for (i = 1; i <= pn[1]; ++i)
  2094.                 scroll(UPWARD, wherey - 1, marginbot - 1, 1);
  2095.                 break;
  2096.             case '@':    /* Insert characters */
  2097.                 blankcell[0] = ' ';
  2098.                 blankcell[1] = attribute;
  2099.                 pn[1] *= dwl[wherey - 1] ? 2 : 1;
  2100.                 if (pn[1] > xsize + 1 - wherex)
  2101.                 pn[1] = xsize + 1 - wherex;
  2102. #ifdef OS2MOUSE
  2103.                 os2_mousehide() ;
  2104. #endif /* OS2MOUSE */
  2105.                 VioScrollRt(wherey - 1,
  2106.                     wherex - 1,
  2107.                     wherey - 1,
  2108.                     xsize - 1,
  2109.                     pn[1],
  2110.                     blankcell,
  2111.                     0
  2112.                     );
  2113. #ifdef OS2MOUSE
  2114.                 os2_mouseshow() ;
  2115. #endif /* OS2MOUSE */
  2116.                 break;
  2117.             case 'P':    /* DeleteChar */
  2118.                 blankcell[0] = ' ';
  2119.                 blankcell[1] = attribute;
  2120.                 pn[1] *= dwl[wherey - 1] ? 2 : 1;
  2121.                 if (pn[1] > xsize + 1 - wherex)
  2122.                 pn[1] = xsize + 1 - wherex;
  2123. #ifdef OS2MOUSE
  2124.                 os2_mousehide() ;
  2125. #endif /* OS2MOUSE */
  2126.                 VioScrollLf(wherey - 1,
  2127.                     wherex - 1,
  2128.                     wherey - 1,
  2129.                     xsize - 1,
  2130.                     pn[1],
  2131.                     blankcell,
  2132.                     0
  2133.                     );
  2134. #ifdef OS2MOUSE
  2135.                 os2_mouseshow() ;
  2136. #endif /* OS2MOUSE */
  2137.                 break;
  2138.             default:
  2139.                 break;
  2140.             }
  2141.             }
  2142.             break;
  2143.         }
  2144.         }            /* Left square bracket */
  2145.         break;
  2146.     case '7':        /* Save cursor position and attributes */
  2147.         savecurpos(1);
  2148.         break;
  2149.     case '8':        /* Restore Cursor Position and attributes */
  2150.         restorecurpos(1);
  2151.         break;
  2152.     case 'A':
  2153.         if (tt_type == TT_VT52)    /* VT52 control */
  2154.           cursorup();
  2155.         break;
  2156.     case 'B':
  2157.         if (tt_type == TT_VT52)    /* VT52 control */
  2158.           cursordown();
  2159.         break;
  2160.     case 'C':
  2161.         if (tt_type == TT_VT52)    /* VT52 control */
  2162.           cursorright();
  2163.         break;
  2164.     case 'D':
  2165.         if (tt_type == TT_VT52)    /* VT52 control */
  2166.           cursorleft();
  2167.         else {            /* Index */
  2168.         if (wherey == marginbot) {
  2169.             toplinetocyclicbuffer(); /* Save in rollback buffer */
  2170.             scroll(UPWARD, margintop - 1, marginbot - 1, 1);
  2171.         } else
  2172.           cursordown();
  2173.         }
  2174.         break;
  2175.     case 'E':            /* Next Line */
  2176.         wrtch(13);
  2177.         wrtch(10);
  2178.         break;
  2179.     case 'F':
  2180.         if (tt_type == TT_VT52)    /* VT52 control */
  2181.           vt52graphics = TRUE;
  2182.         break;
  2183.     case 'G':
  2184.         if (tt_type == TT_VT52)    /* VT52 control */
  2185.           vt52graphics = FALSE;
  2186.         break;
  2187.     case 'H':
  2188.         if (tt_type >= TT_VT100) {
  2189.         /* Set Tab Stop */
  2190.         htab[wherex] = 'T';
  2191.         }
  2192.         /* Set Tab Stop */
  2193.         else
  2194.         lgotoxy(1, 1);
  2195.         /* VT52 control */
  2196.         break;
  2197.     case 'I':            /* Reverse Linefeed, VT52 */
  2198.     case 'M':            /* Reverse Index, VT102 */
  2199.         if ((tt_type == TT_VT52  && achar == 'I') ||
  2200.         (tt_type >= TT_VT100 && achar == 'M')) {
  2201.         if (margintop == wherey) /* "==", not ">="!  - fdc */
  2202.           scroll(DOWNWARD, margintop - 1, marginbot - 1, 1);
  2203.         else
  2204.           cursorup();
  2205.         break;
  2206.         }
  2207.         break;
  2208.     case 'J':
  2209.         if (tt_type == TT_VT52)
  2210.           /* VT52 control */
  2211.           clreoscr_escape();
  2212.         break;
  2213.     case 'K':
  2214.         if (tt_type == TT_VT52)
  2215.           /* VT52 control */
  2216.           clrtoeoln();
  2217.         break;
  2218. #ifdef __32BIT__
  2219. /*
  2220.   VT52 printer controls.  For now, autoprint is treated like transparent
  2221.   print.  32-bit version only, to avoid stack overflows in 16-bit version.
  2222.   Edit 190, fdc.
  2223. */
  2224.     case 'V':            /* Print cursor line */ 
  2225.         if (tt_type == TT_VT52)    /* VT52 control */
  2226.           prtscreen(wherey,wherey);
  2227.         break;
  2228.     case ']':            /* Print screen */
  2229.         if (tt_type == TT_VT52)    /* VT52 control */
  2230.           prtscreen(1,ysize);
  2231.         break;
  2232.     case 'W':            /* Transparent print on */
  2233.     case '^':            /* Autoprint on */
  2234.         if (tt_type == TT_VT52)    /* VT52 control */
  2235.           turnonprinter = xprint = TRUE;
  2236.         break;
  2237.     case 'X':            /* Transparent print off */
  2238.     case '_':            /* Autoprint off */
  2239.         if (tt_type == TT_VT52) {    /* VT52 control */
  2240.         turnoffprinter = TRUE;
  2241.         xprint = FALSE;
  2242.         }
  2243.         break;
  2244. #endif /* __32BIT__ */
  2245.     case 'Y':            /* Direct cursor address */
  2246.         if (tt_type == TT_VT52) {    /* VT52 control */
  2247.         achar = (escnext<=esclast)?escbuffer[escnext++]:0;
  2248.         row = achar - 31;
  2249.         achar = (escnext<=esclast)?escbuffer[escnext++]:0;
  2250.         column = achar - 31;
  2251.         lgotoxy(column, row);
  2252.         }
  2253.         break;
  2254.     case 'Z':            /* DECID - Identify Terminal */
  2255.         if (tt_type >= 0 && tt_type <= max_tt) {
  2256.         if (!network) msleep(100);
  2257.         sendescseq(tt_info[tt_type].x_id);
  2258.         }
  2259.         break;
  2260.     case 'c':
  2261.         /* Reset */
  2262.         doreset(1);
  2263.         break;
  2264.     case '#':
  2265.         /* Esc # sequence */
  2266.         achar = (escnext<=esclast)?escbuffer[escnext++]:0;
  2267.         switch (achar) {
  2268.         case '3':
  2269.         decdwl_escape(TRUE);
  2270.         break;
  2271.         case '4':
  2272.         decdwl_escape(TRUE);
  2273.         break;
  2274.         case '5':
  2275.         decdwl_escape(FALSE);
  2276.         break;
  2277.         case '6':
  2278.         decdwl_escape(TRUE);
  2279.         break;
  2280.         case '8':            /* Self Test */
  2281.         {
  2282.             char cell[2];
  2283.             cell[0] = 'E';
  2284.             cell[1] = 7;
  2285.             /* Self Test */
  2286. #ifdef OS2MOUSE
  2287.             os2_mousehide() ;
  2288. #endif /* OS2MOUSE */
  2289.             VioWrtNCell(cell, 1920, 0, 0, 0);
  2290. #ifdef OS2MOUSE
  2291.             os2_mouseshow() ;
  2292. #endif
  2293.             setmargins(1, ysize);
  2294.             lgotoxy(1, 1);
  2295.         }
  2296.         break;
  2297.         default:
  2298.         break;
  2299.         } /* Esc # sequence */
  2300.         break;
  2301.  
  2302.     case '=':            /* Application mode */
  2303.         tt_keypad = TTK_APPL;
  2304.         break;
  2305.     case '>':            /* Numeric mode */
  2306.         tt_keypad = TTK_NORM;
  2307.         break;
  2308.     case '<':            /* Enter ANSI mode */
  2309.         /* VT52 control */
  2310.         if (tt_type == TT_VT52)
  2311.           tt_type = my_tt_type;
  2312.         break;
  2313.     case '(':
  2314.         achar = (escnext<=esclast)?escbuffer[escnext++]:0;
  2315.         g0 = achar;
  2316.         break;
  2317.     case ')':
  2318.         achar = (escnext<=esclast)?escbuffer[escnext++]:0;
  2319.         g1 = achar;
  2320.         break;
  2321.     case SP:
  2322.         achar = (escnext<=esclast)?escbuffer[escnext++]:0;
  2323.         if (tt_type >= TT_VT220) {
  2324.         if (achar == 'F')    /* S7C1T */
  2325.           send_c1 = FALSE;
  2326.         else if (achar == 'G')    /* S8C1T */
  2327.           if (c1controls && (cmask == 0xFF))
  2328.             send_c1 = TRUE;
  2329.         }
  2330.         break;
  2331.     default:
  2332.         if (achar == 12) {        /* ESC Ctrl-L */
  2333.         lgotoxy(1, 1);
  2334.         clrscreen();
  2335.         }
  2336.         break;
  2337.     } /* First Level Case  */
  2338.     } /* Screen escape sequences  */
  2339.  
  2340. /* Host said to turn off the printer. */
  2341.  
  2342.   if (turnoffprinter) {
  2343.       printeroff();
  2344.       turnoffprinter = FALSE;
  2345.   }
  2346.  
  2347. /* If printer is on, print this escape sequence. */
  2348.  
  2349.     if (printon) {
  2350.     fprintf(lst, "%c", 27);
  2351.     if (esclast > 0) {
  2352.         /* print esc sequence */
  2353.         for (i = 1; i <= esclast; ++i)
  2354.           fprintf(lst, "%c", escbuffer[i]);
  2355.     }
  2356.     }
  2357. /*
  2358.   If we just got a "printer on" directive, turn on the printer now.
  2359.   This way, the "printer on" directive itself is not printed.
  2360. */
  2361.     if (turnonprinter) {        /* Last command was "printer on" */
  2362.     printeron();
  2363.     turnonprinter = FALSE;
  2364.     }
  2365. }
  2366.  
  2367. /* ================================================================== */
  2368. /* VT100  -  emulate a DEC VT terminal writing a character            */
  2369. /* ================================================================== */
  2370. static void
  2371. vt100(unsigned char vtch) {
  2372.     int             i, j;
  2373.     char           *s, str[2];
  2374.  
  2375.     if (tt_type == TT_NONE) {
  2376.     wrtch(vtch);
  2377.     return;
  2378.     } else if (screenon) {
  2379.     if (vtch < 32) {    /* Control Character */
  2380.         achar = vtch;    /* Let the rest of this module see the value */
  2381.         switch (achar) {
  2382.           case FF:            /* Formfeed */
  2383.         if (tt_type == TT_ANSI) {
  2384.             clrscreen();
  2385.             break;
  2386.         } /* else fall thru... */
  2387.           case LF:            /* Linefeed */
  2388.           case 11:            /* Vertical tab */
  2389.         wrtch((char) LF);
  2390.         break;
  2391.           case CR:            /* Carriage return */
  2392.         wrtch((char) achar);
  2393.         break;
  2394. #ifdef COMMENT
  2395. /* This is just plain wrong. */
  2396.           case 27:            /* ESC */
  2397.         vtescape();
  2398.         break;
  2399. #endif /* COMMENT */
  2400.  
  2401.           case 14:            /* SO */
  2402.         if (tt_type != TT_ANSI)    /* "ANSI music" protection... */
  2403.           g0g1 = &g1;
  2404.         break;
  2405.  
  2406.           case 15:            /* SI */
  2407.         if (tt_type != TT_ANSI)    /* Ditto, gag... */
  2408.           g0g1 = &g0;
  2409.         break;
  2410.  
  2411.           case 8:            /* BS */
  2412.         wrtch((char) achar);
  2413.         break;
  2414.  
  2415.           case 7:            /* BEL */
  2416.         bleep();
  2417.         break;
  2418.  
  2419.           case 5:            /* ENQ */
  2420.         if (tt_answer) {
  2421.             int x;
  2422.             x = (tt_pacing > -1) ? tt_pacing : 50;
  2423.             s = answerback;
  2424.             while (*s) {
  2425.             if (x > 0 && !network) msleep(x);
  2426.             sendchar(*s++);
  2427.             }
  2428.         }
  2429.         break;
  2430.           case 9:        /* Horizontal tab */
  2431.         j = dwl[wherey - 1] ? 2 : 1;
  2432.         i = wherex;
  2433.         if (j == 2 && htab[(i - 1) / j + 1] == 'T') {
  2434.             i++;
  2435.             cursorright();
  2436.         }
  2437.         if (i < xsize)
  2438.             do {
  2439.             i++;
  2440.             cursorright();
  2441.             } while ((htab[(i - 1) / j + 1] != 'T') &&
  2442.                  (i <= xsize - j));
  2443.         break;
  2444.           default:        /* ignore it */
  2445.         break;
  2446.         }
  2447.         /* End of Control Character */
  2448.     } else {
  2449.         if (vtch != DEL) {        /* Normal character. */
  2450.         if (tt_type >= TT_VT100) {
  2451.             if (*g0g1 == 'A' && tcsr == FC_USASCII && vtch == 35) {
  2452.             /* UK ISO 646 character-set, # = Pound Sterling Sign */
  2453.             vtch = 156;
  2454.             } else if ((*g0g1 == '0') && /* VT graphics set */
  2455.                    (95 <= vtch) && (vtch <= 126)) {
  2456.             literal = TRUE;
  2457.             vtch = graphicset[vtch - 95];
  2458.             }
  2459.         } else {
  2460.             if (vt52graphics && (95 <= vtch) && (vtch <= 126)) {
  2461.             literal = TRUE;
  2462.             vtch = graphicset[vtch - 95];
  2463.             }
  2464.         }
  2465.         /* On the right margin? */
  2466.         if (wherex != (dwl[wherey - 1] ? xsize - 1 : xsize)) {
  2467.             wrtch(vtch);    /* Not on right margin */
  2468.             if (dwl[wherey-1])    /* Write the character */
  2469.             wrtch(' ');    /* Handle double-width characters */
  2470.             wrapit = FALSE;
  2471.         } else {        /* On right margin. */
  2472.             if (wrapit) {    /* Time to wrap?  */
  2473.             if (marginbot <= wherey) { /* Scroll if bottom line */
  2474.                 toplinetocyclicbuffer(); /* Save in rollback buf */
  2475.                 scroll(UPWARD, margintop - 1, marginbot - 1, 1);
  2476.                 lgotoxy(1, wherey);    /* Go to new bottom row */
  2477.             } else        /* Not bottom line, just wrap. */
  2478.                 lgotoxy(1, wherey + 1); /* Go to next row */
  2479.             wrtch(vtch);    /* Now write the character */
  2480.             if (dwl[wherey - 1]) /* Take care of double-width */
  2481.                 wrtch(' ');
  2482.             wrapit = FALSE;    /* Remember wrapping is done */
  2483.             } else {        /* Not time to wrap */
  2484.             i = dwl[wherey - 1] ? 2 : 1; /* Write the char */
  2485.             str[0] = vtch;
  2486.             str[1] = ' ';
  2487. #ifdef OS2MOUSE
  2488.             os2_mousehide() ;
  2489. #endif /* OS2MOUSE */
  2490.             VioWrtCharStrAtt(&vtch, i,
  2491.                      wherey - 1,
  2492.                      xsize - i,
  2493.                      &attribute,
  2494.                      0);
  2495. #ifdef OS2MOUSE
  2496.             os2_mouseshow() ;
  2497. #endif
  2498.             literal = FALSE;
  2499.             if ((tt_wrap && !deccolm)) /* If TERM WRAP ON */
  2500.                 wrapit = TRUE; /* need to wrap next time */
  2501.             }
  2502.         }
  2503.         }            /* Normal char */
  2504.     }
  2505.     }
  2506.     if (printon && (vtch != 27))
  2507.       fprintf(lst, "%c", vtch);
  2508. }
  2509.  
  2510. /* Save current status of screen */
  2511. void
  2512. savescreen(ascreen *scrn, int wherex, int wherey) {
  2513.     USHORT n = xsize * (ysize + 1) * 2;
  2514.     debug(F101,"x_save scrn","",scrn);
  2515.     debug(F101,"x_save wherex","",wherex);
  2516.     debug(F101,"x_save wherey","",wherey);
  2517.     scrn->ox = wherex;
  2518.     scrn->oy = wherey;
  2519.     scrn->att = attribute;
  2520. #ifdef OS2MOUSE
  2521.     os2_mousehide() ;
  2522. #endif
  2523.     VioReadCellStr((char *) (scrn->scrncpy), &n, 0, 0, 0);
  2524. #ifdef OS2MOUSE
  2525.     os2_mouseshow() ;
  2526. #endif
  2527. }
  2528.  
  2529. /* Restore a saved screen */
  2530. restorescreen(ascreen *scrn) {
  2531.     movetoscreen(scrn->scrncpy, 1, 1, xsize * (ysize + 1) * 2);
  2532.     attribute = scrn->att;
  2533.     wherey = scrn->oy;
  2534.     wherex = scrn->ox;
  2535.     debug(F101,"x_rest scrn","",scrn);
  2536.     debug(F101,"x_rest wherex","",wherex);
  2537.     debug(F101,"x_rest wherey","",wherey);
  2538.     lgotoxy(wherex, wherey);
  2539. }
  2540.  
  2541. #ifdef M_I286
  2542. /* Avoid 16-bit stack overflows */
  2543. #define logchar(c) zchout(ZSFILE,c)
  2544. #else
  2545. static void
  2546. logchar(char c) {
  2547.     if (zchout(ZSFILE,c) < 0) {
  2548.     conoll("");
  2549.     conoll("ERROR WRITING SESSION LOG, LOG CLOSED!");
  2550.     seslog = 0;
  2551.     }
  2552. }
  2553. #endif /* M_I286 */
  2554.  
  2555. static int
  2556. sendchar(CHAR c) {
  2557. #ifndef NOTTOCI
  2558. /*
  2559.    NOTE: ttoci() uses an ioctl() that has been observed to hang, inexplicably,
  2560.    on some systems (e.g. high-end PS/2s that haven't been rebooted in a month,
  2561.    and have been going back and forth between SLIP and Kermit.)  In fact,
  2562.    this was reported only once, and rebooting the system made the problem go
  2563.    away.
  2564.  
  2565.    A NEWER NOTE: As of 8 May 94, ttoci() uses DosWrite, but first does an
  2566.    ioctl() to make sure the connection is OK.  Hopefully, this combines the
  2567.    the benefits of both methods: failure detection, buffering, flow control.
  2568. */
  2569.     int x, i = 0;
  2570.     long wait = 0;
  2571. /*
  2572.   Send a character to the serial line in immediate mode, checking to avoid
  2573.   overwriting a character already waiting to be sent.  If we fail, e.g. because
  2574.   FLOW is RTS/CTS and CTS is not on (like when modems are retraining), enter
  2575.   a retry loop up to the timeout limit.
  2576. */
  2577.     x = ttoci(dopar(c));        /* Try to send the character */
  2578.     if (x) {                /* Transmission error */
  2579.     KEY k;
  2580.     int w, oldw;
  2581.  
  2582.     debug(F101,"sendchar blocked char","",c);
  2583.     oldw = 0;            /* For updating status line once/sec */
  2584.     save_status_line();        /* Save current status line */
  2585.  
  2586.         do {
  2587.         w = (waittime - wait) / 1000L;
  2588.         if (w != oldw) {        /* Countdown timer in status line */
  2589.         oldw = w;
  2590.         sprintf(usertext, " TRANSMISSION BLOCKED: %d",w);
  2591.         helptext[0] = '\0';
  2592.         line25();
  2593.         }
  2594.         if (conchk() > 0) {        /* Is a keystroke waiting? */
  2595.         k = congks(0);        /* Read it */
  2596.         k = keymap[k];        /* Get value from keymap */
  2597.         debug(F101,"BLOCKED key","",k);
  2598.         if (k == (F_KVERB | K_EXIT)) { /* Let them escape back... */
  2599.             active = FALSE;    /* this way */
  2600.             return 0;
  2601.         } else if (k == escape) { /* or this way */
  2602.             k = congks(0);
  2603.             k = keymap[k];
  2604.             if ((k == 'c') || (k == 'C') || (k == 3)) {
  2605.             active = FALSE;
  2606.             return 0;
  2607.             } else bleep();
  2608.         } else bleep();        /* Anything else, just beep. */
  2609.         }
  2610.         DosSleep(INTERVAL);        /* Sleep a bit */
  2611.         wait += INTERVAL;        /* Go round till limit exhausted */
  2612.         x = ttoci(dopar(c));    /* Try to send again */
  2613.     } while ((x != 0) && (wait < waittime));
  2614.     restore_status_line();
  2615.     }
  2616.     if (wait >= waittime) {        /* Go back to prompt if we failed */
  2617.     while (conchk() > 0) congks(0);    /* Flush any remaining typeahead */
  2618.     active = FALSE;
  2619.     if (network)
  2620.       sprintf(termessage,
  2621.           "Can't transmit to network, error status: %d\n", x);
  2622.     else {
  2623.         sprintf(termessage,"Serial port blocked%s%s%s%s%s%s%s%s\n",
  2624.             ( x & TX_WAITING_FOR_CTS )
  2625.             ? "\nTx waiting for CTS to be turned ON" : "",
  2626.             ( x & TX_WAITING_FOR_DSR )
  2627.             ? "\nTx waiting for DSR to be turned ON" : "",
  2628.             ( x & TX_WAITING_FOR_DCD )
  2629.             ? "\nTx waiting for DCD to be turned ON" : "",
  2630.             ( x & TX_WAITING_FOR_XON )
  2631.             ? "\nTx waiting because XOFF received" : "",
  2632.             ( x & TX_WAITING_TO_SEND_XON )
  2633.             ? "\nTx waiting because XOFF transmitted" : "",
  2634.             ( x & TX_WAITING_WHILE_BREAK_ON )
  2635.             ? "\nTx because BREAK is being transmitted" : "",
  2636.             ( x & TX_WAITING_TO_SEND_IMM )
  2637.             ? "\nCharacter waiting to transmit immediately" : "",
  2638.             ( x & RX_WAITING_FOR_DSR )
  2639.             ? "\nRx waiting for DSR to be turned ON" : "" ) ;
  2640.     }
  2641.     }
  2642. #else /* NOTTOCI is defined */
  2643. /*
  2644.   On the other hand, using DosWrite() (via ttoc()) makes C-Kermit hang
  2645.   if modem signals are not just right, plus we can't handle CTS blockage
  2646.   this way, nor do we get the OS/2 error code.
  2647. */
  2648.     if (ttoc(dopar(c)) < 0) {
  2649.     active = FALSE;
  2650.     sprintf(termessage,"Can't transmit to %s\n",
  2651.         network ? "network" : "serial port");
  2652.     }
  2653. #endif /* NOTTOCI */
  2654.    return 0;
  2655. }
  2656.  
  2657. static int
  2658. sendcharduplex(unsigned char key) {
  2659.     unsigned char csave;
  2660.  
  2661.     key &= cmdmsk;            /* Do any requested masking */
  2662.     csave = key;
  2663.  
  2664.     if (outesc == ES_NORMAL) {        /* If not inside escape seq.. */
  2665.                     /* Translate character sets */
  2666.     if (sxo) key = (*sxo)(key);    /* Local to intermediate. */
  2667.     if (rxo) key = (*rxo)(key);    /* Intermediate to remote. */
  2668.     }
  2669.     if (oskipesc) outesc = chkaes(outesc, key);
  2670.     /* Check output (key) escape sequence status */
  2671.  
  2672.     if (sosi) {                /* Shift-In/Out selected? */
  2673.     if (cmask == 0177) {        /* In 7-bit environment? */
  2674.         if (key & 0200) {        /* 8-bit character? */
  2675.         if (outshift == 0) {    /* If not shifted, */
  2676.             sendchar(SO);    /* shift. */
  2677.             outshift = 1;
  2678.         }
  2679.         } else {
  2680.         if (outshift == 1) {    /* 7-bit character */
  2681.             sendchar(SI);    /* If shifted, */
  2682.             outshift = 0;    /* unshift. */
  2683.         }
  2684.         }
  2685.     }
  2686.     if (key == SO) outshift = 1;    /* User typed SO */
  2687.     if (key == SI) outshift = 0;    /* User typed SI */
  2688.     }
  2689.  
  2690.     key &= cmask;            /* Apply Kermit-to-host mask now. */
  2691.     if (key == '\015') {        /* Handle TERMINAL NEWLINE */
  2692.     int stuff = -1;
  2693.     if (tnlm) {            /* TERMINAL NEWLINE ON */
  2694.         stuff = LF;            /* Stuff LF */
  2695. #ifdef TNCODE
  2696.     } else if (network &&        /* TELNET NEWLINE ON/OFF/RAW */
  2697.            (ttnproto == NP_TELNET) &&
  2698.            (tn_nlm != TNL_CR)) {
  2699.         stuff = (tn_nlm == TNL_CRLF) ? LF : NUL;
  2700. #endif /* TNCODE */
  2701.     }
  2702.     if (stuff > -1) {
  2703.         sendchar(dopar('\015'));    /* Send the CR */
  2704.         if (duplex) {        /* If local echoing... */
  2705.         cwrite('\015');        /*   echo to screen */
  2706.         if (seslog)        /*   and if logging */
  2707.           logchar(csave);    /*   log it */
  2708.         }
  2709.         key = stuff;
  2710.         csave = key;
  2711.     } else if (tt_crd && duplex) {    /* CR-DISPLAY CRLF & local echo */
  2712.         cwrite(CR);            /* so we have to echo CRLF locally */
  2713.         if (seslog)
  2714.           logchar(csave);
  2715.         csave = LF;
  2716.         key = CR;            /* ... but only send a CR */
  2717.     }
  2718.     }
  2719. #ifdef TNCODE
  2720.     /* If user types the 0xff character (TELNET IAC), it must be doubled. */
  2721.     else
  2722.       if (dopar(key) == IAC && network && ttnproto == NP_TELNET)
  2723.     sendchar(IAC); /* and the other one just below. */
  2724. #endif /* TNCODE */
  2725.  
  2726.     sendchar(dopar(key));
  2727.     if (duplex) {
  2728.     cwrite(csave);
  2729.     if (seslog) logchar(csave);
  2730.     }
  2731. }
  2732.  
  2733. /*  S E N D E S C S E Q  --  Send ESC followed by the given string  */
  2734. /*
  2735.   Used for sending host-requested reports, as well as for sending
  2736.   F-keys, arrow keys, etc.  Translation, shifting, etc, are not issues here.
  2737. */
  2738. static int
  2739. sendescseq(CHAR *s) {
  2740.     char c;
  2741.     int pause;
  2742.  
  2743.     pause = (tt_pacing > -1) ? tt_pacing : 50;
  2744.  
  2745.     /* Handle 7-bit vs 8-bit escape sequences...*/
  2746.  
  2747.     if (send_c1 && ((*s == '[' || *s == 'O'))) /* 8-bit C1 controls... */
  2748.       c = (*s++ ^ (CHAR) 0x40) | (CHAR) 0x80;
  2749.     else                /* Or 7-bit escape sequences... */
  2750.       c = ESC;
  2751.     sendchar(c);
  2752.  
  2753.     if (duplex) {            /* Half duplex, echo it to the */
  2754.     cwrite(c);            /* console too ... */
  2755.     if (seslog) logchar(c);        /* and maybe log it in session log */
  2756.     }
  2757.     for ( ; *s; s++ ) {            /* Same deal for the rest */
  2758.     if (!network) msleep(pause);    /* But sleep between each character */
  2759.     sendchar(*s);            /* Otherwise sendchars can overrun */
  2760.     if (duplex) {            /* unbuffered UARTs... */
  2761.         cwrite(*s);
  2762.         if (seslog) logchar(*s);
  2763.     }
  2764.     }
  2765. }
  2766.  
  2767. static void                /* Push from CONNECT mode to OS/2 */
  2768. os2push() {
  2769.     VIOMODEINFO mi;
  2770.     savescreen(&savedscreen,wherex,wherey);
  2771.     mi.cb = sizeof(mi);
  2772.     VioGetMode(&mi, 0);
  2773.     concooked();
  2774.     clearscreen(1, colorcmd);
  2775.     restorecursormode();
  2776.     puts("Enter EXIT to return to C-Kermit.");
  2777.     zshcmd("");
  2778.     conraw();
  2779.     connoi();
  2780.     VioSetMode(&mi, 0);
  2781.     setborder();            /* Put back CONNECT screen border */
  2782.     setcursormode();
  2783.     restorescreen(&savedscreen);
  2784.     if (cursorena)            /* If cursor is enabled */
  2785.       newcursor();            /* turn it on explicitly, in case... */
  2786. }
  2787.  
  2788. void
  2789. os2debugoff() {                /* Turn off debugging from outside */
  2790.     debug(F100,"os2debugoff","",0);
  2791.     attribute = defaultattribute;
  2792. }
  2793.  
  2794. void
  2795. os2bold() {                /* Toggle boldness from the outside */
  2796.     tn_bold = 1 - tn_bold;
  2797. }
  2798.  
  2799. static void                /* Toggle session debugging */
  2800. flipdebug() {
  2801.     if (debses) {
  2802.     attribute = defaultattribute;    /* Back to normal coloring */
  2803.     debses = 0;            /* Turn off session debug flag */
  2804.     } else {
  2805.     debses = 1;            /* Turn on session debug flag */
  2806.     }
  2807.     if (!roll.flag && status_saved < 0)
  2808.       ipadl25();
  2809. }
  2810.  
  2811. /* Initialize key map */
  2812.  
  2813. void
  2814. keymapinit() {
  2815.  
  2816.     keymap[0x103] = 0x00;        /* Ctrl-2 = NUL */
  2817.     keymap[0x200 | DEL ] = DEL;        /* Ctrl-Backspace = DEL */
  2818.     keymap[0x200 | ' ' ] = 0x00;    /* Ctrl-Space = NUL */
  2819.  
  2820.     keymap[0x200 | '+' ] = '+';        /* Predefine ambiguous keypad keys */
  2821.     keymap[0x200 | '-' ] = '-';
  2822.     keymap[0x200 | '*' ] = '*';
  2823.     keymap[0x200 | '/' ] = '/';
  2824.     keymap[0x200 | '\r'] = '\r';
  2825.     keymap[0x200 | '\n'] = '\n';
  2826.     keymap[0x200 | '.' ] = '.';
  2827.     keymap[0x200 | ',' ] = ',';
  2828.     keymap[0x200 | '0' ] = '0';
  2829.     keymap[0x200 | '1' ] = '1';
  2830.     keymap[0x200 | '2' ] = '2';
  2831.     keymap[0x200 | '3' ] = '3';
  2832.     keymap[0x200 | '4' ] = '4';
  2833.     keymap[0x200 | '5' ] = '5';
  2834.     keymap[0x200 | '6' ] = '6';
  2835.     keymap[0x200 | '7' ] = '7';
  2836.     keymap[0x200 | '8' ] = '8';
  2837.     keymap[0x200 | '9' ] = '9';
  2838.  
  2839.     keymap[0x109] = 9;            /* Tab-Key = Tab */
  2840.     keymap[0x10f] = 8;            /* Shift-Tab = Backtab = Backspace */
  2841.     keymap[0x11B] = 27;                 /* Shift-Escape = Escape */
  2842.     keymap[0x10f] = 8;            /* Backtab = Backspace */
  2843.     keymap[270] = 8;            /* Alt-Backspace = Backspace */
  2844.     keymap[0x153] = 127;        /* Keypad Del sends DEL */
  2845.     keymap[595] = 127;            /* Gray Delete send DEL */
  2846.  
  2847. #ifndef NOKVERBS
  2848.     keymap[511] = F_KVERB | K_HOLDSCRN; /* Hold Screen */
  2849.     keymap[767] = F_KVERB | K_HOLDSCRN; /* Hold Screen */
  2850.  
  2851.     /* Arrow keys */
  2852.  
  2853.     keymap[584] = F_KVERB | K_UPARR;    /* Up Arrow    Gray */
  2854.     keymap[328] = F_KVERB | K_UPARR;    /* Up Arrow    Numeric */
  2855.     keymap[587] = F_KVERB | K_LFARR;    /* Left Arrow  Gray */
  2856.     keymap[331] = F_KVERB | K_LFARR;    /* Left Arrow  Numeric*/
  2857.     keymap[589] = F_KVERB | K_RTARR;    /* Right Arrow Gray */
  2858.     keymap[333] = F_KVERB | K_RTARR;    /* Right Arrow Numeric */
  2859.     keymap[592] = F_KVERB | K_DNARR;    /* Down Arrow  Gray */
  2860.     keymap[336] = F_KVERB | K_DNARR;    /* Down Arrow  Numeric */
  2861.  
  2862.     /* Screen scroll */
  2863.  
  2864.     keymap[585] = F_KVERB | K_UPSCN;    /* Page Up:        Up one screen */
  2865.     keymap[329] = F_KVERB | K_UPSCN;    /* PgUp:           Up one screen */
  2866.     keymap[644] = F_KVERB | K_UPONE;    /* Ctrl Page Up:   Up one line */
  2867.     keymap[388] = F_KVERB | K_UPONE;    /* Ctrl PgUp:      Up one line */
  2868.     keymap[593] = F_KVERB | K_DNSCN;    /* Page Down:      Down one screen */
  2869.     keymap[337] = F_KVERB | K_DNSCN;    /* PgDn:           Down one screen */
  2870.     keymap[630] = F_KVERB | K_DNONE;    /* Ctrl Page Down: Down one line */
  2871.     keymap[374] = F_KVERB | K_DNONE;    /* Ctrl PgDn:      Down one line */
  2872.     keymap[583] = F_KVERB | K_HOMSCN;    /* Gray Home:      Top of buffer */
  2873.     keymap[327] = F_KVERB | K_HOMSCN;    /* Numeric Home:   Top of buffer */
  2874.     keymap[591] = F_KVERB | K_ENDSCN;    /* Gray End:       Bottom of buffer */
  2875.     keymap[335] = F_KVERB | K_ENDSCN;    /* Numeric End:    Bottom of buffer */
  2876.  
  2877.     /* Numeric keypad */
  2878.  
  2879.     keymap[315] = F_KVERB | K_PF1;    /* F1 = DEC PF1 */
  2880.     keymap[316] = F_KVERB | K_PF2;    /* F2 = DEC PF2 */
  2881.     keymap[317] = F_KVERB | K_PF3;    /* F3 = DEC PF3 */
  2882.     keymap[318] = F_KVERB | K_PF4;    /* F4 = DEC PF4 */
  2883.  
  2884.     keymap[385] = F_KVERB | K_KP0;    /* Alt-0, Top Rank = DEC Keypad 0 */
  2885.     keymap[376] = F_KVERB | K_KP1;    /* Alt-1, Top Rank = DEC Keypad 1 */
  2886.     keymap[377] = F_KVERB | K_KP2;    /* Alt-2, Top Rank = DEC Keypad 2 */
  2887.     keymap[378] = F_KVERB | K_KP3;    /* Alt-3, Top Rank = DEC Keypad 3 */
  2888.     keymap[379] = F_KVERB | K_KP4;    /* Alt-4, Top Rank = DEC Keypad 4 */
  2889.     keymap[380] = F_KVERB | K_KP5;    /* Alt-5, Top Rank = DEC Keypad 5 */
  2890.     keymap[381] = F_KVERB | K_KP6;    /* Alt-6, Top Rank = DEC Keypad 6 */
  2891.     keymap[382] = F_KVERB | K_KP7;    /* Alt-7, Top Rank = DEC Keypad 7 */
  2892.     keymap[383] = F_KVERB | K_KP8;    /* Alt-8, Top Rank = DEC Keypad 8 */
  2893.     keymap[384] = F_KVERB | K_KP9;    /* Alt-9, Top Rank = DEC Keypad 9 */
  2894.  
  2895.     keymap[386] = F_KVERB | K_KPMINUS;    /* Alt -, Top Rank = DEC Keypad - */
  2896.     keymap[307] = F_KVERB | K_KPCOMA;    /* Alt-Comma = DEC Keypad comma   */
  2897.     keymap[308] = F_KVERB | K_KPDOT;    /* Alt-Period = DEC Keypad period */
  2898.     keymap[284] = F_KVERB | K_KPENTER;    /* Alt-Enter  = DEC Keypad Enter  */
  2899.  
  2900.     /* The compose key */
  2901.  
  2902.     keymap[302] = F_KVERB | K_COMPOSE;    /* Alt-c, Compose */
  2903.  
  2904.     /* Kermit action verbs */
  2905.     /* Default mappings designed so key names are valid on all systems */
  2906.  
  2907.     keymap[275] = F_KVERB | K_RESET;    /* Alt-R, Reset emulator */
  2908.     keymap[387] = F_KVERB | K_RESET;    /* Alt-=, Reset emulator */
  2909.     keymap[301] = F_KVERB | K_EXIT;    /* Alt-x, Exit emulator */
  2910.     keymap[304] = F_KVERB | K_BREAK;    /* Alt-b, Send BREAK */
  2911.     keymap[294] = F_KVERB | K_LBREAK;    /* Alt-l, Send Long BREAK */
  2912.     keymap[278] = F_KVERB | K_HANGUP;    /* Alt-u, Hangup connection */
  2913.     keymap[281] = F_KVERB | K_DUMP;    /* Alt-p, Print/Dump screen */
  2914.     keymap[370] = F_KVERB | K_PRTSCN;    /* Ctrl-PrintScreen, Toggle printing */
  2915.     keymap[415] = F_KVERB | K_PRINTFF;    /* Alt-End, Print FF */
  2916.     keymap[417] = F_KVERB | K_DOS;    /* Alt-Page Down, Push to OS/2 */
  2917.     keymap[303] = F_KVERB | K_FLIPSCN;    /* Alt-v, video toggle */
  2918.     keymap[288] = F_KVERB | K_DEBUG;    /* Alt-d, Toggle debugging */
  2919.     keymap[291] = F_KVERB | K_HELP;    /* Alt-h, Help */
  2920.     keymap[510] = F_KVERB | K_IGNORE;    /* Num Lock, don't beep */
  2921.     keymap[766] = F_KVERB | K_IGNORE;    /* Num Lock, don't beep */
  2922. #endif /* NOKVERBS */
  2923. }
  2924.  
  2925. #ifndef NOKVERBS
  2926.  
  2927. VOID
  2928. keynaminit() {
  2929.  
  2930. /*  These names apply only to US keyboards.  */
  2931.  
  2932.     int i;
  2933.  
  2934.     for (i = 0; i < 512; i++)
  2935.       keynam[i] = NULL;
  2936.  
  2937.     keynam[259 - 256] = "Ctrl-2";
  2938.     keynam[265 - 256] = "Tab";
  2939.     keynam[270 - 256] = "Alt-Backspace";
  2940.     keynam[271 - 256] = "Shift-Tab";
  2941.     keynam[272 - 256] = "Alt-q";
  2942.     keynam[273 - 256] = "Alt-w";
  2943.     keynam[274 - 256] = "Alt-e";
  2944.     keynam[275 - 256] = "Alt-r";
  2945.     keynam[276 - 256] = "Alt-t";
  2946.     keynam[277 - 256] = "Alt-y";
  2947.     keynam[278 - 256] = "Alt-u";
  2948.     keynam[279 - 256] = "Alt-i";
  2949.     keynam[280 - 256] = "Alt-o";
  2950.     keynam[281 - 256] = "Alt-p";
  2951.     keynam[282 - 256] = "Alt-[";
  2952.     keynam[283 - 256] = "Shift-Esc";    /* Fullscreen sessions only! */
  2953.     keynam[284 - 256] = "Alt-Enter";
  2954.     keynam[286 - 256] = "Alt-a";
  2955.     keynam[287 - 256] = "Alt-s";
  2956.     keynam[288 - 256] = "Alt-d";
  2957.     keynam[289 - 256] = "Alt-f";
  2958.     keynam[290 - 256] = "Alt-g";
  2959.     keynam[291 - 256] = "Alt-h";
  2960.     keynam[292 - 256] = "Alt-j";
  2961.     keynam[293 - 256] = "Alt-k";
  2962.     keynam[294 - 256] = "Alt-l";
  2963.     keynam[295 - 256] = "Alt-;";
  2964.     keynam[296 - 256] = "Alt-'";
  2965.     keynam[297 - 256] = "Alt-grave";
  2966.     keynam[299 - 256] = "Alt-\\";
  2967.     keynam[300 - 256] = "Alt-z";
  2968.     keynam[301 - 256] = "Alt-x";
  2969.     keynam[302 - 256] = "Alt-c";
  2970.     keynam[303 - 256] = "Alt-v";
  2971.     keynam[304 - 256] = "Alt-b";
  2972.     keynam[305 - 256] = "Alt-n";
  2973.     keynam[306 - 256] = "Alt-m";
  2974.     keynam[307 - 256] = "Alt-,";
  2975.     keynam[308 - 256] = "Alt-.";
  2976.     keynam[309 - 256] = "Alt-?";
  2977.     keynam[311 - 256] = "Alt-Kp *";
  2978.     keynam[315 - 256] = "F1";
  2979.     keynam[316 - 256] = "F2";
  2980.     keynam[317 - 256] = "F3";
  2981.     keynam[318 - 256] = "F4";
  2982.     keynam[319 - 256] = "F5";
  2983.     keynam[320 - 256] = "F6";
  2984.     keynam[321 - 256] = "F7";
  2985.     keynam[322 - 256] = "F8";
  2986.     keynam[323 - 256] = "F9";
  2987.     keynam[324 - 256] = "F10";
  2988.     keynam[327 - 256] = "Kp Home";
  2989.     keynam[329 - 256] = "PgUp";
  2990.     keynam[330 - 256] = "Alt-Kp -";
  2991.     keynam[334 - 256] = "Alt-Kp +";
  2992.     keynam[335 - 256] = "Kp End";
  2993.     keynam[337 - 256] = "PgDn";
  2994.     keynam[339 - 256] = "Kp Del";
  2995.     keynam[350 - 256] = "Ctrl-F1";
  2996.     keynam[351 - 256] = "Ctrl-F2";
  2997.     keynam[352 - 256] = "Ctrl-F3";
  2998.     keynam[353 - 256] = "Ctrl-F4";
  2999.     keynam[354 - 256] = "Ctrl-F5";
  3000.     keynam[355 - 256] = "Ctrl-F6";
  3001.     keynam[356 - 256] = "Ctrl-F7";
  3002.     keynam[357 - 256] = "Ctrl-F8";
  3003.     keynam[358 - 256] = "Ctrl-F9";
  3004.     keynam[359 - 256] = "Ctrl-F10";
  3005.     keynam[360 - 256] = "Alt-F1";
  3006.     keynam[361 - 256] = "Alt-F2";
  3007.     keynam[362 - 256] = "Alt-F3";
  3008.     keynam[363 - 256] = "Alt-F4";
  3009.     keynam[364 - 256] = "Alt-F5";
  3010.     keynam[365 - 256] = "Alt-F6";
  3011.     keynam[366 - 256] = "Alt-F7";
  3012.     keynam[367 - 256] = "Alt-F8";
  3013.     keynam[368 - 256] = "Alt-F9";
  3014.     keynam[369 - 256] = "Alt-F10";
  3015.     keynam[370 - 256] = "Ctrl-Print Screen";
  3016.     keynam[371 - 256] = "Ctrl-Kp 4";
  3017.     keynam[372 - 256] = "Ctrl-Kp 6";
  3018.     keynam[373 - 256] = "Ctrl-Kp 1";
  3019.     keynam[373 - 256] = "Ctrl-Kp End";
  3020.     keynam[374 - 256] = "Ctrl-Kp 4";
  3021.     keynam[374 - 256] = "Ctrl-PgDn";
  3022.     keynam[375 - 256] = "Ctrl-Kp 7";
  3023.     keynam[375 - 256] = "Ctrl-Kp Home";
  3024.     keynam[376 - 256] = "Alt-1";
  3025.     keynam[377 - 256] = "Alt-2";
  3026.     keynam[378 - 256] = "Alt-3";
  3027.     keynam[379 - 256] = "Alt-4";
  3028.     keynam[380 - 256] = "Alt-5";
  3029.     keynam[381 - 256] = "Alt-6";
  3030.     keynam[382 - 256] = "Alt-7";
  3031.     keynam[383 - 256] = "Alt-8";
  3032.     keynam[384 - 256] = "Alt-9";
  3033.     keynam[385 - 256] = "Alt-0";
  3034.     keynam[386 - 256] = "Alt-minus";
  3035.     keynam[387 - 256] = "Alt-=";
  3036.     keynam[388 - 256] = "Ctrl-PgUp";
  3037.     keynam[389 - 256] = "F11";
  3038.     keynam[390 - 256] = "F12";
  3039.     keynam[393 - 256] = "Ctrl-F11";
  3040.     keynam[394 - 256] = "Ctrl-F12";
  3041.     keynam[395 - 256] = "Alt-F11";
  3042.     keynam[396 - 256] = "Alt-F12";
  3043.     keynam[397 - 256] = "Ctrl-Kp 8";
  3044.     keynam[398 - 256] = "Ctrl-Kp -";
  3045.     keynam[399 - 256] = "Ctrl-Kp 5";
  3046.     keynam[400 - 256] = "Ctrl-Kp +";
  3047.     keynam[401 - 256] = "Ctrl-Kp 2";
  3048.     keynam[402 - 256] = "Ctrl-Kp 0";
  3049.     keynam[403 - 256] = "Ctrl-Kp Del";
  3050.     keynam[403 - 256] = "Ctrl-Kp Del";
  3051.     keynam[404 - 256] = "Ctrl-Tab";
  3052.     keynam[405 - 256] = "Ctrl-Kp /";
  3053.     keynam[406 - 256] = "Ctrl-Kp *";
  3054.     keynam[408 - 256] = "Alt-Up Arrow";
  3055.     keynam[409 - 256] = "Alt-Page Up";
  3056.     keynam[411 - 256] = "Alt-Left Arrow";
  3057.     keynam[413 - 256] = "Alt-Right Arrow";
  3058.     keynam[415 - 256] = "Alt-End";
  3059.     keynam[416 - 256] = "Alt-Down Arrow";
  3060.     keynam[417 - 256] = "Alt-Page Down";
  3061.     keynam[418 - 256] = "Alt-Insert";
  3062.     keynam[419 - 256] = "Alt-Delete";
  3063.     keynam[420 - 256] = "Alt-Kp /";
  3064.     keynam[421 - 256] = "Alt-Tab";
  3065.     keynam[422 - 256] = "Alt-Kp Enter";
  3066.     keynam[510 - 256] = "Num Lock";
  3067.     keynam[510 - 256] = "Pause";
  3068.     keynam[511 - 256] = "Scroll Lock";
  3069.     keynam[522 - 256] = "Ctrl-Kp Enter";
  3070.     keynam[583 - 256] = "Home";
  3071.     keynam[585 - 256] = "Page Up";
  3072.     keynam[591 - 256] = "End";
  3073.     keynam[593 - 256] = "Page Down";
  3074.     keynam[627 - 256] = "Ctrl-Left Arrow";
  3075.     keynam[628 - 256] = "Ctrl-Right Arrow";
  3076.     keynam[629 - 256] = "Ctrl-End";
  3077.     keynam[630 - 256] = "Ctrl-Page Down";
  3078.     keynam[631 - 256] = "Ctrl-Home";
  3079.     keynam[639 - 256] = "Ctrl-Backspace";
  3080.     keynam[644 - 256] = "Ctrl-Page Up";
  3081.     keynam[653 - 256] = "Ctrl-Up Arrow";
  3082.     keynam[657 - 256] = "Ctrl-Down Arrow";
  3083.     keynam[658 - 256] = "Ctrl-Insert";
  3084.     keynam[659 - 256] = "Ctrl-Delete";
  3085.     keynam[766 - 256] = "Num Lock";
  3086.     keynam[766 - 256] = "Pause";
  3087.     keynam[767 - 256] = "Scroll Lock";
  3088. }
  3089.  
  3090. /* DEC F-key strings */
  3091. static char * fkeys[] = {
  3092.  "[17~","[18~","[19~","[20~","[21~",    /* F6  - F10 */
  3093.  "[23~","[24~","[25~","[26~","[28~",    /* F11 - F15 */
  3094.  "[29~","[31~","[32~","[33~","[34~"    /* F16 - F20 */
  3095. };
  3096.  
  3097. /* DEC Editing key strings */
  3098. static char * ekeys[] = {
  3099.     "[1~",    /* Find */
  3100.     "[2~",    /* Insert */
  3101.     "[3~",    /* Remove */
  3102.     "[4~",    /* Select */
  3103.     "[5~",    /* Previous Screen */
  3104.     "[6~"    /* Next Screen */
  3105. };
  3106.  
  3107. #ifdef NETCONN
  3108. #ifdef TCPSOCKET
  3109. do_tn_cmd(CHAR x) {
  3110.     CHAR temp[3];
  3111.     if (network && ttnproto == NP_TELNET) { /* TELNET */
  3112.     temp[0] = (CHAR) IAC;
  3113.     temp[1] = x;
  3114.     temp[2] = NUL;
  3115.     ttol((CHAR *)temp,2);
  3116.     } else 
  3117.       bleep();
  3118. }
  3119. #endif /* TCPSOCKET */
  3120. #endif /* NETCONN */
  3121.  
  3122.  
  3123. /*  D O K V E R B  --  Execute a keyboard verb  */
  3124.  
  3125. static void
  3126. dokverb(int k) {            /* 'k' is the kverbs[] table index. */
  3127.     int x;
  3128.     char escbuf[10];            /* For building key escape sequences */
  3129. /*
  3130.   Items are grouped according to function, and checked approximately
  3131.   in order of how frequently they are used.
  3132. */
  3133.     k &= ~(F_KVERB);            /* Clear KVERB flag */
  3134.  
  3135.     if (k >= K_ACT_MIN && k <= K_ACT_MAX) {
  3136.  
  3137.     switch (k) {            /* Common Kermit actions first ... */
  3138.  
  3139.       case K_EXIT:            /* \Kexit: */
  3140.         active = FALSE; return;    /*   Exit from terminal emulator */
  3141.       case K_BREAK:            /* \Kbreak */
  3142.         ttsndb(); return;        /*   Send a BREAK */
  3143.       case K_DOS:            /* \Kdos or \Kos2 */
  3144.         os2push(); return;        /*   Push to system */
  3145.       case K_RESET:            /* \Kreset */
  3146.         doreset(1); return;        /*   Reset terminal emulator */
  3147.       case K_HELP:            /* \Khelp */
  3148.         popuphelp(0); return;    /*   Pop-up help message */
  3149.       case K_PRTSCN:        /* \Kprtscn */
  3150.         if (printon) {        /*   Toggle printer on/off */
  3151.         xprint = FALSE;        /*   It's on, turn it off */
  3152.         printeroff();
  3153.         } else {            /*   vice versa ... */
  3154.         printeron();
  3155.         }
  3156.         return;
  3157.       case K_DUMP:            /* \Kdump   */
  3158.         x = xprintff; xprintff = 0;    /*   Print/Dump current screen */
  3159.         prtscreen(1,ysize);
  3160.         xprintff = x; return;
  3161.       case K_PRINTFF:        /* \KprintFF - Print Form Feed */
  3162.         printeron();
  3163.         fprintf(lst,"%c",FF);    /* Send formfeed */
  3164.         printeroff();
  3165.         return;
  3166.       case K_HANGUP:        /* \Khangup */
  3167.         hangnow = 1;        /*   Hang up connection */
  3168.         active = 0;            /*   and return to prompt. */
  3169.         strcpy(termessage, "Hangup.\n");
  3170.         return;
  3171.       case K_NULL:            /* \Knull */
  3172.         sendcharduplex('\0'); return; /*   Send a NUL */
  3173.       case K_LBREAK:        /* \Klbreak: */
  3174.         ttsndlb(); return;        /*   Send a Long BREAK */
  3175.       case K_DEBUG:            /* \Kdebug */
  3176.         flipdebug(); return;    /*   Toggle debugging */
  3177.       case K_FLIPSCN:        /* \KflipScn */
  3178.         flipscreen(); return;    /*   Toggle video */
  3179.       case K_HOLDSCRN:        /* \KholdScrn */
  3180.         save_status_line();        /* Save current status line */
  3181.         strcpy(usertext,
  3182.            " Scroll-Lock      Press (almost) any key to unlock"
  3183.            );
  3184.         helptext[0] = exittext[0] = hostname[0] = NUL;
  3185.         line25();            /* Make special status line */
  3186.         congks(0);            /* Wait for any keystroke */
  3187.         restore_status_line();    /* Restore status line */
  3188.         return;
  3189.       case K_IGNORE:        /* \Kignore */
  3190.         return;
  3191. #ifdef NETCONN
  3192. #ifdef TCPSOCKET
  3193.       case K_TN_AYT:        /* TELNET Are You There */
  3194.         do_tn_cmd((CHAR) AYT);
  3195.         return;
  3196.       case K_TN_IP:            /* TELNET Interrupt Process */
  3197.         do_tn_cmd((CHAR) IP);
  3198.         return;
  3199. #endif /* TCPSOCKET */
  3200. #endif /* NETCONN */
  3201.       default:            /* None of the above */
  3202.         return;            /* Ignore this key and return. */
  3203.     }
  3204.     }
  3205.     if (k >= K_ROLLMIN && k <= K_ROLLMAX) { /* Screen rollback... */
  3206.     scrollback(k);
  3207.     return;
  3208.     }
  3209.     if (k >= K_ARR_MIN && k <= K_ARR_MAX) { /* DEC arrow (cursor) keys */
  3210.     if (tt_type >= TT_VT100)
  3211.       sprintf(escbuf,"%c%c",( (tt_arrow == TTK_APPL) ? 'O' : '[' ),
  3212.           'A' + (k - K_UPARR));
  3213.     else
  3214.       sprintf(escbuf,"%c", 'A' + (k - K_UPARR));
  3215.     sendescseq(escbuf);
  3216.     return;
  3217.     }
  3218.     if (k >= K_PF1 && k <= K_PF4) {    /* DEC PF keys */
  3219.     char *p = escbuf;
  3220.     if (tt_type >= TT_VT100)    /* SS3 P..S for VT100 & above */
  3221.       *p++ = 'O';
  3222.     *p++ = 'P' + (k - K_PF1);    /* or just ESC P..S for VT52 */
  3223.     *p = NUL;
  3224.     sendescseq(escbuf);
  3225.     return;
  3226.     }
  3227.     if (k >= K_KP0 && k <= K_KP9) {    /* DEC numeric keypad keys */
  3228.     if (tt_keypad == TTK_NORM)    /* Keypad in numeric mode */
  3229.       sendcharduplex((CHAR) ('0' + (CHAR) (k - K_KP0)));
  3230.     else {                /* Application mode */
  3231.         sprintf(escbuf,
  3232.             "%c%c",
  3233.             ((tt_type >= TT_VT100) ? 'O' : '?'),
  3234.             ('p' + (k - K_KP0))
  3235.             );
  3236.         sendescseq(escbuf);
  3237.     }
  3238.     return;
  3239.     }
  3240.     if (k >= K_KPCOMA && k <= K_KPDOT) { /* DEC keypad punctuation keys */
  3241.     if (tt_keypad == TTK_NORM)    /* Keypad in numeric mode */
  3242.       sendcharduplex((CHAR) (',' + (CHAR) (k - K_KPCOMA)));
  3243.     else {                 /* Keypad in application mode */
  3244.         sprintf(escbuf,
  3245.             "%c%c",
  3246.             ((tt_type >= TT_VT100) ? 'O' : '?'),
  3247.             ('l' + (k - K_KPCOMA))
  3248.             );
  3249.         sendescseq(escbuf);
  3250.     }
  3251.     return;
  3252.     }
  3253.     if (k == K_KPENTER) {        /* DEC keypad Enter key */
  3254.     if (tt_keypad == TTK_NORM) {    /* Keypad in numeric mode */
  3255.         sendcharduplex('\015');    /* Send CR */
  3256.         if (tnlm)
  3257.           sendcharduplex('\012');    /* Newline mode, send LF too */ 
  3258.     } else {            /* Keypad in application mode */
  3259.         sprintf(escbuf,
  3260.             "%c%M",
  3261.             ((tt_type >= TT_VT100) ? 'O' : '?')
  3262.             );
  3263.         sendescseq(escbuf);
  3264.     }
  3265.     return;
  3266.     }
  3267.     if (k >= K_DECFIND && k <= K_DECNEXT) { /* DEC editing keypad keys */
  3268.         if (tt_type >= TT_VT220)    /* VT220 and above */
  3269.       sendescseq(ekeys[k - K_DECFIND]);
  3270.     else bleep();
  3271.     return;
  3272.     }
  3273.     if (k >= K_DECF6 && k <= K_DECF20) { /* DEC top-rank function keys */
  3274.         if (tt_type >= TT_VT220) {     /* VT220 and above */
  3275.         sendescseq(fkeys[k - K_DECF6]);
  3276.         return;
  3277.     } else {            /* VT102 or lower */
  3278.         switch (k) {
  3279.           case K_DECF11:
  3280.         sendcharduplex(ESC); return;
  3281.           case K_DECF12:
  3282.         sendcharduplex(BS); return; 
  3283.           case K_DECF13:
  3284.         sendcharduplex(LF); return;
  3285.           default:
  3286.         bleep();
  3287.         return; 
  3288.         }        
  3289.     }
  3290.     }
  3291.     if (k == K_COMPOSE) {        /* Compose key */
  3292.     int i;
  3293.     CHAR x1, x2, c;
  3294.     save_status_line();
  3295.     strcpy(exittext,"Cancel: Space"); /* Make special one */
  3296.     sprintf(usertext," COMPOSE: [  ]"); /* with mini-echo-buffer */
  3297.     if (vik.help > 255 && keynam[vik.help - 256])
  3298.       sprintf(helptext, "Help: %s", keynam[vik.help - 256]);
  3299.     line25();
  3300.     while ((x1 = keymap[congks(0)]) == K_HELP) /* Let them ask for help */
  3301.       popuphelp(2);
  3302.     if (macrotab[x1] || (x1 <= SP) || (x1 > 0x7E)) {
  3303.         if (x1 != SP) bleep();
  3304.         goto compose_exit;
  3305.     }    
  3306.     sprintf(usertext," COMPOSE: [%c ]", x1); /* Echo first char */
  3307.     line25();
  3308.  
  3309.     while ((x2 = keymap[congks(0)]) == K_HELP)
  3310.       popuphelp(2);
  3311.     if (x2 <= SP || x2 > 0x7E) {
  3312.         if (x2 != SP) bleep();
  3313.         goto compose_exit;
  3314.     }    
  3315.     sprintf(usertext," COMPOSE: [%c%c]", x1, x2); /* Echo second char */
  3316.     line25();
  3317.     for (i = 0; i < nl1ktab; i++)    /* Look up the 2-char sequence */
  3318.       if ((x1 == l1ktab[i].c1) && (x2 == l1ktab[i].c2))
  3319.         break;
  3320.     if (i >= nl1ktab) {        /* Not found */
  3321.         bleep();
  3322.         goto compose_exit;
  3323.     } else c = l1ktab[i].c3;    /* Character we found */
  3324.     if (sxi) c = (*sxi)((CHAR)c);    /* Xlate from remote to intermediate */
  3325.     if (rxi) c = (*rxi)((CHAR)c);    /* and from intermediate to local */
  3326.     sendcharduplex(c);        /* Send it */
  3327.     msleep(333);            /* Some time to look at minibuffer */
  3328.       compose_exit:            /* Common exit point */
  3329.     restore_status_line();        /* Restore status line */
  3330.     return;
  3331.     }
  3332.  
  3333.     if (k == K_KB_HEB) {        /* Hebrew keyboard support... */
  3334.     sethebrewmode();
  3335.     return;
  3336.     }
  3337.     if (k == K_KB_ENG) {
  3338.     resethebrewmode();
  3339.     return;
  3340.     }
  3341.  
  3342. #ifdef COMMENT
  3343.     if (k >= K_UDKF6 && k <= K_UDKF20) { /* User-Defined Keys */
  3344.     return;                /* Not implemented yet */
  3345.     }
  3346. #endif /* COMMENT */
  3347. }
  3348. #endif /* NOKVERBS */
  3349.  
  3350. /*  S E N D K E Y D E F  --  Send key definition  */
  3351.   
  3352. static void
  3353. sendkeydef(unsigned char *s) {
  3354.   
  3355. #ifndef NOKVERBS
  3356.     int x, y, brace = 0;
  3357.     int pause;
  3358.     char * p, * b;
  3359. #define K_BUFLEN 30
  3360.     char kbuf[K_BUFLEN + 1];        /* Key verb name buffer */
  3361. #endif /* NOKVERBS */
  3362.  
  3363.     pause = (tt_pacing > -1) ? tt_pacing : 50;
  3364.  
  3365.     for ( ; *s; s++ ) {            /* Go through the string */
  3366. #ifdef NOKVERBS
  3367.     if (!network) msleep(pause);    /* To prevent UART overruns... */
  3368.     sendcharduplex(*s);        /* Send each character literally. */
  3369.   
  3370. #else    /* \Kverb support ... */
  3371.  
  3372.     if (*s != CMDQ) {        /* Normal character */
  3373.         if (!network) msleep(pause); /* Prevent UART overruns. */
  3374.         sendcharduplex(*s);        /* Send it */
  3375.         continue;            /* Get next, etc. */
  3376.     }
  3377.     b = s++;            /* Get next character */
  3378.     if (!*s) {
  3379.         keydefptr = NULL;
  3380.         return;
  3381.     }
  3382.     if (*s == '{') {        /* Opening brace? */
  3383.         brace = 1;            /* Remember */
  3384.         s++;            /* Go to next character */
  3385.         if (!*s) {
  3386.         keydefptr = NULL;
  3387.         return;
  3388.         }
  3389.     }
  3390.     if (*s == 'K' || *s == 'k') {    /* Have K verb? */
  3391.         s++;
  3392.         if (!*s) {
  3393.         keydefptr = NULL;
  3394.         return;
  3395.         }
  3396.  
  3397. /*
  3398.   We assume that the verb name is {braced}, or it extends to the end of the
  3399.   string, s, or it ends with a space, control character, or backslash.
  3400. */
  3401.         p = kbuf;            /* Copy verb name into local buffer */
  3402.         x = 0;
  3403.         while ((x++ < K_BUFLEN) && (*s > SP) && (*s != CMDQ)) {
  3404.         if (brace && *s == '}') {
  3405.             break;
  3406.         }
  3407.         *p++ = *s++;
  3408.         }
  3409.         if (*s && !brace)        /* If we broke because of \, etc, */
  3410.           s--;            /*  back up so we get another look. */
  3411.         brace = 0;
  3412.         *p = NUL;            /* Terminate. */
  3413.         p = kbuf;            /* Point back to beginning */
  3414.         debug(F110,"sendkeydef kverb",p,0);
  3415.         y = xlookup(kverbs,p,nkverbs,&x); /* Look it up */
  3416.         debug(F101,"sendkeydef lookup",0,y);
  3417.         if (y > -1) {
  3418. #ifdef __32BIT__
  3419.         {
  3420.             DosRequestMutexSem( hmtxScreenSem, SEM_INDEFINITE_WAIT ) ;
  3421.             dokverb(y) ;      
  3422.             DosReleaseMutexSem( hmtxScreenSem ) ;
  3423.         }
  3424. #else
  3425.         dokverb(y);    
  3426. #endif /* __32BIT__ */
  3427. #ifndef NOSPL
  3428.         } else {            /* Is it a macro? */
  3429.         y = mxlook(mactab,p,nmac);
  3430.         if (y > -1) {
  3431.             keymac = 1;        /* Flag for key macro active */
  3432.             keymacx = y;    /* Key macro index */
  3433.             keydefptr = s;    /* Where to resume next time */
  3434.             debug(F111,"sendkeydef mxlook",keydefptr,y);
  3435.             active = 0;        /* Leave CONNECT mode */
  3436.         }
  3437. #endif /* NOSPL */
  3438.         }
  3439.     } else if (*s == 'V' || *s == 'v') { /* Have \v(xxx)? */
  3440.         s++;            /* Next char */
  3441.         if (!*s)
  3442.           return;
  3443.         if (*s != '(') {        /* Should be left paren */
  3444.         if (!network) msleep(pause); /* Prevent UART overruns. */
  3445.         sendcharduplex(CMDQ);
  3446.         if (!network) msleep(pause); /* Prevent UART overruns. */
  3447.         sendcharduplex(*s);
  3448.         continue;
  3449.         }
  3450.         b = s - 1;            /* Save my place */
  3451.         s++;            /* Point past paren */
  3452.         p = kbuf;            /* Point to word buffer */
  3453.         x = 0;            /* Copy verb into it */
  3454.         while ((x++ < K_BUFLEN) && (*s > SP) && (*s != ')'))
  3455.           *p++ = *s++;
  3456.         *p = NUL;
  3457.         if (*s != ')') {        /* Have terminating paren? */
  3458.         if (!network) msleep(pause); /* Prevent UART overruns. */
  3459.         sendcharduplex(CMDQ);    /* No, send this literally */
  3460.         s = b;
  3461.         continue;
  3462.         } else {
  3463.         p = kbuf;        /* Point back to beginning */
  3464.         debug(F110,"sendkeydef v(verb)",p,0);
  3465.         p = nvlook(p);        /* Look it up. */
  3466.         if (!p)            /* Not found, */
  3467.           continue;        /* continue silently. */
  3468.         while (*p) {        /* Send it. */
  3469.             if (!network) msleep(pause); /* Prevent UART overruns. */
  3470.             sendcharduplex(*p++);
  3471.         }
  3472.         if (!*s)
  3473.           return;
  3474.         }
  3475.     } else {            /* Not \K, \{K or \V */
  3476.         if (!network) msleep(pause); /* Prevent UART overruns. */
  3477.         sendcharduplex(CMDQ);    /* Back up and send backslash, */
  3478.         if (brace) {        /* and maybe a left brace, */
  3479.         if (!network) msleep(pause); /* Prevent UART overruns. */
  3480.         sendcharduplex('{');
  3481.         brace = 0;
  3482.         }
  3483.         if (!network) msleep(pause);    /* Prevent UART overruns. */
  3484.         if (*s) sendcharduplex(*s);    /* and this char literally. */
  3485.     }
  3486.     if (!*s) {
  3487.         keydefptr = NULL;
  3488.         return;
  3489.     }
  3490. #endif /* NOKVERBS */
  3491.     }
  3492.     keydefptr = NULL;
  3493. }
  3494.  
  3495. /* Scrollback handler */
  3496. /*
  3497.   Totally rewritten for edit 190 to allow TERMINAL ROLL options and to
  3498.   use new keymap  - fdc.
  3499. */
  3500. static void
  3501. scrollback(int key) {            /* Keycode */
  3502.     int nlines,                /* How many lines to roll */
  3503.       nolblines,            /* Lines above top of screen */
  3504.       i, il;                /* Workers */
  3505.  
  3506.     /* Initialization */
  3507.  
  3508. #ifdef DEBUG
  3509.     if (deblog) {
  3510.     debug(F101,"scrollback key","",key);
  3511.     debug(F101,"scrollback botline","",roll.botline);
  3512.     debug(F101,"scrollback numlines","",roll.numlines);
  3513.     debug(F101,"scrollback linesleft","",roll.linesleft);
  3514.     debug(F101,"scrollback nextline","",roll.nextline);
  3515.     debug(F101,"scrollback flag","",roll.flag);
  3516.     debug(F101,"scrollback tt_roll","",tt_roll);
  3517.     }
  3518. #endif /* DEBUG */
  3519.  
  3520.     if (!roll.flag) {            /* Set if we are not at bottom */
  3521.     roll.linesleft = roll.numlines;
  3522.     roll.nextline = roll.botline;
  3523.     }
  3524.  
  3525.     if (cursorena)            /* If cursor not already off */
  3526.       killcursor();            /*  turn it off. */
  3527. /*
  3528.   If TERMINAL ROLL OFF, we just process the argument key and return control of
  3529.   the keyboard to the user.  This lets the user type characters to the host
  3530.   while looking at rollback screens, as well as view new incoming characters
  3531.   on an old screen.  But it can result in some confusion by mixing new and old
  3532.   material in the rollback buffer.
  3533.  
  3534.   If TERMINAL ROLL ON, the user is held captive inside the rolled-back
  3535.   screens, allowed to type only rollback keys until reaching the bottom again,
  3536.   and no characters are read from the communication device while rolled back.
  3537.   This prevents transmission of characters to the host, and it prevents
  3538.   mixture of new and old material in the rollback buffer.
  3539. */
  3540.     do {                /* If ROLL is ON, this is a loop */
  3541.  
  3542.     while (roll.flag && tt_roll) {    /* Get another keystroke */
  3543.         key = keymap[congks(0)];
  3544.         if (key & F_KVERB)        /* It has to be a \Kverb */
  3545.           break;
  3546.         bleep();            /* if not, stay in little loop */
  3547.     }
  3548.  
  3549.     switch (key &= ~(F_KVERB)) {    /* Handle the key... */
  3550.  
  3551.       case K_HOMSCN:        /* Scrolling UP (backwards) ... */
  3552.       case K_UPSCN:
  3553.       case K_UPONE:
  3554.         if (roll.linesleft <= 0) {    /* Can't go any further up */
  3555.         bleep();        /* Beep */
  3556.         if (!roll.flag)
  3557.           return;
  3558.         else if (tt_roll)
  3559.           continue;
  3560.         else {
  3561.             if (cursorena)    /* If cursor is enabled */
  3562.               newcursor();    /* turn it back on. */
  3563.             return;
  3564.         }
  3565.         }
  3566.         if (!roll.flag)        /* If not scrolled up already, */
  3567.           savescreen(&savedscreen,wherex,wherey); /* save current screen */
  3568.         nlines = key == K_UPSCN ? ysize /* How far depends on key */
  3569.           : key == K_HOMSCN  ? roll.linesleft :
  3570.         1;
  3571.         if (nlines > roll.linesleft) /* Don't go past top */
  3572.           nlines = roll.linesleft;
  3573.         debug(F101,"scrollback up nlines","",nlines);
  3574.         if (nlines >= ysize) {    /* More than screen size? */
  3575.         if (nlines > ysize)
  3576.           roll.nextline = roll.topline + ysize - 1;
  3577.         debug(F101,"scrollback up whole screen","",roll.nextline);
  3578.         for (il = ysize; il >= 1; il--) {
  3579.             movetoscreen(
  3580.                  roll.buffer + xsize * 2 * roll.nextline,
  3581.                  1, il, xsize * 2);
  3582.             if (roll.nextline == 0)
  3583.               roll.nextline = LBUFSIZE - 1;
  3584.             else
  3585.               roll.nextline--;
  3586.         } /* for-loop */
  3587.         } else { /* nlines < ysize, so we can scroll some lines down */
  3588.         debug(F101,"scrollback up partial screen","",nlines);
  3589.         scroll(DOWNWARD, 0, ysize - 1, nlines);
  3590.         for (il = 1; il <= nlines; il++) {
  3591.             movetoscreen(roll.buffer + xsize * 2 * roll.nextline,
  3592.                  1, nlines - il + 1, xsize * 2);
  3593.             if (roll.nextline <= 0)
  3594.               roll.nextline = LBUFSIZE - 1;
  3595.             else
  3596.               roll.nextline--;
  3597.         }
  3598.         }
  3599.         roll.linesleft -= nlines;
  3600.         roll.flag = 1;
  3601.         break;
  3602.  
  3603.       case K_DNSCN:            /* Go down */
  3604.       case K_DNONE:
  3605.         if (!roll.flag) {        /* If we're not rolled back */
  3606.         bleep();        /* nothing to do, so beep */
  3607.         if (tt_roll)
  3608.           continue;
  3609.         else {
  3610.             if (cursorena)    /* If cursor is enabled */
  3611.               newcursor();    /* turn it back on. */
  3612.             return;
  3613.         }
  3614.         }
  3615.         nlines = key == K_DNSCN ? ysize : 1; /* Screen Down or Line Down */
  3616.         if (nlines > roll.numlines - roll.linesleft)
  3617.           nlines = roll.numlines - roll.linesleft;
  3618.         debug(F101,"scrollback down nlines","",nlines);
  3619.         if (nlines < ysize)
  3620.           scroll(UPWARD, 0, ysize - 1, nlines);
  3621.         do {
  3622.         if (++roll.nextline >= LBUFSIZE)
  3623.           roll.nextline = 0;
  3624.         roll.linesleft++;
  3625.         /* Lines of extended display above top of the screen */
  3626.         nolblines = roll.numlines - roll.linesleft;
  3627.         /* Number of extended display buffer lines on screen */
  3628.         if (nolblines >= ysize) {
  3629.             i = roll.nextline + ysize;
  3630.             if (i >= LBUFSIZE)
  3631.               i -= LBUFSIZE;
  3632.             /* Move from buffer to screen */
  3633.             movetoscreen(roll.buffer + xsize * 2 * i, 1,
  3634.                  ysize - nlines + 1, xsize * 2);
  3635.         } else {        /* Move from saved current screen */
  3636.             movetoscreen(
  3637.                  &(savedscreen.scrncpy[
  3638.                      (ysize - 1 - nolblines) * xsize * 2
  3639.                                ]),
  3640.                  1,
  3641.                  ysize - nlines + 1,
  3642.                  xsize * 2
  3643.                  );
  3644.         }
  3645.         nlines--;
  3646.         } while (nlines > 0);
  3647.         break;
  3648.  
  3649.       case K_ENDSCN:        /* Scroll to bottom */
  3650.         if (!roll.flag) {        /* If we're not rolled back, */
  3651.         bleep();        /* just beep, */
  3652.         if (cursorena)        /* restore cursor, */
  3653.           newcursor();        /* and return. */
  3654.         return;
  3655.         } else {            /* Otherwise, set exit condition. */
  3656.         roll.linesleft = roll.numlines;
  3657.         }
  3658.         break;
  3659.  
  3660.       case K_DUMP: {        /* Print/Dump current screen */
  3661.         int x;
  3662.         x = xprintff; xprintff = 0;
  3663.         prtscreen(1,ysize);
  3664.         xprintff = x;
  3665.         continue;
  3666.       }
  3667.  
  3668.       case K_HELP:            /* Help */
  3669.         popuphelp(0);        /* Watch out, this turns cursor on */
  3670.         killcursor();        /* Turn it back off */
  3671.         continue;
  3672.  
  3673.       default:            /* Not a rollback key. */
  3674.         bleep();
  3675.         continue;
  3676.  
  3677.     } /* switch (key) */
  3678.  
  3679.  
  3680.     /* If we're still rolled back, make special status line */
  3681.  
  3682.     if (roll.linesleft != roll.numlines) {
  3683.         roll.flag = 1;            /* (Just in case) */
  3684.         sprintf(usertext, " Scroll: %d/%d", /* Do special status line. */
  3685.             roll.numlines - roll.linesleft,
  3686.             roll.numlines
  3687.             );
  3688.         if (vik.upscn > 255 && keynam[vik.upscn - 256]) {
  3689.         strncpy(helptext, keynam[vik.upscn - 256], 20);
  3690.         if (vik.dnscn > 255 && keynam[vik.dnscn - 256]) {
  3691.             if (HLPTXTLEN
  3692.             - (int)strlen(keynam[vik.upscn - 256])
  3693.             - (int)strlen(keynam[vik.dnscn - 256]) > 0) {
  3694.             strcat(helptext,"/");
  3695.             strcat(helptext,keynam[vik.dnscn - 256]);
  3696.             }
  3697.         }
  3698.         } else
  3699.           strcpy(helptext, "\\KupScn,\\KdnScn");
  3700.  
  3701.         if ((vik.help > 255) &&
  3702.         (keynam[vik.help - 256]) &&
  3703.         ((HSTNAMLEN - 6 - (int)strlen(keynam[vik.help - 256])) > 0)) {
  3704.         sprintf(hostname, "Help: %s", keynam[vik.help - 256]);
  3705.         } else if (vik.homscn > 255 && keynam[vik.homscn - 256]) {
  3706.         strcpy(hostname, keynam[vik.homscn - 256]);
  3707.         if (vik.endscn > 255 && keynam[vik.endscn - 256]) {
  3708.             if (HSTNAMLEN - 1
  3709.             - (int)strlen(keynam[vik.homscn - 256])
  3710.             - (int)strlen(keynam[vik.endscn - 256]) > 0) {
  3711.             strcat(hostname,"/");
  3712.             strcat(hostname,keynam[vik.endscn - 256]);
  3713.             }
  3714.         }
  3715.         } else
  3716.           strcpy(hostname, "\\KhomScn,\\KendScn");
  3717.         exittext[0] = '\0';
  3718.         /* filetext[0] = '\0'; */
  3719.         line25();            /* Display the status line */
  3720.     }
  3721.     } while (tt_roll && (roll.linesleft != roll.numlines));
  3722. /*
  3723.   Get here after processing one keystroke and TERMINAL ROLL is OFF,
  3724.   or when TERMINAL ROLL is ON, only when we've reached the bottom.
  3725. */
  3726.     if (roll.linesleft == roll.numlines) { /* We're at the bottom */
  3727.     if (roll.flag) {
  3728.         roll.flag = 0;            /* Reset scrolled-back flag */
  3729.         restorescreen(&savedscreen);    /* Put back current screen */
  3730.         ipadl25();            /* Put back normal status line */
  3731.     }
  3732.     }
  3733.     if (cursorena)            /* If cursor is enabled */
  3734.       newcursor();            /* turn it back on. */
  3735.     return;
  3736. }
  3737.  
  3738. static void
  3739. vt100key(int key) {
  3740.  
  3741. #ifdef NOKVERBS
  3742.     char str[3];            /* Not needed in simplified code */
  3743.     int prt, st;
  3744. #endif /* NOKVERBS */
  3745.  
  3746.     if ( keydefptr ) {            /* First send any leftovers */
  3747.     sendkeydef( keydefptr );    /* from previous session... */
  3748.     keydefptr = NULL;        /* and then forget about it */
  3749.     return;
  3750.     } else if ( macrotab[key] ) {    /* Check for macro */
  3751.     sendkeydef(macrotab[key]);    /* This also handles \Kverbs */
  3752.     return;
  3753.     }
  3754.     key = keymap[key];            /* If no macro, check keymap. */
  3755.  
  3756.     if (key < 0x100) {            /* If it's a regular key, */
  3757.     sendcharduplex((char) key);    /* just send it, */
  3758.     if (tt_pacing > 0)        /* taking care of pacing */
  3759.       msleep(tt_pacing);
  3760.     if (key == CR && tnlm) {    /* and newline mode */
  3761.         sendcharduplex(LF);
  3762.         if (tt_pacing > 0)        /* and pacing */
  3763.           msleep(tt_pacing);
  3764.     }
  3765.         return;
  3766.     }
  3767.  
  3768. #ifndef NOKVERBS
  3769.  
  3770.     if (IS_KVERB(key))            /* Specially precoded keyboard verb */
  3771. #ifdef __32BIT__
  3772.       {
  3773.       DosRequestMutexSem( hmtxScreenSem, SEM_INDEFINITE_WAIT ) ;
  3774.       dokverb(key) ;       /* We already know its index */
  3775.       DosReleaseMutexSem( hmtxScreenSem ) ;
  3776.       }
  3777. #else
  3778.       dokverb(key);            /* We already know its index */
  3779. #endif /* __32BIT__ */
  3780.     else
  3781.       bleep();                /* Extended key with no definition. */
  3782.     return;                /* Just beep & return. */
  3783.  
  3784.  
  3785. #else /* Old way, pre-edit-190, hardwired scan codes... */
  3786.  
  3787.     switch (key & 0xFF) {
  3788.       case 72:                /* Up Arrow */
  3789.         if (tt_type >= TT_VT100) {
  3790.             if (tt_arrow == TTK_APPL)
  3791.           sendescseq("OA");        /* Application mode */
  3792.             else
  3793.           sendescseq("[A");        /* Normal (cursor) mode */
  3794.         } else
  3795.       sendescseq("A");
  3796.         break;
  3797.       case 75:                /* 587 Left Arrow */
  3798.         if (tt_type >= TT_VT100) {
  3799.             if (tt_arrow == TTK_APPL)
  3800.                 sendescseq("OD");
  3801.             else
  3802.                 sendescseq("[D");
  3803.         } else
  3804.             sendescseq("D");
  3805.         break;
  3806.     case 77:                /* 589 Right Arrow */
  3807.         if (tt_type >= TT_VT100) {
  3808.             if (tt_arrow == TTK_APPL)
  3809.                 sendescseq("OC");
  3810.             else
  3811.                 sendescseq("[C");
  3812.         } else
  3813.             sendescseq("C");
  3814.         break;
  3815.     case 80:                /* 592 Down Arrow */
  3816.         if (tt_type >= TT_VT100) {
  3817.             if (tt_arrow == TTK_APPL)
  3818.                 sendescseq("OB");
  3819.             else
  3820.                 sendescseq("[B");
  3821.         } else
  3822.             sendescseq("B");
  3823.         break;
  3824.     case 15:                /* 271 Backtab */
  3825.         sendcharduplex(8);        /* Sends backspace */
  3826.         break;
  3827.     case 83:                /* 127 DEL */
  3828.         sendcharduplex(127);        /* Sends delete */
  3829.         break;
  3830.     case 59:                /* 315 F1 */
  3831.         if (tt_type >= TT_VT100)        /* Sends DEC PF1 */
  3832.       sendescseq("OP");
  3833.         else
  3834.       sendescseq("P");
  3835.         break;
  3836.     case 60:                /* 316 F2 */
  3837.         if (tt_type >= TT_VT100)        /* Sends DEC PF2 */
  3838.       sendescseq("OQ");
  3839.         else
  3840.       sendescseq("Q");
  3841.         break;
  3842.     case 61:                /* 317 F3 */
  3843.         if (tt_type >= TT_VT100)    /* Send DEC PF3 */
  3844.       sendescseq("OR");
  3845.         else
  3846.       sendescseq("R");
  3847.         break;
  3848.     case 62:                /* 318 F4 */
  3849.         if (tt_type >= TT_VT100)        /* Sends DEC PF4 */
  3850.       sendescseq("OS");
  3851.         else
  3852.       sendescseq("S");
  3853.         break;
  3854.     case 120:                /* Alt-1 ... Alt-9 */
  3855.     case 121:                /* 376, 377, ... 384 */
  3856.     case 122:
  3857.     case 123:
  3858.     case 124:
  3859.     case 125:
  3860.     case 126:
  3861.     case 127:
  3862.     case 128:
  3863.     case 129:                /* 385 .. This one is Alt-0 */
  3864.         /* numeric 1-9,0 */
  3865.     if (tt_keypad == TTK_NORM) {    /* Keypad digits in numeric mode */
  3866.         if (key == 129) key = 48;    /* Watch out for zero */
  3867.         else key -= 71;
  3868.         sendcharduplex((unsigned char)key);    /* Send digit */
  3869.         } else {            /* Keypad in Application mode */
  3870.             key = 'q' + (key & 0xFF) - 120;
  3871.             if (key == 'z')
  3872.           key = 'p';
  3873.             /* alt 0 */
  3874.             if (tt_type >= TT_VT100)
  3875.           strcpy(str, "O ");
  3876.             else
  3877.           strcpy(str, "? ");
  3878.             str[1] = key;
  3879.             sendescseq(str);
  3880.         }
  3881.         break;
  3882.     case 63:                /* Keypad minus = F5 or ... */
  3883.     case 64:                /* F6 */
  3884.     if (tt_keypad == TTK_NORM)    /* Keypad in numeric mode */
  3885.       sendcharduplex('-');
  3886.         else if (tt_type >= TT_VT100)    /* Application mode, VT102 */
  3887.       sendescseq("Om");
  3888.         else                /* Application mode, VT52 */
  3889.       sendescseq("?m");
  3890.         break;
  3891.     case 65:                /* Keypad comma = F7 or ... */
  3892.     case 66:                /* F8 */
  3893.     if (tt_keypad == TTK_NORM)    /* Numeric mode... */
  3894.       sendcharduplex(',');
  3895.         else if (tt_type >= TT_VT100)
  3896.       sendescseq("Ol");
  3897.         else
  3898.       sendescseq("?l");
  3899.         break;
  3900.     case 67:                /* Keypad period = F9 */
  3901.     if (tt_keypad == TTK_NORM)
  3902.         sendcharduplex('.');
  3903.         else if (tt_type >= TT_VT100)
  3904.             sendescseq("On");
  3905.         else
  3906.             sendescseq("?n");
  3907.         break;
  3908.     case 68:                /* Keypad Enter = F10 */
  3909.     if (tt_keypad == TTK_NORM) {
  3910.         sendcharduplex('\015');    /* Numeric mode, send CR */
  3911.         if (tnlm)
  3912.           sendcharduplex('\012');    /* Newline mode, send LF too */
  3913.         } else if (tt_type >= TT_VT100)
  3914.       sendescseq("OM");
  3915.         else
  3916.       sendescseq("?M");
  3917.         break;
  3918.     case 255:                /* Scroll-Lock */
  3919.         {
  3920.             strcpy(usertext, " Scroll-Lock ");
  3921.             *exittext = '\0';
  3922.             *helptext = '\0';
  3923.             line25();
  3924.             while (keymap[congks(0)] != 0x1FF) ;
  3925.             ipadl25();
  3926.         }
  3927.         break;
  3928.     case 81:                /* Page-Down */
  3929.     case 118:                /* Control-Page-Down */
  3930.         bleep();
  3931.         /* since not in extended display mode */
  3932.         break;
  3933.     case 71:                /* Home, enter extended display mode */
  3934.     case 73:                /* Page-Up  */
  3935.     case 132:                /* Control-Page-Up */
  3936.         if (roll.numlines == 0)
  3937.       bleep();
  3938.     else
  3939.       scrollback(key);
  3940.         break;
  3941.     case 16:                /* Alt-Q = Quit */
  3942.       doesc('Q'); break;
  3943.     case 45:                /* Alt-X = Return to prompt */
  3944.       doesc('C'); break;
  3945.     case 48:                /* Alt-B = Send BREAK */
  3946.       doesc('B'); break;
  3947.     case 38:                /* Alt-L = Send Long BREAK */
  3948.       doesc('L'); break;
  3949.     case 35:                /* Alt-H = Hangup */
  3950.       doesc('H'); break;
  3951.     case 131:                /* Alt-= is Reset */
  3952.       doreset(1);
  3953.       break;
  3954.     case 53:                /* Alt-? or Alt-/ = Help */
  3955.       strcpy(usertext, " Press (almost) any key to restore the screen");
  3956.       exittext[0] = '\0';
  3957.       helptext[0] = '\0';
  3958.       hostname[0] = '\0';
  3959.       line25();
  3960.       popuphelp(0);
  3961.       ipadl25();
  3962.       break;
  3963.     case 19:                /* Alt-R = Flip screen */
  3964.       flipscreen();
  3965.       break;
  3966.     case 25: {                /* Alt-P = print/dump screen */
  3967.       int x;
  3968.       x = xprintff; xprintff = 0;
  3969.       prtscreen(1,ysize);        /*   Print/Dump screen */
  3970.       xprintff = x;
  3971.       break;
  3972.     }
  3973.     case 32:                /* Alt-D = Toggle debugging */
  3974.       flipdebug();
  3975.       break;
  3976.     default:                /* Others, ignore */
  3977.       break;
  3978.     } /* of switch (key & 0xFF) */
  3979.  
  3980. #endif /* NOKVERBS */
  3981.  
  3982. }
  3983.  
  3984. /* ------------------------------------------------------------------ */
  3985. /* cwrite - check and process escape sequence                         */
  3986. /* ------------------------------------------------------------------ */
  3987.  
  3988. static char old_c = 0;
  3989.  
  3990. void                    /* Note, not static! */
  3991. cwrite(unsigned char ch) {        /* Used by ckcnet.c for */
  3992.                     /* TELNET options debug display. */
  3993. /*
  3994.    Edit 190.
  3995.    New code, supporting APC, and integrating escape sequence state switching
  3996.    that was formerly done, but not used to good advantage, in chkaes().  The
  3997.    additional complexity comes from the fact that ESC is not used only to
  3998.    commence escape sequences, but also, in the case of APC, OSC, PM, etc, to
  3999.    terminate them.  New code also supports session debugging.
  4000. */
  4001.     if (tt_type == TT_NONE) {
  4002.     vt100(ch);
  4003.     return;
  4004.     }
  4005.     if (debses && !f_pushed) {        /* Session debugging */
  4006.     unsigned char ch8;
  4007.     ch8 = f_popped ? ((ch ^ 0x40) | 0x80) : ch;
  4008.     if (ch8 < 32) {            /* C0 Control character */
  4009.         attribute = colorunderline;    /* Use underline color */
  4010.         if (decscnm)        /* Handle flipped screen */
  4011.           attribute = swapcolors(attribute);
  4012.         wrtch((char)(ch8 | 64));    /* Write corresponding letter */
  4013.     } else if (ch8 == 127) {    /* DEL */
  4014.         attribute = colorunderline;    /* Underline color */
  4015.         if (decscnm)        /* Handle flipped screen */
  4016.           attribute = swapcolors(attribute);
  4017.         wrtch('?');            /* question mark */
  4018.     } else if (ch8 > 127 && ch8 < 160) { /* C1 control */
  4019.         attribute = colorunderline;    /* Underline color */
  4020.         if (decscnm)        /* Handle flipped screen */
  4021.           attribute = swapcolors(attribute);
  4022.         wrtch(ch8);            /* The character itself */
  4023.     } else if (escstate != ES_NORMAL) { /* Part of Esc sequence */
  4024.         attribute = swapcolors(defaultattribute); /* Reverse video */
  4025.         wrtch(ch8);
  4026.     } else {            /* Regular character */
  4027.         attribute = defaultattribute; /* Normal colors */
  4028.         if (tn_bold) attribute ^= 8; /* (only for TELNET debugging...) */
  4029.         wrtch(ch8);
  4030.     }
  4031.     if (ch8 == LF && old_c == CR) {    /* Break lines for readability */
  4032.         wrtch(CR);
  4033.         wrtch(LF);
  4034.     }
  4035.     old_c = ch8;            /* Remember this character */
  4036.     }                    /* for CRLF matching. */
  4037. /*
  4038.   Even if debugging, we still plow through the escape-sequence state table 
  4039.   switcher, but we don't call any of the action routines.
  4040.   This lets us highlight text that appears inside an escape sequence.
  4041. */
  4042.     if (escstate == ES_NORMAL) {    /* Not in an escape sequence */
  4043.     if (ch == ESC) {        /* This character is an Escape */
  4044.         escstate = ES_GOTESC;    /* Change state to GOTESC */
  4045.             esclast = 0;        /* Reset buffer pointer */
  4046.         } else                /* Not an ESC, stay in NORMAL state */
  4047.       if (!debses) vt100(ch);    /* and send to vt100() for display. */
  4048.     return;                /* Return in either case. */
  4049.     }
  4050.  
  4051. /* We are in an escape sequence... */
  4052.  
  4053.     if (escstate != ES_STRING && escstate != ES_TERMIN) { /* Not in string */
  4054.     if (ch < SP) {            /* Control character? */
  4055.         if (ch == CAN || ch == SUB) { /* These cancel an escape sequence */
  4056.         escstate = ES_NORMAL;    /* Go back to normal. */
  4057.         } else if (ch == BS && esclast > 0) { /* Erases previous */
  4058.         esclast--;        /* escape sequence char (really?) */
  4059.         } else if (ch == ESC) {
  4060.         escstate = ES_GOTESC;    /* Escape sequence was restarted */
  4061.         esclast = 0;        /* Reset buffer pointer */
  4062.         }
  4063.         return;
  4064.     }
  4065. /*
  4066.   Put this character in the escape sequence buffer.
  4067.   But we don't put "strings" in this buffer; either absorb them silently
  4068.   (as with Operating System Command), or handle them specially (as with APC).
  4069.   Note that indexing starts at 1, not 0.
  4070. */
  4071.     if (esclast < ESCBUFLEN)
  4072.       escbuffer[++esclast] = ch;
  4073.     }
  4074.  
  4075. /* Note: vtescape() sets escstate back to ES_NORMAL. */
  4076.  
  4077.     if (tt_type == TT_VT52) {        /* VT52 Emulation */
  4078.         switch (esclast) {
  4079.           case 1:            /* First char after Esc */
  4080.         if (ch != 'Y')        /* If not Y, */
  4081.           vtescape();        /* then it's a complete sequence */
  4082.         break;
  4083.       case 3:            /* Can only happen with Y<row><col> */
  4084.         vtescape();            /* Cursor position */
  4085.           case 2:            /* First part of cursor position */
  4086.         break;
  4087.           default:              /* Something unexpected, ignore */
  4088.         escstate = ES_NORMAL;
  4089.             break;
  4090.         }
  4091.     return;                /* Done with VT52 */
  4092.     }
  4093.  
  4094.     /* The rest of this routine handles ANSI/VT1xx/VT2xx emulation... */
  4095.     
  4096.     switch (escstate) {            /* Enter esc sequence state switcher */
  4097.  
  4098.       case ES_GOTESC:            /* GOTESC state, prev char was Esc */
  4099.     if (ch == '[')            /* Left bracket after ESC is CSI */
  4100.       escstate = ES_GOTCSI;        /* Change to GOTCSI state */
  4101.     else if (ch == '_' ||        /* Application Program Command (APC) */
  4102.          ch == 'P' ||        /* Device Control String Introducer */
  4103.          ch == '^' ||        /* Privacy Message (PM) */
  4104.          ch == ']') {        /* Operating System Command (OSC) */
  4105.         escstate = ES_STRING;    /* Enter STRING-absorption state */
  4106. #ifdef CK_APC
  4107.         if (ch == '_') {        /* Application Program Command */
  4108.         apcactive = 1;        /* Set APC-Active flag */
  4109.         apclength = 0;        /* and reset APC buffer pointer */
  4110.         }
  4111. #endif /* CK_APC */
  4112.         } else if ((ch > 057) && (ch < 0177)) /* Or final char, '0' thru '~' */
  4113.       vtescape();            /* Go act on it. */
  4114.     else
  4115.       escstate = ES_ESCSEQ;
  4116.     break;
  4117.  
  4118.       case ES_ESCSEQ:            /* ESCSEQ -- in an escape sequence */
  4119.         if (ch > 057 && ch < 0177)    /* Final character is '0' thru '~' */
  4120.       vtescape();            /* Go handle it */
  4121.     break;
  4122.  
  4123.       case ES_GOTCSI:            /* GOTCSI -- In a control sequence */
  4124.     if (ch > 077 && ch < 0177)    /* Final character is '@' thru '~' */
  4125.       vtescape();            /* Go act on it. */
  4126.     break;
  4127.  
  4128.       case ES_STRING:            /* Inside a string */
  4129.     if (ch == ESC)            /* ESC may be 1st char of terminator */
  4130.       escstate = ES_TERMIN;        /* Change state to find out. */
  4131. #ifdef CK_APC
  4132.     else if (apcactive && (apclength < apcbuflen))    /* If in APC string, */
  4133.       apcbuf[apclength++] = ch;    /* deposit this character */
  4134. #endif /* CK_APC */
  4135.     break;                /* Absorb all other characters. */
  4136.         
  4137.       case ES_TERMIN:            /* May have a string terminator */
  4138.     if (ch == '\\') {        /* which must be backslash */
  4139.         escstate = ES_NORMAL;    /* If so, back to NORMAL */
  4140. #ifdef CK_APC
  4141.         if (apcactive) {        /* If it was an APC string, */
  4142.         apcbuf[apclength] = NUL; /* terminate it and then ... */
  4143.         if (apcstatus != APC_OFF) {
  4144.             active = FALSE;    /* exit from the terminal emulator */
  4145.             return;        /* with the apcactive flag still set */
  4146.         } else apcactive = 0;
  4147. #endif /* CK_APC */
  4148.         }
  4149.     } else {            /* Just a stray Esc character. */
  4150.         escstate = ES_STRING;    /* Return to string absorption. */
  4151. #ifdef CK_APC
  4152.         if (apcactive && (apclength+1 < apcbuflen)) { /* In APC string, */
  4153.         apcbuf[apclength++] = ESC; /* deposit the Esc character */
  4154.         apcbuf[apclength++] = ch;  /* and this character too */
  4155.         }
  4156. #endif /* CK_APC */
  4157.     }
  4158.     }
  4159. }
  4160.  
  4161. /*---------------------------------------------------------------------------*/
  4162. /* scrninit                                                                  */
  4163. /*---------------------------------------------------------------------------*/
  4164. static void
  4165. scrninit() {
  4166.  
  4167.     setborder();
  4168.  
  4169.     if ( roll.bufsize != tt_scrsize ) {
  4170.         if ( roll.buffer != NULL )
  4171.         free(roll.buffer);
  4172.     roll.buffer = NULL;
  4173.     scrninitialised = 0;
  4174.     }
  4175.     if (!scrninitialised) {
  4176.     scrninitialised = 1;
  4177.     defaultattribute = colornormal;
  4178.     attribute = defaultattribute;
  4179.     /* Initialise paging info */
  4180.         if ( roll.buffer == NULL ) {
  4181.       roll.bufsize = tt_scrsize;
  4182.       roll.buffer = malloc(tt_scrsize * xsize * 2);
  4183.     }
  4184.     assert(roll.buffer != NULL);
  4185.     roll.numlines = 0;
  4186.     roll.topline = 0;
  4187.     roll.botline = LBUFSIZE - 1;
  4188.     roll.flag = 0;
  4189.     clearscreen(0, attribute);
  4190.     savescreen(&vt100screen,wherex,wherey);
  4191.     }
  4192. }
  4193.  
  4194. /*---------------------------------------------------------------------------*/
  4195. /* bleep                                                                     */
  4196. /*---------------------------------------------------------------------------*/
  4197. static void
  4198. bleep() {
  4199.     switch(tt_bell) {            /* Follows TERMINAL BELL setting. */
  4200.       case 1:                /* AUDIBLE */
  4201.     DosBeep(880, 50);        /* 880 MHz for 50 msec */
  4202.     return;
  4203.       case 2:                /* VISIBLE */
  4204.     flipscreen();            /* Flash the screen */
  4205.     msleep(250);            /* for 250 msec */
  4206.     flipscreen();
  4207.     return;
  4208.       default:                /* NONE or other */
  4209.     return;
  4210.     }
  4211. }
  4212.  
  4213. /*---------------------------------------------------------------------------*/
  4214. /* wrtch                                                                     */
  4215. /*---------------------------------------------------------------------------*/
  4216. static void
  4217. wrtch(char ch) {
  4218.     char cell[2];
  4219.  
  4220.     if (printon && xprint && !debses)    /* If transparent print active, */
  4221.       return;                /*  we don't touch the screen. */
  4222.  
  4223.     if (ch >= ' ' || literal) {        /* Normal character */
  4224.     if (attrib.invisible)
  4225.       ch = ' ';
  4226.     if ((tt_type >= TT_VT102) && insertmode) {
  4227.         cell[0] = ch;
  4228.         cell[1] = attribute;
  4229. #ifdef OS2MOUSE
  4230.         os2_mousehide() ;
  4231. #endif /* OS2MOUSE */
  4232.         VioScrollRt(wherey - 1, wherex - 1, wherey - 1,
  4233.             xsize - 1, 1, cell, 0);
  4234. #ifdef OS2MOUSE
  4235.         os2_mouseshow() ;
  4236. #endif
  4237.     } else
  4238. #ifdef OS2MOUSE
  4239.       os2_mousehide() ;
  4240. #endif /* OS2MOUSE */
  4241.         VioWrtCharStrAtt(&ch, 1, wherey - 1, wherex - 1, &attribute, 0);
  4242. #ifdef OS2MOUSE
  4243.     os2_mouseshow() ;
  4244. #endif
  4245.     literal = FALSE;
  4246.     if (++wherex > xsize) {
  4247.         wherex = 1;
  4248.         wrtch(LF);
  4249.     }
  4250.     } else {                /* Control character */
  4251.     switch (ch) {
  4252.     case LF:
  4253.         if (wherey == marginbot) {
  4254.         if (margintop == 1)
  4255.           toplinetocyclicbuffer();
  4256.         scroll(UPWARD, margintop - 1, marginbot - 1, 1);
  4257.         } else {
  4258.         wherey++;
  4259.         if (wherey == ysize + 1)
  4260.             wherey--;
  4261.         }
  4262.         break;
  4263.     case CR:
  4264.         wherex = 1;
  4265.         break;
  4266.     case BS:
  4267.         if (wherex > 1)
  4268.         wherex--;
  4269.         break;
  4270.     case 12:
  4271.         if (wherex < xsize)
  4272.         wherex++;
  4273.         break;
  4274.     case BEL:
  4275.         DosBeep(440, 100);
  4276.         break;
  4277.     default:{        /* Ignore */
  4278.         }
  4279.     }
  4280.     }
  4281.     if (cursoron)
  4282.     VioSetCurPos(wherey - 1, wherex - 1, 0);
  4283. }
  4284.  
  4285. /*---------------------------------------------------------------------------*/
  4286. /* clearscreen                                                               */
  4287. /*---------------------------------------------------------------------------*/
  4288. static void
  4289. clearscreen(int all, int attr) {
  4290.     char cell[2];
  4291.     cell[0] = ' ';
  4292.     cell[1] = attr;
  4293. #ifdef OS2MOUSE
  4294.    os2_mousehide() ;
  4295. #endif /* OS2MOUSE */
  4296.     VioWrtNCell(cell, xsize * ysize + (all ? xsize : 0), 0, 0, 0);
  4297. #ifdef OS2MOUSE
  4298.    os2_mouseshow() ;
  4299. #endif
  4300.     lgotoxy(1, 1);
  4301. }
  4302.  
  4303. /*---------------------------------------------------------------------------*/
  4304. /* lgotoxy                                                                   */
  4305. /*---------------------------------------------------------------------------*/
  4306. static void
  4307. lgotoxy(int x, int y) {
  4308.     wherex = x;
  4309.     wherey = y;
  4310.     if (cursoron)
  4311.       VioSetCurPos(wherey - 1, wherex - 1, 0);
  4312. }
  4313.  
  4314. /*---------------------------------------------------------------------------*/
  4315. /* scroll                                                                    */
  4316. /*---------------------------------------------------------------------------*/
  4317. static void
  4318. scroll(int updown, int top, int bottom, int nlines) {
  4319.     char blankcell[2];
  4320.     int i;
  4321.  
  4322.     blankcell[0] = ' ';
  4323. #ifdef COMMENT
  4324.     blankcell[1] = attribute;
  4325. #else
  4326. /*
  4327.    Fixed by fdc, Jan 94 -- If the new bottom line inherits the current
  4328.    character attributes, then it will be padded out to the end with
  4329.    attribute-bearing spaces.  Create the new line with default attributes,
  4330.    then let subsequent-character writing operations take care of the
  4331.    per-character attributes.
  4332. */
  4333.     blankcell[1] = defaultattribute;
  4334. #endif /* COMMENT */
  4335.     switch (updown) {
  4336.     case UPWARD:
  4337. #ifdef OS2MOUSE
  4338.     os2_mousehide() ;
  4339. #endif
  4340.     VioScrollUp(top, 0, bottom, xsize - 1, nlines, blankcell, 0);
  4341.         VioShowBuf(0, xsize * 2, 0);
  4342.         /* There is a bug in early OS/2 2.0 8514/A PM drivers that causes
  4343.          * wrong screen update after a scroll operation. We just force
  4344.          * a correct screen update of the line in question here. */
  4345. #ifdef OS2MOUSE
  4346.     os2_mouseshow() ;
  4347. #endif
  4348.     if (dwls) {
  4349.         for (i = top; i <= bottom - nlines; i++)
  4350.           dwl[i] = dwl[i + nlines];
  4351.         for (i = bottom - nlines + 1; i <= bottom; i++)
  4352.           dwl[i] = FALSE;
  4353.     }
  4354.     break;
  4355.     case DOWNWARD:
  4356. #ifdef OS2MOUSE
  4357.     os2_mousehide() ;
  4358. #endif
  4359.     VioScrollDn(top, 0, bottom, xsize - 1, nlines, blankcell, 0);
  4360.         VioShowBuf(xsize * 2, xsize * 2, 0);
  4361. #ifdef OS2MOUSE
  4362.     os2_mouseshow() ;
  4363. #endif
  4364.     if (dwls) {
  4365.         for (i = bottom; i >= top + nlines; i--)
  4366.         dwl[i] = dwl[i - nlines];
  4367.         for (i = top + nlines - 1; i >= top; i--)
  4368.             dwl[i] = FALSE;
  4369.     }
  4370.     break;
  4371.     default: /* ignore */ ;
  4372.     }
  4373.     if (dwls) {
  4374.     dwls = FALSE;
  4375.     for (i = 0; i < ysize; i++)
  4376.         if (dwl[i]) {
  4377.         dwls = TRUE;
  4378.         break;
  4379.         }
  4380.     }
  4381. }
  4382.  
  4383. /*---------------------------------------------------------------------------*/
  4384. /* movetoscreen                                                              */
  4385. /*---------------------------------------------------------------------------*/
  4386. static void
  4387. movetoscreen(char *source, int x, int y, int len) {
  4388. #ifdef OS2MOUSE
  4389.     os2_mousehide() ;
  4390. #endif /* OS2MOUSE */
  4391.     VioWrtCellStr(source, len, y - 1, x - 1, 0);
  4392. #ifdef OS2MOUSE
  4393.     os2_mouseshow() ;
  4394. #endif
  4395. }
  4396.  
  4397. /*---------------------------------------------------------------------------*/
  4398. /* toplinetocyclicbuffer                                                     */
  4399. /*---------------------------------------------------------------------------*/
  4400. static void
  4401. toplinetocyclicbuffer() {
  4402.     USHORT n = xsize * 2;
  4403.     if (roll.numlines == LBUFSIZE) {
  4404.     if (++roll.topline == LBUFSIZE)
  4405.       roll.topline = 0;
  4406.     } else
  4407.       roll.numlines++;
  4408.     if (++roll.botline == LBUFSIZE)
  4409.       roll.botline = 0;
  4410. #ifdef OS2MOUSE
  4411.     os2_mousehide() ;
  4412. #endif
  4413.     VioReadCellStr((roll.buffer + xsize * 2 * roll.botline),
  4414.            &n, 0, 0, 0);
  4415. #ifdef OS2MOUSE
  4416.     os2_mouseshow() ;
  4417. #endif
  4418. }
  4419.  
  4420. /*---------------------------------------------------------------------------*/
  4421. /* cleartoeol                                                                */
  4422. /*---------------------------------------------------------------------------*/
  4423. static void
  4424. clrtoeoln() {
  4425.     char cell[2];
  4426.  
  4427.     cell[0] = ' ';
  4428. #ifdef COMMENT
  4429.     cell[1] = attribute;
  4430. #else
  4431.     cell[1] = defaultattribute;
  4432. #endif /* COMMENT */
  4433. #ifdef OS2MOUSE
  4434.     os2_mousehide() ;
  4435. #endif /* OS2MOUSE */
  4436.     VioWrtNCell(cell, xsize + 1 - wherex, wherey - 1, wherex - 1, 0);
  4437. #ifdef OS2MOUSE
  4438.     os2_mouseshow() ;
  4439. #endif
  4440. }
  4441.  
  4442. /*---------------------------------------------------------------------------*/
  4443. /* setmargins                                                                */
  4444. /*---------------------------------------------------------------------------*/
  4445. static void
  4446. setmargins(int top, int bot) {
  4447.     margintop = top;
  4448.     marginbot = bot;
  4449. }
  4450.  
  4451. /*---------------------------------------------------------------------------*/
  4452. /* killcursor                                                                */
  4453. /*---------------------------------------------------------------------------*/
  4454. static void
  4455. killcursor() {
  4456.     VIOCURSORINFO nocursor;
  4457.     if (!cursoron)            /* It's already off */
  4458.       return;
  4459.     VioGetCurType(&crsr_info, 0);    /* Store current cursor type */
  4460.     nocursor = crsr_info;        /* MS C allows structure copy */
  4461.     nocursor.attr = -1;
  4462.     VioSetCurType(&nocursor, 0);    /* Hide cursor */
  4463.     cursoron = FALSE;
  4464. }
  4465.  
  4466. /*---------------------------------------------------------------------------*/
  4467. /* newcursor                                                                 */
  4468. /*---------------------------------------------------------------------------*/
  4469. static void
  4470. newcursor() {
  4471.     if (cursoron)            /* It's already on */
  4472.       return;
  4473.     VioSetCurType(&crsr_info, 0);
  4474.     VioSetCurPos(wherey - 1, wherex - 1, 0);
  4475.     cursoron = TRUE;
  4476. }
  4477.  
  4478. /*---------------------------------------------------------------------------*/
  4479. /* line25                                                                    */
  4480. /*---------------------------------------------------------------------------*/
  4481.  
  4482. #define STATUS_MAX 10
  4483. static char *save_status[STATUS_MAX];
  4484. static char *save_usertext[STATUS_MAX];
  4485. static char *save_exittext[STATUS_MAX];
  4486. static char *save_helptext[STATUS_MAX];
  4487. static char *save_filetext[STATUS_MAX];
  4488. static char *save_savefiletext[STATUS_MAX];
  4489. static char *save_hostname[STATUS_MAX];
  4490.  
  4491. static void
  4492. save_status_line() {
  4493.     if ((++status_saved >= (STATUS_MAX - 1)) || (status_saved < 0))
  4494.       return;
  4495.  
  4496.     if (!(save_status[status_saved] = malloc(MAXCOL+1)))
  4497.       return;
  4498.     else
  4499.       strncpy(save_status[status_saved],statusline,MAXCOL);
  4500.  
  4501.     if (!(save_usertext[status_saved] = malloc(MAXCOL+1)))
  4502.       return;
  4503.     else
  4504.       strncpy(save_usertext[status_saved],usertext,MAXCOL);
  4505.  
  4506.     if (!(save_exittext[status_saved] = malloc(MAXCOL+1)))
  4507.       return;
  4508.     else
  4509.       strncpy(save_exittext[status_saved],exittext,MAXCOL+1);
  4510.  
  4511.     if (!(save_helptext[status_saved] = malloc(MAXCOL+1)))
  4512.       return;
  4513.     else
  4514.       strncpy(save_helptext[status_saved],helptext,MAXCOL+1);
  4515.  
  4516.     if (!(save_filetext[status_saved] = malloc(MAXCOL+1)))
  4517.       return;
  4518.     else
  4519.       strncpy(save_filetext[status_saved],filetext,MAXCOL+1);
  4520.  
  4521.     if (!(save_savefiletext[status_saved] = malloc(MAXCOL+1)))
  4522.       return;
  4523.     else
  4524.       strncpy(save_savefiletext[status_saved],savefiletext,MAXCOL+1);
  4525.  
  4526.     if (!(save_hostname[status_saved] = malloc(MAXCOL+1)))
  4527.       return;
  4528.     else
  4529.       strncpy(save_hostname[status_saved],hostname,MAXCOL+1);
  4530. }
  4531.  
  4532. static void
  4533. restore_status_line() {
  4534.     if ((status_saved >= (STATUS_MAX - 1)) || (status_saved < 0))
  4535.       return;
  4536.  
  4537.     if (save_status[status_saved]) {
  4538.     strncpy(statusline,save_status[status_saved],MAXCOL);
  4539.     free(save_status[status_saved]);
  4540.     }
  4541.  
  4542.     if (save_usertext[status_saved]) {
  4543.     strncpy(usertext,save_usertext[status_saved],20);
  4544.     free(save_usertext[status_saved]);
  4545.     }
  4546.  
  4547.     if (save_exittext[status_saved]) {
  4548.     strncpy(exittext,save_exittext[status_saved],20);
  4549.     free(save_exittext[status_saved]);
  4550.     }
  4551.  
  4552.     if (save_helptext[status_saved]) {
  4553.     strncpy(helptext,save_helptext[status_saved],20);
  4554.     free(save_helptext[status_saved]);
  4555.     }
  4556.  
  4557.     if (save_filetext[status_saved]) {
  4558.     strncpy(filetext,save_filetext[status_saved],20);
  4559.     free(save_filetext[status_saved]);
  4560.     }
  4561.  
  4562.     if (save_savefiletext[status_saved]) {
  4563.     strncpy(savefiletext,save_savefiletext[status_saved],20);
  4564.     free(save_savefiletext[status_saved]);
  4565.     }
  4566.  
  4567.     if (save_hostname[status_saved]) {
  4568.     strncpy(hostname,save_hostname[status_saved],20);
  4569.     free(save_hostname[status_saved]);
  4570.     }
  4571.  
  4572.     status_saved--;
  4573.     line25();
  4574. }
  4575.  
  4576. static void
  4577. strinsert(char *d, char *s) {
  4578.     while (*s)
  4579.       *d++ = *s++;
  4580. }
  4581.  
  4582. static void
  4583. xline25(char *s) {
  4584.     char attr;
  4585.     attr = colorstatus;
  4586. #ifdef OS2MOUSE
  4587.     os2_mousehide() ;
  4588. #endif /* OS2MOUSE */
  4589.     VioWrtCharStrAtt(s, xsize, ysize, 0, &attr, 0);
  4590. #ifdef OS2MOUSE
  4591.     os2_mouseshow() ;
  4592. #endif
  4593. }
  4594.  
  4595. static void
  4596. line25() {
  4597.     char *s = statusline;
  4598.     int  i;
  4599.  
  4600.     for (i = 0; i < xsize; i++)
  4601.     s[i] = ' ';
  4602.     if (usertext[0]) strinsert(&s[00], usertext);    /* Leftmost item */
  4603.     if (helptext[0]) strinsert(&s[18], helptext);
  4604.     if (exittext[0]) strinsert(&s[32], exittext);
  4605.     i = strlen(filetext);        /* How much needed for last item */
  4606.     if (i > 0) {
  4607.     strinsert(&s[79 - i], filetext); /* Right-justify it */
  4608.     if (hostname[0]) {
  4609.         i = 31 - i;            /* Space remaining for hostname */
  4610.         if ((int) strlen(hostname) > (i - 1)) { /* Too long? */
  4611.         int j;
  4612.         for (j = i; j > 0 && hostname[j] != ':'; j--) ;
  4613.         if (j > 0) {        /* Cut off ":service" if any */
  4614.             hostname[j] = '\0';
  4615.         } else {        /* Or else ... */
  4616.             hostname[i - 3] = '.'; /* show ellipsis */
  4617.             hostname[i - 2] = '.';
  4618.             hostname[i - 1] = '\0';
  4619.         }
  4620.         }
  4621.     }
  4622.     }
  4623.     if (hostname[0])
  4624.       strinsert(&s[47], hostname);
  4625.     xline25(s);
  4626. }
  4627.  
  4628. #ifdef COMMENT
  4629. static void
  4630. sendescseq(char * s) {
  4631.     sendchar(27);
  4632.     while (*s) {
  4633.     if (!network) msleep(50);
  4634.     sendchar(*s++);
  4635.     }
  4636. }
  4637. #endif /* COMMENT */
  4638.  
  4639. /*
  4640.  * RDCOMWRTSCR  --  Read from the communication device and write to the screen.
  4641.  * This function is executed by a separate thread.
  4642.  */
  4643.  
  4644. int
  4645. ckcgetc(int dummy) {
  4646.     return ttinc(1);
  4647. }
  4648.  
  4649. #ifdef __32BIT__
  4650. void 
  4651. rdcomwrtscr(void * pArgList)
  4652. #else
  4653. void FAR
  4654. rdcomwrtscr()
  4655. #endif /* __32BIT__ */
  4656. /* rdcomwrtscr */ {
  4657.     int c, cx, tx;
  4658.  
  4659.     DosSetPrty(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
  4660. #ifdef __32BIT__
  4661.     DosPostEventSem(threadsem);
  4662. #else
  4663.     DosSemClear(&threadsem);        /* Let 'em know we've started */
  4664. #endif
  4665.  
  4666.     while (active) {
  4667.     if (f_pushed) {            /* Handle 8-bit controls */
  4668.         c = c_pushed;        /* by converting to ESC + 7-bit char */
  4669.         f_pushed = 0;
  4670.         f_popped = 1;
  4671.     } else {
  4672.         c = ttinc(-50);        /* Get a character from the host */
  4673.         cx = c & cmask;        /* C1 check must be masked */
  4674.         f_popped = 0;
  4675.         if (tt_type >= TT_VT220) {      /* VT220 and above... */
  4676.         if (c1controls &&      /* Character set has C1 controls */
  4677.            (cx > 127) && (cx < 160) /* It's a C1 character */
  4678.             ) {
  4679.             f_pushed = 1;
  4680.             c_pushed = (c & 0x7F) | 0x40;
  4681.             c = ESC;
  4682.         }
  4683.         }
  4684.     }
  4685.     if (!active)            /* Connection broken? */
  4686.       break;
  4687.     if (c >= 0) {            /* Got character with no error? */
  4688.  
  4689. #ifdef TNCODE
  4690.           /* Handle TELNET negotiations here */    
  4691.         if (c == IAC && network && ttnproto == NP_TELNET) {
  4692.         if ((tx = tn_doop((CHAR)(c & 0xff),duplex,ckcgetc)) == 0) {
  4693.             continue;
  4694.         } else if (tx == -1) {    /* I/O error */
  4695.             strcpy(termessage, "Connection closed.\n");
  4696.             active = FALSE;    /* Quit */
  4697.             break;
  4698.         } else if (tx == 1) {    /* ECHO change */
  4699.             duplex = 1;        /* Get next char */
  4700.             continue;
  4701.         } else if (tx == 2) {    /* ECHO change */
  4702.             duplex = 0;        /* Get next char */
  4703.             continue;
  4704.         } else if (tx == 3) {    /* Quoted IAC */
  4705.             c = 255;        /* proceeed with it. */
  4706.         } else continue;    /* Unknown, get next char */
  4707.         }
  4708. #endif /* TNCODE */
  4709.  
  4710. #ifdef __32BIT__
  4711.         DosRequestMutexSem( hmtxScreenSem, SEM_INDEFINITE_WAIT ) ;
  4712. #ifdef OS2MOUSE
  4713.         if ( hMouse )
  4714.           DosRequestMutexSem( hmtxMouseSem, SEM_INDEFINITE_WAIT ) ;
  4715. #endif /* OS2MOUSE */
  4716. #else
  4717.         DosEnterCritSec();
  4718. #endif /* __32BIT__ */
  4719.         if (tt_hide && cursoron && cursorena) /* Kill cursor if more */
  4720.           if (ttchk() > 20)        /* than 20 input chars are buffered */
  4721.         killcursor();
  4722.  
  4723.             c &= cmask;            /* Maybe strip 8th bit */
  4724.  
  4725.         if (sosi && !debses) {    /* Handle Shift In / Shift Out */
  4726.         if (c == SO) {    /* Shift Out */
  4727.             inshift = 1;
  4728.             goto cont;
  4729.         } else if (c == SI) { /* Shift In */
  4730.             inshift = 0;
  4731.             goto cont;
  4732.         }
  4733.         if (inshift) c |= 0200;
  4734.         }
  4735.         if (escstate == ES_NORMAL) { /* Translate character sets */
  4736.         if (sxi) c = (*sxi)((CHAR)c);
  4737.         if (rxi) c = (*rxi)((CHAR)c);
  4738.         }
  4739. #ifdef COMMENT
  4740.         /* No longer needed, done in cwrite() */
  4741.         if (iskipesc) inesc = chkaes(inesc, (CHAR)c);
  4742.         /* Adjust escape sequence status */
  4743. #endif /* COMMENT */
  4744.         c &= cmdmsk;        /* Apply command mask. */
  4745.         if ((!debses) && (
  4746.            (tnlm && (c == LF || c == FF || c == 11)) || /* NEWLINE-MODE? */
  4747.            (c == CR && tt_crd)  /* CR-DISPLAY CRLF ? */
  4748.         )) {
  4749.         cwrite((char) CR);    /* Yes, output CR */
  4750.         if (seslog) logchar((char) CR);
  4751.         c = LF;             /* and insert a linefeed */
  4752.         }
  4753.         cwrite((char) c);
  4754.         if (seslog) logchar((char) c);
  4755.  
  4756. cont:    ;
  4757. #ifdef __32BIT__
  4758. #ifdef OS2MOUSE
  4759.         if ( hMouse )
  4760.           DosReleaseMutexSem( hmtxMouseSem ) ;
  4761. #endif /* OS2MOUSE */
  4762.         DosReleaseMutexSem( hmtxScreenSem ) ;
  4763. #else
  4764.         DosExitCritSec();
  4765. #endif /* __32BIT__ */
  4766.  
  4767.     } else if (c == -2) {
  4768.             active = FALSE;
  4769.         strcpy(termessage, "Connection closed.\n");
  4770.             /* link broken */
  4771.     } else if (tt_hide && !cursoron && cursorena) {
  4772. #ifdef __32BIT__
  4773.         DosRequestMutexSem( hmtxScreenSem, SEM_INDEFINITE_WAIT ) ;
  4774. #ifdef OS2MOUSE
  4775.         if ( hMouse )
  4776.           DosRequestMutexSem( hmtxMouseSem, SEM_INDEFINITE_WAIT ) ;
  4777. #endif /* OS2MOUSE */
  4778. #else
  4779.         DosEnterCritSec();
  4780. #endif /* __32BIT__ */
  4781.         newcursor();
  4782. #ifdef __32BIT__
  4783. #ifdef OS2MOUSE
  4784.         if ( hMouse )
  4785.           DosReleaseMutexSem( hmtxMouseSem ) ;
  4786. #endif /* OS2MOUSE */
  4787.         DosReleaseMutexSem( hmtxScreenSem ) ;
  4788. #else
  4789.         DosExitCritSec();
  4790. #endif /* __32BIT__ */
  4791.     }
  4792.     }
  4793.  
  4794. #ifdef __32BIT__
  4795.    _endthread() ;
  4796. #else 
  4797.     DosEnterCritSec();        /* Stop thread 1 discarding our stack before
  4798.                  * we've gone */
  4799.     DosSemClear(&threadsem);    /* Tell him we're going to die */
  4800.     DosExit(EXIT_THREAD, 0);
  4801. #endif /* __32BIT__ */
  4802. }
  4803.  
  4804. /* POPUPHELP  --  Give help message for connect.  */
  4805.  
  4806. static int helpcol, helprow;
  4807. static int helpwidth;
  4808.  
  4809. static void
  4810. helpstart(int w, int h) {        /* Start help window */
  4811.     unsigned char cell[2];
  4812.  
  4813.     cell[1] = colorhelp;
  4814.     helpwidth = w;
  4815.     helpcol = (xsize - w) / 2;        /* Column */
  4816.     helprow = (ysize - h) / 2 - 1;    /* Row */
  4817.     cell[0] = 201;            /* IBM upper left box corner double */
  4818. #ifdef OS2MOUSE
  4819.     os2_mousehide() ;
  4820. #endif /* OS2MOUSE */
  4821.     VioWrtNCell(cell, 1, helprow, helpcol, 0);
  4822.     cell[0] = 205;            /* Center box bar horizontal double */
  4823.     VioWrtNCell(cell, helpwidth, helprow, helpcol + 1, 0);
  4824.     cell[0] = 187;            /* Upper right box corner double */
  4825.     VioWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1, 0);
  4826. #ifdef OS2MOUSE
  4827.     os2_mouseshow() ;
  4828. #endif
  4829. }
  4830.  
  4831. static void
  4832. helpline(char *s) {            /* Add line to popup help */
  4833.     unsigned char cell[2];
  4834.     int i;
  4835.  
  4836.     i = strlen(s);            /* Length of this line */
  4837.     helprow++;
  4838.     cell[1] = colorhelp;
  4839.     cell[0] = 186;            /* IBM center bar vertical double */
  4840. #ifdef OS2MOUSE
  4841.     os2_mousehide() ;
  4842. #endif /* OS2MOUSE */
  4843.     VioWrtNCell(cell, 1, helprow, helpcol, 0);
  4844.     VioWrtCharStrAtt(s, i, helprow, helpcol + 1, &cell[1], 0);
  4845.     cell[0] = ' ';
  4846.     VioWrtNCell(cell, helpwidth - i, helprow, helpcol + 1 + i, 0);
  4847.     cell[0] = 186;            /* IBM center bar vertical double */
  4848.     VioWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1, 0);
  4849. #ifdef OS2MOUSE
  4850.     os2_mouseshow() ;
  4851. #endif
  4852. }
  4853.  
  4854. static void
  4855. helpend() {                /* End of popup help box */
  4856.     unsigned char cell[2];
  4857.  
  4858. #ifdef OS2MOUSE
  4859.     os2_mousehide() ;
  4860. #endif /* OS2MOUSE */
  4861.     helprow++;
  4862.     cell[1] = colorhelp;
  4863.     cell[0] = 200;            /* IBM lower left box corner double */
  4864.     VioWrtNCell(cell, 1, helprow, helpcol, 0);
  4865.     cell[0] = 205;            /* Center box bar horizontal double */
  4866.     VioWrtNCell(cell, helpwidth, helprow, helpcol + 1, 0);
  4867.     cell[0] = 188;            /* Lower right box corner double */
  4868.     VioWrtNCell(cell, 1, helprow, helpcol + helpwidth + 1, 0);
  4869. #ifdef OS2MOUSE
  4870.     os2_mouseshow() ;
  4871. #endif
  4872. }
  4873.  
  4874. static int
  4875. popuphelp(int x) {
  4876.     int c, n;
  4877.     char line[81];
  4878.     char kn[41];
  4879.     char *s;
  4880.     static char *hlpmsg[] = {
  4881.   "",
  4882.   " Command:   (SPACE to cancel)",
  4883.   "",
  4884.   "    C    to return to the C-Kermit prompt",
  4885.   "    U    to hangUp and return to the prompt",
  4886.   "    Q    to hangup and Quit C-Kermit",
  4887.   "    !    to enter the OS/2 command processor",
  4888.   "    F    to print or File the current screen",
  4889.   "",
  4890.   "    0    (zero) to send a null",
  4891.   "   ^%c    to send the escape character",
  4892.   "    B    to send a BREAK signal",
  4893.   "    L    to send a Long BREAK",
  4894.   "",
  4895. #ifdef TNCODE
  4896.   "    I    to Interrupt process (TELNET)",
  4897.   "    A    to send \"Are you there?\" (TELNET)",
  4898.   "",
  4899. #endif /* TNCODE */
  4900.   "    \\    backslash escape (end with ENTER):",
  4901.   "         \\nnn   decimal code, like \\199",
  4902.   "         \\Onnn  octal code, like \\o307",
  4903.   "         \\Xhh   hexadecimal code, like \\xC7",
  4904.   ""};
  4905. #define HELPSIZE (sizeof(hlpmsg)/sizeof(char *))
  4906.  
  4907.     static char *cmposmsg[] = {
  4908.   " COMPOSE SEQUENCES FOR MULTINATIONAL CHARACTERS",
  4909.   "",
  4910.   " Press two keys to compose the desired character:",
  4911.   "",
  4912.   " First  Second  Result",
  4913.   "   '     Vowel   Vowel with acute accent",
  4914.   "   `     Vowel   Vowel with grave accent",
  4915.   "   \"     Vowel   Vowel with diaeresis/trema/umlaut",
  4916.   "   ^     Vowel   Vowel with circumflex",
  4917.   "   *       A     A ring",
  4918.   "   ,       C     C cedilla",
  4919.   "   ~     N,A,O   Letter with tilde",
  4920.   "   A       E     AE digraph",
  4921.   "   O       /     O with stroke",
  4922.   "   s       s     German sharp s",
  4923.   "",
  4924.   " And others; see the documentation.",
  4925. };
  4926. #define COMPOSESIZE (sizeof(cmposmsg)/sizeof(char *))
  4927.  
  4928. #ifdef COMMENT
  4929.     unsigned char cell[MAXCOL * 2];    /* For saving status line */
  4930.     USHORT w;
  4931.     w = xsize * 2;
  4932. #ifdef OS2MOUSE
  4933.     os2_mousehide() ;
  4934. #endif
  4935.     VioReadCellStr(cell, &w, ysize - 1, 0, 0); /* Read status line */
  4936. #ifdef OS2MOUSE
  4937.     os2_mouseshow() ;
  4938. #endif
  4939. #else /* !COMMENT */
  4940. #ifdef __32BIT__
  4941.     DosRequestMutexSem( hmtxScreenSem, SEM_INDEFINITE_WAIT ) ;
  4942. #endif /* __32BIT__ */
  4943.     save_status_line();            /* Save current status line */
  4944. #endif /* COMMENT */
  4945.  
  4946.     savescreen(&helpscreen,wherex,wherey);
  4947.     if (cursorena)
  4948.       killcursor();
  4949.     if (x > 0) {            /* List escape-character commands */
  4950.     n = (x == 1) ? HELPSIZE : COMPOSESIZE; /* or compose-key help */
  4951.     helpstart(x == 1 ? 47 : 52, n);
  4952.     for (c = 0; c < n; c++) {
  4953.         s = (x == 1) ? hlpmsg[c] : cmposmsg[c];
  4954.         if (strchr(s, '%')) {
  4955.         sprintf(line, s, ctl(escape));
  4956.         helpline(line);
  4957.         } else
  4958.           helpline(s);
  4959.     }
  4960.  
  4961.     } else {                /* List "hot keys" */
  4962.  
  4963.     strcpy(usertext, " Press (almost) any key to restore the screen");
  4964.     exittext[0] = helptext[0] = hostname[0] = NUL;
  4965.     line25();
  4966.  
  4967.     if (roll.flag) {
  4968.         s = " OS/2 C-KERMIT - SCREEN ROLLBACK KEYS"; /* Box title */
  4969.         n = 13;            /* How many lines for help box */
  4970.         if (vik.upscn   < 256) n--;    /* Deduct for verbs not assigned */
  4971.         if (vik.upone   < 256) n--;
  4972.         if (vik.dnscn   < 256) n--;
  4973.         if (vik.dnone   < 256) n--;
  4974.         if (vik.homscn  < 256) n--;
  4975.         if (vik.endscn  < 256) n--;
  4976.         if (vik.prtscn  < 256) n--;
  4977.  
  4978.         helpstart(50, n);        /* Make popup window 50 x n */
  4979.         helpline(s);        /* 1 */
  4980.         helpline("");        /* 2 */
  4981.  
  4982.         if (vik.upscn > 255 && keynam[vik.upscn - 256]) {
  4983.         strncpy(kn,keynam[vik.upscn - 256],40);
  4984.         sprintf(line,"  %-15.14s%s",kn,"Roll backward one screen");
  4985.         helpline(line);        /* 3 */
  4986.         }
  4987.         if (vik.upone > 255 && keynam[vik.upone - 256]) {
  4988.         strncpy(kn,keynam[vik.upone - 256],40);
  4989.         sprintf(line,"  %-15.14s%s",kn,"Backward one line");
  4990.         helpline(line);        /* 4 */
  4991.         }
  4992.         if (vik.dnscn > 255 && keynam[vik.dnscn - 256]) {
  4993.         strncpy(kn,keynam[vik.dnscn - 256],40);
  4994.         sprintf(line,"  %-15.14s%s",kn,"Roll forward one screen");
  4995.         helpline(line);        /* 5 */
  4996.         }
  4997.         if (vik.dnone > 255 && keynam[vik.dnone - 256]) {
  4998.         strncpy(kn,keynam[vik.dnone - 256],40);
  4999.         sprintf(line,"  %-15.14s%s",kn,"Forward one line");
  5000.         helpline(line);        /* 6 */
  5001.         }
  5002.         if (vik.homscn > 255 && keynam[vik.homscn - 256]) {
  5003.         strncpy(kn,keynam[vik.homscn - 256],40);
  5004.         sprintf(line,"  %-15.14s%s",kn,"Back to beginning");
  5005.         helpline(line);        /* 7 */
  5006.         }
  5007.         if (vik.endscn > 255 && keynam[vik.endscn - 256]) {
  5008.         strncpy(kn,keynam[vik.endscn - 256],40);
  5009.         sprintf(line,"  %-15.14s%s",kn,"Forward to end");
  5010.         helpline(line);        /* 8 */
  5011.         }
  5012.         if (vik.dump > 255 && keynam[vik.dump - 256]) {
  5013.         strncpy(kn,keynam[vik.dump - 256],40);
  5014.         sprintf(line,"  %-15.14s%s",kn,"Print the current screen");
  5015.         helpline(line);        /* 9 */
  5016.         }
  5017.         helpline("");        /* 10 */
  5018.         helpline(tt_roll ?
  5019.              " TERMINAL ROLL is ON: No other keys are valid." :
  5020.              " TERMINAL ROLL is OFF: All keys are valid."
  5021.              );            /* 11 */
  5022.         sprintf(line, " Rollback buffer size: %d lines.",tt_scrsize);
  5023.         helpline(line);        /* 12 */
  5024.         helpline(" Use SET TERMINAL SCROLLBACK to change it."); /* 13 */
  5025.  
  5026.     } else {            /* Regular help message */
  5027.         
  5028.         n = 19;            /* How many lines */
  5029.         s = " OS/2 C-KERMIT - IMPORTANT KEYS";
  5030.         if (vik.upscn   < 256) n--;    /* Deduct for verbs not assigned */
  5031.         if (vik.dnscn   < 256) n--;
  5032.         if (vik.flipscn < 256) n--;
  5033.         if (vik.debug   < 256) n--;
  5034.         if (vik.reset   < 256) n--;
  5035.         if (vik.prtscn  < 256) n--;
  5036.         if (vik.printff < 256) n--;
  5037.         if (vik.compose < 256) n--;
  5038.  
  5039.         helpstart(50, n);        /* Make popup window 50 x n */
  5040.         helpline(s);        /* 1 */
  5041.         helpline("");        /* 2 */
  5042.  
  5043.         if (vik.exit > 255 && keynam[vik.exit - 256])
  5044.           strncpy(kn,keynam[vik.exit - 256],40);
  5045.         else
  5046.           sprintf(kn, "Ctrl-%c?", ctl(escape));
  5047.         sprintf(line,"  %-15.14s%s",kn,"Return to the C-Kermit prompt");
  5048.         helpline(line);            /* 3 */
  5049.  
  5050.         if (vik.hangup > 255 && keynam[vik.hangup - 256])
  5051.           strncpy(kn,keynam[vik.hangup - 256],40);
  5052.         else
  5053.           sprintf(kn, "Ctrl-%cH", ctl(escape));
  5054.         sprintf(line,"  %-15.14s%s",kn,"Hang up and return to the prompt");
  5055.         helpline(line);            /* 4 */
  5056.  
  5057.         if (vik.os2 > 255 && keynam[vik.os2 - 256])
  5058.           strncpy(kn,keynam[vik.os2 - 256],40);
  5059.         else
  5060.           sprintf(kn, "Ctrl-%c!", ctl(escape));
  5061.         sprintf(line,"  %-15.14s%s",kn,"Enter OS/2 command processor");
  5062.         helpline(line);            /* 5 */
  5063.  
  5064.         if (vik.xbreak > 255 && keynam[vik.xbreak - 256])
  5065.           strncpy(kn,keynam[vik.xbreak - 256],40);
  5066.         else
  5067.           sprintf(kn, "Ctrl-%cB", ctl(escape));
  5068.         sprintf(line,"  %-15.14s%s",kn,
  5069.             (network && ttnproto == NP_TELNET) ?
  5070.             "Send TELNET BREAK" :
  5071.             "Send a BREAK signal"
  5072.             );
  5073.         helpline(line);            /* 6 */
  5074.  
  5075.         if (!network) {
  5076.         if ((vik.lbreak > 255) && (keynam[vik.lbreak - 256]))
  5077.           strncpy(kn,keynam[vik.lbreak - 256],40);
  5078.         else
  5079.           sprintf(kn, "Ctrl-%cL", ctl(escape));
  5080.         sprintf(line,"  %-15.14s%s",kn,"Send a Long BREAK signal");
  5081.         helpline(line);            /* 7 */
  5082.         }
  5083.  
  5084.         if (vik.dump > 255 && keynam[vik.dump - 256])
  5085.           strncpy(kn,keynam[vik.dump - 256],40);
  5086.         else
  5087.           sprintf(kn, "Ctrl-%cF", ctl(escape));
  5088.         sprintf(line,"  %-15.14s%s",kn,"Print the current screen");
  5089.         helpline(line);            /* 8 */
  5090.  
  5091.         if (vik.prtscn > 255 && keynam[vik.prtscn - 256]) {
  5092.         strncpy(kn,keynam[vik.prtscn - 256],40);
  5093.         sprintf(line,"  %-15.14s%s%s",kn,"Turn printer ",
  5094.             printon ? "OFF" : "ON");
  5095.         helpline(line);        /* 9, maybe */
  5096.         }
  5097.  
  5098.         if (vik.printff > 255 && keynam[vik.printff - 256]) {
  5099.         strncpy(kn,keynam[vik.printff - 256],40);
  5100.         sprintf(line,"  %-15.14s%s",kn,"Print formeed / page eject");
  5101.         helpline(line);        /* 10, maybe */
  5102.         }
  5103.  
  5104.         if (vik.upscn > 255 && keynam[vik.upscn - 256]) {
  5105.         strncpy(kn,keynam[vik.upscn - 256],40);
  5106.         sprintf(line,"  %-15.14s%s",kn,"Roll backward one screen");
  5107.         helpline(line);        /* 11, maybe */
  5108.         }
  5109.  
  5110.         if (vik.dnscn > 255 && keynam[vik.dnscn - 256]) {
  5111.         strncpy(kn,keynam[vik.dnscn - 256],40);
  5112.         sprintf(line,"  %-15.14s%s",kn,"Roll forward one screen");
  5113.         helpline(line);        /* 12, maybe */
  5114.         }
  5115.  
  5116.         if (vik.flipscn > 255 && keynam[vik.flipscn - 256]) {
  5117.         strncpy(kn,keynam[vik.flipscn - 256],40);
  5118.         sprintf(line,"  %-15.14s%s%s",kn,
  5119.             (decscnm ? "Normal" : "Reverse"),
  5120.             " screen video");
  5121.         helpline(line);        /* 13, maybe */
  5122.         }
  5123.  
  5124.         if (vik.debug > 255 && keynam[vik.debug - 256]) {
  5125.         strncpy(kn,keynam[vik.debug - 256],40);
  5126.         sprintf(line,"  %-15.14s%s%s",kn,"Turn terminal debugging ",
  5127.             debses ? "OFF" : "ON");
  5128.         helpline(line);        /* 14, maybe */
  5129.         }
  5130.  
  5131.         if (vik.reset > 255 && keynam[vik.reset - 256]) {
  5132.         strncpy(kn,keynam[vik.reset - 256],40);
  5133.         sprintf(line,"  %-15.14s%s",kn,"Reset the terminal emulator");
  5134.         helpline(line);        /* 15, maybe */
  5135.         }
  5136.  
  5137.         if (vik.compose > 255 && keynam[vik.compose - 256]) {
  5138.         strncpy(kn,keynam[vik.compose - 256],40);
  5139.         sprintf(line,"  %-15.14s%s",kn,"Compose a special character");
  5140.         helpline(line);        /* 16, maybe */
  5141.         }
  5142.  
  5143.         helpline("");        /* 17 */
  5144.         sprintf(line," or the CONNECT-mode escape character Ctrl-%c",
  5145.             ctl(escape));
  5146.         helpline(line);        /* 18 */
  5147.         helpline(" followed by ? for additional commands."); /* 19 */
  5148.  
  5149.     }
  5150.     }
  5151.     helpend();                /* Write bottom of help panel */
  5152.     c = keymap[congks(0)];        /* Wait till user hits a key */
  5153.     if (cursorena)            /* If cursor is enabled */
  5154.       newcursor();            /* turn it back on */
  5155.     restorescreen(&helpscreen);        /* Restore terminal screen */
  5156. #ifdef COMMENT
  5157. #ifdef OS2MOUSE
  5158.     os2_mousehide() ;
  5159. #endif /* OS2MOUSE */
  5160.     VioWrtCellStr(cell, w, ysize -1, 0, 0); /* Restore the status line */
  5161. #ifdef OS2MOUSE
  5162.     os2_mouseshow() ;
  5163. #endif
  5164. #else
  5165.     restore_status_line();
  5166. #ifdef __32BIT__
  5167.     DosReleaseMutexSem( hmtxScreenSem ) ;
  5168. #endif /* __32BIT__ */
  5169. #endif /* COMMENT */
  5170.     return (c);
  5171. }
  5172.  
  5173. /* CHSTR  --  Make a printable string out of a character  */
  5174.  
  5175. static char*
  5176. chstr(int c) {
  5177.     static char s[8];
  5178.     char *cp = s;
  5179.  
  5180.     if (c < SP || c == DEL)
  5181.       sprintf(cp, "CTRL-%c", ctl(c));
  5182.     else
  5183.       sprintf(cp, "'%c'\n", c);
  5184.     cp = s;
  5185.     return (cp);
  5186. }
  5187.  
  5188. /* DOESC  --  Process an escape character argument  */
  5189.  
  5190. static void
  5191. esc25(int h) {
  5192.     strcpy(usertext, " Command:");
  5193.     strcpy(exittext, h ? "" : (esc_exit ? "Exit: c" : "Prompt: c"));
  5194.     strcpy(helptext, h ? "" : "Help: h");
  5195.     line25();
  5196. }
  5197.  
  5198. static void
  5199. doesc(int c) {
  5200.     int x;
  5201.     CHAR d, temp[8];
  5202.  
  5203.     while (1) {
  5204.     if (c == escape) {    /* Send escape character */
  5205.         sendchar((char)c);
  5206.         return;
  5207.     } else if (isupper(c))    /* Or else look it up below. */
  5208.         c = tolower(c);
  5209.  
  5210.     switch (c) {
  5211.  
  5212.     case 'c':        /* Return to prompt */
  5213.     case '\03':
  5214.         active = 0;
  5215.         return;
  5216.  
  5217.     case 'u':        /* Hangup and return to command mode */
  5218.         hangnow = 1;
  5219.         active = 0;
  5220.         strcpy(termessage, "Hangup.\n");
  5221.         return;
  5222.  
  5223.     case 'q':               /* Hangup and quit */
  5224.         active = 0;
  5225.         hangnow = 1;
  5226.         quitnow = 1;
  5227.         strcpy(termessage, "Hangup and quit.\n");
  5228.         return;
  5229.  
  5230.     case '!':        /* Push to OS/2 */
  5231.         os2push();
  5232.         return;
  5233.  
  5234.     case 'b':        /* Send a BREAK signal */
  5235.     case '\02':
  5236.         ttsndb();
  5237.         return;
  5238.  
  5239.     case 'l':        /* Send a Long BREAK signal */
  5240.     case '\014':
  5241.         ttsndlb();
  5242.         return;
  5243.  
  5244.     case 'f':        /* Print/dump screen */
  5245.         x = xprintff; xprintff = 0;
  5246.         prtscreen(1,ysize);
  5247.         xprintff = x;
  5248.         return;
  5249.  
  5250.     case '0':        /* Send a NUL character */
  5251.         c = '\0';
  5252.         sendchar((char)c);
  5253.         return;
  5254.  
  5255. #ifdef NETCONN
  5256. #ifdef TCPSOCKET
  5257.     case 'i':            /* Send TELNET Interrupt Process */
  5258.         do_tn_cmd((CHAR) IP);
  5259.         return;
  5260.  
  5261.     case 'a':            /* "Are You There?" */
  5262.         do_tn_cmd((CHAR) AYT);
  5263.         return;
  5264. #endif /* TCPSOCKET */
  5265. #endif /* NETCONN */
  5266.  
  5267.         case '\\':
  5268.             {
  5269.                 char kbuf[32];
  5270.         char *kbp = kbuf, *text = usertext + 2;
  5271.  
  5272.         *kbp++ = c;
  5273.  
  5274.                 strcpy(usertext, " \\");
  5275.                 strcpy(exittext,"Exit: ENTER");
  5276.                 helptext[0] = 0;
  5277.                 line25();
  5278.  
  5279.         while (((c = (coninc(0) & cmdmsk)) != '\r') && (c != '\n')) {
  5280.                   if ( c == '\b' ) {
  5281.                     if ( kbp > kbuf + 1 ) {
  5282.               *--kbp = 0;
  5283.                       *--text = 0;
  5284.                     }
  5285.                   } else if ( kbp - kbuf < sizeof(kbuf) - 2 ) {
  5286.             *kbp++ = c;
  5287.                     *text++ = c;
  5288.                     *text = 0;
  5289.                   }
  5290.                   line25();
  5291.                 }
  5292.  
  5293.         *kbp = 0; kbp = kbuf;
  5294.         c = xxesc(&kbp);    /* Interpret it */
  5295.  
  5296.         if (c >= 0) {
  5297.                 sendcharduplex((char)c);
  5298.             return;
  5299.         } else {        /* Invalid backslash code. */
  5300.             conoc(BEL);
  5301.             return;
  5302.         }
  5303.         }
  5304.             return;
  5305.  
  5306.     case SP:        /* Space, ignore */
  5307.         return;
  5308.  
  5309.     default:        /* Other */
  5310.         conoc(BEL);
  5311.         return;        /* Invalid esc arg, beep */
  5312.     }
  5313.     }
  5314. }
  5315.  
  5316. /* CHECKSCREENMODE  --  Make sure we are in a usable mode */
  5317.  
  5318. int                    /* NOTE: not static, on purpose */
  5319. ttgwsiz() {                /* Get Window Size */
  5320.     if (xsize < 0 || ysize < 0)
  5321.       checkscreenmode();
  5322.     return((tt_rows < 1 || tt_cols < 1) ? 0 : 1);
  5323. }
  5324.  
  5325. static void
  5326. checkscreenmode() {
  5327.     VIOMODEINFO  m;
  5328. #ifdef COMMENT                /* Moved to setcursormode() */
  5329.     VIOINTENSITY vi;
  5330.  
  5331.     vi.cb = sizeof(vi);
  5332.     vi.type = 2;
  5333.     vi.fs = 1;
  5334.     VioSetState(&vi, 0);
  5335. #endif /* COMMENT */
  5336.     
  5337.     m.cb = sizeof(m);
  5338.     assert(VioGetMode(&m, 0) == 0);
  5339.  
  5340.     /* Terminal screen not created yet, or user changed the screen size. */
  5341.  
  5342.     if ( xsize != min(MAXCOL, m.col) || ysize != min(MAXROW, m.row) - 1 ) {
  5343.     scrninitialised = 0;
  5344.     if ( roll.buffer )
  5345.       free(roll.buffer);
  5346.     roll.buffer = NULL;
  5347.     if ( vt100screen.scrncpy )
  5348.       free(vt100screen.scrncpy);
  5349.     vt100screen.scrncpy = NULL;
  5350.     if ( commandscreen.scrncpy )
  5351.       free(commandscreen.scrncpy);
  5352.     commandscreen.scrncpy = NULL;
  5353.     if ( savedscreen.scrncpy )
  5354.       free(savedscreen.scrncpy);
  5355.     savedscreen.scrncpy = NULL;
  5356.     if ( helpscreen.scrncpy )
  5357.       free(helpscreen.scrncpy);
  5358.     helpscreen.scrncpy = NULL;
  5359. #ifdef OS2MOUSE
  5360.     if ( mousescreen.scrncpy )
  5361.       free(mousescreen.scrncpy);
  5362.     mousescreen.scrncpy = NULL;
  5363. #endif /* OS2MOUSE */
  5364.    tt_cols = xsize = min(MAXCOL, m.col);
  5365.     tt_rows = ysize = min(MAXROW, m.row) - 1;
  5366. /*
  5367.   If there is a scrolling window in effect, this will wipe it out.  However,
  5368.   this code is executed only upon the first CONNECT, or when the user changed
  5369.   screen sizes while escaped back.  Any nondefault scrolling region does not
  5370.   make sense under these conditions anyway.  The "if" clause is commented out
  5371.   because leaving it in could do more harm than good, for example if the new
  5372.   screen is smaller than the old scrolling region.
  5373.  
  5374.         if (!relcursor)
  5375. */
  5376.       marginbot = ysize;
  5377.     }
  5378.     if ( !vt100screen.scrncpy ) {
  5379.     vt100screen.scrncpy = malloc(xsize * (ysize + 1) * 2);
  5380.     }
  5381.     assert(vt100screen.scrncpy != NULL);
  5382.     if ( !commandscreen.scrncpy )
  5383.       commandscreen.scrncpy = malloc(xsize * (ysize + 1) * 2);
  5384.     assert(commandscreen.scrncpy != NULL);
  5385.     if ( !savedscreen.scrncpy )
  5386.       savedscreen.scrncpy = malloc(xsize * (ysize + 1) * 2);
  5387.     assert(savedscreen.scrncpy != NULL);
  5388.     if ( !helpscreen.scrncpy )
  5389.       helpscreen.scrncpy = malloc(xsize * (ysize + 1) * 2);
  5390.     assert(helpscreen.scrncpy != NULL);
  5391. #ifdef OS2MOUSE
  5392.     if ( !mousescreen.scrncpy )
  5393.       mousescreen.scrncpy = malloc(xsize * (ysize + 1) * 2);
  5394.     assert(mousescreen.scrncpy != NULL);
  5395. #endif /* OS2MOUSE */
  5396. }
  5397.  
  5398. static void
  5399. setcursormode() {
  5400.     VIOMODEINFO vmi;
  5401.     VIOCURSORINFO vci;
  5402.     VIOINTENSITY vi;
  5403.     int cell, bottom, top;
  5404.  
  5405.     vmi.cb = sizeof(vmi);
  5406.     VioGetMode(&vmi, 0);
  5407.     cell   = vmi.vres / vmi.row;
  5408.  
  5409.     VioGetCurType(&vci, 0);
  5410.     crsr_command = vci;
  5411.  
  5412.     vci.cEnd   = cell - 1;
  5413.     vci.yStart = (tt_cursor == 0) ? cell - 2 :
  5414.                  cell - 1 - (cell - 2) * tt_cursor / 2;
  5415.  
  5416.     VioSetCurType(&vci, 0);
  5417. /*
  5418.   Note: For some reason, choosing vi.fs = 0 makes *everything* blink.
  5419.   Receipt of "turn-on-blink" escape sequences turn off blinking.  Thus,
  5420.   everything is backwards.  But when vi.fs = 1, the sense is not reversed.
  5421.   A puzzle.
  5422. */
  5423.     vi.cb = sizeof(vi);
  5424.     vi.type = 2;            /* High-intensity vs blinking */
  5425.     vi.fs = 1;                /* 0 = blinking, 1 = hi intensity */
  5426.     VioSetState(&vi, 0);
  5427. }
  5428.  
  5429. static void
  5430. restorecursormode() {
  5431.     VioSetCurType(&crsr_command, 0);
  5432. }
  5433.  
  5434. #ifdef __32BIT__
  5435. /* C O N K B D H A N D L E R */
  5436.  
  5437. void
  5438. conkbdhandler(void *pArgList) {
  5439.     int c, cm, cx, tx;
  5440.  
  5441.     DosPostEventSem(threadsem2);
  5442.  
  5443.   while (active) {        /* Read the keyboard and write to comms line */
  5444.     c = congks(1);            /* Get keystroke */
  5445.     if (!active)            /* Exit if this happened */
  5446.       break;            /*  (in any of various ways) */
  5447.     if (c == -1) {            /* like:... */
  5448.         if (!active)
  5449.           strcpy(termessage, "Carrier lost.\n");
  5450.         continue;
  5451.     }
  5452.     cm = keymap[c];            /* Do key mapping */
  5453.     if (cm == escape) {        /* Is it the escape character? */
  5454.         DosRequestMutexSem( hmtxScreenSem, SEM_INDEFINITE_WAIT ) ;
  5455.         save_status_line();        /* Yes, save current status line.  */
  5456.         esc25(0);            /* Make new one. */
  5457.         c = keymap[congks(0)];    /* Get escape command. */
  5458.         if (c == '?' || c == 'h' || c == 'H') { /* They want help menu. */
  5459.             esc25(1);        /* Show it */
  5460.         c = popuphelp(1);    /* Then get real escape command */
  5461.         }
  5462.         doesc(c);            /* And process it */
  5463.         restore_status_line();    /* Then restore status line */
  5464.        DosReleaseMutexSem( hmtxScreenSem ) ;
  5465.     } else {            /* Ordinary character */
  5466.         if (!keylock)        /* If keyboard not locked, */
  5467.           vt100key(c);        /* go process it. */
  5468.     }
  5469.     } /* while (active) */
  5470.  
  5471.     _endthread() ;
  5472. }
  5473. #endif /* __32BIT__ */
  5474.  
  5475.  
  5476. /*  C O N E C T  --  Perform CONNECT command  */
  5477.  
  5478. int                /* NOTE: Not static */
  5479. conect() {
  5480.     USHORT          len, x, y;
  5481.     int             i, c, cm;    /* c is a character, but must be signed
  5482.                  * integer to pass thru -1, which is the
  5483.                  * modem disconnection signal, and is
  5484.                  * different from the character 0377 */
  5485.  
  5486.     char errmsg[50], *erp, ac, bc;
  5487.  
  5488. #ifdef CK_APC
  5489.     apcactive = FALSE;
  5490. #endif /* CK_APC */
  5491.     if (!network && speed < 0) {
  5492.     printf("Sorry, you must set speed first.\n");
  5493.     return (0);
  5494.     }
  5495.  
  5496.     if ((escape < 0) || (escape > 0177)) {
  5497.     printf("Escape character out of range: %d\n", escape);
  5498.     return (0);
  5499.     }
  5500.     if (ttopen(ttname, &local, network ? -nettype : mdmtyp, 0) < 0) {
  5501.     erp = errmsg;
  5502.     sprintf(erp, "Sorry, can't open %s", ttname);
  5503.     perror(errmsg);
  5504.     return (0);
  5505.     }
  5506.     /* Condition console terminal and communication line */
  5507.     if (ttvt(speed, flow) < 0) {
  5508.     printf("Sorry, Can't condition communication line\n");
  5509.     return (0);
  5510.     }
  5511.     if (!network && carrier != CAR_OFF && (ttgmdm() & BM_DCD) == 0) {
  5512.         printf("No carrier detected on %s.\n",ttname);
  5513.     printf("Hint: Use the DIAL command, or else SET CARRIER OFF.\n");
  5514.     printf(
  5515.   "If you want to make a network connection, use SET HOST or TELNET.\n");
  5516.     return (0);
  5517.     }
  5518.     my_tt_type = tt_type;        /* Remember prevailing type */
  5519.     what = W_CONNECT;            /* Keep track of what we're doing */
  5520.  
  5521.     /* Will C-Kermit exit when user escapes back? */
  5522.  
  5523.     esc_exit = (cflg || cnflg) && !stayflg;
  5524.     esc_msg  = esc_exit ? "Exit:" : "Prompt:";
  5525.  
  5526.     /* Construct ENQ/Answerback message */
  5527.     sprintf(answerback,"OS/2 C-Kermit %ld %s\n",
  5528.         vernum,
  5529.         tt_info[my_tt_type].x_name
  5530.         );
  5531.  
  5532.     /* Initialize Very Important Keys structure */
  5533.  
  5534.     vik.help = 0;
  5535.     vik.exit = 0;
  5536.     vik.upscn = 0;
  5537.     vik.dnscn = 0;
  5538.     vik.upone = 0;
  5539.     vik.dnone = 0;
  5540.     vik.homscn = 0;
  5541.     vik.endscn = 0;
  5542.     vik.hangup = 0;
  5543.     vik.xbreak = 0;
  5544.     vik.lbreak = 0;
  5545.     vik.dump = 0;
  5546.     vik.prtscn = 0;
  5547.     vik.os2 = 0;
  5548.     vik.printff = 0;
  5549.     vik.flipscn = 0;
  5550.     vik.debug = 0;
  5551.     vik.reset = 0;
  5552.     vik.compose = 0;
  5553.  
  5554.     for (i = 256; i < KMSIZE; i++) {
  5555.     if (!vik.help && (keymap[i] == (F_KVERB | K_HELP)))
  5556.       vik.help = i;
  5557.     else if (!vik.exit && (keymap[i] == (F_KVERB | K_EXIT)))
  5558.       vik.exit = i;
  5559.     else if (keymap[i] == (F_KVERB | K_UPSCN))
  5560.       vik.upscn = i;
  5561.     else if (keymap[i] == (F_KVERB | K_DNSCN))
  5562.       vik.dnscn = i;
  5563.     else if (keymap[i] == (F_KVERB | K_UPONE))
  5564.       vik.upone = i;
  5565.     else if (keymap[i] == (F_KVERB | K_DNONE))
  5566.       vik.dnone = i;
  5567.     else if (keymap[i] == (F_KVERB | K_HOMSCN))
  5568.       vik.homscn = i;
  5569.     else if (keymap[i] == (F_KVERB | K_ENDSCN))
  5570.       vik.endscn = i;
  5571.     else if (!vik.hangup && (keymap[i] == (F_KVERB | K_HANGUP)))
  5572.       vik.hangup = i;
  5573.     else if (!vik.xbreak && (keymap[i] == (F_KVERB | K_BREAK)))
  5574.       vik.xbreak = i;
  5575.     else if (!vik.lbreak && (keymap[i] == (F_KVERB | K_LBREAK)))
  5576.       vik.lbreak = i;
  5577.     else if (!vik.dump && (keymap[i] == (F_KVERB | K_DUMP)))
  5578.       vik.dump = i;
  5579.     else if (!vik.flipscn && (keymap[i] == (F_KVERB | K_FLIPSCN)))
  5580.       vik.flipscn = i;
  5581.     else if (!vik.debug && (keymap[i] == (F_KVERB | K_DEBUG)))
  5582.       vik.debug = i;
  5583.     else if (!vik.reset && (keymap[i] == (F_KVERB | K_RESET)))
  5584.       vik.reset = i;
  5585.     else if (!vik.os2 && (keymap[i] == (F_KVERB | K_DOS)))
  5586.       vik.os2 = i;
  5587.     else if (!vik.prtscn && (keymap[i] == (F_KVERB | K_PRTSCN)))
  5588.       vik.prtscn = i;
  5589.     else if (!vik.printff && (keymap[i] == (F_KVERB | K_PRINTFF)))
  5590.       vik.printff = i;
  5591.     else if (!vik.compose && (keymap[i] == (F_KVERB | K_COMPOSE)))
  5592.       vik.compose = i;
  5593.     }
  5594.     keymac = 0;                /* Initialize \Kmacro flag */
  5595.     keymacx = -1;            /* and index */
  5596.  
  5597.     outshift = inshift = 0;        /* Initial SI/SO shift state. */
  5598.     langsv = language;            /* No language rules during CONNECT! */
  5599.     language = L_USASCII;
  5600.     if (debses) {            /* Session debugging? */
  5601.     tcs = TC_TRANSP;        /* No character-set translation */
  5602.     sxo = rxo = NULL;        /* If so, no translation. */
  5603.     sxi = rxi = NULL;
  5604.     escstate = ES_NORMAL;        /* No escape-sequence processing */
  5605.     tt_wrap = TRUE;            /* Always wrap */
  5606.     } else {                /* No session debugging */
  5607.     tcs = gettcs(tcsr,tcsl);    /* Get intermediate set. */
  5608.     if (tcsr == tcsl) {        /* Remote and local sets the same? */
  5609.         sxo = rxo = NULL;        /* If so, no translation. */
  5610.         sxi = rxi = NULL;
  5611.     } else {            /* Otherwise, set up */
  5612.         sxo = xls[tcs][tcsl];    /* translation function */
  5613.         rxo = xlr[tcs][tcsr];    /* pointers for output functions */
  5614.         sxi = xls[tcs][tcsr];    /* and for input functions. */
  5615.         rxi = xlr[tcs][tcsl];
  5616.     }
  5617.     }
  5618. /*
  5619.   C1 Control characters are possible only if the remote terminal
  5620.   character set does not include graphic characters in the C1 area.
  5621. */
  5622.     c1controls = (tcsl != tcsr) &&    /* Transparent character-set */
  5623.                  (tcsr != FC_CP850) &&    /* or IBM code page */
  5624.          (tcsr != FC_CP437) &&
  5625.          (tcsr != FC_CP852) &&
  5626.          (tcsr != FC_NEXT) &&    /* or NeXT character set */
  5627.          (tcsr != FC_APPQD);    /* or Apple Quickdraw */
  5628.  
  5629. #ifdef COMMENT
  5630.     iskipesc = 
  5631. #endif /* COMMENT */
  5632.       oskipesc = (tcs != TC_TRANSP) &&    /* Not transparent */
  5633.       (fcsinfo[tcsl].size == 128 || fcsinfo[tcsr].size == 128) && /* 7 bits */
  5634.     (fcsinfo[tcsl].code != FC_USASCII);
  5635. #ifdef COMMENT
  5636.     inesc = 
  5637. #endif /* COMMENT */
  5638.       outesc = ES_NORMAL;        /* Initial state of recognizer */
  5639.  
  5640. #ifdef CK_BORDER
  5641.     saveborder();            /* Save command-screen border */
  5642. #endif /* CK_BORDER */
  5643.     checkscreenmode();            /* Initialize terminal emulator */
  5644.     setcursormode();
  5645.     VioGetCurPos(&y, &x, 0);        /* Command screen cursor position */
  5646.     wherex = x + 1;
  5647.     wherey = y + 1;
  5648.     savescreen(&commandscreen,wherex,wherey); /* Remember OS/2 screen */
  5649.     colorcmd = commandscreen.scrncpy[(x + y * xsize) * 2 + 1];
  5650.     scrninit();
  5651.     restorescreen(&vt100screen);    /* Put up previous terminal */
  5652.                     /* emulation screen, if any */
  5653.     newcursor();            /* Install cursor */
  5654.     conraw();                /* Put console in raw mode */
  5655.     connoi();                /* No interrupts from console */
  5656.     ipadl25();                /* Put up status line */
  5657.     waittime = tt_ctstmo * 1000L;    /* CTS timeout */
  5658.  
  5659.     /* Create a thread to read the comms line and write to the screen */
  5660.  
  5661.     active = 1;            /* So thread 2 doesn't end at once */
  5662.     quitnow = 0;
  5663.     hangnow = 0;
  5664.     termessage[0] = 0;
  5665.  
  5666. #ifdef __32BIT__
  5667.     DosCreateEventSem(NULL, &threadsem, 0, 0);
  5668.     DosResetEventSem(threadsem, &semcount);
  5669.     threadid = _beginthread( &rdcomwrtscr, 0, THRDSTKSIZ, 0 ) ;
  5670.     if ( threadid == -1 ) {
  5671.     printf("Sorry, can't create thread\n");
  5672.     return (0);
  5673.     }
  5674.     DosWaitEventSem(threadsem, -1L);
  5675. #else /* Not __32BIT__ */
  5676.     DosSemSet(&threadsem);    /* Thread 2 will clear this when it starts */
  5677.     if (DosCreateThread(rdcomwrtscr, &threadid,
  5678.             (PBYTE)(stack + THRDSTKSIZ))) {
  5679.     printf("Sorry, can't create thread\n");
  5680.     return (0);
  5681.     }
  5682.     DosSemWait(&threadsem, -1L);/* Wait for thread to start */
  5683.     DosSemSet(&threadsem);    /* Thread 2 will clear this on termination */
  5684. #endif /* __32BIT__ */
  5685.  
  5686. #ifdef __32BIT__
  5687.    /* Use a separate thread for Keyboard handling */
  5688.  
  5689.     DosCreateEventSem(NULL, &threadsem2, 0, 0);
  5690.     DosResetEventSem(threadsem2, &semcount2);
  5691.     threadid2 = _beginthread( &conkbdhandler, 0, THRDSTKSIZ, 0 ) ;
  5692.     if ( threadid2 == -1) {
  5693.     printf("Sorry, can't create thread\n");
  5694.     return (0);
  5695.     }
  5696.     DosWaitEventSem(threadsem2, -1L);
  5697.  
  5698. #ifdef OS2MOUSE
  5699.     if (tt_mouse) 
  5700.       os2_mouseon() ;
  5701. #endif /* OS2MOUSE */
  5702.  
  5703.     while (active) {
  5704.     active = network ||        /* I/O error on network connection */
  5705.       (carrier == CAR_OFF) ||    /* Carrier dropped */
  5706.         ((ttgmdm() & BM_DCD) != 0);
  5707.     DosSleep( 1000 ) ;
  5708.     }
  5709.  
  5710.     debug( F100,"Exiting connect mode","",0) ;
  5711. #ifdef COMMENT
  5712. /*
  5713.   If APC commands come too quickly, this thread dies upon startup and its
  5714.   threadid gets used by the mouse.  So we can't wait for it to die.  Why are
  5715.   we waiting anyway?  We no longer allow it to take direct control of the
  5716.   keyboard, so even if it takes a couple of milliseconds to die off, there
  5717.   shouldn't be any problems.
  5718. */
  5719.     DosWaitThread( &threadid2, DCWW_WAIT ) ;
  5720.     debug( F100,"conkbdhandler() is dead","",0) ;
  5721. #endif /* COMMENT */
  5722. #ifdef OS2MOUSE
  5723.     if (tt_mouse)
  5724.       os2_mouseoff() ;
  5725. #endif /* OS2MOUSE */
  5726.  
  5727. #else /* Not __32BIT__ */
  5728.    /* Perform keyboard handling in main thread */
  5729.  
  5730.     while (active) {        /* Read the keyboard and write to comms line */
  5731.     c = congks(2);            /* Get keystroke */
  5732.     if (!active)            /* Exit if this happened */
  5733.       break;            /*  (in any of various ways) */
  5734.     if (c == -1) {            /* like:... */
  5735.         active = network ||        /* I/O error on network connection */
  5736.           (carrier == CAR_OFF) ||    /* Carrier dropped */
  5737.         ((ttgmdm() & BM_DCD) != 0);
  5738.         if (!active)
  5739.           strcpy(termessage, "Carrier lost.\n");
  5740.         continue;
  5741.     }
  5742.     cm = keymap[c];            /* Do key mapping */
  5743.     DosEnterCritSec();        /* Protect the runtime library */
  5744.     if (cm == escape) {        /* Is it the escape character? */
  5745.         save_status_line();        /* Yes, save current status line.  */
  5746.         esc25(0);            /* Make new one. */
  5747.         c = keymap[congks(0)];    /* Get escape command. */
  5748.         if (c == '?' || c == 'h' || c == 'H') { /* They want help menu. */
  5749.             esc25(1);        /* Show it */
  5750.         c = popuphelp(1);    /* Then get real escape command */
  5751.         }
  5752.         doesc(c);            /* And process it */
  5753.         restore_status_line();    /* Then restore status line */
  5754.     } else {            /* Ordinary character */
  5755.         if (!keylock)        /* If keyboard not locked, */
  5756.           vt100key(c);        /* go process it. */
  5757.     }
  5758.     DosExitCritSec();        /* Let others use runtime library */
  5759.     } /* while (active) */
  5760.  
  5761. #endif /* __32BIT__ */
  5762.  
  5763. #ifdef __32BIT__
  5764.     DosWaitThread(&threadid, 0);
  5765.     debug(F100,"rdcomwrtscr() thread dead","",0) ;
  5766.     DosCloseEventSem(threadsem);
  5767. #else
  5768.     DosSemWait(&threadsem, -1L);/* Wait for other thread to terminate */
  5769. #endif
  5770.  
  5771.     language = langsv;            /* Restore language */
  5772.     concooked();            /* Restore console to "cooked" mode */
  5773.     savescreen(&vt100screen,wherex,wherey);
  5774.     x = cursoron;
  5775.     cursoron = TRUE;            /* Needed for lgotoxy()... */
  5776.     restoreborder();            /* Put back command-screen border */
  5777.     restorescreen(&commandscreen);    /* Put back command screen */
  5778.     restorecursormode();        /* Put command-screen cursor back */
  5779.     cursoron = x;            /* Remember this for next time... */
  5780.     if (termessage[0]!='\0') printf(termessage);
  5781.     if (hangnow) {
  5782. #ifndef NODIAL
  5783.       if (mdmhup() < 1)
  5784. #endif /* NODIAL */
  5785.     tthang();
  5786.     }
  5787.     if (quitnow) 
  5788.       doexit(GOOD_EXIT,0);
  5789.     what = W_NOTHING;
  5790.     return (1);
  5791. }
  5792.