1217309Snwhitehorn/* 2251843Sbapt * $Id: buttons.c,v 1.94 2012/12/30 20:51:01 tom Exp $ 3217309Snwhitehorn * 4220749Snwhitehorn * buttons.c -- draw buttons, e.g., OK/Cancel 5217309Snwhitehorn * 6251843Sbapt * Copyright 2000-2011,2012 Thomas E. Dickey 7217309Snwhitehorn * 8217309Snwhitehorn * This program is free software; you can redistribute it and/or modify 9217309Snwhitehorn * it under the terms of the GNU Lesser General Public License, version 2.1 10217309Snwhitehorn * as published by the Free Software Foundation. 11217309Snwhitehorn * 12217309Snwhitehorn * This program is distributed in the hope that it will be useful, but 13217309Snwhitehorn * WITHOUT ANY WARRANTY; without even the implied warranty of 14217309Snwhitehorn * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15217309Snwhitehorn * Lesser General Public License for more details. 16217309Snwhitehorn * 17217309Snwhitehorn * You should have received a copy of the GNU Lesser General Public 18217309Snwhitehorn * License along with this program; if not, write to 19217309Snwhitehorn * Free Software Foundation, Inc. 20217309Snwhitehorn * 51 Franklin St., Fifth Floor 21217309Snwhitehorn * Boston, MA 02110, USA. 22217309Snwhitehorn */ 23217309Snwhitehorn 24217309Snwhitehorn#include <dialog.h> 25217309Snwhitehorn#include <dlg_keys.h> 26217309Snwhitehorn 27217309Snwhitehorn#ifdef NEED_WCHAR_H 28217309Snwhitehorn#include <wchar.h> 29217309Snwhitehorn#endif 30217309Snwhitehorn 31251843Sbapt#define MIN_BUTTON (-dialog_state.visit_cols) 32217309Snwhitehorn 33217309Snwhitehornstatic void 34217309Snwhitehorncenter_label(char *buffer, int longest, const char *label) 35217309Snwhitehorn{ 36217309Snwhitehorn int len = dlg_count_columns(label); 37217309Snwhitehorn int left = 0, right = 0; 38217309Snwhitehorn 39217309Snwhitehorn *buffer = 0; 40217309Snwhitehorn if (len < longest) { 41217309Snwhitehorn left = (longest - len) / 2; 42217309Snwhitehorn right = (longest - len - left); 43217309Snwhitehorn if (left > 0) 44217309Snwhitehorn sprintf(buffer, "%*s", left, " "); 45217309Snwhitehorn } 46217309Snwhitehorn strcat(buffer, label); 47217309Snwhitehorn if (right > 0) 48217309Snwhitehorn sprintf(buffer + strlen(buffer), "%*s", right, " "); 49217309Snwhitehorn} 50217309Snwhitehorn 51217309Snwhitehorn/* 52217309Snwhitehorn * Parse a multibyte character out of the string, set it past the parsed 53217309Snwhitehorn * character. 54217309Snwhitehorn */ 55217309Snwhitehornstatic int 56217309Snwhitehornstring_to_char(const char **stringp) 57217309Snwhitehorn{ 58217309Snwhitehorn int result; 59217309Snwhitehorn#ifdef USE_WIDE_CURSES 60217309Snwhitehorn const char *string = *stringp; 61217309Snwhitehorn size_t have = strlen(string); 62217309Snwhitehorn size_t check; 63217309Snwhitehorn size_t len; 64217309Snwhitehorn wchar_t cmp2[2]; 65217309Snwhitehorn mbstate_t state; 66217309Snwhitehorn 67217309Snwhitehorn memset(&state, 0, sizeof(state)); 68217309Snwhitehorn len = mbrlen(string, have, &state); 69217309Snwhitehorn if ((int) len > 0 && len <= have) { 70217309Snwhitehorn memset(&state, 0, sizeof(state)); 71217309Snwhitehorn memset(cmp2, 0, sizeof(cmp2)); 72217309Snwhitehorn check = mbrtowc(cmp2, string, len, &state); 73217309Snwhitehorn if ((int) check <= 0) 74217309Snwhitehorn cmp2[0] = 0; 75217309Snwhitehorn *stringp += len; 76217309Snwhitehorn } else { 77217309Snwhitehorn cmp2[0] = UCH(*string); 78217309Snwhitehorn *stringp += 1; 79217309Snwhitehorn } 80217309Snwhitehorn result = cmp2[0]; 81217309Snwhitehorn#else 82217309Snwhitehorn const char *string = *stringp; 83217309Snwhitehorn result = UCH(*string); 84217309Snwhitehorn *stringp += 1; 85217309Snwhitehorn#endif 86217309Snwhitehorn return result; 87217309Snwhitehorn} 88217309Snwhitehorn 89251843Sbaptstatic size_t 90251843Sbaptcount_labels(const char **labels) 91251843Sbapt{ 92251843Sbapt size_t result = 0; 93251843Sbapt if (labels != 0) { 94251843Sbapt while (*labels++ != 0) { 95251843Sbapt ++result; 96251843Sbapt } 97251843Sbapt } 98251843Sbapt return result; 99251843Sbapt} 100251843Sbapt 101217309Snwhitehorn/* 102251843Sbapt * Check if the latest key should be added to the hotkey list. 103251843Sbapt */ 104251843Sbaptstatic int 105251843Sbaptwas_hotkey(int this_key, int *used_keys, size_t next) 106251843Sbapt{ 107251843Sbapt int result = FALSE; 108251843Sbapt 109251843Sbapt if (next != 0) { 110251843Sbapt size_t n; 111251843Sbapt for (n = 0; n < next; ++n) { 112251843Sbapt if (used_keys[n] == this_key) { 113251843Sbapt result = TRUE; 114251843Sbapt break; 115251843Sbapt } 116251843Sbapt } 117251843Sbapt } 118251843Sbapt return result; 119251843Sbapt} 120251843Sbapt 121251843Sbapt/* 122251843Sbapt * Determine the hot-keys for a set of button-labels. Normally these are 123251843Sbapt * the first uppercase character in each label. However, if more than one 124251843Sbapt * button has the same first-uppercase, then we will (attempt to) look for 125251843Sbapt * an alternate. 126251843Sbapt * 127251843Sbapt * This allocates data which must be freed by the caller. 128251843Sbapt */ 129251843Sbaptstatic int * 130251843Sbaptget_hotkeys(const char **labels) 131251843Sbapt{ 132251843Sbapt int *result = 0; 133251843Sbapt size_t count = count_labels(labels); 134251843Sbapt size_t n; 135251843Sbapt 136251843Sbapt if ((result = dlg_calloc(int, count + 1)) != 0) { 137251843Sbapt for (n = 0; n < count; ++n) { 138251843Sbapt const char *label = labels[n]; 139251843Sbapt const int *indx = dlg_index_wchars(label); 140251843Sbapt int limit = dlg_count_wchars(label); 141251843Sbapt int i; 142251843Sbapt 143251843Sbapt for (i = 0; i < limit; ++i) { 144251843Sbapt int first = indx[i]; 145251843Sbapt int check = UCH(label[first]); 146251843Sbapt#ifdef USE_WIDE_CURSES 147251843Sbapt int last = indx[i + 1]; 148251843Sbapt if ((last - first) != 1) { 149251843Sbapt const char *temp = (label + first); 150251843Sbapt check = string_to_char(&temp); 151251843Sbapt } 152251843Sbapt#endif 153251843Sbapt if (dlg_isupper(check) && !was_hotkey(check, result, n)) { 154251843Sbapt result[n] = check; 155251843Sbapt break; 156251843Sbapt } 157251843Sbapt } 158251843Sbapt } 159251843Sbapt } 160251843Sbapt return result; 161251843Sbapt} 162251843Sbapt 163251843Sbapt/* 164217309Snwhitehorn * Print a button 165217309Snwhitehorn */ 166217309Snwhitehornstatic void 167251843Sbaptprint_button(WINDOW *win, char *label, int hotkey, int y, int x, int selected) 168217309Snwhitehorn{ 169217309Snwhitehorn int i; 170217309Snwhitehorn int state = 0; 171217309Snwhitehorn const int *indx = dlg_index_wchars(label); 172217309Snwhitehorn int limit = dlg_count_wchars(label); 173217309Snwhitehorn chtype key_attr = (selected 174217309Snwhitehorn ? button_key_active_attr 175217309Snwhitehorn : button_key_inactive_attr); 176217309Snwhitehorn chtype label_attr = (selected 177217309Snwhitehorn ? button_label_active_attr 178217309Snwhitehorn : button_label_inactive_attr); 179217309Snwhitehorn 180217309Snwhitehorn (void) wmove(win, y, x); 181251843Sbapt (void) wattrset(win, selected 182251843Sbapt ? button_active_attr 183251843Sbapt : button_inactive_attr); 184217309Snwhitehorn (void) waddstr(win, "<"); 185251843Sbapt (void) wattrset(win, label_attr); 186217309Snwhitehorn for (i = 0; i < limit; ++i) { 187251843Sbapt int check; 188217309Snwhitehorn int first = indx[i]; 189217309Snwhitehorn int last = indx[i + 1]; 190217309Snwhitehorn 191217309Snwhitehorn switch (state) { 192217309Snwhitehorn case 0: 193251843Sbapt check = UCH(label[first]); 194217309Snwhitehorn#ifdef USE_WIDE_CURSES 195217309Snwhitehorn if ((last - first) != 1) { 196217309Snwhitehorn const char *temp = (label + first); 197251843Sbapt check = string_to_char(&temp); 198217309Snwhitehorn } 199217309Snwhitehorn#endif 200251843Sbapt if (check == hotkey) { 201251843Sbapt (void) wattrset(win, key_attr); 202217309Snwhitehorn state = 1; 203217309Snwhitehorn } 204217309Snwhitehorn break; 205217309Snwhitehorn case 1: 206217309Snwhitehorn wattrset(win, label_attr); 207217309Snwhitehorn state = 2; 208217309Snwhitehorn break; 209217309Snwhitehorn } 210217309Snwhitehorn waddnstr(win, label + first, last - first); 211217309Snwhitehorn } 212251843Sbapt (void) wattrset(win, selected 213251843Sbapt ? button_active_attr 214251843Sbapt : button_inactive_attr); 215217309Snwhitehorn (void) waddstr(win, ">"); 216217309Snwhitehorn (void) wmove(win, y, x + ((int) strspn(label, " ")) + 1); 217217309Snwhitehorn} 218217309Snwhitehorn 219217309Snwhitehorn/* 220217309Snwhitehorn * Count the buttons in the list. 221217309Snwhitehorn */ 222217309Snwhitehornint 223217309Snwhitehorndlg_button_count(const char **labels) 224217309Snwhitehorn{ 225217309Snwhitehorn int result = 0; 226217309Snwhitehorn while (*labels++ != 0) 227217309Snwhitehorn ++result; 228217309Snwhitehorn return result; 229217309Snwhitehorn} 230217309Snwhitehorn 231217309Snwhitehorn/* 232217309Snwhitehorn * Compute the size of the button array in columns. Return the total number of 233217309Snwhitehorn * columns in *length, and the longest button's columns in *longest 234217309Snwhitehorn */ 235217309Snwhitehornvoid 236217309Snwhitehorndlg_button_sizes(const char **labels, 237217309Snwhitehorn int vertical, 238217309Snwhitehorn int *longest, 239217309Snwhitehorn int *length) 240217309Snwhitehorn{ 241217309Snwhitehorn int n; 242217309Snwhitehorn 243217309Snwhitehorn *length = 0; 244217309Snwhitehorn *longest = 0; 245217309Snwhitehorn for (n = 0; labels[n] != 0; n++) { 246217309Snwhitehorn if (vertical) { 247217309Snwhitehorn *length += 1; 248217309Snwhitehorn *longest = 1; 249217309Snwhitehorn } else { 250217309Snwhitehorn int len = dlg_count_columns(labels[n]); 251217309Snwhitehorn if (len > *longest) 252217309Snwhitehorn *longest = len; 253217309Snwhitehorn *length += len; 254217309Snwhitehorn } 255217309Snwhitehorn } 256217309Snwhitehorn /* 257217309Snwhitehorn * If we can, make all of the buttons the same size. This is only optional 258217309Snwhitehorn * for buttons laid out horizontally. 259217309Snwhitehorn */ 260217309Snwhitehorn if (*longest < 6 - (*longest & 1)) 261217309Snwhitehorn *longest = 6 - (*longest & 1); 262217309Snwhitehorn if (!vertical) 263217309Snwhitehorn *length = *longest * n; 264217309Snwhitehorn} 265217309Snwhitehorn 266217309Snwhitehorn/* 267217309Snwhitehorn * Compute the size of the button array. 268217309Snwhitehorn */ 269217309Snwhitehornint 270217309Snwhitehorndlg_button_x_step(const char **labels, int limit, int *gap, int *margin, int *step) 271217309Snwhitehorn{ 272217309Snwhitehorn int count = dlg_button_count(labels); 273217309Snwhitehorn int longest; 274217309Snwhitehorn int length; 275217309Snwhitehorn int unused; 276217309Snwhitehorn int used; 277251843Sbapt int result; 278217309Snwhitehorn 279251843Sbapt *margin = 0; 280251843Sbapt if (count != 0) { 281251843Sbapt dlg_button_sizes(labels, FALSE, &longest, &length); 282251843Sbapt used = (length + (count * 2)); 283251843Sbapt unused = limit - used; 284217309Snwhitehorn 285251843Sbapt if ((*gap = unused / (count + 3)) <= 0) { 286251843Sbapt if ((*gap = unused / (count + 1)) <= 0) 287251843Sbapt *gap = 1; 288251843Sbapt *margin = *gap; 289251843Sbapt } else { 290251843Sbapt *margin = *gap * 2; 291251843Sbapt } 292251843Sbapt *step = *gap + (used + count - 1) / count; 293251843Sbapt result = (*gap > 0) && (unused >= 0); 294217309Snwhitehorn } else { 295251843Sbapt result = 0; 296217309Snwhitehorn } 297251843Sbapt return result; 298217309Snwhitehorn} 299217309Snwhitehorn 300217309Snwhitehorn/* 301217309Snwhitehorn * Make sure there is enough space for the buttons 302217309Snwhitehorn */ 303217309Snwhitehornvoid 304217309Snwhitehorndlg_button_layout(const char **labels, int *limit) 305217309Snwhitehorn{ 306217309Snwhitehorn int width = 1; 307217309Snwhitehorn int gap, margin, step; 308217309Snwhitehorn 309217309Snwhitehorn if (labels != 0 && dlg_button_count(labels)) { 310217309Snwhitehorn while (!dlg_button_x_step(labels, width, &gap, &margin, &step)) 311217309Snwhitehorn ++width; 312217309Snwhitehorn width += (4 * MARGIN); 313217309Snwhitehorn if (width > COLS) 314217309Snwhitehorn width = COLS; 315217309Snwhitehorn if (width > *limit) 316217309Snwhitehorn *limit = width; 317217309Snwhitehorn } 318217309Snwhitehorn} 319217309Snwhitehorn 320217309Snwhitehorn/* 321217309Snwhitehorn * Print a list of buttons at the given position. 322217309Snwhitehorn */ 323217309Snwhitehornvoid 324217309Snwhitehorndlg_draw_buttons(WINDOW *win, 325217309Snwhitehorn int y, int x, 326217309Snwhitehorn const char **labels, 327217309Snwhitehorn int selected, 328217309Snwhitehorn int vertical, 329217309Snwhitehorn int limit) 330217309Snwhitehorn{ 331220749Snwhitehorn chtype save = dlg_get_attrs(win); 332217309Snwhitehorn int n; 333217309Snwhitehorn int step = 0; 334217309Snwhitehorn int length; 335217309Snwhitehorn int longest; 336217309Snwhitehorn int final_x; 337217309Snwhitehorn int final_y; 338217309Snwhitehorn int gap; 339217309Snwhitehorn int margin; 340217309Snwhitehorn size_t need; 341217309Snwhitehorn char *buffer; 342217309Snwhitehorn 343217309Snwhitehorn dlg_mouse_setbase(getbegx(win), getbegy(win)); 344217309Snwhitehorn 345217309Snwhitehorn getyx(win, final_y, final_x); 346217309Snwhitehorn 347217309Snwhitehorn dlg_button_sizes(labels, vertical, &longest, &length); 348217309Snwhitehorn 349217309Snwhitehorn if (vertical) { 350217309Snwhitehorn y += 1; 351217309Snwhitehorn step = 1; 352217309Snwhitehorn } else { 353217309Snwhitehorn dlg_button_x_step(labels, limit, &gap, &margin, &step); 354217309Snwhitehorn x += margin; 355217309Snwhitehorn } 356217309Snwhitehorn 357217309Snwhitehorn /* 358217309Snwhitehorn * Allocate a buffer big enough for any label. 359217309Snwhitehorn */ 360217309Snwhitehorn need = (size_t) longest; 361251843Sbapt if (need != 0) { 362251843Sbapt int *hotkeys = get_hotkeys(labels); 363251843Sbapt assert_ptr(hotkeys, "dlg_draw_buttons"); 364217309Snwhitehorn 365251843Sbapt for (n = 0; labels[n] != 0; ++n) { 366251843Sbapt need += strlen(labels[n]) + 1; 367251843Sbapt } 368251843Sbapt buffer = dlg_malloc(char, need); 369251843Sbapt assert_ptr(buffer, "dlg_draw_buttons"); 370217309Snwhitehorn 371251843Sbapt /* 372251843Sbapt * Draw the labels. 373251843Sbapt */ 374251843Sbapt for (n = 0; labels[n] != 0; n++) { 375251843Sbapt center_label(buffer, longest, labels[n]); 376251843Sbapt mouse_mkbutton(y, x, dlg_count_columns(buffer), n); 377251843Sbapt print_button(win, buffer, hotkeys[n], y, x, 378251843Sbapt (selected == n) || (n == 0 && selected < 0)); 379251843Sbapt if (selected == n) 380251843Sbapt getyx(win, final_y, final_x); 381251843Sbapt 382251843Sbapt if (vertical) { 383251843Sbapt if ((y += step) > limit) 384251843Sbapt break; 385251843Sbapt } else { 386251843Sbapt if ((x += step) > limit) 387251843Sbapt break; 388251843Sbapt } 389217309Snwhitehorn } 390251843Sbapt (void) wmove(win, final_y, final_x); 391251843Sbapt wrefresh(win); 392251843Sbapt (void) wattrset(win, save); 393251843Sbapt free(buffer); 394251843Sbapt free(hotkeys); 395217309Snwhitehorn } 396217309Snwhitehorn} 397217309Snwhitehorn 398217309Snwhitehorn/* 399217309Snwhitehorn * Match a given character against the beginning of the string, ignoring case 400217309Snwhitehorn * of the given character. The matching string must begin with an uppercase 401217309Snwhitehorn * character. 402217309Snwhitehorn */ 403217309Snwhitehornint 404217309Snwhitehorndlg_match_char(int ch, const char *string) 405217309Snwhitehorn{ 406217309Snwhitehorn if (string != 0) { 407217309Snwhitehorn int cmp2 = string_to_char(&string); 408217309Snwhitehorn#ifdef USE_WIDE_CURSES 409217309Snwhitehorn wint_t cmp1 = dlg_toupper(ch); 410217309Snwhitehorn if (cmp2 != 0 && (wchar_t) cmp1 == (wchar_t) dlg_toupper(cmp2)) { 411217309Snwhitehorn return TRUE; 412217309Snwhitehorn } 413217309Snwhitehorn#else 414217309Snwhitehorn if (ch > 0 && ch < 256) { 415217309Snwhitehorn if (dlg_toupper(ch) == dlg_toupper(cmp2)) 416217309Snwhitehorn return TRUE; 417217309Snwhitehorn } 418217309Snwhitehorn#endif 419217309Snwhitehorn } 420217309Snwhitehorn return FALSE; 421217309Snwhitehorn} 422217309Snwhitehorn 423217309Snwhitehorn/* 424217309Snwhitehorn * Find the first uppercase character in the label, which we may use for an 425217309Snwhitehorn * abbreviation. 426217309Snwhitehorn */ 427217309Snwhitehornint 428217309Snwhitehorndlg_button_to_char(const char *label) 429217309Snwhitehorn{ 430217309Snwhitehorn int cmp = -1; 431217309Snwhitehorn 432217309Snwhitehorn while (*label != 0) { 433217309Snwhitehorn cmp = string_to_char(&label); 434217309Snwhitehorn if (dlg_isupper(cmp)) { 435217309Snwhitehorn break; 436217309Snwhitehorn } 437217309Snwhitehorn } 438217309Snwhitehorn return cmp; 439217309Snwhitehorn} 440217309Snwhitehorn 441217309Snwhitehorn/* 442217309Snwhitehorn * Given a list of button labels, and a character which may be the abbreviation 443217309Snwhitehorn * for one, find it, if it exists. An abbreviation will be the first character 444217309Snwhitehorn * which happens to be capitalized in the label. 445217309Snwhitehorn */ 446217309Snwhitehornint 447217309Snwhitehorndlg_char_to_button(int ch, const char **labels) 448217309Snwhitehorn{ 449251843Sbapt int result = DLG_EXIT_UNKNOWN; 450251843Sbapt 451217309Snwhitehorn if (labels != 0) { 452251843Sbapt int *hotkeys = get_hotkeys(labels); 453217309Snwhitehorn int j; 454217309Snwhitehorn 455217309Snwhitehorn ch = (int) dlg_toupper(dlg_last_getc()); 456251843Sbapt 457251843Sbapt if (hotkeys != 0) { 458251843Sbapt for (j = 0; labels[j] != 0; ++j) { 459251843Sbapt if (ch == hotkeys[j]) { 460251843Sbapt dlg_flush_getc(); 461251843Sbapt result = j; 462251843Sbapt break; 463251843Sbapt } 464217309Snwhitehorn } 465251843Sbapt free(hotkeys); 466217309Snwhitehorn } 467217309Snwhitehorn } 468251843Sbapt 469251843Sbapt return result; 470217309Snwhitehorn} 471217309Snwhitehorn 472217309Snwhitehornstatic const char * 473217309Snwhitehornmy_yes_label(void) 474217309Snwhitehorn{ 475217309Snwhitehorn return (dialog_vars.yes_label != NULL) 476217309Snwhitehorn ? dialog_vars.yes_label 477217309Snwhitehorn : _("Yes"); 478217309Snwhitehorn} 479217309Snwhitehorn 480217309Snwhitehornstatic const char * 481217309Snwhitehornmy_no_label(void) 482217309Snwhitehorn{ 483217309Snwhitehorn return (dialog_vars.no_label != NULL) 484217309Snwhitehorn ? dialog_vars.no_label 485217309Snwhitehorn : _("No"); 486217309Snwhitehorn} 487217309Snwhitehorn 488217309Snwhitehornstatic const char * 489217309Snwhitehornmy_ok_label(void) 490217309Snwhitehorn{ 491217309Snwhitehorn return (dialog_vars.ok_label != NULL) 492217309Snwhitehorn ? dialog_vars.ok_label 493217309Snwhitehorn : _("OK"); 494217309Snwhitehorn} 495217309Snwhitehorn 496217309Snwhitehornstatic const char * 497217309Snwhitehornmy_cancel_label(void) 498217309Snwhitehorn{ 499217309Snwhitehorn return (dialog_vars.cancel_label != NULL) 500217309Snwhitehorn ? dialog_vars.cancel_label 501217309Snwhitehorn : _("Cancel"); 502217309Snwhitehorn} 503217309Snwhitehorn 504217309Snwhitehornstatic const char * 505217309Snwhitehornmy_exit_label(void) 506217309Snwhitehorn{ 507217309Snwhitehorn return (dialog_vars.exit_label != NULL) 508217309Snwhitehorn ? dialog_vars.exit_label 509217309Snwhitehorn : _("EXIT"); 510217309Snwhitehorn} 511217309Snwhitehorn 512217309Snwhitehornstatic const char * 513217309Snwhitehornmy_extra_label(void) 514217309Snwhitehorn{ 515217309Snwhitehorn return (dialog_vars.extra_label != NULL) 516217309Snwhitehorn ? dialog_vars.extra_label 517217309Snwhitehorn : _("Extra"); 518217309Snwhitehorn} 519217309Snwhitehorn 520217309Snwhitehornstatic const char * 521217309Snwhitehornmy_help_label(void) 522217309Snwhitehorn{ 523217309Snwhitehorn return (dialog_vars.help_label != NULL) 524217309Snwhitehorn ? dialog_vars.help_label 525217309Snwhitehorn : _("Help"); 526217309Snwhitehorn} 527217309Snwhitehorn 528217309Snwhitehorn/* 529217309Snwhitehorn * Return a list of button labels. 530217309Snwhitehorn */ 531217309Snwhitehornconst char ** 532217309Snwhitehorndlg_exit_label(void) 533217309Snwhitehorn{ 534217309Snwhitehorn const char **result; 535224014Snwhitehorn DIALOG_VARS save; 536217309Snwhitehorn 537217309Snwhitehorn if (dialog_vars.extra_button) { 538224014Snwhitehorn dlg_save_vars(&save); 539224014Snwhitehorn dialog_vars.nocancel = TRUE; 540217309Snwhitehorn result = dlg_ok_labels(); 541224014Snwhitehorn dlg_restore_vars(&save); 542217309Snwhitehorn } else { 543217309Snwhitehorn static const char *labels[3]; 544217309Snwhitehorn int n = 0; 545217309Snwhitehorn 546224014Snwhitehorn if (!dialog_vars.nook) 547224014Snwhitehorn labels[n++] = my_exit_label(); 548217309Snwhitehorn if (dialog_vars.help_button) 549217309Snwhitehorn labels[n++] = my_help_label(); 550224014Snwhitehorn if (n == 0) 551224014Snwhitehorn labels[n++] = my_exit_label(); 552217309Snwhitehorn labels[n] = 0; 553217309Snwhitehorn 554217309Snwhitehorn result = labels; 555217309Snwhitehorn } 556217309Snwhitehorn return result; 557217309Snwhitehorn} 558217309Snwhitehorn 559217309Snwhitehorn/* 560217309Snwhitehorn * Map the given button index for dlg_exit_label() into our exit-code. 561217309Snwhitehorn */ 562217309Snwhitehornint 563217309Snwhitehorndlg_exit_buttoncode(int button) 564217309Snwhitehorn{ 565224014Snwhitehorn int result; 566224014Snwhitehorn DIALOG_VARS save; 567224014Snwhitehorn 568224014Snwhitehorn dlg_save_vars(&save); 569224014Snwhitehorn dialog_vars.nocancel = TRUE; 570224014Snwhitehorn 571224014Snwhitehorn result = dlg_ok_buttoncode(button); 572224014Snwhitehorn 573224014Snwhitehorn dlg_restore_vars(&save); 574224014Snwhitehorn 575224014Snwhitehorn return result; 576217309Snwhitehorn} 577217309Snwhitehorn 578217309Snwhitehornconst char ** 579217309Snwhitehorndlg_ok_label(void) 580217309Snwhitehorn{ 581251843Sbapt static const char *labels[4]; 582217309Snwhitehorn int n = 0; 583217309Snwhitehorn 584217309Snwhitehorn labels[n++] = my_ok_label(); 585251843Sbapt if (dialog_vars.extra_button) 586251843Sbapt labels[n++] = my_extra_label(); 587217309Snwhitehorn if (dialog_vars.help_button) 588217309Snwhitehorn labels[n++] = my_help_label(); 589217309Snwhitehorn labels[n] = 0; 590217309Snwhitehorn return labels; 591217309Snwhitehorn} 592217309Snwhitehorn 593217309Snwhitehorn/* 594217309Snwhitehorn * Return a list of button labels for the OK/Cancel group. 595217309Snwhitehorn */ 596217309Snwhitehornconst char ** 597217309Snwhitehorndlg_ok_labels(void) 598217309Snwhitehorn{ 599217309Snwhitehorn static const char *labels[5]; 600217309Snwhitehorn int n = 0; 601217309Snwhitehorn 602217309Snwhitehorn if (!dialog_vars.nook) 603217309Snwhitehorn labels[n++] = my_ok_label(); 604217309Snwhitehorn if (dialog_vars.extra_button) 605217309Snwhitehorn labels[n++] = my_extra_label(); 606217309Snwhitehorn if (!dialog_vars.nocancel) 607217309Snwhitehorn labels[n++] = my_cancel_label(); 608217309Snwhitehorn if (dialog_vars.help_button) 609217309Snwhitehorn labels[n++] = my_help_label(); 610217309Snwhitehorn labels[n] = 0; 611217309Snwhitehorn return labels; 612217309Snwhitehorn} 613217309Snwhitehorn 614217309Snwhitehorn/* 615217309Snwhitehorn * Map the given button index for dlg_ok_labels() into our exit-code 616217309Snwhitehorn */ 617217309Snwhitehornint 618217309Snwhitehorndlg_ok_buttoncode(int button) 619217309Snwhitehorn{ 620217309Snwhitehorn int result = DLG_EXIT_ERROR; 621217309Snwhitehorn int n = !dialog_vars.nook; 622217309Snwhitehorn 623217309Snwhitehorn if (!dialog_vars.nook && (button <= 0)) { 624217309Snwhitehorn result = DLG_EXIT_OK; 625217309Snwhitehorn } else if (dialog_vars.extra_button && (button == n++)) { 626217309Snwhitehorn result = DLG_EXIT_EXTRA; 627217309Snwhitehorn } else if (!dialog_vars.nocancel && (button == n++)) { 628217309Snwhitehorn result = DLG_EXIT_CANCEL; 629217309Snwhitehorn } else if (dialog_vars.help_button && (button == n)) { 630217309Snwhitehorn result = DLG_EXIT_HELP; 631217309Snwhitehorn } 632251843Sbapt dlg_trace_msg("# dlg_ok_buttoncode(%d) = %d\n", button, result); 633217309Snwhitehorn return result; 634217309Snwhitehorn} 635217309Snwhitehorn 636217309Snwhitehorn/* 637217309Snwhitehorn * Given that we're using dlg_ok_labels() to list buttons, find the next index 638217309Snwhitehorn * in the list of buttons. The 'extra' parameter if negative provides a way to 639217309Snwhitehorn * enumerate extra active areas on the widget. 640217309Snwhitehorn */ 641217309Snwhitehornint 642217309Snwhitehorndlg_next_ok_buttonindex(int current, int extra) 643217309Snwhitehorn{ 644217309Snwhitehorn int result = current + 1; 645217309Snwhitehorn 646217309Snwhitehorn if (current >= 0 647217309Snwhitehorn && dlg_ok_buttoncode(result) < 0) 648217309Snwhitehorn result = extra; 649217309Snwhitehorn return result; 650217309Snwhitehorn} 651217309Snwhitehorn 652217309Snwhitehorn/* 653217309Snwhitehorn * Similarly, find the previous button index. 654217309Snwhitehorn */ 655217309Snwhitehornint 656217309Snwhitehorndlg_prev_ok_buttonindex(int current, int extra) 657217309Snwhitehorn{ 658217309Snwhitehorn int result = current - 1; 659217309Snwhitehorn 660217309Snwhitehorn if (result < extra) { 661217309Snwhitehorn for (result = 0; dlg_ok_buttoncode(result + 1) >= 0; ++result) { 662217309Snwhitehorn ; 663217309Snwhitehorn } 664217309Snwhitehorn } 665217309Snwhitehorn return result; 666217309Snwhitehorn} 667217309Snwhitehorn 668217309Snwhitehorn/* 669217309Snwhitehorn * Find the button-index for the "OK" or "Cancel" button, according to 670217309Snwhitehorn * whether --defaultno is given. If --nocancel was given, we always return 671251843Sbapt * the index for the first button (usually "OK" unless --nook was used). 672217309Snwhitehorn */ 673217309Snwhitehornint 674217309Snwhitehorndlg_defaultno_button(void) 675217309Snwhitehorn{ 676217309Snwhitehorn int result = 0; 677217309Snwhitehorn 678217309Snwhitehorn if (dialog_vars.defaultno && !dialog_vars.nocancel) { 679217309Snwhitehorn while (dlg_ok_buttoncode(result) != DLG_EXIT_CANCEL) 680217309Snwhitehorn ++result; 681217309Snwhitehorn } 682251843Sbapt dlg_trace_msg("# dlg_defaultno_button() = %d\n", result); 683217309Snwhitehorn return result; 684217309Snwhitehorn} 685217309Snwhitehorn 686217309Snwhitehorn/* 687251843Sbapt * Find the button-index for a button named with --default-button. If the 688251843Sbapt * option was not specified, or if the selected button does not exist, return 689251843Sbapt * the index of the first button (usually "OK" unless --nook was used). 690251843Sbapt */ 691251843Sbaptint 692251843Sbaptdlg_default_button(void) 693251843Sbapt{ 694251843Sbapt int i, n; 695251843Sbapt int result = 0; 696251843Sbapt 697251843Sbapt if (dialog_vars.default_button >= 0) { 698251843Sbapt for (i = 0; (n = dlg_ok_buttoncode(i)) >= 0; i++) { 699251843Sbapt if (n == dialog_vars.default_button) { 700251843Sbapt result = i; 701251843Sbapt break; 702251843Sbapt } 703251843Sbapt } 704251843Sbapt } 705251843Sbapt dlg_trace_msg("# dlg_default_button() = %d\n", result); 706251843Sbapt return result; 707251843Sbapt} 708251843Sbapt 709251843Sbapt/* 710217309Snwhitehorn * Return a list of buttons for Yes/No labels. 711217309Snwhitehorn */ 712217309Snwhitehornconst char ** 713217309Snwhitehorndlg_yes_labels(void) 714217309Snwhitehorn{ 715217309Snwhitehorn const char **result; 716217309Snwhitehorn 717217309Snwhitehorn if (dialog_vars.extra_button) { 718217309Snwhitehorn result = dlg_ok_labels(); 719217309Snwhitehorn } else { 720217309Snwhitehorn static const char *labels[4]; 721217309Snwhitehorn int n = 0; 722217309Snwhitehorn 723217309Snwhitehorn labels[n++] = my_yes_label(); 724217309Snwhitehorn labels[n++] = my_no_label(); 725217309Snwhitehorn if (dialog_vars.help_button) 726217309Snwhitehorn labels[n++] = my_help_label(); 727217309Snwhitehorn labels[n] = 0; 728217309Snwhitehorn 729217309Snwhitehorn result = labels; 730217309Snwhitehorn } 731217309Snwhitehorn 732217309Snwhitehorn return result; 733217309Snwhitehorn} 734217309Snwhitehorn 735217309Snwhitehorn/* 736217309Snwhitehorn * Map the given button index for dlg_yes_labels() into our exit-code. 737217309Snwhitehorn */ 738217309Snwhitehornint 739217309Snwhitehorndlg_yes_buttoncode(int button) 740217309Snwhitehorn{ 741217309Snwhitehorn int result = DLG_EXIT_ERROR; 742217309Snwhitehorn 743217309Snwhitehorn if (dialog_vars.extra_button) { 744217309Snwhitehorn result = dlg_ok_buttoncode(button); 745217309Snwhitehorn } else if (button == 0) { 746217309Snwhitehorn result = DLG_EXIT_OK; 747217309Snwhitehorn } else if (button == 1) { 748217309Snwhitehorn result = DLG_EXIT_CANCEL; 749217309Snwhitehorn } else if (button == 2 && dialog_vars.help_button) { 750217309Snwhitehorn result = DLG_EXIT_HELP; 751217309Snwhitehorn } 752217309Snwhitehorn 753217309Snwhitehorn return result; 754217309Snwhitehorn} 755217309Snwhitehorn 756217309Snwhitehorn/* 757217309Snwhitehorn * Return the next index in labels[]; 758217309Snwhitehorn */ 759217309Snwhitehornint 760217309Snwhitehorndlg_next_button(const char **labels, int button) 761217309Snwhitehorn{ 762251843Sbapt if (button < -1) 763251843Sbapt button = -1; 764251843Sbapt 765251843Sbapt if (labels[button + 1] != 0) { 766217309Snwhitehorn ++button; 767251843Sbapt } else { 768217309Snwhitehorn button = MIN_BUTTON; 769251843Sbapt } 770217309Snwhitehorn return button; 771217309Snwhitehorn} 772217309Snwhitehorn 773217309Snwhitehorn/* 774217309Snwhitehorn * Return the previous index in labels[]; 775217309Snwhitehorn */ 776217309Snwhitehornint 777217309Snwhitehorndlg_prev_button(const char **labels, int button) 778217309Snwhitehorn{ 779251843Sbapt if (button > MIN_BUTTON) { 780217309Snwhitehorn --button; 781251843Sbapt } else { 782251843Sbapt if (button < -1) 783251843Sbapt button = -1; 784251843Sbapt 785217309Snwhitehorn while (labels[button + 1] != 0) 786217309Snwhitehorn ++button; 787217309Snwhitehorn } 788217309Snwhitehorn return button; 789217309Snwhitehorn} 790