1 /* Change for xpbiff by Yoshikazu Yamamoto(y-yamamt@ics.es.osaka-u.ac.jp) at Oct 19, 1993 */
2 
3 /* * Last edited: Sep 17 14:39 1991 (mallet) */
4 /*
5  * Copyright 1991 Lionel Mallet
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation for any purpose and without fee is hereby granted, provided
9  * that the above copyright notice appear in all copies and that both that
10  * copyright notice and this permission notice appear in supporting
11  * documentation, and that the name of Lionel MALLET not be used in advertising
12  * or publicity pertaining to distribution of the software without specific,
13  * written prior permission.  Lionel MALLET makes no representations about the
14  * suitability of this software for any purpose.  It is provided "as is"
15  * without express or implied warranty.
16  *
17  * Lionel MALLET DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
18  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
19  * FITNESS, IN NO EVENT SHALL Lionel MALLET BE LIABLE FOR ANY SPECIAL,
20  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
21  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
22  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
23  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24  *
25  * Author:  Lionel Mallet - SIMULOG
26  */
27 
28 #include <X11/Xlib.h>
29 #include <X11/Xresource.h>
30 #include <X11/Xutil.h>
31 #include <X11/StringDefs.h>
32 #include <sys/param.h>			/* get MAXPATHLEN if possible */
33 #ifndef MAXPATHLEN
34 #define MAXPATHLEN 256
35 #endif
36 
37 #include <X11/Xmu/CvtCache.h>
38 #include <X11/xpm.h>
39 #include <X11/Xmu/Drawing.h>
40 
41 
42 /*
43  * LocatePixmapFile - read a pixmap file using the normal defaults
44  */
45 
46 static char **split_path_string();
47 
48 Pixmap LocatePixmapFile (screen, name, srcname, srcnamelen,
49 			    widthp, heightp, mask)
50     Screen *screen;
51     char *name;
52     char *srcname;			/* RETURN */
53     int srcnamelen;
54     int *widthp, *heightp;              /* RETURN */
55     Pixmap *mask;			/* RETURN */
56 {
57     Display *dpy = DisplayOfScreen (screen);
58     Window root = RootWindowOfScreen (screen);
59     Bool try_plain_name = True;
60     XmuCvtCache *cache = _XmuCCLookupDisplay (dpy);
61     char **file_paths;
62     char filename[MAXPATHLEN];
63     unsigned int width, height;
64     int xhot, yhot;
65     int i;
66 
67 
68     /*
69      * look in cache for pixmap path
70      */
71     if (cache) {
72 	if (!cache->string_to_bitmap.bitmapFilePath) {
73 	    XrmName xrm_name[2];
74 	    XrmClass xrm_class[2];
75 	    XrmRepresentation rep_type;
76 	    XrmValue value;
77 
78 	    xrm_name[0] = XrmStringToName ("bitmapFilePath");
79 	    xrm_name[1] = NULL;
80 	    xrm_class[0] = XrmStringToClass ("BitmapFilePath");
81 	    xrm_class[1] = NULL;
82 	    /*
83 	     * XXX - warning, derefing Display * until XDisplayDatabase
84 	     */
85 	    if (!XrmGetDatabase(dpy)) {
86 		/* what a hack; need to initialize dpy->db */
87 		(void) XGetDefault (dpy, "", "");
88 	    }
89 	    if (XrmQGetResource (XrmGetDatabase(dpy), xrm_name, xrm_class,
90 				 &rep_type, &value) &&
91 		rep_type == XrmStringToQuark(XtRString)) {
92 		cache->string_to_bitmap.bitmapFilePath =
93 		  split_path_string (value.addr);
94 	    }
95 	}
96 	file_paths = cache->string_to_bitmap.bitmapFilePath;
97     }
98 
99 
100     /*
101      * Search order:
102      *    1.  name if it begins with / or ./
103      *    2.  "each prefix in file_paths"/name
104      *    3.  BITMAPDIR/name
105      *    4.  name if didn't begin with / or .
106      */
107 
108 #ifndef BITMAPDIR
109 #define BITMAPDIR "/usr/include/X11/bitmaps"
110 #endif
111 
112     for (i = 1; i <= 4; i++) {
113 	char *fn = filename;
114 	Pixmap pixmap;
115 	XpmAttributes attributes;
116 	unsigned char *data;
117 
118 	switch (i) {
119 	  case 1:
120 	    if (!(name[0] == '/' || (name[0] == '.') && name[1] == '/'))
121 	      continue;
122 	    fn = name;
123 	    try_plain_name = False;
124 	    break;
125 	  case 2:
126 	    if (file_paths && *file_paths) {
127 		sprintf (filename, "%s/%s", *file_paths, name);
128 		file_paths++;
129 		i--;
130 		break;
131 	    }
132 	    continue;
133 	  case 3:
134 	    sprintf (filename, "%s/%s", BITMAPDIR, name);
135 	    break;
136 	  case 4:
137 	    if (!try_plain_name) continue;
138 	    fn = name;
139 	    break;
140 	}
141 
142 	data = NULL;
143 	pixmap = None;
144 	if (XmuReadBitmapDataFromFile (fn, &width, &height, &data,
145 				       &xhot, &yhot) == BitmapSuccess) {
146 	    pixmap = XCreatePixmapFromBitmapData (dpy, root, (char *) data,
147 						  width, height,
148 						  (unsigned long) 1,
149 						  (unsigned long) 0,
150 						  (unsigned int) 1);
151 	    XFree ((char *)data);
152 	    if (pixmap != None) {
153 		if (widthp) *widthp = (int)width;
154 		if (heightp) *heightp = (int)height;
155 		if (srcname && srcnamelen > 0) {
156 		    strncpy (srcname, fn, srcnamelen - 1);
157 		    srcname[srcnamelen - 1] = '\0';
158 		}
159 		*mask = None;
160 		return pixmap;
161 	    }
162 	}
163 	attributes.visual = DefaultVisualOfScreen (screen);
164 	attributes.colormap = DefaultColormapOfScreen (screen);
165 	attributes.depth = DefaultDepthOfScreen (screen);
166 	attributes.colorsymbols = (ColorSymbol *)NULL;
167 	attributes.numsymbols = 0;
168 	attributes.valuemask = XpmVisual | XpmColormap | XpmDepth;
169 	if (pixmap == None &&
170 	    XpmReadPixmapFile (dpy, root, fn, &pixmap, mask,
171 			       &attributes) == XpmPixmapSuccess) {
172 	    if (widthp) *widthp = (int)attributes.width;
173 	    if (heightp) *heightp = (int)attributes.height;
174 	    if (srcname && srcnamelen > 0) {
175 		strncpy (srcname, fn, srcnamelen - 1);
176 		srcname[srcnamelen - 1] = '\0';
177 	    }
178 	    XpmFreeAttributes(&attributes);
179 	    return pixmap;
180 	}
181     }
182     *mask = None;
183     return None;
184 }
185 
186 
187 /*
188  * split_path_string - split a colon-separated list into its constituent
189  * parts; to release, free list[0] and list.
190  */
191 static char **split_path_string (src)
192     register char *src;
193 {
194     int nelems = 1;
195     register char *dst;
196     char **elemlist, **elem;
197 
198     /* count the number of elements */
199     for (dst = src; *dst; dst++) if (*dst == ':') nelems++;
200 
201     /* get memory for everything */
202     dst = (char *) malloc (dst - src + 1);
203     if (!dst) return NULL;
204     elemlist = (char **) calloc ((nelems + 1), sizeof (char *));
205     if (!elemlist) {
206 	free (dst);
207 	return NULL;
208     }
209 
210     /* copy to new list and walk up nulling colons and setting list pointers */
211     strcpy (dst, src);
212     for (elem = elemlist, src = dst; *src; src++) {
213 	if (*src == ':') {
214 	    *elem++ = dst;
215 	    *src = '\0';
216 	    dst = src + 1;
217 	}
218     }
219     *elem = dst;
220 
221     return elemlist;
222 }
223 
224 /*
225 void _XmuStringToBitmapInitCache (c)
226     register XmuCvtCache *c;
227 {
228     c->string_to_bitmap.bitmapFilePath = NULL;
229 }
230 
231 void _XmuStringToBitmapFreeCache (c)
232     register XmuCvtCache *c;
233 {
234     if (c->string_to_bitmap.bitmapFilePath) {
235 	if (c->string_to_bitmap.bitmapFilePath[0])
236 	  free (c->string_to_bitmap.bitmapFilePath[0]);
237 	free ((char *) (c->string_to_bitmap.bitmapFilePath));
238     }
239 }
240 */
241