]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - test/ncurses.c
ncurses 6.0 - patch 20170909
[ncurses.git] / test / ncurses.c
index d04effb40b63a44ec63fee897345dcf251ed737d..24a2f8779330c06b13c775ad233376b3c4d796ae 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998-2015,2016 Free Software Foundation, Inc.              *
+ * Copyright (c) 1998-2016,2017 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            *
@@ -40,7 +40,7 @@ AUTHOR
    Author: Eric S. Raymond <esr@snark.thyrsus.com> 1993
            Thomas E. Dickey (beginning revision 1.27 in 1996).
 
-$Id: ncurses.c,v 1.433 2016/04/24 01:00:06 tom Exp $
+$Id: ncurses.c,v 1.460 2017/09/09 22:52:38 tom Exp $
 
 ***************************************************************************/
 
@@ -77,7 +77,6 @@ $Id: ncurses.c,v 1.433 2016/04/24 01:00:06 tom Exp $
 
 #ifdef TRACE
 static unsigned save_trace = TRACE_ORDINARY | TRACE_ICALLS | TRACE_CALLS;
-extern unsigned _nc_tracing;
 #endif
 
 #else
@@ -142,7 +141,7 @@ extern unsigned _nc_tracing;
 #define state_unused
 #endif
 
-#define ToggleAcs(temp,real) temp = ((temp == real) ? 0 : real)
+#define ToggleAcs(temp,real) temp = ((temp == real) ? NULL : real)
 
 #define P(string)      printw("%s\n", string)
 
@@ -156,6 +155,7 @@ static bool use_colors;             /* true if we use colors */
 #undef max_pairs
 static int max_pairs;          /* ...and the number of color pairs */
 
+#if HAVE_COLOR_CONTENT
 typedef struct {
     NCURSES_COLOR_T red;
     NCURSES_COLOR_T green;
@@ -163,8 +163,10 @@ typedef struct {
 } RGB_DATA;
 
 static RGB_DATA *all_colors;
+#endif
 
 static void main_menu(bool);
+static void failed(const char *s) GCC_NORETURN;
 
 static void
 failed(const char *s)
@@ -174,35 +176,22 @@ failed(const char *s)
     ExitProgram(EXIT_FAILURE);
 }
 
-/* The behavior of mvhline, mvvline for negative/zero length is unspecified,
- * though we can rely on negative x/y values to stop the macro.
- */
-static void
-do_h_line(int y, int x, chtype c, int to)
-{
-    if ((to) > (x))
-       MvHLine(y, x, c, (to) - (x));
-}
-
-static void
-do_v_line(int y, int x, chtype c, int to)
-{
-    if ((to) > (y))
-       MvVLine(y, x, c, (to) - (y));
-}
-
 static void
 Repaint(void)
 {
     touchwin(stdscr);
+#if HAVE_CURSCR
     touchwin(curscr);
     wrefresh(curscr);
+#else
+    wrefresh(stdscr);
+#endif
 }
 
 static bool
-isQuit(int c)
+isQuit(int c, bool escape)
 {
-    return ((c) == QUIT || (c) == ESCAPE);
+    return ((c) == QUIT || (escape && ((c) == ESCAPE)));
 }
 #define case_QUIT      QUIT: case ESCAPE
 
@@ -515,10 +504,15 @@ mouse_decode(MEVENT const *ep)
 {
     static char buf[80 + (5 * 10) + (32 * 15)];
 
-    (void) sprintf(buf, "id %2d at (%2d, %2d, %d) state %4lx = {",
-                  ep->id, ep->x, ep->y, ep->z, (unsigned long) ep->bstate);
+    (void) _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf))
+                      "id %2d at (%2d, %2d, %d) state %4lx = {",
+                      ep->id, ep->x, ep->y, ep->z, (unsigned long) ep->bstate);
 
-#define SHOW(m, s) if ((ep->bstate & m)==m) {strcat(buf,s); strcat(buf, ", ");}
+#define SHOW(m, s) \
+       if ((ep->bstate & m)==m) { \
+               _nc_STRCAT(buf, s, sizeof(buf)); \
+               _nc_STRCAT(buf, ", ", sizeof(buf)); \
+       }
 
     SHOW(BUTTON1_RELEASED, "release-1");
     SHOW(BUTTON1_PRESSED, "press-1");
@@ -574,7 +568,7 @@ mouse_decode(MEVENT const *ep)
 
     if (buf[strlen(buf) - 1] == ' ')
        buf[strlen(buf) - 2] = '\0';
-    (void) strcat(buf, "}");
+    _nc_STRCAT(buf, "}", sizeof(buf));
     return (buf);
 }
 
@@ -652,6 +646,8 @@ blocking_getch(GetchFlags flags, int delay)
     return ((delay < 0) && flags['t']);
 }
 
