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