RdBitF.c revision 818534a1
1/*
2
3Copyright 1987, 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
12in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall
23not be used in advertising or otherwise to promote the sale, use or
24other dealings in this Software without prior written authorization
25from The Open Group.
26
27*/
28
29/*
30 *	Code to read bitmaps from disk files. Interprets
31 *	data from X10 and X11 bitmap files and creates
32 *	Pixmap representations of files. Returns Pixmap
33 *	ID and specifics about image.
34 *
35 *	Modified for speedup by Jim Becker, changed image
36 *	data parsing logic (removed some fscanf()s).
37 *	Aug 5, 1988
38 *
39 * Note that this file and ../Xmu/RdBitF.c look very similar....  Keep them
40 * that way (but don't use common source code so that people can have one
41 * without the other).
42 */
43
44#ifdef HAVE_CONFIG_H
45#include <config.h>
46#endif
47#include "Xlibint.h"
48#include <X11/Xos.h>
49#include "Xutil.h"
50#include <stdio.h>
51#include <ctype.h>
52
53
54#define MAX_SIZE 255
55
56/* shared data for the image read/parse logic */
57static const short hexTable[256] = {
58    ['0'] = 0,  ['1'] = 1,
59    ['2'] = 2,  ['3'] = 3,
60    ['4'] = 4,  ['5'] = 5,
61    ['6'] = 6,  ['7'] = 7,
62    ['8'] = 8,  ['9'] = 9,
63    ['A'] = 10, ['B'] = 11,
64    ['C'] = 12, ['D'] = 13,
65    ['E'] = 14, ['F'] = 15,
66    ['a'] = 10, ['b'] = 11,
67    ['c'] = 12, ['d'] = 13,
68    ['e'] = 14, ['f'] = 15,
69
70    [' '] = -1, [','] = -1,
71    ['}'] = -1, ['\n'] = -1,
72    ['\t'] = -1
73};
74
75/*
76 *	read next hex value in the input stream, return -1 if EOF
77 */
78static int
79NextInt (
80    FILE *fstream)
81{
82    int	ch;
83    int	value = 0;
84    int gotone = 0;
85    int done = 0;
86
87    /* loop, accumulate hex value until find delimiter  */
88    /* skip any initial delimiters found in read stream */
89
90    while (!done) {
91	ch = getc(fstream);
92	if (ch == EOF) {
93	    value	= -1;
94	    done++;
95	} else {
96	    /* trim high bits, check type and accumulate */
97	    ch &= 0xff;
98	    if (isascii(ch) && isxdigit(ch)) {
99		value = (value << 4) + hexTable[ch];
100		gotone++;
101	    } else if ((hexTable[ch]) < 0 && gotone)
102	      done++;
103	}
104    }
105    return value;
106}
107
108int
109XReadBitmapFileData (
110    _Xconst char *filename,
111    unsigned int *width,                /* RETURNED */
112    unsigned int *height,               /* RETURNED */
113    unsigned char **data,               /* RETURNED */
114    int *x_hot,                         /* RETURNED */
115    int *y_hot)                         /* RETURNED */
116{
117    FILE *fstream;			/* handle on file  */
118    unsigned char *bits = NULL;		/* working variable */
119    char line[MAX_SIZE];		/* input line from file */
120    int size;				/* number of bytes of data */
121    char name_and_type[MAX_SIZE];	/* an input line */
122    char *type;				/* for parsing */
123    int value;				/* from an input line */
124    int version10p;			/* boolean, old format */
125    int padding;			/* to handle alignment */
126    int bytes_per_line;			/* per scanline of data */
127    unsigned int ww = 0;		/* width */
128    unsigned int hh = 0;		/* height */
129    int hx = -1;			/* x hotspot */
130    int hy = -1;			/* y hotspot */
131
132#ifdef __UNIXOS2__
133    filename = __XOS2RedirRoot(filename);
134#endif
135    if (!(fstream = fopen(filename, "r")))
136	return BitmapOpenFailed;
137
138    /* error cleanup and return macro	*/
139#define	RETURN(code) \
140{ if (bits) Xfree (bits); fclose (fstream); return code; }
141
142    while (fgets(line, MAX_SIZE, fstream)) {
143	if (strlen(line) == MAX_SIZE-1)
144	    RETURN (BitmapFileInvalid);
145	if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
146	    if (!(type = strrchr(name_and_type, '_')))
147	      type = name_and_type;
148	    else
149	      type++;
150
151	    if (!strcmp("width", type))
152	      ww = (unsigned int) value;
153	    if (!strcmp("height", type))
154	      hh = (unsigned int) value;
155	    if (!strcmp("hot", type)) {
156		if (type-- == name_and_type || type-- == name_and_type)
157		  continue;
158		if (!strcmp("x_hot", type))
159		  hx = value;
160		if (!strcmp("y_hot", type))
161		  hy = value;
162	    }
163	    continue;
164	}
165
166	if (sscanf(line, "static short %s = {", name_and_type) == 1)
167	  version10p = 1;
168	else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
169	  version10p = 0;
170	else if (sscanf(line, "static char %s = {", name_and_type) == 1)
171	  version10p = 0;
172	else
173	  continue;
174
175	if (!(type = strrchr(name_and_type, '_')))
176	  type = name_and_type;
177	else
178	  type++;
179
180	if (strcmp("bits[]", type))
181	  continue;
182
183	if (!ww || !hh)
184	  RETURN (BitmapFileInvalid);
185
186	if ((ww % 16) && ((ww % 16) < 9) && version10p)
187	  padding = 1;
188	else
189	  padding = 0;
190
191	bytes_per_line = (ww+7)/8 + padding;
192
193	size = bytes_per_line * hh;
194	bits = Xmalloc (size);
195	if (!bits)
196	  RETURN (BitmapNoMemory);
197
198	if (version10p) {
199	    unsigned char *ptr;
200	    int bytes;
201
202	    for (bytes=0, ptr=bits; bytes<size; (bytes += 2)) {
203		if ((value = NextInt(fstream)) < 0)
204		  RETURN (BitmapFileInvalid);
205		*(ptr++) = value;
206		if (!padding || ((bytes+2) % bytes_per_line))
207		  *(ptr++) = value >> 8;
208	    }
209	} else {
210	    unsigned char *ptr;
211	    int bytes;
212
213	    for (bytes=0, ptr=bits; bytes<size; bytes++, ptr++) {
214		if ((value = NextInt(fstream)) < 0)
215		  RETURN (BitmapFileInvalid);
216		*ptr=value;
217	    }
218	}
219
220	/* If we got to this point, we read a full bitmap file. Break so we don't
221	 * start reading another one from the same file and leak the memory
222	 * allocated for the previous one. */
223	break;
224    }					/* end while */
225
226    fclose(fstream);
227    if (!bits)
228	return (BitmapFileInvalid);
229
230    *data = bits;
231    *width = ww;
232    *height = hh;
233    if (x_hot) *x_hot = hx;
234    if (y_hot) *y_hot = hy;
235
236    return (BitmapSuccess);
237}
238
239int
240XReadBitmapFile (
241    Display *display,
242    Drawable d,
243    _Xconst char *filename,
244    unsigned int *width,                /* RETURNED */
245    unsigned int *height,               /* RETURNED */
246    Pixmap *pixmap,                     /* RETURNED */
247    int *x_hot,                         /* RETURNED */
248    int *y_hot)                         /* RETURNED */
249{
250    unsigned char *data;
251    int res;
252
253    res = XReadBitmapFileData(filename, width, height, &data, x_hot, y_hot);
254    if (res != BitmapSuccess)
255	return res;
256    *pixmap = XCreateBitmapFromData(display, d, (char *)data, *width, *height);
257    Xfree(data);
258    if (*pixmap == None)
259	return (BitmapNoMemory);
260    return (BitmapSuccess);
261}
262