14c8945a0SNathan Whitehorn /*
2*a96ef450SBaptiste Daroussin * $Id: fselect.c,v 1.115 2021/01/16 17:19:15 tom Exp $
34c8945a0SNathan Whitehorn *
44c8945a0SNathan Whitehorn * fselect.c -- implements the file-selector box
54c8945a0SNathan Whitehorn *
6*a96ef450SBaptiste Daroussin * Copyright 2000-2020,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
24*a96ef450SBaptiste Daroussin #include <dlg_internals.h>
254c8945a0SNathan Whitehorn #include <dlg_keys.h>
264c8945a0SNathan Whitehorn
274c8945a0SNathan Whitehorn #include <sys/types.h>
284c8945a0SNathan Whitehorn #include <sys/stat.h>
294c8945a0SNathan Whitehorn
304c8945a0SNathan Whitehorn #if HAVE_DIRENT_H
314c8945a0SNathan Whitehorn # include <dirent.h>
324c8945a0SNathan Whitehorn # define NAMLEN(dirent) strlen((dirent)->d_name)
334c8945a0SNathan Whitehorn #else
344c8945a0SNathan Whitehorn # define dirent direct
354c8945a0SNathan Whitehorn # define NAMLEN(dirent) (dirent)->d_namlen
364c8945a0SNathan Whitehorn # if HAVE_SYS_NDIR_H
374c8945a0SNathan Whitehorn # include <sys/ndir.h>
384c8945a0SNathan Whitehorn # endif
394c8945a0SNathan Whitehorn # if HAVE_SYS_DIR_H
404c8945a0SNathan Whitehorn # include <sys/dir.h>
414c8945a0SNathan Whitehorn # endif
424c8945a0SNathan Whitehorn # if HAVE_NDIR_H
434c8945a0SNathan Whitehorn # include <ndir.h>
444c8945a0SNathan Whitehorn # endif
454c8945a0SNathan Whitehorn #endif
464c8945a0SNathan Whitehorn
474c8945a0SNathan Whitehorn # if defined(_FILE_OFFSET_BITS) && defined(HAVE_STRUCT_DIRENT64)
484c8945a0SNathan Whitehorn # if !defined(_LP64) && (_FILE_OFFSET_BITS == 64)
494c8945a0SNathan Whitehorn # define DIRENT struct dirent64
504c8945a0SNathan Whitehorn # else
514c8945a0SNathan Whitehorn # define DIRENT struct dirent
524c8945a0SNathan Whitehorn # endif
534c8945a0SNathan Whitehorn # else
544c8945a0SNathan Whitehorn # define DIRENT struct dirent
554c8945a0SNathan Whitehorn # endif
564c8945a0SNathan Whitehorn
574c8945a0SNathan Whitehorn #define EXT_WIDE 1
584c8945a0SNathan Whitehorn #define HDR_HIGH 1
594c8945a0SNathan Whitehorn #define BTN_HIGH (1 + 2 * MARGIN) /* Ok/Cancel, also input-box */
604c8945a0SNathan Whitehorn #define MIN_HIGH (HDR_HIGH - MARGIN + (BTN_HIGH * 2) + 4 * MARGIN)
614c8945a0SNathan Whitehorn #define MIN_WIDE (2 * MAX(dlg_count_columns(d_label), dlg_count_columns(f_label)) + 6 * MARGIN + 2 * EXT_WIDE)
624c8945a0SNathan Whitehorn
634c8945a0SNathan Whitehorn #define MOUSE_D (KEY_MAX + 0)
644c8945a0SNathan Whitehorn #define MOUSE_F (KEY_MAX + 10000)
654c8945a0SNathan Whitehorn #define MOUSE_T (KEY_MAX + 20000)
664c8945a0SNathan Whitehorn
674c8945a0SNathan Whitehorn typedef enum {
684c8945a0SNathan Whitehorn sDIRS = -3
694c8945a0SNathan Whitehorn ,sFILES = -2
704c8945a0SNathan Whitehorn ,sTEXT = -1
714c8945a0SNathan Whitehorn } STATES;
724c8945a0SNathan Whitehorn
734c8945a0SNathan Whitehorn typedef struct {
744c8945a0SNathan Whitehorn WINDOW *par; /* parent window */
754c8945a0SNathan Whitehorn WINDOW *win; /* this window */
764c8945a0SNathan Whitehorn int length; /* length of the data[] array */
774c8945a0SNathan Whitehorn int offset; /* index of first item on screen */
784c8945a0SNathan Whitehorn int choice; /* index of the selection */
794c8945a0SNathan Whitehorn int mousex; /* base of mouse-code return-values */
804c8945a0SNathan Whitehorn unsigned allocd;
814c8945a0SNathan Whitehorn char **data;
824c8945a0SNathan Whitehorn } LIST;
834c8945a0SNathan Whitehorn
844c8945a0SNathan Whitehorn typedef struct {
854c8945a0SNathan Whitehorn int length;
864c8945a0SNathan Whitehorn char **data;
874c8945a0SNathan Whitehorn } MATCH;
884c8945a0SNathan Whitehorn
894c8945a0SNathan Whitehorn static void
init_list(LIST * list,WINDOW * par,WINDOW * win,int mousex)904c8945a0SNathan Whitehorn init_list(LIST * list, WINDOW *par, WINDOW *win, int mousex)
914c8945a0SNathan Whitehorn {
924c8945a0SNathan Whitehorn list->par = par;
934c8945a0SNathan Whitehorn list->win = win;
944c8945a0SNathan Whitehorn list->length = 0;
954c8945a0SNathan Whitehorn list->offset = 0;
964c8945a0SNathan Whitehorn list->choice = 0;
974c8945a0SNathan Whitehorn list->mousex = mousex;
984c8945a0SNathan Whitehorn list->allocd = 0;
994c8945a0SNathan Whitehorn list->data = 0;
1004c8945a0SNathan Whitehorn dlg_mouse_mkbigregion(getbegy(win), getbegx(win),
1014c8945a0SNathan Whitehorn getmaxy(win), getmaxx(win),
1024c8945a0SNathan Whitehorn mousex, 1, 1, 1 /* by lines */ );
1034c8945a0SNathan Whitehorn }
1044c8945a0SNathan Whitehorn
1054c8945a0SNathan Whitehorn static char *
leaf_of(char * path)1064c8945a0SNathan Whitehorn leaf_of(char *path)
1074c8945a0SNathan Whitehorn {
1084c8945a0SNathan Whitehorn char *leaf = strrchr(path, '/');
1094c8945a0SNathan Whitehorn if (leaf != 0)
1104c8945a0SNathan Whitehorn leaf++;
1114c8945a0SNathan Whitehorn else
1124c8945a0SNathan Whitehorn leaf = path;
1134c8945a0SNathan Whitehorn return leaf;
1144c8945a0SNathan Whitehorn }
1154c8945a0SNathan Whitehorn
1164c8945a0SNathan Whitehorn static char *
data_of(LIST * list)1174c8945a0SNathan Whitehorn data_of(LIST * list)
1184c8945a0SNathan Whitehorn {
1194c8945a0SNathan Whitehorn if (list != 0
1204c8945a0SNathan Whitehorn && list->data != 0)
1214c8945a0SNathan Whitehorn return list->data[list->choice];
1224c8945a0SNathan Whitehorn return 0;
1234c8945a0SNathan Whitehorn }
1244c8945a0SNathan Whitehorn
1254c8945a0SNathan Whitehorn static void
free_list(LIST * list,int reinit)1264c8945a0SNathan Whitehorn free_list(LIST * list, int reinit)
1274c8945a0SNathan Whitehorn {
128*a96ef450SBaptiste Daroussin if (list->data != 0) {
1294c8945a0SNathan Whitehorn int n;
1304c8945a0SNathan Whitehorn
1314c8945a0SNathan Whitehorn for (n = 0; list->data[n] != 0; n++)
1324c8945a0SNathan Whitehorn free(list->data[n]);
1334c8945a0SNathan Whitehorn free(list->data);
1344c8945a0SNathan Whitehorn list->data = 0;
1354c8945a0SNathan Whitehorn }
1364c8945a0SNathan Whitehorn if (reinit)
1374c8945a0SNathan Whitehorn init_list(list, list->par, list->win, list->mousex);
1384c8945a0SNathan Whitehorn }
1394c8945a0SNathan Whitehorn
1404c8945a0SNathan Whitehorn static void
add_to_list(LIST * list,char * text)1414c8945a0SNathan Whitehorn add_to_list(LIST * list, char *text)
1424c8945a0SNathan Whitehorn {
1434c8945a0SNathan Whitehorn unsigned need;
1444c8945a0SNathan Whitehorn
1454c8945a0SNathan Whitehorn need = (unsigned) (list->length + 1);
1464c8945a0SNathan Whitehorn if (need + 1 > list->allocd) {
1474c8945a0SNathan Whitehorn list->allocd = 2 * (need + 1);
1484c8945a0SNathan Whitehorn if (list->data == 0) {
1494c8945a0SNathan Whitehorn list->data = dlg_malloc(char *, list->allocd);
1504c8945a0SNathan Whitehorn } else {
1514c8945a0SNathan Whitehorn list->data = dlg_realloc(char *, list->allocd, list->data);
1524c8945a0SNathan Whitehorn }
1534c8945a0SNathan Whitehorn assert_ptr(list->data, "add_to_list");
1544c8945a0SNathan Whitehorn }
1554c8945a0SNathan Whitehorn list->data[list->length++] = dlg_strclone(text);
1564c8945a0SNathan Whitehorn list->data[list->length] = 0;
1574c8945a0SNathan Whitehorn }
1584c8945a0SNathan Whitehorn
1594c8945a0SNathan Whitehorn static void
keep_visible(LIST * list)1604c8945a0SNathan Whitehorn keep_visible(LIST * list)
1614c8945a0SNathan Whitehorn {
1624c8945a0SNathan Whitehorn int high = getmaxy(list->win);
1634c8945a0SNathan Whitehorn
1644c8945a0SNathan Whitehorn if (list->choice < list->offset) {
1654c8945a0SNathan Whitehorn list->offset = list->choice;
1664c8945a0SNathan Whitehorn }
1674c8945a0SNathan Whitehorn if (list->choice - list->offset >= high)
1684c8945a0SNathan Whitehorn list->offset = list->choice - high + 1;
1694c8945a0SNathan Whitehorn }
1704c8945a0SNathan Whitehorn
1714c8945a0SNathan Whitehorn #define Value(c) (int)((c) & 0xff)
1724c8945a0SNathan Whitehorn
1734c8945a0SNathan Whitehorn static int
find_choice(char * target,LIST * list)1744c8945a0SNathan Whitehorn find_choice(char *target, LIST * list)
1754c8945a0SNathan Whitehorn {
1764c8945a0SNathan Whitehorn int choice = list->choice;
1774c8945a0SNathan Whitehorn
1784c8945a0SNathan Whitehorn if (*target == 0) {
1794c8945a0SNathan Whitehorn list->choice = 0;
1804c8945a0SNathan Whitehorn } else {
181*a96ef450SBaptiste Daroussin int n;
182*a96ef450SBaptiste Daroussin int len_1, cmp_1;
183*a96ef450SBaptiste Daroussin
1844c8945a0SNathan Whitehorn /* find the match with the longest length. If more than one has the
1854c8945a0SNathan Whitehorn * same length, choose the one with the closest match of the final
1864c8945a0SNathan Whitehorn * character.
1874c8945a0SNathan Whitehorn */
1884c8945a0SNathan Whitehorn len_1 = 0;
1894c8945a0SNathan Whitehorn cmp_1 = 256;
1904c8945a0SNathan Whitehorn for (n = 0; n < list->length; n++) {
1914c8945a0SNathan Whitehorn char *a = target;
1924c8945a0SNathan Whitehorn char *b = list->data[n];
193*a96ef450SBaptiste Daroussin int len_2, cmp_2;
1944c8945a0SNathan Whitehorn
1954c8945a0SNathan Whitehorn len_2 = 0;
1964c8945a0SNathan Whitehorn while ((*a != 0) && (*b != 0) && (*a == *b)) {
1974c8945a0SNathan Whitehorn a++;
1984c8945a0SNathan Whitehorn b++;
1994c8945a0SNathan Whitehorn len_2++;
2004c8945a0SNathan Whitehorn }
2014c8945a0SNathan Whitehorn cmp_2 = Value(*a) - Value(*b);
2024c8945a0SNathan Whitehorn if (cmp_2 < 0)
2034c8945a0SNathan Whitehorn cmp_2 = -cmp_2;
2044c8945a0SNathan Whitehorn if ((len_2 > len_1)
2054c8945a0SNathan Whitehorn || (len_1 == len_2 && cmp_2 < cmp_1)) {
2064c8945a0SNathan Whitehorn len_1 = len_2;
2074c8945a0SNathan Whitehorn cmp_1 = cmp_2;
2084c8945a0SNathan Whitehorn list->choice = n;
2094c8945a0SNathan Whitehorn }
2104c8945a0SNathan Whitehorn }
2114c8945a0SNathan Whitehorn }
2124c8945a0SNathan Whitehorn if (choice != list->choice) {
2134c8945a0SNathan Whitehorn keep_visible(list);
2144c8945a0SNathan Whitehorn }
2154c8945a0SNathan Whitehorn return (choice != list->choice);
2164c8945a0SNathan Whitehorn }
2174c8945a0SNathan Whitehorn
2184c8945a0SNathan Whitehorn static void
display_list(LIST * list)2194c8945a0SNathan Whitehorn display_list(LIST * list)
2204c8945a0SNathan Whitehorn {
221*a96ef450SBaptiste Daroussin if (list->win != 0) {
2224c8945a0SNathan Whitehorn int n;
2234c8945a0SNathan Whitehorn int x;
2244c8945a0SNathan Whitehorn int y;
2254c8945a0SNathan Whitehorn int top;
2264c8945a0SNathan Whitehorn int bottom;
2274c8945a0SNathan Whitehorn
2284c8945a0SNathan Whitehorn dlg_attr_clear(list->win, getmaxy(list->win), getmaxx(list->win), item_attr);
2294c8945a0SNathan Whitehorn for (n = list->offset; n < list->length && list->data[n]; n++) {
2304c8945a0SNathan Whitehorn y = n - list->offset;
2314c8945a0SNathan Whitehorn if (y >= getmaxy(list->win))
2324c8945a0SNathan Whitehorn break;
2334c8945a0SNathan Whitehorn (void) wmove(list->win, y, 0);
2344c8945a0SNathan Whitehorn if (n == list->choice)
235f4f33ea0SBaptiste Daroussin dlg_attrset(list->win, item_selected_attr);
2364c8945a0SNathan Whitehorn (void) waddstr(list->win, list->data[n]);
237f4f33ea0SBaptiste Daroussin dlg_attrset(list->win, item_attr);
2384c8945a0SNathan Whitehorn }
239f4f33ea0SBaptiste Daroussin dlg_attrset(list->win, item_attr);
2404c8945a0SNathan Whitehorn
2414c8945a0SNathan Whitehorn getparyx(list->win, y, x);
2424c8945a0SNathan Whitehorn
2434c8945a0SNathan Whitehorn top = y - 1;
2444c8945a0SNathan Whitehorn bottom = y + getmaxy(list->win);
2454c8945a0SNathan Whitehorn dlg_draw_scrollbar(list->par,
2467a1c0d96SNathan Whitehorn (long) list->offset,
2477a1c0d96SNathan Whitehorn (long) list->offset,
2487a1c0d96SNathan Whitehorn (long) (list->offset + getmaxy(list->win)),
2497a1c0d96SNathan Whitehorn (long) (list->length),
2504c8945a0SNathan Whitehorn x + 1,
2514c8945a0SNathan Whitehorn x + getmaxx(list->win),
2524c8945a0SNathan Whitehorn top,
2534c8945a0SNathan Whitehorn bottom,
2542a3e3873SBaptiste Daroussin menubox_border2_attr,
2554c8945a0SNathan Whitehorn menubox_border_attr);
2564c8945a0SNathan Whitehorn
2574c8945a0SNathan Whitehorn (void) wmove(list->win, list->choice - list->offset, 0);
2584c8945a0SNathan Whitehorn (void) wnoutrefresh(list->win);
2594c8945a0SNathan Whitehorn }
2604c8945a0SNathan Whitehorn }
2614c8945a0SNathan Whitehorn
2624c8945a0SNathan Whitehorn /* FIXME: see arrows.c
2634c8945a0SNathan Whitehorn * This workaround is used to allow two lists to have scroll-tabs at the same
2644c8945a0SNathan Whitehorn * time, by reassigning their return-values to be different. Just for
2654c8945a0SNathan Whitehorn * readability, we use the names of keys with similar connotations, though all
2664c8945a0SNathan Whitehorn * that is really required is that they're distinct, so we can put them in a
2674c8945a0SNathan Whitehorn * switch statement.
2684c8945a0SNathan Whitehorn */
269*a96ef450SBaptiste Daroussin #if USE_MOUSE
2704c8945a0SNathan Whitehorn static void
fix_arrows(LIST * list)2714c8945a0SNathan Whitehorn fix_arrows(LIST * list)
2724c8945a0SNathan Whitehorn {
273*a96ef450SBaptiste Daroussin if (list->win != 0) {
2744c8945a0SNathan Whitehorn int x;
2754c8945a0SNathan Whitehorn int y;
2764c8945a0SNathan Whitehorn int top;
2772a3e3873SBaptiste Daroussin int right;
2784c8945a0SNathan Whitehorn int bottom;
2794c8945a0SNathan Whitehorn
2804c8945a0SNathan Whitehorn getparyx(list->win, y, x);
2814c8945a0SNathan Whitehorn top = y - 1;
2822a3e3873SBaptiste Daroussin right = getmaxx(list->win);
2834c8945a0SNathan Whitehorn bottom = y + getmaxy(list->win);
2844c8945a0SNathan Whitehorn
2852a3e3873SBaptiste Daroussin mouse_mkbutton(top, x, right,
2864c8945a0SNathan Whitehorn ((list->mousex == MOUSE_D)
2874c8945a0SNathan Whitehorn ? KEY_PREVIOUS
2884c8945a0SNathan Whitehorn : KEY_PPAGE));
2892a3e3873SBaptiste Daroussin mouse_mkbutton(bottom, x, right,
2904c8945a0SNathan Whitehorn ((list->mousex == MOUSE_D)
2914c8945a0SNathan Whitehorn ? KEY_NEXT
2924c8945a0SNathan Whitehorn : KEY_NPAGE));
2934c8945a0SNathan Whitehorn }
2944c8945a0SNathan Whitehorn }
2954c8945a0SNathan Whitehorn
296*a96ef450SBaptiste Daroussin #else
297*a96ef450SBaptiste Daroussin #define fix_arrows(list) /* nothing */
298*a96ef450SBaptiste Daroussin #endif
299*a96ef450SBaptiste Daroussin
300f4f33ea0SBaptiste Daroussin static bool
show_list(char * target,LIST * list,bool keep)301f4f33ea0SBaptiste Daroussin show_list(char *target, LIST * list, bool keep)
3024c8945a0SNathan Whitehorn {
303f4f33ea0SBaptiste Daroussin bool changed = keep || find_choice(target, list);
3044c8945a0SNathan Whitehorn display_list(list);
3054c8945a0SNathan Whitehorn return changed;
3064c8945a0SNathan Whitehorn }
3074c8945a0SNathan Whitehorn
3084c8945a0SNathan Whitehorn /*
3094c8945a0SNathan Whitehorn * Highlight the closest match to 'target' in the given list, setting offset
3104c8945a0SNathan Whitehorn * to match.
3114c8945a0SNathan Whitehorn */
312f4f33ea0SBaptiste Daroussin static bool
show_both_lists(char * input,LIST * d_list,LIST * f_list,bool keep)313f4f33ea0SBaptiste Daroussin show_both_lists(char *input, LIST * d_list, LIST * f_list, bool keep)
3144c8945a0SNathan Whitehorn {
3154c8945a0SNathan Whitehorn char *leaf = leaf_of(input);
3164c8945a0SNathan Whitehorn
317f4f33ea0SBaptiste Daroussin return show_list(leaf, d_list, keep) || show_list(leaf, f_list, keep);
3184c8945a0SNathan Whitehorn }
3194c8945a0SNathan Whitehorn
3204c8945a0SNathan Whitehorn /*
3214c8945a0SNathan Whitehorn * Move up/down in the given list
3224c8945a0SNathan Whitehorn */
3234c8945a0SNathan Whitehorn static bool
change_list(int choice,LIST * list)3244c8945a0SNathan Whitehorn change_list(int choice, LIST * list)
3254c8945a0SNathan Whitehorn {
3264c8945a0SNathan Whitehorn if (data_of(list) != 0) {
3274c8945a0SNathan Whitehorn int last = list->length - 1;
3284c8945a0SNathan Whitehorn
3294c8945a0SNathan Whitehorn choice += list->choice;
3304c8945a0SNathan Whitehorn if (choice < 0)
3314c8945a0SNathan Whitehorn choice = 0;
3324c8945a0SNathan Whitehorn if (choice > last)
3334c8945a0SNathan Whitehorn choice = last;
3344c8945a0SNathan Whitehorn list->choice = choice;
3354c8945a0SNathan Whitehorn keep_visible(list);
3364c8945a0SNathan Whitehorn display_list(list);
3374c8945a0SNathan Whitehorn return TRUE;
3384c8945a0SNathan Whitehorn }
3394c8945a0SNathan Whitehorn return FALSE;
3404c8945a0SNathan Whitehorn }
3414c8945a0SNathan Whitehorn
3424c8945a0SNathan Whitehorn static void
scroll_list(int direction,LIST * list)3434c8945a0SNathan Whitehorn scroll_list(int direction, LIST * list)
3444c8945a0SNathan Whitehorn {
3454c8945a0SNathan Whitehorn if (data_of(list) != 0) {
3464c8945a0SNathan Whitehorn int length = getmaxy(list->win);
3474c8945a0SNathan Whitehorn if (change_list(direction * length, list))
3484c8945a0SNathan Whitehorn return;
3494c8945a0SNathan Whitehorn }
3504c8945a0SNathan Whitehorn beep();
3514c8945a0SNathan Whitehorn }
3524c8945a0SNathan Whitehorn
3534c8945a0SNathan Whitehorn static int
compar(const void * a,const void * b)3544c8945a0SNathan Whitehorn compar(const void *a, const void *b)
3554c8945a0SNathan Whitehorn {
3564c8945a0SNathan Whitehorn return strcmp(*(const char *const *) a, *(const char *const *) b);
3574c8945a0SNathan Whitehorn }
3584c8945a0SNathan Whitehorn
3594c8945a0SNathan Whitehorn static void
match(char * name,LIST * d_list,LIST * f_list,MATCH * match_list)3604c8945a0SNathan Whitehorn match(char *name, LIST * d_list, LIST * f_list, MATCH * match_list)
3614c8945a0SNathan Whitehorn {
3624c8945a0SNathan Whitehorn char *test = leaf_of(name);
3634c8945a0SNathan Whitehorn size_t test_len = strlen(test);
3644c8945a0SNathan Whitehorn char **matches = dlg_malloc(char *, (size_t) (d_list->length + f_list->length));
3654c8945a0SNathan Whitehorn size_t data_len = 0;
366*a96ef450SBaptiste Daroussin
367*a96ef450SBaptiste Daroussin if (matches != 0) {
3684c8945a0SNathan Whitehorn int i;
369*a96ef450SBaptiste Daroussin char **new_ptr;
370*a96ef450SBaptiste Daroussin
3714c8945a0SNathan Whitehorn for (i = 2; i < d_list->length; i++) {
3724c8945a0SNathan Whitehorn if (strncmp(test, d_list->data[i], test_len) == 0) {
3734c8945a0SNathan Whitehorn matches[data_len++] = d_list->data[i];
3744c8945a0SNathan Whitehorn }
3754c8945a0SNathan Whitehorn }
3764c8945a0SNathan Whitehorn for (i = 0; i < f_list->length; i++) {
3774c8945a0SNathan Whitehorn if (strncmp(test, f_list->data[i], test_len) == 0) {
3784c8945a0SNathan Whitehorn matches[data_len++] = f_list->data[i];
3794c8945a0SNathan Whitehorn }
3804c8945a0SNathan Whitehorn }
381*a96ef450SBaptiste Daroussin if ((new_ptr = dlg_realloc(char *, data_len + 1, matches)) != 0) {
382*a96ef450SBaptiste Daroussin matches = new_ptr;
383*a96ef450SBaptiste Daroussin } else {
384*a96ef450SBaptiste Daroussin free(matches);
385*a96ef450SBaptiste Daroussin matches = 0;
386*a96ef450SBaptiste Daroussin data_len = 0;
387*a96ef450SBaptiste Daroussin }
388*a96ef450SBaptiste Daroussin }
3894c8945a0SNathan Whitehorn match_list->data = matches;
3904c8945a0SNathan Whitehorn match_list->length = (int) data_len;
3914c8945a0SNathan Whitehorn }
3924c8945a0SNathan Whitehorn
3934c8945a0SNathan Whitehorn static void
free_match(MATCH * match_list)3944c8945a0SNathan Whitehorn free_match(MATCH * match_list)
3954c8945a0SNathan Whitehorn {
3964c8945a0SNathan Whitehorn free(match_list->data);
3974c8945a0SNathan Whitehorn match_list->length = 0;
3984c8945a0SNathan Whitehorn }
3994c8945a0SNathan Whitehorn
4004c8945a0SNathan Whitehorn static int
complete(char * name,LIST * d_list,LIST * f_list,char ** buff_ptr)4014c8945a0SNathan Whitehorn complete(char *name, LIST * d_list, LIST * f_list, char **buff_ptr)
4024c8945a0SNathan Whitehorn {
4034c8945a0SNathan Whitehorn MATCH match_list;
4044c8945a0SNathan Whitehorn char *test;
4054c8945a0SNathan Whitehorn size_t test_len;
4064c8945a0SNathan Whitehorn size_t i;
4074c8945a0SNathan Whitehorn char *buff;
4084c8945a0SNathan Whitehorn
4094c8945a0SNathan Whitehorn match(name, d_list, f_list, &match_list);
4104c8945a0SNathan Whitehorn if (match_list.length == 0) {
411*a96ef450SBaptiste Daroussin free(match_list.data);
4124c8945a0SNathan Whitehorn *buff_ptr = NULL;
4134c8945a0SNathan Whitehorn return 0;
4144c8945a0SNathan Whitehorn }
4154c8945a0SNathan Whitehorn
4164c8945a0SNathan Whitehorn test = match_list.data[0];
4174c8945a0SNathan Whitehorn test_len = strlen(test);
4184c8945a0SNathan Whitehorn buff = dlg_malloc(char, test_len + 2);
4194c8945a0SNathan Whitehorn if (match_list.length == 1) {
4204c8945a0SNathan Whitehorn strcpy(buff, test);
4214c8945a0SNathan Whitehorn i = test_len;
4224c8945a0SNathan Whitehorn if (test == data_of(d_list)) {
4234c8945a0SNathan Whitehorn buff[test_len] = '/';
4244c8945a0SNathan Whitehorn i++;
4254c8945a0SNathan Whitehorn }
4264c8945a0SNathan Whitehorn } else {
427*a96ef450SBaptiste Daroussin int j;
428*a96ef450SBaptiste Daroussin
4294c8945a0SNathan Whitehorn for (i = 0; i < test_len; i++) {
4304c8945a0SNathan Whitehorn char test_char = test[i];
4314c8945a0SNathan Whitehorn if (test_char == '\0')
4324c8945a0SNathan Whitehorn break;
4334c8945a0SNathan Whitehorn for (j = 0; j < match_list.length; j++) {
4344c8945a0SNathan Whitehorn if (match_list.data[j][i] != test_char) {
4354c8945a0SNathan Whitehorn break;
4364c8945a0SNathan Whitehorn }
4374c8945a0SNathan Whitehorn }
4384c8945a0SNathan Whitehorn if (j == match_list.length) {
4394c8945a0SNathan Whitehorn (buff)[i] = test_char;
4404c8945a0SNathan Whitehorn } else
4414c8945a0SNathan Whitehorn break;
4424c8945a0SNathan Whitehorn }
4434c8945a0SNathan Whitehorn buff = dlg_realloc(char, i + 1, buff);
4444c8945a0SNathan Whitehorn }
4454c8945a0SNathan Whitehorn free_match(&match_list);
4464c8945a0SNathan Whitehorn buff[i] = '\0';
4474c8945a0SNathan Whitehorn *buff_ptr = buff;
4484c8945a0SNathan Whitehorn return (i != 0);
4494c8945a0SNathan Whitehorn }
4504c8945a0SNathan Whitehorn
4514c8945a0SNathan Whitehorn static bool
fill_lists(char * current,char * input,LIST * d_list,LIST * f_list,bool keep)452f4f33ea0SBaptiste Daroussin fill_lists(char *current, char *input, LIST * d_list, LIST * f_list, bool keep)
4534c8945a0SNathan Whitehorn {
4542a3e3873SBaptiste Daroussin bool result = TRUE;
4552a3e3873SBaptiste Daroussin bool rescan = FALSE;
4564c8945a0SNathan Whitehorn struct stat sb;
4574c8945a0SNathan Whitehorn int n;
4584c8945a0SNathan Whitehorn char path[MAX_LEN + 1];
4594c8945a0SNathan Whitehorn
4604c8945a0SNathan Whitehorn /* check if we've updated the lists */
4614c8945a0SNathan Whitehorn for (n = 0; current[n] && input[n]; n++) {
4624c8945a0SNathan Whitehorn if (current[n] != input[n])
4634c8945a0SNathan Whitehorn break;
4644c8945a0SNathan Whitehorn }
4652a3e3873SBaptiste Daroussin
4662a3e3873SBaptiste Daroussin if (current[n] == input[n]) {
4672a3e3873SBaptiste Daroussin result = FALSE;
4682a3e3873SBaptiste Daroussin rescan = (n == 0 && d_list->length == 0);
4692a3e3873SBaptiste Daroussin } else if (strchr(current + n, '/') == 0
4704c8945a0SNathan Whitehorn && strchr(input + n, '/') == 0) {
4712a3e3873SBaptiste Daroussin result = show_both_lists(input, d_list, f_list, keep);
4722a3e3873SBaptiste Daroussin } else {
4732a3e3873SBaptiste Daroussin rescan = TRUE;
4744c8945a0SNathan Whitehorn }
4754c8945a0SNathan Whitehorn
4762a3e3873SBaptiste Daroussin if (rescan) {
477*a96ef450SBaptiste Daroussin DIR *dp;
4782a3e3873SBaptiste Daroussin size_t have = strlen(input);
479*a96ef450SBaptiste Daroussin char *leaf;
4802a3e3873SBaptiste Daroussin
4812a3e3873SBaptiste Daroussin if (have > MAX_LEN)
4822a3e3873SBaptiste Daroussin have = MAX_LEN;
4832a3e3873SBaptiste Daroussin memcpy(current, input, have);
4842a3e3873SBaptiste Daroussin current[have] = '\0';
4854c8945a0SNathan Whitehorn
4864c8945a0SNathan Whitehorn /* refill the lists */
4874c8945a0SNathan Whitehorn free_list(d_list, TRUE);
4884c8945a0SNathan Whitehorn free_list(f_list, TRUE);
4892a3e3873SBaptiste Daroussin memcpy(path, current, have);
4902a3e3873SBaptiste Daroussin path[have] = '\0';
4914c8945a0SNathan Whitehorn if ((leaf = strrchr(path, '/')) != 0) {
4924c8945a0SNathan Whitehorn *++leaf = 0;
4934c8945a0SNathan Whitehorn } else {
4944c8945a0SNathan Whitehorn strcpy(path, "./");
4954c8945a0SNathan Whitehorn leaf = path + strlen(path);
4964c8945a0SNathan Whitehorn }
497f4f33ea0SBaptiste Daroussin DLG_TRACE(("opendir '%s'\n", path));
4984c8945a0SNathan Whitehorn if ((dp = opendir(path)) != 0) {
499*a96ef450SBaptiste Daroussin DIRENT *de;
500*a96ef450SBaptiste Daroussin
5014c8945a0SNathan Whitehorn while ((de = readdir(dp)) != 0) {
502f4f33ea0SBaptiste Daroussin size_t len = NAMLEN(de);
503f4f33ea0SBaptiste Daroussin if (len == 0 || (len + have + 2) >= MAX_LEN)
504f4f33ea0SBaptiste Daroussin continue;
505f4f33ea0SBaptiste Daroussin memcpy(leaf, de->d_name, len);
506f4f33ea0SBaptiste Daroussin leaf[len] = '\0';
5074c8945a0SNathan Whitehorn if (stat(path, &sb) == 0) {
5084c8945a0SNathan Whitehorn if ((sb.st_mode & S_IFMT) == S_IFDIR)
5094c8945a0SNathan Whitehorn add_to_list(d_list, leaf);
5104c8945a0SNathan Whitehorn else if (f_list->win)
5114c8945a0SNathan Whitehorn add_to_list(f_list, leaf);
5124c8945a0SNathan Whitehorn }
5134c8945a0SNathan Whitehorn }
5144c8945a0SNathan Whitehorn (void) closedir(dp);
5154c8945a0SNathan Whitehorn /* sort the lists */
5162a3e3873SBaptiste Daroussin if (d_list->data != 0 && d_list->length > 1) {
5174c8945a0SNathan Whitehorn qsort(d_list->data,
5184c8945a0SNathan Whitehorn (size_t) d_list->length,
5194c8945a0SNathan Whitehorn sizeof(d_list->data[0]),
5204c8945a0SNathan Whitehorn compar);
5212a3e3873SBaptiste Daroussin }
5222a3e3873SBaptiste Daroussin if (f_list->data != 0 && f_list->length > 1) {
5234c8945a0SNathan Whitehorn qsort(f_list->data,
5244c8945a0SNathan Whitehorn (size_t) f_list->length,
5254c8945a0SNathan Whitehorn sizeof(f_list->data[0]),
5264c8945a0SNathan Whitehorn compar);
5274c8945a0SNathan Whitehorn }
5282a3e3873SBaptiste Daroussin }
5294c8945a0SNathan Whitehorn
5304c8945a0SNathan Whitehorn (void) show_both_lists(input, d_list, f_list, FALSE);
5314c8945a0SNathan Whitehorn d_list->offset = d_list->choice;
5324c8945a0SNathan Whitehorn f_list->offset = f_list->choice;
5332a3e3873SBaptiste Daroussin result = TRUE;
5342a3e3873SBaptiste Daroussin }
5352a3e3873SBaptiste Daroussin return result;
5364c8945a0SNathan Whitehorn }
5374c8945a0SNathan Whitehorn
5384c8945a0SNathan Whitehorn static bool
usable_state(int state,LIST * dirs,LIST * files)5394c8945a0SNathan Whitehorn usable_state(int state, LIST * dirs, LIST * files)
5404c8945a0SNathan Whitehorn {
5414c8945a0SNathan Whitehorn bool result;
5424c8945a0SNathan Whitehorn
5434c8945a0SNathan Whitehorn switch (state) {
5444c8945a0SNathan Whitehorn case sDIRS:
5454c8945a0SNathan Whitehorn result = (dirs->win != 0) && (data_of(dirs) != 0);
5464c8945a0SNathan Whitehorn break;
5474c8945a0SNathan Whitehorn case sFILES:
5484c8945a0SNathan Whitehorn result = (files->win != 0) && (data_of(files) != 0);
5494c8945a0SNathan Whitehorn break;
5504c8945a0SNathan Whitehorn default:
5514c8945a0SNathan Whitehorn result = TRUE;
5524c8945a0SNathan Whitehorn break;
5534c8945a0SNathan Whitehorn }
5544c8945a0SNathan Whitehorn return result;
5554c8945a0SNathan Whitehorn }
5564c8945a0SNathan Whitehorn
5574c8945a0SNathan Whitehorn #define which_list() ((state == sFILES) \
5584c8945a0SNathan Whitehorn ? &f_list \
5594c8945a0SNathan Whitehorn : ((state == sDIRS) \
5604c8945a0SNathan Whitehorn ? &d_list \
5614c8945a0SNathan Whitehorn : 0))
5624c8945a0SNathan Whitehorn #define NAVIGATE_BINDINGS \
5634c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_FIELD_NEXT, KEY_RIGHT ), \
5644c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ), \
5654c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ), \
5664c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_DOWN ), \
5674c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_NEXT, CHR_NEXT ), \
5684c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_NEXT, KEY_NEXT ), \
5694c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_PREV, CHR_PREVIOUS ), \
5704c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_ITEM_PREV, KEY_UP ), \
5714c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_NEXT, KEY_NPAGE ), \
5724c8945a0SNathan Whitehorn DLG_KEYS_DATA( DLGK_PAGE_PREV, KEY_PPAGE )
5734c8945a0SNathan Whitehorn
5744c8945a0SNathan Whitehorn /*
5754c8945a0SNathan Whitehorn * Display a dialog box for entering a filename
5764c8945a0SNathan Whitehorn */
5774c8945a0SNathan Whitehorn static int
dlg_fselect(const char * title,const char * path,int height,int width,int dselect)5787a1c0d96SNathan Whitehorn dlg_fselect(const char *title, const char *path, int height, int width, int dselect)
5794c8945a0SNathan Whitehorn {
5804c8945a0SNathan Whitehorn /* *INDENT-OFF* */
5814c8945a0SNathan Whitehorn static DLG_KEYS_BINDING binding[] = {
582682c9e0fSNathan Whitehorn HELPKEY_BINDINGS,
5834c8945a0SNathan Whitehorn ENTERKEY_BINDINGS,
5844c8945a0SNathan Whitehorn NAVIGATE_BINDINGS,
585f4f33ea0SBaptiste Daroussin TOGGLEKEY_BINDINGS,
5864c8945a0SNathan Whitehorn END_KEYS_BINDING
5874c8945a0SNathan Whitehorn };
5884c8945a0SNathan Whitehorn static DLG_KEYS_BINDING binding2[] = {
5894c8945a0SNathan Whitehorn INPUTSTR_BINDINGS,
590682c9e0fSNathan Whitehorn HELPKEY_BINDINGS,
5914c8945a0SNathan Whitehorn ENTERKEY_BINDINGS,
5924c8945a0SNathan Whitehorn NAVIGATE_BINDINGS,
593f4f33ea0SBaptiste Daroussin TOGGLEKEY_BINDINGS,
5944c8945a0SNathan Whitehorn END_KEYS_BINDING
5954c8945a0SNathan Whitehorn };
5964c8945a0SNathan Whitehorn /* *INDENT-ON* */
5974c8945a0SNathan Whitehorn
5984c8945a0SNathan Whitehorn #ifdef KEY_RESIZE
5994c8945a0SNathan Whitehorn int old_height = height;
6004c8945a0SNathan Whitehorn int old_width = width;
6014c8945a0SNathan Whitehorn bool resized = FALSE;
6024c8945a0SNathan Whitehorn #endif
6034c8945a0SNathan Whitehorn int tbox_y, tbox_x, tbox_width, tbox_height;
6044c8945a0SNathan Whitehorn int dbox_y, dbox_x, dbox_width, dbox_height;
6054c8945a0SNathan Whitehorn int fbox_y, fbox_x, fbox_width, fbox_height;
6064c8945a0SNathan Whitehorn int show_buttons = TRUE;
6074c8945a0SNathan Whitehorn int offset = 0;
6084c8945a0SNathan Whitehorn int key = 0;
6094c8945a0SNathan Whitehorn int fkey = FALSE;
6104c8945a0SNathan Whitehorn int code;
6114c8945a0SNathan Whitehorn int result = DLG_EXIT_UNKNOWN;
6122a3e3873SBaptiste Daroussin int state = dialog_vars.default_button >= 0 ? dlg_default_button() : sTEXT;
6132a3e3873SBaptiste Daroussin int button;
614f4f33ea0SBaptiste Daroussin bool first = (state == sTEXT);
615f4f33ea0SBaptiste Daroussin bool first_trace = TRUE;
6164c8945a0SNathan Whitehorn char *input;
6174c8945a0SNathan Whitehorn char *completed;
6184c8945a0SNathan Whitehorn char current[MAX_LEN + 1];
6194c8945a0SNathan Whitehorn WINDOW *dialog = 0;
6204c8945a0SNathan Whitehorn WINDOW *w_text = 0;
6214c8945a0SNathan Whitehorn WINDOW *w_work = 0;
6224c8945a0SNathan Whitehorn const char **buttons = dlg_ok_labels();
6237a1c0d96SNathan Whitehorn const char *d_label = _("Directories");
6247a1c0d96SNathan Whitehorn const char *f_label = _("Files");
6252a3e3873SBaptiste Daroussin char *partial = 0;
6264c8945a0SNathan Whitehorn int min_wide = MIN_WIDE;
6274c8945a0SNathan Whitehorn int min_items = height ? 0 : 4;
6284c8945a0SNathan Whitehorn LIST d_list, f_list;
6294c8945a0SNathan Whitehorn
630f4f33ea0SBaptiste Daroussin DLG_TRACE(("# %s args:\n", dselect ? "dselect" : "fselect"));
631f4f33ea0SBaptiste Daroussin DLG_TRACE2S("title", title);
632f4f33ea0SBaptiste Daroussin DLG_TRACE2S("path", path);
633f4f33ea0SBaptiste Daroussin DLG_TRACE2N("height", height);
634f4f33ea0SBaptiste Daroussin DLG_TRACE2N("width", width);
635f4f33ea0SBaptiste Daroussin
6364c8945a0SNathan Whitehorn dlg_does_output();
6374c8945a0SNathan Whitehorn
6384c8945a0SNathan Whitehorn /* Set up the initial value */
6394c8945a0SNathan Whitehorn input = dlg_set_result(path);
6404c8945a0SNathan Whitehorn offset = (int) strlen(input);
6414c8945a0SNathan Whitehorn *current = 0;
6424c8945a0SNathan Whitehorn
6434c8945a0SNathan Whitehorn dlg_button_layout(buttons, &min_wide);
6444c8945a0SNathan Whitehorn
6454c8945a0SNathan Whitehorn #ifdef KEY_RESIZE
6464c8945a0SNathan Whitehorn retry:
6474c8945a0SNathan Whitehorn #endif
648*a96ef450SBaptiste Daroussin dlg_auto_size(title, "", &height, &width, MIN_HIGH + min_items, min_wide);
649*a96ef450SBaptiste Daroussin
6504c8945a0SNathan Whitehorn dlg_print_size(height, width);
6514c8945a0SNathan Whitehorn dlg_ctl_size(height, width);
6524c8945a0SNathan Whitehorn
6534c8945a0SNathan Whitehorn dialog = dlg_new_window(height, width,
6544c8945a0SNathan Whitehorn dlg_box_y_ordinate(height),
6554c8945a0SNathan Whitehorn dlg_box_x_ordinate(width));
6564c8945a0SNathan Whitehorn dlg_register_window(dialog, "fselect", binding);
6574c8945a0SNathan Whitehorn dlg_register_buttons(dialog, "fselect", buttons);
6584c8945a0SNathan Whitehorn
6594c8945a0SNathan Whitehorn dlg_mouse_setbase(0, 0);
6604c8945a0SNathan Whitehorn
6612a3e3873SBaptiste Daroussin dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr);
6622a3e3873SBaptiste Daroussin dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr);
6634c8945a0SNathan Whitehorn dlg_draw_title(dialog, title);
6644c8945a0SNathan Whitehorn
665f4f33ea0SBaptiste Daroussin dlg_attrset(dialog, dialog_attr);
6664c8945a0SNathan Whitehorn
6674c8945a0SNathan Whitehorn /* Draw the input field box */
6684c8945a0SNathan Whitehorn tbox_height = 1;
6694c8945a0SNathan Whitehorn tbox_width = width - (4 * MARGIN + 2);
6704c8945a0SNathan Whitehorn tbox_y = height - (BTN_HIGH * 2) + MARGIN;
6714c8945a0SNathan Whitehorn tbox_x = (width - tbox_width) / 2;
6724c8945a0SNathan Whitehorn
673*a96ef450SBaptiste Daroussin w_text = dlg_der_window(dialog, tbox_height, tbox_width, tbox_y, tbox_x);
6742a3e3873SBaptiste Daroussin if (w_text == 0) {
6752a3e3873SBaptiste Daroussin result = DLG_EXIT_ERROR;
6762a3e3873SBaptiste Daroussin goto finish;
6772a3e3873SBaptiste Daroussin }
6784c8945a0SNathan Whitehorn
6794c8945a0SNathan Whitehorn dlg_draw_box(dialog, tbox_y - MARGIN, tbox_x - MARGIN,
6804c8945a0SNathan Whitehorn (2 * MARGIN + 1), tbox_width + (MARGIN + EXT_WIDE),
6812a3e3873SBaptiste Daroussin menubox_border_attr, menubox_border2_attr);
6824c8945a0SNathan Whitehorn dlg_mouse_mkbigregion(getbegy(dialog) + tbox_y - MARGIN,
6834c8945a0SNathan Whitehorn getbegx(dialog) + tbox_x - MARGIN,
6844c8945a0SNathan Whitehorn 1 + (2 * MARGIN),
6854c8945a0SNathan Whitehorn tbox_width + (MARGIN + EXT_WIDE),
6864c8945a0SNathan Whitehorn MOUSE_T, 1, 1, 3 /* doesn't matter */ );
6874c8945a0SNathan Whitehorn
6882a3e3873SBaptiste Daroussin dlg_register_window(w_text, "fselect2", binding2);
6894c8945a0SNathan Whitehorn
6904c8945a0SNathan Whitehorn /* Draw the directory listing box */
6914c8945a0SNathan Whitehorn if (dselect)
6924c8945a0SNathan Whitehorn dbox_width = (width - (6 * MARGIN));
6934c8945a0SNathan Whitehorn else
6944c8945a0SNathan Whitehorn dbox_width = (width - (6 * MARGIN + 2 * EXT_WIDE)) / 2;
6954c8945a0SNathan Whitehorn dbox_height = height - MIN_HIGH;
6964c8945a0SNathan Whitehorn dbox_y = (2 * MARGIN + 1);
6974c8945a0SNathan Whitehorn dbox_x = tbox_x;
6984c8945a0SNathan Whitehorn
699*a96ef450SBaptiste Daroussin w_work = dlg_der_window(dialog, dbox_height, dbox_width, dbox_y, dbox_x);
7002a3e3873SBaptiste Daroussin if (w_work == 0) {
7012a3e3873SBaptiste Daroussin result = DLG_EXIT_ERROR;
7022a3e3873SBaptiste Daroussin goto finish;
7032a3e3873SBaptiste Daroussin }
7044c8945a0SNathan Whitehorn
7052a3e3873SBaptiste Daroussin (void) mvwaddstr(dialog, dbox_y - (MARGIN + 1), dbox_x - MARGIN, d_label);
7064c8945a0SNathan Whitehorn dlg_draw_box(dialog,
7074c8945a0SNathan Whitehorn dbox_y - MARGIN, dbox_x - MARGIN,
7084c8945a0SNathan Whitehorn dbox_height + (MARGIN + 1), dbox_width + (MARGIN + 1),
7092a3e3873SBaptiste Daroussin menubox_border_attr, menubox_border2_attr);
7104c8945a0SNathan Whitehorn init_list(&d_list, dialog, w_work, MOUSE_D);
7114c8945a0SNathan Whitehorn
7124c8945a0SNathan Whitehorn if (!dselect) {
7134c8945a0SNathan Whitehorn /* Draw the filename listing box */
7144c8945a0SNathan Whitehorn fbox_height = dbox_height;
7154c8945a0SNathan Whitehorn fbox_width = dbox_width;
7164c8945a0SNathan Whitehorn fbox_y = dbox_y;
7174c8945a0SNathan Whitehorn fbox_x = tbox_x + dbox_width + (2 * MARGIN);
7184c8945a0SNathan Whitehorn
719*a96ef450SBaptiste Daroussin w_work = dlg_der_window(dialog, fbox_height, fbox_width, fbox_y, fbox_x);
7202a3e3873SBaptiste Daroussin if (w_work == 0) {
7212a3e3873SBaptiste Daroussin result = DLG_EXIT_ERROR;
7222a3e3873SBaptiste Daroussin goto finish;
7232a3e3873SBaptiste Daroussin }
7244c8945a0SNathan Whitehorn
7252a3e3873SBaptiste Daroussin (void) mvwaddstr(dialog, fbox_y - (MARGIN + 1), fbox_x - MARGIN, f_label);
7264c8945a0SNathan Whitehorn dlg_draw_box(dialog,
7274c8945a0SNathan Whitehorn fbox_y - MARGIN, fbox_x - MARGIN,
7284c8945a0SNathan Whitehorn fbox_height + (MARGIN + 1), fbox_width + (MARGIN + 1),
7292a3e3873SBaptiste Daroussin menubox_border_attr, menubox_border2_attr);
7304c8945a0SNathan Whitehorn init_list(&f_list, dialog, w_work, MOUSE_F);
7314c8945a0SNathan Whitehorn } else {
7324c8945a0SNathan Whitehorn memset(&f_list, 0, sizeof(f_list));
7334c8945a0SNathan Whitehorn }
7344c8945a0SNathan Whitehorn
7354c8945a0SNathan Whitehorn while (result == DLG_EXIT_UNKNOWN) {
7364c8945a0SNathan Whitehorn
7374c8945a0SNathan Whitehorn if (fill_lists(current, input, &d_list, &f_list, state < sTEXT))
7384c8945a0SNathan Whitehorn show_buttons = TRUE;
7394c8945a0SNathan Whitehorn
7404c8945a0SNathan Whitehorn #ifdef KEY_RESIZE
7414c8945a0SNathan Whitehorn if (resized) {
7424c8945a0SNathan Whitehorn resized = FALSE;
7434c8945a0SNathan Whitehorn dlg_show_string(w_text, input, offset, inputbox_attr,
744f4f33ea0SBaptiste Daroussin 0, 0, tbox_width, FALSE, first);
7454c8945a0SNathan Whitehorn }
7464c8945a0SNathan Whitehorn #endif
7474c8945a0SNathan Whitehorn
7484c8945a0SNathan Whitehorn /*
7494c8945a0SNathan Whitehorn * The last field drawn determines where the cursor is shown:
7504c8945a0SNathan Whitehorn */
7514c8945a0SNathan Whitehorn if (show_buttons) {
7524c8945a0SNathan Whitehorn show_buttons = FALSE;
7534c8945a0SNathan Whitehorn button = (state < 0) ? 0 : state;
7544c8945a0SNathan Whitehorn dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width);
7554c8945a0SNathan Whitehorn }
7562a3e3873SBaptiste Daroussin
7572a3e3873SBaptiste Daroussin if (first_trace) {
7582a3e3873SBaptiste Daroussin first_trace = FALSE;
7592a3e3873SBaptiste Daroussin dlg_trace_win(dialog);
7602a3e3873SBaptiste Daroussin }
7612a3e3873SBaptiste Daroussin
7624c8945a0SNathan Whitehorn if (state < 0) {
7634c8945a0SNathan Whitehorn switch (state) {
7644c8945a0SNathan Whitehorn case sTEXT:
7654c8945a0SNathan Whitehorn dlg_set_focus(dialog, w_text);
7664c8945a0SNathan Whitehorn break;
7674c8945a0SNathan Whitehorn case sFILES:
7684c8945a0SNathan Whitehorn dlg_set_focus(dialog, f_list.win);
7694c8945a0SNathan Whitehorn break;
7704c8945a0SNathan Whitehorn case sDIRS:
7714c8945a0SNathan Whitehorn dlg_set_focus(dialog, d_list.win);
7724c8945a0SNathan Whitehorn break;
7734c8945a0SNathan Whitehorn }
7744c8945a0SNathan Whitehorn }
7754c8945a0SNathan Whitehorn
7764c8945a0SNathan Whitehorn if (first) {
7774c8945a0SNathan Whitehorn (void) wrefresh(dialog);
7784c8945a0SNathan Whitehorn } else {
7794c8945a0SNathan Whitehorn fix_arrows(&d_list);
7804c8945a0SNathan Whitehorn fix_arrows(&f_list);
7814c8945a0SNathan Whitehorn key = dlg_mouse_wgetch((state == sTEXT) ? w_text : dialog, &fkey);
782*a96ef450SBaptiste Daroussin if (dlg_result_key(key, fkey, &result)) {
783*a96ef450SBaptiste Daroussin if (!dlg_button_key(result, &button, &key, &fkey))
7844c8945a0SNathan Whitehorn break;
7854c8945a0SNathan Whitehorn }
786*a96ef450SBaptiste Daroussin }
7874c8945a0SNathan Whitehorn
788f4f33ea0SBaptiste Daroussin if (key == DLGK_TOGGLE) {
7894c8945a0SNathan Whitehorn key = DLGK_SELECT;
7904c8945a0SNathan Whitehorn fkey = TRUE;
7914c8945a0SNathan Whitehorn }
7924c8945a0SNathan Whitehorn
7934c8945a0SNathan Whitehorn if (fkey) {
7944c8945a0SNathan Whitehorn switch (key) {
7954c8945a0SNathan Whitehorn case DLGK_MOUSE(KEY_PREVIOUS):
7964c8945a0SNathan Whitehorn state = sDIRS;
7974c8945a0SNathan Whitehorn scroll_list(-1, which_list());
7984c8945a0SNathan Whitehorn continue;
7994c8945a0SNathan Whitehorn case DLGK_MOUSE(KEY_NEXT):
8004c8945a0SNathan Whitehorn state = sDIRS;
8014c8945a0SNathan Whitehorn scroll_list(1, which_list());
8024c8945a0SNathan Whitehorn continue;
8034c8945a0SNathan Whitehorn case DLGK_MOUSE(KEY_PPAGE):
8044c8945a0SNathan Whitehorn state = sFILES;
8054c8945a0SNathan Whitehorn scroll_list(-1, which_list());
8064c8945a0SNathan Whitehorn continue;
8074c8945a0SNathan Whitehorn case DLGK_MOUSE(KEY_NPAGE):
8084c8945a0SNathan Whitehorn state = sFILES;
8094c8945a0SNathan Whitehorn scroll_list(1, which_list());
8104c8945a0SNathan Whitehorn continue;
8114c8945a0SNathan Whitehorn case DLGK_PAGE_PREV:
8124c8945a0SNathan Whitehorn scroll_list(-1, which_list());
8134c8945a0SNathan Whitehorn continue;
8144c8945a0SNathan Whitehorn case DLGK_PAGE_NEXT:
8154c8945a0SNathan Whitehorn scroll_list(1, which_list());
8164c8945a0SNathan Whitehorn continue;
8174c8945a0SNathan Whitehorn case DLGK_ITEM_PREV:
8184c8945a0SNathan Whitehorn if (change_list(-1, which_list()))
8194c8945a0SNathan Whitehorn continue;
8204c8945a0SNathan Whitehorn /* FALLTHRU */
8214c8945a0SNathan Whitehorn case DLGK_FIELD_PREV:
8224c8945a0SNathan Whitehorn show_buttons = TRUE;
8234c8945a0SNathan Whitehorn do {
8244c8945a0SNathan Whitehorn state = dlg_prev_ok_buttonindex(state, sDIRS);
8254c8945a0SNathan Whitehorn } while (!usable_state(state, &d_list, &f_list));
8264c8945a0SNathan Whitehorn continue;
8274c8945a0SNathan Whitehorn case DLGK_ITEM_NEXT:
8284c8945a0SNathan Whitehorn if (change_list(1, which_list()))
8294c8945a0SNathan Whitehorn continue;
8304c8945a0SNathan Whitehorn /* FALLTHRU */
8314c8945a0SNathan Whitehorn case DLGK_FIELD_NEXT:
8324c8945a0SNathan Whitehorn show_buttons = TRUE;
8334c8945a0SNathan Whitehorn do {
8344c8945a0SNathan Whitehorn state = dlg_next_ok_buttonindex(state, sDIRS);
8354c8945a0SNathan Whitehorn } while (!usable_state(state, &d_list, &f_list));
8364c8945a0SNathan Whitehorn continue;
8374c8945a0SNathan Whitehorn case DLGK_SELECT:
8384c8945a0SNathan Whitehorn completed = 0;
8392a3e3873SBaptiste Daroussin if (partial != 0) {
8402a3e3873SBaptiste Daroussin free(partial);
8414c8945a0SNathan Whitehorn partial = 0;
8422a3e3873SBaptiste Daroussin }
8434c8945a0SNathan Whitehorn if (state == sFILES && !dselect) {
8444c8945a0SNathan Whitehorn completed = data_of(&f_list);
8454c8945a0SNathan Whitehorn } else if (state == sDIRS) {
8464c8945a0SNathan Whitehorn completed = data_of(&d_list);
8474c8945a0SNathan Whitehorn } else {
8484c8945a0SNathan Whitehorn if (complete(input, &d_list, &f_list, &partial)) {
8494c8945a0SNathan Whitehorn completed = partial;
8504c8945a0SNathan Whitehorn }
8514c8945a0SNathan Whitehorn }
8524c8945a0SNathan Whitehorn if (completed != 0) {
8534c8945a0SNathan Whitehorn state = sTEXT;
8544c8945a0SNathan Whitehorn show_buttons = TRUE;
8554c8945a0SNathan Whitehorn strcpy(leaf_of(input), completed);
8564c8945a0SNathan Whitehorn offset = (int) strlen(input);
8574c8945a0SNathan Whitehorn dlg_show_string(w_text, input, offset, inputbox_attr,
8584c8945a0SNathan Whitehorn 0, 0, tbox_width, 0, first);
8592a3e3873SBaptiste Daroussin if (partial != NULL) {
8604c8945a0SNathan Whitehorn free(partial);
8612a3e3873SBaptiste Daroussin partial = 0;
8622a3e3873SBaptiste Daroussin }
8634c8945a0SNathan Whitehorn continue;
8644c8945a0SNathan Whitehorn } else { /* if (state < sTEXT) */
8654c8945a0SNathan Whitehorn (void) beep();
8664c8945a0SNathan Whitehorn continue;
8674c8945a0SNathan Whitehorn }
8684c8945a0SNathan Whitehorn /* FALLTHRU */
8694c8945a0SNathan Whitehorn case DLGK_ENTER:
870682c9e0fSNathan Whitehorn result = (state > 0) ? dlg_enter_buttoncode(state) : DLG_EXIT_OK;
8714c8945a0SNathan Whitehorn continue;
872*a96ef450SBaptiste Daroussin case DLGK_LEAVE:
873*a96ef450SBaptiste Daroussin if (state >= 0)
874*a96ef450SBaptiste Daroussin result = dlg_ok_buttoncode(state);
875*a96ef450SBaptiste Daroussin break;
8764c8945a0SNathan Whitehorn #ifdef KEY_RESIZE
8774c8945a0SNathan Whitehorn case KEY_RESIZE:
878f4f33ea0SBaptiste Daroussin dlg_will_resize(dialog);
8794c8945a0SNathan Whitehorn /* reset data */
8804c8945a0SNathan Whitehorn height = old_height;
8814c8945a0SNathan Whitehorn width = old_width;
8824c8945a0SNathan Whitehorn show_buttons = TRUE;
8834c8945a0SNathan Whitehorn *current = 0;
8844c8945a0SNathan Whitehorn resized = TRUE;
8854c8945a0SNathan Whitehorn /* repaint */
886*a96ef450SBaptiste Daroussin free_list(&d_list, FALSE);
887*a96ef450SBaptiste Daroussin free_list(&f_list, FALSE);
888*a96ef450SBaptiste Daroussin _dlg_resize_cleanup(dialog);
8894c8945a0SNathan Whitehorn goto retry;
8904c8945a0SNathan Whitehorn #endif
8914c8945a0SNathan Whitehorn default:
8924c8945a0SNathan Whitehorn if (key >= DLGK_MOUSE(MOUSE_T)) {
8934c8945a0SNathan Whitehorn state = sTEXT;
8944c8945a0SNathan Whitehorn continue;
8954c8945a0SNathan Whitehorn } else if (key >= DLGK_MOUSE(MOUSE_F)) {
8964c8945a0SNathan Whitehorn if (f_list.win != 0) {
8974c8945a0SNathan Whitehorn state = sFILES;
8984c8945a0SNathan Whitehorn f_list.choice = (key - DLGK_MOUSE(MOUSE_F)) + f_list.offset;
8994c8945a0SNathan Whitehorn display_list(&f_list);
9004c8945a0SNathan Whitehorn }
9014c8945a0SNathan Whitehorn continue;
9024c8945a0SNathan Whitehorn } else if (key >= DLGK_MOUSE(MOUSE_D)) {
9034c8945a0SNathan Whitehorn if (d_list.win != 0) {
9044c8945a0SNathan Whitehorn state = sDIRS;
9054c8945a0SNathan Whitehorn d_list.choice = (key - DLGK_MOUSE(MOUSE_D)) + d_list.offset;
9064c8945a0SNathan Whitehorn display_list(&d_list);
9074c8945a0SNathan Whitehorn }
9084c8945a0SNathan Whitehorn continue;
9094c8945a0SNathan Whitehorn } else if (is_DLGK_MOUSE(key)
9104c8945a0SNathan Whitehorn && (code = dlg_ok_buttoncode(key - M_EVENT)) >= 0) {
9114c8945a0SNathan Whitehorn result = code;
9124c8945a0SNathan Whitehorn continue;
9134c8945a0SNathan Whitehorn }
9144c8945a0SNathan Whitehorn break;
9154c8945a0SNathan Whitehorn }
9164c8945a0SNathan Whitehorn }
9174c8945a0SNathan Whitehorn
9184c8945a0SNathan Whitehorn if (state < 0) { /* Input box selected if we're editing */
9194c8945a0SNathan Whitehorn int edit = dlg_edit_string(input, &offset, key, fkey, first);
9204c8945a0SNathan Whitehorn
9214c8945a0SNathan Whitehorn if (edit) {
9224c8945a0SNathan Whitehorn dlg_show_string(w_text, input, offset, inputbox_attr,
9234c8945a0SNathan Whitehorn 0, 0, tbox_width, 0, first);
9244c8945a0SNathan Whitehorn first = FALSE;
9254c8945a0SNathan Whitehorn state = sTEXT;
9264c8945a0SNathan Whitehorn }
927*a96ef450SBaptiste Daroussin } else if ((code = dlg_char_to_button(key, buttons)) >= 0) {
9284c8945a0SNathan Whitehorn result = dlg_ok_buttoncode(code);
9294c8945a0SNathan Whitehorn break;
9304c8945a0SNathan Whitehorn }
9314c8945a0SNathan Whitehorn }
932*a96ef450SBaptiste Daroussin AddLastKey();
9334c8945a0SNathan Whitehorn
9344c8945a0SNathan Whitehorn dlg_unregister_window(w_text);
9354c8945a0SNathan Whitehorn dlg_del_window(dialog);
9364c8945a0SNathan Whitehorn dlg_mouse_free_regions();
9374c8945a0SNathan Whitehorn free_list(&d_list, FALSE);
9384c8945a0SNathan Whitehorn free_list(&f_list, FALSE);
9392a3e3873SBaptiste Daroussin
9402a3e3873SBaptiste Daroussin finish:
9412a3e3873SBaptiste Daroussin if (partial != 0)
9422a3e3873SBaptiste Daroussin free(partial);
9434c8945a0SNathan Whitehorn return result;
9444c8945a0SNathan Whitehorn }
9454c8945a0SNathan Whitehorn
9464c8945a0SNathan Whitehorn /*
9474c8945a0SNathan Whitehorn * Display a dialog box for entering a filename
9484c8945a0SNathan Whitehorn */
9494c8945a0SNathan Whitehorn int
dialog_fselect(const char * title,const char * path,int height,int width)9504c8945a0SNathan Whitehorn dialog_fselect(const char *title, const char *path, int height, int width)
9514c8945a0SNathan Whitehorn {
9524c8945a0SNathan Whitehorn return dlg_fselect(title, path, height, width, FALSE);
9534c8945a0SNathan Whitehorn }
9544c8945a0SNathan Whitehorn
9554c8945a0SNathan Whitehorn /*
9564c8945a0SNathan Whitehorn * Display a dialog box for entering a directory
9574c8945a0SNathan Whitehorn */
9584c8945a0SNathan Whitehorn int
dialog_dselect(const char * title,const char * path,int height,int width)9594c8945a0SNathan Whitehorn dialog_dselect(const char *title, const char *path, int height, int width)
9604c8945a0SNathan Whitehorn {
9614c8945a0SNathan Whitehorn return dlg_fselect(title, path, height, width, TRUE);
9624c8945a0SNathan Whitehorn }
963