~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/Xserver/dix/dixfonts.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

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