1706f2543Smrg/************************************************************************ 2706f2543SmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 3706f2543Smrg 4706f2543Smrg All Rights Reserved 5706f2543Smrg 6706f2543SmrgPermission to use, copy, modify, and distribute this software and its 7706f2543Smrgdocumentation for any purpose and without fee is hereby granted, 8706f2543Smrgprovided that the above copyright notice appear in all copies and that 9706f2543Smrgboth that copyright notice and this permission notice appear in 10706f2543Smrgsupporting documentation, and that the name of Digital not be 11706f2543Smrgused in advertising or publicity pertaining to distribution of the 12706f2543Smrgsoftware without specific, written prior permission. 13706f2543Smrg 14706f2543SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 15706f2543SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 16706f2543SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 17706f2543SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 18706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 19706f2543SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 20706f2543SmrgSOFTWARE. 21706f2543Smrg 22706f2543Smrg************************************************************************/ 23706f2543Smrg/* The panoramix components contained the following notice */ 24706f2543Smrg/* 25706f2543SmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. 26706f2543Smrg 27706f2543SmrgPermission is hereby granted, free of charge, to any person obtaining a copy 28706f2543Smrgof this software and associated documentation files (the "Software"), to deal 29706f2543Smrgin the Software without restriction, including without limitation the rights 30706f2543Smrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell 31706f2543Smrgcopies of the Software. 32706f2543Smrg 33706f2543SmrgThe above copyright notice and this permission notice shall be included in 34706f2543Smrgall copies or substantial portions of the Software. 35706f2543Smrg 36706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 37706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 38706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 39706f2543SmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, 40706f2543SmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, 41706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 42706f2543SmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 43706f2543Smrg 44706f2543SmrgExcept as contained in this notice, the name of Digital Equipment Corporation 45706f2543Smrgshall not be used in advertising or otherwise to promote the sale, use or other 46706f2543Smrgdealings in this Software without prior written authorization from Digital 47706f2543SmrgEquipment Corporation. 48706f2543Smrg 49706f2543Smrg******************************************************************/ 50706f2543Smrg 51706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 52706f2543Smrg#include <dix-config.h> 53706f2543Smrg#endif 54706f2543Smrg 55706f2543Smrg#include <X11/X.h> 56706f2543Smrg#include <X11/Xmd.h> 57706f2543Smrg#include <X11/Xproto.h> 58706f2543Smrg#include "scrnintstr.h" 59706f2543Smrg#include "resource.h" 60706f2543Smrg#include "dixstruct.h" 61706f2543Smrg#include "cursorstr.h" 62706f2543Smrg#include "misc.h" 63706f2543Smrg#include "opaque.h" 64706f2543Smrg#include "dixfontstr.h" 65706f2543Smrg#include "closestr.h" 66706f2543Smrg#include "dixfont.h" 67706f2543Smrg#include "xace.h" 68706f2543Smrg 69706f2543Smrg#ifdef XF86BIGFONT 70706f2543Smrg#include "xf86bigfontsrv.h" 71706f2543Smrg#endif 72706f2543Smrg 73706f2543Smrgextern pointer fosNaturalParams; 74706f2543Smrgextern FontPtr defaultFont; 75706f2543Smrg 76706f2543Smrgstatic FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0; 77706f2543Smrgstatic int num_fpes = 0; 78706f2543Smrgstatic FPEFunctions *fpe_functions = (FPEFunctions *) 0; 79706f2543Smrgstatic int num_fpe_types = 0; 80706f2543Smrg 81706f2543Smrgstatic unsigned char *font_path_string; 82706f2543Smrg 83706f2543Smrgstatic int num_slept_fpes = 0; 84706f2543Smrgstatic int size_slept_fpes = 0; 85706f2543Smrgstatic FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0; 86706f2543Smrgstatic FontPatternCachePtr patternCache; 87706f2543Smrg 88706f2543Smrgstatic int 89706f2543SmrgFontToXError(int err) 90706f2543Smrg{ 91706f2543Smrg switch (err) { 92706f2543Smrg case Successful: 93706f2543Smrg return Success; 94706f2543Smrg case AllocError: 95706f2543Smrg return BadAlloc; 96706f2543Smrg case BadFontName: 97706f2543Smrg return BadName; 98706f2543Smrg case BadFontPath: 99706f2543Smrg case BadFontFormat: /* is there something better? */ 100706f2543Smrg case BadCharRange: 101706f2543Smrg return BadValue; 102706f2543Smrg default: 103706f2543Smrg return err; 104706f2543Smrg } 105706f2543Smrg} 106706f2543Smrg 107706f2543Smrgstatic int 108706f2543SmrgLoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size, 109706f2543Smrg unsigned char *data) 110706f2543Smrg{ 111706f2543Smrg if (fpe_functions[pfont->fpe->type].load_glyphs) 112706f2543Smrg return (*fpe_functions[pfont->fpe->type].load_glyphs) 113706f2543Smrg (client, pfont, 0, nchars, item_size, data); 114706f2543Smrg else 115706f2543Smrg return Successful; 116706f2543Smrg} 117706f2543Smrg 118706f2543Smrg/* 119706f2543Smrg * adding RT_FONT prevents conflict with default cursor font 120706f2543Smrg */ 121706f2543SmrgBool 122706f2543SmrgSetDefaultFont(char *defaultfontname) 123706f2543Smrg{ 124706f2543Smrg int err; 125706f2543Smrg FontPtr pf; 126706f2543Smrg XID fid; 127706f2543Smrg 128706f2543Smrg fid = FakeClientID(0); 129706f2543Smrg err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync, 130706f2543Smrg (unsigned) strlen(defaultfontname), defaultfontname); 131706f2543Smrg if (err != Success) 132706f2543Smrg return FALSE; 133706f2543Smrg err = dixLookupResourceByType((pointer *)&pf, fid, RT_FONT, serverClient, 134706f2543Smrg DixReadAccess); 135706f2543Smrg if (err != Success) 136706f2543Smrg return FALSE; 137706f2543Smrg defaultFont = pf; 138706f2543Smrg return TRUE; 139706f2543Smrg} 140706f2543Smrg 141706f2543Smrg/* 142706f2543Smrg * note that the font wakeup queue is not refcounted. this is because 143706f2543Smrg * an fpe needs to be added when it's inited, and removed when it's finally 144706f2543Smrg * freed, in order to handle any data that isn't requested, like FS events. 145706f2543Smrg * 146706f2543Smrg * since the only thing that should call these routines is the renderer's 147706f2543Smrg * init_fpe() and free_fpe(), there shouldn't be any problem in using 148706f2543Smrg * freed data. 149706f2543Smrg */ 150706f2543Smrgvoid 151706f2543SmrgQueueFontWakeup(FontPathElementPtr fpe) 152706f2543Smrg{ 153706f2543Smrg int i; 154706f2543Smrg FontPathElementPtr *new; 155706f2543Smrg 156706f2543Smrg for (i = 0; i < num_slept_fpes; i++) { 157706f2543Smrg if (slept_fpes[i] == fpe) { 158706f2543Smrg return; 159706f2543Smrg } 160706f2543Smrg } 161706f2543Smrg if (num_slept_fpes == size_slept_fpes) { 162706f2543Smrg new = (FontPathElementPtr *) 163706f2543Smrg realloc(slept_fpes, 164706f2543Smrg sizeof(FontPathElementPtr) * (size_slept_fpes + 4)); 165706f2543Smrg if (!new) 166706f2543Smrg return; 167706f2543Smrg slept_fpes = new; 168706f2543Smrg size_slept_fpes += 4; 169706f2543Smrg } 170706f2543Smrg slept_fpes[num_slept_fpes] = fpe; 171706f2543Smrg num_slept_fpes++; 172706f2543Smrg} 173706f2543Smrg 174706f2543Smrgvoid 175706f2543SmrgRemoveFontWakeup(FontPathElementPtr fpe) 176706f2543Smrg{ 177706f2543Smrg int i, 178706f2543Smrg j; 179706f2543Smrg 180706f2543Smrg for (i = 0; i < num_slept_fpes; i++) { 181706f2543Smrg if (slept_fpes[i] == fpe) { 182706f2543Smrg for (j = i; j < num_slept_fpes; j++) { 183706f2543Smrg slept_fpes[j] = slept_fpes[j + 1]; 184706f2543Smrg } 185706f2543Smrg num_slept_fpes--; 186706f2543Smrg return; 187706f2543Smrg } 188706f2543Smrg } 189706f2543Smrg} 190706f2543Smrg 191706f2543Smrgvoid 192706f2543SmrgFontWakeup(pointer data, int count, pointer LastSelectMask) 193706f2543Smrg{ 194706f2543Smrg int i; 195706f2543Smrg FontPathElementPtr fpe; 196706f2543Smrg 197706f2543Smrg if (count < 0) 198706f2543Smrg return; 199706f2543Smrg /* wake up any fpe's that may be waiting for information */ 200706f2543Smrg for (i = 0; i < num_slept_fpes; i++) { 201706f2543Smrg fpe = slept_fpes[i]; 202706f2543Smrg (void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask); 203706f2543Smrg } 204706f2543Smrg} 205706f2543Smrg 206706f2543Smrg/* XXX -- these two funcs may want to be broken into macros */ 207706f2543Smrgstatic void 208706f2543SmrgUseFPE(FontPathElementPtr fpe) 209706f2543Smrg{ 210706f2543Smrg fpe->refcount++; 211706f2543Smrg} 212706f2543Smrg 213706f2543Smrgstatic void 214706f2543SmrgFreeFPE (FontPathElementPtr fpe) 215706f2543Smrg{ 216706f2543Smrg fpe->refcount--; 217706f2543Smrg if (fpe->refcount == 0) { 218706f2543Smrg (*fpe_functions[fpe->type].free_fpe) (fpe); 219706f2543Smrg free(fpe->name); 220706f2543Smrg free(fpe); 221706f2543Smrg } 222706f2543Smrg} 223706f2543Smrg 224706f2543Smrgstatic Bool 225706f2543SmrgdoOpenFont(ClientPtr client, OFclosurePtr c) 226706f2543Smrg{ 227706f2543Smrg FontPtr pfont = NullFont; 228706f2543Smrg FontPathElementPtr fpe = NULL; 229706f2543Smrg ScreenPtr pScr; 230706f2543Smrg int err = Successful; 231706f2543Smrg int i; 232706f2543Smrg char *alias, 233706f2543Smrg *newname; 234706f2543Smrg int newlen; 235706f2543Smrg int aliascount = 20; 236706f2543Smrg /* 237706f2543Smrg * Decide at runtime what FontFormat to use. 238706f2543Smrg */ 239706f2543Smrg Mask FontFormat = 240706f2543Smrg 241706f2543Smrg ((screenInfo.imageByteOrder == LSBFirst) ? 242706f2543Smrg BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) | 243706f2543Smrg 244706f2543Smrg ((screenInfo.bitmapBitOrder == LSBFirst) ? 245706f2543Smrg BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) | 246706f2543Smrg 247706f2543Smrg BitmapFormatImageRectMin | 248706f2543Smrg 249706f2543Smrg#if GLYPHPADBYTES == 1 250706f2543Smrg BitmapFormatScanlinePad8 | 251706f2543Smrg#endif 252706f2543Smrg 253706f2543Smrg#if GLYPHPADBYTES == 2 254706f2543Smrg BitmapFormatScanlinePad16 | 255706f2543Smrg#endif 256706f2543Smrg 257706f2543Smrg#if GLYPHPADBYTES == 4 258706f2543Smrg BitmapFormatScanlinePad32 | 259706f2543Smrg#endif 260706f2543Smrg 261706f2543Smrg#if GLYPHPADBYTES == 8 262706f2543Smrg BitmapFormatScanlinePad64 | 263706f2543Smrg#endif 264706f2543Smrg 265706f2543Smrg BitmapFormatScanlineUnit8; 266706f2543Smrg 267706f2543Smrg if (client->clientGone) 268706f2543Smrg { 269706f2543Smrg if (c->current_fpe < c->num_fpes) 270706f2543Smrg { 271706f2543Smrg fpe = c->fpe_list[c->current_fpe]; 272706f2543Smrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 273706f2543Smrg } 274706f2543Smrg err = Successful; 275706f2543Smrg goto bail; 276706f2543Smrg } 277706f2543Smrg while (c->current_fpe < c->num_fpes) { 278706f2543Smrg fpe = c->fpe_list[c->current_fpe]; 279706f2543Smrg err = (*fpe_functions[fpe->type].open_font) 280706f2543Smrg ((pointer) client, fpe, c->flags, 281706f2543Smrg c->fontname, c->fnamelen, FontFormat, 282706f2543Smrg BitmapFormatMaskByte | 283706f2543Smrg BitmapFormatMaskBit | 284706f2543Smrg BitmapFormatMaskImageRectangle | 285706f2543Smrg BitmapFormatMaskScanLinePad | 286706f2543Smrg BitmapFormatMaskScanLineUnit, 287706f2543Smrg c->fontid, &pfont, &alias, 288706f2543Smrg c->non_cachable_font && c->non_cachable_font->fpe == fpe ? 289706f2543Smrg c->non_cachable_font : 290706f2543Smrg (FontPtr)0); 291706f2543Smrg 292706f2543Smrg if (err == FontNameAlias && alias) { 293706f2543Smrg newlen = strlen(alias); 294706f2543Smrg newname = (char *) realloc(c->fontname, newlen); 295706f2543Smrg if (!newname) { 296706f2543Smrg err = AllocError; 297706f2543Smrg break; 298706f2543Smrg } 299706f2543Smrg memmove(newname, alias, newlen); 300706f2543Smrg c->fontname = newname; 301706f2543Smrg c->fnamelen = newlen; 302706f2543Smrg c->current_fpe = 0; 303706f2543Smrg if (--aliascount <= 0) { 304706f2543Smrg /* We've tried resolving this alias 20 times, we're 305706f2543Smrg * probably stuck in an infinite loop of aliases pointing 306706f2543Smrg * to each other - time to take emergency exit! 307706f2543Smrg */ 308706f2543Smrg err = BadImplementation; 309706f2543Smrg break; 310706f2543Smrg } 311706f2543Smrg continue; 312706f2543Smrg } 313706f2543Smrg if (err == BadFontName) { 314706f2543Smrg c->current_fpe++; 315706f2543Smrg continue; 316706f2543Smrg } 317706f2543Smrg if (err == Suspended) { 318706f2543Smrg if (!ClientIsAsleep(client)) 319706f2543Smrg ClientSleep(client, (ClientSleepProcPtr)doOpenFont, c); 320706f2543Smrg else 321706f2543Smrg goto xinerama_sleep; 322706f2543Smrg return TRUE; 323706f2543Smrg } 324706f2543Smrg break; 325706f2543Smrg } 326706f2543Smrg 327706f2543Smrg if (err != Successful) 328706f2543Smrg goto bail; 329706f2543Smrg if (!pfont) { 330706f2543Smrg err = BadFontName; 331706f2543Smrg goto bail; 332706f2543Smrg } 333706f2543Smrg /* check values for firstCol, lastCol, firstRow, and lastRow */ 334706f2543Smrg if (pfont->info.firstCol > pfont->info.lastCol || 335706f2543Smrg pfont->info.firstRow > pfont->info.lastRow || 336706f2543Smrg pfont->info.lastCol - pfont->info.firstCol > 255) { 337706f2543Smrg err = AllocError; 338706f2543Smrg goto bail; 339706f2543Smrg } 340706f2543Smrg if (!pfont->fpe) 341706f2543Smrg pfont->fpe = fpe; 342706f2543Smrg pfont->refcnt++; 343706f2543Smrg if (pfont->refcnt == 1) { 344706f2543Smrg UseFPE(pfont->fpe); 345706f2543Smrg for (i = 0; i < screenInfo.numScreens; i++) { 346706f2543Smrg pScr = screenInfo.screens[i]; 347706f2543Smrg if (pScr->RealizeFont) 348706f2543Smrg { 349706f2543Smrg if (!(*pScr->RealizeFont) (pScr, pfont)) 350706f2543Smrg { 351706f2543Smrg CloseFont (pfont, (Font) 0); 352706f2543Smrg err = AllocError; 353706f2543Smrg goto bail; 354706f2543Smrg } 355706f2543Smrg } 356706f2543Smrg } 357706f2543Smrg } 358706f2543Smrg if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) { 359706f2543Smrg err = AllocError; 360706f2543Smrg goto bail; 361706f2543Smrg } 362706f2543Smrg if (patternCache && pfont != c->non_cachable_font) 363706f2543Smrg CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen, 364706f2543Smrg pfont); 365706f2543Smrgbail: 366706f2543Smrg if (err != Successful && c->client != serverClient) { 367706f2543Smrg SendErrorToClient(c->client, X_OpenFont, 0, 368706f2543Smrg c->fontid, FontToXError(err)); 369706f2543Smrg } 370706f2543Smrg ClientWakeup(c->client); 371706f2543Smrgxinerama_sleep: 372706f2543Smrg for (i = 0; i < c->num_fpes; i++) { 373706f2543Smrg FreeFPE(c->fpe_list[i]); 374706f2543Smrg } 375706f2543Smrg free(c->fpe_list); 376706f2543Smrg free(c->fontname); 377706f2543Smrg free(c); 378706f2543Smrg return TRUE; 379706f2543Smrg} 380706f2543Smrg 381706f2543Smrgint 382706f2543SmrgOpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontname) 383706f2543Smrg{ 384706f2543Smrg OFclosurePtr c; 385706f2543Smrg int i; 386706f2543Smrg FontPtr cached = (FontPtr)0; 387706f2543Smrg 388706f2543Smrg if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) 389706f2543Smrg return BadName; 390706f2543Smrg if (patternCache) 391706f2543Smrg { 392706f2543Smrg 393706f2543Smrg /* 394706f2543Smrg ** Check name cache. If we find a cached version of this font that 395706f2543Smrg ** is cachable, immediately satisfy the request with it. If we find 396706f2543Smrg ** a cached version of this font that is non-cachable, we do not 397706f2543Smrg ** satisfy the request with it. Instead, we pass the FontPtr to the 398706f2543Smrg ** FPE's open_font code (the fontfile FPE in turn passes the 399706f2543Smrg ** information to the rasterizer; the fserve FPE ignores it). 400706f2543Smrg ** 401706f2543Smrg ** Presumably, the font is marked non-cachable because the FPE has 402706f2543Smrg ** put some licensing restrictions on it. If the FPE, using 403706f2543Smrg ** whatever logic it relies on, determines that it is willing to 404706f2543Smrg ** share this existing font with the client, then it has the option 405706f2543Smrg ** to return the FontPtr we passed it as the newly-opened font. 406706f2543Smrg ** This allows the FPE to exercise its licensing logic without 407706f2543Smrg ** having to create another instance of a font that already exists. 408706f2543Smrg */ 409706f2543Smrg 410706f2543Smrg cached = FindCachedFontPattern(patternCache, pfontname, lenfname); 411706f2543Smrg if (cached && cached->info.cachable) 412706f2543Smrg { 413706f2543Smrg if (!AddResource(fid, RT_FONT, (pointer) cached)) 414706f2543Smrg return BadAlloc; 415706f2543Smrg cached->refcnt++; 416706f2543Smrg return Success; 417706f2543Smrg } 418706f2543Smrg } 419706f2543Smrg c = malloc(sizeof(OFclosureRec)); 420706f2543Smrg if (!c) 421706f2543Smrg return BadAlloc; 422706f2543Smrg c->fontname = malloc(lenfname); 423706f2543Smrg c->origFontName = pfontname; 424706f2543Smrg c->origFontNameLen = lenfname; 425706f2543Smrg if (!c->fontname) { 426706f2543Smrg free(c); 427706f2543Smrg return BadAlloc; 428706f2543Smrg } 429706f2543Smrg /* 430706f2543Smrg * copy the current FPE list, so that if it gets changed by another client 431706f2543Smrg * while we're blocking, the request still appears atomic 432706f2543Smrg */ 433706f2543Smrg c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes); 434706f2543Smrg if (!c->fpe_list) { 435706f2543Smrg free(c->fontname); 436706f2543Smrg free(c); 437706f2543Smrg return BadAlloc; 438706f2543Smrg } 439706f2543Smrg memmove(c->fontname, pfontname, lenfname); 440706f2543Smrg for (i = 0; i < num_fpes; i++) { 441706f2543Smrg c->fpe_list[i] = font_path_elements[i]; 442706f2543Smrg UseFPE(c->fpe_list[i]); 443706f2543Smrg } 444706f2543Smrg c->client = client; 445706f2543Smrg c->fontid = fid; 446706f2543Smrg c->current_fpe = 0; 447706f2543Smrg c->num_fpes = num_fpes; 448706f2543Smrg c->fnamelen = lenfname; 449706f2543Smrg c->flags = flags; 450706f2543Smrg c->non_cachable_font = cached; 451706f2543Smrg 452706f2543Smrg (void) doOpenFont(client, c); 453706f2543Smrg return Success; 454706f2543Smrg} 455706f2543Smrg 456706f2543Smrg/** 457706f2543Smrg * Decrement font's ref count, and free storage if ref count equals zero 458706f2543Smrg * 459706f2543Smrg * \param value must conform to DeleteType 460706f2543Smrg */ 461706f2543Smrgint 462706f2543SmrgCloseFont(pointer value, XID fid) 463706f2543Smrg{ 464706f2543Smrg int nscr; 465706f2543Smrg ScreenPtr pscr; 466706f2543Smrg FontPathElementPtr fpe; 467706f2543Smrg FontPtr pfont = (FontPtr)value; 468706f2543Smrg 469706f2543Smrg if (pfont == NullFont) 470706f2543Smrg return Success; 471706f2543Smrg if (--pfont->refcnt == 0) { 472706f2543Smrg if (patternCache) 473706f2543Smrg RemoveCachedFontPattern (patternCache, pfont); 474706f2543Smrg /* 475706f2543Smrg * since the last reference is gone, ask each screen to free any 476706f2543Smrg * storage it may have allocated locally for it. 477706f2543Smrg */ 478706f2543Smrg for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { 479706f2543Smrg pscr = screenInfo.screens[nscr]; 480706f2543Smrg if (pscr->UnrealizeFont) 481706f2543Smrg (*pscr->UnrealizeFont) (pscr, pfont); 482706f2543Smrg } 483706f2543Smrg if (pfont == defaultFont) 484706f2543Smrg defaultFont = NULL; 485706f2543Smrg#ifdef XF86BIGFONT 486706f2543Smrg XF86BigfontFreeFontShm(pfont); 487706f2543Smrg#endif 488706f2543Smrg fpe = pfont->fpe; 489706f2543Smrg (*fpe_functions[fpe->type].close_font) (fpe, pfont); 490706f2543Smrg FreeFPE(fpe); 491706f2543Smrg } 492706f2543Smrg return Success; 493706f2543Smrg} 494706f2543Smrg 495706f2543Smrg 496706f2543Smrg/***====================================================================***/ 497706f2543Smrg 498706f2543Smrg/** 499706f2543Smrg * Sets up pReply as the correct QueryFontReply for pFont with the first 500706f2543Smrg * nProtoCCIStructs char infos. 501706f2543Smrg * 502706f2543Smrg * \param pReply caller must allocate this storage 503706f2543Smrg */ 504706f2543Smrgvoid 505706f2543SmrgQueryFont(FontPtr pFont, xQueryFontReply *pReply, int nProtoCCIStructs) 506706f2543Smrg{ 507706f2543Smrg FontPropPtr pFP; 508706f2543Smrg int r, 509706f2543Smrg c, 510706f2543Smrg i; 511706f2543Smrg xFontProp *prFP; 512706f2543Smrg xCharInfo *prCI; 513706f2543Smrg xCharInfo *charInfos[256]; 514706f2543Smrg unsigned char chars[512]; 515706f2543Smrg int ninfos; 516706f2543Smrg unsigned long ncols; 517706f2543Smrg unsigned long count; 518706f2543Smrg 519706f2543Smrg /* pr->length set in dispatch */ 520706f2543Smrg pReply->minCharOrByte2 = pFont->info.firstCol; 521706f2543Smrg pReply->defaultChar = pFont->info.defaultCh; 522706f2543Smrg pReply->maxCharOrByte2 = pFont->info.lastCol; 523706f2543Smrg pReply->drawDirection = pFont->info.drawDirection; 524706f2543Smrg pReply->allCharsExist = pFont->info.allExist; 525706f2543Smrg pReply->minByte1 = pFont->info.firstRow; 526706f2543Smrg pReply->maxByte1 = pFont->info.lastRow; 527706f2543Smrg pReply->fontAscent = pFont->info.fontAscent; 528706f2543Smrg pReply->fontDescent = pFont->info.fontDescent; 529706f2543Smrg 530706f2543Smrg pReply->minBounds = pFont->info.ink_minbounds; 531706f2543Smrg pReply->maxBounds = pFont->info.ink_maxbounds; 532706f2543Smrg 533706f2543Smrg pReply->nFontProps = pFont->info.nprops; 534706f2543Smrg pReply->nCharInfos = nProtoCCIStructs; 535706f2543Smrg 536706f2543Smrg for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]); 537706f2543Smrg i < pFont->info.nprops; 538706f2543Smrg i++, pFP++, prFP++) { 539706f2543Smrg prFP->name = pFP->name; 540706f2543Smrg prFP->value = pFP->value; 541706f2543Smrg } 542706f2543Smrg 543706f2543Smrg ninfos = 0; 544706f2543Smrg ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1); 545706f2543Smrg prCI = (xCharInfo *) (prFP); 546706f2543Smrg for (r = pFont->info.firstRow; 547706f2543Smrg ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow; 548706f2543Smrg r++) { 549706f2543Smrg i = 0; 550706f2543Smrg for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) { 551706f2543Smrg chars[i++] = r; 552706f2543Smrg chars[i++] = c; 553706f2543Smrg } 554706f2543Smrg (*pFont->get_metrics) (pFont, ncols, chars, 555706f2543Smrg TwoD16Bit, &count, charInfos); 556706f2543Smrg i = 0; 557706f2543Smrg for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) { 558706f2543Smrg *prCI = *charInfos[i]; 559706f2543Smrg prCI++; 560706f2543Smrg ninfos++; 561706f2543Smrg } 562706f2543Smrg } 563706f2543Smrg return; 564706f2543Smrg} 565706f2543Smrg 566706f2543Smrgstatic Bool 567706f2543SmrgdoListFontsAndAliases(ClientPtr client, LFclosurePtr c) 568706f2543Smrg{ 569706f2543Smrg FontPathElementPtr fpe; 570706f2543Smrg int err = Successful; 571706f2543Smrg FontNamesPtr names = NULL; 572706f2543Smrg char *name, *resolved=NULL; 573706f2543Smrg int namelen, resolvedlen; 574706f2543Smrg int nnames; 575706f2543Smrg int stringLens; 576706f2543Smrg int i; 577706f2543Smrg xListFontsReply reply; 578706f2543Smrg char *bufptr; 579706f2543Smrg char *bufferStart; 580706f2543Smrg int aliascount = 0; 581706f2543Smrg 582706f2543Smrg if (client->clientGone) 583706f2543Smrg { 584706f2543Smrg if (c->current.current_fpe < c->num_fpes) 585706f2543Smrg { 586706f2543Smrg fpe = c->fpe_list[c->current.current_fpe]; 587706f2543Smrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 588706f2543Smrg } 589706f2543Smrg err = Successful; 590706f2543Smrg goto bail; 591706f2543Smrg } 592706f2543Smrg 593706f2543Smrg if (!c->current.patlen) 594706f2543Smrg goto finish; 595706f2543Smrg 596706f2543Smrg while (c->current.current_fpe < c->num_fpes) { 597706f2543Smrg fpe = c->fpe_list[c->current.current_fpe]; 598706f2543Smrg err = Successful; 599706f2543Smrg 600706f2543Smrg if (!fpe_functions[fpe->type].start_list_fonts_and_aliases) 601706f2543Smrg { 602706f2543Smrg /* This FPE doesn't support/require list_fonts_and_aliases */ 603706f2543Smrg 604706f2543Smrg err = (*fpe_functions[fpe->type].list_fonts) 605706f2543Smrg ((pointer) c->client, fpe, c->current.pattern, 606706f2543Smrg c->current.patlen, c->current.max_names - c->names->nnames, 607706f2543Smrg c->names); 608706f2543Smrg 609706f2543Smrg if (err == Suspended) { 610706f2543Smrg if (!ClientIsAsleep(client)) 611706f2543Smrg ClientSleep(client, 612706f2543Smrg (ClientSleepProcPtr)doListFontsAndAliases, 613706f2543Smrg c); 614706f2543Smrg else 615706f2543Smrg goto xinerama_sleep; 616706f2543Smrg return TRUE; 617706f2543Smrg } 618706f2543Smrg 619706f2543Smrg err = BadFontName; 620706f2543Smrg } 621706f2543Smrg else 622706f2543Smrg { 623706f2543Smrg /* Start of list_fonts_and_aliases functionality. Modeled 624706f2543Smrg after list_fonts_with_info in that it resolves aliases, 625706f2543Smrg except that the information collected from FPEs is just 626706f2543Smrg names, not font info. Each list_next_font_or_alias() 627706f2543Smrg returns either a name into name/namelen or an alias into 628706f2543Smrg name/namelen and its target name into resolved/resolvedlen. 629706f2543Smrg The code at this level then resolves the alias by polling 630706f2543Smrg the FPEs. */ 631706f2543Smrg 632706f2543Smrg if (!c->current.list_started) { 633706f2543Smrg err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases) 634706f2543Smrg ((pointer) c->client, fpe, c->current.pattern, 635706f2543Smrg c->current.patlen, c->current.max_names - c->names->nnames, 636706f2543Smrg &c->current.private); 637706f2543Smrg if (err == Suspended) { 638706f2543Smrg if (!ClientIsAsleep(client)) 639706f2543Smrg ClientSleep(client, 640706f2543Smrg (ClientSleepProcPtr)doListFontsAndAliases, 641706f2543Smrg c); 642706f2543Smrg else 643706f2543Smrg goto xinerama_sleep; 644706f2543Smrg return TRUE; 645706f2543Smrg } 646706f2543Smrg if (err == Successful) 647706f2543Smrg c->current.list_started = TRUE; 648706f2543Smrg } 649706f2543Smrg if (err == Successful) { 650706f2543Smrg char *tmpname; 651706f2543Smrg name = 0; 652706f2543Smrg err = (*fpe_functions[fpe->type].list_next_font_or_alias) 653706f2543Smrg ((pointer) c->client, fpe, &name, &namelen, &tmpname, 654706f2543Smrg &resolvedlen, c->current.private); 655706f2543Smrg if (err == Suspended) { 656706f2543Smrg if (!ClientIsAsleep(client)) 657706f2543Smrg ClientSleep(client, 658706f2543Smrg (ClientSleepProcPtr)doListFontsAndAliases, 659706f2543Smrg c); 660706f2543Smrg else 661706f2543Smrg goto xinerama_sleep; 662706f2543Smrg return TRUE; 663706f2543Smrg } 664706f2543Smrg if (err == FontNameAlias) { 665706f2543Smrg free(resolved); 666706f2543Smrg resolved = malloc(resolvedlen + 1); 667706f2543Smrg if (resolved) 668706f2543Smrg memmove(resolved, tmpname, resolvedlen + 1); 669706f2543Smrg } 670706f2543Smrg } 671706f2543Smrg 672706f2543Smrg if (err == Successful) 673706f2543Smrg { 674706f2543Smrg if (c->haveSaved) 675706f2543Smrg { 676706f2543Smrg if (c->savedName) 677706f2543Smrg (void)AddFontNamesName(c->names, c->savedName, 678706f2543Smrg c->savedNameLen); 679706f2543Smrg } 680706f2543Smrg else 681706f2543Smrg (void)AddFontNamesName(c->names, name, namelen); 682706f2543Smrg } 683706f2543Smrg 684706f2543Smrg /* 685706f2543Smrg * When we get an alias back, save our state and reset back to 686706f2543Smrg * the start of the FPE looking for the specified name. As 687706f2543Smrg * soon as a real font is found for the alias, pop back to the 688706f2543Smrg * old state 689706f2543Smrg */ 690706f2543Smrg else if (err == FontNameAlias) { 691706f2543Smrg char tmp_pattern[XLFDMAXFONTNAMELEN]; 692706f2543Smrg /* 693706f2543Smrg * when an alias recurses, we need to give 694706f2543Smrg * the last FPE a chance to clean up; so we call 695706f2543Smrg * it again, and assume that the error returned 696706f2543Smrg * is BadFontName, indicating the alias resolution 697706f2543Smrg * is complete. 698706f2543Smrg */ 699706f2543Smrg memmove(tmp_pattern, resolved, resolvedlen); 700706f2543Smrg if (c->haveSaved) 701706f2543Smrg { 702706f2543Smrg char *tmpname; 703706f2543Smrg int tmpnamelen; 704706f2543Smrg 705706f2543Smrg tmpname = 0; 706706f2543Smrg (void) (*fpe_functions[fpe->type].list_next_font_or_alias) 707706f2543Smrg ((pointer) c->client, fpe, &tmpname, &tmpnamelen, 708706f2543Smrg &tmpname, &tmpnamelen, c->current.private); 709706f2543Smrg if (--aliascount <= 0) 710706f2543Smrg { 711706f2543Smrg err = BadFontName; 712706f2543Smrg goto ContBadFontName; 713706f2543Smrg } 714706f2543Smrg } 715706f2543Smrg else 716706f2543Smrg { 717706f2543Smrg c->saved = c->current; 718706f2543Smrg c->haveSaved = TRUE; 719706f2543Smrg free(c->savedName); 720706f2543Smrg c->savedName = malloc(namelen + 1); 721706f2543Smrg if (c->savedName) 722706f2543Smrg memmove(c->savedName, name, namelen + 1); 723706f2543Smrg c->savedNameLen = namelen; 724706f2543Smrg aliascount = 20; 725706f2543Smrg } 726706f2543Smrg memmove(c->current.pattern, tmp_pattern, resolvedlen); 727706f2543Smrg c->current.patlen = resolvedlen; 728706f2543Smrg c->current.max_names = c->names->nnames + 1; 729706f2543Smrg c->current.current_fpe = -1; 730706f2543Smrg c->current.private = 0; 731706f2543Smrg err = BadFontName; 732706f2543Smrg } 733706f2543Smrg } 734706f2543Smrg /* 735706f2543Smrg * At the end of this FPE, step to the next. If we've finished 736706f2543Smrg * processing an alias, pop state back. If we've collected enough 737706f2543Smrg * font names, quit. 738706f2543Smrg */ 739706f2543Smrg if (err == BadFontName) { 740706f2543Smrg ContBadFontName: ; 741706f2543Smrg c->current.list_started = FALSE; 742706f2543Smrg c->current.current_fpe++; 743706f2543Smrg err = Successful; 744706f2543Smrg if (c->haveSaved) 745706f2543Smrg { 746706f2543Smrg if (c->names->nnames == c->current.max_names || 747706f2543Smrg c->current.current_fpe == c->num_fpes) { 748706f2543Smrg c->haveSaved = FALSE; 749706f2543Smrg c->current = c->saved; 750706f2543Smrg /* Give the saved namelist a chance to clean itself up */ 751706f2543Smrg continue; 752706f2543Smrg } 753706f2543Smrg } 754706f2543Smrg if (c->names->nnames == c->current.max_names) 755706f2543Smrg break; 756706f2543Smrg } 757706f2543Smrg } 758706f2543Smrg 759706f2543Smrg /* 760706f2543Smrg * send the reply 761706f2543Smrg */ 762706f2543Smrg if (err != Successful) { 763706f2543Smrg SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err)); 764706f2543Smrg goto bail; 765706f2543Smrg } 766706f2543Smrg 767706f2543Smrgfinish: 768706f2543Smrg 769706f2543Smrg names = c->names; 770706f2543Smrg nnames = names->nnames; 771706f2543Smrg client = c->client; 772706f2543Smrg stringLens = 0; 773706f2543Smrg for (i = 0; i < nnames; i++) 774706f2543Smrg stringLens += (names->length[i] <= 255) ? names->length[i] : 0; 775706f2543Smrg 776706f2543Smrg memset(&reply, 0, sizeof(xListFontsReply)); 777706f2543Smrg reply.type = X_Reply; 778706f2543Smrg reply.length = bytes_to_int32(stringLens + nnames); 779706f2543Smrg reply.nFonts = nnames; 780706f2543Smrg reply.sequenceNumber = client->sequence; 781706f2543Smrg 782706f2543Smrg bufptr = bufferStart = malloc(reply.length << 2); 783706f2543Smrg 784706f2543Smrg if (!bufptr && reply.length) { 785706f2543Smrg SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc); 786706f2543Smrg goto bail; 787706f2543Smrg } 788706f2543Smrg /* 789706f2543Smrg * since WriteToClient long word aligns things, copy to temp buffer and 790706f2543Smrg * write all at once 791706f2543Smrg */ 792706f2543Smrg for (i = 0; i < nnames; i++) { 793706f2543Smrg if (names->length[i] > 255) 794706f2543Smrg reply.nFonts--; 795706f2543Smrg else 796706f2543Smrg { 797706f2543Smrg *bufptr++ = names->length[i]; 798706f2543Smrg memmove( bufptr, names->names[i], names->length[i]); 799706f2543Smrg bufptr += names->length[i]; 800706f2543Smrg } 801706f2543Smrg } 802706f2543Smrg nnames = reply.nFonts; 803706f2543Smrg reply.length = bytes_to_int32(stringLens + nnames); 804706f2543Smrg client->pSwapReplyFunc = ReplySwapVector[X_ListFonts]; 805706f2543Smrg WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply); 806706f2543Smrg (void) WriteToClient(client, stringLens + nnames, bufferStart); 807706f2543Smrg free(bufferStart); 808706f2543Smrg 809706f2543Smrgbail: 810706f2543Smrg ClientWakeup(client); 811706f2543Smrgxinerama_sleep: 812706f2543Smrg for (i = 0; i < c->num_fpes; i++) 813706f2543Smrg FreeFPE(c->fpe_list[i]); 814706f2543Smrg free(c->fpe_list); 815706f2543Smrg free(c->savedName); 816706f2543Smrg FreeFontNames(names); 817706f2543Smrg free(c); 818706f2543Smrg free(resolved); 819706f2543Smrg return TRUE; 820706f2543Smrg} 821706f2543Smrg 822706f2543Smrgint 823706f2543SmrgListFonts(ClientPtr client, unsigned char *pattern, unsigned length, 824706f2543Smrg unsigned max_names) 825706f2543Smrg{ 826706f2543Smrg int i; 827706f2543Smrg LFclosurePtr c; 828706f2543Smrg 829706f2543Smrg /* 830706f2543Smrg * The right error to return here would be BadName, however the 831706f2543Smrg * specification does not allow for a Name error on this request. 832706f2543Smrg * Perhaps a better solution would be to return a nil list, i.e. 833706f2543Smrg * a list containing zero fontnames. 834706f2543Smrg */ 835706f2543Smrg if (length > XLFDMAXFONTNAMELEN) 836706f2543Smrg return BadAlloc; 837706f2543Smrg 838706f2543Smrg i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess); 839706f2543Smrg if (i != Success) 840706f2543Smrg return i; 841706f2543Smrg 842706f2543Smrg if (!(c = malloc(sizeof *c))) 843706f2543Smrg return BadAlloc; 844706f2543Smrg c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes); 845706f2543Smrg if (!c->fpe_list) { 846706f2543Smrg free(c); 847706f2543Smrg return BadAlloc; 848706f2543Smrg } 849706f2543Smrg c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100); 850706f2543Smrg if (!c->names) 851706f2543Smrg { 852706f2543Smrg free(c->fpe_list); 853706f2543Smrg free(c); 854706f2543Smrg return BadAlloc; 855706f2543Smrg } 856706f2543Smrg memmove( c->current.pattern, pattern, length); 857706f2543Smrg for (i = 0; i < num_fpes; i++) { 858706f2543Smrg c->fpe_list[i] = font_path_elements[i]; 859706f2543Smrg UseFPE(c->fpe_list[i]); 860706f2543Smrg } 861706f2543Smrg c->client = client; 862706f2543Smrg c->num_fpes = num_fpes; 863706f2543Smrg c->current.patlen = length; 864706f2543Smrg c->current.current_fpe = 0; 865706f2543Smrg c->current.max_names = max_names; 866706f2543Smrg c->current.list_started = FALSE; 867706f2543Smrg c->current.private = 0; 868706f2543Smrg c->haveSaved = FALSE; 869706f2543Smrg c->savedName = 0; 870706f2543Smrg doListFontsAndAliases(client, c); 871706f2543Smrg return Success; 872706f2543Smrg} 873706f2543Smrg 874706f2543Smrgint 875706f2543SmrgdoListFontsWithInfo(ClientPtr client, LFWIclosurePtr c) 876706f2543Smrg{ 877706f2543Smrg FontPathElementPtr fpe; 878706f2543Smrg int err = Successful; 879706f2543Smrg char *name; 880706f2543Smrg int namelen; 881706f2543Smrg int numFonts; 882706f2543Smrg FontInfoRec fontInfo, 883706f2543Smrg *pFontInfo; 884706f2543Smrg xListFontsWithInfoReply *reply; 885706f2543Smrg int length; 886706f2543Smrg xFontProp *pFP; 887706f2543Smrg int i; 888706f2543Smrg int aliascount = 0; 889706f2543Smrg xListFontsWithInfoReply finalReply; 890706f2543Smrg 891706f2543Smrg if (client->clientGone) 892706f2543Smrg { 893706f2543Smrg if (c->current.current_fpe < c->num_fpes) 894706f2543Smrg { 895706f2543Smrg fpe = c->fpe_list[c->current.current_fpe]; 896706f2543Smrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 897706f2543Smrg } 898706f2543Smrg err = Successful; 899706f2543Smrg goto bail; 900706f2543Smrg } 901706f2543Smrg client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo]; 902706f2543Smrg if (!c->current.patlen) 903706f2543Smrg goto finish; 904706f2543Smrg while (c->current.current_fpe < c->num_fpes) 905706f2543Smrg { 906706f2543Smrg fpe = c->fpe_list[c->current.current_fpe]; 907706f2543Smrg err = Successful; 908706f2543Smrg if (!c->current.list_started) 909706f2543Smrg { 910706f2543Smrg err = (*fpe_functions[fpe->type].start_list_fonts_with_info) 911706f2543Smrg (client, fpe, c->current.pattern, c->current.patlen, 912706f2543Smrg c->current.max_names, &c->current.private); 913706f2543Smrg if (err == Suspended) 914706f2543Smrg { 915706f2543Smrg if (!ClientIsAsleep(client)) 916706f2543Smrg ClientSleep(client, 917706f2543Smrg (ClientSleepProcPtr)doListFontsWithInfo, c); 918706f2543Smrg else 919706f2543Smrg goto xinerama_sleep; 920706f2543Smrg return TRUE; 921706f2543Smrg } 922706f2543Smrg if (err == Successful) 923706f2543Smrg c->current.list_started = TRUE; 924706f2543Smrg } 925706f2543Smrg if (err == Successful) 926706f2543Smrg { 927706f2543Smrg name = 0; 928706f2543Smrg pFontInfo = &fontInfo; 929706f2543Smrg err = (*fpe_functions[fpe->type].list_next_font_with_info) 930706f2543Smrg (client, fpe, &name, &namelen, &pFontInfo, 931706f2543Smrg &numFonts, c->current.private); 932706f2543Smrg if (err == Suspended) 933706f2543Smrg { 934706f2543Smrg if (!ClientIsAsleep(client)) 935706f2543Smrg ClientSleep(client, 936706f2543Smrg (ClientSleepProcPtr)doListFontsWithInfo, c); 937706f2543Smrg else 938706f2543Smrg goto xinerama_sleep; 939706f2543Smrg return TRUE; 940706f2543Smrg } 941706f2543Smrg } 942706f2543Smrg /* 943706f2543Smrg * When we get an alias back, save our state and reset back to the 944706f2543Smrg * start of the FPE looking for the specified name. As soon as a real 945706f2543Smrg * font is found for the alias, pop back to the old state 946706f2543Smrg */ 947706f2543Smrg if (err == FontNameAlias) 948706f2543Smrg { 949706f2543Smrg /* 950706f2543Smrg * when an alias recurses, we need to give 951706f2543Smrg * the last FPE a chance to clean up; so we call 952706f2543Smrg * it again, and assume that the error returned 953706f2543Smrg * is BadFontName, indicating the alias resolution 954706f2543Smrg * is complete. 955706f2543Smrg */ 956706f2543Smrg if (c->haveSaved) 957706f2543Smrg { 958706f2543Smrg char *tmpname; 959706f2543Smrg int tmpnamelen; 960706f2543Smrg FontInfoPtr tmpFontInfo; 961706f2543Smrg 962706f2543Smrg tmpname = 0; 963706f2543Smrg tmpFontInfo = &fontInfo; 964706f2543Smrg (void) (*fpe_functions[fpe->type].list_next_font_with_info) 965706f2543Smrg (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo, 966706f2543Smrg &numFonts, c->current.private); 967706f2543Smrg if (--aliascount <= 0) 968706f2543Smrg { 969706f2543Smrg err = BadFontName; 970706f2543Smrg goto ContBadFontName; 971706f2543Smrg } 972706f2543Smrg } 973706f2543Smrg else 974706f2543Smrg { 975706f2543Smrg c->saved = c->current; 976706f2543Smrg c->haveSaved = TRUE; 977706f2543Smrg c->savedNumFonts = numFonts; 978706f2543Smrg free(c->savedName); 979706f2543Smrg c->savedName = malloc(namelen + 1); 980706f2543Smrg if (c->savedName) 981706f2543Smrg memmove(c->savedName, name, namelen + 1); 982706f2543Smrg aliascount = 20; 983706f2543Smrg } 984706f2543Smrg memmove(c->current.pattern, name, namelen); 985706f2543Smrg c->current.patlen = namelen; 986706f2543Smrg c->current.max_names = 1; 987706f2543Smrg c->current.current_fpe = 0; 988706f2543Smrg c->current.private = 0; 989706f2543Smrg c->current.list_started = FALSE; 990706f2543Smrg } 991706f2543Smrg /* 992706f2543Smrg * At the end of this FPE, step to the next. If we've finished 993706f2543Smrg * processing an alias, pop state back. If we've sent enough font 994706f2543Smrg * names, quit. Always wait for BadFontName to let the FPE 995706f2543Smrg * have a chance to clean up. 996706f2543Smrg */ 997706f2543Smrg else if (err == BadFontName) 998706f2543Smrg { 999706f2543Smrg ContBadFontName: ; 1000706f2543Smrg c->current.list_started = FALSE; 1001706f2543Smrg c->current.current_fpe++; 1002706f2543Smrg err = Successful; 1003706f2543Smrg if (c->haveSaved) 1004706f2543Smrg { 1005706f2543Smrg if (c->current.max_names == 0 || 1006706f2543Smrg c->current.current_fpe == c->num_fpes) 1007706f2543Smrg { 1008706f2543Smrg c->haveSaved = FALSE; 1009706f2543Smrg c->saved.max_names -= (1 - c->current.max_names); 1010706f2543Smrg c->current = c->saved; 1011706f2543Smrg } 1012706f2543Smrg } 1013706f2543Smrg else if (c->current.max_names == 0) 1014706f2543Smrg break; 1015706f2543Smrg } 1016706f2543Smrg else if (err == Successful) 1017706f2543Smrg { 1018706f2543Smrg length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp); 1019706f2543Smrg reply = c->reply; 1020706f2543Smrg if (c->length < length) 1021706f2543Smrg { 1022706f2543Smrg reply = (xListFontsWithInfoReply *) realloc(c->reply, length); 1023706f2543Smrg if (!reply) 1024706f2543Smrg { 1025706f2543Smrg err = AllocError; 1026706f2543Smrg break; 1027706f2543Smrg } 1028706f2543Smrg memset((char*)reply + c->length, 0, length - c->length); 1029706f2543Smrg c->reply = reply; 1030706f2543Smrg c->length = length; 1031706f2543Smrg } 1032706f2543Smrg if (c->haveSaved) 1033706f2543Smrg { 1034706f2543Smrg numFonts = c->savedNumFonts; 1035706f2543Smrg name = c->savedName; 1036706f2543Smrg namelen = strlen(name); 1037706f2543Smrg } 1038706f2543Smrg reply->type = X_Reply; 1039706f2543Smrg reply->length = bytes_to_int32(sizeof *reply - sizeof(xGenericReply) + 1040706f2543Smrg pFontInfo->nprops * sizeof(xFontProp) + 1041706f2543Smrg namelen); 1042706f2543Smrg reply->sequenceNumber = client->sequence; 1043706f2543Smrg reply->nameLength = namelen; 1044706f2543Smrg reply->minBounds = pFontInfo->ink_minbounds; 1045706f2543Smrg reply->maxBounds = pFontInfo->ink_maxbounds; 1046706f2543Smrg reply->minCharOrByte2 = pFontInfo->firstCol; 1047706f2543Smrg reply->maxCharOrByte2 = pFontInfo->lastCol; 1048706f2543Smrg reply->defaultChar = pFontInfo->defaultCh; 1049706f2543Smrg reply->nFontProps = pFontInfo->nprops; 1050706f2543Smrg reply->drawDirection = pFontInfo->drawDirection; 1051706f2543Smrg reply->minByte1 = pFontInfo->firstRow; 1052706f2543Smrg reply->maxByte1 = pFontInfo->lastRow; 1053706f2543Smrg reply->allCharsExist = pFontInfo->allExist; 1054706f2543Smrg reply->fontAscent = pFontInfo->fontAscent; 1055706f2543Smrg reply->fontDescent = pFontInfo->fontDescent; 1056706f2543Smrg reply->nReplies = numFonts; 1057706f2543Smrg pFP = (xFontProp *) (reply + 1); 1058706f2543Smrg for (i = 0; i < pFontInfo->nprops; i++) 1059706f2543Smrg { 1060706f2543Smrg pFP->name = pFontInfo->props[i].name; 1061706f2543Smrg pFP->value = pFontInfo->props[i].value; 1062706f2543Smrg pFP++; 1063706f2543Smrg } 1064706f2543Smrg WriteSwappedDataToClient(client, length, reply); 1065706f2543Smrg (void) WriteToClient(client, namelen, name); 1066706f2543Smrg if (pFontInfo == &fontInfo) 1067706f2543Smrg { 1068706f2543Smrg free(fontInfo.props); 1069706f2543Smrg free(fontInfo.isStringProp); 1070706f2543Smrg } 1071706f2543Smrg --c->current.max_names; 1072706f2543Smrg } 1073706f2543Smrg } 1074706f2543Smrgfinish: 1075706f2543Smrg length = sizeof(xListFontsWithInfoReply); 1076706f2543Smrg memset((char *) &finalReply, 0, sizeof(xListFontsWithInfoReply)); 1077706f2543Smrg finalReply.type = X_Reply; 1078706f2543Smrg finalReply.sequenceNumber = client->sequence; 1079706f2543Smrg finalReply.length = bytes_to_int32(sizeof(xListFontsWithInfoReply) 1080706f2543Smrg - sizeof(xGenericReply)); 1081706f2543Smrg WriteSwappedDataToClient(client, length, &finalReply); 1082706f2543Smrgbail: 1083706f2543Smrg ClientWakeup(client); 1084706f2543Smrgxinerama_sleep: 1085706f2543Smrg for (i = 0; i < c->num_fpes; i++) 1086706f2543Smrg FreeFPE(c->fpe_list[i]); 1087706f2543Smrg free(c->reply); 1088706f2543Smrg free(c->fpe_list); 1089706f2543Smrg free(c->savedName); 1090706f2543Smrg free(c); 1091706f2543Smrg return TRUE; 1092706f2543Smrg} 1093706f2543Smrg 1094706f2543Smrgint 1095706f2543SmrgStartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern, 1096706f2543Smrg int max_names) 1097706f2543Smrg{ 1098706f2543Smrg int i; 1099706f2543Smrg LFWIclosurePtr c; 1100706f2543Smrg 1101706f2543Smrg /* 1102706f2543Smrg * The right error to return here would be BadName, however the 1103706f2543Smrg * specification does not allow for a Name error on this request. 1104706f2543Smrg * Perhaps a better solution would be to return a nil list, i.e. 1105706f2543Smrg * a list containing zero fontnames. 1106706f2543Smrg */ 1107706f2543Smrg if (length > XLFDMAXFONTNAMELEN) 1108706f2543Smrg return BadAlloc; 1109706f2543Smrg 1110706f2543Smrg i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess); 1111706f2543Smrg if (i != Success) 1112706f2543Smrg return i; 1113706f2543Smrg 1114706f2543Smrg if (!(c = malloc(sizeof *c))) 1115706f2543Smrg goto badAlloc; 1116706f2543Smrg c->fpe_list = malloc(sizeof(FontPathElementPtr) * num_fpes); 1117706f2543Smrg if (!c->fpe_list) 1118706f2543Smrg { 1119706f2543Smrg free(c); 1120706f2543Smrg goto badAlloc; 1121706f2543Smrg } 1122706f2543Smrg memmove(c->current.pattern, pattern, length); 1123706f2543Smrg for (i = 0; i < num_fpes; i++) 1124706f2543Smrg { 1125706f2543Smrg c->fpe_list[i] = font_path_elements[i]; 1126706f2543Smrg UseFPE(c->fpe_list[i]); 1127706f2543Smrg } 1128706f2543Smrg c->client = client; 1129706f2543Smrg c->num_fpes = num_fpes; 1130706f2543Smrg c->reply = 0; 1131706f2543Smrg c->length = 0; 1132706f2543Smrg c->current.patlen = length; 1133706f2543Smrg c->current.current_fpe = 0; 1134706f2543Smrg c->current.max_names = max_names; 1135706f2543Smrg c->current.list_started = FALSE; 1136706f2543Smrg c->current.private = 0; 1137706f2543Smrg c->savedNumFonts = 0; 1138706f2543Smrg c->haveSaved = FALSE; 1139706f2543Smrg c->savedName = 0; 1140706f2543Smrg doListFontsWithInfo(client, c); 1141706f2543Smrg return Success; 1142706f2543SmrgbadAlloc: 1143706f2543Smrg return BadAlloc; 1144706f2543Smrg} 1145706f2543Smrg 1146706f2543Smrg#define TextEltHeader 2 1147706f2543Smrg#define FontShiftSize 5 1148706f2543Smrgstatic ChangeGCVal clearGC[] = { { .ptr = NullPixmap } }; 1149706f2543Smrg#define clearGCmask (GCClipMask) 1150706f2543Smrg 1151706f2543Smrgint 1152706f2543SmrgdoPolyText(ClientPtr client, PTclosurePtr c) 1153706f2543Smrg{ 1154706f2543Smrg FontPtr pFont = c->pGC->font, oldpFont; 1155706f2543Smrg int err = Success, lgerr; /* err is in X error, not font error, space */ 1156706f2543Smrg enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT; 1157706f2543Smrg FontPathElementPtr fpe; 1158706f2543Smrg GC *origGC = NULL; 1159706f2543Smrg int itemSize = c->reqType == X_PolyText8 ? 1 : 2; 1160706f2543Smrg 1161706f2543Smrg if (client->clientGone) 1162706f2543Smrg { 1163706f2543Smrg fpe = c->pGC->font->fpe; 1164706f2543Smrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 1165706f2543Smrg 1166706f2543Smrg if (ClientIsAsleep(client)) 1167706f2543Smrg { 1168706f2543Smrg /* Client has died, but we cannot bail out right now. We 1169706f2543Smrg need to clean up after the work we did when going to 1170706f2543Smrg sleep. Setting the drawable pointer to 0 makes this 1171706f2543Smrg happen without any attempts to render or perform other 1172706f2543Smrg unnecessary activities. */ 1173706f2543Smrg c->pDraw = (DrawablePtr)0; 1174706f2543Smrg } 1175706f2543Smrg else 1176706f2543Smrg { 1177706f2543Smrg err = Success; 1178706f2543Smrg goto bail; 1179706f2543Smrg } 1180706f2543Smrg } 1181706f2543Smrg 1182706f2543Smrg /* Make sure our drawable hasn't disappeared while we slept. */ 1183706f2543Smrg if (ClientIsAsleep(client) && c->pDraw) 1184706f2543Smrg { 1185706f2543Smrg DrawablePtr pDraw; 1186706f2543Smrg dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess); 1187706f2543Smrg if (c->pDraw != pDraw) { 1188706f2543Smrg /* Our drawable has disappeared. Treat like client died... ask 1189706f2543Smrg the FPE code to clean up after client and avoid further 1190706f2543Smrg rendering while we clean up after ourself. */ 1191706f2543Smrg fpe = c->pGC->font->fpe; 1192706f2543Smrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 1193706f2543Smrg c->pDraw = (DrawablePtr)0; 1194706f2543Smrg } 1195706f2543Smrg } 1196706f2543Smrg 1197706f2543Smrg client_state = ClientIsAsleep(client) ? SLEEPING : NEVER_SLEPT; 1198706f2543Smrg 1199706f2543Smrg while (c->endReq - c->pElt > TextEltHeader) 1200706f2543Smrg { 1201706f2543Smrg if (*c->pElt == FontChange) 1202706f2543Smrg { 1203706f2543Smrg Font fid; 1204706f2543Smrg if (c->endReq - c->pElt < FontShiftSize) 1205706f2543Smrg { 1206706f2543Smrg err = BadLength; 1207706f2543Smrg goto bail; 1208706f2543Smrg } 1209706f2543Smrg 1210706f2543Smrg oldpFont = pFont; 1211706f2543Smrg 1212706f2543Smrg fid = ((Font)*(c->pElt+4)) /* big-endian */ 1213706f2543Smrg | ((Font)*(c->pElt+3)) << 8 1214706f2543Smrg | ((Font)*(c->pElt+2)) << 16 1215706f2543Smrg | ((Font)*(c->pElt+1)) << 24; 1216706f2543Smrg err = dixLookupResourceByType((pointer *)&pFont, fid, RT_FONT, 1217706f2543Smrg client, DixUseAccess); 1218706f2543Smrg if (err != Success) 1219706f2543Smrg { 1220706f2543Smrg /* restore pFont for step 4 (described below) */ 1221706f2543Smrg pFont = oldpFont; 1222706f2543Smrg 1223706f2543Smrg /* If we're in START_SLEEP mode, the following step 1224706f2543Smrg shortens the request... in the unlikely event that 1225706f2543Smrg the fid somehow becomes valid before we come through 1226706f2543Smrg again to actually execute the polytext, which would 1227706f2543Smrg then mess up our refcounting scheme badly. */ 1228706f2543Smrg c->err = err; 1229706f2543Smrg c->endReq = c->pElt; 1230706f2543Smrg 1231706f2543Smrg goto bail; 1232706f2543Smrg } 1233706f2543Smrg 1234706f2543Smrg /* Step 3 (described below) on our new font */ 1235706f2543Smrg if (client_state == START_SLEEP) 1236706f2543Smrg pFont->refcnt++; 1237706f2543Smrg else 1238706f2543Smrg { 1239706f2543Smrg if (pFont != c->pGC->font && c->pDraw) 1240706f2543Smrg { 1241706f2543Smrg ChangeGCVal val; 1242706f2543Smrg val.ptr = pFont; 1243706f2543Smrg ChangeGC(NullClient, c->pGC, GCFont, &val); 1244706f2543Smrg ValidateGC(c->pDraw, c->pGC); 1245706f2543Smrg } 1246706f2543Smrg 1247706f2543Smrg /* Undo the refcnt++ we performed when going to sleep */ 1248706f2543Smrg if (client_state == SLEEPING) 1249706f2543Smrg (void)CloseFont(c->pGC->font, (Font)0); 1250706f2543Smrg } 1251706f2543Smrg c->pElt += FontShiftSize; 1252706f2543Smrg } 1253706f2543Smrg else /* print a string */ 1254706f2543Smrg { 1255706f2543Smrg unsigned char *pNextElt; 1256706f2543Smrg pNextElt = c->pElt + TextEltHeader + (*c->pElt) * itemSize; 1257706f2543Smrg if ( pNextElt > c->endReq) 1258706f2543Smrg { 1259706f2543Smrg err = BadLength; 1260706f2543Smrg goto bail; 1261706f2543Smrg } 1262706f2543Smrg if (client_state == START_SLEEP) 1263706f2543Smrg { 1264706f2543Smrg c->pElt = pNextElt; 1265706f2543Smrg continue; 1266706f2543Smrg } 1267706f2543Smrg if (c->pDraw) 1268706f2543Smrg { 1269706f2543Smrg lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, itemSize, 1270706f2543Smrg c->pElt + TextEltHeader); 1271706f2543Smrg } 1272706f2543Smrg else lgerr = Successful; 1273706f2543Smrg 1274706f2543Smrg if (lgerr == Suspended) 1275706f2543Smrg { 1276706f2543Smrg if (!ClientIsAsleep(client)) { 1277706f2543Smrg int len; 1278706f2543Smrg GC *pGC; 1279706f2543Smrg PTclosurePtr new_closure; 1280706f2543Smrg 1281706f2543Smrg /* We're putting the client to sleep. We need to do a few things 1282706f2543Smrg to ensure successful and atomic-appearing execution of the 1283706f2543Smrg remainder of the request. First, copy the remainder of the 1284706f2543Smrg request into a safe malloc'd area. Second, create a scratch GC 1285706f2543Smrg to use for the remainder of the request. Third, mark all fonts 1286706f2543Smrg referenced in the remainder of the request to prevent their 1287706f2543Smrg deallocation. Fourth, make the original GC look like the 1288706f2543Smrg request has completed... set its font to the final font value 1289706f2543Smrg from this request. These GC manipulations are for the unlikely 1290706f2543Smrg (but possible) event that some other client is using the GC. 1291706f2543Smrg Steps 3 and 4 are performed by running this procedure through 1292706f2543Smrg the remainder of the request in a special no-render mode 1293706f2543Smrg indicated by client_state = START_SLEEP. */ 1294706f2543Smrg 1295706f2543Smrg /* Step 1 */ 1296706f2543Smrg /* Allocate a malloc'd closure structure to replace 1297706f2543Smrg the local one we were passed */ 1298706f2543Smrg new_closure = malloc(sizeof(PTclosureRec)); 1299706f2543Smrg if (!new_closure) 1300706f2543Smrg { 1301706f2543Smrg err = BadAlloc; 1302706f2543Smrg goto bail; 1303706f2543Smrg } 1304706f2543Smrg *new_closure = *c; 1305706f2543Smrg 1306706f2543Smrg len = new_closure->endReq - new_closure->pElt; 1307706f2543Smrg new_closure->data = malloc(len); 1308706f2543Smrg if (!new_closure->data) 1309706f2543Smrg { 1310706f2543Smrg free(new_closure); 1311706f2543Smrg err = BadAlloc; 1312706f2543Smrg goto bail; 1313706f2543Smrg } 1314706f2543Smrg memmove(new_closure->data, new_closure->pElt, len); 1315706f2543Smrg new_closure->pElt = new_closure->data; 1316706f2543Smrg new_closure->endReq = new_closure->pElt + len; 1317706f2543Smrg 1318706f2543Smrg /* Step 2 */ 1319706f2543Smrg 1320706f2543Smrg pGC = GetScratchGC(new_closure->pGC->depth, new_closure->pGC->pScreen); 1321706f2543Smrg if (!pGC) 1322706f2543Smrg { 1323706f2543Smrg free(new_closure->data); 1324706f2543Smrg free(new_closure); 1325706f2543Smrg err = BadAlloc; 1326706f2543Smrg goto bail; 1327706f2543Smrg } 1328706f2543Smrg if ((err = CopyGC(new_closure->pGC, pGC, GCFunction | 1329706f2543Smrg GCPlaneMask | GCForeground | 1330706f2543Smrg GCBackground | GCFillStyle | 1331706f2543Smrg GCTile | GCStipple | 1332706f2543Smrg GCTileStipXOrigin | 1333706f2543Smrg GCTileStipYOrigin | GCFont | 1334706f2543Smrg GCSubwindowMode | GCClipXOrigin | 1335706f2543Smrg GCClipYOrigin | GCClipMask)) != 1336706f2543Smrg Success) 1337706f2543Smrg { 1338706f2543Smrg FreeScratchGC(pGC); 1339706f2543Smrg free(new_closure->data); 1340706f2543Smrg free(new_closure); 1341706f2543Smrg err = BadAlloc; 1342706f2543Smrg goto bail; 1343706f2543Smrg } 1344706f2543Smrg c = new_closure; 1345706f2543Smrg origGC = c->pGC; 1346706f2543Smrg c->pGC = pGC; 1347706f2543Smrg ValidateGC(c->pDraw, c->pGC); 1348706f2543Smrg 1349706f2543Smrg ClientSleep(client, (ClientSleepProcPtr)doPolyText, c); 1350706f2543Smrg 1351706f2543Smrg /* Set up to perform steps 3 and 4 */ 1352706f2543Smrg client_state = START_SLEEP; 1353706f2543Smrg continue; /* on to steps 3 and 4 */ 1354706f2543Smrg } 1355706f2543Smrg else 1356706f2543Smrg goto xinerama_sleep; 1357706f2543Smrg return TRUE; 1358706f2543Smrg } 1359706f2543Smrg else if (lgerr != Successful) 1360706f2543Smrg { 1361706f2543Smrg err = FontToXError(lgerr); 1362706f2543Smrg goto bail; 1363706f2543Smrg } 1364706f2543Smrg if (c->pDraw) 1365706f2543Smrg { 1366706f2543Smrg c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */ 1367706f2543Smrg if (c->reqType == X_PolyText8) 1368706f2543Smrg c->xorg = (* c->pGC->ops->PolyText8)(c->pDraw, c->pGC, c->xorg, c->yorg, 1369706f2543Smrg *c->pElt, (char *) (c->pElt + TextEltHeader)); 1370706f2543Smrg else 1371706f2543Smrg c->xorg = (* c->pGC->ops->PolyText16)(c->pDraw, c->pGC, c->xorg, c->yorg, 1372706f2543Smrg *c->pElt, (unsigned short *) (c->pElt + TextEltHeader)); 1373706f2543Smrg } 1374706f2543Smrg c->pElt = pNextElt; 1375706f2543Smrg } 1376706f2543Smrg } 1377706f2543Smrg 1378706f2543Smrgbail: 1379706f2543Smrg 1380706f2543Smrg if (client_state == START_SLEEP) 1381706f2543Smrg { 1382706f2543Smrg /* Step 4 */ 1383706f2543Smrg if (pFont != origGC->font) 1384706f2543Smrg { 1385706f2543Smrg ChangeGCVal val; 1386706f2543Smrg val.ptr = pFont; 1387706f2543Smrg ChangeGC(NullClient, origGC, GCFont, &val); 1388706f2543Smrg ValidateGC(c->pDraw, origGC); 1389706f2543Smrg } 1390706f2543Smrg 1391706f2543Smrg /* restore pElt pointer for execution of remainder of the request */ 1392706f2543Smrg c->pElt = c->data; 1393706f2543Smrg return TRUE; 1394706f2543Smrg } 1395706f2543Smrg 1396706f2543Smrg if (c->err != Success) err = c->err; 1397706f2543Smrg if (err != Success && c->client != serverClient) { 1398706f2543Smrg#ifdef PANORAMIX 1399706f2543Smrg if (noPanoramiXExtension || !c->pGC->pScreen->myNum) 1400706f2543Smrg#endif 1401706f2543Smrg SendErrorToClient(c->client, c->reqType, 0, 0, err); 1402706f2543Smrg } 1403706f2543Smrg if (ClientIsAsleep(client)) 1404706f2543Smrg { 1405706f2543Smrg ClientWakeup(c->client); 1406706f2543Smrgxinerama_sleep: 1407706f2543Smrg ChangeGC(NullClient, c->pGC, clearGCmask, clearGC); 1408706f2543Smrg 1409706f2543Smrg /* Unreference the font from the scratch GC */ 1410706f2543Smrg CloseFont(c->pGC->font, (Font)0); 1411706f2543Smrg c->pGC->font = NullFont; 1412706f2543Smrg 1413706f2543Smrg FreeScratchGC(c->pGC); 1414706f2543Smrg free(c->data); 1415706f2543Smrg free(c); 1416706f2543Smrg } 1417706f2543Smrg return TRUE; 1418706f2543Smrg} 1419706f2543Smrg 1420706f2543Smrgint 1421706f2543SmrgPolyText(ClientPtr client, DrawablePtr pDraw, GC *pGC, unsigned char *pElt, 1422706f2543Smrg unsigned char *endReq, int xorg, int yorg, int reqType, XID did) 1423706f2543Smrg{ 1424706f2543Smrg PTclosureRec local_closure; 1425706f2543Smrg 1426706f2543Smrg local_closure.pElt = pElt; 1427706f2543Smrg local_closure.endReq = endReq; 1428706f2543Smrg local_closure.client = client; 1429706f2543Smrg local_closure.pDraw = pDraw; 1430706f2543Smrg local_closure.xorg = xorg; 1431706f2543Smrg local_closure.yorg = yorg; 1432706f2543Smrg local_closure.reqType = reqType; 1433706f2543Smrg local_closure.pGC = pGC; 1434706f2543Smrg local_closure.did = did; 1435706f2543Smrg local_closure.err = Success; 1436706f2543Smrg 1437706f2543Smrg (void) doPolyText(client, &local_closure); 1438706f2543Smrg return Success; 1439706f2543Smrg} 1440706f2543Smrg 1441706f2543Smrg 1442706f2543Smrg#undef TextEltHeader 1443706f2543Smrg#undef FontShiftSize 1444706f2543Smrg 1445706f2543Smrgint 1446706f2543SmrgdoImageText(ClientPtr client, ITclosurePtr c) 1447706f2543Smrg{ 1448706f2543Smrg int err = Success, lgerr; /* err is in X error, not font error, space */ 1449706f2543Smrg FontPathElementPtr fpe; 1450706f2543Smrg int itemSize = c->reqType == X_ImageText8 ? 1 : 2; 1451706f2543Smrg 1452706f2543Smrg if (client->clientGone) 1453706f2543Smrg { 1454706f2543Smrg fpe = c->pGC->font->fpe; 1455706f2543Smrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 1456706f2543Smrg err = Success; 1457706f2543Smrg goto bail; 1458706f2543Smrg } 1459706f2543Smrg 1460706f2543Smrg /* Make sure our drawable hasn't disappeared while we slept. */ 1461706f2543Smrg if (ClientIsAsleep(client) && c->pDraw) 1462706f2543Smrg { 1463706f2543Smrg DrawablePtr pDraw; 1464706f2543Smrg dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess); 1465706f2543Smrg if (c->pDraw != pDraw) { 1466706f2543Smrg /* Our drawable has disappeared. Treat like client died... ask 1467706f2543Smrg the FPE code to clean up after client. */ 1468706f2543Smrg fpe = c->pGC->font->fpe; 1469706f2543Smrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 1470706f2543Smrg err = Success; 1471706f2543Smrg goto bail; 1472706f2543Smrg } 1473706f2543Smrg } 1474706f2543Smrg 1475706f2543Smrg lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, itemSize, c->data); 1476706f2543Smrg if (lgerr == Suspended) 1477706f2543Smrg { 1478706f2543Smrg if (!ClientIsAsleep(client)) { 1479706f2543Smrg GC *pGC; 1480706f2543Smrg unsigned char *data; 1481706f2543Smrg ITclosurePtr new_closure; 1482706f2543Smrg ITclosurePtr old_closure; 1483706f2543Smrg 1484706f2543Smrg /* We're putting the client to sleep. We need to 1485706f2543Smrg save some state. Similar problem to that handled 1486706f2543Smrg in doPolyText, but much simpler because the 1487706f2543Smrg request structure is much simpler. */ 1488706f2543Smrg 1489706f2543Smrg new_closure = malloc(sizeof(ITclosureRec)); 1490706f2543Smrg if (!new_closure) 1491706f2543Smrg { 1492706f2543Smrg err = BadAlloc; 1493706f2543Smrg goto bail; 1494706f2543Smrg } 1495706f2543Smrg old_closure = c; 1496706f2543Smrg *new_closure = *c; 1497706f2543Smrg c = new_closure; 1498706f2543Smrg 1499706f2543Smrg data = malloc(c->nChars * itemSize); 1500706f2543Smrg if (!data) 1501706f2543Smrg { 1502706f2543Smrg free(c); 1503706f2543Smrg c = old_closure; 1504706f2543Smrg err = BadAlloc; 1505706f2543Smrg goto bail; 1506706f2543Smrg } 1507706f2543Smrg memmove(data, c->data, c->nChars * itemSize); 1508706f2543Smrg c->data = data; 1509706f2543Smrg 1510706f2543Smrg pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen); 1511706f2543Smrg if (!pGC) 1512706f2543Smrg { 1513706f2543Smrg free(c->data); 1514706f2543Smrg free(c); 1515706f2543Smrg c = old_closure; 1516706f2543Smrg err = BadAlloc; 1517706f2543Smrg goto bail; 1518706f2543Smrg } 1519706f2543Smrg if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask | 1520706f2543Smrg GCForeground | GCBackground | GCFillStyle | 1521706f2543Smrg GCTile | GCStipple | GCTileStipXOrigin | 1522706f2543Smrg GCTileStipYOrigin | GCFont | 1523706f2543Smrg GCSubwindowMode | GCClipXOrigin | 1524706f2543Smrg GCClipYOrigin | GCClipMask)) != Success) 1525706f2543Smrg { 1526706f2543Smrg FreeScratchGC(pGC); 1527706f2543Smrg free(c->data); 1528706f2543Smrg free(c); 1529706f2543Smrg c = old_closure; 1530706f2543Smrg err = BadAlloc; 1531706f2543Smrg goto bail; 1532706f2543Smrg } 1533706f2543Smrg c->pGC = pGC; 1534706f2543Smrg ValidateGC(c->pDraw, c->pGC); 1535706f2543Smrg 1536706f2543Smrg ClientSleep(client, (ClientSleepProcPtr)doImageText, c); 1537706f2543Smrg } 1538706f2543Smrg else 1539706f2543Smrg goto xinerama_sleep; 1540706f2543Smrg return TRUE; 1541706f2543Smrg } 1542706f2543Smrg else if (lgerr != Successful) 1543706f2543Smrg { 1544706f2543Smrg err = FontToXError(lgerr); 1545706f2543Smrg goto bail; 1546706f2543Smrg } 1547706f2543Smrg if (c->pDraw) 1548706f2543Smrg { 1549706f2543Smrg if (c->reqType == X_ImageText8) 1550706f2543Smrg (* c->pGC->ops->ImageText8)(c->pDraw, c->pGC, c->xorg, c->yorg, 1551706f2543Smrg c->nChars, (char *) c->data); 1552706f2543Smrg else 1553706f2543Smrg (* c->pGC->ops->ImageText16)(c->pDraw, c->pGC, c->xorg, c->yorg, 1554706f2543Smrg c->nChars, (unsigned short *) c->data); 1555706f2543Smrg } 1556706f2543Smrg 1557706f2543Smrgbail: 1558706f2543Smrg 1559706f2543Smrg if (err != Success && c->client != serverClient) { 1560706f2543Smrg SendErrorToClient(c->client, c->reqType, 0, 0, err); 1561706f2543Smrg } 1562706f2543Smrg if (ClientIsAsleep(client)) 1563706f2543Smrg { 1564706f2543Smrg ClientWakeup(c->client); 1565706f2543Smrgxinerama_sleep: 1566706f2543Smrg ChangeGC(NullClient, c->pGC, clearGCmask, clearGC); 1567706f2543Smrg 1568706f2543Smrg /* Unreference the font from the scratch GC */ 1569706f2543Smrg CloseFont(c->pGC->font, (Font)0); 1570706f2543Smrg c->pGC->font = NullFont; 1571706f2543Smrg 1572706f2543Smrg FreeScratchGC(c->pGC); 1573706f2543Smrg free(c->data); 1574706f2543Smrg free(c); 1575706f2543Smrg } 1576706f2543Smrg return TRUE; 1577706f2543Smrg} 1578706f2543Smrg 1579706f2543Smrgint 1580706f2543SmrgImageText(ClientPtr client, DrawablePtr pDraw, GC *pGC, int nChars, 1581706f2543Smrg unsigned char *data, int xorg, int yorg, int reqType, XID did) 1582706f2543Smrg{ 1583706f2543Smrg ITclosureRec local_closure; 1584706f2543Smrg 1585706f2543Smrg local_closure.client = client; 1586706f2543Smrg local_closure.pDraw = pDraw; 1587706f2543Smrg local_closure.pGC = pGC; 1588706f2543Smrg local_closure.nChars = nChars; 1589706f2543Smrg local_closure.data = data; 1590706f2543Smrg local_closure.xorg = xorg; 1591706f2543Smrg local_closure.yorg = yorg; 1592706f2543Smrg local_closure.reqType = reqType; 1593706f2543Smrg local_closure.did = did; 1594706f2543Smrg 1595706f2543Smrg (void) doImageText(client, &local_closure); 1596706f2543Smrg return Success; 1597706f2543Smrg} 1598706f2543Smrg 1599706f2543Smrg 1600706f2543Smrg/* does the necessary magic to figure out the fpe type */ 1601706f2543Smrgstatic int 1602706f2543SmrgDetermineFPEType(char *pathname) 1603706f2543Smrg{ 1604706f2543Smrg int i; 1605706f2543Smrg 1606706f2543Smrg for (i = 0; i < num_fpe_types; i++) { 1607706f2543Smrg if ((*fpe_functions[i].name_check) (pathname)) 1608706f2543Smrg return i; 1609706f2543Smrg } 1610706f2543Smrg return -1; 1611706f2543Smrg} 1612706f2543Smrg 1613706f2543Smrg 1614706f2543Smrgstatic void 1615706f2543SmrgFreeFontPath(FontPathElementPtr *list, int n, Bool force) 1616706f2543Smrg{ 1617706f2543Smrg int i; 1618706f2543Smrg 1619706f2543Smrg for (i = 0; i < n; i++) { 1620706f2543Smrg if (force) { 1621706f2543Smrg /* Sanity check that all refcounts will be 0 by the time 1622706f2543Smrg we get to the end of the list. */ 1623706f2543Smrg int found = 1; /* the first reference is us */ 1624706f2543Smrg int j; 1625706f2543Smrg for (j = i+1; j < n; j++) { 1626706f2543Smrg if (list[j] == list[i]) 1627706f2543Smrg found++; 1628706f2543Smrg } 1629706f2543Smrg if (list[i]->refcount != found) { 1630706f2543Smrg list[i]->refcount = found; /* ensure it will get freed */ 1631706f2543Smrg } 1632706f2543Smrg } 1633706f2543Smrg FreeFPE(list[i]); 1634706f2543Smrg } 1635706f2543Smrg free(list); 1636706f2543Smrg} 1637706f2543Smrg 1638706f2543Smrgstatic FontPathElementPtr 1639706f2543Smrgfind_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len) 1640706f2543Smrg{ 1641706f2543Smrg FontPathElementPtr fpe; 1642706f2543Smrg int i; 1643706f2543Smrg 1644706f2543Smrg for (i = 0; i < num; i++) { 1645706f2543Smrg fpe = list[i]; 1646706f2543Smrg if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0) 1647706f2543Smrg return fpe; 1648706f2543Smrg } 1649706f2543Smrg return (FontPathElementPtr) 0; 1650706f2543Smrg} 1651706f2543Smrg 1652706f2543Smrg 1653706f2543Smrgstatic int 1654706f2543SmrgSetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist) 1655706f2543Smrg{ 1656706f2543Smrg int i, err = 0; 1657706f2543Smrg int valid_paths = 0; 1658706f2543Smrg unsigned int len; 1659706f2543Smrg unsigned char *cp = paths; 1660706f2543Smrg FontPathElementPtr fpe = NULL, *fplist; 1661706f2543Smrg 1662706f2543Smrg fplist = malloc(sizeof(FontPathElementPtr) * npaths); 1663706f2543Smrg if (!fplist) { 1664706f2543Smrg *bad = 0; 1665706f2543Smrg return BadAlloc; 1666706f2543Smrg } 1667706f2543Smrg for (i = 0; i < num_fpe_types; i++) { 1668706f2543Smrg if (fpe_functions[i].set_path_hook) 1669706f2543Smrg (*fpe_functions[i].set_path_hook) (); 1670706f2543Smrg } 1671706f2543Smrg for (i = 0; i < npaths; i++) 1672706f2543Smrg { 1673706f2543Smrg len = (unsigned int) (*cp++); 1674706f2543Smrg 1675706f2543Smrg if (len == 0) 1676706f2543Smrg { 1677706f2543Smrg if (persist) 1678706f2543Smrg ErrorF("[dix] Removing empty element from the valid list of fontpaths\n"); 1679706f2543Smrg err = BadValue; 1680706f2543Smrg } 1681706f2543Smrg else 1682706f2543Smrg { 1683706f2543Smrg /* if it's already in our active list, just reset it */ 1684706f2543Smrg /* 1685706f2543Smrg * note that this can miss FPE's in limbo -- may be worth catching 1686706f2543Smrg * them, though it'd muck up refcounting 1687706f2543Smrg */ 1688706f2543Smrg fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len); 1689706f2543Smrg if (fpe) 1690706f2543Smrg { 1691706f2543Smrg err = (*fpe_functions[fpe->type].reset_fpe) (fpe); 1692706f2543Smrg if (err == Successful) 1693706f2543Smrg { 1694706f2543Smrg UseFPE(fpe);/* since it'll be decref'd later when freed 1695706f2543Smrg * from the old list */ 1696706f2543Smrg } 1697706f2543Smrg else 1698706f2543Smrg fpe = 0; 1699706f2543Smrg } 1700706f2543Smrg /* if error or can't do it, act like it's a new one */ 1701706f2543Smrg if (!fpe) 1702706f2543Smrg { 1703706f2543Smrg fpe = malloc(sizeof(FontPathElementRec)); 1704706f2543Smrg if (!fpe) 1705706f2543Smrg { 1706706f2543Smrg err = BadAlloc; 1707706f2543Smrg goto bail; 1708706f2543Smrg } 1709706f2543Smrg fpe->name = malloc(len + 1); 1710706f2543Smrg if (!fpe->name) 1711706f2543Smrg { 1712706f2543Smrg free(fpe); 1713706f2543Smrg err = BadAlloc; 1714706f2543Smrg goto bail; 1715706f2543Smrg } 1716706f2543Smrg fpe->refcount = 1; 1717706f2543Smrg 1718706f2543Smrg strncpy(fpe->name, (char *) cp, (int) len); 1719706f2543Smrg fpe->name[len] = '\0'; 1720706f2543Smrg fpe->name_length = len; 1721706f2543Smrg fpe->type = DetermineFPEType(fpe->name); 1722706f2543Smrg if (fpe->type == -1) 1723706f2543Smrg err = BadValue; 1724706f2543Smrg else 1725706f2543Smrg err = (*fpe_functions[fpe->type].init_fpe) (fpe); 1726706f2543Smrg if (err != Successful) 1727706f2543Smrg { 1728706f2543Smrg if (persist) 1729706f2543Smrg { 1730706f2543Smrg ErrorF("[dix] Could not init font path element %s, removing from list!\n", 1731706f2543Smrg fpe->name); 1732706f2543Smrg } 1733706f2543Smrg free(fpe->name); 1734706f2543Smrg free(fpe); 1735706f2543Smrg } 1736706f2543Smrg } 1737706f2543Smrg } 1738706f2543Smrg if (err != Successful) 1739706f2543Smrg { 1740706f2543Smrg if (!persist) 1741706f2543Smrg goto bail; 1742706f2543Smrg } 1743706f2543Smrg else 1744706f2543Smrg { 1745706f2543Smrg fplist[valid_paths++] = fpe; 1746706f2543Smrg } 1747706f2543Smrg cp += len; 1748706f2543Smrg } 1749706f2543Smrg 1750706f2543Smrg FreeFontPath(font_path_elements, num_fpes, FALSE); 1751706f2543Smrg font_path_elements = fplist; 1752706f2543Smrg if (patternCache) 1753706f2543Smrg EmptyFontPatternCache(patternCache); 1754706f2543Smrg num_fpes = valid_paths; 1755706f2543Smrg 1756706f2543Smrg return Success; 1757706f2543Smrgbail: 1758706f2543Smrg *bad = i; 1759706f2543Smrg while (--valid_paths >= 0) 1760706f2543Smrg FreeFPE(fplist[valid_paths]); 1761706f2543Smrg free(fplist); 1762706f2543Smrg return FontToXError(err); 1763706f2543Smrg} 1764706f2543Smrg 1765706f2543Smrgint 1766706f2543SmrgSetFontPath(ClientPtr client, int npaths, unsigned char *paths) 1767706f2543Smrg{ 1768706f2543Smrg int err = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess); 1769706f2543Smrg if (err != Success) 1770706f2543Smrg return err; 1771706f2543Smrg 1772706f2543Smrg if (npaths == 0) { 1773706f2543Smrg if (SetDefaultFontPath(defaultFontPath) != Success) 1774706f2543Smrg return BadValue; 1775706f2543Smrg } else { 1776706f2543Smrg int bad; 1777706f2543Smrg err = SetFontPathElements(npaths, paths, &bad, FALSE); 1778706f2543Smrg client->errorValue = bad; 1779706f2543Smrg } 1780706f2543Smrg return err; 1781706f2543Smrg} 1782706f2543Smrg 1783706f2543Smrgint 1784706f2543SmrgSetDefaultFontPath(char *path) 1785706f2543Smrg{ 1786706f2543Smrg char *temp_path, 1787706f2543Smrg *start, 1788706f2543Smrg *end; 1789706f2543Smrg unsigned char *cp, 1790706f2543Smrg *pp, 1791706f2543Smrg *nump, 1792706f2543Smrg *newpath; 1793706f2543Smrg int num = 1, 1794706f2543Smrg len, 1795706f2543Smrg err, 1796706f2543Smrg size = 0, 1797706f2543Smrg bad; 1798706f2543Smrg 1799706f2543Smrg /* ensure temp_path contains "built-ins" */ 1800706f2543Smrg start = path; 1801706f2543Smrg while (1) { 1802706f2543Smrg start = strstr(start, "built-ins"); 1803706f2543Smrg if (start == NULL) 1804706f2543Smrg break; 1805706f2543Smrg end = start + strlen("built-ins"); 1806706f2543Smrg if ((start == path || start[-1] == ',') && (!*end || *end == ',')) 1807706f2543Smrg break; 1808706f2543Smrg start = end; 1809706f2543Smrg } 1810706f2543Smrg if (!start) { 1811706f2543Smrg if (asprintf(&temp_path, "%s%sbuilt-ins", path, *path ? "," : "") 1812706f2543Smrg == -1) 1813706f2543Smrg temp_path = NULL; 1814706f2543Smrg } else { 1815706f2543Smrg temp_path = strdup(path); 1816706f2543Smrg } 1817706f2543Smrg if (!temp_path) 1818706f2543Smrg return BadAlloc; 1819706f2543Smrg 1820706f2543Smrg /* get enough for string, plus values -- use up commas */ 1821706f2543Smrg len = strlen(temp_path) + 1; 1822706f2543Smrg nump = cp = newpath = malloc(len); 1823706f2543Smrg if (!newpath) { 1824706f2543Smrg free(temp_path); 1825706f2543Smrg return BadAlloc; 1826706f2543Smrg } 1827706f2543Smrg pp = (unsigned char *) temp_path; 1828706f2543Smrg cp++; 1829706f2543Smrg while (*pp) { 1830706f2543Smrg if (*pp == ',') { 1831706f2543Smrg *nump = (unsigned char) size; 1832706f2543Smrg nump = cp++; 1833706f2543Smrg pp++; 1834706f2543Smrg num++; 1835706f2543Smrg size = 0; 1836706f2543Smrg } else { 1837706f2543Smrg *cp++ = *pp++; 1838706f2543Smrg size++; 1839706f2543Smrg } 1840706f2543Smrg } 1841706f2543Smrg *nump = (unsigned char) size; 1842706f2543Smrg 1843706f2543Smrg err = SetFontPathElements(num, newpath, &bad, TRUE); 1844706f2543Smrg 1845706f2543Smrg free(newpath); 1846706f2543Smrg free(temp_path); 1847706f2543Smrg 1848706f2543Smrg return err; 1849706f2543Smrg} 1850706f2543Smrg 1851706f2543Smrgint 1852706f2543SmrgGetFontPath(ClientPtr client, int *count, int *length, unsigned char **result) 1853706f2543Smrg{ 1854706f2543Smrg int i; 1855706f2543Smrg unsigned char *c; 1856706f2543Smrg int len; 1857706f2543Smrg FontPathElementPtr fpe; 1858706f2543Smrg 1859706f2543Smrg i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess); 1860706f2543Smrg if (i != Success) 1861706f2543Smrg return i; 1862706f2543Smrg 1863706f2543Smrg len = 0; 1864706f2543Smrg for (i = 0; i < num_fpes; i++) { 1865706f2543Smrg fpe = font_path_elements[i]; 1866706f2543Smrg len += fpe->name_length + 1; 1867706f2543Smrg } 1868706f2543Smrg font_path_string = (unsigned char *) realloc(font_path_string, len); 1869706f2543Smrg if (!font_path_string) 1870706f2543Smrg return BadAlloc; 1871706f2543Smrg 1872706f2543Smrg c = font_path_string; 1873706f2543Smrg *length = 0; 1874706f2543Smrg for (i = 0; i < num_fpes; i++) { 1875706f2543Smrg fpe = font_path_elements[i]; 1876706f2543Smrg *c = fpe->name_length; 1877706f2543Smrg *length += *c++; 1878706f2543Smrg memmove(c, fpe->name, fpe->name_length); 1879706f2543Smrg c += fpe->name_length; 1880706f2543Smrg } 1881706f2543Smrg *count = num_fpes; 1882706f2543Smrg *result = font_path_string; 1883706f2543Smrg return Success; 1884706f2543Smrg} 1885706f2543Smrg 1886706f2543Smrgvoid 1887706f2543SmrgDeleteClientFontStuff(ClientPtr client) 1888706f2543Smrg{ 1889706f2543Smrg int i; 1890706f2543Smrg FontPathElementPtr fpe; 1891706f2543Smrg 1892706f2543Smrg for (i = 0; i < num_fpes; i++) 1893706f2543Smrg { 1894706f2543Smrg fpe = font_path_elements[i]; 1895706f2543Smrg if (fpe_functions[fpe->type].client_died) 1896706f2543Smrg (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe); 1897706f2543Smrg } 1898706f2543Smrg} 1899706f2543Smrg 1900706f2543Smrgvoid 1901706f2543SmrgInitFonts (void) 1902706f2543Smrg{ 1903706f2543Smrg patternCache = MakeFontPatternCache(); 1904706f2543Smrg 1905706f2543Smrg register_fpe_functions(); 1906706f2543Smrg} 1907706f2543Smrg 1908706f2543Smrgint 1909706f2543SmrgGetDefaultPointSize (void) 1910706f2543Smrg{ 1911706f2543Smrg return 120; 1912706f2543Smrg} 1913706f2543Smrg 1914706f2543Smrg 1915706f2543SmrgFontResolutionPtr 1916706f2543SmrgGetClientResolutions (int *num) 1917706f2543Smrg{ 1918706f2543Smrg static struct _FontResolution res; 1919706f2543Smrg ScreenPtr pScreen; 1920706f2543Smrg 1921706f2543Smrg pScreen = screenInfo.screens[0]; 1922706f2543Smrg res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth; 1923706f2543Smrg /* 1924706f2543Smrg * XXX - we'll want this as long as bitmap instances are prevalent 1925706f2543Smrg so that we can match them from scalable fonts 1926706f2543Smrg */ 1927706f2543Smrg if (res.x_resolution < 88) 1928706f2543Smrg res.x_resolution = 75; 1929706f2543Smrg else 1930706f2543Smrg res.x_resolution = 100; 1931706f2543Smrg res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight; 1932706f2543Smrg if (res.y_resolution < 88) 1933706f2543Smrg res.y_resolution = 75; 1934706f2543Smrg else 1935706f2543Smrg res.y_resolution = 100; 1936706f2543Smrg res.point_size = 120; 1937706f2543Smrg *num = 1; 1938706f2543Smrg return &res; 1939706f2543Smrg} 1940706f2543Smrg 1941706f2543Smrg/* 1942706f2543Smrg * returns the type index of the new fpe 1943706f2543Smrg * 1944706f2543Smrg * should be called (only once!) by each type of fpe when initialized 1945706f2543Smrg */ 1946706f2543Smrg 1947706f2543Smrgint 1948706f2543SmrgRegisterFPEFunctions(NameCheckFunc name_func, 1949706f2543Smrg InitFpeFunc init_func, 1950706f2543Smrg FreeFpeFunc free_func, 1951706f2543Smrg ResetFpeFunc reset_func, 1952706f2543Smrg OpenFontFunc open_func, 1953706f2543Smrg CloseFontFunc close_func, 1954706f2543Smrg ListFontsFunc list_func, 1955706f2543Smrg StartLfwiFunc start_lfwi_func, 1956706f2543Smrg NextLfwiFunc next_lfwi_func, 1957706f2543Smrg WakeupFpeFunc wakeup_func, 1958706f2543Smrg ClientDiedFunc client_died, 1959706f2543Smrg LoadGlyphsFunc load_glyphs, 1960706f2543Smrg StartLaFunc start_list_alias_func, 1961706f2543Smrg NextLaFunc next_list_alias_func, 1962706f2543Smrg SetPathFunc set_path_func) 1963706f2543Smrg{ 1964706f2543Smrg FPEFunctions *new; 1965706f2543Smrg 1966706f2543Smrg /* grow the list */ 1967706f2543Smrg new = (FPEFunctions *) realloc(fpe_functions, 1968706f2543Smrg (num_fpe_types + 1) * sizeof(FPEFunctions)); 1969706f2543Smrg if (!new) 1970706f2543Smrg return -1; 1971706f2543Smrg fpe_functions = new; 1972706f2543Smrg 1973706f2543Smrg fpe_functions[num_fpe_types].name_check = name_func; 1974706f2543Smrg fpe_functions[num_fpe_types].open_font = open_func; 1975706f2543Smrg fpe_functions[num_fpe_types].close_font = close_func; 1976706f2543Smrg fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func; 1977706f2543Smrg fpe_functions[num_fpe_types].list_fonts = list_func; 1978706f2543Smrg fpe_functions[num_fpe_types].start_list_fonts_with_info = 1979706f2543Smrg start_lfwi_func; 1980706f2543Smrg fpe_functions[num_fpe_types].list_next_font_with_info = 1981706f2543Smrg next_lfwi_func; 1982706f2543Smrg fpe_functions[num_fpe_types].init_fpe = init_func; 1983706f2543Smrg fpe_functions[num_fpe_types].free_fpe = free_func; 1984706f2543Smrg fpe_functions[num_fpe_types].reset_fpe = reset_func; 1985706f2543Smrg fpe_functions[num_fpe_types].client_died = client_died; 1986706f2543Smrg fpe_functions[num_fpe_types].load_glyphs = load_glyphs; 1987706f2543Smrg fpe_functions[num_fpe_types].start_list_fonts_and_aliases = 1988706f2543Smrg start_list_alias_func; 1989706f2543Smrg fpe_functions[num_fpe_types].list_next_font_or_alias = 1990706f2543Smrg next_list_alias_func; 1991706f2543Smrg fpe_functions[num_fpe_types].set_path_hook = set_path_func; 1992706f2543Smrg 1993706f2543Smrg return num_fpe_types++; 1994706f2543Smrg} 1995706f2543Smrg 1996706f2543Smrgvoid 1997706f2543SmrgFreeFonts(void) 1998706f2543Smrg{ 1999706f2543Smrg if (patternCache) { 2000706f2543Smrg FreeFontPatternCache(patternCache); 2001706f2543Smrg patternCache = 0; 2002706f2543Smrg } 2003706f2543Smrg FreeFontPath(font_path_elements, num_fpes, TRUE); 2004706f2543Smrg font_path_elements = 0; 2005706f2543Smrg num_fpes = 0; 2006706f2543Smrg free(fpe_functions); 2007706f2543Smrg num_fpe_types = 0; 2008706f2543Smrg fpe_functions = (FPEFunctions *) 0; 2009706f2543Smrg} 2010706f2543Smrg 2011706f2543Smrg/* convenience functions for FS interface */ 2012706f2543Smrg 2013706f2543SmrgFontPtr 2014706f2543Smrgfind_old_font(XID id) 2015706f2543Smrg{ 2016706f2543Smrg pointer pFont; 2017706f2543Smrg dixLookupResourceByType(&pFont, id, RT_NONE, serverClient, DixReadAccess); 2018706f2543Smrg return (FontPtr)pFont; 2019706f2543Smrg} 2020706f2543Smrg 2021706f2543SmrgFont 2022706f2543SmrgGetNewFontClientID(void) 2023706f2543Smrg{ 2024706f2543Smrg return FakeClientID(0); 2025706f2543Smrg} 2026706f2543Smrg 2027706f2543Smrgint 2028706f2543SmrgStoreFontClientFont(FontPtr pfont, Font id) 2029706f2543Smrg{ 2030706f2543Smrg return AddResource(id, RT_NONE, (pointer) pfont); 2031706f2543Smrg} 2032706f2543Smrg 2033706f2543Smrgvoid 2034706f2543SmrgDeleteFontClientID(Font id) 2035706f2543Smrg{ 2036706f2543Smrg FreeResource(id, RT_NONE); 2037706f2543Smrg} 2038706f2543Smrg 2039706f2543Smrgint 2040706f2543Smrgclient_auth_generation(ClientPtr client) 2041706f2543Smrg{ 2042706f2543Smrg return 0; 2043706f2543Smrg} 2044706f2543Smrg 2045706f2543Smrgstatic int fs_handlers_installed = 0; 2046706f2543Smrgstatic unsigned int last_server_gen; 2047706f2543Smrg 2048706f2543Smrgint 2049706f2543Smrginit_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler) 2050706f2543Smrg{ 2051706f2543Smrg /* if server has reset, make sure the b&w handlers are reinstalled */ 2052706f2543Smrg if (last_server_gen < serverGeneration) { 2053706f2543Smrg last_server_gen = serverGeneration; 2054706f2543Smrg fs_handlers_installed = 0; 2055706f2543Smrg } 2056706f2543Smrg if (fs_handlers_installed == 0) { 2057706f2543Smrg if (!RegisterBlockAndWakeupHandlers(block_handler, 2058706f2543Smrg FontWakeup, (pointer) 0)) 2059706f2543Smrg return AllocError; 2060706f2543Smrg fs_handlers_installed++; 2061706f2543Smrg } 2062706f2543Smrg QueueFontWakeup(fpe); 2063706f2543Smrg return Successful; 2064706f2543Smrg} 2065706f2543Smrg 2066706f2543Smrgvoid 2067706f2543Smrgremove_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler, Bool all) 2068706f2543Smrg{ 2069706f2543Smrg if (all) { 2070706f2543Smrg /* remove the handlers if no one else is using them */ 2071706f2543Smrg if (--fs_handlers_installed == 0) { 2072706f2543Smrg RemoveBlockAndWakeupHandlers(block_handler, FontWakeup, 2073706f2543Smrg (pointer) 0); 2074706f2543Smrg } 2075706f2543Smrg } 2076706f2543Smrg RemoveFontWakeup(fpe); 2077706f2543Smrg} 2078