diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2020-02-12 02:21:21 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2020-02-12 02:21:21 +0000 |
commit | ff448436b2b70771d09b8d5ff34a509dcf02f81b (patch) | |
tree | 2f7abbba7198a4e1c4a23955bc3a539db5a7d999 /ncurses/base/new_pair.c | |
parent | f6d73a10a980bc78969c3af93665cbe7d06c3646 (diff) | |
download | ncurses-ff448436b2b70771d09b8d5ff34a509dcf02f81b.tar.gz |
ncurses-6.2ncurses-6.2
Diffstat (limited to 'ncurses/base/new_pair.c')
-rw-r--r-- | ncurses/base/new_pair.c | 386 |
1 files changed, 386 insertions, 0 deletions
diff --git a/ncurses/base/new_pair.c b/ncurses/base/new_pair.c new file mode 100644 index 0000000..547ab28 --- /dev/null +++ b/ncurses/base/new_pair.c @@ -0,0 +1,386 @@ +/**************************************************************************** + * 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. * + ****************************************************************************/ + +/**************************************************************************** + * Author: Thomas E. Dickey * + ****************************************************************************/ + +/* new_pair.c + * + * New color-pair functions, alloc_pair and free_pair + */ + +#define NEW_PAIR_INTERNAL 1 +#include <curses.priv.h> + +#ifndef CUR +#define CUR SP_TERMTYPE +#endif + +#ifdef USE_TERM_DRIVER +#define MaxColors InfoOf(SP_PARM).maxcolors +#else +#define MaxColors max_colors +#endif + +#if NCURSES_EXT_COLORS + +/* fix redefinition versys tic.h */ +#undef entry +#define entry my_entry +#undef ENTRY +#define ENTRY my_ENTRY + +#include <search.h> + +#endif + +MODULE_ID("$Id: new_pair.c,v 1.19 2020/02/02 23:34:34 tom Exp $") + +#if NCURSES_EXT_COLORS + +#ifdef NEW_PAIR_DEBUG + +static int +prev_len(SCREEN *sp, int pair) +{ + int result = 1; + int base = pair; + colorpair_t *list = sp->_color_pairs; + while (list[pair].prev != base) { + result++; + pair = list[pair].prev; + } + return result; +} + +static int +next_len(SCREEN *sp, int pair) +{ + int result = 1; + int base = pair; + colorpair_t *list = sp->_color_pairs; + while (list[pair].next != base) { + result++; + pair = list[pair].next; + } + return result; +} + +/* + * Trace the contents of LRU color-pairs. + */ +static void +dumpit(SCREEN *sp, int pair, const char *tag) +{ + colorpair_t *list = sp->_color_pairs; + char bigbuf[256 * 20]; + char *p = bigbuf; + int n; + size_t have = sizeof(bigbuf); + + _nc_STRCPY(p, tag, have); + for (n = 0; n < sp->_pair_limit; ++n) { + if (list[n].mode != cpFREE) { + p += strlen(p); + if ((size_t) (p - bigbuf) + 50 > have) + break; + _nc_SPRINTF(p, _nc_SLIMIT(have - (p - bigbuf)) + " %d%c(%d,%d)", + n, n == pair ? '@' : ':', list[n].next, list[n].prev); + } + } + T(("(%d/%d) %ld - %s", + next_len(sp, 0), + prev_len(sp, 0), + strlen(bigbuf), bigbuf)); + + if (next_len(sp, 0) != prev_len(sp, 0)) { + endwin(); + ExitProgram(EXIT_FAILURE); + } +} +#else +#define dumpit(sp, pair, tag) /* nothing */ +#endif + +static int +compare_data(const void *a, const void *b) +{ + const colorpair_t *p = (const colorpair_t *) a; + const colorpair_t *q = (const colorpair_t *) b; + return ((p->fg == q->fg) + ? (p->bg - q->bg) + : (p->fg - q->fg)); +} + +static int +_nc_find_color_pair(SCREEN *sp, int fg, int bg) +{ + colorpair_t find; + int result; + void *pp; + + find.fg = fg; + find.bg = bg; + if (sp != 0 && + (pp = tfind(&find, &sp->_ordered_pairs, compare_data)) != 0) { + colorpair_t *temp = *(colorpair_t **) pp; + result = (int) (temp - sp->_color_pairs); + } else { + result = -1; + } + return result; +} + +static void +delink_color_pair(SCREEN *sp, int pair) +{ + colorpair_t *list = sp->_color_pairs; + int prev = list[pair].prev; + int next = list[pair].next; + + /* delink this from its current location */ + if (list[prev].next == pair && + list[next].prev == pair) { + list[prev].next = next; + list[next].prev = prev; + dumpit(sp, pair, "delinked"); + } +} + +/* + * Discard all nodes in the fast-index. + */ +NCURSES_EXPORT(void) +_nc_free_ordered_pairs(SCREEN *sp) +{ + if (sp && sp->_ordered_pairs && sp->_pair_alloc) { + int n; + for (n = 0; n < sp->_pair_alloc; ++n) { + tdelete(&sp->_color_pairs[n], &sp->_ordered_pairs, compare_data); + } + } +} + +/* + * Use this call to update the fast-index when modifying an entry in the color + * pair table. + */ +NCURSES_EXPORT(void) +_nc_reset_color_pair(SCREEN *sp, int pair, colorpair_t * next) +{ + colorpair_t *last; + if (ValidPair(sp, pair)) { + ReservePairs(sp, pair); + last = &(sp->_color_pairs[pair]); + delink_color_pair(sp, pair); + if (last->mode > cpFREE && + (last->fg != next->fg || last->bg != next->bg)) { + /* remove the old entry from fast index */ + tdelete(last, &sp->_ordered_pairs, compare_data); + /* create a new entry in fast index */ + *last = *next; + tsearch(last, &sp->_ordered_pairs, compare_data); + } + } +} + +/* + * Use this call to relink the newest pair to the front of the list, keeping + * "0" first. + */ +NCURSES_EXPORT(void) +_nc_set_color_pair(SCREEN *sp, int pair, int mode) +{ + if (ValidPair(sp, pair)) { + colorpair_t *list = sp->_color_pairs; + dumpit(sp, pair, "SET_PAIR"); + list[0].mode = cpKEEP; + if (list[pair].mode <= cpFREE) + sp->_pairs_used++; + list[pair].mode = mode; + if (list[0].next != pair) { + /* link it at the front of the list */ + list[pair].next = list[0].next; + list[list[pair].next].prev = pair; + list[pair].prev = 0; + list[0].next = pair; + } + dumpit(sp, pair, "...after"); + } +} + +/* + * If we reallocate the color-pair array, we have to adjust the fast-index. + */ +NCURSES_EXPORT(void) +_nc_copy_pairs(SCREEN *sp, colorpair_t * target, colorpair_t * source, int length) +{ + int n; + for (n = 0; n < length; ++n) { + void *find = tfind(source + n, &sp->_ordered_pairs, compare_data); + if (find != 0) { + tdelete(source + n, &sp->_ordered_pairs, compare_data); + tsearch(target + n, &sp->_ordered_pairs, compare_data); + } + } +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(alloc_pair) (NCURSES_SP_DCLx int fg, int bg) +{ + int pair; + + T((T_CALLED("alloc_pair(%d,%d)"), fg, bg)); + if (SP_PARM == 0) { + pair = -1; + } else if ((pair = _nc_find_color_pair(SP_PARM, fg, bg)) < 0) { + /* + * Check if all of the slots have been used. If not, find one and + * use that. + */ + if (SP_PARM->_pairs_used + 1 < SP_PARM->_pair_limit) { + bool found = FALSE; + int hint = SP_PARM->_recent_pair; + + /* + * The linear search is done to allow mixing calls to init_pair() + * and alloc_pair(). The former can make gaps... + */ + for (pair = hint + 1; pair < SP_PARM->_pair_alloc; pair++) { + if (SP_PARM->_color_pairs[pair].mode == cpFREE) { + T(("found gap %d", pair)); + found = TRUE; + break; + } + } + if (!found && (SP_PARM->_pair_alloc < SP_PARM->_pair_limit)) { + pair = SP_PARM->_pair_alloc; + ReservePairs(SP_PARM, pair); + if (SP_PARM->_color_pairs == 0) { + pair = -1; + } else { + found = TRUE; + } + } + if (!found) { + for (pair = 1; pair <= hint; pair++) { + if (SP_PARM->_color_pairs[pair].mode == cpFREE) { + T(("found gap %d", pair)); + found = TRUE; + break; + } + } + } + if (found) { + SP_PARM->_recent_pair = pair; + } else { + pair = ERR; + } + } else { + /* reuse the oldest one */ + pair = SP_PARM->_color_pairs[0].prev; + T(("reusing %d", pair)); + } + + if (_nc_init_pair(SP_PARM, pair, fg, bg) == ERR) + pair = ERR; + } + returnCode(pair); +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(find_pair) (NCURSES_SP_DCLx int fg, int bg) +{ + int pair; + + T((T_CALLED("find_pair(%d,%d)"), fg, bg)); + pair = _nc_find_color_pair(SP_PARM, fg, bg); + returnCode(pair); +} + +NCURSES_EXPORT(int) +NCURSES_SP_NAME(free_pair) (NCURSES_SP_DCLx int pair) +{ + int result = ERR; + T((T_CALLED("free_pair(%d)"), pair)); + if (ValidPair(SP_PARM, pair) && pair < SP_PARM->_pair_alloc) { + colorpair_t *cp = &(SP_PARM->_color_pairs[pair]); + if (pair != 0) { + _nc_change_pair(SP_PARM, pair); + delink_color_pair(SP_PARM, pair); + tdelete(cp, &SP_PARM->_ordered_pairs, compare_data); + cp->mode = cpFREE; + result = OK; + SP_PARM->_pairs_used--; + } + } + returnCode(result); +} + +#if NCURSES_SP_FUNCS +NCURSES_EXPORT(int) +alloc_pair(int f, int b) +{ + return NCURSES_SP_NAME(alloc_pair) (CURRENT_SCREEN, f, b); +} + +NCURSES_EXPORT(int) +find_pair(int f, int b) +{ + return NCURSES_SP_NAME(find_pair) (CURRENT_SCREEN, f, b); +} + +NCURSES_EXPORT(int) +free_pair(int pair) +{ + return NCURSES_SP_NAME(free_pair) (CURRENT_SCREEN, pair); +} +#endif + +#if NO_LEAKS +NCURSES_EXPORT(void) +_nc_new_pair_leaks(SCREEN *sp) +{ + if (sp->_color_pairs) { + while (sp->_color_pairs[0].next) { + free_pair(sp->_color_pairs[0].next); + } + } +} +#endif + +#else +void _nc_new_pair(void); +void +_nc_new_pair(void) +{ +} +#endif /* NCURSES_EXT_COLORS */ |