WmImage.c 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /*
  24. * (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC.
  25. * ALL RIGHTS RESERVED
  26. */
  27. /*
  28. * Motif Release 1.2.3
  29. */
  30. /*
  31. * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
  32. /*
  33. * Included Files:
  34. */
  35. #include "WmGlobal.h"
  36. #define MWM_NEED_IIMAGE
  37. #include "WmIBitmap.h"
  38. #include <Xm/XmosP.h>
  39. /* Copied from XmosI.h */
  40. extern String _XmOSInitPath(
  41. String file_name,
  42. String env_pathname,
  43. Boolean *user_path) ;
  44. #include <Xm/IconFile.h>
  45. #include <Dt/GetDispRes.h>
  46. #define MATCH_XBM 'B' /* .xbm character: see XmGetPixmap */
  47. #define MATCH_PATH "XBMLANGPATH"
  48. /*
  49. * include extern functions
  50. */
  51. #include "WmImage.h"
  52. #include "WmGraphics.h"
  53. #include "WmResource.h"
  54. #include "WmResParse.h"
  55. #include "WmMenu.h"
  56. #include "WmError.h"
  57. /******************************<->*************************************
  58. *
  59. * MakeClientIconPixmap (pCD, iconBitmap, iconMask)
  60. *
  61. *
  62. * Description:
  63. * -----------
  64. * This function takes a client supplied icon image pixmap and mask
  65. * bitmap and makes it into a colored pixmap suitable for use as an
  66. * icon image.
  67. *
  68. *
  69. * Inputs:
  70. * ------
  71. * pCD = pointer to client data (icon colors and tiles)
  72. *
  73. * iconBitmap = icon bitmap
  74. * iconMask = mask bitmap
  75. *
  76. *
  77. * Outputs:
  78. * -------
  79. * RETURN = icon pixmap (NULL if error)
  80. *
  81. ******************************<->***********************************/
  82. Pixmap MakeClientIconPixmap (
  83. ClientData *pCD,
  84. Pixmap iconBitmap,
  85. Pixmap iconMask)
  86. {
  87. Window root;
  88. int x;
  89. int y;
  90. unsigned int bitmapWidth;
  91. unsigned int bitmapHeight;
  92. unsigned int border;
  93. unsigned int depth;
  94. /*
  95. * Check out the attributes of the bitmap to insure that it is usable.
  96. */
  97. if (!XGetGeometry (DISPLAY, iconBitmap, &root, &x, &y,
  98. &bitmapWidth, &bitmapHeight, &border, &depth))
  99. {
  100. Warning (((char *)GETMESSAGE(38, 1, "Invalid icon bitmap")));
  101. return ((Pixmap)NULL);
  102. }
  103. if (ROOT_FOR_CLIENT(pCD) != root)
  104. {
  105. /*
  106. * The bitmap was not made with usable parameters.
  107. */
  108. Warning (((char *)GETMESSAGE(38, 9, "Icon bitmap cannot be used on this screen")));
  109. return ((Pixmap)NULL);
  110. }
  111. /*
  112. * Color the bitmap, center it in a pixmap ....
  113. */
  114. return (MakeIconPixmap (pCD, iconBitmap, (Pixmap)iconMask,
  115. bitmapWidth, bitmapHeight, depth));
  116. } /* END OF FUNCTION MakeClientIconPixmap */
  117. /*************************************<->*************************************
  118. *
  119. * MakeNamedIconPixmap (pCD, iconName)
  120. *
  121. *
  122. * Description:
  123. * -----------
  124. * This function makes an icon pixmap for a particular client given the
  125. * name of a bitmap file.
  126. *
  127. *
  128. * Inputs:
  129. * ------
  130. * pCD = (nonNULL) pointer to client data
  131. * iconName = pointer to the icon name (bitmap file path name or NULL)
  132. *
  133. *
  134. * Outputs:
  135. * -------
  136. * RETURN = icon pixmap or NULL
  137. *
  138. *************************************<->***********************************/
  139. Pixmap MakeNamedIconPixmap (ClientData *pCD, String iconName)
  140. {
  141. int bitmapIndex;
  142. Pixmap pixmap, pixmap_r, mask;
  143. Window root;
  144. int x, y;
  145. unsigned int width, height, border_width, depth;
  146. String sIconFileName;
  147. int iconSizeDesired;
  148. /*
  149. * Get the bitmap cache entry (will read data from file if necessary).
  150. * If unable to find the iconName file return NULL.
  151. */
  152. if ((bitmapIndex = GetBitmapIndex (PSD_FOR_CLIENT(pCD), iconName,
  153. False)) < 0)
  154. {
  155. if ((PSD_FOR_CLIENT(pCD)->displayResolutionType == LOW_RES_DISPLAY) ||
  156. (PSD_FOR_CLIENT(pCD)->displayResolutionType == VGA_RES_DISPLAY))
  157. {
  158. iconSizeDesired = XmMEDIUM_ICON_SIZE;
  159. }
  160. else
  161. {
  162. iconSizeDesired = XmLARGE_ICON_SIZE;
  163. }
  164. pixmap = XmUNSPECIFIED_PIXMAP;
  165. sIconFileName = XmGetIconFileName(
  166. XtScreen(PSD_FOR_CLIENT(pCD)->screenTopLevelW1),
  167. NULL,
  168. iconName,
  169. NULL,
  170. iconSizeDesired);
  171. if (sIconFileName != NULL)
  172. {
  173. pixmap = XmGetPixmap (
  174. XtScreen (PSD_FOR_CLIENT(pCD)->screenTopLevelW1),
  175. sIconFileName,
  176. pCD->iconImageForeground,
  177. pCD->iconImageBackground);
  178. }
  179. if (pixmap == XmUNSPECIFIED_PIXMAP)
  180. {
  181. pixmap = XmGetPixmap (
  182. XtScreen (PSD_FOR_CLIENT(pCD)->screenTopLevelW1),
  183. iconName,
  184. pCD->iconImageForeground,
  185. pCD->iconImageBackground);
  186. }
  187. if (pixmap == XmUNSPECIFIED_PIXMAP)
  188. {
  189. MWarning (((char *)GETMESSAGE(38, 7, "Unable to read bitmap file %s\n")), iconName);
  190. }
  191. else
  192. {
  193. mask = XmeGetMask (XtScreen(PSD_FOR_CLIENT(pCD)->screenTopLevelW1),
  194. (sIconFileName == NULL) ? iconName : sIconFileName);
  195. if (mask == XmUNSPECIFIED_PIXMAP)
  196. {
  197. mask = (Pixmap) NULL;
  198. }
  199. if (sIconFileName != NULL)
  200. XtFree(sIconFileName);
  201. /*
  202. * We need to synchronize DISPLAY1 here because the pixmap and mask
  203. * were created on that display connection, and we must ensure that
  204. * the server has processed those requests before we attempt to use
  205. * the pixmap and mask on DISPLAY. We thus assume that the
  206. * subsequent XGetGeometry() call is successful.
  207. */
  208. XSync(DISPLAY1, False);
  209. (void) XGetGeometry (DISPLAY, pixmap, &root, &x, &y, &width,
  210. &height, &border_width, &depth);
  211. pixmap_r = MakeIconPixmap (pCD, pixmap, mask,
  212. width, height, depth);
  213. XmDestroyPixmap (XtScreen (PSD_FOR_CLIENT(pCD)->screenTopLevelW1),
  214. pixmap);
  215. if (mask)
  216. XmDestroyPixmap (
  217. XtScreen (PSD_FOR_CLIENT(pCD)->screenTopLevelW1), mask);
  218. return (pixmap_r);
  219. }
  220. if (sIconFileName != NULL)
  221. XtFree (sIconFileName);
  222. return ((Pixmap)NULL);
  223. }
  224. /*
  225. * Color the bitmap, center it in a pixmap ....
  226. */
  227. return (MakeCachedIconPixmap (pCD, bitmapIndex, (Pixmap)NULL));
  228. } /* END OF FUNCTION MakeNamedIconPixmap */
  229. /*************************************<->*************************************
  230. *
  231. * Pixmap
  232. * MakeCachedIconPixmap (pCD, bitmapIndex, mask)
  233. *
  234. *
  235. * Description:
  236. * -----------
  237. * Convert the cached bitmap and mask into an icon pixmap.
  238. *
  239. *
  240. * Inputs:
  241. * ------
  242. * pCD - (nonNULL) pointer to client data (icon colors and tiles)
  243. * bitmapIndex - bitmap cache index of image to be converted
  244. * mask - bitmap mask, 1 for bits of "bitmap" to be kept
  245. *
  246. *
  247. * Outputs:
  248. * -------
  249. * RETURN - icon pixmap or NULL
  250. *
  251. *
  252. * Comments:
  253. * --------
  254. * o "mask" is not used.
  255. *
  256. *************************************<->***********************************/
  257. Pixmap MakeCachedIconPixmap (ClientData *pCD, int bitmapIndex, Pixmap mask)
  258. {
  259. BitmapCache *bitmapc;
  260. PixmapCache *pixmapc;
  261. Pixmap pixmap = (Pixmap)NULL;
  262. WmScreenData *pSD = PSD_FOR_CLIENT(pCD);
  263. if (bitmapIndex < 0)
  264. {
  265. return ((Pixmap)NULL);
  266. }
  267. bitmapc = &(pSD->bitmapCache[bitmapIndex]);
  268. /*
  269. * Search for an icon pixmap matching the client icon colors.
  270. */
  271. pixmapc = bitmapc->pixmapCache;
  272. while (pixmapc)
  273. {
  274. if ((pixmapc->pixmapType == ICON_PIXMAP) &&
  275. (pixmapc->foreground == pCD->iconImageForeground) &&
  276. (pixmapc->background == pCD->iconImageBackground))
  277. {
  278. pixmap = pixmapc->pixmap;
  279. break;
  280. }
  281. pixmapc = pixmapc->next;
  282. }
  283. /*
  284. * If a matching pixmap was not found in the pixmap cache for this bitmap
  285. * then create the icon pixmap with the appropriate colors.
  286. * If have sufficient memory, save the pixmap info in the pixmapCache.
  287. */
  288. if (!pixmap &&
  289. (pixmap = MakeIconPixmap (pCD, bitmapc->bitmap, mask,
  290. bitmapc->width, bitmapc->height, 1)) &&
  291. (pixmapc = (PixmapCache *) XtMalloc (sizeof (PixmapCache))))
  292. {
  293. pixmapc->pixmapType = ICON_PIXMAP;
  294. pixmapc->foreground = pCD->iconImageForeground;
  295. pixmapc->background = pCD->iconImageBackground;
  296. pixmapc->pixmap = pixmap;
  297. pixmapc->next = bitmapc->pixmapCache;
  298. bitmapc->pixmapCache = pixmapc;
  299. }
  300. return (pixmap);
  301. } /* END OF FUNCTION MakeCachedIconPixmap */
  302. /*************************************<->*************************************
  303. *
  304. * MakeIconPixmap (pCD, bitmap, mask, width, height, depth)
  305. *
  306. *
  307. * Description:
  308. * -----------
  309. * Convert the bitmap and mask into an icon pixmap.
  310. *
  311. *
  312. * Inputs:
  313. * ------
  314. * pCD - pointer to client data (icon colors and tiles)
  315. * pWS - pointer to workspace data
  316. * bitmap - bitmap image to be converted
  317. * mask - bitmap mask, 1 for bits of "bitmap" to be kept
  318. * width - pixel width of bitmap
  319. * height - pixel height of bitmap
  320. * depth - depth of bitmap (pixmap, really)
  321. *
  322. *
  323. * Outputs:
  324. * -------
  325. * RETURN - icon pixmap or NULL
  326. *
  327. *
  328. * Comments:
  329. * --------
  330. * o "mask" is not used.
  331. *
  332. *************************************<->***********************************/
  333. Pixmap MakeIconPixmap (ClientData *pCD, Pixmap bitmap, Pixmap mask, unsigned int width, unsigned int height, unsigned int depth)
  334. {
  335. Pixmap iconPixmap;
  336. GC imageGC, topGC, botGC;
  337. XGCValues gcv;
  338. unsigned long gc_mask;
  339. XmPixelSet *pPS = NULL;
  340. unsigned int imageWidth;
  341. unsigned int imageHeight;
  342. int dest_x, dest_y;
  343. #ifndef NO_CLIP_CENTER
  344. int src_x, src_y;
  345. #endif /* NO_CLIP_CENTER */
  346. Pixel fg;
  347. Pixel bg;
  348. static RList *top_rects = NULL;
  349. static RList *bot_rects = NULL;
  350. WmScreenData *pSD;
  351. if ((top_rects == NULL) &&
  352. (top_rects = AllocateRList
  353. ((unsigned)2 * ICON_INTERNAL_SHADOW_WIDTH)) == NULL)
  354. {
  355. /* Out of memory! */
  356. Warning (((char *)GETMESSAGE(38, 3, "Insufficient memory to bevel icon image")));
  357. return ((Pixmap)NULL);
  358. }
  359. if ((bot_rects == NULL) &&
  360. (bot_rects = AllocateRList
  361. ((unsigned)2 * ICON_INTERNAL_SHADOW_WIDTH)) == NULL)
  362. {
  363. /* Out of memory! */
  364. Warning (((char *)GETMESSAGE(38, 4, "Insufficient memory to bevel icon image")));
  365. return ((Pixmap)NULL);
  366. }
  367. if (pCD)
  368. {
  369. pSD = pCD->pSD;
  370. }
  371. else
  372. {
  373. pSD = wmGD.pActiveSD;
  374. }
  375. /* don't make icon pixmap if bitmap is too small */
  376. if ((width < pSD->iconImageMinimum.width) ||
  377. (height < pSD->iconImageMinimum.height))
  378. {
  379. /* bitmap is too small */
  380. return ((Pixmap)NULL);
  381. }
  382. #ifndef NO_CLIP_CENTER
  383. /* copy the center of the icon if too big */
  384. if (width > pSD->iconImageMaximum.width)
  385. {
  386. src_x = (width - pSD->iconImageMaximum.width)/2;
  387. }
  388. else
  389. {
  390. src_x = 0;
  391. }
  392. if (height > pSD->iconImageMaximum.height)
  393. {
  394. src_y = (height - pSD->iconImageMaximum.height)/2;
  395. }
  396. else
  397. {
  398. src_y = 0;
  399. }
  400. #endif /* NO_CLIP_CENTER */
  401. /*
  402. * SLAB frameStyle adds a single pixel of background color around
  403. * the image to set it off from the beveling.
  404. */
  405. imageWidth = pSD->iconImageMaximum.width +
  406. 2 * ICON_INTERNAL_SHADOW_WIDTH +
  407. ((wmGD.frameStyle == WmSLAB) ? 2 : 0);
  408. imageHeight = pSD->iconImageMaximum.height +
  409. 2 * ICON_INTERNAL_SHADOW_WIDTH +
  410. ((wmGD.frameStyle == WmSLAB) ? 2 : 0);
  411. /* create a pixmap (to be returned) */
  412. iconPixmap = XCreatePixmap (DISPLAY, pSD->rootWindow,
  413. imageWidth, imageHeight,
  414. DefaultDepth(DISPLAY, pSD->screen));
  415. /*
  416. * If a client is not specified use icon component colors, otherwise
  417. * use the client-specific icon colors.
  418. */
  419. if (pCD)
  420. {
  421. bg = pCD->iconImageBackground;
  422. fg = pCD->iconImageForeground;
  423. }
  424. else
  425. {
  426. bg = pSD->iconAppearance.background;
  427. fg = pSD->iconAppearance.foreground;
  428. }
  429. /* create a GC to use */
  430. gc_mask = GCForeground | GCBackground | GCGraphicsExposures;
  431. if (mask)
  432. {
  433. if (pSD->pPrimaryPixelSet != NULL)
  434. {
  435. pPS = pSD->pPrimaryPixelSet;
  436. gcv.background = pPS->bg;
  437. /* set fg to bg color to clear it first */
  438. gcv.foreground = pPS->bg;
  439. }
  440. else
  441. {
  442. gcv.background = ICON_APPEARANCE(pCD).background;
  443. /* set fg to bg color to clear it first */
  444. gcv.foreground = ICON_APPEARANCE(pCD).background;
  445. }
  446. }
  447. else
  448. {
  449. gcv.foreground = bg; /* clear it first! */
  450. gcv.background = bg;
  451. }
  452. gcv.graphics_exposures = False;
  453. imageGC = XCreateGC (DISPLAY, iconPixmap, gc_mask, &gcv);
  454. /*
  455. * Format the image.
  456. */
  457. /* fill in background */
  458. XFillRectangle(DISPLAY, iconPixmap, imageGC, 0, 0,
  459. imageWidth, imageHeight);
  460. /* center the image */
  461. if (width > pSD->iconImageMaximum.width)
  462. {
  463. width = pSD->iconImageMaximum.width;
  464. }
  465. if (height > pSD->iconImageMaximum.height)
  466. {
  467. height = pSD->iconImageMaximum.height;
  468. }
  469. /* center the image */
  470. dest_x = (imageWidth - width) / 2;
  471. dest_y = (imageHeight - height) / 2;
  472. if (mask)
  473. {
  474. if (pPS != NULL)
  475. {
  476. gcv.foreground = pPS->fg;
  477. }
  478. else
  479. {
  480. gcv.foreground = ICON_APPEARANCE(pCD).foreground;
  481. }
  482. }
  483. else
  484. {
  485. gcv.foreground = fg;
  486. }
  487. gc_mask = GCForeground;
  488. if (mask)
  489. {
  490. gcv.clip_mask = mask;
  491. #ifndef NO_CLIP_CENTER
  492. gcv.clip_x_origin = dest_x - src_x;
  493. gcv.clip_y_origin = dest_y - src_y;
  494. #else /* NO_CLIP_CENTER */
  495. gcv.clip_x_origin = dest_x;
  496. gcv.clip_y_origin = dest_y;
  497. #endif /* NO_CLIP_CENTER */
  498. gc_mask |= GCClipXOrigin | GCClipYOrigin | GCClipMask;
  499. }
  500. XChangeGC (DISPLAY, imageGC, gc_mask, &gcv);
  501. /* copy the bitmap to the pixmap */
  502. if ((depth > 1) &&
  503. (depth == DefaultDepth(DISPLAY, pSD->screen)))
  504. {
  505. #ifndef NO_CLIP_CENTER
  506. XCopyArea (DISPLAY, bitmap, iconPixmap, imageGC, src_x, src_y,
  507. width, height, dest_x, dest_y);
  508. #else /* NO_CLIP_CENTER */
  509. XCopyArea (DISPLAY, bitmap, iconPixmap, imageGC, 0, 0,
  510. width, height, dest_x, dest_y);
  511. #endif /* NO_CLIP_CENTER */
  512. }
  513. else
  514. #ifndef NO_CLIP_CENTER
  515. XCopyPlane (DISPLAY, bitmap, iconPixmap, imageGC, src_x, src_y, width,
  516. height, dest_x, dest_y, 1L);
  517. #else /* NO_CLIP_CENTER */
  518. XCopyPlane (DISPLAY, bitmap, iconPixmap, imageGC, 0, 0, width, height,
  519. dest_x, dest_y, 1L);
  520. #endif /* NO_CLIP_CENTER */
  521. /* free resources */
  522. XFreeGC (DISPLAY, imageGC);
  523. if (pCD)
  524. {
  525. /*
  526. * Shadowing
  527. */
  528. if (mask && (pPS != NULL))
  529. {
  530. topGC = GetHighlightGC (pSD, pPS->ts, pPS->bg,
  531. pCD->iconImageTopShadowPixmap);
  532. botGC = GetHighlightGC (pSD, pPS->bs, pPS->bg,
  533. pCD->iconImageBottomShadowPixmap);
  534. }
  535. else
  536. {
  537. topGC = GetHighlightGC (pSD, pCD->iconImageTopShadowColor,
  538. pCD->iconImageBackground,
  539. pCD->iconImageTopShadowPixmap);
  540. botGC = GetHighlightGC (pSD, pCD->iconImageBottomShadowColor,
  541. pCD->iconImageBackground,
  542. pCD->iconImageBottomShadowPixmap);
  543. }
  544. /*
  545. * CR5208 - Better fix than from OSF!
  546. * Zero out the rectangle count in our
  547. * static structures so that BevelRectangle
  548. * won't extend the RList causing a memory leak.
  549. * Old fix allocated and freed rectangle structure
  550. * each time through.
  551. */
  552. top_rects->used = 0; /* reset count */
  553. bot_rects->used = 0;
  554. BevelRectangle (top_rects,
  555. bot_rects,
  556. 0, 0,
  557. imageWidth, imageHeight,
  558. ICON_INTERNAL_SHADOW_WIDTH,
  559. ICON_INTERNAL_SHADOW_WIDTH,
  560. ICON_INTERNAL_SHADOW_WIDTH,
  561. ICON_INTERNAL_SHADOW_WIDTH);
  562. XFillRectangles (DISPLAY, iconPixmap, topGC, top_rects->prect,
  563. top_rects->used);
  564. XFillRectangles (DISPLAY, iconPixmap, botGC, bot_rects->prect,
  565. bot_rects->used);
  566. }
  567. return (iconPixmap);
  568. } /* END OF FUNCTION MakeIconPixmap */
  569. /*************************************<->*************************************
  570. *
  571. * Pixmap
  572. * MakeCachedLabelPixmap (pSD, menuW, bitmapIndex)
  573. *
  574. *
  575. * Description:
  576. * -----------
  577. * Creates and returns a label pixmap.
  578. *
  579. *
  580. * Inputs:
  581. * ------
  582. * pSD = pointer to screen data
  583. * menuW = menu widget (for foreground and background colors)
  584. * bitmapIndex = bitmap cache index
  585. *
  586. *
  587. * Outputs:
  588. * -------
  589. * Return = label pixmap or NULL.
  590. *
  591. *
  592. * Comments:
  593. * --------
  594. * Assumes bitmapIndex is valid.
  595. *
  596. *************************************<->***********************************/
  597. Pixmap MakeCachedLabelPixmap (WmScreenData *pSD, Widget menuW, int bitmapIndex)
  598. {
  599. BitmapCache *bitmapc;
  600. PixmapCache *pixmapc;
  601. int i;
  602. Arg args[5];
  603. Pixel fg, bg;
  604. Pixmap pixmap = (Pixmap)NULL;
  605. GC gc;
  606. XGCValues gcv;
  607. if (bitmapIndex < 0)
  608. {
  609. return ((Pixmap)NULL);
  610. }
  611. bitmapc = &(pSD->bitmapCache[bitmapIndex]);
  612. /*
  613. * Get the foreground and background colors from the menu widget.
  614. * Search for a label pixmap matching those colors.
  615. */
  616. i = 0;
  617. XtSetArg (args[i], XtNforeground, &fg); i++;
  618. XtSetArg (args[i], XtNbackground, &bg); i++;
  619. XtGetValues (menuW, (ArgList)args, i);
  620. pixmapc = bitmapc->pixmapCache;
  621. while (pixmapc)
  622. {
  623. if ((pixmapc->pixmapType == LABEL_PIXMAP) &&
  624. (pixmapc->foreground == fg) &&
  625. (pixmapc->background == bg))
  626. {
  627. pixmap = pixmapc->pixmap;
  628. break;
  629. }
  630. pixmapc = pixmapc->next;
  631. }
  632. if (!pixmap)
  633. /*
  634. * A matching pixmap was not found in the pixmap cache for this bitmap.
  635. * Create and save the label pixmap with appropriate colors.
  636. */
  637. {
  638. /*
  639. * Create a pixmap of the appropriate size, root, and depth.
  640. * Only BadAlloc error possible; BadDrawable and BadValue are avoided.
  641. */
  642. pixmap = XCreatePixmap (DISPLAY, pSD->rootWindow,
  643. bitmapc->width, bitmapc->height,
  644. DefaultDepth (DISPLAY, pSD->screen));
  645. /*
  646. * Create a GC and copy the bitmap to the pixmap.
  647. * Only BadAlloc and BadDrawable errors are possible; others are avoided
  648. */
  649. gcv.foreground = bg;
  650. gcv.background = bg;
  651. gcv.graphics_exposures = False;
  652. gc = XCreateGC(DISPLAY, pixmap, (GCForeground|GCBackground), &gcv);
  653. /*
  654. * Fill in the background, set the foreground, copy the bitmap to the
  655. * pixmap, and free the gc.
  656. */
  657. XFillRectangle (DISPLAY, pixmap, gc, 0, 0,
  658. bitmapc->width, bitmapc->height);
  659. XSetForeground (DISPLAY, gc, fg);
  660. XCopyPlane (DISPLAY, bitmapc->bitmap, pixmap, gc, 0, 0,
  661. bitmapc->width, bitmapc->height, 0, 0, 1L);
  662. XFreeGC (DISPLAY, gc);
  663. /*
  664. * If have sufficient memory, save the pixmap info in the pixmapCache.
  665. */
  666. if ((pixmapc = (PixmapCache *) XtMalloc(sizeof(PixmapCache))) != NULL)
  667. {
  668. pixmapc->pixmapType = LABEL_PIXMAP;
  669. pixmapc->foreground = fg;
  670. pixmapc->background = bg;
  671. pixmapc->pixmap = pixmap;
  672. pixmapc->next = bitmapc->pixmapCache;
  673. bitmapc->pixmapCache = pixmapc;
  674. }
  675. }
  676. return (pixmap);
  677. } /* END OF FUNCTION MakeCachedLabelPixmap */
  678. /*************************************<->*************************************
  679. *
  680. * int
  681. * GetBitmapIndex (pSD, name)
  682. *
  683. *
  684. * Description:
  685. * -----------
  686. * Retrieve bitmap from cache.
  687. *
  688. *
  689. * Inputs:
  690. * ------
  691. * pSD = pointer to screen data
  692. * name = bitmap file name or NULL pointer
  693. * bitmapCache[]
  694. * bitmapCacheSize
  695. * bitmapCacheCount
  696. *
  697. *
  698. * Outputs:
  699. * -------
  700. * bitmapCache[]
  701. * bitmapCacheSize
  702. * bitmapCacheCount
  703. * Return = bitmap cache index or -1
  704. *
  705. *
  706. * Comments:
  707. * --------
  708. * None
  709. *
  710. *************************************<->***********************************/
  711. #define BITMAP_CACHE_INC 5
  712. int GetBitmapIndex (WmScreenData *pSD, char *name, Boolean bReportError)
  713. {
  714. char *path;
  715. BitmapCache *bitmapc;
  716. unsigned int n;
  717. int x, y;
  718. /*
  719. * Search a nonempty bitmap cache for a pathname match.
  720. */
  721. path = BitmapPathName (name);
  722. for (n = 0, bitmapc = pSD->bitmapCache;
  723. n < pSD->bitmapCacheCount;
  724. n++, bitmapc++)
  725. {
  726. if ((!path && !bitmapc->path) ||
  727. (path && bitmapc->path &&
  728. !strcmp (path, bitmapc->path)))
  729. {
  730. return (n);
  731. }
  732. }
  733. /*
  734. * The bitmap path name was not found in bitmapCache.
  735. * Find the next BitmapCache entry, creating or enlarging bitmapCache if
  736. * necessary.
  737. */
  738. if (pSD->bitmapCacheSize == 0)
  739. /* create */
  740. {
  741. pSD->bitmapCacheSize = BITMAP_CACHE_INC;
  742. pSD->bitmapCache =
  743. (BitmapCache *) XtMalloc (BITMAP_CACHE_INC * sizeof (BitmapCache));
  744. }
  745. else if (pSD->bitmapCacheCount == pSD->bitmapCacheSize)
  746. /* enlarge */
  747. {
  748. pSD->bitmapCacheSize += BITMAP_CACHE_INC;
  749. pSD->bitmapCache = (BitmapCache *)
  750. XtRealloc ((char*)pSD->bitmapCache,
  751. pSD->bitmapCacheSize * sizeof (BitmapCache));
  752. }
  753. if (pSD->bitmapCache == NULL)
  754. {
  755. MWarning (((char *)GETMESSAGE(38, 5, "Insufficient memory for bitmap %s\n")), name);
  756. pSD->bitmapCacheSize = 0;
  757. pSD->bitmapCacheCount = 0;
  758. return (-1);
  759. }
  760. bitmapc = &(pSD->bitmapCache[pSD->bitmapCacheCount]);
  761. /*
  762. * Fill the entry with the bitmap info.
  763. * A NULL path indicates the builtin icon bitmap.
  764. * Indicate that no pixmapCache exists yet.
  765. */
  766. if (path)
  767. {
  768. if ((bitmapc->path = (String)
  769. XtMalloc ((unsigned int)(strlen (path) + 1))) == NULL)
  770. {
  771. MWarning (((char *)GETMESSAGE(38, 6, "Insufficient memory for bitmap %s\n")), name);
  772. return (-1);
  773. }
  774. strcpy (bitmapc->path, path);
  775. if (XReadBitmapFile (DISPLAY, pSD->rootWindow, path,
  776. &bitmapc->width, &bitmapc->height,
  777. &bitmapc->bitmap, &x, &y)
  778. != BitmapSuccess)
  779. {
  780. if (bReportError)
  781. MWarning (((char *)GETMESSAGE(38, 7, "Unable to read bitmap file %s\n")), path);
  782. XtFree ((char *)bitmapc->path);
  783. return (-1);
  784. }
  785. if (bitmapc->width == 0 || bitmapc->height == 0)
  786. {
  787. if (bReportError)
  788. MWarning (((char *)GETMESSAGE(38, 8, "Invalid bitmap file %s\n")), path);
  789. XtFree ((char *)bitmapc->path);
  790. return (-1);
  791. }
  792. }
  793. else
  794. /* builtin icon bitmap */
  795. {
  796. bitmapc->path = NULL;
  797. bitmapc->bitmap = pSD->builtinIconPixmap;
  798. bitmapc->width = iImage_width;
  799. bitmapc->height = iImage_height;
  800. }
  801. bitmapc->pixmapCache = NULL;
  802. return (pSD->bitmapCacheCount++);
  803. } /* END OF FUNCTION GetBitmapIndex */
  804. /*************************************<->*************************************
  805. *
  806. * BitmapPathName (string)
  807. *
  808. *
  809. * Description:
  810. * -----------
  811. * Constructs a bitmap file pathname from the bitmap file name and the
  812. * bitmapDirectory resource value.
  813. *
  814. *
  815. * Inputs:
  816. * ------
  817. * string = bitmap file name or NULL
  818. * wmGD.bitmapDirectory = bitmapDirectory resource value
  819. * HOME = environment variable for home directory
  820. * XBMLANGPATH
  821. * XAPPLRESDIR
  822. *
  823. *
  824. * Outputs:
  825. * -------
  826. * Return = string containing the bitmap file pathname or NULL.
  827. *
  828. *
  829. * Comments:
  830. * --------
  831. * If the bitmap file does not exist, searches using XBMLANGPATH.
  832. * Returns NULL path name for a NULL file name.
  833. *
  834. *************************************<->***********************************/
  835. char *BitmapPathName (char *string)
  836. {
  837. static char fileName[MAXWMPATH+1];
  838. char *retname;
  839. SubstitutionRec subs[1];
  840. char *homeDir = XmeGetHomeDirName();
  841. if (!string || !*string)
  842. {
  843. return (NULL);
  844. }
  845. /*
  846. * Interpret "~/.." as relative to the user's home directory.
  847. * Interpret "/.." as an absolute pathname.
  848. * If the bitmapDirectory resource is nonNULL, interpret path as relative
  849. * to it.
  850. * Else, or if bitmapDirectory has no such file, use a XBMLANGPATH lookup.
  851. */
  852. if ((string[0] == '~') && (string[1] == '/'))
  853. /*
  854. * Handle "~/.."
  855. */
  856. {
  857. snprintf(fileName, MAXWMPATH, "%s%s", homeDir, &(string[1]));
  858. return (fileName);
  859. }
  860. if (string[0] == '/')
  861. {
  862. return(string);
  863. }
  864. if (wmGD.bitmapDirectory && *wmGD.bitmapDirectory)
  865. /*
  866. * Relative to nonNULL bitmapDirectory (which may have relative to HOME)
  867. */
  868. {
  869. if ((wmGD.bitmapDirectory[0] == '~') &&
  870. (wmGD.bitmapDirectory[1] == '/'))
  871. {
  872. strcpy (fileName, homeDir);
  873. strncat (fileName, &wmGD.bitmapDirectory[1],
  874. MAXWMPATH - strlen (fileName));
  875. } else {
  876. snprintf(fileName, sizeof(fileName), "%s", wmGD.bitmapDirectory);
  877. }
  878. strncat (fileName, "/", MAXWMPATH - strlen (fileName));
  879. strncat (fileName, string, MAXWMPATH - strlen (fileName));
  880. /* Test file for existence. */
  881. subs[0].substitution = "";
  882. if ((retname = XtFindFile(fileName, subs, 0,
  883. (XtFilePredicate) NULL)) != NULL) {
  884. XtFree(retname);
  885. return (fileName);
  886. }
  887. }
  888. /* Fall back on a path search */
  889. {
  890. char *search_path;
  891. Boolean user_path;
  892. search_path = _XmOSInitPath(string, MATCH_PATH, &user_path);
  893. subs[0].match = user_path ? MATCH_XBM : MATCH_CHAR;
  894. subs[0].substitution = string;
  895. retname = XtResolvePathname(DISPLAY, "bitmaps", NULL, NULL,
  896. search_path, subs, XtNumber(subs),
  897. (XtFilePredicate)NULL);
  898. XtFree(search_path);
  899. if (!retname)
  900. return (string);
  901. strncpy(fileName, retname, MAXWMPATH);
  902. XtFree(retname);
  903. return (fileName);
  904. }
  905. } /* END OF FUNCTION BitmapPathName */
  906. /**************************** eof ***************************/