fonts.c revision 34f90d55
1/* 2 * font control 3 */ 4/* 5 6Copyright 1990, 1991, 1998 The Open Group 7 8Permission to use, copy, modify, distribute, and sell this software and its 9documentation for any purpose is hereby granted without fee, provided that 10the above copyright notice appear in all copies and that both that 11copyright notice and this permission notice appear in supporting 12documentation. 13 14The above copyright notice and this permission notice shall be included in 15all copies or substantial portions of the Software. 16 17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 24Except as contained in this notice, the name of The Open Group shall not be 25used in advertising or otherwise to promote the sale, use or other dealings 26in this Software without prior written authorization from The Open Group. 27 28 * Copyright 1990, 1991 Network Computing Devices; 29 * Portions Copyright 1987 by Digital Equipment Corporation 30 * 31 * Permission to use, copy, modify, distribute, and sell this software and 32 * its documentation for any purpose is hereby granted without fee, provided 33 * that the above copyright notice appear in all copies and that both that 34 * copyright notice and this permission notice appear in supporting 35 * documentation, and that the names of Network Computing Devices or Digital 36 * not be used in advertising or publicity pertaining to distribution 37 * of the software without specific, written prior permission. 38 * 39 * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH 40 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 41 * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES 42 * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 43 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 44 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 45 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 46 * THIS SOFTWARE. 47 */ 48/*#define DEBUG*/ 49 50#include "config.h" 51 52#include <X11/fonts/FS.h> 53#include <X11/fonts/FSproto.h> 54#include <stdio.h> 55#include <stdlib.h> 56#include <X11/Xos.h> 57#include "clientstr.h" 58#include "fsresource.h" 59#include "difsfnst.h" 60#include <X11/fonts/fontstruct.h> 61#include "closestr.h" 62#include "globals.h" 63#include "difs.h" 64#include "dispatch.h" 65#include "swaprep.h" 66 67static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0; 68static int num_fpes = 0; 69static FPEFunctions *fpe_functions = (FPEFunctions *) 0; 70static int num_fpe_types = 0; 71 72static int num_slept_fpes = 0; 73static int size_slept_fpes = 0; 74static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0; 75 76#define NUM_IDS_PER_CLIENT 5 77 78int 79FontToFSError(int err) 80{ 81 switch (err) { 82 case Successful: 83 return FSSuccess; 84 case AllocError: 85 return FSBadAlloc; 86 case BadFontName: 87 case BadFontPath: 88 return FSBadName; 89 case BadFontFormat: 90 return FSBadFormat; 91 case BadCharRange: 92 return FSBadRange; 93 default: 94 return err; 95 } 96} 97 98static inline void 99UseFPE(FontPathElementPtr fpe) 100{ 101 fpe->refcount++; 102} 103 104static inline void 105FreeFPE(FontPathElementPtr fpe) 106{ 107 fpe->refcount--; 108 if (fpe->refcount == 0) { 109 (*fpe_functions[fpe->type].free_fpe) (fpe); 110 fsfree(fpe->name); 111 fsfree(fpe); 112 } 113} 114 115/* 116 * note that the font wakeup queue is not refcounted. this is because 117 * an fpe needs to be added when it's inited, and removed when it's finally 118 * freed, in order to handle any data that isn't requested, like FS events. 119 * 120 * since the only thing that should call these routines is the renderer's 121 * init_fpe() and free_fpe(), there shouldn't be any problem in using 122 * freed data. 123 */ 124static void 125QueueFontWakeup(FontPathElementPtr fpe) 126{ 127 int i; 128 FontPathElementPtr *new; 129 130 for (i = 0; i < num_slept_fpes; i++) { 131 if (slept_fpes[i] == fpe) { 132 133#ifdef DEBUG 134 fprintf(stderr, "re-queueing fpe wakeup\n"); 135#endif 136 137 return; 138 } 139 } 140 if (num_slept_fpes == size_slept_fpes) { 141 new = (FontPathElementPtr *) 142 fsrealloc(slept_fpes, 143 sizeof(FontPathElementPtr) * (size_slept_fpes + 4)); 144 if (!new) 145 return; 146 slept_fpes = new; 147 size_slept_fpes += 4; 148 } 149 slept_fpes[num_slept_fpes] = fpe; 150 num_slept_fpes++; 151} 152 153static void 154RemoveFontWakeup(FontPathElementPtr fpe) 155{ 156 int i, 157 j; 158 159 for (i = 0; i < num_slept_fpes; i++) { 160 if (slept_fpes[i] == fpe) { 161 for (j = i; j < num_slept_fpes; j++) { 162 slept_fpes[j] = slept_fpes[j + 1]; 163 } 164 num_slept_fpes--; 165 return; 166 } 167 } 168} 169 170/* ARGSUSED */ 171static void 172FontWakeup(pointer data, int count, unsigned long *LastSelectMask) 173{ 174 int i; 175 FontPathElementPtr fpe; 176 177 if (count < 0) 178 return; /* ignore -1 return from select XXX */ 179 /* wake up any fpe's that may be waiting for information */ 180 for (i = 0; i < num_slept_fpes; i++) { 181 fpe = slept_fpes[i]; 182 (void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask); 183 } 184} 185 186static Bool 187add_id_to_list(FontIDListPtr ids, Font fid) 188{ 189 Font *newlist; 190 191 /* 192 * assumes the list is packed tightly 193 */ 194 if (ids->num == ids->size) { 195 /* increase size of array */ 196 newlist = (Font *) fsrealloc(ids->client_list, 197 sizeof(Font) * (ids->size + NUM_IDS_PER_CLIENT)); 198 if (!newlist) 199 return FALSE; 200 ids->client_list = newlist; 201 ids->size += NUM_IDS_PER_CLIENT; 202 } 203 ids->client_list[ids->num++] = fid; 204 return TRUE; 205} 206 207static void 208remove_id_from_list(FontIDListPtr ids, Font fid) 209{ 210 int i; 211 212 for (i = 0; i < ids->num; i++) { 213 if (ids->client_list[i] == fid) { 214 /* a memmove() might be better here */ 215 while (i < ids->num) { 216 ids->client_list[i] = ids->client_list[i + 1]; 217 i++; 218 } 219 ids->num--; 220 return; 221 } 222 } 223 assert(0); 224} 225 226static FontIDListPtr 227make_clients_id_list(void) 228{ 229 FontIDListPtr ids; 230 Font *fids; 231 232 ids = (FontIDListPtr) fsalloc(sizeof(FontIDListRec)); 233 fids = (Font *) fsalloc(sizeof(Font) * NUM_IDS_PER_CLIENT); 234 if (!ids || !fids) { 235 fsfree(ids); 236 fsfree(fids); 237 return (FontIDListPtr) 0; 238 } 239 bzero((char *) fids, sizeof(Font) * NUM_IDS_PER_CLIENT); 240 ids->client_list = fids; 241 ids->size = NUM_IDS_PER_CLIENT; 242 ids->num = 0; 243 return ids; 244} 245 246static void 247free_svrPrivate(pointer svrPrivate) 248{ 249 int i; 250 FontIDListPtr *idlist, ids; 251 252 idlist = (FontIDListPtr *) svrPrivate; 253 if (idlist) { 254 for (i = 0; i < MAXCLIENTS; i++) { 255 ids = idlist[i]; 256 if (ids) { 257 fsfree((char *) ids->client_list); 258 fsfree((char *) ids); 259 } 260 } 261 fsfree((char *) idlist); 262 } 263} 264 265#undef cPtr 266#define cPtr ((OFclosurePtr )data) 267 268static Bool 269do_open_font(ClientPtr client, pointer data) 270{ 271 FontPtr pfont = NullFont; 272 FontPathElementPtr fpe = NULL; 273 int err = 0; 274 int i; 275 char *alias, 276 *newname; 277 int newlen; 278 ClientFontPtr cfp; 279 Font orig; 280 FontIDListPtr *idlist, 281 ids; 282 int aliascount = 20; 283 284 if (client->clientGone == CLIENT_GONE) { 285 if (cPtr->current_fpe < cPtr->num_fpes) { 286 fpe = cPtr->fpe_list[cPtr->current_fpe]; 287 (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 288 } 289 err = Successful; 290 goto dropout; 291 } 292 while (cPtr->current_fpe < cPtr->num_fpes) { 293 fpe = cPtr->fpe_list[cPtr->current_fpe]; 294 err = (*fpe_functions[fpe->type].open_font) 295 ((pointer) cPtr->client, fpe, cPtr->flags, 296 cPtr->fontname, cPtr->fnamelen, cPtr->format, cPtr->format_mask, 297 cPtr->fontid, &pfont, &alias, 298 cPtr->non_cachable_font && cPtr->non_cachable_font->fpe == fpe ? 299 cPtr->non_cachable_font : 300 (FontPtr)0); 301 302 if (err == FontNameAlias && alias) { 303 newlen = strlen(alias); 304 newname = (char *) fsrealloc(cPtr->fontname, newlen); 305 if (!newname) { 306 err = AllocError; 307 break; 308 } 309 memmove( newname, alias, newlen); 310 cPtr->fontname = newname; 311 cPtr->fnamelen = newlen; 312 cPtr->current_fpe = 0; 313 if (--aliascount <= 0) break; 314 continue; 315 } 316 if (err == BadFontName) { 317 cPtr->current_fpe++; 318 continue; 319 } 320 if (err == Suspended) { 321 if (!cPtr->slept) { 322 cPtr->slept = TRUE; 323 ClientSleep(client, do_open_font, (pointer) cPtr); 324 } 325 return TRUE; 326 } 327 break; 328 } 329 if (err != Successful) { 330 goto dropout; 331 } 332 if (!pfont) { 333 err = BadFontName; 334 goto dropout; 335 } 336 cfp = (ClientFontPtr) fsalloc(sizeof(ClientFontRec)); 337 if (!cfp) { 338 err = AllocError; 339 goto dropout; 340 } 341 cfp->font = pfont; 342 cfp->clientindex = cPtr->client->index; 343 344 if (fontPatternCache && pfont != cPtr->non_cachable_font) 345 CacheFontPattern(fontPatternCache, cPtr->orig_name, cPtr->orig_len, pfont); 346 347 /* either pull out the other id or make the array */ 348 if (pfont->refcnt != 0) { 349 idlist = (FontIDListPtr *) pfont->svrPrivate; 350 ids = idlist[cPtr->client->index]; 351 if (!ids) { 352 ids = make_clients_id_list(); 353 if (!ids) { 354 err = AllocError; 355 fsfree(cfp); 356 goto dropout; 357 } 358 idlist[cPtr->client->index] = ids; 359 } 360 orig = (ids->num > 0) ? ids->client_list[0] : (Font)0; 361 } else { 362 idlist = (FontIDListPtr *) fsalloc(sizeof(FontIDListPtr) * MAXCLIENTS); 363 if (!idlist) { 364 err = AllocError; 365 fsfree(cfp); 366 goto dropout; 367 } 368 ids = make_clients_id_list(); 369 if (!ids) { 370 err = AllocError; 371 fsfree(idlist); 372 fsfree(cfp); 373 goto dropout; 374 } 375 bzero((char *) idlist, (sizeof(FontIDListPtr) * MAXCLIENTS)); 376 idlist[cPtr->client->index] = ids; 377 orig = (Font) 0; 378 pfont->svrPrivate = (pointer) idlist; 379 } 380 if (!AddResource(cPtr->client->index, cPtr->fontid, RT_FONT, (pointer) cfp)) { 381 fsfree(cfp); 382 free_svrPrivate(pfont->svrPrivate); 383 pfont->svrPrivate = (pointer) 0; 384 err = AllocError; 385 goto dropout; 386 } 387 else { 388 /* send the reply */ 389 fsOpenBitmapFontReply rep = { 390 .type = FS_Reply, 391 .otherid_valid = orig ? TRUE : FALSE, 392 .sequenceNumber = client->sequence, 393 .length = SIZEOF(fsOpenBitmapFontReply) >> 2, 394 .otherid = orig, 395 .cachable = pfont->info.cachable 396 }; 397 WriteReplyToClient(client, 398 SIZEOF(fsOpenBitmapFontReply), &rep); 399 add_id_to_list(ids, cPtr->fontid); 400 if (pfont->refcnt == 0) { 401 if (!pfont->fpe) 402 pfont->fpe = fpe; 403 UseFPE(pfont->fpe); 404 } 405 pfont->refcnt++; 406 } 407dropout: 408 if (err != Successful) { 409 SendErrToClient(cPtr->client, FontToFSError(err), (pointer) &(cPtr->fontid)); 410 } 411 if (cPtr->slept) 412 ClientWakeup(cPtr->client); 413 for (i = 0; i < cPtr->num_fpes; i++) { 414 FreeFPE(cPtr->fpe_list[i]); 415 } 416 fsfree(cPtr->fpe_list); 417 fsfree(cPtr->fontname); 418 fsfree(cPtr); 419 return TRUE; 420} 421 422int 423OpenFont( 424 ClientPtr client, 425 Font fid, 426 fsBitmapFormat format, 427 fsBitmapFormatMask format_mask, 428 int namelen, 429 char *name) 430{ 431 FontPtr pfont = (FontPtr)0; 432 OFclosurePtr c; 433 FontIDListPtr *idlist, 434 ids; 435 int i; 436 437 if (namelen == 0 || namelen > XLFDMAXFONTNAMELEN) { 438 SendErrToClient(client, FSBadName, (pointer) 0); 439 return FSBadName; 440 } 441#ifdef DEBUG 442 fprintf(stderr,"OpenFont: %sn",name); 443#endif 444 /* 445 ** Check name cache. If we find a cached version of this font that 446 ** is cachable, immediately satisfy the request with it. If we find 447 ** a cached version of this font that is non-cachable, we do not 448 ** satisfy the request with it. Instead, we pass the FontPtr to the 449 ** FPE's open_font code (the fontfile FPE in turn passes the 450 ** information to the rasterizer; the fserve FPE ignores it). 451 ** 452 ** Presumably, the font is marked non-cachable because the FPE has 453 ** put some licensing restrictions on it. If the FPE, using 454 ** whatever logic it relies on, determines that it is willing to 455 ** share this existing font with the client, then it has the option 456 ** to return the FontPtr we passed it as the newly-opened font. 457 ** This allows the FPE to exercise its licensing logic without 458 ** having to create another instance of a font that already exists. 459 */ 460 461 if (fontPatternCache && 462 (pfont = FindCachedFontPattern(fontPatternCache, name, namelen)) && 463 pfont->info.cachable) { 464 ClientFontPtr cfp; 465 466 idlist = (FontIDListPtr *) pfont->svrPrivate; 467 ids = idlist[client->index]; 468 if (!ids) { 469 ids = make_clients_id_list(); 470 if (!ids) { 471 goto lowmem; 472 } 473 idlist[client->index] = ids; 474 } 475 cfp = (ClientFontPtr) fsalloc(sizeof(ClientFontRec)); 476 if (!cfp) { 477 lowmem: 478 SendErrToClient(client, FSBadAlloc, (pointer) 0); 479 return FSBadAlloc; 480 } 481 cfp->font = pfont; 482 cfp->clientindex = client->index; 483 if (!AddResource(client->index, fid, RT_FONT, (pointer) cfp)) { 484 goto lowmem; 485 } 486 if (!add_id_to_list(ids, fid)) { 487 goto lowmem; 488 } 489 else { 490 fsOpenBitmapFontReply rep = { 491 .type = FS_Reply, 492 .otherid_valid = (ids->num > 1) ? TRUE : FALSE, 493 .sequenceNumber = client->sequence, 494 .length = SIZEOF(fsOpenBitmapFontReply) >> 2, 495 .otherid = (ids->num > 1) ? ids->client_list[0] : 0, 496 .cachable = TRUE /* XXX */ 497 }; 498 WriteReplyToClient(client, 499 SIZEOF(fsOpenBitmapFontReply), &rep); 500 pfont->refcnt++; 501 return FSSuccess; 502 } 503 } 504 c = (OFclosurePtr) fsalloc(sizeof(OFclosureRec)); 505 if (!c) 506 goto lowmem; 507 c->fontname = (char *) fsalloc(namelen); 508 if (!c->fontname) { 509 fsfree(c); 510 goto lowmem; 511 } 512 /* 513 * copy the current FPE list, so that if it gets changed by another client 514 * while we're blocking, the request still appears atomic 515 */ 516 c->fpe_list = (FontPathElementPtr *) 517 fsalloc(sizeof(FontPathElementPtr) * num_fpes); 518 if (!c->fpe_list) { 519 fsfree(c->fontname); 520 fsfree(c); 521 goto lowmem; 522 } 523 memmove( c->fontname, name, namelen); 524 for (i = 0; i < num_fpes; i++) { 525 c->fpe_list[i] = font_path_elements[i]; 526 UseFPE(c->fpe_list[i]); 527 } 528 c->client = client; 529 c->fontid = fid; 530 c->current_fpe = 0; 531 c->num_fpes = num_fpes; 532 c->fnamelen = namelen; 533 c->orig_name = name; 534 c->orig_len = namelen; 535 c->slept = FALSE; 536 c->flags = (FontLoadInfo | FontLoadProps); 537 c->format = format; 538 c->format_mask = format_mask; 539 c->non_cachable_font = pfont; 540 541 (void) do_open_font(client, (pointer) c); 542 return FSSuccess; 543} 544 545static int 546close_font(FontPtr pfont) 547{ 548 FontPathElementPtr fpe; 549 550 assert(pfont); 551 if (--pfont->refcnt == 0) { 552 if (fontPatternCache) 553 RemoveCachedFontPattern(fontPatternCache, pfont); 554 fpe = pfont->fpe; 555 free_svrPrivate(pfont->svrPrivate); 556 (*fpe_functions[fpe->type].close_font) (fpe, pfont); 557 FreeFPE(fpe); 558 } 559 return FSSuccess; 560} 561 562int 563CloseClientFont( 564 ClientFontPtr cfp, 565 FSID fid) 566{ 567 FontIDListPtr *idlist; 568 FontIDListPtr ids; 569 int ret; 570 571 assert(cfp); 572 /* clear otherid id */ 573 idlist = (FontIDListPtr *) cfp->font->svrPrivate; 574 ids = idlist[cfp->clientindex]; 575 remove_id_from_list(ids, fid); 576 ret = close_font(cfp->font); 577 fsfree((char *) cfp); 578 return ret; 579} 580 581/* 582 * search all the known FPE prefixes looking for one to match the given 583 * FPE name 584 */ 585static int 586determine_fpe_type(char *name) 587{ 588 int i; 589 for (i = 0; i < num_fpe_types; i++) { 590 if ((*fpe_functions[i].name_check) (name)) 591 return i; 592 } 593 return -1; 594} 595 596static void 597free_font_path(FontPathElementPtr *list, int n) 598{ 599 int i; 600 601 for (i = 0; i < n; i++) { 602 FreeFPE(list[i]); 603 } 604 fsfree((char *) list); 605} 606 607static FontPathElementPtr 608find_existing_fpe( 609 FontPathElementPtr *list, 610 int num, 611 char *name, 612 int len) 613{ 614 FontPathElementPtr fpe; 615 int i; 616 617 for (i = 0; i < num; i++) { 618 fpe = list[i]; 619 if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0) 620 return fpe; 621 } 622 return (FontPathElementPtr) 0; 623} 624 625/* 626 * does the work of setting up the fpe list 627 * 628 * paths should be a counted string 629 */ 630static int 631set_font_path_elements( 632 int npaths, 633 char *paths, 634 int *bad) 635{ 636 int i, validpaths, err = 0; 637 int len; 638 int type; 639 char *cp = paths; 640 char *name; 641 FontPathElementPtr fpe, *fplist; 642 643 fplist = (FontPathElementPtr *) 644 fsalloc(sizeof(FontPathElementPtr) * npaths); 645 if (!fplist) { 646 *bad = 0; 647 return FSBadAlloc; 648 } 649 for (i = 0; i < num_fpe_types; i++) { 650 if (fpe_functions[i].set_path_hook) 651 (*fpe_functions[i].set_path_hook) (); 652 } 653 for (i = 0, validpaths = 0; i < npaths; i++) { 654 len = *cp++; 655 if (len) { 656 /* if it's already in our active list, just reset it */ 657 /* 658 * note that this can miss FPE's in limbo -- may be worth catching 659 * them, though it'd muck up refcounting 660 */ 661 fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len); 662 if (fpe) { 663 err = (*fpe_functions[fpe->type].reset_fpe) (fpe); 664 if (err == Successful) { 665 UseFPE(fpe);/* since it'll be decref'd later when freed 666 * from the old list */ 667 fplist[validpaths++] = fpe; 668 cp += len; 669 continue; 670 } 671 /* can't do it, so act like it's a new one */ 672 } 673 name = (char *) fsalloc(len + 1); 674 if (!name) { 675 err = FSBadAlloc; 676 goto bail; 677 } 678 strncpy(name, (char *) cp, len); 679 name[len] = '\0'; 680 type = determine_fpe_type(name); 681 if (type == -1) 682 { 683 NoticeF("ignoring font path element %s (bad font path descriptor)\n", name); 684 fsfree(name); 685 cp += len; 686 continue; 687 } 688 /* must be new -- make it */ 689 fpe = (FontPathElementPtr) fsalloc(sizeof(FontPathElementRec)); 690 if (!fpe) { 691 fsfree(name); 692 err = FSBadAlloc; 693 goto bail; 694 } 695 fpe->type = type; 696 fpe->name = name; 697 fpe->refcount = 1; 698 699 cp += len; 700 fpe->name_length = len; 701 err = (*fpe_functions[fpe->type].init_fpe) (fpe); 702 if (err != Successful) { 703 NoticeF("ignoring font path element %s (unreadable)\n", fpe->name); 704 fsfree(fpe->name); 705 fsfree(fpe); 706 continue; 707 } 708 fplist[validpaths++] = fpe; 709 } 710 } 711 if (validpaths < npaths) { 712 FontPathElementPtr *ftmp = (FontPathElementPtr *) 713 fsrealloc(fplist, sizeof(FontPathElementPtr) * validpaths); 714 715 if (!ftmp && validpaths) 716 goto bail; 717 718 fplist = ftmp; 719 npaths = validpaths; 720 } 721 if (validpaths == 0) { 722 err = FontToFSError(err); 723 goto bail; 724 } 725 free_font_path(font_path_elements, num_fpes); 726 font_path_elements = fplist; 727 num_fpes = npaths; 728 if (fontPatternCache) 729 EmptyFontPatternCache(fontPatternCache); 730 return FSSuccess; 731bail: 732 *bad = validpaths; 733 while (--validpaths >= 0) 734 FreeFPE(fplist[i]); 735 fsfree(fplist); 736 return err; 737} 738 739/* 740 * expects comma seperated string 741 */ 742int 743SetFontCatalogue( 744 char *str, 745 int *badpath) 746{ 747 int len, 748 npaths; 749 char *paths, 750 *end, 751 *p; 752 int err; 753 754 len = strlen(str) + 1; 755 paths = p = (char *) ALLOCATE_LOCAL(len); 756 npaths = 0; 757 758 while (*str) { 759 end = index(str, ','); 760 if (!end) { 761 end = str + strlen(str); 762 } 763 *p++ = len = end - str; 764 memmove( p, str, len); 765 npaths++; 766 str += len; /* skip entry */ 767 if (*str == ',') 768 str++; /* skip any comma */ 769 p += len; 770 } 771 772 err = set_font_path_elements(npaths, paths, badpath); 773 774 DEALLOCATE_LOCAL(paths); 775 776 return err; 777} 778 779#undef cPtr 780#define cPtr ((LFclosurePtr)data) 781 782static Bool 783do_list_fonts_and_aliases(ClientPtr client, pointer data) 784{ 785 FontPathElementPtr fpe; 786 int err = Successful; 787 FontNamesPtr names = NULL; 788 char *name, *resolved; 789 int namelen, resolvedlen; 790 int nnames; 791 int stringLens; 792 int i; 793 fsListFontsReply reply; 794 char *bufptr; 795 char *bufferStart; 796 int aliascount = 0; 797 798 if (client->clientGone == CLIENT_GONE) { 799 if (cPtr->current.current_fpe < cPtr->num_fpes) { 800 fpe = cPtr->fpe_list[cPtr->current.current_fpe]; 801 (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 802 } 803 err = Successful; 804 goto bail; 805 } 806 807 if (!cPtr->current.patlen) 808 goto finish; 809 810 while (cPtr->current.current_fpe < cPtr->num_fpes) { 811 fpe = cPtr->fpe_list[cPtr->current.current_fpe]; 812 err = Successful; 813 814 if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) 815 { 816 /* This FPE doesn't support/require list_fonts_and_aliases */ 817 818 err = (*fpe_functions[fpe->type].list_fonts) 819 ((pointer) cPtr->client, fpe, cPtr->current.pattern, 820 cPtr->current.patlen, cPtr->current.max_names - cPtr->names->nnames, 821 cPtr->names); 822 823 if (err == Suspended) { 824 if (!cPtr->slept) { 825 cPtr->slept = TRUE; 826 ClientSleep(client, do_list_fonts_and_aliases, (pointer) cPtr); 827 } 828 return TRUE; 829 } 830 831 err = BadFontName; 832 } 833 else 834 { 835 /* Start of list_fonts_and_aliases functionality. Modeled 836 after list_fonts_with_info in that it resolves aliases, 837 except that the information collected from FPEs is just 838 names, not font info. Each list_next_font_or_alias() 839 returns either a name into name/namelen or an alias into 840 name/namelen and its target name into resolved/resolvedlen. 841 The code at this level then resolves the alias by polling 842 the FPEs. */ 843 844 if (!cPtr->current.list_started) { 845 err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) 846 ((pointer) cPtr->client, fpe, cPtr->current.pattern, 847 cPtr->current.patlen, cPtr->current.max_names - cPtr->names->nnames, 848 &cPtr->current.private); 849 if (err == Suspended) { 850 if (!cPtr->slept) { 851 ClientSleep(client, do_list_fonts_and_aliases, 852 (pointer) cPtr); 853 cPtr->slept = TRUE; 854 } 855 return TRUE; 856 } 857 if (err == Successful) 858 cPtr->current.list_started = TRUE; 859 } 860 if (err == Successful) { 861 name = NULL; 862 err = (*fpe_functions[fpe->type].list_next_font_or_alias) 863 ((pointer) cPtr->client, fpe, &name, &namelen, &resolved, 864 &resolvedlen, cPtr->current.private); 865 if (err == Suspended) { 866 if (!cPtr->slept) { 867 ClientSleep(client, do_list_fonts_and_aliases, 868 (pointer) cPtr); 869 cPtr->slept = TRUE; 870 } 871 return TRUE; 872 } 873 } 874 875 if (err == Successful) 876 { 877 if (cPtr->haveSaved) 878 { 879 if (cPtr->savedName) 880 (void)AddFontNamesName(cPtr->names, cPtr->savedName, 881 cPtr->savedNameLen); 882 } 883 else 884 (void)AddFontNamesName(cPtr->names, name, namelen); 885 } 886 887 /* 888 * When we get an alias back, save our state and reset back to 889 * the start of the FPE looking for the specified name. As 890 * soon as a real font is found for the alias, pop back to the 891 * old state 892 */ 893 else if (err == FontNameAlias) { 894 char tmp_pattern[XLFDMAXFONTNAMELEN]; 895 /* 896 * when an alias recurses, we need to give 897 * the last FPE a chance to clean up; so we call 898 * it again, and assume that the error returned 899 * is BadFontName, indicating the alias resolution 900 * is complete. 901 */ 902 memmove(tmp_pattern, resolved, resolvedlen); 903 if (cPtr->haveSaved) 904 { 905 char *tmpname; 906 int tmpnamelen; 907 908 tmpname = NULL; 909 (void) (*fpe_functions[fpe->type].list_next_font_or_alias) 910 ((pointer) cPtr->client, fpe, &tmpname, &tmpnamelen, 911 &tmpname, &tmpnamelen, cPtr->current.private); 912 if (--aliascount <= 0) 913 { 914 err = BadFontName; 915 goto ContBadFontName; 916 } 917 } 918 else 919 { 920 cPtr->saved = cPtr->current; 921 cPtr->haveSaved = TRUE; 922 if (cPtr->savedName) 923 fsfree(cPtr->savedName); 924 cPtr->savedName = (char *)fsalloc(namelen + 1); 925 if (cPtr->savedName) 926 memmove(cPtr->savedName, name, namelen + 1); 927 cPtr->savedNameLen = namelen; 928 aliascount = 20; 929 } 930 memmove(cPtr->current.pattern, tmp_pattern, resolvedlen); 931 cPtr->current.patlen = resolvedlen; 932 cPtr->current.max_names = cPtr->names->nnames + 1; 933 cPtr->current.current_fpe = -1; 934 cPtr->current.private = NULL; 935 err = BadFontName; 936 } 937 } 938 /* 939 * At the end of this FPE, step to the next. If we've finished 940 * processing an alias, pop state back. If we've collected enough 941 * font names, quit. 942 */ 943 if (err == BadFontName) { 944 ContBadFontName: ; 945 cPtr->current.list_started = FALSE; 946 cPtr->current.current_fpe++; 947 err = Successful; 948 if (cPtr->haveSaved) 949 { 950 /* If we're searching for an alias, limit the search to 951 FPE's of the same type as the one the alias came 952 from. This is unnecessarily restrictive, but if we 953 have both fontfile and fs FPE's, this restriction can 954 drastically reduce network traffic to the fs -- else 955 we could poll the fs for *every* local alias found; 956 on a typical system enabling FILE_NAMES_ALIASES, this 957 is significant. */ 958 959 while (cPtr->current.current_fpe < cPtr->num_fpes && 960 cPtr->fpe_list[cPtr->current.current_fpe]->type != 961 cPtr->fpe_list[cPtr->saved.current_fpe]->type) 962 cPtr->current.current_fpe++; 963 964 if (cPtr->names->nnames == cPtr->current.max_names || 965 cPtr->current.current_fpe == cPtr->num_fpes) { 966 cPtr->haveSaved = FALSE; 967 cPtr->current = cPtr->saved; 968 /* Give the saved namelist a chance to clean itself up */ 969 continue; 970 } 971 } 972 if (cPtr->names->nnames == cPtr->current.max_names) 973 break; 974 } 975 } 976 977 /* 978 * send the reply 979 */ 980 if (err != Successful) { 981 SendErrToClient(client, FontToFSError(err), (pointer) 0); 982 goto bail; 983 } 984 985finish: 986 987 names = cPtr->names; 988 nnames = names->nnames; 989 client = cPtr->client; 990 stringLens = 0; 991 for (i = 0; i < nnames; i++) 992 stringLens += (names->length[i] <= 255) ? names->length[i] : 0; 993 994 reply = (fsListFontsReply) { 995 .type = FS_Reply, 996 .sequenceNumber = client->sequence, 997 .length = (SIZEOF(fsListFontsReply) + stringLens + nnames + 3) >> 2, 998 .following = 0, 999 .nFonts = nnames 1000 }; 1001 1002 bufptr = bufferStart = (char *) ALLOCATE_LOCAL(reply.length << 2); 1003 1004 if (!bufptr && reply.length) { 1005 SendErrToClient(client, FSBadAlloc, (pointer) 0); 1006 goto bail; 1007 } 1008 /* 1009 * since WriteToClient long word aligns things, copy to temp buffer and 1010 * write all at once 1011 */ 1012 for (i = 0; i < nnames; i++) { 1013 if (names->length[i] > 255) 1014 reply.nFonts--; 1015 else 1016 { 1017 *bufptr++ = names->length[i]; 1018 memmove( bufptr, names->names[i], names->length[i]); 1019 bufptr += names->length[i]; 1020 } 1021 } 1022 nnames = reply.nFonts; 1023 reply.length = (SIZEOF(fsListFontsReply) + stringLens + nnames + 3) >> 2; 1024 WriteReplyToClient(client, SIZEOF(fsListFontsReply), &reply); 1025 (void) WriteToClient(client, stringLens + nnames, bufferStart); 1026 DEALLOCATE_LOCAL(bufferStart); 1027 1028bail: 1029 if (cPtr->slept) 1030 ClientWakeup(client); 1031 for (i = 0; i < cPtr->num_fpes; i++) 1032 FreeFPE(cPtr->fpe_list[i]); 1033 fsfree(cPtr->fpe_list); 1034 if (cPtr->savedName) fsfree(cPtr->savedName); 1035 FreeFontNames(names); 1036 fsfree(cPtr); 1037 return TRUE; 1038} 1039 1040int 1041ListFonts( 1042 ClientPtr client, 1043 int length, 1044 unsigned char *pattern, 1045 int maxNames) 1046{ 1047 int i; 1048 LFclosurePtr c; 1049 1050 /* 1051 * The right error to return here would be BadName, however the 1052 * specification does not allow for a Name error on this request. 1053 * Perhaps a better solution would be to return a nil list, i.e. 1054 * a list containing zero fontnames. 1055 */ 1056 if (length > XLFDMAXFONTNAMELEN) { 1057 SendErrToClient(client, FSBadAlloc, (pointer) 0); 1058 return TRUE; 1059 } 1060 1061 if (!(c = (LFclosurePtr) fsalloc(sizeof *c))) 1062 goto badAlloc; 1063 c->fpe_list = (FontPathElementPtr *) 1064 fsalloc(sizeof(FontPathElementPtr) * num_fpes); 1065 if (!c->fpe_list) { 1066 fsfree(c); 1067 goto badAlloc; 1068 } 1069 c->names = MakeFontNamesRecord(maxNames < 100 ? maxNames : 100); 1070 if (!c->names) 1071 { 1072 fsfree(c->fpe_list); 1073 fsfree(c); 1074 goto badAlloc; 1075 } 1076 memmove( c->current.pattern, pattern, length); 1077 for (i = 0; i < num_fpes; i++) { 1078 c->fpe_list[i] = font_path_elements[i]; 1079 UseFPE(c->fpe_list[i]); 1080 } 1081 c->client = client; 1082 c->num_fpes = num_fpes; 1083 c->current.patlen = length; 1084 c->current.current_fpe = 0; 1085 c->current.max_names = maxNames; 1086 c->current.list_started = FALSE; 1087 c->current.private = NULL; 1088 c->haveSaved = FALSE; 1089 c->slept = FALSE; 1090 c->savedName = NULL; 1091 do_list_fonts_and_aliases(client, (pointer) c); 1092 return TRUE; 1093badAlloc: 1094 SendErrToClient(client, FSBadAlloc, (pointer) 0); 1095 return TRUE; 1096} 1097 1098static int padlength[4] = {0, 3, 2, 1}; 1099static char padding[3]; 1100 1101#undef cPtr 1102#define cPtr ((LFWXIclosurePtr)data) 1103 1104static Bool 1105do_list_fonts_with_info(ClientPtr client, pointer data) 1106{ 1107 FontPathElementPtr fpe; 1108 int err = Successful; 1109 char *name; 1110 int namelen; 1111 int numFonts; 1112 FontInfoRec fontInfo, 1113 *pFontInfo; 1114 fsListFontsWithXInfoReply *reply; 1115 int length; 1116 fsPropInfo *prop_info; 1117 int lenpropdata; 1118 int i; 1119 int aliascount = 0; 1120 1121 if (client->clientGone == CLIENT_GONE) { 1122 if (cPtr->current.current_fpe < cPtr->num_fpes) { 1123 fpe = cPtr->fpe_list[cPtr->current.current_fpe]; 1124 (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 1125 } 1126 err = Successful; 1127 goto bail; 1128 } 1129 while (cPtr->current.current_fpe < cPtr->num_fpes) { 1130 fpe = cPtr->fpe_list[cPtr->current.current_fpe]; 1131 err = Successful; 1132 if (!cPtr->current.list_started) { 1133 err = (*fpe_functions[fpe->type].start_list_fonts_with_info) 1134 ((pointer) cPtr->client, fpe, cPtr->current.pattern, 1135 cPtr->current.patlen, cPtr->current.max_names, 1136 &cPtr->current.private); 1137 if (err == Suspended) { 1138 if (!cPtr->slept) { 1139 ClientSleep(client, do_list_fonts_with_info, 1140 (pointer) cPtr); 1141 cPtr->slept = TRUE; 1142 } 1143 return TRUE; 1144 } 1145 if (err == Successful) 1146 cPtr->current.list_started = TRUE; 1147 } 1148 if (err == Successful) { 1149 name = NULL; 1150 pFontInfo = &fontInfo; 1151 err = (*fpe_functions[fpe->type].list_next_font_with_info) 1152 ((pointer) cPtr->client, fpe, &name, &namelen, 1153 &pFontInfo, &numFonts, cPtr->current.private); 1154 if (err == Suspended) { 1155 if (!cPtr->slept) { 1156 ClientSleep(client, do_list_fonts_with_info, 1157 (pointer) cPtr); 1158 cPtr->slept = TRUE; 1159 } 1160 return TRUE; 1161 } 1162 } 1163 /* 1164 * When we get an alias back, save our state and reset back to the 1165 * start of the FPE looking for the specified name. As soon as a real 1166 * font is found for the alias, pop back to the old state 1167 */ 1168 if (err == FontNameAlias) { 1169 /* 1170 * when an alias recurses, we need to give 1171 * the last FPE a chance to clean up; so we call 1172 * it again, and assume that the error returned 1173 * is BadFontName, indicating the alias resolution 1174 * is complete. 1175 */ 1176 if (cPtr->haveSaved) 1177 { 1178 char *tmpname; 1179 int tmpnamelen; 1180 FontInfoPtr tmpFontInfo; 1181 1182 tmpname = NULL; 1183 tmpFontInfo = &fontInfo; 1184 (void) (*fpe_functions[fpe->type].list_next_font_with_info) 1185 ((pointer) client, fpe, &tmpname, &tmpnamelen, 1186 &tmpFontInfo, &numFonts, cPtr->current.private); 1187 if (--aliascount <= 0) 1188 { 1189 err = BadFontName; 1190 goto ContBadFontName; 1191 } 1192 } 1193 else 1194 { 1195 cPtr->saved = cPtr->current; 1196 cPtr->haveSaved = TRUE; 1197 cPtr->savedNumFonts = numFonts; 1198 if (cPtr->savedName) 1199 fsfree(cPtr->savedName); 1200 cPtr->savedName = (char *)fsalloc(namelen + 1); 1201 if (cPtr->savedName) 1202 memmove(cPtr->savedName, name, namelen + 1); 1203 aliascount = 20; 1204 } 1205 memmove(cPtr->current.pattern, name, namelen); 1206 cPtr->current.patlen = namelen; 1207 cPtr->current.max_names = 1; 1208 cPtr->current.current_fpe = 0; 1209 cPtr->current.private = NULL; 1210 cPtr->current.list_started = FALSE; 1211 } 1212 /* 1213 * At the end of this FPE, step to the next. If we've finished 1214 * processing an alias, pop state back. If we've sent enough font 1215 * names, quit. 1216 */ 1217 else if (err == BadFontName) { 1218 ContBadFontName: ; 1219 cPtr->current.list_started = FALSE; 1220 cPtr->current.current_fpe++; 1221 err = Successful; 1222 if (cPtr->haveSaved) { 1223 if (cPtr->current.max_names == 0 || 1224 cPtr->current.current_fpe == cPtr->num_fpes) { 1225 cPtr->haveSaved = FALSE; 1226 cPtr->saved.max_names -= (1 - cPtr->current.max_names); 1227 cPtr->current = cPtr->saved; 1228 } 1229 } 1230 else if (cPtr->current.max_names == 0) 1231 break; 1232 } else if (err == Successful) { 1233/* XXX why is it xFontProp ? */ 1234 length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp); 1235 reply = cPtr->reply; 1236 if (cPtr->length < length) { 1237 reply = (fsListFontsWithXInfoReply *) fsrealloc(cPtr->reply, length); 1238 if (!reply) { 1239 err = AllocError; 1240 break; 1241 } 1242 cPtr->reply = reply; 1243 cPtr->length = length; 1244 } 1245 if (cPtr->haveSaved) { 1246 numFonts = cPtr->savedNumFonts; 1247 name = cPtr->savedName; 1248 namelen = strlen(name); 1249 } 1250 fsPack_XFontInfoHeader(pFontInfo, reply, client->major_version); 1251 err = convert_props(pFontInfo, &prop_info); 1252 if (err != Successful) 1253 break; 1254 lenpropdata = SIZEOF(fsPropInfo) + 1255 prop_info->num_offsets * SIZEOF(fsPropOffset) + 1256 prop_info->data_len; 1257 1258 reply->type = FS_Reply; 1259 reply->length = 1260 (SIZEOF(fsListFontsWithXInfoReply) + 1261 lenpropdata + namelen + 3) >> 2; 1262 reply->sequenceNumber = client->sequence; 1263 reply->nameLength = namelen; 1264 reply->nReplies = numFonts; 1265 WriteReplyToClient(client, SIZEOF(fsListFontsWithXInfoReply), reply); 1266 if (client->swapped) 1267 SwapPropInfo(prop_info); 1268 if (client->major_version > 1) 1269 { 1270 (void)WriteToClientUnpadded(client, lenpropdata, (char *) prop_info); 1271 (void)WriteToClientUnpadded(client, namelen, name); 1272 (void)WriteToClientUnpadded(client, 1273 padlength[(lenpropdata+namelen)&3], 1274 padding); 1275 } else { 1276 (void) WriteToClient(client, namelen, name); 1277 (void) WriteToClient(client, lenpropdata, (char *) prop_info); 1278 } 1279 if (pFontInfo == &fontInfo) { 1280 fsfree(fontInfo.props); 1281 fsfree(fontInfo.isStringProp); 1282 } 1283 fsfree(prop_info); 1284 1285 --cPtr->current.max_names; 1286 if (cPtr->current.max_names < 0) 1287 abort(); 1288 } 1289 } 1290 1291 /* 1292 * send the final reply 1293 */ 1294 if (err == Successful) { 1295 fsGenericReply *final_reply; 1296 1297 final_reply = (fsGenericReply *)cPtr->reply; 1298 if (client->major_version > 1) 1299 length = SIZEOF(fsGenericReply); 1300 else 1301 length = SIZEOF(fsListFontsWithXInfoReply); 1302 if (cPtr->length < length) { 1303 final_reply = (fsGenericReply *) fsrealloc(cPtr->reply, length); 1304 if (final_reply) { 1305 cPtr->reply = (fsListFontsWithXInfoReply *)final_reply; 1306 cPtr->length = length; 1307 } else 1308 err = AllocError; 1309 } 1310 if (err == Successful) { 1311 final_reply->type = FS_Reply; 1312 final_reply->data1 = 0; /* notes that this is final */ 1313 final_reply->sequenceNumber = client->sequence; 1314 final_reply->length = length >> 2; 1315 WriteReplyToClient(client, length, final_reply); 1316 } 1317 } 1318 if (err != Successful) 1319 SendErrToClient(client, FontToFSError(err), (pointer) 0); 1320bail: 1321 if (cPtr->slept) 1322 ClientWakeup(client); 1323 for (i = 0; i < cPtr->num_fpes; i++) 1324 FreeFPE(cPtr->fpe_list[i]); 1325 fsfree(cPtr->fpe_list); 1326 if (cPtr->savedName) fsfree(cPtr->savedName); 1327 fsfree(cPtr->reply); 1328 fsfree(cPtr); 1329 return TRUE; 1330} 1331 1332int 1333StartListFontsWithInfo( 1334 ClientPtr client, 1335 int length, 1336 unsigned char *pattern, 1337 int maxNames) 1338{ 1339 int i; 1340 LFWXIclosurePtr c; 1341 1342 /* 1343 * The right error to return here would be BadName, however the 1344 * specification does not allow for a Name error on this request. 1345 * Perhaps a better solution would be to return a nil list, i.e. 1346 * a list containing zero fontnames. 1347 */ 1348 if (length > XLFDMAXFONTNAMELEN) { 1349 SendErrToClient(client, FSBadAlloc, (pointer) 0); 1350 return TRUE; 1351 } 1352 1353 if (!(c = (LFWXIclosurePtr) fsalloc(sizeof *c))) 1354 goto badAlloc; 1355 c->fpe_list = (FontPathElementPtr *) 1356 fsalloc(sizeof(FontPathElementPtr) * num_fpes); 1357 if (!c->fpe_list) { 1358 fsfree(c); 1359 goto badAlloc; 1360 } 1361 memmove( c->current.pattern, pattern, length); 1362 for (i = 0; i < num_fpes; i++) { 1363 c->fpe_list[i] = font_path_elements[i]; 1364 UseFPE(c->fpe_list[i]); 1365 } 1366 c->client = client; 1367 c->num_fpes = num_fpes; 1368 c->reply = NULL; 1369 c->length = 0; 1370 c->current.patlen = length; 1371 c->current.current_fpe = 0; 1372 c->current.max_names = maxNames; 1373 c->current.list_started = FALSE; 1374 c->current.private = NULL; 1375 c->savedNumFonts = 0; 1376 c->haveSaved = FALSE; 1377 c->slept = FALSE; 1378 c->savedName = NULL; 1379 do_list_fonts_with_info(client, (pointer) c); 1380 return TRUE; 1381badAlloc: 1382 SendErrToClient(client, FSBadAlloc, (pointer) 0); 1383 return TRUE; 1384} 1385 1386int 1387LoadGlyphRanges( 1388 ClientPtr client, 1389 FontPtr pfont, 1390 Bool range_flag, 1391 int num_ranges, 1392 int item_size, 1393 fsChar2b *data) 1394{ 1395 /* either returns Successful, Suspended, or some nasty error */ 1396 if (fpe_functions[pfont->fpe->type].load_glyphs) 1397 return (*fpe_functions[pfont->fpe->type].load_glyphs)( 1398 (pointer)client, pfont, range_flag, num_ranges, item_size, 1399 (unsigned char *)data); 1400 else 1401 return Successful; 1402} 1403 1404 1405int 1406RegisterFPEFunctions( 1407 Bool (*name_func) (char *name), 1408 InitFpeFunc init_func, 1409 FreeFpeFunc free_func, 1410 ResetFpeFunc reset_func, 1411 OpenFontFunc open_func, 1412 CloseFontFunc close_func, 1413 ListFontsFunc list_func, 1414 StartLfwiFunc start_lfwi_func, 1415 NextLfwiFunc next_lfwi_func, 1416 WakeupFpeFunc wakeup_func, 1417 ClientDiedFunc client_died, 1418 LoadGlyphsFunc load_glyphs, 1419 StartLaFunc start_list_alias_func, 1420 NextLaFunc next_list_alias_func, 1421 void (*set_path_func) (void)) 1422{ 1423 FPEFunctions *new; 1424 1425 /* grow the list */ 1426 new = (FPEFunctions *) fsrealloc(fpe_functions, 1427 (num_fpe_types + 1) * sizeof(FPEFunctions)); 1428 if (!new) 1429 return -1; 1430 fpe_functions = new; 1431 1432 fpe_functions[num_fpe_types].name_check = name_func; 1433 fpe_functions[num_fpe_types].open_font = open_func; 1434 fpe_functions[num_fpe_types].close_font = close_func; 1435 fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func; 1436 fpe_functions[num_fpe_types].list_fonts = list_func; 1437 fpe_functions[num_fpe_types].start_list_fonts_with_info = 1438 start_lfwi_func; 1439 fpe_functions[num_fpe_types].list_next_font_with_info = 1440 next_lfwi_func; 1441 fpe_functions[num_fpe_types].init_fpe = init_func; 1442 fpe_functions[num_fpe_types].free_fpe = free_func; 1443 fpe_functions[num_fpe_types].reset_fpe = reset_func; 1444 1445 fpe_functions[num_fpe_types].client_died = client_died; 1446 fpe_functions[num_fpe_types].load_glyphs = load_glyphs; 1447 fpe_functions[num_fpe_types].start_list_fonts_and_aliases = 1448 start_list_alias_func; 1449 fpe_functions[num_fpe_types].list_next_font_or_alias = 1450 next_list_alias_func; 1451 fpe_functions[num_fpe_types].set_path_hook = set_path_func; 1452 1453 return num_fpe_types++; 1454} 1455 1456 1457/* convenience functions for FS interface */ 1458 1459FontPtr 1460find_old_font(FSID id) 1461{ 1462 return (FontPtr) LookupIDByType(SERVER_CLIENT, id, RT_NONE); 1463} 1464 1465Font 1466GetNewFontClientID(void) 1467{ 1468 return (Font) FakeClientID(SERVER_CLIENT); 1469} 1470 1471int 1472StoreFontClientFont( 1473 FontPtr pfont, 1474 Font id) 1475{ 1476 return AddResource(SERVER_CLIENT, id, RT_NONE, (pointer) pfont); 1477} 1478 1479void 1480DeleteFontClientID(Font id) 1481{ 1482 FreeResource(SERVER_CLIENT, id, RT_NONE); 1483} 1484 1485static int fs_handlers_installed = 0; 1486static unsigned int last_server_gen; 1487 1488int 1489init_fs_handlers( 1490 FontPathElementPtr fpe, 1491 BlockHandlerProcPtr block_handler) 1492{ 1493 /* if server has reset, make sure the b&w handlers are reinstalled */ 1494 if (last_server_gen < serverGeneration) { 1495 last_server_gen = serverGeneration; 1496 fs_handlers_installed = 0; 1497 } 1498 if (fs_handlers_installed == 0) { 1499 1500#ifdef DEBUG 1501 fprintf(stderr, "adding FS b & w handlers\n"); 1502#endif 1503 1504 if (!RegisterBlockAndWakeupHandlers(block_handler, 1505 FontWakeup, (pointer) 0)) 1506 return AllocError; 1507 fs_handlers_installed++; 1508 } 1509 QueueFontWakeup(fpe); 1510 return Successful; 1511} 1512 1513void 1514remove_fs_handlers( 1515 FontPathElementPtr fpe, 1516 BlockHandlerProcPtr block_handler, 1517 Bool all) 1518{ 1519 if (all) { 1520 /* remove the handlers if no one else is using them */ 1521 if (--fs_handlers_installed == 0) { 1522 1523#ifdef DEBUG 1524 fprintf(stderr, "removing FS b & w handlers\n"); 1525#endif 1526 1527 RemoveBlockAndWakeupHandlers(block_handler, FontWakeup, 1528 (pointer) 0); 1529 } 1530 } 1531 RemoveFontWakeup(fpe); 1532} 1533 1534void 1535DeleteClientFontStuff(ClientPtr client) 1536{ 1537 int i; 1538 FontPathElementPtr fpe; 1539 1540 for (i = 0; i < num_fpes; i++) 1541 { 1542 fpe = font_path_elements[i]; 1543 1544 if (fpe_functions[fpe->type].client_died) 1545 (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 1546 } 1547} 1548