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