?? ansi.c
字號:
/*** Copyright (C) 1991, 1997 Free Software Foundation, Inc.** ** This file is part of TACK.** ** TACK 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, or (at your option)** any later version.** ** TACK is distributed in the hope that it will be useful,** but WITHOUT ANY WARRANTY; without even the implied warranty of** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the** GNU General Public License for more details.** ** You should have received a copy of the GNU General Public License** along with TACK; see the file COPYING. If not, write to** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,** Boston, MA 02111-1307, USA.*/#include <tack.h>MODULE_ID("$Id: ansi.c,v 1.9 2001/06/18 18:44:17 tom Exp $")/* * Standalone tests for ANSI terminals. Three entry points: * test_ansi_graphics(), test_ansi_reports() and test_ansi_sgr(). *//***************************************************************************** * * Test ANSI status reports * *****************************************************************************//* ASCII control characters */#define A_DC1 0x11 /* Control Q */#define A_DC3 0x13 /* Control S */#define A_ESC 0x1b#define A_DCS 0x90#define A_CSI 0x9b#define A_ST 0x9c#define MAX_MODES 256static char default_bank[] = "\033(B\017";static int private_use, ape, terminal_class;static short ansi_value[256];static unsigned char ansi_buf[512], pack_buf[512];struct ansi_reports { int lvl, final; const char *text; const char *request;};static struct ansi_reports report_list[] = { {0, 'c', "(DA) Primary device attributes", "\033[0c"}, {1, 0, "(DSR) Terminal status", "\033[5n"}, {1, 'R', "(DSR) Cursor position", "\033[6n"}, {62, 0, "(DA) Secondary device attributes", "\033[>0c"}, {62, 0, "(DSR) Printer status", "\033[?15n"}, {62, 0, "(DSR) Function key definition", "\033[?25n"}, {62, 0, "(DSR) Keyboard language", "\033[?26n"}, {63, 0, "(DECRQSS) Data destination", "\033P$q$}\033\\"}, {63, 0, "(DECRQSS) Status line type", "\033P$q$~\033\\"}, {63, 0, "(DECRQSS) Erase attribute", "\033P$q\"q\033\\"}, {63, 0, "(DECRQSS) Personality", "\033P$q\"p\033\\"}, {63, 0, "(DECRQSS) Top and bottom margins", "\033P$qr\033\\"}, {63, 0, "(DECRQSS) Character attributes", "\033P$qm\033\\"}, {63, 0, "(DECRQSS) Illegal request", "\033P$q@\033\\"}, {63, 0, "(DECRQUPSS) User pref supplemental set", "\033[&u"}, {63, 0, "(DECRQPSR) Cursor information", "\033[1$w"}, {63, 0, "(DECRQPSR) Tab stop information", "\033[2$w"}, {64, 0, "(DA) Tertiary device attributes", "\033[=0c"}, {64, 0, "(DSR) Extended cursor position", "\033[?6n"}, {64, 0, "(DSR) Macro space", "\033[?62n"}, {64, 0, "(DSR) Memory checksum", "\033[?63n"}, {64, 0, "(DSR) Data integrity", "\033[?75n"}, {64, 0, "(DSR) Multiple session status", "\033[?85n"}, {64, 0, "(DECRQSS) Attribute change extent", "\033P$q*x\033\\"}, {64, 0, "(DECRQSS) Columns per page", "\033P$q$|\033\\"}, {64, 0, "(DECRQSS) Lines per page", "\033P$qt\033\\"}, {64, 0, "(DECRQSS) Lines per screen", "\033P$q*|\033\\"}, {64, 0, "(DECRQSS) Left and right margins", "\033P$qs\033\\"}, {64, 0, "(DECRQSS) Local functions", "\033P$q+q\033\\"}, {64, 0, "(DECRQSS) Local function key control", "\033P$q=}\033\\"}, {64, 0, "(DECRQSS) Select modifier key reporting", "\033P$q+r\033\\"}, {64, 0, "(DECRQDE) Window report", "\033[\"v"}, {0, 0, 0, 0}};struct request_control { const char *text; const char *expect; const char *request; const char *set_mode; const char *reset_mode;};/* Request control function selection or setting */static const struct request_control rqss[] = { {"Data sent to screen", "0", "$}", "\033[0$}", 0}, {"Data sent to disabled status line", "0", "$}", 0, 0}, {"\033[0$~\033[1$}", "\033[0$}", 0, 0, 0}, {"Data sent to enabled status line", "1", "$}", 0, 0}, {"\033[2$~\033[1$}", "\033[0$}", 0, 0, 0}, {"Disable status line", "0", "$~", "\033[0$~", 0}, {"Top status line", "1", "$~", "\033[1$~", 0}, {"Bottom status line", "2", "$~", "\033[2$~", 0}, {"Erasable character", "0", "\"q", "\033[0\"q", 0}, {"Nonerasable character", "1", "\"q", "\033[1\"q", "\033[0\"q"}, {"Top and bottom margins", "3;10", "r", "\0337\033[3;10r", 0}, {"\033[r\0338", 0, 0, 0, 0}, {"Top and bottom margins", "default", "r", "\0337\033[r", "\0338"}, {"Character attributes, dim, bold", "1", "m", "\033[2;1m", "\033[m"}, {"Character attributes, bold, dim", "2", "m", "\033[1;2m", "\033[m"}, {"Character attributes, under, rev", "4;7", "m", "\033[4;7m", "\033[m"}, {"Character attributes, color", "35;42", "m", "\033[35;42m", "\033[m"}, {"All character attributes", "", "m", "\033[1;2;3;4;5;6;7;8;9m", 0}, {"\033[m", 0, 0, 0, 0}, {0, 0, 0, 0, 0}};/*** read_ansi()**** read an ANSI status report from terminal*/static voidread_ansi(void){ int ch, i, j, last_escape; fflush(stdout); read_key((char *)ansi_buf, sizeof(ansi_buf)); /* Throw away control characters inside CSI sequences. Convert two character 7-bit sequences into 8-bit sequences. */ for (i = j = last_escape = 0; (ch = ansi_buf[i]) != 0; i++) { if (ch == A_ESC) { if (last_escape == A_ESC) { pack_buf[j++] = A_ESC; } last_escape = A_ESC; } else if (last_escape == A_ESC && ch >= '@' && ch <= '_') { pack_buf[j++] = last_escape = ch + 0x40; } else if (last_escape != A_CSI || (ch > 0x20 && ch != 0x80)) { if (last_escape == A_ESC) { pack_buf[j++] = A_ESC; } if (ch > 0x80 && ch < 0xa0) { last_escape = ch; } pack_buf[j++] = ch; } } if (last_escape == A_ESC) { pack_buf[j++] = A_ESC; } pack_buf[j] = '\0'; return;}/*** valid_mode(expected)**** read a terminal mode status report and parse the result** Return TRUE if we got the expected terminating character.*/static intvalid_mode(int expected){ unsigned char *s; int ch, terminator; read_ansi(); ape = 0; ch = UChar(pack_buf[0]); ansi_value[0] = 0; if (ch != A_CSI && ch != A_DCS) return FALSE; s = pack_buf + 1; private_use = 0; if ((*s >= '<') & (*s <= '?')) { private_use = *s++; } terminator = 0; for (; (ch = *s); s++) { if (ch >= '0' && ch <= '9') ansi_value[ape] = ansi_value[ape] * 10 + ch - '0'; else if (ch == ';' || ch == ':') ansi_value[++ape] = 0; else if (ch >= '<' && ch <= '?') private_use = ch; else if (ch >= ' ') terminator = (terminator << 8) | ch; else break; } return terminator == expected;}/*** read_reports()**** read all the reports in the ANSI report structure*/static intread_reports(void){ int i, j, k, tc, vcr, lc; char *s; const char *t; lc = 5; terminal_class = tc = 0; for (i = 0; report_list[i].text; i++, lc++) { if (terminal_class < report_list[i].lvl && tc < report_list[i].lvl) { put_crlf(); menu_prompt(); ptext("/status [q] > "); j = wait_here(); if (j != 'n' && j != 'N') return 0; tc = report_list[i].lvl; lc = 1; } else if (lc + 2 >= lines) { put_crlf(); ptext("Hit any key to continue "); (void) wait_here(); lc = 1; } sprintf(temp, "%s (%s) ", report_list[i].text, expand_command(report_list[i].request)); ptext(temp); for (j = strlen(temp); j < 49; j++) putchp(' '); tc_putp(report_list[i].request); vcr = 0; if (report_list[i].final == 0) { read_ansi(); } else if (valid_mode(report_list[i].final)) switch (report_list[i].final) { case 'c': terminal_class = ansi_value[0]; break; case 'R': vcr = TRUE; break; } j = UChar(pack_buf[0]); if (j != A_CSI && j != A_DCS) { put_crlf(); t = "*** The above request gives illegal response ***"; ptext(t); for (j = strlen(t); j < 49; j++) putchp(' '); } s = expand((const char *)ansi_buf); if (char_count + expand_chars >= columns) { put_str("\r\n "); lc++; } putln(s); if (vcr) { /* find out how big the screen is */ tc_putp(report_list[i].request); if (!valid_mode('R')) continue; j = ansi_value[0]; k = ansi_value[1]; tc_putp("\033[255B\033[255C\033[6n"); if (!valid_mode('R')) continue; sprintf(temp, "\033[%d;%dH", j, k); tc_putp(temp); ptext("(DSR) Screen size (CSI 6 n)"); for (j = char_count; j < 50; j++) putchp(' '); sprintf(temp, "%d x %d", ansi_value[1], ansi_value[0]); ptextln(temp); } } menu_prompt(); ptext("/status r->repeat test, <return> to continue > "); return wait_here();}/*** request_cfss()**** Request Control function selection or settings*/static intrequest_cfss(void){ int i, j, k, l, ch; char *s; put_clear(); ptextln("Request Expected Received"); put_crlf(); for (i = 0; rqss[i].text; i++) { ptext(rqss[i].text); j = strlen(rqss[i].text) + strlen(rqss[i].expect); putchp(' '); for (j++; j < 40; j++) putchp(' '); ptext(rqss[i].expect); putchp(' '); tc_putp(rqss[i].set_mode); sprintf(temp, "\033P$q%s\033\\", rqss[i].request); tc_putp(temp); read_ansi(); tc_putp(rqss[i].reset_mode); putchp(' '); for (j = 0; ansi_buf[j]; j++) { if (ansi_buf[j] == 'r') { for (k = j++; (ch = UChar(ansi_buf[k])) != 0; k++) if (ch == A_ESC) { break; } else if (ch == A_ST) { break; } ansi_buf[k] = '\0'; s = expand((const char *)&ansi_buf[j]); if (char_count + expand_chars >= columns) put_str("\r\n "); put_str(s); } } put_crlf(); } /* calculate the valid attributes */ ptext("Valid attributes: 0"); j = 0; for (i = 1; i < 20; i++) { sprintf(temp, "\033[0;%dm\033P$qm\033\\", i); tc_putp(temp); (void) valid_mode('m'); if (ape > 0) { j = i; sprintf(temp, "\033[0m; %d", i); tc_putp(temp); } } put_crlf(); /* calculate how many parameters can be sent */ ptext("Max number of parameters: "); sprintf(temp, "%dm\033P$qm\033\\", j); l = -1; if (j > 0) for (l = 1; l < 33; l++) { tc_putp("\033[0"); for (ch = 1; ch <= l; ch++) put_this(';'); tc_putp(temp); (void) valid_mode('m'); if (ape == 0) break; } tc_putp("\033[m"); if (l >= 0) { sprintf(temp, "%d", l); ptext(temp); } else ptext("unknown"); put_crlf(); return wait_here();}/*** mode_display(puc, mode, initial, set, reset)**** print the mode display entry*/static voidmode_display(const char *p, int n, int c, char s, char r){ int k; sprintf(temp, "%s%d (%c, %c, %c)", p, n, c, s, r); k = strlen(temp); if (char_count + k >= columns) put_crlf(); for (; k < 14; k++) putchp(' '); put_str(temp);}/*** terminal_state()**** test DECRQM status reports*/static voidterminal_state(void){ static const char *puc[] = {"", "<", "=", ">", "?", 0}; int i, j, k, l, modes_found; char *s; char buf[256], tms[256]; int mode_puc[MAX_MODES], mode_number[MAX_MODES]; char set_value[MAX_MODES], reset_value[MAX_MODES]; char current_value[MAX_MODES]; ptext("Testing terminal mode status. (CSI 0 $ p)"); tc_putp("\033[0$p"); modes_found = 0; tms[0] = '\0'; if (valid_mode(('$' << 8) | 'y')) { for (i = 0; puc[i]; i++) { put_crlf(); if (i) { sprintf(temp, "Private use: %c", puc[i][0]); } else { strcpy(temp, "Standard modes:"); } k = strlen(temp); ptext(temp);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -