shithub: neatroff

Download patch

ref: 338f7e3154e7c527d356dbcf2e6db48d2452444a
parent: 0f5500b07902ea32e84976e48d765279aacc0d81
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat Apr 13 14:55:08 EDT 2013

ren: implement \w

--- a/adj.c
+++ b/adj.c
@@ -169,3 +169,8 @@
 {
 	free(adj);
 }
+
+int adj_wid(struct adj *adj)
+{
+	return adj->wid;
+}
--- a/ren.c
+++ b/ren.c
@@ -6,7 +6,7 @@
 
 #define ADJ_LL		(n_l - n_i)	/* effective line length */
 #define ADJ_MODE	(n_u ? n_j : ADJ_N)
-#define adj		env_adj()	/* line buffer */
+#define cadj		env_adj()	/* line buffer */
 
 /* diversions */
 struct div {
@@ -185,8 +185,8 @@
 {
 	char out[LNLEN];
 	int w;
-	if (!adj_empty(adj, ADJ_MODE)) {
-		w = adj_fill(adj, force ? ADJ_N : ADJ_MODE, ADJ_LL, out);
+	if (!adj_empty(cadj, ADJ_MODE)) {
+		w = adj_fill(cadj, force ? ADJ_N : ADJ_MODE, ADJ_LL, out);
 		out_line(out, w);
 	}
 }
@@ -326,55 +326,103 @@
 	*d = '\0';
 }
 
-void render(void)
+static void render_wid(void);
+
+/* read one character and place it inside adj buffer */
+static int render_char(struct adj *adj)
 {
 	char c[GNLEN * 2];
 	char arg[ILNLEN];
 	struct glyph *g;
 	int esc = 0;
-	ren_br(1);
-	while (nextchar(c) > 0) {
-		if (c[0] == ' ' || c[0] == '\n')
-			adj_put(adj, charwid(dev_spacewid(), n_s), c);
-		while (adj_full(adj, ADJ_MODE, ADJ_LL))
-			ren_br(0);
-		if (c[0] == ' ' || c[0] == '\n')
-			continue;
-		esc = 0;
-		if (c[0] == '\\') {
-			esc = 1;
-			nextchar(c);
-			if (c[0] == '(') {
-				int l = nextchar(c);
-				l += nextchar(c + l);
-				c[l] = '\0';
-			} else if (strchr("sf", c[0])) {
-				escarg_ren(arg, c[0]);
-				if (c[0] == 'f')
-					ren_ft(arg);
-				if (c[0] == 's')
-					ren_ps(arg);
-				continue;
+	nextchar(c);
+	if (c[0] == ' ' || c[0] == '\n') {
+		adj_put(cadj, charwid(dev_spacewid(), n_s), c);
+		return 0;
+	}
+	if (c[0] == '\\') {
+		esc = 1;
+		nextchar(c);
+		if (c[0] == '(') {
+			int l = nextchar(c);
+			l += nextchar(c + l);
+			c[l] = '\0';
+		} else if (strchr("sfw", c[0])) {
+			if (c[0] == 'w') {
+				render_wid();
+				return 0;
 			}
+			escarg_ren(arg, c[0]);
+			if (c[0] == 'f')
+				ren_ft(arg);
+			if (c[0] == 's')
+				ren_ps(arg);
+			return 0;
 		}
-		if (ren_s != n_s) {
-			adj_swid(adj, charwid(dev_spacewid(), n_s));
-			adj_put(adj, 0, "\\s(%02d", n_s);
-			ren_s = n_s;
+	}
+	if (ren_s != n_s) {
+		adj_swid(adj, charwid(dev_spacewid(), n_s));
+		adj_put(adj, 0, "\\s(%02d", n_s);
+		ren_s = n_s;
+	}
+	if (ren_f != n_f) {
+		adj_put(adj, 0, "\\f(%02d", n_f);
+		ren_f = n_f;
+	}
+	if (utf8len(c[0]) == strlen(c))
+		sprintf(arg, "%s%s", esc ? "\\" : "", c);
+	else
+		sprintf(arg, "\\(%s", c);
+	g = dev_glyph(c, n_f);
+	adj_put(adj, charwid(g ? g->wid : dev_spacewid(), n_s), arg);
+	return g ? g->type : 0;
+}
+
+/* read the argument of \w and push its width */
+static void render_wid(void)
+{
+	char widbuf[16];
+	struct adj *adj = adj_alloc();
+	int c, wid_c;
+	int type = 0;
+	wid_c = ren_next();
+	c = ren_next();
+	odiv_beg();
+	while (c >= 0 && c != wid_c) {
+		ren_back(c);
+		type |= render_char(adj);
+		c = ren_next();
+	}
+	odiv_end();
+	sprintf(widbuf, "%d", adj_wid(adj));
+	in_push(widbuf, NULL);
+	n_ct = type;
+	adj_free(adj);
+}
+
+/* read characters from in.c and pass rendered lines to out.c */
+void render(void)
+{
+	int c;
+	ren_br(1);
+	c = ren_next();
+	while (c >= 0) {
+		if (c == ' ' || c == '\n') {
+			ren_back(c);
+			render_char(cadj);
 		}
-		if (ren_f != n_f) {
-			adj_put(adj, 0, "\\f(%02d", n_f);
-			ren_f = n_f;
+		while (adj_full(cadj, ADJ_MODE, ADJ_LL))
+			ren_br(0);
+		if (c != ' ' && c != '\n') {
+			ren_back(c);
+			render_char(cadj);
 		}
-		if (utf8len(c[0]) == strlen(c))
-			sprintf(arg, "%s%s", esc ? "\\" : "", c);
-		else
-			sprintf(arg, "\\(%s", c);
-		g = dev_glyph(c, n_f);
-		adj_put(adj, charwid(g ? g->wid : dev_spacewid(), n_s), arg);
+		c = ren_next();
 	}
 	ren_br(1);
 }
+
+/* trap handling */
 
 static int tpos[NTRAPS];	/* trap positions */
 static int treg[NTRAPS];	/* trap registers */
--- a/xroff.h
+++ b/xroff.h
@@ -164,6 +164,7 @@
 void adj_swid(struct adj *adj, int swid);
 int adj_full(struct adj *adj, int mode, int linelen);
 int adj_empty(struct adj *adj, int mode);
+int adj_wid(struct adj *adj);
 
 /* builtin number registers; n_X for .X register */
 #define REG(c1, c2)	((c1) * 256 + (c2))
@@ -181,6 +182,7 @@
 #define n_dl		(*nreg(REG('d', 'l')))
 #define n_dn		(*nreg(REG('d', 'n')))
 #define n_nl		(*nreg(REG('n', 'l')))
+#define n_ct		(*nreg(REG('c', 't')))
 #define n_pg		(*nreg(REG('%', '\0')))	/* % */
 #define n_f0		(*nreg(REG(0, 'f')))	/* last font */
 #define n_s0		(*nreg(REG(0, 's')))	/* last size */