14c8945a0SNathan Whitehorn /* 2*2a3e3873SBaptiste Daroussin * $Id: buttons.c,v 1.94 2012/12/30 20:51:01 tom Exp $ 34c8945a0SNathan Whitehorn * 44c8945a0SNathan Whitehorn * buttons.c -- draw buttons, e.g., OK/Cancel 54c8945a0SNathan Whitehorn * 6*2a3e3873SBaptiste Daroussin * Copyright 2000-2011,2012 Thomas E. Dickey 74c8945a0SNathan Whitehorn * 84c8945a0SNathan Whitehorn * This program is free software; you can redistribute it and/or modify 94c8945a0SNathan Whitehorn * it under the terms of the GNU Lesser General Public License, version 2.1 104c8945a0SNathan Whitehorn * as published by the Free Software Foundation. 114c8945a0SNathan Whitehorn * 124c8945a0SNathan Whitehorn * This program is distributed in the hope that it will be useful, but 134c8945a0SNathan Whitehorn * WITHOUT ANY WARRANTY; without even the implied warranty of 144c8945a0SNathan Whitehorn * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 154c8945a0SNathan Whitehorn * Lesser General Public License for more details. 164c8945a0SNathan Whitehorn * 174c8945a0SNathan Whitehorn * You should have received a copy of the GNU Lesser General Public 184c8945a0SNathan Whitehorn * License along with this program; if not, write to 194c8945a0SNathan Whitehorn * Free Software Foundation, Inc. 204c8945a0SNathan Whitehorn * 51 Franklin St., Fifth Floor 214c8945a0SNathan Whitehorn * Boston, MA 02110, USA. 224c8945a0SNathan Whitehorn */ 234c8945a0SNathan Whitehorn 244c8945a0SNathan Whitehorn #include <dialog.h> 254c8945a0SNathan Whitehorn #include <dlg_keys.h> 264c8945a0SNathan Whitehorn 274c8945a0SNathan Whitehorn #ifdef NEED_WCHAR_H 284c8945a0SNathan Whitehorn #include <wchar.h> 294c8945a0SNathan Whitehorn #endif 304c8945a0SNathan Whitehorn 31*2a3e3873SBaptiste Daroussin #define MIN_BUTTON (-dialog_state.visit_cols) 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 89*2a3e3873SBaptiste Daroussin static size_t 90*2a3e3873SBaptiste Daroussin count_labels(const char **labels) 91*2a3e3873SBaptiste Daroussin { 92*2a3e3873SBaptiste Daroussin size_t result = 0; 93*2a3e3873SBaptiste Daroussin if (labels != 0) { 94*2a3e3873SBaptiste Daroussin while (*labels++ != 0) { 95*2a3e3873SBaptiste Daroussin ++result; 96*2a3e3873SBaptiste Daroussin } 97*2a3e3873SBaptiste Daroussin } 98*2a3e3873SBaptiste Daroussin return result; 99*2a3e3873SBaptiste Daroussin } 100*2a3e3873SBaptiste Daroussin 101*2a3e3873SBaptiste Daroussin /* 102*2a3e3873SBaptiste Daroussin * Check if the latest key should be added to the hotkey list. 103*2a3e3873SBaptiste Daroussin */ 104*2a3e3873SBaptiste Daroussin static int 105*2a3e3873SBaptiste Daroussin was_hotkey(int this_key, int *used_keys, size_t next) 106*2a3e3873SBaptiste Daroussin { 107*2a3e3873SBaptiste Daroussin int result = FALSE; 108*2a3e3873SBaptiste Daroussin 109*2a3e3873SBaptiste Daroussin if (next != 0) { 110*2a3e3873SBaptiste Daroussin size_t n; 111*2a3e3873SBaptiste Daroussin for (n = 0; n < next; ++n) { 112*2a3e3873SBaptiste Daroussin if (used_keys[n] == this_key) { 113*2a3e3873SBaptiste Daroussin result = TRUE; 114*2a3e3873SBaptiste Daroussin break; 115*2a3e3873SBaptiste Daroussin } 116*2a3e3873SBaptiste Daroussin } 117*2a3e3873SBaptiste Daroussin } 118*2a3e3873SBaptiste Daroussin return result; 119*2a3e3873SBaptiste Daroussin } 120*2a3e3873SBaptiste Daroussin 121*2a3e3873SBaptiste Daroussin /* 122*2a3e3873SBaptiste Daroussin * Determine the hot-keys for a set of button-labels. Normally these are 123*2a3e3873SBaptiste Daroussin * the first uppercase character in each label. However, if more than one 124*2a3e3873SBaptiste Daroussin * button has the same first-uppercase, then we will (attempt to) look for 125*2a3e3873SBaptiste Daroussin * an alternate. 126*2a3e3873SBaptiste Daroussin * 127*2a3e3873SBaptiste Daroussin * This allocates data which must be freed by the caller. 128*2a3e3873SBaptiste Daroussin */ 129*2a3e3873SBaptiste Daroussin static int * 130*2a3e3873SBaptiste Daroussin get_hotkeys(const char **labels) 131*2a3e3873SBaptiste Daroussin { 132*2a3e3873SBaptiste Daroussin int *result = 0; 133*2a3e3873SBaptiste Daroussin size_t count = count_labels(labels); 134*2a3e3873SBaptiste Daroussin size_t n; 135*2a3e3873SBaptiste Daroussin 136*2a3e3873SBaptiste Daroussin if ((result = dlg_calloc(int, count + 1)) != 0) { 137*2a3e3873SBaptiste Daroussin for (n = 0; n < count; ++n) { 138*2a3e3873SBaptiste Daroussin const char *label = labels[n]; 139*2a3e3873SBaptiste Daroussin const int *indx = dlg_index_wchars(label); 140*2a3e3873SBaptiste Daroussin int limit = dlg_count_wchars(label); 141*2a3e3873SBaptiste Daroussin int i; 142*2a3e3873SBaptiste Daroussin 143*2a3e3873SBaptiste Daroussin for (i = 0; i < limit; ++i) { 144*2a3e3873SBaptiste Daroussin int first = indx[i]; 145*2a3e3873SBaptiste Daroussin int check = UCH(label[first]); 146*2a3e3873SBaptiste Daroussin #ifdef USE_WIDE_CURSES 147*2a3e3873SBaptiste Daroussin int last = indx[i + 1]; 148*2a3e3873SBaptiste Daroussin if ((last - first) != 1) { 149*2a3e3873SBaptiste Daroussin const char *temp = (label + first); 150*2a3e3873SBaptiste Daroussin check = string_to_char(&temp); 151*2a3e3873SBaptiste Daroussin } 152*2a3e3873SBaptiste Daroussin #endif 153*2a3e3873SBaptiste Daroussin if (dlg_isupper(check) && !was_hotkey(check, result, n)) { 154*2a3e3873SBaptiste Daroussin result[n] = check; 155*2a3e3873SBaptiste Daroussin break; 156*2a3e3873SBaptiste Daroussin } 157*2a3e3873SBaptiste Daroussin } 158*2a3e3873SBaptiste Daroussin } 159*2a3e3873SBaptiste Daroussin } 160*2a3e3873SBaptiste Daroussin return result; 161*2a3e3873SBaptiste Daroussin } 162*2a3e3873SBaptiste Daroussin 1634c8945a0SNathan Whitehorn /* 1644c8945a0SNathan Whitehorn * Print a button 1654c8945a0SNathan Whitehorn */ 1664c8945a0SNathan Whitehorn static void 167*2a3e3873SBaptiste Daroussin print_button(WINDOW *win, char *label, int hotkey, int y, int x, int selected) 1684c8945a0SNathan Whitehorn { 1694c8945a0SNathan Whitehorn int i; 1704c8945a0SNathan Whitehorn int state = 0; 1714c8945a0SNathan Whitehorn const int *indx = dlg_index_wchars(label); 1724c8945a0SNathan Whitehorn int limit = dlg_count_wchars(label); 1734c8945a0SNathan Whitehorn chtype key_attr = (selected 1744c8945a0SNathan Whitehorn ? button_key_active_attr 1754c8945a0SNathan Whitehorn : button_key_inactive_attr); 1764c8945a0SNathan Whitehorn chtype label_attr = (selected 1774c8945a0SNathan Whitehorn ? button_label_active_attr 1784c8945a0SNathan Whitehorn : button_label_inactive_attr); 1794c8945a0SNathan Whitehorn 1804c8945a0SNathan Whitehorn (void) wmove(win, y, x); 181*2a3e3873SBaptiste Daroussin (void) wattrset(win, selected 1824c8945a0SNathan Whitehorn ? button_active_attr 1834c8945a0SNathan Whitehorn : button_inactive_attr); 1844c8945a0SNathan Whitehorn (void) waddstr(win, "<"); 185*2a3e3873SBaptiste Daroussin (void) wattrset(win, label_attr); 1864c8945a0SNathan Whitehorn for (i = 0; i < limit; ++i) { 187*2a3e3873SBaptiste Daroussin int check; 1884c8945a0SNathan Whitehorn int first = indx[i]; 1894c8945a0SNathan Whitehorn int last = indx[i + 1]; 1904c8945a0SNathan Whitehorn 1914c8945a0SNathan Whitehorn switch (state) { 1924c8945a0SNathan Whitehorn case 0: 193*2a3e3873SBaptiste Daroussin check = UCH(label[first]); 1944c8945a0SNathan Whitehorn #ifdef USE_WIDE_CURSES 1954c8945a0SNathan Whitehorn if ((last - first) != 1) { 1964c8945a0SNathan Whitehorn const char *temp = (label + first); 197*2a3e3873SBaptiste Daroussin check = string_to_char(&temp); 1984c8945a0SNathan Whitehorn } 1994c8945a0SNathan Whitehorn #endif 200*2a3e3873SBaptiste Daroussin if (check == hotkey) { 201*2a3e3873SBaptiste Daroussin (void) wattrset(win, key_attr); 2024c8945a0SNathan Whitehorn state = 1; 2034c8945a0SNathan Whitehorn } 2044c8945a0SNathan Whitehorn break; 2054c8945a0SNathan Whitehorn case 1: 2064c8945a0SNathan Whitehorn wattrset(win, label_attr); 2074c8945a0SNathan Whitehorn state = 2; 2084c8945a0SNathan Whitehorn break; 2094c8945a0SNathan Whitehorn } 2104c8945a0SNathan Whitehorn waddnstr(win, label + first, last - first); 2114c8945a0SNathan Whitehorn } 212*2a3e3873SBaptiste Daroussin (void) wattrset(win, selected 2134c8945a0SNathan Whitehorn ? button_active_attr 2144c8945a0SNathan Whitehorn : button_inactive_attr); 2154c8945a0SNathan Whitehorn (void) waddstr(win, ">"); 2164c8945a0SNathan Whitehorn (void) wmove(win, y, x + ((int) strspn(label, " ")) + 1); 2174c8945a0SNathan Whitehorn } 2184c8945a0SNathan Whitehorn 2194c8945a0SNathan Whitehorn /* 2204c8945a0SNathan Whitehorn * Count the buttons in the list. 2214c8945a0SNathan Whitehorn */ 2224c8945a0SNathan Whitehorn int 2234c8945a0SNathan Whitehorn dlg_button_count(const char **labels) 2244c8945a0SNathan Whitehorn { 2254c8945a0SNathan Whitehorn int result = 0; 2264c8945a0SNathan Whitehorn while (*labels++ != 0) 2274c8945a0SNathan Whitehorn ++result; 2284c8945a0SNathan Whitehorn return result; 2294c8945a0SNathan Whitehorn } 2304c8945a0SNathan Whitehorn 2314c8945a0SNathan Whitehorn /* 2324c8945a0SNathan Whitehorn * Compute the size of the button array in columns. Return the total number of 2334c8945a0SNathan Whitehorn * columns in *length, and the longest button's columns in *longest 2344c8945a0SNathan Whitehorn */ 2354c8945a0SNathan Whitehorn void 2364c8945a0SNathan Whitehorn dlg_button_sizes(const char **labels, 2374c8945a0SNathan Whitehorn int vertical, 2384c8945a0SNathan Whitehorn int *longest, 2394c8945a0SNathan Whitehorn int *length) 2404c8945a0SNathan Whitehorn { 2414c8945a0SNathan Whitehorn int n; 2424c8945a0SNathan Whitehorn 2434c8945a0SNathan Whitehorn *length = 0; 2444c8945a0SNathan Whitehorn *longest = 0; 2454c8945a0SNathan Whitehorn for (n = 0; labels[n] != 0; n++) { 2464c8945a0SNathan Whitehorn if (vertical) { 2474c8945a0SNathan Whitehorn *length += 1; 2484c8945a0SNathan Whitehorn *longest = 1; 2494c8945a0SNathan Whitehorn } else { 2504c8945a0SNathan Whitehorn int len = dlg_count_columns(labels[n]); 2514c8945a0SNathan Whitehorn if (len > *longest) 2524c8945a0SNathan Whitehorn *longest = len; 2534c8945a0SNathan Whitehorn *length += len; 2544c8945a0SNathan Whitehorn } 2554c8945a0SNathan Whitehorn } 2564c8945a0SNathan Whitehorn /* 2574c8945a0SNathan Whitehorn * If we can, make all of the buttons the same size. This is only optional 2584c8945a0SNathan Whitehorn * for buttons laid out horizontally. 2594c8945a0SNathan Whitehorn */ 2604c8945a0SNathan Whitehorn if (*longest < 6 - (*longest & 1)) 2614c8945a0SNathan Whitehorn *longest = 6 - (*longest & 1); 2624c8945a0SNathan Whitehorn if (!vertical) 2634c8945a0SNathan Whitehorn *length = *longest * n; 2644c8945a0SNathan Whitehorn } 2654c8945a0SNathan Whitehorn 2664c8945a0SNathan Whitehorn /* 2674c8945a0SNathan Whitehorn * Compute the size of the button array. 2684c8945a0SNathan Whitehorn */ 2694c8945a0SNathan Whitehorn int 2704c8945a0SNathan Whitehorn dlg_button_x_step(const char **labels, int limit, int *gap, int *margin, int *step) 2714c8945a0SNathan Whitehorn { 2724c8945a0SNathan Whitehorn int count = dlg_button_count(labels); 2734c8945a0SNathan Whitehorn int longest; 2744c8945a0SNathan Whitehorn int length; 2754c8945a0SNathan Whitehorn int unused; 2764c8945a0SNathan Whitehorn int used; 277*2a3e3873SBaptiste Daroussin int result; 2784c8945a0SNathan Whitehorn 279*2a3e3873SBaptiste Daroussin *margin = 0; 280*2a3e3873SBaptiste Daroussin if (count != 0) { 2814c8945a0SNathan Whitehorn dlg_button_sizes(labels, FALSE, &longest, &length); 2824c8945a0SNathan Whitehorn used = (length + (count * 2)); 2834c8945a0SNathan Whitehorn unused = limit - used; 2844c8945a0SNathan Whitehorn 2854c8945a0SNathan Whitehorn if ((*gap = unused / (count + 3)) <= 0) { 2864c8945a0SNathan Whitehorn if ((*gap = unused / (count + 1)) <= 0) 2874c8945a0SNathan Whitehorn *gap = 1; 2884c8945a0SNathan Whitehorn *margin = *gap; 2894c8945a0SNathan Whitehorn } else { 2904c8945a0SNathan Whitehorn *margin = *gap * 2; 2914c8945a0SNathan Whitehorn } 2924c8945a0SNathan Whitehorn *step = *gap + (used + count - 1) / count; 293*2a3e3873SBaptiste Daroussin result = (*gap > 0) && (unused >= 0); 294*2a3e3873SBaptiste Daroussin } else { 295*2a3e3873SBaptiste Daroussin result = 0; 296*2a3e3873SBaptiste Daroussin } 297*2a3e3873SBaptiste Daroussin return result; 2984c8945a0SNathan Whitehorn } 2994c8945a0SNathan Whitehorn 3004c8945a0SNathan Whitehorn /* 3014c8945a0SNathan Whitehorn * Make sure there is enough space for the buttons 3024c8945a0SNathan Whitehorn */ 3034c8945a0SNathan Whitehorn void 3044c8945a0SNathan Whitehorn dlg_button_layout(const char **labels, int *limit) 3054c8945a0SNathan Whitehorn { 3064c8945a0SNathan Whitehorn int width = 1; 3074c8945a0SNathan Whitehorn int gap, margin, step; 3084c8945a0SNathan Whitehorn 3094c8945a0SNathan Whitehorn if (labels != 0 && dlg_button_count(labels)) { 3104c8945a0SNathan Whitehorn while (!dlg_button_x_step(labels, width, &gap, &margin, &step)) 3114c8945a0SNathan Whitehorn ++width; 3124c8945a0SNathan Whitehorn width += (4 * MARGIN); 3134c8945a0SNathan Whitehorn if (width > COLS) 3144c8945a0SNathan Whitehorn width = COLS; 3154c8945a0SNathan Whitehorn if (width > *limit) 3164c8945a0SNathan Whitehorn *limit = width; 3174c8945a0SNathan Whitehorn } 3184c8945a0SNathan Whitehorn } 3194c8945a0SNathan Whitehorn 3204c8945a0SNathan Whitehorn /* 3214c8945a0SNathan Whitehorn * Print a list of buttons at the given position. 3224c8945a0SNathan Whitehorn */ 3234c8945a0SNathan Whitehorn void 3244c8945a0SNathan Whitehorn dlg_draw_buttons(WINDOW *win, 3254c8945a0SNathan Whitehorn int y, int x, 3264c8945a0SNathan Whitehorn const char **labels, 3274c8945a0SNathan Whitehorn int selected, 3284c8945a0SNathan Whitehorn int vertical, 3294c8945a0SNathan Whitehorn int limit) 3304c8945a0SNathan Whitehorn { 3317a1c0d96SNathan Whitehorn chtype save = dlg_get_attrs(win); 3324c8945a0SNathan Whitehorn int n; 3334c8945a0SNathan Whitehorn int step = 0; 3344c8945a0SNathan Whitehorn int length; 3354c8945a0SNathan Whitehorn int longest; 3364c8945a0SNathan Whitehorn int final_x; 3374c8945a0SNathan Whitehorn int final_y; 3384c8945a0SNathan Whitehorn int gap; 3394c8945a0SNathan Whitehorn int margin; 3404c8945a0SNathan Whitehorn size_t need; 3414c8945a0SNathan Whitehorn char *buffer; 3424c8945a0SNathan Whitehorn 3434c8945a0SNathan Whitehorn dlg_mouse_setbase(getbegx(win), getbegy(win)); 3444c8945a0SNathan Whitehorn 3454c8945a0SNathan Whitehorn getyx(win, final_y, final_x); 3464c8945a0SNathan Whitehorn 3474c8945a0SNathan Whitehorn dlg_button_sizes(labels, vertical, &longest, &length); 3484c8945a0SNathan Whitehorn 3494c8945a0SNathan Whitehorn if (vertical) { 3504c8945a0SNathan Whitehorn y += 1; 3514c8945a0SNathan Whitehorn step = 1; 3524c8945a0SNathan Whitehorn } else { 3534c8945a0SNathan Whitehorn dlg_button_x_step(labels, limit, &gap, &margin, &step); 3544c8945a0SNathan Whitehorn x += margin; 3554c8945a0SNathan Whitehorn } 3564c8945a0SNathan Whitehorn 3574c8945a0SNathan Whitehorn /* 3584c8945a0SNathan Whitehorn * Allocate a buffer big enough for any label. 3594c8945a0SNathan Whitehorn */ 3604c8945a0SNathan Whitehorn need = (size_t) longest; 361*2a3e3873SBaptiste Daroussin if (need != 0) { 362*2a3e3873SBaptiste Daroussin int *hotkeys = get_hotkeys(labels); 363*2a3e3873SBaptiste Daroussin assert_ptr(hotkeys, "dlg_draw_buttons"); 364*2a3e3873SBaptiste Daroussin 3654c8945a0SNathan Whitehorn for (n = 0; labels[n] != 0; ++n) { 3664c8945a0SNathan Whitehorn need += strlen(labels[n]) + 1; 3674c8945a0SNathan Whitehorn } 3684c8945a0SNathan Whitehorn buffer = dlg_malloc(char, need); 3694c8945a0SNathan Whitehorn assert_ptr(buffer, "dlg_draw_buttons"); 3704c8945a0SNathan Whitehorn 3714c8945a0SNathan Whitehorn /* 3724c8945a0SNathan Whitehorn * Draw the labels. 3734c8945a0SNathan Whitehorn */ 3744c8945a0SNathan Whitehorn for (n = 0; labels[n] != 0; n++) { 3754c8945a0SNathan Whitehorn center_label(buffer, longest, labels[n]); 3764c8945a0SNathan Whitehorn mouse_mkbutton(y, x, dlg_count_columns(buffer), n); 377*2a3e3873SBaptiste Daroussin print_button(win, buffer, hotkeys[n], y, x, 3784c8945a0SNathan Whitehorn (selected == n) || (n == 0 && selected < 0)); 3794c8945a0SNathan Whitehorn if (selected == n) 3804c8945a0SNathan Whitehorn getyx(win, final_y, final_x); 3814c8945a0SNathan Whitehorn 3824c8945a0SNathan Whitehorn if (vertical) { 3834c8945a0SNathan Whitehorn if ((y += step) > limit) 3844c8945a0SNathan Whitehorn break; 3854c8945a0SNathan Whitehorn } else { 3864c8945a0SNathan Whitehorn if ((x += step) > limit) 3874c8945a0SNathan Whitehorn break; 3884c8945a0SNathan Whitehorn } 3894c8945a0SNathan Whitehorn } 3904c8945a0SNathan Whitehorn (void) wmove(win, final_y, final_x); 3914c8945a0SNathan Whitehorn wrefresh(win); 392*2a3e3873SBaptiste Daroussin (void) wattrset(win, save); 3934c8945a0SNathan Whitehorn free(buffer); 394*2a3e3873SBaptiste Daroussin free(hotkeys); 395*2a3e3873SBaptiste Daroussin } 3964c8945a0SNathan Whitehorn } 3974c8945a0SNathan Whitehorn 3984c8945a0SNathan Whitehorn /* 3994c8945a0SNathan Whitehorn * Match a given character against the beginning of the string, ignoring case 4004c8945a0SNathan Whitehorn * of the given character. The matching string must begin with an uppercase 4014c8945a0SNathan Whitehorn * character. 4024c8945a0SNathan Whitehorn */ 4034c8945a0SNathan Whitehorn int 4044c8945a0SNathan Whitehorn dlg_match_char(int ch, const char *string) 4054c8945a0SNathan Whitehorn { 4064c8945a0SNathan Whitehorn if (string != 0) { 4074c8945a0SNathan Whitehorn int cmp2 = string_to_char(&string); 4084c8945a0SNathan Whitehorn #ifdef USE_WIDE_CURSES 4094c8945a0SNathan Whitehorn wint_t cmp1 = dlg_toupper(ch); 4104c8945a0SNathan Whitehorn if (cmp2 != 0 && (wchar_t) cmp1 == (wchar_t) dlg_toupper(cmp2)) { 4114c8945a0SNathan Whitehorn return TRUE; 4124c8945a0SNathan Whitehorn } 4134c8945a0SNathan Whitehorn #else 4144c8945a0SNathan Whitehorn if (ch > 0 && ch < 256) { 4154c8945a0SNathan Whitehorn if (dlg_toupper(ch) == dlg_toupper(cmp2)) 4164c8945a0SNathan Whitehorn return TRUE; 4174c8945a0SNathan Whitehorn } 4184c8945a0SNathan Whitehorn #endif 4194c8945a0SNathan Whitehorn } 4204c8945a0SNathan Whitehorn return FALSE; 4214c8945a0SNathan Whitehorn } 4224c8945a0SNathan Whitehorn 4234c8945a0SNathan Whitehorn /* 4244c8945a0SNathan Whitehorn * Find the first uppercase character in the label, which we may use for an 4254c8945a0SNathan Whitehorn * abbreviation. 4264c8945a0SNathan Whitehorn */ 4274c8945a0SNathan Whitehorn int 4284c8945a0SNathan Whitehorn dlg_button_to_char(const char *label) 4294c8945a0SNathan Whitehorn { 4304c8945a0SNathan Whitehorn int cmp = -1; 4314c8945a0SNathan Whitehorn 4324c8945a0SNathan Whitehorn while (*label != 0) { 4334c8945a0SNathan Whitehorn cmp = string_to_char(&label); 4344c8945a0SNathan Whitehorn if (dlg_isupper(cmp)) { 4354c8945a0SNathan Whitehorn break; 4364c8945a0SNathan Whitehorn } 4374c8945a0SNathan Whitehorn } 4384c8945a0SNathan Whitehorn return cmp; 4394c8945a0SNathan Whitehorn } 4404c8945a0SNathan Whitehorn 4414c8945a0SNathan Whitehorn /* 4424c8945a0SNathan Whitehorn * Given a list of button labels, and a character which may be the abbreviation 4434c8945a0SNathan Whitehorn * for one, find it, if it exists. An abbreviation will be the first character 4444c8945a0SNathan Whitehorn * which happens to be capitalized in the label. 4454c8945a0SNathan Whitehorn */ 4464c8945a0SNathan Whitehorn int 4474c8945a0SNathan Whitehorn dlg_char_to_button(int ch, const char **labels) 4484c8945a0SNathan Whitehorn { 449*2a3e3873SBaptiste Daroussin int result = DLG_EXIT_UNKNOWN; 450*2a3e3873SBaptiste Daroussin 4514c8945a0SNathan Whitehorn if (labels != 0) { 452*2a3e3873SBaptiste Daroussin int *hotkeys = get_hotkeys(labels); 4534c8945a0SNathan Whitehorn int j; 4544c8945a0SNathan Whitehorn 4554c8945a0SNathan Whitehorn ch = (int) dlg_toupper(dlg_last_getc()); 456*2a3e3873SBaptiste Daroussin 457*2a3e3873SBaptiste Daroussin if (hotkeys != 0) { 4584c8945a0SNathan Whitehorn for (j = 0; labels[j] != 0; ++j) { 459*2a3e3873SBaptiste Daroussin if (ch == hotkeys[j]) { 4604c8945a0SNathan Whitehorn dlg_flush_getc(); 461*2a3e3873SBaptiste Daroussin result = j; 462*2a3e3873SBaptiste Daroussin break; 4634c8945a0SNathan Whitehorn } 4644c8945a0SNathan Whitehorn } 465*2a3e3873SBaptiste Daroussin free(hotkeys); 4664c8945a0SNathan Whitehorn } 467*2a3e3873SBaptiste Daroussin } 468*2a3e3873SBaptiste Daroussin 469*2a3e3873SBaptiste Daroussin return result; 4704c8945a0SNathan Whitehorn } 4714c8945a0SNathan Whitehorn 4724c8945a0SNathan Whitehorn static const char * 4734c8945a0SNathan Whitehorn my_yes_label(void) 4744c8945a0SNathan Whitehorn { 4754c8945a0SNathan Whitehorn return (dialog_vars.yes_label != NULL) 4764c8945a0SNathan Whitehorn ? dialog_vars.yes_label 4774c8945a0SNathan Whitehorn : _("Yes"); 4784c8945a0SNathan Whitehorn } 4794c8945a0SNathan Whitehorn 4804c8945a0SNathan Whitehorn static const char * 4814c8945a0SNathan Whitehorn my_no_label(void) 4824c8945a0SNathan Whitehorn { 4834c8945a0SNathan Whitehorn return (dialog_vars.no_label != NULL) 4844c8945a0SNathan Whitehorn ? dialog_vars.no_label 4854c8945a0SNathan Whitehorn : _("No"); 4864c8945a0SNathan Whitehorn } 4874c8945a0SNathan Whitehorn 4884c8945a0SNathan Whitehorn static const char * 4894c8945a0SNathan Whitehorn my_ok_label(void) 4904c8945a0SNathan Whitehorn { 4914c8945a0SNathan Whitehorn return (dialog_vars.ok_label != NULL) 4924c8945a0SNathan Whitehorn ? dialog_vars.ok_label 4934c8945a0SNathan Whitehorn : _("OK"); 4944c8945a0SNathan Whitehorn } 4954c8945a0SNathan Whitehorn 4964c8945a0SNathan Whitehorn static const char * 4974c8945a0SNathan Whitehorn my_cancel_label(void) 4984c8945a0SNathan Whitehorn { 4994c8945a0SNathan Whitehorn return (dialog_vars.cancel_label != NULL) 5004c8945a0SNathan Whitehorn ? dialog_vars.cancel_label 5014c8945a0SNathan Whitehorn : _("Cancel"); 5024c8945a0SNathan Whitehorn } 5034c8945a0SNathan Whitehorn 5044c8945a0SNathan Whitehorn static const char * 5054c8945a0SNathan Whitehorn my_exit_label(void) 5064c8945a0SNathan Whitehorn { 5074c8945a0SNathan Whitehorn return (dialog_vars.exit_label != NULL) 5084c8945a0SNathan Whitehorn ? dialog_vars.exit_label 5094c8945a0SNathan Whitehorn : _("EXIT"); 5104c8945a0SNathan Whitehorn } 5114c8945a0SNathan Whitehorn 5124c8945a0SNathan Whitehorn static const char * 5134c8945a0SNathan Whitehorn my_extra_label(void) 5144c8945a0SNathan Whitehorn { 5154c8945a0SNathan Whitehorn return (dialog_vars.extra_label != NULL) 5164c8945a0SNathan Whitehorn ? dialog_vars.extra_label 5174c8945a0SNathan Whitehorn : _("Extra"); 5184c8945a0SNathan Whitehorn } 5194c8945a0SNathan Whitehorn 5204c8945a0SNathan Whitehorn static const char * 5214c8945a0SNathan Whitehorn my_help_label(void) 5224c8945a0SNathan Whitehorn { 5234c8945a0SNathan Whitehorn return (dialog_vars.help_label != NULL) 5244c8945a0SNathan Whitehorn ? dialog_vars.help_label 5254c8945a0SNathan Whitehorn : _("Help"); 5264c8945a0SNathan Whitehorn } 5274c8945a0SNathan Whitehorn 5284c8945a0SNathan Whitehorn /* 5294c8945a0SNathan Whitehorn * Return a list of button labels. 5304c8945a0SNathan Whitehorn */ 5314c8945a0SNathan Whitehorn const char ** 5324c8945a0SNathan Whitehorn dlg_exit_label(void) 5334c8945a0SNathan Whitehorn { 5344c8945a0SNathan Whitehorn const char **result; 535682c9e0fSNathan Whitehorn DIALOG_VARS save; 5364c8945a0SNathan Whitehorn 5374c8945a0SNathan Whitehorn if (dialog_vars.extra_button) { 538682c9e0fSNathan Whitehorn dlg_save_vars(&save); 539682c9e0fSNathan Whitehorn dialog_vars.nocancel = TRUE; 5404c8945a0SNathan Whitehorn result = dlg_ok_labels(); 541682c9e0fSNathan Whitehorn dlg_restore_vars(&save); 5424c8945a0SNathan Whitehorn } else { 5434c8945a0SNathan Whitehorn static const char *labels[3]; 5444c8945a0SNathan Whitehorn int n = 0; 5454c8945a0SNathan Whitehorn 546682c9e0fSNathan Whitehorn if (!dialog_vars.nook) 5474c8945a0SNathan Whitehorn labels[n++] = my_exit_label(); 5484c8945a0SNathan Whitehorn if (dialog_vars.help_button) 5494c8945a0SNathan Whitehorn labels[n++] = my_help_label(); 550682c9e0fSNathan Whitehorn if (n == 0) 551682c9e0fSNathan Whitehorn labels[n++] = my_exit_label(); 5524c8945a0SNathan Whitehorn labels[n] = 0; 5534c8945a0SNathan Whitehorn 5544c8945a0SNathan Whitehorn result = labels; 5554c8945a0SNathan Whitehorn } 5564c8945a0SNathan Whitehorn return result; 5574c8945a0SNathan Whitehorn } 5584c8945a0SNathan Whitehorn 5594c8945a0SNathan Whitehorn /* 5604c8945a0SNathan Whitehorn * Map the given button index for dlg_exit_label() into our exit-code. 5614c8945a0SNathan Whitehorn */ 5624c8945a0SNathan Whitehorn int 5634c8945a0SNathan Whitehorn dlg_exit_buttoncode(int button) 5644c8945a0SNathan Whitehorn { 565682c9e0fSNathan Whitehorn int result; 566682c9e0fSNathan Whitehorn DIALOG_VARS save; 567682c9e0fSNathan Whitehorn 568682c9e0fSNathan Whitehorn dlg_save_vars(&save); 569682c9e0fSNathan Whitehorn dialog_vars.nocancel = TRUE; 570682c9e0fSNathan Whitehorn 571682c9e0fSNathan Whitehorn result = dlg_ok_buttoncode(button); 572682c9e0fSNathan Whitehorn 573682c9e0fSNathan Whitehorn dlg_restore_vars(&save); 574682c9e0fSNathan Whitehorn 575682c9e0fSNathan Whitehorn return result; 5764c8945a0SNathan Whitehorn } 5774c8945a0SNathan Whitehorn 5784c8945a0SNathan Whitehorn const char ** 5794c8945a0SNathan Whitehorn dlg_ok_label(void) 5804c8945a0SNathan Whitehorn { 581*2a3e3873SBaptiste Daroussin static const char *labels[4]; 5824c8945a0SNathan Whitehorn int n = 0; 5834c8945a0SNathan Whitehorn 5844c8945a0SNathan Whitehorn labels[n++] = my_ok_label(); 585*2a3e3873SBaptiste Daroussin if (dialog_vars.extra_button) 586*2a3e3873SBaptiste Daroussin labels[n++] = my_extra_label(); 5874c8945a0SNathan Whitehorn if (dialog_vars.help_button) 5884c8945a0SNathan Whitehorn labels[n++] = my_help_label(); 5894c8945a0SNathan Whitehorn labels[n] = 0; 5904c8945a0SNathan Whitehorn return labels; 5914c8945a0SNathan Whitehorn } 5924c8945a0SNathan Whitehorn 5934c8945a0SNathan Whitehorn /* 5944c8945a0SNathan Whitehorn * Return a list of button labels for the OK/Cancel group. 5954c8945a0SNathan Whitehorn */ 5964c8945a0SNathan Whitehorn const char ** 5974c8945a0SNathan Whitehorn dlg_ok_labels(void) 5984c8945a0SNathan Whitehorn { 5994c8945a0SNathan Whitehorn static const char *labels[5]; 6004c8945a0SNathan Whitehorn int n = 0; 6014c8945a0SNathan Whitehorn 6024c8945a0SNathan Whitehorn if (!dialog_vars.nook) 6034c8945a0SNathan Whitehorn labels[n++] = my_ok_label(); 6044c8945a0SNathan Whitehorn if (dialog_vars.extra_button) 6054c8945a0SNathan Whitehorn labels[n++] = my_extra_label(); 6064c8945a0SNathan Whitehorn if (!dialog_vars.nocancel) 6074c8945a0SNathan Whitehorn labels[n++] = my_cancel_label(); 6084c8945a0SNathan Whitehorn if (dialog_vars.help_button) 6094c8945a0SNathan Whitehorn labels[n++] = my_help_label(); 6104c8945a0SNathan Whitehorn labels[n] = 0; 6114c8945a0SNathan Whitehorn return labels; 6124c8945a0SNathan Whitehorn } 6134c8945a0SNathan Whitehorn 6144c8945a0SNathan Whitehorn /* 6154c8945a0SNathan Whitehorn * Map the given button index for dlg_ok_labels() into our exit-code 6164c8945a0SNathan Whitehorn */ 6174c8945a0SNathan Whitehorn int 6184c8945a0SNathan Whitehorn dlg_ok_buttoncode(int button) 6194c8945a0SNathan Whitehorn { 6204c8945a0SNathan Whitehorn int result = DLG_EXIT_ERROR; 6214c8945a0SNathan Whitehorn int n = !dialog_vars.nook; 6224c8945a0SNathan Whitehorn 6234c8945a0SNathan Whitehorn if (!dialog_vars.nook && (button <= 0)) { 6244c8945a0SNathan Whitehorn result = DLG_EXIT_OK; 6254c8945a0SNathan Whitehorn } else if (dialog_vars.extra_button && (button == n++)) { 6264c8945a0SNathan Whitehorn result = DLG_EXIT_EXTRA; 6274c8945a0SNathan Whitehorn } else if (!dialog_vars.nocancel && (button == n++)) { 6284c8945a0SNathan Whitehorn result = DLG_EXIT_CANCEL; 6294c8945a0SNathan Whitehorn } else if (dialog_vars.help_button && (button == n)) { 6304c8945a0SNathan Whitehorn result = DLG_EXIT_HELP; 6314c8945a0SNathan Whitehorn } 632*2a3e3873SBaptiste Daroussin dlg_trace_msg("# dlg_ok_buttoncode(%d) = %d\n", button, result); 6334c8945a0SNathan Whitehorn return result; 6344c8945a0SNathan Whitehorn } 6354c8945a0SNathan Whitehorn 6364c8945a0SNathan Whitehorn /* 6374c8945a0SNathan Whitehorn * Given that we're using dlg_ok_labels() to list buttons, find the next index 6384c8945a0SNathan Whitehorn * in the list of buttons. The 'extra' parameter if negative provides a way to 6394c8945a0SNathan Whitehorn * enumerate extra active areas on the widget. 6404c8945a0SNathan Whitehorn */ 6414c8945a0SNathan Whitehorn int 6424c8945a0SNathan Whitehorn dlg_next_ok_buttonindex(int current, int extra) 6434c8945a0SNathan Whitehorn { 6444c8945a0SNathan Whitehorn int result = current + 1; 6454c8945a0SNathan Whitehorn 6464c8945a0SNathan Whitehorn if (current >= 0 6474c8945a0SNathan Whitehorn && dlg_ok_buttoncode(result) < 0) 6484c8945a0SNathan Whitehorn result = extra; 6494c8945a0SNathan Whitehorn return result; 6504c8945a0SNathan Whitehorn } 6514c8945a0SNathan Whitehorn 6524c8945a0SNathan Whitehorn /* 6534c8945a0SNathan Whitehorn * Similarly, find the previous button index. 6544c8945a0SNathan Whitehorn */ 6554c8945a0SNathan Whitehorn int 6564c8945a0SNathan Whitehorn dlg_prev_ok_buttonindex(int current, int extra) 6574c8945a0SNathan Whitehorn { 6584c8945a0SNathan Whitehorn int result = current - 1; 6594c8945a0SNathan Whitehorn 6604c8945a0SNathan Whitehorn if (result < extra) { 6614c8945a0SNathan Whitehorn for (result = 0; dlg_ok_buttoncode(result + 1) >= 0; ++result) { 6624c8945a0SNathan Whitehorn ; 6634c8945a0SNathan Whitehorn } 6644c8945a0SNathan Whitehorn } 6654c8945a0SNathan Whitehorn return result; 6664c8945a0SNathan Whitehorn } 6674c8945a0SNathan Whitehorn 6684c8945a0SNathan Whitehorn /* 6694c8945a0SNathan Whitehorn * Find the button-index for the "OK" or "Cancel" button, according to 6704c8945a0SNathan Whitehorn * whether --defaultno is given. If --nocancel was given, we always return 671*2a3e3873SBaptiste Daroussin * the index for the first button (usually "OK" unless --nook was used). 6724c8945a0SNathan Whitehorn */ 6734c8945a0SNathan Whitehorn int 6744c8945a0SNathan Whitehorn dlg_defaultno_button(void) 6754c8945a0SNathan Whitehorn { 6764c8945a0SNathan Whitehorn int result = 0; 6774c8945a0SNathan Whitehorn 6784c8945a0SNathan Whitehorn if (dialog_vars.defaultno && !dialog_vars.nocancel) { 6794c8945a0SNathan Whitehorn while (dlg_ok_buttoncode(result) != DLG_EXIT_CANCEL) 6804c8945a0SNathan Whitehorn ++result; 6814c8945a0SNathan Whitehorn } 682*2a3e3873SBaptiste Daroussin dlg_trace_msg("# dlg_defaultno_button() = %d\n", result); 683*2a3e3873SBaptiste Daroussin return result; 684*2a3e3873SBaptiste Daroussin } 685*2a3e3873SBaptiste Daroussin 686*2a3e3873SBaptiste Daroussin /* 687*2a3e3873SBaptiste Daroussin * Find the button-index for a button named with --default-button. If the 688*2a3e3873SBaptiste Daroussin * option was not specified, or if the selected button does not exist, return 689*2a3e3873SBaptiste Daroussin * the index of the first button (usually "OK" unless --nook was used). 690*2a3e3873SBaptiste Daroussin */ 691*2a3e3873SBaptiste Daroussin int 692*2a3e3873SBaptiste Daroussin dlg_default_button(void) 693*2a3e3873SBaptiste Daroussin { 694*2a3e3873SBaptiste Daroussin int i, n; 695*2a3e3873SBaptiste Daroussin int result = 0; 696*2a3e3873SBaptiste Daroussin 697*2a3e3873SBaptiste Daroussin if (dialog_vars.default_button >= 0) { 698*2a3e3873SBaptiste Daroussin for (i = 0; (n = dlg_ok_buttoncode(i)) >= 0; i++) { 699*2a3e3873SBaptiste Daroussin if (n == dialog_vars.default_button) { 700*2a3e3873SBaptiste Daroussin result = i; 701*2a3e3873SBaptiste Daroussin break; 702*2a3e3873SBaptiste Daroussin } 703*2a3e3873SBaptiste Daroussin } 704*2a3e3873SBaptiste Daroussin } 705*2a3e3873SBaptiste Daroussin dlg_trace_msg("# dlg_default_button() = %d\n", result); 7064c8945a0SNathan Whitehorn return result; 7074c8945a0SNathan Whitehorn } 7084c8945a0SNathan Whitehorn 7094c8945a0SNathan Whitehorn /* 7104c8945a0SNathan Whitehorn * Return a list of buttons for Yes/No labels. 7114c8945a0SNathan Whitehorn */ 7124c8945a0SNathan Whitehorn const char ** 7134c8945a0SNathan Whitehorn dlg_yes_labels(void) 7144c8945a0SNathan Whitehorn { 7154c8945a0SNathan Whitehorn const char **result; 7164c8945a0SNathan Whitehorn 7174c8945a0SNathan Whitehorn if (dialog_vars.extra_button) { 7184c8945a0SNathan Whitehorn result = dlg_ok_labels(); 7194c8945a0SNathan Whitehorn } else { 7204c8945a0SNathan Whitehorn static const char *labels[4]; 7214c8945a0SNathan Whitehorn int n = 0; 7224c8945a0SNathan Whitehorn 7234c8945a0SNathan Whitehorn labels[n++] = my_yes_label(); 7244c8945a0SNathan Whitehorn labels[n++] = my_no_label(); 7254c8945a0SNathan Whitehorn if (dialog_vars.help_button) 7264c8945a0SNathan Whitehorn labels[n++] = my_help_label(); 7274c8945a0SNathan Whitehorn labels[n] = 0; 7284c8945a0SNathan Whitehorn 7294c8945a0SNathan Whitehorn result = labels; 7304c8945a0SNathan Whitehorn } 7314c8945a0SNathan Whitehorn 7324c8945a0SNathan Whitehorn return result; 7334c8945a0SNathan Whitehorn } 7344c8945a0SNathan Whitehorn 7354c8945a0SNathan Whitehorn /* 7364c8945a0SNathan Whitehorn * Map the given button index for dlg_yes_labels() into our exit-code. 7374c8945a0SNathan Whitehorn */ 7384c8945a0SNathan Whitehorn int 7394c8945a0SNathan Whitehorn dlg_yes_buttoncode(int button) 7404c8945a0SNathan Whitehorn { 7414c8945a0SNathan Whitehorn int result = DLG_EXIT_ERROR; 7424c8945a0SNathan Whitehorn 7434c8945a0SNathan Whitehorn if (dialog_vars.extra_button) { 7444c8945a0SNathan Whitehorn result = dlg_ok_buttoncode(button); 7454c8945a0SNathan Whitehorn } else if (button == 0) { 7464c8945a0SNathan Whitehorn result = DLG_EXIT_OK; 7474c8945a0SNathan Whitehorn } else if (button == 1) { 7484c8945a0SNathan Whitehorn result = DLG_EXIT_CANCEL; 7494c8945a0SNathan Whitehorn } else if (button == 2 && dialog_vars.help_button) { 7504c8945a0SNathan Whitehorn result = DLG_EXIT_HELP; 7514c8945a0SNathan Whitehorn } 7524c8945a0SNathan Whitehorn 7534c8945a0SNathan Whitehorn return result; 7544c8945a0SNathan Whitehorn } 7554c8945a0SNathan Whitehorn 7564c8945a0SNathan Whitehorn /* 7574c8945a0SNathan Whitehorn * Return the next index in labels[]; 7584c8945a0SNathan Whitehorn */ 7594c8945a0SNathan Whitehorn int 7604c8945a0SNathan Whitehorn dlg_next_button(const char **labels, int button) 7614c8945a0SNathan Whitehorn { 762*2a3e3873SBaptiste Daroussin if (button < -1) 763*2a3e3873SBaptiste Daroussin button = -1; 764*2a3e3873SBaptiste Daroussin 765*2a3e3873SBaptiste Daroussin if (labels[button + 1] != 0) { 7664c8945a0SNathan Whitehorn ++button; 767*2a3e3873SBaptiste Daroussin } else { 7684c8945a0SNathan Whitehorn button = MIN_BUTTON; 769*2a3e3873SBaptiste Daroussin } 7704c8945a0SNathan Whitehorn return button; 7714c8945a0SNathan Whitehorn } 7724c8945a0SNathan Whitehorn 7734c8945a0SNathan Whitehorn /* 7744c8945a0SNathan Whitehorn * Return the previous index in labels[]; 7754c8945a0SNathan Whitehorn */ 7764c8945a0SNathan Whitehorn int 7774c8945a0SNathan Whitehorn dlg_prev_button(const char **labels, int button) 7784c8945a0SNathan Whitehorn { 779*2a3e3873SBaptiste Daroussin if (button > MIN_BUTTON) { 7804c8945a0SNathan Whitehorn --button; 781*2a3e3873SBaptiste Daroussin } else { 782*2a3e3873SBaptiste Daroussin if (button < -1) 783*2a3e3873SBaptiste Daroussin button = -1; 784*2a3e3873SBaptiste Daroussin 7854c8945a0SNathan Whitehorn while (labels[button + 1] != 0) 7864c8945a0SNathan Whitehorn ++button; 7874c8945a0SNathan Whitehorn } 7884c8945a0SNathan Whitehorn return button; 7894c8945a0SNathan Whitehorn } 790