PageRenderTime 40ms CodeModel.GetById 18ms app.highlight 18ms RepoModel.GetById 1ms app.codeStats 0ms

/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}