+#define ExitOnEscape() (flags[UChar('k')] && flags[UChar('t')])
+
 static void
 wgetch_help(WINDOW *win, GetchFlags flags)
 {
@@ -678,13 +674,16 @@ wgetch_help(WINDOW *win, GetchFlags flags)
     printw("Type any key to see its %s value.  Also:\n",
           flags['k'] ? "keypad" : "literal");
     for (n = 0; n < SIZEOF(help); ++n) {
+       const char *msg = help[n];
        int row = 1 + (int) (n % chk);
        int col = (n >= chk) ? COLS / 2 : 0;
-       int flg = ((strstr(help[n], "toggle") != 0)
-                  && (flags[UChar(*help[n])] != FALSE));
+       int flg = ((strstr(msg, "toggle") != 0)
+                  && (flags[UChar(*msg)] != FALSE));
+       if (*msg == '^' && ExitOnEscape())
+           msg = "^[,^q -- quit";
        if (flg)
            (void) standout();
-       MvPrintw(row, col, "%s", help[n]);
+       MvPrintw(row, col, "%s", msg);
        if (col == 0)
            clrtoeol();
        if (flg)
@@ -842,7 +841,7 @@ wgetch_test(unsigned level, WINDOW *win, int delay)
        if (c == ERR && blocking_getch(flags, delay)) {
            wprintw(win, "ERR");
            wgetch_wrap(win, first_y);
-       } else if (isQuit(c)) {
+       } else if (isQuit(c, ExitOnEscape())) {
            break;
        } else if (c == 'e') {
            flags[UChar('e')] = !flags[UChar('e')];
@@ -1098,7 +1097,7 @@ wget_wch_test(unsigned level, WINDOW *win, int delay)
        if (code == ERR && blocking_getch(flags, delay)) {
            wprintw(win, "ERR");
            wgetch_wrap(win, first_y);
-       } else if (isQuit((int) c)) {
+       } else if (isQuit((int) c, ExitOnEscape())) {
            break;
        } else if (c == 'e') {
            flags[UChar('e')] = !flags[UChar('e')];
@@ -1301,7 +1300,7 @@ attr_legend(WINDOW *helpwin)
              "Toggles:");
     if (use_colors) {
        MvWPrintw(helpwin, row++, col,
-                 "  f/F/b/F toggle foreground/background background color");
+                 "  f/F/b/B toggle foreground/background background color");
        MvWPrintw(helpwin, row++, col,
                  "  t/T     toggle text/background color attribute");
     }
@@ -1564,7 +1563,7 @@ attr_getc(int *skip,
            case CTRL('L'):
                Repaint();
                break;
-           case '?':
+           case HELP_KEY_1:
                if ((helpwin = newwin(LINES - 1, COLS - 2, 0, 0)) != 0) {
                    box(helpwin, 0, 0);
                    attr_legend(helpwin);
@@ -1914,7 +1913,7 @@ wide_attr_getc(int *skip,
            case CTRL('L'):
                Repaint();
                break;
-           case '?':
+           case HELP_KEY_1:
                if ((helpwin = newwin(LINES - 1, COLS - 2, 0, 0)) != 0) {
                    box_set(helpwin, 0, 0);
                    attr_legend(helpwin);
@@ -2084,14 +2083,17 @@ show_color_name(int y, int x, int color, bool wide)
        int width = 8;
 
        if (wide) {
-           sprintf(temp, "%02d", color);
+           _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp))
+                       "%02d", color);
            width = 4;
        } else if (color >= 8) {
-           sprintf(temp, "[%02d]", color);
+           _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp))
+                       "[%02d]", color);
        } else if (color < 0) {
-           strcpy(temp, "default");
+           _nc_STRCPY(temp, "default", sizeof(temp));
        } else {
-           sprintf(temp, "%.*s", 16, the_color_names[color]);
+           _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp))
+                       "%.*s", 16, the_color_names[color]);
        }
        printw("%-*.*s", width, width, temp);
     }
@@ -2278,7 +2280,8 @@ color_test(void)
                    attron(A_REVERSE);
 
                if (opt_nums) {
-                   sprintf(numbered, "{%02X}", (int) i);
+                   _nc_SPRINTF(numbered, _nc_SLIMIT((size_t) (COLS + 1))
+                               "{%02X}", (int) i);
                    hello = numbered;
                }
                printw("%-*.*s", width, width, hello);
@@ -2372,7 +2375,7 @@ color_test(void)
                }
            }
            break;
