Add a new flag SCENEOF_MULTILINE that allows the textedit widget to accept multiline input. When this flag is set, pressing Enter inserts a newline character instead of closing the textedit. Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: Simon Glass <simon.glass@canonical.com> --- boot/editenv.c | 2 ++ boot/scene_txtin.c | 21 ++++++++++++++++++++- include/expo.h | 2 ++ test/boot/editenv.c | 22 +++++++++++----------- test/boot/expo.c | 16 ++++++++++++++-- 5 files changed, 49 insertions(+), 14 deletions(-) diff --git a/boot/editenv.c b/boot/editenv.c index de7df6fe3fa..fd7670263b7 100644 --- a/boot/editenv.c +++ b/boot/editenv.c @@ -47,6 +47,7 @@ static int editenv_setup(struct expo *exp, struct udevice *dev, ret = scene_texted(scn, "textedit", EDITENV_OBJ_TEXTEDIT, 70, &ted); if (ret < 0) return log_msg_ret("ted", ret); + ted->obj.flags |= SCENEOF_MULTILINE; ret = scene_obj_set_bbox(scn, EDITENV_OBJ_TEXTEDIT, 50, 200, 1300, 400); if (ret < 0) @@ -122,6 +123,7 @@ int expo_editenv_init(const char *varname, const char *value, if (ret) { expo_destroy(exp); return log_msg_ret("set", ret); + } return 0; diff --git a/boot/scene_txtin.c b/boot/scene_txtin.c index 8b49daddd56..ab4fd5056a0 100644 --- a/boot/scene_txtin.c +++ b/boot/scene_txtin.c @@ -342,13 +342,32 @@ int scene_txtin_send_key(struct scene_obj *obj, struct scene_txtin *tin, log_debug("menu quit\n"); } break; - case BKEY_SELECT: + case BKEY_SAVE: if (!open) break; + /* Accept contents even in multiline mode */ event->type = EXPOACT_CLOSE; event->select.id = obj->id; scene_txtin_close(scn, tin); break; + case BKEY_SELECT: + if (!open) + break; + if (obj->flags & SCENEOF_MULTILINE) { + char *buf = cls->buf; + int wlen = cls->eol_num - cls->num; + + /* Insert newline at cursor position */ + memmove(&buf[cls->num + 1], &buf[cls->num], wlen); + buf[cls->num] = '\n'; + cls->num++; + cls->eol_num++; + } else { + event->type = EXPOACT_CLOSE; + event->select.id = obj->id; + scene_txtin_close(scn, tin); + } + break; case BKEY_UP: cread_line_process_ch(cls, CTL_CH('p')); break; diff --git a/include/expo.h b/include/expo.h index 5a35d72c58f..3846b58abdd 100644 --- a/include/expo.h +++ b/include/expo.h @@ -321,6 +321,7 @@ enum scene_obj_align { * @SCENEOF_MANUAL: manually arrange the items associated with this object * @SCENEOF_DIRTY: object has been modified and needs to be redrawn * @SCENEOF_PASSWORD: textline input should show stars instead of characters + * @SCENEOF_MULTILINE: textedit allows multiline input (Enter adds newline) * @SCENEOF_LAST: used just as a check for the size of the flags mask */ enum scene_obj_flags_t { @@ -335,6 +336,7 @@ enum scene_obj_flags_t { SCENEOF_MANUAL = BIT(8), SCENEOF_DIRTY = BIT(9), SCENEOF_PASSWORD = BIT(10), + SCENEOF_MULTILINE = BIT(11), SCENEOF_LAST, /* check for size of flags below */ }; diff --git a/test/boot/editenv.c b/test/boot/editenv.c index 20273c53647..69e543ea51f 100644 --- a/test/boot/editenv.c +++ b/test/boot/editenv.c @@ -74,10 +74,10 @@ static int editenv_test_base(struct unit_test_state *uts) int ret; /* - * Type "test" then press Enter to accept - * \x0d is Ctrl-M (Enter/carriage return) + * Type "test" then press Ctrl-S to save + * \x13 is Ctrl-S */ - console_in_puts("test\x0d"); + console_in_puts("test\x13"); ret = expo_editenv("myvar", NULL, buf, sizeof(buf)); ut_assertok(ret); ut_asserteq_str("test", buf); @@ -94,9 +94,9 @@ static int editenv_test_initial(struct unit_test_state *uts) /* * Start with "world", go to start with Ctrl-A, type "hello ", then - * press Enter + * press Ctrl-S to save */ - console_in_puts("\x01hello \x0d"); + console_in_puts("\x01hello \x13"); ret = expo_editenv("myvar", "world", buf, sizeof(buf)); ut_assertok(ret); ut_asserteq_str("hello world", buf); @@ -138,11 +138,11 @@ static int editenv_test_video(struct unit_test_state *uts) ut_assertok(vidconsole_select_font(con, NULL, NULL, 30)); /* - * Navigate with up arrow, insert text, then press Enter. The up arrow - * should be converted to Ctrl-P by scene_txtin_send_key(). - * \x1b[A is the escape sequence for up arrow + * Navigate with up arrow, insert text, then press Ctrl-S to save. + * The up arrow should be converted to Ctrl-P by scene_txtin_send_key(). + * \x1b[A is the escape sequence for up arrow, \x13 is Ctrl-S (save) */ - console_in_puts("\x1b[A!\x0d"); + console_in_puts("\x1b[A!\x13"); ret = expo_editenv("testvar", initial, buf, sizeof(buf)); ut_assertok(ret); @@ -179,11 +179,11 @@ static int editenv_test_funcs(struct unit_test_state *uts) ut_assertok(editenv_send(&info, BKEY_DOWN)); ut_asserteq(16611, ut_check_video(uts, "down")); - /* Type a character and press Enter to accept */ + /* Type a character and press Ctrl-S to save */ ut_assertok(editenv_send(&info, '*')); ut_asserteq(16689, ut_check_video(uts, "insert")); - ut_asserteq(1, editenv_send(&info, BKEY_SELECT)); + ut_asserteq(1, editenv_send(&info, BKEY_SAVE)); /* The '*' should be appended to the initial text */ ut_assert(strstr(expo_editenv_result(&info), "editor.*")); diff --git a/test/boot/expo.c b/test/boot/expo.c index 824fd0cca38..f598b9cb86c 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -1703,7 +1703,19 @@ static int expo_render_textedit(struct unit_test_state *uts) ut_assertok(expo_render(exp)); ut_asserteq(21083, video_compress_fb(uts, dev, false)); - /* close the textedit with Enter (BKEY_SELECT) */ + /* set multiline mode and check Enter inserts newline */ + ted->obj.flags |= SCENEOF_MULTILINE; + ut_assertok(expo_send_key(exp, BKEY_SELECT)); + ut_asserteq(90, ted->tin.cls.num); + ut_asserteq(90, ted->tin.cls.eol_num); + ut_assert(ted->obj.flags & SCENEOF_OPEN); + ut_asserteq('\n', ((char *)abuf_data(&ted->tin.buf))[89]); + ut_assertok(scene_arrange(scn)); + ut_assertok(expo_render(exp)); + ut_asserteq(21091, video_compress_fb(uts, dev, false)); + + /* clear multiline mode, close the textedit with Enter (BKEY_SELECT) */ + ted->obj.flags &= ~SCENEOF_MULTILINE; ut_assertok(expo_send_key(exp, BKEY_SELECT)); ut_assertok(expo_action_get(exp, &act)); ut_asserteq(EXPOACT_CLOSE, act.type); @@ -1713,7 +1725,7 @@ static int expo_render_textedit(struct unit_test_state *uts) /* check the textedit is closed and text is changed */ ut_asserteq(0, ted->obj.flags & SCENEOF_OPEN); ut_asserteq_str("his\nis the initial contents of the text " - "editor but it is ely that more will be added latr", + "editor but it is ely that more will be added latr\n", abuf_data(&ted->tin.buf)); ut_assertok(scene_arrange(scn)); ut_assertok(expo_render(exp)); -- 2.43.0