PageRenderTime 34ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/nx-3.5.0/nx-X11/programs/Xserver/hw/nxagent/NXdixfonts.c

#
C | 2883 lines | 2331 code | 258 blank | 294 comment | 421 complexity | d562051342b9992d93a2940cc22bb875 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. #ifdef NXAGENT_UPGRADE
  2. #include "X/NXdixfonts.c"
  3. #else
  4. /**************************************************************************/
  5. /* */
  6. /* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
  7. /* */
  8. /* NXAGENT, NX protocol compression and NX extensions to this software */
  9. /* are copyright of NoMachine. Redistribution and use of the present */
  10. /* software is allowed according to terms specified in the file LICENSE */
  11. /* which comes in the source distribution. */
  12. /* */
  13. /* Check http://www.nomachine.com/licensing.html for applicability. */
  14. /* */
  15. /* NX and NoMachine are trademarks of Medialogic S.p.A. */
  16. /* */
  17. /* All rights reserved. */
  18. /* */
  19. /**************************************************************************/
  20. /* $XFree86: xc/programs/Xserver/dix/dixfonts.c,v 3.27 2003/02/15 03:47:05 dawes Exp $ */
  21. /************************************************************************
  22. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
  23. All Rights Reserved
  24. Permission to use, copy, modify, and distribute this software and its
  25. documentation for any purpose and without fee is hereby granted,
  26. provided that the above copyright notice appear in all copies and that
  27. both that copyright notice and this permission notice appear in
  28. supporting documentation, and that the name of Digital not be
  29. used in advertising or publicity pertaining to distribution of the
  30. software without specific, written prior permission.
  31. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  32. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  33. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  34. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  35. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  36. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  37. SOFTWARE.
  38. ************************************************************************/
  39. /* $Xorg: dixfonts.c,v 1.4 2000/08/17 19:48:18 cpqbld Exp $ */
  40. #define NEED_REPLIES
  41. #include "X.h"
  42. #include "Xmd.h"
  43. #include "Xproto.h"
  44. #include "scrnintstr.h"
  45. #include "resource.h"
  46. #include "dixstruct.h"
  47. #include "cursorstr.h"
  48. #include "misc.h"
  49. #include "opaque.h"
  50. #include "dixfontstr.h"
  51. #include "closestr.h"
  52. /*
  53. #define NXAGENT_DEBUG
  54. */
  55. #ifdef DEBUG
  56. #include <stdio.h>
  57. #endif
  58. #include "Agent.h"
  59. #include "Font.h"
  60. #ifndef NX_TRANS_SOCKET
  61. #define NX_TRANS_SOCKET
  62. #endif
  63. #ifdef NX_TRANS_SOCKET
  64. char _NXFontPath[1024];
  65. /*
  66. * Override the default font path and make
  67. * it configurable at run time, based on
  68. * the NX_FONT environment.
  69. */
  70. static const char *_NXGetFontPath(const char *path)
  71. {
  72. const char *fontEnv;
  73. /*
  74. * Check the environment only once.
  75. */
  76. if (*_NXFontPath != '\0')
  77. {
  78. return _NXFontPath;
  79. }
  80. fontEnv = getenv("NX_FONT");
  81. if (fontEnv != NULL && *fontEnv != '\0')
  82. {
  83. if (strlen(fontEnv) + 1 > 1024)
  84. {
  85. #ifdef NX_TRANS_TEST
  86. fprintf(stderr, "_NXGetFontPath: WARNING! Maximum length of font path exceeded.\n");
  87. #endif
  88. goto _NXGetFontPathError;
  89. }
  90. strcpy(_NXFontPath, fontEnv);
  91. #ifdef NX_TRANS_TEST
  92. fprintf(stderr, "_NXGetFontPath: Using NX font path [%s].\n", _NXFontPath);
  93. #endif
  94. return _NXFontPath;
  95. }
  96. _NXGetFontPathError:
  97. strcpy(_NXFontPath, path);
  98. #ifdef NX_TRANS_TEST
  99. fprintf(stderr, "_NXGetFontPath: Using default font path [%s].\n", _NXFontPath);
  100. #endif
  101. return _NXFontPath;
  102. }
  103. #endif
  104. #ifdef PANORAMIX
  105. #include "../../Xext/panoramiX.h"
  106. #include "../../Xext/panoramiXsrv.h"
  107. #endif
  108. #ifdef LBX
  109. #include "lbxserve.h"
  110. #endif
  111. #ifdef XF86BIGFONT
  112. #define _XF86BIGFONT_SERVER_
  113. #include "xf86bigfont.h"
  114. #endif
  115. #define QUERYCHARINFO(pci, pr) *(pr) = (pci)->metrics
  116. extern pointer fosNaturalParams;
  117. extern FontPtr defaultFont;
  118. static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0;
  119. static int num_fpes = 0;
  120. FPEFunctions *fpe_functions = (FPEFunctions *) 0;
  121. static int num_fpe_types = 0;
  122. static unsigned char *font_path_string;
  123. static int num_slept_fpes = 0;
  124. static int size_slept_fpes = 0;
  125. static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0;
  126. static FontPatternCachePtr patternCache;
  127. int
  128. FontToXError(err)
  129. int err;
  130. {
  131. switch (err) {
  132. case Successful:
  133. return Success;
  134. case AllocError:
  135. return BadAlloc;
  136. case BadFontName:
  137. return BadName;
  138. case BadFontPath:
  139. case BadFontFormat: /* is there something better? */
  140. case BadCharRange:
  141. return BadValue;
  142. default:
  143. return err;
  144. }
  145. }
  146. /*
  147. * adding RT_FONT prevents conflict with default cursor font
  148. */
  149. Bool
  150. SetDefaultFont(defaultfontname)
  151. char *defaultfontname;
  152. {
  153. int err;
  154. FontPtr pf;
  155. XID fid;
  156. fid = FakeClientID(0);
  157. err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync,
  158. (unsigned) strlen(defaultfontname), defaultfontname);
  159. if (err != Success)
  160. return FALSE;
  161. pf = (FontPtr) LookupIDByType(fid, RT_FONT);
  162. if (pf == (FontPtr) NULL)
  163. return FALSE;
  164. defaultFont = pf;
  165. return TRUE;
  166. }
  167. /*
  168. * note that the font wakeup queue is not refcounted. this is because
  169. * an fpe needs to be added when it's inited, and removed when it's finally
  170. * freed, in order to handle any data that isn't requested, like FS events.
  171. *
  172. * since the only thing that should call these routines is the renderer's
  173. * init_fpe() and free_fpe(), there shouldn't be any problem in using
  174. * freed data.
  175. */
  176. void
  177. QueueFontWakeup(fpe)
  178. FontPathElementPtr fpe;
  179. {
  180. int i;
  181. FontPathElementPtr *new;
  182. for (i = 0; i < num_slept_fpes; i++) {
  183. if (slept_fpes[i] == fpe) {
  184. #ifdef DEBUG
  185. fprintf(stderr, "re-queueing fpe wakeup\n");
  186. #endif
  187. return;
  188. }
  189. }
  190. if (num_slept_fpes == size_slept_fpes) {
  191. new = (FontPathElementPtr *)
  192. xrealloc(slept_fpes,
  193. sizeof(FontPathElementPtr) * (size_slept_fpes + 4));
  194. if (!new)
  195. return;
  196. slept_fpes = new;
  197. size_slept_fpes += 4;
  198. }
  199. slept_fpes[num_slept_fpes] = fpe;
  200. num_slept_fpes++;
  201. }
  202. void
  203. RemoveFontWakeup(fpe)
  204. FontPathElementPtr fpe;
  205. {
  206. int i,
  207. j;
  208. for (i = 0; i < num_slept_fpes; i++) {
  209. if (slept_fpes[i] == fpe) {
  210. for (j = i; j < num_slept_fpes; j++) {
  211. slept_fpes[j] = slept_fpes[j + 1];
  212. }
  213. num_slept_fpes--;
  214. return;
  215. }
  216. }
  217. }
  218. /* ARGSUSED */
  219. void
  220. FontWakeup(data, count, LastSelectMask)
  221. pointer data;
  222. int count;
  223. pointer LastSelectMask;
  224. {
  225. int i;
  226. FontPathElementPtr fpe;
  227. if (count < 0)
  228. return;
  229. /* wake up any fpe's that may be waiting for information */
  230. for (i = 0; i < num_slept_fpes; i++) {
  231. fpe = slept_fpes[i];
  232. (void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask);
  233. }
  234. }
  235. /* XXX -- these two funcs may want to be broken into macros */
  236. static void
  237. #if NeedFunctionPrototypes
  238. UseFPE(FontPathElementPtr fpe)
  239. #else
  240. UseFPE(fpe)
  241. FontPathElementPtr fpe;
  242. #endif
  243. {
  244. fpe->refcount++;
  245. }
  246. static void
  247. #if NeedFunctionPrototypes
  248. FreeFPE (FontPathElementPtr fpe)
  249. #else
  250. FreeFPE (fpe)
  251. FontPathElementPtr fpe;
  252. #endif
  253. {
  254. fpe->refcount--;
  255. if (fpe->refcount == 0) {
  256. (*fpe_functions[fpe->type].free_fpe) (fpe);
  257. xfree(fpe->name);
  258. xfree(fpe);
  259. }
  260. }
  261. static Bool
  262. #if NeedFunctionPrototypes
  263. doOpenFont(ClientPtr client, OFclosurePtr c)
  264. #else
  265. doOpenFont(client, c)
  266. ClientPtr client;
  267. OFclosurePtr c;
  268. #endif
  269. {
  270. FontPtr pfont = NullFont;
  271. FontPathElementPtr fpe = NULL;
  272. ScreenPtr pScr;
  273. int err = Successful;
  274. int i;
  275. char *alias,
  276. *newname;
  277. int newlen;
  278. int aliascount = 20;
  279. char nxagentOrigFontName[256];
  280. int nxagentOrigFontNameLen;
  281. /*
  282. * Decide at runtime what FontFormat to use.
  283. */
  284. Mask FontFormat =
  285. ((screenInfo.imageByteOrder == LSBFirst) ?
  286. BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) |
  287. ((screenInfo.bitmapBitOrder == LSBFirst) ?
  288. BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) |
  289. BitmapFormatImageRectMin |
  290. #if GLYPHPADBYTES == 1
  291. BitmapFormatScanlinePad8 |
  292. #endif
  293. #if GLYPHPADBYTES == 2
  294. BitmapFormatScanlinePad16 |
  295. #endif
  296. #if GLYPHPADBYTES == 4
  297. BitmapFormatScanlinePad32 |
  298. #endif
  299. #if GLYPHPADBYTES == 8
  300. BitmapFormatScanlinePad64 |
  301. #endif
  302. BitmapFormatScanlineUnit8;
  303. nxagentOrigFontNameLen = (c -> origFontNameLen < 256) ? c -> origFontNameLen : 255;
  304. memcpy(nxagentOrigFontName, c -> origFontName, nxagentOrigFontNameLen);
  305. nxagentOrigFontName[nxagentOrigFontNameLen] = 0;
  306. if (client->clientGone)
  307. {
  308. if (c->current_fpe < c->num_fpes)
  309. {
  310. fpe = c->fpe_list[c->current_fpe];
  311. (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
  312. }
  313. err = Successful;
  314. goto bail;
  315. }
  316. while (c->current_fpe < c->num_fpes) {
  317. fpe = c->fpe_list[c->current_fpe];
  318. err = (*fpe_functions[fpe->type].open_font)
  319. ((pointer) client, fpe, c->flags,
  320. c->fontname, c->fnamelen, FontFormat,
  321. BitmapFormatMaskByte |
  322. BitmapFormatMaskBit |
  323. BitmapFormatMaskImageRectangle |
  324. BitmapFormatMaskScanLinePad |
  325. BitmapFormatMaskScanLineUnit,
  326. c->fontid, &pfont, &alias,
  327. c->non_cachable_font && c->non_cachable_font->fpe == fpe ?
  328. c->non_cachable_font :
  329. (FontPtr)0);
  330. if (err == FontNameAlias && alias) {
  331. newlen = strlen(alias);
  332. newname = (char *) xrealloc(c->fontname, newlen);
  333. if (!newname) {
  334. err = AllocError;
  335. break;
  336. }
  337. memmove(newname, alias, newlen);
  338. c->fontname = newname;
  339. c->fnamelen = newlen;
  340. c->current_fpe = 0;
  341. if (--aliascount <= 0)
  342. break;
  343. continue;
  344. }
  345. if (err == BadFontName) {
  346. c->current_fpe++;
  347. continue;
  348. }
  349. if (err == Suspended) {
  350. if (!c->slept) {
  351. c->slept = TRUE;
  352. ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c);
  353. #ifdef NXAGENT_DEBUG
  354. fprintf(stderr, " NXdixfonts: doOpenFont: client [%lx] sleeping.\n", client);
  355. #endif
  356. }
  357. return TRUE;
  358. }
  359. break;
  360. }
  361. if (err != Successful)
  362. goto bail;
  363. if (!pfont) {
  364. err = BadFontName;
  365. goto bail;
  366. }
  367. if (!pfont->fpe)
  368. pfont->fpe = fpe;
  369. pfont->refcnt++;
  370. if (pfont->refcnt == 1) {
  371. UseFPE(pfont->fpe);
  372. for (i = 0; i < screenInfo.numScreens; i++) {
  373. pScr = screenInfo.screens[i];
  374. if (pScr->RealizeFont)
  375. {
  376. /* NXAGENT uses useless screen pointer to pass the original font name
  377. * to realizeFont, could be a source of problems in the future.
  378. */
  379. if (!(*pScr->RealizeFont) ((ScreenPtr)nxagentOrigFontName, pfont))
  380. {
  381. CloseFont (pfont, (Font) 0);
  382. err=BadFontName;
  383. goto bail;
  384. }
  385. }
  386. }
  387. }
  388. if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) {
  389. err = AllocError;
  390. goto bail;
  391. }
  392. if( nxagentFontPriv(pfont) -> mirrorID == 0 )
  393. {
  394. extern RESTYPE RT_NX_FONT;
  395. nxagentFontPriv(pfont) -> mirrorID = FakeClientID(0);
  396. if (!AddResource(nxagentFontPriv(pfont) -> mirrorID, RT_NX_FONT, (pointer) pfont)) {
  397. FreeResource(c->fontid, RT_NONE);
  398. err = AllocError;
  399. goto bail;
  400. }
  401. }
  402. if (patternCache && pfont != c->non_cachable_font)
  403. CacheFontPattern(patternCache, nxagentOrigFontName, nxagentOrigFontNameLen,
  404. pfont);
  405. bail:
  406. if (err != Successful && c->client != serverClient) {
  407. SendErrorToClient(c->client, X_OpenFont, 0,
  408. c->fontid, FontToXError(err));
  409. }
  410. if (c->slept)
  411. {
  412. ClientWakeup(c->client);
  413. #ifdef NXAGENT_DEBUG
  414. fprintf(stderr, " NXdixfonts: doOpenFont: client [%lx] wakeup.\n", client);
  415. #endif
  416. }
  417. for (i = 0; i < c->num_fpes; i++) {
  418. FreeFPE(c->fpe_list[i]);
  419. }
  420. xfree(c->fpe_list);
  421. xfree(c->fontname);
  422. xfree(c);
  423. return TRUE;
  424. }
  425. int
  426. OpenFont(client, fid, flags, lenfname, pfontname)
  427. ClientPtr client;
  428. XID fid;
  429. Mask flags;
  430. unsigned lenfname;
  431. char *pfontname;
  432. {
  433. OFclosurePtr c;
  434. int i;
  435. FontPtr cached = (FontPtr)0;
  436. #ifdef FONTDEBUG
  437. char *f;
  438. f = (char *)xalloc(lenfname + 1);
  439. memmove(f, pfontname, lenfname);
  440. f[lenfname] = '\0';
  441. ErrorF("OpenFont: fontname is \"%s\"\n", f);
  442. xfree(f);
  443. #endif
  444. if (!lenfname || lenfname > XLFDMAXFONTNAMELEN)
  445. return BadName;
  446. if (patternCache)
  447. {
  448. /*
  449. ** Check name cache. If we find a cached version of this font that
  450. ** is cachable, immediately satisfy the request with it. If we find
  451. ** a cached version of this font that is non-cachable, we do not
  452. ** satisfy the request with it. Instead, we pass the FontPtr to the
  453. ** FPE's open_font code (the fontfile FPE in turn passes the
  454. ** information to the rasterizer; the fserve FPE ignores it).
  455. **
  456. ** Presumably, the font is marked non-cachable because the FPE has
  457. ** put some licensing restrictions on it. If the FPE, using
  458. ** whatever logic it relies on, determines that it is willing to
  459. ** share this existing font with the client, then it has the option
  460. ** to return the FontPtr we passed it as the newly-opened font.
  461. ** This allows the FPE to exercise its licensing logic without
  462. ** having to create another instance of a font that already exists.
  463. */
  464. cached = FindCachedFontPattern(patternCache, pfontname, lenfname);
  465. if (cached && cached->info.cachable)
  466. {
  467. if (!AddResource(fid, RT_FONT, (pointer) cached))
  468. return BadAlloc;
  469. cached->refcnt++;
  470. return Success;
  471. }
  472. }
  473. c = (OFclosurePtr) xalloc(sizeof(OFclosureRec));
  474. if (!c)
  475. return BadAlloc;
  476. c->fontname = (char *) xalloc(lenfname);
  477. c->origFontName = pfontname;
  478. c->origFontNameLen = lenfname;
  479. if (!c->fontname) {
  480. xfree(c);
  481. return BadAlloc;
  482. }
  483. /*
  484. * copy the current FPE list, so that if it gets changed by another client
  485. * while we're blocking, the request still appears atomic
  486. */
  487. c->fpe_list = (FontPathElementPtr *)
  488. xalloc(sizeof(FontPathElementPtr) * num_fpes);
  489. if (!c->fpe_list) {
  490. xfree(c->fontname);
  491. xfree(c);
  492. return BadAlloc;
  493. }
  494. memmove(c->fontname, pfontname, lenfname);
  495. for (i = 0; i < num_fpes; i++) {
  496. c->fpe_list[i] = font_path_elements[i];
  497. UseFPE(c->fpe_list[i]);
  498. }
  499. c->client = client;
  500. c->fontid = fid;
  501. c->current_fpe = 0;
  502. c->num_fpes = num_fpes;
  503. c->fnamelen = lenfname;
  504. c->slept = FALSE;
  505. c->flags = flags;
  506. c->non_cachable_font = cached;
  507. (void) doOpenFont(client, c);
  508. return Success;
  509. }
  510. /*
  511. * Decrement font's ref count, and free storage if ref count equals zero
  512. */
  513. /*ARGSUSED*/
  514. int
  515. CloseFont(value, fid)
  516. pointer value; /* must conform to DeleteType */
  517. XID fid;
  518. {
  519. int nscr;
  520. ScreenPtr pscr;
  521. FontPathElementPtr fpe;
  522. FontPtr pfont = (FontPtr)value;
  523. if (pfont == NullFont)
  524. return (Success);
  525. if (--pfont->refcnt == 0) {
  526. if (patternCache)
  527. RemoveCachedFontPattern (patternCache, pfont);
  528. /*
  529. * since the last reference is gone, ask each screen to free any
  530. * storage it may have allocated locally for it.
  531. */
  532. for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
  533. pscr = screenInfo.screens[nscr];
  534. if (pscr->UnrealizeFont)
  535. (*pscr->UnrealizeFont) (pscr, pfont);
  536. }
  537. if (pfont == defaultFont)
  538. defaultFont = NULL;
  539. #ifdef LBX
  540. LbxFreeFontTag(pfont);
  541. #endif
  542. #ifdef XF86BIGFONT
  543. {
  544. extern void XF86BigfontFreeFontShm(FontPtr);
  545. XF86BigfontFreeFontShm(pfont);
  546. }
  547. #endif
  548. fpe = pfont->fpe;
  549. (*fpe_functions[fpe->type].close_font) (fpe, pfont);
  550. FreeFPE(fpe);
  551. }
  552. return (Success);
  553. }
  554. /***====================================================================***/
  555. /*
  556. * \ Sets up pReply as the correct QueryFontReply for pFont with the first
  557. * nProtoCCIStructs char infos. \
  558. */
  559. void
  560. QueryFont(pFont, pReply, nProtoCCIStructs)
  561. FontPtr pFont;
  562. xQueryFontReply *pReply; /* caller must allocate this storage */
  563. int nProtoCCIStructs;
  564. {
  565. FontPropPtr pFP;
  566. int r,
  567. c,
  568. i;
  569. xFontProp *prFP;
  570. xCharInfo *prCI;
  571. xCharInfo *charInfos[256];
  572. unsigned char chars[512];
  573. int ninfos;
  574. unsigned long ncols;
  575. unsigned long count;
  576. /* pr->length set in dispatch */
  577. pReply->minCharOrByte2 = pFont->info.firstCol;
  578. pReply->defaultChar = pFont->info.defaultCh;
  579. pReply->maxCharOrByte2 = pFont->info.lastCol;
  580. pReply->drawDirection = pFont->info.drawDirection;
  581. pReply->allCharsExist = pFont->info.allExist;
  582. pReply->minByte1 = pFont->info.firstRow;
  583. pReply->maxByte1 = pFont->info.lastRow;
  584. pReply->fontAscent = pFont->info.fontAscent;
  585. pReply->fontDescent = pFont->info.fontDescent;
  586. pReply->minBounds = pFont->info.ink_minbounds;
  587. pReply->maxBounds = pFont->info.ink_maxbounds;
  588. pReply->nFontProps = pFont->info.nprops;
  589. pReply->nCharInfos = nProtoCCIStructs;
  590. for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]);
  591. i < pFont->info.nprops;
  592. i++, pFP++, prFP++) {
  593. prFP->name = pFP->name;
  594. prFP->value = pFP->value;
  595. }
  596. ninfos = 0;
  597. ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1);
  598. prCI = (xCharInfo *) (prFP);
  599. for (r = pFont->info.firstRow;
  600. ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow;
  601. r++) {
  602. i = 0;
  603. for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) {
  604. chars[i++] = r;
  605. chars[i++] = c;
  606. }
  607. (*pFont->get_metrics) (pFont, ncols, chars,
  608. TwoD16Bit, &count, charInfos);
  609. i = 0;
  610. for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) {
  611. *prCI = *charInfos[i];
  612. prCI++;
  613. ninfos++;
  614. }
  615. }
  616. return;
  617. }
  618. static Bool
  619. #if NeedFunctionPrototypes
  620. doListFontsAndAliases(ClientPtr client, LFclosurePtr c)
  621. #else
  622. doListFontsAndAliases(client, c)
  623. ClientPtr client;
  624. LFclosurePtr c;
  625. #endif
  626. {
  627. FontPathElementPtr fpe;
  628. int err = Successful;
  629. FontNamesPtr names = NULL;
  630. char *name, *resolved=NULL;
  631. int namelen, resolvedlen;
  632. int nnames;
  633. int stringLens;
  634. int i;
  635. xListFontsReply reply;
  636. char *bufptr;
  637. char *bufferStart;
  638. int aliascount = 0;
  639. if (client->clientGone)
  640. {
  641. if (c->current.current_fpe < c->num_fpes)
  642. {
  643. fpe = c->fpe_list[c->current.current_fpe];
  644. (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
  645. }
  646. err = Successful;
  647. goto bail;
  648. }
  649. if (!c->current.patlen)
  650. goto finish;
  651. while (c->current.current_fpe < c->num_fpes) {
  652. fpe = c->fpe_list[c->current.current_fpe];
  653. err = Successful;
  654. if (!fpe_functions[fpe->type].start_list_fonts_and_aliases)
  655. {
  656. /* This FPE doesn't support/require list_fonts_and_aliases */
  657. err = (*fpe_functions[fpe->type].list_fonts)
  658. ((pointer) c->client, fpe, c->current.pattern,
  659. c->current.patlen, c->current.max_names - c->names->nnames,
  660. c->names);
  661. if (err == Suspended) {
  662. if (!c->slept) {
  663. c->slept = TRUE;
  664. ClientSleep(client,
  665. (ClientSleepProcPtr)doListFontsAndAliases,
  666. (pointer) c);
  667. #ifdef NXAGENT_DEBUG
  668. fprintf(stderr, " NXdixfonts: doListFont (1): client [%lx] sleeping.\n", client);
  669. #endif
  670. }
  671. return TRUE;
  672. }
  673. err = BadFontName;
  674. }
  675. else
  676. {
  677. /* Start of list_fonts_and_aliases functionality. Modeled
  678. after list_fonts_with_info in that it resolves aliases,
  679. except that the information collected from FPEs is just
  680. names, not font info. Each list_next_font_or_alias()
  681. returns either a name into name/namelen or an alias into
  682. name/namelen and its target name into resolved/resolvedlen.
  683. The code at this level then resolves the alias by polling
  684. the FPEs. */
  685. if (!c->current.list_started) {
  686. err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases)
  687. ((pointer) c->client, fpe, c->current.pattern,
  688. c->current.patlen, c->current.max_names - c->names->nnames,
  689. &c->current.private);
  690. if (err == Suspended) {
  691. if (!c->slept) {
  692. ClientSleep(client,
  693. (ClientSleepProcPtr)doListFontsAndAliases,
  694. (pointer) c);
  695. c->slept = TRUE;
  696. #ifdef NXAGENT_DEBUG
  697. fprintf(stderr, " NXdixfonts: doListFont (2): client [%lx] sleeping.\n", client);
  698. #endif
  699. }
  700. return TRUE;
  701. }
  702. if (err == Successful)
  703. c->current.list_started = TRUE;
  704. }
  705. if (err == Successful) {
  706. char *tmpname;
  707. name = 0;
  708. err = (*fpe_functions[fpe->type].list_next_font_or_alias)
  709. ((pointer) c->client, fpe, &name, &namelen, &tmpname,
  710. &resolvedlen, c->current.private);
  711. if (err == Suspended) {
  712. if (!c->slept) {
  713. ClientSleep(client,
  714. (ClientSleepProcPtr)doListFontsAndAliases,
  715. (pointer) c);
  716. c->slept = TRUE;
  717. #ifdef NXAGENT_DEBUG
  718. fprintf(stderr, " NXdixfonts: doListFont (3): client [%lx] sleeping.\n", client);
  719. #endif
  720. }
  721. return TRUE;
  722. }
  723. if (err == FontNameAlias) {
  724. if (resolved) xfree(resolved);
  725. resolved = (char *) xalloc(resolvedlen + 1);
  726. if (resolved)
  727. memmove(resolved, tmpname, resolvedlen + 1);
  728. }
  729. }
  730. if (err == Successful)
  731. {
  732. if (c->haveSaved)
  733. {
  734. if (c->savedName)
  735. (void)AddFontNamesName(c->names, c->savedName,
  736. c->savedNameLen);
  737. }
  738. else
  739. (void)AddFontNamesName(c->names, name, namelen);
  740. }
  741. /*
  742. * When we get an alias back, save our state and reset back to
  743. * the start of the FPE looking for the specified name. As
  744. * soon as a real font is found for the alias, pop back to the
  745. * old state
  746. */
  747. else if (err == FontNameAlias) {
  748. char tmp_pattern[XLFDMAXFONTNAMELEN];
  749. /*
  750. * when an alias recurses, we need to give
  751. * the last FPE a chance to clean up; so we call
  752. * it again, and assume that the error returned
  753. * is BadFontName, indicating the alias resolution
  754. * is complete.
  755. */
  756. memmove(tmp_pattern, resolved, resolvedlen);
  757. if (c->haveSaved)
  758. {
  759. char *tmpname;
  760. int tmpnamelen;
  761. tmpname = 0;
  762. (void) (*fpe_functions[fpe->type].list_next_font_or_alias)
  763. ((pointer) c->client, fpe, &tmpname, &tmpnamelen,
  764. &tmpname, &tmpnamelen, c->current.private);
  765. if (--aliascount <= 0)
  766. {
  767. err = BadFontName;
  768. goto ContBadFontName;
  769. }
  770. }
  771. else
  772. {
  773. c->saved = c->current;
  774. c->haveSaved = TRUE;
  775. if (c->savedName)
  776. xfree(c->savedName);
  777. c->savedName = (char *)xalloc(namelen + 1);
  778. if (c->savedName)
  779. memmove(c->savedName, name, namelen + 1);
  780. c->savedNameLen = namelen;
  781. aliascount = 20;
  782. }
  783. memmove(c->current.pattern, tmp_pattern, resolvedlen);
  784. c->current.patlen = resolvedlen;
  785. c->current.max_names = c->names->nnames + 1;
  786. c->current.current_fpe = -1;
  787. c->current.private = 0;
  788. err = BadFontName;
  789. }
  790. }
  791. /*
  792. * At the end of this FPE, step to the next. If we've finished
  793. * processing an alias, pop state back. If we've collected enough
  794. * font names, quit.
  795. */
  796. if (err == BadFontName) {
  797. ContBadFontName: ;
  798. c->current.list_started = FALSE;
  799. c->current.current_fpe++;
  800. err = Successful;
  801. if (c->haveSaved)
  802. {
  803. if (c->names->nnames == c->current.max_names ||
  804. c->current.current_fpe == c->num_fpes) {
  805. c->haveSaved = FALSE;
  806. c->current = c->saved;
  807. /* Give the saved namelist a chance to clean itself up */
  808. continue;
  809. }
  810. }
  811. if (c->names->nnames == c->current.max_names)
  812. break;
  813. }
  814. }
  815. /*
  816. * send the reply
  817. */
  818. if (err != Successful) {
  819. SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err));
  820. goto bail;
  821. }
  822. finish:
  823. names = c->names;
  824. nnames = names->nnames;
  825. client = c->client;
  826. stringLens = 0;
  827. for (i = 0; i < nnames; i++)
  828. stringLens += (names->length[i] <= 255) ? names->length[i] : 0;
  829. reply.type = X_Reply;
  830. reply.length = (stringLens + nnames + 3) >> 2;
  831. reply.nFonts = nnames;
  832. reply.sequenceNumber = client->sequence;
  833. bufptr = bufferStart = (char *) ALLOCATE_LOCAL(reply.length << 2);
  834. if (!bufptr && reply.length) {
  835. SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc);
  836. goto bail;
  837. }
  838. /*
  839. * since WriteToClient long word aligns things, copy to temp buffer and
  840. * write all at once
  841. */
  842. for (i = 0; i < nnames; i++) {
  843. if (names->length[i] > 255)
  844. reply.nFonts--;
  845. else
  846. {
  847. {
  848. /* dirty hack: don't list to client fonts not existing on the remote side */
  849. char tmp[256];
  850. memcpy(tmp, names->names[i], names->length[i]);
  851. tmp[ names->length[i] ] = 0;
  852. if (nxagentFontLookUp(tmp) == 0)
  853. {
  854. #ifdef NXAGENT_FONTMATCH_DEBUG
  855. fprintf(stderr, "doListFontsAndAliases:\n");
  856. fprintf(stderr, " removing font: %s \n", tmp);
  857. #endif
  858. reply.nFonts--;
  859. stringLens -= names->length[i];
  860. continue;
  861. }
  862. }
  863. *bufptr++ = names->length[i];
  864. memmove( bufptr, names->names[i], names->length[i]);
  865. bufptr += names->length[i];
  866. }
  867. }
  868. nnames = reply.nFonts;
  869. reply.length = (stringLens + nnames + 3) >> 2;
  870. client->pSwapReplyFunc = ReplySwapVector[X_ListFonts];
  871. WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply);
  872. (void) WriteToClient(client, stringLens + nnames, bufferStart);
  873. DEALLOCATE_LOCAL(bufferStart);
  874. bail:
  875. if (c->slept)
  876. {
  877. ClientWakeup(client);
  878. #ifdef NXAGENT_DEBUG
  879. fprintf(stderr, " NXdixfonts: doListFont: client [%lx] wakeup.\n", client);
  880. #endif
  881. }
  882. for (i = 0; i < c->num_fpes; i++)
  883. FreeFPE(c->fpe_list[i]);
  884. xfree(c->fpe_list);
  885. if (c->savedName) xfree(c->savedName);
  886. FreeFontNames(names);
  887. xfree(c);
  888. if (resolved) xfree(resolved);
  889. return TRUE;
  890. }
  891. int
  892. ListFonts(client, pattern, length, max_names)
  893. ClientPtr client;
  894. unsigned char *pattern;
  895. unsigned int length;
  896. unsigned int max_names;
  897. {
  898. int i;
  899. LFclosurePtr c;
  900. /*
  901. * The right error to return here would be BadName, however the
  902. * specification does not allow for a Name error on this request.
  903. * Perhaps a better solution would be to return a nil list, i.e.
  904. * a list containing zero fontnames.
  905. */
  906. if (length > XLFDMAXFONTNAMELEN)
  907. return BadAlloc;
  908. if (!(c = (LFclosurePtr) xalloc(sizeof *c)))
  909. return BadAlloc;
  910. c->fpe_list = (FontPathElementPtr *)
  911. xalloc(sizeof(FontPathElementPtr) * num_fpes);
  912. if (!c->fpe_list) {
  913. xfree(c);
  914. return BadAlloc;
  915. }
  916. c->names = MakeFontNamesRecord(max_names < nxagentMaxFontNames ? max_names : nxagentMaxFontNames);
  917. if (!c->names)
  918. {
  919. xfree(c->fpe_list);
  920. xfree(c);
  921. return BadAlloc;
  922. }
  923. memmove( c->current.pattern, pattern, length);
  924. for (i = 0; i < num_fpes; i++) {
  925. c->fpe_list[i] = font_path_elements[i];
  926. UseFPE(c->fpe_list[i]);
  927. }
  928. c->client = client;
  929. c->num_fpes = num_fpes;
  930. c->current.patlen = length;
  931. c->current.current_fpe = 0;
  932. c->current.max_names = max_names;
  933. c->current.list_started = FALSE;
  934. c->current.private = 0;
  935. c->haveSaved = FALSE;
  936. c->slept = FALSE;
  937. c->savedName = 0;
  938. doListFontsAndAliases(client, c);
  939. return Success;
  940. }
  941. int
  942. doListFontsWithInfo(client, c)
  943. ClientPtr client;
  944. LFWIclosurePtr c;
  945. {
  946. FontPathElementPtr fpe;
  947. int err = Successful;
  948. char *name;
  949. int namelen;
  950. int numFonts;
  951. FontInfoRec fontInfo,
  952. *pFontInfo;
  953. xListFontsWithInfoReply *reply;
  954. int length;
  955. xFontProp *pFP;
  956. int i;
  957. int aliascount = 0;
  958. xListFontsWithInfoReply finalReply;
  959. if (client->clientGone)
  960. {
  961. if (c->current.current_fpe < c->num_fpes)
  962. {
  963. fpe = c->fpe_list[c->current.current_fpe];
  964. (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
  965. }
  966. err = Successful;
  967. goto bail;
  968. }
  969. client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo];
  970. if (!c->current.patlen)
  971. goto finish;
  972. while (c->current.current_fpe < c->num_fpes)
  973. {
  974. fpe = c->fpe_list[c->current.current_fpe];
  975. err = Successful;
  976. if (!c->current.list_started)
  977. {
  978. err = (*fpe_functions[fpe->type].start_list_fonts_with_info)
  979. (client, fpe, c->current.pattern, c->current.patlen,
  980. c->current.max_names, &c->current.private);
  981. if (err == Suspended)
  982. {
  983. if (!c->slept)
  984. {
  985. ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c);
  986. c->slept = TRUE;
  987. #ifdef NXAGENT_DEBUG
  988. fprintf(stderr, " NXdixfonts: doListFontWinfo (1): client [%lx] sleeping.\n", client);
  989. #endif
  990. }
  991. return TRUE;
  992. }
  993. if (err == Successful)
  994. c->current.list_started = TRUE;
  995. }
  996. if (err == Successful)
  997. {
  998. name = 0;
  999. pFontInfo = &fontInfo;
  1000. err = (*fpe_functions[fpe->type].list_next_font_with_info)
  1001. (client, fpe, &name, &namelen, &pFontInfo,
  1002. &numFonts, c->current.private);
  1003. if (err == Suspended)
  1004. {
  1005. if (!c->slept)
  1006. {
  1007. ClientSleep(client,
  1008. (ClientSleepProcPtr)doListFontsWithInfo,
  1009. c);
  1010. c->slept = TRUE;
  1011. #ifdef NXAGENT_DEBUG
  1012. fprintf(stderr, " NXdixfonts: doListFontWinfo (2): client [%lx] sleeping.\n", client);
  1013. #endif
  1014. }
  1015. return TRUE;
  1016. }
  1017. }
  1018. /*
  1019. * When we get an alias back, save our state and reset back to the
  1020. * start of the FPE looking for the specified name. As soon as a real
  1021. * font is found for the alias, pop back to the old state
  1022. */
  1023. if (err == FontNameAlias)
  1024. {
  1025. /*
  1026. * when an alias recurses, we need to give
  1027. * the last FPE a chance to clean up; so we call
  1028. * it again, and assume that the error returned
  1029. * is BadFontName, indicating the alias resolution
  1030. * is complete.
  1031. */
  1032. if (c->haveSaved)
  1033. {
  1034. char *tmpname;
  1035. int tmpnamelen;
  1036. FontInfoPtr tmpFontInfo;
  1037. tmpname = 0;
  1038. tmpFontInfo = &fontInfo;
  1039. (void) (*fpe_functions[fpe->type].list_next_font_with_info)
  1040. (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo,
  1041. &numFonts, c->current.private);
  1042. if (--aliascount <= 0)
  1043. {
  1044. err = BadFontName;
  1045. goto ContBadFontName;
  1046. }
  1047. }
  1048. else
  1049. {
  1050. c->saved = c->current;
  1051. c->haveSaved = TRUE;
  1052. c->savedNumFonts = numFonts;
  1053. c->savedName = (char *) pFontInfo;
  1054. aliascount = 20;
  1055. }
  1056. memmove(c->current.pattern, name, namelen);
  1057. c->current.patlen = namelen;
  1058. c->current.max_names = 1;
  1059. c->current.current_fpe = 0;
  1060. c->current.private = 0;
  1061. c->current.list_started = FALSE;
  1062. }
  1063. /*
  1064. * At the end of this FPE, step to the next. If we've finished
  1065. * processing an alias, pop state back. If we've sent enough font
  1066. * names, quit. Always wait for BadFontName to let the FPE
  1067. * have a chance to clean up.
  1068. */
  1069. else if (err == BadFontName)
  1070. {
  1071. ContBadFontName: ;
  1072. c->current.list_started = FALSE;
  1073. c->current.current_fpe++;
  1074. err = Successful;
  1075. if (c->haveSaved)
  1076. {
  1077. if (c->current.max_names == 0 ||
  1078. c->current.current_fpe == c->num_fpes)
  1079. {
  1080. c->haveSaved = FALSE;
  1081. c->saved.max_names -= (1 - c->current.max_names);
  1082. c->current = c->saved;
  1083. }
  1084. }
  1085. else if (c->current.max_names == 0)
  1086. break;
  1087. }
  1088. else if (err == Successful)
  1089. {
  1090. if (c->haveSaved)
  1091. {
  1092. numFonts = c->savedNumFonts;
  1093. name = c->savedName;
  1094. namelen = strlen(name);
  1095. }
  1096. if (nxagentFontLookUp(name) == 0)
  1097. {
  1098. #ifdef NXAGENT_FONTMATCH_DEBUG
  1099. fprintf(stderr, "doListFontsAndAliases (with info):\n");
  1100. fprintf(stderr, " removing font: %s \n", name);
  1101. #endif
  1102. continue;
  1103. }
  1104. length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp);
  1105. reply = c->reply;
  1106. if (c->length < length)
  1107. {
  1108. reply = (xListFontsWithInfoReply *) xrealloc(c->reply, length);
  1109. if (!reply)
  1110. {
  1111. err = AllocError;
  1112. break;
  1113. }
  1114. c->reply = reply;
  1115. c->length = length;
  1116. }
  1117. reply->type = X_Reply;
  1118. reply->length = (sizeof *reply - sizeof(xGenericReply) +
  1119. pFontInfo->nprops * sizeof(xFontProp) +
  1120. namelen + 3) >> 2;
  1121. reply->sequenceNumber = client->sequence;
  1122. reply->nameLength = namelen;
  1123. reply->minBounds = pFontInfo->ink_minbounds;
  1124. reply->maxBounds = pFontInfo->ink_maxbounds;
  1125. reply->minCharOrByte2 = pFontInfo->firstCol;
  1126. reply->maxCharOrByte2 = pFontInfo->lastCol;
  1127. reply->defaultChar = pFontInfo->defaultCh;
  1128. reply->nFontProps = pFontInfo->nprops;
  1129. reply->drawDirection = pFontInfo->drawDirection;
  1130. reply->minByte1 = pFontInfo->firstRow;
  1131. reply->maxByte1 = pFontInfo->lastRow;
  1132. reply->allCharsExist = pFontInfo->allExist;
  1133. reply->fontAscent = pFontInfo->fontAscent;
  1134. reply->fontDescent = pFontInfo->fontDescent;
  1135. reply->nReplies = numFonts;
  1136. pFP = (xFontProp *) (reply + 1);
  1137. for (i = 0; i < pFontInfo->nprops; i++)
  1138. {
  1139. pFP->name = pFontInfo->props[i].name;
  1140. pFP->value = pFontInfo->props[i].value;
  1141. pFP++;
  1142. }
  1143. WriteSwappedDataToClient(client, length, reply);
  1144. (void) WriteToClient(client, namelen, name);
  1145. if (pFontInfo == &fontInfo)
  1146. {
  1147. xfree(fontInfo.props);
  1148. xfree(fontInfo.isStringProp);
  1149. }
  1150. --c->current.max_names;
  1151. }
  1152. }
  1153. finish:
  1154. length = sizeof(xListFontsWithInfoReply);
  1155. bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply));
  1156. finalReply.type = X_Reply;
  1157. finalReply.sequenceNumber = client->sequence;
  1158. finalReply.length = (sizeof(xListFontsWithInfoReply)
  1159. - sizeof(xGenericReply)) >> 2;
  1160. WriteSwappedDataToClient(client, length, &finalReply);
  1161. bail:
  1162. if (c->slept)
  1163. {
  1164. ClientWakeup(client);
  1165. #ifdef NXAGENT_DEBUG
  1166. fprintf(stderr, " NXdixfonts: doListFontWinfo: client [%lx] wakeup.\n", client);
  1167. #endif
  1168. }
  1169. for (i = 0; i < c->num_fpes; i++)
  1170. FreeFPE(c->fpe_list[i]);
  1171. xfree(c->reply);
  1172. xfree(c->fpe_list);
  1173. xfree(c);
  1174. return TRUE;
  1175. }
  1176. int
  1177. StartListFontsWithInfo(client, length, pattern, max_names)
  1178. ClientPtr client;
  1179. int length;
  1180. unsigned char *pattern;
  1181. int max_names;
  1182. {
  1183. int i;
  1184. LFWIclosurePtr c;
  1185. /*
  1186. * The right error to return here would be BadName, however the
  1187. * specification does not allow for a Name error on this request.
  1188. * Perhaps a better solution would be to return a nil list, i.e.
  1189. * a list containing zero fontnames.
  1190. */
  1191. if (length > XLFDMAXFONTNAMELEN)
  1192. return BadAlloc;
  1193. if (!(c = (LFWIclosurePtr) xalloc(sizeof *c)))
  1194. goto badAlloc;
  1195. c->fpe_list = (FontPathElementPtr *)
  1196. xalloc(sizeof(FontPathElementPtr) * num_fpes);
  1197. if (!c->fpe_list)
  1198. {
  1199. xfree(c);
  1200. goto badAlloc;
  1201. }
  1202. memmove(c->current.pattern, pattern, length);
  1203. for (i = 0; i < num_fpes; i++)
  1204. {
  1205. c->fpe_list[i] = font_path_elements[i];
  1206. UseFPE(c->fpe_list[i]);
  1207. }
  1208. c->client = client;
  1209. c->num_fpes = num_fpes;
  1210. c->reply = 0;
  1211. c->length = 0;
  1212. c->current.patlen = length;
  1213. c->current.current_fpe = 0;
  1214. c->current.max_names = max_names;
  1215. c->current.list_started = FALSE;
  1216. c->current.private = 0;
  1217. c->savedNumFonts = 0;
  1218. c->haveSaved = FALSE;
  1219. c->slept = FALSE;
  1220. doListFontsWithInfo(client, c);
  1221. return Success;
  1222. badAlloc:
  1223. return BadAlloc;
  1224. }
  1225. #define TextEltHeader 2
  1226. #define FontShiftSize 5
  1227. static XID clearGC[] = { CT_NONE };
  1228. #define clearGCmask (GCClipMask)
  1229. int
  1230. doPolyText(client, c)
  1231. ClientPtr client;
  1232. register PTclosurePtr c;
  1233. {
  1234. register FontPtr pFont = c->pGC->font, oldpFont;
  1235. Font fid, oldfid;
  1236. int err = Success, lgerr; /* err is in X error, not font error, space */
  1237. enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT;
  1238. FontPathElementPtr fpe;
  1239. GC *origGC = NULL;
  1240. if (client->clientGone)
  1241. {
  1242. fpe = c->pGC->font->fpe;
  1243. (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
  1244. if (c->slept)
  1245. {
  1246. /* Client has died, but we cannot bail out right now. We
  1247. need to clean up after the work we did when going to
  1248. sleep. Setting the drawable pointer to 0 makes this
  1249. happen without any attempts to render or perform other
  1250. unnecessary activities. */
  1251. c->pDraw = (DrawablePtr)0;
  1252. }
  1253. else
  1254. {
  1255. err = Success;
  1256. goto bail;
  1257. }
  1258. }
  1259. /* Make sure our drawable hasn't disappeared while we slept. */
  1260. if (c->slept &&
  1261. c->pDraw &&
  1262. c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did,
  1263. RC_DRAWABLE, SecurityWriteAccess))
  1264. {
  1265. /* Our drawable has disappeared. Treat like client died... ask
  1266. the FPE code to clean up after client and avoid further
  1267. rendering while we clean up after ourself. */
  1268. fpe = c->pGC->font->fpe;
  1269. (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
  1270. c->pDraw = (DrawablePtr)0;
  1271. }
  1272. client_state = c->slept ? SLEEPING : NEVER_SLEPT;
  1273. while (c->endReq - c->pElt > TextEltHeader)
  1274. {
  1275. if (*c->pElt == FontChange)
  1276. {
  1277. if (c->endReq - c->pElt < FontShiftSize)
  1278. {
  1279. err = BadLength;
  1280. goto bail;
  1281. }
  1282. oldpFont = pFont;
  1283. oldfid = fid;
  1284. fid = ((Font)*(c->pElt+4)) /* big-endian */
  1285. | ((Font)*(c->pElt+3)) << 8
  1286. | ((Font)*(c->pElt+2)) << 16
  1287. | ((Font)*(c->pElt+1)) << 24;
  1288. pFont = (FontPtr)SecurityLookupIDByType(client, fid, RT_FONT,
  1289. SecurityReadAccess);
  1290. if (!pFont)
  1291. {
  1292. client->errorValue = fid;
  1293. err = BadFont;
  1294. /* restore pFont and fid for step 4 (described below) */
  1295. pFont = oldpFont;
  1296. fid = oldfid;
  1297. /* If we're in START_SLEEP mode, the following step
  1298. shortens the request... in the unlikely event that
  1299. the fid somehow becomes valid before we come through
  1300. again to actually execute the polytext, which would
  1301. then mess up our refcounting scheme badly. */
  1302. c->err = err;
  1303. c->endReq = c->pElt;
  1304. goto bail;
  1305. }
  1306. /* Step 3 (described below) on our new font */
  1307. if (client_state == START_SLEEP)
  1308. pFont->refcnt++;
  1309. else
  1310. {
  1311. if (pFont != c->pGC->font && c->pDraw)
  1312. {
  1313. ChangeGC( c->pGC, GCFont, &fid);
  1314. ValidateGC(c->pDraw, c->pGC);
  1315. if (c->reqType == X_PolyText8)
  1316. c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8;
  1317. else
  1318. c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16;
  1319. }
  1320. /* Undo the refcnt++ we performed when going to sleep */
  1321. if (client_state == SLEEPING)
  1322. (void)CloseFont(c->pGC->font, (Font)0);
  1323. }
  1324. c->pElt += FontShiftSize;
  1325. }
  1326. else /* print a string */
  1327. {
  1328. unsigned char *pNextElt;
  1329. pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize;
  1330. if ( pNextElt > c->endReq)
  1331. {
  1332. err = BadLength;
  1333. goto bail;
  1334. }
  1335. if (client_state == START_SLEEP)
  1336. {
  1337. c->pElt = pNextElt;
  1338. continue;
  1339. }
  1340. if (c->pDraw)
  1341. {
  1342. lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize,
  1343. c->pElt + TextEltHeader);
  1344. }
  1345. else lgerr = Successful;
  1346. if (lgerr == Suspended)
  1347. {
  1348. if (!c->slept) {
  1349. int len;
  1350. GC *pGC;
  1351. PTclosurePtr new_closure;
  1352. /* We're putting the client to sleep. We need to do a few things
  1353. to ensure successful and atomic-appearing execution of the
  1354. remainder of the request. First, copy the remainder of the
  1355. request into a safe malloc'd area. Second, create a scratch GC
  1356. to use for the remainder of the request. Third, mark all fonts
  1357. referenced in the remainder of the request to prevent their
  1358. deallocation. Fourth, make the original GC look like the
  1359. request has completed... set its font to the final font value
  1360. from this request. These GC manipulations are for the unlikely
  1361. (but possible) event that some other client is using the GC.
  1362. Steps 3 and 4 are performed by running this procedure through
  1363. the remainder of the request in a special no-render mode
  1364. indicated by client_state = START_SLEEP. */
  1365. /* Step 1 */
  1366. /* Allocate a malloc'd closure structure to replace
  1367. the local one we were passed */
  1368. new_closure = (PTclosurePtr) xalloc(sizeof(PTclosureRec));
  1369. if (!new_closure)
  1370. {
  1371. err = BadAlloc;
  1372. goto bail;
  1373. }
  1374. *new_closure = *c;
  1375. c = new_closure;
  1376. len = c->endReq - c->pElt;
  1377. c->data = (unsigned char *)xalloc(len);
  1378. if (!c->data)
  1379. {
  1380. xfree(c);
  1381. err = BadAlloc;
  1382. goto bail;
  1383. }
  1384. memmove(c->data, c->pElt, len);
  1385. c->pElt = c->data;
  1386. c->endReq = c->pElt + len;
  1387. /* Step 2 */
  1388. pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
  1389. if (!pGC)
  1390. {
  1391. xfree(c->data);
  1392. xfree(c);
  1393. err = BadAlloc;
  1394. goto bail;
  1395. }
  1396. pGC->tileIsPixel = TRUE;
  1397. pGC->tile.pixel = 0;
  1398. pGC->stipple = NullPixmap;
  1399. if ((err = CopyGC(c->pGC, pGC, GCFunction |
  1400. GCPlaneMask | GCForeground |
  1401. GCBackground | GCFillStyle |
  1402. GCTile | GCStipple |
  1403. GCTileStipXOrigin |
  1404. GCTileStipYOrigin | GCFont |
  1405. GCSubwindowMode | GCClipXOrigin |
  1406. GCClipYOrigin | GCClipMask)) !=
  1407. Success)
  1408. {
  1409. FreeScratchGC(pGC);
  1410. xfree(c->data);
  1411. xfree(c);
  1412. err = BadAlloc;
  1413. goto bail;
  1414. }
  1415. origGC = c->pGC;
  1416. c->pGC = pGC;
  1417. ValidateGC(c->pDraw, c->pGC);
  1418. c->slept = TRUE;
  1419. ClientSleep(client,
  1420. (ClientSleepProcPtr)doPolyText,
  1421. (pointer) c);
  1422. #ifdef NXAGENT_DEBUG
  1423. fprintf(stderr, " NXdixfonts: doPolyText (1): client [%lx] sleeping.\n", client);
  1424. #endif
  1425. /* Set up to perform steps 3 and 4 */
  1426. client_state = START_SLEEP;
  1427. continue; /* on to steps 3 and 4 */
  1428. }
  1429. return TRUE;
  1430. }
  1431. else if (lgerr != Successful)
  1432. {
  1433. err = FontToXError(lgerr);
  1434. goto bail;
  1435. }
  1436. if (c->pDraw)
  1437. {
  1438. c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */
  1439. c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg,
  1440. *c->pElt, c->pElt + TextEltHeader);
  1441. }
  1442. c->pElt = pNextElt;
  1443. }
  1444. }
  1445. bail:
  1446. if (client_state == START_SLEEP)
  1447. {
  1448. /* Step 4 */
  1449. if (pFont != origGC->font)
  1450. {
  1451. ChangeGC(origGC, GCFont, &fid);
  1452. ValidateGC(c->pDraw, origGC);
  1453. }
  1454. /* restore pElt pointer for execution of remainder of the request */
  1455. c->pElt = c->data;
  1456. return TRUE;
  1457. }
  1458. if (c->err != Success) err = c->err;
  1459. if (err != Success && c->client != serverClient) {
  1460. #ifdef PANORAMIX
  1461. if (noPanoramiXExtension || !c->pGC->pScreen->myNum)
  1462. #endif
  1463. SendErrorToClient(c->client, c->reqType, 0, 0, err);
  1464. }
  1465. if (c->slept)
  1466. {
  1467. ClientWakeup(c->client);
  1468. #ifdef NXAGENT_DEBUG
  1469. fprintf(stderr, " NXdixfonts: doPolytext: client [%lx] wakeup.\n", client);
  1470. #endif
  1471. ChangeGC(c->pGC, clearGCmask, clearGC);
  1472. /* Unreference the font from the scratch GC */
  1473. CloseFont(c->pGC->font, (Font)0);
  1474. c->pGC->font = NullFont;
  1475. FreeScratchGC(c->pGC);
  1476. xfree(c->data);
  1477. xfree(c);
  1478. }
  1479. return TRUE;
  1480. }
  1481. int
  1482. PolyText(client, pDraw, pGC, pElt, endReq, xorg, yorg, reqType, did)
  1483. ClientPtr client;
  1484. DrawablePtr pDraw;
  1485. GC *pGC;
  1486. unsigned char *pElt;
  1487. unsigned char *endReq;
  1488. int xorg;
  1489. int yorg;
  1490. int reqType;
  1491. XID did;
  1492. {
  1493. PTclosureRec local_closure;
  1494. local_closure.pElt = pElt;
  1495. local_closure.endReq = endReq;
  1496. local_closure.client = client;
  1497. local_closure.pDraw = pDraw;
  1498. local_closure.xorg = xorg;
  1499. local_closure.yorg = yorg;
  1500. if ((local_closure.reqType = reqType) == X_PolyText8)
  1501. {
  1502. local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8;
  1503. local_closure.itemSize = 1;
  1504. }
  1505. else
  1506. {
  1507. local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText16;
  1508. local_closure.itemSize = 2;
  1509. }
  1510. local_closure.pGC = pGC;
  1511. local_closure.did = did;
  1512. local_closure.err = Success;
  1513. local_closure.slept = FALSE;
  1514. (void) doPolyText(client, &local_closure);
  1515. return Success;
  1516. }
  1517. #undef TextEltHeader
  1518. #undef FontShiftSize
  1519. int
  1520. doImageText(client, c)
  1521. ClientPtr client;
  1522. register ITclosurePtr c;
  1523. {
  1524. int err = Success, lgerr; /* err is in X error, not font error, space */
  1525. FontPathElementPtr fpe;
  1526. if (client->clientGone)
  1527. {
  1528. fpe = c->pGC->font->fpe;
  1529. (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
  1530. err = Success;
  1531. goto bail;
  1532. }
  1533. /* Make sure our drawable hasn't disappeared while we slept. */
  1534. if (c->slept &&
  1535. c->pDraw &&
  1536. c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did,
  1537. RC_DRAWABLE, SecurityWriteAccess))
  1538. {
  1539. /* Our drawable has disappeared. Treat like client died... ask
  1540. the FPE code to clean up after client. */
  1541. fpe = c->pGC->font->fpe;
  1542. (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
  1543. err = Success;
  1544. goto bail;
  1545. }
  1546. lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data);
  1547. if (lgerr == Suspended)
  1548. {
  1549. if (!c->slept) {
  1550. GC *pGC;
  1551. unsigned char *data;
  1552. ITclosurePtr new_closure;
  1553. /* We're putting the client to sleep. We need to
  1554. save some state. Similar problem to that handled
  1555. in doPolyText, but much simpler because the
  1556. request structure is much simpler. */
  1557. new_closure = (ITclosurePtr) xalloc(sizeof(ITclosureRec));
  1558. if (!new_closure)
  1559. {
  1560. err = BadAlloc;
  1561. goto bail;
  1562. }
  1563. *new_closure = *c;
  1564. c = new_closure;
  1565. data = (unsigned char *)xalloc(c->nChars * c->itemSize);
  1566. if (!data)
  1567. {
  1568. xfree(c);
  1569. err = BadAlloc;
  1570. goto bail;
  1571. }
  1572. memmove(data, c->data, c->nChars * c->itemSize);
  1573. c->data = data;
  1574. pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
  1575. if (!pGC)
  1576. {
  1577. xfree(c->data);
  1578. xfree(c);
  1579. err = BadAlloc;
  1580. goto bail;
  1581. }
  1582. pGC->tileIsPixel = TRUE;
  1583. pGC->tile.pixel = 0;
  1584. pGC->stipple = NullPixmap;
  1585. if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask |
  1586. GCForeground | GCBackground | GCFillStyle |
  1587. GCTile | GCStipple | GCTileStipXOrigin |
  1588. GCTileStipYOrigin | GCFont |
  1589. GCSubwindowMode | GCClipXOrigin |
  1590. GCClipYOrigin | GCClipMask)) != Success)
  1591. {
  1592. FreeScratchGC(pGC);
  1593. xfree(c->data);
  1594. xfree(c);
  1595. err = BadAlloc;
  1596. goto bail;
  1597. }
  1598. c->pGC = pGC;
  1599. ValidateGC(c->pDraw, c->pGC);
  1600. c->slept = TRUE;
  1601. ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c);
  1602. #ifdef NXAGENT_DEBUG
  1603. fprintf(stderr, " NXdixfonts: doImageText (1): client [%lx] sleeping.\n", client);
  1604. #endif
  1605. }
  1606. return TRUE;
  1607. }
  1608. else if (lgerr != Successful)
  1609. {
  1610. err = FontToXError(lgerr);
  1611. goto bail;
  1612. }
  1613. if (c->pDraw)
  1614. {
  1615. (* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg,
  1616. c->nChars, c->data);
  1617. }
  1618. bail:
  1619. if (err != Success && c->client != serverClient) {
  1620. SendErrorToClient(c->client, c->reqType, 0, 0, err);
  1621. }
  1622. if (c->slept)
  1623. {
  1624. ClientWakeup(c->client);
  1625. #ifdef NXAGENT_DEBUG
  1626. fprintf(stderr, " NXdixfonts: doImageText: client [%lx] wakeup.\n", client);
  1627. #endif
  1628. ChangeGC(c->pGC, clearGCmask, clearGC);
  1629. /* Unreference the font from the scratch GC */
  1630. CloseFont(c->pGC->font, (Font)0);
  1631. c->pGC->font = NullFont;
  1632. FreeScratchGC(c->pGC);
  1633. xfree(c->data);
  1634. xfree(c);
  1635. }
  1636. return TRUE;
  1637. }
  1638. int
  1639. ImageText(client, pDraw, pGC, nChars, data, xorg, yorg, reqType, did)
  1640. ClientPtr client;
  1641. DrawablePtr pDraw;
  1642. GC *pGC;
  1643. int nChars;
  1644. unsigned char *data;
  1645. int xorg;
  1646. int yorg;
  1647. int reqType;
  1648. XID did;
  1649. {
  1650. ITclosureRec local_closure;
  1651. local_closure.client = client;
  1652. local_closure.pDraw = pDraw;
  1653. local_closure.pGC = pGC;
  1654. local_closure.nChars = nChars;
  1655. local_closure.data = data;
  1656. local_closure.xorg = xorg;
  1657. local_closure.yorg = yorg;
  1658. if ((local_closure.reqType = reqType) == X_ImageText8)
  1659. {
  1660. local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8;
  1661. local_closure.itemSize = 1;
  1662. }
  1663. else
  1664. {
  1665. local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16;
  1666. local_closure.itemSize = 2;
  1667. }
  1668. local_closure.did = did;
  1669. local_closure.slept = FALSE;
  1670. (void) doImageText(client, &local_closure);
  1671. return Success;
  1672. }
  1673. /* does the necessary magic to figure out the fpe type */
  1674. static int
  1675. #if NeedFunctionPrototypes
  1676. DetermineFPEType(char *pathname)
  1677. #else
  1678. DetermineFPEType(pathname)
  1679. char *pathname;
  1680. #endif
  1681. {
  1682. int i;
  1683. for (i = 0; i < num_fpe_types; i++) {
  1684. if ((*fpe_functions[i].name_check) (pathname))
  1685. return i;
  1686. }
  1687. return -1;
  1688. }
  1689. static void
  1690. #if NeedFunctionPrototypes
  1691. FreeFontPath(FontPathElementPtr *list, int n, Bool force)
  1692. #else
  1693. FreeFontPath(list, n, force)
  1694. FontPathElementPtr *list;
  1695. Bool force;
  1696. int n;
  1697. #endif
  1698. {
  1699. int i;
  1700. for (i = 0; i < n; i++) {
  1701. if (force) {
  1702. /* Sanity check that all refcounts will be 0 by the time
  1703. we get to the end of the list. */
  1704. int found = 1; /* the first reference is us */
  1705. int j;
  1706. for (j = i+1; j < n; j++) {
  1707. if (list[j] == list[i])
  1708. found++;
  1709. }
  1710. if (list[i]->refcount != found) {
  1711. ErrorF("FreeFontPath: FPE \"%.*s\" refcount is %d, should be %d; fixing.\n",
  1712. list[i]->name_length, list[i]->name,
  1713. list[i]->refcount, found);
  1714. list[i]->refcount = found; /* ensure it will get freed */
  1715. }
  1716. }
  1717. FreeFPE(list[i]);
  1718. }
  1719. xfree((char *) list);
  1720. }
  1721. static FontPathElementPtr
  1722. #if NeedFunctionPrototypes
  1723. find_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len)
  1724. #else
  1725. find_existing_fpe(list, num, name, len)
  1726. FontPathElementPtr *list;
  1727. int num;
  1728. unsigned char *name;
  1729. int len;
  1730. #endif
  1731. {
  1732. FontPathElementPtr fpe;
  1733. int i;
  1734. for (i = 0; i < num; i++) {
  1735. fpe =

Large files files are truncated, but you can click here to view the full file