dixfonts.c revision 6747b715
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" 6805b261ecSmrg 6905b261ecSmrg#ifdef DEBUG 7005b261ecSmrg#include <stdio.h> 7105b261ecSmrg#endif 7205b261ecSmrg 7305b261ecSmrg#ifdef XF86BIGFONT 746747b715Smrg#include "xf86bigfontsrv.h" 7505b261ecSmrg#endif 7605b261ecSmrg 7705b261ecSmrg#define QUERYCHARINFO(pci, pr) *(pr) = (pci)->metrics 7805b261ecSmrg 7905b261ecSmrgextern pointer fosNaturalParams; 8005b261ecSmrgextern FontPtr defaultFont; 8105b261ecSmrg 8205b261ecSmrgstatic FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0; 8305b261ecSmrgstatic int num_fpes = 0; 844642e01fSmrgstatic FPEFunctions *fpe_functions = (FPEFunctions *) 0; 8505b261ecSmrgstatic int num_fpe_types = 0; 8605b261ecSmrg 8705b261ecSmrgstatic unsigned char *font_path_string; 8805b261ecSmrg 8905b261ecSmrgstatic int num_slept_fpes = 0; 9005b261ecSmrgstatic int size_slept_fpes = 0; 9105b261ecSmrgstatic FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0; 9205b261ecSmrgstatic FontPatternCachePtr patternCache; 9305b261ecSmrg 944642e01fSmrgstatic int 954642e01fSmrgFontToXError(int err) 9605b261ecSmrg{ 9705b261ecSmrg switch (err) { 9805b261ecSmrg case Successful: 9905b261ecSmrg return Success; 10005b261ecSmrg case AllocError: 10105b261ecSmrg return BadAlloc; 10205b261ecSmrg case BadFontName: 10305b261ecSmrg return BadName; 10405b261ecSmrg case BadFontPath: 10505b261ecSmrg case BadFontFormat: /* is there something better? */ 10605b261ecSmrg case BadCharRange: 10705b261ecSmrg return BadValue; 10805b261ecSmrg default: 10905b261ecSmrg return err; 11005b261ecSmrg } 11105b261ecSmrg} 11205b261ecSmrg 1134642e01fSmrgstatic int 1144642e01fSmrgLoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size, 1154642e01fSmrg unsigned char *data) 1164642e01fSmrg{ 1174642e01fSmrg if (fpe_functions[pfont->fpe->type].load_glyphs) 1184642e01fSmrg return (*fpe_functions[pfont->fpe->type].load_glyphs) 1194642e01fSmrg (client, pfont, 0, nchars, item_size, data); 1204642e01fSmrg else 1214642e01fSmrg return Successful; 1224642e01fSmrg} 12305b261ecSmrg 12405b261ecSmrg/* 12505b261ecSmrg * adding RT_FONT prevents conflict with default cursor font 12605b261ecSmrg */ 12705b261ecSmrgBool 12805b261ecSmrgSetDefaultFont(char *defaultfontname) 12905b261ecSmrg{ 13005b261ecSmrg int err; 13105b261ecSmrg FontPtr pf; 13205b261ecSmrg XID fid; 13305b261ecSmrg 13405b261ecSmrg fid = FakeClientID(0); 13505b261ecSmrg err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync, 13605b261ecSmrg (unsigned) strlen(defaultfontname), defaultfontname); 13705b261ecSmrg if (err != Success) 13805b261ecSmrg return FALSE; 1396747b715Smrg err = dixLookupResourceByType((pointer *)&pf, fid, RT_FONT, serverClient, 1406747b715Smrg DixReadAccess); 1416747b715Smrg if (err != Success) 14205b261ecSmrg return FALSE; 14305b261ecSmrg defaultFont = pf; 14405b261ecSmrg return TRUE; 14505b261ecSmrg} 14605b261ecSmrg 14705b261ecSmrg/* 14805b261ecSmrg * note that the font wakeup queue is not refcounted. this is because 14905b261ecSmrg * an fpe needs to be added when it's inited, and removed when it's finally 15005b261ecSmrg * freed, in order to handle any data that isn't requested, like FS events. 15105b261ecSmrg * 15205b261ecSmrg * since the only thing that should call these routines is the renderer's 15305b261ecSmrg * init_fpe() and free_fpe(), there shouldn't be any problem in using 15405b261ecSmrg * freed data. 15505b261ecSmrg */ 15605b261ecSmrgvoid 15705b261ecSmrgQueueFontWakeup(FontPathElementPtr fpe) 15805b261ecSmrg{ 15905b261ecSmrg int i; 16005b261ecSmrg FontPathElementPtr *new; 16105b261ecSmrg 16205b261ecSmrg for (i = 0; i < num_slept_fpes; i++) { 16305b261ecSmrg if (slept_fpes[i] == fpe) { 16405b261ecSmrg return; 16505b261ecSmrg } 16605b261ecSmrg } 16705b261ecSmrg if (num_slept_fpes == size_slept_fpes) { 16805b261ecSmrg new = (FontPathElementPtr *) 1696747b715Smrg realloc(slept_fpes, 17005b261ecSmrg sizeof(FontPathElementPtr) * (size_slept_fpes + 4)); 17105b261ecSmrg if (!new) 17205b261ecSmrg return; 17305b261ecSmrg slept_fpes = new; 17405b261ecSmrg size_slept_fpes += 4; 17505b261ecSmrg } 17605b261ecSmrg slept_fpes[num_slept_fpes] = fpe; 17705b261ecSmrg num_slept_fpes++; 17805b261ecSmrg} 17905b261ecSmrg 18005b261ecSmrgvoid 18105b261ecSmrgRemoveFontWakeup(FontPathElementPtr fpe) 18205b261ecSmrg{ 18305b261ecSmrg int i, 18405b261ecSmrg j; 18505b261ecSmrg 18605b261ecSmrg for (i = 0; i < num_slept_fpes; i++) { 18705b261ecSmrg if (slept_fpes[i] == fpe) { 18805b261ecSmrg for (j = i; j < num_slept_fpes; j++) { 18905b261ecSmrg slept_fpes[j] = slept_fpes[j + 1]; 19005b261ecSmrg } 19105b261ecSmrg num_slept_fpes--; 19205b261ecSmrg return; 19305b261ecSmrg } 19405b261ecSmrg } 19505b261ecSmrg} 19605b261ecSmrg 19705b261ecSmrgvoid 19805b261ecSmrgFontWakeup(pointer data, int count, pointer LastSelectMask) 19905b261ecSmrg{ 20005b261ecSmrg int i; 20105b261ecSmrg FontPathElementPtr fpe; 20205b261ecSmrg 20305b261ecSmrg if (count < 0) 20405b261ecSmrg return; 20505b261ecSmrg /* wake up any fpe's that may be waiting for information */ 20605b261ecSmrg for (i = 0; i < num_slept_fpes; i++) { 20705b261ecSmrg fpe = slept_fpes[i]; 20805b261ecSmrg (void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask); 20905b261ecSmrg } 21005b261ecSmrg} 21105b261ecSmrg 21205b261ecSmrg/* XXX -- these two funcs may want to be broken into macros */ 21305b261ecSmrgstatic void 21405b261ecSmrgUseFPE(FontPathElementPtr fpe) 21505b261ecSmrg{ 21605b261ecSmrg fpe->refcount++; 21705b261ecSmrg} 21805b261ecSmrg 21905b261ecSmrgstatic void 22005b261ecSmrgFreeFPE (FontPathElementPtr fpe) 22105b261ecSmrg{ 22205b261ecSmrg fpe->refcount--; 22305b261ecSmrg if (fpe->refcount == 0) { 22405b261ecSmrg (*fpe_functions[fpe->type].free_fpe) (fpe); 2256747b715Smrg free(fpe->name); 2266747b715Smrg free(fpe); 22705b261ecSmrg } 22805b261ecSmrg} 22905b261ecSmrg 23005b261ecSmrgstatic Bool 23105b261ecSmrgdoOpenFont(ClientPtr client, OFclosurePtr c) 23205b261ecSmrg{ 23305b261ecSmrg FontPtr pfont = NullFont; 23405b261ecSmrg FontPathElementPtr fpe = NULL; 23505b261ecSmrg ScreenPtr pScr; 23605b261ecSmrg int err = Successful; 23705b261ecSmrg int i; 23805b261ecSmrg char *alias, 23905b261ecSmrg *newname; 24005b261ecSmrg int newlen; 24105b261ecSmrg int aliascount = 20; 24205b261ecSmrg /* 24305b261ecSmrg * Decide at runtime what FontFormat to use. 24405b261ecSmrg */ 24505b261ecSmrg Mask FontFormat = 24605b261ecSmrg 24705b261ecSmrg ((screenInfo.imageByteOrder == LSBFirst) ? 24805b261ecSmrg BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) | 24905b261ecSmrg 25005b261ecSmrg ((screenInfo.bitmapBitOrder == LSBFirst) ? 25105b261ecSmrg BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) | 25205b261ecSmrg 25305b261ecSmrg BitmapFormatImageRectMin | 25405b261ecSmrg 25505b261ecSmrg#if GLYPHPADBYTES == 1 25605b261ecSmrg BitmapFormatScanlinePad8 | 25705b261ecSmrg#endif 25805b261ecSmrg 25905b261ecSmrg#if GLYPHPADBYTES == 2 26005b261ecSmrg BitmapFormatScanlinePad16 | 26105b261ecSmrg#endif 26205b261ecSmrg 26305b261ecSmrg#if GLYPHPADBYTES == 4 26405b261ecSmrg BitmapFormatScanlinePad32 | 26505b261ecSmrg#endif 26605b261ecSmrg 26705b261ecSmrg#if GLYPHPADBYTES == 8 26805b261ecSmrg BitmapFormatScanlinePad64 | 26905b261ecSmrg#endif 27005b261ecSmrg 27105b261ecSmrg BitmapFormatScanlineUnit8; 27205b261ecSmrg 27305b261ecSmrg if (client->clientGone) 27405b261ecSmrg { 27505b261ecSmrg if (c->current_fpe < c->num_fpes) 27605b261ecSmrg { 27705b261ecSmrg fpe = c->fpe_list[c->current_fpe]; 27805b261ecSmrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 27905b261ecSmrg } 28005b261ecSmrg err = Successful; 28105b261ecSmrg goto bail; 28205b261ecSmrg } 28305b261ecSmrg while (c->current_fpe < c->num_fpes) { 28405b261ecSmrg fpe = c->fpe_list[c->current_fpe]; 28505b261ecSmrg err = (*fpe_functions[fpe->type].open_font) 28605b261ecSmrg ((pointer) client, fpe, c->flags, 28705b261ecSmrg c->fontname, c->fnamelen, FontFormat, 28805b261ecSmrg BitmapFormatMaskByte | 28905b261ecSmrg BitmapFormatMaskBit | 29005b261ecSmrg BitmapFormatMaskImageRectangle | 29105b261ecSmrg BitmapFormatMaskScanLinePad | 29205b261ecSmrg BitmapFormatMaskScanLineUnit, 29305b261ecSmrg c->fontid, &pfont, &alias, 29405b261ecSmrg c->non_cachable_font && c->non_cachable_font->fpe == fpe ? 29505b261ecSmrg c->non_cachable_font : 29605b261ecSmrg (FontPtr)0); 29705b261ecSmrg 29805b261ecSmrg if (err == FontNameAlias && alias) { 29905b261ecSmrg newlen = strlen(alias); 3006747b715Smrg newname = (char *) realloc(c->fontname, newlen); 30105b261ecSmrg if (!newname) { 30205b261ecSmrg err = AllocError; 30305b261ecSmrg break; 30405b261ecSmrg } 30505b261ecSmrg memmove(newname, alias, newlen); 30605b261ecSmrg c->fontname = newname; 30705b261ecSmrg c->fnamelen = newlen; 30805b261ecSmrg c->current_fpe = 0; 3094642e01fSmrg if (--aliascount <= 0) { 3104642e01fSmrg /* We've tried resolving this alias 20 times, we're 3114642e01fSmrg * probably stuck in an infinite loop of aliases pointing 3124642e01fSmrg * to each other - time to take emergency exit! 3134642e01fSmrg */ 3144642e01fSmrg err = BadImplementation; 31505b261ecSmrg break; 3164642e01fSmrg } 31705b261ecSmrg continue; 31805b261ecSmrg } 31905b261ecSmrg if (err == BadFontName) { 32005b261ecSmrg c->current_fpe++; 32105b261ecSmrg continue; 32205b261ecSmrg } 32305b261ecSmrg if (err == Suspended) { 3246747b715Smrg if (!ClientIsAsleep(client)) 3256747b715Smrg ClientSleep(client, (ClientSleepProcPtr)doOpenFont, c); 3266747b715Smrg else 3276747b715Smrg goto xinerama_sleep; 32805b261ecSmrg return TRUE; 32905b261ecSmrg } 33005b261ecSmrg break; 33105b261ecSmrg } 33205b261ecSmrg 33305b261ecSmrg if (err != Successful) 33405b261ecSmrg goto bail; 33505b261ecSmrg if (!pfont) { 33605b261ecSmrg err = BadFontName; 33705b261ecSmrg goto bail; 33805b261ecSmrg } 33905b261ecSmrg /* check values for firstCol, lastCol, firstRow, and lastRow */ 34005b261ecSmrg if (pfont->info.firstCol > pfont->info.lastCol || 34105b261ecSmrg pfont->info.firstRow > pfont->info.lastRow || 34205b261ecSmrg pfont->info.lastCol - pfont->info.firstCol > 255) { 34305b261ecSmrg err = AllocError; 34405b261ecSmrg goto bail; 34505b261ecSmrg } 34605b261ecSmrg if (!pfont->fpe) 34705b261ecSmrg pfont->fpe = fpe; 34805b261ecSmrg pfont->refcnt++; 34905b261ecSmrg if (pfont->refcnt == 1) { 35005b261ecSmrg UseFPE(pfont->fpe); 35105b261ecSmrg for (i = 0; i < screenInfo.numScreens; i++) { 35205b261ecSmrg pScr = screenInfo.screens[i]; 35305b261ecSmrg if (pScr->RealizeFont) 35405b261ecSmrg { 35505b261ecSmrg if (!(*pScr->RealizeFont) (pScr, pfont)) 35605b261ecSmrg { 35705b261ecSmrg CloseFont (pfont, (Font) 0); 35805b261ecSmrg err = AllocError; 35905b261ecSmrg goto bail; 36005b261ecSmrg } 36105b261ecSmrg } 36205b261ecSmrg } 36305b261ecSmrg } 36405b261ecSmrg if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) { 36505b261ecSmrg err = AllocError; 36605b261ecSmrg goto bail; 36705b261ecSmrg } 36805b261ecSmrg if (patternCache && pfont != c->non_cachable_font) 36905b261ecSmrg CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen, 37005b261ecSmrg pfont); 37105b261ecSmrgbail: 37205b261ecSmrg if (err != Successful && c->client != serverClient) { 37305b261ecSmrg SendErrorToClient(c->client, X_OpenFont, 0, 37405b261ecSmrg c->fontid, FontToXError(err)); 37505b261ecSmrg } 3766747b715Smrg ClientWakeup(c->client); 3776747b715Smrgxinerama_sleep: 37805b261ecSmrg for (i = 0; i < c->num_fpes; i++) { 37905b261ecSmrg FreeFPE(c->fpe_list[i]); 38005b261ecSmrg } 3816747b715Smrg free(c->fpe_list); 3826747b715Smrg free(c->fontname); 3836747b715Smrg free(c); 38405b261ecSmrg return TRUE; 38505b261ecSmrg} 38605b261ecSmrg 38705b261ecSmrgint 38805b261ecSmrgOpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontname) 38905b261ecSmrg{ 39005b261ecSmrg OFclosurePtr c; 39105b261ecSmrg int i; 39205b261ecSmrg FontPtr cached = (FontPtr)0; 39305b261ecSmrg 39405b261ecSmrg#ifdef FONTDEBUG 39505b261ecSmrg char *f; 3966747b715Smrg f = malloc(lenfname + 1); 39705b261ecSmrg memmove(f, pfontname, lenfname); 39805b261ecSmrg f[lenfname] = '\0'; 3994642e01fSmrg ErrorF("[dix] OpenFont: fontname is \"%s\"\n", f); 4006747b715Smrg free(f); 40105b261ecSmrg#endif 40205b261ecSmrg if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) 40305b261ecSmrg return BadName; 40405b261ecSmrg if (patternCache) 40505b261ecSmrg { 40605b261ecSmrg 40705b261ecSmrg /* 40805b261ecSmrg ** Check name cache. If we find a cached version of this font that 40905b261ecSmrg ** is cachable, immediately satisfy the request with it. If we find 41005b261ecSmrg ** a cached version of this font that is non-cachable, we do not 41105b261ecSmrg ** satisfy the request with it. Instead, we pass the FontPtr to the 41205b261ecSmrg ** FPE's open_font code (the fontfile FPE in turn passes the 41305b261ecSmrg ** information to the rasterizer; the fserve FPE ignores it). 41405b261ecSmrg ** 41505b261ecSmrg ** Presumably, the font is marked non-cachable because the FPE has 41605b261ecSmrg ** put some licensing restrictions on it. If the FPE, using 41705b261ecSmrg ** whatever logic it relies on, determines that it is willing to 41805b261ecSmrg ** share this existing font with the client, then it has the option 41905b261ecSmrg ** to return the FontPtr we passed it as the newly-opened font. 42005b261ecSmrg ** This allows the FPE to exercise its licensing logic without 42105b261ecSmrg ** having to create another instance of a font that already exists. 42205b261ecSmrg */ 42305b261ecSmrg 42405b261ecSmrg cached = FindCachedFontPattern(patternCache, pfontname, lenfname); 42505b261ecSmrg if (cached && cached->info.cachable) 42605b261ecSmrg { 42705b261ecSmrg if (!AddResource(fid, RT_FONT, (pointer) cached)) 42805b261ecSmrg return BadAlloc; 42905b261ecSmrg cached->refcnt++; 43005b261ecSmrg return Success; 43105b261ecSmrg } 43205b261ecSmrg } 4336747b715Smrg c = malloc(sizeof(OFclosureRec)); 43405b261ecSmrg if (!c) 43505b261ecSmrg return BadAlloc; 4366747b715Smrg c->fontname = malloc(lenfname); 43705b261ecSmrg c->origFontName = pfontname; 43805b261ecSmrg c->origFontNameLen = lenfname; 43905b261ecSmrg if (!c->fontname) { 4406747b715Smrg free(c); 44105b261ecSmrg return BadAlloc; 44205b261ecSmrg } 44305b261ecSmrg /* 44405b261ecSmrg * copy the current FPE list, so that if it gets changed by another client 44505b261ecSmrg * while we're blocking, the request still appears atomic 44605b261ecSmrg */ 4476747b715Smrg c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes); 44805b261ecSmrg if (!c->fpe_list) { 4496747b715Smrg free(c->fontname); 4506747b715Smrg free(c); 45105b261ecSmrg return BadAlloc; 45205b261ecSmrg } 45305b261ecSmrg memmove(c->fontname, pfontname, lenfname); 45405b261ecSmrg for (i = 0; i < num_fpes; i++) { 45505b261ecSmrg c->fpe_list[i] = font_path_elements[i]; 45605b261ecSmrg UseFPE(c->fpe_list[i]); 45705b261ecSmrg } 45805b261ecSmrg c->client = client; 45905b261ecSmrg c->fontid = fid; 46005b261ecSmrg c->current_fpe = 0; 46105b261ecSmrg c->num_fpes = num_fpes; 46205b261ecSmrg c->fnamelen = lenfname; 46305b261ecSmrg c->flags = flags; 46405b261ecSmrg c->non_cachable_font = cached; 46505b261ecSmrg 46605b261ecSmrg (void) doOpenFont(client, c); 46705b261ecSmrg return Success; 46805b261ecSmrg} 46905b261ecSmrg 47005b261ecSmrg/** 47105b261ecSmrg * Decrement font's ref count, and free storage if ref count equals zero 47205b261ecSmrg * 47305b261ecSmrg * \param value must conform to DeleteType 47405b261ecSmrg */ 4754642e01fSmrgint 47605b261ecSmrgCloseFont(pointer value, XID fid) 47705b261ecSmrg{ 47805b261ecSmrg int nscr; 47905b261ecSmrg ScreenPtr pscr; 48005b261ecSmrg FontPathElementPtr fpe; 48105b261ecSmrg FontPtr pfont = (FontPtr)value; 48205b261ecSmrg 48305b261ecSmrg if (pfont == NullFont) 4846747b715Smrg return Success; 48505b261ecSmrg if (--pfont->refcnt == 0) { 48605b261ecSmrg if (patternCache) 48705b261ecSmrg RemoveCachedFontPattern (patternCache, pfont); 48805b261ecSmrg /* 48905b261ecSmrg * since the last reference is gone, ask each screen to free any 49005b261ecSmrg * storage it may have allocated locally for it. 49105b261ecSmrg */ 49205b261ecSmrg for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { 49305b261ecSmrg pscr = screenInfo.screens[nscr]; 49405b261ecSmrg if (pscr->UnrealizeFont) 49505b261ecSmrg (*pscr->UnrealizeFont) (pscr, pfont); 49605b261ecSmrg } 49705b261ecSmrg if (pfont == defaultFont) 49805b261ecSmrg defaultFont = NULL; 49905b261ecSmrg#ifdef XF86BIGFONT 50005b261ecSmrg XF86BigfontFreeFontShm(pfont); 50105b261ecSmrg#endif 50205b261ecSmrg fpe = pfont->fpe; 50305b261ecSmrg (*fpe_functions[fpe->type].close_font) (fpe, pfont); 50405b261ecSmrg FreeFPE(fpe); 50505b261ecSmrg } 5066747b715Smrg return Success; 50705b261ecSmrg} 50805b261ecSmrg 50905b261ecSmrg 51005b261ecSmrg/***====================================================================***/ 51105b261ecSmrg 51205b261ecSmrg/** 51305b261ecSmrg * Sets up pReply as the correct QueryFontReply for pFont with the first 51405b261ecSmrg * nProtoCCIStructs char infos. 51505b261ecSmrg * 51605b261ecSmrg * \param pReply caller must allocate this storage 51705b261ecSmrg */ 51805b261ecSmrgvoid 51905b261ecSmrgQueryFont(FontPtr pFont, xQueryFontReply *pReply, int nProtoCCIStructs) 52005b261ecSmrg{ 52105b261ecSmrg FontPropPtr pFP; 52205b261ecSmrg int r, 52305b261ecSmrg c, 52405b261ecSmrg i; 52505b261ecSmrg xFontProp *prFP; 52605b261ecSmrg xCharInfo *prCI; 52705b261ecSmrg xCharInfo *charInfos[256]; 52805b261ecSmrg unsigned char chars[512]; 52905b261ecSmrg int ninfos; 53005b261ecSmrg unsigned long ncols; 53105b261ecSmrg unsigned long count; 53205b261ecSmrg 53305b261ecSmrg /* pr->length set in dispatch */ 53405b261ecSmrg pReply->minCharOrByte2 = pFont->info.firstCol; 53505b261ecSmrg pReply->defaultChar = pFont->info.defaultCh; 53605b261ecSmrg pReply->maxCharOrByte2 = pFont->info.lastCol; 53705b261ecSmrg pReply->drawDirection = pFont->info.drawDirection; 53805b261ecSmrg pReply->allCharsExist = pFont->info.allExist; 53905b261ecSmrg pReply->minByte1 = pFont->info.firstRow; 54005b261ecSmrg pReply->maxByte1 = pFont->info.lastRow; 54105b261ecSmrg pReply->fontAscent = pFont->info.fontAscent; 54205b261ecSmrg pReply->fontDescent = pFont->info.fontDescent; 54305b261ecSmrg 54405b261ecSmrg pReply->minBounds = pFont->info.ink_minbounds; 54505b261ecSmrg pReply->maxBounds = pFont->info.ink_maxbounds; 54605b261ecSmrg 54705b261ecSmrg pReply->nFontProps = pFont->info.nprops; 54805b261ecSmrg pReply->nCharInfos = nProtoCCIStructs; 54905b261ecSmrg 55005b261ecSmrg for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]); 55105b261ecSmrg i < pFont->info.nprops; 55205b261ecSmrg i++, pFP++, prFP++) { 55305b261ecSmrg prFP->name = pFP->name; 55405b261ecSmrg prFP->value = pFP->value; 55505b261ecSmrg } 55605b261ecSmrg 55705b261ecSmrg ninfos = 0; 55805b261ecSmrg ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1); 55905b261ecSmrg prCI = (xCharInfo *) (prFP); 56005b261ecSmrg for (r = pFont->info.firstRow; 56105b261ecSmrg ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow; 56205b261ecSmrg r++) { 56305b261ecSmrg i = 0; 56405b261ecSmrg for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) { 56505b261ecSmrg chars[i++] = r; 56605b261ecSmrg chars[i++] = c; 56705b261ecSmrg } 56805b261ecSmrg (*pFont->get_metrics) (pFont, ncols, chars, 56905b261ecSmrg TwoD16Bit, &count, charInfos); 57005b261ecSmrg i = 0; 57105b261ecSmrg for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) { 57205b261ecSmrg *prCI = *charInfos[i]; 57305b261ecSmrg prCI++; 57405b261ecSmrg ninfos++; 57505b261ecSmrg } 57605b261ecSmrg } 57705b261ecSmrg return; 57805b261ecSmrg} 57905b261ecSmrg 58005b261ecSmrgstatic Bool 58105b261ecSmrgdoListFontsAndAliases(ClientPtr client, LFclosurePtr c) 58205b261ecSmrg{ 58305b261ecSmrg FontPathElementPtr fpe; 58405b261ecSmrg int err = Successful; 58505b261ecSmrg FontNamesPtr names = NULL; 58605b261ecSmrg char *name, *resolved=NULL; 58705b261ecSmrg int namelen, resolvedlen; 58805b261ecSmrg int nnames; 58905b261ecSmrg int stringLens; 59005b261ecSmrg int i; 59105b261ecSmrg xListFontsReply reply; 59205b261ecSmrg char *bufptr; 59305b261ecSmrg char *bufferStart; 59405b261ecSmrg int aliascount = 0; 59505b261ecSmrg 59605b261ecSmrg if (client->clientGone) 59705b261ecSmrg { 59805b261ecSmrg if (c->current.current_fpe < c->num_fpes) 59905b261ecSmrg { 60005b261ecSmrg fpe = c->fpe_list[c->current.current_fpe]; 60105b261ecSmrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 60205b261ecSmrg } 60305b261ecSmrg err = Successful; 60405b261ecSmrg goto bail; 60505b261ecSmrg } 60605b261ecSmrg 60705b261ecSmrg if (!c->current.patlen) 60805b261ecSmrg goto finish; 60905b261ecSmrg 61005b261ecSmrg while (c->current.current_fpe < c->num_fpes) { 61105b261ecSmrg fpe = c->fpe_list[c->current.current_fpe]; 61205b261ecSmrg err = Successful; 61305b261ecSmrg 61405b261ecSmrg if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) 61505b261ecSmrg { 61605b261ecSmrg /* This FPE doesn't support/require list_fonts_and_aliases */ 61705b261ecSmrg 61805b261ecSmrg err = (*fpe_functions[fpe->type].list_fonts) 61905b261ecSmrg ((pointer) c->client, fpe, c->current.pattern, 62005b261ecSmrg c->current.patlen, c->current.max_names - c->names->nnames, 62105b261ecSmrg c->names); 62205b261ecSmrg 62305b261ecSmrg if (err == Suspended) { 6246747b715Smrg if (!ClientIsAsleep(client)) 62505b261ecSmrg ClientSleep(client, 6266747b715Smrg (ClientSleepProcPtr)doListFontsAndAliases, 6276747b715Smrg c); 6286747b715Smrg else 6296747b715Smrg goto xinerama_sleep; 63005b261ecSmrg return TRUE; 63105b261ecSmrg } 63205b261ecSmrg 63305b261ecSmrg err = BadFontName; 63405b261ecSmrg } 63505b261ecSmrg else 63605b261ecSmrg { 63705b261ecSmrg /* Start of list_fonts_and_aliases functionality. Modeled 63805b261ecSmrg after list_fonts_with_info in that it resolves aliases, 63905b261ecSmrg except that the information collected from FPEs is just 64005b261ecSmrg names, not font info. Each list_next_font_or_alias() 64105b261ecSmrg returns either a name into name/namelen or an alias into 64205b261ecSmrg name/namelen and its target name into resolved/resolvedlen. 64305b261ecSmrg The code at this level then resolves the alias by polling 64405b261ecSmrg the FPEs. */ 64505b261ecSmrg 64605b261ecSmrg if (!c->current.list_started) { 64705b261ecSmrg err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) 64805b261ecSmrg ((pointer) c->client, fpe, c->current.pattern, 64905b261ecSmrg c->current.patlen, c->current.max_names - c->names->nnames, 65005b261ecSmrg &c->current.private); 65105b261ecSmrg if (err == Suspended) { 6526747b715Smrg if (!ClientIsAsleep(client)) 65305b261ecSmrg ClientSleep(client, 65405b261ecSmrg (ClientSleepProcPtr)doListFontsAndAliases, 6556747b715Smrg c); 6566747b715Smrg else 6576747b715Smrg goto xinerama_sleep; 65805b261ecSmrg return TRUE; 65905b261ecSmrg } 66005b261ecSmrg if (err == Successful) 66105b261ecSmrg c->current.list_started = TRUE; 66205b261ecSmrg } 66305b261ecSmrg if (err == Successful) { 66405b261ecSmrg char *tmpname; 66505b261ecSmrg name = 0; 66605b261ecSmrg err = (*fpe_functions[fpe->type].list_next_font_or_alias) 66705b261ecSmrg ((pointer) c->client, fpe, &name, &namelen, &tmpname, 66805b261ecSmrg &resolvedlen, c->current.private); 66905b261ecSmrg if (err == Suspended) { 6706747b715Smrg if (ClientIsAsleep(client)) 67105b261ecSmrg ClientSleep(client, 67205b261ecSmrg (ClientSleepProcPtr)doListFontsAndAliases, 6736747b715Smrg c); 6746747b715Smrg else 6756747b715Smrg goto xinerama_sleep; 67605b261ecSmrg return TRUE; 67705b261ecSmrg } 67805b261ecSmrg if (err == FontNameAlias) { 6796747b715Smrg free(resolved); 6806747b715Smrg resolved = malloc(resolvedlen + 1); 68105b261ecSmrg if (resolved) 68205b261ecSmrg memmove(resolved, tmpname, resolvedlen + 1); 68305b261ecSmrg } 68405b261ecSmrg } 68505b261ecSmrg 68605b261ecSmrg if (err == Successful) 68705b261ecSmrg { 68805b261ecSmrg if (c->haveSaved) 68905b261ecSmrg { 69005b261ecSmrg if (c->savedName) 69105b261ecSmrg (void)AddFontNamesName(c->names, c->savedName, 69205b261ecSmrg c->savedNameLen); 69305b261ecSmrg } 69405b261ecSmrg else 69505b261ecSmrg (void)AddFontNamesName(c->names, name, namelen); 69605b261ecSmrg } 69705b261ecSmrg 69805b261ecSmrg /* 69905b261ecSmrg * When we get an alias back, save our state and reset back to 70005b261ecSmrg * the start of the FPE looking for the specified name. As 70105b261ecSmrg * soon as a real font is found for the alias, pop back to the 70205b261ecSmrg * old state 70305b261ecSmrg */ 70405b261ecSmrg else if (err == FontNameAlias) { 70505b261ecSmrg char tmp_pattern[XLFDMAXFONTNAMELEN]; 70605b261ecSmrg /* 70705b261ecSmrg * when an alias recurses, we need to give 70805b261ecSmrg * the last FPE a chance to clean up; so we call 70905b261ecSmrg * it again, and assume that the error returned 71005b261ecSmrg * is BadFontName, indicating the alias resolution 71105b261ecSmrg * is complete. 71205b261ecSmrg */ 71305b261ecSmrg memmove(tmp_pattern, resolved, resolvedlen); 71405b261ecSmrg if (c->haveSaved) 71505b261ecSmrg { 71605b261ecSmrg char *tmpname; 71705b261ecSmrg int tmpnamelen; 71805b261ecSmrg 71905b261ecSmrg tmpname = 0; 72005b261ecSmrg (void) (*fpe_functions[fpe->type].list_next_font_or_alias) 72105b261ecSmrg ((pointer) c->client, fpe, &tmpname, &tmpnamelen, 72205b261ecSmrg &tmpname, &tmpnamelen, c->current.private); 72305b261ecSmrg if (--aliascount <= 0) 72405b261ecSmrg { 72505b261ecSmrg err = BadFontName; 72605b261ecSmrg goto ContBadFontName; 72705b261ecSmrg } 72805b261ecSmrg } 72905b261ecSmrg else 73005b261ecSmrg { 73105b261ecSmrg c->saved = c->current; 73205b261ecSmrg c->haveSaved = TRUE; 7336747b715Smrg free(c->savedName); 7346747b715Smrg c->savedName = malloc(namelen + 1); 73505b261ecSmrg if (c->savedName) 73605b261ecSmrg memmove(c->savedName, name, namelen + 1); 73705b261ecSmrg c->savedNameLen = namelen; 73805b261ecSmrg aliascount = 20; 73905b261ecSmrg } 74005b261ecSmrg memmove(c->current.pattern, tmp_pattern, resolvedlen); 74105b261ecSmrg c->current.patlen = resolvedlen; 74205b261ecSmrg c->current.max_names = c->names->nnames + 1; 74305b261ecSmrg c->current.current_fpe = -1; 74405b261ecSmrg c->current.private = 0; 74505b261ecSmrg err = BadFontName; 74605b261ecSmrg } 74705b261ecSmrg } 74805b261ecSmrg /* 74905b261ecSmrg * At the end of this FPE, step to the next. If we've finished 75005b261ecSmrg * processing an alias, pop state back. If we've collected enough 75105b261ecSmrg * font names, quit. 75205b261ecSmrg */ 75305b261ecSmrg if (err == BadFontName) { 75405b261ecSmrg ContBadFontName: ; 75505b261ecSmrg c->current.list_started = FALSE; 75605b261ecSmrg c->current.current_fpe++; 75705b261ecSmrg err = Successful; 75805b261ecSmrg if (c->haveSaved) 75905b261ecSmrg { 76005b261ecSmrg if (c->names->nnames == c->current.max_names || 76105b261ecSmrg c->current.current_fpe == c->num_fpes) { 76205b261ecSmrg c->haveSaved = FALSE; 76305b261ecSmrg c->current = c->saved; 76405b261ecSmrg /* Give the saved namelist a chance to clean itself up */ 76505b261ecSmrg continue; 76605b261ecSmrg } 76705b261ecSmrg } 76805b261ecSmrg if (c->names->nnames == c->current.max_names) 76905b261ecSmrg break; 77005b261ecSmrg } 77105b261ecSmrg } 77205b261ecSmrg 77305b261ecSmrg /* 77405b261ecSmrg * send the reply 77505b261ecSmrg */ 77605b261ecSmrg if (err != Successful) { 77705b261ecSmrg SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err)); 77805b261ecSmrg goto bail; 77905b261ecSmrg } 78005b261ecSmrg 78105b261ecSmrgfinish: 78205b261ecSmrg 78305b261ecSmrg names = c->names; 78405b261ecSmrg nnames = names->nnames; 78505b261ecSmrg client = c->client; 78605b261ecSmrg stringLens = 0; 78705b261ecSmrg for (i = 0; i < nnames; i++) 78805b261ecSmrg stringLens += (names->length[i] <= 255) ? names->length[i] : 0; 78905b261ecSmrg 7906747b715Smrg memset(&reply, 0, sizeof(xListFontsReply)); 79105b261ecSmrg reply.type = X_Reply; 7926747b715Smrg reply.length = bytes_to_int32(stringLens + nnames); 79305b261ecSmrg reply.nFonts = nnames; 79405b261ecSmrg reply.sequenceNumber = client->sequence; 79505b261ecSmrg 7966747b715Smrg bufptr = bufferStart = malloc(reply.length << 2); 79705b261ecSmrg 79805b261ecSmrg if (!bufptr && reply.length) { 79905b261ecSmrg SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc); 80005b261ecSmrg goto bail; 80105b261ecSmrg } 80205b261ecSmrg /* 80305b261ecSmrg * since WriteToClient long word aligns things, copy to temp buffer and 80405b261ecSmrg * write all at once 80505b261ecSmrg */ 80605b261ecSmrg for (i = 0; i < nnames; i++) { 80705b261ecSmrg if (names->length[i] > 255) 80805b261ecSmrg reply.nFonts--; 80905b261ecSmrg else 81005b261ecSmrg { 81105b261ecSmrg *bufptr++ = names->length[i]; 81205b261ecSmrg memmove( bufptr, names->names[i], names->length[i]); 81305b261ecSmrg bufptr += names->length[i]; 81405b261ecSmrg } 81505b261ecSmrg } 81605b261ecSmrg nnames = reply.nFonts; 8176747b715Smrg reply.length = bytes_to_int32(stringLens + nnames); 81805b261ecSmrg client->pSwapReplyFunc = ReplySwapVector[X_ListFonts]; 81905b261ecSmrg WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply); 82005b261ecSmrg (void) WriteToClient(client, stringLens + nnames, bufferStart); 8216747b715Smrg free(bufferStart); 82205b261ecSmrg 82305b261ecSmrgbail: 8246747b715Smrg ClientWakeup(client); 8256747b715Smrgxinerama_sleep: 82605b261ecSmrg for (i = 0; i < c->num_fpes; i++) 82705b261ecSmrg FreeFPE(c->fpe_list[i]); 8286747b715Smrg free(c->fpe_list); 8296747b715Smrg free(c->savedName); 83005b261ecSmrg FreeFontNames(names); 8316747b715Smrg free(c); 8326747b715Smrg free(resolved); 83305b261ecSmrg return TRUE; 83405b261ecSmrg} 83505b261ecSmrg 83605b261ecSmrgint 83705b261ecSmrgListFonts(ClientPtr client, unsigned char *pattern, unsigned length, 83805b261ecSmrg unsigned max_names) 83905b261ecSmrg{ 84005b261ecSmrg int i; 84105b261ecSmrg LFclosurePtr c; 84205b261ecSmrg 84305b261ecSmrg /* 84405b261ecSmrg * The right error to return here would be BadName, however the 84505b261ecSmrg * specification does not allow for a Name error on this request. 84605b261ecSmrg * Perhaps a better solution would be to return a nil list, i.e. 84705b261ecSmrg * a list containing zero fontnames. 84805b261ecSmrg */ 84905b261ecSmrg if (length > XLFDMAXFONTNAMELEN) 85005b261ecSmrg return BadAlloc; 85105b261ecSmrg 8524642e01fSmrg i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess); 8534642e01fSmrg if (i != Success) 8544642e01fSmrg return i; 8554642e01fSmrg 8566747b715Smrg if (!(c = malloc(sizeof *c))) 85705b261ecSmrg return BadAlloc; 8586747b715Smrg c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes); 85905b261ecSmrg if (!c->fpe_list) { 8606747b715Smrg free(c); 86105b261ecSmrg return BadAlloc; 86205b261ecSmrg } 86305b261ecSmrg c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100); 86405b261ecSmrg if (!c->names) 86505b261ecSmrg { 8666747b715Smrg free(c->fpe_list); 8676747b715Smrg free(c); 86805b261ecSmrg return BadAlloc; 86905b261ecSmrg } 87005b261ecSmrg memmove( c->current.pattern, pattern, length); 87105b261ecSmrg for (i = 0; i < num_fpes; i++) { 87205b261ecSmrg c->fpe_list[i] = font_path_elements[i]; 87305b261ecSmrg UseFPE(c->fpe_list[i]); 87405b261ecSmrg } 87505b261ecSmrg c->client = client; 87605b261ecSmrg c->num_fpes = num_fpes; 87705b261ecSmrg c->current.patlen = length; 87805b261ecSmrg c->current.current_fpe = 0; 87905b261ecSmrg c->current.max_names = max_names; 88005b261ecSmrg c->current.list_started = FALSE; 88105b261ecSmrg c->current.private = 0; 88205b261ecSmrg c->haveSaved = FALSE; 88305b261ecSmrg c->savedName = 0; 88405b261ecSmrg doListFontsAndAliases(client, c); 88505b261ecSmrg return Success; 88605b261ecSmrg} 88705b261ecSmrg 88805b261ecSmrgint 88905b261ecSmrgdoListFontsWithInfo(ClientPtr client, LFWIclosurePtr c) 89005b261ecSmrg{ 89105b261ecSmrg FontPathElementPtr fpe; 89205b261ecSmrg int err = Successful; 89305b261ecSmrg char *name; 89405b261ecSmrg int namelen; 89505b261ecSmrg int numFonts; 89605b261ecSmrg FontInfoRec fontInfo, 89705b261ecSmrg *pFontInfo; 89805b261ecSmrg xListFontsWithInfoReply *reply; 89905b261ecSmrg int length; 90005b261ecSmrg xFontProp *pFP; 90105b261ecSmrg int i; 90205b261ecSmrg int aliascount = 0; 90305b261ecSmrg xListFontsWithInfoReply finalReply; 90405b261ecSmrg 90505b261ecSmrg if (client->clientGone) 90605b261ecSmrg { 90705b261ecSmrg if (c->current.current_fpe < c->num_fpes) 90805b261ecSmrg { 90905b261ecSmrg fpe = c->fpe_list[c->current.current_fpe]; 91005b261ecSmrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 91105b261ecSmrg } 91205b261ecSmrg err = Successful; 91305b261ecSmrg goto bail; 91405b261ecSmrg } 91505b261ecSmrg client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo]; 91605b261ecSmrg if (!c->current.patlen) 91705b261ecSmrg goto finish; 91805b261ecSmrg while (c->current.current_fpe < c->num_fpes) 91905b261ecSmrg { 92005b261ecSmrg fpe = c->fpe_list[c->current.current_fpe]; 92105b261ecSmrg err = Successful; 92205b261ecSmrg if (!c->current.list_started) 92305b261ecSmrg { 92405b261ecSmrg err = (*fpe_functions[fpe->type].start_list_fonts_with_info) 92505b261ecSmrg (client, fpe, c->current.pattern, c->current.patlen, 92605b261ecSmrg c->current.max_names, &c->current.private); 92705b261ecSmrg if (err == Suspended) 92805b261ecSmrg { 9296747b715Smrg if (!ClientIsAsleep(client)) 9306747b715Smrg ClientSleep(client, 9316747b715Smrg (ClientSleepProcPtr)doListFontsWithInfo, c); 9326747b715Smrg else 9336747b715Smrg goto xinerama_sleep; 93405b261ecSmrg return TRUE; 93505b261ecSmrg } 93605b261ecSmrg if (err == Successful) 93705b261ecSmrg c->current.list_started = TRUE; 93805b261ecSmrg } 93905b261ecSmrg if (err == Successful) 94005b261ecSmrg { 94105b261ecSmrg name = 0; 94205b261ecSmrg pFontInfo = &fontInfo; 94305b261ecSmrg err = (*fpe_functions[fpe->type].list_next_font_with_info) 94405b261ecSmrg (client, fpe, &name, &namelen, &pFontInfo, 94505b261ecSmrg &numFonts, c->current.private); 94605b261ecSmrg if (err == Suspended) 94705b261ecSmrg { 9486747b715Smrg if (!ClientIsAsleep(client)) 94905b261ecSmrg ClientSleep(client, 9506747b715Smrg (ClientSleepProcPtr)doListFontsWithInfo, c); 9516747b715Smrg else 9526747b715Smrg goto xinerama_sleep; 95305b261ecSmrg return TRUE; 95405b261ecSmrg } 95505b261ecSmrg } 95605b261ecSmrg /* 95705b261ecSmrg * When we get an alias back, save our state and reset back to the 95805b261ecSmrg * start of the FPE looking for the specified name. As soon as a real 95905b261ecSmrg * font is found for the alias, pop back to the old state 96005b261ecSmrg */ 96105b261ecSmrg if (err == FontNameAlias) 96205b261ecSmrg { 96305b261ecSmrg /* 96405b261ecSmrg * when an alias recurses, we need to give 96505b261ecSmrg * the last FPE a chance to clean up; so we call 96605b261ecSmrg * it again, and assume that the error returned 96705b261ecSmrg * is BadFontName, indicating the alias resolution 96805b261ecSmrg * is complete. 96905b261ecSmrg */ 97005b261ecSmrg if (c->haveSaved) 97105b261ecSmrg { 97205b261ecSmrg char *tmpname; 97305b261ecSmrg int tmpnamelen; 97405b261ecSmrg FontInfoPtr tmpFontInfo; 97505b261ecSmrg 97605b261ecSmrg tmpname = 0; 97705b261ecSmrg tmpFontInfo = &fontInfo; 97805b261ecSmrg (void) (*fpe_functions[fpe->type].list_next_font_with_info) 97905b261ecSmrg (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo, 98005b261ecSmrg &numFonts, c->current.private); 98105b261ecSmrg if (--aliascount <= 0) 98205b261ecSmrg { 98305b261ecSmrg err = BadFontName; 98405b261ecSmrg goto ContBadFontName; 98505b261ecSmrg } 98605b261ecSmrg } 98705b261ecSmrg else 98805b261ecSmrg { 98905b261ecSmrg c->saved = c->current; 99005b261ecSmrg c->haveSaved = TRUE; 99105b261ecSmrg c->savedNumFonts = numFonts; 9926747b715Smrg free(c->savedName); 9936747b715Smrg c->savedName = malloc(namelen + 1); 99405b261ecSmrg if (c->savedName) 99505b261ecSmrg memmove(c->savedName, name, namelen + 1); 99605b261ecSmrg aliascount = 20; 99705b261ecSmrg } 99805b261ecSmrg memmove(c->current.pattern, name, namelen); 99905b261ecSmrg c->current.patlen = namelen; 100005b261ecSmrg c->current.max_names = 1; 100105b261ecSmrg c->current.current_fpe = 0; 100205b261ecSmrg c->current.private = 0; 100305b261ecSmrg c->current.list_started = FALSE; 100405b261ecSmrg } 100505b261ecSmrg /* 100605b261ecSmrg * At the end of this FPE, step to the next. If we've finished 100705b261ecSmrg * processing an alias, pop state back. If we've sent enough font 100805b261ecSmrg * names, quit. Always wait for BadFontName to let the FPE 100905b261ecSmrg * have a chance to clean up. 101005b261ecSmrg */ 101105b261ecSmrg else if (err == BadFontName) 101205b261ecSmrg { 101305b261ecSmrg ContBadFontName: ; 101405b261ecSmrg c->current.list_started = FALSE; 101505b261ecSmrg c->current.current_fpe++; 101605b261ecSmrg err = Successful; 101705b261ecSmrg if (c->haveSaved) 101805b261ecSmrg { 101905b261ecSmrg if (c->current.max_names == 0 || 102005b261ecSmrg c->current.current_fpe == c->num_fpes) 102105b261ecSmrg { 102205b261ecSmrg c->haveSaved = FALSE; 102305b261ecSmrg c->saved.max_names -= (1 - c->current.max_names); 102405b261ecSmrg c->current = c->saved; 102505b261ecSmrg } 102605b261ecSmrg } 102705b261ecSmrg else if (c->current.max_names == 0) 102805b261ecSmrg break; 102905b261ecSmrg } 103005b261ecSmrg else if (err == Successful) 103105b261ecSmrg { 103205b261ecSmrg length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp); 103305b261ecSmrg reply = c->reply; 103405b261ecSmrg if (c->length < length) 103505b261ecSmrg { 10366747b715Smrg reply = (xListFontsWithInfoReply *) realloc(c->reply, length); 103705b261ecSmrg if (!reply) 103805b261ecSmrg { 103905b261ecSmrg err = AllocError; 104005b261ecSmrg break; 104105b261ecSmrg } 10426747b715Smrg memset((char*)reply + c->length, 0, length - c->length); 104305b261ecSmrg c->reply = reply; 104405b261ecSmrg c->length = length; 104505b261ecSmrg } 104605b261ecSmrg if (c->haveSaved) 104705b261ecSmrg { 104805b261ecSmrg numFonts = c->savedNumFonts; 104905b261ecSmrg name = c->savedName; 105005b261ecSmrg namelen = strlen(name); 105105b261ecSmrg } 105205b261ecSmrg reply->type = X_Reply; 10536747b715Smrg reply->length = bytes_to_int32(sizeof *reply - sizeof(xGenericReply) + 105405b261ecSmrg pFontInfo->nprops * sizeof(xFontProp) + 10556747b715Smrg namelen); 105605b261ecSmrg reply->sequenceNumber = client->sequence; 105705b261ecSmrg reply->nameLength = namelen; 105805b261ecSmrg reply->minBounds = pFontInfo->ink_minbounds; 105905b261ecSmrg reply->maxBounds = pFontInfo->ink_maxbounds; 106005b261ecSmrg reply->minCharOrByte2 = pFontInfo->firstCol; 106105b261ecSmrg reply->maxCharOrByte2 = pFontInfo->lastCol; 106205b261ecSmrg reply->defaultChar = pFontInfo->defaultCh; 106305b261ecSmrg reply->nFontProps = pFontInfo->nprops; 106405b261ecSmrg reply->drawDirection = pFontInfo->drawDirection; 106505b261ecSmrg reply->minByte1 = pFontInfo->firstRow; 106605b261ecSmrg reply->maxByte1 = pFontInfo->lastRow; 106705b261ecSmrg reply->allCharsExist = pFontInfo->allExist; 106805b261ecSmrg reply->fontAscent = pFontInfo->fontAscent; 106905b261ecSmrg reply->fontDescent = pFontInfo->fontDescent; 107005b261ecSmrg reply->nReplies = numFonts; 107105b261ecSmrg pFP = (xFontProp *) (reply + 1); 107205b261ecSmrg for (i = 0; i < pFontInfo->nprops; i++) 107305b261ecSmrg { 107405b261ecSmrg pFP->name = pFontInfo->props[i].name; 107505b261ecSmrg pFP->value = pFontInfo->props[i].value; 107605b261ecSmrg pFP++; 107705b261ecSmrg } 107805b261ecSmrg WriteSwappedDataToClient(client, length, reply); 107905b261ecSmrg (void) WriteToClient(client, namelen, name); 108005b261ecSmrg if (pFontInfo == &fontInfo) 108105b261ecSmrg { 10826747b715Smrg free(fontInfo.props); 10836747b715Smrg free(fontInfo.isStringProp); 108405b261ecSmrg } 108505b261ecSmrg --c->current.max_names; 108605b261ecSmrg } 108705b261ecSmrg } 108805b261ecSmrgfinish: 108905b261ecSmrg length = sizeof(xListFontsWithInfoReply); 10906747b715Smrg memset((char *) &finalReply, 0, sizeof(xListFontsWithInfoReply)); 109105b261ecSmrg finalReply.type = X_Reply; 109205b261ecSmrg finalReply.sequenceNumber = client->sequence; 10936747b715Smrg finalReply.length = bytes_to_int32(sizeof(xListFontsWithInfoReply) 10946747b715Smrg - sizeof(xGenericReply)); 109505b261ecSmrg WriteSwappedDataToClient(client, length, &finalReply); 109605b261ecSmrgbail: 10976747b715Smrg ClientWakeup(client); 10986747b715Smrgxinerama_sleep: 109905b261ecSmrg for (i = 0; i < c->num_fpes; i++) 110005b261ecSmrg FreeFPE(c->fpe_list[i]); 11016747b715Smrg free(c->reply); 11026747b715Smrg free(c->fpe_list); 11036747b715Smrg free(c->savedName); 11046747b715Smrg free(c); 110505b261ecSmrg return TRUE; 110605b261ecSmrg} 110705b261ecSmrg 110805b261ecSmrgint 110905b261ecSmrgStartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern, 111005b261ecSmrg int max_names) 111105b261ecSmrg{ 111205b261ecSmrg int i; 111305b261ecSmrg LFWIclosurePtr c; 111405b261ecSmrg 111505b261ecSmrg /* 111605b261ecSmrg * The right error to return here would be BadName, however the 111705b261ecSmrg * specification does not allow for a Name error on this request. 111805b261ecSmrg * Perhaps a better solution would be to return a nil list, i.e. 111905b261ecSmrg * a list containing zero fontnames. 112005b261ecSmrg */ 112105b261ecSmrg if (length > XLFDMAXFONTNAMELEN) 112205b261ecSmrg return BadAlloc; 112305b261ecSmrg 11244642e01fSmrg i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess); 11254642e01fSmrg if (i != Success) 11264642e01fSmrg return i; 11274642e01fSmrg 11286747b715Smrg if (!(c = malloc(sizeof *c))) 112905b261ecSmrg goto badAlloc; 11306747b715Smrg c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes); 113105b261ecSmrg if (!c->fpe_list) 113205b261ecSmrg { 11336747b715Smrg free(c); 113405b261ecSmrg goto badAlloc; 113505b261ecSmrg } 113605b261ecSmrg memmove(c->current.pattern, pattern, length); 113705b261ecSmrg for (i = 0; i < num_fpes; i++) 113805b261ecSmrg { 113905b261ecSmrg c->fpe_list[i] = font_path_elements[i]; 114005b261ecSmrg UseFPE(c->fpe_list[i]); 114105b261ecSmrg } 114205b261ecSmrg c->client = client; 114305b261ecSmrg c->num_fpes = num_fpes; 114405b261ecSmrg c->reply = 0; 114505b261ecSmrg c->length = 0; 114605b261ecSmrg c->current.patlen = length; 114705b261ecSmrg c->current.current_fpe = 0; 114805b261ecSmrg c->current.max_names = max_names; 114905b261ecSmrg c->current.list_started = FALSE; 115005b261ecSmrg c->current.private = 0; 115105b261ecSmrg c->savedNumFonts = 0; 115205b261ecSmrg c->haveSaved = FALSE; 115305b261ecSmrg c->savedName = 0; 115405b261ecSmrg doListFontsWithInfo(client, c); 115505b261ecSmrg return Success; 115605b261ecSmrgbadAlloc: 115705b261ecSmrg return BadAlloc; 115805b261ecSmrg} 115905b261ecSmrg 116005b261ecSmrg#define TextEltHeader 2 116105b261ecSmrg#define FontShiftSize 5 11626747b715Smrgstatic ChangeGCVal clearGC[] = { { .ptr = NullPixmap } }; 116305b261ecSmrg#define clearGCmask (GCClipMask) 116405b261ecSmrg 116505b261ecSmrgint 116605b261ecSmrgdoPolyText(ClientPtr client, PTclosurePtr c) 116705b261ecSmrg{ 116805b261ecSmrg FontPtr pFont = c->pGC->font, oldpFont; 116905b261ecSmrg int err = Success, lgerr; /* err is in X error, not font error, space */ 117005b261ecSmrg enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT; 117105b261ecSmrg FontPathElementPtr fpe; 117205b261ecSmrg GC *origGC = NULL; 117305b261ecSmrg 117405b261ecSmrg if (client->clientGone) 117505b261ecSmrg { 117605b261ecSmrg fpe = c->pGC->font->fpe; 117705b261ecSmrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 117805b261ecSmrg 11796747b715Smrg if (ClientIsAsleep(client)) 118005b261ecSmrg { 118105b261ecSmrg /* Client has died, but we cannot bail out right now. We 118205b261ecSmrg need to clean up after the work we did when going to 118305b261ecSmrg sleep. Setting the drawable pointer to 0 makes this 118405b261ecSmrg happen without any attempts to render or perform other 118505b261ecSmrg unnecessary activities. */ 118605b261ecSmrg c->pDraw = (DrawablePtr)0; 118705b261ecSmrg } 118805b261ecSmrg else 118905b261ecSmrg { 119005b261ecSmrg err = Success; 119105b261ecSmrg goto bail; 119205b261ecSmrg } 119305b261ecSmrg } 119405b261ecSmrg 119505b261ecSmrg /* Make sure our drawable hasn't disappeared while we slept. */ 11966747b715Smrg if (ClientIsAsleep(client) && c->pDraw) 119705b261ecSmrg { 11986747b715Smrg DrawablePtr pDraw; 11996747b715Smrg dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess); 12006747b715Smrg if (c->pDraw != pDraw) { 12016747b715Smrg /* Our drawable has disappeared. Treat like client died... ask 12026747b715Smrg the FPE code to clean up after client and avoid further 12036747b715Smrg rendering while we clean up after ourself. */ 12046747b715Smrg fpe = c->pGC->font->fpe; 12056747b715Smrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 12066747b715Smrg c->pDraw = (DrawablePtr)0; 12076747b715Smrg } 120805b261ecSmrg } 120905b261ecSmrg 12106747b715Smrg client_state = ClientIsAsleep(client) ? SLEEPING : NEVER_SLEPT; 121105b261ecSmrg 121205b261ecSmrg while (c->endReq - c->pElt > TextEltHeader) 121305b261ecSmrg { 121405b261ecSmrg if (*c->pElt == FontChange) 121505b261ecSmrg { 12166747b715Smrg Font fid; 121705b261ecSmrg if (c->endReq - c->pElt < FontShiftSize) 121805b261ecSmrg { 121905b261ecSmrg err = BadLength; 122005b261ecSmrg goto bail; 122105b261ecSmrg } 122205b261ecSmrg 122305b261ecSmrg oldpFont = pFont; 122405b261ecSmrg 122505b261ecSmrg fid = ((Font)*(c->pElt+4)) /* big-endian */ 122605b261ecSmrg | ((Font)*(c->pElt+3)) << 8 122705b261ecSmrg | ((Font)*(c->pElt+2)) << 16 122805b261ecSmrg | ((Font)*(c->pElt+1)) << 24; 12296747b715Smrg err = dixLookupResourceByType((pointer *)&pFont, fid, RT_FONT, 12306747b715Smrg client, DixUseAccess); 12316747b715Smrg if (err != Success) 123205b261ecSmrg { 12336747b715Smrg /* restore pFont for step 4 (described below) */ 123405b261ecSmrg pFont = oldpFont; 123505b261ecSmrg 123605b261ecSmrg /* If we're in START_SLEEP mode, the following step 123705b261ecSmrg shortens the request... in the unlikely event that 123805b261ecSmrg the fid somehow becomes valid before we come through 123905b261ecSmrg again to actually execute the polytext, which would 124005b261ecSmrg then mess up our refcounting scheme badly. */ 124105b261ecSmrg c->err = err; 124205b261ecSmrg c->endReq = c->pElt; 124305b261ecSmrg 124405b261ecSmrg goto bail; 124505b261ecSmrg } 124605b261ecSmrg 124705b261ecSmrg /* Step 3 (described below) on our new font */ 124805b261ecSmrg if (client_state == START_SLEEP) 124905b261ecSmrg pFont->refcnt++; 125005b261ecSmrg else 125105b261ecSmrg { 125205b261ecSmrg if (pFont != c->pGC->font && c->pDraw) 125305b261ecSmrg { 12546747b715Smrg ChangeGCVal val; 12556747b715Smrg val.ptr = pFont; 12566747b715Smrg ChangeGC(NullClient, c->pGC, GCFont, &val); 125705b261ecSmrg ValidateGC(c->pDraw, c->pGC); 125805b261ecSmrg if (c->reqType == X_PolyText8) 125905b261ecSmrg c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8; 126005b261ecSmrg else 126105b261ecSmrg c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16; 126205b261ecSmrg } 126305b261ecSmrg 126405b261ecSmrg /* Undo the refcnt++ we performed when going to sleep */ 126505b261ecSmrg if (client_state == SLEEPING) 126605b261ecSmrg (void)CloseFont(c->pGC->font, (Font)0); 126705b261ecSmrg } 126805b261ecSmrg c->pElt += FontShiftSize; 126905b261ecSmrg } 127005b261ecSmrg else /* print a string */ 127105b261ecSmrg { 127205b261ecSmrg unsigned char *pNextElt; 127305b261ecSmrg pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize; 127405b261ecSmrg if ( pNextElt > c->endReq) 127505b261ecSmrg { 127605b261ecSmrg err = BadLength; 127705b261ecSmrg goto bail; 127805b261ecSmrg } 127905b261ecSmrg if (client_state == START_SLEEP) 128005b261ecSmrg { 128105b261ecSmrg c->pElt = pNextElt; 128205b261ecSmrg continue; 128305b261ecSmrg } 128405b261ecSmrg if (c->pDraw) 128505b261ecSmrg { 128605b261ecSmrg lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize, 128705b261ecSmrg c->pElt + TextEltHeader); 128805b261ecSmrg } 128905b261ecSmrg else lgerr = Successful; 129005b261ecSmrg 129105b261ecSmrg if (lgerr == Suspended) 129205b261ecSmrg { 12936747b715Smrg if (!ClientIsAsleep(client)) { 129405b261ecSmrg int len; 129505b261ecSmrg GC *pGC; 129605b261ecSmrg PTclosurePtr new_closure; 129705b261ecSmrg 129805b261ecSmrg /* We're putting the client to sleep. We need to do a few things 129905b261ecSmrg to ensure successful and atomic-appearing execution of the 130005b261ecSmrg remainder of the request. First, copy the remainder of the 130105b261ecSmrg request into a safe malloc'd area. Second, create a scratch GC 130205b261ecSmrg to use for the remainder of the request. Third, mark all fonts 130305b261ecSmrg referenced in the remainder of the request to prevent their 130405b261ecSmrg deallocation. Fourth, make the original GC look like the 130505b261ecSmrg request has completed... set its font to the final font value 130605b261ecSmrg from this request. These GC manipulations are for the unlikely 130705b261ecSmrg (but possible) event that some other client is using the GC. 130805b261ecSmrg Steps 3 and 4 are performed by running this procedure through 130905b261ecSmrg the remainder of the request in a special no-render mode 131005b261ecSmrg indicated by client_state = START_SLEEP. */ 131105b261ecSmrg 131205b261ecSmrg /* Step 1 */ 131305b261ecSmrg /* Allocate a malloc'd closure structure to replace 131405b261ecSmrg the local one we were passed */ 13156747b715Smrg new_closure = malloc(sizeof(PTclosureRec)); 131605b261ecSmrg if (!new_closure) 131705b261ecSmrg { 131805b261ecSmrg err = BadAlloc; 131905b261ecSmrg goto bail; 132005b261ecSmrg } 132105b261ecSmrg *new_closure = *c; 132205b261ecSmrg c = new_closure; 132305b261ecSmrg 132405b261ecSmrg len = c->endReq - c->pElt; 13256747b715Smrg c->data = malloc(len); 132605b261ecSmrg if (!c->data) 132705b261ecSmrg { 13286747b715Smrg free(c); 132905b261ecSmrg err = BadAlloc; 133005b261ecSmrg goto bail; 133105b261ecSmrg } 133205b261ecSmrg memmove(c->data, c->pElt, len); 133305b261ecSmrg c->pElt = c->data; 133405b261ecSmrg c->endReq = c->pElt + len; 133505b261ecSmrg 133605b261ecSmrg /* Step 2 */ 133705b261ecSmrg 133805b261ecSmrg pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); 133905b261ecSmrg if (!pGC) 134005b261ecSmrg { 13416747b715Smrg free(c->data); 13426747b715Smrg free(c); 134305b261ecSmrg err = BadAlloc; 134405b261ecSmrg goto bail; 134505b261ecSmrg } 134605b261ecSmrg if ((err = CopyGC(c->pGC, pGC, GCFunction | 134705b261ecSmrg GCPlaneMask | GCForeground | 134805b261ecSmrg GCBackground | GCFillStyle | 134905b261ecSmrg GCTile | GCStipple | 135005b261ecSmrg GCTileStipXOrigin | 135105b261ecSmrg GCTileStipYOrigin | GCFont | 135205b261ecSmrg GCSubwindowMode | GCClipXOrigin | 135305b261ecSmrg GCClipYOrigin | GCClipMask)) != 135405b261ecSmrg Success) 135505b261ecSmrg { 135605b261ecSmrg FreeScratchGC(pGC); 13576747b715Smrg free(c->data); 13586747b715Smrg free(c); 135905b261ecSmrg err = BadAlloc; 136005b261ecSmrg goto bail; 136105b261ecSmrg } 136205b261ecSmrg origGC = c->pGC; 136305b261ecSmrg c->pGC = pGC; 136405b261ecSmrg ValidateGC(c->pDraw, c->pGC); 136505b261ecSmrg 13666747b715Smrg ClientSleep(client, (ClientSleepProcPtr)doPolyText, c); 136705b261ecSmrg 136805b261ecSmrg /* Set up to perform steps 3 and 4 */ 136905b261ecSmrg client_state = START_SLEEP; 137005b261ecSmrg continue; /* on to steps 3 and 4 */ 137105b261ecSmrg } 13726747b715Smrg else 13736747b715Smrg goto xinerama_sleep; 137405b261ecSmrg return TRUE; 137505b261ecSmrg } 137605b261ecSmrg else if (lgerr != Successful) 137705b261ecSmrg { 137805b261ecSmrg err = FontToXError(lgerr); 137905b261ecSmrg goto bail; 138005b261ecSmrg } 138105b261ecSmrg if (c->pDraw) 138205b261ecSmrg { 138305b261ecSmrg c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */ 138405b261ecSmrg c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg, 138505b261ecSmrg *c->pElt, c->pElt + TextEltHeader); 138605b261ecSmrg } 138705b261ecSmrg c->pElt = pNextElt; 138805b261ecSmrg } 138905b261ecSmrg } 139005b261ecSmrg 139105b261ecSmrgbail: 139205b261ecSmrg 139305b261ecSmrg if (client_state == START_SLEEP) 139405b261ecSmrg { 139505b261ecSmrg /* Step 4 */ 139605b261ecSmrg if (pFont != origGC->font) 139705b261ecSmrg { 13986747b715Smrg ChangeGCVal val; 13996747b715Smrg val.ptr = pFont; 14006747b715Smrg ChangeGC(NullClient, origGC, GCFont, &val); 140105b261ecSmrg ValidateGC(c->pDraw, origGC); 140205b261ecSmrg } 140305b261ecSmrg 140405b261ecSmrg /* restore pElt pointer for execution of remainder of the request */ 140505b261ecSmrg c->pElt = c->data; 140605b261ecSmrg return TRUE; 140705b261ecSmrg } 140805b261ecSmrg 140905b261ecSmrg if (c->err != Success) err = c->err; 141005b261ecSmrg if (err != Success && c->client != serverClient) { 141105b261ecSmrg#ifdef PANORAMIX 141205b261ecSmrg if (noPanoramiXExtension || !c->pGC->pScreen->myNum) 141305b261ecSmrg#endif 141405b261ecSmrg SendErrorToClient(c->client, c->reqType, 0, 0, err); 141505b261ecSmrg } 14166747b715Smrg if (ClientIsAsleep(client)) 141705b261ecSmrg { 141805b261ecSmrg ClientWakeup(c->client); 14196747b715Smrgxinerama_sleep: 14206747b715Smrg ChangeGC(NullClient, c->pGC, clearGCmask, clearGC); 142105b261ecSmrg 142205b261ecSmrg /* Unreference the font from the scratch GC */ 142305b261ecSmrg CloseFont(c->pGC->font, (Font)0); 142405b261ecSmrg c->pGC->font = NullFont; 142505b261ecSmrg 142605b261ecSmrg FreeScratchGC(c->pGC); 14276747b715Smrg free(c->data); 14286747b715Smrg free(c); 142905b261ecSmrg } 143005b261ecSmrg return TRUE; 143105b261ecSmrg} 143205b261ecSmrg 143305b261ecSmrgint 143405b261ecSmrgPolyText(ClientPtr client, DrawablePtr pDraw, GC *pGC, unsigned char *pElt, 143505b261ecSmrg unsigned char *endReq, int xorg, int yorg, int reqType, XID did) 143605b261ecSmrg{ 143705b261ecSmrg PTclosureRec local_closure; 143805b261ecSmrg 143905b261ecSmrg local_closure.pElt = pElt; 144005b261ecSmrg local_closure.endReq = endReq; 144105b261ecSmrg local_closure.client = client; 144205b261ecSmrg local_closure.pDraw = pDraw; 144305b261ecSmrg local_closure.xorg = xorg; 144405b261ecSmrg local_closure.yorg = yorg; 144505b261ecSmrg if ((local_closure.reqType = reqType) == X_PolyText8) 144605b261ecSmrg { 144705b261ecSmrg local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8; 144805b261ecSmrg local_closure.itemSize = 1; 144905b261ecSmrg } 145005b261ecSmrg else 145105b261ecSmrg { 145205b261ecSmrg local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText16; 145305b261ecSmrg local_closure.itemSize = 2; 145405b261ecSmrg } 145505b261ecSmrg local_closure.pGC = pGC; 145605b261ecSmrg local_closure.did = did; 145705b261ecSmrg local_closure.err = Success; 145805b261ecSmrg 145905b261ecSmrg (void) doPolyText(client, &local_closure); 146005b261ecSmrg return Success; 146105b261ecSmrg} 146205b261ecSmrg 146305b261ecSmrg 146405b261ecSmrg#undef TextEltHeader 146505b261ecSmrg#undef FontShiftSize 146605b261ecSmrg 146705b261ecSmrgint 146805b261ecSmrgdoImageText(ClientPtr client, ITclosurePtr c) 146905b261ecSmrg{ 147005b261ecSmrg int err = Success, lgerr; /* err is in X error, not font error, space */ 147105b261ecSmrg FontPathElementPtr fpe; 147205b261ecSmrg 147305b261ecSmrg if (client->clientGone) 147405b261ecSmrg { 147505b261ecSmrg fpe = c->pGC->font->fpe; 147605b261ecSmrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 147705b261ecSmrg err = Success; 147805b261ecSmrg goto bail; 147905b261ecSmrg } 148005b261ecSmrg 148105b261ecSmrg /* Make sure our drawable hasn't disappeared while we slept. */ 14826747b715Smrg if (ClientIsAsleep(client) && c->pDraw) 148305b261ecSmrg { 14846747b715Smrg DrawablePtr pDraw; 14856747b715Smrg dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess); 14866747b715Smrg if (c->pDraw != pDraw) { 14876747b715Smrg /* Our drawable has disappeared. Treat like client died... ask 14886747b715Smrg the FPE code to clean up after client. */ 14896747b715Smrg fpe = c->pGC->font->fpe; 14906747b715Smrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 14916747b715Smrg err = Success; 14926747b715Smrg goto bail; 14936747b715Smrg } 149405b261ecSmrg } 149505b261ecSmrg 149605b261ecSmrg lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data); 149705b261ecSmrg if (lgerr == Suspended) 149805b261ecSmrg { 14996747b715Smrg if (!ClientIsAsleep(client)) { 150005b261ecSmrg GC *pGC; 150105b261ecSmrg unsigned char *data; 150205b261ecSmrg ITclosurePtr new_closure; 150305b261ecSmrg 150405b261ecSmrg /* We're putting the client to sleep. We need to 150505b261ecSmrg save some state. Similar problem to that handled 150605b261ecSmrg in doPolyText, but much simpler because the 150705b261ecSmrg request structure is much simpler. */ 150805b261ecSmrg 15096747b715Smrg new_closure = malloc(sizeof(ITclosureRec)); 151005b261ecSmrg if (!new_closure) 151105b261ecSmrg { 151205b261ecSmrg err = BadAlloc; 151305b261ecSmrg goto bail; 151405b261ecSmrg } 151505b261ecSmrg *new_closure = *c; 151605b261ecSmrg c = new_closure; 151705b261ecSmrg 15186747b715Smrg data = malloc(c->nChars * c->itemSize); 151905b261ecSmrg if (!data) 152005b261ecSmrg { 15216747b715Smrg free(c); 152205b261ecSmrg err = BadAlloc; 152305b261ecSmrg goto bail; 152405b261ecSmrg } 152505b261ecSmrg memmove(data, c->data, c->nChars * c->itemSize); 152605b261ecSmrg c->data = data; 152705b261ecSmrg 152805b261ecSmrg pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); 152905b261ecSmrg if (!pGC) 153005b261ecSmrg { 15316747b715Smrg free(c->data); 15326747b715Smrg free(c); 153305b261ecSmrg err = BadAlloc; 153405b261ecSmrg goto bail; 153505b261ecSmrg } 153605b261ecSmrg if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask | 153705b261ecSmrg GCForeground | GCBackground | GCFillStyle | 153805b261ecSmrg GCTile | GCStipple | GCTileStipXOrigin | 153905b261ecSmrg GCTileStipYOrigin | GCFont | 154005b261ecSmrg GCSubwindowMode | GCClipXOrigin | 154105b261ecSmrg GCClipYOrigin | GCClipMask)) != Success) 154205b261ecSmrg { 154305b261ecSmrg FreeScratchGC(pGC); 15446747b715Smrg free(c->data); 15456747b715Smrg free(c); 154605b261ecSmrg err = BadAlloc; 154705b261ecSmrg goto bail; 154805b261ecSmrg } 154905b261ecSmrg c->pGC = pGC; 155005b261ecSmrg ValidateGC(c->pDraw, c->pGC); 155105b261ecSmrg 15526747b715Smrg ClientSleep(client, (ClientSleepProcPtr)doImageText, c); 155305b261ecSmrg } 15546747b715Smrg else 15556747b715Smrg goto xinerama_sleep; 155605b261ecSmrg return TRUE; 155705b261ecSmrg } 155805b261ecSmrg else if (lgerr != Successful) 155905b261ecSmrg { 156005b261ecSmrg err = FontToXError(lgerr); 156105b261ecSmrg goto bail; 156205b261ecSmrg } 156305b261ecSmrg if (c->pDraw) 156405b261ecSmrg { 156505b261ecSmrg (* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg, 156605b261ecSmrg c->nChars, c->data); 156705b261ecSmrg } 156805b261ecSmrg 156905b261ecSmrgbail: 157005b261ecSmrg 157105b261ecSmrg if (err != Success && c->client != serverClient) { 157205b261ecSmrg SendErrorToClient(c->client, c->reqType, 0, 0, err); 157305b261ecSmrg } 15746747b715Smrg if (ClientIsAsleep(client)) 157505b261ecSmrg { 157605b261ecSmrg ClientWakeup(c->client); 15776747b715Smrgxinerama_sleep: 15786747b715Smrg ChangeGC(NullClient, c->pGC, clearGCmask, clearGC); 157905b261ecSmrg 158005b261ecSmrg /* Unreference the font from the scratch GC */ 158105b261ecSmrg CloseFont(c->pGC->font, (Font)0); 158205b261ecSmrg c->pGC->font = NullFont; 158305b261ecSmrg 158405b261ecSmrg FreeScratchGC(c->pGC); 15856747b715Smrg free(c->data); 15866747b715Smrg free(c); 158705b261ecSmrg } 158805b261ecSmrg return TRUE; 158905b261ecSmrg} 159005b261ecSmrg 159105b261ecSmrgint 159205b261ecSmrgImageText(ClientPtr client, DrawablePtr pDraw, GC *pGC, int nChars, 159305b261ecSmrg unsigned char *data, int xorg, int yorg, int reqType, XID did) 159405b261ecSmrg{ 159505b261ecSmrg ITclosureRec local_closure; 159605b261ecSmrg 159705b261ecSmrg local_closure.client = client; 159805b261ecSmrg local_closure.pDraw = pDraw; 159905b261ecSmrg local_closure.pGC = pGC; 160005b261ecSmrg local_closure.nChars = nChars; 160105b261ecSmrg local_closure.data = data; 160205b261ecSmrg local_closure.xorg = xorg; 160305b261ecSmrg local_closure.yorg = yorg; 160405b261ecSmrg if ((local_closure.reqType = reqType) == X_ImageText8) 160505b261ecSmrg { 160605b261ecSmrg local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8; 160705b261ecSmrg local_closure.itemSize = 1; 160805b261ecSmrg } 160905b261ecSmrg else 161005b261ecSmrg { 161105b261ecSmrg local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16; 161205b261ecSmrg local_closure.itemSize = 2; 161305b261ecSmrg } 161405b261ecSmrg local_closure.did = did; 161505b261ecSmrg 161605b261ecSmrg (void) doImageText(client, &local_closure); 161705b261ecSmrg return Success; 161805b261ecSmrg} 161905b261ecSmrg 162005b261ecSmrg 162105b261ecSmrg/* does the necessary magic to figure out the fpe type */ 162205b261ecSmrgstatic int 162305b261ecSmrgDetermineFPEType(char *pathname) 162405b261ecSmrg{ 162505b261ecSmrg int i; 162605b261ecSmrg 162705b261ecSmrg for (i = 0; i < num_fpe_types; i++) { 162805b261ecSmrg if ((*fpe_functions[i].name_check) (pathname)) 162905b261ecSmrg return i; 163005b261ecSmrg } 163105b261ecSmrg return -1; 163205b261ecSmrg} 163305b261ecSmrg 163405b261ecSmrg 163505b261ecSmrgstatic void 163605b261ecSmrgFreeFontPath(FontPathElementPtr *list, int n, Bool force) 163705b261ecSmrg{ 163805b261ecSmrg int i; 163905b261ecSmrg 164005b261ecSmrg for (i = 0; i < n; i++) { 164105b261ecSmrg if (force) { 164205b261ecSmrg /* Sanity check that all refcounts will be 0 by the time 164305b261ecSmrg we get to the end of the list. */ 164405b261ecSmrg int found = 1; /* the first reference is us */ 164505b261ecSmrg int j; 164605b261ecSmrg for (j = i+1; j < n; j++) { 164705b261ecSmrg if (list[j] == list[i]) 164805b261ecSmrg found++; 164905b261ecSmrg } 165005b261ecSmrg if (list[i]->refcount != found) { 165105b261ecSmrg list[i]->refcount = found; /* ensure it will get freed */ 165205b261ecSmrg } 165305b261ecSmrg } 165405b261ecSmrg FreeFPE(list[i]); 165505b261ecSmrg } 16566747b715Smrg free(list); 165705b261ecSmrg} 165805b261ecSmrg 165905b261ecSmrgstatic FontPathElementPtr 166005b261ecSmrgfind_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len) 166105b261ecSmrg{ 166205b261ecSmrg FontPathElementPtr fpe; 166305b261ecSmrg int i; 166405b261ecSmrg 166505b261ecSmrg for (i = 0; i < num; i++) { 166605b261ecSmrg fpe = list[i]; 166705b261ecSmrg if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0) 166805b261ecSmrg return fpe; 166905b261ecSmrg } 167005b261ecSmrg return (FontPathElementPtr) 0; 167105b261ecSmrg} 167205b261ecSmrg 167305b261ecSmrg 167405b261ecSmrgstatic int 167505b261ecSmrgSetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist) 167605b261ecSmrg{ 167705b261ecSmrg int i, err = 0; 167805b261ecSmrg int valid_paths = 0; 167905b261ecSmrg unsigned int len; 168005b261ecSmrg unsigned char *cp = paths; 168105b261ecSmrg FontPathElementPtr fpe = NULL, *fplist; 168205b261ecSmrg 16836747b715Smrg fplist = malloc(sizeof(FontPathElementPtr) * npaths); 168405b261ecSmrg if (!fplist) { 168505b261ecSmrg *bad = 0; 168605b261ecSmrg return BadAlloc; 168705b261ecSmrg } 168805b261ecSmrg for (i = 0; i < num_fpe_types; i++) { 168905b261ecSmrg if (fpe_functions[i].set_path_hook) 169005b261ecSmrg (*fpe_functions[i].set_path_hook) (); 169105b261ecSmrg } 169205b261ecSmrg for (i = 0; i < npaths; i++) 169305b261ecSmrg { 169405b261ecSmrg len = (unsigned int) (*cp++); 169505b261ecSmrg 169605b261ecSmrg if (len == 0) 169705b261ecSmrg { 169805b261ecSmrg if (persist) 16994642e01fSmrg ErrorF("[dix] Removing empty element from the valid list of fontpaths\n"); 170005b261ecSmrg err = BadValue; 170105b261ecSmrg } 170205b261ecSmrg else 170305b261ecSmrg { 170405b261ecSmrg /* if it's already in our active list, just reset it */ 170505b261ecSmrg /* 170605b261ecSmrg * note that this can miss FPE's in limbo -- may be worth catching 170705b261ecSmrg * them, though it'd muck up refcounting 170805b261ecSmrg */ 170905b261ecSmrg fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len); 171005b261ecSmrg if (fpe) 171105b261ecSmrg { 171205b261ecSmrg err = (*fpe_functions[fpe->type].reset_fpe) (fpe); 171305b261ecSmrg if (err == Successful) 171405b261ecSmrg { 171505b261ecSmrg UseFPE(fpe);/* since it'll be decref'd later when freed 171605b261ecSmrg * from the old list */ 171705b261ecSmrg } 171805b261ecSmrg else 171905b261ecSmrg fpe = 0; 172005b261ecSmrg } 172105b261ecSmrg /* if error or can't do it, act like it's a new one */ 172205b261ecSmrg if (!fpe) 172305b261ecSmrg { 17246747b715Smrg fpe = malloc(sizeof(FontPathElementRec)); 172505b261ecSmrg if (!fpe) 172605b261ecSmrg { 172705b261ecSmrg err = BadAlloc; 172805b261ecSmrg goto bail; 172905b261ecSmrg } 17306747b715Smrg fpe->name = malloc(len + 1); 173105b261ecSmrg if (!fpe->name) 173205b261ecSmrg { 17336747b715Smrg free(fpe); 173405b261ecSmrg err = BadAlloc; 173505b261ecSmrg goto bail; 173605b261ecSmrg } 173705b261ecSmrg fpe->refcount = 1; 173805b261ecSmrg 173905b261ecSmrg strncpy(fpe->name, (char *) cp, (int) len); 174005b261ecSmrg fpe->name[len] = '\0'; 174105b261ecSmrg fpe->name_length = len; 174205b261ecSmrg fpe->type = DetermineFPEType(fpe->name); 174305b261ecSmrg if (fpe->type == -1) 174405b261ecSmrg err = BadValue; 174505b261ecSmrg else 174605b261ecSmrg err = (*fpe_functions[fpe->type].init_fpe) (fpe); 174705b261ecSmrg if (err != Successful) 174805b261ecSmrg { 174905b261ecSmrg if (persist) 175005b261ecSmrg { 17514642e01fSmrg ErrorF("[dix] Could not init font path element %s, removing from list!\n", 175205b261ecSmrg fpe->name); 175305b261ecSmrg } 17546747b715Smrg free(fpe->name); 17556747b715Smrg free(fpe); 175605b261ecSmrg } 175705b261ecSmrg } 175805b261ecSmrg } 175905b261ecSmrg if (err != Successful) 176005b261ecSmrg { 176105b261ecSmrg if (!persist) 176205b261ecSmrg goto bail; 176305b261ecSmrg } 176405b261ecSmrg else 176505b261ecSmrg { 176605b261ecSmrg fplist[valid_paths++] = fpe; 176705b261ecSmrg } 176805b261ecSmrg cp += len; 176905b261ecSmrg } 177005b261ecSmrg 177105b261ecSmrg FreeFontPath(font_path_elements, num_fpes, FALSE); 177205b261ecSmrg font_path_elements = fplist; 177305b261ecSmrg if (patternCache) 177405b261ecSmrg EmptyFontPatternCache(patternCache); 177505b261ecSmrg num_fpes = valid_paths; 177605b261ecSmrg 177705b261ecSmrg return Success; 177805b261ecSmrgbail: 177905b261ecSmrg *bad = i; 178005b261ecSmrg while (--valid_paths >= 0) 178105b261ecSmrg FreeFPE(fplist[valid_paths]); 17826747b715Smrg free(fplist); 178305b261ecSmrg return FontToXError(err); 178405b261ecSmrg} 178505b261ecSmrg 178605b261ecSmrgint 17876747b715SmrgSetFontPath(ClientPtr client, int npaths, unsigned char *paths) 178805b261ecSmrg{ 17894642e01fSmrg int err = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess); 17904642e01fSmrg if (err != Success) 17914642e01fSmrg return err; 179205b261ecSmrg 179305b261ecSmrg if (npaths == 0) { 179405b261ecSmrg if (SetDefaultFontPath(defaultFontPath) != Success) 179505b261ecSmrg return BadValue; 179605b261ecSmrg } else { 17976747b715Smrg int bad; 17986747b715Smrg err = SetFontPathElements(npaths, paths, &bad, FALSE); 17996747b715Smrg client->errorValue = bad; 180005b261ecSmrg } 180105b261ecSmrg return err; 180205b261ecSmrg} 180305b261ecSmrg 180405b261ecSmrgint 180505b261ecSmrgSetDefaultFontPath(char *path) 180605b261ecSmrg{ 1807b1d344b3Smrg char *temp_path, 1808b1d344b3Smrg *start, 1809b1d344b3Smrg *end; 181005b261ecSmrg unsigned char *cp, 181105b261ecSmrg *pp, 181205b261ecSmrg *nump, 181305b261ecSmrg *newpath; 181405b261ecSmrg int num = 1, 181505b261ecSmrg len, 181605b261ecSmrg err, 181705b261ecSmrg size = 0, 181805b261ecSmrg bad; 181905b261ecSmrg 1820b1d344b3Smrg /* ensure temp_path contains "built-ins" */ 1821b1d344b3Smrg start = path; 1822b1d344b3Smrg while (1) { 1823b1d344b3Smrg start = strstr(start, "built-ins"); 1824b1d344b3Smrg if (start == NULL) 1825b1d344b3Smrg break; 1826b1d344b3Smrg end = start + strlen("built-ins"); 1827b1d344b3Smrg if ((start == path || start[-1] == ',') && (!*end || *end == ',')) 1828b1d344b3Smrg break; 1829b1d344b3Smrg start = end; 1830b1d344b3Smrg } 1831b1d344b3Smrg if (!start) { 1832b1d344b3Smrg temp_path = Xprintf("%s%sbuilt-ins", path, *path ? "," : ""); 1833b1d344b3Smrg } else { 18346747b715Smrg temp_path = strdup(path); 1835b1d344b3Smrg } 1836b1d344b3Smrg if (!temp_path) 1837b1d344b3Smrg return BadAlloc; 1838b1d344b3Smrg 183905b261ecSmrg /* get enough for string, plus values -- use up commas */ 1840b1d344b3Smrg len = strlen(temp_path) + 1; 18416747b715Smrg nump = cp = newpath = malloc(len); 184205b261ecSmrg if (!newpath) 184305b261ecSmrg return BadAlloc; 1844b1d344b3Smrg pp = (unsigned char *) temp_path; 184505b261ecSmrg cp++; 184605b261ecSmrg while (*pp) { 184705b261ecSmrg if (*pp == ',') { 184805b261ecSmrg *nump = (unsigned char) size; 184905b261ecSmrg nump = cp++; 185005b261ecSmrg pp++; 185105b261ecSmrg num++; 185205b261ecSmrg size = 0; 185305b261ecSmrg } else { 185405b261ecSmrg *cp++ = *pp++; 185505b261ecSmrg size++; 185605b261ecSmrg } 185705b261ecSmrg } 185805b261ecSmrg *nump = (unsigned char) size; 185905b261ecSmrg 186005b261ecSmrg err = SetFontPathElements(num, newpath, &bad, TRUE); 186105b261ecSmrg 18626747b715Smrg free(newpath); 18636747b715Smrg free(temp_path); 186405b261ecSmrg 186505b261ecSmrg return err; 186605b261ecSmrg} 186705b261ecSmrg 18684642e01fSmrgint 18694642e01fSmrgGetFontPath(ClientPtr client, int *count, int *length, unsigned char **result) 187005b261ecSmrg{ 187105b261ecSmrg int i; 187205b261ecSmrg unsigned char *c; 187305b261ecSmrg int len; 187405b261ecSmrg FontPathElementPtr fpe; 187505b261ecSmrg 18764642e01fSmrg i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess); 18774642e01fSmrg if (i != Success) 18784642e01fSmrg return i; 18794642e01fSmrg 188005b261ecSmrg len = 0; 188105b261ecSmrg for (i = 0; i < num_fpes; i++) { 188205b261ecSmrg fpe = font_path_elements[i]; 188305b261ecSmrg len += fpe->name_length + 1; 188405b261ecSmrg } 18856747b715Smrg font_path_string = (unsigned char *) realloc(font_path_string, len); 188605b261ecSmrg if (!font_path_string) 18874642e01fSmrg return BadAlloc; 188805b261ecSmrg 188905b261ecSmrg c = font_path_string; 189005b261ecSmrg *length = 0; 189105b261ecSmrg for (i = 0; i < num_fpes; i++) { 189205b261ecSmrg fpe = font_path_elements[i]; 189305b261ecSmrg *c = fpe->name_length; 189405b261ecSmrg *length += *c++; 189505b261ecSmrg memmove(c, fpe->name, fpe->name_length); 189605b261ecSmrg c += fpe->name_length; 189705b261ecSmrg } 189805b261ecSmrg *count = num_fpes; 18994642e01fSmrg *result = font_path_string; 19004642e01fSmrg return Success; 190105b261ecSmrg} 190205b261ecSmrg 190305b261ecSmrgvoid 190405b261ecSmrgDeleteClientFontStuff(ClientPtr client) 190505b261ecSmrg{ 190605b261ecSmrg int i; 190705b261ecSmrg FontPathElementPtr fpe; 190805b261ecSmrg 190905b261ecSmrg for (i = 0; i < num_fpes; i++) 191005b261ecSmrg { 191105b261ecSmrg fpe = font_path_elements[i]; 191205b261ecSmrg if (fpe_functions[fpe->type].client_died) 191305b261ecSmrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 191405b261ecSmrg } 191505b261ecSmrg} 191605b261ecSmrg 191705b261ecSmrgvoid 191805b261ecSmrgInitFonts (void) 191905b261ecSmrg{ 192005b261ecSmrg patternCache = MakeFontPatternCache(); 192105b261ecSmrg 19226747b715Smrg register_fpe_functions(); 192305b261ecSmrg} 192405b261ecSmrg 192505b261ecSmrgint 19266747b715SmrgGetDefaultPointSize (void) 192705b261ecSmrg{ 192805b261ecSmrg return 120; 192905b261ecSmrg} 193005b261ecSmrg 193105b261ecSmrg 193205b261ecSmrgFontResolutionPtr 193305b261ecSmrgGetClientResolutions (int *num) 193405b261ecSmrg{ 19354642e01fSmrg static struct _FontResolution res; 19364642e01fSmrg ScreenPtr pScreen; 193705b261ecSmrg 19384642e01fSmrg pScreen = screenInfo.screens[0]; 19394642e01fSmrg res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth; 19404642e01fSmrg /* 19414642e01fSmrg * XXX - we'll want this as long as bitmap instances are prevalent 19424642e01fSmrg so that we can match them from scalable fonts 19434642e01fSmrg */ 19444642e01fSmrg if (res.x_resolution < 88) 19454642e01fSmrg res.x_resolution = 75; 19464642e01fSmrg else 19474642e01fSmrg res.x_resolution = 100; 19484642e01fSmrg res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight; 19494642e01fSmrg if (res.y_resolution < 88) 19504642e01fSmrg res.y_resolution = 75; 19514642e01fSmrg else 19524642e01fSmrg res.y_resolution = 100; 19534642e01fSmrg res.point_size = 120; 19544642e01fSmrg *num = 1; 19554642e01fSmrg return &res; 195605b261ecSmrg} 195705b261ecSmrg 195805b261ecSmrg/* 195905b261ecSmrg * returns the type index of the new fpe 196005b261ecSmrg * 196105b261ecSmrg * should be called (only once!) by each type of fpe when initialized 196205b261ecSmrg */ 196305b261ecSmrg 196405b261ecSmrgint 196505b261ecSmrgRegisterFPEFunctions(NameCheckFunc name_func, 196605b261ecSmrg InitFpeFunc init_func, 196705b261ecSmrg FreeFpeFunc free_func, 196805b261ecSmrg ResetFpeFunc reset_func, 196905b261ecSmrg OpenFontFunc open_func, 197005b261ecSmrg CloseFontFunc close_func, 197105b261ecSmrg ListFontsFunc list_func, 197205b261ecSmrg StartLfwiFunc start_lfwi_func, 197305b261ecSmrg NextLfwiFunc next_lfwi_func, 197405b261ecSmrg WakeupFpeFunc wakeup_func, 197505b261ecSmrg ClientDiedFunc client_died, 197605b261ecSmrg LoadGlyphsFunc load_glyphs, 197705b261ecSmrg StartLaFunc start_list_alias_func, 197805b261ecSmrg NextLaFunc next_list_alias_func, 197905b261ecSmrg SetPathFunc set_path_func) 198005b261ecSmrg{ 198105b261ecSmrg FPEFunctions *new; 198205b261ecSmrg 198305b261ecSmrg /* grow the list */ 19846747b715Smrg new = (FPEFunctions *) realloc(fpe_functions, 198505b261ecSmrg (num_fpe_types + 1) * sizeof(FPEFunctions)); 198605b261ecSmrg if (!new) 198705b261ecSmrg return -1; 198805b261ecSmrg fpe_functions = new; 198905b261ecSmrg 199005b261ecSmrg fpe_functions[num_fpe_types].name_check = name_func; 199105b261ecSmrg fpe_functions[num_fpe_types].open_font = open_func; 199205b261ecSmrg fpe_functions[num_fpe_types].close_font = close_func; 199305b261ecSmrg fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func; 199405b261ecSmrg fpe_functions[num_fpe_types].list_fonts = list_func; 199505b261ecSmrg fpe_functions[num_fpe_types].start_list_fonts_with_info = 199605b261ecSmrg start_lfwi_func; 199705b261ecSmrg fpe_functions[num_fpe_types].list_next_font_with_info = 199805b261ecSmrg next_lfwi_func; 199905b261ecSmrg fpe_functions[num_fpe_types].init_fpe = init_func; 200005b261ecSmrg fpe_functions[num_fpe_types].free_fpe = free_func; 200105b261ecSmrg fpe_functions[num_fpe_types].reset_fpe = reset_func; 200205b261ecSmrg fpe_functions[num_fpe_types].client_died = client_died; 200305b261ecSmrg fpe_functions[num_fpe_types].load_glyphs = load_glyphs; 200405b261ecSmrg fpe_functions[num_fpe_types].start_list_fonts_and_aliases = 200505b261ecSmrg start_list_alias_func; 200605b261ecSmrg fpe_functions[num_fpe_types].list_next_font_or_alias = 200705b261ecSmrg next_list_alias_func; 200805b261ecSmrg fpe_functions[num_fpe_types].set_path_hook = set_path_func; 200905b261ecSmrg 201005b261ecSmrg return num_fpe_types++; 201105b261ecSmrg} 201205b261ecSmrg 201305b261ecSmrgvoid 201405b261ecSmrgFreeFonts(void) 201505b261ecSmrg{ 201605b261ecSmrg if (patternCache) { 201705b261ecSmrg FreeFontPatternCache(patternCache); 201805b261ecSmrg patternCache = 0; 201905b261ecSmrg } 202005b261ecSmrg FreeFontPath(font_path_elements, num_fpes, TRUE); 202105b261ecSmrg font_path_elements = 0; 202205b261ecSmrg num_fpes = 0; 20236747b715Smrg free(fpe_functions); 202405b261ecSmrg num_fpe_types = 0; 202505b261ecSmrg fpe_functions = (FPEFunctions *) 0; 202605b261ecSmrg} 202705b261ecSmrg 202805b261ecSmrg/* convenience functions for FS interface */ 202905b261ecSmrg 203005b261ecSmrgFontPtr 203105b261ecSmrgfind_old_font(XID id) 203205b261ecSmrg{ 20336747b715Smrg pointer pFont; 20346747b715Smrg dixLookupResourceByType(&pFont, id, RT_NONE, serverClient, DixReadAccess); 20356747b715Smrg return (FontPtr)pFont; 203605b261ecSmrg} 203705b261ecSmrg 203805b261ecSmrgFont 20396747b715SmrgGetNewFontClientID(void) 204005b261ecSmrg{ 204105b261ecSmrg return FakeClientID(0); 204205b261ecSmrg} 204305b261ecSmrg 204405b261ecSmrgint 204505b261ecSmrgStoreFontClientFont(FontPtr pfont, Font id) 204605b261ecSmrg{ 204705b261ecSmrg return AddResource(id, RT_NONE, (pointer) pfont); 204805b261ecSmrg} 204905b261ecSmrg 205005b261ecSmrgvoid 205105b261ecSmrgDeleteFontClientID(Font id) 205205b261ecSmrg{ 205305b261ecSmrg FreeResource(id, RT_NONE); 205405b261ecSmrg} 205505b261ecSmrg 205605b261ecSmrgint 205705b261ecSmrgclient_auth_generation(ClientPtr client) 205805b261ecSmrg{ 205905b261ecSmrg return 0; 206005b261ecSmrg} 206105b261ecSmrg 206205b261ecSmrgstatic int fs_handlers_installed = 0; 206305b261ecSmrgstatic unsigned int last_server_gen; 206405b261ecSmrg 206505b261ecSmrgint 206605b261ecSmrginit_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler) 206705b261ecSmrg{ 206805b261ecSmrg /* if server has reset, make sure the b&w handlers are reinstalled */ 206905b261ecSmrg if (last_server_gen < serverGeneration) { 207005b261ecSmrg last_server_gen = serverGeneration; 207105b261ecSmrg fs_handlers_installed = 0; 207205b261ecSmrg } 207305b261ecSmrg if (fs_handlers_installed == 0) { 207405b261ecSmrg if (!RegisterBlockAndWakeupHandlers(block_handler, 207505b261ecSmrg FontWakeup, (pointer) 0)) 207605b261ecSmrg return AllocError; 207705b261ecSmrg fs_handlers_installed++; 207805b261ecSmrg } 207905b261ecSmrg QueueFontWakeup(fpe); 208005b261ecSmrg return Successful; 208105b261ecSmrg} 208205b261ecSmrg 208305b261ecSmrgvoid 208405b261ecSmrgremove_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler, Bool all) 208505b261ecSmrg{ 208605b261ecSmrg if (all) { 208705b261ecSmrg /* remove the handlers if no one else is using them */ 208805b261ecSmrg if (--fs_handlers_installed == 0) { 208905b261ecSmrg RemoveBlockAndWakeupHandlers(block_handler, FontWakeup, 209005b261ecSmrg (pointer) 0); 209105b261ecSmrg } 209205b261ecSmrg } 209305b261ecSmrg RemoveFontWakeup(fpe); 209405b261ecSmrg} 2095