shithub: neatroff

Download patch

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, &lt, &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, &lt, &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 */