]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - test/ncurses.c
ncurses 6.0 - patch 20160625
[ncurses.git] / test / ncurses.c
index 9fb47f1254568634849465a7b568a732b45b9565..5764dd75c2451d15da18f53507d7077e393995f8 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * Copyright (c) 1998-2014,2015 Free Software Foundation, Inc.              *
+ * Copyright (c) 1998-2015,2016 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.425 2015/11/29 01:26:41 tom Exp $
+$Id: ncurses.c,v 1.438 2016/06/11 21:05:48 tom Exp $
 
 ***************************************************************************/
 
@@ -200,9 +200,9 @@ Repaint(void)
 }
 
 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
 
@@ -652,6 +652,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 +680,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 +847,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 +1103,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')];
@@ -2185,9 +2190,10 @@ color_test(void)
     int page_size = (LINES - grid_top);
     int pairs_max;
     int colors_max = COLORS;
+    int col_limit;
     int row_limit;
     int per_row;
-    char numbered[80];
+    char *numbered = 0;
     const char *hello;
     bool done = FALSE;
     bool opt_acsc = FALSE;
@@ -2197,6 +2203,15 @@ color_test(void)
     bool opt_wide = FALSE;
     WINDOW *helpwin;
 
+    numbered = (char *) calloc((size_t) (COLS + 1), sizeof(char));
+    done = ((COLS < 16) || (numbered == 0));
+
+    /*
+     * Because the number of colors is usually a power of two, we also use
+     * a power of two for the number of colors shown per line (to be tidy).
+     */
+    for (col_limit = 1; col_limit * 2 < COLS; col_limit *= 2) ;
+
     while (!done) {
        int shown = 0;
 
@@ -2214,11 +2229,11 @@ color_test(void)
        if (opt_wide) {
            width = 4;
            hello = "Test";
-           per_row = (colors_max > 8) ? 16 : 8;
+           per_row = (col_limit / ((colors_max > 8) ? 4 : 8));
        } else {
            width = 8;
            hello = "Hello";
-           per_row = 8;
+           per_row = (col_limit / 8);
        }
        per_row -= min_colors;
 
@@ -2249,6 +2264,9 @@ color_test(void)
            int col = (i % per_row + 1) * width;
            NCURSES_PAIRS_T pair = i;
 
+           if ((i / per_row) > row_limit)
+               break;
+
 #define InxToFG(i) (NCURSES_COLOR_T) ((i % (colors_max - min_colors)) + min_colors)
 #define InxToBG(i) (NCURSES_COLOR_T) ((i / (colors_max - min_colors)) + min_colors)
            if (row >= 0 && move(row, col) != ERR) {
@@ -2375,6 +2393,8 @@ color_test(void)
 
     erase();
     endwin();
+
+    free(numbered);
 }
 
 #if USE_WIDEC_SUPPORT
@@ -2389,9 +2409,10 @@ wide_color_test(void)
     int page_size = (LINES - grid_top);
     int pairs_max = (unsigned short) (-1);
     int colors_max = COLORS;
+    int col_limit;
     int row_limit;
     int per_row;
-    char numbered[80];
+    char *numbered = 0;
     const char *hello;
     bool done = FALSE;
     bool opt_acsc = FALSE;
@@ -2400,9 +2421,19 @@ wide_color_test(void)
     bool opt_wide = FALSE;
     bool opt_nums = FALSE;
     bool opt_xchr = FALSE;
-    wchar_t buffer[80];
+    wchar_t *buffer = 0;
     WINDOW *helpwin;
 
+    numbered = (char *) calloc((size_t) (COLS + 1), sizeof(char));
+    buffer = (wchar_t *) calloc((size_t) (COLS + 1), sizeof(wchar_t));
+    done = ((COLS < 16) || (numbered == 0) || (buffer == 0));
+
+    /*
+     * Because the number of colors is usually a power of two, we also use
+     * a power of two for the number of colors shown per line (to be tidy).
+     */
+    for (col_limit = 1; col_limit * 2 < COLS; col_limit *= 2) ;
+
     while (!done) {
        int shown = 0;
 
@@ -2416,15 +2447,14 @@ wide_color_test(void)
                pairs_max = COLOR_PAIRS;
        }
 
-       /* this assumes an 80-column line */
        if (opt_wide) {
            width = 4;
            hello = "Test";
-           per_row = (colors_max > 8) ? 16 : 8;
+           per_row = (col_limit / ((colors_max > 8) ? 4 : 8));
        } else {
            width = 8;
            hello = "Hello";
-           per_row = 8;
+           per_row = (col_limit / 8);
        }
        per_row -= min_colors;
 
@@ -2463,6 +2493,9 @@ wide_color_test(void)
            int col = (i % per_row + 1) * width;
            NCURSES_PAIRS_T pair = (NCURSES_PAIRS_T) i;
 
+           if ((i / per_row) > row_limit)
+               break;
+
            if (row >= 0 && move(row, col) != ERR) {
                init_pair(pair, InxToFG(i), InxToBG(i));
                (void) color_set(pair, NULL);
@@ -2594,6 +2627,9 @@ wide_color_test(void)
 
     erase();
     endwin();
+
+    free(numbered);
+    free(buffer);
 }
 #endif /* USE_WIDEC_SUPPORT */
 
@@ -2621,7 +2657,7 @@ change_color(NCURSES_PAIRS_T current, int field, int value, int usebase)
 }
 
 static void
