summaryrefslogtreecommitdiffstats
path: root/buttons.c
diff options
context:
space:
mode:
Diffstat (limited to 'buttons.c')
-rw-r--r--buttons.c213
1 files changed, 155 insertions, 58 deletions
diff --git a/buttons.c b/buttons.c
index 1799851..d37cfe5 100644
--- a/buttons.c
+++ b/buttons.c
@@ -1,5 +1,5 @@
/*
- * $Id: buttons.c,v 1.90 2012/07/01 20:42:05 tom Exp $
+ * $Id: buttons.c,v 1.94 2012/12/30 20:51:01 tom Exp $
*
* buttons.c -- draw buttons, e.g., OK/Cancel
*
@@ -28,7 +28,7 @@
#include <wchar.h>
#endif
-#define MIN_BUTTON (dialog_state.visit_items ? -1 : 0)
+#define MIN_BUTTON (-dialog_state.visit_cols)
static void
center_label(char *buffer, int longest, const char *label)
@@ -86,11 +86,85 @@ string_to_char(const char **stringp)
return result;
}
+static size_t
+count_labels(const char **labels)
+{
+ size_t result = 0;
+ if (labels != 0) {
+ while (*labels++ != 0) {
+ ++result;
+ }
+ }
+ return result;
+}
+
+/*
+ * Check if the latest key should be added to the hotkey list.
+ */
+static int
+was_hotkey(int this_key, int *used_keys, size_t next)
+{
+ int result = FALSE;
+
+ if (next != 0) {
+ size_t n;
+ for (n = 0; n < next; ++n) {
+ if (used_keys[n] == this_key) {
+ result = TRUE;
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+/*
+ * Determine the hot-keys for a set of button-labels. Normally these are
+ * the first uppercase character in each label. However, if more than one
+ * button has the same first-uppercase, then we will (attempt to) look for
+ * an alternate.
+ *
+ * This allocates data which must be freed by the caller.
+ */
+static int *
+get_hotkeys(const char **labels)
+{
+ int *result = 0;
+ size_t count = count_labels(labels);
+ size_t n;
+
+ if ((result = dlg_calloc(int, count + 1)) != 0) {
+ for (n = 0; n < count; ++n) {
+ const char *label = labels[n];
+ const int *indx = dlg_index_wchars(label);
+ int limit = dlg_count_wchars(label);
+ int i;
+
+ for (i = 0; i < limit; ++i) {
+ int first = indx[i];
+ int check = UCH(label[first]);
+#ifdef USE_WIDE_CURSES
+ int last = indx[i + 1];
+ if ((last - first) != 1) {
+ const char *temp = (label + first);
+ check = string_to_char(&temp);
+ }
+#endif
+ if (dlg_isupper(check) && !was_hotkey(check, result, n)) {
+ result[n] = check;
+ break;
+ }
+ }
+ }
+ }
+ return result;
+}
+
/*
* Print a button
*/
static void
-print_button(WINDOW *win, char *label, int y, int x, int selected)
+print_button(WINDOW *win, char *label, int hotkey, int y, int x, int selected)
{
int i;
int state = 0;
@@ -110,23 +184,20 @@ print_button(WINDOW *win, char *label, int y, int x, int selected)
(void) waddstr(win, "<");
(void) wattrset(win, label_attr);
for (i = 0; i < limit; ++i) {
+ int check;
int first = indx[i];
int last = indx[i + 1];
switch (state) {
case 0:
+ check = UCH(label[first]);
#ifdef USE_WIDE_CURSES
if ((last - first) != 1) {
const char *temp = (label + first);
- int cmp = string_to_char(&temp);
- if (dlg_isupper(cmp)) {
- (void) wattrset(win, key_attr);
- state = 1;
- }
- break;
+ check = string_to_char(&temp);
}
#endif
- if (dlg_isupper(UCH(label[first]))) {
+ if (check == hotkey) {
(void) wattrset(win, key_attr);
state = 1;
}
@@ -203,22 +274,27 @@ dlg_button_x_step(const char **labels, int limit, int *gap, int *margin, int *st
int length;
int unused;
int used;
+ int result;
- if (count == 0)
- return 0;
- dlg_button_sizes(labels, FALSE, &longest, &length);
- used = (length + (count * 2));
- unused = limit - used;
+ *margin = 0;
+ if (count != 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;
+ 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;
+ result = (*gap > 0) && (unused >= 0);
} else {
- *margin = *gap * 2;
+ result = 0;
}
- *step = *gap + (used + count - 1) / count;
- return (*gap > 0) && (unused >= 0);
+ return result;
}
/*
@@ -282,35 +358,41 @@ dlg_draw_buttons(WINDOW *win,
* 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");
+ if (need != 0) {
+ int *hotkeys = get_hotkeys(labels);
+ assert_ptr(hotkeys, "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;
+ 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, hotkeys[n], 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);
+ (void) wattrset(win, save);
+ free(buffer);
+ free(hotkeys);
}
- (void) wmove(win, final_y, final_x);
- wrefresh(win);
- free(buffer);
- (void) wattrset(win, save);
}
/*
@@ -364,19 +446,27 @@ dlg_button_to_char(const char *label)
int
dlg_char_to_button(int ch, const char **labels)
{
+ int result = DLG_EXIT_UNKNOWN;
+
if (labels != 0) {
+ int *hotkeys = get_hotkeys(labels);
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;
+
+ if (hotkeys != 0) {
+ for (j = 0; labels[j] != 0; ++j) {
+ if (ch == hotkeys[j]) {
+ dlg_flush_getc();
+ result = j;
+ break;
+ }
}
+ free(hotkeys);
}
}
- return DLG_EXIT_UNKNOWN;
+
+ return result;
}
static const char *
@@ -669,10 +759,14 @@ dlg_yes_buttoncode(int button)
int
dlg_next_button(const char **labels, int button)
{
- if (labels[button + 1] != 0)
+ if (button < -1)
+ button = -1;
+
+ if (labels[button + 1] != 0) {
++button;
- else
+ } else {
button = MIN_BUTTON;
+ }
return button;
}
@@ -682,9 +776,12 @@ dlg_next_button(const char **labels, int button)
int
dlg_prev_button(const char **labels, int button)
{
- if (button > MIN_BUTTON)
+ if (button > MIN_BUTTON) {
--button;
- else {
+ } else {
+ if (button < -1)
+ button = -1;
+
while (labels[button + 1] != 0)
++button;
}
OpenPOWER on IntegriCloud