shithub: neatroff

Download patch

ref: 0459f7fcd938752ba827be6bea9de78eb2bd137e
parent: aa9e73a208521ca06d36ec739c14d0c7c1c08c55
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat Apr 6 14:50:44 EDT 2013

ren: preserve line spacing in diversions

Note that reading diversions in .fi mode is not compatible.

--- a/ren.c
+++ b/ren.c
@@ -17,6 +17,9 @@
 };
 static struct div divs[NPREV];	/* diversion stack */
 static struct div *cdiv;	/* current diversion */
+static int ren_f;		/* last rendered n_f */
+static int ren_s;		/* last rendered n_s */
+static int ren_div;		/* rendering a diversion */
 
 static int ren_backed = -1;	/* pushed back character */
 
@@ -63,8 +66,12 @@
 		if (args[0][2] == 'a' && str_get(cdiv->reg))	/* .da */
 			sbuf_append(&cdiv->sbuf, str_get(cdiv->reg));
 		n_d = 0;
+		sbuf_append(&cdiv->sbuf, DIV_BEG "\n");
+		ren_f = 0;
+		ren_s = 0;
 	} else if (cdiv) {
 		sbuf_putnl(&cdiv->sbuf);
+		sbuf_append(&cdiv->sbuf, DIV_END "\n");
 		str_set(cdiv->reg, sbuf_buf(&cdiv->sbuf));
 		sbuf_done(&cdiv->sbuf);
 		n_dl = cdiv->dl;
@@ -71,19 +78,34 @@
 		n_dn = n_d;
 		n_d = cdiv->prev_d;
 		cdiv = cdiv > divs ? cdiv - 1 : NULL;
+		ren_f = 0;
+		ren_s = 0;
 	}
 }
 
+void tr_divbeg(char **args)
+{
+	odiv_beg();
+	ren_div++;
+}
+
+void tr_divend(char **args)
+{
+	odiv_end();
+	ren_div--;
+}
+
 /* vertical motion before rendering lines */
 static void down(int n)
 {
 	char cmd[32];
+	if (!n && ren_div && !n_u)
+		return;
 	n_d += n ? n : n_v;
 	if (cdiv) {
 		sbuf_putnl(&cdiv->sbuf);
-		sprintf(cmd, ".sp %du\n", n);
-		if (n)
-			sbuf_append(&cdiv->sbuf, cmd);
+		sprintf(cmd, ".sp %du\n", n ? n : n_v);
+		sbuf_append(&cdiv->sbuf, cmd);
 	} else {
 		n_nl = n_d;
 		if (n_nl <= n_p)
@@ -94,17 +116,12 @@
 
 static void out_line(char *out, int w)
 {
-	char cmd[32];
 	down(0);
 	n_n = w;
 	if (cdiv) {
 		if (cdiv->dl < w)
 			cdiv->dl = w;
-		sprintf(cmd, "\\h'%d'", n_i);
-		sbuf_append(&cdiv->sbuf, DIV_BEG);
-		sbuf_append(&cdiv->sbuf, cmd);
 		sbuf_append(&cdiv->sbuf, out);
-		sbuf_append(&cdiv->sbuf, DIV_END);
 	} else {
 		OUT("H%d\n", n_o + n_i);
 		output(out);
@@ -132,7 +149,7 @@
 
 void tr_sp(char **args)
 {
-	int sp = 0;
+	int sp = n_v;
 	if (args[1])
 		sp = tr_int(args[1], 0, 'v');
 	ren_br(sp, 1);
@@ -251,8 +268,6 @@
 	char c[GNLEN * 2];
 	char arg[ILNLEN];
 	struct glyph *g;
-	int r_s = n_s;
-	int r_f = n_f;
 	int esc = 0;
 	ren_br(0, 1);
 	while (nextchar(c) > 0) {
@@ -266,15 +281,6 @@
 		if (c[0] == '\\') {
 			esc = 1;
 			nextchar(c);
-			/* rendered lines inside diversions */
-			if (c[0] == DIV_BEG[1]) {
-				nextchar(c);
-				if (c[0] == DIV_BEG[2])
-					odiv_beg();
-				if (c[0] == DIV_END[2])
-					odiv_end();
-				continue;
-			}
 			if (c[0] == '(') {
 				int l = nextchar(c);
 				l += nextchar(c + l);
@@ -288,14 +294,14 @@
 				continue;
 			}
 		}
-		if (r_s != n_s) {
+		if (ren_s != n_s) {
 			adj_swid(adj, charwid(dev_spacewid(), n_s));
 			adj_put(adj, 0, "\\s(%02d", n_s);
-			r_s = n_s;
+			ren_s = n_s;
 		}
-		if (r_f != n_f) {
+		if (ren_f != n_f) {
 			adj_put(adj, 0, "\\f(%02d", n_f);
-			r_f = n_f;
+			ren_f = n_f;
 		}
 		if (utf8len(c[0]) == strlen(c))
 			sprintf(arg, "%s%s", esc ? "\\" : "", c);
--- a/tr.c
+++ b/tr.c
@@ -303,6 +303,8 @@
 	void (*f)(char **args);
 	int (*args)(char **args, char *buf, int len);
 } cmds[] = {
+	{DIV_BEG + 1, tr_divbeg},
+	{DIV_END + 1, tr_divend},
 	{"am", tr_de, mkargs_reg1},
 	{"as", tr_as, mkargs_ds},
 	{"bp", tr_bp},
--- a/xroff.h
+++ b/xroff.h
@@ -107,6 +107,8 @@
 void tr_bp(char **args);
 void tr_br(char **args);
 void tr_di(char **args);
+void tr_divbeg(char **args);
+void tr_divend(char **args);
 void tr_ev(char **args);
 void tr_fi(char **args);
 void tr_fp(char **args);
@@ -138,8 +140,8 @@
 int sbuf_empty(struct sbuf *sbuf);
 
 /* diversions */
-#define DIV_BEG		"\\I<"
-#define DIV_END		"\\I>"
+#define DIV_BEG		".&<"
+#define DIV_END		".&>"
 
 /* adjustment */
 #define ADJ_L		0