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