-       case '?':
+       case HELP_KEY_1:
            if ((helpwin = newwin(LINES - 1, COLS - 2, 0, 0)) != 0) {
                box(helpwin, 0, 0);
                color_legend(helpwin, FALSE);
@@ -2502,7 +2505,9 @@ wide_color_test(void)
                    attr_on(A_REVERSE, NULL);
 
                if (opt_nums) {
-                   sprintf(numbered, "{%02X}", i);
+                   _nc_SPRINTF(numbered,
+                               _nc_SLIMIT((size_t) (COLS + 1) * sizeof(wchar_t))
+                               "{%02X}", i);
                    if (opt_xchr) {
                        make_fullwidth_text(buffer, numbered);
                    } else {
@@ -2606,7 +2611,7 @@ wide_color_test(void)
                }
            }
            break;
-       case '?':
+       case HELP_KEY_1:
            if ((helpwin = newwin(LINES - 1, COLS - 2, 0, 0)) != 0) {
                box(helpwin, 0, 0);
                color_legend(helpwin, TRUE);
@@ -2628,6 +2633,7 @@ wide_color_test(void)
 }
 #endif /* USE_WIDEC_SUPPORT */
 
+#if HAVE_COLOR_CONTENT
 static void
 change_color(NCURSES_PAIRS_T current, int field, int value, int usebase)
 {
@@ -2665,7 +2671,7 @@ reset_all_colors(void)
 
 #define okCOLOR(n) ((n) >= 0 && (n) < max_colors)
 #define okRGB(n)   ((n) >= 0 && (n) <= 1000)
-#define DecodeRGB(n) ((n * 1000) / 0xffff)
+#define DecodeRGB(n) (NCURSES_COLOR_T) ((n * 1000) / 0xffff)
 
 static void
 init_all_colors(bool xterm_colors, char *palette_file)
@@ -2687,13 +2693,14 @@ init_all_colors(bool xterm_colors, char *palette_file)
        int n;
        int got;
        char result[BUFSIZ];
-       int check_n, check_r, check_g, check_b;
+       int check_n;
+       unsigned check_r, check_g, check_b;
 
        raw();
        noecho();
        for (n = 0; n < max_colors; ++n) {
            fprintf(stderr, "\033]4;%d;?\007", n);
-           got = read(0, result, sizeof(result) - 1);
+           got = (int) read(0, result, sizeof(result) - 1);
            if (got < 0)
                break;
            result[got] = '\0';
@@ -2786,7 +2793,7 @@ color_edit(void)
             && (i < max_colors); i++) {
            char numeric[80];
 
-           sprintf(numeric, "[%d]", i);
+           _nc_SPRINTF(numeric, _nc_SLIMIT(sizeof(numeric)) "[%d]", i);
            MvPrintw(2 + i - top_color, 0, "%c %-8s:",
                     (i == current ? '>' : ' '),
                     (i < (int) SIZEOF(the_color_names)
@@ -2910,7 +2917,7 @@ color_edit(void)
            change_color((NCURSES_PAIRS_T) current, field, value, 0);
            break;
 
-       case '?':
+       case HELP_KEY_1:
            erase();
            P("                      RGB Value Editing Help");
            P("");
@@ -2962,7 +2969,7 @@ color_edit(void)
        MvPrintw(LINES - 1, 0, "Number: %d", value);
        clrtoeol();
     } while
-       (!isQuit(this_c));
+       (!isQuit(this_c, TRUE));
 
     erase();
 
@@ -2973,6 +2980,7 @@ color_edit(void)
 
     endwin();
 }
+#endif /* HAVE_COLOR_CONTENT */
 
 /****************************************************************************
  *
@@ -3154,7 +3162,7 @@ slk_test(void)
        case 's':
            MvPrintw(SLK_WORK, 0, "Press Q to stop the scrolling-test: ");
            while ((c = Getchar()) != 'Q' && (c != ERR))
-               addch((chtype) c);
+               AddCh(c);
            break;
 
        case 'd':
@@ -3182,9 +3190,9 @@ slk_test(void)
        case '7':
        case '8':
            MvAddStr(SLK_WORK, 0, "Please enter the label value: ");
-           strcpy(buf, "");
+           _nc_STRCPY(buf, "", sizeof(buf));
            if ((s = slk_label(c - '0')) != 0) {
-               strncpy(buf, s, (size_t) 8);
+               _nc_STRNCPY(buf, s, (size_t) 8);
            }
            wGetstring(stdscr, buf, 8);
            slk_set((c - '0'), buf, fmt);
@@ -3222,7 +3230,7 @@ slk_test(void)
            beep();
            break;
        }
-    } while (!isQuit(c = Getchar()));
+    } while (!isQuit(c = Getchar(), TRUE));
 
   done:
     slk_clear();
@@ -3274,7 +3282,7 @@ wide_slk_test(void)
        case 's':
            MvPrintw(SLK_WORK, 0, "Press Q to stop the scrolling-test: ");
            while ((c = Getchar()) != 'Q' && (c != ERR))
-               addch((chtype) c);
+               AddCh(c);
            break;
 
        case 'd':
@@ -3376,7 +3384,7 @@ wide_slk_test(void)
            beep();
            break;
        }
-    } while (!isQuit(c = Getchar()));
+    } while (!isQuit(c = Getchar(), TRUE));
 
   done:
     slk_clear();
@@ -3406,7 +3414,7 @@ show_256_chars(int repeat, attr_t attr, NCURSES_PAIRS_T pair)
        int col = (int) (5 * (code % 16));
        IGNORE_RC(mvaddch(row, col, colored_chtype(code, attr, pair)));
        for (count = 1; count < repeat; ++count) {
-           addch(colored_chtype(code, attr, pair));
+           AddCh(colored_chtype(code, attr, pair));
        }
     }
 
@@ -3440,7 +3448,7 @@ show_upper_chars(int base, int pagesize, int repeat, attr_t attr, NCURSES_PAIRS_
        int row = 2 + ((int) (code - first) % (pagesize / 2));
        int col = ((int) (code - first) / (pagesize / 2)) * COLS / 2;
        char tmp[80];
-       sprintf(tmp, "%3u (0x%x)", code, code);
+       _nc_SPRINTF(tmp, _nc_SLIMIT(sizeof(tmp)) "%3u (0x%x)", code, code);
        MvPrintw(row, col, "%*s: ", COLS / 4, tmp);
 
        do {
@@ -3450,7 +3458,7 @@ show_upper_chars(int base, int pagesize, int repeat, attr_t attr, NCURSES_PAIRS_
            if (C1) {
                /* (yes, this _is_ crude) */
                while ((reply = Getchar()) != ERR) {
-                   addch(UChar(reply));
+                   AddCh(UChar(reply));
                    napms(10);
                }
                nodelay(stdscr, FALSE);
@@ -3495,7 +3503,7 @@ show_pc_chars(int repeat, attr_t attr, NCURSES_PAIRS_T pair)
                 */
                break;
            default:
-               addch(colored_chtype(code, A_ALTCHARSET | attr, pair));
+               AddCh(colored_chtype(code, A_ALTCHARSET | attr, pair));
                break;
            }
        } while (--count > 0);
@@ -3544,7 +3552,7 @@ show_1_acs(int n, int repeat, const char *name, chtype code)
 
     MvPrintw(row, col, "%*s : ", COLS / 4, name);
     do {
-       addch(code);
+       AddCh(code);
     } while (--repeat > 0);
     return n + 1;
 }
