RdBitF.c revision b4ee4795
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 ((char *)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 = (unsigned char *) Xmalloc ((unsigned int) 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    }					/* end while */
220
221    fclose(fstream);
222    if (!bits)
223	return (BitmapFileInvalid);
224
225    *data = bits;
226    *width = ww;
227    *height = hh;
228    if (x_hot) *x_hot = hx;
229    if (y_hot) *y_hot = hy;
230
231    return (BitmapSuccess);
232}
233
234int
235XReadBitmapFile (
236    Display *display,
237    Drawable d,
238    _Xconst char *filename,
239    unsigned int *width,                /* RETURNED */
240    unsigned int *height,               /* RETURNED */
241    Pixmap *pixmap,                     /* RETURNED */
242    int *x_hot,                         /* RETURNED */
243    int *y_hot)                         /* RETURNED */
244{
245    unsigned char *data;
246    int res;
247
248    res = XReadBitmapFileData(filename, width, height, &data, x_hot, y_hot);
249    if (res != BitmapSuccess)
250	return res;
251    *pixmap = XCreateBitmapFromData(display, d, (char *)data, *width, *height);
252    Xfree((char *)data);
253    if (*pixmap == None)
254	return (BitmapNoMemory);
255    return (BitmapSuccess);
256}
257