#include <log/log.h>
#include <util/util.h>
#include <i18n/i18n.h>
+#include <fold/fold.h>
#include "nc-cui.h"
#include "nc-widgets.h"
char *str;
int val;
FIELD *field;
+ int lines;
} *options;
int top, left, size;
int n_options, selected_option;
return key == ' ' || key == '\r' || key == '\n' || key == KEY_ENTER;
}
-static bool key_is_minus(int key)
-{
- return key == 055;
-}
-
-static bool key_is_left(int key)
-{
- return key == KEY_LEFT;
-}
-
-static bool key_is_right(int key)
-{
- return key == KEY_RIGHT;
-}
-
static bool process_key_nop(struct nc_widget *widget __attribute__((unused)),
FORM *form __attribute((unused)),
int key __attribute__((unused)))
case KEY_DC:
form_driver(form, REQ_DEL_CHAR);
break;
+ case '\t':
+ case KEY_BTAB:
+ case KEY_UP:
+ case KEY_DOWN:
+ case KEY_PPAGE:
+ case KEY_NPAGE:
+ /* Don't catch navigational keys */
+ return false;
default:
form_driver(form, key);
break;
struct nc_widget *widget;
size_t rem;
int i, val;
+ uint32_t opts;
/* Shift field focus to nearest active option or next visible field */
if (subset->n_active > 1) {
} else {
for (i = 0; i < set->n_fields; i++)
if (field_visible(set->fields[i])) {
- set->cur_field = set->fields[i];
- break;
+ opts = field_opts(set->fields[i]);
+ if ((opts & O_ACTIVE) == O_ACTIVE) {
+ set->cur_field = set->fields[i];
+ break;
+ }
}
}
int i, val, opt_idx = -1;
FIELD *field;
- if (!key_is_minus(key) && !key_is_left(key) && !key_is_right(key))
+ if (key != '-' && key != '+' && key != KEY_DC && key != KEY_BACKSPACE)
return false;
field = current_field(form);
if (opt_idx < 0)
return false;
- if (key_is_minus(key))
+ if (key == KEY_DC || key == KEY_BACKSPACE)
subset_delete_active(subset, opt_idx);
- if (key_is_left(key)){
+ if (key == '-') {
if (opt_idx == 0)
return true;
subset->active[opt_idx - 1] = val;
}
- if (key_is_right(key)){
+ if (key == '+') {
if (opt_idx >= subset->n_active - 1)
return true;
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;
}
}
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;
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)
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,
field = current_field(set->form);
assert(field);
+ widget = field_userptr(field);
+
+ if (widget->process_key)
+ if (widget->process_key(widget, set->form, key))
+ return true;
+
tab = false;
/* handle field change events */
case KEY_NPAGE:
req = REQ_SLAST_FIELD;
break;
+ case KEY_LEFT:
+ req = REQ_LEFT_FIELD;
+ break;
+ case KEY_RIGHT:
+ req = REQ_RIGHT_FIELD;
+ break;
}
- widget = field_userptr(field);
if (req) {
widget_focus_change(widget, field, false);
form_driver(set->form, req);
return true;
}
- if (!widget->process_key)
- return false;
-
- return widget->process_key(widget, set->form, key);
+ return false;
}
static int widgetset_destructor(void *ptr)
post_form(set->form);
form_driver(set->form, REQ_END_FIELD);
- if (set->cur_field) {
+ if (set->cur_field)
set_current_field(set->form, set->cur_field);
- field = set->cur_field;
- }
field = current_field(set->form);
widget = field_userptr(field);