summaryrefslogtreecommitdiffstats
path: root/linenoise
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2015-09-16 07:19:19 -0700
committerKaz Kylheku <kaz@kylheku.com>2015-09-16 07:19:19 -0700
commit15346886504761400e6db3930b74cc59adfce6f9 (patch)
tree3b73f8976f7c330b70b820a53add3f0a129d83aa /linenoise
parentfbc56f3575640f4acbdb6dbee78a299132fe55b8 (diff)
downloadtxr-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.c38
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. */