diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2015-09-16 07:19:19 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2015-09-16 07:19:19 -0700 |
commit | 15346886504761400e6db3930b74cc59adfce6f9 (patch) | |
tree | 3b73f8976f7c330b70b820a53add3f0a129d83aa /linenoise | |
parent | fbc56f3575640f4acbdb6dbee78a299132fe55b8 (diff) | |
download | txr-15346886504761400e6db3930b74cc59adfce6f9.tar.gz txr-15346886504761400e6db3930b74cc59adfce6f9.tar.bz2 txr-15346886504761400e6db3930b74cc59adfce6f9.zip |
linenoise: oldpos-related multi-line refresh issue.
The oldpos variable for tracing the previous cursor position
as an absolute offset into the display data is not appropriate
any more under enhanced multi-line mode. The reason is that
edit operations can completely replace the buffer (e.g.
history recall). When the buffer is replaced, because there
can be arbitrary line breaks in the data, the oldpos
variable's saved position has no meaning relative to the new
buffer contents. But the only use of oldpos is to calculate
the previous *row* of the cursor position! So, we can replace
oldpos with a variable that just remembers the row directly.
As a bonus, we can get rid of the calculation which tries to
recover the oldrow from oldpos.
* linenoise/linenoise.c (struct lino_state): Removed member
oldpos. Added member oldrow.
(struct row_values): Array reduced to two elements.
(screen_rows): Doesn't take oldpos argument any more.
Current cursor position returned in out.rows[1].
(refresh_multiline): Some variables renamed. rpos2 becomes
nrow (new row position). old_rows is oldmaxrows to avoid
confusion with l->oldrow. The rpos variable (old row
position) is gone: its uses are replaced with l->oldrow.
Near the end of the function, we save the new cursor row
position (nrow) in l->oldrow, in the same spot where
we previously saved the current position in l->oldpos.
(edit): Initialize l->oldrow to 0. Remove initialization
of l->oldpos.
Diffstat (limited to 'linenoise')
-rw-r--r-- | linenoise/linenoise.c | 38 |
1 files changed, 17 insertions, 21 deletions
diff --git a/linenoise/linenoise.c b/linenoise/linenoise.c index 4b82898f..2a6173a4 100644 --- a/linenoise/linenoise.c +++ b/linenoise/linenoise.c @@ -90,11 +90,11 @@ struct lino_state { const char *prompt; /* Prompt to display. */ size_t plen; /* Prompt length. */ size_t pos; /* Current cursor position. */ - size_t oldpos; /* Previous refresh cursor position. */ size_t len; /* Current edited line display length. */ size_t dlen; /* True underlying length. */ size_t dpos; /* True underlying position. */ size_t cols; /* Number of columns in terminal. */ + size_t oldrow; /* Row of previous cursor position (multiline mode) */ size_t maxrows; /* Maximum num of rows used so far (multiline mode) */ int history_index; /* The history index we are currently editing. */ int need_resize; /* Need resize flag. */ @@ -664,26 +664,22 @@ static void refresh_singleline(lino_t *l) { } struct row_values { - int rows[3]; + int rows[2]; }; -static struct row_values screen_rows(const char *str, - size_t oldpos, size_t pos, - int cols) +static struct row_values screen_rows(const char *str, size_t pos, int cols) { const char *start = str; int ch = *str; - struct row_values out = { { 1, 1, 1 } }; + struct row_values out = { { 1, 1 } }; int col = 1; if (!ch) return out; for (; ; ch = *++str, col++) { - if (str - start == oldpos) - out.rows[1] = out.rows[0]; if (str - start == pos) - out.rows[2] = out.rows[0]; + out.rows[1] = out.rows[0]; if (ch == 0) break; if (ch == '\r') @@ -711,12 +707,11 @@ static int col_offset_in_str(const char *str, size_t pos) * cursor position, and number of columns of the terminal. */ static void refresh_multiline(lino_t *l) { char seq[64]; - struct row_values r = screen_rows(l->buf, l->oldpos, l->pos, l->cols); + struct row_values r = screen_rows(l->buf, l->pos, l->cols); int rows = r.rows[0]; /* rows used by current buf. */ - int rpos = r.rows[1]; /* cursor relative row. */ - int rpos2 = r.rows[2]; /* rpos after refresh. */ + int nrow = r.rows[1]; /* cursor row after refresh. */ int col; /* colum position, zero-based. */ - int old_rows = l->maxrows; + int oldmaxrows = l->maxrows; int fd = l->ofd, j; struct abuf ab; @@ -726,13 +721,13 @@ static void refresh_multiline(lino_t *l) { /* First step: clear all the lines used before. To do so start by * going to the last row. */ ab_init(&ab); - if (old_rows-rpos > 0) { - snprintf(seq,64,"\x1b[%dB", old_rows-rpos); + if (oldmaxrows - l->oldrow > 0) { + snprintf(seq,64,"\x1b[%dB", oldmaxrows - l->oldrow); ab_append(&ab,seq,strlen(seq)); } /* Now for every row clear it, go up. */ - for (j = 0; j < old_rows-1; j++) { + for (j = 0; j < oldmaxrows - 1; j++) { snprintf(seq,64,"\r\x1b[0K\x1b[1A"); ab_append(&ab,seq,strlen(seq)); } @@ -759,8 +754,8 @@ static void refresh_multiline(lino_t *l) { } /* Go up till we reach the expected positon. */ - if (rows-rpos2 > 0) { - snprintf(seq,64,"\x1b[%dA", rows-rpos2); + if (rows - nrow > 0) { + snprintf(seq,64,"\x1b[%dA", rows - nrow); ab_append(&ab,seq,strlen(seq)); } @@ -771,7 +766,8 @@ static void refresh_multiline(lino_t *l) { snprintf(seq,64,"\r"); ab_append(&ab,seq,strlen(seq)); - l->oldpos = l->pos; + /* Remember current cursor row for next time */ + l->oldrow = nrow; if (write(fd,ab.b,ab.len) == -1) {} /* Can't recover from write error. */ ab_free(&ab); @@ -1022,10 +1018,10 @@ static int edit(lino_t *l, const char *prompt) * specific editing functionalities. */ l->prompt = prompt; l->plen = strlen(prompt); - l->oldpos = l->pos = l->len = 0; + l->pos = l->len = 0; l->dpos = l->dlen = 0; l->cols = get_columns(l->ifd, l->ofd); - l->maxrows = 0; + l->oldrow = l->maxrows = 0; l->history_index = 0; /* Buffer starts empty. */ |