CrDatFrI.c revision a966c04f
1/* 2 * Copyright (C) 1989-95 GROUPE BULL 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to 6 * deal in the Software without restriction, including without limitation the 7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 * sell copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 * 21 * Except as contained in this notice, the name of GROUPE BULL shall not be 22 * used in advertising or otherwise to promote the sale, use or other dealings 23 * in this Software without prior written authorization from GROUPE BULL. 24 */ 25 26/*****************************************************************************\ 27* CrDataFI.c: * 28* * 29* XPM library * 30* Scan an image and possibly its mask and create an XPM array * 31* * 32* Developed by Arnaud Le Hors * 33\*****************************************************************************/ 34/* $XFree86$ */ 35 36/* October 2004, source code review by Thomas Biege <thomas@suse.de> */ 37 38#ifdef HAVE_CONFIG_H 39#include <config.h> 40#endif 41#include "XpmI.h" 42 43LFUNC(CreateColors, int, (char **dataptr, unsigned int *data_size, 44 XpmColor *colors, unsigned int ncolors, 45 unsigned int cpp)); 46 47LFUNC(CreatePixels, void, (char **dataptr, unsigned int data_size, 48 unsigned int width, 49 unsigned int height, unsigned int cpp, 50 unsigned int *pixels, XpmColor *colors)); 51 52LFUNC(CountExtensions, void, (XpmExtension *ext, unsigned int num, 53 unsigned int *ext_size, 54 unsigned int *ext_nlines)); 55 56LFUNC(CreateExtensions, void, (char **dataptr, unsigned int data_size, 57 unsigned int offset, 58 XpmExtension *ext, unsigned int num, 59 unsigned int ext_nlines)); 60 61int 62XpmCreateDataFromImage(display, data_return, image, shapeimage, attributes) 63 Display *display; 64 char ***data_return; 65 XImage *image; 66 XImage *shapeimage; 67 XpmAttributes *attributes; 68{ 69 XpmImage xpmimage; 70 XpmInfo info; 71 int ErrorStatus; 72 73 /* initialize return value */ 74 if (data_return) 75 *data_return = NULL; 76 77 /* create an XpmImage from the image */ 78 ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage, 79 &xpmimage, attributes); 80 if (ErrorStatus != XpmSuccess) 81 return (ErrorStatus); 82 83 /* create the data from the XpmImage */ 84 if (attributes) { 85 xpmSetInfo(&info, attributes); 86 ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, &info); 87 } else 88 ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, NULL); 89 90 /* free the XpmImage */ 91 XpmFreeXpmImage(&xpmimage); 92 93 return (ErrorStatus); 94} 95 96#undef RETURN 97#define RETURN(status) \ 98do \ 99{ \ 100 ErrorStatus = status; \ 101 goto exit; \ 102} while(0) 103 104int 105XpmCreateDataFromXpmImage(data_return, image, info) 106 char ***data_return; 107 XpmImage *image; 108 XpmInfo *info; 109{ 110 /* calculation variables */ 111 int ErrorStatus; 112 char buf[BUFSIZ]; 113 char **header = NULL, **data, **sptr, **sptr2, *s; 114 unsigned int header_size, header_nlines; 115 unsigned int data_size, data_nlines; 116 unsigned int extensions = 0, ext_size = 0, ext_nlines = 0; 117 unsigned int offset, l, n; 118 119 *data_return = NULL; 120 121 extensions = info && (info->valuemask & XpmExtensions) 122 && info->nextensions; 123 124 /* compute the number of extensions lines and size */ 125 if (extensions) 126 CountExtensions(info->extensions, info->nextensions, 127 &ext_size, &ext_nlines); 128 129 /* 130 * alloc a temporary array of char pointer for the header section which 131 * is the hints line + the color table lines 132 */ 133 header_nlines = 1 + image->ncolors; /* this may wrap and/or become 0 */ 134 135 /* 2nd check superfluous if we do not need header_nlines any further */ 136 if(header_nlines <= image->ncolors || 137 header_nlines >= UINT_MAX / sizeof(char *)) 138 return(XpmNoMemory); 139 140 header_size = sizeof(char *) * header_nlines; 141 if (header_size >= UINT_MAX / sizeof(char *)) 142 return (XpmNoMemory); 143 header = (char **) XpmCalloc(header_size, sizeof(char *)); /* can we trust image->ncolors */ 144 if (!header) 145 return (XpmNoMemory); 146 147 /* print the hints line */ 148 s = buf; 149#ifndef VOID_SPRINTF 150 s += 151#endif 152 sprintf(s, "%d %d %d %d", image->width, image->height, 153 image->ncolors, image->cpp); 154#ifdef VOID_SPRINTF 155 s += strlen(s); 156#endif 157 158 if (info && (info->valuemask & XpmHotspot)) { 159#ifndef VOID_SPRINTF 160 s += 161#endif 162 sprintf(s, " %d %d", info->x_hotspot, info->y_hotspot); 163#ifdef VOID_SPRINTF 164 s += strlen(s); 165#endif 166 } 167 if (extensions) { 168 strcpy(s, " XPMEXT"); 169 s += 7; 170 } 171 l = s - buf + 1; 172 *header = (char *) XpmMalloc(l); 173 if (!*header) 174 RETURN(XpmNoMemory); 175 header_size += l; 176 strcpy(*header, buf); 177 178 /* print colors */ 179 ErrorStatus = CreateColors(header + 1, &header_size, 180 image->colorTable, image->ncolors, image->cpp); 181 182 if (ErrorStatus != XpmSuccess) 183 RETURN(ErrorStatus); 184 185 /* now we know the size needed, alloc the data and copy the header lines */ 186 offset = image->width * image->cpp + 1; 187 188 if(offset <= image->width || offset <= image->cpp) 189 RETURN(XpmNoMemory); 190 191 if( (image->height + ext_nlines) >= UINT_MAX / sizeof(char *)) 192 RETURN(XpmNoMemory); 193 data_size = (image->height + ext_nlines) * sizeof(char *); 194 195 if (image->height > UINT_MAX / offset || 196 image->height * offset > UINT_MAX - data_size) 197 RETURN(XpmNoMemory); 198 data_size += image->height * offset; 199 200 if( (header_size + ext_size) >= (UINT_MAX - data_size) ) 201 RETURN(XpmNoMemory); 202 data_size += header_size + ext_size; 203 204 data = (char **) XpmMalloc(data_size); 205 if (!data) 206 RETURN(XpmNoMemory); 207 208 data_nlines = header_nlines + image->height + ext_nlines; 209 *data = (char *) (data + data_nlines); 210 211 /* can header have less elements then n suggests? */ 212 n = image->ncolors; 213 for (l = 0, sptr = data, sptr2 = header; l <= n && sptr && sptr2; l++, sptr++, sptr2++) { 214 strcpy(*sptr, *sptr2); 215 *(sptr + 1) = *sptr + strlen(*sptr2) + 1; 216 } 217 218 /* print pixels */ 219 data[header_nlines] = (char *) data + header_size 220 + (image->height + ext_nlines) * sizeof(char *); 221 222 CreatePixels(data + header_nlines, data_size-header_nlines, image->width, image->height, 223 image->cpp, image->data, image->colorTable); 224 225 /* print extensions */ 226 if (extensions) 227 CreateExtensions(data + header_nlines + image->height - 1, 228 data_size - header_nlines - image->height + 1, offset, 229 info->extensions, info->nextensions, 230 ext_nlines); 231 232 *data_return = data; 233 ErrorStatus = XpmSuccess; 234 235/* exit point, free only locally allocated variables */ 236exit: 237 if (header) { 238 for (l = 0; l < header_nlines; l++) 239 if (header[l]) 240 XpmFree(header[l]); 241 XpmFree(header); 242 } 243 return(ErrorStatus); 244} 245 246static int 247CreateColors(dataptr, data_size, colors, ncolors, cpp) 248 char **dataptr; 249 unsigned int *data_size; 250 XpmColor *colors; 251 unsigned int ncolors; 252 unsigned int cpp; 253{ 254 char buf[BUFSIZ]; 255 unsigned int a, key, l; 256 char *s, *s2; 257 char **defaults; 258 259 /* can ncolors be trusted here? */ 260 for (a = 0; a < ncolors; a++, colors++, dataptr++) { 261 262 defaults = (char **) colors; 263 if(sizeof(buf) <= cpp) 264 return(XpmNoMemory); 265 strncpy(buf, *defaults++, cpp); 266 s = buf + cpp; 267 268 if(sizeof(buf) <= (s-buf)) 269 return XpmNoMemory; 270 271 for (key = 1; key <= NKEYS; key++, defaults++) { 272 if ((s2 = *defaults)) { 273#ifndef VOID_SPRINTF 274 s += 275#endif 276 /* assume C99 compliance */ 277 snprintf(s, sizeof(buf)-(s-buf), "\t%s %s", xpmColorKeys[key - 1], s2); 278#ifdef VOID_SPRINTF 279 s += strlen(s); 280#endif 281 /* does s point out-of-bounds? */ 282 if(sizeof(buf) < (s-buf)) 283 return XpmNoMemory; 284 } 285 } 286 /* what about using strdup()? */ 287 l = s - buf + 1; 288 s = (char *) XpmMalloc(l); 289 if (!s) 290 return (XpmNoMemory); 291 *data_size += l; 292 *dataptr = strcpy(s, buf); 293 } 294 return (XpmSuccess); 295} 296 297static void 298CreatePixels(dataptr, data_size, width, height, cpp, pixels, colors) 299 char **dataptr; 300 unsigned int data_size; 301 unsigned int width; 302 unsigned int height; 303 unsigned int cpp; 304 unsigned int *pixels; 305 XpmColor *colors; 306{ 307 char *s; 308 unsigned int x, y, h, offset; 309 310 if(height <= 1) 311 return; 312 313 h = height - 1; 314 315 offset = width * cpp + 1; 316 317 if(offset <= width || offset <= cpp) 318 return; 319 320 /* why trust h? */ 321 for (y = 0; y < h; y++, dataptr++) { 322 s = *dataptr; 323 /* why trust width? */ 324 for (x = 0; x < width; x++, pixels++) { 325 if(cpp > (data_size - (s - *dataptr))) 326 return; 327 strncpy(s, colors[*pixels].string, cpp); /* why trust pixel? */ 328 s += cpp; 329 } 330 *s = '\0'; 331 if(offset > data_size) 332 return; 333 *(dataptr + 1) = *dataptr + offset; 334 } 335 /* duplicate some code to avoid a test in the loop */ 336 s = *dataptr; 337 /* why trust width? */ 338 for (x = 0; x < width; x++, pixels++) { 339 if(cpp > data_size - (s - *dataptr)) 340 return; 341 strncpy(s, colors[*pixels].string, cpp); /* why should we trust *pixel? */ 342 s += cpp; 343 } 344 *s = '\0'; 345} 346 347static void 348CountExtensions(ext, num, ext_size, ext_nlines) 349 XpmExtension *ext; 350 unsigned int num; 351 unsigned int *ext_size; 352 unsigned int *ext_nlines; 353{ 354 unsigned int x, y, a, size, nlines; 355 char **line; 356 357 size = 0; 358 nlines = 0; 359 for (x = 0; x < num; x++, ext++) { 360 /* 1 for the name */ 361 nlines += ext->nlines + 1; 362 /* 8 = 7 (for "XPMEXT ") + 1 (for 0) */ 363 size += strlen(ext->name) + 8; 364 a = ext->nlines; 365 for (y = 0, line = ext->lines; y < a; y++, line++) 366 size += strlen(*line) + 1; 367 } 368 /* 10 and 1 are for the ending "XPMENDEXT" */ 369 *ext_size = size + 10; 370 *ext_nlines = nlines + 1; 371} 372 373static void 374CreateExtensions(dataptr, data_size, offset, ext, num, ext_nlines) 375 char **dataptr; 376 unsigned int data_size; 377 unsigned int offset; 378 XpmExtension *ext; 379 unsigned int num; 380 unsigned int ext_nlines; 381{ 382 unsigned int x, y, a, b; 383 char **line; 384 385 *(dataptr + 1) = *dataptr + offset; 386 dataptr++; 387 a = 0; 388 for (x = 0; x < num; x++, ext++) { 389 snprintf(*dataptr, data_size, "XPMEXT %s", ext->name); 390 a++; 391 if (a < ext_nlines) 392 *(dataptr + 1) = *dataptr + strlen(ext->name) + 8; 393 dataptr++; 394 b = ext->nlines; /* can we trust these values? */ 395 for (y = 0, line = ext->lines; y < b; y++, line++) { 396 strcpy(*dataptr, *line); 397 a++; 398 if (a < ext_nlines) 399 *(dataptr + 1) = *dataptr + strlen(*line) + 1; 400 dataptr++; 401 } 402 } 403 strcpy(*dataptr, "XPMENDEXT"); 404} 405