-init_all_colors(void)
+reset_all_colors(void)
 {
     NCURSES_PAIRS_T c;
 
@@ -2632,6 +2668,85 @@ init_all_colors(void)
                   all_colors[c].blue);
 }
 
+#define okCOLOR(n) ((n) >= 0 && (n) < max_colors)
+#define okRGB(n)   ((n) >= 0 && (n) <= 1000)
+#define DecodeRGB(n) (NCURSES_COLOR_T) ((n * 1000) / 0xffff)
+
+static void
+init_all_colors(bool xterm_colors, char *palette_file)
+{
+    NCURSES_PAIRS_T cp;
+    all_colors = typeMalloc(RGB_DATA, (unsigned) max_colors);
+    if (!all_colors)
+       failed("all_colors");
+    for (cp = 0; cp < max_colors; ++cp) {
+       color_content(cp,
+                     &all_colors[cp].red,
+                     &all_colors[cp].green,
+                     &all_colors[cp].blue);
+    }
+    /* xterm and compatible terminals can read results of an OSC string
+     * asking for the current color palette.
+     */
+    if (xterm_colors) {
+       int n;
+       int got;
+       char result[BUFSIZ];
+       int check_n, check_r, check_g, check_b;
+
+       raw();
+       noecho();
+       for (n = 0; n < max_colors; ++n) {
+           fprintf(stderr, "\033]4;%d;?\007", n);
+           got = (int) read(0, result, sizeof(result) - 1);
+           if (got < 0)
+               break;
+           result[got] = '\0';
+           if (sscanf(result, "\033]4;%d;rgb:%x/%x/%x\007",
+                      &check_n,
+                      &check_r,
+                      &check_g,
+                      &check_b) == 4 &&
+               check_n == n) {
+               all_colors[n].red = DecodeRGB(check_r);
+               all_colors[n].green = DecodeRGB(check_g);
+               all_colors[n].blue = DecodeRGB(check_b);
+           } else {
+               break;
+           }
+       }
+       reset_prog_mode();
+    }
+    if (palette_file != 0) {
+       FILE *fp = fopen(palette_file, "r");
+       if (fp != 0) {
+           char buffer[BUFSIZ];
+           int red, green, blue;
+           int scale = 1000;
+           int c;
+           while (fgets(buffer, sizeof(buffer), fp) != 0) {
+               if (sscanf(buffer, "scale:%d", &c) == 1) {
+                   scale = c;
+               } else if (sscanf(buffer, "%d:%d %d %d",
+                                 &c,
+                                 &red,
+                                 &green,
+                                 &blue) == 4
+                          && okCOLOR(c)
+                          && okRGB(red)
+                          && okRGB(green)
+                          && okRGB(blue)) {
+#define Scaled(n) (NCURSES_COLOR_T) (((n) * 1000) / scale)
+                   all_colors[c].red = Scaled(red);
+                   all_colors[c].green = Scaled(green);
+                   all_colors[c].blue = Scaled(blue);
+               }
+           }
+           fclose(fp);
+       }
+    }
+}
+
 #define scaled_rgb(n) ((255 * (n)) / 1000)
 
 static void
