1a966c04fSmrg/* 2a966c04fSmrg * Copyright (C) 1989-95 GROUPE BULL 3a966c04fSmrg * 4a966c04fSmrg * Permission is hereby granted, free of charge, to any person obtaining a copy 5a966c04fSmrg * of this software and associated documentation files (the "Software"), to 6a966c04fSmrg * deal in the Software without restriction, including without limitation the 7a966c04fSmrg * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8a966c04fSmrg * sell copies of the Software, and to permit persons to whom the Software is 9a966c04fSmrg * furnished to do so, subject to the following conditions: 10a966c04fSmrg * 11a966c04fSmrg * The above copyright notice and this permission notice shall be included in 12a966c04fSmrg * all copies or substantial portions of the Software. 13a966c04fSmrg * 14a966c04fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15a966c04fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16a966c04fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17a966c04fSmrg * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18a966c04fSmrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19a966c04fSmrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20a966c04fSmrg * 21a966c04fSmrg * Except as contained in this notice, the name of GROUPE BULL shall not be 22a966c04fSmrg * used in advertising or otherwise to promote the sale, use or other dealings 23a966c04fSmrg * in this Software without prior written authorization from GROUPE BULL. 24a966c04fSmrg */ 25a966c04fSmrg 26a966c04fSmrg/*****************************************************************************\ 27a966c04fSmrg* CrDataFI.c: * 28a966c04fSmrg* * 29a966c04fSmrg* XPM library * 30a966c04fSmrg* Scan an image and possibly its mask and create an XPM array * 31a966c04fSmrg* * 32a966c04fSmrg* Developed by Arnaud Le Hors * 33a966c04fSmrg\*****************************************************************************/ 34a966c04fSmrg 35a966c04fSmrg/* October 2004, source code review by Thomas Biege <thomas@suse.de> */ 36a966c04fSmrg 37a966c04fSmrg#ifdef HAVE_CONFIG_H 38a966c04fSmrg#include <config.h> 39a966c04fSmrg#endif 40a966c04fSmrg#include "XpmI.h" 41a966c04fSmrg 42edce3322Smrg#ifdef FOR_MSW 43edce3322Smrg#define snprintf _snprintf 44edce3322Smrg#endif 45edce3322Smrg 46a966c04fSmrgLFUNC(CreateColors, int, (char **dataptr, unsigned int *data_size, 47a966c04fSmrg XpmColor *colors, unsigned int ncolors, 48a966c04fSmrg unsigned int cpp)); 49a966c04fSmrg 50a966c04fSmrgLFUNC(CreatePixels, void, (char **dataptr, unsigned int data_size, 51a966c04fSmrg unsigned int width, 52a966c04fSmrg unsigned int height, unsigned int cpp, 53a966c04fSmrg unsigned int *pixels, XpmColor *colors)); 54a966c04fSmrg 559f00f3a1SmrgLFUNC(CountExtensions, int, (XpmExtension *ext, unsigned int num, 56a966c04fSmrg unsigned int *ext_size, 57a966c04fSmrg unsigned int *ext_nlines)); 58a966c04fSmrg 59a966c04fSmrgLFUNC(CreateExtensions, void, (char **dataptr, unsigned int data_size, 60a966c04fSmrg unsigned int offset, 61a966c04fSmrg XpmExtension *ext, unsigned int num, 62a966c04fSmrg unsigned int ext_nlines)); 63a966c04fSmrg 64a966c04fSmrgint 652e2dd055SmrgXpmCreateDataFromImage( 662e2dd055Smrg Display *display, 672e2dd055Smrg char ***data_return, 682e2dd055Smrg XImage *image, 692e2dd055Smrg XImage *shapeimage, 702e2dd055Smrg XpmAttributes *attributes) 71a966c04fSmrg{ 72a966c04fSmrg XpmImage xpmimage; 73a966c04fSmrg XpmInfo info; 74a966c04fSmrg int ErrorStatus; 75a966c04fSmrg 76a966c04fSmrg /* initialize return value */ 77a966c04fSmrg if (data_return) 78a966c04fSmrg *data_return = NULL; 79a966c04fSmrg 80a966c04fSmrg /* create an XpmImage from the image */ 81a966c04fSmrg ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage, 82a966c04fSmrg &xpmimage, attributes); 83a966c04fSmrg if (ErrorStatus != XpmSuccess) 84a966c04fSmrg return (ErrorStatus); 85a966c04fSmrg 86a966c04fSmrg /* create the data from the XpmImage */ 87a966c04fSmrg if (attributes) { 88a966c04fSmrg xpmSetInfo(&info, attributes); 89a966c04fSmrg ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, &info); 90a966c04fSmrg } else 91a966c04fSmrg ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, NULL); 92a966c04fSmrg 93a966c04fSmrg /* free the XpmImage */ 94a966c04fSmrg XpmFreeXpmImage(&xpmimage); 95a966c04fSmrg 96a966c04fSmrg return (ErrorStatus); 97a966c04fSmrg} 98a966c04fSmrg 99a966c04fSmrg#undef RETURN 100a966c04fSmrg#define RETURN(status) \ 101a966c04fSmrgdo \ 102a966c04fSmrg{ \ 103a966c04fSmrg ErrorStatus = status; \ 104a966c04fSmrg goto exit; \ 105a966c04fSmrg} while(0) 106a966c04fSmrg 107a966c04fSmrgint 1082e2dd055SmrgXpmCreateDataFromXpmImage( 1092e2dd055Smrg char ***data_return, 1102e2dd055Smrg XpmImage *image, 1112e2dd055Smrg XpmInfo *info) 112a966c04fSmrg{ 113a966c04fSmrg /* calculation variables */ 114a966c04fSmrg int ErrorStatus; 115a966c04fSmrg char buf[BUFSIZ]; 116a966c04fSmrg char **header = NULL, **data, **sptr, **sptr2, *s; 117a966c04fSmrg unsigned int header_size, header_nlines; 118a966c04fSmrg unsigned int data_size, data_nlines; 119a966c04fSmrg unsigned int extensions = 0, ext_size = 0, ext_nlines = 0; 120a966c04fSmrg unsigned int offset, l, n; 121a966c04fSmrg 122a966c04fSmrg *data_return = NULL; 123a966c04fSmrg 124a966c04fSmrg extensions = info && (info->valuemask & XpmExtensions) 125a966c04fSmrg && info->nextensions; 126a966c04fSmrg 127a966c04fSmrg /* compute the number of extensions lines and size */ 128a966c04fSmrg if (extensions) 1299f00f3a1Smrg if (CountExtensions(info->extensions, info->nextensions, 1309f00f3a1Smrg &ext_size, &ext_nlines)) 1319f00f3a1Smrg return(XpmNoMemory); 132a966c04fSmrg 133a966c04fSmrg /* 134a966c04fSmrg * alloc a temporary array of char pointer for the header section which 135a966c04fSmrg * is the hints line + the color table lines 136a966c04fSmrg */ 137a966c04fSmrg header_nlines = 1 + image->ncolors; /* this may wrap and/or become 0 */ 138a966c04fSmrg 139a966c04fSmrg /* 2nd check superfluous if we do not need header_nlines any further */ 140a966c04fSmrg if(header_nlines <= image->ncolors || 141a966c04fSmrg header_nlines >= UINT_MAX / sizeof(char *)) 142a966c04fSmrg return(XpmNoMemory); 143a966c04fSmrg 144a966c04fSmrg header_size = sizeof(char *) * header_nlines; 145a966c04fSmrg if (header_size >= UINT_MAX / sizeof(char *)) 146a966c04fSmrg return (XpmNoMemory); 147a966c04fSmrg header = (char **) XpmCalloc(header_size, sizeof(char *)); /* can we trust image->ncolors */ 148a966c04fSmrg if (!header) 149a966c04fSmrg return (XpmNoMemory); 150a966c04fSmrg 151a966c04fSmrg /* print the hints line */ 152a966c04fSmrg s = buf; 153a966c04fSmrg#ifndef VOID_SPRINTF 154a966c04fSmrg s += 155a966c04fSmrg#endif 156a966c04fSmrg sprintf(s, "%d %d %d %d", image->width, image->height, 157a966c04fSmrg image->ncolors, image->cpp); 158a966c04fSmrg#ifdef VOID_SPRINTF 159a966c04fSmrg s += strlen(s); 160a966c04fSmrg#endif 161a966c04fSmrg 162a966c04fSmrg if (info && (info->valuemask & XpmHotspot)) { 163a966c04fSmrg#ifndef VOID_SPRINTF 164a966c04fSmrg s += 165a966c04fSmrg#endif 166a966c04fSmrg sprintf(s, " %d %d", info->x_hotspot, info->y_hotspot); 167a966c04fSmrg#ifdef VOID_SPRINTF 168a966c04fSmrg s += strlen(s); 169a966c04fSmrg#endif 170a966c04fSmrg } 171a966c04fSmrg if (extensions) { 172a966c04fSmrg strcpy(s, " XPMEXT"); 173a966c04fSmrg s += 7; 174a966c04fSmrg } 175a966c04fSmrg l = s - buf + 1; 176a966c04fSmrg *header = (char *) XpmMalloc(l); 177a966c04fSmrg if (!*header) 178a966c04fSmrg RETURN(XpmNoMemory); 179a966c04fSmrg header_size += l; 180a966c04fSmrg strcpy(*header, buf); 181a966c04fSmrg 182a966c04fSmrg /* print colors */ 183a966c04fSmrg ErrorStatus = CreateColors(header + 1, &header_size, 184a966c04fSmrg image->colorTable, image->ncolors, image->cpp); 185a966c04fSmrg 186a966c04fSmrg if (ErrorStatus != XpmSuccess) 187a966c04fSmrg RETURN(ErrorStatus); 188a966c04fSmrg 189a966c04fSmrg /* now we know the size needed, alloc the data and copy the header lines */ 190a966c04fSmrg offset = image->width * image->cpp + 1; 191a966c04fSmrg 192a966c04fSmrg if(offset <= image->width || offset <= image->cpp) 193a966c04fSmrg RETURN(XpmNoMemory); 194a966c04fSmrg 1959f00f3a1Smrg if (image->height > UINT_MAX - ext_nlines || 1969f00f3a1Smrg image->height + ext_nlines >= UINT_MAX / sizeof(char *)) 197a966c04fSmrg RETURN(XpmNoMemory); 198a966c04fSmrg data_size = (image->height + ext_nlines) * sizeof(char *); 199a966c04fSmrg 200a966c04fSmrg if (image->height > UINT_MAX / offset || 201a966c04fSmrg image->height * offset > UINT_MAX - data_size) 202a966c04fSmrg RETURN(XpmNoMemory); 203a966c04fSmrg data_size += image->height * offset; 204a966c04fSmrg 2059f00f3a1Smrg if (header_size > UINT_MAX - ext_size || 2069f00f3a1Smrg header_size + ext_size >= (UINT_MAX - data_size) ) 207a966c04fSmrg RETURN(XpmNoMemory); 208a966c04fSmrg data_size += header_size + ext_size; 209a966c04fSmrg 210a966c04fSmrg data = (char **) XpmMalloc(data_size); 211a966c04fSmrg if (!data) 212a966c04fSmrg RETURN(XpmNoMemory); 213a966c04fSmrg 214a966c04fSmrg data_nlines = header_nlines + image->height + ext_nlines; 215a966c04fSmrg *data = (char *) (data + data_nlines); 216a966c04fSmrg 217a966c04fSmrg /* can header have less elements then n suggests? */ 218a966c04fSmrg n = image->ncolors; 219a966c04fSmrg for (l = 0, sptr = data, sptr2 = header; l <= n && sptr && sptr2; l++, sptr++, sptr2++) { 220a966c04fSmrg strcpy(*sptr, *sptr2); 221a966c04fSmrg *(sptr + 1) = *sptr + strlen(*sptr2) + 1; 222a966c04fSmrg } 223a966c04fSmrg 224a966c04fSmrg /* print pixels */ 225a966c04fSmrg data[header_nlines] = (char *) data + header_size 226a966c04fSmrg + (image->height + ext_nlines) * sizeof(char *); 227a966c04fSmrg 228a966c04fSmrg CreatePixels(data + header_nlines, data_size-header_nlines, image->width, image->height, 229a966c04fSmrg image->cpp, image->data, image->colorTable); 230a966c04fSmrg 231a966c04fSmrg /* print extensions */ 232a966c04fSmrg if (extensions) 233a966c04fSmrg CreateExtensions(data + header_nlines + image->height - 1, 234a966c04fSmrg data_size - header_nlines - image->height + 1, offset, 235a966c04fSmrg info->extensions, info->nextensions, 236a966c04fSmrg ext_nlines); 237a966c04fSmrg 238a966c04fSmrg *data_return = data; 239a966c04fSmrg ErrorStatus = XpmSuccess; 240a966c04fSmrg 241a966c04fSmrg/* exit point, free only locally allocated variables */ 242a966c04fSmrgexit: 243a966c04fSmrg if (header) { 24474835918Smrg for (l = 0; l < header_nlines; l++) { 245a966c04fSmrg if (header[l]) 246a966c04fSmrg XpmFree(header[l]); 24774835918Smrg } 24874835918Smrg XpmFree(header); 249a966c04fSmrg } 250a966c04fSmrg return(ErrorStatus); 251a966c04fSmrg} 252a966c04fSmrg 253a966c04fSmrgstatic int 2542e2dd055SmrgCreateColors( 2552e2dd055Smrg char **dataptr, 2562e2dd055Smrg unsigned int *data_size, 2572e2dd055Smrg XpmColor *colors, 2582e2dd055Smrg unsigned int ncolors, 2592e2dd055Smrg unsigned int cpp) 260a966c04fSmrg{ 261a966c04fSmrg char buf[BUFSIZ]; 262a966c04fSmrg unsigned int a, key, l; 263a966c04fSmrg char *s, *s2; 264a966c04fSmrg char **defaults; 265a966c04fSmrg 266a966c04fSmrg /* can ncolors be trusted here? */ 267a966c04fSmrg for (a = 0; a < ncolors; a++, colors++, dataptr++) { 268a966c04fSmrg 269a966c04fSmrg defaults = (char **) colors; 270a966c04fSmrg if(sizeof(buf) <= cpp) 271a966c04fSmrg return(XpmNoMemory); 272a966c04fSmrg strncpy(buf, *defaults++, cpp); 273a966c04fSmrg s = buf + cpp; 274a966c04fSmrg 275a966c04fSmrg if(sizeof(buf) <= (s-buf)) 276a966c04fSmrg return XpmNoMemory; 277a966c04fSmrg 278a966c04fSmrg for (key = 1; key <= NKEYS; key++, defaults++) { 279a966c04fSmrg if ((s2 = *defaults)) { 280a966c04fSmrg#ifndef VOID_SPRINTF 281a966c04fSmrg s += 282a966c04fSmrg#endif 283a966c04fSmrg /* assume C99 compliance */ 284a966c04fSmrg snprintf(s, sizeof(buf)-(s-buf), "\t%s %s", xpmColorKeys[key - 1], s2); 285a966c04fSmrg#ifdef VOID_SPRINTF 286a966c04fSmrg s += strlen(s); 287a966c04fSmrg#endif 288a966c04fSmrg /* does s point out-of-bounds? */ 289a966c04fSmrg if(sizeof(buf) < (s-buf)) 290a966c04fSmrg return XpmNoMemory; 291a966c04fSmrg } 292a966c04fSmrg } 293a966c04fSmrg /* what about using strdup()? */ 294a966c04fSmrg l = s - buf + 1; 295a966c04fSmrg s = (char *) XpmMalloc(l); 296a966c04fSmrg if (!s) 297a966c04fSmrg return (XpmNoMemory); 298a966c04fSmrg *data_size += l; 299a966c04fSmrg *dataptr = strcpy(s, buf); 300a966c04fSmrg } 301a966c04fSmrg return (XpmSuccess); 302a966c04fSmrg} 303a966c04fSmrg 304a966c04fSmrgstatic void 3052e2dd055SmrgCreatePixels( 3062e2dd055Smrg char **dataptr, 3072e2dd055Smrg unsigned int data_size, 3082e2dd055Smrg unsigned int width, 3092e2dd055Smrg unsigned int height, 3102e2dd055Smrg unsigned int cpp, 3112e2dd055Smrg unsigned int *pixels, 3122e2dd055Smrg XpmColor *colors) 313a966c04fSmrg{ 314a966c04fSmrg char *s; 315a966c04fSmrg unsigned int x, y, h, offset; 316a966c04fSmrg 317a966c04fSmrg if(height <= 1) 318a966c04fSmrg return; 319a966c04fSmrg 320a966c04fSmrg h = height - 1; 321a966c04fSmrg 322a966c04fSmrg offset = width * cpp + 1; 323a966c04fSmrg 324a966c04fSmrg if(offset <= width || offset <= cpp) 325a966c04fSmrg return; 326a966c04fSmrg 327a966c04fSmrg /* why trust h? */ 328a966c04fSmrg for (y = 0; y < h; y++, dataptr++) { 329a966c04fSmrg s = *dataptr; 330a966c04fSmrg /* why trust width? */ 331a966c04fSmrg for (x = 0; x < width; x++, pixels++) { 332a966c04fSmrg if(cpp > (data_size - (s - *dataptr))) 333a966c04fSmrg return; 334a966c04fSmrg strncpy(s, colors[*pixels].string, cpp); /* why trust pixel? */ 335a966c04fSmrg s += cpp; 336a966c04fSmrg } 337a966c04fSmrg *s = '\0'; 338a966c04fSmrg if(offset > data_size) 339a966c04fSmrg return; 340a966c04fSmrg *(dataptr + 1) = *dataptr + offset; 341a966c04fSmrg } 342a966c04fSmrg /* duplicate some code to avoid a test in the loop */ 343a966c04fSmrg s = *dataptr; 344a966c04fSmrg /* why trust width? */ 345a966c04fSmrg for (x = 0; x < width; x++, pixels++) { 346a966c04fSmrg if(cpp > data_size - (s - *dataptr)) 347a966c04fSmrg return; 348a966c04fSmrg strncpy(s, colors[*pixels].string, cpp); /* why should we trust *pixel? */ 349a966c04fSmrg s += cpp; 350a966c04fSmrg } 351a966c04fSmrg *s = '\0'; 352a966c04fSmrg} 353a966c04fSmrg 3549f00f3a1Smrgstatic int 3552e2dd055SmrgCountExtensions( 3562e2dd055Smrg XpmExtension *ext, 3572e2dd055Smrg unsigned int num, 3582e2dd055Smrg unsigned int *ext_size, 3592e2dd055Smrg unsigned int *ext_nlines) 360a966c04fSmrg{ 3619f00f3a1Smrg size_t len; 362a966c04fSmrg unsigned int x, y, a, size, nlines; 363a966c04fSmrg char **line; 364a966c04fSmrg 365a966c04fSmrg size = 0; 366a966c04fSmrg nlines = 0; 367a966c04fSmrg for (x = 0; x < num; x++, ext++) { 368a966c04fSmrg /* 1 for the name */ 3699f00f3a1Smrg if (ext->nlines == UINT_MAX || nlines > UINT_MAX - ext->nlines - 1) 3709f00f3a1Smrg return (1); 371a966c04fSmrg nlines += ext->nlines + 1; 372a966c04fSmrg /* 8 = 7 (for "XPMEXT ") + 1 (for 0) */ 3739f00f3a1Smrg len = strlen(ext->name) + 8; 3749f00f3a1Smrg if (len > UINT_MAX - size) 3759f00f3a1Smrg return (1); 3769f00f3a1Smrg size += len; 377a966c04fSmrg a = ext->nlines; 3789f00f3a1Smrg for (y = 0, line = ext->lines; y < a; y++, line++) { 3799f00f3a1Smrg len = strlen(*line) + 1; 3809f00f3a1Smrg if (len > UINT_MAX - size) 3819f00f3a1Smrg return (1); 3829f00f3a1Smrg size += len; 3839f00f3a1Smrg } 384a966c04fSmrg } 3859f00f3a1Smrg if (size > UINT_MAX - 10 || nlines > UINT_MAX - 1) 3869f00f3a1Smrg return (1); 387a966c04fSmrg /* 10 and 1 are for the ending "XPMENDEXT" */ 388a966c04fSmrg *ext_size = size + 10; 389a966c04fSmrg *ext_nlines = nlines + 1; 3909f00f3a1Smrg return (0); 391a966c04fSmrg} 392a966c04fSmrg 393a966c04fSmrgstatic void 3942e2dd055SmrgCreateExtensions( 3952e2dd055Smrg char **dataptr, 3962e2dd055Smrg unsigned int data_size, 3972e2dd055Smrg unsigned int offset, 3982e2dd055Smrg XpmExtension *ext, 3992e2dd055Smrg unsigned int num, 4002e2dd055Smrg unsigned int ext_nlines) 401a966c04fSmrg{ 402a966c04fSmrg unsigned int x, y, a, b; 403a966c04fSmrg char **line; 404a966c04fSmrg 405a966c04fSmrg *(dataptr + 1) = *dataptr + offset; 406a966c04fSmrg dataptr++; 407a966c04fSmrg a = 0; 408a966c04fSmrg for (x = 0; x < num; x++, ext++) { 409a966c04fSmrg snprintf(*dataptr, data_size, "XPMEXT %s", ext->name); 410a966c04fSmrg a++; 411a966c04fSmrg if (a < ext_nlines) 412a966c04fSmrg *(dataptr + 1) = *dataptr + strlen(ext->name) + 8; 413a966c04fSmrg dataptr++; 414a966c04fSmrg b = ext->nlines; /* can we trust these values? */ 415a966c04fSmrg for (y = 0, line = ext->lines; y < b; y++, line++) { 416a966c04fSmrg strcpy(*dataptr, *line); 417a966c04fSmrg a++; 418a966c04fSmrg if (a < ext_nlines) 419a966c04fSmrg *(dataptr + 1) = *dataptr + strlen(*line) + 1; 420a966c04fSmrg dataptr++; 421a966c04fSmrg } 422a966c04fSmrg } 423a966c04fSmrg strcpy(*dataptr, "XPMENDEXT"); 424a966c04fSmrg} 425