Bug Summary

File:dix/dixfonts.c
Location:line 683, column 25
Description:Value stored to 'err' is never read

Annotated Source Code

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