1 /* $Id: vt420.c,v 1.170 2018/07/26 00:41:17 tom Exp $ */
2 
3 /*
4  * Reference:  Installing and Using the VT420 Video Terminal (North American
5  *             Model (EK-VT420-UG.002)
6  */
7 #include <vttest.h>
8 #include <draw.h>
9 #include <esc.h>
10 #include <ttymodes.h>
11 
12 typedef enum {
13   marNone = -1,
14   marReset = 0,
15   marFirst = 1,
16   marLast = 2,
17   marMiddle = 3,
18   marEnd
19 } MARS;
20 
21 int origin_mode = FALSE;
22 char txt_override_color[80];
23 
24 static int do_lines = FALSE;
25 static int use_colors = FALSE;
26 
27 /******************************************************************************/
28 
29 static void
reset_colors(void)30 reset_colors(void)
31 {
32   if (use_colors) {
33     sgr("0");
34     use_colors = FALSE;
35     if (LOG_ENABLED) {
36       fprintf(log_fp, "Note: turned off colors\n");
37     }
38   }
39 }
40 
41 void
set_colors(const char * value)42 set_colors(const char *value)
43 {
44   if (do_colors) {
45     if (value == 0)
46       value = "0";
47     sgr(value);
48     use_colors = strcmp(value, "0");
49     if (LOG_ENABLED) {
50       fprintf(log_fp, "Note: turned %s colors\n", use_colors ? "on" : "off");
51     }
52   }
53 }
54 
55 /******************************************************************************/
56 
57 int lrmm_flag;
58 
59 static MARS lr_marg_flag;
60 static int lr_marg1, lr_marg2;
61 static MARS tb_marg_flag;
62 static int tb_marg1, tb_marg2;
63 
64 char origin_mode_mesg[80];
65 char lrmm_mesg[80];
66 char lr_marg_mesg[80];
67 char tb_marg_mesg[80];
68 
69 int
toggle_LRMM(MENU_ARGS)70 toggle_LRMM(MENU_ARGS)
71 {
72   lrmm_flag = !lrmm_flag;
73   if (lrmm_flag)
74     sm("?69");
75   else
76     rm("?69");
77   return MENU_NOHOLD;
78 }
79 
80 /*
81  * The message tells what margins will be used in the test, not what their
82  * value is while drawing the menu (since actually setting margins would
83  * interfere with the menu).
84  */
85 int
toggle_STBM(MENU_ARGS)86 toggle_STBM(MENU_ARGS)
87 {
88   switch (++tb_marg_flag) {
89   default:
90     tb_marg_flag = marReset;
91     tb_marg1 = 0;
92     tb_marg2 = 0;
93     strcpy(tb_marg_mesg, "Top/Bottom margins are reset");
94     break;
95   case marFirst:
96     tb_marg1 = 1;
97     tb_marg2 = max_lines / 2;
98     strcpy(tb_marg_mesg, "Top/Bottom margins are set to top half of screen");
99     break;
100   case marLast:
101     tb_marg1 = max_lines / 2;
102     tb_marg2 = max_lines;
103     strcpy(tb_marg_mesg,
104            "Top/Bottom margins are set to bottom half of screen");
105     break;
106   case marMiddle:
107     tb_marg1 = max_lines / 4;
108     tb_marg2 = (3 * max_lines) / 4;
109     strcpy(tb_marg_mesg,
110            "Top/Bottom margins are set to middle half of screen");
111     break;
112   }
113   return MENU_NOHOLD;
114 }
115 
116 int
toggle_SLRM(MENU_ARGS)117 toggle_SLRM(MENU_ARGS)
118 {
119   switch (++lr_marg_flag) {
120   default:
121     lr_marg_flag = marReset;
122     lr_marg1 = 0;
123     lr_marg2 = 0;
124     strcpy(lr_marg_mesg, "Left/right margins are reset");
125     break;
126   case marFirst:
127     lr_marg1 = 1;
128     lr_marg2 = min_cols / 2;
129     strcpy(lr_marg_mesg, "Left/right margins are set to left half of screen");
130     break;
131   case marLast:
132     lr_marg1 = (min_cols / 2) + 1;
133     lr_marg2 = min_cols;
134     strcpy(lr_marg_mesg,
135            "Left/right margins are set to right half of screen");
136     break;
137   case marMiddle:
138     lr_marg1 = (min_cols / 4) + 1;
139     lr_marg2 = (3 * min_cols) / 4;
140     strcpy(lr_marg_mesg,
141            "Left/right margins are set to middle half of screen");
142     break;
143   }
144   return MENU_NOHOLD;
145 }
146 
147 int
get_top_margin(void)148 get_top_margin(void)
149 {
150   int result = (tb_marg1 ? tb_marg1 : 1);
151   if (origin_mode)
152     result = 1;
153   return result;
154 }
155 
156 int
get_left_margin(void)157 get_left_margin(void)
158 {
159   int result = ((lrmm_flag && lr_marg1) ? lr_marg1 : 1);
160   if (origin_mode)
161     result = 1;
162   return result;
163 }
164 
165 int
get_right_margin(void)166 get_right_margin(void)
167 {
168   int result = ((lrmm_flag && lr_marg2) ? lr_marg2 : min_cols);
169   if (origin_mode) {
170     result = (((lrmm_flag && lr_marg2) ? lr_marg2 : min_cols) -
171               ((lrmm_flag && lr_marg1) ? lr_marg1 : 1) +
172               1);
173   }
174   return result;
175 }
176 
177 int
get_bottom_margin(int n)178 get_bottom_margin(int n)
179 {
180   int result = (tb_marg2 ? tb_marg2 : (n));
181   if (origin_mode) {
182     result = ((tb_marg2 ? tb_marg2 : max_lines) -
183               (tb_marg1 ? tb_marg1 : 1) +
184               1);
185   }
186   return result;
187 }
188 
189 static int
get_hold_col(void)190 get_hold_col(void)
191 {
192   int hold_col = 1;
193 
194   if (lrmm_flag) {
195     switch (lr_marg_flag) {
196     default:
197       break;
198     case marFirst:
199       hold_col = get_right_margin() + 1;
200       break;
201     case marMiddle:
202       hold_col = get_left_margin();
203       break;
204     }
205   }
206   return hold_col;
207 }
208 
209 /*
210  * Return a good row value at which to print a prompt, avoiding most overwrite
211  * of test-results.
212  */
213 static int
get_hold_row(void)214 get_hold_row(void)
215 {
216   int hold_row;
217 
218   switch (tb_marg_flag) {
219   default:
220     hold_row = max_lines / 2;
221     break;
222   case marFirst:
223     hold_row = (origin_mode
224                 ? (max_lines - 4)
225                 : (get_bottom_margin(max_lines) + 1));
226     break;
227   case marMiddle:
228     hold_row = (max_lines > 16) ? (max_lines - 4) : (max_lines / 2);
229     break;
230   case marLast:
231     hold_row = 1;
232     break;
233   }
234   return hold_row;
235 }
236 
237 static int
hold_clear(void)238 hold_clear(void)
239 {
240   int result;
241 
242   switch (tb_marg_flag) {
243   default:
244     result = 0;
245     break;
246   case marFirst:
247     result = 1;
248     break;
249   case marReset:
250   case marLast:
251     result = 0;
252     break;
253   }
254 
255   return result;
256 }
257 
258 /*
259  * Prompt as part of a multi-step test, temporarily resetting DECOM so we can
260  * put the prompt anywhere.
261  */
262 static void
special_prompt(int row,int col,const char * msg)263 special_prompt(int row, int col, const char *msg)
264 {
265   if (origin_mode)
266     decom(FALSE);
267 
268   vt_move(row, col);
269   if (msg != 0) {
270     printf("%s", msg);
271     vt_move(row + 1, col);
272   }
273   holdit();
274 
275   if (origin_mode)
276     decom(TRUE);
277 }
278 
279 /*
280  * Fill area outside margins with given character, to help show that changes
281  * are limited to the area within margins.
282  */
283 static void
fill_outside(int ch)284 fill_outside(int ch)
285 {
286   int row, col;
287 
288   if (LOG_ENABLED) {
289     fprintf(log_fp, "Note: filling outside margins with '%c'\n", ch);
290   }
291 
292   if (!do_colors)
293     set_colors("0");
294 
295   if (origin_mode)
296     decom(FALSE);
297 
298   for (row = 1; row <= max_lines; ++row) {
299     if (row < tb_marg1 ||
300         row > tb_marg2 ||
301         lr_marg1 > 1 ||
302         lr_marg2 < min_cols) {
303       int first = 1;
304       int next = 0;
305 
306       for (col = 1; col <= min_cols; ++col) {
307         if ((lrmm_flag && lr_marg1 && col < lr_marg1) ||
308             (lrmm_flag && lr_marg2 && col > lr_marg2) ||
309             (tb_marg1 != 0 && row < tb_marg1) ||
310             (tb_marg2 != 0 && row > tb_marg2)) {
311           if (first || (next != col)) {
312             vt_move(row, col);
313             first = 0;
314             next = col + 1;
315           }
316           putchar(ch);
317           ++next;
318         }
319       }
320     }
321   }
322 
323   if (origin_mode)
324     decom(TRUE);
325 }
326 
327 void
test_with_margins(int enable)328 test_with_margins(int enable)
329 {
330   switch (enable) {
331   case 1:
332     fill_outside('.');
333     /* FALLTHRU */
334   case 2:
335     decstbm(tb_marg1, tb_marg2);
336     decslrm(lr_marg1, lr_marg2);
337     if (origin_mode)
338       decom(TRUE);
339     break;
340   default:
341     decstbm(0, 0);
342     decslrm(0, 0);
343     if (origin_mode)
344       decom(FALSE);
345     break;
346   }
347 }
348 
349 /*
350  * Fill the area within margins with a test pattern.  The top line is numbers,
351  * the bottom line is alphas.  In between, use asterisks.
352  */
353 static void
fill_margins(void)354 fill_margins(void)
355 {
356   int top = get_top_margin();
357   int bot = get_bottom_margin(max_lines);
358   int lft = get_left_margin();
359   int rgt = get_right_margin();
360   int row, col;
361 
362   set_colors(WHITE_ON_BLUE);
363 
364   decawm(FALSE);  /* do this to allow writing in lower-right */
365   for (row = top; row <= bot; ++row) {
366     cup(row, lft);
367     for (col = lft; col <= rgt; ++col) {
368       if (row == top) {
369         putchar((col - lft) % 10 + '0');
370       } else if (row == bot) {
371         putchar((col - lft) % 26 + 'a');
372       } else {
373         putchar('*');
374       }
375     }
376   }
377   decawm(TRUE);
378 }
379 
380 static void
setup_rectangle(BOX * box,int last)381 setup_rectangle(BOX *box, int last)
382 {
383   box->top = 5;
384   box->left = 5;
385   box->right = min_cols - 5;
386   box->bottom = max_lines - 10;
387 
388   if (origin_mode) {
389     int top = get_top_margin();
390     int lft = get_left_margin();
391     int rgt = get_right_margin();
392     int bot = get_bottom_margin(last - 1);
393     int wide = (rgt - lft + 1);
394     int high = (bot - top + 1);
395 
396     if (high > 20) {
397       box->top = 5;
398       box->bottom = high - 10;
399     } else {
400       box->top = 2;
401       box->bottom = high - 2;
402     }
403 
404     if (wide > 20) {
405       box->left = 5;
406       box->right = wide - 5;
407     } else {
408       box->left = 2;
409       box->right = wide - 2;
410     }
411   }
412 }
413 
414 #define DATA(name,level) { name, #name, level }
415 
416 static int
show_DECLRMM(MENU_ARGS)417 show_DECLRMM(MENU_ARGS)
418 {
419   /* *INDENT-OFF* */
420   RQM_DATA dec_modes[] = { /* this list is sorted by code, not name */
421     DATA( DECLRMM, 4 /* left/right margin mode */),
422   };
423   /* *INDENT-ON* */
424 
425   int code;
426   int old_DECRPM = set_DECRPM(4);
427 
428   code = any_RQM(PASS_ARGS, dec_modes, TABLESIZE(dec_modes), 1);
429   set_DECRPM(old_DECRPM);
430   return code;
431 }
432 
433 #undef DATA
434 
435 /*
436  * Allow user to test the same screens with/without lines.
437  */
438 static int
toggle_lines_mode(MENU_ARGS)439 toggle_lines_mode(MENU_ARGS)
440 {
441   do_lines = !do_lines;
442   return MENU_NOHOLD;
443 }
444 
445 /*
446  * Allow user to test the same screens with/without origin-mode.
447  */
448 int
toggle_DECOM(MENU_ARGS)449 toggle_DECOM(MENU_ARGS)
450 {
451   origin_mode = !origin_mode;
452   return MENU_NOHOLD;
453 }
454 
455 /*
456  * DECALN does not set attributes; we want a colored screen for some tests.
457  */
458 static void
fill_screen(void)459 fill_screen(void)
460 {
461   if (do_colors) {
462     int y, x;
463 
464     set_colors(WHITE_ON_BLUE);
465     for (y = 0; y < max_lines - 4; ++y) {
466       cup(y + 1, 1);
467       for (x = 0; x < min_cols; ++x)
468         putchar('E');
469     }
470     /* make this a different color to show fill versus erase diffs */
471     set_colors(WHITE_ON_GREEN);
472   } else {
473     decaln();   /* fill the screen */
474   }
475 }
476 
477 /******************************************************************************/
478 
479 static int
rpt_DECSACE(MENU_ARGS)480 rpt_DECSACE(MENU_ARGS)
481 {
482   return any_decrqss(the_title, "*x");
483 }
484 
485 static int
rpt_DECSNLS(MENU_ARGS)486 rpt_DECSNLS(MENU_ARGS)
487 {
488   return any_decrqss(the_title, "*|");
489 }
490 
491 static int
rpt_DECSLRM(MENU_ARGS)492 rpt_DECSLRM(MENU_ARGS)
493 {
494   return any_decrqss(the_title, "s");
495 }
496 
497 static int
rpt_DECELF(MENU_ARGS)498 rpt_DECELF(MENU_ARGS)
499 {
500   return any_decrqss(the_title, "+q");
501 }
502 
503 /*
504  * VT420 manual shows "=}", but the terminal returns an error.  VT510 sequences
505  * show "*}".
506  */
507 static int
rpt_DECLFKC(MENU_ARGS)508 rpt_DECLFKC(MENU_ARGS)
509 {
510   return any_decrqss(the_title, "*}");
511 }
512 
513 static int
rpt_DECSMKR(MENU_ARGS)514 rpt_DECSMKR(MENU_ARGS)
515 {
516   return any_decrqss(the_title, "+r");
517 }
518 
519 /******************************************************************************/
520 
521 static void
show_DataIntegrity(char * report)522 show_DataIntegrity(char *report)
523 {
524   int pos = 0;
525   int code = scanto(report, &pos, 'n');
526   const char *show;
527 
528   switch (code) {
529   case 70:
530     show = "No communication errors";
531     break;
532   case 71:
533     show = "Communication errors";
534     break;
535   case 73:
536     show = "Not reported since last power-up or RIS";
537     break;
538   default:
539     show = SHOW_FAILURE;
540   }
541   show_result("%s", show);
542 }
543 
544 static void
show_keypress(int row,int col)545 show_keypress(int row, int col)
546 {
547   char *report;
548   char last[BUFSIZ];
549 
550   last[0] = '\0';
551   vt_move(row++, 1);
552   println("When you are done, press any key twice to quit.");
553   vt_move(row, col);
554   fflush(stdout);
555   while (strcmp(report = instr(), last)) {
556     vt_move(row, col);
557     vt_clear(0);
558     chrprint2(report, row, col);
559     strcpy(last, report);
560   }
561 }
562 
563 static void
show_MultisessionStatus(char * report)564 show_MultisessionStatus(char *report)
565 {
566   int pos = 0;
567   int Ps1 = scan_any(report, &pos, 'n');
568   int Ps2 = scanto(report, &pos, 'n');
569   const char *show;
570 
571   switch (Ps1) {
572   case 80:
573     show = "SSU sessions enabled (%d max)";
574     break;
575   case 81:
576     show = "SSU sessions available but pending (%d max)";
577     break;
578   case 83:
579     show = "SSU sessions not ready";
580     break;
581   case 87:
582     show = "Sessions on separate lines";
583     break;
584   default:
585     show = SHOW_FAILURE;
586   }
587   show_result(show, Ps2);
588 }
589 
590 /******************************************************************************/
591 
592 /*
593  * VT400 & up.
594  * DECBI - Back Index
595  * This control function moves the cursor backward one column.  If the cursor
596  * is at the left margin, then all screen data within the margin moves one
597  * column to the right.  The column that shifted past the right margin is lost.
598  *
599  * Format:  ESC 6
600  * Description:
601  * DECBI adds a new column at the left margin with no visual attributes.  DECBI
602  * is not affected by the margins.  If the cursor is at the left border of the
603  * page when the terminal received DECBI, then the terminal ignores DECBI.
604  */
605 static int
tst_DECBI(MENU_ARGS)606 tst_DECBI(MENU_ARGS)
607 {
608   int n, m;
609   int last = max_lines - 4;
610   int final;
611   int top;
612   int lft;
613   int rgt;
614 
615   test_with_margins(1);
616 
617   top = get_top_margin();
618   lft = get_left_margin();
619   rgt = get_right_margin();
620 
621   final = (rgt - lft + 1) / 4;
622 
623   set_colors(WHITE_ON_BLUE);
624 
625   for (n = final; n > 0; n--) {
626     slowly();
627     cup(top, lft);
628     if (n != final) {
629       for (m = 0; m < 4; m++)
630         decbi();
631     }
632     printf("%3d", n);
633   }
634 
635   reset_colors();
636 
637   test_with_margins(0);
638 
639   vt_move(last, 1);
640   vt_clear(0);
641 
642   println(the_title);
643   println("If your terminal supports DECBI (backward index), then the top row");
644   printf("should be numbered 1 through %d.\n", final);
645   return MENU_HOLD;
646 }
647 
648 static int
tst_DECBKM(MENU_ARGS)649 tst_DECBKM(MENU_ARGS)
650 {
651   int row, col;
652   char *report;
653 
654   vt_move(1, 1);
655   println(the_title);
656 
657   set_tty_raw(TRUE);
658   set_tty_echo(FALSE);
659 
660   reset_inchar();
661   decbkm(TRUE);
662   println("Press the backspace key");
663   vt_move(row = 3, col = 10);
664   report = instr();
665   chrprint2(report, row, col);
666   show_result(!strcmp(report, "\010") ? SHOW_SUCCESS : SHOW_FAILURE);
667 
668   reset_inchar();
669   vt_move(5, 1);
670   decbkm(FALSE);
671   println("Press the backspace key again");
672   vt_move(row = 6, col = 10);
673   report = instr();
674   chrprint2(report, row, col);
675   show_result(!strcmp(report, "\177") ? SHOW_SUCCESS : SHOW_FAILURE);
676 
677   vt_move(max_lines - 1, 1);
678   restore_ttymodes();
679   return MENU_HOLD;
680 }
681 
682 /*
683  * VT400 & up
684  * Change Attributes in Rectangular Area
685  */
686 static int
tst_DECCARA(MENU_ARGS)687 tst_DECCARA(MENU_ARGS)
688 {
689   int last = max_lines - 4;
690   BOX box;
691 
692   setup_rectangle(&box, last);
693 
694   test_with_margins(1);
695 
696   set_colors(WHITE_ON_BLUE);
697 
698   decsace(TRUE);
699   fill_screen();
700   deccara(box.top, box.left, box.bottom, box.right, 7);   /* invert a rectangle) */
701   deccara(box.top + 1, box.left + 1, box.bottom - 1, box.right - 1, 0);   /* invert a rectangle) */
702 
703   test_with_margins(0);
704   sgr("0");
705   vt_move(last, 1);
706   vt_clear(0);
707 
708   println(the_title);
709   println("There should be an open rectangle formed by reverse-video E's");
710   holdit();
711 
712   test_with_margins(2);
713   decsace(FALSE);
714   fill_screen();
715   deccara(box.top, box.left, box.bottom, box.right, 7);   /* invert a rectangle) */
716   deccara(box.top + 1, box.left + 1, box.bottom - 1, box.right - 1, 0);   /* invert a rectangle) */
717 
718   sgr("0");
719 
720   test_with_margins(0);
721 
722   vt_move(last, 1);
723   vt_clear(0);
724 
725   println(the_title);
726   println("There should be an open rectangle formed by reverse-video E's");
727   println("combined with wrapping at the margins.");
728   return MENU_HOLD;
729 }
730 
731 #define fmt_DECCKSR "Testing DECCKSR: %s\n"
732 
733 static int
tst_DECCKSR(MENU_ARGS,int Pid,const char * the_csi,int expected)734 tst_DECCKSR(MENU_ARGS, int Pid, const char *the_csi, int expected)
735 {
736   char *report;
737   char *before;
738   char *after;
739   int pos = 0;
740   int actual;
741   int row, col;
742 
743   vt_move(1, 1);
744   printf(fmt_DECCKSR, the_title);
745 
746   set_tty_raw(TRUE);
747   set_tty_echo(FALSE);
748 
749   do_csi("%s", the_csi);
750   report = get_reply();
751   vt_move(row = 3, col = 10);
752   chrprint2(report, row, col);
753   if ((report = skip_dcs(report)) != 0
754       && strip_terminator(report)
755       && strlen(report) > 1
756       && scanto(report, &pos, '!') == Pid
757       && report[pos++] == '~'
758       && (after = skip_xdigits((before = report + pos), &actual)) != 0
759       && *after == '\0') {
760     if ((after - before) != 4) {
761       show_result("%s: expected 4 digits", SHOW_FAILURE);
762     } else if (expected >= 0) {
763       if (actual == expected) {
764         show_result(SHOW_SUCCESS);
765       } else {
766         char msg[80];
767         sprintf(msg, "%04X", (expected & 0xffff));
768         show_result("expected %s", msg);
769       }
770     } else {
771       show_result(SHOW_SUCCESS);
772     }
773   } else {
774     show_result(SHOW_FAILURE);
775   }
776 
777   restore_ttymodes();
778   vt_move(max_lines - 1, 1);
779   return MENU_HOLD;
780 }
781 
782 /*
783  * VT400 & up.
784  * Copy Rectangular area
785  */
786 static int
tst_DECCRA(MENU_ARGS)787 tst_DECCRA(MENU_ARGS)
788 {
789 #define adj_y 3
790 #define adj_x 4
791 #define adj_DECCRA " (down %d, right %d)\r\n", box.bottom + 1 - box.top, box.right + 1 - box.left, adj_y, adj_x
792 #define msg_DECCRA(msg) "The %dx%d box " msg adj_DECCRA
793   BOX box;
794   int hmargin = origin_mode ? ((get_right_margin() * 3) / 8) : 30;
795   int vmargin = origin_mode ? ((get_bottom_margin(max_lines) * 2) / 5) : 10;
796   int last = max_lines - 3;
797 
798   if (make_box_params(&box, vmargin, hmargin) == 0) {
799     box.top = 5;
800     box.left = 5;
801 
802     test_with_margins(1);
803 
804     if (do_colors) {
805       set_colors(WHITE_ON_BLUE);
806     } else {
807       sgr(BLINK_REVERSE);
808     }
809     draw_box_outline(&box, do_lines ? -1 : '*');
810     sgr("0");
811 
812     test_with_margins(0);
813 
814     vt_move(last, 1);
815     println(the_title);
816     tprintf(msg_DECCRA("will be copied"));
817     holdit();
818 
819     test_with_margins(2);
820 
821     deccra(box.top, box.left, box.bottom, box.right, 1,
822            box.top + adj_y, box.left + adj_x, 1);
823 
824     test_with_margins(0);
825 
826     vt_move(last, 1);
827     vt_clear(0);
828 
829     tprintf(msg_DECCRA("should be copied, overlapping"));
830     holdit();
831 
832     test_with_margins(2);
833 
834     make_box_params(&box, vmargin, hmargin);
835     box.top = 5;
836     box.left = 5;
837 
838     if (do_colors) {
839       set_colors(YELLOW_ON_BLACK);
840     } else {
841       sgr("0;7");   /* fill the box in reverse */
842     }
843     draw_box_filled(&box, -1);
844 
845     if (do_colors) {
846       set_colors(WHITE_ON_BLUE);
847     } else {
848       sgr(BLINK_REVERSE);
849     }
850     draw_box_outline(&box, do_lines ? -1 : '*');
851     sgr("0");
852 
853     test_with_margins(0);
854 
855     vt_move(last, 1);
856     println(the_title);
857     tprintf(msg_DECCRA("will be copied"));
858     holdit();
859 
860     test_with_margins(2);
861 
862     sgr("0;4"); /* set underline, to check if that leaks through */
863     deccra(box.top, box.left, box.bottom, box.right, 1,
864            box.top + adj_y, box.left + adj_x, 1);
865     sgr("0");
866 
867     test_with_margins(0);
868 
869     vt_move(last, 1);
870     vt_clear(0);
871 
872     tprintf(msg_DECCRA("should be copied, overlapping"));
873   }
874   return MENU_HOLD;
875 }
876 
877 static int
marker_of(int n)878 marker_of(int n)
879 {
880   return (n - 1) % 26 + 'a';
881 }
882 
883 /*
884  * VT400 & up.
885  * Delete column.
886  */
887 static int
tst_DECDC(MENU_ARGS)888 tst_DECDC(MENU_ARGS)
889 {
890   int n;
891   int last = max_lines - 3;
892   int base_row;
893   int base_col;
894   int left_col;
895   int last_row;
896   int real_col;
897   int top;
898   int bot;
899   int lft;
900   int rgt;
901   int final_dc;
902   char mark_1st = 0;
903   char mark_2nd = 0;
904 
905   test_with_margins(1);
906 
907   set_colors(WHITE_ON_BLUE);
908 
909   top = get_top_margin();
910   lft = get_left_margin();
911   rgt = get_right_margin();
912   bot = get_bottom_margin(last - 1);
913 
914   /*
915    * Adjustments so that most of the initial line (before shifting) passes
916    * through the area within margins.
917    */
918   if (origin_mode) {
919     base_row = 0;
920     if (lrmm_flag) {
921       left_col = 1;
922       switch (tb_marg_flag) {
923       default:
924         last_row = bot;
925         break;
926       case marReset:
927       case marLast:
928         last_row = bot - 3;
929         break;
930       }
931       base_col = rgt - (bot - top) + last_row;
932       if (base_col < 0)
933         base_col = 0;
934       if (base_col > rgt)
935         base_col = rgt;
936       real_col = lr_marg1 + lft - (lr_marg1 != 0);
937     } else {
938       last_row = last;
939       base_col = (2 * last);
940       left_col = 1;
941       real_col = lft;
942     }
943   } else {
944     switch (lr_marg_flag) {
945     default:
946       base_col = (2 * last);
947       left_col = 1;
948       break;
949     case marFirst:
950       base_col = (min_cols / 2);
951       left_col = 1;
952       break;
953     case marMiddle:
954       base_col = (3 * min_cols) / 4;
955       left_col = (min_cols / 4) + 1;
956       break;
957     case marLast:
958       base_col = min_cols + 0;
959       left_col = (min_cols / 2) + 1;
960       break;
961     }
962     if (tb_marg_flag == marLast) {
963       base_row = max_lines / 2;
964     } else {
965       base_row = 0;
966     }
967     last_row = last;
968     real_col = lft;
969   }
970 
971   final_dc = base_col - 1;
972 
973   for (n = 1; n < last_row; n++) {
974     int row = base_row + n;
975     int col = base_col - n;
976 
977     if (row <= last_row) {
978       int mark = marker_of(n);
979 
980       if (row >= top && row <= bot && row < last_row) {
981         mark_2nd = (char) mark;
982         if (mark_1st == 0) {
983           mark_1st = (char) mark;
984         }
985       }
986 
987       slowly();
988       __(cup(row, col), print_chr(mark));
989       if (top > 1 || (lrmm_flag && lft > 1)) {
990         __(cup(1, 1), decdc(1));  /* outside margins, should be ignored */
991         __(cup(row, col), print_chr(mark));
992       }
993       if (final_dc-- > left_col)
994         __(cup(top, lft), decdc(1));
995     }
996   }
997   if (final_dc > left_col) {
998     slowly();
999     __(cup(top, lft), decdc(final_dc - left_col));
1000   }
1001 
1002   reset_colors();
1003 
1004   test_with_margins(0);
1005 
1006   ruler(last, min_cols);
1007   vt_move(last + 1, 1);
1008   vt_clear(0);
1009 
1010   tprintf("If your terminal supports DECDC, letters %c-%c are on column %d\n",
1011           mark_1st, mark_2nd, real_col);
1012   return MENU_HOLD;
1013 }
1014 
1015 /*
1016  * VT400 & up
1017  * Erase Rectangular area
1018  */
1019 static int
tst_DECERA(MENU_ARGS)1020 tst_DECERA(MENU_ARGS)
1021 {
1022   int last = max_lines - 3;
1023   BOX box;
1024 
1025   setup_rectangle(&box, last);
1026 
1027   fill_screen();
1028 
1029   test_with_margins(1);
1030 
1031   set_colors(WHITE_ON_GREEN);
1032 
1033   decera(box.top, box.left, box.bottom, box.right);
1034 
1035   sgr("0");
1036 
1037   test_with_margins(0);
1038 
1039   vt_move(last, 1);
1040   vt_clear(0);
1041 
1042   println(the_title);
1043   if (origin_mode)
1044     println("There should be a rectangle cleared in the middle of the margins.");
1045   else
1046     println("There should be a rectangle cleared in the middle of the screen.");
1047   return MENU_HOLD;
1048 }
1049 
1050 /*
1051  * This is two tests:  IND (index) and RI (reverse index).  For each test, we
1052  * start by filling the area inside (including) the margins with a test
1053  * pattern, and then after the user presses "return", update the screen so that
1054  * only one line of the test-pattern should remain visible.
1055  */
1056 static int
tst_IND_RI(MENU_ARGS)1057 tst_IND_RI(MENU_ARGS)
1058 {
1059   int hold_row = get_hold_row();
1060   int hold_col = get_hold_col();  /* where to put "Push RETURN" */
1061   int row;
1062   int top = get_top_margin();
1063   int bot = get_bottom_margin(max_lines);
1064   int lft = get_left_margin();
1065   int rgt = get_right_margin();
1066 
1067   test_with_margins(1);
1068 
1069   fill_margins();
1070 
1071   set_colors(0);
1072   special_prompt(hold_row, hold_col, 0);
1073 
1074   set_colors(WHITE_ON_GREEN);
1075   cup(bot, (lft + rgt) / 2);
1076   for (row = top; row < bot; ++row) {
1077     slowly();
1078     ind();
1079   }
1080 
1081   set_colors(0);
1082   special_prompt(hold_row, hold_col, "\"abcd...\" should be at top. ");
1083 
1084   fill_margins();
1085   fill_outside('.');
1086 
1087   set_colors(0);
1088   special_prompt(hold_row, hold_col, 0);
1089 
1090   set_colors(WHITE_ON_GREEN);
1091   cup(top, (lft + rgt) / 2);
1092   for (row = top; row < bot; ++row) {
1093     slowly();
1094     ri();
1095   }
1096 
1097   set_colors(0);
1098   special_prompt(hold_row, hold_col, "\"0123...\" should be at bottom. ");
1099 
1100   test_with_margins(0);
1101 
1102   return MENU_NOHOLD;
1103 }
1104 
1105 static int
tst_IL_DL(MENU_ARGS)1106 tst_IL_DL(MENU_ARGS)
1107 {
1108   int hold_row = get_hold_row();
1109   int hold_col = get_hold_col();  /* where to put "Push RETURN" */
1110   int row;
1111   int top = get_top_margin();
1112   int bot = get_bottom_margin(max_lines);
1113   int lft = get_left_margin();
1114   int rgt = get_right_margin();
1115 
1116   test_with_margins(1);
1117 
1118   fill_margins();
1119 
1120   set_colors(0);
1121   special_prompt(hold_row, hold_col, 0);
1122 
1123   /*
1124    * This should be ignored because it is outside margins.
1125    */
1126   set_colors(WHITE_ON_GREEN);
1127   if (!origin_mode) {
1128     if (top > 1) {
1129       cup(top - 1, lft);
1130       il(1);
1131     } else if (bot < max_lines) {
1132       cup(bot + 1, lft);
1133       il(1);
1134     } else if (lft > 1) {
1135       cup(top, lft - 1);
1136       il(1);
1137     } else if (rgt < min_cols) {
1138       cup(top, rgt + 1);
1139       il(1);
1140     }
1141   }
1142 
1143   cup(top, (lft + rgt) / 2);
1144   for (row = top; row < bot;) {
1145     int skip = (row % 2) + 1;
1146     row += skip;
1147     if (row >= bot)
1148       skip = 1;
1149     slowly();
1150     il(skip);
1151   }
1152 
1153   set_colors(0);
1154   special_prompt(hold_row, hold_col, "\"0123...\" should be at bottom. ");
1155 
1156   fill_margins();
1157   fill_outside('.');
1158 
1159   set_colors(0);
1160   special_prompt(hold_row, hold_col, 0);
1161 
1162   set_colors(WHITE_ON_GREEN);
1163   cup(top, (lft + rgt) / 2);
1164   for (row = top; row < bot;) {
1165     int skip = (row % 2) + 1;
1166     row += skip;
1167     if (row >= bot)
1168       skip = 1;
1169     slowly();
1170     dl(skip);
1171   }
1172 
1173   set_colors(0);
1174   special_prompt(hold_row, hold_col, "\"abcd...\" should be at top. ");
1175 
1176   test_with_margins(0);
1177 
1178   return MENU_NOHOLD;
1179 }
1180 
1181 static int
tst_ICH_DCH(MENU_ARGS)1182 tst_ICH_DCH(MENU_ARGS)
1183 {
1184   int n;
1185   int last = max_lines - 3;
1186   int base_row;
1187   int base_col;
1188   int last_row;
1189   int real_col;
1190   int top;
1191   int bot;
1192   int lft;
1193   int rgt;
1194   char mark_1st = 0;
1195   char mark_2nd = 0;
1196 
1197   test_with_margins(1);
1198 
1199   set_colors(WHITE_ON_BLUE);
1200 
1201   top = get_top_margin();
1202   bot = get_bottom_margin(last - 1);
1203   lft = get_left_margin();
1204   rgt = get_right_margin();
1205 
1206   /*
1207    * Adjustments so that most of the initial line (before shifting) passes
1208    * through the area within margins.
1209    */
1210   if (origin_mode) {
1211     base_row = 0;
1212     if (lrmm_flag) {
1213       base_col = rgt - (bot - top) - 2;
1214       if (base_col < 0)
1215         base_col = 0;
1216       switch (tb_marg_flag) {
1217       default:
1218         last_row = bot;
1219         break;
1220       case marReset:
1221       case marLast:
1222         last_row = bot - 3;
1223         break;
1224       }
1225       real_col = rgt + lr_marg1 - (lr_marg1 != 0);
1226     } else {
1227       last_row = last;
1228       base_col = (2 * last);
1229       real_col = rgt;
1230     }
1231   } else {
1232     switch (lr_marg_flag) {
1233     default:
1234       base_col = (2 * last);
1235       break;
1236     case marFirst:
1237       base_col = 0;
1238       break;
1239     case marMiddle:
1240       base_col = min_cols / 4;
1241       break;
1242     case marLast:
1243       base_col = (min_cols / 2);
1244       break;
1245     }
1246     if (tb_marg_flag == marLast) {
1247       base_row = max_lines / 2;
1248     } else {
1249       base_row = 0;
1250     }
1251     last_row = last;
1252     real_col = rgt;
1253   }
1254 
1255   for (n = 1; n < last_row; n++) {
1256     int row = base_row + n;
1257     int col = base_col + n;
1258 
1259     if (row < last_row) {
1260       int mark = marker_of(n);
1261 
1262       if (row >= top && row <= bot && row < last_row) {
1263         mark_2nd = (char) mark;
1264         if (mark_1st == 0) {
1265           mark_1st = (char) mark;
1266         }
1267       }
1268 
1269       slowly();
1270       __(cup(row, col), print_chr(mark));
1271       if (col < rgt) {
1272         cup(row, lft);
1273         print_chr('?');
1274         cup(row, lft);
1275         ich(rgt - col);
1276       }
1277     }
1278   }
1279 
1280   reset_colors();
1281 
1282   test_with_margins(0);
1283 
1284   ruler(last, min_cols);
1285   vt_move(last + 1, 1);
1286   vt_clear(0);
1287 
1288   tprintf("If your terminal supports ICH, letters %c-%c are on column %d\n",
1289           mark_1st, mark_2nd, real_col);
1290   holdit();
1291 
1292   vt_clear(0);
1293   test_with_margins(1);
1294 
1295   set_colors(WHITE_ON_BLUE);
1296 
1297   /*
1298    * Adjustments so that most of the initial line (before shifting) passes
1299    * through the area within margins.
1300    */
1301   if (origin_mode) {
1302     base_row = 0;
1303     if (lrmm_flag) {
1304       switch (tb_marg_flag) {
1305       default:
1306         last_row = bot;
1307         break;
1308       case marReset:
1309       case marLast:
1310         last_row = bot - 3;
1311         break;
1312       }
1313       base_col = rgt - (bot - top) + last_row;
1314       if (base_col < 0)
1315         base_col = 0;
1316       if (base_col > rgt)
1317         base_col = rgt;
1318       real_col = lr_marg1 + lft - (lr_marg1 != 0);
1319     } else {
1320       last_row = last;
1321       base_col = (2 * last);
1322       real_col = lft;
1323     }
1324   } else {
1325     switch (lr_marg_flag) {
1326     default:
1327       base_col = (2 * last);
1328       break;
1329     case marFirst:
1330       base_col = (min_cols / 2);
1331       break;
1332     case marMiddle:
1333       base_col = (3 * min_cols) / 4;
1334       break;
1335     case marLast:
1336       base_col = min_cols + 0;
1337       break;
1338     }
1339     if (tb_marg_flag == marLast) {
1340       base_row = max_lines / 2;
1341     } else {
1342       base_row = 0;
1343     }
1344     last_row = last;
1345     real_col = lft;
1346   }
1347 
1348   for (n = 1; n < last_row; n++) {
1349     int row = base_row + n;
1350     int col = base_col - n;
1351 
1352     if (row <= last_row) {
1353       int mark = marker_of(n);
1354 
1355       if (row >= top && row <= bot && row < last_row) {
1356         mark_2nd = (char) mark;
1357         if (mark_1st == 0) {
1358           mark_1st = (char) mark;
1359         }
1360       }
1361 
1362       __(cup(row, col), print_chr(mark));
1363       slowly();
1364       if (col < rgt)
1365         ech(rgt - col);
1366       if (col > lft) {
1367         cup(row, lft);
1368         dch(col - lft);
1369       } else {
1370         cup(row, 1);
1371         dch(col - 1);
1372       }
1373     }
1374   }
1375 
1376   reset_colors();
1377 
1378   test_with_margins(0);
1379 
1380   ruler(last, min_cols);
1381   vt_move(last + 1, 1);
1382   vt_clear(0);
1383 
1384   tprintf("If your terminal supports DCH, letters %c-%c are on column %d\n",
1385           mark_1st, mark_2nd, real_col);
1386   return MENU_HOLD;
1387 }
1388 
1389 /*
1390  * Check to see if ASCII formatting controls (BS, HT, CR) are affected by
1391  * left/right margins.  Do this by starting after the left-margin, and
1392  * backspacing "before" the left margin.  Then fill the margins with a usable
1393  * test pattern.  After that, use tabs to go to the right margin, adding
1394  * another usable test (+), and use carriage returns to go to the left margin,
1395  * adding another usable test (-).
1396  */
1397 static int
tst_ASCII_format(MENU_ARGS)1398 tst_ASCII_format(MENU_ARGS)
1399 {
1400   int last = max_lines - 4;
1401   int top;
1402   int bot;
1403   int lft;
1404   int rgt;
1405   int n;
1406   int tab;
1407   int size;
1408 
1409   test_with_margins(1);
1410 
1411   top = get_top_margin();
1412   bot = get_bottom_margin(last - 1);
1413   lft = get_left_margin();
1414   rgt = get_right_margin();
1415 
1416   /*
1417    * This should stop at the left margin, and the result overwritten by a
1418    * fill-pattern.
1419    */
1420   set_colors(WHITE_ON_BLUE);
1421   cup(top, rgt);
1422   for (n = 0; n < rgt; ++n) {
1423     printf("*%c%c", BS, BS);
1424   }
1425 
1426   /*
1427    * Fill the margins with a repeating pattern.  Do it twice, to force it to
1428    * scroll up.
1429    */
1430   set_colors(WHITE_ON_GREEN);
1431   size = 2 * (rgt - lft + 1) * (bot - top + 1);
1432   for (n = 0; n < size; ++n) {
1433     int ch = ((n % 10) ? ((n % 10) + '0') : '_');
1434     putchar(ch);
1435   }
1436 
1437   /*
1438    * Mark the margins with '-' (left) and '+' (right).
1439    */
1440   set_colors(YELLOW_ON_BLACK);
1441   cup(top, lft);
1442   for (n = top; n <= bot; ++n) {
1443     for (tab = 0; tab < (rgt - lft + 16) / TABWIDTH; ++tab) {
1444       putchar(TAB);
1445     }
1446     putchar('+');
1447     putchar(CR);
1448     putchar('-');
1449     putchar(TAB);
1450     putchar('*');
1451     if (n < bot) {
1452       putchar(LF);
1453     }
1454   }
1455 
1456   test_with_margins(0);
1457 
1458   set_colors("0");
1459 
1460   vt_move(last, 1);
1461   vt_clear(0);
1462 
1463   ruler(last, min_cols);
1464   println(the_title);
1465   println("A repeating \"0123456789_\" pattern should fall within the -/+ margins");
1466   return MENU_HOLD;
1467 }
1468 
1469 /*
1470  * VT400 & up.
1471  *
1472  * DECFI - Forward Index
1473  * This control function moves the column forward one column.  If the cursor is
1474  * at the right margin, then all screen data within the margins moves one
1475  * column to the left.  The column shifted past the left margin is lost.
1476  *
1477  * Format: ESC 9
1478  * Description:
1479  * DECFI adds a new column at the right margin with no visual attributes.
1480  * DECFI is not affected by the margins.  If the cursor is at the right border
1481  * of the page when the terminal receives DECFI, then the terminal ignores
1482  * DECFI.
1483  */
1484 static int
tst_DECFI(MENU_ARGS)1485 tst_DECFI(MENU_ARGS)
1486 {
1487   int n, m;
1488   int last = max_lines - 4;
1489   int final;
1490   int top;
1491   int lft;
1492   int rgt;
1493 
1494   test_with_margins(1);
1495 
1496   set_colors(WHITE_ON_BLUE);
1497 
1498   top = get_top_margin();
1499   lft = get_left_margin();
1500   rgt = get_right_margin();
1501 
1502   final = (rgt - lft + 1) / 4;
1503 
1504   for (n = 1; n <= final; n++) {
1505     slowly();
1506     cup(top, rgt - 3);
1507     printf("%3d", n);   /* leaves cursor in rightmost column */
1508     if (n != final) {
1509       for (m = 0; m < 4; m++)
1510         decfi();
1511     }
1512   }
1513 
1514   reset_colors();
1515 
1516   test_with_margins(0);
1517 
1518   vt_move(last, 1);
1519   vt_clear(0);
1520 
1521   println(the_title);
1522   println("If your terminal supports DECFI (forward index), then the top row");
1523   printf("should be numbered 1 through %d.\n", final);
1524   return MENU_HOLD;
1525 }
1526 
1527 /*
1528  * Demonstrate whether cursor movement is limited by margins.  VT420 manual
1529  * says that CUU/CUD will stop on the margins, but if outside the margins
1530  * will proceed to the page border.  So we can test this by
1531  *
1532  * a) moving to the margin, and cursor up/down toward the border, placing a
1533  * marker at the end of the cursor movement (to overwrite a prior marker placed
1534  * explicitly on the border).
1535  *
1536  * b) repeat the process, going from the border into the area within margins.
1537  *
1538  * c) Even for the no-margins case, this is useful, since it demonstrates
1539  * whether the cursor forces scrolling.
1540  */
1541 static int
tst_cursor_margins(MENU_ARGS)1542 tst_cursor_margins(MENU_ARGS)
1543 {
1544   BOX box;
1545   int last = get_hold_row();
1546   int row;
1547   int col;
1548 
1549   test_with_margins(1);
1550 
1551   box.top = get_top_margin();
1552   box.left = get_left_margin();
1553   box.right = get_right_margin();
1554   box.bottom = get_bottom_margin(max_lines);
1555 
1556   set_colors(WHITE_ON_BLUE);
1557   draw_box_filled(&box, ' ');
1558   draw_box_outline(&box, '*');
1559   set_colors(WHITE_ON_GREEN);
1560 
1561   for (row = box.top; row <= box.bottom; ++row) {
1562     cup(row, box.left);
1563     for (col = min_cols; col > 0; col--) {
1564       cub(1);
1565     }
1566     putchar('l');
1567   }
1568 
1569   for (row = box.top; row <= box.bottom; ++row) {
1570     cup(row, box.right);
1571     for (col = 1; col <= min_cols; col++) {
1572       cuf(1);
1573     }
1574     putchar('r');
1575   }
1576 
1577   for (col = box.left; col <= box.right; ++col) {
1578     cup(box.top, col);
1579     for (row = box.top; row > 0; row--) {
1580       cuu(1);
1581     }
1582     putchar('u');
1583   }
1584 
1585   for (col = box.left; col <= box.right; ++col) {
1586     cup(box.bottom, col);
1587     for (row = box.bottom; row <= max_lines; row++) {
1588       cud(1);
1589     }
1590     putchar('d');
1591   }
1592 
1593   set_colors("0");
1594   test_with_margins(0);
1595 
1596   vt_move(last, 1);
1597   if (last > box.bottom)
1598     vt_clear(0);
1599 
1600   println(the_title);
1601   println("A box of *'s was written on screen border, overwritten using margins (u/d/l/r)");
1602   return MENU_HOLD;
1603 }
1604 
1605 /*
1606  * Test movement with other things than cursor controls, i.e., BS, HT, CR, LF,
1607  * to see how margins affect them.
1608  */
1609 static int
tst_other_margins(MENU_ARGS)1610 tst_other_margins(MENU_ARGS)
1611 {
1612   BOX box;
1613   int last = get_hold_row();
1614   int row;
1615   int col;
1616 
1617   test_with_margins(1);
1618 
1619   box.top = get_top_margin();
1620   box.left = get_left_margin();
1621   box.right = get_right_margin();
1622   box.bottom = get_bottom_margin(max_lines);
1623 
1624   set_colors(WHITE_ON_BLUE);
1625   draw_box_filled(&box, ' ');
1626   draw_box_outline(&box, '*');
1627   set_colors(WHITE_ON_GREEN);
1628 
1629   for (row = box.top; row <= box.bottom; ++row) {
1630     cup(row, box.left);
1631     for (col = box.left; col > 0; col--) {
1632       putchar('\b');
1633     }
1634     putchar('l');
1635   }
1636 
1637   for (row = box.top; row <= box.bottom; ++row) {
1638     cup(row, box.right);
1639     for (col = 1; col <= min_cols; col++) {
1640       putchar('\t');
1641     }
1642     putchar('r');
1643   }
1644 
1645   for (col = box.left; col <= box.right; ++col) {
1646     cup(box.top, col);
1647     putchar('u');
1648     for (row = box.bottom; row > box.top; row--) {
1649       ind();
1650     }
1651   }
1652 
1653   for (col = box.left; col <= box.right; ++col) {
1654     switch (col % 4) {
1655     case 0:
1656       cup(box.bottom, col);
1657       putchar('d');
1658       break;
1659     case 1:
1660       cup(box.top, col);
1661       for (row = box.top; row < box.bottom; row++) {
1662         putchar('\f');
1663       }
1664       putchar('d');
1665       break;
1666     case 2:
1667       cup(box.top, col);
1668       for (row = box.top; row < box.bottom; row++) {
1669         nel();
1670         cuf(col - 1);
1671       }
1672       putchar('d');
1673       break;
1674     case 3:
1675       cup(box.bottom, col);
1676       putchar('d');
1677       for (row = box.top; row < box.bottom; row++) {
1678         ri();
1679       }
1680       putchar('u');
1681       break;
1682     }
1683   }
1684 
1685   set_colors("0");
1686   test_with_margins(0);
1687 
1688   vt_move(last, 1);
1689   if (hold_clear())
1690     vt_clear(0);
1691 
1692   println(the_title);
1693   println("A box of *'s was written on screen border, overwritten using margins (u/d/l/r)");
1694   return MENU_HOLD;
1695 }
1696 
1697 /*
1698  * VT400 & up
1699  * Fill Rectangular area
1700  */
1701 static int
tst_DECFRA(MENU_ARGS)1702 tst_DECFRA(MENU_ARGS)
1703 {
1704   int last = max_lines - 3;
1705   BOX box;
1706 
1707   setup_rectangle(&box, last);
1708 
1709   test_with_margins(1);
1710 
1711   if (do_colors) {
1712     set_colors(WHITE_ON_BLUE);
1713     vt_clear(2);  /* xterm fills the whole screen's background */
1714     set_colors(WHITE_ON_GREEN);
1715   }
1716   decfra('*', box.top, box.left, box.bottom, box.right);
1717 
1718   set_colors("0");
1719 
1720   test_with_margins(0);
1721 
1722   vt_move(last, 1);
1723   vt_clear(0);
1724 
1725   println(the_title);
1726   if (origin_mode)
1727     println("There should be a rectangle of *'s in the middle of the margins.");
1728   else
1729     println("There should be a rectangle of *'s in the middle of the screen.");
1730   holdit();
1731 
1732   test_with_margins(2);
1733 
1734   set_colors(WHITE_ON_BLUE);
1735 
1736   decfra(' ', box.top, box.left, box.bottom, box.right);
1737   sgr("0");
1738 
1739   test_with_margins(0);
1740 
1741   vt_move(last, 1);
1742   vt_clear(0);
1743 
1744   println(the_title);
1745   println("The rectangle of *'s should be gone.");
1746   return MENU_HOLD;
1747 }
1748 
1749 /*
1750  * VT400 & up.
1751  * Insert column.
1752  */
1753 static int
tst_DECIC(MENU_ARGS)1754 tst_DECIC(MENU_ARGS)
1755 {
1756   int n;
1757   int last = max_lines - 3;
1758   int base_row;
1759   int base_col;
1760   int last_row;
1761   int last_col;
1762   int real_col;
1763   int top;
1764   int bot;
1765   int lft;
1766   int rgt;
1767   int final_ic;
1768   char mark_1st = 0;
1769   char mark_2nd = 0;
1770 
1771   test_with_margins(1);
1772 
1773   set_colors(WHITE_ON_BLUE);
1774 
1775   top = get_top_margin();
1776   bot = get_bottom_margin(last - 1);
1777   lft = get_left_margin();
1778   rgt = get_right_margin();
1779 
1780   /*
1781    * Adjustments so that most of the initial line (before shifting) passes
1782    * through the area within margins.
1783    */
1784   if (origin_mode) {
1785     base_row = 0;
1786     if (lrmm_flag) {
1787       base_col = rgt - (bot - top) - 2;
1788       if (base_col < 0)
1789         base_col = 0;
1790       last_col = rgt - 1;
1791       switch (tb_marg_flag) {
1792       default:
1793         last_row = bot;
1794         break;
1795       case marReset:
1796       case marLast:
1797         last_row = bot - 3;
1798         break;
1799       }
1800       real_col = rgt + lr_marg1 - (lr_marg1 != 0);
1801     } else {
1802       last_row = last;
1803       base_col = (2 * last);
1804       last_col = min_cols - 1;
1805       real_col = rgt;
1806     }
1807   } else {
1808     if (lrmm_flag) {
1809       switch (lr_marg_flag) {
1810       default:
1811         base_col = (2 * last);
1812         last_col = min_cols - 1;
1813         break;
1814       case marFirst:
1815         base_col = 0;
1816         last_col = min_cols / 2 - 1;
1817         break;
1818       case marMiddle:
1819         base_col = min_cols / 4;
1820         last_col = (3 * min_cols) / 4 - 1;
1821         break;
1822       case marLast:
1823         base_col = (min_cols / 2);
1824         last_col = min_cols - 1;
1825         break;
1826       }
1827     } else {
1828       base_col = (2 * last);
1829       last_col = min_cols - 1;
1830     }
1831     if (tb_marg_flag == marLast) {
1832       base_row = max_lines / 2;
1833     } else {
1834       base_row = 0;
1835     }
1836     last_row = last;
1837     real_col = rgt;
1838   }
1839 
1840   final_ic = base_col;
1841 
1842   for (n = 1; n < last_row; n++) {
1843     int row = base_row + n;
1844     int col = base_col + n;
1845 
1846     if (row < last_row) {
1847       int mark = marker_of(n);
1848 
1849       if (row >= top && row <= bot && row < last_row) {
1850         mark_2nd = (char) mark;
1851         if (mark_1st == 0) {
1852           mark_1st = (char) mark;
1853         }
1854       }
1855 
1856       slowly();
1857       __(cup(row, col), print_chr(mark));
1858       if (!origin_mode && (top > 1 || (lrmm_flag && lft > 1))) {
1859         __(cup(1, 1), decic(1));  /* outside margins, should be ignored */
1860         __(cup(row, col), print_chr(mark));
1861       }
1862       if (final_ic++ <= last_col)
1863         __(cup(top, lft), decic(1));
1864     }
1865   }
1866   if (final_ic <= last_col) {
1867     slowly();
1868     decic(last_col - final_ic);
1869   }
1870 
1871   reset_colors();
1872 
1873   test_with_margins(0);
1874 
1875   ruler(last, min_cols);
1876   vt_move(last + 1, 1);
1877   vt_clear(0);
1878 
1879   tprintf("If your terminal supports DECIC, letters %c-%c are on column %d\n",
1880           mark_1st, mark_2nd, real_col);
1881   return MENU_HOLD;
1882 }
1883 
1884 static int
tst_DECIC_DECDC(MENU_ARGS)1885 tst_DECIC_DECDC(MENU_ARGS)
1886 {
1887   tst_DECIC(PASS_ARGS);
1888   holdit();
1889   vt_clear(2);
1890   tst_DECDC(PASS_ARGS);
1891   return MENU_HOLD;
1892 }
1893 
1894 static int
tst_DECKBUM(MENU_ARGS)1895 tst_DECKBUM(MENU_ARGS)
1896 {
1897   vt_move(1, 1);
1898   println(the_title);
1899 
1900   set_tty_raw(TRUE);
1901   set_tty_echo(FALSE);
1902 
1903   deckbum(TRUE);
1904   println("The keyboard is set for data processing.");
1905   show_keypress(3, 10);
1906 
1907   vt_move(10, 1);
1908   deckbum(FALSE);
1909   println("The keyboard is set for normal (typewriter) processing.");
1910   show_keypress(11, 10);
1911 
1912   restore_ttymodes();
1913   vt_move(max_lines - 1, 1);
1914   return MENU_HOLD;
1915 }
1916 
1917 static int
tst_DECKPM(MENU_ARGS)1918 tst_DECKPM(MENU_ARGS)
1919 {
1920   vt_move(1, 1);
1921   println(the_title);
1922 
1923   set_tty_raw(TRUE);
1924   set_tty_echo(FALSE);
1925 
1926   deckpm(TRUE);
1927   println("The keyboard is set for position reports.");
1928   show_keypress(3, 10);
1929 
1930   vt_move(10, 1);
1931   deckpm(FALSE);
1932   println("The keyboard is set for character codes.");
1933   show_keypress(11, 10);
1934 
1935   restore_ttymodes();
1936   vt_move(max_lines - 1, 1);
1937   return MENU_HOLD;
1938 }
1939 
1940 static int
tst_DECNKM(MENU_ARGS)1941 tst_DECNKM(MENU_ARGS)
1942 {
1943   vt_move(1, 1);
1944   println(the_title);
1945 
1946   set_tty_raw(TRUE);
1947   set_tty_echo(FALSE);
1948 
1949   decnkm(FALSE);
1950   println("Press one or more keys on the keypad.  They should generate numeric codes.");
1951   show_keypress(3, 10);
1952 
1953   vt_move(10, 1);
1954   decnkm(TRUE);
1955   println("Press one or more keys on the keypad.  They should generate control codes.");
1956   show_keypress(11, 10);
1957 
1958   decnkm(FALSE);
1959   vt_move(max_lines - 1, 1);
1960   restore_ttymodes();
1961   return MENU_HOLD;
1962 }
1963 
1964 /*
1965  * VT400 & up
1966  * Reverse Attributes in Rectangular Area
1967  */
1968 static int
tst_DECRARA(MENU_ARGS)1969 tst_DECRARA(MENU_ARGS)
1970 {
1971   int last = max_lines - 4;
1972   BOX box;
1973 
1974   setup_rectangle(&box, last);
1975 
1976   decsace(TRUE);
1977   fill_screen();
1978 
1979   test_with_margins(1);
1980 
1981   decrara(box.top, box.left, box.bottom, box.right, 7);   /* invert a rectangle) */
1982   decrara(box.top + 1, box.left + 1, box.bottom - 1, box.right - 1, 7);   /* invert a rectangle) */
1983 
1984   sgr("0");
1985 
1986   test_with_margins(0);
1987 
1988   vt_move(last, 1);
1989   vt_clear(0);
1990 
1991   println(the_title);
1992   println("There should be an open rectangle formed by reverse-video E's");
1993   holdit();
1994 
1995   decsace(FALSE);
1996   fill_screen();
1997 
1998   test_with_margins(1);
1999 
2000   decrara(box.top, box.left, box.bottom, box.right, 7);   /* invert a rectangle) */
2001   decrara(box.top + 1, box.left + 1, box.bottom - 1, box.right - 1, 7);   /* invert a rectangle) */
2002 
2003   sgr("0");
2004 
2005   test_with_margins(0);
2006 
2007   vt_move(last, 1);
2008   vt_clear(0);
2009 
2010   println(the_title);
2011   println("There should be an open rectangle formed by reverse-video E's");
2012   println("combined with wrapping at the margins.");
2013   return MENU_HOLD;
2014 }
2015 
2016 int
tst_vt420_DECRQSS(MENU_ARGS)2017 tst_vt420_DECRQSS(MENU_ARGS)
2018 {
2019   /* *INDENT-OFF* */
2020   static MENU my_menu[] = {
2021       { "Exit",                                              0 },
2022       { "Test VT320 features (DECRQSS)",                     tst_vt320_DECRQSS },
2023       { "Select attribute change extent (DECSACE)",          rpt_DECSACE },
2024       { "Set number of lines per screen (DECSNLS)",          rpt_DECSNLS },
2025       { "Set left and right margins (DECSLRM)",              rpt_DECSLRM },
2026       { "Enable local functions (DECELF)",                   rpt_DECELF },
2027       { "Local function key control (DECLFKC)",              rpt_DECLFKC },
2028       { "Select modifier key reporting (DECSMKR)",           rpt_DECSMKR },
2029       { "",                                                  0 }
2030     };
2031   /* *INDENT-ON* */
2032 
2033   do {
2034     vt_clear(2);
2035     __(title(0), printf("VT420 Status-Strings Reports"));
2036     __(title(2), println("Choose test type:"));
2037   } while (menu(my_menu));
2038   return MENU_NOHOLD;
2039 }
2040 
2041 /*
2042  * Selective-Erase Rectangular area
2043  */
2044 static int
tst_DECSERA(MENU_ARGS)2045 tst_DECSERA(MENU_ARGS)
2046 {
2047   int last = max_lines - 3;
2048   BOX box;
2049 
2050   setup_rectangle(&box, last);
2051 
2052   /*
2053    * Part 1: clear the borders of a rectangle, leaving protect inner rectangle.
2054    */
2055   fill_screen();
2056 
2057   test_with_margins(1);
2058 
2059   set_colors(WHITE_ON_GREEN);
2060 
2061   /*
2062    * Protect an area slightly smaller than we will erase.
2063    *
2064    * That way (since the SGR color at this point differs from the color used to
2065    * fill the screen), we can see whether the colors are modified by the erase,
2066    * and if so, whether they come from the SGR color.
2067    */
2068   decfra('*', box.top, box.left, box.bottom, box.right);
2069   decsca(1);
2070   decfra('*', box.top + 1, box.left + 1, box.bottom - 1, box.right - 1);
2071   decsca(0);
2072 
2073   sgr("0");
2074 
2075   test_with_margins(0);
2076 
2077   vt_move(last, 1);
2078   vt_clear(0);
2079 
2080   println(the_title);
2081   tprintf("Rectangle %d,%d - %d,%d was filled using DECFRA\n",
2082           box.top,
2083           box.left,
2084           box.bottom,
2085           box.right);
2086   holdit();
2087 
2088   test_with_margins(2);   /* reenable but do not paint margins */
2089 
2090   set_colors(WHITE_ON_BLUE);
2091 
2092   decsera(box.top, box.left, box.bottom, box.right);  /* erase the border */
2093 
2094   sgr("0");
2095 
2096   test_with_margins(0);
2097 
2098   vt_move(last, 1);
2099   vt_clear(0);
2100 
2101   println(the_title);
2102   tprintf("Border %d,%d - %d,%d is cleared using DECSERA\n",
2103           box.top,
2104           box.left,
2105           box.bottom,
2106           box.right);
2107   holdit();
2108 
2109   /*
2110    * Part 2: clear within the borders instead of clearing the borders.
2111    */
2112   fill_screen();
2113 
2114   test_with_margins(1);
2115 
2116   set_colors(WHITE_ON_GREEN);
2117 
2118   /*
2119    * Protect a rectangle and overwrite an inner rectangle which is not
2120    * protected.
2121    *
2122    * That way (since the SGR color at this point differs from the color used to
2123    * fill the screen), we can see whether the colors are modified by the erase,
2124    * and if so, whether they come from the SGR color.
2125    */
2126   decsca(1);
2127   decfra('*', box.top, box.left, box.bottom, box.right);
2128   decsca(0);
2129   decfra('*', box.top + 1, box.left + 1, box.bottom - 1, box.right - 1);
2130 
2131   sgr("0");
2132 
2133   test_with_margins(0);
2134 
2135   vt_move(last, 1);
2136   vt_clear(0);
2137 
2138   println(the_title);
2139   tprintf("Rectangle %d,%d - %d,%d was filled using DECFRA\n",
2140           box.top,
2141           box.left,
2142           box.bottom,
2143           box.right);
2144   holdit();
2145 
2146   test_with_margins(2);   /* reenable but do not paint margins */
2147 
2148   set_colors(WHITE_ON_BLUE);
2149 
2150   decsera(box.top, box.left, box.bottom, box.right);  /* erase inside border */
2151 
2152   sgr("0");
2153 
2154   test_with_margins(0);
2155 
2156   vt_move(last, 1);
2157   vt_clear(0);
2158 
2159   println(the_title);
2160   tprintf("Inside %d,%d - %d,%d is cleared using DECSERA\n",
2161           box.top + 1,
2162           box.left + 1,
2163           box.bottom - 1,
2164           box.right - 1);
2165 
2166   return MENU_HOLD;
2167 }
2168 
2169 static int
tst_DECSNLS(MENU_ARGS)2170 tst_DECSNLS(MENU_ARGS)
2171 {
2172   int rows;
2173   int row, col;
2174   char temp[80];
2175 
2176   vt_move(row = 1, col = 1);
2177   println("Testing Select Number of Lines per Screen (DECSNLS)");
2178   println("");
2179 
2180   for (rows = 48; rows >= 24; rows -= 12) {
2181     set_tty_raw(TRUE);
2182     set_tty_echo(FALSE);
2183 
2184     row += 2;
2185     sprintf(temp, "%d Lines/Screen:", rows);
2186     fputs(temp, stdout);
2187     decsnls(rows);
2188     decrqss("*|");
2189     chrprint2(instr(), row, (int) strlen(temp));
2190     println("");
2191 
2192     restore_ttymodes();
2193     holdit();
2194   }
2195 
2196   return MENU_NOHOLD;
2197 }
2198 
2199 static int
tst_DSR_area_sum(MENU_ARGS)2200 tst_DSR_area_sum(MENU_ARGS)
2201 {
2202   char buffer[1024];
2203   int expected = 0;
2204   int pid = 1;
2205   int page = 1;
2206   int r, c;
2207   int rows = 2;                 /* first two rows have known content */
2208   size_t len;
2209 
2210   sprintf(buffer, fmt_DECCKSR, the_title);
2211   len = strlen(buffer) - 1;
2212   memset(buffer + len, ' ', sizeof(buffer) - len);
2213   for (r = 0; r < rows; ++r) {
2214     for (c = 0; c < min_cols; ++c) {
2215       expected += (unsigned char) buffer[(min_cols * r) + c];
2216       expected &= 0xffff;
2217     }
2218   }
2219 
2220   /* compute a checksum on the title line, which contains some text */
2221   sprintf(buffer, "%d;%d;1;1;%d;%d*y", pid, page, rows, min_cols);
2222   return tst_DECCKSR(PASS_ARGS, 1, buffer, expected);
2223 }
2224 
2225 static int
tst_DSR_data_ok(MENU_ARGS)2226 tst_DSR_data_ok(MENU_ARGS)
2227 {
2228   return any_DSR(PASS_ARGS, "?75n", show_DataIntegrity);
2229 }
2230 
2231 static int
tst_DSR_macrospace(MENU_ARGS)2232 tst_DSR_macrospace(MENU_ARGS)
2233 {
2234   int row, col;
2235   char *report;
2236   const char *show;
2237 
2238   vt_move(1, 1);
2239   printf("Testing DECMSR: %s\n", the_title);
2240 
2241   set_tty_raw(TRUE);
2242   set_tty_echo(FALSE);
2243 
2244   do_csi("?62n");
2245   report = instr();
2246   vt_move(row = 3, col = 10);
2247   chrprint2(report, row, col);
2248   if ((report = skip_csi(report)) != 0
2249       && (report = skip_digits(report)) != 0
2250       && !strcmp(report, "*{")) {
2251     show = SHOW_SUCCESS;
2252   } else {
2253     show = SHOW_FAILURE;
2254   }
2255   show_result("%s", show);
2256 
2257   restore_ttymodes();
2258   vt_move(max_lines - 1, 1);
2259   return MENU_HOLD;
2260 }
2261 
2262 static int
tst_DSR_memory_sum(MENU_ARGS)2263 tst_DSR_memory_sum(MENU_ARGS)
2264 {
2265   return tst_DECCKSR(PASS_ARGS, 1, "?63;1n", -1);
2266 }
2267 
2268 static int
tst_DSR_multisession(MENU_ARGS)2269 tst_DSR_multisession(MENU_ARGS)
2270 {
2271   return any_DSR(PASS_ARGS, "?85n", show_MultisessionStatus);
2272 }
2273 
2274 int
tst_SRM(MENU_ARGS)2275 tst_SRM(MENU_ARGS)
2276 {
2277   int oldc, newc;
2278 
2279   vt_move(1, 1);
2280   println(the_title);
2281 
2282   set_tty_raw(TRUE);
2283 
2284   set_tty_echo(FALSE);
2285   srm(FALSE);
2286 
2287   println("Local echo is enabled, remote echo disabled.  Press any keys, repeat to quit.");
2288   vt_move(3, 10);
2289 
2290   oldc = -1;
2291   while ((newc = inchar()) != oldc)
2292     oldc = newc;
2293 
2294   set_tty_echo(TRUE);
2295   srm(TRUE);
2296 
2297   vt_move(10, 1);
2298   println("Local echo is disabled, remote echo enabled.  Press any keys, repeat to quit.");
2299   vt_move(11, 10);
2300 
2301   oldc = -1;
2302   while ((newc = inchar()) != oldc)
2303     oldc = newc;
2304 
2305   vt_move(max_lines - 1, 1);
2306   restore_ttymodes();
2307   return MENU_HOLD;
2308 }
2309 
2310 /******************************************************************************/
2311 
2312 void
setup_vt420_cursor(MENU_ARGS)2313 setup_vt420_cursor(MENU_ARGS)
2314 {
2315   tb_marg_flag = marNone;
2316   toggle_STBM(PASS_ARGS);
2317 
2318   lr_marg_flag = marNone;
2319   toggle_SLRM(PASS_ARGS);
2320 }
2321 
2322 void
menus_vt420_cursor(void)2323 menus_vt420_cursor(void)
2324 {
2325   sprintf(origin_mode_mesg, "%s DECOM (origin mode)", STR_ENABLE(origin_mode));
2326   sprintf(lrmm_mesg, "%s DECLRMM (left/right mode)", STR_ENABLE(lrmm_flag));
2327   sprintf(txt_override_color, "%s test-regions (xterm)",
2328           do_colors ? "Color" : "Do not color");
2329 }
2330 
2331 void
finish_vt420_cursor(MENU_ARGS)2332 finish_vt420_cursor(MENU_ARGS)
2333 {
2334   reset_colors();
2335   do_colors = FALSE;
2336 
2337   if (tb_marg_flag > marReset)
2338     decstbm(0, 0);
2339 
2340   if (lr_marg_flag > marReset) {
2341     if (!lrmm_flag)
2342       toggle_LRMM(PASS_ARGS);
2343     decslrm(0, 0);
2344   }
2345 
2346   if (lrmm_flag)
2347     toggle_LRMM(PASS_ARGS);
2348 
2349   if (origin_mode) {
2350     decom(FALSE);
2351     origin_mode = FALSE;
2352   }
2353 }
2354 
2355 /*
2356  * The main vt100 module tests CUP, HVP, CUF, CUB, CUU, CUD
2357  */
2358 int
tst_vt420_cursor(MENU_ARGS)2359 tst_vt420_cursor(MENU_ARGS)
2360 {
2361   /* *INDENT-OFF* */
2362   static MENU my_menu[] = {
2363       { "Exit",                                              0 },
2364       { "Test VT320 features",                               tst_vt320_cursor },
2365       { origin_mode_mesg,                                    toggle_DECOM },
2366       { lrmm_mesg,                                           toggle_LRMM },
2367       { tb_marg_mesg,                                        toggle_STBM },
2368       { lr_marg_mesg,                                        toggle_SLRM },
2369       { txt_override_color,                                  toggle_color_mode, },
2370       { "Test Back Index (DECBI)",                           tst_DECBI },
2371       { "Test Forward Index (DECFI)",                        tst_DECFI },
2372       { "Test cursor movement within margins",               tst_cursor_margins },
2373       { "Test other movement (CR/HT/LF/FF) within margins",  tst_other_margins },
2374       { "",                                                  0 }
2375     };
2376   /* *INDENT-ON* */
2377 
2378   setup_vt420_cursor(PASS_ARGS);
2379 
2380   do {
2381     vt_clear(2);
2382     __(title(0), printf("VT420 Cursor-Movement Tests"));
2383     __(title(2), println("Choose test type:"));
2384     menus_vt420_cursor();
2385   } while (menu(my_menu));
2386 
2387   finish_vt420_cursor(PASS_ARGS);
2388 
2389   return MENU_NOHOLD;
2390 }
2391 
2392 /******************************************************************************/
2393 
2394 static int
show_DECSTBM(MENU_ARGS)2395 show_DECSTBM(MENU_ARGS)
2396 {
2397   int code;
2398   decstbm(tb_marg1, tb_marg2);
2399   code = rpt_DECSTBM(PASS_ARGS);
2400   return code;
2401 }
2402 
2403 static int
show_DECSLRM(MENU_ARGS)2404 show_DECSLRM(MENU_ARGS)
2405 {
2406   int code;
2407   decslrm(lr_marg1, lr_marg2);
2408   code = rpt_DECSLRM(PASS_ARGS);
2409   return code;
2410 }
2411 
2412 /*
2413  * The main vt100 module tests IRM, DL, IL, DCH, ICH, ED, EL
2414  * The vt220 module tests ECH and DECSCA
2415  */
2416 static int
tst_VT420_editing(MENU_ARGS)2417 tst_VT420_editing(MENU_ARGS)
2418 {
2419   /* *INDENT-OFF* */
2420   static MENU my_menu[] = {
2421       { "Exit",                                              0 },
2422       { origin_mode_mesg,                                    toggle_DECOM },
2423       { lrmm_mesg,                                           toggle_LRMM },
2424       { tb_marg_mesg,                                        toggle_STBM },
2425       { lr_marg_mesg,                                        toggle_SLRM },
2426       { txt_override_color,                                  toggle_color_mode, },
2427       { "Show DECRQM response for DECLRMM",                  show_DECLRMM },
2428       { "Show DECRQSS response for DECSTBM",                 show_DECSTBM },
2429       { "Show DECRQSS response for DECSLRM",                 show_DECSLRM },
2430       { "Test insert/delete column (DECIC, DECDC)",          tst_DECIC_DECDC },
2431       { "Test vertical scrolling (IND, RI)",                 tst_IND_RI },
2432       { "Test insert/delete line (IL, DL)",                  tst_IL_DL },
2433       { "Test insert/delete char (ICH, DCH)",                tst_ICH_DCH },
2434       { "Test ASCII formatting (BS, CR, TAB)",               tst_ASCII_format },
2435       { "",                                                  0 }
2436     };
2437   /* *INDENT-ON* */
2438 
2439   setup_vt420_cursor(PASS_ARGS);
2440 
2441   do {
2442     vt_clear(2);
2443     __(title(0), printf("VT420 Editing Sequence Tests"));
2444     __(title(2), println("Choose test type:"));
2445     menus_vt420_cursor();
2446   } while (menu(my_menu));
2447 
2448   finish_vt420_cursor(PASS_ARGS);
2449 
2450   return MENU_NOHOLD;
2451 }
2452 
2453 /******************************************************************************/
2454 
2455 /*
2456  * The main vt100 module tests LNM, DECKPAM, DECARM, DECAWM
2457  */
2458 static int
tst_VT420_keyboard_ctl(MENU_ARGS)2459 tst_VT420_keyboard_ctl(MENU_ARGS)
2460 {
2461   /* *INDENT-OFF* */
2462   static MENU my_menu[] = {
2463       { "Exit",                                              0 },
2464       { "Test Backarrow key (DECBKM)",                       tst_DECBKM },
2465       { "Test Numeric keypad (DECNKM)",                      tst_DECNKM },
2466       { "Test Keyboard usage (DECKBUM)",                     tst_DECKBUM },
2467       { "Test Key position (DECKPM)",                        tst_DECKPM },
2468       { "Test Enable Local Functions (DECELF)",              not_impl },
2469       { "Test Local Function-Key Control (DECLFKC)",         not_impl },
2470       { "Test Select Modifier-Key Reporting (DECSMKR)",      not_impl }, /* DECEKBD */
2471       { "",                                                  0 }
2472     };
2473   /* *INDENT-ON* */
2474 
2475   do {
2476     vt_clear(2);
2477     __(title(0), printf("VT420 Keyboard-Control Tests"));
2478     __(title(2), println("Choose test type:"));
2479   } while (menu(my_menu));
2480   return MENU_NOHOLD;
2481 }
2482 
2483 /******************************************************************************/
2484 
2485 static int
tst_VT420_rectangle(MENU_ARGS)2486 tst_VT420_rectangle(MENU_ARGS)
2487 {
2488   static char txt_override_lines[80];
2489   /* *INDENT-OFF* */
2490   static MENU my_menu[] = {
2491       { "Exit",                                              0 },
2492       { origin_mode_mesg,                                    toggle_DECOM },
2493       { lrmm_mesg,                                           toggle_LRMM },
2494       { tb_marg_mesg,                                        toggle_STBM },
2495       { lr_marg_mesg,                                        toggle_SLRM },
2496       { txt_override_color,                                  toggle_color_mode, },
2497       { txt_override_lines,                                  toggle_lines_mode, },
2498       { "Test Change-Attributes in Rectangular Area (DECCARA)", tst_DECCARA },
2499       { "Test Copy Rectangular area (DECCRA)",               tst_DECCRA },
2500       { "Test Erase Rectangular area (DECERA)",              tst_DECERA },
2501       { "Test Fill Rectangular area (DECFRA)",               tst_DECFRA },
2502       { "Test Reverse-Attributes in Rectangular Area (DECRARA)", tst_DECRARA },
2503       { "Test Selective-Erase Rectangular area (DECSERA)",   tst_DECSERA },
2504       { "",                                                  0 }
2505     };
2506   /* *INDENT-ON* */
2507 
2508   setup_vt420_cursor(PASS_ARGS);
2509 
2510   do {
2511     vt_clear(2);
2512     __(title(0), printf("VT420 Rectangular Area Tests%s",
2513                         ((terminal_id() < 400)
2514                          ? " (should not work)"
2515                          : "")));
2516     __(title(2), println("Choose test type:"));
2517     menus_vt420_cursor();
2518     sprintf(txt_override_lines, "%s line-drawing characters",
2519             do_lines ? "Use" : "Do not use");
2520   } while (menu(my_menu));
2521 
2522   finish_vt420_cursor(PASS_ARGS);
2523 
2524   return MENU_NOHOLD;
2525 }
2526 
2527 /******************************************************************************/
2528 
2529 /* UDK and rectangle-checksum status are available only on VT400 */
2530 
2531 int
tst_vt420_device_status(MENU_ARGS)2532 tst_vt420_device_status(MENU_ARGS)
2533 {
2534   /* *INDENT-OFF* */
2535   static MENU my_menu[] = {
2536       { "Exit",                                              0 },
2537       { "Test VT320 features",                               tst_vt320_device_status },
2538       { "Test Printer Status",                               tst_DSR_printer },
2539       { "Test UDK Status",                                   tst_DSR_userkeys },
2540       { "Test Keyboard Status",                              tst_DSR_keyboard },
2541       { "Test Locator Status",                               tst_DSR_locator },
2542       { "Test Macro Space",                                  tst_DSR_macrospace },
2543       { "Test Memory Checksum",                              tst_DSR_memory_sum },
2544       { "Test Data Integrity",                               tst_DSR_data_ok },
2545       { "Test Multiple Session Status",                      tst_DSR_multisession },
2546       { "Test Checksum of Rectangular Area (DECRQCRA)",      tst_DSR_area_sum },
2547       { "Test Extended Cursor-Position (DECXCPR)",           tst_DSR_cursor },
2548       { "",                                                  0 }
2549     };
2550   /* *INDENT-ON* */
2551 
2552   do {
2553     vt_clear(2);
2554     __(title(0), printf("VT420 Device Status Reports (DSR)"));
2555     __(title(2), println("Choose test type:"));
2556   } while (menu(my_menu));
2557   return MENU_NOHOLD;
2558 }
2559 
2560 /******************************************************************************/
2561 
2562 int
tst_vt420_report_presentation(MENU_ARGS)2563 tst_vt420_report_presentation(MENU_ARGS)
2564 {
2565   /* *INDENT-OFF* */
2566   static MENU my_menu[] = {
2567       { "Exit",                                              0 },
2568       { "Test VT320 features",                               tst_vt320_report_presentation },
2569       { "Request Mode (DECRQM)/Report Mode (DECRPM)",        tst_DECRPM },
2570       { "Status-String Report (DECRQSS)",                    tst_vt420_DECRQSS },
2571       { "",                                                  0 }
2572     };
2573   /* *INDENT-ON* */
2574 
2575   int old_DECRPM = set_DECRPM(4);
2576 
2577   do {
2578     vt_clear(2);
2579     __(title(0), printf("VT420 Presentation State Reports"));
2580     __(title(2), println("Choose test type:"));
2581   } while (menu(my_menu));
2582   set_DECRPM(old_DECRPM);
2583   return MENU_NOHOLD;
2584 }
2585 
2586 int
tst_vt420_reports(MENU_ARGS)2587 tst_vt420_reports(MENU_ARGS)
2588 {
2589   /* *INDENT-OFF* */
2590   static MENU my_menu[] = {
2591       { "Exit",                                              0 },
2592       { "Test VT320 features",                               tst_vt320_reports },
2593       { "Test Presentation State Reports",                   tst_vt420_report_presentation },
2594       { "Test Device Status Reports (DSR)",                  tst_vt420_device_status },
2595       { "",                                                  0 }
2596     };
2597   /* *INDENT-ON* */
2598 
2599   do {
2600     vt_clear(2);
2601     __(title(0), printf("VT420 Reports"));
2602     __(title(2), println("Choose test type:"));
2603   } while (menu(my_menu));
2604   return MENU_NOHOLD;
2605 }
2606 
2607 /******************************************************************************/
2608 
2609 static int
tst_VT420_screen(MENU_ARGS)2610 tst_VT420_screen(MENU_ARGS)
2611 {
2612   /* *INDENT-OFF* */
2613   static MENU my_menu[] = {
2614       { "Exit",                                              0 },
2615       { "Test VT320 features",                               tst_vt320_screen },
2616       { "Test Select Number of Lines per Screen (DECSNLS)",  tst_DECSNLS },
2617       { "",                                                  0 }
2618     };
2619   /* *INDENT-ON* */
2620 
2621   do {
2622     vt_clear(2);
2623     __(title(0), printf("VT420 Screen-Display Tests"));
2624     __(title(2), println("Choose test type:"));
2625   } while (menu(my_menu));
2626   return MENU_NOHOLD;
2627 }
2628 
2629 /******************************************************************************/
2630 
2631 /*
2632  * These apply only to VT400's & above.
2633  */
2634 int
tst_vt420(MENU_ARGS)2635 tst_vt420(MENU_ARGS)
2636 {
2637   /* *INDENT-OFF* */
2638   static MENU my_menu[] = {
2639       { "Exit",                                              0 },
2640       { "Test VT320 features",                               tst_vt320 },
2641       { "Test cursor-movement",                              tst_vt420_cursor },
2642       { "Test editing sequences",                            tst_VT420_editing },
2643       { "Test keyboard-control",                             tst_VT420_keyboard_ctl },
2644       { "Test macro-definition (DECDMAC)",                   not_impl },
2645       { "Test rectangular area functions",                   tst_VT420_rectangle },
2646       { "Test reporting functions",                          tst_vt420_reports },
2647       { "Test screen-display functions",                     tst_VT420_screen },
2648       { "",                                                  0 }
2649     };
2650   /* *INDENT-ON* */
2651 
2652   do {
2653     vt_clear(2);
2654     __(title(0), printf("VT420 Tests"));
2655     __(title(2), println("Choose test type:"));
2656   } while (menu(my_menu));
2657   return MENU_NOHOLD;
2658 }
2659