4 Written Novemeber 1983 - July 1984 by Per Lindberg,
5 Stockholm University Computer Center (QZ), Sweden.
7 THE MAD PROGRAMMER STRIKES AGAIN!
9 This software is (c) 1984 by QZ
10 Non-commercial use and copying allowed.
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.
18 /* $FreeBSD: src/usr.sbin/pcvt/vttest/main.c,v 1.4.6.1 2000/12/11 01:03:35 obrien Exp $ */
22 char inchar(), *instr(), *lookup();
62 return(ioctl(fd, TIOCSETP, ptr));
70 return(ioctl(fd, TIOCGETP, ptr));
79 static char *mainmenu[] = {
81 "Test of cursor movements",
82 "Test of screen features",
83 "Test of character sets",
84 "Test of double-sized characters",
86 "Test of terminal reports",
88 "Test of VT102 features (Insert/Delete Char/Line)",
90 "Test of reset and self-test",
95 initterminal(setjmp(intrenv));
96 signal(SIGINT, onbrk);
97 signal(SIGTERM, onterm);
104 ttybin(1); /* set line to binary mode again. It's reset somehow!! */
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;
122 } while (menuchoice);
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)
136 DECALN (Screen Alignment Display)
138 Cursor control characters inside CSI sequences
141 int i, row, col, pass, width, hlfxtra;
142 char c, *ctext = "This is a correct sentence";
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; }
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);
157 for (col = 1; col <= width; col++) {
158 hvp(24, col); printf("*");
159 hvp( 1, col); printf("*");
162 for (row = 2; row <= 23; row++) {
168 for (row = 23; row >=2; row--) {
173 for (row = 2; row <= 23; row++) {
184 cub(42+hlfxtra); cuf(2);
185 for (col = 3; col <= width-2; col++) {
187 cuf(0); cub(2); cuf(1);
190 cuf(42+hlfxtra); cub(2);
191 for (col = width-2; col >= 3; col--) {
193 cub(1); cuf(1); cub(0); printf("%c", 8);
195 cup( 1, 1); cuu(10); cuu(1); cuu(0);
196 cup(24,width); cud(10); cud(1); cud(0);
199 for (row = 10; row <= 15; row++) {
200 for (col = 12+hlfxtra; col <= 69+hlfxtra; col++) printf(" ");
204 printf("The screen should be cleared, and have an unbroken bor-");
206 printf("der of *'s and +'s around the edge, and exactly in the");
208 printf("middle there should be a frame of E's around this text");
210 printf("with one (1) free position around it. ");
217 println("Test of cursor-control characters inside ESC sequences.");
218 println("Below should be two identical lines:");
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 */
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++);
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
249 - SGR (Select Graphic Rendition)
250 - SM RM (Set/Reset Mode) - Inverse
251 - DECSC (Save Cursor)
252 - DECRC (Restore Cursor)
255 int i, j, cset, row, col, down, soft, background;
257 static char *tststr = "*qx`";
258 static char *attr[5] = { ";0", ";1", ";4", ";5", ";7" };
261 sm("?7"); /* Wrap Around ON */
262 for (col = 1; col <= 160; col++) printf("*");
263 rm("?7"); /* Wrap Around OFF */
265 for (col = 1; col <= 160; col++) printf("*");
266 sm("?7"); /* Wrap Around ON */
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.)");
276 for (col = 1; col <= 78; col += 3) {
280 for (col = 4; col <= 78; col += 6) {
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(" *");
287 println("Test of TAB setting/resetting. These two lines");
288 printf("should look the same. ");
290 for (background = 0; background <= 1; background++) {
291 if (background) rm("?5");
293 sm("?3"); /* 132 cols */
294 ed(2); /* VT100 clears screen on SM3/RM3, but not obviously, so... */
296 for (col = 1; col <= 132; col += 8) {
299 cup(1,1); for (col = 1; col <= 130; col += 10) printf("1234567890");
301 for (row = 3; row <= 20; row++) {
303 printf("This is 132 column mode, %s background.",
304 background ? "dark" : "light");
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++) {
312 printf("This is 80 column mode, %s background.",
313 background ? "dark" : "light");
319 sm("?6"); /* Origin mode (relative) */
320 for (soft = -1; soft <= 0; soft++) {
323 for (row = 12; row >= 1; row -= 11) {
324 decstbm(row, 24-row+1);
326 for (down = 0; down >= -1; down--) {
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",
334 if (down) { ri(); ri(); }
343 "\nOrigin mode test. This line should be at the bottom of the screen.");
346 "This line should be the one above the bottom of the screeen. ");
349 rm("?6"); /* Origin mode (absolute) */
352 "Origin mode test. This line should be at the bottom of the screen.");
354 printf("%s", "This line should be at the top if the screen. ");
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");
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();
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);
397 if (cset == 0 || cset == 2) scs(0,'B');
399 for (j = 0; j <= 4; j++) {
400 printf("%c", tststr[cset]);
403 cup(cset + 1, i + 1); sgr(""); scs(0,'B'); printf("A");
405 for (j = 0; j <= 4; j++) {
406 printf("%c", tststr[cset]);
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.");
419 SCS (Select character Set)
423 char chcode[5], *setmsg[5];
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";
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++) {
440 cup(3 + 4 * cset, 1);
442 printf("Character set %c (%s)",chcode[cset], setmsg[cset]);
444 for (g = 0; g <= 1; g++) {
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);
455 cup(24,1); printf("These are the installed character sets. ");
461 DECSWL (Single Width Line)
462 DECDWL (Double Width Line)
463 DECDHL (Double Height Line) (also implicit double width)
468 /* Print the test pattern in both 80 and 132 character width */
470 for(w = 0; w <= 1; w++) {
475 if (w) { sm("?3"); printf("132 column mode"); }
476 else { rm("?3"); printf(" 80 column mode"); }
479 printf("v------- left margin");
482 printf("This is a normal-sized line");
483 decdhl(0); decdhl(1); decdwl(); decswl();
486 printf("This is a Double-width line");
487 decswl(); decdhl(0); decdhl(1); decdwl();
490 decdwl(); decswl(); decdhl(1); decdhl(0);
491 printf("This is a Double-width-and-height line");
493 decdwl(); decswl(); decdhl(0); decdhl(1);
494 printf("This is a Double-width-and-height line");
497 decdwl(); decswl(); decdhl(1); decdhl(0); el(2);
498 printf("This is another such line");
500 decdwl(); decswl(); decdhl(0); decdhl(1);
501 printf("This is another such line");
504 printf("^------- left margin");
507 printf("This is not a double-width line");
508 for (i = 0; i <= 1; i++) {
510 if (i) { printf("**is**"); decdwl(); }
511 else { printf("is not"); decswl(); }
515 /* Set vanilla tabs for next test */
516 cup(1,1); tbc(3); for (col = 1; col <= 132; col += 8) { cuf(8); hts(); }
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");
533 printf("* The mad programmer strikes again * ");
534 cup(13,3); printf("%c",9); cub(6);
535 printf("* The mad programmer strikes again *");
538 println("Another test pattern... a frame with blinking bold text,");
539 printf("all in double-height double-width size. ");
542 decstbm(8,24); /* Absolute origin mode, so cursor is set at (1,1) */
544 for (i = 1; i <= 12; i++)
546 decstbm(0,0); /* No scroll region */
548 printf("%s", "Exactly half of the box should remain. ");
556 - Keyboard return messages
557 - SM RM (Set/Reset Mode) - Cursor Keys
559 - DECKPAM (Keypad Application Mode)
560 - DECKPNM (Keypad Numeric Mode)
562 The standard VT100 keayboard layout:
566 ESC 1! 2@ 3# 4$ 5% 6^ 7& 8* 9( 0) -_ =+ `~ BS
568 TAB* qQ wW eE rR tT yY uU iI oO pP [{ ]} DEL
570 ** ** aA sS dD fF gG hH jJ kK lL ;: ," RETN \|
572 ** **** zZ xX cC vV bB nN mM ,< .> /? **** LF
574 ****************SPACE BAR****************
587 char *ledmsg[6], *ledseq[6];
595 char *curkeystr, *fnkeystr, *abmstr;
596 char arptstring[500];
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, "~" },
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, "?" },
657 { ' ', 5, 13, " SPACE BAR "},
661 static struct natkey {
666 } natkeytab [][29] = {
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, "_" },
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, "_" },
709 static struct curkey {
717 /* A Reset, A Set, VT52 */
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, "", "" }
726 static struct fnkey {
734 /* ANSI-num,ANSI-app,VT52-nu,VT52-ap, r, c, symb name */
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, "", "" }
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-?)" }
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 */
803 static char *curkeymodes[3] = {
804 "ANSI / Cursor key mode RESET",
805 "ANSI / Cursor key mode SET",
809 static char *fnkeymodes[4] = {
811 "ANSI Application mode",
813 "VT52 Application mode"
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] = "";
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]);
838 println("Test of the AUTO REPEAT feature");
840 println("Hold down an alphanumeric key for a while, then push RETURN.");
841 printf("%s", "Auto Repeat OFF: ");
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.");
848 println("Hold down an alphanumeric key for a while, then push RETURN.");
849 printf("%s", "Auto Repeat ON: ");
851 inputline(arptstring);
852 if (strlen(arptstring) == 0) println("No characters read!??");
853 else if (strlen(arptstring) == 1) println("Not enough characters read.");
860 println("Choose keyboard layout:");
861 kblayout = menu(keyboardmenu);
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;
877 for (i = 0; keytab[i].c != '\0'; i++) {
878 cup(1 + 2 * keytab[i].row, 1 + keytab[i].col);
880 printf("%s", keytab[i].symbol);
885 sgttyNew.sg_flags &= ~CRMOD;
886 sgttyNew.sg_flags &= ~ECHO;
890 printf("Press each key, both shifted and unshifted. Finish with RETURN:");
891 do { /* while (kbdc != 13) */
892 cup(23,1); kbdc = inchar();
894 sprintf(kbds, "%c", kbdc);
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);
903 } while (kbdc != 13);
905 inchar(); /* Local hack: Read LF that TOPS-10 adds to CR */
909 for (ckeymode = 0; ckeymode <= 2; ckeymode++) {
910 if (ckeymode) sm("?1");
912 for (i = 0; curkeytab[i].curkeysymbol[0] != '\0'; i++) {
913 cup(1 + 2 * curkeytab[i].curkeyrow, 1 + curkeytab[i].curkeycol);
915 printf("%s", curkeytab[i].curkeysymbol);
918 cup(20,1); printf("<%s>%20s", curkeymodes[ckeymode], "");
920 cup(22,1); printf("%s", "Press each cursor key. Finish with TAB.");
923 if (ckeymode == 2) rm("?2"); /* VT52 mode */
925 esc("<"); /* ANSI mode */
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])) {
932 printf(" (%s key) ", curkeytab[i].curkeyname);
934 cup(1 + 2 * curkeytab[i].curkeyrow,
935 1 + curkeytab[i].curkeycol);
936 printf("%s", curkeytab[i].curkeysymbol);
940 if (i == sizeof(curkeytab) / sizeof(struct curkey) - 1) {
942 printf("%s", " (Unknown cursor key) ");
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);
952 printf("%s", fnkeytab[i].fnkeysymbol);
955 cup(20,1); printf("<%s>%20s", fnkeymodes[fkeymode], "");
957 cup(22,1); printf("%s", "Press each function key. Finish with TAB.");
960 if (fkeymode >= 2) rm("?2"); /* VT52 mode */
961 if (fkeymode % 2) deckpam(); /* Application mode */
962 else deckpnm(); /* Numeric mode */
964 esc("<"); /* ANSI mode */
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])) {
971 printf(" (%s key) ", fnkeytab[i].fnkeyname);
973 cup(1 + 2 * fnkeytab[i].fnkeyrow, 1 + fnkeytab[i].fnkeycol);
974 printf("%s", fnkeytab[i].fnkeysymbol);
978 if (i == sizeof(fnkeytab) / sizeof(struct fnkey) - 1) {
980 printf("%s", " (Unknown function key) ");
987 sgttyNew.sg_flags |= CRMOD;
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.");
996 println(" \" H e l l o , w o r l d Return \"");
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.");
1004 sgttyNew.sg_flags &= ~CRMOD;
1014 } while (strcmp(abmstr,"\r"));
1017 for (i = 0; i < 32; i++) {
1018 cup(1 + (i % 16), 1 + 40 * (i / 16));
1020 printf("%s", ckeytab[i].csymbol);
1025 sgttyNew.sg_flags |= CRMOD;
1029 "Push each CTRL-key TWICE. Note that you should be able to send *all*");
1031 "CTRL-codes twice, including CTRL-S (X-Off) and CTRL-Q (X-Off)!");
1033 "Finish with DEL (also called DELETE or RUB OUT), or wait 1 minute.");
1036 sgttyNew.sg_flags &= ~CBREAK;
1039 sgttyNew.sg_flags |= RAW;
1044 page(0); /* Turn off all character processing at input */
1045 superbin(1); /* Turn off ^C (among others). Keep your fingers crossed!! */
1048 cup(23,1); kbdc = inchar();
1050 if (kbdc < 32) printf(" %s", ckeytab[kbdc].csymbol);
1052 sprintf(kbds, "%c", kbdc);
1054 printf("%s", " -- not a CTRL key");
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);
1061 } while (kbdc != '\177');
1063 sgttyNew.sg_flags &= ~RAW;
1064 sgttyNew.sg_flags |= ECHO;
1067 sgttyNew.sg_flags |= CBREAK;
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 */
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! ");
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)
1094 int parity, nbits, xspeed, rspeed, clkmul, flags;
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)" },
1123 sgttyNew.sg_flags &= ~ECHO;
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.");
1133 printf("%c", 5); /* ENQ */
1142 println("Test of LineFeed/NewLine mode.");
1146 sgttyNew.sg_flags &= ~CRMOD;
1149 printf("NewLine mode set. Push the RETURN key: ");
1154 if (!strcmp(report, "\015\012")) printf(" -- OK");
1155 else printf(" -- Not expected");
1158 printf("NewLine mode reset. Push the RETURN key: ");
1163 if (!strcmp(report, "\015")) printf(" -- OK");
1164 else printf(" -- Not expected");
1167 sgttyNew.sg_flags |= CRMOD;
1174 printf("Test of Device Status Report 5 (report terminal status).");
1180 printf("Report is: ");
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!");
1187 println("Test of Device Status Report 6 (report cursor position).");
1193 printf("Report is: ");
1195 if (!strcmp(report,"\033[5;1R")) printf(" -- OK");
1196 else printf(" -- Unknown response!");
1199 println("Test of Device Attributes report (what are you)");
1205 printf("Report is: ");
1207 for (i = 0; *attributes[i][0] != '\0'; i++) {
1208 if (!strcmp(report,attributes[i][0])) break;
1210 if (*attributes[i][0] == '\0')
1211 printf(" -- Unknown response, refer to the manual");
1213 printf(" -- means %s", attributes[i][1]);
1216 println("Legend: STP = Processor Option");
1217 println(" AVO = Advanced Video Option");
1218 println(" GPO = Graphics Processor Option");
1219 println(" PP = Printer Port");
1224 println("Test of the \"Request Terminal Parameters\" feature, argument 0.");
1230 printf("Report is: ");
1232 if (strlen(report) < 16
1233 || report[0] != '\033'
1236 || report[3] != ';')
1237 println(" -- Bad format");
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");
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);
1258 println("Test of the \"Request Terminal Parameters\" feature, argument 1.");
1260 decreqtparm(1); /* Does the same as decreqtparm(0), reports "3" */
1264 printf("Report is: ");
1266 if (strlen(report2) < 3
1267 || report2[2] != '3')
1268 println(" -- Bad format");
1271 if (!strcmp(report,report2)) println(" -- OK");
1272 else println(" -- Bad format");
1277 sgttyNew.sg_flags |= ECHO;
1284 static struct rtabl {
1288 { "\033/K", " -- OK (means Standard VT52)" },
1289 { "\033/Z", " -- OK (means VT100 emulating VT52)" },
1290 { "", " -- Unknown response"}
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 ");
1305 esc("H"); /* Cursor home */
1306 esc("J"); /* Erase to end of screen */
1309 printf("nothing more.");
1310 for (i = 1; i <= 10; i++) printf("THIS SHOULD GO AWAY! ");
1311 for (i = 1; i <= 5; i++) {
1313 printf("%s", "Back scroll (this should go away)");
1314 esc("I"); /* Reverse LineFeed (with backscroll!) */
1317 esc("J"); /* Erase to end of screen */
1318 for (i = 2; i <= 6; i++) {
1320 esc("K"); /* Erase to end of line */
1323 for (i = 2; i <= 23; i++) {
1324 vt52cup(i,70); printf("%s", "**Foobar");
1327 for (i = 23; i >= 2; i--) {
1329 printf("%c", 8); /* BS */
1330 esc("I"); /* Reverse LineFeed (LineStarve) */
1333 for (i = 70; i >= 10; i--) {
1335 esc("D"); esc("D"); /* Cursor Left */
1338 for (i = 10; i <= 70; i++) {
1340 printf("%c", 8); /* BS */
1341 esc("C"); /* Cursor Right */
1344 for (i = 2; i <= 23; i++) {
1346 printf("%c", 8); /* BS */
1347 esc("B"); /* Cursor Down */
1350 for (i = 23; i >= 2; i--) {
1352 printf("%c", 8); /* BS */
1353 esc("A"); /* Cursor Up */
1355 for (i = 2; i <= 23; i++) {
1357 esc("K"); /* Erase to end of line */
1361 printf("%s", "The screen should be cleared, and have a centered");
1363 printf("%s", "rectangle of \"*\"s with \"!\"s on the inside to the");
1365 printf("%s", "left and right. Only this, and");
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++) {
1374 for (i = 0; i <= 47; i++)
1375 printf("%c", 32 + i + 48 * j);
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++) {
1382 for (i = 0; i <= 47; i++)
1383 printf("%c", 32 + i + 48 * j);
1385 esc("G"); /* Select ASCII character set */
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 */
1395 printf("Response was");
1396 esc("<"); /* Enter ANSI mode (VT100 mode) */
1398 for(i = 0; resptable[i].rcode[0] != '\0'; i++)
1399 if (!strcmp(response, resptable[i].rcode))
1401 printf("%s", resptable[i].rmsg);
1410 SM/RM(4) (= IRM (Insertion/replacement mode))
1411 ICH (Insert Character)
1412 DCH (Delete character)
1417 int i, row, col, sw, dblchr, scr132;
1419 for(scr132 = 0; scr132 <= 1; scr132++) {
1420 if (scr132) { sm("?3"); sw = 132; }
1421 else { rm("?3"); sw = 80; }
1424 for (row=1; row<=24; row++) {
1426 for (col=1; col<=sw; col++)
1427 printf("%c", 'A'-1+row);
1430 printf("Screen accordion test (Insert & Delete Line). "); holdit();
1435 for (row=1; row<=24; row++) {
1443 "Top line: A's, bottom line: X's, this line, nothing more. ");
1450 for (col=2; col<=sw-1; col++)
1454 printf("Test of 'Insert Mode'. The top line should be 'A*** ... ***B'. ");
1455 holdit(); ri(); el(2);
1459 printf("Test of 'Delete Character'. The top line should be 'AB'. ");
1462 for(dblchr = 1; dblchr <= 2; dblchr++) {
1464 for (row=1; row<=24; row++) {
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);
1473 println("The right column should be staggered ");
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");
1484 for (i = 'Z'; i >= 'A'; i--) {
1491 if (sw == 132) rm("?3");
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 */
1500 /* Test of some known VT100 bugs and misfeatures */
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",
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.",
1534 for (i = 0; *hmsg[i]; i++) println(hmsg[i]);
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;
1549 } while (menuchoice);
1552 /* Bug A: Smooth scroll to jump scroll */
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.");
1563 /* Invoke the bug */
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");
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);
1579 println("That should have been enough to show the bug, if present.");
1583 /* Bug B: Scrolling region */
1590 printf("Line 11 should be double-wide, line 12 should be cleared.");
1592 printf("Then, the letters A-P should be written at the beginning");
1594 printf("of lines 12-24, and the empty line and A-E are scrolled away.");
1596 printf("If the bug is present, some lines are confused, look at K-P.");
1597 cup(11,1); decdwl();
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 */
1603 decstbm(0,0); /* No scr. region */
1606 /* Bug C: Wide to narrow screen */
1609 sm("?3"); /* 132 column mode */
1611 rm("?3"); /* 80 column mode */
1613 printf("Except for this line, the screen should be blank. ");
1617 /* Bug D: Narrow to wide screen */
1622 /* Make the bug appear */
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).
1632 sm("?3"); /* Make the bug visible */
1634 println("You should see blinking text at the bottom line.");
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("");
1640 result = inchar(); readnl();
1642 } while (result == '1');
1643 sm("?4"); /* Syrup scroll */
1645 for (i = 1; i <= 5; i++)
1646 println("If the bug is present, this should make things much worse!");
1648 rm("?4"); /* Jump scroll */
1651 /* Bug E: Cursor move from double- to single-wide line */
1655 static char *rend[2] = { "\033[m", "\033[7m" };
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. */
1663 cup(4, 66); printf("! !");
1665 printf("--------------------------- The 'X' should NOT be above here -");
1666 printf("---+------------ but above here -----+");
1667 cup(10,1); decdwl(); holdit();
1671 /* Bug F: Column mode escape sequence */
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.
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.");
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.");
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
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.");
1716 for (col = 1; col <= 79; col++)
1718 for (row = 1; row <= 24; row++) {
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.
1731 * A VT100 has this misfeature, and many others. Foo!
1736 printf("This-is-a-long-line-This-is-a-long-line-");
1737 printf("This-is-a-long-line-This-is-a-long-line-");
1739 printf("This is a test of what happens to the right half of double-width");
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.");
1747 println("Now the line below should contain 80 characters in single width.");
1749 cup(15, 1); decdwl();
1751 println("Now the line below should contain 40 characters in double width.");
1753 cup(15, 1); decswl();
1755 println("Now the line below should contain 80 characters in single width.");
1758 /* ...and in 132 column mode */
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-");
1769 printf("This is the same test in 132 column mode.");
1772 println("Now the line below should contain 132 characters in single width.");
1774 cup(15, 1); decdwl();
1776 println("Now the line below should contain 66 characters in double width.");
1778 cup(15, 1); decswl();
1780 println("Now the line below should contain 132 characters in single width.");
1787 decstbm(20,10); /* 20-10=-10, < 2, so no scroll region. */
1789 for (i=1; i<=20; i++)
1790 printf("This is 20 lines of text (line %d), no scroll region.\n", i);
1793 decstbm(0,1); /* Should be interpreted as decstbm(1,1) = none */
1795 for (i=1; i<=20; i++)
1796 printf("This is 20 lines of text (line %d), no scroll region.\n", i);
1798 decstbm(0,0); /* No scroll region (just in case...) */
1805 * - RIS (Reset to Initial State)
1806 * - DECTST (invoke terminal test)
1810 printf ("The terminal will now be RESET. ");
1816 zleep(5000); /* Wait 5.0 seconds */
1818 println("The terminal is now RESET. Next, the built-in confidence test");
1819 printf("%s", "will be invoked. ");
1826 zleep(5000); /* Wait 5.0 seconds */
1828 println("If the built-in confidence test found any errors, a code");
1829 printf("%s", "is visible above. ");
1833 initterminal(pn) int pn; {
1840 sgttyNew.sg_flags |= CBREAK;
1846 sgttyNew.sg_flags = sgttyOrg.sg_flags | CBREAK;
1851 open(_PATH_TTY,O_RDWR|O_NDELAY);
1855 /* Set up neccesary TOPS-10 terminal parameters */
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 */
1869 ttybin(1); /* set line to binary mode */
1871 /* Set up my personal prejudices */
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 */
1887 /* Force my personal prejudices upon the poor luser */
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 */
1903 printf("That's all, folks!\n");
1907 ttybin(0); /* reset line to normal mode */
1917 signal(SIGINT, onbrk);
1921 longjmp(intrenv, 1);
1925 signal(SIGTERM, onterm);
1926 longjmp(intrenv, 1);
1932 printf("Push <RETURN>");
1942 do { read(0,&ch,1); } while(ch != '\n' && !brkrd);
1944 kill(getpid(), SIGTERM);
1948 while (getchar() != '\n')
1952 while (getchar() != '\n')
1957 scanto(str, pos, toc) char *str; int *pos; char toc; {
1961 while (toc != (c = str[(*pos)++])) {
1962 if (isdigit(c)) result = result * 10 + c - '0';
1965 if (c == toc) return(result);
1969 char *lookup(t, k) struct table t[]; int k; {
1972 for (i = 0; t[i].key != -1; i++) {
1973 if (t[i].key == k) return(t[i].msg);
1975 return("BAD VALUE");
1978 menu(table) char *table[]; {
1980 int i, tablesize, choice;
1986 for (i = 0; *table[i] != '\0'; i++) {
1987 printf(" %d. %s\n", i, table[i]);
1992 printf("\n Enter choice number (0 - %d): ", tablesize);
1996 while (c = *s++) choice = 10 * choice + c - '0';
1997 if (choice >= 0 && choice <= tablesize) {
2001 printf(" Bad choice, try again: ");
2005 chrprint (s) char *s; {
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]);