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]);