@@ -3716,7 +3724,7 @@ acs_display(void)
                     my_list[at_code].name);
        }
        refresh();
-    } while (!isQuit(c = Getchar()));
+    } while (!isQuit(c = Getchar(), TRUE));
 
     Pause();
     erase();
@@ -3778,7 +3786,7 @@ show_paged_widechars(int base,
        setcchar(&temp, codes, attr, pair, 0);
        move(row, col);
        if (wcwidth(code) == 0 && code != 0) {
-           addch((chtype) space |
+           AddCh((chtype) space |
                  (A_REVERSE ^ attr) |
                  (attr_t) COLOR_PAIR(pair));
        }
@@ -3809,7 +3817,8 @@ show_upper_widechars(int first, int repeat, int space, attr_t attr, NCURSES_PAIR
        int count = repeat;
        int y, x;
 
-       sprintf(tmp, "%3ld (0x%lx)", (long) code, (long) code);
+       _nc_SPRINTF(tmp, _nc_SLIMIT(sizeof(tmp))
+                   "%3ld (0x%lx)", (long) code, (long) code);
        MvPrintw(row, col, "%*s: ", COLS / 4, tmp);
 
        memset(&codes, 0, sizeof(codes));
@@ -3824,7 +3833,7 @@ show_upper_widechars(int first, int repeat, int space, attr_t attr, NCURSES_PAIR
             * the display.
             */
            if (wcwidth(code) == 0) {
-               addch((chtype) space |
+               AddCh((chtype) space |
                      (A_REVERSE ^ attr) |
                      (attr_t) COLOR_PAIR(pair));
            }
@@ -3965,7 +3974,7 @@ show_wacs_chars_double(int repeat, attr_t attr, NCURSES_PAIRS_T pair)
     n = show_1_wacs(n, repeat, BOTH2(WACS_DEGREE));
     n = show_1_wacs(n, repeat, BOTH2(WACS_DIAMOND));
     n = show_1_wacs(n, repeat, BOTH2(WACS_PLMINUS));
-    n = show_1_wacs(n, repeat, BOTH2(WACS_PLUS));
+    n = show_1_wacs(n, repeat, BOTH2(WACS_D_PLUS));
 
 #ifdef CURSES_WACS_ARRAY
     n = show_1_wacs(n, repeat, BOTH2(WACS_GEQUAL));
@@ -4026,7 +4035,7 @@ show_wacs_chars_thick(int repeat, attr_t attr, NCURSES_PAIRS_T pair)
     n = show_1_wacs(n, repeat, BOTH2(WACS_DEGREE));
     n = show_1_wacs(n, repeat, BOTH2(WACS_DIAMOND));
     n = show_1_wacs(n, repeat, BOTH2(WACS_PLMINUS));
-    n = show_1_wacs(n, repeat, BOTH2(WACS_PLUS));
+    n = show_1_wacs(n, repeat, BOTH2(WACS_T_PLUS));
 
 #ifdef CURSES_WACS_ARRAY
     n = show_1_wacs(n, repeat, BOTH2(WACS_GEQUAL));
@@ -4092,7 +4101,8 @@ show_2_wacs(int n, const char *name, const char *code, attr_t attr, NCURSES_PAIR
 
     MvPrintw(row, col, "%*s : ", COLS / 4, name);
     (void) attr_set(attr, pair, 0);
-    addstr(strncpy(temp, code, 20));
+    _nc_STRNCPY(temp, code, 20);
+    addstr(temp);
     (void) attr_set(A_NORMAL, 0, 0);
     return n + 1;
 }
@@ -4251,7 +4261,7 @@ wide_acs_display(void)
                     my_list[at_code].name);
        }
        refresh();
-    } while (!isQuit(c = Getchar()));
+    } while (!isQuit(c = Getchar(), TRUE));
 
     Pause();
     erase();
@@ -4361,13 +4371,10 @@ FRAME
     WINDOW *wind;
 };
 
-#if defined(NCURSES_VERSION)
-#if (NCURSES_VERSION_PATCH < 20070331) && NCURSES_EXT_FUNCS
+#if defined(NCURSES_VERSION) && NCURSES_EXT_FUNCS
+#if (NCURSES_VERSION_PATCH < 20070331)
 #define is_keypad(win)   (win)->_use_keypad
 #define is_scrollok(win) (win)->_scroll
-#elif !defined(is_keypad)
-#define is_keypad(win)   FALSE
-#define is_scrollok(win) FALSE
 #endif
 #else
 #define is_keypad(win)   FALSE
