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