vt100.c
上传用户:tianjinjs
上传日期:2007-01-05
资源大小:309k
文件大小:23k
源码类别:

Modem编程

开发平台:

Unix_Linux

  1. /*
  2.  * vt100.c ANSI/VT102 emulator code.
  3.  * This code was integrated to the Minicom communications
  4.  * package, but has been reworked to allow usage as a separate
  5.  * module.
  6.  *
  7.  * It's not a "real" vt102 emulator - it's more than that:
  8.  * somewhere between vt220 and vt420 in commands.
  9.  *
  10.  * This file is part of the minicom communications package,
  11.  * Copyright 1991-1995 Miquel van Smoorenburg.
  12.  *
  13.  * This program is free software; you can redistribute it and/or
  14.  * modify it under the terms of the GNU General Public License
  15.  * as published by the Free Software Foundation; either version
  16.  * 2 of the License, or (at your option) any later version.
  17.  *
  18.  * // jl 04.09.97 character map conversions in and out
  19.  *    jl 06.07.98 use conversion tables with the capture file
  20.  */
  21. #include "port.h"
  22. #include "window.h"
  23. #include "vt100.h"
  24. #include "config.h"
  25. #include "configsym.h"
  26. #include "patchlevel.h"
  27. #define OLD 0
  28. /*
  29.  * The global variable esc_s holds the escape sequence status:
  30.  * 0 - normal
  31.  * 1 - ESC
  32.  * 2 - ESC [
  33.  * 3 - ESC [ ?
  34.  * 4 - ESC (
  35.  * 5 - ESC )
  36.  * 6 - ESC #
  37.  * 7 - ESC P
  38.  */
  39. static int esc_s = 0;
  40. #define ESC 27
  41. /* Structure to hold escape sequences. */
  42. struct escseq {
  43.   int code;
  44.   char *vt100_st;
  45.   char *vt100_app;
  46.   char *ansi;
  47. };
  48. /* Escape sequences for different terminal types. */
  49. static struct escseq vt_keys[] = {
  50. #ifndef _DGUX_SOURCE
  51.   { K_F1, "OP", "OP", "OP" },
  52.   { K_F2, "OQ", "OQ", "OQ" },
  53.   { K_F3, "OR", "OR", "OR" },
  54.   { K_F4, "OS", "OS", "OS" },
  55.   { K_F5, "[16~", "[16~", "OT" },
  56.   { K_F6, "[17~", "[17~", "OU" },
  57.   { K_F7, "[18~", "[18~", "OV" },
  58.   { K_F8, "[19~", "[19~", "OW" },
  59.   { K_F9, "[20~", "[20~", "OX" },
  60.   { K_F10, "[21~", "[21~", "OY" },
  61.   { K_F11, "[23~", "[23~", "OY" },
  62.   { K_F12, "[24~", "[24~", "OY" },
  63.   { K_HOME, "[1~", "[1~", "[H" },
  64.   { K_PGUP, "[5~", "[5~", "[V" },
  65.   { K_UP, "[A", "OA", "[A" },
  66.   { K_LT, "[D", "OD", "[D" },
  67.   { K_RT, "[C", "OC", "[C" },
  68.   { K_DN, "[B", "OB", "[B" },
  69.   { K_END, "[4~", "[4~", "[Y" },
  70.   { K_PGDN, "[6~", "[6~", "[U" },
  71.   { K_INS, "[2~", "[2~", "[@" },
  72.   { K_DEL, "[3~", "[3~", "177" },
  73.   { 0, NULL, NULL, NULL }
  74. #else
  75.   { K_F1,      "[17~", "[17~", "OP" },
  76.   { K_F2,      "[18~", "[18~", "OQ" },
  77.   { K_F3,      "[19~", "[19~", "OR" },
  78.   { K_F4,      "[20~", "[20~", "OS" },
  79.   { K_F5,      "[21~", "[21~", "OT" },
  80.   { K_F6,      "[23~", "[23~", "OU" },
  81.   { K_F7,      "[24~", "[24~", "OV" },
  82.   { K_F8,      "[25~", "[25~", "OW" },
  83.   { K_F9,      "[26~", "[26~", "OX" },
  84.   { K_F10,     "[28~", "[28~", "OY" },
  85.   { K_F11,     "[29~", "[29~", "OZ" },
  86.   { K_F12,     "[31~", "[31~", "OA" },
  87.   { K_HOME,    "OP",   "OP",   "[H" },
  88.   { K_PGUP,    "OQ",   "OQ",   "[V" },
  89.   { K_UP,      "[A",   "OA",   "[A" },
  90.   { K_LT,      "[D",   "OD",   "[D" },
  91.   { K_RT,      "[C",   "OC",   "[C" },
  92.   { K_DN,      "[B",   "OB",   "[B" },
  93.   { K_END,     "OR",   "OR",   "[Y" },
  94.   { K_PGDN,    "OS",   "OS",   "[U" },
  95.   { K_INS,     "[1~",  "[1~",  "[@"  },
  96.   { K_DEL,     "[3~",  "[3~",  "177" },
  97.   { 0,         NULL,   NULL,   NULL }
  98. #endif
  99. };
  100. /* Two tables for user-defined character map conversions.
  101.  * defmap.h should contain all characters 0-255 in ascending order
  102.  * to default to no conversion.    jl 04.09.1997
  103.  */
  104. unsigned char vt_inmap[256] = {
  105. #include "defmap.h"
  106. };
  107. unsigned char vt_outmap[256] = {
  108. #include "defmap.h"
  109. };
  110. #if TRANSLATE
  111. /* Taken from the Linux kernel source: linux/drivers/char/console.c */
  112. static unsigned char * vt_map[] = {
  113. /* 8-bit Latin-1 mapped to the PC character set: '.' means non-printable */
  114. (unsigned char *)
  115. "................"
  116. "................"
  117. " !"#$%&'()*+,-./0123456789:;<=>?"
  118. "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"
  119. "`abcdefghijklmnopqrstuvwxyz{|}~."
  120. "................"
  121. "................"
  122. "3772552332343762351742537637624625625255376376"
  123. "37036137537637634624371376376247257254253376250"
  124. "376376376376216217222200376220376376376376376376"
  125. "376245376376376376231376350376376376232376376341"
  126. "205240203376204206221207212202210211215241214213"
  127. "376244225242223376224366355227243226201376376230",
  128. /* vt100 graphics */
  129. (unsigned char *)
  130. "................"
  131. "376"
  132. " !"#$%&'()*+,-./0123456789:;<=>?"
  133. "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ "
  134. "04261070707073703610707331277332300305304"
  135. "30430413713730326430130226336336234333023407"
  136. "................"
  137. "................"
  138. "3772552332343762351742537637624625625255376376"
  139. "37036137537637634624371376376247257254253376250"
  140. "376376376376216217222200376220376376376376376376"
  141. "376245376376376376231376376376376376232376376341"
  142. "205240203376204206221207212202210211215241214213"
  143. "376244225242223376224366376227243226201376376230"
  144. };
  145. static char *vt_trans[2];
  146. static int vt_charset = 0; /* Character set. */
  147. #endif
  148. #ifdef _SELECT
  149. static int vt_echo; /* Local echo on/off. */
  150. #endif
  151. int vt_nl_delay; /* Delay after CR key */
  152. static int vt_type   = ANSI; /* Terminal type. */
  153. static int vt_wrap   = 0; /* Line wrap on/off */
  154. static int vt_addlf  = 0; /* Add linefeed on/off */
  155. static int vt_fg; /* Standard foreground color. */
  156. static int vt_bg; /* Standard background color. */
  157. static int vt_keypad; /* Keypad mode. */
  158. static int vt_cursor; /* cursor key mode. */
  159. static int vt_asis = 0; /* 8bit clean mode. */
  160. static int vt_bs = 8; /* Code that backspace key sends. */
  161. static int vt_insert = 0; /* Insert mode */
  162. static int vt_crlf = 0; /* Return sends CR/LF */
  163. static int vt_om; /* Origin mode. */
  164. WIN *vt_win          = NIL_WIN; /* Output window. */
  165. static int vt_docap; /* Capture on/off. */
  166. static FILE *vt_capfp; /* Capture file. */
  167. static void (*vt_keyb)(); /* Gets called for NORMAL/APPL switch. */
  168. static void (*termout)(); /* Gets called to output a string. */
  169. static int escparms[8]; /* Cumulated escape sequence. */
  170. #if OLD
  171. static int ptr = -2; /* Index into escparms array. */
  172. #else
  173. static int ptr = 0; /* Index into escparms array. */
  174. #endif
  175. static long vt_tabs[5]; /* Tab stops for max. 32*5 = 160 columns. */
  176. short newy1 = 0; /* Current size of scrolling region. */
  177. short newy2 = 23;
  178. /* Saved color and posistions */
  179. static short savex = 0, savey = 0, saveattr = XA_NORMAL, savecol = 112;
  180. #if TRANSLATE
  181. static short savecharset;
  182. static char *savetrans[2];
  183. #endif
  184. /*
  185.  * Initialize the emulator once.
  186.  */
  187. void vt_install(fun1, fun2, win)
  188. void (*fun1)();
  189. void (*fun2)();
  190. WIN *win;
  191. {
  192.   termout = fun1;
  193.   vt_keyb = fun2;
  194.   vt_win = win;
  195. }
  196. /* Partial init (after screen resize) */
  197. void vt_pinit(win, fg, bg)
  198. WIN *win;
  199. int fg, bg;
  200. {
  201.   vt_win = win;
  202.   newy1 = 0;
  203.   newy2 = vt_win->ys - 1;
  204.   wresetregion(vt_win);
  205.   if (fg > 0) vt_fg = fg;
  206.   if (bg > 0) vt_bg = bg;
  207.   wsetfgcol(vt_win, vt_fg);
  208.   wsetbgcol(vt_win, vt_bg);
  209. }
  210. /* Set characteristics of emulator. */
  211. void vt_init(type, fg, bg, wrap, add)
  212. int type;
  213. int fg;
  214. int bg;
  215. int wrap;
  216. int add;
  217. {
  218.   vt_type = type;
  219.   if (vt_type == ANSI) {
  220. vt_fg = WHITE;
  221. vt_bg = BLACK;
  222.   } else {
  223. vt_fg = fg;
  224. vt_bg = bg;
  225.   }
  226.   if (wrap >= 0) vt_win->wrap = vt_wrap = wrap;
  227.   vt_addlf = add;
  228.   vt_insert = 0;
  229.   vt_crlf = 0;
  230.   vt_om = 0;
  231.   newy1 = 0;
  232.   newy2 = vt_win->ys - 1;
  233.   wresetregion(vt_win);
  234.   vt_keypad = NORMAL;
  235.   vt_cursor = NORMAL;
  236. #ifdef _SELECT
  237.   vt_echo = 0;
  238. #endif
  239.   vt_tabs[0] = 0x01010100;
  240.   vt_tabs[1] =
  241.   vt_tabs[2] =
  242.   vt_tabs[3] =
  243.   vt_tabs[4] = 0x01010101;
  244. #if TRANSLATE
  245.   vt_charset = 0;
  246.   vt_trans[0] = vt_map[0];
  247.   vt_trans[1] = vt_map[1];
  248. #endif
  249. #if OLD
  250.   ptr = -2;
  251. #else
  252.   ptr = 0;
  253.   memset(escparms, 0, sizeof(escparms));
  254. #endif
  255.   esc_s = 0;
  256.   if (vt_keyb) (*vt_keyb)(vt_keypad, vt_cursor);
  257.   wsetfgcol(vt_win, vt_fg);
  258.   wsetbgcol(vt_win, vt_bg);
  259. }
  260. /* Change some things on the fly. */
  261. void vt_set(addlf, wrap, capfp, docap, bscode, echo, cursor, asis)
  262. int addlf;
  263. int wrap;
  264. FILE *capfp;
  265. int docap;
  266. int bscode;
  267. int echo;
  268. int cursor;
  269. int asis;
  270. {
  271.   if (addlf >= 0) vt_addlf = addlf;
  272.   if (wrap >= 0)  vt_win->wrap = vt_wrap = wrap;
  273.   if (capfp != (FILE *)0) vt_capfp = capfp;
  274.   if (docap >= 0) vt_docap = docap;
  275.   if (bscode >= 0) vt_bs = bscode;
  276. #ifdef _SELECT
  277.   if (echo >= 0) vt_echo = echo;
  278. #endif
  279.   if (cursor >= 0) vt_cursor = cursor;
  280.   if (asis >=0) vt_asis = asis;
  281. }
  282. /* Output a string to the modem. */
  283. static void v_termout(s, len)
  284. char *s;
  285. int len;
  286. {
  287. #ifdef _SELECT
  288.   char *p;
  289.   if (vt_echo) {
  290. for(p = s; *p; p++) {
  291. vt_out(*p);
  292. if (!vt_addlf && *p == 'r') vt_out('n');
  293. }
  294. wflush();
  295.   }
  296. #endif
  297.   (*termout)(s, len);
  298. }
  299. /*
  300.  * Escape code handling.
  301.  */
  302. /*
  303.  * ESC was seen the last time. Process the next character.
  304.  */
  305. static void state1(c)
  306. int c;
  307. {
  308.   short x, y, f;
  309.   switch(c) {
  310. case '[': /* ESC [ */
  311. esc_s = 2;
  312. return;
  313. case '(': /* ESC ( */
  314. esc_s = 4;
  315. return;
  316. case ')': /* ESC ) */
  317. esc_s = 5;
  318. return;
  319. case '#': /* ESC # */
  320. esc_s = 6;
  321. return;
  322. case 'P': /* ESC P (DCS, Device Control String) */
  323. esc_s = 7;
  324. return;
  325. case 'D': /* Cursor down */
  326. case 'M': /* Cursor up */
  327. x = vt_win->curx;
  328. if (c == 'D')  { /* Down. */
  329. y = vt_win->cury + 1;
  330. if (y == newy2 + 1)
  331. wscroll(vt_win, S_UP);
  332. else if (vt_win->cury < vt_win->ys)
  333. wlocate(vt_win, x, y);
  334. }
  335. if (c == 'M')  { /* Up. */
  336. y = vt_win->cury - 1;
  337. if (y == newy1 - 1)
  338. wscroll(vt_win, S_DOWN);
  339. else if (y >= 0)
  340. wlocate(vt_win, x, y);
  341. }
  342. break;
  343. case 'E': /* CR + NL */
  344.   wputs(vt_win, "rn");
  345.   break;
  346.   case '7': /* Save attributes and cursor position */
  347.   case 's':
  348.   savex = vt_win->curx;
  349.   savey = vt_win->cury;
  350.   saveattr = vt_win->attr;
  351.   savecol = vt_win->color;
  352. #if TRANSLATE
  353. savecharset = vt_charset;
  354. savetrans[0] = vt_trans[0];
  355. savetrans[1] = vt_trans[1];
  356. #endif
  357.   break;
  358.   case '8': /* Restore them */
  359.   case 'u':
  360. #if TRANSLATE
  361. vt_charset = savecharset;
  362. vt_trans[0] = savetrans[0];
  363. vt_trans[1] = savetrans[1];
  364. #endif
  365.   vt_win->color = savecol; /* HACK should use wsetfgcol etc */
  366.   wsetattr(vt_win, saveattr);
  367.   wlocate(vt_win, savex, savey);
  368.   break;
  369.   case '=': /* Keypad into applications mode */
  370. vt_keypad = APPL;
  371. if (vt_keyb) (*vt_keyb)(vt_keypad, vt_cursor);
  372.   break;
  373.   case '>': /* Keypad into numeric mode */
  374.   vt_keypad = NORMAL;
  375. if (vt_keyb) (*vt_keyb)(vt_keypad, vt_cursor);
  376.   break;
  377.   case 'Z': /* Report terminal type */
  378. if (vt_type == VT100)
  379. v_termout("33[?1;0c", 0);
  380.   else
  381.   v_termout("33[?c", 0);
  382.   break;
  383.   case 'c': /* Reset to initial state */
  384.   f = XA_NORMAL;
  385.   wsetattr(vt_win, f);
  386. vt_win->wrap = (vt_type != VT100);
  387. if (vt_wrap != -1) vt_win->wrap = vt_wrap;
  388. vt_crlf = vt_insert = 0;
  389. vt_init(vt_type, vt_fg, vt_bg, vt_win->wrap, 0);
  390.   wlocate(vt_win, 0, 0);
  391.   break;
  392.   case 'H': /* Set tab in current position */
  393. x = vt_win->curx;
  394. if (x > 159) x = 159;
  395. vt_tabs[x / 32] |= 1 << (x % 32);
  396. break;
  397.   case 'N': /* G2 character set for next character only*/
  398.   case 'O': /* G3 " "    */
  399.   case '<': /* Exit vt52 mode */
  400.   default:
  401.   /* ALL IGNORED */
  402.   break;
  403.   }
  404.   esc_s = 0;
  405.   return;
  406. }
  407. /* ESC [ ... [hl] seen. */
  408. static void ansi_mode(on_off)
  409. int on_off;
  410. {
  411.   int i;
  412.   for(i = 0; i <= ptr; i++) {
  413. switch(escparms[i]) {
  414. case 4: /* Insert mode  */
  415. vt_insert = on_off;
  416. break;
  417. case 20: /* Return key mode */
  418. vt_crlf = on_off;
  419. break;
  420. }
  421.   }
  422. }
  423. /*
  424.  * ESC [ ... was seen the last time. Process next character.
  425.  */
  426. static void state2(c)
  427. int c;
  428. {
  429.   short x, y, attr, f;
  430.   char temp[32];
  431.   /* See if a number follows */
  432.   if (c >= '0' && c <= '9') {
  433. #if OLD
  434. if (ptr < 0) ptr = 0;
  435. #endif
  436. escparms[ptr] = 10*(escparms[ptr]) + c - '0';
  437. return;
  438.   }
  439.   /* Separation between numbers ? */
  440.   if (c == ';') {
  441. #if OLD
  442. if (ptr < 0) ptr = 0; /* keithr@primenet.com */
  443. if (ptr >= 0 && ptr < 15) ptr++;
  444. #else
  445. if (ptr < 15) ptr++;
  446. #endif
  447. return;
  448.   }
  449.   /* ESC [ ? sequence */
  450. #if OLD
  451.   if (ptr < 0 && c == '?') {
  452. #else
  453.   if (escparms[0] == 0 && ptr == 0 && c == '?') {
  454. #endif
  455. esc_s = 3;
  456. return;
  457.   }
  458.   /* Process functions with zero, one, two or more arguments */
  459.   switch(c) {
  460. case 'A':
  461. case 'B':
  462. case 'C':
  463. case 'D': /* Cursor motion */
  464. if ((f = escparms[0]) == 0) f = 1;
  465. x = vt_win->curx;
  466. y = vt_win->cury;
  467. x += f * ((c == 'C') - (c == 'D'));
  468. if (x < 0) x = 0;
  469. if (x >= vt_win->xs) x = vt_win->xs - 1;
  470. if (c == 'B') { /* Down. */
  471. y += f;
  472. if (y >= vt_win->ys) y = vt_win->ys - 1;
  473. if (y >= newy2 + 1) y = newy2;
  474. }
  475. if (c == 'A') { /* Up. */
  476. y -= f;
  477.   if (y < 0) y = 0;
  478. if (y <= newy1 - 1) y = newy1;
  479. }
  480. wlocate(vt_win, x, y);
  481. break;
  482. case 'K': /* Line erasing */
  483. switch(escparms[0]) {
  484. case 0:
  485. wclreol(vt_win);
  486. break;
  487. case 1:
  488. wclrbol(vt_win);
  489. break;
  490. case 2:
  491. wclrel(vt_win);
  492. break;
  493. }
  494. break;
  495. case 'J': /* Screen erasing */
  496. x = vt_win->color;
  497. y = vt_win->attr;
  498. if (vt_type == ANSI) {
  499. wsetattr(vt_win, XA_NORMAL);
  500. wsetfgcol(vt_win, WHITE);
  501. wsetbgcol(vt_win, BLACK);
  502. }
  503. switch(escparms[0]) {
  504. case 0:
  505. wclreos(vt_win);
  506. break;
  507. case 1:
  508. wclrbos(vt_win);
  509. break;
  510. case 2:
  511. winclr(vt_win);
  512. break;
  513. }
  514. if (vt_type == ANSI) {
  515. vt_win->color = x;
  516. vt_win->attr = y;
  517. }
  518. break;
  519. case 'n': /* Requests / Reports */
  520. switch(escparms[0]) {
  521. case 5: /* Status */
  522. v_termout("33[0n", 0);
  523. break;
  524. case 6: /* Cursor Position */
  525. sprintf(temp, "33[%d;%dR", 
  526. vt_win->cury + 1, vt_win->curx + 1);
  527. v_termout(temp, 0);
  528. break;
  529. }
  530. break;
  531. case 'c': /* Identify Terminal Type */
  532. if (vt_type == VT100) {
  533. v_termout("33[?1;2c", 0);
  534. break;
  535. }
  536. v_termout("33[?c", 0);
  537. break;
  538. case 'x': /* Request terminal parameters. */
  539.   /* Always answers 19200-8N1 no options. */
  540. sprintf(temp, "33[%c;1;1;120;120;1;0x",
  541. escparms[0] == 1 ? '3' : '2');
  542. v_termout(temp, 0);
  543. break;
  544.   case 's': /* Save attributes and cursor position */
  545.   savex = vt_win->curx;
  546.   savey = vt_win->cury;
  547.   saveattr = vt_win->attr;
  548.   savecol = vt_win->color;
  549. #if TRANSLATE
  550. savecharset = vt_charset;
  551. savetrans[0] = vt_trans[0];
  552. savetrans[1] = vt_trans[1];
  553. #endif
  554.   break;
  555.   case 'u': /* Restore them */
  556. #if TRANSLATE
  557. vt_charset = savecharset;
  558. vt_trans[0] = savetrans[0];
  559. vt_trans[1] = savetrans[1];
  560. #endif
  561.   break;
  562.   vt_win->color = savecol; /* HACK should use wsetfgcol etc */
  563.   wsetattr(vt_win, saveattr);
  564.   wlocate(vt_win, savex, savey);
  565.   break;
  566. case 'h':
  567. ansi_mode(1);
  568. break;
  569. case 'l':
  570. ansi_mode(0);
  571. break;
  572. case 'H':
  573. case 'f': /* Set cursor position */
  574. if ((y = escparms[0]) == 0) y = 1;
  575. if ((x = escparms[1]) == 0) x = 1;
  576. if (vt_om) y += newy1;
  577. wlocate(vt_win, x - 1, y - 1);
  578. break;
  579. case 'g': /* Clear tab stop(s) */
  580. if (escparms[0] == 0) {
  581. x = vt_win->curx;
  582. if (x > 159) x = 159;
  583. vt_tabs[x / 32] &= ~ (1 << x % 32);
  584. }
  585. if (escparms[0] == 3)
  586. for(x = 0; x < 5; x++) vt_tabs[x] = 0;
  587. break;
  588. case 'm': /* Set attributes */
  589. #if OLD
  590.   /* Without argument, esc-parms[0] is 0 */
  591. if (ptr < 0) ptr = 0;  
  592. #endif
  593. attr = wgetattr((vt_win));
  594. for (f = 0; f <= ptr; f++) {
  595.     if (escparms[f] >= 30 && escparms[f] <= 37)
  596. wsetfgcol(vt_win, escparms[f] - 30);
  597.     if (escparms[f] >= 40 && escparms[f] <= 47)
  598. wsetbgcol(vt_win, escparms[f] - 40);
  599.     switch(escparms[f]) {
  600. case 0:
  601. attr = XA_NORMAL;
  602. wsetfgcol(vt_win, vt_fg);
  603. wsetbgcol(vt_win, vt_bg);
  604. break;
  605. case 4:
  606. attr |= XA_UNDERLINE;
  607. break;
  608. case 7:
  609. attr |= XA_REVERSE;
  610. break;
  611. case 1:
  612. attr |= XA_BOLD;
  613. break;
  614. case 5:
  615. attr |= XA_BLINK;
  616. break;
  617. case 22: /* Bold off */
  618. attr &= ~XA_BOLD;
  619. break;
  620. case 24: /* Not underlined */
  621. attr &=~XA_UNDERLINE;
  622. break;
  623. case 25: /* Not blinking */
  624. attr &= ~XA_BLINK;
  625. break;
  626. case 27: /* Not reverse */
  627. attr &= ~XA_REVERSE;
  628. break;
  629. case 39: /* Default fg color */
  630. wsetfgcol(vt_win, vt_fg);
  631. break;
  632. case 49: /* Default bg color */
  633. wsetbgcol(vt_win, vt_bg);
  634. break;
  635.     }
  636. }
  637. wsetattr(vt_win, attr);
  638. break;
  639. case 'L': /* Insert lines */
  640. if ((x = escparms[0]) == 0) x = 1;
  641. for(f = 0; f < x; f++)
  642. winsline(vt_win);
  643. break;
  644. case 'M': /* Delete lines */
  645. if ((x = escparms[0]) == 0) x = 1;
  646. for(f = 0; f < x; f++)
  647. wdelline(vt_win);
  648. break;
  649. case 'P': /* Delete Characters */
  650. if ((x = escparms[0]) == 0) x = 1;
  651. for(f = 0; f < x; f++)
  652. wdelchar(vt_win);
  653. break;
  654. case '@': /* Insert Characters */
  655. if ((x = escparms[0]) == 0) x = 1;
  656. for(f = 0; f < x; f++)
  657. winschar(vt_win);
  658. break;
  659. case 'r': /* Set scroll region */
  660. if ((newy1 = escparms[0]) == 0) newy1 = 1;
  661. if ((newy2 = escparms[1]) == 0) newy2 = vt_win->ys;
  662. newy1-- ; newy2--;
  663. if (newy1 < 0) newy1 = 0;
  664. if (newy2 < 0) newy2 = 0;
  665. if (newy1 >= vt_win->ys) newy1 = vt_win->ys - 1;
  666. if (newy2 >= vt_win->ys) newy2 = vt_win->ys - 1;
  667. if (newy1 >= newy2) {
  668. newy1 = 0;
  669. newy2 = vt_win->ys - 1;
  670. }
  671. wsetregion(vt_win, newy1, newy2);
  672. wlocate(vt_win, 0, newy1);
  673. break;
  674. case 'i': /* Printing */
  675. case 'y': /* Self test modes */
  676. default:
  677. /* IGNORED */
  678. break;
  679.   }
  680.   /* Ok, our escape sequence is all done */
  681.   esc_s = 0;
  682. #if OLD
  683.   ptr = -2;
  684. #else
  685.   ptr = 0;
  686.   memset(escparms, 0, sizeof(escparms));
  687. #endif
  688.   return;
  689. }
  690.   
  691. /* ESC [? ... [hl] seen. */
  692. static void dec_mode(on_off)
  693. int on_off;
  694. {
  695.   int i;
  696.   for(i = 0; i <= ptr; i++) {
  697. switch(escparms[i]) {
  698. case 1: /* Cursor keys in cursor/appl mode */
  699. vt_cursor = on_off ? APPL : NORMAL;
  700. if (vt_keyb) (*vt_keyb)(vt_keypad, vt_cursor);
  701. break;
  702. case 6: /* Origin mode. */
  703. vt_om = on_off;
  704. wlocate(vt_win, 0, newy1);
  705. break;
  706. case 7: /* Auto wrap */
  707. vt_win->wrap = on_off;
  708. break;
  709. case 25: /* Cursor on/off */
  710. wcursor(vt_win, on_off ? CNORMAL : CNONE);
  711. break;
  712. case 67: /* Backspace key sends. (FIXME: vt420) */
  713. /* setbackspace(on_off ? 8 : 127); */
  714. break;
  715. default: /* Mostly set up functions */
  716. /* IGNORED */
  717. break;
  718. }
  719.   }
  720. }
  721. /*
  722.  * ESC [ ? ... seen.
  723.  */
  724. static void state3(c)
  725. int c;
  726. {
  727.   /* See if a number follows */
  728.   if (c >= '0' && c <= '9') {
  729. #if OLD
  730. if (ptr < 0) ptr = 0;
  731. #endif
  732. escparms[ptr] = 10*(escparms[ptr]) + c - '0';
  733. return;
  734.   }
  735. #if OLD
  736.   /* ESC [ ? number seen */
  737.   if (ptr < 0) {
  738. esc_s = 0;
  739. return;
  740.   }
  741. #endif
  742.   switch(c) {
  743. case 'h':
  744. dec_mode(1);
  745. break;
  746. case 'l':
  747. dec_mode(0);
  748. break;
  749. case 'i': /* Printing */
  750. case 'n': /* Request printer status */
  751. default:
  752. /* IGNORED */
  753. break;
  754.   }
  755.   esc_s = 0;
  756. #if OLD
  757.   ptr = -2;
  758. #else
  759.   ptr = 0;
  760.   memset(escparms, 0, sizeof(escparms));
  761. #endif
  762.   return;
  763. }
  764. /*
  765.  * ESC ( Seen.
  766.  */
  767. /*ARGSUSED*/
  768. static void state4(c)
  769. int c;
  770. {
  771.   /* Switch Character Sets. */
  772. #if !TRANSLATE
  773.   /* IGNORED */
  774.   (void)c;
  775. #else
  776.   switch(c) {
  777. case 'A':
  778. case 'B':
  779. vt_trans[0] = vt_map[0];
  780. break;
  781. case '0':
  782. case 'O':
  783. vt_trans[0] = vt_map[1];
  784. break;
  785.   }
  786. #endif
  787.   esc_s = 0;
  788. }
  789. /*
  790.  * ESC ) Seen.
  791.  */
  792. /*ARGSUSED*/
  793. static void state5(c)
  794. int c;
  795. {
  796.   /* Switch Character Sets. */
  797. #if !TRANSLATE
  798.   /* IGNORED */
  799.   (void)c;
  800. #else
  801.   switch(c) {
  802. case 'A':
  803. case 'B':
  804. vt_trans[1] = vt_map[0];
  805. break;
  806. case 'O':
  807. case '0':
  808. vt_trans[1] = vt_map[1];
  809. break;
  810.   }
  811. #endif
  812.   esc_s = 0;
  813. }
  814. /*
  815.  * ESC # Seen.
  816.  */
  817. /*ARGSUSED*/
  818. static void state6(c)
  819. int c;
  820. {
  821.   int x, y;
  822.   /* Double height, double width and selftests. */
  823.   switch(c) {
  824. case '8':
  825. /* Selftest: fill screen with E's */
  826. vt_win->doscroll = 0;
  827. vt_win->direct = 0;
  828. wlocate(vt_win, 0, 0);
  829. for(y = 0; y < vt_win->ys; y++) {
  830. wlocate(vt_win, 0, y);
  831. for(x = 0; x < vt_win->xs; x++)
  832. wputc(vt_win, 'E');
  833. }
  834. wlocate(vt_win, 0, 0);
  835. vt_win->doscroll = 1;
  836. wredraw(vt_win, 1);
  837. break;
  838. default:
  839. /* IGNORED */
  840. break;
  841.   }
  842.   esc_s = 0;
  843. }
  844. /*
  845.  * ESC P Seen.
  846.  */
  847. static void state7(c)
  848. int c;
  849. {
  850.   /*
  851.    * Device dependant control strings. The Minix virtual console package
  852.    * uses these sequences. We can only turn cursor on or off, because
  853.    * that's the only one supported in termcap. The rest is ignored.
  854.    */
  855.   static char buf[17];
  856.   static int pos = 0;
  857.   static int state = 0;
  858.   if (c == ESC) {
  859.    state = 1;
  860.    return;
  861.   }
  862.   if (state == 1) {
  863.    buf[pos] = 0;
  864.    pos = 0;
  865.    state = 0;
  866.    esc_s = 0;
  867.    if (c != '\') return;
  868.    /* Process string here! */
  869.    if (!strcmp(buf, "cursor.on")) wcursor(vt_win, CNORMAL);
  870.    if (!strcmp(buf, "cursor.off")) wcursor(vt_win, CNONE);
  871.    if (!strcmp(buf, "linewrap.on")) {
  872.    vt_wrap = -1;
  873.    vt_win->wrap = 1;
  874.    }
  875.    if (!strcmp(buf, "linewrap.off")) {
  876.    vt_wrap = -1;
  877.    vt_win->wrap = 0;
  878.    }
  879.    return;
  880.   }
  881.   if (pos > 15) return;
  882.   buf[pos++] = c;
  883. }
  884. void vt_out(ch)
  885. int ch;
  886. {
  887.   int f;
  888.   unsigned char c;
  889.   int go_on = 0;
  890.   if (!ch) return;
  891. #if OLD
  892.   if (ptr == -2) { /* Initialize */
  893. ptr = -1;
  894. for(f = 0; f < 8; f++) escparms[f] = 0;
  895.   }
  896. #endif
  897.   c = (unsigned char)ch;
  898.   
  899.   if (vt_docap == 2) /* Literal. */
  900. fputc(c, vt_capfp);
  901.   /* Process <31 chars first, even in an escape sequence. */
  902.   switch(c) {
  903. case 5: /* AnswerBack for vt100's */
  904. if (vt_type != VT100) {
  905. go_on = 1;
  906. break;
  907. }
  908. v_termout(SCCS_ID, 0);
  909. break;
  910. case 'r': /* Carriage return */
  911. wputc(vt_win, c);
  912. if (vt_addlf) {
  913. wputc(vt_win, 'n');
  914. if (vt_docap == 1)
  915. fputc('n', vt_capfp);
  916. }
  917. break;
  918. case 't': /* Non - destructive TAB */
  919. /* Find next tab stop. */
  920. for(f = vt_win->curx + 1; f < 160; f++)
  921. if (vt_tabs[f / 32] & (1 << f % 32)) break;
  922. if (f >= vt_win->xs) f = vt_win->xs - 1;
  923. wlocate(vt_win, f, vt_win->cury);
  924. if (vt_docap == 1) fputc(c, vt_capfp);
  925. break;
  926. case 013: /* Old Minix: CTRL-K = up */
  927. wlocate(vt_win, vt_win->curx, vt_win->cury - 1);
  928. break;
  929. case 'f': /* Form feed: clear screen. */
  930. winclr(vt_win);
  931. wlocate(vt_win, 0, 0);
  932. break;
  933. #if !TRANSLATE
  934. case 14:
  935. case 15:  /* Change character set. Not supported. */
  936. break;
  937. #else
  938. case 14:
  939. vt_charset = 1;
  940. break;
  941. case 15:
  942. vt_charset = 0;
  943. break;
  944. #endif
  945. case 24:
  946. case 26:  /* Cancel escape sequence. */
  947. esc_s = 0;
  948. break;
  949. case ESC: /* Begin escape sequence */
  950. esc_s = 1;
  951. break;
  952. case 128+ESC: /* Begin ESC [ sequence. */
  953. esc_s = 2;
  954. break;
  955. case 'n':
  956. case 'b':
  957. case 7: /* Bell */
  958. wputc(vt_win, c);
  959. if (vt_docap == 1)
  960. fputc(c, vt_capfp);
  961. break;
  962. default:
  963. go_on = 1;
  964. break;
  965.   }
  966.   if (!go_on) return;
  967.   /* Now see which state we are in. */
  968.   switch(esc_s) {
  969. case 0: /* Normal character */
  970. if (vt_docap == 1)
  971. fputc(P_CONVCAP[0]=='Y'? vt_inmap[c]: c, vt_capfp);
  972.         c = vt_inmap[c];    /* conversion 04.09.97 / jl */
  973. #if TRANSLATE
  974. if (vt_type == VT100 && vt_asis == 0) {
  975. if (vt_insert)
  976. winschar2(vt_win, vt_trans[vt_charset][c], 1);
  977. else
  978. wputc(vt_win, vt_trans[vt_charset][c]);
  979. } else {
  980. #endif
  981. if (vt_insert)
  982. winschar2(vt_win, c, 1);
  983. else
  984. wputc(vt_win, c);
  985. #if TRANSLATE
  986. }
  987. #endif
  988. break;
  989. case 1: /* ESC seen */
  990. state1(c);
  991. break;
  992. case 2: /* ESC [ ... seen */
  993. state2(c);
  994. break;
  995. case 3:
  996. state3(c);
  997. break;
  998. case 4:
  999. state4(c);
  1000. break;
  1001. case 5:
  1002. state5(c);
  1003. break;
  1004. case 6:
  1005. state6(c);
  1006. break;
  1007. case 7:
  1008. state7(c);
  1009. break;
  1010.   }
  1011. }
  1012. /* Translate keycode to escape sequence. */
  1013. void vt_send(c)
  1014. int c;
  1015. {
  1016.   char s[3];
  1017.   int f;
  1018.   int len = 1;
  1019.   /* Special key? */
  1020.   if (c < 256) {
  1021. /* Translate backspace key? */
  1022. if (c == K_ERA) c = vt_bs;
  1023. s[0] = vt_outmap[(unsigned char) c];  /* conversion 04.09.97 / jl */
  1024. s[1] = 0;
  1025. /* CR/LF mode? */
  1026. if (c == 'r' && vt_crlf) {
  1027. s[1] = 'n';
  1028. s[2] = 0;
  1029. len = 2;
  1030. }
  1031. v_termout(s, len);
  1032. if (vt_nl_delay > 0 && c == 'r')
  1033. usleep(1000 * vt_nl_delay);
  1034. return;
  1035.   }
  1036.   /* Look up code in translation table. */
  1037.   for(f = 0; vt_keys[f].code; f++)
  1038. if (vt_keys[f].code == c) break;
  1039.   if (vt_keys[f].code == 0) return;
  1040.   /* Now send appropriate escape code. */
  1041.   v_termout("33", 0);
  1042.   if (vt_type == VT100) {
  1043. if (vt_cursor == NORMAL)
  1044. v_termout(vt_keys[f].vt100_st, 0);
  1045. else
  1046. v_termout(vt_keys[f].vt100_app, 0);
  1047.   } else
  1048. v_termout(vt_keys[f].ansi, 0);
  1049. }