system/cle: Remove cle_getcursor()
Fix https://github.com/apache/nuttx/issues/8731, don't rely on the vt100 to report the cursor position. This avoid the implicit input (response of get cursor command) during the user inputs. Notice: This assume that the nsh prompt is always shown at line start. Signed-off-by: Huang Qi <huangqi3@xiaomi.com>
This commit is contained in:
parent
04a156e0d0
commit
0af64dc045
176
system/cle/cle.c
176
system/cle/cle.c
@ -108,9 +108,8 @@ enum cle_key_e
|
||||
|
||||
struct cle_s
|
||||
{
|
||||
uint16_t curpos; /* Current cursor position */
|
||||
uint16_t cursave; /* Saved cursor position */
|
||||
uint16_t row; /* This is the row that we are editing in */
|
||||
int16_t curpos; /* Current cursor position in buffer */
|
||||
int16_t realpos; /* Current cursor position in terminal */
|
||||
uint16_t coloffs; /* Left cursor offset */
|
||||
uint16_t linelen; /* Size of the line buffer */
|
||||
uint16_t nchars; /* Size of data in the line buffer */
|
||||
@ -136,9 +135,7 @@ static void cle_putch(FAR struct cle_s *priv, char ch);
|
||||
static int cle_getch(FAR struct cle_s *priv);
|
||||
static void cle_cursoron(FAR struct cle_s *priv);
|
||||
static void cle_cursoroff(FAR struct cle_s *priv);
|
||||
static void cle_setcursor(FAR struct cle_s *priv, uint16_t column);
|
||||
static int cle_getcursor(FAR struct cle_s *priv, uint16_t *prow,
|
||||
uint16_t *pcolumn);
|
||||
static void cle_setcursor(FAR struct cle_s *priv, int16_t column);
|
||||
static void cle_clrtoeol(FAR struct cle_s *priv);
|
||||
|
||||
/* Editor function */
|
||||
@ -183,10 +180,9 @@ static int g_cmd_history_len = 0;
|
||||
|
||||
static const char g_cursoron[] = VT100_CURSORON;
|
||||
static const char g_cursoroff[] = VT100_CURSOROFF;
|
||||
static const char g_getcursor[] = VT100_GETCURSOR;
|
||||
static const char g_erasetoeol[] = VT100_CLEAREOL;
|
||||
static const char g_fmtcursorpos[] = VT100_FMT_CURSORPOS;
|
||||
static const char g_clrscr[] = VT100_CLEARSCREEN;
|
||||
static const char g_clrline[] = VT100_CLEARLINE;
|
||||
static const char g_home[] = VT100_CURSORHOME;
|
||||
#ifdef CONFIG_SYSTEM_COLOR_CLE
|
||||
static const char g_setcolor[] = VT100_FMT_FORE_COLOR;
|
||||
@ -367,21 +363,49 @@ static void cle_cursoroff(FAR struct cle_s *priv)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void cle_setcursor(FAR struct cle_s *priv, uint16_t column)
|
||||
static void cle_setcursor(FAR struct cle_s *priv, int16_t column)
|
||||
{
|
||||
char buffer[16];
|
||||
int len;
|
||||
int off;
|
||||
|
||||
cleinfo("row=%d column=%d offset=%d\n", priv->row, column, priv->coloffs);
|
||||
/* Sub prompt offset from real postion to get correct offset to execute */
|
||||
|
||||
/* Format the cursor position command. The origin is (1,1). */
|
||||
off = column - (priv->realpos - priv->coloffs);
|
||||
|
||||
len = snprintf(buffer, 16, g_fmtcursorpos,
|
||||
priv->row, column + priv->coloffs);
|
||||
cleinfo("column=%d offset=%d\n", column, off);
|
||||
|
||||
/* If cursor not move, retrun directly */
|
||||
|
||||
if (off == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* If position after adjustment is belong to promot area,
|
||||
* limit it to edge of the prompt.
|
||||
*/
|
||||
|
||||
if (off + priv->realpos < priv->coloffs)
|
||||
{
|
||||
off = priv->realpos - priv->coloffs;
|
||||
}
|
||||
|
||||
/* Format the cursor position command.
|
||||
* Move left or right depends on the current cursor position in buffer.
|
||||
*/
|
||||
|
||||
len = snprintf(buffer, sizeof(buffer),
|
||||
off < 0 ? VT100_FMT_CURSORLF : VT100_FMT_CURSORRT,
|
||||
off < 0 ? -off : off);
|
||||
|
||||
/* Send the VT100 CURSORPOS command */
|
||||
|
||||
cle_write(priv, buffer, len);
|
||||
|
||||
/* Update the current cursor position in terminal */
|
||||
|
||||
priv->realpos = priv->coloffs + column;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -436,96 +460,9 @@ static void cle_clrscr(FAR struct cle_s *priv)
|
||||
|
||||
cle_write(priv, g_clrscr, sizeof(g_clrscr));
|
||||
cle_write(priv, g_home, sizeof(g_home));
|
||||
priv->row = 1;
|
||||
cle_outputprompt(priv);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cle_getcursor
|
||||
*
|
||||
* Description:
|
||||
* Get the current cursor position.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int cle_getcursor(FAR struct cle_s *priv, FAR uint16_t *prow,
|
||||
FAR uint16_t *pcolumn)
|
||||
{
|
||||
uint32_t row;
|
||||
uint32_t column;
|
||||
int nbad;
|
||||
int ch;
|
||||
|
||||
/* Send the VT100 GETCURSOR command */
|
||||
|
||||
cle_write(priv, g_getcursor, sizeof(g_getcursor));
|
||||
|
||||
/* We expect to get back ESC[v;hR where v is the row and h is the column.
|
||||
* once the sequence has started we don't expect any characters
|
||||
* interspersed.
|
||||
*/
|
||||
|
||||
for (nbad = 0; nbad < 10; nbad++)
|
||||
{
|
||||
/* Look for initial ESC */
|
||||
|
||||
ch = cle_getch(priv);
|
||||
if (ch != ASCII_ESC)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Have ESC, now we expect '[' */
|
||||
|
||||
ch = cle_getch(priv);
|
||||
if (ch != '[')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* ...now we expect to see a numeric value terminated with ';' */
|
||||
|
||||
row = 0;
|
||||
|
||||
while (isdigit(ch = cle_getch(priv)))
|
||||
{
|
||||
row = row * 10 + (ch - '0');
|
||||
}
|
||||
|
||||
if (ch != ';')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* ...now we expect to see another numeric value terminated with 'R' */
|
||||
|
||||
column = 0;
|
||||
while (isdigit(ch = cle_getch(priv)))
|
||||
{
|
||||
column = 10 * column + (ch - '0');
|
||||
}
|
||||
|
||||
/* ...we are done */
|
||||
|
||||
cleinfo("row=%" PRId32 " column=%" PRId32 "\n", row, column);
|
||||
|
||||
/* Make sure that the values are within range */
|
||||
|
||||
if (row <= UINT16_MAX && column <= UINT16_MAX)
|
||||
{
|
||||
*prow = row;
|
||||
*pcolumn = column;
|
||||
return OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -ERANGE;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: cle_clrtoeol
|
||||
*
|
||||
@ -627,7 +564,7 @@ static void cle_closetext(FAR struct cle_s *priv, uint16_t pos,
|
||||
* the beginning of the deleted region.
|
||||
*/
|
||||
|
||||
priv->curpos = pos;
|
||||
priv->curpos = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -672,6 +609,7 @@ static void cle_showtext(FAR struct cle_s *priv)
|
||||
for (; column < tabcol; column++)
|
||||
{
|
||||
cle_putch(priv, ' ');
|
||||
priv->realpos++;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -690,6 +628,7 @@ static void cle_showtext(FAR struct cle_s *priv)
|
||||
{
|
||||
cle_putch(priv, priv->line[column]);
|
||||
column++;
|
||||
priv->realpos++;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1070,6 +1009,13 @@ static int cle_editloop(FAR struct cle_s *priv)
|
||||
/* Insert the filtered character into the buffer */
|
||||
|
||||
cle_insertch(priv, ch);
|
||||
|
||||
/* Printable character will change the cursor position in */
|
||||
|
||||
if (ch != '\t')
|
||||
{
|
||||
priv->realpos++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1104,7 +1050,6 @@ int cle_fd(FAR char *line, FAR const char *prompt, uint16_t linelen,
|
||||
int infd, int outfd)
|
||||
{
|
||||
FAR struct cle_s priv;
|
||||
uint16_t column;
|
||||
int ret;
|
||||
|
||||
/* Initialize the CLE state structure */
|
||||
@ -1117,30 +1062,21 @@ int cle_fd(FAR char *line, FAR const char *prompt, uint16_t linelen,
|
||||
priv.infd = infd;
|
||||
priv.outfd = outfd;
|
||||
|
||||
/* Clear line, move cursor to column 1 */
|
||||
|
||||
cle_write(&priv, g_clrline, sizeof(g_clrline));
|
||||
|
||||
/* Store the prompt in case we need to re-print it */
|
||||
|
||||
priv.prompt = prompt;
|
||||
cle_outputprompt(&priv);
|
||||
|
||||
/* Get the current cursor position */
|
||||
/* Assumption:
|
||||
* nsh prompt is always shown at line start by clear line.
|
||||
*/
|
||||
|
||||
ret = cle_getcursor(&priv, &priv.row, &column);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Turn the column number into an offset */
|
||||
|
||||
if (column < 1)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
priv.coloffs = column;
|
||||
|
||||
cleinfo("row=%d column=%d\n", priv.row, column);
|
||||
priv.coloffs = strlen(prompt);
|
||||
priv.realpos = priv.coloffs;
|
||||
|
||||
/* The editor loop */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user