dixfonts.c revision 2717a907
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 1306475c125cSmrg len = new_closure->endReq - new_closure->pElt; 1307475c125cSmrg new_closure->data = malloc(len); 1308475c125cSmrg if (!new_closure->data) 130905b261ecSmrg { 1310475c125cSmrg free(new_closure); 131105b261ecSmrg err = BadAlloc; 131205b261ecSmrg goto bail; 131305b261ecSmrg } 1314475c125cSmrg memmove(new_closure->data, new_closure->pElt, len); 1315475c125cSmrg new_closure->pElt = new_closure->data; 1316475c125cSmrg new_closure->endReq = new_closure->pElt + len; 131705b261ecSmrg 131805b261ecSmrg /* Step 2 */ 131905b261ecSmrg 1320475c125cSmrg pGC = GetScratchGC(new_closure->pGC->depth, new_closure->pGC->pScreen); 132105b261ecSmrg if (!pGC) 132205b261ecSmrg { 1323475c125cSmrg free(new_closure->data); 1324475c125cSmrg free(new_closure); 132505b261ecSmrg err = BadAlloc; 132605b261ecSmrg goto bail; 132705b261ecSmrg } 1328475c125cSmrg if ((err = CopyGC(new_closure->pGC, pGC, GCFunction | 132905b261ecSmrg GCPlaneMask | GCForeground | 133005b261ecSmrg GCBackground | GCFillStyle | 133105b261ecSmrg GCTile | GCStipple | 133205b261ecSmrg GCTileStipXOrigin | 133305b261ecSmrg GCTileStipYOrigin | GCFont | 133405b261ecSmrg GCSubwindowMode | GCClipXOrigin | 133505b261ecSmrg GCClipYOrigin | GCClipMask)) != 133605b261ecSmrg Success) 133705b261ecSmrg { 133805b261ecSmrg FreeScratchGC(pGC); 1339475c125cSmrg free(new_closure->data); 1340475c125cSmrg free(new_closure); 134105b261ecSmrg err = BadAlloc; 134205b261ecSmrg goto bail; 134305b261ecSmrg } 1344475c125cSmrg c = new_closure; 134505b261ecSmrg origGC = c->pGC; 134605b261ecSmrg c->pGC = pGC; 134705b261ecSmrg ValidateGC(c->pDraw, c->pGC); 1348475c125cSmrg 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; 14822717a907Sspz ITclosurePtr old_closure; 148305b261ecSmrg 148405b261ecSmrg /* We're putting the client to sleep. We need to 148505b261ecSmrg save some state. Similar problem to that handled 148605b261ecSmrg in doPolyText, but much simpler because the 148705b261ecSmrg request structure is much simpler. */ 148805b261ecSmrg 14896747b715Smrg new_closure = malloc(sizeof(ITclosureRec)); 149005b261ecSmrg if (!new_closure) 149105b261ecSmrg { 149205b261ecSmrg err = BadAlloc; 149305b261ecSmrg goto bail; 149405b261ecSmrg } 14952717a907Sspz old_closure = c; 149605b261ecSmrg *new_closure = *c; 149705b261ecSmrg c = new_closure; 149805b261ecSmrg 14999ace9065Smrg data = malloc(c->nChars * itemSize); 150005b261ecSmrg if (!data) 150105b261ecSmrg { 15026747b715Smrg free(c); 15032717a907Sspz c = old_closure; 150405b261ecSmrg err = BadAlloc; 150505b261ecSmrg goto bail; 150605b261ecSmrg } 15079ace9065Smrg memmove(data, c->data, c->nChars * itemSize); 150805b261ecSmrg c->data = data; 150905b261ecSmrg 151005b261ecSmrg pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); 151105b261ecSmrg if (!pGC) 151205b261ecSmrg { 15136747b715Smrg free(c->data); 15146747b715Smrg free(c); 15152717a907Sspz c = old_closure; 151605b261ecSmrg err = BadAlloc; 151705b261ecSmrg goto bail; 151805b261ecSmrg } 151905b261ecSmrg if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask | 152005b261ecSmrg GCForeground | GCBackground | GCFillStyle | 152105b261ecSmrg GCTile | GCStipple | GCTileStipXOrigin | 152205b261ecSmrg GCTileStipYOrigin | GCFont | 152305b261ecSmrg GCSubwindowMode | GCClipXOrigin | 152405b261ecSmrg GCClipYOrigin | GCClipMask)) != Success) 152505b261ecSmrg { 152605b261ecSmrg FreeScratchGC(pGC); 15276747b715Smrg free(c->data); 15286747b715Smrg free(c); 15292717a907Sspz c = old_closure; 153005b261ecSmrg err = BadAlloc; 153105b261ecSmrg goto bail; 153205b261ecSmrg } 153305b261ecSmrg c->pGC = pGC; 153405b261ecSmrg ValidateGC(c->pDraw, c->pGC); 153505b261ecSmrg 15366747b715Smrg ClientSleep(client, (ClientSleepProcPtr)doImageText, c); 153705b261ecSmrg } 15386747b715Smrg else 15396747b715Smrg goto xinerama_sleep; 154005b261ecSmrg return TRUE; 154105b261ecSmrg } 154205b261ecSmrg else if (lgerr != Successful) 154305b261ecSmrg { 154405b261ecSmrg err = FontToXError(lgerr); 154505b261ecSmrg goto bail; 154605b261ecSmrg } 154705b261ecSmrg if (c->pDraw) 154805b261ecSmrg { 15499ace9065Smrg if (c->reqType == X_ImageText8) 15509ace9065Smrg (* c->pGC->ops->ImageText8)(c->pDraw, c->pGC, c->xorg, c->yorg, 15519ace9065Smrg c->nChars, (char *) c->data); 15529ace9065Smrg else 15539ace9065Smrg (* c->pGC->ops->ImageText16)(c->pDraw, c->pGC, c->xorg, c->yorg, 15549ace9065Smrg c->nChars, (unsigned short *) c->data); 155505b261ecSmrg } 155605b261ecSmrg 155705b261ecSmrgbail: 155805b261ecSmrg 155905b261ecSmrg if (err != Success && c->client != serverClient) { 156005b261ecSmrg SendErrorToClient(c->client, c->reqType, 0, 0, err); 156105b261ecSmrg } 15626747b715Smrg if (ClientIsAsleep(client)) 156305b261ecSmrg { 156405b261ecSmrg ClientWakeup(c->client); 15656747b715Smrgxinerama_sleep: 15666747b715Smrg ChangeGC(NullClient, c->pGC, clearGCmask, clearGC); 156705b261ecSmrg 156805b261ecSmrg /* Unreference the font from the scratch GC */ 156905b261ecSmrg CloseFont(c->pGC->font, (Font)0); 157005b261ecSmrg c->pGC->font = NullFont; 157105b261ecSmrg 157205b261ecSmrg FreeScratchGC(c->pGC); 15736747b715Smrg free(c->data); 15746747b715Smrg free(c); 157505b261ecSmrg } 157605b261ecSmrg return TRUE; 157705b261ecSmrg} 157805b261ecSmrg 157905b261ecSmrgint 158005b261ecSmrgImageText(ClientPtr client, DrawablePtr pDraw, GC *pGC, int nChars, 158105b261ecSmrg unsigned char *data, int xorg, int yorg, int reqType, XID did) 158205b261ecSmrg{ 158305b261ecSmrg ITclosureRec local_closure; 158405b261ecSmrg 158505b261ecSmrg local_closure.client = client; 158605b261ecSmrg local_closure.pDraw = pDraw; 158705b261ecSmrg local_closure.pGC = pGC; 158805b261ecSmrg local_closure.nChars = nChars; 158905b261ecSmrg local_closure.data = data; 159005b261ecSmrg local_closure.xorg = xorg; 159105b261ecSmrg local_closure.yorg = yorg; 15929ace9065Smrg local_closure.reqType = reqType; 159305b261ecSmrg local_closure.did = did; 159405b261ecSmrg 159505b261ecSmrg (void) doImageText(client, &local_closure); 159605b261ecSmrg return Success; 159705b261ecSmrg} 159805b261ecSmrg 159905b261ecSmrg 160005b261ecSmrg/* does the necessary magic to figure out the fpe type */ 160105b261ecSmrgstatic int 160205b261ecSmrgDetermineFPEType(char *pathname) 160305b261ecSmrg{ 160405b261ecSmrg int i; 160505b261ecSmrg 160605b261ecSmrg for (i = 0; i < num_fpe_types; i++) { 160705b261ecSmrg if ((*fpe_functions[i].name_check) (pathname)) 160805b261ecSmrg return i; 160905b261ecSmrg } 161005b261ecSmrg return -1; 161105b261ecSmrg} 161205b261ecSmrg 161305b261ecSmrg 161405b261ecSmrgstatic void 161505b261ecSmrgFreeFontPath(FontPathElementPtr *list, int n, Bool force) 161605b261ecSmrg{ 161705b261ecSmrg int i; 161805b261ecSmrg 161905b261ecSmrg for (i = 0; i < n; i++) { 162005b261ecSmrg if (force) { 162105b261ecSmrg /* Sanity check that all refcounts will be 0 by the time 162205b261ecSmrg we get to the end of the list. */ 162305b261ecSmrg int found = 1; /* the first reference is us */ 162405b261ecSmrg int j; 162505b261ecSmrg for (j = i+1; j < n; j++) { 162605b261ecSmrg if (list[j] == list[i]) 162705b261ecSmrg found++; 162805b261ecSmrg } 162905b261ecSmrg if (list[i]->refcount != found) { 163005b261ecSmrg list[i]->refcount = found; /* ensure it will get freed */ 163105b261ecSmrg } 163205b261ecSmrg } 163305b261ecSmrg FreeFPE(list[i]); 163405b261ecSmrg } 16356747b715Smrg free(list); 163605b261ecSmrg} 163705b261ecSmrg 163805b261ecSmrgstatic FontPathElementPtr 163905b261ecSmrgfind_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len) 164005b261ecSmrg{ 164105b261ecSmrg FontPathElementPtr fpe; 164205b261ecSmrg int i; 164305b261ecSmrg 164405b261ecSmrg for (i = 0; i < num; i++) { 164505b261ecSmrg fpe = list[i]; 164605b261ecSmrg if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0) 164705b261ecSmrg return fpe; 164805b261ecSmrg } 164905b261ecSmrg return (FontPathElementPtr) 0; 165005b261ecSmrg} 165105b261ecSmrg 165205b261ecSmrg 165305b261ecSmrgstatic int 165405b261ecSmrgSetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist) 165505b261ecSmrg{ 165605b261ecSmrg int i, err = 0; 165705b261ecSmrg int valid_paths = 0; 165805b261ecSmrg unsigned int len; 165905b261ecSmrg unsigned char *cp = paths; 166005b261ecSmrg FontPathElementPtr fpe = NULL, *fplist; 166105b261ecSmrg 16626747b715Smrg fplist = malloc(sizeof(FontPathElementPtr) * npaths); 166305b261ecSmrg if (!fplist) { 166405b261ecSmrg *bad = 0; 166505b261ecSmrg return BadAlloc; 166605b261ecSmrg } 166705b261ecSmrg for (i = 0; i < num_fpe_types; i++) { 166805b261ecSmrg if (fpe_functions[i].set_path_hook) 166905b261ecSmrg (*fpe_functions[i].set_path_hook) (); 167005b261ecSmrg } 167105b261ecSmrg for (i = 0; i < npaths; i++) 167205b261ecSmrg { 167305b261ecSmrg len = (unsigned int) (*cp++); 167405b261ecSmrg 167505b261ecSmrg if (len == 0) 167605b261ecSmrg { 167705b261ecSmrg if (persist) 16784642e01fSmrg ErrorF("[dix] Removing empty element from the valid list of fontpaths\n"); 167905b261ecSmrg err = BadValue; 168005b261ecSmrg } 168105b261ecSmrg else 168205b261ecSmrg { 168305b261ecSmrg /* if it's already in our active list, just reset it */ 168405b261ecSmrg /* 168505b261ecSmrg * note that this can miss FPE's in limbo -- may be worth catching 168605b261ecSmrg * them, though it'd muck up refcounting 168705b261ecSmrg */ 168805b261ecSmrg fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len); 168905b261ecSmrg if (fpe) 169005b261ecSmrg { 169105b261ecSmrg err = (*fpe_functions[fpe->type].reset_fpe) (fpe); 169205b261ecSmrg if (err == Successful) 169305b261ecSmrg { 169405b261ecSmrg UseFPE(fpe);/* since it'll be decref'd later when freed 169505b261ecSmrg * from the old list */ 169605b261ecSmrg } 169705b261ecSmrg else 169805b261ecSmrg fpe = 0; 169905b261ecSmrg } 170005b261ecSmrg /* if error or can't do it, act like it's a new one */ 170105b261ecSmrg if (!fpe) 170205b261ecSmrg { 17036747b715Smrg fpe = malloc(sizeof(FontPathElementRec)); 170405b261ecSmrg if (!fpe) 170505b261ecSmrg { 170605b261ecSmrg err = BadAlloc; 170705b261ecSmrg goto bail; 170805b261ecSmrg } 17096747b715Smrg fpe->name = malloc(len + 1); 171005b261ecSmrg if (!fpe->name) 171105b261ecSmrg { 17126747b715Smrg free(fpe); 171305b261ecSmrg err = BadAlloc; 171405b261ecSmrg goto bail; 171505b261ecSmrg } 171605b261ecSmrg fpe->refcount = 1; 171705b261ecSmrg 171805b261ecSmrg strncpy(fpe->name, (char *) cp, (int) len); 171905b261ecSmrg fpe->name[len] = '\0'; 172005b261ecSmrg fpe->name_length = len; 172105b261ecSmrg fpe->type = DetermineFPEType(fpe->name); 172205b261ecSmrg if (fpe->type == -1) 172305b261ecSmrg err = BadValue; 172405b261ecSmrg else 172505b261ecSmrg err = (*fpe_functions[fpe->type].init_fpe) (fpe); 172605b261ecSmrg if (err != Successful) 172705b261ecSmrg { 172805b261ecSmrg if (persist) 172905b261ecSmrg { 17304642e01fSmrg ErrorF("[dix] Could not init font path element %s, removing from list!\n", 173105b261ecSmrg fpe->name); 173205b261ecSmrg } 17336747b715Smrg free(fpe->name); 17346747b715Smrg free(fpe); 173505b261ecSmrg } 173605b261ecSmrg } 173705b261ecSmrg } 173805b261ecSmrg if (err != Successful) 173905b261ecSmrg { 174005b261ecSmrg if (!persist) 174105b261ecSmrg goto bail; 174205b261ecSmrg } 174305b261ecSmrg else 174405b261ecSmrg { 174505b261ecSmrg fplist[valid_paths++] = fpe; 174605b261ecSmrg } 174705b261ecSmrg cp += len; 174805b261ecSmrg } 174905b261ecSmrg 175005b261ecSmrg FreeFontPath(font_path_elements, num_fpes, FALSE); 175105b261ecSmrg font_path_elements = fplist; 175205b261ecSmrg if (patternCache) 175305b261ecSmrg EmptyFontPatternCache(patternCache); 175405b261ecSmrg num_fpes = valid_paths; 175505b261ecSmrg 175605b261ecSmrg return Success; 175705b261ecSmrgbail: 175805b261ecSmrg *bad = i; 175905b261ecSmrg while (--valid_paths >= 0) 176005b261ecSmrg FreeFPE(fplist[valid_paths]); 17616747b715Smrg free(fplist); 176205b261ecSmrg return FontToXError(err); 176305b261ecSmrg} 176405b261ecSmrg 176505b261ecSmrgint 17666747b715SmrgSetFontPath(ClientPtr client, int npaths, unsigned char *paths) 176705b261ecSmrg{ 17684642e01fSmrg int err = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess); 17694642e01fSmrg if (err != Success) 17704642e01fSmrg return err; 177105b261ecSmrg 177205b261ecSmrg if (npaths == 0) { 177305b261ecSmrg if (SetDefaultFontPath(defaultFontPath) != Success) 177405b261ecSmrg return BadValue; 177505b261ecSmrg } else { 17766747b715Smrg int bad; 17776747b715Smrg err = SetFontPathElements(npaths, paths, &bad, FALSE); 17786747b715Smrg client->errorValue = bad; 177905b261ecSmrg } 178005b261ecSmrg return err; 178105b261ecSmrg} 178205b261ecSmrg 178305b261ecSmrgint 178405b261ecSmrgSetDefaultFontPath(char *path) 178505b261ecSmrg{ 1786b1d344b3Smrg char *temp_path, 1787b1d344b3Smrg *start, 1788b1d344b3Smrg *end; 178905b261ecSmrg unsigned char *cp, 179005b261ecSmrg *pp, 179105b261ecSmrg *nump, 179205b261ecSmrg *newpath; 179305b261ecSmrg int num = 1, 179405b261ecSmrg len, 179505b261ecSmrg err, 179605b261ecSmrg size = 0, 179705b261ecSmrg bad; 179805b261ecSmrg 1799b1d344b3Smrg /* ensure temp_path contains "built-ins" */ 1800b1d344b3Smrg start = path; 1801b1d344b3Smrg while (1) { 1802b1d344b3Smrg start = strstr(start, "built-ins"); 1803b1d344b3Smrg if (start == NULL) 1804b1d344b3Smrg break; 1805b1d344b3Smrg end = start + strlen("built-ins"); 1806b1d344b3Smrg if ((start == path || start[-1] == ',') && (!*end || *end == ',')) 1807b1d344b3Smrg break; 1808b1d344b3Smrg start = end; 1809b1d344b3Smrg } 1810b1d344b3Smrg if (!start) { 18119ace9065Smrg if (asprintf(&temp_path, "%s%sbuilt-ins", path, *path ? "," : "") 18129ace9065Smrg == -1) 18139ace9065Smrg temp_path = NULL; 1814b1d344b3Smrg } else { 18156747b715Smrg temp_path = strdup(path); 1816b1d344b3Smrg } 1817b1d344b3Smrg if (!temp_path) 1818b1d344b3Smrg return BadAlloc; 1819b1d344b3Smrg 182005b261ecSmrg /* get enough for string, plus values -- use up commas */ 1821b1d344b3Smrg len = strlen(temp_path) + 1; 18226747b715Smrg nump = cp = newpath = malloc(len); 18239ace9065Smrg if (!newpath) { 18249ace9065Smrg free(temp_path); 182505b261ecSmrg return BadAlloc; 18269ace9065Smrg } 1827b1d344b3Smrg pp = (unsigned char *) temp_path; 182805b261ecSmrg cp++; 182905b261ecSmrg while (*pp) { 183005b261ecSmrg if (*pp == ',') { 183105b261ecSmrg *nump = (unsigned char) size; 183205b261ecSmrg nump = cp++; 183305b261ecSmrg pp++; 183405b261ecSmrg num++; 183505b261ecSmrg size = 0; 183605b261ecSmrg } else { 183705b261ecSmrg *cp++ = *pp++; 183805b261ecSmrg size++; 183905b261ecSmrg } 184005b261ecSmrg } 184105b261ecSmrg *nump = (unsigned char) size; 184205b261ecSmrg 184305b261ecSmrg err = SetFontPathElements(num, newpath, &bad, TRUE); 184405b261ecSmrg 18456747b715Smrg free(newpath); 18466747b715Smrg free(temp_path); 184705b261ecSmrg 184805b261ecSmrg return err; 184905b261ecSmrg} 185005b261ecSmrg 18514642e01fSmrgint 18524642e01fSmrgGetFontPath(ClientPtr client, int *count, int *length, unsigned char **result) 185305b261ecSmrg{ 185405b261ecSmrg int i; 185505b261ecSmrg unsigned char *c; 185605b261ecSmrg int len; 185705b261ecSmrg FontPathElementPtr fpe; 185805b261ecSmrg 18594642e01fSmrg i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess); 18604642e01fSmrg if (i != Success) 18614642e01fSmrg return i; 18624642e01fSmrg 186305b261ecSmrg len = 0; 186405b261ecSmrg for (i = 0; i < num_fpes; i++) { 186505b261ecSmrg fpe = font_path_elements[i]; 186605b261ecSmrg len += fpe->name_length + 1; 186705b261ecSmrg } 18686747b715Smrg font_path_string = (unsigned char *) realloc(font_path_string, len); 186905b261ecSmrg if (!font_path_string) 18704642e01fSmrg return BadAlloc; 187105b261ecSmrg 187205b261ecSmrg c = font_path_string; 187305b261ecSmrg *length = 0; 187405b261ecSmrg for (i = 0; i < num_fpes; i++) { 187505b261ecSmrg fpe = font_path_elements[i]; 187605b261ecSmrg *c = fpe->name_length; 187705b261ecSmrg *length += *c++; 187805b261ecSmrg memmove(c, fpe->name, fpe->name_length); 187905b261ecSmrg c += fpe->name_length; 188005b261ecSmrg } 188105b261ecSmrg *count = num_fpes; 18824642e01fSmrg *result = font_path_string; 18834642e01fSmrg return Success; 188405b261ecSmrg} 188505b261ecSmrg 188605b261ecSmrgvoid 188705b261ecSmrgDeleteClientFontStuff(ClientPtr client) 188805b261ecSmrg{ 188905b261ecSmrg int i; 189005b261ecSmrg FontPathElementPtr fpe; 189105b261ecSmrg 189205b261ecSmrg for (i = 0; i < num_fpes; i++) 189305b261ecSmrg { 189405b261ecSmrg fpe = font_path_elements[i]; 189505b261ecSmrg if (fpe_functions[fpe->type].client_died) 189605b261ecSmrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 189705b261ecSmrg } 189805b261ecSmrg} 189905b261ecSmrg 190005b261ecSmrgvoid 190105b261ecSmrgInitFonts (void) 190205b261ecSmrg{ 190305b261ecSmrg patternCache = MakeFontPatternCache(); 190405b261ecSmrg 19056747b715Smrg register_fpe_functions(); 190605b261ecSmrg} 190705b261ecSmrg 190805b261ecSmrgint 19096747b715SmrgGetDefaultPointSize (void) 191005b261ecSmrg{ 191105b261ecSmrg return 120; 191205b261ecSmrg} 191305b261ecSmrg 191405b261ecSmrg 191505b261ecSmrgFontResolutionPtr 191605b261ecSmrgGetClientResolutions (int *num) 191705b261ecSmrg{ 19184642e01fSmrg static struct _FontResolution res; 19194642e01fSmrg ScreenPtr pScreen; 192005b261ecSmrg 19214642e01fSmrg pScreen = screenInfo.screens[0]; 19224642e01fSmrg res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth; 19234642e01fSmrg /* 19244642e01fSmrg * XXX - we'll want this as long as bitmap instances are prevalent 19254642e01fSmrg so that we can match them from scalable fonts 19264642e01fSmrg */ 19274642e01fSmrg if (res.x_resolution < 88) 19284642e01fSmrg res.x_resolution = 75; 19294642e01fSmrg else 19304642e01fSmrg res.x_resolution = 100; 19314642e01fSmrg res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight; 19324642e01fSmrg if (res.y_resolution < 88) 19334642e01fSmrg res.y_resolution = 75; 19344642e01fSmrg else 19354642e01fSmrg res.y_resolution = 100; 19364642e01fSmrg res.point_size = 120; 19374642e01fSmrg *num = 1; 19384642e01fSmrg return &res; 193905b261ecSmrg} 194005b261ecSmrg 194105b261ecSmrg/* 194205b261ecSmrg * returns the type index of the new fpe 194305b261ecSmrg * 194405b261ecSmrg * should be called (only once!) by each type of fpe when initialized 194505b261ecSmrg */ 194605b261ecSmrg 194705b261ecSmrgint 194805b261ecSmrgRegisterFPEFunctions(NameCheckFunc name_func, 194905b261ecSmrg InitFpeFunc init_func, 195005b261ecSmrg FreeFpeFunc free_func, 195105b261ecSmrg ResetFpeFunc reset_func, 195205b261ecSmrg OpenFontFunc open_func, 195305b261ecSmrg CloseFontFunc close_func, 195405b261ecSmrg ListFontsFunc list_func, 195505b261ecSmrg StartLfwiFunc start_lfwi_func, 195605b261ecSmrg NextLfwiFunc next_lfwi_func, 195705b261ecSmrg WakeupFpeFunc wakeup_func, 195805b261ecSmrg ClientDiedFunc client_died, 195905b261ecSmrg LoadGlyphsFunc load_glyphs, 196005b261ecSmrg StartLaFunc start_list_alias_func, 196105b261ecSmrg NextLaFunc next_list_alias_func, 196205b261ecSmrg SetPathFunc set_path_func) 196305b261ecSmrg{ 196405b261ecSmrg FPEFunctions *new; 196505b261ecSmrg 196605b261ecSmrg /* grow the list */ 19676747b715Smrg new = (FPEFunctions *) realloc(fpe_functions, 196805b261ecSmrg (num_fpe_types + 1) * sizeof(FPEFunctions)); 196905b261ecSmrg if (!new) 197005b261ecSmrg return -1; 197105b261ecSmrg fpe_functions = new; 197205b261ecSmrg 197305b261ecSmrg fpe_functions[num_fpe_types].name_check = name_func; 197405b261ecSmrg fpe_functions[num_fpe_types].open_font = open_func; 197505b261ecSmrg fpe_functions[num_fpe_types].close_font = close_func; 197605b261ecSmrg fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func; 197705b261ecSmrg fpe_functions[num_fpe_types].list_fonts = list_func; 197805b261ecSmrg fpe_functions[num_fpe_types].start_list_fonts_with_info = 197905b261ecSmrg start_lfwi_func; 198005b261ecSmrg fpe_functions[num_fpe_types].list_next_font_with_info = 198105b261ecSmrg next_lfwi_func; 198205b261ecSmrg fpe_functions[num_fpe_types].init_fpe = init_func; 198305b261ecSmrg fpe_functions[num_fpe_types].free_fpe = free_func; 198405b261ecSmrg fpe_functions[num_fpe_types].reset_fpe = reset_func; 198505b261ecSmrg fpe_functions[num_fpe_types].client_died = client_died; 198605b261ecSmrg fpe_functions[num_fpe_types].load_glyphs = load_glyphs; 198705b261ecSmrg fpe_functions[num_fpe_types].start_list_fonts_and_aliases = 198805b261ecSmrg start_list_alias_func; 198905b261ecSmrg fpe_functions[num_fpe_types].list_next_font_or_alias = 199005b261ecSmrg next_list_alias_func; 199105b261ecSmrg fpe_functions[num_fpe_types].set_path_hook = set_path_func; 199205b261ecSmrg 199305b261ecSmrg return num_fpe_types++; 199405b261ecSmrg} 199505b261ecSmrg 199605b261ecSmrgvoid 199705b261ecSmrgFreeFonts(void) 199805b261ecSmrg{ 199905b261ecSmrg if (patternCache) { 200005b261ecSmrg FreeFontPatternCache(patternCache); 200105b261ecSmrg patternCache = 0; 200205b261ecSmrg } 200305b261ecSmrg FreeFontPath(font_path_elements, num_fpes, TRUE); 200405b261ecSmrg font_path_elements = 0; 200505b261ecSmrg num_fpes = 0; 20066747b715Smrg free(fpe_functions); 200705b261ecSmrg num_fpe_types = 0; 200805b261ecSmrg fpe_functions = (FPEFunctions *) 0; 200905b261ecSmrg} 201005b261ecSmrg 201105b261ecSmrg/* convenience functions for FS interface */ 201205b261ecSmrg 201305b261ecSmrgFontPtr 201405b261ecSmrgfind_old_font(XID id) 201505b261ecSmrg{ 20166747b715Smrg pointer pFont; 20176747b715Smrg dixLookupResourceByType(&pFont, id, RT_NONE, serverClient, DixReadAccess); 20186747b715Smrg return (FontPtr)pFont; 201905b261ecSmrg} 202005b261ecSmrg 202105b261ecSmrgFont 20226747b715SmrgGetNewFontClientID(void) 202305b261ecSmrg{ 202405b261ecSmrg return FakeClientID(0); 202505b261ecSmrg} 202605b261ecSmrg 202705b261ecSmrgint 202805b261ecSmrgStoreFontClientFont(FontPtr pfont, Font id) 202905b261ecSmrg{ 203005b261ecSmrg return AddResource(id, RT_NONE, (pointer) pfont); 203105b261ecSmrg} 203205b261ecSmrg 203305b261ecSmrgvoid 203405b261ecSmrgDeleteFontClientID(Font id) 203505b261ecSmrg{ 203605b261ecSmrg FreeResource(id, RT_NONE); 203705b261ecSmrg} 203805b261ecSmrg 203905b261ecSmrgint 204005b261ecSmrgclient_auth_generation(ClientPtr client) 204105b261ecSmrg{ 204205b261ecSmrg return 0; 204305b261ecSmrg} 204405b261ecSmrg 204505b261ecSmrgstatic int fs_handlers_installed = 0; 204605b261ecSmrgstatic unsigned int last_server_gen; 204705b261ecSmrg 204805b261ecSmrgint 204905b261ecSmrginit_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler) 205005b261ecSmrg{ 205105b261ecSmrg /* if server has reset, make sure the b&w handlers are reinstalled */ 205205b261ecSmrg if (last_server_gen < serverGeneration) { 205305b261ecSmrg last_server_gen = serverGeneration; 205405b261ecSmrg fs_handlers_installed = 0; 205505b261ecSmrg } 205605b261ecSmrg if (fs_handlers_installed == 0) { 205705b261ecSmrg if (!RegisterBlockAndWakeupHandlers(block_handler, 205805b261ecSmrg FontWakeup, (pointer) 0)) 205905b261ecSmrg return AllocError; 206005b261ecSmrg fs_handlers_installed++; 206105b261ecSmrg } 206205b261ecSmrg QueueFontWakeup(fpe); 206305b261ecSmrg return Successful; 206405b261ecSmrg} 206505b261ecSmrg 206605b261ecSmrgvoid 206705b261ecSmrgremove_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler, Bool all) 206805b261ecSmrg{ 206905b261ecSmrg if (all) { 207005b261ecSmrg /* remove the handlers if no one else is using them */ 207105b261ecSmrg if (--fs_handlers_installed == 0) { 207205b261ecSmrg RemoveBlockAndWakeupHandlers(block_handler, FontWakeup, 207305b261ecSmrg (pointer) 0); 207405b261ecSmrg } 207505b261ecSmrg } 207605b261ecSmrg RemoveFontWakeup(fpe); 207705b261ecSmrg} 2078