3 Copyright 1988, 1998 The Open Group
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
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
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.
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.
28 * This file contains miscellaneous utility routines and is not part of the
31 * Public entry points:
33 * XmuReadBitmapData read data from FILE descriptor
34 * XmuReadBitmapDataFromFile read X10 or X11 format bitmap files
37 * Note that this file and ../X/XRdBitF.c look very similar.... Keep them
38 * that way (but don't use common source code so that people can have one
44 * Based on an optimized version provided by Jim Becker, Auguest 5, 1988.
52 #include <X11/Xutil.h>
53 #include <X11/Xlibint.h>
56 #include <X11/Xmu/Drawing.h>
58 #include <X11/Xwindows.h>
66 static void initHexTable(void);
67 static int NextInt(FILE*);
69 /* shared data for the image read/parse logic */
70 static short hexTable[256]; /* conversion value */
71 static Bool initialized = False; /* easier to fill in at run time */
75 * Table index for the hex values. Initialized once, first time.
76 * Used for translation value or delimiter significance lookup.
82 * We build the table at run time for several reasons:
84 * 1. portable to non-ASCII machines.
85 * 2. still reentrant since we set the init flag after setting table.
86 * 3. easier to extend.
87 * 4. less prone to bugs.
89 hexTable['0'] = 0; hexTable['1'] = 1;
90 hexTable['2'] = 2; hexTable['3'] = 3;
91 hexTable['4'] = 4; hexTable['5'] = 5;
92 hexTable['6'] = 6; hexTable['7'] = 7;
93 hexTable['8'] = 8; hexTable['9'] = 9;
94 hexTable['A'] = 10; hexTable['B'] = 11;
95 hexTable['C'] = 12; hexTable['D'] = 13;
96 hexTable['E'] = 14; hexTable['F'] = 15;
97 hexTable['a'] = 10; hexTable['b'] = 11;
98 hexTable['c'] = 12; hexTable['d'] = 13;
99 hexTable['e'] = 14; hexTable['f'] = 15;
101 /* delimiters of significance are flagged w/ negative value */
102 hexTable[' '] = -1; hexTable[','] = -1;
103 hexTable['}'] = -1; hexTable['\n'] = -1;
110 * read next hex value in the input stream, return -1 if EOF
113 NextInt(FILE *fstream)
120 /* loop, accumulate hex value until find delimiter */
121 /* skip any initial delimiters found in read stream */
129 /* trim high bits, check type and accumulate */
131 if (isascii(ch) && isxdigit(ch)) {
132 value = (value << 4) + hexTable[ch];
134 } else if ((hexTable[ch]) < 0 && gotone)
143 * The data returned by the following routine is always in left-most byte
144 * first and left-most bit first. If it doesn't return BitmapSuccess then
145 * its arguments won't have been touched. This routine should look as much
146 * like the Xlib routine XReadBitmapfile as possible.
149 XmuReadBitmapData(FILE *fstream, unsigned int *width, unsigned int *height,
150 unsigned char **datap, int *x_hot, int *y_hot)
152 unsigned char *data = NULL; /* working variable */
153 char line[MAX_SIZE]; /* input line from file */
154 int size; /* number of bytes of data */
155 char name_and_type[MAX_SIZE]; /* an input line */
156 char *type; /* for parsing */
157 int value; /* from an input line */
158 int version10p; /* boolean, old format */
159 int padding; /* to handle alignment */
160 int bytes_per_line; /* per scanline of data */
161 unsigned int ww = 0; /* width */
162 unsigned int hh = 0; /* height */
163 int hx = -1; /* x hotspot */
164 int hy = -1; /* y hotspot */
166 #undef Xmalloc /* see MALLOC_0_RETURNS_NULL in Xlibint.h */
167 #define Xmalloc(size) malloc(size)
169 /* first time initialization */
170 if (initialized == False) initHexTable();
172 /* error cleanup and return macro */
173 #define RETURN(code) { if (data) free (data); return code; }
175 while (fgets(line, MAX_SIZE, fstream)) {
176 if (strlen(line) == MAX_SIZE-1) {
177 RETURN (BitmapFileInvalid);
179 if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
180 if (!(type = strrchr(name_and_type, '_')))
181 type = name_and_type;
185 if (!strcmp("width", type))
186 ww = (unsigned int) value;
187 if (!strcmp("height", type))
188 hh = (unsigned int) value;
189 if (!strcmp("hot", type)) {
190 if (type-- == name_and_type || type-- == name_and_type)
192 if (!strcmp("x_hot", type))
194 if (!strcmp("y_hot", type))
200 if (sscanf(line, "static short %s = {", name_and_type) == 1)
202 else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
204 else if (sscanf(line, "static char %s = {", name_and_type) == 1)
209 if (!(type = strrchr(name_and_type, '_')))
210 type = name_and_type;
214 if (strcmp("bits[]", type))
218 RETURN (BitmapFileInvalid);
220 if ((ww % 16) && ((ww % 16) < 9) && version10p)
225 bytes_per_line = (ww+7)/8 + padding;
227 size = bytes_per_line * hh;
228 data = (unsigned char *) Xmalloc ((unsigned int) size);
230 RETURN (BitmapNoMemory);
236 for (bytes=0, ptr=data; bytes<size; (bytes += 2)) {
237 if ((value = NextInt(fstream)) < 0)
238 RETURN (BitmapFileInvalid);
240 if (!padding || ((bytes+2) % bytes_per_line))
241 *(ptr++) = value >> 8;
247 for (bytes=0, ptr=data; bytes<size; bytes++, ptr++) {
248 if ((value = NextInt(fstream)) < 0)
249 RETURN (BitmapFileInvalid);
257 RETURN (BitmapFileInvalid);
264 if (x_hot) *x_hot = hx;
265 if (y_hot) *y_hot = hy;
267 RETURN (BitmapSuccess);
272 access_file(char *path, char *pathbuf, int len_pathbuf, char **pathret)
274 if (access (path, F_OK) == 0) {
275 if (strlen (path) < len_pathbuf)
278 *pathret = malloc (strlen (path) + 1);
280 strcpy (*pathret, path);
288 AccessFile(char *path, char *pathbuf, int len_pathbuf, char **pathret)
294 unsigned long drives;
300 /* just try the "raw" name first and see if it works */
301 if (access_file (path, pathbuf, len_pathbuf, pathret))
304 /* try the places set in the environment */
305 drive = getenv ("_XBASEDRIVE");
308 drive = getenv ("X11ROOT");
312 len = strlen (drive) + strlen (path);
313 if (len < MAX_PATH) bufp = buf;
314 else bufp = malloc (len + 1);
315 strcpy (bufp, drive);
317 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
318 if (bufp != buf) free (bufp);
323 /* one last place to look */
324 drive = getenv ("HOMEDRIVE");
326 len = strlen (drive) + strlen (path);
327 if (len < MAX_PATH) bufp = buf;
328 else bufp = malloc (len + 1);
329 strcpy (bufp, drive);
331 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
332 if (bufp != buf) free (bufp);
337 /* does OS/2 (with or with gcc-emx) have getdrives? */
338 /* tried everywhere else, go fishing */
339 #define C_DRIVE ('C' - 'A')
340 #define Z_DRIVE ('Z' - 'A')
341 drives = _getdrives ();
342 for (i = C_DRIVE; i <= Z_DRIVE; i++) { /* don't check on A: or B: */
343 if ((1 << i) & drives) {
344 len = 2 + strlen (path);
345 if (len < MAX_PATH) bufp = buf;
346 else bufp = malloc (len + 1);
351 if (access_file (bufp, pathbuf, len_pathbuf, pathret)) {
352 if (bufp != buf) free (bufp);
362 fopen_file(char *path, char *mode)
367 UINT olderror = SetErrorMode (SEM_FAILCRITICALERRORS);
369 if (AccessFile (path, buf, MAX_PATH, &bufp))
370 ret = fopen (bufp, mode);
372 (void) SetErrorMode (olderror);
374 if (bufp != buf) free (bufp);
380 #define fopen_file fopen
385 XmuReadBitmapDataFromFile(_Xconst char *filename, unsigned int *width,
386 unsigned int *height, unsigned char **datap,
387 int *x_hot, int *y_hot)
393 filename = __XOS2RedirRoot(filename);
395 if ((fstream = fopen_file (filename, "r")) == NULL) {
396 return BitmapOpenFailed;
398 status = XmuReadBitmapData(fstream, width, height, datap, x_hot, y_hot);