dixfonts.c revision 9ace9065
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 XF86BIGFONT 706747b715Smrg#include "xf86bigfontsrv.h" 7105b261ecSmrg#endif 7205b261ecSmrg 7305b261ecSmrgextern pointer fosNaturalParams; 7405b261ecSmrgextern FontPtr defaultFont; 7505b261ecSmrg 7605b261ecSmrgstatic FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0; 7705b261ecSmrgstatic int num_fpes = 0; 784642e01fSmrgstatic FPEFunctions *fpe_functions = (FPEFunctions *) 0; 7905b261ecSmrgstatic int num_fpe_types = 0; 8005b261ecSmrg 8105b261ecSmrgstatic unsigned char *font_path_string; 8205b261ecSmrg 8305b261ecSmrgstatic int num_slept_fpes = 0; 8405b261ecSmrgstatic int size_slept_fpes = 0; 8505b261ecSmrgstatic FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0; 8605b261ecSmrgstatic FontPatternCachePtr patternCache; 8705b261ecSmrg 884642e01fSmrgstatic int 894642e01fSmrgFontToXError(int err) 9005b261ecSmrg{ 9105b261ecSmrg switch (err) { 9205b261ecSmrg case Successful: 9305b261ecSmrg return Success; 9405b261ecSmrg case AllocError: 9505b261ecSmrg return BadAlloc; 9605b261ecSmrg case BadFontName: 9705b261ecSmrg return BadName; 9805b261ecSmrg case BadFontPath: 9905b261ecSmrg case BadFontFormat: /* is there something better? */ 10005b261ecSmrg case BadCharRange: 10105b261ecSmrg return BadValue; 10205b261ecSmrg default: 10305b261ecSmrg return err; 10405b261ecSmrg } 10505b261ecSmrg} 10605b261ecSmrg 1074642e01fSmrgstatic int 1084642e01fSmrgLoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size, 1094642e01fSmrg unsigned char *data) 1104642e01fSmrg{ 1114642e01fSmrg if (fpe_functions[pfont->fpe->type].load_glyphs) 1124642e01fSmrg return (*fpe_functions[pfont->fpe->type].load_glyphs) 1134642e01fSmrg (client, pfont, 0, nchars, item_size, data); 1144642e01fSmrg else 1154642e01fSmrg return Successful; 1164642e01fSmrg} 11705b261ecSmrg 11805b261ecSmrg/* 11905b261ecSmrg * adding RT_FONT prevents conflict with default cursor font 12005b261ecSmrg */ 12105b261ecSmrgBool 12205b261ecSmrgSetDefaultFont(char *defaultfontname) 12305b261ecSmrg{ 12405b261ecSmrg int err; 12505b261ecSmrg FontPtr pf; 12605b261ecSmrg XID fid; 12705b261ecSmrg 12805b261ecSmrg fid = FakeClientID(0); 12905b261ecSmrg err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync, 13005b261ecSmrg (unsigned) strlen(defaultfontname), defaultfontname); 13105b261ecSmrg if (err != Success) 13205b261ecSmrg return FALSE; 1336747b715Smrg err = dixLookupResourceByType((pointer *)&pf, fid, RT_FONT, serverClient, 1346747b715Smrg DixReadAccess); 1356747b715Smrg if (err != Success) 13605b261ecSmrg return FALSE; 13705b261ecSmrg defaultFont = pf; 13805b261ecSmrg return TRUE; 13905b261ecSmrg} 14005b261ecSmrg 14105b261ecSmrg/* 14205b261ecSmrg * note that the font wakeup queue is not refcounted. this is because 14305b261ecSmrg * an fpe needs to be added when it's inited, and removed when it's finally 14405b261ecSmrg * freed, in order to handle any data that isn't requested, like FS events. 14505b261ecSmrg * 14605b261ecSmrg * since the only thing that should call these routines is the renderer's 14705b261ecSmrg * init_fpe() and free_fpe(), there shouldn't be any problem in using 14805b261ecSmrg * freed data. 14905b261ecSmrg */ 15005b261ecSmrgvoid 15105b261ecSmrgQueueFontWakeup(FontPathElementPtr fpe) 15205b261ecSmrg{ 15305b261ecSmrg int i; 15405b261ecSmrg FontPathElementPtr *new; 15505b261ecSmrg 15605b261ecSmrg for (i = 0; i < num_slept_fpes; i++) { 15705b261ecSmrg if (slept_fpes[i] == fpe) { 15805b261ecSmrg return; 15905b261ecSmrg } 16005b261ecSmrg } 16105b261ecSmrg if (num_slept_fpes == size_slept_fpes) { 16205b261ecSmrg new = (FontPathElementPtr *) 1636747b715Smrg realloc(slept_fpes, 16405b261ecSmrg sizeof(FontPathElementPtr) * (size_slept_fpes + 4)); 16505b261ecSmrg if (!new) 16605b261ecSmrg return; 16705b261ecSmrg slept_fpes = new; 16805b261ecSmrg size_slept_fpes += 4; 16905b261ecSmrg } 17005b261ecSmrg slept_fpes[num_slept_fpes] = fpe; 17105b261ecSmrg num_slept_fpes++; 17205b261ecSmrg} 17305b261ecSmrg 17405b261ecSmrgvoid 17505b261ecSmrgRemoveFontWakeup(FontPathElementPtr fpe) 17605b261ecSmrg{ 17705b261ecSmrg int i, 17805b261ecSmrg j; 17905b261ecSmrg 18005b261ecSmrg for (i = 0; i < num_slept_fpes; i++) { 18105b261ecSmrg if (slept_fpes[i] == fpe) { 18205b261ecSmrg for (j = i; j < num_slept_fpes; j++) { 18305b261ecSmrg slept_fpes[j] = slept_fpes[j + 1]; 18405b261ecSmrg } 18505b261ecSmrg num_slept_fpes--; 18605b261ecSmrg return; 18705b261ecSmrg } 18805b261ecSmrg } 18905b261ecSmrg} 19005b261ecSmrg 19105b261ecSmrgvoid 19205b261ecSmrgFontWakeup(pointer data, int count, pointer LastSelectMask) 19305b261ecSmrg{ 19405b261ecSmrg int i; 19505b261ecSmrg FontPathElementPtr fpe; 19605b261ecSmrg 19705b261ecSmrg if (count < 0) 19805b261ecSmrg return; 19905b261ecSmrg /* wake up any fpe's that may be waiting for information */ 20005b261ecSmrg for (i = 0; i < num_slept_fpes; i++) { 20105b261ecSmrg fpe = slept_fpes[i]; 20205b261ecSmrg (void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask); 20305b261ecSmrg } 20405b261ecSmrg} 20505b261ecSmrg 20605b261ecSmrg/* XXX -- these two funcs may want to be broken into macros */ 20705b261ecSmrgstatic void 20805b261ecSmrgUseFPE(FontPathElementPtr fpe) 20905b261ecSmrg{ 21005b261ecSmrg fpe->refcount++; 21105b261ecSmrg} 21205b261ecSmrg 21305b261ecSmrgstatic void 21405b261ecSmrgFreeFPE (FontPathElementPtr fpe) 21505b261ecSmrg{ 21605b261ecSmrg fpe->refcount--; 21705b261ecSmrg if (fpe->refcount == 0) { 21805b261ecSmrg (*fpe_functions[fpe->type].free_fpe) (fpe); 2196747b715Smrg free(fpe->name); 2206747b715Smrg free(fpe); 22105b261ecSmrg } 22205b261ecSmrg} 22305b261ecSmrg 22405b261ecSmrgstatic Bool 22505b261ecSmrgdoOpenFont(ClientPtr client, OFclosurePtr c) 22605b261ecSmrg{ 22705b261ecSmrg FontPtr pfont = NullFont; 22805b261ecSmrg FontPathElementPtr fpe = NULL; 22905b261ecSmrg ScreenPtr pScr; 23005b261ecSmrg int err = Successful; 23105b261ecSmrg int i; 23205b261ecSmrg char *alias, 23305b261ecSmrg *newname; 23405b261ecSmrg int newlen; 23505b261ecSmrg int aliascount = 20; 23605b261ecSmrg /* 23705b261ecSmrg * Decide at runtime what FontFormat to use. 23805b261ecSmrg */ 23905b261ecSmrg Mask FontFormat = 24005b261ecSmrg 24105b261ecSmrg ((screenInfo.imageByteOrder == LSBFirst) ? 24205b261ecSmrg BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) | 24305b261ecSmrg 24405b261ecSmrg ((screenInfo.bitmapBitOrder == LSBFirst) ? 24505b261ecSmrg BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) | 24605b261ecSmrg 24705b261ecSmrg BitmapFormatImageRectMin | 24805b261ecSmrg 24905b261ecSmrg#if GLYPHPADBYTES == 1 25005b261ecSmrg BitmapFormatScanlinePad8 | 25105b261ecSmrg#endif 25205b261ecSmrg 25305b261ecSmrg#if GLYPHPADBYTES == 2 25405b261ecSmrg BitmapFormatScanlinePad16 | 25505b261ecSmrg#endif 25605b261ecSmrg 25705b261ecSmrg#if GLYPHPADBYTES == 4 25805b261ecSmrg BitmapFormatScanlinePad32 | 25905b261ecSmrg#endif 26005b261ecSmrg 26105b261ecSmrg#if GLYPHPADBYTES == 8 26205b261ecSmrg BitmapFormatScanlinePad64 | 26305b261ecSmrg#endif 26405b261ecSmrg 26505b261ecSmrg BitmapFormatScanlineUnit8; 26605b261ecSmrg 26705b261ecSmrg if (client->clientGone) 26805b261ecSmrg { 26905b261ecSmrg if (c->current_fpe < c->num_fpes) 27005b261ecSmrg { 27105b261ecSmrg fpe = c->fpe_list[c->current_fpe]; 27205b261ecSmrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 27305b261ecSmrg } 27405b261ecSmrg err = Successful; 27505b261ecSmrg goto bail; 27605b261ecSmrg } 27705b261ecSmrg while (c->current_fpe < c->num_fpes) { 27805b261ecSmrg fpe = c->fpe_list[c->current_fpe]; 27905b261ecSmrg err = (*fpe_functions[fpe->type].open_font) 28005b261ecSmrg ((pointer) client, fpe, c->flags, 28105b261ecSmrg c->fontname, c->fnamelen, FontFormat, 28205b261ecSmrg BitmapFormatMaskByte | 28305b261ecSmrg BitmapFormatMaskBit | 28405b261ecSmrg BitmapFormatMaskImageRectangle | 28505b261ecSmrg BitmapFormatMaskScanLinePad | 28605b261ecSmrg BitmapFormatMaskScanLineUnit, 28705b261ecSmrg c->fontid, &pfont, &alias, 28805b261ecSmrg c->non_cachable_font && c->non_cachable_font->fpe == fpe ? 28905b261ecSmrg c->non_cachable_font : 29005b261ecSmrg (FontPtr)0); 29105b261ecSmrg 29205b261ecSmrg if (err == FontNameAlias && alias) { 29305b261ecSmrg newlen = strlen(alias); 2946747b715Smrg newname = (char *) realloc(c->fontname, newlen); 29505b261ecSmrg if (!newname) { 29605b261ecSmrg err = AllocError; 29705b261ecSmrg break; 29805b261ecSmrg } 29905b261ecSmrg memmove(newname, alias, newlen); 30005b261ecSmrg c->fontname = newname; 30105b261ecSmrg c->fnamelen = newlen; 30205b261ecSmrg c->current_fpe = 0; 3034642e01fSmrg if (--aliascount <= 0) { 3044642e01fSmrg /* We've tried resolving this alias 20 times, we're 3054642e01fSmrg * probably stuck in an infinite loop of aliases pointing 3064642e01fSmrg * to each other - time to take emergency exit! 3074642e01fSmrg */ 3084642e01fSmrg err = BadImplementation; 30905b261ecSmrg break; 3104642e01fSmrg } 31105b261ecSmrg continue; 31205b261ecSmrg } 31305b261ecSmrg if (err == BadFontName) { 31405b261ecSmrg c->current_fpe++; 31505b261ecSmrg continue; 31605b261ecSmrg } 31705b261ecSmrg if (err == Suspended) { 3186747b715Smrg if (!ClientIsAsleep(client)) 3196747b715Smrg ClientSleep(client, (ClientSleepProcPtr)doOpenFont, c); 3206747b715Smrg else 3216747b715Smrg goto xinerama_sleep; 32205b261ecSmrg return TRUE; 32305b261ecSmrg } 32405b261ecSmrg break; 32505b261ecSmrg } 32605b261ecSmrg 32705b261ecSmrg if (err != Successful) 32805b261ecSmrg goto bail; 32905b261ecSmrg if (!pfont) { 33005b261ecSmrg err = BadFontName; 33105b261ecSmrg goto bail; 33205b261ecSmrg } 33305b261ecSmrg /* check values for firstCol, lastCol, firstRow, and lastRow */ 33405b261ecSmrg if (pfont->info.firstCol > pfont->info.lastCol || 33505b261ecSmrg pfont->info.firstRow > pfont->info.lastRow || 33605b261ecSmrg pfont->info.lastCol - pfont->info.firstCol > 255) { 33705b261ecSmrg err = AllocError; 33805b261ecSmrg goto bail; 33905b261ecSmrg } 34005b261ecSmrg if (!pfont->fpe) 34105b261ecSmrg pfont->fpe = fpe; 34205b261ecSmrg pfont->refcnt++; 34305b261ecSmrg if (pfont->refcnt == 1) { 34405b261ecSmrg UseFPE(pfont->fpe); 34505b261ecSmrg for (i = 0; i < screenInfo.numScreens; i++) { 34605b261ecSmrg pScr = screenInfo.screens[i]; 34705b261ecSmrg if (pScr->RealizeFont) 34805b261ecSmrg { 34905b261ecSmrg if (!(*pScr->RealizeFont) (pScr, pfont)) 35005b261ecSmrg { 35105b261ecSmrg CloseFont (pfont, (Font) 0); 35205b261ecSmrg err = AllocError; 35305b261ecSmrg goto bail; 35405b261ecSmrg } 35505b261ecSmrg } 35605b261ecSmrg } 35705b261ecSmrg } 35805b261ecSmrg if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) { 35905b261ecSmrg err = AllocError; 36005b261ecSmrg goto bail; 36105b261ecSmrg } 36205b261ecSmrg if (patternCache && pfont != c->non_cachable_font) 36305b261ecSmrg CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen, 36405b261ecSmrg pfont); 36505b261ecSmrgbail: 36605b261ecSmrg if (err != Successful && c->client != serverClient) { 36705b261ecSmrg SendErrorToClient(c->client, X_OpenFont, 0, 36805b261ecSmrg c->fontid, FontToXError(err)); 36905b261ecSmrg } 3706747b715Smrg ClientWakeup(c->client); 3716747b715Smrgxinerama_sleep: 37205b261ecSmrg for (i = 0; i < c->num_fpes; i++) { 37305b261ecSmrg FreeFPE(c->fpe_list[i]); 37405b261ecSmrg } 3756747b715Smrg free(c->fpe_list); 3766747b715Smrg free(c->fontname); 3776747b715Smrg free(c); 37805b261ecSmrg return TRUE; 37905b261ecSmrg} 38005b261ecSmrg 38105b261ecSmrgint 38205b261ecSmrgOpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontname) 38305b261ecSmrg{ 38405b261ecSmrg OFclosurePtr c; 38505b261ecSmrg int i; 38605b261ecSmrg FontPtr cached = (FontPtr)0; 38705b261ecSmrg 38805b261ecSmrg if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) 38905b261ecSmrg return BadName; 39005b261ecSmrg if (patternCache) 39105b261ecSmrg { 39205b261ecSmrg 39305b261ecSmrg /* 39405b261ecSmrg ** Check name cache. If we find a cached version of this font that 39505b261ecSmrg ** is cachable, immediately satisfy the request with it. If we find 39605b261ecSmrg ** a cached version of this font that is non-cachable, we do not 39705b261ecSmrg ** satisfy the request with it. Instead, we pass the FontPtr to the 39805b261ecSmrg ** FPE's open_font code (the fontfile FPE in turn passes the 39905b261ecSmrg ** information to the rasterizer; the fserve FPE ignores it). 40005b261ecSmrg ** 40105b261ecSmrg ** Presumably, the font is marked non-cachable because the FPE has 40205b261ecSmrg ** put some licensing restrictions on it. If the FPE, using 40305b261ecSmrg ** whatever logic it relies on, determines that it is willing to 40405b261ecSmrg ** share this existing font with the client, then it has the option 40505b261ecSmrg ** to return the FontPtr we passed it as the newly-opened font. 40605b261ecSmrg ** This allows the FPE to exercise its licensing logic without 40705b261ecSmrg ** having to create another instance of a font that already exists. 40805b261ecSmrg */ 40905b261ecSmrg 41005b261ecSmrg cached = FindCachedFontPattern(patternCache, pfontname, lenfname); 41105b261ecSmrg if (cached && cached->info.cachable) 41205b261ecSmrg { 41305b261ecSmrg if (!AddResource(fid, RT_FONT, (pointer) cached)) 41405b261ecSmrg return BadAlloc; 41505b261ecSmrg cached->refcnt++; 41605b261ecSmrg return Success; 41705b261ecSmrg } 41805b261ecSmrg } 4196747b715Smrg c = malloc(sizeof(OFclosureRec)); 42005b261ecSmrg if (!c) 42105b261ecSmrg return BadAlloc; 4226747b715Smrg c->fontname = malloc(lenfname); 42305b261ecSmrg c->origFontName = pfontname; 42405b261ecSmrg c->origFontNameLen = lenfname; 42505b261ecSmrg if (!c->fontname) { 4266747b715Smrg free(c); 42705b261ecSmrg return BadAlloc; 42805b261ecSmrg } 42905b261ecSmrg /* 43005b261ecSmrg * copy the current FPE list, so that if it gets changed by another client 43105b261ecSmrg * while we're blocking, the request still appears atomic 43205b261ecSmrg */ 4336747b715Smrg c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes); 43405b261ecSmrg if (!c->fpe_list) { 4356747b715Smrg free(c->fontname); 4366747b715Smrg free(c); 43705b261ecSmrg return BadAlloc; 43805b261ecSmrg } 43905b261ecSmrg memmove(c->fontname, pfontname, lenfname); 44005b261ecSmrg for (i = 0; i < num_fpes; i++) { 44105b261ecSmrg c->fpe_list[i] = font_path_elements[i]; 44205b261ecSmrg UseFPE(c->fpe_list[i]); 44305b261ecSmrg } 44405b261ecSmrg c->client = client; 44505b261ecSmrg c->fontid = fid; 44605b261ecSmrg c->current_fpe = 0; 44705b261ecSmrg c->num_fpes = num_fpes; 44805b261ecSmrg c->fnamelen = lenfname; 44905b261ecSmrg c->flags = flags; 45005b261ecSmrg c->non_cachable_font = cached; 45105b261ecSmrg 45205b261ecSmrg (void) doOpenFont(client, c); 45305b261ecSmrg return Success; 45405b261ecSmrg} 45505b261ecSmrg 45605b261ecSmrg/** 45705b261ecSmrg * Decrement font's ref count, and free storage if ref count equals zero 45805b261ecSmrg * 45905b261ecSmrg * \param value must conform to DeleteType 46005b261ecSmrg */ 4614642e01fSmrgint 46205b261ecSmrgCloseFont(pointer value, XID fid) 46305b261ecSmrg{ 46405b261ecSmrg int nscr; 46505b261ecSmrg ScreenPtr pscr; 46605b261ecSmrg FontPathElementPtr fpe; 46705b261ecSmrg FontPtr pfont = (FontPtr)value; 46805b261ecSmrg 46905b261ecSmrg if (pfont == NullFont) 4706747b715Smrg return Success; 47105b261ecSmrg if (--pfont->refcnt == 0) { 47205b261ecSmrg if (patternCache) 47305b261ecSmrg RemoveCachedFontPattern (patternCache, pfont); 47405b261ecSmrg /* 47505b261ecSmrg * since the last reference is gone, ask each screen to free any 47605b261ecSmrg * storage it may have allocated locally for it. 47705b261ecSmrg */ 47805b261ecSmrg for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { 47905b261ecSmrg pscr = screenInfo.screens[nscr]; 48005b261ecSmrg if (pscr->UnrealizeFont) 48105b261ecSmrg (*pscr->UnrealizeFont) (pscr, pfont); 48205b261ecSmrg } 48305b261ecSmrg if (pfont == defaultFont) 48405b261ecSmrg defaultFont = NULL; 48505b261ecSmrg#ifdef XF86BIGFONT 48605b261ecSmrg XF86BigfontFreeFontShm(pfont); 48705b261ecSmrg#endif 48805b261ecSmrg fpe = pfont->fpe; 48905b261ecSmrg (*fpe_functions[fpe->type].close_font) (fpe, pfont); 49005b261ecSmrg FreeFPE(fpe); 49105b261ecSmrg } 4926747b715Smrg return Success; 49305b261ecSmrg} 49405b261ecSmrg 49505b261ecSmrg 49605b261ecSmrg/***====================================================================***/ 49705b261ecSmrg 49805b261ecSmrg/** 49905b261ecSmrg * Sets up pReply as the correct QueryFontReply for pFont with the first 50005b261ecSmrg * nProtoCCIStructs char infos. 50105b261ecSmrg * 50205b261ecSmrg * \param pReply caller must allocate this storage 50305b261ecSmrg */ 50405b261ecSmrgvoid 50505b261ecSmrgQueryFont(FontPtr pFont, xQueryFontReply *pReply, int nProtoCCIStructs) 50605b261ecSmrg{ 50705b261ecSmrg FontPropPtr pFP; 50805b261ecSmrg int r, 50905b261ecSmrg c, 51005b261ecSmrg i; 51105b261ecSmrg xFontProp *prFP; 51205b261ecSmrg xCharInfo *prCI; 51305b261ecSmrg xCharInfo *charInfos[256]; 51405b261ecSmrg unsigned char chars[512]; 51505b261ecSmrg int ninfos; 51605b261ecSmrg unsigned long ncols; 51705b261ecSmrg unsigned long count; 51805b261ecSmrg 51905b261ecSmrg /* pr->length set in dispatch */ 52005b261ecSmrg pReply->minCharOrByte2 = pFont->info.firstCol; 52105b261ecSmrg pReply->defaultChar = pFont->info.defaultCh; 52205b261ecSmrg pReply->maxCharOrByte2 = pFont->info.lastCol; 52305b261ecSmrg pReply->drawDirection = pFont->info.drawDirection; 52405b261ecSmrg pReply->allCharsExist = pFont->info.allExist; 52505b261ecSmrg pReply->minByte1 = pFont->info.firstRow; 52605b261ecSmrg pReply->maxByte1 = pFont->info.lastRow; 52705b261ecSmrg pReply->fontAscent = pFont->info.fontAscent; 52805b261ecSmrg pReply->fontDescent = pFont->info.fontDescent; 52905b261ecSmrg 53005b261ecSmrg pReply->minBounds = pFont->info.ink_minbounds; 53105b261ecSmrg pReply->maxBounds = pFont->info.ink_maxbounds; 53205b261ecSmrg 53305b261ecSmrg pReply->nFontProps = pFont->info.nprops; 53405b261ecSmrg pReply->nCharInfos = nProtoCCIStructs; 53505b261ecSmrg 53605b261ecSmrg for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]); 53705b261ecSmrg i < pFont->info.nprops; 53805b261ecSmrg i++, pFP++, prFP++) { 53905b261ecSmrg prFP->name = pFP->name; 54005b261ecSmrg prFP->value = pFP->value; 54105b261ecSmrg } 54205b261ecSmrg 54305b261ecSmrg ninfos = 0; 54405b261ecSmrg ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1); 54505b261ecSmrg prCI = (xCharInfo *) (prFP); 54605b261ecSmrg for (r = pFont->info.firstRow; 54705b261ecSmrg ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow; 54805b261ecSmrg r++) { 54905b261ecSmrg i = 0; 55005b261ecSmrg for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) { 55105b261ecSmrg chars[i++] = r; 55205b261ecSmrg chars[i++] = c; 55305b261ecSmrg } 55405b261ecSmrg (*pFont->get_metrics) (pFont, ncols, chars, 55505b261ecSmrg TwoD16Bit, &count, charInfos); 55605b261ecSmrg i = 0; 55705b261ecSmrg for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) { 55805b261ecSmrg *prCI = *charInfos[i]; 55905b261ecSmrg prCI++; 56005b261ecSmrg ninfos++; 56105b261ecSmrg } 56205b261ecSmrg } 56305b261ecSmrg return; 56405b261ecSmrg} 56505b261ecSmrg 56605b261ecSmrgstatic Bool 56705b261ecSmrgdoListFontsAndAliases(ClientPtr client, LFclosurePtr c) 56805b261ecSmrg{ 56905b261ecSmrg FontPathElementPtr fpe; 57005b261ecSmrg int err = Successful; 57105b261ecSmrg FontNamesPtr names = NULL; 57205b261ecSmrg char *name, *resolved=NULL; 57305b261ecSmrg int namelen, resolvedlen; 57405b261ecSmrg int nnames; 57505b261ecSmrg int stringLens; 57605b261ecSmrg int i; 57705b261ecSmrg xListFontsReply reply; 57805b261ecSmrg char *bufptr; 57905b261ecSmrg char *bufferStart; 58005b261ecSmrg int aliascount = 0; 58105b261ecSmrg 58205b261ecSmrg if (client->clientGone) 58305b261ecSmrg { 58405b261ecSmrg if (c->current.current_fpe < c->num_fpes) 58505b261ecSmrg { 58605b261ecSmrg fpe = c->fpe_list[c->current.current_fpe]; 58705b261ecSmrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 58805b261ecSmrg } 58905b261ecSmrg err = Successful; 59005b261ecSmrg goto bail; 59105b261ecSmrg } 59205b261ecSmrg 59305b261ecSmrg if (!c->current.patlen) 59405b261ecSmrg goto finish; 59505b261ecSmrg 59605b261ecSmrg while (c->current.current_fpe < c->num_fpes) { 59705b261ecSmrg fpe = c->fpe_list[c->current.current_fpe]; 59805b261ecSmrg err = Successful; 59905b261ecSmrg 60005b261ecSmrg if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) 60105b261ecSmrg { 60205b261ecSmrg /* This FPE doesn't support/require list_fonts_and_aliases */ 60305b261ecSmrg 60405b261ecSmrg err = (*fpe_functions[fpe->type].list_fonts) 60505b261ecSmrg ((pointer) c->client, fpe, c->current.pattern, 60605b261ecSmrg c->current.patlen, c->current.max_names - c->names->nnames, 60705b261ecSmrg c->names); 60805b261ecSmrg 60905b261ecSmrg if (err == Suspended) { 6106747b715Smrg if (!ClientIsAsleep(client)) 61105b261ecSmrg ClientSleep(client, 6126747b715Smrg (ClientSleepProcPtr)doListFontsAndAliases, 6136747b715Smrg c); 6146747b715Smrg else 6156747b715Smrg goto xinerama_sleep; 61605b261ecSmrg return TRUE; 61705b261ecSmrg } 61805b261ecSmrg 61905b261ecSmrg err = BadFontName; 62005b261ecSmrg } 62105b261ecSmrg else 62205b261ecSmrg { 62305b261ecSmrg /* Start of list_fonts_and_aliases functionality. Modeled 62405b261ecSmrg after list_fonts_with_info in that it resolves aliases, 62505b261ecSmrg except that the information collected from FPEs is just 62605b261ecSmrg names, not font info. Each list_next_font_or_alias() 62705b261ecSmrg returns either a name into name/namelen or an alias into 62805b261ecSmrg name/namelen and its target name into resolved/resolvedlen. 62905b261ecSmrg The code at this level then resolves the alias by polling 63005b261ecSmrg the FPEs. */ 63105b261ecSmrg 63205b261ecSmrg if (!c->current.list_started) { 63305b261ecSmrg err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) 63405b261ecSmrg ((pointer) c->client, fpe, c->current.pattern, 63505b261ecSmrg c->current.patlen, c->current.max_names - c->names->nnames, 63605b261ecSmrg &c->current.private); 63705b261ecSmrg if (err == Suspended) { 6386747b715Smrg if (!ClientIsAsleep(client)) 63905b261ecSmrg ClientSleep(client, 64005b261ecSmrg (ClientSleepProcPtr)doListFontsAndAliases, 6416747b715Smrg c); 6426747b715Smrg else 6436747b715Smrg goto xinerama_sleep; 64405b261ecSmrg return TRUE; 64505b261ecSmrg } 64605b261ecSmrg if (err == Successful) 64705b261ecSmrg c->current.list_started = TRUE; 64805b261ecSmrg } 64905b261ecSmrg if (err == Successful) { 65005b261ecSmrg char *tmpname; 65105b261ecSmrg name = 0; 65205b261ecSmrg err = (*fpe_functions[fpe->type].list_next_font_or_alias) 65305b261ecSmrg ((pointer) c->client, fpe, &name, &namelen, &tmpname, 65405b261ecSmrg &resolvedlen, c->current.private); 65505b261ecSmrg if (err == Suspended) { 6569ace9065Smrg if (!ClientIsAsleep(client)) 65705b261ecSmrg ClientSleep(client, 65805b261ecSmrg (ClientSleepProcPtr)doListFontsAndAliases, 6596747b715Smrg c); 6606747b715Smrg else 6616747b715Smrg goto xinerama_sleep; 66205b261ecSmrg return TRUE; 66305b261ecSmrg } 66405b261ecSmrg if (err == FontNameAlias) { 6656747b715Smrg free(resolved); 6666747b715Smrg resolved = malloc(resolvedlen + 1); 66705b261ecSmrg if (resolved) 66805b261ecSmrg memmove(resolved, tmpname, resolvedlen + 1); 66905b261ecSmrg } 67005b261ecSmrg } 67105b261ecSmrg 67205b261ecSmrg if (err == Successful) 67305b261ecSmrg { 67405b261ecSmrg if (c->haveSaved) 67505b261ecSmrg { 67605b261ecSmrg if (c->savedName) 67705b261ecSmrg (void)AddFontNamesName(c->names, c->savedName, 67805b261ecSmrg c->savedNameLen); 67905b261ecSmrg } 68005b261ecSmrg else 68105b261ecSmrg (void)AddFontNamesName(c->names, name, namelen); 68205b261ecSmrg } 68305b261ecSmrg 68405b261ecSmrg /* 68505b261ecSmrg * When we get an alias back, save our state and reset back to 68605b261ecSmrg * the start of the FPE looking for the specified name. As 68705b261ecSmrg * soon as a real font is found for the alias, pop back to the 68805b261ecSmrg * old state 68905b261ecSmrg */ 69005b261ecSmrg else if (err == FontNameAlias) { 69105b261ecSmrg char tmp_pattern[XLFDMAXFONTNAMELEN]; 69205b261ecSmrg /* 69305b261ecSmrg * when an alias recurses, we need to give 69405b261ecSmrg * the last FPE a chance to clean up; so we call 69505b261ecSmrg * it again, and assume that the error returned 69605b261ecSmrg * is BadFontName, indicating the alias resolution 69705b261ecSmrg * is complete. 69805b261ecSmrg */ 69905b261ecSmrg memmove(tmp_pattern, resolved, resolvedlen); 70005b261ecSmrg if (c->haveSaved) 70105b261ecSmrg { 70205b261ecSmrg char *tmpname; 70305b261ecSmrg int tmpnamelen; 70405b261ecSmrg 70505b261ecSmrg tmpname = 0; 70605b261ecSmrg (void) (*fpe_functions[fpe->type].list_next_font_or_alias) 70705b261ecSmrg ((pointer) c->client, fpe, &tmpname, &tmpnamelen, 70805b261ecSmrg &tmpname, &tmpnamelen, c->current.private); 70905b261ecSmrg if (--aliascount <= 0) 71005b261ecSmrg { 71105b261ecSmrg err = BadFontName; 71205b261ecSmrg goto ContBadFontName; 71305b261ecSmrg } 71405b261ecSmrg } 71505b261ecSmrg else 71605b261ecSmrg { 71705b261ecSmrg c->saved = c->current; 71805b261ecSmrg c->haveSaved = TRUE; 7196747b715Smrg free(c->savedName); 7206747b715Smrg c->savedName = malloc(namelen + 1); 72105b261ecSmrg if (c->savedName) 72205b261ecSmrg memmove(c->savedName, name, namelen + 1); 72305b261ecSmrg c->savedNameLen = namelen; 72405b261ecSmrg aliascount = 20; 72505b261ecSmrg } 72605b261ecSmrg memmove(c->current.pattern, tmp_pattern, resolvedlen); 72705b261ecSmrg c->current.patlen = resolvedlen; 72805b261ecSmrg c->current.max_names = c->names->nnames + 1; 72905b261ecSmrg c->current.current_fpe = -1; 73005b261ecSmrg c->current.private = 0; 73105b261ecSmrg err = BadFontName; 73205b261ecSmrg } 73305b261ecSmrg } 73405b261ecSmrg /* 73505b261ecSmrg * At the end of this FPE, step to the next. If we've finished 73605b261ecSmrg * processing an alias, pop state back. If we've collected enough 73705b261ecSmrg * font names, quit. 73805b261ecSmrg */ 73905b261ecSmrg if (err == BadFontName) { 74005b261ecSmrg ContBadFontName: ; 74105b261ecSmrg c->current.list_started = FALSE; 74205b261ecSmrg c->current.current_fpe++; 74305b261ecSmrg err = Successful; 74405b261ecSmrg if (c->haveSaved) 74505b261ecSmrg { 74605b261ecSmrg if (c->names->nnames == c->current.max_names || 74705b261ecSmrg c->current.current_fpe == c->num_fpes) { 74805b261ecSmrg c->haveSaved = FALSE; 74905b261ecSmrg c->current = c->saved; 75005b261ecSmrg /* Give the saved namelist a chance to clean itself up */ 75105b261ecSmrg continue; 75205b261ecSmrg } 75305b261ecSmrg } 75405b261ecSmrg if (c->names->nnames == c->current.max_names) 75505b261ecSmrg break; 75605b261ecSmrg } 75705b261ecSmrg } 75805b261ecSmrg 75905b261ecSmrg /* 76005b261ecSmrg * send the reply 76105b261ecSmrg */ 76205b261ecSmrg if (err != Successful) { 76305b261ecSmrg SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err)); 76405b261ecSmrg goto bail; 76505b261ecSmrg } 76605b261ecSmrg 76705b261ecSmrgfinish: 76805b261ecSmrg 76905b261ecSmrg names = c->names; 77005b261ecSmrg nnames = names->nnames; 77105b261ecSmrg client = c->client; 77205b261ecSmrg stringLens = 0; 77305b261ecSmrg for (i = 0; i < nnames; i++) 77405b261ecSmrg stringLens += (names->length[i] <= 255) ? names->length[i] : 0; 77505b261ecSmrg 7766747b715Smrg memset(&reply, 0, sizeof(xListFontsReply)); 77705b261ecSmrg reply.type = X_Reply; 7786747b715Smrg reply.length = bytes_to_int32(stringLens + nnames); 77905b261ecSmrg reply.nFonts = nnames; 78005b261ecSmrg reply.sequenceNumber = client->sequence; 78105b261ecSmrg 7826747b715Smrg bufptr = bufferStart = malloc(reply.length << 2); 78305b261ecSmrg 78405b261ecSmrg if (!bufptr && reply.length) { 78505b261ecSmrg SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc); 78605b261ecSmrg goto bail; 78705b261ecSmrg } 78805b261ecSmrg /* 78905b261ecSmrg * since WriteToClient long word aligns things, copy to temp buffer and 79005b261ecSmrg * write all at once 79105b261ecSmrg */ 79205b261ecSmrg for (i = 0; i < nnames; i++) { 79305b261ecSmrg if (names->length[i] > 255) 79405b261ecSmrg reply.nFonts--; 79505b261ecSmrg else 79605b261ecSmrg { 79705b261ecSmrg *bufptr++ = names->length[i]; 79805b261ecSmrg memmove( bufptr, names->names[i], names->length[i]); 79905b261ecSmrg bufptr += names->length[i]; 80005b261ecSmrg } 80105b261ecSmrg } 80205b261ecSmrg nnames = reply.nFonts; 8036747b715Smrg reply.length = bytes_to_int32(stringLens + nnames); 80405b261ecSmrg client->pSwapReplyFunc = ReplySwapVector[X_ListFonts]; 80505b261ecSmrg WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply); 80605b261ecSmrg (void) WriteToClient(client, stringLens + nnames, bufferStart); 8076747b715Smrg free(bufferStart); 80805b261ecSmrg 80905b261ecSmrgbail: 8106747b715Smrg ClientWakeup(client); 8116747b715Smrgxinerama_sleep: 81205b261ecSmrg for (i = 0; i < c->num_fpes; i++) 81305b261ecSmrg FreeFPE(c->fpe_list[i]); 8146747b715Smrg free(c->fpe_list); 8156747b715Smrg free(c->savedName); 81605b261ecSmrg FreeFontNames(names); 8176747b715Smrg free(c); 8186747b715Smrg free(resolved); 81905b261ecSmrg return TRUE; 82005b261ecSmrg} 82105b261ecSmrg 82205b261ecSmrgint 82305b261ecSmrgListFonts(ClientPtr client, unsigned char *pattern, unsigned length, 82405b261ecSmrg unsigned max_names) 82505b261ecSmrg{ 82605b261ecSmrg int i; 82705b261ecSmrg LFclosurePtr c; 82805b261ecSmrg 82905b261ecSmrg /* 83005b261ecSmrg * The right error to return here would be BadName, however the 83105b261ecSmrg * specification does not allow for a Name error on this request. 83205b261ecSmrg * Perhaps a better solution would be to return a nil list, i.e. 83305b261ecSmrg * a list containing zero fontnames. 83405b261ecSmrg */ 83505b261ecSmrg if (length > XLFDMAXFONTNAMELEN) 83605b261ecSmrg return BadAlloc; 83705b261ecSmrg 8384642e01fSmrg i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess); 8394642e01fSmrg if (i != Success) 8404642e01fSmrg return i; 8414642e01fSmrg 8426747b715Smrg if (!(c = malloc(sizeof *c))) 84305b261ecSmrg return BadAlloc; 8446747b715Smrg c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes); 84505b261ecSmrg if (!c->fpe_list) { 8466747b715Smrg free(c); 84705b261ecSmrg return BadAlloc; 84805b261ecSmrg } 84905b261ecSmrg c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100); 85005b261ecSmrg if (!c->names) 85105b261ecSmrg { 8526747b715Smrg free(c->fpe_list); 8536747b715Smrg free(c); 85405b261ecSmrg return BadAlloc; 85505b261ecSmrg } 85605b261ecSmrg memmove( c->current.pattern, pattern, length); 85705b261ecSmrg for (i = 0; i < num_fpes; i++) { 85805b261ecSmrg c->fpe_list[i] = font_path_elements[i]; 85905b261ecSmrg UseFPE(c->fpe_list[i]); 86005b261ecSmrg } 86105b261ecSmrg c->client = client; 86205b261ecSmrg c->num_fpes = num_fpes; 86305b261ecSmrg c->current.patlen = length; 86405b261ecSmrg c->current.current_fpe = 0; 86505b261ecSmrg c->current.max_names = max_names; 86605b261ecSmrg c->current.list_started = FALSE; 86705b261ecSmrg c->current.private = 0; 86805b261ecSmrg c->haveSaved = FALSE; 86905b261ecSmrg c->savedName = 0; 87005b261ecSmrg doListFontsAndAliases(client, c); 87105b261ecSmrg return Success; 87205b261ecSmrg} 87305b261ecSmrg 87405b261ecSmrgint 87505b261ecSmrgdoListFontsWithInfo(ClientPtr client, LFWIclosurePtr c) 87605b261ecSmrg{ 87705b261ecSmrg FontPathElementPtr fpe; 87805b261ecSmrg int err = Successful; 87905b261ecSmrg char *name; 88005b261ecSmrg int namelen; 88105b261ecSmrg int numFonts; 88205b261ecSmrg FontInfoRec fontInfo, 88305b261ecSmrg *pFontInfo; 88405b261ecSmrg xListFontsWithInfoReply *reply; 88505b261ecSmrg int length; 88605b261ecSmrg xFontProp *pFP; 88705b261ecSmrg int i; 88805b261ecSmrg int aliascount = 0; 88905b261ecSmrg xListFontsWithInfoReply finalReply; 89005b261ecSmrg 89105b261ecSmrg if (client->clientGone) 89205b261ecSmrg { 89305b261ecSmrg if (c->current.current_fpe < c->num_fpes) 89405b261ecSmrg { 89505b261ecSmrg fpe = c->fpe_list[c->current.current_fpe]; 89605b261ecSmrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 89705b261ecSmrg } 89805b261ecSmrg err = Successful; 89905b261ecSmrg goto bail; 90005b261ecSmrg } 90105b261ecSmrg client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo]; 90205b261ecSmrg if (!c->current.patlen) 90305b261ecSmrg goto finish; 90405b261ecSmrg while (c->current.current_fpe < c->num_fpes) 90505b261ecSmrg { 90605b261ecSmrg fpe = c->fpe_list[c->current.current_fpe]; 90705b261ecSmrg err = Successful; 90805b261ecSmrg if (!c->current.list_started) 90905b261ecSmrg { 91005b261ecSmrg err = (*fpe_functions[fpe->type].start_list_fonts_with_info) 91105b261ecSmrg (client, fpe, c->current.pattern, c->current.patlen, 91205b261ecSmrg c->current.max_names, &c->current.private); 91305b261ecSmrg if (err == Suspended) 91405b261ecSmrg { 9156747b715Smrg if (!ClientIsAsleep(client)) 9166747b715Smrg ClientSleep(client, 9176747b715Smrg (ClientSleepProcPtr)doListFontsWithInfo, c); 9186747b715Smrg else 9196747b715Smrg goto xinerama_sleep; 92005b261ecSmrg return TRUE; 92105b261ecSmrg } 92205b261ecSmrg if (err == Successful) 92305b261ecSmrg c->current.list_started = TRUE; 92405b261ecSmrg } 92505b261ecSmrg if (err == Successful) 92605b261ecSmrg { 92705b261ecSmrg name = 0; 92805b261ecSmrg pFontInfo = &fontInfo; 92905b261ecSmrg err = (*fpe_functions[fpe->type].list_next_font_with_info) 93005b261ecSmrg (client, fpe, &name, &namelen, &pFontInfo, 93105b261ecSmrg &numFonts, c->current.private); 93205b261ecSmrg if (err == Suspended) 93305b261ecSmrg { 9346747b715Smrg if (!ClientIsAsleep(client)) 93505b261ecSmrg ClientSleep(client, 9366747b715Smrg (ClientSleepProcPtr)doListFontsWithInfo, c); 9376747b715Smrg else 9386747b715Smrg goto xinerama_sleep; 93905b261ecSmrg return TRUE; 94005b261ecSmrg } 94105b261ecSmrg } 94205b261ecSmrg /* 94305b261ecSmrg * When we get an alias back, save our state and reset back to the 94405b261ecSmrg * start of the FPE looking for the specified name. As soon as a real 94505b261ecSmrg * font is found for the alias, pop back to the old state 94605b261ecSmrg */ 94705b261ecSmrg if (err == FontNameAlias) 94805b261ecSmrg { 94905b261ecSmrg /* 95005b261ecSmrg * when an alias recurses, we need to give 95105b261ecSmrg * the last FPE a chance to clean up; so we call 95205b261ecSmrg * it again, and assume that the error returned 95305b261ecSmrg * is BadFontName, indicating the alias resolution 95405b261ecSmrg * is complete. 95505b261ecSmrg */ 95605b261ecSmrg if (c->haveSaved) 95705b261ecSmrg { 95805b261ecSmrg char *tmpname; 95905b261ecSmrg int tmpnamelen; 96005b261ecSmrg FontInfoPtr tmpFontInfo; 96105b261ecSmrg 96205b261ecSmrg tmpname = 0; 96305b261ecSmrg tmpFontInfo = &fontInfo; 96405b261ecSmrg (void) (*fpe_functions[fpe->type].list_next_font_with_info) 96505b261ecSmrg (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo, 96605b261ecSmrg &numFonts, c->current.private); 96705b261ecSmrg if (--aliascount <= 0) 96805b261ecSmrg { 96905b261ecSmrg err = BadFontName; 97005b261ecSmrg goto ContBadFontName; 97105b261ecSmrg } 97205b261ecSmrg } 97305b261ecSmrg else 97405b261ecSmrg { 97505b261ecSmrg c->saved = c->current; 97605b261ecSmrg c->haveSaved = TRUE; 97705b261ecSmrg c->savedNumFonts = numFonts; 9786747b715Smrg free(c->savedName); 9796747b715Smrg c->savedName = malloc(namelen + 1); 98005b261ecSmrg if (c->savedName) 98105b261ecSmrg memmove(c->savedName, name, namelen + 1); 98205b261ecSmrg aliascount = 20; 98305b261ecSmrg } 98405b261ecSmrg memmove(c->current.pattern, name, namelen); 98505b261ecSmrg c->current.patlen = namelen; 98605b261ecSmrg c->current.max_names = 1; 98705b261ecSmrg c->current.current_fpe = 0; 98805b261ecSmrg c->current.private = 0; 98905b261ecSmrg c->current.list_started = FALSE; 99005b261ecSmrg } 99105b261ecSmrg /* 99205b261ecSmrg * At the end of this FPE, step to the next. If we've finished 99305b261ecSmrg * processing an alias, pop state back. If we've sent enough font 99405b261ecSmrg * names, quit. Always wait for BadFontName to let the FPE 99505b261ecSmrg * have a chance to clean up. 99605b261ecSmrg */ 99705b261ecSmrg else if (err == BadFontName) 99805b261ecSmrg { 99905b261ecSmrg ContBadFontName: ; 100005b261ecSmrg c->current.list_started = FALSE; 100105b261ecSmrg c->current.current_fpe++; 100205b261ecSmrg err = Successful; 100305b261ecSmrg if (c->haveSaved) 100405b261ecSmrg { 100505b261ecSmrg if (c->current.max_names == 0 || 100605b261ecSmrg c->current.current_fpe == c->num_fpes) 100705b261ecSmrg { 100805b261ecSmrg c->haveSaved = FALSE; 100905b261ecSmrg c->saved.max_names -= (1 - c->current.max_names); 101005b261ecSmrg c->current = c->saved; 101105b261ecSmrg } 101205b261ecSmrg } 101305b261ecSmrg else if (c->current.max_names == 0) 101405b261ecSmrg break; 101505b261ecSmrg } 101605b261ecSmrg else if (err == Successful) 101705b261ecSmrg { 101805b261ecSmrg length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp); 101905b261ecSmrg reply = c->reply; 102005b261ecSmrg if (c->length < length) 102105b261ecSmrg { 10226747b715Smrg reply = (xListFontsWithInfoReply *) realloc(c->reply, length); 102305b261ecSmrg if (!reply) 102405b261ecSmrg { 102505b261ecSmrg err = AllocError; 102605b261ecSmrg break; 102705b261ecSmrg } 10286747b715Smrg memset((char*)reply + c->length, 0, length - c->length); 102905b261ecSmrg c->reply = reply; 103005b261ecSmrg c->length = length; 103105b261ecSmrg } 103205b261ecSmrg if (c->haveSaved) 103305b261ecSmrg { 103405b261ecSmrg numFonts = c->savedNumFonts; 103505b261ecSmrg name = c->savedName; 103605b261ecSmrg namelen = strlen(name); 103705b261ecSmrg } 103805b261ecSmrg reply->type = X_Reply; 10396747b715Smrg reply->length = bytes_to_int32(sizeof *reply - sizeof(xGenericReply) + 104005b261ecSmrg pFontInfo->nprops * sizeof(xFontProp) + 10416747b715Smrg namelen); 104205b261ecSmrg reply->sequenceNumber = client->sequence; 104305b261ecSmrg reply->nameLength = namelen; 104405b261ecSmrg reply->minBounds = pFontInfo->ink_minbounds; 104505b261ecSmrg reply->maxBounds = pFontInfo->ink_maxbounds; 104605b261ecSmrg reply->minCharOrByte2 = pFontInfo->firstCol; 104705b261ecSmrg reply->maxCharOrByte2 = pFontInfo->lastCol; 104805b261ecSmrg reply->defaultChar = pFontInfo->defaultCh; 104905b261ecSmrg reply->nFontProps = pFontInfo->nprops; 105005b261ecSmrg reply->drawDirection = pFontInfo->drawDirection; 105105b261ecSmrg reply->minByte1 = pFontInfo->firstRow; 105205b261ecSmrg reply->maxByte1 = pFontInfo->lastRow; 105305b261ecSmrg reply->allCharsExist = pFontInfo->allExist; 105405b261ecSmrg reply->fontAscent = pFontInfo->fontAscent; 105505b261ecSmrg reply->fontDescent = pFontInfo->fontDescent; 105605b261ecSmrg reply->nReplies = numFonts; 105705b261ecSmrg pFP = (xFontProp *) (reply + 1); 105805b261ecSmrg for (i = 0; i < pFontInfo->nprops; i++) 105905b261ecSmrg { 106005b261ecSmrg pFP->name = pFontInfo->props[i].name; 106105b261ecSmrg pFP->value = pFontInfo->props[i].value; 106205b261ecSmrg pFP++; 106305b261ecSmrg } 106405b261ecSmrg WriteSwappedDataToClient(client, length, reply); 106505b261ecSmrg (void) WriteToClient(client, namelen, name); 106605b261ecSmrg if (pFontInfo == &fontInfo) 106705b261ecSmrg { 10686747b715Smrg free(fontInfo.props); 10696747b715Smrg free(fontInfo.isStringProp); 107005b261ecSmrg } 107105b261ecSmrg --c->current.max_names; 107205b261ecSmrg } 107305b261ecSmrg } 107405b261ecSmrgfinish: 107505b261ecSmrg length = sizeof(xListFontsWithInfoReply); 10766747b715Smrg memset((char *) &finalReply, 0, sizeof(xListFontsWithInfoReply)); 107705b261ecSmrg finalReply.type = X_Reply; 107805b261ecSmrg finalReply.sequenceNumber = client->sequence; 10796747b715Smrg finalReply.length = bytes_to_int32(sizeof(xListFontsWithInfoReply) 10806747b715Smrg - sizeof(xGenericReply)); 108105b261ecSmrg WriteSwappedDataToClient(client, length, &finalReply); 108205b261ecSmrgbail: 10836747b715Smrg ClientWakeup(client); 10846747b715Smrgxinerama_sleep: 108505b261ecSmrg for (i = 0; i < c->num_fpes; i++) 108605b261ecSmrg FreeFPE(c->fpe_list[i]); 10876747b715Smrg free(c->reply); 10886747b715Smrg free(c->fpe_list); 10896747b715Smrg free(c->savedName); 10906747b715Smrg free(c); 109105b261ecSmrg return TRUE; 109205b261ecSmrg} 109305b261ecSmrg 109405b261ecSmrgint 109505b261ecSmrgStartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern, 109605b261ecSmrg int max_names) 109705b261ecSmrg{ 109805b261ecSmrg int i; 109905b261ecSmrg LFWIclosurePtr c; 110005b261ecSmrg 110105b261ecSmrg /* 110205b261ecSmrg * The right error to return here would be BadName, however the 110305b261ecSmrg * specification does not allow for a Name error on this request. 110405b261ecSmrg * Perhaps a better solution would be to return a nil list, i.e. 110505b261ecSmrg * a list containing zero fontnames. 110605b261ecSmrg */ 110705b261ecSmrg if (length > XLFDMAXFONTNAMELEN) 110805b261ecSmrg return BadAlloc; 110905b261ecSmrg 11104642e01fSmrg i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess); 11114642e01fSmrg if (i != Success) 11124642e01fSmrg return i; 11134642e01fSmrg 11146747b715Smrg if (!(c = malloc(sizeof *c))) 111505b261ecSmrg goto badAlloc; 11166747b715Smrg c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes); 111705b261ecSmrg if (!c->fpe_list) 111805b261ecSmrg { 11196747b715Smrg free(c); 112005b261ecSmrg goto badAlloc; 112105b261ecSmrg } 112205b261ecSmrg memmove(c->current.pattern, pattern, length); 112305b261ecSmrg for (i = 0; i < num_fpes; i++) 112405b261ecSmrg { 112505b261ecSmrg c->fpe_list[i] = font_path_elements[i]; 112605b261ecSmrg UseFPE(c->fpe_list[i]); 112705b261ecSmrg } 112805b261ecSmrg c->client = client; 112905b261ecSmrg c->num_fpes = num_fpes; 113005b261ecSmrg c->reply = 0; 113105b261ecSmrg c->length = 0; 113205b261ecSmrg c->current.patlen = length; 113305b261ecSmrg c->current.current_fpe = 0; 113405b261ecSmrg c->current.max_names = max_names; 113505b261ecSmrg c->current.list_started = FALSE; 113605b261ecSmrg c->current.private = 0; 113705b261ecSmrg c->savedNumFonts = 0; 113805b261ecSmrg c->haveSaved = FALSE; 113905b261ecSmrg c->savedName = 0; 114005b261ecSmrg doListFontsWithInfo(client, c); 114105b261ecSmrg return Success; 114205b261ecSmrgbadAlloc: 114305b261ecSmrg return BadAlloc; 114405b261ecSmrg} 114505b261ecSmrg 114605b261ecSmrg#define TextEltHeader 2 114705b261ecSmrg#define FontShiftSize 5 11486747b715Smrgstatic ChangeGCVal clearGC[] = { { .ptr = NullPixmap } }; 114905b261ecSmrg#define clearGCmask (GCClipMask) 115005b261ecSmrg 115105b261ecSmrgint 115205b261ecSmrgdoPolyText(ClientPtr client, PTclosurePtr c) 115305b261ecSmrg{ 115405b261ecSmrg FontPtr pFont = c->pGC->font, oldpFont; 115505b261ecSmrg int err = Success, lgerr; /* err is in X error, not font error, space */ 115605b261ecSmrg enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT; 115705b261ecSmrg FontPathElementPtr fpe; 115805b261ecSmrg GC *origGC = NULL; 11599ace9065Smrg int itemSize = c->reqType == X_PolyText8 ? 1 : 2; 116005b261ecSmrg 116105b261ecSmrg if (client->clientGone) 116205b261ecSmrg { 116305b261ecSmrg fpe = c->pGC->font->fpe; 116405b261ecSmrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 116505b261ecSmrg 11666747b715Smrg if (ClientIsAsleep(client)) 116705b261ecSmrg { 116805b261ecSmrg /* Client has died, but we cannot bail out right now. We 116905b261ecSmrg need to clean up after the work we did when going to 117005b261ecSmrg sleep. Setting the drawable pointer to 0 makes this 117105b261ecSmrg happen without any attempts to render or perform other 117205b261ecSmrg unnecessary activities. */ 117305b261ecSmrg c->pDraw = (DrawablePtr)0; 117405b261ecSmrg } 117505b261ecSmrg else 117605b261ecSmrg { 117705b261ecSmrg err = Success; 117805b261ecSmrg goto bail; 117905b261ecSmrg } 118005b261ecSmrg } 118105b261ecSmrg 118205b261ecSmrg /* Make sure our drawable hasn't disappeared while we slept. */ 11836747b715Smrg if (ClientIsAsleep(client) && c->pDraw) 118405b261ecSmrg { 11856747b715Smrg DrawablePtr pDraw; 11866747b715Smrg dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess); 11876747b715Smrg if (c->pDraw != pDraw) { 11886747b715Smrg /* Our drawable has disappeared. Treat like client died... ask 11896747b715Smrg the FPE code to clean up after client and avoid further 11906747b715Smrg rendering while we clean up after ourself. */ 11916747b715Smrg fpe = c->pGC->font->fpe; 11926747b715Smrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 11936747b715Smrg c->pDraw = (DrawablePtr)0; 11946747b715Smrg } 119505b261ecSmrg } 119605b261ecSmrg 11976747b715Smrg client_state = ClientIsAsleep(client) ? SLEEPING : NEVER_SLEPT; 119805b261ecSmrg 119905b261ecSmrg while (c->endReq - c->pElt > TextEltHeader) 120005b261ecSmrg { 120105b261ecSmrg if (*c->pElt == FontChange) 120205b261ecSmrg { 12036747b715Smrg Font fid; 120405b261ecSmrg if (c->endReq - c->pElt < FontShiftSize) 120505b261ecSmrg { 120605b261ecSmrg err = BadLength; 120705b261ecSmrg goto bail; 120805b261ecSmrg } 120905b261ecSmrg 121005b261ecSmrg oldpFont = pFont; 121105b261ecSmrg 121205b261ecSmrg fid = ((Font)*(c->pElt+4)) /* big-endian */ 121305b261ecSmrg | ((Font)*(c->pElt+3)) << 8 121405b261ecSmrg | ((Font)*(c->pElt+2)) << 16 121505b261ecSmrg | ((Font)*(c->pElt+1)) << 24; 12166747b715Smrg err = dixLookupResourceByType((pointer *)&pFont, fid, RT_FONT, 12176747b715Smrg client, DixUseAccess); 12186747b715Smrg if (err != Success) 121905b261ecSmrg { 12206747b715Smrg /* restore pFont for step 4 (described below) */ 122105b261ecSmrg pFont = oldpFont; 122205b261ecSmrg 122305b261ecSmrg /* If we're in START_SLEEP mode, the following step 122405b261ecSmrg shortens the request... in the unlikely event that 122505b261ecSmrg the fid somehow becomes valid before we come through 122605b261ecSmrg again to actually execute the polytext, which would 122705b261ecSmrg then mess up our refcounting scheme badly. */ 122805b261ecSmrg c->err = err; 122905b261ecSmrg c->endReq = c->pElt; 123005b261ecSmrg 123105b261ecSmrg goto bail; 123205b261ecSmrg } 123305b261ecSmrg 123405b261ecSmrg /* Step 3 (described below) on our new font */ 123505b261ecSmrg if (client_state == START_SLEEP) 123605b261ecSmrg pFont->refcnt++; 123705b261ecSmrg else 123805b261ecSmrg { 123905b261ecSmrg if (pFont != c->pGC->font && c->pDraw) 124005b261ecSmrg { 12416747b715Smrg ChangeGCVal val; 12426747b715Smrg val.ptr = pFont; 12436747b715Smrg ChangeGC(NullClient, c->pGC, GCFont, &val); 124405b261ecSmrg ValidateGC(c->pDraw, c->pGC); 124505b261ecSmrg } 124605b261ecSmrg 124705b261ecSmrg /* Undo the refcnt++ we performed when going to sleep */ 124805b261ecSmrg if (client_state == SLEEPING) 124905b261ecSmrg (void)CloseFont(c->pGC->font, (Font)0); 125005b261ecSmrg } 125105b261ecSmrg c->pElt += FontShiftSize; 125205b261ecSmrg } 125305b261ecSmrg else /* print a string */ 125405b261ecSmrg { 125505b261ecSmrg unsigned char *pNextElt; 12569ace9065Smrg pNextElt = c->pElt + TextEltHeader + (*c->pElt) * itemSize; 125705b261ecSmrg if ( pNextElt > c->endReq) 125805b261ecSmrg { 125905b261ecSmrg err = BadLength; 126005b261ecSmrg goto bail; 126105b261ecSmrg } 126205b261ecSmrg if (client_state == START_SLEEP) 126305b261ecSmrg { 126405b261ecSmrg c->pElt = pNextElt; 126505b261ecSmrg continue; 126605b261ecSmrg } 126705b261ecSmrg if (c->pDraw) 126805b261ecSmrg { 12699ace9065Smrg lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, itemSize, 127005b261ecSmrg c->pElt + TextEltHeader); 127105b261ecSmrg } 127205b261ecSmrg else lgerr = Successful; 127305b261ecSmrg 127405b261ecSmrg if (lgerr == Suspended) 127505b261ecSmrg { 12766747b715Smrg if (!ClientIsAsleep(client)) { 127705b261ecSmrg int len; 127805b261ecSmrg GC *pGC; 127905b261ecSmrg PTclosurePtr new_closure; 128005b261ecSmrg 128105b261ecSmrg /* We're putting the client to sleep. We need to do a few things 128205b261ecSmrg to ensure successful and atomic-appearing execution of the 128305b261ecSmrg remainder of the request. First, copy the remainder of the 128405b261ecSmrg request into a safe malloc'd area. Second, create a scratch GC 128505b261ecSmrg to use for the remainder of the request. Third, mark all fonts 128605b261ecSmrg referenced in the remainder of the request to prevent their 128705b261ecSmrg deallocation. Fourth, make the original GC look like the 128805b261ecSmrg request has completed... set its font to the final font value 128905b261ecSmrg from this request. These GC manipulations are for the unlikely 129005b261ecSmrg (but possible) event that some other client is using the GC. 129105b261ecSmrg Steps 3 and 4 are performed by running this procedure through 129205b261ecSmrg the remainder of the request in a special no-render mode 129305b261ecSmrg indicated by client_state = START_SLEEP. */ 129405b261ecSmrg 129505b261ecSmrg /* Step 1 */ 129605b261ecSmrg /* Allocate a malloc'd closure structure to replace 129705b261ecSmrg the local one we were passed */ 12986747b715Smrg new_closure = malloc(sizeof(PTclosureRec)); 129905b261ecSmrg if (!new_closure) 130005b261ecSmrg { 130105b261ecSmrg err = BadAlloc; 130205b261ecSmrg goto bail; 130305b261ecSmrg } 130405b261ecSmrg *new_closure = *c; 130505b261ecSmrg c = new_closure; 130605b261ecSmrg 130705b261ecSmrg len = c->endReq - c->pElt; 13086747b715Smrg c->data = malloc(len); 130905b261ecSmrg if (!c->data) 131005b261ecSmrg { 13116747b715Smrg free(c); 131205b261ecSmrg err = BadAlloc; 131305b261ecSmrg goto bail; 131405b261ecSmrg } 131505b261ecSmrg memmove(c->data, c->pElt, len); 131605b261ecSmrg c->pElt = c->data; 131705b261ecSmrg c->endReq = c->pElt + len; 131805b261ecSmrg 131905b261ecSmrg /* Step 2 */ 132005b261ecSmrg 132105b261ecSmrg pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); 132205b261ecSmrg if (!pGC) 132305b261ecSmrg { 13246747b715Smrg free(c->data); 13256747b715Smrg free(c); 132605b261ecSmrg err = BadAlloc; 132705b261ecSmrg goto bail; 132805b261ecSmrg } 132905b261ecSmrg if ((err = CopyGC(c->pGC, pGC, GCFunction | 133005b261ecSmrg GCPlaneMask | GCForeground | 133105b261ecSmrg GCBackground | GCFillStyle | 133205b261ecSmrg GCTile | GCStipple | 133305b261ecSmrg GCTileStipXOrigin | 133405b261ecSmrg GCTileStipYOrigin | GCFont | 133505b261ecSmrg GCSubwindowMode | GCClipXOrigin | 133605b261ecSmrg GCClipYOrigin | GCClipMask)) != 133705b261ecSmrg Success) 133805b261ecSmrg { 133905b261ecSmrg FreeScratchGC(pGC); 13406747b715Smrg free(c->data); 13416747b715Smrg free(c); 134205b261ecSmrg err = BadAlloc; 134305b261ecSmrg goto bail; 134405b261ecSmrg } 134505b261ecSmrg origGC = c->pGC; 134605b261ecSmrg c->pGC = pGC; 134705b261ecSmrg ValidateGC(c->pDraw, c->pGC); 134805b261ecSmrg 13496747b715Smrg ClientSleep(client, (ClientSleepProcPtr)doPolyText, c); 135005b261ecSmrg 135105b261ecSmrg /* Set up to perform steps 3 and 4 */ 135205b261ecSmrg client_state = START_SLEEP; 135305b261ecSmrg continue; /* on to steps 3 and 4 */ 135405b261ecSmrg } 13556747b715Smrg else 13566747b715Smrg goto xinerama_sleep; 135705b261ecSmrg return TRUE; 135805b261ecSmrg } 135905b261ecSmrg else if (lgerr != Successful) 136005b261ecSmrg { 136105b261ecSmrg err = FontToXError(lgerr); 136205b261ecSmrg goto bail; 136305b261ecSmrg } 136405b261ecSmrg if (c->pDraw) 136505b261ecSmrg { 136605b261ecSmrg c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */ 13679ace9065Smrg if (c->reqType == X_PolyText8) 13689ace9065Smrg c->xorg = (* c->pGC->ops->PolyText8)(c->pDraw, c->pGC, c->xorg, c->yorg, 13699ace9065Smrg *c->pElt, (char *) (c->pElt + TextEltHeader)); 13709ace9065Smrg else 13719ace9065Smrg c->xorg = (* c->pGC->ops->PolyText16)(c->pDraw, c->pGC, c->xorg, c->yorg, 13729ace9065Smrg *c->pElt, (unsigned short *) (c->pElt + TextEltHeader)); 137305b261ecSmrg } 137405b261ecSmrg c->pElt = pNextElt; 137505b261ecSmrg } 137605b261ecSmrg } 137705b261ecSmrg 137805b261ecSmrgbail: 137905b261ecSmrg 138005b261ecSmrg if (client_state == START_SLEEP) 138105b261ecSmrg { 138205b261ecSmrg /* Step 4 */ 138305b261ecSmrg if (pFont != origGC->font) 138405b261ecSmrg { 13856747b715Smrg ChangeGCVal val; 13866747b715Smrg val.ptr = pFont; 13876747b715Smrg ChangeGC(NullClient, origGC, GCFont, &val); 138805b261ecSmrg ValidateGC(c->pDraw, origGC); 138905b261ecSmrg } 139005b261ecSmrg 139105b261ecSmrg /* restore pElt pointer for execution of remainder of the request */ 139205b261ecSmrg c->pElt = c->data; 139305b261ecSmrg return TRUE; 139405b261ecSmrg } 139505b261ecSmrg 139605b261ecSmrg if (c->err != Success) err = c->err; 139705b261ecSmrg if (err != Success && c->client != serverClient) { 139805b261ecSmrg#ifdef PANORAMIX 139905b261ecSmrg if (noPanoramiXExtension || !c->pGC->pScreen->myNum) 140005b261ecSmrg#endif 140105b261ecSmrg SendErrorToClient(c->client, c->reqType, 0, 0, err); 140205b261ecSmrg } 14036747b715Smrg if (ClientIsAsleep(client)) 140405b261ecSmrg { 140505b261ecSmrg ClientWakeup(c->client); 14066747b715Smrgxinerama_sleep: 14076747b715Smrg ChangeGC(NullClient, c->pGC, clearGCmask, clearGC); 140805b261ecSmrg 140905b261ecSmrg /* Unreference the font from the scratch GC */ 141005b261ecSmrg CloseFont(c->pGC->font, (Font)0); 141105b261ecSmrg c->pGC->font = NullFont; 141205b261ecSmrg 141305b261ecSmrg FreeScratchGC(c->pGC); 14146747b715Smrg free(c->data); 14156747b715Smrg free(c); 141605b261ecSmrg } 141705b261ecSmrg return TRUE; 141805b261ecSmrg} 141905b261ecSmrg 142005b261ecSmrgint 142105b261ecSmrgPolyText(ClientPtr client, DrawablePtr pDraw, GC *pGC, unsigned char *pElt, 142205b261ecSmrg unsigned char *endReq, int xorg, int yorg, int reqType, XID did) 142305b261ecSmrg{ 142405b261ecSmrg PTclosureRec local_closure; 142505b261ecSmrg 142605b261ecSmrg local_closure.pElt = pElt; 142705b261ecSmrg local_closure.endReq = endReq; 142805b261ecSmrg local_closure.client = client; 142905b261ecSmrg local_closure.pDraw = pDraw; 143005b261ecSmrg local_closure.xorg = xorg; 143105b261ecSmrg local_closure.yorg = yorg; 14329ace9065Smrg local_closure.reqType = reqType; 143305b261ecSmrg local_closure.pGC = pGC; 143405b261ecSmrg local_closure.did = did; 143505b261ecSmrg local_closure.err = Success; 143605b261ecSmrg 143705b261ecSmrg (void) doPolyText(client, &local_closure); 143805b261ecSmrg return Success; 143905b261ecSmrg} 144005b261ecSmrg 144105b261ecSmrg 144205b261ecSmrg#undef TextEltHeader 144305b261ecSmrg#undef FontShiftSize 144405b261ecSmrg 144505b261ecSmrgint 144605b261ecSmrgdoImageText(ClientPtr client, ITclosurePtr c) 144705b261ecSmrg{ 144805b261ecSmrg int err = Success, lgerr; /* err is in X error, not font error, space */ 144905b261ecSmrg FontPathElementPtr fpe; 14509ace9065Smrg int itemSize = c->reqType == X_ImageText8 ? 1 : 2; 145105b261ecSmrg 145205b261ecSmrg if (client->clientGone) 145305b261ecSmrg { 145405b261ecSmrg fpe = c->pGC->font->fpe; 145505b261ecSmrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 145605b261ecSmrg err = Success; 145705b261ecSmrg goto bail; 145805b261ecSmrg } 145905b261ecSmrg 146005b261ecSmrg /* Make sure our drawable hasn't disappeared while we slept. */ 14616747b715Smrg if (ClientIsAsleep(client) && c->pDraw) 146205b261ecSmrg { 14636747b715Smrg DrawablePtr pDraw; 14646747b715Smrg dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess); 14656747b715Smrg if (c->pDraw != pDraw) { 14666747b715Smrg /* Our drawable has disappeared. Treat like client died... ask 14676747b715Smrg the FPE code to clean up after client. */ 14686747b715Smrg fpe = c->pGC->font->fpe; 14696747b715Smrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 14706747b715Smrg err = Success; 14716747b715Smrg goto bail; 14726747b715Smrg } 147305b261ecSmrg } 147405b261ecSmrg 14759ace9065Smrg lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, itemSize, c->data); 147605b261ecSmrg if (lgerr == Suspended) 147705b261ecSmrg { 14786747b715Smrg if (!ClientIsAsleep(client)) { 147905b261ecSmrg GC *pGC; 148005b261ecSmrg unsigned char *data; 148105b261ecSmrg ITclosurePtr new_closure; 148205b261ecSmrg 148305b261ecSmrg /* We're putting the client to sleep. We need to 148405b261ecSmrg save some state. Similar problem to that handled 148505b261ecSmrg in doPolyText, but much simpler because the 148605b261ecSmrg request structure is much simpler. */ 148705b261ecSmrg 14886747b715Smrg new_closure = malloc(sizeof(ITclosureRec)); 148905b261ecSmrg if (!new_closure) 149005b261ecSmrg { 149105b261ecSmrg err = BadAlloc; 149205b261ecSmrg goto bail; 149305b261ecSmrg } 149405b261ecSmrg *new_closure = *c; 149505b261ecSmrg c = new_closure; 149605b261ecSmrg 14979ace9065Smrg data = malloc(c->nChars * itemSize); 149805b261ecSmrg if (!data) 149905b261ecSmrg { 15006747b715Smrg free(c); 150105b261ecSmrg err = BadAlloc; 150205b261ecSmrg goto bail; 150305b261ecSmrg } 15049ace9065Smrg memmove(data, c->data, c->nChars * itemSize); 150505b261ecSmrg c->data = data; 150605b261ecSmrg 150705b261ecSmrg pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); 150805b261ecSmrg if (!pGC) 150905b261ecSmrg { 15106747b715Smrg free(c->data); 15116747b715Smrg free(c); 151205b261ecSmrg err = BadAlloc; 151305b261ecSmrg goto bail; 151405b261ecSmrg } 151505b261ecSmrg if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask | 151605b261ecSmrg GCForeground | GCBackground | GCFillStyle | 151705b261ecSmrg GCTile | GCStipple | GCTileStipXOrigin | 151805b261ecSmrg GCTileStipYOrigin | GCFont | 151905b261ecSmrg GCSubwindowMode | GCClipXOrigin | 152005b261ecSmrg GCClipYOrigin | GCClipMask)) != Success) 152105b261ecSmrg { 152205b261ecSmrg FreeScratchGC(pGC); 15236747b715Smrg free(c->data); 15246747b715Smrg free(c); 152505b261ecSmrg err = BadAlloc; 152605b261ecSmrg goto bail; 152705b261ecSmrg } 152805b261ecSmrg c->pGC = pGC; 152905b261ecSmrg ValidateGC(c->pDraw, c->pGC); 153005b261ecSmrg 15316747b715Smrg ClientSleep(client, (ClientSleepProcPtr)doImageText, c); 153205b261ecSmrg } 15336747b715Smrg else 15346747b715Smrg goto xinerama_sleep; 153505b261ecSmrg return TRUE; 153605b261ecSmrg } 153705b261ecSmrg else if (lgerr != Successful) 153805b261ecSmrg { 153905b261ecSmrg err = FontToXError(lgerr); 154005b261ecSmrg goto bail; 154105b261ecSmrg } 154205b261ecSmrg if (c->pDraw) 154305b261ecSmrg { 15449ace9065Smrg if (c->reqType == X_ImageText8) 15459ace9065Smrg (* c->pGC->ops->ImageText8)(c->pDraw, c->pGC, c->xorg, c->yorg, 15469ace9065Smrg c->nChars, (char *) c->data); 15479ace9065Smrg else 15489ace9065Smrg (* c->pGC->ops->ImageText16)(c->pDraw, c->pGC, c->xorg, c->yorg, 15499ace9065Smrg c->nChars, (unsigned short *) c->data); 155005b261ecSmrg } 155105b261ecSmrg 155205b261ecSmrgbail: 155305b261ecSmrg 155405b261ecSmrg if (err != Success && c->client != serverClient) { 155505b261ecSmrg SendErrorToClient(c->client, c->reqType, 0, 0, err); 155605b261ecSmrg } 15576747b715Smrg if (ClientIsAsleep(client)) 155805b261ecSmrg { 155905b261ecSmrg ClientWakeup(c->client); 15606747b715Smrgxinerama_sleep: 15616747b715Smrg ChangeGC(NullClient, c->pGC, clearGCmask, clearGC); 156205b261ecSmrg 156305b261ecSmrg /* Unreference the font from the scratch GC */ 156405b261ecSmrg CloseFont(c->pGC->font, (Font)0); 156505b261ecSmrg c->pGC->font = NullFont; 156605b261ecSmrg 156705b261ecSmrg FreeScratchGC(c->pGC); 15686747b715Smrg free(c->data); 15696747b715Smrg free(c); 157005b261ecSmrg } 157105b261ecSmrg return TRUE; 157205b261ecSmrg} 157305b261ecSmrg 157405b261ecSmrgint 157505b261ecSmrgImageText(ClientPtr client, DrawablePtr pDraw, GC *pGC, int nChars, 157605b261ecSmrg unsigned char *data, int xorg, int yorg, int reqType, XID did) 157705b261ecSmrg{ 157805b261ecSmrg ITclosureRec local_closure; 157905b261ecSmrg 158005b261ecSmrg local_closure.client = client; 158105b261ecSmrg local_closure.pDraw = pDraw; 158205b261ecSmrg local_closure.pGC = pGC; 158305b261ecSmrg local_closure.nChars = nChars; 158405b261ecSmrg local_closure.data = data; 158505b261ecSmrg local_closure.xorg = xorg; 158605b261ecSmrg local_closure.yorg = yorg; 15879ace9065Smrg local_closure.reqType = reqType; 158805b261ecSmrg local_closure.did = did; 158905b261ecSmrg 159005b261ecSmrg (void) doImageText(client, &local_closure); 159105b261ecSmrg return Success; 159205b261ecSmrg} 159305b261ecSmrg 159405b261ecSmrg 159505b261ecSmrg/* does the necessary magic to figure out the fpe type */ 159605b261ecSmrgstatic int 159705b261ecSmrgDetermineFPEType(char *pathname) 159805b261ecSmrg{ 159905b261ecSmrg int i; 160005b261ecSmrg 160105b261ecSmrg for (i = 0; i < num_fpe_types; i++) { 160205b261ecSmrg if ((*fpe_functions[i].name_check) (pathname)) 160305b261ecSmrg return i; 160405b261ecSmrg } 160505b261ecSmrg return -1; 160605b261ecSmrg} 160705b261ecSmrg 160805b261ecSmrg 160905b261ecSmrgstatic void 161005b261ecSmrgFreeFontPath(FontPathElementPtr *list, int n, Bool force) 161105b261ecSmrg{ 161205b261ecSmrg int i; 161305b261ecSmrg 161405b261ecSmrg for (i = 0; i < n; i++) { 161505b261ecSmrg if (force) { 161605b261ecSmrg /* Sanity check that all refcounts will be 0 by the time 161705b261ecSmrg we get to the end of the list. */ 161805b261ecSmrg int found = 1; /* the first reference is us */ 161905b261ecSmrg int j; 162005b261ecSmrg for (j = i+1; j < n; j++) { 162105b261ecSmrg if (list[j] == list[i]) 162205b261ecSmrg found++; 162305b261ecSmrg } 162405b261ecSmrg if (list[i]->refcount != found) { 162505b261ecSmrg list[i]->refcount = found; /* ensure it will get freed */ 162605b261ecSmrg } 162705b261ecSmrg } 162805b261ecSmrg FreeFPE(list[i]); 162905b261ecSmrg } 16306747b715Smrg free(list); 163105b261ecSmrg} 163205b261ecSmrg 163305b261ecSmrgstatic FontPathElementPtr 163405b261ecSmrgfind_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len) 163505b261ecSmrg{ 163605b261ecSmrg FontPathElementPtr fpe; 163705b261ecSmrg int i; 163805b261ecSmrg 163905b261ecSmrg for (i = 0; i < num; i++) { 164005b261ecSmrg fpe = list[i]; 164105b261ecSmrg if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0) 164205b261ecSmrg return fpe; 164305b261ecSmrg } 164405b261ecSmrg return (FontPathElementPtr) 0; 164505b261ecSmrg} 164605b261ecSmrg 164705b261ecSmrg 164805b261ecSmrgstatic int 164905b261ecSmrgSetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist) 165005b261ecSmrg{ 165105b261ecSmrg int i, err = 0; 165205b261ecSmrg int valid_paths = 0; 165305b261ecSmrg unsigned int len; 165405b261ecSmrg unsigned char *cp = paths; 165505b261ecSmrg FontPathElementPtr fpe = NULL, *fplist; 165605b261ecSmrg 16576747b715Smrg fplist = malloc(sizeof(FontPathElementPtr) * npaths); 165805b261ecSmrg if (!fplist) { 165905b261ecSmrg *bad = 0; 166005b261ecSmrg return BadAlloc; 166105b261ecSmrg } 166205b261ecSmrg for (i = 0; i < num_fpe_types; i++) { 166305b261ecSmrg if (fpe_functions[i].set_path_hook) 166405b261ecSmrg (*fpe_functions[i].set_path_hook) (); 166505b261ecSmrg } 166605b261ecSmrg for (i = 0; i < npaths; i++) 166705b261ecSmrg { 166805b261ecSmrg len = (unsigned int) (*cp++); 166905b261ecSmrg 167005b261ecSmrg if (len == 0) 167105b261ecSmrg { 167205b261ecSmrg if (persist) 16734642e01fSmrg ErrorF("[dix] Removing empty element from the valid list of fontpaths\n"); 167405b261ecSmrg err = BadValue; 167505b261ecSmrg } 167605b261ecSmrg else 167705b261ecSmrg { 167805b261ecSmrg /* if it's already in our active list, just reset it */ 167905b261ecSmrg /* 168005b261ecSmrg * note that this can miss FPE's in limbo -- may be worth catching 168105b261ecSmrg * them, though it'd muck up refcounting 168205b261ecSmrg */ 168305b261ecSmrg fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len); 168405b261ecSmrg if (fpe) 168505b261ecSmrg { 168605b261ecSmrg err = (*fpe_functions[fpe->type].reset_fpe) (fpe); 168705b261ecSmrg if (err == Successful) 168805b261ecSmrg { 168905b261ecSmrg UseFPE(fpe);/* since it'll be decref'd later when freed 169005b261ecSmrg * from the old list */ 169105b261ecSmrg } 169205b261ecSmrg else 169305b261ecSmrg fpe = 0; 169405b261ecSmrg } 169505b261ecSmrg /* if error or can't do it, act like it's a new one */ 169605b261ecSmrg if (!fpe) 169705b261ecSmrg { 16986747b715Smrg fpe = malloc(sizeof(FontPathElementRec)); 169905b261ecSmrg if (!fpe) 170005b261ecSmrg { 170105b261ecSmrg err = BadAlloc; 170205b261ecSmrg goto bail; 170305b261ecSmrg } 17046747b715Smrg fpe->name = malloc(len + 1); 170505b261ecSmrg if (!fpe->name) 170605b261ecSmrg { 17076747b715Smrg free(fpe); 170805b261ecSmrg err = BadAlloc; 170905b261ecSmrg goto bail; 171005b261ecSmrg } 171105b261ecSmrg fpe->refcount = 1; 171205b261ecSmrg 171305b261ecSmrg strncpy(fpe->name, (char *) cp, (int) len); 171405b261ecSmrg fpe->name[len] = '\0'; 171505b261ecSmrg fpe->name_length = len; 171605b261ecSmrg fpe->type = DetermineFPEType(fpe->name); 171705b261ecSmrg if (fpe->type == -1) 171805b261ecSmrg err = BadValue; 171905b261ecSmrg else 172005b261ecSmrg err = (*fpe_functions[fpe->type].init_fpe) (fpe); 172105b261ecSmrg if (err != Successful) 172205b261ecSmrg { 172305b261ecSmrg if (persist) 172405b261ecSmrg { 17254642e01fSmrg ErrorF("[dix] Could not init font path element %s, removing from list!\n", 172605b261ecSmrg fpe->name); 172705b261ecSmrg } 17286747b715Smrg free(fpe->name); 17296747b715Smrg free(fpe); 173005b261ecSmrg } 173105b261ecSmrg } 173205b261ecSmrg } 173305b261ecSmrg if (err != Successful) 173405b261ecSmrg { 173505b261ecSmrg if (!persist) 173605b261ecSmrg goto bail; 173705b261ecSmrg } 173805b261ecSmrg else 173905b261ecSmrg { 174005b261ecSmrg fplist[valid_paths++] = fpe; 174105b261ecSmrg } 174205b261ecSmrg cp += len; 174305b261ecSmrg } 174405b261ecSmrg 174505b261ecSmrg FreeFontPath(font_path_elements, num_fpes, FALSE); 174605b261ecSmrg font_path_elements = fplist; 174705b261ecSmrg if (patternCache) 174805b261ecSmrg EmptyFontPatternCache(patternCache); 174905b261ecSmrg num_fpes = valid_paths; 175005b261ecSmrg 175105b261ecSmrg return Success; 175205b261ecSmrgbail: 175305b261ecSmrg *bad = i; 175405b261ecSmrg while (--valid_paths >= 0) 175505b261ecSmrg FreeFPE(fplist[valid_paths]); 17566747b715Smrg free(fplist); 175705b261ecSmrg return FontToXError(err); 175805b261ecSmrg} 175905b261ecSmrg 176005b261ecSmrgint 17616747b715SmrgSetFontPath(ClientPtr client, int npaths, unsigned char *paths) 176205b261ecSmrg{ 17634642e01fSmrg int err = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess); 17644642e01fSmrg if (err != Success) 17654642e01fSmrg return err; 176605b261ecSmrg 176705b261ecSmrg if (npaths == 0) { 176805b261ecSmrg if (SetDefaultFontPath(defaultFontPath) != Success) 176905b261ecSmrg return BadValue; 177005b261ecSmrg } else { 17716747b715Smrg int bad; 17726747b715Smrg err = SetFontPathElements(npaths, paths, &bad, FALSE); 17736747b715Smrg client->errorValue = bad; 177405b261ecSmrg } 177505b261ecSmrg return err; 177605b261ecSmrg} 177705b261ecSmrg 177805b261ecSmrgint 177905b261ecSmrgSetDefaultFontPath(char *path) 178005b261ecSmrg{ 1781b1d344b3Smrg char *temp_path, 1782b1d344b3Smrg *start, 1783b1d344b3Smrg *end; 178405b261ecSmrg unsigned char *cp, 178505b261ecSmrg *pp, 178605b261ecSmrg *nump, 178705b261ecSmrg *newpath; 178805b261ecSmrg int num = 1, 178905b261ecSmrg len, 179005b261ecSmrg err, 179105b261ecSmrg size = 0, 179205b261ecSmrg bad; 179305b261ecSmrg 1794b1d344b3Smrg /* ensure temp_path contains "built-ins" */ 1795b1d344b3Smrg start = path; 1796b1d344b3Smrg while (1) { 1797b1d344b3Smrg start = strstr(start, "built-ins"); 1798b1d344b3Smrg if (start == NULL) 1799b1d344b3Smrg break; 1800b1d344b3Smrg end = start + strlen("built-ins"); 1801b1d344b3Smrg if ((start == path || start[-1] == ',') && (!*end || *end == ',')) 1802b1d344b3Smrg break; 1803b1d344b3Smrg start = end; 1804b1d344b3Smrg } 1805b1d344b3Smrg if (!start) { 18069ace9065Smrg if (asprintf(&temp_path, "%s%sbuilt-ins", path, *path ? "," : "") 18079ace9065Smrg == -1) 18089ace9065Smrg temp_path = NULL; 1809b1d344b3Smrg } else { 18106747b715Smrg temp_path = strdup(path); 1811b1d344b3Smrg } 1812b1d344b3Smrg if (!temp_path) 1813b1d344b3Smrg return BadAlloc; 1814b1d344b3Smrg 181505b261ecSmrg /* get enough for string, plus values -- use up commas */ 1816b1d344b3Smrg len = strlen(temp_path) + 1; 18176747b715Smrg nump = cp = newpath = malloc(len); 18189ace9065Smrg if (!newpath) { 18199ace9065Smrg free(temp_path); 182005b261ecSmrg return BadAlloc; 18219ace9065Smrg } 1822b1d344b3Smrg pp = (unsigned char *) temp_path; 182305b261ecSmrg cp++; 182405b261ecSmrg while (*pp) { 182505b261ecSmrg if (*pp == ',') { 182605b261ecSmrg *nump = (unsigned char) size; 182705b261ecSmrg nump = cp++; 182805b261ecSmrg pp++; 182905b261ecSmrg num++; 183005b261ecSmrg size = 0; 183105b261ecSmrg } else { 183205b261ecSmrg *cp++ = *pp++; 183305b261ecSmrg size++; 183405b261ecSmrg } 183505b261ecSmrg } 183605b261ecSmrg *nump = (unsigned char) size; 183705b261ecSmrg 183805b261ecSmrg err = SetFontPathElements(num, newpath, &bad, TRUE); 183905b261ecSmrg 18406747b715Smrg free(newpath); 18416747b715Smrg free(temp_path); 184205b261ecSmrg 184305b261ecSmrg return err; 184405b261ecSmrg} 184505b261ecSmrg 18464642e01fSmrgint 18474642e01fSmrgGetFontPath(ClientPtr client, int *count, int *length, unsigned char **result) 184805b261ecSmrg{ 184905b261ecSmrg int i; 185005b261ecSmrg unsigned char *c; 185105b261ecSmrg int len; 185205b261ecSmrg FontPathElementPtr fpe; 185305b261ecSmrg 18544642e01fSmrg i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess); 18554642e01fSmrg if (i != Success) 18564642e01fSmrg return i; 18574642e01fSmrg 185805b261ecSmrg len = 0; 185905b261ecSmrg for (i = 0; i < num_fpes; i++) { 186005b261ecSmrg fpe = font_path_elements[i]; 186105b261ecSmrg len += fpe->name_length + 1; 186205b261ecSmrg } 18636747b715Smrg font_path_string = (unsigned char *) realloc(font_path_string, len); 186405b261ecSmrg if (!font_path_string) 18654642e01fSmrg return BadAlloc; 186605b261ecSmrg 186705b261ecSmrg c = font_path_string; 186805b261ecSmrg *length = 0; 186905b261ecSmrg for (i = 0; i < num_fpes; i++) { 187005b261ecSmrg fpe = font_path_elements[i]; 187105b261ecSmrg *c = fpe->name_length; 187205b261ecSmrg *length += *c++; 187305b261ecSmrg memmove(c, fpe->name, fpe->name_length); 187405b261ecSmrg c += fpe->name_length; 187505b261ecSmrg } 187605b261ecSmrg *count = num_fpes; 18774642e01fSmrg *result = font_path_string; 18784642e01fSmrg return Success; 187905b261ecSmrg} 188005b261ecSmrg 188105b261ecSmrgvoid 188205b261ecSmrgDeleteClientFontStuff(ClientPtr client) 188305b261ecSmrg{ 188405b261ecSmrg int i; 188505b261ecSmrg FontPathElementPtr fpe; 188605b261ecSmrg 188705b261ecSmrg for (i = 0; i < num_fpes; i++) 188805b261ecSmrg { 188905b261ecSmrg fpe = font_path_elements[i]; 189005b261ecSmrg if (fpe_functions[fpe->type].client_died) 189105b261ecSmrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 189205b261ecSmrg } 189305b261ecSmrg} 189405b261ecSmrg 189505b261ecSmrgvoid 189605b261ecSmrgInitFonts (void) 189705b261ecSmrg{ 189805b261ecSmrg patternCache = MakeFontPatternCache(); 189905b261ecSmrg 19006747b715Smrg register_fpe_functions(); 190105b261ecSmrg} 190205b261ecSmrg 190305b261ecSmrgint 19046747b715SmrgGetDefaultPointSize (void) 190505b261ecSmrg{ 190605b261ecSmrg return 120; 190705b261ecSmrg} 190805b261ecSmrg 190905b261ecSmrg 191005b261ecSmrgFontResolutionPtr 191105b261ecSmrgGetClientResolutions (int *num) 191205b261ecSmrg{ 19134642e01fSmrg static struct _FontResolution res; 19144642e01fSmrg ScreenPtr pScreen; 191505b261ecSmrg 19164642e01fSmrg pScreen = screenInfo.screens[0]; 19174642e01fSmrg res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth; 19184642e01fSmrg /* 19194642e01fSmrg * XXX - we'll want this as long as bitmap instances are prevalent 19204642e01fSmrg so that we can match them from scalable fonts 19214642e01fSmrg */ 19224642e01fSmrg if (res.x_resolution < 88) 19234642e01fSmrg res.x_resolution = 75; 19244642e01fSmrg else 19254642e01fSmrg res.x_resolution = 100; 19264642e01fSmrg res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight; 19274642e01fSmrg if (res.y_resolution < 88) 19284642e01fSmrg res.y_resolution = 75; 19294642e01fSmrg else 19304642e01fSmrg res.y_resolution = 100; 19314642e01fSmrg res.point_size = 120; 19324642e01fSmrg *num = 1; 19334642e01fSmrg return &res; 193405b261ecSmrg} 193505b261ecSmrg 193605b261ecSmrg/* 193705b261ecSmrg * returns the type index of the new fpe 193805b261ecSmrg * 193905b261ecSmrg * should be called (only once!) by each type of fpe when initialized 194005b261ecSmrg */ 194105b261ecSmrg 194205b261ecSmrgint 194305b261ecSmrgRegisterFPEFunctions(NameCheckFunc name_func, 194405b261ecSmrg InitFpeFunc init_func, 194505b261ecSmrg FreeFpeFunc free_func, 194605b261ecSmrg ResetFpeFunc reset_func, 194705b261ecSmrg OpenFontFunc open_func, 194805b261ecSmrg CloseFontFunc close_func, 194905b261ecSmrg ListFontsFunc list_func, 195005b261ecSmrg StartLfwiFunc start_lfwi_func, 195105b261ecSmrg NextLfwiFunc next_lfwi_func, 195205b261ecSmrg WakeupFpeFunc wakeup_func, 195305b261ecSmrg ClientDiedFunc client_died, 195405b261ecSmrg LoadGlyphsFunc load_glyphs, 195505b261ecSmrg StartLaFunc start_list_alias_func, 195605b261ecSmrg NextLaFunc next_list_alias_func, 195705b261ecSmrg SetPathFunc set_path_func) 195805b261ecSmrg{ 195905b261ecSmrg FPEFunctions *new; 196005b261ecSmrg 196105b261ecSmrg /* grow the list */ 19626747b715Smrg new = (FPEFunctions *) realloc(fpe_functions, 196305b261ecSmrg (num_fpe_types + 1) * sizeof(FPEFunctions)); 196405b261ecSmrg if (!new) 196505b261ecSmrg return -1; 196605b261ecSmrg fpe_functions = new; 196705b261ecSmrg 196805b261ecSmrg fpe_functions[num_fpe_types].name_check = name_func; 196905b261ecSmrg fpe_functions[num_fpe_types].open_font = open_func; 197005b261ecSmrg fpe_functions[num_fpe_types].close_font = close_func; 197105b261ecSmrg fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func; 197205b261ecSmrg fpe_functions[num_fpe_types].list_fonts = list_func; 197305b261ecSmrg fpe_functions[num_fpe_types].start_list_fonts_with_info = 197405b261ecSmrg start_lfwi_func; 197505b261ecSmrg fpe_functions[num_fpe_types].list_next_font_with_info = 197605b261ecSmrg next_lfwi_func; 197705b261ecSmrg fpe_functions[num_fpe_types].init_fpe = init_func; 197805b261ecSmrg fpe_functions[num_fpe_types].free_fpe = free_func; 197905b261ecSmrg fpe_functions[num_fpe_types].reset_fpe = reset_func; 198005b261ecSmrg fpe_functions[num_fpe_types].client_died = client_died; 198105b261ecSmrg fpe_functions[num_fpe_types].load_glyphs = load_glyphs; 198205b261ecSmrg fpe_functions[num_fpe_types].start_list_fonts_and_aliases = 198305b261ecSmrg start_list_alias_func; 198405b261ecSmrg fpe_functions[num_fpe_types].list_next_font_or_alias = 198505b261ecSmrg next_list_alias_func; 198605b261ecSmrg fpe_functions[num_fpe_types].set_path_hook = set_path_func; 198705b261ecSmrg 198805b261ecSmrg return num_fpe_types++; 198905b261ecSmrg} 199005b261ecSmrg 199105b261ecSmrgvoid 199205b261ecSmrgFreeFonts(void) 199305b261ecSmrg{ 199405b261ecSmrg if (patternCache) { 199505b261ecSmrg FreeFontPatternCache(patternCache); 199605b261ecSmrg patternCache = 0; 199705b261ecSmrg } 199805b261ecSmrg FreeFontPath(font_path_elements, num_fpes, TRUE); 199905b261ecSmrg font_path_elements = 0; 200005b261ecSmrg num_fpes = 0; 20016747b715Smrg free(fpe_functions); 200205b261ecSmrg num_fpe_types = 0; 200305b261ecSmrg fpe_functions = (FPEFunctions *) 0; 200405b261ecSmrg} 200505b261ecSmrg 200605b261ecSmrg/* convenience functions for FS interface */ 200705b261ecSmrg 200805b261ecSmrgFontPtr 200905b261ecSmrgfind_old_font(XID id) 201005b261ecSmrg{ 20116747b715Smrg pointer pFont; 20126747b715Smrg dixLookupResourceByType(&pFont, id, RT_NONE, serverClient, DixReadAccess); 20136747b715Smrg return (FontPtr)pFont; 201405b261ecSmrg} 201505b261ecSmrg 201605b261ecSmrgFont 20176747b715SmrgGetNewFontClientID(void) 201805b261ecSmrg{ 201905b261ecSmrg return FakeClientID(0); 202005b261ecSmrg} 202105b261ecSmrg 202205b261ecSmrgint 202305b261ecSmrgStoreFontClientFont(FontPtr pfont, Font id) 202405b261ecSmrg{ 202505b261ecSmrg return AddResource(id, RT_NONE, (pointer) pfont); 202605b261ecSmrg} 202705b261ecSmrg 202805b261ecSmrgvoid 202905b261ecSmrgDeleteFontClientID(Font id) 203005b261ecSmrg{ 203105b261ecSmrg FreeResource(id, RT_NONE); 203205b261ecSmrg} 203305b261ecSmrg 203405b261ecSmrgint 203505b261ecSmrgclient_auth_generation(ClientPtr client) 203605b261ecSmrg{ 203705b261ecSmrg return 0; 203805b261ecSmrg} 203905b261ecSmrg 204005b261ecSmrgstatic int fs_handlers_installed = 0; 204105b261ecSmrgstatic unsigned int last_server_gen; 204205b261ecSmrg 204305b261ecSmrgint 204405b261ecSmrginit_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler) 204505b261ecSmrg{ 204605b261ecSmrg /* if server has reset, make sure the b&w handlers are reinstalled */ 204705b261ecSmrg if (last_server_gen < serverGeneration) { 204805b261ecSmrg last_server_gen = serverGeneration; 204905b261ecSmrg fs_handlers_installed = 0; 205005b261ecSmrg } 205105b261ecSmrg if (fs_handlers_installed == 0) { 205205b261ecSmrg if (!RegisterBlockAndWakeupHandlers(block_handler, 205305b261ecSmrg FontWakeup, (pointer) 0)) 205405b261ecSmrg return AllocError; 205505b261ecSmrg fs_handlers_installed++; 205605b261ecSmrg } 205705b261ecSmrg QueueFontWakeup(fpe); 205805b261ecSmrg return Successful; 205905b261ecSmrg} 206005b261ecSmrg 206105b261ecSmrgvoid 206205b261ecSmrgremove_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler, Bool all) 206305b261ecSmrg{ 206405b261ecSmrg if (all) { 206505b261ecSmrg /* remove the handlers if no one else is using them */ 206605b261ecSmrg if (--fs_handlers_installed == 0) { 206705b261ecSmrg RemoveBlockAndWakeupHandlers(block_handler, FontWakeup, 206805b261ecSmrg (pointer) 0); 206905b261ecSmrg } 207005b261ecSmrg } 207105b261ecSmrg RemoveFontWakeup(fpe); 207205b261ecSmrg} 2073