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 $Id: ncurses.c,v 1.91 1997/05/10 18:19:48 tom Exp $
19 ***************************************************************************/
21 #include <test.priv.h>
30 #if HAVE_SYS_TIME_H && ! SYSTEM_LOOKS_LIKE_SCO
34 #include <sys/select.h>
39 #define USE_LIBPANEL 1
42 #define USE_LIBPANEL 0
45 #if HAVE_MENU_H && HAVE_LIBMENU
52 #if HAVE_FORM_H && HAVE_LIBFORM
59 #ifdef NCURSES_VERSION
62 static int save_trace = TRACE_ORDINARY|TRACE_CALLS;
63 extern int _nc_tracing;
72 #define mmask_t chtype /* not specified in XSI */
73 #define attr_t chtype /* not specified in XSI */
74 #define ACS_S3 (acs_map['p']) /* scan line 3 */
75 #define ACS_S7 (acs_map['r']) /* scan line 7 */
76 #define ACS_LEQUAL (acs_map['y']) /* less/equal */
77 #define ACS_GEQUAL (acs_map['z']) /* greater/equal */
78 #define ACS_PI (acs_map['{']) /* Pi */
79 #define ACS_NEQUAL (acs_map['|']) /* not equal */
80 #define ACS_STERLING (acs_map['}']) /* UK pound sign */
84 #define P(string) printw("%s\n", string)
86 #define CTRL(x) ((x) & 0x1f)
89 #define SIZEOF(table) (sizeof(table)/sizeof(table[0]))
90 #define QUIT CTRL('Q')
91 #define ESCAPE CTRL('[')
92 #define BLANK ' ' /* this is the background character */
94 /* The behavior of mvhline, mvvline for negative/zero length is unspecified,
95 * though we can rely on negative x/y values to stop the macro.
97 static void do_h_line(int y, int x, chtype c, int to)
100 mvhline(y, x, c, (to) - (x));
103 static void do_v_line(int y, int x, chtype c, int to)
106 mvvline(y, x, c, (to) - (y));
109 /* Common function to allow ^T to toggle trace-mode in the middle of a test
110 * so that trace-files can be made smaller.
112 static int wGetchar(WINDOW *win)
116 while ((c = wgetch(win)) == CTRL('T')) {
118 save_trace = _nc_tracing;
119 _tracef("TOGGLE-TRACING OFF");
122 _nc_tracing = save_trace;
126 _tracef("TOGGLE-TRACING ON");
133 #define Getchar() wGetchar(stdscr)
135 static void Pause(void)
138 addstr("Press any key to continue... ");
142 static void Cannot(const char *what)
144 printw("\nThis %s terminal %s\n\n", getenv("TERM"), what);
148 static void ShellOut(bool message)
151 addstr("Shelling out...");
156 addstr("returned from shellout.\n");
160 /****************************************************************************
162 * Character input test
164 ****************************************************************************/
166 static void getch_test(void)
167 /* test the keypad feature */
171 int incount = 0, firsttime = 0;
172 bool blocking = TRUE;
177 #ifdef NCURSES_MOUSE_VERSION
178 mousemask(ALL_MOUSE_EVENTS, (mmask_t *)0);
181 (void) printw("Delay in 10ths of a second (<CR> for blocking input)? ");
189 timeout(atoi(buf) * 100);
199 printw("Key pressed: %04o ", c);
200 #ifdef NCURSES_MOUSE_VERSION
206 printw("KEY_MOUSE, %s\n", _tracemouse(&event));
209 #endif /* NCURSES_MOUSE_VERSION */
212 (void) addstr(keyname(c));
219 (void) printw("M-%c", c2);
221 (void) printw("M-%s", unctrl(c2));
222 addstr(" (high-half character)\n");
227 (void) printw("%c (ASCII printable character)\n", c);
229 (void) printw("%s (ASCII control character)\n", unctrl(c));
239 addstr("getstr test: ");
240 echo(); getstr(buf); noecho();
241 printw("I saw `%s'.\n", buf);
247 if (c == 'x' || c == 'q' || (c == ERR && blocking))
251 addstr("Type any key to see its keypad value. Also:\n");
252 addstr("g -- triggers a getstr test\n");
253 addstr("s -- shell out\n");
254 addstr("q -- quit\n");
255 addstr("? -- repeats this help message\n");
258 while ((c = Getchar()) == ERR)
260 (void) printw("%05d: input timed out\n", incount++);
262 (void) printw("%05d: input error\n", incount++);
267 #ifdef NCURSES_MOUSE_VERSION
268 mousemask(0, (mmask_t *)0);
277 static int show_attr(int row, chtype attr, const char *name, bool once, const char *capname)
279 mvprintw(row, 8, "%s mode:", name);
280 mvprintw(row, 24, "|");
285 addstr("abcde fghij klmno pqrst uvwxy z");
289 if (capname != 0 && tigetstr(capname) == 0)
294 static void attr_test(void)
295 /* test text attributes */
300 mvaddstr(0, 20, "Character attribute test display");
302 row = show_attr(row, A_STANDOUT, "STANDOUT", TRUE, "smso");
303 row = show_attr(row, A_REVERSE, "REVERSE", TRUE, "rev");
304 row = show_attr(row, A_BOLD, "BOLD", TRUE, "bold");
305 row = show_attr(row, A_UNDERLINE, "UNDERLINE", TRUE, "smul");
306 row = show_attr(row, A_DIM, "DIM", TRUE, "dim");
307 row = show_attr(row, A_BLINK, "BLINK", TRUE, "blink");
308 row = show_attr(row, A_PROTECT, "PROTECT", TRUE, "prot");
309 row = show_attr(row, A_INVIS, "INVISIBLE", TRUE, "invis");
310 row = show_attr(row, A_NORMAL, "NORMAL", FALSE,0);
313 "This terminal does %shave the magic-cookie glitch",
314 tigetnum("xmc") > -1 ? "" : "not ");
324 /****************************************************************************
326 * Color support tests
328 ****************************************************************************/
330 static NCURSES_CONST char *colors[] =
342 static void color_test(void)
343 /* generate a color test pattern */
348 (void) printw("There are %d color pairs\n", COLOR_PAIRS);
350 (void) mvprintw(1, 0,
351 "%dx%d matrix of foreground/background colors, bright *off*\n",
353 for (i = 0; i < COLORS; i++)
354 mvaddstr(2, (i+1) * 8, colors[i]);
355 for (i = 0; i < COLORS; i++)
356 mvaddstr(3 + i, 0, colors[i]);
357 for (i = 1; i < COLOR_PAIRS; i++)
359 init_pair(i, i % COLORS, i / COLORS);
360 attron((attr_t)COLOR_PAIR(i));
361 mvaddstr(3 + (i / COLORS), (i % COLORS + 1) * 8, "Hello");
365 (void) mvprintw(COLORS + 4, 0,
366 "%dx%d matrix of foreground/background colors, bright *on*\n",
368 for (i = 0; i < COLORS; i++)
369 mvaddstr(5 + COLORS, (i+1) * 8, colors[i]);
370 for (i = 0; i < COLORS; i++)
371 mvaddstr(6 + COLORS + i, 0, colors[i]);
372 for (i = 1; i < COLOR_PAIRS; i++)
374 init_pair(i, i % COLORS, i / COLORS);
375 attron((attr_t)(COLOR_PAIR(i) | A_BOLD));
376 mvaddstr(6 + COLORS + (i / COLORS), (i % COLORS + 1) * 8, "Hello");
386 static void change_color(int current, int field, int value, int usebase)
388 short red, green, blue;
391 color_content(current, &red, &green, &blue);
393 red = green = blue = 0;
407 if (init_color(current, red, green, blue) == ERR)
411 static void color_edit(void)
412 /* display the color test pattern, without trying to edit colors */
414 int i, this_c = 0, value = 0, current = 0, field = 0;
419 for (i = 0; i < COLORS; i++)
420 init_pair(i, COLOR_WHITE, i);
422 mvprintw(LINES-2, 0, "Number: %d", value);
425 short red, green, blue;
428 mvaddstr(0, 20, "Color RGB Value Editing");
431 for (i = 0; i < COLORS; i++)
433 mvprintw(2 + i, 0, "%c %-8s:",
434 (i == current ? '>' : ' '),
435 (i < (int) SIZEOF(colors)
437 attrset(COLOR_PAIR(i));
442 * Note: this refresh should *not* be necessary! It works around
443 * a bug in attribute handling that apparently causes the A_NORMAL
444 * attribute sets to interfere with the actual emission of the
445 * color setting somehow. This needs to be fixed.
449 color_content(i, &red, &green, &blue);
451 if (current == i && field == 0) attron(A_STANDOUT);
453 if (current == i && field == 0) attrset(A_NORMAL);
455 if (current == i && field == 1) attron(A_STANDOUT);
456 printw("%04d", green);
457 if (current == i && field == 1) attrset(A_NORMAL);
459 if (current == i && field == 2) attron(A_STANDOUT);
460 printw("%04d", blue);
461 if (current == i && field == 2) attrset(A_NORMAL);
466 mvaddstr(COLORS + 3, 0,
467 "Use up/down to select a color, left/right to change fields.");
468 mvaddstr(COLORS + 4, 0,
469 "Modify field by typing nnn=, nnn-, or nnn+. ? for help.");
471 move(2 + current, 0);
475 if (isdigit(this_c) && !isdigit(last_c))
481 current = (current == 0 ? (COLORS - 1) : current - 1);
485 current = (current == (COLORS - 1) ? 0 : current + 1);
489 field = (field == 2 ? 0 : field + 1);
493 field = (field == 0 ? 2 : field - 1);
496 case '0': case '1': case '2': case '3': case '4':
497 case '5': case '6': case '7': case '8': case '9':
498 value = value * 10 + (this_c - '0');
502 change_color(current, field, value, 1);
506 change_color(current, field, -value, 1);
510 change_color(current, field, value, 0);
515 P(" RGB Value Editing Help");
517 P("You are in the RGB value editor. Use the arrow keys to select one of");
518 P("the fields in one of the RGB triples of the current colors; the one");
519 P("currently selected will be reverse-video highlighted.");
521 P("To change a field, enter the digits of the new value; they are echoed");
522 P("echoed. Finish by typing `='; the change will take effect instantly.");
523 P("To increment or decrement a value, use the same procedure, but finish");
524 P("with a `+' or `-'.");
526 P("To quit, do `x' or 'q'");
540 mvprintw(LINES-2, 0, "Number: %d", value);
543 (this_c != 'x' && this_c != 'q');
549 /****************************************************************************
551 * Soft-key label test
553 ****************************************************************************/
555 static void slk_test(void)
556 /* exercise the soft keys */
569 mvaddstr(0, 20, "Soft Key Exerciser");
573 P("Available commands are:");
575 P("^L -- refresh screen");
576 P("a -- activate or restore soft keys");
577 P("d -- disable soft keys");
578 P("c -- set centered format for labels");
579 P("l -- set left-justified format for labels");
580 P("r -- set right-justified format for labels");
581 P("[12345678] -- set label; labels are numbered 1 through 8");
582 P("e -- erase stdscr (should not erase labels)");
583 P("s -- test scrolling of shortened screen");
584 P("x, q -- return to main menu");
586 P("Note: if activating the soft keys causes your terminal to");
587 P("scroll up one line, your terminal auto-scrolls when anything");
588 P("is written to the last screen position. The ncurses code");
589 P("does not yet handle this gracefully.");
602 mvprintw(20, 0, "Press Q to stop the scrolling-test: ");
603 while ((c = Getchar()) != 'Q' && (c != ERR))
623 case '1': case '2': case '3': case '4':
624 case '5': case '6': case '7': case '8':
625 (void) mvaddstr(20, 0, "Please enter the label value: ");
627 wgetnstr(stdscr, buf, 8);
629 slk_set((c - '0'), buf, fmt);
631 move(20, 0); clrtoeol();
642 ((c = Getchar()) != EOF);
649 /****************************************************************************
651 * Alternate character-set stuff
653 ****************************************************************************/
655 /* ISO 6429: codes 0x80 to 0x9f may be control characters that cause the
656 * terminal to perform functions. The remaining codes can be graphic.
658 static void show_upper_chars(int first)
660 bool C1 = (first == 128);
662 int last = first + 31;
667 mvprintw(0, 20, "Display of %s Character Codes %d to %d",
668 C1 ? "C1" : "GR", first, last);
672 for (code = first; code <= last; code++) {
673 int row = 4 + ((code - first) % 16);
674 int col = ((code - first) / 16) * COLS / 2;
676 sprintf(tmp, "%3d (0x%x)", code, code);
677 mvprintw(row, col, "%*s: ", COLS/4, tmp);
679 nodelay(stdscr, TRUE);
682 /* (yes, this _is_ crude) */
683 while ((reply = Getchar()) != ERR) {
687 nodelay(stdscr, FALSE);
692 static int show_1_acs(int n, const char *name, chtype code)
694 const int height = 16;
695 int row = 4 + (n % height);
696 int col = (n / height) * COLS / 2;
697 mvprintw(row, col, "%*s : ", COLS/4, name);
702 static void show_acs_chars(void)
703 /* display the ACS character set */
707 #define BOTH(name) #name, name
711 mvaddstr(0, 20, "Display of the ACS Character Set");
715 n = show_1_acs(0, BOTH(ACS_ULCORNER));
716 n = show_1_acs(n, BOTH(ACS_LLCORNER));
717 n = show_1_acs(n, BOTH(ACS_URCORNER));
718 n = show_1_acs(n, BOTH(ACS_LRCORNER));
719 n = show_1_acs(n, BOTH(ACS_RTEE));
720 n = show_1_acs(n, BOTH(ACS_LTEE));
721 n = show_1_acs(n, BOTH(ACS_BTEE));
722 n = show_1_acs(n, BOTH(ACS_TTEE));
723 n = show_1_acs(n, BOTH(ACS_HLINE));
724 n = show_1_acs(n, BOTH(ACS_VLINE));
725 n = show_1_acs(n, BOTH(ACS_PLUS));
726 n = show_1_acs(n, BOTH(ACS_S1));
727 n = show_1_acs(n, BOTH(ACS_S9));
728 n = show_1_acs(n, BOTH(ACS_DIAMOND));
729 n = show_1_acs(n, BOTH(ACS_CKBOARD));
730 n = show_1_acs(n, BOTH(ACS_DEGREE));
731 n = show_1_acs(n, BOTH(ACS_PLMINUS));
732 n = show_1_acs(n, BOTH(ACS_BULLET));
733 n = show_1_acs(n, BOTH(ACS_LARROW));
734 n = show_1_acs(n, BOTH(ACS_RARROW));
735 n = show_1_acs(n, BOTH(ACS_DARROW));
736 n = show_1_acs(n, BOTH(ACS_UARROW));
737 n = show_1_acs(n, BOTH(ACS_BOARD));
738 n = show_1_acs(n, BOTH(ACS_LANTERN));
739 n = show_1_acs(n, BOTH(ACS_BLOCK));
740 n = show_1_acs(n, BOTH(ACS_S3));
741 n = show_1_acs(n, BOTH(ACS_S7));
742 n = show_1_acs(n, BOTH(ACS_LEQUAL));
743 n = show_1_acs(n, BOTH(ACS_GEQUAL));
744 n = show_1_acs(n, BOTH(ACS_PI));
745 n = show_1_acs(n, BOTH(ACS_NEQUAL));
746 n = show_1_acs(n, BOTH(ACS_STERLING));
749 static void acs_display(void)
762 show_upper_chars((c - '0') * 32 + 128);
765 mvprintw(LINES-3,0, "Note: ANSI terminals may not display C1 characters.");
766 mvprintw(LINES-2,0, "Select: a=ACS, 0=C1, 1,2,3=GR characters, q=quit");
768 } while ((c = Getchar()) != 'x' && c != 'q');
776 * Graphic-rendition test (adapted from vttest)
779 test_sgr_attributes(void)
783 for (pass = 0; pass < 2; pass++) {
784 int normal = ((pass == 0 ? A_NORMAL : A_REVERSE)) | BLANK;
786 /* Use non-default colors if possible to exercise bce a little */
788 init_pair(1, COLOR_WHITE, COLOR_BLUE);
789 normal |= COLOR_PAIR(1);
793 mvprintw( 1,20, "Graphic rendition test pattern:");
795 mvprintw( 4, 1, "vanilla");
797 #define set_sgr(mask) bkgdset((normal^(mask)));
799 mvprintw( 4,40, "bold");
801 set_sgr(A_UNDERLINE);
802 mvprintw( 6, 6, "underline");
804 set_sgr(A_BOLD|A_UNDERLINE);
805 mvprintw( 6,45, "bold underline");
808 mvprintw( 8, 1, "blink");
810 set_sgr(A_BLINK|A_BOLD);
811 mvprintw( 8,40, "bold blink");
813 set_sgr(A_UNDERLINE|A_BLINK);
814 mvprintw(10, 6, "underline blink");
816 set_sgr(A_BOLD|A_UNDERLINE|A_BLINK);
817 mvprintw(10,45, "bold underline blink");
820 mvprintw(12, 1, "negative");
822 set_sgr(A_BOLD|A_REVERSE);
823 mvprintw(12,40, "bold negative");
825 set_sgr(A_UNDERLINE|A_REVERSE);
826 mvprintw(14, 6, "underline negative");
828 set_sgr(A_BOLD|A_UNDERLINE|A_REVERSE);
829 mvprintw(14,45, "bold underline negative");
831 set_sgr(A_BLINK|A_REVERSE);
832 mvprintw(16, 1, "blink negative");
834 set_sgr(A_BOLD|A_BLINK|A_REVERSE);
835 mvprintw(16,40, "bold blink negative");
837 set_sgr(A_UNDERLINE|A_BLINK|A_REVERSE);
838 mvprintw(18, 6, "underline blink negative");
840 set_sgr(A_BOLD|A_UNDERLINE|A_BLINK|A_REVERSE);
841 mvprintw(18,45, "bold underline blink negative");
844 mvprintw(LINES-2,1, "%s background. ", pass == 0 ? "Dark" : "Light");
849 bkgdset(A_NORMAL | BLANK);
854 /****************************************************************************
856 * Windows and scrolling tester.
858 ****************************************************************************/
860 #define BOTLINES 4 /* number of line stolen from screen bottom */
868 #define FRAME struct frame
877 /* We need to know if these flags are actually set, so don't look in FRAME.
878 * These names are known to work with SVr4 curses as well as ncurses.
880 static bool HaveKeypad(FRAME *curp)
882 WINDOW *win = (curp ? curp->wind : stdscr);
883 return win->_use_keypad;
886 static bool HaveScroll(FRAME *curp)
888 WINDOW *win = (curp ? curp->wind : stdscr);
892 static void newwin_legend(FRAME *curp)
894 static const struct {
898 { "^C = create window", 0 },
899 { "^N = next window", 0 },
900 { "^P = previous window", 0 },
901 { "^F = scroll forward", 0 },
902 { "^B = scroll backward", 0 },
903 { "^K = keypad(%s)", 1 },
904 { "^S = scrollok(%s)", 2 },
905 { "^W = save window to file", 0 },
906 { "^R = restore window", 0 },
907 #ifdef NCURSES_VERSION
908 { "^X = resize", 0 },
914 bool do_keypad = HaveKeypad(curp);
915 bool do_scroll = HaveScroll(curp);
919 for (n = 0; n < SIZEOF(legend); n++) {
920 switch (legend[n].code) {
922 strcpy(buf, legend[n].msg);
925 sprintf(buf, legend[n].msg, do_keypad ? "yes" : "no");
928 sprintf(buf, legend[n].msg, do_scroll ? "yes" : "no");
931 sprintf(buf, legend[n].msg, do_keypad ? "/ESC" : "");
935 addstr((COLS < (x + 3 + (int)strlen(buf))) ? "\n" : (n ? ", " : ""));
941 static void transient(FRAME *curp, NCURSES_CONST char *msg)
946 mvaddstr(LINES - 1, 0, msg);
952 printw("%s characters are echoed, window should %sscroll.",
953 HaveKeypad(curp) ? "Non-arrow" : "All other",
954 HaveScroll(curp) ? "" : "not " );
958 static void newwin_report(FRAME *curp)
959 /* report on the cursor's current position, then restore it */
961 WINDOW *win = (curp != 0) ? curp->wind : stdscr;
965 transient(curp, (char *)0);
967 move(LINES - 1, COLS - 17);
968 printw("Y = %2d X = %2d", y, x);
975 static pair *selectcell(int uli, int ulj, int lri, int lrj)
976 /* arrows keys move cursor, return location at current on non-arrow key */
978 static pair res; /* result cell */
979 int si = lri - uli + 1; /* depth of the select area */
980 int sj = lrj - ulj + 1; /* width of the select area */
981 int i = 0, j = 0; /* offsets into the select area */
987 move(uli + i, ulj + j);
988 newwin_report((FRAME *)0);
992 case KEY_UP: i += si - 1; break;
993 case KEY_DOWN: i++; break;
994 case KEY_LEFT: j += sj - 1; break;
995 case KEY_RIGHT: j++; break;
997 case ESCAPE: return((pair *)0);
998 #ifdef NCURSES_MOUSE_VERSION
1004 if (event.y > uli && event.x > ulj) {
1014 default: res.y = uli + i; res.x = ulj + j; return(&res);
1021 static void outerbox(pair ul, pair lr, bool onoff)
1022 /* draw or erase a box *outside* the given pair of corners */
1024 mvaddch(ul.y-1, lr.x-1, onoff ? ACS_ULCORNER : ' ');
1025 mvaddch(ul.y-1, lr.x+1, onoff ? ACS_URCORNER : ' ');
1026 mvaddch(lr.y+1, lr.x+1, onoff ? ACS_LRCORNER : ' ');
1027 mvaddch(lr.y+1, ul.x-1, onoff ? ACS_LLCORNER : ' ');
1028 move(ul.y-1, ul.x); hline(onoff ? ACS_HLINE : ' ', lr.x - ul.x + 1);
1029 move(ul.y, ul.x-1); vline(onoff ? ACS_VLINE : ' ', lr.y - ul.y + 1);
1030 move(lr.y+1, ul.x); hline(onoff ? ACS_HLINE : ' ', lr.x - ul.x + 1);
1031 move(ul.y, lr.x+1); vline(onoff ? ACS_VLINE : ' ', lr.y - ul.y + 1);
1034 static WINDOW *getwindow(void)
1035 /* Ask user for a window definition */
1040 move(0, 0); clrtoeol();
1041 addstr("Use arrows to move cursor, anything else to mark corner 1");
1043 if ((tmp = selectcell(2, 1, LINES-BOTLINES-2, COLS-2)) == (pair *)0)
1044 return((WINDOW *)0);
1045 memcpy(&ul, tmp, sizeof(pair));
1046 mvaddch(ul.y-1, ul.x-1, ACS_ULCORNER);
1047 move(0, 0); clrtoeol();
1048 addstr("Use arrows to move cursor, anything else to mark corner 2");
1050 if ((tmp = selectcell(ul.y, ul.x, LINES-BOTLINES-2, COLS-2)) == (pair *)0)
1051 return((WINDOW *)0);
1052 memcpy(&lr, tmp, sizeof(pair));
1054 rwindow = subwin(stdscr, lr.y - ul.y + 1, lr.x - ul.x + 1, ul.y, ul.x);
1056 outerbox(ul, lr, TRUE);
1061 move(0, 0); clrtoeol();
1065 static void newwin_move(FRAME *curp, int dy, int dx)
1067 WINDOW *win = (curp != 0) ? curp->wind : stdscr;
1071 getyx(win, cur_y, cur_x);
1072 getmaxyx(win, max_y, max_x);
1073 if ((cur_x += dx) < 0)
1075 else if (cur_x >= max_x)
1077 if ((cur_y += dy) < 0)
1079 else if (cur_y >= max_y)
1081 wmove(win, cur_y, cur_x);
1084 static FRAME *delete_framed(FRAME *fp, bool showit)
1088 fp->last->next = fp->next;
1089 fp->next->last = fp->last;
1097 np = (fp == fp->next) ? 0 : fp->next;
1102 static void acs_and_scroll(void)
1103 /* Demonstrate windows */
1107 FRAME *current = (FRAME *)0, *neww;
1108 WINDOW *usescr = stdscr;
1110 #define DUMPFILE "screendump"
1112 #ifdef NCURSES_MOUSE_VERSION
1113 mousemask(BUTTON1_CLICKED, (mmask_t *)0);
1118 transient((FRAME *)0, (char *)0);
1122 neww = (FRAME *) calloc(1, sizeof(FRAME));
1123 if ((neww->wind = getwindow()) == (WINDOW *)0)
1126 if (current == 0) /* First element, */
1128 neww->next = neww; /* so point it at itself */
1133 neww->next = current->next;
1134 neww->last = current;
1135 neww->last->next = neww;
1136 neww->next->last = neww;
1139 current->do_keypad = HaveKeypad(current);
1140 current->do_scroll = HaveScroll(current);
1143 case CTRL('N'): /* go to next window */
1145 current = current->next;
1148 case CTRL('P'): /* go to previous window */
1150 current = current->last;
1153 case CTRL('F'): /* scroll current window forward */
1155 wscrl(current->wind, 1);
1158 case CTRL('B'): /* scroll current window backwards */
1160 wscrl(current->wind, -1);
1163 case CTRL('K'): /* toggle keypad mode for current */
1165 current->do_keypad = !current->do_keypad;
1166 keypad(current->wind, current->do_keypad);
1172 current->do_scroll = !current->do_scroll;
1173 scrollok(current->wind, current->do_scroll);
1177 case CTRL('W'): /* save and delete window */
1178 if (current == current->next)
1180 if ((fp = fopen(DUMPFILE, "w")) == (FILE *)0)
1181 transient(current, "Can't open screen dump file");
1184 (void) putwin(current->wind, fp);
1187 current = delete_framed(current, TRUE);
1191 case CTRL('R'): /* restore window */
1192 if ((fp = fopen(DUMPFILE, "r")) == (FILE *)0)
1193 transient(current, "Can't open screen dump file");
1196 neww = (FRAME *) calloc(1, sizeof(FRAME));
1198 neww->next = current->next;
1199 neww->last = current;
1200 neww->last->next = neww;
1201 neww->next->last = neww;
1203 neww->wind = getwin(fp);
1206 wrefresh(neww->wind);
1210 #ifdef NCURSES_VERSION
1211 case CTRL('X'): /* resize window */
1216 move(0, 0); clrtoeol();
1217 addstr("Use arrows to move cursor, anything else to mark new corner");
1220 getbegyx(current->wind, ul.y, ul.x);
1222 tmp = selectcell(ul.y, ul.x, LINES-BOTLINES-2, COLS-2);
1223 if (tmp == (pair *)0)
1229 getmaxyx(current->wind, lr.y, lr.x);
1232 outerbox(ul, lr, FALSE);
1233 wnoutrefresh(stdscr);
1235 /* strictly cosmetic hack for the test */
1236 if (current->wind->_maxy > tmp->y - ul.y)
1238 getyx(current->wind, lr.y, lr.x);
1239 wmove(current->wind, tmp->y - ul.y + 1, 0);
1240 wclrtobot(current->wind);
1241 wmove(current->wind, lr.y, lr.x);
1243 if (current->wind->_maxx > tmp->x - ul.x)
1244 for (i = 0; i < current->wind->_maxy; i++)
1246 wmove(current->wind, i, tmp->x - ul.x + 1);
1247 wclrtoeol(current->wind);
1249 wnoutrefresh(current->wind);
1251 memcpy(&lr, tmp, sizeof(pair));
1252 (void) wresize(current->wind, lr.y-ul.y+0, lr.x-ul.x+0);
1254 getbegyx(current->wind, ul.y, ul.x);
1255 getmaxyx(current->wind, lr.y, lr.x);
1258 outerbox(ul, lr, TRUE);
1259 wnoutrefresh(stdscr);
1261 wnoutrefresh(current->wind);
1262 move(0, 0); clrtoeol();
1266 #endif /* NCURSES_VERSION */
1268 case KEY_F(10): /* undocumented --- use this to test area clears */
1269 selectcell(0, 0, LINES - 1, COLS - 1);
1275 newwin_move(current, -1, 0);
1278 newwin_move(current, 1, 0);
1281 newwin_move(current, 0, -1);
1284 newwin_move(current, 0, 1);
1292 getyx(current->wind, y, x);
1296 x = getmaxx(current->wind) - 1;
1298 mvwdelch(current->wind, y, x);
1308 waddch(current->wind, (chtype)c);
1313 newwin_report(current);
1314 usescr = (current ? current->wind : stdscr);
1317 ((c = wGetchar(usescr))
1318 && !((c == ESCAPE) && (usescr->_use_keypad))
1322 while (current != 0)
1323 current = delete_framed(current, FALSE);
1325 scrollok(stdscr, TRUE); /* reset to driver's default */
1326 #ifdef NCURSES_MOUSE_VERSION
1327 mousemask(0, (mmask_t *)0);
1334 /****************************************************************************
1338 ****************************************************************************/
1352 static unsigned long nap_msec = 1;
1354 static NCURSES_CONST char *mod[] =
1364 /*+-------------------------------------------------------------------------
1366 --------------------------------------------------------------------------*/
1368 wait_a_while(unsigned long msec GCC_UNUSED)
1378 else if(msec > 1000L)
1379 sleep((int)msec/1000L);
1383 } /* end of wait_a_while */
1385 /*+-------------------------------------------------------------------------
1387 --------------------------------------------------------------------------*/
1389 saywhat(NCURSES_CONST char *text)
1391 wmove(stdscr,LINES - 1,0);
1393 waddstr(stdscr, text);
1394 } /* end of saywhat */
1396 /*+-------------------------------------------------------------------------
1397 mkpanel(rows,cols,tly,tlx) - alloc a win and panel and associate them
1398 --------------------------------------------------------------------------*/
1400 mkpanel(int rows, int cols, int tly, int tlx)
1402 WINDOW *win = newwin(rows,cols,tly,tlx);
1407 if((pan = new_panel(win)))
1411 } /* end of mkpanel */
1413 /*+-------------------------------------------------------------------------
1415 --------------------------------------------------------------------------*/
1419 WINDOW *win = panel_window(pan);
1422 } /* end of rmpanel */
1424 /*+-------------------------------------------------------------------------
1426 --------------------------------------------------------------------------*/
1432 } /* end of pflush */
1434 /*+-------------------------------------------------------------------------
1436 --------------------------------------------------------------------------*/
1438 fill_panel(PANEL *pan)
1440 WINDOW *win = panel_window(pan);
1441 int num = ((const char *)panel_userptr(pan))[1];
1446 wprintw(win,"-pan%c-", num);
1447 for(y = 2; y < getmaxy(win) - 1; y++)
1449 for(x = 1; x < getmaxx(win) - 1; x++)
1455 } /* end of fill_panel */
1457 static void demo_panels(void)
1464 for(y = 0; y < LINES - 1; y++)
1466 for(x = 0; x < COLS; x++)
1467 wprintw(stdscr,"%d",(y + x) % 10);
1469 for(y = 0; y < 5; y++)
1471 p1 = mkpanel(LINES/2 - 2, COLS/8 + 1, 0, 0);
1472 w1 = panel_window(p1);
1473 set_panel_userptr(p1,"p1");
1475 p2 = mkpanel(LINES/2 + 1, COLS/7, LINES/4, COLS/10);
1476 w2 = panel_window(p2);
1477 set_panel_userptr(p2,"p2");
1479 p3 = mkpanel(LINES/4, COLS/10, LINES/2, COLS/9);
1480 w3 = panel_window(p3);
1481 set_panel_userptr(p3,"p3");
1483 p4 = mkpanel(LINES/2 - 2, COLS/8, LINES/2 - 2, COLS/3);
1484 w4 = panel_window(p4);
1485 set_panel_userptr(p4,"p4");
1487 p5 = mkpanel(LINES/2 - 2, COLS/8, LINES/2, COLS/2 - 2);
1488 w5 = panel_window(p5);
1489 set_panel_userptr(p5,"p5");
1499 saywhat("press any key to continue");
1500 wait_a_while(nap_msec);
1502 saywhat("h3 s1 s2 s4 s5; press any key to continue");
1510 wait_a_while(nap_msec);
1512 saywhat("s1; press any key to continue");
1515 wait_a_while(nap_msec);
1517 saywhat("s2; press any key to continue");
1520 wait_a_while(nap_msec);
1522 saywhat("m2; press any key to continue");
1523 move_panel(p2, LINES/3 + 1, COLS / 8);
1525 wait_a_while(nap_msec);
1530 wait_a_while(nap_msec);
1532 saywhat("m3; press any key to continue");
1533 move_panel(p3, LINES/4 + 1, COLS / 15);
1535 wait_a_while(nap_msec);
1537 saywhat("b3; press any key to continue");
1540 wait_a_while(nap_msec);
1542 saywhat("s4; press any key to continue");
1545 wait_a_while(nap_msec);
1547 saywhat("s5; press any key to continue");
1550 wait_a_while(nap_msec);
1552 saywhat("t3; press any key to continue");
1555 wait_a_while(nap_msec);
1557 saywhat("t1; press any key to continue");
1560 wait_a_while(nap_msec);
1562 saywhat("t2; press any key to continue");
1565 wait_a_while(nap_msec);
1567 saywhat("t3; press any key to continue");
1570 wait_a_while(nap_msec);
1572 saywhat("t4; press any key to continue");
1575 wait_a_while(nap_msec);
1577 for(itmp = 0; itmp < 6; itmp++)
1579 saywhat("m4; press any key to continue");
1580 wmove(w4, LINES/8, 1);
1581 waddstr(w4,mod[itmp]);
1582 move_panel(p4, LINES/6, itmp*(COLS/8));
1583 wmove(w5, LINES/6, 1);
1584 waddstr(w5,mod[itmp]);
1586 wait_a_while(nap_msec);
1587 saywhat("m5; press any key to continue");
1588 wmove(w4, LINES/6, 1);
1589 waddstr(w4,mod[itmp]);
1590 move_panel(p5, LINES/3 - 1,(itmp*10) + 6);
1591 wmove(w5, LINES/8, 1);
1592 waddstr(w5,mod[itmp]);
1594 wait_a_while(nap_msec);
1597 saywhat("m4; press any key to continue");
1598 move_panel(p4, LINES/6, itmp*(COLS/8));
1600 wait_a_while(nap_msec);
1602 saywhat("t5; press any key to continue");
1605 wait_a_while(nap_msec);
1607 saywhat("t2; press any key to continue");
1610 wait_a_while(nap_msec);
1612 saywhat("t1; press any key to continue");
1615 wait_a_while(nap_msec);
1617 saywhat("d2; press any key to continue");
1620 wait_a_while(nap_msec);
1622 saywhat("h3; press any key to continue");
1625 wait_a_while(nap_msec);
1627 saywhat("d1; press any key to continue");
1630 wait_a_while(nap_msec);
1632 saywhat("d4; press any key to continue");
1635 wait_a_while(nap_msec);
1637 saywhat("d5; press any key to continue");
1640 wait_a_while(nap_msec);
1650 /****************************************************************************
1654 ****************************************************************************/
1658 static bool show_panner_legend = TRUE;
1660 static int panner_legend(int line)
1662 static const char *const legend[] = {
1663 "Use arrow keys (or U,D,L,R) to pan, q to quit (?,t,s flags)",
1664 "Use ! to shell-out. Toggle legend:?, timer:t, scroll mark:s.",
1665 "Use +,- (or j,k) to grow/shrink the panner vertically.",
1666 "Use <,> (or h,l) to grow/shrink the panner horizontally."
1668 int n = (SIZEOF(legend) - (LINES - line));
1669 if (line < LINES && (n >= 0)) {
1671 if (show_panner_legend)
1672 printw("%s", legend[n]);
1674 return show_panner_legend;
1679 static void panner_h_cleanup(int from_y, int from_x, int to_x)
1681 if (!panner_legend(from_y))
1682 do_h_line(from_y, from_x, ' ', to_x);
1685 static void panner_v_cleanup(int from_y, int from_x, int to_y)
1687 if (!panner_legend(from_y))
1688 do_v_line(from_y, from_x, ' ', to_y);
1691 static void panner(WINDOW *pad,
1692 int top_x, int top_y, int porty, int portx,
1693 int (*pgetc)(WINDOW *))
1695 #if HAVE_GETTIMEOFDAY
1696 struct timeval before, after;
1699 bool scrollers = TRUE;
1702 int pxmax, pymax, lowend, highend, c;
1704 getmaxyx(pad, pymax, pxmax);
1705 scrollok(stdscr, FALSE); /* we don't want stdscr to scroll! */
1709 #ifdef NCURSES_VERSION
1711 * During shell-out, the user may have resized the window. Adjust
1712 * the port size of the pad to accommodate this. Ncurses automatically
1713 * resizes all of the normal windows to fit on the new screen.
1715 if (top_x > COLS) top_x = COLS;
1716 if (portx > COLS) portx = COLS;
1717 if (top_y > LINES) top_y = LINES;
1718 if (porty > LINES) porty = LINES;
1728 show_panner_legend = !show_panner_legend;
1729 panner_legend(LINES - 4);
1730 panner_legend(LINES - 3);
1731 panner_legend(LINES - 2);
1732 panner_legend(LINES - 1);
1734 #if HAVE_GETTIMEOFDAY
1738 panner_legend(LINES-1);
1742 scrollers = !scrollers;
1745 /* Move the top-left corner of the pad, keeping the bottom-right
1748 case 'h': /* increase-columns: move left edge to left */
1753 panner_v_cleanup(top_y, top_x, porty);
1758 case 'j': /* decrease-lines: move top-edge down */
1763 panner_h_cleanup(top_y - 1, top_x - (top_x > 0), portx);
1768 case 'k': /* increase-lines: move top-edge up */
1774 panner_h_cleanup(top_y, top_x, portx);
1778 case 'l': /* decrease-columns: move left-edge to right */
1783 panner_v_cleanup(top_y - (top_y > 0), top_x - 1, porty);
1788 /* Move the bottom-right corner of the pad, keeping the top-left
1791 case KEY_IC: /* increase-columns: move right-edge to right */
1792 if (portx >= pxmax || portx >= COLS)
1796 panner_v_cleanup(top_y - (top_y > 0), portx - 1, porty);
1801 case KEY_IL: /* increase-lines: move bottom-edge down */
1802 if (porty >= pymax || porty >= LINES)
1806 panner_h_cleanup(porty - 1, top_x - (top_x > 0), portx);
1811 case KEY_DC: /* decrease-columns: move bottom edge up */
1817 panner_v_cleanup(top_y - (top_y > 0), portx, porty);
1821 case KEY_DL: /* decrease-lines */
1827 panner_h_cleanup(porty, top_x - (top_x > 0), portx);
1831 case KEY_LEFT: /* pan leftwards */
1838 case KEY_RIGHT: /* pan rightwards */
1839 if (basex + portx - (pymax > porty) < pxmax)
1845 case KEY_UP: /* pan upwards */
1852 case KEY_DOWN: /* pan downwards */
1853 if (basey + porty - (pxmax > portx) < pymax)
1864 mvaddch(top_y - 1, top_x - 1, ACS_ULCORNER);
1865 do_v_line(top_y, top_x - 1, ACS_VLINE, porty);
1866 do_h_line(top_y - 1, top_x, ACS_HLINE, portx);
1868 if (scrollers && (pxmax > portx - 1)) {
1869 int length = (portx - top_x - 1);
1870 float ratio = ((float) length) / ((float) pxmax);
1872 lowend = top_x + (basex * ratio);
1873 highend = top_x + ((basex + length) * ratio);
1875 do_h_line(porty - 1, top_x, ACS_HLINE, lowend);
1876 if (highend < portx) {
1878 do_h_line(porty - 1, lowend, ' ', highend + 1);
1880 do_h_line(porty - 1, highend + 1, ACS_HLINE, portx);
1883 do_h_line(porty - 1, top_x, ACS_HLINE, portx);
1885 if (scrollers && (pymax > porty - 1)) {
1886 int length = (porty - top_y - 1);
1887 float ratio = ((float) length) / ((float) pymax);
1889 lowend = top_y + (basey * ratio);
1890 highend = top_y + ((basey + length) * ratio);
1892 do_v_line(top_y, portx - 1, ACS_VLINE, lowend);
1893 if (highend < porty) {
1895 do_v_line(lowend, portx - 1, ' ', highend + 1);
1897 do_v_line(highend + 1, portx - 1, ACS_VLINE, porty);
1900 do_v_line(top_y, portx - 1, ACS_VLINE, porty);
1902 mvaddch(top_y - 1, portx - 1, ACS_URCORNER);
1903 mvaddch(porty - 1, top_x - 1, ACS_LLCORNER);
1904 mvaddch(porty - 1, portx - 1, ACS_LRCORNER);
1906 #if HAVE_GETTIMEOFDAY
1907 gettimeofday(&before, 0);
1909 wnoutrefresh(stdscr);
1914 porty - (pxmax > portx) - 1,
1915 portx - (pymax > porty) - 1);
1918 #if HAVE_GETTIMEOFDAY
1921 gettimeofday(&after, 0);
1922 elapsed = (after.tv_sec + after.tv_usec / 1.0e6)
1923 - (before.tv_sec + before.tv_usec / 1.0e6);
1924 move(LINES-1, COLS-20);
1925 printw("Secs: %2.03f", elapsed);
1931 ((c = pgetc(pad)) != KEY_EXIT);
1933 scrollok(stdscr, TRUE); /* reset to driver's default */
1937 int padgetch(WINDOW *win)
1942 switch(c = wGetchar(win))
1944 case '!': ShellOut(FALSE); return KEY_REFRESH;
1945 case CTRL('r'): endwin(); refresh(); return KEY_REFRESH;
1946 case CTRL('l'): return KEY_REFRESH;
1947 case 'U': return(KEY_UP);
1948 case 'D': return(KEY_DOWN);
1949 case 'R': return(KEY_RIGHT);
1950 case 'L': return(KEY_LEFT);
1951 case '+': return(KEY_IL);
1952 case '-': return(KEY_DL);
1953 case '>': return(KEY_IC);
1954 case '<': return(KEY_DC);
1955 case ERR: /* FALLTHRU */
1956 case 'q': return(KEY_EXIT);
1961 static void demo_pad(void)
1962 /* Demonstrate pads. */
1965 unsigned gridcount = 0;
1966 WINDOW *panpad = newpad(200, 200);
1968 for (i = 0; i < 200; i++)
1970 for (j = 0; j < 200; j++)
1971 if (i % GRIDSIZE == 0 && j % GRIDSIZE == 0)
1973 if (i == 0 || j == 0)
1974 waddch(panpad, '+');
1976 waddch(panpad, (chtype)('A' + (gridcount++ % 26)));
1978 else if (i % GRIDSIZE == 0)
1979 waddch(panpad, '-');
1980 else if (j % GRIDSIZE == 0)
1981 waddch(panpad, '|');
1983 waddch(panpad, ' ');
1985 panner_legend(LINES - 4);
1986 panner_legend(LINES - 3);
1987 panner_legend(LINES - 2);
1988 panner_legend(LINES - 1);
1990 keypad(panpad, TRUE);
1992 /* Make the pad (initially) narrow enough that a trace file won't wrap.
1993 * We'll still be able to widen it during a test, since that's required
1994 * for testing boundaries.
1996 panner(panpad, 2, 2, LINES - 5, COLS-15, padgetch);
2002 #endif /* USE_LIBPANEL */
2004 /****************************************************************************
2006 * Tests from John Burnell's PDCurses tester
2008 ****************************************************************************/
2010 static void Continue (WINDOW *win)
2014 mvwaddstr(win, 10, 1, " Press any key to continue");
2019 static void flushinp_test(WINDOW *win)
2020 /* Input test, adapted from John Burnell's PDCurses tester */
2022 int w, h, bx, by, sw, sh, i;
2033 if((subWin = subwin(win, sh, sw, by + h - sh - 2, bx + w - sw - 2)) == 0)
2039 init_pair(2,COLOR_CYAN,COLOR_BLUE);
2040 wattrset(subWin, COLOR_PAIR(2) | A_BOLD);
2043 wattrset(subWin, A_BOLD);
2045 wattrset(subWin, A_BOLD);
2047 box(subWin, ACS_VLINE, ACS_HLINE);
2048 mvwaddstr(subWin, 2, 1, "This is a subwindow");
2052 mvwaddstr(win, 0, 1, "This is a test of the flushinp() call.");
2054 mvwaddstr(win, 2, 1, "Type random keys for 5 seconds.");
2055 mvwaddstr(win, 3, 1,
2056 "These should be discarded (not echoed) after the subwindow goes away.");
2059 for (i = 0; i < 5; i++)
2061 mvwprintw (subWin, 1, 1, "Time = %d", i);
2073 mvwaddstr(win, 2, 1,
2074 "If you were still typing when the window timer expired,");
2075 mvwaddstr(win, 3, 1,
2076 "or else you typed nothing at all while it was running,");
2077 mvwaddstr(win, 4, 1,
2078 "test was invalid. You'll see garbage or nothing at all. ");
2079 mvwaddstr(win, 6, 1, "Press a key");
2085 mvwaddstr(win, 12, 0,
2086 "If you see any key other than what you typed, flushinp() is broken.");
2095 "What you typed should now have been deleted; if not, wdelch() failed.");
2101 /****************************************************************************
2105 ****************************************************************************/
2112 static int menu_virtualize(int c)
2114 if (c == '\n' || c == KEY_EXIT)
2115 return(MAX_COMMAND + 1);
2116 else if (c == 'n' || c == KEY_DOWN)
2117 return(REQ_NEXT_ITEM);
2118 else if (c == 'p' || c == KEY_UP)
2119 return(REQ_PREV_ITEM);
2121 return(REQ_TOGGLE_ITEM);
2126 static const char *animals[] =
2128 "Lions", "Tigers", "Bears", "(Oh my!)", "Newts", "Platypi", "Lemurs",
2132 static void menu_test(void)
2135 ITEM *items[SIZEOF(animals)];
2141 mvaddstr(0, 0, "This is the menu test:");
2142 mvaddstr(2, 0, " Use up and down arrow to move the select bar.");
2143 mvaddstr(3, 0, " 'n' and 'p' act like arrows.");
2144 mvaddstr(4, 0, " Press return to exit.");
2147 for (ap = animals; *ap; ap++)
2148 *ip++ = new_item(*ap, "");
2151 m = new_menu(items);
2153 scale_menu(m, &mrows, &mcols);
2155 menuwin = newwin(mrows + 2, mcols + 2, MENU_Y, MENU_X);
2156 set_menu_win(m, menuwin);
2157 keypad(menuwin, TRUE);
2160 set_menu_sub(m, derwin(menuwin, mrows, mcols, 1, 1));
2164 while (menu_driver(m, menu_virtualize(wGetchar(menuwin))) != E_UNKNOWN_COMMAND)
2167 (void) mvprintw(LINES - 2, 0,
2168 "You chose: %s\n", item_name(current_item(m)));
2169 (void) addstr("Press any key to continue...");
2176 for (ip = items; *ip; ip++)
2181 #define T_TBL(name) { #name, name }
2186 T_TBL(TRACE_DISABLE),
2189 T_TBL(TRACE_UPDATE),
2191 T_TBL(TRACE_CHARPUT),
2192 T_TBL(TRACE_ORDINARY),
2194 T_TBL(TRACE_VIRTPUT),
2195 T_TBL(TRACE_IEVENT),
2197 T_TBL(TRACE_ICALLS),
2198 T_TBL(TRACE_CCALLS),
2199 T_TBL(TRACE_MAXIMUM),
2203 static char *tracetrace(int tlevel)
2210 for (n = 0; t_tbl[n].name != 0; n++)
2211 need += strlen(t_tbl[n].name) + 2;
2214 sprintf(buf, "0x%02x = {", tlevel);
2216 sprintf(buf + strlen(buf), "%s, ", t_tbl[0].name);
2218 for (n = 1; t_tbl[n].name != 0; n++)
2219 if ((tlevel & t_tbl[n].mask) == t_tbl[n].mask)
2221 strcat(buf, t_tbl[n].name);
2225 if (buf[strlen(buf) - 2] == ',')
2226 buf[strlen(buf) - 2] = '\0';
2227 return(strcat(buf,"}"));
2230 /* fake a dynamically reconfigurable menu using the 0th entry to deselect
2233 static int run_trace_menu(MENU *m)
2239 bool changed = FALSE;
2240 switch (menu_driver(m, menu_virtualize(wGetchar(menu_win(m))))) {
2241 case E_UNKNOWN_COMMAND:
2244 items = menu_items(m);
2245 i = current_item(m);
2246 if (i == items[0]) {
2247 if (item_value(i)) {
2248 for (p = items+1; *p != 0; p++)
2249 if (item_value(*p)) {
2250 set_item_value(*p, FALSE);
2255 for (p = items+1; *p != 0; p++)
2256 if (item_value(*p)) {
2257 set_item_value(items[0], FALSE);
2268 static void trace_set(void)
2269 /* interactively set the trace level */
2272 ITEM *items[SIZEOF(t_tbl)];
2274 int mrows, mcols, newtrace;
2278 mvaddstr(0, 0, "Interactively set trace level:");
2279 mvaddstr(2, 0, " Press space bar to toggle a selection.");
2280 mvaddstr(3, 0, " Use up and down arrow to move the select bar.");
2281 mvaddstr(4, 0, " Press return to set the trace level.");
2282 mvprintw(6, 0, "(Current trace level is %s)", tracetrace(_nc_tracing));
2286 for (n = 0; t_tbl[n].name != 0; n++)
2287 *ip++ = new_item(t_tbl[n].name, "");
2290 m = new_menu(items);
2292 set_menu_format(m, 0, 2);
2293 scale_menu(m, &mrows, &mcols);
2295 menu_opts_off(m, O_ONEVALUE);
2296 menuwin = newwin(mrows + 2, mcols + 2, MENU_Y, MENU_X);
2297 set_menu_win(m, menuwin);
2298 keypad(menuwin, TRUE);
2301 set_menu_sub(m, derwin(menuwin, mrows, mcols, 1, 1));
2305 for (ip = menu_items(m); *ip; ip++) {
2306 int mask = t_tbl[item_index(*ip)].mask;
2308 set_item_value(*ip, _nc_tracing == 0);
2309 else if ((mask & _nc_tracing) == mask)
2310 set_item_value(*ip, TRUE);
2313 while (run_trace_menu(m))
2317 for (ip = menu_items(m); *ip; ip++)
2318 if (item_value(*ip))
2319 newtrace |= t_tbl[item_index(*ip)].mask;
2321 _tracef("trace level interactively set to %s", tracetrace(_nc_tracing));
2323 (void) mvprintw(LINES - 2, 0,
2324 "Trace level is %s\n", tracetrace(_nc_tracing));
2325 (void) addstr("Press any key to continue...");
2332 for (ip = items; *ip; ip++)
2336 #endif /* USE_LIBMENU */
2338 /****************************************************************************
2342 ****************************************************************************/
2344 static FIELD *make_label(int frow, int fcol, NCURSES_CONST char *label)
2346 FIELD *f = new_field(1, strlen(label), frow, fcol, 0, 0);
2350 set_field_buffer(f, 0, label);
2351 set_field_opts(f, field_opts(f) & ~O_ACTIVE);
2356 static FIELD *make_field(int frow, int fcol, int rows, int cols)
2358 FIELD *f = new_field(rows, cols, frow, fcol, 0, 0);
2361 set_field_back(f, A_UNDERLINE);
2365 static void display_form(FORM *f)
2370 scale_form(f, &rows, &cols);
2372 if ((w =newwin(rows+2, cols+4, 0, 0)) != (WINDOW *)0)
2375 set_form_sub(f, derwin(w, rows, cols, 1, 2));
2380 if (post_form(f) != E_OK)
2384 static void erase_form(FORM *f)
2386 WINDOW *w = form_win(f);
2387 WINDOW *s = form_sub(f);
2396 static int form_virtualize(WINDOW *w)
2398 static int mode = REQ_INS_MODE;
2399 int c = wGetchar(w);
2405 return(MAX_FORM_COMMAND + 1);
2407 /* demo doesn't use these three, leave them in anyway as sample code */
2410 return(REQ_NEXT_PAGE);
2412 return(REQ_PREV_PAGE);
2416 return(REQ_NEXT_FIELD);
2419 return(REQ_PREV_FIELD);
2422 return(REQ_FIRST_FIELD);
2425 return(REQ_LAST_FIELD);
2428 return(REQ_LEFT_FIELD);
2430 return(REQ_RIGHT_FIELD);
2432 return(REQ_UP_FIELD);
2434 return(REQ_DOWN_FIELD);
2437 return(REQ_NEXT_WORD);
2439 return(REQ_PREV_WORD);
2441 return(REQ_BEG_FIELD);
2443 return(REQ_END_FIELD);
2446 return(REQ_LEFT_CHAR);
2448 return(REQ_RIGHT_CHAR);
2450 return(REQ_UP_CHAR);
2452 return(REQ_DOWN_CHAR);
2455 return(REQ_NEW_LINE);
2457 return(REQ_INS_CHAR);
2459 return(REQ_INS_LINE);
2461 return(REQ_DEL_CHAR);
2465 return(REQ_DEL_PREV);
2467 return(REQ_DEL_LINE);
2469 return(REQ_DEL_WORD);
2472 return(REQ_CLR_EOL);
2474 return(REQ_CLR_EOF);
2476 return(REQ_CLR_FIELD);
2478 return(REQ_NEXT_CHOICE);
2480 return(REQ_PREV_CHOICE);
2483 if (mode == REQ_INS_MODE)
2484 return(mode = REQ_OVL_MODE);
2486 return(mode = REQ_INS_MODE);
2493 static int my_form_driver(FORM *form, int c)
2495 if (c == (MAX_FORM_COMMAND + 1)
2496 && form_driver(form, REQ_VALIDATION) == E_OK)
2505 static void demo_forms(void)
2510 int finished = 0, c;
2512 mvaddstr(10, 57, "Forms Entry Test");
2515 addstr("Defined form-traversal keys: ^Q/ESC- exit form\n");
2516 addstr("^N -- go to next field ^P -- go to previous field\n");
2517 addstr("Home -- go to first field End -- go to last field\n");
2518 addstr("^L -- go to field to left ^R -- go to field to right\n");
2519 addstr("^U -- move upward to field ^D -- move downward to field\n");
2520 addstr("^W -- go to next word ^B -- go to previous word\n");
2521 addstr("^S -- go to start of field ^E -- go to end of field\n");
2522 addstr("^H -- delete previous char ^Y -- delete line\n");
2523 addstr("^G -- delete current word ^C -- clear to end of line\n");
2524 addstr("^K -- clear to end of field ^X -- clear field\n");
2525 addstr("Arrow keys move within a field as you would expect.");
2528 /* describe the form */
2529 f[0] = make_label(0, 15, "Sample Form");
2530 f[1] = make_label(2, 0, "Last Name");
2531 f[2] = make_field(3, 0, 1, 18);
2532 f[3] = make_label(2, 20, "First Name");
2533 f[4] = make_field(3, 20, 1, 12);
2534 f[5] = make_label(2, 34, "Middle Name");
2535 f[6] = make_field(3, 34, 1, 12);
2536 f[7] = make_label(5, 0, "Comments");
2537 f[8] = make_field(6, 0, 4, 46);
2548 switch(form_driver(form, c = form_virtualize(w)))
2552 case E_UNKNOWN_COMMAND:
2553 finished = my_form_driver(form, c);
2564 for (c = 0; f[c] != 0; c++)
2568 #endif /* USE_LIBFORM */
2570 /****************************************************************************
2574 ****************************************************************************/
2576 static void fillwin(WINDOW *win, char ch)
2580 for (y = 0; y <= win->_maxy; y++)
2583 for (x = 0; x <= win->_maxx; x++)
2588 static void crosswin(WINDOW *win, char ch)
2592 for (y = 0; y <= win->_maxy; y++)
2594 for (x = 0; x <= win->_maxx; x++)
2595 if (((x > win->_maxx / 3) && (x <= 2 * win->_maxx / 3))
2596 || (((y > win->_maxy / 3) && (y <= 2 * win->_maxy / 3))))
2604 static void overlap_test(void)
2605 /* test effects of overlapping windows */
2609 WINDOW *win1 = newwin(9, 20, 3, 3);
2610 WINDOW *win2 = newwin(9, 20, 9, 16);
2614 printw("This test shows the behavior of wnoutrefresh() with respect to\n");
2615 printw("the shared region of two overlapping windows A and B. The cross\n");
2616 printw("pattern in each window does not overlap the other.\n");
2620 printw("a = refresh A, then B, then doupdate. b = refresh B, then A, then doupdaute\n");
2621 printw("c = fill window A with letter A. d = fill window B with letter B.\n");
2622 printw("e = cross pattern in window A. f = cross pattern in window B.\n");
2623 printw("g = clear window A. h = clear window B.\n");
2624 printw("i = overwrite A onto B. j = overwrite B onto A.\n");
2625 printw("^Q/ESC = terminate test.");
2627 while ((ch = Getchar()) != QUIT && ch != ESCAPE)
2630 case 'a': /* refresh window A first, then B */
2636 case 'b': /* refresh window B first, then A */
2642 case 'c': /* fill window A so it's visible */
2646 case 'd': /* fill window B so it's visible */
2650 case 'e': /* cross test pattern in window A */
2651 crosswin(win1, 'A');
2654 case 'f': /* cross test pattern in window A */
2655 crosswin(win2, 'B');
2658 case 'g': /* clear window A */
2663 case 'h': /* clear window B */
2668 case 'i': /* overwrite A onto B */
2669 overwrite(win1, win2);
2672 case 'j': /* overwrite B onto A */
2673 overwrite(win2, win1);
2683 /****************************************************************************
2687 ****************************************************************************/
2690 do_single_test(const char c)
2691 /* perform a single specified test */
2705 Cannot("does not support color.");
2712 Cannot("does not support color.");
2713 else if (!can_change_color())
2714 Cannot("has hardwired color values.");
2738 flushinp_test(stdscr);
2742 test_sgr_attributes();
2767 #if USE_LIBMENU && defined(TRACE)
2774 (void) puts("This is the ncurses capability tester.");
2775 (void) puts("You may select a test from the main menu by typing the");
2776 (void) puts("key letter of the choice (the letter to left of the =)");
2777 (void) puts("at the > prompt. The commands `x' or `q' will exit.");
2790 static const char *const tbl[] = {
2791 "Usage: ncurses [options]"
2794 ," -e fmt specify format for soft-keys test (e)"
2795 ," -f rip-off footer line (can repeat)"
2796 ," -h rip-off header line (can repeat)"
2797 ," -s msec specify nominal time for panel-demo (default: 1, to hold)"
2799 ," -t mask specify default trace-level (may toggle with ^T)"
2803 for (n = 0; n < sizeof(tbl)/sizeof(tbl[0]); n++)
2804 fprintf(stderr, "%s\n", tbl[n]);
2809 set_terminal_modes(void)
2814 scrollok(stdscr, TRUE);
2815 idlok(stdscr, TRUE);
2816 keypad(stdscr, TRUE);
2820 static RETSIGTYPE announce_sig(int sig)
2822 (void) fprintf(stderr, "Handled signal %d\r\n", sig);
2826 static int rip_footer(WINDOW *win, int columns)
2828 wbkgd(win, A_REVERSE);
2831 wprintw(win, "footer: %d columns", columns);
2836 static int rip_header(WINDOW *win, int columns)
2838 wbkgd(win, A_REVERSE);
2841 wprintw(win, "header: %d columns", columns);
2846 /*+-------------------------------------------------------------------------
2848 --------------------------------------------------------------------------*/
2851 main(int argc, char *argv[])
2856 while ((c = getopt(argc, argv, "e:fhs:t:")) != EOF) {
2859 my_e_param = atoi(optarg);
2860 #ifdef NCURSES_VERSION
2861 if (my_e_param > 3) /* allow extended layouts */
2869 ripoffline(-1, rip_footer);
2872 ripoffline(1, rip_header);
2875 nap_msec = atol(optarg);
2879 save_trace = atoi(optarg);
2888 * If there's no menus (unlikely for ncurses!), then we'll have to set
2889 * tracing on initially, just in case the user wants to test something that
2890 * doesn't involve wGetchar.
2893 /* enable debugging */
2897 if (!isatty(fileno(stdin)))
2899 #endif /* USE_LIBMENU */
2902 /* tell it we're going to play with soft keys */
2903 slk_init(my_e_param);
2906 /* set up null signal catcher so we can see what interrupts to getch do */
2907 signal(SIGUSR1, announce_sig);
2910 /* we must initialize the curses data structure only once */
2914 /* tests, in general, will want these modes */
2916 set_terminal_modes();
2920 * Return to terminal mode, so we're guaranteed of being able to
2921 * select terminal commands even if the capabilities are wrong.
2925 (void) puts("Welcome to ncurses. Press ? for help.");
2928 (void) puts("This is the ncurses main menu");
2929 (void) puts("a = keyboard and mouse input test");
2930 (void) puts("b = character attribute test");
2931 (void) puts("c = color test pattern");
2932 (void) puts("d = edit RGB color values");
2933 (void) puts("e = exercise soft keys");
2934 (void) puts("f = display ACS characters");
2935 (void) puts("g = display windows and scrolling");
2936 (void) puts("i = test of flushinp()");
2937 (void) puts("k = display character attributes");
2939 (void) puts("m = menu code test");
2942 (void) puts("o = exercise panels library");
2943 (void) puts("p = exercise pad features");
2944 (void) puts("q = quit");
2947 (void) puts("r = exercise forms code");
2949 (void) puts("s = overlapping-refresh test");
2950 #if USE_LIBMENU && defined(TRACE)
2951 (void) puts("t = set trace level");
2953 (void) puts("? = repeat this command summary");
2955 (void) fputs("> ", stdout);
2956 (void) fflush(stdout); /* necessary under SVr4 curses */
2959 * This used to be an 'fgets()' call. However (on Linux, at least)
2960 * mixing stream I/O and 'read()' (used in the library) causes the
2961 * input stream to be flushed when switching between the two.
2966 if (read(fileno(stdin), &ch, 1) <= 0) {
2970 } else if (command == 0 && !isspace(ch)) {
2972 } else if (ch == '\n' || ch == '\r') {
2975 (void) fputs("> ", stdout);
2976 (void) fflush(stdout);
2980 if (do_single_test(command)) {
2982 * This may be overkill; it's intended to reset everything back
2983 * to the initial terminal modes so that tests don't get in
2987 set_terminal_modes();
2997 ExitProgram(EXIT_SUCCESS);
3000 /* ncurses.c ends here */