1 /* Copyright (C) 2000-2012 by George Williams */
2 /*
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions are met:
5 
6  * Redistributions of source code must retain the above copyright notice, this
7  * list of conditions and the following disclaimer.
8 
9  * Redistributions in binary form must reproduce the above copyright notice,
10  * this list of conditions and the following disclaimer in the documentation
11  * and/or other materials provided with the distribution.
12 
13  * The name of the author may not be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15 
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <fontforge-config.h>
29 
30 #include "utype.c"
31 #include "utype.h"
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 
37 #define ACUTE		0x1
38 #define GRAVE		0x2
39 #define DIAERESIS	0x4
40 #define CIRCUMFLEX	0x8
41 #define TILDE		0x10
42 #define RING		0x20
43 #define SLASH		0x40
44 #define BREVE		0x80
45 #define CARON		0x100
46 #define DOTABOVE	0x200
47 #define DOTBELOW	0x400
48 #define CEDILLA		0x800
49 #define OGONEK		0x1000
50 #define MACRON		0x2000
51 #define DBLGRAVE	0x4000
52 #define DBLACUTE	0x8000
53 #define INVBREVE	0x10000
54 #define DIAERESISBELOW	0x20000
55 #define CIRCUMFLEXBELOW	0x40000
56 #define TILDEBELOW	0x80000
57 #define RINGBELOW	0x100000
58 #define LINEBELOW	0x200000
59 #define HOOKABOVE	0x400000
60 #define HORN		0x800000
61 
62 #define GREEK		0x8000000
63 
64 #define ANY		(0xfffffff)
65 
66 struct names { char *name; int mask; } names[] = {
67     {"ACUTE", 0x1},
68     {"GRAVE", 0x2},
69     {"DIAERESIS", 0x4},
70     {"CIRCUMFLEX", 0x8},
71     {"TILDE", 0x10},
72     {"RING", 0x20},
73     {"SLASH", 0x40},
74     {"BREVE", 0x80},
75     {"CARON", 0x100},
76     {"DOTABOVE", 0x200},
77     {"DOTBELOW", 0x400},
78     {"CEDILLA", 0x800},
79     {"OGONEK", 0x1000},
80     {"MACRON", 0x2000},
81     {"DBLGRAVE", 0x4000},
82     {"DBLACUTE", 0x8000},
83     {"INVBREVE", 0x10000},
84     {"DIAERESISBELOW", 0x20000},
85     {"CIRCUMFLEXBELOW", 0x40000},
86     {"TILDEBELOW", 0x80000},
87     {"RINGBELOW", 0x100000},
88     {"LINEBELOW", 0x200000},
89     {"HOOKABOVE", 0x400000},
90     {"HORN",  0x800000},
91     {"GREEK", 0x8000000},
92     {NULL}};
93 
94 struct names names2[] = {
95     {"ACUTE", 0x1},
96     {"GRAVE", 0x2},
97     {"DIAERESIS BELOW", 0x20000},
98     {"DIAERESIS", 0x4},
99     {"CIRCUMFLEX BELOW", 0x40000},
100     {"CIRCUMFLEX", 0x8},
101     {"TILDE BELOW", 0x80000},
102     {"TILDE", 0x10},
103     {"RING ABOVE", 0x20},
104     {"RING BELOW", 0x100000},
105     {"STROKE", 0x40},
106     {"SLASH", 0x40},
107     {"BREVE", 0x80},
108     {"CARON", 0x100},
109     {"DOT ABOVE", 0x200},
110     {"MIDDLE DOT", 0x200},
111     {"DOT BELOW", 0x400},
112     {"CEDILLA", 0x800},
113     {"OGONEK", 0x1000},
114     {"MACRON", 0x2000},
115     {"DOUBLE GRAVE", 0x4000},
116     {"DOUBLE ACUTE", 0x8000},
117     {"INVERTED BREVE", 0x10000},
118     {"LINE BELOW", 0x200000},
119     {"HOOK ABOVE", 0x400000},
120     {"HORN",  0x800000},
121     {NULL}};
122 
123 char *charnames[] = {
124 /* 0x0020 */	"space","exclam","quotedbl","numbersign","dollar","percent","ampersand","quotesingle",
125 /* 0x0028 */	"parenleft","parenright","asterisk","plus","comma","hyphenminus","period","slash",
126 /* 0x0030 */	"zero","one","two","three","four","five","six","seven",
127 /* 0x0038 */	"eight","nine","colon","semicolon","less","equal","greater","question",
128 /* 0x0040 */	"at","A","B","C","D","E","F","G",
129 /* 0x0048 */	"H","I","J","K","L","M","N","O",
130 /* 0x0050 */	"P","Q","R","S","T","U","V","W",
131 /* 0x0058 */	"X","Y","Z","bracketleft","backslash","bracketright","asciicircum","underscore",
132 /* 0x0060 */	"grave","a","b","c","d","e","f","g",
133 /* 0x0068 */	"h","i","j","k","l","m","n","o",
134 /* 0x0070 */	"p","q","r","s","t","u","v","w",
135 /* 0x0078 */	"x","y","z","braceleft","bar","braceright","asciitilde"
136 };
137 
138 struct { char ch; unsigned int oldstate, newstate; unsigned short result; }
139     predefined[] = {
140 	{ '\'', ANY, ACUTE },
141 	{ 'e', 0, ACUTE },
142 	{ '`', ANY, GRAVE },
143 	{ ':', ANY, DIAERESIS },
144 	{ 'u', 0, DIAERESIS },
145 	{ '^', ANY, CIRCUMFLEX },
146 	{ 'i', 0, CIRCUMFLEX },
147 	{ '~', ANY, TILDE },
148 	{ 'n', 0, TILDE },
149 	{ '0', ANY, RING },
150 	{ '/', ANY, SLASH },
151 	{ '7', ANY, BREVE },
152 	{ '6', ANY, CARON },
153 	{ '.', ANY, DOTABOVE },
154 	{ ',', ANY, DOTBELOW },
155 	{ '5', ANY, CEDILLA },
156 	{ '4', ANY, OGONEK },
157 	{ '_', ANY, MACRON },
158 	{ '"', ANY, DBLGRAVE },
159 	{ '@', ANY, GREEK },
160 
161 	{ ' ', 0, 0, 0x00a0 },		/* no break space */
162 	{ ' ', GREEK, 0, 0x2001 },	/* em space */
163 	{ '!', 0, 0, 0x00a1 },		/* inverted exclaim */
164 	{ '#', 0, 0, 0x00a3 },		/* sterling */
165 	{ '#', GREEK, 0, 0x00a5 },	/* Yen */
166 	{ '$', 0, 0, 0x20ac },		/* Euro */
167 	{ '$', GREEK, 0, 0x00a2 },	/* cent */
168 	{ '\\',0, 0, 0x00ab },		/* guillemotleft */
169 	{ '\\',GREEK, 0, 0x2039 },	/* single guillemotleft */
170 	{ '|', 0, 0, 0x00bb },		/* guillemotright */
171 	{ '|', GREEK, 0, 0x203a },	/* single guillemotright */
172 	{ '*', 0, 0, 0x00b0 },		/* degree */
173 	{ '*', GREEK, 0, 0x2022 },	/* bullet */
174 	{ '.', GREEK, 0, 0x00b7 },	/* centered dot */
175 	{ '-', 0, 0, 0x00ad },		/* soft hyphen */
176 	{ '-', GREEK, 0, 0x2013 },	/* en dash */
177 	{ '_', GREEK, 0, 0x2014 },	/* em dash */
178 	{ '=', GREEK, 0, 0x2015 },	/* quote dash */
179 	{ '+', 0, 0, 0x00b1 },		/* plus minus */
180 	{ ';', 0, 0, 0x2026 },		/* ellipsis */
181 	{ '[', 0, 0, 0x2018 },		/* open quote */
182 	{ ']', 0, 0, 0x2019 },		/* close quote */
183 	{ '{', 0, 0, 0x201c },		/* open double quote */
184 	{ '}', 0, 0, 0x201c },		/* close double quote */
185 	{ '>', 0, 0, 0x2264 },		/* greater than or equal */
186 	{ '>', GREEK, 0, 0x2023 },	/* triangle bullet */
187 	{ '<', 0, 0, 0x2265 },		/* less than or equal */
188 	{ '?', 0, 0, 0x00bf },		/* inverted quest */
189 	{ 'f', 0, 0, 0x2640 },		/* female */
190 	{ 'g', 0, 0, 0x00a9 },		/* copyright */
191 	{ 'h', GREEK|SLASH, 0, 0x210f },/* hbar */
192 	{ 'h', 0, 0, 0x261e },		/* right hand */
193 	{ 'H', 0, 0, 0x261e },		/* left hand */
194 	{ 'm', 0, 0, 0x2642 },		/* male */
195 	{ 'p', 0, 0, 0x00b6 },		/* paragraph */
196 	{ 'P', 0, 0, 0x00a7 },		/* section */
197 	{ 'r', 0, 0, 0x00ae },		/* registered */
198 	{ 't', 0, 0, 0x2122 },		/* TM */
199 	{ '2', BREVE, 0, 0x00bd },	/* 1/2 */
200 
201 /*	{ 'A', 0, 0, 0x00c5 },*/	/* A ring */
202 /*	{ 'a', 0, 0, 0x00e5 },*/	/* a ring */
203 	{ 'C', 0, 0, 0x00c7 },		/* C cedilla */
204 	{ 'c', 0, 0, 0x00e7 },		/* c cedilla */
205 	{ 'A', 0, 0, 0x00c6 },		/* AE */
206 	{ 'a', 0, 0, 0x00e6 },		/* ae */
207 	{ 'O', 0, 0, 0x0152 },		/* OE */
208 	{ 'o', 0, 0, 0x1536 },		/* oe */
209 	{ 's', 0, 0, 0x00df },		/* es-zet */
210 	{ 'z', 0, 0, 0x017f },		/* long-s */
211 
212 	{ 'i', DOTABOVE, 0, 0x131 },	/* dotless i */
213 
214 /* the mapping from ascii->greek follows the symbol font */
215 	{ 'A', GREEK, 0, 0x391 },		/* Alpha */
216 	{ 'B', GREEK, 0, 0x392 },		/* Beta */
217 	{ 'C', GREEK, 0, 0x3A7 },		/* Chi */
218 	{ 'D', GREEK, 0, 0x394 },		/* Delta */
219 	{ 'E', GREEK, 0, 0x395 },		/* Epsilon */
220 	{ 'F', GREEK, 0, 0x3A6 },		/* Phi */
221 	{ 'G', GREEK, 0, 0x393 },		/* Gamma */
222 	{ 'H', GREEK, 0, 0x397 },		/* Eta */
223 	{ 'I', GREEK, 0, 0x399 },		/* Iota */
224 	{ 'J', GREEK, 0, 0x3d1 },		/* Theta Symbol */
225 	{ 'K', GREEK, 0, 0x39A },		/* Kappa */
226 	{ 'L', GREEK, 0, 0x39B },		/* Lamda */
227 	{ 'M', GREEK, 0, 0x39C },		/* Mu */
228 	{ 'N', GREEK, 0, 0x39D },		/* Nu */
229 	{ 'O', GREEK, 0, 0x39F },		/* Omicron */
230 	{ 'P', GREEK, 0, 0x3A0 },		/* Pi */
231 	{ 'Q', GREEK, 0, 0x398 },		/* Theta */
232 	{ 'R', GREEK, 0, 0x3A1 },		/* Rho */
233 	{ 'S', GREEK, 0, 0x3A3 },		/* Sigma */
234 	{ 'T', GREEK, 0, 0x3A4 },		/* Tau */
235 	{ 'U', GREEK, 0, 0x3A5 },		/* Upsilon */
236 	{ 'V', GREEK, 0, 0x3c2 },		/* lowercase final sigma */
237 	{ 'W', GREEK, 0, 0x3A9 },		/* Omega */
238 	{ 'X', GREEK, 0, 0x39E },		/* Xi */
239 	{ 'Y', GREEK, 0, 0x3A8 },		/* Psi */
240 	{ 'Z', GREEK, 0, 0x396 },		/* Zeta */
241 	{ 'a', GREEK, 0, 0x3b1 },		/* alpha */
242 	{ 'b', GREEK, 0, 0x3b2 },		/* beta */
243 	{ 'c', GREEK, 0, 0x3c7 },		/* chi */
244 	{ 'd', GREEK, 0, 0x3b4 },		/* delta */
245 	{ 'e', GREEK, 0, 0x3b5 },		/* epsilon */
246 	{ 'f', GREEK, 0, 0x3c6 },		/* phi */
247 	{ 'g', GREEK, 0, 0x3b3 },		/* gamma */
248 	{ 'h', GREEK, 0, 0x3b7 },		/* eta */
249 	{ 'i', GREEK, 0, 0x3b9 },		/* iota */
250 	{ 'j', GREEK, 0, 0x3d5 },		/* phi Symbol */
251 	{ 'k', GREEK, 0, 0x3bA },		/* kappa */
252 	{ 'l', GREEK, 0, 0x3bB },		/* lamda */
253 	{ 'm', GREEK, 0, 0x3bC },		/* mu */
254 	{ 'n', GREEK, 0, 0x3bD },		/* nu */
255 	{ 'o', GREEK, 0, 0x3bF },		/* omicron */
256 	{ 'p', GREEK, 0, 0x3c0 },		/* pi */
257 	{ 'q', GREEK, 0, 0x3b8 },		/* theta */
258 	{ 'r', GREEK, 0, 0x3c1 },		/* rho */
259 	{ 's', GREEK, 0, 0x3c3 },		/* sigma */
260 	{ 't', GREEK, 0, 0x3c4 },		/* tau */
261 	{ 'u', GREEK, 0, 0x3c5 },		/* upsilon */
262 	{ 'v', GREEK, 0, 0x3D6 },		/* pi Symbol */
263 	{ 'w', GREEK, 0, 0x3c9 },		/* omega */
264 	{ 'x', GREEK, 0, 0x3bE },		/* xi */
265 	{ 'y', GREEK, 0, 0x3c8 },		/* psi */
266 	{ 'z', GREEK, 0, 0x3b6 },		/* zeta */
267 	{ 'A', GREEK|DBLGRAVE, 0, 0x386 },	/* Alpha tonos */
268 	{ 'A', GREEK|BREVE, 0, 0x1fb8 },	/* Alpha vrachy */
269 	{ 'A', GREEK|MACRON, 0, 0x1fb9 },	/* Alpha macron */
270 	{ 'a', GREEK|DBLGRAVE, 0, 0x3ac },	/* alpha tonos */
271 	{ 'a', GREEK|GRAVE, 0, 0x1f70 },	/* alpha varia */
272 	{ 'a', GREEK|ACUTE, 0, 0x1f71 },	/* alpha oxia */
273 	{ 'a', GREEK|BREVE, 0, 0x1fb0 },	/* alpha vrachy */
274 	{ 'a', GREEK|MACRON, 0, 0x1fb1 },	/* alpha macron */
275 	{ 'a', GREEK|TILDE, 0, 0x1fb6 },	/* alpha perispomeni */
276 	{ 'E', GREEK|DBLGRAVE, 0, 0x388 },	/* Epsilon tonos */
277 	{ 'E', GREEK|GRAVE, 0, 0x1fc8 },	/* Epsilon varia */
278 	{ 'E', GREEK|ACUTE, 0, 0x1fc9 },	/* Epsilon oxia */
279 	{ 'e', GREEK|DBLGRAVE, 0, 0x3ad },	/* epsilon tonos */
280 	{ 'e', GREEK|GRAVE, 0, 0x1f72 },	/* epsilon varia */
281 	{ 'e', GREEK|ACUTE, 0, 0x1f73 },	/* epsilon oxia */
282 	{ 'H', GREEK|DBLGRAVE, 0, 0x389 },	/* Eta tonos */
283 	{ 'H', GREEK|GRAVE, 0, 0x1fca },	/* Eta varia */
284 	{ 'H', GREEK|ACUTE, 0, 0x1fcb },	/* Eta oxia */
285 	{ 'h', GREEK|DBLGRAVE, 0, 0x3ae },	/* eta tonos */
286 	{ 'h', GREEK|GRAVE, 0, 0x1f74 },	/* eta varia */
287 	{ 'h', GREEK|ACUTE, 0, 0x1f75 },	/* eta oxia */
288 	{ 'h', GREEK|TILDE, 0, 0x1fc6 },	/* eta perispomeni */
289 	{ 'I', GREEK|DBLGRAVE, 0, 0x38A },	/* Iota tonos */
290 	{ 'I', GREEK|DIAERESIS, 0, 0x3AA },	/* Iota dialytika */
291 	{ 'I', GREEK|GRAVE, 0, 0x1f7a },	/* Iota varia */
292 	{ 'I', GREEK|ACUTE, 0, 0x1f7b },	/* Iota oxia */
293 	{ 'I', GREEK|TILDE, 0, 0x1f78 },	/* Iota perispomeni */
294 	{ 'I', GREEK|MACRON, 0, 0x1f79 },	/* Iota macron */
295 	{ 'i', GREEK|DBLGRAVE, 0, 0x3af },	/* iota tonos */
296 	{ 'i', GREEK|DIAERESIS, 0, 0x3ca },	/* iota dialytika */
297 	{ 'i', GREEK|DBLGRAVE|DIAERESIS, 0, 0x390 },/* iota dialytika tonos */
298 	{ 'i', GREEK|GRAVE, 0, 0x1f76 },	/* iota varia */
299 	{ 'i', GREEK|ACUTE, 0, 0x1f77 },	/* iota oxia */
300 	{ 'i', GREEK|BREVE, 0, 0x1fd0 },	/* iota vrachy */
301 	{ 'i', GREEK|MACRON, 0, 0x1fd1 },	/* iota macron */
302 	{ 'i', GREEK|TILDE, 0, 0x1fd6 },	/* iota perispomeni */
303 	{ 'i', GREEK|GRAVE|DIAERESIS, 0, 0x1fd2},/* iota dialytika varia */
304 	{ 'i', GREEK|ACUTE|DIAERESIS, 0, 0x1fd3},/* iota dialytika oxia */
305 	{ 'i', GREEK|TILDE|DIAERESIS, 0, 0x1fd7},/* iota dialytika perispomeni */
306 	{ 'O', GREEK|DBLGRAVE, 0, 0x38C },	/* Omicron tonos */
307 	{ 'O', GREEK|GRAVE, 0, 0x1ff8 },	/* Omicron varia */
308 	{ 'O', GREEK|ACUTE, 0, 0x1ff9 },	/* Omicron oxia */
309 	{ 'o', GREEK|DBLGRAVE, 0, 0x3cc },	/* omicron tonos */
310 	{ 'o', GREEK|GRAVE, 0, 0x1f78 },	/* omicron varia */
311 	{ 'o', GREEK|ACUTE, 0, 0x1f79 },	/* omicron oxia */
312 	{ 'U', GREEK|DBLGRAVE, 0, 0x38E },	/* Upsilon tonos */
313 	{ 'U', GREEK|DIAERESIS, 0, 0x3AB },	/* Upsilon dialytika */
314 	{ 'U', GREEK|GRAVE, 0, 0x1fea },	/* Upsilon varia */
315 	{ 'U', GREEK|ACUTE, 0, 0x1feb },	/* Upsilon oxia */
316 	{ 'U', GREEK|BREVE, 0, 0x1fe8 },	/* Upsilon perispomeni */
317 	{ 'U', GREEK|MACRON, 0, 0x1fe9 },	/* Upsilon macron */
318 	{ 'u', GREEK|DBLGRAVE, 0, 0x3cd },	/* upsilon tonos */
319 	{ 'u', GREEK|DIAERESIS, 0, 0x3cb },	/* upsilon dialytika */
320 	{ 'u', GREEK|DBLGRAVE|DIAERESIS, 0, 0x3b0 },/* upsilon dialytika tonos */
321 	{ 'u', GREEK|GRAVE, 0, 0x1f7a },	/* upsilon varia */
322 	{ 'u', GREEK|ACUTE, 0, 0x1f7b },	/* upsilon oxia */
323 	{ 'u', GREEK|BREVE, 0, 0x1ff0 },	/* upsilon perispomeni */
324 	{ 'u', GREEK|MACRON, 0, 0x1fe1 },	/* upsilon macron */
325 	{ 'u', GREEK|GRAVE|DIAERESIS, 0, 0x1fe3 },/* upsilon dialytika varia */
326 	{ 'u', GREEK|ACUTE|DIAERESIS, 0, 0x1fe4 },/* upsilon dialytika oxia */
327 	{ 'u', GREEK|TILDE, 0, 0x1fe6 },	/* upsilon perispomeni */
328 	{ 'u', GREEK|TILDE|DIAERESIS, 0, 0x1fe7 },/* upsilon dialytika perispomeni */
329 	{ 'W', GREEK|DBLGRAVE, 0, 0x38F },	/* Omega tonos */
330 	{ 'W', GREEK|GRAVE, 0, 0x1ffa },	/* Omega varia */
331 	{ 'W', GREEK|ACUTE, 0, 0x1ffb },	/* Omega oxia */
332 	{ 'w', GREEK|DBLGRAVE, 0, 0x3ce },	/* omega tonos */
333 	{ 'w', GREEK|GRAVE, 0, 0x1f7a },	/* omega varia */
334 	{ 'w', GREEK|ACUTE, 0, 0x1f7b },	/* omega oxia */
335 	{ 0 }
336 };
337 
338 struct transform {
339     uint32 oldstate;
340     uint32 newstate;
341     unichar_t resch;
342     struct transform *next;
343 } *info[95] = { 0 };
344 
queuelen(struct transform * queue)345 int queuelen(struct transform *queue) {
346     int len=0;
347 
348     while ( queue!=NULL ) {
349 	queue = queue->next;
350 	++len;
351     }
352 return( len );
353 }
354 
Mask(char * buffer,int mask)355 static char *Mask(char *buffer,int mask) {
356     int i;
357     char *bpt = buffer;
358 
359     if ( mask==0 )
360 return( "0" );
361     if ( mask==ANY )
362 return("ANY");
363     *buffer = '\0';
364     for (i=0; names[i].name!=NULL; ++i ) {
365 	if ( names[i].mask&mask ) {
366 	    if ( bpt!=buffer )
367 		*bpt++ ='|';
368 	    strcpy(bpt,names[i].name);
369 	    bpt += strlen(bpt);
370 	}
371     }
372 return( buffer );
373 }
374 
dumpinfo()375 void dumpinfo() {
376     FILE *out;
377     int i;
378     struct transform *t;
379     char buffer[400], buffer2[400];
380 
381     out = fopen("gdrawbuildchars.c","w");
382     fprintf(out, "/* Copyright (C) 2000-2012 by George Williams */\n" );
383     fprintf(out, "/*\n * Redistribution and use in source and binary forms, with or without\n" );
384     fprintf(out, " * modification, are permitted provided that the following conditions are met:\n *\n" );
385     fprintf(out, " * Redistributions of source code must retain the above copyright notice, this\n" );
386     fprintf(out, " * list of conditions and the following disclaimer.\n *\n" );
387     fprintf(out, " * Redistributions in binary form must reproduce the above copyright notice,\n" );
388     fprintf(out, " * this list of conditions and the following disclaimer in the documentation\n" );
389     fprintf(out, " * and/or other materials provided with the distribution.\n *\n" );
390     fprintf(out, " * The name of the author may not be used to endorse or promote products\n" );
391     fprintf(out, " * derived from this software without specific prior written permission.\n *\n" );
392     fprintf(out, " * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED\n" );
393     fprintf(out, " * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n" );
394     fprintf(out, " * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\n" );
395     fprintf(out, " * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" );
396     fprintf(out, " * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n" );
397     fprintf(out, " * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\n" );
398     fprintf(out, " * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n" );
399     fprintf(out, " * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\n" );
400     fprintf(out, " * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF\n" );
401     fprintf(out, " * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n" );
402     fprintf(out, "/* This file was generated using the program 'makebuildtables.c' */\n\n" );
403     fprintf(out,"#include \"gdrawP.h\"\n\n" );
404 
405     for ( i=0; names[i].name!=NULL; ++i )
406 	fprintf( out, "#define\t%s\t%s0x%07x\n", names[i].name, \
407 		 strlen(names[i].name)>7?"":"\t", names[i].mask );
408     fprintf(out,"\n#define\tANY\t\t0x%07x\n\n", ANY );
409 
410     for ( i=0; i<95; ++i ) if ( info[i]!=NULL ) {
411 	fprintf(out, "static struct gchr_transform trans_%s[] = {\n", charnames[i] );
412 	for ( t=info[i]; t!=NULL; t=t->next )
413 	    fprintf(out, "    { %s, %s, 0x%07x }%s\n", Mask(buffer,t->oldstate),
414 		    Mask(buffer2,t->newstate), t->resch, t->next==NULL?"":"," );
415 	fprintf(out,"};\n\n");
416     }
417     fprintf(out,"struct gchr_lookup _gdraw_chrlookup[95] = {\n" );
418     for ( i=0; i<95; ++i ) {
419 	if ( info[i]==NULL )
420 	    fprintf(out, "    /* %c */ { 0 },\n", i+' ' );
421 	else
422 	    fprintf(out, "    /* %c */ { %d, trans_%s },\n", i+' ', queuelen(info[i]), charnames[i] );
423     }
424     fprintf(out,"};\n\n" );
425 
426     fprintf(out, "struct gchr_accents _gdraw_accents[] = {\n" );
427     fprintf(out, "    { 0x0301, 0x%07x },\n", ACUTE );
428     fprintf(out, "    { 0x0300, 0x%07x },\n", GRAVE );
429     fprintf(out, "    { 0x0308, 0x%07x },\n", DIAERESIS );
430     fprintf(out, "    { 0x0302, 0x%07x },\n", CIRCUMFLEX );
431     fprintf(out, "    { 0x0303, 0x%07x },\n", TILDE );
432     fprintf(out, "    { 0x030a, 0x%07x },\n", RING );
433     fprintf(out, "    { 0x0338, 0x%07x },\n", SLASH );
434     fprintf(out, "    { 0x0306, 0x%07x },\n", BREVE );
435     fprintf(out, "    { 0x030c, 0x%07x },\n", CARON );
436     fprintf(out, "    { 0x0307, 0x%07x },\n", DOTABOVE );
437     fprintf(out, "    { 0x0323, 0x%07x },\n", DOTBELOW );
438     fprintf(out, "    { 0x0327, 0x%07x },\n", CEDILLA );
439     fprintf(out, "    { 0x0328, 0x%07x },\n", OGONEK );
440     fprintf(out, "    { 0x0304, 0x%07x },\n", MACRON );
441     fprintf(out, "    { 0x030d, 0x%07x },\n", DBLGRAVE|GREEK );
442     fprintf(out, "    { 0x030b, 0x%07x },\n", DBLGRAVE );
443     fprintf(out, "    { 0x030b, 0x%07x },\n", DBLACUTE );
444     fprintf(out, "    { 0x030b, 0x%07x },\n", INVBREVE );
445     fprintf(out, "    { 0x030b, 0x%07x },\n", DIAERESISBELOW );
446     fprintf(out, "    { 0x030b, 0x%07x },\n", CIRCUMFLEXBELOW );
447     fprintf(out, "    { 0x030b, 0x%07x },\n", TILDEBELOW );
448     fprintf(out, "    { 0x030b, 0x%07x },\n", RINGBELOW );
449     fprintf(out, "    { 0x030b, 0x%07x },\n", LINEBELOW );
450     fprintf(out, "    { 0x030b, 0x%07x },\n", HOOKABOVE );
451     fprintf(out, "    { 0x030b, 0x%07x },\n", HORN );
452     fprintf(out, "    { 0, 0 },\n" );
453     fprintf(out, "};\n\n" );
454     fprintf(out, "uint32 _gdraw_chrs_any=ANY, _gdraw_chrs_ctlmask=GREEK, _gdraw_chrs_metamask=0;\n" );
455     fclose(out);
456 }
457 
mygets(FILE * in,char * buffer)458 char *mygets(FILE *in,char *buffer) {
459     char *bpt = buffer;
460     int ch;
461 
462     while ((ch = getc(in))!=EOF && ch!='\n' )
463 	*bpt++ = ch;
464     *bpt = '\0';
465     if ( bpt==buffer && ch==EOF )
466 return( NULL );
467 return(buffer );
468 }
469 
AddTransform(int ch,uint32 oldstate,uint32 newstate,unsigned short resch)470 void AddTransform(int ch, uint32 oldstate, uint32 newstate, unsigned short resch ) {
471     struct transform *trans;
472 
473     ch -= ' ';
474     for ( trans=info[ch]; trans!=NULL; trans = trans->next )
475 	if ( trans->oldstate==oldstate ) {
476 	    fprintf(stderr, "Duplicate entry for %c(%d) at 0x%07x, 0x%07x,0x%07x and 0x%07x,0x%07x\n",
477 		    ch+' ', ch+' ', oldstate, trans->newstate, trans->resch, newstate, resch );
478     break;
479 	}
480 
481     trans = calloc(1,sizeof(struct transform));
482     trans->next = info[ch];
483     info[ch] = trans;
484     trans->oldstate = oldstate;
485     trans->newstate = newstate;
486     trans->resch = resch;
487 }
488 
ParseUnicodeFile(FILE * in)489 void ParseUnicodeFile(FILE *in) {
490     char buffer[600];
491     int ch, mask, base, lc, i;
492     char *pt;
493 
494     while ( mygets(in,buffer)!=NULL ) {
495 	ch = strtol(buffer,NULL,16);
496 	if ( ch==0x1ec0 )
497 	    ch = 0x1ec0;
498 	pt = buffer+4;
499 	if ( strncmp(pt,";LATIN ",7)!=0 )
500     continue;
501 	pt += 7;
502 	if ( strncmp(pt,"CAPITAL ",8)==0 ) {
503 	    lc = 0;
504 	    pt += 8;
505 	} else if ( strncmp(pt,"SMALL ",6)==0 ) {
506 	    lc = 1;
507 	    pt += 6;
508 	} else
509     continue;
510 	if ( strncmp(pt,"LETTER ",7)!=0 )
511     continue;
512 	pt += 7;
513 	base = *pt++;
514 	if ( lc ) base = tolower(base);
515 	if ( strncmp(pt," WITH ",6)!=0 )
516     continue;
517 	pt += 6;
518 	mask = 0;
519 	for (;;) {
520 	    for ( i=0; names2[i].name!=NULL; ++i ) {
521 		if ( strncmp(pt,names2[i].name,strlen(names2[i].name))==0 )
522 	    break;
523 	    }
524 	    if ( names2[i].name==NULL || names2[i].mask==0 )
525     goto continue_2_loop;
526 	    mask |= names2[i].mask;
527 	    pt += strlen(names2[i].name);
528 	    while ( *pt!=';' && !(*pt==' ' && pt[1]=='A' && pt[2]=='N' && pt[3]=='D' && pt[4]==' '))
529 		++pt;
530 	    if ( *pt==';' )
531 	break;
532 	    else
533 		pt += 5;
534 	}
535 	AddTransform(base,mask,0,ch);
536     continue_2_loop:;
537     }
538     fclose(in);
539 }
540 
AddPredefineds()541 void AddPredefineds() {
542     int i;
543 
544     for ( i=0; predefined[i].ch!='\0'; ++i )
545 	AddTransform(predefined[i].ch, predefined[i].oldstate,
546 		predefined[i].newstate, predefined[i].result );
547 }
548 
RevQueue(struct transform * cur)549 struct transform *RevQueue(struct transform *cur) {
550     struct transform *prev=NULL, *next;
551 
552     if ( cur==NULL )
553 return( NULL );
554     next = cur->next;
555     while ( next!=NULL ) {
556 	cur->next = prev;
557 	prev = cur;
558 	cur = next;
559 	next = cur->next;
560     }
561     cur->next = prev;
562 return( cur );
563 }
564 
main()565 int main() {
566     FILE *in;
567     int i;
568 
569     AddPredefineds();
570     in = fopen("UnicodeData.txt","r");
571     if ( in==NULL ) {
572 	fprintf(stderr,"Can't open UnicodeData.txt\n" );
573 	return( -1 );
574     }
575     ParseUnicodeFile(in);
576     for ( i=0; i<95; ++i )
577 	info[i] = RevQueue(info[i]);
578     dumpinfo();
579     return( 0 );
580 }
581