@@ -4403,46 +4410,26 @@ HaveScroll(FRAME * curp)
 static void
 newwin_legend(FRAME * curp)
 {
+#define DATA(num, name) { name, num }
     static const struct {
        const char *msg;
        int code;
     } legend[] = {
-       {
-           "^C = create window", 0
-       },
-       {
-           "^N = next window", 0
-       },
-       {
-           "^P = previous window", 0
-       },
-       {
-           "^F = scroll forward", 0
-       },
-       {
-           "^B = scroll backward", 0
-       },
-       {
-           "^K = keypad(%s)", 1
-       },
-       {
-           "^S = scrollok(%s)", 2
-       },
-       {
-           "^W = save window to file", 0
-       },
-       {
-           "^R = restore window", 0
-       },
+       DATA(0, "^C = create window"),
+           DATA(0, "^N = next window"),
+           DATA(0, "^P = previous window"),
+           DATA(0, "^F = scroll forward"),
+           DATA(0, "^B = scroll backward"),
+           DATA(1, "^K = keypad(%s)"),
+           DATA(2, "^S = scrollok(%s)"),
+           DATA(0, "^W = save window"),
+           DATA(0, "^R = restore window"),
 #if HAVE_WRESIZE
-       {
-           "^X = resize", 0
-       },
+           DATA(0, "^X = resize"),
 #endif
-       {
-           "^Q%s = exit", 3
-       }
+           DATA(3, "^Q%s = exit")
     };
+#undef DATA
     size_t n;
     int x;
     bool do_keypad = HaveKeypad(curp);
@@ -4453,16 +4440,19 @@ newwin_legend(FRAME * curp)
     for (n = 0; n < SIZEOF(legend); n++) {
        switch (legend[n].code) {
        default:
-           strcpy(buf, legend[n].msg);
+           _nc_STRCPY(buf, legend[n].msg, sizeof(buf));
            break;
        case 1:
-           sprintf(buf, legend[n].msg, do_keypad ? "yes" : "no");
+           _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf))
+                       legend[n].msg, do_keypad ? "yes" : "no");
            break;
        case 2:
-           sprintf(buf, legend[n].msg, do_scroll ? "yes" : "no");
+           _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf))
+                       legend[n].msg, do_scroll ? "yes" : "no");
            break;
        case 3:
-           sprintf(buf, legend[n].msg, do_keypad ? "/ESC" : "");
+           _nc_SPRINTF(buf, _nc_SLIMIT(sizeof(buf))
+                       legend[n].msg, do_keypad ? "/ESC" : "");
            break;
        }
        x = getcurx(stdscr);
@@ -4551,8 +4541,8 @@ selectcell(int uli, int ulj, int lri, int lrj)
                    break;
                }
            }
-           /* FALLTHRU */
 #endif
+           /* FALLTHRU */
        default:
            res.y = uli + i;
            res.x = ulj + j;
@@ -4653,7 +4643,7 @@ delete_framed(FRAME * fp, bool showit)
        }
        delwin(fp->wind);
 
-       np = (fp == fp->next) ? 0 : fp->next;
+       np = (fp == fp->next) ? NULL : fp->next;
        free(fp);
     }
     return np;
@@ -4752,10 +4742,14 @@ acs_and_scroll(void)
            } else if ((fp = fopen(DUMPFILE, "w")) == (FILE *) 0) {
                transient(current, "Can't open screen dump file");
            } else {
-               (void) putwin(frame_win(current), fp);
+               int rc = putwin(frame_win(current), fp);
                (void) fclose(fp);
 
-               current = delete_framed(current, TRUE);
+               if (rc == OK) {
+                   current = delete_framed(current, TRUE);
+               } else {
+                   transient(current, "Can't write screen dump file");
+               }
            }
            break;
 
@@ -4841,12 +4835,6 @@ acs_and_scroll(void)
            break;
 #endif /* HAVE_WRESIZE */
 
-       case KEY_F(10): /* undocumented --- use this to test area clears */
-           selectcell(0, 0, LINES - 1, COLS - 1);
-           clrtobot();
-           refresh();
-           break;
-
        case KEY_UP:
            newwin_move(current, -1, 0);
            break;
@@ -4890,7 +4878,7 @@ acs_and_scroll(void)
        usescr = frame_win(current);
        wrefresh(usescr);
     } while
