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