/**************************************************************************** * Copyright 2018-2019,2020 Thomas E. Dickey * * * * 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: color_content.c,v 1.12 2020/02/02 23:34:34 tom Exp $ */ #define NEED_TIME_H #include #if USE_EXTENDED_COLOR typedef int my_color_t; #else typedef NCURSES_COLOR_T my_color_t; #endif typedef struct { my_color_t r; my_color_t g; my_color_t b; } MYCOLOR; static int f_opt; static int i_opt; static int l_opt; static int n_opt; static int p_opt; static int r_opt; static int s_opt; #if USE_EXTENDED_COLOR static int x_opt; #endif static MYCOLOR *expected; #if HAVE_GETTIMEOFDAY static struct timeval initial_time; static struct timeval finish_time; #endif static void failed(const char *msg) { printw("%s", msg); getch(); endwin(); ExitProgram(EXIT_FAILURE); } #if USE_EXTENDED_COLOR static int InitColor(int pair, int r, int g, int b) { int rc; if (x_opt) { rc = init_extended_color(pair, r, g, b); } else { rc = init_color((NCURSES_PAIRS_T) pair, (NCURSES_COLOR_T) r, (NCURSES_COLOR_T) g, (NCURSES_COLOR_T) b); } return rc; } static int ColorContent(int color, int *rp, int *gp, int *bp) { int rc; if (x_opt) { rc = extended_color_content(color, rp, gp, bp); } else { NCURSES_COLOR_T r, g, b; if ((rc = color_content((NCURSES_COLOR_T) color, &r, &g, &b)) == OK) { *rp = r; *gp = g; *bp = b; } } return rc; } #else #define InitColor(color,r,g,b) init_color((NCURSES_COLOR_T)color,(NCURSES_COLOR_T)r,(NCURSES_COLOR_T)g,(NCURSES_COLOR_T)b) #define ColorContent(color,rp,gp,bp) color_content((NCURSES_COLOR_T)color,rp,gp,bp) #endif static my_color_t random_color(void) { return (my_color_t) (rand() % 1000); } static void setup_test(void) { initscr(); cbreak(); noecho(); scrollok(stdscr, TRUE); if (has_colors()) { start_color(); if (!can_change_color() && !p_opt) failed("this terminal cannot initialize colors"); if (!f_opt) f_opt = 0; if (!l_opt) l_opt = COLORS; if (l_opt <= 0) failed("color limit must be greater than zero"); if (!n_opt) { int color; size_t need = (size_t) ((l_opt > COLORS) ? l_opt : COLORS) + 1; expected = typeCalloc(MYCOLOR, need); if (s_opt) { int r; int g; int b; color = f_opt; for (r = 0; r < 1000; ++r) { for (g = 0; g < 1000; ++g) { for (b = 0; b < 1000; ++b) { if (color < l_opt) { InitColor(color, r, g, b); expected[color].r = (my_color_t) r; expected[color].g = (my_color_t) g; expected[color].b = (my_color_t) b; ++color; } else { break; } } } } } else { for (color = f_opt; color < l_opt; ++color) { expected[color].r = random_color(); expected[color].g = random_color(); expected[color].b = random_color(); InitColor(color, expected[color].r, expected[color].g, expected[color].b); } } } } else { failed("This demo requires a color terminal"); } #if HAVE_GETTIMEOFDAY gettimeofday(&initial_time, 0); #endif } static void run_test(void) { int color; bool success = TRUE; for (color = f_opt; color < l_opt; ++color) { my_color_t r; my_color_t g; my_color_t b; if (ColorContent(color, &r, &g, &b) == OK) { if (expected != 0) { if (r != expected[color].r) success = FALSE; if (g != expected[color].g) success = FALSE; if (b != expected[color].b) success = FALSE; } } } if (i_opt) { addch(success ? '.' : '?'); refresh(); } } static void finish_test(void) { getch(); endwin(); } #if HAVE_GETTIMEOFDAY static double seconds(struct timeval *mark) { double result = (double) mark->tv_sec; result += ((double) mark->tv_usec / 1e6); return result; } #endif static void usage(void) { static const char *msg[] = { "Usage: color_content [options]" ,"" ,"Options:" ," -f COLOR first color value to test (default: 0)" ," -i interactive, showing test-progress" ," -l COLOR last color value to test (default: max_colors-1)" ," -n do not initialize color pairs" ," -p print data for color content instead of testing" ," -r COUNT repeat for given count" ," -s initialize pairs sequentially rather than random" #if USE_EXTENDED_COLOR ," -x use extended color pairs/values" #endif }; size_t n; for (n = 0; n < SIZEOF(msg); n++) fprintf(stderr, "%s\n", msg[n]); ExitProgram(EXIT_FAILURE); } int main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) { int i; while ((i = getopt(argc, argv, "f:il:npr:sx")) != -1) { switch (i) { case 'f': if ((f_opt = atoi(optarg)) <= 0) usage(); break; case 'i': i_opt = 1; break; case 'l': if ((l_opt = atoi(optarg)) <= 0) usage(); break; case 'n': n_opt = 1; break; case 'p': p_opt = 1; break; case 'r': if ((r_opt = atoi(optarg)) <= 0) usage(); break; case 's': s_opt = 1; break; #if USE_EXTENDED_COLOR case 'x': x_opt = 1; break; #endif default: usage(); } } if (optind < argc) usage(); if (r_opt <= 0) r_opt = 1; setup_test(); if (p_opt) { endwin(); for (i = 0; i < COLORS; ++i) { my_color_t r, g, b; if (ColorContent(i, &r, &g, &b) == OK) { printf("%d: %d %d %d\n", i, r, g, b); } else { printf("%d: ? ?\n", i); } } } else { int repeat; for (repeat = 0; repeat < r_opt; ++repeat) { run_test(); if (i_opt) { addch('.'); refresh(); } } if (i_opt) { addch('\n'); } printw("DONE: "); #if HAVE_GETTIMEOFDAY gettimeofday(&finish_time, 0); printw("%.03f seconds", seconds(&finish_time) - seconds(&initial_time)); #endif finish_test(); } ExitProgram(EXIT_SUCCESS); }