neatvi

[fork] simple vi-type editor with UTF-8 support
git clone git://src.adamsgaard.dk/neatvi # fast
git clone https://src.adamsgaard.dk/neatvi.git # slow
Log | Files | Refs | README Back to index

commit 0c2fb9f33f08de99cfc4e5b61e14259bbbe2c468
parent a183ae6d1a2a745051c1f2a45f1b4de5fcaa4d5d
Author: Ali Gholami Rudi <ali@rudi.ir>
Date:   Sun, 17 May 2015 10:10:27 +0430

ren: return placeholder characters from ren_translate()

Placeholders are useful especially for zerowidth characters.

Diffstat:
Mdir.c | 2+-
Mled.c | 45+++++++++++++++++++++++++++++----------------
Mren.c | 64+++++++++++++++++++++++++++++++++++++++++++---------------------
Muc.c | 6++----
Mvi.h | 3++-
5 files changed, 77 insertions(+), 43 deletions(-)

diff --git a/dir.c b/dir.c @@ -3,7 +3,7 @@ #include <string.h> #include "vi.h" -#define CR2L "ءآأؤإئابةتثجحخدذرزسشصضطظعغـفقكلمنهوىييپچژکگی‌‍؛،»«؟" +#define CR2L "ءآأؤإئابةتثجحخدذرزسشصضطظعغـفقكلمنهوىييپچژکگی‌‍؛،»«؟ًٌٍَُِّْ" #define CNEUT "-!\"#$%&'()*+,./:;<=>?@^_`{|}~ " /* direction context patterns */ diff --git a/led.c b/led.c @@ -31,33 +31,45 @@ static char *led_render(char *s0) 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); + int i, j; + chrs = uc_chop(s0, &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; + int curpos = pos[i]; + int curwid = ren_cwid(chrs[i], curpos); + if (curpos >= 0 && curpos + curwid < xcols) { + for (j = 0; j < curwid; j++) { + off[led_pos(s0, curpos + j)] = i; + if (led_pos(s0, curpos + j) > maxcol) + maxcol = led_pos(s0, curpos + j); + } } } 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 + i = 0; + while (i <= maxcol) { + int o = off[i]; + if (o >= 0) { + if (ren_translate(chrs[o], s0)) + sbuf_str(out, ren_translate(chrs[o], s0)); + else if (uc_isprint(chrs[o])) + sbuf_mem(out, chrs[o], uc_len(chrs[o])); + else + for (j = i; j <= maxcol && off[j] == o; j++) + sbuf_chr(out, ' '); + while (i <= maxcol && off[i] == o) + i++; + } else { sbuf_chr(out, ' '); + i++; + } } free(pos); free(off); free(chrs); - free(s1); return sbuf_done(out); } @@ -99,15 +111,16 @@ static void led_printparts(char *ai, char *pref, char *main, char *post) sbuf_str(ln, pref); sbuf_str(ln, main); off = uc_slen(sbuf_buf(ln)); - sbuf_str(ln, post); /* cursor position for inserting the next character */ - if (post[0]) { + if (post[0] && post[0] != '\n') { + sbuf_str(ln, post); 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_cursor(sbuf_buf(ln), ren_pos(sbuf_buf(ln), off)); sbuf_cut(ln, len); + sbuf_str(ln, post); } led_print(sbuf_buf(ln), -1); term_pos(-1, led_pos(sbuf_buf(ln), pos)); diff --git a/ren.c b/ren.c @@ -11,7 +11,7 @@ int *ren_position(char *s) int i, n; char **chrs = uc_chop(s, &n); int *off, *pos; - int diff = 0; + int cpos = 0; pos = malloc((n + 1) * sizeof(pos[0])); for (i = 0; i < n; i++) pos[i] = i; @@ -20,11 +20,10 @@ int *ren_position(char *s) for (i = 0; i < n; i++) off[pos[i]] = i; for (i = 0; i < n; i++) { - pos[off[i]] += diff; - if (*chrs[i] == '\t') - diff += 8 - (pos[off[i]] & 7) - 1; + pos[off[i]] = cpos; + cpos += ren_cwid(chrs[off[i]], cpos); } - pos[n] = n + diff; + pos[n] = cpos; free(chrs); free(off); return pos; @@ -39,22 +38,6 @@ int ren_wid(char *s) return ret; } -char *ren_translate(char *s) -{ - struct sbuf *sb = sbuf_make(); - char *r = s; - while (*r) { - char *c = uc_shape(s, r); - if (!strcmp(c, "‌")) - c = "-"; - if (!strcmp(c, "‍")) - c = "-"; - sbuf_str(sb, c); - r = uc_next(r); - } - return sbuf_done(sb); -} - /* 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) { @@ -175,3 +158,42 @@ int ren_region(char *s, int c1, int c2, int *l1, int *l2, int closed) free(ord); return 0; } + +static struct placeholder { + char *s; /* the source character */ + char *d; /* the placeholder */ +} placeholders[] = { + {"‌", "-"}, + {"‍", "-"}, + {"ْ", "ـْ"}, + {"ٌ", "ـٌ"}, + {"ٍ", "ـٍ"}, + {"ً", "ـً"}, + {"ُ", "ـُ"}, + {"ِ", "ـِ"}, + {"َ", "ـَ"}, + {"ّ", "ـّ"}, +}; + +static char *ren_placeholder(char *s) +{ + int i = 0; + int c = uc_code(s); + for (i = 0; i < LEN(placeholders); i++) + if (uc_code(placeholders[i].s) == c) + return placeholders[i].d; + return NULL; +} + +int ren_cwid(char *s, int pos) +{ + if (s[0] == '\t') + return 8 - (pos & 7); + return 1; +} + +char *ren_translate(char *s, char *ln) +{ + char *p = ren_placeholder(s); + return p ? p : uc_shape(ln, s); +} diff --git a/uc.c b/uc.c @@ -323,10 +323,8 @@ char *uc_shape(char *beg, char *s) int prev = 0; int next = 0; int curr = uc_code(s); - if (!curr || !UC_R2L(curr)) { - uc_cput(out, curr); - return out; - } + if (!curr || !UC_R2L(curr)) + return NULL; r = s; while (r > beg) { r = uc_beg(beg, r - 1); diff --git a/vi.h b/vi.h @@ -45,7 +45,6 @@ void rset_free(struct rset *re); /* rendering lines */ 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); @@ -53,6 +52,8 @@ int ren_pos(char *s, int off); int ren_off(char *s, int pos); int ren_wid(char *s); int ren_region(char *s, int c1, int c2, int *l1, int *l2, int closed); +char *ren_translate(char *s, char *ln); +int ren_cwid(char *s, int pos); /* text direction */ int dir_context(char *s);