FileUtils.c: fix CERT VU#575804
[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/Xlibint.h>
78 #include <X11/Xos.h>
79 #include <X11/Xutil.h>
80 #include <stdio.h>
81 #include <ctype.h>
82
83 #include "GraphicsP.h"
84 #include "Lock.h"
85
86 #define MAX_SIZE 255
87
88 /* shared data for the image read/parse logic */
89 static short hexTable[256];             /* conversion value */
90
91 /*
92  *      Table index for the hex values. Initialized once, first time.
93  *      Used for translation value or delimiter significance lookup.
94  */
95 static void initHexTable()
96 {
97     /*
98      * We build the table at run time for several reasons:
99      *
100      *     1.  portable to non-ASCII machines.
101      *     2.  still reentrant since we set the init flag after setting table.
102      *     3.  easier to extend.
103      *     4.  less prone to bugs.
104      */
105     hexTable['0'] = 0;  hexTable['1'] = 1;
106     hexTable['2'] = 2;  hexTable['3'] = 3;
107     hexTable['4'] = 4;  hexTable['5'] = 5;
108     hexTable['6'] = 6;  hexTable['7'] = 7;
109     hexTable['8'] = 8;  hexTable['9'] = 9;
110     hexTable['A'] = 10; hexTable['B'] = 11;
111     hexTable['C'] = 12; hexTable['D'] = 13;
112     hexTable['E'] = 14; hexTable['F'] = 15;
113     hexTable['a'] = 10; hexTable['b'] = 11;
114     hexTable['c'] = 12; hexTable['d'] = 13;
115     hexTable['e'] = 14; hexTable['f'] = 15;
116
117     /* delimiters of significance are flagged w/ negative value */
118     hexTable[' '] = -1; hexTable[','] = -1;
119     hexTable['}'] = -1; hexTable['\n'] = -1;
120     hexTable['\t'] = -1;
121 }
122
123 /*
124  *      read next hex value in the input stream, return -1 if EOF
125  */
126 static NextInt (fstream)
127     _DtGrStream *fstream;
128 {
129     int ch;
130     int value = 0;
131     int gotone = 0;
132     int done = 0;
133     
134     /* loop, accumulate hex value until find delimiter  */
135     /* skip any initial delimiters found in read stream */
136
137     _DtHelpProcessLock();
138     while (!done) {
139         ch = _DtGrGetChar(fstream);
140         if (ch == EOF) {
141             value       = -1;
142             done++;
143         } else {
144             /* trim high bits, check type and accumulate */
145             ch &= 0xff;
146             if (isascii(ch) && isxdigit(ch)) {
147                 value = (value << 4) + hexTable[ch];
148                 gotone++;
149             } else if ((hexTable[ch]) < 0 && gotone)
150               done++;
151         }
152     }
153     _DtHelpProcessUnlock();
154     return value;
155 }
156
157 #if NeedFunctionPrototypes
158 int _DtGrReadBitmapStreamData (
159     _DtGrStream *fstream,
160     unsigned int *width,                /* RETURNED */
161     unsigned int *height,               /* RETURNED */
162     unsigned char **data,               /* RETURNED */
163     int *x_hot,                         /* RETURNED */
164     int *y_hot)                         /* RETURNED */
165 #else
166 int _DtGrReadBitmapStreamData (stream, width, height, data, x_hot, y_hot)
167     _DtGrStream *fstream;
168     unsigned int *width, *height;       /* RETURNED */
169     unsigned char **data;               /* RETURNED */
170     int *x_hot, *y_hot;                 /* RETURNED */
171 #endif
172 {
173     unsigned char *bits = NULL;         /* working variable */
174     char line[MAX_SIZE];                /* input line from file */
175     int size;                           /* number of bytes of data */
176     char name_and_type[MAX_SIZE];       /* an input line */
177     char *type;                         /* for parsing */
178     int value;                          /* from an input line */
179     int version10p;                     /* boolean, old format */
180     int padding;                        /* to handle alignment */
181     int bytes_per_line;                 /* per scanline of data */
182     unsigned int ww = 0;                /* width */
183     unsigned int hh = 0;                /* height */
184     int hx = -1;                        /* x hotspot */
185     int hy = -1;                        /* y hotspot */
186     static Bool initialized = False;    /* easier to fill in at run time */
187
188     /* first time initialization */
189     _DtHelpProcessLock();
190     if (initialized == False)
191       {
192         initHexTable();
193         initialized = True;
194       }
195     _DtHelpProcessUnlock();
196
197     /* error cleanup and return macro   */
198 #define RETURN(code) \
199 { if (bits) Xfree ((char *)bits); return code; }
200
201     while (_DtGrGetString(line, MAX_SIZE, fstream)) {
202         if (strlen(line) == MAX_SIZE-1)
203             RETURN (BitmapFileInvalid);
204         if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) {
205             if (!(type = strrchr(name_and_type, '_')))
206               type = name_and_type;
207             else
208               type++;
209
210             if (!strcmp("width", type))
211               ww = (unsigned int) value;
212             if (!strcmp("height", type))
213               hh = (unsigned int) value;
214             if (!strcmp("hot", type)) {
215                 if (type-- == name_and_type || type-- == name_and_type)
216                   continue;
217                 if (!strcmp("x_hot", type))
218                   hx = value;
219                 if (!strcmp("y_hot", type))
220                   hy = value;
221             }
222             continue;
223         }
224     
225         if (sscanf(line, "static short %s = {", name_and_type) == 1)
226           version10p = 1;
227         else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1)
228           version10p = 0;
229         else if (sscanf(line, "static char %s = {", name_and_type) == 1)
230           version10p = 0;
231         else
232           continue;
233
234         if (!(type = strrchr(name_and_type, '_')))
235           type = name_and_type;
236         else
237           type++;
238
239         if (strcmp("bits[]", type))
240           continue;
241     
242         if (!ww || !hh)
243           RETURN (BitmapFileInvalid);
244
245         if ((ww % 16) && ((ww % 16) < 9) && version10p)
246           padding = 1;
247         else
248           padding = 0;
249
250         bytes_per_line = (ww+7)/8 + padding;
251
252         size = bytes_per_line * hh;
253         bits = (unsigned char *) Xmalloc ((unsigned int) size);
254         if (!bits) 
255           RETURN (BitmapNoMemory);
256
257         if (version10p) {
258             unsigned char *ptr;
259             int bytes;
260
261             for (bytes=0, ptr=bits; bytes<size; (bytes += 2)) {
262                 if ((value = NextInt(fstream)) < 0)
263                   RETURN (BitmapFileInvalid);
264                 *(ptr++) = value;
265                 if (!padding || ((bytes+2) % bytes_per_line))
266                   *(ptr++) = value >> 8;
267             }
268         } else {
269             unsigned char *ptr;
270             int bytes;
271
272             for (bytes=0, ptr=bits; bytes<size; bytes++, ptr++) {
273                 if ((value = NextInt(fstream)) < 0) 
274                   RETURN (BitmapFileInvalid);
275                 *ptr=value;
276             }
277         }
278     }                                   /* end while */
279
280     if (!bits)
281         return (BitmapFileInvalid);
282
283     *data = bits;
284     *width = ww;
285     *height = hh;
286     if (x_hot) *x_hot = hx;
287     if (y_hot) *y_hot = hy;
288
289     return (BitmapSuccess);
290 }
291
292 #if NeedFunctionPrototypes
293 int _DtGrReadBitmapStream (
294     Display *display,
295     Drawable d,
296     _DtGrStream *stream,
297     unsigned int *width,                /* RETURNED */
298     unsigned int *height,               /* RETURNED */
299     Pixmap *pixmap,                     /* RETURNED */
300     int *x_hot,                         /* RETURNED */
301     int *y_hot)                         /* RETURNED */
302 #else
303 int _DtGrReadBitmapStream (display, d, stream, width, height, pixmap, x_hot, y_hot)
304     Display *display;
305     Drawable d;
306     _DtGrStream *stream;
307     char *filename;
308     unsigned int *width, *height;       /* RETURNED */
309     Pixmap *pixmap;                     /* RETURNED */
310     int *x_hot, *y_hot;                 /* RETURNED */
311 #endif
312 {
313     Pixmap pix;                         /* value to return */
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 }