ncurses 5.9 - patch 20131005
[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.48 2013/05/18 22:05:06 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 #ifdef NCURSES_MOUSE_VERSION
345     mousemask(ALL_MOUSE_EVENTS, (mmask_t *) 0);
346 #endif
347 #if defined(PDCURSES)
348     mouse_set(ALL_MOUSE_EVENTS);
349 #endif
350
351     for (;;) {
352         wmove(win, 3, 5);
353         c = wgetch(win);
354         wclrtobot(win);
355         if (c >= KEY_MIN)
356             wprintw(win, "Key Pressed: %s", keyname(c));
357         else if (isprint(c))
358             wprintw(win, "Key Pressed: %c", c);
359         else
360             wprintw(win, "Key Pressed: %s", unctrl(UChar(c)));
361 #ifdef KEY_MOUSE
362         if (c == KEY_MOUSE) {
363 #if defined(NCURSES_MOUSE_VERSION)
364 #define ButtonChanged(n) ((event.bstate) & NCURSES_MOUSE_MASK(1, 037))
365 #define ButtonPressed(n) ((event.bstate) & NCURSES_MOUSE_MASK(1, NCURSES_BUTTON_PRESSED))
366 #define ButtonDouble(n)  ((event.bstate) & NCURSES_MOUSE_MASK(1, NCURSES_DOUBLE_CLICKED))
367 #define ButtonTriple(n)  ((event.bstate) & NCURSES_MOUSE_MASK(1, NCURSES_TRIPLE_CLICKED))
368 #define ButtonRelease(n) ((event.bstate) & NCURSES_MOUSE_MASK(1, NCURSES_BUTTON_RELEASED))
369             MEVENT event;
370             int button = 0;
371
372             getmouse(&event);
373             if (ButtonChanged(1))
374                 button = 1;
375             else if (ButtonChanged(2))
376                 button = 2;
377             else if (ButtonChanged(3))
378                 button = 3;
379             else
380                 button = 0;
381             wmove(win, 4, 18);
382             wprintw(win, "Button %d: ", button);
383             if (ButtonPressed(button))
384                 wprintw(win, "pressed: ");
385             else if (ButtonDouble(button))
386                 wprintw(win, "double: ");
387             else if (ButtonTriple(button))
388                 wprintw(win, "triple: ");
389             else
390                 wprintw(win, "released: ");
391             wprintw(win, " Position: Y: %d X: %d", event.y, event.x);
392 #elif defined(PDCURSES)
393             int button = 0;
394             request_mouse_pos();
395             if (BUTTON_CHANGED(1))
396                 button = 1;
397             else if (BUTTON_CHANGED(2))
398                 button = 2;
399             else if (BUTTON_CHANGED(3))
400                 button = 3;
401             else
402                 button = 0;
403             wmove(win, 4, 18);
404             wprintw(win, "Button %d: ", button);
405             if (MOUSE_MOVED)
406                 wprintw(win, "moved: ");
407             else if ((BUTTON_STATUS(button) & BUTTON_ACTION_MASK) == BUTTON_PRESSED)
408                 wprintw(win, "pressed: ");
409             else if ((BUTTON_STATUS(button) & BUTTON_ACTION_MASK) == BUTTON_DOUBLE_CLICKED)
410                 wprintw(win, "double: ");
411             else
412                 wprintw(win, "released: ");
413             wprintw(win, " Position: Y: %d X: %d", MOUSE_Y_POS, MOUSE_X_POS);
414 #endif /* NCURSES_VERSION vs PDCURSES */
415         }
416 #endif /* KEY_MOUSE */
417         wrefresh(win);
418         if (c == ' ')
419             break;
420     }
421 #if 0
422     nodelay(win, TRUE);
423     wgetch(win);
424     nodelay(win, FALSE);
425 #endif
426 #if defined(PDCURSES)
427     mouse_set(0L);
428 #endif
429     refresh();
430
431     repeat = 0;
432     do {
433         static const char *fmt[] =
434         {
435             "%d %10s",
436             "%d %[a-zA-Z]s",
437             "%d %[][a-zA-Z]s",
438             "%d %[^0-9]"
439         };
440         const char *format = fmt[(unsigned) repeat % SIZEOF(fmt)];
441
442         wclear(win);
443         MvWAddStr(win, 3, 2, "The window should have moved");
444         MvWAddStr(win, 4, 2,
445                   "This text should have appeared without you pressing a key");
446         MvWPrintw(win, 6, 2,
447                   "Scanning with format \"%s\"", format);
448         mvwin(win, 2 + 2 * (repeat % 4), 1 + 2 * (repeat % 4));
449         erase();
450         refresh();
451         wrefresh(win);
452         echo();
453         noraw();
454         num = 0;
455         *buffer = 0;
456         answered = mvwscanw(win, 7, 6, strdup(format), &num, buffer);
457         MvWPrintw(win, 8, 6,
458                   "String: %s Number: %d (%d values read)",
459                   buffer, num, answered);
460         Continue(win);
461         ++repeat;
462     } while (answered > 0);
463 }
464
465 static void
466 outputTest(WINDOW *win)
467 {
468     WINDOW *win1;
469     char Buffer[80];
470     chtype ch;
471     int by, bx;
472
473 #if !HAVE_TIGETSTR
474 #if HAVE_TGETENT
475     char tc_buffer[4096];
476     char tc_parsed[4096];
477     char *area_pointer = tc_parsed;
478     tgetent(tc_buffer, getenv("TERM"));
479 #else
480 #define tgetstr(a,b) 0
481 #endif
482 #endif /* !HAVE_TIGETSTR */
483
484     nl();
485     wclear(win);
486     MvWAddStr(win, 1, 1,
487               "You should now have a screen in the upper left corner, and this text should have wrapped");
488     mvwin(win, 2, 1);
489     waddstr(win, "\nThis text should be down\n");
490     waddstr(win, "and broken into two here ^");
491     Continue(win);
492
493     wclear(win);
494     wattron(win, A_BOLD);
495     MvWAddStr(win, 1, 1, "A new window will appear with this text in it");
496     MvWAddStr(win, 8, 1, "Press any key to continue");
497     wrefresh(win);
498     wgetch(win);
499
500     getbegyx(win, by, bx);
501
502     if (LINES < 24 || COLS < 75) {
503         MvWAddStr(win, 5, 1,
504                   "Some tests have been skipped as they require a");
505         MvWAddStr(win, 6, 1, "display of at least 24 LINES by 75 COLUMNS");
506         Continue(win);
507     } else {
508         win1 = newwin(10, 50, 14, 25);
509         if (win1 == NULL) {
510             endwin();
511             return;
512         }
513 #ifdef A_COLOR
514         if (has_colors()) {
515             init_pair(3, COLOR_BLUE, COLOR_WHITE);
516             wbkgd(win1, (chtype) COLOR_PAIR(3));
517         } else
518             wbkgd(win1, A_NORMAL);
519 #else
520         wbkgd(win1, A_NORMAL);
521 #endif
522         wclear(win1);
523         MvWAddStr(win1, 5, 1,
524                   "This text should appear; using overlay option");
525         copywin(win, win1, 0, 0, 0, 0, 9, 49, TRUE);
526
527 #if defined(PDCURSES) && !defined(XCURSES)
528         box(win1, 0xb3, 0xc4);
529 #else
530         box(win1, ACS_VLINE, ACS_HLINE);
531 #endif
532         wmove(win1, 8, 26);
533         wrefresh(win1);
534         wgetch(win1);
535
536         wclear(win1);
537         wattron(win1, A_BLINK);
538         MvWAddStr(win1, 4, 1,
539                   "This blinking text should appear in only the second window");
540         wattroff(win1, A_BLINK);
541         mvwin(win1, by, bx);
542         overlay(win, win1);
543         mvwin(win1, 14, 25);
544         wmove(win1, 8, 26);
545         wrefresh(win1);
546         wgetch(win1);
547         delwin(win1);
548     }
549
550     clear();
551     wclear(win);
552     wrefresh(win);
553     MvWAddStr(win, 6, 2, "This line shouldn't appear");
554     MvWAddStr(win, 4, 2, "Only half of the next line is visible");
555     MvWAddStr(win, 5, 2, "Only half of the next line is visible");
556     wmove(win, 6, 1);
557     wclrtobot(win);
558     wmove(win, 5, 20);
559     wclrtoeol(win);
560     MvWAddStr(win, 8, 2, "This line also shouldn't appear");
561     wmove(win, 8, 1);
562     wdeleteln(win);
563     Continue(win);
564
565     wmove(win, 5, 9);
566     ch = winch(win);
567
568     wclear(win);
569     wmove(win, 6, 2);
570     waddstr(win, "The next char should be l:  ");
571     winsch(win, ch);
572     Continue(win);
573
574 #if HAVE_WINSSTR
575     (void) mvwinsstr(win, 6, 2, "A1B2C3D4E5");
576     Continue(win);
577 #endif
578
579     wmove(win, 5, 1);
580     winsertln(win);
581     MvWAddStr(win, 5, 2, "The lines below should have moved down");
582     Continue(win);
583
584     wclear(win);
585     wmove(win, 2, 2);
586     wprintw(win, "This is a formatted string in a window: %d %s\n", 42,
587             "is it");
588     MvWAddStr(win, 10, 1, "Enter a string: ");
589     wrefresh(win);
590     noraw();
591     echo();
592     *Buffer = 0;
593     wscanw(win, "%s", Buffer);
594
595     printw("This is a formatted string in stdscr: %d %s\n", 42, "is it");
596     MvAddStr(10, 1, "Enter a string: ");
597     *Buffer = 0;
598     scanw("%s", Buffer);
599
600     if (TIGETSTR("cvvis", "vs") != 0) {
601         wclear(win);
602         curs_set(2);
603         MvWAddStr(win, 1, 1, "The cursor should appear as a block (visible)");
604         Continue(win);
605     }
606
607     if (TIGETSTR("civis", "vi") != 0) {
608         wclear(win);
609         curs_set(0);
610         MvWAddStr(win, 1, 1,
611                   "The cursor should have disappeared (invisible)");
612         Continue(win);
613     }
614
615     if (TIGETSTR("cnorm", "ve") != 0) {
616         wclear(win);
617         curs_set(1);
618         MvWAddStr(win, 1, 1, "The cursor should be an underline (normal)");
619         Continue(win);
620     }
621 #ifdef A_COLOR
622     if (has_colors()) {
623         wclear(win);
624         MvWAddStr(win, 1, 1, "Colors should change after you press a key");
625         Continue(win);
626         init_pair(1, COLOR_RED, COLOR_WHITE);
627         wrefresh(win);
628     }
629 #endif
630
631     werase(win);
632
633 #if HAVE_TERMNAME
634     MvWAddStr(win, 1, 1, "Information About Your Terminal");
635     MvWAddStr(win, 3, 1, termname());
636     MvWAddStr(win, 4, 1, longname());
637     if (termattrs() & A_BLINK)
638         MvWAddStr(win, 5, 1, "This terminal supports blinking.");
639     else
640         MvWAddStr(win, 5, 1, "This terminal does NOT support blinking.");
641 #endif
642
643     (void) mvwaddnstr(win, 7, 5, "Have a nice day!ok", 16);
644     wrefresh(win);
645
646     (void) mvwinnstr(win, 7, 5, Buffer, 18);
647     MvAddStr(LINES - 2, 10, Buffer);
648     refresh();
649     Continue(win);
650 }
651
652 #if defined(PDCURSES) && !defined(XCURSES)
653 static void
654 resizeTest(WINDOW *dummy GCC_UNUSED)
655 {
656     WINDOW *win1;
657
658     savetty();
659
660     clear();
661     refresh();
662 #  if defined(OS2)
663     resize_term(50, 120);
664 #  else
665     resize_term(50, 80);
666 #  endif
667
668     win1 = newwin(10, 50, 14, 25);
669     if (win1 == NULL) {
670         endwin();
671         return;
672     }
673 #ifdef A_COLOR
674     if (has_colors()) {
675         init_pair(3, COLOR_BLUE, COLOR_WHITE);
676         wattrset(win1, COLOR_PAIR(3));
677     }
678 #endif
679     wclear(win1);
680
681     MvWAddStr(win1, 1, 1, "The screen may now have 50 lines");
682     Continue(win1);
683
684     wclear(win1);
685     resetty();
686
687     MvWAddStr(win1, 1, 1, "The screen should now be reset");
688     Continue(win1);
689
690     delwin(win1);
691
692     clear();
693     refresh();
694
695 }
696 #endif
697
698 static void
699 padTest(WINDOW *dummy GCC_UNUSED)
700 {
701     WINDOW *pad, *spad;
702
703     if ((pad = newpad(50, 100)) != 0) {
704         wattron(pad, A_REVERSE);
705         MvWAddStr(pad, 5, 2, "This is a new pad");
706         (void) wattrset(pad, A_NORMAL);
707         MvWAddStr(pad, 8, 0,
708                   "The end of this line should be truncated here:except  now");
709         MvWAddStr(pad, 11, 1, "This line should not appear.It will now");
710         wmove(pad, 10, 1);
711         wclrtoeol(pad);
712         MvWAddStr(pad, 10, 1, " Press any key to continue");
713         prefresh(pad, 0, 0, 0, 0, 10, 45);
714         keypad(pad, TRUE);
715         raw();
716         wgetch(pad);
717
718         if ((spad = subpad(pad, 12, 25, 6, 52)) != 0) {
719             MvWAddStr(spad, 2, 2, "This is a new subpad");
720             box(spad, 0, 0);
721             delwin(spad);
722         }
723         prefresh(pad, 0, 0, 0, 0, 15, 75);
724         keypad(pad, TRUE);
725         raw();
726         wgetch(pad);
727
728         MvWAddStr(pad, 35, 2, "This is displayed at line 35 in the pad");
729         MvWAddStr(pad, 40, 1, " Press any key to continue");
730         prefresh(pad, 30, 0, 0, 0, 10, 45);
731         keypad(pad, TRUE);
732         raw();
733         wgetch(pad);
734
735         delwin(pad);
736     }
737 }
738
739 static void
740 display_menu(int old_option, int new_option)
741 {
742     int i;
743
744     assert((new_option >= 0) && (new_option < MAX_OPTIONS));
745
746     (void) attrset(A_NORMAL);
747     MvAddStr(3, 20, "PDCurses Test Program");
748
749     for (i = 0; i < (int) MAX_OPTIONS; i++)
750         MvAddStr(5 + i, 25, command[i].text);
751
752     if ((old_option >= 0) && (old_option < MAX_OPTIONS))
753         MvAddStr(5 + old_option, 25, command[old_option].text);
754
755     (void) attrset(A_REVERSE);
756     MvAddStr(5 + new_option, 25, command[new_option].text);
757     (void) attrset(A_NORMAL);
758     MvAddStr(13, 3,
759              "Use Up and Down Arrows to select - Enter to run - Q to quit");
760     refresh();
761 }