shithub: neatroff

Download patch

ref: 3bb6a7bbeebc83a29b60a83f356e2935af02d992
parent: 7936220f7971f2a34be3a215750626f5e82f2353
author: Ali Gholami Rudi <ali@rudi.ir>
date: Thu Apr 24 08:13:14 EDT 2014

adj: store the words as strings

--- a/adj.c
+++ b/adj.c
@@ -7,7 +7,10 @@
 #define ADJ_LLEN(a)	MAX(0, (a)->ll - (a)->li)
 
 struct adj {
-	struct wb wbs[NWORDS];	/* words in buf */
+	char *words[NWORDS];	/* words to be adjusted */
+	int wids[NWORDS];	/* the width of words */
+	int elsn[NWORDS];	/* els_neg of words */
+	int elsp[NWORDS];	/* els_pos of words */
 	int gaps[NWORDS];	/* gaps before words */
 	int nwords;
 	int wid;		/* total width of buf */
@@ -16,6 +19,7 @@
 	int nls;		/* newlines before the next word */
 	int li, ll;		/* current line indentation and length */
 	int filled;		/* filled all words in the last adj_fill() */
+	int eos;		/* last word ends a sentence */
 };
 
 /* .ll, .in and .ti are delayed until the partial line is output */
@@ -59,15 +63,36 @@
 /* move words inside an adj struct */
 static void adj_movewords(struct adj *a, int dst, int src, int len)
 {
-	memmove(a->wbs + dst, a->wbs + src, len * sizeof(a->wbs[0]));
+	memmove(a->words + dst, a->words + src, len * sizeof(a->words[0]));
+	memmove(a->wids + dst, a->wids + src, len * sizeof(a->wids[0]));
+	memmove(a->elsn + dst, a->elsn + src, len * sizeof(a->elsn[0]));
+	memmove(a->elsp + dst, a->elsp + src, len * sizeof(a->elsp[0]));
 	memmove(a->gaps + dst, a->gaps + src, len * sizeof(a->gaps[0]));
 }
 
+static char *adj_strdup(char *s)
+{
+	int l = strlen(s);
+	char *r = malloc(l + 1);
+	memcpy(r, s, l + 1);
+	return r;
+}
+
+/* copy word buffer wb in adj->words[i] */
+static void adj_word(struct adj *adj, int i, struct wb *wb, int gap)
+{
+	adj->words[i] = adj_strdup(wb_buf(wb));
+	adj->wids[i] = wb_wid(wb);
+	adj->elsn[i] = wb->els_neg;
+	adj->elsp[i] = wb->els_pos;
+	adj->gaps[i] = gap;
+}
+
 static int adj_linewid(struct adj *a, int n)
 {
 	int i, w = 0;
 	for (i = 0; i < n; i++)
-		w += wb_wid(&a->wbs[i]) + a->gaps[i];
+		w += a->wids[i] + a->gaps[i];
 	return w;
 }
 
