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.
20 char inchar(), *instr(), *lookup();
58 static char *mainmenu
[] = {
60 "Test of cursor movements",
61 "Test of screen features",
62 "Test of character sets",
63 "Test of double-sized characters",
65 "Test of terminal reports",
67 "Test of VT102 features (Insert/Delete Char/Line)",
69 "Test of reset and self-test",
74 initterminal(setjmp(intrenv
));
75 signal(SIGINT
, onbrk
);
76 signal(SIGTERM
, onterm
);
83 ttybin(1); /* set line to binary mode again. It's reset somehow!! */
86 cup(5,10); printf("VT100 test program, version %s", VERSION
);
87 cup(7,10); println("Choose test type:");
88 menuchoice
= menu(mainmenu
);
90 case 1: tst_movements(); break;
91 case 2: tst_screen(); break;
92 case 3: tst_characters(); break;
93 case 4: tst_doublesize(); break;
94 case 5: tst_keyboard(); break;
95 case 6: tst_reports(); break;
96 case 7: tst_vt52(); break;
97 case 8: tst_insdel(); break;
98 case 9: tst_bugs(); break;
99 case 10: tst_rst(); break;
101 } while (menuchoice
);
109 CUB (Cursor Backward)
110 CUD (Cursor Down) IND (Index) NEL (Next Line)
111 CUU (Cursor Up) RI (Reverse Index)
112 CUP (Cursor Position) HVP (Horizontal and Vertical Position)
113 ED (Erase in Display)
115 DECALN (Screen Alignment Display)
117 Cursor control characters inside CSI sequences
120 int i
, row
, col
, pass
, width
, hlfxtra
;
121 char c
, *ctext
= "This is a correct sentence";
123 for (pass
= 0; pass
<= 1; pass
++) {
124 if (pass
== 0) { rm("?3"); width
= 80; hlfxtra
= 0; }
125 else { sm("?3"); width
= 132; hlfxtra
= 26; }
128 cup( 9,10+hlfxtra
); ed(1);
129 cup(18,60+hlfxtra
); ed(0); el(1);
130 cup( 9,71+hlfxtra
); el(0);
131 for (row
= 10; row
<= 16; row
++) {
132 cup(row
, 10+hlfxtra
); el(1);
133 cup(row
, 71+hlfxtra
); el(0);
136 for (col
= 1; col
<= width
; col
++) {
137 hvp(24, col
); printf("*");
138 hvp( 1, col
); printf("*");
141 for (row
= 2; row
<= 23; row
++) {
147 for (row
= 23; row
>=2; row
--) {
152 for (row
= 2; row
<= 23; row
++) {
153 printf("*"); cup(row
, width
);
160 cub(42+hlfxtra
); cuf(2);
161 for (col
= 3; col
<= width
-2; col
++) {
163 cuf(0); cub(2); cuf(1);
166 cuf(42+hlfxtra
); cub(2);
167 for (col
= width
-2; col
>= 3; col
--) {
169 cub(1); cuf(1); cub(0); printf("%c", 8);
171 cup( 1, 1); cuu(10); cuu(1); cuu(0);
172 cup(24,width
); cud(10); cud(1); cud(0);
175 for (row
= 10; row
<= 15; row
++) {
176 for (col
= 12+hlfxtra
; col
<= 69+hlfxtra
; col
++) printf(" ");
180 printf("The screen should be cleared, and have an unbroken bor-");
182 printf("der of *'s and +'s around the edge, and exactly in the");
184 printf("middle there should be a frame of E's around this text");
186 printf("with one (1) free position around it. ");
193 println("Test of cursor-control characters inside ESC sequences.");
194 println("Below should be two identical lines:");
196 println("A B C D E F G H I J K L M N O P Q R S");
197 for (i
= 1; i
< 20; i
++) {
198 printf("%c", 64 + i
);
199 brcstr("2\010", 'C'); /* Two forward, one backspace */
207 println("Test of leading zeros in ESC sequences.");
208 printf("Two lines below you should see the sentence \"%s\".",ctext
);
209 for (col
= 1; *ctext
; col
++)
210 printf("\033[00000000004;00000000%dH%c",col
,*ctext
++);
218 - DECSTBM (Set Top and Bottom Margins)
219 - TBC (Tabulation Clear)
220 - HTS (Horizontal Tabulation Set)
221 - SM RM (Set/Reset mode): - 80/132 chars
222 - Origin: Realtive/absolute
223 - Scroll: Smooth/jump
225 - SGR (Select Graphic Rendition)
226 - SM RM (Set/Reset Mode) - Inverse
227 - DECSC (Save Cursor)
228 - DECRC (Restore Cursor)
231 int i
, j
, cset
, row
, col
, down
, soft
, background
;
233 static char *tststr
= "*qx`";
234 static char *attr
[5] = { ";0", ";1", ";4", ";5", ";7" };
237 sm("?7"); /* Wrap Around ON */
238 for (col
= 1; col
<= 160; col
++) printf("*");
239 rm("?7"); /* Wrap Around OFF */
241 for (col
= 1; col
<= 160; col
++) printf("*");
242 sm("?7"); /* Wrap Around ON */
244 println("This should be three identical lines of *'s completely filling");
245 println("the top of the screen without any empty lines between.");
246 println("(Test of WRAP AROUND mode setting.)");
252 for (col
= 1; col
<= 78; col
+= 3) {
256 for (col
= 4; col
<= 78; col
+= 6) {
259 cup(1,7); tbc(1); tbc(2); /* no-op */
260 cup(1,1); for (col
= 1; col
<= 78; col
+= 6) printf("\t*");
261 cup(2,2); for (col
= 2; col
<= 78; col
+= 6) printf(" *");
263 println("Test of TAB setting/resetting. These two lines");
264 printf("should look the same. ");
266 for (background
= 0; background
<= 1; background
++) {
267 if (background
) rm("?5");
269 sm("?3"); /* 132 cols */
270 ed(2); /* VT100 clears screen on SM3/RM3, but not obviously, so... */
272 for (col
= 1; col
<= 132; col
+= 8) {
275 cup(1,1); for (col
= 1; col
<= 130; col
+= 10) printf("1234567890");
277 for (row
= 3; row
<= 20; row
++) {
279 printf("This is 132 column mode, %s background.",
280 background
? "dark" : "light");
283 rm("?3"); /* 80 cols */
284 ed(2); /* VT100 clears screen on SM3/RM3, but not obviously, so... */
285 cup(1,1); for (col
= 1; col
<= 80; col
+= 10) printf("1234567890");
286 for (row
= 3; row
<= 20; row
++) {
288 printf("This is 80 column mode, %s background.",
289 background
? "dark" : "light");
294 sm("?6"); /* Origin mode (relative) */
295 for (soft
= -1; soft
<= 0; soft
++) {
298 for (row
= 12; row
>= 1; row
-= 11) {
299 decstbm(row
, 24-row
+1);
301 for (down
= 0; down
>= -1; down
--) {
304 for (i
= 1; i
<= 30; i
++) {
305 printf("%s scroll %s region %d Line %d\n",
306 soft
? "Soft" : "Jump",
307 down
? "down" : "up",
309 if (down
) { ri(); ri(); }
318 "\nOrigin mode test. This line should be at the bottom of the screen.");
321 "This line should be the one above the bottom of the screeen. ");
324 rm("?6"); /* Origin mode (absolute) */
327 "Origin mode test. This line should be at the bottom of the screen.");
329 printf("%s", "This line should be at the top if the screen. ");
334 cup( 1,20); printf("Graphic rendition test pattern:");
335 cup( 4, 1); sgr("0"); printf("vanilla");
336 cup( 4,40); sgr("0;1"); printf("bold");
337 cup( 6, 6); sgr(";4"); printf("underline");
338 cup( 6,45);sgr(";1");sgr("4");printf("bold underline");
339 cup( 8, 1); sgr("0;5"); printf("blink");
340 cup( 8,40); sgr("0;5;1"); printf("bold blink");
341 cup(10, 6); sgr("0;4;5"); printf("underline blink");
342 cup(10,45); sgr("0;1;4;5"); printf("bold underline blink");
343 cup(12, 1); sgr("1;4;5;0;7"); printf("negative");
344 cup(12,40); sgr("0;1;7"); printf("bold negative");
345 cup(14, 6); sgr("0;4;7"); printf("underline negative");
346 cup(14,45); sgr("0;1;4;7"); printf("bold underline negative");
347 cup(16, 1); sgr("1;4;;5;7"); printf("blink negative");
348 cup(16,40); sgr("0;1;5;7"); printf("bold blink negative");
349 cup(18, 6); sgr("0;4;5;7"); printf("underline blink negative");
350 cup(18,45); sgr("0;1;4;5;7"); printf("bold underline blink negative");
353 rm("?5"); /* Inverse video off */
354 cup(23,1); el(0); printf("Dark background. "); holdit();
355 sm("?5"); /* Inverse video */
356 cup(23,1); el(0); printf("Light background. "); holdit();
359 cup(8,12); printf("normal");
360 cup(8,24); printf("bold");
361 cup(8,36); printf("underscored");
362 cup(8,48); printf("blinking");
363 cup(8,60); printf("reversed");
364 cup(10,1); printf("stars:");
365 cup(12,1); printf("line:");
366 cup(14,1); printf("x'es:");
367 cup(16,1); printf("diamonds:");
368 for (cset
= 0; cset
<= 3; cset
++) {
369 for (i
= 0; i
<= 4; i
++) {
370 cup(10 + 2 * cset
, 12 + 12 * i
);
372 if (cset
== 0 || cset
== 2) scs(0,'B');
374 for (j
= 0; j
<= 4; j
++) {
375 printf("%c", tststr
[cset
]);
378 cup(cset
+ 1, i
+ 1); sgr(""); scs(0,'B'); printf("A");
380 for (j
= 0; j
<= 4; j
++) {
381 printf("%c", tststr
[cset
]);
385 sgr("0"); scs(0,'B'); cup(21,1);
386 println("Test of the SAVE/RESTORE CURSOR feature. There should");
387 println("be ten characters of each flavour, and a rectangle");
388 println("of 5 x 4 A's filling the top left of the screen.");
394 SCS (Select character Set)
398 char chcode
[5], *setmsg
[5];
405 setmsg
[0] = "UK / national";
406 setmsg
[1] = "US ASCII";
407 setmsg
[2] = "Special graphics and line drawing";
408 setmsg
[3] = "Alternate character ROM standard characters";
409 setmsg
[4] = "Alternate character ROM special graphics";
411 cup(1,10); printf("Selected as G0 (with SI)");
412 cup(1,48); printf("Selected as G1 (with SO)");
413 for (cset
= 0; cset
<= 4; cset
++) {
415 cup(3 + 4 * cset
, 1);
417 printf("Character set %c (%s)",chcode
[cset
], setmsg
[cset
]);
419 for (g
= 0; g
<= 1; g
++) {
421 for (i
= 1; i
<= 3; i
++) {
422 cup(3 + 4 * cset
+ i
, 10 + 38 * g
);
423 for (j
= 0; j
<= 31; j
++) {
424 printf("%c", i
* 32 + j
);
430 cup(24,1); printf("These are the installed character sets. ");
436 DECSWL (Single Width Line)
437 DECDWL (Double Width Line)
438 DECDHL (Double Height Line) (also implicit double width)
443 /* Print the test pattern in both 80 and 132 character width */
445 for(w
= 0; w
<= 1; w
++) {
450 if (w
) { sm("?3"); printf("132 column mode"); }
451 else { rm("?3"); printf(" 80 column mode"); }
454 printf("v------- left margin");
457 printf("This is a normal-sized line");
458 decdhl(0); decdhl(1); decdwl(); decswl();
461 printf("This is a Double-width line");
462 decswl(); decdhl(0); decdhl(1); decdwl();
465 decdwl(); decswl(); decdhl(1); decdhl(0);
466 printf("This is a Double-width-and-height line");
468 decdwl(); decswl(); decdhl(0); decdhl(1);
469 printf("This is a Double-width-and-height line");
472 decdwl(); decswl(); decdhl(1); decdhl(0); el(2);
473 printf("This is another such line");
475 decdwl(); decswl(); decdhl(0); decdhl(1);
476 printf("This is another such line");
479 printf("^------- left margin");
482 printf("This is not a double-width line");
483 for (i
= 0; i
<= 1; i
++) {
485 if (i
) { printf("**is**"); decdwl(); }
486 else { printf("is not"); decswl(); }
490 /* Set vanilla tabs for next test */
491 cup(1,1); tbc(3); for (col
= 1; col
<= 132; col
+= 8) { cuf(8); hts(); }
496 cup( 8,1); decdhl(0); printf("lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk");
497 cup( 9,1); decdhl(1); printf("lqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqk");
498 cup(10,1); decdhl(0); printf("x%c%c%c%c%cx",9,9,9,9,9);
499 cup(11,1); decdhl(1); printf("x%c%c%c%c%cx",9,9,9,9,9);
500 cup(12,1); decdhl(0); printf("x%c%c%c%c%cx",9,9,9,9,9);
501 cup(13,1); decdhl(1); printf("x%c%c%c%c%cx",9,9,9,9,9);
502 cup(14,1); decdhl(0); printf("x x");
503 cup(15,1); decdhl(1); printf("x x");
504 cup(16,1); decdhl(0); printf("mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj");
505 cup(17,1); decdhl(1); printf("mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqj");
506 scs(0,'B'); sgr("1;5");
508 printf("* The mad programmer strikes again * ");
509 cup(13,3); printf("%c",9); cub(6);
510 printf("* The mad programmer strikes again *");
513 println("Another test pattern... a frame with blinking bold text,");
514 printf("all in double-height double-width size. ");
517 decstbm(8,24); /* Absolute origin mode, so cursor is set at (1,1) */
519 for (i
= 1; i
<= 12; i
++)
521 decstbm(0,0); /* No scroll region */
523 printf("%s", "Exactly half of the box should remain. ");
531 - Keyboard return messages
532 - SM RM (Set/Reset Mode) - Cursor Keys
534 - DECKPAM (Keypad Application Mode)
535 - DECKPNM (Keypad Numeric Mode)
537 The standard VT100 keayboard layout:
541 ESC 1! 2@ 3# 4$ 5% 6^ 7& 8* 9( 0) -_ =+ `~ BS
543 TAB* qQ wW eE rR tT yY uU iI oO pP [{ ]} DEL
545 ** ** aA sS dD fF gG hH jJ kK lL ;: ," RETN \|
547 ** **** zZ xX cC vV bB nN mM ,< .> /? **** LF
549 ****************SPACE BAR****************
562 char *ledmsg
[6], *ledseq
[6];
570 char *curkeystr
, *fnkeystr
, *abmstr
;
571 char arptstring
[500];
580 { '1', 1, 6, "1" }, { '!', 1, 7, "!" },
581 { '2', 1, 11, "2" }, { '@', 1, 12, "@" },
582 { '3', 1, 16, "3" }, { '#', 1, 17, "#" },
583 { '4', 1, 21, "4" }, { '$', 1, 22, "$" },
584 { '5', 1, 26, "5" }, { '%', 1, 27, "%" },
585 { '6', 1, 31, "6" }, { '^', 1, 32, "^" },
586 { '7', 1, 36, "7" }, { '&', 1, 37, "&" },
587 { '8', 1, 41, "8" }, { '*', 1, 42, "*" },
588 { '9', 1, 46, "9" }, { '(', 1, 47, "(" },
589 { '0', 1, 51, "0" }, { ')', 1, 52, ")" },
590 { '-', 1, 56, "-" }, { '_', 1, 57, "_" },
591 { '=', 1, 61, "=" }, { '+', 1, 62, "+" },
592 { '`', 1, 66, "`" }, { '~', 1, 67, "~" },
594 { 9, 2, 0, " TAB " },
595 { 'q', 2, 8, "q" }, { 'Q', 2, 9, "Q" },
596 { 'w', 2, 13, "w" }, { 'W', 2, 14, "W" },
597 { 'e', 2, 18, "e" }, { 'E', 2, 19, "E" },
598 { 'r', 2, 23, "r" }, { 'R', 2, 24, "R" },
599 { 't', 2, 28, "t" }, { 'T', 2, 29, "T" },
600 { 'y', 2, 33, "y" }, { 'Y', 2, 34, "Y" },
601 { 'u', 2, 38, "u" }, { 'U', 2, 39, "U" },
602 { 'i', 2, 43, "i" }, { 'I', 2, 44, "I" },
603 { 'o', 2, 48, "o" }, { 'O', 2, 49, "O" },
604 { 'p', 2, 53, "p" }, { 'P', 2, 54, "P" },
605 { '[', 2, 58, "[" }, { '{', 2, 59, "{" },
606 { ']', 2, 63, "]" }, { '}', 2, 64, "}" },
607 { 127, 2, 71, "DEL" },
608 { 'a', 3, 10, "a" }, { 'A', 3, 11, "A" },
609 { 's', 3, 15, "s" }, { 'S', 3, 16, "S" },
610 { 'd', 3, 20, "d" }, { 'D', 3, 21, "D" },
611 { 'f', 3, 25, "f" }, { 'F', 3, 26, "F" },
612 { 'g', 3, 30, "g" }, { 'G', 3, 31, "G" },
613 { 'h', 3, 35, "h" }, { 'H', 3, 36, "H" },
614 { 'j', 3, 40, "j" }, { 'J', 3, 41, "J" },
615 { 'k', 3, 45, "k" }, { 'K', 3, 46, "K" },
616 { 'l', 3, 50, "l" }, { 'L', 3, 51, "L" },
617 { ';', 3, 55, ";" }, { ':', 3, 56, ":" },
618 {'\'', 3, 60, "'" }, { '"', 3, 61,"\"" },
619 { 13, 3, 65, "RETN"},
620 {'\\', 3, 71,"\\" }, { '|', 3, 72, "|" },
621 { 'z', 4, 12, "z" }, { 'Z', 4, 13, "Z" },
622 { 'x', 4, 17, "x" }, { 'X', 4, 18, "X" },
623 { 'c', 4, 22, "c" }, { 'C', 4, 23, "C" },
624 { 'v', 4, 27, "v" }, { 'V', 4, 28, "V" },
625 { 'b', 4, 32, "b" }, { 'B', 4, 33, "B" },
626 { 'n', 4, 37, "n" }, { 'N', 4, 38, "N" },
627 { 'm', 4, 42, "m" }, { 'M', 4, 43, "M" },
628 { ',', 4, 47, "," }, { '<', 4, 48, "<" },
629 { '.', 4, 52, "." }, { '>', 4, 53, ">" },
630 { '/', 4, 57, "/" }, { '?', 4, 58, "?" },
632 { ' ', 5, 13, " SPACE BAR "},
636 static struct natkey
{
641 } natkeytab
[][29] = {
649 { '+', 1, 56, "+" }, { '?', 1, 57, "?" },
650 { '`', 1, 61, "`" }, { '@', 1, 62, "@" },
651 { '<', 1, 66, "<" }, { '>', 1, 67, ">" },
652 { '}', 2, 58, "}" }, { ']', 2, 59, "]" },
653 { '^', 2, 63, "^" }, { '~', 2, 64, "~" },
654 { '|', 3, 55, "|" }, {'\\', 3, 56,"\\" },
655 { '{', 3, 60, "{" }, { '[', 3, 61, "[" },
656 {'\'', 3, 71, "'" }, { '*', 3, 72, "*" },
657 { ',', 4, 47, "," }, { ';', 4, 48, ";" },
658 { '.', 4, 52, "." }, { ':', 4, 53, ":" },
659 { '-', 4, 57, "-" }, { '_', 4, 58, "_" },
669 { '+', 1, 56, "+" }, { '?', 1, 57, "?" },
670 { '`', 1, 61, "`" }, { '@', 1, 62, "@" },
671 { '<', 1, 66, "<" }, { '>', 1, 67, ">" },
672 { '}', 2, 58, "}" }, { ']', 2, 59, "]" },
673 { '~', 2, 63, "~" }, { '^', 2, 64, "^" },
674 { '|', 3, 55, "|" }, {'\\', 3, 56,"\\" },
675 { '{', 3, 60, "{" }, { '[', 3, 61, "[" },
676 {'\'', 3, 71, "'" }, { '*', 3, 72, "*" },
677 { ',', 4, 47, "," }, { ';', 4, 48, ";" },
678 { '.', 4, 52, "." }, { ':', 4, 53, ":" },
679 { '-', 4, 57, "-" }, { '_', 4, 58, "_" },
684 static struct curkey
{
692 /* A Reset, A Set, VT52 */
694 {{"\033[A","\033OA","\033A"}, 0, 56, "UP", "Up arrow" },
695 {{"\033[B","\033OB","\033B"}, 0, 61, "DN", "Down arrow" },
696 {{"\033[D","\033OD","\033D"}, 0, 66, "LT", "Left arrow" },
697 {{"\033[C","\033OC","\033C"}, 0, 71, "RT", "Right arrow"},
698 {{"", "", "" }, 0, 0, "", "" }
701 static struct fnkey
{
709 /* ANSI-num,ANSI-app,VT52-nu,VT52-ap, r, c, symb name */
711 {{"\033OP","\033OP","\033P","\033P" }, 6, 59, "PF1", "PF1" },
712 {{"\033OQ","\033OQ","\033Q","\033Q" }, 6, 63, "PF2", "PF2" },
713 {{"\033OR","\033OR","\033R","\033R" }, 6, 67, "PF3", "PF3" },
714 {{"\033OS","\033OS","\033S","\033S" }, 6, 71, "PF4", "PF4" },
715 {{"7", "\033Ow","7", "\033?w"}, 7, 59, " 7 ", "Numeric 7" },
716 {{"8", "\033Ox","8", "\033?x"}, 7, 63, " 8 ", "Numeric 8" },
717 {{"9", "\033Oy","9", "\033?y"}, 7, 67, " 9 ", "Numeric 9" },
718 {{"-", "\033Om","-", "\033?m"}, 7, 71, " - ", "Minus" },
719 {{"4", "\033Ot","4", "\033?t"}, 8, 59, " 4 ", "Numeric 4" },
720 {{"5", "\033Ou","5", "\033?u"}, 8, 63, " 5 ", "Numeric 5" },
721 {{"6", "\033Ov","6", "\033?v"}, 8, 67, " 6 ", "Numeric 6" },
722 {{",", "\033Ol",",", "\033?l"}, 8, 71, " , ", "Comma" },
723 {{"1", "\033Oq","1", "\033?q"}, 9, 59, " 1 ", "Numeric 1" },
724 {{"2", "\033Or","2", "\033?r"}, 9, 63, " 2 ", "Numeric 2" },
725 {{"3", "\033Os","3", "\033?s"}, 9, 67, " 3 ", "Numeric 3" },
726 {{"0", "\033Op","0", "\033?p"},10, 59," O ","Numeric 0"},
727 {{".", "\033On",".", "\033?n"},10, 67, " . ", "Point" },
728 {{"\015", "\033OM","\015", "\033?M"},10, 71, "ENT", "ENTER" },
729 {{"","","",""}, 0, 0, "", "" }
736 { 0, "NUL (CTRL-@ or CTRL-Space)" },
737 { 0, "SOH (CTRL-A)" },
738 { 0, "STX (CTRL-B)" },
739 { 0, "ETX (CTRL-C)" },
740 { 0, "EOT (CTRL-D)" },
741 { 0, "ENQ (CTRL-E)" },
742 { 0, "ACK (CTRL-F)" },
743 { 0, "BEL (CTRL-G)" },
744 { 0, "BS (CTRL-H) (BACK SPACE)" },
745 { 0, "HT (CTRL-I) (TAB)" },
746 { 0, "LF (CTRL-J) (LINE FEED)" },
747 { 0, "VT (CTRL-K)" },
748 { 0, "FF (CTRL-L)" },
749 { 0, "CR (CTRL-M) (RETURN)" },
750 { 0, "SO (CTRL-N)" },
751 { 0, "SI (CTRL-O)" },
752 { 0, "DLE (CTRL-P)" },
753 { 0, "DC1 (CTRL-Q) (X-On)" },
754 { 0, "DC2 (CTRL-R)" },
755 { 0, "DC3 (CTRL-S) (X-Off)" },
756 { 0, "DC4 (CTRL-T)" },
757 { 0, "NAK (CTRL-U)" },
758 { 0, "SYN (CTRL-V)" },
759 { 0, "ETB (CTRL-W)" },
760 { 0, "CAN (CTRL-X)" },
761 { 0, "EM (CTRL-Y)" },
762 { 0, "SUB (CTRL-Z)" },
763 { 0, "ESC (CTRL-[) (ESCAPE)" },
764 { 0, "FS (CTRL-\\ or CTRL-? or CTRL-_)" },
765 { 0, "GS (CTRL-])" },
766 { 0, "RS (CTRL-^ or CTRL-~ or CTRL-`)" },
767 { 0, "US (CTRL-_ or CTRL-?)" }
770 static char *keyboardmenu
[] = {
771 "Standard American ASCII layout",
772 "Swedish national layout D47",
773 "Swedish national layout E47",
774 /* add new keyboard layouts here */
778 static char *curkeymodes
[3] = {
779 "ANSI / Cursor key mode RESET",
780 "ANSI / Cursor key mode SET",
784 static char *fnkeymodes
[4] = {
786 "ANSI Application mode",
788 "VT52 Application mode"
791 ledmsg
[0] = "L1 L2 L3 L4"; ledseq
[0] = "1;2;3;4";
792 ledmsg
[1] = " L2 L3 L4"; ledseq
[1] = "1;0;4;3;2";
793 ledmsg
[2] = " L2 L3"; ledseq
[2] = "1;4;;2;3";
794 ledmsg
[3] = "L1 L2"; ledseq
[3] = ";;2;1";
795 ledmsg
[4] = "L1"; ledseq
[4] = "1";
796 ledmsg
[5] = ""; ledseq
[5] = "";
804 println("These LEDs (\"lamps\") on the keyboard should be on:");
805 for (i
= 0; i
<= 5; i
++) {
806 cup(10,52); el(0); printf("%s", ledmsg
[i
]);
814 println("Test of the AUTO REPEAT feature");
816 println("Hold down an alphanumeric key for a while, then push RETURN.");
817 printf("%s", "Auto Repeat OFF: ");
819 inputline(arptstring
);
820 if (strlen(arptstring
) == 0) println("No characters read!??");
821 else if (strlen(arptstring
) == 1) println("OK.");
822 else println("Too many characters read.");
824 println("Hold down an alphanumeric key for a while, then push RETURN.");
825 printf("%s", "Auto Repeat ON: ");
827 inputline(arptstring
);
828 if (strlen(arptstring
) == 0) println("No characters read!??");
829 else if (strlen(arptstring
) == 1) println("Not enough characters read.");
836 println("Choose keyboard layout:");
837 kblayout
= menu(keyboardmenu
);
840 for (j
= 0; natkeytab
[kblayout
][j
].natc
!= '\0'; j
++) {
841 for (i
= 0; keytab
[i
].c
!= '\0'; i
++) {
842 if (keytab
[i
].row
== natkeytab
[kblayout
][j
].natrow
&&
843 keytab
[i
].col
== natkeytab
[kblayout
][j
].natcol
) {
844 keytab
[i
].c
= natkeytab
[kblayout
][j
].natc
;
845 keytab
[i
].symbol
= natkeytab
[kblayout
][j
].natsymbol
;
853 for (i
= 0; keytab
[i
].c
!= '\0'; i
++) {
854 cup(1 + 2 * keytab
[i
].row
, 1 + keytab
[i
].col
);
856 printf("%s", keytab
[i
].symbol
);
862 termioNew
.c_iflag
&= (~ICRNL
);
863 termioNew
.c_oflag
&= (~ONLCR
);
864 termioNew
.c_lflag
&= (~ECHO
& ~ECHOE
& ~ECHOK
& ~ECHONL
);
865 (void) ioctl(0, TCSETAW
, &termioNew
);
867 sgttyNew
.sg_flags
&= ~CRMOD
;
868 sgttyNew
.sg_flags
&= ~ECHO
;
873 printf("Press each key, both shifted and unshifted. Finish with RETURN:");
874 do { /* while (kbdc != 13) */
875 cup(23,1); kbdc
= inchar();
877 sprintf(kbds
, "%c", kbdc
);
879 for (i
= 0; keytab
[i
].c
!= '\0'; i
++) {
880 if (keytab
[i
].c
== kbdc
) {
881 cup(1 + 2 * keytab
[i
].row
, 1 + keytab
[i
].col
);
882 printf("%s", keytab
[i
].symbol
);
886 } while (kbdc
!= 13);
888 inchar(); /* Local hack: Read LF that TOPS-10 adds to CR */
892 for (ckeymode
= 0; ckeymode
<= 2; ckeymode
++) {
893 if (ckeymode
) sm("?1");
895 for (i
= 0; curkeytab
[i
].curkeysymbol
[0] != '\0'; i
++) {
896 cup(1 + 2 * curkeytab
[i
].curkeyrow
, 1 + curkeytab
[i
].curkeycol
);
898 printf("%s", curkeytab
[i
].curkeysymbol
);
901 cup(20,1); printf("<%s>%20s", curkeymodes
[ckeymode
], "");
903 cup(22,1); printf("%s", "Press each cursor key. Finish with TAB.");
906 if (ckeymode
== 2) rm("?2"); /* VT52 mode */
908 esc("<"); /* ANSI mode */
910 cup(23,1); chrprint(curkeystr
);
911 if (!strcmp(curkeystr
,"\t")) break;
912 for (i
= 0; curkeytab
[i
].curkeysymbol
[0] != '\0'; i
++) {
913 if (!strcmp(curkeystr
,curkeytab
[i
].curkeymsg
[ckeymode
])) {
915 printf(" (%s key) ", curkeytab
[i
].curkeyname
);
917 cup(1 + 2 * curkeytab
[i
].curkeyrow
,
918 1 + curkeytab
[i
].curkeycol
);
919 printf("%s", curkeytab
[i
].curkeysymbol
);
923 if (i
== sizeof(curkeytab
) / sizeof(struct curkey
) - 1) {
925 printf("%s", " (Unknown cursor key) ");
931 for (fkeymode
= 0; fkeymode
<= 3; fkeymode
++) {
932 for (i
= 0; fnkeytab
[i
].fnkeysymbol
[0] != '\0'; i
++) {
933 cup(1 + 2 * fnkeytab
[i
].fnkeyrow
, 1 + fnkeytab
[i
].fnkeycol
);
935 printf("%s", fnkeytab
[i
].fnkeysymbol
);
938 cup(20,1); printf("<%s>%20s", fnkeymodes
[fkeymode
], "");
940 cup(22,1); printf("%s", "Press each function key. Finish with TAB.");
943 if (fkeymode
>= 2) rm("?2"); /* VT52 mode */
944 if (fkeymode
% 2) deckpam(); /* Application mode */
945 else deckpnm(); /* Numeric mode */
947 esc("<"); /* ANSI mode */
949 cup(23,1); chrprint(fnkeystr
);
950 if (!strcmp(fnkeystr
,"\t")) break;
951 for (i
= 0; fnkeytab
[i
].fnkeysymbol
[0] != '\0'; i
++) {
952 if (!strcmp(fnkeystr
,fnkeytab
[i
].fnkeymsg
[fkeymode
])) {
954 printf(" (%s key) ", fnkeytab
[i
].fnkeyname
);
956 cup(1 + 2 * fnkeytab
[i
].fnkeyrow
, 1 + fnkeytab
[i
].fnkeycol
);
957 printf("%s", fnkeytab
[i
].fnkeysymbol
);
961 if (i
== sizeof(fnkeytab
) / sizeof(struct fnkey
) - 1) {
963 printf("%s", " (Unknown function key) ");
971 termioNew
.c_iflag
|= ICRNL
;
972 termioNew
.c_oflag
|= ONLCR
;
973 (void) ioctl(0, TCSETAW
, &termioNew
);
975 sgttyNew
.sg_flags
|= CRMOD
;
981 println("Finally, a check of the ANSWERBACK MESSAGE, which can be sent");
982 println("by pressing CTRL-BREAK. The answerback message can be loaded");
983 println("in SET-UP B by pressing SHIFT-A and typing e.g.");
985 println(" \" H e l l o , w o r l d Return \"");
987 println("(the double-quote characters included). Do that, and then try");
988 println("to send an answerback message with CTRL-BREAK. If it works,");
989 println("the answerback message should be displayed in reverse mode.");
990 println("Finish with a single RETURN.");
994 termioNew
.c_iflag
&= ~ICRNL
;
995 termioNew
.c_oflag
&= ~ONLCR
;
996 (void) ioctl(0, TCSETAW
, &termioNew
);
998 sgttyNew
.sg_flags
&= ~CRMOD
;
1009 } while (strcmp(abmstr
,"\r"));
1012 for (i
= 0; i
< 32; i
++) {
1013 cup(1 + (i
% 16), 1 + 40 * (i
/ 16));
1015 printf("%s", ckeytab
[i
].csymbol
);
1021 termioNew
.c_iflag
|= ICRNL
;
1022 termioNew
.c_oflag
|= ONLCR
;
1023 (void) ioctl(0, TCSETAW
, &termioNew
);
1025 sgttyNew
.sg_flags
|= CRMOD
;
1031 "Push each CTRL-key TWICE. Note that you should be able to send *all*");
1033 "CTRL-codes twice, including CTRL-S (X-Off) and CTRL-Q (X-Off)!");
1035 "Finish with DEL (also called DELETE or RUB OUT), or wait 1 minute.");
1038 termioNew
.c_iflag
&= ~(ICRNL
|IXON
);
1039 termioNew
.c_lflag
&= ~(ICANON
|ISIG
);
1040 termioNew
.c_cc
[VMIN
] = 1;
1041 termioNew
.c_cc
[VTIME
] = 0;
1042 (void) ioctl(0, TCSETAW
, &termioNew
);
1045 sgttyNew
.sg_flags
&= ~CBREAK
;
1048 sgttyNew
.sg_flags
|= RAW
;
1054 page(0); /* Turn off all character processing at input */
1055 superbin(1); /* Turn off ^C (among others). Keep your fingers crossed!! */
1058 cup(23,1); kbdc
= inchar();
1060 if (kbdc
< 32) printf(" %s", ckeytab
[kbdc
].csymbol
);
1062 sprintf(kbds
, "%c", kbdc
);
1064 printf("%s", " -- not a CTRL key");
1066 if (kbdc
< 32) ckeytab
[kbdc
].ccount
++;
1067 if (ckeytab
[kbdc
].ccount
== 2) {
1068 cup(1 + (kbdc
% 16), 1 + 40 * (kbdc
/ 16));
1069 printf("%s", ckeytab
[kbdc
].csymbol
);
1071 } while (kbdc
!= '\177');
1074 termioNew
.c_iflag
|= (IGNBRK
|BRKINT
|ICRNL
|IXON
);
1075 termioNew
.c_lflag
|= (ICANON
|ECHO
|ISIG
);
1076 (void) ioctl(0, TCSETAW
, &termioNew
);
1078 sgttyNew
.sg_flags
&= ~RAW
;
1079 sgttyNew
.sg_flags
|= ECHO
;
1082 sgttyNew
.sg_flags
|= CBREAK
;
1089 superbin(0); /* Puuuh! We made it!? */
1090 page(1); /* Back to normal input processing */
1091 ttybin(1); /* This must be the mode for DEC20 */
1095 for (i
= 0; i
< 32; i
++) if (ckeytab
[i
].ccount
< 2) okflag
= 0;
1096 if (okflag
) printf("%s", "OK. ");
1097 else printf("%s", "You have not been able to send all CTRL keys! ");
1103 <ENQ> (AnswerBack Message)
1104 SM RM (Set/Reset Mode) - LineFeed / Newline
1105 DSR (Device Status Report)
1106 DA (Device Attributes)
1107 DECREQTPARM (Request Terminal Parameters)
1110 int parity
, nbits
, xspeed
, rspeed
, clkmul
, flags
;
1112 char *report
, *report2
;
1113 static char *attributes
[][2] = {
1114 { "\033[?1;0c", "No options (vanilla VT100)" },
1115 { "\033[?1;1c", "VT100 with STP" },
1116 { "\033[?1;2c", "VT100 with AVO (could be a VT102)" },
1117 { "\033[?1;3c", "VT100 with STP and AVO" },
1118 { "\033[?1;4c", "VT100 with GPO" },
1119 { "\033[?1;5c", "VT100 with STP and GPO" },
1120 { "\033[?1;6c", "VT100 with AVO and GPO" },
1121 { "\033[?1;7c", "VT100 with STP, AVO and GPO" },
1122 { "\033[?1;11c", "VT100 with PP and AVO" },
1123 { "\033[?1;15c", "VT100 with PP, GPO and AVO" },
1124 { "\033[?4;2c", "VT132 with AVO" },
1125 { "\033[?4;3c", "VT132 with AVO and STP" },
1126 { "\033[?4;6c", "VT132 with GPO and AVO" },
1127 { "\033[?4;7c", "VT132 with GPO, AVO, and STP" },
1128 { "\033[?4;11c", "VT132 with PP and AVO" },
1129 { "\033[?4;15c", "VT132 with PP, GPO and AVO" },
1130 { "\033[?7c", "VT131" },
1131 { "\033[?12;5c", "VT125" }, /* VT125 also has ROM version */
1132 { "\033[?12;7c", "VT125 with AVO" }, /* number, so this won't work */
1133 { "\033[?5;0c", "VK100 (GIGI)" },
1134 { "\033[?5c", "VK100 (GIGI)" },
1140 termioNew
.c_lflag
&= ~ECHO
;
1141 (void) ioctl(0, TCSETAW
, &termioNew
);
1143 sgttyNew
.sg_flags
&= ~ECHO
;
1148 println("This is a test of the ANSWERBACK MESSAGE. (To load the A.B.M.");
1149 println("see the TEST KEYBOARD part of this program). Below here, the");
1150 println("current answerback message in your terminal should be");
1151 println("displayed. Finish this test with RETURN.");
1154 printf("%c", 5); /* ENQ */
1163 println("Test of LineFeed/NewLine mode.");
1168 termioNew
.c_iflag
&= ~ICRNL
;
1169 termioNew
.c_oflag
&= ~ONLCR
;
1170 (void) ioctl(0, TCSETAW
, &termioNew
);
1172 sgttyNew
.sg_flags
&= ~CRMOD
;
1176 printf("NewLine mode set. Push the RETURN key: ");
1181 if (!strcmp(report
, "\015\012")) printf(" -- OK");
1182 else printf(" -- Not expected");
1185 printf("NewLine mode reset. Push the RETURN key: ");
1190 if (!strcmp(report
, "\015")) printf(" -- OK");
1191 else printf(" -- Not expected");
1195 termioNew
.c_iflag
|= ICRNL
;
1196 termioNew
.c_oflag
|= ONLCR
;
1197 (void) ioctl(0, TCSETAW
, &termioNew
);
1199 sgttyNew
.sg_flags
|= CRMOD
;
1207 printf("Test of Device Status Report 5 (report terminal status).");
1213 printf("Report is: ");
1215 if (!strcmp(report
,"\033[0n")) printf(" -- means \"TERMINAL OK\"");
1216 else if (!strcmp(report
,"\033[3n")) printf(" -- means \"TERMINAL OK\"");
1217 else printf(" -- Unknown response!");
1220 println("Test of Device Status Report 6 (report cursor position).");
1226 printf("Report is: ");
1228 if (!strcmp(report
,"\033[5;1R")) printf(" -- OK");
1229 else printf(" -- Unknown response!");
1232 println("Test of Device Attributes report (what are you)");
1238 printf("Report is: ");
1240 for (i
= 0; *attributes
[i
][0] != '\0'; i
++) {
1241 if (!strcmp(report
,attributes
[i
][0])) break;
1243 if (*attributes
[i
][0] == '\0')
1244 printf(" -- Unknown response, refer to the manual");
1246 printf(" -- means %s", attributes
[i
][1]);
1249 println("Legend: STP = Processor Option");
1250 println(" AVO = Advanced Video Option");
1251 println(" GPO = Graphics Processor Option");
1252 println(" PP = Printer Port");
1257 println("Test of the \"Request Terminal Parameters\" feature, argument 0.");
1263 printf("Report is: ");
1265 if (strlen(report
) < 16
1266 || report
[0] != '\033'
1269 || report
[3] != ';')
1270 println(" -- Bad format");
1273 parity
= scanto(report
, &reportpos
, ';');
1274 nbits
= scanto(report
, &reportpos
, ';');
1275 xspeed
= scanto(report
, &reportpos
, ';');
1276 rspeed
= scanto(report
, &reportpos
, ';');
1277 clkmul
= scanto(report
, &reportpos
, ';');
1278 flags
= scanto(report
, &reportpos
, 'x');
1279 if (parity
== 0 || nbits
== 0 || clkmul
== 0) println(" -- Bad format");
1280 else println(" -- OK");
1282 "This means: Parity %s, %s bits, xmitspeed %s, recvspeed %s.\n",
1283 lookup(paritytable
, parity
),
1284 lookup(nbitstable
, nbits
),
1285 lookup(speedtable
, xspeed
),
1286 lookup(speedtable
, rspeed
));
1287 printf("(CLoCk MULtiplier = %d, STP option flags = %d)\n", clkmul
, flags
);
1291 println("Test of the \"Request Terminal Parameters\" feature, argument 1.");
1293 decreqtparm(1); /* Does the same as decreqtparm(0), reports "3" */
1297 printf("Report is: ");
1299 if (strlen(report2
) < 3
1300 || report2
[2] != '3')
1301 println(" -- Bad format");
1304 if (!strcmp(report
,report2
)) println(" -- OK");
1305 else println(" -- Bad format");
1311 termioNew
.c_lflag
|= ECHO
;
1312 (void) ioctl(0, TCSETAW
, &termioNew
);
1314 sgttyNew
.sg_flags
|= ECHO
;
1322 static struct rtabl
{
1326 { "\033/K", " -- OK (means Standard VT52)" },
1327 { "\033/Z", " -- OK (means VT100 emulating VT52)" },
1328 { "", " -- Unknown response"}
1334 rm("?2"); /* Reset ANSI (VT100) mode, Set VT52 mode */
1335 esc("H"); /* Cursor home */
1336 esc("J"); /* Erase to end of screen */
1337 esc("H"); /* Cursor home */
1338 for (i
= 0; i
<= 23; i
++) {
1339 for (j
= 0; j
<= 9; j
++)
1340 printf("%s", "FooBar ");
1343 esc("H"); /* Cursor home */
1344 esc("J"); /* Erase to end of screen */
1347 printf("nothing more.");
1348 for (i
= 1; i
<= 10; i
++) printf("THIS SHOULD GO AWAY! ");
1349 for (i
= 1; i
<= 5; i
++) {
1351 printf("%s", "Back scroll (this should go away)");
1352 esc("I"); /* Reverse LineFeed (with backscroll!) */
1355 esc("J"); /* Erase to end of screen */
1356 for (i
= 2; i
<= 6; i
++) {
1358 esc("K"); /* Erase to end of line */
1361 for (i
= 2; i
<= 23; i
++) {
1362 vt52cup(i
,70); printf("%s", "**Foobar");
1365 for (i
= 23; i
>= 2; i
--) {
1367 printf("%c", 8); /* BS */
1368 esc("I"); /* Reverse LineFeed (LineStarve) */
1371 for (i
= 70; i
>= 10; i
--) {
1373 esc("D"); esc("D"); /* Cursor Left */
1376 for (i
= 10; i
<= 70; i
++) {
1378 printf("%c", 8); /* BS */
1379 esc("C"); /* Cursor Right */
1382 for (i
= 2; i
<= 23; i
++) {
1384 printf("%c", 8); /* BS */
1385 esc("B"); /* Cursor Down */
1388 for (i
= 23; i
>= 2; i
--) {
1390 printf("%c", 8); /* BS */
1391 esc("A"); /* Cursor Up */
1393 for (i
= 2; i
<= 23; i
++) {
1395 esc("K"); /* Erase to end of line */
1399 printf("%s", "The screen should be cleared, and have a centered");
1401 printf("%s", "rectangle of \"*\"s with \"!\"s on the inside to the");
1403 printf("%s", "left and right. Only this, and");
1407 esc("H"); /* Cursor home */
1408 esc("J"); /* Erase to end of screen */
1409 printf("%s", "This is the normal character set:");
1410 for (j
= 0; j
<= 1; j
++) {
1412 for (i
= 0; i
<= 47; i
++)
1413 printf("%c", 32 + i
+ 48 * j
);
1416 printf("%s", "This is the special graphics character set:");
1417 esc("F"); /* Select Special Graphics character set */
1418 for (j
= 0; j
<= 1; j
++) {
1420 for (i
= 0; i
<= 47; i
++)
1421 printf("%c", 32 + i
+ 48 * j
);
1423 esc("G"); /* Select ASCII character set */
1427 esc("H"); /* Cursor home */
1428 esc("J"); /* Erase to end of screen */
1429 println("Test of terminal response to IDENTIFY command");
1430 esc("Z"); /* Identify */
1433 printf("Response was");
1434 esc("<"); /* Enter ANSI mode (VT100 mode) */
1436 for(i
= 0; resptable
[i
].rcode
[0] != '\0'; i
++)
1437 if (!strcmp(response
, resptable
[i
].rcode
))
1439 printf("%s", resptable
[i
].rmsg
);
1448 SM/RM(4) (= IRM (Insertion/replacement mode))
1449 ICH (Insert Character)
1450 DCH (Delete character)
1455 int i
, row
, col
, sw
, dblchr
, scr132
;
1457 for(scr132
= 0; scr132
<= 1; scr132
++) {
1458 if (scr132
) { sm("?3"); sw
= 132; }
1459 else { rm("?3"); sw
= 80; }
1462 for (row
=1; row
<=24; row
++) {
1464 for (col
=1; col
<=sw
; col
++)
1465 printf("%c", 'A'-1+row
);
1468 printf("Screen accordion test (Insert & Delete Line). "); holdit();
1473 for (row
=1; row
<=24; row
++) {
1481 "Top line: A's, bottom line: X's, this line, nothing more. ");
1488 for (col
=2; col
<=sw
-1; col
++)
1492 printf("Test of 'Insert Mode'. The top line should be 'A*** ... ***B'. ");
1493 holdit(); ri(); el(2);
1497 printf("Test of 'Delete Character'. The top line should be 'AB'. ");
1500 for(dblchr
= 1; dblchr
<= 2; dblchr
++) {
1502 for (row
=1; row
<=24; row
++) {
1504 if (dblchr
== 2) decdwl();
1505 for (col
=1; col
<=sw
/dblchr
; col
++)
1506 printf("%c", 'A'-1+row
);
1507 cup(row
,sw
/dblchr
-row
);
1511 println("The right column should be staggered ");
1517 println("If your terminal has the ANSI 'Insert Character' function");
1518 println("(the VT102 does not), then you should see a line like this");
1519 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");
1522 for (i
= 'Z'; i
>= 'A'; i
--) {
1529 if (sw
== 132) rm("?3");
1533 dch(pn
) int pn
; { brc(pn
, 'P'); } /* Delete character */
1534 ich(pn
) int pn
; { brc(pn
, '@'); } /* Insert character -- not in VT102 */
1535 dl(pn
) int pn
; { brc(pn
, 'M'); } /* Delete line */
1536 il(pn
) int pn
; { brc(pn
, 'L'); } /* Insert line */
1538 /* Test of some known VT100 bugs and misfeatures */
1544 static char *menutable
[] = {
1545 "Exit to main menu",
1546 "Bug A: Smooth scroll to jump scroll",
1547 "Bug B: Scrolling region",
1548 "Bug C: Wide to narrow screen",
1549 "Bug D: Narrow to wide screen",
1550 "Bug E: Cursor move from double- to single-wide line",
1551 "Bug F: Column mode escape sequence",
1552 "Wrap around with cursor addressing",
1553 "Erase right half of double width lines",
1554 "Funny scroll regions",
1559 static char *hmsg
[] = {
1560 "Test of known bugs in the DEC VT100 series. The numbering of some of",
1561 "the bugs (A-F) refers to the article 'VT100 MAGIC' by Sami Tabih in",
1562 "the 'Proceedings of the DEC Users Society' at St. Louis, Missouri, May",
1563 "1983. To understand some of the tests, you have to look at the source",
1564 "code or the article. Of course, a good VT100-compatible terminal",
1565 "should not have these bugs (or have some means of disabling them)! If",
1566 "a bug appears, you might want to RESET the terminal before continuing",
1567 "the test. There is a test of the RESET function in the main menu.",
1572 for (i
= 0; *hmsg
[i
]; i
++) println(hmsg
[i
]);
1574 println(" Choose bug test number:");
1575 menuchoice
= menu(menutable
);
1576 switch (menuchoice
) {
1577 case 1: bug_a(); break;
1578 case 2: bug_b(); break;
1579 case 3: bug_c(); break;
1580 case 4: bug_d(); break;
1581 case 5: bug_e(); break;
1582 case 6: bug_f(); break;
1583 case 7: bug_w(); break;
1584 case 8: bug_l(); break;
1585 case 9: bug_s(); break;
1587 } while (menuchoice
);
1590 /* Bug A: Smooth scroll to jump scroll */
1596 println("This is a test of the VT100 'Scroll while toggle softscroll'");
1597 println("bug. The cursor may disappear, or move UP the screen, or");
1598 println("multiple copies of some lines may appear.");
1601 /* Invoke the bug */
1603 esc ("[24H"); /* Simplified cursor movement */
1604 rm("?4"); for (i
= 1; i
<= 20; i
++) printf("\n");
1605 sm("?4"); for (i
= 1; i
<= 10; i
++) printf("\n");
1606 rm("?4"); for (i
= 1; i
<= 5; i
++) printf("\n");
1608 /* That should be enough to show the bug. But we'll try another way: */
1609 sm ("?4"); /* Set soft scroll */
1610 nel (); /* "NextLine", move down */
1611 rm ("?4"); /* Reset soft scroll */
1612 nel (); /* "NextLine", move down */
1613 for (i
= 1; i
<= 10; i
++) { /* Show the bug */
1614 printf ("Softscroll bug test, line %d. ", i
);
1617 println("That should have been enough to show the bug, if present.");
1621 /* Bug B: Scrolling region */
1628 printf("Line 11 should be double-wide, line 12 should be cleared.");
1630 printf("Then, the letters A-P should be written at the beginning");
1632 printf("of lines 12-24, and the empty line and A-E are scrolled away.");
1634 printf("If the bug is present, some lines are confused, look at K-P.");
1635 cup(11,1); decdwl();
1637 cup(12,1); el(0); printf("Here we go... "); holdit();
1638 cup(12,1); ri(); /* Bug comes here */
1639 for (c
= 'A'; c
<= 'P'; c
++) printf("%c\n",c
); /* Bug shows here */
1641 decstbm(0,0); /* No scr. region */
1644 /* Bug C: Wide to narrow screen */
1647 sm("?3"); /* 132 column mode */
1649 rm("?3"); /* 80 column mode */
1651 printf("Except for this line, the screen should be blank. ");
1655 /* Bug D: Narrow to wide screen */
1660 /* Make the bug appear */
1664 /* The original code in the article says
1665 * PRINT ESC$; "[13;1H"; CHR$(10%);
1666 * but I guess a cup(14,1); would do.
1667 * (To output a pure LF might be tricky).
1670 sm("?3"); /* Make the bug visible */
1672 println("You should see blinking text at the bottom line.");
1674 println("Enter 0 to exit, 1 to try to invoke the bug again.");
1675 cup(24,9); decdwl(); sgr("1;5;7");
1676 printf("If you can see this then the bug did not appear."); sgr("");
1678 result
= inchar(); readnl();
1680 } while (result
== '1');
1681 sm("?4"); /* Syrup scroll */
1683 for (i
= 1; i
<= 5; i
++)
1684 println("If the bug is present, this should make things much worse!");
1686 rm("?4"); /* Jump scroll */
1689 /* Bug E: Cursor move from double- to single-wide line */
1693 static char *rend
[2] = { "\033[m", "\033[7m" };
1696 println("This test should put an 'X' at line 3 column 100.");
1697 for (i
= 1; i
<= 12; i
++) printf("1234567890%s",rend
[i
& 1]);
1698 cup(1,1); /* The bug appears when we jump from a dobule-wide line */
1699 cup(3,100); /* to a single-wide line, column > 66. */
1701 cup(4, 66); printf("! !");
1703 printf("--------------------------- The 'X' should NOT be above here -");
1704 printf("---+------------ but above here -----+");
1705 cup(10,1); decdwl(); holdit();
1709 /* Bug F: Column mode escape sequence */
1715 * VT100 "toggle origin mode, forget rest" bug. If you try to set
1716 * (or clear) parameters and one of them is the "origin mode"
1717 * ("?6") parameter, parameters that appear after the "?6"
1718 * remain unaffected. This is also true on CIT-101 terminals.
1720 sm ("?5"); /* Set reverse mode */
1721 sm ("?3"); /* Set 132 column mode */
1722 println("Test VT100 'Toggle origin mode, forget rest' bug, part 1.");
1723 println("The screen should be in reverse, 132 column mode.");
1726 rm ("?6;5;3"); /* Reset (origin, reverse, 132 col) */
1727 println("Test VT100 'Toggle origin mode, forget rest' bug, part 2.\n");
1728 println("The screen should be in non-reverse, 80 column mode.");
1733 * The dreaded "wraparound" bug! You CUP to col 80, write a char,
1734 * CUP to another line in col 80, write a char. And the brain-damaged
1735 * terminal thinks that "Hokay, so he's written a char in col 80, so
1736 * I stay in col 80 and wait for next character. Let's see now, here
1737 * comes another character, and I'm still in col 80, so I must make
1738 * a NewLine first." -- It doesn't clear that "still in col 80" flag
1746 println(" This illustrates the \"wrap around bug\" which exists on a");
1747 println(" standard VT100. At the top of the screen there should be");
1748 println(" a row of +'s, and the rightmost column should be filled");
1749 println(" with *'s. But if the bug is present, some of the *'s may");
1750 println(" be placed in other places, e.g. in the leftmost column,");
1751 println(" and the top line of +'s may be scrolled away.");
1754 for (col
= 1; col
<= 79; col
++)
1756 for (row
= 1; row
<= 24; row
++) {
1765 * Check if the right half of double-width lines comes back
1766 * when a line is first set to single-width, filled with stuff,
1767 * set to double-width, and finally reset to single-width.
1769 * A VT100 has this misfeature, and many others. Foo!
1774 printf("This-is-a-long-line-This-is-a-long-line-");
1775 printf("This-is-a-long-line-This-is-a-long-line-");
1777 printf("This is a test of what happens to the right half of double-width");
1779 printf("A common misfeature is that the right half does not come back");
1780 println(" when a long");
1781 printf("single-width line is set to double-width and then reset to");
1782 println(" single-width.");
1785 println("Now the line below should contain 80 characters in single width.");
1787 cup(15, 1); decdwl();
1789 println("Now the line below should contain 40 characters in double width.");
1791 cup(15, 1); decswl();
1793 println("Now the line below should contain 80 characters in single width.");
1796 /* ...and in 132 column mode */
1801 printf("This-is-a-long-line-This-is-a-long-line-");
1802 printf("This-is-a-long-line-This-is-a-long-line-");
1803 printf("This-is-a-long-line-This-is-a-long-line-");
1804 printf("ending-here-");
1807 printf("This is the same test in 132 column mode.");
1810 println("Now the line below should contain 132 characters in single width.");
1812 cup(15, 1); decdwl();
1814 println("Now the line below should contain 66 characters in double width.");
1816 cup(15, 1); decswl();
1818 println("Now the line below should contain 132 characters in single width.");
1825 decstbm(20,10); /* 20-10=-10, < 2, so no scroll region. */
1827 for (i
=1; i
<=20; i
++)
1828 printf("This is 20 lines of text (line %d), no scroll region.\n", i
);
1831 decstbm(0,1); /* Should be interpreted as decstbm(1,1) = none */
1833 for (i
=1; i
<=20; i
++)
1834 printf("This is 20 lines of text (line %d), no scroll region.\n", i
);
1836 decstbm(0,0); /* No scroll region (just in case...) */
1843 * - RIS (Reset to Initial State)
1844 * - DECTST (invoke terminal test)
1848 printf ("The terminal will now be RESET. ");
1854 zleep(5000); /* Wait 5.0 seconds */
1856 println("The terminal is now RESET. Next, the built-in confidence test");
1857 printf("%s", "will be invoked. ");
1864 zleep(5000); /* Wait 5.0 seconds */
1866 println("If the built-in confidence test found any errors, a code");
1867 printf("%s", "is visible above. ");
1871 initterminal(pn
) int pn
; {
1878 (void) ioctl(0, TCGETA
, &termioOrg
);
1879 (void) ioctl(0, TCGETA
, &termioNew
);
1880 termioNew
.c_lflag
&= ~ICANON
;
1881 termioNew
.c_cc
[VMIN
] = 1;
1882 termioNew
.c_cc
[VTIME
] = 0;
1883 (void) ioctl(0, TCSETAW
, &termioNew
);
1889 termioNew
.c_lflag
= termioOrg
.c_lflag
& ~ICANON
;
1890 termioNew
.c_cc
[VMIN
] = 1;
1891 termioNew
.c_cc
[VTIME
] = 0;
1893 (void) ioctl(0, TCSETAW
, &termioNew
);
1899 sgttyNew
.sg_flags
|= CBREAK
;
1905 sgttyNew
.sg_flags
= sgttyOrg
.sg_flags
| CBREAK
;
1911 open("/dev/tty",O_RDWR
|O_NDELAY
);
1916 /* Set up necessary TOPS-10 terminal parameters */
1918 trmop(02041, `VT100`
); /* tty type vt100 */
1919 trmop(02002, 0); /* tty no tape */
1920 trmop(02003, 0); /* tty lc */
1921 trmop(02005, 1); /* tty tab */
1922 trmop(02010, 1); /* tty no crlf */
1923 trmop(02020, 0); /* tty no tape */
1924 trmop(02021, 1); /* tty page */
1925 trmop(02025, 0); /* tty blanks */
1926 trmop(02026, 1); /* tty no alt */
1927 trmop(02040, 1); /* tty defer */
1930 ttybin(1); /* set line to binary mode */
1932 /* Set up my personal prejudices */
1934 esc("<"); /* Enter ANSI mode (if in VT52 mode) */
1935 rm("?1"); /* cursor keys normal */
1936 rm("?3"); /* 80 col mode */
1937 rm("?4"); /* Jump scroll */
1938 rm("?5"); /* Normal screen */
1939 rm("?6"); /* Absolute origin mode */
1940 sm("?7"); /* Wrap around on */
1941 rm("?8"); /* Auto repeat off */
1942 decstbm(0,0); /* No scroll region */
1943 sgr("0"); /* Normal character attributes */
1948 /* Force my personal prejudices upon the poor luser */
1950 esc("<"); /* Enter ANSI mode (if in VT52 mode) */
1951 rm("?1"); /* cursor keys normal */
1952 rm("?3"); /* 80 col mode */
1953 rm("?5"); /* Normal screen */
1954 rm("?6"); /* Absolute origin mode */
1955 sm("?7"); /* Wrap around on */
1956 sm("?8"); /* Auto repeat on */
1957 decstbm(0,0); /* No scroll region */
1958 sgr("0"); /* Normal character attributes */
1964 printf("That's all, folks!\n");
1968 ttybin(0); /* reset line to normal mode */
1972 (void) ioctl(0, TCSETAW
, &termioOrg
);
1982 signal(SIGINT
, onbrk
);
1986 longjmp(intrenv
, 1);
1990 signal(SIGTERM
, onterm
);
1991 longjmp(intrenv
, 1);
1997 printf("Push <RETURN>");
2007 do { read(0,&ch
,1); } while(ch
!= '\n' && !brkrd
);
2009 kill(getpid(), SIGTERM
);
2013 while (getchar() != '\n')
2017 while (getchar() != '\n')
2022 scanto(str
, pos
, toc
) char *str
; int *pos
; char toc
; {
2026 while (toc
!= (c
= str
[(*pos
)++])) {
2027 if (isdigit(c
)) result
= result
* 10 + c
- '0';
2030 if (c
== toc
) return(result
);
2034 char *lookup(t
, k
) struct table t
[]; int k
; {
2037 for (i
= 0; t
[i
].key
!= -1; i
++) {
2038 if (t
[i
].key
== k
) return(t
[i
].msg
);
2040 return("BAD VALUE");
2043 menu(table
) char *table
[]; {
2045 int i
, tablesize
, choice
;
2051 for (i
= 0; *table
[i
] != '\0'; i
++) {
2052 printf(" %d. %s\n", i
, table
[i
]);
2057 printf("\n Enter choice number (0 - %d): ", tablesize
);
2061 while (c
= *s
++) choice
= 10 * choice
+ c
- '0';
2062 if (choice
>= 0 && choice
<= tablesize
) {
2066 printf(" Bad choice, try again: ");
2070 chrprint (s
) char *s
; {
2077 for (i
= 0; s
[i
] != '\0'; i
++) {
2078 if (s
[i
] <= ' ' || s
[i
] == '\177')
2079 printf("<%d> ", s
[i
]);
2080 else printf("%c ", s
[i
]);