| t@@ -336,8 +336,7 @@ static int ec_edit(char *ec)
bufs_switch(bufs_open(path));
fd = open(ex_path(), O_RDONLY);
if (fd >= 0) {
- lbuf_rm(xb, 0, lbuf_len(xb));
- lbuf_rd(xb, fd, 0);
+ lbuf_rd(xb, fd, 0, lbuf_len(xb));
close(fd);
snprintf(msg, sizeof(msg), "\"%s\" %d lines [r]\n",
ex_path(), lbuf_len(xb));
t@@ -362,19 +361,21 @@ static int ec_read(char *ec)
if (ex_region(loc, &beg, &end))
return 1;
if (arg[0] == '!') {
+ int pos = MIN(xrow + 1, lbuf_len(xb));
if (ex_expand(arg, ex_argeol(ec)))
return 1;
obuf = cmd_pipe(arg + 1, NULL, 0, 1);
if (obuf)
- lbuf_put(xb, MIN(xrow + 1, lbuf_len(xb)), obuf);
+ lbuf_edit(xb, obuf, pos, pos);
free(obuf);
} else {
int fd = open(path, O_RDONLY);
+ int pos = lbuf_len(xb) ? end : 0;
if (fd < 0) {
ex_show("read failed\n");
return 1;
}
- lbuf_rd(xb, fd, lbuf_len(xb) ? end : 0);
+ lbuf_rd(xb, fd, pos, pos);
close(fd);
}
xrow = end + lbuf_len(xb) - n - 1;
t@@ -445,11 +446,6 @@ static int ec_insert(char *ec)
ex_loc(ec, loc);
if (ex_region(loc, &beg, &end) && (beg != 0 || end != 0))
return 1;
- if (cmd[0] == 'c') {
- if (lbuf_len(xb))
- lbuf_rm(xb, beg, end);
- end = beg + 1;
- }
sb = sbuf_make();
while ((s = ex_read(""))) {
if (!strcmp(".", s)) {
t@@ -461,10 +457,12 @@ static int ec_insert(char *ec)
free(s);
}
if (cmd[0] == 'a')
- if (end > lbuf_len(xb))
- end = lbuf_len(xb);
+ if (beg + 1 <= lbuf_len(xb))
+ beg++;
+ if (cmd[0] != 'c')
+ end = beg;
n = lbuf_len(xb);
- lbuf_put(xb, end, sbuf_buf(sb));
+ lbuf_edit(xb, sbuf_buf(sb), beg, end);
xrow = MIN(lbuf_len(xb) - 1, end + lbuf_len(xb) - n - 1);
sbuf_free(sb);
return 0;
t@@ -522,7 +520,7 @@ static int ec_delete(char *ec)
if (ex_region(loc, &beg, &end) || !lbuf_len(xb))
return 1;
ex_yank(arg[0], beg, end);
- lbuf_rm(xb, beg, end);
+ lbuf_edit(xb, NULL, beg, end);
xrow = beg;
return 0;
}
t@@ -553,7 +551,7 @@ static int ec_put(char *ec)
buf = reg_get(arg[0], &lnmode);
if (!buf || ex_region(loc, &beg, &end))
return 1;
- lbuf_put(xb, end, buf);
+ lbuf_edit(xb, buf, end, end);
xrow = MIN(lbuf_len(xb) - 1, end + lbuf_len(xb) - n - 1);
return 0;
}
t@@ -647,8 +645,7 @@ static int ec_substitute(char *ec)
break;
}
sbuf_str(r, ln);
- lbuf_rm(xb, i, i + 1);
- lbuf_put(xb, i, sbuf_buf(r));
+ lbuf_edit(xb, sbuf_buf(r), i, i + 1);
sbuf_free(r);
}
rset_free(re); |
| t@@ -1,3 +1,4 @@
+#include
#include
#include
#include
t@@ -8,9 +9,9 @@
/* line operations */
struct lopt {
- char *buf; /* text inserted or deleted */
- int ins; /* insertion operation if non-zero */
- int beg, end;
+ char *ins; /* inserted text */
+ char *del; /* deleted text */
+ int pos, n_ins, n_del; /* modification location */
int seq; /* operation number */
int *mark, *mark_off; /* saved marks */
};
t@@ -27,7 +28,6 @@ struct lbuf {
int hist_sz; /* size of hist[] */
int hist_n; /* current history head in hist[] */
int hist_u; /* current undo head in hist[] */
- int mod_new; /* clear modification marks */
int useq_zero; /* useq for lbuf_saved() */
int useq_last; /* useq before hist[] */
};
t@@ -45,11 +45,33 @@ struct lbuf *lbuf_make(void)
static void lopt_done(struct lopt *lo)
{
- free(lo->buf);
+ free(lo->ins);
+ free(lo->del);
free(lo->mark);
free(lo->mark_off);
}
+static void lbuf_savemark(struct lbuf *lb, struct lopt *lo, int m)
+{
+ if (lb->mark[m] >= 0) {
+ if (!lo->mark) {
+ lo->mark = malloc(sizeof(lb->mark));
+ lo->mark_off = malloc(sizeof(lb->mark_off));
+ memset(lo->mark, 0xff, sizeof(lb->mark));
+ }
+ lo->mark[m] = lb->mark[m];
+ lo->mark_off[m] = lb->mark_off[m];
+ }
+}
+
+static void lbuf_loadmark(struct lbuf *lb, struct lopt *lo, int m)
+{
+ if (lo->mark && lo->mark[m] >= 0) {
+ lb->mark[m] = lo->mark[m];
+ lb->mark_off[m] = lo->mark_off[m];
+ }
+}
+
void lbuf_free(struct lbuf *lb)
{
int i;
t@@ -79,51 +101,46 @@ static void lbuf_insertline(struct lbuf *lb, int pos, char *s)
lb->ln[pos] = s;
}
-/* low-level insertion */
-static void lbuf_insert(struct lbuf *lb, int pos, char *s)
+/* low-level replacement */
+static void lbuf_replace(struct lbuf *lb, char *s, int pos, int n_del)
{
- int lb_len = lbuf_len(lb);
- int beg = pos, end;
char *r;
+ int n_ins = 0;
int i;
- while ((r = strchr(s, '\n'))) {
+ for (i = 0; i < n_del; i++)
+ free(lb->ln[pos + i]);
+ memmove(lb->ln + pos, lb->ln + pos + n_del,
+ (lb->ln_n - pos - n_del) * sizeof(lb->ln[0]));
+ lb->ln_n -= n_del;
+ while (s && (r = strchr(s, '\n'))) {
char *n = malloc(r - s + 2);
memcpy(n, s, r - s + 1);
n[r - s + 1] = '\0';
- lbuf_insertline(lb, pos++, n);
+ lbuf_insertline(lb, pos + n_ins++, n);
s = r + 1;
}
- for (i = 0; i < LEN(lb->mark); i++) /* updating marks */
- if (lb->mark[i] >= pos)
- lb->mark[i] += lbuf_len(lb) - lb_len;
- end = beg + lbuf_len(lb) - lb_len;
- if (lb->mod_new || lb->mark['['] < 0 || lb->mark['['] > beg)
- lbuf_mark(lb, '[', beg, 0);
- if (lb->mod_new || lb->mark[']'] < 0 || lb->mark[']'] < end - 1)
- lbuf_mark(lb, ']', end - 1, 0);
- lb->mod_new = 0;
+ for (i = 0; i < LEN(lb->mark); i++) { /* updating marks */
+ if (!s && lb->mark[i] >= pos && lb->mark[i] < pos + n_del)
+ lb->mark[i] = -1;
+ else if (lb->mark[i] >= pos + n_del)
+ lb->mark[i] += n_ins - n_del;
+ else if (lb->mark[i] >= pos + n_ins)
+ lb->mark[i] = pos + n_ins - 1;
+ }
+ lbuf_mark(lb, '[', pos, 0);
+ lbuf_mark(lb, ']', pos + n_ins - n_del, 0);
}
-/* low-level deletion */
-static void lbuf_delete(struct lbuf *lb, int beg, int end)
+static int uc_newlines(char *s)
{
- int i;
- for (i = beg; i < end; i++)
- free(lb->ln[i]);
- memmove(lb->ln + beg, lb->ln + end, (lb->ln_n - end) * sizeof(lb->ln[0]));
- lb->ln_n -= end - beg;
- for (i = 0; i < LEN(lb->mark); i++) /* updating marks */
- if (lb->mark[i] > beg)
- lb->mark[i] = MAX(beg, lb->mark[i] + beg - end);
- if (lb->mod_new || lb->mark['['] < 0 || lb->mark['['] > beg)
- lbuf_mark(lb, '[', beg, 0);
- if (lb->mod_new || lb->mark[']'] < 0 || lb->mark[']'] < beg)
- lbuf_mark(lb, ']', beg, 0);
- lb->mod_new = 0;
+ int n;
+ for (n = 0; (s = strchr(s, '\n')); n++)
+ s++;
+ return n;
}
/* append undo/redo history */
-static void lbuf_opt(struct lbuf *lb, int ins, int beg, int end)
+static void lbuf_opt(struct lbuf *lb, char *buf, int pos, int n_del)
{
struct lopt *lo;
int i;
t@@ -142,14 +159,19 @@ static void lbuf_opt(struct lbuf *lb, int ins, int beg, int end)
lb->hist_n++;
lb->hist_u = lb->hist_n;
memset(lo, 0, sizeof(*lo));
- lo->ins = ins;
- lo->beg = beg;
- lo->end = end;
- lo->buf = lbuf_cp(lb, beg, end);
+ lo->pos = pos;
+ lo->n_del = n_del;
+ lo->del = n_del ? lbuf_cp(lb, pos, pos + n_del) : NULL;
+ lo->n_ins = buf ? uc_newlines(buf) : 0;
+ lo->ins = buf ? uc_dup(buf) : NULL;
lo->seq = lb->useq;
+ for (i = 0; i < LEN(lb->mark); i++)
+ if (lb->mark[i] >= pos && lb->mark[i] < pos + n_del)
+ if (isalpha(i))
+ lbuf_savemark(lb, lo, i);
}
-void lbuf_rd(struct lbuf *lbuf, int fd, int pos)
+void lbuf_rd(struct lbuf *lbuf, int fd, int beg, int end)
{
char buf[1 << 10];
struct sbuf *sb;
t@@ -157,7 +179,7 @@ void lbuf_rd(struct lbuf *lbuf, int fd, int pos)
sb = sbuf_make();
while ((nr = read(fd, buf, sizeof(buf))) > 0)
sbuf_mem(sb, buf, nr);
- lbuf_put(lbuf, pos, sbuf_buf(sb));
+ lbuf_edit(lbuf, sbuf_buf(sb), beg, end);
sbuf_free(sb);
}
t@@ -168,23 +190,17 @@ void lbuf_wr(struct lbuf *lbuf, int fd, int beg, int end)
write(fd, lbuf->ln[i], strlen(lbuf->ln[i]));
}
-void lbuf_rm(struct lbuf *lb, int beg, int end)
+/* replace lines beg through end with buf */
+void lbuf_edit(struct lbuf *lb, char *buf, int beg, int end)
{
+ if (beg > lb->ln_n)
+ beg = lb->ln_n;
if (end > lb->ln_n)
end = lb->ln_n;
- if (beg == end)
- return;
- lbuf_opt(lb, 0, beg, end);
- lbuf_delete(lb, beg, end);
-}
-
-void lbuf_put(struct lbuf *lb, int pos, char *s)
-{
- int lb_len = lbuf_len(lb);
- if (!*s)
+ if (beg == end && !buf)
return;
- lbuf_insert(lb, pos, s);
- lbuf_opt(lb, 1, pos, pos + lbuf_len(lb) - lb_len);
+ lbuf_opt(lb, buf, beg, end - beg);
+ lbuf_replace(lb, buf, beg, end - beg);
}
char *lbuf_cp(struct lbuf *lb, int beg, int end)
t@@ -226,42 +242,18 @@ int lbuf_jump(struct lbuf *lbuf, int mark, int *pos, int *off)
return 0;
}
-static void lbuf_savemarks(struct lbuf *lb, struct lopt *lo)
-{
- int i;
- lo->mark = malloc(sizeof(lb->mark));
- lo->mark_off = malloc(sizeof(lb->mark_off));
- for (i = 0; i < LEN(lb->mark); i++)
- lo->mark[i] = -1;
- lo->mark['*'] = lb->mark['*'];
- lo->mark_off['*'] = lb->mark_off['*'];
-}
-
-static void lbuf_loadmarks(struct lbuf *lb, struct lopt *lo)
-{
- int i;
- for (i = 0; lo->mark && i < LEN(lb->mark); i++) {
- if (lo->mark[i] >= 0) {
- lb->mark[i] = lo->mark[i];
- lb->mark_off[i] = lo->mark_off[i];
- }
- }
-}
-
int lbuf_undo(struct lbuf *lb)
{
- int useq;
+ int useq, i;
if (!lb->hist_u)
return 1;
useq = lb->hist[lb->hist_u - 1].seq;
- lb->mod_new = 1;
while (lb->hist_u && lb->hist[lb->hist_u - 1].seq == useq) {
struct lopt *lo = &lb->hist[--(lb->hist_u)];
- if (lo->ins)
- lbuf_delete(lb, lo->beg, lo->end);
- else
- lbuf_insert(lb, lo->beg, lo->buf);
- lbuf_loadmarks(lb, lo);
+ lbuf_replace(lb, lo->del, lo->pos, lo->n_ins);
+ lbuf_loadmark(lb, lo, '*');
+ for (i = 0; i < LEN(lb->mark); i++)
+ lbuf_loadmark(lb, lo, i);
}
return 0;
}
t@@ -272,14 +264,10 @@ int lbuf_redo(struct lbuf *lb)
if (lb->hist_u == lb->hist_n)
return 1;
useq = lb->hist[lb->hist_u].seq;
- lb->mod_new = 1;
while (lb->hist_u < lb->hist_n && lb->hist[lb->hist_u].seq == useq) {
struct lopt *lo = &lb->hist[lb->hist_u++];
- if (lo->ins)
- lbuf_insert(lb, lo->beg, lo->buf);
- else
- lbuf_delete(lb, lo->beg, lo->end);
- lbuf_loadmarks(lb, lo);
+ lbuf_replace(lb, lo->ins, lo->pos, lo->n_del);
+ lbuf_loadmark(lb, lo, '*');
}
return 0;
}
t@@ -309,8 +297,7 @@ int lbuf_modified(struct lbuf *lb)
{
struct lopt *lo = lb->hist_n ? &lb->hist[lb->hist_n - 1] : NULL;
if (lb->hist_u == lb->hist_n && lo && !lo->mark)
- lbuf_savemarks(lb, lo);
- lb->mod_new = 1;
+ lbuf_savemark(lb, lo, '*');
lb->useq++;
return lbuf_seq(lb) != lb->useq_zero;
} |
| t@@ -572,13 +572,14 @@ static void vi_delete(int r1, int o1, int r2, int o2, int lnmode)
free(region);
pref = lnmode ? uc_dup("") : uc_sub(lbuf_get(xb, r1), 0, o1);
post = lnmode ? uc_dup("\n") : uc_sub(lbuf_get(xb, r2), o2, -1);
- lbuf_rm(xb, r1, r2 + 1);
if (!lnmode) {
struct sbuf *sb = sbuf_make();
sbuf_str(sb, pref);
sbuf_str(sb, post);
- lbuf_put(xb, r1, sbuf_buf(sb));
+ lbuf_edit(xb, sbuf_buf(sb), r1, r2 + 1);
sbuf_free(sb);
+ } else {
+ lbuf_edit(xb, NULL, r1, r2 + 1);
}
xrow = r1;
xoff = lnmode ? lbuf_indents(xb, xrow) : o1;
t@@ -653,8 +654,7 @@ static void vi_change(int r1, int o1, int r2, int o2, int lnmode)
vi_drawrm(r1, r2, 0);
rep = vi_input(pref, post, &row, &off);
if (rep) {
- lbuf_rm(xb, r1, r2 + 1);
- lbuf_put(xb, r1, rep);
+ lbuf_edit(xb, rep, r1, r2 + 1);
xrow = r1 + row - 1;
xoff = off;
free(rep);
t@@ -683,16 +683,15 @@ static void vi_case(int r1, int o1, int r2, int o2, int lnmode, int cmd)
}
pref = lnmode ? uc_dup("") : uc_sub(lbuf_get(xb, r1), 0, o1);
post = lnmode ? uc_dup("\n") : uc_sub(lbuf_get(xb, r2), o2, -1);
- lbuf_rm(xb, r1, r2 + 1);
if (!lnmode) {
struct sbuf *sb = sbuf_make();
sbuf_str(sb, pref);
sbuf_str(sb, region);
sbuf_str(sb, post);
- lbuf_put(xb, r1, sbuf_buf(sb));
+ lbuf_edit(xb, sbuf_buf(sb), r1, r2 + 1);
sbuf_free(sb);
} else {
- lbuf_put(xb, r1, region);
+ lbuf_edit(xb, region, r1, r2 + 1);
}
xrow = r2;
xoff = lnmode ? lbuf_indents(xb, r2) : o2;
t@@ -711,10 +710,8 @@ static void vi_pipe(int r1, int r2)
return;
text = lbuf_cp(xb, r1, r2 + 1);
rep = cmd_pipe(cmd, text, 1, 1);
- if (rep) {
- lbuf_rm(xb, r1, r2 + 1);
- lbuf_put(xb, r1, rep);
- }
+ if (rep)
+ lbuf_edit(xb, rep, r1, r2 + 1);
free(cmd);
free(text);
free(rep);
t@@ -734,8 +731,7 @@ static void vi_shift(int r1, int r2, int dir)
else
ln = ln[0] == ' ' || ln[0] == '\t' ? ln + 1 : ln;
sbuf_str(sb, ln);
- lbuf_rm(xb, i, i + 1);
- lbuf_put(xb, i, sbuf_buf(sb));
+ lbuf_edit(xb, sbuf_buf(sb), i, i + 1);
sbuf_free(sb);
}
xrow = r1;
t@@ -813,11 +809,9 @@ static int vc_insert(int cmd)
vi_drawrm(xrow, xrow, cmd == 'o' || cmd == 'O');
rep = vi_input(pref, post, &row, &off);
if ((cmd == 'o' || cmd == 'O') && !lbuf_len(xb))
- lbuf_put(xb, 0, "\n");
+ lbuf_edit(xb, "\n", 0, 0);
if (rep) {
- if (cmd != 'o' && cmd != 'O')
- lbuf_rm(xb, xrow, xrow + 1);
- lbuf_put(xb, xrow, rep);
+ lbuf_edit(xb, rep, xrow, xrow + (cmd != 'o' && cmd != 'O'));
xrow += row - 1;
xoff = off;
free(rep);
t@@ -842,10 +836,10 @@ static int vc_put(int cmd)
for (i = 0; i < cnt; i++)
sbuf_str(sb, buf);
if (!lbuf_len(xb))
- lbuf_put(xb, 0, "\n");
+ lbuf_edit(xb, "\n", 0, 0);
if (cmd == 'p')
xrow++;
- lbuf_put(xb, xrow, sbuf_buf(sb));
+ lbuf_edit(xb, sbuf_buf(sb), xrow, xrow);
xoff = lbuf_indents(xb, xrow);
sbuf_free(sb);
} else {
t@@ -860,8 +854,7 @@ static int vc_put(int cmd)
s = uc_sub(ln, off, -1);
sbuf_str(sb, s);
free(s);
- lbuf_rm(xb, xrow, xrow + 1);
- lbuf_put(xb, xrow, sbuf_buf(sb));
+ lbuf_edit(xb, sbuf_buf(sb), xrow, xrow + 1);
xoff = off + uc_slen(buf) * cnt - 1;
sbuf_free(sb);
}
t@@ -903,8 +896,7 @@ static int vc_join(void)
sbuf_mem(sb, ln, lnend - ln);
}
sbuf_chr(sb, '\n');
- lbuf_rm(xb, beg, end);
- lbuf_put(xb, beg, sbuf_buf(sb));
+ lbuf_edit(xb, sbuf_buf(sb), beg, end);
xoff = off;
sbuf_free(sb);
return 0;
t@@ -963,8 +955,7 @@ static int vc_replace(void)
for (i = 0; i < cnt; i++)
sbuf_str(sb, cs);
sbuf_str(sb, post);
- lbuf_rm(xb, xrow, xrow + 1);
- lbuf_put(xb, xrow, sbuf_buf(sb));
+ lbuf_edit(xb, sbuf_buf(sb), xrow, xrow + 1);
off += cnt - 1;
xoff = off;
sbuf_free(sb); |