357 lines
8.7 KiB
C
357 lines
8.7 KiB
C
/****************************************************************************
|
|
* Copyright 2018-2019,2020 Thomas E. Dickey *
|
|
* Copyright 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.21 2020/02/02 23:34:34 tom Exp $
|
|
*
|
|
* Demonstrate the alloc_pair() function.
|
|
*/
|
|
|
|
#include <test.priv.h>
|
|
#include <time.h>
|
|
#include <popup_msg.h>
|
|
|
|
#if HAVE_ALLOC_PAIR && USE_WIDEC_SUPPORT
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
|
|
#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++] = WA_NORMAL;
|
|
if (valid_cap("smso"))
|
|
bits[limit++] = WA_STANDOUT;
|
|
if (valid_cap("smul"))
|
|
bits[limit++] = WA_UNDERLINE;
|
|
if (valid_cap("rev"))
|
|
bits[limit++] = WA_REVERSE;
|
|
if (valid_cap("blink"))
|
|
bits[limit++] = WA_BLINK;
|
|
if (valid_cap("dim"))
|
|
bits[limit++] = WA_DIM;
|
|
if (valid_cap("bold"))
|
|
bits[limit++] = WA_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 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;
|
|
FILE *output = 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 (isatty(fileno(stderr))) {
|
|
output = stderr;
|
|
} else if ((ch = open("/dev/tty", O_WRONLY)) >= 0) {
|
|
output = fdopen(ch, "w");
|
|
} else {
|
|
fprintf(stderr, "cannot open terminal for output\n");
|
|
ExitProgram(EXIT_FAILURE);
|
|
}
|
|
if (newterm(NULL, output, stdin) == 0) {
|
|
fprintf(stderr, "Cannot initialize terminal\n");
|
|
fclose(output);
|
|
ExitProgram(EXIT_FAILURE);
|
|
}
|
|
(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 HELP_KEY_1:
|
|
popup_msg(stdscr, 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,
|
|
(use_init ? NULL : (void *) &my_pair));
|
|
/*
|
|
* 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;
|
|
}
|
|
stop_curses();
|
|
fclose(output);
|
|
|
|
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
|