14c8945a0SNathan Whitehorn /*
2febdb468SDevin Teske * $Id: inputstr.c,v 1.91 2021/01/17 22:19:05 tom Exp $
34c8945a0SNathan Whitehorn *
44c8945a0SNathan Whitehorn * inputstr.c -- functions for input/display of a string
54c8945a0SNathan Whitehorn *
6febdb468SDevin Teske * Copyright 2000-2019,2021 Thomas E. Dickey
74c8945a0SNathan Whitehorn *
84c8945a0SNathan Whitehorn * This program is free software; you can redistribute it and/or modify
94c8945a0SNathan Whitehorn * it under the terms of the GNU Lesser General Public License, version 2.1
104c8945a0SNathan Whitehorn * as published by the Free Software Foundation.
114c8945a0SNathan Whitehorn *
124c8945a0SNathan Whitehorn * This program is distributed in the hope that it will be useful, but
134c8945a0SNathan Whitehorn * WITHOUT ANY WARRANTY; without even the implied warranty of
144c8945a0SNathan Whitehorn * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
154c8945a0SNathan Whitehorn * Lesser General Public License for more details.
164c8945a0SNathan Whitehorn *
174c8945a0SNathan Whitehorn * You should have received a copy of the GNU Lesser General Public
184c8945a0SNathan Whitehorn * License along with this program; if not, write to
194c8945a0SNathan Whitehorn * Free Software Foundation, Inc.
204c8945a0SNathan Whitehorn * 51 Franklin St., Fifth Floor
214c8945a0SNathan Whitehorn * Boston, MA 02110, USA.
224c8945a0SNathan Whitehorn */
234c8945a0SNathan Whitehorn
244c8945a0SNathan Whitehorn #include <dialog.h>
254c8945a0SNathan Whitehorn #include <dlg_keys.h>
264c8945a0SNathan Whitehorn
274c8945a0SNathan Whitehorn #include <errno.h>
284c8945a0SNathan Whitehorn
294c8945a0SNathan Whitehorn #ifdef HAVE_SETLOCALE
304c8945a0SNathan Whitehorn #include <locale.h>
314c8945a0SNathan Whitehorn #endif
324c8945a0SNathan Whitehorn
334c8945a0SNathan Whitehorn #if defined(HAVE_SEARCH_H) && defined(HAVE_TSEARCH)
344c8945a0SNathan Whitehorn #include <search.h>
354c8945a0SNathan Whitehorn #else
364c8945a0SNathan Whitehorn #undef HAVE_TSEARCH
374c8945a0SNathan Whitehorn #endif
384c8945a0SNathan Whitehorn
394c8945a0SNathan Whitehorn #ifdef NEED_WCHAR_H
404c8945a0SNathan Whitehorn #include <wchar.h>
414c8945a0SNathan Whitehorn #endif
424c8945a0SNathan Whitehorn
434c8945a0SNathan Whitehorn #if defined(USE_WIDE_CURSES)
444c8945a0SNathan Whitehorn #define USE_CACHING 1
454c8945a0SNathan Whitehorn #elif defined(HAVE_XDIALOG)
464c8945a0SNathan Whitehorn #define USE_CACHING 1 /* editbox really needs caching! */
474c8945a0SNathan Whitehorn #else
484c8945a0SNathan Whitehorn #define USE_CACHING 0
494c8945a0SNathan Whitehorn #endif
504c8945a0SNathan Whitehorn
514c8945a0SNathan Whitehorn typedef struct _cache {
524c8945a0SNathan Whitehorn struct _cache *next;
534c8945a0SNathan Whitehorn #if USE_CACHING
54febdb468SDevin Teske int cache_num; /* tells what type of data is in list[] */
554c8945a0SNathan Whitehorn const char *string_at; /* unique: associate caches by char* */
564c8945a0SNathan Whitehorn #endif
577a1c0d96SNathan Whitehorn size_t s_len; /* strlen(string) - we add 1 for EOS */
587a1c0d96SNathan Whitehorn size_t i_len; /* length(list) - we add 1 for EOS */
594c8945a0SNathan Whitehorn char *string; /* a copy of the last-processed string */
604c8945a0SNathan Whitehorn int *list; /* indices into the string */
614c8945a0SNathan Whitehorn } CACHE;
624c8945a0SNathan Whitehorn
634c8945a0SNathan Whitehorn #if USE_CACHING
644c8945a0SNathan Whitehorn #define SAME_CACHE(c,s,l) (c->string != 0 && memcmp(c->string,s,l) == 0)
654c8945a0SNathan Whitehorn
664c8945a0SNathan Whitehorn static CACHE *cache_list;
674c8945a0SNathan Whitehorn
68febdb468SDevin Teske typedef enum {
69febdb468SDevin Teske cInxCols
70febdb468SDevin Teske ,cCntWideBytes
71febdb468SDevin Teske ,cCntWideChars
72febdb468SDevin Teske ,cInxWideChars
73febdb468SDevin Teske ,cMAX
74febdb468SDevin Teske } CACHE_USED;
75febdb468SDevin Teske
764c8945a0SNathan Whitehorn #ifdef HAVE_TSEARCH
774c8945a0SNathan Whitehorn static void *sorted_cache;
784c8945a0SNathan Whitehorn #endif
794c8945a0SNathan Whitehorn
804c8945a0SNathan Whitehorn #ifdef USE_WIDE_CURSES
814c8945a0SNathan Whitehorn static int
have_locale(void)824c8945a0SNathan Whitehorn have_locale(void)
834c8945a0SNathan Whitehorn {
844c8945a0SNathan Whitehorn static int result = -1;
854c8945a0SNathan Whitehorn if (result < 0) {
864c8945a0SNathan Whitehorn char *test = setlocale(LC_ALL, 0);
874c8945a0SNathan Whitehorn if (test == 0 || *test == 0) {
884c8945a0SNathan Whitehorn result = FALSE;
894c8945a0SNathan Whitehorn } else if (strcmp(test, "C") && strcmp(test, "POSIX")) {
904c8945a0SNathan Whitehorn result = TRUE;
914c8945a0SNathan Whitehorn } else {
924c8945a0SNathan Whitehorn result = FALSE;
934c8945a0SNathan Whitehorn }
944c8945a0SNathan Whitehorn }
954c8945a0SNathan Whitehorn return result;
964c8945a0SNathan Whitehorn }
974c8945a0SNathan Whitehorn #endif
984c8945a0SNathan Whitehorn
994c8945a0SNathan Whitehorn #ifdef HAVE_TSEARCH
100febdb468SDevin Teske
101febdb468SDevin Teske #if 0
102febdb468SDevin Teske static void
103febdb468SDevin Teske show_tsearch(const void *nodep, const VISIT which, const int depth)
104febdb468SDevin Teske {
105febdb468SDevin Teske const CACHE *p = *(CACHE * const *) nodep;
106febdb468SDevin Teske (void) depth;
107febdb468SDevin Teske if (which == postorder || which == leaf) {
108febdb468SDevin Teske DLG_TRACE(("# cache %p %p:%s\n", p, p->string, p->string));
109febdb468SDevin Teske }
110febdb468SDevin Teske }
111febdb468SDevin Teske
112febdb468SDevin Teske static void
113febdb468SDevin Teske trace_cache(const char *fn, int ln)
114febdb468SDevin Teske {
115febdb468SDevin Teske DLG_TRACE(("# trace_cache %s@%d\n", fn, ln));
116febdb468SDevin Teske twalk(sorted_cache, show_tsearch);
117febdb468SDevin Teske }
118febdb468SDevin Teske
119febdb468SDevin Teske #else
120febdb468SDevin Teske #define trace_cache(fn, ln) /* nothing */
121febdb468SDevin Teske #endif
122febdb468SDevin Teske
1234c8945a0SNathan Whitehorn #define CMP(a,b) (((a) > (b)) ? 1 : (((a) < (b)) ? -1 : 0))
1244c8945a0SNathan Whitehorn
1254c8945a0SNathan Whitehorn static int
compare_cache(const void * a,const void * b)1264c8945a0SNathan Whitehorn compare_cache(const void *a, const void *b)
1274c8945a0SNathan Whitehorn {
128febdb468SDevin Teske const CACHE *p = (const CACHE *) a;
1294c8945a0SNathan Whitehorn const CACHE *q = (const CACHE *) b;
1307a1c0d96SNathan Whitehorn int result = CMP(p->cache_num, q->cache_num);
1314c8945a0SNathan Whitehorn if (result == 0)
1324c8945a0SNathan Whitehorn result = CMP(p->string_at, q->string_at);
1334c8945a0SNathan Whitehorn return result;
1344c8945a0SNathan Whitehorn }
1354c8945a0SNathan Whitehorn #endif
136febdb468SDevin Teske
1374c8945a0SNathan Whitehorn static CACHE *
find_cache(int cache_num,const char * string)1384c8945a0SNathan Whitehorn find_cache(int cache_num, const char *string)
1394c8945a0SNathan Whitehorn {
1404c8945a0SNathan Whitehorn CACHE *p;
1414c8945a0SNathan Whitehorn
1424c8945a0SNathan Whitehorn #ifdef HAVE_TSEARCH
1434c8945a0SNathan Whitehorn void *pp;
1444c8945a0SNathan Whitehorn CACHE find;
145febdb468SDevin Teske
1464c8945a0SNathan Whitehorn memset(&find, 0, sizeof(find));
1474c8945a0SNathan Whitehorn find.cache_num = cache_num;
1484c8945a0SNathan Whitehorn find.string_at = string;
1494c8945a0SNathan Whitehorn
1504c8945a0SNathan Whitehorn if ((pp = tfind(&find, &sorted_cache, compare_cache)) != 0) {
1514c8945a0SNathan Whitehorn p = *(CACHE **) pp;
1524c8945a0SNathan Whitehorn } else {
1534c8945a0SNathan Whitehorn p = 0;
1544c8945a0SNathan Whitehorn }
155febdb468SDevin Teske #else
1564c8945a0SNathan Whitehorn for (p = cache_list; p != 0; p = p->next) {
1574c8945a0SNathan Whitehorn if (p->string_at == string) {
1584c8945a0SNathan Whitehorn break;
1594c8945a0SNathan Whitehorn }
1604c8945a0SNathan Whitehorn }
1614c8945a0SNathan Whitehorn #endif
1624c8945a0SNathan Whitehorn return p;
163febdb468SDevin Teske }
164febdb468SDevin Teske
1654c8945a0SNathan Whitehorn static CACHE *
make_cache(int cache_num,const char * string)1664c8945a0SNathan Whitehorn make_cache(int cache_num, const char *string)
1674c8945a0SNathan Whitehorn {
1684c8945a0SNathan Whitehorn CACHE *p;
1694c8945a0SNathan Whitehorn
1704c8945a0SNathan Whitehorn p = dlg_calloc(CACHE, 1);
1714c8945a0SNathan Whitehorn assert_ptr(p, "load_cache");
1724c8945a0SNathan Whitehorn p->next = cache_list;
173febdb468SDevin Teske cache_list = p;
1744c8945a0SNathan Whitehorn
1754c8945a0SNathan Whitehorn p->cache_num = cache_num;
1764c8945a0SNathan Whitehorn p->string_at = string;
1774c8945a0SNathan Whitehorn
1784c8945a0SNathan Whitehorn #ifdef HAVE_TSEARCH
179febdb468SDevin Teske (void) tsearch(p, &sorted_cache, compare_cache);
1804c8945a0SNathan Whitehorn #endif
1814c8945a0SNathan Whitehorn return p;
182febdb468SDevin Teske }
183febdb468SDevin Teske
1844c8945a0SNathan Whitehorn static CACHE *
load_cache(int cache_num,const char * string)1854c8945a0SNathan Whitehorn load_cache(int cache_num, const char *string)
1864c8945a0SNathan Whitehorn {
187febdb468SDevin Teske CACHE *p;
188febdb468SDevin Teske
1894c8945a0SNathan Whitehorn if ((p = find_cache(cache_num, string)) == 0) {
190febdb468SDevin Teske p = make_cache(cache_num, string);
1914c8945a0SNathan Whitehorn }
1924c8945a0SNathan Whitehorn return p;
193febdb468SDevin Teske }
1944c8945a0SNathan Whitehorn #else
195febdb468SDevin Teske static CACHE my_cache;
196febdb468SDevin Teske #define SAME_CACHE(c,s,l) (c->string != 0)
1974c8945a0SNathan Whitehorn #define load_cache(cache, string) &my_cache
1984c8945a0SNathan Whitehorn #endif /* USE_CACHING */
1994c8945a0SNathan Whitehorn
2004c8945a0SNathan Whitehorn /*
2014c8945a0SNathan Whitehorn * If the given string has not changed, we do not need to update the index.
2024c8945a0SNathan Whitehorn * If we need to update the index, allocate enough memory for it.
2034c8945a0SNathan Whitehorn */
2044c8945a0SNathan Whitehorn static bool
same_cache2(CACHE * cache,const char * string,unsigned i_len)2054c8945a0SNathan Whitehorn same_cache2(CACHE * cache, const char *string, unsigned i_len)
2067a1c0d96SNathan Whitehorn {
207febdb468SDevin Teske size_t s_len = strlen(string);
2084c8945a0SNathan Whitehorn bool result = TRUE;
209febdb468SDevin Teske
210febdb468SDevin Teske if (cache->s_len == 0
211febdb468SDevin Teske || cache->s_len < s_len
212febdb468SDevin Teske || cache->list == 0
2134c8945a0SNathan Whitehorn || !SAME_CACHE(cache, string, (size_t) s_len)) {
2144c8945a0SNathan Whitehorn unsigned need = (i_len + 1);
2154c8945a0SNathan Whitehorn
2164c8945a0SNathan Whitehorn if (cache->list == 0) {
2174c8945a0SNathan Whitehorn cache->list = dlg_malloc(int, need);
2184c8945a0SNathan Whitehorn } else if (cache->i_len < i_len) {
2194c8945a0SNathan Whitehorn cache->list = dlg_realloc(int, need, cache->list);
220febdb468SDevin Teske }
2214c8945a0SNathan Whitehorn assert_ptr(cache->list, "load_cache");
2224c8945a0SNathan Whitehorn cache->i_len = i_len;
2234c8945a0SNathan Whitehorn
2244c8945a0SNathan Whitehorn if (cache->s_len >= s_len && cache->string != 0) {
2254c8945a0SNathan Whitehorn strcpy(cache->string, string);
2264c8945a0SNathan Whitehorn } else {
2274c8945a0SNathan Whitehorn if (cache->string != 0)
2284c8945a0SNathan Whitehorn free(cache->string);
2294c8945a0SNathan Whitehorn cache->string = dlg_strclone(string);
2304c8945a0SNathan Whitehorn }
2314c8945a0SNathan Whitehorn cache->s_len = s_len;
232febdb468SDevin Teske
233febdb468SDevin Teske result = FALSE;
234febdb468SDevin Teske }
2354c8945a0SNathan Whitehorn return result;
2364c8945a0SNathan Whitehorn }
2374c8945a0SNathan Whitehorn
2384c8945a0SNathan Whitehorn #ifdef USE_WIDE_CURSES
2394c8945a0SNathan Whitehorn /*
2404c8945a0SNathan Whitehorn * Like same_cache2(), but we are only concerned about caching a copy of the
2414c8945a0SNathan Whitehorn * string and its associated length.
2424c8945a0SNathan Whitehorn */
2437a1c0d96SNathan Whitehorn static bool
same_cache1(CACHE * cache,const char * string,size_t i_len)2444c8945a0SNathan Whitehorn same_cache1(CACHE * cache, const char *string, size_t i_len)
2457a1c0d96SNathan Whitehorn {
246febdb468SDevin Teske size_t s_len = strlen(string);
2474c8945a0SNathan Whitehorn bool result = TRUE;
248febdb468SDevin Teske
249febdb468SDevin Teske if (cache->s_len != s_len
2504c8945a0SNathan Whitehorn || !SAME_CACHE(cache, string, (size_t) s_len)) {
2514c8945a0SNathan Whitehorn
2524c8945a0SNathan Whitehorn if (cache->s_len >= s_len && cache->string != 0) {
2534c8945a0SNathan Whitehorn strcpy(cache->string, string);
2544c8945a0SNathan Whitehorn } else {
2554c8945a0SNathan Whitehorn if (cache->string != 0)
2564c8945a0SNathan Whitehorn free(cache->string);
2574c8945a0SNathan Whitehorn cache->string = dlg_strclone(string);
2584c8945a0SNathan Whitehorn }
2594c8945a0SNathan Whitehorn cache->s_len = s_len;
2604c8945a0SNathan Whitehorn cache->i_len = i_len;
261febdb468SDevin Teske
262febdb468SDevin Teske result = FALSE;
263febdb468SDevin Teske }
2644c8945a0SNathan Whitehorn return result;
2654c8945a0SNathan Whitehorn }
2664c8945a0SNathan Whitehorn #endif /* USE_CACHING */
2674c8945a0SNathan Whitehorn
2684c8945a0SNathan Whitehorn /*
2694c8945a0SNathan Whitehorn * Counts the number of bytes that make up complete wide-characters, up to byte
2704c8945a0SNathan Whitehorn * 'len'. If there is no locale set, simply return the original length.
2714c8945a0SNathan Whitehorn */
2724c8945a0SNathan Whitehorn #ifdef USE_WIDE_CURSES
2734c8945a0SNathan Whitehorn static int
dlg_count_wcbytes(const char * string,size_t len)2744c8945a0SNathan Whitehorn dlg_count_wcbytes(const char *string, size_t len)
2754c8945a0SNathan Whitehorn {
2764c8945a0SNathan Whitehorn int result;
2774c8945a0SNathan Whitehorn
278febdb468SDevin Teske if (have_locale()) {
279febdb468SDevin Teske CACHE *cache = load_cache(cCntWideBytes, string);
2804c8945a0SNathan Whitehorn if (!same_cache1(cache, string, len)) {
2814c8945a0SNathan Whitehorn while (len != 0) {
282febdb468SDevin Teske size_t code = 0;
2834c8945a0SNathan Whitehorn const char *src = cache->string;
284febdb468SDevin Teske mbstate_t state;
2854c8945a0SNathan Whitehorn char save = cache->string[len];
286febdb468SDevin Teske
2874c8945a0SNathan Whitehorn cache->string[len] = '\0';
2884c8945a0SNathan Whitehorn memset(&state, 0, sizeof(state));
289febdb468SDevin Teske code = mbsrtowcs((wchar_t *) 0, &src, len, &state);
2904c8945a0SNathan Whitehorn cache->string[len] = save;
2914c8945a0SNathan Whitehorn if ((int) code >= 0) {
2924c8945a0SNathan Whitehorn break;
2934c8945a0SNathan Whitehorn }
2944c8945a0SNathan Whitehorn --len;
295febdb468SDevin Teske }
2964c8945a0SNathan Whitehorn cache->i_len = len;
297febdb468SDevin Teske }
2984c8945a0SNathan Whitehorn result = (int) cache->i_len;
2994c8945a0SNathan Whitehorn } else {
3004c8945a0SNathan Whitehorn result = (int) len;
3014c8945a0SNathan Whitehorn }
3024c8945a0SNathan Whitehorn return result;
3034c8945a0SNathan Whitehorn }
3044c8945a0SNathan Whitehorn #endif /* USE_WIDE_CURSES */
3054c8945a0SNathan Whitehorn
3064c8945a0SNathan Whitehorn /*
3074c8945a0SNathan Whitehorn * Counts the number of wide-characters in the string.
3084c8945a0SNathan Whitehorn */
3094c8945a0SNathan Whitehorn int
dlg_count_wchars(const char * string)3104c8945a0SNathan Whitehorn dlg_count_wchars(const char *string)
3114c8945a0SNathan Whitehorn {
3124c8945a0SNathan Whitehorn int result;
3134c8945a0SNathan Whitehorn #ifdef USE_WIDE_CURSES
314febdb468SDevin Teske
315febdb468SDevin Teske if (have_locale()) {
316febdb468SDevin Teske size_t len = strlen(string);
317febdb468SDevin Teske CACHE *cache = load_cache(cCntWideChars, string);
318febdb468SDevin Teske
319febdb468SDevin Teske if (!same_cache1(cache, string, len)) {
3204c8945a0SNathan Whitehorn const char *src = cache->string;
321febdb468SDevin Teske mbstate_t state;
322febdb468SDevin Teske int part = dlg_count_wcbytes(cache->string, len);
3234c8945a0SNathan Whitehorn char save = cache->string[part];
3244c8945a0SNathan Whitehorn wchar_t *temp = dlg_calloc(wchar_t, len + 1);
3254c8945a0SNathan Whitehorn
3262a3e3873SBaptiste Daroussin if (temp != 0) {
327febdb468SDevin Teske size_t code;
3284c8945a0SNathan Whitehorn
3294c8945a0SNathan Whitehorn cache->string[part] = '\0';
330febdb468SDevin Teske memset(&state, 0, sizeof(state));
331febdb468SDevin Teske code = mbsrtowcs(temp, &src, (size_t) part, &state);
3324c8945a0SNathan Whitehorn cache->i_len = ((int) code >= 0) ? wcslen(temp) : 0;
3332a3e3873SBaptiste Daroussin cache->string[part] = save;
334febdb468SDevin Teske free(temp);
3352a3e3873SBaptiste Daroussin } else {
3364c8945a0SNathan Whitehorn cache->i_len = 0;
337febdb468SDevin Teske }
3384c8945a0SNathan Whitehorn }
3394c8945a0SNathan Whitehorn result = (int) cache->i_len;
3404c8945a0SNathan Whitehorn } else
3414c8945a0SNathan Whitehorn #endif /* USE_WIDE_CURSES */
3424c8945a0SNathan Whitehorn {
3434c8945a0SNathan Whitehorn result = (int) strlen(string);
3444c8945a0SNathan Whitehorn }
3454c8945a0SNathan Whitehorn return result;
3464c8945a0SNathan Whitehorn }
3474c8945a0SNathan Whitehorn
3484c8945a0SNathan Whitehorn /*
3494c8945a0SNathan Whitehorn * Build an index of the wide-characters in the string, so we can easily tell
3504c8945a0SNathan Whitehorn * which byte-offset begins a given wide-character.
3514c8945a0SNathan Whitehorn */
3524c8945a0SNathan Whitehorn const int *
dlg_index_wchars(const char * string)3534c8945a0SNathan Whitehorn dlg_index_wchars(const char *string)
3544c8945a0SNathan Whitehorn {
355febdb468SDevin Teske unsigned len = (unsigned) dlg_count_wchars(string);
3564c8945a0SNathan Whitehorn CACHE *cache = load_cache(cInxWideChars, string);
357febdb468SDevin Teske
3584c8945a0SNathan Whitehorn if (!same_cache2(cache, string, len)) {
3594c8945a0SNathan Whitehorn const char *current = string;
360febdb468SDevin Teske unsigned inx;
3614c8945a0SNathan Whitehorn
3624c8945a0SNathan Whitehorn cache->list[0] = 0;
3634c8945a0SNathan Whitehorn for (inx = 1; inx <= len; ++inx) {
3644c8945a0SNathan Whitehorn #ifdef USE_WIDE_CURSES
3654c8945a0SNathan Whitehorn if (have_locale()) {
3664c8945a0SNathan Whitehorn mbstate_t state;
3674c8945a0SNathan Whitehorn int width;
3684c8945a0SNathan Whitehorn memset(&state, 0, sizeof(state));
3694c8945a0SNathan Whitehorn width = (int) mbrlen(current, strlen(current), &state);
3704c8945a0SNathan Whitehorn if (width <= 0)
371febdb468SDevin Teske width = 1; /* FIXME: what if we have a control-char? */
3724c8945a0SNathan Whitehorn current += width;
3734c8945a0SNathan Whitehorn cache->list[inx] = cache->list[inx - 1] + width;
3744c8945a0SNathan Whitehorn } else
3754c8945a0SNathan Whitehorn #endif /* USE_WIDE_CURSES */
376febdb468SDevin Teske {
3774c8945a0SNathan Whitehorn (void) current;
3784c8945a0SNathan Whitehorn cache->list[inx] = (int) inx;
3794c8945a0SNathan Whitehorn }
380febdb468SDevin Teske }
3814c8945a0SNathan Whitehorn }
3824c8945a0SNathan Whitehorn return cache->list;
3834c8945a0SNathan Whitehorn }
3844c8945a0SNathan Whitehorn
3854c8945a0SNathan Whitehorn /*
3864c8945a0SNathan Whitehorn * Given the character-offset to find in the list, return the corresponding
3874c8945a0SNathan Whitehorn * array index.
3884c8945a0SNathan Whitehorn */
3894c8945a0SNathan Whitehorn int
dlg_find_index(const int * list,int limit,int to_find)3904c8945a0SNathan Whitehorn dlg_find_index(const int *list, int limit, int to_find)
3914c8945a0SNathan Whitehorn {
3924c8945a0SNathan Whitehorn int result;
3934c8945a0SNathan Whitehorn for (result = 0; result <= limit; ++result) {
3942a3e3873SBaptiste Daroussin if (to_find == list[result]
3954c8945a0SNathan Whitehorn || result == limit
3964c8945a0SNathan Whitehorn || ((result < limit) && (to_find < list[result + 1]))) {
3972a3e3873SBaptiste Daroussin break;
3984c8945a0SNathan Whitehorn }
3994c8945a0SNathan Whitehorn }
4004c8945a0SNathan Whitehorn return result;
4014c8945a0SNathan Whitehorn }
4024c8945a0SNathan Whitehorn
4034c8945a0SNathan Whitehorn /*
4044c8945a0SNathan Whitehorn * Build a list of the display-columns for the given string's characters.
4054c8945a0SNathan Whitehorn */
4064c8945a0SNathan Whitehorn const int *
dlg_index_columns(const char * string)4074c8945a0SNathan Whitehorn dlg_index_columns(const char *string)
4084c8945a0SNathan Whitehorn {
409febdb468SDevin Teske unsigned len = (unsigned) dlg_count_wchars(string);
4104c8945a0SNathan Whitehorn CACHE *cache = load_cache(cInxCols, string);
411febdb468SDevin Teske
412febdb468SDevin Teske if (!same_cache2(cache, string, len)) {
4134c8945a0SNathan Whitehorn
4144c8945a0SNathan Whitehorn cache->list[0] = 0;
4154c8945a0SNathan Whitehorn #ifdef USE_WIDE_CURSES
4164c8945a0SNathan Whitehorn if (have_locale()) {
4174c8945a0SNathan Whitehorn unsigned inx;
4184c8945a0SNathan Whitehorn size_t num_bytes = strlen(string);
4194c8945a0SNathan Whitehorn const int *inx_wchars = dlg_index_wchars(string);
4204c8945a0SNathan Whitehorn mbstate_t state;
4214c8945a0SNathan Whitehorn
4224c8945a0SNathan Whitehorn for (inx = 0; inx < len; ++inx) {
4234c8945a0SNathan Whitehorn int result;
4244c8945a0SNathan Whitehorn
425febdb468SDevin Teske if (string[inx_wchars[inx]] == TAB) {
4264c8945a0SNathan Whitehorn result = ((cache->list[inx] | 7) + 1) - cache->list[inx];
4274c8945a0SNathan Whitehorn } else {
4284c8945a0SNathan Whitehorn wchar_t temp[2];
4294c8945a0SNathan Whitehorn size_t check;
4304c8945a0SNathan Whitehorn
4314c8945a0SNathan Whitehorn memset(&state, 0, sizeof(state));
4324c8945a0SNathan Whitehorn memset(temp, 0, sizeof(temp));
4334c8945a0SNathan Whitehorn check = mbrtowc(temp,
4344c8945a0SNathan Whitehorn string + inx_wchars[inx],
4354c8945a0SNathan Whitehorn num_bytes - (size_t) inx_wchars[inx],
4364c8945a0SNathan Whitehorn &state);
4374c8945a0SNathan Whitehorn if ((int) check <= 0) {
4384c8945a0SNathan Whitehorn result = 1;
4397a1c0d96SNathan Whitehorn } else {
4407a1c0d96SNathan Whitehorn result = wcwidth(temp[0]);
4417a1c0d96SNathan Whitehorn }
4427a1c0d96SNathan Whitehorn if (result < 0) {
4434c8945a0SNathan Whitehorn const wchar_t *printable;
4444c8945a0SNathan Whitehorn cchar_t temp2, *temp2p = &temp2;
4454c8945a0SNathan Whitehorn setcchar(temp2p, temp, 0, 0, 0);
446febdb468SDevin Teske printable = wunctrl(temp2p);
4474c8945a0SNathan Whitehorn result = printable ? (int) wcslen(printable) : 1;
448febdb468SDevin Teske }
4494c8945a0SNathan Whitehorn }
4504c8945a0SNathan Whitehorn cache->list[inx + 1] = result;
4514c8945a0SNathan Whitehorn if (inx != 0)
4524c8945a0SNathan Whitehorn cache->list[inx + 1] += cache->list[inx];
4534c8945a0SNathan Whitehorn }
4544c8945a0SNathan Whitehorn } else
4554c8945a0SNathan Whitehorn #endif /* USE_WIDE_CURSES */
4564c8945a0SNathan Whitehorn {
457febdb468SDevin Teske unsigned inx;
458febdb468SDevin Teske
4594c8945a0SNathan Whitehorn for (inx = 0; inx < len; ++inx) {
460febdb468SDevin Teske chtype ch = UCH(string[inx]);
4614c8945a0SNathan Whitehorn
4624c8945a0SNathan Whitehorn if (ch == TAB)
4634c8945a0SNathan Whitehorn cache->list[inx + 1] =
464febdb468SDevin Teske ((cache->list[inx] | 7) + 1) - cache->list[inx];
4654c8945a0SNathan Whitehorn else if (isprint(UCH(ch)))
4664c8945a0SNathan Whitehorn cache->list[inx + 1] = 1;
4674c8945a0SNathan Whitehorn else {
4684c8945a0SNathan Whitehorn const char *printable;
469febdb468SDevin Teske printable = unctrl(ch);
4704c8945a0SNathan Whitehorn cache->list[inx + 1] = (printable
4714c8945a0SNathan Whitehorn ? (int) strlen(printable)
4724c8945a0SNathan Whitehorn : 1);
473febdb468SDevin Teske }
4744c8945a0SNathan Whitehorn if (inx != 0)
4754c8945a0SNathan Whitehorn cache->list[inx + 1] += cache->list[inx];
4764c8945a0SNathan Whitehorn }
4774c8945a0SNathan Whitehorn }
4784c8945a0SNathan Whitehorn }
4794c8945a0SNathan Whitehorn return cache->list;
4804c8945a0SNathan Whitehorn }
4814c8945a0SNathan Whitehorn
4824c8945a0SNathan Whitehorn /*
4834c8945a0SNathan Whitehorn * Returns the number of columns used for a string. That happens to be the
4844c8945a0SNathan Whitehorn * end-value of the cols[] array.
4854c8945a0SNathan Whitehorn */
4864c8945a0SNathan Whitehorn int
dlg_count_columns(const char * string)4874c8945a0SNathan Whitehorn dlg_count_columns(const char *string)
4884c8945a0SNathan Whitehorn {
4894c8945a0SNathan Whitehorn int result = 0;
4904c8945a0SNathan Whitehorn int limit = dlg_count_wchars(string);
491febdb468SDevin Teske if (limit > 0) {
4924c8945a0SNathan Whitehorn const int *cols = dlg_index_columns(string);
4934c8945a0SNathan Whitehorn result = cols[limit];
4944c8945a0SNathan Whitehorn } else {
4954c8945a0SNathan Whitehorn result = (int) strlen(string);
4964c8945a0SNathan Whitehorn }
4974c8945a0SNathan Whitehorn dlg_finish_string(string);
4984c8945a0SNathan Whitehorn return result;
4994c8945a0SNathan Whitehorn }
5004c8945a0SNathan Whitehorn
5014c8945a0SNathan Whitehorn /*
5024c8945a0SNathan Whitehorn * Given a column limit, count the number of wide characters that can fit
5034c8945a0SNathan Whitehorn * into that limit. The offset is used to skip over a leading character
5044c8945a0SNathan Whitehorn * that was already written.
5054c8945a0SNathan Whitehorn */
5064c8945a0SNathan Whitehorn int
dlg_limit_columns(const char * string,int limit,int offset)5074c8945a0SNathan Whitehorn dlg_limit_columns(const char *string, int limit, int offset)
5084c8945a0SNathan Whitehorn {
5094c8945a0SNathan Whitehorn const int *cols = dlg_index_columns(string);
5104c8945a0SNathan Whitehorn int result = dlg_count_wchars(string);
5114c8945a0SNathan Whitehorn
5124c8945a0SNathan Whitehorn while (result > 0 && (cols[result] - cols[offset]) > limit)
5134c8945a0SNathan Whitehorn --result;
5144c8945a0SNathan Whitehorn return result;
5154c8945a0SNathan Whitehorn }
5164c8945a0SNathan Whitehorn
5174c8945a0SNathan Whitehorn /*
5184c8945a0SNathan Whitehorn * Updates the string and character-offset, given various editing characters
5194c8945a0SNathan Whitehorn * or literal characters which are inserted at the character-offset.
5204c8945a0SNathan Whitehorn */
5214c8945a0SNathan Whitehorn bool
dlg_edit_string(char * string,int * chr_offset,int key,int fkey,bool force)5224c8945a0SNathan Whitehorn dlg_edit_string(char *string, int *chr_offset, int key, int fkey, bool force)
5234c8945a0SNathan Whitehorn {
5244c8945a0SNathan Whitehorn int i;
5254c8945a0SNathan Whitehorn int len = (int) strlen(string);
5264c8945a0SNathan Whitehorn int limit = dlg_count_wchars(string);
5274c8945a0SNathan Whitehorn const int *indx = dlg_index_wchars(string);
5284c8945a0SNathan Whitehorn int offset = dlg_find_index(indx, limit, *chr_offset);
5294c8945a0SNathan Whitehorn int max_len = dlg_max_input(MAX_LEN);
5304c8945a0SNathan Whitehorn bool edit = TRUE;
5314c8945a0SNathan Whitehorn
5324c8945a0SNathan Whitehorn /* transform editing characters into equivalent function-keys */
5334c8945a0SNathan Whitehorn if (!fkey) {
5344c8945a0SNathan Whitehorn fkey = TRUE; /* assume we transform */
5354c8945a0SNathan Whitehorn switch (key) {
5364c8945a0SNathan Whitehorn case 0:
5374c8945a0SNathan Whitehorn break;
5384c8945a0SNathan Whitehorn case ESC:
5394c8945a0SNathan Whitehorn case TAB:
5404c8945a0SNathan Whitehorn fkey = FALSE; /* this is used for navigation */
5414c8945a0SNathan Whitehorn break;
5424c8945a0SNathan Whitehorn default:
5434c8945a0SNathan Whitehorn fkey = FALSE; /* ...no, we did not transform */
5444c8945a0SNathan Whitehorn break;
5454c8945a0SNathan Whitehorn }
5464c8945a0SNathan Whitehorn }
5474c8945a0SNathan Whitehorn
5482a3e3873SBaptiste Daroussin if (fkey) {
5494c8945a0SNathan Whitehorn switch (key) {
5504c8945a0SNathan Whitehorn case 0: /* special case for loop entry */
5514c8945a0SNathan Whitehorn edit = force;
5524c8945a0SNathan Whitehorn break;
5534c8945a0SNathan Whitehorn case DLGK_GRID_LEFT:
5544c8945a0SNathan Whitehorn if (*chr_offset && offset > 0)
5554c8945a0SNathan Whitehorn *chr_offset = indx[offset - 1];
5564c8945a0SNathan Whitehorn break;
5574c8945a0SNathan Whitehorn case DLGK_GRID_RIGHT:
5584c8945a0SNathan Whitehorn if (offset < limit)
5594c8945a0SNathan Whitehorn *chr_offset = indx[offset + 1];
5604c8945a0SNathan Whitehorn break;
5614c8945a0SNathan Whitehorn case DLGK_BEGIN:
5624c8945a0SNathan Whitehorn if (*chr_offset)
5634c8945a0SNathan Whitehorn *chr_offset = 0;
5644c8945a0SNathan Whitehorn break;
5654c8945a0SNathan Whitehorn case DLGK_FINAL:
5664c8945a0SNathan Whitehorn if (offset < limit)
5674c8945a0SNathan Whitehorn *chr_offset = indx[limit];
5684c8945a0SNathan Whitehorn break;
5694c8945a0SNathan Whitehorn case DLGK_DELETE_LEFT:
5704c8945a0SNathan Whitehorn if (offset) {
5714c8945a0SNathan Whitehorn int gap = indx[offset] - indx[offset - 1];
5724c8945a0SNathan Whitehorn *chr_offset = indx[offset - 1];
5734c8945a0SNathan Whitehorn if (gap > 0) {
5744c8945a0SNathan Whitehorn for (i = *chr_offset;
5754c8945a0SNathan Whitehorn (string[i] = string[i + gap]) != '\0';
5764c8945a0SNathan Whitehorn i++) {
5774c8945a0SNathan Whitehorn ;
5784c8945a0SNathan Whitehorn }
5794c8945a0SNathan Whitehorn }
5804c8945a0SNathan Whitehorn }
5814c8945a0SNathan Whitehorn break;
5824c8945a0SNathan Whitehorn case DLGK_DELETE_RIGHT:
5834c8945a0SNathan Whitehorn if (limit) {
5844c8945a0SNathan Whitehorn if (--limit == 0) {
5854c8945a0SNathan Whitehorn string[*chr_offset = 0] = '\0';
5864c8945a0SNathan Whitehorn } else {
5874c8945a0SNathan Whitehorn int gap = ((offset <= limit)
5884c8945a0SNathan Whitehorn ? (indx[offset + 1] - indx[offset])
5894c8945a0SNathan Whitehorn : 0);
5904c8945a0SNathan Whitehorn if (gap > 0) {
5914c8945a0SNathan Whitehorn for (i = indx[offset];
5924c8945a0SNathan Whitehorn (string[i] = string[i + gap]) != '\0';
5934c8945a0SNathan Whitehorn i++) {
5944c8945a0SNathan Whitehorn ;
5954c8945a0SNathan Whitehorn }
5964c8945a0SNathan Whitehorn } else if (offset > 0) {
5974c8945a0SNathan Whitehorn string[indx[offset - 1]] = '\0';
5984c8945a0SNathan Whitehorn }
5994c8945a0SNathan Whitehorn if (*chr_offset > indx[limit])
6004c8945a0SNathan Whitehorn *chr_offset = indx[limit];
6014c8945a0SNathan Whitehorn }
6024c8945a0SNathan Whitehorn }
6034c8945a0SNathan Whitehorn break;
6044c8945a0SNathan Whitehorn case DLGK_DELETE_ALL:
6054c8945a0SNathan Whitehorn string[*chr_offset = 0] = '\0';
6064c8945a0SNathan Whitehorn break;
6074c8945a0SNathan Whitehorn case DLGK_ENTER:
6084c8945a0SNathan Whitehorn edit = 0;
6094c8945a0SNathan Whitehorn break;
6104c8945a0SNathan Whitehorn #ifdef KEY_RESIZE
6114c8945a0SNathan Whitehorn case KEY_RESIZE:
6124c8945a0SNathan Whitehorn edit = 0;
6134c8945a0SNathan Whitehorn break;
6144c8945a0SNathan Whitehorn #endif
6154c8945a0SNathan Whitehorn case DLGK_GRID_UP:
6164c8945a0SNathan Whitehorn case DLGK_GRID_DOWN:
6174c8945a0SNathan Whitehorn case DLGK_FIELD_NEXT:
6184c8945a0SNathan Whitehorn case DLGK_FIELD_PREV:
6194c8945a0SNathan Whitehorn edit = 0;
6204c8945a0SNathan Whitehorn break;
6214c8945a0SNathan Whitehorn case ERR:
6224c8945a0SNathan Whitehorn edit = 0;
6234c8945a0SNathan Whitehorn break;
6244c8945a0SNathan Whitehorn default:
6254c8945a0SNathan Whitehorn beep();
6264c8945a0SNathan Whitehorn break;
6274c8945a0SNathan Whitehorn }
6284c8945a0SNathan Whitehorn } else {
6294c8945a0SNathan Whitehorn if (key == ESC || key == ERR) {
6304c8945a0SNathan Whitehorn edit = 0;
6314c8945a0SNathan Whitehorn } else {
6324c8945a0SNathan Whitehorn if (len < max_len) {
6334c8945a0SNathan Whitehorn for (i = ++len; i > *chr_offset; i--)
6344c8945a0SNathan Whitehorn string[i] = string[i - 1];
6354c8945a0SNathan Whitehorn string[*chr_offset] = (char) key;
6364c8945a0SNathan Whitehorn *chr_offset += 1;
6374c8945a0SNathan Whitehorn } else {
6384c8945a0SNathan Whitehorn (void) beep();
6394c8945a0SNathan Whitehorn }
6404c8945a0SNathan Whitehorn }
6414c8945a0SNathan Whitehorn }
6424c8945a0SNathan Whitehorn return edit;
6434c8945a0SNathan Whitehorn }
6444c8945a0SNathan Whitehorn
6454c8945a0SNathan Whitehorn static void
compute_edit_offset(const char * string,int chr_offset,int x_last,int * p_dpy_column,int * p_scroll_amt)6464c8945a0SNathan Whitehorn compute_edit_offset(const char *string,
6474c8945a0SNathan Whitehorn int chr_offset,
6484c8945a0SNathan Whitehorn int x_last,
6494c8945a0SNathan Whitehorn int *p_dpy_column,
6504c8945a0SNathan Whitehorn int *p_scroll_amt)
6514c8945a0SNathan Whitehorn {
6524c8945a0SNathan Whitehorn const int *cols = dlg_index_columns(string);
6534c8945a0SNathan Whitehorn const int *indx = dlg_index_wchars(string);
6544c8945a0SNathan Whitehorn int limit = dlg_count_wchars(string);
6554c8945a0SNathan Whitehorn int offset = dlg_find_index(indx, limit, chr_offset);
6564c8945a0SNathan Whitehorn int offset2;
6574c8945a0SNathan Whitehorn int dpy_column;
6584c8945a0SNathan Whitehorn int n;
6594c8945a0SNathan Whitehorn
6604c8945a0SNathan Whitehorn for (n = offset2 = 0; n <= offset; ++n) {
6614c8945a0SNathan Whitehorn if ((cols[offset] - cols[n]) < x_last
6624c8945a0SNathan Whitehorn && (offset == limit || (cols[offset + 1] - cols[n]) < x_last)) {
6634c8945a0SNathan Whitehorn offset2 = n;
6644c8945a0SNathan Whitehorn break;
6654c8945a0SNathan Whitehorn }
6664c8945a0SNathan Whitehorn }
6674c8945a0SNathan Whitehorn
6684c8945a0SNathan Whitehorn dpy_column = cols[offset] - cols[offset2];
6694c8945a0SNathan Whitehorn
6704c8945a0SNathan Whitehorn if (p_dpy_column != 0)
6714c8945a0SNathan Whitehorn *p_dpy_column = dpy_column;
6724c8945a0SNathan Whitehorn if (p_scroll_amt != 0)
6734c8945a0SNathan Whitehorn *p_scroll_amt = offset2;
6744c8945a0SNathan Whitehorn }
6754c8945a0SNathan Whitehorn
6764c8945a0SNathan Whitehorn /*
6774c8945a0SNathan Whitehorn * Given the character-offset in the string, returns the display-offset where
6784c8945a0SNathan Whitehorn * we will position the cursor.
6794c8945a0SNathan Whitehorn */
6804c8945a0SNathan Whitehorn int
dlg_edit_offset(char * string,int chr_offset,int x_last)6814c8945a0SNathan Whitehorn dlg_edit_offset(char *string, int chr_offset, int x_last)
6824c8945a0SNathan Whitehorn {
6834c8945a0SNathan Whitehorn int result;
6844c8945a0SNathan Whitehorn
6854c8945a0SNathan Whitehorn compute_edit_offset(string, chr_offset, x_last, &result, 0);
6864c8945a0SNathan Whitehorn
6874c8945a0SNathan Whitehorn return result;
6884c8945a0SNathan Whitehorn }
6894c8945a0SNathan Whitehorn
6904c8945a0SNathan Whitehorn /*
6914c8945a0SNathan Whitehorn * Displays the string, shifted as necessary, to fit within the box and show
6924c8945a0SNathan Whitehorn * the current character-offset.
6934c8945a0SNathan Whitehorn */
6944c8945a0SNathan Whitehorn void
dlg_show_string(WINDOW * win,const char * string,int chr_offset,chtype attr,int y_base,int x_base,int x_last,bool hidden,bool force)6954c8945a0SNathan Whitehorn dlg_show_string(WINDOW *win,
6964c8945a0SNathan Whitehorn const char *string, /* string to display (may be multibyte) */
6974c8945a0SNathan Whitehorn int chr_offset, /* character (not bytes) offset */
6984c8945a0SNathan Whitehorn chtype attr, /* window-attributes */
6994c8945a0SNathan Whitehorn int y_base, /* beginning row on screen */
7004c8945a0SNathan Whitehorn int x_base, /* beginning column on screen */
7014c8945a0SNathan Whitehorn int x_last, /* number of columns on screen */
7024c8945a0SNathan Whitehorn bool hidden, /* if true, do not echo */
7034c8945a0SNathan Whitehorn bool force) /* if true, force repaint */
7044c8945a0SNathan Whitehorn {
7054c8945a0SNathan Whitehorn x_last = MIN(x_last + x_base, getmaxx(win)) - x_base;
7064c8945a0SNathan Whitehorn
7074c8945a0SNathan Whitehorn if (hidden && !dialog_vars.insecure) {
7084c8945a0SNathan Whitehorn if (force) {
7094c8945a0SNathan Whitehorn (void) wmove(win, y_base, x_base);
7104c8945a0SNathan Whitehorn wrefresh(win);
7114c8945a0SNathan Whitehorn }
7124c8945a0SNathan Whitehorn } else {
7134c8945a0SNathan Whitehorn const int *cols = dlg_index_columns(string);
7144c8945a0SNathan Whitehorn const int *indx = dlg_index_wchars(string);
7154c8945a0SNathan Whitehorn int limit = dlg_count_wchars(string);
7164c8945a0SNathan Whitehorn
7172a3e3873SBaptiste Daroussin int i, j, k;
7184c8945a0SNathan Whitehorn int input_x;
7194c8945a0SNathan Whitehorn int scrollamt;
7204c8945a0SNathan Whitehorn
7214c8945a0SNathan Whitehorn compute_edit_offset(string, chr_offset, x_last, &input_x, &scrollamt);
7224c8945a0SNathan Whitehorn
7234c8945a0SNathan Whitehorn dlg_attrset(win, attr);
7244c8945a0SNathan Whitehorn (void) wmove(win, y_base, x_base);
7254c8945a0SNathan Whitehorn for (i = scrollamt, k = 0; i < limit && k < x_last; ++i) {
7264c8945a0SNathan Whitehorn int check = cols[i + 1] - cols[scrollamt];
7274c8945a0SNathan Whitehorn if (check <= x_last) {
7284c8945a0SNathan Whitehorn for (j = indx[i]; j < indx[i + 1]; ++j) {
7294c8945a0SNathan Whitehorn chtype ch = UCH(string[j]);
7304c8945a0SNathan Whitehorn if (hidden && dialog_vars.insecure) {
7314c8945a0SNathan Whitehorn waddch(win, '*');
7324c8945a0SNathan Whitehorn } else if (ch == TAB) {
7334c8945a0SNathan Whitehorn int count = cols[i + 1] - cols[i];
7344c8945a0SNathan Whitehorn while (--count >= 0)
7354c8945a0SNathan Whitehorn waddch(win, ' ');
7364c8945a0SNathan Whitehorn } else {
7374c8945a0SNathan Whitehorn waddch(win, ch);
7384c8945a0SNathan Whitehorn }
7394c8945a0SNathan Whitehorn }
7404c8945a0SNathan Whitehorn k = check;
7414c8945a0SNathan Whitehorn } else {
7424c8945a0SNathan Whitehorn break;
7434c8945a0SNathan Whitehorn }
7444c8945a0SNathan Whitehorn }
7454c8945a0SNathan Whitehorn while (k++ < x_last)
746febdb468SDevin Teske waddch(win, ' ');
747febdb468SDevin Teske (void) wmove(win, y_base, x_base + input_x);
748febdb468SDevin Teske wrefresh(win);
749febdb468SDevin Teske }
750febdb468SDevin Teske }
751febdb468SDevin Teske
752febdb468SDevin Teske /*
753febdb468SDevin Teske * Discard cached data for the given string.
754febdb468SDevin Teske */
755febdb468SDevin Teske void
dlg_finish_string(const char * string)756febdb468SDevin Teske dlg_finish_string(const char *string)
757febdb468SDevin Teske {
758febdb468SDevin Teske #if USE_CACHING
759febdb468SDevin Teske if ((string != 0) && dialog_state.finish_string) {
760febdb468SDevin Teske CACHE *p = cache_list;
761febdb468SDevin Teske CACHE *q = 0;
762febdb468SDevin Teske CACHE *r;
763febdb468SDevin Teske
764febdb468SDevin Teske while (p != 0) {
765febdb468SDevin Teske if (p->string_at == string) {
766febdb468SDevin Teske #ifdef HAVE_TSEARCH
767febdb468SDevin Teske if (tdelete(p, &sorted_cache, compare_cache) == 0) {
768febdb468SDevin Teske continue;
769febdb468SDevin Teske }
770febdb468SDevin Teske trace_cache(__FILE__, __LINE__);
771febdb468SDevin Teske #endif
772febdb468SDevin Teske if (p->string != 0)
773febdb468SDevin Teske free(p->string);
774febdb468SDevin Teske if (p->list != 0)
775febdb468SDevin Teske free(p->list);
776febdb468SDevin Teske if (p == cache_list) {
777febdb468SDevin Teske cache_list = p->next;
778febdb468SDevin Teske r = cache_list;
779febdb468SDevin Teske } else {
780febdb468SDevin Teske q->next = p->next;
781febdb468SDevin Teske r = q;
782febdb468SDevin Teske }
783febdb468SDevin Teske free(p);
784febdb468SDevin Teske p = r;
785febdb468SDevin Teske } else {
786febdb468SDevin Teske q = p;
787febdb468SDevin Teske p = p->next;
788febdb468SDevin Teske }
789febdb468SDevin Teske }
7904c8945a0SNathan Whitehorn }
7914c8945a0SNathan Whitehorn #else
7924c8945a0SNathan Whitehorn (void) string;
7934c8945a0SNathan Whitehorn #endif
7944c8945a0SNathan Whitehorn }
795febdb468SDevin Teske
796febdb468SDevin Teske #ifdef NO_LEAKS
7974c8945a0SNathan Whitehorn void
_dlg_inputstr_leaks(void)798febdb468SDevin Teske _dlg_inputstr_leaks(void)
7994c8945a0SNathan Whitehorn {
8004c8945a0SNathan Whitehorn #if USE_CACHING
8014c8945a0SNathan Whitehorn dialog_state.finish_string = TRUE;
8024c8945a0SNathan Whitehorn trace_cache(__FILE__, __LINE__);
803 while (cache_list != 0) {
804 dlg_finish_string(cache_list->string_at);
805 }
806 #endif /* USE_CACHING */
807 }
808 #endif /* NO_LEAKS */
809