/* * vt100.c ANSI/VT102 emulator code. * This code was integrated to the Minicom communications * package, but has been reworked to allow usage as a separate * module. * * It's not a "real" vt102 emulator - it's more than that: * somewhere between vt220 and vt420 in commands. * * This file is part of the minicom communications package, * Copyright 1991-1995 Miquel van Smoorenburg. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * // jl 04.09.97 character map conversions in and out * jl 06.07.98 use conversion tables with the capture file */ #ifdef HAVE_CONFIG_H #include #endif #include "rcsid.h" RCSID("$Id: vt100.c,v 1.2 2003/04/04 20:23:47 al-guest Exp $") #include "port.h" #include "window.h" #include "vt100.h" #include "config.h" #include "configsym.h" #define OLD 0 /* * The global variable esc_s holds the escape sequence status: * 0 - normal * 1 - ESC * 2 - ESC [ * 3 - ESC [ ? * 4 - ESC ( * 5 - ESC ) * 6 - ESC # * 7 - ESC P */ static int esc_s = 0; #define ESC 27 /* Structure to hold escape sequences. */ struct escseq { int code; char *vt100_st; char *vt100_app; char *ansi; }; /* Escape sequences for different terminal types. */ static struct escseq vt_keys[] = { #ifndef _DGUX_SOURCE { K_F1, "OP", "OP", "OP" }, { K_F2, "OQ", "OQ", "OQ" }, { K_F3, "OR", "OR", "OR" }, { K_F4, "OS", "OS", "OS" }, { K_F5, "[16~", "[16~", "OT" }, { K_F6, "[17~", "[17~", "OU" }, { K_F7, "[18~", "[18~", "OV" }, { K_F8, "[19~", "[19~", "OW" }, { K_F9, "[20~", "[20~", "OX" }, { K_F10, "[21~", "[21~", "OY" }, { K_F11, "[23~", "[23~", "OY" }, { K_F12, "[24~", "[24~", "OY" }, { K_HOME, "[1~", "[1~", "[H" }, { K_PGUP, "[5~", "[5~", "[V" }, { K_UP, "[A", "OA", "[A" }, { K_LT, "[D", "OD", "[D" }, { K_RT, "[C", "OC", "[C" }, { K_DN, "[B", "OB", "[B" }, { K_END, "[4~", "[4~", "[Y" }, { K_PGDN, "[6~", "[6~", "[U" }, { K_INS, "[2~", "[2~", "[@" }, { K_DEL, "[3~", "[3~", "\177" }, { 0, NULL, NULL, NULL } #else { K_F1, "[17~", "[17~", "OP" }, { K_F2, "[18~", "[18~", "OQ" }, { K_F3, "[19~", "[19~", "OR" }, { K_F4, "[20~", "[20~", "OS" }, { K_F5, "[21~", "[21~", "OT" }, { K_F6, "[23~", "[23~", "OU" }, { K_F7, "[24~", "[24~", "OV" }, { K_F8, "[25~", "[25~", "OW" }, { K_F9, "[26~", "[26~", "OX" }, { K_F10, "[28~", "[28~", "OY" }, { K_F11, "[29~", "[29~", "OZ" }, { K_F12, "[31~", "[31~", "OA" }, { K_HOME, "OP", "OP", "[H" }, { K_PGUP, "OQ", "OQ", "[V" }, { K_UP, "[A", "OA", "[A" }, { K_LT, "[D", "OD", "[D" }, { K_RT, "[C", "OC", "[C" }, { K_DN, "[B", "OB", "[B" }, { K_END, "OR", "OR", "[Y" }, { K_PGDN, "OS", "OS", "[U" }, { K_INS, "[1~", "[1~", "[@" }, { K_DEL, "[3~", "[3~", "\177" }, { 0, NULL, NULL, NULL } #endif }; /* Two tables for user-defined character map conversions. * defmap.h should contain all characters 0-255 in ascending order * to default to no conversion. jl 04.09.1997 */ unsigned char vt_inmap[256] = { #include "defmap.h" }; unsigned char vt_outmap[256] = { #include "defmap.h" }; #if TRANSLATE /* Taken from the Linux kernel source: linux/drivers/char/console.c */ static unsigned char * vt_map[] = { /* 8-bit Latin-1 mapped to the PC character set: '.' means non-printable */ (unsigned char *) "................" "................" " !\"#$%&'()*+,-./0123456789:;<=>?" "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_" "`abcdefghijklmnopqrstuvwxyz{|}~." "................" "................" "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376" "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250" "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376" "\376\245\376\376\376\376\231\376\350\376\376\376\232\376\376\341" "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213" "\376\244\225\242\223\376\224\366\355\227\243\226\201\376\376\230", /* vt100 graphics */ (unsigned char *) "................" "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0" " !\"#$%&'()*+,-./0123456789:;<=>?" "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ " "\004\261\007\007\007\007\370\361\007\007\331\277\332\300\305\304" "\304\304\137\137\303\264\301\302\263\363\362\343\330\234\007\0" "................" "................" "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376" "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250" "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376" "\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341" "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213" "\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230" }; static char *vt_trans[2]; static int vt_charset = 0; /* Character set. */ #endif #ifdef HAVE_SELECT static int vt_echo; /* Local echo on/off. */ #endif int vt_nl_delay; /* Delay after CR key */ static int vt_type = ANSI; /* Terminal type. */ static int vt_wrap = 0; /* Line wrap on/off */ static int vt_addlf = 0; /* Add linefeed on/off */ static int vt_fg; /* Standard foreground color. */ static int vt_bg; /* Standard background color. */ static int vt_keypad; /* Keypad mode. */ static int vt_cursor; /* cursor key mode. */ static int vt_asis = 0; /* 8bit clean mode. */ static int vt_bs = 8; /* Code that backspace key sends. */ static int vt_insert = 0; /* Insert mode */ static int vt_crlf = 0; /* Return sends CR/LF */ static int vt_om; /* Origin mode. */ WIN *vt_win = NIL_WIN; /* Output window. */ static int vt_docap; /* Capture on/off. */ static FILE *vt_capfp; /* Capture file. */ static void (*vt_keyb)(); /* Gets called for NORMAL/APPL switch. */ static void (*termout)(); /* Gets called to output a string. */ static int escparms[8]; /* Cumulated escape sequence. */ #if OLD static int ptr = -2; /* Index into escparms array. */ #else static int ptr = 0; /* Index into escparms array. */ #endif static long vt_tabs[5]; /* Tab stops for max. 32*5 = 160 columns. */ short newy1 = 0; /* Current size of scrolling region. */ short newy2 = 23; /* Saved color and posistions */ static short savex = 0, savey = 0, saveattr = XA_NORMAL, savecol = 112; #if TRANSLATE static short savecharset; static char *savetrans[2]; #endif /* * Initialize the emulator once. */ void vt_install(fun1, fun2, win) void (*fun1)(); void (*fun2)(); WIN *win; { termout = fun1; vt_keyb = fun2; vt_win = win; } /* Partial init (after screen resize) */ void vt_pinit(win, fg, bg) WIN *win; int fg, bg; { vt_win = win; newy1 = 0; newy2 = vt_win->ys - 1; wresetregion(vt_win); if (fg > 0) vt_fg = fg; if (bg > 0) vt_bg = bg; wsetfgcol(vt_win, vt_fg); wsetbgcol(vt_win, vt_bg); } /* Set characteristics of emulator. */ void vt_init(type, fg, bg, wrap, add) int type; int fg; int bg; int wrap; int add; { vt_type = type; if (vt_type == ANSI) { vt_fg = WHITE; vt_bg = BLACK; } else { vt_fg = fg; vt_bg = bg; } if (wrap >= 0) vt_win->wrap = vt_wrap = wrap; vt_addlf = add; vt_insert = 0; vt_crlf = 0; vt_om = 0; newy1 = 0; newy2 = vt_win->ys - 1; wresetregion(vt_win); vt_keypad = NORMAL; vt_cursor = NORMAL; #ifdef HAVE_SELECT vt_echo = 0; #endif vt_tabs[0] = 0x01010100; vt_tabs[1] = vt_tabs[2] = vt_tabs[3] = vt_tabs[4] = 0x01010101; #if TRANSLATE vt_charset = 0; vt_trans[0] = savetrans[0] = vt_map[0]; vt_trans[1] = savetrans[1] = vt_map[1]; #endif #if OLD ptr = -2; #else ptr = 0; memset(escparms, 0, sizeof(escparms)); #endif esc_s = 0; if (vt_keyb) (*vt_keyb)(vt_keypad, vt_cursor); wsetfgcol(vt_win, vt_fg); wsetbgcol(vt_win, vt_bg); } /* Change some things on the fly. */ void vt_set(addlf, wrap, capfp, docap, bscode, echo, cursor, asis) int addlf; int wrap; FILE *capfp; int docap; int bscode; int echo; int cursor; int asis; { if (addlf >= 0) vt_addlf = addlf; if (wrap >= 0) vt_win->wrap = vt_wrap = wrap; if (capfp != (FILE *)0) vt_capfp = capfp; if (docap >= 0) vt_docap = docap; if (bscode >= 0) vt_bs = bscode; #ifdef HAVE_SELECT if (echo >= 0) vt_echo = echo; #endif if (cursor >= 0) vt_cursor = cursor; if (asis >=0) vt_asis = asis; } /* Output a string to the modem. */ static void v_termout(s, len) char *s; int len; { #ifdef HAVE_SELECT char *p; if (vt_echo) { for(p = s; *p; p++) { vt_out(*p); if (!vt_addlf && *p == '\r') vt_out('\n'); } wflush(); } #endif (*termout)(s, len); } /* * Escape code handling. */ /* * ESC was seen the last time. Process the next character. */ static void state1(c) int c; { short x, y, f; switch(c) { case '[': /* ESC [ */ esc_s = 2; return; case '(': /* ESC ( */ esc_s = 4; return; case ')': /* ESC ) */ esc_s = 5; return; case '#': /* ESC # */ esc_s = 6; return; case 'P': /* ESC P (DCS, Device Control String) */ esc_s = 7; return; case 'D': /* Cursor down */ case 'M': /* Cursor up */ x = vt_win->curx; if (c == 'D') { /* Down. */ y = vt_win->cury + 1; if (y == newy2 + 1) wscroll(vt_win, S_UP); else if (vt_win->cury < vt_win->ys) wlocate(vt_win, x, y); } if (c == 'M') { /* Up. */ y = vt_win->cury - 1; if (y == newy1 - 1) wscroll(vt_win, S_DOWN); else if (y >= 0) wlocate(vt_win, x, y); } break; case 'E': /* CR + NL */ wputs(vt_win, "\r\n"); break; case '7': /* Save attributes and cursor position */ case 's': savex = vt_win->curx; savey = vt_win->cury; saveattr = vt_win->attr; savecol = vt_win->color; #if TRANSLATE savecharset = vt_charset; savetrans[0] = vt_trans[0]; savetrans[1] = vt_trans[1]; #endif break; case '8': /* Restore them */ case 'u': #if TRANSLATE vt_charset = savecharset; vt_trans[0] = savetrans[0]; vt_trans[1] = savetrans[1]; #endif vt_win->color = savecol; /* HACK should use wsetfgcol etc */ wsetattr(vt_win, saveattr); wlocate(vt_win, savex, savey); break; case '=': /* Keypad into applications mode */ vt_keypad = APPL; if (vt_keyb) (*vt_keyb)(vt_keypad, vt_cursor); break; case '>': /* Keypad into numeric mode */ vt_keypad = NORMAL; if (vt_keyb) (*vt_keyb)(vt_keypad, vt_cursor); break; case 'Z': /* Report terminal type */ if (vt_type == VT100) v_termout("\033[?1;0c", 0); else v_termout("\033[?c", 0); break; case 'c': /* Reset to initial state */ f = XA_NORMAL; wsetattr(vt_win, f); vt_win->wrap = (vt_type != VT100); if (vt_wrap != -1) vt_win->wrap = vt_wrap; vt_crlf = vt_insert = 0; vt_init(vt_type, vt_fg, vt_bg, vt_win->wrap, 0); wlocate(vt_win, 0, 0); break; case 'H': /* Set tab in current position */ x = vt_win->curx; if (x > 159) x = 159; vt_tabs[x / 32] |= 1 << (x % 32); break; case 'N': /* G2 character set for next character only*/ case 'O': /* G3 " " */ case '<': /* Exit vt52 mode */ default: /* ALL IGNORED */ break; } esc_s = 0; return; } /* ESC [ ... [hl] seen. */ static void ansi_mode(on_off) int on_off; { int i; for(i = 0; i <= ptr; i++) { switch(escparms[i]) { case 4: /* Insert mode */ vt_insert = on_off; break; case 20: /* Return key mode */ vt_crlf = on_off; break; } } } /* * ESC [ ... was seen the last time. Process next character. */ static void state2(c) int c; { short x, y, attr, f; char temp[32]; /* See if a number follows */ if (c >= '0' && c <= '9') { #if OLD if (ptr < 0) ptr = 0; #endif escparms[ptr] = 10*(escparms[ptr]) + c - '0'; return; } /* Separation between numbers ? */ if (c == ';') { #if OLD if (ptr < 0) ptr = 0; /* keithr@primenet.com */ if (ptr >= 0 && ptr < 15) ptr++; #else if (ptr < 15) ptr++; #endif return; } /* ESC [ ? sequence */ #if OLD if (ptr < 0 && c == '?') { #else if (escparms[0] == 0 && ptr == 0 && c == '?') { #endif esc_s = 3; return; } /* Process functions with zero, one, two or more arguments */ switch(c) { case 'A': case 'B': case 'C': case 'D': /* Cursor motion */ if ((f = escparms[0]) == 0) f = 1; x = vt_win->curx; y = vt_win->cury; x += f * ((c == 'C') - (c == 'D')); if (x < 0) x = 0; if (x >= vt_win->xs) x = vt_win->xs - 1; if (c == 'B') { /* Down. */ y += f; if (y >= vt_win->ys) y = vt_win->ys - 1; if (y >= newy2 + 1) y = newy2; } if (c == 'A') { /* Up. */ y -= f; if (y < 0) y = 0; if (y <= newy1 - 1) y = newy1; } wlocate(vt_win, x, y); break; case 'K': /* Line erasing */ switch(escparms[0]) { case 0: wclreol(vt_win); break; case 1: wclrbol(vt_win); break; case 2: wclrel(vt_win); break; } break; case 'J': /* Screen erasing */ x = vt_win->color; y = vt_win->attr; if (vt_type == ANSI) { wsetattr(vt_win, XA_NORMAL); wsetfgcol(vt_win, WHITE); wsetbgcol(vt_win, BLACK); } switch(escparms[0]) { case 0: wclreos(vt_win); break; case 1: wclrbos(vt_win); break; case 2: winclr(vt_win); break; } if (vt_type == ANSI) { vt_win->color = x; vt_win->attr = y; } break; case 'n': /* Requests / Reports */ switch(escparms[0]) { case 5: /* Status */ v_termout("\033[0n", 0); break; case 6: /* Cursor Position */ sprintf(temp, "\033[%d;%dR", vt_win->cury + 1, vt_win->curx + 1); v_termout(temp, 0); break; } break; case 'c': /* Identify Terminal Type */ if (vt_type == VT100) { v_termout("\033[?1;2c", 0); break; } v_termout("\033[?c", 0); break; case 'x': /* Request terminal parameters. */ /* Always answers 19200-8N1 no options. */ sprintf(temp, "\033[%c;1;1;120;120;1;0x", escparms[0] == 1 ? '3' : '2'); v_termout(temp, 0); break; case 's': /* Save attributes and cursor position */ savex = vt_win->curx; savey = vt_win->cury; saveattr = vt_win->attr; savecol = vt_win->color; #if TRANSLATE savecharset = vt_charset; savetrans[0] = vt_trans[0]; savetrans[1] = vt_trans[1]; #endif break; case 'u': /* Restore them */ #if TRANSLATE vt_charset = savecharset; vt_trans[0] = savetrans[0]; vt_trans[1] = savetrans[1]; #endif break; vt_win->color = savecol; /* HACK should use wsetfgcol etc */ wsetattr(vt_win, saveattr); wlocate(vt_win, savex, savey); break; case 'h': ansi_mode(1); break; case 'l': ansi_mode(0); break; case 'H': case 'f': /* Set cursor position */ if ((y = escparms[0]) == 0) y = 1; if ((x = escparms[1]) == 0) x = 1; if (vt_om) y += newy1; wlocate(vt_win, x - 1, y - 1); break; case 'g': /* Clear tab stop(s) */ if (escparms[0] == 0) { x = vt_win->curx; if (x > 159) x = 159; vt_tabs[x / 32] &= ~ (1 << x % 32); } if (escparms[0] == 3) for(x = 0; x < 5; x++) vt_tabs[x] = 0; break; case 'm': /* Set attributes */ #if OLD /* Without argument, esc-parms[0] is 0 */ if (ptr < 0) ptr = 0; #endif attr = wgetattr((vt_win)); for (f = 0; f <= ptr; f++) { if (escparms[f] >= 30 && escparms[f] <= 37) wsetfgcol(vt_win, escparms[f] - 30); if (escparms[f] >= 40 && escparms[f] <= 47) wsetbgcol(vt_win, escparms[f] - 40); switch(escparms[f]) { case 0: attr = XA_NORMAL; wsetfgcol(vt_win, vt_fg); wsetbgcol(vt_win, vt_bg); break; case 4: attr |= XA_UNDERLINE; break; case 7: attr |= XA_REVERSE; break; case 1: attr |= XA_BOLD; break; case 5: attr |= XA_BLINK; break; case 22: /* Bold off */ attr &= ~XA_BOLD; break; case 24: /* Not underlined */ attr &=~XA_UNDERLINE; break; case 25: /* Not blinking */ attr &= ~XA_BLINK; break; case 27: /* Not reverse */ attr &= ~XA_REVERSE; break; case 39: /* Default fg color */ wsetfgcol(vt_win, vt_fg); break; case 49: /* Default bg color */ wsetbgcol(vt_win, vt_bg); break; } } wsetattr(vt_win, attr); break; case 'L': /* Insert lines */ if ((x = escparms[0]) == 0) x = 1; for(f = 0; f < x; f++) winsline(vt_win); break; case 'M': /* Delete lines */ if ((x = escparms[0]) == 0) x = 1; for(f = 0; f < x; f++) wdelline(vt_win); break; case 'P': /* Delete Characters */ if ((x = escparms[0]) == 0) x = 1; for(f = 0; f < x; f++) wdelchar(vt_win); break; case '@': /* Insert Characters */ if ((x = escparms[0]) == 0) x = 1; for(f = 0; f < x; f++) winschar(vt_win); break; case 'r': /* Set scroll region */ if ((newy1 = escparms[0]) == 0) newy1 = 1; if ((newy2 = escparms[1]) == 0) newy2 = vt_win->ys; newy1-- ; newy2--; if (newy1 < 0) newy1 = 0; if (newy2 < 0) newy2 = 0; if (newy1 >= vt_win->ys) newy1 = vt_win->ys - 1; if (newy2 >= vt_win->ys) newy2 = vt_win->ys - 1; if (newy1 >= newy2) { newy1 = 0; newy2 = vt_win->ys - 1; } wsetregion(vt_win, newy1, newy2); wlocate(vt_win, 0, newy1); break; case 'i': /* Printing */ case 'y': /* Self test modes */ default: /* IGNORED */ break; } /* Ok, our escape sequence is all done */ esc_s = 0; #if OLD ptr = -2; #else ptr = 0; memset(escparms, 0, sizeof(escparms)); #endif return; } /* ESC [? ... [hl] seen. */ static void dec_mode(on_off) int on_off; { int i; for(i = 0; i <= ptr; i++) { switch(escparms[i]) { case 1: /* Cursor keys in cursor/appl mode */ vt_cursor = on_off ? APPL : NORMAL; if (vt_keyb) (*vt_keyb)(vt_keypad, vt_cursor); break; case 6: /* Origin mode. */ vt_om = on_off; wlocate(vt_win, 0, newy1); break; case 7: /* Auto wrap */ vt_win->wrap = on_off; break; case 25: /* Cursor on/off */ wcursor(vt_win, on_off ? CNORMAL : CNONE); break; case 67: /* Backspace key sends. (FIXME: vt420) */ /* setbackspace(on_off ? 8 : 127); */ break; default: /* Mostly set up functions */ /* IGNORED */ break; } } } /* * ESC [ ? ... seen. */ static void state3(c) int c; { /* See if a number follows */ if (c >= '0' && c <= '9') { #if OLD if (ptr < 0) ptr = 0; #endif escparms[ptr] = 10*(escparms[ptr]) + c - '0'; return; } #if OLD /* ESC [ ? number seen */ if (ptr < 0) { esc_s = 0; return; } #endif switch(c) { case 'h': dec_mode(1); break; case 'l': dec_mode(0); break; case 'i': /* Printing */ case 'n': /* Request printer status */ default: /* IGNORED */ break; } esc_s = 0; #if OLD ptr = -2; #else ptr = 0; memset(escparms, 0, sizeof(escparms)); #endif return; } /* * ESC ( Seen. */ /*ARGSUSED*/ static void state4(c) int c; { /* Switch Character Sets. */ #if !TRANSLATE /* IGNORED */ (void)c; #else switch(c) { case 'A': case 'B': vt_trans[0] = vt_map[0]; break; case '0': case 'O': vt_trans[0] = vt_map[1]; break; } #endif esc_s = 0; } /* * ESC ) Seen. */ /*ARGSUSED*/ static void state5(c) int c; { /* Switch Character Sets. */ #if !TRANSLATE /* IGNORED */ (void)c; #else switch(c) { case 'A': case 'B': vt_trans[1] = vt_map[0]; break; case 'O': case '0': vt_trans[1] = vt_map[1]; break; } #endif esc_s = 0; } /* * ESC # Seen. */ /*ARGSUSED*/ static void state6(c) int c; { int x, y; /* Double height, double width and selftests. */ switch(c) { case '8': /* Selftest: fill screen with E's */ vt_win->doscroll = 0; vt_win->direct = 0; wlocate(vt_win, 0, 0); for(y = 0; y < vt_win->ys; y++) { wlocate(vt_win, 0, y); for(x = 0; x < vt_win->xs; x++) wputc(vt_win, 'E'); } wlocate(vt_win, 0, 0); vt_win->doscroll = 1; wredraw(vt_win, 1); break; default: /* IGNORED */ break; } esc_s = 0; } /* * ESC P Seen. */ static void state7(c) int c; { /* * Device dependant control strings. The Minix virtual console package * uses these sequences. We can only turn cursor on or off, because * that's the only one supported in termcap. The rest is ignored. */ static char buf[17]; static int pos = 0; static int state = 0; if (c == ESC) { state = 1; return; } if (state == 1) { buf[pos] = 0; pos = 0; state = 0; esc_s = 0; if (c != '\\') return; /* Process string here! */ if (!strcmp(buf, "cursor.on")) wcursor(vt_win, CNORMAL); if (!strcmp(buf, "cursor.off")) wcursor(vt_win, CNONE); if (!strcmp(buf, "linewrap.on")) { vt_wrap = -1; vt_win->wrap = 1; } if (!strcmp(buf, "linewrap.off")) { vt_wrap = -1; vt_win->wrap = 0; } return; } if (pos > 15) return; buf[pos++] = c; } void vt_out(ch) int ch; { int f; unsigned char c; int go_on = 0; if (!ch) return; #if OLD if (ptr == -2) { /* Initialize */ ptr = -1; for(f = 0; f < 8; f++) escparms[f] = 0; } #endif c = (unsigned char)ch; if (vt_docap == 2) /* Literal. */ fputc(c, vt_capfp); /* Process <31 chars first, even in an escape sequence. */ switch(c) { case 5: /* AnswerBack for vt100's */ if (vt_type != VT100) { go_on = 1; break; } v_termout("Minicom" VERSION, 0); break; case '\r': /* Carriage return */ wputc(vt_win, c); if (vt_addlf) { wputc(vt_win, '\n'); if (vt_docap == 1) fputc('\n', vt_capfp); } break; case '\t': /* Non - destructive TAB */ /* Find next tab stop. */ for(f = vt_win->curx + 1; f < 160; f++) if (vt_tabs[f / 32] & (1 << f % 32)) break; if (f >= vt_win->xs) f = vt_win->xs - 1; wlocate(vt_win, f, vt_win->cury); if (vt_docap == 1) fputc(c, vt_capfp); break; case 013: /* Old Minix: CTRL-K = up */ wlocate(vt_win, vt_win->curx, vt_win->cury - 1); break; case '\f': /* Form feed: clear screen. */ winclr(vt_win); wlocate(vt_win, 0, 0); break; #if !TRANSLATE case 14: case 15: /* Change character set. Not supported. */ break; #else case 14: vt_charset = 1; break; case 15: vt_charset = 0; break; #endif case 24: case 26: /* Cancel escape sequence. */ esc_s = 0; break; case ESC: /* Begin escape sequence */ esc_s = 1; break; case 128+ESC: /* Begin ESC [ sequence. */ esc_s = 2; break; case '\n': case '\b': case 7: /* Bell */ wputc(vt_win, c); if (vt_docap == 1) fputc(c, vt_capfp); break; default: go_on = 1; break; } if (!go_on) return; /* Now see which state we are in. */ switch(esc_s) { case 0: /* Normal character */ if (vt_docap == 1) fputc(P_CONVCAP[0]=='Y'? vt_inmap[c]: c, vt_capfp); c = vt_inmap[c]; /* conversion 04.09.97 / jl */ #if TRANSLATE if (vt_type == VT100 && vt_asis == 0) { if (vt_insert) winschar2(vt_win, vt_trans[vt_charset][c], 1); else wputc(vt_win, vt_trans[vt_charset][c]); } else { #endif if (vt_insert) winschar2(vt_win, c, 1); else wputc(vt_win, c); #if TRANSLATE } #endif break; case 1: /* ESC seen */ state1(c); break; case 2: /* ESC [ ... seen */ state2(c); break; case 3: state3(c); break; case 4: state4(c); break; case 5: state5(c); break; case 6: state6(c); break; case 7: state7(c); break; } } /* Translate keycode to escape sequence. */ void vt_send(c) int c; { char s[3]; int f; int len = 1; /* Special key? */ if (c < 256) { /* Translate backspace key? */ if (c == K_ERA) c = vt_bs; s[0] = vt_outmap[(unsigned char) c]; /* conversion 04.09.97 / jl */ s[1] = 0; /* CR/LF mode? */ if (c == '\r' && vt_crlf) { s[1] = '\n'; s[2] = 0; len = 2; } v_termout(s, len); if (vt_nl_delay > 0 && c == '\r') usleep(1000 * vt_nl_delay); return; } /* Look up code in translation table. */ for(f = 0; vt_keys[f].code; f++) if (vt_keys[f].code == c) break; if (vt_keys[f].code == 0) return; /* Now send appropriate escape code. */ v_termout("\033", 0); if (vt_type == VT100) { if (vt_cursor == NORMAL) v_termout(vt_keys[f].vt100_st, 0); else v_termout(vt_keys[f].vt100_app, 0); } else v_termout(vt_keys[f].ansi, 0); }