summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-01-21 09:57:43 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-01-21 09:57:43 -0600
commitdc943a35d15f571d596369c0f516a206ade0c643 (patch)
tree261b09a7d87fe6816b6efc1ddd9497abed2bdde3
parenta34994e624fafe9b74411868519504e452246004 (diff)
downloadnuttx-dc943a35d15f571d596369c0f516a206ade0c643.tar.gz
nuttx-dc943a35d15f571d596369c0f516a206ade0c643.tar.bz2
nuttx-dc943a35d15f571d596369c0f516a206ade0c643.zip
VI: Several bug fixes
-rw-r--r--apps/system/vi/vi.c185
1 files changed, 136 insertions, 49 deletions
diff --git a/apps/system/vi/vi.c b/apps/system/vi/vi.c
index d580f57c6..4d8528913 100644
--- a/apps/system/vi/vi.c
+++ b/apps/system/vi/vi.c
@@ -309,6 +309,8 @@ static off_t vi_cursorright(FAR struct vi_s *vi, off_t curpos,
int ncolumns);
static void vi_delforward(FAR struct vi_s *vi);
static void vi_delbackward(FAR struct vi_s *vi);
+static void vi_linerange(FAR struct vi_s *vi, off_t *start, off_t *end);
+static void vi_delline(FAR struct vi_s *vi);
static void vi_yank(FAR struct vi_s *vi);
static void vi_paste(FAR struct vi_s *vi);
static void vi_gotoline(FAR struct vi_s *vi);
@@ -367,7 +369,7 @@ static const char g_blinkon[] = VT100_BLINK;
static const char g_boldoff[] = VT100_BOLDOFF;
static const char g_reverseoff[] = VT100_REVERSEOFF;
static const char g_blinkoff[] = VT100_BLINKOFF;
-#endif
+#endif
static const char g_fmtcursorpos[] = VT100_FMT_CURSORPOS;
@@ -799,7 +801,7 @@ static off_t vi_linebegin(FAR struct vi_s *vi, off_t pos)
* Name: vi_prevline
*
* Description:
- * Search backward for the end of the previous line
+ * Search backward for the beginning of the previous line
*
****************************************************************************/
@@ -1375,10 +1377,10 @@ static void vi_scrollcheck(FAR struct vi_s *vi)
while (curline < vi->winpos)
{
- /* Yes.. move the window position up by one line and check again */
+ /* Yes.. move the window position up to the beginning of the previous
+ * line line and check again */
- pos = vi_prevline(vi, vi->winpos);
- vi->winpos = vi_linebegin(vi, pos);
+ vi->winpos = vi_prevline(vi, vi->winpos);
}
/* Reset the cursor row position so that it is relative to the
@@ -1654,13 +1656,12 @@ static void vi_cusorup(FAR struct vi_s *vi, int nlines)
int remaining;
off_t start;
off_t end;
- off_t pos;
vivdbg("nlines=%d\n", nlines);
/* How many lines do we need to move? Zero means 1 (so does 1) */
- remaining = (nlines == 0 ? 1 : nlines);
+ remaining = (nlines < 1 ? 1 : nlines);
/* Get the offset to the start of the current line */
@@ -1670,14 +1671,15 @@ static void vi_cusorup(FAR struct vi_s *vi, int nlines)
for (; remaining > 0; remaining--)
{
- /* Get the start and end offset of the line */
+ /* Get the start position of the previous line */
- pos = vi_prevline(vi, start);
- start = vi_linebegin(vi, pos);
- end = start + vi->cursor.column + vi->hscroll;
+ start = vi_prevline(vi, start);
- /* Get the text buffer position to the horizontal cursor position */
+ /* Find the cursor position on the next line corresponding to the
+ * cursor position on the current line.
+ */
+ end = start + vi->cursor.column + vi->hscroll;
vi_windowpos(vi, start, end, NULL, &vi->curpos);
}
}
@@ -1700,7 +1702,7 @@ static void vi_cursordown(FAR struct vi_s *vi, int nlines)
/* How many lines do we need to move? Zero means 1 (so does 1) */
- remaining = (nlines == 0 ? 1 : nlines);
+ remaining = (nlines < 1 ? 1 : nlines);
/* Get the offset to the start of the current line */
@@ -1710,18 +1712,15 @@ static void vi_cursordown(FAR struct vi_s *vi, int nlines)
for (; remaining > 0; remaining--)
{
- if (!vi_lineend(vi, vi->curpos) < vi->textsize)
- {
- break;
- }
-
- /* Get the start and end offset of the line */
+ /* Get the start of the next line. */
start = vi_nextline(vi, start);
- end = start + vi->cursor.column + vi->hscroll;
- /* Get the text buffer position to the horizontal cursor position */
+ /* Find the cursor position on the next line corresponding to the
+ * cursor position on the current line.
+ */
+ end = start + vi->cursor.column + vi->hscroll;
vi_windowpos(vi, start, end, NULL, &vi->curpos);
}
}
@@ -1742,8 +1741,13 @@ static off_t vi_cursorleft(FAR struct vi_s *vi, off_t curpos, int ncolumns)
vivdbg("curpos=%ld ncolumns=%d\n", curpos, ncolumns);
+ /* Loop decrementing the cursor position for each repitition count. Break
+ * out early if we hit either the beginning of the text buffer, or the end
+ * of the previous line.
+ */
+
for (remaining = (ncolumns < 1 ? 1 : ncolumns);
- curpos > 0 && remaining > 0 && vi->text[curpos] != '\n';
+ curpos > 0 && remaining > 0 && vi->text[curpos - 1] != '\n';
curpos--, remaining--);
return curpos;
@@ -1765,6 +1769,10 @@ static off_t vi_cursorright(FAR struct vi_s *vi, off_t curpos, int ncolumns)
vivdbg("curpos=%ld ncolumns=%d\n", curpos, ncolumns);
+ /* Loop incrementing the cursor position for each repitition count. Break
+ * out early if we hit either the end of the text buffer, or the end of the line.
+ */
+
for (remaining = (ncolumns < 1 ? 1 : ncolumns);
curpos < vi->textsize && remaining > 0 && vi->text[curpos] != '\n';
curpos++, remaining--);
@@ -1787,8 +1795,17 @@ static void vi_delforward(FAR struct vi_s *vi)
vivdbg("curpos=%ld value=%ld\n", (long)vi->curpos, vi->value);
+ /* Get the cursor position as if we would have move the cursor right N
+ * times (which might be <N characters).
+ */
+
end = vi_cursorright(vi, vi->curpos, vi->value);
- size = end - vi->curpos - 1;
+
+ /* The difference from the current position then is the number of
+ * characters to be deleted.
+ */
+
+ size = end - vi->curpos;
vi_shrinktext(vi, vi->curpos, size);
}
@@ -1808,46 +1825,104 @@ static void vi_delbackward(FAR struct vi_s *vi)
vivdbg("curpos=%ld value=%ld\n", (long)vi->curpos, vi->value);
- start = vi_cursorleft(vi, vi->curpos, 1);
- end = vi_cursorleft(vi, start, vi->value);
- size = end - start - 1;
+ /* Back up one character. This is where the deletion will end */
+
+ end = vi_cursorleft(vi, vi->curpos, 1);
+
+ /* Get the cursor position as if we would have move the cursor left N
+ * times (which might be <N characters).
+ */
+
+ start = vi_cursorleft(vi, end, vi->value);
+
+ /* The difference from the current position then is the number of
+ * characters to be deleted.
+ */
+
+ size = end - start;
vi_shrinktext(vi, start, size);
}
/****************************************************************************
- * Name: vi_yank
+ * Name: vi_linerange
*
* Description:
- * Remove N lines from the text buffer, beginning at the current line and
- * copy the lines to an allocated yank buffer.
+ * Return the start and end positions for N lines int the text buffer,
+ * beginning at the current line. This is logic common to yanking and
+ * deleting lines.
*
****************************************************************************/
-static void vi_yank(FAR struct vi_s *vi)
+static void vi_linerange(FAR struct vi_s *vi, off_t *start, off_t *end)
{
- off_t start;
- off_t end;
off_t next;
int nlines;
/* Get the offset in the text buffer to the beginning of the current line */
- start = vi_linebegin(vi, vi->curpos);
+ *start = vi_linebegin(vi, vi->curpos);
/* Move one line unless a repetition count was provided */
nlines = (vi->value > 0 ? vi->value : 1);
- vivdbg("start=%ld nlines=%d\n", (long)start, nlines);
-
/* Search ahead to find the end of the last line to yank */
- for (next = start; nlines > 1; nlines--)
+ for (next = *start; nlines > 1; nlines--)
{
next = vi_nextline(vi, next);
}
- end = vi_lineend(vi, next);
+ *end = vi_lineend(vi, next);
+}
+
+/****************************************************************************
+ * Name: vi_delline
+ *
+ * Description:
+ * Delete N lines from the text buffer, beginning at the current line.
+ *
+ ****************************************************************************/
+
+static void vi_delline(FAR struct vi_s *vi)
+{
+ off_t delsize;
+ off_t start;
+ off_t end;
+
+ /* Get the offset in the text buffer corresponding to the range of lines to
+ * be deleted
+ */
+
+ vi_linerange(vi, &start, &end);
+ vivdbg("start=%ld end=%ld\n", (long)start, (long)end);
+
+ /* Remove the text from the text buffer */
+
+ delsize = end - start + 1;
+ vi_shrinktext(vi, start, delsize);
+}
+
+/****************************************************************************
+ * Name: vi_yank
+ *
+ * Description:
+ * Remove N lines from the text buffer, beginning at the current line and
+ * copy the lines to an allocated yank buffer.
+ *
+ ****************************************************************************/
+
+static void vi_yank(FAR struct vi_s *vi)
+{
+ off_t start;
+ off_t end;
+
+ /* Get the offset in the text buffer corresponding to the range of lines to
+ * be yanked
+ */
+
+ vi_linerange(vi, &start, &end);
+ vivdbg("start=%ld end=%ld\n", (long)start, (long)end);
/* Free any previously yanked lines */
@@ -2115,8 +2190,8 @@ static void vi_cmd_mode(FAR struct vi_s *vi)
{
if (vi->delarm)
{
- off_t curline = vi_linebegin(vi, vi->curpos);
- vi_shrinktext(vi, curline, vi_nextline(vi, curline) - curline);
+ vi_delline(vi);
+ vi->delarm = false;
}
else
{
@@ -2130,6 +2205,7 @@ static void vi_cmd_mode(FAR struct vi_s *vi)
if (vi->yankarm)
{
vi_yank(vi);
+ vi->yankarm = false;
}
else
{
@@ -2158,6 +2234,10 @@ static void vi_cmd_mode(FAR struct vi_s *vi)
case KEY_CMDMODE_OPENBELOW: /* Enter insertion mode in new line below current */
{
+ /* Go forward to the end of the current line */
+
+ vi->curpos = vi_lineend(vi, vi->curpos);
+
/* Insert a newline to break the line. The cursor now points
* beginning of the new line.
*/
@@ -2172,12 +2252,16 @@ static void vi_cmd_mode(FAR struct vi_s *vi)
case KEY_CMDMODE_OPENABOVE: /* Enter insertion mode in new line above current */
{
- /* Insert a newline to break the line. Backup the cursor so
- * that it points to the end of the (previous) current line.
+ /* Back up to the beginning of the end of the previous line */
+
+ off_t pos = vi_prevline(vi, vi->curpos);
+ vi->curpos = vi_lineend(vi, pos);
+
+ /* Insert a newline to open the line. The cursor will now point to the
+ * beginning of newly openly line before the current line.
*/
vi_insertch(vi, '\n');
- vi->curpos = vi_prevline(vi, vi->curpos);
/* Then enter insert mode */
@@ -2187,7 +2271,7 @@ static void vi_cmd_mode(FAR struct vi_s *vi)
case KEY_CMDMODE_APPEND: /* Enter insertion mode after the current cursor position */
{
- vi->curpos = vi_cursorleft(vi, vi->curpos, 1);
+ vi->curpos = vi_cursorright(vi, vi->curpos, 1);
vi_setmode(vi, MODE_INSERT, 0);
}
break;
@@ -2242,10 +2326,14 @@ static void vi_cmd_mode(FAR struct vi_s *vi)
}
/* Any non-numeric input will reset the accumulated value (after it has
- * been used)
+ * been used). For the double character sequences, we need to retain
+ * the value until the next character is entered.
*/
- vi->value = 0;
+ if (!vi->delarm && !vi->yankarm)
+ {
+ vi->value = 0;
+ }
}
}
@@ -2836,7 +2924,7 @@ static void vi_replacech_submode(FAR struct vi_s *vi)
off_t end;
long nchars;
bool found = false;
- int ch;
+ int ch = 0;
/* Get the number of characters to replace */
@@ -2850,13 +2938,12 @@ static void vi_replacech_submode(FAR struct vi_s *vi)
if (vi->curpos + nchars > end)
{
vi_error(vi, g_fmtnotvalid);
- vi_exitsubmode(vi, MODE_COMMAND);
vi_setmode(vi, MODE_COMMAND, 0);
}
/* Loop until we get the replacement character */
- while (!found)
+ while (vi->mode == SUBMODE_REPLACECH && !found)
{
/* Get the next character from the input */
@@ -3023,7 +3110,7 @@ static void vi_insert_mode(FAR struct vi_s *vi)
case ASCII_BS:
{
- if (vi->curpos)
+ if (vi->curpos > 0)
{
vi_shrinktext(vi, --vi->curpos, 1);
}