Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / lib / DtHelp / XbmUtils.c
1 /* $XConsortium: XbmUtils.c /main/4 1996/05/09 03:44:48 drk $ */
2 /* 
3 ** XbmUtils.c
4 **
5 ** This module provides routines that allow a pixmap to be generated from 
6 ** a _DtGrStream containing XBM data.  The module is adapted from the 
7 ** RdBitF.c module in the X11R6 version of libX11.
8 */
9
10 /*
11
12 Copyright (c) 1987  X Consortium
13
14 Permission is hereby granted, free of charge, to any person obtaining
15 a copy of this software and associated documentation files (the
16 "Software"), to deal in the Software without restriction, including
17 without limitation the rights to use, copy, modify, merge, publish,
18 distribute, sublicense, and/or sell copies of the Software, and to
19 permit persons to whom the Software is furnished to do so, subject to
20 the following conditions:
21
22 The above copyright notice and this permission notice shall be included
23 in all copies or substantial portions of the Software.
24
25 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
26 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
28 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
29 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
31 OTHER DEALINGS IN THE SOFTWARE.
32
33 Except as contained in this notice, the name of the X Consortium shall
34 not be used in advertising or otherwise to promote the sale, use or
35 other dealings in this Software without prior written authorization
36 from the X Consortium.
37
38 */
39
40 /*
41  *      Code to read bitmaps from disk files. Interprets 
42  *      data from X10 and X11 bitmap files and creates
43  *      Pixmap representations of files. Returns Pixmap
44  *      ID and specifics about image.
45  *
46  *      Modified for speedup by Jim Becker, changed image
47  *      data parsing logic (removed some fscanf()s). 
48  *      Aug 5, 1988
49  *
50  * Note that this file and ../Xmu/RdBitF.c look very similar....  Keep them
51  * that way (but don't use common source code so that people can have one 
52  * without the other).
53  */
54
55 #include <X11/Xlibint.h>
56 #include <X11/Xos.h>
57 #include <X11/Xutil.h>
58 #include <stdio.h>
59 #include <ctype.h>
60
61 #include "GraphicsP.h"
62 #include "Lock.h"
63
64 #define MAX_SIZE 255
65
66 /* shared data for the image read/parse logic */
67 static short hexTable[256];             /* conversion value */
68
69 /*
70  *      Table index for the hex values. Initialized once, first time.
71  *      Used for translation value or delimiter significance lookup.
72  */
73 static void initHexTable()
74 {
75     /*
76      * We build the table at run time for several reasons:
77      *
78      *     1.  portable to non-ASCII machines.
79      *     2.  still reentrant since we set the init flag after setting table.
80      *     3.  easier to extend.
81      *     4.  less prone to bugs.
82      */
83     hexTable['0'] = 0;  hexTable['1'] = 1;
84     hexTable['2'] = 2;  hexTable['3'] = 3;
85     hexTable['4'] = 4;  hexTable['5'] = 5;
86     hexTable['6'] = 6;  hexTable['7'] = 7;
87     hexTable['8'] = 8;  hexTable['9'] = 9;
88     hexTable['A'] = 10; hexTable['B'] = 11;
89     hexTable['C'] = 12; hexTable['D'] = 13;
90     hexTable['E'] = 14; hexTable['F'] = 15;
91     hexTable['a'] = 10; hexTable['b'] = 11;
92     hexTable['c'] = 12; hexTable['d'] = 13;
93     hexTable['e'] = 14; hexTable['f'] = 15;
94
95     /* delimiters of significance are flagged w/ negative value */
96     hexTable[' '] = -1; hexTable[','] = -1;
97     hexTable['}'] = -1; hexTable['\n'] = -1;
98     hexTable['\t'] = -1;
99 }
100
101 /*
102  *      read next hex value in the input stream, return -1 if EOF
103  */
104 static NextInt (fstream)
105     _DtGrStream *fstream;
106 {
107     int ch;
108     int value = 0;
109     int gotone = 0;
110     int done = 0;
111     
112     /* loop, accumulate hex value until find delimiter  */
113     /* skip any initial delimiters found in read stream */
114
115     _DtHelpProcessLock();
116     while (!done) {
117         ch = _DtGrGetChar(fstream);
118         if (ch == EOF) {
119             value       = -1;
120             done++;
121         } else {
122             /* trim high bits, check type and accumulate */
123             ch &= 0xff;
124             if (isascii(ch) && isxdigit(ch)) {
125                 value = (value << 4) + hexTable[ch];
126                 gotone++;
127             } else if ((hexTable[ch]) < 0 && gotone)
128               done++;
129         }
130     }
131     _DtHelpProcessUnlock();
132     return value;
133 }
134
135 #if NeedFunctionPrototypes
136 int _DtGrReadBitmapStreamData (
137     _DtGrStream *fstream,
138     unsigned int *width,                /* RETURNED */
139     unsigned int *height,               /* RETURNED */
140     unsigned char **data,               /* RETURNED */
141     int *x_hot,                         /* RETURNED */
142     int *y_hot)                         /* RETURNED */
143 #else
144 int _DtGrReadBitmapStreamData (stream, width, height, data, x_hot, y_hot)
145     _DtGrStream *fstream;
146     unsigned int *width, *height;       /* RETURNED */
147     unsigned char **data;               /* RETURNED */
148     int *x_hot, *y_hot;                 /* RETURNED */
149 #endif
150 {
151     unsigned char *bits = NULL;         /* working variable */
152     char line[MAX_SIZE];                /* input line from file */
153     int size;                           /* number of bytes of data */
154     char name_and_type[MAX_SIZE];       /* an input line */
155     char *type;                         /* for parsing */
156     int value;                          /* from an input line */
157     int version10p;                     /* boolean, old format */
158     int padding;                        /* to handle alignment */
159     int bytes_per_line;                 /* per scanline of data */
160     unsigned int ww = 0;                /* width */
161     unsigned int hh = 0;                /* height */
162     int hx = -1;                        /* x hotspot */
163     int hy = -1;                        /* y hotspot */
164     static Bool initialized = False;    /* easier to fill in at run time */
165
166     /* first time initialization */
167     _DtHelpProcessLock();
168     if (initialized == False)
169       {
170         initHexTable();
171         initialized = True;
172       }
173     _DtHelpProcessUnlock();
174
175     /* error cleanup and return macro   */
176 #define RETURN(code) \
177 { if (bits) Xfree ((char *)bits); return code; }
178
179     while (_DtGrGetString(line, MAX_SIZE, fstream)) {
180         if (strlen(line) == MAX_SIZE-1)
181             RETURN (BitmapFileInvalid);
182         if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
183             if (!(type = strrchr(name_and_type, '_')))
184               type = name_and_type;
185             else
186               type++;
187
188             if (!strcmp("width", type))
189               ww = (unsigned int) value;
190             if (!strcmp("height", type))
191               hh = (unsigned int) value;
192             if (!strcmp("hot", type)) {
193                 if (type-- == name_and_type || type-- == name_and_type)
194                   continue;
195                 if (!strcmp("x_hot", type))
196                   hx = value;
197                 if (!strcmp("y_hot", type))
198                   hy = value;
199             }
200             continue;
201         }
202     
203         if (sscanf(line, "static short %s = {", name_and_type) == 1)
204           version10p = 1;
205         else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
206           version10p = 0;
207         else if (sscanf(line, "static char %s = {", name_and_type) == 1)
208           version10p = 0;
209         else
210           continue;
211
212         if (!(type = strrchr(name_and_type, '_')))
213           type = name_and_type;
214         else
215           type++;
216
217         if (strcmp("bits[]", type))
218           continue;
219     
220         if (!ww || !hh)
221           RETURN (BitmapFileInvalid);
222
223         if ((ww % 16) && ((ww % 16) < 9) && version10p)
224           padding = 1;
225         else
226           padding = 0;
227
228         bytes_per_line = (ww+7)/8 + padding;
229
230         size = bytes_per_line * hh;
231         bits = (unsigned char *) Xmalloc ((unsigned int) size);
232         if (!bits) 
233           RETURN (BitmapNoMemory);
234
235         if (version10p) {
236             unsigned char *ptr;
237             int bytes;
238
239             for (bytes=0, ptr=bits; bytes<size; (bytes += 2)) {
240                 if ((value = NextInt(fstream)) < 0)
241                   RETURN (BitmapFileInvalid);
242                 *(ptr++) = value;
243                 if (!padding || ((bytes+2) % bytes_per_line))
244                   *(ptr++) = value >> 8;
245             }
246         } else {
247             unsigned char *ptr;
248             int bytes;
249
250             for (bytes=0, ptr=bits; bytes<size; bytes++, ptr++) {
251                 if ((value = NextInt(fstream)) < 0) 
252                   RETURN (BitmapFileInvalid);
253                 *ptr=value;
254             }
255         }
256     }                                   /* end while */
257
258     if (!bits)
259         return (BitmapFileInvalid);
260
261     *data = bits;
262     *width = ww;
263     *height = hh;
264     if (x_hot) *x_hot = hx;
265     if (y_hot) *y_hot = hy;
266
267     return (BitmapSuccess);
268 }
269
270 #if NeedFunctionPrototypes
271 int _DtGrReadBitmapStream (
272     Display *display,
273     Drawable d,
274     _DtGrStream *stream,
275     unsigned int *width,                /* RETURNED */
276     unsigned int *height,               /* RETURNED */
277     Pixmap *pixmap,                     /* RETURNED */
278     int *x_hot,                         /* RETURNED */
279     int *y_hot)                         /* RETURNED */
280 #else
281 int _DtGrReadBitmapStream (display, d, stream, width, height, pixmap, x_hot, y_hot)
282     Display *display;
283     Drawable d;
284     _DtGrStream *stream;
285     char *filename;
286     unsigned int *width, *height;       /* RETURNED */
287     Pixmap *pixmap;                     /* RETURNED */
288     int *x_hot, *y_hot;                 /* RETURNED */
289 #endif
290 {
291     Pixmap pix;                         /* value to return */
292     unsigned char *data;
293     int res;
294
295     res = _DtGrReadBitmapStreamData(stream, width, height, &data, x_hot, y_hot);
296     if (res != BitmapSuccess)
297         return res;
298     *pixmap = XCreateBitmapFromData(display, d, (char *)data, *width, *height);
299     Xfree((char *)data);
300     if (*pixmap == None)
301         return (BitmapNoMemory);
302     return (BitmapSuccess);
303 }