/****************************************************************************
- * Copyright (c) 1998-2005,2006 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 *
#include <term.h>
#include <tic.h>
-MODULE_ID("$Id: lib_color.c,v 1.80 2006/11/26 01:33:16 tom Exp $")
+MODULE_ID("$Id: lib_color.c,v 1.87 2009/01/25 00:25:31 tom Exp $")
/*
* These should be screen structure members. They need to be globals for
* historical reasons. So we assign them in start_color() and also in
* set_term()'s screen-switching logic.
*/
+#if USE_REENTRANT
+NCURSES_EXPORT(int)
+NCURSES_PUBLIC_VAR(COLOR_PAIRS) (void)
+{
+ return SP ? SP->_pair_count : -1;
+}
+NCURSES_EXPORT(int)
+NCURSES_PUBLIC_VAR(COLORS) (void)
+{
+ return SP ? SP->_color_count : -1;
+}
+#else
NCURSES_EXPORT_VAR(int) COLOR_PAIRS = 0;
NCURSES_EXPORT_VAR(int) COLORS = 0;
+#endif
#define DATA(r,g,b) {r,g,b, 0,0,0, 0}
#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
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 {
}
if (max_pairs > 0 && max_colors > 0) {
- COLOR_PAIRS = SP->_pair_count = max_pairs;
- COLORS = SP->_color_count = max_colors;
+ SP->_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->_pair_limit += (1 + (2 * max_colors));
+#endif
+ SP->_pair_count = max_pairs;
+ SP->_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) {
+ SP->_pair_limit)) != 0) {
if ((SP->_color_table = TYPE_CALLOC(color_t,
max_colors)) != 0) {
SP->_color_pairs[0] = PAIR_OF(default_fg(), default_bg());
init_pair(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->_color_pairs[pair];
#if NCURSES_EXT_FUNCS
if (SP->_default_color) {
- if (f < 0)
+ bool isDefault = FALSE;
+ bool wasDefault = FALSE;
+ int default_pairs = SP->_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->_pair_count + default_pairs)) {
returnCode(ERR);
+ }
+ SP->_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++) {
if (GET_SCREEN_PAIR(SP) == pair)
SET_SCREEN_PAIR(SP, (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;
- T(("initializing pair: pair = %d, fg=(%d,%d,%d), bg=(%d,%d,%d)",
- pair,
- tp[f].red, tp[f].green, tp[f].blue,
- tp[b].red, tp[b].green, tp[b].blue));
+ TR(TRACE_ATTRS,
+ ("initializing pair: pair = %d, fg=(%d,%d,%d), bg=(%d,%d,%d)",
+ pair,
+ tp[f].red, tp[f].green, tp[f].blue,
+ tp[b].red, tp[b].green, tp[b].blue));
TPUTS_TRACE("initialize_pair");
putp(TPARM_7(initialize_pair,
if (b)
*b = c_b;
- T(("...color_content(%d,%d,%d,%d)", color, c_r, c_g, c_b));
+ TR(TRACE_ATTRS, ("...color_content(%d,%d,%d,%d)",
+ color, c_r, c_g, c_b));
result = OK;
}
returnCode(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->_color_pairs[pair]);
+ NCURSES_COLOR_T bg = BACK_OF(SP->_color_pairs[pair]);
#if NCURSES_EXT_FUNCS
if (fg == COLOR_DEFAULT)
if (b)
*b = bg;
- T(("...pair_content(%d,%d,%d)", pair, fg, bg));
+ TR(TRACE_ATTRS, ("...pair_content(%d,%d,%d)", pair, fg, bg));
result = OK;
}
returnCode(result);
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) {