File: | fontfile/fontdir.c |
Location: | line 157, column 2 |
Description: | Null pointer argument in call to string copy function |
1 | /* | |||||
2 | ||||||
3 | Copyright 1991, 1998 The Open Group | |||||
4 | ||||||
5 | Permission to use, copy, modify, distribute, and sell this software and its | |||||
6 | documentation for any purpose is hereby granted without fee, provided that | |||||
7 | the above copyright notice appear in all copies and that both that | |||||
8 | copyright notice and this permission notice appear in supporting | |||||
9 | documentation. | |||||
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 THE | |||||
17 | OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |||||
18 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |||||
19 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||||
20 | ||||||
21 | Except as contained in this notice, the name of The Open Group shall not be | |||||
22 | used in advertising or otherwise to promote the sale, use or other dealings | |||||
23 | in this Software without prior written authorization from The Open Group. | |||||
24 | ||||||
25 | */ | |||||
26 | ||||||
27 | /* | |||||
28 | * Author: Keith Packard, MIT X Consortium | |||||
29 | */ | |||||
30 | ||||||
31 | #ifdef HAVE_CONFIG_H1 | |||||
32 | #include <config.h> | |||||
33 | #endif | |||||
34 | #include "libxfontint.h" | |||||
35 | #include <X11/fonts/fntfilst.h> | |||||
36 | #include <X11/keysym.h> | |||||
37 | ||||||
38 | #if HAVE_STDINT_H1 | |||||
39 | #include <stdint.h> | |||||
40 | #elif !defined(INT32_MAX2147483647) | |||||
41 | #define INT32_MAX2147483647 0x7fffffff | |||||
42 | #endif | |||||
43 | ||||||
44 | Bool | |||||
45 | FontFileInitTable (FontTablePtr table, int size) | |||||
46 | { | |||||
47 | if (size < 0 || (size > INT32_MAX2147483647/sizeof(FontEntryRec))) | |||||
48 | return FALSE0; | |||||
49 | if (size) | |||||
50 | { | |||||
51 | table->entries = malloc(sizeof(FontEntryRec) * size); | |||||
52 | if (!table->entries) | |||||
53 | return FALSE0; | |||||
54 | } | |||||
55 | else | |||||
56 | table->entries = 0; | |||||
57 | table->used = 0; | |||||
58 | table->size = size; | |||||
59 | table->sorted = FALSE0; | |||||
60 | return TRUE1; | |||||
61 | } | |||||
62 | ||||||
63 | void | |||||
64 | FontFileFreeEntry (FontEntryPtr entry) | |||||
65 | { | |||||
66 | FontScalableExtraPtr extra; | |||||
67 | int i; | |||||
68 | ||||||
69 | if (entry->name.name) | |||||
70 | free(entry->name.name); | |||||
71 | entry->name.name = NULL((void *)0); | |||||
72 | ||||||
73 | switch (entry->type) | |||||
74 | { | |||||
75 | case FONT_ENTRY_SCALABLE0: | |||||
76 | free (entry->u.scalable.fileName); | |||||
77 | extra = entry->u.scalable.extra; | |||||
78 | for (i = 0; i < extra->numScaled; i++) | |||||
79 | if (extra->scaled[i].vals.ranges) | |||||
80 | free (extra->scaled[i].vals.ranges); | |||||
81 | free (extra->scaled); | |||||
82 | free (extra); | |||||
83 | break; | |||||
84 | case FONT_ENTRY_BITMAP2: | |||||
85 | free (entry->u.bitmap.fileName); | |||||
86 | entry->u.bitmap.fileName = NULL((void *)0); | |||||
87 | break; | |||||
88 | case FONT_ENTRY_ALIAS3: | |||||
89 | free (entry->u.alias.resolved); | |||||
90 | entry->u.alias.resolved = NULL((void *)0); | |||||
91 | break; | |||||
92 | } | |||||
93 | } | |||||
94 | ||||||
95 | void | |||||
96 | FontFileFreeTable (FontTablePtr table) | |||||
97 | { | |||||
98 | int i; | |||||
99 | ||||||
100 | for (i = 0; i < table->used; i++) | |||||
101 | FontFileFreeEntry (&table->entries[i]); | |||||
102 | free (table->entries); | |||||
103 | } | |||||
104 | ||||||
105 | FontDirectoryPtr | |||||
106 | FontFileMakeDir(const char *dirName, int size) | |||||
107 | { | |||||
108 | FontDirectoryPtr dir; | |||||
109 | int dirlen; | |||||
110 | int needslash = 0; | |||||
111 | const char *attrib; | |||||
112 | int attriblen; | |||||
113 | ||||||
114 | #if !defined(WIN32) | |||||
115 | attrib = strchr(dirName, ':'); | |||||
| ||||||
116 | #else | |||||
117 | /* OS/2 uses the colon in the drive letter descriptor, skip this */ | |||||
118 | attrib = strchr(dirName+2, ':'); | |||||
119 | #endif | |||||
120 | if (attrib) { | |||||
121 | dirlen = attrib - dirName; | |||||
122 | attriblen = strlen(attrib); | |||||
123 | } else { | |||||
124 | dirlen = strlen(dirName); | |||||
125 | attriblen = 0; | |||||
126 | } | |||||
127 | if (dirName[dirlen - 1] != '/') | |||||
128 | #ifdef NCD | |||||
129 | if (dirlen) /* leave out slash for builtins */ | |||||
130 | #endif | |||||
131 | needslash = 1; | |||||
132 | dir = malloc(sizeof *dir + dirlen + needslash + 1 + | |||||
133 | (attriblen ? attriblen + 1 : 0)); | |||||
134 | if (!dir) | |||||
135 | return (FontDirectoryPtr)0; | |||||
136 | if (!FontFileInitTable (&dir->scalable, 0)) | |||||
137 | { | |||||
138 | free (dir); | |||||
139 | return (FontDirectoryPtr)0; | |||||
140 | } | |||||
141 | if (!FontFileInitTable (&dir->nonScalable, size)) | |||||
142 | { | |||||
143 | FontFileFreeTable (&dir->scalable); | |||||
144 | free (dir); | |||||
145 | return (FontDirectoryPtr)0; | |||||
146 | } | |||||
147 | dir->directory = (char *) (dir + 1); | |||||
148 | dir->dir_mtime = 0; | |||||
149 | dir->alias_mtime = 0; | |||||
150 | if (attriblen) | |||||
151 | dir->attributes = dir->directory + dirlen + needslash + 1; | |||||
152 | else | |||||
153 | dir->attributes = NULL((void *)0); | |||||
154 | strncpy(dir->directory, dirName, dirlen)__builtin___strncpy_chk (dir->directory, dirName, dirlen, __builtin_object_size (dir->directory, 2 > 1 ? 1 : 0)); | |||||
155 | dir->directory[dirlen] = '\0'; | |||||
156 | if (dir->attributes) | |||||
157 | strcpy(dir->attributes, attrib)__builtin___strcpy_chk (dir->attributes, attrib, __builtin_object_size (dir->attributes, 2 > 1 ? 1 : 0)); | |||||
| ||||||
158 | if (needslash) | |||||
159 | strcat(dir->directory, "/")__builtin___strcat_chk (dir->directory, "/", __builtin_object_size (dir->directory, 2 > 1 ? 1 : 0)); | |||||
160 | return dir; | |||||
161 | } | |||||
162 | ||||||
163 | void | |||||
164 | FontFileFreeDir (FontDirectoryPtr dir) | |||||
165 | { | |||||
166 | FontFileFreeTable (&dir->scalable); | |||||
167 | FontFileFreeTable (&dir->nonScalable); | |||||
168 | free(dir); | |||||
169 | } | |||||
170 | ||||||
171 | FontEntryPtr | |||||
172 | FontFileAddEntry(FontTablePtr table, FontEntryPtr prototype) | |||||
173 | { | |||||
174 | FontEntryPtr entry; | |||||
175 | int newsize; | |||||
176 | ||||||
177 | /* can't add entries to a sorted table, pointers get broken! */ | |||||
178 | if (table->sorted) | |||||
179 | return (FontEntryPtr) 0; /* "cannot" happen */ | |||||
180 | if (table->used == table->size) { | |||||
181 | if (table->size >= ((INT32_MAX2147483647 / sizeof(FontEntryRec)) - 100)) | |||||
182 | /* If we've read so many entries we're going to ask for 2gb | |||||
183 | or more of memory, something is so wrong with this font | |||||
184 | directory that we should just give up before we overflow. */ | |||||
185 | return NULL((void *)0); | |||||
186 | newsize = table->size + 100; | |||||
187 | entry = realloc(table->entries, newsize * sizeof(FontEntryRec)); | |||||
188 | if (!entry) | |||||
189 | return (FontEntryPtr)0; | |||||
190 | table->size = newsize; | |||||
191 | table->entries = entry; | |||||
192 | } | |||||
193 | entry = &table->entries[table->used]; | |||||
194 | *entry = *prototype; | |||||
195 | entry->name.name = malloc(prototype->name.length + 1); | |||||
196 | if (!entry->name.name) | |||||
197 | return (FontEntryPtr)0; | |||||
198 | memcpy (entry->name.name, prototype->name.name, prototype->name.length)__builtin___memcpy_chk (entry->name.name, prototype->name .name, prototype->name.length, __builtin_object_size (entry ->name.name, 0)); | |||||
199 | entry->name.name[entry->name.length] = '\0'; | |||||
200 | table->used++; | |||||
201 | return entry; | |||||
202 | } | |||||
203 | ||||||
204 | /* | |||||
205 | * Compare two strings just like strcmp, but preserve decimal integer | |||||
206 | * sorting order, i.e. "2" < "10" or "iso8859-2" < "iso8859-10" < | |||||
207 | * "iso10646-1". Strings are sorted as if sequences of digits were | |||||
208 | * prefixed by a length indicator (i.e., does not ignore leading zeroes). | |||||
209 | * | |||||
210 | * Markus Kuhn <Markus.Kuhn@cl.cam.ac.uk> | |||||
211 | */ | |||||
212 | #define Xisdigit(c)('\060' <= (c) && (c) <= '\071') ('\060' <= (c) && (c) <= '\071') | |||||
213 | ||||||
214 | static int strcmpn(const char *s1, const char *s2) | |||||
215 | { | |||||
216 | int digits, predigits = 0; | |||||
217 | const char *ss1, *ss2; | |||||
218 | ||||||
219 | while (1) { | |||||
220 | if (*s1 == 0 && *s2 == 0) | |||||
221 | return 0; | |||||
222 | digits = Xisdigit(*s1)('\060' <= (*s1) && (*s1) <= '\071') && Xisdigit(*s2)('\060' <= (*s2) && (*s2) <= '\071'); | |||||
223 | if (digits && !predigits) { | |||||
224 | ss1 = s1; | |||||
225 | ss2 = s2; | |||||
226 | while (Xisdigit(*ss1)('\060' <= (*ss1) && (*ss1) <= '\071') && Xisdigit(*ss2)('\060' <= (*ss2) && (*ss2) <= '\071')) | |||||
227 | ss1++, ss2++; | |||||
228 | if (!Xisdigit(*ss1)('\060' <= (*ss1) && (*ss1) <= '\071') && Xisdigit(*ss2)('\060' <= (*ss2) && (*ss2) <= '\071')) | |||||
229 | return -1; | |||||
230 | if (Xisdigit(*ss1)('\060' <= (*ss1) && (*ss1) <= '\071') && !Xisdigit(*ss2)('\060' <= (*ss2) && (*ss2) <= '\071')) | |||||
231 | return 1; | |||||
232 | } | |||||
233 | if ((unsigned char)*s1 < (unsigned char)*s2) | |||||
234 | return -1; | |||||
235 | if ((unsigned char)*s1 > (unsigned char)*s2) | |||||
236 | return 1; | |||||
237 | predigits = digits; | |||||
238 | s1++, s2++; | |||||
239 | } | |||||
240 | } | |||||
241 | ||||||
242 | ||||||
243 | static int | |||||
244 | FontFileNameCompare(const void* a, const void* b) | |||||
245 | { | |||||
246 | FontEntryPtr a_name = (FontEntryPtr) a, | |||||
247 | b_name = (FontEntryPtr) b; | |||||
248 | ||||||
249 | return strcmpn(a_name->name.name, b_name->name.name); | |||||
250 | } | |||||
251 | ||||||
252 | void | |||||
253 | FontFileSortTable (FontTablePtr table) | |||||
254 | { | |||||
255 | if (!table->sorted) { | |||||
256 | qsort((char *) table->entries, table->used, sizeof(FontEntryRec), | |||||
257 | FontFileNameCompare); | |||||
258 | table->sorted = TRUE1; | |||||
259 | } | |||||
260 | } | |||||
261 | ||||||
262 | void | |||||
263 | FontFileSortDir(FontDirectoryPtr dir) | |||||
264 | { | |||||
265 | FontFileSortTable (&dir->scalable); | |||||
266 | FontFileSortTable (&dir->nonScalable); | |||||
267 | /* now that the table is fixed in size, swizzle the pointers */ | |||||
268 | FontFileSwitchStringsToBitmapPointers (dir); | |||||
269 | } | |||||
270 | ||||||
271 | /* | |||||
272 | Given a Font Table, SetupWildMatch() sets up various pointers and state | |||||
273 | information so the table can be searched for name(s) that match a given | |||||
274 | fontname pattern -- which may contain wildcards. Under certain | |||||
275 | circumstances, SetupWildMatch() will find the one table entry that | |||||
276 | matches the pattern. If those circumstances do not pertain, | |||||
277 | SetupWildMatch() returns a range within the the table that should be | |||||
278 | searched for matching name(s). With the information established by | |||||
279 | SetupWildMatch(), including state information in "private", the | |||||
280 | PatternMatch() procedure is then used to test names in the range for a | |||||
281 | match. | |||||
282 | */ | |||||
283 | ||||||
284 | #define isWild(c)((c) == 0x002a || (c) == 0x003f) ((c) == XK_asterisk0x002a || (c) == XK_question0x003f) | |||||
285 | #define isDigit(c)(0x0030 <= (c) && (c) <= 0x0039) (XK_00x0030 <= (c) && (c) <= XK_90x0039) | |||||
286 | ||||||
287 | static int | |||||
288 | SetupWildMatch(FontTablePtr table, FontNamePtr pat, | |||||
289 | int *leftp, int *rightp, int *privatep) | |||||
290 | { | |||||
291 | int nDashes; | |||||
292 | char c; | |||||
293 | char *t; | |||||
294 | char *firstWild; | |||||
295 | char *firstDigit; | |||||
296 | int first; | |||||
297 | int center, | |||||
298 | left, | |||||
299 | right; | |||||
300 | int result; | |||||
301 | char *name; | |||||
302 | ||||||
303 | name = pat->name; | |||||
304 | nDashes = pat->ndashes; | |||||
305 | firstWild = 0; | |||||
306 | firstDigit = 0; | |||||
307 | t = name; | |||||
308 | while ((c = *t++)) { | |||||
309 | if (isWild(c)((c) == 0x002a || (c) == 0x003f)) { | |||||
310 | if (!firstWild) | |||||
311 | firstWild = t - 1; | |||||
312 | } | |||||
313 | if (isDigit(c)(0x0030 <= (c) && (c) <= 0x0039)) { | |||||
314 | if (!firstDigit) | |||||
315 | firstDigit = t - 1; | |||||
316 | } | |||||
317 | } | |||||
318 | left = 0; | |||||
319 | right = table->used; | |||||
320 | if (firstWild) | |||||
321 | *privatep = nDashes; | |||||
322 | else | |||||
323 | *privatep = -1; | |||||
324 | if (!table->sorted) { | |||||
325 | *leftp = left; | |||||
326 | *rightp = right; | |||||
327 | return -1; | |||||
328 | } else if (firstWild) { | |||||
329 | if (firstDigit && firstDigit < firstWild) | |||||
330 | first = firstDigit - name; | |||||
331 | else | |||||
332 | first = firstWild - name; | |||||
333 | while (left < right) { | |||||
334 | center = (left + right) / 2; | |||||
335 | result = strncmp(name, table->entries[center].name.name, first); | |||||
336 | if (result == 0) | |||||
337 | break; | |||||
338 | if (result < 0) | |||||
339 | right = center; | |||||
340 | else | |||||
341 | left = center + 1; | |||||
342 | } | |||||
343 | *leftp = left; | |||||
344 | *rightp = right; | |||||
345 | return -1; | |||||
346 | } else { | |||||
347 | while (left < right) { | |||||
348 | center = (left + right) / 2; | |||||
349 | result = strcmpn(name, table->entries[center].name.name); | |||||
350 | if (result == 0) | |||||
351 | return center; | |||||
352 | if (result < 0) | |||||
353 | right = center; | |||||
354 | else | |||||
355 | left = center + 1; | |||||
356 | } | |||||
357 | *leftp = 1; | |||||
358 | *rightp = 0; | |||||
359 | return -1; | |||||
360 | } | |||||
361 | } | |||||
362 | ||||||
363 | static int | |||||
364 | PatternMatch(char *pat, int patdashes, char *string, int stringdashes) | |||||
365 | { | |||||
366 | char c, | |||||
367 | t; | |||||
368 | ||||||
369 | if (stringdashes < patdashes) | |||||
370 | return 0; | |||||
371 | for (;;) { | |||||
372 | switch (c = *pat++) { | |||||
373 | case '*': | |||||
374 | if (!(c = *pat++)) | |||||
375 | return 1; | |||||
376 | if (c == XK_minus0x002d) { | |||||
377 | patdashes--; | |||||
378 | for (;;) { | |||||
379 | while ((t = *string++) != XK_minus0x002d) | |||||
380 | if (!t) | |||||
381 | return 0; | |||||
382 | stringdashes--; | |||||
383 | if (PatternMatch(pat, patdashes, string, stringdashes)) | |||||
384 | return 1; | |||||
385 | if (stringdashes == patdashes) | |||||
386 | return 0; | |||||
387 | } | |||||
388 | } else { | |||||
389 | for (;;) { | |||||
390 | while ((t = *string++) != c) { | |||||
391 | if (!t) | |||||
392 | return 0; | |||||
393 | if (t == XK_minus0x002d) { | |||||
394 | if (stringdashes-- < patdashes) | |||||
395 | return 0; | |||||
396 | } | |||||
397 | } | |||||
398 | if (PatternMatch(pat, patdashes, string, stringdashes)) | |||||
399 | return 1; | |||||
400 | } | |||||
401 | } | |||||
402 | case '?': | |||||
403 | if (*string++ == XK_minus0x002d) | |||||
404 | stringdashes--; | |||||
405 | break; | |||||
406 | case '\0': | |||||
407 | return (*string == '\0'); | |||||
408 | case XK_minus0x002d: | |||||
409 | if (*string++ == XK_minus0x002d) { | |||||
410 | patdashes--; | |||||
411 | stringdashes--; | |||||
412 | break; | |||||
413 | } | |||||
414 | return 0; | |||||
415 | default: | |||||
416 | if (c == *string++) | |||||
417 | break; | |||||
418 | return 0; | |||||
419 | } | |||||
420 | } | |||||
421 | } | |||||
422 | ||||||
423 | int | |||||
424 | FontFileCountDashes (char *name, int namelen) | |||||
425 | { | |||||
426 | int ndashes = 0; | |||||
427 | ||||||
428 | while (namelen--) | |||||
429 | if (*name++ == '\055') /* avoid non ascii systems */ | |||||
430 | ++ndashes; | |||||
431 | return ndashes; | |||||
432 | } | |||||
433 | ||||||
434 | /* exported in public API in <X11/fonts/fntfil.h> */ | |||||
435 | char * | |||||
436 | FontFileSaveString (char *s)strdup(char *s) | |||||
437 | { | |||||
438 | return strdup(s); | |||||
439 | } | |||||
440 | #define FontFileSaveString(s)strdup(s) strdup(s) | |||||
441 | ||||||
442 | FontEntryPtr | |||||
443 | FontFileFindNameInScalableDir(FontTablePtr table, FontNamePtr pat, | |||||
444 | FontScalablePtr vals) | |||||
445 | { | |||||
446 | int i, | |||||
447 | start, | |||||
448 | stop, | |||||
449 | res, | |||||
450 | private; | |||||
451 | FontNamePtr name; | |||||
452 | ||||||
453 | if (!table->entries) | |||||
454 | return NULL((void *)0); | |||||
455 | if ((i = SetupWildMatch(table, pat, &start, &stop, &private)) >= 0) | |||||
456 | return &table->entries[i]; | |||||
457 | for (i = start; i < stop; i++) { | |||||
458 | name = &table->entries[i].name; | |||||
459 | res = PatternMatch(pat->name, private, name->name, name->ndashes); | |||||
460 | if (res > 0) | |||||
461 | { | |||||
462 | /* Check to see if enhancements requested are available */ | |||||
463 | if (vals) | |||||
464 | { | |||||
465 | int vs = vals->values_supplied; | |||||
466 | int cap; | |||||
467 | ||||||
468 | if (table->entries[i].type == FONT_ENTRY_SCALABLE0) | |||||
469 | cap = table->entries[i].u.scalable.renderer->capabilities; | |||||
470 | else if (table->entries[i].type == FONT_ENTRY_ALIAS3) | |||||
471 | cap = ~0; /* Calling code will have to see if true */ | |||||
472 | else | |||||
473 | cap = 0; | |||||
474 | if ((((vs & PIXELSIZE_MASK0x3) == PIXELSIZE_ARRAY0x2 || | |||||
475 | (vs & POINTSIZE_MASK0xc) == POINTSIZE_ARRAY0x8) && | |||||
476 | !(cap & CAP_MATRIX0x1)) || | |||||
477 | ((vs & CHARSUBSET_SPECIFIED0x40) && | |||||
478 | !(cap & CAP_CHARSUBSETTING0x2))) | |||||
479 | continue; | |||||
480 | } | |||||
481 | return &table->entries[i]; | |||||
482 | } | |||||
483 | if (res < 0) | |||||
484 | break; | |||||
485 | } | |||||
486 | return (FontEntryPtr)0; | |||||
487 | } | |||||
488 | ||||||
489 | FontEntryPtr | |||||
490 | FontFileFindNameInDir(FontTablePtr table, FontNamePtr pat) | |||||
491 | { | |||||
492 | return FontFileFindNameInScalableDir(table, pat, (FontScalablePtr)0); | |||||
493 | } | |||||
494 | ||||||
495 | int | |||||
496 | FontFileFindNamesInScalableDir(FontTablePtr table, FontNamePtr pat, int max, | |||||
497 | FontNamesPtr names, FontScalablePtr vals, | |||||
498 | int alias_behavior, int *newmax) | |||||
499 | { | |||||
500 | int i, | |||||
501 | start, | |||||
502 | stop, | |||||
503 | res, | |||||
504 | private; | |||||
505 | int ret = Successful85; | |||||
506 | FontEntryPtr fname; | |||||
507 | FontNamePtr name; | |||||
508 | ||||||
509 | if (max <= 0) | |||||
510 | return Successful85; | |||||
511 | if ((i = SetupWildMatch(table, pat, &start, &stop, &private)) >= 0) { | |||||
512 | if (alias_behavior == NORMAL_ALIAS_BEHAVIOR0 || | |||||
513 | table->entries[i].type != FONT_ENTRY_ALIAS3) | |||||
514 | { | |||||
515 | name = &table->entries[i].name; | |||||
516 | if (newmax) *newmax = max - 1; | |||||
517 | return xfont2_add_font_names_name(names, name->name, name->length); | |||||
518 | } | |||||
519 | start = i; | |||||
520 | stop = i + 1; | |||||
521 | } | |||||
522 | for (i = start, fname = &table->entries[start]; i < stop; i++, fname++) { | |||||
523 | res = PatternMatch(pat->name, private, fname->name.name, fname->name.ndashes); | |||||
524 | if (res > 0) { | |||||
525 | if (vals) | |||||
526 | { | |||||
527 | int vs = vals->values_supplied; | |||||
528 | int cap; | |||||
529 | ||||||
530 | if (fname->type == FONT_ENTRY_SCALABLE0) | |||||
531 | cap = fname->u.scalable.renderer->capabilities; | |||||
532 | else if (fname->type == FONT_ENTRY_ALIAS3) | |||||
533 | cap = ~0; /* Calling code will have to see if true */ | |||||
534 | else | |||||
535 | cap = 0; | |||||
536 | if ((((vs & PIXELSIZE_MASK0x3) == PIXELSIZE_ARRAY0x2 || | |||||
537 | (vs & POINTSIZE_MASK0xc) == POINTSIZE_ARRAY0x8) && | |||||
538 | !(cap & CAP_MATRIX0x1)) || | |||||
539 | ((vs & CHARSUBSET_SPECIFIED0x40) && | |||||
540 | !(cap & CAP_CHARSUBSETTING0x2))) | |||||
541 | continue; | |||||
542 | } | |||||
543 | ||||||
544 | if ((alias_behavior & IGNORE_SCALABLE_ALIASES(1<<1)) && | |||||
545 | fname->type == FONT_ENTRY_ALIAS3) | |||||
546 | { | |||||
547 | FontScalableRec tmpvals; | |||||
548 | if (FontParseXLFDName (fname->name.name, &tmpvals, | |||||
549 | FONT_XLFD_REPLACE_NONE0) && | |||||
550 | !(tmpvals.values_supplied & SIZE_SPECIFY_MASK0xf)) | |||||
551 | continue; | |||||
552 | } | |||||
553 | ||||||
554 | ret = xfont2_add_font_names_name(names, fname->name.name, fname->name.length); | |||||
555 | if (ret != Successful85) | |||||
556 | goto bail; | |||||
557 | ||||||
558 | /* If alias_behavior is LIST_ALIASES_AND_TARGET_NAMES, mark | |||||
559 | this entry as an alias by negating its length and follow | |||||
560 | it by the resolved name */ | |||||
561 | if ((alias_behavior & LIST_ALIASES_AND_TARGET_NAMES(1<<0)) && | |||||
562 | fname->type == FONT_ENTRY_ALIAS3) | |||||
563 | { | |||||
564 | names->length[names->nnames - 1] = | |||||
565 | -names->length[names->nnames - 1]; | |||||
566 | ret = xfont2_add_font_names_name(names, fname->u.alias.resolved, | |||||
567 | strlen(fname->u.alias.resolved)); | |||||
568 | if (ret != Successful85) | |||||
569 | goto bail; | |||||
570 | } | |||||
571 | ||||||
572 | if (--max <= 0) | |||||
573 | break; | |||||
574 | } else if (res < 0) | |||||
575 | break; | |||||
576 | } | |||||
577 | bail: ; | |||||
578 | if (newmax) *newmax = max; | |||||
579 | return ret; | |||||
580 | } | |||||
581 | ||||||
582 | int | |||||
583 | FontFileFindNamesInDir(FontTablePtr table, FontNamePtr pat, | |||||
584 | int max, FontNamesPtr names) | |||||
585 | { | |||||
586 | return FontFileFindNamesInScalableDir(table, pat, max, names, | |||||
587 | (FontScalablePtr)0, | |||||
588 | NORMAL_ALIAS_BEHAVIOR0, (int *)0); | |||||
589 | } | |||||
590 | ||||||
591 | Bool | |||||
592 | FontFileMatchName(char *name, int length, FontNamePtr pat) | |||||
593 | { | |||||
594 | /* Perform a fontfile-type name match on a single name */ | |||||
595 | FontTableRec table; | |||||
596 | FontEntryRec entries[1]; | |||||
597 | ||||||
598 | /* Dummy up a table */ | |||||
599 | table.used = 1; | |||||
600 | table.size = 1; | |||||
601 | table.sorted = TRUE1; | |||||
602 | table.entries = entries; | |||||
603 | entries[0].name.name = name; | |||||
604 | entries[0].name.length = length; | |||||
605 | entries[0].name.ndashes = FontFileCountDashes(name, length); | |||||
606 | ||||||
607 | return FontFileFindNameInDir(&table, pat) != (FontEntryPtr)0; | |||||
608 | } | |||||
609 | ||||||
610 | /* | |||||
611 | * Add a font file to a directory. This handles bitmap and | |||||
612 | * scalable names both | |||||
613 | */ | |||||
614 | ||||||
615 | Bool | |||||
616 | FontFileAddFontFile (FontDirectoryPtr dir, char *fontName, char *fileName) | |||||
617 | { | |||||
618 | FontEntryRec entry; | |||||
619 | FontScalableRec vals, zeroVals; | |||||
620 | FontRendererPtr renderer; | |||||
621 | FontEntryPtr existing; | |||||
622 | FontScalableExtraPtr extra; | |||||
623 | FontEntryPtr bitmap = 0, scalable; | |||||
624 | Bool isscale; | |||||
625 | Bool scalable_xlfd; | |||||
626 | ||||||
627 | renderer = FontFileMatchRenderer (fileName); | |||||
628 | if (!renderer) | |||||
629 | return FALSE0; | |||||
630 | entry.name.length = strlen (fontName); | |||||
631 | if (entry.name.length > MAXFONTNAMELEN1024) | |||||
632 | entry.name.length = MAXFONTNAMELEN1024; | |||||
633 | entry.name.name = fontName; | |||||
634 | CopyISOLatin1Lowered (entry.name.name, fontName, entry.name.length); | |||||
635 | entry.name.ndashes = FontFileCountDashes (entry.name.name, entry.name.length); | |||||
636 | entry.name.name[entry.name.length] = '\0'; | |||||
637 | /* | |||||
638 | * Add a bitmap name if the incoming name isn't an XLFD name, or | |||||
639 | * if it isn't a scalable name (i.e. non-zero scalable fields) | |||||
640 | * | |||||
641 | * If name of bitmapped font contains XLFD enhancements, do not add | |||||
642 | * a scalable version of the name... this can lead to confusion and | |||||
643 | * ambiguity between the font name and the field enhancements. | |||||
644 | */ | |||||
645 | isscale = entry.name.ndashes == 14 && | |||||
646 | FontParseXLFDName(entry.name.name, | |||||
647 | &vals, FONT_XLFD_REPLACE_NONE0) && | |||||
648 | (vals.values_supplied & PIXELSIZE_MASK0x3) != PIXELSIZE_ARRAY0x2 && | |||||
649 | (vals.values_supplied & POINTSIZE_MASK0xc) != POINTSIZE_ARRAY0x8 && | |||||
650 | !(vals.values_supplied & ENHANCEMENT_SPECIFY_MASK0x40); | |||||
651 | #define UNSCALED_ATTRIB"unscaled" "unscaled" | |||||
652 | scalable_xlfd = (isscale && | |||||
653 | (((vals.values_supplied & PIXELSIZE_MASK0x3) == 0) || | |||||
654 | ((vals.values_supplied & POINTSIZE_MASK0xc) == 0))); | |||||
655 | /* | |||||
656 | * For scalable fonts without a scalable XFLD, check if the "unscaled" | |||||
657 | * attribute is present. | |||||
658 | */ | |||||
659 | if (isscale && !scalable_xlfd && | |||||
660 | dir->attributes && dir->attributes[0] == ':') { | |||||
661 | char *ptr1 = dir->attributes + 1; | |||||
662 | char *ptr2; | |||||
663 | int length; | |||||
664 | int uslength = strlen(UNSCALED_ATTRIB"unscaled"); | |||||
665 | ||||||
666 | do { | |||||
667 | ptr2 = strchr(ptr1, ':'); | |||||
668 | if (ptr2) | |||||
669 | length = ptr2 - ptr1; | |||||
670 | else | |||||
671 | length = dir->attributes + strlen(dir->attributes) - ptr1; | |||||
672 | if (length == uslength && !strncmp(ptr1, UNSCALED_ATTRIB"unscaled", uslength)) | |||||
673 | isscale = FALSE0; | |||||
674 | if (ptr2) | |||||
675 | ptr1 = ptr2 + 1; | |||||
676 | } while (ptr2); | |||||
677 | } | |||||
678 | if (!isscale || (vals.values_supplied & SIZE_SPECIFY_MASK0xf)) | |||||
679 | { | |||||
680 | /* | |||||
681 | * If the renderer doesn't support OpenBitmap, FontFileOpenFont | |||||
682 | * will still do the right thing. | |||||
683 | */ | |||||
684 | entry.type = FONT_ENTRY_BITMAP2; | |||||
685 | entry.u.bitmap.renderer = renderer; | |||||
686 | entry.u.bitmap.pFont = NullFont((FontPtr) 0); | |||||
687 | if (!(entry.u.bitmap.fileName = FontFileSaveString (fileName)strdup(fileName))) | |||||
688 | return FALSE0; | |||||
689 | if (!(bitmap = FontFileAddEntry (&dir->nonScalable, &entry))) | |||||
690 | { | |||||
691 | free (entry.u.bitmap.fileName); | |||||
692 | return FALSE0; | |||||
693 | } | |||||
694 | } | |||||
695 | /* | |||||
696 | * Parse out scalable fields from XLFD names - a scalable name | |||||
697 | * just gets inserted, a scaled name has more things to do. | |||||
698 | */ | |||||
699 | if (isscale) | |||||
700 | { | |||||
701 | if (vals.values_supplied & SIZE_SPECIFY_MASK0xf) | |||||
702 | { | |||||
703 | bzero((char *)&zeroVals, sizeof(zeroVals))__builtin___memset_chk ((char *)&zeroVals, 0, sizeof(zeroVals ), __builtin_object_size ((char *)&zeroVals, 0)); | |||||
704 | zeroVals.x = vals.x; | |||||
705 | zeroVals.y = vals.y; | |||||
706 | zeroVals.values_supplied = PIXELSIZE_SCALAR0x1 | POINTSIZE_SCALAR0x4; | |||||
707 | FontParseXLFDName (entry.name.name, &zeroVals, | |||||
708 | FONT_XLFD_REPLACE_VALUE3); | |||||
709 | entry.name.length = strlen (entry.name.name); | |||||
710 | existing = FontFileFindNameInDir (&dir->scalable, &entry.name); | |||||
711 | if (existing) | |||||
712 | { | |||||
713 | if ((vals.values_supplied & POINTSIZE_MASK0xc) == | |||||
714 | POINTSIZE_SCALAR0x4 && | |||||
715 | (int)(vals.point_matrix[3] * 10) == GetDefaultPointSize__libxfont__GetDefaultPointSize()) | |||||
716 | { | |||||
717 | existing->u.scalable.extra->defaults = vals; | |||||
718 | ||||||
719 | free (existing->u.scalable.fileName); | |||||
720 | if (!(existing->u.scalable.fileName = FontFileSaveString (fileName)strdup(fileName))) | |||||
721 | return FALSE0; | |||||
722 | } | |||||
723 | if(bitmap) | |||||
724 | { | |||||
725 | FontFileCompleteXLFD(&vals, &vals); | |||||
726 | FontFileAddScaledInstance (existing, &vals, NullFont((FontPtr) 0), | |||||
727 | bitmap->name.name); | |||||
728 | return TRUE1; | |||||
729 | } | |||||
730 | } | |||||
731 | } | |||||
732 | if (!(entry.u.scalable.fileName = FontFileSaveString (fileName)strdup(fileName))) | |||||
733 | return FALSE0; | |||||
734 | extra = malloc (sizeof (FontScalableExtraRec)); | |||||
735 | if (!extra) | |||||
736 | { | |||||
737 | free (entry.u.scalable.fileName); | |||||
738 | return FALSE0; | |||||
739 | } | |||||
740 | bzero((char *)&extra->defaults, sizeof(extra->defaults))__builtin___memset_chk ((char *)&extra->defaults, 0, sizeof (extra->defaults), __builtin_object_size ((char *)&extra ->defaults, 0)); | |||||
741 | if ((vals.values_supplied & POINTSIZE_MASK0xc) == POINTSIZE_SCALAR0x4 && | |||||
742 | (int)(vals.point_matrix[3] * 10) == GetDefaultPointSize__libxfont__GetDefaultPointSize()) | |||||
743 | extra->defaults = vals; | |||||
744 | else | |||||
745 | { | |||||
746 | FontResolutionPtr resolution; | |||||
747 | int num; | |||||
748 | int default_point_size = GetDefaultPointSize__libxfont__GetDefaultPointSize(); | |||||
749 | ||||||
750 | extra->defaults.point_matrix[0] = | |||||
751 | extra->defaults.point_matrix[3] = | |||||
752 | (double)default_point_size / 10.0; | |||||
753 | extra->defaults.point_matrix[1] = | |||||
754 | extra->defaults.point_matrix[2] = 0.0; | |||||
755 | extra->defaults.values_supplied = | |||||
756 | POINTSIZE_SCALAR0x4 | PIXELSIZE_UNDEFINED0; | |||||
757 | extra->defaults.width = -1; | |||||
758 | if (vals.x <= 0 || vals.y <= 0) | |||||
759 | { | |||||
760 | resolution = GetClientResolutions__libxfont__GetClientResolutions (&num); | |||||
761 | if (resolution && num > 0) | |||||
762 | { | |||||
763 | extra->defaults.x = resolution->x_resolution; | |||||
764 | extra->defaults.y = resolution->y_resolution; | |||||
765 | } | |||||
766 | else | |||||
767 | { | |||||
768 | extra->defaults.x = 75; | |||||
769 | extra->defaults.y = 75; | |||||
770 | } | |||||
771 | } | |||||
772 | else | |||||
773 | { | |||||
774 | extra->defaults.x = vals.x; | |||||
775 | extra->defaults.y = vals.y; | |||||
776 | } | |||||
777 | FontFileCompleteXLFD (&extra->defaults, &extra->defaults); | |||||
778 | } | |||||
779 | extra->numScaled = 0; | |||||
780 | extra->sizeScaled = 0; | |||||
781 | extra->scaled = 0; | |||||
782 | extra->private = 0; | |||||
783 | entry.type = FONT_ENTRY_SCALABLE0; | |||||
784 | entry.u.scalable.renderer = renderer; | |||||
785 | entry.u.scalable.extra = extra; | |||||
786 | if (!(scalable = FontFileAddEntry (&dir->scalable, &entry))) | |||||
787 | { | |||||
788 | free (extra); | |||||
789 | free (entry.u.scalable.fileName); | |||||
790 | return FALSE0; | |||||
791 | } | |||||
792 | if (vals.values_supplied & SIZE_SPECIFY_MASK0xf) | |||||
793 | { | |||||
794 | if(bitmap) | |||||
795 | { | |||||
796 | FontFileCompleteXLFD(&vals, &vals); | |||||
797 | FontFileAddScaledInstance (scalable, &vals, NullFont((FontPtr) 0), | |||||
798 | bitmap->name.name); | |||||
799 | } | |||||
800 | } | |||||
801 | } | |||||
802 | return TRUE1; | |||||
803 | } | |||||
804 | ||||||
805 | Bool | |||||
806 | FontFileAddFontAlias (FontDirectoryPtr dir, char *aliasName, char *fontName) | |||||
807 | { | |||||
808 | FontEntryRec entry; | |||||
809 | ||||||
810 | if (strcmp(aliasName,fontName) == 0) { | |||||
811 | /* Don't allow an alias to point to itself and create a loop */ | |||||
812 | return FALSE0; | |||||
813 | } | |||||
814 | entry.name.length = strlen (aliasName); | |||||
815 | CopyISOLatin1Lowered (aliasName, aliasName, entry.name.length); | |||||
816 | entry.name.name = aliasName; | |||||
817 | entry.name.ndashes = FontFileCountDashes (entry.name.name, entry.name.length); | |||||
818 | entry.type = FONT_ENTRY_ALIAS3; | |||||
819 | if (!(entry.u.alias.resolved = FontFileSaveString (fontName)strdup(fontName))) | |||||
820 | return FALSE0; | |||||
821 | if (!FontFileAddEntry (&dir->nonScalable, &entry)) | |||||
822 | { | |||||
823 | free (entry.u.alias.resolved); | |||||
824 | return FALSE0; | |||||
825 | } | |||||
826 | return TRUE1; | |||||
827 | } |