shithub: neatroff

Download patch

ref: ebce0cd6c0ceacec630657ae14df6f6110ce0d28
parent: 8cf75f23fe223588cbd8e30f302bf77b766511bc
author: Ali Gholami Rudi <ali@rudi.ir>
date: Thu May 1 07:43:00 EDT 2014

fmt: preserve current font and size when hyphenating

--- a/fmt.c
+++ b/fmt.c
@@ -205,36 +205,51 @@
 	}
 }
 
-/* copy word buffer wb in fmt->words[i] */
+static void fmt_wb2word(struct fmt *f, struct word *word, struct wb *wb,
+			int hy, int str, int gap)
+{
+	int len = strlen(wb_buf(wb));
+	word->s = malloc(len + 1);
+	memcpy(word->s, wb_buf(wb), len + 1);
+	word->wid = wb_wid(wb);
+	word->elsn = wb->els_neg;
+	word->elsp = wb->els_pos;
+	word->hy = hy ? wb_dashwid(wb) : 0;
+	word->str = str;
+	word->gap = gap;
+}
+
 static void fmt_insertword(struct fmt *f, struct wb *wb, int gap)
 {
 	int hyidx[NHYPHS];
-	int hywid[NHYPHS];
-	int hydash[NHYPHS];
-	struct word *w;
-	char *beg, *end;
+	int hyins[NHYPHS] = {0};
 	char *src = wb_buf(wb);
+	struct wb wbc;
+	char *beg;
+	char *end;
 	int n, i;
-	n = wb_hyph(src, hyidx, hywid, hydash, n_hy);
+	int cf, cs, cm;
+	int hy = 0;		/* insert hyphens */
+	n = wb_hyphmark(src, hyidx, hyins);
+	if (!n && n_hy && (n = wb_hyph(src, hyidx, n_hy)) > 0)
+		hy = 1;
+	if (n <= 0) {
+		fmt_wb2word(f, &f->words[f->nwords++], wb, 0, 1, gap);
+		return;
+	}
+	wb_init(&wbc);
 	for (i = 0; i <= n; i++) {
-		w = &f->words[f->nwords++];
 		beg = src + (i > 0 ? hyidx[i - 1] : 0);
 		end = src + (i < n ? hyidx[i] : strlen(src));
-		w->s = malloc(end - beg + 1);
-		memcpy(w->s, beg, end - beg);
-		w->s[end - beg] = '\0';
-		if (n) {
-			w->wid = (i < n ? hywid[i] : wb_wid(wb)) -
-				(i > 0 ? hywid[i - 1] : 0);
-		} else {
-			w->wid = wb_wid(wb);
-		}
-		w->elsn = wb->els_neg;
-		w->elsp = wb->els_pos;
-		w->hy = i < n ? hydash[i] : 0;
-		w->str = i == 0;
-		w->gap = i == 0 ? gap : 0;
+		wb_catstr(&wbc, beg, end);
+		fmt_wb2word(f, &f->words[f->nwords++], &wbc,
+			i < n && (hy || hyins[i]), i == 0, i == 0 ? gap : 0);
+		/* restoring wbc */
+		wb_fnszget(&wbc, &cs, &cf, &cm);
+		wb_reset(&wbc);
+		wb_fnszset(&wbc, cs, cf, cm);
 	}
+	wb_done(&wbc);
 }
 
 /* insert wb into fmt */
--- a/roff.h
+++ b/roff.h
@@ -266,8 +266,11 @@
 void wb_italiccorrection(struct wb *wb);
 void wb_italiccorrectionleft(struct wb *wb);
 void wb_cat(struct wb *wb, struct wb *src);
-int wb_hyph(char *word, int *hyidx, int *hywid, int *hydash, int flg);
+void wb_catstr(struct wb *wb, char *beg, char *end);
+int wb_hyphmark(char *word, int *hyidx, int *hyins);
+int wb_hyph(char *word, int *hyidx, int flg);
 int wb_wid(struct wb *wb);
+int wb_dashwid(struct wb *wb);
 int wb_empty(struct wb *wb);
 int wb_eos(struct wb *wb);
 void wb_wconf(struct wb *wb, int *ct, int *st, int *sb,
@@ -276,6 +279,8 @@
 int wb_kern(struct wb *wb, char *c);
 void wb_reset(struct wb *wb);
 char *wb_buf(struct wb *wb);
+void wb_fnszget(struct wb *wb, int *fn, int *sz, int *m);
+void wb_fnszset(struct wb *wb, int fn, int sz, int m);
 
 /* character translation (.tr) */
 void cmap_add(char *c1, char *c2);
--- a/wb.c
+++ b/wb.c
@@ -416,9 +416,11 @@
 	char d[ILNLEN];
 	char *r = *s;
 	int c;
-	wb_reset(w1);
+	if (w1)
+		wb_reset(w1);
 	while ((c = escread(s, d)) > 0) {
-		wb_putc(w1, c, d);
+		if (w1)
+			wb_putc(w1, c, d);
 		r = *s;
 	}
 	if (c < 0 || !strcmp(c_hc, d))
@@ -427,43 +429,37 @@
 	return 0;
 }
 
