1706f2543Smrg/************************************************************************
2706f2543SmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
3706f2543Smrg
4706f2543Smrg                        All Rights Reserved
5706f2543Smrg
6706f2543SmrgPermission to use, copy, modify, and distribute this software and its
7706f2543Smrgdocumentation for any purpose and without fee is hereby granted,
8706f2543Smrgprovided that the above copyright notice appear in all copies and that
9706f2543Smrgboth that copyright notice and this permission notice appear in
10706f2543Smrgsupporting documentation, and that the name of Digital not be
11706f2543Smrgused in advertising or publicity pertaining to distribution of the
12706f2543Smrgsoftware without specific, written prior permission.
13706f2543Smrg
14706f2543SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15706f2543SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16706f2543SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17706f2543SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19706f2543SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20706f2543SmrgSOFTWARE.
21706f2543Smrg
22706f2543Smrg************************************************************************/
23706f2543Smrg/* The panoramix components contained the following notice */
24706f2543Smrg/*
25706f2543SmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
26706f2543Smrg
27706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining a copy
28706f2543Smrgof this software and associated documentation files (the "Software"), to deal
29706f2543Smrgin the Software without restriction, including without limitation the rights
30706f2543Smrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
31706f2543Smrgcopies of the Software.
32706f2543Smrg
33706f2543SmrgThe above copyright notice and this permission notice shall be included in
34706f2543Smrgall copies or substantial portions of the Software.
35706f2543Smrg
36706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
37706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
39706f2543SmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
40706f2543SmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
41706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
42706f2543SmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43706f2543Smrg
44706f2543SmrgExcept as contained in this notice, the name of Digital Equipment Corporation
45706f2543Smrgshall not be used in advertising or otherwise to promote the sale, use or other
46706f2543Smrgdealings in this Software without prior written authorization from Digital
47706f2543SmrgEquipment Corporation.
48706f2543Smrg
49706f2543Smrg******************************************************************/
50706f2543Smrg
51706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
52706f2543Smrg#include <dix-config.h>
53706f2543Smrg#endif
54706f2543Smrg
55706f2543Smrg#include <X11/X.h>
56706f2543Smrg#include <X11/Xmd.h>
57706f2543Smrg#include <X11/Xproto.h>
58706f2543Smrg#include "scrnintstr.h"
59706f2543Smrg#include "resource.h"
60706f2543Smrg#include "dixstruct.h"
61706f2543Smrg#include "cursorstr.h"
62706f2543Smrg#include "misc.h"
63706f2543Smrg#include "opaque.h"
64706f2543Smrg#include "dixfontstr.h"
65706f2543Smrg#include "closestr.h"
66706f2543Smrg#include "dixfont.h"
67706f2543Smrg#include "xace.h"
68706f2543Smrg
69706f2543Smrg#ifdef XF86BIGFONT
70706f2543Smrg#include "xf86bigfontsrv.h"
71706f2543Smrg#endif
72706f2543Smrg
73706f2543Smrgextern pointer fosNaturalParams;
74706f2543Smrgextern FontPtr defaultFont;
75706f2543Smrg
76706f2543Smrgstatic FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0;
77706f2543Smrgstatic int  num_fpes = 0;
78706f2543Smrgstatic FPEFunctions *fpe_functions = (FPEFunctions *) 0;
79706f2543Smrgstatic int  num_fpe_types = 0;
80706f2543Smrg
81706f2543Smrgstatic unsigned char *font_path_string;
82706f2543Smrg
83706f2543Smrgstatic int  num_slept_fpes = 0;
84706f2543Smrgstatic int  size_slept_fpes = 0;
85706f2543Smrgstatic FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0;
86706f2543Smrgstatic FontPatternCachePtr patternCache;
87706f2543Smrg
88706f2543Smrgstatic int
89706f2543SmrgFontToXError(int err)
90706f2543Smrg{
91706f2543Smrg    switch (err) {
92706f2543Smrg    case Successful:
93706f2543Smrg	return Success;
94706f2543Smrg    case AllocError:
95706f2543Smrg	return BadAlloc;
96706f2543Smrg    case BadFontName:
97706f2543Smrg	return BadName;
98706f2543Smrg    case BadFontPath:
99706f2543Smrg    case BadFontFormat:	/* is there something better? */
100706f2543Smrg    case BadCharRange:
101706f2543Smrg	return BadValue;
102706f2543Smrg    default:
103706f2543Smrg	return err;
104706f2543Smrg    }
105706f2543Smrg}
106706f2543Smrg
107706f2543Smrgstatic int
108706f2543SmrgLoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size,
109706f2543Smrg	   unsigned char *data)
110706f2543Smrg{
111706f2543Smrg    if (fpe_functions[pfont->fpe->type].load_glyphs)
112706f2543Smrg	return (*fpe_functions[pfont->fpe->type].load_glyphs)
113706f2543Smrg	    (client, pfont, 0, nchars, item_size, data);
114706f2543Smrg    else
115706f2543Smrg	return Successful;
116706f2543Smrg}
117706f2543Smrg
118706f2543Smrg/*
119706f2543Smrg * adding RT_FONT prevents conflict with default cursor font
120706f2543Smrg */
121706f2543SmrgBool
122706f2543SmrgSetDefaultFont(char *defaultfontname)
123706f2543Smrg{
124706f2543Smrg    int         err;
125706f2543Smrg    FontPtr     pf;
126706f2543Smrg    XID         fid;
127706f2543Smrg
128706f2543Smrg    fid = FakeClientID(0);
129706f2543Smrg    err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync,
130706f2543Smrg		   (unsigned) strlen(defaultfontname), defaultfontname);
131706f2543Smrg    if (err != Success)
132706f2543Smrg	return FALSE;
133706f2543Smrg    err = dixLookupResourceByType((pointer *)&pf, fid, RT_FONT, serverClient,
134706f2543Smrg				  DixReadAccess);
135706f2543Smrg    if (err != Success)
136706f2543Smrg	return FALSE;
137706f2543Smrg    defaultFont = pf;
138706f2543Smrg    return TRUE;
139706f2543Smrg}
140706f2543Smrg
141706f2543Smrg/*
142706f2543Smrg * note that the font wakeup queue is not refcounted.  this is because
143706f2543Smrg * an fpe needs to be added when it's inited, and removed when it's finally
144706f2543Smrg * freed, in order to handle any data that isn't requested, like FS events.
145706f2543Smrg *
146706f2543Smrg * since the only thing that should call these routines is the renderer's
147706f2543Smrg * init_fpe() and free_fpe(), there shouldn't be any problem in using
148706f2543Smrg * freed data.
149706f2543Smrg */
150706f2543Smrgvoid
151706f2543SmrgQueueFontWakeup(FontPathElementPtr fpe)
152706f2543Smrg{
153706f2543Smrg    int         i;
154706f2543Smrg    FontPathElementPtr *new;
155706f2543Smrg
156706f2543Smrg    for (i = 0; i < num_slept_fpes; i++) {
157706f2543Smrg	if (slept_fpes[i] == fpe) {
158706f2543Smrg	    return;
159706f2543Smrg	}
160706f2543Smrg    }
161706f2543Smrg    if (num_slept_fpes == size_slept_fpes) {
162706f2543Smrg	new = (FontPathElementPtr *)
163706f2543Smrg	    realloc(slept_fpes,
164706f2543Smrg		     sizeof(FontPathElementPtr) * (size_slept_fpes + 4));
165706f2543Smrg	if (!new)
166706f2543Smrg	    return;
167706f2543Smrg	slept_fpes = new;
168706f2543Smrg	size_slept_fpes += 4;
169706f2543Smrg    }
170706f2543Smrg    slept_fpes[num_slept_fpes] = fpe;
171706f2543Smrg    num_slept_fpes++;
172706f2543Smrg}
173706f2543Smrg
174706f2543Smrgvoid
175706f2543SmrgRemoveFontWakeup(FontPathElementPtr fpe)
176706f2543Smrg{
177706f2543Smrg    int         i,
178706f2543Smrg                j;
179706f2543Smrg
180706f2543Smrg    for (i = 0; i < num_slept_fpes; i++) {
181706f2543Smrg	if (slept_fpes[i] == fpe) {
182706f2543Smrg	    for (j = i; j < num_slept_fpes; j++) {
183706f2543Smrg		slept_fpes[j] = slept_fpes[j + 1];
184706f2543Smrg	    }
185706f2543Smrg	    num_slept_fpes--;
186706f2543Smrg	    return;
187706f2543Smrg	}
188706f2543Smrg    }
189706f2543Smrg}
190706f2543Smrg
191706f2543Smrgvoid
192706f2543SmrgFontWakeup(pointer data, int count, pointer LastSelectMask)
193706f2543Smrg{
194706f2543Smrg    int         i;
195706f2543Smrg    FontPathElementPtr fpe;
196706f2543Smrg
197706f2543Smrg    if (count < 0)
198706f2543Smrg	return;
199706f2543Smrg    /* wake up any fpe's that may be waiting for information */
200706f2543Smrg    for (i = 0; i < num_slept_fpes; i++) {
201706f2543Smrg	fpe = slept_fpes[i];
202706f2543Smrg	(void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask);
203706f2543Smrg    }
204706f2543Smrg}
205706f2543Smrg
206706f2543Smrg/* XXX -- these two funcs may want to be broken into macros */
207706f2543Smrgstatic void
208706f2543SmrgUseFPE(FontPathElementPtr fpe)
209706f2543Smrg{
210706f2543Smrg    fpe->refcount++;
211706f2543Smrg}
212706f2543Smrg
213706f2543Smrgstatic void
214706f2543SmrgFreeFPE (FontPathElementPtr fpe)
215706f2543Smrg{
216706f2543Smrg    fpe->refcount--;
217706f2543Smrg    if (fpe->refcount == 0) {
218706f2543Smrg	(*fpe_functions[fpe->type].free_fpe) (fpe);
219706f2543Smrg	free(fpe->name);
220706f2543Smrg	free(fpe);
221706f2543Smrg    }
222706f2543Smrg}
223706f2543Smrg
224706f2543Smrgstatic Bool
225706f2543SmrgdoOpenFont(ClientPtr client, OFclosurePtr c)
226706f2543Smrg{
227706f2543Smrg    FontPtr     pfont = NullFont;
228706f2543Smrg    FontPathElementPtr fpe = NULL;
229706f2543Smrg    ScreenPtr   pScr;
230706f2543Smrg    int         err = Successful;
231706f2543Smrg    int         i;
232706f2543Smrg    char       *alias,
233706f2543Smrg               *newname;
234706f2543Smrg    int         newlen;
235706f2543Smrg    int		aliascount = 20;
236706f2543Smrg    /*
237706f2543Smrg     * Decide at runtime what FontFormat to use.
238706f2543Smrg     */
239706f2543Smrg    Mask FontFormat =
240706f2543Smrg
241706f2543Smrg	((screenInfo.imageByteOrder == LSBFirst) ?
242706f2543Smrg	    BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) |
243706f2543Smrg
244706f2543Smrg	((screenInfo.bitmapBitOrder == LSBFirst) ?
245706f2543Smrg	    BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) |
246706f2543Smrg
247706f2543Smrg	BitmapFormatImageRectMin |
248706f2543Smrg
249706f2543Smrg#if GLYPHPADBYTES == 1
250706f2543Smrg	BitmapFormatScanlinePad8 |
251706f2543Smrg#endif
252706f2543Smrg
253706f2543Smrg#if GLYPHPADBYTES == 2
254706f2543Smrg	BitmapFormatScanlinePad16 |
255706f2543Smrg#endif
256706f2543Smrg
257706f2543Smrg#if GLYPHPADBYTES == 4
258706f2543Smrg	BitmapFormatScanlinePad32 |
259706f2543Smrg#endif
260706f2543Smrg
261706f2543Smrg#if GLYPHPADBYTES == 8
262706f2543Smrg	BitmapFormatScanlinePad64 |
263706f2543Smrg#endif
264706f2543Smrg
265706f2543Smrg	BitmapFormatScanlineUnit8;
266706f2543Smrg
267706f2543Smrg    if (client->clientGone)
268706f2543Smrg    {
269706f2543Smrg	if (c->current_fpe < c->num_fpes)
270706f2543Smrg	{
271706f2543Smrg	    fpe = c->fpe_list[c->current_fpe];
272706f2543Smrg	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
273706f2543Smrg	}
274706f2543Smrg	err = Successful;
275706f2543Smrg	goto bail;
276706f2543Smrg    }
277706f2543Smrg    while (c->current_fpe < c->num_fpes) {
278706f2543Smrg	fpe = c->fpe_list[c->current_fpe];
279706f2543Smrg	err = (*fpe_functions[fpe->type].open_font)
280706f2543Smrg	    ((pointer) client, fpe, c->flags,
281706f2543Smrg	     c->fontname, c->fnamelen, FontFormat,
282706f2543Smrg	     BitmapFormatMaskByte |
283706f2543Smrg	     BitmapFormatMaskBit |
284706f2543Smrg	     BitmapFormatMaskImageRectangle |
285706f2543Smrg	     BitmapFormatMaskScanLinePad |
286706f2543Smrg	     BitmapFormatMaskScanLineUnit,
287706f2543Smrg	     c->fontid, &pfont, &alias,
288706f2543Smrg	     c->non_cachable_font && c->non_cachable_font->fpe == fpe ?
289706f2543Smrg		 c->non_cachable_font :
290706f2543Smrg		 (FontPtr)0);
291706f2543Smrg
292706f2543Smrg	if (err == FontNameAlias && alias) {
293706f2543Smrg	    newlen = strlen(alias);
294706f2543Smrg	    newname = (char *) realloc(c->fontname, newlen);
295706f2543Smrg	    if (!newname) {
296706f2543Smrg		err = AllocError;
297706f2543Smrg		break;
298706f2543Smrg	    }
299706f2543Smrg	    memmove(newname, alias, newlen);
300706f2543Smrg	    c->fontname = newname;
301706f2543Smrg	    c->fnamelen = newlen;
302706f2543Smrg	    c->current_fpe = 0;
303706f2543Smrg	    if (--aliascount <= 0) {
304706f2543Smrg		/* We've tried resolving this alias 20 times, we're
305706f2543Smrg 		 * probably stuck in an infinite loop of aliases pointing
306706f2543Smrg 		 * to each other - time to take emergency exit!
307706f2543Smrg 		 */
308706f2543Smrg 		err = BadImplementation;
309706f2543Smrg		break;
310706f2543Smrg	    }
311706f2543Smrg	    continue;
312706f2543Smrg	}
313706f2543Smrg	if (err == BadFontName) {
314706f2543Smrg	    c->current_fpe++;
315706f2543Smrg	    continue;
316706f2543Smrg	}
317706f2543Smrg	if (err == Suspended) {
318706f2543Smrg	    if (!ClientIsAsleep(client))
319706f2543Smrg		ClientSleep(client, (ClientSleepProcPtr)doOpenFont, c);
320706f2543Smrg	    else
321706f2543Smrg		goto xinerama_sleep;
322706f2543Smrg	    return TRUE;
323706f2543Smrg	}
324706f2543Smrg	break;
325706f2543Smrg    }
326706f2543Smrg
327706f2543Smrg    if (err != Successful)
328706f2543Smrg	goto bail;
329706f2543Smrg    if (!pfont) {
330706f2543Smrg	err = BadFontName;
331706f2543Smrg	goto bail;
332706f2543Smrg    }
333706f2543Smrg    /* check values for firstCol, lastCol, firstRow, and lastRow */
334706f2543Smrg    if (pfont->info.firstCol > pfont->info.lastCol ||
335706f2543Smrg       pfont->info.firstRow > pfont->info.lastRow ||
336706f2543Smrg       pfont->info.lastCol - pfont->info.firstCol > 255) {
337706f2543Smrg       err = AllocError;
338706f2543Smrg       goto bail;
339706f2543Smrg    }
340706f2543Smrg    if (!pfont->fpe)
341706f2543Smrg	pfont->fpe = fpe;
342706f2543Smrg    pfont->refcnt++;
343706f2543Smrg    if (pfont->refcnt == 1) {
344706f2543Smrg	UseFPE(pfont->fpe);
345706f2543Smrg	for (i = 0; i < screenInfo.numScreens; i++) {
346706f2543Smrg	    pScr = screenInfo.screens[i];
347706f2543Smrg	    if (pScr->RealizeFont)
348706f2543Smrg	    {
349706f2543Smrg		if (!(*pScr->RealizeFont) (pScr, pfont))
350706f2543Smrg		{
351706f2543Smrg		    CloseFont (pfont, (Font) 0);
352706f2543Smrg		    err = AllocError;
353706f2543Smrg		    goto bail;
354706f2543Smrg		}
355706f2543Smrg	    }
356706f2543Smrg	}
357706f2543Smrg    }
358706f2543Smrg    if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) {
359706f2543Smrg	err = AllocError;
360706f2543Smrg	goto bail;
361706f2543Smrg    }
362706f2543Smrg    if (patternCache && pfont != c->non_cachable_font)
363706f2543Smrg	CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen,
364706f2543Smrg			 pfont);
365706f2543Smrgbail:
366706f2543Smrg    if (err != Successful && c->client != serverClient) {
367706f2543Smrg	SendErrorToClient(c->client, X_OpenFont, 0,
368706f2543Smrg			  c->fontid, FontToXError(err));
369706f2543Smrg    }
370706f2543Smrg    ClientWakeup(c->client);
371706f2543Smrgxinerama_sleep:
372706f2543Smrg    for (i = 0; i < c->num_fpes; i++) {
373706f2543Smrg	FreeFPE(c->fpe_list[i]);
374706f2543Smrg    }
375706f2543Smrg    free(c->fpe_list);
376706f2543Smrg    free(c->fontname);
377706f2543Smrg    free(c);
378706f2543Smrg    return TRUE;
379706f2543Smrg}
380706f2543Smrg
381706f2543Smrgint
382706f2543SmrgOpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontname)
383706f2543Smrg{
384706f2543Smrg    OFclosurePtr c;
385706f2543Smrg    int         i;
386706f2543Smrg    FontPtr     cached = (FontPtr)0;
387706f2543Smrg
388706f2543Smrg    if (!lenfname || lenfname > XLFDMAXFONTNAMELEN)
389706f2543Smrg	return BadName;
390706f2543Smrg    if (patternCache)
391706f2543Smrg    {
392706f2543Smrg
393706f2543Smrg    /*
394706f2543Smrg    ** Check name cache.  If we find a cached version of this font that
395706f2543Smrg    ** is cachable, immediately satisfy the request with it.  If we find
396706f2543Smrg    ** a cached version of this font that is non-cachable, we do not
397706f2543Smrg    ** satisfy the request with it.  Instead, we pass the FontPtr to the
398706f2543Smrg    ** FPE's open_font code (the fontfile FPE in turn passes the
399706f2543Smrg    ** information to the rasterizer; the fserve FPE ignores it).
400706f2543Smrg    **
401706f2543Smrg    ** Presumably, the font is marked non-cachable because the FPE has
402706f2543Smrg    ** put some licensing restrictions on it.  If the FPE, using
403706f2543Smrg    ** whatever logic it relies on, determines that it is willing to
404706f2543Smrg    ** share this existing font with the client, then it has the option
405706f2543Smrg    ** to return the FontPtr we passed it as the newly-opened font.
406706f2543Smrg    ** This allows the FPE to exercise its licensing logic without
407706f2543Smrg    ** having to create another instance of a font that already exists.
408706f2543Smrg    */
409706f2543Smrg
410706f2543Smrg	cached = FindCachedFontPattern(patternCache, pfontname, lenfname);
411706f2543Smrg	if (cached && cached->info.cachable)
412706f2543Smrg	{
413706f2543Smrg	    if (!AddResource(fid, RT_FONT, (pointer) cached))
414706f2543Smrg		return BadAlloc;
415706f2543Smrg	    cached->refcnt++;
416706f2543Smrg	    return Success;
417706f2543Smrg	}
418706f2543Smrg    }
419706f2543Smrg    c = malloc(sizeof(OFclosureRec));
420706f2543Smrg    if (!c)
421706f2543Smrg	return BadAlloc;
422706f2543Smrg    c->fontname = malloc(lenfname);
423706f2543Smrg    c->origFontName = pfontname;
424706f2543Smrg    c->origFontNameLen = lenfname;
425706f2543Smrg    if (!c->fontname) {
426706f2543Smrg	free(c);
427706f2543Smrg	return BadAlloc;
428706f2543Smrg    }
429706f2543Smrg    /*
430706f2543Smrg     * copy the current FPE list, so that if it gets changed by another client
431706f2543Smrg     * while we're blocking, the request still appears atomic
432706f2543Smrg     */
433706f2543Smrg    c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes);
434706f2543Smrg    if (!c->fpe_list) {
435706f2543Smrg	free(c->fontname);
436706f2543Smrg	free(c);
437706f2543Smrg	return BadAlloc;
438706f2543Smrg    }
439706f2543Smrg    memmove(c->fontname, pfontname, lenfname);
440706f2543Smrg    for (i = 0; i < num_fpes; i++) {
441706f2543Smrg	c->fpe_list[i] = font_path_elements[i];
442706f2543Smrg	UseFPE(c->fpe_list[i]);
443706f2543Smrg    }
444706f2543Smrg    c->client = client;
445706f2543Smrg    c->fontid = fid;
446706f2543Smrg    c->current_fpe = 0;
447706f2543Smrg    c->num_fpes = num_fpes;
448706f2543Smrg    c->fnamelen = lenfname;
449706f2543Smrg    c->flags = flags;
450706f2543Smrg    c->non_cachable_font = cached;
451706f2543Smrg
452706f2543Smrg    (void) doOpenFont(client, c);
453706f2543Smrg    return Success;
454706f2543Smrg}
455706f2543Smrg
456706f2543Smrg/**
457706f2543Smrg * Decrement font's ref count, and free storage if ref count equals zero
458706f2543Smrg *
459706f2543Smrg *  \param value must conform to DeleteType
460706f2543Smrg */
461706f2543Smrgint
462706f2543SmrgCloseFont(pointer value, XID fid)
463706f2543Smrg{
464706f2543Smrg    int         nscr;
465706f2543Smrg    ScreenPtr   pscr;
466706f2543Smrg    FontPathElementPtr fpe;
467706f2543Smrg    FontPtr     pfont = (FontPtr)value;
468706f2543Smrg
469706f2543Smrg    if (pfont == NullFont)
470706f2543Smrg	return Success;
471706f2543Smrg    if (--pfont->refcnt == 0) {
472706f2543Smrg	if (patternCache)
473706f2543Smrg	    RemoveCachedFontPattern (patternCache, pfont);
474706f2543Smrg	/*
475706f2543Smrg	 * since the last reference is gone, ask each screen to free any
476706f2543Smrg	 * storage it may have allocated locally for it.
477706f2543Smrg	 */
478706f2543Smrg	for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
479706f2543Smrg	    pscr = screenInfo.screens[nscr];
480706f2543Smrg	    if (pscr->UnrealizeFont)
481706f2543Smrg		(*pscr->UnrealizeFont) (pscr, pfont);
482706f2543Smrg	}
483706f2543Smrg	if (pfont == defaultFont)
484706f2543Smrg	    defaultFont = NULL;
485706f2543Smrg#ifdef XF86BIGFONT
486706f2543Smrg	XF86BigfontFreeFontShm(pfont);
487706f2543Smrg#endif
488706f2543Smrg	fpe = pfont->fpe;
489706f2543Smrg	(*fpe_functions[fpe->type].close_font) (fpe, pfont);
490706f2543Smrg	FreeFPE(fpe);
491706f2543Smrg    }
492706f2543Smrg    return Success;
493706f2543Smrg}
494706f2543Smrg
495706f2543Smrg
496706f2543Smrg/***====================================================================***/
497706f2543Smrg
498706f2543Smrg/**
499706f2543Smrg * Sets up pReply as the correct QueryFontReply for pFont with the first
500706f2543Smrg * nProtoCCIStructs char infos.
501706f2543Smrg *
502706f2543Smrg *  \param pReply caller must allocate this storage
503706f2543Smrg  */
504706f2543Smrgvoid
505706f2543SmrgQueryFont(FontPtr pFont, xQueryFontReply *pReply, int nProtoCCIStructs)
506706f2543Smrg{
507706f2543Smrg    FontPropPtr      pFP;
508706f2543Smrg    int              r,
509706f2543Smrg                     c,
510706f2543Smrg                     i;
511706f2543Smrg    xFontProp       *prFP;
512706f2543Smrg    xCharInfo       *prCI;
513706f2543Smrg    xCharInfo       *charInfos[256];
514706f2543Smrg    unsigned char    chars[512];
515706f2543Smrg    int              ninfos;
516706f2543Smrg    unsigned long    ncols;
517706f2543Smrg    unsigned long    count;
518706f2543Smrg
519706f2543Smrg    /* pr->length set in dispatch */
520706f2543Smrg    pReply->minCharOrByte2 = pFont->info.firstCol;
521706f2543Smrg    pReply->defaultChar = pFont->info.defaultCh;
522706f2543Smrg    pReply->maxCharOrByte2 = pFont->info.lastCol;
523706f2543Smrg    pReply->drawDirection = pFont->info.drawDirection;
524706f2543Smrg    pReply->allCharsExist = pFont->info.allExist;
525706f2543Smrg    pReply->minByte1 = pFont->info.firstRow;
526706f2543Smrg    pReply->maxByte1 = pFont->info.lastRow;
527706f2543Smrg    pReply->fontAscent = pFont->info.fontAscent;
528706f2543Smrg    pReply->fontDescent = pFont->info.fontDescent;
529706f2543Smrg
530706f2543Smrg    pReply->minBounds = pFont->info.ink_minbounds;
531706f2543Smrg    pReply->maxBounds = pFont->info.ink_maxbounds;
532706f2543Smrg
533706f2543Smrg    pReply->nFontProps = pFont->info.nprops;
534706f2543Smrg    pReply->nCharInfos = nProtoCCIStructs;
535706f2543Smrg
536706f2543Smrg    for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]);
537706f2543Smrg	    i < pFont->info.nprops;
538706f2543Smrg	    i++, pFP++, prFP++) {
539706f2543Smrg	prFP->name = pFP->name;
540706f2543Smrg	prFP->value = pFP->value;
541706f2543Smrg    }
542706f2543Smrg
543706f2543Smrg    ninfos = 0;
544706f2543Smrg    ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1);
545706f2543Smrg    prCI = (xCharInfo *) (prFP);
546706f2543Smrg    for (r = pFont->info.firstRow;
547706f2543Smrg	    ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow;
548706f2543Smrg	    r++) {
549706f2543Smrg	i = 0;
550706f2543Smrg	for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) {
551706f2543Smrg	    chars[i++] = r;
552706f2543Smrg	    chars[i++] = c;
553706f2543Smrg	}
554706f2543Smrg	(*pFont->get_metrics) (pFont, ncols, chars,
555706f2543Smrg				TwoD16Bit, &count, charInfos);
556706f2543Smrg	i = 0;
557706f2543Smrg	for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) {
558706f2543Smrg	    *prCI = *charInfos[i];
559706f2543Smrg	    prCI++;
560706f2543Smrg	    ninfos++;
561706f2543Smrg	}
562706f2543Smrg    }
563706f2543Smrg    return;
564706f2543Smrg}
565706f2543Smrg
566706f2543Smrgstatic Bool
567706f2543SmrgdoListFontsAndAliases(ClientPtr client, LFclosurePtr c)
568706f2543Smrg{
569706f2543Smrg    FontPathElementPtr fpe;
570706f2543Smrg    int         err = Successful;
571706f2543Smrg    FontNamesPtr names = NULL;
572706f2543Smrg    char       *name, *resolved=NULL;
573706f2543Smrg    int         namelen, resolvedlen;
574706f2543Smrg    int		nnames;
575706f2543Smrg    int         stringLens;
576706f2543Smrg    int         i;
577706f2543Smrg    xListFontsReply reply;
578706f2543Smrg    char	*bufptr;
579706f2543Smrg    char	*bufferStart;
580706f2543Smrg    int		aliascount = 0;
581706f2543Smrg
582706f2543Smrg    if (client->clientGone)
583706f2543Smrg    {
584706f2543Smrg	if (c->current.current_fpe < c->num_fpes)
585706f2543Smrg	{
586706f2543Smrg	    fpe = c->fpe_list[c->current.current_fpe];
587706f2543Smrg	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
588706f2543Smrg	}
589706f2543Smrg	err = Successful;
590706f2543Smrg	goto bail;
591706f2543Smrg    }
592706f2543Smrg
593706f2543Smrg    if (!c->current.patlen)
594706f2543Smrg	goto finish;
595706f2543Smrg
596706f2543Smrg    while (c->current.current_fpe < c->num_fpes) {
597706f2543Smrg	fpe = c->fpe_list[c->current.current_fpe];
598706f2543Smrg	err = Successful;
599706f2543Smrg
600706f2543Smrg	if (!fpe_functions[fpe->type].start_list_fonts_and_aliases)
601706f2543Smrg	{
602706f2543Smrg	    /* This FPE doesn't support/require list_fonts_and_aliases */
603706f2543Smrg
604706f2543Smrg	    err = (*fpe_functions[fpe->type].list_fonts)
605706f2543Smrg		((pointer) c->client, fpe, c->current.pattern,
606706f2543Smrg		 c->current.patlen, c->current.max_names - c->names->nnames,
607706f2543Smrg		 c->names);
608706f2543Smrg
609706f2543Smrg	    if (err == Suspended) {
610706f2543Smrg		if (!ClientIsAsleep(client))
611706f2543Smrg		    ClientSleep(client,
612706f2543Smrg				(ClientSleepProcPtr)doListFontsAndAliases,
613706f2543Smrg				c);
614706f2543Smrg		else
615706f2543Smrg		    goto xinerama_sleep;
616706f2543Smrg		return TRUE;
617706f2543Smrg	    }
618706f2543Smrg
619706f2543Smrg	    err = BadFontName;
620706f2543Smrg	}
621706f2543Smrg	else
622706f2543Smrg	{
623706f2543Smrg	    /* Start of list_fonts_and_aliases functionality.  Modeled
624706f2543Smrg	       after list_fonts_with_info in that it resolves aliases,
625706f2543Smrg	       except that the information collected from FPEs is just
626706f2543Smrg	       names, not font info.  Each list_next_font_or_alias()
627706f2543Smrg	       returns either a name into name/namelen or an alias into
628706f2543Smrg	       name/namelen and its target name into resolved/resolvedlen.
629706f2543Smrg	       The code at this level then resolves the alias by polling
630706f2543Smrg	       the FPEs.  */
631706f2543Smrg
632706f2543Smrg	    if (!c->current.list_started) {
633706f2543Smrg		err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases)
634706f2543Smrg		    ((pointer) c->client, fpe, c->current.pattern,
635706f2543Smrg		     c->current.patlen, c->current.max_names - c->names->nnames,
636706f2543Smrg		     &c->current.private);
637706f2543Smrg		if (err == Suspended) {
638706f2543Smrg		    if (!ClientIsAsleep(client))
639706f2543Smrg			ClientSleep(client,
640706f2543Smrg				    (ClientSleepProcPtr)doListFontsAndAliases,
641706f2543Smrg				    c);
642706f2543Smrg		    else
643706f2543Smrg			goto xinerama_sleep;
644706f2543Smrg		    return TRUE;
645706f2543Smrg		}
646706f2543Smrg		if (err == Successful)
647706f2543Smrg		    c->current.list_started = TRUE;
648706f2543Smrg	    }
649706f2543Smrg	    if (err == Successful) {
650706f2543Smrg		char    *tmpname;
651706f2543Smrg		name = 0;
652706f2543Smrg		err = (*fpe_functions[fpe->type].list_next_font_or_alias)
653706f2543Smrg		    ((pointer) c->client, fpe, &name, &namelen, &tmpname,
654706f2543Smrg		     &resolvedlen, c->current.private);
655706f2543Smrg		if (err == Suspended) {
656706f2543Smrg		    if (!ClientIsAsleep(client))
657706f2543Smrg			ClientSleep(client,
658706f2543Smrg				    (ClientSleepProcPtr)doListFontsAndAliases,
659706f2543Smrg				    c);
660706f2543Smrg		    else
661706f2543Smrg			goto xinerama_sleep;
662706f2543Smrg		    return TRUE;
663706f2543Smrg		}
664706f2543Smrg		if (err == FontNameAlias) {
665706f2543Smrg		    free(resolved);
666706f2543Smrg		    resolved = malloc(resolvedlen + 1);
667706f2543Smrg		    if (resolved)
668706f2543Smrg			memmove(resolved, tmpname, resolvedlen + 1);
669706f2543Smrg		}
670706f2543Smrg	    }
671706f2543Smrg
672706f2543Smrg	    if (err == Successful)
673706f2543Smrg	    {
674706f2543Smrg		if (c->haveSaved)
675706f2543Smrg		{
676706f2543Smrg		    if (c->savedName)
677706f2543Smrg			(void)AddFontNamesName(c->names, c->savedName,
678706f2543Smrg					       c->savedNameLen);
679706f2543Smrg		}
680706f2543Smrg		else
681706f2543Smrg		    (void)AddFontNamesName(c->names, name, namelen);
682706f2543Smrg	    }
683706f2543Smrg
684706f2543Smrg	    /*
685706f2543Smrg	     * When we get an alias back, save our state and reset back to
686706f2543Smrg	     * the start of the FPE looking for the specified name.  As
687706f2543Smrg	     * soon as a real font is found for the alias, pop back to the
688706f2543Smrg	     * old state
689706f2543Smrg	     */
690706f2543Smrg	    else if (err == FontNameAlias) {
691706f2543Smrg		char	tmp_pattern[XLFDMAXFONTNAMELEN];
692706f2543Smrg		/*
693706f2543Smrg		 * when an alias recurses, we need to give
694706f2543Smrg		 * the last FPE a chance to clean up; so we call
695706f2543Smrg		 * it again, and assume that the error returned
696706f2543Smrg		 * is BadFontName, indicating the alias resolution
697706f2543Smrg		 * is complete.
698706f2543Smrg		 */
699706f2543Smrg		memmove(tmp_pattern, resolved, resolvedlen);
700706f2543Smrg		if (c->haveSaved)
701706f2543Smrg		{
702706f2543Smrg		    char    *tmpname;
703706f2543Smrg		    int     tmpnamelen;
704706f2543Smrg
705706f2543Smrg		    tmpname = 0;
706706f2543Smrg		    (void) (*fpe_functions[fpe->type].list_next_font_or_alias)
707706f2543Smrg			((pointer) c->client, fpe, &tmpname, &tmpnamelen,
708706f2543Smrg			 &tmpname, &tmpnamelen, c->current.private);
709706f2543Smrg		    if (--aliascount <= 0)
710706f2543Smrg		    {
711706f2543Smrg			err = BadFontName;
712706f2543Smrg			goto ContBadFontName;
713706f2543Smrg		    }
714706f2543Smrg		}
715706f2543Smrg		else
716706f2543Smrg		{
717706f2543Smrg		    c->saved = c->current;
718706f2543Smrg		    c->haveSaved = TRUE;
719706f2543Smrg		    free(c->savedName);
720706f2543Smrg		    c->savedName = malloc(namelen + 1);
721706f2543Smrg		    if (c->savedName)
722706f2543Smrg			memmove(c->savedName, name, namelen + 1);
723706f2543Smrg		    c->savedNameLen = namelen;
724706f2543Smrg		    aliascount = 20;
725706f2543Smrg		}
726706f2543Smrg		memmove(c->current.pattern, tmp_pattern, resolvedlen);
727706f2543Smrg		c->current.patlen = resolvedlen;
728706f2543Smrg		c->current.max_names = c->names->nnames + 1;
729706f2543Smrg		c->current.current_fpe = -1;
730706f2543Smrg		c->current.private = 0;
731706f2543Smrg		err = BadFontName;
732706f2543Smrg	    }
733706f2543Smrg	}
734706f2543Smrg	/*
735706f2543Smrg	 * At the end of this FPE, step to the next.  If we've finished
736706f2543Smrg	 * processing an alias, pop state back. If we've collected enough
737706f2543Smrg	 * font names, quit.
738706f2543Smrg	 */
739706f2543Smrg	if (err == BadFontName) {
740706f2543Smrg	  ContBadFontName: ;
741706f2543Smrg	    c->current.list_started = FALSE;
742706f2543Smrg	    c->current.current_fpe++;
743706f2543Smrg	    err = Successful;
744706f2543Smrg	    if (c->haveSaved)
745706f2543Smrg	    {
746706f2543Smrg		if (c->names->nnames == c->current.max_names ||
747706f2543Smrg			c->current.current_fpe == c->num_fpes) {
748706f2543Smrg		    c->haveSaved = FALSE;
749706f2543Smrg		    c->current = c->saved;
750706f2543Smrg		    /* Give the saved namelist a chance to clean itself up */
751706f2543Smrg		    continue;
752706f2543Smrg		}
753706f2543Smrg	    }
754706f2543Smrg	    if (c->names->nnames == c->current.max_names)
755706f2543Smrg		break;
756706f2543Smrg	}
757706f2543Smrg    }
758706f2543Smrg
759706f2543Smrg    /*
760706f2543Smrg     * send the reply
761706f2543Smrg     */
762706f2543Smrg    if (err != Successful) {
763706f2543Smrg	SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err));
764706f2543Smrg	goto bail;
765706f2543Smrg    }
766706f2543Smrg
767706f2543Smrgfinish:
768706f2543Smrg
769706f2543Smrg    names = c->names;
770706f2543Smrg    nnames = names->nnames;
771706f2543Smrg    client = c->client;
772706f2543Smrg    stringLens = 0;
773706f2543Smrg    for (i = 0; i < nnames; i++)
774706f2543Smrg	stringLens += (names->length[i] <= 255) ? names->length[i] : 0;
775706f2543Smrg
776706f2543Smrg    memset(&reply, 0, sizeof(xListFontsReply));
777706f2543Smrg    reply.type = X_Reply;
778706f2543Smrg    reply.length = bytes_to_int32(stringLens + nnames);
779706f2543Smrg    reply.nFonts = nnames;
780706f2543Smrg    reply.sequenceNumber = client->sequence;
781706f2543Smrg
782706f2543Smrg    bufptr = bufferStart = malloc(reply.length << 2);
783706f2543Smrg
784706f2543Smrg    if (!bufptr && reply.length) {
785706f2543Smrg	SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc);
786706f2543Smrg	goto bail;
787706f2543Smrg    }
788706f2543Smrg    /*
789706f2543Smrg     * since WriteToClient long word aligns things, copy to temp buffer and
790706f2543Smrg     * write all at once
791706f2543Smrg     */
792706f2543Smrg    for (i = 0; i < nnames; i++) {
793706f2543Smrg	if (names->length[i] > 255)
794706f2543Smrg	    reply.nFonts--;
795706f2543Smrg	else
796706f2543Smrg	{
797706f2543Smrg	    *bufptr++ = names->length[i];
798706f2543Smrg	    memmove( bufptr, names->names[i], names->length[i]);
799706f2543Smrg	    bufptr += names->length[i];
800706f2543Smrg	}
801706f2543Smrg    }
802706f2543Smrg    nnames = reply.nFonts;
803706f2543Smrg    reply.length = bytes_to_int32(stringLens + nnames);
804706f2543Smrg    client->pSwapReplyFunc = ReplySwapVector[X_ListFonts];
805706f2543Smrg    WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply);
806706f2543Smrg    (void) WriteToClient(client, stringLens + nnames, bufferStart);
807706f2543Smrg    free(bufferStart);
808706f2543Smrg
809706f2543Smrgbail:
810706f2543Smrg    ClientWakeup(client);
811706f2543Smrgxinerama_sleep:
812706f2543Smrg    for (i = 0; i < c->num_fpes; i++)
813706f2543Smrg	FreeFPE(c->fpe_list[i]);
814706f2543Smrg    free(c->fpe_list);
815706f2543Smrg    free(c->savedName);
816706f2543Smrg    FreeFontNames(names);
817706f2543Smrg    free(c);
818706f2543Smrg    free(resolved);
819706f2543Smrg    return TRUE;
820706f2543Smrg}
821706f2543Smrg
822706f2543Smrgint
823706f2543SmrgListFonts(ClientPtr client, unsigned char *pattern, unsigned length,
824706f2543Smrg          unsigned max_names)
825706f2543Smrg{
826706f2543Smrg    int         i;
827706f2543Smrg    LFclosurePtr c;
828706f2543Smrg
829706f2543Smrg    /*
830706f2543Smrg     * The right error to return here would be BadName, however the
831706f2543Smrg     * specification does not allow for a Name error on this request.
832706f2543Smrg     * Perhaps a better solution would be to return a nil list, i.e.
833706f2543Smrg     * a list containing zero fontnames.
834706f2543Smrg     */
835706f2543Smrg    if (length > XLFDMAXFONTNAMELEN)
836706f2543Smrg	return BadAlloc;
837706f2543Smrg
838706f2543Smrg    i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
839706f2543Smrg    if (i != Success)
840706f2543Smrg	return i;
841706f2543Smrg
842706f2543Smrg    if (!(c = malloc(sizeof *c)))
843706f2543Smrg	return BadAlloc;
844706f2543Smrg    c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes);
845706f2543Smrg    if (!c->fpe_list) {
846706f2543Smrg	free(c);
847706f2543Smrg	return BadAlloc;
848706f2543Smrg    }
849706f2543Smrg    c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100);
850706f2543Smrg    if (!c->names)
851706f2543Smrg    {
852706f2543Smrg	free(c->fpe_list);
853706f2543Smrg	free(c);
854706f2543Smrg	return BadAlloc;
855706f2543Smrg    }
856706f2543Smrg    memmove( c->current.pattern, pattern, length);
857706f2543Smrg    for (i = 0; i < num_fpes; i++) {
858706f2543Smrg	c->fpe_list[i] = font_path_elements[i];
859706f2543Smrg	UseFPE(c->fpe_list[i]);
860706f2543Smrg    }
861706f2543Smrg    c->client = client;
862706f2543Smrg    c->num_fpes = num_fpes;
863706f2543Smrg    c->current.patlen = length;
864706f2543Smrg    c->current.current_fpe = 0;
865706f2543Smrg    c->current.max_names = max_names;
866706f2543Smrg    c->current.list_started = FALSE;
867706f2543Smrg    c->current.private = 0;
868706f2543Smrg    c->haveSaved = FALSE;
869706f2543Smrg    c->savedName = 0;
870706f2543Smrg    doListFontsAndAliases(client, c);
871706f2543Smrg    return Success;
872706f2543Smrg}
873706f2543Smrg
874706f2543Smrgint
875706f2543SmrgdoListFontsWithInfo(ClientPtr client, LFWIclosurePtr c)
876706f2543Smrg{
877706f2543Smrg    FontPathElementPtr fpe;
878706f2543Smrg    int         err = Successful;
879706f2543Smrg    char       *name;
880706f2543Smrg    int         namelen;
881706f2543Smrg    int         numFonts;
882706f2543Smrg    FontInfoRec fontInfo,
883706f2543Smrg               *pFontInfo;
884706f2543Smrg    xListFontsWithInfoReply *reply;
885706f2543Smrg    int         length;
886706f2543Smrg    xFontProp  *pFP;
887706f2543Smrg    int         i;
888706f2543Smrg    int		aliascount = 0;
889706f2543Smrg    xListFontsWithInfoReply finalReply;
890706f2543Smrg
891706f2543Smrg    if (client->clientGone)
892706f2543Smrg    {
893706f2543Smrg	if (c->current.current_fpe < c->num_fpes)
894706f2543Smrg 	{
895706f2543Smrg	    fpe = c->fpe_list[c->current.current_fpe];
896706f2543Smrg	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
897706f2543Smrg	}
898706f2543Smrg	err = Successful;
899706f2543Smrg	goto bail;
900706f2543Smrg    }
901706f2543Smrg    client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo];
902706f2543Smrg    if (!c->current.patlen)
903706f2543Smrg	goto finish;
904706f2543Smrg    while (c->current.current_fpe < c->num_fpes)
905706f2543Smrg    {
906706f2543Smrg	fpe = c->fpe_list[c->current.current_fpe];
907706f2543Smrg	err = Successful;
908706f2543Smrg	if (!c->current.list_started)
909706f2543Smrg 	{
910706f2543Smrg	    err = (*fpe_functions[fpe->type].start_list_fonts_with_info)
911706f2543Smrg		(client, fpe, c->current.pattern, c->current.patlen,
912706f2543Smrg		 c->current.max_names, &c->current.private);
913706f2543Smrg	    if (err == Suspended)
914706f2543Smrg 	    {
915706f2543Smrg		if (!ClientIsAsleep(client))
916706f2543Smrg		    ClientSleep(client,
917706f2543Smrg				(ClientSleepProcPtr)doListFontsWithInfo, c);
918706f2543Smrg		else
919706f2543Smrg		    goto xinerama_sleep;
920706f2543Smrg		return TRUE;
921706f2543Smrg	    }
922706f2543Smrg	    if (err == Successful)
923706f2543Smrg		c->current.list_started = TRUE;
924706f2543Smrg	}
925706f2543Smrg	if (err == Successful)
926706f2543Smrg 	{
927706f2543Smrg	    name = 0;
928706f2543Smrg	    pFontInfo = &fontInfo;
929706f2543Smrg	    err = (*fpe_functions[fpe->type].list_next_font_with_info)
930706f2543Smrg		(client, fpe, &name, &namelen, &pFontInfo,
931706f2543Smrg		 &numFonts, c->current.private);
932706f2543Smrg	    if (err == Suspended)
933706f2543Smrg 	    {
934706f2543Smrg		if (!ClientIsAsleep(client))
935706f2543Smrg		    ClientSleep(client,
936706f2543Smrg				(ClientSleepProcPtr)doListFontsWithInfo, c);
937706f2543Smrg		else
938706f2543Smrg		    goto xinerama_sleep;
939706f2543Smrg		return TRUE;
940706f2543Smrg	    }
941706f2543Smrg	}
942706f2543Smrg	/*
943706f2543Smrg	 * When we get an alias back, save our state and reset back to the
944706f2543Smrg	 * start of the FPE looking for the specified name.  As soon as a real
945706f2543Smrg	 * font is found for the alias, pop back to the old state
946706f2543Smrg	 */
947706f2543Smrg	if (err == FontNameAlias)
948706f2543Smrg 	{
949706f2543Smrg	    /*
950706f2543Smrg	     * when an alias recurses, we need to give
951706f2543Smrg	     * the last FPE a chance to clean up; so we call
952706f2543Smrg	     * it again, and assume that the error returned
953706f2543Smrg	     * is BadFontName, indicating the alias resolution
954706f2543Smrg	     * is complete.
955706f2543Smrg	     */
956706f2543Smrg	    if (c->haveSaved)
957706f2543Smrg	    {
958706f2543Smrg		char	*tmpname;
959706f2543Smrg		int	tmpnamelen;
960706f2543Smrg		FontInfoPtr tmpFontInfo;
961706f2543Smrg
962706f2543Smrg	    	tmpname = 0;
963706f2543Smrg	    	tmpFontInfo = &fontInfo;
964706f2543Smrg	    	(void) (*fpe_functions[fpe->type].list_next_font_with_info)
965706f2543Smrg		    (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo,
966706f2543Smrg		     &numFonts, c->current.private);
967706f2543Smrg		if (--aliascount <= 0)
968706f2543Smrg		{
969706f2543Smrg		    err = BadFontName;
970706f2543Smrg		    goto ContBadFontName;
971706f2543Smrg		}
972706f2543Smrg	    }
973706f2543Smrg	    else
974706f2543Smrg	    {
975706f2543Smrg		c->saved = c->current;
976706f2543Smrg		c->haveSaved = TRUE;
977706f2543Smrg		c->savedNumFonts = numFonts;
978706f2543Smrg		free(c->savedName);
979706f2543Smrg		c->savedName = malloc(namelen + 1);
980706f2543Smrg		if (c->savedName)
981706f2543Smrg		  memmove(c->savedName, name, namelen + 1);
982706f2543Smrg		aliascount = 20;
983706f2543Smrg	    }
984706f2543Smrg	    memmove(c->current.pattern, name, namelen);
985706f2543Smrg	    c->current.patlen = namelen;
986706f2543Smrg	    c->current.max_names = 1;
987706f2543Smrg	    c->current.current_fpe = 0;
988706f2543Smrg	    c->current.private = 0;
989706f2543Smrg	    c->current.list_started = FALSE;
990706f2543Smrg	}
991706f2543Smrg	/*
992706f2543Smrg	 * At the end of this FPE, step to the next.  If we've finished
993706f2543Smrg	 * processing an alias, pop state back.  If we've sent enough font
994706f2543Smrg	 * names, quit.  Always wait for BadFontName to let the FPE
995706f2543Smrg	 * have a chance to clean up.
996706f2543Smrg	 */
997706f2543Smrg	else if (err == BadFontName)
998706f2543Smrg 	{
999706f2543Smrg	  ContBadFontName: ;
1000706f2543Smrg	    c->current.list_started = FALSE;
1001706f2543Smrg	    c->current.current_fpe++;
1002706f2543Smrg	    err = Successful;
1003706f2543Smrg	    if (c->haveSaved)
1004706f2543Smrg 	    {
1005706f2543Smrg		if (c->current.max_names == 0 ||
1006706f2543Smrg			c->current.current_fpe == c->num_fpes)
1007706f2543Smrg 		{
1008706f2543Smrg		    c->haveSaved = FALSE;
1009706f2543Smrg		    c->saved.max_names -= (1 - c->current.max_names);
1010706f2543Smrg		    c->current = c->saved;
1011706f2543Smrg		}
1012706f2543Smrg	    }
1013706f2543Smrg	    else if (c->current.max_names == 0)
1014706f2543Smrg		break;
1015706f2543Smrg	}
1016706f2543Smrg 	else if (err == Successful)
1017706f2543Smrg 	{
1018706f2543Smrg	    length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp);
1019706f2543Smrg	    reply = c->reply;
1020706f2543Smrg	    if (c->length < length)
1021706f2543Smrg 	    {
1022706f2543Smrg		reply = (xListFontsWithInfoReply *) realloc(c->reply, length);
1023706f2543Smrg		if (!reply)
1024706f2543Smrg 		{
1025706f2543Smrg		    err = AllocError;
1026706f2543Smrg		    break;
1027706f2543Smrg		}
1028706f2543Smrg		memset((char*)reply + c->length, 0, length - c->length);
1029706f2543Smrg		c->reply = reply;
1030706f2543Smrg		c->length = length;
1031706f2543Smrg	    }
1032706f2543Smrg	    if (c->haveSaved)
1033706f2543Smrg 	    {
1034706f2543Smrg		numFonts = c->savedNumFonts;
1035706f2543Smrg		name = c->savedName;
1036706f2543Smrg		namelen = strlen(name);
1037706f2543Smrg	    }
1038706f2543Smrg	    reply->type = X_Reply;
1039706f2543Smrg	    reply->length = bytes_to_int32(sizeof *reply - sizeof(xGenericReply) +
1040706f2543Smrg			     pFontInfo->nprops * sizeof(xFontProp) +
1041706f2543Smrg			     namelen);
1042706f2543Smrg	    reply->sequenceNumber = client->sequence;
1043706f2543Smrg	    reply->nameLength = namelen;
1044706f2543Smrg	    reply->minBounds = pFontInfo->ink_minbounds;
1045706f2543Smrg	    reply->maxBounds = pFontInfo->ink_maxbounds;
1046706f2543Smrg	    reply->minCharOrByte2 = pFontInfo->firstCol;
1047706f2543Smrg	    reply->maxCharOrByte2 = pFontInfo->lastCol;
1048706f2543Smrg	    reply->defaultChar = pFontInfo->defaultCh;
1049706f2543Smrg	    reply->nFontProps = pFontInfo->nprops;
1050706f2543Smrg	    reply->drawDirection = pFontInfo->drawDirection;
1051706f2543Smrg	    reply->minByte1 = pFontInfo->firstRow;
1052706f2543Smrg	    reply->maxByte1 = pFontInfo->lastRow;
1053706f2543Smrg	    reply->allCharsExist = pFontInfo->allExist;
1054706f2543Smrg	    reply->fontAscent = pFontInfo->fontAscent;
1055706f2543Smrg	    reply->fontDescent = pFontInfo->fontDescent;
1056706f2543Smrg	    reply->nReplies = numFonts;
1057706f2543Smrg	    pFP = (xFontProp *) (reply + 1);
1058706f2543Smrg	    for (i = 0; i < pFontInfo->nprops; i++)
1059706f2543Smrg 	    {
1060706f2543Smrg		pFP->name = pFontInfo->props[i].name;
1061706f2543Smrg		pFP->value = pFontInfo->props[i].value;
1062706f2543Smrg		pFP++;
1063706f2543Smrg	    }
1064706f2543Smrg	    WriteSwappedDataToClient(client, length, reply);
1065706f2543Smrg	    (void) WriteToClient(client, namelen, name);
1066706f2543Smrg	    if (pFontInfo == &fontInfo)
1067706f2543Smrg 	    {
1068706f2543Smrg		free(fontInfo.props);
1069706f2543Smrg		free(fontInfo.isStringProp);
1070706f2543Smrg	    }
1071706f2543Smrg	    --c->current.max_names;
1072706f2543Smrg	}
1073706f2543Smrg    }
1074706f2543Smrgfinish:
1075706f2543Smrg    length = sizeof(xListFontsWithInfoReply);
1076706f2543Smrg    memset((char *) &finalReply, 0, sizeof(xListFontsWithInfoReply));
1077706f2543Smrg    finalReply.type = X_Reply;
1078706f2543Smrg    finalReply.sequenceNumber = client->sequence;
1079706f2543Smrg    finalReply.length = bytes_to_int32(sizeof(xListFontsWithInfoReply)
1080706f2543Smrg		     - sizeof(xGenericReply));
1081706f2543Smrg    WriteSwappedDataToClient(client, length, &finalReply);
1082706f2543Smrgbail:
1083706f2543Smrg    ClientWakeup(client);
1084706f2543Smrgxinerama_sleep:
1085706f2543Smrg    for (i = 0; i < c->num_fpes; i++)
1086706f2543Smrg	FreeFPE(c->fpe_list[i]);
1087706f2543Smrg    free(c->reply);
1088706f2543Smrg    free(c->fpe_list);
1089706f2543Smrg    free(c->savedName);
1090706f2543Smrg    free(c);
1091706f2543Smrg    return TRUE;
1092706f2543Smrg}
1093706f2543Smrg
1094706f2543Smrgint
1095706f2543SmrgStartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern,
1096706f2543Smrg                       int max_names)
1097706f2543Smrg{
1098706f2543Smrg    int		    i;
1099706f2543Smrg    LFWIclosurePtr  c;
1100706f2543Smrg
1101706f2543Smrg    /*
1102706f2543Smrg     * The right error to return here would be BadName, however the
1103706f2543Smrg     * specification does not allow for a Name error on this request.
1104706f2543Smrg     * Perhaps a better solution would be to return a nil list, i.e.
1105706f2543Smrg     * a list containing zero fontnames.
1106706f2543Smrg     */
1107706f2543Smrg    if (length > XLFDMAXFONTNAMELEN)
1108706f2543Smrg	return BadAlloc;
1109706f2543Smrg
1110706f2543Smrg    i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
1111706f2543Smrg    if (i != Success)
1112706f2543Smrg	return i;
1113706f2543Smrg
1114706f2543Smrg    if (!(c = malloc(sizeof *c)))
1115706f2543Smrg	goto badAlloc;
1116706f2543Smrg    c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes);
1117706f2543Smrg    if (!c->fpe_list)
1118706f2543Smrg    {
1119706f2543Smrg	free(c);
1120706f2543Smrg	goto badAlloc;
1121706f2543Smrg    }
1122706f2543Smrg    memmove(c->current.pattern, pattern, length);
1123706f2543Smrg    for (i = 0; i < num_fpes; i++)
1124706f2543Smrg    {
1125706f2543Smrg	c->fpe_list[i] = font_path_elements[i];
1126706f2543Smrg	UseFPE(c->fpe_list[i]);
1127706f2543Smrg    }
1128706f2543Smrg    c->client = client;
1129706f2543Smrg    c->num_fpes = num_fpes;
1130706f2543Smrg    c->reply = 0;
1131706f2543Smrg    c->length = 0;
1132706f2543Smrg    c->current.patlen = length;
1133706f2543Smrg    c->current.current_fpe = 0;
1134706f2543Smrg    c->current.max_names = max_names;
1135706f2543Smrg    c->current.list_started = FALSE;
1136706f2543Smrg    c->current.private = 0;
1137706f2543Smrg    c->savedNumFonts = 0;
1138706f2543Smrg    c->haveSaved = FALSE;
1139706f2543Smrg    c->savedName = 0;
1140706f2543Smrg    doListFontsWithInfo(client, c);
1141706f2543Smrg    return Success;
1142706f2543SmrgbadAlloc:
1143706f2543Smrg    return BadAlloc;
1144706f2543Smrg}
1145706f2543Smrg
1146706f2543Smrg#define TextEltHeader 2
1147706f2543Smrg#define FontShiftSize 5
1148706f2543Smrgstatic ChangeGCVal clearGC[] = { { .ptr = NullPixmap } };
1149706f2543Smrg#define clearGCmask (GCClipMask)
1150706f2543Smrg
1151706f2543Smrgint
1152706f2543SmrgdoPolyText(ClientPtr client, PTclosurePtr c)
1153706f2543Smrg{
1154706f2543Smrg    FontPtr pFont = c->pGC->font, oldpFont;
1155706f2543Smrg    int err = Success, lgerr;	/* err is in X error, not font error, space */
1156706f2543Smrg    enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT;
1157706f2543Smrg    FontPathElementPtr fpe;
1158706f2543Smrg    GC *origGC = NULL;
1159706f2543Smrg    int itemSize = c->reqType == X_PolyText8 ? 1 : 2;
1160706f2543Smrg
1161706f2543Smrg    if (client->clientGone)
1162706f2543Smrg    {
1163706f2543Smrg	fpe = c->pGC->font->fpe;
1164706f2543Smrg	(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
1165706f2543Smrg
1166706f2543Smrg	if (ClientIsAsleep(client))
1167706f2543Smrg	{
1168706f2543Smrg	    /* Client has died, but we cannot bail out right now.  We
1169706f2543Smrg	       need to clean up after the work we did when going to
1170706f2543Smrg	       sleep.  Setting the drawable pointer to 0 makes this
1171706f2543Smrg	       happen without any attempts to render or perform other
1172706f2543Smrg	       unnecessary activities.  */
1173706f2543Smrg	    c->pDraw = (DrawablePtr)0;
1174706f2543Smrg	}
1175706f2543Smrg	else
1176706f2543Smrg	{
1177706f2543Smrg	    err = Success;
1178706f2543Smrg	    goto bail;
1179706f2543Smrg	}
1180706f2543Smrg    }
1181706f2543Smrg
1182706f2543Smrg    /* Make sure our drawable hasn't disappeared while we slept. */
1183706f2543Smrg    if (ClientIsAsleep(client) && c->pDraw)
1184706f2543Smrg    {
1185706f2543Smrg	DrawablePtr pDraw;
1186706f2543Smrg	dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess);
1187706f2543Smrg	if (c->pDraw != pDraw) {
1188706f2543Smrg	    /* Our drawable has disappeared.  Treat like client died... ask
1189706f2543Smrg	       the FPE code to clean up after client and avoid further
1190706f2543Smrg	       rendering while we clean up after ourself.  */
1191706f2543Smrg	    fpe = c->pGC->font->fpe;
1192706f2543Smrg	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
1193706f2543Smrg	    c->pDraw = (DrawablePtr)0;
1194706f2543Smrg	}
1195706f2543Smrg    }
1196706f2543Smrg
1197706f2543Smrg    client_state = ClientIsAsleep(client) ? SLEEPING : NEVER_SLEPT;
1198706f2543Smrg
1199706f2543Smrg    while (c->endReq - c->pElt > TextEltHeader)
1200706f2543Smrg    {
1201706f2543Smrg	if (*c->pElt == FontChange)
1202706f2543Smrg        {
1203706f2543Smrg	    Font fid;
1204706f2543Smrg	    if (c->endReq - c->pElt < FontShiftSize)
1205706f2543Smrg	    {
1206706f2543Smrg		 err = BadLength;
1207706f2543Smrg		 goto bail;
1208706f2543Smrg	    }
1209706f2543Smrg
1210706f2543Smrg	    oldpFont = pFont;
1211706f2543Smrg
1212706f2543Smrg	    fid =  ((Font)*(c->pElt+4))		/* big-endian */
1213706f2543Smrg		 | ((Font)*(c->pElt+3)) << 8
1214706f2543Smrg		 | ((Font)*(c->pElt+2)) << 16
1215706f2543Smrg		 | ((Font)*(c->pElt+1)) << 24;
1216706f2543Smrg	    err = dixLookupResourceByType((pointer *)&pFont, fid, RT_FONT,
1217706f2543Smrg					  client, DixUseAccess);
1218706f2543Smrg	    if (err != Success)
1219706f2543Smrg	    {
1220706f2543Smrg		/* restore pFont for step 4 (described below) */
1221706f2543Smrg		pFont = oldpFont;
1222706f2543Smrg
1223706f2543Smrg		/* If we're in START_SLEEP mode, the following step
1224706f2543Smrg		   shortens the request...  in the unlikely event that
1225706f2543Smrg		   the fid somehow becomes valid before we come through
1226706f2543Smrg		   again to actually execute the polytext, which would
1227706f2543Smrg		   then mess up our refcounting scheme badly.  */
1228706f2543Smrg		c->err = err;
1229706f2543Smrg		c->endReq = c->pElt;
1230706f2543Smrg
1231706f2543Smrg		goto bail;
1232706f2543Smrg	    }
1233706f2543Smrg
1234706f2543Smrg	    /* Step 3 (described below) on our new font */
1235706f2543Smrg	    if (client_state == START_SLEEP)
1236706f2543Smrg		pFont->refcnt++;
1237706f2543Smrg	    else
1238706f2543Smrg	    {
1239706f2543Smrg		if (pFont != c->pGC->font && c->pDraw)
1240706f2543Smrg		{
1241706f2543Smrg		    ChangeGCVal val;
1242706f2543Smrg		    val.ptr = pFont;
1243706f2543Smrg		    ChangeGC(NullClient, c->pGC, GCFont, &val);
1244706f2543Smrg		    ValidateGC(c->pDraw, c->pGC);
1245706f2543Smrg		}
1246706f2543Smrg
1247706f2543Smrg		/* Undo the refcnt++ we performed when going to sleep */
1248706f2543Smrg		if (client_state == SLEEPING)
1249706f2543Smrg		    (void)CloseFont(c->pGC->font, (Font)0);
1250706f2543Smrg	    }
1251706f2543Smrg	    c->pElt += FontShiftSize;
1252706f2543Smrg	}
1253706f2543Smrg	else	/* print a string */
1254706f2543Smrg	{
1255706f2543Smrg	    unsigned char *pNextElt;
1256706f2543Smrg	    pNextElt = c->pElt + TextEltHeader + (*c->pElt) * itemSize;
1257706f2543Smrg	    if ( pNextElt > c->endReq)
1258706f2543Smrg	    {
1259706f2543Smrg		err = BadLength;
1260706f2543Smrg		goto bail;
1261706f2543Smrg	    }
1262706f2543Smrg	    if (client_state == START_SLEEP)
1263706f2543Smrg	    {
1264706f2543Smrg		c->pElt = pNextElt;
1265706f2543Smrg		continue;
1266706f2543Smrg	    }
1267706f2543Smrg	    if (c->pDraw)
1268706f2543Smrg	    {
1269706f2543Smrg		lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, itemSize,
1270706f2543Smrg				   c->pElt + TextEltHeader);
1271706f2543Smrg	    }
1272706f2543Smrg	    else lgerr = Successful;
1273706f2543Smrg
1274706f2543Smrg	    if (lgerr == Suspended)
1275706f2543Smrg	    {
1276706f2543Smrg		if (!ClientIsAsleep(client)) {
1277706f2543Smrg		    int len;
1278706f2543Smrg		    GC *pGC;
1279706f2543Smrg		    PTclosurePtr new_closure;
1280706f2543Smrg
1281706f2543Smrg    /*  We're putting the client to sleep.  We need to do a few things
1282706f2543Smrg	to ensure successful and atomic-appearing execution of the
1283706f2543Smrg	remainder of the request.  First, copy the remainder of the
1284706f2543Smrg	request into a safe malloc'd area.  Second, create a scratch GC
1285706f2543Smrg	to use for the remainder of the request.  Third, mark all fonts
1286706f2543Smrg	referenced in the remainder of the request to prevent their
1287706f2543Smrg	deallocation.  Fourth, make the original GC look like the
1288706f2543Smrg	request has completed...  set its font to the final font value
1289706f2543Smrg	from this request.  These GC manipulations are for the unlikely
1290706f2543Smrg	(but possible) event that some other client is using the GC.
1291706f2543Smrg	Steps 3 and 4 are performed by running this procedure through
1292706f2543Smrg	the remainder of the request in a special no-render mode
1293706f2543Smrg	indicated by client_state = START_SLEEP.  */
1294706f2543Smrg
1295706f2543Smrg		    /* Step 1 */
1296706f2543Smrg		    /* Allocate a malloc'd closure structure to replace
1297706f2543Smrg		       the local one we were passed */
1298706f2543Smrg		    new_closure = malloc(sizeof(PTclosureRec));
1299706f2543Smrg		    if (!new_closure)
1300706f2543Smrg		    {
1301706f2543Smrg			err = BadAlloc;
1302706f2543Smrg			goto bail;
1303706f2543Smrg		    }
1304706f2543Smrg		    *new_closure = *c;
1305706f2543Smrg
1306706f2543Smrg		    len = new_closure->endReq - new_closure->pElt;
1307706f2543Smrg		    new_closure->data = malloc(len);
1308706f2543Smrg		    if (!new_closure->data)
1309706f2543Smrg		    {
1310706f2543Smrg			free(new_closure);
1311706f2543Smrg			err = BadAlloc;
1312706f2543Smrg			goto bail;
1313706f2543Smrg		    }
1314706f2543Smrg		    memmove(new_closure->data, new_closure->pElt, len);
1315706f2543Smrg		    new_closure->pElt = new_closure->data;
1316706f2543Smrg		    new_closure->endReq = new_closure->pElt + len;
1317706f2543Smrg
1318706f2543Smrg		    /* Step 2 */
1319706f2543Smrg
1320706f2543Smrg		    pGC = GetScratchGC(new_closure->pGC->depth, new_closure->pGC->pScreen);
1321706f2543Smrg		    if (!pGC)
1322706f2543Smrg		    {
1323706f2543Smrg			free(new_closure->data);
1324706f2543Smrg			free(new_closure);
1325706f2543Smrg			err = BadAlloc;
1326706f2543Smrg			goto bail;
1327706f2543Smrg		    }
1328706f2543Smrg		    if ((err = CopyGC(new_closure->pGC, pGC, GCFunction |
1329706f2543Smrg				      GCPlaneMask | GCForeground |
1330706f2543Smrg				      GCBackground | GCFillStyle |
1331706f2543Smrg				      GCTile | GCStipple |
1332706f2543Smrg				      GCTileStipXOrigin |
1333706f2543Smrg				      GCTileStipYOrigin | GCFont |
1334706f2543Smrg				      GCSubwindowMode | GCClipXOrigin |
1335706f2543Smrg				      GCClipYOrigin | GCClipMask)) !=
1336706f2543Smrg				      Success)
1337706f2543Smrg		    {
1338706f2543Smrg			FreeScratchGC(pGC);
1339706f2543Smrg			free(new_closure->data);
1340706f2543Smrg			free(new_closure);
1341706f2543Smrg			err = BadAlloc;
1342706f2543Smrg			goto bail;
1343706f2543Smrg		    }
1344706f2543Smrg		    c = new_closure;
1345706f2543Smrg		    origGC = c->pGC;
1346706f2543Smrg		    c->pGC = pGC;
1347706f2543Smrg		    ValidateGC(c->pDraw, c->pGC);
1348706f2543Smrg
1349706f2543Smrg		    ClientSleep(client, (ClientSleepProcPtr)doPolyText, c);
1350706f2543Smrg
1351706f2543Smrg		    /* Set up to perform steps 3 and 4 */
1352706f2543Smrg		    client_state = START_SLEEP;
1353706f2543Smrg		    continue;	/* on to steps 3 and 4 */
1354706f2543Smrg		}
1355706f2543Smrg		else
1356706f2543Smrg		    goto xinerama_sleep;
1357706f2543Smrg		return TRUE;
1358706f2543Smrg	    }
1359706f2543Smrg	    else if (lgerr != Successful)
1360706f2543Smrg	    {
1361706f2543Smrg		err = FontToXError(lgerr);
1362706f2543Smrg		goto bail;
1363706f2543Smrg	    }
1364706f2543Smrg	    if (c->pDraw)
1365706f2543Smrg	    {
1366706f2543Smrg		c->xorg += *((INT8 *)(c->pElt + 1));	/* must be signed */
1367706f2543Smrg		if (c->reqType == X_PolyText8)
1368706f2543Smrg		    c->xorg = (* c->pGC->ops->PolyText8)(c->pDraw, c->pGC, c->xorg, c->yorg,
1369706f2543Smrg			*c->pElt, (char *) (c->pElt + TextEltHeader));
1370706f2543Smrg		else
1371706f2543Smrg		    c->xorg = (* c->pGC->ops->PolyText16)(c->pDraw, c->pGC, c->xorg, c->yorg,
1372706f2543Smrg			*c->pElt, (unsigned short *) (c->pElt + TextEltHeader));
1373706f2543Smrg	    }
1374706f2543Smrg	    c->pElt = pNextElt;
1375706f2543Smrg	}
1376706f2543Smrg    }
1377706f2543Smrg
1378706f2543Smrgbail:
1379706f2543Smrg
1380706f2543Smrg    if (client_state == START_SLEEP)
1381706f2543Smrg    {
1382706f2543Smrg	/* Step 4 */
1383706f2543Smrg	if (pFont != origGC->font)
1384706f2543Smrg	{
1385706f2543Smrg	    ChangeGCVal val;
1386706f2543Smrg	    val.ptr = pFont;
1387706f2543Smrg	    ChangeGC(NullClient, origGC, GCFont, &val);
1388706f2543Smrg	    ValidateGC(c->pDraw, origGC);
1389706f2543Smrg	}
1390706f2543Smrg
1391706f2543Smrg	/* restore pElt pointer for execution of remainder of the request */
1392706f2543Smrg	c->pElt = c->data;
1393706f2543Smrg	return TRUE;
1394706f2543Smrg    }
1395706f2543Smrg
1396706f2543Smrg    if (c->err != Success) err = c->err;
1397706f2543Smrg    if (err != Success && c->client != serverClient) {
1398706f2543Smrg#ifdef PANORAMIX
1399706f2543Smrg        if (noPanoramiXExtension || !c->pGC->pScreen->myNum)
1400706f2543Smrg#endif
1401706f2543Smrg	    SendErrorToClient(c->client, c->reqType, 0, 0, err);
1402706f2543Smrg    }
1403706f2543Smrg    if (ClientIsAsleep(client))
1404706f2543Smrg    {
1405706f2543Smrg	ClientWakeup(c->client);
1406706f2543Smrgxinerama_sleep:
1407706f2543Smrg	ChangeGC(NullClient, c->pGC, clearGCmask, clearGC);
1408706f2543Smrg
1409706f2543Smrg	/* Unreference the font from the scratch GC */
1410706f2543Smrg	CloseFont(c->pGC->font, (Font)0);
1411706f2543Smrg	c->pGC->font = NullFont;
1412706f2543Smrg
1413706f2543Smrg	FreeScratchGC(c->pGC);
1414706f2543Smrg	free(c->data);
1415706f2543Smrg	free(c);
1416706f2543Smrg    }
1417706f2543Smrg    return TRUE;
1418706f2543Smrg}
1419706f2543Smrg
1420706f2543Smrgint
1421706f2543SmrgPolyText(ClientPtr client, DrawablePtr pDraw, GC *pGC, unsigned char *pElt,
1422706f2543Smrg         unsigned char *endReq, int xorg, int yorg, int reqType, XID did)
1423706f2543Smrg{
1424706f2543Smrg    PTclosureRec local_closure;
1425706f2543Smrg
1426706f2543Smrg    local_closure.pElt = pElt;
1427706f2543Smrg    local_closure.endReq = endReq;
1428706f2543Smrg    local_closure.client = client;
1429706f2543Smrg    local_closure.pDraw = pDraw;
1430706f2543Smrg    local_closure.xorg = xorg;
1431706f2543Smrg    local_closure.yorg = yorg;
1432706f2543Smrg    local_closure.reqType = reqType;
1433706f2543Smrg    local_closure.pGC = pGC;
1434706f2543Smrg    local_closure.did = did;
1435706f2543Smrg    local_closure.err = Success;
1436706f2543Smrg
1437706f2543Smrg    (void) doPolyText(client, &local_closure);
1438706f2543Smrg    return Success;
1439706f2543Smrg}
1440706f2543Smrg
1441706f2543Smrg
1442706f2543Smrg#undef TextEltHeader
1443706f2543Smrg#undef FontShiftSize
1444706f2543Smrg
1445706f2543Smrgint
1446706f2543SmrgdoImageText(ClientPtr client, ITclosurePtr c)
1447706f2543Smrg{
1448706f2543Smrg    int err = Success, lgerr;	/* err is in X error, not font error, space */
1449706f2543Smrg    FontPathElementPtr fpe;
1450706f2543Smrg    int itemSize = c->reqType == X_ImageText8 ? 1 : 2;
1451706f2543Smrg
1452706f2543Smrg    if (client->clientGone)
1453706f2543Smrg    {
1454706f2543Smrg	fpe = c->pGC->font->fpe;
1455706f2543Smrg	(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
1456706f2543Smrg	err = Success;
1457706f2543Smrg	goto bail;
1458706f2543Smrg    }
1459706f2543Smrg
1460706f2543Smrg    /* Make sure our drawable hasn't disappeared while we slept. */
1461706f2543Smrg    if (ClientIsAsleep(client) && c->pDraw)
1462706f2543Smrg    {
1463706f2543Smrg	DrawablePtr pDraw;
1464706f2543Smrg	dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess);
1465706f2543Smrg	if (c->pDraw != pDraw) {
1466706f2543Smrg	    /* Our drawable has disappeared.  Treat like client died... ask
1467706f2543Smrg	       the FPE code to clean up after client. */
1468706f2543Smrg	    fpe = c->pGC->font->fpe;
1469706f2543Smrg	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
1470706f2543Smrg	    err = Success;
1471706f2543Smrg	    goto bail;
1472706f2543Smrg	}
1473706f2543Smrg    }
1474706f2543Smrg
1475706f2543Smrg    lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, itemSize, c->data);
1476706f2543Smrg    if (lgerr == Suspended)
1477706f2543Smrg    {
1478706f2543Smrg        if (!ClientIsAsleep(client)) {
1479706f2543Smrg	    GC *pGC;
1480706f2543Smrg	    unsigned char *data;
1481706f2543Smrg	    ITclosurePtr new_closure;
1482706f2543Smrg            ITclosurePtr old_closure;
1483706f2543Smrg
1484706f2543Smrg	    /* We're putting the client to sleep.  We need to
1485706f2543Smrg	       save some state.  Similar problem to that handled
1486706f2543Smrg	       in doPolyText, but much simpler because the
1487706f2543Smrg	       request structure is much simpler. */
1488706f2543Smrg
1489706f2543Smrg	    new_closure = malloc(sizeof(ITclosureRec));
1490706f2543Smrg	    if (!new_closure)
1491706f2543Smrg	    {
1492706f2543Smrg		err = BadAlloc;
1493706f2543Smrg		goto bail;
1494706f2543Smrg	    }
1495706f2543Smrg            old_closure = c;
1496706f2543Smrg	    *new_closure = *c;
1497706f2543Smrg	    c = new_closure;
1498706f2543Smrg
1499706f2543Smrg	    data = malloc(c->nChars * itemSize);
1500706f2543Smrg	    if (!data)
1501706f2543Smrg	    {
1502706f2543Smrg		free(c);
1503706f2543Smrg                c = old_closure;
1504706f2543Smrg		err = BadAlloc;
1505706f2543Smrg		goto bail;
1506706f2543Smrg	    }
1507706f2543Smrg	    memmove(data, c->data, c->nChars * itemSize);
1508706f2543Smrg	    c->data = data;
1509706f2543Smrg
1510706f2543Smrg	    pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
1511706f2543Smrg	    if (!pGC)
1512706f2543Smrg	    {
1513706f2543Smrg		free(c->data);
1514706f2543Smrg		free(c);
1515706f2543Smrg                c = old_closure;
1516706f2543Smrg		err = BadAlloc;
1517706f2543Smrg		goto bail;
1518706f2543Smrg	    }
1519706f2543Smrg	    if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask |
1520706f2543Smrg			      GCForeground | GCBackground | GCFillStyle |
1521706f2543Smrg			      GCTile | GCStipple | GCTileStipXOrigin |
1522706f2543Smrg			      GCTileStipYOrigin | GCFont |
1523706f2543Smrg			      GCSubwindowMode | GCClipXOrigin |
1524706f2543Smrg			      GCClipYOrigin | GCClipMask)) != Success)
1525706f2543Smrg	    {
1526706f2543Smrg		FreeScratchGC(pGC);
1527706f2543Smrg		free(c->data);
1528706f2543Smrg		free(c);
1529706f2543Smrg                c = old_closure;
1530706f2543Smrg		err = BadAlloc;
1531706f2543Smrg		goto bail;
1532706f2543Smrg	    }
1533706f2543Smrg	    c->pGC = pGC;
1534706f2543Smrg	    ValidateGC(c->pDraw, c->pGC);
1535706f2543Smrg
1536706f2543Smrg            ClientSleep(client, (ClientSleepProcPtr)doImageText, c);
1537706f2543Smrg        }
1538706f2543Smrg	else
1539706f2543Smrg	    goto xinerama_sleep;
1540706f2543Smrg        return TRUE;
1541706f2543Smrg    }
1542706f2543Smrg    else if (lgerr != Successful)
1543706f2543Smrg    {
1544706f2543Smrg        err = FontToXError(lgerr);
1545706f2543Smrg        goto bail;
1546706f2543Smrg    }
1547706f2543Smrg    if (c->pDraw)
1548706f2543Smrg    {
1549706f2543Smrg	if (c->reqType == X_ImageText8)
1550706f2543Smrg	    (* c->pGC->ops->ImageText8)(c->pDraw, c->pGC, c->xorg, c->yorg,
1551706f2543Smrg		c->nChars, (char *) c->data);
1552706f2543Smrg	else
1553706f2543Smrg	    (* c->pGC->ops->ImageText16)(c->pDraw, c->pGC, c->xorg, c->yorg,
1554706f2543Smrg		c->nChars, (unsigned short *) c->data);
1555706f2543Smrg    }
1556706f2543Smrg
1557706f2543Smrgbail:
1558706f2543Smrg
1559706f2543Smrg    if (err != Success && c->client != serverClient) {
1560706f2543Smrg	SendErrorToClient(c->client, c->reqType, 0, 0, err);
1561706f2543Smrg    }
1562706f2543Smrg    if (ClientIsAsleep(client))
1563706f2543Smrg    {
1564706f2543Smrg	ClientWakeup(c->client);
1565706f2543Smrgxinerama_sleep:
1566706f2543Smrg	ChangeGC(NullClient, c->pGC, clearGCmask, clearGC);
1567706f2543Smrg
1568706f2543Smrg	/* Unreference the font from the scratch GC */
1569706f2543Smrg	CloseFont(c->pGC->font, (Font)0);
1570706f2543Smrg	c->pGC->font = NullFont;
1571706f2543Smrg
1572706f2543Smrg	FreeScratchGC(c->pGC);
1573706f2543Smrg	free(c->data);
1574706f2543Smrg	free(c);
1575706f2543Smrg    }
1576706f2543Smrg    return TRUE;
1577706f2543Smrg}
1578706f2543Smrg
1579706f2543Smrgint
1580706f2543SmrgImageText(ClientPtr client, DrawablePtr pDraw, GC *pGC, int nChars,
1581706f2543Smrg          unsigned char *data, int xorg, int yorg, int reqType, XID did)
1582706f2543Smrg{
1583706f2543Smrg    ITclosureRec local_closure;
1584706f2543Smrg
1585706f2543Smrg    local_closure.client = client;
1586706f2543Smrg    local_closure.pDraw = pDraw;
1587706f2543Smrg    local_closure.pGC = pGC;
1588706f2543Smrg    local_closure.nChars = nChars;
1589706f2543Smrg    local_closure.data = data;
1590706f2543Smrg    local_closure.xorg = xorg;
1591706f2543Smrg    local_closure.yorg = yorg;
1592706f2543Smrg    local_closure.reqType = reqType;
1593706f2543Smrg    local_closure.did = did;
1594706f2543Smrg
1595706f2543Smrg    (void) doImageText(client, &local_closure);
1596706f2543Smrg    return Success;
1597706f2543Smrg}
1598706f2543Smrg
1599706f2543Smrg
1600706f2543Smrg/* does the necessary magic to figure out the fpe type */
1601706f2543Smrgstatic int
1602706f2543SmrgDetermineFPEType(char *pathname)
1603706f2543Smrg{
1604706f2543Smrg    int         i;
1605706f2543Smrg
1606706f2543Smrg    for (i = 0; i < num_fpe_types; i++) {
1607706f2543Smrg	if ((*fpe_functions[i].name_check) (pathname))
1608706f2543Smrg	    return i;
1609706f2543Smrg    }
1610706f2543Smrg    return -1;
1611706f2543Smrg}
1612706f2543Smrg
1613706f2543Smrg
1614706f2543Smrgstatic void
1615706f2543SmrgFreeFontPath(FontPathElementPtr *list, int n, Bool force)
1616706f2543Smrg{
1617706f2543Smrg    int         i;
1618706f2543Smrg
1619706f2543Smrg    for (i = 0; i < n; i++) {
1620706f2543Smrg	if (force) {
1621706f2543Smrg	    /* Sanity check that all refcounts will be 0 by the time
1622706f2543Smrg	       we get to the end of the list. */
1623706f2543Smrg	    int found = 1;	/* the first reference is us */
1624706f2543Smrg	    int j;
1625706f2543Smrg	    for (j = i+1; j < n; j++) {
1626706f2543Smrg		if (list[j] == list[i])
1627706f2543Smrg		    found++;
1628706f2543Smrg	    }
1629706f2543Smrg	    if (list[i]->refcount != found) {
1630706f2543Smrg		list[i]->refcount = found; /* ensure it will get freed */
1631706f2543Smrg	    }
1632706f2543Smrg	}
1633706f2543Smrg	FreeFPE(list[i]);
1634706f2543Smrg    }
1635706f2543Smrg    free(list);
1636706f2543Smrg}
1637706f2543Smrg
1638706f2543Smrgstatic FontPathElementPtr
1639706f2543Smrgfind_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len)
1640706f2543Smrg{
1641706f2543Smrg    FontPathElementPtr fpe;
1642706f2543Smrg    int         i;
1643706f2543Smrg
1644706f2543Smrg    for (i = 0; i < num; i++) {
1645706f2543Smrg	fpe = list[i];
1646706f2543Smrg	if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0)
1647706f2543Smrg	    return fpe;
1648706f2543Smrg    }
1649706f2543Smrg    return (FontPathElementPtr) 0;
1650706f2543Smrg}
1651706f2543Smrg
1652706f2543Smrg
1653706f2543Smrgstatic int
1654706f2543SmrgSetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist)
1655706f2543Smrg{
1656706f2543Smrg    int         i, err = 0;
1657706f2543Smrg    int         valid_paths = 0;
1658706f2543Smrg    unsigned int len;
1659706f2543Smrg    unsigned char *cp = paths;
1660706f2543Smrg    FontPathElementPtr fpe = NULL, *fplist;
1661706f2543Smrg
1662706f2543Smrg    fplist = malloc(sizeof(FontPathElementPtr) * npaths);
1663706f2543Smrg    if (!fplist) {
1664706f2543Smrg	*bad = 0;
1665706f2543Smrg	return BadAlloc;
1666706f2543Smrg    }
1667706f2543Smrg    for (i = 0; i < num_fpe_types; i++) {
1668706f2543Smrg	if (fpe_functions[i].set_path_hook)
1669706f2543Smrg	    (*fpe_functions[i].set_path_hook) ();
1670706f2543Smrg    }
1671706f2543Smrg    for (i = 0; i < npaths; i++)
1672706f2543Smrg    {
1673706f2543Smrg	len = (unsigned int) (*cp++);
1674706f2543Smrg
1675706f2543Smrg	if (len == 0)
1676706f2543Smrg	{
1677706f2543Smrg	    if (persist)
1678706f2543Smrg		ErrorF("[dix] Removing empty element from the valid list of fontpaths\n");
1679706f2543Smrg	    err = BadValue;
1680706f2543Smrg	}
1681706f2543Smrg	else
1682706f2543Smrg	{
1683706f2543Smrg	    /* if it's already in our active list, just reset it */
1684706f2543Smrg	    /*
1685706f2543Smrg	     * note that this can miss FPE's in limbo -- may be worth catching
1686706f2543Smrg	     * them, though it'd muck up refcounting
1687706f2543Smrg	     */
1688706f2543Smrg	    fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len);
1689706f2543Smrg	    if (fpe)
1690706f2543Smrg	    {
1691706f2543Smrg		err = (*fpe_functions[fpe->type].reset_fpe) (fpe);
1692706f2543Smrg		if (err == Successful)
1693706f2543Smrg		{
1694706f2543Smrg		    UseFPE(fpe);/* since it'll be decref'd later when freed
1695706f2543Smrg				 * from the old list */
1696706f2543Smrg		}
1697706f2543Smrg		else
1698706f2543Smrg		    fpe = 0;
1699706f2543Smrg	    }
1700706f2543Smrg	    /* if error or can't do it, act like it's a new one */
1701706f2543Smrg	    if (!fpe)
1702706f2543Smrg	    {
1703706f2543Smrg		fpe = malloc(sizeof(FontPathElementRec));
1704706f2543Smrg		if (!fpe)
1705706f2543Smrg		{
1706706f2543Smrg		    err = BadAlloc;
1707706f2543Smrg		    goto bail;
1708706f2543Smrg		}
1709706f2543Smrg		fpe->name = malloc(len + 1);
1710706f2543Smrg		if (!fpe->name)
1711706f2543Smrg		{
1712706f2543Smrg		    free(fpe);
1713706f2543Smrg		    err = BadAlloc;
1714706f2543Smrg		    goto bail;
1715706f2543Smrg		}
1716706f2543Smrg		fpe->refcount = 1;
1717706f2543Smrg
1718706f2543Smrg		strncpy(fpe->name, (char *) cp, (int) len);
1719706f2543Smrg		fpe->name[len] = '\0';
1720706f2543Smrg		fpe->name_length = len;
1721706f2543Smrg		fpe->type = DetermineFPEType(fpe->name);
1722706f2543Smrg		if (fpe->type == -1)
1723706f2543Smrg		    err = BadValue;
1724706f2543Smrg		else
1725706f2543Smrg		    err = (*fpe_functions[fpe->type].init_fpe) (fpe);
1726706f2543Smrg		if (err != Successful)
1727706f2543Smrg		{
1728706f2543Smrg		    if (persist)
1729706f2543Smrg		    {
1730706f2543Smrg			ErrorF("[dix] Could not init font path element %s, removing from list!\n",
1731706f2543Smrg			       fpe->name);
1732706f2543Smrg		    }
1733706f2543Smrg		    free(fpe->name);
1734706f2543Smrg		    free(fpe);
1735706f2543Smrg		}
1736706f2543Smrg	    }
1737706f2543Smrg	}
1738706f2543Smrg	if (err != Successful)
1739706f2543Smrg	{
1740706f2543Smrg	    if (!persist)
1741706f2543Smrg		goto bail;
1742706f2543Smrg	}
1743706f2543Smrg	else
1744706f2543Smrg	{
1745706f2543Smrg	    fplist[valid_paths++] = fpe;
1746706f2543Smrg	}
1747706f2543Smrg	cp += len;
1748706f2543Smrg    }
1749706f2543Smrg
1750706f2543Smrg    FreeFontPath(font_path_elements, num_fpes, FALSE);
1751706f2543Smrg    font_path_elements = fplist;
1752706f2543Smrg    if (patternCache)
1753706f2543Smrg	EmptyFontPatternCache(patternCache);
1754706f2543Smrg    num_fpes = valid_paths;
1755706f2543Smrg
1756706f2543Smrg    return Success;
1757706f2543Smrgbail:
1758706f2543Smrg    *bad = i;
1759706f2543Smrg    while (--valid_paths >= 0)
1760706f2543Smrg	FreeFPE(fplist[valid_paths]);
1761706f2543Smrg    free(fplist);
1762706f2543Smrg    return FontToXError(err);
1763706f2543Smrg}
1764706f2543Smrg
1765706f2543Smrgint
1766706f2543SmrgSetFontPath(ClientPtr client, int npaths, unsigned char *paths)
1767706f2543Smrg{
1768706f2543Smrg    int err = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
1769706f2543Smrg    if (err != Success)
1770706f2543Smrg	return err;
1771706f2543Smrg
1772706f2543Smrg    if (npaths == 0) {
1773706f2543Smrg	if (SetDefaultFontPath(defaultFontPath) != Success)
1774706f2543Smrg	    return BadValue;
1775706f2543Smrg    } else {
1776706f2543Smrg	int bad;
1777706f2543Smrg	err = SetFontPathElements(npaths, paths, &bad, FALSE);
1778706f2543Smrg	client->errorValue = bad;
1779706f2543Smrg    }
1780706f2543Smrg    return err;
1781706f2543Smrg}
1782706f2543Smrg
1783706f2543Smrgint
1784706f2543SmrgSetDefaultFontPath(char *path)
1785706f2543Smrg{
1786706f2543Smrg    char       *temp_path,
1787706f2543Smrg               *start,
1788706f2543Smrg               *end;
1789706f2543Smrg    unsigned char *cp,
1790706f2543Smrg               *pp,
1791706f2543Smrg               *nump,
1792706f2543Smrg               *newpath;
1793706f2543Smrg    int         num = 1,
1794706f2543Smrg                len,
1795706f2543Smrg                err,
1796706f2543Smrg                size = 0,
1797706f2543Smrg                bad;
1798706f2543Smrg
1799706f2543Smrg    /* ensure temp_path contains "built-ins" */
1800706f2543Smrg    start = path;
1801706f2543Smrg    while (1) {
1802706f2543Smrg	start = strstr(start, "built-ins");
1803706f2543Smrg	if (start == NULL)
1804706f2543Smrg	    break;
1805706f2543Smrg	end = start + strlen("built-ins");
1806706f2543Smrg	if ((start == path || start[-1] == ',') && (!*end || *end == ','))
1807706f2543Smrg	    break;
1808706f2543Smrg	start = end;
1809706f2543Smrg    }
1810706f2543Smrg    if (!start) {
1811706f2543Smrg	if (asprintf(&temp_path, "%s%sbuilt-ins", path, *path ? "," : "")
1812706f2543Smrg	    == -1)
1813706f2543Smrg	    temp_path = NULL;
1814706f2543Smrg    } else {
1815706f2543Smrg	temp_path = strdup(path);
1816706f2543Smrg    }
1817706f2543Smrg    if (!temp_path)
1818706f2543Smrg        return BadAlloc;
1819706f2543Smrg
1820706f2543Smrg    /* get enough for string, plus values -- use up commas */
1821706f2543Smrg    len = strlen(temp_path) + 1;
1822706f2543Smrg    nump = cp = newpath = malloc(len);
1823706f2543Smrg    if (!newpath) {
1824706f2543Smrg	free(temp_path);
1825706f2543Smrg	return BadAlloc;
1826706f2543Smrg    }
1827706f2543Smrg    pp = (unsigned char *) temp_path;
1828706f2543Smrg    cp++;
1829706f2543Smrg    while (*pp) {
1830706f2543Smrg	if (*pp == ',') {
1831706f2543Smrg	    *nump = (unsigned char) size;
1832706f2543Smrg	    nump = cp++;
1833706f2543Smrg	    pp++;
1834706f2543Smrg	    num++;
1835706f2543Smrg	    size = 0;
1836706f2543Smrg	} else {
1837706f2543Smrg	    *cp++ = *pp++;
1838706f2543Smrg	    size++;
1839706f2543Smrg	}
1840706f2543Smrg    }
1841706f2543Smrg    *nump = (unsigned char) size;
1842706f2543Smrg
1843706f2543Smrg    err = SetFontPathElements(num, newpath, &bad, TRUE);
1844706f2543Smrg
1845706f2543Smrg    free(newpath);
1846706f2543Smrg    free(temp_path);
1847706f2543Smrg
1848706f2543Smrg    return err;
1849706f2543Smrg}
1850706f2543Smrg
1851706f2543Smrgint
1852706f2543SmrgGetFontPath(ClientPtr client, int *count, int *length, unsigned char **result)
1853706f2543Smrg{
1854706f2543Smrg    int			i;
1855706f2543Smrg    unsigned char       *c;
1856706f2543Smrg    int			len;
1857706f2543Smrg    FontPathElementPtr	fpe;
1858706f2543Smrg
1859706f2543Smrg    i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
1860706f2543Smrg    if (i != Success)
1861706f2543Smrg	return i;
1862706f2543Smrg
1863706f2543Smrg    len = 0;
1864706f2543Smrg    for (i = 0; i < num_fpes; i++) {
1865706f2543Smrg	fpe = font_path_elements[i];
1866706f2543Smrg	len += fpe->name_length + 1;
1867706f2543Smrg    }
1868706f2543Smrg    font_path_string = (unsigned char *) realloc(font_path_string, len);
1869706f2543Smrg    if (!font_path_string)
1870706f2543Smrg	return BadAlloc;
1871706f2543Smrg
1872706f2543Smrg    c = font_path_string;
1873706f2543Smrg    *length = 0;
1874706f2543Smrg    for (i = 0; i < num_fpes; i++) {
1875706f2543Smrg	fpe = font_path_elements[i];
1876706f2543Smrg	*c = fpe->name_length;
1877706f2543Smrg	*length += *c++;
1878706f2543Smrg	memmove(c, fpe->name, fpe->name_length);
1879706f2543Smrg	c += fpe->name_length;
1880706f2543Smrg    }
1881706f2543Smrg    *count = num_fpes;
1882706f2543Smrg    *result = font_path_string;
1883706f2543Smrg    return Success;
1884706f2543Smrg}
1885706f2543Smrg
1886706f2543Smrgvoid
1887706f2543SmrgDeleteClientFontStuff(ClientPtr client)
1888706f2543Smrg{
1889706f2543Smrg    int			i;
1890706f2543Smrg    FontPathElementPtr	fpe;
1891706f2543Smrg
1892706f2543Smrg    for (i = 0; i < num_fpes; i++)
1893706f2543Smrg    {
1894706f2543Smrg	fpe = font_path_elements[i];
1895706f2543Smrg	if (fpe_functions[fpe->type].client_died)
1896706f2543Smrg	    (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
1897706f2543Smrg    }
1898706f2543Smrg}
1899706f2543Smrg
1900706f2543Smrgvoid
1901706f2543SmrgInitFonts (void)
1902706f2543Smrg{
1903706f2543Smrg    patternCache = MakeFontPatternCache();
1904706f2543Smrg
1905706f2543Smrg    register_fpe_functions();
1906706f2543Smrg}
1907706f2543Smrg
1908706f2543Smrgint
1909706f2543SmrgGetDefaultPointSize (void)
1910706f2543Smrg{
1911706f2543Smrg    return 120;
1912706f2543Smrg}
1913706f2543Smrg
1914706f2543Smrg
1915706f2543SmrgFontResolutionPtr
1916706f2543SmrgGetClientResolutions (int *num)
1917706f2543Smrg{
1918706f2543Smrg    static struct _FontResolution res;
1919706f2543Smrg    ScreenPtr   pScreen;
1920706f2543Smrg
1921706f2543Smrg    pScreen = screenInfo.screens[0];
1922706f2543Smrg    res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth;
1923706f2543Smrg    /*
1924706f2543Smrg     * XXX - we'll want this as long as bitmap instances are prevalent
1925706f2543Smrg     so that we can match them from scalable fonts
1926706f2543Smrg     */
1927706f2543Smrg    if (res.x_resolution < 88)
1928706f2543Smrg	res.x_resolution = 75;
1929706f2543Smrg    else
1930706f2543Smrg	res.x_resolution = 100;
1931706f2543Smrg    res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight;
1932706f2543Smrg    if (res.y_resolution < 88)
1933706f2543Smrg	res.y_resolution = 75;
1934706f2543Smrg    else
1935706f2543Smrg	res.y_resolution = 100;
1936706f2543Smrg    res.point_size = 120;
1937706f2543Smrg    *num = 1;
1938706f2543Smrg    return &res;
1939706f2543Smrg}
1940706f2543Smrg
1941706f2543Smrg/*
1942706f2543Smrg * returns the type index of the new fpe
1943706f2543Smrg *
1944706f2543Smrg * should be called (only once!) by each type of fpe when initialized
1945706f2543Smrg */
1946706f2543Smrg
1947706f2543Smrgint
1948706f2543SmrgRegisterFPEFunctions(NameCheckFunc name_func,
1949706f2543Smrg		     InitFpeFunc init_func,
1950706f2543Smrg		     FreeFpeFunc free_func,
1951706f2543Smrg		     ResetFpeFunc reset_func,
1952706f2543Smrg		     OpenFontFunc open_func,
1953706f2543Smrg		     CloseFontFunc close_func,
1954706f2543Smrg		     ListFontsFunc list_func,
1955706f2543Smrg		     StartLfwiFunc start_lfwi_func,
1956706f2543Smrg		     NextLfwiFunc next_lfwi_func,
1957706f2543Smrg		     WakeupFpeFunc wakeup_func,
1958706f2543Smrg		     ClientDiedFunc client_died,
1959706f2543Smrg		     LoadGlyphsFunc load_glyphs,
1960706f2543Smrg		     StartLaFunc start_list_alias_func,
1961706f2543Smrg		     NextLaFunc next_list_alias_func,
1962706f2543Smrg		     SetPathFunc set_path_func)
1963706f2543Smrg{
1964706f2543Smrg    FPEFunctions *new;
1965706f2543Smrg
1966706f2543Smrg    /* grow the list */
1967706f2543Smrg    new = (FPEFunctions *) realloc(fpe_functions,
1968706f2543Smrg				 (num_fpe_types + 1) * sizeof(FPEFunctions));
1969706f2543Smrg    if (!new)
1970706f2543Smrg	return -1;
1971706f2543Smrg    fpe_functions = new;
1972706f2543Smrg
1973706f2543Smrg    fpe_functions[num_fpe_types].name_check = name_func;
1974706f2543Smrg    fpe_functions[num_fpe_types].open_font = open_func;
1975706f2543Smrg    fpe_functions[num_fpe_types].close_font = close_func;
1976706f2543Smrg    fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func;
1977706f2543Smrg    fpe_functions[num_fpe_types].list_fonts = list_func;
1978706f2543Smrg    fpe_functions[num_fpe_types].start_list_fonts_with_info =
1979706f2543Smrg	start_lfwi_func;
1980706f2543Smrg    fpe_functions[num_fpe_types].list_next_font_with_info =
1981706f2543Smrg	next_lfwi_func;
1982706f2543Smrg    fpe_functions[num_fpe_types].init_fpe = init_func;
1983706f2543Smrg    fpe_functions[num_fpe_types].free_fpe = free_func;
1984706f2543Smrg    fpe_functions[num_fpe_types].reset_fpe = reset_func;
1985706f2543Smrg    fpe_functions[num_fpe_types].client_died = client_died;
1986706f2543Smrg    fpe_functions[num_fpe_types].load_glyphs = load_glyphs;
1987706f2543Smrg    fpe_functions[num_fpe_types].start_list_fonts_and_aliases =
1988706f2543Smrg	start_list_alias_func;
1989706f2543Smrg    fpe_functions[num_fpe_types].list_next_font_or_alias =
1990706f2543Smrg	next_list_alias_func;
1991706f2543Smrg    fpe_functions[num_fpe_types].set_path_hook = set_path_func;
1992706f2543Smrg
1993706f2543Smrg    return num_fpe_types++;
1994706f2543Smrg}
1995706f2543Smrg
1996706f2543Smrgvoid
1997706f2543SmrgFreeFonts(void)
1998706f2543Smrg{
1999706f2543Smrg    if (patternCache) {
2000706f2543Smrg	FreeFontPatternCache(patternCache);
2001706f2543Smrg	patternCache = 0;
2002706f2543Smrg    }
2003706f2543Smrg    FreeFontPath(font_path_elements, num_fpes, TRUE);
2004706f2543Smrg    font_path_elements = 0;
2005706f2543Smrg    num_fpes = 0;
2006706f2543Smrg    free(fpe_functions);
2007706f2543Smrg    num_fpe_types = 0;
2008706f2543Smrg    fpe_functions = (FPEFunctions *) 0;
2009706f2543Smrg}
2010706f2543Smrg
2011706f2543Smrg/* convenience functions for FS interface */
2012706f2543Smrg
2013706f2543SmrgFontPtr
2014706f2543Smrgfind_old_font(XID id)
2015706f2543Smrg{
2016706f2543Smrg    pointer pFont;
2017706f2543Smrg    dixLookupResourceByType(&pFont, id, RT_NONE, serverClient, DixReadAccess);
2018706f2543Smrg    return (FontPtr)pFont;
2019706f2543Smrg}
2020706f2543Smrg
2021706f2543SmrgFont
2022706f2543SmrgGetNewFontClientID(void)
2023706f2543Smrg{
2024706f2543Smrg    return FakeClientID(0);
2025706f2543Smrg}
2026706f2543Smrg
2027706f2543Smrgint
2028706f2543SmrgStoreFontClientFont(FontPtr pfont, Font id)
2029706f2543Smrg{
2030706f2543Smrg    return AddResource(id, RT_NONE, (pointer) pfont);
2031706f2543Smrg}
2032706f2543Smrg
2033706f2543Smrgvoid
2034706f2543SmrgDeleteFontClientID(Font id)
2035706f2543Smrg{
2036706f2543Smrg    FreeResource(id, RT_NONE);
2037706f2543Smrg}
2038706f2543Smrg
2039706f2543Smrgint
2040706f2543Smrgclient_auth_generation(ClientPtr client)
2041706f2543Smrg{
2042706f2543Smrg    return 0;
2043706f2543Smrg}
2044706f2543Smrg
2045706f2543Smrgstatic int  fs_handlers_installed = 0;
2046706f2543Smrgstatic unsigned int last_server_gen;
2047706f2543Smrg
2048706f2543Smrgint
2049706f2543Smrginit_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler)
2050706f2543Smrg{
2051706f2543Smrg    /* if server has reset, make sure the b&w handlers are reinstalled */
2052706f2543Smrg    if (last_server_gen < serverGeneration) {
2053706f2543Smrg	last_server_gen = serverGeneration;
2054706f2543Smrg	fs_handlers_installed = 0;
2055706f2543Smrg    }
2056706f2543Smrg    if (fs_handlers_installed == 0) {
2057706f2543Smrg	if (!RegisterBlockAndWakeupHandlers(block_handler,
2058706f2543Smrg					    FontWakeup, (pointer) 0))
2059706f2543Smrg	    return AllocError;
2060706f2543Smrg	fs_handlers_installed++;
2061706f2543Smrg    }
2062706f2543Smrg    QueueFontWakeup(fpe);
2063706f2543Smrg    return Successful;
2064706f2543Smrg}
2065706f2543Smrg
2066706f2543Smrgvoid
2067706f2543Smrgremove_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler, Bool all)
2068706f2543Smrg{
2069706f2543Smrg    if (all) {
2070706f2543Smrg	/* remove the handlers if no one else is using them */
2071706f2543Smrg	if (--fs_handlers_installed == 0) {
2072706f2543Smrg	    RemoveBlockAndWakeupHandlers(block_handler, FontWakeup,
2073706f2543Smrg					 (pointer) 0);
2074706f2543Smrg	}
2075706f2543Smrg    }
2076706f2543Smrg    RemoveFontWakeup(fpe);
2077706f2543Smrg}
2078