xref: /freebsd/contrib/dialog/dlg_keys.c (revision 2a3e3873a1e4cd958f2b0f85d3b10cfa40575d30)
14c8945a0SNathan Whitehorn /*
2*2a3e3873SBaptiste Daroussin  *  $Id: dlg_keys.c,v 1.34 2011/10/14 00:41:08 tom Exp $
34c8945a0SNathan Whitehorn  *
44c8945a0SNathan Whitehorn  *  dlg_keys.c -- runtime binding support for dialog
54c8945a0SNathan Whitehorn  *
6*2a3e3873SBaptiste Daroussin  *  Copyright 2006-2009,2011 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 #define LIST_BINDINGS struct _list_bindings
284c8945a0SNathan Whitehorn 
294c8945a0SNathan Whitehorn LIST_BINDINGS {
304c8945a0SNathan Whitehorn     LIST_BINDINGS *link;
314c8945a0SNathan Whitehorn     WINDOW *win;		/* window on which widget gets input */
324c8945a0SNathan Whitehorn     const char *name;		/* widget name */
334c8945a0SNathan Whitehorn     bool buttons;		/* true only for dlg_register_buttons() */
344c8945a0SNathan Whitehorn     DLG_KEYS_BINDING *binding;	/* list of bindings */
354c8945a0SNathan Whitehorn };
364c8945a0SNathan Whitehorn 
37*2a3e3873SBaptiste Daroussin #define WILDNAME "*"
384c8945a0SNathan Whitehorn static LIST_BINDINGS *all_bindings;
394c8945a0SNathan Whitehorn static const DLG_KEYS_BINDING end_keys_binding = END_KEYS_BINDING;
404c8945a0SNathan Whitehorn 
414c8945a0SNathan Whitehorn /*
424c8945a0SNathan Whitehorn  * For a given named widget's window, associate a binding table.
434c8945a0SNathan Whitehorn  */
444c8945a0SNathan Whitehorn void
454c8945a0SNathan Whitehorn dlg_register_window(WINDOW *win, const char *name, DLG_KEYS_BINDING * binding)
464c8945a0SNathan Whitehorn {
474c8945a0SNathan Whitehorn     LIST_BINDINGS *p, *q;
484c8945a0SNathan Whitehorn 
494c8945a0SNathan Whitehorn     for (p = all_bindings, q = 0; p != 0; q = p, p = p->link) {
504c8945a0SNathan Whitehorn 	if (p->win == win && !strcmp(p->name, name)) {
514c8945a0SNathan Whitehorn 	    p->binding = binding;
524c8945a0SNathan Whitehorn 	    return;
534c8945a0SNathan Whitehorn 	}
544c8945a0SNathan Whitehorn     }
554c8945a0SNathan Whitehorn     /* add built-in bindings at the end of the list (see compare_bindings). */
564c8945a0SNathan Whitehorn     if ((p = dlg_calloc(LIST_BINDINGS, 1)) != 0) {
574c8945a0SNathan Whitehorn 	p->win = win;
584c8945a0SNathan Whitehorn 	p->name = name;
594c8945a0SNathan Whitehorn 	p->binding = binding;
604c8945a0SNathan Whitehorn 	if (q != 0)
614c8945a0SNathan Whitehorn 	    q->link = p;
624c8945a0SNathan Whitehorn 	else
634c8945a0SNathan Whitehorn 	    all_bindings = p;
644c8945a0SNathan Whitehorn     }
65*2a3e3873SBaptiste Daroussin #if defined(HAVE_DLG_TRACE) && defined(HAVE_RC_FILE)
66*2a3e3873SBaptiste Daroussin     /*
67*2a3e3873SBaptiste Daroussin      * Trace the binding information assigned to this window.  For most widgets
68*2a3e3873SBaptiste Daroussin      * there is only one binding table.  forms have two, so the trace will be
69*2a3e3873SBaptiste Daroussin      * longer.  Since compiled-in bindings are only visible when the widget is
70*2a3e3873SBaptiste Daroussin      * registered, there is no other way to see what bindings are available,
71*2a3e3873SBaptiste Daroussin      * than by running dialog and tracing it.
72*2a3e3873SBaptiste Daroussin      */
73*2a3e3873SBaptiste Daroussin     dlg_trace_msg("# dlg_register_window %s\n", name);
74*2a3e3873SBaptiste Daroussin     dlg_dump_window_keys(dialog_state.trace_output, win);
75*2a3e3873SBaptiste Daroussin #endif
764c8945a0SNathan Whitehorn }
774c8945a0SNathan Whitehorn 
784c8945a0SNathan Whitehorn /*
794c8945a0SNathan Whitehorn  * Unlike dlg_lookup_key(), this looks for either widget-builtin or rc-file
804c8945a0SNathan Whitehorn  * definitions, depending on whether 'win' is null.
814c8945a0SNathan Whitehorn  */
824c8945a0SNathan Whitehorn static int
834c8945a0SNathan Whitehorn key_is_bound(WINDOW *win, const char *name, int curses_key, int function_key)
844c8945a0SNathan Whitehorn {
854c8945a0SNathan Whitehorn     LIST_BINDINGS *p;
864c8945a0SNathan Whitehorn 
874c8945a0SNathan Whitehorn     for (p = all_bindings; p != 0; p = p->link) {
884c8945a0SNathan Whitehorn 	if (p->win == win && !dlg_strcmp(p->name, name)) {
894c8945a0SNathan Whitehorn 	    int n;
904c8945a0SNathan Whitehorn 	    for (n = 0; p->binding[n].is_function_key >= 0; ++n) {
914c8945a0SNathan Whitehorn 		if (p->binding[n].curses_key == curses_key
924c8945a0SNathan Whitehorn 		    && p->binding[n].is_function_key == function_key) {
934c8945a0SNathan Whitehorn 		    return TRUE;
944c8945a0SNathan Whitehorn 		}
954c8945a0SNathan Whitehorn 	    }
964c8945a0SNathan Whitehorn 	}
974c8945a0SNathan Whitehorn     }
984c8945a0SNathan Whitehorn     return FALSE;
994c8945a0SNathan Whitehorn }
1004c8945a0SNathan Whitehorn 
1014c8945a0SNathan Whitehorn /*
1024c8945a0SNathan Whitehorn  * Call this function after dlg_register_window(), for the list of button
1034c8945a0SNathan Whitehorn  * labels associated with the widget.
1044c8945a0SNathan Whitehorn  *
1054c8945a0SNathan Whitehorn  * Ensure that dlg_lookup_key() will not accidentally translate a key that
1064c8945a0SNathan Whitehorn  * we would like to use for a button abbreviation to some other key, e.g.,
1074c8945a0SNathan Whitehorn  * h/j/k/l for navigation into a cursor key.  Do this by binding the key
1084c8945a0SNathan Whitehorn  * to itself.
1094c8945a0SNathan Whitehorn  *
1104c8945a0SNathan Whitehorn  * See dlg_char_to_button().
1114c8945a0SNathan Whitehorn  */
1124c8945a0SNathan Whitehorn void
1134c8945a0SNathan Whitehorn dlg_register_buttons(WINDOW *win, const char *name, const char **buttons)
1144c8945a0SNathan Whitehorn {
1154c8945a0SNathan Whitehorn     int n;
1164c8945a0SNathan Whitehorn     LIST_BINDINGS *p;
1174c8945a0SNathan Whitehorn     DLG_KEYS_BINDING *q;
1184c8945a0SNathan Whitehorn 
1194c8945a0SNathan Whitehorn     if (buttons == 0)
1204c8945a0SNathan Whitehorn 	return;
1214c8945a0SNathan Whitehorn 
1224c8945a0SNathan Whitehorn     for (n = 0; buttons[n] != 0; ++n) {
1234c8945a0SNathan Whitehorn 	int curses_key = dlg_button_to_char(buttons[n]);
1244c8945a0SNathan Whitehorn 
1254c8945a0SNathan Whitehorn 	/* ignore multibyte characters */
1264c8945a0SNathan Whitehorn 	if (curses_key >= KEY_MIN)
1274c8945a0SNathan Whitehorn 	    continue;
1284c8945a0SNathan Whitehorn 
1294c8945a0SNathan Whitehorn 	/* if it is not bound in the widget, skip it (no conflicts) */
1304c8945a0SNathan Whitehorn 	if (!key_is_bound(win, name, curses_key, FALSE))
1314c8945a0SNathan Whitehorn 	    continue;
1324c8945a0SNathan Whitehorn 
1334c8945a0SNathan Whitehorn #ifdef HAVE_RC_FILE
1344c8945a0SNathan Whitehorn 	/* if it is bound in the rc-file, skip it */
1354c8945a0SNathan Whitehorn 	if (key_is_bound(0, name, curses_key, FALSE))
1364c8945a0SNathan Whitehorn 	    continue;
1374c8945a0SNathan Whitehorn #endif
1384c8945a0SNathan Whitehorn 
1394c8945a0SNathan Whitehorn 	if ((p = dlg_calloc(LIST_BINDINGS, 1)) != 0) {
1404c8945a0SNathan Whitehorn 	    if ((q = dlg_calloc(DLG_KEYS_BINDING, 2)) != 0) {
1414c8945a0SNathan Whitehorn 		q[0].is_function_key = 0;
1424c8945a0SNathan Whitehorn 		q[0].curses_key = curses_key;
1434c8945a0SNathan Whitehorn 		q[0].dialog_key = curses_key;
1444c8945a0SNathan Whitehorn 		q[1] = end_keys_binding;
1454c8945a0SNathan Whitehorn 
1464c8945a0SNathan Whitehorn 		p->win = win;
1474c8945a0SNathan Whitehorn 		p->name = name;
1484c8945a0SNathan Whitehorn 		p->buttons = TRUE;
1494c8945a0SNathan Whitehorn 		p->binding = q;
1504c8945a0SNathan Whitehorn 
1514c8945a0SNathan Whitehorn 		/* put these at the beginning, to override the widget's table */
1524c8945a0SNathan Whitehorn 		p->link = all_bindings;
1534c8945a0SNathan Whitehorn 		all_bindings = p;
1544c8945a0SNathan Whitehorn 	    } else {
1554c8945a0SNathan Whitehorn 		free(p);
1564c8945a0SNathan Whitehorn 	    }
1574c8945a0SNathan Whitehorn 	}
1584c8945a0SNathan Whitehorn     }
1594c8945a0SNathan Whitehorn }
1604c8945a0SNathan Whitehorn 
1614c8945a0SNathan Whitehorn /*
1624c8945a0SNathan Whitehorn  * Remove the bindings for a given window.
1634c8945a0SNathan Whitehorn  */
1644c8945a0SNathan Whitehorn void
1654c8945a0SNathan Whitehorn dlg_unregister_window(WINDOW *win)
1664c8945a0SNathan Whitehorn {
1674c8945a0SNathan Whitehorn     LIST_BINDINGS *p, *q;
1684c8945a0SNathan Whitehorn 
1694c8945a0SNathan Whitehorn     for (p = all_bindings, q = 0; p != 0; p = p->link) {
1704c8945a0SNathan Whitehorn 	if (p->win == win) {
1714c8945a0SNathan Whitehorn 	    if (q != 0) {
1724c8945a0SNathan Whitehorn 		q->link = p->link;
1734c8945a0SNathan Whitehorn 	    } else {
1744c8945a0SNathan Whitehorn 		all_bindings = p->link;
1754c8945a0SNathan Whitehorn 	    }
1764c8945a0SNathan Whitehorn 	    /* the user-defined and buttons-bindings all are length=1 */
1774c8945a0SNathan Whitehorn 	    if (p->binding[1].is_function_key < 0)
1784c8945a0SNathan Whitehorn 		free(p->binding);
1794c8945a0SNathan Whitehorn 	    free(p);
1804c8945a0SNathan Whitehorn 	    dlg_unregister_window(win);
1814c8945a0SNathan Whitehorn 	    break;
1824c8945a0SNathan Whitehorn 	}
1834c8945a0SNathan Whitehorn 	q = p;
1844c8945a0SNathan Whitehorn     }
1854c8945a0SNathan Whitehorn }
1864c8945a0SNathan Whitehorn 
1874c8945a0SNathan Whitehorn /*
1884c8945a0SNathan Whitehorn  * Call this after wgetch(), using the same window pointer and passing
1894c8945a0SNathan Whitehorn  * the curses-key.
1904c8945a0SNathan Whitehorn  *
1914c8945a0SNathan Whitehorn  * If there is no binding associated with the widget, it simply returns
1924c8945a0SNathan Whitehorn  * the given curses-key.
1934c8945a0SNathan Whitehorn  *
1944c8945a0SNathan Whitehorn  * Parameters:
1954c8945a0SNathan Whitehorn  *	win is the window on which the wgetch() was done.
1964c8945a0SNathan Whitehorn  *	curses_key is the value returned by wgetch().
1974c8945a0SNathan Whitehorn  *	fkey in/out (on input, it is true if curses_key is a function key,
1984c8945a0SNathan Whitehorn  *		and on output, it is true if the result is a function key).
1994c8945a0SNathan Whitehorn  */
2004c8945a0SNathan Whitehorn int
2014c8945a0SNathan Whitehorn dlg_lookup_key(WINDOW *win, int curses_key, int *fkey)
2024c8945a0SNathan Whitehorn {
2034c8945a0SNathan Whitehorn     LIST_BINDINGS *p;
204*2a3e3873SBaptiste Daroussin     DLG_KEYS_BINDING *q;
2054c8945a0SNathan Whitehorn 
2064c8945a0SNathan Whitehorn     /*
2074c8945a0SNathan Whitehorn      * Ignore mouse clicks, since they are already encoded properly.
2084c8945a0SNathan Whitehorn      */
2094c8945a0SNathan Whitehorn #ifdef KEY_MOUSE
2104c8945a0SNathan Whitehorn     if (*fkey != 0 && curses_key == KEY_MOUSE) {
2114c8945a0SNathan Whitehorn 	;
2124c8945a0SNathan Whitehorn     } else
2134c8945a0SNathan Whitehorn #endif
2144c8945a0SNathan Whitehorn 	/*
2154c8945a0SNathan Whitehorn 	 * Ignore resize events, since they are already encoded properly.
2164c8945a0SNathan Whitehorn 	 */
2174c8945a0SNathan Whitehorn #ifdef KEY_RESIZE
2184c8945a0SNathan Whitehorn     if (*fkey != 0 && curses_key == KEY_RESIZE) {
2194c8945a0SNathan Whitehorn 	;
2204c8945a0SNathan Whitehorn     } else
2214c8945a0SNathan Whitehorn #endif
2224c8945a0SNathan Whitehorn     if (*fkey == 0 || curses_key < KEY_MAX) {
223*2a3e3873SBaptiste Daroussin 	const char *name = WILDNAME;
224*2a3e3873SBaptiste Daroussin 	if (win != 0) {
2254c8945a0SNathan Whitehorn 	    for (p = all_bindings; p != 0; p = p->link) {
226*2a3e3873SBaptiste Daroussin 		if (p->win == win) {
227*2a3e3873SBaptiste Daroussin 		    name = p->name;
228*2a3e3873SBaptiste Daroussin 		    break;
229*2a3e3873SBaptiste Daroussin 		}
230*2a3e3873SBaptiste Daroussin 	    }
231*2a3e3873SBaptiste Daroussin 	}
232*2a3e3873SBaptiste Daroussin 	for (p = all_bindings; p != 0; p = p->link) {
233*2a3e3873SBaptiste Daroussin 	    if (p->win == win || (p->win == 0 && !strcmp(p->name, name))) {
2344c8945a0SNathan Whitehorn 		int function_key = (*fkey != 0);
235*2a3e3873SBaptiste Daroussin 		for (q = p->binding; q->is_function_key >= 0; ++q) {
2364c8945a0SNathan Whitehorn 		    if (p->buttons
2374c8945a0SNathan Whitehorn 			&& !function_key
238*2a3e3873SBaptiste Daroussin 			&& q->curses_key == (int) dlg_toupper(curses_key)) {
2394c8945a0SNathan Whitehorn 			*fkey = 0;
240*2a3e3873SBaptiste Daroussin 			return q->dialog_key;
2414c8945a0SNathan Whitehorn 		    }
242*2a3e3873SBaptiste Daroussin 		    if (q->curses_key == curses_key
243*2a3e3873SBaptiste Daroussin 			&& q->is_function_key == function_key) {
244*2a3e3873SBaptiste Daroussin 			*fkey = q->dialog_key;
2454c8945a0SNathan Whitehorn 			return *fkey;
2464c8945a0SNathan Whitehorn 		    }
2474c8945a0SNathan Whitehorn 		}
2484c8945a0SNathan Whitehorn 	    }
2494c8945a0SNathan Whitehorn 	}
2504c8945a0SNathan Whitehorn     }
2514c8945a0SNathan Whitehorn     return curses_key;
2524c8945a0SNathan Whitehorn }
2534c8945a0SNathan Whitehorn 
2544c8945a0SNathan Whitehorn /*
2554c8945a0SNathan Whitehorn  * Test a dialog internal keycode to see if it corresponds to one of the push
2564c8945a0SNathan Whitehorn  * buttons on the widget such as "OK".
2574c8945a0SNathan Whitehorn  *
2584c8945a0SNathan Whitehorn  * This is only useful if there are user-defined key bindings, since there are
2594c8945a0SNathan Whitehorn  * no built-in bindings that map directly to DLGK_OK, etc.
2604c8945a0SNathan Whitehorn  *
2614c8945a0SNathan Whitehorn  * See also dlg_ok_buttoncode().
2624c8945a0SNathan Whitehorn  */
2634c8945a0SNathan Whitehorn int
2644c8945a0SNathan Whitehorn dlg_result_key(int dialog_key, int fkey GCC_UNUSED, int *resultp)
2654c8945a0SNathan Whitehorn {
2664c8945a0SNathan Whitehorn     int done = FALSE;
2674c8945a0SNathan Whitehorn 
2684c8945a0SNathan Whitehorn #ifdef HAVE_RC_FILE
2694c8945a0SNathan Whitehorn     if (fkey) {
2704c8945a0SNathan Whitehorn 	switch ((DLG_KEYS_ENUM) dialog_key) {
2714c8945a0SNathan Whitehorn 	case DLGK_OK:
2724c8945a0SNathan Whitehorn 	    *resultp = DLG_EXIT_OK;
2734c8945a0SNathan Whitehorn 	    done = TRUE;
2744c8945a0SNathan Whitehorn 	    break;
2754c8945a0SNathan Whitehorn 	case DLGK_CANCEL:
2764c8945a0SNathan Whitehorn 	    if (!dialog_vars.nocancel) {
2774c8945a0SNathan Whitehorn 		*resultp = DLG_EXIT_CANCEL;
2784c8945a0SNathan Whitehorn 		done = TRUE;
2794c8945a0SNathan Whitehorn 	    }
2804c8945a0SNathan Whitehorn 	    break;
2814c8945a0SNathan Whitehorn 	case DLGK_EXTRA:
2824c8945a0SNathan Whitehorn 	    if (dialog_vars.extra_button) {
2834c8945a0SNathan Whitehorn 		*resultp = DLG_EXIT_EXTRA;
2844c8945a0SNathan Whitehorn 		done = TRUE;
2854c8945a0SNathan Whitehorn 	    }
2864c8945a0SNathan Whitehorn 	    break;
2874c8945a0SNathan Whitehorn 	case DLGK_HELP:
2884c8945a0SNathan Whitehorn 	    if (dialog_vars.help_button) {
2894c8945a0SNathan Whitehorn 		*resultp = DLG_EXIT_HELP;
2904c8945a0SNathan Whitehorn 		done = TRUE;
2914c8945a0SNathan Whitehorn 	    }
2924c8945a0SNathan Whitehorn 	    break;
2934c8945a0SNathan Whitehorn 	case DLGK_ESC:
2944c8945a0SNathan Whitehorn 	    *resultp = DLG_EXIT_ESC;
2954c8945a0SNathan Whitehorn 	    done = TRUE;
2964c8945a0SNathan Whitehorn 	    break;
2974c8945a0SNathan Whitehorn 	default:
2984c8945a0SNathan Whitehorn 	    break;
2994c8945a0SNathan Whitehorn 	}
3004c8945a0SNathan Whitehorn     } else
3014c8945a0SNathan Whitehorn #endif
3024c8945a0SNathan Whitehorn     if (dialog_key == ESC) {
3034c8945a0SNathan Whitehorn 	*resultp = DLG_EXIT_ESC;
3044c8945a0SNathan Whitehorn 	done = TRUE;
3054c8945a0SNathan Whitehorn     } else if (dialog_key == ERR) {
3064c8945a0SNathan Whitehorn 	*resultp = DLG_EXIT_ERROR;
3074c8945a0SNathan Whitehorn 	done = TRUE;
3084c8945a0SNathan Whitehorn     }
3094c8945a0SNathan Whitehorn 
3104c8945a0SNathan Whitehorn     return done;
3114c8945a0SNathan Whitehorn }
3124c8945a0SNathan Whitehorn 
3134c8945a0SNathan Whitehorn #ifdef HAVE_RC_FILE
3144c8945a0SNathan Whitehorn typedef struct {
3154c8945a0SNathan Whitehorn     const char *name;
3164c8945a0SNathan Whitehorn     int code;
3174c8945a0SNathan Whitehorn } CODENAME;
3184c8945a0SNathan Whitehorn 
319*2a3e3873SBaptiste Daroussin #define ASCII_NAME(name,code)  { #name, code }
3204c8945a0SNathan Whitehorn #define CURSES_NAME(upper) { #upper, KEY_ ## upper }
3214c8945a0SNathan Whitehorn #define COUNT_CURSES  sizeof(curses_names)/sizeof(curses_names[0])
3224c8945a0SNathan Whitehorn static const CODENAME curses_names[] =
3234c8945a0SNathan Whitehorn {
324*2a3e3873SBaptiste Daroussin     ASCII_NAME(ESC, '\033'),
325*2a3e3873SBaptiste Daroussin     ASCII_NAME(CR, '\r'),
326*2a3e3873SBaptiste Daroussin     ASCII_NAME(LF, '\n'),
327*2a3e3873SBaptiste Daroussin     ASCII_NAME(FF, '\f'),
328*2a3e3873SBaptiste Daroussin     ASCII_NAME(TAB, '\t'),
329*2a3e3873SBaptiste Daroussin     ASCII_NAME(DEL, '\177'),
330*2a3e3873SBaptiste Daroussin 
3314c8945a0SNathan Whitehorn     CURSES_NAME(DOWN),
3324c8945a0SNathan Whitehorn     CURSES_NAME(UP),
3334c8945a0SNathan Whitehorn     CURSES_NAME(LEFT),
3344c8945a0SNathan Whitehorn     CURSES_NAME(RIGHT),
3354c8945a0SNathan Whitehorn     CURSES_NAME(HOME),
3364c8945a0SNathan Whitehorn     CURSES_NAME(BACKSPACE),
3374c8945a0SNathan Whitehorn     CURSES_NAME(F0),
3384c8945a0SNathan Whitehorn     CURSES_NAME(DL),
3394c8945a0SNathan Whitehorn     CURSES_NAME(IL),
3404c8945a0SNathan Whitehorn     CURSES_NAME(DC),
3414c8945a0SNathan Whitehorn     CURSES_NAME(IC),
3424c8945a0SNathan Whitehorn     CURSES_NAME(EIC),
3434c8945a0SNathan Whitehorn     CURSES_NAME(CLEAR),
3444c8945a0SNathan Whitehorn     CURSES_NAME(EOS),
3454c8945a0SNathan Whitehorn     CURSES_NAME(EOL),
3464c8945a0SNathan Whitehorn     CURSES_NAME(SF),
3474c8945a0SNathan Whitehorn     CURSES_NAME(SR),
3484c8945a0SNathan Whitehorn     CURSES_NAME(NPAGE),
3494c8945a0SNathan Whitehorn     CURSES_NAME(PPAGE),
3504c8945a0SNathan Whitehorn     CURSES_NAME(STAB),
3514c8945a0SNathan Whitehorn     CURSES_NAME(CTAB),
3524c8945a0SNathan Whitehorn     CURSES_NAME(CATAB),
3534c8945a0SNathan Whitehorn     CURSES_NAME(ENTER),
3544c8945a0SNathan Whitehorn     CURSES_NAME(PRINT),
3554c8945a0SNathan Whitehorn     CURSES_NAME(LL),
3564c8945a0SNathan Whitehorn     CURSES_NAME(A1),
3574c8945a0SNathan Whitehorn     CURSES_NAME(A3),
3584c8945a0SNathan Whitehorn     CURSES_NAME(B2),
3594c8945a0SNathan Whitehorn     CURSES_NAME(C1),
3604c8945a0SNathan Whitehorn     CURSES_NAME(C3),
3614c8945a0SNathan Whitehorn     CURSES_NAME(BTAB),
3624c8945a0SNathan Whitehorn     CURSES_NAME(BEG),
3634c8945a0SNathan Whitehorn     CURSES_NAME(CANCEL),
3644c8945a0SNathan Whitehorn     CURSES_NAME(CLOSE),
3654c8945a0SNathan Whitehorn     CURSES_NAME(COMMAND),
3664c8945a0SNathan Whitehorn     CURSES_NAME(COPY),
3674c8945a0SNathan Whitehorn     CURSES_NAME(CREATE),
3684c8945a0SNathan Whitehorn     CURSES_NAME(END),
3694c8945a0SNathan Whitehorn     CURSES_NAME(EXIT),
3704c8945a0SNathan Whitehorn     CURSES_NAME(FIND),
3714c8945a0SNathan Whitehorn     CURSES_NAME(HELP),
3724c8945a0SNathan Whitehorn     CURSES_NAME(MARK),
3734c8945a0SNathan Whitehorn     CURSES_NAME(MESSAGE),
3744c8945a0SNathan Whitehorn     CURSES_NAME(MOVE),
3754c8945a0SNathan Whitehorn     CURSES_NAME(NEXT),
3764c8945a0SNathan Whitehorn     CURSES_NAME(OPEN),
3774c8945a0SNathan Whitehorn     CURSES_NAME(OPTIONS),
3784c8945a0SNathan Whitehorn     CURSES_NAME(PREVIOUS),
3794c8945a0SNathan Whitehorn     CURSES_NAME(REDO),
3804c8945a0SNathan Whitehorn     CURSES_NAME(REFERENCE),
3814c8945a0SNathan Whitehorn     CURSES_NAME(REFRESH),
3824c8945a0SNathan Whitehorn     CURSES_NAME(REPLACE),
3834c8945a0SNathan Whitehorn     CURSES_NAME(RESTART),
3844c8945a0SNathan Whitehorn     CURSES_NAME(RESUME),
3854c8945a0SNathan Whitehorn     CURSES_NAME(SAVE),
3864c8945a0SNathan Whitehorn     CURSES_NAME(SBEG),
3874c8945a0SNathan Whitehorn     CURSES_NAME(SCANCEL),
3884c8945a0SNathan Whitehorn     CURSES_NAME(SCOMMAND),
3894c8945a0SNathan Whitehorn     CURSES_NAME(SCOPY),
3904c8945a0SNathan Whitehorn     CURSES_NAME(SCREATE),
3914c8945a0SNathan Whitehorn     CURSES_NAME(SDC),
3924c8945a0SNathan Whitehorn     CURSES_NAME(SDL),
3934c8945a0SNathan Whitehorn     CURSES_NAME(SELECT),
3944c8945a0SNathan Whitehorn     CURSES_NAME(SEND),
3954c8945a0SNathan Whitehorn     CURSES_NAME(SEOL),
3964c8945a0SNathan Whitehorn     CURSES_NAME(SEXIT),
3974c8945a0SNathan Whitehorn     CURSES_NAME(SFIND),
3984c8945a0SNathan Whitehorn     CURSES_NAME(SHELP),
3994c8945a0SNathan Whitehorn     CURSES_NAME(SHOME),
4004c8945a0SNathan Whitehorn     CURSES_NAME(SIC),
4014c8945a0SNathan Whitehorn     CURSES_NAME(SLEFT),
4024c8945a0SNathan Whitehorn     CURSES_NAME(SMESSAGE),
4034c8945a0SNathan Whitehorn     CURSES_NAME(SMOVE),
4044c8945a0SNathan Whitehorn     CURSES_NAME(SNEXT),
4054c8945a0SNathan Whitehorn     CURSES_NAME(SOPTIONS),
4064c8945a0SNathan Whitehorn     CURSES_NAME(SPREVIOUS),
4074c8945a0SNathan Whitehorn     CURSES_NAME(SPRINT),
4084c8945a0SNathan Whitehorn     CURSES_NAME(SREDO),
4094c8945a0SNathan Whitehorn     CURSES_NAME(SREPLACE),
4104c8945a0SNathan Whitehorn     CURSES_NAME(SRIGHT),
4114c8945a0SNathan Whitehorn     CURSES_NAME(SRSUME),
4124c8945a0SNathan Whitehorn     CURSES_NAME(SSAVE),
4134c8945a0SNathan Whitehorn     CURSES_NAME(SSUSPEND),
4144c8945a0SNathan Whitehorn     CURSES_NAME(SUNDO),
4154c8945a0SNathan Whitehorn     CURSES_NAME(SUSPEND),
4164c8945a0SNathan Whitehorn     CURSES_NAME(UNDO),
4174c8945a0SNathan Whitehorn };
4184c8945a0SNathan Whitehorn 
4194c8945a0SNathan Whitehorn #define DIALOG_NAME(upper) { #upper, DLGK_ ## upper }
4204c8945a0SNathan Whitehorn #define COUNT_DIALOG  sizeof(dialog_names)/sizeof(dialog_names[0])
4214c8945a0SNathan Whitehorn static const CODENAME dialog_names[] =
4224c8945a0SNathan Whitehorn {
4234c8945a0SNathan Whitehorn     DIALOG_NAME(OK),
4244c8945a0SNathan Whitehorn     DIALOG_NAME(CANCEL),
4254c8945a0SNathan Whitehorn     DIALOG_NAME(EXTRA),
4264c8945a0SNathan Whitehorn     DIALOG_NAME(HELP),
4274c8945a0SNathan Whitehorn     DIALOG_NAME(ESC),
4284c8945a0SNathan Whitehorn     DIALOG_NAME(PAGE_FIRST),
4294c8945a0SNathan Whitehorn     DIALOG_NAME(PAGE_LAST),
4304c8945a0SNathan Whitehorn     DIALOG_NAME(PAGE_NEXT),
4314c8945a0SNathan Whitehorn     DIALOG_NAME(PAGE_PREV),
4324c8945a0SNathan Whitehorn     DIALOG_NAME(ITEM_FIRST),
4334c8945a0SNathan Whitehorn     DIALOG_NAME(ITEM_LAST),
4344c8945a0SNathan Whitehorn     DIALOG_NAME(ITEM_NEXT),
4354c8945a0SNathan Whitehorn     DIALOG_NAME(ITEM_PREV),
4364c8945a0SNathan Whitehorn     DIALOG_NAME(FIELD_FIRST),
4374c8945a0SNathan Whitehorn     DIALOG_NAME(FIELD_LAST),
4384c8945a0SNathan Whitehorn     DIALOG_NAME(FIELD_NEXT),
4394c8945a0SNathan Whitehorn     DIALOG_NAME(FIELD_PREV),
440*2a3e3873SBaptiste Daroussin     DIALOG_NAME(FORM_FIRST),
441*2a3e3873SBaptiste Daroussin     DIALOG_NAME(FORM_LAST),
442*2a3e3873SBaptiste Daroussin     DIALOG_NAME(FORM_NEXT),
443*2a3e3873SBaptiste Daroussin     DIALOG_NAME(FORM_PREV),
4444c8945a0SNathan Whitehorn     DIALOG_NAME(GRID_UP),
4454c8945a0SNathan Whitehorn     DIALOG_NAME(GRID_DOWN),
4464c8945a0SNathan Whitehorn     DIALOG_NAME(GRID_LEFT),
4474c8945a0SNathan Whitehorn     DIALOG_NAME(GRID_RIGHT),
4484c8945a0SNathan Whitehorn     DIALOG_NAME(DELETE_LEFT),
4494c8945a0SNathan Whitehorn     DIALOG_NAME(DELETE_RIGHT),
4504c8945a0SNathan Whitehorn     DIALOG_NAME(DELETE_ALL),
4514c8945a0SNathan Whitehorn     DIALOG_NAME(ENTER),
4524c8945a0SNathan Whitehorn     DIALOG_NAME(BEGIN),
4534c8945a0SNathan Whitehorn     DIALOG_NAME(FINAL),
454*2a3e3873SBaptiste Daroussin     DIALOG_NAME(SELECT),
455*2a3e3873SBaptiste Daroussin     DIALOG_NAME(HELPFILE),
456*2a3e3873SBaptiste Daroussin     DIALOG_NAME(TRACE)
4574c8945a0SNathan Whitehorn };
4584c8945a0SNathan Whitehorn 
4594c8945a0SNathan Whitehorn static char *
4604c8945a0SNathan Whitehorn skip_white(char *s)
4614c8945a0SNathan Whitehorn {
4624c8945a0SNathan Whitehorn     while (*s != '\0' && isspace(UCH(*s)))
4634c8945a0SNathan Whitehorn 	++s;
4644c8945a0SNathan Whitehorn     return s;
4654c8945a0SNathan Whitehorn }
4664c8945a0SNathan Whitehorn 
4674c8945a0SNathan Whitehorn static char *
4684c8945a0SNathan Whitehorn skip_black(char *s)
4694c8945a0SNathan Whitehorn {
4704c8945a0SNathan Whitehorn     while (*s != '\0' && !isspace(UCH(*s)))
4714c8945a0SNathan Whitehorn 	++s;
4724c8945a0SNathan Whitehorn     return s;
4734c8945a0SNathan Whitehorn }
4744c8945a0SNathan Whitehorn 
4754c8945a0SNathan Whitehorn /*
4764c8945a0SNathan Whitehorn  * Find a user-defined binding, given the curses key code.
4774c8945a0SNathan Whitehorn  */
4784c8945a0SNathan Whitehorn static DLG_KEYS_BINDING *
4794c8945a0SNathan Whitehorn find_binding(char *widget, int curses_key)
4804c8945a0SNathan Whitehorn {
4814c8945a0SNathan Whitehorn     LIST_BINDINGS *p;
4824c8945a0SNathan Whitehorn     DLG_KEYS_BINDING *result = 0;
4834c8945a0SNathan Whitehorn 
4844c8945a0SNathan Whitehorn     for (p = all_bindings; p != 0; p = p->link) {
4854c8945a0SNathan Whitehorn 	if (p->win == 0
4864c8945a0SNathan Whitehorn 	    && !dlg_strcmp(p->name, widget)
4874c8945a0SNathan Whitehorn 	    && p->binding->curses_key == curses_key) {
4884c8945a0SNathan Whitehorn 	    result = p->binding;
4894c8945a0SNathan Whitehorn 	    break;
4904c8945a0SNathan Whitehorn 	}
4914c8945a0SNathan Whitehorn     }
4924c8945a0SNathan Whitehorn     return result;
4934c8945a0SNathan Whitehorn }
4944c8945a0SNathan Whitehorn 
4954c8945a0SNathan Whitehorn /*
4964c8945a0SNathan Whitehorn  * Built-in bindings have a nonzero "win" member, and the associated binding
4974c8945a0SNathan Whitehorn  * table can have more than one entry.  We keep those last, since lookups will
4984c8945a0SNathan Whitehorn  * find the user-defined bindings first and use those.
4994c8945a0SNathan Whitehorn  *
5004c8945a0SNathan Whitehorn  * Sort "*" (all-widgets) entries past named widgets, since those are less
5014c8945a0SNathan Whitehorn  * specific.
5024c8945a0SNathan Whitehorn  */
5034c8945a0SNathan Whitehorn static int
5044c8945a0SNathan Whitehorn compare_bindings(LIST_BINDINGS * a, LIST_BINDINGS * b)
5054c8945a0SNathan Whitehorn {
5064c8945a0SNathan Whitehorn     int result = 0;
5074c8945a0SNathan Whitehorn     if (a->win == b->win) {
5084c8945a0SNathan Whitehorn 	if (!strcmp(a->name, b->name)) {
5094c8945a0SNathan Whitehorn 	    result = a->binding[0].curses_key - b->binding[0].curses_key;
510*2a3e3873SBaptiste Daroussin 	} else if (!strcmp(b->name, WILDNAME)) {
5114c8945a0SNathan Whitehorn 	    result = -1;
512*2a3e3873SBaptiste Daroussin 	} else if (!strcmp(a->name, WILDNAME)) {
5134c8945a0SNathan Whitehorn 	    result = 1;
5144c8945a0SNathan Whitehorn 	} else {
5154c8945a0SNathan Whitehorn 	    result = dlg_strcmp(a->name, b->name);
5164c8945a0SNathan Whitehorn 	}
5174c8945a0SNathan Whitehorn     } else if (b->win) {
5184c8945a0SNathan Whitehorn 	result = -1;
5194c8945a0SNathan Whitehorn     } else {
5204c8945a0SNathan Whitehorn 	result = 1;
5214c8945a0SNathan Whitehorn     }
5224c8945a0SNathan Whitehorn     return result;
5234c8945a0SNathan Whitehorn }
5244c8945a0SNathan Whitehorn 
5254c8945a0SNathan Whitehorn /*
5264c8945a0SNathan Whitehorn  * Find a user-defined binding, given the curses key code.  If it does not
5274c8945a0SNathan Whitehorn  * exist, create a new one, inserting it into the linked list, keeping it
5284c8945a0SNathan Whitehorn  * sorted to simplify lookups for user-defined bindings that can override
5294c8945a0SNathan Whitehorn  * the built-in bindings.
5304c8945a0SNathan Whitehorn  */
5314c8945a0SNathan Whitehorn static DLG_KEYS_BINDING *
5324c8945a0SNathan Whitehorn make_binding(char *widget, int curses_key, int is_function, int dialog_key)
5334c8945a0SNathan Whitehorn {
5344c8945a0SNathan Whitehorn     LIST_BINDINGS *entry = 0;
5354c8945a0SNathan Whitehorn     DLG_KEYS_BINDING *data = 0;
5364c8945a0SNathan Whitehorn     char *name;
5374c8945a0SNathan Whitehorn     LIST_BINDINGS *p, *q;
5384c8945a0SNathan Whitehorn     DLG_KEYS_BINDING *result = find_binding(widget, curses_key);
5394c8945a0SNathan Whitehorn 
5404c8945a0SNathan Whitehorn     if (result == 0
5414c8945a0SNathan Whitehorn 	&& (entry = dlg_calloc(LIST_BINDINGS, 1)) != 0
5424c8945a0SNathan Whitehorn 	&& (data = dlg_calloc(DLG_KEYS_BINDING, 2)) != 0
5434c8945a0SNathan Whitehorn 	&& (name = dlg_strclone(widget)) != 0) {
5444c8945a0SNathan Whitehorn 
5454c8945a0SNathan Whitehorn 	entry->name = name;
5464c8945a0SNathan Whitehorn 	entry->binding = data;
5474c8945a0SNathan Whitehorn 
5484c8945a0SNathan Whitehorn 	data[0].is_function_key = is_function;
5494c8945a0SNathan Whitehorn 	data[0].curses_key = curses_key;
5504c8945a0SNathan Whitehorn 	data[0].dialog_key = dialog_key;
5514c8945a0SNathan Whitehorn 
5524c8945a0SNathan Whitehorn 	data[1] = end_keys_binding;
5534c8945a0SNathan Whitehorn 
5544c8945a0SNathan Whitehorn 	for (p = all_bindings, q = 0; p != 0; q = p, p = p->link) {
5554c8945a0SNathan Whitehorn 	    if (compare_bindings(entry, p) < 0) {
5564c8945a0SNathan Whitehorn 		break;
5574c8945a0SNathan Whitehorn 	    }
5584c8945a0SNathan Whitehorn 	}
5594c8945a0SNathan Whitehorn 	if (q != 0) {
5604c8945a0SNathan Whitehorn 	    q->link = entry;
5614c8945a0SNathan Whitehorn 	} else {
5624c8945a0SNathan Whitehorn 	    all_bindings = entry;
5634c8945a0SNathan Whitehorn 	}
5644c8945a0SNathan Whitehorn 	if (p != 0) {
5654c8945a0SNathan Whitehorn 	    entry->link = p;
5664c8945a0SNathan Whitehorn 	}
5674c8945a0SNathan Whitehorn 	result = data;
5684c8945a0SNathan Whitehorn     } else if (entry != 0) {
5694c8945a0SNathan Whitehorn 	free(entry);
5704c8945a0SNathan Whitehorn 	if (data)
5714c8945a0SNathan Whitehorn 	    free(data);
5724c8945a0SNathan Whitehorn     }
5734c8945a0SNathan Whitehorn 
5744c8945a0SNathan Whitehorn     return result;
5754c8945a0SNathan Whitehorn }
5764c8945a0SNathan Whitehorn 
5774c8945a0SNathan Whitehorn /*
5784c8945a0SNathan Whitehorn  * Parse the parameters of the "bindkeys" configuration-file entry.  This
5794c8945a0SNathan Whitehorn  * expects widget name which may be "*", followed by curses key definition and
5804c8945a0SNathan Whitehorn  * then dialog key definition.
5814c8945a0SNathan Whitehorn  *
5824c8945a0SNathan Whitehorn  * The curses key "should" be one of the names (ignoring case) from
5834c8945a0SNathan Whitehorn  * curses_names[], but may also be a single control character (prefix "^" or
5844c8945a0SNathan Whitehorn  * "~" depending on whether it is C0 or C1), or an escaped single character.
5854c8945a0SNathan Whitehorn  * Binding a printable character with dialog is possible but not useful.
5864c8945a0SNathan Whitehorn  *
5874c8945a0SNathan Whitehorn  * The dialog key must be one of the names from dialog_names[].
5884c8945a0SNathan Whitehorn  */
5894c8945a0SNathan Whitehorn int
5904c8945a0SNathan Whitehorn dlg_parse_bindkey(char *params)
5914c8945a0SNathan Whitehorn {
5924c8945a0SNathan Whitehorn     char *p = skip_white(params);
5934c8945a0SNathan Whitehorn     char *q;
5944c8945a0SNathan Whitehorn     bool escaped = FALSE;
5954c8945a0SNathan Whitehorn     int modified = 0;
5964c8945a0SNathan Whitehorn     int result = FALSE;
5974c8945a0SNathan Whitehorn     unsigned xx;
5984c8945a0SNathan Whitehorn     char *widget;
5994c8945a0SNathan Whitehorn     int is_function = FALSE;
6004c8945a0SNathan Whitehorn     int curses_key;
6014c8945a0SNathan Whitehorn     int dialog_key;
6024c8945a0SNathan Whitehorn 
6034c8945a0SNathan Whitehorn     curses_key = -1;
6044c8945a0SNathan Whitehorn     dialog_key = -1;
6054c8945a0SNathan Whitehorn     widget = p;
6064c8945a0SNathan Whitehorn 
6074c8945a0SNathan Whitehorn     p = skip_black(p);
6084c8945a0SNathan Whitehorn     if (p != widget && *p != '\0') {
6094c8945a0SNathan Whitehorn 	*p++ = '\0';
610*2a3e3873SBaptiste Daroussin 	p = skip_white(p);
6114c8945a0SNathan Whitehorn 	q = p;
6124c8945a0SNathan Whitehorn 	while (*p != '\0' && curses_key < 0) {
6134c8945a0SNathan Whitehorn 	    if (escaped) {
6144c8945a0SNathan Whitehorn 		escaped = FALSE;
6154c8945a0SNathan Whitehorn 		curses_key = *p;
6164c8945a0SNathan Whitehorn 	    } else if (*p == '\\') {
6174c8945a0SNathan Whitehorn 		escaped = TRUE;
6184c8945a0SNathan Whitehorn 	    } else if (modified) {
6194c8945a0SNathan Whitehorn 		if (*p == '?') {
6204c8945a0SNathan Whitehorn 		    curses_key = ((modified == '^')
6214c8945a0SNathan Whitehorn 				  ? 127
6224c8945a0SNathan Whitehorn 				  : 255);
6234c8945a0SNathan Whitehorn 		} else {
6244c8945a0SNathan Whitehorn 		    curses_key = ((modified == '^')
6254c8945a0SNathan Whitehorn 				  ? (*p & 0x1f)
6264c8945a0SNathan Whitehorn 				  : ((*p & 0x1f) | 0x80));
6274c8945a0SNathan Whitehorn 		}
6284c8945a0SNathan Whitehorn 	    } else if (*p == '^') {
6294c8945a0SNathan Whitehorn 		modified = *p;
6304c8945a0SNathan Whitehorn 	    } else if (*p == '~') {
6314c8945a0SNathan Whitehorn 		modified = *p;
6324c8945a0SNathan Whitehorn 	    } else if (isspace(UCH(*p))) {
6334c8945a0SNathan Whitehorn 		break;
6344c8945a0SNathan Whitehorn 	    }
6354c8945a0SNathan Whitehorn 	    ++p;
6364c8945a0SNathan Whitehorn 	}
6374c8945a0SNathan Whitehorn 	if (!isspace(UCH(*p))) {
6384c8945a0SNathan Whitehorn 	    ;
6394c8945a0SNathan Whitehorn 	} else {
6404c8945a0SNathan Whitehorn 	    *p++ = '\0';
6414c8945a0SNathan Whitehorn 	    if (curses_key < 0) {
6424c8945a0SNathan Whitehorn 		char fprefix[2];
6434c8945a0SNathan Whitehorn 		char check[2];
6444c8945a0SNathan Whitehorn 		int keynumber;
6454c8945a0SNathan Whitehorn 		if (sscanf(q, "%[Ff]%d%c", fprefix, &keynumber, check) == 2) {
6464c8945a0SNathan Whitehorn 		    curses_key = KEY_F(keynumber);
6474c8945a0SNathan Whitehorn 		    is_function = TRUE;
6484c8945a0SNathan Whitehorn 		} else {
6494c8945a0SNathan Whitehorn 		    for (xx = 0; xx < COUNT_CURSES; ++xx) {
6504c8945a0SNathan Whitehorn 			if (!dlg_strcmp(curses_names[xx].name, q)) {
6514c8945a0SNathan Whitehorn 			    curses_key = curses_names[xx].code;
652*2a3e3873SBaptiste Daroussin 			    is_function = (curses_key >= KEY_MIN);
6534c8945a0SNathan Whitehorn 			    break;
6544c8945a0SNathan Whitehorn 			}
6554c8945a0SNathan Whitehorn 		    }
6564c8945a0SNathan Whitehorn 		}
6574c8945a0SNathan Whitehorn 	    }
6584c8945a0SNathan Whitehorn 	}
6594c8945a0SNathan Whitehorn 	q = skip_white(p);
6604c8945a0SNathan Whitehorn 	p = skip_black(q);
6614c8945a0SNathan Whitehorn 	if (p != q) {
6624c8945a0SNathan Whitehorn 	    for (xx = 0; xx < COUNT_DIALOG; ++xx) {
6634c8945a0SNathan Whitehorn 		if (!dlg_strcmp(dialog_names[xx].name, q)) {
6644c8945a0SNathan Whitehorn 		    dialog_key = dialog_names[xx].code;
6654c8945a0SNathan Whitehorn 		    break;
6664c8945a0SNathan Whitehorn 		}
6674c8945a0SNathan Whitehorn 	    }
6684c8945a0SNathan Whitehorn 	}
6694c8945a0SNathan Whitehorn 	if (*widget != '\0'
6704c8945a0SNathan Whitehorn 	    && curses_key >= 0
6714c8945a0SNathan Whitehorn 	    && dialog_key >= 0
6724c8945a0SNathan Whitehorn 	    && make_binding(widget, curses_key, is_function, dialog_key) != 0) {
6734c8945a0SNathan Whitehorn 	    result = TRUE;
6744c8945a0SNathan Whitehorn 	}
6754c8945a0SNathan Whitehorn     }
6764c8945a0SNathan Whitehorn     return result;
6774c8945a0SNathan Whitehorn }
6784c8945a0SNathan Whitehorn 
6794c8945a0SNathan Whitehorn static void
6804c8945a0SNathan Whitehorn dump_curses_key(FILE *fp, int curses_key)
6814c8945a0SNathan Whitehorn {
6824c8945a0SNathan Whitehorn     if (curses_key > KEY_MIN) {
6834c8945a0SNathan Whitehorn 	unsigned n;
6844c8945a0SNathan Whitehorn 	bool found = FALSE;
6854c8945a0SNathan Whitehorn 	for (n = 0; n < COUNT_CURSES; ++n) {
6864c8945a0SNathan Whitehorn 	    if (curses_names[n].code == curses_key) {
6874c8945a0SNathan Whitehorn 		fprintf(fp, "%s", curses_names[n].name);
6884c8945a0SNathan Whitehorn 		found = TRUE;
6894c8945a0SNathan Whitehorn 		break;
6904c8945a0SNathan Whitehorn 	    }
6914c8945a0SNathan Whitehorn 	}
6924c8945a0SNathan Whitehorn 	if (!found) {
6934c8945a0SNathan Whitehorn 	    if (curses_key >= KEY_F(0)) {
6944c8945a0SNathan Whitehorn 		fprintf(fp, "F%d", curses_key - KEY_F(0));
6954c8945a0SNathan Whitehorn 	    } else {
6964c8945a0SNathan Whitehorn 		fprintf(fp, "curses%d", curses_key);
6974c8945a0SNathan Whitehorn 	    }
6984c8945a0SNathan Whitehorn 	}
6994c8945a0SNathan Whitehorn     } else if (curses_key >= 0 && curses_key < 32) {
7004c8945a0SNathan Whitehorn 	fprintf(fp, "^%c", curses_key + 64);
7014c8945a0SNathan Whitehorn     } else if (curses_key == 127) {
7024c8945a0SNathan Whitehorn 	fprintf(fp, "^?");
7034c8945a0SNathan Whitehorn     } else if (curses_key >= 128 && curses_key < 160) {
7044c8945a0SNathan Whitehorn 	fprintf(fp, "~%c", curses_key - 64);
7054c8945a0SNathan Whitehorn     } else if (curses_key == 255) {
7064c8945a0SNathan Whitehorn 	fprintf(fp, "~?");
7074c8945a0SNathan Whitehorn     } else {
7084c8945a0SNathan Whitehorn 	fprintf(fp, "\\%c", curses_key);
7094c8945a0SNathan Whitehorn     }
7104c8945a0SNathan Whitehorn }
7114c8945a0SNathan Whitehorn 
7124c8945a0SNathan Whitehorn static void
7134c8945a0SNathan Whitehorn dump_dialog_key(FILE *fp, int dialog_key)
7144c8945a0SNathan Whitehorn {
7154c8945a0SNathan Whitehorn     unsigned n;
7164c8945a0SNathan Whitehorn     bool found = FALSE;
7174c8945a0SNathan Whitehorn     for (n = 0; n < COUNT_DIALOG; ++n) {
7184c8945a0SNathan Whitehorn 	if (dialog_names[n].code == dialog_key) {
7194c8945a0SNathan Whitehorn 	    fputs(dialog_names[n].name, fp);
7204c8945a0SNathan Whitehorn 	    found = TRUE;
7214c8945a0SNathan Whitehorn 	    break;
7224c8945a0SNathan Whitehorn 	}
7234c8945a0SNathan Whitehorn     }
7244c8945a0SNathan Whitehorn     if (!found) {
7254c8945a0SNathan Whitehorn 	fprintf(fp, "dialog%d", dialog_key);
7264c8945a0SNathan Whitehorn     }
7274c8945a0SNathan Whitehorn }
7284c8945a0SNathan Whitehorn 
7294c8945a0SNathan Whitehorn static void
7304c8945a0SNathan Whitehorn dump_one_binding(FILE *fp, const char *widget, DLG_KEYS_BINDING * binding)
7314c8945a0SNathan Whitehorn {
7324c8945a0SNathan Whitehorn     fprintf(fp, "bindkey %s ", widget);
7334c8945a0SNathan Whitehorn     dump_curses_key(fp, binding->curses_key);
7344c8945a0SNathan Whitehorn     fputc(' ', fp);
7354c8945a0SNathan Whitehorn     dump_dialog_key(fp, binding->dialog_key);
7364c8945a0SNathan Whitehorn     fputc('\n', fp);
7374c8945a0SNathan Whitehorn }
7384c8945a0SNathan Whitehorn 
739*2a3e3873SBaptiste Daroussin /*
740*2a3e3873SBaptiste Daroussin  * Dump bindings for the given window.  If it is a null, then this dumps the
741*2a3e3873SBaptiste Daroussin  * initial bindings which were loaded from the rc-file that are used as
742*2a3e3873SBaptiste Daroussin  * overall defaults.
743*2a3e3873SBaptiste Daroussin  */
744*2a3e3873SBaptiste Daroussin void
745*2a3e3873SBaptiste Daroussin dlg_dump_window_keys(FILE *fp, WINDOW *win)
746*2a3e3873SBaptiste Daroussin {
747*2a3e3873SBaptiste Daroussin     if (fp != 0) {
748*2a3e3873SBaptiste Daroussin 	LIST_BINDINGS *p;
749*2a3e3873SBaptiste Daroussin 	DLG_KEYS_BINDING *q;
750*2a3e3873SBaptiste Daroussin 	const char *last = "";
751*2a3e3873SBaptiste Daroussin 
752*2a3e3873SBaptiste Daroussin 	for (p = all_bindings; p != 0; p = p->link) {
753*2a3e3873SBaptiste Daroussin 	    if (p->win == win) {
754*2a3e3873SBaptiste Daroussin 		if (dlg_strcmp(last, p->name)) {
755*2a3e3873SBaptiste Daroussin 		    fprintf(fp, "\n# key bindings for %s widgets\n",
756*2a3e3873SBaptiste Daroussin 			    !strcmp(p->name, WILDNAME) ? "all" : p->name);
757*2a3e3873SBaptiste Daroussin 		    last = p->name;
758*2a3e3873SBaptiste Daroussin 		}
759*2a3e3873SBaptiste Daroussin 		for (q = p->binding; q->is_function_key >= 0; ++q) {
760*2a3e3873SBaptiste Daroussin 		    dump_one_binding(fp, p->name, q);
761*2a3e3873SBaptiste Daroussin 		}
762*2a3e3873SBaptiste Daroussin 	    }
763*2a3e3873SBaptiste Daroussin 	}
764*2a3e3873SBaptiste Daroussin     }
765*2a3e3873SBaptiste Daroussin }
766*2a3e3873SBaptiste Daroussin 
767*2a3e3873SBaptiste Daroussin /*
768*2a3e3873SBaptiste Daroussin  * Dump all of the bindings which are not specific to a given widget, i.e.,
769*2a3e3873SBaptiste Daroussin  * the "win" member is null.
770*2a3e3873SBaptiste Daroussin  */
7714c8945a0SNathan Whitehorn void
7724c8945a0SNathan Whitehorn dlg_dump_keys(FILE *fp)
7734c8945a0SNathan Whitehorn {
774*2a3e3873SBaptiste Daroussin     if (fp != 0) {
7754c8945a0SNathan Whitehorn 	LIST_BINDINGS *p;
7764c8945a0SNathan Whitehorn 	unsigned count = 0;
7774c8945a0SNathan Whitehorn 
7784c8945a0SNathan Whitehorn 	for (p = all_bindings; p != 0; p = p->link) {
7794c8945a0SNathan Whitehorn 	    if (p->win == 0) {
7804c8945a0SNathan Whitehorn 		++count;
7814c8945a0SNathan Whitehorn 	    }
7824c8945a0SNathan Whitehorn 	}
7834c8945a0SNathan Whitehorn 	if (count != 0) {
784*2a3e3873SBaptiste Daroussin 	    dlg_dump_window_keys(fp, 0);
7854c8945a0SNathan Whitehorn 	}
7864c8945a0SNathan Whitehorn     }
7874c8945a0SNathan Whitehorn }
7884c8945a0SNathan Whitehorn #endif /* HAVE_RC_FILE */
789