1/*
2
3Copyright 1989, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in 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 */
70static char **split_path_string(char*);
71
72/*
73 * XmuLocateBitmapFile - read a bitmap file using the normal defaults
74 */
75
76Pixmap
77XmuLocateBitmapFile(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 */
91Pixmap
92XmuLocatePixmapFile(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 */
213static char **
214split_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 = malloc (dst - src + 1);
225    if (!dst) return NULL;
226    elemlist = 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
247void
248_XmuStringToBitmapInitCache(register XmuCvtCache *c)
249{
250    c->string_to_bitmap.bitmapFilePath = NULL;
251}
252
253void
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 (c->string_to_bitmap.bitmapFilePath);
260    }
261}
262