diff options
Diffstat (limited to 'Build/source/utils/dialog/dialog-1.1-20110118/buttons.c')
-rw-r--r-- | Build/source/utils/dialog/dialog-1.1-20110118/buttons.c | 648 |
1 files changed, 648 insertions, 0 deletions
diff --git a/Build/source/utils/dialog/dialog-1.1-20110118/buttons.c b/Build/source/utils/dialog/dialog-1.1-20110118/buttons.c new file mode 100644 index 00000000000..d82c4558d7c --- /dev/null +++ b/Build/source/utils/dialog/dialog-1.1-20110118/buttons.c @@ -0,0 +1,648 @@ +/* + * $Id: buttons.c,v 1.84 2011/01/19 00:27:53 tom Exp $ + * + * buttons.c -- draw buttons, e.g., OK/Cancel + * + * Copyright 2000-2010,2011 Thomas E. Dickey + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License, version 2.1 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to + * Free Software Foundation, Inc. + * 51 Franklin St., Fifth Floor + * Boston, MA 02110, USA. + */ + +#include <dialog.h> +#include <dlg_keys.h> + +#ifdef NEED_WCHAR_H +#include <wchar.h> +#endif + +#define MIN_BUTTON (dialog_state.visit_items ? -1 : 0) + +static void +center_label(char *buffer, int longest, const char *label) +{ + int len = dlg_count_columns(label); + int left = 0, right = 0; + + *buffer = 0; + if (len < longest) { + left = (longest - len) / 2; + right = (longest - len - left); + if (left > 0) + sprintf(buffer, "%*s", left, " "); + } + strcat(buffer, label); + if (right > 0) + sprintf(buffer + strlen(buffer), "%*s", right, " "); +} + +/* + * Parse a multibyte character out of the string, set it past the parsed + * character. + */ +static int +string_to_char(const char **stringp) +{ + int result; +#ifdef USE_WIDE_CURSES + const char *string = *stringp; + size_t have = strlen(string); + size_t check; + size_t len; + wchar_t cmp2[2]; + mbstate_t state; + + memset(&state, 0, sizeof(state)); + len = mbrlen(string, have, &state); + if ((int) len > 0 && len <= have) { + memset(&state, 0, sizeof(state)); + memset(cmp2, 0, sizeof(cmp2)); + check = mbrtowc(cmp2, string, len, &state); + if ((int) check <= 0) + cmp2[0] = 0; + *stringp += len; + } else { + cmp2[0] = UCH(*string); + *stringp += 1; + } + result = cmp2[0]; +#else + const char *string = *stringp; + result = UCH(*string); + *stringp += 1; +#endif + return result; +} + +/* + * Print a button + */ +static void +print_button(WINDOW *win, char *label, int y, int x, int selected) +{ + int i; + int state = 0; + const int *indx = dlg_index_wchars(label); + int limit = dlg_count_wchars(label); + chtype key_attr = (selected + ? button_key_active_attr + : button_key_inactive_attr); + chtype label_attr = (selected + ? button_label_active_attr + : button_label_inactive_attr); + + (void) wmove(win, y, x); + wattrset(win, selected + ? button_active_attr + : button_inactive_attr); + (void) waddstr(win, "<"); + wattrset(win, label_attr); + for (i = 0; i < limit; ++i) { + int first = indx[i]; + int last = indx[i + 1]; + + switch (state) { + case 0: +#ifdef USE_WIDE_CURSES + if ((last - first) != 1) { + const char *temp = (label + first); + int cmp = string_to_char(&temp); + if (dlg_isupper(cmp)) { + wattrset(win, key_attr); + state = 1; + } + break; + } +#endif + if (dlg_isupper(UCH(label[first]))) { + wattrset(win, key_attr); + state = 1; + } + break; + case 1: + wattrset(win, label_attr); + state = 2; + break; + } + waddnstr(win, label + first, last - first); + } + wattrset(win, selected + ? button_active_attr + : button_inactive_attr); + (void) waddstr(win, ">"); + (void) wmove(win, y, x + ((int) strspn(label, " ")) + 1); +} + +/* + * Count the buttons in the list. + */ +int +dlg_button_count(const char **labels) +{ + int result = 0; + while (*labels++ != 0) + ++result; + return result; +} + +/* + * Compute the size of the button array in columns. Return the total number of + * columns in *length, and the longest button's columns in *longest + */ +void +dlg_button_sizes(const char **labels, + int vertical, + int *longest, + int *length) +{ + int n; + + *length = 0; + *longest = 0; + for (n = 0; labels[n] != 0; n++) { + if (vertical) { + *length += 1; + *longest = 1; + } else { + int len = dlg_count_columns(labels[n]); + if (len > *longest) + *longest = len; + *length += len; + } + } + /* + * If we can, make all of the buttons the same size. This is only optional + * for buttons laid out horizontally. + */ + if (*longest < 6 - (*longest & 1)) + *longest = 6 - (*longest & 1); + if (!vertical) + *length = *longest * n; +} + +/* + * Compute the size of the button array. + */ +int +dlg_button_x_step(const char **labels, int limit, int *gap, int *margin, int *step) +{ + int count = dlg_button_count(labels); + int longest; + int length; + int unused; + int used; + + if (count == 0) + return 0; + dlg_button_sizes(labels, FALSE, &longest, &length); + used = (length + (count * 2)); + unused = limit - used; + + if ((*gap = unused / (count + 3)) <= 0) { + if ((*gap = unused / (count + 1)) <= 0) + *gap = 1; + *margin = *gap; + } else { + *margin = *gap * 2; + } + *step = *gap + (used + count - 1) / count; + return (*gap > 0) && (unused >= 0); +} + +/* + * Make sure there is enough space for the buttons + */ +void +dlg_button_layout(const char **labels, int *limit) +{ + int width = 1; + int gap, margin, step; + + if (labels != 0 && dlg_button_count(labels)) { + while (!dlg_button_x_step(labels, width, &gap, &margin, &step)) + ++width; + width += (4 * MARGIN); + if (width > COLS) + width = COLS; + if (width > *limit) + *limit = width; + } +} + +/* + * Print a list of buttons at the given position. + */ +void +dlg_draw_buttons(WINDOW *win, + int y, int x, + const char **labels, + int selected, + int vertical, + int limit) +{ + chtype save = dlg_get_attrs(win); + int n; + int step = 0; + int length; + int longest; + int final_x; + int final_y; + int gap; + int margin; + size_t need; + char *buffer; + + dlg_mouse_setbase(getbegx(win), getbegy(win)); + + getyx(win, final_y, final_x); + + dlg_button_sizes(labels, vertical, &longest, &length); + + if (vertical) { + y += 1; + step = 1; + } else { + dlg_button_x_step(labels, limit, &gap, &margin, &step); + x += margin; + } + + /* + * Allocate a buffer big enough for any label. + */ + need = (size_t) longest; + for (n = 0; labels[n] != 0; ++n) { + need += strlen(labels[n]) + 1; + } + buffer = dlg_malloc(char, need); + assert_ptr(buffer, "dlg_draw_buttons"); + + /* + * Draw the labels. + */ + for (n = 0; labels[n] != 0; n++) { + center_label(buffer, longest, labels[n]); + mouse_mkbutton(y, x, dlg_count_columns(buffer), n); + print_button(win, buffer, y, x, + (selected == n) || (n == 0 && selected < 0)); + if (selected == n) + getyx(win, final_y, final_x); + + if (vertical) { + if ((y += step) > limit) + break; + } else { + if ((x += step) > limit) + break; + } + } + (void) wmove(win, final_y, final_x); + wrefresh(win); + free(buffer); + wattrset(win, save); +} + +/* + * Match a given character against the beginning of the string, ignoring case + * of the given character. The matching string must begin with an uppercase + * character. + */ +int +dlg_match_char(int ch, const char *string) +{ + if (string != 0) { + int cmp2 = string_to_char(&string); +#ifdef USE_WIDE_CURSES + wint_t cmp1 = dlg_toupper(ch); + if (cmp2 != 0 && (wchar_t) cmp1 == (wchar_t) dlg_toupper(cmp2)) { + return TRUE; + } +#else + if (ch > 0 && ch < 256) { + if (dlg_toupper(ch) == dlg_toupper(cmp2)) + return TRUE; + } +#endif + } + return FALSE; +} + +/* + * Find the first uppercase character in the label, which we may use for an + * abbreviation. + */ +int +dlg_button_to_char(const char *label) +{ + int cmp = -1; + + while (*label != 0) { + cmp = string_to_char(&label); + if (dlg_isupper(cmp)) { + break; + } + } + return cmp; +} + +/* + * Given a list of button labels, and a character which may be the abbreviation + * for one, find it, if it exists. An abbreviation will be the first character + * which happens to be capitalized in the label. + */ +int +dlg_char_to_button(int ch, const char **labels) +{ + if (labels != 0) { + int j; + + ch = (int) dlg_toupper(dlg_last_getc()); + for (j = 0; labels[j] != 0; ++j) { + int cmp = dlg_button_to_char(labels[j]); + if (ch == cmp) { + dlg_flush_getc(); + return j; + } + } + } + return DLG_EXIT_UNKNOWN; +} + +static const char * +my_yes_label(void) +{ + return (dialog_vars.yes_label != NULL) + ? dialog_vars.yes_label + : _("Yes"); +} + +static const char * +my_no_label(void) +{ + return (dialog_vars.no_label != NULL) + ? dialog_vars.no_label + : _("No"); +} + +static const char * +my_ok_label(void) +{ + return (dialog_vars.ok_label != NULL) + ? dialog_vars.ok_label + : _("OK"); +} + +static const char * +my_cancel_label(void) +{ + return (dialog_vars.cancel_label != NULL) + ? dialog_vars.cancel_label + : _("Cancel"); +} + +static const char * +my_exit_label(void) +{ + return (dialog_vars.exit_label != NULL) + ? dialog_vars.exit_label + : _("EXIT"); +} + +static const char * +my_extra_label(void) +{ + return (dialog_vars.extra_label != NULL) + ? dialog_vars.extra_label + : _("Extra"); +} + +static const char * +my_help_label(void) +{ + return (dialog_vars.help_label != NULL) + ? dialog_vars.help_label + : _("Help"); +} + +/* + * Return a list of button labels. + */ +const char ** +dlg_exit_label(void) +{ + const char **result; + + if (dialog_vars.extra_button) { + result = dlg_ok_labels(); + } else { + static const char *labels[3]; + int n = 0; + + labels[n++] = my_exit_label(); + if (dialog_vars.help_button) + labels[n++] = my_help_label(); + labels[n] = 0; + + result = labels; + } + return result; +} + +/* + * Map the given button index for dlg_exit_label() into our exit-code. + */ +int +dlg_exit_buttoncode(int button) +{ + return dlg_ok_buttoncode(button); +} + +const char ** +dlg_ok_label(void) +{ + static const char *labels[3]; + int n = 0; + + labels[n++] = my_ok_label(); + if (dialog_vars.help_button) + labels[n++] = my_help_label(); + labels[n] = 0; + return labels; +} + +/* + * Return a list of button labels for the OK/Cancel group. + */ +const char ** +dlg_ok_labels(void) +{ + static const char *labels[5]; + int n = 0; + + if (!dialog_vars.nook) + labels[n++] = my_ok_label(); + if (dialog_vars.extra_button) + labels[n++] = my_extra_label(); + if (!dialog_vars.nocancel) + labels[n++] = my_cancel_label(); + if (dialog_vars.help_button) + labels[n++] = my_help_label(); + labels[n] = 0; + return labels; +} + +/* + * Map the given button index for dlg_ok_labels() into our exit-code + */ +int +dlg_ok_buttoncode(int button) +{ + int result = DLG_EXIT_ERROR; + int n = !dialog_vars.nook; + + if (!dialog_vars.nook && (button <= 0)) { + result = DLG_EXIT_OK; + } else if (dialog_vars.extra_button && (button == n++)) { + result = DLG_EXIT_EXTRA; + } else if (!dialog_vars.nocancel && (button == n++)) { + result = DLG_EXIT_CANCEL; + } else if (dialog_vars.help_button && (button == n)) { + result = DLG_EXIT_HELP; + } + return result; +} + +/* + * Given that we're using dlg_ok_labels() to list buttons, find the next index + * in the list of buttons. The 'extra' parameter if negative provides a way to + * enumerate extra active areas on the widget. + */ +int +dlg_next_ok_buttonindex(int current, int extra) +{ + int result = current + 1; + + if (current >= 0 + && dlg_ok_buttoncode(result) < 0) + result = extra; + return result; +} + +/* + * Similarly, find the previous button index. + */ +int +dlg_prev_ok_buttonindex(int current, int extra) +{ + int result = current - 1; + + if (result < extra) { + for (result = 0; dlg_ok_buttoncode(result + 1) >= 0; ++result) { + ; + } + } + return result; +} + +/* + * Find the button-index for the "OK" or "Cancel" button, according to + * whether --defaultno is given. If --nocancel was given, we always return + * the index for "OK". + */ +int +dlg_defaultno_button(void) +{ + int result = 0; + + if (dialog_vars.defaultno && !dialog_vars.nocancel) { + while (dlg_ok_buttoncode(result) != DLG_EXIT_CANCEL) + ++result; + } + return result; +} + +/* + * Return a list of buttons for Yes/No labels. + */ +const char ** +dlg_yes_labels(void) +{ + const char **result; + + if (dialog_vars.extra_button) { + result = dlg_ok_labels(); + } else { + static const char *labels[4]; + int n = 0; + + labels[n++] = my_yes_label(); + labels[n++] = my_no_label(); + if (dialog_vars.help_button) + labels[n++] = my_help_label(); + labels[n] = 0; + + result = labels; + } + + return result; +} + +/* + * Map the given button index for dlg_yes_labels() into our exit-code. + */ +int +dlg_yes_buttoncode(int button) +{ + int result = DLG_EXIT_ERROR; + + if (dialog_vars.extra_button) { + result = dlg_ok_buttoncode(button); + } else if (button == 0) { + result = DLG_EXIT_OK; + } else if (button == 1) { + result = DLG_EXIT_CANCEL; + } else if (button == 2 && dialog_vars.help_button) { + result = DLG_EXIT_HELP; + } + + return result; +} + +/* + * Return the next index in labels[]; + */ +int +dlg_next_button(const char **labels, int button) +{ + if (labels[button + 1] != 0) + ++button; + else + button = MIN_BUTTON; + return button; +} + +/* + * Return the previous index in labels[]; + */ +int +dlg_prev_button(const char **labels, int button) +{ + if (button > MIN_BUTTON) + --button; + else { + while (labels[button + 1] != 0) + ++button; + } + return button; +} |