]> ncurses.scripts.mit.edu Git - ncurses.git/blobdiff - test/demo_new_pair.c
ncurses 6.0 - patch 20170311
[ncurses.git] / test / demo_new_pair.c
diff --git a/test/demo_new_pair.c b/test/demo_new_pair.c
new file mode 100644 (file)
index 0000000..aef725a
--- /dev/null
@@ -0,0 +1,353 @@
+/****************************************************************************
+ * Copyright (c) 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            *
+ * "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.                                                           *
+ ****************************************************************************/
+/*
+ * $Id: demo_new_pair.c,v 1.10 2017/03/10 09:47:15 tom Exp $
+ *
+ * Demonstrate the alloc_pair() function.
+ */
+
+#include <test.priv.h>
+#include <time.h>
+
+#if HAVE_ALLOC_PAIR && USE_WIDEC_SUPPORT
+
+#define MAX_BITS 8             /* all but A_ALTCHARSET */
+#define MAX_ATTR ((1<<MAX_BITS)-1)
+
+static bool
+valid_cap(NCURSES_CONST char *name)
+{
+    char *value = tigetstr(name);
+    return (value != 0 && value != (char *) -1) ? TRUE : FALSE;
+}
+
+static attr_t
+next_attr(int now)
+{
+    static bool init = FALSE;
+    static attr_t table[MAX_BITS * MAX_BITS];
+    static int limit = 0;
+
+    if (!init) {
+       int j, k;
+       attr_t bits[MAX_BITS];
+
+       init = TRUE;
+       bits[limit++] = A_NORMAL;
+       if (valid_cap("smso"))
+           bits[limit++] = A_STANDOUT;
+       if (valid_cap("smul"))
+           bits[limit++] = A_UNDERLINE;
+       if (valid_cap("rev"))
+           bits[limit++] = A_REVERSE;
+       if (valid_cap("blink"))
+           bits[limit++] = A_BLINK;
+       if (valid_cap("dim"))
+           bits[limit++] = A_DIM;
+       if (valid_cap("bold"))
+           bits[limit++] = A_BOLD;
+       for (j = 0; j < limit; ++j) {
+           for (k = 0; k < limit; ++k) {
+               table[j * limit + k] = bits[j] | bits[k];
+           }
+       }
+    }
+    return table[now % limit];
+}
+
+static void
+our_content(int pair, int *fg, int *bg)
+{
+    pair %= COLOR_PAIRS;
+    *fg = (pair / COLORS) % COLORS;
+    *bg = (pair % COLORS);
+}
+
+static int
+make_color(int now)
+{
+    int fg, bg;
+    our_content(now, &fg, &bg);
+    return alloc_pair(fg, bg);
+}
+
+static int
+next_color(int now)
+{
+    int result = 0;
+    if ((short) now > 0) {
+       if (now < COLOR_PAIRS) {
+           int fg, bg;
+           our_content(now, &fg, &bg);
+           if (init_pair((short) now, (short) fg, (short) bg) != OK)
+               now = ERR;
+       } else {
+           now %= COLOR_PAIRS;
+       }
+       result = now;
+    }
+    return result;
+}
+
+static void
+show_help(const char **help)
+{
+    WINDOW *mywin = newwin(LINES, COLS, 0, 0);
+    int n;
+
+    wmove(mywin, 1, 1);
+    for (n = 0; help[n] != 0; ++n) {
+       wmove(mywin, 1 + n, 2);
+       wprintw(mywin, "%.*s\n", COLS - 4, help[n]);
+    }
+    box(mywin, 0, 0);
+    wgetch(mywin);
+    delwin(mywin);
+    touchwin(stdscr);
+    refresh();
+}
+
+static time_t
+now(void)
+{
+    return time((time_t *) 0);
+}
+
+static void
+usage(void)
+{
+    static const char *msg[] =
+    {
+       "Usage: demo_new_pair [options]",
+       "",
+       "Repeatedly print using all possible color combinations.",
+       "",
+       "Options:",
+       " -i       use init_pair rather than alloc_pair",
+       " -p       start in paged-mode",
+       " -s       start in single-step mode",
+       " -w       print a wide-character cell",
+    };
+    unsigned n;
+    for (n = 0; n < SIZEOF(msg); ++n) {
+       fprintf(stderr, "%s\n", msg[n]);
+    }
+    ExitProgram(EXIT_FAILURE);
+}
+
+#define use_pages() \
+       paged_mode = TRUE, single_mode = TRUE
+
+#define use_single() \
+       paged_mode = FALSE, single_mode = TRUE
+
+#define update_modes() \
+           scrollok(stdscr, !paged_mode); \
+           nodelay(stdscr, !single_mode || paged_mode)
+
+int
+main(int argc, char *argv[])
+{
+    static const char *help[] =
+    {
+       "This program iterates over the possible color combinations,",
+       "allocating or initializing color pairs.  For best results,",
+       "choose screen-width dividing evenly into the number of colors,",
+       "e.g.,",
+       "",
+       "  32x64,32x128  256 colors",
+       "  24x44,24x88   88 colors",
+       "  32x64,24x128  16 colors",
+       "",
+       "Keys:",
+       "  c      toggle between coloring and de-coloring cells",
+       "  p      show one page at a time",
+       "  s      show one character at a time",
+       " <space> display char/page without pausing",
+       "  v/V    cycle through video attributes",
+       "  w      toggle between \"#\" and a double-width equivalent",
+       "  ?      print this screen (exit on any character).",
+       "",
+       "To exit this program, press ^Q, ^[ or \"q\".",
+       0
+    };
+
+    bool done = FALSE;
+    bool clobber = FALSE;
+    bool hascolor = FALSE;
+    bool use_init = FALSE;
+    bool use_wide = FALSE;
+    bool paged_mode = FALSE;
+    bool single_mode = FALSE;
+    int video_mode = 0;
+    int current;
+    int ch;
+    wchar_t wch[2];
+    time_t start = now();
+    long total_cells = 0;
+
+    setlocale(LC_ALL, "");
+
+    while ((ch = getopt(argc, argv, "ipsw")) != -1) {
+       switch (ch) {
+       case 'i':
+           use_init = TRUE;
+           break;
+       case 'p':
+           use_pages();
+           break;
+       case 's':
+           use_single();
+           break;
+       case 'w':
+           use_wide = TRUE;
+           break;
+       default:
+           usage();
+           break;
+       }
+    }
+
+    if (newterm(NULL, stderr, stdin) == 0)
+       usage();
+    (void) cbreak();           /* read chars without wait for \n */
+    (void) noecho();           /* don't echo input */
+    update_modes();
+    curs_set(0);
+
+    keypad(stdscr, TRUE);
+
+    if ((hascolor = has_colors())) {
+       start_color();
+       current = 1;
+    } else {
+       current = 0;
+    }
+
+    /*
+     * Repeatedly cycle through all colors, initializing pairs as needed.
+     * Provide for single-stepping, or page-at-a-time, as well as quitting.
+     */
+    while (!done) {
+       cchar_t temp;
+       attr_t my_attrs;
+       int my_pair;
+
+       switch (getch()) {
+       case '?':
+           show_help(help);
+           break;
+       case 'p':
+           /* step-by-page */
+           use_pages();
+           update_modes();
+           break;
+       case 's':
+           /* step-by-char */
+           use_single();
+           update_modes();
+           break;
+       case ' ':
+           single_mode = FALSE;
+           update_modes();
+           break;
+       case QUIT:
+       case ESCAPE:
+       case 'q':
+           done = TRUE;
+           continue;
+       case 'c':
+           clobber = !clobber;
+           continue;
+       case 'v':
+           if (--video_mode < 0)
+               video_mode = MAX_ATTR;
+           continue;
+       case 'V':
+           if (video_mode > MAX_ATTR)
+               video_mode = 0;
+           continue;
+       case 'w':
+           use_wide = !use_wide;
+           continue;
+       case ERR:
+           break;
+       default:
+           beep();
+           break;
+       }
+       if (hascolor) {
+           my_attrs = next_attr(video_mode);
+           if (clobber) {
+               int fg, bg;
+               our_content(current, &fg, &bg);
+               my_pair = find_pair(fg, bg);
+               if (my_pair > 0) {
+                   free_pair(my_pair);
+               }
+               my_pair = 0;
+           } else {
+               my_pair = (use_init
+                          ? next_color(current)
+                          : make_color(current));
+           }
+       } else {
+           my_attrs = next_attr(current);
+           my_pair = 0;
+       }
+       if (my_pair < 0)
+           break;
+       wch[0] = use_wide ? 0xff03 : '#';
+       wch[1] = 0;
+       setcchar(&temp, wch, my_attrs, (short) my_pair, NULL);
+       /*
+        * At the end of a page, move the cursor to the home position.
+        */
+       if ((add_wch(&temp) == ERR) && paged_mode) {
+           nodelay(stdscr, !single_mode);
+           move(0, 0);
+       }
+       total_cells += 1 + (use_wide ? 1 : 0);
+       ++current;
+    }
+    endwin();
+
+    printf("%.1f cells/second\n",
+          (double) (total_cells) / (double) (now() - start));
+
+    ExitProgram(EXIT_SUCCESS);
+}
+
+#else
+int
+main(void)
+{
+    printf("This program requires the ncurses alloc_pair function\n");
+    ExitProgram(EXIT_FAILURE);
+}
+#endif