shithub: neatroff

Download patch

ref: a174597fc92cb42492559805f1e3eb7d85939732
parent: 96f78282dd2aa43bb8cc038cf15cfdf20cd598b9
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sun Dec 14 13:28:37 EST 2014

fmt: more penalty when hyphenating consecutive lines

The .hycost request now takes three arguments: the second specifies
the additional cost of two consecutive hyphenated lines and the third
does so for three consecutive hyphenated lines.

--- a/fmt.c
+++ b/fmt.c
@@ -384,10 +384,20 @@
 	return ratio * ratio / 100l * (nspc ? nspc : 1);
 }
 
+/* the number of hyphenations in consecutive lines ending at pos (2 at most) */
+static int fmt_hydepth(struct fmt *f, int pos)
+{
+	int n = 0;
+	while (pos > 0 && f->words[pos - 1].hy && ++n < 2)
+		pos = f->best_pos[pos];
+	return n;
+}
+
 /* the cost of putting a line break before word pos */
 static long fmt_findcost(struct fmt *f, int pos)
 {
-	int i, pen = 0;
+	int hycost[] = {0, n_hycost2, n_hycost2 + n_hycost3};
+	int i, hyphenated;
 	long cur;
 	int llen = MAX(1, FMT_LLEN(f));
 	int lwid = 0;		/* current line length */
@@ -397,12 +407,9 @@
 		return 0;
 	if (f->best_pos[pos] >= 0)
 		return f->best[pos];
+	lwid = f->words[pos - 1].hy;	/* non-zero if the last word is hyphenated */
+	hyphenated = f->words[pos - 1].hy != 0;
 	i = pos - 1;
-	lwid = 0;
-	if (f->words[i].hy)	/* the last word is hyphenated */
-		lwid += f->words[i].hy;
-	if (f->words[i].hy)
-		pen = n_hycost;
 	while (i >= 0) {
 		lwid += f->words[i].wid;
 		if (i + 1 < pos)
@@ -414,8 +421,9 @@
 		if (lwid - (swid * n_ssh / 100) > llen)
 			if (pos - i > 1)
 				break;
-		cur = fmt_findcost(f, i) + FMT_COST(llen, lwid, swid, nspc) +
-			pen * (nspc ? nspc : 1);
+		cur = fmt_findcost(f, i) + FMT_COST(llen, lwid, swid, nspc);
+		if (hyphenated)
+			cur += n_hycost + hycost[fmt_hydepth(f, i)];
 		if (f->best_pos[pos] < 0 || cur < f->best[pos]) {
 			f->best_pos[pos] = i;
 			f->best_dep[pos] = f->best_dep[i] + 1;
--- a/reg.c
+++ b/reg.c
@@ -37,7 +37,7 @@
 	".L", ".nI", ".nm", ".nM", ".nn",
 	".nS", ".m", ".s", ".u", ".v",
 	".it", ".itn", ".mc", ".mcn",
-	".ce", ".f0", ".hy", ".hycost", ".i0", ".l0",
+	".ce", ".f0", ".hy", ".hycost", ".hycost2",".hycost3",  ".i0", ".l0",
 	".L0", ".m0", ".n0", ".s0", ".ss", ".ssh", ".sss", ".pmll", ".pmllcost",
 	".ti", ".lt", ".lt0", ".v0",
 };
--- a/roff.h
+++ b/roff.h
@@ -465,6 +465,8 @@
 #define n_lg		(*nreg(map(".lg")))	/* .lg mode */
 #define n_hy		(*nreg(map(".hy")))	/* .hy mode */
 #define n_hycost	(*nreg(map(".hycost")))	/* hyphenation cost */
+#define n_hycost2	(*nreg(map(".hycost2")))	/* hyphenation cost #2 */
+#define n_hycost3	(*nreg(map(".hycost3")))	/* hyphenation cost #3 */
 #define n_i0		(*nreg(map(".i0")))	/* last .i */
 #define n_ti		(*nreg(map(".ti")))	/* pending .ti */
 #define n_kn		(*nreg(map(".kn")))	/* .kn mode */
--- a/tr.c
+++ b/tr.c
@@ -462,6 +462,8 @@
 static void tr_hycost(char **args)
 {
 	n_hycost = args[1] ? eval_re(args[1], n_hycost, '\0') : 0;
+	n_hycost2 = args[2] ? eval_re(args[2], n_hycost2, '\0') : 0;
+	n_hycost3 = args[3] ? eval_re(args[3], n_hycost3, '\0') : 0;
 }
 
 static void tr_hydash(char **args)