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