xref: /freebsd/contrib/dialog/buttons.c (revision 682c9e0fed0115eb6f283e755901c0aac90e86e8)
14c8945a0SNathan Whitehorn /*
2*682c9e0fSNathan Whitehorn  *  $Id: buttons.c,v 1.86 2011/06/28 10:46:46 tom Exp $
34c8945a0SNathan Whitehorn  *
44c8945a0SNathan Whitehorn  *  buttons.c -- draw buttons, e.g., OK/Cancel
54c8945a0SNathan Whitehorn  *
67a1c0d96SNathan Whitehorn  *  Copyright 2000-2010,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 #ifdef NEED_WCHAR_H
284c8945a0SNathan Whitehorn #include <wchar.h>
294c8945a0SNathan Whitehorn #endif
304c8945a0SNathan Whitehorn 
314c8945a0SNathan Whitehorn #define MIN_BUTTON (dialog_state.visit_items ? -1 : 0)
324c8945a0SNathan Whitehorn 
334c8945a0SNathan Whitehorn static void
344c8945a0SNathan Whitehorn center_label(char *buffer, int longest, const char *label)
354c8945a0SNathan Whitehorn {
364c8945a0SNathan Whitehorn     int len = dlg_count_columns(label);
374c8945a0SNathan Whitehorn     int left = 0, right = 0;
384c8945a0SNathan Whitehorn 
394c8945a0SNathan Whitehorn     *buffer = 0;
404c8945a0SNathan Whitehorn     if (len < longest) {
414c8945a0SNathan Whitehorn 	left = (longest - len) / 2;
424c8945a0SNathan Whitehorn 	right = (longest - len - left);
434c8945a0SNathan Whitehorn 	if (left > 0)
444c8945a0SNathan Whitehorn 	    sprintf(buffer, "%*s", left, " ");
454c8945a0SNathan Whitehorn     }
464c8945a0SNathan Whitehorn     strcat(buffer, label);
474c8945a0SNathan Whitehorn     if (right > 0)
484c8945a0SNathan Whitehorn 	sprintf(buffer + strlen(buffer), "%*s", right, " ");
494c8945a0SNathan Whitehorn }
504c8945a0SNathan Whitehorn 
514c8945a0SNathan Whitehorn /*
524c8945a0SNathan Whitehorn  * Parse a multibyte character out of the string, set it past the parsed
534c8945a0SNathan Whitehorn  * character.
544c8945a0SNathan Whitehorn  */
554c8945a0SNathan Whitehorn static int
564c8945a0SNathan Whitehorn string_to_char(const char **stringp)
574c8945a0SNathan Whitehorn {
584c8945a0SNathan Whitehorn     int result;
594c8945a0SNathan Whitehorn #ifdef USE_WIDE_CURSES
604c8945a0SNathan Whitehorn     const char *string = *stringp;
614c8945a0SNathan Whitehorn     size_t have = strlen(string);
624c8945a0SNathan Whitehorn     size_t check;
634c8945a0SNathan Whitehorn     size_t len;
644c8945a0SNathan Whitehorn     wchar_t cmp2[2];
654c8945a0SNathan Whitehorn     mbstate_t state;
664c8945a0SNathan Whitehorn 
674c8945a0SNathan Whitehorn     memset(&state, 0, sizeof(state));
684c8945a0SNathan Whitehorn     len = mbrlen(string, have, &state);
694c8945a0SNathan Whitehorn     if ((int) len > 0 && len <= have) {
704c8945a0SNathan Whitehorn 	memset(&state, 0, sizeof(state));
714c8945a0SNathan Whitehorn 	memset(cmp2, 0, sizeof(cmp2));
724c8945a0SNathan Whitehorn 	check = mbrtowc(cmp2, string, len, &state);
734c8945a0SNathan Whitehorn 	if ((int) check <= 0)
744c8945a0SNathan Whitehorn 	    cmp2[0] = 0;
754c8945a0SNathan Whitehorn 	*stringp += len;
764c8945a0SNathan Whitehorn     } else {
774c8945a0SNathan Whitehorn 	cmp2[0] = UCH(*string);
784c8945a0SNathan Whitehorn 	*stringp += 1;
794c8945a0SNathan Whitehorn     }
804c8945a0SNathan Whitehorn     result = cmp2[0];
814c8945a0SNathan Whitehorn #else
824c8945a0SNathan Whitehorn     const char *string = *stringp;
834c8945a0SNathan Whitehorn     result = UCH(*string);
844c8945a0SNathan Whitehorn     *stringp += 1;
854c8945a0SNathan Whitehorn #endif
864c8945a0SNathan Whitehorn     return result;
874c8945a0SNathan Whitehorn }
884c8945a0SNathan Whitehorn 
894c8945a0SNathan Whitehorn /*
904c8945a0SNathan Whitehorn  * Print a button
914c8945a0SNathan Whitehorn  */
924c8945a0SNathan Whitehorn static void
934c8945a0SNathan Whitehorn print_button(WINDOW *win, char *label, int y, int x, int selected)
944c8945a0SNathan Whitehorn {
954c8945a0SNathan Whitehorn     int i;
964c8945a0SNathan Whitehorn     int state = 0;
974c8945a0SNathan Whitehorn     const int *indx = dlg_index_wchars(label);
984c8945a0SNathan Whitehorn     int limit = dlg_count_wchars(label);
994c8945a0SNathan Whitehorn     chtype key_attr = (selected
1004c8945a0SNathan Whitehorn 		       ? button_key_active_attr
1014c8945a0SNathan Whitehorn 		       : button_key_inactive_attr);
1024c8945a0SNathan Whitehorn     chtype label_attr = (selected
1034c8945a0SNathan Whitehorn 			 ? button_label_active_attr
1044c8945a0SNathan Whitehorn 			 : button_label_inactive_attr);
1054c8945a0SNathan Whitehorn 
1064c8945a0SNathan Whitehorn     (void) wmove(win, y, x);
1074c8945a0SNathan Whitehorn     wattrset(win, selected
1084c8945a0SNathan Whitehorn 	     ? button_active_attr
1094c8945a0SNathan Whitehorn 	     : button_inactive_attr);
1104c8945a0SNathan Whitehorn     (void) waddstr(win, "<");
1114c8945a0SNathan Whitehorn     wattrset(win, label_attr);
1124c8945a0SNathan Whitehorn     for (i = 0; i < limit; ++i) {
1134c8945a0SNathan Whitehorn 	int first = indx[i];
1144c8945a0SNathan Whitehorn 	int last = indx[i + 1];
1154c8945a0SNathan Whitehorn 
1164c8945a0SNathan Whitehorn 	switch (state) {
1174c8945a0SNathan Whitehorn 	case 0:
1184c8945a0SNathan Whitehorn #ifdef USE_WIDE_CURSES
1194c8945a0SNathan Whitehorn 	    if ((last - first) != 1) {
1204c8945a0SNathan Whitehorn 		const char *temp = (label + first);
1214c8945a0SNathan Whitehorn 		int cmp = string_to_char(&temp);
1224c8945a0SNathan Whitehorn 		if (dlg_isupper(cmp)) {
1234c8945a0SNathan Whitehorn 		    wattrset(win, key_attr);
1244c8945a0SNathan Whitehorn 		    state = 1;
1254c8945a0SNathan Whitehorn 		}
1264c8945a0SNathan Whitehorn 		break;
1274c8945a0SNathan Whitehorn 	    }
1284c8945a0SNathan Whitehorn #endif
1294c8945a0SNathan Whitehorn 	    if (dlg_isupper(UCH(label[first]))) {
1304c8945a0SNathan Whitehorn 		wattrset(win, key_attr);
1314c8945a0SNathan Whitehorn 		state = 1;
1324c8945a0SNathan Whitehorn 	    }
1334c8945a0SNathan Whitehorn 	    break;
1344c8945a0SNathan Whitehorn 	case 1:
1354c8945a0SNathan Whitehorn 	    wattrset(win, label_attr);
1364c8945a0SNathan Whitehorn 	    state = 2;
1374c8945a0SNathan Whitehorn 	    break;
1384c8945a0SNathan Whitehorn 	}
1394c8945a0SNathan Whitehorn 	waddnstr(win, label + first, last - first);
1404c8945a0SNathan Whitehorn     }
1414c8945a0SNathan Whitehorn     wattrset(win, selected
1424c8945a0SNathan Whitehorn 	     ? button_active_attr
1434c8945a0SNathan Whitehorn 	     : button_inactive_attr);
1444c8945a0SNathan Whitehorn     (void) waddstr(win, ">");
1454c8945a0SNathan Whitehorn     (void) wmove(win, y, x + ((int) strspn(label, " ")) + 1);
1464c8945a0SNathan Whitehorn }
1474c8945a0SNathan Whitehorn 
1484c8945a0SNathan Whitehorn /*
1494c8945a0SNathan Whitehorn  * Count the buttons in the list.
1504c8945a0SNathan Whitehorn  */
1514c8945a0SNathan Whitehorn int
1524c8945a0SNathan Whitehorn dlg_button_count(const char **labels)
1534c8945a0SNathan Whitehorn {
1544c8945a0SNathan Whitehorn     int result = 0;
1554c8945a0SNathan Whitehorn     while (*labels++ != 0)
1564c8945a0SNathan Whitehorn 	++result;
1574c8945a0SNathan Whitehorn     return result;
1584c8945a0SNathan Whitehorn }
1594c8945a0SNathan Whitehorn 
1604c8945a0SNathan Whitehorn /*
1614c8945a0SNathan Whitehorn  * Compute the size of the button array in columns.  Return the total number of
1624c8945a0SNathan Whitehorn  * columns in *length, and the longest button's columns in *longest
1634c8945a0SNathan Whitehorn  */
1644c8945a0SNathan Whitehorn void
1654c8945a0SNathan Whitehorn dlg_button_sizes(const char **labels,
1664c8945a0SNathan Whitehorn 		 int vertical,
1674c8945a0SNathan Whitehorn 		 int *longest,
1684c8945a0SNathan Whitehorn 		 int *length)
1694c8945a0SNathan Whitehorn {
1704c8945a0SNathan Whitehorn     int n;
1714c8945a0SNathan Whitehorn 
1724c8945a0SNathan Whitehorn     *length = 0;
1734c8945a0SNathan Whitehorn     *longest = 0;
1744c8945a0SNathan Whitehorn     for (n = 0; labels[n] != 0; n++) {
1754c8945a0SNathan Whitehorn 	if (vertical) {
1764c8945a0SNathan Whitehorn 	    *length += 1;
1774c8945a0SNathan Whitehorn 	    *longest = 1;
1784c8945a0SNathan Whitehorn 	} else {
1794c8945a0SNathan Whitehorn 	    int len = dlg_count_columns(labels[n]);
1804c8945a0SNathan Whitehorn 	    if (len > *longest)
1814c8945a0SNathan Whitehorn 		*longest = len;
1824c8945a0SNathan Whitehorn 	    *length += len;
1834c8945a0SNathan Whitehorn 	}
1844c8945a0SNathan Whitehorn     }
1854c8945a0SNathan Whitehorn     /*
1864c8945a0SNathan Whitehorn      * If we can, make all of the buttons the same size.  This is only optional
1874c8945a0SNathan Whitehorn      * for buttons laid out horizontally.
1884c8945a0SNathan Whitehorn      */
1894c8945a0SNathan Whitehorn     if (*longest < 6 - (*longest & 1))
1904c8945a0SNathan Whitehorn 	*longest = 6 - (*longest & 1);
1914c8945a0SNathan Whitehorn     if (!vertical)
1924c8945a0SNathan Whitehorn 	*length = *longest * n;
1934c8945a0SNathan Whitehorn }
1944c8945a0SNathan Whitehorn 
1954c8945a0SNathan Whitehorn /*
1964c8945a0SNathan Whitehorn  * Compute the size of the button array.
1974c8945a0SNathan Whitehorn  */
1984c8945a0SNathan Whitehorn int
1994c8945a0SNathan Whitehorn dlg_button_x_step(const char **labels, int limit, int *gap, int *margin, int *step)
2004c8945a0SNathan Whitehorn {
2014c8945a0SNathan Whitehorn     int count = dlg_button_count(labels);
2024c8945a0SNathan Whitehorn     int longest;
2034c8945a0SNathan Whitehorn     int length;
2044c8945a0SNathan Whitehorn     int unused;
2054c8945a0SNathan Whitehorn     int used;
2064c8945a0SNathan Whitehorn 
2074c8945a0SNathan Whitehorn     if (count == 0)
2084c8945a0SNathan Whitehorn 	return 0;
2094c8945a0SNathan Whitehorn     dlg_button_sizes(labels, FALSE, &longest, &length);
2104c8945a0SNathan Whitehorn     used = (length + (count * 2));
2114c8945a0SNathan Whitehorn     unused = limit - used;
2124c8945a0SNathan Whitehorn 
2134c8945a0SNathan Whitehorn     if ((*gap = unused / (count + 3)) <= 0) {
2144c8945a0SNathan Whitehorn 	if ((*gap = unused / (count + 1)) <= 0)
2154c8945a0SNathan Whitehorn 	    *gap = 1;
2164c8945a0SNathan Whitehorn 	*margin = *gap;
2174c8945a0SNathan Whitehorn     } else {
2184c8945a0SNathan Whitehorn 	*margin = *gap * 2;
2194c8945a0SNathan Whitehorn     }
2204c8945a0SNathan Whitehorn     *step = *gap + (used + count - 1) / count;
2214c8945a0SNathan Whitehorn     return (*gap > 0) && (unused >= 0);
2224c8945a0SNathan Whitehorn }
2234c8945a0SNathan Whitehorn 
2244c8945a0SNathan Whitehorn /*
2254c8945a0SNathan Whitehorn  * Make sure there is enough space for the buttons
2264c8945a0SNathan Whitehorn  */
2274c8945a0SNathan Whitehorn void
2284c8945a0SNathan Whitehorn dlg_button_layout(const char **labels, int *limit)
2294c8945a0SNathan Whitehorn {
2304c8945a0SNathan Whitehorn     int width = 1;
2314c8945a0SNathan Whitehorn     int gap, margin, step;
2324c8945a0SNathan Whitehorn 
2334c8945a0SNathan Whitehorn     if (labels != 0 && dlg_button_count(labels)) {
2344c8945a0SNathan Whitehorn 	while (!dlg_button_x_step(labels, width, &gap, &margin, &step))
2354c8945a0SNathan Whitehorn 	    ++width;
2364c8945a0SNathan Whitehorn 	width += (4 * MARGIN);
2374c8945a0SNathan Whitehorn 	if (width > COLS)
2384c8945a0SNathan Whitehorn 	    width = COLS;
2394c8945a0SNathan Whitehorn 	if (width > *limit)
2404c8945a0SNathan Whitehorn 	    *limit = width;
2414c8945a0SNathan Whitehorn     }
2424c8945a0SNathan Whitehorn }
2434c8945a0SNathan Whitehorn 
2444c8945a0SNathan Whitehorn /*
2454c8945a0SNathan Whitehorn  * Print a list of buttons at the given position.
2464c8945a0SNathan Whitehorn  */
2474c8945a0SNathan Whitehorn void
2484c8945a0SNathan Whitehorn dlg_draw_buttons(WINDOW *win,
2494c8945a0SNathan Whitehorn 		 int y, int x,
2504c8945a0SNathan Whitehorn 		 const char **labels,
2514c8945a0SNathan Whitehorn 		 int selected,
2524c8945a0SNathan Whitehorn 		 int vertical,
2534c8945a0SNathan Whitehorn 		 int limit)
2544c8945a0SNathan Whitehorn {
2557a1c0d96SNathan Whitehorn     chtype save = dlg_get_attrs(win);
2564c8945a0SNathan Whitehorn     int n;
2574c8945a0SNathan Whitehorn     int step = 0;
2584c8945a0SNathan Whitehorn     int length;
2594c8945a0SNathan Whitehorn     int longest;
2604c8945a0SNathan Whitehorn     int final_x;
2614c8945a0SNathan Whitehorn     int final_y;
2624c8945a0SNathan Whitehorn     int gap;
2634c8945a0SNathan Whitehorn     int margin;
2644c8945a0SNathan Whitehorn     size_t need;
2654c8945a0SNathan Whitehorn     char *buffer;
2664c8945a0SNathan Whitehorn 
2674c8945a0SNathan Whitehorn     dlg_mouse_setbase(getbegx(win), getbegy(win));
2684c8945a0SNathan Whitehorn 
2694c8945a0SNathan Whitehorn     getyx(win, final_y, final_x);
2704c8945a0SNathan Whitehorn 
2714c8945a0SNathan Whitehorn     dlg_button_sizes(labels, vertical, &longest, &length);
2724c8945a0SNathan Whitehorn 
2734c8945a0SNathan Whitehorn     if (vertical) {
2744c8945a0SNathan Whitehorn 	y += 1;
2754c8945a0SNathan Whitehorn 	step = 1;
2764c8945a0SNathan Whitehorn     } else {
2774c8945a0SNathan Whitehorn 	dlg_button_x_step(labels, limit, &gap, &margin, &step);
2784c8945a0SNathan Whitehorn 	x += margin;
2794c8945a0SNathan Whitehorn     }
2804c8945a0SNathan Whitehorn 
2814c8945a0SNathan Whitehorn     /*
2824c8945a0SNathan Whitehorn      * Allocate a buffer big enough for any label.
2834c8945a0SNathan Whitehorn      */
2844c8945a0SNathan Whitehorn     need = (size_t) longest;
2854c8945a0SNathan Whitehorn     for (n = 0; labels[n] != 0; ++n) {
2864c8945a0SNathan Whitehorn 	need += strlen(labels[n]) + 1;
2874c8945a0SNathan Whitehorn     }
2884c8945a0SNathan Whitehorn     buffer = dlg_malloc(char, need);
2894c8945a0SNathan Whitehorn     assert_ptr(buffer, "dlg_draw_buttons");
2904c8945a0SNathan Whitehorn 
2914c8945a0SNathan Whitehorn     /*
2924c8945a0SNathan Whitehorn      * Draw the labels.
2934c8945a0SNathan Whitehorn      */
2944c8945a0SNathan Whitehorn     for (n = 0; labels[n] != 0; n++) {
2954c8945a0SNathan Whitehorn 	center_label(buffer, longest, labels[n]);
2964c8945a0SNathan Whitehorn 	mouse_mkbutton(y, x, dlg_count_columns(buffer), n);
2974c8945a0SNathan Whitehorn 	print_button(win, buffer, y, x,
2984c8945a0SNathan Whitehorn 		     (selected == n) || (n == 0 && selected < 0));
2994c8945a0SNathan Whitehorn 	if (selected == n)
3004c8945a0SNathan Whitehorn 	    getyx(win, final_y, final_x);
3014c8945a0SNathan Whitehorn 
3024c8945a0SNathan Whitehorn 	if (vertical) {
3034c8945a0SNathan Whitehorn 	    if ((y += step) > limit)
3044c8945a0SNathan Whitehorn 		break;
3054c8945a0SNathan Whitehorn 	} else {
3064c8945a0SNathan Whitehorn 	    if ((x += step) > limit)
3074c8945a0SNathan Whitehorn 		break;
3084c8945a0SNathan Whitehorn 	}
3094c8945a0SNathan Whitehorn     }
3104c8945a0SNathan Whitehorn     (void) wmove(win, final_y, final_x);
3114c8945a0SNathan Whitehorn     wrefresh(win);
3124c8945a0SNathan Whitehorn     free(buffer);
3134c8945a0SNathan Whitehorn     wattrset(win, save);
3144c8945a0SNathan Whitehorn }
3154c8945a0SNathan Whitehorn 
3164c8945a0SNathan Whitehorn /*
3174c8945a0SNathan Whitehorn  * Match a given character against the beginning of the string, ignoring case
3184c8945a0SNathan Whitehorn  * of the given character.  The matching string must begin with an uppercase
3194c8945a0SNathan Whitehorn  * character.
3204c8945a0SNathan Whitehorn  */
3214c8945a0SNathan Whitehorn int
3224c8945a0SNathan Whitehorn dlg_match_char(int ch, const char *string)
3234c8945a0SNathan Whitehorn {
3244c8945a0SNathan Whitehorn     if (string != 0) {
3254c8945a0SNathan Whitehorn 	int cmp2 = string_to_char(&string);
3264c8945a0SNathan Whitehorn #ifdef USE_WIDE_CURSES
3274c8945a0SNathan Whitehorn 	wint_t cmp1 = dlg_toupper(ch);
3284c8945a0SNathan Whitehorn 	if (cmp2 != 0 && (wchar_t) cmp1 == (wchar_t) dlg_toupper(cmp2)) {
3294c8945a0SNathan Whitehorn 	    return TRUE;
3304c8945a0SNathan Whitehorn 	}
3314c8945a0SNathan Whitehorn #else
3324c8945a0SNathan Whitehorn 	if (ch > 0 && ch < 256) {
3334c8945a0SNathan Whitehorn 	    if (dlg_toupper(ch) == dlg_toupper(cmp2))
3344c8945a0SNathan Whitehorn 		return TRUE;
3354c8945a0SNathan Whitehorn 	}
3364c8945a0SNathan Whitehorn #endif
3374c8945a0SNathan Whitehorn     }
3384c8945a0SNathan Whitehorn     return FALSE;
3394c8945a0SNathan Whitehorn }
3404c8945a0SNathan Whitehorn 
3414c8945a0SNathan Whitehorn /*
3424c8945a0SNathan Whitehorn  * Find the first uppercase character in the label, which we may use for an
3434c8945a0SNathan Whitehorn  * abbreviation.
3444c8945a0SNathan Whitehorn  */
3454c8945a0SNathan Whitehorn int
3464c8945a0SNathan Whitehorn dlg_button_to_char(const char *label)
3474c8945a0SNathan Whitehorn {
3484c8945a0SNathan Whitehorn     int cmp = -1;
3494c8945a0SNathan Whitehorn 
3504c8945a0SNathan Whitehorn     while (*label != 0) {
3514c8945a0SNathan Whitehorn 	cmp = string_to_char(&label);
3524c8945a0SNathan Whitehorn 	if (dlg_isupper(cmp)) {
3534c8945a0SNathan Whitehorn 	    break;
3544c8945a0SNathan Whitehorn 	}
3554c8945a0SNathan Whitehorn     }
3564c8945a0SNathan Whitehorn     return cmp;
3574c8945a0SNathan Whitehorn }
3584c8945a0SNathan Whitehorn 
3594c8945a0SNathan Whitehorn /*
3604c8945a0SNathan Whitehorn  * Given a list of button labels, and a character which may be the abbreviation
3614c8945a0SNathan Whitehorn  * for one, find it, if it exists.  An abbreviation will be the first character
3624c8945a0SNathan Whitehorn  * which happens to be capitalized in the label.
3634c8945a0SNathan Whitehorn  */
3644c8945a0SNathan Whitehorn int
3654c8945a0SNathan Whitehorn dlg_char_to_button(int ch, const char **labels)
3664c8945a0SNathan Whitehorn {
3674c8945a0SNathan Whitehorn     if (labels != 0) {
3684c8945a0SNathan Whitehorn 	int j;
3694c8945a0SNathan Whitehorn 
3704c8945a0SNathan Whitehorn 	ch = (int) dlg_toupper(dlg_last_getc());
3714c8945a0SNathan Whitehorn 	for (j = 0; labels[j] != 0; ++j) {
3724c8945a0SNathan Whitehorn 	    int cmp = dlg_button_to_char(labels[j]);
3734c8945a0SNathan Whitehorn 	    if (ch == cmp) {
3744c8945a0SNathan Whitehorn 		dlg_flush_getc();
3754c8945a0SNathan Whitehorn 		return j;
3764c8945a0SNathan Whitehorn 	    }
3774c8945a0SNathan Whitehorn 	}
3784c8945a0SNathan Whitehorn     }
3794c8945a0SNathan Whitehorn     return DLG_EXIT_UNKNOWN;
3804c8945a0SNathan Whitehorn }
3814c8945a0SNathan Whitehorn 
3824c8945a0SNathan Whitehorn static const char *
3834c8945a0SNathan Whitehorn my_yes_label(void)
3844c8945a0SNathan Whitehorn {
3854c8945a0SNathan Whitehorn     return (dialog_vars.yes_label != NULL)
3864c8945a0SNathan Whitehorn 	? dialog_vars.yes_label
3874c8945a0SNathan Whitehorn 	: _("Yes");
3884c8945a0SNathan Whitehorn }
3894c8945a0SNathan Whitehorn 
3904c8945a0SNathan Whitehorn static const char *
3914c8945a0SNathan Whitehorn my_no_label(void)
3924c8945a0SNathan Whitehorn {
3934c8945a0SNathan Whitehorn     return (dialog_vars.no_label != NULL)
3944c8945a0SNathan Whitehorn 	? dialog_vars.no_label
3954c8945a0SNathan Whitehorn 	: _("No");
3964c8945a0SNathan Whitehorn }
3974c8945a0SNathan Whitehorn 
3984c8945a0SNathan Whitehorn static const char *
3994c8945a0SNathan Whitehorn my_ok_label(void)
4004c8945a0SNathan Whitehorn {
4014c8945a0SNathan Whitehorn     return (dialog_vars.ok_label != NULL)
4024c8945a0SNathan Whitehorn 	? dialog_vars.ok_label
4034c8945a0SNathan Whitehorn 	: _("OK");
4044c8945a0SNathan Whitehorn }
4054c8945a0SNathan Whitehorn 
4064c8945a0SNathan Whitehorn static const char *
4074c8945a0SNathan Whitehorn my_cancel_label(void)
4084c8945a0SNathan Whitehorn {
4094c8945a0SNathan Whitehorn     return (dialog_vars.cancel_label != NULL)
4104c8945a0SNathan Whitehorn 	? dialog_vars.cancel_label
4114c8945a0SNathan Whitehorn 	: _("Cancel");
4124c8945a0SNathan Whitehorn }
4134c8945a0SNathan Whitehorn 
4144c8945a0SNathan Whitehorn static const char *
4154c8945a0SNathan Whitehorn my_exit_label(void)
4164c8945a0SNathan Whitehorn {
4174c8945a0SNathan Whitehorn     return (dialog_vars.exit_label != NULL)
4184c8945a0SNathan Whitehorn 	? dialog_vars.exit_label
4194c8945a0SNathan Whitehorn 	: _("EXIT");
4204c8945a0SNathan Whitehorn }
4214c8945a0SNathan Whitehorn 
4224c8945a0SNathan Whitehorn static const char *
4234c8945a0SNathan Whitehorn my_extra_label(void)
4244c8945a0SNathan Whitehorn {
4254c8945a0SNathan Whitehorn     return (dialog_vars.extra_label != NULL)
4264c8945a0SNathan Whitehorn 	? dialog_vars.extra_label
4274c8945a0SNathan Whitehorn 	: _("Extra");
4284c8945a0SNathan Whitehorn }
4294c8945a0SNathan Whitehorn 
4304c8945a0SNathan Whitehorn static const char *
4314c8945a0SNathan Whitehorn my_help_label(void)
4324c8945a0SNathan Whitehorn {
4334c8945a0SNathan Whitehorn     return (dialog_vars.help_label != NULL)
4344c8945a0SNathan Whitehorn 	? dialog_vars.help_label
4354c8945a0SNathan Whitehorn 	: _("Help");
4364c8945a0SNathan Whitehorn }
4374c8945a0SNathan Whitehorn 
4384c8945a0SNathan Whitehorn /*
4394c8945a0SNathan Whitehorn  * Return a list of button labels.
4404c8945a0SNathan Whitehorn  */
4414c8945a0SNathan Whitehorn const char **
4424c8945a0SNathan Whitehorn dlg_exit_label(void)
4434c8945a0SNathan Whitehorn {
4444c8945a0SNathan Whitehorn     const char **result;
445*682c9e0fSNathan Whitehorn     DIALOG_VARS save;
4464c8945a0SNathan Whitehorn 
4474c8945a0SNathan Whitehorn     if (dialog_vars.extra_button) {
448*682c9e0fSNathan Whitehorn 	dlg_save_vars(&save);
449*682c9e0fSNathan Whitehorn 	dialog_vars.nocancel = TRUE;
4504c8945a0SNathan Whitehorn 	result = dlg_ok_labels();
451*682c9e0fSNathan Whitehorn 	dlg_restore_vars(&save);
4524c8945a0SNathan Whitehorn     } else {
4534c8945a0SNathan Whitehorn 	static const char *labels[3];
4544c8945a0SNathan Whitehorn 	int n = 0;
4554c8945a0SNathan Whitehorn 
456*682c9e0fSNathan Whitehorn 	if (!dialog_vars.nook)
4574c8945a0SNathan Whitehorn 	    labels[n++] = my_exit_label();
4584c8945a0SNathan Whitehorn 	if (dialog_vars.help_button)
4594c8945a0SNathan Whitehorn 	    labels[n++] = my_help_label();
460*682c9e0fSNathan Whitehorn 	if (n == 0)
461*682c9e0fSNathan Whitehorn 	    labels[n++] = my_exit_label();
4624c8945a0SNathan Whitehorn 	labels[n] = 0;
4634c8945a0SNathan Whitehorn 
4644c8945a0SNathan Whitehorn 	result = labels;
4654c8945a0SNathan Whitehorn     }
4664c8945a0SNathan Whitehorn     return result;
4674c8945a0SNathan Whitehorn }
4684c8945a0SNathan Whitehorn 
4694c8945a0SNathan Whitehorn /*
4704c8945a0SNathan Whitehorn  * Map the given button index for dlg_exit_label() into our exit-code.
4714c8945a0SNathan Whitehorn  */
4724c8945a0SNathan Whitehorn int
4734c8945a0SNathan Whitehorn dlg_exit_buttoncode(int button)
4744c8945a0SNathan Whitehorn {
475*682c9e0fSNathan Whitehorn     int result;
476*682c9e0fSNathan Whitehorn     DIALOG_VARS save;
477*682c9e0fSNathan Whitehorn 
478*682c9e0fSNathan Whitehorn     dlg_save_vars(&save);
479*682c9e0fSNathan Whitehorn     dialog_vars.nocancel = TRUE;
480*682c9e0fSNathan Whitehorn 
481*682c9e0fSNathan Whitehorn     result = dlg_ok_buttoncode(button);
482*682c9e0fSNathan Whitehorn 
483*682c9e0fSNathan Whitehorn     dlg_restore_vars(&save);
484*682c9e0fSNathan Whitehorn 
485*682c9e0fSNathan Whitehorn     return result;
4864c8945a0SNathan Whitehorn }
4874c8945a0SNathan Whitehorn 
4884c8945a0SNathan Whitehorn const char **
4894c8945a0SNathan Whitehorn dlg_ok_label(void)
4904c8945a0SNathan Whitehorn {
4914c8945a0SNathan Whitehorn     static const char *labels[3];
4924c8945a0SNathan Whitehorn     int n = 0;
4934c8945a0SNathan Whitehorn 
4944c8945a0SNathan Whitehorn     labels[n++] = my_ok_label();
4954c8945a0SNathan Whitehorn     if (dialog_vars.help_button)
4964c8945a0SNathan Whitehorn 	labels[n++] = my_help_label();
4974c8945a0SNathan Whitehorn     labels[n] = 0;
4984c8945a0SNathan Whitehorn     return labels;
4994c8945a0SNathan Whitehorn }
5004c8945a0SNathan Whitehorn 
5014c8945a0SNathan Whitehorn /*
5024c8945a0SNathan Whitehorn  * Return a list of button labels for the OK/Cancel group.
5034c8945a0SNathan Whitehorn  */
5044c8945a0SNathan Whitehorn const char **
5054c8945a0SNathan Whitehorn dlg_ok_labels(void)
5064c8945a0SNathan Whitehorn {
5074c8945a0SNathan Whitehorn     static const char *labels[5];
5084c8945a0SNathan Whitehorn     int n = 0;
5094c8945a0SNathan Whitehorn 
5104c8945a0SNathan Whitehorn     if (!dialog_vars.nook)
5114c8945a0SNathan Whitehorn 	labels[n++] = my_ok_label();
5124c8945a0SNathan Whitehorn     if (dialog_vars.extra_button)
5134c8945a0SNathan Whitehorn 	labels[n++] = my_extra_label();
5144c8945a0SNathan Whitehorn     if (!dialog_vars.nocancel)
5154c8945a0SNathan Whitehorn 	labels[n++] = my_cancel_label();
5164c8945a0SNathan Whitehorn     if (dialog_vars.help_button)
5174c8945a0SNathan Whitehorn 	labels[n++] = my_help_label();
5184c8945a0SNathan Whitehorn     labels[n] = 0;
5194c8945a0SNathan Whitehorn     return labels;
5204c8945a0SNathan Whitehorn }
5214c8945a0SNathan Whitehorn 
5224c8945a0SNathan Whitehorn /*
5234c8945a0SNathan Whitehorn  * Map the given button index for dlg_ok_labels() into our exit-code
5244c8945a0SNathan Whitehorn  */
5254c8945a0SNathan Whitehorn int
5264c8945a0SNathan Whitehorn dlg_ok_buttoncode(int button)
5274c8945a0SNathan Whitehorn {
5284c8945a0SNathan Whitehorn     int result = DLG_EXIT_ERROR;
5294c8945a0SNathan Whitehorn     int n = !dialog_vars.nook;
5304c8945a0SNathan Whitehorn 
5314c8945a0SNathan Whitehorn     if (!dialog_vars.nook && (button <= 0)) {
5324c8945a0SNathan Whitehorn 	result = DLG_EXIT_OK;
5334c8945a0SNathan Whitehorn     } else if (dialog_vars.extra_button && (button == n++)) {
5344c8945a0SNathan Whitehorn 	result = DLG_EXIT_EXTRA;
5354c8945a0SNathan Whitehorn     } else if (!dialog_vars.nocancel && (button == n++)) {
5364c8945a0SNathan Whitehorn 	result = DLG_EXIT_CANCEL;
5374c8945a0SNathan Whitehorn     } else if (dialog_vars.help_button && (button == n)) {
5384c8945a0SNathan Whitehorn 	result = DLG_EXIT_HELP;
5394c8945a0SNathan Whitehorn     }
5404c8945a0SNathan Whitehorn     return result;
5414c8945a0SNathan Whitehorn }
5424c8945a0SNathan Whitehorn 
5434c8945a0SNathan Whitehorn /*
5444c8945a0SNathan Whitehorn  * Given that we're using dlg_ok_labels() to list buttons, find the next index
5454c8945a0SNathan Whitehorn  * in the list of buttons.  The 'extra' parameter if negative provides a way to
5464c8945a0SNathan Whitehorn  * enumerate extra active areas on the widget.
5474c8945a0SNathan Whitehorn  */
5484c8945a0SNathan Whitehorn int
5494c8945a0SNathan Whitehorn dlg_next_ok_buttonindex(int current, int extra)
5504c8945a0SNathan Whitehorn {
5514c8945a0SNathan Whitehorn     int result = current + 1;
5524c8945a0SNathan Whitehorn 
5534c8945a0SNathan Whitehorn     if (current >= 0
5544c8945a0SNathan Whitehorn 	&& dlg_ok_buttoncode(result) < 0)
5554c8945a0SNathan Whitehorn 	result = extra;
5564c8945a0SNathan Whitehorn     return result;
5574c8945a0SNathan Whitehorn }
5584c8945a0SNathan Whitehorn 
5594c8945a0SNathan Whitehorn /*
5604c8945a0SNathan Whitehorn  * Similarly, find the previous button index.
5614c8945a0SNathan Whitehorn  */
5624c8945a0SNathan Whitehorn int
5634c8945a0SNathan Whitehorn dlg_prev_ok_buttonindex(int current, int extra)
5644c8945a0SNathan Whitehorn {
5654c8945a0SNathan Whitehorn     int result = current - 1;
5664c8945a0SNathan Whitehorn 
5674c8945a0SNathan Whitehorn     if (result < extra) {
5684c8945a0SNathan Whitehorn 	for (result = 0; dlg_ok_buttoncode(result + 1) >= 0; ++result) {
5694c8945a0SNathan Whitehorn 	    ;
5704c8945a0SNathan Whitehorn 	}
5714c8945a0SNathan Whitehorn     }
5724c8945a0SNathan Whitehorn     return result;
5734c8945a0SNathan Whitehorn }
5744c8945a0SNathan Whitehorn 
5754c8945a0SNathan Whitehorn /*
5764c8945a0SNathan Whitehorn  * Find the button-index for the "OK" or "Cancel" button, according to
5774c8945a0SNathan Whitehorn  * whether --defaultno is given.  If --nocancel was given, we always return
5784c8945a0SNathan Whitehorn  * the index for "OK".
5794c8945a0SNathan Whitehorn  */
5804c8945a0SNathan Whitehorn int
5814c8945a0SNathan Whitehorn dlg_defaultno_button(void)
5824c8945a0SNathan Whitehorn {
5834c8945a0SNathan Whitehorn     int result = 0;
5844c8945a0SNathan Whitehorn 
5854c8945a0SNathan Whitehorn     if (dialog_vars.defaultno && !dialog_vars.nocancel) {
5864c8945a0SNathan Whitehorn 	while (dlg_ok_buttoncode(result) != DLG_EXIT_CANCEL)
5874c8945a0SNathan Whitehorn 	    ++result;
5884c8945a0SNathan Whitehorn     }
5894c8945a0SNathan Whitehorn     return result;
5904c8945a0SNathan Whitehorn }
5914c8945a0SNathan Whitehorn 
5924c8945a0SNathan Whitehorn /*
5934c8945a0SNathan Whitehorn  * Return a list of buttons for Yes/No labels.
5944c8945a0SNathan Whitehorn  */
5954c8945a0SNathan Whitehorn const char **
5964c8945a0SNathan Whitehorn dlg_yes_labels(void)
5974c8945a0SNathan Whitehorn {
5984c8945a0SNathan Whitehorn     const char **result;
5994c8945a0SNathan Whitehorn 
6004c8945a0SNathan Whitehorn     if (dialog_vars.extra_button) {
6014c8945a0SNathan Whitehorn 	result = dlg_ok_labels();
6024c8945a0SNathan Whitehorn     } else {
6034c8945a0SNathan Whitehorn 	static const char *labels[4];
6044c8945a0SNathan Whitehorn 	int n = 0;
6054c8945a0SNathan Whitehorn 
6064c8945a0SNathan Whitehorn 	labels[n++] = my_yes_label();
6074c8945a0SNathan Whitehorn 	labels[n++] = my_no_label();
6084c8945a0SNathan Whitehorn 	if (dialog_vars.help_button)
6094c8945a0SNathan Whitehorn 	    labels[n++] = my_help_label();
6104c8945a0SNathan Whitehorn 	labels[n] = 0;
6114c8945a0SNathan Whitehorn 
6124c8945a0SNathan Whitehorn 	result = labels;
6134c8945a0SNathan Whitehorn     }
6144c8945a0SNathan Whitehorn 
6154c8945a0SNathan Whitehorn     return result;
6164c8945a0SNathan Whitehorn }
6174c8945a0SNathan Whitehorn 
6184c8945a0SNathan Whitehorn /*
6194c8945a0SNathan Whitehorn  * Map the given button index for dlg_yes_labels() into our exit-code.
6204c8945a0SNathan Whitehorn  */
6214c8945a0SNathan Whitehorn int
6224c8945a0SNathan Whitehorn dlg_yes_buttoncode(int button)
6234c8945a0SNathan Whitehorn {
6244c8945a0SNathan Whitehorn     int result = DLG_EXIT_ERROR;
6254c8945a0SNathan Whitehorn 
6264c8945a0SNathan Whitehorn     if (dialog_vars.extra_button) {
6274c8945a0SNathan Whitehorn 	result = dlg_ok_buttoncode(button);
6284c8945a0SNathan Whitehorn     } else if (button == 0) {
6294c8945a0SNathan Whitehorn 	result = DLG_EXIT_OK;
6304c8945a0SNathan Whitehorn     } else if (button == 1) {
6314c8945a0SNathan Whitehorn 	result = DLG_EXIT_CANCEL;
6324c8945a0SNathan Whitehorn     } else if (button == 2 && dialog_vars.help_button) {
6334c8945a0SNathan Whitehorn 	result = DLG_EXIT_HELP;
6344c8945a0SNathan Whitehorn     }
6354c8945a0SNathan Whitehorn 
6364c8945a0SNathan Whitehorn     return result;
6374c8945a0SNathan Whitehorn }
6384c8945a0SNathan Whitehorn 
6394c8945a0SNathan Whitehorn /*
6404c8945a0SNathan Whitehorn  * Return the next index in labels[];
6414c8945a0SNathan Whitehorn  */
6424c8945a0SNathan Whitehorn int
6434c8945a0SNathan Whitehorn dlg_next_button(const char **labels, int button)
6444c8945a0SNathan Whitehorn {
6454c8945a0SNathan Whitehorn     if (labels[button + 1] != 0)
6464c8945a0SNathan Whitehorn 	++button;
6474c8945a0SNathan Whitehorn     else
6484c8945a0SNathan Whitehorn 	button = MIN_BUTTON;
6494c8945a0SNathan Whitehorn     return button;
6504c8945a0SNathan Whitehorn }
6514c8945a0SNathan Whitehorn 
6524c8945a0SNathan Whitehorn /*
6534c8945a0SNathan Whitehorn  * Return the previous index in labels[];
6544c8945a0SNathan Whitehorn  */
6554c8945a0SNathan Whitehorn int
6564c8945a0SNathan Whitehorn dlg_prev_button(const char **labels, int button)
6574c8945a0SNathan Whitehorn {
6584c8945a0SNathan Whitehorn     if (button > MIN_BUTTON)
6594c8945a0SNathan Whitehorn 	--button;
6604c8945a0SNathan Whitehorn     else {
6614c8945a0SNathan Whitehorn 	while (labels[button + 1] != 0)
6624c8945a0SNathan Whitehorn 	    ++button;
6634c8945a0SNathan Whitehorn     }
6644c8945a0SNathan Whitehorn     return button;
6654c8945a0SNathan Whitehorn }
666