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