Bug Summary

File:dix/dixfonts.c
Location:line 1492, column 9
Description:Argument to free() is the address of the local variable 'local_closure', which is not memory allocated by malloc()

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