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;
 }

Reply via email to