shithub: neatroff

Download patch

ref: fa9769a25be700f1aecaeb688f1dd57c9366b87e
parent: a5c5a55a1576bd756d101d529ffd48eaf7d7f975
author: Ali Gholami Rudi <ali@rudi.ir>
date: Sat Sep 21 16:05:18 EDT 2013

hyph: drop non-alpha characters for HY_FIRST2 and HY_FINAL2

This prevents "finally..." from being hyphenated as "final-ly...".

--- a/hyph.c
+++ b/hyph.c
@@ -21,7 +21,7 @@
 
 static void hyph_initpatterns(void);
 static void hyph_initexceptions(void);
-static void hyfind(char *hyph, char *word);
+static void hyfind(char *hyph, char *word, int flg);
 
 static void hyexcept_add(char *s)
 {
@@ -66,7 +66,7 @@
 	return NULL;
 }
 
-void hyphenate(char *hyph, char *word)
+void hyphenate(char *hyph, char *word, int flg)
 {
 	char *r;
 	if (!hyinit) {
@@ -78,7 +78,7 @@
 	if (r)
 		memcpy(hyph, r, strlen(word) + 1);
 	else
-		hyfind(hyph, word);
+		hyfind(hyph, word, flg);
 }
 
 void tr_hw(char **args)
@@ -98,7 +98,7 @@
 	return (HYC_MAP(a) << 5) | HYC_MAP(b);
 }
 
-static void hyfind(char *hyph, char *word)
+static void hyfind(char *hyph, char *word, int flg)
 {
 	char n[ILNLEN] = {0};
 	char w[ILNLEN];
@@ -124,8 +124,11 @@
 				break;
 		}
 	}
-	for (i = 1; i < wlen - 1; i++)
-		hyph[i - 1] = i > 2 && i < wlen - 3 && n[i] % 2;
+	memset(hyph, 0, wlen * sizeof(hyph[0]));
+	for (i = 3; i < wlen - 2; i++)
+		if (n[i] % 2 && w[i - 1] != '.' && w[i - 2] != '.' && w[i + 1] != '.')
+			hyph[i - 1] = (~flg & HY_FINAL2 || w[i + 2] != '.') &&
+				(~flg & HY_FIRST2 || w[i - 3] != '.');
 }
 
 static void hyins(char *s)
--- a/roff.h
+++ b/roff.h
@@ -244,7 +244,7 @@
 #define HY_FIRST2	0x08	/* do not hyphenate the first two characters */
 #define HY_ANY		0x10	/* break at any possible position */
 
-void hyphenate(char *hyphs, char *word);
+void hyphenate(char *hyphs, char *word, int flg);
 
 /* adjustment */
 #define AD_L		0
--- a/wb.c
+++ b/wb.c
@@ -399,35 +399,36 @@
 
 static char *hyphpos(char *s, int w, struct wb *w1, int flg)
 {
-	char *map[ILNLEN] = {NULL};	/* mapping from word to s */
-	int fits[ILNLEN] = {0};		/* fits[i] if word[0..i]- fits w */
-	char word[ILNLEN];
-	char hyph[ILNLEN];
+	char word[ILNLEN];	/* word to pass to hyphenate() */
+	char hyph[ILNLEN];	/* hyphenation points returned from hyphenate() */
+	char *iw[ILNLEN];	/* beginning of i-th char in word */
+	char *is[ILNLEN];	/* beginning of i-th char in s */
+	int fits[ILNLEN];	/* fits[i] is 1, if the first i chars fit w */
+	int n = 0;		/* the number of characters in word */
 	char d[ILNLEN];
 	char *prev_s = s;
 	char *r = NULL;
 	char *wp = word, *we = word + sizeof(word);
-	int beg, end;
 	int i, c;
 	skipreqs(&s, w1);
-	while ((c = escread(&s, d)) >= 0 && wp + strlen(d) + 1 < we) {
+	while ((c = escread(&s, d)) >= 0 && (c > 0 || strlen(d) + 1 < we - wp)) {
+		fits[n] = wb_wid(w1) + wb_dashwid(w1) <= w;
 		wb_putc(w1, c, d);
 		if (c == 0) {
+			iw[n] = wp;
+			is[n] = prev_s;
 			strcpy(wp, d);
-			map[wp - word] = prev_s;
 			wp = strchr(wp, '\0');
-			fits[wp - word] = wb_wid(w1) + wb_dashwid(w1) <= w;
+			n++;
 		}
 		prev_s = s;
 	}
-	if (strlen(word) < 4)
+	if (n < 4)
 		return NULL;
-	hyphenate(hyph, word);
-	beg = flg & HY_FIRST2 ? 3 : 2;
-	end = strlen(word) - (flg & HY_FINAL2 ? 2 : 1);
-	for (i = beg; i < end; i++)
-		if (map[i] && hyph[i] && (fits[i] || ((flg & HY_ANY) && !r)))
-			r = map[i];
+	hyphenate(hyph, word, flg);
+	for (i = 2; i < n - 1; i++)
+		if (hyph[iw[i] - word] && (fits[i] || ((flg & HY_ANY) && !r)))
+			r = is[i];
 	return r;
 }