Imported Upstream version 1.1.2
[platform/upstream/libXmu.git] / src / LocBitmap.c
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
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
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 **
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
248 _XmuStringToBitmapInitCache(register XmuCvtCache *c)
249 {
250     c->string_to_bitmap.bitmapFilePath = NULL;
251 }
252
253 void
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 }