1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include "dict.h"
5 
6 /*
7  * American Heritage Dictionary (encrypted)
8  */
9 
10 static Rune intab[256];
11 
12 static void
initintab(void)13 initintab(void)
14 {
15 	intab[0x82] =  0xe9;
16 	intab[0x85] =  0xe0;
17 	intab[0x89] =  0xeb;
18 	intab[0x8a] =  0xe8;
19 	intab[0xa4] =  0xf1;
20 	intab[0xf8] =  0xb0;
21 	intab[0xf9] =  0xb7;
22 }
23 
24 static char	tag[64];
25 
26 enum{
27 	Run, Openper, Openat, Closeat
28 };
29 
30 void
ahdprintentry(Entry e,int cmd)31 ahdprintentry(Entry e, int cmd)
32 {
33 	static int inited;
34 	long addr;
35 	char *p, *t = tag;
36 	int obreaklen;
37 	int c, state = Run;
38 
39 	if(!inited){
40 		initintab();
41 		for(c=0; c<256; c++)
42 			if(intab[c] == 0)
43 				intab[c] = c;
44 		inited = 1;
45 	}
46 	obreaklen = breaklen;
47 	breaklen = 80;
48 	addr = e.doff;
49 	for(p=e.start; p<e.end; p++){
50 		c = intab[(*p ^ (addr++>>1))&0xff];
51 		switch(state){
52 		case Run:
53 			if(c == '%'){
54 				t = tag;
55 				state = Openper;
56 				break;
57 			}
58 		Putchar:
59 			if(c == '\n')
60 				outnl(0);
61 			else if(c < Runeself)
62 				outchar(c);
63 			else
64 				outrune(c);
65 			break;
66 
67 		case Openper:
68 			if(c == '@')
69 				state = Openat;
70 			else{
71 				outchar('%');
72 				state = Run;
73 				goto Putchar;
74 			}
75 			break;
76 
77 		case Openat:
78 			if(c == '@')
79 				state = Closeat;
80 			else if(t < &tag[sizeof tag-1])
81 				*t++ = c;
82 			break;
83 
84 		case Closeat:
85 			if(c == '%'){
86 				*t = 0;
87 				switch(cmd){
88 				case 'h':
89 					if(strcmp("EH", tag) == 0)
90 						goto out;
91 					break;
92 				case 'r':
93 					outprint("%%@%s@%%", tag);
94 					break;
95 				}
96 				state = Run;
97 			}else{
98 				if(t < &tag[sizeof tag-1])
99 					*t++ = '@';
100 				if(t < &tag[sizeof tag-1])
101 					*t++ = c;
102 				state = Openat;
103 			}
104 			break;
105 		}
106 	}
107 out:
108 	outnl(0);
109 	breaklen = obreaklen;
110 }
111 
112 long
ahdnextoff(long fromoff)113 ahdnextoff(long fromoff)
114 {
115 	static char *patterns[] = { "%@NL@%", "%@2@%", 0 };
116 	int c, k = 0, state = 0;
117 	char *pat = patterns[0];
118 	long defoff = -1;
119 
120 	if(Bseek(bdict, fromoff, 0) < 0)
121 		return -1;
122 	while((c = Bgetc(bdict)) >= 0){
123 		c ^= (fromoff++>>1)&0xff;
124 		if(c != pat[state]){
125 			state = 0;
126 			continue;
127 		}
128 		if(pat[++state])
129 			continue;
130 		if(pat = patterns[++k]){	/* assign = */
131 			state = 0;
132 			defoff = fromoff-6;
133 			continue;
134 		}
135 		return fromoff-5;
136 	}
137 	return defoff;
138 }
139 
140 void
ahdprintkey(void)141 ahdprintkey(void)
142 {
143 	Bprint(bout, "No pronunciations.\n");
144 }
145