ncurses 6.0 - patch 20150822
[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.50 2015/07/05 00:11:10 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, (chtype) 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         char *format = strdup(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, 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         free(format);
463     } while (answered > 0);
464 }
465
466 static void
467 outputTest(WINDOW *win)
468 {
469     WINDOW *win1;
470     char Buffer[80];
471     chtype ch;
472     int by, bx;
473
474 #if !HAVE_TIGETSTR
475 #if HAVE_TGETENT
476     char tc_buffer[4096];
477     char tc_parsed[4096];
478     char *area_pointer = tc_parsed;
479     tgetent(tc_buffer, getenv("TERM"));
480 #else
481 #define tgetstr(a,b) 0
482 #endif
483 #endif /* !HAVE_TIGETSTR */
484
485     nl();
486     wclear(win);
487     MvWAddStr(win, 1, 1,
488               "You should now have a screen in the upper left corner, and this text should have wrapped");
489     mvwin(win, 2, 1);
490     waddstr(win, "\nThis text should be down\n");
491     waddstr(win, "and broken into two here ^");
492     Continue(win);
493
494     wclear(win);
495     wattron(win, A_BOLD);
496     MvWAddStr(win, 1, 1, "A new window will appear with this text in it");
497     MvWAddStr(win, 8, 1, "Press any key to continue");
498     wrefresh(win);
499     wgetch(win);
500
501     getbegyx(win, by, bx);
502
503     if (LINES < 24 || COLS < 75) {
504         MvWAddStr(win, 5, 1,
505                   "Some tests have been skipped as they require a");
506         MvWAddStr(win, 6, 1, "display of at least 24 LINES by 75 COLUMNS");
507         Continue(win);
508     } else {
509         win1 = newwin(10, 50, 14, 25);
510         if (win1 == NULL) {
511             endwin();
512             return;
513         }
514 #ifdef A_COLOR
515         if (has_colors()) {
516             init_pair(3, COLOR_BLUE, COLOR_WHITE);
517             wbkgd(win1, (chtype) COLOR_PAIR(3));
518         } else
519             wbkgd(win1, A_NORMAL);
520 #else
521         wbkgd(win1, A_NORMAL);
522 #endif
523         wclear(win1);
524         MvWAddStr(win1, 5, 1,
525                   "This text should appear; using overlay option");
526         copywin(win, win1, 0, 0, 0, 0, 9, 49, TRUE);
527
528 #if defined(PDCURSES) && !defined(XCURSES)
529         box(win1, 0xb3, 0xc4);
530 #else
531         box(win1, ACS_VLINE, ACS_HLINE);
532 #endif
533         wmove(win1, 8, 26);
534         wrefresh(win1);
535         wgetch(win1);
536
537         wclear(win1);
538         wattron(win1, A_BLINK);
539         MvWAddStr(win1, 4, 1,
540                   "This blinking text should appear in only the second window");
541         wattroff(win1, A_BLINK);
542         mvwin(win1, by, bx);
543         overlay(win, win1);
544         mvwin(win1, 14, 25);
545         wmove(win1, 8, 26);
546         wrefresh(win1);
547         wgetch(win1);
548         delwin(win1);
549     }
550
551     clear();
552     wclear(win);
553     wrefresh(win);
554     MvWAddStr(win, 6, 2, "This line shouldn't appear");
555     MvWAddStr(win, 4, 2, "Only half of the next line is visible");
556     MvWAddStr(win, 5, 2, "Only half of the next line is visible");
557     wmove(win, 6, 1);
558     wclrtobot(win);
559     wmove(win, 5, 20);
560     wclrtoeol(win);
561     MvWAddStr(win, 8, 2, "This line also shouldn't appear");
562     wmove(win, 8, 1);
563     wdeleteln(win);
564     Continue(win);
565
566     wmove(win, 5, 9);
567     ch = winch(win);
568
569     wclear(win);
570     wmove(win, 6, 2);
571     waddstr(win, "The next char should be l:  ");
572     winsch(win, ch);
573     Continue(win);
574
575 #if HAVE_WINSSTR
576     (void) mvwinsstr(win, 6, 2, "A1B2C3D4E5");
577     Continue(win);
578 #endif
579
580     wmove(win, 5, 1);
581     winsertln(win);
582     MvWAddStr(win, 5, 2, "The lines below should have moved down");
583     Continue(win);
584
585     wclear(win);
586     wmove(win, 2, 2);
587     wprintw(win, "This is a formatted string in a window: %d %s\n", 42,
588             "is it");
589     MvWAddStr(win, 10, 1, "Enter a string: ");
590     wrefresh(win);
591     noraw();
592     echo();
593     *Buffer = 0;
594     wscanw(win, "%s", Buffer);
595
596     printw("This is a formatted string in stdscr: %d %s\n", 42, "is it");
597     MvAddStr(10, 1, "Enter a string: ");
598     *Buffer = 0;
599     scanw("%s", Buffer);
600
601     if (TIGETSTR("cvvis", "vs") != 0) {
602         wclear(win);
603         curs_set(2);
604         MvWAddStr(win, 1, 1, "The cursor should appear as a block (visible)");
605         Continue(win);
606     }
607
608     if (TIGETSTR("civis", "vi") != 0) {
609         wclear(win);
610         curs_set(0);
611         MvWAddStr(win, 1, 1,
612                   "The cursor should have disappeared (invisible)");
613         Continue(win);
614     }
615
616     if (TIGETSTR("cnorm", "ve") != 0) {
617         wclear(win);
618         curs_set(1);
619         MvWAddStr(win, 1, 1, "The cursor should be an underline (normal)");
620         Continue(win);
621     }
622 #ifdef A_COLOR
623     if (has_colors()) {
624         wclear(win);
625         MvWAddStr(win, 1, 1, "Colors should change after you press a key");
626         Continue(win);
627         init_pair(1, COLOR_RED, COLOR_WHITE);
628         wrefresh(win);
629     }
630 #endif
631
632     werase(win);
633
634 #if HAVE_TERMNAME
635     MvWAddStr(win, 1, 1, "Information About Your Terminal");
636     MvWAddStr(win, 3, 1, termname());
637     MvWAddStr(win, 4, 1, longname());
638     if (termattrs() & A_BLINK)
639         MvWAddStr(win, 5, 1, "This terminal supports blinking.");
640     else
641         MvWAddStr(win, 5, 1, "This terminal does NOT support blinking.");
642 #endif
643
644     (void) mvwaddnstr(win, 7, 5, "Have a nice day!ok", 16);
645     wrefresh(win);
646
647     (void) mvwinnstr(win, 7, 5, Buffer, 18);
648     MvAddStr(LINES - 2, 10, Buffer);
649     refresh();
650     Continue(win);
651 }
652
653 #if defined(PDCURSES) && !defined(XCURSES)
654 static void
655 resizeTest(WINDOW *dummy GCC_UNUSED)
656 {
657     WINDOW *win1;
658
659     savetty();
660
661     clear();
662     refresh();
663 #  if defined(OS2)
664     resize_term(50, 120);
665 #  else
666     resize_term(50, 80);
667 #  endif
668
669     win1 = newwin(10, 50, 14, 25);
670     if (win1 == NULL) {
671         endwin();
672         return;
673     }
674 #ifdef A_COLOR
675     if (has_colors()) {
676         init_pair(3, COLOR_BLUE, COLOR_WHITE);
677         wattrset(win1, COLOR_PAIR(3));
678     }
679 #endif
680     wclear(win1);
681
682     MvWAddStr(win1, 1, 1, "The screen may now have 50 lines");
683     Continue(win1);
684
685     wclear(win1);
686     resetty();
687
688     MvWAddStr(win1, 1, 1, "The screen should now be reset");
689     Continue(win1);
690
691     delwin(win1);
692
693     clear();
694     refresh();
695
696 }
697 #endif
698
699 static void
700 padTest(WINDOW *dummy GCC_UNUSED)
701 {
702     WINDOW *pad, *spad;
703
704     if ((pad = newpad(50, 100)) != 0) {
705         wattron(pad, A_REVERSE);
706         MvWAddStr(pad, 5, 2, "This is a new pad");
707         (void) wattrset(pad, A_NORMAL);
708         MvWAddStr(pad, 8, 0,
709                   "The end of this line should be truncated here:except  now");
710         MvWAddStr(pad, 11, 1, "This line should not appear.It will now");
711         wmove(pad, 10, 1);
712         wclrtoeol(pad);
713         MvWAddStr(pad, 10, 1, " Press any key to continue");
714         prefresh(pad, 0, 0, 0, 0, 10, 45);
715         keypad(pad, TRUE);
716         raw();
717         wgetch(pad);
718
719         if ((spad = subpad(pad, 12, 25, 6, 52)) != 0) {
720             MvWAddStr(spad, 2, 2, "This is a new subpad");
721             box(spad, 0, 0);
722             delwin(spad);
723         }
724         prefresh(pad, 0, 0, 0, 0, 15, 75);
725         keypad(pad, TRUE);
726         raw();
727         wgetch(pad);
728
729         MvWAddStr(pad, 35, 2, "This is displayed at line 35 in the pad");
730         MvWAddStr(pad, 40, 1, " Press any key to continue");
731         prefresh(pad, 30, 0, 0, 0, 10, 45);
732         keypad(pad, TRUE);
733         raw();
734         wgetch(pad);
735
736         delwin(pad);
737     }
738 }
739
740 static void
741 display_menu(int old_option, int new_option)
742 {
743     int i;
744
745     assert((new_option >= 0) && (new_option < MAX_OPTIONS));
746
747     (void) attrset(A_NORMAL);
748     MvAddStr(3, 20, "PDCurses Test Program");
749
750     for (i = 0; i < (int) MAX_OPTIONS; i++)
751         MvAddStr(5 + i, 25, command[i].text);
752
753     if ((old_option >= 0) && (old_option < MAX_OPTIONS))
754         MvAddStr(5 + old_option, 25, command[old_option].text);
755
756     (void) attrset(A_REVERSE);
757     MvAddStr(5 + new_option, 25, command[new_option].text);
758     (void) attrset(A_NORMAL);
759     MvAddStr(13, 3,
760              "Use Up and Down Arrows to select - Enter to run - Q to quit");
761     refresh();
762 }