]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libncurses/TESTS/ncurses.c
Make bdev userland access work like cdev userland access unless
[FreeBSD/FreeBSD.git] / lib / libncurses / TESTS / ncurses.c
1 /****************************************************************************
2
3 NAME
4    ncurses.c --- ncurses library exerciser
5
6 SYNOPSIS
7    ncurses
8
9 DESCRIPTION
10    An interactive test module for the ncurses library.
11
12 AUTHOR
13    This software is Copyright (C) 1993 by Eric S. Raymond, all rights reserved.
14 It is issued with ncurses under the same terms and conditions as the ncurses
15 library source.
16
17 ***************************************************************************/
18 /*LINTLIBRARY */
19 #include <stdio.h>
20 #include <ctype.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <assert.h>
25 #include <ncurses.h>
26
27 #define P(s)            printw("%s\n", s)
28 #ifndef CTRL
29 #define CTRL(x)         ((x) & 0x1f)
30 #endif
31
32 /****************************************************************************
33  *
34  * Character input test
35  *
36  ****************************************************************************/
37
38 static void getch_test(void)
39 /* test the keypad feature */
40 {
41 char buf[BUFSIZ];
42 unsigned int c;
43 int incount = 0, firsttime = 0;
44 bool blocking = TRUE;
45
46       refresh();
47
48      (void) printw("Delay in 10ths of a second (<CR> for blocking input)? ");
49      echo();
50      getstr(buf);
51      noecho();
52
53      if (isdigit(buf[0]))
54      {
55         timeout(atoi(buf) * 100);
56         blocking = FALSE;
57      }
58
59       c = '?';
60      for (;;)
61      {
62         if (firsttime++)
63         {
64             printw("Key pressed: %04o ", c);
65             if (c >= KEY_MIN)
66             {
67                 (void) addstr(keyname(c));
68                 addch('\n');
69             }
70             else if (c > 0x80)
71             {
72                 if (isprint(c & ~0x80))
73                     (void) printw("M-%c", c);
74                 else
75                     (void) printw("M-%s", unctrl(c));
76                 addstr(" (high-half character)\n");
77             }
78             else
79             {
80                 if (isprint(c))
81                     (void) printw("%c (ASCII printable character)\n", c);
82                 else
83                     (void) printw("%s (ASCII control character)\n", unctrl(c));
84             }
85         }
86         if (c == 'x' || c == 'q')
87             break;
88         if (c == '?')
89             addstr("Type any key to see its keypad value, `q' to quit, `?' for help.\n");
90
91         while ((c = getch()) == ERR)
92             if (!blocking)
93                 (void) printw("%05d: input timed out\n", incount++);
94     }
95
96     timeout(-1);
97     erase();
98     endwin();
99 }
100
101 static void attr_test(void)
102 /* test text attributes */
103 {
104     refresh();
105
106     mvaddstr(0, 20, "Character attribute test display");
107
108     mvaddstr(2,8,"This is STANDOUT mode: ");
109     attron(A_STANDOUT);
110     addstr("abcde fghij klmno pqrst uvwxy x");
111     attroff(A_STANDOUT);
112
113     mvaddstr(4,8,"This is REVERSE mode: ");
114     attron(A_REVERSE);
115     addstr("abcde fghij klmno pqrst uvwxy x");
116     attroff(A_REVERSE);
117
118     mvaddstr(6,8,"This is BOLD mode: ");
119     attron(A_BOLD);
120     addstr("abcde fghij klmno pqrst uvwxy x");
121     attroff(A_BOLD);
122
123     mvaddstr(8,8,"This is UNDERLINE mode: ");
124     attron(A_UNDERLINE);
125     addstr("abcde fghij klmno pqrst uvwxy x");
126     attroff(A_UNDERLINE);
127
128     mvaddstr(10,8,"This is DIM mode: ");
129     attron(A_DIM);
130     addstr("abcde fghij klmno pqrst uvwxy x");
131     attroff(A_DIM);
132
133     mvaddstr(12,8,"This is BLINK mode: ");
134     attron(A_BLINK);
135     addstr("abcde fghij klmno pqrst uvwxy x");
136     attroff(A_BLINK);
137
138     mvaddstr(14,8,"This is BOLD UNDERLINE BLINK mode: ");
139     attron(A_BOLD|A_BLINK|A_UNDERLINE);
140     addstr("abcde fghij klmno pqrst uvwxy x");
141     attroff(A_BOLD|A_BLINK|A_UNDERLINE);
142
143     attrset(A_NORMAL);
144     mvaddstr(16,8,"This is NORMAL mode: ");
145     addstr("abcde fghij klmno pqrst uvwxy x");
146
147     refresh();
148
149     move(LINES - 1, 0);
150     addstr("Press any key to continue... ");
151     (void) getch();
152
153     erase();
154     endwin();
155 }
156
157 /****************************************************************************
158  *
159  * Color support tests
160  *
161  ****************************************************************************/
162
163 static char     *colors[] =
164 {
165     "black",
166     "red",
167     "green",
168     "yellow",
169     "blue",
170     "magenta",
171     "cyan",
172     "white"
173 };
174
175 static void color_test(void)
176 /* generate a color test pattern */
177 {
178     int i;
179
180     refresh();
181     (void) printw("There are %d color pairs\n", COLOR_PAIRS);
182
183     (void) mvprintw(1, 0,
184          "%dx%d matrix of foreground/background colors, bright *off*\n",
185          COLORS, COLORS);
186     for (i = 0; i < COLORS; i++)
187         mvaddstr(2, (i+1) * 8, colors[i]);
188     for (i = 0; i < COLORS; i++)
189         mvaddstr(3 + i, 0, colors[i]);
190     for (i = 1; i < COLOR_PAIRS; i++)
191     {
192         init_pair(i, i % COLORS, i / COLORS);
193         attron(COLOR_PAIR(i));
194         mvaddstr(3 + (i / COLORS), (i % COLORS + 1) * 8, "Hello");
195         attrset(A_NORMAL);
196     }
197
198     (void) mvprintw(COLORS + 4, 0,
199            "%dx%d matrix of foreground/background colors, bright *on*\n",
200            COLORS, COLORS);
201     for (i = 0; i < COLORS; i++)
202         mvaddstr(5 + COLORS, (i+1) * 8, colors[i]);
203     for (i = 0; i < COLORS; i++)
204         mvaddstr(6 + COLORS + i, 0, colors[i]);
205     for (i = 1; i < COLOR_PAIRS; i++)
206     {
207         init_pair(i, i % COLORS, i / COLORS);
208         attron(COLOR_PAIR(i) | A_BOLD);
209         mvaddstr(6 + COLORS + (i / COLORS), (i % COLORS + 1) * 8, "Hello");
210         attrset(A_NORMAL);
211     }
212
213     move(LINES - 1, 0);
214     addstr("Press any key to continue... ");
215     (void) getch();
216
217     erase();
218     endwin();
219 }
220
221 static void color_edit(void)
222 /* display the color test pattern, without trying to edit colors */
223 {
224     int i, c, value = 0, current = 0, field = 0, usebase = 0;
225
226     refresh();
227
228     for (i = 0; i < COLORS; i++)
229         init_pair(i, COLOR_WHITE, i);
230
231     do {
232         short   red, green, blue;
233
234         attron(A_BOLD);
235         mvaddstr(0, 20, "Color RGB Value Editing");
236         attroff(A_BOLD);
237
238         for (i = 0; i < COLORS; i++)
239         {
240             mvprintw(2 + i, 0, "%c %-8s:",
241                      (i == current ? '>' : ' '),
242                      (i < sizeof(colors)/sizeof(colors[0]) ? colors[i] : ""));
243             attrset(COLOR_PAIR(i));
244             addstr("        ");
245             attrset(A_NORMAL);
246
247             /*
248              * Note: this refresh should *not* be necessary!  It works around
249              * a bug in attribute handling that apparently causes the A_NORMAL
250              * attribute sets to interfere with the actual emission of the
251              * color setting somehow.  This needs to be fixed.
252              */
253             refresh();
254
255             color_content(i, &red, &green, &blue);
256             addstr("   R = ");
257             if (current == i && field == 0) attron(A_STANDOUT);
258             printw("%04d", red);
259             if (current == i && field == 0) attrset(A_NORMAL);
260             addstr(", G = ");
261             if (current == i && field == 1) attron(A_STANDOUT);
262             printw("%04d", green);
263             if (current == i && field == 1) attrset(A_NORMAL);
264             addstr(", B = ");
265             if (current == i && field == 2) attron(A_STANDOUT);
266             printw("%04d", blue);
267             if (current == i && field == 2) attrset(A_NORMAL);
268             attrset(A_NORMAL);
269             addstr(")");
270         }
271
272         mvaddstr(COLORS + 3, 0,
273             "Use up/down to select a color, left/right to change fields.");
274         mvaddstr(COLORS + 4, 0,
275             "Modify field by typing nnn=, nnn-, or nnn+.  ? for help.");
276
277         move(2 + current, 0);
278
279         switch (c = getch())
280         {
281         case KEY_UP:
282             current = (current == 0 ? (COLORS - 1) : current - 1);
283             value = 0;
284             break;
285
286         case KEY_DOWN:
287             current = (current == (COLORS - 1) ? 0 : current + 1);
288             value = 0;
289             break;
290
291         case KEY_RIGHT:
292             field = (field == 2 ? 0 : field + 1);
293             value = 0;
294             break;
295
296         case KEY_LEFT:
297             field = (field == 0 ? 2 : field - 1);
298             value = 0;
299             break;
300
301         case '0': case '1': case '2': case '3': case '4':
302         case '5': case '6': case '7': case '8': case '9':
303             do {
304                 value = value * 10 + (c - '0');
305                 c = getch();
306             } while
307                 (isdigit(c));
308             if (c != '+' && c != '-' && c != '=')
309                 beep();
310             else
311                 ungetch(c);
312             break;
313
314         case '+':
315             usebase = 1;
316             goto changeit;
317
318         case '-':
319             value = -value;
320             usebase = 1;
321             goto changeit;
322
323         case '=':
324             usebase = 0;
325         changeit:
326             color_content(current, &red, &green, &blue);
327             if (field == 0)
328                 red = red * usebase + value;
329             else if (field == 1)
330                 green = green * usebase + value;
331             else if (field == 2)
332                 blue = blue * usebase + value;
333             init_color(current, red, green, blue);
334             break;
335
336         case '?':
337             erase();
338     P("                      RGB Value Editing Help");
339     P("");
340     P("You are in the RGB value editor.  Use the arrow keys to select one of");
341     P("the fields in one of the RGB triples of the current colors; the one");
342     P("currently selected will be reverse-video highlighted.");
343     P("");
344     P("To change a field, enter the digits of the new value; they won't be");
345     P("echoed.  Finish by typing `='; the change will take effect instantly.");
346     P("To increment or decrement a value, use the same procedure, but finish");
347     P("with a `+' or `-'.");
348     P("");
349     P("To quit, do `x' or 'q'");
350
351             move(LINES - 1, 0);
352             addstr("Press any key to continue... ");
353             (void) getch();
354             erase();
355             break;
356
357         case 'x':
358         case 'q':
359             break;
360
361         default:
362             beep();
363             break;
364         }
365     } while
366         (c != 'x' && c != 'q');
367
368     erase();
369     endwin();
370 }
371
372 /****************************************************************************
373  *
374  * Soft-key label test
375  *
376  ****************************************************************************/
377
378 static void slk_test(void)
379 /* exercise the soft keys */
380 {
381     int c, fmt = 1;
382     char buf[9];
383
384     c = CTRL('l');
385     do {
386         switch(c)
387         {
388         case CTRL('l'):
389             erase();
390             attron(A_BOLD);
391             mvaddstr(0, 20, "Soft Key Exerciser");
392             attroff(A_BOLD);
393
394             move(2, 0);
395             P("Available commands are:");
396             P("");
397             P("^L         -- refresh screen");
398             P("a          -- activate or restore soft keys");
399             P("d          -- disable soft keys");
400             P("c          -- set centered format for labels");
401             P("l          -- set left-justified format for labels");
402             P("r          -- set right-justified format for labels");
403             P("[12345678] -- set label; labels are numbered 1 through 8");
404             P("e          -- erase stdscr (should not erase labels)");
405             P("s          -- test scrolling of shortened screen");
406             P("x, q       -- return to main menu");
407             P("");
408             P("Note: if activating the soft keys causes your terminal to");
409             P("scroll up one line, your terminal auto-scrolls when anything");
410             P("is written to the last screen position.  The ncurses code");
411             P("does not yet handle this gracefully.");
412             refresh();
413             /* fall through */
414
415         case 'a':
416             slk_restore();
417             break;
418
419         case 'e':
420             wclear(stdscr);
421             break;
422
423         case 's':
424             move(20, 0);
425             while ((c = getch()) != 'Q')
426                 addch(c);
427             break;
428
429         case 'd':
430             slk_clear();
431             break;
432
433         case 'l':
434             fmt = 0;
435             break;
436
437         case 'c':
438             fmt = 1;
439             break;
440
441         case 'r':
442             fmt = 2;
443             break;
444
445         case '1': case '2': case '3': case '4':
446         case '5': case '6': case '7': case '8':
447             (void) mvaddstr(20, 0, "Please enter the label value: ");
448             wgetnstr(stdscr, buf, 8);
449             slk_set((c - '0'), buf, fmt);
450             slk_refresh();
451             break;
452
453         case 'x':
454         case 'q':
455             goto done;
456
457         default:
458             beep();
459         }
460     } while
461         ((c = getch()) != EOF);
462
463  done:
464     erase();
465     endwin();
466 }
467
468 /****************************************************************************
469  *
470  * Alternate character-set stuff
471  *
472  ****************************************************************************/
473
474 static void acs_display()
475 /* display the ACS character set */
476 {
477     int i, j;
478
479     erase();
480     attron(A_BOLD);
481     mvaddstr(0, 20, "Display of the ACS Character Set");
482     attroff(A_BOLD);
483     refresh();
484
485 #define ACSY    2
486     mvaddstr(ACSY + 0, 0, "ACS_ULCORNER: "); addch(ACS_ULCORNER);
487     mvaddstr(ACSY + 1, 0, "ACS_LLCORNER: "); addch(ACS_LLCORNER);
488     mvaddstr(ACSY + 2, 0, "ACS_URCORNER: "); addch(ACS_URCORNER);
489     mvaddstr(ACSY + 3, 0, "ACS_LRCORNER: "); addch(ACS_LRCORNER);
490     mvaddstr(ACSY + 4, 0, "ACS_RTEE: "); addch(ACS_RTEE);
491     mvaddstr(ACSY + 5, 0, "ACS_LTEE: "); addch(ACS_LTEE);
492     mvaddstr(ACSY + 6, 0, "ACS_BTEE: "); addch(ACS_BTEE);
493     mvaddstr(ACSY + 7, 0, "ACS_TTEE: "); addch(ACS_TTEE);
494     mvaddstr(ACSY + 8, 0, "ACS_HLINE: "); addch(ACS_HLINE);
495     mvaddstr(ACSY + 9, 0, "ACS_VLINE: "); addch(ACS_VLINE);
496     mvaddstr(ACSY + 10,0, "ACS_PLUS: "); addch(ACS_PLUS);
497     mvaddstr(ACSY + 11,0, "ACS_S1: "); addch(ACS_S1);
498     mvaddstr(ACSY + 12,0, "ACS_S9: "); addch(ACS_S9);
499
500     mvaddstr(ACSY + 0, 40, "ACS_DIAMOND: "); addch(ACS_DIAMOND);
501     mvaddstr(ACSY + 1, 40, "ACS_CKBOARD: "); addch(ACS_CKBOARD);
502     mvaddstr(ACSY + 2, 40, "ACS_DEGREE: "); addch(ACS_DEGREE);
503     mvaddstr(ACSY + 3, 40, "ACS_PLMINUS: "); addch(ACS_PLMINUS);
504     mvaddstr(ACSY + 4, 40, "ACS_BULLET: "); addch(ACS_BULLET);
505     mvaddstr(ACSY + 5, 40, "ACS_LARROW: "); addch(ACS_LARROW);
506     mvaddstr(ACSY + 6, 40, "ACS_RARROW: "); addch(ACS_RARROW);
507     mvaddstr(ACSY + 7, 40, "ACS_DARROW: "); addch(ACS_DARROW);
508     mvaddstr(ACSY + 8, 40, "ACS_UARROW: "); addch(ACS_UARROW);
509     mvaddstr(ACSY + 9, 40, "ACS_BOARD: "); addch(ACS_BOARD);
510     mvaddstr(ACSY + 10,40, "ACS_LANTERN: "); addch(ACS_LANTERN);
511     mvaddstr(ACSY + 11,40, "ACS_BLOCK: "); addch(ACS_BLOCK);
512
513 #define HYBASE  (ACSY + 13)
514     mvprintw(HYBASE + 1, 0, "High-half characters via echochar:\n");
515     for (i = 0; i < 4; i++)
516     {
517         move(HYBASE + i + 3, 24);
518         for (j = 0; j < 32; j++)
519             echochar(128 + 32 * i + j);
520     }
521
522     move(LINES - 1, 0);
523     addstr("Press any key to continue... ");
524     (void) getch();
525
526     erase();
527     endwin();
528 }
529
530 /****************************************************************************
531  *
532  * Windows and scrolling tester.
533  *
534  ****************************************************************************/
535
536 typedef struct
537 {
538     int y, x;
539 }
540 pair;
541
542 static void report(void)
543 /* report on the cursor's current position, then restore it */
544 {
545     int y, x;
546
547     getyx(stdscr, y, x);
548     move(LINES - 1, COLS - 17);
549     printw("Y = %2d X = %2d", y, x);
550     move(y, x);
551 }
552
553 static pair *selectcell(uli, ulj, lri, lrj)
554 /* arrows keys move cursor, return location at current on non-arrow key */
555 int     uli, ulj, lri, lrj;     /* co-ordinates of corners */
556 {
557     static pair res;                    /* result cell */
558     int         si = lri - uli + 1;     /* depth of the select area */
559     int         sj = lrj - ulj + 1;     /* width of the select area */
560     int         i = 0, j = 0;           /* offsets into the select area */
561
562     for (;;)
563     {
564         move(LINES - 1, COLS - 17);
565         printw("Y = %2d X = %2d", uli + i, ulj + j);
566         move(uli + i, ulj + j);
567
568         switch(getch())
569         {
570         case KEY_UP:    i += si - 1; break;
571         case KEY_DOWN:  i++; break;
572         case KEY_LEFT:  j += sj - 1; break;
573         case KEY_RIGHT: j++; break;
574         case '\004':    return((pair *)NULL);
575         default:        res.y = uli + i; res.x = ulj + j; return(&res);
576         }
577         i %= si;
578         j %= sj;
579     }
580 }
581
582 static WINDOW *getwindow(void)
583 /* Ask user for a window definition */
584 {
585     WINDOW      *rwindow, *bwindow;
586     pair        ul, lr, *tmp;
587
588     move(0, 0); clrtoeol();
589     addstr("Use arrows to move cursor, anything else to mark corner 1");
590     refresh();
591     if ((tmp = selectcell(1,    0,    LINES-1, COLS-1)) == (pair *)NULL)
592         return((WINDOW *)NULL);
593     memcpy(&ul, tmp, sizeof(pair));
594     addch(ACS_ULCORNER);
595     move(0, 0); clrtoeol();
596     addstr("Use arrows to move cursor, anything else to mark corner 2");
597     refresh();
598     if ((tmp = selectcell(ul.y, ul.x, LINES-1, COLS-1)) == (pair *)NULL)
599         return((WINDOW *)NULL);
600     memcpy(&lr, tmp, sizeof(pair));
601
602     rwindow = newwin(lr.y - ul.y + 1, lr.x - ul.x + 1, ul.y, ul.x);
603
604     bwindow = newwin(lr.y - ul.y + 3, lr.x - ul.x + 3, ul.y - 1, ul.x - 1);
605     wborder(bwindow, ACS_VLINE, ACS_VLINE, ACS_HLINE, ACS_HLINE,
606                 0, 0, 0, 0);
607     wrefresh(bwindow);
608     delwin(bwindow);
609
610     scrollok(rwindow, TRUE);
611 /*    immedok(rwindow); */
612     wrefresh(rwindow);
613
614     return(rwindow);
615 }
616
617 static void acs_and_scroll()
618 /* Demonstrate windows */
619 {
620     int c;
621     struct frame
622     {
623         struct frame    *next, *last;
624         WINDOW          *wind;
625     }
626     *oldw  = (struct frame *)NULL, *current = (struct frame *)NULL, *neww;
627
628     refresh();
629     mvaddstr(LINES - 2, 0,
630              "F1 = make new window, F2 = next window, F3 = previous window, Ctrl-D = exit");
631     mvaddstr(LINES - 1, 0,
632              "All other characters are echoed, windows should scroll.");
633
634     c = KEY_F(1);
635     do {
636         report();
637         if (current)
638             wrefresh(current->wind);
639
640         switch(c)
641         {
642         case KEY_F(1):
643             neww = (struct frame *) malloc(sizeof(struct frame));
644             if ((neww->wind = getwindow()) == (WINDOW *)NULL)
645                 goto breakout;
646             if (oldw == NULL)   /* First element,  */
647             {
648                 neww->next = neww; /*   so point it at itself */
649                 neww->last = neww;
650                 current = neww;
651             }
652             else
653             {
654                 neww->last = oldw;  oldw->next = neww;
655                 neww->next = current; current->last = neww;
656             }
657             oldw = neww;
658             keypad(neww->wind, TRUE);
659             break;
660
661         case KEY_F(2):
662             current = current->next;
663             break;
664
665         case KEY_F(3):
666             current = current->last;
667             break;
668
669         case KEY_F(4):  /* undocumented --- use this to test area clears */
670             selectcell(0, 0, LINES - 1, COLS - 1);
671             clrtobot();
672             refresh();
673             break;
674
675         case '\r':
676             c = '\n';
677             /* FALLTHROUGH */
678
679         default:
680             waddch(current->wind, c);
681             break;
682         }
683         report();
684         wrefresh(current->wind);
685     } while
686         ((c = wgetch(current->wind)) != '\004');
687
688  breakout:
689     erase();
690     endwin();
691 }
692
693 #define GRIDSIZE        5
694
695 static void panner(WINDOW *pad, int iy, int ix, int (*pgetc)(void))
696 {
697     static int porty, portx, basex = 0, basey = 0;
698     int pxmax, pymax, c;
699     WINDOW *vscroll = (WINDOW *)NULL, *hscroll = (WINDOW *)NULL;
700
701     porty = iy; portx = ix;
702
703     getmaxyx(pad, pymax, pxmax);
704
705     if (pymax > porty)
706         vscroll = newwin(porty - (pxmax > ix), 1,  0, portx - (pymax > iy));
707     if (pxmax > portx)
708         hscroll = newwin(1, portx - (pymax > iy),  porty - (pxmax > ix), 0);
709
710     c = KEY_REFRESH;
711     do {
712         switch(c)
713         {
714         case KEY_REFRESH:
715             /* do nothing */
716             break;
717
718         case KEY_IC:
719             if (portx >= pxmax || portx >= ix)
720                 beep();
721             else
722             {
723                 mvwin(vscroll, 0, ++portx - 1);
724                 delwin(hscroll);
725                 hscroll = newwin(1, portx - (pymax > porty),
726                                  porty - (pxmax > portx), 0);
727             }
728             break;
729
730         case KEY_IL:
731             if (porty >= pymax || porty >= iy)
732                 beep();
733             else
734             {
735                 mvwin(hscroll, ++porty - 1, 0);
736                 delwin(vscroll);
737                 vscroll = newwin(porty - (pxmax > portx), 1,
738                                  0, portx - (pymax > porty));
739             }
740             break;
741
742         case KEY_DC:
743             if (portx <= 0)
744                 beep();
745             else
746             {
747                 mvwin(vscroll, 0, --portx - 1);
748                 delwin(hscroll);
749                 hscroll = newwin(1, portx - (pymax > porty),
750                                  porty - (pxmax > portx), 0);
751             }
752             break;
753
754         case KEY_DL:
755             if (porty <= 0)
756                 beep();
757             else
758             {
759                 mvwin(hscroll, --porty - 1, 0);
760                 delwin(vscroll);
761                 vscroll = newwin(porty - (pxmax > portx), 1,
762                                  0, portx - (pymax > porty));
763             }
764             break;
765
766         case KEY_LEFT:
767             if (basex > 0)
768                 basex--;
769             else
770                 beep();
771             break;
772
773         case KEY_RIGHT:
774             if (basex + portx < pxmax)
775                 basex++;
776             else
777                 beep();
778             break;
779
780         case KEY_UP:
781             if (basey > 0)
782                 basey--;
783             else
784                 beep();
785             break;
786
787         case KEY_DOWN:
788             if (basey + porty < pymax)
789                 basey++;
790             else
791                 beep();
792             break;
793         }
794
795         prefresh(pad,
796                  basey, basex,
797                  0, 0,
798                  porty - (hscroll != (WINDOW *)NULL) - 1,
799                  portx - (vscroll != (WINDOW *)NULL) - 1);
800         if (vscroll)
801         {
802             int lowend, i, highend;
803
804             lowend = basey * ((float)porty / (float)pymax);
805             highend = (basey + porty) * ((float)porty / (float)pymax);
806
807             touchwin(vscroll);
808             for (i = 0; i < lowend; i++)
809                 mvwaddch(vscroll, i, 0, ACS_VLINE);
810             wattron(vscroll, A_REVERSE);
811             for (i = lowend; i <= highend; i++)
812                 mvwaddch(vscroll, i, 0, ' ');
813             wattroff(vscroll, A_REVERSE);
814             for (i = highend + 1; i < porty; i++)
815                 mvwaddch(vscroll, i, 0, ACS_VLINE);
816             wrefresh(vscroll);
817         }
818         if (hscroll)
819         {
820             int lowend, j, highend;
821
822             lowend = basex * ((float)portx / (float)pxmax);
823             highend = (basex + portx) * ((float)portx / (float)pxmax);
824
825             touchwin(hscroll);
826             for (j = 0; j < lowend; j++)
827                 mvwaddch(hscroll, 0, j, ACS_HLINE);
828             wattron(hscroll, A_REVERSE);
829             for (j = lowend; j <= highend; j++)
830                 mvwaddch(hscroll, 0, j, ' ');
831             wattroff(hscroll, A_REVERSE);
832             for (j = highend + 1; j < portx; j++)
833                 mvwaddch(hscroll, 0, j, ACS_HLINE);
834             wrefresh(hscroll);
835         }
836         mvaddch(porty - 1, portx - 1, ACS_LRCORNER);
837
838     } while
839         ((c = pgetc()) != KEY_EXIT);
840 }
841
842 int padgetch(void)
843 {
844     int c;
845
846     switch(c = getch())
847     {
848     case 'u': return(KEY_UP);
849     case 'd': return(KEY_DOWN);
850     case 'r': return(KEY_RIGHT);
851     case 'l': return(KEY_LEFT);
852     case '+': return(KEY_IL);
853     case '-': return(KEY_DL);
854     case '>': return(KEY_IC);
855     case '<': return(KEY_DC);
856     default: return(c);
857     }
858 }
859
860 static void demo_pad(void)
861 /* Demonstrate pads. */
862 {
863     int i, j, gridcount = 0;
864     WINDOW *panpad = newpad(200, 200);
865
866     for (i = 0; i < 200; i++)
867     {
868         for (j = 0; j < 200; j++)
869             if (i % GRIDSIZE == 0 && j % GRIDSIZE == 0)
870             {
871                 if (i == 0 || j == 0)
872                     waddch(panpad, '+');
873                 else
874                     waddch(panpad, 'A' + (gridcount++ % 26));
875             }
876             else if (i % GRIDSIZE == 0)
877                 waddch(panpad, '-');
878             else if (j % GRIDSIZE == 0)
879                 waddch(panpad, '|');
880             else
881                 waddch(panpad, ' ');
882     }
883     mvprintw(LINES - 3, 0, "Use arrow keys to pan over the test pattern");
884     mvprintw(LINES - 2, 0, "Use +,- to grow/shrink the panner vertically.");
885     mvprintw(LINES - 1, 0, "Use <,> to grow/shrink the panner horizontally.");
886     panner(panpad, LINES - 4, COLS, padgetch);
887
888     endwin();
889     erase();
890 }
891
892 /****************************************************************************
893  *
894  * Tests from John Burnell's PDCurses tester
895  *
896  ****************************************************************************/
897
898 static void Continue (WINDOW *win)
899 {
900     wmove(win, 10, 1);
901     mvwaddstr(win, 10, 1, " Press any key to continue");
902     wrefresh(win);
903     wgetch(win);
904 }
905
906 static void input_test(WINDOW *win)
907 /* Input test, adapted from John Burnell's PDCurses tester */
908 {
909     int w, h, bx, by, sw, sh, i;
910     WINDOW *subWin;
911     wclear (win);
912 #ifdef FOO
913     char buffer [80];
914     int num;
915 #endif /* FOO */
916
917     w  = win->_maxx;
918     h  = win->_maxy;
919     bx = win->_begx;
920     by = win->_begy;
921     sw = w / 3;
922     sh = h / 3;
923     if((subWin = subwin(win, sh, sw, by + h - sh - 2, bx + w - sw - 2)) == NULL)
924         return;
925
926 #ifdef A_COLOR
927     if (has_colors())
928     {
929         init_pair(2,COLOR_CYAN,COLOR_BLUE);
930         wattrset(subWin, COLOR_PAIR(2) | A_BOLD);
931     }
932     else
933         wattrset(subWin, A_BOLD);
934 #else
935     wattrset(subWin, A_BOLD);
936 #endif
937     box(subWin, ACS_VLINE, ACS_HLINE);
938 #ifdef FOO
939     mvwaddstr(subWin, 2, 1, "This is a subwindow");
940 #endif /* FOO */
941     wrefresh(win);
942
943     nocbreak();
944     mvwaddstr(win, 1, 1, "Type random keys for 5 seconds.");
945     mvwaddstr(win, 2, 1,
946       "These should be discarded (not echoed) after the subwindow goes away.");
947     wrefresh(win);
948
949     for (i = 0; i < 5; i++)
950     {
951         mvwprintw (subWin, 1, 1, "Time = %d", i);
952         wrefresh(subWin);
953         sleep(1);
954         flushinp();
955     }
956
957     delwin (subWin);
958     werase(win);
959     flash();
960     wrefresh(win);
961     sleep(1);
962
963     mvwaddstr(win, 2, 1, "Press a key");
964     wmove(win, 9, 10);
965     wrefresh(win);
966     echo();
967     wgetch(win);
968     flushinp();
969     mvwaddstr(win, 12, 0,
970               "If you see any key other than what you typed, flushinp() is broken.");
971     Continue(win);
972
973     wmove(win, 9, 10);
974     wdelch(win);
975     wrefresh(win);
976     wmove(win, 12, 0);
977     clrtoeol();
978     waddstr(win,
979             "What you typed should now have been deleted; if not, wdelch() failed.");
980     Continue(win);
981
982 #ifdef FOO
983     /*
984      * This test won't be portable until vsscanf() is
985      */
986     mvwaddstr(win, 6, 2, "Enter a number then a string separated by space");
987     echo();
988     mvwscanw(win, 7, 6, "%d %s", &num,buffer);
989     mvwprintw(win, 8, 6, "String: %s Number: %d", buffer,num);
990 #endif /* FOO */
991
992     Continue(win);
993 }
994
995 /****************************************************************************
996  *
997  * Main sequence
998  *
999  ****************************************************************************/
1000
1001 bool do_single_test(const char c)
1002 /* perform a single specified test */
1003 {
1004     switch (c)
1005     {
1006     case 'a':
1007         getch_test();
1008         return(TRUE);
1009
1010     case 'b':
1011         attr_test();
1012         return(TRUE);
1013
1014     case 'c':
1015         if (!has_colors())
1016             (void) printf("This %s terminal does not support color.\n",
1017                           getenv("TERM"));
1018         else
1019             color_test();
1020         return(TRUE);
1021
1022     case 'd':
1023         if (!has_colors())
1024             (void) printf("This %s terminal does not support color.\n",
1025                           getenv("TERM"));
1026         else if (!can_change_color())
1027             (void) printf("This %s terminal has hardwired color values.\n",
1028                           getenv("TERM"));
1029         else
1030             color_edit();
1031         return(TRUE);
1032
1033     case 'e':
1034         slk_test();
1035         return(TRUE);
1036
1037     case 'f':
1038         acs_display();
1039         return(TRUE);
1040
1041     case 'g':
1042         acs_and_scroll();
1043         return(TRUE);
1044
1045     case 'p':
1046         demo_pad();
1047         return(TRUE);
1048
1049     case 'i':
1050         input_test(stdscr);
1051         return(TRUE);
1052
1053     case '?':
1054         (void) puts("This is the ncurses capability tester.");
1055         (void) puts("You may select a test from the main menu by typing the");
1056         (void) puts("key letter of the choice (the letter to left of the =)");
1057         (void) puts("at the > prompt.  The commands `x' or `q' will exit.");
1058         return(TRUE);
1059     }
1060
1061     return(FALSE);
1062 }
1063
1064 int main(const int argc, const char *argv[])
1065 {
1066     char        buf[BUFSIZ];
1067
1068     /* enable debugging */
1069     trace(TRACE_ORDINARY);
1070
1071     /* tell it we're going to play with soft keys */
1072     slk_init(1);
1073
1074     /* we must initialize the curses data structure only once */
1075     initscr();
1076
1077     /* tests, in general, will want these modes */
1078     start_color();
1079     cbreak();
1080     noecho();
1081     scrollok(stdscr, TRUE);
1082     keypad(stdscr, TRUE);
1083
1084     /*
1085      * Return to terminal mode, so we're guaranteed of being able to
1086      * select terminal commands even if the capabilities are wrong.
1087      */
1088     endwin();
1089
1090     (void) puts("Welcome to ncurses.  Press ? for help.");
1091
1092     do {
1093         (void) puts("This is the ncurses main menu");
1094         (void) puts("a = character input test");
1095         (void) puts("b = character attribute test");
1096         (void) puts("c = color test pattern");
1097         (void) puts("d = edit RGB color values");
1098         (void) puts("e = exercise soft keys");
1099         (void) puts("f = display ACS characters");
1100         (void) puts("g = display windows and scrolling");
1101         (void) puts("p = exercise pad features");
1102         (void) puts("i = subwindow input test");
1103         (void) puts("? = get help");
1104
1105         (void) fputs("> ", stdout);
1106         (void) fflush(stdout);          /* necessary under SVr4 curses */
1107         (void) fgets(buf, BUFSIZ, stdin);
1108
1109         if (do_single_test(buf[0])) {
1110                 clear();
1111                 refresh();
1112                 endwin();
1113             continue;
1114         }
1115     } while
1116         (buf[0] != 'q' && buf[0] != 'x');
1117
1118     exit(0);
1119 }
1120
1121 /* ncurses.c ends here */