shithub: neatroff

Download patch

ref: b01175229102277d71f34c45c8360a0426c094bf
parent: ba2d79127881030e079be609d77df850b660dd2d
author: Ali Gholami Rudi <ali@rudi.ir>
date: Tue Jul 1 20:16:30 EDT 2014

hyph: .hcode request

--- a/hyph.c
+++ b/hyph.c
@@ -7,6 +7,8 @@
 
 #define HYPATLEN	(NHYPHS * 16)	/* hyphenation pattern length */
 
+static int hcode_mapchar(char *s);
+
 /* the hyphenation dictionary (.hw) */
 
 static char hwword[HYPATLEN];	/* buffer for .hw words */
@@ -40,25 +42,35 @@
 	dict_put(&hwdict, hwword + hwoff[i], i);
 }
 
-/* copy lower-cased s to d */
-static void hw_strcpy(char *d, char *s)
+/* copy s to d after .hcode mappings; s[map[j]] corresponds to d[j] */
+static void hw_strcpy(char *d, char *s, int *map)
 {
-	while (*s) {
-		if (*s & 0x80)
-			*d++ = *s++;
-		else
-			*d++ = tolower(*s++);
+	int di = 0, si = 0, len;
+	while (s[si]) {
+		len = utf8len((unsigned char) s[si]);
+		map[di] = si;
+		memcpy(d + di, s + si, len);
+		si += len;
+		di += hcode_mapchar(d + di);
 	}
-	*d = '\0';
+	d[di] = '\0';
 }
 
-static char *hw_lookup(char *s)
+static int hw_lookup(char *word, char *hyph)
 {
-	char word[ILNLEN];
-	int i, idx = -1;
-	hw_strcpy(word, s);
-	i = dict_prefix(&hwdict, s, &idx);
-	return i >= 0 ? hwhyph + hwoff[i] : NULL;
+	char word2[WORDLEN] = {0};
+	char *hyph2;
+	int map[WORDLEN] = {0};
+	int i, j, idx = -1;
+	hw_strcpy(word2, word, map);
+	i = dict_prefix(&hwdict, word2, &idx);
+	if (i < 0)
+		return 1;
+	hyph2 = hwhyph + hwoff[i];
+	for (j = 0; word2[j]; j++)
+		if (hyph2[j])
+			hyph[map[j]] = hyph2[j];
+	return 0;
 }
 
 void tr_hw(char **args)
@@ -78,15 +90,20 @@
 static int hyoff[NHYPHS];	/* the offset of this pattern in hypats[] */
 static int hy_n;		/* number of words in hy_*[] lists */
 
-/* make s lower-case and replace its non-alphabetic characters with . */
-static void hy_strcpy(char *d, char *s)
+/* copy s to d after .hcode mappings; s[map[j]] corresponds to d[j] */
+static void hy_strcpy(char *d, char *s, int *map)
 {
-	int c;
-	*d++ = '.';
-	while ((c = (unsigned char) *s++))
-		*d++ = c & 0x80 ? c : (isalpha(c) ? tolower(c) : '.');
-	*d++ = '.';
-	*d = '\0';
+	int di = 0, si = 0, len;
+	d[di++] = '.';
+	while (s[si]) {
+		len = utf8len((unsigned char) s[si]);
+		map[di] = si;
+		memcpy(d + di, s + si, len);
+		si += len;
+		di += hcode_mapchar(d + di);
+	}
+	d[di++] = '.';
+	d[di] = '\0';
 }
 
 /* find the patterns matching s and update hyphenation values in n */
@@ -109,12 +126,13 @@
 /* mark the hyphenation points of word in hyph */
 static void hy_dohyph(char *hyph, char *word, int flg)
 {
-	char n[ILNLEN] = {0};
-	char w[ILNLEN];
-	int c[ILNLEN];	/* start of the i-th character in w */
+	char n[WORDLEN] = {0};
+	char w[WORDLEN] = {0};
+	int c[WORDLEN];			/* start of the i-th character in w */
+	int wmap[WORDLEN] = {0};	/* word[wmap[i]] is w[i] */
 	int nc = 0;
 	int i, wlen;
-	hy_strcpy(w, word);
+	hy_strcpy(w, word, wmap);
 	wlen = strlen(w);
 	for (i = 0; i < wlen - 1; i += utf8len((unsigned int) w[i]))
 		c[nc++] = i;
@@ -123,12 +141,12 @@
 	memset(hyph, 0, wlen * sizeof(hyph[0]));
 	for (i = 3; i < nc - 2; i++)
 		if (n[i] % 2 && w[c[i - 1]] != '.' && w[c[i - 2]] != '.' && w[c[i + 1]] != '.')
-			hyph[c[i - 1]] = (~flg & HY_FINAL2 || w[c[i + 2]] != '.') &&
+			hyph[wmap[c[i]]] = (~flg & HY_FINAL2 || w[c[i + 2]] != '.') &&
 				(~flg & HY_FIRST2 || w[c[i - 3]] != '.');
 }
 
 /* insert pattern s into hypats[] and hynums[] */
-static void hy_ins(char *s)
+static void hy_add(char *s)
 {
 	char *p = hypats + hypats_len;
 	char *n = hynums + hypats_len;
@@ -148,9 +166,38 @@
 	hypats_len += i + 1;
 }
 
+/* .hcode request */
+static struct dict hcodedict;
+static char hcodesrc[NHCODES][GNLEN];
+static char hcodedst[NHCODES][GNLEN];
+static int hcode_n;
+
+/* replace the character in s after .hcode mapping; returns s's new length */
+static int hcode_mapchar(char *s)
+{
+	int i = dict_get(&hcodedict, s);
+	if (i >= 0)
+		strcpy(s, hcodedst[i]);
+	else if (isalpha((unsigned char) *s))
+		*s = tolower(*s);
+	return strlen(s);
+}
+
+void tr_hcode(char **args)
+{
+	int i = 1;
+	while (args[i] && args[i + 1] && hcode_n < NHCODES) {
+		strcpy(hcodesrc[hcode_n], args[i]);
+		strcpy(hcodedst[hcode_n], args[i + 1]);
+		dict_put(&hcodedict, hcodesrc[hcode_n], hcode_n);
+		hcode_n++;
+		i += 2;
+	}
+}
+
 static void hyph_readpatterns(char *s)
 {
-	char word[ILNLEN];
+	char word[WORDLEN];
 	char *d;
 	while (*s) {
 		d = word;
@@ -157,7 +204,7 @@
 		while (*s && !isspace((unsigned char) *s))
 			*d++ = *s++;
 		*d = '\0';
-		hy_ins(word);
+		hy_add(word);
 		while (*s && isspace((unsigned char) *s))
 			s++;
 	}
@@ -165,7 +212,7 @@
 
 static void hyph_readexceptions(char *s)
 {
-	char word[ILNLEN];
+	char word[WORDLEN];
 	char *d;
 	while (*s) {
 		d = word;
@@ -180,16 +227,12 @@
 
 void hyphenate(char *hyph, char *word, int flg)
 {
-	char *r;
 	if (!hyinit) {
 		hyinit = 1;
 		hyph_readpatterns(en_patterns);
 		hyph_readexceptions(en_exceptions);
 	}
-	r = hw_lookup(word);
-	if (r)
-		memcpy(hyph, r, strlen(word) + 1);
-	else
+	if (hw_lookup(word, hyph))
 		hy_dohyph(hyph, word, flg);
 }
 
@@ -202,7 +245,8 @@
 		hyinit = 1;
 		filp = fopen(args[1], "r");
 		while (fscanf(filp, "%s", tok) == 1)
-			hy_ins(tok);
+			if (strlen(tok) < WORDLEN)
+				hy_add(tok);
 		fclose(filp);
 	}
 	/* reading exceptions */
@@ -209,7 +253,8 @@
 	if (args[2]) {
 		filp = fopen(args[1], "r");
 		while (fscanf(filp, "%s", tok) == 1)
-			hw_add(tok);
+			if (strlen(tok) < WORDLEN)
+				hw_add(tok);
 		fclose(filp);
 	}
 }
@@ -218,6 +263,7 @@
 {
 	dict_init(&hwdict, NHYPHS, -1, 0, 1);
 	dict_init(&hydict, NHYPHS, -1, 0, 1);
+	dict_init(&hcodedict, NHYPHS, -1, 0, 1);
 }
 
 void tr_hpf(char **args)
--- a/roff.h
+++ b/roff.h
@@ -50,6 +50,8 @@
 #define NCDEFS		128	/* number of character definitions (.char) */
 #define NHYPHS		16384	/* hyphenation dictionary/patterns (.hw) */
 #define NHYPHSWORD	16	/* number of hyphenations per word */
+#define NHCODES		512	/* number of .hcode characters */
+#define WORDLEN		256	/* word length (for hyph.c) */
 
 /* converting scales */
 #define SC_IN		(dev_res)	/* inch in units */
@@ -380,6 +382,7 @@
 void tr_fp(char **args);
 void tr_fspecial(char **args);
 void tr_ft(char **args);
+void tr_hcode(char **args);
 void tr_hpf(char **args);
 void tr_hpfa(char **args);
 void tr_hw(char **args);
--- a/tr.c
+++ b/tr.c
@@ -878,6 +878,7 @@
 	{"fspecial", tr_fspecial},
 	{"ft", tr_ft},
 	{"hc", tr_hc},
+	{"hcode", tr_hcode},
 	{"hpf", tr_hpf},
 	{"hpfa", tr_hpfa},
 	{"hy", tr_hy},
--- a/wb.c
+++ b/wb.c
@@ -461,10 +461,10 @@
 /* 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() */
-	char *iw[ILNLEN];	/* beginning of i-th char in word */
-	char *is[ILNLEN];	/* beginning of i-th char in s */
+	char word[WORDLEN];	/* word to pass to hyphenate() */
+	char hyph[WORDLEN];	/* hyphenation points returned from hyphenate() */
+	char *iw[WORDLEN];	/* beginning of i-th char in word */
+	char *is[WORDLEN];	/* beginning of i-th char in s */
 	int n = 0;		/* the number of characters in word */
 	int nhy = 0;		/* number of hyphenations found */
 	char d[ILNLEN];
@@ -492,6 +492,7 @@
 	wb_done(&wb);
 	if (n < 3)
 		return 0;
+	memset(hyph, 0, (wp - word) * sizeof(hyph[0]));
 	hyphenate(hyph, word, flg);
 	for (i = 1; i < n - 1 && nhy < NHYPHSWORD; i++)
 		if (hyph[iw[i] - word])