ncurses 5.0
[ncurses.git] / tack / fun.c
1 /*
2 ** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
3 ** 
4 ** This file is part of TACK.
5 ** 
6 ** TACK is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2, or (at your option)
9 ** any later version.
10 ** 
11 ** TACK is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ** GNU General Public License for more details.
15 ** 
16 ** You should have received a copy of the GNU General Public License
17 ** along with TACK; see the file COPYING.  If not, write to
18 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 ** Boston, MA 02111-1307, USA.
20 */
21
22 #include <tack.h>
23
24 MODULE_ID("$Id: fun.c,v 1.2 1999/06/16 00:46:12 tom Exp $")
25
26 /*
27  * Test the function keys on the terminal.  The code for echo tests
28  * lives here too.
29  */
30
31 static void funkey_keys(struct test_list *, int *, int *);
32 static void funkey_meta(struct test_list *, int *, int *);
33 static void funkey_label(struct test_list *, int *, int *);
34 static void funkey_prog(struct test_list *, int *, int *);
35 static void funkey_local(struct test_list *, int *, int *);
36
37 struct test_list funkey_test_list[] = {
38         {0, 0, 0, 0, "e) edit terminfo", 0, &edit_menu},
39         {MENU_CLEAR + FLAG_FUNCTION_KEY, 0, 0, 0, "f) show a list of function keys", show_report, 0},
40         {MENU_NEXT | MENU_CLEAR, 0, "smkx) (rmkx", 0,
41                 "k) test function keys", funkey_keys, 0},
42         {MENU_NEXT, 10, "km", "smm rmm", 0, funkey_meta, 0},
43         {MENU_NEXT, 8, "nlab) (smln) (pln) (rmln", "lw lh", 0, funkey_label, 0},
44         {MENU_NEXT, 2, "pfx", 0, 0, funkey_prog, 0},
45         {MENU_NEXT, 2, "pfloc", 0, 0, funkey_local, 0},
46         {MENU_LAST, 0, 0, 0, 0, 0, 0}
47 };
48
49 static void printer_on(struct test_list *, int *, int *);
50 static void printer_mc0(struct test_list *, int *, int *);
51
52 struct test_list printer_test_list[] = {
53         {0, 0, 0, 0, "e) edit terminfo", 0, &edit_menu},
54         {MENU_NEXT | MENU_CLEAR, 0, "mc4) (mc5) (mc5i", 0, 0, printer_on, 0},
55         {MENU_NEXT | MENU_CLEAR, 0, "mc0", 0, 0, printer_mc0, 0},
56         {MENU_LAST, 0, 0, 0, 0, 0, 0}
57 };
58
59 #define MAX_STRINGS STRCOUNT
60
61 /* scan code externals */
62 extern int scan_max;            /* length of longest scan code */
63 extern char **scan_up, **scan_down, **scan_name;
64 extern int *scan_tested, *scan_length;
65
66 /* local definitions */
67 static const char *fk_name[MAX_STRINGS];
68 static char *fkval[MAX_STRINGS];
69 static char *fk_label[MAX_STRINGS];     /* function key labels (if any) */
70 static int fk_tested[MAX_STRINGS];
71 static int fkmax = 1;           /* length of longest key */
72 static int got_labels = 0;      /* true if we have some labels */
73 static int key_count = 0;
74 static int end_state;
75
76 /* unknown function keys */
77 #define MAX_FK_UNK 50
78 static char *fk_unknown[MAX_FK_UNK];
79 static int fk_length[MAX_FK_UNK];
80 static int funk;
81
82 /*
83 **      keys_tested(first-time, show-help, hex-output)
84 **
85 **      Display a list of the keys not tested.
86 */
87 static void
88 keys_tested(
89         int first_time,
90         int show_help,
91         int hex_output)
92 {
93         int i, l;
94         char outbuf[256];
95
96         put_clear();
97         tty_set();
98         flush_input();
99         if (got_labels) {
100                 putln("Function key labels:");
101                 for (i = 0; i < key_count; ++i) {
102                         if (fk_label[i]) {
103                                 sprintf(outbuf, "%s %s",
104                                         fk_name[i] ? fk_name[i] : "??", fk_label[i]);
105                                 put_columns(outbuf, strlen(outbuf), 16);
106                         }
107                 }
108                 put_newlines(2);
109         }
110         if (funk) {
111                 putln("The following keys are not defined:");
112                 for (i = 0; i < funk; ++i) {
113                         put_columns(fk_unknown[i], fk_length[i], 16);
114                 }
115                 put_mode(exit_attribute_mode);
116                 put_newlines(2);
117         }
118         if (first_time) {
119                 putln("The following keys are defined:");
120         } else {
121                 putln("The following keys have not been tested:");
122         }
123         if (scan_mode) {
124                 for (i = 0; scan_down[i]; i++) {
125                         if (!scan_tested[i]) {
126                                 if (hex_output) {
127                                         strcpy(outbuf, hex_expand_to(scan_down[i], 3));
128                                 } else {
129                                         strcpy(outbuf, expand(scan_down[i]));
130                                 }
131                                 l = expand_chars;
132                                 if (hex_output) {
133                                         strcat(outbuf, hex_expand_to(scan_up[i], 3));
134                                 } else {
135                                         strcat(outbuf, expand(scan_up[i]));
136                                 }
137                                 expand_chars += l;
138                                 l = strlen(scan_name[i]);
139                                 if (((char_count + 16) & ~15) +
140                                         ((expand_chars + 7) & ~7) + l >= columns) {
141                                         put_crlf();
142                                 } else
143                                 if (char_count + 24 > columns) {
144                                         put_crlf();
145                                 } else if (char_count) {
146                                         putchp(' ');
147                                 }
148                                 put_columns(outbuf, expand_chars, 16);
149                                 put_columns(scan_name[i], l, 8);
150                         }
151                 }
152         } else {
153                 for (i = 0; i < key_count; i++) {
154                         if (!fk_tested[i]) {
155                                 if (hex_output) {
156                                         strcpy(outbuf, hex_expand_to(fkval[i], 3));
157                                 } else {
158                                         strcpy(outbuf, expand(fkval[i]));
159                                 }
160                                 l = strlen(fk_name[i]);
161                                 if (((char_count + 16) & ~15) +
162                                         ((expand_chars + 7) & ~7) + l >= columns) {
163                                         put_crlf();
164                                 } else
165                                 if (char_count + 24 > columns) {
166                                         put_crlf();
167                                 } else
168                                 if (char_count) {
169                                         putchp(' ');
170                                 }
171                                 put_columns(outbuf, expand_chars, 16);
172                                 put_columns(fk_name[i], l, 8);
173                         }
174                 }
175         }
176         put_newlines(2);
177         if (show_help) {
178                 ptextln("Hit any function key.  Type 'end' to quit.  Type ? to update the display.");
179                 put_crlf();
180         }
181 }
182
183 /*
184 **      enter_key(name, value, label)
185 **
186 **      Enter a function key into the data base
187 */
188 void
189 enter_key(
190         const char *name,
191         char *value,
192         char *lab)
193 {
194         int j;
195
196         if (value) {
197                 j = strlen(value);
198                 fkmax = fkmax > j ? fkmax : j;
199                 /* do not permit duplicates */
200                 for (j = 0; j < key_count; j++) {
201                         if (!strcmp(fk_name[j], name)) {
202                                 return;
203                         }
204                 }
205                 fkval[key_count] = value;
206                 fk_tested[key_count] = 0;
207                 fk_label[key_count] = lab;
208                 fk_name[key_count++] = name;
209                 if (lab) {
210                         got_labels = TRUE;
211                 }
212         }
213 }
214
215
216 static void
217 fresh_line(void)
218 {                               /* clear the line for a new fumction key line */
219         if (over_strike) {
220                 put_crlf();
221         } else {
222                 put_cr();
223                 if (clr_eol) {
224                         tc_putp(clr_eol);
225                 } else {
226                         put_str("                    \r");
227                 }
228         }
229 }
230
231
232 static int
233 end_funky(int ch)
234 {                               /* return true if this is the end */
235         switch (ch) {
236         case 'e':
237         case 'E':
238                 end_state = 'e';
239                 break;
240         case 'n':
241         case 'N':
242                 if (end_state == 'e') {
243                         end_state = 'n';
244                 } else {
245                         end_state = 0;
246                 }
247                 break;
248         case 'd':
249         case 'D':
250                 if (end_state == 'n') {
251                         end_state = 'd';
252                 } else {
253                         end_state = 0;
254                 }
255                 break;
256         case 'l':
257         case 'L':
258                 if (end_state == 'l') {
259                         end_state = '?';
260                 } else {
261                         end_state = 'l';
262                 }
263                 break;
264         default:
265                 end_state = 0;
266                 break;
267         }
268         return end_state == 'd';
269 }
270
271
272 static int
273 found_match(char *s, int hx, int cc)
274 {                               /* return true if this string is a match */
275         int j, f;
276         char outbuf[256];
277
278         if (!*s) {
279                 return 0;
280         }
281         if (scan_mode) {
282                 for (j = f = 0; scan_down[j]; j++) {
283                         if (scan_length[j] == 0) {
284                                 continue;
285                         }
286                         if (!strncmp(s, scan_down[j], scan_length[j])) {
287                                 if (!f) {       /* first match */
288                                         put_cr();
289                                         if (hx) {
290                                                 put_str(hex_expand_to(s, 10));
291                                         } else {
292                                                 put_str(expand_to(s, 10));
293                                         }
294                                         f = 1;
295                                 }
296                                 (void) end_funky(scan_name[j][0]);
297                                 put_str(" ");
298                                 put_str(scan_name[j]);
299                                 scan_tested[j] = 1;
300                                 s += scan_length[j];
301                                 if (strncmp(s, scan_up[j], scan_length[j])) {
302                                         put_str(" scan down");
303                                 } else {
304                                         s += scan_length[j];
305                                 }
306                                 if (!*s) {
307                                         break;
308                                 }
309                                 j = -1;
310                         }
311                         if (!strncmp(s, scan_up[j], scan_length[j])) {
312                                 if (!f) {       /* first match */
313                                         put_cr();
314                                         if (hx) {
315                                                 put_str(hex_expand_to(s, 10));
316                                         } else {
317                                                 put_str(expand_to(s, 10));
318                                         }
319                                         f = 1;
320                                 }
321                                 put_str(" ");
322                                 put_str(scan_name[j]);
323                                 put_str(" scan up");
324                                 s += scan_length[j];
325                                 if (!*s) {
326                                         break;
327                                 }
328                                 j = -1;
329                         }
330                 }
331         } else {
332                 for (j = f = 0; j < key_count; j++) {
333                         if (!strcmp(s, fkval[j])) {
334                                 if (!f) {       /* first match */
335                                         put_cr();
336                                         if (hx) {
337                                                 put_str(hex_expand_to(s, 10));
338                                         } else {
339                                                 put_str(expand_to(s, 10));
340                                         }
341                                         f = 1;
342                                 }
343                                 sprintf(outbuf, " (%s)", fk_name[j]);
344                                 put_str(outbuf);
345                                 if (fk_label[j]) {
346                                         sprintf(outbuf, " <%s>", fk_label[j]);
347                                         put_str(outbuf);
348                                 }
349                                 fk_tested[j] = 1;
350                         }
351                 }
352         }
353         if (end_state == '?') {
354                 keys_tested(0, 1, hx);
355                 tty_raw(cc, char_mask);
356                 end_state = 0;
357         }
358         return f;
359 }
360
361
362 static int
363 found_exit(char *keybuf, int hx, int cc)
364 {                               /* return true if the user wants to exit */
365         int j, k;
366         char *s;
367
368
369         if (scan_mode) {
370                 if (*keybuf == '\0') {
371                         return TRUE;
372                 }
373         } else {
374                 /* break is a special case */
375                 if (*keybuf == '\0') {
376                         fresh_line();
377                         tty_set();
378                         ptext("Hit X to exit: ");
379                         if (wait_here() == 'X') {
380                                 return TRUE;
381                         }
382                         keys_tested(0, 1, hx);
383                         tty_raw(cc, char_mask);
384                         return FALSE;
385                 }
386                 /* is this the end? */
387                 for (k = 0; (j = (keybuf[k] & STRIP_PARITY)); k++) {
388                         if (end_funky(j)) {
389                                 return TRUE;
390                         }
391                 }
392
393                 j = TRUE;       /* does he need an updated list? */
394                 for (k = 0; keybuf[k]; k++) {
395                         j &= (keybuf[k] & STRIP_PARITY) == '?';
396                 }
397                 if (j || end_state == '?') {
398                         keys_tested(0, 1, hx);
399                         tty_raw(cc, char_mask);
400                         end_state = 0;
401                         return FALSE;
402                 }
403         }
404
405         put_cr();
406         if (hx) {
407                 s = hex_expand_to(keybuf, 10);
408         } else {
409                 s = expand_to(keybuf, 10);
410         }
411         sprintf(temp, "%s Unknown", s);
412         put_str(temp);
413         for (j = 0; j < MAX_FK_UNK; j++) {
414                 if (j == funk) {
415                         fk_length[funk] = expand_chars;
416                         if ((fk_unknown[funk] = (char *)malloc(strlen(s) + 1))) {
417                                 strcpy(fk_unknown[funk++], s);
418                         }
419                         break;
420                 }
421                 if (fk_length[j] == expand_chars) {
422                         if (!strcmp(fk_unknown[j], s)) {
423                                 break;
424                         }
425                 }
426         }
427         return FALSE;
428 }
429
430 /*
431 **      funkey_keys(test_list, status, ch)
432 **
433 **      Test function keys
434 */
435 static void
436 funkey_keys(
437         struct test_list *t,
438         int *state,
439         int *ch)
440 {
441         char keybuf[256];
442
443         if (keypad_xmit) {
444                 tc_putp(keypad_xmit);
445         }
446         keys_tested(1, 1, hex_out);     /* also clears screen */
447         keybuf[0] = '\0';
448         end_state = 0;
449         if (scan_mode) {
450                 fkmax = scan_max;
451         }
452         tty_raw(0, char_mask);
453         while (end_state != 'd') {
454                 read_key(keybuf, sizeof(keybuf));
455                 fresh_line();
456                 if (found_match(keybuf, hex_out, 0)) {
457                         continue;
458                 }
459                 if (found_exit(keybuf, hex_out, 0)) {
460                         break;
461                 }
462         }
463         if (keypad_local) {
464                 tc_putp(keypad_local);
465         }
466         keys_tested(0, 0, hex_out);
467         ptext("Function key test ");
468         generic_done_message(t, state, ch);
469 }
470
471 int
472 tty_meta_prep(void)
473 {                               /* print a warning before the meta key test */
474         if (not_a_tty) {
475                 return 0;
476         }
477         if (initial_stty_query(TTY_8_BIT)) {
478                 return 0;
479         }
480         ptext("The meta key test must be run with the");
481         ptext(" terminal set for 8 data bits.  Two stop bits");
482         ptext(" may also be needed for correct display.  I will");
483         ptext(" transmit 8 bit data but if the terminal is set for");
484         ptextln(" 7 bit data, garbage may appear on the screen.");
485         return 1;
486 }
487
488 /*
489 **      funkey_meta(test_list, status, ch)
490 **
491 **      Test meta key (km) (smm) (rmm)
492 */
493 static void
494 funkey_meta(
495         struct test_list *t,
496         int *state,
497         int *ch)
498 {
499         int i, j, k, len;
500         char outbuf[256];
501
502         if (has_meta_key) {
503                 put_crlf();
504                 if (char_mask != ALLOW_PARITY) {
505                         if (tty_meta_prep()) {
506                                 ptext("\nHit any key to continue > ");
507                                 (void) wait_here();
508                                 put_crlf();
509                         }
510                 }
511                 ptext("Begin meta key test. (km) (smm) (rmm)  Hit any key");
512                 ptext(" with the meta key.  The character will be");
513                 ptext(" displayed in hex.  If the meta key is working");
514                 ptext(" then the most significant bit will be set.  Type");
515                 ptextln(" 'end' to exit.");
516                 tty_raw(1, ALLOW_PARITY);
517                 tc_putp(meta_on);
518
519                 for (i = j = k = len = 0; i != 'e' || j != 'n' || k != 'd';) {
520                         i = j;
521                         j = k;
522                         k = getchp(ALLOW_PARITY);
523                         if (k == EOF) {
524                                 break;
525                         }
526                         if ((len += 3) >= columns) {
527                                 put_crlf();
528                                 len = 3;
529                         }
530                         sprintf(outbuf, "%02X ", k);
531                         put_str(outbuf);
532                         k &= STRIP_PARITY;
533                 }
534                 tc_putp(meta_off);
535                 put_crlf();
536                 tty_set();
537                 put_crlf();
538         } else {
539                 ptext("(km) Has-meta-key is not set.  ");
540         }
541         generic_done_message(t, state, ch);
542 }
543
544 /*
545 **      funkey_label(test_list, status, ch)
546 **
547 **      Test labels (nlab) (smln) (pln) (rmln) (lw) (lh)
548 */
549 static void
550 funkey_label(
551         struct test_list *t,
552         int *state,
553         int *ch)
554 {
555         int i;
556         char outbuf[256];
557
558         if (num_labels == -1) {
559                 ptextln("Your terminal has no labels. (nlab)");
560         } else {
561                 sprintf(temp, "Your terminal has %d labels (nlab) that are %d characters wide (lw) and %d lines high (lh)",
562                         num_labels, label_width, label_height);
563                 ptext(temp);
564                 ptextln(" Testing (smln) (pln) (rmln)");
565                 if (label_on) {
566                         tc_putp(label_on);
567                 }
568                 if (label_width <= 0) {
569                         label_width = sizeof(outbuf) - 1;
570                 }
571                 for (i = 1; i <= num_labels; i++) {
572                         sprintf(outbuf, "L%d..............................", i);
573                         outbuf[label_width] = '\0';
574                         tc_putp(tparm(plab_norm, i, outbuf));
575                 }
576                 if (label_off) {
577                         ptext("Hit any key to remove the labels: ");
578                         (void) wait_here();
579                         tc_putp(label_off);
580                 }
581         }
582         generic_done_message(t, state, ch);
583 }
584
585 /*
586 **      funkey_prog(test_list, status, ch)
587 **
588 **      Test program function keys (pfx)
589 */
590 static void
591 funkey_prog(
592         struct test_list *t,
593         int *state,
594         int *ch)
595 {
596         int i, fk;
597         char mm[256];
598
599         fk = 1; /* use function key 1 for now */
600         if (pkey_xmit) {
601                 /* test program function key */
602                 sprintf(temp,
603                         "(pfx) Set function key %d to transmit abc\\n", fk);
604                 ptextln(temp);
605                 tc_putp(tparm(pkey_xmit, fk, "abc\n"));
606                 sprintf(temp, "Hit function key %d\n", fk);
607                 ptextln(temp);
608                 for (i = 0; i < 4; ++i)
609                         mm[i] = getchp(STRIP_PARITY);
610                 mm[i] = '\0';
611                 put_crlf();
612                 if (mm[0] != 'a' || mm[1] != 'b' || mm[2] != 'c') {
613                         sprintf(temp, "Error string recieved was: %s", expand(mm));
614                         ptextln(temp);
615                 } else {
616                         putln("Thank you\n");
617                 }
618                 flush_input();
619                 if (key_f1) {
620                         tc_putp(tparm(pkey_xmit, fk, key_f1));
621                 }
622         } else {
623                 ptextln("Function key transmit (pfx), not present.");
624         }
625         generic_done_message(t, state, ch);
626 }
627
628 /*
629 **      funkey_local(test_list, status, ch)
630 **
631 **      Test program local function keys (pfloc)
632 */
633 static void
634 funkey_local(
635         struct test_list *t,
636         int *state,
637         int *ch)
638 {
639         int fk;
640
641         fk = 1;
642         if (pkey_local) {
643                 /* test local function key */
644                 sprintf(temp,
645                         "(pfloc) Set function key %d to execute a clear and print \"Done!\"", fk);
646                 ptextln(temp);
647                 sprintf(temp, "%sDone!", liberated(clear_screen));
648                 tc_putp(tparm(pkey_local, fk, temp));
649                 sprintf(temp, "Hit function key %d.  Then hit return.", fk);
650                 ptextln(temp);
651                 (void) wait_here();
652                 flush_input();
653                 if (key_f1 && pkey_xmit) {
654                         tc_putp(tparm(pkey_xmit, fk, key_f1));
655                 }
656         } else {
657                 ptextln("Function key execute local (pfloc), not present.");
658         }
659
660         generic_done_message(t, state, ch);
661 }
662
663 /*
664 **      printer_on(test_list, status, ch)
665 **
666 **      Test printer on/off (mc4) (mc5) (mc5i)
667 */
668 static void
669 printer_on(
670         struct test_list *t,
671         int *state,
672         int *ch)
673 {
674         if (!prtr_on || !prtr_off) {
675                 ptextln("Printer on/off missing. (mc5) (mc4)");
676         } else if (prtr_silent) {
677                 ptextln("Your printer is silent. (mc5i) is set.");
678                 tc_putp(prtr_on);
679                 ptextln("This line should be on the printer but not your screen. (mc5)");
680                 tc_putp(prtr_off);
681                 ptextln("This line should be only on the screen. (mc4)");
682         } else {
683                 ptextln("Your printer is not silent. (mc5i) is reset.");
684                 tc_putp(prtr_on);
685                 ptextln("This line should be on the printer and the screen. (mc5)");
686                 tc_putp(prtr_off);
687                 ptextln("This line should only be on the screen. (mc4)");
688         }
689         generic_done_message(t, state, ch);
690 }
691
692 /*
693 **      printer_mc0(test_list, status, ch)
694 **
695 **      Test screen print (mc0)
696 */
697 static void
698 printer_mc0(
699         struct test_list *t,
700         int *state,
701         int *ch)
702 {
703         if (print_screen) {
704                 ptext("I am going to send the contents of the screen to");
705                 ptext(" the printer, then wait for a keystroke from you.");
706                 ptext("  All of the text that appears on the screen");
707                 ptextln(" should be printed. (mc0)");
708                 tc_putp(print_screen);
709         } else {
710                 ptext("(mc0) Print-screen is not present.  ");
711         }
712         generic_done_message(t, state, ch);
713 }
714
715
716 static void
717 line_pattern(void)
718 {                               /* put up a pattern that will help count the
719                                    number of lines */
720         int i, j;
721
722         put_clear();
723         if (over_strike) {
724                 for (i = 0; i < 100; i++) {
725                         if (i) {
726                                 put_crlf();
727                         }
728                         for (j = i / 10; j; j--) {
729                                 put_this(' ');
730                         }
731                         put_this('0' + ((i + 1) % 10));
732                 }
733         } else  /* I assume it will scroll */ {
734                 for (i = 100; i; i--) {
735                         sprintf(temp, "\r\n%d", i);
736                         put_str(temp);
737                 }
738         }
739 }
740
741
742 static void
743 column_pattern(void)
744 {                               /* put up a pattern that will help count the
745                                    number of columns */
746         int i, j;
747
748         put_clear();
749         for (i = 0; i < 20; i++) {
750                 for (j = 1; j < 10; j++) {
751                         put_this('0' + j);
752                 }
753                 put_this('.');
754         }
755 }
756
757 /*
758 **      report_help()
759 **
760 **      Print the help text for the echo tests
761 */
762 static void
763 report_help(int crx)
764 {
765         ptextln("The following commands may also be entered:");
766         ptextln(" clear   clear screen.");
767         ptextln(" columns print a test patterm to help count screen width.");
768         ptextln(" lines   print a test patterm to help count screen length.");
769         ptextln(" end     exit.");
770         ptextln(" echo    redisplay last report.");
771         if (crx) {
772                 ptextln(" hex     redisplay last report in hex.");
773         } else {
774                 ptextln(" hex     toggle hex display mode.");
775         }
776         ptextln(" help    display this list.");
777         ptextln(" high    toggle forced high bit (0x80).");
778         ptextln(" scan    toggle scan mode.");
779         ptextln(" one     echo one character after <cr> or <lf> as is. (report mode)");
780         ptextln(" two     echo two characters after <cr> or <lf> as is.");
781         ptextln(" all     echo all characters after <cr> or <lf> as is. (echo mode)");
782 }
783
784 /*
785 **      tools_report(testlist, state, ch)
786 **
787 **      Run the echo tool and report tool
788 */
789 void
790 tools_report(
791         struct test_list *t,
792         int *state GCC_UNUSED,
793         int *pch GCC_UNUSED)
794 {
795         int i, j, ch, crp, crx, high_bit, save_scan_mode, hex_display;
796         char buf[1024];
797         char txt[8];
798
799         hex_display = hex_out;
800         put_clear();
801         if ((crx = (t->flags & 255)) == 1) {
802                 ptext("Characters after a CR or LF will be echoed as");
803                 ptextln(" is.  All other characters will be expanded.");
804                 report_help(crx);
805         } else {        /* echo test */
806                 ptextln("Begin echo test.");
807                 report_help(crx);
808         }
809         txt[sizeof(txt) - 1] = '\0';
810         save_scan_mode = scan_mode;
811         tty_raw(1, char_mask);
812         for (i = crp = high_bit = 0;;) {
813                 ch = getchp(char_mask);
814                 if (ch == EOF) {
815                         break;
816                 }
817                 if (i >= (int) sizeof(buf) - 1) {
818                         i = 0;
819                 }
820                 buf[i++] = ch;
821                 buf[i] = '\0';
822                 for (j = 0; j < (int) sizeof(txt) - 1; j++) {
823                         txt[j] = txt[j + 1];
824                 }
825                 txt[sizeof(txt) - 1] = ch & STRIP_PARITY;
826                 if (crx == 0) { /* echo test */
827                         if (hex_display) {
828                                 ptext(hex_expand_to(&buf[i - 1], 3));
829                         } else {
830                                 tc_putch(ch | high_bit);
831                         }
832                 } else /* status report test */
833                 if (ch == '\n' || ch == '\r') {
834                         put_crlf();
835                         crp = 0;
836                 } else if (crp++ < crx) {
837                         tc_putch(ch | high_bit);
838                 } else {
839                         put_str(expand(&buf[i - 1]));
840                 }
841                 if (!strncmp(&txt[sizeof(txt) - 7], "columns", 7)) {
842                         column_pattern();
843                         buf[i = 0] = '\0';
844                         crp = 0;
845                 }
846                 if (!strncmp(&txt[sizeof(txt) - 5], "lines", 5)) {
847                         line_pattern();
848                         buf[i = 0] = '\0';
849                         crp = 0;
850                 }
851                 if (!strncmp(&txt[sizeof(txt) - 5], "clear", 5)) {
852                         put_clear();
853                         buf[i = 0] = '\0';
854                         crp = 0;
855                 }
856                 if (!strncmp(&txt[sizeof(txt) - 4], "high", 4)) {
857                         high_bit ^= 0x80;
858                         if (high_bit) {
859                                 ptextln("\nParity bit set");
860                         } else {
861                                 ptextln("\nParity bit reset");
862                         }
863                 }
864                 if (!strncmp(&txt[sizeof(txt) - 4], "help", 4)) {
865                         put_crlf();
866                         report_help(crx);
867                 }
868                 if (!strncmp(&txt[sizeof(txt) - 4], "echo", 4)) {
869                         /* display the last status report */
870                         /* clear bypass condition on Tek terminals */
871                         put_crlf();
872                         if (i >= 4) {
873                                 buf[i -= 4] = '\0';
874                         }
875                         put_str(expand(buf));
876                 }
877                 if (save_scan_mode &&
878                         !strncmp(&txt[sizeof(txt) - 4], "scan", 4)) {
879                         /* toggle scan mode */
880                         scan_mode = !scan_mode;
881                 }
882                 if (!strncmp(&txt[sizeof(txt) - 3], "end", 3))
883                         break;
884                 if (!strncmp(&txt[sizeof(txt) - 3], "hex", 3)) {
885                         if (crx) {
886                                 /* display the last status report in hex */
887                                 /* clear bypass condition on Tek terminals */
888                                 put_crlf();
889                                 if (i >= 3) {
890                                         buf[i -= 3] = '\0';
891                                 }
892                                 put_str(hex_expand_to(buf, 3));
893                         } else {
894                                 hex_display = !hex_display;
895                         }
896                 }
897                 if (!strncmp(&txt[sizeof(txt) - 3], "two", 3))
898                         crx = 2;
899                 if (!strncmp(&txt[sizeof(txt) - 3], "one", 3))
900                         crx = 1;
901                 if (!strncmp(&txt[sizeof(txt) - 3], "all", 3))
902                         crx = 0;
903         }
904         scan_mode = save_scan_mode;
905         put_crlf();
906         tty_set();
907         if (crx) {
908                 ptextln("End of status report test.");
909         } else {
910                 ptextln("End of echo test.");
911         }
912 }