-       (!isQuit(c = wGetchar(usescr))
+       (!isQuit(c = wGetchar(usescr), TRUE)
         && (c != ERR));
 
   breakout:
@@ -4992,7 +4980,7 @@ mkpanel(NCURSES_COLOR_T color, int rows, int cols, int tly, int tlx)
        rmpanel(pan)
 --------------------------------------------------------------------------*/
 static void
-rmpanel(PANEL * pan)
+rmpanel(PANEL *pan)
 {
     WINDOW *win = panel_window(pan);
     del_panel(pan);
@@ -5024,7 +5012,7 @@ init_panel(WINDOW *win)
 }
 
 static void
-fill_panel(PANEL * pan)
+fill_panel(PANEL *pan)
 {
     WINDOW *win = panel_window(pan);
     const char *userptr = (const char *) panel_userptr(pan);
@@ -5061,7 +5049,7 @@ init_wide_panel(WINDOW *win)
 }
 
 static void
-fill_wide_panel(PANEL * pan)
+fill_wide_panel(PANEL *pan)
 {
     WINDOW *win = panel_window(pan);
     const char *userptr = (const char *) panel_userptr(pan);
@@ -5084,7 +5072,7 @@ fill_wide_panel(PANEL * pan)
 #define MAX_PANELS 5
 
 static void
-canned_panel(PANEL * px[MAX_PANELS + 1], NCURSES_CONST char *cmd)
+canned_panel(PANEL *px[MAX_PANELS + 1], NCURSES_CONST char *cmd)
 {
     int which = cmd[1] - '0';
 
@@ -5258,6 +5246,25 @@ demo_panels(void (*InitPanel) (WINDOW *), void (*FillPanel) (PANEL *))
  *
  ****************************************************************************/
 
+#if HAVE_NEWPAD
+
+/* The behavior of mvhline, mvvline for negative/zero length is unspecified,
+ * though we can rely on negative x/y values to stop the macro.
+ */
+static void
+do_h_line(int y, int x, chtype c, int to)
+{
+    if ((to) > (x))
+       MvHLine(y, x, c, (to) - (x));
+}
+
+static void
+do_v_line(int y, int x, chtype c, int to)
+{
+    if ((to) > (y))
+       MvVLine(y, x, c, (to) - (y));
+}
+
 #define GRIDSIZE       3
 
 static bool pending_pan = FALSE;
@@ -5374,8 +5381,8 @@ panner(WINDOW *pad,
            erase();
 
            /* FALLTHRU */
-       case '?':
-           if (c == '?')
+       case HELP_KEY_1:
+           if (c == HELP_KEY_1)
                show_panner_legend = !show_panner_legend;
            panner_legend(LINES - 4);
            panner_legend(LINES - 3);
@@ -5706,6 +5713,7 @@ demo_pad(bool colored)
     endwin();
     erase();
 }
+#endif /* HAVE_NEWPAD */
 
 /****************************************************************************
  *
@@ -5958,29 +5966,31 @@ static char *
 tracetrace(unsigned tlevel)
 {
     static char *buf;
+    static size_t need = 12;
     int n;
 
     if (buf == 0) {
-       size_t need = 12;
        for (n = 0; t_tbl[n].name != 0; n++)
            need += strlen(t_tbl[n].name) + 2;
        buf = typeMalloc(char, need);
        if (!buf)
            failed("tracetrace");
     }
-    sprintf(buf, "0x%02x = {", tlevel);
+    _nc_SPRINTF(buf, _nc_SLIMIT(need) "0x%02x = {", tlevel);
     if (tlevel == 0) {
-       sprintf(buf + strlen(buf), "%s, ", t_tbl[0].name);
+       _nc_STRCAT(buf, t_tbl[0].name, need);
+       _nc_STRCAT(buf, ", ", need);
     } else {
        for (n = 1; t_tbl[n].name != 0; n++)
            if ((tlevel & t_tbl[n].mask) == t_tbl[n].mask) {
-               strcat(buf, t_tbl[n].name);
-               strcat(buf, ", ");
+               _nc_STRCAT(buf, t_tbl[n].name, need);
+               _nc_STRCAT(buf, ", ", need);
            }
     }
     if (buf[strlen(buf) - 2] == ',')
        buf[strlen(buf) - 2] = '\0';
-    return (strcat(buf, "}"));
+    _nc_STRCAT(buf, "}", need);
+    return buf;
 }
 
 /* fake a dynamically reconfigurable menu using the 0th entry to deselect
@@ -6128,7 +6138,7 @@ make_field(int frow, int fcol, int rows, int cols, bool secure)
 }
 
 static void
-display_form(FORM * f)
+display_form(FORM *f)
 {
     WINDOW *w;
     int rows, cols;
@@ -6146,7 +6156,7 @@ display_form(FORM * f)
 }
 
 static void
-erase_form(FORM * f)
+erase_form(FORM *f)
 {
     WINDOW *w = form_win(f);
     WINDOW *s = form_sub(f);
@@ -6159,7 +6169,7 @@ erase_form(FORM * f)
 }
 
 static int
-edit_secure(FIELD * me, int c)
+edit_secure(FIELD *me, int c)
 {
     int rows, cols, frow, fcol, nrow, nbuf;
 
@@ -6172,7 +6182,7 @@ edit_secure(FIELD * me, int c)
        size_t len;
 
        if (temp != 0) {
-           strncpy(temp, source ? source : "", have + 1);
+           _nc_STRNCPY(temp, source ? source : "", have + 1);
            len = (size_t) (char *) field_userptr(me);
            if (c <= KEY_MAX) {
                if (isgraph(c) && (len + 1) < sizeof(temp)) {
@@ -6225,7 +6235,7 @@ edit_secure(FIELD * me, int c)
 }
 
 static int
-form_virtualize(FORM * f, WINDOW *w)
+form_virtualize(FORM *f, WINDOW *w)
 {
     /* *INDENT-OFF* */
     static const struct {
@@ -6332,7 +6342,7 @@ form_virtualize(FORM * f, WINDOW *w)
 }
 
 static int
-my_form_driver(FORM * form, int c)
+my_form_driver(FORM *form, int c)
 {
     if (c == (MAX_FORM_COMMAND + 1)
        && form_driver(form, REQ_VALIDATION) == E_OK)
@@ -6520,6 +6530,7 @@ demo_forms(void)
  *
  ****************************************************************************/
 
+#if HAVE_COPYWIN               /* ...and overlay, overwrite */
 static void
 fillwin(WINDOW *win, char ch)
 {
@@ -6632,7 +6643,8 @@ overlap_help(int state, int flavors[OVERLAP_FLAVORS])
        switch (row) {
        case 0:
            flavors[row] = 0;
-           sprintf(msg, "refresh %s, then %s, then doupdate.", ths, tht);
+           _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+                       "refresh %s, then %s, then doupdate.", ths, tht);
            break;
        case 1:
            if (use_colors) {
@@ -6641,7 +6653,8 @@ overlap_help(int state, int flavors[OVERLAP_FLAVORS])
                flavors[row] %= 2;
            }
            overlap_test_1_attr(stdscr, flavors[row], col);
-           sprintf(msg, "fill window %s with letter %s.", ths, ths);
+           _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+                       "fill window %s with letter %s.", ths, ths);
            break;
        case 2:
            if (use_colors) {
@@ -6651,37 +6664,46 @@ overlap_help(int state, int flavors[OVERLAP_FLAVORS])
            }
            switch (flavors[row]) {
            case 0:
-               sprintf(msg, "cross pattern in window %s.", ths);
+               _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+                           "cross pattern in window %s.", ths);
                break;
            case 1:
-               sprintf(msg, "draw box in window %s.", ths);
+               _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+                           "draw box in window %s.", ths);
                break;
            case 2:
-               sprintf(msg, "set background of window %s.", ths);
+               _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+                           "set background of window %s.", ths);
                break;
            case 3:
-               sprintf(msg, "reset background of window %s.", ths);
+               _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+                           "reset background of window %s.", ths);
                break;
            }
            break;
        case 3:
            flavors[row] = 0;
