1 /****************************************************************************
4 ncurses.c --- ncurses library exerciser
10 An interactive test module for the ncurses library.
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
17 ***************************************************************************/
27 #define P(s) printw("%s\n", s)
29 #define CTRL(x) ((x) & 0x1f)
32 /****************************************************************************
34 * Character input test
36 ****************************************************************************/
38 static void getch_test(void)
39 /* test the keypad feature */
43 int incount = 0, firsttime = 0;
48 (void) printw("Delay in 10ths of a second (<CR> for blocking input)? ");
55 timeout(atoi(buf) * 100);
64 printw("Key pressed: %04o ", c);
67 (void) addstr(keyname(c));
72 if (isprint(c & ~0x80))
73 (void) printw("M-%c", c);
75 (void) printw("M-%s", unctrl(c));
76 addstr(" (high-half character)\n");
81 (void) printw("%c (ASCII printable character)\n", c);
83 (void) printw("%s (ASCII control character)\n", unctrl(c));
86 if (c == 'x' || c == 'q')
89 addstr("Type any key to see its keypad value, `q' to quit, `?' for help.\n");
91 while ((c = getch()) == ERR)
93 (void) printw("%05d: input timed out\n", incount++);
101 static void attr_test(void)
102 /* test text attributes */
106 mvaddstr(0, 20, "Character attribute test display");
108 mvaddstr(2,8,"This is STANDOUT mode: ");
110 addstr("abcde fghij klmno pqrst uvwxy x");
113 mvaddstr(4,8,"This is REVERSE mode: ");
115 addstr("abcde fghij klmno pqrst uvwxy x");
118 mvaddstr(6,8,"This is BOLD mode: ");
120 addstr("abcde fghij klmno pqrst uvwxy x");
123 mvaddstr(8,8,"This is UNDERLINE mode: ");
125 addstr("abcde fghij klmno pqrst uvwxy x");
126 attroff(A_UNDERLINE);
128 mvaddstr(10,8,"This is DIM mode: ");
130 addstr("abcde fghij klmno pqrst uvwxy x");
133 mvaddstr(12,8,"This is BLINK mode: ");
135 addstr("abcde fghij klmno pqrst uvwxy x");
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);
144 mvaddstr(16,8,"This is NORMAL mode: ");
145 addstr("abcde fghij klmno pqrst uvwxy x");
150 addstr("Press any key to continue... ");
157 /****************************************************************************
159 * Color support tests
161 ****************************************************************************/
163 static char *colors[] =
175 static void color_test(void)
176 /* generate a color test pattern */
181 (void) printw("There are %d color pairs\n", COLOR_PAIRS);
183 (void) mvprintw(1, 0,
184 "%dx%d matrix of foreground/background colors, bright *off*\n",
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++)
192 init_pair(i, i % COLORS, i / COLORS);
193 attron(COLOR_PAIR(i));
194 mvaddstr(3 + (i / COLORS), (i % COLORS + 1) * 8, "Hello");
198 (void) mvprintw(COLORS + 4, 0,
199 "%dx%d matrix of foreground/background colors, bright *on*\n",
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++)
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");
214 addstr("Press any key to continue... ");
221 static void color_edit(void)
222 /* display the color test pattern, without trying to edit colors */
224 int i, c, value = 0, current = 0, field = 0, usebase = 0;
228 for (i = 0; i < COLORS; i++)
229 init_pair(i, COLOR_WHITE, i);
232 short red, green, blue;
235 mvaddstr(0, 20, "Color RGB Value Editing");
238 for (i = 0; i < COLORS; i++)
240 mvprintw(2 + i, 0, "%c %-8s:",
241 (i == current ? '>' : ' '),
242 (i < sizeof(colors)/sizeof(colors[0]) ? colors[i] : ""));
243 attrset(COLOR_PAIR(i));
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.
255 color_content(i, &red, &green, &blue);
257 if (current == i && field == 0) attron(A_STANDOUT);
259 if (current == i && field == 0) attrset(A_NORMAL);
261 if (current == i && field == 1) attron(A_STANDOUT);
262 printw("%04d", green);
263 if (current == i && field == 1) attrset(A_NORMAL);
265 if (current == i && field == 2) attron(A_STANDOUT);
266 printw("%04d", blue);
267 if (current == i && field == 2) attrset(A_NORMAL);
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.");
277 move(2 + current, 0);
282 current = (current == 0 ? (COLORS - 1) : current - 1);
287 current = (current == (COLORS - 1) ? 0 : current + 1);
292 field = (field == 2 ? 0 : field + 1);
297 field = (field == 0 ? 2 : field - 1);
301 case '0': case '1': case '2': case '3': case '4':
302 case '5': case '6': case '7': case '8': case '9':
304 value = value * 10 + (c - '0');
308 if (c != '+' && c != '-' && c != '=')
326 color_content(current, &red, &green, &blue);
328 red = red * usebase + value;
330 green = green * usebase + value;
332 blue = blue * usebase + value;
333 init_color(current, red, green, blue);
338 P(" RGB Value Editing Help");
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.");
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 `-'.");
349 P("To quit, do `x' or 'q'");
352 addstr("Press any key to continue... ");
366 (c != 'x' && c != 'q');
372 /****************************************************************************
374 * Soft-key label test
376 ****************************************************************************/
378 static void slk_test(void)
379 /* exercise the soft keys */
391 mvaddstr(0, 20, "Soft Key Exerciser");
395 P("Available commands are:");
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");
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.");
425 while ((c = getch()) != 'Q')
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);
461 ((c = getch()) != EOF);
468 /****************************************************************************
470 * Alternate character-set stuff
472 ****************************************************************************/
474 static void acs_display()
475 /* display the ACS character set */
481 mvaddstr(0, 20, "Display of the ACS Character Set");
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);
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);
513 #define HYBASE (ACSY + 13)
514 mvprintw(HYBASE + 1, 0, "High-half characters via echochar:\n");
515 for (i = 0; i < 4; i++)
517 move(HYBASE + i + 3, 24);
518 for (j = 0; j < 32; j++)
519 echochar(128 + 32 * i + j);
523 addstr("Press any key to continue... ");
530 /****************************************************************************
532 * Windows and scrolling tester.
534 ****************************************************************************/
542 static void report(void)
543 /* report on the cursor's current position, then restore it */
548 move(LINES - 1, COLS - 17);
549 printw("Y = %2d X = %2d", y, x);
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 */
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 */
564 move(LINES - 1, COLS - 17);
565 printw("Y = %2d X = %2d", uli + i, ulj + j);
566 move(uli + i, ulj + j);
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);
582 static WINDOW *getwindow(void)
583 /* Ask user for a window definition */
585 WINDOW *rwindow, *bwindow;
588 move(0, 0); clrtoeol();
589 addstr("Use arrows to move cursor, anything else to mark corner 1");
591 if ((tmp = selectcell(1, 0, LINES-1, COLS-1)) == (pair *)NULL)
592 return((WINDOW *)NULL);
593 memcpy(&ul, tmp, sizeof(pair));
595 move(0, 0); clrtoeol();
596 addstr("Use arrows to move cursor, anything else to mark corner 2");
598 if ((tmp = selectcell(ul.y, ul.x, LINES-1, COLS-1)) == (pair *)NULL)
599 return((WINDOW *)NULL);
600 memcpy(&lr, tmp, sizeof(pair));
602 rwindow = newwin(lr.y - ul.y + 1, lr.x - ul.x + 1, ul.y, ul.x);
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,
610 scrollok(rwindow, TRUE);
611 /* immedok(rwindow); */
617 static void acs_and_scroll()
618 /* Demonstrate windows */
623 struct frame *next, *last;
626 *oldw = (struct frame *)NULL, *current = (struct frame *)NULL, *neww;
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.");
638 wrefresh(current->wind);
643 neww = (struct frame *) malloc(sizeof(struct frame));
644 if ((neww->wind = getwindow()) == (WINDOW *)NULL)
646 if (oldw == NULL) /* First element, */
648 neww->next = neww; /* so point it at itself */
654 neww->last = oldw; oldw->next = neww;
655 neww->next = current; current->last = neww;
658 keypad(neww->wind, TRUE);
662 current = current->next;
666 current = current->last;
669 case KEY_F(4): /* undocumented --- use this to test area clears */
670 selectcell(0, 0, LINES - 1, COLS - 1);
680 waddch(current->wind, c);
684 wrefresh(current->wind);
686 ((c = wgetch(current->wind)) != '\004');
695 static void panner(WINDOW *pad, int iy, int ix, int (*pgetc)(void))
697 static int porty, portx, basex = 0, basey = 0;
699 WINDOW *vscroll = (WINDOW *)NULL, *hscroll = (WINDOW *)NULL;
701 porty = iy; portx = ix;
703 getmaxyx(pad, pymax, pxmax);
706 vscroll = newwin(porty - (pxmax > ix), 1, 0, portx - (pymax > iy));
708 hscroll = newwin(1, portx - (pymax > iy), porty - (pxmax > ix), 0);
719 if (portx >= pxmax || portx >= ix)
723 mvwin(vscroll, 0, ++portx - 1);
725 hscroll = newwin(1, portx - (pymax > porty),
726 porty - (pxmax > portx), 0);
731 if (porty >= pymax || porty >= iy)
735 mvwin(hscroll, ++porty - 1, 0);
737 vscroll = newwin(porty - (pxmax > portx), 1,
738 0, portx - (pymax > porty));
747 mvwin(vscroll, 0, --portx - 1);
749 hscroll = newwin(1, portx - (pymax > porty),
750 porty - (pxmax > portx), 0);
759 mvwin(hscroll, --porty - 1, 0);
761 vscroll = newwin(porty - (pxmax > portx), 1,
762 0, portx - (pymax > porty));
774 if (basex + portx < pxmax)
788 if (basey + porty < pymax)
798 porty - (hscroll != (WINDOW *)NULL) - 1,
799 portx - (vscroll != (WINDOW *)NULL) - 1);
802 int lowend, i, highend;
804 lowend = basey * ((float)porty / (float)pymax);
805 highend = (basey + porty) * ((float)porty / (float)pymax);
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);
820 int lowend, j, highend;
822 lowend = basex * ((float)portx / (float)pxmax);
823 highend = (basex + portx) * ((float)portx / (float)pxmax);
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);
836 mvaddch(porty - 1, portx - 1, ACS_LRCORNER);
839 ((c = pgetc()) != KEY_EXIT);
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);
860 static void demo_pad(void)
861 /* Demonstrate pads. */
863 int i, j, gridcount = 0;
864 WINDOW *panpad = newpad(200, 200);
866 for (i = 0; i < 200; i++)
868 for (j = 0; j < 200; j++)
869 if (i % GRIDSIZE == 0 && j % GRIDSIZE == 0)
871 if (i == 0 || j == 0)
874 waddch(panpad, 'A' + (gridcount++ % 26));
876 else if (i % GRIDSIZE == 0)
878 else if (j % GRIDSIZE == 0)
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);
892 /****************************************************************************
894 * Tests from John Burnell's PDCurses tester
896 ****************************************************************************/
898 static void Continue (WINDOW *win)
901 mvwaddstr(win, 10, 1, " Press any key to continue");
906 static void input_test(WINDOW *win)
907 /* Input test, adapted from John Burnell's PDCurses tester */
909 int w, h, bx, by, sw, sh, i;
923 if((subWin = subwin(win, sh, sw, by + h - sh - 2, bx + w - sw - 2)) == NULL)
929 init_pair(2,COLOR_CYAN,COLOR_BLUE);
930 wattrset(subWin, COLOR_PAIR(2) | A_BOLD);
933 wattrset(subWin, A_BOLD);
935 wattrset(subWin, A_BOLD);
937 box(subWin, ACS_VLINE, ACS_HLINE);
939 mvwaddstr(subWin, 2, 1, "This is a subwindow");
944 mvwaddstr(win, 1, 1, "Type random keys for 5 seconds.");
946 "These should be discarded (not echoed) after the subwindow goes away.");
949 for (i = 0; i < 5; i++)
951 mvwprintw (subWin, 1, 1, "Time = %d", i);
963 mvwaddstr(win, 2, 1, "Press a key");
969 mvwaddstr(win, 12, 0,
970 "If you see any key other than what you typed, flushinp() is broken.");
979 "What you typed should now have been deleted; if not, wdelch() failed.");
984 * This test won't be portable until vsscanf() is
986 mvwaddstr(win, 6, 2, "Enter a number then a string separated by space");
988 mvwscanw(win, 7, 6, "%d %s", &num,buffer);
989 mvwprintw(win, 8, 6, "String: %s Number: %d", buffer,num);
995 /****************************************************************************
999 ****************************************************************************/
1001 bool do_single_test(const char c)
1002 /* perform a single specified test */
1016 (void) printf("This %s terminal does not support color.\n",
1024 (void) printf("This %s terminal does not support color.\n",
1026 else if (!can_change_color())
1027 (void) printf("This %s terminal has hardwired color values.\n",
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.");
1064 int main(const int argc, const char *argv[])
1068 /* enable debugging */
1069 trace(TRACE_ORDINARY);
1071 /* tell it we're going to play with soft keys */
1074 /* we must initialize the curses data structure only once */
1077 /* tests, in general, will want these modes */
1081 scrollok(stdscr, TRUE);
1082 keypad(stdscr, TRUE);
1085 * Return to terminal mode, so we're guaranteed of being able to
1086 * select terminal commands even if the capabilities are wrong.
1090 (void) puts("Welcome to ncurses. Press ? for help.");
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");
1105 (void) fputs("> ", stdout);
1106 (void) fflush(stdout); /* necessary under SVr4 curses */
1107 (void) fgets(buf, BUFSIZ, stdin);
1109 if (do_single_test(buf[0])) {
1116 (buf[0] != 'q' && buf[0] != 'x');
1121 /* ncurses.c ends here */