X-Git-Url: http://git.ozlabs.org/?p=petitboot;a=blobdiff_plain;f=ui%2Fncurses%2Fnc-widgets.c;h=7e03e573d943a81d84ce45c3ba56a2729c8029ed;hp=5c67d827b506e5372158586beeb761b9d2b1bce0;hb=b6f99a457cb906277b172a0332a1e16ddba99228;hpb=60252961c21a0f102e69373f2bea36f8af495c29 diff --git a/ui/ncurses/nc-widgets.c b/ui/ncurses/nc-widgets.c index 5c67d82..7e03e57 100644 --- a/ui/ncurses/nc-widgets.c +++ b/ui/ncurses/nc-widgets.c @@ -51,6 +51,8 @@ #include #include #include +#include +#include #include "nc-cui.h" #include "nc-widgets.h" @@ -137,6 +139,7 @@ struct nc_widget_select { char *str; int val; FIELD *field; + int lines; } *options; int top, left, size; int n_options, selected_option; @@ -838,21 +841,25 @@ static void select_set_visible(struct nc_widget *widget, bool visible) static void select_move(struct nc_widget *widget, int y, int x) { struct nc_widget_select *select = to_select(widget); - int i; + int i, cur = 0; - for (i = 0; i < select->n_options; i++) - field_move(select->options[i].field, y + i, x); + for (i = 0; i < select->n_options; i++) { + field_move(select->options[i].field, y + cur, x); + cur += select->options[i].lines; + } } static void select_field_focus(struct nc_widget *widget, FIELD *field) { struct nc_widget_select *select = to_select(widget); - int i; + int i, cur = 0; for (i = 0; i < select->n_options; i++) { - if (field != select->options[i].field) + if (field != select->options[i].field) { + cur += select->options[i].lines; continue; - widget->focus_y = i; + } + widget->focus_y = cur; return; } } @@ -894,10 +901,47 @@ struct nc_widget_select *widget_new_select(struct nc_widgetset *set, return select; } +static int widget_select_fold_cb(void *arg, const char *buf, int len) +{ + struct nc_widget_select *select = arg; + char *line, *newstr, *padbuf = NULL; + int i, pad; + + if (!len) + return 0; + + line = talloc_strndup(select->options, buf, len); + + i = select->n_options - 1; + pad = max(0, select->widget.width - strncols(line)); + + if (pad) { + padbuf = talloc_array(select->options, char, pad + 1); + memset(padbuf, ' ', pad); + padbuf[pad] = '\0'; + } + + if (select->options[i].str) + newstr = talloc_asprintf_append(select->options[i].str, + "%s%s", line, + pad ? padbuf : ""); + else + newstr = talloc_asprintf(select->options, "%s%s", line, + pad ? padbuf : ""); + + select->options[i].str = newstr; + select->options[i].lines++; + + talloc_free(padbuf); + talloc_free(line); + return 0; +} + void widget_select_add_option(struct nc_widget_select *select, int value, const char *text, bool selected) { const char *str; + char *full_text; FIELD *f; int i; @@ -916,23 +960,29 @@ void widget_select_add_option(struct nc_widget_select *select, int value, str = select_unselected_str; i = select->n_options++; - select->widget.height = select->n_options; - select->options = talloc_realloc(select, select->options, struct select_option, i + 2); select->options[i].val = value; - select->options[i].str = talloc_asprintf(select->options, - "%s %s", str, text); + select->options[i].lines = 0; + select->options[i].str = NULL; - select->options[i].field = f = new_field(1, select->size, - select->top + i, - select->left, 0, 0); + full_text = talloc_asprintf(select->options, "%s %s", str, text); + fold_text(full_text, select->widget.width, + widget_select_fold_cb, select); - field_opts_off(f, O_WRAP | O_EDIT); + select->options[i].field = f = new_field(select->options[i].lines, + select->size, + select->top + select->widget.height, + select->left, 0, 0); + + select->widget.height += select->options[i].lines; + + field_opts_off(f, O_EDIT); set_field_userptr(f, &select->widget); set_field_buffer(f, 0, select->options[i].str); widgetset_add_field(select->set, f); + talloc_free(full_text); } int widget_select_get_value(struct nc_widget_select *select) @@ -944,7 +994,7 @@ int widget_select_get_value(struct nc_widget_select *select) int widget_select_height(struct nc_widget_select *select) { - return select->n_options; + return select->widget.height; } void widget_select_on_change(struct nc_widget_select *select, @@ -1002,16 +1052,18 @@ struct nc_widget_button *widget_new_button(struct nc_widgetset *set, void (*click)(void *), void *arg) { struct nc_widget_button *button; + int idx, len, pad1, pad2, bufsz; char *text; FIELD *f; - int idx, len; + + int field_size = size + 2; button = talloc_zero(set, struct nc_widget_button); button->widget.height = 1; - button->widget.width = size; + button->widget.width = field_size; button->widget.x = x; button->widget.y = y; - button->widget.field = f = new_field(1, size + 2, y, x, 0, 0); + button->widget.field = f = new_field(1, field_size, y, x, 0, 0); button->widget.process_key = button_process_key; button->widget.focussed_attr = A_REVERSE; button->widget.unfocussed_attr = A_NORMAL; @@ -1021,17 +1073,28 @@ struct nc_widget_button *widget_new_button(struct nc_widgetset *set, field_opts_off(f, O_EDIT); set_field_userptr(f, &button->widget); - /* center str in a size-char buffer, but don't overrun */ - len = strlen(str); - len = min(len, size); - idx = (size - len) / 2; + /* Center str in the field. This depends on the number of columns used + * by the string, not the number of chars in str */ + len = strncols(str); + if (len <= size) { + idx = (field_size - len) / 2; + } else { + idx = 1; + pb_log("Warning: '%s' %d columns wide " + "but button is %d columns wide\n", + str, len, size); + } + + pad1 = max(idx - 1, 0); + pad2 = max(size - len - pad1, 0); + bufsz = 1 + pad1 + strlen(str) + pad2 + 2; - text = talloc_array(button, char, size + 3); - memset(text, ' ', size + 2); - memcpy(text + idx + 1, str, len); + text = talloc_array(button, char, bufsz); + memset(text, ' ', bufsz); + memcpy(text + idx, str, strlen(str)); text[0] = '['; - text[size + 1] = ']'; - text[size + 2] = '\0'; + text[bufsz - 2] = ']'; + text[bufsz - 1] = '\0'; set_field_buffer(f, 0, text); @@ -1066,19 +1129,19 @@ bool widgetset_process_key(struct nc_widgetset *set, int key) tab = true; /* fall through */ case KEY_UP: - req = REQ_PREV_FIELD; + req = REQ_SPREV_FIELD; break; case '\t': tab = true; /* fall through */ case KEY_DOWN: - req = REQ_NEXT_FIELD; + req = REQ_SNEXT_FIELD; break; case KEY_PPAGE: - req = REQ_FIRST_FIELD; + req = REQ_SFIRST_FIELD; break; case KEY_NPAGE: - req = REQ_LAST_FIELD; + req = REQ_SLAST_FIELD; break; }