X11 Work Bench Toolkit  1.0
pixmap_helper.c
1 
2 // _ _ _ //
3 // _ __ (_)__ __ _ __ ___ __ _ _ __ | |__ ___ | | _ __ ___ _ __ ___ //
4 // | '_ \ | |\ \/ /| '_ ` _ \ / _` || '_ \ | '_ \ / _ \| || '_ \ / _ \| '__|/ __| //
5 // | |_) || | > < | | | | | || (_| || |_) | | | | || __/| || |_) || __/| | _| (__ //
6 // | .__/ |_|/_/\_\|_| |_| |_| \__,_|| .__/_____|_| |_| \___||_|| .__/ \___||_|(_)\___| //
7 // |_| |_| |_____| |_| //
8 // //
9 // pixmap and icon helpers (ultimately providing universal support) //
10 // //
12 
13 /*****************************************************************************
14 
15  X11workbench - X11 programmer's 'work bench' application and toolkit
16  Copyright (c) 2010-2016 by Bob Frazier (aka 'Big Bad Bombastic Bob')
17  all rights reserved
18 
19  DISCLAIMER: The X11workbench application and toolkit software are supplied
20  'as-is', with no warranties, either implied or explicit.
21  Any claims to alleged functionality or features should be
22  considered 'preliminary', and might not function as advertised.
23 
24  BSD-like license:
25 
26  There is no restriction as to what you can do with this software, so long
27  as you include the above copyright notice and DISCLAIMER for any distributed
28  work that is equal to or derived from this one, along with this paragraph
29  that explains the terms of the license if the source is also being made
30  available. A "derived work" describes a work that uses a significant portion
31  of the source files or algorithms that are included with this one.
32  Specifically excluded from this are files that were generated by the software,
33  or anything that is included with the software that is part of another package
34  (such as files that were created or added during the 'configure' process).
35  Specifically included is the use of part or all of any of the X11 workbench
36  toolkit source or header files in your distributed application. If you do not
37  ship the source, the above copyright statement is still required to be placed
38  in a reasonably prominent place, such as documentation, splash screens, and/or
39  'about the application' dialog boxes.
40 
41  Use and distribution are in accordance with GPL, LGPL, and/or the above
42  BSD-like license. See COPYING and README files for more information.
43 
44 
45  Additional information at http://sourceforge.net/projects/X11workbench
46 
47 ******************************************************************************/
48 
49 
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <memory.h>
53 #include <string.h>
54 #include <strings.h>
55 
56 // application header file
57 #include "pixmap_helper.h" // this will include platform_helper.h and window_helper.h
58 
59 // include pixmap data
60 
61 #include "icon_ok.xpm"
62 #include "icon_stop.xpm"
63 #include "icon_warn.xpm"
64 #include "icon_what.xpm"
65 #include "icon_splat.xpm"
66 
67 // other pixmaps (some not entirely work safe)
68 #include "icon_bang.xpm"
69 #include "icon_barney.xpm"
70 #include "icon_bear.xpm"
71 #include "icon_death.xpm"
72 #include "icon_finger.xpm"
73 #include "icon_skull.xpm"
74 #include "icon_triangle.xpm"
75 #include "icon_what_bold.xpm"
76 #include "icon_wtf.xpm"
77 #include "icon_thumbup.xpm"
78 #include "icon_thumbdown.xpm"
79 
80 
81 
82 #ifdef NO_DEBUG
83 #define DEBUG_DUMP_XPM_ATTRIBUTES(X)
84 #define DEBUG_DUMP_COLORMAP(X)
85 #else
86 static void DebugDumpXpmAttributes(const char *szFunction, int nLine, XPM_ATTRIBUTES *pAttr);
87 static void DebugDumpColormap(const XStandardColormap *pMap);
88 #define DEBUG_DUMP_XPM_ATTRIBUTES(X) DebugDumpXpmAttributes(__FUNCTION__, __LINE__, X)
89 #define DEBUG_DUMP_COLORMAP(X) DebugDumpColormap(X)
90 #endif // NO_DEBUG
91 
92 
93 #define MINIMUM_ATOM_RESOURCE_LIST_SIZE 256
94 
95 typedef struct __INTERNAL_ATOM_RESOURCE_LIST__
96 {
97  Atom aAtom;
98  char **ppResource;
99 } INTERNAL_ATOM_RESOURCE_LIST;
100 
101 static INTERNAL_ATOM_RESOURCE_LIST *pAtomResourceList = NULL;
102 static int nAtomResourceList = 0, nAtomResourceListMax = 0;
103 
104 static char **ppRegAppLarge_Internal = NULL;
105 static char **ppRegAppSmall_Internal = NULL;
106 
107 
108 //-------------------------
109 // RGB and YUV conversions
110 //-------------------------
111 
112 static int clip255(int iIn)
113 {
114  if(iIn < 0)
115  {
116  return 0;
117  }
118  else if(iIn > 255)
119  {
120  return 255;
121  }
122 
123  return iIn;
124 }
125 
126 void PXM_RGBToYUV(int iR, int iG, int iB, int *piY, int *piU, int *piV)
127 {
128 int iY, iU, iV;
129 
130  iR = clip255(iR);
131  iG = clip255(iG);
132  iB = clip255(iB);
133 
134  iY = clip255((( 66 * iR + 129 * iG + 25 * iB + 128) >> 8) + 16);
135  iU = clip255((( -38 * iR - 74 * iG + 112 * iB + 128) >> 8) + 128);
136  iV = clip255((( 112 * iR - 94 * iG - 18 * iB + 128) >> 8) + 128);
137 
138  if(piY)
139  {
140  *piY = iY;
141  }
142 
143  if(piU)
144  {
145  *piU = iU;
146  }
147 
148  if(piV)
149  {
150  *piV = iV;
151  }
152 }
153 
154 void PXM_YUVToRGB(int iY, int iU, int iV, int *piR, int *piG, int *piB)
155 {
156 int iR, iG, iB;
157 int iC = iY - 16;
158 int iD = iU - 128;
159 int iE = iV - 128;
160 
161  iR = clip255(( 298 * iC + 409 * iE + 128) >> 8);
162  iG = clip255(( 298 * iC - 100 * iD - 208 * iE + 128) >> 8);
163  iB = clip255(( 298 * iC + 516 * iD + 128) >> 8);
164 
165  if(piR)
166  {
167  *piR = iR;
168  }
169 
170  if(piG)
171  {
172  *piG = iG;
173  }
174 
175  if(piB)
176  {
177  *piB = iB;
178  }
179 }
180 
181 
182 void PXM_PixelToRGB(XStandardColormap *pMap, XColor *pColor)
183 {
184 unsigned long long lColor, l2;
185 XStandardColormap map;
186 
187 
188  if(!pColor)
189  {
190  return;
191  }
192 
193  if(!pMap)
194  {
196  pMap = &map;
197 
198 // DEBUG_DUMP_COLORMAP(pMap);
199  }
200 
201  // 'nuking' this one out is a bit difficult. I have to sort the values properly
202 
203  lColor = pColor->pixel - pMap->base_pixel;
204 
205  if(!pMap->red_mult && !pMap->green_mult && !pMap->blue_mult)
206  {
207  return;
208  }
209 
210  pColor->flags = DoRed | DoGreen | DoBlue; // pre-assign this, re-assign as needed
211 
212  if(pMap->red_mult >= pMap->green_mult &&
213  pMap->red_mult >= pMap->blue_mult) // this includes monochrome I think
214  {
215  if(!pMap->green_mult && !pMap->blue_mult)
216  {
217  // it's monochrome, so I only use red
218 
219  if(pMap->red_mult == 1)
220  {
221  l2 = ((unsigned long long)65535 * lColor);
222  }
223  else
224  {
225  l2 = ((unsigned long long)65535 * lColor) / pMap->red_mult;
226  }
227 
228  if(l2 >= 65536 * pMap->red_max)
229  {
230  l2 = 65535;
231  }
232  else if(lColor < 0)
233  {
234  l2 = 0;
235  }
236  else
237  {
238  l2 /= pMap->red_max;
239  }
240 
241  pColor->red = l2;
242  pColor->green = l2;
243  pColor->blue = l2; // since it's monochrome, though only 'DoRed' is assigned
244 
245  pColor->flags = DoRed; // usually indicates 'monochrome'
246  }
247  else if(pMap->green_mult > pMap->blue_mult)
248  {
249  // red first
250 
251  l2 = ((unsigned long long)65535 * lColor) / pMap->red_mult;
252  lColor %= pMap->red_mult;
253 
254 
255  if(l2 >= 65536 * pMap->red_max)
256  {
257  l2 = 65535 * pMap->red_max;
258  }
259  else if(lColor < 0) // won't happen
260  {
261  l2 = 0;
262  }
263  else
264  {
265  l2 /= pMap->red_max;
266  }
267 
268  pColor->red = l2;
269 
270  // then green
271 
272  l2 = ((unsigned long long)65535 * lColor) / pMap->green_mult;
273  lColor %= pMap->green_mult;
274 
275  if(l2 >= 65536 * pMap->green_max)
276  {
277  l2 = 65535 * pMap->green_max;
278  }
279  else if(lColor < 0) // won't happen
280  {
281  l2 = 0;
282  }
283  else
284  {
285  l2 /= pMap->green_max;
286  }
287 
288  pColor->green = l2;
289 
290  // and then, blue
291 
292  if(!pMap->blue_mult)
293  {
294  l2 = 0;
295  }
296  else
297  {
298  l2 = ((unsigned long long)65535 * lColor) / pMap->blue_mult;
299 
300  if(l2 >= 65536 * pMap->blue_max)
301  {
302  l2 = 65535 * pMap->blue_max;
303  }
304  else if(lColor < 0)
305  {
306  l2 = 0;
307  }
308  else
309  {
310  l2 /= pMap->blue_max;
311  }
312  }
313  pColor->blue = l2;
314  }
315  else // if(pMap->blue_mult > pMap->green_mult)
316  {
317  // red first
318 
319  l2 = ((unsigned long long)65535 * lColor) / pMap->red_mult;
320  lColor %= pMap->red_mult;
321 
322  if(l2 >= 65536 * pMap->red_max)
323  {
324  l2 = 65535 * pMap->red_max;
325  }
326  else if(lColor < 0)
327  {
328  l2 = 0;
329  }
330  else
331  {
332  l2 /= pMap->red_max;
333  }
334 
335  pColor->red = l2;
336 
337  // then blue
338 
339  l2 = ((unsigned long long)65535 * lColor) / pMap->blue_mult;
340  lColor %= pMap->blue_mult;
341 
342  if(l2 >= 65536 * pMap->blue_max)
343  {
344  l2 = 65535 * pMap->blue_max;
345  }
346  else if(lColor < 0)
347  {
348  l2 = 0;
349  }
350  else
351  {
352  l2 /= pMap->blue_max;
353  }
354 
355  pColor->blue = l2;
356 
357  // and then, green
358 
359  if(!pMap->green_mult)
360  {
361  l2 = 0;
362  }
363  else
364  {
365  l2 = ((unsigned long long)65535 * lColor) / pMap->green_mult;
366 
367  if(l2 >= 65536 * pMap->green_max)
368  {
369  l2 = 65535 * pMap->green_max;
370  }
371  else if(lColor < 0)
372  {
373  l2 = 0;
374  }
375  else
376  {
377  l2 /= pMap->green_max;
378  }
379  }
380 
381  pColor->green = l2;
382  }
383  }
384  else if(pMap->green_mult >= pMap->red_mult &&
385  pMap->green_mult >= pMap->blue_mult)
386  {
387  if(pMap->red_mult > pMap->blue_mult)
388  {
389  // green first
390 
391  l2 = ((unsigned long long)65535 * lColor) / pMap->green_mult;
392  lColor %= pMap->green_mult;
393 
394  if(l2 >= 65536 * pMap->green_max)
395  {
396  l2 = 65535 * pMap->green_max;
397  }
398  else if(lColor < 0)
399  {
400  l2 = 0;
401  }
402  else
403  {
404  l2 /= pMap->green_max;
405  }
406 
407  pColor->green = l2;
408 
409  // then red
410 
411  l2 = ((unsigned long long)65535 * lColor) / pMap->red_mult;
412  lColor %= pMap->red_mult;
413 
414  if(l2 >= 65536 * pMap->red_max)
415  {
416  l2 = 65535 * pMap->red_max;
417  }
418  else if(lColor < 0)
419  {
420  l2 = 0;
421  }
422  else
423  {
424  l2 /= pMap->red_max;
425  }
426 
427  pColor->red = l2;
428 
429  // and then, blue
430 
431  if(!pMap->blue_mult)
432  {
433  l2 = 0;
434  }
435  else
436  {
437  l2 = ((unsigned long long)65535 * lColor) / pMap->blue_mult;
438 
439  if(l2 >= 65536 * pMap->blue_max)
440  {
441  l2 = 65535 * pMap->blue_max;
442  }
443  else if(lColor < 0)
444  {
445  l2 = 0;
446  }
447  else
448  {
449  l2 /= pMap->blue_max;
450  }
451  }
452  pColor->blue = l2;
453  }
454  else // if(pMap->blue_mult > pMap->green_mult)
455  {
456  // green first
457 
458  l2 = ((unsigned long long)65535 * lColor) / pMap->green_mult;
459  lColor %= pMap->green_mult;
460 
461  if(l2 >= 65536 * pMap->green_max)
462  {
463  l2 = 65535 * pMap->green_max;
464  }
465  else if(lColor < 0)
466  {
467  l2 = 0;
468  }
469  else
470  {
471  l2 /= pMap->green_max;
472  }
473 
474  pColor->green = l2;
475 
476  // then blue
477 
478  l2 = ((unsigned long long)65535 * lColor) / pMap->blue_mult;
479  lColor %= pMap->blue_mult;
480 
481  if(l2 >= 65536 * pMap->blue_max)
482  {
483  l2 = 65535 * pMap->blue_max;
484  }
485  else if(lColor < 0)
486  {
487  l2 = 0;
488  }
489  else
490  {
491  l2 /= pMap->blue_max;
492  }
493 
494  pColor->blue = l2;
495 
496  // and then, red
497 
498  if(!pMap->red_mult)
499  {
500  l2 = 0;
501  }
502  else
503  {
504  l2 = ((unsigned long long)65535 * lColor) / pMap->red_mult;
505 
506  if(l2 >= 65536 * pMap->red_max)
507  {
508  l2 = 65535 * pMap->red_max;
509  }
510  else if(lColor < 0)
511  {
512  l2 = 0;
513  }
514  else
515  {
516  l2 /= pMap->red_max;
517  }
518  }
519 
520  pColor->red = l2;
521  }
522  }
523  else //if(pMap->blue_mult >= pMap->red_mult &&
524  // pMap->blue_mult >= pMap->green_mult)
525  {
526  if(pMap->red_mult > pMap->green_mult)
527  {
528  // blue first
529 
530  l2 = ((unsigned long long)65535 * lColor) / pMap->blue_mult;
531  lColor %= pMap->blue_mult;
532 
533  if(l2 >= 65536 * pMap->blue_max)
534  {
535  l2 = 65535 * pMap->blue_max;
536  }
537  else if(lColor < 0)
538  {
539  l2 = 0;
540  }
541  else
542  {
543  l2 /= pMap->blue_max;
544  }
545 
546  pColor->blue = l2;
547 
548  // then red
549 
550  l2 = ((unsigned long long)65535 * lColor) / pMap->red_mult;
551  lColor %= pMap->red_mult;
552 
553  if(l2 >= 65536 * pMap->red_max)
554  {
555  l2 = 65535 * pMap->red_max;
556  }
557  else if(lColor < 0)
558  {
559  l2 = 0;
560  }
561  else
562  {
563  l2 /= pMap->red_max;
564  }
565 
566  pColor->red = l2;
567 
568  // and then, green
569 
570  if(!pMap->green_mult)
571  {
572  l2 = 0;
573  }
574  else
575  {
576  l2 = ((unsigned long long)65535 * lColor) / pMap->green_mult;
577 
578  if(l2 >= 65536 * pMap->green_max)
579  {
580  l2 = 65535 * pMap->green_max;
581  }
582  else if(lColor < 0)
583  {
584  l2 = 0;
585  }
586  else
587  {
588  l2 /= pMap->green_max;
589  }
590  }
591  pColor->green = l2;
592  }
593  else // if(pMap->blue_mult > pMap->green_mult)
594  {
595  // blue first
596 
597  l2 = ((unsigned long long)65535 * lColor) / pMap->blue_mult;
598  lColor %= pMap->blue_mult;
599 
600  if(l2 >= 65536 * pMap->blue_max)
601  {
602  l2 = 65535 * pMap->blue_max;
603  }
604  else if(lColor < 0)
605  {
606  l2 = 0;
607  }
608  else
609  {
610  l2 /= pMap->blue_max;
611  }
612 
613  pColor->blue = l2;
614 
615  // then green
616 
617  l2 = ((unsigned long long)65535 * lColor) / pMap->green_mult;
618  lColor %= pMap->green_mult;
619 
620  if(l2 >= 65536 * pMap->green_max)
621  {
622  l2 = 65535 * pMap->green_max;
623  }
624  else if(lColor < 0)
625  {
626  l2 = 0;
627  }
628  else
629  {
630  l2 /= pMap->green_max;
631  }
632 
633  pColor->green = l2;
634 
635 
636  // and then, red
637 
638  if(!pMap->red_mult)
639  {
640  l2 = 0;
641  }
642  else
643  {
644  l2 = ((unsigned long long)65535 * lColor) / pMap->red_mult;
645 
646  if(l2 >= 65536 * pMap->red_max)
647  {
648  l2 = 65535 * pMap->red_max;
649  }
650  else if(lColor < 0)
651  {
652  l2 = 0;
653  }
654  else
655  {
656  l2 /= pMap->red_max;
657  }
658  }
659 
660  pColor->red = l2;
661  }
662  }
663 }
664 
665 void PXM_RGBToPixel(XStandardColormap *pMap, XColor *pColor)
666 {
667 unsigned long lR, lG, lB;
668 XStandardColormap map;
669 
670 
671  if(!pColor)
672  {
673  return;
674  }
675 
676  if(!pMap)
677  {
679  pMap = &map;
680 
681 // DEBUG_DUMP_COLORMAP(pMap);
682  }
683 
684  // this one is straightforward, right out of the docs for the XStandardColormap structure
685 
686  lR = lG = lB = 0; // pre-assign
687 
688  if(!pColor->flags) // assume all 3 primaries, assign accordingly
689  {
690  pColor->flags = DoRed | DoGreen | DoBlue;
691  }
692 
693  if(pColor->flags & DoRed)
694  {
695  lR = (unsigned long)(pColor->red * pMap->red_max) / 65535;
696  }
697 
698  if(lR < 0)
699  {
700  lR = 0;
701  }
702  else if(lR > pMap->red_max)
703  {
704  lR = pMap->red_max;
705  }
706 
707  if(pColor->flags & DoGreen)
708  {
709  lG = (unsigned long)(pColor->green * pMap->green_max) / 65535;
710  }
711 
712  if(lG < 0)
713  {
714  lG = 0;
715  }
716  else if(lG > pMap->green_max)
717  {
718  lG = pMap->green_max;
719  }
720 
721  if(pColor->flags & DoBlue)
722  {
723  lB = (unsigned long)(pColor->blue * pMap->blue_max) / 65535;
724  }
725 
726  if(lB < 0)
727  {
728  lB = 0;
729  }
730  else if(lB > pMap->blue_max)
731  {
732  lB = pMap->blue_max;
733  }
734 
735  pColor->pixel = (pMap->base_pixel
736  + lR * pMap->red_mult
737  + lG * pMap->green_mult
738  + lB * pMap->blue_mult)
739  & 0xffffffffL;
740 }
741 
742 
743 void PXM_RegisterAppIcons(char *ppRegAppLarge[], char *ppRegAppSmall[])
744 {
745  ppRegAppLarge_Internal = ppRegAppLarge;
746  ppRegAppSmall_Internal = ppRegAppSmall;
747 }
748 
749 static char **GetPreDefinedIconResource(int idIcon)
750 {
751 char **pData = NULL;
752 
753  switch(idIcon)
754  {
755  case ID_APPLICATION:
756  if(ppRegAppSmall_Internal)
757  {
758  pData = ppRegAppSmall_Internal;
759  }
760  else
761  {
762  pData = icon_ok_xpm; // TODO: make a 19x19 version
763  }
764  break;
765  case ID_ICON_APP:
766  if(ppRegAppLarge_Internal)
767  {
768  pData = ppRegAppLarge_Internal;
769  }
770  else
771  {
772  pData = icon_ok_xpm;
773  }
774  break;
775  case ID_ICON_OK:
776  pData = icon_ok_xpm;
777  break;
778  case ID_ICON_STOP:
779  pData = icon_stop_xpm;
780  break;
781  case ID_ICON_WARN:
782  pData = icon_warn_xpm;
783  break;
784  case ID_ICON_WHAT:
785  pData = icon_what_xpm;
786  break;
787  case ID_ICON_SPLAT:
788  pData = icon_splat_xpm;
789  break;
790  case ID_ICON_BANG:
791  pData = icon_bang_xpm;
792  break;
793  case ID_ICON_TRIANGLE:
794  pData = icon_triangle_xpm;
795  break;
796  case ID_ICON_WHAT_BOLD:
797  pData = icon_what_bold_xpm;
798  break;
799  case ID_ICON_WTF:
800  pData = icon_wtf_xpm;
801  break;
802  case ID_ICON_DEATH:
803  pData = icon_death_xpm;
804  break;
805  case ID_ICON_FINGER:
806  pData = icon_finger_xpm;
807  break;
808  case ID_ICON_SKULL:
809  pData = icon_skull_xpm;
810  break;
811  case ID_ICON_THUMBUP:
812  pData = icon_thumbup_xpm;
813  break;
814  case ID_ICON_THUMBDOWN:
815  pData = icon_thumbdown_xpm;
816  break;
817  case ID_ICON_BEAR:
818  pData = icon_bear_xpm;
819  break;
820  case ID_ICON_BARNEY: // this is a joke. really.
821  pData = icon_barney_xpm;
822  break;
823  }
824 
825  return pData;
826 }
827 
828 static void RegisterIconResource(Atom aIcon, char **ppResource)
829 {
830 int i1;
831 
832  if(!pAtomResourceList)
833  {
834  pAtomResourceList = (INTERNAL_ATOM_RESOURCE_LIST *)
835  WBAlloc(MINIMUM_ATOM_RESOURCE_LIST_SIZE * sizeof(*pAtomResourceList));
836 
837  if(!pAtomResourceList)
838  {
839  WB_ERROR_PRINT("%s - not enough memoory for atom resource list\n", __FUNCTION__);
840  return;
841  }
842 
843  nAtomResourceList = 0;
844  nAtomResourceListMax = MINIMUM_ATOM_RESOURCE_LIST_SIZE;
845  }
846 
847  for(i1=0; i1 < nAtomResourceList; i1++)
848  {
849  if(pAtomResourceList[i1].aAtom == aIcon) // already there?
850  {
851  WB_ERROR_PRINT("%s - matching atom already in the list (ignoring)\n", __FUNCTION__);
852  return; // fow now I just leave. later I might allow editing
853  }
854  }
855 
856  if((nAtomResourceList + 1) >= nAtomResourceListMax)
857  {
858  int iNewSize = MINIMUM_ATOM_RESOURCE_LIST_SIZE / 2 + nAtomResourceListMax;
859 
860  void *pTemp = WBReAlloc(pAtomResourceList, iNewSize);
861  if(!pTemp)
862  {
863  WB_ERROR_PRINT("%s - not enough memoory for atom resource list re-alloc\n", __FUNCTION__);
864  return;
865  }
866 
867  pAtomResourceList = (INTERNAL_ATOM_RESOURCE_LIST *)pTemp;
868  nAtomResourceListMax += MINIMUM_ATOM_RESOURCE_LIST_SIZE / 2;
869  }
870 
871  pAtomResourceList[nAtomResourceList].aAtom = aIcon;
872  pAtomResourceList[nAtomResourceList].ppResource = ppResource;
873  nAtomResourceList++;
874 }
875 
876 static const char * const szPreDefinedIconResources[] =
877 {
878  "ID_APPLICATION",
879  "ID_ICON_OK",
880  "ID_ICON_STOP",
881  "ID_ICON_WARN",
882  "ID_ICON_WHAT",
883  "ID_ICON_QUESTION",
884  "ID_ICON_SPLAT",
885  "ID_ICON_ASTERISK",
886  "ID_ICON_BANG",
887  "ID_ICON_TRIANGLE",
888  "ID_ICON_WHAT_BOLD",
889  "ID_ICON_WTF",
890  "ID_ICON_DEATH",
891  "ID_ICON_FINGER",
892  "ID_ICON_SKULL",
893  "ID_ICON_THUMBUP",
894  "ID_ICON_THUMBDOWN",
895  "ID_ICON_BEAR",
896  "ID_ICON_BARNEY",
897  "ID_ICON_APP"
898 };
899 
900 static char **GetRegisteredIconResource(Atom aIcon)
901 {
902 static int iHasBeenRegistered = 0;
903 int i1, i2;
904 
905  // if the pre-defined atoms have not yet been registered, do it NOW
906 
907  if(!iHasBeenRegistered)
908  {
909  for(i1=ID_ICON_FIRST, i2=0;
910  i1 <= ID_ICON_LAST
911  && i2 < sizeof(szPreDefinedIconResources)/sizeof(szPreDefinedIconResources[0]);
912  i1++, i2++)
913  {
914  Atom aTemp = WBGetAtom(WBGetDefaultDisplay(), szPreDefinedIconResources[i2]);
915 
916  if(aTemp != None)
917  {
918  RegisterIconResource(aTemp, GetPreDefinedIconResource(i1));
919  }
920  }
921 
922  iHasBeenRegistered = 1;
923  }
924 
925  for(i1=0; i1 < nAtomResourceList; i1++)
926  {
927  if(pAtomResourceList[i1].aAtom == aIcon) // already there?
928  {
929  return pAtomResourceList[i1].ppResource;
930  }
931  }
932 
933  return NULL;
934 }
935 
936 
937 
938 Pixmap PXM_GetIconPixmap(int idIcon, XPM_ATTRIBUTES *pAttr, Pixmap *pMask)
939 {
940 char **pData;
941 
942 
943  pData = GetPreDefinedIconResource(idIcon);
944 
945  if(!pData)
946  {
947  if(pAttr)
948  {
949  bzero(pAttr, sizeof(*pAttr));
950  }
951 
952  if(pMask)
953  {
954  *pMask = None;
955  }
956 
957  return None;
958  }
959 
960  return PXM_LoadPixmap(pData, pAttr, pMask);
961 }
962 
963 
964 Pixmap PXM_GetIconPixmapFromAtom(Atom aIcon, XPM_ATTRIBUTES *pAttr, Pixmap *pMask /* = NULL*/)
965 {
966 char **pData;
967 
968 
969  pData = GetRegisteredIconResource(aIcon);
970 
971  if(!pData)
972  {
973  if(pAttr)
974  {
975  bzero(pAttr, sizeof(*pAttr));
976  }
977 
978  if(pMask)
979  {
980  *pMask = None;
981  }
982 
983  return None;
984  }
985 
986  return PXM_LoadPixmap(pData, pAttr, pMask);
987 }
988 
989 
990 Pixmap PXM_LoadPixmap(char *ppXPM[], XPM_ATTRIBUTES *pAttr, Pixmap *pMask /* = NULL*/)
991 {
992 Pixmap pixRval = None, pixRval2 = None;
993 XPM_ATTRIBUTES xattr;
994 //#ifndef NO_DEBUG
995 //WB_UINT64 ullTime = WBGetTimeIndex();
996 //#endif // NO_DEBUG
997 
998 
999  if(!ppXPM)
1000  {
1001  if(pAttr)
1002  {
1003  bzero(pAttr, sizeof(*pAttr));
1004  }
1005 
1006  if(pMask)
1007  {
1008  *pMask = None;
1009  }
1010 
1011  return None;
1012  }
1013 
1014  bzero(&xattr, sizeof(xattr));
1015 
1016 // WB_ERROR_PRINT("TEMPORARY: %s line %d delta tick %lld\n", __FUNCTION__, __LINE__, (WBGetTimeIndex() - ullTime));
1017 
1018 #ifdef X11WORKBENCH_TOOLKIT_HAVE_XPM
1020 #endif // X11WORKBENCH_TOOLKIT_HAVE_XPM
1022  ppXPM, &pixRval, &pixRval2, &xattr);
1023 #ifdef X11WORKBENCH_TOOLKIT_HAVE_XPM
1025 #endif // X11WORKBENCH_TOOLKIT_HAVE_XPM
1026 
1027 // WB_ERROR_PRINT("TEMPORARY: %s line %d delta tick %lld\n", __FUNCTION__, __LINE__, (WBGetTimeIndex() - ullTime));
1028 
1029  if(pAttr)
1030  {
1031  memcpy(pAttr, &xattr, sizeof(xattr));
1032  }
1033  else
1034  {
1036  {
1037  DEBUG_DUMP_XPM_ATTRIBUTES(&xattr);
1038  }
1039 
1040  XPM_FREE_ATTRIBUTES(&xattr);
1041  }
1042 
1043  if(pMask)
1044  {
1045  *pMask = pixRval2;
1046  }
1047  else if(pixRval2 != None) // free pixRval2 if it was allocated (it's the 'mask')
1048  {
1050  XFreePixmap(WBGetDefaultDisplay(), pixRval2);
1052  }
1053 
1054  return(pixRval);
1055 }
1056 
1057 Pixmap PXM_ImageToPixmap(Display *pDisplay, Drawable dw, XImage *pImage,
1058  unsigned long clrFGPixel, unsigned long clrBGPixel)
1059 {
1060 Pixmap pxRval;
1061 GC gc;
1062 XGCValues gcv;
1063 int iW, iH;
1064 
1065  if(!pDisplay)
1066  {
1067  pDisplay = WBGetDefaultDisplay();
1068  }
1069 
1070  if(!pImage)
1071  {
1072  WB_ERROR_PRINT("%s - pImage is NULL\n", __FUNCTION__);
1073  return None;
1074  }
1075 
1076  iW = pImage->width;
1077  iH = pImage->height;
1078 
1079  if(!iW || !iH)
1080  {
1081  WB_ERROR_PRINT("%s - Image width/height not valid, iW=%d,iH=%d\n", __FUNCTION__, iW, iH);
1082  return None;
1083  }
1084 
1086  pxRval = XCreatePixmap(pDisplay, dw, iW, iH, DefaultDepth(pDisplay, DefaultScreen(pDisplay)));
1088 
1089  if(pxRval == None)
1090  {
1091  WB_ERROR_PRINT("%s - XCreatePixmap failed\n", __FUNCTION__);
1092  return None;
1093  }
1094 
1095  // I will need to create a GC. Make it a simple one that only specifies FG and BG
1096 
1097  gcv.foreground = clrFGPixel;//BlackPixel(pDisplay, DefaultScreen(pDisplay));
1098  gcv.background = clrBGPixel;//WhitePixel(pDisplay, DefaultScreen(pDisplay));
1099 
1100  // NOTE: for monochrome masks I'd likely use '1' for foreground, '0' for background
1101 
1103  gc = XCreateGC(pDisplay, dw, (GCForeground | GCBackground), &gcv);
1105 
1106  if(gc == None)
1107  {
1108  WB_ERROR_PRINT("%s - XCreateGC failed\n", __FUNCTION__);
1109 
1111  XFreePixmap(pDisplay, pxRval);
1113  return None;
1114  }
1115  else
1116  {
1118  XPutImage(pDisplay, pxRval, gc, pImage, 0, 0, 0, 0, iW, iH); // and now I have a copy of it
1119 
1120  XFreeGC(pDisplay, gc);
1122  }
1123 
1124  return pxRval;
1125 }
1126 
1127 
1128 Pixmap PXM_ImageToPixmap0(Display *pDisplay, Drawable dw, XImage *pImage)
1129 {
1130  if(!pDisplay)
1131  {
1132  pDisplay = WBGetDefaultDisplay();
1133  }
1134 
1135  return PXM_ImageToPixmap(pDisplay, dw, pImage,
1136  BlackPixel(pDisplay, DefaultScreen(pDisplay)),
1137  WhitePixel(pDisplay, DefaultScreen(pDisplay)));
1138 }
1139 
1140 
1141 XImage *PXM_PixmapToImage(Display *pDisplay, Pixmap pxImage)
1142 {
1143 XImage *pRval;
1144 int iX=0, iY=0;
1145 Window winRoot; // not used, still needed?
1146 unsigned int iWidth=0, iHeight=0, iBorder;
1147 unsigned int uiDepth = 0;
1148 
1149 
1150  if(!pDisplay)
1151  {
1152  pDisplay = WBGetDefaultDisplay();
1153  }
1154 
1155  // TODO: special handling for pxImage == None ???
1156 
1157  if(pxImage == None)
1158  {
1159  return NULL;
1160  }
1161 
1163 
1164  // use XGetGeometry to obtain the characteristics of the pixmap. iX and iY SHOULD be zero...
1165  XGetGeometry(pDisplay, pxImage, &winRoot, &iX, &iY, &iWidth, &iHeight, &iBorder, &uiDepth);
1166 
1167  if(!iWidth || !iHeight)
1168  {
1169  pRval = NULL;
1170  }
1171  else
1172  {
1173  // TODO: do I still need iX and iY?
1174  pRval = XGetImage(pDisplay, pxImage, 0, 0, iWidth, iHeight, -1L, ZPixmap);
1175  }
1176 
1178 
1179  return pRval;
1180 }
1181 
1182 
1183 
1184 
1185 void PXM_OnExit(void)
1186 {
1187  if(pAtomResourceList)
1188  {
1189  WBFree(pAtomResourceList);
1190  pAtomResourceList = NULL;
1191  }
1192 
1193  nAtomResourceList = 0;
1194  nAtomResourceListMax = 0;
1195 
1196  ppRegAppLarge_Internal = NULL;
1197  ppRegAppSmall_Internal = NULL;
1198 }
1199 
1200 
1201 
1202 #ifndef NO_DEBUG
1203 static void DebugDumpXpmAttributes(const char *szFunction, int nLine, XPM_ATTRIBUTES *pAttr)
1204 {
1205  WBDebugPrint("%s line %d XPM_ATTRIBUTES contain:\n", szFunction, nLine);
1206 #if defined(X11WORKBENCH_TOOLKIT_HAVE_XPM)
1207  WBDebugPrint(" valuemask: %ld\n", pAttr->valuemask);
1208  WBDebugPrint(" visual: %p\n", pAttr->visual);
1209  WBDebugPrint(" colormap: %p\n", (void *)pAttr->colormap);
1210 #endif // defined(X11WORKBENCH_TOOLKIT_HAVE_XPM)
1211 
1212  WBDebugPrint(" depth: %u\n", pAttr->depth);
1213  WBDebugPrint(" width: %u\n", pAttr->width);
1214  WBDebugPrint(" height: %u\n", pAttr->height);
1215 
1216 #if defined(X11WORKBENCH_TOOLKIT_HAVE_XPM)
1217  WBDebugPrint(" x_hotspot: %u\n", pAttr->x_hotspot);
1218  WBDebugPrint(" y_hotspot: %u\n", pAttr->y_hotspot);
1219  WBDebugPrint(" cpp: %u\n", pAttr->cpp);
1220  WBDebugPrint(" pixels: %p\n", pAttr->pixels);
1221  WBDebugPrint(" npixels: %u\n", pAttr->npixels);
1222  WBDebugPrint(" colorsymbols: %p\n", pAttr->colorsymbols);
1223  WBDebugPrint(" numsymbols: %u\n", pAttr->numsymbols);
1224  WBDebugPrint(" rgb_fname: %s\n", pAttr->rgb_fname);
1225  WBDebugPrint(" nextensions: %u\n", pAttr->nextensions);
1226  WBDebugPrint(" extensions: %p\n", pAttr->extensions);
1227  WBDebugPrint(" ncolors: %u\n", pAttr->ncolors);
1228  WBDebugPrint(" colorTable: %p\n", pAttr->colorTable);
1229  WBDebugPrint(" mask_pixel: %u\n", pAttr->mask_pixel);
1230  WBDebugPrint(" exactColors: %c\n", pAttr->exactColors ? 'T' : 'F');
1231  WBDebugPrint(" closeness: %u\n", pAttr->closeness);
1232  WBDebugPrint(" red_closeness: %u\n", pAttr->red_closeness);
1233  WBDebugPrint(" green_closeness: %u\n", pAttr->green_closeness);
1234  WBDebugPrint(" blue_closeness: %u\n", pAttr->blue_closeness);
1235  WBDebugPrint(" color_key: %d\n", pAttr->color_key);
1236  WBDebugPrint(" alloc_pixels: %p\n", pAttr->alloc_pixels);
1237  WBDebugPrint(" nalloc_pixels: %d\n", pAttr->nalloc_pixels);
1238  WBDebugPrint(" alloc_close_colors: %c\n", pAttr->alloc_close_colors ? 'T' : 'F');
1239  WBDebugPrint(" bitmap_format: %d\n", pAttr->bitmap_format);
1240  WBDebugPrint(" alloc_color: %p\n", pAttr->alloc_color);
1241  WBDebugPrint(" free_colors: %p\n", pAttr->free_colors);
1242  WBDebugPrint(" color_closure: %p\n", pAttr->color_closure);
1243 #endif // defined(X11WORKBENCH_TOOLKIT_HAVE_XPM)
1244 }
1245 
1246 static void DebugDumpColormap(const XStandardColormap *pMap)
1247 {
1248  WBDebugPrint("XStandardColormap: %p\n", pMap);
1249  WBDebugPrint(" colormap = %lld\n", (WB_UINT64)pMap->colormap);
1250  WBDebugPrint(" red_max = %ld\n", pMap->red_max);
1251  WBDebugPrint(" red_mult = %ld\n", pMap->red_mult);
1252  WBDebugPrint(" green_max = %ld\n", pMap->green_max);
1253  WBDebugPrint(" green_mult = %ld\n", pMap->green_mult);
1254  WBDebugPrint(" blue_max = %ld\n", pMap->blue_max);
1255  WBDebugPrint(" blue_mult = %ld\n", pMap->blue_mult);
1256  WBDebugPrint(" base_pixel = %ld (%08lxH)\n", pMap->base_pixel, pMap->base_pixel);
1257 }
1258 
1259 
1260 #endif // !NO_DEBUG
1261