/****************************************************************************
- * Copyright (c) 1998-2006,2007 Free Software Foundation, Inc. *
+ * Copyright (c) 1998-2007,2009 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 *
* Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 *
* and: Eric S. Raymond <esr@snark.thyrsus.com> *
* and: Thomas E. Dickey 1996-on *
+ * and: Juergen Pfeifer 2009 *
****************************************************************************/
/* lib_color.c
#include <term.h>
#include <tic.h>
-MODULE_ID("$Id: lib_color.c,v 1.84 2007/03/10 19:20:15 tom Exp $")
+#ifndef CUR
+#define CUR SP_TERMTYPE
+#endif
+
+MODULE_ID("$Id: lib_color.c,v 1.91 2009/05/10 00:48:29 tom Exp $")
/*
* These should be screen structure members. They need to be globals for
#define TYPE_CALLOC(type,elts) typeCalloc(type, (unsigned)(elts))
+#define MAX_PALETTE 8
+
#define OkColorHi(n) (((n) < COLORS) && ((n) < max_colors))
+#define InPalette(n) ((n) >= 0 && (n) < MAX_PALETTE)
/*
* Given a RGB range of 0..1000, we'll normally set the individual values
};
/* *INDENT-ON* */
+/*
+ * Ensure that we use color pairs only when colors have been started, and also
+ * that the index is within the limits of the table which we allocated.
+ */
+#define ValidPair(pair) \
+ ((SP != 0) && (pair >= 0) && (pair < SP->_pair_limit) && SP->_coloron)
+
#if NCURSES_EXT_FUNCS
/*
* These are called from _nc_do_color(), which in turn is called from
}
static void
-set_background_color(int bg, int (*outc) (int))
+set_background_color(NCURSES_SP_DCLx int bg, NCURSES_SP_OUTC outc)
{
if (set_a_background) {
TPUTS_TRACE("set_a_background");
- tputs(TPARM_1(set_a_background, bg), 1, outc);
+ NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
+ TPARM_1(set_a_background, bg),
+ 1, outc);
} else {
TPUTS_TRACE("set_background");
- tputs(TPARM_1(set_background, toggled_colors(bg)), 1, outc);
+ NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
+ TPARM_1(set_background, toggled_colors(bg)),
+ 1, outc);
}
}
static void
-set_foreground_color(int fg, int (*outc) (int))
+set_foreground_color(NCURSES_SP_DCLx int fg, NCURSES_SP_OUTC outc)
{
if (set_a_foreground) {
TPUTS_TRACE("set_a_foreground");
- tputs(TPARM_1(set_a_foreground, fg), 1, outc);
+ NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
+ TPARM_1(set_a_foreground, fg),
+ 1, outc);
} else {
TPUTS_TRACE("set_foreground");
- tputs(TPARM_1(set_foreground, toggled_colors(fg)), 1, outc);
+ NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
+ TPARM_1(set_foreground, toggled_colors(fg)),
+ 1, outc);
}
}
static void
-init_color_table(void)
+init_color_table(NCURSES_SP_DCL0)
{
const color_t *tp;
int n;
tp = (hue_lightness_saturation) ? hls_palette : cga_palette;
for (n = 0; n < COLORS; n++) {
- if (n < 8) {
+ if (InPalette(n)) {
SP->_color_table[n] = tp[n];
} else {
- SP->_color_table[n] = tp[n % 8];
+ SP->_color_table[n] = tp[n % MAX_PALETTE];
if (hue_lightness_saturation) {
SP->_color_table[n].green = 100;
} else {
* Reset the color pair, e.g., to whatever color pair 0 is.
*/
static bool
-reset_color_pair(void)
+reset_color_pair(NCURSES_SP_DCL0)
{
bool result = FALSE;
bool
_nc_reset_colors(void)
{
+#if NCURSES_SP_FUNCS
+ SCREEN *sp = CURRENT_SCREEN;
+#endif
int result = FALSE;
T((T_CALLED("_nc_reset_colors()")));
if (SP->_color_defs > 0)
SP->_color_defs = -(SP->_color_defs);
- if (reset_color_pair())
+ if (reset_color_pair(NCURSES_SP_ARG))
result = TRUE;
if (orig_colors != 0) {
TPUTS_TRACE("orig_colors");
}
NCURSES_EXPORT(int)
-start_color(void)
+NCURSES_SP_NAME(start_color) (NCURSES_SP_DCL0)
{
int result = ERR;
T((T_CALLED("start_color()")));
- if (SP == 0) {
+ if (SP_PARM == 0) {
result = ERR;
- } else if (SP->_coloron) {
+ } else if (SP_PARM->_coloron) {
result = OK;
} else {
- if (reset_color_pair() != TRUE) {
- set_foreground_color(default_fg(), _nc_outch);
- set_background_color(default_bg(), _nc_outch);
+ if (reset_color_pair(NCURSES_SP_ARG) != TRUE) {
+ set_foreground_color(NCURSES_SP_ARGx
+ default_fg(),
+ NCURSES_SP_NAME(_nc_outch));
+ set_background_color(NCURSES_SP_ARGx
+ default_bg(),
+ NCURSES_SP_NAME(_nc_outch));
}
if (max_pairs > 0 && max_colors > 0) {
- SP->_pair_count = max_pairs;
- SP->_color_count = max_colors;
+ SP_PARM->_pair_limit = max_pairs;
+
+#if NCURSES_EXT_FUNCS
+ /*
+ * If using default colors, allocate extra space in table to
+ * allow for default-color as a component of a color-pair.
+ */
+ SP_PARM->_pair_limit += (1 + (2 * max_colors));
+#endif
+ SP_PARM->_pair_count = max_pairs;
+ SP_PARM->_color_count = max_colors;
#if !USE_REENTRANT
COLOR_PAIRS = max_pairs;
COLORS = max_colors;
#endif
- if ((SP->_color_pairs = TYPE_CALLOC(colorpair_t,
- max_pairs)) != 0) {
- if ((SP->_color_table = TYPE_CALLOC(color_t,
- max_colors)) != 0) {
- SP->_color_pairs[0] = PAIR_OF(default_fg(), default_bg());
- init_color_table();
+ SP_PARM->_color_pairs = TYPE_CALLOC(colorpair_t,
+ SP_PARM->_pair_limit);
+ if (SP_PARM->_color_pairs != 0) {
+ SP_PARM->_color_table = TYPE_CALLOC(color_t, max_colors);
+ if (SP_PARM->_color_table != 0) {
+ SP_PARM->_color_pairs[0] = PAIR_OF(default_fg(),
+ default_bg());
+ init_color_table(NCURSES_SP_ARG);
T(("started color: COLORS = %d, COLOR_PAIRS = %d",
COLORS, COLOR_PAIRS));
- SP->_coloron = 1;
+ SP_PARM->_coloron = 1;
result = OK;
- } else if (SP->_color_pairs != 0) {
- FreeAndNull(SP->_color_pairs);
+ } else if (SP_PARM->_color_pairs != 0) {
+ FreeAndNull(SP_PARM->_color_pairs);
}
}
} else {
returnCode(result);
}
+#if NCURSES_SP_FUNCS
+NCURSES_EXPORT(int)
+start_color(void)
+{
+ return NCURSES_SP_NAME(start_color) (CURRENT_SCREEN);
+}
+#endif
+
/* This function was originally written by Daniel Weaver <danw@znyx.com> */
static void
rgb2hls(short r, short g, short b, short *h, short *l, short *s)
* values.
*/
NCURSES_EXPORT(int)
-init_pair(short pair, short f, short b)
+NCURSES_SP_NAME(init_pair) (NCURSES_SP_DCLx short pair, short f, short b)
{
colorpair_t result;
+ colorpair_t previous;
T((T_CALLED("init_pair(%d,%d,%d)"), pair, f, b));
- if ((pair < 0) || (pair >= COLOR_PAIRS) || SP == 0 || !SP->_coloron)
+ if (!ValidPair(pair))
returnCode(ERR);
+
+ previous = SP_PARM->_color_pairs[pair];
#if NCURSES_EXT_FUNCS
- if (SP->_default_color) {
- if (f < 0)
+ if (SP_PARM->_default_color) {
+ bool isDefault = FALSE;
+ bool wasDefault = FALSE;
+ int default_pairs = SP_PARM->_default_pairs;
+
+ /*
+ * Map caller's color number, e.g., -1, 0, 1, .., 7, etc., into
+ * internal unsigned values which we will store in the _color_pairs[]
+ * table.
+ */
+ if (isDefaultColor(f)) {
f = COLOR_DEFAULT;
- if (b < 0)
+ isDefault = TRUE;
+ } else if (!OkColorHi(f)) {
+ returnCode(ERR);
+ }
+
+ if (isDefaultColor(b)) {
b = COLOR_DEFAULT;
- if (!OkColorHi(f) && !isDefaultColor(f))
+ isDefault = TRUE;
+ } else if (!OkColorHi(b)) {
returnCode(ERR);
- if (!OkColorHi(b) && !isDefaultColor(b))
+ }
+
+ /*
+ * Check if the table entry that we are going to init/update used
+ * default colors.
+ */
+ if ((FORE_OF(previous) == COLOR_DEFAULT)
+ || (BACK_OF(previous) == COLOR_DEFAULT))
+ wasDefault = TRUE;
+
+ /*
+ * Keep track of the number of entries in the color pair table which
+ * used a default color.
+ */
+ if (isDefault && !wasDefault) {
+ ++default_pairs;
+ } else if (wasDefault && !isDefault) {
+ --default_pairs;
+ }
+
+ /*
+ * As an extension, ncurses allows the pair number to exceed the
+ * terminal's color_pairs value for pairs using a default color.
+ *
+ * Note that updating a pair which used a default color with one
+ * that does not will decrement the count - and possibly interfere
+ * with sequentially adding new pairs.
+ */
+ if (pair > (SP_PARM->_pair_count + default_pairs)) {
returnCode(ERR);
+ }
+ SP_PARM->_default_pairs = default_pairs;
} else
#endif
{
* pair colors with the new ones).
*/
result = PAIR_OF(f, b);
- if (SP->_color_pairs[pair] != 0
- && SP->_color_pairs[pair] != result) {
+ if (previous != 0
+ && previous != result) {
int y, x;
for (y = 0; y <= curscr->_maxy; y++) {
_nc_make_oldhash(y);
}
}
- SP->_color_pairs[pair] = result;
- if (GET_SCREEN_PAIR(SP) == pair)
- SET_SCREEN_PAIR(SP, (chtype) (~0)); /* force attribute update */
+ SP_PARM->_color_pairs[pair] = result;
+ if (GET_SCREEN_PAIR(SP_PARM) == pair)
+ SET_SCREEN_PAIR(SP_PARM, (chtype) (~0)); /* force attribute update */
- if (initialize_pair) {
+ if (initialize_pair && InPalette(f) && InPalette(b)) {
const color_t *tp = hue_lightness_saturation ? hls_palette : cga_palette;
TR(TRACE_ATTRS,
returnCode(OK);
}
+#if NCURSES_SP_FUNCS
+NCURSES_EXPORT(int)
+init_pair(short pair, short f, short b)
+{
+ return NCURSES_SP_NAME(init_pair) (CURRENT_SCREEN, pair, f, b);
+}
+#endif
+
#define okRGB(n) ((n) >= 0 && (n) <= 1000)
NCURSES_EXPORT(int)
-init_color(short color, short r, short g, short b)
+NCURSES_SP_NAME(init_color) (NCURSES_SP_DCLx
+ short color, short r, short g, short b)
{
int result = ERR;
T((T_CALLED("init_color(%d,%d,%d,%d)"), color, r, g, b));
if (initialize_color != NULL
- && SP != 0
- && SP->_coloron
+ && SP_PARM != 0
+ && SP_PARM->_coloron
&& (color >= 0 && OkColorHi(color))
&& (okRGB(r) && okRGB(g) && okRGB(b))) {
- SP->_color_table[color].init = 1;
- SP->_color_table[color].r = r;
- SP->_color_table[color].g = g;
- SP->_color_table[color].b = b;
+ SP_PARM->_color_table[color].init = 1;
+ SP_PARM->_color_table[color].r = r;
+ SP_PARM->_color_table[color].g = g;
+ SP_PARM->_color_table[color].b = b;
if (hue_lightness_saturation) {
rgb2hls(r, g, b,
- &SP->_color_table[color].red,
- &SP->_color_table[color].green,
- &SP->_color_table[color].blue);
+ &SP_PARM->_color_table[color].red,
+ &SP_PARM->_color_table[color].green,
+ &SP_PARM->_color_table[color].blue);
} else {
- SP->_color_table[color].red = r;
- SP->_color_table[color].green = g;
- SP->_color_table[color].blue = b;
+ SP_PARM->_color_table[color].red = r;
+ SP_PARM->_color_table[color].green = g;
+ SP_PARM->_color_table[color].blue = b;
}
TPUTS_TRACE("initialize_color");
putp(TPARM_4(initialize_color, color, r, g, b));
- SP->_color_defs = max(color + 1, SP->_color_defs);
+ SP_PARM->_color_defs = max(color + 1, SP_PARM->_color_defs);
result = OK;
}
returnCode(result);
}
+#if NCURSES_SP_FUNCS
+NCURSES_EXPORT(int)
+init_color(short color, short r, short g, short b)
+{
+ return NCURSES_SP_NAME(init_color) (CURRENT_SCREEN, color, r, g, b);
+}
+#endif
+
NCURSES_EXPORT(bool)
-can_change_color(void)
+NCURSES_SP_NAME(can_change_color) (NCURSES_SP_DCL0)
{
T((T_CALLED("can_change_color()")));
returnCode((can_change != 0) ? TRUE : FALSE);
}
+#if NCURSES_SP_FUNCS
NCURSES_EXPORT(bool)
-has_colors(void)
+can_change_color(void)
+{
+ return NCURSES_SP_NAME(can_change_color) (CURRENT_SCREEN);
+}
+#endif
+
+NCURSES_EXPORT(bool)
+NCURSES_SP_NAME(has_colors) (NCURSES_SP_DCL0)
{
T((T_CALLED("has_colors()")));
returnCode((VALID_NUMERIC(max_colors) && VALID_NUMERIC(max_pairs)
|| set_color_pair)) ? TRUE : FALSE);
}
+#if NCURSES_SP_FUNCS
+NCURSES_EXPORT(bool)
+has_colors(void)
+{
+ return NCURSES_SP_NAME(has_colors) (CURRENT_SCREEN);
+}
+#endif
+
NCURSES_EXPORT(int)
-color_content(short color, short *r, short *g, short *b)
+NCURSES_SP_NAME(color_content) (NCURSES_SP_DCLx short color, short *r,
+ short *g, short *b)
{
int result;
T((T_CALLED("color_content(%d,%p,%p,%p)"), color, r, g, b));
- if (color < 0 || !OkColorHi(color) || SP == 0 || !SP->_coloron) {
+ if (color < 0 || !OkColorHi(color) || SP_PARM == 0 || !SP_PARM->_coloron) {
result = ERR;
} else {
- NCURSES_COLOR_T c_r = SP->_color_table[color].red;
- NCURSES_COLOR_T c_g = SP->_color_table[color].green;
- NCURSES_COLOR_T c_b = SP->_color_table[color].blue;
+ NCURSES_COLOR_T c_r = SP_PARM->_color_table[color].red;
+ NCURSES_COLOR_T c_g = SP_PARM->_color_table[color].green;
+ NCURSES_COLOR_T c_b = SP_PARM->_color_table[color].blue;
if (r)
*r = c_r;
returnCode(result);
}
+#if NCURSES_SP_FUNCS
NCURSES_EXPORT(int)
-pair_content(short pair, short *f, short *b)
+color_content(short color, short *r, short *g, short *b)
+{
+ return NCURSES_SP_NAME(color_content) (CURRENT_SCREEN, color, r, g, b);
+}
+#endif
+
+NCURSES_EXPORT(int)
+NCURSES_SP_NAME(pair_content) (NCURSES_SP_DCLx short pair, short *f,
+ short *b)
{
int result;
T((T_CALLED("pair_content(%d,%p,%p)"), pair, f, b));
- if ((pair < 0) || (pair >= COLOR_PAIRS) || SP == 0 || !SP->_coloron) {
+ if (!ValidPair(pair)) {
result = ERR;
} else {
- NCURSES_COLOR_T fg = ((SP->_color_pairs[pair] >> C_SHIFT) & C_MASK);
- NCURSES_COLOR_T bg = (SP->_color_pairs[pair] & C_MASK);
+ NCURSES_COLOR_T fg = FORE_OF(SP_PARM->_color_pairs[pair]);
+ NCURSES_COLOR_T bg = BACK_OF(SP_PARM->_color_pairs[pair]);
#if NCURSES_EXT_FUNCS
if (fg == COLOR_DEFAULT)
returnCode(result);
}
+#if NCURSES_SP_FUNCS
+NCURSES_EXPORT(int)
+pair_content(short pair, short *f, short *b)
+{
+ return NCURSES_SP_NAME(pair_content) (CURRENT_SCREEN, pair, f, b);
+}
+#endif
+
NCURSES_EXPORT(void)
-_nc_do_color(short old_pair, short pair, bool reverse, int (*outc) (int))
+NCURSES_SP_NAME(_nc_do_color) (NCURSES_SP_DCLx
+ short old_pair,
+ short pair,
+ bool reverse,
+ NCURSES_SP_OUTC outc)
{
NCURSES_COLOR_T fg = COLOR_DEFAULT;
NCURSES_COLOR_T bg = COLOR_DEFAULT;
NCURSES_COLOR_T old_fg, old_bg;
- if (pair < 0 || pair >= COLOR_PAIRS) {
+ if (!ValidPair(pair)) {
return;
} else if (pair != 0) {
if (set_color_pair) {
TPUTS_TRACE("set_color_pair");
- tputs(TPARM_1(set_color_pair, pair), 1, outc);
+ NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx
+ TPARM_1(set_color_pair, pair),
+ 1, outc);
return;
} else if (SP != 0) {
pair_content((short) pair, &fg, &bg);
if (SP->_has_sgr_39_49
&& isDefaultColor(old_bg)
&& !isDefaultColor(old_fg)) {
- tputs("\033[39m", 1, outc);
+ NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx "\033[39m", 1, outc);
} else if (SP->_has_sgr_39_49
&& isDefaultColor(old_fg)
&& !isDefaultColor(old_bg)) {
- tputs("\033[49m", 1, outc);
+ NCURSES_SP_NAME(tputs) (NCURSES_SP_ARGx "\033[49m", 1, outc);
} else
#endif
- reset_color_pair();
+ reset_color_pair(NCURSES_SP_ARG);
}
} else {
- reset_color_pair();
+ reset_color_pair(NCURSES_SP_ARG);
if (old_pair < 0)
return;
}
fg, bg));
if (!isDefaultColor(fg)) {
- set_foreground_color(fg, outc);
+ set_foreground_color(NCURSES_SP_ARGx fg, outc);
}
if (!isDefaultColor(bg)) {
- set_background_color(bg, outc);
+ set_background_color(NCURSES_SP_ARGx bg, outc);
}
}
+
+#if NCURSES_SP_FUNCS
+NCURSES_EXPORT(void)
+_nc_do_color(short old_pair, short pair, bool reverse, NCURSES_OUTC outc)
+{
+ SetSafeOutcWrapper(outc);
+ NCURSES_SP_NAME(_nc_do_color) (CURRENT_SCREEN,
+ old_pair,
+ pair,
+ reverse,
+ _nc_outc_wrapper);
+}
+#endif