• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This is a test program for the PDCurses screen package for IBM PC type
3  * machines.
4  *
5  * This program was written by John Burnell (johnb@kea.am.dsir.govt.nz)
6  *  wrs(5/28/93) -- modified to be consistent (perform identically) with either
7  *                  PDCurses or under Unix System V, R4
8  *
9  * $Id: testcurs.c,v 1.58 2023/05/28 14:23:34 tom Exp $
10  */
11 
12 #include <test.priv.h>
13 
14 #if defined(XCURSES)
15 const char *XCursesProgramName = "testcurs";
16 #endif
17 
18 static int initTest(WINDOW **);
19 static void display_menu(int, int);
20 static void inputTest(WINDOW *);
21 static void introTest(WINDOW *);
22 static void outputTest(WINDOW *);
23 #if HAVE_NEWPAD
24 static void padTest(WINDOW *);
25 #endif
26 static void scrollTest(WINDOW *);
27 #if defined(PDCURSES) && !defined(XCURSES)
28 static void resizeTest(WINDOW *);
29 #endif
30 
31 static int width, height;
32 
33 static void
Continue(WINDOW * win)34 Continue(WINDOW *win)
35 {
36     int y1 = getmaxy(win);
37     int x1 = getmaxx(win);
38     int y0 = y1 < 10 ? y1 : 10;
39     int x0 = 1;
40     chtype save;
41 
42     save = mvwinch(win, y0, x1 - 1);
43 
44     MvWAddStr(win, y0, x0, " Press any key to continue");
45     wclrtoeol(win);
46     getyx(win, y0, x0);
47 
48     MvWAddCh(win, y0, x1 - 1, save);
49 
50     wmove(win, y0, x0);
51     raw();
52     wgetch(win);
53 }
54 
55 static int
initTest(WINDOW ** win)56 initTest(WINDOW **win)
57 {
58 #ifdef PDCDEBUG
59     PDC_debug("initTest called\n");
60 #endif
61 #ifdef TRACE
62     curses_trace(TRACE_MAXIMUM);
63 #endif
64     initscr();
65 #ifdef PDCDEBUG
66     PDC_debug("after initscr()\n");
67 #endif
68 #ifdef A_COLOR
69     if (has_colors())
70 	start_color();
71 #endif
72     width = 60;
73     height = 13;		/* Create a drawing window */
74     *win = newwin(height, width, (LINES - height) / 2, (COLS - width) / 2);
75     if (*win == NULL) {
76 	stop_curses();
77 	return 0;
78     }
79     return 1;
80 }
81 
82 static void
introTest(WINDOW * win)83 introTest(WINDOW *win)
84 {
85     wmove(win, height / 2 - 5, width / 2);
86     wvline(win, ACS_VLINE, 10);
87     wmove(win, height / 2, width / 2 - 10);
88     whline(win, ACS_HLINE, 20);
89     Continue(win);
90 
91     beep();
92     werase(win);
93 
94     box(win, ACS_VLINE, ACS_HLINE);
95     wrefresh(win);
96     cbreak();
97     MvWAddStr(win, 1, 1,
98 	      "You should have rectangle in the middle of the screen");
99     MvWAddStr(win, 2, 1, "You should have heard a beep");
100     Continue(win);
101     return;
102 }
103 
104 static void
scrollTest(WINDOW * win)105 scrollTest(WINDOW *win)
106 {
107     int i;
108     int half;
109     int OldY;
110     NCURSES_CONST char *Message = "The window will now scroll slowly";
111 
112     wclear(win);
113     OldY = getmaxy(win);
114     half = OldY / 2;
115     MvWAddStr(win, OldY - 2, 1, Message);
116     wrefresh(win);
117     scrollok(win, TRUE);
118     for (i = 1; i <= OldY; i++) {
119 	napms(600);
120 	scroll(win);
121 	wrefresh(win);
122     }
123 
124     werase(win);
125     for (i = 1; i < OldY; i++) {
126 	MvWPrintw(win, i, 1, "Line %d", i);
127     }
128     MvWPrintw(win, OldY - 2, 1, "The top of the window will scroll");
129     wmove(win, 1, 1);
130     wsetscrreg(win, 0, half - 1);
131     box(win, ACS_VLINE, ACS_HLINE);
132     wrefresh(win);
133     for (i = 1; i <= half; i++) {
134 	napms(600);
135 	scroll(win);
136 	box(win, ACS_VLINE, ACS_HLINE);
137 	wrefresh(win);
138     }
139 
140     werase(win);
141     for (i = 1; i < OldY; i++) {
142 	MvWPrintw(win, i, 1, "Line %d", i);
143     }
144     MvWPrintw(win, 1, 1, "The bottom of the window will scroll");
145     wmove(win, OldY - 2, 1);
146     wsetscrreg(win, half, --OldY);
147     box(win, ACS_VLINE, ACS_HLINE);
148     wrefresh(win);
149     for (i = half; i <= OldY; i++) {
150 	napms(600);
151 	wscrl(win, -1);
152 	box(win, ACS_VLINE, ACS_HLINE);
153 	wrefresh(win);
154     }
155     wsetscrreg(win, 0, OldY);
156 }
157 
158 static void
inputTest(WINDOW * win)159 inputTest(WINDOW *win)
160 {
161     int answered;
162     int repeat;
163     int w, h, bx, by, sw, sh, i, num;
164     char buffer[80];
165     WINDOW *subWin;
166     wclear(win);
167 
168     getmaxyx(win, h, w);
169     getbegyx(win, by, bx);
170     sw = w / 3;
171     sh = h / 3;
172     if ((subWin = subwin(win, sh, sw, by + h - sh - 2, bx + w - sw - 2)) == NULL)
173 	return;
174 
175 #ifdef A_COLOR
176     if (has_colors()) {
177 	init_pair(2, COLOR_WHITE, COLOR_RED);
178 	wbkgd(subWin, (chtype) COLOR_PAIR(2) | A_BOLD);
179     } else
180 	wbkgd(subWin, A_BOLD);
181 #else
182     wbkgd(subWin, A_BOLD);
183 #endif
184     box(subWin, ACS_VLINE, ACS_HLINE);
185     wrefresh(win);
186 
187     nocbreak();
188     MvWAddStr(win, 2, 1, "Press some keys for 5 seconds");
189     MvWAddStr(win, 1, 1, "Pressing ^C should do nothing");
190     wrefresh(win);
191 
192     werase(subWin);
193     box(subWin, ACS_VLINE, ACS_HLINE);
194     for (i = 0; i < 5; i++) {
195 	MvWPrintw(subWin, 1, 1, "Time = %d", i);
196 	wrefresh(subWin);
197 	napms(1000);
198 	flushinp();
199     }
200 
201     delwin(subWin);
202     werase(win);
203     flash();
204     wrefresh(win);
205     napms(500);
206 
207     MvWAddStr(win, 2, 1, "Press a key, followed by ENTER");
208     wmove(win, 9, 10);
209     wrefresh(win);
210     echo();
211     noraw();
212     wgetch(win);
213     flushinp();
214 
215     wmove(win, 9, 10);
216     wdelch(win);
217     MvWAddStr(win, 4, 1, "The character should now have been deleted");
218     Continue(win);
219 
220     wclear(win);
221     MvWAddStr(win, 1, 1, "Press keys (or mouse buttons) to show their names");
222     MvWAddStr(win, 2, 1, "Press spacebar to finish");
223     wrefresh(win);
224 
225     keypad(win, TRUE);
226     raw();
227     noecho();
228 
229 #if HAVE_TYPEAHEAD
230     typeahead(-1);
231 #endif
232 
233 #ifdef NCURSES_MOUSE_VERSION
234     mousemask(ALL_MOUSE_EVENTS, (mmask_t *) 0);
235 #endif
236 #if defined(PDCURSES)
237     mouse_set(ALL_MOUSE_EVENTS);
238 #endif
239 
240     for (;;) {
241 	int c;
242 
243 	wmove(win, 3, 5);
244 	c = wgetch(win);
245 	wclrtobot(win);
246 	if (c >= KEY_MIN)
247 	    wprintw(win, "Key Pressed: %s", keyname(c));
248 	else if (isprint(c))
249 	    wprintw(win, "Key Pressed: %c", c);
250 	else
251 	    wprintw(win, "Key Pressed: %s", unctrl(UChar(c)));
252 #ifdef KEY_MOUSE
253 	if (c == KEY_MOUSE) {
254 #if defined(NCURSES_MOUSE_VERSION)
255 #define ButtonChanged(n) ((event.bstate) & NCURSES_MOUSE_MASK(n, (NCURSES_BUTTON_RELEASED|NCURSES_BUTTON_PRESSED|NCURSES_BUTTON_CLICKED|NCURSES_DOUBLE_CLICKED|NCURSES_TRIPLE_CLICKED|NCURSES_RESERVED_EVENT)))
256 #define ButtonPressed(n) ((event.bstate) & NCURSES_MOUSE_MASK(n, NCURSES_BUTTON_PRESSED))
257 #define ButtonDouble(n)  ((event.bstate) & NCURSES_MOUSE_MASK(n, NCURSES_DOUBLE_CLICKED))
258 #define ButtonTriple(n)  ((event.bstate) & NCURSES_MOUSE_MASK(n, NCURSES_TRIPLE_CLICKED))
259 #define ButtonRelease(n) ((event.bstate) & NCURSES_MOUSE_MASK(n, NCURSES_BUTTON_RELEASED))
260 	    MEVENT event;
261 	    int button = 0;
262 
263 	    getmouse(&event);
264 	    if (ButtonChanged(1))
265 		button = 1;
266 	    else if (ButtonChanged(2))
267 		button = 2;
268 	    else if (ButtonChanged(3))
269 		button = 3;
270 	    else
271 		button = 0;
272 	    wmove(win, 4, 18);
273 	    wprintw(win, "Button %d: ", button);
274 	    if (ButtonPressed(button))
275 		wprintw(win, "pressed: ");
276 	    else if (ButtonDouble(button))
277 		wprintw(win, "double: ");
278 	    else if (ButtonTriple(button))
279 		wprintw(win, "triple: ");
280 	    else
281 		wprintw(win, "released: ");
282 	    wprintw(win, " Position: Y: %d X: %d", event.y, event.x);
283 #elif defined(PDCURSES)
284 	    int button = 0;
285 	    request_mouse_pos();
286 	    if (BUTTON_CHANGED(1))
287 		button = 1;
288 	    else if (BUTTON_CHANGED(2))
289 		button = 2;
290 	    else if (BUTTON_CHANGED(3))
291 		button = 3;
292 	    else
293 		button = 0;
294 	    wmove(win, 4, 18);
295 	    wprintw(win, "Button %d: ", button);
296 	    if (MOUSE_MOVED)
297 		wprintw(win, "moved: ");
298 	    else if ((BUTTON_STATUS(button) & BUTTON_ACTION_MASK) == BUTTON_PRESSED)
299 		wprintw(win, "pressed: ");
300 	    else if ((BUTTON_STATUS(button) & BUTTON_ACTION_MASK) == BUTTON_DOUBLE_CLICKED)
301 		wprintw(win, "double: ");
302 	    else
303 		wprintw(win, "released: ");
304 	    wprintw(win, " Position: Y: %d X: %d", MOUSE_Y_POS, MOUSE_X_POS);
305 #endif /* NCURSES_VERSION vs PDCURSES */
306 	}
307 #endif /* KEY_MOUSE */
308 	wrefresh(win);
309 	if (c == ' ')
310 	    break;
311     }
312 #if 0
313     nodelay(win, TRUE);
314     wgetch(win);
315     nodelay(win, FALSE);
316 #endif
317 #if defined(PDCURSES)
318     mouse_set(0L);
319 #endif
320     refresh();
321 
322     repeat = 0;
323     do {
324 	static const char *fmt[] =
325 	{
326 	    "%d %10s",
327 	    "%d %[a-zA-Z]s",
328 	    "%d %[][a-zA-Z]s",
329 	    "%d %[^0-9]"
330 	};
331 	char *format = strdup(fmt[(unsigned) repeat % SIZEOF(fmt)]);
332 
333 	wclear(win);
334 	MvWAddStr(win, 3, 2, "The window should have moved");
335 	MvWAddStr(win, 4, 2,
336 		  "This text should have appeared without you pressing a key");
337 	MvWPrintw(win, 6, 2,
338 		  "Scanning with format \"%s\"", format);
339 	mvwin(win, 2 + 2 * (repeat % 4), 1 + 2 * (repeat % 4));
340 	erase();
341 	refresh();
342 	wrefresh(win);
343 	echo();
344 	noraw();
345 	num = 0;
346 	*buffer = 0;
347 	answered = mvwscanw(win, 7, 6, format, &num, buffer);
348 	MvWPrintw(win, 8, 6,
349 		  "String: %s Number: %d (%d values read)",
350 		  buffer, num, answered);
351 	Continue(win);
352 	++repeat;
353 	free(format);
354     } while (answered > 0);
355 }
356 
357 static void
outputTest(WINDOW * win)358 outputTest(WINDOW *win)
359 {
360     char Buffer[80];
361     chtype ch;
362     int by, bx;
363 
364 #if !HAVE_TIGETSTR
365 #if HAVE_TGETENT
366     char tc_buffer[4096];
367     char tc_parsed[4096];
368     char *area_pointer = tc_parsed;
369     tgetent(tc_buffer, getenv("TERM"));
370 #else
371 #define tgetstr(a,b) 0
372 #endif
373 #endif /* !HAVE_TIGETSTR */
374 
375     nl();
376     wclear(win);
377     MvWAddStr(win, 1, 1,
378 	      "You should now have a screen in the upper left corner, and this text should have wrapped");
379     mvwin(win, 2, 1);
380     waddstr(win, "\nThis text should be down\n");
381     waddstr(win, "and broken into two here ^");
382     Continue(win);
383 
384     wclear(win);
385     wattron(win, A_BOLD);
386     MvWAddStr(win, 1, 1, "A new window will appear with this text in it");
387     MvWAddStr(win, 8, 1, "Press any key to continue");
388     wrefresh(win);
389     wgetch(win);
390 
391     getbegyx(win, by, bx);
392 
393     if (LINES < 24 || COLS < 75) {
394 	MvWAddStr(win, 5, 1,
395 		  "Some tests have been skipped as they require a");
396 	MvWAddStr(win, 6, 1, "display of at least 24 LINES by 75 COLUMNS");
397 	Continue(win);
398     } else {
399 	WINDOW *win1 = newwin(10, 50, 14, 25);
400 	if (win1 == NULL) {
401 	    endwin();
402 	    return;
403 	}
404 #ifdef A_COLOR
405 	if (has_colors()) {
406 	    init_pair(3, COLOR_BLUE, COLOR_WHITE);
407 	    wbkgd(win1, (chtype) COLOR_PAIR(3));
408 	} else
409 	    wbkgd(win1, A_NORMAL);
410 #else
411 	wbkgd(win1, A_NORMAL);
412 #endif
413 	wclear(win1);
414 	MvWAddStr(win1, 5, 1,
415 		  "This text should appear; using overlay option");
416 	copywin(win, win1, 0, 0, 0, 0, 9, 49, TRUE);
417 
418 #if defined(PDCURSES) && !defined(XCURSES)
419 	box(win1, 0xb3, 0xc4);
420 #else
421 	box(win1, ACS_VLINE, ACS_HLINE);
422 #endif
423 	wmove(win1, 8, 26);
424 	wrefresh(win1);
425 	wgetch(win1);
426 
427 	wclear(win1);
428 	wattron(win1, A_BLINK);
429 	MvWAddStr(win1, 4, 1,
430 		  "This blinking text should appear in only the second window");
431 	wattroff(win1, A_BLINK);
432 	mvwin(win1, by, bx);
433 	overlay(win, win1);
434 	mvwin(win1, 14, 25);
435 	wmove(win1, 8, 26);
436 	wrefresh(win1);
437 	wgetch(win1);
438 	delwin(win1);
439     }
440 
441     clear();
442     wclear(win);
443     wrefresh(win);
444     MvWAddStr(win, 6, 2, "This line shouldn't appear");
445     MvWAddStr(win, 4, 2, "Only half of the next line is visible");
446     MvWAddStr(win, 5, 2, "Only half of the next line is visible");
447     wmove(win, 6, 1);
448     wclrtobot(win);
449     wmove(win, 5, 20);
450     wclrtoeol(win);
451     MvWAddStr(win, 8, 2, "This line also shouldn't appear");
452     wmove(win, 8, 1);
453     wdeleteln(win);
454     Continue(win);
455 
456     wmove(win, 5, 9);
457     ch = winch(win);
458 
459     wclear(win);
460     wmove(win, 6, 2);
461     waddstr(win, "The next char should be l:  ");
462     winsch(win, ch);
463     Continue(win);
464 
465 #if HAVE_WINSSTR
466     (void) mvwinsstr(win, 6, 2, "A1B2C3D4E5");
467     Continue(win);
468 #endif
469 
470     wmove(win, 5, 1);
471     winsertln(win);
472     MvWAddStr(win, 5, 2, "The lines below should have moved down");
473     Continue(win);
474 
475     wclear(win);
476     wmove(win, 2, 2);
477     wprintw(win, "This is a formatted string in a window: %d %s\n", 42,
478 	    "is it");
479     MvWAddStr(win, 10, 1, "Enter a string: ");
480     wrefresh(win);
481     noraw();
482     echo();
483     *Buffer = 0;
484     wscanw(win, "%s", Buffer);
485 
486     printw("This is a formatted string in stdscr: %d %s\n", 42, "is it");
487     MvAddStr(10, 1, "Enter a string: ");
488     *Buffer = 0;
489     scanw("%s", Buffer);
490 
491     if (TIGETSTR("cvvis", "vs") != 0) {
492 	wclear(win);
493 	curs_set(2);
494 	MvWAddStr(win, 1, 1, "The cursor should appear as a block (visible)");
495 	Continue(win);
496     }
497 
498     if (TIGETSTR("civis", "vi") != 0) {
499 	wclear(win);
500 	curs_set(0);
501 	MvWAddStr(win, 1, 1,
502 		  "The cursor should have disappeared (invisible)");
503 	Continue(win);
504     }
505 
506     if (TIGETSTR("cnorm", "ve") != 0) {
507 	wclear(win);
508 	curs_set(1);
509 	MvWAddStr(win, 1, 1, "The cursor should be an underline (normal)");
510 	Continue(win);
511     }
512 #ifdef A_COLOR
513     if (has_colors()) {
514 	wclear(win);
515 	MvWAddStr(win, 1, 1, "Colors should change after you press a key");
516 	Continue(win);
517 	init_pair(1, COLOR_RED, COLOR_WHITE);
518 	wrefresh(win);
519     }
520 #endif
521 
522     werase(win);
523 
524 #if HAVE_TERMNAME
525     MvWAddStr(win, 1, 1, "Information About Your Terminal");
526     MvWAddStr(win, 3, 1, termname());
527     MvWAddStr(win, 4, 1, longname());
528     if (termattrs() & A_BLINK)
529 	MvWAddStr(win, 5, 1, "This terminal supports blinking.");
530     else
531 	MvWAddStr(win, 5, 1, "This terminal does NOT support blinking.");
532 #endif
533 
534     (void) mvwaddnstr(win, 7, 5, "Have a nice day!ok", 16);
535     wrefresh(win);
536 
537     (void) mvwinnstr(win, 7, 5, Buffer, 18);
538     MvAddStr(LINES - 2, 10, Buffer);
539     refresh();
540     Continue(win);
541 }
542 
543 #if defined(PDCURSES) && !defined(XCURSES)
544 static void
resizeTest(WINDOW * dummy GCC_UNUSED)545 resizeTest(WINDOW *dummy GCC_UNUSED)
546 {
547     WINDOW *win1;
548 
549     savetty();
550 
551     clear();
552     refresh();
553 #  if defined(OS2)
554     resize_term(50, 120);
555 #  else
556     resize_term(50, 80);
557 #  endif
558 
559     win1 = newwin(10, 50, 14, 25);
560     if (win1 == NULL) {
561 	stop_curses();
562 	return;
563     }
564 #ifdef A_COLOR
565     if (has_colors()) {
566 	init_pair(3, COLOR_BLUE, COLOR_WHITE);
567 	wattrset(win1, COLOR_PAIR(3));
568     }
569 #endif
570     wclear(win1);
571 
572     MvWAddStr(win1, 1, 1, "The screen may now have 50 lines");
573     Continue(win1);
574 
575     wclear(win1);
576     resetty();
577 
578     MvWAddStr(win1, 1, 1, "The screen should now be reset");
579     Continue(win1);
580 
581     delwin(win1);
582 
583     clear();
584     refresh();
585 
586 }
587 #endif
588 
589 #if HAVE_NEWPAD
590 static void
padTest(WINDOW * dummy GCC_UNUSED)591 padTest(WINDOW *dummy GCC_UNUSED)
592 {
593     WINDOW *pad;
594 
595     if ((pad = newpad(50, 100)) != 0) {
596 	WINDOW *spad;
597 
598 	wattron(pad, A_REVERSE);
599 	MvWAddStr(pad, 5, 2, "This is a new pad");
600 	(void) wattrset(pad, A_NORMAL);
601 	MvWAddStr(pad, 8, 0,
602 		  "The end of this line should be truncated here:except  now");
603 	MvWAddStr(pad, 11, 1, "This line should not appear.It will now");
604 	wmove(pad, 10, 1);
605 	wclrtoeol(pad);
606 	MvWAddStr(pad, 10, 1, " Press any key to continue");
607 	prefresh(pad, 0, 0, 0, 0, 10, 45);
608 	keypad(pad, TRUE);
609 	raw();
610 	wgetch(pad);
611 
612 	if ((spad = subpad(pad, 12, 25, 6, 52)) != 0) {
613 	    MvWAddStr(spad, 2, 2, "This is a new subpad");
614 	    box(spad, 0, 0);
615 	    delwin(spad);
616 	}
617 	prefresh(pad, 0, 0, 0, 0, 15, 75);
618 	keypad(pad, TRUE);
619 	raw();
620 	wgetch(pad);
621 
622 	MvWAddStr(pad, 35, 2, "This is displayed at line 35 in the pad");
623 	MvWAddStr(pad, 40, 1, " Press any key to continue");
624 	prefresh(pad, 30, 0, 0, 0, 10, 45);
625 	keypad(pad, TRUE);
626 	raw();
627 	wgetch(pad);
628 
629 	delwin(pad);
630     }
631 }
632 #endif /* HAVE_NEWPAD */
633 
634 struct commands {
635     NCURSES_CONST char *text;
636     void (*function) (WINDOW *);
637 };
638 typedef struct commands COMMAND;
639 
640 static const COMMAND command[] =
641 {
642     {"General Test", introTest},
643 #if HAVE_NEWPAD
644     {"Pad Test", padTest},
645 #endif
646 #if defined(PDCURSES) && !defined(XCURSES)
647     {"Resize Test", resizeTest},
648 #endif
649     {"Scroll Test", scrollTest},
650     {"Input Test", inputTest},
651     {"Output Test", outputTest}
652 };
653 #define MAX_OPTIONS (int) SIZEOF(command)
654 
655 static void
display_menu(int old_option,int new_option)656 display_menu(int old_option, int new_option)
657 {
658     int i;
659 
660     assert((new_option >= 0) && (new_option < MAX_OPTIONS));
661 
662     (void) attrset(A_NORMAL);
663     MvAddStr(3, 20, "PDCurses Test Program");
664 
665     for (i = 0; i < (int) MAX_OPTIONS; i++)
666 	MvAddStr(5 + i, 25, command[i].text);
667 
668     if ((old_option >= 0) && (old_option < MAX_OPTIONS))
669 	MvAddStr(5 + old_option, 25, command[old_option].text);
670 
671     (void) attrset(A_REVERSE);
672     MvAddStr(5 + new_option, 25, command[new_option].text);
673     (void) attrset(A_NORMAL);
674     MvAddStr(13, 3,
675 	     "Use Up and Down Arrows to select - Enter to run - Q to quit");
676     refresh();
677 }
678 
679 static void
usage(int ok)680 usage(int ok)
681 {
682     static const char *msg[] =
683     {
684 	"Usage: testcurs [options]"
685 	,""
686 	,USAGE_COMMON
687     };
688     size_t n;
689 
690     for (n = 0; n < SIZEOF(msg); n++)
691 	fprintf(stderr, "%s\n", msg[n]);
692 
693     ExitProgram(ok ? EXIT_SUCCESS : EXIT_FAILURE);
694 }
695 /* *INDENT-OFF* */
VERSION_COMMON()696 VERSION_COMMON()
697 /* *INDENT-ON* */
698 
699 int
700 main(int argc, char *argv[])
701 {
702     WINDOW *win;
703     int old_option = (-1);
704     int new_option = 0;
705     bool quit = FALSE;
706     int n;
707     int ch;
708 
709     while ((ch = getopt(argc, argv, OPTS_COMMON)) != -1) {
710 	switch (ch) {
711 	case OPTS_VERSION:
712 	    show_version(argv);
713 	    ExitProgram(EXIT_SUCCESS);
714 	default:
715 	    usage(ch == OPTS_USAGE);
716 	    /* NOTREACHED */
717 	}
718     }
719     if (optind < argc)
720 	usage(FALSE);
721 
722     setlocale(LC_ALL, "");
723 
724 #ifdef PDCDEBUG
725     PDC_debug("testcurs started\n");
726 #endif
727     if (!initTest(&win))
728 	ExitProgram(EXIT_FAILURE);
729 
730     erase();
731     display_menu(old_option, new_option);
732 
733     for (;;) {
734 	int key;
735 
736 #ifdef A_COLOR
737 	if (has_colors()) {
738 	    init_pair(1, COLOR_WHITE, COLOR_BLUE);
739 	    wbkgd(win, (chtype) COLOR_PAIR(1));
740 	} else
741 	    wbkgd(win, A_REVERSE);
742 #else
743 	wbkgd(win, A_REVERSE);
744 #endif
745 	werase(win);
746 
747 	noecho();
748 	keypad(stdscr, TRUE);
749 	raw();
750 	key = getch();
751 	if (key < KEY_MIN && key > 0 && isalpha(key)) {
752 	    if (islower(key))
753 		key = toupper(key);
754 	    for (n = 0; n < MAX_OPTIONS; ++n) {
755 		if (key == command[n].text[0]) {
756 		    display_menu(old_option, new_option = n);
757 		    key = ' ';
758 		    break;
759 		}
760 	    }
761 	}
762 	switch (key) {
763 	case 10:
764 	case 13:
765 	case KEY_ENTER:
766 	    erase();
767 	    refresh();
768 	    (*command[new_option].function) (win);
769 	    erase();
770 	    display_menu(old_option, new_option);
771 	    break;
772 	case KEY_UP:
773 	    new_option = ((new_option == 0)
774 			  ? new_option
775 			  : new_option - 1);
776 	    display_menu(old_option, new_option);
777 	    break;
778 	case KEY_DOWN:
779 	    new_option = ((new_option == (MAX_OPTIONS - 1))
780 			  ? new_option
781 			  : new_option + 1);
782 	    display_menu(old_option, new_option);
783 	    break;
784 	case 'Q':
785 	case 'q':
786 	    quit = TRUE;
787 	    break;
788 	default:
789 	    beep();
790 	    break;
791 	case ' ':
792 	    break;
793 	}
794 	if (quit == TRUE)
795 	    break;
796     }
797 
798     delwin(win);
799 
800     stop_curses();
801 #ifdef XCURSES
802     XCursesExit();
803 #endif
804     ExitProgram(EXIT_SUCCESS);
805 }
806