1 /*
2 * font control
3 */
4 /*
5
6 Copyright 1990, 1991, 1998 The Open Group
7
8 Permission to use, copy, modify, distribute, and sell this software and its
9 documentation for any purpose is hereby granted without fee, provided that
10 the above copyright notice appear in all copies and that both that
11 copyright notice and this permission notice appear in supporting
12 documentation.
13
14 The above copyright notice and this permission notice shall be included in
15 all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24 Except as contained in this notice, the name of The Open Group shall not be
25 used in advertising or otherwise to promote the sale, use or other dealings
26 in 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
68 static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0;
69 static int num_fpes = 0;
70 static xfont2_fpe_funcs_rec *fpe_functions;
71 static int num_fpe_types = 0;
72
73 static int num_slept_fpes = 0;
74 static int size_slept_fpes = 0;
75 static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0;
76
77 #define NUM_IDS_PER_CLIENT 5
78
79 int
FontToFSError(int err)80 FontToFSError(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
99 static inline void
UseFPE(FontPathElementPtr fpe)100 UseFPE(FontPathElementPtr fpe)
101 {
102 fpe->refcount++;
103 }
104
105 static inline void
FreeFPE(FontPathElementPtr fpe)106 FreeFPE(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 */
125 static void
QueueFontWakeup(FontPathElementPtr fpe)126 QueueFontWakeup(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
154 static void
RemoveFontWakeup(FontPathElementPtr fpe)155 RemoveFontWakeup(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 */
172 static void
FontWakeup(pointer data,int count,unsigned long * lastSelectMask)173 FontWakeup(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
187 static Bool
add_id_to_list(FontIDListPtr ids,Font fid)188 add_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
208 static void
remove_id_from_list(FontIDListPtr ids,Font fid)209 remove_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
227 static FontIDListPtr
make_clients_id_list(void)228 make_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
247 static void
free_svrPrivate(pointer svrPrivate)248 free_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
269 static Bool
do_open_font(ClientPtr client,pointer data)270 do_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 }
409 dropout:
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
424 int
OpenFont(ClientPtr client,Font fid,fsBitmapFormat format,fsBitmapFormatMask format_mask,int namelen,char * name)425 OpenFont(
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
548 static int
close_font(FontPtr pfont)549 close_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
565 int
CloseClientFont(ClientFontPtr cfp,FSID fid)566 CloseClientFont(
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 */
588 static int
determine_fpe_type(char * name)589 determine_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
599 static void
free_font_path(FontPathElementPtr * list,int n)600 free_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
610 static FontPathElementPtr
find_existing_fpe(FontPathElementPtr * list,int num,char * name,int len)611 find_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 */
633 static int
set_font_path_elements(int npaths,char * paths,int * bad)634 set_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;
734 bail:
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 */
745 int
SetFontCatalogue(char * str,int * badpath)746 SetFontCatalogue(
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
785 static Bool
do_list_fonts_and_aliases(ClientPtr client,pointer data)786 do_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
988 finish:
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
1031 bail:
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
1043 int
ListFonts(ClientPtr client,int length,unsigned char * pattern,int maxNames)1044 ListFonts(
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;
1096 badAlloc:
1097 SendErrToClient(client, FSBadAlloc, (pointer) 0);
1098 return TRUE;
1099 }
1100
1101 static int padlength[4] = {0, 3, 2, 1};
1102 static char padding[3];
1103
1104 #undef cPtr
1105 #define cPtr ((LFWXIclosurePtr)data)
1106
1107 static Bool
do_list_fonts_with_info(ClientPtr client,pointer data)1108 do_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);
1323 bail:
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
1335 int
StartListFontsWithInfo(ClientPtr client,int length,unsigned char * pattern,int maxNames)1336 StartListFontsWithInfo(
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;
1384 badAlloc:
1385 SendErrToClient(client, FSBadAlloc, (pointer) 0);
1386 return TRUE;
1387 }
1388
1389 int
LoadGlyphRanges(ClientPtr client,FontPtr pfont,Bool range_flag,int num_ranges,int item_size,fsChar2b * data)1390 LoadGlyphRanges(
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
1408 int
register_fpe_funcs(const xfont2_fpe_funcs_rec * funcs)1409 register_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
1427 FontPtr
find_old_font(FSID id)1428 find_old_font(FSID id)
1429 {
1430 return (FontPtr) LookupIDByType(SERVER_CLIENT, id, RT_NONE);
1431 }
1432
1433 Font
GetNewFontClientID(void)1434 GetNewFontClientID(void)
1435 {
1436 return (Font) FakeClientID(SERVER_CLIENT);
1437 }
1438
1439 int
StoreFontClientFont(FontPtr pfont,Font id)1440 StoreFontClientFont(
1441 FontPtr pfont,
1442 Font id)
1443 {
1444 return AddResource(SERVER_CLIENT, id, RT_NONE, (pointer) pfont);
1445 }
1446
1447 void
DeleteFontClientID(Font id)1448 DeleteFontClientID(Font id)
1449 {
1450 FreeResource(SERVER_CLIENT, id, RT_NONE);
1451 }
1452
1453 static int fs_handlers_installed = 0;
1454 static unsigned int last_server_gen;
1455
1456 int
xfs_init_fs_handlers(FontPathElementPtr fpe,FontBlockHandlerProcPtr block_handler)1457 xfs_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
1481 void
xfs_remove_fs_handlers(FontPathElementPtr fpe,FontBlockHandlerProcPtr block_handler,Bool all)1482 xfs_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
1502 void
DeleteClientFontStuff(ClientPtr client)1503 DeleteClientFontStuff(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