From 1874ab5126cf9ae58f12f8b89a8da14b9ccbfbb7 Mon Sep 17 00:00:00 2001 From: Ali Gholami Rudi Date: Sat, 27 Jul 2013 18:40:27 +0430 Subject: [PATCH] tr: add .tc and .lc --- draw.c | 217 ++++++++++++++++++++++++++++++++++------------------------------- reg.c | 15 ++++- ren.c | 18 +++--- roff.h | 15 +++-- tr.c | 12 ++++ wb.c | 2 +- 6 files changed, 163 insertions(+), 116 deletions(-) diff --git a/draw.c b/draw.c index 1d35ef9..92bcc03 100644 --- a/draw.c +++ b/draw.c @@ -3,30 +3,6 @@ #include #include "roff.h" -static char *ln_s; - -static int ln_next(void) -{ - return *ln_s ? (unsigned char) *ln_s++ : -1; -} - -static void ln_back(int c) -{ - ln_s--; -} - -static char *ln_push(char *s) -{ - char *old_s = ln_s; - ln_s = s; - return old_s; -} - -static void ln_pop(char *s) -{ - ln_s = s; -} - static int cwid(char *c) { struct glyph *g = dev_glyph(c, n_f); @@ -50,18 +26,10 @@ static int vchar(char *c) return (c[2] == 'b' && c[3] == 'v') || (c[2] == 'b' && c[3] == 'r'); } -void ren_hline(struct wb *wb, char *arg) +void ren_hline(struct wb *wb, int l, char *c) { - char lc[GNLEN] = {c_ec, '(', 'r', 'u'}; - int w, l, n, i, rem; - l = eval_up(&arg, 'm'); - if (!l) - return; - if (arg[0] == c_ec && arg[1] == '&') /* \& can be used as a separator */ - arg += 2; - if (*arg) - strcpy(lc, arg); - w = cwid(lc); + int w, n, i, rem; + w = cwid(c); /* negative length; moving backwards */ if (l < 0) { wb_hmov(wb, l); @@ -77,34 +45,26 @@ void ren_hline(struct wb *wb, char *arg) } /* the initial gap */ if (rem) { - if (hchar(lc)) { - wb_put(wb, lc); + if (hchar(c)) { + wb_put(wb, c); wb_hmov(wb, rem - w); } else { wb_hmov(wb, rem); } } for (i = 0; i < n; i++) - wb_put(wb, lc); + wb_put(wb, c); /* moving back */ if (l < w) wb_hmov(wb, -(w - l + 1) / 2); } -void ren_vline(struct wb *wb, char *arg) +static void ren_vline(struct wb *wb, int l, char *c) { - char lc[GNLEN] = {c_ec, '(', 'b', 'r'}; - int w, l, n, i, rem, hw, neg; - l = eval_up(&arg, 'v'); - if (!l) - return; + int w, n, i, rem, hw, neg; neg = l < 0; - if (arg[0] == c_ec && arg[1] == '&') /* \& can be used as a separator */ - arg += 2; - if (*arg) - strcpy(lc, arg); w = SC_HT; /* character height */ - hw = cwid(lc); /* character width */ + hw = cwid(c); /* character width */ /* negative length; moving backwards */ if (l < 0) { wb_vmov(wb, l); @@ -120,9 +80,9 @@ void ren_vline(struct wb *wb, char *arg) } /* the initial gap */ if (rem) { - if (vchar(lc)) { + if (vchar(c)) { wb_vmov(wb, w); - wb_put(wb, lc); + wb_put(wb, c); wb_hmov(wb, -hw); wb_vmov(wb, rem - w); } else { @@ -131,7 +91,7 @@ void ren_vline(struct wb *wb, char *arg) } for (i = 0; i < n; i++) { wb_vmov(wb, w); - wb_put(wb, lc); + wb_put(wb, c); wb_hmov(wb, -hw); } /* moving back */ @@ -142,59 +102,24 @@ void ren_vline(struct wb *wb, char *arg) wb_hmov(wb, hw); } -void ren_bracket(struct wb *wb, char *arg) +void ren_hlcmd(struct wb *wb, char *arg) { - struct wb wb2; - int n = 0, w = 0; - int c, center; - char *ln_prev = ln_push(arg); - wb_init(&wb2); - c = ln_next(); - while (c >= 0) { - ln_back(c); - ren_char(&wb2, ln_next, ln_back); - if (wb_wid(&wb2) > w) - w = wb_wid(&wb2); - wb_hmov(&wb2, -wb_wid(&wb2)); - wb_vmov(&wb2, SC_HT); - n++; - c = ln_next(); - } - ln_pop(ln_prev); - center = -(n * SC_HT + SC_EM) / 2; - wb_vmov(wb, center + SC_HT); - wb_cat(wb, &wb2); - wb_done(&wb2); - wb_vmov(wb, center); - wb_hmov(wb, w); + char lc[GNLEN] = {c_ec, '(', 'r', 'u'}; + int l = eval_up(&arg, 'm'); + if (arg[0] == c_ec && arg[1] == '&') /* \& can be used as a separator */ + arg += 2; + if (l) + ren_hline(wb, l, *arg ? arg : lc); } -void ren_over(struct wb *wb, char *arg) +void ren_vlcmd(struct wb *wb, char *arg) { - struct wb wb2, wb3; - int w = 0, wc; - int c; - char *ln_prev = ln_push(arg); - wb_init(&wb2); - wb_init(&wb3); - c = ln_next(); - while (c >= 0) { - ln_back(c); - ren_char(&wb3, ln_next, ln_back); - wc = wb_wid(&wb3); - if (wc > w) - w = wc; - wb_hmov(&wb2, -wc / 2); - wb_cat(&wb2, &wb3); - wb_hmov(&wb2, -wc / 2); - c = ln_next(); - } - ln_pop(ln_prev); - wb_hmov(wb, w / 2); - wb_cat(wb, &wb2); - wb_hmov(wb, w / 2); - wb_done(&wb3); - wb_done(&wb2); + char lc[GNLEN] = {c_ec, '(', 'b', 'r'}; + int l = eval_up(&arg, 'v'); + if (arg[0] == c_ec && arg[1] == '&') /* \& can be used as a separator */ + arg += 2; + if (l) + ren_vline(wb, l, *arg ? arg : lc); } static int tok_num(char **s, int scale) @@ -209,7 +134,7 @@ static int tok_num(char **s, int scale) return eval(tok, scale); } -void ren_draw(struct wb *wb, char *s) +void ren_dcmd(struct wb *wb, char *s) { int h1, h2, v1, v2; int c = *s++; @@ -245,3 +170,91 @@ void ren_draw(struct wb *wb, char *s) wb_drawxend(wb); } } + +/* + * the implementation of \b and \o + * + * ren_bcmd() and ren_ocmd() call ren_char(), which requires + * next() and back() functions, similar to ren_next() and ren_back(). + * ln_*() here provide such an interface for the given string, + * added via ln_push(). ln_*() may be called recursively to + * handle \o'\b"ab"c'. + */ +static char *ln_s; + +static int ln_next(void) +{ + return *ln_s ? (unsigned char) *ln_s++ : -1; +} + +static void ln_back(int c) +{ + ln_s--; +} + +static char *ln_push(char *s) +{ + char *old_s = ln_s; + ln_s = s; + return old_s; +} + +static void ln_pop(char *s) +{ + ln_s = s; +} + +void ren_bcmd(struct wb *wb, char *arg) +{ + struct wb wb2; + int n = 0, w = 0; + int c, center; + char *ln_prev = ln_push(arg); + wb_init(&wb2); + c = ln_next(); + while (c >= 0) { + ln_back(c); + ren_char(&wb2, ln_next, ln_back); + if (wb_wid(&wb2) > w) + w = wb_wid(&wb2); + wb_hmov(&wb2, -wb_wid(&wb2)); + wb_vmov(&wb2, SC_HT); + n++; + c = ln_next(); + } + ln_pop(ln_prev); + center = -(n * SC_HT + SC_EM) / 2; + wb_vmov(wb, center + SC_HT); + wb_cat(wb, &wb2); + wb_done(&wb2); + wb_vmov(wb, center); + wb_hmov(wb, w); +} + +void ren_ocmd(struct wb *wb, char *arg) +{ + struct wb wb2, wb3; + int w = 0, wc; + int c; + char *ln_prev = ln_push(arg); + wb_init(&wb2); + wb_init(&wb3); + c = ln_next(); + while (c >= 0) { + ln_back(c); + ren_char(&wb3, ln_next, ln_back); + wc = wb_wid(&wb3); + if (wc > w) + w = wc; + wb_hmov(&wb2, -wc / 2); + wb_cat(&wb2, &wb3); + wb_hmov(&wb2, -wc / 2); + c = ln_next(); + } + ln_pop(ln_prev); + wb_hmov(wb, w / 2); + wb_cat(wb, &wb2); + wb_hmov(wb, w / 2); + wb_done(&wb3); + wb_done(&wb2); +} diff --git a/reg.c b/reg.c index 39f0a6c..b07e83c 100644 --- a/reg.c +++ b/reg.c @@ -12,7 +12,9 @@ struct env { int eregs[NENVS]; /* environment-specific number registers */ int tabs[NTABS]; /* tab stops */ struct adj *adj; /* per environment line buffer */ - char hc[GNLEN]; /* hyphenation character */ + char tc[GNLEN]; /* tab character (.tc) */ + char lc[GNLEN]; /* leader character (.lc) */ + char hc[GNLEN]; /* hyphenation character (.hc) */ char mc[GNLEN]; /* margin character (.mc) */ }; @@ -192,6 +194,7 @@ static void env_set(int id) n_nM = 1; n_nS = 1; strcpy(env->hc, "\\%"); + strcpy(env->lc, "."); adj_ll(env->adj, n_l); adj_in(env->adj, n_i); for (i = 0; i < NTABS; i++) @@ -258,6 +261,16 @@ char *env_mc(void) return env->mc; } +char *env_tc(void) +{ + return env->tc; +} + +char *env_lc(void) +{ + return env->lc; +} + /* saving and restoring registers around diverted lines */ struct odiv { int f, s, m, f0, s0, m0; diff --git a/ren.c b/ren.c index c7e54c8..c686f4e 100644 --- a/ren.c +++ b/ren.c @@ -645,13 +645,13 @@ static void ren_cmd(struct wb *wb, int c, char *arg) wb_hmov(wb, spacewid(n_f, n_s)); break; case 'b': - ren_bracket(wb, arg); + ren_bcmd(wb, arg); break; case 'c': wb_setpart(wb); break; case 'D': - ren_draw(wb, arg); + ren_dcmd(wb, arg); break; case 'd': wb_vmov(wb, SC_EM / 2); @@ -666,16 +666,16 @@ static void ren_cmd(struct wb *wb, int c, char *arg) num_set(map(arg), RENWB(wb) ? f_hpos() - n_lb : wb_wid(wb)); break; case 'L': - ren_vline(wb, arg); + ren_vlcmd(wb, arg); break; case 'l': - ren_hline(wb, arg); + ren_hlcmd(wb, arg); break; case 'm': ren_m(arg); break; case 'o': - ren_over(wb, arg); + ren_ocmd(wb, arg); break; case 'p': if (RENWB(wb)) @@ -725,7 +725,7 @@ void ren_char(struct wb *wb, int (*next)(void), void (*back)(int)) char c[GNLEN * 4]; char arg[ILNLEN]; struct glyph *g; - char *s; + char *s, *tc; int w, n, l; nextchar(c, next); if (c[0] == ' ' || c[0] == '\n') { @@ -734,7 +734,11 @@ void ren_char(struct wb *wb, int (*next)(void), void (*back)(int)) } if (c[0] == '\t' || c[0] == '') { n = RENWB(wb) ? f_hpos() : wb_wid(wb); - wb_hmov(wb, tab_next(n) - n); + tc = c[0] == '\t' ? c_tc : c_lc; + if (!tc[0]) + wb_hmov(wb, tab_next(n) - n); + else + ren_hline(wb, tab_next(n) - n, tc); return; } if (c[0] == c_fa) { diff --git a/roff.h b/roff.h index 409ec3e..3816b53 100644 --- a/roff.h +++ b/roff.h @@ -43,6 +43,8 @@ extern int c_c2; /* no-break control character (') */ #define c_ni 4 /* non-interpreted copy mode escape */ #define c_hc env_hc()/* hyphenation character */ #define c_mc env_mc()/* margin character (.mc) */ +#define c_tc env_tc() +#define c_lc env_lc() /* number registers */ int num_get(int id, int inc); @@ -75,6 +77,8 @@ void env_done(void); struct adj *env_adj(void); char *env_hc(void); char *env_mc(void); +char *env_tc(void); +char *env_lc(void); int tab_next(int pos); /* device related variables */ @@ -256,11 +260,12 @@ int render(void); /* the main loop */ void 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, char *arg); /* horizontal line */ -void ren_vline(struct wb *wb, char *arg); /* vertical line */ -void ren_bracket(struct wb *wb, char *arg); /* \b */ -void ren_over(struct wb *wb, char *arg); /* \o */ -void ren_draw(struct wb *wb, char *arg); /* \D */ +void ren_hline(struct wb *wb, int l, char *c); /* horizontal line */ +void ren_hlcmd(struct wb *wb, char *arg); /* \l */ +void ren_vlcmd(struct wb *wb, char *arg); /* \L */ +void ren_bcmd(struct wb *wb, char *arg); /* \b */ +void ren_ocmd(struct wb *wb, char *arg); /* \o */ +void ren_dcmd(struct wb *wb, char *arg); /* \D */ /* out.c */ void out_line(char *s); /* output rendered line */ diff --git a/tr.c b/tr.c index 374fb16..7327a65 100644 --- a/tr.c +++ b/tr.c @@ -502,6 +502,16 @@ static void tr_mc(char **args) } } +static void tr_tc(char **args) +{ + strcpy(c_tc, args[1] ? args[1] : ""); +} + +static void tr_lc(char **args) +{ + strcpy(c_lc, args[1] ? args[1] : ""); +} + static void tr_lf(char **args) { if (args[1]) @@ -716,6 +726,7 @@ static struct cmd { {"in", tr_in}, {"it", tr_it}, {"kn", tr_kn}, + {"lc", tr_lc}, {"lf", tr_lf}, {"lg", tr_lg}, {"ll", tr_ll}, @@ -749,6 +760,7 @@ static struct cmd { {"sv", tr_sv}, {"sy", tr_sy, mkargs_eol}, {"ta", tr_ta}, + {"tc", tr_tc}, {"ti", tr_ti}, {"tl", tr_tl, mkargs_null}, {"tm", tr_tm, mkargs_eol}, diff --git a/wb.c b/wb.c index 60ff396..cc28706 100644 --- a/wb.c +++ b/wb.c @@ -275,7 +275,7 @@ static void wb_putc(struct wb *wb, int t, char *s) wb_put(wb, s); break; case 'D': - ren_draw(wb, s); + ren_dcmd(wb, s); break; case 'f': wb->r_f = atoi(s); -- 2.11.4.GIT