xref: /freebsd/contrib/ncurses/ncurses/tinfo/alloc_entry.c (revision 21817992b3314c908ab50f0bb88d2ee750b9c4ac)
10e3d5408SPeter Wemm /****************************************************************************
2*21817992SBaptiste Daroussin  * Copyright 2018-2022,2023 Thomas E. Dickey                                *
3e1865124SBaptiste Daroussin  * Copyright 1998-2013,2017 Free Software Foundation, Inc.                  *
40e3d5408SPeter Wemm  *                                                                          *
50e3d5408SPeter Wemm  * Permission is hereby granted, free of charge, to any person obtaining a  *
60e3d5408SPeter Wemm  * copy of this software and associated documentation files (the            *
70e3d5408SPeter Wemm  * "Software"), to deal in the Software without restriction, including      *
80e3d5408SPeter Wemm  * without limitation the rights to use, copy, modify, merge, publish,      *
90e3d5408SPeter Wemm  * distribute, distribute with modifications, sublicense, and/or sell       *
100e3d5408SPeter Wemm  * copies of the Software, and to permit persons to whom the Software is    *
110e3d5408SPeter Wemm  * furnished to do so, subject to the following conditions:                 *
120e3d5408SPeter Wemm  *                                                                          *
130e3d5408SPeter Wemm  * The above copyright notice and this permission notice shall be included  *
140e3d5408SPeter Wemm  * in all copies or substantial portions of the Software.                   *
150e3d5408SPeter Wemm  *                                                                          *
160e3d5408SPeter Wemm  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
170e3d5408SPeter Wemm  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
180e3d5408SPeter Wemm  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
190e3d5408SPeter Wemm  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
200e3d5408SPeter Wemm  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
210e3d5408SPeter Wemm  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
220e3d5408SPeter Wemm  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
230e3d5408SPeter Wemm  *                                                                          *
240e3d5408SPeter Wemm  * Except as contained in this notice, the name(s) of the above copyright   *
250e3d5408SPeter Wemm  * holders shall not be used in advertising or otherwise to promote the     *
260e3d5408SPeter Wemm  * sale, use or other dealings in this Software without prior written       *
270e3d5408SPeter Wemm  * authorization.                                                           *
280e3d5408SPeter Wemm  ****************************************************************************/
290e3d5408SPeter Wemm 
300e3d5408SPeter Wemm /****************************************************************************
310e3d5408SPeter Wemm  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
320e3d5408SPeter Wemm  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
334a1a9510SRong-En Fan  *     and: Thomas E. Dickey                        1996-on                 *
340e3d5408SPeter Wemm  ****************************************************************************/
350e3d5408SPeter Wemm 
360e3d5408SPeter Wemm /*
370e3d5408SPeter Wemm  * alloc_entry.c -- allocation functions for terminfo entries
380e3d5408SPeter Wemm  *
390e3d5408SPeter Wemm  *	_nc_copy_entry()
400e3d5408SPeter Wemm  *	_nc_init_entry()
410e3d5408SPeter Wemm  *	_nc_merge_entry()
420e3d5408SPeter Wemm  *	_nc_save_str()
430e3d5408SPeter Wemm  *	_nc_wrap_entry()
440e3d5408SPeter Wemm  *
450e3d5408SPeter Wemm  */
460e3d5408SPeter Wemm 
470e3d5408SPeter Wemm #include <curses.priv.h>
480e3d5408SPeter Wemm 
490e3d5408SPeter Wemm #include <tic.h>
500e3d5408SPeter Wemm 
51*21817992SBaptiste Daroussin MODULE_ID("$Id: alloc_entry.c,v 1.79 2023/09/15 08:16:12 tom Exp $")
520e3d5408SPeter Wemm 
530e3d5408SPeter Wemm #define ABSENT_OFFSET    -1
540e3d5408SPeter Wemm #define CANCELLED_OFFSET -2
550e3d5408SPeter Wemm 
5639f2269fSPeter Wemm static char *stringbuf;		/* buffer for string capabilities */
570e3d5408SPeter Wemm static size_t next_free;	/* next free character in stringbuf */
580e3d5408SPeter Wemm 
597a69bbfbSPeter Wemm NCURSES_EXPORT(void)
_nc_init_entry(ENTRY * const tp)60aae38d10SBaptiste Daroussin _nc_init_entry(ENTRY * const tp)
610e3d5408SPeter Wemm /* initialize a terminal type data block */
620e3d5408SPeter Wemm {
63*21817992SBaptiste Daroussin     DEBUG(2, (T_CALLED("_nc_init_entry(tp=%p)"), (void *) tp));
64*21817992SBaptiste Daroussin 
65*21817992SBaptiste Daroussin     if (tp == NULL) {
664a1a9510SRong-En Fan #if NO_LEAKS
67*21817992SBaptiste Daroussin 	if (stringbuf != NULL) {
684a1a9510SRong-En Fan 	    FreeAndNull(stringbuf);
6906bfebdeSXin LI 	}
704a1a9510SRong-En Fan 	return;
71*21817992SBaptiste Daroussin #else
72*21817992SBaptiste Daroussin 	_nc_err_abort("_nc_init_entry called without initialization");
734a1a9510SRong-En Fan #endif
74*21817992SBaptiste Daroussin     }
750e3d5408SPeter Wemm 
76*21817992SBaptiste Daroussin     if (stringbuf == NULL)
77*21817992SBaptiste Daroussin 	TYPE_CALLOC(char, (size_t) MAX_ENTRY_SIZE, stringbuf);
780e3d5408SPeter Wemm 
790e3d5408SPeter Wemm     next_free = 0;
8073f0a83dSXin LI 
81aae38d10SBaptiste Daroussin     _nc_init_termtype(&(tp->tterm));
82*21817992SBaptiste Daroussin 
83*21817992SBaptiste Daroussin     DEBUG(2, (T_RETURN("")));
840e3d5408SPeter Wemm }
850e3d5408SPeter Wemm 
867a69bbfbSPeter Wemm NCURSES_EXPORT(ENTRY *)
_nc_copy_entry(ENTRY * oldp)8715589c42SPeter Wemm _nc_copy_entry(ENTRY * oldp)
880e3d5408SPeter Wemm {
89*21817992SBaptiste Daroussin     ENTRY *newp;
900e3d5408SPeter Wemm 
91*21817992SBaptiste Daroussin     DEBUG(2, (T_CALLED("_nc_copy_entry(oldp=%p)"), (void *) oldp));
92*21817992SBaptiste Daroussin 
93*21817992SBaptiste Daroussin     newp = typeCalloc(ENTRY, 1);
94*21817992SBaptiste Daroussin     if (newp != NULL) {
950e3d5408SPeter Wemm 	*newp = *oldp;
96aae38d10SBaptiste Daroussin 	_nc_copy_termtype2(&(newp->tterm), &(oldp->tterm));
970e3d5408SPeter Wemm     }
98*21817992SBaptiste Daroussin 
99*21817992SBaptiste Daroussin     DEBUG(2, (T_RETURN("%p"), (void *) newp));
100*21817992SBaptiste Daroussin     return (newp);
1010e3d5408SPeter Wemm }
1020e3d5408SPeter Wemm 
1034a1a9510SRong-En Fan /* save a copy of string in the string buffer */
1047a69bbfbSPeter Wemm NCURSES_EXPORT(char *)
_nc_save_str(const char * string)105*21817992SBaptiste Daroussin _nc_save_str(const char *string)
1060e3d5408SPeter Wemm {
1074a1a9510SRong-En Fan     char *result = 0;
1080e3d5408SPeter Wemm     size_t old_next_free = next_free;
109*21817992SBaptiste Daroussin 
110*21817992SBaptiste Daroussin     if (stringbuf != NULL) {
111aae38d10SBaptiste Daroussin 	size_t len;
112aae38d10SBaptiste Daroussin 
113aae38d10SBaptiste Daroussin 	if (!VALID_STRING(string))
114*21817992SBaptiste Daroussin 	    string = "";
115aae38d10SBaptiste Daroussin 	len = strlen(string) + 1;
1160e3d5408SPeter Wemm 
1174a1a9510SRong-En Fan 	if (len == 1 && next_free != 0) {
1184a1a9510SRong-En Fan 	    /*
1194a1a9510SRong-En Fan 	     * Cheat a little by making an empty string point to the end of the
1204a1a9510SRong-En Fan 	     * previous string.
1214a1a9510SRong-En Fan 	     */
122*21817992SBaptiste Daroussin 	    if (next_free < MAX_ENTRY_SIZE) {
1234a1a9510SRong-En Fan 		result = (stringbuf + next_free - 1);
1244a1a9510SRong-En Fan 	    }
125*21817992SBaptiste Daroussin 	} else if (next_free + len < MAX_ENTRY_SIZE) {
126*21817992SBaptiste Daroussin 	    _nc_STRCPY(&stringbuf[next_free], string, MAX_ENTRY_SIZE);
1270e3d5408SPeter Wemm 	    DEBUG(7, ("Saved string %s", _nc_visbuf(string)));
1280e3d5408SPeter Wemm 	    DEBUG(7, ("at location %d", (int) next_free));
1290e3d5408SPeter Wemm 	    next_free += len;
1304a1a9510SRong-En Fan 	    result = (stringbuf + old_next_free);
1314a1a9510SRong-En Fan 	} else {
13273f0a83dSXin LI 	    _nc_warning("Too much data, some is lost: %s", string);
1330e3d5408SPeter Wemm 	}
134*21817992SBaptiste Daroussin     }
1354a1a9510SRong-En Fan     return result;
1360e3d5408SPeter Wemm }
1370e3d5408SPeter Wemm 
1387a69bbfbSPeter Wemm NCURSES_EXPORT(void)
_nc_wrap_entry(ENTRY * const ep,bool copy_strings)1397a69bbfbSPeter Wemm _nc_wrap_entry(ENTRY * const ep, bool copy_strings)
1400e3d5408SPeter Wemm /* copy the string parts to allocated storage, preserving pointers to it */
1410e3d5408SPeter Wemm {
1425d08fb1fSRong-En Fan     int offsets[MAX_ENTRY_SIZE / sizeof(short)];
1435d08fb1fSRong-En Fan     int useoffsets[MAX_USES];
1444a1a9510SRong-En Fan     unsigned i, n;
145*21817992SBaptiste Daroussin     unsigned nuses;
146*21817992SBaptiste Daroussin     TERMTYPE2 *tp;
1470e3d5408SPeter Wemm 
148*21817992SBaptiste Daroussin     DEBUG(2, (T_CALLED("_nc_wrap_entry(ep=%p, copy_strings=%d)"), (void *)
149*21817992SBaptiste Daroussin 	      ep, copy_strings));
150*21817992SBaptiste Daroussin     if (ep == NULL || stringbuf == NULL)
151*21817992SBaptiste Daroussin 	_nc_err_abort("_nc_wrap_entry called without initialization");
152*21817992SBaptiste Daroussin 
153*21817992SBaptiste Daroussin     nuses = ep->nuses;
154*21817992SBaptiste Daroussin     tp = &(ep->tterm);
1557a69bbfbSPeter Wemm     if (copy_strings) {
1567a69bbfbSPeter Wemm 	next_free = 0;		/* clear static storage */
1577a69bbfbSPeter Wemm 
1587a69bbfbSPeter Wemm 	/* copy term_names, Strings, uses */
1597a69bbfbSPeter Wemm 	tp->term_names = _nc_save_str(tp->term_names);
1607a69bbfbSPeter Wemm 	for_each_string(i, tp) {
161*21817992SBaptiste Daroussin 	    if (VALID_STRING(tp->Strings[i])) {
1627a69bbfbSPeter Wemm 		tp->Strings[i] = _nc_save_str(tp->Strings[i]);
1637a69bbfbSPeter Wemm 	    }
1647a69bbfbSPeter Wemm 	}
1657a69bbfbSPeter Wemm 
1664a1a9510SRong-En Fan 	for (i = 0; i < nuses; i++) {
1677a69bbfbSPeter Wemm 	    if (ep->uses[i].name == 0) {
1687a69bbfbSPeter Wemm 		ep->uses[i].name = _nc_save_str(ep->uses[i].name);
1697a69bbfbSPeter Wemm 	    }
1707a69bbfbSPeter Wemm 	}
1717a69bbfbSPeter Wemm 
1727a69bbfbSPeter Wemm 	free(tp->str_table);
1737a69bbfbSPeter Wemm     }
1747a69bbfbSPeter Wemm 
1755d08fb1fSRong-En Fan     assert(tp->term_names >= stringbuf);
1765d08fb1fSRong-En Fan     n = (unsigned) (tp->term_names - stringbuf);
1770e3d5408SPeter Wemm     for_each_string(i, &(ep->tterm)) {
1785d08fb1fSRong-En Fan 	if (i < SIZEOF(offsets)) {
1795d08fb1fSRong-En Fan 	    if (tp->Strings[i] == ABSENT_STRING) {
1800e3d5408SPeter Wemm 		offsets[i] = ABSENT_OFFSET;
1815d08fb1fSRong-En Fan 	    } else if (tp->Strings[i] == CANCELLED_STRING) {
1820e3d5408SPeter Wemm 		offsets[i] = CANCELLED_OFFSET;
1835d08fb1fSRong-En Fan 	    } else {
18406bfebdeSXin LI 		offsets[i] = (int) (tp->Strings[i] - stringbuf);
1850e3d5408SPeter Wemm 	    }
1865d08fb1fSRong-En Fan 	}
1875d08fb1fSRong-En Fan     }
1880e3d5408SPeter Wemm 
1894a1a9510SRong-En Fan     for (i = 0; i < nuses; i++) {
19015589c42SPeter Wemm 	if (ep->uses[i].name == 0)
1910e3d5408SPeter Wemm 	    useoffsets[i] = ABSENT_OFFSET;
1920e3d5408SPeter Wemm 	else
19306bfebdeSXin LI 	    useoffsets[i] = (int) (ep->uses[i].name - stringbuf);
1940e3d5408SPeter Wemm     }
1950e3d5408SPeter Wemm 
19673f0a83dSXin LI     TYPE_MALLOC(char, next_free, tp->str_table);
1970e3d5408SPeter Wemm     (void) memcpy(tp->str_table, stringbuf, next_free);
1980e3d5408SPeter Wemm 
1990e3d5408SPeter Wemm     tp->term_names = tp->str_table + n;
2000e3d5408SPeter Wemm     for_each_string(i, &(ep->tterm)) {
2015d08fb1fSRong-En Fan 	if (i < SIZEOF(offsets)) {
2025d08fb1fSRong-En Fan 	    if (offsets[i] == ABSENT_OFFSET) {
2030e3d5408SPeter Wemm 		tp->Strings[i] = ABSENT_STRING;
2045d08fb1fSRong-En Fan 	    } else if (offsets[i] == CANCELLED_OFFSET) {
2050e3d5408SPeter Wemm 		tp->Strings[i] = CANCELLED_STRING;
2065d08fb1fSRong-En Fan 	    } else {
2070e3d5408SPeter Wemm 		tp->Strings[i] = tp->str_table + offsets[i];
2080e3d5408SPeter Wemm 	    }
2095d08fb1fSRong-En Fan 	}
2105d08fb1fSRong-En Fan     }
2110e3d5408SPeter Wemm 
2120e3d5408SPeter Wemm #if NCURSES_XNAMES
2137a69bbfbSPeter Wemm     if (!copy_strings) {
2145d08fb1fSRong-En Fan 	if ((n = (unsigned) NUM_EXT_NAMES(tp)) != 0) {
2155d08fb1fSRong-En Fan 	    if (n < SIZEOF(offsets)) {
21606bfebdeSXin LI 		size_t length = 0;
21773f0a83dSXin LI 		size_t offset;
2180e3d5408SPeter Wemm 		for (i = 0; i < n; i++) {
2190e3d5408SPeter Wemm 		    length += strlen(tp->ext_Names[i]) + 1;
22006bfebdeSXin LI 		    offsets[i] = (int) (tp->ext_Names[i] - stringbuf);
2210e3d5408SPeter Wemm 		}
22273f0a83dSXin LI 		TYPE_MALLOC(char, length, tp->ext_str_table);
22373f0a83dSXin LI 		for (i = 0, offset = 0; i < n; i++) {
22473f0a83dSXin LI 		    tp->ext_Names[i] = tp->ext_str_table + offset;
22573f0a83dSXin LI 		    _nc_STRCPY(tp->ext_Names[i],
22673f0a83dSXin LI 			       stringbuf + offsets[i],
22773f0a83dSXin LI 			       length - offset);
22873f0a83dSXin LI 		    offset += strlen(tp->ext_Names[i]) + 1;
2290e3d5408SPeter Wemm 		}
2300e3d5408SPeter Wemm 	    }
2317a69bbfbSPeter Wemm 	}
2325d08fb1fSRong-En Fan     }
2330e3d5408SPeter Wemm #endif
2340e3d5408SPeter Wemm 
2354a1a9510SRong-En Fan     for (i = 0; i < nuses; i++) {
236*21817992SBaptiste Daroussin 	if (useoffsets[i] == ABSENT_OFFSET) {
23715589c42SPeter Wemm 	    ep->uses[i].name = 0;
238*21817992SBaptiste Daroussin 	} else {
239*21817992SBaptiste Daroussin 	    ep->uses[i].name = strdup(tp->str_table + useoffsets[i]);
2400e3d5408SPeter Wemm 	}
2410e3d5408SPeter Wemm     }
242*21817992SBaptiste Daroussin     DEBUG(2, (T_RETURN("")));
243*21817992SBaptiste Daroussin }
2440e3d5408SPeter Wemm 
2457a69bbfbSPeter Wemm NCURSES_EXPORT(void)
_nc_merge_entry(ENTRY * const target,ENTRY * const source)246aae38d10SBaptiste Daroussin _nc_merge_entry(ENTRY * const target, ENTRY * const source)
2470e3d5408SPeter Wemm /* merge capabilities from `from' entry into `to' entry */
2480e3d5408SPeter Wemm {
249aae38d10SBaptiste Daroussin     TERMTYPE2 *to = &(target->tterm);
250aae38d10SBaptiste Daroussin     TERMTYPE2 *from = &(source->tterm);
251aae38d10SBaptiste Daroussin #if NCURSES_XNAMES
252aae38d10SBaptiste Daroussin     TERMTYPE2 copy;
253*21817992SBaptiste Daroussin     size_t str_size, copy_size;
254*21817992SBaptiste Daroussin     char *str_table;
255aae38d10SBaptiste Daroussin #endif
2564a1a9510SRong-En Fan     unsigned i;
2570e3d5408SPeter Wemm 
258aae38d10SBaptiste Daroussin     if (source == 0 || from == 0 || target == 0 || to == 0)
259aae38d10SBaptiste Daroussin 	return;
260aae38d10SBaptiste Daroussin 
2610e3d5408SPeter Wemm #if NCURSES_XNAMES
262aae38d10SBaptiste Daroussin     _nc_copy_termtype2(&copy, from);
263aae38d10SBaptiste Daroussin     from = &copy;
2640e3d5408SPeter Wemm     _nc_align_termtype(to, from);
265*21817992SBaptiste Daroussin     /*
266*21817992SBaptiste Daroussin      * compute the maximum size of the string-table.
267*21817992SBaptiste Daroussin      */
268*21817992SBaptiste Daroussin     str_size = strlen(to->term_names) + 1;
269*21817992SBaptiste Daroussin     for_each_string(i, from) {
270*21817992SBaptiste Daroussin 	if (VALID_STRING(from->Strings[i]))
271*21817992SBaptiste Daroussin 	    str_size += strlen(from->Strings[i]) + 1;
272*21817992SBaptiste Daroussin     }
273*21817992SBaptiste Daroussin     for_each_string(i, to) {
274*21817992SBaptiste Daroussin 	if (VALID_STRING(to->Strings[i]))
275*21817992SBaptiste Daroussin 	    str_size += strlen(to->Strings[i]) + 1;
276*21817992SBaptiste Daroussin     }
277*21817992SBaptiste Daroussin     /* allocate a string-table large enough for both source/target, and
278*21817992SBaptiste Daroussin      * copy all of the strings into that table.  In the merge, we will
279*21817992SBaptiste Daroussin      * select from the original source/target lists to construct a new
280*21817992SBaptiste Daroussin      * target list.
281*21817992SBaptiste Daroussin      */
282*21817992SBaptiste Daroussin     if (str_size != 0) {
283*21817992SBaptiste Daroussin 	char *str_copied;
284*21817992SBaptiste Daroussin 	if ((str_table = malloc(str_size)) == NULL)
285*21817992SBaptiste Daroussin 	    _nc_err_abort(MSG_NO_MEMORY);
286*21817992SBaptiste Daroussin 	str_copied = str_table;
287*21817992SBaptiste Daroussin 	_nc_STRCPY(str_copied, to->term_names, str_size);
288*21817992SBaptiste Daroussin 	to->term_names = str_copied;
289*21817992SBaptiste Daroussin 	copy_size = strlen(str_copied) + 1;
290*21817992SBaptiste Daroussin 	str_copied += copy_size;
291*21817992SBaptiste Daroussin 	str_size -= copy_size;
292*21817992SBaptiste Daroussin 	for_each_string(i, from) {
293*21817992SBaptiste Daroussin 	    if (VALID_STRING(from->Strings[i])) {
294*21817992SBaptiste Daroussin 		_nc_STRCPY(str_copied, from->Strings[i], str_size);
295*21817992SBaptiste Daroussin 		from->Strings[i] = str_copied;
296*21817992SBaptiste Daroussin 		copy_size = strlen(str_copied) + 1;
297*21817992SBaptiste Daroussin 		str_copied += copy_size;
298*21817992SBaptiste Daroussin 		str_size -= copy_size;
299*21817992SBaptiste Daroussin 	    }
300*21817992SBaptiste Daroussin 	}
301*21817992SBaptiste Daroussin 	for_each_string(i, to) {
302*21817992SBaptiste Daroussin 	    if (VALID_STRING(to->Strings[i])) {
303*21817992SBaptiste Daroussin 		_nc_STRCPY(str_copied, to->Strings[i], str_size);
304*21817992SBaptiste Daroussin 		to->Strings[i] = str_copied;
305*21817992SBaptiste Daroussin 		copy_size = strlen(str_copied) + 1;
306*21817992SBaptiste Daroussin 		str_copied += copy_size;
307*21817992SBaptiste Daroussin 		str_size -= copy_size;
308*21817992SBaptiste Daroussin 	    }
309*21817992SBaptiste Daroussin 	}
310*21817992SBaptiste Daroussin 	free(to->str_table);
311*21817992SBaptiste Daroussin 	to->str_table = str_table;
312*21817992SBaptiste Daroussin 	free(from->str_table);
313*21817992SBaptiste Daroussin     }
314*21817992SBaptiste Daroussin     /*
315*21817992SBaptiste Daroussin      * Do the same for the extended-strings (i.e., lists of capabilities).
316*21817992SBaptiste Daroussin      */
317*21817992SBaptiste Daroussin     str_size = 0;
318*21817992SBaptiste Daroussin     for (i = 0; i < NUM_EXT_NAMES(from); ++i) {
319*21817992SBaptiste Daroussin 	if (VALID_STRING(from->ext_Names[i]))
320*21817992SBaptiste Daroussin 	    str_size += strlen(from->ext_Names[i]) + 1;
321*21817992SBaptiste Daroussin     }
322*21817992SBaptiste Daroussin     for (i = 0; i < NUM_EXT_NAMES(to); ++i) {
323*21817992SBaptiste Daroussin 	if (VALID_STRING(to->ext_Names[i]))
324*21817992SBaptiste Daroussin 	    str_size += strlen(to->ext_Names[i]) + 1;
325*21817992SBaptiste Daroussin     }
326*21817992SBaptiste Daroussin     /* allocate a string-table large enough for both source/target, and
327*21817992SBaptiste Daroussin      * copy all of the strings into that table.  In the merge, we will
328*21817992SBaptiste Daroussin      * select from the original source/target lists to construct a new
329*21817992SBaptiste Daroussin      * target list.
330*21817992SBaptiste Daroussin      */
331*21817992SBaptiste Daroussin     if (str_size != 0) {
332*21817992SBaptiste Daroussin 	char *str_copied;
333*21817992SBaptiste Daroussin 	if ((str_table = malloc(str_size)) == NULL)
334*21817992SBaptiste Daroussin 	    _nc_err_abort(MSG_NO_MEMORY);
335*21817992SBaptiste Daroussin 	str_copied = str_table;
336*21817992SBaptiste Daroussin 	for (i = 0; i < NUM_EXT_NAMES(from); ++i) {
337*21817992SBaptiste Daroussin 	    if (VALID_STRING(from->ext_Names[i])) {
338*21817992SBaptiste Daroussin 		_nc_STRCPY(str_copied, from->ext_Names[i], str_size);
339*21817992SBaptiste Daroussin 		from->ext_Names[i] = str_copied;
340*21817992SBaptiste Daroussin 		copy_size = strlen(str_copied) + 1;
341*21817992SBaptiste Daroussin 		str_copied += copy_size;
342*21817992SBaptiste Daroussin 		str_size -= copy_size;
343*21817992SBaptiste Daroussin 	    }
344*21817992SBaptiste Daroussin 	}
345*21817992SBaptiste Daroussin 	for (i = 0; i < NUM_EXT_NAMES(to); ++i) {
346*21817992SBaptiste Daroussin 	    if (VALID_STRING(to->ext_Names[i])) {
347*21817992SBaptiste Daroussin 		_nc_STRCPY(str_copied, to->ext_Names[i], str_size);
348*21817992SBaptiste Daroussin 		to->ext_Names[i] = str_copied;
349*21817992SBaptiste Daroussin 		copy_size = strlen(str_copied) + 1;
350*21817992SBaptiste Daroussin 		str_copied += copy_size;
351*21817992SBaptiste Daroussin 		str_size -= copy_size;
352*21817992SBaptiste Daroussin 	    }
353*21817992SBaptiste Daroussin 	}
354*21817992SBaptiste Daroussin 	free(to->ext_str_table);
355*21817992SBaptiste Daroussin 	to->ext_str_table = str_table;
356*21817992SBaptiste Daroussin 	free(from->ext_str_table);
357*21817992SBaptiste Daroussin     }
3580e3d5408SPeter Wemm #endif
35915589c42SPeter Wemm     for_each_boolean(i, from) {
360*21817992SBaptiste Daroussin 	if (to->Booleans[i] != (NCURSES_SBOOL) CANCELLED_BOOLEAN) {
3610e3d5408SPeter Wemm 	    int mergebool = from->Booleans[i];
3620e3d5408SPeter Wemm 
3630e3d5408SPeter Wemm 	    if (mergebool == CANCELLED_BOOLEAN)
3640e3d5408SPeter Wemm 		to->Booleans[i] = FALSE;
3650e3d5408SPeter Wemm 	    else if (mergebool == TRUE)
366aae38d10SBaptiste Daroussin 		to->Booleans[i] = (NCURSES_SBOOL) mergebool;
3670e3d5408SPeter Wemm 	}
3684a1a9510SRong-En Fan     }
3690e3d5408SPeter Wemm 
37015589c42SPeter Wemm     for_each_number(i, from) {
3714a1a9510SRong-En Fan 	if (to->Numbers[i] != CANCELLED_NUMERIC) {
372aae38d10SBaptiste Daroussin 	    int mergenum = from->Numbers[i];
3730e3d5408SPeter Wemm 
3740e3d5408SPeter Wemm 	    if (mergenum == CANCELLED_NUMERIC)
3750e3d5408SPeter Wemm 		to->Numbers[i] = ABSENT_NUMERIC;
3760e3d5408SPeter Wemm 	    else if (mergenum != ABSENT_NUMERIC)
377aae38d10SBaptiste Daroussin 		to->Numbers[i] = (NCURSES_INT2) mergenum;
3780e3d5408SPeter Wemm 	}
3794a1a9510SRong-En Fan     }
3800e3d5408SPeter Wemm 
3810e3d5408SPeter Wemm     /*
3820e3d5408SPeter Wemm      * Note: the copies of strings this makes don't have their own
3830e3d5408SPeter Wemm      * storage.  This is OK right now, but will be a problem if we
3840e3d5408SPeter Wemm      * we ever want to deallocate entries.
3850e3d5408SPeter Wemm      */
38615589c42SPeter Wemm     for_each_string(i, from) {
3874a1a9510SRong-En Fan 	if (to->Strings[i] != CANCELLED_STRING) {
3880e3d5408SPeter Wemm 	    char *mergestring = from->Strings[i];
3890e3d5408SPeter Wemm 
3900e3d5408SPeter Wemm 	    if (mergestring == CANCELLED_STRING)
3910e3d5408SPeter Wemm 		to->Strings[i] = ABSENT_STRING;
3920e3d5408SPeter Wemm 	    else if (mergestring != ABSENT_STRING)
3930e3d5408SPeter Wemm 		to->Strings[i] = mergestring;
3940e3d5408SPeter Wemm 	}
3950e3d5408SPeter Wemm     }
396aae38d10SBaptiste Daroussin #if NCURSES_XNAMES
397*21817992SBaptiste Daroussin     /* cleanup */
398aae38d10SBaptiste Daroussin     free(copy.Booleans);
399aae38d10SBaptiste Daroussin     free(copy.Numbers);
400aae38d10SBaptiste Daroussin     free(copy.Strings);
401aae38d10SBaptiste Daroussin     free(copy.ext_Names);
402aae38d10SBaptiste Daroussin #endif
4034a1a9510SRong-En Fan }
4044a1a9510SRong-En Fan 
4054a1a9510SRong-En Fan #if NO_LEAKS
4064a1a9510SRong-En Fan NCURSES_EXPORT(void)
_nc_alloc_entry_leaks(void)4074a1a9510SRong-En Fan _nc_alloc_entry_leaks(void)
4084a1a9510SRong-En Fan {
409*21817992SBaptiste Daroussin     if (stringbuf != NULL) {
4104a1a9510SRong-En Fan 	FreeAndNull(stringbuf);
4114a1a9510SRong-En Fan     }
4124a1a9510SRong-En Fan     next_free = 0;
4134a1a9510SRong-En Fan }
4144a1a9510SRong-En Fan #endif
415