1 /*
2 * $XConsortium: LocBitmap.c,v 1.16 91/07/02 09:09:59 rws Exp $
3 *
4 * Copyright 1989 Massachusetts Institute of Technology
5 *
6 * Portions Copyright 1991 by the University of Maryland
7 * College Park, Maryland
8 * $Id: LocPixmap.c,v 1.7 1991/10/05 08:39:16 cross Exp $
9 *
10 * Permission to use, copy, modify, and distribute this software and its
11 * documentation for any purpose and without fee is hereby granted, provided
12 * that the above copyright notice appear in all copies and that both that
13 * copyright notice and this permission notice appear in supporting
14 * documentation, and that the name of M.I.T. not be used in advertising
15 * or publicity pertaining to distribution of the software without specific,
16 * written prior permission. M.I.T. makes no representations about the
17 * suitability of this software for any purpose. It is provided "as is"
18 * without express or implied warranty.
19 *
20 * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
22 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
24 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
25 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 *
27 * Author: Jim Fulton, MIT X Consortium
28 */
29
30 /*
31 * This file is a modified version of mit/lib/Xmu/LocBitmap.c designed to
32 * work with tvtwm and the additions of Xpm support. This will work when
33 * compiled with Xpm v3.0 (as distributes on the R5 contrib tape) or higher.
34 *
35 * Chris P. Ross
36 */
37
38 #include <stdlib.h>
39 #include "twm.h"
40 #include <X11/Xlib.h>
41 #include <X11/Xresource.h>
42 #include <X11/Xutil.h>
43 #include <X11/Xmu/CvtCache.h>
44 #include <X11/Xmu/Drawing.h>
45 #include <X11/xpm.h>
46
47 #ifndef X_NOT_POSIX
48 # ifdef _POSIX_SOURCE
49 # include <limits.h>
50 # else
51 # define _POSIX_SOURCE
52 # include <limits.h>
53 # undef _POSIX_SOURCE
54 # endif
55 #endif /* X_NOT_POSIX */
56
57 #ifndef PATH_MAX
58 # include <sys/param.h>
59 # ifdef MAXPATHLEN
60 # define PATH_MAX MAXPATHLEN
61 # else
62 # define PATH_MAX 1024
63 # endif
64 #endif /* PATH_MAX */
65
66 static char **split_path_string();
67
68 /*
69 * version that reads pixmap data as well as bitmap data
70 */
XcprLocatePixmapFile(Screen * screen,_Xconst char * name,unsigned long fore,unsigned long back,unsigned int depth,char * srcname,int srcnamelen,int * widthp,int * heightp,int * xhotp,int * yhotp,Bool * isXpm,XpmAttributes * attribs,Pixmap * mask)71 Pixmap XcprLocatePixmapFile (Screen *screen, _Xconst char *name,
72 unsigned long fore, unsigned long back,
73 unsigned int depth,
74 char *srcname, int srcnamelen,
75 int *widthp, int *heightp, int *xhotp, int *yhotp,
76 Bool *isXpm, XpmAttributes *attribs, Pixmap *mask)
77 {
78 Display *dpy = DisplayOfScreen (screen);
79 Window root = RootWindowOfScreen (screen);
80 Bool try_plain_name = True;
81 XmuCvtCache *cache = _XmuCCLookupDisplay (dpy);
82 char **file_paths = (char **) NULL;
83 char filename[PATH_MAX];
84 unsigned int width, height;
85 int xhot, yhot;
86 int i;
87 int XPMret;
88 XpmAttributes localAttribs;
89
90 /*
91 * We need to use the attribs...
92 */
93
94 localAttribs.valuemask = 0;
95
96 if (!attribs) {
97 attribs = &localAttribs;
98 attribs->valuemask = 0;
99 }
100
101 /*
102 * Assume a Bitmap...
103 */
104
105 *isXpm = False; /* xxxmask */
106 if (mask)
107 *mask = None;
108
109 /*
110 * look in cache for bitmap path
111 */
112 if (cache) {
113 if (!cache->string_to_bitmap.bitmapFilePath) {
114 XrmName xrm_name[2];
115 XrmClass xrm_class[2];
116 XrmRepresentation rep_type;
117 XrmValue value;
118
119 /* xrm_name[0] = XrmPermStringToQuark ("bitmapFilePath"); */
120 xrm_name[0] = XrmStringToQuark ("bitmapFilePath");
121 xrm_name[1] = NULLQUARK;
122 /* xrm_class[0] = XrmPermStringToQuark ("BitmapFilePath"); */
123 xrm_class[0] = XrmStringToQuark ("BitmapFilePath");
124 xrm_class[1] = NULLQUARK;
125 if (!XrmGetDatabase(dpy)) {
126 /* what a hack; need to initialize it */
127 (void) XGetDefault (dpy, "", "");
128 }
129 if (XrmQGetResource (XrmGetDatabase(dpy),
130 xrm_name, xrm_class,
131 &rep_type, &value) &&
132 /* rep_type == XrmPermStringToQuark("String") */
133 rep_type == XrmStringToQuark("String")
134 ) {
135 cache->string_to_bitmap.bitmapFilePath =
136 split_path_string (value.addr);
137 }
138 }
139 file_paths = cache->string_to_bitmap.bitmapFilePath;
140 }
141
142
143 /*
144 * Search order:
145 * 1. name if it begins with / or ./
146 * 2. "each prefix in file_paths"/name
147 * 3. BITMAPDIR/name
148 * 4. name if didn't begin with / or .
149 */
150
151 #ifndef BITMAPDIR
152 #define BITMAPDIR "/usr/include/X11/bitmaps"
153 #endif
154
155 for (i = 1; i <= 4; i++) {
156 char *fn = filename;
157 Pixmap pixmap;
158 unsigned char *data;
159
160 switch (i) {
161 case 1:
162 if (!((name[0] == '/') || ((name[0] == '.') && (name[1] == '/'))))
163 continue;
164 fn = (char *) name;
165 try_plain_name = False;
166 break;
167 case 2:
168 if (file_paths && *file_paths) {
169 sprintf (filename, "%s/%s", *file_paths, name);
170 file_paths++;
171 i--;
172 break;
173 }
174 continue;
175 case 3:
176 sprintf (filename, "%s/%s", BITMAPDIR, name);
177 break;
178 case 4:
179 if (!try_plain_name) continue;
180 fn = (char *) name;
181 break;
182 }
183
184 XPMret = XpmReadFileToPixmap(dpy, root, fn, &pixmap, mask, attribs);
185
186 switch (XPMret) {
187 case XpmSuccess:
188 case XpmColorError:
189 *isXpm = True;
190 if (widthp) *widthp = (int)attribs->width;
191 if (heightp) *heightp = (int)attribs->height;
192 if (attribs->valuemask & XpmHotspot) {
193 if (xhotp) *xhotp = (int)attribs->x_hotspot;
194 if (yhotp) *yhotp = (int)attribs->y_hotspot;
195 }
196 if (srcname && srcnamelen > 0) {
197 strncpy (srcname, fn, srcnamelen - 1);
198 srcname[srcnamelen - 1] = '\0';
199 }
200 if (XPMret == XpmColorError)
201 fprintf(stderr, "%s: Color substitution performed for file \"%s\"\n", ProgramName, fn);
202 XpmFreeAttributes(&localAttribs);
203 return pixmap;
204 break;
205 case XpmColorFailed:
206 fprintf(stderr, "%s: Color allocation failed on file \"%s\"\n", ProgramName, fn);
207 pixmap = None;
208 if (mask)
209 *mask = None;
210 break;
211 case XpmNoMemory:
212 fprintf(stderr, "%s: Color allocation failed on file \"%s\"\n", ProgramName, fn);
213 pixmap = None;
214 if (mask)
215 *mask = None;
216 break;
217 case XpmOpenFailed:
218 case XpmFileInvalid:
219 default:
220 /* XpmFreeAttributes(&localAttribs); */
221 data = NULL;
222 pixmap = None;
223 if (mask)
224 *mask = None;
225 if (XmuReadBitmapDataFromFile (fn, &width, &height,
226 &data, &xhot, &yhot) == BitmapSuccess) {
227 pixmap = XCreatePixmapFromBitmapData (dpy, root,
228 (char *) data, width, height,
229 fore, back, depth);
230 XFree ((char *)data);
231 }
232
233 if (pixmap) {
234 if (widthp) *widthp = (int)width;
235 if (heightp) *heightp = (int)height;
236 if (xhotp) *xhotp = xhot;
237 if (yhotp) *yhotp = yhot;
238 if (srcname && srcnamelen > 0) {
239 strncpy (srcname, fn, srcnamelen - 1);
240 srcname[srcnamelen - 1] = '\0';
241 }
242 XpmFreeAttributes(&localAttribs);
243 return pixmap;
244 }
245 break;
246 }
247
248 }
249 XpmFreeAttributes(&localAttribs);
250 return None;
251 }
252
253
254 /*
255 * split_path_string - split a colon-separated list into its constituent
256 * parts; to release, free list[0] and list.
257 */
split_path_string(src)258 static char **split_path_string (src)
259 register char *src;
260 {
261 int nelems = 1;
262 register char *dst;
263 char **elemlist, **elem;
264
265 /* count the number of elements */
266 for (dst = src; *dst; dst++) if (*dst == ':') nelems++;
267
268 /* get memory for everything */
269 dst = (char *) malloc (dst - src + 1);
270 if (!dst) return NULL;
271 elemlist = (char **) calloc ((nelems + 1), sizeof (char *));
272 if (!elemlist) {
273 free (dst);
274 return NULL;
275 }
276
277 /* copy to new list and walk up nulling colons and setting list pointers */
278 strcpy (dst, src);
279 for (elem = elemlist, src = dst; *src; src++) {
280 if (*src == ':') {
281 *elem++ = dst;
282 *src = '\0';
283 dst = src + 1;
284 }
285 }
286 *elem = dst;
287
288 return elemlist;
289 }
290
291
_XmuStringToBitmapInitCache(c)292 void _XmuStringToBitmapInitCache (c)
293 register XmuCvtCache *c;
294 {
295 c->string_to_bitmap.bitmapFilePath = NULL;
296 }
297
_XmuStringToBitmapFreeCache(c)298 void _XmuStringToBitmapFreeCache (c)
299 register XmuCvtCache *c;
300 {
301 if (c->string_to_bitmap.bitmapFilePath) {
302 if (c->string_to_bitmap.bitmapFilePath[0])
303 free (c->string_to_bitmap.bitmapFilePath[0]);
304 free ((char *) (c->string_to_bitmap.bitmapFilePath));
305 }
306 }
307