1 /*
2 * Motif Tools Library, Version 3.1
3 * $Id: GetPixmap.c,v 1.2 2001/09/19 02:57:18 grmcdorman Exp $
4 *
5 * Written by David Flanagan.
6 * Copyright (c) 1992-2001 by David Flanagan.
7 * All Rights Reserved. See the file COPYRIGHT for details.
8 * This is open source software. See the file LICENSE for details.
9 * There is no warranty for this software. See NO_WARRANTY for details.
10 *
11 * $Log: GetPixmap.c,v $
12 * Revision 1.2 2001/09/19 02:57:18 grmcdorman
13 * This change makes the following modifications:
14 * A new program, printConfig, is provided. This is built by a
15 * simple rule in the Makefile and not installed. It prints
16 * significant defines from Xmt.tmpl.
17 *
18 * XmtP.h is now generated from XmtP.h.in using printConfig. As
19 * a result, code compiled outside of the Xmt Imakefiles will
20 * have all of the Xmt.tmpl defines.
21 *
22 * Source files are modified to use XmtP.h instead of Xmt.h.
23 *
24 * WorkingBox.c is modified to use the new Progress widget.
25 * It can be compiled in the old style if WORKINGBOX_USE_SCALE is
26 * defined at compile time.
27 *
28 * Because XmtP.h is generated dynamically, it is removed from CVS
29 * with this check-in.
30 *
31 * Revision 1.1.1.1 2001/02/10 13:42:46 motiftools
32 * Initial import of Xmt310 to CVS
33 *
34 *
35 */
36
37 #include <stdio.h>
38 #include <ctype.h>
39 #include <Xmt/XmtP.h>
40 #include <Xmt/Pixmap.h>
41 #include <Xmt/Xpm.h>
42 #include <Xmt/Xbm.h>
43 #include <Xmt/Color.h>
44 #include <Xmt/AppResP.h>
45 #include <Xmt/ConvertersP.h>
46 #include <Xmt/LookupP.h>
47 #include <X11/IntrinsicP.h>
48
49 #if NeedFunctionPrototypes
GetPixmap(Widget object,StringConst str,XmtColorTable table,Boolean get_bitmap)50 static Pixmap GetPixmap(Widget object, StringConst str, XmtColorTable table,
51 Boolean get_bitmap)
52 #else
53 static Pixmap GetPixmap(object, str, table, get_bitmap)
54 Widget object;
55 StringConst str;
56 XmtColorTable table;
57 Boolean get_bitmap;
58 #endif
59 {
60 Widget w, shell;
61 Display *display;
62 Screen *screen;
63 Visual *visual;
64 Colormap colormap;
65 unsigned int depth;
66 XmtAppResources *app;
67 XmtImage *xmtimage = NULL;
68 struct {
69 char *bits;
70 int width, height, hot_x, hot_y;
71 } xbmdata;
72 Pixmap pixmap = None;
73 String name = NULL;
74 String table_string;
75 String filename = NULL;
76 String path = NULL;
77 Boolean pixmap_file = False;
78 Boolean bitmap_file = False;
79 XtCacheRef color_table_cache_ref;
80 XtCacheRef refs[2];
81 Boolean free_color_table = False;
82 static int unique_image_number;
83 extern char *getenv();
84
85 for(w=object; !XtIsWidget(w); w = XtParent(w));
86 shell = XmtGetShell(w);
87
88 app = XmtGetApplicationResources(shell);
89 screen = XtScreen(w);
90 display = DisplayOfScreen(screen);
91 visual = XmtGetVisual(shell);
92 colormap = w->core.colormap;
93 depth = w->core.depth;
94 if (!table) table = app->colortable;
95
96 /*
97 * see if it is a literal XPM file
98 */
99 if (!get_bitmap && strncmp(str, "/* XPM */", 9) == 0) {
100 xmtimage = XmtParseXpmString(str);
101 if (xmtimage) {
102 name = XtMalloc(8);
103 sprintf(name, "_%d_", unique_image_number++);
104 goto found;
105 }
106 else return None;
107 }
108
109 /*
110 * see if it is a literal XBM file
111 */
112 xbmdata.bits = NULL;
113 if (strncmp(str, "#define", 7) == 0) {
114 if (XmtParseXbmString(str, &xbmdata.bits,
115 &xbmdata.width, &xbmdata.height,
116 &xbmdata.hot_x, &xbmdata.hot_y)) {
117 name = XtMalloc(16);
118 sprintf(name, "_Xmt%d", unique_image_number++);
119 goto found;
120 }
121 else
122 return None;
123 }
124
125 /*
126 * Otherwise it is a single name, optionally followed by a color table.
127 * If there is a colon, parse the color table, and get a null-terminated
128 * copy of the single name.
129 * In either case, name is set to the image name.
130 * if (name != str) then name must be freed later.
131 */
132 table_string = strchr(str, ':');
133 if (table_string) {
134 register int i;
135
136 table_string++; /* points to first char after colon */
137 if (!get_bitmap) {
138 if (_XmtColorTableConverter != NULL) {
139 XrmValue from, to;
140 XrmValue color_table_args[2];
141 XmtColorTable parent_table;
142 Boolean status;
143
144 parent_table = table;
145 from.addr = table_string;
146 from.size = strlen(table_string);
147 to.addr = (XPointer)&table;
148 to.size = sizeof(XmtColorTable);
149 color_table_args[0].addr = (XPointer)&parent_table;
150 color_table_args[0].size = sizeof(XmtColorTable);
151 color_table_args[1].addr = (XPointer)&screen;
152 color_table_args[1].size = sizeof(Screen *);
153 status = XtCallConverter(display, _XmtColorTableConverter,
154 color_table_args, 2,
155 &from, &to, &color_table_cache_ref);
156 if (!status)
157 XmtWarningMsg("XmtGetPixmap", "badColor",
158 "continuing with default color table.");
159 else
160 free_color_table = True;
161 }
162 else {
163 XmtWarningMsg("XmtGetPixmap", "noColor",
164 "No XmtColorTable converter registered.\n\tSee XmtRegisterColorTableConverter();");
165 }
166 }
167 else {
168 XmtWarningMsg("XmtGetBitmap", "table",
169 "color table specification unused in bitmap conversion.");
170 }
171
172 table_string -= 2; /* points to char before colon */
173 for(; isspace(*table_string); table_string--); /* skip over blanks*/
174 i = (table_string - str) + 1;
175 name = strncpy(XtMalloc(i+1), str, i);
176 name[i] = '\0';
177 }
178 else
179 name = (String) str;
180
181 /*
182 * see if name is defined in the image cache
183 */
184 if (get_bitmap)
185 pixmap = XmtLookupBitmap(w, name);
186 else
187 pixmap = XmtLookupPixmap(w, visual, colormap, depth, table, name);
188
189 if (pixmap) goto end;
190 else {
191 /*
192 * If it is not in the image cache, check if it is the name of a
193 * resource under _Pixmaps_ or _Bitmaps_. We lookup the image
194 * as:
195 * _Pixmaps_.visual.depth.resolution.language.territory.codeset.name
196 * For backward compatibility with Xmt 1.2, we also do just:
197 * _Pixmaps_.name
198 * because in 1.2 '.name' was more common than '*name'
199 *
200 * For bitmaps, we use _Bitmaps_, and omit the visual and depth.
201 */
202 String value;
203
204 if (!get_bitmap) {
205 value = _XmtLookupResource(screen, "PVDZltc", name);
206 if (value) {
207 if ((xmtimage = XmtParseXpmString(value))) goto found;
208 else goto end;
209 }
210 }
211
212 value = _XmtLookupResource(screen, "BZltc", name);
213 if (value) {
214 if (XmtParseXbmString(value, &xbmdata.bits,
215 &xbmdata.width, &xbmdata.height,
216 &xbmdata.hot_x, &xbmdata.hot_y))
217 goto found;
218 else goto end;
219 }
220
221 /* if still not found, look up the old way, for compatibility */
222 if (!get_bitmap) {
223 value = _XmtLookupResource(screen, "P", name);
224 if (value) {
225 if ((xmtimage = XmtParseXpmString(value))) goto found;
226 else goto end;
227 }
228 }
229
230 value = _XmtLookupResource(screen, "B", name);
231 if (value) {
232 if (XmtParseXbmString(value, &xbmdata.bits,
233 &xbmdata.width, &xbmdata.height,
234 &xbmdata.hot_x, &xbmdata.hot_y))
235 goto found;
236 else goto end;
237 }
238 }
239
240 /*
241 * if we still haven't found a pixmap, name must be a filename
242 */
243 if (pixmap == None) {
244 /*
245 * handle absolute and relative filenames
246 */
247 if ((name[0] == '/') ||
248 ((name[0] == '.') && (name[1] == '/')) ||
249 ((name[0] == '.') && (name[1] == '.') && (name[2] == '/')))
250 filename = name;
251
252 /*
253 * check relative to an environment variable, if defined
254 * Note that since we don't know the path, we don't know for
255 * sure that it uses the supplied type and suffix, so we don't
256 * know what type of file is being found
257 */
258 if (!get_bitmap && !filename && (path = getenv("XPMLANGPATH"))) {
259 filename = XmtFindFile(shell, "pixmaps", name, ".xpm",
260 NULL, path, XmtSearchPathOnly);
261 if (filename) pixmap_file = True;
262 }
263
264 if (!filename && (path = getenv("XBMLANGPATH"))) {
265 filename = XmtFindFile(shell, "bitmaps", name, ".xbm",
266 NULL, path, XmtSearchPathOnly);
267 if (filename) bitmap_file = True;
268 }
269
270 /* next check the user, app, and system pixmap and bitmap paths */
271 if (!filename) {
272 if (!get_bitmap) {
273 filename = XmtFindFile(shell, "pixmaps", name, ".xpm",
274 NULL, app->pixmap_file_path,
275 XmtSearchEverywhere);
276 if (filename)
277 pixmap_file = True;
278 }
279 if (!filename) {
280 filename = XmtFindFile(shell, "bitmaps", name, ".xbm",
281 NULL, app->bitmap_file_path,
282 XmtSearchEverywhere);
283 if (filename)
284 bitmap_file = True;
285 }
286 }
287
288 /*
289 * if we found a file, read the first few bytes to determine the
290 * type. Read it as appropriate. Register the resulting
291 * pixmap in the cache using the filename as the key.
292 */
293 if (filename) {
294 FILE *f;
295 char buf[10];
296
297 if (!pixmap_file && !bitmap_file) {
298 if (get_bitmap) bitmap_file = True;
299 else if ((f = fopen(filename, "r")) != NULL) {
300 (void)fgets(buf, 10, f);
301 if (strncmp(buf, "/* XPM */", 9) == 0)
302 pixmap_file = True;
303 else if (strncmp(buf, "#define", 7) == 0)
304 bitmap_file = True;
305 (void)fclose(f);
306 }
307 }
308
309 if (pixmap_file || (!pixmap_file && !bitmap_file)) {
310 xmtimage = XmtParseXpmFile(filename);
311 if (xmtimage) goto found;
312 }
313
314 if (bitmap_file || (!pixmap_file && !bitmap_file)) {
315 if (XmtParseXbmFile(filename, &xbmdata.bits,
316 &xbmdata.width, &xbmdata.height,
317 &xbmdata.hot_x, &xbmdata.hot_y))
318 goto found;
319 }
320 }
321 }
322
323 found:
324 /*
325 * register the xpm or xbm data, and then get a pixmap for it.
326 * we jump here when we successfully parse a xpm or xbm file or string.
327 */
328 if (xmtimage)
329 XmtRegisterImage(name, xmtimage);
330 else if (xbmdata.bits)
331 XmtRegisterXbmData(name, xbmdata.bits, NULL,
332 xbmdata.width, xbmdata.height,
333 xbmdata.hot_x, xbmdata.hot_y);
334
335 if (xmtimage || xbmdata.bits) {
336 if (get_bitmap)
337 pixmap = XmtLookupBitmap(w, name);
338 else
339 pixmap = XmtLookupPixmap(w, visual, colormap,
340 depth, table, name);
341 }
342
343 end:
344 /*
345 * free what we need to and return.
346 * we jump here if the pixmap is already cached, or on error.
347 */
348 if (filename && filename != name) XtFree(filename);
349 if (name && name != str) XtFree(name);
350 if (free_color_table) {
351 refs[0] = color_table_cache_ref;
352 refs[1] = NULL;
353 XtAppReleaseCacheRefs(XtWidgetToApplicationContext(w), refs);
354 }
355 return pixmap;
356 }
357
358 #if NeedFunctionPrototypes
XmtGetBitmap(Widget object,StringConst str)359 Pixmap XmtGetBitmap(Widget object, StringConst str)
360 #else
361 Pixmap XmtGetBitmap(object, str)
362 Widget object;
363 StringConst str;
364 #endif
365 {
366 return GetPixmap(object, str, NULL, True);
367 }
368
369 #if NeedFunctionPrototypes
XmtGetPixmap(Widget object,XmtColorTable table,StringConst str)370 Pixmap XmtGetPixmap(Widget object, XmtColorTable table, StringConst str)
371 #else
372 Pixmap XmtGetPixmap(object, table, str)
373 Widget object;
374 XmtColorTable table;
375 StringConst str;
376 #endif
377 {
378 return GetPixmap(object, str, table, False);
379 }
380