X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=test%2Fncurses.c;h=aa24a4261809fb36b84f6589125c9ab6f745ed1c;hp=faef03dcf5011df9adf501c8f012477b1035389d;hb=0eb88fc5281804773e2a0c7a488a4452463535ce;hpb=3a9b6a3bf0269231bef7de74757a910dedd04e0c diff --git a/test/ncurses.c b/test/ncurses.c index faef03dc..aa24a426 100644 --- a/test/ncurses.c +++ b/test/ncurses.c @@ -1,3 +1,30 @@ +/**************************************************************************** + * Copyright (c) 1998,1999 Free Software Foundation, Inc. * + * * + * Permission is hereby granted, free of charge, to any person obtaining a * + * copy of this software and associated documentation files (the * + * "Software"), to deal in the Software without restriction, including * + * without limitation the rights to use, copy, modify, merge, publish, * + * distribute, distribute with modifications, sublicense, and/or sell * + * copies of the Software, and to permit persons to whom the Software is * + * furnished to do so, subject to the following conditions: * + * * + * The above copyright notice and this permission notice shall be included * + * in all copies or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * + * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * + * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + * * + * Except as contained in this notice, the name(s) of the above copyright * + * holders shall not be used in advertising or otherwise to promote the * + * sale, use or other dealings in this Software without prior written * + * authorization. * + ****************************************************************************/ /**************************************************************************** NAME @@ -10,11 +37,9 @@ DESCRIPTION An interactive test module for the ncurses library. AUTHOR - This software is Copyright (C) 1993 by Eric S. Raymond, all rights reserved. -It is issued with ncurses under the same terms and conditions as the ncurses -library source. + Author: Eric S. Raymond 1993 -$Id: ncurses.c,v 1.91 1997/05/10 18:19:48 tom Exp $ +$Id: ncurses.c,v 1.120 1999/10/23 20:01:30 tom Exp $ ***************************************************************************/ @@ -26,8 +51,12 @@ $Id: ncurses.c,v 1.91 1997/05/10 18:19:48 tom Exp $ #include #include +#if HAVE_LOCALE_H +#include +#endif + #if HAVE_GETTIMEOFDAY -#if HAVE_SYS_TIME_H && ! SYSTEM_LOOKS_LIKE_SCO +#if HAVE_SYS_TIME_H && HAVE_SYS_TIME_SELECT #include #endif #if HAVE_SYS_SELECT_H @@ -86,7 +115,6 @@ extern int _nc_tracing; #define CTRL(x) ((x) & 0x1f) #endif -#define SIZEOF(table) (sizeof(table)/sizeof(table[0])) #define QUIT CTRL('Q') #define ESCAPE CTRL('[') #define BLANK ' ' /* this is the background character */ @@ -157,6 +185,53 @@ static void ShellOut(bool message) refresh(); } +#ifdef NCURSES_MOUSE_VERSION +static const char *mouse_decode(MEVENT const *ep) +{ + static char buf[80]; + + (void) sprintf(buf, "id %2d at (%2d, %2d, %2d) state %4lx = {", + ep->id, ep->x, ep->y, ep->z, ep->bstate); + +#define SHOW(m, s) if ((ep->bstate & m)==m) {strcat(buf,s); strcat(buf, ", ");} + SHOW(BUTTON1_RELEASED, "release-1") + SHOW(BUTTON1_PRESSED, "press-1") + SHOW(BUTTON1_CLICKED, "click-1") + SHOW(BUTTON1_DOUBLE_CLICKED, "doubleclick-1") + SHOW(BUTTON1_TRIPLE_CLICKED, "tripleclick-1") + SHOW(BUTTON1_RESERVED_EVENT, "reserved-1") + SHOW(BUTTON2_RELEASED, "release-2") + SHOW(BUTTON2_PRESSED, "press-2") + SHOW(BUTTON2_CLICKED, "click-2") + SHOW(BUTTON2_DOUBLE_CLICKED, "doubleclick-2") + SHOW(BUTTON2_TRIPLE_CLICKED, "tripleclick-2") + SHOW(BUTTON2_RESERVED_EVENT, "reserved-2") + SHOW(BUTTON3_RELEASED, "release-3") + SHOW(BUTTON3_PRESSED, "press-3") + SHOW(BUTTON3_CLICKED, "click-3") + SHOW(BUTTON3_DOUBLE_CLICKED, "doubleclick-3") + SHOW(BUTTON3_TRIPLE_CLICKED, "tripleclick-3") + SHOW(BUTTON3_RESERVED_EVENT, "reserved-3") + SHOW(BUTTON4_RELEASED, "release-4") + SHOW(BUTTON4_PRESSED, "press-4") + SHOW(BUTTON4_CLICKED, "click-4") + SHOW(BUTTON4_DOUBLE_CLICKED, "doubleclick-4") + SHOW(BUTTON4_TRIPLE_CLICKED, "tripleclick-4") + SHOW(BUTTON4_RESERVED_EVENT, "reserved-4") + SHOW(BUTTON_CTRL, "ctrl") + SHOW(BUTTON_SHIFT, "shift") + SHOW(BUTTON_ALT, "alt") + SHOW(ALL_MOUSE_EVENTS, "all-events") + SHOW(REPORT_MOUSE_POSITION, "position") +#undef SHOW + + if (buf[strlen(buf)-1] == ' ') + buf[strlen(buf)-2] = '\0'; + (void) strcat(buf, "}"); + return(buf); +} +#endif /* NCURSES_MOUSE_VERSION */ + /**************************************************************************** * * Character input test @@ -203,7 +278,7 @@ int y, x; MEVENT event; getmouse(&event); - printw("KEY_MOUSE, %s\n", _tracemouse(&event)); + printw("KEY_MOUSE, %s\n", mouse_decode(&event)); } else #endif /* NCURSES_MOUSE_VERSION */ @@ -274,10 +349,13 @@ int y, x; endwin(); } -static int show_attr(int row, chtype attr, const char *name, bool once, const char *capname) +static int show_attr(int row, int skip, chtype attr, const char *name, bool once) { + int ncv = tigetnum("ncv"); + mvprintw(row, 8, "%s mode:", name); mvprintw(row, 24, "|"); + if (skip) printw("%*s", skip, " "); if (once) attron(attr); else @@ -285,38 +363,125 @@ static int show_attr(int row, chtype attr, const char *name, bool once, const ch addstr("abcde fghij klmno pqrst uvwxy z"); if (once) attroff(attr); + if (skip) printw("%*s", skip, " "); printw("|"); - if (capname != 0 && tigetstr(capname) == 0) - printw(" (N/A)"); + if (attr != A_NORMAL) { + if (!(termattrs() & attr)) { + printw(" (N/A)"); + } else if (ncv > 0 && (getbkgd(stdscr) & A_COLOR)) { + static const attr_t table[] = { + A_STANDOUT, + A_UNDERLINE, + A_REVERSE, + A_BLINK, + A_DIM, + A_BOLD, + A_INVIS, + A_PROTECT, + A_ALTCHARSET + }; + unsigned n; + bool found = FALSE; + for (n = 0; n < sizeof(table)/sizeof(table[0]); n++) { + if ((table[n] & attr) != 0 + && ((1 << n) & ncv) != 0) { + found = TRUE; + break; + } + } + if (found) + printw(" (NCV)"); + } + } return row + 2; } +static bool attr_getc(int *skip, int *fg, int *bg) +{ + int ch = Getchar(); + + if (isdigit(ch)) { + *skip = (ch - '0'); + return TRUE; + } else if (ch == CTRL('L')) { + touchwin(stdscr); + touchwin(curscr); + return TRUE; + } else if (has_colors()) { + switch (ch) { + case 'f': *fg = (*fg + 1); break; + case 'F': *fg = (*fg - 1); break; + case 'b': *bg = (*bg + 1); break; + case 'B': *bg = (*bg - 1); break; + default: + return FALSE; + } + if (*fg >= COLORS) *fg = 0; + if (*fg < 0) *fg = COLORS - 1; + if (*bg >= COLORS) *bg = 0; + if (*bg < 0) *bg = COLORS - 1; + return TRUE; + } + return FALSE; +} + static void attr_test(void) /* test text attributes */ { - int row = 2; - refresh(); + int n; + int skip = tigetnum("xmc"); + int fg = COLOR_BLACK; /* color pair 0 is special */ + int bg = COLOR_BLACK; + bool *pairs = (bool *)calloc(COLOR_PAIRS, sizeof(bool)); + pairs[0] = TRUE; + + if (skip < 0) + skip = 0; + + n = skip; /* make it easy */ + + do { + int row = 2; + int normal = A_NORMAL | BLANK; + + if (has_colors()) { + int pair = (fg * COLORS) + bg; + if (!pairs[pair]) { + init_pair(pair, fg, bg); + pairs[pair] = TRUE; + } + normal |= COLOR_PAIR(pair); + } + bkgdset(normal); + erase(); - mvaddstr(0, 20, "Character attribute test display"); + mvaddstr(0, 20, "Character attribute test display"); - row = show_attr(row, A_STANDOUT, "STANDOUT", TRUE, "smso"); - row = show_attr(row, A_REVERSE, "REVERSE", TRUE, "rev"); - row = show_attr(row, A_BOLD, "BOLD", TRUE, "bold"); - row = show_attr(row, A_UNDERLINE, "UNDERLINE", TRUE, "smul"); - row = show_attr(row, A_DIM, "DIM", TRUE, "dim"); - row = show_attr(row, A_BLINK, "BLINK", TRUE, "blink"); - row = show_attr(row, A_PROTECT, "PROTECT", TRUE, "prot"); - row = show_attr(row, A_INVIS, "INVISIBLE", TRUE, "invis"); - row = show_attr(row, A_NORMAL, "NORMAL", FALSE,0); + row = show_attr(row, n, A_STANDOUT, "STANDOUT", TRUE); + row = show_attr(row, n, A_REVERSE, "REVERSE", TRUE); + row = show_attr(row, n, A_BOLD, "BOLD", TRUE); + row = show_attr(row, n, A_UNDERLINE, "UNDERLINE", TRUE); + row = show_attr(row, n, A_DIM, "DIM", TRUE); + row = show_attr(row, n, A_BLINK, "BLINK", TRUE); + row = show_attr(row, n, A_PROTECT, "PROTECT", TRUE); + row = show_attr(row, n, A_INVIS, "INVISIBLE", TRUE); + row = show_attr(row, n, A_NORMAL, "NORMAL", FALSE); - mvprintw(row, 8, + mvprintw(row, 8, "This terminal does %shave the magic-cookie glitch", tigetnum("xmc") > -1 ? "" : "not "); + mvprintw(row+1, 8, + "Enter a digit to set gaps on each side of displayed attributes"); + mvprintw(row+2, 8, + "^L = repaint"); + if (has_colors()) + printw(". f/F/b/F toggle colors (now %d/%d)", fg, bg); - refresh(); - - Pause(); + refresh(); + } while (attr_getc(&n, &fg, &bg)); + free((char *)pairs); + bkgdset(A_NORMAL | BLANK); erase(); endwin(); } @@ -327,7 +492,7 @@ static void attr_test(void) * ****************************************************************************/ -static NCURSES_CONST char *colors[] = +static NCURSES_CONST char *color_names[] = { "black", "red", @@ -339,46 +504,52 @@ static NCURSES_CONST char *colors[] = "white" }; +static void show_color_name(int y, int x, int color) +{ + if (COLORS > 8) + mvprintw(y, x, "%02d ", color); + else + mvaddstr(y, x, color_names[color]); +} + static void color_test(void) /* generate a color test pattern */ { int i; + int base, top, width; + NCURSES_CONST char *hello; refresh(); (void) printw("There are %d color pairs\n", COLOR_PAIRS); - (void) mvprintw(1, 0, - "%dx%d matrix of foreground/background colors, bright *off*\n", - COLORS, COLORS); - for (i = 0; i < COLORS; i++) - mvaddstr(2, (i+1) * 8, colors[i]); - for (i = 0; i < COLORS; i++) - mvaddstr(3 + i, 0, colors[i]); - for (i = 1; i < COLOR_PAIRS; i++) - { - init_pair(i, i % COLORS, i / COLORS); - attron((attr_t)COLOR_PAIR(i)); - mvaddstr(3 + (i / COLORS), (i % COLORS + 1) * 8, "Hello"); - attrset(A_NORMAL); - } + width = (COLORS > 8) ? 4 : 8; + hello = (COLORS > 8) ? "Test" : "Hello"; - (void) mvprintw(COLORS + 4, 0, - "%dx%d matrix of foreground/background colors, bright *on*\n", - COLORS, COLORS); - for (i = 0; i < COLORS; i++) - mvaddstr(5 + COLORS, (i+1) * 8, colors[i]); - for (i = 0; i < COLORS; i++) - mvaddstr(6 + COLORS + i, 0, colors[i]); - for (i = 1; i < COLOR_PAIRS; i++) + for (base = 0; base < 2; base++) { - init_pair(i, i % COLORS, i / COLORS); - attron((attr_t)(COLOR_PAIR(i) | A_BOLD)); - mvaddstr(6 + COLORS + (i / COLORS), (i % COLORS + 1) * 8, "Hello"); - attrset(A_NORMAL); + top = (COLORS > 8) ? 0 : base * (COLORS+3); + clrtobot(); + (void) mvprintw(top + 1, 0, + "%dx%d matrix of foreground/background colors, bright *%s*\n", + COLORS, COLORS, + base ? "on" : "off"); + for (i = 0; i < COLORS; i++) + show_color_name(top + 2, (i+1) * width, i); + for (i = 0; i < COLORS; i++) + show_color_name(top + 3 + i, 0, i); + for (i = 1; i < COLOR_PAIRS; i++) + { + init_pair(i, i % COLORS, i / COLORS); + attron((attr_t)COLOR_PAIR(i)); + if (base) + attron((attr_t)A_BOLD); + mvaddstr(top + 3 + (i / COLORS), (i % COLORS + 1) * width, hello); + attrset(A_NORMAL); + } + if ((COLORS > 8) || base) + Pause(); } - Pause(); - erase(); endwin(); } @@ -432,8 +603,8 @@ static void color_edit(void) { mvprintw(2 + i, 0, "%c %-8s:", (i == current ? '>' : ' '), - (i < (int) SIZEOF(colors) - ? colors[i] : "")); + (i < (int) SIZEOF(color_names) + ? color_names[i] : "")); attrset(COLOR_PAIR(i)); addstr(" "); attrset(A_NORMAL); @@ -519,7 +690,7 @@ static void color_edit(void) P("currently selected will be reverse-video highlighted."); P(""); P("To change a field, enter the digits of the new value; they are echoed"); - P("echoed. Finish by typing `='; the change will take effect instantly."); + P("as entered. Finish by typing `='. The change will take effect instantly."); P("To increment or decrement a value, use the same procedure, but finish"); P("with a `+' or `-'."); P(""); @@ -1136,6 +1307,11 @@ static void acs_and_scroll(void) neww->next->last = neww; } current = neww; + /* SVr4 curses sets the keypad on all newly-created windows to + * false. Someone reported that PDCurses makes new windows inherit + * this flag. Remove the following 'keypad()' call to test this + */ + keypad(current->wind, TRUE); current->do_keypad = HaveKeypad(current); current->do_scroll = HaveScroll(current); break; @@ -1212,6 +1388,7 @@ static void acs_and_scroll(void) if (current) { pair *tmp, ul, lr; + int mx, my; move(0, 0); clrtoeol(); addstr("Use arrows to move cursor, anything else to mark new corner"); @@ -1233,15 +1410,16 @@ static void acs_and_scroll(void) wnoutrefresh(stdscr); /* strictly cosmetic hack for the test */ - if (current->wind->_maxy > tmp->y - ul.y) + getmaxyx(current->wind, my, mx); + if (my > tmp->y - ul.y) { getyx(current->wind, lr.y, lr.x); wmove(current->wind, tmp->y - ul.y + 1, 0); wclrtobot(current->wind); wmove(current->wind, lr.y, lr.x); } - if (current->wind->_maxx > tmp->x - ul.x) - for (i = 0; i < current->wind->_maxy; i++) + if (mx > tmp->x - ul.x) + for (i = 0; i < my; i++) { wmove(current->wind, i, tmp->x - ul.x + 1); wclrtoeol(current->wind); @@ -1314,7 +1492,7 @@ static void acs_and_scroll(void) usescr = (current ? current->wind : stdscr); wrefresh(usescr); } while - ((c = wGetchar(usescr)) + ((c = wGetchar(usescr)) != QUIT && !((c == ESCAPE) && (usescr->_use_keypad)) && (c != ERR)); @@ -1338,17 +1516,6 @@ static void acs_and_scroll(void) ****************************************************************************/ #if USE_LIBPANEL -static PANEL *p1; -static PANEL *p2; -static PANEL *p3; -static PANEL *p4; -static PANEL *p5; -static WINDOW *w1; -static WINDOW *w2; -static WINDOW *w3; -static WINDOW *w4; -static WINDOW *w5; - static unsigned long nap_msec = 1; static NCURSES_CONST char *mod[] = @@ -1397,17 +1564,24 @@ saywhat(NCURSES_CONST char *text) mkpanel(rows,cols,tly,tlx) - alloc a win and panel and associate them --------------------------------------------------------------------------*/ static PANEL * -mkpanel(int rows, int cols, int tly, int tlx) -{ -WINDOW *win = newwin(rows,cols,tly,tlx); -PANEL *pan; - - if(!win) - return((PANEL *)0); - if((pan = new_panel(win))) - return(pan); - delwin(win); - return((PANEL *)0); +mkpanel(int color, int rows, int cols, int tly, int tlx) +{ +WINDOW *win; +PANEL *pan = 0; + + if ((win = newwin(rows, cols, tly, tlx)) != 0) { + if ((pan = new_panel(win)) == 0) { + delwin(win); + } else if (has_colors()) { + int fg = (color == COLOR_BLUE) ? COLOR_WHITE : COLOR_BLACK; + int bg = color; + init_pair(color, fg, bg); + wbkgdset(win, COLOR_PAIR(color) | ' '); + } else { + wbkgdset(win, A_BOLD | ' '); + } + } + return pan; } /* end of mkpanel */ /*+------------------------------------------------------------------------- @@ -1441,9 +1615,10 @@ WINDOW *win = panel_window(pan); int num = ((const char *)panel_userptr(pan))[1]; int y,x; - box(win, 0, 0); wmove(win,1,1); wprintw(win,"-pan%c-", num); + wclrtoeol(win); + box(win, 0, 0); for(y = 2; y < getmaxy(win) - 1; y++) { for(x = 1; x < getmaxx(win) - 1; x++) @@ -1457,7 +1632,7 @@ int y,x; static void demo_panels(void) { int itmp; -register y,x; +register int y,x; refresh(); @@ -1468,24 +1643,25 @@ register y,x; } for(y = 0; y < 5; y++) { - p1 = mkpanel(LINES/2 - 2, COLS/8 + 1, 0, 0); - w1 = panel_window(p1); + PANEL *p1; + PANEL *p2; + PANEL *p3; + PANEL *p4; + PANEL *p5; + + p1 = mkpanel(COLOR_RED, LINES/2 - 2, COLS/8 + 1, 0, 0); set_panel_userptr(p1,"p1"); - p2 = mkpanel(LINES/2 + 1, COLS/7, LINES/4, COLS/10); - w2 = panel_window(p2); + p2 = mkpanel(COLOR_GREEN, LINES/2 + 1, COLS/7, LINES/4, COLS/10); set_panel_userptr(p2,"p2"); - p3 = mkpanel(LINES/4, COLS/10, LINES/2, COLS/9); - w3 = panel_window(p3); + p3 = mkpanel(COLOR_YELLOW, LINES/4, COLS/10, LINES/2, COLS/9); set_panel_userptr(p3,"p3"); - p4 = mkpanel(LINES/2 - 2, COLS/8, LINES/2 - 2, COLS/3); - w4 = panel_window(p4); + p4 = mkpanel(COLOR_BLUE, LINES/2 - 2, COLS/8, LINES/2 - 2, COLS/3); set_panel_userptr(p4,"p4"); - p5 = mkpanel(LINES/2 - 2, COLS/8, LINES/2, COLS/2 - 2); - w5 = panel_window(p5); + p5 = mkpanel(COLOR_MAGENTA, LINES/2 - 2, COLS/8, LINES/2, COLS/2 - 2); set_panel_userptr(p5,"p5"); fill_panel(p1); @@ -1576,6 +1752,9 @@ register y,x; for(itmp = 0; itmp < 6; itmp++) { + WINDOW *w4 = panel_window(p4); + WINDOW *w5 = panel_window(p5); + saywhat("m4; press any key to continue"); wmove(w4, LINES/8, 1); waddstr(w4,mod[itmp]); @@ -1584,6 +1763,7 @@ register y,x; waddstr(w5,mod[itmp]); pflush(); wait_a_while(nap_msec); + saywhat("m5; press any key to continue"); wmove(w4, LINES/6, 1); waddstr(w4,mod[itmp]); @@ -1869,8 +2049,8 @@ static void panner(WINDOW *pad, int length = (portx - top_x - 1); float ratio = ((float) length) / ((float) pxmax); - lowend = top_x + (basex * ratio); - highend = top_x + ((basex + length) * ratio); + lowend = (int)(top_x + (basex * ratio)); + highend = (int)(top_x + ((basex + length) * ratio)); do_h_line(porty - 1, top_x, ACS_HLINE, lowend); if (highend < portx) { @@ -1886,8 +2066,8 @@ static void panner(WINDOW *pad, int length = (porty - top_y - 1); float ratio = ((float) length) / ((float) pymax); - lowend = top_y + (basey * ratio); - highend = top_y + ((basey + length) * ratio); + lowend = (int)(top_y + (basey * ratio)); + highend = (int)(top_y + ((basey + length) * ratio)); do_v_line(top_y, portx - 1, ACS_VLINE, lowend); if (highend < porty) { @@ -1938,7 +2118,6 @@ int padgetch(WINDOW *win) { int c; - while(1) switch(c = wGetchar(win)) { case '!': ShellOut(FALSE); return KEY_REFRESH; @@ -2024,10 +2203,8 @@ static void flushinp_test(WINDOW *win) WINDOW *subWin; wclear (win); - w = win->_maxx; - h = win->_maxy; - bx = win->_begx; - by = win->_begy; + getmaxyx(win, h, w); + getbegyx(win, by, bx); sw = w / 3; sh = h / 3; if((subWin = subwin(win, sh, sw, by + h - sh - 2, bx + w - sw - 2)) == 0) @@ -2048,7 +2225,14 @@ static void flushinp_test(WINDOW *win) mvwaddstr(subWin, 2, 1, "This is a subwindow"); wrefresh(win); - nocbreak(); + /* + * This used to set 'nocbreak()'. However, Alexander Lukyanov says that + * it only happened to "work" on SVr4 because that implementation does not + * emulate nocbreak+noecho mode, whereas ncurses does. To get the desired + * test behavior, we're using 'cbreak()', which will allow a single + * character to return without needing a newline. - T.Dickey 1997/10/11. + */ + cbreak(); mvwaddstr(win, 0, 1, "This is a test of the flushinp() call."); mvwaddstr(win, 2, 1, "Type random keys for 5 seconds."); @@ -2113,14 +2297,25 @@ static int menu_virtualize(int c) { if (c == '\n' || c == KEY_EXIT) return(MAX_COMMAND + 1); + else if (c == 'u') + return(REQ_SCR_ULINE); + else if (c == 'd') + return(REQ_SCR_DLINE); + else if (c == 'b' || c == KEY_NPAGE) + return(REQ_SCR_UPAGE); + else if (c == 'f' || c == KEY_PPAGE) + return(REQ_SCR_DPAGE); else if (c == 'n' || c == KEY_DOWN) return(REQ_NEXT_ITEM); else if (c == 'p' || c == KEY_UP) return(REQ_PREV_ITEM); else if (c == ' ') return(REQ_TOGGLE_ITEM); - else + else { + if (c != KEY_MOUSE) + beep(); return(c); + } } static const char *animals[] = @@ -2135,13 +2330,17 @@ static void menu_test(void) ITEM *items[SIZEOF(animals)]; ITEM **ip = items; const char **ap; - int mrows, mcols; + int mrows, mcols, c; WINDOW *menuwin; +#ifdef NCURSES_MOUSE_VERSION + mousemask(ALL_MOUSE_EVENTS, (mmask_t *)0); +#endif mvaddstr(0, 0, "This is the menu test:"); mvaddstr(2, 0, " Use up and down arrow to move the select bar."); mvaddstr(3, 0, " 'n' and 'p' act like arrows."); - mvaddstr(4, 0, " Press return to exit."); + mvaddstr(4, 0, " 'b' and 'f' scroll up/down (page), 'u' and 'd' (line)."); + mvaddstr(5, 0, " Press return to exit."); refresh(); for (ap = animals; *ap; ap++) @@ -2150,6 +2349,7 @@ static void menu_test(void) m = new_menu(items); + set_menu_format(m, (SIZEOF(animals)+1)/2, 1); scale_menu(m, &mrows, &mcols); menuwin = newwin(mrows + 2, mcols + 2, MENU_Y, MENU_X); @@ -2161,8 +2361,11 @@ static void menu_test(void) post_menu(m); - while (menu_driver(m, menu_virtualize(wGetchar(menuwin))) != E_UNKNOWN_COMMAND) + while ((c = menu_driver(m, menu_virtualize(wGetchar(menuwin)))) != E_UNKNOWN_COMMAND) { + if (c == E_REQUEST_DENIED) + beep(); continue; + } (void) mvprintw(LINES - 2, 0, "You chose: %s\n", item_name(current_item(m))); @@ -2175,6 +2378,9 @@ static void menu_test(void) free_menu(m); for (ip = items; *ip; ip++) free_item(*ip); +#ifdef NCURSES_MOUSE_VERSION + mousemask(0, (mmask_t *)0); +#endif } #ifdef TRACE @@ -2209,7 +2415,7 @@ static char *tracetrace(int tlevel) size_t need = 12; for (n = 0; t_tbl[n].name != 0; n++) need += strlen(t_tbl[n].name) + 2; - buf = malloc(need); + buf = (char *)malloc(need); } sprintf(buf, "0x%02x = {", tlevel); if (tlevel == 0) { @@ -2353,12 +2559,14 @@ static FIELD *make_label(int frow, int fcol, NCURSES_CONST char *label) return(f); } -static FIELD *make_field(int frow, int fcol, int rows, int cols) +static FIELD *make_field(int frow, int fcol, int rows, int cols, bool secure) { - FIELD *f = new_field(rows, cols, frow, fcol, 0, 0); + FIELD *f = new_field(rows, cols, frow, fcol, 0, secure ? 1 : 0); - if (f) + if (f) { set_field_back(f, A_UNDERLINE); + set_field_userptr(f, (void *)0); + } return(f); } @@ -2393,101 +2601,142 @@ static void erase_form(FORM *f) delwin(w); } -static int form_virtualize(WINDOW *w) +static int edit_secure(FIELD *me, int c) { + int rows, cols, frow, fcol, nbuf; + + if (field_info(me, &rows, &cols, &frow, &fcol, (int *)0, &nbuf) == E_OK + && nbuf > 0) { + char temp[80]; + long len; + + strcpy(temp, field_buffer(me, 1)); + len = (long)(char *) field_userptr(me); + if (c <= KEY_MAX) { + if (isgraph(c)) { + temp[len++] = c; + temp[len] = 0; + set_field_buffer(me, 1, temp); + c = '*'; + } else { + c = 0; + } + } else { + switch (c) { + case REQ_BEG_FIELD: + case REQ_CLR_EOF: + case REQ_CLR_EOL: + case REQ_DEL_LINE: + case REQ_DEL_WORD: + case REQ_DOWN_CHAR: + case REQ_END_FIELD: + case REQ_INS_CHAR: + case REQ_INS_LINE: + case REQ_LEFT_CHAR: + case REQ_NEW_LINE: + case REQ_NEXT_WORD: + case REQ_PREV_WORD: + case REQ_RIGHT_CHAR: + case REQ_UP_CHAR: + c = 0; /* we don't want to do inline editing */ + break; + case REQ_CLR_FIELD: + if (len) { + temp[0] = 0; + set_field_buffer(me, 1, temp); + } + break; + case REQ_DEL_CHAR: + case REQ_DEL_PREV: + if (len) { + temp[--len] = 0; + set_field_buffer(me, 1, temp); + } + break; + } + } + set_field_userptr(me, (void *)len); + } + return c; +} + +static int form_virtualize(FORM *f, WINDOW *w) +{ + static const struct { + int code; + int result; + } lookup[] = { + { CTRL('A'), REQ_NEXT_CHOICE }, + { CTRL('B'), REQ_PREV_WORD }, + { CTRL('C'), REQ_CLR_EOL }, + { CTRL('D'), REQ_DOWN_FIELD }, + { CTRL('E'), REQ_END_FIELD }, + { CTRL('F'), REQ_NEXT_PAGE }, + { CTRL('G'), REQ_DEL_WORD }, + { CTRL('H'), REQ_DEL_PREV }, + { CTRL('I'), REQ_INS_CHAR }, + { CTRL('K'), REQ_CLR_EOF }, + { CTRL('L'), REQ_LEFT_FIELD }, + { CTRL('M'), REQ_NEW_LINE }, + { CTRL('N'), REQ_NEXT_FIELD }, + { CTRL('O'), REQ_INS_LINE }, + { CTRL('P'), REQ_PREV_FIELD }, + { CTRL('R'), REQ_RIGHT_FIELD }, + { CTRL('S'), REQ_BEG_FIELD }, + { CTRL('U'), REQ_UP_FIELD }, + { CTRL('V'), REQ_DEL_CHAR }, + { CTRL('W'), REQ_NEXT_WORD }, + { CTRL('X'), REQ_CLR_FIELD }, + { CTRL('Y'), REQ_DEL_LINE }, + { CTRL('Z'), REQ_PREV_CHOICE }, + { ESCAPE, MAX_FORM_COMMAND + 1 }, + { KEY_BACKSPACE, REQ_DEL_PREV }, + { KEY_DOWN, REQ_DOWN_CHAR }, + { KEY_END, REQ_LAST_FIELD }, + { KEY_HOME, REQ_FIRST_FIELD }, + { KEY_LEFT, REQ_LEFT_CHAR }, + { KEY_LL, REQ_LAST_FIELD }, + { KEY_NEXT, REQ_NEXT_FIELD }, + { KEY_NPAGE, REQ_NEXT_PAGE }, + { KEY_PPAGE, REQ_PREV_PAGE }, + { KEY_PREVIOUS, REQ_PREV_FIELD }, + { KEY_RIGHT, REQ_RIGHT_CHAR }, + { KEY_UP, REQ_UP_CHAR }, + { QUIT, MAX_FORM_COMMAND + 1 } + }; + static int mode = REQ_INS_MODE; int c = wGetchar(w); + unsigned n; + FIELD *me = current_field(f); - switch(c) - { - case QUIT: - case ESCAPE: - return(MAX_FORM_COMMAND + 1); - - /* demo doesn't use these three, leave them in anyway as sample code */ - case KEY_NPAGE: - case CTRL('F'): - return(REQ_NEXT_PAGE); - case KEY_PPAGE: - return(REQ_PREV_PAGE); - - case KEY_NEXT: - case CTRL('N'): - return(REQ_NEXT_FIELD); - case KEY_PREVIOUS: - case CTRL('P'): - return(REQ_PREV_FIELD); - - case KEY_HOME: - return(REQ_FIRST_FIELD); - case KEY_END: - case KEY_LL: - return(REQ_LAST_FIELD); - - case CTRL('L'): - return(REQ_LEFT_FIELD); - case CTRL('R'): - return(REQ_RIGHT_FIELD); - case CTRL('U'): - return(REQ_UP_FIELD); - case CTRL('D'): - return(REQ_DOWN_FIELD); - - case CTRL('W'): - return(REQ_NEXT_WORD); - case CTRL('B'): - return(REQ_PREV_WORD); - case CTRL('S'): - return(REQ_BEG_FIELD); - case CTRL('E'): - return(REQ_END_FIELD); - - case KEY_LEFT: - return(REQ_LEFT_CHAR); - case KEY_RIGHT: - return(REQ_RIGHT_CHAR); - case KEY_UP: - return(REQ_UP_CHAR); - case KEY_DOWN: - return(REQ_DOWN_CHAR); - - case CTRL('M'): - return(REQ_NEW_LINE); - case CTRL('I'): - return(REQ_INS_CHAR); - case CTRL('O'): - return(REQ_INS_LINE); - case CTRL('V'): - return(REQ_DEL_CHAR); - - case CTRL('H'): - case KEY_BACKSPACE: - return(REQ_DEL_PREV); - case CTRL('Y'): - return(REQ_DEL_LINE); - case CTRL('G'): - return(REQ_DEL_WORD); - - case CTRL('C'): - return(REQ_CLR_EOL); - case CTRL('K'): - return(REQ_CLR_EOF); - case CTRL('X'): - return(REQ_CLR_FIELD); - case CTRL('A'): - return(REQ_NEXT_CHOICE); - case CTRL('Z'): - return(REQ_PREV_CHOICE); - - case CTRL(']'): + if (c == CTRL(']')) { if (mode == REQ_INS_MODE) - return(mode = REQ_OVL_MODE); + mode = REQ_OVL_MODE; else - return(mode = REQ_INS_MODE); + mode = REQ_INS_MODE; + c = mode; + } else { + for (n = 0; n < sizeof(lookup)/sizeof(lookup[0]); n++) { + if (lookup[n].code == c) { + c = lookup[n].result; + break; + } + } + } - default: - return(c); + /* + * Force the field that the user is typing into to be in reverse video, + * while the other fields are shown underlined. + */ + if (c <= KEY_MAX) { + c = edit_secure(me, c); + set_field_back(me, A_REVERSE); + } else if (c <= MAX_FORM_COMMAND) { + c = edit_secure(me, c); + set_field_back(me, A_UNDERLINE); } + return c; } static int my_form_driver(FORM *form, int c) @@ -2506,10 +2755,9 @@ static void demo_forms(void) { WINDOW *w; FORM *form; - FIELD *f[10]; + FIELD *f[12], *secure; int finished = 0, c; - - mvaddstr(10, 57, "Forms Entry Test"); + unsigned n = 0; move(18, 0); addstr("Defined form-traversal keys: ^Q/ESC- exit form\n"); @@ -2523,19 +2771,25 @@ static void demo_forms(void) addstr("^G -- delete current word ^C -- clear to end of line\n"); addstr("^K -- clear to end of field ^X -- clear field\n"); addstr("Arrow keys move within a field as you would expect."); + + mvaddstr(4, 57, "Forms Entry Test"); + refresh(); /* describe the form */ - f[0] = make_label(0, 15, "Sample Form"); - f[1] = make_label(2, 0, "Last Name"); - f[2] = make_field(3, 0, 1, 18); - f[3] = make_label(2, 20, "First Name"); - f[4] = make_field(3, 20, 1, 12); - f[5] = make_label(2, 34, "Middle Name"); - f[6] = make_field(3, 34, 1, 12); - f[7] = make_label(5, 0, "Comments"); - f[8] = make_field(6, 0, 4, 46); - f[9] = (FIELD *)0; + f[n++] = make_label(0, 15, "Sample Form"); + f[n++] = make_label(2, 0, "Last Name"); + f[n++] = make_field(3, 0, 1, 18, FALSE); + f[n++] = make_label(2, 20, "First Name"); + f[n++] = make_field(3, 20, 1, 12, FALSE); + f[n++] = make_label(2, 34, "Middle Name"); + f[n++] = make_field(3, 34, 1, 12, FALSE); + f[n++] = make_label(5, 0, "Comments"); + f[n++] = make_field(6, 0, 4, 46, FALSE); + f[n++] = make_label(5, 20, "Password:"); + secure = + f[n++] = make_field(5, 30, 1, 9, TRUE); + f[n++] = (FIELD *)0; form = new_form(f); @@ -2545,9 +2799,12 @@ static void demo_forms(void) raw(); while (!finished) { - switch(form_driver(form, c = form_virtualize(w))) + switch(form_driver(form, c = form_virtualize(form, w))) { case E_OK: + mvaddstr(5, 57, field_buffer(secure, 1)); + clrtoeol(); + refresh(); break; case E_UNKNOWN_COMMAND: finished = my_form_driver(form, c); @@ -2576,11 +2833,13 @@ static void demo_forms(void) static void fillwin(WINDOW *win, char ch) { int y, x; + int y1, x1; - for (y = 0; y <= win->_maxy; y++) + getmaxyx(win, y1, x1); + for (y = 0; y < y1; y++) { wmove(win, y, 0); - for (x = 0; x <= win->_maxx; x++) + for (x = 0; x < x1; x++) waddch(win, ch); } } @@ -2588,12 +2847,14 @@ static void fillwin(WINDOW *win, char ch) static void crosswin(WINDOW *win, char ch) { int y, x; + int y1, x1; - for (y = 0; y <= win->_maxy; y++) + getmaxyx(win, y1, x1); + for (y = 0; y < y1; y++) { - for (x = 0; x <= win->_maxx; x++) - if (((x > win->_maxx / 3) && (x <= 2 * win->_maxx / 3)) - || (((y > win->_maxy / 3) && (y <= 2 * win->_maxy / 3)))) + for (x = 0; x < x1; x++) + if (((x > (x1 - 1) / 3) && (x <= (2 * (x1 - 1)) / 3)) + || (((y > (y1 - 1) / 3) && (y <= (2 * (y1 - 1)) / 3)))) { wmove(win, y, x); waddch(win, ch); @@ -2609,6 +2870,7 @@ static void overlap_test(void) WINDOW *win1 = newwin(9, 20, 3, 3); WINDOW *win2 = newwin(9, 20, 9, 16); + raw(); refresh(); move(0, 0); printw("This test shows the behavior of wnoutrefresh() with respect to\n"); @@ -2771,10 +3033,6 @@ do_single_test(const char c) #endif case '?': - (void) puts("This is the ncurses capability tester."); - (void) puts("You may select a test from the main menu by typing the"); - (void) puts("key letter of the choice (the letter to left of the =)"); - (void) puts("at the > prompt. The commands `x' or `q' will exit."); break; default: @@ -2853,6 +3111,10 @@ main(int argc, char *argv[]) int command, c; int my_e_param = 1; +#if HAVE_LOCALE_H + setlocale(LC_CTYPE, ""); +#endif + while ((c = getopt(argc, argv, "e:fhs:t:")) != EOF) { switch (c) { case 'e': @@ -2871,9 +3133,11 @@ main(int argc, char *argv[]) case 'h': ripoffline(1, rip_header); break; +#if USE_LIBPANEL case 's': nap_msec = atol(optarg); break; +#endif #ifdef TRACE case 't': save_trace = atoi(optarg); @@ -2922,7 +3186,16 @@ main(int argc, char *argv[]) */ endwin(); +#if HAVE_CURSES_VERSION + (void) printf("Welcome to %s. Press ? for help.\n", curses_version()); +#elif defined(NCURSES_VERSION_MAJOR) && defined(NCURSES_VERSION_MINOR) && defined(NCURSES_VERSION_PATCH) + (void) printf("Welcome to ncurses %d.%d.%d. Press ? for help.\n", + NCURSES_VERSION_MAJOR, + NCURSES_VERSION_MINOR, + NCURSES_VERSION_PATCH); +#else (void) puts("Welcome to ncurses. Press ? for help."); +#endif do { (void) puts("This is the ncurses main menu"); @@ -2989,6 +3262,12 @@ main(int argc, char *argv[]) clear(); refresh(); endwin(); + if (command == '?') { + (void) puts("This is the ncurses capability tester."); + (void) puts("You may select a test from the main menu by typing the"); + (void) puts("key letter of the choice (the letter to left of the =)"); + (void) puts("at the > prompt. The commands `x' or `q' will exit."); + } continue; } } while