tvi: find cursor position after insertion in vi_input() - neatvi - [fork] simple vi-type editor with UTF-8 support
(HTM) git clone git://src.adamsgaard.dk/neatvi
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
---
(DIR) commit 674db133b8d6995f54c4cb682d7193dbda7ca62a
(DIR) parent 7344f210fcb3b51fa46f90f0ace3bbe126cb47b8
(HTM) Author: Ali Gholami Rudi <ali@rudi.ir>
Date: Tue, 12 May 2015 22:45:59 +0430
vi: find cursor position after insertion in vi_input()
Diffstat:
M led.c | 36 +++++++++++--------------------
M ren.c | 9 ---------
M uc.c | 14 --------------
M vi.c | 51 ++++++++++++++++++++++++++++---
M vi.h | 4 +---
5 files changed, 60 insertions(+), 54 deletions(-)
---
(DIR) diff --git a/led.c b/led.c
t@@ -90,30 +90,26 @@ static int led_lastword(char *s)
return r - s;
}
-/* the position of the cursor for inserting another character */
-static int led_insertionpos(struct sbuf *sb)
-{
- int len = sbuf_len(sb);
- char *chr = keymap(led_kmap, 'a');
- int col;
- sbuf_str(sb, chr);
- col = ren_cursor(sbuf_buf(sb),
- ren_pos(sbuf_buf(sb), uc_slen(sbuf_buf(sb)) - 1));
- sbuf_cut(sb, len);
- return col;
-}
-
static void led_printparts(char *pref, char *main, char *post)
{
struct sbuf *ln;
- int col;
+ int off, pos;
ln = sbuf_make();
sbuf_str(ln, pref);
sbuf_str(ln, main);
- col = led_insertionpos(ln);
+ off = uc_slen(sbuf_buf(ln));
sbuf_str(ln, post);
+ /* cursor position for inserting the next character */
+ if (post[0]) {
+ pos = ren_cursor(sbuf_buf(ln), ren_pos(sbuf_buf(ln), off));
+ } else {
+ int len = sbuf_len(ln);
+ sbuf_str(ln, keymap(led_kmap, 'a'));
+ pos = ren_pos(sbuf_buf(ln), off);
+ sbuf_cut(ln, len);
+ }
led_print(sbuf_buf(ln), -1);
- term_pos(-1, led_pos(sbuf_buf(ln), col));
+ term_pos(-1, led_pos(sbuf_buf(ln), ren_cursor(sbuf_buf(ln), pos)));
sbuf_free(ln);
}
t@@ -177,19 +173,15 @@ char *led_prompt(char *pref, char *post)
}
/* read visual command input */
-char *led_input(char *pref, char *post, int *row, int *col)
+char *led_input(char *pref, char *post)
{
struct sbuf *sb = sbuf_make();
int key;
- *row = 0;
while (1) {
char *ln = led_line(pref, post, &key, &led_kmap);
- if (pref)
- sbuf_str(sb, pref);
sbuf_str(sb, ln);
if (key == '\n')
sbuf_chr(sb, '\n');
- *col = ren_last(pref ? sbuf_buf(sb) : ln);
led_printparts(pref ? pref : "", ln, key == '\n' ? "" : post);
if (key == '\n')
term_chr('\n');
t@@ -198,9 +190,7 @@ char *led_input(char *pref, char *post, int *row, int *col)
free(ln);
if (key != '\n')
break;
- (*row)++;
}
- sbuf_str(sb, post);
if (key == TERMESC)
return sbuf_done(sb);
sbuf_free(sb);
(DIR) diff --git a/ren.c b/ren.c
t@@ -55,15 +55,6 @@ char *ren_translate(char *s)
return sbuf_done(sb);
}
-int ren_last(char *s)
-{
- int n = uc_slen(s);
- int *pos = ren_position(s);
- int ret = n ? pos[n - 1] : 0;
- free(pos);
- return ret;
-}
-
/* find the next character after visual position p; if cur start from p itself */
static int pos_next(int *pos, int n, int p, int cur)
{
(DIR) diff --git a/uc.c b/uc.c
t@@ -285,20 +285,6 @@ static int uc_comb(int c)
c == 0x0670; /* superscript alef */
}
-/* the direction of the given utf-8 character */
-int uc_dir(char *s)
-{
- int u, c = (unsigned char) s[0];
- if (c < 128 && (ispunct(c) || isspace(c)))
- return 0;
- if (c < 128 && isalnum(c))
- return 1;
- u = uc_code(s);
- if (UC_R2L(u))
- return -1;
- return 1;
-}
-
static void uc_cput(char *d, int c)
{
int l = 0;
(DIR) diff --git a/vi.c b/vi.c
t@@ -398,7 +398,12 @@ static int vi_insertionoffset(char *s, int c1, int before)
return l2 < l1 ? l1 + 1 : l1;
}
ren_region(s, c1, c2, &l1, &l2, 0);
- return l1 < l2 ? l2 : l1;
+ c1 = ren_pos(s, l1);
+ c2 = ren_pos(s, l2);
+ if (c1 < c2)
+ return l1 < l2 ? l2 : l1;
+ else
+ return l1 < l2 ? l1 : l2;
}
static void vi_commandregion(int *r1, int *r2, int *c1, int *c2, int *l1, int *l2, int closed)
t@@ -454,6 +459,42 @@ static void vi_delete(int r1, int c1, int r2, int c2, int lnmode, int closed)
free(post);
}
+static int lastline(char *str)
+{
+ char *s = str;
+ char *r = s;
+ while (s && s[0]) {
+ r = s;
+ s = strchr(s == str ? s : s + 1, '\n');
+ }
+ return r - str;
+}
+
+static int linecount(char *s)
+{
+ int n;
+ for (n = 0; s; n++)
+ if ((s = strchr(s, '\n')))
+ s++;
+ return n;
+}
+
+static char *vi_input(char *pref, char *post, int *row, int *col)
+{
+ char *rep = led_input(pref, post);
+ struct sbuf *sb = sbuf_make();
+ int last, off;
+ sbuf_str(sb, pref);
+ sbuf_str(sb, rep);
+ last = lastline(sbuf_buf(sb));
+ off = uc_slen(sbuf_buf(sb) + last);
+ sbuf_str(sb, post);
+ *row = linecount(sbuf_buf(sb)) - 1;
+ *col = ren_pos(sbuf_buf(sb) + last, MAX(0, off - 1));
+ free(rep);
+ return sbuf_done(sb);
+}
+
static void vi_change(int r1, int c1, int r2, int c2, int lnmode, int closed)
{
char *region;
t@@ -467,11 +508,11 @@ static void vi_change(int r1, int c1, int r2, int c2, int lnmode, int closed)
free(region);
pref = lnmode ? uc_dup("") : uc_sub(lbuf_get(xb, r1), 0, l1);
post = lnmode ? uc_dup("\n") : uc_sub(lbuf_get(xb, r2), l2, -1);
- rep = led_input(pref, post, &row, &col);
+ rep = vi_input(pref, post, &row, &col);
if (rep) {
lbuf_rm(xb, r1, r2 + 1);
lbuf_put(xb, r1, rep);
- xrow = r1 + row;
+ xrow = r1 + row - 1;
xcol = col;
free(rep);
}
t@@ -529,14 +570,14 @@ static void vc_insert(int cmd)
off = ln ? vi_insertionoffset(ln, xcol, 0) : 0;
pref = ln ? uc_sub(ln, 0, off) : uc_dup("");
post = ln ? uc_sub(ln, off, -1) : uc_dup("\n");
- rep = led_input(pref, post, &row, &col);
+ rep = vi_input(pref, post, &row, &col);
if ((cmd == 'o' || cmd == 'O') && !lbuf_len(xb))
lbuf_put(xb, 0, "\n");
if (rep) {
if (cmd != 'o' && cmd != 'O')
lbuf_rm(xb, xrow, xrow + 1);
lbuf_put(xb, xrow, rep);
- xrow += row;
+ xrow += row - 1;
xcol = col;
free(rep);
}
(DIR) diff --git a/vi.h b/vi.h
t@@ -49,7 +49,6 @@ int ren_next(char *s, int p, int dir);
int ren_eol(char *s, int dir);
int ren_pos(char *s, int off);
int ren_off(char *s, int pos);
-int ren_last(char *s);
int ren_wid(char *s);
int ren_region(char *s, int c1, int c2, int *l1, int *l2, int closed);
t@@ -66,7 +65,6 @@ void reg_done(void);
/* utf-8 helper functions */
int uc_len(char *s);
-int uc_dir(char *s);
int uc_wid(char *s);
int uc_slen(char *s);
int uc_code(char *s);
t@@ -106,7 +104,7 @@ void term_commit(void);
/* line-oriented input and output */
char *led_prompt(char *pref, char *post);
-char *led_input(char *pref, char *post, int *row, int *col);
+char *led_input(char *pref, char *post);
void led_print(char *msg, int row);
char *led_keymap(int c);
int led_pos(char *s, int pos);