@@ -2639,14 +2754,23 @@ color_edit(void)
 /* display the color test pattern, without trying to edit colors */
 {
     int i;
-    int current = 0;
-    int this_c = 0, value = 0, field = 0;
+    int current;
+    int this_c, value, field;
     int last_c;
-    int top_color = 0;
-    int page_size = (LINES - 6);
-
-    init_all_colors();
-    refresh();
+    int top_color;
+    int page_size;
+
+    reset_all_colors();
+#ifdef KEY_RESIZE
+  retry:
+#endif
+    current = 0;
+    this_c = 0;
+    value = 0;
+    field = 0;
+    top_color = 0;
+    page_size = (LINES - 6);
+    erase();
 
     for (i = 0; i < max_colors; i++)
        init_pair((NCURSES_PAIRS_T) i,
@@ -2715,6 +2839,21 @@ color_edit(void)
            value = 0;
 
        switch (this_c) {
+#ifdef KEY_RESIZE
+       case KEY_RESIZE:
+           move(0, 0);
+           goto retry;
+#endif
+       case '!':
+           ShellOut(FALSE);
+           /* FALLTHRU */
+       case CTRL('r'):
+           endwin();
+           refresh();
+           break;
+       case CTRL('l'):
+           refresh();
+           break;
        case CTRL('b'):
        case KEY_PPAGE:
            if (current > 0)
@@ -2741,10 +2880,12 @@ color_edit(void)
            current = (current == (max_colors - 1) ? 0 : current + 1);
            break;
 
+       case '\t':
        case KEY_RIGHT:
            field = (field == 2 ? 0 : field + 1);
            break;
 
+       case KEY_BTAB:
        case KEY_LEFT:
            field = (field == 0 ? 2 : field - 1);
            break;
@@ -2787,6 +2928,8 @@ color_edit(void)
            P("To increment or decrement a value, use the same procedure, but finish");
            P("with a `+' or `-'.");
            P("");
+           P("Use `!' to shell-out, ^R or ^L to repaint the screen.");
+           P("");
            P("Press 'm' to invoke the top-level menu with the current color settings.");
            P("To quit, do ESC");
 
@@ -2824,14 +2967,14 @@ color_edit(void)
        MvPrintw(LINES - 1, 0, "Number: %d", value);
        clrtoeol();
     } while
-       (!isQuit(this_c));
+       (!isQuit(this_c, TRUE));
 
     erase();
 
     /*
      * ncurses does not reset each color individually when calling endwin().
      */
-    init_all_colors();
+    reset_all_colors();
 
     endwin();
 }
@@ -3084,7 +3227,7 @@ slk_test(void)
            beep();
            break;
        }
-    } while (!isQuit(c = Getchar()));
+    } while (!isQuit(c = Getchar(), TRUE));
 
   done:
     slk_clear();
@@ -3238,7 +3381,7 @@ wide_slk_test(void)
            beep();
            break;
        }
-    } while (!isQuit(c = Getchar()));
+    } while (!isQuit(c = Getchar(), TRUE));
 
   done:
     slk_clear();
@@ -3578,7 +3721,7 @@ acs_display(void)
                     my_list[at_code].name);
        }
        refresh();
-    } while (!isQuit(c = Getchar()));
+    } while (!isQuit(c = Getchar(), TRUE));
 
     Pause();
     erase();
@@ -4113,7 +4256,7 @@ wide_acs_display(void)
                     my_list[at_code].name);
        }
        refresh();
-    } while (!isQuit(c = Getchar()));
+    } while (!isQuit(c = Getchar(), TRUE));
 
     Pause();
     erase();
@@ -4223,13 +4366,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
@@ -4265,46 +4405,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);
@@ -4614,10 +4734,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;
 
