ref: 54aeeafab3117a7cbbcb5b96a21d22101f78eac2
parent: 9e9121225b695ed05d8d1a12c9ce8caa21a00528
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat Apr 27 14:45:53 EDT 2013
ren: add .tl, .lt and .pc
--- a/reg.c
+++ b/reg.c
@@ -36,6 +36,8 @@
REG(0, 'L'),
REG(0, 'n'),
REG(0, 's'),
+ REG(0, 't'),
+ REG(0, 'T'),
REG(0, 'v'),
};
@@ -162,6 +164,7 @@
n_s0 = n_s;
n_f0 = n_f;
n_na = 0;
+ n_lt = SC_IN * 65 / 10;
adj_ll(env->adj, n_l);
adj_in(env->adj, n_i);
}
--- a/ren.c
+++ b/ren.c
@@ -194,16 +194,16 @@
}
/* flush the given line and send it to out.c */
-static void ren_line(char *s, int w, int ll, int li, int lt)
+static void ren_line(char *s, int w, int ad, int ll, int li, int lt)
{
int ljust = 0;
char cmd[32];
int llen = ll - (lt >= 0 ? lt : li);
n_n = w;
- if (n_u && !n_na && (n_j == AD_C || n_j == AD_R))
- ljust = n_j == AD_C ? (llen - w) / 2 : llen - w;
- if (n_ce)
+ if (ad == AD_C)
ljust = llen > w ? (llen - w) / 2 : 0;
+ if (ad == AD_R)
+ ljust = llen - w;
if (cdiv) {
if (cdiv->dl < w)
cdiv->dl = w;
@@ -221,16 +221,14 @@
}
/* return 1 if triggered a trap */
-static int ren_br(int force)
+static int ren_bradj(struct adj *adj, int fill, int ad)
{
char buf[LNLEN];
int ll, li, lt, els_neg, els_pos;
- int adj_b, fill, w, prev_d;
+ int w, prev_d;
ren_first();
- if (!adj_empty(cadj, !n_ce && n_u)) {
- adj_b = !n_ce && n_u && !n_na && n_j == AD_B;
- fill = !n_ce && n_u;
- w = adj_fill(cadj, !force && adj_b, !force && fill, buf,
+ if (!adj_empty(adj, fill)) {
+ w = adj_fill(adj, ad == AD_B, fill, buf,
&ll, &li, <, &els_neg, &els_pos);
prev_d = n_d;
if (els_neg)
@@ -237,7 +235,7 @@
ren_sp(-els_neg);
if (!n_ns || w || els_neg || els_pos) {
ren_sp(0);
- ren_line(buf, w, ll, li, lt);
+ ren_line(buf, w, ad, ll, li, lt);
n_ns = 0;
}
if (els_pos)
@@ -257,6 +255,13 @@
return 0;
}
+/* return 1 if triggered a trap */
+static int ren_br(int force)
+{
+ return ren_bradj(cadj, !force && !n_ce && n_u,
+ n_ce ? AD_C : (n_u && !n_na && (n_j != AD_B || !force) ? n_j : AD_L));
+}
+
void tr_br(char **args)
{
if (args[0][0] == '.')
@@ -481,7 +486,7 @@
int n, w;
switch (c) {
case ' ':
- w = dev_spacewid();
+ w = charwid(dev_spacewid(), n_s);
adj_put(adj, w, "\\h'%du'", w);
break;
case 'b':
@@ -600,7 +605,7 @@
}
g = dev_glyph(c, n_f);
w = charwid(g ? g->wid : SC_DW, n_s);
- adj_put(adj, w, c);
+ adj_put(adj, w, "%s", c);
if (zerowid)
adj_put(adj, -w, "\\h'%du'", -w);
return g ? g->type : 0;
@@ -609,15 +614,18 @@
/* read the argument of \w and push its width */
int ren_wid(int (*next)(void), void (*back)(int))
{
+ char delim[GNLEN];
struct adj *adj = adj_alloc();
- int c, wid_c, n;
+ int c, n;
int type = 0;
- wid_c = next();
- c = next();
+ schar_read(delim, next);
adj_ll(adj, n_l);
odiv_beg();
- while (c >= 0 && c != wid_c) {
+ c = next();
+ while (c >= 0 && c != '\n') {
back(c);
+ if (!schar_jump(delim, next, back))
+ break;
type |= ren_char(adj, next, back);
c = next();
}
@@ -628,6 +636,57 @@
n_ct = type;
adj_free(adj);
return n;
+}
+
+static void ren_until(struct adj *adj, char *delim, int (*next)(void), void (*back)(int))
+{
+ int c;
+ c = next();
+ while (c >= 0 && c != '\n') {
+ back(c);
+ if (!schar_jump(delim, next, back))
+ break;
+ ren_char(adj, next, back);
+ c = next();
+ }
+ if (c == '\n')
+ back(c);
+}
+
+static void adj_cpy(struct adj *dst, struct adj *src, int left)
+{
+ char buf[LNLEN];
+ int ll, li, lt, els_neg, els_pos;
+ int w;
+ adj_put(src, 0, "\n");
+ w = adj_fill(src, 0, 0, buf, &ll, &li, <, &els_neg, &els_pos);
+ adj_put(dst, left - adj_wid(dst), "\\h'%du'", left - adj_wid(dst));
+ adj_put(dst, w, "%s", buf);
+ adj_els(dst, els_neg);
+ adj_els(dst, els_pos);
+}
+
+void ren_tl(int (*next)(void), void (*back)(int))
+{
+ struct adj *adj = adj_alloc();
+ struct adj *tmp = adj_alloc();
+ char delim[GNLEN];
+ adj_ll(tmp, n_lt);
+ adj_ll(adj, n_lt);
+ schar_read(delim, next);
+ /* the left-adjusted string */
+ ren_until(adj, delim, next, back);
+ /* the centered string */
+ ren_until(tmp, delim, next, back);
+ adj_cpy(adj, tmp, (n_lt - adj_wid(tmp)) / 2);
+ /* the right-adjusted string */
+ ren_until(tmp, delim, next, back);
+ adj_cpy(adj, tmp, n_lt - adj_wid(tmp));
+ /* flushing the line */
+ adj_put(adj, 0, "\n");
+ ren_bradj(adj, 0, AD_L);
+ adj_free(tmp);
+ adj_free(adj);
}
/* read characters from in.c and pass rendered lines to out.c */
--- a/tr.c
+++ b/tr.c
@@ -5,6 +5,7 @@
#include "xroff.h"
static int tr_nl = 1;
+static int c_pc = '%'; /* page number character */
/* skip everything until the end of line */
static void jmp_eol(void)
@@ -153,27 +154,58 @@
macrobody(NULL, args[1] ? args[1] : ".");
}
+void schar_read(char *d, int (*next)(void))
+{
+ d[0] = next();
+ d[1] = '\0';
+ if (d[0] == '\\') {
+ d[1] = next();
+ d[2] = '\0';
+ if (d[1] == '(') {
+ d[2] = next();
+ d[3] = next();
+ d[4] = '\0';
+ }
+ }
+}
+
+int schar_jump(char *d, int (*next)(void), void (*back)(int))
+{
+ int c, i;
+ for (i = 0; d[i]; i++)
+ if ((c = next()) != d[i])
+ break;
+ if (d[i]) {
+ back(c);
+ while (i > 0)
+ back(d[--i]);
+ return 1;
+ }
+ return 0;
+}
+
/* read into sbuf until stop */
-static void read_until(struct sbuf *sbuf, int stop)
+static int read_until(struct sbuf *sbuf, char *stop)
{
int c;
while ((c = cp_next()) >= 0) {
- if (c == stop)
- return;
- if (c == '\n') {
- cp_back(c);
- return;
- }
- sbuf_add(sbuf, c);
+ cp_back(c);
+ if (c == '\n')
+ return 1;
+ if (!schar_jump(stop, cp_next, cp_back))
+ return 0;
+ sbuf_add(sbuf, cp_next());
}
+ return 1;
}
/* evaluate .if strcmp (i.e. 'str'str') */
static int if_strcmp(void)
{
+ char delim[GNLEN];
struct sbuf s1, s2;
- int ret, delim;
- delim = cp_next();
+ int ret;
+ schar_read(delim, cp_next);
sbuf_init(&s1);
sbuf_init(&s2);
read_until(&s1, delim);
@@ -206,7 +238,8 @@
struct sbuf sbuf;
int ret;
sbuf_init(&sbuf);
- read_until(&sbuf, ' ');
+ if (!read_until(&sbuf, " "))
+ cp_back(' ');
ret = eval(sbuf_buf(&sbuf), '\0') > 0;
sbuf_done(&sbuf);
return ret;
@@ -299,6 +332,41 @@
in_ex();
}
+static void tr_lt(char **args)
+{
+ int lt = args[1] ? eval_re(args[1], n_lt, 'm') : n_t0;
+ n_t0 = n_t0;
+ n_lt = MAX(0, lt);
+}
+
+static void tr_pc(char **args)
+{
+ c_pc = args[1] ? args[1][0] : -1;
+}
+
+static int tl_next(void)
+{
+ int c = cp_next();
+ if (c >= 0 && c == c_pc) {
+ in_push(num_str(REG('%', '\0')), NULL);
+ c = cp_next();
+ }
+ return c;
+}
+
+static void tr_tl(char **args)
+{
+ int c;
+ do {
+ c = cp_next();
+ } while (c >= 0 && (c == ' ' || c == '\t'));
+ cp_back(c);
+ ren_tl(tl_next, cp_back);
+ do {
+ c = cp_next();
+ } while (c >= 0 && c != '\n');
+}
+
static char *arg_regname(char *s, int len)
{
char *e = s + 2;
@@ -418,7 +486,9 @@
args[0] = s;
s = arg_regname(s, e - s);
args[1] = s;
+ cp_wid(0);
s = arg_string(s, e - s);
+ cp_wid(1);
c = cp_next();
if (c >= 0 && c != '\n')
jmp_eol();
@@ -490,6 +560,7 @@
{"in", tr_in},
{"ll", tr_ll},
{"ls", tr_ls},
+ {"lt", tr_lt},
{"mk", tr_mk},
{"na", tr_na},
{"ne", tr_ne},
@@ -498,6 +569,7 @@
{"ns", tr_ns},
{"nx", tr_nx},
{"os", tr_os},
+ {"pc", tr_pc},
{"pl", tr_pl},
{"pn", tr_pn},
{"po", tr_po},
@@ -511,6 +583,7 @@
{"sp", tr_sp},
{"sv", tr_sv},
{"ti", tr_ti},
+ {"tl", tr_tl, mkargs_null},
{"tm", tr_tm, mkargs_eol},
{"vs", tr_vs},
{"wh", tr_wh},
--- a/xroff.h
+++ b/xroff.h
@@ -124,6 +124,7 @@
/* rendering */
void render(void); /* read from in.c and print the output */
int ren_wid(int (*next)(void), void (*back)(int));
+void ren_tl(int (*next)(void), void (*back)(int));
void out_line(char *s); /* output the given rendered line */
int out_draw(char *s, char *cc);
void out(char *s, ...); /* output troff cmd */
@@ -167,6 +168,8 @@
void errmsg(char *msg, ...);
int utf8len(int c);
char *utf8get(char *d, char *s);
+void schar_read(char *d, int (*next)(void));
+int schar_jump(char *d, int (*next)(void), void (*back)(int));
/* variable length string buffer */
struct sbuf {
@@ -241,6 +244,8 @@
#define n_o0 (*nreg(REG(0, 'o'))) /* last .o */
#define n_s0 (*nreg(REG(0, 's'))) /* last .s */
#define n_sv (*nreg(REG(0, 'S'))) /* .sv value */
+#define n_lt (*nreg(REG(0, 't'))) /* .lt value */
+#define n_t0 (*nreg(REG(0, 'T'))) /* previous .lt value */
#define n_v0 (*nreg(REG(0, 'v'))) /* last .v */
/* functions for implementing read-only registers */