1 /*
2 
3 Copyright 1989, 1998  The Open Group
4 
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10 
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24 
25 */
26 
27 /*
28  * Author:  Jim Fulton, MIT X Consortium
29  */
30 
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34 #include <X11/Xlib.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <X11/Xresource.h>
38 #include <X11/Xutil.h>
39 #include <X11/Xmu/CvtCache.h>
40 #include <X11/Xmu/Drawing.h>
41 #include <X11/Xmu/SysUtil.h>
42 
43 #ifndef X_NOT_POSIX
44 #ifdef _POSIX_SOURCE
45 #include <limits.h>
46 #else
47 #define _POSIX_SOURCE
48 #include <limits.h>
49 #undef _POSIX_SOURCE
50 #endif
51 #endif /* X_NOT_POSIX */
52 #ifndef PATH_MAX
53 #ifdef WIN32
54 #define PATH_MAX 512
55 #else
56 #include <sys/param.h>
57 #endif
58 #ifndef PATH_MAX
59 #ifdef MAXPATHLEN
60 #define PATH_MAX MAXPATHLEN
61 #else
62 #define PATH_MAX 1024
63 #endif
64 #endif
65 #endif /* PATH_MAX */
66 
67 /*
68  * Prototypes
69  */
70 static char **split_path_string(char*);
71 
72 /*
73  * XmuLocateBitmapFile - read a bitmap file using the normal defaults
74  */
75 
76 Pixmap
XmuLocateBitmapFile(Screen * screen,_Xconst char * name,char * srcname,int srcnamelen,int * widthp,int * heightp,int * xhotp,int * yhotp)77 XmuLocateBitmapFile(Screen *screen, _Xconst char *name, char *srcname,
78 			    int srcnamelen, int *widthp, int *heightp,
79 			    int *xhotp, int *yhotp)
80 {
81     return XmuLocatePixmapFile (screen, name,
82 				(unsigned long) 1, (unsigned long) 0,
83 				(unsigned int) 1, srcname, srcnamelen,
84 				widthp, heightp, xhotp, yhotp);
85 }
86 
87 
88 /*
89  * version that reads pixmap data as well as bitmap data
90  */
91 Pixmap
XmuLocatePixmapFile(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)92 XmuLocatePixmapFile(Screen *screen, _Xconst char *name,
93 			    unsigned long fore, unsigned long back,
94 			    unsigned int depth,
95 			    char *srcname, int srcnamelen,
96 			    int *widthp, int *heightp, int *xhotp, int *yhotp)
97 {
98 
99 #ifndef BITMAPDIR
100 #define BITMAPDIR "/usr/include/X11/bitmaps"
101 #endif
102 
103     Display *dpy = DisplayOfScreen (screen);
104     Window root = RootWindowOfScreen (screen);
105     Bool try_plain_name = True;
106     XmuCvtCache *cache = _XmuCCLookupDisplay (dpy);
107     char **file_paths = (char **) NULL;
108     char filename[PATH_MAX];
109 #if 0
110     char* bitmapdir = BITMAPDIR;
111 #endif
112     unsigned int width, height;
113     int xhot, yhot;
114     int i;
115 
116     /*
117      * look in cache for bitmap path
118      */
119     if (cache) {
120 	if (!cache->string_to_bitmap.bitmapFilePath) {
121 	    XrmName xrm_name[2];
122 	    XrmClass xrm_class[2];
123 	    XrmRepresentation rep_type;
124 	    XrmValue value;
125 
126 	    xrm_name[0] = XrmPermStringToQuark ("bitmapFilePath");
127 	    xrm_name[1] = NULLQUARK;
128 	    xrm_class[0] = XrmPermStringToQuark ("BitmapFilePath");
129 	    xrm_class[1] = NULLQUARK;
130 	    if (!XrmGetDatabase(dpy)) {
131 		/* what a hack; need to initialize it */
132 		(void) XGetDefault (dpy, "", "");
133 	    }
134 	    if (XrmQGetResource (XrmGetDatabase(dpy), xrm_name, xrm_class,
135 				 &rep_type, &value) &&
136 		rep_type == XrmPermStringToQuark("String")) {
137 		cache->string_to_bitmap.bitmapFilePath =
138 		  split_path_string (value.addr);
139 	    }
140 	}
141 	file_paths = cache->string_to_bitmap.bitmapFilePath;
142     }
143 
144     /*
145      * Search order:
146      *    1.  name if it begins with / or ./
147      *    2.  "each prefix in file_paths"/name
148      *    3.  BITMAPDIR/name
149      *    4.  name if didn't begin with / or .
150      */
151 
152     for (i = 1; i <= 4; i++) {
153 	const char *fn = filename;
154 	Pixmap pixmap;
155 	unsigned char *data;
156 
157 	switch (i) {
158 	  case 1:
159 	    if (!(name[0] == '/' || ((name[0] == '.') && name[1] == '/')))
160 	      continue;
161 	    fn = name;
162 	    try_plain_name = False;
163 	    break;
164 	  case 2:
165 	    if (file_paths && *file_paths) {
166 		XmuSnprintf(filename, sizeof(filename),
167 			    "%s/%s", *file_paths, name);
168 		file_paths++;
169 		i--;
170 		break;
171 	    }
172 	    continue;
173 	  case 3:
174 	    XmuSnprintf(filename, sizeof(filename), "%s/%s", BITMAPDIR, name);
175 	    break;
176 	  case 4:
177 	    if (!try_plain_name) continue;
178 	    fn = name;
179 	    break;
180 	}
181 
182 	data = NULL;
183 	pixmap = None;
184 	if (XmuReadBitmapDataFromFile (fn, &width, &height, &data,
185 				       &xhot, &yhot) == BitmapSuccess) {
186 	    pixmap = XCreatePixmapFromBitmapData (dpy, root, (char *) data,
187 						  width, height,
188 						  fore, back, depth);
189 	    XFree ((char *)data);
190 	}
191 
192 	if (pixmap) {
193 	    if (widthp) *widthp = (int)width;
194 	    if (heightp) *heightp = (int)height;
195 	    if (xhotp) *xhotp = xhot;
196 	    if (yhotp) *yhotp = yhot;
197 	    if (srcname && srcnamelen > 0) {
198 		strncpy (srcname, fn, srcnamelen - 1);
199 		srcname[srcnamelen - 1] = '\0';
200 	    }
201 	    return pixmap;
202 	}
203     }
204 
205     return None;
206 }
207 
208 
209 /*
210  * split_path_string - split a colon-separated list into its constituent
211  * parts; to release, free list[0] and list.
212  */
213 static char **
split_path_string(register char * src)214 split_path_string(register char *src)
215 {
216     int nelems = 1;
217     register char *dst;
218     char **elemlist, **elem;
219 
220     /* count the number of elements */
221     for (dst = src; *dst; dst++) if (*dst == ':') nelems++;
222 
223     /* get memory for everything */
224     dst = (char *) malloc (dst - src + 1);
225     if (!dst) return NULL;
226     elemlist = (char **) calloc ((nelems + 1), sizeof (char *));
227     if (!elemlist) {
228 	free (dst);
229 	return NULL;
230     }
231 
232     /* copy to new list and walk up nulling colons and setting list pointers */
233     strcpy (dst, src);
234     for (elem = elemlist, src = dst; *src; src++) {
235 	if (*src == ':') {
236 	    *elem++ = dst;
237 	    *src = '\0';
238 	    dst = src + 1;
239 	}
240     }
241     *elem = dst;
242 
243     return elemlist;
244 }
245 
246 
247 void
_XmuStringToBitmapInitCache(register XmuCvtCache * c)248 _XmuStringToBitmapInitCache(register XmuCvtCache *c)
249 {
250     c->string_to_bitmap.bitmapFilePath = NULL;
251 }
252 
253 void
_XmuStringToBitmapFreeCache(register XmuCvtCache * c)254 _XmuStringToBitmapFreeCache(register XmuCvtCache *c)
255 {
256     if (c->string_to_bitmap.bitmapFilePath) {
257 	if (c->string_to_bitmap.bitmapFilePath[0])
258 	  free (c->string_to_bitmap.bitmapFilePath[0]);
259 	free ((char *) (c->string_to_bitmap.bitmapFilePath));
260     }
261 }
262