apps/system/vi/vi.c: Fix an infinite loop bug that can show up in some coases (plus a couple of other items).
This commit is contained in:
parent
6fb399fd65
commit
1a82551036
142
system/vi/vi.c
142
system/vi/vi.c
@ -220,6 +220,7 @@ enum vi_cmdmode_key_e
|
|||||||
KEY_CMDMODE_BEGINLINE = '0', /* Move cursor to start of current line */
|
KEY_CMDMODE_BEGINLINE = '0', /* Move cursor to start of current line */
|
||||||
KEY_CMDMODE_APPEND = 'a', /* Enter insertion mode after current character */
|
KEY_CMDMODE_APPEND = 'a', /* Enter insertion mode after current character */
|
||||||
KEY_CMDMODE_WORDBACK = 'b', /* Scan to previous word */
|
KEY_CMDMODE_WORDBACK = 'b', /* Scan to previous word */
|
||||||
|
KEY_CMDMODE_CHANGE = 'c', /* Delete text and enter insert mode */
|
||||||
KEY_CMDMODE_DEL_LINE = 'd', /* "dd" deletes a lines */
|
KEY_CMDMODE_DEL_LINE = 'd', /* "dd" deletes a lines */
|
||||||
KEY_CMDMODE_FINDINLINE = 'f', /* Find within current line */
|
KEY_CMDMODE_FINDINLINE = 'f', /* Find within current line */
|
||||||
KEY_CMDMODE_GOTOTOP = 'g', /* Two of these sends cursor to the top */
|
KEY_CMDMODE_GOTOTOP = 'g', /* Two of these sends cursor to the top */
|
||||||
@ -351,8 +352,9 @@ struct vi_s
|
|||||||
uint8_t cmdlen; /* Length of the command in the scratch[] buffer */
|
uint8_t cmdlen; /* Length of the command in the scratch[] buffer */
|
||||||
bool modified; /* True: The file has modified */
|
bool modified; /* True: The file has modified */
|
||||||
bool error; /* True: There is an error message on the last line */
|
bool error; /* True: There is an error message on the last line */
|
||||||
bool delarm; /* One more 'd' and the line(s) will be deleted */
|
bool delarm; /* Delete text arm flag */
|
||||||
bool yankarm; /* One more 'y' and the line(s) will be yanked */
|
bool chgarm; /* Change text arm flag */
|
||||||
|
bool yankarm; /* Yank text arm flag */
|
||||||
bool toparm; /* One more 'g' and the cursor moves to the top */
|
bool toparm; /* One more 'g' and the cursor moves to the top */
|
||||||
bool wqarm; /* One more 'Z' is the same as :wq */
|
bool wqarm; /* One more 'Z' is the same as :wq */
|
||||||
bool fullredraw; /* True to draw all lines on screen */
|
bool fullredraw; /* True to draw all lines on screen */
|
||||||
@ -1453,6 +1455,7 @@ static void vi_setmode(FAR struct vi_s *vi, uint8_t mode, long value)
|
|||||||
vi->delarm = false;
|
vi->delarm = false;
|
||||||
vi->yankarm = false;
|
vi->yankarm = false;
|
||||||
vi->toparm = false;
|
vi->toparm = false;
|
||||||
|
vi->chgarm = false;
|
||||||
vi->wqarm = false;
|
vi->wqarm = false;
|
||||||
vi->value = value;
|
vi->value = value;
|
||||||
vi->cmdlen = 0;
|
vi->cmdlen = 0;
|
||||||
@ -1641,6 +1644,13 @@ static void vi_scrollcheck(FAR struct vi_s *vi)
|
|||||||
int column;
|
int column;
|
||||||
int nlines;
|
int nlines;
|
||||||
|
|
||||||
|
/* Sanity test */
|
||||||
|
|
||||||
|
if (vi->curpos > vi->textsize)
|
||||||
|
{
|
||||||
|
vi->curpos = vi->textsize;
|
||||||
|
}
|
||||||
|
|
||||||
/* Get the text buffer offset to the beginning of the current line */
|
/* Get the text buffer offset to the beginning of the current line */
|
||||||
|
|
||||||
curline = vi_linebegin(vi, vi->curpos);
|
curline = vi_linebegin(vi, vi->curpos);
|
||||||
@ -2470,7 +2480,7 @@ static void vi_deltoeol(FAR struct vi_s *vi)
|
|||||||
/* Yank and remove text from the buffer */
|
/* Yank and remove text from the buffer */
|
||||||
|
|
||||||
vi_yanktext(vi, start, end, true, true);
|
vi_yanktext(vi, start, end, true, true);
|
||||||
if (start != vi->textsize && vi->text[start] != '\n')
|
if (start > 0 && start != vi->textsize && vi->text[start - 1] != '\n')
|
||||||
{
|
{
|
||||||
vi->curpos = start-1;
|
vi->curpos = start-1;
|
||||||
}
|
}
|
||||||
@ -2589,6 +2599,7 @@ static void vi_yank(FAR struct vi_s *vi, bool del_after_yank)
|
|||||||
off_t yank_end;
|
off_t yank_end;
|
||||||
off_t textsize;
|
off_t textsize;
|
||||||
int pos_increment = 0;
|
int pos_increment = 0;
|
||||||
|
bool empty_last_line = false;
|
||||||
|
|
||||||
/* Get the offset in the text buffer corresponding to the range of lines to
|
/* Get the offset in the text buffer corresponding to the range of lines to
|
||||||
* be yanked
|
* be yanked
|
||||||
@ -2621,6 +2632,15 @@ static void vi_yank(FAR struct vi_s *vi, bool del_after_yank)
|
|||||||
|
|
||||||
viinfo("start=%ld end=%ld\n", (long)start, (long)end);
|
viinfo("start=%ld end=%ld\n", (long)start, (long)end);
|
||||||
|
|
||||||
|
/* Test if deleting last line with empty line above it */
|
||||||
|
|
||||||
|
if ((end > 0 && start == end && end == vi->textsize -1 &&
|
||||||
|
vi->text[end-1] == '\n') || (start > 1 && end + 1 ==
|
||||||
|
vi->textsize && vi->text[start-2] == '\n'))
|
||||||
|
{
|
||||||
|
empty_last_line = true;
|
||||||
|
}
|
||||||
|
|
||||||
vi_yanktext(vi, start, yank_end, 0, del_after_yank);
|
vi_yanktext(vi, start, yank_end, 0, del_after_yank);
|
||||||
|
|
||||||
/* If the last line was yanked, then remove the '\n' on the
|
/* If the last line was yanked, then remove the '\n' on the
|
||||||
@ -2634,8 +2654,18 @@ static void vi_yank(FAR struct vi_s *vi, bool del_after_yank)
|
|||||||
|
|
||||||
/* Place cursor at beginning of the line */
|
/* Place cursor at beginning of the line */
|
||||||
|
|
||||||
|
if (del_after_yank)
|
||||||
|
{
|
||||||
|
if (empty_last_line)
|
||||||
|
{
|
||||||
|
vi->curpos = vi->textsize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
vi->curpos = vi_linebegin(vi, vi->curpos + pos_increment);
|
vi->curpos = vi_linebegin(vi, vi->curpos + pos_increment);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: vi_paste
|
* Name: vi_paste
|
||||||
@ -2654,7 +2684,7 @@ static void vi_paste(FAR struct vi_s *vi, bool paste_before)
|
|||||||
|
|
||||||
viinfo("curpos=%ld yankalloc=%d\n", (long)vi->curpos, (long)vi->yankalloc);
|
viinfo("curpos=%ld yankalloc=%d\n", (long)vi->curpos, (long)vi->yankalloc);
|
||||||
|
|
||||||
/* Make sure there is something to be yanked */
|
/* Make sure there is something to be pasted */
|
||||||
|
|
||||||
if (!vi->yank || vi->yanksize <= 0)
|
if (!vi->yank || vi->yanksize <= 0)
|
||||||
{
|
{
|
||||||
@ -2726,9 +2756,11 @@ static void vi_paste(FAR struct vi_s *vi, bool paste_before)
|
|||||||
/* Test if pasting at end of file */
|
/* Test if pasting at end of file */
|
||||||
|
|
||||||
new_curpos = start;
|
new_curpos = start;
|
||||||
if (start >= vi->textsize && vi->text[vi->textsize-1] != '\n')
|
if ((start >= vi->textsize && vi->text[vi->textsize-1] != '\n') ||
|
||||||
|
vi->curpos == vi->textsize)
|
||||||
{
|
{
|
||||||
off_t textsize = vi->textsize;
|
off_t textsize = vi->textsize;
|
||||||
|
bool at_end = vi->curpos == vi->textsize;
|
||||||
|
|
||||||
vi->curpos = vi->textsize;
|
vi->curpos = vi->textsize;
|
||||||
vi_insertch(vi, '\n');
|
vi_insertch(vi, '\n');
|
||||||
@ -2737,7 +2769,7 @@ static void vi_paste(FAR struct vi_s *vi, bool paste_before)
|
|||||||
|
|
||||||
/* Don't append the \n' in the yank buffer */
|
/* Don't append the \n' in the yank buffer */
|
||||||
|
|
||||||
if (vi->text[textsize-1] != '\n')
|
if (vi->text[textsize-1] != '\n' || at_end)
|
||||||
{
|
{
|
||||||
size--;
|
size--;
|
||||||
}
|
}
|
||||||
@ -2748,7 +2780,7 @@ static void vi_paste(FAR struct vi_s *vi, bool paste_before)
|
|||||||
else if (start >= vi->textsize)
|
else if (start >= vi->textsize)
|
||||||
{
|
{
|
||||||
start = vi->textsize;
|
start = vi->textsize;
|
||||||
new_curpos = start + size;
|
new_curpos = start;
|
||||||
vi->fullredraw = true;
|
vi->fullredraw = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3031,9 +3063,9 @@ static void vi_gotonextword(FAR struct vi_s *vi)
|
|||||||
vi->curpos = vi_findnextword(vi);
|
vi->curpos = vi_findnextword(vi);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Test if yank or delete are armed */
|
/* Test if yank, delete or change are armed */
|
||||||
|
|
||||||
if (vi->yankarm || vi->delarm)
|
if (vi->yankarm || vi->delarm || vi->chgarm)
|
||||||
{
|
{
|
||||||
/* Rewind so we don't yank skipped whitespace */
|
/* Rewind so we don't yank skipped whitespace */
|
||||||
|
|
||||||
@ -3083,14 +3115,25 @@ static void vi_gotonextword(FAR struct vi_s *vi)
|
|||||||
{
|
{
|
||||||
/* Multi-line delete? */
|
/* Multi-line delete? */
|
||||||
|
|
||||||
vi->fullredraw = vi->delarm;
|
vi->fullredraw = vi->delarm || vi->chgarm;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Perform the yank */
|
/* Perform the yank */
|
||||||
|
|
||||||
end = vi->curpos + 1 == vi->textsize ? vi->curpos : vi->curpos - 1;
|
end = vi->curpos + 1 == vi->textsize ? vi->curpos : vi->curpos - 1;
|
||||||
vi_yanktext(vi, start, end, 1, vi->delarm);
|
if (vi->chgarm)
|
||||||
if (vi->delarm)
|
{
|
||||||
|
end--;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Yank text if it isn't a single \n character */
|
||||||
|
|
||||||
|
if (!(start == end && vi->text[start] == '\n'))
|
||||||
|
{
|
||||||
|
vi_yanktext(vi, start, end, 1, vi->delarm | vi->chgarm);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vi->delarm | vi->chgarm)
|
||||||
{
|
{
|
||||||
/* Redraw line if text deleted */
|
/* Redraw line if text deleted */
|
||||||
|
|
||||||
@ -3104,14 +3147,22 @@ static void vi_gotonextword(FAR struct vi_s *vi)
|
|||||||
#ifdef CONFIG_SYSTEM_VI_INCLUDE_COMMAND_REPEAT
|
#ifdef CONFIG_SYSTEM_VI_INCLUDE_COMMAND_REPEAT
|
||||||
/* Setup command repeat */
|
/* Setup command repeat */
|
||||||
|
|
||||||
if (vi->delarm)
|
if (vi->delarm | vi->chgarm)
|
||||||
{
|
{
|
||||||
vi_saverepeat(vi, 'd');
|
vi_saverepeat(vi, vi->delarm ? 'd' : 'c');
|
||||||
vi_appendrepeat(vi, 'w');
|
vi_appendrepeat(vi, 'w');
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* If change text is armed, then enter insert mode */
|
||||||
|
|
||||||
|
if (vi->chgarm)
|
||||||
|
{
|
||||||
|
vi_setmode(vi, MODE_INSERT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
vi->delarm = false;
|
vi->delarm = false;
|
||||||
|
vi->chgarm = false;
|
||||||
vi->yankarm = false;
|
vi->yankarm = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3506,6 +3557,13 @@ static void vi_cmd_mode(FAR struct vi_s *vi)
|
|||||||
{
|
{
|
||||||
vi->yankarm = false;
|
vi->yankarm = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Anything other than 'c' disarms line yanking */
|
||||||
|
|
||||||
|
if (ch != 'c')
|
||||||
|
{
|
||||||
|
vi->chgarm = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Anything other than'g' disarms goto top */
|
/* Anything other than'g' disarms goto top */
|
||||||
@ -3743,6 +3801,36 @@ static void vi_cmd_mode(FAR struct vi_s *vi)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case KEY_CMDMODE_CHANGE:
|
||||||
|
{
|
||||||
|
if (vi->chgarm)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_SYSTEM_VI_INCLUDE_COMMAND_REPEAT
|
||||||
|
vi_saverepeat(vi, ch);
|
||||||
|
vi_appendrepeat(vi, ch);
|
||||||
|
#endif
|
||||||
|
vi_gotofirstnonwhite(vi);
|
||||||
|
vi_deltoeol(vi);
|
||||||
|
vi_setmode(vi, MODE_INSERT, 0);
|
||||||
|
if (vi->curpos == vi->textsize)
|
||||||
|
{
|
||||||
|
vi->curpos = vi_cursorright(vi, vi->curpos, 1) + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vi->curpos = vi_cursorright(vi, vi->curpos, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
vi->chgarm = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vi->chgarm = true;
|
||||||
|
preserve = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case KEY_CMDMODE_DELTOEOL: /* Delete to end of current line */
|
case KEY_CMDMODE_DELTOEOL: /* Delete to end of current line */
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_SYSTEM_VI_INCLUDE_COMMAND_REPEAT
|
#ifdef CONFIG_SYSTEM_VI_INCLUDE_COMMAND_REPEAT
|
||||||
@ -4116,9 +4204,16 @@ static void vi_cmd_mode(FAR struct vi_s *vi)
|
|||||||
case KEY_CMDMODE_REDRAW2: /* Redraws the screen, removing deleted lines */
|
case KEY_CMDMODE_REDRAW2: /* Redraws the screen, removing deleted lines */
|
||||||
case KEY_CMDMODE_MARK: /* Place a mark beginning at the current cursor position */
|
case KEY_CMDMODE_MARK: /* Place a mark beginning at the current cursor position */
|
||||||
default:
|
default:
|
||||||
|
{
|
||||||
|
if (ch == -1)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
VI_BEL(vi);
|
VI_BEL(vi);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5186,12 +5281,12 @@ static void vi_findinline_mode(FAR struct vi_s *vi)
|
|||||||
|
|
||||||
/* Test if yank or del armed */
|
/* Test if yank or del armed */
|
||||||
|
|
||||||
if (vi->yankarm || vi->delarm)
|
if (vi->yankarm || vi->delarm || vi->chgarm)
|
||||||
{
|
{
|
||||||
/* Yank the text and possibly delete */
|
/* Yank the text and possibly delete */
|
||||||
|
|
||||||
vi_yanktext(vi, vi->curpos, pos, 1, vi->delarm);
|
vi_yanktext(vi, vi->curpos, pos, 1, vi->delarm || vi->chgarm);
|
||||||
if (vi->delarm)
|
if (vi->delarm || vi->chgarm)
|
||||||
{
|
{
|
||||||
/* Redraw line if text deleted */
|
/* Redraw line if text deleted */
|
||||||
|
|
||||||
@ -5201,14 +5296,23 @@ static void vi_findinline_mode(FAR struct vi_s *vi)
|
|||||||
#ifdef CONFIG_SYSTEM_VI_INCLUDE_COMMAND_REPEAT
|
#ifdef CONFIG_SYSTEM_VI_INCLUDE_COMMAND_REPEAT
|
||||||
/* Setup command repeat */
|
/* Setup command repeat */
|
||||||
|
|
||||||
if (vi->delarm)
|
if (vi->delarm || vi->chgarm)
|
||||||
{
|
{
|
||||||
vi_saverepeat(vi, 'd');
|
vi_saverepeat(vi, vi->delarm ? 'd' : 'c');
|
||||||
vi_appendrepeat(vi, vi->tfind ? 't' : 'f');
|
vi_appendrepeat(vi, vi->tfind ? 't' : 'f');
|
||||||
vi_appendrepeat(vi, ch);
|
vi_appendrepeat(vi, ch);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* If change text is armed, then enter insert mode */
|
||||||
|
|
||||||
|
if (vi->chgarm)
|
||||||
|
{
|
||||||
|
vi->chgarm = false;
|
||||||
|
vi_setmode(vi, MODE_INSERT, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
vi->delarm = false;
|
vi->delarm = false;
|
||||||
vi->yankarm = false;
|
vi->yankarm = false;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user