ref: 27c39c735ad6b88784ed7450af2ab088a4f13770
parent: 700e46aa7b3e7b6d5060bed7272c3accb7296bb3
author: Ali Gholami Rudi <ali@rudi.ir>
date: Mon Aug 19 15:31:55 EDT 2013
ren: field delimiters and padding indicators can be utf-8
--- a/draw.c
+++ b/draw.c
@@ -185,7 +185,7 @@
c = sstr_next();
while (c >= 0) {
sstr_back(c);
- ren_char(&wb2, sstr_next, sstr_back, NULL);
+ ren_char(&wb2, sstr_next, sstr_back);
if (wb_wid(&wb2) > w)
w = wb_wid(&wb2);
wb_hmov(&wb2, -wb_wid(&wb2));
@@ -213,7 +213,7 @@
c = sstr_next();
while (c >= 0) {
sstr_back(c);
- ren_char(&wb3, sstr_next, sstr_back, NULL);
+ ren_char(&wb3, sstr_next, sstr_back);
wc = wb_wid(&wb3);
if (wc > w)
w = wc;
--- a/ren.c
+++ b/ren.c
@@ -38,7 +38,7 @@
static int bp_ejected; /* current ejected page */
static int bp_final; /* 1: executing em, 2: the final page, 3: the 2nd final page */
-static int c_fa; /* field delimiter */
+static char c_fa[GNLEN]; /* field delimiter */
static char c_fb[GNLEN]; /* field padding */
static int ren_next(void)
@@ -563,11 +563,13 @@
void tr_fc(char **args)
{
- if (args[1]) {
- c_fa = args[1][0];
- strcpy(c_fb, args[2] ? args[2] : " ");
+ char *fa = args[1];
+ char *fb = args[2];
+ if (fa && charread(&fa, c_fa) >= 0) {
+ if (!fb || charread(&fb, c_fb) < 0)
+ strcpy(c_fb, " ");
} else {
- c_fa = -1;
+ c_fa[0] = '\0';
c_fb[0] = '\0';
}
}
@@ -667,36 +669,31 @@
static void ren_field(struct wb *wb, int (*next)(void), void (*back)(int));
static void ren_tab(struct wb *wb, char *tc, int (*next)(void), void (*back)(int));
-/* read one character and place it inside wb buffer; return 1 if read delim */
-int ren_char(struct wb *wb, int (*next)(void), void (*back)(int), char *delim)
+/* insert a character, escape sequence, field or etc into wb */
+static void ren_put(struct wb *wb, char *c, int (*next)(void), void (*back)(int))
{
- char c[GNLEN * 4];
char arg[ILNLEN];
struct glyph *g;
char *s;
int w, n;
- if (charnext(c, next, back) < 0)
- return -1;
- if (delim && !strcmp(c, delim))
- return 1;
if (c[0] == ' ' || c[0] == '\n') {
wb_put(wb, c);
- return 0;
+ return;
}
if (c[0] == '\t' || c[0] == '') {
ren_tab(wb, c[0] == '\t' ? c_tc : c_lc, next, back);
- return 0;
+ return;
}
- if (c[0] == c_fa) {
+ if (c_fa[0] && !strcmp(c_fa, c)) {
ren_field(wb, next, back);
- return 0;
+ return;
}
if (c[0] == c_ec) {
if (c[1] == 'z') {
w = wb_wid(wb);
- ren_char(wb, next, back, NULL);
+ ren_char(wb, next, back);
wb_hmov(wb, w - wb_wid(wb));
- return 0;
+ return;
}
if (c[1] == '!') {
if (ren_nl && next == ren_next) {
@@ -709,15 +706,15 @@
*s = '\0';
ren_transparent(arg);
}
- return 0;
+ return;
}
if (strchr(" bCcDdfHhkLlmNoprSsuvXxz0^|{}&", c[1])) {
argnext(arg, c[1], next, back);
if (c[1] == 'S' || c[1] == 'H')
- return 0; /* not implemented */
+ return; /* not implemented */
if (c[1] != 'N') {
ren_cmd(wb, c[1], arg);
- return 0;
+ return;
}
g = dev_glyph_byid(arg, n_f);
strcpy(c, g ? g->name : "cnull");
@@ -728,9 +725,33 @@
wb_kern(wb, c);
wb_put(wb, c);
}
+}
+
+/* read one character and place it inside wb buffer */
+int ren_char(struct wb *wb, int (*next)(void), void (*back)(int))
+{
+ char c[GNLEN * 4];
+ if (charnext(c, next, back) < 0)
+ return -1;
+ ren_put(wb, c, next, back);
return 0;
}
+/* like ren_char(); return 1 if d1 was read and d2 if d2 was read */
+static int ren_chardel(struct wb *wb, int (*next)(void), void (*back)(int),
+ char *d1, char *d2)
+{
+ char c[GNLEN * 4];
+ if (charnext(c, next, back) < 0)
+ return -1;
+ if (d1 && !strcmp(d1, c))
+ return 1;
+ if (d2 && !strcmp(d2, c))
+ return 2;
+ ren_put(wb, c, next, back);
+ return 0;
+}
+
/* read the argument of \w and push its width */
int ren_wid(int (*next)(void), void (*back)(int))
{
@@ -743,7 +764,7 @@
c = next();
while (c >= 0 && c != '\n') {
back(c);
- if (ren_char(&wb, next, back, delim))
+ if (ren_chardel(&wb, next, back, delim, NULL))
break;
c = next();
}
@@ -754,21 +775,22 @@
return n;
}
-/* return 1 if the ending character (ec) was read */
-static int ren_until(struct wb *wb, char *delim, int ec,
+/* return 1 if d1 was read and 2 if d2 was read */
+static int ren_until(struct wb *wb, char *d1, char *d2,
int (*next)(void), void (*back)(int))
{
- int c;
+ int c, ret;
c = next();
- while (c >= 0 && c != '\n' && c != ec) {
+ while (c >= 0 && c != '\n') {
back(c);
- if (ren_char(wb, next, back, delim))
- break;
+ ret = ren_chardel(wb, next, back, d1, d2);
+ if (ret)
+ return ret;
c = next();
}
if (c == '\n')
back(c);
- return c == ec;
+ return 0;
}
static void wb_cpy(struct wb *dst, struct wb *src, int left)
@@ -787,13 +809,13 @@
wb_init(&wb2);
charnext(delim, next, back);
/* the left-adjusted string */
- ren_until(&wb2, delim, '\n', next, back);
+ ren_until(&wb2, delim, NULL, next, back);
wb_cpy(&wb, &wb2, 0);
/* the centered string */
- ren_until(&wb2, delim, '\n', next, back);
+ ren_until(&wb2, delim, NULL, next, back);
wb_cpy(&wb, &wb2, (n_lt - wb_wid(&wb2)) / 2);
/* the right-adjusted string */
- ren_until(&wb2, delim, '\n', next, back);
+ ren_until(&wb2, delim, NULL, next, back);
wb_cpy(&wb, &wb2, n_lt - wb_wid(&wb2));
/* flushing the line */
adj_ll(adj, n_lt);
@@ -814,7 +836,7 @@
int pad, rem;
while (n < LEN(wbs)) {
wb_init(&wbs[n]);
- if (ren_until(&wbs[n++], c_fb, c_fa, next, back))
+ if (ren_until(&wbs[n++], c_fb, c_fa, next, back) != 1)
break;
}
left = RENWB(wb) ? f_hpos() : wb_wid(wb);
@@ -847,7 +869,7 @@
c = next();
while (c >= 0 && c != '\n' && c != '\t' && c != '') {
back(c);
- ren_char(&t, next, back, NULL);
+ ren_char(&t, next, back);
c = next();
}
back(c);
@@ -919,7 +941,7 @@
n_ce = MAX(0, n_ce - 1);
if (c != ' ') {
ren_back(c);
- ren_char(wb, ren_next, ren_back, NULL);
+ ren_char(wb, ren_next, ren_back);
if (c != '\n' && wb_empty(wb))
adj_nonl(cadj);
}
--- a/roff.h
+++ b/roff.h
@@ -270,7 +270,7 @@
/* rendering */
int render(void); /* the main loop */
-int ren_char(struct wb *wb, int (*next)(void), void (*back)(int), char *delim);
+int ren_char(struct wb *wb, int (*next)(void), void (*back)(int));
int ren_wid(int (*next)(void), void (*back)(int));
void ren_tl(int (*next)(void), void (*back)(int));
void ren_hline(struct wb *wb, int l, char *c); /* horizontal line */