tled: map cursor position to terminal column number with led_pos() - neatvi - [… | |
git clone git://src.adamsgaard.dk/neatvi | |
Log | |
Files | |
Refs | |
README | |
--- | |
commit 9eea97a38d9862f405e00ab6a5b830a19a0df101 | |
parent 7feca5e3a5de42c3ee1d3a0a0b13dc27c93280ed | |
Author: Ali Gholami Rudi <[email protected]> | |
Date: Mon, 11 May 2015 18:19:30 +0430 | |
led: map cursor position to terminal column number with led_pos() | |
Diffstat: | |
M led.c | 46 +++++++++++++++++++++++++++++… | |
M ren.c | 114 +++++++----------------------… | |
M term.c | 4 ++++ | |
M vi.c | 13 +++++++------ | |
M vi.h | 6 ++++-- | |
5 files changed, 84 insertions(+), 99 deletions(-) | |
--- | |
diff --git a/led.c b/led.c | |
t@@ -14,14 +14,56 @@ static char *keymap(char **kmap, int c) | |
return kmap[c] ? kmap[c] : cs; | |
} | |
+/* map cursor horizontal position to terminal column number */ | |
+int led_pos(char *s, int pos) | |
+{ | |
+ return dir_context(s) >= 0 ? pos : xcols - pos - 1; | |
+} | |
+ | |
char *led_keymap(int c) | |
{ | |
return c >= 0 ? keymap(led_kmap, c) : NULL; | |
} | |
+static char *led_render(char *s0) | |
+{ | |
+ int n, maxcol = 0; | |
+ int *pos; /* pos[i]: the screen position of the i-th character … | |
+ int *off; /* off[i]: the character at screen position i */ | |
+ char **chrs; /* chrs[i]: the i-th character in s1 */ | |
+ char *s1; | |
+ struct sbuf *out; | |
+ int i; | |
+ s1 = ren_translate(s0 ? s0 : ""); | |
+ chrs = uc_chop(s1, &n); | |
+ pos = ren_position(s0); | |
+ off = malloc(xcols * sizeof(off[0])); | |
+ memset(off, 0xff, xcols * sizeof(off[0])); | |
+ for (i = 0; i < n; i++) { | |
+ int curpos = led_pos(s0, pos[i]); | |
+ if (curpos >= 0 && curpos < xcols) { | |
+ off[curpos] = i; | |
+ if (curpos > maxcol) | |
+ maxcol = curpos; | |
+ } | |
+ } | |
+ out = sbuf_make(); | |
+ for (i = 0; i <= maxcol; i++) { | |
+ if (off[i] >= 0 && uc_isprint(chrs[off[i]])) | |
+ sbuf_mem(out, chrs[off[i]], uc_len(chrs[off[i]])); | |
+ else | |
+ sbuf_chr(out, ' '); | |
+ } | |
+ free(pos); | |
+ free(off); | |
+ free(chrs); | |
+ free(s1); | |
+ return sbuf_done(out); | |
+} | |
+ | |
void led_print(char *s, int row) | |
{ | |
- char *r = ren_all(s, -1); | |
+ char *r = led_render(s); | |
term_pos(row, 0); | |
term_kill(); | |
term_str(r); | |
t@@ -71,7 +113,7 @@ static void led_printparts(char *pref, char *main, char *po… | |
col = led_insertionpos(ln); | |
sbuf_str(ln, post); | |
led_print(sbuf_buf(ln), -1); | |
- term_pos(-1, col); | |
+ term_pos(-1, led_pos(sbuf_buf(ln), col)); | |
sbuf_free(ln); | |
} | |
diff --git a/ren.c b/ren.c | |
t@@ -6,14 +6,13 @@ | |
#include "vi.h" | |
/* specify the screen position of the characters in s */ | |
-static int *ren_position(char *s, int *beg, int *end) | |
+int *ren_position(char *s) | |
{ | |
int i, n; | |
char **chrs = uc_chop(s, &n); | |
int *off, *pos; | |
int diff = 0; | |
- int dir = dir_context(s); | |
- pos = malloc(n * sizeof(pos[0])); | |
+ pos = malloc((n + 1) * sizeof(pos[0])); | |
for (i = 0; i < n; i++) | |
pos[i] = i; | |
dir_reorder(s, pos); | |
t@@ -25,24 +24,22 @@ static int *ren_position(char *s, int *beg, int *end) | |
if (*chrs[i] == '\t') | |
diff += 8 - (pos[off[i]] & 7); | |
} | |
- if (beg) | |
- *beg = 0; | |
- if (end) | |
- *end = n + diff; | |
- if (dir < 0) { | |
- if (beg) | |
- *beg = xcols - *end - 1; | |
- if (end) | |
- *end = xcols - 1; | |
- for (i = 0; i < n; i++) | |
- pos[i] = xcols - pos[i] - 1; | |
- } | |
+ pos[n] = n + diff; | |
free(chrs); | |
free(off); | |
return pos; | |
} | |
-static char *ren_translate(char *s) | |
+int ren_wid(char *s) | |
+{ | |
+ int *pos = ren_position(s); | |
+ int n = uc_slen(s); | |
+ int ret = pos[n]; | |
+ free(pos); | |
+ return ret; | |
+} | |
+ | |
+char *ren_translate(char *s) | |
{ | |
struct sbuf *sb = sbuf_make(); | |
char *r = s; | |
t@@ -58,43 +55,10 @@ static char *ren_translate(char *s) | |
return sbuf_done(sb); | |
} | |
-char *ren_all(char *s0, int wid) | |
-{ | |
- int n, w = 0; | |
- int *pos; /* pos[i]: the screen position of the i-th character … | |
- int *off; /* off[i]: the character at screen position i */ | |
- char **chrs; /* chrs[i]: the i-th character in s1 */ | |
- char *s1; | |
- struct sbuf *out; | |
- int i; | |
- s1 = ren_translate(s0 ? s0 : ""); | |
- chrs = uc_chop(s1, &n); | |
- pos = ren_position(s0, NULL, NULL); | |
- for (i = 0; i < n; i++) | |
- if (w <= pos[i]) | |
- w = pos[i] + 1; | |
- off = malloc(w * sizeof(off[0])); | |
- memset(off, 0xff, w * sizeof(off[0])); | |
- for (i = 0; i < n; i++) | |
- off[pos[i]] = i; | |
- out = sbuf_make(); | |
- for (i = 0; i < w; i++) { | |
- if (off[i] >= 0 && uc_isprint(chrs[off[i]])) | |
- sbuf_mem(out, chrs[off[i]], uc_len(chrs[off[i]])); | |
- else | |
- sbuf_chr(out, ' '); | |
- } | |
- free(pos); | |
- free(off); | |
- free(chrs); | |
- free(s1); | |
- return sbuf_done(out); | |
-} | |
- | |
int ren_last(char *s) | |
{ | |
int n = uc_slen(s); | |
- int *pos = ren_position(s, NULL, NULL); | |
+ int *pos = ren_position(s); | |
int ret = n ? pos[n - 1] : 0; | |
free(pos); | |
return ret; | |
t@@ -124,7 +88,7 @@ static int pos_prev(int *pos, int n, int p, int cur) | |
int ren_pos(char *s, int off) | |
{ | |
int n = uc_slen(s); | |
- int *pos = ren_position(s, NULL, NULL); | |
+ int *pos = ren_position(s); | |
int ret = off < n ? pos[off] : 0; | |
free(pos); | |
return ret; | |
t@@ -135,12 +99,9 @@ int ren_off(char *s, int p) | |
{ | |
int off = -1; | |
int n = uc_slen(s); | |
- int *pos = ren_position(s, NULL, NULL); | |
+ int *pos = ren_position(s); | |
int i; | |
- if (dir_context(s) >= 0) | |
- p = pos_prev(pos, n, p, 1); | |
- else | |
- p = pos_next(pos, n, p, 1); | |
+ p = pos_prev(pos, n, p, 1); | |
for (i = 0; i < n; i++) | |
if (pos[i] == p) | |
off = i; | |
t@@ -151,23 +112,15 @@ int ren_off(char *s, int p) | |
/* adjust cursor position */ | |
int ren_cursor(char *s, int p) | |
{ | |
- int dir = dir_context(s ? s : ""); | |
int n, next; | |
- int beg, end; | |
int *pos; | |
if (!s) | |
return 0; | |
n = uc_slen(s); | |
- pos = ren_position(s, &beg, &end); | |
- if (dir >= 0) | |
- p = pos_prev(pos, n, p, 1); | |
- else | |
- p = pos_next(pos, n, p, 1); | |
- if (dir >= 0) | |
- next = pos_next(pos, n, p, 0); | |
- else | |
- next = pos_prev(pos, n, p, 0); | |
- p = (next >= 0 ? next : (dir >= 0 ? end : beg)) - dir; | |
+ pos = ren_position(s); | |
+ p = pos_prev(pos, n, p, 1); | |
+ next = pos_next(pos, n, p, 0); | |
+ p = (next >= 0 ? next : pos[n]) - 1; | |
free(pos); | |
return p >= 0 ? p : 0; | |
} | |
t@@ -176,12 +129,9 @@ int ren_cursor(char *s, int p) | |
int ren_next(char *s, int p, int dir) | |
{ | |
int n = uc_slen(s); | |
- int *pos = ren_position(s, NULL, NULL); | |
- if (dir_context(s ? s : "") >= 0) | |
- p = pos_prev(pos, n, p, 1); | |
- else | |
- p = pos_next(pos, n, p, 1); | |
- if (dir * dir_context(s ? s : "") >= 0) | |
+ int *pos = ren_position(s); | |
+ p = pos_prev(pos, n, p, 1); | |
+ if (dir >= 0) | |
p = pos_next(pos, n, p, 0); | |
else | |
p = pos_prev(pos, n, p, 0); | |
t@@ -189,20 +139,6 @@ int ren_next(char *s, int p, int dir) | |
return p; | |
} | |
-int ren_eol(char *s, int dir) | |
-{ | |
- int beg, end; | |
- int *pos = ren_position(s, &beg, &end); | |
- free(pos); | |
- return dir * dir_context(s) >= 0 ? end : beg; | |
-} | |
- | |
-/* compare two visual positions */ | |
-int ren_cmp(char *s, int pos1, int pos2) | |
-{ | |
- return dir_context(s ? s : "") >= 0 ? pos1 - pos2 : pos2 - pos1; | |
-} | |
- | |
static void swap(int *i1, int *i2) | |
{ | |
int t = *i1; | |
t@@ -228,7 +164,7 @@ int ren_region(char *s, int c1, int c2, int *l1, int *l2, … | |
ord[i] = i; | |
dir_reorder(s, ord); | |
- if (ren_cmp(s, c1, c2) > 0) | |
+ if (c2 < c1) | |
swap(&c1, &c2); | |
if (!closed) | |
c2 = ren_next(s, c2, -1); | |
diff --git a/term.c b/term.c | |
t@@ -80,6 +80,10 @@ void term_kill(void) | |
void term_pos(int r, int c) | |
{ | |
char buf[32] = "\r"; | |
+ if (c < 0) | |
+ c = 0; | |
+ if (c >= xcols) | |
+ c = cols - 1; | |
if (r < 0) | |
sprintf(buf, "\r\33[%d%c", abs(c), c > 0 ? 'C' : 'D'); | |
else | |
diff --git a/vi.c b/vi.c | |
t@@ -27,7 +27,7 @@ static void vi_draw(void) | |
char *s = lbuf_get(xb, i); | |
led_print(s ? s : "~", i - xtop); | |
} | |
- term_pos(xrow, xcol); | |
+ term_pos(xrow, led_pos(lbuf_get(xb, i), xcol)); | |
term_commit(); | |
} | |
t@@ -77,7 +77,7 @@ static int lbuf_lnnext(struct lbuf *lb, int *r, int *c, int … | |
static void lbuf_eol(struct lbuf *lb, int *r, int *c, int dir) | |
{ | |
char *ln = lbuf_get(lb, *r); | |
- *c = ren_eol(ln ? ln : "", dir); | |
+ *c = dir < 0 ? 0 : MAX(0, ren_wid(ln ? ln : "") - 1); | |
} | |
static int lbuf_next(struct lbuf *lb, int *r, int *c, int dir) | |
t@@ -394,7 +394,7 @@ static int vi_insertionoffset(char *s, int c1, int before) | |
static void vi_commandregion(int *r1, int *r2, int *c1, int *c2, int *l1, int … | |
{ | |
- if (*r2 < *r1 || (*r2 == *r1 && ren_cmp(lbuf_get(xb, *r1), *c1, *c2) >… | |
+ if (*r2 < *r1 || (*r2 == *r1 && *c2 < *c1)) { | |
swap(r1, r2); | |
swap(c1, c2); | |
} | |
t@@ -618,7 +618,7 @@ static void vi(void) | |
xrow = 0; | |
lbuf_eol(xb, &xrow, &xcol, -1); | |
vi_draw(); | |
- term_pos(xrow, xcol); | |
+ term_pos(xrow, led_pos(lbuf_get(xb, xrow), xcol)); | |
while (!xquit) { | |
int redraw = 0; | |
int orow = xrow; | |
t@@ -660,7 +660,7 @@ static void vi(void) | |
redraw = 1; | |
break; | |
case ':': | |
- term_pos(xrows, 0); | |
+ term_pos(xrows, led_pos(":", 0)); | |
term_kill(); | |
ex_command(NULL); | |
if (xquit) | |
t@@ -763,7 +763,8 @@ static void vi(void) | |
} | |
if (redraw) | |
vi_draw(); | |
- term_pos(xrow - xtop, ren_cursor(lbuf_get(xb, xrow), xcol)); | |
+ term_pos(xrow - xtop, led_pos(lbuf_get(xb, xrow), | |
+ ren_cursor(lbuf_get(xb, xrow), xcol))); | |
lbuf_undomark(xb); | |
} | |
term_pos(xrows, 0); | |
diff --git a/vi.h b/vi.h | |
t@@ -42,14 +42,15 @@ int reset_find(struct reset *re, char *s, int n, int *grps… | |
void reset_free(struct reset *re); | |
/* rendering lines */ | |
-char *ren_all(char *s, int wid); | |
+int *ren_position(char *s); | |
+char *ren_translate(char *s); | |
int ren_cursor(char *s, int pos); | |
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_cmp(char *s, int pos1, int pos2); | |
+int ren_wid(char *s); | |
int ren_region(char *s, int c1, int c2, int *l1, int *l2, int closed); | |
/* text direction */ | |
t@@ -108,6 +109,7 @@ char *led_prompt(char *pref, char *post); | |
char *led_input(char *pref, char *post, int *row, int *col); | |
void led_print(char *msg, int row); | |
char *led_keymap(int c); | |
+int led_pos(char *s, int pos); | |
/* ex commands */ | |
void ex(void); |