dixfonts.c 62 KB

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