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:
M | dir.c | | | 2 | +- |
M | led.c | | | 45 | +++++++++++++++++++++++++++++---------------- |
M | ren.c | | | 64 | +++++++++++++++++++++++++++++++++++++++++++--------------------- |
M | uc.c | | | 6 | ++---- |
M | vi.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);