150276Speter/**************************************************************************** 2184989Srafan * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * 350276Speter * * 450276Speter * Permission is hereby granted, free of charge, to any person obtaining a * 550276Speter * copy of this software and associated documentation files (the * 650276Speter * "Software"), to deal in the Software without restriction, including * 750276Speter * without limitation the rights to use, copy, modify, merge, publish, * 850276Speter * distribute, distribute with modifications, sublicense, and/or sell * 950276Speter * copies of the Software, and to permit persons to whom the Software is * 1050276Speter * furnished to do so, subject to the following conditions: * 1150276Speter * * 1250276Speter * The above copyright notice and this permission notice shall be included * 1350276Speter * in all copies or substantial portions of the Software. * 1450276Speter * * 1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 2250276Speter * * 2350276Speter * Except as contained in this notice, the name(s) of the above copyright * 2450276Speter * holders shall not be used in advertising or otherwise to promote the * 2550276Speter * sale, use or other dealings in this Software without prior written * 2650276Speter * authorization. * 2750276Speter ****************************************************************************/ 2850276Speter 2950276Speter/**************************************************************************** 3050276Speter * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 3150276Speter * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32166124Srafan * and: Thomas E. Dickey 1996-on * 3350276Speter ****************************************************************************/ 3450276Speter 3550276Speter/* 3650276Speter * alloc_entry.c -- allocation functions for terminfo entries 3750276Speter * 3850276Speter * _nc_copy_entry() 3950276Speter * _nc_init_entry() 4050276Speter * _nc_merge_entry() 4150276Speter * _nc_save_str() 4250276Speter * _nc_wrap_entry() 4350276Speter * 4450276Speter */ 4550276Speter 4650276Speter#include <curses.priv.h> 4750276Speter 4850276Speter#include <tic.h> 4950276Speter#include <term_entry.h> 5050276Speter 51184989SrafanMODULE_ID("$Id: alloc_entry.c,v 1.48 2008/08/16 16:25:31 tom Exp $") 5250276Speter 5350276Speter#define ABSENT_OFFSET -1 5450276Speter#define CANCELLED_OFFSET -2 5550276Speter 5650276Speter#define MAX_STRTAB 4096 /* documented maximum entry size */ 5750276Speter 5897049Speterstatic char *stringbuf; /* buffer for string capabilities */ 5962449Speterstatic size_t next_free; /* next free character in stringbuf */ 6050276Speter 6176726SpeterNCURSES_EXPORT(void) 62166124Srafan_nc_init_entry(TERMTYPE *const tp) 6350276Speter/* initialize a terminal type data block */ 6450276Speter{ 65166124Srafan unsigned i; 6650276Speter 67166124Srafan#if NO_LEAKS 68166124Srafan if (tp == 0 && stringbuf != 0) { 69166124Srafan FreeAndNull(stringbuf); 70166124Srafan return; 71166124Srafan } 72166124Srafan#endif 73166124Srafan 7497049Speter if (stringbuf == 0) 75166124Srafan stringbuf = (char *) malloc(MAX_STRTAB); 7697049Speter 7750276Speter#if NCURSES_XNAMES 7862449Speter tp->num_Booleans = BOOLCOUNT; 7962449Speter tp->num_Numbers = NUMCOUNT; 8062449Speter tp->num_Strings = STRCOUNT; 8162449Speter tp->ext_Booleans = 0; 8262449Speter tp->ext_Numbers = 0; 8362449Speter tp->ext_Strings = 0; 8450276Speter#endif 8562449Speter if (tp->Booleans == 0) 86166124Srafan tp->Booleans = typeMalloc(NCURSES_SBOOL, BOOLCOUNT); 8762449Speter if (tp->Numbers == 0) 8862449Speter tp->Numbers = typeMalloc(short, NUMCOUNT); 8962449Speter if (tp->Strings == 0) 9062449Speter tp->Strings = typeMalloc(char *, STRCOUNT); 9150276Speter 9262449Speter for_each_boolean(i, tp) 9362449Speter tp->Booleans[i] = FALSE; 9450276Speter 9562449Speter for_each_number(i, tp) 9662449Speter tp->Numbers[i] = ABSENT_NUMERIC; 9750276Speter 9862449Speter for_each_string(i, tp) 9962449Speter tp->Strings[i] = ABSENT_STRING; 10050276Speter 10162449Speter next_free = 0; 10250276Speter} 10350276Speter 10476726SpeterNCURSES_EXPORT(ENTRY *) 10562449Speter_nc_copy_entry(ENTRY * oldp) 10650276Speter{ 10762449Speter ENTRY *newp = typeCalloc(ENTRY, 1); 10850276Speter 10962449Speter if (newp != 0) { 11062449Speter *newp = *oldp; 11162449Speter _nc_copy_termtype(&(newp->tterm), &(oldp->tterm)); 11262449Speter } 11362449Speter return newp; 11450276Speter} 11550276Speter 116166124Srafan/* save a copy of string in the string buffer */ 11776726SpeterNCURSES_EXPORT(char *) 11862449Speter_nc_save_str(const char *const string) 11950276Speter{ 120166124Srafan char *result = 0; 12162449Speter size_t old_next_free = next_free; 12262449Speter size_t len = strlen(string) + 1; 12350276Speter 124166124Srafan if (len == 1 && next_free != 0) { 125166124Srafan /* 126166124Srafan * Cheat a little by making an empty string point to the end of the 127166124Srafan * previous string. 128166124Srafan */ 129166124Srafan if (next_free < MAX_STRTAB) { 130166124Srafan result = (stringbuf + next_free - 1); 131166124Srafan } 132166124Srafan } else if (next_free + len < MAX_STRTAB) { 13362449Speter strcpy(&stringbuf[next_free], string); 13462449Speter DEBUG(7, ("Saved string %s", _nc_visbuf(string))); 13562449Speter DEBUG(7, ("at location %d", (int) next_free)); 13662449Speter next_free += len; 137166124Srafan result = (stringbuf + old_next_free); 138166124Srafan } else { 139166124Srafan _nc_warning("Too much data, some is lost"); 14062449Speter } 141166124Srafan return result; 14250276Speter} 14350276Speter 14476726SpeterNCURSES_EXPORT(void) 14576726Speter_nc_wrap_entry(ENTRY * const ep, bool copy_strings) 14650276Speter/* copy the string parts to allocated storage, preserving pointers to it */ 14750276Speter{ 148184989Srafan int offsets[MAX_ENTRY_SIZE / sizeof(short)]; 149184989Srafan int useoffsets[MAX_USES]; 150166124Srafan unsigned i, n; 151166124Srafan unsigned nuses = ep->nuses; 15262449Speter TERMTYPE *tp = &(ep->tterm); 15350276Speter 15476726Speter if (copy_strings) { 15576726Speter next_free = 0; /* clear static storage */ 15676726Speter 15776726Speter /* copy term_names, Strings, uses */ 15876726Speter tp->term_names = _nc_save_str(tp->term_names); 15976726Speter for_each_string(i, tp) { 16076726Speter if (tp->Strings[i] != ABSENT_STRING && 16176726Speter tp->Strings[i] != CANCELLED_STRING) { 16276726Speter tp->Strings[i] = _nc_save_str(tp->Strings[i]); 16376726Speter } 16476726Speter } 16576726Speter 166166124Srafan for (i = 0; i < nuses; i++) { 16776726Speter if (ep->uses[i].name == 0) { 16876726Speter ep->uses[i].name = _nc_save_str(ep->uses[i].name); 16976726Speter } 17076726Speter } 17176726Speter 17276726Speter free(tp->str_table); 17376726Speter } 17476726Speter 175184989Srafan assert(tp->term_names >= stringbuf); 176184989Srafan n = (unsigned) (tp->term_names - stringbuf); 17762449Speter for_each_string(i, &(ep->tterm)) { 178184989Srafan if (i < SIZEOF(offsets)) { 179184989Srafan if (tp->Strings[i] == ABSENT_STRING) { 180184989Srafan offsets[i] = ABSENT_OFFSET; 181184989Srafan } else if (tp->Strings[i] == CANCELLED_STRING) { 182184989Srafan offsets[i] = CANCELLED_OFFSET; 183184989Srafan } else { 184184989Srafan offsets[i] = tp->Strings[i] - stringbuf; 185184989Srafan } 186184989Srafan } 18762449Speter } 18850276Speter 189166124Srafan for (i = 0; i < nuses; i++) { 19062449Speter if (ep->uses[i].name == 0) 19162449Speter useoffsets[i] = ABSENT_OFFSET; 19262449Speter else 19362449Speter useoffsets[i] = ep->uses[i].name - stringbuf; 19462449Speter } 19550276Speter 19662449Speter if ((tp->str_table = typeMalloc(char, next_free)) == (char *) 0) 197166124Srafan _nc_err_abort(MSG_NO_MEMORY); 19862449Speter (void) memcpy(tp->str_table, stringbuf, next_free); 19950276Speter 20062449Speter tp->term_names = tp->str_table + n; 20162449Speter for_each_string(i, &(ep->tterm)) { 202184989Srafan if (i < SIZEOF(offsets)) { 203184989Srafan if (offsets[i] == ABSENT_OFFSET) { 204184989Srafan tp->Strings[i] = ABSENT_STRING; 205184989Srafan } else if (offsets[i] == CANCELLED_OFFSET) { 206184989Srafan tp->Strings[i] = CANCELLED_STRING; 207184989Srafan } else { 208184989Srafan tp->Strings[i] = tp->str_table + offsets[i]; 209184989Srafan } 210184989Srafan } 21162449Speter } 21250276Speter 21350276Speter#if NCURSES_XNAMES 21476726Speter if (!copy_strings) { 215184989Srafan if ((n = (unsigned) NUM_EXT_NAMES(tp)) != 0) { 216184989Srafan if (n < SIZEOF(offsets)) { 217184989Srafan unsigned length = 0; 218184989Srafan for (i = 0; i < n; i++) { 219184989Srafan length += strlen(tp->ext_Names[i]) + 1; 220184989Srafan offsets[i] = tp->ext_Names[i] - stringbuf; 221184989Srafan } 222184989Srafan if ((tp->ext_str_table = typeMalloc(char, length)) == 0) 223184989Srafan _nc_err_abort(MSG_NO_MEMORY); 224184989Srafan for (i = 0, length = 0; i < n; i++) { 225184989Srafan tp->ext_Names[i] = tp->ext_str_table + length; 226184989Srafan strcpy(tp->ext_Names[i], stringbuf + offsets[i]); 227184989Srafan length += strlen(tp->ext_Names[i]) + 1; 228184989Srafan } 22976726Speter } 23050276Speter } 23162449Speter } 23250276Speter#endif 23350276Speter 234166124Srafan for (i = 0; i < nuses; i++) { 23562449Speter if (useoffsets[i] == ABSENT_OFFSET) 23662449Speter ep->uses[i].name = 0; 23762449Speter else 23862449Speter ep->uses[i].name = (tp->str_table + useoffsets[i]); 23962449Speter } 24050276Speter} 24150276Speter 24276726SpeterNCURSES_EXPORT(void) 243166124Srafan_nc_merge_entry(TERMTYPE *const to, TERMTYPE *const from) 24450276Speter/* merge capabilities from `from' entry into `to' entry */ 24550276Speter{ 246166124Srafan unsigned i; 24750276Speter 24850276Speter#if NCURSES_XNAMES 24950276Speter _nc_align_termtype(to, from); 25050276Speter#endif 25162449Speter for_each_boolean(i, from) { 252166124Srafan if (to->Booleans[i] != (char) CANCELLED_BOOLEAN) { 253166124Srafan int mergebool = from->Booleans[i]; 25450276Speter 255166124Srafan if (mergebool == CANCELLED_BOOLEAN) 256166124Srafan to->Booleans[i] = FALSE; 257166124Srafan else if (mergebool == TRUE) 258184989Srafan to->Booleans[i] = (char) mergebool; 259166124Srafan } 26050276Speter } 26150276Speter 26262449Speter for_each_number(i, from) { 263166124Srafan if (to->Numbers[i] != CANCELLED_NUMERIC) { 264184989Srafan short mergenum = from->Numbers[i]; 26550276Speter 266166124Srafan if (mergenum == CANCELLED_NUMERIC) 267166124Srafan to->Numbers[i] = ABSENT_NUMERIC; 268166124Srafan else if (mergenum != ABSENT_NUMERIC) 269166124Srafan to->Numbers[i] = mergenum; 270166124Srafan } 27150276Speter } 27250276Speter 27350276Speter /* 27450276Speter * Note: the copies of strings this makes don't have their own 27550276Speter * storage. This is OK right now, but will be a problem if we 27650276Speter * we ever want to deallocate entries. 27750276Speter */ 27862449Speter for_each_string(i, from) { 279166124Srafan if (to->Strings[i] != CANCELLED_STRING) { 280166124Srafan char *mergestring = from->Strings[i]; 28150276Speter 282166124Srafan if (mergestring == CANCELLED_STRING) 283166124Srafan to->Strings[i] = ABSENT_STRING; 284166124Srafan else if (mergestring != ABSENT_STRING) 285166124Srafan to->Strings[i] = mergestring; 286166124Srafan } 28750276Speter } 28850276Speter} 289166124Srafan 290166124Srafan#if NO_LEAKS 291166124SrafanNCURSES_EXPORT(void) 292166124Srafan_nc_alloc_entry_leaks(void) 293166124Srafan{ 294166124Srafan if (stringbuf != 0) { 295166124Srafan FreeAndNull(stringbuf); 296166124Srafan } 297166124Srafan next_free = 0; 298166124Srafan} 299166124Srafan#endif 300