[Concept,33/42] video: Support a cursor in multi-line text

Message ID 20250919201507.4024144-34-sjg@u-boot.org
State New
Headers
Series video: Support a cursor more generally |

Commit Message

Simon Glass Sept. 19, 2025, 8:14 p.m. UTC
  From: Simon Glass <sjg@chromium.org>

For expo, lineedit only supports a single line.

For the CLI, the text can extend across multiple lines. Add support for
this in the normal console, calculating the x and y offset of the cursor
position based on the display width and font size.

The truetype console already works, since it has had this tracking for a
while.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 drivers/video/console_normal.c | 29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)
  

Patch

diff --git a/drivers/video/console_normal.c b/drivers/video/console_normal.c
index 5ef1cb1c68f..8f936191dd8 100644
--- a/drivers/video/console_normal.c
+++ b/drivers/video/console_normal.c
@@ -88,7 +88,7 @@  static __maybe_unused int console_get_cursor_info(struct udevice *dev)
 	struct console_simple_priv *priv = dev_get_priv(dev);
 	struct video_fontdata *fontdata = priv->fontdata;
 	struct vidconsole_cursor *curs = &vc_priv->curs;
-	int x, y, index;
+	int x, y, index, xspace, xpos;
 
 	/* for now, this is not used outside expo */
 	if (!IS_ENABLED(CONFIG_EXPO))
@@ -97,7 +97,30 @@  static __maybe_unused int console_get_cursor_info(struct udevice *dev)
 	x = VID_TO_PIXEL(vc_priv->xmark_frac);
 	y = vc_priv->ymark;
 	index = vc_priv->cli_index;
-	x += index * fontdata->width;
+
+	/* rounded up character position in this line */
+	xpos = (x + vc_priv->x_charsize - 1) / vc_priv->x_charsize;
+
+	/* number of characters which can fit on this (first) line */
+	xspace = vc_priv->cols - xpos;
+
+	if (!curs->indent && index > xspace) {
+		/* move to the next line */
+		y += vc_priv->y_charsize;
+		index -= xspace;
+
+		/* figure out the available space in subsequent lines */
+		if (!curs->indent) {
+			xspace = vc_priv->cols;
+			x = 0;
+		}
+
+		/* calculate the line based on that */
+		y += index / xspace;
+		x += (index % xspace) * fontdata->width;
+	} else {
+		x += index * fontdata->width;
+	}
 
 	/* place the cursor 1 pixel before the start of the next char */
 	if (x > 0)
@@ -107,7 +130,7 @@  static __maybe_unused int console_get_cursor_info(struct udevice *dev)
 	curs->x = x;
 	curs->y = y;
 	curs->height = vc_priv->y_charsize;
-	curs->index = index;
+	curs->index = vc_priv->cli_index;
 
 	return 0;
 }