/src/CrDatFrI.c
C | 403 lines | 288 code | 53 blank | 62 comment | 51 complexity | 32581a330304cf42736c297e5f5f8647 MD5 | raw file
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 35/* October 2004, source code review by Thomas Biege <thomas@suse.de> */ 36 37#ifdef HAVE_CONFIG_H 38#include <config.h> 39#endif 40#include "XpmI.h" 41 42LFUNC(CreateColors, int, (char **dataptr, unsigned int *data_size, 43 XpmColor *colors, unsigned int ncolors, 44 unsigned int cpp)); 45 46LFUNC(CreatePixels, void, (char **dataptr, unsigned int data_size, 47 unsigned int width, 48 unsigned int height, unsigned int cpp, 49 unsigned int *pixels, XpmColor *colors)); 50 51LFUNC(CountExtensions, void, (XpmExtension *ext, unsigned int num, 52 unsigned int *ext_size, 53 unsigned int *ext_nlines)); 54 55LFUNC(CreateExtensions, void, (char **dataptr, unsigned int data_size, 56 unsigned int offset, 57 XpmExtension *ext, unsigned int num, 58 unsigned int ext_nlines)); 59 60int 61XpmCreateDataFromImage( 62 Display *display, 63 char ***data_return, 64 XImage *image, 65 XImage *shapeimage, 66 XpmAttributes *attributes) 67{ 68 XpmImage xpmimage; 69 XpmInfo info; 70 int ErrorStatus; 71 72 /* initialize return value */ 73 if (data_return) 74 *data_return = NULL; 75 76 /* create an XpmImage from the image */ 77 ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage, 78 &xpmimage, attributes); 79 if (ErrorStatus != XpmSuccess) 80 return (ErrorStatus); 81 82 /* create the data from the XpmImage */ 83 if (attributes) { 84 xpmSetInfo(&info, attributes); 85 ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, &info); 86 } else 87 ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, NULL); 88 89 /* free the XpmImage */ 90 XpmFreeXpmImage(&xpmimage); 91 92 return (ErrorStatus); 93} 94 95#undef RETURN 96#define RETURN(status) \ 97do \ 98{ \ 99 ErrorStatus = status; \ 100 goto exit; \ 101} while(0) 102 103int 104XpmCreateDataFromXpmImage( 105 char ***data_return, 106 XpmImage *image, 107 XpmInfo *info) 108{ 109 /* calculation variables */ 110 int ErrorStatus; 111 char buf[BUFSIZ]; 112 char **header = NULL, **data, **sptr, **sptr2, *s; 113 unsigned int header_size, header_nlines; 114 unsigned int data_size, data_nlines; 115 unsigned int extensions = 0, ext_size = 0, ext_nlines = 0; 116 unsigned int offset, l, n; 117 118 *data_return = NULL; 119 120 extensions = info && (info->valuemask & XpmExtensions) 121 && info->nextensions; 122 123 /* compute the number of extensions lines and size */ 124 if (extensions) 125 CountExtensions(info->extensions, info->nextensions, 126 &ext_size, &ext_nlines); 127 128 /* 129 * alloc a temporary array of char pointer for the header section which 130 * is the hints line + the color table lines 131 */ 132 header_nlines = 1 + image->ncolors; /* this may wrap and/or become 0 */ 133 134 /* 2nd check superfluous if we do not need header_nlines any further */ 135 if(header_nlines <= image->ncolors || 136 header_nlines >= UINT_MAX / sizeof(char *)) 137 return(XpmNoMemory); 138 139 header_size = sizeof(char *) * header_nlines; 140 if (header_size >= UINT_MAX / sizeof(char *)) 141 return (XpmNoMemory); 142 header = (char **) XpmCalloc(header_size, sizeof(char *)); /* can we trust image->ncolors */ 143 if (!header) 144 return (XpmNoMemory); 145 146 /* print the hints line */ 147 s = buf; 148#ifndef VOID_SPRINTF 149 s += 150#endif 151 sprintf(s, "%d %d %d %d", image->width, image->height, 152 image->ncolors, image->cpp); 153#ifdef VOID_SPRINTF 154 s += strlen(s); 155#endif 156 157 if (info && (info->valuemask & XpmHotspot)) { 158#ifndef VOID_SPRINTF 159 s += 160#endif 161 sprintf(s, " %d %d", info->x_hotspot, info->y_hotspot); 162#ifdef VOID_SPRINTF 163 s += strlen(s); 164#endif 165 } 166 if (extensions) { 167 strcpy(s, " XPMEXT"); 168 s += 7; 169 } 170 l = s - buf + 1; 171 *header = (char *) XpmMalloc(l); 172 if (!*header) 173 RETURN(XpmNoMemory); 174 header_size += l; 175 strcpy(*header, buf); 176 177 /* print colors */ 178 ErrorStatus = CreateColors(header + 1, &header_size, 179 image->colorTable, image->ncolors, image->cpp); 180 181 if (ErrorStatus != XpmSuccess) 182 RETURN(ErrorStatus); 183 184 /* now we know the size needed, alloc the data and copy the header lines */ 185 offset = image->width * image->cpp + 1; 186 187 if(offset <= image->width || offset <= image->cpp) 188 RETURN(XpmNoMemory); 189 190 if( (image->height + ext_nlines) >= UINT_MAX / sizeof(char *)) 191 RETURN(XpmNoMemory); 192 data_size = (image->height + ext_nlines) * sizeof(char *); 193 194 if (image->height > UINT_MAX / offset || 195 image->height * offset > UINT_MAX - data_size) 196 RETURN(XpmNoMemory); 197 data_size += image->height * offset; 198 199 if( (header_size + ext_size) >= (UINT_MAX - data_size) ) 200 RETURN(XpmNoMemory); 201 data_size += header_size + ext_size; 202 203 data = (char **) XpmMalloc(data_size); 204 if (!data) 205 RETURN(XpmNoMemory); 206 207 data_nlines = header_nlines + image->height + ext_nlines; 208 *data = (char *) (data + data_nlines); 209 210 /* can header have less elements then n suggests? */ 211 n = image->ncolors; 212 for (l = 0, sptr = data, sptr2 = header; l <= n && sptr && sptr2; l++, sptr++, sptr2++) { 213 strcpy(*sptr, *sptr2); 214 *(sptr + 1) = *sptr + strlen(*sptr2) + 1; 215 } 216 217 /* print pixels */ 218 data[header_nlines] = (char *) data + header_size 219 + (image->height + ext_nlines) * sizeof(char *); 220 221 CreatePixels(data + header_nlines, data_size-header_nlines, image->width, image->height, 222 image->cpp, image->data, image->colorTable); 223 224 /* print extensions */ 225 if (extensions) 226 CreateExtensions(data + header_nlines + image->height - 1, 227 data_size - header_nlines - image->height + 1, offset, 228 info->extensions, info->nextensions, 229 ext_nlines); 230 231 *data_return = data; 232 ErrorStatus = XpmSuccess; 233 234/* exit point, free only locally allocated variables */ 235exit: 236 if (header) { 237 for (l = 0; l < header_nlines; l++) 238 if (header[l]) 239 XpmFree(header[l]); 240 XpmFree(header); 241 } 242 return(ErrorStatus); 243} 244 245static int 246CreateColors( 247 char **dataptr, 248 unsigned int *data_size, 249 XpmColor *colors, 250 unsigned int ncolors, 251 unsigned int cpp) 252{ 253 char buf[BUFSIZ]; 254 unsigned int a, key, l; 255 char *s, *s2; 256 char **defaults; 257 258 /* can ncolors be trusted here? */ 259 for (a = 0; a < ncolors; a++, colors++, dataptr++) { 260 261 defaults = (char **) colors; 262 if(sizeof(buf) <= cpp) 263 return(XpmNoMemory); 264 strncpy(buf, *defaults++, cpp); 265 s = buf + cpp; 266 267 if(sizeof(buf) <= (s-buf)) 268 return XpmNoMemory; 269 270 for (key = 1; key <= NKEYS; key++, defaults++) { 271 if ((s2 = *defaults)) { 272#ifndef VOID_SPRINTF 273 s += 274#endif 275 /* assume C99 compliance */ 276 snprintf(s, sizeof(buf)-(s-buf), "\t%s %s", xpmColorKeys[key - 1], s2); 277#ifdef VOID_SPRINTF 278 s += strlen(s); 279#endif 280 /* does s point out-of-bounds? */ 281 if(sizeof(buf) < (s-buf)) 282 return XpmNoMemory; 283 } 284 } 285 /* what about using strdup()? */ 286 l = s - buf + 1; 287 s = (char *) XpmMalloc(l); 288 if (!s) 289 return (XpmNoMemory); 290 *data_size += l; 291 *dataptr = strcpy(s, buf); 292 } 293 return (XpmSuccess); 294} 295 296static void 297CreatePixels( 298 char **dataptr, 299 unsigned int data_size, 300 unsigned int width, 301 unsigned int height, 302 unsigned int cpp, 303 unsigned int *pixels, 304 XpmColor *colors) 305{ 306 char *s; 307 unsigned int x, y, h, offset; 308 309 if(height <= 1) 310 return; 311 312 h = height - 1; 313 314 offset = width * cpp + 1; 315 316 if(offset <= width || offset <= cpp) 317 return; 318 319 /* why trust h? */ 320 for (y = 0; y < h; y++, dataptr++) { 321 s = *dataptr; 322 /* why trust width? */ 323 for (x = 0; x < width; x++, pixels++) { 324 if(cpp > (data_size - (s - *dataptr))) 325 return; 326 strncpy(s, colors[*pixels].string, cpp); /* why trust pixel? */ 327 s += cpp; 328 } 329 *s = '\0'; 330 if(offset > data_size) 331 return; 332 *(dataptr + 1) = *dataptr + offset; 333 } 334 /* duplicate some code to avoid a test in the loop */ 335 s = *dataptr; 336 /* why trust width? */ 337 for (x = 0; x < width; x++, pixels++) { 338 if(cpp > data_size - (s - *dataptr)) 339 return; 340 strncpy(s, colors[*pixels].string, cpp); /* why should we trust *pixel? */ 341 s += cpp; 342 } 343 *s = '\0'; 344} 345 346static void 347CountExtensions( 348 XpmExtension *ext, 349 unsigned int num, 350 unsigned int *ext_size, 351 unsigned int *ext_nlines) 352{ 353 unsigned int x, y, a, size, nlines; 354 char **line; 355 356 size = 0; 357 nlines = 0; 358 for (x = 0; x < num; x++, ext++) { 359 /* 1 for the name */ 360 nlines += ext->nlines + 1; 361 /* 8 = 7 (for "XPMEXT ") + 1 (for 0) */ 362 size += strlen(ext->name) + 8; 363 a = ext->nlines; 364 for (y = 0, line = ext->lines; y < a; y++, line++) 365 size += strlen(*line) + 1; 366 } 367 /* 10 and 1 are for the ending "XPMENDEXT" */ 368 *ext_size = size + 10; 369 *ext_nlines = nlines + 1; 370} 371 372static void 373CreateExtensions( 374 char **dataptr, 375 unsigned int data_size, 376 unsigned int offset, 377 XpmExtension *ext, 378 unsigned int num, 379 unsigned int ext_nlines) 380{ 381 unsigned int x, y, a, b; 382 char **line; 383 384 *(dataptr + 1) = *dataptr + offset; 385 dataptr++; 386 a = 0; 387 for (x = 0; x < num; x++, ext++) { 388 snprintf(*dataptr, data_size, "XPMEXT %s", ext->name); 389 a++; 390 if (a < ext_nlines) 391 *(dataptr + 1) = *dataptr + strlen(ext->name) + 8; 392 dataptr++; 393 b = ext->nlines; /* can we trust these values? */ 394 for (y = 0, line = ext->lines; y < b; y++, line++) { 395 strcpy(*dataptr, *line); 396 a++; 397 if (a < ext_nlines) 398 *(dataptr + 1) = *dataptr + strlen(*line) + 1; 399 dataptr++; 400 } 401 } 402 strcpy(*dataptr, "XPMENDEXT"); 403}