[Concept,09/36] expo: Use text-input CLI line state instead of scene's

Message ID 20260120231814.2033069-10-sjg@u-boot.org
State New
Headers
Series video: Add multiple-context support to vidconsole (part F) |

Commit Message

Simon Glass Jan. 20, 2026, 11:17 p.m. UTC
  From: Simon Glass <simon.glass@canonical.com>

Update scene_txtin to use tin->cls instead of scn->cls, so that each
text-input object maintains its own CLI line-editing state.

Add a priv pointer to struct cli_line_state so the putch callback can
access the scene without using container_of. This is necessary because
the cls is now embedded in scene_txtin rather than scene.

Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
---

 boot/scene_txtin.c | 18 +++++++++++-------
 include/cli.h      |  2 ++
 test/boot/expo.c   | 12 ++++++------
 3 files changed, 19 insertions(+), 13 deletions(-)
  

Patch

diff --git a/boot/scene_txtin.c b/boot/scene_txtin.c
index d08b9e4ff0f..296b2fb1a1b 100644
--- a/boot/scene_txtin.c
+++ b/boot/scene_txtin.c
@@ -63,6 +63,7 @@  int scene_txtin_arrange(struct scene *scn, struct expo_arrange_info *arr,
 int scene_txtin_render_deps(struct scene *scn, struct scene_obj *obj,
 			    struct scene_txtin *tin)
 {
+	struct cli_line_state *cls = &tin->cls;
 	const bool open = obj->flags & SCENEOF_OPEN;
 	struct udevice *cons = scn->expo->cons;
 	uint i;
@@ -77,7 +78,7 @@  int scene_txtin_render_deps(struct scene *scn, struct scene_obj *obj,
 		scene_render_obj(scn, tin->edit_id);
 
 		/* move cursor back to the correct position */
-		for (i = scn->cls.num; i < scn->cls.eol_num; i++)
+		for (i = cls->num; i < cls->eol_num; i++)
 			vidconsole_put_char(cons, '\b');
 		ret = vidconsole_entry_save(cons, &scn->entry_save);
 		if (ret)
@@ -100,7 +101,7 @@  int scene_txtin_render_deps(struct scene *scn, struct scene_obj *obj,
  */
 static void scene_txtin_putch(struct cli_line_state *cls, int ch)
 {
-	struct scene *scn = container_of(cls, struct scene, cls);
+	struct scene *scn = cls->priv;
 
 	vidconsole_put_char(scn->expo->cons, ch);
 }
@@ -114,6 +115,7 @@  void scene_txtin_close(struct scene *scn)
 int scene_txtin_open(struct scene *scn, struct scene_obj *obj,
 		     struct scene_txtin *tin)
 {
+	struct cli_line_state *cls = &tin->cls;
 	struct udevice *cons = scn->expo->cons;
 	struct scene_obj_txt *txt;
 	int ret;
@@ -129,10 +131,11 @@  int scene_txtin_open(struct scene *scn, struct scene_obj *obj,
 
 	vidconsole_set_cursor_pos(cons, NULL, txt->obj.bbox.x0, txt->obj.bbox.y0);
 	vidconsole_entry_start(cons, NULL);
-	cli_cread_init(&scn->cls, abuf_data(&tin->buf), tin->line_chars);
-	scn->cls.insert = true;
-	scn->cls.putch = scene_txtin_putch;
-	cli_cread_add_initial(&scn->cls);
+	cli_cread_init(cls, abuf_data(&tin->buf), tin->line_chars);
+	cls->insert = true;
+	cls->putch = scene_txtin_putch;
+	cls->priv = scn;
+	cli_cread_add_initial(cls);
 	ret = vidconsole_entry_save(cons, &scn->entry_save);
 	if (ret)
 		return log_msg_ret("sav", ret);
@@ -162,6 +165,7 @@  void scene_txtin_calc_bbox(struct scene_obj *obj, struct scene_txtin *tin,
 int scene_txtin_send_key(struct scene_obj *obj, struct scene_txtin *tin,
 			 int key, struct expo_action *event)
 {
+	struct cli_line_state *cls = &tin->cls;
 	const bool open = obj->flags & SCENEOF_OPEN;
 	struct scene *scn = obj->scene;
 
@@ -196,7 +200,7 @@  int scene_txtin_send_key(struct scene_obj *obj, struct scene_txtin *tin,
 		ret = vidconsole_entry_restore(cons, &scn->entry_save);
 		if (ret)
 			return log_msg_ret("sav", ret);
-		ret = cread_line_process_ch(&scn->cls, key);
+		ret = cread_line_process_ch(cls, key);
 		ret = vidconsole_entry_save(cons, &scn->entry_save);
 		if (ret)
 			return log_msg_ret("sav", ret);
diff --git a/include/cli.h b/include/cli.h
index ec0f5d31046..a02e228bf8a 100644
--- a/include/cli.h
+++ b/include/cli.h
@@ -37,6 +37,7 @@  struct cli_ch_state {
  * @buf: Buffer containing line
  * @prompt: Prompt for the line
  * @putch: Function to call to output a character (NULL to use putc())
+ * @priv: Private data for putch callback
  */
 struct cli_line_state {
 	uint num;
@@ -48,6 +49,7 @@  struct cli_line_state {
 	char *buf;
 	const char *prompt;
 	void (*putch)(struct cli_line_state *cls, int ch);
+	void *priv;
 };
 
 /**
diff --git a/test/boot/expo.c b/test/boot/expo.c
index d7430dc4284..f94927eb6b7 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -1481,8 +1481,8 @@  static int expo_render_textline(struct unit_test_state *uts)
 	ut_assertok(expo_send_key(exp, CTL_CH('b')));
 
 	/* check cursor moved back one position, before 'a' */
-	ut_asserteq(14, scn->cls.num);
-	ut_asserteq(15, scn->cls.eol_num);
+	ut_asserteq(14, tline->tin.cls.num);
+	ut_asserteq(15, tline->tin.cls.eol_num);
 	ut_asserteq_str("sample hopwinda", abuf_data(&tline->tin.buf));
 	ut_assertok(scene_arrange(scn));
 	ut_assertok(expo_render(exp));
@@ -1493,8 +1493,8 @@  static int expo_render_textline(struct unit_test_state *uts)
 	ut_assertok(expo_send_key(exp, CTL_CH('b')));
 
 	/* check cursor moved back three more positions, before 'i' */
-	ut_asserteq(11, scn->cls.num);
-	ut_asserteq(15, scn->cls.eol_num);
+	ut_asserteq(11, tline->tin.cls.num);
+	ut_asserteq(15, tline->tin.cls.eol_num);
 	ut_asserteq_str("sample hopwinda", abuf_data(&tline->tin.buf));
 	ut_assertok(scene_arrange(scn));
 	ut_assertok(expo_render(exp));
@@ -1504,8 +1504,8 @@  static int expo_render_textline(struct unit_test_state *uts)
 	ut_assertok(expo_send_key(exp, CTL_CH('d')));
 
 	/* check character deleted at cursor position */
-	ut_asserteq(11, scn->cls.num);
-	ut_asserteq(14, scn->cls.eol_num);
+	ut_asserteq(11, tline->tin.cls.num);
+	ut_asserteq(14, tline->tin.cls.eol_num);
 	ut_asserteq_str("sample hopwnda", abuf_data(&tline->tin.buf));
 	ut_assertok(scene_arrange(scn));
 	ut_assertok(expo_render(exp));