-static int wb_dashwid(struct wb *wb)
+/* return the size of \(hy if appended to wb */
+int wb_dashwid(struct wb *wb)
 {
 	struct glyph *g = dev_glyph("hy", R_F(wb));
 	return charwid(R_F(wb), R_S(wb), g ? g->wid : 0);
 }
 
-/* find the positions marked with dashes, hyphens or \: */
-static int dashpos(char *word, int *hyidx, int *hywid, int *hydash, int flg)
+/* find explicit hyphenation positions: dashes, \: and \% */
+int wb_hyphmark(char *word, int *hyidx, int *hyins)
 {
 	char d[ILNLEN];
-	struct wb wb;
 	char *s = word;
-	int n = 0;
-	int c;
-	wb_init(&wb);
-	skipreqs(&s, &wb);
+	int c, n = 0;
+	if (skipreqs(&s, NULL))
+		return -1;
 	while ((c = escread(&s, d)) >= 0 && n < NHYPHS) {
-		wb_putc(&wb, c, d);
-		if (c)
-			continue;
-		hyidx[n] = s - word;
-		hywid[n] = wb_wid(&wb);
-		hydash[n] = 0;
-		if (!strcmp("-", d) || (!strcmp("em", d) ||
-				!strcmp("hy", d)) || !strcmp(c_bp, d)) {
-			n++;
+		if (!c && !strcmp(c_hc, d)) {
+			hyins[n] = 1;
+			hyidx[n++] = s - word;
 		}
-		if (!strcmp(c_hc, d)) {
-			hydash[n] = wb_dashwid(&wb);
-			n++;
+		if (!c && (!strcmp(c_bp, d) || !strcmp("-", d) ||
+				(!strcmp("em", d) || !strcmp("hy", d)))) {
+			hyins[n] = 0;
+			hyidx[n++] = s - word;
 		}
 	}
-	wb_done(&wb);
 	return n;
 }
 
-static int hyphpos(char *src, int *hyidx, int *hywid, int *hydash, int flg)
+/* find the hyphenation positions of the given word */
+int wb_hyph(char *src, int *hyidx, int flg)
 {
 	char word[ILNLEN];	/* word to pass to hyphenate() */
 	char hyph[ILNLEN];	/* hyphenation points returned from hyphenate() */
@@ -470,8 +466,6 @@
 	char *iw[ILNLEN];	/* beginning of i-th char in word */
 	char *is[ILNLEN];	/* beginning of i-th char in s */
 	int n = 0;		/* the number of characters in word */
-	int sw[ILNLEN];		/* dash width at i-th char in word */
-	int dw[ILNLEN];		/* dash width at i-th char in word */
 	int nhy = 0;		/* number of hyphenations found */
 	char d[ILNLEN];
 	struct wb wb;
@@ -486,8 +480,6 @@
 		if (c == 0) {
 			iw[n] = wp;
 			is[n] = prev_s;
-			dw[n] = wb_dashwid(&wb);
-			sw[n] = wb_wid(&wb);
 			/* ignore multi-char aliases except for ligatures */
 			if (!utf8one(d) && !font_islig(dev_font(R_F(&wb)), d))
 				strcpy(d, ".");
@@ -501,33 +493,12 @@
 	if (n < 3)
 		return 0;
 	hyphenate(hyph, word, flg);
-	for (i = 1; i < n - 1 && nhy < NHYPHS; i++) {
-		if (hyph[iw[i] - word]) {
-			hyidx[nhy] = is[i] - src;
-			hywid[nhy] = sw[i - 1];
-			hydash[nhy] = dw[i];
-			nhy++;
-		}
-	}
+	for (i = 1; i < n - 1 && nhy < NHYPHS; i++)
+		if (hyph[iw[i] - word])
+			hyidx[nhy++] = is[i] - src;
 	return nhy;
 }
 
-int wb_hyph(char *word, int *hyidx, int *hywid, int *hydash, int flg)
-{
-	char *s = word;
-	struct wb wb;
-	int n;
-	wb_init(&wb);
-	if (skipreqs(&s, &wb)) {
-		wb_done(&wb);
-		return 0;
-	}
-	wb_done(&wb);
-	if ((n = dashpos(word, hyidx, hywid, hydash, flg)))
-		return n;
-	return flg ? hyphpos(word, hyidx, hywid, hydash, flg) : 0;
-}
-
 void wb_italiccorrection(struct wb *wb)
 {
 	struct glyph *g = wb_prevglyph(wb);
@@ -538,4 +509,26 @@
 void wb_italiccorrectionleft(struct wb *wb)
 {
 	wb->icleft_ll = sbuf_len(&wb->sbuf);
+}
+
+void wb_fnszget(struct wb *wb, int *fn, int *sz, int *m)
+{
+	*fn = wb->r_f;
+	*sz = wb->r_s;
+	*m = wb->r_m;
+}
+
+void wb_fnszset(struct wb *wb, int fn, int sz, int m)
+{
+	wb->r_f = fn;
+	wb->r_s = sz;
+	wb->r_m = m;
+}
+
+void wb_catstr(struct wb *wb, char *s, char *end)
+{
+	char d[ILNLEN];
+	int c;
+	while (s < end && (c = escread(&s, d)) >= 0)
+		wb_putc(wb, c, d);
 }