PageRenderTime 52ms CodeModel.GetById 2ms app.highlight 45ms RepoModel.GetById 1ms app.codeStats 0ms

/src/CrBufFrI.c

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