expo: Support rendering multiple lines of text

Use the measurement info to write each line of text separately, thus
respecting word-wrapping and newlines.

Fix up the comment for scene_obj_render() while we are here.

Since a lineedit does not support alignment, add a special case to just
display the text if there is no measurement. This happens assuming the
lineedit is initially empty.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/boot/bootflow_menu.c b/boot/bootflow_menu.c
index 6a37fa8..ab21ed8 100644
--- a/boot/bootflow_menu.c
+++ b/boot/bootflow_menu.c
@@ -241,6 +241,10 @@
 	if (text_mode)
 		expo_set_text_mode(exp, text_mode);
 
+	ret = expo_calc_dims(exp);
+	if (ret)
+		return log_msg_ret("bmd", ret);
+
 	*expp = exp;
 
 	return 0;
diff --git a/boot/scene.c b/boot/scene.c
index aacdccd..72a8e27 100644
--- a/boot/scene.c
+++ b/boot/scene.c
@@ -8,6 +8,7 @@
 
 #define LOG_CATEGORY	LOGC_EXPO
 
+#include <alist.h>
 #include <dm.h>
 #include <expo.h>
 #include <malloc.h>
@@ -163,6 +164,7 @@
 	}
 
 	gen->str_id = str_id;
+	alist_init_struct(&gen->lines, struct vidconsole_mline);
 
 	return 0;
 }
@@ -336,8 +338,8 @@
 		struct scene_txt_generic *gen = &((struct scene_obj_txt *)obj)->gen;
 		struct expo *exp = scn->expo;
 		struct vidconsole_bbox bbox;
+		int len, ret, limit;
 		const char *str;
-		int len, ret;
 
 		str = expo_get_str(exp, gen->str_id);
 		if (!str)
@@ -351,8 +353,12 @@
 			return 16;
 		}
 
+		limit = obj->flags & SCENEOF_SIZE_VALID ?
+			obj->bbox.x1 - obj->bbox.x0 : -1;
+
 		ret = vidconsole_measure(scn->expo->cons, gen->font_name,
-					 gen->font_size, str, -1, &bbox, NULL);
+					 gen->font_size, str, limit, &bbox,
+					 &gen->lines);
 		if (ret)
 			return log_msg_ret("mea", ret);
 		if (widthp)
@@ -418,6 +424,7 @@
 			    struct scene_txt_generic *gen, int x, int y,
 			    int menu_inset)
 {
+	const struct vidconsole_mline *mline;
 	struct video_priv *vid_priv;
 	struct vidconsole_colour old;
 	enum colour_idx fore, back;
@@ -453,8 +460,16 @@
 		video_fill_part(dev, x - menu_inset, y, obj->bbox.x1,
 				obj->bbox.y1, vid_priv->colour_bg);
 	}
+
+	if (!gen->lines.count) {
+		vidconsole_set_cursor_pos(cons, x, y);
+		vidconsole_put_string(cons, str);
+	}
-	vidconsole_set_cursor_pos(cons, x, y);
-	vidconsole_put_string(cons, str);
+	alist_for_each(mline, &gen->lines) {
+		vidconsole_set_cursor_pos(cons, x + mline->bbox.x0,
+					  y + mline->bbox.y0);
+		vidconsole_put_stringn(cons, str + mline->start, mline->len);
+	}
 	if (obj->flags & SCENEOF_POINT)
 		vidconsole_pop_colour(cons, &old);
 
@@ -464,6 +479,9 @@
 /**
  * scene_obj_render() - Render an object
  *
+ * @obj: Object to render
+ * @text_mode: true to use text mode
+ * Return: 0 if OK, -ve on error
  */
 static int scene_obj_render(struct scene_obj *obj, bool text_mode)
 {