-           sprintf(msg, "clear window %s.", ths);
+           _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+                       "clear window %s.", ths);
            break;
        case 4:
            flavors[row] %= 4;
            switch (flavors[row]) {
            case 0:
-               sprintf(msg, "overwrite %s onto %s.", ths, tht);
+               _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+                           "overwrite %s onto %s.", ths, tht);
                break;
            case 1:
-               sprintf(msg, "copywin(FALSE) %s onto %s.", ths, tht);
+               _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+                           "copywin(FALSE) %s onto %s.", ths, tht);
                break;
            case 2:
-               sprintf(msg, "copywin(TRUE) %s onto %s.", ths, tht);
+               _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+                           "copywin(TRUE) %s onto %s.", ths, tht);
                break;
            case 3:
-               sprintf(msg, "overlay %s onto %s.", ths, tht);
+               _nc_SPRINTF(msg, _nc_SLIMIT(sizeof(msg))
+                           "overlay %s onto %s.", ths, tht);
                break;
            }
            break;
@@ -6782,7 +6804,7 @@ overlap_test(void)
     memset(flavor, 0, sizeof(flavor));
     state = overlap_help(0, flavor);
 
-    while (!isQuit(ch = Getchar()))
+    while (!isQuit(ch = Getchar(), TRUE))
        switch (ch) {
        case 'a':               /* refresh window A first, then B */
            overlap_test_0(win1, win2);
@@ -6839,7 +6861,7 @@ overlap_test(void)
            state = overlap_help(state, flavor);
            break;
 
-       case '?':
+       case HELP_KEY_1:
            state = overlap_help(state, flavor);
            break;
 
@@ -6851,8 +6873,91 @@ overlap_test(void)
     delwin(win2);
     delwin(win1);
     erase();
-    curs_set(1);
-    endwin();
+    exit_curses();
+}
+
+#endif /* HAVE_COPYWIN */
+
+static void
+show_setting_name(const char *name)
+{
+    printw("%-25s ", name);
+}
+
+static void
+show_string_setting(const char *name, const char *value)
+{
+    show_setting_name(name);
+    if (value) {
+       printw("\"%s\"", value);
+    } else {
+       attron(A_REVERSE);
+       addstr("<NULL>");
+       attroff(A_REVERSE);
+    }
+    AddCh('\n');
+}
+
+static void
+show_number_setting(const char *name, int value)
+{
+    show_setting_name(name);
+    if (value >= 0) {
+       printw("%d", value);
+    } else {
+       attron(A_REVERSE);
+       printw("%d", value);
+       attroff(A_REVERSE);
+    }
+    AddCh('\n');
+}
+
+static void
+show_boolean_setting(const char *name, int value)
+{
+    show_setting_name(name);
+    if (value >= 0) {
+       printw("%s", value ? "TRUE" : "FALSE");
+    } else {
+       attron(A_REVERSE);
+       printw("%d", value);
+       attroff(A_REVERSE);
+    }
+    AddCh('\n');
+}
+
+static void
+show_settings(void)
+{
+#if USE_WIDEC_SUPPORT
+    wchar_t ch;
+#endif
+
+    move(0, 0);
+    show_string_setting("termname", termname());
+    show_string_setting("longname", longname());
+    show_number_setting("baudrate", baudrate());
+    if (erasechar() > 0) {
+       show_string_setting("unctrl(erasechar)", unctrl((chtype) erasechar()));
+       show_string_setting("keyname(erasechar)", keyname(erasechar()));
+    }
+    if (killchar() > 0) {
+       show_string_setting("unctrl(killchar)", unctrl((chtype) killchar()));
+       show_string_setting("keyname(killchar)", keyname(killchar()));
+    }
+#if USE_WIDEC_SUPPORT
+    if (erasewchar(&ch) == OK) {
+       show_string_setting("key_name(erasewchar)", key_name(ch));
+    }
+    if (killwchar(&ch) == OK) {
+       show_string_setting("key_name(killwchar)", key_name(ch));
+    }
+#endif
+    show_boolean_setting("has_ic", has_ic());
+    show_boolean_setting("has_il", has_il());
+    Pause();
+    erase();
+    exit_curses();
 }
 
 /****************************************************************************
@@ -6902,6 +7007,7 @@ do_single_test(const char c)
        break;
 #endif
 
+#if HAVE_COLOR_CONTENT
     case 'd':
        if (!use_colors)
            Cannot("does not support color.");
@@ -6910,6 +7016,7 @@ do_single_test(const char c)
        else
            color_edit();
        break;
+#endif
 
 #if USE_SOFTKEYS
     case 'e':
@@ -6963,6 +7070,7 @@ do_single_test(const char c)
        break;
 #endif
 
+#if HAVE_NEWPAD
     case 'p':
        demo_pad(FALSE);
        break;
@@ -6970,6 +7078,7 @@ do_single_test(const char c)
     case 'P':
        demo_pad(TRUE);
        break;
+#endif
 
 #if USE_LIBFORM
     case 'r':
@@ -6977,9 +7086,11 @@ do_single_test(const char c)
        break;
 #endif
 
+#if HAVE_COPYWIN
     case 's':
        overlap_test();
        break;
+#endif
 
 #if USE_LIBMENU && defined(TRACE)
     case 't':
@@ -6987,6 +7098,10 @@ do_single_test(const char c)
        break;
 #endif
 
+    case 'v':
+       show_settings();
+       break;
+
     case '?':
        break;
 
@@ -7020,7 +7135,9 @@ usage(void)
        ,"  -h       rip-off header line (can repeat)"
 #endif
        ,"  -m       do not use colors"
+#if HAVE_COLOR_CONTENT
        ,"  -p file  rgb values to use in 'd' rather than ncurses's builtin"
+#endif
 #if USE_LIBPANEL
        ,"  -s msec  specify nominal time for panel-demo (default: 1, to hold)"
 #endif
@@ -7030,7 +7147,9 @@ usage(void)
 #ifdef TRACE
        ,"  -t mask  specify default trace-level (may toggle with ^T)"
 #endif
+#if HAVE_COLOR_CONTENT
        ,"  -x       use xterm-compatible control for reading color palette"
+#endif
     };
     size_t n;
     for (n = 0; n < SIZEOF(tbl); n++)
@@ -7100,8 +7219,10 @@ main_menu(bool top)
 #if USE_WIDEC_SUPPORT
        (void) puts("C = color test pattern using wide-character calls");
 #endif
+#if HAVE_COLOR_CONTENT
        if (top)
            (void) puts("d = edit RGB color values");
+#endif
 #if USE_SOFTKEYS
        (void) puts("e = exercise soft keys");
 #if USE_WIDEC_SUPPORT
@@ -7124,16 +7245,21 @@ main_menu(bool top)
        (void) puts("O = exercise panels with wide-characters");
 #endif
 #endif
+#if HAVE_NEWPAD
        (void) puts("p = exercise pad features");
        (void) puts("P = exercise pad features, using color");
+#endif
        (void) puts("q = quit");
 #if USE_LIBFORM
        (void) puts("r = exercise forms code");
 #endif
+#if HAVE_COPYWIN
        (void) puts("s = overlapping-refresh test");
+#endif
 #if USE_LIBMENU && defined(TRACE)
        (void) puts("t = set trace level");
 #endif
+       (void) puts("v = show terminal name and settings");
        (void) puts("? = repeat this command summary");
 
        (void) fputs("> ", stdout);
@@ -7207,9 +7333,11 @@ main(int argc, char *argv[])
     bool assumed_colors = FALSE;
     bool default_colors = FALSE;
 #endif
-    char *palette_file = 0;
     bool monochrome = FALSE;
+#if HAVE_COLOR_CONTENT
     bool xterm_colors = FALSE;
+    char *palette_file = 0;
+#endif
 
     setlocale(LC_ALL, "");
 
@@ -7257,9 +7385,11 @@ main(int argc, char *argv[])
        case 'm':
            monochrome = TRUE;
            break;
+#if HAVE_COLOR_CONTENT
        case 'p':
            palette_file = optarg;
            break;
+#endif
 #if USE_LIBPANEL
        case 's':
            nap_msec = (int) atol(optarg);
@@ -7275,9 +7405,11 @@ main(int argc, char *argv[])
            save_trace = (unsigned) strtol(optarg, 0, 0);
            break;
 #endif
+#if HAVE_COLOR_CONTENT
        case 'x':
            xterm_colors = TRUE;
            break;
+#endif
        default:
            usage();
        }
@@ -7337,9 +7469,11 @@ main(int argc, char *argv[])
 #endif
        max_pairs = COLOR_PAIRS;        /* was > 256 ? 256 : COLOR_PAIRS */
 
+#if HAVE_COLOR_CONTENT
        if (can_change_color()) {
            init_all_colors(xterm_colors, palette_file);
        }
+#endif
     }
 
     /*