home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume25 / ted / part01 / fun.c next >
Encoding:
C/C++ Source or Header  |  1991-11-06  |  43.7 KB  |  1,398 lines

  1. /*
  2. ** This software is Copyright (c) 1991 by Daniel Weaver.
  3. **
  4. ** Permission is hereby granted to copy, distribute or otherwise
  5. ** use any part of this package as long as you do not try to make
  6. ** money from it or pretend that you wrote it.  This copyright
  7. ** notice must be maintained in any copy made.
  8. **
  9. ** Use of this software constitutes acceptance for use in an AS IS
  10. ** condition. There are NO warranties with regard to this software.
  11. ** In no event shall the author be liable for any damages whatsoever
  12. ** arising out of or in connection with the use or performance of this
  13. ** software.  Any use of this software is at the user's own risk.
  14. **
  15. **  If you make modifications to this software that you feel
  16. **  increases it usefulness for the rest of the community, please
  17. **  email the changes, enhancements, bug fixes as well as any and
  18. **  all ideas to me. This software is going to be maintained and
  19. **  enhanced as deemed necessary by the community.
  20. */
  21. /* test the function keys on the terminal */
  22.  
  23. #include "curses.h"
  24. #include "ted.h"
  25.  
  26. #define MAX_MODES 256
  27.  
  28. extern char *malloc();
  29.  
  30. /* scan code externals */
  31. extern int scan_max;  /* length of longest scan code */
  32. extern char **scan_up, **scan_down, **scan_name;
  33. extern int *scan_tested, *scan_length;
  34.  
  35. /* local definitions */
  36. static char *fk_name[MAX_STRINGS];
  37. static char *fkval[MAX_STRINGS];
  38. static char *fk_label[MAX_STRINGS];  /* function key labels (if any) */
  39. static int fk_tested[MAX_STRINGS];
  40. static int fkmax = 1;  /* length of longest key */
  41. static int got_labels = 0;  /* true if we have some labels */
  42. static int key_count = 0;
  43. static int end_state;
  44.  
  45. /* unknown function keys */
  46. #define MAX_FK_UNK 50
  47. static char *fk_unknown[MAX_FK_UNK];
  48. static int fk_length[MAX_FK_UNK];
  49. static int funk;
  50.  
  51. static char default_bank[] = "\033(B\017";
  52. static char *puc[] = {"", "<", "=", ">", "?", 0};
  53. static int private_use, ape, terminal_class, got_escape;
  54. static short ansi_value[256];
  55. static char ansi_buf[512], pack_buf[512];
  56. static char *ach, *pch;
  57.  
  58. struct ansi_reports {
  59.    int lvl, final;
  60.    char *text;
  61.    char *request;
  62. };
  63.  
  64. static struct ansi_reports report_list[] = {
  65.    0, 'c', "(DA) Primary device attributes", "\033[0c",
  66.    1,  0,  "(DSR) Terminal status", "\033[5n",
  67.    1, 'R', "(DSR) Cursor position", "\033[6n",
  68.    62, 0, "(DA) Secondary device attributes", "\033[>0c",
  69.    62, 0, "(DSR) Printer status", "\033[?15n",
  70.    62, 0, "(DSR) Function key definition", "\033[?25n",
  71.    62, 0, "(DSR) Keyboard language", "\033[?26n",
  72.    63, 0, "(DECRQSS) Data destination", "\033P$q$}\033\\",
  73.    63, 0, "(DECRQSS) Status line type", "\033P$q$~\033\\",
  74.    63, 0, "(DECRQSS) Erase attribute", "\033P$q\"q\033\\",
  75.    63, 0, "(DECRQSS) Personality", "\033P$q\"p\033\\",
  76.    63, 0, "(DECRQSS) Top and bottom margins", "\033P$qr\033\\",
  77.    63, 0, "(DECRQSS) Character attributes", "\033P$qm\033\\",
  78.    63, 0, "(DECRQSS) Illegal request", "\033P$q@\033\\",
  79.    63, 0, "(DECRQUPSS) User pref suplemental set", "\033[&u",
  80.    63, 0, "(DECRQPSR) Cursor information", "\033[1$w",
  81.    63, 0, "(DECRQPSR) Tab stop information", "\033[2$w",
  82.    64, 0, "(DA) Tertiary device attributes", "\033[=0c",
  83.    64, 0, "(DSR) Extended cursor position", "\033[?6n",
  84.    64, 0, "(DSR) Macro space", "\033[?62n",
  85.    64, 0, "(DSR) Memory checksum", "\033[?63n",
  86.    64, 0, "(DSR) Data integrity", "\033[?75n",
  87.    64, 0, "(DSR) Multiple session status", "\033[?85n",
  88.    64, 0, "(DECRQSS) Attribute change extent", "\033P$q*x\033\\",
  89.    64, 0, "(DECRQSS) Columns per page", "\033P$q$|\033\\",
  90.    64, 0, "(DECRQSS) Lines per page", "\033P$qt\033\\",
  91.    64, 0, "(DECRQSS) Lines per screen", "\033P$q*|\033\\",
  92.    64, 0, "(DECRQSS) Left and right margins", "\033P$qs\033\\",
  93.    64, 0, "(DECRQSS) Local functions", "\033P$q+q\033\\",
  94.    64, 0, "(DECRQSS) Local function key control", "\033P$q=}\033\\",
  95.    64, 0, "(DECRQSS) Select modifier key reporting", "\033P$q+r\033\\",
  96.    64, 0, "(DECRQDE) Window report", "\033[\"v",
  97.    0, 0, 0, 0};
  98.  
  99. struct request_control {
  100.    char *text;
  101.    char *expect;
  102.    char *request;
  103.    char *set_mode;
  104.    char *reset_mode;
  105. };
  106.  
  107. /* Request control function selection or setting */
  108. struct request_control rqss[] = {
  109.     "Data sent to screen",    "0", "$}", "\033[0$}", 0,
  110.     "Data sent to disabled status line", "0", "$}",
  111.         "\033[0$~\033[1$}", "\033[0$}",
  112.     "Data sent to enabled status line", "1", "$}",
  113.         "\033[2$~\033[1$}", "\033[0$}",
  114.     "Disbale status line",    "0", "$~", "\033[0$~", 0,
  115.     "Top status line",        "1", "$~", "\033[1$~", 0,
  116.     "Bottom status line",    "2", "$~", "\033[2$~", 0,
  117.     "Eraseable character",    "0", "\"q", "\033[0\"q", 0,
  118.     "Noneraseable character",    "1", "\"q", "\033[1\"q", "\033[0\"q",
  119.     "Top and bottom margins",    "3;10", "r", "\0337\033[3;10r",
  120.     "\033[r\0338",
  121.     "Top and bottom margins",    "default", "r", "\0337\033[r", "\0338",
  122.     "Character attributes, dim, bold", "1", "m", "\033[2;1m", "\033[m",
  123.     "Character attributes, bold, dim", "2", "m", "\033[1;2m", "\033[m",
  124.     "Character attributes, under, rev",    "4;7", "m", "\033[4;7m", "\033[m",
  125.     "Character attributes, color", "35;42", "m", "\033[35;42m", "\033[m",
  126.     "All character attributes",    "", "m", "\033[1;2;3;4;5;6;7;8;9m",
  127.     "\033[m",
  128.     0, 0, 0, 0, 0
  129. };
  130.  
  131. static void
  132. keys_tested(first_time, hex_output)
  133. int first_time, hex_output;
  134.    {  /* display a list of the keys not tested */
  135.       int i, l;
  136.       char outbuf[256];
  137.  
  138.       put_clear();
  139.       tty_set();
  140.       if (tty_can_sync) (void) tty_sync_error();
  141.       if (got_labels)
  142.          {
  143.             putln("Function key labels:");
  144.                for (i = 0; i < key_count; ++i) {
  145.                   if (fk_label[i])
  146.                      {
  147.                         sprintf(outbuf, "%s %s",
  148.                            fk_name[i] ? fk_name[i] : "??", fk_label[i]);
  149.                         put_columns(outbuf, strlen(outbuf), 16);
  150.                      }
  151.                }
  152.             put_newlines(2);
  153.          }
  154.       if (funk)
  155.          {
  156.             putln("The following keys are not defined:");
  157.                for (i = 0; i < funk; ++i) {
  158.                   put_columns(fk_unknown[i], fk_length[i], 16);
  159.                }
  160.             put_mode(exit_attribute_mode);
  161.             put_newlines(2);
  162.          }
  163.       if (first_time) putln("The following keys are defined:");
  164.       else putln("The following keys have not been tested:");
  165.       if (scan_mode)
  166.          for (i = 0; scan_down[i]; i++) {
  167.             if (!scan_tested[i])
  168.                {
  169.                   if (hex_output)
  170.                      strcpy(outbuf, hex_expand_to(scan_down[i], 3));
  171.                   else strcpy(outbuf, expand(scan_down[i]));
  172.                   l = expand_chars;
  173.                   if (hex_output)
  174.                      strcat(outbuf, hex_expand_to(scan_up[i], 3));
  175.                   else strcat(outbuf, expand(scan_up[i]));
  176.                   expand_chars += l;
  177.                   l = strlen(scan_name[i]);
  178.                   if (((char_count + 16) & ~15) +
  179.                      ((expand_chars + 7) & ~7) + l >= columns)
  180.                      put_crlf();
  181.                   else
  182.                   if (char_count) putchp(' ');
  183.                   put_columns(outbuf, expand_chars, 16);
  184.                   put_columns(scan_name[i], l, 8);
  185.                }
  186.          }
  187.       else
  188.          for (i = 0; i < key_count; i++) {
  189.             if (!fk_tested[i])
  190.                {
  191.                   if (hex_output)
  192.                      strcpy(outbuf, hex_expand_to(fkval[i], 3));
  193.                   else strcpy(outbuf, expand(fkval[i]));
  194.                   l = strlen(fk_name[i]);
  195.                   if (((char_count + 16) & ~15) +
  196.                      ((expand_chars + 7) & ~7) + l >= columns)
  197.                      put_crlf();
  198.                   else
  199.                   if (char_count) putchp(' ');
  200.                   put_columns(outbuf, expand_chars, 16);
  201.                   put_columns(fk_name[i], l, 8);
  202.                }
  203.          }
  204.       put_newlines(2);
  205.    }
  206.  
  207.  
  208. #ifdef TESTCAP
  209. void
  210. enter_lab(key_name, key_value, lab_name, lab_value)
  211. char *key_name, *key_value, *lab_name, *lab_value;
  212.    {  /* enter a label.  Called by getcap() */
  213.       int j;
  214.  
  215.       cap_test(key_name);
  216.       cap_test(lab_name);
  217.       /* ignore labels without function key values */
  218.       if (key_value)
  219.          {
  220.             j = strlen(key_value);
  221.             fkmax = fkmax > j ? fkmax : j;
  222.             fkval[key_count] = key_value;
  223.             fk_tested[key_count] = 0;
  224.             fk_name[key_count] = key_name;
  225.             fk_label[key_count++] = lab_value;
  226.             if (lab_value) got_labels = TRUE;
  227.          }
  228.    }
  229. #endif
  230.  
  231.  
  232. void
  233. enter_key(name, value)
  234. char *name, *value;
  235.    {  /* enter a function key.  Also called by getcap() */
  236.       int j;
  237.  
  238. #ifdef TESTCAP
  239.       cap_test(name);
  240. #else
  241.       can_test(name);
  242. #endif
  243.       if (value)
  244.          {
  245.             j = strlen(value);
  246.             fkmax = fkmax > j ? fkmax : j;
  247.             /* do not permit duplicates */
  248.                for (j = 0; j < key_count; j++) {
  249.                   if (!strcmp(fk_name[j], name)) return;
  250.                }
  251.             fkval[key_count] = value;
  252.             fk_tested[key_count] = 0;
  253.             fk_label[key_count] = NULL;
  254.             fk_name[key_count++] = name;
  255.          }
  256.    }
  257.  
  258.  
  259. static void
  260. find_keys()
  261.    {  /* find out which function keys are defined */
  262. #ifndef TESTCAP
  263.       char **string_base;
  264.       char *fkey_number[MAX_STRINGS];  /* function key number */
  265.       char *fkey_label[MAX_STRINGS];  /* function key labels */
  266.       int i, j, k;
  267.  
  268.       string_base = &back_tab;
  269.          for (i = j = 0; strnames[i]; i++) {
  270.             if (*string_base)
  271.                if (strncmp(strnames[i], "lf", 2) == 0)
  272.                   {
  273.                      fkey_number[j] = strnames[i];
  274.                      fkey_label[j++] = *string_base;
  275.                   }
  276.                else
  277.                if (strnames[i][0] == 'k')
  278.                   enter_key(strnames[i], *string_base);
  279.             if (string_base == &prtr_non)
  280. #ifdef SVR3
  281.                string_base = &char_padding;
  282. #else
  283.                break;
  284. #endif
  285.             else string_base++;
  286.          }
  287.       /* match the labels to the function keys */
  288.          for (i = 0; i < j; i++) {
  289.                for (k = 0; k < key_count; k++)
  290.                   if (!strcmp(&fkey_number[i][1], &fk_name[k][1])) {
  291.                      fk_label[k] = fkey_label[i];
  292.                      got_labels = TRUE;
  293.                      break;
  294.                   }
  295.          }
  296. #endif
  297.    }
  298.  
  299.  
  300. static void
  301. fresh_line()
  302.    {  /* clear the line for a new fumction key line */
  303.       if (over_strike) put_crlf();
  304.       else
  305.          {
  306.             put_cr();
  307.             if (clr_eol) putp(clr_eol);
  308.             else put_str("                    \r");
  309.          }
  310.    }
  311.  
  312.  
  313. static int
  314. end_funky(ch)
  315.    {  /* return true if this is the end */
  316.       switch (ch) {
  317.          case 'e':
  318.          case 'E':
  319.             end_state = 'e';
  320.             break;
  321.          case 'n':
  322.          case 'N':
  323.             if (end_state == 'e') end_state = 'n';
  324.             else end_state = 0;
  325.             break;
  326.          case 'd':
  327.          case 'D':
  328.             if (end_state == 'n') end_state = 'd';
  329.             else end_state = 0;
  330.             break;
  331.          case 'l':
  332.          case 'L':
  333.             if (end_state == 'l') end_state = '?';
  334.             else end_state = 'l';
  335.             break;
  336.          default:
  337.             end_state = 0;
  338.             break;
  339.       }
  340.       return end_state == 'd';
  341.    }
  342.  
  343.  
  344. static int
  345. found_match(s, hx, cc)
  346. char *s;
  347. int hx, cc;
  348.    {  /* return true if this string is a match */
  349.       int j, f;
  350.       char outbuf[256];
  351.  
  352.       if (!*s) return 0;
  353.       if (scan_mode)
  354.          for (j = f = 0; scan_down[j]; j++) {
  355.             if (scan_length[j] == 0) continue;
  356.             if (!strncmp(s, scan_down[j], scan_length[j]))
  357.                {
  358.                   if (!f)
  359.                      {  /* first match */
  360.                         put_cr();
  361.                         if (hx) put_str(hex_expand_to(s, 10));
  362.                         else put_str(expand_to(s, 10));
  363.                         f = 1;
  364.                      }
  365.                   (void) end_funky(scan_name[j][0]);
  366.                   put_str(" ");
  367.                   put_str(scan_name[j]);
  368.                   scan_tested[j] = 1;
  369.                   s += scan_length[j];
  370.                   if (strncmp(s, scan_up[j], scan_length[j]))
  371.                      {
  372.                         put_str(" scan down");
  373.                      }
  374.                   else s += scan_length[j];
  375.                   if (!*s) break;
  376.                   j = -1;
  377.                }
  378.             if (!strncmp(s, scan_up[j], scan_length[j]))
  379.                {
  380.                   if (!f)
  381.                      {  /* first match */
  382.                         put_cr();
  383.                         if (hx) put_str(hex_expand_to(s, 10));
  384.                         else put_str(expand_to(s, 10));
  385.                         f = 1;
  386.                      }
  387.                   put_str(" ");
  388.                   put_str(scan_name[j]);
  389.                   put_str(" scan up");
  390.                   s += scan_length[j];
  391.                   if (!*s) break;
  392.                   j = -1;
  393.                }
  394.          }
  395.       else
  396.          for (j = f = 0; j < key_count; j++) {
  397.             if (!strcmp(s, fkval[j]))
  398.                {
  399.                   if (!f)
  400.                      {  /* first match */
  401.                         put_cr();
  402.                         if (hx) put_str(hex_expand_to(s, 10));
  403.                         else put_str(expand_to(s, 10));
  404.                         f = 1;
  405.                      }
  406.                   sprintf(outbuf, " (%s)", fk_name[j]);
  407.                   put_str(outbuf);
  408.                   if (fk_label[j])
  409.                      {
  410.                         sprintf(outbuf, " <%s>", fk_label[j]);
  411.                         put_str(outbuf);
  412.                      }
  413.                   fk_tested[j] = 1;
  414.                }
  415.          }
  416.       if (end_state == '?')
  417.          {
  418.             keys_tested(0, hx);
  419.             tty_raw(cc, char_mask);
  420.             end_state = 0;
  421.          }
  422.       return f;
  423.    }
  424.  
  425.  
  426. static int
  427. found_exit(keybuf, hx, cc)
  428. char *keybuf;
  429. int hx, cc;
  430.    {  /* return true if the user wants to exit */
  431.       int j, k;
  432.       char *s;
  433.  
  434.  
  435.       if (scan_mode)
  436.          {
  437.             if (*keybuf == '\0') return TRUE;
  438.          }
  439.       else
  440.          {
  441.             /* break is a special case */
  442.             if (*keybuf == '\0')
  443.                {
  444.                   fresh_line();
  445.                   tty_set();
  446.                   ptext("Hit X to exit");
  447.                   if (wait_here() == 'X') return TRUE;
  448.                   keys_tested(0, hx);
  449.                   tty_raw(cc, char_mask);
  450.                   return FALSE;
  451.                }
  452.             /* is this the end? */
  453.                for (k = 0; j = (keybuf[k] & STRIP_PARITY); k++) {
  454.                   if (end_funky(j)) return TRUE;
  455.                }
  456.  
  457.             j = TRUE;  /* does he need an updated list? */
  458.                for (k = 0; keybuf[k]; k++)
  459.                   j &= (keybuf[k] & STRIP_PARITY) == '?';
  460.             if (j || end_state == '?')
  461.                {
  462.                   keys_tested(0, hx);
  463.                   tty_raw(cc, char_mask);
  464.                   end_state = 0;
  465.                   return FALSE;
  466.                }
  467.          }
  468.  
  469.       put_cr();
  470.       if (hx) s = hex_expand_to(keybuf, 10);
  471.       else s = expand_to(keybuf, 10);
  472.       sprintf(temp, "%s Unknown", s);
  473.       put_str(temp);
  474.          for (j = 0; j < MAX_FK_UNK; j++) {
  475.             if (j == funk)
  476.                {
  477.                   fk_length[funk] = expand_chars;
  478.                   if (fk_unknown[funk] = malloc(strlen(s) + 1))
  479.                       strcpy(fk_unknown[funk++], s);
  480.                   break;
  481.                }
  482.             if (fk_length[j] == expand_chars)
  483.                if (!strcmp(fk_unknown[j], s)) break;
  484.          }
  485.       return FALSE;
  486.    }
  487.  
  488.  
  489. test_funky(hex_output)
  490. int hex_output;
  491.    {
  492.       int i, j, k, len, fk;
  493.       char outbuf[256];
  494.       char keybuf[256];
  495.  
  496.       find_keys();
  497.       if (stop_testing)
  498.          {
  499.             can_test("(km)(smm)(rmm)");
  500. #ifdef SVR3
  501.             can_test("(nlab)(lw)(lh)(smln)(plm)(rmln)");
  502. #endif
  503. #ifndef TESTCAP
  504.             can_test("(pfx)(pfloc)");
  505. #endif
  506.             return;
  507.          }
  508.       if (tty_can_sync == 1) verify_time();
  509.       if (keypad_xmit) putp(keypad_xmit);
  510.       keys_tested(1, hex_output);  /* also clears screen */
  511.       ptextln("Hit any function key.  Type 'end' to quit.  Type ? to update the display.");
  512.       put_crlf();
  513.       keybuf[0] = '\0';
  514.       end_state = 0;
  515.       if (scan_mode) fkmax = scan_max;
  516. #ifdef WAIT_MODE
  517.       sprintf(temp, "All function keys are assumed to be %d characters long.  You must pad shorter keys with blanks.", fkmax);
  518.       ptextln(temp);
  519.       /* use this code if your OS can not tell if a character is ready.
  520.          Reads will be done in wait mode.  Use blanks to pad short
  521.          strings. */
  522.       tty_raw(1, char_mask);
  523.          while(end_state != 'd') {
  524.             fflush(stdout);
  525.             if (!read(fileno(stdin), keybuf, 1)) break;
  526.             keybuf[0] &= char_mask;
  527.             fresh_line();
  528.                for (len = 1; len < fkmax; len++) {
  529.                   keybuf[len] = '\0';
  530.                   if (hex_output)
  531.                      put_str(hex_expand_to(&keybuf[len - 1], 3));
  532.                   else put_str(expand(&keybuf[len - 1]));
  533.                   fflush(stdout);
  534.                   if (!read(fileno(stdin), &keybuf[len], 1)) break;
  535.                   keybuf[len] &= char_mask;
  536.                }
  537.             /* come here when typing stops */
  538.             keybuf[len] = '\0';
  539.             if (found_match(keybuf, hex_output, 1)) continue;
  540.             /* backup over the blanks */
  541.                for ( ; len; keybuf[--len] = '\0')
  542.                   if (keybuf[len - 1] != ' ') break;
  543.             if (len == 0) continue;
  544.             if (found_match(keybuf, hex_output, 1)) continue;
  545.             if (found_exit(keybuf, hex_output, 1)) break;
  546.          }
  547. #else
  548.       /* use this code if your OS can tell if a character is ready.
  549.          Reads will be done by read_key() defined in sysdep.c */
  550.       tty_raw(0, char_mask);
  551.          while(end_state != 'd') {
  552.             read_key(keybuf, fkmax);
  553.             fresh_line();
  554.             if (found_match(keybuf, hex_output, 0)) continue;
  555.             if (found_exit(keybuf, hex_output, 0)) break;
  556.          }
  557. #endif
  558.       if (keypad_local) putp(keypad_local);
  559.       keys_tested(0, hex_output);
  560.       if (has_meta_key)
  561.          {
  562.             if (char_mask != ALLOW_PARITY)
  563.                {
  564.                   if (tty_meta_prep()) (void) wait_here();
  565.                }
  566.             ptext("Begin meta key test. (km) (smm) (rmm)  Hit any key");
  567.             ptext(" with the meta key.  The character will be");
  568.             ptext(" displayed in hex.  If the meta key is working");
  569.             ptext(" then the most significant bit will be set.  Type");
  570.             ptextln(" 'end' to exit.");
  571.             tty_raw(1, ALLOW_PARITY);
  572.             putp(meta_on);
  573.  
  574.                for (i = j = k = len = 0; i != 'e' | j != 'n' | k != 'd'; ) {
  575.                   i = j;  j = k;
  576.                   k = getchp(ALLOW_PARITY);
  577.                   if (k == EOF) break;
  578.                   if ((len += 3) >= columns)
  579.                      {
  580.                         put_crlf();  len = 3;
  581.                      }
  582.                   sprintf(outbuf, "%02X ", k);
  583.                   put_str(outbuf);
  584.                   k &= STRIP_PARITY;
  585.                }
  586.             putp(meta_off);
  587.             put_crlf();
  588.          }
  589.       else
  590.          {
  591.             ptextln("This terminal has no meta key. (km)");
  592.             (void) wait_here();
  593.          }
  594.       tty_set();
  595.  
  596. #ifdef SVR3
  597.       new_test(8);
  598.       sprintf(temp, "Your terminal has %d labels (nlab) that are %d characters wide (lw) and %d lines high (lh)",
  599.       num_labels, label_width, label_height);
  600.       ptext(temp);
  601.       ptextln(" Testing (smln) (pln) (rmln)");
  602.       if (label_on) putp(label_on);
  603.       if (label_width <= 0) label_width = sizeof(outbuf) - 1;
  604.          for (i = 1; i <= num_labels; i++) {
  605.             sprintf(outbuf, "L%d..............................", i);
  606.             outbuf[label_width] = '\0';
  607.             putp(tparm(plab_norm, i, outbuf));
  608.          }
  609.       (void) wait_here();
  610.       if (label_off) putp(label_off);
  611. #endif
  612.  
  613. #ifndef TESTCAP
  614.       new_test(8);
  615.       fk = 1;  /* use function key 1 for now */
  616.       if (pkey_xmit)
  617.          {
  618.             char mm[256];
  619.  
  620.             /* test program function key */
  621.             sprintf(temp,
  622.                "(pfx) Set function key %d to transmit abc\\n", fk);
  623.             ptextln(temp);
  624.             putp(tparm(pkey_xmit, fk, "abc\n"));
  625.             sprintf(temp, "Hit function key %d\n", fk);
  626.             ptextln(temp);
  627.                for (i = 0; i < 4; ++i) mm[i] = getchp(STRIP_PARITY);
  628.             mm[i] = '\0';
  629.             put_crlf();
  630.             if (mm[0] != 'a' | mm[1] != 'b' | mm[2] != 'c')
  631.                {
  632.                   sprintf(temp, "Error string recieved was: %s", expand(mm));
  633.                   ptextln(temp);
  634.                }
  635.             else putln("Thank you\n");
  636.             /* if the terminal sent too much, flush it */
  637.             if (tty_can_sync) (void) tty_sync_error();
  638.          }
  639.       else ptextln("Function key transmit (pfx), not present.");
  640.  
  641.       if (pkey_local)
  642.          {
  643.             /* test local function key */
  644.             sprintf(temp,
  645.                "(pfloc) Set function key %d to execute a clear and print \"Done!\"", fk);
  646.             ptextln(temp);
  647.             sprintf(temp, "%sDone!", liberated(clear_screen));
  648.             putp(tparm(pkey_local, fk, temp));
  649.             sprintf(temp, "Hit function key %d.  Then hit return.", fk);
  650.             ptextln(temp);
  651.          }
  652.       else ptextln("Function key execute local (pfloc), not present.");
  653.  
  654.       (void) wait_here();
  655.       /* if the terminal sent anything else, flush it */
  656.       if (tty_can_sync) (void) tty_sync_error();
  657.       if (key_f1 && pkey_xmit) putp(tparm(pkey_xmit, fk, key_f1));
  658. #endif
  659.    }
  660.  
  661.  
  662. test_printer()
  663.    {  /* test the printer commands */
  664.  
  665.       if (stop_testing)
  666.          {
  667.             can_test("(mc4)(mc5)(mc0)(mc5i)");
  668.             return;
  669.          }
  670.       put_clear();
  671.       putln("Begin printer test.");
  672.       if (!prtr_on || !prtr_off)
  673.          {
  674.             ptextln("Printer on/off missing. (mc5) (mc4)");
  675.          }
  676.       else
  677. #if defined(SVR3) || defined(XENIX)
  678.       if (prtr_silent)
  679.          {
  680.             ptextln("Your printer is silent. (mc5i) is set.");
  681.             putp(prtr_on);
  682.             ptextln("This line should be on the printer but not your screen. (mc5)");
  683.             putp(prtr_off);
  684.             ptextln("This line should be only on the screen. (mc4)");
  685.          }
  686.       else
  687.          {
  688.             ptextln("Your printer is not silent. (mc5i) is reset.");
  689.             putp(prtr_on);
  690.             ptextln("This line should be on the printer and the screen. (mc5)");
  691.             putp(prtr_off);
  692.             ptextln("This line should only be on the screen. (mc4)");
  693.          }
  694. #else
  695.          {
  696.             putp(prtr_on);
  697.             ptextln("This line should be on the printer. (mc5)");
  698.             putp(prtr_off);
  699.             ptextln("This line should only be on the screen. (mc4)");
  700.          }
  701. #endif
  702.       (void) wait_here();
  703.       if (print_screen)
  704.          {
  705.             ptext("I am going to send the contents of the screen to");
  706.             ptext(" the printer, then wait for a keystroke from you.");
  707.             ptext("  All of the text that appears on the screen");
  708.             ptextln(" should be printed. (mc0)");
  709.             putp(print_screen);
  710.             (void) wait_here();
  711.          }
  712.       putln("End of printer test.");
  713.    }
  714.  
  715.  
  716. static void
  717. line_pattern()
  718.    {  /* put up a pattern that will help count the number of lines */
  719.       int i, j;
  720.  
  721.       put_clear();
  722.       if (over_strike)
  723.          for (i = 0; i < 100; i++) {
  724.             if (i) put_crlf();
  725.                for (j = i / 10; j; j--) put_this(' ');
  726.             put_this('0' + ((i + 1) % 10));
  727.          }
  728.       else  /* I assume it will scroll */
  729.          for (i = 100; i; i--) {
  730.             sprintf(temp, "\r\n%d", i);
  731.             put_str(temp);
  732.          }
  733.    }
  734.  
  735.  
  736. static void
  737. column_pattern()
  738.    {  /* put up at pattern that will help count the number of columns */
  739.       int i, j;
  740.  
  741.       put_clear();
  742.          for (i = 0; i < 20; i++) {
  743.                for (j = 1; j < 10; j++) {
  744.                   put_this('0' + j);
  745.                }
  746.             put_this('.');
  747.          }
  748.    }
  749.  
  750.  
  751. test_report(crx, hex_display)
  752. int crx, hex_display;
  753.    {  /* status report and echo test */
  754.       int i, j, ch, crp, high_bit, save_scan_mode;
  755.       char buf[1024];
  756.       char txt[8];
  757.  
  758.       put_clear();
  759.       if (crx == 1)
  760.          {
  761.             ptext("Characters after a CR or LF will be echoed as");
  762.             ptext(" is.  All other characters will be expanded.  Type");
  763.             ptext(" 'end' to exit.  Type");
  764.             ptext(" 'echo' to redisplay last report.  Type");
  765.             ptext(" 'hex' to redisplay last report in hex.  Type");
  766.             ptextln(" 'clear' to clear screen.");
  767.          }
  768.       else /* echo test */
  769.          {
  770.             ptext("Begin echo test.  Type");
  771.             ptext(" 'end' to exit.  Type");
  772.             ptext(" 'hex' to display characters in hex.  Type");
  773.             ptext(" 'high' to toggle high order bit on output.  Type");
  774.             ptextln(" 'clear' to clear screen.");
  775.          }
  776.       txt[sizeof(txt) - 1] = '\0';
  777.       save_scan_mode = scan_mode;
  778.       tty_raw(1, char_mask);
  779.          for (i = crp = high_bit = 0; ; ) {
  780.             ch = getchp(char_mask);
  781.             if (ch == EOF) break;
  782.             if (i >= sizeof(buf) - 1) i = 0;
  783.             buf[i++] = ch;
  784.             buf[i] = '\0';
  785.                for (j = 0; j < sizeof(txt) - 1; j++) {
  786.                   txt[j] = txt[j + 1];
  787.                }
  788.             txt[sizeof(txt) - 1] = ch & STRIP_PARITY;
  789.             if (crx == 0) /* echo test */
  790.                {
  791.                   if (hex_display) ptext(hex_expand_to(&buf[i - 1], 3));
  792.                   else putch(ch | high_bit);
  793.                }
  794.             else /* status report test */
  795.             if (ch == '\n' | ch == '\r')
  796.                {
  797.                   put_crlf();
  798.                   crp = 0;
  799.                }
  800.             else
  801.             if (crp++ < crx) putch(ch | high_bit);
  802.             else put_str(expand(&buf[i - 1]));
  803.             if (!strncmp(&txt[sizeof(txt) - 7], "columns", 7))
  804.                {
  805.                   column_pattern();
  806.                   buf[i = 0] = '\0';
  807.                   crp = 0;
  808.                }
  809.             if (!strncmp(&txt[sizeof(txt) - 5], "lines", 5))
  810.                {
  811.                   line_pattern();
  812.                   buf[i = 0] = '\0';
  813.                   crp = 0;
  814.                }
  815.             if (!strncmp(&txt[sizeof(txt) - 5], "clear", 5))
  816.                {
  817.                   put_clear();
  818.                   buf[i = 0] = '\0';
  819.                   crp = 0;
  820.                }
  821.             if (!strncmp(&txt[sizeof(txt) - 4], "high", 4))
  822.                {
  823.                   high_bit ^= 0x80;
  824.                   if (high_bit) ptextln("\nParity bit set");
  825.                   else ptextln("\nParity bit reset");
  826.                }
  827.             if (!strncmp(&txt[sizeof(txt) - 4], "echo", 4))
  828.                {
  829.                   /* display the last status report */
  830.                   /* clear bypass condition on Tek terminals */
  831.                   put_crlf();
  832.                   buf[i -= 4] = '\0';
  833.                   put_str(expand(buf));
  834.                }
  835.             if (save_scan_mode &&
  836.                !strncmp(&txt[sizeof(txt) - 4], "scan", 4))
  837.                {
  838.                   /* toggle scan mode */
  839.                   scan_mode = !scan_mode;
  840.                }
  841.             if (!strncmp(&txt[sizeof(txt) - 3], "end", 3)) break;
  842.             if (!strncmp(&txt[sizeof(txt) - 3], "hex", 3))
  843.                if (crx)
  844.                   {
  845.                      /* display the last status report */
  846.                      /* clear bypass condition on Tek terminals */
  847.                      put_crlf();
  848.                      buf[i -= 3] = '\0';
  849.                      put_str(hex_expand_to(buf, 3));
  850.                   }
  851.                else hex_display = !hex_display;
  852.             if (!strncmp(&txt[sizeof(txt) - 3], "two", 3)) crx = 2;
  853.             if (!strncmp(&txt[sizeof(txt) - 3], "one", 3)) crx = 1;
  854.             if (!strncmp(&txt[sizeof(txt) - 3], "all", 3)) crx = 0;
  855.          }
  856.       scan_mode = save_scan_mode;
  857.       put_crlf();
  858.       tty_set();
  859.       if (crx) ptextln("End of status report test.");
  860.       else ptextln("End of echo test.");
  861.    }
  862.  
  863.  
  864. static int
  865. pack_ansi()
  866.    {  /* read and pack an ANSI character */
  867.       int ch;
  868.  
  869.       if (*pch) return *pch++;
  870.  
  871.          while (1) {
  872.             ch = getchp(char_mask);
  873.             if (ch == EOF) return EOF;
  874.             if (ch == A_DC1 || ch == A_DC3) continue;
  875.             *ach++ = ch;  *ach = '\0';
  876.             if (got_escape && ch >= ' ')
  877.                {
  878.                   got_escape = 0;
  879.                   if (ch < '@' || ch > '_')
  880.                      {
  881.                         *pch++ = A_ESC;
  882.                         *pch = ch;
  883.                         pch[1] = '\0';
  884.                         return A_ESC;
  885.                      }
  886.                   ch += 0x40;
  887.                   break;
  888.                }
  889.             else
  890.             if (ch == A_ESC) got_escape = 1;
  891.             else break;
  892.          }
  893.       *pch++ = ch;  *pch = '\0';
  894.       return ch;
  895.    }
  896.  
  897.  
  898. static void
  899. read_ansi()
  900.    {  /* read an ANSI status report */
  901.       int ch;
  902.  
  903.       fflush(stdout);
  904.       ach = ansi_buf;  pch = pack_buf;
  905.       ansi_buf[0] = pack_buf[0] = '\0';
  906.       got_escape = 0;
  907.       ch = pack_ansi();
  908.       if (ch == A_ESC)
  909.          do {
  910.             ch = pack_ansi();
  911.             if (ch == EOF) return;
  912.          } while (ch < '0' || ch > '~');
  913.       else
  914.       if (ch == A_CSI)
  915.          do {
  916.             ch = pack_ansi();
  917.             if (ch == EOF) return;
  918.          } while (ch < '@' || ch > '~');
  919.       else
  920.       if (ch == A_DCS)
  921.          do {
  922.             ch = pack_ansi();
  923.             if (ch == EOF) return;
  924.          } while (ch != A_ST);
  925.       return;
  926.    }
  927.  
  928.  
  929. static int
  930. valid_mode(expected)
  931. int expected;
  932.    {  /* read a terminal mode status report and parse the result */
  933.       char *s;
  934.       int ch, terminator;
  935.  
  936.       read_ansi();
  937.  
  938.       ape = 0;
  939.       ch = pack_buf[0] & 0xff;
  940.       if (ch != A_CSI && ch != A_DCS) return FALSE;
  941.  
  942.       s = pack_buf + 1;
  943.       private_use = 0;
  944.       if (*s >= '<' & *s <= '?') private_use = *s++;
  945.       ansi_value[0] = 0;
  946.       terminator = 0;
  947.          for ( ; ch = *s; s++) {
  948.             if (ch >= '0' && ch <= '9')
  949.                ansi_value[ape] = ansi_value[ape] * 10 + ch - '0';
  950.             else
  951.             if (ch == ';' || ch == ':')
  952.                ansi_value[++ape] = 0;
  953.             else
  954.             if (ch >= '<' && ch <= '?')
  955.                private_use = ch;
  956.             else
  957.             if (ch >= ' ')
  958.                terminator = (terminator << 8) | ch;
  959.             else break;
  960.          }
  961.       return terminator == expected;
  962.    }
  963.  
  964.  
  965. static int
  966. read_reports()
  967.    {  /* read all the reports in the ANSI report structure */
  968.       int i, j, k, tc, vcr, lc;
  969.       char *s;
  970.  
  971.       lc = 5;
  972.       terminal_class = tc = 0;
  973.          for (i = 0; report_list[i].text; i++, lc++) {
  974.             if (terminal_class < report_list[i].lvl &&
  975.                tc < report_list[i].lvl)
  976.                {
  977.                   j = wait_here();
  978.                   if (j != 'c' && j != 'C') return j;
  979.                   tc = report_list[i].lvl;
  980.                }
  981.             else
  982.             if (lc >= lines)
  983.                {
  984.                   (void) wait_here();
  985.                   lc = 1;
  986.                }
  987.             sprintf(temp, "%s (%s) ", report_list[i].text,
  988.                expand_command(report_list[i].request));
  989.             ptext(temp);
  990.                for (j = strlen(temp); j < 49; j++) putchp(' ');
  991.             putp(report_list[i].request);
  992.             vcr = 0;
  993.             if (report_list[i].final == 0) read_ansi();
  994.             else
  995.             if (valid_mode(report_list[i].final))
  996.                switch(report_list[i].final) {
  997.                   case 'c':
  998.                      terminal_class = ansi_value[0];
  999.                      break;
  1000.                   case 'R':
  1001.                      vcr = TRUE;
  1002.                      break;
  1003.                }
  1004.             j = pack_buf[0] & 0xff;
  1005.             if (j == A_CSI || j == A_DCS)
  1006.                {
  1007.                   s = expand(ansi_buf);
  1008.                   if (char_count + expand_chars >= columns)
  1009.                      {
  1010.                         put_str("\r\n        ");
  1011.                         lc++;
  1012.                      }
  1013.                   put_str(s);
  1014.                }
  1015.             put_crlf();
  1016.             if (vcr)
  1017.                {  /* find out how big the screen is */
  1018.                   putp(report_list[i].request);
  1019.                   if (!valid_mode('R')) continue;
  1020.                   j = ansi_value[0];
  1021.                   k = ansi_value[1];
  1022.                   putp("\033[255B\033[255C\033[6n");
  1023.                   if (!valid_mode('R')) continue;
  1024.                   sprintf(temp, "\033[%d;%dH", j, k);
  1025.                   putp(temp);
  1026.                   ptext("(DSR) Screen size (CSI 6 n)");
  1027.                      for (j = char_count; j < 50; j++) putchp(' ');
  1028.                   sprintf(temp, "%d x %d", ansi_value[1], ansi_value[0]);
  1029.                   ptextln(temp);
  1030.                   
  1031.                }
  1032.          }
  1033.       return wait_here();
  1034.    }
  1035.  
  1036.  
  1037. static int
  1038. request_cfss()
  1039.    {  /* Request Control function selection or settings */
  1040.       int i, j, k, l, ch;
  1041.       char *s;
  1042.  
  1043.       put_clear();
  1044.       ptextln("Request                         Expected  Received");
  1045.       put_crlf();
  1046.          for (i = 0; rqss[i].text; i++) {
  1047.             ptext(rqss[i].text);
  1048.             j = strlen(rqss[i].text) + strlen(rqss[i].expect);
  1049.             putchp(' ');
  1050.                for (j++; j < 40; j++) putchp(' ');
  1051.             ptext(rqss[i].expect);
  1052.             putchp(' ');
  1053.             putp(rqss[i].set_mode);
  1054.             sprintf(temp, "\033P$q%s\033\\", rqss[i].request);
  1055.             putp(temp);
  1056.             read_ansi();
  1057.             putp(rqss[i].reset_mode);
  1058.             putchp(' ');
  1059.                for (j = 0; ansi_buf[j]; j++) {
  1060.                   if (ansi_buf[j] == 'r')
  1061.                      {
  1062.                            for (k = j++; ch = (ansi_buf[k] & 0xff); k++)
  1063.                               if (ch == A_ESC) break;
  1064.                               else
  1065.                               if (ch == A_ST) break;
  1066.                         ansi_buf[k] = '\0';
  1067.                         s = expand(&ansi_buf[j]);
  1068.                         if (char_count + expand_chars >= columns)
  1069.                            put_str("\r\n        ");
  1070.                         put_str(s);
  1071.                      }
  1072.                }
  1073.             put_crlf();
  1074.          }
  1075.       /* calculate the valid attributes */
  1076.       ptext("Valid attributes:         0");
  1077.       j = 0;
  1078.          for (i = 1; i < 20; i++) {
  1079.             sprintf(temp, "\033[0;%dm\033P$qm\033\\", i);
  1080.             putp(temp);
  1081.             (void) valid_mode('m');
  1082.             if (ape > 0)
  1083.                {
  1084.                   j = i;
  1085.                   sprintf(temp, "\033[0m; %d", i);
  1086.                   putp(temp);
  1087.                }
  1088.          }
  1089.       put_crlf();
  1090.       /* calculate how many parameters can be sent */
  1091.       ptext("Max number of parameters: ");
  1092.       sprintf(temp, "%dm\033P$qm\033\\", j);
  1093.       l = -1;
  1094.       if (j > 0)
  1095.          for (l = 1; l < 33; l++ ) {
  1096.             putp("\033[0");
  1097.                for (ch = 1; ch <= l; ch++) put_this(';');
  1098.             putp(temp);
  1099.             (void) valid_mode('m');
  1100.             if (ape == 0) break;
  1101.          }
  1102.       putp("\033[m");
  1103.       if (l >= 0)
  1104.          {
  1105.             sprintf(temp, "%d", l);
  1106.             ptext(temp);
  1107.          }
  1108.       else ptext("unknown");
  1109.       put_crlf();
  1110.       return wait_here();
  1111.    }
  1112.  
  1113.  
  1114. static
  1115. mode_display(p, n, c, s, r)
  1116. char *p;
  1117. char n, c, s, r;
  1118.    {   /* print the mode display entry */
  1119.       int k;
  1120.  
  1121.       sprintf(temp, "%s%d (%c, %c, %c)", p, n, c, s, r);
  1122.       k = strlen(temp);
  1123.       if (char_count + k >= columns) put_crlf();
  1124.          for ( ; k < 14; k++) putchp(' ');
  1125.       put_str(temp);
  1126.    }
  1127.  
  1128.  
  1129. static void
  1130. terminal_state()
  1131.    {  /* test DECRQM status reports */
  1132.       int i, j, k, l, modes_found;
  1133.       char *s;
  1134.       char buf[256], tms[256];
  1135.       char mode_puc[MAX_MODES], mode_number[MAX_MODES];
  1136.       char set_value[MAX_MODES], reset_value[MAX_MODES];
  1137.       char current_value[MAX_MODES];
  1138.  
  1139.       ptext("Testing terminal mode status. (CSI 0 $ p)");
  1140.       putp("\033[0$p");
  1141.       modes_found = 0;
  1142.       tms[0] = '\0';
  1143.       if (valid_mode(('$' << 8) | 'y'))
  1144.          for (i = 0; puc[i]; i++) {
  1145.             put_crlf();
  1146.             if (i)
  1147.                {
  1148.                   sprintf(temp, "Private use: %c", puc[i][0]);
  1149.                }
  1150.             else strcpy(temp, "Standard modes:");
  1151.             k = strlen(temp);
  1152.             ptext(temp);
  1153.                for (j = 0; j < sizeof(buf); buf[j++] = ' ');
  1154.                for (j = l = 0; j < 255 && j - l < 50; j++) {
  1155.                   sprintf(temp, "\033[%s%d$p", puc[i], j);
  1156.                   putp(temp);
  1157.                   if (!valid_mode(('$' << 8) | 'y'))
  1158.                      {  /* not valid, save terminating value */
  1159.                         s = expand(ansi_buf);
  1160.                         sprintf(tms, "%s%s%d %s  ", tms, puc[i], j, s);
  1161.                         break;
  1162.                      }
  1163.                   if (private_use != puc[i][0]) break;
  1164.                   if (ansi_value[0] != j) break;
  1165.                   if (ansi_value[1])
  1166.                      {
  1167.                         l = j;
  1168.                         if (k > 70)
  1169.                            {
  1170.                               buf[k] = '\0';
  1171.                               put_crlf();
  1172.                               ptextln(buf);
  1173.                                  for (k = 0; k < sizeof(buf); )
  1174.                                     buf[k++] = ' ';
  1175.                               k = 0;
  1176.                            }
  1177.                         sprintf(temp, " %d", j);
  1178.                         ptext(temp);
  1179.                         k += strlen(temp);
  1180.                         buf[k - 1] = ansi_value[1] + '0';
  1181.                         if (modes_found >= MAX_MODES) continue;
  1182.                         current_value[modes_found] =
  1183.                            ansi_value[1] + '0';
  1184.                         /* some modes never return */
  1185.                         if ((i == 0 && j == 13) /* control execution */
  1186.                            || (puc[i][0] == '?' && j == 2)) /* VT52 */
  1187.                            set_value[modes_found] =
  1188.                               reset_value[modes_found] = '-';
  1189.                         else set_value[modes_found] =
  1190.                            reset_value[modes_found] = ' ';
  1191.                         mode_puc[modes_found] = i;
  1192.                         mode_number[modes_found++] = j;
  1193.                      }
  1194.                }
  1195.             buf[k] = '\0';
  1196.             if (buf[k - 1] != ' ')
  1197.                {
  1198.                   put_crlf();
  1199.                   ptext(buf);
  1200.                }
  1201.          }
  1202.  
  1203.       if (i = modes_found)
  1204.          {
  1205.             put_crlf();
  1206.             put_crlf();
  1207.             if (tms[0]) ptextln(tms);
  1208.             ptext("Hit 'Y' to test mode set/reset states.");
  1209.             i = wait_here();
  1210.          }
  1211.       if (i == 'y' || i == 'Y')
  1212.          while (1) {
  1213. #ifdef STATUSFIX
  1214.             FILE *fp;
  1215.  
  1216. #ifdef TEDANSI
  1217.             fp = fopen("ted.ansi", "w");
  1218. #else
  1219.             fp = fopen("/dev/console", "w");
  1220. #endif
  1221. #endif
  1222.                for (i = j = 0; j < modes_found; j = ++i >> 1) {
  1223.                   if (set_value[j] == '-') continue;
  1224.                   k = (current_value[j] ^ i) & 1;
  1225.                   sprintf(temp, "\033[%s%d%c\033[%s%d$p",
  1226.                      puc[mode_puc[j]], mode_number[j],
  1227.                      k ? 'l' : 'h',
  1228.                      puc[mode_puc[j]], mode_number[j]);
  1229. #ifdef STATUSFIX
  1230.                   if (fp)
  1231.                      {
  1232.                         fprintf(fp, "%s\n", expand(temp));
  1233.                         fflush(fp);
  1234.                      }
  1235. #endif
  1236.                   putp(temp);
  1237.                   if (!valid_mode(('$' << 8) | 'y')) continue;
  1238.                   if (k) reset_value[j] = ansi_value[1] + '0';
  1239.                   else set_value[j] = ansi_value[1] + '0';
  1240.                }
  1241.             put_str("\033[30l");  /* added for GORT bug (WY-185) */
  1242. #ifdef STATUSFIX
  1243.             if (fp) fclose(fp);
  1244. #endif
  1245.             tty_set();
  1246.             /* print the results */
  1247.             put_clear();
  1248.             putln("mode (initial, set, reset)");
  1249.                for (j = 0; j < modes_found; j++) {
  1250.                   mode_display(puc[mode_puc[j]], mode_number[j],
  1251.                      current_value[j], set_value[j], reset_value[j]);
  1252.                }
  1253.             ptext("\n\nHit 'R' to repeat test.  'S' to sort results.");
  1254.             i = wait_here();
  1255.             if (i == 's' || i == 'S')
  1256.                {  /* print the same stuff, sorted by current_value */
  1257.                   put_crlf();
  1258.                      for (i = '1'; i <= '4'; i++) {
  1259.                            for (j = 0; j < modes_found; j++) {
  1260.                               if (current_value[j] == i)
  1261.                                  mode_display(puc[mode_puc[j]],
  1262.                                     mode_number[j], current_value[j],
  1263.                                     set_value[j], reset_value[j]);
  1264.                            }
  1265.                      }
  1266.                   ptext("\n\nHit 'R' to repeat test.");
  1267.                   i = wait_here();
  1268.                }
  1269.             if (i != 'r' && i != 'R') break;
  1270.             tty_raw(1, char_mask);
  1271.          }
  1272.       else tty_set();
  1273.    }
  1274.  
  1275.  
  1276. test_ansi_reports()
  1277.    {  /* test ansi status reports */
  1278.       int i;
  1279.  
  1280.       put_clear();
  1281.       ptext("Begin ANSI status report testing. ");
  1282.       ptext(" Parity bit set will be displayed in reverse video. ");
  1283.       ptextln(" If the terminal hangs, hit any alphabetic key.");
  1284.       put_crlf();
  1285.       tty_raw(1, char_mask);
  1286.  
  1287.          do {
  1288.             i = read_reports();
  1289.          } while(i == 'r' || i == 'R');
  1290.  
  1291.       if (terminal_class >= 63)
  1292.          {
  1293.                do {
  1294.                   i = request_cfss();
  1295.                } while(i == 'r' || i == 'R');
  1296.             terminal_state();
  1297.          }
  1298.       else tty_set();
  1299.  
  1300.       putln("\nEnd of ANSI status report test.");
  1301.       (void) wait_here();
  1302.    }
  1303.  
  1304.  
  1305. static void
  1306. select_bank(bank)
  1307. char *bank;
  1308.    {  /* select a graphics character set for ANSI terminals */
  1309.       putp(bank);
  1310.       switch (bank[1] & 3) {
  1311.       case 0:
  1312.          putchp('O' & 0x1f);  /* control O */
  1313.          break;
  1314.       case 1:
  1315.          putchp('N' & 0x1f);  /* control N */
  1316.          putp("\033~");
  1317.          break;
  1318.       case 2:
  1319.          putp("\033n\033}");
  1320.          break;
  1321.       case 3:
  1322.          putp("\033o\033|");
  1323.          break;
  1324.       }
  1325.    }
  1326.  
  1327.  
  1328. static void
  1329. show_characters(bank, bias)
  1330. char *bank;
  1331. int bias;
  1332.    {  /* print the ANSI graphics characters */
  1333.       int i;
  1334.  
  1335.       sprintf(temp, "G%d GL   ", bank[1] & 3);
  1336.       ptext(temp);
  1337.       select_bank(bank);
  1338.          for (i = ' '; i < 0x80; i++) {
  1339.             if (char_count >= columns ||
  1340.                (i != ' ' && (i & 31) == 0)) put_str("\n        ");
  1341.             putchp(i + bias);
  1342.          }
  1343.       select_bank(default_bank);
  1344.       put_str("   DEL <");
  1345.       select_bank(bank);
  1346.       putchp(0x7f + bias);
  1347.       select_bank(default_bank);
  1348.       putchp('>');
  1349.       put_crlf();
  1350.       put_crlf();
  1351.    }
  1352.  
  1353.  
  1354. /* ANSI graphics test
  1355.         94     96   character sets
  1356.    G0   (      ,
  1357.    G1   )      -
  1358.    G2   *      .
  1359.    G3   +      /
  1360.  
  1361. Standard Definitions
  1362.    A    UK
  1363.    B    US ASCII
  1364.  
  1365. Dec extended definitions
  1366.    0    Special graphics
  1367.    
  1368.  */
  1369.  
  1370. ansi_graphics()
  1371.    {  /* test ANSI character sets */
  1372.       int j, ch;
  1373.       char bank[32];
  1374.  
  1375.       put_clear();
  1376.       ptext("Enter the bank ()*+,-./ followed by the character set");
  1377.       ptext(" 0123456789:;<=>? for private use, and");
  1378.       ptextln(" @A...Z[\\]^_`a...z{|}~ for standard sets.");
  1379.       strcpy(bank, "\033)0");
  1380.          for ( ; bank[0]; ) {
  1381.             put_crlf();
  1382.             show_characters(bank, 0);
  1383.             /* G0 will not print in GR */
  1384.             if (bank[1] & 3) show_characters(bank, 0x80);
  1385.                for (j = 1; ch = getchp(char_mask); j++) {
  1386.                   if (ch == EOF) break;
  1387.                   putchp(ch);
  1388.                   if (j == 1 && ch > '/') j++;
  1389.                   bank[j] = ch;
  1390.                   if (ch < ' ' | ch > '/') break;
  1391.                   if (j + 1 >= sizeof(bank)) break;
  1392.                }
  1393.             if (j == 1) break;
  1394.             if (bank[j] < '0' || bank[j] > '~') break;
  1395.             bank[j + 1] = '\0';
  1396.          }
  1397.    }
  1398.