xref: /OK3568_Linux_fs/external/xserver/dix/dixfonts.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /************************************************************************
2*4882a593Smuzhiyun Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun                         All Rights Reserved
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun Permission to use, copy, modify, and distribute this software and its
7*4882a593Smuzhiyun documentation for any purpose and without fee is hereby granted,
8*4882a593Smuzhiyun provided that the above copyright notice appear in all copies and that
9*4882a593Smuzhiyun both that copyright notice and this permission notice appear in
10*4882a593Smuzhiyun supporting documentation, and that the name of Digital not be
11*4882a593Smuzhiyun used in advertising or publicity pertaining to distribution of the
12*4882a593Smuzhiyun software without specific, written prior permission.
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15*4882a593Smuzhiyun ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16*4882a593Smuzhiyun DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17*4882a593Smuzhiyun ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18*4882a593Smuzhiyun WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19*4882a593Smuzhiyun ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20*4882a593Smuzhiyun SOFTWARE.
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun ************************************************************************/
23*4882a593Smuzhiyun /* The panoramix components contained the following notice */
24*4882a593Smuzhiyun /*
25*4882a593Smuzhiyun Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun Permission is hereby granted, free of charge, to any person obtaining a copy
28*4882a593Smuzhiyun of this software and associated documentation files (the "Software"), to deal
29*4882a593Smuzhiyun in the Software without restriction, including without limitation the rights
30*4882a593Smuzhiyun to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
31*4882a593Smuzhiyun copies of the Software.
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun The above copyright notice and this permission notice shall be included in
34*4882a593Smuzhiyun all copies or substantial portions of the Software.
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
37*4882a593Smuzhiyun IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
38*4882a593Smuzhiyun FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
39*4882a593Smuzhiyun DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
40*4882a593Smuzhiyun BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
41*4882a593Smuzhiyun WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
42*4882a593Smuzhiyun IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun Except as contained in this notice, the name of Digital Equipment Corporation
45*4882a593Smuzhiyun shall not be used in advertising or otherwise to promote the sale, use or other
46*4882a593Smuzhiyun dealings in this Software without prior written authorization from Digital
47*4882a593Smuzhiyun Equipment Corporation.
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun ******************************************************************/
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
52*4882a593Smuzhiyun #include <dix-config.h>
53*4882a593Smuzhiyun #endif
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun #include <X11/X.h>
56*4882a593Smuzhiyun #include <X11/Xmd.h>
57*4882a593Smuzhiyun #include <X11/Xproto.h>
58*4882a593Smuzhiyun #include "scrnintstr.h"
59*4882a593Smuzhiyun #include "resource.h"
60*4882a593Smuzhiyun #include "dixstruct.h"
61*4882a593Smuzhiyun #include "cursorstr.h"
62*4882a593Smuzhiyun #include "misc.h"
63*4882a593Smuzhiyun #include "opaque.h"
64*4882a593Smuzhiyun #include "dixfontstr.h"
65*4882a593Smuzhiyun #include "closestr.h"
66*4882a593Smuzhiyun #include "dixfont.h"
67*4882a593Smuzhiyun #include "xace.h"
68*4882a593Smuzhiyun #include <X11/fonts/libxfont2.h>
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun #ifdef XF86BIGFONT
71*4882a593Smuzhiyun #include "xf86bigfontsrv.h"
72*4882a593Smuzhiyun #endif
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun extern void *fosNaturalParams;
75*4882a593Smuzhiyun extern FontPtr defaultFont;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0;
78*4882a593Smuzhiyun static int num_fpes = 0;
79*4882a593Smuzhiyun static xfont2_fpe_funcs_rec const **fpe_functions;
80*4882a593Smuzhiyun static int num_fpe_types = 0;
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun static unsigned char *font_path_string;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun static int num_slept_fpes = 0;
85*4882a593Smuzhiyun static int size_slept_fpes = 0;
86*4882a593Smuzhiyun static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0;
87*4882a593Smuzhiyun static xfont2_pattern_cache_ptr patternCache;
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun static int
FontToXError(int err)90*4882a593Smuzhiyun FontToXError(int err)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun     switch (err) {
93*4882a593Smuzhiyun     case Successful:
94*4882a593Smuzhiyun         return Success;
95*4882a593Smuzhiyun     case AllocError:
96*4882a593Smuzhiyun         return BadAlloc;
97*4882a593Smuzhiyun     case BadFontName:
98*4882a593Smuzhiyun         return BadName;
99*4882a593Smuzhiyun     case BadFontPath:
100*4882a593Smuzhiyun     case BadFontFormat:        /* is there something better? */
101*4882a593Smuzhiyun     case BadCharRange:
102*4882a593Smuzhiyun         return BadValue;
103*4882a593Smuzhiyun     default:
104*4882a593Smuzhiyun         return err;
105*4882a593Smuzhiyun     }
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun static int
LoadGlyphs(ClientPtr client,FontPtr pfont,unsigned nchars,int item_size,unsigned char * data)109*4882a593Smuzhiyun LoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size,
110*4882a593Smuzhiyun            unsigned char *data)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun     if (fpe_functions[pfont->fpe->type]->load_glyphs)
113*4882a593Smuzhiyun         return (*fpe_functions[pfont->fpe->type]->load_glyphs)
114*4882a593Smuzhiyun             (client, pfont, 0, nchars, item_size, data);
115*4882a593Smuzhiyun     else
116*4882a593Smuzhiyun         return Successful;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun void
GetGlyphs(FontPtr font,unsigned long count,unsigned char * chars,FontEncoding fontEncoding,unsigned long * glyphcount,CharInfoPtr * glyphs)120*4882a593Smuzhiyun GetGlyphs(FontPtr font, unsigned long count, unsigned char *chars,
121*4882a593Smuzhiyun           FontEncoding fontEncoding,
122*4882a593Smuzhiyun           unsigned long *glyphcount,    /* RETURN */
123*4882a593Smuzhiyun           CharInfoPtr *glyphs)          /* RETURN */
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun     (*font->get_glyphs) (font, count, chars, fontEncoding, glyphcount, glyphs);
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun /*
129*4882a593Smuzhiyun  * adding RT_FONT prevents conflict with default cursor font
130*4882a593Smuzhiyun  */
131*4882a593Smuzhiyun Bool
SetDefaultFont(const char * defaultfontname)132*4882a593Smuzhiyun SetDefaultFont(const char *defaultfontname)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun     int err;
135*4882a593Smuzhiyun     FontPtr pf;
136*4882a593Smuzhiyun     XID fid;
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun     fid = FakeClientID(0);
139*4882a593Smuzhiyun     err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync,
140*4882a593Smuzhiyun                    (unsigned) strlen(defaultfontname), defaultfontname);
141*4882a593Smuzhiyun     if (err != Success)
142*4882a593Smuzhiyun         return FALSE;
143*4882a593Smuzhiyun     err = dixLookupResourceByType((void **) &pf, fid, RT_FONT, serverClient,
144*4882a593Smuzhiyun                                   DixReadAccess);
145*4882a593Smuzhiyun     if (err != Success)
146*4882a593Smuzhiyun         return FALSE;
147*4882a593Smuzhiyun     defaultFont = pf;
148*4882a593Smuzhiyun     return TRUE;
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun /*
152*4882a593Smuzhiyun  * note that the font wakeup queue is not refcounted.  this is because
153*4882a593Smuzhiyun  * an fpe needs to be added when it's inited, and removed when it's finally
154*4882a593Smuzhiyun  * freed, in order to handle any data that isn't requested, like FS events.
155*4882a593Smuzhiyun  *
156*4882a593Smuzhiyun  * since the only thing that should call these routines is the renderer's
157*4882a593Smuzhiyun  * init_fpe() and free_fpe(), there shouldn't be any problem in using
158*4882a593Smuzhiyun  * freed data.
159*4882a593Smuzhiyun  */
160*4882a593Smuzhiyun static void
QueueFontWakeup(FontPathElementPtr fpe)161*4882a593Smuzhiyun QueueFontWakeup(FontPathElementPtr fpe)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun     int i;
164*4882a593Smuzhiyun     FontPathElementPtr *new;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun     for (i = 0; i < num_slept_fpes; i++) {
167*4882a593Smuzhiyun         if (slept_fpes[i] == fpe) {
168*4882a593Smuzhiyun             return;
169*4882a593Smuzhiyun         }
170*4882a593Smuzhiyun     }
171*4882a593Smuzhiyun     if (num_slept_fpes == size_slept_fpes) {
172*4882a593Smuzhiyun         new = reallocarray(slept_fpes, size_slept_fpes + 4,
173*4882a593Smuzhiyun                            sizeof(FontPathElementPtr));
174*4882a593Smuzhiyun         if (!new)
175*4882a593Smuzhiyun             return;
176*4882a593Smuzhiyun         slept_fpes = new;
177*4882a593Smuzhiyun         size_slept_fpes += 4;
178*4882a593Smuzhiyun     }
179*4882a593Smuzhiyun     slept_fpes[num_slept_fpes] = fpe;
180*4882a593Smuzhiyun     num_slept_fpes++;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun static void
RemoveFontWakeup(FontPathElementPtr fpe)184*4882a593Smuzhiyun RemoveFontWakeup(FontPathElementPtr fpe)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun     int i, j;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun     for (i = 0; i < num_slept_fpes; i++) {
189*4882a593Smuzhiyun         if (slept_fpes[i] == fpe) {
190*4882a593Smuzhiyun             for (j = i; j < num_slept_fpes; j++) {
191*4882a593Smuzhiyun                 slept_fpes[j] = slept_fpes[j + 1];
192*4882a593Smuzhiyun             }
193*4882a593Smuzhiyun             num_slept_fpes--;
194*4882a593Smuzhiyun             return;
195*4882a593Smuzhiyun         }
196*4882a593Smuzhiyun     }
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun static void
FontWakeup(void * data,int count)200*4882a593Smuzhiyun FontWakeup(void *data, int count)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun     int i;
203*4882a593Smuzhiyun     FontPathElementPtr fpe;
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun     if (count < 0)
206*4882a593Smuzhiyun         return;
207*4882a593Smuzhiyun     /* wake up any fpe's that may be waiting for information */
208*4882a593Smuzhiyun     for (i = 0; i < num_slept_fpes; i++) {
209*4882a593Smuzhiyun         fpe = slept_fpes[i];
210*4882a593Smuzhiyun         (void) (*fpe_functions[fpe->type]->wakeup_fpe) (fpe);
211*4882a593Smuzhiyun     }
212*4882a593Smuzhiyun }
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun /* XXX -- these two funcs may want to be broken into macros */
215*4882a593Smuzhiyun static void
UseFPE(FontPathElementPtr fpe)216*4882a593Smuzhiyun UseFPE(FontPathElementPtr fpe)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun     fpe->refcount++;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun static void
FreeFPE(FontPathElementPtr fpe)222*4882a593Smuzhiyun FreeFPE(FontPathElementPtr fpe)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun     fpe->refcount--;
225*4882a593Smuzhiyun     if (fpe->refcount == 0) {
226*4882a593Smuzhiyun         (*fpe_functions[fpe->type]->free_fpe) (fpe);
227*4882a593Smuzhiyun         free((void *) fpe->name);
228*4882a593Smuzhiyun         free(fpe);
229*4882a593Smuzhiyun     }
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun static Bool
doOpenFont(ClientPtr client,OFclosurePtr c)233*4882a593Smuzhiyun doOpenFont(ClientPtr client, OFclosurePtr c)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun     FontPtr pfont = NullFont;
236*4882a593Smuzhiyun     FontPathElementPtr fpe = NULL;
237*4882a593Smuzhiyun     ScreenPtr pScr;
238*4882a593Smuzhiyun     int err = Successful;
239*4882a593Smuzhiyun     int i;
240*4882a593Smuzhiyun     char *alias, *newname;
241*4882a593Smuzhiyun     int newlen;
242*4882a593Smuzhiyun     int aliascount = 20;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun     /*
245*4882a593Smuzhiyun      * Decide at runtime what FontFormat to use.
246*4882a593Smuzhiyun      */
247*4882a593Smuzhiyun     Mask FontFormat =
248*4882a593Smuzhiyun         ((screenInfo.imageByteOrder == LSBFirst) ?
249*4882a593Smuzhiyun          BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) |
250*4882a593Smuzhiyun         ((screenInfo.bitmapBitOrder == LSBFirst) ?
251*4882a593Smuzhiyun          BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) |
252*4882a593Smuzhiyun         BitmapFormatImageRectMin |
253*4882a593Smuzhiyun #if GLYPHPADBYTES == 1
254*4882a593Smuzhiyun         BitmapFormatScanlinePad8 |
255*4882a593Smuzhiyun #endif
256*4882a593Smuzhiyun #if GLYPHPADBYTES == 2
257*4882a593Smuzhiyun         BitmapFormatScanlinePad16 |
258*4882a593Smuzhiyun #endif
259*4882a593Smuzhiyun #if GLYPHPADBYTES == 4
260*4882a593Smuzhiyun         BitmapFormatScanlinePad32 |
261*4882a593Smuzhiyun #endif
262*4882a593Smuzhiyun #if GLYPHPADBYTES == 8
263*4882a593Smuzhiyun         BitmapFormatScanlinePad64 |
264*4882a593Smuzhiyun #endif
265*4882a593Smuzhiyun         BitmapFormatScanlineUnit8;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun     if (client->clientGone) {
268*4882a593Smuzhiyun         if (c->current_fpe < c->num_fpes) {
269*4882a593Smuzhiyun             fpe = c->fpe_list[c->current_fpe];
270*4882a593Smuzhiyun             (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe);
271*4882a593Smuzhiyun         }
272*4882a593Smuzhiyun         err = Successful;
273*4882a593Smuzhiyun         goto bail;
274*4882a593Smuzhiyun     }
275*4882a593Smuzhiyun     while (c->current_fpe < c->num_fpes) {
276*4882a593Smuzhiyun         fpe = c->fpe_list[c->current_fpe];
277*4882a593Smuzhiyun         err = (*fpe_functions[fpe->type]->open_font)
278*4882a593Smuzhiyun             ((void *) client, fpe, c->flags,
279*4882a593Smuzhiyun              c->fontname, c->fnamelen, FontFormat,
280*4882a593Smuzhiyun              BitmapFormatMaskByte |
281*4882a593Smuzhiyun              BitmapFormatMaskBit |
282*4882a593Smuzhiyun              BitmapFormatMaskImageRectangle |
283*4882a593Smuzhiyun              BitmapFormatMaskScanLinePad |
284*4882a593Smuzhiyun              BitmapFormatMaskScanLineUnit,
285*4882a593Smuzhiyun              c->fontid, &pfont, &alias,
286*4882a593Smuzhiyun              c->non_cachable_font && c->non_cachable_font->fpe == fpe ?
287*4882a593Smuzhiyun              c->non_cachable_font : (FontPtr) 0);
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun         if (err == FontNameAlias && alias) {
290*4882a593Smuzhiyun             newlen = strlen(alias);
291*4882a593Smuzhiyun             newname = (char *) realloc((char *) c->fontname, newlen);
292*4882a593Smuzhiyun             if (!newname) {
293*4882a593Smuzhiyun                 err = AllocError;
294*4882a593Smuzhiyun                 break;
295*4882a593Smuzhiyun             }
296*4882a593Smuzhiyun             memmove(newname, alias, newlen);
297*4882a593Smuzhiyun             c->fontname = newname;
298*4882a593Smuzhiyun             c->fnamelen = newlen;
299*4882a593Smuzhiyun             c->current_fpe = 0;
300*4882a593Smuzhiyun             if (--aliascount <= 0) {
301*4882a593Smuzhiyun                 /* We've tried resolving this alias 20 times, we're
302*4882a593Smuzhiyun                  * probably stuck in an infinite loop of aliases pointing
303*4882a593Smuzhiyun                  * to each other - time to take emergency exit!
304*4882a593Smuzhiyun                  */
305*4882a593Smuzhiyun                 err = BadImplementation;
306*4882a593Smuzhiyun                 break;
307*4882a593Smuzhiyun             }
308*4882a593Smuzhiyun             continue;
309*4882a593Smuzhiyun         }
310*4882a593Smuzhiyun         if (err == BadFontName) {
311*4882a593Smuzhiyun             c->current_fpe++;
312*4882a593Smuzhiyun             continue;
313*4882a593Smuzhiyun         }
314*4882a593Smuzhiyun         if (err == Suspended) {
315*4882a593Smuzhiyun             if (!ClientIsAsleep(client))
316*4882a593Smuzhiyun                 ClientSleep(client, (ClientSleepProcPtr) doOpenFont, c);
317*4882a593Smuzhiyun             return TRUE;
318*4882a593Smuzhiyun         }
319*4882a593Smuzhiyun         break;
320*4882a593Smuzhiyun     }
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun     if (err != Successful)
323*4882a593Smuzhiyun         goto bail;
324*4882a593Smuzhiyun     if (!pfont) {
325*4882a593Smuzhiyun         err = BadFontName;
326*4882a593Smuzhiyun         goto bail;
327*4882a593Smuzhiyun     }
328*4882a593Smuzhiyun     /* check values for firstCol, lastCol, firstRow, and lastRow */
329*4882a593Smuzhiyun     if (pfont->info.firstCol > pfont->info.lastCol ||
330*4882a593Smuzhiyun         pfont->info.firstRow > pfont->info.lastRow ||
331*4882a593Smuzhiyun         pfont->info.lastCol - pfont->info.firstCol > 255) {
332*4882a593Smuzhiyun         err = AllocError;
333*4882a593Smuzhiyun         goto bail;
334*4882a593Smuzhiyun     }
335*4882a593Smuzhiyun     if (!pfont->fpe)
336*4882a593Smuzhiyun         pfont->fpe = fpe;
337*4882a593Smuzhiyun     pfont->refcnt++;
338*4882a593Smuzhiyun     if (pfont->refcnt == 1) {
339*4882a593Smuzhiyun         UseFPE(pfont->fpe);
340*4882a593Smuzhiyun         for (i = 0; i < screenInfo.numScreens; i++) {
341*4882a593Smuzhiyun             pScr = screenInfo.screens[i];
342*4882a593Smuzhiyun             if (pScr->RealizeFont) {
343*4882a593Smuzhiyun                 if (!(*pScr->RealizeFont) (pScr, pfont)) {
344*4882a593Smuzhiyun                     CloseFont(pfont, (Font) 0);
345*4882a593Smuzhiyun                     err = AllocError;
346*4882a593Smuzhiyun                     goto bail;
347*4882a593Smuzhiyun                 }
348*4882a593Smuzhiyun             }
349*4882a593Smuzhiyun         }
350*4882a593Smuzhiyun     }
351*4882a593Smuzhiyun     if (!AddResource(c->fontid, RT_FONT, (void *) pfont)) {
352*4882a593Smuzhiyun         err = AllocError;
353*4882a593Smuzhiyun         goto bail;
354*4882a593Smuzhiyun     }
355*4882a593Smuzhiyun     if (patternCache && pfont != c->non_cachable_font)
356*4882a593Smuzhiyun         xfont2_cache_font_pattern(patternCache, c->origFontName, c->origFontNameLen,
357*4882a593Smuzhiyun                                   pfont);
358*4882a593Smuzhiyun  bail:
359*4882a593Smuzhiyun     if (err != Successful && c->client != serverClient) {
360*4882a593Smuzhiyun         SendErrorToClient(c->client, X_OpenFont, 0,
361*4882a593Smuzhiyun                           c->fontid, FontToXError(err));
362*4882a593Smuzhiyun     }
363*4882a593Smuzhiyun     ClientWakeup(c->client);
364*4882a593Smuzhiyun     for (i = 0; i < c->num_fpes; i++) {
365*4882a593Smuzhiyun         FreeFPE(c->fpe_list[i]);
366*4882a593Smuzhiyun     }
367*4882a593Smuzhiyun     free(c->fpe_list);
368*4882a593Smuzhiyun     free((void *) c->fontname);
369*4882a593Smuzhiyun     free(c);
370*4882a593Smuzhiyun     return TRUE;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun int
OpenFont(ClientPtr client,XID fid,Mask flags,unsigned lenfname,const char * pfontname)374*4882a593Smuzhiyun OpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname,
375*4882a593Smuzhiyun          const char *pfontname)
376*4882a593Smuzhiyun {
377*4882a593Smuzhiyun     OFclosurePtr c;
378*4882a593Smuzhiyun     int i;
379*4882a593Smuzhiyun     FontPtr cached = (FontPtr) 0;
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun     if (!lenfname || lenfname > XLFDMAXFONTNAMELEN)
382*4882a593Smuzhiyun         return BadName;
383*4882a593Smuzhiyun     if (patternCache) {
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun         /*
386*4882a593Smuzhiyun          ** Check name cache.  If we find a cached version of this font that
387*4882a593Smuzhiyun          ** is cachable, immediately satisfy the request with it.  If we find
388*4882a593Smuzhiyun          ** a cached version of this font that is non-cachable, we do not
389*4882a593Smuzhiyun          ** satisfy the request with it.  Instead, we pass the FontPtr to the
390*4882a593Smuzhiyun          ** FPE's open_font code (the fontfile FPE in turn passes the
391*4882a593Smuzhiyun          ** information to the rasterizer; the fserve FPE ignores it).
392*4882a593Smuzhiyun          **
393*4882a593Smuzhiyun          ** Presumably, the font is marked non-cachable because the FPE has
394*4882a593Smuzhiyun          ** put some licensing restrictions on it.  If the FPE, using
395*4882a593Smuzhiyun          ** whatever logic it relies on, determines that it is willing to
396*4882a593Smuzhiyun          ** share this existing font with the client, then it has the option
397*4882a593Smuzhiyun          ** to return the FontPtr we passed it as the newly-opened font.
398*4882a593Smuzhiyun          ** This allows the FPE to exercise its licensing logic without
399*4882a593Smuzhiyun          ** having to create another instance of a font that already exists.
400*4882a593Smuzhiyun          */
401*4882a593Smuzhiyun 
402*4882a593Smuzhiyun         cached = xfont2_find_cached_font_pattern(patternCache, pfontname, lenfname);
403*4882a593Smuzhiyun         if (cached && cached->info.cachable) {
404*4882a593Smuzhiyun             if (!AddResource(fid, RT_FONT, (void *) cached))
405*4882a593Smuzhiyun                 return BadAlloc;
406*4882a593Smuzhiyun             cached->refcnt++;
407*4882a593Smuzhiyun             return Success;
408*4882a593Smuzhiyun         }
409*4882a593Smuzhiyun     }
410*4882a593Smuzhiyun     c = malloc(sizeof(OFclosureRec));
411*4882a593Smuzhiyun     if (!c)
412*4882a593Smuzhiyun         return BadAlloc;
413*4882a593Smuzhiyun     c->fontname = malloc(lenfname);
414*4882a593Smuzhiyun     c->origFontName = pfontname;
415*4882a593Smuzhiyun     c->origFontNameLen = lenfname;
416*4882a593Smuzhiyun     if (!c->fontname) {
417*4882a593Smuzhiyun         free(c);
418*4882a593Smuzhiyun         return BadAlloc;
419*4882a593Smuzhiyun     }
420*4882a593Smuzhiyun     /*
421*4882a593Smuzhiyun      * copy the current FPE list, so that if it gets changed by another client
422*4882a593Smuzhiyun      * while we're blocking, the request still appears atomic
423*4882a593Smuzhiyun      */
424*4882a593Smuzhiyun     c->fpe_list = xallocarray(num_fpes, sizeof(FontPathElementPtr));
425*4882a593Smuzhiyun     if (!c->fpe_list) {
426*4882a593Smuzhiyun         free((void *) c->fontname);
427*4882a593Smuzhiyun         free(c);
428*4882a593Smuzhiyun         return BadAlloc;
429*4882a593Smuzhiyun     }
430*4882a593Smuzhiyun     memmove(c->fontname, pfontname, lenfname);
431*4882a593Smuzhiyun     for (i = 0; i < num_fpes; i++) {
432*4882a593Smuzhiyun         c->fpe_list[i] = font_path_elements[i];
433*4882a593Smuzhiyun         UseFPE(c->fpe_list[i]);
434*4882a593Smuzhiyun     }
435*4882a593Smuzhiyun     c->client = client;
436*4882a593Smuzhiyun     c->fontid = fid;
437*4882a593Smuzhiyun     c->current_fpe = 0;
438*4882a593Smuzhiyun     c->num_fpes = num_fpes;
439*4882a593Smuzhiyun     c->fnamelen = lenfname;
440*4882a593Smuzhiyun     c->flags = flags;
441*4882a593Smuzhiyun     c->non_cachable_font = cached;
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun     (void) doOpenFont(client, c);
444*4882a593Smuzhiyun     return Success;
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun 
447*4882a593Smuzhiyun /**
448*4882a593Smuzhiyun  * Decrement font's ref count, and free storage if ref count equals zero
449*4882a593Smuzhiyun  *
450*4882a593Smuzhiyun  *  \param value must conform to DeleteType
451*4882a593Smuzhiyun  */
452*4882a593Smuzhiyun int
CloseFont(void * value,XID fid)453*4882a593Smuzhiyun CloseFont(void *value, XID fid)
454*4882a593Smuzhiyun {
455*4882a593Smuzhiyun     int nscr;
456*4882a593Smuzhiyun     ScreenPtr pscr;
457*4882a593Smuzhiyun     FontPathElementPtr fpe;
458*4882a593Smuzhiyun     FontPtr pfont = (FontPtr) value;
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun     if (pfont == NullFont)
461*4882a593Smuzhiyun         return Success;
462*4882a593Smuzhiyun     if (--pfont->refcnt == 0) {
463*4882a593Smuzhiyun         if (patternCache)
464*4882a593Smuzhiyun             xfont2_remove_cached_font_pattern(patternCache, pfont);
465*4882a593Smuzhiyun         /*
466*4882a593Smuzhiyun          * since the last reference is gone, ask each screen to free any
467*4882a593Smuzhiyun          * storage it may have allocated locally for it.
468*4882a593Smuzhiyun          */
469*4882a593Smuzhiyun         for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
470*4882a593Smuzhiyun             pscr = screenInfo.screens[nscr];
471*4882a593Smuzhiyun             if (pscr->UnrealizeFont)
472*4882a593Smuzhiyun                 (*pscr->UnrealizeFont) (pscr, pfont);
473*4882a593Smuzhiyun         }
474*4882a593Smuzhiyun         if (pfont == defaultFont)
475*4882a593Smuzhiyun             defaultFont = NULL;
476*4882a593Smuzhiyun #ifdef XF86BIGFONT
477*4882a593Smuzhiyun         XF86BigfontFreeFontShm(pfont);
478*4882a593Smuzhiyun #endif
479*4882a593Smuzhiyun         fpe = pfont->fpe;
480*4882a593Smuzhiyun         (*fpe_functions[fpe->type]->close_font) (fpe, pfont);
481*4882a593Smuzhiyun         FreeFPE(fpe);
482*4882a593Smuzhiyun     }
483*4882a593Smuzhiyun     return Success;
484*4882a593Smuzhiyun }
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun /***====================================================================***/
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun /**
489*4882a593Smuzhiyun  * Sets up pReply as the correct QueryFontReply for pFont with the first
490*4882a593Smuzhiyun  * nProtoCCIStructs char infos.
491*4882a593Smuzhiyun  *
492*4882a593Smuzhiyun  *  \param pReply caller must allocate this storage
493*4882a593Smuzhiyun   */
494*4882a593Smuzhiyun void
QueryFont(FontPtr pFont,xQueryFontReply * pReply,int nProtoCCIStructs)495*4882a593Smuzhiyun QueryFont(FontPtr pFont, xQueryFontReply * pReply, int nProtoCCIStructs)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun     FontPropPtr pFP;
498*4882a593Smuzhiyun     int r, c, i;
499*4882a593Smuzhiyun     xFontProp *prFP;
500*4882a593Smuzhiyun     xCharInfo *prCI;
501*4882a593Smuzhiyun     xCharInfo *charInfos[256];
502*4882a593Smuzhiyun     unsigned char chars[512];
503*4882a593Smuzhiyun     int ninfos;
504*4882a593Smuzhiyun     unsigned long ncols;
505*4882a593Smuzhiyun     unsigned long count;
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun     /* pr->length set in dispatch */
508*4882a593Smuzhiyun     pReply->minCharOrByte2 = pFont->info.firstCol;
509*4882a593Smuzhiyun     pReply->defaultChar = pFont->info.defaultCh;
510*4882a593Smuzhiyun     pReply->maxCharOrByte2 = pFont->info.lastCol;
511*4882a593Smuzhiyun     pReply->drawDirection = pFont->info.drawDirection;
512*4882a593Smuzhiyun     pReply->allCharsExist = pFont->info.allExist;
513*4882a593Smuzhiyun     pReply->minByte1 = pFont->info.firstRow;
514*4882a593Smuzhiyun     pReply->maxByte1 = pFont->info.lastRow;
515*4882a593Smuzhiyun     pReply->fontAscent = pFont->info.fontAscent;
516*4882a593Smuzhiyun     pReply->fontDescent = pFont->info.fontDescent;
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun     pReply->minBounds = pFont->info.ink_minbounds;
519*4882a593Smuzhiyun     pReply->maxBounds = pFont->info.ink_maxbounds;
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun     pReply->nFontProps = pFont->info.nprops;
522*4882a593Smuzhiyun     pReply->nCharInfos = nProtoCCIStructs;
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun     for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]);
525*4882a593Smuzhiyun          i < pFont->info.nprops; i++, pFP++, prFP++) {
526*4882a593Smuzhiyun         prFP->name = pFP->name;
527*4882a593Smuzhiyun         prFP->value = pFP->value;
528*4882a593Smuzhiyun     }
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun     ninfos = 0;
531*4882a593Smuzhiyun     ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1);
532*4882a593Smuzhiyun     prCI = (xCharInfo *) (prFP);
533*4882a593Smuzhiyun     for (r = pFont->info.firstRow;
534*4882a593Smuzhiyun          ninfos < nProtoCCIStructs && r <= (int) pFont->info.lastRow; r++) {
535*4882a593Smuzhiyun         i = 0;
536*4882a593Smuzhiyun         for (c = pFont->info.firstCol; c <= (int) pFont->info.lastCol; c++) {
537*4882a593Smuzhiyun             chars[i++] = r;
538*4882a593Smuzhiyun             chars[i++] = c;
539*4882a593Smuzhiyun         }
540*4882a593Smuzhiyun         (*pFont->get_metrics) (pFont, ncols, chars,
541*4882a593Smuzhiyun                                TwoD16Bit, &count, charInfos);
542*4882a593Smuzhiyun         i = 0;
543*4882a593Smuzhiyun         for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) {
544*4882a593Smuzhiyun             *prCI = *charInfos[i];
545*4882a593Smuzhiyun             prCI++;
546*4882a593Smuzhiyun             ninfos++;
547*4882a593Smuzhiyun         }
548*4882a593Smuzhiyun     }
549*4882a593Smuzhiyun     return;
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun static Bool
doListFontsAndAliases(ClientPtr client,LFclosurePtr c)553*4882a593Smuzhiyun doListFontsAndAliases(ClientPtr client, LFclosurePtr c)
554*4882a593Smuzhiyun {
555*4882a593Smuzhiyun     FontPathElementPtr fpe;
556*4882a593Smuzhiyun     int err = Successful;
557*4882a593Smuzhiyun     FontNamesPtr names = NULL;
558*4882a593Smuzhiyun     char *name, *resolved = NULL;
559*4882a593Smuzhiyun     int namelen, resolvedlen;
560*4882a593Smuzhiyun     int nnames;
561*4882a593Smuzhiyun     int stringLens;
562*4882a593Smuzhiyun     int i;
563*4882a593Smuzhiyun     xListFontsReply reply;
564*4882a593Smuzhiyun     char *bufptr;
565*4882a593Smuzhiyun     char *bufferStart;
566*4882a593Smuzhiyun     int aliascount = 0;
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun     if (client->clientGone) {
569*4882a593Smuzhiyun         if (c->current.current_fpe < c->num_fpes) {
570*4882a593Smuzhiyun             fpe = c->fpe_list[c->current.current_fpe];
571*4882a593Smuzhiyun             (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe);
572*4882a593Smuzhiyun         }
573*4882a593Smuzhiyun         err = Successful;
574*4882a593Smuzhiyun         goto bail;
575*4882a593Smuzhiyun     }
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun     if (!c->current.patlen)
578*4882a593Smuzhiyun         goto finish;
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun     while (c->current.current_fpe < c->num_fpes) {
581*4882a593Smuzhiyun         fpe = c->fpe_list[c->current.current_fpe];
582*4882a593Smuzhiyun         err = Successful;
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun         if (!fpe_functions[fpe->type]->start_list_fonts_and_aliases) {
585*4882a593Smuzhiyun             /* This FPE doesn't support/require list_fonts_and_aliases */
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun             err = (*fpe_functions[fpe->type]->list_fonts)
588*4882a593Smuzhiyun                 ((void *) c->client, fpe, c->current.pattern,
589*4882a593Smuzhiyun                  c->current.patlen, c->current.max_names - c->names->nnames,
590*4882a593Smuzhiyun                  c->names);
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun             if (err == Suspended) {
593*4882a593Smuzhiyun                 if (!ClientIsAsleep(client))
594*4882a593Smuzhiyun                     ClientSleep(client,
595*4882a593Smuzhiyun                                 (ClientSleepProcPtr) doListFontsAndAliases, c);
596*4882a593Smuzhiyun                 return TRUE;
597*4882a593Smuzhiyun             }
598*4882a593Smuzhiyun 
599*4882a593Smuzhiyun             err = BadFontName;
600*4882a593Smuzhiyun         }
601*4882a593Smuzhiyun         else {
602*4882a593Smuzhiyun             /* Start of list_fonts_and_aliases functionality.  Modeled
603*4882a593Smuzhiyun                after list_fonts_with_info in that it resolves aliases,
604*4882a593Smuzhiyun                except that the information collected from FPEs is just
605*4882a593Smuzhiyun                names, not font info.  Each list_next_font_or_alias()
606*4882a593Smuzhiyun                returns either a name into name/namelen or an alias into
607*4882a593Smuzhiyun                name/namelen and its target name into resolved/resolvedlen.
608*4882a593Smuzhiyun                The code at this level then resolves the alias by polling
609*4882a593Smuzhiyun                the FPEs.  */
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun             if (!c->current.list_started) {
612*4882a593Smuzhiyun                 err = (*fpe_functions[fpe->type]->start_list_fonts_and_aliases)
613*4882a593Smuzhiyun                     ((void *) c->client, fpe, c->current.pattern,
614*4882a593Smuzhiyun                      c->current.patlen, c->current.max_names - c->names->nnames,
615*4882a593Smuzhiyun                      &c->current.private);
616*4882a593Smuzhiyun                 if (err == Suspended) {
617*4882a593Smuzhiyun                     if (!ClientIsAsleep(client))
618*4882a593Smuzhiyun                         ClientSleep(client,
619*4882a593Smuzhiyun                                     (ClientSleepProcPtr) doListFontsAndAliases,
620*4882a593Smuzhiyun                                     c);
621*4882a593Smuzhiyun                     return TRUE;
622*4882a593Smuzhiyun                 }
623*4882a593Smuzhiyun                 if (err == Successful)
624*4882a593Smuzhiyun                     c->current.list_started = TRUE;
625*4882a593Smuzhiyun             }
626*4882a593Smuzhiyun             if (err == Successful) {
627*4882a593Smuzhiyun                 char *tmpname;
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun                 name = 0;
630*4882a593Smuzhiyun                 err = (*fpe_functions[fpe->type]->list_next_font_or_alias)
631*4882a593Smuzhiyun                     ((void *) c->client, fpe, &name, &namelen, &tmpname,
632*4882a593Smuzhiyun                      &resolvedlen, c->current.private);
633*4882a593Smuzhiyun                 if (err == Suspended) {
634*4882a593Smuzhiyun                     if (!ClientIsAsleep(client))
635*4882a593Smuzhiyun                         ClientSleep(client,
636*4882a593Smuzhiyun                                     (ClientSleepProcPtr) doListFontsAndAliases,
637*4882a593Smuzhiyun                                     c);
638*4882a593Smuzhiyun                     return TRUE;
639*4882a593Smuzhiyun                 }
640*4882a593Smuzhiyun                 if (err == FontNameAlias) {
641*4882a593Smuzhiyun                     free(resolved);
642*4882a593Smuzhiyun                     resolved = malloc(resolvedlen + 1);
643*4882a593Smuzhiyun                     if (resolved)
644*4882a593Smuzhiyun                         memmove(resolved, tmpname, resolvedlen + 1);
645*4882a593Smuzhiyun                 }
646*4882a593Smuzhiyun             }
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun             if (err == Successful) {
649*4882a593Smuzhiyun                 if (c->haveSaved) {
650*4882a593Smuzhiyun                     if (c->savedName)
651*4882a593Smuzhiyun                         (void) xfont2_add_font_names_name(c->names, c->savedName,
652*4882a593Smuzhiyun                                                 c->savedNameLen);
653*4882a593Smuzhiyun                 }
654*4882a593Smuzhiyun                 else
655*4882a593Smuzhiyun                     (void) xfont2_add_font_names_name(c->names, name, namelen);
656*4882a593Smuzhiyun             }
657*4882a593Smuzhiyun 
658*4882a593Smuzhiyun             /*
659*4882a593Smuzhiyun              * When we get an alias back, save our state and reset back to
660*4882a593Smuzhiyun              * the start of the FPE looking for the specified name.  As
661*4882a593Smuzhiyun              * soon as a real font is found for the alias, pop back to the
662*4882a593Smuzhiyun              * old state
663*4882a593Smuzhiyun              */
664*4882a593Smuzhiyun             else if (err == FontNameAlias) {
665*4882a593Smuzhiyun                 char tmp_pattern[XLFDMAXFONTNAMELEN];
666*4882a593Smuzhiyun 
667*4882a593Smuzhiyun                 /*
668*4882a593Smuzhiyun                  * when an alias recurses, we need to give
669*4882a593Smuzhiyun                  * the last FPE a chance to clean up; so we call
670*4882a593Smuzhiyun                  * it again, and assume that the error returned
671*4882a593Smuzhiyun                  * is BadFontName, indicating the alias resolution
672*4882a593Smuzhiyun                  * is complete.
673*4882a593Smuzhiyun                  */
674*4882a593Smuzhiyun                 memmove(tmp_pattern, resolved, resolvedlen);
675*4882a593Smuzhiyun                 if (c->haveSaved) {
676*4882a593Smuzhiyun                     char *tmpname;
677*4882a593Smuzhiyun                     int tmpnamelen;
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun                     tmpname = 0;
680*4882a593Smuzhiyun                     (void) (*fpe_functions[fpe->type]->list_next_font_or_alias)
681*4882a593Smuzhiyun                         ((void *) c->client, fpe, &tmpname, &tmpnamelen,
682*4882a593Smuzhiyun                          &tmpname, &tmpnamelen, c->current.private);
683*4882a593Smuzhiyun                     if (--aliascount <= 0) {
684*4882a593Smuzhiyun                         err = BadFontName;
685*4882a593Smuzhiyun                         goto ContBadFontName;
686*4882a593Smuzhiyun                     }
687*4882a593Smuzhiyun                 }
688*4882a593Smuzhiyun                 else {
689*4882a593Smuzhiyun                     c->saved = c->current;
690*4882a593Smuzhiyun                     c->haveSaved = TRUE;
691*4882a593Smuzhiyun                     free(c->savedName);
692*4882a593Smuzhiyun                     c->savedName = malloc(namelen + 1);
693*4882a593Smuzhiyun                     if (c->savedName)
694*4882a593Smuzhiyun                         memmove(c->savedName, name, namelen + 1);
695*4882a593Smuzhiyun                     c->savedNameLen = namelen;
696*4882a593Smuzhiyun                     aliascount = 20;
697*4882a593Smuzhiyun                 }
698*4882a593Smuzhiyun                 memmove(c->current.pattern, tmp_pattern, resolvedlen);
699*4882a593Smuzhiyun                 c->current.patlen = resolvedlen;
700*4882a593Smuzhiyun                 c->current.max_names = c->names->nnames + 1;
701*4882a593Smuzhiyun                 c->current.current_fpe = -1;
702*4882a593Smuzhiyun                 c->current.private = 0;
703*4882a593Smuzhiyun                 err = BadFontName;
704*4882a593Smuzhiyun             }
705*4882a593Smuzhiyun         }
706*4882a593Smuzhiyun         /*
707*4882a593Smuzhiyun          * At the end of this FPE, step to the next.  If we've finished
708*4882a593Smuzhiyun          * processing an alias, pop state back. If we've collected enough
709*4882a593Smuzhiyun          * font names, quit.
710*4882a593Smuzhiyun          */
711*4882a593Smuzhiyun         if (err == BadFontName) {
712*4882a593Smuzhiyun  ContBadFontName:;
713*4882a593Smuzhiyun             c->current.list_started = FALSE;
714*4882a593Smuzhiyun             c->current.current_fpe++;
715*4882a593Smuzhiyun             err = Successful;
716*4882a593Smuzhiyun             if (c->haveSaved) {
717*4882a593Smuzhiyun                 if (c->names->nnames == c->current.max_names ||
718*4882a593Smuzhiyun                     c->current.current_fpe == c->num_fpes) {
719*4882a593Smuzhiyun                     c->haveSaved = FALSE;
720*4882a593Smuzhiyun                     c->current = c->saved;
721*4882a593Smuzhiyun                     /* Give the saved namelist a chance to clean itself up */
722*4882a593Smuzhiyun                     continue;
723*4882a593Smuzhiyun                 }
724*4882a593Smuzhiyun             }
725*4882a593Smuzhiyun             if (c->names->nnames == c->current.max_names)
726*4882a593Smuzhiyun                 break;
727*4882a593Smuzhiyun         }
728*4882a593Smuzhiyun     }
729*4882a593Smuzhiyun 
730*4882a593Smuzhiyun     /*
731*4882a593Smuzhiyun      * send the reply
732*4882a593Smuzhiyun      */
733*4882a593Smuzhiyun     if (err != Successful) {
734*4882a593Smuzhiyun         SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err));
735*4882a593Smuzhiyun         goto bail;
736*4882a593Smuzhiyun     }
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun  finish:
739*4882a593Smuzhiyun 
740*4882a593Smuzhiyun     names = c->names;
741*4882a593Smuzhiyun     nnames = names->nnames;
742*4882a593Smuzhiyun     client = c->client;
743*4882a593Smuzhiyun     stringLens = 0;
744*4882a593Smuzhiyun     for (i = 0; i < nnames; i++)
745*4882a593Smuzhiyun         stringLens += (names->length[i] <= 255) ? names->length[i] : 0;
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun     reply = (xListFontsReply) {
748*4882a593Smuzhiyun         .type = X_Reply,
749*4882a593Smuzhiyun         .length = bytes_to_int32(stringLens + nnames),
750*4882a593Smuzhiyun         .nFonts = nnames,
751*4882a593Smuzhiyun         .sequenceNumber = client->sequence
752*4882a593Smuzhiyun     };
753*4882a593Smuzhiyun 
754*4882a593Smuzhiyun     bufptr = bufferStart = malloc(reply.length << 2);
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun     if (!bufptr && reply.length) {
757*4882a593Smuzhiyun         SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc);
758*4882a593Smuzhiyun         goto bail;
759*4882a593Smuzhiyun     }
760*4882a593Smuzhiyun     /*
761*4882a593Smuzhiyun      * since WriteToClient long word aligns things, copy to temp buffer and
762*4882a593Smuzhiyun      * write all at once
763*4882a593Smuzhiyun      */
764*4882a593Smuzhiyun     for (i = 0; i < nnames; i++) {
765*4882a593Smuzhiyun         if (names->length[i] > 255)
766*4882a593Smuzhiyun             reply.nFonts--;
767*4882a593Smuzhiyun         else {
768*4882a593Smuzhiyun             *bufptr++ = names->length[i];
769*4882a593Smuzhiyun             memmove(bufptr, names->names[i], names->length[i]);
770*4882a593Smuzhiyun             bufptr += names->length[i];
771*4882a593Smuzhiyun         }
772*4882a593Smuzhiyun     }
773*4882a593Smuzhiyun     nnames = reply.nFonts;
774*4882a593Smuzhiyun     reply.length = bytes_to_int32(stringLens + nnames);
775*4882a593Smuzhiyun     client->pSwapReplyFunc = ReplySwapVector[X_ListFonts];
776*4882a593Smuzhiyun     WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply);
777*4882a593Smuzhiyun     WriteToClient(client, stringLens + nnames, bufferStart);
778*4882a593Smuzhiyun     free(bufferStart);
779*4882a593Smuzhiyun 
780*4882a593Smuzhiyun  bail:
781*4882a593Smuzhiyun     ClientWakeup(client);
782*4882a593Smuzhiyun     for (i = 0; i < c->num_fpes; i++)
783*4882a593Smuzhiyun         FreeFPE(c->fpe_list[i]);
784*4882a593Smuzhiyun     free(c->fpe_list);
785*4882a593Smuzhiyun     free(c->savedName);
786*4882a593Smuzhiyun     xfont2_free_font_names(names);
787*4882a593Smuzhiyun     free(c);
788*4882a593Smuzhiyun     free(resolved);
789*4882a593Smuzhiyun     return TRUE;
790*4882a593Smuzhiyun }
791*4882a593Smuzhiyun 
792*4882a593Smuzhiyun int
ListFonts(ClientPtr client,unsigned char * pattern,unsigned length,unsigned max_names)793*4882a593Smuzhiyun ListFonts(ClientPtr client, unsigned char *pattern, unsigned length,
794*4882a593Smuzhiyun           unsigned max_names)
795*4882a593Smuzhiyun {
796*4882a593Smuzhiyun     int i;
797*4882a593Smuzhiyun     LFclosurePtr c;
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun     /*
800*4882a593Smuzhiyun      * The right error to return here would be BadName, however the
801*4882a593Smuzhiyun      * specification does not allow for a Name error on this request.
802*4882a593Smuzhiyun      * Perhaps a better solution would be to return a nil list, i.e.
803*4882a593Smuzhiyun      * a list containing zero fontnames.
804*4882a593Smuzhiyun      */
805*4882a593Smuzhiyun     if (length > XLFDMAXFONTNAMELEN)
806*4882a593Smuzhiyun         return BadAlloc;
807*4882a593Smuzhiyun 
808*4882a593Smuzhiyun     i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
809*4882a593Smuzhiyun     if (i != Success)
810*4882a593Smuzhiyun         return i;
811*4882a593Smuzhiyun 
812*4882a593Smuzhiyun     if (!(c = malloc(sizeof *c)))
813*4882a593Smuzhiyun         return BadAlloc;
814*4882a593Smuzhiyun     c->fpe_list = xallocarray(num_fpes, sizeof(FontPathElementPtr));
815*4882a593Smuzhiyun     if (!c->fpe_list) {
816*4882a593Smuzhiyun         free(c);
817*4882a593Smuzhiyun         return BadAlloc;
818*4882a593Smuzhiyun     }
819*4882a593Smuzhiyun     c->names = xfont2_make_font_names_record(max_names < 100 ? max_names : 100);
820*4882a593Smuzhiyun     if (!c->names) {
821*4882a593Smuzhiyun         free(c->fpe_list);
822*4882a593Smuzhiyun         free(c);
823*4882a593Smuzhiyun         return BadAlloc;
824*4882a593Smuzhiyun     }
825*4882a593Smuzhiyun     memmove(c->current.pattern, pattern, length);
826*4882a593Smuzhiyun     for (i = 0; i < num_fpes; i++) {
827*4882a593Smuzhiyun         c->fpe_list[i] = font_path_elements[i];
828*4882a593Smuzhiyun         UseFPE(c->fpe_list[i]);
829*4882a593Smuzhiyun     }
830*4882a593Smuzhiyun     c->client = client;
831*4882a593Smuzhiyun     c->num_fpes = num_fpes;
832*4882a593Smuzhiyun     c->current.patlen = length;
833*4882a593Smuzhiyun     c->current.current_fpe = 0;
834*4882a593Smuzhiyun     c->current.max_names = max_names;
835*4882a593Smuzhiyun     c->current.list_started = FALSE;
836*4882a593Smuzhiyun     c->current.private = 0;
837*4882a593Smuzhiyun     c->haveSaved = FALSE;
838*4882a593Smuzhiyun     c->savedName = 0;
839*4882a593Smuzhiyun     doListFontsAndAliases(client, c);
840*4882a593Smuzhiyun     return Success;
841*4882a593Smuzhiyun }
842*4882a593Smuzhiyun 
843*4882a593Smuzhiyun static int
doListFontsWithInfo(ClientPtr client,LFWIclosurePtr c)844*4882a593Smuzhiyun doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c)
845*4882a593Smuzhiyun {
846*4882a593Smuzhiyun     FontPathElementPtr fpe;
847*4882a593Smuzhiyun     int err = Successful;
848*4882a593Smuzhiyun     char *name;
849*4882a593Smuzhiyun     int namelen;
850*4882a593Smuzhiyun     int numFonts;
851*4882a593Smuzhiyun     FontInfoRec fontInfo, *pFontInfo;
852*4882a593Smuzhiyun     xListFontsWithInfoReply *reply;
853*4882a593Smuzhiyun     int length;
854*4882a593Smuzhiyun     xFontProp *pFP;
855*4882a593Smuzhiyun     int i;
856*4882a593Smuzhiyun     int aliascount = 0;
857*4882a593Smuzhiyun     xListFontsWithInfoReply finalReply;
858*4882a593Smuzhiyun 
859*4882a593Smuzhiyun     if (client->clientGone) {
860*4882a593Smuzhiyun         if (c->current.current_fpe < c->num_fpes) {
861*4882a593Smuzhiyun             fpe = c->fpe_list[c->current.current_fpe];
862*4882a593Smuzhiyun             (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe);
863*4882a593Smuzhiyun         }
864*4882a593Smuzhiyun         err = Successful;
865*4882a593Smuzhiyun         goto bail;
866*4882a593Smuzhiyun     }
867*4882a593Smuzhiyun     client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo];
868*4882a593Smuzhiyun     if (!c->current.patlen)
869*4882a593Smuzhiyun         goto finish;
870*4882a593Smuzhiyun     while (c->current.current_fpe < c->num_fpes) {
871*4882a593Smuzhiyun         fpe = c->fpe_list[c->current.current_fpe];
872*4882a593Smuzhiyun         err = Successful;
873*4882a593Smuzhiyun         if (!c->current.list_started) {
874*4882a593Smuzhiyun             err = (*fpe_functions[fpe->type]->start_list_fonts_with_info)
875*4882a593Smuzhiyun                 (client, fpe, c->current.pattern, c->current.patlen,
876*4882a593Smuzhiyun                  c->current.max_names, &c->current.private);
877*4882a593Smuzhiyun             if (err == Suspended) {
878*4882a593Smuzhiyun                 if (!ClientIsAsleep(client))
879*4882a593Smuzhiyun                     ClientSleep(client,
880*4882a593Smuzhiyun                                 (ClientSleepProcPtr) doListFontsWithInfo, c);
881*4882a593Smuzhiyun                 return TRUE;
882*4882a593Smuzhiyun             }
883*4882a593Smuzhiyun             if (err == Successful)
884*4882a593Smuzhiyun                 c->current.list_started = TRUE;
885*4882a593Smuzhiyun         }
886*4882a593Smuzhiyun         if (err == Successful) {
887*4882a593Smuzhiyun             name = 0;
888*4882a593Smuzhiyun             pFontInfo = &fontInfo;
889*4882a593Smuzhiyun             err = (*fpe_functions[fpe->type]->list_next_font_with_info)
890*4882a593Smuzhiyun                 (client, fpe, &name, &namelen, &pFontInfo,
891*4882a593Smuzhiyun                  &numFonts, c->current.private);
892*4882a593Smuzhiyun             if (err == Suspended) {
893*4882a593Smuzhiyun                 if (!ClientIsAsleep(client))
894*4882a593Smuzhiyun                     ClientSleep(client,
895*4882a593Smuzhiyun                                 (ClientSleepProcPtr) doListFontsWithInfo, c);
896*4882a593Smuzhiyun                 return TRUE;
897*4882a593Smuzhiyun             }
898*4882a593Smuzhiyun         }
899*4882a593Smuzhiyun         /*
900*4882a593Smuzhiyun          * When we get an alias back, save our state and reset back to the
901*4882a593Smuzhiyun          * start of the FPE looking for the specified name.  As soon as a real
902*4882a593Smuzhiyun          * font is found for the alias, pop back to the old state
903*4882a593Smuzhiyun          */
904*4882a593Smuzhiyun         if (err == FontNameAlias) {
905*4882a593Smuzhiyun             /*
906*4882a593Smuzhiyun              * when an alias recurses, we need to give
907*4882a593Smuzhiyun              * the last FPE a chance to clean up; so we call
908*4882a593Smuzhiyun              * it again, and assume that the error returned
909*4882a593Smuzhiyun              * is BadFontName, indicating the alias resolution
910*4882a593Smuzhiyun              * is complete.
911*4882a593Smuzhiyun              */
912*4882a593Smuzhiyun             if (c->haveSaved) {
913*4882a593Smuzhiyun                 char *tmpname;
914*4882a593Smuzhiyun                 int tmpnamelen;
915*4882a593Smuzhiyun                 FontInfoPtr tmpFontInfo;
916*4882a593Smuzhiyun 
917*4882a593Smuzhiyun                 tmpname = 0;
918*4882a593Smuzhiyun                 tmpFontInfo = &fontInfo;
919*4882a593Smuzhiyun                 (void) (*fpe_functions[fpe->type]->list_next_font_with_info)
920*4882a593Smuzhiyun                     (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo,
921*4882a593Smuzhiyun                      &numFonts, c->current.private);
922*4882a593Smuzhiyun                 if (--aliascount <= 0) {
923*4882a593Smuzhiyun                     err = BadFontName;
924*4882a593Smuzhiyun                     goto ContBadFontName;
925*4882a593Smuzhiyun                 }
926*4882a593Smuzhiyun             }
927*4882a593Smuzhiyun             else {
928*4882a593Smuzhiyun                 c->saved = c->current;
929*4882a593Smuzhiyun                 c->haveSaved = TRUE;
930*4882a593Smuzhiyun                 c->savedNumFonts = numFonts;
931*4882a593Smuzhiyun                 free(c->savedName);
932*4882a593Smuzhiyun                 c->savedName = malloc(namelen + 1);
933*4882a593Smuzhiyun                 if (c->savedName)
934*4882a593Smuzhiyun                     memmove(c->savedName, name, namelen + 1);
935*4882a593Smuzhiyun                 aliascount = 20;
936*4882a593Smuzhiyun             }
937*4882a593Smuzhiyun             memmove(c->current.pattern, name, namelen);
938*4882a593Smuzhiyun             c->current.patlen = namelen;
939*4882a593Smuzhiyun             c->current.max_names = 1;
940*4882a593Smuzhiyun             c->current.current_fpe = 0;
941*4882a593Smuzhiyun             c->current.private = 0;
942*4882a593Smuzhiyun             c->current.list_started = FALSE;
943*4882a593Smuzhiyun         }
944*4882a593Smuzhiyun         /*
945*4882a593Smuzhiyun          * At the end of this FPE, step to the next.  If we've finished
946*4882a593Smuzhiyun          * processing an alias, pop state back.  If we've sent enough font
947*4882a593Smuzhiyun          * names, quit.  Always wait for BadFontName to let the FPE
948*4882a593Smuzhiyun          * have a chance to clean up.
949*4882a593Smuzhiyun          */
950*4882a593Smuzhiyun         else if (err == BadFontName) {
951*4882a593Smuzhiyun  ContBadFontName:;
952*4882a593Smuzhiyun             c->current.list_started = FALSE;
953*4882a593Smuzhiyun             c->current.current_fpe++;
954*4882a593Smuzhiyun             err = Successful;
955*4882a593Smuzhiyun             if (c->haveSaved) {
956*4882a593Smuzhiyun                 if (c->current.max_names == 0 ||
957*4882a593Smuzhiyun                     c->current.current_fpe == c->num_fpes) {
958*4882a593Smuzhiyun                     c->haveSaved = FALSE;
959*4882a593Smuzhiyun                     c->saved.max_names -= (1 - c->current.max_names);
960*4882a593Smuzhiyun                     c->current = c->saved;
961*4882a593Smuzhiyun                 }
962*4882a593Smuzhiyun             }
963*4882a593Smuzhiyun             else if (c->current.max_names == 0)
964*4882a593Smuzhiyun                 break;
965*4882a593Smuzhiyun         }
966*4882a593Smuzhiyun         else if (err == Successful) {
967*4882a593Smuzhiyun             length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp);
968*4882a593Smuzhiyun             reply = c->reply;
969*4882a593Smuzhiyun             if (c->length < length) {
970*4882a593Smuzhiyun                 reply = (xListFontsWithInfoReply *) realloc(c->reply, length);
971*4882a593Smuzhiyun                 if (!reply) {
972*4882a593Smuzhiyun                     err = AllocError;
973*4882a593Smuzhiyun                     break;
974*4882a593Smuzhiyun                 }
975*4882a593Smuzhiyun                 memset((char *) reply + c->length, 0, length - c->length);
976*4882a593Smuzhiyun                 c->reply = reply;
977*4882a593Smuzhiyun                 c->length = length;
978*4882a593Smuzhiyun             }
979*4882a593Smuzhiyun             if (c->haveSaved) {
980*4882a593Smuzhiyun                 numFonts = c->savedNumFonts;
981*4882a593Smuzhiyun                 name = c->savedName;
982*4882a593Smuzhiyun                 namelen = strlen(name);
983*4882a593Smuzhiyun             }
984*4882a593Smuzhiyun             reply->type = X_Reply;
985*4882a593Smuzhiyun             reply->length =
986*4882a593Smuzhiyun                 bytes_to_int32(sizeof *reply - sizeof(xGenericReply) +
987*4882a593Smuzhiyun                                pFontInfo->nprops * sizeof(xFontProp) + namelen);
988*4882a593Smuzhiyun             reply->sequenceNumber = client->sequence;
989*4882a593Smuzhiyun             reply->nameLength = namelen;
990*4882a593Smuzhiyun             reply->minBounds = pFontInfo->ink_minbounds;
991*4882a593Smuzhiyun             reply->maxBounds = pFontInfo->ink_maxbounds;
992*4882a593Smuzhiyun             reply->minCharOrByte2 = pFontInfo->firstCol;
993*4882a593Smuzhiyun             reply->maxCharOrByte2 = pFontInfo->lastCol;
994*4882a593Smuzhiyun             reply->defaultChar = pFontInfo->defaultCh;
995*4882a593Smuzhiyun             reply->nFontProps = pFontInfo->nprops;
996*4882a593Smuzhiyun             reply->drawDirection = pFontInfo->drawDirection;
997*4882a593Smuzhiyun             reply->minByte1 = pFontInfo->firstRow;
998*4882a593Smuzhiyun             reply->maxByte1 = pFontInfo->lastRow;
999*4882a593Smuzhiyun             reply->allCharsExist = pFontInfo->allExist;
1000*4882a593Smuzhiyun             reply->fontAscent = pFontInfo->fontAscent;
1001*4882a593Smuzhiyun             reply->fontDescent = pFontInfo->fontDescent;
1002*4882a593Smuzhiyun             reply->nReplies = numFonts;
1003*4882a593Smuzhiyun             pFP = (xFontProp *) (reply + 1);
1004*4882a593Smuzhiyun             for (i = 0; i < pFontInfo->nprops; i++) {
1005*4882a593Smuzhiyun                 pFP->name = pFontInfo->props[i].name;
1006*4882a593Smuzhiyun                 pFP->value = pFontInfo->props[i].value;
1007*4882a593Smuzhiyun                 pFP++;
1008*4882a593Smuzhiyun             }
1009*4882a593Smuzhiyun             WriteSwappedDataToClient(client, length, reply);
1010*4882a593Smuzhiyun             WriteToClient(client, namelen, name);
1011*4882a593Smuzhiyun             if (pFontInfo == &fontInfo) {
1012*4882a593Smuzhiyun                 free(fontInfo.props);
1013*4882a593Smuzhiyun                 free(fontInfo.isStringProp);
1014*4882a593Smuzhiyun             }
1015*4882a593Smuzhiyun             --c->current.max_names;
1016*4882a593Smuzhiyun         }
1017*4882a593Smuzhiyun     }
1018*4882a593Smuzhiyun  finish:
1019*4882a593Smuzhiyun     length = sizeof(xListFontsWithInfoReply);
1020*4882a593Smuzhiyun     finalReply = (xListFontsWithInfoReply) {
1021*4882a593Smuzhiyun         .type = X_Reply,
1022*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
1023*4882a593Smuzhiyun         .length = bytes_to_int32(sizeof(xListFontsWithInfoReply)
1024*4882a593Smuzhiyun                                  - sizeof(xGenericReply))
1025*4882a593Smuzhiyun     };
1026*4882a593Smuzhiyun     WriteSwappedDataToClient(client, length, &finalReply);
1027*4882a593Smuzhiyun  bail:
1028*4882a593Smuzhiyun     ClientWakeup(client);
1029*4882a593Smuzhiyun     for (i = 0; i < c->num_fpes; i++)
1030*4882a593Smuzhiyun         FreeFPE(c->fpe_list[i]);
1031*4882a593Smuzhiyun     free(c->reply);
1032*4882a593Smuzhiyun     free(c->fpe_list);
1033*4882a593Smuzhiyun     free(c->savedName);
1034*4882a593Smuzhiyun     free(c);
1035*4882a593Smuzhiyun     return TRUE;
1036*4882a593Smuzhiyun }
1037*4882a593Smuzhiyun 
1038*4882a593Smuzhiyun int
StartListFontsWithInfo(ClientPtr client,int length,unsigned char * pattern,int max_names)1039*4882a593Smuzhiyun StartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern,
1040*4882a593Smuzhiyun                        int max_names)
1041*4882a593Smuzhiyun {
1042*4882a593Smuzhiyun     int i;
1043*4882a593Smuzhiyun     LFWIclosurePtr c;
1044*4882a593Smuzhiyun 
1045*4882a593Smuzhiyun     /*
1046*4882a593Smuzhiyun      * The right error to return here would be BadName, however the
1047*4882a593Smuzhiyun      * specification does not allow for a Name error on this request.
1048*4882a593Smuzhiyun      * Perhaps a better solution would be to return a nil list, i.e.
1049*4882a593Smuzhiyun      * a list containing zero fontnames.
1050*4882a593Smuzhiyun      */
1051*4882a593Smuzhiyun     if (length > XLFDMAXFONTNAMELEN)
1052*4882a593Smuzhiyun         return BadAlloc;
1053*4882a593Smuzhiyun 
1054*4882a593Smuzhiyun     i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
1055*4882a593Smuzhiyun     if (i != Success)
1056*4882a593Smuzhiyun         return i;
1057*4882a593Smuzhiyun 
1058*4882a593Smuzhiyun     if (!(c = malloc(sizeof *c)))
1059*4882a593Smuzhiyun         goto badAlloc;
1060*4882a593Smuzhiyun     c->fpe_list = xallocarray(num_fpes, sizeof(FontPathElementPtr));
1061*4882a593Smuzhiyun     if (!c->fpe_list) {
1062*4882a593Smuzhiyun         free(c);
1063*4882a593Smuzhiyun         goto badAlloc;
1064*4882a593Smuzhiyun     }
1065*4882a593Smuzhiyun     memmove(c->current.pattern, pattern, length);
1066*4882a593Smuzhiyun     for (i = 0; i < num_fpes; i++) {
1067*4882a593Smuzhiyun         c->fpe_list[i] = font_path_elements[i];
1068*4882a593Smuzhiyun         UseFPE(c->fpe_list[i]);
1069*4882a593Smuzhiyun     }
1070*4882a593Smuzhiyun     c->client = client;
1071*4882a593Smuzhiyun     c->num_fpes = num_fpes;
1072*4882a593Smuzhiyun     c->reply = 0;
1073*4882a593Smuzhiyun     c->length = 0;
1074*4882a593Smuzhiyun     c->current.patlen = length;
1075*4882a593Smuzhiyun     c->current.current_fpe = 0;
1076*4882a593Smuzhiyun     c->current.max_names = max_names;
1077*4882a593Smuzhiyun     c->current.list_started = FALSE;
1078*4882a593Smuzhiyun     c->current.private = 0;
1079*4882a593Smuzhiyun     c->savedNumFonts = 0;
1080*4882a593Smuzhiyun     c->haveSaved = FALSE;
1081*4882a593Smuzhiyun     c->savedName = 0;
1082*4882a593Smuzhiyun     doListFontsWithInfo(client, c);
1083*4882a593Smuzhiyun     return Success;
1084*4882a593Smuzhiyun  badAlloc:
1085*4882a593Smuzhiyun     return BadAlloc;
1086*4882a593Smuzhiyun }
1087*4882a593Smuzhiyun 
1088*4882a593Smuzhiyun #define TextEltHeader 2
1089*4882a593Smuzhiyun #define FontShiftSize 5
1090*4882a593Smuzhiyun static ChangeGCVal clearGC[] = { {.ptr = NullPixmap} };
1091*4882a593Smuzhiyun 
1092*4882a593Smuzhiyun #define clearGCmask (GCClipMask)
1093*4882a593Smuzhiyun 
1094*4882a593Smuzhiyun static int
doPolyText(ClientPtr client,PTclosurePtr c)1095*4882a593Smuzhiyun doPolyText(ClientPtr client, PTclosurePtr c)
1096*4882a593Smuzhiyun {
1097*4882a593Smuzhiyun     FontPtr pFont = c->pGC->font, oldpFont;
1098*4882a593Smuzhiyun     int err = Success, lgerr;   /* err is in X error, not font error, space */
1099*4882a593Smuzhiyun     enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT;
1100*4882a593Smuzhiyun     FontPathElementPtr fpe;
1101*4882a593Smuzhiyun     GC *origGC = NULL;
1102*4882a593Smuzhiyun     int itemSize = c->reqType == X_PolyText8 ? 1 : 2;
1103*4882a593Smuzhiyun 
1104*4882a593Smuzhiyun     if (client->clientGone) {
1105*4882a593Smuzhiyun         fpe = c->pGC->font->fpe;
1106*4882a593Smuzhiyun         (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe);
1107*4882a593Smuzhiyun 
1108*4882a593Smuzhiyun         if (ClientIsAsleep(client)) {
1109*4882a593Smuzhiyun             /* Client has died, but we cannot bail out right now.  We
1110*4882a593Smuzhiyun                need to clean up after the work we did when going to
1111*4882a593Smuzhiyun                sleep.  Setting the drawable poiner to 0 makes this
1112*4882a593Smuzhiyun                happen without any attempts to render or perform other
1113*4882a593Smuzhiyun                unnecessary activities.  */
1114*4882a593Smuzhiyun             c->pDraw = (DrawablePtr) 0;
1115*4882a593Smuzhiyun         }
1116*4882a593Smuzhiyun         else {
1117*4882a593Smuzhiyun             err = Success;
1118*4882a593Smuzhiyun             goto bail;
1119*4882a593Smuzhiyun         }
1120*4882a593Smuzhiyun     }
1121*4882a593Smuzhiyun 
1122*4882a593Smuzhiyun     /* Make sure our drawable hasn't disappeared while we slept. */
1123*4882a593Smuzhiyun     if (ClientIsAsleep(client) && c->pDraw) {
1124*4882a593Smuzhiyun         DrawablePtr pDraw;
1125*4882a593Smuzhiyun 
1126*4882a593Smuzhiyun         dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess);
1127*4882a593Smuzhiyun         if (c->pDraw != pDraw) {
1128*4882a593Smuzhiyun             /* Our drawable has disappeared.  Treat like client died... ask
1129*4882a593Smuzhiyun                the FPE code to clean up after client and avoid further
1130*4882a593Smuzhiyun                rendering while we clean up after ourself.  */
1131*4882a593Smuzhiyun             fpe = c->pGC->font->fpe;
1132*4882a593Smuzhiyun             (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe);
1133*4882a593Smuzhiyun             c->pDraw = (DrawablePtr) 0;
1134*4882a593Smuzhiyun         }
1135*4882a593Smuzhiyun     }
1136*4882a593Smuzhiyun 
1137*4882a593Smuzhiyun     client_state = ClientIsAsleep(client) ? SLEEPING : NEVER_SLEPT;
1138*4882a593Smuzhiyun 
1139*4882a593Smuzhiyun     while (c->endReq - c->pElt > TextEltHeader) {
1140*4882a593Smuzhiyun         if (*c->pElt == FontChange) {
1141*4882a593Smuzhiyun             Font fid;
1142*4882a593Smuzhiyun 
1143*4882a593Smuzhiyun             if (c->endReq - c->pElt < FontShiftSize) {
1144*4882a593Smuzhiyun                 err = BadLength;
1145*4882a593Smuzhiyun                 goto bail;
1146*4882a593Smuzhiyun             }
1147*4882a593Smuzhiyun 
1148*4882a593Smuzhiyun             oldpFont = pFont;
1149*4882a593Smuzhiyun 
1150*4882a593Smuzhiyun             fid = ((Font) *(c->pElt + 4))       /* big-endian */
1151*4882a593Smuzhiyun                 |((Font) *(c->pElt + 3)) << 8
1152*4882a593Smuzhiyun                 | ((Font) *(c->pElt + 2)) << 16 | ((Font) *(c->pElt + 1)) << 24;
1153*4882a593Smuzhiyun             err = dixLookupResourceByType((void **) &pFont, fid, RT_FONT,
1154*4882a593Smuzhiyun                                           client, DixUseAccess);
1155*4882a593Smuzhiyun             if (err != Success) {
1156*4882a593Smuzhiyun                 /* restore pFont for step 4 (described below) */
1157*4882a593Smuzhiyun                 pFont = oldpFont;
1158*4882a593Smuzhiyun 
1159*4882a593Smuzhiyun                 /* If we're in START_SLEEP mode, the following step
1160*4882a593Smuzhiyun                    shortens the request...  in the unlikely event that
1161*4882a593Smuzhiyun                    the fid somehow becomes valid before we come through
1162*4882a593Smuzhiyun                    again to actually execute the polytext, which would
1163*4882a593Smuzhiyun                    then mess up our refcounting scheme badly.  */
1164*4882a593Smuzhiyun                 c->err = err;
1165*4882a593Smuzhiyun                 c->endReq = c->pElt;
1166*4882a593Smuzhiyun 
1167*4882a593Smuzhiyun                 goto bail;
1168*4882a593Smuzhiyun             }
1169*4882a593Smuzhiyun 
1170*4882a593Smuzhiyun             /* Step 3 (described below) on our new font */
1171*4882a593Smuzhiyun             if (client_state == START_SLEEP)
1172*4882a593Smuzhiyun                 pFont->refcnt++;
1173*4882a593Smuzhiyun             else {
1174*4882a593Smuzhiyun                 if (pFont != c->pGC->font && c->pDraw) {
1175*4882a593Smuzhiyun                     ChangeGCVal val;
1176*4882a593Smuzhiyun 
1177*4882a593Smuzhiyun                     val.ptr = pFont;
1178*4882a593Smuzhiyun                     ChangeGC(NullClient, c->pGC, GCFont, &val);
1179*4882a593Smuzhiyun                     ValidateGC(c->pDraw, c->pGC);
1180*4882a593Smuzhiyun                 }
1181*4882a593Smuzhiyun 
1182*4882a593Smuzhiyun                 /* Undo the refcnt++ we performed when going to sleep */
1183*4882a593Smuzhiyun                 if (client_state == SLEEPING)
1184*4882a593Smuzhiyun                     (void) CloseFont(c->pGC->font, (Font) 0);
1185*4882a593Smuzhiyun             }
1186*4882a593Smuzhiyun             c->pElt += FontShiftSize;
1187*4882a593Smuzhiyun         }
1188*4882a593Smuzhiyun         else {                  /* print a string */
1189*4882a593Smuzhiyun 
1190*4882a593Smuzhiyun             unsigned char *pNextElt;
1191*4882a593Smuzhiyun 
1192*4882a593Smuzhiyun             pNextElt = c->pElt + TextEltHeader + (*c->pElt) * itemSize;
1193*4882a593Smuzhiyun             if (pNextElt > c->endReq) {
1194*4882a593Smuzhiyun                 err = BadLength;
1195*4882a593Smuzhiyun                 goto bail;
1196*4882a593Smuzhiyun             }
1197*4882a593Smuzhiyun             if (client_state == START_SLEEP) {
1198*4882a593Smuzhiyun                 c->pElt = pNextElt;
1199*4882a593Smuzhiyun                 continue;
1200*4882a593Smuzhiyun             }
1201*4882a593Smuzhiyun             if (c->pDraw) {
1202*4882a593Smuzhiyun                 lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, itemSize,
1203*4882a593Smuzhiyun                                    c->pElt + TextEltHeader);
1204*4882a593Smuzhiyun             }
1205*4882a593Smuzhiyun             else
1206*4882a593Smuzhiyun                 lgerr = Successful;
1207*4882a593Smuzhiyun 
1208*4882a593Smuzhiyun             if (lgerr == Suspended) {
1209*4882a593Smuzhiyun                 if (!ClientIsAsleep(client)) {
1210*4882a593Smuzhiyun                     int len;
1211*4882a593Smuzhiyun                     GC *pGC;
1212*4882a593Smuzhiyun                     PTclosurePtr new_closure;
1213*4882a593Smuzhiyun 
1214*4882a593Smuzhiyun                     /*  We're putting the client to sleep.  We need to do a few things
1215*4882a593Smuzhiyun                        to ensure successful and atomic-appearing execution of the
1216*4882a593Smuzhiyun                        remainder of the request.  First, copy the remainder of the
1217*4882a593Smuzhiyun                        request into a safe malloc'd area.  Second, create a scratch GC
1218*4882a593Smuzhiyun                        to use for the remainder of the request.  Third, mark all fonts
1219*4882a593Smuzhiyun                        referenced in the remainder of the request to prevent their
1220*4882a593Smuzhiyun                        deallocation.  Fourth, make the original GC look like the
1221*4882a593Smuzhiyun                        request has completed...  set its font to the final font value
1222*4882a593Smuzhiyun                        from this request.  These GC manipulations are for the unlikely
1223*4882a593Smuzhiyun                        (but possible) event that some other client is using the GC.
1224*4882a593Smuzhiyun                        Steps 3 and 4 are performed by running this procedure through
1225*4882a593Smuzhiyun                        the remainder of the request in a special no-render mode
1226*4882a593Smuzhiyun                        indicated by client_state = START_SLEEP.  */
1227*4882a593Smuzhiyun 
1228*4882a593Smuzhiyun                     /* Step 1 */
1229*4882a593Smuzhiyun                     /* Allocate a malloc'd closure structure to replace
1230*4882a593Smuzhiyun                        the local one we were passed */
1231*4882a593Smuzhiyun                     new_closure = malloc(sizeof(PTclosureRec));
1232*4882a593Smuzhiyun                     if (!new_closure) {
1233*4882a593Smuzhiyun                         err = BadAlloc;
1234*4882a593Smuzhiyun                         goto bail;
1235*4882a593Smuzhiyun                     }
1236*4882a593Smuzhiyun                     *new_closure = *c;
1237*4882a593Smuzhiyun 
1238*4882a593Smuzhiyun                     len = new_closure->endReq - new_closure->pElt;
1239*4882a593Smuzhiyun                     new_closure->data = malloc(len);
1240*4882a593Smuzhiyun                     if (!new_closure->data) {
1241*4882a593Smuzhiyun                         free(new_closure);
1242*4882a593Smuzhiyun                         err = BadAlloc;
1243*4882a593Smuzhiyun                         goto bail;
1244*4882a593Smuzhiyun                     }
1245*4882a593Smuzhiyun                     memmove(new_closure->data, new_closure->pElt, len);
1246*4882a593Smuzhiyun                     new_closure->pElt = new_closure->data;
1247*4882a593Smuzhiyun                     new_closure->endReq = new_closure->pElt + len;
1248*4882a593Smuzhiyun 
1249*4882a593Smuzhiyun                     /* Step 2 */
1250*4882a593Smuzhiyun 
1251*4882a593Smuzhiyun                     pGC =
1252*4882a593Smuzhiyun                         GetScratchGC(new_closure->pGC->depth,
1253*4882a593Smuzhiyun                                      new_closure->pGC->pScreen);
1254*4882a593Smuzhiyun                     if (!pGC) {
1255*4882a593Smuzhiyun                         free(new_closure->data);
1256*4882a593Smuzhiyun                         free(new_closure);
1257*4882a593Smuzhiyun                         err = BadAlloc;
1258*4882a593Smuzhiyun                         goto bail;
1259*4882a593Smuzhiyun                     }
1260*4882a593Smuzhiyun                     if ((err = CopyGC(new_closure->pGC, pGC, GCFunction |
1261*4882a593Smuzhiyun                                       GCPlaneMask | GCForeground |
1262*4882a593Smuzhiyun                                       GCBackground | GCFillStyle |
1263*4882a593Smuzhiyun                                       GCTile | GCStipple |
1264*4882a593Smuzhiyun                                       GCTileStipXOrigin |
1265*4882a593Smuzhiyun                                       GCTileStipYOrigin | GCFont |
1266*4882a593Smuzhiyun                                       GCSubwindowMode | GCClipXOrigin |
1267*4882a593Smuzhiyun                                       GCClipYOrigin | GCClipMask)) != Success) {
1268*4882a593Smuzhiyun                         FreeScratchGC(pGC);
1269*4882a593Smuzhiyun                         free(new_closure->data);
1270*4882a593Smuzhiyun                         free(new_closure);
1271*4882a593Smuzhiyun                         err = BadAlloc;
1272*4882a593Smuzhiyun                         goto bail;
1273*4882a593Smuzhiyun                     }
1274*4882a593Smuzhiyun                     c = new_closure;
1275*4882a593Smuzhiyun                     origGC = c->pGC;
1276*4882a593Smuzhiyun                     c->pGC = pGC;
1277*4882a593Smuzhiyun                     ValidateGC(c->pDraw, c->pGC);
1278*4882a593Smuzhiyun 
1279*4882a593Smuzhiyun                     ClientSleep(client, (ClientSleepProcPtr) doPolyText, c);
1280*4882a593Smuzhiyun 
1281*4882a593Smuzhiyun                     /* Set up to perform steps 3 and 4 */
1282*4882a593Smuzhiyun                     client_state = START_SLEEP;
1283*4882a593Smuzhiyun                     continue;   /* on to steps 3 and 4 */
1284*4882a593Smuzhiyun                 }
1285*4882a593Smuzhiyun                 return TRUE;
1286*4882a593Smuzhiyun             }
1287*4882a593Smuzhiyun             else if (lgerr != Successful) {
1288*4882a593Smuzhiyun                 err = FontToXError(lgerr);
1289*4882a593Smuzhiyun                 goto bail;
1290*4882a593Smuzhiyun             }
1291*4882a593Smuzhiyun             if (c->pDraw) {
1292*4882a593Smuzhiyun                 c->xorg += *((INT8 *) (c->pElt + 1));   /* must be signed */
1293*4882a593Smuzhiyun                 if (c->reqType == X_PolyText8)
1294*4882a593Smuzhiyun                     c->xorg =
1295*4882a593Smuzhiyun                         (*c->pGC->ops->PolyText8) (c->pDraw, c->pGC, c->xorg,
1296*4882a593Smuzhiyun                                                    c->yorg, *c->pElt,
1297*4882a593Smuzhiyun                                                    (char *) (c->pElt +
1298*4882a593Smuzhiyun                                                              TextEltHeader));
1299*4882a593Smuzhiyun                 else
1300*4882a593Smuzhiyun                     c->xorg =
1301*4882a593Smuzhiyun                         (*c->pGC->ops->PolyText16) (c->pDraw, c->pGC, c->xorg,
1302*4882a593Smuzhiyun                                                     c->yorg, *c->pElt,
1303*4882a593Smuzhiyun                                                     (unsigned short *) (c->
1304*4882a593Smuzhiyun                                                                         pElt +
1305*4882a593Smuzhiyun                                                                         TextEltHeader));
1306*4882a593Smuzhiyun             }
1307*4882a593Smuzhiyun             c->pElt = pNextElt;
1308*4882a593Smuzhiyun         }
1309*4882a593Smuzhiyun     }
1310*4882a593Smuzhiyun 
1311*4882a593Smuzhiyun  bail:
1312*4882a593Smuzhiyun 
1313*4882a593Smuzhiyun     if (client_state == START_SLEEP) {
1314*4882a593Smuzhiyun         /* Step 4 */
1315*4882a593Smuzhiyun         if (pFont != origGC->font) {
1316*4882a593Smuzhiyun             ChangeGCVal val;
1317*4882a593Smuzhiyun 
1318*4882a593Smuzhiyun             val.ptr = pFont;
1319*4882a593Smuzhiyun             ChangeGC(NullClient, origGC, GCFont, &val);
1320*4882a593Smuzhiyun             ValidateGC(c->pDraw, origGC);
1321*4882a593Smuzhiyun         }
1322*4882a593Smuzhiyun 
1323*4882a593Smuzhiyun         /* restore pElt pointer for execution of remainder of the request */
1324*4882a593Smuzhiyun         c->pElt = c->data;
1325*4882a593Smuzhiyun         return TRUE;
1326*4882a593Smuzhiyun     }
1327*4882a593Smuzhiyun 
1328*4882a593Smuzhiyun     if (c->err != Success)
1329*4882a593Smuzhiyun         err = c->err;
1330*4882a593Smuzhiyun     if (err != Success && c->client != serverClient) {
1331*4882a593Smuzhiyun #ifdef PANORAMIX
1332*4882a593Smuzhiyun         if (noPanoramiXExtension || !c->pGC->pScreen->myNum)
1333*4882a593Smuzhiyun #endif
1334*4882a593Smuzhiyun             SendErrorToClient(c->client, c->reqType, 0, 0, err);
1335*4882a593Smuzhiyun     }
1336*4882a593Smuzhiyun     if (ClientIsAsleep(client)) {
1337*4882a593Smuzhiyun         ClientWakeup(c->client);
1338*4882a593Smuzhiyun         ChangeGC(NullClient, c->pGC, clearGCmask, clearGC);
1339*4882a593Smuzhiyun 
1340*4882a593Smuzhiyun         /* Unreference the font from the scratch GC */
1341*4882a593Smuzhiyun         CloseFont(c->pGC->font, (Font) 0);
1342*4882a593Smuzhiyun         c->pGC->font = NullFont;
1343*4882a593Smuzhiyun 
1344*4882a593Smuzhiyun         FreeScratchGC(c->pGC);
1345*4882a593Smuzhiyun         free(c->data);
1346*4882a593Smuzhiyun         free(c);
1347*4882a593Smuzhiyun     }
1348*4882a593Smuzhiyun     return TRUE;
1349*4882a593Smuzhiyun }
1350*4882a593Smuzhiyun 
1351*4882a593Smuzhiyun int
PolyText(ClientPtr client,DrawablePtr pDraw,GC * pGC,unsigned char * pElt,unsigned char * endReq,int xorg,int yorg,int reqType,XID did)1352*4882a593Smuzhiyun PolyText(ClientPtr client, DrawablePtr pDraw, GC * pGC, unsigned char *pElt,
1353*4882a593Smuzhiyun          unsigned char *endReq, int xorg, int yorg, int reqType, XID did)
1354*4882a593Smuzhiyun {
1355*4882a593Smuzhiyun     PTclosureRec local_closure;
1356*4882a593Smuzhiyun 
1357*4882a593Smuzhiyun     local_closure.pElt = pElt;
1358*4882a593Smuzhiyun     local_closure.endReq = endReq;
1359*4882a593Smuzhiyun     local_closure.client = client;
1360*4882a593Smuzhiyun     local_closure.pDraw = pDraw;
1361*4882a593Smuzhiyun     local_closure.xorg = xorg;
1362*4882a593Smuzhiyun     local_closure.yorg = yorg;
1363*4882a593Smuzhiyun     local_closure.reqType = reqType;
1364*4882a593Smuzhiyun     local_closure.pGC = pGC;
1365*4882a593Smuzhiyun     local_closure.did = did;
1366*4882a593Smuzhiyun     local_closure.err = Success;
1367*4882a593Smuzhiyun 
1368*4882a593Smuzhiyun     (void) doPolyText(client, &local_closure);
1369*4882a593Smuzhiyun     return Success;
1370*4882a593Smuzhiyun }
1371*4882a593Smuzhiyun 
1372*4882a593Smuzhiyun #undef TextEltHeader
1373*4882a593Smuzhiyun #undef FontShiftSize
1374*4882a593Smuzhiyun 
1375*4882a593Smuzhiyun static int
doImageText(ClientPtr client,ITclosurePtr c)1376*4882a593Smuzhiyun doImageText(ClientPtr client, ITclosurePtr c)
1377*4882a593Smuzhiyun {
1378*4882a593Smuzhiyun     int err = Success, lgerr;   /* err is in X error, not font error, space */
1379*4882a593Smuzhiyun     FontPathElementPtr fpe;
1380*4882a593Smuzhiyun     int itemSize = c->reqType == X_ImageText8 ? 1 : 2;
1381*4882a593Smuzhiyun 
1382*4882a593Smuzhiyun     if (client->clientGone) {
1383*4882a593Smuzhiyun         fpe = c->pGC->font->fpe;
1384*4882a593Smuzhiyun         (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe);
1385*4882a593Smuzhiyun         err = Success;
1386*4882a593Smuzhiyun         goto bail;
1387*4882a593Smuzhiyun     }
1388*4882a593Smuzhiyun 
1389*4882a593Smuzhiyun     /* Make sure our drawable hasn't disappeared while we slept. */
1390*4882a593Smuzhiyun     if (ClientIsAsleep(client) && c->pDraw) {
1391*4882a593Smuzhiyun         DrawablePtr pDraw;
1392*4882a593Smuzhiyun 
1393*4882a593Smuzhiyun         dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess);
1394*4882a593Smuzhiyun         if (c->pDraw != pDraw) {
1395*4882a593Smuzhiyun             /* Our drawable has disappeared.  Treat like client died... ask
1396*4882a593Smuzhiyun                the FPE code to clean up after client. */
1397*4882a593Smuzhiyun             fpe = c->pGC->font->fpe;
1398*4882a593Smuzhiyun             (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe);
1399*4882a593Smuzhiyun             err = Success;
1400*4882a593Smuzhiyun             goto bail;
1401*4882a593Smuzhiyun         }
1402*4882a593Smuzhiyun     }
1403*4882a593Smuzhiyun 
1404*4882a593Smuzhiyun     lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, itemSize, c->data);
1405*4882a593Smuzhiyun     if (lgerr == Suspended) {
1406*4882a593Smuzhiyun         if (!ClientIsAsleep(client)) {
1407*4882a593Smuzhiyun             GC *pGC;
1408*4882a593Smuzhiyun             unsigned char *data;
1409*4882a593Smuzhiyun             ITclosurePtr new_closure;
1410*4882a593Smuzhiyun             ITclosurePtr old_closure;
1411*4882a593Smuzhiyun 
1412*4882a593Smuzhiyun             /* We're putting the client to sleep.  We need to
1413*4882a593Smuzhiyun                save some state.  Similar problem to that handled
1414*4882a593Smuzhiyun                in doPolyText, but much simpler because the
1415*4882a593Smuzhiyun                request structure is much simpler. */
1416*4882a593Smuzhiyun 
1417*4882a593Smuzhiyun             new_closure = malloc(sizeof(ITclosureRec));
1418*4882a593Smuzhiyun             if (!new_closure) {
1419*4882a593Smuzhiyun                 err = BadAlloc;
1420*4882a593Smuzhiyun                 goto bail;
1421*4882a593Smuzhiyun             }
1422*4882a593Smuzhiyun             old_closure = c;
1423*4882a593Smuzhiyun             *new_closure = *c;
1424*4882a593Smuzhiyun             c = new_closure;
1425*4882a593Smuzhiyun 
1426*4882a593Smuzhiyun             data = xallocarray(c->nChars, itemSize);
1427*4882a593Smuzhiyun             if (!data) {
1428*4882a593Smuzhiyun                 free(c);
1429*4882a593Smuzhiyun                 c = old_closure;
1430*4882a593Smuzhiyun                 err = BadAlloc;
1431*4882a593Smuzhiyun                 goto bail;
1432*4882a593Smuzhiyun             }
1433*4882a593Smuzhiyun             memmove(data, c->data, c->nChars * itemSize);
1434*4882a593Smuzhiyun             c->data = data;
1435*4882a593Smuzhiyun 
1436*4882a593Smuzhiyun             pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
1437*4882a593Smuzhiyun             if (!pGC) {
1438*4882a593Smuzhiyun                 free(c->data);
1439*4882a593Smuzhiyun                 free(c);
1440*4882a593Smuzhiyun                 c = old_closure;
1441*4882a593Smuzhiyun                 err = BadAlloc;
1442*4882a593Smuzhiyun                 goto bail;
1443*4882a593Smuzhiyun             }
1444*4882a593Smuzhiyun             if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask |
1445*4882a593Smuzhiyun                               GCForeground | GCBackground | GCFillStyle |
1446*4882a593Smuzhiyun                               GCTile | GCStipple | GCTileStipXOrigin |
1447*4882a593Smuzhiyun                               GCTileStipYOrigin | GCFont |
1448*4882a593Smuzhiyun                               GCSubwindowMode | GCClipXOrigin |
1449*4882a593Smuzhiyun                               GCClipYOrigin | GCClipMask)) != Success) {
1450*4882a593Smuzhiyun                 FreeScratchGC(pGC);
1451*4882a593Smuzhiyun                 free(c->data);
1452*4882a593Smuzhiyun                 free(c);
1453*4882a593Smuzhiyun                 c = old_closure;
1454*4882a593Smuzhiyun                 err = BadAlloc;
1455*4882a593Smuzhiyun                 goto bail;
1456*4882a593Smuzhiyun             }
1457*4882a593Smuzhiyun             c->pGC = pGC;
1458*4882a593Smuzhiyun             ValidateGC(c->pDraw, c->pGC);
1459*4882a593Smuzhiyun 
1460*4882a593Smuzhiyun             ClientSleep(client, (ClientSleepProcPtr) doImageText, c);
1461*4882a593Smuzhiyun         }
1462*4882a593Smuzhiyun         return TRUE;
1463*4882a593Smuzhiyun     }
1464*4882a593Smuzhiyun     else if (lgerr != Successful) {
1465*4882a593Smuzhiyun         err = FontToXError(lgerr);
1466*4882a593Smuzhiyun         goto bail;
1467*4882a593Smuzhiyun     }
1468*4882a593Smuzhiyun     if (c->pDraw) {
1469*4882a593Smuzhiyun         if (c->reqType == X_ImageText8)
1470*4882a593Smuzhiyun             (*c->pGC->ops->ImageText8) (c->pDraw, c->pGC, c->xorg, c->yorg,
1471*4882a593Smuzhiyun                                         c->nChars, (char *) c->data);
1472*4882a593Smuzhiyun         else
1473*4882a593Smuzhiyun             (*c->pGC->ops->ImageText16) (c->pDraw, c->pGC, c->xorg, c->yorg,
1474*4882a593Smuzhiyun                                          c->nChars, (unsigned short *) c->data);
1475*4882a593Smuzhiyun     }
1476*4882a593Smuzhiyun 
1477*4882a593Smuzhiyun  bail:
1478*4882a593Smuzhiyun 
1479*4882a593Smuzhiyun     if (err != Success && c->client != serverClient) {
1480*4882a593Smuzhiyun         SendErrorToClient(c->client, c->reqType, 0, 0, err);
1481*4882a593Smuzhiyun     }
1482*4882a593Smuzhiyun     if (ClientIsAsleep(client)) {
1483*4882a593Smuzhiyun         ClientWakeup(c->client);
1484*4882a593Smuzhiyun         ChangeGC(NullClient, c->pGC, clearGCmask, clearGC);
1485*4882a593Smuzhiyun 
1486*4882a593Smuzhiyun         /* Unreference the font from the scratch GC */
1487*4882a593Smuzhiyun         CloseFont(c->pGC->font, (Font) 0);
1488*4882a593Smuzhiyun         c->pGC->font = NullFont;
1489*4882a593Smuzhiyun 
1490*4882a593Smuzhiyun         FreeScratchGC(c->pGC);
1491*4882a593Smuzhiyun         free(c->data);
1492*4882a593Smuzhiyun         free(c);
1493*4882a593Smuzhiyun     }
1494*4882a593Smuzhiyun     return TRUE;
1495*4882a593Smuzhiyun }
1496*4882a593Smuzhiyun 
1497*4882a593Smuzhiyun int
ImageText(ClientPtr client,DrawablePtr pDraw,GC * pGC,int nChars,unsigned char * data,int xorg,int yorg,int reqType,XID did)1498*4882a593Smuzhiyun ImageText(ClientPtr client, DrawablePtr pDraw, GC * pGC, int nChars,
1499*4882a593Smuzhiyun           unsigned char *data, int xorg, int yorg, int reqType, XID did)
1500*4882a593Smuzhiyun {
1501*4882a593Smuzhiyun     ITclosureRec local_closure;
1502*4882a593Smuzhiyun 
1503*4882a593Smuzhiyun     local_closure.client = client;
1504*4882a593Smuzhiyun     local_closure.pDraw = pDraw;
1505*4882a593Smuzhiyun     local_closure.pGC = pGC;
1506*4882a593Smuzhiyun     local_closure.nChars = nChars;
1507*4882a593Smuzhiyun     local_closure.data = data;
1508*4882a593Smuzhiyun     local_closure.xorg = xorg;
1509*4882a593Smuzhiyun     local_closure.yorg = yorg;
1510*4882a593Smuzhiyun     local_closure.reqType = reqType;
1511*4882a593Smuzhiyun     local_closure.did = did;
1512*4882a593Smuzhiyun 
1513*4882a593Smuzhiyun     (void) doImageText(client, &local_closure);
1514*4882a593Smuzhiyun     return Success;
1515*4882a593Smuzhiyun }
1516*4882a593Smuzhiyun 
1517*4882a593Smuzhiyun /* does the necessary magic to figure out the fpe type */
1518*4882a593Smuzhiyun static int
DetermineFPEType(const char * pathname)1519*4882a593Smuzhiyun DetermineFPEType(const char *pathname)
1520*4882a593Smuzhiyun {
1521*4882a593Smuzhiyun     int i;
1522*4882a593Smuzhiyun 
1523*4882a593Smuzhiyun     for (i = 0; i < num_fpe_types; i++) {
1524*4882a593Smuzhiyun         if ((*fpe_functions[i]->name_check) (pathname))
1525*4882a593Smuzhiyun             return i;
1526*4882a593Smuzhiyun     }
1527*4882a593Smuzhiyun     return -1;
1528*4882a593Smuzhiyun }
1529*4882a593Smuzhiyun 
1530*4882a593Smuzhiyun static void
FreeFontPath(FontPathElementPtr * list,int n,Bool force)1531*4882a593Smuzhiyun FreeFontPath(FontPathElementPtr * list, int n, Bool force)
1532*4882a593Smuzhiyun {
1533*4882a593Smuzhiyun     int i;
1534*4882a593Smuzhiyun 
1535*4882a593Smuzhiyun     for (i = 0; i < n; i++) {
1536*4882a593Smuzhiyun         if (force) {
1537*4882a593Smuzhiyun             /* Sanity check that all refcounts will be 0 by the time
1538*4882a593Smuzhiyun                we get to the end of the list. */
1539*4882a593Smuzhiyun             int found = 1;      /* the first reference is us */
1540*4882a593Smuzhiyun             int j;
1541*4882a593Smuzhiyun 
1542*4882a593Smuzhiyun             for (j = i + 1; j < n; j++) {
1543*4882a593Smuzhiyun                 if (list[j] == list[i])
1544*4882a593Smuzhiyun                     found++;
1545*4882a593Smuzhiyun             }
1546*4882a593Smuzhiyun             if (list[i]->refcount != found) {
1547*4882a593Smuzhiyun                 list[i]->refcount = found;      /* ensure it will get freed */
1548*4882a593Smuzhiyun             }
1549*4882a593Smuzhiyun         }
1550*4882a593Smuzhiyun         FreeFPE(list[i]);
1551*4882a593Smuzhiyun     }
1552*4882a593Smuzhiyun     free(list);
1553*4882a593Smuzhiyun }
1554*4882a593Smuzhiyun 
1555*4882a593Smuzhiyun static FontPathElementPtr
find_existing_fpe(FontPathElementPtr * list,int num,unsigned char * name,int len)1556*4882a593Smuzhiyun find_existing_fpe(FontPathElementPtr * list, int num, unsigned char *name,
1557*4882a593Smuzhiyun                   int len)
1558*4882a593Smuzhiyun {
1559*4882a593Smuzhiyun     FontPathElementPtr fpe;
1560*4882a593Smuzhiyun     int i;
1561*4882a593Smuzhiyun 
1562*4882a593Smuzhiyun     for (i = 0; i < num; i++) {
1563*4882a593Smuzhiyun         fpe = list[i];
1564*4882a593Smuzhiyun         if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0)
1565*4882a593Smuzhiyun             return fpe;
1566*4882a593Smuzhiyun     }
1567*4882a593Smuzhiyun     return (FontPathElementPtr) 0;
1568*4882a593Smuzhiyun }
1569*4882a593Smuzhiyun 
1570*4882a593Smuzhiyun static int
SetFontPathElements(int npaths,unsigned char * paths,int * bad,Bool persist)1571*4882a593Smuzhiyun SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist)
1572*4882a593Smuzhiyun {
1573*4882a593Smuzhiyun     int i, err = 0;
1574*4882a593Smuzhiyun     int valid_paths = 0;
1575*4882a593Smuzhiyun     unsigned int len;
1576*4882a593Smuzhiyun     unsigned char *cp = paths;
1577*4882a593Smuzhiyun     FontPathElementPtr fpe = NULL, *fplist;
1578*4882a593Smuzhiyun 
1579*4882a593Smuzhiyun     fplist = xallocarray(npaths, sizeof(FontPathElementPtr));
1580*4882a593Smuzhiyun     if (!fplist) {
1581*4882a593Smuzhiyun         *bad = 0;
1582*4882a593Smuzhiyun         return BadAlloc;
1583*4882a593Smuzhiyun     }
1584*4882a593Smuzhiyun     for (i = 0; i < num_fpe_types; i++) {
1585*4882a593Smuzhiyun         if (fpe_functions[i]->set_path_hook)
1586*4882a593Smuzhiyun             (*fpe_functions[i]->set_path_hook) ();
1587*4882a593Smuzhiyun     }
1588*4882a593Smuzhiyun     for (i = 0; i < npaths; i++) {
1589*4882a593Smuzhiyun         len = (unsigned int) (*cp++);
1590*4882a593Smuzhiyun 
1591*4882a593Smuzhiyun         if (len == 0) {
1592*4882a593Smuzhiyun             if (persist)
1593*4882a593Smuzhiyun                 ErrorF
1594*4882a593Smuzhiyun                     ("[dix] Removing empty element from the valid list of fontpaths\n");
1595*4882a593Smuzhiyun             err = BadValue;
1596*4882a593Smuzhiyun         }
1597*4882a593Smuzhiyun         else {
1598*4882a593Smuzhiyun             /* if it's already in our active list, just reset it */
1599*4882a593Smuzhiyun             /*
1600*4882a593Smuzhiyun              * note that this can miss FPE's in limbo -- may be worth catching
1601*4882a593Smuzhiyun              * them, though it'd muck up refcounting
1602*4882a593Smuzhiyun              */
1603*4882a593Smuzhiyun             fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len);
1604*4882a593Smuzhiyun             if (fpe) {
1605*4882a593Smuzhiyun                 err = (*fpe_functions[fpe->type]->reset_fpe) (fpe);
1606*4882a593Smuzhiyun                 if (err == Successful) {
1607*4882a593Smuzhiyun                     UseFPE(fpe);        /* since it'll be decref'd later when freed
1608*4882a593Smuzhiyun                                          * from the old list */
1609*4882a593Smuzhiyun                 }
1610*4882a593Smuzhiyun                 else
1611*4882a593Smuzhiyun                     fpe = 0;
1612*4882a593Smuzhiyun             }
1613*4882a593Smuzhiyun             /* if error or can't do it, act like it's a new one */
1614*4882a593Smuzhiyun             if (!fpe) {
1615*4882a593Smuzhiyun                 char *name;
1616*4882a593Smuzhiyun                 fpe = malloc(sizeof(FontPathElementRec));
1617*4882a593Smuzhiyun                 if (!fpe) {
1618*4882a593Smuzhiyun                     err = BadAlloc;
1619*4882a593Smuzhiyun                     goto bail;
1620*4882a593Smuzhiyun                 }
1621*4882a593Smuzhiyun                 name = malloc(len + 1);
1622*4882a593Smuzhiyun                 if (!name) {
1623*4882a593Smuzhiyun                     free(fpe);
1624*4882a593Smuzhiyun                     err = BadAlloc;
1625*4882a593Smuzhiyun                     goto bail;
1626*4882a593Smuzhiyun                 }
1627*4882a593Smuzhiyun                 fpe->refcount = 1;
1628*4882a593Smuzhiyun 
1629*4882a593Smuzhiyun                 strncpy(name, (char *) cp, (int) len);
1630*4882a593Smuzhiyun                 name[len] = '\0';
1631*4882a593Smuzhiyun                 fpe->name = name;
1632*4882a593Smuzhiyun                 fpe->name_length = len;
1633*4882a593Smuzhiyun                 fpe->type = DetermineFPEType(fpe->name);
1634*4882a593Smuzhiyun                 if (fpe->type == -1)
1635*4882a593Smuzhiyun                     err = BadValue;
1636*4882a593Smuzhiyun                 else
1637*4882a593Smuzhiyun                     err = (*fpe_functions[fpe->type]->init_fpe) (fpe);
1638*4882a593Smuzhiyun                 if (err != Successful) {
1639*4882a593Smuzhiyun                     if (persist) {
1640*4882a593Smuzhiyun                         DebugF
1641*4882a593Smuzhiyun                             ("[dix] Could not init font path element %s, removing from list!\n",
1642*4882a593Smuzhiyun                              fpe->name);
1643*4882a593Smuzhiyun                     }
1644*4882a593Smuzhiyun                     free((void *) fpe->name);
1645*4882a593Smuzhiyun                     free(fpe);
1646*4882a593Smuzhiyun                 }
1647*4882a593Smuzhiyun             }
1648*4882a593Smuzhiyun         }
1649*4882a593Smuzhiyun         if (err != Successful) {
1650*4882a593Smuzhiyun             if (!persist)
1651*4882a593Smuzhiyun                 goto bail;
1652*4882a593Smuzhiyun         }
1653*4882a593Smuzhiyun         else {
1654*4882a593Smuzhiyun             fplist[valid_paths++] = fpe;
1655*4882a593Smuzhiyun         }
1656*4882a593Smuzhiyun         cp += len;
1657*4882a593Smuzhiyun     }
1658*4882a593Smuzhiyun 
1659*4882a593Smuzhiyun     FreeFontPath(font_path_elements, num_fpes, FALSE);
1660*4882a593Smuzhiyun     font_path_elements = fplist;
1661*4882a593Smuzhiyun     if (patternCache)
1662*4882a593Smuzhiyun         xfont2_empty_font_pattern_cache(patternCache);
1663*4882a593Smuzhiyun     num_fpes = valid_paths;
1664*4882a593Smuzhiyun 
1665*4882a593Smuzhiyun     return Success;
1666*4882a593Smuzhiyun  bail:
1667*4882a593Smuzhiyun     *bad = i;
1668*4882a593Smuzhiyun     while (--valid_paths >= 0)
1669*4882a593Smuzhiyun         FreeFPE(fplist[valid_paths]);
1670*4882a593Smuzhiyun     free(fplist);
1671*4882a593Smuzhiyun     return FontToXError(err);
1672*4882a593Smuzhiyun }
1673*4882a593Smuzhiyun 
1674*4882a593Smuzhiyun int
SetFontPath(ClientPtr client,int npaths,unsigned char * paths)1675*4882a593Smuzhiyun SetFontPath(ClientPtr client, int npaths, unsigned char *paths)
1676*4882a593Smuzhiyun {
1677*4882a593Smuzhiyun     int err = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
1678*4882a593Smuzhiyun 
1679*4882a593Smuzhiyun     if (err != Success)
1680*4882a593Smuzhiyun         return err;
1681*4882a593Smuzhiyun 
1682*4882a593Smuzhiyun     if (npaths == 0) {
1683*4882a593Smuzhiyun         if (SetDefaultFontPath(defaultFontPath) != Success)
1684*4882a593Smuzhiyun             return BadValue;
1685*4882a593Smuzhiyun     }
1686*4882a593Smuzhiyun     else {
1687*4882a593Smuzhiyun         int bad;
1688*4882a593Smuzhiyun 
1689*4882a593Smuzhiyun         err = SetFontPathElements(npaths, paths, &bad, FALSE);
1690*4882a593Smuzhiyun         client->errorValue = bad;
1691*4882a593Smuzhiyun     }
1692*4882a593Smuzhiyun     return err;
1693*4882a593Smuzhiyun }
1694*4882a593Smuzhiyun 
1695*4882a593Smuzhiyun int
SetDefaultFontPath(const char * path)1696*4882a593Smuzhiyun SetDefaultFontPath(const char *path)
1697*4882a593Smuzhiyun {
1698*4882a593Smuzhiyun     const char *start, *end;
1699*4882a593Smuzhiyun     char *temp_path;
1700*4882a593Smuzhiyun     unsigned char *cp, *pp, *nump, *newpath;
1701*4882a593Smuzhiyun     int num = 1, len, err, size = 0, bad;
1702*4882a593Smuzhiyun 
1703*4882a593Smuzhiyun     /* ensure temp_path contains "built-ins" */
1704*4882a593Smuzhiyun     start = path;
1705*4882a593Smuzhiyun     while (1) {
1706*4882a593Smuzhiyun         start = strstr(start, "built-ins");
1707*4882a593Smuzhiyun         if (start == NULL)
1708*4882a593Smuzhiyun             break;
1709*4882a593Smuzhiyun         end = start + strlen("built-ins");
1710*4882a593Smuzhiyun         if ((start == path || start[-1] == ',') && (!*end || *end == ','))
1711*4882a593Smuzhiyun             break;
1712*4882a593Smuzhiyun         start = end;
1713*4882a593Smuzhiyun     }
1714*4882a593Smuzhiyun     if (!start) {
1715*4882a593Smuzhiyun         if (asprintf(&temp_path, "%s%sbuilt-ins", path, *path ? "," : "")
1716*4882a593Smuzhiyun             == -1)
1717*4882a593Smuzhiyun             temp_path = NULL;
1718*4882a593Smuzhiyun     }
1719*4882a593Smuzhiyun     else {
1720*4882a593Smuzhiyun         temp_path = strdup(path);
1721*4882a593Smuzhiyun     }
1722*4882a593Smuzhiyun     if (!temp_path)
1723*4882a593Smuzhiyun         return BadAlloc;
1724*4882a593Smuzhiyun 
1725*4882a593Smuzhiyun     /* get enough for string, plus values -- use up commas */
1726*4882a593Smuzhiyun     len = strlen(temp_path) + 1;
1727*4882a593Smuzhiyun     nump = cp = newpath = malloc(len);
1728*4882a593Smuzhiyun     if (!newpath) {
1729*4882a593Smuzhiyun         free(temp_path);
1730*4882a593Smuzhiyun         return BadAlloc;
1731*4882a593Smuzhiyun     }
1732*4882a593Smuzhiyun     pp = (unsigned char *) temp_path;
1733*4882a593Smuzhiyun     cp++;
1734*4882a593Smuzhiyun     while (*pp) {
1735*4882a593Smuzhiyun         if (*pp == ',') {
1736*4882a593Smuzhiyun             *nump = (unsigned char) size;
1737*4882a593Smuzhiyun             nump = cp++;
1738*4882a593Smuzhiyun             pp++;
1739*4882a593Smuzhiyun             num++;
1740*4882a593Smuzhiyun             size = 0;
1741*4882a593Smuzhiyun         }
1742*4882a593Smuzhiyun         else {
1743*4882a593Smuzhiyun             *cp++ = *pp++;
1744*4882a593Smuzhiyun             size++;
1745*4882a593Smuzhiyun         }
1746*4882a593Smuzhiyun     }
1747*4882a593Smuzhiyun     *nump = (unsigned char) size;
1748*4882a593Smuzhiyun 
1749*4882a593Smuzhiyun     err = SetFontPathElements(num, newpath, &bad, TRUE);
1750*4882a593Smuzhiyun 
1751*4882a593Smuzhiyun     free(newpath);
1752*4882a593Smuzhiyun     free(temp_path);
1753*4882a593Smuzhiyun 
1754*4882a593Smuzhiyun     return err;
1755*4882a593Smuzhiyun }
1756*4882a593Smuzhiyun 
1757*4882a593Smuzhiyun int
GetFontPath(ClientPtr client,int * count,int * length,unsigned char ** result)1758*4882a593Smuzhiyun GetFontPath(ClientPtr client, int *count, int *length, unsigned char **result)
1759*4882a593Smuzhiyun {
1760*4882a593Smuzhiyun     int i;
1761*4882a593Smuzhiyun     unsigned char *c;
1762*4882a593Smuzhiyun     int len;
1763*4882a593Smuzhiyun     FontPathElementPtr fpe;
1764*4882a593Smuzhiyun 
1765*4882a593Smuzhiyun     i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
1766*4882a593Smuzhiyun     if (i != Success)
1767*4882a593Smuzhiyun         return i;
1768*4882a593Smuzhiyun 
1769*4882a593Smuzhiyun     len = 0;
1770*4882a593Smuzhiyun     for (i = 0; i < num_fpes; i++) {
1771*4882a593Smuzhiyun         fpe = font_path_elements[i];
1772*4882a593Smuzhiyun         len += fpe->name_length + 1;
1773*4882a593Smuzhiyun     }
1774*4882a593Smuzhiyun     c = realloc(font_path_string, len);
1775*4882a593Smuzhiyun     if (c == NULL) {
1776*4882a593Smuzhiyun         free(font_path_string);
1777*4882a593Smuzhiyun         font_path_string = NULL;
1778*4882a593Smuzhiyun         return BadAlloc;
1779*4882a593Smuzhiyun     }
1780*4882a593Smuzhiyun 
1781*4882a593Smuzhiyun     font_path_string = c;
1782*4882a593Smuzhiyun     *length = 0;
1783*4882a593Smuzhiyun     for (i = 0; i < num_fpes; i++) {
1784*4882a593Smuzhiyun         fpe = font_path_elements[i];
1785*4882a593Smuzhiyun         *c = fpe->name_length;
1786*4882a593Smuzhiyun         *length += *c++;
1787*4882a593Smuzhiyun         memmove(c, fpe->name, fpe->name_length);
1788*4882a593Smuzhiyun         c += fpe->name_length;
1789*4882a593Smuzhiyun     }
1790*4882a593Smuzhiyun     *count = num_fpes;
1791*4882a593Smuzhiyun     *result = font_path_string;
1792*4882a593Smuzhiyun     return Success;
1793*4882a593Smuzhiyun }
1794*4882a593Smuzhiyun 
1795*4882a593Smuzhiyun void
DeleteClientFontStuff(ClientPtr client)1796*4882a593Smuzhiyun DeleteClientFontStuff(ClientPtr client)
1797*4882a593Smuzhiyun {
1798*4882a593Smuzhiyun     int i;
1799*4882a593Smuzhiyun     FontPathElementPtr fpe;
1800*4882a593Smuzhiyun 
1801*4882a593Smuzhiyun     for (i = 0; i < num_fpes; i++) {
1802*4882a593Smuzhiyun         fpe = font_path_elements[i];
1803*4882a593Smuzhiyun         if (fpe_functions[fpe->type]->client_died)
1804*4882a593Smuzhiyun             (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe);
1805*4882a593Smuzhiyun     }
1806*4882a593Smuzhiyun }
1807*4882a593Smuzhiyun 
1808*4882a593Smuzhiyun static int
register_fpe_funcs(const xfont2_fpe_funcs_rec * funcs)1809*4882a593Smuzhiyun register_fpe_funcs(const xfont2_fpe_funcs_rec *funcs)
1810*4882a593Smuzhiyun {
1811*4882a593Smuzhiyun     xfont2_fpe_funcs_rec const **new;
1812*4882a593Smuzhiyun 
1813*4882a593Smuzhiyun     /* grow the list */
1814*4882a593Smuzhiyun     new = reallocarray(fpe_functions, num_fpe_types + 1, sizeof(xfont2_fpe_funcs_ptr));
1815*4882a593Smuzhiyun     if (!new)
1816*4882a593Smuzhiyun         return -1;
1817*4882a593Smuzhiyun     fpe_functions = new;
1818*4882a593Smuzhiyun 
1819*4882a593Smuzhiyun     fpe_functions[num_fpe_types] = funcs;
1820*4882a593Smuzhiyun 
1821*4882a593Smuzhiyun     return num_fpe_types++;
1822*4882a593Smuzhiyun }
1823*4882a593Smuzhiyun 
1824*4882a593Smuzhiyun static unsigned long
get_server_generation(void)1825*4882a593Smuzhiyun get_server_generation(void)
1826*4882a593Smuzhiyun {
1827*4882a593Smuzhiyun     return serverGeneration;
1828*4882a593Smuzhiyun }
1829*4882a593Smuzhiyun 
1830*4882a593Smuzhiyun static void *
get_server_client(void)1831*4882a593Smuzhiyun get_server_client(void)
1832*4882a593Smuzhiyun {
1833*4882a593Smuzhiyun     return serverClient;
1834*4882a593Smuzhiyun }
1835*4882a593Smuzhiyun 
1836*4882a593Smuzhiyun static int
get_default_point_size(void)1837*4882a593Smuzhiyun get_default_point_size(void)
1838*4882a593Smuzhiyun {
1839*4882a593Smuzhiyun     return 120;
1840*4882a593Smuzhiyun }
1841*4882a593Smuzhiyun 
1842*4882a593Smuzhiyun static FontResolutionPtr
get_client_resolutions(int * num)1843*4882a593Smuzhiyun get_client_resolutions(int *num)
1844*4882a593Smuzhiyun {
1845*4882a593Smuzhiyun     static struct _FontResolution res;
1846*4882a593Smuzhiyun     ScreenPtr pScreen;
1847*4882a593Smuzhiyun 
1848*4882a593Smuzhiyun     pScreen = screenInfo.screens[0];
1849*4882a593Smuzhiyun     res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth;
1850*4882a593Smuzhiyun     /*
1851*4882a593Smuzhiyun      * XXX - we'll want this as long as bitmap instances are prevalent
1852*4882a593Smuzhiyun      so that we can match them from scalable fonts
1853*4882a593Smuzhiyun      */
1854*4882a593Smuzhiyun     if (res.x_resolution < 88)
1855*4882a593Smuzhiyun         res.x_resolution = 75;
1856*4882a593Smuzhiyun     else
1857*4882a593Smuzhiyun         res.x_resolution = 100;
1858*4882a593Smuzhiyun     res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight;
1859*4882a593Smuzhiyun     if (res.y_resolution < 88)
1860*4882a593Smuzhiyun         res.y_resolution = 75;
1861*4882a593Smuzhiyun     else
1862*4882a593Smuzhiyun         res.y_resolution = 100;
1863*4882a593Smuzhiyun     res.point_size = 120;
1864*4882a593Smuzhiyun     *num = 1;
1865*4882a593Smuzhiyun     return &res;
1866*4882a593Smuzhiyun }
1867*4882a593Smuzhiyun 
1868*4882a593Smuzhiyun void
FreeFonts(void)1869*4882a593Smuzhiyun FreeFonts(void)
1870*4882a593Smuzhiyun {
1871*4882a593Smuzhiyun     if (patternCache) {
1872*4882a593Smuzhiyun         xfont2_free_font_pattern_cache(patternCache);
1873*4882a593Smuzhiyun         patternCache = 0;
1874*4882a593Smuzhiyun     }
1875*4882a593Smuzhiyun     FreeFontPath(font_path_elements, num_fpes, TRUE);
1876*4882a593Smuzhiyun     font_path_elements = 0;
1877*4882a593Smuzhiyun     num_fpes = 0;
1878*4882a593Smuzhiyun     free(fpe_functions);
1879*4882a593Smuzhiyun     num_fpe_types = 0;
1880*4882a593Smuzhiyun     fpe_functions = NULL;
1881*4882a593Smuzhiyun }
1882*4882a593Smuzhiyun 
1883*4882a593Smuzhiyun /* convenience functions for FS interface */
1884*4882a593Smuzhiyun 
1885*4882a593Smuzhiyun static FontPtr
find_old_font(XID id)1886*4882a593Smuzhiyun find_old_font(XID id)
1887*4882a593Smuzhiyun {
1888*4882a593Smuzhiyun     void *pFont;
1889*4882a593Smuzhiyun 
1890*4882a593Smuzhiyun     dixLookupResourceByType(&pFont, id, RT_NONE, serverClient, DixReadAccess);
1891*4882a593Smuzhiyun     return (FontPtr) pFont;
1892*4882a593Smuzhiyun }
1893*4882a593Smuzhiyun 
1894*4882a593Smuzhiyun static Font
get_new_font_client_id(void)1895*4882a593Smuzhiyun get_new_font_client_id(void)
1896*4882a593Smuzhiyun {
1897*4882a593Smuzhiyun     return FakeClientID(0);
1898*4882a593Smuzhiyun }
1899*4882a593Smuzhiyun 
1900*4882a593Smuzhiyun static int
store_font_Client_font(FontPtr pfont,Font id)1901*4882a593Smuzhiyun store_font_Client_font(FontPtr pfont, Font id)
1902*4882a593Smuzhiyun {
1903*4882a593Smuzhiyun     return AddResource(id, RT_NONE, (void *) pfont);
1904*4882a593Smuzhiyun }
1905*4882a593Smuzhiyun 
1906*4882a593Smuzhiyun static void
delete_font_client_id(Font id)1907*4882a593Smuzhiyun delete_font_client_id(Font id)
1908*4882a593Smuzhiyun {
1909*4882a593Smuzhiyun     FreeResource(id, RT_NONE);
1910*4882a593Smuzhiyun }
1911*4882a593Smuzhiyun 
1912*4882a593Smuzhiyun static int
_client_auth_generation(ClientPtr client)1913*4882a593Smuzhiyun _client_auth_generation(ClientPtr client)
1914*4882a593Smuzhiyun {
1915*4882a593Smuzhiyun     return 0;
1916*4882a593Smuzhiyun }
1917*4882a593Smuzhiyun 
1918*4882a593Smuzhiyun static int fs_handlers_installed = 0;
1919*4882a593Smuzhiyun static unsigned int last_server_gen;
1920*4882a593Smuzhiyun 
fs_block_handler(void * blockData,void * timeout)1921*4882a593Smuzhiyun static void fs_block_handler(void *blockData, void *timeout)
1922*4882a593Smuzhiyun {
1923*4882a593Smuzhiyun     FontBlockHandlerProcPtr block_handler = blockData;
1924*4882a593Smuzhiyun 
1925*4882a593Smuzhiyun     (*block_handler)(timeout);
1926*4882a593Smuzhiyun }
1927*4882a593Smuzhiyun 
1928*4882a593Smuzhiyun struct fs_fd_entry {
1929*4882a593Smuzhiyun     struct xorg_list            entry;
1930*4882a593Smuzhiyun     int                         fd;
1931*4882a593Smuzhiyun     void                        *data;
1932*4882a593Smuzhiyun     FontFdHandlerProcPtr        handler;
1933*4882a593Smuzhiyun };
1934*4882a593Smuzhiyun 
1935*4882a593Smuzhiyun static void
fs_fd_handler(int fd,int ready,void * data)1936*4882a593Smuzhiyun fs_fd_handler(int fd, int ready, void *data)
1937*4882a593Smuzhiyun {
1938*4882a593Smuzhiyun     struct fs_fd_entry    *entry = data;
1939*4882a593Smuzhiyun 
1940*4882a593Smuzhiyun     entry->handler(fd, entry->data);
1941*4882a593Smuzhiyun }
1942*4882a593Smuzhiyun 
1943*4882a593Smuzhiyun static struct xorg_list fs_fd_list;
1944*4882a593Smuzhiyun 
1945*4882a593Smuzhiyun static int
add_fs_fd(int fd,FontFdHandlerProcPtr handler,void * data)1946*4882a593Smuzhiyun add_fs_fd(int fd, FontFdHandlerProcPtr handler, void *data)
1947*4882a593Smuzhiyun {
1948*4882a593Smuzhiyun     struct fs_fd_entry  *entry = calloc(1, sizeof (struct fs_fd_entry));
1949*4882a593Smuzhiyun 
1950*4882a593Smuzhiyun     if (!entry)
1951*4882a593Smuzhiyun         return FALSE;
1952*4882a593Smuzhiyun 
1953*4882a593Smuzhiyun     entry->fd = fd;
1954*4882a593Smuzhiyun     entry->data = data;
1955*4882a593Smuzhiyun     entry->handler = handler;
1956*4882a593Smuzhiyun     if (!SetNotifyFd(fd, fs_fd_handler, X_NOTIFY_READ, entry)) {
1957*4882a593Smuzhiyun         free(entry);
1958*4882a593Smuzhiyun         return FALSE;
1959*4882a593Smuzhiyun     }
1960*4882a593Smuzhiyun     xorg_list_add(&entry->entry, &fs_fd_list);
1961*4882a593Smuzhiyun     return TRUE;
1962*4882a593Smuzhiyun }
1963*4882a593Smuzhiyun 
1964*4882a593Smuzhiyun static void
remove_fs_fd(int fd)1965*4882a593Smuzhiyun remove_fs_fd(int fd)
1966*4882a593Smuzhiyun {
1967*4882a593Smuzhiyun     struct fs_fd_entry  *entry, *temp;
1968*4882a593Smuzhiyun 
1969*4882a593Smuzhiyun     xorg_list_for_each_entry_safe(entry, temp, &fs_fd_list, entry) {
1970*4882a593Smuzhiyun         if (entry->fd == fd) {
1971*4882a593Smuzhiyun             xorg_list_del(&entry->entry);
1972*4882a593Smuzhiyun             free(entry);
1973*4882a593Smuzhiyun             break;
1974*4882a593Smuzhiyun         }
1975*4882a593Smuzhiyun     }
1976*4882a593Smuzhiyun     RemoveNotifyFd(fd);
1977*4882a593Smuzhiyun }
1978*4882a593Smuzhiyun 
1979*4882a593Smuzhiyun static void
adjust_fs_wait_for_delay(void * wt,unsigned long newdelay)1980*4882a593Smuzhiyun adjust_fs_wait_for_delay(void *wt, unsigned long newdelay)
1981*4882a593Smuzhiyun {
1982*4882a593Smuzhiyun     AdjustWaitForDelay(wt, newdelay);
1983*4882a593Smuzhiyun }
1984*4882a593Smuzhiyun 
1985*4882a593Smuzhiyun static int
_init_fs_handlers(FontPathElementPtr fpe,FontBlockHandlerProcPtr block_handler)1986*4882a593Smuzhiyun _init_fs_handlers(FontPathElementPtr fpe, FontBlockHandlerProcPtr block_handler)
1987*4882a593Smuzhiyun {
1988*4882a593Smuzhiyun     /* if server has reset, make sure the b&w handlers are reinstalled */
1989*4882a593Smuzhiyun     if (last_server_gen < serverGeneration) {
1990*4882a593Smuzhiyun         last_server_gen = serverGeneration;
1991*4882a593Smuzhiyun         fs_handlers_installed = 0;
1992*4882a593Smuzhiyun     }
1993*4882a593Smuzhiyun     if (fs_handlers_installed == 0) {
1994*4882a593Smuzhiyun         if (!RegisterBlockAndWakeupHandlers(fs_block_handler,
1995*4882a593Smuzhiyun                                             FontWakeup, (void *) block_handler))
1996*4882a593Smuzhiyun             return AllocError;
1997*4882a593Smuzhiyun         xorg_list_init(&fs_fd_list);
1998*4882a593Smuzhiyun         fs_handlers_installed++;
1999*4882a593Smuzhiyun     }
2000*4882a593Smuzhiyun     QueueFontWakeup(fpe);
2001*4882a593Smuzhiyun     return Successful;
2002*4882a593Smuzhiyun }
2003*4882a593Smuzhiyun 
2004*4882a593Smuzhiyun static void
_remove_fs_handlers(FontPathElementPtr fpe,FontBlockHandlerProcPtr block_handler,Bool all)2005*4882a593Smuzhiyun _remove_fs_handlers(FontPathElementPtr fpe, FontBlockHandlerProcPtr block_handler,
2006*4882a593Smuzhiyun                     Bool all)
2007*4882a593Smuzhiyun {
2008*4882a593Smuzhiyun     if (all) {
2009*4882a593Smuzhiyun         /* remove the handlers if no one else is using them */
2010*4882a593Smuzhiyun         if (--fs_handlers_installed == 0) {
2011*4882a593Smuzhiyun             RemoveBlockAndWakeupHandlers(fs_block_handler, FontWakeup,
2012*4882a593Smuzhiyun                                          (void *) block_handler);
2013*4882a593Smuzhiyun         }
2014*4882a593Smuzhiyun     }
2015*4882a593Smuzhiyun     RemoveFontWakeup(fpe);
2016*4882a593Smuzhiyun }
2017*4882a593Smuzhiyun 
wrap_time_in_millis(void)2018*4882a593Smuzhiyun static uint32_t wrap_time_in_millis(void)
2019*4882a593Smuzhiyun {
2020*4882a593Smuzhiyun     return GetTimeInMillis();
2021*4882a593Smuzhiyun }
2022*4882a593Smuzhiyun 
2023*4882a593Smuzhiyun static const xfont2_client_funcs_rec xfont2_client_funcs = {
2024*4882a593Smuzhiyun     .version = XFONT2_CLIENT_FUNCS_VERSION,
2025*4882a593Smuzhiyun     .client_auth_generation = _client_auth_generation,
2026*4882a593Smuzhiyun     .client_signal = ClientSignal,
2027*4882a593Smuzhiyun     .delete_font_client_id = delete_font_client_id,
2028*4882a593Smuzhiyun     .verrorf = VErrorF,
2029*4882a593Smuzhiyun     .find_old_font = find_old_font,
2030*4882a593Smuzhiyun     .get_client_resolutions = get_client_resolutions,
2031*4882a593Smuzhiyun     .get_default_point_size = get_default_point_size,
2032*4882a593Smuzhiyun     .get_new_font_client_id = get_new_font_client_id,
2033*4882a593Smuzhiyun     .get_time_in_millis = wrap_time_in_millis,
2034*4882a593Smuzhiyun     .init_fs_handlers = _init_fs_handlers,
2035*4882a593Smuzhiyun     .register_fpe_funcs = register_fpe_funcs,
2036*4882a593Smuzhiyun     .remove_fs_handlers = _remove_fs_handlers,
2037*4882a593Smuzhiyun     .get_server_client = get_server_client,
2038*4882a593Smuzhiyun     .set_font_authorizations = set_font_authorizations,
2039*4882a593Smuzhiyun     .store_font_client_font = store_font_Client_font,
2040*4882a593Smuzhiyun     .make_atom = MakeAtom,
2041*4882a593Smuzhiyun     .valid_atom = ValidAtom,
2042*4882a593Smuzhiyun     .name_for_atom = NameForAtom,
2043*4882a593Smuzhiyun     .get_server_generation = get_server_generation,
2044*4882a593Smuzhiyun     .add_fs_fd = add_fs_fd,
2045*4882a593Smuzhiyun     .remove_fs_fd = remove_fs_fd,
2046*4882a593Smuzhiyun     .adjust_fs_wait_for_delay = adjust_fs_wait_for_delay,
2047*4882a593Smuzhiyun };
2048*4882a593Smuzhiyun 
2049*4882a593Smuzhiyun xfont2_pattern_cache_ptr fontPatternCache;
2050*4882a593Smuzhiyun 
2051*4882a593Smuzhiyun void
InitFonts(void)2052*4882a593Smuzhiyun InitFonts(void)
2053*4882a593Smuzhiyun {
2054*4882a593Smuzhiyun     if (fontPatternCache)
2055*4882a593Smuzhiyun 	xfont2_free_font_pattern_cache(fontPatternCache);
2056*4882a593Smuzhiyun     fontPatternCache = xfont2_make_font_pattern_cache();
2057*4882a593Smuzhiyun     xfont2_init(&xfont2_client_funcs);
2058*4882a593Smuzhiyun }
2059