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