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