This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 856fad2ffa8d801db730492bc18060813aca40cc Author: raiden00pl <[email protected]> AuthorDate: Thu Aug 20 09:20:15 2026 +0200 graphics/nxterm: support command-line cursor editing Handle carriage return, cursor-left/right, and erase-to-end-of-line sequences required by readline. Restore glyphs hidden by the cursor so edited text redraws correctly. Signed-off-by: raiden00pl <[email protected]> Assisted-by: OpenAI Codex:gpt-5 --- graphics/nxterm/nxterm_putc.c | 20 ++++++++- graphics/nxterm/nxterm_vt100.c | 98 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 116 insertions(+), 2 deletions(-) diff --git a/graphics/nxterm/nxterm_putc.c b/graphics/nxterm/nxterm_putc.c index de7a3553160..226175288bd 100644 --- a/graphics/nxterm/nxterm_putc.c +++ b/graphics/nxterm/nxterm_putc.c @@ -51,10 +51,11 @@ void nxterm_putc(FAR struct nxterm_state_s *priv, uint8_t ch) FAR const struct nxterm_bitmap_s *bm; int lineheight; - /* Ignore carriage returns */ + /* Handle carriage returns */ if (ch == '\r') { + priv->fpos.x = priv->spwidth; return; } @@ -170,5 +171,22 @@ void nxterm_showcursor(FAR struct nxterm_state_s *priv) void nxterm_hidecursor(FAR struct nxterm_state_s *priv) { + int i; + nxterm_hidechar(priv, &priv->cursor); + + /* A cursor moved into an existing line is drawn on top of a saved glyph. + * Restore that glyph after erasing the cursor so command-line editing does + * not leave a hole in the displayed text. + */ + + for (i = priv->nchars - 1; i >= 0; i--) + { + if (priv->bm[i].pos.x == priv->cursor.pos.x && + priv->bm[i].pos.y == priv->cursor.pos.y) + { + nxterm_fillchar(priv, NULL, &priv->bm[i]); + break; + } + } } diff --git a/graphics/nxterm/nxterm_vt100.c b/graphics/nxterm/nxterm_vt100.c index a5530b9d69e..7e67a39c4f4 100644 --- a/graphics/nxterm/nxterm_vt100.c +++ b/graphics/nxterm/nxterm_vt100.c @@ -51,6 +51,8 @@ struct vt100_sequence_s ****************************************************************************/ static int nxterm_erasetoeol(FAR struct nxterm_state_s *priv); +static int nxterm_cursorleft(FAR struct nxterm_state_s *priv); +static int nxterm_cursorright(FAR struct nxterm_state_s *priv); /**************************************************************************** * Private Data @@ -63,12 +65,23 @@ static int nxterm_erasetoeol(FAR struct nxterm_state_s *priv); /* <esc>[K is the VT100 command erases to the end of the line. */ static const char g_erasetoeol[] = VT100_CLEAREOL; +static const char g_cursorleft[] = +{ + ASCII_ESC, '[', 'D' +}; + +static const char g_cursorright[] = +{ + ASCII_ESC, '[', 'C' +}; /* The list of all VT100 sequences supported by the emulation */ static const struct vt100_sequence_s g_vt100sequences[] = { {g_erasetoeol, nxterm_erasetoeol, sizeof(g_erasetoeol)}, + {g_cursorleft, nxterm_cursorleft, sizeof(g_cursorleft)}, + {g_cursorright, nxterm_cursorright, sizeof(g_cursorright)}, {NULL, NULL, 0} }; @@ -92,7 +105,90 @@ static const struct vt100_sequence_s g_vt100sequences[] = static int nxterm_erasetoeol(FAR struct nxterm_state_s *priv) { - /* Does nothing yet (other than consume the sequence) */ + struct nxgl_rect_s bounds; + uint16_t dst; + uint16_t src; + + bounds.pt1.x = priv->fpos.x; + bounds.pt1.y = priv->fpos.y; + bounds.pt2.x = priv->wndo.wsize.w - 1; + bounds.pt2.y = priv->fpos.y + priv->fheight - 1; + + priv->ops->fill(priv, &bounds, priv->wndo.wcolor); + + /* Discard every saved glyph covered by the erased portion of this line. + * Keeping the bitmap list in sync is necessary for later redraw events. + */ + + for (src = 0, dst = 0; src < priv->nchars; src++) + { + if (priv->bm[src].pos.y == priv->fpos.y && + priv->bm[src].pos.x >= priv->fpos.x) + { + continue; + } + + if (dst != src) + { + priv->bm[dst] = priv->bm[src]; + } + + dst++; + } + + priv->nchars = dst; + + return OK; +} + +/**************************************************************************** + * Name: nxterm_cursorleft + ****************************************************************************/ + +static int nxterm_cursorleft(FAR struct nxterm_state_s *priv) +{ + nxgl_coord_t x = priv->spwidth; + uint16_t i; + + /* Find the closest saved glyph to the left on the current line. */ + + for (i = 0; i < priv->nchars; i++) + { + if (priv->bm[i].pos.y == priv->fpos.y && + priv->bm[i].pos.x < priv->fpos.x && + priv->bm[i].pos.x > x) + { + x = priv->bm[i].pos.x; + } + } + + priv->fpos.x = x; + return OK; +} + +/**************************************************************************** + * Name: nxterm_cursorright + ****************************************************************************/ + +static int nxterm_cursorright(FAR struct nxterm_state_s *priv) +{ + FAR const struct nxfonts_glyph_s *glyph; + int i; + + /* Prefer the most recently rendered glyph when editing has overdrawn a + * character at the same location. + */ + + for (i = priv->nchars - 1; i >= 0; i--) + { + if (priv->bm[i].pos.y == priv->fpos.y && + priv->bm[i].pos.x == priv->fpos.x) + { + glyph = nxf_cache_getglyph(priv->fcache, priv->bm[i].code); + priv->fpos.x += glyph == NULL ? priv->spwidth : glyph->width; + break; + } + } return OK; }
