shithub: neatroff

Download patch

ref: 05ce05cf03e9a81cfa8b65f45e91739d83741fe3
parent: 73e0f630cdbbeb348edeb7eada032b368968b624
author: Ali Gholami Rudi <ali@rudi.ir>
date: Thu May 8 16:24:26 EDT 2014

ren: executing traps while half of an input line is read

The old scheme did not work well while formatting whole paragraphs.

--- a/fmt.c
+++ b/fmt.c
@@ -49,6 +49,7 @@
 	/* current line */
 	int gap;		/* space before the next word */
 	int nls;		/* newlines before the next word */
+	int nls_sup;		/* suppressed newlines */
 	int li, ll;		/* current line indentation and length */
 	int filled;		/* filled all words in the last fmt_fill() */
 	int eos;		/* last word ends a sentence */
@@ -170,6 +171,7 @@
 		return 1;
 	f->filled = 0;
 	f->nls--;
+	f->nls_sup = 0;
 	l->wid = fmt_wordscopy(f, 0, f->nwords, &l->sbuf, &l->elsn, &l->elsp);
 	f->nwords = 0;
 	f->fillreq = 0;
@@ -265,24 +267,33 @@
 	wb_done(&wbc);
 }
 
+/* the amount of space necessary before the next word */
+static int fmt_wordgap(struct fmt *f)
+{
+	if ((f->nls || f->nls_sup) && !f->gap && f->nwords >= 1)
+		return (f->nwords && f->eos) ? FMT_SWID(f) * 2 : FMT_SWID(f);
+	return f->gap;
+}
+
 /* insert wb into fmt */
 int fmt_word(struct fmt *f, struct wb *wb)
 {
+	if (wb_empty(wb))
+		return 0;
 	if (f->nwords + NHYPHS >= NWORDS || fmt_confchanged(f))
 		if (fmt_fill(f))
 			return 1;
-	if (wb_empty(wb))
-		return 0;
 	if (FMT_FILL(f) && f->nls && f->gap)
-		fmt_sp(f);
+		if (fmt_sp(f))
+			return 1;
 	if (!f->nwords)		/* apply the new .l and .i */
 		fmt_confupdate(f);
-	if (f->nls && !f->gap && f->nwords >= 1)
-		f->gap = (f->nwords && f->eos) ? FMT_SWID(f) * 2 : FMT_SWID(f);
+	f->gap = fmt_wordgap(f);
 	f->eos = wb_eos(wb);
 	fmt_insertword(f, wb, f->filled ? 0 : f->gap);
 	f->filled = 0;
 	f->nls = 0;
+	f->nls_sup = 0;
 	f->gap = 0;
 	return 0;
 }
@@ -468,8 +479,7 @@
 
 int fmt_wid(struct fmt *fmt)
 {
-	return fmt_wordslen(fmt, 0, fmt->nwords) +
-		(fmt->nls ? FMT_SWID(fmt) : fmt->gap);
+	return fmt_wordslen(fmt, 0, fmt->nwords) + fmt_wordgap(fmt);
 }
 
 int fmt_morewords(struct fmt *fmt)
@@ -480,4 +490,13 @@
 int fmt_morelines(struct fmt *fmt)
 {
 	return fmt->l_head != fmt->l_tail;
+}
+
+/* suppress the last newline */
+void fmt_suppressnl(struct fmt *fmt)
+{
+	if (fmt->nls) {
+		fmt->nls--;
+		fmt->nls_sup = 1;
+	}
 }
--- a/ren.c
+++ b/ren.c
@@ -26,8 +26,8 @@
 static int trap_em = -1;	/* end macro */
 
 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_nl;		/* just after a newline */
+static int ren_partial;		/* reading an input line in render_rec() */
 static int ren_unbuf[8];	/* ren_back() buffer */
 static int ren_un;
 static int ren_aborted;		/* .ab executed */
@@ -140,12 +140,14 @@
 		trap_exec(trap_reg(-1));
 }
 
-static void ren_first(void)
+static int ren_first(void)
 {
 	if (bp_first && !cdiv) {
 		bp_first = 0;
 		ren_page(bp_next, 1);
+		return 0;
 	}
+	return 1;
 }
 
 /* when nodiv, do not append .sp to diversions */
@@ -170,11 +172,15 @@
 static void trap_exec(int reg)
 {
 	char cmd[16];
+	int partial = ren_partial;
 	if (str_get(reg)) {
 		sprintf(cmd, "%c%s %d\n", c_cc, TR_POPREN, ren_level);
 		in_pushnl(cmd, NULL);
 		in_pushnl(str_get(reg), NULL);
 		render_rec(++ren_level);
+		/* executed the trap while in the middle of an input line */
+		if (partial)
+			fmt_suppressnl(cfmt);
 	}
 }
 
@@ -310,7 +316,6 @@
 static int ren_line(char *line, int w, int ad, int body,
 		int li, int ll, int els_neg, int els_pos)
 {
-	char cmd[16];
 	struct sbuf sbeg, send;
 	int prev_d, lspc, ljust;
 	ren_first();
@@ -336,11 +341,8 @@
 		ren_sp(els_pos, 1);
 	n_a = els_pos;
 	if (detect_traps(prev_d, n_d) || detect_pagelimit(lspc - n_v)) {
-		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 - n_v);
+		if (!ren_pagelimit(lspc - n_v))
+			ren_traps(prev_d, n_d, 0);
 		return 1;
 	}
 	if (lspc - n_v && down(lspc - n_v))
@@ -453,6 +455,8 @@
 void tr_ne(char **args)
 {
 	int n = args[1] ? eval(args[1], 'v') : n_v;
+	if (!ren_first())
+		return;
 	if (!ren_traps(n_d, n_d + n - 1, 1))
 		ren_pagelimit(n);
 }
@@ -955,20 +959,21 @@
 			}
 		}
 		if (c >= 0)
-			ren_cnl = c == '\n';
+			ren_partial = c != '\n';
 		/* add wb (the current word) to cfmt */
 		if (c == ' ' || c == '\n') {
 			if (!wb_part(wb)) {	/* not after a \c */
 				while (fmt_word(cfmt, wb))
 					ren_fmtpop(cfmt);
+				wb_reset(wb);
 				if (c == '\n')
 					while (fmt_newline(cfmt))
 						ren_fmtpop(cfmt);
-				if (c == ' ')
-					fmt_space(cfmt);
-				wb_reset(wb);
 				if (!(n_j & AD_P))
 					ren_fmtpopall(cfmt);
+				ren_fmtpop(cfmt);
+				if (c == ' ')
+					fmt_space(cfmt);
 			}
 		}
 		/* flush the line if necessary */
--- a/roff.h
+++ b/roff.h
@@ -309,6 +309,7 @@
 void fmt_free(struct fmt *fmt);
 int fmt_wid(struct fmt *fmt);
 void fmt_space(struct fmt *fmt);
+void fmt_suppressnl(struct fmt *fmt);
 int fmt_word(struct fmt *fmt, struct wb *wb);
 int fmt_newline(struct fmt *fmt);
 int fmt_fillreq(struct fmt *f);