tled: map cursor position to terminal column number with led_pos() - 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 9eea97a38d9862f405e00ab6a5b830a19a0df101
(DIR) parent 7feca5e3a5de42c3ee1d3a0a0b13dc27c93280ed
(HTM) Author: Ali Gholami Rudi <ali@rudi.ir>
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(-)
---
(DIR) 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 *post)
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);
}
(DIR) 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, int closed)
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);
(DIR) 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
(DIR) 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 dir)
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 *l2, int closed)
{
- if (*r2 < *r1 || (*r2 == *r1 && ren_cmp(lbuf_get(xb, *r1), *c1, *c2) > 0)) {
+ 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);
(DIR) 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, int flg);
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);