[PATCH 1/2] ui/ncurses: Allow text wrapping in select widgets

Samuel Mendoza-Jonas sam.mj at au1.ibm.com
Wed Sep 9 15:17:32 AEST 2015


Several string translations used in select widgets are longer than the
maximum possible width of the widget. Rather than associating several
FIELDs with a select option, use a fold_text callback to pad out
substrings of the original string such that the ncurses O_WRAP option
properly wraps strings within the field.

Signed-off-by: Samuel Mendoza-Jonas <sam.mj at au1.ibm.com>
---
 ui/ncurses/nc-config.c  |  6 ++--
 ui/ncurses/nc-widgets.c | 79 +++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 68 insertions(+), 17 deletions(-)

diff --git a/ui/ncurses/nc-config.c b/ui/ncurses/nc-config.c
index 7c02250..2750bbb 100644
--- a/ui/ncurses/nc-config.c
+++ b/ui/ncurses/nc-config.c
@@ -811,7 +811,8 @@ static void config_screen_setup_widgets(struct config_screen *screen,
 	}
 
 	screen->widgets.network_l = widget_new_label(set, 0, 0, _("Network:"));
-	screen->widgets.network_f = widget_new_select(set, 0, 0, 50);
+	screen->widgets.network_f = widget_new_select(set, 0, 0,
+						COLS - screen->field_x - 1);
 
 	widget_select_add_option(screen->widgets.network_f,
 					NET_CONF_TYPE_DHCP_ALL,
@@ -908,11 +909,12 @@ static void config_screen_setup_widgets(struct config_screen *screen,
 	screen->widgets.allow_write_l = widget_new_label(set, 0, 0,
 			_("Disk R/W:"));
 	screen->widgets.allow_write_f = widget_new_select(set, 0, 0,
-						COLS - screen->field_x);
+						COLS - screen->field_x - 1);
 
 	widget_select_add_option(screen->widgets.allow_write_f, 0,
 				_("Prevent all writes to disk"),
 				!config->allow_writes);
+
 	widget_select_add_option(screen->widgets.allow_write_f, 1,
 				_("Allow bootloader scripts to modify disks"),
 				config->allow_writes);
diff --git a/ui/ncurses/nc-widgets.c b/ui/ncurses/nc-widgets.c
index e092f8b..7e03e57 100644
--- a/ui/ncurses/nc-widgets.c
+++ b/ui/ncurses/nc-widgets.c
@@ -52,6 +52,7 @@
 #include <log/log.h>
 #include <util/util.h>
 #include <i18n/i18n.h>
+#include <fold/fold.h>
 
 #include "nc-cui.h"
 #include "nc-widgets.h"
@@ -138,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;
@@ -839,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;
 	}
 }
@@ -895,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;
 
@@ -917,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)
@@ -945,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,
-- 
2.5.1



More information about the Petitboot mailing list