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