@@ -75,7 +100,7 @@
 {
 	int i, w = 0;
 	for (i = 0; i < a->nwords; i++) {
-		w += wb_wid(&a->wbs[i]) + a->gaps[i];
+		w += a->wids[i] + a->gaps[i];
 		if (w > llen)
 			return i;
 	}
@@ -85,21 +110,19 @@
 /* move n words from the adjustment buffer to s */
 static int adj_move(struct adj *a, int n, struct sbuf *s, int *els_neg, int *els_pos)
 {
-	struct wb *cur;
 	int w = 0;
 	int i;
 	*els_neg = 0;
 	*els_pos = 0;
 	for (i = 0; i < n; i++) {
-		cur = &a->wbs[i];
 		sbuf_printf(s, "%ch'%du'", c_ec, a->gaps[i]);
-		sbuf_append(s, sbuf_buf(&cur->sbuf));
-		w += wb_wid(cur) + a->gaps[i];
-		if (cur->els_neg < *els_neg)
-			*els_neg = cur->els_neg;
-		if (cur->els_pos > *els_pos)
-			*els_pos = cur->els_pos;
-		wb_done(cur);
+		sbuf_append(s, a->words[i]);
+		w += a->wids[i] + a->gaps[i];
+		if (a->elsn[i] < *els_neg)
+			*els_neg = a->elsn[i];
+		if (a->elsp[i] > *els_pos)
+			*els_pos = a->elsp[i];
+		free(a->words[i]);
 	}
 	if (!n)
 		return 0;
@@ -118,18 +141,16 @@
 	int flg = hyph | (n ? 0 : HY_ANY);
 	wb_init(&w1);
 	wb_init(&w2);
-	if (wb_hyph(&a->wbs[n], w, &w1, &w2, flg)) {
-		wb_done(&w1);
-		wb_done(&w2);
-		return;
+	if (!wb_hyph(a->words[n], w, &w1, &w2, flg)) {
+		adj_movewords(a, n + 2, n + 1, a->nwords - n);
+		free(a->words[n]);
+		adj_word(a, n, &w1, a->gaps[n]);
+		adj_word(a, n + 1, &w2, 0);
+		a->nwords++;
+		a->wid = adj_linewid(a, a->nwords);
 	}
-	adj_movewords(a, n + 2, n + 1, a->nwords - n);
-	wb_done(&a->wbs[n]);
-	memcpy(&a->wbs[n], &w1, sizeof(w1));
-	memcpy(&a->wbs[n + 1], &w2, sizeof(w2));
-	a->nwords++;
-	a->gaps[n + 1] = 0;
-	a->wid = adj_linewid(a, a->nwords);
+	wb_done(&w1);
+	wb_done(&w2);
 }
 
 /* fill and copy a line into s */
@@ -187,21 +208,6 @@
 	adj->nls = 0;
 }
 
-static void adj_word(struct adj *adj, struct wb *wb)
-{
-	int i = adj->nwords++;
-	wb_init(&adj->wbs[i]);
-	adj->gaps[i] = adj->filled ? 0 : adj->gap;
-	adj->filled = 0;
-	adj->wid += wb_wid(wb) + adj->gap;
-	wb_cat(&adj->wbs[i], wb);
-}
-
-static int adj_eos(struct adj *adj)
-{
-	return adj->nwords && wb_eos(&adj->wbs[adj->nwords - 1]);
-}
-
 /* insert wb into the adjustment buffer */
 void adj_wb(struct adj *adj, struct wb *wb)
 {
@@ -210,10 +216,13 @@
 	if (!adj->nwords)	/* apply the new .l and .i */
 		adj_confupdate(adj);
 	if (adj->nls && !adj->gap && adj->nwords >= 1)
-		adj->gap = adj_eos(adj) ? adj->swid * 2 : adj->swid;
-	adj_word(adj, wb);
+		adj->gap = (adj->nwords && adj->eos) ? adj->swid * 2 : adj->swid;
+	adj_word(adj, adj->nwords++, wb, adj->filled ? 0 : adj->gap);
+	adj->filled = 0;
+	adj->wid += adj->wids[adj->nwords - 1] + adj->gaps[adj->nwords - 1];
 	adj->nls = 0;
 	adj->gap = 0;
+	adj->eos = wb_eos(wb);
 }
 
 struct adj *adj_alloc(void)
--- a/ren.c
+++ b/ren.c
@@ -961,6 +961,7 @@
 			adj_swid(cadj, spacewid(n_f, n_s));
 			if (!wb_part(wb)) {	/* not after a \c */
 				adj_wb(cadj, wb);
+				wb_reset(wb);
 				/* wb contains only commands like \f */
 				if (!ren_nl && wb_empty(wb))
 					adj_nonl(cadj);
--- a/roff.h
+++ b/roff.h
@@ -264,7 +264,7 @@
 void wb_italiccorrection(struct wb *wb);
 void wb_italiccorrectionleft(struct wb *wb);
 void wb_cat(struct wb *wb, struct wb *src);
-int wb_hyph(struct wb *wb, int w, struct wb *w1, struct wb *w2, int flg);
+int wb_hyph(char *word, int w, struct wb *w1, struct wb *w2, int flg);
 int wb_wid(struct wb *wb);
 int wb_empty(struct wb *wb);
 int wb_eos(struct wb *wb);
@@ -272,6 +272,8 @@
 		int *llx, int *lly, int *urx, int *ury);
 int wb_lig(struct wb *wb, char *c);
 int wb_kern(struct wb *wb, char *c);
+void wb_reset(struct wb *wb);
+char *wb_buf(struct wb *wb);
 
 /* character translation (.tr) */
 void cmap_add(char *c1, char *c2);
--- a/wb.c
+++ b/wb.c
@@ -319,12 +319,17 @@
 	sbuf_printf(&wb->sbuf, "'");
 }
 
-static void wb_reset(struct wb *wb)
+void wb_reset(struct wb *wb)
 {
 	wb_done(wb);
 	wb_init(wb);
 }
 
+char *wb_buf(struct wb *wb)
+{
+	return sbuf_buf(&wb->sbuf);
+}
+
 static void wb_putc(struct wb *wb, int t, char *s)
 {
 	switch (t) {
@@ -519,22 +524,22 @@
 }
 
 /* hyphenate wb into w1 and w2; return zero on success */
-int wb_hyph(struct wb *wb, int w, struct wb *w1, struct wb *w2, int flg)
+int wb_hyph(char *word, int w, struct wb *w1, struct wb *w2, int flg)
 {
-	char *s = sbuf_buf(&wb->sbuf);
+	char *s = word;
 	char *dp, *hp, *p;
 	if (skipreqs(&s, w1))
 		return 1;
-	dp = bp_pos(sbuf_buf(&wb->sbuf), w, w1, flg);
-	hp = hc_pos(sbuf_buf(&wb->sbuf), w, w1, flg);
+	dp = bp_pos(word, w, w1, flg);
+	hp = hc_pos(word, w, w1, flg);
 	if (hp && dp)
 		p = flg & HY_ANY ? MIN(dp, hp) : MAX(dp, hp);
 	else
 		p = dp ? dp : hp;
 	if (!p && flg & HY_MASK)
-		p = hyphpos(sbuf_buf(&wb->sbuf), w, w1, flg);
+		p = hyphpos(word, w, w1, flg);
 	if (p)
-		dohyph(sbuf_buf(&wb->sbuf), p, p != dp, w1, w2);
+		dohyph(word, p, p != dp, w1, w2);
 	return !p;
 }