105b261ecSmrg/************************************************************************ 205b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 305b261ecSmrg 405b261ecSmrg All Rights Reserved 505b261ecSmrg 605b261ecSmrgPermission to use, copy, modify, and distribute this software and its 705b261ecSmrgdocumentation for any purpose and without fee is hereby granted, 805b261ecSmrgprovided that the above copyright notice appear in all copies and that 905b261ecSmrgboth that copyright notice and this permission notice appear in 1005b261ecSmrgsupporting documentation, and that the name of Digital not be 1105b261ecSmrgused in advertising or publicity pertaining to distribution of the 1205b261ecSmrgsoftware without specific, written prior permission. 1305b261ecSmrg 1405b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1505b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 1605b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 1705b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 1805b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 1905b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2005b261ecSmrgSOFTWARE. 2105b261ecSmrg 2205b261ecSmrg************************************************************************/ 2305b261ecSmrg/* The panoramix components contained the following notice */ 2405b261ecSmrg/* 2505b261ecSmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. 2605b261ecSmrg 2705b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy 2805b261ecSmrgof this software and associated documentation files (the "Software"), to deal 2905b261ecSmrgin the Software without restriction, including without limitation the rights 3005b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell 3105b261ecSmrgcopies of the Software. 3205b261ecSmrg 3305b261ecSmrgThe above copyright notice and this permission notice shall be included in 3405b261ecSmrgall copies or substantial portions of the Software. 3505b261ecSmrg 3605b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 3705b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 3805b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 3905b261ecSmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, 4005b261ecSmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, 4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 4205b261ecSmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 4305b261ecSmrg 4405b261ecSmrgExcept as contained in this notice, the name of Digital Equipment Corporation 4505b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use or other 4605b261ecSmrgdealings in this Software without prior written authorization from Digital 4705b261ecSmrgEquipment Corporation. 4805b261ecSmrg 4905b261ecSmrg******************************************************************/ 5005b261ecSmrg 5105b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 5205b261ecSmrg#include <dix-config.h> 5305b261ecSmrg#endif 5405b261ecSmrg 5505b261ecSmrg#include <X11/X.h> 5605b261ecSmrg#include <X11/Xmd.h> 5705b261ecSmrg#include <X11/Xproto.h> 5805b261ecSmrg#include "scrnintstr.h" 5905b261ecSmrg#include "resource.h" 6005b261ecSmrg#include "dixstruct.h" 6105b261ecSmrg#include "cursorstr.h" 6205b261ecSmrg#include "misc.h" 6305b261ecSmrg#include "opaque.h" 6405b261ecSmrg#include "dixfontstr.h" 6505b261ecSmrg#include "closestr.h" 6605b261ecSmrg#include "dixfont.h" 674642e01fSmrg#include "xace.h" 687e31ba66Smrg#include <X11/fonts/libxfont2.h> 6905b261ecSmrg 7005b261ecSmrg#ifdef XF86BIGFONT 716747b715Smrg#include "xf86bigfontsrv.h" 7205b261ecSmrg#endif 7305b261ecSmrg 74f7df2e56Smrgextern void *fosNaturalParams; 7505b261ecSmrgextern FontPtr defaultFont; 7605b261ecSmrg 7705b261ecSmrgstatic FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0; 78f7df2e56Smrgstatic int num_fpes = 0; 797e31ba66Smrgstatic xfont2_fpe_funcs_rec const **fpe_functions; 80f7df2e56Smrgstatic int num_fpe_types = 0; 8105b261ecSmrg 8205b261ecSmrgstatic unsigned char *font_path_string; 8305b261ecSmrg 84f7df2e56Smrgstatic int num_slept_fpes = 0; 85f7df2e56Smrgstatic int size_slept_fpes = 0; 8605b261ecSmrgstatic FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0; 877e31ba66Smrgstatic xfont2_pattern_cache_ptr patternCache; 8805b261ecSmrg 894642e01fSmrgstatic int 904642e01fSmrgFontToXError(int err) 9105b261ecSmrg{ 9205b261ecSmrg switch (err) { 9305b261ecSmrg case Successful: 94f7df2e56Smrg return Success; 9505b261ecSmrg case AllocError: 96f7df2e56Smrg return BadAlloc; 9705b261ecSmrg case BadFontName: 98f7df2e56Smrg return BadName; 9905b261ecSmrg case BadFontPath: 100f7df2e56Smrg case BadFontFormat: /* is there something better? */ 10105b261ecSmrg case BadCharRange: 102f7df2e56Smrg return BadValue; 10305b261ecSmrg default: 104f7df2e56Smrg return err; 10505b261ecSmrg } 10605b261ecSmrg} 10705b261ecSmrg 1084642e01fSmrgstatic int 1094642e01fSmrgLoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size, 110f7df2e56Smrg unsigned char *data) 1114642e01fSmrg{ 1127e31ba66Smrg if (fpe_functions[pfont->fpe->type]->load_glyphs) 1137e31ba66Smrg return (*fpe_functions[pfont->fpe->type]->load_glyphs) 114f7df2e56Smrg (client, pfont, 0, nchars, item_size, data); 1154642e01fSmrg else 116f7df2e56Smrg return Successful; 117f7df2e56Smrg} 118f7df2e56Smrg 119f7df2e56Smrgvoid 1207e31ba66SmrgGetGlyphs(FontPtr font, unsigned long count, unsigned char *chars, 1217e31ba66Smrg FontEncoding fontEncoding, 1227e31ba66Smrg unsigned long *glyphcount, /* RETURN */ 1237e31ba66Smrg CharInfoPtr *glyphs) /* RETURN */ 124f7df2e56Smrg{ 125f7df2e56Smrg (*font->get_glyphs) (font, count, chars, fontEncoding, glyphcount, glyphs); 1264642e01fSmrg} 12705b261ecSmrg 12805b261ecSmrg/* 12905b261ecSmrg * adding RT_FONT prevents conflict with default cursor font 13005b261ecSmrg */ 13105b261ecSmrgBool 132f7df2e56SmrgSetDefaultFont(const char *defaultfontname) 13305b261ecSmrg{ 134f7df2e56Smrg int err; 135f7df2e56Smrg FontPtr pf; 136f7df2e56Smrg XID fid; 13705b261ecSmrg 13805b261ecSmrg fid = FakeClientID(0); 13905b261ecSmrg err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync, 140f7df2e56Smrg (unsigned) strlen(defaultfontname), defaultfontname); 14105b261ecSmrg if (err != Success) 142f7df2e56Smrg return FALSE; 143f7df2e56Smrg err = dixLookupResourceByType((void **) &pf, fid, RT_FONT, serverClient, 144f7df2e56Smrg DixReadAccess); 1456747b715Smrg if (err != Success) 146f7df2e56Smrg return FALSE; 14705b261ecSmrg defaultFont = pf; 14805b261ecSmrg return TRUE; 14905b261ecSmrg} 15005b261ecSmrg 15105b261ecSmrg/* 15205b261ecSmrg * note that the font wakeup queue is not refcounted. this is because 15305b261ecSmrg * an fpe needs to be added when it's inited, and removed when it's finally 15405b261ecSmrg * freed, in order to handle any data that isn't requested, like FS events. 15505b261ecSmrg * 15605b261ecSmrg * since the only thing that should call these routines is the renderer's 15705b261ecSmrg * init_fpe() and free_fpe(), there shouldn't be any problem in using 15805b261ecSmrg * freed data. 15905b261ecSmrg */ 160f7df2e56Smrgstatic void 16105b261ecSmrgQueueFontWakeup(FontPathElementPtr fpe) 16205b261ecSmrg{ 163f7df2e56Smrg int i; 16405b261ecSmrg FontPathElementPtr *new; 16505b261ecSmrg 16605b261ecSmrg for (i = 0; i < num_slept_fpes; i++) { 167f7df2e56Smrg if (slept_fpes[i] == fpe) { 168f7df2e56Smrg return; 169f7df2e56Smrg } 17005b261ecSmrg } 17105b261ecSmrg if (num_slept_fpes == size_slept_fpes) { 172f7df2e56Smrg new = reallocarray(slept_fpes, size_slept_fpes + 4, 173f7df2e56Smrg sizeof(FontPathElementPtr)); 174f7df2e56Smrg if (!new) 175f7df2e56Smrg return; 176f7df2e56Smrg slept_fpes = new; 177f7df2e56Smrg size_slept_fpes += 4; 17805b261ecSmrg } 17905b261ecSmrg slept_fpes[num_slept_fpes] = fpe; 18005b261ecSmrg num_slept_fpes++; 18105b261ecSmrg} 18205b261ecSmrg 183f7df2e56Smrgstatic void 18405b261ecSmrgRemoveFontWakeup(FontPathElementPtr fpe) 18505b261ecSmrg{ 186f7df2e56Smrg int i, j; 18705b261ecSmrg 18805b261ecSmrg for (i = 0; i < num_slept_fpes; i++) { 189f7df2e56Smrg if (slept_fpes[i] == fpe) { 190f7df2e56Smrg for (j = i; j < num_slept_fpes; j++) { 191f7df2e56Smrg slept_fpes[j] = slept_fpes[j + 1]; 192f7df2e56Smrg } 193f7df2e56Smrg num_slept_fpes--; 194f7df2e56Smrg return; 195f7df2e56Smrg } 19605b261ecSmrg } 19705b261ecSmrg} 19805b261ecSmrg 199f7df2e56Smrgstatic void 2007e31ba66SmrgFontWakeup(void *data, int count) 20105b261ecSmrg{ 202f7df2e56Smrg int i; 20305b261ecSmrg FontPathElementPtr fpe; 20405b261ecSmrg 20505b261ecSmrg if (count < 0) 206f7df2e56Smrg return; 20705b261ecSmrg /* wake up any fpe's that may be waiting for information */ 20805b261ecSmrg for (i = 0; i < num_slept_fpes; i++) { 209f7df2e56Smrg fpe = slept_fpes[i]; 2107e31ba66Smrg (void) (*fpe_functions[fpe->type]->wakeup_fpe) (fpe); 21105b261ecSmrg } 21205b261ecSmrg} 21305b261ecSmrg 21405b261ecSmrg/* XXX -- these two funcs may want to be broken into macros */ 21505b261ecSmrgstatic void 21605b261ecSmrgUseFPE(FontPathElementPtr fpe) 21705b261ecSmrg{ 21805b261ecSmrg fpe->refcount++; 21905b261ecSmrg} 22005b261ecSmrg 22105b261ecSmrgstatic void 222f7df2e56SmrgFreeFPE(FontPathElementPtr fpe) 22305b261ecSmrg{ 22405b261ecSmrg fpe->refcount--; 22505b261ecSmrg if (fpe->refcount == 0) { 2267e31ba66Smrg (*fpe_functions[fpe->type]->free_fpe) (fpe); 227f7df2e56Smrg free((void *) fpe->name); 228f7df2e56Smrg free(fpe); 22905b261ecSmrg } 23005b261ecSmrg} 23105b261ecSmrg 23205b261ecSmrgstatic Bool 23305b261ecSmrgdoOpenFont(ClientPtr client, OFclosurePtr c) 23405b261ecSmrg{ 235f7df2e56Smrg FontPtr pfont = NullFont; 23605b261ecSmrg FontPathElementPtr fpe = NULL; 237f7df2e56Smrg ScreenPtr pScr; 238f7df2e56Smrg int err = Successful; 239f7df2e56Smrg int i; 240f7df2e56Smrg char *alias, *newname; 241f7df2e56Smrg int newlen; 242f7df2e56Smrg int aliascount = 20; 243f7df2e56Smrg 24405b261ecSmrg /* 24505b261ecSmrg * Decide at runtime what FontFormat to use. 24605b261ecSmrg */ 247f7df2e56Smrg Mask FontFormat = 248f7df2e56Smrg ((screenInfo.imageByteOrder == LSBFirst) ? 249f7df2e56Smrg BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) | 250f7df2e56Smrg ((screenInfo.bitmapBitOrder == LSBFirst) ? 251f7df2e56Smrg BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) | 252f7df2e56Smrg BitmapFormatImageRectMin | 25305b261ecSmrg#if GLYPHPADBYTES == 1 254f7df2e56Smrg BitmapFormatScanlinePad8 | 25505b261ecSmrg#endif 25605b261ecSmrg#if GLYPHPADBYTES == 2 257f7df2e56Smrg BitmapFormatScanlinePad16 | 25805b261ecSmrg#endif 25905b261ecSmrg#if GLYPHPADBYTES == 4 260f7df2e56Smrg BitmapFormatScanlinePad32 | 26105b261ecSmrg#endif 26205b261ecSmrg#if GLYPHPADBYTES == 8 263f7df2e56Smrg BitmapFormatScanlinePad64 | 26405b261ecSmrg#endif 265f7df2e56Smrg BitmapFormatScanlineUnit8; 26605b261ecSmrg 267f7df2e56Smrg if (client->clientGone) { 268f7df2e56Smrg if (c->current_fpe < c->num_fpes) { 269f7df2e56Smrg fpe = c->fpe_list[c->current_fpe]; 2707e31ba66Smrg (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe); 271f7df2e56Smrg } 272f7df2e56Smrg err = Successful; 273f7df2e56Smrg goto bail; 27405b261ecSmrg } 27505b261ecSmrg while (c->current_fpe < c->num_fpes) { 276f7df2e56Smrg fpe = c->fpe_list[c->current_fpe]; 2777e31ba66Smrg err = (*fpe_functions[fpe->type]->open_font) 278f7df2e56Smrg ((void *) client, fpe, c->flags, 279f7df2e56Smrg c->fontname, c->fnamelen, FontFormat, 280f7df2e56Smrg BitmapFormatMaskByte | 281f7df2e56Smrg BitmapFormatMaskBit | 282f7df2e56Smrg BitmapFormatMaskImageRectangle | 283f7df2e56Smrg BitmapFormatMaskScanLinePad | 284f7df2e56Smrg BitmapFormatMaskScanLineUnit, 285f7df2e56Smrg c->fontid, &pfont, &alias, 286f7df2e56Smrg c->non_cachable_font && c->non_cachable_font->fpe == fpe ? 287f7df2e56Smrg c->non_cachable_font : (FontPtr) 0); 288f7df2e56Smrg 289f7df2e56Smrg if (err == FontNameAlias && alias) { 290f7df2e56Smrg newlen = strlen(alias); 291f7df2e56Smrg newname = (char *) realloc((char *) c->fontname, newlen); 292f7df2e56Smrg if (!newname) { 293f7df2e56Smrg err = AllocError; 294f7df2e56Smrg break; 295f7df2e56Smrg } 296f7df2e56Smrg memmove(newname, alias, newlen); 297f7df2e56Smrg c->fontname = newname; 298f7df2e56Smrg c->fnamelen = newlen; 299f7df2e56Smrg c->current_fpe = 0; 300f7df2e56Smrg if (--aliascount <= 0) { 301f7df2e56Smrg /* We've tried resolving this alias 20 times, we're 302f7df2e56Smrg * probably stuck in an infinite loop of aliases pointing 303f7df2e56Smrg * to each other - time to take emergency exit! 304f7df2e56Smrg */ 305f7df2e56Smrg err = BadImplementation; 306f7df2e56Smrg break; 307f7df2e56Smrg } 308f7df2e56Smrg continue; 309f7df2e56Smrg } 310f7df2e56Smrg if (err == BadFontName) { 311f7df2e56Smrg c->current_fpe++; 312f7df2e56Smrg continue; 313f7df2e56Smrg } 314f7df2e56Smrg if (err == Suspended) { 315f7df2e56Smrg if (!ClientIsAsleep(client)) 316f7df2e56Smrg ClientSleep(client, (ClientSleepProcPtr) doOpenFont, c); 317f7df2e56Smrg return TRUE; 318f7df2e56Smrg } 319f7df2e56Smrg break; 32005b261ecSmrg } 32105b261ecSmrg 32205b261ecSmrg if (err != Successful) 323f7df2e56Smrg goto bail; 32405b261ecSmrg if (!pfont) { 325f7df2e56Smrg err = BadFontName; 326f7df2e56Smrg goto bail; 32705b261ecSmrg } 32805b261ecSmrg /* check values for firstCol, lastCol, firstRow, and lastRow */ 32905b261ecSmrg if (pfont->info.firstCol > pfont->info.lastCol || 330f7df2e56Smrg pfont->info.firstRow > pfont->info.lastRow || 331f7df2e56Smrg pfont->info.lastCol - pfont->info.firstCol > 255) { 332f7df2e56Smrg err = AllocError; 333f7df2e56Smrg goto bail; 33405b261ecSmrg } 33505b261ecSmrg if (!pfont->fpe) 336f7df2e56Smrg pfont->fpe = fpe; 33705b261ecSmrg pfont->refcnt++; 33805b261ecSmrg if (pfont->refcnt == 1) { 339f7df2e56Smrg UseFPE(pfont->fpe); 340f7df2e56Smrg for (i = 0; i < screenInfo.numScreens; i++) { 341f7df2e56Smrg pScr = screenInfo.screens[i]; 342f7df2e56Smrg if (pScr->RealizeFont) { 343f7df2e56Smrg if (!(*pScr->RealizeFont) (pScr, pfont)) { 344f7df2e56Smrg CloseFont(pfont, (Font) 0); 345f7df2e56Smrg err = AllocError; 346f7df2e56Smrg goto bail; 347f7df2e56Smrg } 348f7df2e56Smrg } 349f7df2e56Smrg } 350f7df2e56Smrg } 351f7df2e56Smrg if (!AddResource(c->fontid, RT_FONT, (void *) pfont)) { 352f7df2e56Smrg err = AllocError; 353f7df2e56Smrg goto bail; 35405b261ecSmrg } 35505b261ecSmrg if (patternCache && pfont != c->non_cachable_font) 3567e31ba66Smrg xfont2_cache_font_pattern(patternCache, c->origFontName, c->origFontNameLen, 3577e31ba66Smrg pfont); 358f7df2e56Smrg bail: 35905b261ecSmrg if (err != Successful && c->client != serverClient) { 360f7df2e56Smrg SendErrorToClient(c->client, X_OpenFont, 0, 361f7df2e56Smrg c->fontid, FontToXError(err)); 36205b261ecSmrg } 3636747b715Smrg ClientWakeup(c->client); 36405b261ecSmrg for (i = 0; i < c->num_fpes; i++) { 365f7df2e56Smrg FreeFPE(c->fpe_list[i]); 36605b261ecSmrg } 3676747b715Smrg free(c->fpe_list); 368f7df2e56Smrg free((void *) c->fontname); 3696747b715Smrg free(c); 37005b261ecSmrg return TRUE; 37105b261ecSmrg} 37205b261ecSmrg 37305b261ecSmrgint 374f7df2e56SmrgOpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, 375f7df2e56Smrg const char *pfontname) 37605b261ecSmrg{ 37705b261ecSmrg OFclosurePtr c; 378f7df2e56Smrg int i; 379f7df2e56Smrg FontPtr cached = (FontPtr) 0; 38005b261ecSmrg 38105b261ecSmrg if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) 382f7df2e56Smrg return BadName; 383f7df2e56Smrg if (patternCache) { 38405b261ecSmrg 385f7df2e56Smrg /* 386f7df2e56Smrg ** Check name cache. If we find a cached version of this font that 387f7df2e56Smrg ** is cachable, immediately satisfy the request with it. If we find 388f7df2e56Smrg ** a cached version of this font that is non-cachable, we do not 389f7df2e56Smrg ** satisfy the request with it. Instead, we pass the FontPtr to the 390f7df2e56Smrg ** FPE's open_font code (the fontfile FPE in turn passes the 391f7df2e56Smrg ** information to the rasterizer; the fserve FPE ignores it). 392f7df2e56Smrg ** 393f7df2e56Smrg ** Presumably, the font is marked non-cachable because the FPE has 394f7df2e56Smrg ** put some licensing restrictions on it. If the FPE, using 395f7df2e56Smrg ** whatever logic it relies on, determines that it is willing to 396f7df2e56Smrg ** share this existing font with the client, then it has the option 397f7df2e56Smrg ** to return the FontPtr we passed it as the newly-opened font. 398f7df2e56Smrg ** This allows the FPE to exercise its licensing logic without 399f7df2e56Smrg ** having to create another instance of a font that already exists. 400f7df2e56Smrg */ 401f7df2e56Smrg 4027e31ba66Smrg cached = xfont2_find_cached_font_pattern(patternCache, pfontname, lenfname); 403f7df2e56Smrg if (cached && cached->info.cachable) { 404f7df2e56Smrg if (!AddResource(fid, RT_FONT, (void *) cached)) 405f7df2e56Smrg return BadAlloc; 406f7df2e56Smrg cached->refcnt++; 407f7df2e56Smrg return Success; 408f7df2e56Smrg } 40905b261ecSmrg } 4106747b715Smrg c = malloc(sizeof(OFclosureRec)); 41105b261ecSmrg if (!c) 412f7df2e56Smrg return BadAlloc; 4136747b715Smrg c->fontname = malloc(lenfname); 41405b261ecSmrg c->origFontName = pfontname; 41505b261ecSmrg c->origFontNameLen = lenfname; 41605b261ecSmrg if (!c->fontname) { 417f7df2e56Smrg free(c); 418f7df2e56Smrg return BadAlloc; 41905b261ecSmrg } 42005b261ecSmrg /* 42105b261ecSmrg * copy the current FPE list, so that if it gets changed by another client 42205b261ecSmrg * while we're blocking, the request still appears atomic 42305b261ecSmrg */ 424f7df2e56Smrg c->fpe_list = xallocarray(num_fpes, sizeof(FontPathElementPtr)); 42505b261ecSmrg if (!c->fpe_list) { 426f7df2e56Smrg free((void *) c->fontname); 427f7df2e56Smrg free(c); 428f7df2e56Smrg return BadAlloc; 42905b261ecSmrg } 43005b261ecSmrg memmove(c->fontname, pfontname, lenfname); 43105b261ecSmrg for (i = 0; i < num_fpes; i++) { 432f7df2e56Smrg c->fpe_list[i] = font_path_elements[i]; 433f7df2e56Smrg UseFPE(c->fpe_list[i]); 43405b261ecSmrg } 43505b261ecSmrg c->client = client; 43605b261ecSmrg c->fontid = fid; 43705b261ecSmrg c->current_fpe = 0; 43805b261ecSmrg c->num_fpes = num_fpes; 43905b261ecSmrg c->fnamelen = lenfname; 44005b261ecSmrg c->flags = flags; 44105b261ecSmrg c->non_cachable_font = cached; 44205b261ecSmrg 44305b261ecSmrg (void) doOpenFont(client, c); 44405b261ecSmrg return Success; 44505b261ecSmrg} 44605b261ecSmrg 44705b261ecSmrg/** 44805b261ecSmrg * Decrement font's ref count, and free storage if ref count equals zero 44905b261ecSmrg * 45005b261ecSmrg * \param value must conform to DeleteType 45105b261ecSmrg */ 4524642e01fSmrgint 453f7df2e56SmrgCloseFont(void *value, XID fid) 45405b261ecSmrg{ 455f7df2e56Smrg int nscr; 456f7df2e56Smrg ScreenPtr pscr; 45705b261ecSmrg FontPathElementPtr fpe; 458f7df2e56Smrg FontPtr pfont = (FontPtr) value; 45905b261ecSmrg 46005b261ecSmrg if (pfont == NullFont) 461f7df2e56Smrg return Success; 46205b261ecSmrg if (--pfont->refcnt == 0) { 463f7df2e56Smrg if (patternCache) 4647e31ba66Smrg xfont2_remove_cached_font_pattern(patternCache, pfont); 465f7df2e56Smrg /* 466f7df2e56Smrg * since the last reference is gone, ask each screen to free any 467f7df2e56Smrg * storage it may have allocated locally for it. 468f7df2e56Smrg */ 469f7df2e56Smrg for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { 470f7df2e56Smrg pscr = screenInfo.screens[nscr]; 471f7df2e56Smrg if (pscr->UnrealizeFont) 472f7df2e56Smrg (*pscr->UnrealizeFont) (pscr, pfont); 473f7df2e56Smrg } 474f7df2e56Smrg if (pfont == defaultFont) 475f7df2e56Smrg defaultFont = NULL; 47605b261ecSmrg#ifdef XF86BIGFONT 477f7df2e56Smrg XF86BigfontFreeFontShm(pfont); 47805b261ecSmrg#endif 479f7df2e56Smrg fpe = pfont->fpe; 4807e31ba66Smrg (*fpe_functions[fpe->type]->close_font) (fpe, pfont); 481f7df2e56Smrg FreeFPE(fpe); 48205b261ecSmrg } 4836747b715Smrg return Success; 48405b261ecSmrg} 48505b261ecSmrg 48605b261ecSmrg/***====================================================================***/ 48705b261ecSmrg 48805b261ecSmrg/** 48905b261ecSmrg * Sets up pReply as the correct QueryFontReply for pFont with the first 49005b261ecSmrg * nProtoCCIStructs char infos. 49105b261ecSmrg * 49205b261ecSmrg * \param pReply caller must allocate this storage 49305b261ecSmrg */ 49405b261ecSmrgvoid 495f7df2e56SmrgQueryFont(FontPtr pFont, xQueryFontReply * pReply, int nProtoCCIStructs) 49605b261ecSmrg{ 497f7df2e56Smrg FontPropPtr pFP; 498f7df2e56Smrg int r, c, i; 499f7df2e56Smrg xFontProp *prFP; 500f7df2e56Smrg xCharInfo *prCI; 501f7df2e56Smrg xCharInfo *charInfos[256]; 502f7df2e56Smrg unsigned char chars[512]; 503f7df2e56Smrg int ninfos; 504f7df2e56Smrg unsigned long ncols; 505f7df2e56Smrg unsigned long count; 50605b261ecSmrg 50705b261ecSmrg /* pr->length set in dispatch */ 50805b261ecSmrg pReply->minCharOrByte2 = pFont->info.firstCol; 50905b261ecSmrg pReply->defaultChar = pFont->info.defaultCh; 51005b261ecSmrg pReply->maxCharOrByte2 = pFont->info.lastCol; 51105b261ecSmrg pReply->drawDirection = pFont->info.drawDirection; 51205b261ecSmrg pReply->allCharsExist = pFont->info.allExist; 51305b261ecSmrg pReply->minByte1 = pFont->info.firstRow; 51405b261ecSmrg pReply->maxByte1 = pFont->info.lastRow; 51505b261ecSmrg pReply->fontAscent = pFont->info.fontAscent; 51605b261ecSmrg pReply->fontDescent = pFont->info.fontDescent; 51705b261ecSmrg 51805b261ecSmrg pReply->minBounds = pFont->info.ink_minbounds; 51905b261ecSmrg pReply->maxBounds = pFont->info.ink_maxbounds; 52005b261ecSmrg 52105b261ecSmrg pReply->nFontProps = pFont->info.nprops; 52205b261ecSmrg pReply->nCharInfos = nProtoCCIStructs; 52305b261ecSmrg 52405b261ecSmrg for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]); 525f7df2e56Smrg i < pFont->info.nprops; i++, pFP++, prFP++) { 526f7df2e56Smrg prFP->name = pFP->name; 527f7df2e56Smrg prFP->value = pFP->value; 52805b261ecSmrg } 52905b261ecSmrg 53005b261ecSmrg ninfos = 0; 53105b261ecSmrg ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1); 53205b261ecSmrg prCI = (xCharInfo *) (prFP); 53305b261ecSmrg for (r = pFont->info.firstRow; 534f7df2e56Smrg ninfos < nProtoCCIStructs && r <= (int) pFont->info.lastRow; r++) { 535f7df2e56Smrg i = 0; 536f7df2e56Smrg for (c = pFont->info.firstCol; c <= (int) pFont->info.lastCol; c++) { 537f7df2e56Smrg chars[i++] = r; 538f7df2e56Smrg chars[i++] = c; 539f7df2e56Smrg } 540f7df2e56Smrg (*pFont->get_metrics) (pFont, ncols, chars, 541f7df2e56Smrg TwoD16Bit, &count, charInfos); 542f7df2e56Smrg i = 0; 543f7df2e56Smrg for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) { 544f7df2e56Smrg *prCI = *charInfos[i]; 545f7df2e56Smrg prCI++; 546f7df2e56Smrg ninfos++; 547f7df2e56Smrg } 54805b261ecSmrg } 54905b261ecSmrg return; 55005b261ecSmrg} 55105b261ecSmrg 55205b261ecSmrgstatic Bool 55305b261ecSmrgdoListFontsAndAliases(ClientPtr client, LFclosurePtr c) 55405b261ecSmrg{ 55505b261ecSmrg FontPathElementPtr fpe; 556f7df2e56Smrg int err = Successful; 55705b261ecSmrg FontNamesPtr names = NULL; 558f7df2e56Smrg char *name, *resolved = NULL; 559f7df2e56Smrg int namelen, resolvedlen; 560f7df2e56Smrg int nnames; 561f7df2e56Smrg int stringLens; 562f7df2e56Smrg int i; 56305b261ecSmrg xListFontsReply reply; 564f7df2e56Smrg char *bufptr; 565f7df2e56Smrg char *bufferStart; 566f7df2e56Smrg int aliascount = 0; 567f7df2e56Smrg 568f7df2e56Smrg if (client->clientGone) { 569f7df2e56Smrg if (c->current.current_fpe < c->num_fpes) { 570f7df2e56Smrg fpe = c->fpe_list[c->current.current_fpe]; 5717e31ba66Smrg (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe); 572f7df2e56Smrg } 573f7df2e56Smrg err = Successful; 574f7df2e56Smrg goto bail; 57505b261ecSmrg } 57605b261ecSmrg 57705b261ecSmrg if (!c->current.patlen) 578f7df2e56Smrg goto finish; 57905b261ecSmrg 58005b261ecSmrg while (c->current.current_fpe < c->num_fpes) { 581f7df2e56Smrg fpe = c->fpe_list[c->current.current_fpe]; 582f7df2e56Smrg err = Successful; 583f7df2e56Smrg 5847e31ba66Smrg if (!fpe_functions[fpe->type]->start_list_fonts_and_aliases) { 585f7df2e56Smrg /* This FPE doesn't support/require list_fonts_and_aliases */ 586f7df2e56Smrg 5877e31ba66Smrg err = (*fpe_functions[fpe->type]->list_fonts) 588f7df2e56Smrg ((void *) c->client, fpe, c->current.pattern, 589f7df2e56Smrg c->current.patlen, c->current.max_names - c->names->nnames, 590f7df2e56Smrg c->names); 591f7df2e56Smrg 592f7df2e56Smrg if (err == Suspended) { 593f7df2e56Smrg if (!ClientIsAsleep(client)) 594f7df2e56Smrg ClientSleep(client, 595f7df2e56Smrg (ClientSleepProcPtr) doListFontsAndAliases, c); 596f7df2e56Smrg return TRUE; 597f7df2e56Smrg } 598f7df2e56Smrg 599f7df2e56Smrg err = BadFontName; 600f7df2e56Smrg } 601f7df2e56Smrg else { 602f7df2e56Smrg /* Start of list_fonts_and_aliases functionality. Modeled 603f7df2e56Smrg after list_fonts_with_info in that it resolves aliases, 604f7df2e56Smrg except that the information collected from FPEs is just 605f7df2e56Smrg names, not font info. Each list_next_font_or_alias() 606f7df2e56Smrg returns either a name into name/namelen or an alias into 607f7df2e56Smrg name/namelen and its target name into resolved/resolvedlen. 608f7df2e56Smrg The code at this level then resolves the alias by polling 609f7df2e56Smrg the FPEs. */ 610f7df2e56Smrg 611f7df2e56Smrg if (!c->current.list_started) { 6127e31ba66Smrg err = (*fpe_functions[fpe->type]->start_list_fonts_and_aliases) 613f7df2e56Smrg ((void *) c->client, fpe, c->current.pattern, 614f7df2e56Smrg c->current.patlen, c->current.max_names - c->names->nnames, 615f7df2e56Smrg &c->current.private); 616f7df2e56Smrg if (err == Suspended) { 617f7df2e56Smrg if (!ClientIsAsleep(client)) 618f7df2e56Smrg ClientSleep(client, 619f7df2e56Smrg (ClientSleepProcPtr) doListFontsAndAliases, 620f7df2e56Smrg c); 621f7df2e56Smrg return TRUE; 622f7df2e56Smrg } 623f7df2e56Smrg if (err == Successful) 624f7df2e56Smrg c->current.list_started = TRUE; 625f7df2e56Smrg } 626f7df2e56Smrg if (err == Successful) { 627f7df2e56Smrg char *tmpname; 628f7df2e56Smrg 629f7df2e56Smrg name = 0; 6307e31ba66Smrg err = (*fpe_functions[fpe->type]->list_next_font_or_alias) 631f7df2e56Smrg ((void *) c->client, fpe, &name, &namelen, &tmpname, 632f7df2e56Smrg &resolvedlen, c->current.private); 633f7df2e56Smrg if (err == Suspended) { 634f7df2e56Smrg if (!ClientIsAsleep(client)) 635f7df2e56Smrg ClientSleep(client, 636f7df2e56Smrg (ClientSleepProcPtr) doListFontsAndAliases, 637f7df2e56Smrg c); 638f7df2e56Smrg return TRUE; 639f7df2e56Smrg } 640f7df2e56Smrg if (err == FontNameAlias) { 641f7df2e56Smrg free(resolved); 642f7df2e56Smrg resolved = malloc(resolvedlen + 1); 643f7df2e56Smrg if (resolved) 644f7df2e56Smrg memmove(resolved, tmpname, resolvedlen + 1); 645f7df2e56Smrg } 646f7df2e56Smrg } 647f7df2e56Smrg 648f7df2e56Smrg if (err == Successful) { 649f7df2e56Smrg if (c->haveSaved) { 650f7df2e56Smrg if (c->savedName) 6517e31ba66Smrg (void) xfont2_add_font_names_name(c->names, c->savedName, 652f7df2e56Smrg c->savedNameLen); 653f7df2e56Smrg } 654f7df2e56Smrg else 6557e31ba66Smrg (void) xfont2_add_font_names_name(c->names, name, namelen); 656f7df2e56Smrg } 657f7df2e56Smrg 658f7df2e56Smrg /* 659f7df2e56Smrg * When we get an alias back, save our state and reset back to 660f7df2e56Smrg * the start of the FPE looking for the specified name. As 661f7df2e56Smrg * soon as a real font is found for the alias, pop back to the 662f7df2e56Smrg * old state 663f7df2e56Smrg */ 664f7df2e56Smrg else if (err == FontNameAlias) { 665f7df2e56Smrg char tmp_pattern[XLFDMAXFONTNAMELEN]; 666f7df2e56Smrg 667f7df2e56Smrg /* 668f7df2e56Smrg * when an alias recurses, we need to give 669f7df2e56Smrg * the last FPE a chance to clean up; so we call 670f7df2e56Smrg * it again, and assume that the error returned 671f7df2e56Smrg * is BadFontName, indicating the alias resolution 672f7df2e56Smrg * is complete. 673f7df2e56Smrg */ 674f7df2e56Smrg memmove(tmp_pattern, resolved, resolvedlen); 675f7df2e56Smrg if (c->haveSaved) { 676f7df2e56Smrg char *tmpname; 677f7df2e56Smrg int tmpnamelen; 678f7df2e56Smrg 679f7df2e56Smrg tmpname = 0; 6807e31ba66Smrg (void) (*fpe_functions[fpe->type]->list_next_font_or_alias) 681f7df2e56Smrg ((void *) c->client, fpe, &tmpname, &tmpnamelen, 682f7df2e56Smrg &tmpname, &tmpnamelen, c->current.private); 683f7df2e56Smrg if (--aliascount <= 0) { 684f7df2e56Smrg err = BadFontName; 685f7df2e56Smrg goto ContBadFontName; 686f7df2e56Smrg } 687f7df2e56Smrg } 688f7df2e56Smrg else { 689f7df2e56Smrg c->saved = c->current; 690f7df2e56Smrg c->haveSaved = TRUE; 691f7df2e56Smrg free(c->savedName); 692f7df2e56Smrg c->savedName = malloc(namelen + 1); 693f7df2e56Smrg if (c->savedName) 694f7df2e56Smrg memmove(c->savedName, name, namelen + 1); 695f7df2e56Smrg c->savedNameLen = namelen; 696f7df2e56Smrg aliascount = 20; 697f7df2e56Smrg } 698f7df2e56Smrg memmove(c->current.pattern, tmp_pattern, resolvedlen); 699f7df2e56Smrg c->current.patlen = resolvedlen; 700f7df2e56Smrg c->current.max_names = c->names->nnames + 1; 701f7df2e56Smrg c->current.current_fpe = -1; 702f7df2e56Smrg c->current.private = 0; 703f7df2e56Smrg err = BadFontName; 704f7df2e56Smrg } 705f7df2e56Smrg } 706f7df2e56Smrg /* 707f7df2e56Smrg * At the end of this FPE, step to the next. If we've finished 708f7df2e56Smrg * processing an alias, pop state back. If we've collected enough 709f7df2e56Smrg * font names, quit. 710f7df2e56Smrg */ 711f7df2e56Smrg if (err == BadFontName) { 712f7df2e56Smrg ContBadFontName:; 713f7df2e56Smrg c->current.list_started = FALSE; 714f7df2e56Smrg c->current.current_fpe++; 715f7df2e56Smrg err = Successful; 716f7df2e56Smrg if (c->haveSaved) { 717f7df2e56Smrg if (c->names->nnames == c->current.max_names || 718f7df2e56Smrg c->current.current_fpe == c->num_fpes) { 719f7df2e56Smrg c->haveSaved = FALSE; 720f7df2e56Smrg c->current = c->saved; 721f7df2e56Smrg /* Give the saved namelist a chance to clean itself up */ 722f7df2e56Smrg continue; 723f7df2e56Smrg } 724f7df2e56Smrg } 725f7df2e56Smrg if (c->names->nnames == c->current.max_names) 726f7df2e56Smrg break; 727f7df2e56Smrg } 72805b261ecSmrg } 72905b261ecSmrg 73005b261ecSmrg /* 73105b261ecSmrg * send the reply 73205b261ecSmrg */ 73305b261ecSmrg if (err != Successful) { 734f7df2e56Smrg SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err)); 735f7df2e56Smrg goto bail; 73605b261ecSmrg } 73705b261ecSmrg 738f7df2e56Smrg finish: 73905b261ecSmrg 74005b261ecSmrg names = c->names; 74105b261ecSmrg nnames = names->nnames; 74205b261ecSmrg client = c->client; 74305b261ecSmrg stringLens = 0; 74405b261ecSmrg for (i = 0; i < nnames; i++) 745f7df2e56Smrg stringLens += (names->length[i] <= 255) ? names->length[i] : 0; 74605b261ecSmrg 747f7df2e56Smrg reply = (xListFontsReply) { 748f7df2e56Smrg .type = X_Reply, 749f7df2e56Smrg .length = bytes_to_int32(stringLens + nnames), 750f7df2e56Smrg .nFonts = nnames, 751f7df2e56Smrg .sequenceNumber = client->sequence 752f7df2e56Smrg }; 75305b261ecSmrg 7546747b715Smrg bufptr = bufferStart = malloc(reply.length << 2); 75505b261ecSmrg 75605b261ecSmrg if (!bufptr && reply.length) { 757f7df2e56Smrg SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc); 758f7df2e56Smrg goto bail; 75905b261ecSmrg } 76005b261ecSmrg /* 76105b261ecSmrg * since WriteToClient long word aligns things, copy to temp buffer and 76205b261ecSmrg * write all at once 76305b261ecSmrg */ 76405b261ecSmrg for (i = 0; i < nnames; i++) { 765f7df2e56Smrg if (names->length[i] > 255) 766f7df2e56Smrg reply.nFonts--; 767f7df2e56Smrg else { 768f7df2e56Smrg *bufptr++ = names->length[i]; 769f7df2e56Smrg memmove(bufptr, names->names[i], names->length[i]); 770f7df2e56Smrg bufptr += names->length[i]; 771f7df2e56Smrg } 77205b261ecSmrg } 77305b261ecSmrg nnames = reply.nFonts; 7746747b715Smrg reply.length = bytes_to_int32(stringLens + nnames); 77505b261ecSmrg client->pSwapReplyFunc = ReplySwapVector[X_ListFonts]; 77605b261ecSmrg WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply); 777f7df2e56Smrg WriteToClient(client, stringLens + nnames, bufferStart); 7786747b715Smrg free(bufferStart); 77905b261ecSmrg 780f7df2e56Smrg bail: 7816747b715Smrg ClientWakeup(client); 78205b261ecSmrg for (i = 0; i < c->num_fpes; i++) 783f7df2e56Smrg FreeFPE(c->fpe_list[i]); 7846747b715Smrg free(c->fpe_list); 7856747b715Smrg free(c->savedName); 7867e31ba66Smrg xfont2_free_font_names(names); 7876747b715Smrg free(c); 7886747b715Smrg free(resolved); 78905b261ecSmrg return TRUE; 79005b261ecSmrg} 79105b261ecSmrg 79205b261ecSmrgint 793f7df2e56SmrgListFonts(ClientPtr client, unsigned char *pattern, unsigned length, 79405b261ecSmrg unsigned max_names) 79505b261ecSmrg{ 796f7df2e56Smrg int i; 79705b261ecSmrg LFclosurePtr c; 79805b261ecSmrg 799f7df2e56Smrg /* 80005b261ecSmrg * The right error to return here would be BadName, however the 80105b261ecSmrg * specification does not allow for a Name error on this request. 80205b261ecSmrg * Perhaps a better solution would be to return a nil list, i.e. 80305b261ecSmrg * a list containing zero fontnames. 80405b261ecSmrg */ 80505b261ecSmrg if (length > XLFDMAXFONTNAMELEN) 806f7df2e56Smrg return BadAlloc; 80705b261ecSmrg 8084642e01fSmrg i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess); 8094642e01fSmrg if (i != Success) 810f7df2e56Smrg return i; 8114642e01fSmrg 8126747b715Smrg if (!(c = malloc(sizeof *c))) 813f7df2e56Smrg return BadAlloc; 814f7df2e56Smrg c->fpe_list = xallocarray(num_fpes, sizeof(FontPathElementPtr)); 81505b261ecSmrg if (!c->fpe_list) { 816f7df2e56Smrg free(c); 817f7df2e56Smrg return BadAlloc; 81805b261ecSmrg } 8197e31ba66Smrg c->names = xfont2_make_font_names_record(max_names < 100 ? max_names : 100); 820f7df2e56Smrg if (!c->names) { 821f7df2e56Smrg free(c->fpe_list); 822f7df2e56Smrg free(c); 823f7df2e56Smrg return BadAlloc; 82405b261ecSmrg } 825f7df2e56Smrg memmove(c->current.pattern, pattern, length); 82605b261ecSmrg for (i = 0; i < num_fpes; i++) { 827f7df2e56Smrg c->fpe_list[i] = font_path_elements[i]; 828f7df2e56Smrg UseFPE(c->fpe_list[i]); 82905b261ecSmrg } 83005b261ecSmrg c->client = client; 83105b261ecSmrg c->num_fpes = num_fpes; 83205b261ecSmrg c->current.patlen = length; 83305b261ecSmrg c->current.current_fpe = 0; 83405b261ecSmrg c->current.max_names = max_names; 83505b261ecSmrg c->current.list_started = FALSE; 83605b261ecSmrg c->current.private = 0; 83705b261ecSmrg c->haveSaved = FALSE; 83805b261ecSmrg c->savedName = 0; 83905b261ecSmrg doListFontsAndAliases(client, c); 84005b261ecSmrg return Success; 84105b261ecSmrg} 84205b261ecSmrg 843f7df2e56Smrgstatic int 84405b261ecSmrgdoListFontsWithInfo(ClientPtr client, LFWIclosurePtr c) 84505b261ecSmrg{ 84605b261ecSmrg FontPathElementPtr fpe; 847f7df2e56Smrg int err = Successful; 848f7df2e56Smrg char *name; 849f7df2e56Smrg int namelen; 850f7df2e56Smrg int numFonts; 851f7df2e56Smrg FontInfoRec fontInfo, *pFontInfo; 85205b261ecSmrg xListFontsWithInfoReply *reply; 853f7df2e56Smrg int length; 854f7df2e56Smrg xFontProp *pFP; 855f7df2e56Smrg int i; 856f7df2e56Smrg int aliascount = 0; 85705b261ecSmrg xListFontsWithInfoReply finalReply; 85805b261ecSmrg 859f7df2e56Smrg if (client->clientGone) { 860f7df2e56Smrg if (c->current.current_fpe < c->num_fpes) { 861f7df2e56Smrg fpe = c->fpe_list[c->current.current_fpe]; 8627e31ba66Smrg (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe); 863f7df2e56Smrg } 864f7df2e56Smrg err = Successful; 865f7df2e56Smrg goto bail; 86605b261ecSmrg } 86705b261ecSmrg client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo]; 86805b261ecSmrg if (!c->current.patlen) 869f7df2e56Smrg goto finish; 870f7df2e56Smrg while (c->current.current_fpe < c->num_fpes) { 871f7df2e56Smrg fpe = c->fpe_list[c->current.current_fpe]; 872f7df2e56Smrg err = Successful; 873f7df2e56Smrg if (!c->current.list_started) { 8747e31ba66Smrg err = (*fpe_functions[fpe->type]->start_list_fonts_with_info) 875f7df2e56Smrg (client, fpe, c->current.pattern, c->current.patlen, 876f7df2e56Smrg c->current.max_names, &c->current.private); 877f7df2e56Smrg if (err == Suspended) { 878f7df2e56Smrg if (!ClientIsAsleep(client)) 879f7df2e56Smrg ClientSleep(client, 880f7df2e56Smrg (ClientSleepProcPtr) doListFontsWithInfo, c); 881f7df2e56Smrg return TRUE; 882f7df2e56Smrg } 883f7df2e56Smrg if (err == Successful) 884f7df2e56Smrg c->current.list_started = TRUE; 885f7df2e56Smrg } 886f7df2e56Smrg if (err == Successful) { 887f7df2e56Smrg name = 0; 888f7df2e56Smrg pFontInfo = &fontInfo; 8897e31ba66Smrg err = (*fpe_functions[fpe->type]->list_next_font_with_info) 890f7df2e56Smrg (client, fpe, &name, &namelen, &pFontInfo, 891f7df2e56Smrg &numFonts, c->current.private); 892f7df2e56Smrg if (err == Suspended) { 893f7df2e56Smrg if (!ClientIsAsleep(client)) 894f7df2e56Smrg ClientSleep(client, 895f7df2e56Smrg (ClientSleepProcPtr) doListFontsWithInfo, c); 896f7df2e56Smrg return TRUE; 897f7df2e56Smrg } 898f7df2e56Smrg } 899f7df2e56Smrg /* 900f7df2e56Smrg * When we get an alias back, save our state and reset back to the 901f7df2e56Smrg * start of the FPE looking for the specified name. As soon as a real 902f7df2e56Smrg * font is found for the alias, pop back to the old state 903f7df2e56Smrg */ 904f7df2e56Smrg if (err == FontNameAlias) { 905f7df2e56Smrg /* 906f7df2e56Smrg * when an alias recurses, we need to give 907f7df2e56Smrg * the last FPE a chance to clean up; so we call 908f7df2e56Smrg * it again, and assume that the error returned 909f7df2e56Smrg * is BadFontName, indicating the alias resolution 910f7df2e56Smrg * is complete. 911f7df2e56Smrg */ 912f7df2e56Smrg if (c->haveSaved) { 913f7df2e56Smrg char *tmpname; 914f7df2e56Smrg int tmpnamelen; 915f7df2e56Smrg FontInfoPtr tmpFontInfo; 916f7df2e56Smrg 917f7df2e56Smrg tmpname = 0; 918f7df2e56Smrg tmpFontInfo = &fontInfo; 9197e31ba66Smrg (void) (*fpe_functions[fpe->type]->list_next_font_with_info) 920f7df2e56Smrg (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo, 921f7df2e56Smrg &numFonts, c->current.private); 922f7df2e56Smrg if (--aliascount <= 0) { 923f7df2e56Smrg err = BadFontName; 924f7df2e56Smrg goto ContBadFontName; 925f7df2e56Smrg } 926f7df2e56Smrg } 927f7df2e56Smrg else { 928f7df2e56Smrg c->saved = c->current; 929f7df2e56Smrg c->haveSaved = TRUE; 930f7df2e56Smrg c->savedNumFonts = numFonts; 931f7df2e56Smrg free(c->savedName); 932f7df2e56Smrg c->savedName = malloc(namelen + 1); 933f7df2e56Smrg if (c->savedName) 934f7df2e56Smrg memmove(c->savedName, name, namelen + 1); 935f7df2e56Smrg aliascount = 20; 936f7df2e56Smrg } 937f7df2e56Smrg memmove(c->current.pattern, name, namelen); 938f7df2e56Smrg c->current.patlen = namelen; 939f7df2e56Smrg c->current.max_names = 1; 940f7df2e56Smrg c->current.current_fpe = 0; 941f7df2e56Smrg c->current.private = 0; 942f7df2e56Smrg c->current.list_started = FALSE; 943f7df2e56Smrg } 944f7df2e56Smrg /* 945f7df2e56Smrg * At the end of this FPE, step to the next. If we've finished 946f7df2e56Smrg * processing an alias, pop state back. If we've sent enough font 947f7df2e56Smrg * names, quit. Always wait for BadFontName to let the FPE 948f7df2e56Smrg * have a chance to clean up. 949f7df2e56Smrg */ 950f7df2e56Smrg else if (err == BadFontName) { 951f7df2e56Smrg ContBadFontName:; 952f7df2e56Smrg c->current.list_started = FALSE; 953f7df2e56Smrg c->current.current_fpe++; 954f7df2e56Smrg err = Successful; 955f7df2e56Smrg if (c->haveSaved) { 956f7df2e56Smrg if (c->current.max_names == 0 || 957f7df2e56Smrg c->current.current_fpe == c->num_fpes) { 958f7df2e56Smrg c->haveSaved = FALSE; 959f7df2e56Smrg c->saved.max_names -= (1 - c->current.max_names); 960f7df2e56Smrg c->current = c->saved; 961f7df2e56Smrg } 962f7df2e56Smrg } 963f7df2e56Smrg else if (c->current.max_names == 0) 964f7df2e56Smrg break; 965f7df2e56Smrg } 966f7df2e56Smrg else if (err == Successful) { 967f7df2e56Smrg length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp); 968f7df2e56Smrg reply = c->reply; 969f7df2e56Smrg if (c->length < length) { 970f7df2e56Smrg reply = (xListFontsWithInfoReply *) realloc(c->reply, length); 971f7df2e56Smrg if (!reply) { 972f7df2e56Smrg err = AllocError; 973f7df2e56Smrg break; 974f7df2e56Smrg } 975f7df2e56Smrg memset((char *) reply + c->length, 0, length - c->length); 976f7df2e56Smrg c->reply = reply; 977f7df2e56Smrg c->length = length; 978f7df2e56Smrg } 979f7df2e56Smrg if (c->haveSaved) { 980f7df2e56Smrg numFonts = c->savedNumFonts; 981f7df2e56Smrg name = c->savedName; 982f7df2e56Smrg namelen = strlen(name); 983f7df2e56Smrg } 984f7df2e56Smrg reply->type = X_Reply; 985f7df2e56Smrg reply->length = 986f7df2e56Smrg bytes_to_int32(sizeof *reply - sizeof(xGenericReply) + 987f7df2e56Smrg pFontInfo->nprops * sizeof(xFontProp) + namelen); 988f7df2e56Smrg reply->sequenceNumber = client->sequence; 989f7df2e56Smrg reply->nameLength = namelen; 990f7df2e56Smrg reply->minBounds = pFontInfo->ink_minbounds; 991f7df2e56Smrg reply->maxBounds = pFontInfo->ink_maxbounds; 992f7df2e56Smrg reply->minCharOrByte2 = pFontInfo->firstCol; 993f7df2e56Smrg reply->maxCharOrByte2 = pFontInfo->lastCol; 994f7df2e56Smrg reply->defaultChar = pFontInfo->defaultCh; 995f7df2e56Smrg reply->nFontProps = pFontInfo->nprops; 996f7df2e56Smrg reply->drawDirection = pFontInfo->drawDirection; 997f7df2e56Smrg reply->minByte1 = pFontInfo->firstRow; 998f7df2e56Smrg reply->maxByte1 = pFontInfo->lastRow; 999f7df2e56Smrg reply->allCharsExist = pFontInfo->allExist; 1000f7df2e56Smrg reply->fontAscent = pFontInfo->fontAscent; 1001f7df2e56Smrg reply->fontDescent = pFontInfo->fontDescent; 1002f7df2e56Smrg reply->nReplies = numFonts; 1003f7df2e56Smrg pFP = (xFontProp *) (reply + 1); 1004f7df2e56Smrg for (i = 0; i < pFontInfo->nprops; i++) { 1005f7df2e56Smrg pFP->name = pFontInfo->props[i].name; 1006f7df2e56Smrg pFP->value = pFontInfo->props[i].value; 1007f7df2e56Smrg pFP++; 1008f7df2e56Smrg } 1009f7df2e56Smrg WriteSwappedDataToClient(client, length, reply); 1010f7df2e56Smrg WriteToClient(client, namelen, name); 1011f7df2e56Smrg if (pFontInfo == &fontInfo) { 1012f7df2e56Smrg free(fontInfo.props); 1013f7df2e56Smrg free(fontInfo.isStringProp); 1014f7df2e56Smrg } 1015f7df2e56Smrg --c->current.max_names; 1016f7df2e56Smrg } 1017f7df2e56Smrg } 1018f7df2e56Smrg finish: 101905b261ecSmrg length = sizeof(xListFontsWithInfoReply); 1020f7df2e56Smrg finalReply = (xListFontsWithInfoReply) { 1021f7df2e56Smrg .type = X_Reply, 1022f7df2e56Smrg .sequenceNumber = client->sequence, 1023f7df2e56Smrg .length = bytes_to_int32(sizeof(xListFontsWithInfoReply) 1024f7df2e56Smrg - sizeof(xGenericReply)) 1025f7df2e56Smrg }; 102605b261ecSmrg WriteSwappedDataToClient(client, length, &finalReply); 1027f7df2e56Smrg bail: 10286747b715Smrg ClientWakeup(client); 102905b261ecSmrg for (i = 0; i < c->num_fpes; i++) 1030f7df2e56Smrg FreeFPE(c->fpe_list[i]); 10316747b715Smrg free(c->reply); 10326747b715Smrg free(c->fpe_list); 10336747b715Smrg free(c->savedName); 10346747b715Smrg free(c); 103505b261ecSmrg return TRUE; 103605b261ecSmrg} 103705b261ecSmrg 103805b261ecSmrgint 1039f7df2e56SmrgStartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern, 104005b261ecSmrg int max_names) 104105b261ecSmrg{ 1042f7df2e56Smrg int i; 1043f7df2e56Smrg LFWIclosurePtr c; 104405b261ecSmrg 1045f7df2e56Smrg /* 104605b261ecSmrg * The right error to return here would be BadName, however the 104705b261ecSmrg * specification does not allow for a Name error on this request. 104805b261ecSmrg * Perhaps a better solution would be to return a nil list, i.e. 104905b261ecSmrg * a list containing zero fontnames. 105005b261ecSmrg */ 105105b261ecSmrg if (length > XLFDMAXFONTNAMELEN) 1052f7df2e56Smrg return BadAlloc; 105305b261ecSmrg 10544642e01fSmrg i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess); 10554642e01fSmrg if (i != Success) 1056f7df2e56Smrg return i; 10574642e01fSmrg 10586747b715Smrg if (!(c = malloc(sizeof *c))) 1059f7df2e56Smrg goto badAlloc; 1060f7df2e56Smrg c->fpe_list = xallocarray(num_fpes, sizeof(FontPathElementPtr)); 1061f7df2e56Smrg if (!c->fpe_list) { 1062f7df2e56Smrg free(c); 1063f7df2e56Smrg goto badAlloc; 106405b261ecSmrg } 106505b261ecSmrg memmove(c->current.pattern, pattern, length); 1066f7df2e56Smrg for (i = 0; i < num_fpes; i++) { 1067f7df2e56Smrg c->fpe_list[i] = font_path_elements[i]; 1068f7df2e56Smrg UseFPE(c->fpe_list[i]); 106905b261ecSmrg } 107005b261ecSmrg c->client = client; 107105b261ecSmrg c->num_fpes = num_fpes; 107205b261ecSmrg c->reply = 0; 107305b261ecSmrg c->length = 0; 107405b261ecSmrg c->current.patlen = length; 107505b261ecSmrg c->current.current_fpe = 0; 107605b261ecSmrg c->current.max_names = max_names; 107705b261ecSmrg c->current.list_started = FALSE; 107805b261ecSmrg c->current.private = 0; 107905b261ecSmrg c->savedNumFonts = 0; 108005b261ecSmrg c->haveSaved = FALSE; 108105b261ecSmrg c->savedName = 0; 108205b261ecSmrg doListFontsWithInfo(client, c); 108305b261ecSmrg return Success; 1084f7df2e56Smrg badAlloc: 108505b261ecSmrg return BadAlloc; 108605b261ecSmrg} 108705b261ecSmrg 108805b261ecSmrg#define TextEltHeader 2 108905b261ecSmrg#define FontShiftSize 5 1090f7df2e56Smrgstatic ChangeGCVal clearGC[] = { {.ptr = NullPixmap} }; 1091f7df2e56Smrg 109205b261ecSmrg#define clearGCmask (GCClipMask) 109305b261ecSmrg 1094f7df2e56Smrgstatic int 109505b261ecSmrgdoPolyText(ClientPtr client, PTclosurePtr c) 109605b261ecSmrg{ 109705b261ecSmrg FontPtr pFont = c->pGC->font, oldpFont; 1098f7df2e56Smrg int err = Success, lgerr; /* err is in X error, not font error, space */ 109905b261ecSmrg enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT; 110005b261ecSmrg FontPathElementPtr fpe; 110105b261ecSmrg GC *origGC = NULL; 11029ace9065Smrg int itemSize = c->reqType == X_PolyText8 ? 1 : 2; 110305b261ecSmrg 1104f7df2e56Smrg if (client->clientGone) { 1105f7df2e56Smrg fpe = c->pGC->font->fpe; 11067e31ba66Smrg (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe); 1107f7df2e56Smrg 1108f7df2e56Smrg if (ClientIsAsleep(client)) { 1109f7df2e56Smrg /* Client has died, but we cannot bail out right now. We 1110f7df2e56Smrg need to clean up after the work we did when going to 11115a112b11Smrg sleep. Setting the drawable pointer to 0 makes this 1112f7df2e56Smrg happen without any attempts to render or perform other 1113f7df2e56Smrg unnecessary activities. */ 1114f7df2e56Smrg c->pDraw = (DrawablePtr) 0; 1115f7df2e56Smrg } 1116f7df2e56Smrg else { 1117f7df2e56Smrg err = Success; 1118f7df2e56Smrg goto bail; 1119f7df2e56Smrg } 112005b261ecSmrg } 112105b261ecSmrg 112205b261ecSmrg /* Make sure our drawable hasn't disappeared while we slept. */ 1123f7df2e56Smrg if (ClientIsAsleep(client) && c->pDraw) { 1124f7df2e56Smrg DrawablePtr pDraw; 1125f7df2e56Smrg 1126f7df2e56Smrg dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess); 1127f7df2e56Smrg if (c->pDraw != pDraw) { 1128f7df2e56Smrg /* Our drawable has disappeared. Treat like client died... ask 1129f7df2e56Smrg the FPE code to clean up after client and avoid further 1130f7df2e56Smrg rendering while we clean up after ourself. */ 1131f7df2e56Smrg fpe = c->pGC->font->fpe; 11327e31ba66Smrg (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe); 1133f7df2e56Smrg c->pDraw = (DrawablePtr) 0; 1134f7df2e56Smrg } 113505b261ecSmrg } 113605b261ecSmrg 11376747b715Smrg client_state = ClientIsAsleep(client) ? SLEEPING : NEVER_SLEPT; 113805b261ecSmrg 1139f7df2e56Smrg while (c->endReq - c->pElt > TextEltHeader) { 1140f7df2e56Smrg if (*c->pElt == FontChange) { 1141f7df2e56Smrg Font fid; 1142f7df2e56Smrg 1143f7df2e56Smrg if (c->endReq - c->pElt < FontShiftSize) { 1144f7df2e56Smrg err = BadLength; 1145f7df2e56Smrg goto bail; 1146f7df2e56Smrg } 1147f7df2e56Smrg 1148f7df2e56Smrg oldpFont = pFont; 1149f7df2e56Smrg 1150f7df2e56Smrg fid = ((Font) *(c->pElt + 4)) /* big-endian */ 1151f7df2e56Smrg |((Font) *(c->pElt + 3)) << 8 1152f7df2e56Smrg | ((Font) *(c->pElt + 2)) << 16 | ((Font) *(c->pElt + 1)) << 24; 1153f7df2e56Smrg err = dixLookupResourceByType((void **) &pFont, fid, RT_FONT, 1154f7df2e56Smrg client, DixUseAccess); 1155f7df2e56Smrg if (err != Success) { 1156f7df2e56Smrg /* restore pFont for step 4 (described below) */ 1157f7df2e56Smrg pFont = oldpFont; 1158f7df2e56Smrg 1159f7df2e56Smrg /* If we're in START_SLEEP mode, the following step 1160f7df2e56Smrg shortens the request... in the unlikely event that 1161f7df2e56Smrg the fid somehow becomes valid before we come through 1162f7df2e56Smrg again to actually execute the polytext, which would 1163f7df2e56Smrg then mess up our refcounting scheme badly. */ 1164f7df2e56Smrg c->err = err; 1165f7df2e56Smrg c->endReq = c->pElt; 1166f7df2e56Smrg 1167f7df2e56Smrg goto bail; 1168f7df2e56Smrg } 1169f7df2e56Smrg 1170f7df2e56Smrg /* Step 3 (described below) on our new font */ 1171f7df2e56Smrg if (client_state == START_SLEEP) 1172f7df2e56Smrg pFont->refcnt++; 1173f7df2e56Smrg else { 1174f7df2e56Smrg if (pFont != c->pGC->font && c->pDraw) { 1175f7df2e56Smrg ChangeGCVal val; 1176f7df2e56Smrg 1177f7df2e56Smrg val.ptr = pFont; 1178f7df2e56Smrg ChangeGC(NullClient, c->pGC, GCFont, &val); 1179f7df2e56Smrg ValidateGC(c->pDraw, c->pGC); 1180f7df2e56Smrg } 1181f7df2e56Smrg 1182f7df2e56Smrg /* Undo the refcnt++ we performed when going to sleep */ 1183f7df2e56Smrg if (client_state == SLEEPING) 1184f7df2e56Smrg (void) CloseFont(c->pGC->font, (Font) 0); 1185f7df2e56Smrg } 1186f7df2e56Smrg c->pElt += FontShiftSize; 1187f7df2e56Smrg } 1188f7df2e56Smrg else { /* print a string */ 1189f7df2e56Smrg 1190f7df2e56Smrg unsigned char *pNextElt; 1191f7df2e56Smrg 1192f7df2e56Smrg pNextElt = c->pElt + TextEltHeader + (*c->pElt) * itemSize; 1193f7df2e56Smrg if (pNextElt > c->endReq) { 1194f7df2e56Smrg err = BadLength; 1195f7df2e56Smrg goto bail; 1196f7df2e56Smrg } 1197f7df2e56Smrg if (client_state == START_SLEEP) { 1198f7df2e56Smrg c->pElt = pNextElt; 1199f7df2e56Smrg continue; 1200f7df2e56Smrg } 1201f7df2e56Smrg if (c->pDraw) { 1202f7df2e56Smrg lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, itemSize, 1203f7df2e56Smrg c->pElt + TextEltHeader); 1204f7df2e56Smrg } 1205f7df2e56Smrg else 1206f7df2e56Smrg lgerr = Successful; 1207f7df2e56Smrg 1208f7df2e56Smrg if (lgerr == Suspended) { 1209f7df2e56Smrg if (!ClientIsAsleep(client)) { 1210f7df2e56Smrg int len; 1211f7df2e56Smrg GC *pGC; 1212f7df2e56Smrg PTclosurePtr new_closure; 1213f7df2e56Smrg 1214f7df2e56Smrg /* We're putting the client to sleep. We need to do a few things 1215f7df2e56Smrg to ensure successful and atomic-appearing execution of the 1216f7df2e56Smrg remainder of the request. First, copy the remainder of the 1217f7df2e56Smrg request into a safe malloc'd area. Second, create a scratch GC 1218f7df2e56Smrg to use for the remainder of the request. Third, mark all fonts 1219f7df2e56Smrg referenced in the remainder of the request to prevent their 1220f7df2e56Smrg deallocation. Fourth, make the original GC look like the 1221f7df2e56Smrg request has completed... set its font to the final font value 1222f7df2e56Smrg from this request. These GC manipulations are for the unlikely 1223f7df2e56Smrg (but possible) event that some other client is using the GC. 1224f7df2e56Smrg Steps 3 and 4 are performed by running this procedure through 1225f7df2e56Smrg the remainder of the request in a special no-render mode 1226f7df2e56Smrg indicated by client_state = START_SLEEP. */ 1227f7df2e56Smrg 1228f7df2e56Smrg /* Step 1 */ 1229f7df2e56Smrg /* Allocate a malloc'd closure structure to replace 1230f7df2e56Smrg the local one we were passed */ 1231f7df2e56Smrg new_closure = malloc(sizeof(PTclosureRec)); 1232f7df2e56Smrg if (!new_closure) { 1233f7df2e56Smrg err = BadAlloc; 1234f7df2e56Smrg goto bail; 1235f7df2e56Smrg } 1236f7df2e56Smrg *new_closure = *c; 1237f7df2e56Smrg 1238f7df2e56Smrg len = new_closure->endReq - new_closure->pElt; 1239f7df2e56Smrg new_closure->data = malloc(len); 1240f7df2e56Smrg if (!new_closure->data) { 1241f7df2e56Smrg free(new_closure); 1242f7df2e56Smrg err = BadAlloc; 1243f7df2e56Smrg goto bail; 1244f7df2e56Smrg } 1245f7df2e56Smrg memmove(new_closure->data, new_closure->pElt, len); 1246f7df2e56Smrg new_closure->pElt = new_closure->data; 1247f7df2e56Smrg new_closure->endReq = new_closure->pElt + len; 1248f7df2e56Smrg 1249f7df2e56Smrg /* Step 2 */ 1250f7df2e56Smrg 1251f7df2e56Smrg pGC = 1252f7df2e56Smrg GetScratchGC(new_closure->pGC->depth, 1253f7df2e56Smrg new_closure->pGC->pScreen); 1254f7df2e56Smrg if (!pGC) { 1255f7df2e56Smrg free(new_closure->data); 1256f7df2e56Smrg free(new_closure); 1257f7df2e56Smrg err = BadAlloc; 1258f7df2e56Smrg goto bail; 1259f7df2e56Smrg } 1260f7df2e56Smrg if ((err = CopyGC(new_closure->pGC, pGC, GCFunction | 1261f7df2e56Smrg GCPlaneMask | GCForeground | 1262f7df2e56Smrg GCBackground | GCFillStyle | 1263f7df2e56Smrg GCTile | GCStipple | 1264f7df2e56Smrg GCTileStipXOrigin | 1265f7df2e56Smrg GCTileStipYOrigin | GCFont | 1266f7df2e56Smrg GCSubwindowMode | GCClipXOrigin | 1267f7df2e56Smrg GCClipYOrigin | GCClipMask)) != Success) { 1268f7df2e56Smrg FreeScratchGC(pGC); 1269f7df2e56Smrg free(new_closure->data); 1270f7df2e56Smrg free(new_closure); 1271f7df2e56Smrg err = BadAlloc; 1272f7df2e56Smrg goto bail; 1273f7df2e56Smrg } 1274f7df2e56Smrg c = new_closure; 1275f7df2e56Smrg origGC = c->pGC; 1276f7df2e56Smrg c->pGC = pGC; 1277f7df2e56Smrg ValidateGC(c->pDraw, c->pGC); 1278f7df2e56Smrg 1279f7df2e56Smrg ClientSleep(client, (ClientSleepProcPtr) doPolyText, c); 1280f7df2e56Smrg 1281f7df2e56Smrg /* Set up to perform steps 3 and 4 */ 1282f7df2e56Smrg client_state = START_SLEEP; 1283f7df2e56Smrg continue; /* on to steps 3 and 4 */ 1284f7df2e56Smrg } 1285f7df2e56Smrg return TRUE; 1286f7df2e56Smrg } 1287f7df2e56Smrg else if (lgerr != Successful) { 1288f7df2e56Smrg err = FontToXError(lgerr); 1289f7df2e56Smrg goto bail; 1290f7df2e56Smrg } 1291f7df2e56Smrg if (c->pDraw) { 1292f7df2e56Smrg c->xorg += *((INT8 *) (c->pElt + 1)); /* must be signed */ 1293f7df2e56Smrg if (c->reqType == X_PolyText8) 1294f7df2e56Smrg c->xorg = 1295f7df2e56Smrg (*c->pGC->ops->PolyText8) (c->pDraw, c->pGC, c->xorg, 1296f7df2e56Smrg c->yorg, *c->pElt, 1297f7df2e56Smrg (char *) (c->pElt + 1298f7df2e56Smrg TextEltHeader)); 1299f7df2e56Smrg else 1300f7df2e56Smrg c->xorg = 1301f7df2e56Smrg (*c->pGC->ops->PolyText16) (c->pDraw, c->pGC, c->xorg, 1302f7df2e56Smrg c->yorg, *c->pElt, 1303f7df2e56Smrg (unsigned short *) (c-> 1304f7df2e56Smrg pElt + 1305f7df2e56Smrg TextEltHeader)); 1306f7df2e56Smrg } 1307f7df2e56Smrg c->pElt = pNextElt; 1308f7df2e56Smrg } 1309f7df2e56Smrg } 1310f7df2e56Smrg 1311f7df2e56Smrg bail: 1312f7df2e56Smrg 1313f7df2e56Smrg if (client_state == START_SLEEP) { 1314f7df2e56Smrg /* Step 4 */ 1315f7df2e56Smrg if (pFont != origGC->font) { 1316f7df2e56Smrg ChangeGCVal val; 1317f7df2e56Smrg 1318f7df2e56Smrg val.ptr = pFont; 1319f7df2e56Smrg ChangeGC(NullClient, origGC, GCFont, &val); 1320f7df2e56Smrg ValidateGC(c->pDraw, origGC); 1321f7df2e56Smrg } 1322f7df2e56Smrg 1323f7df2e56Smrg /* restore pElt pointer for execution of remainder of the request */ 1324f7df2e56Smrg c->pElt = c->data; 1325f7df2e56Smrg return TRUE; 1326f7df2e56Smrg } 1327f7df2e56Smrg 1328f7df2e56Smrg if (c->err != Success) 1329f7df2e56Smrg err = c->err; 133005b261ecSmrg if (err != Success && c->client != serverClient) { 133105b261ecSmrg#ifdef PANORAMIX 133205b261ecSmrg if (noPanoramiXExtension || !c->pGC->pScreen->myNum) 133305b261ecSmrg#endif 1334f7df2e56Smrg SendErrorToClient(c->client, c->reqType, 0, 0, err); 133505b261ecSmrg } 1336f7df2e56Smrg if (ClientIsAsleep(client)) { 1337f7df2e56Smrg ClientWakeup(c->client); 1338f7df2e56Smrg ChangeGC(NullClient, c->pGC, clearGCmask, clearGC); 133905b261ecSmrg 1340f7df2e56Smrg /* Unreference the font from the scratch GC */ 1341f7df2e56Smrg CloseFont(c->pGC->font, (Font) 0); 1342f7df2e56Smrg c->pGC->font = NullFont; 134305b261ecSmrg 1344f7df2e56Smrg FreeScratchGC(c->pGC); 1345f7df2e56Smrg free(c->data); 1346f7df2e56Smrg free(c); 134705b261ecSmrg } 134805b261ecSmrg return TRUE; 134905b261ecSmrg} 135005b261ecSmrg 135105b261ecSmrgint 1352f7df2e56SmrgPolyText(ClientPtr client, DrawablePtr pDraw, GC * pGC, unsigned char *pElt, 135305b261ecSmrg unsigned char *endReq, int xorg, int yorg, int reqType, XID did) 135405b261ecSmrg{ 135559ca590cSmrg PTclosureRec local_closure = { 135659ca590cSmrg .client = client, 135759ca590cSmrg .pDraw = pDraw, 135859ca590cSmrg .pGC = pGC, 135959ca590cSmrg .pElt = pElt, 136059ca590cSmrg .endReq = endReq, 136159ca590cSmrg .xorg = xorg, 136259ca590cSmrg .yorg = yorg, 136359ca590cSmrg .reqType = reqType, 136459ca590cSmrg .did = did, 136559ca590cSmrg .err = Success 136659ca590cSmrg }; 136705b261ecSmrg 136805b261ecSmrg (void) doPolyText(client, &local_closure); 136905b261ecSmrg return Success; 137005b261ecSmrg} 137105b261ecSmrg 137205b261ecSmrg#undef TextEltHeader 137305b261ecSmrg#undef FontShiftSize 137405b261ecSmrg 1375f7df2e56Smrgstatic int 137605b261ecSmrgdoImageText(ClientPtr client, ITclosurePtr c) 137705b261ecSmrg{ 1378f7df2e56Smrg int err = Success, lgerr; /* err is in X error, not font error, space */ 137905b261ecSmrg FontPathElementPtr fpe; 13809ace9065Smrg int itemSize = c->reqType == X_ImageText8 ? 1 : 2; 138105b261ecSmrg 1382f7df2e56Smrg if (client->clientGone) { 1383f7df2e56Smrg fpe = c->pGC->font->fpe; 13847e31ba66Smrg (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe); 1385f7df2e56Smrg err = Success; 1386f7df2e56Smrg goto bail; 138705b261ecSmrg } 138805b261ecSmrg 138905b261ecSmrg /* Make sure our drawable hasn't disappeared while we slept. */ 1390f7df2e56Smrg if (ClientIsAsleep(client) && c->pDraw) { 1391f7df2e56Smrg DrawablePtr pDraw; 1392f7df2e56Smrg 1393f7df2e56Smrg dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess); 1394f7df2e56Smrg if (c->pDraw != pDraw) { 1395f7df2e56Smrg /* Our drawable has disappeared. Treat like client died... ask 1396f7df2e56Smrg the FPE code to clean up after client. */ 1397f7df2e56Smrg fpe = c->pGC->font->fpe; 13987e31ba66Smrg (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe); 1399f7df2e56Smrg err = Success; 1400f7df2e56Smrg goto bail; 1401f7df2e56Smrg } 140205b261ecSmrg } 140305b261ecSmrg 14049ace9065Smrg lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, itemSize, c->data); 1405f7df2e56Smrg if (lgerr == Suspended) { 14066747b715Smrg if (!ClientIsAsleep(client)) { 1407f7df2e56Smrg GC *pGC; 1408f7df2e56Smrg unsigned char *data; 1409f7df2e56Smrg ITclosurePtr new_closure; 14102717a907Sspz ITclosurePtr old_closure; 141105b261ecSmrg 1412f7df2e56Smrg /* We're putting the client to sleep. We need to 1413f7df2e56Smrg save some state. Similar problem to that handled 1414f7df2e56Smrg in doPolyText, but much simpler because the 1415f7df2e56Smrg request structure is much simpler. */ 1416f7df2e56Smrg 1417f7df2e56Smrg new_closure = malloc(sizeof(ITclosureRec)); 1418f7df2e56Smrg if (!new_closure) { 1419f7df2e56Smrg err = BadAlloc; 1420f7df2e56Smrg goto bail; 1421f7df2e56Smrg } 14222717a907Sspz old_closure = c; 1423f7df2e56Smrg *new_closure = *c; 1424f7df2e56Smrg c = new_closure; 142505b261ecSmrg 1426f7df2e56Smrg data = xallocarray(c->nChars, itemSize); 1427f7df2e56Smrg if (!data) { 1428f7df2e56Smrg free(c); 14292717a907Sspz c = old_closure; 1430f7df2e56Smrg err = BadAlloc; 1431f7df2e56Smrg goto bail; 1432f7df2e56Smrg } 1433f7df2e56Smrg memmove(data, c->data, c->nChars * itemSize); 1434f7df2e56Smrg c->data = data; 1435f7df2e56Smrg 1436f7df2e56Smrg pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); 1437f7df2e56Smrg if (!pGC) { 1438f7df2e56Smrg free(c->data); 1439f7df2e56Smrg free(c); 14402717a907Sspz c = old_closure; 1441f7df2e56Smrg err = BadAlloc; 1442f7df2e56Smrg goto bail; 1443f7df2e56Smrg } 1444f7df2e56Smrg if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask | 1445f7df2e56Smrg GCForeground | GCBackground | GCFillStyle | 1446f7df2e56Smrg GCTile | GCStipple | GCTileStipXOrigin | 1447f7df2e56Smrg GCTileStipYOrigin | GCFont | 1448f7df2e56Smrg GCSubwindowMode | GCClipXOrigin | 1449f7df2e56Smrg GCClipYOrigin | GCClipMask)) != Success) { 1450f7df2e56Smrg FreeScratchGC(pGC); 1451f7df2e56Smrg free(c->data); 1452f7df2e56Smrg free(c); 14532717a907Sspz c = old_closure; 1454f7df2e56Smrg err = BadAlloc; 1455f7df2e56Smrg goto bail; 1456f7df2e56Smrg } 1457f7df2e56Smrg c->pGC = pGC; 1458f7df2e56Smrg ValidateGC(c->pDraw, c->pGC); 145905b261ecSmrg 1460f7df2e56Smrg ClientSleep(client, (ClientSleepProcPtr) doImageText, c); 146105b261ecSmrg } 146205b261ecSmrg return TRUE; 146305b261ecSmrg } 1464f7df2e56Smrg else if (lgerr != Successful) { 146505b261ecSmrg err = FontToXError(lgerr); 146605b261ecSmrg goto bail; 146705b261ecSmrg } 1468f7df2e56Smrg if (c->pDraw) { 1469f7df2e56Smrg if (c->reqType == X_ImageText8) 1470f7df2e56Smrg (*c->pGC->ops->ImageText8) (c->pDraw, c->pGC, c->xorg, c->yorg, 1471f7df2e56Smrg c->nChars, (char *) c->data); 1472f7df2e56Smrg else 1473f7df2e56Smrg (*c->pGC->ops->ImageText16) (c->pDraw, c->pGC, c->xorg, c->yorg, 1474f7df2e56Smrg c->nChars, (unsigned short *) c->data); 147505b261ecSmrg } 147605b261ecSmrg 1477f7df2e56Smrg bail: 147805b261ecSmrg 147905b261ecSmrg if (err != Success && c->client != serverClient) { 1480f7df2e56Smrg SendErrorToClient(c->client, c->reqType, 0, 0, err); 148105b261ecSmrg } 1482f7df2e56Smrg if (ClientIsAsleep(client)) { 1483f7df2e56Smrg ClientWakeup(c->client); 1484f7df2e56Smrg ChangeGC(NullClient, c->pGC, clearGCmask, clearGC); 148505b261ecSmrg 1486f7df2e56Smrg /* Unreference the font from the scratch GC */ 1487f7df2e56Smrg CloseFont(c->pGC->font, (Font) 0); 1488f7df2e56Smrg c->pGC->font = NullFont; 148905b261ecSmrg 1490f7df2e56Smrg FreeScratchGC(c->pGC); 1491f7df2e56Smrg free(c->data); 1492f7df2e56Smrg free(c); 149305b261ecSmrg } 149405b261ecSmrg return TRUE; 149505b261ecSmrg} 149605b261ecSmrg 149705b261ecSmrgint 1498f7df2e56SmrgImageText(ClientPtr client, DrawablePtr pDraw, GC * pGC, int nChars, 149905b261ecSmrg unsigned char *data, int xorg, int yorg, int reqType, XID did) 150005b261ecSmrg{ 150105b261ecSmrg ITclosureRec local_closure; 150205b261ecSmrg 150305b261ecSmrg local_closure.client = client; 150405b261ecSmrg local_closure.pDraw = pDraw; 150505b261ecSmrg local_closure.pGC = pGC; 150605b261ecSmrg local_closure.nChars = nChars; 150705b261ecSmrg local_closure.data = data; 150805b261ecSmrg local_closure.xorg = xorg; 150905b261ecSmrg local_closure.yorg = yorg; 15109ace9065Smrg local_closure.reqType = reqType; 151105b261ecSmrg local_closure.did = did; 151205b261ecSmrg 151305b261ecSmrg (void) doImageText(client, &local_closure); 151405b261ecSmrg return Success; 151505b261ecSmrg} 151605b261ecSmrg 151705b261ecSmrg/* does the necessary magic to figure out the fpe type */ 151805b261ecSmrgstatic int 1519f7df2e56SmrgDetermineFPEType(const char *pathname) 152005b261ecSmrg{ 1521f7df2e56Smrg int i; 152205b261ecSmrg 152305b261ecSmrg for (i = 0; i < num_fpe_types; i++) { 15247e31ba66Smrg if ((*fpe_functions[i]->name_check) (pathname)) 1525f7df2e56Smrg return i; 152605b261ecSmrg } 152705b261ecSmrg return -1; 152805b261ecSmrg} 152905b261ecSmrg 153005b261ecSmrgstatic void 1531f7df2e56SmrgFreeFontPath(FontPathElementPtr * list, int n, Bool force) 153205b261ecSmrg{ 1533f7df2e56Smrg int i; 153405b261ecSmrg 153505b261ecSmrg for (i = 0; i < n; i++) { 1536f7df2e56Smrg if (force) { 1537f7df2e56Smrg /* Sanity check that all refcounts will be 0 by the time 1538f7df2e56Smrg we get to the end of the list. */ 1539f7df2e56Smrg int found = 1; /* the first reference is us */ 1540f7df2e56Smrg int j; 1541f7df2e56Smrg 1542f7df2e56Smrg for (j = i + 1; j < n; j++) { 1543f7df2e56Smrg if (list[j] == list[i]) 1544f7df2e56Smrg found++; 1545f7df2e56Smrg } 1546f7df2e56Smrg if (list[i]->refcount != found) { 1547f7df2e56Smrg list[i]->refcount = found; /* ensure it will get freed */ 1548f7df2e56Smrg } 1549f7df2e56Smrg } 1550f7df2e56Smrg FreeFPE(list[i]); 155105b261ecSmrg } 15526747b715Smrg free(list); 155305b261ecSmrg} 155405b261ecSmrg 155505b261ecSmrgstatic FontPathElementPtr 1556f7df2e56Smrgfind_existing_fpe(FontPathElementPtr * list, int num, unsigned char *name, 1557f7df2e56Smrg int len) 155805b261ecSmrg{ 155905b261ecSmrg FontPathElementPtr fpe; 1560f7df2e56Smrg int i; 156105b261ecSmrg 156205b261ecSmrg for (i = 0; i < num; i++) { 1563f7df2e56Smrg fpe = list[i]; 1564f7df2e56Smrg if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0) 1565f7df2e56Smrg return fpe; 156605b261ecSmrg } 156705b261ecSmrg return (FontPathElementPtr) 0; 156805b261ecSmrg} 156905b261ecSmrg 157005b261ecSmrgstatic int 157105b261ecSmrgSetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist) 157205b261ecSmrg{ 1573f7df2e56Smrg int i, err = 0; 1574f7df2e56Smrg int valid_paths = 0; 157505b261ecSmrg unsigned int len; 157605b261ecSmrg unsigned char *cp = paths; 157705b261ecSmrg FontPathElementPtr fpe = NULL, *fplist; 157805b261ecSmrg 1579f7df2e56Smrg fplist = xallocarray(npaths, sizeof(FontPathElementPtr)); 158005b261ecSmrg if (!fplist) { 1581f7df2e56Smrg *bad = 0; 1582f7df2e56Smrg return BadAlloc; 158305b261ecSmrg } 158405b261ecSmrg for (i = 0; i < num_fpe_types; i++) { 15857e31ba66Smrg if (fpe_functions[i]->set_path_hook) 15867e31ba66Smrg (*fpe_functions[i]->set_path_hook) (); 1587f7df2e56Smrg } 1588f7df2e56Smrg for (i = 0; i < npaths; i++) { 1589f7df2e56Smrg len = (unsigned int) (*cp++); 1590f7df2e56Smrg 1591f7df2e56Smrg if (len == 0) { 1592f7df2e56Smrg if (persist) 1593f7df2e56Smrg ErrorF 1594f7df2e56Smrg ("[dix] Removing empty element from the valid list of fontpaths\n"); 1595f7df2e56Smrg err = BadValue; 1596f7df2e56Smrg } 1597f7df2e56Smrg else { 1598f7df2e56Smrg /* if it's already in our active list, just reset it */ 1599f7df2e56Smrg /* 1600f7df2e56Smrg * note that this can miss FPE's in limbo -- may be worth catching 1601f7df2e56Smrg * them, though it'd muck up refcounting 1602f7df2e56Smrg */ 1603f7df2e56Smrg fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len); 1604f7df2e56Smrg if (fpe) { 16057e31ba66Smrg err = (*fpe_functions[fpe->type]->reset_fpe) (fpe); 1606f7df2e56Smrg if (err == Successful) { 1607f7df2e56Smrg UseFPE(fpe); /* since it'll be decref'd later when freed 1608f7df2e56Smrg * from the old list */ 1609f7df2e56Smrg } 1610f7df2e56Smrg else 1611f7df2e56Smrg fpe = 0; 1612f7df2e56Smrg } 1613f7df2e56Smrg /* if error or can't do it, act like it's a new one */ 1614f7df2e56Smrg if (!fpe) { 1615f7df2e56Smrg char *name; 1616f7df2e56Smrg fpe = malloc(sizeof(FontPathElementRec)); 1617f7df2e56Smrg if (!fpe) { 1618f7df2e56Smrg err = BadAlloc; 1619f7df2e56Smrg goto bail; 1620f7df2e56Smrg } 1621f7df2e56Smrg name = malloc(len + 1); 1622f7df2e56Smrg if (!name) { 1623f7df2e56Smrg free(fpe); 1624f7df2e56Smrg err = BadAlloc; 1625f7df2e56Smrg goto bail; 1626f7df2e56Smrg } 1627f7df2e56Smrg fpe->refcount = 1; 1628f7df2e56Smrg 1629f7df2e56Smrg strncpy(name, (char *) cp, (int) len); 1630f7df2e56Smrg name[len] = '\0'; 1631f7df2e56Smrg fpe->name = name; 1632f7df2e56Smrg fpe->name_length = len; 1633f7df2e56Smrg fpe->type = DetermineFPEType(fpe->name); 1634f7df2e56Smrg if (fpe->type == -1) 1635f7df2e56Smrg err = BadValue; 1636f7df2e56Smrg else 16377e31ba66Smrg err = (*fpe_functions[fpe->type]->init_fpe) (fpe); 1638f7df2e56Smrg if (err != Successful) { 1639f7df2e56Smrg if (persist) { 1640f7df2e56Smrg DebugF 1641f7df2e56Smrg ("[dix] Could not init font path element %s, removing from list!\n", 1642f7df2e56Smrg fpe->name); 1643f7df2e56Smrg } 1644f7df2e56Smrg free((void *) fpe->name); 1645f7df2e56Smrg free(fpe); 1646f7df2e56Smrg } 1647f7df2e56Smrg } 1648f7df2e56Smrg } 1649f7df2e56Smrg if (err != Successful) { 1650f7df2e56Smrg if (!persist) 1651f7df2e56Smrg goto bail; 1652f7df2e56Smrg } 1653f7df2e56Smrg else { 1654f7df2e56Smrg fplist[valid_paths++] = fpe; 1655f7df2e56Smrg } 1656f7df2e56Smrg cp += len; 165705b261ecSmrg } 165805b261ecSmrg 165905b261ecSmrg FreeFontPath(font_path_elements, num_fpes, FALSE); 166005b261ecSmrg font_path_elements = fplist; 166105b261ecSmrg if (patternCache) 16627e31ba66Smrg xfont2_empty_font_pattern_cache(patternCache); 166305b261ecSmrg num_fpes = valid_paths; 166405b261ecSmrg 166505b261ecSmrg return Success; 1666f7df2e56Smrg bail: 166705b261ecSmrg *bad = i; 166805b261ecSmrg while (--valid_paths >= 0) 1669f7df2e56Smrg FreeFPE(fplist[valid_paths]); 16706747b715Smrg free(fplist); 167105b261ecSmrg return FontToXError(err); 167205b261ecSmrg} 167305b261ecSmrg 167405b261ecSmrgint 16756747b715SmrgSetFontPath(ClientPtr client, int npaths, unsigned char *paths) 167605b261ecSmrg{ 16774642e01fSmrg int err = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess); 1678f7df2e56Smrg 16794642e01fSmrg if (err != Success) 1680f7df2e56Smrg return err; 168105b261ecSmrg 168205b261ecSmrg if (npaths == 0) { 1683f7df2e56Smrg if (SetDefaultFontPath(defaultFontPath) != Success) 1684f7df2e56Smrg return BadValue; 1685f7df2e56Smrg } 1686f7df2e56Smrg else { 1687f7df2e56Smrg int bad; 1688f7df2e56Smrg 1689f7df2e56Smrg err = SetFontPathElements(npaths, paths, &bad, FALSE); 169059ca590cSmrg if (err != Success) 169159ca590cSmrg client->errorValue = bad; 169205b261ecSmrg } 169305b261ecSmrg return err; 169405b261ecSmrg} 169505b261ecSmrg 169605b261ecSmrgint 1697f7df2e56SmrgSetDefaultFontPath(const char *path) 169805b261ecSmrg{ 1699f7df2e56Smrg const char *start, *end; 1700f7df2e56Smrg char *temp_path; 1701f7df2e56Smrg unsigned char *cp, *pp, *nump, *newpath; 1702f7df2e56Smrg int num = 1, len, err, size = 0, bad; 170305b261ecSmrg 1704b1d344b3Smrg /* ensure temp_path contains "built-ins" */ 1705b1d344b3Smrg start = path; 1706b1d344b3Smrg while (1) { 1707f7df2e56Smrg start = strstr(start, "built-ins"); 1708f7df2e56Smrg if (start == NULL) 1709f7df2e56Smrg break; 1710f7df2e56Smrg end = start + strlen("built-ins"); 1711f7df2e56Smrg if ((start == path || start[-1] == ',') && (!*end || *end == ',')) 1712f7df2e56Smrg break; 1713f7df2e56Smrg start = end; 1714b1d344b3Smrg } 1715b1d344b3Smrg if (!start) { 1716f7df2e56Smrg if (asprintf(&temp_path, "%s%sbuilt-ins", path, *path ? "," : "") 1717f7df2e56Smrg == -1) 1718f7df2e56Smrg temp_path = NULL; 1719f7df2e56Smrg } 1720f7df2e56Smrg else { 1721f7df2e56Smrg temp_path = strdup(path); 1722b1d344b3Smrg } 1723b1d344b3Smrg if (!temp_path) 1724b1d344b3Smrg return BadAlloc; 1725b1d344b3Smrg 172605b261ecSmrg /* get enough for string, plus values -- use up commas */ 1727b1d344b3Smrg len = strlen(temp_path) + 1; 17286747b715Smrg nump = cp = newpath = malloc(len); 17299ace9065Smrg if (!newpath) { 1730f7df2e56Smrg free(temp_path); 1731f7df2e56Smrg return BadAlloc; 17329ace9065Smrg } 1733b1d344b3Smrg pp = (unsigned char *) temp_path; 173405b261ecSmrg cp++; 173505b261ecSmrg while (*pp) { 1736f7df2e56Smrg if (*pp == ',') { 1737f7df2e56Smrg *nump = (unsigned char) size; 1738f7df2e56Smrg nump = cp++; 1739f7df2e56Smrg pp++; 1740f7df2e56Smrg num++; 1741f7df2e56Smrg size = 0; 1742f7df2e56Smrg } 1743f7df2e56Smrg else { 1744f7df2e56Smrg *cp++ = *pp++; 1745f7df2e56Smrg size++; 1746f7df2e56Smrg } 174705b261ecSmrg } 174805b261ecSmrg *nump = (unsigned char) size; 174905b261ecSmrg 175005b261ecSmrg err = SetFontPathElements(num, newpath, &bad, TRUE); 175105b261ecSmrg 17526747b715Smrg free(newpath); 17536747b715Smrg free(temp_path); 175405b261ecSmrg 175505b261ecSmrg return err; 175605b261ecSmrg} 175705b261ecSmrg 17584642e01fSmrgint 17594642e01fSmrgGetFontPath(ClientPtr client, int *count, int *length, unsigned char **result) 176005b261ecSmrg{ 1761f7df2e56Smrg int i; 1762f7df2e56Smrg unsigned char *c; 1763f7df2e56Smrg int len; 1764f7df2e56Smrg FontPathElementPtr fpe; 176505b261ecSmrg 17664642e01fSmrg i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess); 17674642e01fSmrg if (i != Success) 1768f7df2e56Smrg return i; 17694642e01fSmrg 177005b261ecSmrg len = 0; 177105b261ecSmrg for (i = 0; i < num_fpes; i++) { 1772f7df2e56Smrg fpe = font_path_elements[i]; 1773f7df2e56Smrg len += fpe->name_length + 1; 1774f7df2e56Smrg } 1775f7df2e56Smrg c = realloc(font_path_string, len); 1776f7df2e56Smrg if (c == NULL) { 1777f7df2e56Smrg free(font_path_string); 1778f7df2e56Smrg font_path_string = NULL; 1779f7df2e56Smrg return BadAlloc; 178005b261ecSmrg } 178105b261ecSmrg 1782f7df2e56Smrg font_path_string = c; 178305b261ecSmrg *length = 0; 178405b261ecSmrg for (i = 0; i < num_fpes; i++) { 1785f7df2e56Smrg fpe = font_path_elements[i]; 1786f7df2e56Smrg *c = fpe->name_length; 1787f7df2e56Smrg *length += *c++; 1788f7df2e56Smrg memmove(c, fpe->name, fpe->name_length); 1789f7df2e56Smrg c += fpe->name_length; 179005b261ecSmrg } 179105b261ecSmrg *count = num_fpes; 17924642e01fSmrg *result = font_path_string; 17934642e01fSmrg return Success; 179405b261ecSmrg} 179505b261ecSmrg 179605b261ecSmrgvoid 179705b261ecSmrgDeleteClientFontStuff(ClientPtr client) 179805b261ecSmrg{ 1799f7df2e56Smrg int i; 1800f7df2e56Smrg FontPathElementPtr fpe; 180105b261ecSmrg 1802f7df2e56Smrg for (i = 0; i < num_fpes; i++) { 1803f7df2e56Smrg fpe = font_path_elements[i]; 18047e31ba66Smrg if (fpe_functions[fpe->type]->client_died) 18057e31ba66Smrg (*fpe_functions[fpe->type]->client_died) ((void *) client, fpe); 180605b261ecSmrg } 180705b261ecSmrg} 180805b261ecSmrg 18097e31ba66Smrgstatic int 18107e31ba66Smrgregister_fpe_funcs(const xfont2_fpe_funcs_rec *funcs) 181105b261ecSmrg{ 18127e31ba66Smrg xfont2_fpe_funcs_rec const **new; 181305b261ecSmrg 18147e31ba66Smrg /* grow the list */ 18157e31ba66Smrg new = reallocarray(fpe_functions, num_fpe_types + 1, sizeof(xfont2_fpe_funcs_ptr)); 18167e31ba66Smrg if (!new) 18177e31ba66Smrg return -1; 18187e31ba66Smrg fpe_functions = new; 18197e31ba66Smrg 18207e31ba66Smrg fpe_functions[num_fpe_types] = funcs; 18217e31ba66Smrg 18227e31ba66Smrg return num_fpe_types++; 182305b261ecSmrg} 182405b261ecSmrg 18257e31ba66Smrgstatic unsigned long 18267e31ba66Smrgget_server_generation(void) 18277e31ba66Smrg{ 18287e31ba66Smrg return serverGeneration; 18297e31ba66Smrg} 18307e31ba66Smrg 18317e31ba66Smrgstatic void * 18327e31ba66Smrgget_server_client(void) 18337e31ba66Smrg{ 18347e31ba66Smrg return serverClient; 18357e31ba66Smrg} 18367e31ba66Smrg 18377e31ba66Smrgstatic int 18387e31ba66Smrgget_default_point_size(void) 183905b261ecSmrg{ 184005b261ecSmrg return 120; 184105b261ecSmrg} 184205b261ecSmrg 18437e31ba66Smrgstatic FontResolutionPtr 18447e31ba66Smrgget_client_resolutions(int *num) 184505b261ecSmrg{ 18464642e01fSmrg static struct _FontResolution res; 1847f7df2e56Smrg ScreenPtr pScreen; 184805b261ecSmrg 18494642e01fSmrg pScreen = screenInfo.screens[0]; 18504642e01fSmrg res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth; 18514642e01fSmrg /* 1852f7df2e56Smrg * XXX - we'll want this as long as bitmap instances are prevalent 18534642e01fSmrg so that we can match them from scalable fonts 18544642e01fSmrg */ 18554642e01fSmrg if (res.x_resolution < 88) 1856f7df2e56Smrg res.x_resolution = 75; 18574642e01fSmrg else 1858f7df2e56Smrg res.x_resolution = 100; 18594642e01fSmrg res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight; 18604642e01fSmrg if (res.y_resolution < 88) 1861f7df2e56Smrg res.y_resolution = 75; 18624642e01fSmrg else 1863f7df2e56Smrg res.y_resolution = 100; 18644642e01fSmrg res.point_size = 120; 18654642e01fSmrg *num = 1; 18664642e01fSmrg return &res; 186705b261ecSmrg} 186805b261ecSmrg 186905b261ecSmrgvoid 187005b261ecSmrgFreeFonts(void) 187105b261ecSmrg{ 187205b261ecSmrg if (patternCache) { 18737e31ba66Smrg xfont2_free_font_pattern_cache(patternCache); 1874f7df2e56Smrg patternCache = 0; 187505b261ecSmrg } 187605b261ecSmrg FreeFontPath(font_path_elements, num_fpes, TRUE); 187705b261ecSmrg font_path_elements = 0; 187805b261ecSmrg num_fpes = 0; 18796747b715Smrg free(fpe_functions); 188005b261ecSmrg num_fpe_types = 0; 18817e31ba66Smrg fpe_functions = NULL; 188205b261ecSmrg} 188305b261ecSmrg 188405b261ecSmrg/* convenience functions for FS interface */ 188505b261ecSmrg 18867e31ba66Smrgstatic FontPtr 188705b261ecSmrgfind_old_font(XID id) 188805b261ecSmrg{ 1889f7df2e56Smrg void *pFont; 1890f7df2e56Smrg 18916747b715Smrg dixLookupResourceByType(&pFont, id, RT_NONE, serverClient, DixReadAccess); 1892f7df2e56Smrg return (FontPtr) pFont; 189305b261ecSmrg} 189405b261ecSmrg 18957e31ba66Smrgstatic Font 18967e31ba66Smrgget_new_font_client_id(void) 189705b261ecSmrg{ 189805b261ecSmrg return FakeClientID(0); 189905b261ecSmrg} 190005b261ecSmrg 19017e31ba66Smrgstatic int 19027e31ba66Smrgstore_font_Client_font(FontPtr pfont, Font id) 190305b261ecSmrg{ 1904f7df2e56Smrg return AddResource(id, RT_NONE, (void *) pfont); 190505b261ecSmrg} 190605b261ecSmrg 19077e31ba66Smrgstatic void 19087e31ba66Smrgdelete_font_client_id(Font id) 190905b261ecSmrg{ 191005b261ecSmrg FreeResource(id, RT_NONE); 191105b261ecSmrg} 191205b261ecSmrg 19137e31ba66Smrgstatic int 19147e31ba66Smrg_client_auth_generation(ClientPtr client) 191505b261ecSmrg{ 191605b261ecSmrg return 0; 191705b261ecSmrg} 191805b261ecSmrg 1919f7df2e56Smrgstatic int fs_handlers_installed = 0; 192005b261ecSmrgstatic unsigned int last_server_gen; 192105b261ecSmrg 19227e31ba66Smrgstatic void fs_block_handler(void *blockData, void *timeout) 19237e31ba66Smrg{ 19247e31ba66Smrg FontBlockHandlerProcPtr block_handler = blockData; 19257e31ba66Smrg 19267e31ba66Smrg (*block_handler)(timeout); 19277e31ba66Smrg} 19287e31ba66Smrg 19297e31ba66Smrgstruct fs_fd_entry { 19307e31ba66Smrg struct xorg_list entry; 19317e31ba66Smrg int fd; 19327e31ba66Smrg void *data; 19337e31ba66Smrg FontFdHandlerProcPtr handler; 19347e31ba66Smrg}; 19357e31ba66Smrg 19367e31ba66Smrgstatic void 19377e31ba66Smrgfs_fd_handler(int fd, int ready, void *data) 19387e31ba66Smrg{ 19397e31ba66Smrg struct fs_fd_entry *entry = data; 19407e31ba66Smrg 19417e31ba66Smrg entry->handler(fd, entry->data); 19427e31ba66Smrg} 19437e31ba66Smrg 19447e31ba66Smrgstatic struct xorg_list fs_fd_list; 19457e31ba66Smrg 19467e31ba66Smrgstatic int 19477e31ba66Smrgadd_fs_fd(int fd, FontFdHandlerProcPtr handler, void *data) 19487e31ba66Smrg{ 19497e31ba66Smrg struct fs_fd_entry *entry = calloc(1, sizeof (struct fs_fd_entry)); 19507e31ba66Smrg 19517e31ba66Smrg if (!entry) 19527e31ba66Smrg return FALSE; 19537e31ba66Smrg 19547e31ba66Smrg entry->fd = fd; 19557e31ba66Smrg entry->data = data; 19567e31ba66Smrg entry->handler = handler; 19577e31ba66Smrg if (!SetNotifyFd(fd, fs_fd_handler, X_NOTIFY_READ, entry)) { 19587e31ba66Smrg free(entry); 19597e31ba66Smrg return FALSE; 19607e31ba66Smrg } 19617e31ba66Smrg xorg_list_add(&entry->entry, &fs_fd_list); 19627e31ba66Smrg return TRUE; 19637e31ba66Smrg} 19647e31ba66Smrg 19657e31ba66Smrgstatic void 19667e31ba66Smrgremove_fs_fd(int fd) 19677e31ba66Smrg{ 19687e31ba66Smrg struct fs_fd_entry *entry, *temp; 19697e31ba66Smrg 19707e31ba66Smrg xorg_list_for_each_entry_safe(entry, temp, &fs_fd_list, entry) { 19717e31ba66Smrg if (entry->fd == fd) { 19727e31ba66Smrg xorg_list_del(&entry->entry); 19737e31ba66Smrg free(entry); 19747e31ba66Smrg break; 19757e31ba66Smrg } 19767e31ba66Smrg } 19777e31ba66Smrg RemoveNotifyFd(fd); 19787e31ba66Smrg} 19797e31ba66Smrg 19807e31ba66Smrgstatic void 19817e31ba66Smrgadjust_fs_wait_for_delay(void *wt, unsigned long newdelay) 19827e31ba66Smrg{ 19837e31ba66Smrg AdjustWaitForDelay(wt, newdelay); 19847e31ba66Smrg} 19857e31ba66Smrg 19867e31ba66Smrgstatic int 19877e31ba66Smrg_init_fs_handlers(FontPathElementPtr fpe, FontBlockHandlerProcPtr block_handler) 198805b261ecSmrg{ 198905b261ecSmrg /* if server has reset, make sure the b&w handlers are reinstalled */ 199005b261ecSmrg if (last_server_gen < serverGeneration) { 1991f7df2e56Smrg last_server_gen = serverGeneration; 1992f7df2e56Smrg fs_handlers_installed = 0; 199305b261ecSmrg } 199405b261ecSmrg if (fs_handlers_installed == 0) { 19957e31ba66Smrg if (!RegisterBlockAndWakeupHandlers(fs_block_handler, 19967e31ba66Smrg FontWakeup, (void *) block_handler)) 1997f7df2e56Smrg return AllocError; 19987e31ba66Smrg xorg_list_init(&fs_fd_list); 1999f7df2e56Smrg fs_handlers_installed++; 200005b261ecSmrg } 200105b261ecSmrg QueueFontWakeup(fpe); 200205b261ecSmrg return Successful; 200305b261ecSmrg} 200405b261ecSmrg 20057e31ba66Smrgstatic void 20067e31ba66Smrg_remove_fs_handlers(FontPathElementPtr fpe, FontBlockHandlerProcPtr block_handler, 20077e31ba66Smrg Bool all) 200805b261ecSmrg{ 200905b261ecSmrg if (all) { 2010f7df2e56Smrg /* remove the handlers if no one else is using them */ 2011f7df2e56Smrg if (--fs_handlers_installed == 0) { 20127e31ba66Smrg RemoveBlockAndWakeupHandlers(fs_block_handler, FontWakeup, 20137e31ba66Smrg (void *) block_handler); 2014f7df2e56Smrg } 201505b261ecSmrg } 201605b261ecSmrg RemoveFontWakeup(fpe); 201705b261ecSmrg} 20187e31ba66Smrg 20197e31ba66Smrgstatic uint32_t wrap_time_in_millis(void) 20207e31ba66Smrg{ 20217e31ba66Smrg return GetTimeInMillis(); 20227e31ba66Smrg} 20237e31ba66Smrg 20247e31ba66Smrgstatic const xfont2_client_funcs_rec xfont2_client_funcs = { 20257e31ba66Smrg .version = XFONT2_CLIENT_FUNCS_VERSION, 20267e31ba66Smrg .client_auth_generation = _client_auth_generation, 20277e31ba66Smrg .client_signal = ClientSignal, 20287e31ba66Smrg .delete_font_client_id = delete_font_client_id, 20297e31ba66Smrg .verrorf = VErrorF, 20307e31ba66Smrg .find_old_font = find_old_font, 20317e31ba66Smrg .get_client_resolutions = get_client_resolutions, 20327e31ba66Smrg .get_default_point_size = get_default_point_size, 20337e31ba66Smrg .get_new_font_client_id = get_new_font_client_id, 20347e31ba66Smrg .get_time_in_millis = wrap_time_in_millis, 20357e31ba66Smrg .init_fs_handlers = _init_fs_handlers, 20367e31ba66Smrg .register_fpe_funcs = register_fpe_funcs, 20377e31ba66Smrg .remove_fs_handlers = _remove_fs_handlers, 20387e31ba66Smrg .get_server_client = get_server_client, 20397e31ba66Smrg .set_font_authorizations = set_font_authorizations, 20407e31ba66Smrg .store_font_client_font = store_font_Client_font, 20417e31ba66Smrg .make_atom = MakeAtom, 20427e31ba66Smrg .valid_atom = ValidAtom, 20437e31ba66Smrg .name_for_atom = NameForAtom, 20447e31ba66Smrg .get_server_generation = get_server_generation, 20457e31ba66Smrg .add_fs_fd = add_fs_fd, 20467e31ba66Smrg .remove_fs_fd = remove_fs_fd, 20477e31ba66Smrg .adjust_fs_wait_for_delay = adjust_fs_wait_for_delay, 20487e31ba66Smrg}; 20497e31ba66Smrg 20507e31ba66Smrgxfont2_pattern_cache_ptr fontPatternCache; 20517e31ba66Smrg 20527e31ba66Smrgvoid 20537e31ba66SmrgInitFonts(void) 20547e31ba66Smrg{ 20557e31ba66Smrg if (fontPatternCache) 20567e31ba66Smrg xfont2_free_font_pattern_cache(fontPatternCache); 20577e31ba66Smrg fontPatternCache = xfont2_make_font_pattern_cache(); 20587e31ba66Smrg xfont2_init(&xfont2_client_funcs); 20597e31ba66Smrg} 2060