1/****************************************************************************
2 * Copyright 2020,2023 Thomas E. Dickey                                     *
3 * Copyright 2013-2014,2016 Free Software Foundation, Inc.                  *
4 *                                                                          *
5 * Permission is hereby granted, free of charge, to any person obtaining a  *
6 * copy of this software and associated documentation files (the            *
7 * "Software"), to deal in the Software without restriction, including      *
8 * without limitation the rights to use, copy, modify, merge, publish,      *
9 * distribute, distribute with modifications, sublicense, and/or sell       *
10 * copies of the Software, and to permit persons to whom the Software is    *
11 * furnished to do so, subject to the following conditions:                 *
12 *                                                                          *
13 * The above copyright notice and this permission notice shall be included  *
14 * in all copies or substantial portions of the Software.                   *
15 *                                                                          *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
19 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
22 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
23 *                                                                          *
24 * Except as contained in this notice, the name(s) of the above copyright   *
25 * holders shall not be used in advertising or otherwise to promote the     *
26 * sale, use or other dealings in this Software without prior written       *
27 * authorization.                                                           *
28 ****************************************************************************/
29
30/****************************************************************************
31 *  Author: Thomas E. Dickey                        2013-on                 *
32 ****************************************************************************/
33
34/*
35**	Support for obsolete/unusual features.
36*/
37
38#include <curses.priv.h>
39
40MODULE_ID("$Id: obsolete.c,v 1.1 2023/10/17 09:52:09 nicm Exp $")
41
42/*
43 * Obsolete entrypoint retained for binary compatibility.
44 */
45NCURSES_EXPORT(void)
46NCURSES_SP_NAME(_nc_set_buffer) (NCURSES_SP_DCLx FILE *ofp, int buffered)
47{
48#if NCURSES_SP_FUNCS
49    (void) SP_PARM;
50#endif
51    (void) ofp;
52    (void) buffered;
53}
54
55#if NCURSES_SP_FUNCS
56NCURSES_EXPORT(void)
57_nc_set_buffer(FILE *ofp, int buffered)
58{
59    NCURSES_SP_NAME(_nc_set_buffer) (CURRENT_SCREEN, ofp, buffered);
60}
61#endif
62
63#if !HAVE_STRDUP
64NCURSES_EXPORT(char *)
65_nc_strdup(const char *s)
66{
67    char *result = 0;
68    if (s != 0) {
69	size_t need = strlen(s);
70	result = malloc(need + 1);
71	if (result != 0) {
72	    _nc_STRCPY(result, s, need);
73	}
74    }
75    return result;
76}
77#endif
78
79#if USE_MY_MEMMOVE
80#define DST ((char *)s1)
81#define SRC ((const char *)s2)
82NCURSES_EXPORT(void *)
83_nc_memmove(void *s1, const void *s2, size_t n)
84{
85    if (n != 0) {
86	if ((DST + n > SRC) && (SRC + n > DST)) {
87	    static char *bfr;
88	    static size_t length;
89	    register size_t j;
90	    if (length < n) {
91		length = (n * 3) / 2;
92		bfr = typeRealloc(char, length, bfr);
93	    }
94	    for (j = 0; j < n; j++)
95		bfr[j] = SRC[j];
96	    s2 = bfr;
97	}
98	while (n-- != 0)
99	    DST[n] = SRC[n];
100    }
101    return s1;
102}
103#endif /* USE_MY_MEMMOVE */
104
105#ifdef EXP_XTERM_1005
106NCURSES_EXPORT(int)
107_nc_conv_to_utf8(unsigned char *target, unsigned source, unsigned limit)
108{
109#define CH(n) UChar((source) >> ((n) * 8))
110    int rc = 0;
111
112    if (source <= 0x0000007f)
113	rc = 1;
114    else if (source <= 0x000007ff)
115	rc = 2;
116    else if (source <= 0x0000ffff)
117	rc = 3;
118    else if (source <= 0x001fffff)
119	rc = 4;
120    else if (source <= 0x03ffffff)
121	rc = 5;
122    else			/* (source <= 0x7fffffff) */
123	rc = 6;
124
125    if ((unsigned) rc > limit) {	/* whatever it is, we cannot decode it */
126	rc = 0;
127    }
128
129    if (target != 0) {
130	switch (rc) {
131	case 1:
132	    target[0] = CH(0);
133	    break;
134
135	case 2:
136	    target[1] = UChar(0x80 | (CH(0) & 0x3f));
137	    target[0] = UChar(0xc0 | (CH(0) >> 6) | ((CH(1) & 0x07) << 2));
138	    break;
139
140	case 3:
141	    target[2] = UChar(0x80 | (CH(0) & 0x3f));
142	    target[1] = UChar(0x80 | (CH(0) >> 6) | ((CH(1) & 0x0f) << 2));
143	    target[0] = UChar(0xe0 | ((int) (CH(1) & 0xf0) >> 4));
144	    break;
145
146	case 4:
147	    target[3] = UChar(0x80 | (CH(0) & 0x3f));
148	    target[2] = UChar(0x80 | (CH(0) >> 6) | ((CH(1) & 0x0f) << 2));
149	    target[1] = UChar(0x80 |
150			      ((int) (CH(1) & 0xf0) >> 4) |
151			      ((int) (CH(2) & 0x03) << 4));
152	    target[0] = UChar(0xf0 | ((int) (CH(2) & 0x1f) >> 2));
153	    break;
154
155	case 5:
156	    target[4] = UChar(0x80 | (CH(0) & 0x3f));
157	    target[3] = UChar(0x80 | (CH(0) >> 6) | ((CH(1) & 0x0f) << 2));
158	    target[2] = UChar(0x80 |
159			      ((int) (CH(1) & 0xf0) >> 4) |
160			      ((int) (CH(2) & 0x03) << 4));
161	    target[1] = UChar(0x80 | (CH(2) >> 2));
162	    target[0] = UChar(0xf8 | (CH(3) & 0x03));
163	    break;
164
165	case 6:
166	    target[5] = UChar(0x80 | (CH(0) & 0x3f));
167	    target[4] = UChar(0x80 | (CH(0) >> 6) | ((CH(1) & 0x0f) << 2));
168	    target[3] = UChar(0x80 | (CH(1) >> 4) | ((CH(2) & 0x03) << 4));
169	    target[2] = UChar(0x80 | (CH(2) >> 2));
170	    target[1] = UChar(0x80 | (CH(3) & 0x3f));
171	    target[0] = UChar(0xfc | ((int) (CH(3) & 0x40) >> 6));
172	    break;
173	}
174    }
175
176    return rc;			/* number of bytes needed in target */
177#undef CH
178}
179
180NCURSES_EXPORT(int)
181_nc_conv_to_utf32(unsigned *target, const char *source, unsigned limit)
182{
183#define CH(n) UChar((*target) >> ((n) * 8))
184    int rc = 0;
185    int j;
186    unsigned mask = 0;
187
188    /*
189     * Find the number of bytes we will need from the source.
190     */
191    if ((*source & 0x80) == 0) {
192	rc = 1;
193	mask = (unsigned) *source;
194    } else if ((*source & 0xe0) == 0xc0) {
195	rc = 2;
196	mask = (unsigned) (*source & 0x1f);
197    } else if ((*source & 0xf0) == 0xe0) {
198	rc = 3;
199	mask = (unsigned) (*source & 0x0f);
200    } else if ((*source & 0xf8) == 0xf0) {
201	rc = 4;
202	mask = (unsigned) (*source & 0x07);
203    } else if ((*source & 0xfc) == 0xf8) {
204	rc = 5;
205	mask = (unsigned) (*source & 0x03);
206    } else if ((*source & 0xfe) == 0xfc) {
207	rc = 6;
208	mask = (unsigned) (*source & 0x01);
209    }
210
211    if ((unsigned) rc > limit) {	/* whatever it is, we cannot decode it */
212	rc = 0;
213    }
214
215    /*
216     * sanity-check.
217     */
218    if (rc > 1) {
219	for (j = 1; j < rc; j++) {
220	    if ((source[j] & 0xc0) != 0x80)
221		break;
222	}
223	if (j != rc) {
224	    rc = 0;
225	}
226    }
227
228    if (target != 0) {
229	int shift = 0;
230	*target = 0;
231	for (j = 1; j < rc; j++) {
232	    *target |= (unsigned) (source[rc - j] & 0x3f) << shift;
233	    shift += 6;
234	}
235	*target |= mask << shift;
236    }
237    return rc;
238#undef CH
239}
240#endif /* EXP_XTERM_1005 */
241
242#ifdef EXP_OOM_TESTING
243/*
244 * Out-of-memory testing, suitable for checking if initialization (and limited
245 * running) recovers from errors due to insufficient memory.  In practice, this
246 * is unlikely except with artifically constructed tests (or poorly behaved
247 * applications).
248 */
249#undef malloc
250#undef calloc
251#undef realloc
252#undef free
253#undef strdup
254
255#define TR_OOM(stmt) T(stmt)
256
257static long oom_limit = -1;
258static long oom_count = 0;
259
260static bool
261oom_check(void)
262{
263    static bool initialized = FALSE;
264    static bool triggered = FALSE;
265    bool result = FALSE;
266
267    if (!initialized) {
268	char *env = getenv("NCURSES_OOM_TESTING");
269	initialized = TRUE;
270	if (env != NULL) {
271	    char *check;
272	    oom_limit = strtol(env, &check, 0);
273	    if (check != NULL && *check != '\0')
274		oom_limit = 0;
275	}
276    }
277    ++oom_count;
278    if (oom_limit >= 0) {
279	result = (oom_count > oom_limit);
280	if (result && !triggered) {
281	    triggered = TRUE;
282	    TR_OOM(("out-of-memory"));
283	}
284    }
285    return result;
286}
287
288NCURSES_EXPORT(void *)
289_nc_oom_malloc(size_t size)
290{
291    char *result = (oom_check()
292		    ? NULL
293		    : malloc(size));
294    TR_OOM(("oom #%ld malloc(%ld) %p", oom_count, size, result));
295    return result;
296}
297
298NCURSES_EXPORT(void *)
299_nc_oom_calloc(size_t nmemb, size_t size)
300{
301    char *result = (oom_check()
302		    ? NULL
303		    : calloc(nmemb, size));
304    TR_OOM(("oom #%ld calloc(%ld, %ld) %p", oom_count, nmemb, size, result));
305    return result;
306}
307
308NCURSES_EXPORT(void *)
309_nc_oom_realloc(void *ptr, size_t size)
310{
311    char *result = (oom_check()
312		    ? NULL
313		    : realloc(ptr, size));
314    TR_OOM(("oom #%ld realloc(%p, %ld) %p", oom_count, ptr, size, result));
315    return result;
316}
317
318NCURSES_EXPORT(void)
319_nc_oom_free(void *ptr)
320{
321    ++oom_count;
322    TR_OOM(("oom #%ld free(%p)", oom_count, ptr));
323    free(ptr);
324}
325
326NCURSES_EXPORT(char *)
327_nc_oom_strdup(const char *ptr)
328{
329    char *result = (oom_check()
330		    ? NULL
331		    : strdup(ptr));
332    TR_OOM(("oom #%ld strdup(%p) %p", oom_count, ptr, result));
333    return result;
334}
335#endif /* EXP_OOM_TESTING */
336