]> git.kernelconcepts.de Git - gbdfed.git/blob - bdfgname.c
Fixup several compile faults due to changes in recent distributions,
[gbdfed.git] / bdfgname.c
1 /*
2  * Copyright 2008 Department of Mathematical Sciences, New Mexico State University
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17  * DEPARTMENT OF MATHEMATICAL SCIENCES OR NEW MEXICO STATE UNIVERSITY BE
18  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22
23 #include "bdfP.h"
24
25 typedef struct {
26     int code;
27     int start;
28     int end;
29     int pad;
30 } _bdf_adobe_name_t;
31
32 static _bdf_adobe_name_t *adobe_names;
33 static unsigned int adobe_names_size;
34 static unsigned int adobe_names_used;
35
36 /*
37  * Provide a maximum length for glyph names just to make things clearer.
38  */
39 #define MAX_GLYPH_NAME_LEN 127
40
41 static int
42 bdf_getline(FILE *in, char *buf, int limit)
43 {
44     int c, i;
45
46     c = EOF;
47
48     for (i = 0; i < limit - 1; i++) {
49         if ((c = getc(in)) == EOF || (c == '\n' || c == '\r'))
50           break;
51         buf[i] = c;
52     }
53     buf[i] = 0;
54
55     /*
56      * Discard the rest of the line which did not fit into the buffer.
57      */
58     while (c != EOF && c != '\n' && c != '\r')
59       c = getc(in);
60
61     if (c == '\r') {
62         /*
63          * Check for a trailing newline.
64          */
65         c = getc(in);
66         if (c != '\n')
67           ungetc(c, in);
68     }
69
70     return i;
71 }
72
73 static int
74 _bdf_find_name(int code, char *name, FILE *in)
75 {
76     int c, i, pos;
77     char *sp, buf[256];
78
79     while (!feof(in)) {
80         pos = ftell(in);
81         (void) bdf_getline(in, buf, 256);
82         while (!feof(in) && (buf[0] == 0 || buf[0] == '#')) {
83             buf[0] = 0;
84             pos = ftell(in);
85             (void) bdf_getline(in, buf, 256);
86         }
87
88         if (buf[0] == 0)
89           return -1;
90
91         c = _bdf_atol(buf, 0, 16);
92
93         if (c > code) {
94             /*
95              * Restore the last position read in case the code is not in the
96              * file and the current code is greater than the expected code.
97              */
98             fseek(in, pos, 0L);
99             return -1;
100         }
101
102         if (c == code) {
103             for (sp = buf; *sp != ';'; sp++) ;
104             sp++;
105             for (i = 0; *sp != ';' && i < MAX_GLYPH_NAME_LEN; sp++, i++)
106               name[i] = *sp;
107             name[i] = 0;
108             return i;
109         }
110     }
111     return -1;
112 }
113
114 static int
115 by_encoding(const void *a, const void *b)
116 {
117     _bdf_adobe_name_t *c1, *c2;
118
119     c1 = (_bdf_adobe_name_t *) a;
120     c2 = (_bdf_adobe_name_t *) b;
121     if (c1->code < c2->code)
122       return -1;
123     else if (c1->code > c2->code)
124       return 1;
125     return 0;
126 }
127
128 static void
129 _bdf_load_adobe_names(FILE *in)
130 {
131     int c, pos;
132     char *sp, buf[256];
133
134     /*
135      * Go back to the beginning of the file to look for the code because the
136      * codes are not in order in the current Adobe Glyph Name list file.
137      */
138     fseek(in, 0, 0);
139
140     while (!feof(in)) {
141         pos = ftell(in);
142         (void) bdf_getline(in, buf, 256);
143         while (!feof(in) && (buf[0] == 0 || buf[0] == '#')) {
144             buf[0] = 0;
145             pos = ftell(in);
146             (void) bdf_getline(in, buf, 256);
147         }
148
149         if (adobe_names_used == adobe_names_size) {
150             if (adobe_names_size == 0)
151               adobe_names = (_bdf_adobe_name_t *)
152                   malloc(sizeof(_bdf_adobe_name_t) << 9);
153             else
154               adobe_names = (_bdf_adobe_name_t *)
155                   realloc((char *) adobe_names,
156                           sizeof(_bdf_adobe_name_t) *
157                           (adobe_names_size + 512));
158             (void) memset((char *) (adobe_names + adobe_names_size), 0,
159                           sizeof(_bdf_adobe_name_t) << 9);
160             adobe_names_size += 512;
161         }
162
163         adobe_names[adobe_names_used].start = pos;
164         for (sp = buf; *sp != ';'; sp++) ;
165         adobe_names[adobe_names_used].end = pos + (sp - buf);
166         sp++;
167
168         c = _bdf_atol(sp, 0, 16);
169
170         /*
171          * Ignore the Adobe-specific names in the Private Use Area.
172          */
173         if (c < 0xe000 || c > 0xf8ff)
174           adobe_names[adobe_names_used++].code = c;
175     }
176
177     /*
178      * Sort the results by code.
179      */
180     qsort((char *) adobe_names, adobe_names_used, sizeof(_bdf_adobe_name_t),
181           by_encoding);
182 }
183
184 static int
185 _bdf_find_adobe_name(int code, char *name, FILE *in)
186 {
187     int len;
188     int l, r, m;
189
190     if (code < 0x20 || (code >= 0x7f && code <= 0x9f) ||
191         code == 0xfffe || code == 0xffff) {
192         sprintf(name, "char%u", code);
193         return (int) strlen(name);
194     }
195
196     if (code >= 0xe000 && code <= 0xf8ff) {
197         sprintf(name, "uni%04X", code & 0xffff);
198         return (int) strlen(name);
199     }
200
201     if (adobe_names_size == 0)
202       _bdf_load_adobe_names(in);
203
204     l = 0;
205     r = adobe_names_used - 1;
206     while (l <= r) {
207         m = (l + r) >> 1;
208         if (adobe_names[m].code < code)
209           l = m + 1;
210         else if (adobe_names[m].code > code)
211           r = m - 1;
212         else {
213             fseek(in, adobe_names[m].start, 0);
214             len = adobe_names[m].end - adobe_names[m].start;
215             if (len > MAX_GLYPH_NAME_LEN)
216               len = MAX_GLYPH_NAME_LEN;
217             len = (int) fread(name, sizeof(char), len, in);
218             name[len] = 0;
219             return len;
220         }
221     }
222
223     sprintf(name, "uni%04X", code & 0xffff);
224     return (int) strlen(name);
225 }
226
227 static int
228 _bdf_set_glyph_names(FILE *in, bdf_font_t *font, bdf_callback_t callback,
229                      int adobe)
230 {
231     int changed;
232     int i, size, len;
233     bdf_glyph_t *gp;
234     bdf_callback_struct_t cb;
235     char name[MAX_GLYPH_NAME_LEN + 1];
236
237     if (callback != 0) {
238         cb.reason = BDF_GLYPH_NAME_START;
239         cb.current = 0;
240         cb.total = font->glyphs_used;
241         (*callback)(&cb, 0);
242     }
243     for (changed = 0, i = 0, gp = font->glyphs; i < font->glyphs_used;
244          i++, gp++) {
245         size = (adobe) ?
246             _bdf_find_adobe_name(gp->encoding, name, in) :
247             _bdf_find_name(gp->encoding, name, in);
248         if (size < 0)
249           continue;
250
251         len = (gp->name) ? strlen(gp->name) : 0;
252         if (len == 0) {
253           gp->name = (char *) _bdf_strdup((unsigned char *) name, size + 1);
254           changed = 1;
255         } else if (size != len || strcmp(gp->name, name) != 0) {
256             /*
257              * Simply resize existing storage so lots of memory allocations
258              * are not needed.
259              */
260             if (size > len)
261               gp->name = (char *) realloc(gp->name, size + 1);
262             (void) strcpy(gp->name, name);
263             changed = 1;
264         }
265
266         if (callback != 0) {
267             cb.reason = BDF_GLYPH_NAME;
268             cb.current = i;
269             (*callback)(&cb, 0);
270         }
271     }
272
273     if (callback != 0) {
274         cb.reason = BDF_GLYPH_NAME;
275         cb.current = cb.total;
276         (*callback)(&cb, 0);
277     }
278
279     return changed;
280 }
281
282 int
283 bdf_set_unicode_glyph_names(FILE *in, bdf_font_t *font,
284                             bdf_callback_t callback)
285 {
286     return _bdf_set_glyph_names(in, font, callback, 0);
287 }
288
289 int
290 bdf_set_adobe_glyph_names(FILE *in, bdf_font_t *font, bdf_callback_t callback)
291 {
292     return _bdf_set_glyph_names(in, font, callback, 1);
293 }
294
295 int
296 bdf_set_glyph_code_names(int prefix, bdf_font_t *font, bdf_callback_t callback)
297 {
298     int changed;
299     int i, size, len;
300     bdf_glyph_t *gp;
301     bdf_callback_struct_t cb;
302     char name[128];
303
304     if (callback != 0) {
305         cb.reason = BDF_GLYPH_NAME_START;
306         cb.current = 0;
307         cb.total = font->glyphs_used;
308         (*callback)(&cb, 0);
309     }
310     for (changed = 0, i = 0, gp = font->glyphs; i < font->glyphs_used;
311          i++, gp++) {
312         switch (prefix) {
313           case 'u': sprintf(name, "uni%04X", gp->encoding & 0xffff); break;
314           case 'x': sprintf(name, "0x%04X", gp->encoding & 0xffff); break;
315           case '+': sprintf(name, "U+%04X", gp->encoding & 0xffff); break;
316           case '\\': sprintf(name, "\\u%04X", gp->encoding & 0xffff); break;
317         }
318         size = 6;
319
320         len = (gp->name) ? strlen(gp->name) : 0;
321         if (len == 0) {
322           gp->name = (char *) _bdf_strdup((unsigned char *) name, size + 1);
323           changed = 1;
324         } else if (size != len || strcmp(gp->name, name) != 0) {
325             /*
326              * Simply resize existing storage so lots of memory allocations
327              * are not needed.
328              */
329             if (size > len)
330               gp->name = (char *) realloc(gp->name, size + 1);
331             (void) strcpy(gp->name, name);
332             changed = 1;
333         }
334
335         if (callback != 0) {
336             cb.reason = BDF_GLYPH_NAME;
337             cb.current = i;
338             (*callback)(&cb, 0);
339         }
340     }
341
342     if (callback != 0) {
343         cb.reason = BDF_GLYPH_NAME;
344         cb.current = cb.total;
345         (*callback)(&cb, 0);
346     }
347
348     return changed;
349 }
350
351 void
352 _bdf_glyph_name_cleanup(void)
353 {
354     if (adobe_names_size > 0)
355       free((char *) adobe_names);
356     adobe_names_size = adobe_names_used = 0;
357 }