fonts.c revision bbe1b32b
1/* $Xorg: fonts.c,v 1.5 2001/02/09 02:05:42 xorgcvs Exp $ */ 2/* 3 * font control 4 */ 5/* 6 7Copyright 1990, 1991, 1998 The Open Group 8 9Permission to use, copy, modify, distribute, and sell this software and its 10documentation for any purpose is hereby granted without fee, provided that 11the above copyright notice appear in all copies and that both that 12copyright notice and this permission notice appear in supporting 13documentation. 14 15The above copyright notice and this permission notice shall be included in 16all copies or substantial portions of the Software. 17 18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25Except as contained in this notice, the name of The Open Group shall not be 26used in advertising or otherwise to promote the sale, use or other dealings 27in this Software without prior written authorization from The Open Group. 28 29 * Copyright 1990, 1991 Network Computing Devices; 30 * Portions Copyright 1987 by Digital Equipment Corporation 31 * 32 * Permission to use, copy, modify, distribute, and sell this software and 33 * its documentation for any purpose is hereby granted without fee, provided 34 * that the above copyright notice appear in all copies and that both that 35 * copyright notice and this permission notice appear in supporting 36 * documentation, and that the names of Network Computing Devices or Digital 37 * not be used in advertising or publicity pertaining to distribution 38 * of the software without specific, written prior permission. 39 * 40 * NETWORK COMPUTING DEVICES AND DIGITAL DISCLAIM ALL WARRANTIES WITH 41 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 42 * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES 43 * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 44 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 45 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 46 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 47 * THIS SOFTWARE. 48 */ 49/*#define DEBUG*/ 50#include <X11/fonts/FS.h> 51#include <X11/fonts/FSproto.h> 52#include <stdio.h> 53#include <stdlib.h> 54#include <X11/Xos.h> 55#include "clientstr.h" 56#include "fsresource.h" 57#include "difsfnst.h" 58#include <X11/fonts/fontstruct.h> 59#include "closestr.h" 60#include "globals.h" 61#include "difs.h" 62#include "dispatch.h" 63#include "swaprep.h" 64 65static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0; 66static int num_fpes = 0; 67static FPEFunctions *fpe_functions = (FPEFunctions *) 0; 68static int num_fpe_types = 0; 69 70static int num_slept_fpes = 0; 71static int size_slept_fpes = 0; 72static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0; 73 74extern FontPatternCachePtr fontPatternCache; 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 98/* XXX -- these two funcs may want to be broken into macros */ 99void 100UseFPE(FontPathElementPtr fpe) 101{ 102 fpe->refcount++; 103} 104 105void 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 */ 125void 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 154void 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 */ 172void 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, LastSelectMask); 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 fsOpenBitmapFontReply rep; 281 Font orig; 282 FontIDListPtr *idlist, 283 ids; 284 int aliascount = 20; 285 286 if (client->clientGone == CLIENT_GONE) { 287 if (cPtr->current_fpe < cPtr->num_fpes) { 288 fpe = cPtr->fpe_list[cPtr->current_fpe]; 289 (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 290 } 291 err = Successful; 292 goto dropout; 293 } 294 while (cPtr->current_fpe < cPtr->num_fpes) { 295 fpe = cPtr->fpe_list[cPtr->current_fpe]; 296 err = (*fpe_functions[fpe->type].open_font) 297 ((pointer) cPtr->client, fpe, cPtr->flags, 298 cPtr->fontname, cPtr->fnamelen, cPtr->format, cPtr->format_mask, 299 cPtr->fontid, &pfont, &alias, 300 cPtr->non_cachable_font && cPtr->non_cachable_font->fpe == fpe ? 301 cPtr->non_cachable_font : 302 (FontPtr)0); 303 304 if (err == FontNameAlias && alias) { 305 newlen = strlen(alias); 306 newname = (char *) fsrealloc(cPtr->fontname, newlen); 307 if (!newname) { 308 err = AllocError; 309 break; 310 } 311 memmove( newname, alias, newlen); 312 cPtr->fontname = newname; 313 cPtr->fnamelen = newlen; 314 cPtr->current_fpe = 0; 315 if (--aliascount <= 0) break; 316 continue; 317 } 318 if (err == BadFontName) { 319 cPtr->current_fpe++; 320 continue; 321 } 322 if (err == Suspended) { 323 if (!cPtr->slept) { 324 cPtr->slept = TRUE; 325 ClientSleep(client, do_open_font, (pointer) cPtr); 326 } 327 return TRUE; 328 } 329 break; 330 } 331 if (err != Successful) { 332 goto dropout; 333 } 334 if (!pfont) { 335 err = BadFontName; 336 goto dropout; 337 } 338 cfp = (ClientFontPtr) fsalloc(sizeof(ClientFontRec)); 339 if (!cfp) { 340 err = AllocError; 341 goto dropout; 342 } 343 cfp->font = pfont; 344 cfp->clientindex = cPtr->client->index; 345 346 if (fontPatternCache && pfont != cPtr->non_cachable_font) 347 CacheFontPattern(fontPatternCache, cPtr->orig_name, 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 add_id_to_list(ids, cPtr->fontid); 390 /* send the reply */ 391 rep.type = FS_Reply; 392 rep.otherid = orig; 393 if (orig) 394 rep.otherid_valid = TRUE; 395 else 396 rep.otherid_valid = FALSE; 397 rep.cachable = pfont->info.cachable; 398 rep.sequenceNumber = client->sequence; 399 rep.length = SIZEOF(fsOpenBitmapFontReply) >> 2; 400 WriteReplyToClient(client, 401 SIZEOF(fsOpenBitmapFontReply), &rep); 402 if (pfont->refcnt == 0) { 403 if (!pfont->fpe) 404 pfont->fpe = fpe; 405 UseFPE(pfont->fpe); 406 } 407 pfont->refcnt++; 408dropout: 409 if (err != Successful) { 410 SendErrToClient(cPtr->client, FontToFSError(err), (pointer) &(cPtr->fontid)); 411 } 412 if (cPtr->slept) 413 ClientWakeup(cPtr->client); 414 for (i = 0; i < cPtr->num_fpes; i++) { 415 FreeFPE(cPtr->fpe_list[i]); 416 } 417 fsfree(cPtr->fpe_list); 418 fsfree(cPtr->fontname); 419 fsfree(cPtr); 420 return TRUE; 421} 422 423int 424OpenFont( 425 ClientPtr client, 426 Font fid, 427 fsBitmapFormat format, 428 fsBitmapFormatMask format_mask, 429 int namelen, 430 char *name) 431{ 432 FontPtr pfont = (FontPtr)0; 433 fsOpenBitmapFontReply rep; 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 = FindCachedFontPattern(fontPatternCache, name, namelen)) && 465 pfont->info.cachable) { 466 ClientFontPtr cfp; 467 468 idlist = (FontIDListPtr *) pfont->svrPrivate; 469 ids = idlist[client->index]; 470 if (!ids) { 471 ids = make_clients_id_list(); 472 if (!ids) { 473 goto lowmem; 474 } 475 idlist[client->index] = ids; 476 } 477 cfp = (ClientFontPtr) fsalloc(sizeof(ClientFontRec)); 478 if (!cfp) { 479 lowmem: 480 SendErrToClient(client, FSBadAlloc, (pointer) 0); 481 return FSBadAlloc; 482 } 483 cfp->font = pfont; 484 cfp->clientindex = client->index; 485 if (!AddResource(client->index, fid, RT_FONT, (pointer) cfp)) { 486 goto lowmem; 487 } 488 if (!add_id_to_list(ids, fid)) { 489 goto lowmem; 490 } 491 pfont->refcnt++; 492 rep.type = FS_Reply; 493 if (ids->num > 1) 494 { 495 rep.otherid = ids->client_list[0]; 496 rep.otherid_valid = TRUE; 497 } 498 else 499 { 500 rep.otherid = 0; 501 rep.otherid_valid = FALSE; 502 } 503 rep.cachable = TRUE; /* XXX */ 504 rep.sequenceNumber = client->sequence; 505 rep.length = SIZEOF(fsOpenBitmapFontReply) >> 2; 506 WriteReplyToClient(client, 507 SIZEOF(fsOpenBitmapFontReply), &rep); 508 return FSSuccess; 509 } 510 c = (OFclosurePtr) fsalloc(sizeof(OFclosureRec)); 511 if (!c) 512 goto lowmem; 513 c->fontname = (char *) fsalloc(namelen); 514 if (!c->fontname) { 515 fsfree(c); 516 goto lowmem; 517 } 518 /* 519 * copy the current FPE list, so that if it gets changed by another client 520 * while we're blocking, the request still appears atomic 521 */ 522 c->fpe_list = (FontPathElementPtr *) 523 fsalloc(sizeof(FontPathElementPtr) * num_fpes); 524 if (!c->fpe_list) { 525 fsfree(c->fontname); 526 fsfree(c); 527 goto lowmem; 528 } 529 memmove( c->fontname, name, namelen); 530 for (i = 0; i < num_fpes; i++) { 531 c->fpe_list[i] = font_path_elements[i]; 532 UseFPE(c->fpe_list[i]); 533 } 534 c->client = client; 535 c->fontid = fid; 536 c->current_fpe = 0; 537 c->num_fpes = num_fpes; 538 c->fnamelen = namelen; 539 c->orig_name = name; 540 c->orig_len = namelen; 541 c->slept = FALSE; 542 c->flags = (FontLoadInfo | FontLoadProps); 543 c->format = format; 544 c->format_mask = format_mask; 545 c->non_cachable_font = pfont; 546 547 (void) do_open_font(client, (pointer) c); 548 return FSSuccess; 549} 550 551static int 552close_font(FontPtr pfont) 553{ 554 FontPathElementPtr fpe; 555 556 assert(pfont); 557 if (--pfont->refcnt == 0) { 558 if (fontPatternCache) 559 RemoveCachedFontPattern(fontPatternCache, pfont); 560 fpe = pfont->fpe; 561 free_svrPrivate(pfont->svrPrivate); 562 (*fpe_functions[fpe->type].close_font) (fpe, pfont); 563 FreeFPE(fpe); 564 } 565 return FSSuccess; 566} 567 568int 569CloseClientFont( 570 ClientFontPtr cfp, 571 FSID fid) 572{ 573 FontIDListPtr *idlist; 574 FontIDListPtr ids; 575 int ret; 576 577 assert(cfp); 578 /* clear otherid id */ 579 idlist = (FontIDListPtr *) cfp->font->svrPrivate; 580 ids = idlist[cfp->clientindex]; 581 remove_id_from_list(ids, fid); 582 ret = close_font(cfp->font); 583 fsfree((char *) cfp); 584 return ret; 585} 586 587/* 588 * search all the known FPE prefixes looking for one to match the given 589 * FPE name 590 */ 591static int 592determine_fpe_type(char *name) 593{ 594 int i; 595 for (i = 0; i < num_fpe_types; i++) { 596 if ((*fpe_functions[i].name_check) (name)) 597 return i; 598 } 599 return -1; 600} 601 602static void 603free_font_path(FontPathElementPtr *list, int n) 604{ 605 int i; 606 607 for (i = 0; i < n; i++) { 608 FreeFPE(list[i]); 609 } 610 fsfree((char *) list); 611} 612 613static FontPathElementPtr 614find_existing_fpe( 615 FontPathElementPtr *list, 616 int num, 617 char *name, 618 int len) 619{ 620 FontPathElementPtr fpe; 621 int i; 622 623 for (i = 0; i < num; i++) { 624 fpe = list[i]; 625 if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0) 626 return fpe; 627 } 628 return (FontPathElementPtr) 0; 629} 630 631/* 632 * does the work of setting up the fpe list 633 * 634 * paths should be a counted string 635 */ 636static int 637set_font_path_elements( 638 int npaths, 639 char *paths, 640 int *bad) 641{ 642 int i, validpaths, err = 0; 643 int len; 644 int type; 645 char *cp = paths; 646 char *name; 647 FontPathElementPtr fpe, *fplist; 648 649 fplist = (FontPathElementPtr *) 650 fsalloc(sizeof(FontPathElementPtr) * npaths); 651 if (!fplist) { 652 *bad = 0; 653 return FSBadAlloc; 654 } 655 for (i = 0; i < num_fpe_types; i++) { 656 if (fpe_functions[i].set_path_hook) 657 (*fpe_functions[i].set_path_hook) (); 658 } 659 for (i = 0, validpaths = 0; i < npaths; i++) { 660 len = *cp++; 661 if (len) { 662 /* if it's already in our active list, just reset it */ 663 /* 664 * note that this can miss FPE's in limbo -- may be worth catching 665 * them, though it'd muck up refcounting 666 */ 667 fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len); 668 if (fpe) { 669 err = (*fpe_functions[fpe->type].reset_fpe) (fpe); 670 if (err == Successful) { 671 UseFPE(fpe);/* since it'll be decref'd later when freed 672 * from the old list */ 673 fplist[validpaths++] = fpe; 674 cp += len; 675 continue; 676 } 677 /* can't do it, so act like it's a new one */ 678 } 679 name = (char *) fsalloc(len + 1); 680 if (!name) { 681 err = FSBadAlloc; 682 goto bail; 683 } 684 strncpy(name, (char *) cp, len); 685 name[len] = '\0'; 686 type = determine_fpe_type(name); 687 if (type == -1) 688 { 689 NoticeF("ignoring font path element %s (bad font path descriptor)\n", name); 690 fsfree(name); 691 continue; 692 } 693 /* must be new -- make it */ 694 fpe = (FontPathElementPtr) fsalloc(sizeof(FontPathElementRec)); 695 if (!fpe) { 696 fsfree(name); 697 err = FSBadAlloc; 698 goto bail; 699 } 700 fpe->type = type; 701 fpe->name = name; 702 fpe->refcount = 1; 703 704 cp += len; 705 fpe->name_length = len; 706 err = (*fpe_functions[fpe->type].init_fpe) (fpe); 707 if (err != Successful) { 708 NoticeF("ignoring font path element %s (unreadable)\n", fpe->name); 709 fsfree(fpe->name); 710 fsfree(fpe); 711 continue; 712 } 713 fplist[validpaths++] = fpe; 714 } 715 } 716 if (validpaths < npaths) { 717 FontPathElementPtr *ftmp = (FontPathElementPtr *) 718 fsrealloc(fplist, sizeof(FontPathElementPtr) * validpaths); 719 720 if (!ftmp && validpaths) 721 goto bail; 722 723 fplist = ftmp; 724 npaths = validpaths; 725 } 726 if (validpaths == 0) { 727 err = FontToFSError(err); 728 goto bail; 729 } 730 free_font_path(font_path_elements, num_fpes); 731 font_path_elements = fplist; 732 num_fpes = npaths; 733 if (fontPatternCache) 734 EmptyFontPatternCache(fontPatternCache); 735 return FSSuccess; 736bail: 737 *bad = validpaths; 738 while (--validpaths >= 0) 739 FreeFPE(fplist[i]); 740 fsfree(fplist); 741 return err; 742} 743 744/* 745 * expects comma seperated string 746 */ 747int 748SetFontCatalogue( 749 char *str, 750 int *badpath) 751{ 752 int len, 753 npaths; 754 char *paths, 755 *end, 756 *p; 757 int err; 758 759 len = strlen(str) + 1; 760 paths = p = (char *) ALLOCATE_LOCAL(len); 761 npaths = 0; 762 763 while (*str) { 764 end = index(str, ','); 765 if (!end) { 766 end = str + strlen(str); 767 } 768 *p++ = len = end - str; 769 memmove( 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 = 0; 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 (void)AddFontNamesName(cPtr->names, cPtr->savedName, 886 cPtr->savedNameLen); 887 } 888 else 889 (void)AddFontNamesName(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 memmove(tmp_pattern, resolved, resolvedlen); 908 if (cPtr->haveSaved) 909 { 910 char *tmpname; 911 int tmpnamelen; 912 913 tmpname = 0; 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 memmove(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 = 0; 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.type = FS_Reply; 1000 reply.length = (SIZEOF(fsListFontsReply) + stringLens + nnames + 3) >> 2; 1001 reply.following = 0; 1002 reply.nFonts = nnames; 1003 reply.sequenceNumber = client->sequence; 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 FreeFontNames(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 = MakeFontNamesRecord(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 = 0; 1091 c->haveSaved = FALSE; 1092 c->slept = FALSE; 1093 c->savedName = 0; 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 = 0; 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 = 0; 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 = 0; 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 abort(); 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 = 0; 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 = 0; 1378 c->savedNumFonts = 0; 1379 c->haveSaved = FALSE; 1380 c->slept = FALSE; 1381 c->savedName = 0; 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 1409RegisterFPEFunctions( 1410 Bool (*name_func) (char *name), 1411 InitFpeFunc init_func, 1412 FreeFpeFunc free_func, 1413 ResetFpeFunc reset_func, 1414 OpenFontFunc open_func, 1415 CloseFontFunc close_func, 1416 ListFontsFunc list_func, 1417 StartLfwiFunc start_lfwi_func, 1418 NextLfwiFunc next_lfwi_func, 1419 WakeupFpeFunc wakeup_func, 1420 ClientDiedFunc client_died, 1421 LoadGlyphsFunc load_glyphs, 1422 StartLaFunc start_list_alias_func, 1423 NextLaFunc next_list_alias_func, 1424 void (*set_path_func) (void)) 1425{ 1426 FPEFunctions *new; 1427 1428 /* grow the list */ 1429 new = (FPEFunctions *) fsrealloc(fpe_functions, 1430 (num_fpe_types + 1) * sizeof(FPEFunctions)); 1431 if (!new) 1432 return -1; 1433 fpe_functions = new; 1434 1435 fpe_functions[num_fpe_types].name_check = name_func; 1436 fpe_functions[num_fpe_types].open_font = open_func; 1437 fpe_functions[num_fpe_types].close_font = close_func; 1438 fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func; 1439 fpe_functions[num_fpe_types].list_fonts = list_func; 1440 fpe_functions[num_fpe_types].start_list_fonts_with_info = 1441 start_lfwi_func; 1442 fpe_functions[num_fpe_types].list_next_font_with_info = 1443 next_lfwi_func; 1444 fpe_functions[num_fpe_types].init_fpe = init_func; 1445 fpe_functions[num_fpe_types].free_fpe = free_func; 1446 fpe_functions[num_fpe_types].reset_fpe = reset_func; 1447 1448 fpe_functions[num_fpe_types].client_died = client_died; 1449 fpe_functions[num_fpe_types].load_glyphs = load_glyphs; 1450 fpe_functions[num_fpe_types].start_list_fonts_and_aliases = 1451 start_list_alias_func; 1452 fpe_functions[num_fpe_types].list_next_font_or_alias = 1453 next_list_alias_func; 1454 fpe_functions[num_fpe_types].set_path_hook = set_path_func; 1455 1456 return num_fpe_types++; 1457} 1458 1459void 1460FreeFonts(void) 1461{ 1462} 1463 1464/* convenience functions for FS interface */ 1465 1466FontPtr 1467find_old_font(FSID id) 1468{ 1469 return (FontPtr) LookupIDByType(SERVER_CLIENT, id, RT_NONE); 1470} 1471 1472Font 1473GetNewFontClientID(void) 1474{ 1475 return (Font) FakeClientID(SERVER_CLIENT); 1476} 1477 1478int 1479StoreFontClientFont( 1480 FontPtr pfont, 1481 Font id) 1482{ 1483 return AddResource(SERVER_CLIENT, id, RT_NONE, (pointer) pfont); 1484} 1485 1486void 1487DeleteFontClientID(Font id) 1488{ 1489 FreeResource(SERVER_CLIENT, id, RT_NONE); 1490} 1491 1492static int fs_handlers_installed = 0; 1493static unsigned int last_server_gen; 1494 1495int 1496init_fs_handlers( 1497 FontPathElementPtr fpe, 1498 BlockHandlerProcPtr block_handler) 1499{ 1500 /* if server has reset, make sure the b&w handlers are reinstalled */ 1501 if (last_server_gen < serverGeneration) { 1502 last_server_gen = serverGeneration; 1503 fs_handlers_installed = 0; 1504 } 1505 if (fs_handlers_installed == 0) { 1506 1507#ifdef DEBUG 1508 fprintf(stderr, "adding FS b & w handlers\n"); 1509#endif 1510 1511 if (!RegisterBlockAndWakeupHandlers(block_handler, 1512 FontWakeup, (pointer) 0)) 1513 return AllocError; 1514 fs_handlers_installed++; 1515 } 1516 QueueFontWakeup(fpe); 1517 return Successful; 1518} 1519 1520void 1521remove_fs_handlers( 1522 FontPathElementPtr fpe, 1523 BlockHandlerProcPtr block_handler, 1524 Bool all) 1525{ 1526 if (all) { 1527 /* remove the handlers if no one else is using them */ 1528 if (--fs_handlers_installed == 0) { 1529 1530#ifdef DEBUG 1531 fprintf(stderr, "removing FS b & w handlers\n"); 1532#endif 1533 1534 RemoveBlockAndWakeupHandlers(block_handler, FontWakeup, 1535 (pointer) 0); 1536 } 1537 } 1538 RemoveFontWakeup(fpe); 1539} 1540 1541void 1542DeleteClientFontStuff(ClientPtr client) 1543{ 1544 int i; 1545 FontPathElementPtr fpe; 1546 1547 for (i = 0; i < num_fpes; i++) 1548 { 1549 fpe = font_path_elements[i]; 1550 1551 if (fpe_functions[fpe->type].client_died) 1552 (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 1553 } 1554} 1555