xref: /freebsd/contrib/dialog/inputstr.c (revision 2a3e3873)
14c8945a0SNathan Whitehorn /*
22a3e3873SBaptiste Daroussin  *  $Id: inputstr.c,v 1.72 2012/12/30 22:11:37 tom Exp $
34c8945a0SNathan Whitehorn  *
44c8945a0SNathan Whitehorn  *  inputstr.c -- functions for input/display of a string
54c8945a0SNathan Whitehorn  *
62a3e3873SBaptiste Daroussin  *  Copyright 2000-2011,2012	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
544c8945a0SNathan Whitehorn     struct _cache *cache_at;	/* unique: associate caches by CACHE */
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 
684c8945a0SNathan Whitehorn #ifdef HAVE_TSEARCH
694c8945a0SNathan Whitehorn static void *sorted_cache;
704c8945a0SNathan Whitehorn #endif
714c8945a0SNathan Whitehorn 
724c8945a0SNathan Whitehorn #ifdef USE_WIDE_CURSES
734c8945a0SNathan Whitehorn static int
744c8945a0SNathan Whitehorn have_locale(void)
754c8945a0SNathan Whitehorn {
764c8945a0SNathan Whitehorn     static int result = -1;
774c8945a0SNathan Whitehorn     if (result < 0) {
784c8945a0SNathan Whitehorn 	char *test = setlocale(LC_ALL, 0);
794c8945a0SNathan Whitehorn 	if (test == 0 || *test == 0) {
804c8945a0SNathan Whitehorn 	    result = FALSE;
814c8945a0SNathan Whitehorn 	} else if (strcmp(test, "C") && strcmp(test, "POSIX")) {
824c8945a0SNathan Whitehorn 	    result = TRUE;
834c8945a0SNathan Whitehorn 	} else {
844c8945a0SNathan Whitehorn 	    result = FALSE;
854c8945a0SNathan Whitehorn 	}
864c8945a0SNathan Whitehorn     }
874c8945a0SNathan Whitehorn     return result;
884c8945a0SNathan Whitehorn }
894c8945a0SNathan Whitehorn #endif
904c8945a0SNathan Whitehorn 
914c8945a0SNathan Whitehorn #ifdef HAVE_TSEARCH
924c8945a0SNathan Whitehorn static int
934c8945a0SNathan Whitehorn compare_cache(const void *a, const void *b)
944c8945a0SNathan Whitehorn {
954c8945a0SNathan Whitehorn     const CACHE *p = (const CACHE *) a;
964c8945a0SNathan Whitehorn     const CACHE *q = (const CACHE *) b;
974c8945a0SNathan Whitehorn     int result = 0;
987a1c0d96SNathan Whitehorn     result = (int) (p->cache_at - q->cache_at);
994c8945a0SNathan Whitehorn     if (result == 0)
1007a1c0d96SNathan Whitehorn 	result = (int) (p->string_at - q->string_at);
1014c8945a0SNathan Whitehorn     return result;
1024c8945a0SNathan Whitehorn }
1034c8945a0SNathan Whitehorn #endif
1044c8945a0SNathan Whitehorn 
1054c8945a0SNathan Whitehorn static CACHE *
1064c8945a0SNathan Whitehorn find_cache(CACHE * cache, const char *string)
1074c8945a0SNathan Whitehorn {
1084c8945a0SNathan Whitehorn     CACHE *p;
1094c8945a0SNathan Whitehorn 
1104c8945a0SNathan Whitehorn #ifdef HAVE_TSEARCH
1114c8945a0SNathan Whitehorn     void *pp;
1124c8945a0SNathan Whitehorn     CACHE find;
1134c8945a0SNathan Whitehorn 
1144c8945a0SNathan Whitehorn     memset(&find, 0, sizeof(find));
1154c8945a0SNathan Whitehorn     find.cache_at = cache;
1164c8945a0SNathan Whitehorn     find.string_at = string;
1174c8945a0SNathan Whitehorn 
1184c8945a0SNathan Whitehorn     if ((pp = tfind(&find, &sorted_cache, compare_cache)) != 0) {
1194c8945a0SNathan Whitehorn 	p = *(CACHE **) pp;
1204c8945a0SNathan Whitehorn     } else {
1214c8945a0SNathan Whitehorn 	p = 0;
1224c8945a0SNathan Whitehorn     }
1234c8945a0SNathan Whitehorn #else
1244c8945a0SNathan Whitehorn     for (p = cache_list; p != 0; p = p->next) {
1254c8945a0SNathan Whitehorn 	if (p->cache_at == cache
1264c8945a0SNathan Whitehorn 	    && p->string_at == string) {
1274c8945a0SNathan Whitehorn 	    break;
1284c8945a0SNathan Whitehorn 	}
1294c8945a0SNathan Whitehorn     }
1304c8945a0SNathan Whitehorn #endif
1314c8945a0SNathan Whitehorn     return p;
1324c8945a0SNathan Whitehorn }
1334c8945a0SNathan Whitehorn 
1344c8945a0SNathan Whitehorn static void
1354c8945a0SNathan Whitehorn make_cache(CACHE * cache, const char *string)
1364c8945a0SNathan Whitehorn {
1374c8945a0SNathan Whitehorn     CACHE *p;
1384c8945a0SNathan Whitehorn 
1394c8945a0SNathan Whitehorn     p = dlg_calloc(CACHE, 1);
1404c8945a0SNathan Whitehorn     assert_ptr(p, "load_cache");
1414c8945a0SNathan Whitehorn     p->next = cache_list;
1424c8945a0SNathan Whitehorn     cache_list = p;
1434c8945a0SNathan Whitehorn 
1444c8945a0SNathan Whitehorn     p->cache_at = cache;
1454c8945a0SNathan Whitehorn     p->string_at = string;
1464c8945a0SNathan Whitehorn 
1474c8945a0SNathan Whitehorn     *cache = *p;
1484c8945a0SNathan Whitehorn #ifdef HAVE_TSEARCH
1494c8945a0SNathan Whitehorn     (void) tsearch(p, &sorted_cache, compare_cache);
1504c8945a0SNathan Whitehorn #endif
1514c8945a0SNathan Whitehorn }
1524c8945a0SNathan Whitehorn 
1534c8945a0SNathan Whitehorn static void
1544c8945a0SNathan Whitehorn load_cache(CACHE * cache, const char *string)
1554c8945a0SNathan Whitehorn {
1564c8945a0SNathan Whitehorn     CACHE *p;
1574c8945a0SNathan Whitehorn 
1584c8945a0SNathan Whitehorn     if ((p = find_cache(cache, string)) != 0) {
1594c8945a0SNathan Whitehorn 	*cache = *p;
1604c8945a0SNathan Whitehorn     } else {
1614c8945a0SNathan Whitehorn 	make_cache(cache, string);
1624c8945a0SNathan Whitehorn     }
1634c8945a0SNathan Whitehorn }
1644c8945a0SNathan Whitehorn 
1654c8945a0SNathan Whitehorn static void
1664c8945a0SNathan Whitehorn save_cache(CACHE * cache, const char *string)
1674c8945a0SNathan Whitehorn {
1684c8945a0SNathan Whitehorn     CACHE *p;
1694c8945a0SNathan Whitehorn 
1704c8945a0SNathan Whitehorn     if ((p = find_cache(cache, string)) != 0) {
1714c8945a0SNathan Whitehorn 	CACHE *q = p->next;
1724c8945a0SNathan Whitehorn 	*p = *cache;
1734c8945a0SNathan Whitehorn 	p->next = q;
1744c8945a0SNathan Whitehorn     }
1754c8945a0SNathan Whitehorn }
1764c8945a0SNathan Whitehorn #else
1774c8945a0SNathan Whitehorn #define SAME_CACHE(c,s,l) (c->string != 0)
1784c8945a0SNathan Whitehorn #define load_cache(cache, string)	/* nothing */
1794c8945a0SNathan Whitehorn #define save_cache(cache, string)	/* nothing */
1804c8945a0SNathan Whitehorn #endif /* USE_WIDE_CURSES */
1814c8945a0SNathan Whitehorn 
1824c8945a0SNathan Whitehorn /*
1834c8945a0SNathan Whitehorn  * If the given string has not changed, we do not need to update the index.
1844c8945a0SNathan Whitehorn  * If we need to update the index, allocate enough memory for it.
1854c8945a0SNathan Whitehorn  */
1864c8945a0SNathan Whitehorn static bool
1874c8945a0SNathan Whitehorn same_cache2(CACHE * cache, const char *string, unsigned i_len)
1884c8945a0SNathan Whitehorn {
1894c8945a0SNathan Whitehorn     unsigned need;
1907a1c0d96SNathan Whitehorn     size_t s_len = strlen(string);
1914c8945a0SNathan Whitehorn 
1924c8945a0SNathan Whitehorn     if (cache->s_len != 0
1934c8945a0SNathan Whitehorn 	&& cache->s_len >= s_len
1944c8945a0SNathan Whitehorn 	&& cache->list != 0
1957a1c0d96SNathan Whitehorn 	&& SAME_CACHE(cache, string, (size_t) s_len)) {
1964c8945a0SNathan Whitehorn 	return TRUE;
1974c8945a0SNathan Whitehorn     }
1984c8945a0SNathan Whitehorn 
1994c8945a0SNathan Whitehorn     need = (i_len + 1);
2004c8945a0SNathan Whitehorn     if (cache->list == 0) {
2014c8945a0SNathan Whitehorn 	cache->list = dlg_malloc(int, need);
2024c8945a0SNathan Whitehorn     } else if (cache->i_len < i_len) {
2034c8945a0SNathan Whitehorn 	cache->list = dlg_realloc(int, need, cache->list);
2044c8945a0SNathan Whitehorn     }
2054c8945a0SNathan Whitehorn     cache->i_len = i_len;
2064c8945a0SNathan Whitehorn 
2074c8945a0SNathan Whitehorn     if (cache->s_len >= s_len && cache->string != 0) {
2084c8945a0SNathan Whitehorn 	strcpy(cache->string, string);
2094c8945a0SNathan Whitehorn     } else {
2104c8945a0SNathan Whitehorn 	if (cache->string != 0)
2114c8945a0SNathan Whitehorn 	    free(cache->string);
2124c8945a0SNathan Whitehorn 	cache->string = dlg_strclone(string);
2134c8945a0SNathan Whitehorn     }
2144c8945a0SNathan Whitehorn     cache->s_len = s_len;
2154c8945a0SNathan Whitehorn 
2164c8945a0SNathan Whitehorn     return FALSE;
2174c8945a0SNathan Whitehorn }
2184c8945a0SNathan Whitehorn 
2194c8945a0SNathan Whitehorn #ifdef USE_WIDE_CURSES
2204c8945a0SNathan Whitehorn /*
2214c8945a0SNathan Whitehorn  * Like same_cache2(), but we are only concerned about caching a copy of the
2224c8945a0SNathan Whitehorn  * string and its associated length.
2234c8945a0SNathan Whitehorn  */
2244c8945a0SNathan Whitehorn static bool
2257a1c0d96SNathan Whitehorn same_cache1(CACHE * cache, const char *string, size_t i_len)
2264c8945a0SNathan Whitehorn {
2277a1c0d96SNathan Whitehorn     size_t s_len = strlen(string);
2284c8945a0SNathan Whitehorn 
2294c8945a0SNathan Whitehorn     if (cache->s_len == s_len
2307a1c0d96SNathan Whitehorn 	&& SAME_CACHE(cache, string, (size_t) s_len)) {
2314c8945a0SNathan Whitehorn 	return TRUE;
2324c8945a0SNathan Whitehorn     }
2334c8945a0SNathan Whitehorn 
2344c8945a0SNathan Whitehorn     if (cache->s_len >= s_len && cache->string != 0) {
2354c8945a0SNathan Whitehorn 	strcpy(cache->string, string);
2364c8945a0SNathan Whitehorn     } else {
2374c8945a0SNathan Whitehorn 	if (cache->string != 0)
2384c8945a0SNathan Whitehorn 	    free(cache->string);
2394c8945a0SNathan Whitehorn 	cache->string = dlg_strclone(string);
2404c8945a0SNathan Whitehorn     }
2414c8945a0SNathan Whitehorn     cache->s_len = s_len;
2424c8945a0SNathan Whitehorn     cache->i_len = i_len;
2434c8945a0SNathan Whitehorn 
2444c8945a0SNathan Whitehorn     return FALSE;
2454c8945a0SNathan Whitehorn }
2464c8945a0SNathan Whitehorn #endif /* USE_CACHING */
2474c8945a0SNathan Whitehorn 
2484c8945a0SNathan Whitehorn /*
2494c8945a0SNathan Whitehorn  * Counts the number of bytes that make up complete wide-characters, up to byte
2504c8945a0SNathan Whitehorn  * 'len'.  If there is no locale set, simply return the original length.
2514c8945a0SNathan Whitehorn  */
2524c8945a0SNathan Whitehorn #ifdef USE_WIDE_CURSES
2534c8945a0SNathan Whitehorn static int
2544c8945a0SNathan Whitehorn dlg_count_wcbytes(const char *string, size_t len)
2554c8945a0SNathan Whitehorn {
2564c8945a0SNathan Whitehorn     int result;
2574c8945a0SNathan Whitehorn 
2584c8945a0SNathan Whitehorn     if (have_locale()) {
2594c8945a0SNathan Whitehorn 	static CACHE cache;
2604c8945a0SNathan Whitehorn 
2614c8945a0SNathan Whitehorn 	load_cache(&cache, string);
2624c8945a0SNathan Whitehorn 	if (!same_cache1(&cache, string, len)) {
2634c8945a0SNathan Whitehorn 	    while (len != 0) {
2644c8945a0SNathan Whitehorn 		size_t code = 0;
2654c8945a0SNathan Whitehorn 		const char *src = cache.string;
2664c8945a0SNathan Whitehorn 		mbstate_t state;
2674c8945a0SNathan Whitehorn 		char save = cache.string[len];
2684c8945a0SNathan Whitehorn 
2694c8945a0SNathan Whitehorn 		cache.string[len] = '\0';
2704c8945a0SNathan Whitehorn 		memset(&state, 0, sizeof(state));
2714c8945a0SNathan Whitehorn 		code = mbsrtowcs((wchar_t *) 0, &src, len, &state);
2724c8945a0SNathan Whitehorn 		cache.string[len] = save;
2734c8945a0SNathan Whitehorn 		if ((int) code >= 0) {
2744c8945a0SNathan Whitehorn 		    break;
2754c8945a0SNathan Whitehorn 		}
2764c8945a0SNathan Whitehorn 		--len;
2774c8945a0SNathan Whitehorn 	    }
2784c8945a0SNathan Whitehorn 	    cache.i_len = len;
2794c8945a0SNathan Whitehorn 	    save_cache(&cache, string);
2804c8945a0SNathan Whitehorn 	}
2814c8945a0SNathan Whitehorn 	result = (int) cache.i_len;
2824c8945a0SNathan Whitehorn     } else {
2834c8945a0SNathan Whitehorn 	result = (int) len;
2844c8945a0SNathan Whitehorn     }
2854c8945a0SNathan Whitehorn     return result;
2864c8945a0SNathan Whitehorn }
2874c8945a0SNathan Whitehorn #endif /* USE_WIDE_CURSES */
2884c8945a0SNathan Whitehorn 
2894c8945a0SNathan Whitehorn /*
2904c8945a0SNathan Whitehorn  * Counts the number of wide-characters in the string.
2914c8945a0SNathan Whitehorn  */
2924c8945a0SNathan Whitehorn int
2934c8945a0SNathan Whitehorn dlg_count_wchars(const char *string)
2944c8945a0SNathan Whitehorn {
2954c8945a0SNathan Whitehorn     int result;
2964c8945a0SNathan Whitehorn 
2974c8945a0SNathan Whitehorn #ifdef USE_WIDE_CURSES
2984c8945a0SNathan Whitehorn     if (have_locale()) {
2994c8945a0SNathan Whitehorn 	static CACHE cache;
3004c8945a0SNathan Whitehorn 	size_t len = strlen(string);
3014c8945a0SNathan Whitehorn 
3024c8945a0SNathan Whitehorn 	load_cache(&cache, string);
3034c8945a0SNathan Whitehorn 	if (!same_cache1(&cache, string, len)) {
3044c8945a0SNathan Whitehorn 	    const char *src = cache.string;
3054c8945a0SNathan Whitehorn 	    mbstate_t state;
3064c8945a0SNathan Whitehorn 	    int part = dlg_count_wcbytes(cache.string, len);
3074c8945a0SNathan Whitehorn 	    char save = cache.string[part];
3084c8945a0SNathan Whitehorn 	    size_t code;
3094c8945a0SNathan Whitehorn 	    wchar_t *temp = dlg_calloc(wchar_t, len + 1);
3104c8945a0SNathan Whitehorn 
3112a3e3873SBaptiste Daroussin 	    if (temp != 0) {
3124c8945a0SNathan Whitehorn 		cache.string[part] = '\0';
3134c8945a0SNathan Whitehorn 		memset(&state, 0, sizeof(state));
3144c8945a0SNathan Whitehorn 		code = mbsrtowcs(temp, &src, (size_t) part, &state);
3154c8945a0SNathan Whitehorn 		cache.i_len = ((int) code >= 0) ? wcslen(temp) : 0;
3164c8945a0SNathan Whitehorn 		cache.string[part] = save;
3174c8945a0SNathan Whitehorn 		free(temp);
3184c8945a0SNathan Whitehorn 		save_cache(&cache, string);
3192a3e3873SBaptiste Daroussin 	    } else {
3202a3e3873SBaptiste Daroussin 		cache.i_len = 0;
3212a3e3873SBaptiste Daroussin 	    }
3224c8945a0SNathan Whitehorn 	}
3234c8945a0SNathan Whitehorn 	result = (int) cache.i_len;
3244c8945a0SNathan Whitehorn     } else
3254c8945a0SNathan Whitehorn #endif /* USE_WIDE_CURSES */
3264c8945a0SNathan Whitehorn     {
3274c8945a0SNathan Whitehorn 	result = (int) strlen(string);
3284c8945a0SNathan Whitehorn     }
3294c8945a0SNathan Whitehorn     return result;
3304c8945a0SNathan Whitehorn }
3314c8945a0SNathan Whitehorn 
3324c8945a0SNathan Whitehorn /*
3334c8945a0SNathan Whitehorn  * Build an index of the wide-characters in the string, so we can easily tell
3344c8945a0SNathan Whitehorn  * which byte-offset begins a given wide-character.
3354c8945a0SNathan Whitehorn  */
3364c8945a0SNathan Whitehorn const int *
3374c8945a0SNathan Whitehorn dlg_index_wchars(const char *string)
3384c8945a0SNathan Whitehorn {
3394c8945a0SNathan Whitehorn     static CACHE cache;
3404c8945a0SNathan Whitehorn     unsigned len = (unsigned) dlg_count_wchars(string);
3414c8945a0SNathan Whitehorn     unsigned inx;
3424c8945a0SNathan Whitehorn 
3434c8945a0SNathan Whitehorn     load_cache(&cache, string);
3444c8945a0SNathan Whitehorn     if (!same_cache2(&cache, string, len)) {
3454c8945a0SNathan Whitehorn 	const char *current = string;
3464c8945a0SNathan Whitehorn 
3474c8945a0SNathan Whitehorn 	cache.list[0] = 0;
3484c8945a0SNathan Whitehorn 	for (inx = 1; inx <= len; ++inx) {
3494c8945a0SNathan Whitehorn #ifdef USE_WIDE_CURSES
3504c8945a0SNathan Whitehorn 	    if (have_locale()) {
3514c8945a0SNathan Whitehorn 		mbstate_t state;
3524c8945a0SNathan Whitehorn 		int width;
3534c8945a0SNathan Whitehorn 		memset(&state, 0, sizeof(state));
3544c8945a0SNathan Whitehorn 		width = (int) mbrlen(current, strlen(current), &state);
3554c8945a0SNathan Whitehorn 		if (width <= 0)
3564c8945a0SNathan Whitehorn 		    width = 1;	/* FIXME: what if we have a control-char? */
3574c8945a0SNathan Whitehorn 		current += width;
3584c8945a0SNathan Whitehorn 		cache.list[inx] = cache.list[inx - 1] + width;
3594c8945a0SNathan Whitehorn 	    } else
3604c8945a0SNathan Whitehorn #endif /* USE_WIDE_CURSES */
3614c8945a0SNathan Whitehorn 	    {
3624c8945a0SNathan Whitehorn 		(void) current;
3634c8945a0SNathan Whitehorn 		cache.list[inx] = (int) inx;
3644c8945a0SNathan Whitehorn 	    }
3654c8945a0SNathan Whitehorn 	}
3664c8945a0SNathan Whitehorn 	save_cache(&cache, string);
3674c8945a0SNathan Whitehorn     }
3684c8945a0SNathan Whitehorn     return cache.list;
3694c8945a0SNathan Whitehorn }
3704c8945a0SNathan Whitehorn 
3714c8945a0SNathan Whitehorn /*
3724c8945a0SNathan Whitehorn  * Given the character-offset to find in the list, return the corresponding
3734c8945a0SNathan Whitehorn  * array index.
3744c8945a0SNathan Whitehorn  */
3754c8945a0SNathan Whitehorn int
3764c8945a0SNathan Whitehorn dlg_find_index(const int *list, int limit, int to_find)
3774c8945a0SNathan Whitehorn {
3784c8945a0SNathan Whitehorn     int result;
3794c8945a0SNathan Whitehorn     for (result = 0; result <= limit; ++result) {
3804c8945a0SNathan Whitehorn 	if (to_find == list[result]
3814c8945a0SNathan Whitehorn 	    || result == limit
3822a3e3873SBaptiste Daroussin 	    || ((result < limit) && (to_find < list[result + 1]))) {
3834c8945a0SNathan Whitehorn 	    break;
3844c8945a0SNathan Whitehorn 	}
3852a3e3873SBaptiste Daroussin     }
3864c8945a0SNathan Whitehorn     return result;
3874c8945a0SNathan Whitehorn }
3884c8945a0SNathan Whitehorn 
3894c8945a0SNathan Whitehorn /*
3904c8945a0SNathan Whitehorn  * Build a list of the display-columns for the given string's characters.
3914c8945a0SNathan Whitehorn  */
3924c8945a0SNathan Whitehorn const int *
3934c8945a0SNathan Whitehorn dlg_index_columns(const char *string)
3944c8945a0SNathan Whitehorn {
3954c8945a0SNathan Whitehorn     static CACHE cache;
3964c8945a0SNathan Whitehorn     unsigned len = (unsigned) dlg_count_wchars(string);
3974c8945a0SNathan Whitehorn     unsigned inx;
3984c8945a0SNathan Whitehorn 
3994c8945a0SNathan Whitehorn     load_cache(&cache, string);
4004c8945a0SNathan Whitehorn     if (!same_cache2(&cache, string, len)) {
4014c8945a0SNathan Whitehorn 	cache.list[0] = 0;
4024c8945a0SNathan Whitehorn #ifdef USE_WIDE_CURSES
4034c8945a0SNathan Whitehorn 	if (have_locale()) {
4044c8945a0SNathan Whitehorn 	    size_t num_bytes = strlen(string);
4054c8945a0SNathan Whitehorn 	    const int *inx_wchars = dlg_index_wchars(string);
4064c8945a0SNathan Whitehorn 	    mbstate_t state;
4074c8945a0SNathan Whitehorn 
4084c8945a0SNathan Whitehorn 	    for (inx = 0; inx < len; ++inx) {
4094c8945a0SNathan Whitehorn 		wchar_t temp[2];
4104c8945a0SNathan Whitehorn 		size_t check;
4114c8945a0SNathan Whitehorn 		int result;
4124c8945a0SNathan Whitehorn 
4134c8945a0SNathan Whitehorn 		if (string[inx_wchars[inx]] == TAB) {
4144c8945a0SNathan Whitehorn 		    result = ((cache.list[inx] | 7) + 1) - cache.list[inx];
4154c8945a0SNathan Whitehorn 		} else {
4164c8945a0SNathan Whitehorn 		    memset(&state, 0, sizeof(state));
4174c8945a0SNathan Whitehorn 		    memset(temp, 0, sizeof(temp));
4184c8945a0SNathan Whitehorn 		    check = mbrtowc(temp,
4194c8945a0SNathan Whitehorn 				    string + inx_wchars[inx],
4204c8945a0SNathan Whitehorn 				    num_bytes - (size_t) inx_wchars[inx],
4214c8945a0SNathan Whitehorn 				    &state);
4224c8945a0SNathan Whitehorn 		    if ((int) check <= 0) {
4234c8945a0SNathan Whitehorn 			result = 1;
4244c8945a0SNathan Whitehorn 		    } else {
4254c8945a0SNathan Whitehorn 			result = wcwidth(temp[0]);
4264c8945a0SNathan Whitehorn 		    }
4274c8945a0SNathan Whitehorn 		    if (result < 0) {
4287a1c0d96SNathan Whitehorn 			const wchar_t *printable;
4297a1c0d96SNathan Whitehorn 			cchar_t temp2, *temp2p = &temp2;
4307a1c0d96SNathan Whitehorn 			setcchar(temp2p, temp, 0, 0, 0);
4317a1c0d96SNathan Whitehorn 			printable = wunctrl(temp2p);
4324c8945a0SNathan Whitehorn 			result = printable ? (int) wcslen(printable) : 1;
4334c8945a0SNathan Whitehorn 		    }
4344c8945a0SNathan Whitehorn 		}
4354c8945a0SNathan Whitehorn 		cache.list[inx + 1] = result;
4364c8945a0SNathan Whitehorn 		if (inx != 0)
4374c8945a0SNathan Whitehorn 		    cache.list[inx + 1] += cache.list[inx];
4384c8945a0SNathan Whitehorn 	    }
4394c8945a0SNathan Whitehorn 	} else
4404c8945a0SNathan Whitehorn #endif /* USE_WIDE_CURSES */
4414c8945a0SNathan Whitehorn 	{
4424c8945a0SNathan Whitehorn 	    for (inx = 0; inx < len; ++inx) {
4434c8945a0SNathan Whitehorn 		chtype ch = UCH(string[inx]);
4444c8945a0SNathan Whitehorn 
4454c8945a0SNathan Whitehorn 		if (ch == TAB)
4464c8945a0SNathan Whitehorn 		    cache.list[inx + 1] =
4474c8945a0SNathan Whitehorn 			((cache.list[inx] | 7) + 1) - cache.list[inx];
4484c8945a0SNathan Whitehorn 		else if (isprint(ch))
4494c8945a0SNathan Whitehorn 		    cache.list[inx + 1] = 1;
4504c8945a0SNathan Whitehorn 		else {
4514c8945a0SNathan Whitehorn 		    const char *printable;
4524c8945a0SNathan Whitehorn 		    printable = unctrl(ch);
4534c8945a0SNathan Whitehorn 		    cache.list[inx + 1] = (printable
4544c8945a0SNathan Whitehorn 					   ? (int) strlen(printable)
4554c8945a0SNathan Whitehorn 					   : 1);
4564c8945a0SNathan Whitehorn 		}
4574c8945a0SNathan Whitehorn 		if (inx != 0)
4584c8945a0SNathan Whitehorn 		    cache.list[inx + 1] += cache.list[inx];
4594c8945a0SNathan Whitehorn 	    }
4604c8945a0SNathan Whitehorn 	}
4614c8945a0SNathan Whitehorn 	save_cache(&cache, string);
4624c8945a0SNathan Whitehorn     }
4634c8945a0SNathan Whitehorn     return cache.list;
4644c8945a0SNathan Whitehorn }
4654c8945a0SNathan Whitehorn 
4664c8945a0SNathan Whitehorn /*
4674c8945a0SNathan Whitehorn  * Returns the number of columns used for a string.  That happens to be the
4684c8945a0SNathan Whitehorn  * end-value of the cols[] array.
4694c8945a0SNathan Whitehorn  */
4704c8945a0SNathan Whitehorn int
4714c8945a0SNathan Whitehorn dlg_count_columns(const char *string)
4724c8945a0SNathan Whitehorn {
4734c8945a0SNathan Whitehorn     int result = 0;
4744c8945a0SNathan Whitehorn     int limit = dlg_count_wchars(string);
4754c8945a0SNathan Whitehorn     if (limit > 0) {
4764c8945a0SNathan Whitehorn 	const int *cols = dlg_index_columns(string);
4774c8945a0SNathan Whitehorn 	result = cols[limit];
4784c8945a0SNathan Whitehorn     } else {
4794c8945a0SNathan Whitehorn 	result = (int) strlen(string);
4804c8945a0SNathan Whitehorn     }
4814c8945a0SNathan Whitehorn     return result;
4824c8945a0SNathan Whitehorn }
4834c8945a0SNathan Whitehorn 
4844c8945a0SNathan Whitehorn /*
4854c8945a0SNathan Whitehorn  * Given a column limit, count the number of wide characters that can fit
4864c8945a0SNathan Whitehorn  * into that limit.  The offset is used to skip over a leading character
4874c8945a0SNathan Whitehorn  * that was already written.
4884c8945a0SNathan Whitehorn  */
4894c8945a0SNathan Whitehorn int
4904c8945a0SNathan Whitehorn dlg_limit_columns(const char *string, int limit, int offset)
4914c8945a0SNathan Whitehorn {
4924c8945a0SNathan Whitehorn     const int *cols = dlg_index_columns(string);
4934c8945a0SNathan Whitehorn     int result = dlg_count_wchars(string);
4944c8945a0SNathan Whitehorn 
4954c8945a0SNathan Whitehorn     while (result > 0 && (cols[result] - cols[offset]) > limit)
4964c8945a0SNathan Whitehorn 	--result;
4974c8945a0SNathan Whitehorn     return result;
4984c8945a0SNathan Whitehorn }
4994c8945a0SNathan Whitehorn 
5004c8945a0SNathan Whitehorn /*
5014c8945a0SNathan Whitehorn  * Updates the string and character-offset, given various editing characters
5024c8945a0SNathan Whitehorn  * or literal characters which are inserted at the character-offset.
5034c8945a0SNathan Whitehorn  */
5044c8945a0SNathan Whitehorn bool
5054c8945a0SNathan Whitehorn dlg_edit_string(char *string, int *chr_offset, int key, int fkey, bool force)
5064c8945a0SNathan Whitehorn {
5074c8945a0SNathan Whitehorn     int i;
5084c8945a0SNathan Whitehorn     int len = (int) strlen(string);
5094c8945a0SNathan Whitehorn     int limit = dlg_count_wchars(string);
5104c8945a0SNathan Whitehorn     const int *indx = dlg_index_wchars(string);
5114c8945a0SNathan Whitehorn     int offset = dlg_find_index(indx, limit, *chr_offset);
5124c8945a0SNathan Whitehorn     int max_len = dlg_max_input(MAX_LEN);
5134c8945a0SNathan Whitehorn     bool edit = TRUE;
5144c8945a0SNathan Whitehorn 
5154c8945a0SNathan Whitehorn     /* transform editing characters into equivalent function-keys */
5164c8945a0SNathan Whitehorn     if (!fkey) {
5174c8945a0SNathan Whitehorn 	fkey = TRUE;		/* assume we transform */
5184c8945a0SNathan Whitehorn 	switch (key) {
5194c8945a0SNathan Whitehorn 	case 0:
5204c8945a0SNathan Whitehorn 	    break;
5214c8945a0SNathan Whitehorn 	case ESC:
5224c8945a0SNathan Whitehorn 	case TAB:
5234c8945a0SNathan Whitehorn 	    fkey = FALSE;	/* this is used for navigation */
5244c8945a0SNathan Whitehorn 	    break;
5254c8945a0SNathan Whitehorn 	default:
5264c8945a0SNathan Whitehorn 	    fkey = FALSE;	/* ...no, we did not transform */
5274c8945a0SNathan Whitehorn 	    break;
5284c8945a0SNathan Whitehorn 	}
5294c8945a0SNathan Whitehorn     }
5304c8945a0SNathan Whitehorn 
5314c8945a0SNathan Whitehorn     if (fkey) {
5324c8945a0SNathan Whitehorn 	switch (key) {
5334c8945a0SNathan Whitehorn 	case 0:		/* special case for loop entry */
5344c8945a0SNathan Whitehorn 	    edit = force;
5354c8945a0SNathan Whitehorn 	    break;
5364c8945a0SNathan Whitehorn 	case DLGK_GRID_LEFT:
5372a3e3873SBaptiste Daroussin 	    if (*chr_offset && offset > 0)
5384c8945a0SNathan Whitehorn 		*chr_offset = indx[offset - 1];
5394c8945a0SNathan Whitehorn 	    break;
5404c8945a0SNathan Whitehorn 	case DLGK_GRID_RIGHT:
5414c8945a0SNathan Whitehorn 	    if (offset < limit)
5424c8945a0SNathan Whitehorn 		*chr_offset = indx[offset + 1];
5434c8945a0SNathan Whitehorn 	    break;
5444c8945a0SNathan Whitehorn 	case DLGK_BEGIN:
5454c8945a0SNathan Whitehorn 	    if (*chr_offset)
5464c8945a0SNathan Whitehorn 		*chr_offset = 0;
5474c8945a0SNathan Whitehorn 	    break;
5484c8945a0SNathan Whitehorn 	case DLGK_FINAL:
5494c8945a0SNathan Whitehorn 	    if (offset < limit)
5504c8945a0SNathan Whitehorn 		*chr_offset = indx[limit];
5514c8945a0SNathan Whitehorn 	    break;
5524c8945a0SNathan Whitehorn 	case DLGK_DELETE_LEFT:
5534c8945a0SNathan Whitehorn 	    if (offset) {
5544c8945a0SNathan Whitehorn 		int gap = indx[offset] - indx[offset - 1];
5554c8945a0SNathan Whitehorn 		*chr_offset = indx[offset - 1];
5564c8945a0SNathan Whitehorn 		if (gap > 0) {
5574c8945a0SNathan Whitehorn 		    for (i = *chr_offset;
5584c8945a0SNathan Whitehorn 			 (string[i] = string[i + gap]) != '\0';
5594c8945a0SNathan Whitehorn 			 i++) {
5604c8945a0SNathan Whitehorn 			;
5614c8945a0SNathan Whitehorn 		    }
5624c8945a0SNathan Whitehorn 		}
5634c8945a0SNathan Whitehorn 	    }
5644c8945a0SNathan Whitehorn 	    break;
5654c8945a0SNathan Whitehorn 	case DLGK_DELETE_RIGHT:
5664c8945a0SNathan Whitehorn 	    if (limit) {
5674c8945a0SNathan Whitehorn 		if (--limit == 0) {
5684c8945a0SNathan Whitehorn 		    string[*chr_offset = 0] = '\0';
5694c8945a0SNathan Whitehorn 		} else {
5704c8945a0SNathan Whitehorn 		    int gap = ((offset <= limit)
5714c8945a0SNathan Whitehorn 			       ? (indx[offset + 1] - indx[offset])
5724c8945a0SNathan Whitehorn 			       : 0);
5734c8945a0SNathan Whitehorn 		    if (gap > 0) {
5744c8945a0SNathan Whitehorn 			for (i = indx[offset];
5754c8945a0SNathan Whitehorn 			     (string[i] = string[i + gap]) != '\0';
5764c8945a0SNathan Whitehorn 			     i++) {
5774c8945a0SNathan Whitehorn 			    ;
5784c8945a0SNathan Whitehorn 			}
5794c8945a0SNathan Whitehorn 		    } else if (offset > 0) {
5804c8945a0SNathan Whitehorn 			string[indx[offset - 1]] = '\0';
5814c8945a0SNathan Whitehorn 		    }
5824c8945a0SNathan Whitehorn 		    if (*chr_offset > indx[limit])
5834c8945a0SNathan Whitehorn 			*chr_offset = indx[limit];
5844c8945a0SNathan Whitehorn 		}
5854c8945a0SNathan Whitehorn 	    }
5864c8945a0SNathan Whitehorn 	    break;
5874c8945a0SNathan Whitehorn 	case DLGK_DELETE_ALL:
5884c8945a0SNathan Whitehorn 	    string[*chr_offset = 0] = '\0';
5894c8945a0SNathan Whitehorn 	    break;
5904c8945a0SNathan Whitehorn 	case DLGK_ENTER:
5914c8945a0SNathan Whitehorn 	    edit = 0;
5924c8945a0SNathan Whitehorn 	    break;
5934c8945a0SNathan Whitehorn #ifdef KEY_RESIZE
5944c8945a0SNathan Whitehorn 	case KEY_RESIZE:
5954c8945a0SNathan Whitehorn 	    edit = 0;
5964c8945a0SNathan Whitehorn 	    break;
5974c8945a0SNathan Whitehorn #endif
5984c8945a0SNathan Whitehorn 	case DLGK_GRID_UP:
5994c8945a0SNathan Whitehorn 	case DLGK_GRID_DOWN:
6004c8945a0SNathan Whitehorn 	case DLGK_FIELD_NEXT:
6014c8945a0SNathan Whitehorn 	case DLGK_FIELD_PREV:
6024c8945a0SNathan Whitehorn 	    edit = 0;
6034c8945a0SNathan Whitehorn 	    break;
6044c8945a0SNathan Whitehorn 	case ERR:
6054c8945a0SNathan Whitehorn 	    edit = 0;
6064c8945a0SNathan Whitehorn 	    break;
6074c8945a0SNathan Whitehorn 	default:
6084c8945a0SNathan Whitehorn 	    beep();
6094c8945a0SNathan Whitehorn 	    break;
6104c8945a0SNathan Whitehorn 	}
6114c8945a0SNathan Whitehorn     } else {
6124c8945a0SNathan Whitehorn 	if (key == ESC || key == ERR) {
6134c8945a0SNathan Whitehorn 	    edit = 0;
6144c8945a0SNathan Whitehorn 	} else {
6154c8945a0SNathan Whitehorn 	    if (len < max_len) {
6164c8945a0SNathan Whitehorn 		for (i = ++len; i > *chr_offset; i--)
6174c8945a0SNathan Whitehorn 		    string[i] = string[i - 1];
6184c8945a0SNathan Whitehorn 		string[*chr_offset] = (char) key;
6194c8945a0SNathan Whitehorn 		*chr_offset += 1;
6204c8945a0SNathan Whitehorn 	    } else {
6214c8945a0SNathan Whitehorn 		(void) beep();
6224c8945a0SNathan Whitehorn 	    }
6234c8945a0SNathan Whitehorn 	}
6244c8945a0SNathan Whitehorn     }
6254c8945a0SNathan Whitehorn     return edit;
6264c8945a0SNathan Whitehorn }
6274c8945a0SNathan Whitehorn 
6284c8945a0SNathan Whitehorn static void
6294c8945a0SNathan Whitehorn compute_edit_offset(const char *string,
6304c8945a0SNathan Whitehorn 		    int chr_offset,
6314c8945a0SNathan Whitehorn 		    int x_last,
6324c8945a0SNathan Whitehorn 		    int *p_dpy_column,
6334c8945a0SNathan Whitehorn 		    int *p_scroll_amt)
6344c8945a0SNathan Whitehorn {
6354c8945a0SNathan Whitehorn     const int *cols = dlg_index_columns(string);
6364c8945a0SNathan Whitehorn     const int *indx = dlg_index_wchars(string);
6374c8945a0SNathan Whitehorn     int limit = dlg_count_wchars(string);
6384c8945a0SNathan Whitehorn     int offset = dlg_find_index(indx, limit, chr_offset);
6394c8945a0SNathan Whitehorn     int offset2;
6404c8945a0SNathan Whitehorn     int dpy_column;
6414c8945a0SNathan Whitehorn     int n;
6424c8945a0SNathan Whitehorn 
6434c8945a0SNathan Whitehorn     for (n = offset2 = 0; n <= offset; ++n) {
6444c8945a0SNathan Whitehorn 	if ((cols[offset] - cols[n]) < x_last
6454c8945a0SNathan Whitehorn 	    && (offset == limit || (cols[offset + 1] - cols[n]) < x_last)) {
6464c8945a0SNathan Whitehorn 	    offset2 = n;
6474c8945a0SNathan Whitehorn 	    break;
6484c8945a0SNathan Whitehorn 	}
6494c8945a0SNathan Whitehorn     }
6504c8945a0SNathan Whitehorn 
6514c8945a0SNathan Whitehorn     dpy_column = cols[offset] - cols[offset2];
6524c8945a0SNathan Whitehorn 
6534c8945a0SNathan Whitehorn     if (p_dpy_column != 0)
6544c8945a0SNathan Whitehorn 	*p_dpy_column = dpy_column;
6554c8945a0SNathan Whitehorn     if (p_scroll_amt != 0)
6564c8945a0SNathan Whitehorn 	*p_scroll_amt = offset2;
6574c8945a0SNathan Whitehorn }
6584c8945a0SNathan Whitehorn 
6594c8945a0SNathan Whitehorn /*
6604c8945a0SNathan Whitehorn  * Given the character-offset in the string, returns the display-offset where
6614c8945a0SNathan Whitehorn  * we will position the cursor.
6624c8945a0SNathan Whitehorn  */
6634c8945a0SNathan Whitehorn int
6644c8945a0SNathan Whitehorn dlg_edit_offset(char *string, int chr_offset, int x_last)
6654c8945a0SNathan Whitehorn {
6664c8945a0SNathan Whitehorn     int result;
6674c8945a0SNathan Whitehorn 
6684c8945a0SNathan Whitehorn     compute_edit_offset(string, chr_offset, x_last, &result, 0);
6694c8945a0SNathan Whitehorn 
6704c8945a0SNathan Whitehorn     return result;
6714c8945a0SNathan Whitehorn }
6724c8945a0SNathan Whitehorn 
6734c8945a0SNathan Whitehorn /*
6744c8945a0SNathan Whitehorn  * Displays the string, shifted as necessary, to fit within the box and show
6754c8945a0SNathan Whitehorn  * the current character-offset.
6764c8945a0SNathan Whitehorn  */
6774c8945a0SNathan Whitehorn void
6784c8945a0SNathan Whitehorn dlg_show_string(WINDOW *win,
6794c8945a0SNathan Whitehorn 		const char *string,	/* string to display (may be multibyte) */
6804c8945a0SNathan Whitehorn 		int chr_offset,	/* character (not bytes) offset */
6814c8945a0SNathan Whitehorn 		chtype attr,	/* window-attributes */
6824c8945a0SNathan Whitehorn 		int y_base,	/* beginning row on screen */
6834c8945a0SNathan Whitehorn 		int x_base,	/* beginning column on screen */
6844c8945a0SNathan Whitehorn 		int x_last,	/* number of columns on screen */
6854c8945a0SNathan Whitehorn 		bool hidden,	/* if true, do not echo */
6864c8945a0SNathan Whitehorn 		bool force)	/* if true, force repaint */
6874c8945a0SNathan Whitehorn {
6884c8945a0SNathan Whitehorn     x_last = MIN(x_last + x_base, getmaxx(win)) - x_base;
6894c8945a0SNathan Whitehorn 
6904c8945a0SNathan Whitehorn     if (hidden && !dialog_vars.insecure) {
6914c8945a0SNathan Whitehorn 	if (force) {
6924c8945a0SNathan Whitehorn 	    (void) wmove(win, y_base, x_base);
6934c8945a0SNathan Whitehorn 	    wrefresh(win);
6944c8945a0SNathan Whitehorn 	}
6954c8945a0SNathan Whitehorn     } else {
6964c8945a0SNathan Whitehorn 	const int *cols = dlg_index_columns(string);
6974c8945a0SNathan Whitehorn 	const int *indx = dlg_index_wchars(string);
6984c8945a0SNathan Whitehorn 	int limit = dlg_count_wchars(string);
6994c8945a0SNathan Whitehorn 
7004c8945a0SNathan Whitehorn 	int i, j, k;
7014c8945a0SNathan Whitehorn 	int input_x;
7024c8945a0SNathan Whitehorn 	int scrollamt;
7034c8945a0SNathan Whitehorn 
7044c8945a0SNathan Whitehorn 	compute_edit_offset(string, chr_offset, x_last, &input_x, &scrollamt);
7054c8945a0SNathan Whitehorn 
7062a3e3873SBaptiste Daroussin 	(void) wattrset(win, attr);
7074c8945a0SNathan Whitehorn 	(void) wmove(win, y_base, x_base);
7084c8945a0SNathan Whitehorn 	for (i = scrollamt, k = 0; i < limit && k < x_last; ++i) {
7094c8945a0SNathan Whitehorn 	    int check = cols[i + 1] - cols[scrollamt];
7104c8945a0SNathan Whitehorn 	    if (check <= x_last) {
7114c8945a0SNathan Whitehorn 		for (j = indx[i]; j < indx[i + 1]; ++j) {
7124c8945a0SNathan Whitehorn 		    chtype ch = UCH(string[j]);
7134c8945a0SNathan Whitehorn 		    if (hidden && dialog_vars.insecure) {
7144c8945a0SNathan Whitehorn 			waddch(win, '*');
7154c8945a0SNathan Whitehorn 		    } else if (ch == TAB) {
7164c8945a0SNathan Whitehorn 			int count = cols[i + 1] - cols[i];
7174c8945a0SNathan Whitehorn 			while (--count >= 0)
7184c8945a0SNathan Whitehorn 			    waddch(win, ' ');
7194c8945a0SNathan Whitehorn 		    } else {
7204c8945a0SNathan Whitehorn 			waddch(win, ch);
7214c8945a0SNathan Whitehorn 		    }
7224c8945a0SNathan Whitehorn 		}
7234c8945a0SNathan Whitehorn 		k = check;
7244c8945a0SNathan Whitehorn 	    } else {
7254c8945a0SNathan Whitehorn 		break;
7264c8945a0SNathan Whitehorn 	    }
7274c8945a0SNathan Whitehorn 	}
7284c8945a0SNathan Whitehorn 	while (k++ < x_last)
7294c8945a0SNathan Whitehorn 	    waddch(win, ' ');
7304c8945a0SNathan Whitehorn 	(void) wmove(win, y_base, x_base + input_x);
7314c8945a0SNathan Whitehorn 	wrefresh(win);
7324c8945a0SNathan Whitehorn     }
7334c8945a0SNathan Whitehorn }
7344c8945a0SNathan Whitehorn 
7354c8945a0SNathan Whitehorn #ifdef NO_LEAKS
7364c8945a0SNathan Whitehorn void
7374c8945a0SNathan Whitehorn _dlg_inputstr_leaks(void)
7384c8945a0SNathan Whitehorn {
7394c8945a0SNathan Whitehorn #if USE_CACHING
7404c8945a0SNathan Whitehorn     while (cache_list != 0) {
7414c8945a0SNathan Whitehorn 	CACHE *next = cache_list->next;
7424c8945a0SNathan Whitehorn #ifdef HAVE_TSEARCH
7434c8945a0SNathan Whitehorn 	tdelete(cache_list, &sorted_cache, compare_cache);
7444c8945a0SNathan Whitehorn #endif
7454c8945a0SNathan Whitehorn 	if (cache_list->string != 0)
7464c8945a0SNathan Whitehorn 	    free(cache_list->string);
7474c8945a0SNathan Whitehorn 	if (cache_list->list != 0)
7484c8945a0SNathan Whitehorn 	    free(cache_list->list);
7494c8945a0SNathan Whitehorn 	free(cache_list);
7504c8945a0SNathan Whitehorn 	cache_list = next;
7514c8945a0SNathan Whitehorn     }
7524c8945a0SNathan Whitehorn #endif /* USE_CACHING */
7534c8945a0SNathan Whitehorn }
7544c8945a0SNathan Whitehorn #endif /* NO_LEAKS */
755