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