1 #include <assert.h>
2 #include <stdlib.h>
3 #include <stdio.h>
4 
5 #include <X11/xpm.h>
6 #include <X11/Xmu/StdCmap.h>
7 #include <X11/Xmu/Atoms.h>
8 
9 #include <Xm/Xm.h>
10 #include <Xm/Form.h>
11 #include <Xm/PushB.h>
12 
13 // define to 0 for default visual - a visualid to get specific visual
14 #define WANT_VISUALID 0
15 
16 static const char * home_xpm[] = {
17   "24 24 11 1",
18   " 	c None",
19   ".	c #000000",
20   "+	c #808080",
21   "@	c #898989",
22   "#	c #C0C0C0",
23   "$	c #F9F9F9",
24   "%	c #424242",
25   "&	c #A4A4A4",
26   "*	c #5D5D5D",
27   "=	c #C1C1C1",
28   "-	c #DFDFDF",
29   "                        ", "                        ", "                        ",
30   "           ..           ", "           ..           ", "      .............     ",
31   "     ..+............    ", "    ..+@+............   ", "   ..+###+............  ",
32   "  ..+#$$$#+............ ", " ...#$$$$$#+.......%%   ", "   .$+&$$$+++....%**%   ",
33   "   .$&#$$$+#$.*%**%+%   ", "   .$##$$$=#$$**++++%   ", "   .$$$$$$--$$++++%+%   ",
34   "   .$$$$$$$$$$+%++*+%   ", "   .$$$@@#-$$$+*++++%   ", "   .$$$@##-$$$+%+++%%   ",
35   "   .$$$###-$$$+++%%     ", "   .%+####-$$$+%%       ", "     %%%%%%%..%         ",
36   "                        ", "                        ", "                        "
37 };
38 
39 
40 Pixmap
createPixmapFromXpm(Widget widget,const char ** xpm)41 createPixmapFromXpm(Widget widget, const char ** xpm)
42 {
43   Pixmap pixels = 0;
44   Widget shell = widget;
45   while (! XtIsShell(shell) && shell != (Widget) NULL) {
46     shell = XtParent(shell);
47   }
48   assert(shell != (Widget) NULL);
49   fprintf(stderr, "shell: %p\n", shell);
50   Display * display = XtDisplay(shell);
51 
52   XpmAttributes attrs;
53   attrs.visual = NULL;
54   attrs.colormap = 0;
55   attrs.depth = 0;
56   attrs.valuemask = XpmVisual | XpmColormap | XpmDepth;
57 
58   XtVaGetValues(shell, XmNcolormap, &attrs.colormap, NULL);
59   XtVaGetValues(shell, XmNdepth, &attrs.depth, NULL);
60   XtVaGetValues(shell, XmNvisual, &attrs.visual, NULL);
61   if ( attrs.visual == NULL ) {
62     fprintf(stderr, "attrs.visual for shell was NULL - using default\n");
63     attrs.visual = DefaultVisual(display, DefaultScreen(display));
64     attrs.depth = DefaultDepth(display, DefaultScreen(display));
65     attrs.colormap = DefaultColormap(display, DefaultScreen(display));
66   }
67 
68   /* I'm questioning the use of the root Window here... */
69   /* An alternative approach could maybe be to set it up once the window was
70    * created (so we can use the actual window in question) through the use
71    * of XtAddCallback()? */
72 
73   Drawable draw = RootWindow(display, DefaultScreen(display));
74   Pixmap stencil = 0;
75 
76   // FIXME: that cast is pretty nasty -- get rid of it. 20020319 mortene.
77   int error = XpmCreatePixmapFromData(display, draw, (char **)xpm, &pixels, &stencil, &attrs);
78 
79   if (error != XpmSuccess) {
80     fprintf(stderr, "XpmCreatePixmapFromData() failed: %d", error);
81     return (Pixmap) 0;
82   }
83 
84   if (stencil) {
85     Pixel bg;
86     XtVaGetValues(widget, XmNbackground, &bg, NULL);
87 
88     XImage * pixmap = XGetImage(display, pixels, 0, 0, attrs.width, attrs.height,
89                                 0xffffffff, ZPixmap);
90     XImage * mask = XGetImage(display, stencil, 0, 0, attrs.width, attrs.height,
91                               0xffffffff, ZPixmap);
92     assert(pixmap != NULL && mask != NULL);
93 
94     for (unsigned int x = 0; x < attrs.width; x++) {
95       for (unsigned int y = 0; y < attrs.height; y++) {
96         Pixel pixel = XGetPixel(mask, x, y);
97         Bool usebg = (pixel == 0);
98         if (usebg) { // background must be set in image
99           XPutPixel(pixmap, x, y, bg);
100         }
101       }
102     }
103 
104     GC temp = XCreateGC(display, pixels, 0, NULL);
105     XPutImage(display, pixels, temp, pixmap,
106               0, 0, 0, 0, attrs.width, attrs.height);
107     XFreeGC(display, temp);
108 
109     XDestroyImage(pixmap);
110     XDestroyImage(mask);
111   }
112   return pixels;
113 }
114 
115 int
main(int argc,char ** argv)116 main(int argc, char ** argv)
117 {
118 
119   setbuf(stdout, NULL);
120   setbuf(stderr, NULL);
121 
122   Display * display = XOpenDisplay(NULL);
123   assert(display != NULL);
124   XSynchronize(display, True);
125 
126   XtAppContext context = XtCreateApplicationContext();
127 
128   Widget appshell = XtVaAppInitialize(&context, "SoXtTest", NULL, 0, &argc, argv, NULL, NULL);
129   fprintf(stderr, "appshell: %p\n", appshell);
130 
131 #if WANT_VISUALID
132   int i, numvisuals;
133   unsigned int wanted = WANT_VISUALID;
134   XVisualInfo templ;
135   XVisualInfo * visuals = XGetVisualInfo(display, VisualNoMask, &templ, &numvisuals);
136   for ( i = 0; i < numvisuals; i++ ) {
137     if ( visuals[i].visualid == wanted ) goto selected;
138   }
139   assert(0 && "no visual selected");
140 selected:
141 
142   Visual * visual = visuals[i].visual;
143   int visualid = visuals[i].visualid;
144   int depth = visuals[i].depth;
145   Colormap colormap = 0;
146 
147   fprintf(stderr, "visualid: %d, depth: %d, class: %s\n", visualid, depth, visuals[i].c_class == DirectColor ? "DirectColor" : "Other");
148 
149   int numcmaps;
150   XStandardColormap * stdcolormaps = NULL;
151   if ( XmuLookupStandardColormap(display, visuals[i].screen, visuals[i].visualid, visuals[i].depth,
152                                  XA_RGB_DEFAULT_MAP, False, True) &&
153        XGetRGBColormaps(display, RootWindow(display, visuals[i].screen),
154                         &stdcolormaps, &numcmaps, XA_RGB_DEFAULT_MAP) ) {
155     for ( int j = 0; j < numcmaps; j++ ) {
156       if (stdcolormaps[j].visualid == visuals[i].visualid) {
157         colormap = stdcolormaps[j].colormap;
158         goto cont;
159       }
160     }
161     colormap = XCreateColormap(display, RootWindow(display, visuals[i].screen), visuals[i].visual, AllocNone);
162     fprintf(stderr, "standard RGB colormaps did not work with visual - created own (%ld)", colormap);
163   } else {
164     assert(0);
165   }
166 
167 cont:
168   fprintf(stderr, "colormap: %ld\n", colormap);
169 #else
170   Visual * visual = NULL;
171   int depth = 0;
172   Colormap colormap = 0;
173 
174   int snum = XDefaultScreen(display);
175   visual = XDefaultVisual(display, snum);
176   depth = XDefaultDepth(display, snum);
177   colormap = XDefaultColormap(display, snum);
178 
179   fprintf(stderr, "visual: %p, depth: %d\n", visual, depth);
180   fprintf(stderr, "colormap: %ld\n", colormap);
181 #endif
182 
183   XtVaSetValues(appshell,
184     XmNwidth, 100,
185     XmNheight, 100,
186     XmNvisual, visual,
187     XmNcolormap, colormap,
188     XmNdepth, depth,
189     NULL);
190 
191   Widget form = XtVaCreateManagedWidget(
192     "form", xmFormWidgetClass,
193     appshell,
194     NULL);
195 
196   Widget button = XtVaCreateManagedWidget(
197     "button", xmPushButtonWidgetClass,
198     form,
199     XmNtopAttachment, XmATTACH_FORM,
200     XmNleftAttachment, XmATTACH_FORM,
201     XmNbottomAttachment, XmATTACH_FORM,
202     XmNrightAttachment, XmATTACH_FORM,
203     NULL);
204 
205   Pixmap pixmap = createPixmapFromXpm(button, home_xpm);
206   XtVaSetValues(button,
207     XmNlabelType, XmPIXMAP,
208     XmNlabelPixmap, pixmap,
209     XmNlabelInsensitivePixmap, pixmap,
210     XmNselectPixmap, pixmap,
211     XmNselectInsensitivePixmap, pixmap,
212     NULL);
213 
214   Widget list[] = { appshell, form, button, NULL };
215   XtSetWMColormapWindows(appshell, list, 3);
216 
217   XtRealizeWidget(appshell);
218   XtAppMainLoop(context);
219 }
220 
221