icon.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  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. /* $XConsortium: icon.c /main/3 1995/10/27 10:39:09 rswiston $ */
  24. /*****************************************************************************
  25. *****************************************************************************
  26. **
  27. ** File: icon.c
  28. **
  29. ** Description: Icon support functions for the CDE Drag & Drop Demo.
  30. **
  31. ** (c) Copyright 1993, 1994 Hewlett-Packard Company
  32. ** (c) Copyright 1993, 1994 International Business Machines Corp.
  33. ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  34. ** (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of
  35. ** Novell, Inc.
  36. **
  37. ****************************************************************************
  38. ************************************<+>*************************************/
  39. #include <stdio.h>
  40. #include <Xm/Screen.h>
  41. #include <Dt/Dts.h>
  42. #include <Dt/Dnd.h>
  43. #include "icon.h"
  44. /*************************************************************************
  45. *
  46. * Data Structures & Private Declarations For Icon Handling Functions
  47. *
  48. **************************************************************************/
  49. #define ICON_TEXT_YGAP 2
  50. #define ICON_PATH "/usr/dt/appconfig/icons/C"
  51. #define ICON_BITMAP_SUFFIX "m.bm"
  52. #define ICON_MASK_SUFFIX "m_m.bm"
  53. /*
  54. * Default Generic Icon Bitmap & Mask
  55. */
  56. #define iconWidth 32
  57. #define iconHeight 32
  58. static unsigned char iconBits[] = {
  59. 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x0f, 0x08, 0x00, 0x00, 0x08,
  60. 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x88, 0x9d, 0x6d, 0x08,
  61. 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x88, 0xf9, 0xed, 0x08,
  62. 0x08, 0x00, 0x00, 0x08, 0xc8, 0x6e, 0x7d, 0x08, 0x08, 0x00, 0x00, 0x08,
  63. 0xc8, 0x9d, 0xef, 0x09, 0x08, 0x00, 0x00, 0x08, 0xc8, 0xdd, 0xb3, 0x08,
  64. 0x08, 0x00, 0x00, 0x08, 0xc8, 0xdf, 0xfd, 0x09, 0x08, 0x00, 0x00, 0x08,
  65. 0xc8, 0xf6, 0xde, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08,
  66. 0x88, 0xed, 0xd2, 0x08, 0x08, 0x00, 0x00, 0x08, 0xc8, 0xbb, 0xf3, 0x08,
  67. 0x08, 0x00, 0x00, 0x08, 0x48, 0xdf, 0x5e, 0x08, 0x08, 0x00, 0x00, 0x08,
  68. 0xc8, 0x36, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x08,
  69. 0x08, 0x00, 0x00, 0x08, 0xf8, 0xff, 0xff, 0x0f};
  70. #define iconMaskWidth 32
  71. #define iconMaskHeight 32
  72. static unsigned char iconMaskBits[] = {
  73. 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  74. 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  75. 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  76. 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  77. 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  78. 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  79. 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  80. 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  81. 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  82. 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f,
  83. 0xf8, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x0f};
  84. /*
  85. * Blank Bitmap
  86. */
  87. #define blankWidth 16
  88. #define blankHeight 16
  89. static unsigned char blankBits[] = {
  90. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  91. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  92. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  93. };
  94. /*
  95. * Private Icon Handling Function Declarations
  96. */
  97. static void iconClearBitmap(Display*, Window, GC, Pixmap, int, int);
  98. static Pixmap iconDefaultBitmap(Display*, Window, IconBitmapPart,
  99. unsigned short*, unsigned short*);
  100. static void iconFree(IconInfo*);
  101. static Pixmap iconGetBitmap(Widget, char*, IconBitmapPart, unsigned short*,
  102. unsigned short*);
  103. static char *iconGetIconPath(void*, int, IconTyping, IconBitmapPart);
  104. static Pixmap iconMergeBitmaps(Widget, Pixmap, int, int, Pixmap, int, int,
  105. int, int, Boolean);
  106. /*************************************************************************
  107. *
  108. * Public Icon Handling Functions
  109. *
  110. **************************************************************************/
  111. /*
  112. * IconCreateDouble
  113. *
  114. * Create a double icon from a single icon. The double icon has a bitmap
  115. * consisting of 2 images of the original bitmap offset from one another.
  116. */
  117. void
  118. IconCreateDouble(
  119. Widget widget,
  120. IconInfo *oldIcon,
  121. int xOffset,
  122. int yOffset,
  123. IconInfo *newIcon,
  124. short xx,
  125. short yy)
  126. {
  127. newIcon->bitmap = iconMergeBitmaps(widget,
  128. oldIcon->bitmap, oldIcon->icon.width, oldIcon->icon.height,
  129. oldIcon->bitmap, oldIcon->icon.width, oldIcon->icon.height,
  130. xOffset, yOffset, False);
  131. newIcon->mask = iconMergeBitmaps(widget,
  132. oldIcon->mask, oldIcon->icon.width, oldIcon->icon.height,
  133. oldIcon->mask, oldIcon->icon.width, oldIcon->icon.height,
  134. xOffset, yOffset, True);
  135. newIcon->icon.width = oldIcon->icon.width + 10;
  136. newIcon->icon.height = oldIcon->icon.height + 10;
  137. newIcon->name = XtNewString("Multiple");
  138. newIcon->icon.x = xx;
  139. newIcon->icon.y = yy;
  140. newIcon->dragIcon = DtDndCreateSourceIcon(widget,
  141. newIcon->bitmap, newIcon->mask);
  142. }
  143. /*
  144. * IconDelete
  145. *
  146. * Remove the icon from its list and deallocate memory used by the icon.
  147. */
  148. void
  149. IconDelete(
  150. Widget drawArea,
  151. IconInfo *iconPtr)
  152. {
  153. IconInfo *iconList;
  154. if (iconPtr == NULL || drawArea == NULL) {
  155. return;
  156. }
  157. if (iconPtr->next != NULL) { /* iconPtr is not the tail of the list */
  158. iconPtr->next->prev = iconPtr->prev;
  159. }
  160. if (iconPtr->prev != NULL) { /* iconPtr is not the head of the list */
  161. iconPtr->prev->next = iconPtr->next;
  162. }
  163. if (iconPtr->next == NULL) { /* iconPtr is the tail of the list */
  164. iconList = iconPtr->prev;
  165. } else {
  166. iconList = iconPtr->next;
  167. }
  168. while (iconList != NULL && iconList->prev != NULL) {
  169. iconList = iconList->prev;
  170. }
  171. iconFree(iconPtr);
  172. XtVaSetValues(drawArea, XmNuserData, iconList, NULL);
  173. }
  174. /*
  175. * IconDraw
  176. *
  177. * Render given icon in the window of the given widget.
  178. */
  179. void
  180. IconDraw(
  181. Widget widget,
  182. IconInfo *iconPtr)
  183. {
  184. static GC graphicsContext = NULL;
  185. static XFontStruct *fontStruct;
  186. Display *display = XtDisplayOfObject(widget);
  187. Window window = XtWindow(widget);
  188. int screen = DefaultScreen(display);
  189. XGCValues gcValues;
  190. if (graphicsContext == NULL) {
  191. gcValues.foreground = BlackPixel(display, screen);
  192. gcValues.background = WhitePixel(display, screen);
  193. graphicsContext = XCreateGC(display, window,
  194. GCForeground | GCBackground, &gcValues);
  195. }
  196. /*
  197. * Draw icon
  198. */
  199. gcValues.clip_mask = iconPtr->mask;
  200. gcValues.clip_x_origin = iconPtr->icon.x;
  201. gcValues.clip_y_origin = iconPtr->icon.y;
  202. XChangeGC(display, graphicsContext,
  203. GCClipMask | GCClipXOrigin | GCClipYOrigin, &gcValues);
  204. XCopyPlane(display, iconPtr->bitmap, window, graphicsContext, 0, 0,
  205. iconPtr->icon.width, iconPtr->icon.height,
  206. iconPtr->icon.x, iconPtr->icon.y, 1L);
  207. /*
  208. * Draw icon name centered below icon
  209. */
  210. if (iconPtr->name != NULL) {
  211. int nameX, nameY;
  212. int direction, ascent, decent;
  213. XCharStruct overall;
  214. Widget xmScreen;
  215. if (fontStruct == NULL) {
  216. xmScreen = XmGetXmScreen(XtScreen(widget));
  217. XtVaGetValues(xmScreen, XmNfont, &fontStruct, NULL);
  218. }
  219. XTextExtents(fontStruct, iconPtr->name, strlen(iconPtr->name),
  220. &direction, &ascent, &decent, &overall);
  221. nameX = (iconPtr->icon.x + (iconPtr->icon.width/2)) -
  222. (overall.width/2);
  223. nameY = iconPtr->icon.y + iconPtr->icon.height +
  224. ICON_TEXT_YGAP + ascent;
  225. gcValues.font = fontStruct->fid;
  226. gcValues.clip_mask = None;
  227. XChangeGC(display, graphicsContext,
  228. GCFont | GCClipMask, &gcValues);
  229. XDrawString(display, window, graphicsContext, nameX, nameY,
  230. iconPtr->name, strlen(iconPtr->name));
  231. }
  232. }
  233. /*
  234. * IconInitialize
  235. *
  236. * Initialize given icon with given data. Get icon bitmap based on data
  237. * associated with the icon. This data may be a file name, a buffer or
  238. * a type name. Create source icon for dragging based on the bitmap and mask.
  239. */
  240. void
  241. IconInitialize(
  242. Widget widget,
  243. IconInfo *iconPtr,
  244. short x,
  245. short y,
  246. void *data,
  247. int dataLen,
  248. char *name,
  249. IconTyping typing)
  250. {
  251. char *iconPath;
  252. iconPath = iconGetIconPath(data, dataLen, typing, IconMask);
  253. iconPtr->mask = iconGetBitmap(widget, iconPath, IconMask,
  254. &(iconPtr->icon.width), &(iconPtr->icon.height));
  255. XtFree(iconPath);
  256. iconPath = iconGetIconPath(data, dataLen, typing, IconBitmap);
  257. iconPtr->bitmap = iconGetBitmap(widget, iconPath, IconBitmap,
  258. &(iconPtr->icon.width), &(iconPtr->icon.height));
  259. XtFree(iconPath);
  260. iconPtr->icon.x = x;
  261. iconPtr->icon.y = y;
  262. iconPtr->name = XtNewString(name);
  263. iconPtr->dragIcon = DtDndCreateSourceIcon(widget,
  264. iconPtr->bitmap, iconPtr->mask);
  265. }
  266. /*
  267. * IconNew
  268. *
  269. * Allocate memory for a new icon structure and clear.
  270. */
  271. IconInfo*
  272. IconNew()
  273. {
  274. IconInfo *iconPtr;
  275. iconPtr = (IconInfo*) XtMalloc(sizeof(IconInfo));
  276. memset(iconPtr, 0x00, sizeof(IconInfo));
  277. return iconPtr;
  278. }
  279. /*************************************************************************
  280. *
  281. * Private Icon Handling Functions
  282. *
  283. **************************************************************************/
  284. /*
  285. * iconClearBitmap
  286. *
  287. * Clear a bitmap by filling it with zeros.
  288. */
  289. static void
  290. iconClearBitmap(
  291. Display *display,
  292. Window window,
  293. GC graphicsContext,
  294. Pixmap bitmap,
  295. int width,
  296. int height)
  297. {
  298. int xx, yy;
  299. static Pixmap blankBitmap = NULL;
  300. if (blankBitmap == NULL) {
  301. blankBitmap = XCreateBitmapFromData(display, window,
  302. (char *)blankBits, blankWidth, blankHeight);
  303. }
  304. for (xx = 0; xx < width + blankWidth; xx += blankWidth) {
  305. for (yy = 0; yy < height + blankHeight; yy += blankHeight) {
  306. XCopyArea(display, blankBitmap, bitmap,
  307. graphicsContext, 0, 0,
  308. blankWidth, blankHeight, xx, yy);
  309. }
  310. }
  311. }
  312. /*
  313. * iconDefaultBitmap
  314. *
  315. * Create default icon bitmap or mask and set width and height accordingly.
  316. */
  317. static Pixmap
  318. iconDefaultBitmap(
  319. Display *display,
  320. Window window,
  321. IconBitmapPart iconPart,
  322. unsigned short *width,
  323. unsigned short *height)
  324. {
  325. static Pixmap bitmap;
  326. static Pixmap mask;
  327. if (iconPart == IconMask) { /* create default mask */
  328. if (mask == NULL) {
  329. mask = XCreateBitmapFromData(display, window,
  330. (char *)iconMaskBits, iconMaskWidth, iconMaskHeight);
  331. }
  332. *width = iconMaskWidth;
  333. *height = iconMaskHeight;
  334. return mask;
  335. } else { /* create default bitmap */
  336. if (bitmap == NULL) {
  337. bitmap = XCreateBitmapFromData(display, window,
  338. (char *)iconBits, iconWidth, iconHeight);
  339. }
  340. *width = iconWidth;
  341. *height = iconHeight;
  342. return bitmap;
  343. }
  344. }
  345. /*
  346. * iconFree
  347. *
  348. * Deallocate the icon and associated resources.
  349. */
  350. static void
  351. iconFree(
  352. IconInfo *iconPtr)
  353. {
  354. Display *display = XtDisplayOfObject(iconPtr->dragIcon);
  355. if (iconPtr == NULL) {
  356. return;
  357. }
  358. XtFree(iconPtr->name);
  359. /*
  360. * REMIND: This needs to free other things too...
  361. * XFreePixmap(display, iconPtr->bitmap);
  362. * XFreePixmap(display, iconPtr->mask);
  363. * Free(iconPtr->dragIcon);
  364. */
  365. XtFree((char *)iconPtr);
  366. }
  367. /*
  368. * iconGetBitmap
  369. *
  370. * Get a bitmap for the icon based on the path and name of the icon.
  371. * If no bitmap file is found use a built-in default.
  372. */
  373. static Pixmap
  374. iconGetBitmap(
  375. Widget widget,
  376. char *iconPath,
  377. IconBitmapPart iconPart,
  378. unsigned short *returnWidth,
  379. unsigned short *returnHeight)
  380. {
  381. Display *display = XtDisplayOfObject(widget);
  382. Window window = DefaultRootWindow(display);
  383. int status;
  384. int xHot, yHot;
  385. Pixmap bitmap;
  386. unsigned int width, height;
  387. *returnWidth = *returnHeight = 0;
  388. if (iconPath != NULL) {
  389. status = XReadBitmapFile(display, window, iconPath,
  390. &width, &height, &bitmap, &xHot, &yHot);
  391. if (status == BitmapSuccess) {
  392. *returnWidth = (unsigned short) width;
  393. *returnHeight = (unsigned short) height;
  394. } else {
  395. printf(
  396. "Unable to read icon from bitmap file \"%s\".\n"
  397. "Using default icon bitmap.\n",
  398. iconPath, NULL);
  399. bitmap = iconDefaultBitmap(display, window, iconPart,
  400. returnWidth, returnHeight);
  401. }
  402. } else {
  403. bitmap = iconDefaultBitmap(display, window, iconPart,
  404. returnWidth, returnHeight);
  405. }
  406. return bitmap;
  407. }
  408. /*
  409. * iconGetIconPath
  410. *
  411. * Get the file path and name for an icon based on the given data and
  412. * method of typing that data. This function assumes the data typing
  413. * database has been loaded with DtDtsLoadDataTypes().
  414. */
  415. static char*
  416. iconGetIconPath(
  417. void *data,
  418. int dataLen,
  419. IconTyping typing,
  420. IconBitmapPart iconPart)
  421. {
  422. char iconPath[MAXPATHLEN + 1],
  423. *iconName,
  424. *iconSuffix;
  425. switch (typing) {
  426. case IconByFile:
  427. iconName = DtDtsFileToAttributeValue(data, "ICON");
  428. break;
  429. case IconByData:
  430. iconName = DtDtsBufferToAttributeValue(data, dataLen,
  431. "ICON", NULL);
  432. break;
  433. case IconByType:
  434. iconName = DtDtsDataTypeToAttributeValue(data, "ICON", NULL);
  435. break;
  436. default:
  437. iconName = NULL;
  438. }
  439. if (iconName != NULL) {
  440. if (iconPart == IconMask) {
  441. iconSuffix = ICON_MASK_SUFFIX;
  442. } else {
  443. iconSuffix = ICON_BITMAP_SUFFIX;
  444. }
  445. sprintf(iconPath, "%s/%s.%s", ICON_PATH, iconName, iconSuffix);
  446. DtDtsFreeAttributeValue(iconName);
  447. }
  448. return XtNewString(iconPath);
  449. }
  450. /*
  451. * iconMergeBitmaps
  452. *
  453. * Create new bitmap consisting of the offset composition of the given bitmaps.
  454. */
  455. static Pixmap
  456. iconMergeBitmaps(
  457. Widget widget,
  458. Pixmap bitmap1,
  459. int width1,
  460. int height1,
  461. Pixmap bitmap2,
  462. int width2,
  463. int height2,
  464. int xOffset,
  465. int yOffset,
  466. Boolean clear)
  467. {
  468. Display *display = XtDisplayOfObject(widget);
  469. Window window = DefaultRootWindow(display);
  470. int screen = DefaultScreen(display);
  471. Pixmap mergedBitmap, blankBitmap;
  472. int extraX, extraY, width, height;
  473. static GC graphicsContext = NULL;
  474. XGCValues gcValues;
  475. extraX = width2 - width1 + xOffset + 1;
  476. if (extraX < 0) extraX = 0;
  477. width = width1 + extraX;
  478. extraY = height2 - height1 + yOffset + 1;
  479. if (extraY < 0) extraY = 0;
  480. height = height1 + extraY;
  481. mergedBitmap = XCreatePixmap(display, window, width, height, 1);
  482. if (graphicsContext == NULL) {
  483. graphicsContext = XCreateGC(display, mergedBitmap, 0L, NULL);
  484. }
  485. if (clear) {
  486. iconClearBitmap(display, window, graphicsContext, mergedBitmap,
  487. width, height);
  488. }
  489. XCopyArea(display, bitmap2, mergedBitmap, graphicsContext, 0, 0,
  490. width2, height2, xOffset, yOffset);
  491. XCopyArea(display, bitmap1, mergedBitmap, graphicsContext, 0, 0,
  492. width1, height1, 0, 0);
  493. return mergedBitmap;
  494. }