home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / vt100 / main.c < prev    next >
C/C++ Source or Header  |  1995-09-11  |  58KB  |  1,994 lines

  1. /*
  2.                                VTTEST.C
  3.  
  4.          Written Novemeber 1983 - July 1984 by Per Lindberg,
  5.          Stockholm University Computer Center (QZ), Sweden.
  6.  
  7.                   THE MAD PROGRAMMER STRIKES AGAIN!
  8.  
  9.                    This software is (c) 1984 by QZ
  10.                Non-commercial use and copying allowed.
  11.  
  12. If you are developing a commercial product, and use this program to do
  13. it, and that product is successful, please send a sum of money of your
  14. choice to the address below.
  15.  
  16. */
  17.  
  18. #include "header.h"
  19.  
  20. char inchar(), *instr(), *lookup();
  21.  
  22. struct table {
  23.     int key;
  24.     char *msg;
  25. } paritytable[] = {
  26.     { 1, "NONE" },
  27.     { 4, "ODD"  },
  28.     { 5, "EVEN" },
  29.     { -1, "" }
  30. },nbitstable[] = {
  31.     { 1, "8" },
  32.     { 2, "7" },
  33.     { -1,"" }
  34. },speedtable[] = {
  35.     {   0,    "50" },
  36.     {   8,    "75" },
  37.     {  16,   "110" },
  38.     {  24,   "132.5"},
  39.     {  32,   "150" },
  40.     {  40,   "200" },
  41.     {  48,   "300" },
  42.     {  56,   "600" },
  43.     {  64,  "1200" },
  44.     {  72,  "1800" },
  45.     {  80,  "2000" },
  46.     {  88,  "2400" },
  47.     {  96,  "3600" },
  48.     { 104,  "4800" },
  49.     { 112,  "9600" },
  50.     { 120, "19200" },
  51.     { -1, "" }
  52. };
  53.  
  54. main() {
  55.  
  56.   int menuchoice;
  57.  
  58.   static char *mainmenu[] = {
  59.       "Exit",
  60.       "Test of cursor movements",
  61.       "Test of screen features",
  62.       "Test of character sets",
  63.       "Test of double-sized characters",
  64.       "Test of keyboard",
  65.       "Test of terminal reports",
  66.       "Test of VT52 mode",
  67.       "Test of VT102 features (Insert/Delete Char/Line)",
  68.       "Test of known bugs",
  69.       "Test of reset and self-test",
  70.       ""
  71.     };
  72.  
  73. #ifdef UNIX
  74.   initterminal(setjmp(intrenv));
  75.   signal(SIGINT, onbrk);
  76.   signal(SIGTERM, onterm);
  77.   reading = 0;
  78. #else
  79.   initterminal(0);
  80. #endif
  81.   do {
  82. #ifdef SARG20
  83.     ttybin(1);    /* set line to binary mode again. It's reset somehow!! */
  84. #endif
  85.     ed(2);
  86.     cup(5,10); printf("VT100 test program, version %s", VERSION);
  87.     cup(7,10); println("Choose test type:");
  88.     menuchoice = menu(mainmenu);
  89.     switch (menuchoice) {
  90.       case 1:  tst_movements();   break;
  91.       case 2:  tst_screen();      break;
  92.       case 3:  tst_characters();  break;
  93.       case 4:  tst_doublesize();  break;
  94.       case 5:  tst_keyboard();    break;
  95.       case 6:  tst_reports();     break;
  96.       case 7:  tst_vt52();        break;
  97.       case 8:  tst_insdel();      break;
  98.       case 9:  tst_bugs();        break;
  99.       case 10: tst_rst();         break;
  100.     }
  101.   } while (menuchoice);
  102.   bye();
  103. }
  104.  
  105. tst_movements() {
  106.  
  107.   /* Test of:
  108.      CUF (Cursor Forward)
  109.      CUB (Cursor Backward)
  110.      CUD (Cursor Down)      IND (Index)  NEL (Next Line)
  111.      CUU (Cursor Up)        RI  (Reverse Index)
  112.      CUP (Cursor Position)  HVP (Horizontal and Vertical Position)
  113.      ED  (Erase in Display)
  114.      EL  (Erase in Line)
  115.      DECALN (Screen Alignment Display)
  116.      <CR> <BS>
  117.      Cursor control characters inside CSI sequences
  118.   */
  119.  
  120.   int i, row, col, pass, width, hlfxtra;
  121.   char c, *ctext = "This is a correct sentence";
  122.  
  123.   for (pass = 0; pass <= 1; pass++) {
  124.     if (pass == 0) { rm("?3"); width =  80; hlfxtra =  0; }
  125.     else           { sm("?3"); width = 132; hlfxtra = 26; }
  126.  
  127.     decaln();
  128.     cup( 9,10+hlfxtra); ed(1);
  129.     cup(18,60+hlfxtra); ed(0); el(1);
  130.     cup( 9,71+hlfxtra); el(0);
  131.     for (row = 10; row <= 16; row++) {
  132.       cup(row, 10+hlfxtra); el(1);
  133.       cup(row, 71+hlfxtra); el(0);
  134.     }
  135.     cup(17,30); el(2);
  136.     for (col = 1; col <= width; col++) {
  137.       hvp(24, col); printf("*");
  138.       hvp( 1, col); printf("*");
  139.     }
  140.     cup(2,2);
  141.     for (row = 2; row <= 23; row++) {
  142.       printf("+");
  143.       cub(1);
  144.       ind();
  145.     }
  146.     cup(23,width-1);
  147.     for (row = 23; row >=2; row--) {
  148.       printf("+");
  149.       cub(1); ri();
  150.     }
  151.     cup(2,1);
  152.     for (row = 2; row <= 23; row++) {
  153.       printf("*");  cup(row, width);
  154.       printf("*");
  155.       cub(10);
  156.       if (row < 10) nel();
  157.       else          printf("\n");
  158.     }
  159.     cup(2,10);
  160.     cub(42+hlfxtra); cuf(2);
  161.     for (col = 3; col <= width-2; col++) {
  162.       printf("+");
  163.       cuf(0); cub(2); cuf(1);
  164.     }
  165.     cup(23,70+hlfxtra);
  166.     cuf(42+hlfxtra); cub(2);
  167.     for (col = width-2; col >= 3; col--) {
  168.       printf("+");
  169.       cub(1); cuf(1); cub(0); printf("%c", 8);
  170.     }
  171.     cup( 1, 1); cuu(10); cuu(1); cuu(0);
  172.     cup(24,width); cud(10); cud(1); cud(0);
  173.  
  174.     cup(10,12+hlfxtra);
  175.     for (row = 10; row <= 15; row++) {
  176.       for (col = 12+hlfxtra; col <= 69+hlfxtra; col++) printf(" ");
  177.       cud(1); cub(58);
  178.     }
  179.     cuu(5); cuf(1);
  180.     printf("The screen should be cleared,  and have an unbroken bor-");
  181.     cup(12,13+hlfxtra);
  182.     printf("der of *'s and +'s around the edge,   and exactly in the");
  183.     cup(13,13+hlfxtra);
  184.     printf("middle  there should be a frame of E's around this  text");
  185.     cup(14,13+hlfxtra);
  186.     printf("with  one (1) free position around it.    ");
  187.     holdit();
  188.   }
  189.   rm("?3");
  190.  
  191.   ed(2);
  192.   cup(1,1);
  193.   println("Test of cursor-control characters inside ESC sequences.");
  194.   println("Below should be two identical lines:");
  195.   println("");
  196.   println("A B C D E F G H I J K L M N O P Q R S");
  197.   for (i = 1; i < 20; i++) {
  198.     printf("%c", 64 + i);
  199.     brcstr("2\010", 'C');    /* Two forward, one backspace */
  200.   }
  201.   println("");
  202.   println("");
  203.   holdit();
  204.  
  205.   ed(2);
  206.   cup(1,1);
  207.   println("Test of leading zeros in ESC sequences.");
  208.   printf("Two lines below you should see the sentence \"%s\".",ctext);
  209.   for (col = 1; *ctext; col++)
  210.    printf("\033[00000000004;00000000%dH%c",col,*ctext++);
  211.   cup(20,1);
  212.   holdit();
  213. }
  214.  
  215. tst_screen() {
  216.  
  217.   /* Test of:
  218.      - DECSTBM (Set Top and Bottom Margins)
  219.      - TBC     (Tabulation Clear)
  220.      - HTS     (Horizontal Tabulation Set)
  221.      - SM RM   (Set/Reset mode): - 80/132 chars
  222.                                  - Origin: Realtive/absolute
  223.                  - Scroll: Smooth/jump
  224.                  - Wraparound
  225.      - SGR     (Select Graphic Rendition)
  226.      - SM RM   (Set/Reset Mode) - Inverse
  227.      - DECSC   (Save Cursor)
  228.      - DECRC   (Restore Cursor)
  229.   */
  230.  
  231.   int i, j, cset, row, col, down, soft, background;
  232.  
  233.   static char *tststr = "*qx`";
  234.   static char *attr[5] = { ";0", ";1", ";4", ";5", ";7" };
  235.  
  236.   cup(1,1);
  237.   sm("?7");  /* Wrap Around ON */
  238.   for (col = 1; col <= 160; col++) printf("*");
  239.   rm("?7");  /* Wrap Around OFF */
  240.   cup(3,1);
  241.   for (col = 1; col <= 160; col++) printf("*");
  242.   sm("?7");  /* Wrap Around ON */
  243.   cup(5,1);
  244.   println("This should be three identical lines of *'s completely filling");
  245.   println("the top of the screen without any empty lines between.");
  246.   println("(Test of WRAP AROUND mode setting.)");
  247.   holdit();
  248.  
  249.   ed(2);
  250.   tbc(3);
  251.   cup(1,1);
  252.   for (col = 1; col <= 78; col += 3) {
  253.     cuf(3); hts();
  254.   }
  255.   cup(1,4);
  256.   for (col = 4; col <= 78; col += 6) {
  257.     tbc(0); cuf(6);
  258.   }
  259.   cup(1,7); tbc(1); tbc(2); /* no-op */
  260.   cup(1,1); for (col = 1; col <= 78; col += 6) printf("\t*");
  261.   cup(2,2); for (col = 2; col <= 78; col += 6) printf("     *");
  262.   cup(4,1);
  263.   println("Test of TAB setting/resetting. These two lines");
  264.   printf("should look the same. ");
  265.   holdit();
  266.   for (background = 0; background <= 1; background++) {
  267.     if (background) rm("?5");
  268.     else            sm("?5");
  269.     sm("?3"); /* 132 cols */
  270.     ed(2);    /* VT100 clears screen on SM3/RM3, but not obviously, so... */
  271.     cup(1,1); tbc(3);
  272.     for (col = 1; col <= 132; col += 8) {
  273.       cuf(8); hts();
  274.     }
  275.     cup(1,1); for (col = 1; col <= 130; col += 10) printf("1234567890");
  276.     printf("12");
  277.     for (row = 3; row <= 20; row++) {
  278.       cup(row,row);
  279.       printf("This is 132 column mode, %s background.",
  280.       background ? "dark" : "light");
  281.     }
  282.     holdit();
  283.     rm("?3"); /* 80 cols */
  284.     ed(2);    /* VT100 clears screen on SM3/RM3, but not obviously, so... */
  285.     cup(1,1); for (col = 1; col <= 80; col += 10) printf("1234567890");
  286.     for (row = 3; row <= 20; row++) {
  287.       cup(row,row);
  288.       printf("This is 80 column mode, %s background.",
  289.       background ? "dark" : "light");
  290.     }
  291.     holdit();
  292.   }
  293.   ed(2);
  294.   sm("?6"); /* Origin mode (relative) */
  295.   for (soft = -1; soft <= 0; soft++) {
  296.     if (soft) sm("?4");
  297.     else      rm("?4");
  298.     for (row = 12; row >= 1; row -= 11) {
  299.       decstbm(row, 24-row+1);
  300.       ed(2);
  301.       for (down = 0; down >= -1; down--) {
  302.         if (down) cuu(24);
  303.     else      cud(24);
  304.     for (i = 1; i <= 30; i++) {
  305.       printf("%s scroll %s region %d Line %d\n",
  306.          soft ? "Soft" : "Jump",
  307.          down ? "down" : "up",
  308.          2*(13-row), i);
  309.       if (down) { ri(); ri(); }
  310.     }
  311.       }
  312.       holdit();
  313.     }
  314.   }
  315.   ed(2);
  316.   decstbm(23,24);
  317.   printf(
  318.   "\nOrigin mode test. This line should be at the bottom of the screen.");
  319.   cup(1,1);
  320.   printf("%s",
  321.   "This line should be the one above the bottom of the screeen. ");
  322.   holdit();
  323.   ed(2);
  324.   rm("?6"); /* Origin mode (absolute) */
  325.   cup(24,1);
  326.   printf(
  327.   "Origin mode test. This line should be at the bottom of the screen.");
  328.   cup(1,1);
  329.   printf("%s", "This line should be at the top if the screen. ");
  330.   holdit();
  331.   decstbm(1,24);
  332.  
  333.   ed(2);
  334.   cup( 1,20); printf("Graphic rendition test pattern:");
  335.   cup( 4, 1); sgr("0");         printf("vanilla");
  336.   cup( 4,40); sgr("0;1");       printf("bold");
  337.   cup( 6, 6); sgr(";4");        printf("underline");
  338.   cup( 6,45);sgr(";1");sgr("4");printf("bold underline");
  339.   cup( 8, 1); sgr("0;5");       printf("blink");
  340.   cup( 8,40); sgr("0;5;1");     printf("bold blink");
  341.   cup(10, 6); sgr("0;4;5");     printf("underline blink");
  342.   cup(10,45); sgr("0;1;4;5");   printf("bold underline blink");
  343.   cup(12, 1); sgr("1;4;5;0;7"); printf("negative");
  344.   cup(12,40); sgr("0;1;7");     printf("bold negative");
  345.   cup(14, 6); sgr("0;4;7");     printf("underline negative");
  346.   cup(14,45); sgr("0;1;4;7");   printf("bold underline negative");
  347.   cup(16, 1); sgr("1;4;;5;7");  printf("blink negative");
  348.   cup(16,40); sgr("0;1;5;7");   printf("bold blink negative");
  349.   cup(18, 6); sgr("0;4;5;7");   printf("underline blink negative");
  350.   cup(18,45); sgr("0;1;4;5;7"); printf("bold underline blink negative");
  351.   sgr("");
  352.  
  353.   rm("?5"); /* Inverse video off */
  354.   cup(23,1); el(0); printf("Dark background. "); holdit();
  355.   sm("?5"); /* Inverse video */
  356.   cup(23,1); el(0); printf("Light background. "); holdit();
  357.   rm("?5");
  358.   ed(2);
  359.   cup(8,12); printf("normal");
  360.   cup(8,24); printf("bold");
  361.   cup(8,36); printf("underscored");
  362.   cup(8,48); printf("blinking");
  363.   cup(8,60); printf("reversed");
  364.   cup(10,1); printf("stars:");
  365.   cup(12,1); printf("line:");
  366.   cup(14,1); printf("x'es:");
  367.   cup(16,1); printf("diamonds:");
  368.   for (cset = 0; cset <= 3; cset++) {
  369.     for (i = 0; i <= 4; i++) {
  370.     cup(10 + 2 * cset, 12 + 12 * i);
  371.     sgr(attr[i]);
  372.     if (cset == 0 || cset == 2) scs(0,'B');
  373.     else                        scs(0,'0');
  374.       for (j = 0; j <= 4; j++) {
  375.         printf("%c", tststr[cset]);
  376.       }
  377.       decsc();
  378.       cup(cset + 1, i + 1); sgr(""); scs(0,'B'); printf("A");
  379.       decrc();
  380.       for (j = 0; j <= 4; j++) {
  381.         printf("%c", tststr[cset]);
  382.       }
  383.     }
  384.   }
  385.   sgr("0"); scs(0,'B'); cup(21,1);
  386.   println("Test of the SAVE/RESTORE CURSOR feature. There should");
  387.   println("be ten characters of each flavour, and a rectangle");
  388.   println("of 5 x 4 A's filling the top left of the screen.");
  389.   holdit();
  390. }
  391.  
  392. tst_characters() {
  393.   /* Test of:
  394.      SCS    (Select character Set)
  395.   */
  396.  
  397.   int i, j, g, cset;
  398.   char chcode[5], *setmsg[5];
  399.  
  400.   chcode[0] = 'A';
  401.   chcode[1] = 'B';
  402.   chcode[2] = '0';
  403.   chcode[3] = '1';
  404.   chcode[4] = '2';
  405.   setmsg[0] = "UK / national";
  406.   setmsg[1] = "US ASCII";
  407.   setmsg[2] = "Special graphics and line drawing";
  408.   setmsg[3] = "Alternate character ROM standard characters";
  409.   setmsg[4] = "Alternate character ROM special graphics";
  410.  
  411.   cup(1,10); printf("Selected as G0 (with SI)");
  412.   cup(1,48); printf("Selected as G1 (with SO)");
  413.   for (cset = 0; cset <= 4; cset++) {
  414.     scs(1,'B');
  415.     cup(3 + 4 * cset, 1);
  416.     sgr("1");
  417.     printf("Character set %c (%s)",chcode[cset], setmsg[cset]);
  418.     sgr("0");
  419.     for (g = 0; g <= 1; g++) {
  420.       scs(g,chcode[cset]);
  421.       for (i = 1; i <= 3; i++) {
  422.         cup(3 + 4 * cset + i, 10 + 38 * g);
  423.         for (j = 0; j <= 31; j++) {
  424.       printf("%c", i * 32 + j);
  425.     }
  426.       }
  427.     }
  428.   }
  429.   scs(1,'B');
  430.   cup(24,1); printf("These are the installed character sets. ");
  431.   holdit();
  432. }
  433.  
  434. tst_doublesize() {
  435.   /* Test of:
  436.      DECSWL  (Single Width Line)
  437.      DECDWL  (Double Width Line)
  438.      DECDHL  (Double Height Line) (also implicit double width)
  439.   */
  440.  
  441.   int col, i, w, w1;
  442.  
  443.   /* Print the test pattern in both 80 and 132 character width  */
  444.  
  445.   for(w = 0; w <= 1; w++) {
  446.     w1 = 13 * w;
  447.  
  448.     ed(2);
  449.     cup(1, 1);
  450.     if (w) { sm("?3"); printf("132 column mode"); }
  451.     else   { rm("?3"); printf(" 80 column mode"); }
  452.  
  453.     cup( 5, 3 + 2 * w1);
  454.     printf("v------- left margin");
  455.  
  456.     cup( 7, 3 + 2 * w1);
  457.     printf("This is a normal-sized line");
  458.     decdhl(0); decdhl(1); decdwl(); decswl();
  459.  
  460.     cup( 9, 2 + w1);
  461.     printf("This is a Double-width line");
  462.     decswl(); decdhl(0); decdhl(1); decdwl();
  463.  
  464.     cup(11, 2 + w1);
  465.     decdwl(); decswl(); decdhl(1); decdhl(0);
  466.     printf("This is a Double-width-and-height line");
  467.     cup(12, 2 + w1);
  468.     decdwl(); decswl(); decdhl(0); decdhl(1);
  469.     printf("This is a Double-width-and-height line");
  470.  
  471.     cup(14, 2 + w1);
  472.     decdwl(); decswl(); decdhl(1); decdhl(0); el(2);
  473.     printf("This is another such line");
  474.     cup(15, 2 + w1);
  475.     decdwl(); decswl(); decdhl(0); decdhl(1);
  476.     printf("This is another such line");
  477.  
  478.     cup(17, 3 + 2 * w1);
  479.     printf("^------- left margin");
  480.  
  481.     cup(21, 1);
  482.     printf("This is not a double-width line");
  483.     for (i = 0; i <= 1; i++) {
  484.       cup(21,6);
  485.       if (i) { printf("**is**"); decdwl(); }
  486.       else   { printf("is not"); decswl(); }
  487.       cup(23,1); holdit();
  488.     }
  489.   }
  490.   /* Set vanilla tabs for next test */
  491.   cup(1,1); tbc(3); for (col = 1; col <= 132; col += 8) { cuf(8); hts(); }
  492.   rm("?3");
  493.   ed(2);
  494.   scs(0,'0');
  495.  
  496.   cup( 8,1); decdhl(0); printf("lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk");
  497.   cup( 9,1); decdhl(1); printf("lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk");
  498.   cup(10,1); decdhl(0); printf("x%c%c%c%c%cx",9,9,9,9,9);
  499.   cup(11,1); decdhl(1); printf("x%c%c%c%c%cx",9,9,9,9,9);
  500.   cup(12,1); decdhl(0); printf("x%c%c%c%c%cx",9,9,9,9,9);
  501.   cup(13,1); decdhl(1); printf("x%c%c%c%c%cx",9,9,9,9,9);
  502.   cup(14,1); decdhl(0); printf("x                                      x");
  503.   cup(15,1); decdhl(1); printf("x                                      x");
  504.   cup(16,1); decdhl(0); printf("mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj");
  505.   cup(17,1); decdhl(1); printf("mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj");
  506.   scs(0,'B'); sgr("1;5");
  507.   cup(12,3);
  508.   printf("* The mad programmer strikes again * ");
  509.   cup(13,3); printf("%c",9); cub(6);
  510.   printf("* The mad programmer strikes again *");
  511.   sgr("0");
  512.   cup(22,1);
  513.   println("Another test pattern...  a frame with blinking bold text,");
  514.   printf("all in double-height double-width size. ");
  515.   holdit();
  516.  
  517.   decstbm(8,24); /* Absolute origin mode, so cursor is set at (1,1) */
  518.   cup(8,1);
  519.   for (i = 1; i <= 12; i++)
  520.     ri();
  521.   decstbm(0,0);    /* No scroll region    */
  522.   cup(1,1);
  523.   printf("%s", "Exactly half of the box should remain. ");
  524.   holdit();
  525. }
  526.  
  527. tst_keyboard() {
  528.  
  529. /* Test of:
  530.      - DECLL   (Load LEDs)
  531.      - Keyboard return messages
  532.      - SM RM   (Set/Reset Mode) - Cursor Keys
  533.                                 - Auto repeat
  534.      - DECKPAM (Keypad Application Mode)
  535.      - DECKPNM (Keypad Numeric Mode)
  536.  
  537. The standard VT100 keayboard layout:
  538.  
  539.                                                         UP   DN   LE  RI
  540.  
  541. ESC   1!   2@   3#   4$   5%   6^   7&   8*   9(   0)   -_   =+   `~  BS
  542.  
  543. TAB*    qQ   wW   eE   rR   tT   yY   uU   iI   oO   pP   [{   ]}      DEL
  544.  
  545. **   **   aA   sS   dD   fF   gG   hH   jJ   kK   lL   ;:   ,"   RETN  \|
  546.  
  547. **   ****   zZ   xX   cC   vV   bB   nN   mM   ,<   .>   /?   ****   LF
  548.  
  549.              ****************SPACE BAR****************
  550.  
  551.                                                            PF1 PF2 PF3 PF4
  552.  
  553.                                                            *7* *8* *9* *-*
  554.  
  555.                                                            *4* *5* *6* *,*
  556.  
  557.                                                            *1* *2* *3*
  558.  
  559.                                                            ***0*** *.* ENT
  560. */
  561.  
  562.   char *ledmsg[6], *ledseq[6];
  563.  
  564.   int  i, j, okflag;
  565.   int  kblayout;
  566.   int  ckeymode;
  567.   int  fkeymode;
  568.   char kbdc;
  569.   char *kbds = " ";
  570.   char *curkeystr, *fnkeystr, *abmstr;
  571.   char arptstring[500];
  572.  
  573.   static struct key {
  574.       char c;
  575.       int  row;
  576.       int  col;
  577.       char *symbol;
  578.   } keytab [] = {
  579.       { 27, 1,  0, "ESC" },
  580.       { '1', 1,  6, "1" },    { '!', 1,  7, "!" },
  581.       { '2', 1, 11, "2" },    { '@', 1, 12, "@" },
  582.       { '3', 1, 16, "3" },    { '#', 1, 17, "#" },
  583.       { '4', 1, 21, "4" },    { '$', 1, 22, "$" },
  584.       { '5', 1, 26, "5" },    {'\%', 1, 27, "%" },
  585.       { '6', 1, 31, "6" },    { '^', 1, 32, "^" },
  586.       { '7', 1, 36, "7" },    { '&', 1, 37, "&" },
  587.       { '8', 1, 41, "8" },    { '*', 1, 42, "*" },
  588.       { '9', 1, 46, "9" },    { '(', 1, 47, "(" },
  589.       { '0', 1, 51, "0" },    { ')', 1, 52, ")" },
  590.       { '-', 1, 56, "-" },    { '_', 1, 57, "_" },
  591.       { '=', 1, 61, "=" },    { '+', 1, 62, "+" },
  592.       { '`', 1, 66, "`" },    { '~', 1, 67, "~" },
  593.       {   8, 1, 70, "BS" },
  594.       {   9, 2,  0, " TAB " },
  595.       { 'q', 2,  8, "q" },    { 'Q', 2,  9, "Q" },
  596.       { 'w', 2, 13, "w" },    { 'W', 2, 14, "W" },
  597.       { 'e', 2, 18, "e" },    { 'E', 2, 19, "E" },
  598.       { 'r', 2, 23, "r" },    { 'R', 2, 24, "R" },
  599.       { 't', 2, 28, "t" },    { 'T', 2, 29, "T" },
  600.       { 'y', 2, 33, "y" },    { 'Y', 2, 34, "Y" },
  601.       { 'u', 2, 38, "u" },    { 'U', 2, 39, "U" },
  602.       { 'i', 2, 43, "i" },    { 'I', 2, 44, "I" },
  603.       { 'o', 2, 48, "o" },    { 'O', 2, 49, "O" },
  604.       { 'p', 2, 53, "p" },    { 'P', 2, 54, "P" },
  605.       { '[', 2, 58, "[" },    { '{', 2, 59, "{" },
  606.       { ']', 2, 63, "]" },    { '}', 2, 64, "}" },
  607.       { 127, 2, 71, "DEL" },
  608.       { 'a', 3, 10, "a" },    { 'A', 3, 11, "A" },
  609.       { 's', 3, 15, "s" },    { 'S', 3, 16, "S" },
  610.       { 'd', 3, 20, "d" },    { 'D', 3, 21, "D" },
  611.       { 'f', 3, 25, "f" },    { 'F', 3, 26, "F" },
  612.       { 'g', 3, 30, "g" },    { 'G', 3, 31, "G" },
  613.       { 'h', 3, 35, "h" },    { 'H', 3, 36, "H" },
  614.       { 'j', 3, 40, "j" },    { 'J', 3, 41, "J" },
  615.       { 'k', 3, 45, "k" },    { 'K', 3, 46, "K" },
  616.       { 'l', 3, 50, "l" },    { 'L', 3, 51, "L" },
  617.       { ';', 3, 55, ";" },    { ':', 3, 56, ":" },
  618.       {'\'', 3, 60, "'" },    { '"', 3, 61,"\"" },
  619.       {  13, 3, 65, "RETN"},
  620.       {'\\', 3, 71,"\\" },    { '|', 3, 72, "|" },
  621.       { 'z', 4, 12, "z" },    { 'Z', 4, 13, "Z" },
  622.       { 'x', 4, 17, "x" },    { 'X', 4, 18, "X" },
  623.       { 'c', 4, 22, "c" },    { 'C', 4, 23, "C" },
  624.       { 'v', 4, 27, "v" },    { 'V', 4, 28, "V" },
  625.       { 'b', 4, 32, "b" },    { 'B', 4, 33, "B" },
  626.       { 'n', 4, 37, "n" },    { 'N', 4, 38, "N" },
  627.       { 'm', 4, 42, "m" },    { 'M', 4, 43, "M" },
  628.       { ',', 4, 47, "," },    { '<', 4, 48, "<" },
  629.       { '.', 4, 52, "." },    { '>', 4, 53, ">" },
  630.       { '/', 4, 57, "/" },    { '?', 4, 58, "?" },
  631.       {  10, 4, 69, "LF" },
  632.       { ' ', 5, 13, "                SPACE BAR                "},
  633.       {'\0', 0,  0, ""  }
  634.     };
  635.  
  636.   static struct natkey {
  637.       char natc;
  638.       int  natrow;
  639.       int  natcol;
  640.       char *natsymbol;
  641.   } natkeytab [][29] = {
  642.       {
  643.         { '"', 1, 12, "\""},
  644.         { '&', 1, 32, "&" },
  645.         { '/', 1, 37, "/" },
  646.         { '(', 1, 42, "(" },
  647.         { ')', 1, 47, ")" },
  648.         { '=', 1, 52, "=" },
  649.         { '+', 1, 56, "+" },    { '?', 1, 57, "?" },
  650.         { '`', 1, 61, "`" },    { '@', 1, 62, "@" },
  651.         { '<', 1, 66, "<" },    { '>', 1, 67, ">" },
  652.         { '}', 2, 58, "}" },    { ']', 2, 59, "]" },
  653.         { '^', 2, 63, "^" },    { '~', 2, 64, "~" },
  654.         { '|', 3, 55, "|" },    {'\\', 3, 56,"\\" },
  655.         { '{', 3, 60, "{" },    { '[', 3, 61, "[" },
  656.         {'\'', 3, 71, "'" },    { '*', 3, 72, "*" },
  657.         { ',', 4, 47, "," },    { ';', 4, 48, ";" },
  658.         { '.', 4, 52, "." },    { ':', 4, 53, ":" },
  659.         { '-', 4, 57, "-" },    { '_', 4, 58, "_" },
  660.         {'\0', 0,  0, ""  }
  661.       },
  662.       {
  663.         { '"', 1, 12, "\""},
  664.         { '&', 1, 32, "&" },
  665.         { '/', 1, 37, "/" },
  666.         { '(', 1, 42, "(" },
  667.         { ')', 1, 47, ")" },
  668.         { '=', 1, 52, "=" },
  669.         { '+', 1, 56, "+" },    { '?', 1, 57, "?" },
  670.         { '`', 1, 61, "`" },    { '@', 1, 62, "@" },
  671.         { '<', 1, 66, "<" },    { '>', 1, 67, ">" },
  672.         { '}', 2, 58, "}" },    { ']', 2, 59, "]" },
  673.         { '~', 2, 63, "~" },    { '^', 2, 64, "^" },
  674.         { '|', 3, 55, "|" },    {'\\', 3, 56,"\\" },
  675.         { '{', 3, 60, "{" },    { '[', 3, 61, "[" },
  676.         {'\'', 3, 71, "'" },    { '*', 3, 72, "*" },
  677.         { ',', 4, 47, "," },    { ';', 4, 48, ";" },
  678.         { '.', 4, 52, "." },    { ':', 4, 53, ":" },
  679.         { '-', 4, 57, "-" },    { '_', 4, 58, "_" },
  680.         {'\0', 0,  0, ""  }
  681.       }
  682.   };
  683.  
  684.   static struct curkey {
  685.       char *curkeymsg[3];
  686.       int  curkeyrow;
  687.       int  curkeycol;
  688.       char *curkeysymbol;
  689.       char *curkeyname;
  690.   } curkeytab [] = {
  691.  
  692.       /* A Reset, A Set,  VT52  */
  693.  
  694.       {{"\033[A","\033OA","\033A"}, 0, 56, "UP",  "Up arrow"   },
  695.       {{"\033[B","\033OB","\033B"}, 0, 61, "DN",  "Down arrow" },
  696.       {{"\033[D","\033OD","\033D"}, 0, 66, "LT",  "Left arrow" },
  697.       {{"\033[C","\033OC","\033C"}, 0, 71, "RT",  "Right arrow"},
  698.       {{"",      "",       ""     }, 0,  0, "",    "" }
  699.   };
  700.  
  701.   static struct fnkey {
  702.       char *fnkeymsg[4];
  703.       int  fnkeyrow;
  704.       int  fnkeycol;
  705.       char *fnkeysymbol;
  706.       char *fnkeyname;
  707.   } fnkeytab [] = {
  708.  
  709.       /* ANSI-num,ANSI-app,VT52-nu,VT52-ap,  r, c,  symb   name         */
  710.  
  711.       {{"\033OP","\033OP","\033P","\033P" }, 6, 59, "PF1", "PF1"        },
  712.       {{"\033OQ","\033OQ","\033Q","\033Q" }, 6, 63, "PF2", "PF2"        },
  713.       {{"\033OR","\033OR","\033R","\033R" }, 6, 67, "PF3", "PF3"        },
  714.       {{"\033OS","\033OS","\033S","\033S" }, 6, 71, "PF4", "PF4"        },
  715.       {{"7",     "\033Ow","7",    "\033?w"}, 7, 59, " 7 ", "Numeric 7"  },
  716.       {{"8",     "\033Ox","8",    "\033?x"}, 7, 63, " 8 ", "Numeric 8"  },
  717.       {{"9",     "\033Oy","9",    "\033?y"}, 7, 67, " 9 ", "Numeric 9"  },
  718.       {{"-",     "\033Om","-",    "\033?m"}, 7, 71, " - ", "Minus"      },
  719.       {{"4",     "\033Ot","4",    "\033?t"}, 8, 59, " 4 ", "Numeric 4"  },
  720.       {{"5",     "\033Ou","5",    "\033?u"}, 8, 63, " 5 ", "Numeric 5"  },
  721.       {{"6",     "\033Ov","6",    "\033?v"}, 8, 67, " 6 ", "Numeric 6"  },
  722.       {{",",     "\033Ol",",",    "\033?l"}, 8, 71, " , ", "Comma"      },
  723.       {{"1",     "\033Oq","1",    "\033?q"}, 9, 59, " 1 ", "Numeric 1"  },
  724.       {{"2",     "\033Or","2",    "\033?r"}, 9, 63, " 2 ", "Numeric 2"  },
  725.       {{"3",     "\033Os","3",    "\033?s"}, 9, 67, " 3 ", "Numeric 3"  },
  726.       {{"0",     "\033Op","0",    "\033?p"},10, 59,"   O   ","Numeric 0"},
  727.       {{".",     "\033On",".",    "\033?n"},10, 67, " . ", "Point"      },
  728.       {{"\015",  "\033OM","\015", "\033?M"},10, 71, "ENT", "ENTER"      },
  729.       {{"","","",""},       0,  0, "",    ""           }
  730.     };
  731.  
  732.   static struct ckey {
  733.       int  ccount;
  734.       char *csymbol;
  735.   } ckeytab [] = {
  736.       { 0, "NUL (CTRL-@ or CTRL-Space)" },
  737.       { 0, "SOH (CTRL-A)" },
  738.       { 0, "STX (CTRL-B)" },
  739.       { 0, "ETX (CTRL-C)" },
  740.       { 0, "EOT (CTRL-D)" },
  741.       { 0, "ENQ (CTRL-E)" },
  742.       { 0, "ACK (CTRL-F)" },
  743.       { 0, "BEL (CTRL-G)" },
  744.       { 0, "BS  (CTRL-H) (BACK SPACE)" },
  745.       { 0, "HT  (CTRL-I) (TAB)" },
  746.       { 0, "LF  (CTRL-J) (LINE FEED)" },
  747.       { 0, "VT  (CTRL-K)" },
  748.       { 0, "FF  (CTRL-L)" },
  749.       { 0, "CR  (CTRL-M) (RETURN)" },
  750.       { 0, "SO  (CTRL-N)" },
  751.       { 0, "SI  (CTRL-O)" },
  752.       { 0, "DLE (CTRL-P)" },
  753.       { 0, "DC1 (CTRL-Q) (X-On)" },
  754.       { 0, "DC2 (CTRL-R)" },
  755.       { 0, "DC3 (CTRL-S) (X-Off)" },
  756.       { 0, "DC4 (CTRL-T)" },
  757.       { 0, "NAK (CTRL-U)" },
  758.       { 0, "SYN (CTRL-V)" },
  759.       { 0, "ETB (CTRL-W)" },
  760.       { 0, "CAN (CTRL-X)" },
  761.       { 0, "EM  (CTRL-Y)" },
  762.       { 0, "SUB (CTRL-Z)" },
  763.       { 0, "ESC (CTRL-[) (ESCAPE)" },
  764.       { 0, "FS  (CTRL-\\ or CTRL-? or CTRL-_)" },
  765.       { 0, "GS  (CTRL-])" },
  766.       { 0, "RS  (CTRL-^ or CTRL-~ or CTRL-`)" },
  767.       { 0, "US  (CTRL-_ or CTRL-?)" }
  768.   };
  769.  
  770.   static char *keyboardmenu[] = {
  771.       "Standard American ASCII layout",
  772.       "Swedish national layout D47",
  773.       "Swedish national layout E47",
  774.       /* add new keyboard layouts here */
  775.       ""
  776.     };
  777.  
  778.   static char *curkeymodes[3] = {
  779.       "ANSI / Cursor key mode RESET",
  780.       "ANSI / Cursor key mode SET",
  781.       "VT52 Mode"
  782.   };
  783.  
  784.   static char *fnkeymodes[4] = {
  785.       "ANSI Numeric mode",
  786.       "ANSI Application mode",
  787.       "VT52 Numeric mode",
  788.       "VT52 Application mode"
  789.   };
  790.  
  791.   ledmsg[0] = "L1 L2 L3 L4"; ledseq[0] = "1;2;3;4";
  792.   ledmsg[1] = "   L2 L3 L4"; ledseq[1] = "1;0;4;3;2";
  793.   ledmsg[2] = "   L2 L3";    ledseq[2] = "1;4;;2;3";
  794.   ledmsg[3] = "L1 L2";       ledseq[3] = ";;2;1";
  795.   ledmsg[4] = "L1";          ledseq[4] = "1";
  796.   ledmsg[5] = "";            ledseq[5] = "";
  797.  
  798. #ifdef UNIX
  799.   fflush(stdout);
  800. #endif
  801.   ed(2);
  802.   cup(10,1);
  803.   println("These LEDs (\"lamps\") on the keyboard should be on:");
  804.   for (i = 0; i <= 5; i++) {
  805.     cup(10,52); el(0); printf("%s", ledmsg[i]);
  806.     decll("0");
  807.     decll(ledseq[i]);
  808.     cup(12,1); holdit();
  809.   }
  810.  
  811.   ed(2);
  812.   cup(10,1);
  813.   println("Test of the AUTO REPEAT feature");
  814.   println("");
  815.   println("Hold down an alphanumeric key for a while, then push RETURN.");
  816.   printf("%s", "Auto Repeat OFF: ");
  817.   rm("?8");
  818.   inputline(arptstring);
  819.   if (strlen(arptstring) == 0)      println("No characters read!??");
  820.   else if (strlen(arptstring) == 1) println("OK.");
  821.   else                              println("Too many characters read.");
  822.   println("");
  823.   println("Hold down an alphanumeric key for a while, then push RETURN.");
  824.   printf("%s", "Auto Repeat ON: ");
  825.   sm("?8");
  826.   inputline(arptstring);
  827.   if (strlen(arptstring) == 0)      println("No characters read!??");
  828.   else if (strlen(arptstring) == 1) println("Not enough characters read.");
  829.   else                              println("OK.");
  830.   println("");
  831.   holdit();
  832.  
  833.   ed(2);
  834.   cup(5,10);
  835.   println("Choose keyboard layout:");
  836.   kblayout = menu(keyboardmenu);
  837.   if (kblayout) {
  838.     kblayout--;
  839.     for (j = 0; natkeytab[kblayout][j].natc != '\0'; j++) {
  840.       for (i = 0; keytab[i].c != '\0'; i++) {
  841.     if (keytab[i].row == natkeytab[kblayout][j].natrow &&
  842.         keytab[i].col == natkeytab[kblayout][j].natcol) {
  843.       keytab[i].c = natkeytab[kblayout][j].natc;
  844.       keytab[i].symbol = natkeytab[kblayout][j].natsymbol;
  845.       break;
  846.     }
  847.       }
  848.     }
  849.   }
  850.  
  851.   ed(2);
  852.   for (i = 0; keytab[i].c != '\0'; i++) {
  853.     cup(1 + 2 * keytab[i].row, 1 + keytab[i].col);
  854.     sgr("7");
  855.     printf("%s", keytab[i].symbol);
  856.     sgr("");
  857.   }
  858.   cup(22,1);
  859. #ifdef UNIX
  860.   sgttyNew.sg_flags &= ~CRMOD;
  861.   sgttyNew.sg_flags &= ~ECHO;
  862.   stty(0, &sgttyNew);
  863. #endif
  864.   inflush();
  865.   printf("Press each key, both shifted and unshifted. Finish with RETURN:");
  866.   do { /* while (kbdc != 13) */
  867.     cup(23,1); kbdc = inchar();
  868.     cup(23,1); el(0);
  869.     sprintf(kbds, "%c", kbdc);
  870.     chrprint(kbds);
  871.     for (i = 0; keytab[i].c != '\0'; i++) {
  872.       if (keytab[i].c == kbdc) {
  873.         cup(1 + 2 * keytab[i].row, 1 + keytab[i].col);
  874.     printf("%s", keytab[i].symbol);
  875.     break;
  876.       }
  877.     }
  878.   } while (kbdc != 13);
  879. #ifdef SARG10
  880.   inchar();  /* Local hack: Read LF that TOPS-10 adds to CR */
  881. #endif
  882.   cup(23,1); el(0);
  883.  
  884.   for (ckeymode = 0; ckeymode <= 2; ckeymode++) {
  885.     if (ckeymode) sm("?1");
  886.     else            rm("?1");
  887.     for (i = 0; curkeytab[i].curkeysymbol[0] != '\0'; i++) {
  888.       cup(1 + 2 * curkeytab[i].curkeyrow, 1 + curkeytab[i].curkeycol);
  889.       sgr("7");
  890.       printf("%s", curkeytab[i].curkeysymbol);
  891.       sgr("");
  892.     }
  893.     cup(20,1); printf("<%s>%20s", curkeymodes[ckeymode], "");
  894.     cup(22,1); el(0);
  895.     cup(22,1); printf("%s", "Press each cursor key. Finish with TAB.");
  896.     for(;;) {
  897.       cup(23,1);
  898.       if (ckeymode == 2) rm("?2"); /* VT52 mode */
  899.       curkeystr = instr();
  900.       esc("<");                      /* ANSI mode */
  901.       cup(23,1); el(0);
  902.       cup(23,1); chrprint(curkeystr);
  903.       if (!strcmp(curkeystr,"\t")) break;
  904.       for (i = 0; curkeytab[i].curkeysymbol[0] != '\0'; i++) {
  905.     if (!strcmp(curkeystr,curkeytab[i].curkeymsg[ckeymode])) {
  906.       sgr("7");
  907.       printf(" (%s key) ", curkeytab[i].curkeyname);
  908.       sgr("");
  909.       cup(1 + 2 * curkeytab[i].curkeyrow,
  910.           1 + curkeytab[i].curkeycol);
  911.       printf("%s", curkeytab[i].curkeysymbol);
  912.       break;
  913.     }
  914.       }
  915.       if (i == sizeof(curkeytab) / sizeof(struct curkey) - 1) {
  916.     sgr("7");
  917.     printf("%s", " (Unknown cursor key) ");
  918.     sgr("");
  919.       }
  920.     }
  921.   }
  922.  
  923.   for (fkeymode = 0; fkeymode <= 3; fkeymode++) {
  924.     for (i = 0; fnkeytab[i].fnkeysymbol[0] != '\0'; i++) {
  925.       cup(1 + 2 * fnkeytab[i].fnkeyrow, 1 + fnkeytab[i].fnkeycol);
  926.       sgr("7");
  927.       printf("%s", fnkeytab[i].fnkeysymbol);
  928.       sgr("");
  929.     }
  930.     cup(20,1); printf("<%s>%20s", fnkeymodes[fkeymode], "");
  931.     cup(22,1); el(0);
  932.     cup(22,1); printf("%s", "Press each function key. Finish with TAB.");
  933.     for(;;) {
  934.       cup(23,1);
  935.       if (fkeymode >= 2)  rm("?2");    /* VT52 mode */
  936.       if (fkeymode % 2)   deckpam();   /* Application mode */
  937.       else                 deckpnm();    /* Numeric mode     */
  938.       fnkeystr = instr();
  939.       esc("<");                /* ANSI mode */
  940.       cup(23,1); el(0);
  941.       cup(23,1); chrprint(fnkeystr);
  942.       if (!strcmp(fnkeystr,"\t")) break;
  943.       for (i = 0; fnkeytab[i].fnkeysymbol[0] != '\0'; i++) {
  944.     if (!strcmp(fnkeystr,fnkeytab[i].fnkeymsg[fkeymode])) {
  945.       sgr("7");
  946.       printf(" (%s key) ", fnkeytab[i].fnkeyname);
  947.       sgr("");
  948.       cup(1 + 2 * fnkeytab[i].fnkeyrow, 1 + fnkeytab[i].fnkeycol);
  949.       printf("%s", fnkeytab[i].fnkeysymbol);
  950.       break;
  951.     }
  952.       }
  953.       if (i == sizeof(fnkeytab) / sizeof(struct fnkey) - 1) {
  954.     sgr("7");
  955.     printf("%s", " (Unknown function key) ");
  956.     sgr("");
  957.       }
  958.     }
  959.   }
  960.  
  961. #ifdef UNIX
  962.   sgttyNew.sg_flags |= CRMOD;
  963.   stty(0, &sgttyNew);
  964. #endif
  965.   ed(2);
  966.   cup(5,1);
  967.   println("Finally, a check of the ANSWERBACK MESSAGE, which can be sent");
  968.   println("by pressing CTRL-BREAK. The answerback message can be loaded");
  969.   println("in SET-UP B by pressing SHIFT-A and typing e.g.");
  970.   println("");
  971.   println("         \" H e l l o , w o r l d Return \"");
  972.   println("");
  973.   println("(the double-quote characters included).  Do that, and then try");
  974.   println("to send an answerback message with CTRL-BREAK.  If it works,");
  975.   println("the answerback message should be displayed in reverse mode.");
  976.   println("Finish with a single RETURN.");
  977.  
  978. #ifdef UNIX
  979.   sgttyNew.sg_flags &= ~CRMOD;
  980.   stty(0, &sgttyNew);
  981. #endif
  982.   do {
  983.     cup(17,1);
  984.     inflush();
  985.     abmstr = instr();
  986.     cup(17,1);
  987.     el(0);
  988.     chrprint(abmstr);
  989.   } while (strcmp(abmstr,"\r"));
  990.  
  991.   ed(2);
  992.   for (i = 0; i < 32; i++) {
  993.     cup(1 + (i % 16), 1 + 40 * (i / 16));
  994.     sgr("7");
  995.     printf("%s", ckeytab[i].csymbol);
  996.     sgr("0");
  997.   }
  998.   cup(19,1);
  999. #ifdef UNIX
  1000.   sgttyNew.sg_flags |= CRMOD;
  1001.   stty(0, &sgttyNew);
  1002. #endif
  1003.   println(
  1004.   "Push each CTRL-key TWICE. Note that you should be able to send *all*");
  1005.   println(
  1006.   "CTRL-codes twice, including CTRL-S (X-Off) and CTRL-Q (X-Off)!");
  1007.   println(
  1008.   "Finish with DEL (also called DELETE or RUB OUT), or wait 1 minute.");
  1009. #ifdef UNIX
  1010. #ifdef SIII
  1011.   sgttyNew.sg_flags &= ~CBREAK;
  1012.   stty(0, &sgttyNew);
  1013. #endif
  1014.   sgttyNew.sg_flags |= RAW;
  1015.   stty(0, &sgttyNew);
  1016. #endif
  1017.   ttybin(1);
  1018. #ifdef SARG20
  1019.   page(0);    /* Turn off all character processing at input */
  1020.   superbin(1);    /* Turn off ^C (among others). Keep your fingers crossed!! */
  1021. #endif
  1022.   do {
  1023.     cup(23,1); kbdc = inchar();
  1024.     cup(23,1); el(0);
  1025.     if (kbdc < 32) printf("  %s", ckeytab[kbdc].csymbol);
  1026.     else {
  1027.       sprintf(kbds, "%c", kbdc);
  1028.       chrprint(kbds);
  1029.       printf("%s", " -- not a CTRL key");
  1030.     }
  1031.     if (kbdc < 32) ckeytab[kbdc].ccount++;
  1032.     if (ckeytab[kbdc].ccount == 2) {
  1033.       cup(1 + (kbdc % 16), 1 + 40 * (kbdc / 16));
  1034.       printf("%s", ckeytab[kbdc].csymbol);
  1035.     }
  1036.   } while (kbdc != '\177');
  1037. #ifdef UNIX
  1038.   sgttyNew.sg_flags &= ~RAW;
  1039.   sgttyNew.sg_flags |= ECHO;
  1040.   stty(0, &sgttyNew);
  1041. #ifdef SIII
  1042.   sgttyNew.sg_flags |= CBREAK;
  1043.   stty(0, &sgttyNew);
  1044. #endif
  1045. #endif
  1046.   ttybin(0);
  1047. #ifdef SARG20
  1048.   superbin(0);    /* Puuuh! We made it!? */
  1049.   page(1);    /* Back to normal input processing */
  1050.   ttybin(1);    /* This must be the mode for DEC20 */
  1051. #endif
  1052.   cup(24,1);
  1053.   okflag = 1;
  1054.   for (i = 0; i < 32; i++) if (ckeytab[i].ccount < 2) okflag = 0;
  1055.   if (okflag) printf("%s", "OK. ");
  1056.   else        printf("%s", "You have not been able to send all CTRL keys! ");
  1057.   holdit();
  1058. }
  1059.  
  1060. tst_reports() {
  1061.   /* Test of:
  1062.        <ENQ>       (AnswerBack Message)
  1063.        SM RM       (Set/Reset Mode) - LineFeed / Newline
  1064.        DSR         (Device Status Report)
  1065.        DA          (Device Attributes)
  1066.        DECREQTPARM (Request Terminal Parameters)
  1067.   */
  1068.  
  1069.   int parity, nbits, xspeed, rspeed, clkmul, flags;
  1070.   int i, reportpos;
  1071.   char *report, *report2;
  1072.   static char *attributes[][2] = {
  1073.     { "\033[?1;0c",   "No options (vanilla VT100)" },
  1074.     { "\033[?1;1c",   "VT100 with STP" },
  1075.     { "\033[?1;2c",   "VT100 with AVO (could be a VT102)" },
  1076.     { "\033[?1;3c",   "VT100 with STP and AVO" },
  1077.     { "\033[?1;4c",   "VT100 with GPO" },
  1078.     { "\033[?1;5c",   "VT100 with STP and GPO" },
  1079.     { "\033[?1;6c",   "VT100 with AVO and GPO" },
  1080.     { "\033[?1;7c",   "VT100 with STP, AVO and GPO" },
  1081.     { "\033[?1;11c",  "VT100 with PP and AVO" },
  1082.     { "\033[?1;15c",  "VT100 with PP, GPO and AVO" },
  1083.     { "\033[?4;2c",   "VT132 with AVO" },
  1084.     { "\033[?4;3c",   "VT132 with AVO and STP" },
  1085.     { "\033[?4;6c",   "VT132 with GPO and AVO" },
  1086.     { "\033[?4;7c",   "VT132 with GPO, AVO, and STP" },
  1087.     { "\033[?4;11c",  "VT132 with PP and AVO" },
  1088.     { "\033[?4;15c",  "VT132 with PP, GPO and AVO" },
  1089.     { "\033[?7c",     "VT131" },
  1090.     { "\033[?12;5c",  "VT125" },           /* VT125 also has ROM version */
  1091.     { "\033[?12;7c",  "VT125 with AVO" },  /* number, so this won't work */
  1092.     { "\033[?5;0c",   "VK100 (GIGI)" },
  1093.     { "\033[?5c",     "VK100 (GIGI)" },
  1094.     { "", "" }
  1095.   };
  1096.  
  1097. #ifdef UNIX
  1098.   sgttyNew.sg_flags &= ~ECHO;
  1099.   stty(0, &sgttyNew);
  1100. #endif
  1101.   cup(5,1);
  1102.   println("This is a test of the ANSWERBACK MESSAGE. (To load the A.B.M.");
  1103.   println("see the TEST KEYBOARD part of this program). Below here, the");
  1104.   println("current answerback message in your terminal should be");
  1105.   println("displayed. Finish this test with RETURN.");
  1106.   cup(10,1);
  1107.   inflush();
  1108.   printf("%c", 5); /* ENQ */
  1109.   report = instr();
  1110.   cup(10,1);
  1111.   chrprint(report);
  1112.   cup(12,1);
  1113.   holdit();
  1114.  
  1115.   ed(2);
  1116.   cup(1,1);
  1117.   println("Test of LineFeed/NewLine mode.");
  1118.   cup(3,1);
  1119.   sm("20");
  1120. #ifdef UNIX
  1121.   sgttyNew.sg_flags &= ~CRMOD;
  1122.   stty(0, &sgttyNew);
  1123. #endif
  1124.   printf("NewLine mode set. Push the RETURN key: ");
  1125.   report = instr();
  1126.   cup(4,1);
  1127.   el(0);
  1128.   chrprint(report);
  1129.   if (!strcmp(report, "\015\012")) printf(" -- OK");
  1130.   else                             printf(" -- Not expected");
  1131.   cup(6,1);
  1132.   rm("20");
  1133.   printf("NewLine mode reset. Push the RETURN key: ");
  1134.   report = instr();
  1135.   cup(7,1);
  1136.   el(0);
  1137.   chrprint(report);
  1138.   if (!strcmp(report, "\015")) printf(" -- OK");
  1139.   else                         printf(" -- Not expected");
  1140.   cup(9,1);
  1141. #ifdef UNIX
  1142.   sgttyNew.sg_flags |= CRMOD;
  1143.   stty(0, &sgttyNew);
  1144. #endif
  1145.   holdit();
  1146.  
  1147.   ed(2);
  1148.   cup(1,1);
  1149.   printf("Test of Device Status Report 5 (report terminal status).");
  1150.   cup(2,1);
  1151.   dsr(5);
  1152.   report = instr();
  1153.   cup(2,1);
  1154.   el(0);
  1155.   printf("Report is: ");
  1156.   chrprint(report);
  1157.   if      (!strcmp(report,"\033[0n")) printf(" -- means \"TERMINAL OK\"");
  1158.   else if (!strcmp(report,"\033[3n")) printf(" -- means \"TERMINAL OK\"");
  1159.   else                                printf(" -- Unknown response!");
  1160.  
  1161.   cup(4,1);
  1162.   println("Test of Device Status Report 6 (report cursor position).");
  1163.   cup(5,1);
  1164.   dsr(6);
  1165.   report = instr();
  1166.   cup(5,1);
  1167.   el(0);
  1168.   printf("Report is: ");
  1169.   chrprint(report);
  1170.   if (!strcmp(report,"\033[5;1R")) printf(" -- OK");
  1171.   else                             printf(" -- Unknown response!");
  1172.  
  1173.   cup(7,1);
  1174.   println("Test of Device Attributes report (what are you)");
  1175.   cup(8,1);
  1176.   da(0);
  1177.   report = instr();
  1178.   cup(8,1);
  1179.   el(0);
  1180.   printf("Report is: ");
  1181.   chrprint(report);
  1182.   for (i = 0; *attributes[i][0] != '\0'; i++) {
  1183.     if (!strcmp(report,attributes[i][0])) break;
  1184.   }
  1185.   if (*attributes[i][0] == '\0')
  1186.   printf(" -- Unknown response, refer to the manual");
  1187.   else {
  1188.     printf(" -- means %s", attributes[i][1]);
  1189.     if (i) {
  1190.       cup(9,1);
  1191.       println("Legend: STP = Processor Option");
  1192.       println("        AVO = Advanced Video Option");
  1193.       println("        GPO = Graphics Processor Option");
  1194.       println("        PP  = Printer Port");
  1195.     }
  1196.   }
  1197.  
  1198.   cup(14,1);
  1199.   println("Test of the \"Request Terminal Parameters\" feature, argument 0.");
  1200.   cup(15,1);
  1201.   decreqtparm(0);
  1202.   report = instr();
  1203.   cup(15,1);
  1204.   el(0);
  1205.   printf("Report is: ");
  1206.   chrprint(report);
  1207.   if (strlen(report) < 16
  1208.    || report[0] != '\033'
  1209.    || report[1] != '['
  1210.    || report[2] != '2'
  1211.    || report[3] != ';')
  1212.   println(" -- Bad format");
  1213.   else {
  1214.     reportpos = 4;
  1215.     parity = scanto(report, &reportpos, ';');
  1216.     nbits  = scanto(report, &reportpos, ';');
  1217.     xspeed = scanto(report, &reportpos, ';');
  1218.     rspeed = scanto(report, &reportpos, ';');
  1219.     clkmul = scanto(report, &reportpos, ';');
  1220.     flags  = scanto(report, &reportpos, 'x');
  1221.     if (parity == 0 || nbits == 0 || clkmul == 0) println(" -- Bad format");
  1222.     else                                          println(" -- OK");
  1223.     printf(
  1224.     "This means: Parity %s, %s bits, xmitspeed %s, recvspeed %s.\n",
  1225.     lookup(paritytable, parity),
  1226.     lookup(nbitstable, nbits),
  1227.     lookup(speedtable, xspeed),
  1228.     lookup(speedtable, rspeed));
  1229.     printf("(CLoCk MULtiplier = %d, STP option flags = %d)\n", clkmul, flags);
  1230.   }
  1231.  
  1232.   cup(19,1);
  1233.   println("Test of the \"Request Terminal Parameters\" feature, argument 1.");
  1234.   cup(20,1);
  1235.   decreqtparm(1);    /* Does the same as decreqtparm(0), reports "3" */
  1236.   report2 = instr();
  1237.   cup(20,1);
  1238.   el(0);
  1239.   printf("Report is: ");
  1240.   chrprint(report2);
  1241.   if (strlen(report2) < 3
  1242.    || report2[2] != '3')
  1243.   println(" -- Bad format");
  1244.   else {
  1245.     report2[2] = '2';
  1246.     if (!strcmp(report,report2)) println(" -- OK");
  1247.     else                         println(" -- Bad format");
  1248.   }
  1249.   cup(24,1);
  1250.   holdit();
  1251. #ifdef UNIX
  1252.   sgttyNew.sg_flags |= ECHO;
  1253.   stty(0, &sgttyNew);
  1254. #endif
  1255. }
  1256.  
  1257. tst_vt52() {
  1258.  
  1259.   static struct rtabl {
  1260.       char *rcode;
  1261.       char *rmsg;
  1262.   } resptable[] = {
  1263.       { "\033/K", " -- OK (means Standard VT52)" },
  1264.       { "\033/Z", " -- OK (means VT100 emulating VT52)" },
  1265.       { "",       " -- Unknown response"}
  1266.   };
  1267.  
  1268.   int i,j;
  1269.   char *response;
  1270.  
  1271.   rm("?2");  /* Reset ANSI (VT100) mode, Set VT52 mode    */
  1272.   esc("H");  /* Cursor home    */
  1273.   esc("J");  /* Erase to end of screen    */
  1274.   esc("H");  /* Cursor home    */
  1275.   for (i = 0; i <= 23; i++) {
  1276.     for (j = 0; j <= 9; j++)
  1277.     printf("%s", "FooBar ");
  1278.     println("Bletch");
  1279.   }
  1280.   esc("H");  /* Cursor home    */
  1281.   esc("J");  /* Erase to end of screen    */
  1282.  
  1283.   vt52cup(7,47);
  1284.   printf("nothing more.");
  1285.   for (i = 1; i <= 10; i++) printf("THIS SHOULD GO AWAY! ");
  1286.   for (i = 1; i <= 5; i++) {
  1287.     vt52cup(1,1);
  1288.     printf("%s", "Back scroll (this should go away)");
  1289.     esc("I");         /* Reverse LineFeed (with backscroll!)    */
  1290.   }
  1291.   vt52cup(12,60);
  1292.   esc("J");  /* Erase to end of screen    */
  1293.   for (i = 2; i <= 6; i++) {
  1294.     vt52cup(i,1);
  1295.     esc("K");        /* Erase to end of line    */
  1296.   }
  1297.  
  1298.   for (i = 2; i <= 23; i++) {
  1299.     vt52cup(i,70); printf("%s", "**Foobar");
  1300.   }
  1301.   vt52cup(23,10); 
  1302.   for (i = 23; i >= 2; i--) {
  1303.     printf("%s", "*");
  1304.     printf("%c", 8);    /* BS */
  1305.     esc("I");        /* Reverse LineFeed (LineStarve)    */
  1306.   }
  1307.   vt52cup(1,70);
  1308.   for (i = 70; i >= 10; i--) {
  1309.     printf("%s", "*");
  1310.     esc("D"); esc("D");    /* Cursor Left */
  1311.   }
  1312.   vt52cup(24,10);
  1313.   for (i = 10; i <= 70; i++) {
  1314.     printf("%s", "*");
  1315.     printf("%c", 8);    /* BS */
  1316.     esc("C");        /* Cursor Right    */
  1317.   }
  1318.   vt52cup(2,11);
  1319.   for (i = 2; i <= 23; i++) {
  1320.     printf("%s", "!");
  1321.     printf("%c", 8);    /* BS */
  1322.     esc("B");        /* Cursor Down    */
  1323.   }
  1324.   vt52cup(23,69);
  1325.   for (i = 23; i >= 2; i--) {
  1326.     printf("%s", "!");
  1327.     printf("%c", 8);    /* BS */
  1328.     esc("A");        /* Cursor Up    */
  1329.   }
  1330.   for (i = 2; i <= 23; i++) {
  1331.     vt52cup(i,71);
  1332.     esc("K");        /* Erase to end of line    */
  1333.   }
  1334.  
  1335.   vt52cup(10,16);
  1336.   printf("%s", "The screen should be cleared, and have a centered");
  1337.   vt52cup(11,16);
  1338.   printf("%s", "rectangle of \"*\"s with \"!\"s on the inside to the");
  1339.   vt52cup(12,16);
  1340.   printf("%s", "left and right. Only this, and");
  1341.   vt52cup(13,16);
  1342.   holdit();
  1343.  
  1344.   esc("H");  /* Cursor home    */
  1345.   esc("J");  /* Erase to end of screen    */
  1346.   printf("%s", "This is the normal character set:");
  1347.   for (j =  0; j <=  1; j++) {
  1348.     vt52cup(3 + j, 16);
  1349.     for (i = 0; i <= 47; i++)
  1350.     printf("%c", 32 + i + 48 * j);
  1351.   }
  1352.   vt52cup(6,1);
  1353.   printf("%s", "This is the special graphics character set:");
  1354.   esc("F");    /* Select Special Graphics character set    */
  1355.   for (j =  0; j <=  1; j++) {
  1356.     vt52cup(8 + j, 16);
  1357.     for (i = 0; i <= 47; i++)
  1358.     printf("%c", 32 + i + 48 * j);
  1359.   }
  1360.   esc("G");    /* Select ASCII character set    */
  1361.   vt52cup(12,1);
  1362.   holdit();
  1363.  
  1364.   esc("H");  /* Cursor home    */
  1365.   esc("J");  /* Erase to end of screen    */
  1366.   println("Test of terminal response to IDENTIFY command");
  1367.   esc("Z");    /* Identify    */
  1368.   response = instr();
  1369.   println("");
  1370.   printf("Response was");
  1371.   esc("<");  /* Enter ANSI mode (VT100 mode) */
  1372.   chrprint(response);
  1373.   for(i = 0; resptable[i].rcode[0] != '\0'; i++)
  1374.     if (!strcmp(response, resptable[i].rcode))
  1375.       break;
  1376.   printf("%s", resptable[i].rmsg);
  1377.   println("");
  1378.   println("");
  1379.   holdit();
  1380. }
  1381.  
  1382. tst_insdel() {
  1383.  
  1384.     /* Test of:
  1385.        SM/RM(4) (= IRM (Insertion/replacement mode))
  1386.        ICH (Insert Character)
  1387.        DCH (Delete character)
  1388.        IL  (Insert line)
  1389.        DL  (Delete line)
  1390.     */
  1391.  
  1392.   int i, row, col, sw, dblchr, scr132;
  1393.  
  1394.   for(scr132 = 0; scr132 <= 1; scr132++) {
  1395.     if (scr132) { sm("?3"); sw = 132; }
  1396.     else        { rm("?3"); sw =  80; }
  1397.     ed(2);
  1398.     cup(1,1);
  1399.     for (row=1; row<=24; row++) {
  1400.     cup(row,1);
  1401.     for (col=1; col<=sw; col++)
  1402.         printf("%c", 'A'-1+row);
  1403.     }
  1404.     cup(4,1);
  1405.     printf("Screen accordion test (Insert & Delete Line). "); holdit();
  1406.     ri(); el(2);
  1407.     decstbm( 2,23);
  1408.     sm("?6");
  1409.     cup(1,1);
  1410.     for (row=1; row<=24; row++) {
  1411.       il(row);
  1412.       dl(row);
  1413.     }
  1414.     rm("?6");
  1415.     decstbm( 0, 0);
  1416.     cup(2,1);
  1417.     printf(
  1418.     "Top line: A's, bottom line: X's, this line, nothing more. ");
  1419.     holdit();
  1420.     cup(2,1); ed(0);
  1421.     cup(1,2);
  1422.     printf("B");
  1423.     cub(1);
  1424.     sm("4");
  1425.     for (col=2; col<=sw-1; col++)
  1426.       printf("*");
  1427.     rm("4");
  1428.     cup(4,1);
  1429.     printf("Test of 'Insert Mode'. The top line should be 'A*** ... ***B'. ");
  1430.     holdit(); ri(); el(2);
  1431.     cup(1,2);
  1432.     dch(sw-2);
  1433.     cup(4,1);
  1434.     printf("Test of 'Delete Character'. The top line should be 'AB'. ");
  1435.     holdit();
  1436.  
  1437.     for(dblchr = 1; dblchr <= 2; dblchr++) {
  1438.       ed(2);
  1439.       for (row=1; row<=24; row++) {
  1440.     cup(row,1);
  1441.     if (dblchr == 2) decdwl();
  1442.     for (col=1; col<=sw/dblchr; col++)
  1443.       printf("%c", 'A'-1+row);
  1444.     cup(row,sw/dblchr-row);
  1445.     dch(row);
  1446.       }
  1447.       cup(4,1);
  1448.       println("The right column should be staggered ");
  1449.       printf("by one.  ");
  1450.       holdit();
  1451.     }
  1452.     ed(2);
  1453.     cup(1,1);
  1454.     println("If your terminal has the ANSI 'Insert Character' function");
  1455.     println("(the VT102 does not), then you should see a line like this");
  1456.     println("  A B C D E F G H I J K L M N O P Q R S T U V W X Y Z");
  1457.     println("below:");
  1458.     println("");
  1459.     for (i = 'Z'; i >= 'A'; i--) {
  1460.       printf("%c\010",i);
  1461.       ich(2);
  1462.     }
  1463.     cup(10,1);
  1464.     holdit();
  1465.  
  1466.     if (sw == 132) rm("?3");
  1467.   }
  1468. }
  1469.  
  1470. dch(pn) int pn; { brc(pn, 'P'); }  /* Delete character */
  1471. ich(pn) int pn; { brc(pn, '@'); }  /* Insert character -- not in VT102 */
  1472. dl(pn)  int pn; { brc(pn, 'M'); }  /* Delete line */
  1473. il(pn)  int pn; { brc(pn, 'L'); }  /* Insert line */
  1474.  
  1475. /*  Test of some known VT100 bugs and misfeatures  */
  1476.  
  1477. tst_bugs() {
  1478.  
  1479.   int i, menuchoice;
  1480.  
  1481.   static char *menutable[] = {
  1482.     "Exit to main menu",
  1483.     "Bug A: Smooth scroll to jump scroll",
  1484.     "Bug B: Scrolling region",
  1485.     "Bug C: Wide to narrow screen",
  1486.     "Bug D: Narrow to wide screen",
  1487.     "Bug E: Cursor move from double- to single-wide line",
  1488.     "Bug F: Column mode escape sequence",
  1489.     "Wrap around with cursor addressing",
  1490.     "Erase right half of double width lines",
  1491.     "Funny scroll regions",
  1492.     /* Add more here */
  1493.     ""
  1494.   };
  1495.  
  1496.   static char *hmsg[] = {
  1497.   "Test of known bugs in the DEC VT100 series. The numbering of some of",
  1498.   "the bugs (A-F) refers to the article 'VT100 MAGIC' by Sami Tabih in",
  1499.   "the 'Proceedings of the DEC Users Society' at St. Louis, Missouri, May",
  1500.   "1983. To understand some of the tests, you have to look at the source",
  1501.   "code or the article. Of course, a good VT100-compatible terminal",
  1502.   "should not have these bugs (or have some means of disabling them)! If",
  1503.   "a bug appears, you might want to RESET the terminal before continuing",
  1504.   "the test. There is a test of the RESET function in the main menu.",
  1505.   "" };
  1506.  
  1507.   do {
  1508.     ed(2); cup(1,1);
  1509.     for (i = 0; *hmsg[i]; i++) println(hmsg[i]);
  1510.     println("");
  1511.     println("          Choose bug test number:");
  1512.     menuchoice = menu(menutable);
  1513.     switch (menuchoice) {
  1514.       case  1:  bug_a();  break;
  1515.       case  2:  bug_b();  break;
  1516.       case  3:  bug_c();  break;
  1517.       case  4:  bug_d();  break;
  1518.       case  5:  bug_e();  break;
  1519.       case  6:  bug_f();  break;
  1520.       case  7:  bug_w();  break;
  1521.       case  8:  bug_l();  break;
  1522.       case  9:  bug_s();  break;
  1523.     }
  1524.   } while (menuchoice);
  1525. }
  1526.  
  1527. /* Bug A: Smooth scroll to jump scroll */
  1528.  
  1529. bug_a() {
  1530.   int i;
  1531.  
  1532.   cup (10, 1);
  1533.   println("This is a test of the VT100 'Scroll while toggle softscroll'");
  1534.   println("bug.  The cursor may disappear, or move UP the screen, or");
  1535.   println("multiple copies of some lines may appear.");
  1536.   holdit();
  1537.  
  1538.   /*  Invoke the bug  */
  1539.  
  1540.   esc ("[24H");                /* Simplified cursor movement    */
  1541.   rm("?4"); for (i = 1; i <= 20; i++) printf("\n");
  1542.   sm("?4"); for (i = 1; i <= 10; i++) printf("\n");
  1543.   rm("?4"); for (i = 1; i <=  5; i++) printf("\n");
  1544.  
  1545.   /* That should be enough to show the bug. But we'll try another way:    */
  1546.   sm ("?4");                /* Set soft scroll        */
  1547.   nel ();                /* "NextLine", move down    */
  1548.   rm ("?4");                /* Reset soft scroll        */
  1549.   nel ();                /* "NextLine", move down    */
  1550.   for (i = 1; i <= 10; i++) {        /* Show the bug            */
  1551.       printf ("Softscroll bug test, line %d.  ", i);
  1552.       holdit();
  1553.   }
  1554.   println("That should have been enough to show the bug, if present.");
  1555.   holdit();
  1556. }
  1557.  
  1558. /*  Bug B: Scrolling region  */
  1559.  
  1560. bug_b() {
  1561.   char c;
  1562.  
  1563.   decaln();
  1564.   cup( 1,1); el(0);
  1565.   printf("Line 11 should be double-wide, line 12 should be cleared.");
  1566.   cup( 2,1); el(0);
  1567.   printf("Then, the letters A-P should be written at the beginning");
  1568.   cup( 3,1); el(0);
  1569.   printf("of lines 12-24, and the empty line and A-E are scrolled away.");
  1570.   cup( 4,1); el(0);
  1571.   printf("If the bug is present, some lines are confused, look at K-P.");
  1572.   cup(11,1); decdwl();
  1573.   decstbm(12,24);
  1574.   cup(12,1); el(0); printf("Here we go... "); holdit();
  1575.   cup(12,1); ri();                    /* Bug comes here */
  1576.   for (c = 'A'; c <= 'P'; c++) printf("%c\n",c);    /* Bug shows here */
  1577.   holdit();
  1578.   decstbm(0,0);                        /* No scr. region */
  1579. }
  1580.  
  1581. /*  Bug C: Wide to narrow screen  */
  1582.  
  1583. bug_c() {
  1584.   sm("?3");                        /* 132 column mode */
  1585.   cup(1,81);
  1586.   rm("?3");                        /*  80 column mode */
  1587.   cup(12,5);
  1588.   printf("Except for this line, the screen should be blank. ");
  1589.   holdit();
  1590. }
  1591.  
  1592. /*  Bug D: Narrow to wide screen  */
  1593.  
  1594. bug_d() {
  1595.   int i;
  1596.   char result;
  1597.   /* Make the bug appear */
  1598.   do {
  1599.     cup(14,1);
  1600.  
  1601.     /* The original code in the article says
  1602.      * PRINT ESC$; "[13;1H"; CHR$(10%);
  1603.      * but I guess a cup(14,1); would do.
  1604.      * (To output a pure LF might be tricky).
  1605.      */
  1606.  
  1607.     sm("?3");              /* Make the bug visible */
  1608.     cup(1,9); decdwl();
  1609.     println("You should see blinking text at the bottom line.");
  1610.     cup(3,9); decdwl();
  1611.     println("Enter 0 to exit, 1 to try to invoke the bug again.");
  1612.     cup(24,9); decdwl(); sgr("1;5;7");
  1613.     printf("If you can see this then the bug did not appear."); sgr("");
  1614.     cup(4,9); decdwl();
  1615.     result = inchar(); readnl();
  1616.     rm("?3");
  1617.   } while (result == '1');
  1618.   sm("?4");    /* Syrup scroll */
  1619.   cup(23,1);
  1620.   for (i = 1; i <= 5; i++)
  1621.   println("If the bug is present, this should make things much worse!");
  1622.   holdit();
  1623.   rm("?4");    /* Jump scroll */
  1624. }
  1625.  
  1626. /*  Bug E: Cursor move from double- to single-wide line  */
  1627.  
  1628. bug_e() {
  1629.   int i;
  1630.   static char *rend[2] = { "\033[m", "\033[7m" };
  1631.   sm("?3");
  1632.   cup(1,1); decdwl();
  1633.   println("This test should put an 'X' at line 3 column 100.");
  1634.   for (i = 1; i <= 12; i++) printf("1234567890%s",rend[i & 1]);
  1635.   cup(1,1);    /* The bug appears when we jump from a dobule-wide line */
  1636.   cup(3,100);    /* to a single-wide line, column > 66.                  */
  1637.   printf("X");
  1638.   cup(4, 66); printf("!                                 !");
  1639.   cup(5,1);
  1640.   printf("--------------------------- The 'X' should NOT be above here -");
  1641.   printf("---+------------ but above here -----+");
  1642.   cup(10,1); decdwl(); holdit();
  1643.   rm("?3");
  1644. }
  1645.  
  1646. /*  Bug F: Column mode escape sequence  */
  1647.  
  1648. bug_f() {
  1649.   int i, row, col;
  1650.  
  1651.  /*
  1652.   *  VT100 "toggle origin mode, forget rest" bug.  If you try to set
  1653.   *    (or clear) parameters and one of them is the "origin mode"
  1654.   *    ("?6") parameter, parameters that appear after the "?6"
  1655.   *    remain unaffected.  This is also true on CIT-101 terminals.
  1656.   */
  1657.   sm ("?5");                /* Set reverse mode        */
  1658.   sm ("?3");                /* Set 132 column mode        */
  1659.   println("Test VT100 'Toggle origin mode, forget rest' bug, part 1.");
  1660.   println("The screen should be in reverse, 132 column mode.");
  1661.   holdit();
  1662.   ed (2);
  1663.   rm ("?6;5;3");        /* Reset (origin, reverse, 132 col)    */
  1664.   println("Test VT100 'Toggle origin mode, forget rest' bug, part 2.\n");
  1665.   println("The screen should be in non-reverse, 80 column mode.");
  1666.   holdit();
  1667. }
  1668.  
  1669.   /*    Bug W:
  1670.    *    The dreaded "wraparound" bug!  You CUP to col 80, write a char,
  1671.    *    CUP to another line in col 80, write a char. And the brain-damaged
  1672.    *    terminal thinks that "Hokay, so he's written a char in col 80, so
  1673.    *    I stay in col 80 and wait for next character. Let's see now, here
  1674.    *    comes another character, and I'm still in col 80, so I must make
  1675.    *    a NewLine first." -- It doesn't clear that "still in col 80" flag
  1676.    *    on a CUP. Argh!
  1677.    */
  1678.  
  1679. bug_w() {
  1680.   int row, col;
  1681.  
  1682.   cup (16,1);
  1683.   println("   This illustrates the \"wrap around bug\" which exists on a");
  1684.   println("   standard VT100. At the top of the screen there should be");
  1685.   println("   a row of +'s, and the rightmost column should be filled");
  1686.   println("   with *'s. But if the bug is present, some of the *'s may");
  1687.   println("   be placed in other places, e.g. in the leftmost column,");
  1688.   println("   and the top line of +'s may be scrolled away.");
  1689.  
  1690.   cup(1,1);
  1691.   for (col = 1; col <= 79; col++)
  1692.       printf ("+");
  1693.   for (row = 1; row <= 24; row++) {
  1694.       hvp (row, 80);
  1695.       printf ("*");
  1696.   }
  1697.   cup(24,1);
  1698.   holdit();
  1699. }
  1700.  
  1701.   /*    Bug L:
  1702.    *    Check if the right half of double-width lines comes back
  1703.    *    when a line is first set to single-width, filled with stuff,
  1704.    *    set to double-width, and finally reset to single-width.
  1705.    *
  1706.    *    A VT100 has this misfeature, and many others. Foo!
  1707.    */
  1708.  
  1709. bug_l() {
  1710.   cup(15, 1);
  1711.   printf("This-is-a-long-line-This-is-a-long-line-");
  1712.   printf("This-is-a-long-line-This-is-a-long-line-");
  1713.   cup(1, 1);
  1714.   printf("This is a test of what happens to the right half of double-width");
  1715.   println(" lines.");
  1716.   printf("A common misfeature is that the right half does not come back");
  1717.   println(" when a long");
  1718.   printf("single-width line is set to double-width and then reset to");
  1719.   println(" single-width.");
  1720.  
  1721.   cup(5, 1);
  1722.   println("Now the line below should contain 80 characters in single width.");
  1723.   holdit();
  1724.   cup(15, 1); decdwl();
  1725.   cup(8, 1);
  1726.   println("Now the line below should contain 40 characters in double width.");
  1727.   holdit();
  1728.   cup(15, 1); decswl();
  1729.   cup(11, 1);
  1730.   println("Now the line below should contain 80 characters in single width.");
  1731.   holdit();
  1732.  
  1733.   /* ...and in 132 column mode  */
  1734.  
  1735.   sm("?3");
  1736.   ed(2);
  1737.   cup(15, 1);
  1738.   printf("This-is-a-long-line-This-is-a-long-line-");
  1739.   printf("This-is-a-long-line-This-is-a-long-line-");
  1740.   printf("This-is-a-long-line-This-is-a-long-line-");
  1741.   printf("ending-here-");
  1742.  
  1743.   cup(1, 1);
  1744.   printf("This is the same test in 132 column mode.");
  1745.  
  1746.   cup(5, 1);
  1747.   println("Now the line below should contain 132 characters in single width.");
  1748.   holdit();
  1749.   cup(15, 1); decdwl();
  1750.   cup(8, 1);
  1751.   println("Now the line below should contain 66 characters in double width.");
  1752.   holdit();
  1753.   cup(15, 1); decswl();
  1754.   cup(11, 1);
  1755.   println("Now the line below should contain 132 characters in single width.");
  1756.   holdit();
  1757.   rm("?3");
  1758. }
  1759.  
  1760. bug_s() {
  1761.   int i;
  1762.   decstbm(20,10);    /* 20-10=-10, < 2, so no scroll region. */
  1763.   cup(1,1);
  1764.   for (i=1; i<=20; i++)
  1765.     printf("This is 20 lines of text (line %d), no scroll region.\n", i);
  1766.   holdit();
  1767.   ed(2);
  1768.   decstbm(0,1);        /* Should be interpreted as decstbm(1,1) = none */
  1769.   cup(1,1);
  1770.   for (i=1; i<=20; i++)
  1771.     printf("This is 20 lines of text (line %d), no scroll region.\n", i);
  1772.   holdit();
  1773.   decstbm(0,0);        /* No scroll region (just in case...)    */
  1774. }
  1775.  
  1776. tst_rst() {
  1777.  
  1778.   /*
  1779.    * Test of
  1780.    *    - RIS    (Reset to Initial State)
  1781.    *    - DECTST (invoke terminal test)
  1782.    */
  1783.  
  1784.   cup(10,1);
  1785.   printf ("The terminal will now be RESET. ");
  1786.   holdit();
  1787.   ris();
  1788. #ifdef UNIX
  1789.   fflush(stdout);
  1790. #endif
  1791.   zleep(5000);        /* Wait 5.0 seconds */
  1792.   cup(10,1);
  1793.   println("The terminal is now RESET. Next, the built-in confidence test");
  1794.   printf("%s", "will be invoked. ");
  1795.   holdit();
  1796.   ed(2);
  1797.   dectst(1);
  1798. #ifdef UNIX
  1799.   fflush(stdout);
  1800. #endif
  1801.   zleep(5000);        /* Wait 5.0 seconds */
  1802.   cup(10,1);
  1803.   println("If the built-in confidence test found any errors, a code");
  1804.   printf("%s", "is visible above. ");
  1805.   holdit();
  1806. }
  1807.  
  1808. initterminal(pn) int pn; {
  1809.  
  1810. #ifdef UNIX
  1811.   if (pn==0) {
  1812.     fflush(stdout);
  1813.     gtty(0,&sgttyOrg);
  1814.     gtty(0,&sgttyNew);
  1815.     sgttyNew.sg_flags |= CBREAK;
  1816.     }
  1817.   else  {
  1818.     fflush(stdout);
  1819.     inflush();
  1820.     sleep(2);
  1821.     sgttyNew.sg_flags = sgttyOrg.sg_flags | CBREAK;
  1822.     }
  1823.   stty(0,&sgttyNew);
  1824. #ifdef SIII
  1825.   close(2);
  1826.   open("/dev/tty",O_RDWR|O_NDELAY);
  1827. #endif
  1828. #endif
  1829. #ifdef SARG10
  1830.   /* Set up neccesary TOPS-10 terminal parameters    */
  1831.  
  1832.   trmop(02041, `VT100`);    /* tty type vt100    */
  1833.   trmop(02002, 0);    /* tty no tape    */
  1834.   trmop(02003, 0);    /* tty lc    */
  1835.   trmop(02005, 1);    /* tty tab    */
  1836.   trmop(02010, 1);    /* tty no crlf    */
  1837.   trmop(02020, 0);    /* tty no tape    */
  1838.   trmop(02021, 1);    /* tty page    */
  1839.   trmop(02025, 0);    /* tty blanks    */
  1840.   trmop(02026, 1);    /* tty no alt    */
  1841.   trmop(02040, 1);    /* tty defer    */
  1842. #endif
  1843. #ifdef SARG20
  1844.   ttybin(1);    /* set line to binary mode */
  1845. #endif
  1846.   /* Set up my personal prejudices    */
  1847.  
  1848.   esc("<");    /* Enter ANSI mode (if in VT52 mode)    */
  1849.   rm("?1");     /* cursor keys normal   */
  1850.   rm("?3");    /* 80 col mode        */
  1851.   rm("?4");     /* Jump scroll          */
  1852.   rm("?5");     /* Normal screen        */
  1853.   rm("?6");    /* Absolute origin mode    */
  1854.   sm("?7");    /* Wrap around on    */
  1855.   rm("?8");    /* Auto repeat off    */
  1856.   decstbm(0,0);    /* No scroll region    */
  1857.   sgr("0");     /* Normal character attributes  */
  1858.  
  1859. }
  1860.  
  1861. bye () {
  1862.   /* Force my personal prejudices upon the poor luser    */
  1863.  
  1864.   esc("<");    /* Enter ANSI mode (if in VT52 mode)    */
  1865.   rm("?1");     /* cursor keys normal   */
  1866.   rm("?3");    /* 80 col mode        */
  1867.   rm("?5");     /* Normal screen        */
  1868.   rm("?6");    /* Absolute origin mode    */
  1869.   sm("?7");    /* Wrap around on    */
  1870.   sm("?8");    /* Auto repeat on    */
  1871.   decstbm(0,0);    /* No scroll region    */
  1872.   sgr("0");     /* Normal character attributes  */
  1873.  
  1874.   /* Say goodbye */
  1875.  
  1876.   ed(2);
  1877.   cup(12,30);
  1878.   printf("That's all, folks!\n");
  1879.   printf("\n\n\n");
  1880.   inflush();
  1881. #ifdef SARG20
  1882.   ttybin(0);    /* reset line to normal mode */
  1883. #endif
  1884. #ifdef UNIX
  1885.   stty(0,&sgttyOrg);
  1886. #endif
  1887.   exit();
  1888. }
  1889.  
  1890. #ifdef UNIX
  1891. onbrk() {
  1892.   signal(SIGINT, onbrk);
  1893.   if (reading)
  1894.     brkrd = 1;
  1895.   else
  1896.     longjmp(intrenv, 1);
  1897. }
  1898.  
  1899. onterm() {
  1900.   signal(SIGTERM, onterm);
  1901.   longjmp(intrenv, 1);
  1902. }
  1903. #endif
  1904.  
  1905. holdit() {
  1906.   inflush();
  1907.   printf("Push <RETURN>");
  1908.   readnl();
  1909. }
  1910.  
  1911. readnl() {
  1912. #ifdef UNIX
  1913.   char ch;
  1914.   fflush(stdout);
  1915.   brkrd = 0;
  1916.   reading = 1;
  1917.   do { read(0,&ch,1); } while(ch != '\n' && !brkrd);
  1918.   if (brkrd)
  1919.     kill(getpid(), SIGTERM);
  1920.   reading = 0;
  1921. #endif
  1922. #ifdef SARG10
  1923.  while (getchar() != '\n')
  1924.  ;
  1925. #endif
  1926. #ifdef SARG20
  1927.  while (getchar() != '\n')
  1928.    ;
  1929. #endif
  1930. }
  1931.  
  1932. scanto(str, pos, toc) char *str; int *pos; char toc; {
  1933.   char c;
  1934.   int result = 0;
  1935.  
  1936.   while (toc != (c = str[(*pos)++])) {
  1937.     if (isdigit(c)) result = result * 10 + c - '0';
  1938.     else break;
  1939.   }
  1940.   if (c == toc) return(result);
  1941.   else          return(0);
  1942. }
  1943.  
  1944. char *lookup(t, k) struct table t[]; int k; {
  1945.  
  1946.   int i;
  1947.   for (i = 0; t[i].key != -1; i++) {
  1948.     if (t[i].key == k) return(t[i].msg);
  1949.   }
  1950.   return("BAD VALUE");
  1951. }
  1952.  
  1953. menu(table) char *table[]; {
  1954.  
  1955.   int i, tablesize, choice;
  1956.   char c;
  1957.   char storage[80];
  1958.   char *s = storage;
  1959.   println("");
  1960.   tablesize = 0;
  1961.   for (i = 0; *table[i] != '\0'; i++) {
  1962.     printf("          %d. %s\n", i, table[i]);
  1963.     tablesize++;
  1964.   }
  1965.   tablesize--;
  1966.  
  1967.   printf("\n          Enter choice number (0 - %d): ", tablesize);
  1968.   for(;;) {
  1969.     inputline(s);
  1970.     choice = 0;
  1971.     while (c = *s++) choice = 10 * choice + c - '0';
  1972.     if (choice >= 0 && choice <= tablesize) {
  1973.       ed(2);
  1974.       return (choice);
  1975.     }
  1976.     printf("          Bad choice, try again: ");
  1977.   }
  1978. }
  1979.  
  1980. chrprint (s) char *s; {
  1981.  
  1982.   int i;
  1983.  
  1984.   printf("  ");
  1985.   sgr("7");
  1986.   printf(" ");
  1987.   for (i = 0; s[i] != '\0'; i++) {
  1988.     if (s[i] <= ' ' || s[i] == '\177')
  1989.     printf("<%d> ", s[i]);
  1990.     else printf("%c ", s[i]);
  1991.   }
  1992.   sgr("");
  1993. }
  1994.