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* CrBufFrI.c: * 28a966c04fSmrg* * 29a966c04fSmrg* XPM library * 30a966c04fSmrg* Scan an image and possibly its mask and create an XPM buffer * 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(WriteColors, int, (char **dataptr, unsigned int *data_size, 47a966c04fSmrg unsigned int *used_size, XpmColor *colors, 48a966c04fSmrg unsigned int ncolors, unsigned int cpp)); 49a966c04fSmrg 50a966c04fSmrgLFUNC(WritePixels, void, (char *dataptr, unsigned int data_size, 51a966c04fSmrg unsigned int *used_size, 52a966c04fSmrg unsigned int width, unsigned int height, 53a966c04fSmrg unsigned int cpp, unsigned int *pixels, 54a966c04fSmrg XpmColor *colors)); 55a966c04fSmrg 56a966c04fSmrgLFUNC(WriteExtensions, void, (char *dataptr, unsigned int data_size, 57a966c04fSmrg unsigned int *used_size, 58a966c04fSmrg XpmExtension *ext, unsigned int num)); 59a966c04fSmrg 60a966c04fSmrgLFUNC(ExtensionsSize, unsigned int, (XpmExtension *ext, unsigned int num)); 61a966c04fSmrgLFUNC(CommentsSize, int, (XpmInfo *info)); 62a966c04fSmrg 63a966c04fSmrgint 642e2dd055SmrgXpmCreateBufferFromImage( 652e2dd055Smrg Display *display, 662e2dd055Smrg char **buffer_return, 672e2dd055Smrg XImage *image, 682e2dd055Smrg XImage *shapeimage, 692e2dd055Smrg XpmAttributes *attributes) 70a966c04fSmrg{ 71a966c04fSmrg XpmImage xpmimage; 72a966c04fSmrg XpmInfo info; 73a966c04fSmrg int ErrorStatus; 74a966c04fSmrg 75a966c04fSmrg /* initialize return value */ 76a966c04fSmrg if (buffer_return) 77a966c04fSmrg *buffer_return = NULL; 78a966c04fSmrg 79a966c04fSmrg /* create an XpmImage from the image */ 80a966c04fSmrg ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage, 81a966c04fSmrg &xpmimage, attributes); 82a966c04fSmrg if (ErrorStatus != XpmSuccess) 83a966c04fSmrg return (ErrorStatus); 84a966c04fSmrg 85a966c04fSmrg /* create the buffer from the XpmImage */ 86a966c04fSmrg if (attributes) { 87a966c04fSmrg xpmSetInfo(&info, attributes); 88a966c04fSmrg ErrorStatus = 89a966c04fSmrg XpmCreateBufferFromXpmImage(buffer_return, &xpmimage, &info); 90a966c04fSmrg } else 91a966c04fSmrg ErrorStatus = 92a966c04fSmrg XpmCreateBufferFromXpmImage(buffer_return, &xpmimage, NULL); 93a966c04fSmrg 94a966c04fSmrg /* free the XpmImage */ 95a966c04fSmrg XpmFreeXpmImage(&xpmimage); 96a966c04fSmrg 97a966c04fSmrg return (ErrorStatus); 98a966c04fSmrg} 99a966c04fSmrg 100a966c04fSmrg 101a966c04fSmrg#undef RETURN 102a966c04fSmrg#define RETURN(status) \ 103a966c04fSmrgdo \ 104a966c04fSmrg{ \ 105a966c04fSmrg ErrorStatus = status; \ 106a966c04fSmrg goto error; \ 107a966c04fSmrg}while(0) 108a966c04fSmrg 109a966c04fSmrgint 1102e2dd055SmrgXpmCreateBufferFromXpmImage( 1112e2dd055Smrg char **buffer_return, 1122e2dd055Smrg XpmImage *image, 1132e2dd055Smrg XpmInfo *info) 114a966c04fSmrg{ 115a966c04fSmrg /* calculation variables */ 116a966c04fSmrg int ErrorStatus; 117a966c04fSmrg char buf[BUFSIZ]; 118a966c04fSmrg unsigned int cmts, extensions, ext_size = 0; 119a966c04fSmrg unsigned int l, cmt_size = 0; 120a966c04fSmrg char *ptr = NULL, *p; 121a966c04fSmrg unsigned int ptr_size, used_size, tmp; 122a966c04fSmrg 123a966c04fSmrg *buffer_return = NULL; 124a966c04fSmrg 125a966c04fSmrg cmts = info && (info->valuemask & XpmComments); 126a966c04fSmrg extensions = info && (info->valuemask & XpmExtensions) 127a966c04fSmrg && info->nextensions; 128a966c04fSmrg 129a966c04fSmrg /* compute the extensions and comments size */ 130a966c04fSmrg if (extensions) 131a966c04fSmrg ext_size = ExtensionsSize(info->extensions, info->nextensions); 132a966c04fSmrg if (cmts) 133a966c04fSmrg cmt_size = CommentsSize(info); 134a966c04fSmrg 135a966c04fSmrg /* write the header line */ 136a966c04fSmrg#ifndef VOID_SPRINTF 137a966c04fSmrg used_size = 138a966c04fSmrg#endif 139a966c04fSmrg sprintf(buf, "/* XPM */\nstatic char * image_name[] = {\n"); 140a966c04fSmrg#ifdef VOID_SPRINTF 141a966c04fSmrg used_size = strlen(buf); 142a966c04fSmrg#endif 143a966c04fSmrg ptr_size = used_size + ext_size + cmt_size + 1; /* ptr_size can't be 0 */ 144a966c04fSmrg if(ptr_size <= used_size || 145a966c04fSmrg ptr_size <= ext_size || 146a966c04fSmrg ptr_size <= cmt_size) 147a966c04fSmrg { 148a966c04fSmrg return XpmNoMemory; 149a966c04fSmrg } 150a966c04fSmrg ptr = (char *) XpmMalloc(ptr_size); 151a966c04fSmrg if (!ptr) 152a966c04fSmrg return XpmNoMemory; 153a966c04fSmrg strcpy(ptr, buf); 154a966c04fSmrg 155a966c04fSmrg /* write the values line */ 156a966c04fSmrg if (cmts && info->hints_cmt) { 157a966c04fSmrg#ifndef VOID_SPRINTF 158a966c04fSmrg used_size += 159a966c04fSmrg#endif 160a966c04fSmrg snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->hints_cmt); 161a966c04fSmrg#ifdef VOID_SPRINTF 162a966c04fSmrg used_size += strlen(info->hints_cmt) + 5; 163a966c04fSmrg#endif 164a966c04fSmrg } 165a966c04fSmrg#ifndef VOID_SPRINTF 166a966c04fSmrg l = 167a966c04fSmrg#endif 168a966c04fSmrg sprintf(buf, "\"%d %d %d %d", image->width, image->height, 169a966c04fSmrg image->ncolors, image->cpp); 170a966c04fSmrg#ifdef VOID_SPRINTF 171a966c04fSmrg l = strlen(buf); 172a966c04fSmrg#endif 173a966c04fSmrg 174a966c04fSmrg if (info && (info->valuemask & XpmHotspot)) { 175a966c04fSmrg#ifndef VOID_SPRINTF 176a966c04fSmrg l += 177a966c04fSmrg#endif 178a966c04fSmrg snprintf(buf + l, sizeof(buf)-l, " %d %d", info->x_hotspot, info->y_hotspot); 179a966c04fSmrg#ifdef VOID_SPRINTF 180a966c04fSmrg l = strlen(buf); 181a966c04fSmrg#endif 182a966c04fSmrg } 183a966c04fSmrg if (extensions) { 184a966c04fSmrg#ifndef VOID_SPRINTF 185a966c04fSmrg l += 186a966c04fSmrg#endif 187a966c04fSmrg sprintf(buf + l, " XPMEXT"); 188a966c04fSmrg#ifdef VOID_SPRINTF 189a966c04fSmrg l = strlen(buf); 190a966c04fSmrg#endif 191a966c04fSmrg } 192a966c04fSmrg#ifndef VOID_SPRINTF 193a966c04fSmrg l += 194a966c04fSmrg#endif 195a966c04fSmrg sprintf(buf + l, "\",\n"); 196a966c04fSmrg#ifdef VOID_SPRINTF 197a966c04fSmrg l = strlen(buf); 198a966c04fSmrg#endif 199a966c04fSmrg ptr_size += l; 200a966c04fSmrg if(ptr_size <= l) 201a966c04fSmrg RETURN(XpmNoMemory); 202a966c04fSmrg p = (char *) XpmRealloc(ptr, ptr_size); 203a966c04fSmrg if (!p) 204a966c04fSmrg RETURN(XpmNoMemory); 205a966c04fSmrg ptr = p; 206a966c04fSmrg strcpy(ptr + used_size, buf); 207a966c04fSmrg used_size += l; 208a966c04fSmrg 209a966c04fSmrg /* write colors */ 210a966c04fSmrg if (cmts && info->colors_cmt) { 211a966c04fSmrg#ifndef VOID_SPRINTF 212a966c04fSmrg used_size += 213a966c04fSmrg#endif 214a966c04fSmrg snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->colors_cmt); 215a966c04fSmrg#ifdef VOID_SPRINTF 216a966c04fSmrg used_size += strlen(info->colors_cmt) + 5; 217a966c04fSmrg#endif 218a966c04fSmrg } 219a966c04fSmrg ErrorStatus = WriteColors(&ptr, &ptr_size, &used_size, 220a966c04fSmrg image->colorTable, image->ncolors, image->cpp); 22197cf2ee2Smrg 222a966c04fSmrg if (ErrorStatus != XpmSuccess) 223a966c04fSmrg RETURN(ErrorStatus); 224a966c04fSmrg 225a966c04fSmrg /* 226a966c04fSmrg * now we know the exact size we need, realloc the data 227a966c04fSmrg * 4 = 1 (for '"') + 3 (for '",\n') 228a966c04fSmrg * 1 = - 2 (because the last line does not end with ',\n') + 3 (for '};\n') 229a966c04fSmrg */ 230a966c04fSmrg if(image->width > UINT_MAX / image->cpp || 231a966c04fSmrg (tmp = image->width * image->cpp + 4) <= 4 || 232a966c04fSmrg image->height > UINT_MAX / tmp || 233a966c04fSmrg (tmp = image->height * tmp + 1) <= 1 || 234a966c04fSmrg (ptr_size += tmp) <= tmp) 235a966c04fSmrg RETURN(XpmNoMemory); 236a966c04fSmrg 237a966c04fSmrg p = (char *) XpmRealloc(ptr, ptr_size); 238a966c04fSmrg if (!p) 239a966c04fSmrg RETURN(XpmNoMemory); 240a966c04fSmrg ptr = p; 241a966c04fSmrg 242a966c04fSmrg /* print pixels */ 243a966c04fSmrg if (cmts && info->pixels_cmt) { 244a966c04fSmrg#ifndef VOID_SPRINTF 245a966c04fSmrg used_size += 246a966c04fSmrg#endif 247a966c04fSmrg snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->pixels_cmt); 248a966c04fSmrg#ifdef VOID_SPRINTF 249a966c04fSmrg used_size += strlen(info->pixels_cmt) + 5; 250a966c04fSmrg#endif 251a966c04fSmrg } 252a966c04fSmrg WritePixels(ptr + used_size, ptr_size - used_size, &used_size, image->width, image->height, 253a966c04fSmrg image->cpp, image->data, image->colorTable); 254a966c04fSmrg 255a966c04fSmrg /* print extensions */ 256a966c04fSmrg if (extensions) 257a966c04fSmrg WriteExtensions(ptr + used_size, ptr_size-used_size, &used_size, 258a966c04fSmrg info->extensions, info->nextensions); 259a966c04fSmrg 260a966c04fSmrg /* close the array */ 261a966c04fSmrg strcpy(ptr + used_size, "};\n"); 262a966c04fSmrg 263a966c04fSmrg *buffer_return = ptr; 264a966c04fSmrg 265a966c04fSmrg return (XpmSuccess); 266a966c04fSmrg 267a966c04fSmrg/* exit point in case of error, free only locally allocated variables */ 268a966c04fSmrgerror: 269a966c04fSmrg if (ptr) 270a966c04fSmrg XpmFree(ptr); 271a966c04fSmrg return (ErrorStatus); 272a966c04fSmrg} 273a966c04fSmrg 274a966c04fSmrg 275a966c04fSmrgstatic int 2762e2dd055SmrgWriteColors( 2772e2dd055Smrg char **dataptr, 2782e2dd055Smrg unsigned int *data_size, 2792e2dd055Smrg unsigned int *used_size, 2802e2dd055Smrg XpmColor *colors, 2812e2dd055Smrg unsigned int ncolors, 2822e2dd055Smrg unsigned int cpp) 283a966c04fSmrg{ 284a966c04fSmrg char buf[BUFSIZ] = {0}; 285a966c04fSmrg unsigned int a, key, l; 286a966c04fSmrg char *s, *s2; 287a966c04fSmrg char **defaults; 288a966c04fSmrg 289a966c04fSmrg *buf = '"'; 290a966c04fSmrg for (a = 0; a < ncolors; a++, colors++) { 291a966c04fSmrg 292a966c04fSmrg defaults = (char **) colors; 293a966c04fSmrg s = buf + 1; 294a966c04fSmrg if(cpp > (sizeof(buf) - (s-buf))) 295a966c04fSmrg return(XpmNoMemory); 296a966c04fSmrg strncpy(s, *defaults++, cpp); 297a966c04fSmrg s += cpp; 298a966c04fSmrg 299a966c04fSmrg for (key = 1; key <= NKEYS; key++, defaults++) { 300a966c04fSmrg if ((s2 = *defaults)) { 301a966c04fSmrg#ifndef VOID_SPRINTF 302a966c04fSmrg s += 303a966c04fSmrg#endif 304a966c04fSmrg /* assume C99 compliance */ 305a966c04fSmrg snprintf(s, sizeof(buf) - (s-buf), "\t%s %s", xpmColorKeys[key - 1], s2); 306a966c04fSmrg#ifdef VOID_SPRINTF 307a966c04fSmrg s += strlen(s); 308a966c04fSmrg#endif 309a966c04fSmrg /* now let's check if s points out-of-bounds */ 310a966c04fSmrg if((s-buf) > sizeof(buf)) 311a966c04fSmrg return(XpmNoMemory); 312a966c04fSmrg } 313a966c04fSmrg } 314a966c04fSmrg if(sizeof(buf) - (s-buf) < 4) 315a966c04fSmrg return(XpmNoMemory); 316a966c04fSmrg strcpy(s, "\",\n"); 317a966c04fSmrg l = s + 3 - buf; 318a966c04fSmrg if( *data_size >= UINT_MAX-l || 319a966c04fSmrg *data_size + l <= *used_size || 320a966c04fSmrg (*data_size + l - *used_size) <= sizeof(buf)) 321a966c04fSmrg return(XpmNoMemory); 322a966c04fSmrg s = (char *) XpmRealloc(*dataptr, *data_size + l); 323a966c04fSmrg if (!s) 324a966c04fSmrg return (XpmNoMemory); 325a966c04fSmrg *data_size += l; 326a966c04fSmrg strcpy(s + *used_size, buf); 327a966c04fSmrg *used_size += l; 328a966c04fSmrg *dataptr = s; 329a966c04fSmrg } 330a966c04fSmrg return (XpmSuccess); 331a966c04fSmrg} 332a966c04fSmrg 333a966c04fSmrgstatic void 3342e2dd055SmrgWritePixels( 3352e2dd055Smrg char *dataptr, 3362e2dd055Smrg unsigned int data_size, 3372e2dd055Smrg unsigned int *used_size, 3382e2dd055Smrg unsigned int width, 3392e2dd055Smrg unsigned int height, 3402e2dd055Smrg unsigned int cpp, 3412e2dd055Smrg unsigned int *pixels, 3422e2dd055Smrg XpmColor *colors) 343a966c04fSmrg{ 344a966c04fSmrg char *s = dataptr; 345a966c04fSmrg unsigned int x, y, h; 346a966c04fSmrg 347a966c04fSmrg if(height <= 1) 348a966c04fSmrg return; 349a966c04fSmrg 350a966c04fSmrg h = height - 1; 351a966c04fSmrg for (y = 0; y < h; y++) { 352a966c04fSmrg *s++ = '"'; 353a966c04fSmrg for (x = 0; x < width; x++, pixels++) { 354a966c04fSmrg if(cpp >= (data_size - (s-dataptr))) 355a966c04fSmrg return; 356a966c04fSmrg strncpy(s, colors[*pixels].string, cpp); /* how can we trust *pixels? :-\ */ 357a966c04fSmrg s += cpp; 358a966c04fSmrg } 359a966c04fSmrg if((data_size - (s-dataptr)) < 4) 360a966c04fSmrg return; 361a966c04fSmrg strcpy(s, "\",\n"); 362a966c04fSmrg s += 3; 363a966c04fSmrg } 364a966c04fSmrg /* duplicate some code to avoid a test in the loop */ 365a966c04fSmrg *s++ = '"'; 366a966c04fSmrg for (x = 0; x < width; x++, pixels++) { 367a966c04fSmrg if(cpp >= (data_size - (s-dataptr))) 368a966c04fSmrg return; 369a966c04fSmrg strncpy(s, colors[*pixels].string, cpp); /* how can we trust *pixels? */ 370a966c04fSmrg s += cpp; 371a966c04fSmrg } 372a966c04fSmrg *s++ = '"'; 373a966c04fSmrg *used_size += s - dataptr; 374a966c04fSmrg} 375a966c04fSmrg 376a966c04fSmrgstatic unsigned int 3772e2dd055SmrgExtensionsSize( 3782e2dd055Smrg XpmExtension *ext, 3792e2dd055Smrg unsigned int num) 380a966c04fSmrg{ 381a966c04fSmrg unsigned int x, y, a, size; 382a966c04fSmrg char **line; 383a966c04fSmrg 384a966c04fSmrg size = 0; 385a966c04fSmrg if(num == 0) 386a966c04fSmrg return(0); /* ok? */ 387a966c04fSmrg for (x = 0; x < num; x++, ext++) { 388a966c04fSmrg /* 11 = 10 (for ',\n"XPMEXT ') + 1 (for '"') */ 389a966c04fSmrg size += strlen(ext->name) + 11; 390a966c04fSmrg a = ext->nlines; /* how can we trust ext->nlines to be not out-of-bounds? */ 391a966c04fSmrg for (y = 0, line = ext->lines; y < a; y++, line++) 392a966c04fSmrg /* 4 = 3 (for ',\n"') + 1 (for '"') */ 393a966c04fSmrg size += strlen(*line) + 4; 394a966c04fSmrg } 395a966c04fSmrg /* 13 is for ',\n"XPMENDEXT"' */ 396a966c04fSmrg if(size > UINT_MAX - 13) /* unlikely */ 397a966c04fSmrg return(0); 398a966c04fSmrg return size + 13; 399a966c04fSmrg} 400a966c04fSmrg 401a966c04fSmrgstatic void 4022e2dd055SmrgWriteExtensions( 4032e2dd055Smrg char *dataptr, 4042e2dd055Smrg unsigned int data_size, 4052e2dd055Smrg unsigned int *used_size, 4062e2dd055Smrg XpmExtension *ext, 4072e2dd055Smrg unsigned int num) 408a966c04fSmrg{ 409a966c04fSmrg unsigned int x, y, a; 410a966c04fSmrg char **line; 411a966c04fSmrg char *s = dataptr; 412a966c04fSmrg 413a966c04fSmrg for (x = 0; x < num; x++, ext++) { 414a966c04fSmrg#ifndef VOID_SPRINTF 415a966c04fSmrg s += 416a966c04fSmrg#endif 417a966c04fSmrg snprintf(s, data_size - (s-dataptr), ",\n\"XPMEXT %s\"", ext->name); 418a966c04fSmrg#ifdef VOID_SPRINTF 419a966c04fSmrg s += strlen(ext->name) + 11; 420a966c04fSmrg#endif 421a966c04fSmrg a = ext->nlines; 422a966c04fSmrg for (y = 0, line = ext->lines; y < a; y++, line++) { 423a966c04fSmrg#ifndef VOID_SPRINTF 424a966c04fSmrg s += 425a966c04fSmrg#endif 426a966c04fSmrg snprintf(s, data_size - (s-dataptr), ",\n\"%s\"", *line); 427a966c04fSmrg#ifdef VOID_SPRINTF 428a966c04fSmrg s += strlen(*line) + 4; 429a966c04fSmrg#endif 430a966c04fSmrg } 431a966c04fSmrg } 432a966c04fSmrg strncpy(s, ",\n\"XPMENDEXT\"", data_size - (s-dataptr)-1); 433a966c04fSmrg *used_size += s - dataptr + 13; 434a966c04fSmrg} 435a966c04fSmrg 436a966c04fSmrgstatic int 4372e2dd055SmrgCommentsSize(XpmInfo *info) 438a966c04fSmrg{ 439a966c04fSmrg int size = 0; 440a966c04fSmrg 441a966c04fSmrg /* 5 = 2 (for "/_*") + 3 (for "*_/\n") */ 442a966c04fSmrg /* wrap possible but *very* unlikely */ 443a966c04fSmrg if (info->hints_cmt) 444a966c04fSmrg size += 5 + strlen(info->hints_cmt); 445a966c04fSmrg 446a966c04fSmrg if (info->colors_cmt) 447a966c04fSmrg size += 5 + strlen(info->colors_cmt); 448a966c04fSmrg 449a966c04fSmrg if (info->pixels_cmt) 450a966c04fSmrg size += 5 + strlen(info->pixels_cmt); 451a966c04fSmrg 452a966c04fSmrg return size; 453a966c04fSmrg} 454