1219b2ee8SDavid du Colombier #include <u.h>
2219b2ee8SDavid du Colombier #include <libc.h>
3219b2ee8SDavid du Colombier #include <bio.h>
4219b2ee8SDavid du Colombier #include "dict.h"
5219b2ee8SDavid du Colombier
6219b2ee8SDavid du Colombier Dict dicts[] = {
7219b2ee8SDavid du Colombier {"oed", "Oxford English Dictionary, 2nd Ed.",
8219b2ee8SDavid du Colombier "/lib/dict/oed2", "/lib/dict/oed2index",
9219b2ee8SDavid du Colombier oednextoff, oedprintentry, oedprintkey},
10219b2ee8SDavid du Colombier {"ahd", "American Heritage Dictionary, 2nd College Ed.",
11219b2ee8SDavid du Colombier "/lib/ahd/DICT.DB", "/lib/ahd/index",
12219b2ee8SDavid du Colombier ahdnextoff, ahdprintentry, ahdprintkey},
13705edaf8SDavid du Colombier {"pgw", "Project Gutenberg Webster Dictionary",
14705edaf8SDavid du Colombier "/lib/dict/pgw", "/lib/dict/pgwindex",
15705edaf8SDavid du Colombier pgwnextoff, pgwprintentry, pgwprintkey},
16219b2ee8SDavid du Colombier {"thesaurus", "Collins Thesaurus",
17219b2ee8SDavid du Colombier "/lib/dict/thesaurus", "/lib/dict/thesindex",
18219b2ee8SDavid du Colombier thesnextoff, thesprintentry, thesprintkey},
19119a69faSDavid du Colombier {"roget", "Project Gutenberg Roget's Thesaurus",
20119a69faSDavid du Colombier "/lib/dict/roget", "/lib/dict/rogetindex",
21119a69faSDavid du Colombier rogetnextoff, rogetprintentry, rogetprintkey},
22219b2ee8SDavid du Colombier
23219b2ee8SDavid du Colombier {"ce", "Gendai Chinese->English",
24219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic24.dat",
25219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/ceindex",
26219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
27219b2ee8SDavid du Colombier {"ceh", "Gendai Chinese->English (Hanzi index)",
28219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic24.dat",
29219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/cehindex",
30219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
31219b2ee8SDavid du Colombier {"ec", "Gendai English->Chinese",
32219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic24.dat",
33219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/ecindex",
34219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
35219b2ee8SDavid du Colombier
36219b2ee8SDavid du Colombier {"dae", "Gyldendal Danish->English",
37219b2ee8SDavid du Colombier "/lib/dict/world/gylddata/sandic30.dat",
38219b2ee8SDavid du Colombier "/lib/dict/world/gylddata/daeindex",
39219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
40219b2ee8SDavid du Colombier {"eda", "Gyldendal English->Danish",
41219b2ee8SDavid du Colombier "/lib/dict/world/gylddata/sandic29.dat",
42219b2ee8SDavid du Colombier "/lib/dict/world/gylddata/edaindex",
43219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
44219b2ee8SDavid du Colombier
45219b2ee8SDavid du Colombier {"due", "Wolters-Noordhoff Dutch->English",
46219b2ee8SDavid du Colombier "/lib/dict/world/woltdata/sandic07.dat",
47219b2ee8SDavid du Colombier "/lib/dict/world/woltdata/deindex",
48219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
49219b2ee8SDavid du Colombier {"edu", "Wolters-Noordhoff English->Dutch",
50219b2ee8SDavid du Colombier "/lib/dict/world/woltdata/sandic06.dat",
51219b2ee8SDavid du Colombier "/lib/dict/world/woltdata/edindex",
52219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
53219b2ee8SDavid du Colombier
54219b2ee8SDavid du Colombier {"fie", "WSOY Finnish->English",
55219b2ee8SDavid du Colombier "/lib/dict/world/werndata/sandic32.dat",
56219b2ee8SDavid du Colombier "/lib/dict/world/werndata/fieindex",
57219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
58219b2ee8SDavid du Colombier {"efi", "WSOY English->Finnish",
59219b2ee8SDavid du Colombier "/lib/dict/world/werndata/sandic31.dat",
60219b2ee8SDavid du Colombier "/lib/dict/world/werndata/efiindex",
61219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
62219b2ee8SDavid du Colombier
63219b2ee8SDavid du Colombier {"fe", "Collins French->English",
64219b2ee8SDavid du Colombier "/lib/dict/fe", "/lib/dict/feindex",
65219b2ee8SDavid du Colombier pcollnextoff, pcollprintentry, pcollprintkey},
66219b2ee8SDavid du Colombier {"ef", "Collins English->French",
67219b2ee8SDavid du Colombier "/lib/dict/ef", "/lib/dict/efindex",
68219b2ee8SDavid du Colombier pcollnextoff, pcollprintentry, pcollprintkey},
69219b2ee8SDavid du Colombier
70219b2ee8SDavid du Colombier {"ge", "Collins German->English",
71219b2ee8SDavid du Colombier "/lib/dict/ge", "/lib/dict/geindex",
72219b2ee8SDavid du Colombier pcollgnextoff, pcollgprintentry, pcollgprintkey},
73219b2ee8SDavid du Colombier {"eg", "Collins English->German",
74219b2ee8SDavid du Colombier "/lib/dict/eg", "/lib/dict/egindex",
75219b2ee8SDavid du Colombier pcollgnextoff, pcollgprintentry, pcollgprintkey},
76219b2ee8SDavid du Colombier
77219b2ee8SDavid du Colombier {"ie", "Collins Italian->English",
78219b2ee8SDavid du Colombier "/lib/dict/ie", "/lib/dict/ieindex",
79219b2ee8SDavid du Colombier pcollnextoff, pcollprintentry, pcollprintkey},
80219b2ee8SDavid du Colombier {"ei", "Collins English->Italian",
81219b2ee8SDavid du Colombier "/lib/dict/ei", "/lib/dict/eiindex",
82219b2ee8SDavid du Colombier pcollnextoff, pcollprintentry, pcollprintkey},
83219b2ee8SDavid du Colombier
84219b2ee8SDavid du Colombier {"je", "Sanshusha Japanese->English",
85219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic18.dat",
86219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/jeindex",
87219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
88219b2ee8SDavid du Colombier {"jek", "Sanshusha Japanese->English (Kanji index)",
89219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic18.dat",
90219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/jekindex",
91219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
92219b2ee8SDavid du Colombier {"ej", "Sanshusha English->Japanese",
93219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic18.dat",
94219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/ejindex",
95219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
96219b2ee8SDavid du Colombier
97219b2ee8SDavid du Colombier {"tjeg", "Sanshusha technical Japanese->English,German",
98219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic16.dat",
99219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/tjegindex",
100219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
101219b2ee8SDavid du Colombier {"tjegk", "Sanshusha technical Japanese->English,German (Kanji index)",
102219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic16.dat",
103219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/tjegkindex",
104219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
105219b2ee8SDavid du Colombier {"tegj", "Sanshusha technical English->German,Japanese",
106219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic16.dat",
107219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/tegjindex",
108219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
109219b2ee8SDavid du Colombier {"tgje", "Sanshusha technical German->Japanese,English",
110219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/sandic16.dat",
111219b2ee8SDavid du Colombier "/lib/dict/world/sansdata/tgjeindex",
112219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
113219b2ee8SDavid du Colombier
114219b2ee8SDavid du Colombier {"ne", "Kunnskapforlaget Norwegian->English",
115219b2ee8SDavid du Colombier "/lib/dict/world/kunndata/sandic28.dat",
116219b2ee8SDavid du Colombier "/lib/dict/world/kunndata/neindex",
117219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
118219b2ee8SDavid du Colombier {"en", "Kunnskapforlaget English->Norwegian",
119219b2ee8SDavid du Colombier "/lib/dict/world/kunndata/sandic27.dat",
120219b2ee8SDavid du Colombier "/lib/dict/world/kunndata/enindex",
121219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
122219b2ee8SDavid du Colombier
123219b2ee8SDavid du Colombier {"re", "Leon Ungier Russian->English",
124219b2ee8SDavid du Colombier "/lib/dict/re", "/lib/dict/reindex",
125219b2ee8SDavid du Colombier simplenextoff, simpleprintentry, simpleprintkey},
126219b2ee8SDavid du Colombier {"er", "Leon Ungier English->Russian",
127219b2ee8SDavid du Colombier "/lib/dict/re", "/lib/dict/erindex",
128219b2ee8SDavid du Colombier simplenextoff, simpleprintentry, simpleprintkey},
129219b2ee8SDavid du Colombier
130219b2ee8SDavid du Colombier {"se", "Collins Spanish->English",
131219b2ee8SDavid du Colombier "/lib/dict/se", "/lib/dict/seindex",
132219b2ee8SDavid du Colombier pcollnextoff, pcollprintentry, pcollprintkey},
133219b2ee8SDavid du Colombier {"es", "Collins English->Spanish",
134219b2ee8SDavid du Colombier "/lib/dict/es", "/lib/dict/esindex",
135219b2ee8SDavid du Colombier pcollnextoff, pcollprintentry, pcollprintkey},
136219b2ee8SDavid du Colombier
137219b2ee8SDavid du Colombier {"swe", "Esselte Studium Swedish->English",
138219b2ee8SDavid du Colombier "/lib/dict/world/essedata/sandic34.dat",
139219b2ee8SDavid du Colombier "/lib/dict/world/essedata/sweindex",
140219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
141219b2ee8SDavid du Colombier {"esw", "Esselte Studium English->Swedish",
142219b2ee8SDavid du Colombier "/lib/dict/world/essedata/sandic33.dat",
143219b2ee8SDavid du Colombier "/lib/dict/world/essedata/eswindex",
144219b2ee8SDavid du Colombier worldnextoff, worldprintentry, worldprintkey},
145219b2ee8SDavid du Colombier
146219b2ee8SDavid du Colombier {"movie", "Movies -- by title",
147219b2ee8SDavid du Colombier "/lib/movie/data", "/lib/dict/movtindex",
148219b2ee8SDavid du Colombier movienextoff, movieprintentry, movieprintkey},
149219b2ee8SDavid du Colombier {"moviea", "Movies -- by actor",
150219b2ee8SDavid du Colombier "/lib/movie/data", "/lib/dict/movaindex",
151219b2ee8SDavid du Colombier movienextoff, movieprintentry, movieprintkey},
152219b2ee8SDavid du Colombier {"movied", "Movies -- by director",
153219b2ee8SDavid du Colombier "/lib/movie/data", "/lib/dict/movdindex",
154219b2ee8SDavid du Colombier movienextoff, movieprintentry, movieprintkey},
155219b2ee8SDavid du Colombier
156219b2ee8SDavid du Colombier {"slang", "English Slang",
157219b2ee8SDavid du Colombier "/lib/dict/slang", "/lib/dict/slangindex",
158219b2ee8SDavid du Colombier slangnextoff, slangprintentry, slangprintkey},
159219b2ee8SDavid du Colombier
160219b2ee8SDavid du Colombier {"robert", "Robert Électronique",
161219b2ee8SDavid du Colombier "/lib/dict/robert/_pointers", "/lib/dict/robert/_index",
162219b2ee8SDavid du Colombier robertnextoff, robertindexentry, robertprintkey},
163219b2ee8SDavid du Colombier {"robertv", "Robert Électronique - formes des verbes",
164219b2ee8SDavid du Colombier "/lib/dict/robert/flex.rob", "/lib/dict/robert/_flexindex",
165219b2ee8SDavid du Colombier robertnextflex, robertflexentry, robertprintkey},
166219b2ee8SDavid du Colombier
167219b2ee8SDavid du Colombier {0, 0, 0, 0, 0}
168219b2ee8SDavid du Colombier };
169219b2ee8SDavid du Colombier
170219b2ee8SDavid du Colombier typedef struct Lig Lig;
171219b2ee8SDavid du Colombier struct Lig {
172219b2ee8SDavid du Colombier Rune start; /* accent rune */
173219b2ee8SDavid du Colombier Rune *pairs; /* <char,accented version> pairs */
174219b2ee8SDavid du Colombier };
175219b2ee8SDavid du Colombier
176219b2ee8SDavid du Colombier static Lig ligtab[Nligs] = {
177219b2ee8SDavid du Colombier [LACU-LIGS] {L'´', L"AÁaáCĆcćEÉeégģIÍiíıíLĹlĺNŃnńOÓoóRŔrŕSŚsśUÚuúYÝyýZŹzź"},
178219b2ee8SDavid du Colombier [LGRV-LIGS] {L'ˋ', L"AÀaàEÈeèIÌiìıìOÒoòUÙuù"},
179219b2ee8SDavid du Colombier [LUML-LIGS] {L'¨', L"AÄaäEËeëIÏiïOÖoöUÜuüYŸyÿ"},
180219b2ee8SDavid du Colombier [LCED-LIGS] {L'¸', L"CÇcçGĢKĶkķLĻlļNŅnņRŖrŗSŞsşTŢtţ"},
181219b2ee8SDavid du Colombier [LTIL-LIGS] {L'˜', L"AÃaãIĨiĩıĩNÑnñOÕoõUŨuũ"},
182219b2ee8SDavid du Colombier [LBRV-LIGS] {L'˘', L"AĂaăEĔeĕGĞgğIĬiĭıĭOŎoŏUŬuŭ"},
183219b2ee8SDavid du Colombier [LRNG-LIGS] {L'˚', L"AÅaåUŮuů"},
184219b2ee8SDavid du Colombier [LDOT-LIGS] {L'˙', L"CĊcċEĖeėGĠgġIİLĿlŀZŻzż"},
185219b2ee8SDavid du Colombier [LDTB-LIGS] {L'.', L""},
186219b2ee8SDavid du Colombier [LFRN-LIGS] {L'⌢', L"AÂaâCĈcĉEÊeêGĜgĝHĤhĥIÎiîıîJĴjĵOÔoôSŜsŝUÛuûWŴwŵYŶyŷ"},
187219b2ee8SDavid du Colombier [LFRB-LIGS] {L'̯', L""},
188219b2ee8SDavid du Colombier [LOGO-LIGS] {L'˛', L"AĄaąEĘeęIĮiįıįUŲuų"},
189219b2ee8SDavid du Colombier [LMAC-LIGS] {L'¯', L"AĀaāEĒeēIĪiīıīOŌoōUŪuū"},
190219b2ee8SDavid du Colombier [LHCK-LIGS] {L'ˇ', L"CČcčDĎdďEĚeěLĽlľNŇnňRŘrřSŠsšTŤtťZŽzž"},
191219b2ee8SDavid du Colombier [LASP-LIGS] {L'ʽ', L""},
192219b2ee8SDavid du Colombier [LLEN-LIGS] {L'ʼ', L""},
193219b2ee8SDavid du Colombier [LBRB-LIGS] {L'̮', L""}
194219b2ee8SDavid du Colombier };
195219b2ee8SDavid du Colombier
196219b2ee8SDavid du Colombier Rune *multitab[Nmulti] = {
197219b2ee8SDavid du Colombier [MAAS-MULTI] L"ʽα",
198219b2ee8SDavid du Colombier [MALN-MULTI] L"ʼα",
199219b2ee8SDavid du Colombier [MAND-MULTI] L"and",
200219b2ee8SDavid du Colombier [MAOQ-MULTI] L"a/q",
201219b2ee8SDavid du Colombier [MBRA-MULTI] L"<|",
202219b2ee8SDavid du Colombier [MDD-MULTI] L"..",
203219b2ee8SDavid du Colombier [MDDD-MULTI] L"...",
204219b2ee8SDavid du Colombier [MEAS-MULTI] L"ʽε",
205219b2ee8SDavid du Colombier [MELN-MULTI] L"ʼε",
206219b2ee8SDavid du Colombier [MEMM-MULTI] L"——",
207219b2ee8SDavid du Colombier [MHAS-MULTI] L"ʽη",
208219b2ee8SDavid du Colombier [MHLN-MULTI] L"ʼη",
209219b2ee8SDavid du Colombier [MIAS-MULTI] L"ʽι",
210219b2ee8SDavid du Colombier [MILN-MULTI] L"ʼι",
211219b2ee8SDavid du Colombier [MLCT-MULTI] L"ct",
212219b2ee8SDavid du Colombier [MLFF-MULTI] L"ff",
213219b2ee8SDavid du Colombier [MLFFI-MULTI] L"ffi",
214219b2ee8SDavid du Colombier [MLFFL-MULTI] L"ffl",
215219b2ee8SDavid du Colombier [MLFL-MULTI] L"fl",
216219b2ee8SDavid du Colombier [MLFI-MULTI] L"fi",
217219b2ee8SDavid du Colombier [MLLS-MULTI] L"ɫɫ",
218219b2ee8SDavid du Colombier [MLST-MULTI] L"st",
219219b2ee8SDavid du Colombier [MOAS-MULTI] L"ʽο",
220219b2ee8SDavid du Colombier [MOLN-MULTI] L"ʼο",
221219b2ee8SDavid du Colombier [MOR-MULTI] L"or",
222219b2ee8SDavid du Colombier [MRAS-MULTI] L"ʽρ",
223219b2ee8SDavid du Colombier [MRLN-MULTI] L"ʼρ",
224219b2ee8SDavid du Colombier [MTT-MULTI] L"~~",
225219b2ee8SDavid du Colombier [MUAS-MULTI] L"ʽυ",
226219b2ee8SDavid du Colombier [MULN-MULTI] L"ʼυ",
227219b2ee8SDavid du Colombier [MWAS-MULTI] L"ʽω",
228219b2ee8SDavid du Colombier [MWLN-MULTI] L"ʼω",
229219b2ee8SDavid du Colombier [MOE-MULTI] L"oe",
230219b2ee8SDavid du Colombier [MES-MULTI] L" ",
231219b2ee8SDavid du Colombier };
232219b2ee8SDavid du Colombier
233219b2ee8SDavid du Colombier static Rune *ttabstack[20];
234219b2ee8SDavid du Colombier static int ntt;
235219b2ee8SDavid du Colombier
236219b2ee8SDavid du Colombier /*
237219b2ee8SDavid du Colombier * tab is an array of n Assoc's, sorted by key.
238219b2ee8SDavid du Colombier * Look for key in tab, and return corresponding val
239219b2ee8SDavid du Colombier * or -1 if not there
240219b2ee8SDavid du Colombier */
241219b2ee8SDavid du Colombier long
lookassoc(Assoc * tab,int n,char * key)242219b2ee8SDavid du Colombier lookassoc(Assoc *tab, int n, char *key)
243219b2ee8SDavid du Colombier {
244219b2ee8SDavid du Colombier Assoc *q;
245219b2ee8SDavid du Colombier long i, low, high;
246219b2ee8SDavid du Colombier int r;
247219b2ee8SDavid du Colombier
248219b2ee8SDavid du Colombier for(low = -1, high = n; high > low+1; ){
249219b2ee8SDavid du Colombier i = (high+low)/2;
250219b2ee8SDavid du Colombier q = &tab[i];
251219b2ee8SDavid du Colombier if((r=strcmp(key, q->key))<0)
252219b2ee8SDavid du Colombier high = i;
253219b2ee8SDavid du Colombier else if(r == 0)
254219b2ee8SDavid du Colombier return q->val;
255219b2ee8SDavid du Colombier else
256219b2ee8SDavid du Colombier low=i;
257219b2ee8SDavid du Colombier }
258219b2ee8SDavid du Colombier return -1;
259219b2ee8SDavid du Colombier }
260219b2ee8SDavid du Colombier
261219b2ee8SDavid du Colombier long
looknassoc(Nassoc * tab,int n,long key)262219b2ee8SDavid du Colombier looknassoc(Nassoc *tab, int n, long key)
263219b2ee8SDavid du Colombier {
264219b2ee8SDavid du Colombier Nassoc *q;
265219b2ee8SDavid du Colombier long i, low, high;
266219b2ee8SDavid du Colombier
267219b2ee8SDavid du Colombier for(low = -1, high = n; high > low+1; ){
268219b2ee8SDavid du Colombier i = (high+low)/2;
269219b2ee8SDavid du Colombier q = &tab[i];
270219b2ee8SDavid du Colombier if(key < q->key)
271219b2ee8SDavid du Colombier high = i;
272219b2ee8SDavid du Colombier else if(key == q->key)
273219b2ee8SDavid du Colombier return q->val;
274219b2ee8SDavid du Colombier else
275219b2ee8SDavid du Colombier low=i;
276219b2ee8SDavid du Colombier }
277219b2ee8SDavid du Colombier return -1;
278219b2ee8SDavid du Colombier }
279219b2ee8SDavid du Colombier
280219b2ee8SDavid du Colombier void
err(char * fmt,...)281219b2ee8SDavid du Colombier err(char *fmt, ...)
282219b2ee8SDavid du Colombier {
283219b2ee8SDavid du Colombier char buf[1000];
284219b2ee8SDavid du Colombier va_list v;
285219b2ee8SDavid du Colombier
286219b2ee8SDavid du Colombier va_start(v, fmt);
2879a747e4fSDavid du Colombier vsnprint(buf, sizeof(buf), fmt, v);
288219b2ee8SDavid du Colombier va_end(v);
289219b2ee8SDavid du Colombier fprint(2, "%s: %s\n", argv0, buf);
290219b2ee8SDavid du Colombier }
291219b2ee8SDavid du Colombier
292219b2ee8SDavid du Colombier /*
293219b2ee8SDavid du Colombier * Write the rune r to bout, keeping track of line length
294219b2ee8SDavid du Colombier * and breaking the lines (at blanks) when they get too long
295219b2ee8SDavid du Colombier */
296219b2ee8SDavid du Colombier void
outrune(long r)297219b2ee8SDavid du Colombier outrune(long r)
298219b2ee8SDavid du Colombier {
299219b2ee8SDavid du Colombier if(outinhibit)
300219b2ee8SDavid du Colombier return;
301219b2ee8SDavid du Colombier if(++linelen > breaklen && r == L' ') {
302219b2ee8SDavid du Colombier Bputc(bout, '\n');
303219b2ee8SDavid du Colombier linelen = 0;
304219b2ee8SDavid du Colombier } else
305219b2ee8SDavid du Colombier Bputrune(bout, r);
306219b2ee8SDavid du Colombier }
307219b2ee8SDavid du Colombier
308219b2ee8SDavid du Colombier void
outrunes(Rune * rp)309219b2ee8SDavid du Colombier outrunes(Rune *rp)
310219b2ee8SDavid du Colombier {
311219b2ee8SDavid du Colombier Rune r;
312219b2ee8SDavid du Colombier
313219b2ee8SDavid du Colombier while((r = *rp++) != 0)
314219b2ee8SDavid du Colombier outrune(r);
315219b2ee8SDavid du Colombier }
316219b2ee8SDavid du Colombier
317219b2ee8SDavid du Colombier /* like outrune, but when arg is know to be a char */
318219b2ee8SDavid du Colombier void
outchar(int c)319219b2ee8SDavid du Colombier outchar(int c)
320219b2ee8SDavid du Colombier {
321219b2ee8SDavid du Colombier if(outinhibit)
322219b2ee8SDavid du Colombier return;
323219b2ee8SDavid du Colombier if(++linelen > breaklen && c == ' ') {
324219b2ee8SDavid du Colombier c ='\n';
325219b2ee8SDavid du Colombier linelen = 0;
326219b2ee8SDavid du Colombier }
3277dd7cddfSDavid du Colombier Bputc(bout, c);
328219b2ee8SDavid du Colombier }
329219b2ee8SDavid du Colombier
330219b2ee8SDavid du Colombier void
outchars(char * s)331219b2ee8SDavid du Colombier outchars(char *s)
332219b2ee8SDavid du Colombier {
333219b2ee8SDavid du Colombier char c;
334219b2ee8SDavid du Colombier
335219b2ee8SDavid du Colombier while((c = *s++) != 0)
336219b2ee8SDavid du Colombier outchar(c);
337219b2ee8SDavid du Colombier }
338219b2ee8SDavid du Colombier
339219b2ee8SDavid du Colombier void
outprint(char * fmt,...)340219b2ee8SDavid du Colombier outprint(char *fmt, ...)
341219b2ee8SDavid du Colombier {
342219b2ee8SDavid du Colombier char buf[1000];
343219b2ee8SDavid du Colombier va_list v;
344219b2ee8SDavid du Colombier
345219b2ee8SDavid du Colombier va_start(v, fmt);
3469a747e4fSDavid du Colombier vsnprint(buf, sizeof(buf), fmt, v);
347219b2ee8SDavid du Colombier va_end(v);
348219b2ee8SDavid du Colombier outchars(buf);
349219b2ee8SDavid du Colombier }
350219b2ee8SDavid du Colombier
351219b2ee8SDavid du Colombier void
outpiece(char * b,char * e)352219b2ee8SDavid du Colombier outpiece(char *b, char *e)
353219b2ee8SDavid du Colombier {
354219b2ee8SDavid du Colombier int c, lastc;
355219b2ee8SDavid du Colombier
356219b2ee8SDavid du Colombier lastc = 0;
357219b2ee8SDavid du Colombier while(b < e) {
358219b2ee8SDavid du Colombier c = *b++;
359219b2ee8SDavid du Colombier if(c == '\n')
360219b2ee8SDavid du Colombier c = ' ';
361219b2ee8SDavid du Colombier if(!(c == ' ' && lastc == ' '))
362219b2ee8SDavid du Colombier outchar(c);
363219b2ee8SDavid du Colombier lastc = c;
364219b2ee8SDavid du Colombier }
365219b2ee8SDavid du Colombier }
366219b2ee8SDavid du Colombier
367219b2ee8SDavid du Colombier /*
368219b2ee8SDavid du Colombier * Go to new line if not already there; indent if ind != 0.
369219b2ee8SDavid du Colombier * If ind > 1, leave a blank line too.
370219b2ee8SDavid du Colombier * Slight hack: assume if current line is only one or two
371219b2ee8SDavid du Colombier * characters long, then they were spaces.
372219b2ee8SDavid du Colombier */
373219b2ee8SDavid du Colombier void
outnl(int ind)374219b2ee8SDavid du Colombier outnl(int ind)
375219b2ee8SDavid du Colombier {
376219b2ee8SDavid du Colombier if(outinhibit)
377219b2ee8SDavid du Colombier return;
378219b2ee8SDavid du Colombier if(ind) {
379219b2ee8SDavid du Colombier if(ind > 1) {
380219b2ee8SDavid du Colombier if(linelen > 2)
381219b2ee8SDavid du Colombier Bputc(bout, '\n');
382219b2ee8SDavid du Colombier Bprint(bout, "\n ");
383219b2ee8SDavid du Colombier } else if(linelen == 0)
384219b2ee8SDavid du Colombier Bprint(bout, " ");
385219b2ee8SDavid du Colombier else if(linelen == 1)
386219b2ee8SDavid du Colombier Bputc(bout, ' ');
387219b2ee8SDavid du Colombier else if(linelen != 2)
388219b2ee8SDavid du Colombier Bprint(bout, "\n ");
389219b2ee8SDavid du Colombier linelen = 2;
390219b2ee8SDavid du Colombier } else {
391219b2ee8SDavid du Colombier if(linelen) {
392219b2ee8SDavid du Colombier Bputc(bout, '\n');
393219b2ee8SDavid du Colombier linelen = 0;
394219b2ee8SDavid du Colombier }
395219b2ee8SDavid du Colombier }
396219b2ee8SDavid du Colombier }
397219b2ee8SDavid du Colombier
398219b2ee8SDavid du Colombier /*
399219b2ee8SDavid du Colombier * Fold the runes in null-terminated rp.
400219b2ee8SDavid du Colombier * Use the sort(1) definition of folding (uppercase to lowercase,
401*eaba85aaSDavid du Colombier * accented characters to corresponding unaccented chars)
402219b2ee8SDavid du Colombier */
403219b2ee8SDavid du Colombier void
fold(Rune * rp)404219b2ee8SDavid du Colombier fold(Rune *rp)
405219b2ee8SDavid du Colombier {
406219b2ee8SDavid du Colombier Rune r;
407219b2ee8SDavid du Colombier
408219b2ee8SDavid du Colombier while((r = *rp) != 0) {
409*eaba85aaSDavid du Colombier r = tobaserune(r);
410*eaba85aaSDavid du Colombier if(isupperrune(r))
411*eaba85aaSDavid du Colombier r = tolowerrune(r);
412219b2ee8SDavid du Colombier *rp++ = r;
413219b2ee8SDavid du Colombier }
414219b2ee8SDavid du Colombier }
415219b2ee8SDavid du Colombier
416219b2ee8SDavid du Colombier /*
417219b2ee8SDavid du Colombier * Like fold, but put folded result into new
418219b2ee8SDavid du Colombier * (assumed to have enough space).
419219b2ee8SDavid du Colombier * old is a regular expression, but we know that
420219b2ee8SDavid du Colombier * metacharacters aren't affected
421219b2ee8SDavid du Colombier */
422219b2ee8SDavid du Colombier void
foldre(char * new,char * old)423219b2ee8SDavid du Colombier foldre(char *new, char *old)
424219b2ee8SDavid du Colombier {
425219b2ee8SDavid du Colombier Rune r;
426219b2ee8SDavid du Colombier
427219b2ee8SDavid du Colombier while(*old) {
428219b2ee8SDavid du Colombier old += chartorune(&r, old);
429*eaba85aaSDavid du Colombier r = tobaserune(r);
430*eaba85aaSDavid du Colombier if(isupperrune(r))
431*eaba85aaSDavid du Colombier r = tolowerrune(r);
432219b2ee8SDavid du Colombier new += runetochar(new, &r);
433219b2ee8SDavid du Colombier }
434219b2ee8SDavid du Colombier *new = 0;
435219b2ee8SDavid du Colombier }
436219b2ee8SDavid du Colombier
437219b2ee8SDavid du Colombier /*
438219b2ee8SDavid du Colombier * acomp(s, t) returns:
439219b2ee8SDavid du Colombier * -2 if s strictly precedes t
440219b2ee8SDavid du Colombier * -1 if s is a prefix of t
441219b2ee8SDavid du Colombier * 0 if s is the same as t
442219b2ee8SDavid du Colombier * 1 if t is a prefix of s
443219b2ee8SDavid du Colombier * 2 if t strictly precedes s
444219b2ee8SDavid du Colombier */
445219b2ee8SDavid du Colombier
446219b2ee8SDavid du Colombier int
acomp(Rune * s,Rune * t)447219b2ee8SDavid du Colombier acomp(Rune *s, Rune *t)
448219b2ee8SDavid du Colombier {
449219b2ee8SDavid du Colombier int cs, ct;
450219b2ee8SDavid du Colombier
451219b2ee8SDavid du Colombier for(;;) {
452219b2ee8SDavid du Colombier cs = *s;
453219b2ee8SDavid du Colombier ct = *t;
454219b2ee8SDavid du Colombier if(cs != ct)
455219b2ee8SDavid du Colombier break;
456219b2ee8SDavid du Colombier if(cs == 0)
457219b2ee8SDavid du Colombier return 0;
458219b2ee8SDavid du Colombier s++;
459219b2ee8SDavid du Colombier t++;
460219b2ee8SDavid du Colombier }
461219b2ee8SDavid du Colombier if(cs == 0)
462219b2ee8SDavid du Colombier return -1;
463219b2ee8SDavid du Colombier if(ct == 0)
464219b2ee8SDavid du Colombier return 1;
465219b2ee8SDavid du Colombier if(cs < ct)
466219b2ee8SDavid du Colombier return -2;
467219b2ee8SDavid du Colombier return 2;
468219b2ee8SDavid du Colombier }
469219b2ee8SDavid du Colombier
470219b2ee8SDavid du Colombier /*
471219b2ee8SDavid du Colombier * Copy null terminated Runes from 'from' to 'to'.
472219b2ee8SDavid du Colombier */
473219b2ee8SDavid du Colombier void
runescpy(Rune * to,Rune * from)474219b2ee8SDavid du Colombier runescpy(Rune *to, Rune *from)
475219b2ee8SDavid du Colombier {
476219b2ee8SDavid du Colombier while((*to++ = *from++) != 0)
477219b2ee8SDavid du Colombier continue;
478219b2ee8SDavid du Colombier }
479219b2ee8SDavid du Colombier
480219b2ee8SDavid du Colombier /*
481219b2ee8SDavid du Colombier * Conversion of unsigned number to long, no overflow detection
482219b2ee8SDavid du Colombier */
483219b2ee8SDavid du Colombier long
runetol(Rune * r)484219b2ee8SDavid du Colombier runetol(Rune *r)
485219b2ee8SDavid du Colombier {
486219b2ee8SDavid du Colombier int c;
487219b2ee8SDavid du Colombier long n;
488219b2ee8SDavid du Colombier
489219b2ee8SDavid du Colombier n = 0;
490219b2ee8SDavid du Colombier for(;; r++){
491219b2ee8SDavid du Colombier c = *r;
492219b2ee8SDavid du Colombier if(L'0'<=c && c<=L'9')
493219b2ee8SDavid du Colombier c -= '0';
494219b2ee8SDavid du Colombier else
495219b2ee8SDavid du Colombier break;
496219b2ee8SDavid du Colombier n = n*10 + c;
497219b2ee8SDavid du Colombier }
498219b2ee8SDavid du Colombier return n;
499219b2ee8SDavid du Colombier }
500219b2ee8SDavid du Colombier
501219b2ee8SDavid du Colombier /*
502219b2ee8SDavid du Colombier * See if there is a rune corresponding to the accented
503219b2ee8SDavid du Colombier * version of r with accent acc (acc in [LIGS..LIGE-1]),
504219b2ee8SDavid du Colombier * and return it if so, else return NONE.
505219b2ee8SDavid du Colombier */
506219b2ee8SDavid du Colombier Rune
liglookup(Rune acc,Rune r)507219b2ee8SDavid du Colombier liglookup(Rune acc, Rune r)
508219b2ee8SDavid du Colombier {
509219b2ee8SDavid du Colombier Rune *p;
510219b2ee8SDavid du Colombier
511219b2ee8SDavid du Colombier if(acc < LIGS || acc >= LIGE)
512219b2ee8SDavid du Colombier return NONE;
513219b2ee8SDavid du Colombier for(p = ligtab[acc-LIGS].pairs; *p; p += 2)
514219b2ee8SDavid du Colombier if(*p == r)
515219b2ee8SDavid du Colombier return *(p+1);
516219b2ee8SDavid du Colombier return NONE;
517219b2ee8SDavid du Colombier }
518219b2ee8SDavid du Colombier
519219b2ee8SDavid du Colombier /*
520219b2ee8SDavid du Colombier * Maintain a translation table stack (a translation table
521219b2ee8SDavid du Colombier * is an array of Runes indexed by bytes or 7-bit bytes).
522219b2ee8SDavid du Colombier * If starting is true, push the curtab onto the stack
523219b2ee8SDavid du Colombier * and return newtab; else pop the top of the stack and
524219b2ee8SDavid du Colombier * return it.
525219b2ee8SDavid du Colombier * If curtab is 0, initialize the stack and return.
526219b2ee8SDavid du Colombier */
527219b2ee8SDavid du Colombier Rune *
changett(Rune * curtab,Rune * newtab,int starting)528219b2ee8SDavid du Colombier changett(Rune *curtab, Rune *newtab, int starting)
529219b2ee8SDavid du Colombier {
530219b2ee8SDavid du Colombier if(curtab == 0) {
531219b2ee8SDavid du Colombier ntt = 0;
532219b2ee8SDavid du Colombier return 0;
533219b2ee8SDavid du Colombier }
534219b2ee8SDavid du Colombier if(starting) {
535219b2ee8SDavid du Colombier if(ntt >= asize(ttabstack)) {
536219b2ee8SDavid du Colombier if(debug)
537219b2ee8SDavid du Colombier err("translation stack overflow");
538219b2ee8SDavid du Colombier return curtab;
539219b2ee8SDavid du Colombier }
540219b2ee8SDavid du Colombier ttabstack[ntt++] = curtab;
541219b2ee8SDavid du Colombier return newtab;
542219b2ee8SDavid du Colombier } else {
543219b2ee8SDavid du Colombier if(ntt == 0) {
544219b2ee8SDavid du Colombier if(debug)
545219b2ee8SDavid du Colombier err("translation stack underflow");
546219b2ee8SDavid du Colombier return curtab;
547219b2ee8SDavid du Colombier }
548219b2ee8SDavid du Colombier return ttabstack[--ntt];
549219b2ee8SDavid du Colombier }
550219b2ee8SDavid du Colombier }
551