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
174
system/cle/cle.c
174
system/cle/cle.c
@ -108,9 +108,8 @@ enum cle_key_e
|
|||||||
|
|
||||||
struct cle_s
|
struct cle_s
|
||||||
{
|
{
|
||||||
uint16_t curpos; /* Current cursor position */
|
int16_t curpos; /* Current cursor position in buffer */
|
||||||
uint16_t cursave; /* Saved cursor position */
|
int16_t realpos; /* Current cursor position in terminal */
|
||||||
uint16_t row; /* This is the row that we are editing in */
|
|
||||||
uint16_t coloffs; /* Left cursor offset */
|
uint16_t coloffs; /* Left cursor offset */
|
||||||
uint16_t linelen; /* Size of the line buffer */
|
uint16_t linelen; /* Size of the line buffer */
|
||||||
uint16_t nchars; /* Size of data in 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 int cle_getch(FAR struct cle_s *priv);
|
||||||
static void cle_cursoron(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_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);
|
||||||
static int cle_getcursor(FAR struct cle_s *priv, uint16_t *prow,
|
|
||||||
uint16_t *pcolumn);
|
|
||||||
static void cle_clrtoeol(FAR struct cle_s *priv);
|
static void cle_clrtoeol(FAR struct cle_s *priv);
|
||||||
|
|
||||||
/* Editor function */
|
/* Editor function */
|
||||||
@ -183,10 +180,9 @@ static int g_cmd_history_len = 0;
|
|||||||
|
|
||||||
static const char g_cursoron[] = VT100_CURSORON;
|
static const char g_cursoron[] = VT100_CURSORON;
|
||||||
static const char g_cursoroff[] = VT100_CURSOROFF;
|
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_erasetoeol[] = VT100_CLEAREOL;
|
||||||
static const char g_fmtcursorpos[] = VT100_FMT_CURSORPOS;
|
|
||||||
static const char g_clrscr[] = VT100_CLEARSCREEN;
|
static const char g_clrscr[] = VT100_CLEARSCREEN;
|
||||||
|
static const char g_clrline[] = VT100_CLEARLINE;
|
||||||
static const char g_home[] = VT100_CURSORHOME;
|
static const char g_home[] = VT100_CURSORHOME;
|
||||||
#ifdef CONFIG_SYSTEM_COLOR_CLE
|
#ifdef CONFIG_SYSTEM_COLOR_CLE
|
||||||
static const char g_setcolor[] = VT100_FMT_FORE_COLOR;
|
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];
|
char buffer[16];
|
||||||
int len;
|
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,
|
cleinfo("column=%d offset=%d\n", column, off);
|
||||||
priv->row, column + priv->coloffs);
|
|
||||||
|
/* 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 */
|
/* Send the VT100 CURSORPOS command */
|
||||||
|
|
||||||
cle_write(priv, buffer, len);
|
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_clrscr, sizeof(g_clrscr));
|
||||||
cle_write(priv, g_home, sizeof(g_home));
|
cle_write(priv, g_home, sizeof(g_home));
|
||||||
priv->row = 1;
|
|
||||||
cle_outputprompt(priv);
|
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
|
* Name: cle_clrtoeol
|
||||||
*
|
*
|
||||||
@ -672,6 +609,7 @@ static void cle_showtext(FAR struct cle_s *priv)
|
|||||||
for (; column < tabcol; column++)
|
for (; column < tabcol; column++)
|
||||||
{
|
{
|
||||||
cle_putch(priv, ' ');
|
cle_putch(priv, ' ');
|
||||||
|
priv->realpos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -690,6 +628,7 @@ static void cle_showtext(FAR struct cle_s *priv)
|
|||||||
{
|
{
|
||||||
cle_putch(priv, priv->line[column]);
|
cle_putch(priv, priv->line[column]);
|
||||||
column++;
|
column++;
|
||||||
|
priv->realpos++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1070,6 +1009,13 @@ static int cle_editloop(FAR struct cle_s *priv)
|
|||||||
/* Insert the filtered character into the buffer */
|
/* Insert the filtered character into the buffer */
|
||||||
|
|
||||||
cle_insertch(priv, ch);
|
cle_insertch(priv, ch);
|
||||||
|
|
||||||
|
/* Printable character will change the cursor position in */
|
||||||
|
|
||||||
|
if (ch != '\t')
|
||||||
|
{
|
||||||
|
priv->realpos++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1104,7 +1050,6 @@ int cle_fd(FAR char *line, FAR const char *prompt, uint16_t linelen,
|
|||||||
int infd, int outfd)
|
int infd, int outfd)
|
||||||
{
|
{
|
||||||
FAR struct cle_s priv;
|
FAR struct cle_s priv;
|
||||||
uint16_t column;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Initialize the CLE state structure */
|
/* 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.infd = infd;
|
||||||
priv.outfd = outfd;
|
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 */
|
/* Store the prompt in case we need to re-print it */
|
||||||
|
|
||||||
priv.prompt = prompt;
|
priv.prompt = prompt;
|
||||||
cle_outputprompt(&priv);
|
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);
|
priv.coloffs = strlen(prompt);
|
||||||
|
priv.realpos = priv.coloffs;
|
||||||
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);
|
|
||||||
|
|
||||||
/* The editor loop */
|
/* The editor loop */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user