From: Petr Hodina <[email protected]> The pixel-drawn menu is rendered to serial or USB CDC-ACM. Add pm_term_puts()/pm_term_render() to render the same menu as ANSI escapes over those byte-stream consoles.
Wire it into pm_render_all() for initial draw and the up/down navigation in pm_run(). Signed-off-by: Petr Hodina <[email protected]> --- cmd/phonemenu.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/cmd/phonemenu.c b/cmd/phonemenu.c index 30f994bcb64..e83394714c3 100644 --- a/cmd/phonemenu.c +++ b/cmd/phonemenu.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ +#include <ansi.h> #include <cli.h> #include <command.h> #include <dm.h> @@ -9,6 +10,8 @@ #include <log.h> #include <malloc.h> #include <menu.h> +#include <stdio.h> +#include <stdio_dev.h> #include <video.h> #include <video_console.h> #include <version.h> @@ -234,6 +237,76 @@ static void pm_draw_frame(struct pm_state *s) COL_FOOTER, COL_BG, foot); } +/* ANSI escape sequences and line ending used on the byte-stream consoles */ +#define PM_TERM_EOL "\r\n" +#define PM_TERM_CLEAR ANSI_CLEAR_CONSOLE "\e[H" +#define PM_TERM_CURSOR_HIDE ANSI_CURSOR_HIDE +#define PM_TERM_CURSOR_SHOW ANSI_CURSOR_SHOW +#define PM_TERM_REVERSE ANSI_COLOR_REVERSE +#define PM_TERM_RESET ANSI_COLOR_RESET + +/* Mirror the menu to byte-stream consoles (serial UART, USB CDC ACM) */ +static void pm_term_puts(const char *str) +{ + static const char * const names[] = { "serial", "usbacm" }; + struct stdio_dev *d; + size_t i; + + for (i = 0; i < ARRAY_SIZE(names); i++) { + d = stdio_get_by_name(names[i]); + if (!d || !d->puts) + continue; + + if (!strcmp(names[i], "usbacm") && !d->priv) + continue; + + d->puts(d, str); + } +} + +static void pm_term_render(struct pm_state *s) +{ + enum pm_section prev = PM_SEC_COUNT; + char buf[160]; + int i; + + /* Clear screen, cursor home, hide cursor while we paint. */ + pm_term_puts(PM_TERM_CLEAR PM_TERM_CURSOR_HIDE); + + snprintf(buf, sizeof(buf), " %s" PM_TERM_EOL, s->title); + pm_term_puts(buf); + if (s->subtitle && *s->subtitle) { + snprintf(buf, sizeof(buf), " %s" PM_TERM_EOL, s->subtitle); + pm_term_puts(buf); + } + if (s->version && *s->version) { + snprintf(buf, sizeof(buf), " %s" PM_TERM_EOL, s->version); + pm_term_puts(buf); + } + pm_term_puts(PM_TERM_EOL); + + for (i = 0; i < s->count; i++) { + if (s->items[i].section != prev) { + snprintf(buf, sizeof(buf), " [%s]" PM_TERM_EOL, + pm_section_label[s->items[i].section]); + pm_term_puts(buf); + prev = s->items[i].section; + } + if (i == s->active) + snprintf(buf, sizeof(buf), + " " PM_TERM_REVERSE "> %s" PM_TERM_RESET PM_TERM_EOL, + s->items[i].label); + else + snprintf(buf, sizeof(buf), " %s" PM_TERM_EOL, + s->items[i].label); + pm_term_puts(buf); + } + + pm_term_puts(PM_TERM_EOL + " Vol up/down or arrows to move Power or Enter to select" + PM_TERM_EOL); +} + static void pm_render_all(struct pm_state *s) { int i; @@ -242,6 +315,8 @@ static void pm_render_all(struct pm_state *s) for (i = 0; i < s->count; i++) pm_draw_item(s, i, i == s->active); video_sync(s->vid, true); + + pm_term_render(s); } static int pm_run(const struct pm_item *items, int count, @@ -290,6 +365,7 @@ static int pm_run(const struct pm_item *items, int count, pm_draw_item(&s, s.last_active, false); pm_draw_item(&s, s.active, true); video_sync(s.vid, true); + pm_term_render(&s); break; case BKEY_DOWN: /* Wrap from the last item back to item 0. */ @@ -298,6 +374,7 @@ static int pm_run(const struct pm_item *items, int count, pm_draw_item(&s, s.last_active, false); pm_draw_item(&s, s.active, true); video_sync(s.vid, true); + pm_term_render(&s); break; case BKEY_SELECT: running = false; @@ -318,6 +395,9 @@ static int pm_run(const struct pm_item *items, int count, s.vp->colour_bg = COL_BG; video_sync(s.vid, true); + /* Reset the terminal: clear screen, show cursor, reset colours. */ + pm_term_puts(PM_TERM_CLEAR PM_TERM_CURSOR_SHOW PM_TERM_RESET); + cmd = items[s.active].command; if (cmd && cmd[0]) run_command((char *)cmd, 0); -- 2.55.0
