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