fonts.c revision 40c5823b
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 fsrealloc(slept_fpes, 144 sizeof(FontPathElementPtr) * (size_slept_fpes + 4)); 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 *) fsrealloc(ids->client_list, 198 sizeof(Font) * (ids->size + NUM_IDS_PER_CLIENT)); 199 if (!newlist) 200 return FALSE; 201 ids->client_list = newlist; 202 ids->size += NUM_IDS_PER_CLIENT; 203 } 204 ids->client_list[ids->num++] = fid; 205 return TRUE; 206} 207 208static void 209remove_id_from_list(FontIDListPtr ids, Font fid) 210{ 211 int i; 212 213 for (i = 0; i < ids->num; i++) { 214 if (ids->client_list[i] == fid) { 215 /* a memmove() might be better here */ 216 while (i < ids->num) { 217 ids->client_list[i] = ids->client_list[i + 1]; 218 i++; 219 } 220 ids->num--; 221 return; 222 } 223 } 224 assert(0); 225} 226 227static FontIDListPtr 228make_clients_id_list(void) 229{ 230 FontIDListPtr ids; 231 Font *fids; 232 233 ids = (FontIDListPtr) fsalloc(sizeof(FontIDListRec)); 234 fids = (Font *) fsalloc(sizeof(Font) * NUM_IDS_PER_CLIENT); 235 if (!ids || !fids) { 236 fsfree(ids); 237 fsfree(fids); 238 return (FontIDListPtr) 0; 239 } 240 bzero((char *) fids, sizeof(Font) * NUM_IDS_PER_CLIENT); 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 *) fsalloc(sizeof(FontIDListPtr) * MAXCLIENTS); 365 if (!idlist) { 366 err = AllocError; 367 fsfree(cfp); 368 goto dropout; 369 } 370 ids = make_clients_id_list(); 371 if (!ids) { 372 err = AllocError; 373 fsfree(idlist); 374 fsfree(cfp); 375 goto dropout; 376 } 377 bzero((char *) idlist, (sizeof(FontIDListPtr) * MAXCLIENTS)); 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 fsalloc(sizeof(FontPathElementPtr) * num_fpes); 521 if (!c->fpe_list) { 522 fsfree(c->fontname); 523 fsfree(c); 524 goto lowmem; 525 } 526 memmove( 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 fsalloc(sizeof(FontPathElementPtr) * npaths); 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 fsrealloc(fplist, sizeof(FontPathElementPtr) * validpaths); 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 seperated 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 761 while (*str) { 762 end = index(str, ','); 763 if (!end) { 764 end = str + strlen(str); 765 } 766 *p++ = len = end - str; 767 memmove( p, str, len); 768 npaths++; 769 str += len; /* skip entry */ 770 if (*str == ',') 771 str++; /* skip any comma */ 772 p += len; 773 } 774 775 err = set_font_path_elements(npaths, paths, badpath); 776 777 DEALLOCATE_LOCAL(paths); 778 779 return err; 780} 781 782#undef cPtr 783#define cPtr ((LFclosurePtr)data) 784 785static Bool 786do_list_fonts_and_aliases(ClientPtr client, pointer data) 787{ 788 FontPathElementPtr fpe; 789 int err = Successful; 790 FontNamesPtr names = NULL; 791 char *name, *resolved; 792 int namelen, resolvedlen; 793 int nnames; 794 int stringLens; 795 int i; 796 fsListFontsReply reply; 797 char *bufptr; 798 char *bufferStart; 799 int aliascount = 0; 800 801 if (client->clientGone == CLIENT_GONE) { 802 if (cPtr->current.current_fpe < cPtr->num_fpes) { 803 fpe = cPtr->fpe_list[cPtr->current.current_fpe]; 804 (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 805 } 806 err = Successful; 807 goto bail; 808 } 809 810 if (!cPtr->current.patlen) 811 goto finish; 812 813 while (cPtr->current.current_fpe < cPtr->num_fpes) { 814 fpe = cPtr->fpe_list[cPtr->current.current_fpe]; 815 err = Successful; 816 817 if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) 818 { 819 /* This FPE doesn't support/require list_fonts_and_aliases */ 820 821 err = (*fpe_functions[fpe->type].list_fonts) 822 ((pointer) cPtr->client, fpe, cPtr->current.pattern, 823 cPtr->current.patlen, cPtr->current.max_names - cPtr->names->nnames, 824 cPtr->names); 825 826 if (err == Suspended) { 827 if (!cPtr->slept) { 828 cPtr->slept = TRUE; 829 ClientSleep(client, do_list_fonts_and_aliases, (pointer) cPtr); 830 } 831 return TRUE; 832 } 833 834 err = BadFontName; 835 } 836 else 837 { 838 /* Start of list_fonts_and_aliases functionality. Modeled 839 after list_fonts_with_info in that it resolves aliases, 840 except that the information collected from FPEs is just 841 names, not font info. Each list_next_font_or_alias() 842 returns either a name into name/namelen or an alias into 843 name/namelen and its target name into resolved/resolvedlen. 844 The code at this level then resolves the alias by polling 845 the FPEs. */ 846 847 if (!cPtr->current.list_started) { 848 err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) 849 ((pointer) cPtr->client, fpe, cPtr->current.pattern, 850 cPtr->current.patlen, cPtr->current.max_names - cPtr->names->nnames, 851 &cPtr->current.private); 852 if (err == Suspended) { 853 if (!cPtr->slept) { 854 ClientSleep(client, do_list_fonts_and_aliases, 855 (pointer) cPtr); 856 cPtr->slept = TRUE; 857 } 858 return TRUE; 859 } 860 if (err == Successful) 861 cPtr->current.list_started = TRUE; 862 } 863 if (err == Successful) { 864 name = NULL; 865 err = (*fpe_functions[fpe->type].list_next_font_or_alias) 866 ((pointer) cPtr->client, fpe, &name, &namelen, &resolved, 867 &resolvedlen, cPtr->current.private); 868 if (err == Suspended) { 869 if (!cPtr->slept) { 870 ClientSleep(client, do_list_fonts_and_aliases, 871 (pointer) cPtr); 872 cPtr->slept = TRUE; 873 } 874 return TRUE; 875 } 876 } 877 878 if (err == Successful) 879 { 880 if (cPtr->haveSaved) 881 { 882 if (cPtr->savedName) 883 xfont2_add_font_names_name(cPtr->names, cPtr->savedName, 884 cPtr->savedNameLen); 885 } 886 else 887 xfont2_add_font_names_name(cPtr->names, name, namelen); 888 } 889 890 /* 891 * When we get an alias back, save our state and reset back to 892 * the start of the FPE looking for the specified name. As 893 * soon as a real font is found for the alias, pop back to the 894 * old state 895 */ 896 else if (err == FontNameAlias) { 897 char tmp_pattern[XLFDMAXFONTNAMELEN]; 898 /* 899 * when an alias recurses, we need to give 900 * the last FPE a chance to clean up; so we call 901 * it again, and assume that the error returned 902 * is BadFontName, indicating the alias resolution 903 * is complete. 904 */ 905 memmove(tmp_pattern, resolved, resolvedlen); 906 if (cPtr->haveSaved) 907 { 908 char *tmpname; 909 int tmpnamelen; 910 911 tmpname = NULL; 912 (void) (*fpe_functions[fpe->type].list_next_font_or_alias) 913 ((pointer) cPtr->client, fpe, &tmpname, &tmpnamelen, 914 &tmpname, &tmpnamelen, cPtr->current.private); 915 if (--aliascount <= 0) 916 { 917 err = BadFontName; 918 goto ContBadFontName; 919 } 920 } 921 else 922 { 923 cPtr->saved = cPtr->current; 924 cPtr->haveSaved = TRUE; 925 if (cPtr->savedName) 926 fsfree(cPtr->savedName); 927 cPtr->savedName = (char *)fsalloc(namelen + 1); 928 if (cPtr->savedName) 929 memmove(cPtr->savedName, name, namelen + 1); 930 cPtr->savedNameLen = namelen; 931 aliascount = 20; 932 } 933 memmove(cPtr->current.pattern, tmp_pattern, resolvedlen); 934 cPtr->current.patlen = resolvedlen; 935 cPtr->current.max_names = cPtr->names->nnames + 1; 936 cPtr->current.current_fpe = -1; 937 cPtr->current.private = NULL; 938 err = BadFontName; 939 } 940 } 941 /* 942 * At the end of this FPE, step to the next. If we've finished 943 * processing an alias, pop state back. If we've collected enough 944 * font names, quit. 945 */ 946 if (err == BadFontName) { 947 ContBadFontName: ; 948 cPtr->current.list_started = FALSE; 949 cPtr->current.current_fpe++; 950 err = Successful; 951 if (cPtr->haveSaved) 952 { 953 /* If we're searching for an alias, limit the search to 954 FPE's of the same type as the one the alias came 955 from. This is unnecessarily restrictive, but if we 956 have both fontfile and fs FPE's, this restriction can 957 drastically reduce network traffic to the fs -- else 958 we could poll the fs for *every* local alias found; 959 on a typical system enabling FILE_NAMES_ALIASES, this 960 is significant. */ 961 962 while (cPtr->current.current_fpe < cPtr->num_fpes && 963 cPtr->fpe_list[cPtr->current.current_fpe]->type != 964 cPtr->fpe_list[cPtr->saved.current_fpe]->type) 965 cPtr->current.current_fpe++; 966 967 if (cPtr->names->nnames == cPtr->current.max_names || 968 cPtr->current.current_fpe == cPtr->num_fpes) { 969 cPtr->haveSaved = FALSE; 970 cPtr->current = cPtr->saved; 971 /* Give the saved namelist a chance to clean itself up */ 972 continue; 973 } 974 } 975 if (cPtr->names->nnames == cPtr->current.max_names) 976 break; 977 } 978 } 979 980 /* 981 * send the reply 982 */ 983 if (err != Successful) { 984 SendErrToClient(client, FontToFSError(err), (pointer) 0); 985 goto bail; 986 } 987 988finish: 989 990 names = cPtr->names; 991 nnames = names->nnames; 992 client = cPtr->client; 993 stringLens = 0; 994 for (i = 0; i < nnames; i++) 995 stringLens += (names->length[i] <= 255) ? names->length[i] : 0; 996 997 reply = (fsListFontsReply) { 998 .type = FS_Reply, 999 .sequenceNumber = client->sequence, 1000 .length = (SIZEOF(fsListFontsReply) + stringLens + nnames + 3) >> 2, 1001 .following = 0, 1002 .nFonts = nnames 1003 }; 1004 1005 bufptr = bufferStart = (char *) ALLOCATE_LOCAL(reply.length << 2); 1006 1007 if (!bufptr && reply.length) { 1008 SendErrToClient(client, FSBadAlloc, (pointer) 0); 1009 goto bail; 1010 } 1011 /* 1012 * since WriteToClient long word aligns things, copy to temp buffer and 1013 * write all at once 1014 */ 1015 for (i = 0; i < nnames; i++) { 1016 if (names->length[i] > 255) 1017 reply.nFonts--; 1018 else 1019 { 1020 *bufptr++ = names->length[i]; 1021 memmove( bufptr, names->names[i], names->length[i]); 1022 bufptr += names->length[i]; 1023 } 1024 } 1025 nnames = reply.nFonts; 1026 reply.length = (SIZEOF(fsListFontsReply) + stringLens + nnames + 3) >> 2; 1027 WriteReplyToClient(client, SIZEOF(fsListFontsReply), &reply); 1028 (void) WriteToClient(client, stringLens + nnames, bufferStart); 1029 DEALLOCATE_LOCAL(bufferStart); 1030 1031bail: 1032 if (cPtr->slept) 1033 ClientWakeup(client); 1034 for (i = 0; i < cPtr->num_fpes; i++) 1035 FreeFPE(cPtr->fpe_list[i]); 1036 fsfree(cPtr->fpe_list); 1037 if (cPtr->savedName) fsfree(cPtr->savedName); 1038 xfont2_free_font_names(names); 1039 fsfree(cPtr); 1040 return TRUE; 1041} 1042 1043int 1044ListFonts( 1045 ClientPtr client, 1046 int length, 1047 unsigned char *pattern, 1048 int maxNames) 1049{ 1050 int i; 1051 LFclosurePtr c; 1052 1053 /* 1054 * The right error to return here would be BadName, however the 1055 * specification does not allow for a Name error on this request. 1056 * Perhaps a better solution would be to return a nil list, i.e. 1057 * a list containing zero fontnames. 1058 */ 1059 if (length > XLFDMAXFONTNAMELEN) { 1060 SendErrToClient(client, FSBadAlloc, (pointer) 0); 1061 return TRUE; 1062 } 1063 1064 if (!(c = (LFclosurePtr) fsalloc(sizeof *c))) 1065 goto badAlloc; 1066 c->fpe_list = (FontPathElementPtr *) 1067 fsalloc(sizeof(FontPathElementPtr) * num_fpes); 1068 if (!c->fpe_list) { 1069 fsfree(c); 1070 goto badAlloc; 1071 } 1072 c->names = xfont2_make_font_names_record(maxNames < 100 ? maxNames : 100); 1073 if (!c->names) 1074 { 1075 fsfree(c->fpe_list); 1076 fsfree(c); 1077 goto badAlloc; 1078 } 1079 memmove( c->current.pattern, pattern, length); 1080 for (i = 0; i < num_fpes; i++) { 1081 c->fpe_list[i] = font_path_elements[i]; 1082 UseFPE(c->fpe_list[i]); 1083 } 1084 c->client = client; 1085 c->num_fpes = num_fpes; 1086 c->current.patlen = length; 1087 c->current.current_fpe = 0; 1088 c->current.max_names = maxNames; 1089 c->current.list_started = FALSE; 1090 c->current.private = NULL; 1091 c->haveSaved = FALSE; 1092 c->slept = FALSE; 1093 c->savedName = NULL; 1094 do_list_fonts_and_aliases(client, (pointer) c); 1095 return TRUE; 1096badAlloc: 1097 SendErrToClient(client, FSBadAlloc, (pointer) 0); 1098 return TRUE; 1099} 1100 1101static int padlength[4] = {0, 3, 2, 1}; 1102static char padding[3]; 1103 1104#undef cPtr 1105#define cPtr ((LFWXIclosurePtr)data) 1106 1107static Bool 1108do_list_fonts_with_info(ClientPtr client, pointer data) 1109{ 1110 FontPathElementPtr fpe; 1111 int err = Successful; 1112 char *name; 1113 int namelen; 1114 int numFonts; 1115 FontInfoRec fontInfo, 1116 *pFontInfo; 1117 fsListFontsWithXInfoReply *reply; 1118 int length; 1119 fsPropInfo *prop_info; 1120 int lenpropdata; 1121 int i; 1122 int aliascount = 0; 1123 1124 if (client->clientGone == CLIENT_GONE) { 1125 if (cPtr->current.current_fpe < cPtr->num_fpes) { 1126 fpe = cPtr->fpe_list[cPtr->current.current_fpe]; 1127 (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 1128 } 1129 err = Successful; 1130 goto bail; 1131 } 1132 while (cPtr->current.current_fpe < cPtr->num_fpes) { 1133 fpe = cPtr->fpe_list[cPtr->current.current_fpe]; 1134 err = Successful; 1135 if (!cPtr->current.list_started) { 1136 err = (*fpe_functions[fpe->type].start_list_fonts_with_info) 1137 ((pointer) cPtr->client, fpe, cPtr->current.pattern, 1138 cPtr->current.patlen, cPtr->current.max_names, 1139 &cPtr->current.private); 1140 if (err == Suspended) { 1141 if (!cPtr->slept) { 1142 ClientSleep(client, do_list_fonts_with_info, 1143 (pointer) cPtr); 1144 cPtr->slept = TRUE; 1145 } 1146 return TRUE; 1147 } 1148 if (err == Successful) 1149 cPtr->current.list_started = TRUE; 1150 } 1151 if (err == Successful) { 1152 name = NULL; 1153 pFontInfo = &fontInfo; 1154 err = (*fpe_functions[fpe->type].list_next_font_with_info) 1155 ((pointer) cPtr->client, fpe, &name, &namelen, 1156 &pFontInfo, &numFonts, cPtr->current.private); 1157 if (err == Suspended) { 1158 if (!cPtr->slept) { 1159 ClientSleep(client, do_list_fonts_with_info, 1160 (pointer) cPtr); 1161 cPtr->slept = TRUE; 1162 } 1163 return TRUE; 1164 } 1165 } 1166 /* 1167 * When we get an alias back, save our state and reset back to the 1168 * start of the FPE looking for the specified name. As soon as a real 1169 * font is found for the alias, pop back to the old state 1170 */ 1171 if (err == FontNameAlias) { 1172 /* 1173 * when an alias recurses, we need to give 1174 * the last FPE a chance to clean up; so we call 1175 * it again, and assume that the error returned 1176 * is BadFontName, indicating the alias resolution 1177 * is complete. 1178 */ 1179 if (cPtr->haveSaved) 1180 { 1181 char *tmpname; 1182 int tmpnamelen; 1183 FontInfoPtr tmpFontInfo; 1184 1185 tmpname = NULL; 1186 tmpFontInfo = &fontInfo; 1187 (void) (*fpe_functions[fpe->type].list_next_font_with_info) 1188 ((pointer) client, fpe, &tmpname, &tmpnamelen, 1189 &tmpFontInfo, &numFonts, cPtr->current.private); 1190 if (--aliascount <= 0) 1191 { 1192 err = BadFontName; 1193 goto ContBadFontName; 1194 } 1195 } 1196 else 1197 { 1198 cPtr->saved = cPtr->current; 1199 cPtr->haveSaved = TRUE; 1200 cPtr->savedNumFonts = numFonts; 1201 if (cPtr->savedName) 1202 fsfree(cPtr->savedName); 1203 cPtr->savedName = (char *)fsalloc(namelen + 1); 1204 if (cPtr->savedName) 1205 memmove(cPtr->savedName, name, namelen + 1); 1206 aliascount = 20; 1207 } 1208 memmove(cPtr->current.pattern, name, namelen); 1209 cPtr->current.patlen = namelen; 1210 cPtr->current.max_names = 1; 1211 cPtr->current.current_fpe = 0; 1212 cPtr->current.private = NULL; 1213 cPtr->current.list_started = FALSE; 1214 } 1215 /* 1216 * At the end of this FPE, step to the next. If we've finished 1217 * processing an alias, pop state back. If we've sent enough font 1218 * names, quit. 1219 */ 1220 else if (err == BadFontName) { 1221 ContBadFontName: ; 1222 cPtr->current.list_started = FALSE; 1223 cPtr->current.current_fpe++; 1224 err = Successful; 1225 if (cPtr->haveSaved) { 1226 if (cPtr->current.max_names == 0 || 1227 cPtr->current.current_fpe == cPtr->num_fpes) { 1228 cPtr->haveSaved = FALSE; 1229 cPtr->saved.max_names -= (1 - cPtr->current.max_names); 1230 cPtr->current = cPtr->saved; 1231 } 1232 } 1233 else if (cPtr->current.max_names == 0) 1234 break; 1235 } else if (err == Successful) { 1236/* XXX why is it xFontProp ? */ 1237 length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp); 1238 reply = cPtr->reply; 1239 if (cPtr->length < length) { 1240 reply = (fsListFontsWithXInfoReply *) fsrealloc(cPtr->reply, length); 1241 if (!reply) { 1242 err = AllocError; 1243 break; 1244 } 1245 cPtr->reply = reply; 1246 cPtr->length = length; 1247 } 1248 if (cPtr->haveSaved) { 1249 numFonts = cPtr->savedNumFonts; 1250 name = cPtr->savedName; 1251 namelen = strlen(name); 1252 } 1253 fsPack_XFontInfoHeader(pFontInfo, reply, client->major_version); 1254 err = convert_props(pFontInfo, &prop_info); 1255 if (err != Successful) 1256 break; 1257 lenpropdata = SIZEOF(fsPropInfo) + 1258 prop_info->num_offsets * SIZEOF(fsPropOffset) + 1259 prop_info->data_len; 1260 1261 reply->type = FS_Reply; 1262 reply->length = 1263 (SIZEOF(fsListFontsWithXInfoReply) + 1264 lenpropdata + namelen + 3) >> 2; 1265 reply->sequenceNumber = client->sequence; 1266 reply->nameLength = namelen; 1267 reply->nReplies = numFonts; 1268 WriteReplyToClient(client, SIZEOF(fsListFontsWithXInfoReply), reply); 1269 if (client->swapped) 1270 SwapPropInfo(prop_info); 1271 if (client->major_version > 1) 1272 { 1273 (void)WriteToClientUnpadded(client, lenpropdata, (char *) prop_info); 1274 (void)WriteToClientUnpadded(client, namelen, name); 1275 (void)WriteToClientUnpadded(client, 1276 padlength[(lenpropdata+namelen)&3], 1277 padding); 1278 } else { 1279 (void) WriteToClient(client, namelen, name); 1280 (void) WriteToClient(client, lenpropdata, (char *) prop_info); 1281 } 1282 if (pFontInfo == &fontInfo) { 1283 fsfree(fontInfo.props); 1284 fsfree(fontInfo.isStringProp); 1285 } 1286 fsfree(prop_info); 1287 1288 --cPtr->current.max_names; 1289 if (cPtr->current.max_names < 0) 1290 break; 1291 } 1292 } 1293 1294 /* 1295 * send the final reply 1296 */ 1297 if (err == Successful) { 1298 fsGenericReply *final_reply; 1299 1300 final_reply = (fsGenericReply *)cPtr->reply; 1301 if (client->major_version > 1) 1302 length = SIZEOF(fsGenericReply); 1303 else 1304 length = SIZEOF(fsListFontsWithXInfoReply); 1305 if (cPtr->length < length) { 1306 final_reply = (fsGenericReply *) fsrealloc(cPtr->reply, length); 1307 if (final_reply) { 1308 cPtr->reply = (fsListFontsWithXInfoReply *)final_reply; 1309 cPtr->length = length; 1310 } else 1311 err = AllocError; 1312 } 1313 if (err == Successful) { 1314 final_reply->type = FS_Reply; 1315 final_reply->data1 = 0; /* notes that this is final */ 1316 final_reply->sequenceNumber = client->sequence; 1317 final_reply->length = length >> 2; 1318 WriteReplyToClient(client, length, final_reply); 1319 } 1320 } 1321 if (err != Successful) 1322 SendErrToClient(client, FontToFSError(err), (pointer) 0); 1323bail: 1324 if (cPtr->slept) 1325 ClientWakeup(client); 1326 for (i = 0; i < cPtr->num_fpes; i++) 1327 FreeFPE(cPtr->fpe_list[i]); 1328 fsfree(cPtr->fpe_list); 1329 if (cPtr->savedName) fsfree(cPtr->savedName); 1330 fsfree(cPtr->reply); 1331 fsfree(cPtr); 1332 return TRUE; 1333} 1334 1335int 1336StartListFontsWithInfo( 1337 ClientPtr client, 1338 int length, 1339 unsigned char *pattern, 1340 int maxNames) 1341{ 1342 int i; 1343 LFWXIclosurePtr c; 1344 1345 /* 1346 * The right error to return here would be BadName, however the 1347 * specification does not allow for a Name error on this request. 1348 * Perhaps a better solution would be to return a nil list, i.e. 1349 * a list containing zero fontnames. 1350 */ 1351 if (length > XLFDMAXFONTNAMELEN) { 1352 SendErrToClient(client, FSBadAlloc, (pointer) 0); 1353 return TRUE; 1354 } 1355 1356 if (!(c = (LFWXIclosurePtr) fsalloc(sizeof *c))) 1357 goto badAlloc; 1358 c->fpe_list = (FontPathElementPtr *) 1359 fsalloc(sizeof(FontPathElementPtr) * num_fpes); 1360 if (!c->fpe_list) { 1361 fsfree(c); 1362 goto badAlloc; 1363 } 1364 memmove( c->current.pattern, pattern, length); 1365 for (i = 0; i < num_fpes; i++) { 1366 c->fpe_list[i] = font_path_elements[i]; 1367 UseFPE(c->fpe_list[i]); 1368 } 1369 c->client = client; 1370 c->num_fpes = num_fpes; 1371 c->reply = NULL; 1372 c->length = 0; 1373 c->current.patlen = length; 1374 c->current.current_fpe = 0; 1375 c->current.max_names = maxNames; 1376 c->current.list_started = FALSE; 1377 c->current.private = NULL; 1378 c->savedNumFonts = 0; 1379 c->haveSaved = FALSE; 1380 c->slept = FALSE; 1381 c->savedName = NULL; 1382 do_list_fonts_with_info(client, (pointer) c); 1383 return TRUE; 1384badAlloc: 1385 SendErrToClient(client, FSBadAlloc, (pointer) 0); 1386 return TRUE; 1387} 1388 1389int 1390LoadGlyphRanges( 1391 ClientPtr client, 1392 FontPtr pfont, 1393 Bool range_flag, 1394 int num_ranges, 1395 int item_size, 1396 fsChar2b *data) 1397{ 1398 /* either returns Successful, Suspended, or some nasty error */ 1399 if (fpe_functions[pfont->fpe->type].load_glyphs) 1400 return (*fpe_functions[pfont->fpe->type].load_glyphs)( 1401 (pointer)client, pfont, range_flag, num_ranges, item_size, 1402 (unsigned char *)data); 1403 else 1404 return Successful; 1405} 1406 1407 1408int 1409register_fpe_funcs(const xfont2_fpe_funcs_rec *funcs) 1410{ 1411 xfont2_fpe_funcs_rec *new; 1412 1413 /* grow the list */ 1414 new = fsrealloc(fpe_functions, (num_fpe_types + 1) * sizeof(*new)); 1415 if (!new) 1416 return -1; 1417 fpe_functions = new; 1418 1419 memcpy(&fpe_functions[num_fpe_types], funcs, sizeof(*funcs)); 1420 1421 return num_fpe_types++; 1422} 1423 1424 1425/* convenience functions for FS interface */ 1426 1427FontPtr 1428find_old_font(FSID id) 1429{ 1430 return (FontPtr) LookupIDByType(SERVER_CLIENT, id, RT_NONE); 1431} 1432 1433Font 1434GetNewFontClientID(void) 1435{ 1436 return (Font) FakeClientID(SERVER_CLIENT); 1437} 1438 1439int 1440StoreFontClientFont( 1441 FontPtr pfont, 1442 Font id) 1443{ 1444 return AddResource(SERVER_CLIENT, id, RT_NONE, (pointer) pfont); 1445} 1446 1447void 1448DeleteFontClientID(Font id) 1449{ 1450 FreeResource(SERVER_CLIENT, id, RT_NONE); 1451} 1452 1453static int fs_handlers_installed = 0; 1454static unsigned int last_server_gen; 1455 1456int 1457xfs_init_fs_handlers( 1458 FontPathElementPtr fpe, 1459 FontBlockHandlerProcPtr block_handler) 1460{ 1461 /* if server has reset, make sure the b&w handlers are reinstalled */ 1462 if (last_server_gen < serverGeneration) { 1463 last_server_gen = serverGeneration; 1464 fs_handlers_installed = 0; 1465 } 1466 if (fs_handlers_installed == 0) { 1467 1468#ifdef DEBUG 1469 fprintf(stderr, "adding FS b & w handlers\n"); 1470#endif 1471 1472 if (!RegisterBlockAndWakeupHandlers(block_handler, 1473 FontWakeup, (pointer) 0)) 1474 return AllocError; 1475 fs_handlers_installed++; 1476 } 1477 QueueFontWakeup(fpe); 1478 return Successful; 1479} 1480 1481void 1482xfs_remove_fs_handlers( 1483 FontPathElementPtr fpe, 1484 FontBlockHandlerProcPtr block_handler, 1485 Bool all) 1486{ 1487 if (all) { 1488 /* remove the handlers if no one else is using them */ 1489 if (--fs_handlers_installed == 0) { 1490 1491#ifdef DEBUG 1492 fprintf(stderr, "removing FS b & w handlers\n"); 1493#endif 1494 1495 RemoveBlockAndWakeupHandlers(block_handler, FontWakeup, 1496 (pointer) 0); 1497 } 1498 } 1499 RemoveFontWakeup(fpe); 1500} 1501 1502void 1503DeleteClientFontStuff(ClientPtr client) 1504{ 1505 int i; 1506 FontPathElementPtr fpe; 1507 1508 for (i = 0; i < num_fpes; i++) 1509 { 1510 fpe = font_path_elements[i]; 1511 1512 if (fpe_functions[fpe->type].client_died) 1513 (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 1514 } 1515} 1516