shithub: neatroff

Download patch

ref: 7a5b33eb77e544f5a6c814c40c9a8ae2787b5c96
parent: fc70233e629c5a83b20e72086e6c5e4d038982bd
author: Ali Gholami Rudi <ali@rudi.ir>
date: Mon May 6 18:06:22 EDT 2013

ren: prevent invalid line breaks after traps

--- a/adj.c
+++ b/adj.c
@@ -151,6 +151,14 @@
 	adj->gap = 0;
 }
 
+/* ignore the previous newline */
+void adj_nonl(struct adj *adj)
+{
+	if (adj->nls)
+		adj->gap += adj->swid;
+	adj->nls = 0;
+}
+
 static void adj_word(struct adj *adj, struct wb *wb)
 {
 	struct word *cur = &adj->words[adj->nwords++];
--- a/ren.c
+++ b/ren.c
@@ -24,6 +24,7 @@
 
 static struct wb ren_wb;	/* the main ren.c word buffer */
 static int ren_nl;		/* just after newline */
+static int ren_cnl;		/* current char is a newline */
 static int ren_unbuf[8];	/* ren_back() buffer */
 static int ren_un;
 
@@ -158,11 +159,17 @@
 		in_pushnl(str_get(reg), NULL);
 }
 
+static int detect_traps(int beg, int end)
+{
+	int pos = trap_pos(beg);
+	return pos >= 0 && (cdiv || pos < n_p) && pos <= end;
+}
+
 /* return 1 if executed a trap */
 static int ren_traps(int beg, int end, int dosp)
 {
 	int pos = trap_pos(beg);
-	if (pos >= 0 && (cdiv || pos < n_p) && pos <= end) {
+	if (detect_traps(beg, end)) {
 		if (dosp && pos > beg)
 			ren_sp(pos - beg);
 		trap_exec(trap_reg(beg));
@@ -171,10 +178,15 @@
 	return 0;
 }
 
+static int detect_pagelimit(int ne)
+{
+	return !cdiv && n_nl + ne >= n_p;
+}
+
 /* start a new page if needed */
 static int ren_pagelimit(int ne)
 {
-	if (n_nl + ne >= n_p && !cdiv) {
+	if (detect_pagelimit(ne)) {
 		bp_force = 0;
 		ren_page(bp_next);
 		return 1;
@@ -228,9 +240,10 @@
 /* return 1 if triggered a trap */
 static int ren_bradj(struct adj *adj, int fill, int ad)
 {
+	char cmd[16];
 	struct sbuf sbuf;
 	int ll, li, lt, els_neg, els_pos;
-	int w, prev_d;
+	int w, prev_d, lspc;
 	ren_first();
 	if (!adj_empty(adj, fill)) {
 		sbuf_init(&sbuf);
@@ -248,16 +261,17 @@
 		if (els_pos)
 			ren_sp(els_pos);
 		n_a = els_pos;
-		if (!ren_traps(prev_d, n_d, 0)) {
-			if (n_L > 1 && (cdiv || n_d < n_p)) {
-				down(n_L * n_v - n_v);
-			} else {
-				if (ren_pagelimit(0))
-					return 1;
-			}
-			return 0;
+		lspc = MAX(1, n_L) * n_v - n_v;
+		if (detect_traps(prev_d, n_d) || detect_pagelimit(lspc)) {
+			sprintf(cmd, "%c&", c_ec);
+			if (!ren_cnl)	/* prevent unwanted newlines */
+				in_push(cmd, NULL);
+			if (!ren_traps(prev_d, n_d, 0))
+				ren_pagelimit(lspc);
+			return 1;
 		}
-		return 1;
+		if (lspc)
+			down(lspc);
 	}
 	return 0;
 }
@@ -742,6 +756,7 @@
 	ren_first();			/* transition to the first page */
 	c = ren_next();
 	while (c >= 0) {
+		ren_cnl = c == '\n';
 		if (c == ' ' || c == '\n') {
 			adj_swid(cadj, charwid(dev_spacewid(), n_s));
 			adj_wb(cadj, wb);
@@ -761,6 +776,8 @@
 		if (c != ' ') {
 			ren_back(c);
 			ren_char(wb, ren_next, ren_back);
+			if (c != '\n' && wb_empty(wb))
+				adj_nonl(cadj);
 		}
 		ren_nl = c == '\n';
 		c = ren_next();
--- a/xroff.h
+++ b/xroff.h
@@ -201,6 +201,7 @@
 void adj_wb(struct adj *adj, struct wb *wb);
 void adj_nl(struct adj *adj);
 void adj_sp(struct adj *adj);
+void adj_nonl(struct adj *adj);
 
 /* rendering */
 void render(void);		/* read from in.c and print the output */