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#include "reallocarray.h" 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 if (!(fstream = fopen(filename, "r"))) 133 return BitmapOpenFailed; 134 135 /* error cleanup and return macro */ 136#define RETURN(code) \ 137 do { Xfree (bits); fclose (fstream); return code; } while (0) 138 139 while (fgets(line, MAX_SIZE, fstream)) { 140 if (strlen(line) == MAX_SIZE-1) 141 RETURN (BitmapFileInvalid); 142 if (sscanf(line,"#define %s %d",name_and_type,&value) == 2) { 143 if (!(type = strrchr(name_and_type, '_'))) 144 type = name_and_type; 145 else 146 type++; 147 148 if (!strcmp("width", type)) 149 ww = (unsigned int) value; 150 if (!strcmp("height", type)) 151 hh = (unsigned int) value; 152 if (!strcmp("hot", type)) { 153 if (type-- == name_and_type || type-- == name_and_type) 154 continue; 155 if (!strcmp("x_hot", type)) 156 hx = value; 157 if (!strcmp("y_hot", type)) 158 hy = value; 159 } 160 continue; 161 } 162 163 if (sscanf(line, "static short %s = {", name_and_type) == 1) 164 version10p = 1; 165 else if (sscanf(line,"static unsigned char %s = {",name_and_type) == 1) 166 version10p = 0; 167 else if (sscanf(line, "static char %s = {", name_and_type) == 1) 168 version10p = 0; 169 else 170 continue; 171 172 if (!(type = strrchr(name_and_type, '_'))) 173 type = name_and_type; 174 else 175 type++; 176 177 if (strcmp("bits[]", type)) 178 continue; 179 180 if (!ww || !hh) 181 RETURN (BitmapFileInvalid); 182 183 if ((ww % 16) && ((ww % 16) < 9) && version10p) 184 padding = 1; 185 else 186 padding = 0; 187 188 bytes_per_line = (ww+7)/8 + padding; 189 190 bits = Xmallocarray (hh, bytes_per_line); 191 if (!bits) 192 RETURN (BitmapNoMemory); 193 size = bytes_per_line * hh; 194 195 if (version10p) { 196 unsigned char *ptr; 197 int bytes; 198 199 for (bytes=0, ptr=bits; bytes<size; (bytes += 2)) { 200 if ((value = NextInt(fstream)) < 0) 201 RETURN (BitmapFileInvalid); 202 *(ptr++) = value; 203 if (!padding || ((bytes+2) % bytes_per_line)) 204 *(ptr++) = value >> 8; 205 } 206 } else { 207 unsigned char *ptr; 208 int bytes; 209 210 for (bytes=0, ptr=bits; bytes<size; bytes++, ptr++) { 211 if ((value = NextInt(fstream)) < 0) 212 RETURN (BitmapFileInvalid); 213 *ptr=value; 214 } 215 } 216 217 /* If we got to this point, we read a full bitmap file. Break so we don't 218 * start reading another one from the same file and leak the memory 219 * allocated for the previous one. */ 220 break; 221 } /* end while */ 222 223 fclose(fstream); 224 if (!bits) 225 return (BitmapFileInvalid); 226 227 *data = bits; 228 *width = ww; 229 *height = hh; 230 if (x_hot) *x_hot = hx; 231 if (y_hot) *y_hot = hy; 232 233 return (BitmapSuccess); 234} 235 236int 237XReadBitmapFile ( 238 Display *display, 239 Drawable d, 240 _Xconst char *filename, 241 unsigned int *width, /* RETURNED */ 242 unsigned int *height, /* RETURNED */ 243 Pixmap *pixmap, /* RETURNED */ 244 int *x_hot, /* RETURNED */ 245 int *y_hot) /* RETURNED */ 246{ 247 unsigned char *data; 248 int res; 249 250 res = XReadBitmapFileData(filename, width, height, &data, x_hot, y_hot); 251 if (res != BitmapSuccess) 252 return res; 253 *pixmap = XCreateBitmapFromData(display, d, (char *)data, *width, *height); 254 Xfree(data); 255 if (*pixmap == None) 256 return (BitmapNoMemory); 257 return (BitmapSuccess); 258} 259