@@ -4703,12 +4827,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;
@@ -4752,7 +4870,7 @@ acs_and_scroll(void)
        usescr = frame_win(current);
        wrefresh(usescr);
     } while
-       (!isQuit(c = wGetchar(usescr))
+       (!isQuit(c = wGetchar(usescr), TRUE)
         && (c != ERR));
 
   breakout:
@@ -6644,7 +6762,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);
@@ -6892,6 +7010,7 @@ usage(void)
 #ifdef TRACE
        ,"  -t mask  specify default trace-level (may toggle with ^T)"
 #endif
+       ,"  -x       use xterm-compatible control for reading color palette"
     };
     size_t n;
     for (n = 0; n < SIZEOF(tbl); n++)
@@ -7057,9 +7176,6 @@ main_menu(bool top)
        main(argc,argv)
 --------------------------------------------------------------------------*/
 
-#define okCOLOR(n) ((n) >= 0 && (n) < max_colors)
-#define okRGB(n)   ((n) >= 0 && (n) <= 1000)
-
 int
 main(int argc, char *argv[])
 {
@@ -7073,10 +7189,11 @@ main(int argc, char *argv[])
 #endif
     char *palette_file = 0;
     bool monochrome = FALSE;
+    bool xterm_colors = FALSE;
 
     setlocale(LC_ALL, "");
 
-    while ((c = getopt(argc, argv, "a:dEe:fhmp:s:Tt:")) != -1) {
+    while ((c = getopt(argc, argv, "a:dEe:fhmp:s:Tt:x")) != -1) {
        switch (c) {
 #ifdef NCURSES_VERSION
        case 'a':
@@ -7138,6 +7255,9 @@ main(int argc, char *argv[])
            save_trace = (unsigned) strtol(optarg, 0, 0);
            break;
 #endif
+       case 'x':
+           xterm_colors = TRUE;
+           break;
        default:
            usage();
        }
@@ -7172,6 +7292,9 @@ main(int argc, char *argv[])
     initscr();
     bkgdset(BLANK);
 
+    set_terminal_modes();
+    def_prog_mode();
+
     /* tests, in general, will want these modes */
     use_colors = (bool) (monochrome ? FALSE : has_colors());
 
@@ -7195,47 +7318,9 @@ main(int argc, char *argv[])
        max_pairs = COLOR_PAIRS;        /* was > 256 ? 256 : COLOR_PAIRS */
 
        if (can_change_color()) {
-           NCURSES_PAIRS_T cp;
-           all_colors = typeMalloc(RGB_DATA, (unsigned) max_colors);
-           if (!all_colors)
-               failed("all_colors");
-           for (cp = 0; cp < max_colors; ++cp) {
-               color_content(cp,
-                             &all_colors[cp].red,
-                             &all_colors[cp].green,
-                             &all_colors[cp].blue);
-           }
-           if (palette_file != 0) {
-               FILE *fp = fopen(palette_file, "r");
-               if (fp != 0) {
-                   char buffer[BUFSIZ];
-                   int red, green, blue;
-                   int scale = 1000;
-                   while (fgets(buffer, sizeof(buffer), fp) != 0) {
-                       if (sscanf(buffer, "scale:%d", &c) == 1) {
-                           scale = c;
-                       } else if (sscanf(buffer, "%d:%d %d %d",
-                                         &c,
-                                         &red,
-                                         &green,
-                                         &blue) == 4
-                                  && okCOLOR(c)
-                                  && okRGB(red)
-                                  && okRGB(green)
-                                  && okRGB(blue)) {
-#define Scaled(n) (NCURSES_COLOR_T) (((n) * 1000) / scale)
-                           all_colors[c].red = Scaled(red);
-                           all_colors[c].green = Scaled(green);
-                           all_colors[c].blue = Scaled(blue);
-                       }
-                   }
-                   fclose(fp);
-               }
-           }
+           init_all_colors(xterm_colors, palette_file);
        }
     }
-    set_terminal_modes();
-    def_prog_mode();
 
     /*
      * Return to terminal mode, so we're guaranteed of being able to