From patchwork Fri Jan 30 03:58:39 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1791 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org Authentication-Results: mail.u-boot.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=VSrUxW/E; dkim-atps=neutral Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 3DAB2697DF for ; Thu, 29 Jan 2026 20:59:48 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id mhIpUgsUTFxf for ; Thu, 29 Jan 2026 20:59:48 -0700 (MST) Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 8D736697EA for ; Thu, 29 Jan 2026 20:59:47 -0700 (MST) Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 8BB8B697E8 for ; Thu, 29 Jan 2026 20:59:45 -0700 (MST) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id quqfTsDSCvri for ; Thu, 29 Jan 2026 20:59:45 -0700 (MST) Received-SPF: Pass (mailfrom) identity=mailfrom; client-ip=209.85.161.41; helo=mail-oo1-f41.google.com; envelope-from=sjg@chromium.org; receiver=u-boot.org Received: from mail-oo1-f41.google.com (mail-oo1-f41.google.com [209.85.161.41]) by mail.u-boot.org (Postfix) with ESMTPS id EC10C697DD for ; Thu, 29 Jan 2026 20:59:41 -0700 (MST) Received: by mail-oo1-f41.google.com with SMTP id 006d021491bc7-662f2fa7e67so634882eaf.1 for ; Thu, 29 Jan 2026 19:59:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1769745581; x=1770350381; darn=u-boot.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=LhxIORmTTG2ge2cWorK8EFPo3UMupl96NwELofm+erE=; b=VSrUxW/E7fTimvwbu2KSisiM6TyuuZ5HDNOJChpDp4tdl/Wqm3gmA41pHIaLgAzlGJ XjMT199eVvWRrs2clMu9VGcPtNS2jouHLZkxYvTXTGuABbd315Kx/xvUSYU3Rg0Z589g aM39gkNGOHFKj2KdXsWiBk3eSmrGHfIBSxHJ0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1769745581; x=1770350381; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=LhxIORmTTG2ge2cWorK8EFPo3UMupl96NwELofm+erE=; b=rw+ZcsfzR36V8nj46GKkGYMz1m2Ib0kCvO30jbL+yWRqYuxLDm7CmxwnCfQhIzWpdI ktGCL1hTDqkBa+dM+Jt91LBLcPkQZjaH2D6Mt7B0sVFgu3TkcB+X5KwuV0+yEqpJDTOq fU/H/kqtmbxk7PgjMcGLhW5f7/WPGXRUk9bEhdL3aw5QFD44gH3gz7eQjswxYbJUD+wP veeODr1sEpzWYvPvxvSnZk1EiUg//YpenUlOc9zdIRugSGku38QINbE/LUhg0Ls0y03f TECUS4CoAoH4O4pHz7C4w6hEsxh6nYgAx0XpcEHb94445CW4gTBmnCsNT1q/XFNmlFkX 1hHw== X-Gm-Message-State: AOJu0YzQVtzeV7YCJRkUOPe0FK7zBm1uggvEPfTVK1/ffi7aTECFkvn2 Qg/0+Hz7zah9dkV1a/Clusuz04SIcn4VkUnGZM/A6WvsGt3s9Uf+v87w+W6CBR7sViC85B594bt ovY9mYg== X-Gm-Gg: AZuq6aIGFcbg7zsyhcnwk7mKHEk6DeQs4VTKFeYkevGkAbxzUxaNDE23k8mLCA1DvG/ yrrwnhqe0M9CWiwsbHPx/6vzaw12wr2V4ra32YCzns1BKd7gRV+1YA3FGrsQRVhLqwSu/iLUN/b CCd/LJkQud+xix0WArIfkwTgLaDWVqceul0G9xjGQ+gr8W15BcqtUgu3ErsDxle6WpES3wt75+E IG/goO655TBtLVPyNWt3XNL2lJEbCypupA5O6zjmf/k2rQijMZn/EbzGP2XE+2B6fqZotsf3YKe ldB6sw6oTWbS0YW7EFa3H2TZZSpyn398HRgVnJCwQxybgE2khLhkAG13xm7G2scGibGNC9sGlKE AuDh3WiEjTiohJhsNzZK1MWYjXHvgEVChLagGeZQEya/3xEjSI48x6SGcc1rVw9jhw/mRIWa3xZ oc4JaxMAOT6CYuWq4O X-Received: by 2002:a05:6820:179a:b0:654:18f9:10f4 with SMTP id 006d021491bc7-6630ef30dd8mr824900eaf.0.1769745580636; Thu, 29 Jan 2026 19:59:40 -0800 (PST) Received: from chromium.org ([73.34.74.121]) by smtp.gmail.com with ESMTPSA id 006d021491bc7-662f9a4e491sm4128687eaf.16.2026.01.29.19.59.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 29 Jan 2026 19:59:40 -0800 (PST) From: Simon Glass X-Google-Original-From: Simon Glass To: U-Boot Concept Date: Thu, 29 Jan 2026 20:58:39 -0700 Message-ID: <20260130035849.3580212-17-simon.glass@canonical.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260130035849.3580212-1-simon.glass@canonical.com> References: <20260130035849.3580212-1-simon.glass@canonical.com> MIME-Version: 1.0 Message-ID-Hash: W6URR4HH2SOYLAVYRKKXMKU6J2MYEMFN X-Message-ID-Hash: W6URR4HH2SOYLAVYRKKXMKU6J2MYEMFN X-MailFrom: sjg@chromium.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Simon Glass , "Claude Opus 4 . 5" X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 16/19] expo: Add SCENEOF_MULTILINE flag for textedit List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: 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 Signed-off-by: Simon Glass --- 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));