CrDatFrI.c revision 9f00f3a1
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
42a966c04fSmrgLFUNC(CreateColors, int, (char **dataptr, unsigned int *data_size,
43a966c04fSmrg			  XpmColor *colors, unsigned int ncolors,
44a966c04fSmrg			  unsigned int cpp));
45a966c04fSmrg
46a966c04fSmrgLFUNC(CreatePixels, void, (char **dataptr, unsigned int data_size,
47a966c04fSmrg			   unsigned int width,
48a966c04fSmrg			   unsigned int height, unsigned int cpp,
49a966c04fSmrg			   unsigned int *pixels, XpmColor *colors));
50a966c04fSmrg
519f00f3a1SmrgLFUNC(CountExtensions, int, (XpmExtension *ext, unsigned int num,
52a966c04fSmrg			      unsigned int *ext_size,
53a966c04fSmrg			      unsigned int *ext_nlines));
54a966c04fSmrg
55a966c04fSmrgLFUNC(CreateExtensions, void, (char **dataptr, unsigned int data_size,
56a966c04fSmrg			       unsigned int offset,
57a966c04fSmrg			       XpmExtension *ext, unsigned int num,
58a966c04fSmrg			       unsigned int ext_nlines));
59a966c04fSmrg
60a966c04fSmrgint
612e2dd055SmrgXpmCreateDataFromImage(
622e2dd055Smrg    Display		  *display,
632e2dd055Smrg    char		***data_return,
642e2dd055Smrg    XImage		  *image,
652e2dd055Smrg    XImage		  *shapeimage,
662e2dd055Smrg    XpmAttributes	  *attributes)
67a966c04fSmrg{
68a966c04fSmrg    XpmImage xpmimage;
69a966c04fSmrg    XpmInfo info;
70a966c04fSmrg    int ErrorStatus;
71a966c04fSmrg
72a966c04fSmrg    /* initialize return value */
73a966c04fSmrg    if (data_return)
74a966c04fSmrg	*data_return = NULL;
75a966c04fSmrg
76a966c04fSmrg    /* create an XpmImage from the image */
77a966c04fSmrg    ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage,
78a966c04fSmrg					     &xpmimage, attributes);
79a966c04fSmrg    if (ErrorStatus != XpmSuccess)
80a966c04fSmrg	return (ErrorStatus);
81a966c04fSmrg
82a966c04fSmrg    /* create the data from the XpmImage */
83a966c04fSmrg    if (attributes) {
84a966c04fSmrg	xpmSetInfo(&info, attributes);
85a966c04fSmrg	ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, &info);
86a966c04fSmrg    } else
87a966c04fSmrg	ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, NULL);
88a966c04fSmrg
89a966c04fSmrg    /* free the XpmImage */
90a966c04fSmrg    XpmFreeXpmImage(&xpmimage);
91a966c04fSmrg
92a966c04fSmrg    return (ErrorStatus);
93a966c04fSmrg}
94a966c04fSmrg
95a966c04fSmrg#undef RETURN
96a966c04fSmrg#define RETURN(status) \
97a966c04fSmrgdo \
98a966c04fSmrg{ \
99a966c04fSmrg      ErrorStatus = status; \
100a966c04fSmrg      goto exit; \
101a966c04fSmrg} while(0)
102a966c04fSmrg
103a966c04fSmrgint
1042e2dd055SmrgXpmCreateDataFromXpmImage(
1052e2dd055Smrg    char	***data_return,
1062e2dd055Smrg    XpmImage	  *image,
1072e2dd055Smrg    XpmInfo	  *info)
108a966c04fSmrg{
109a966c04fSmrg    /* calculation variables */
110a966c04fSmrg    int ErrorStatus;
111a966c04fSmrg    char buf[BUFSIZ];
112a966c04fSmrg    char **header = NULL, **data, **sptr, **sptr2, *s;
113a966c04fSmrg    unsigned int header_size, header_nlines;
114a966c04fSmrg    unsigned int data_size, data_nlines;
115a966c04fSmrg    unsigned int extensions = 0, ext_size = 0, ext_nlines = 0;
116a966c04fSmrg    unsigned int offset, l, n;
117a966c04fSmrg
118a966c04fSmrg    *data_return = NULL;
119a966c04fSmrg
120a966c04fSmrg    extensions = info && (info->valuemask & XpmExtensions)
121a966c04fSmrg	&& info->nextensions;
122a966c04fSmrg
123a966c04fSmrg    /* compute the number of extensions lines and size */
124a966c04fSmrg    if (extensions)
1259f00f3a1Smrg	if (CountExtensions(info->extensions, info->nextensions,
1269f00f3a1Smrg			&ext_size, &ext_nlines))
1279f00f3a1Smrg	    return(XpmNoMemory);
128a966c04fSmrg
129a966c04fSmrg    /*
130a966c04fSmrg     * alloc a temporary array of char pointer for the header section which
131a966c04fSmrg     * is the hints line + the color table lines
132a966c04fSmrg     */
133a966c04fSmrg    header_nlines = 1 + image->ncolors; /* this may wrap and/or become 0 */
134a966c04fSmrg
135a966c04fSmrg    /* 2nd check superfluous if we do not need header_nlines any further */
136a966c04fSmrg    if(header_nlines <= image->ncolors ||
137a966c04fSmrg       header_nlines >= UINT_MAX / sizeof(char *))
138a966c04fSmrg    	return(XpmNoMemory);
139a966c04fSmrg
140a966c04fSmrg    header_size = sizeof(char *) * header_nlines;
141a966c04fSmrg    if (header_size >= UINT_MAX / sizeof(char *))
142a966c04fSmrg	return (XpmNoMemory);
143a966c04fSmrg    header = (char **) XpmCalloc(header_size, sizeof(char *)); /* can we trust image->ncolors */
144a966c04fSmrg    if (!header)
145a966c04fSmrg	return (XpmNoMemory);
146a966c04fSmrg
147a966c04fSmrg    /* print the hints line */
148a966c04fSmrg    s = buf;
149a966c04fSmrg#ifndef VOID_SPRINTF
150a966c04fSmrg    s +=
151a966c04fSmrg#endif
152a966c04fSmrg    sprintf(s, "%d %d %d %d", image->width, image->height,
153a966c04fSmrg	    image->ncolors, image->cpp);
154a966c04fSmrg#ifdef VOID_SPRINTF
155a966c04fSmrg    s += strlen(s);
156a966c04fSmrg#endif
157a966c04fSmrg
158a966c04fSmrg    if (info && (info->valuemask & XpmHotspot)) {
159a966c04fSmrg#ifndef VOID_SPRINTF
160a966c04fSmrg	s +=
161a966c04fSmrg#endif
162a966c04fSmrg	sprintf(s, " %d %d", info->x_hotspot, info->y_hotspot);
163a966c04fSmrg#ifdef VOID_SPRINTF
164a966c04fSmrg	s += strlen(s);
165a966c04fSmrg#endif
166a966c04fSmrg    }
167a966c04fSmrg    if (extensions) {
168a966c04fSmrg	strcpy(s, " XPMEXT");
169a966c04fSmrg	s += 7;
170a966c04fSmrg    }
171a966c04fSmrg    l = s - buf + 1;
172a966c04fSmrg    *header = (char *) XpmMalloc(l);
173a966c04fSmrg    if (!*header)
174a966c04fSmrg	RETURN(XpmNoMemory);
175a966c04fSmrg    header_size += l;
176a966c04fSmrg    strcpy(*header, buf);
177a966c04fSmrg
178a966c04fSmrg    /* print colors */
179a966c04fSmrg    ErrorStatus = CreateColors(header + 1, &header_size,
180a966c04fSmrg			       image->colorTable, image->ncolors, image->cpp);
181a966c04fSmrg
182a966c04fSmrg    if (ErrorStatus != XpmSuccess)
183a966c04fSmrg	RETURN(ErrorStatus);
184a966c04fSmrg
185a966c04fSmrg    /* now we know the size needed, alloc the data and copy the header lines */
186a966c04fSmrg    offset = image->width * image->cpp + 1;
187a966c04fSmrg
188a966c04fSmrg    if(offset <= image->width || offset <= image->cpp)
189a966c04fSmrg	RETURN(XpmNoMemory);
190a966c04fSmrg
1919f00f3a1Smrg    if (image->height > UINT_MAX - ext_nlines ||
1929f00f3a1Smrg	image->height + ext_nlines >= UINT_MAX / sizeof(char *))
193a966c04fSmrg	RETURN(XpmNoMemory);
194a966c04fSmrg    data_size = (image->height + ext_nlines) * sizeof(char *);
195a966c04fSmrg
196a966c04fSmrg    if (image->height > UINT_MAX / offset ||
197a966c04fSmrg        image->height * offset > UINT_MAX - data_size)
198a966c04fSmrg	RETURN(XpmNoMemory);
199a966c04fSmrg    data_size += image->height * offset;
200a966c04fSmrg
2019f00f3a1Smrg    if (header_size > UINT_MAX - ext_size ||
2029f00f3a1Smrg	header_size + ext_size >= (UINT_MAX - data_size) )
203a966c04fSmrg	RETURN(XpmNoMemory);
204a966c04fSmrg    data_size += header_size + ext_size;
205a966c04fSmrg
206a966c04fSmrg    data = (char **) XpmMalloc(data_size);
207a966c04fSmrg    if (!data)
208a966c04fSmrg	RETURN(XpmNoMemory);
209a966c04fSmrg
210a966c04fSmrg    data_nlines = header_nlines + image->height + ext_nlines;
211a966c04fSmrg    *data = (char *) (data + data_nlines);
212a966c04fSmrg
213a966c04fSmrg    /* can header have less elements then n suggests? */
214a966c04fSmrg    n = image->ncolors;
215a966c04fSmrg    for (l = 0, sptr = data, sptr2 = header; l <= n && sptr && sptr2; l++, sptr++, sptr2++) {
216a966c04fSmrg	strcpy(*sptr, *sptr2);
217a966c04fSmrg	*(sptr + 1) = *sptr + strlen(*sptr2) + 1;
218a966c04fSmrg    }
219a966c04fSmrg
220a966c04fSmrg    /* print pixels */
221a966c04fSmrg    data[header_nlines] = (char *) data + header_size
222a966c04fSmrg	+ (image->height + ext_nlines) * sizeof(char *);
223a966c04fSmrg
224a966c04fSmrg    CreatePixels(data + header_nlines, data_size-header_nlines, image->width, image->height,
225a966c04fSmrg		 image->cpp, image->data, image->colorTable);
226a966c04fSmrg
227a966c04fSmrg    /* print extensions */
228a966c04fSmrg    if (extensions)
229a966c04fSmrg	CreateExtensions(data + header_nlines + image->height - 1,
230a966c04fSmrg			 data_size - header_nlines - image->height + 1, offset,
231a966c04fSmrg			 info->extensions, info->nextensions,
232a966c04fSmrg			 ext_nlines);
233a966c04fSmrg
234a966c04fSmrg    *data_return = data;
235a966c04fSmrg    ErrorStatus = XpmSuccess;
236a966c04fSmrg
237a966c04fSmrg/* exit point, free only locally allocated variables */
238a966c04fSmrgexit:
239a966c04fSmrg    if (header) {
240a966c04fSmrg	for (l = 0; l < header_nlines; l++)
241a966c04fSmrg	    if (header[l])
242a966c04fSmrg		XpmFree(header[l]);
243a966c04fSmrg		XpmFree(header);
244a966c04fSmrg    }
245a966c04fSmrg    return(ErrorStatus);
246a966c04fSmrg}
247a966c04fSmrg
248a966c04fSmrgstatic int
2492e2dd055SmrgCreateColors(
2502e2dd055Smrg    char		**dataptr,
2512e2dd055Smrg    unsigned int	 *data_size,
2522e2dd055Smrg    XpmColor		 *colors,
2532e2dd055Smrg    unsigned int	  ncolors,
2542e2dd055Smrg    unsigned int	  cpp)
255a966c04fSmrg{
256a966c04fSmrg    char buf[BUFSIZ];
257a966c04fSmrg    unsigned int a, key, l;
258a966c04fSmrg    char *s, *s2;
259a966c04fSmrg    char **defaults;
260a966c04fSmrg
261a966c04fSmrg    /* can ncolors be trusted here? */
262a966c04fSmrg    for (a = 0; a < ncolors; a++, colors++, dataptr++) {
263a966c04fSmrg
264a966c04fSmrg	defaults = (char **) colors;
265a966c04fSmrg	if(sizeof(buf) <= cpp)
266a966c04fSmrg	    return(XpmNoMemory);
267a966c04fSmrg	strncpy(buf, *defaults++, cpp);
268a966c04fSmrg	s = buf + cpp;
269a966c04fSmrg
270a966c04fSmrg	if(sizeof(buf) <= (s-buf))
271a966c04fSmrg		return XpmNoMemory;
272a966c04fSmrg
273a966c04fSmrg	for (key = 1; key <= NKEYS; key++, defaults++) {
274a966c04fSmrg	    if ((s2 = *defaults)) {
275a966c04fSmrg#ifndef VOID_SPRINTF
276a966c04fSmrg		s +=
277a966c04fSmrg#endif
278a966c04fSmrg		/* assume C99 compliance */
279a966c04fSmrg			snprintf(s, sizeof(buf)-(s-buf), "\t%s %s", xpmColorKeys[key - 1], s2);
280a966c04fSmrg#ifdef VOID_SPRINTF
281a966c04fSmrg		s += strlen(s);
282a966c04fSmrg#endif
283a966c04fSmrg		/* does s point out-of-bounds? */
284a966c04fSmrg		if(sizeof(buf) < (s-buf))
285a966c04fSmrg			return XpmNoMemory;
286a966c04fSmrg	    }
287a966c04fSmrg	}
288a966c04fSmrg	/* what about using strdup()? */
289a966c04fSmrg	l = s - buf + 1;
290a966c04fSmrg	s = (char *) XpmMalloc(l);
291a966c04fSmrg	if (!s)
292a966c04fSmrg	    return (XpmNoMemory);
293a966c04fSmrg	*data_size += l;
294a966c04fSmrg	*dataptr = strcpy(s, buf);
295a966c04fSmrg    }
296a966c04fSmrg    return (XpmSuccess);
297a966c04fSmrg}
298a966c04fSmrg
299a966c04fSmrgstatic void
3002e2dd055SmrgCreatePixels(
3012e2dd055Smrg    char		**dataptr,
3022e2dd055Smrg    unsigned int	  data_size,
3032e2dd055Smrg    unsigned int	  width,
3042e2dd055Smrg    unsigned int	  height,
3052e2dd055Smrg    unsigned int	  cpp,
3062e2dd055Smrg    unsigned int	 *pixels,
3072e2dd055Smrg    XpmColor		 *colors)
308a966c04fSmrg{
309a966c04fSmrg    char *s;
310a966c04fSmrg    unsigned int x, y, h, offset;
311a966c04fSmrg
312a966c04fSmrg    if(height <= 1)
313a966c04fSmrg    	return;
314a966c04fSmrg
315a966c04fSmrg    h = height - 1;
316a966c04fSmrg
317a966c04fSmrg    offset = width * cpp + 1;
318a966c04fSmrg
319a966c04fSmrg    if(offset <= width || offset <= cpp)
320a966c04fSmrg    	return;
321a966c04fSmrg
322a966c04fSmrg    /* why trust h? */
323a966c04fSmrg    for (y = 0; y < h; y++, dataptr++) {
324a966c04fSmrg	s = *dataptr;
325a966c04fSmrg	/* why trust width? */
326a966c04fSmrg	for (x = 0; x < width; x++, pixels++) {
327a966c04fSmrg	    if(cpp > (data_size - (s - *dataptr)))
328a966c04fSmrg	    	return;
329a966c04fSmrg	    strncpy(s, colors[*pixels].string, cpp); /* why trust pixel? */
330a966c04fSmrg	    s += cpp;
331a966c04fSmrg	}
332a966c04fSmrg	*s = '\0';
333a966c04fSmrg	if(offset > data_size)
334a966c04fSmrg		return;
335a966c04fSmrg	*(dataptr + 1) = *dataptr + offset;
336a966c04fSmrg    }
337a966c04fSmrg    /* duplicate some code to avoid a test in the loop */
338a966c04fSmrg    s = *dataptr;
339a966c04fSmrg    /* why trust width? */
340a966c04fSmrg    for (x = 0; x < width; x++, pixels++) {
341a966c04fSmrg	if(cpp > data_size - (s - *dataptr))
342a966c04fSmrg	    	return;
343a966c04fSmrg	strncpy(s, colors[*pixels].string, cpp); /* why should we trust *pixel? */
344a966c04fSmrg	s += cpp;
345a966c04fSmrg    }
346a966c04fSmrg    *s = '\0';
347a966c04fSmrg}
348a966c04fSmrg
3499f00f3a1Smrgstatic int
3502e2dd055SmrgCountExtensions(
3512e2dd055Smrg    XpmExtension	*ext,
3522e2dd055Smrg    unsigned int	 num,
3532e2dd055Smrg    unsigned int	*ext_size,
3542e2dd055Smrg    unsigned int	*ext_nlines)
355a966c04fSmrg{
3569f00f3a1Smrg    size_t len;
357a966c04fSmrg    unsigned int x, y, a, size, nlines;
358a966c04fSmrg    char **line;
359a966c04fSmrg
360a966c04fSmrg    size = 0;
361a966c04fSmrg    nlines = 0;
362a966c04fSmrg    for (x = 0; x < num; x++, ext++) {
363a966c04fSmrg	/* 1 for the name */
3649f00f3a1Smrg	if (ext->nlines == UINT_MAX || nlines > UINT_MAX - ext->nlines - 1)
3659f00f3a1Smrg	    return (1);
366a966c04fSmrg	nlines += ext->nlines + 1;
367a966c04fSmrg	/* 8 = 7 (for "XPMEXT ") + 1 (for 0) */
3689f00f3a1Smrg	len = strlen(ext->name) + 8;
3699f00f3a1Smrg	if (len > UINT_MAX - size)
3709f00f3a1Smrg	    return (1);
3719f00f3a1Smrg	size += len;
372a966c04fSmrg	a = ext->nlines;
3739f00f3a1Smrg	for (y = 0, line = ext->lines; y < a; y++, line++) {
3749f00f3a1Smrg	    len = strlen(*line) + 1;
3759f00f3a1Smrg	    if (len > UINT_MAX - size)
3769f00f3a1Smrg		return (1);
3779f00f3a1Smrg	    size += len;
3789f00f3a1Smrg	}
379a966c04fSmrg    }
3809f00f3a1Smrg    if (size > UINT_MAX - 10 || nlines > UINT_MAX - 1)
3819f00f3a1Smrg	return (1);
382a966c04fSmrg    /* 10 and 1 are for the ending "XPMENDEXT" */
383a966c04fSmrg    *ext_size = size + 10;
384a966c04fSmrg    *ext_nlines = nlines + 1;
3859f00f3a1Smrg    return (0);
386a966c04fSmrg}
387a966c04fSmrg
388a966c04fSmrgstatic void
3892e2dd055SmrgCreateExtensions(
3902e2dd055Smrg    char		**dataptr,
3912e2dd055Smrg    unsigned int	  data_size,
3922e2dd055Smrg    unsigned int	  offset,
3932e2dd055Smrg    XpmExtension	 *ext,
3942e2dd055Smrg    unsigned int	  num,
3952e2dd055Smrg    unsigned int	  ext_nlines)
396a966c04fSmrg{
397a966c04fSmrg    unsigned int x, y, a, b;
398a966c04fSmrg    char **line;
399a966c04fSmrg
400a966c04fSmrg    *(dataptr + 1) = *dataptr + offset;
401a966c04fSmrg    dataptr++;
402a966c04fSmrg    a = 0;
403a966c04fSmrg    for (x = 0; x < num; x++, ext++) {
404a966c04fSmrg	snprintf(*dataptr, data_size, "XPMEXT %s", ext->name);
405a966c04fSmrg	a++;
406a966c04fSmrg	if (a < ext_nlines)
407a966c04fSmrg	    *(dataptr + 1) = *dataptr + strlen(ext->name) + 8;
408a966c04fSmrg	dataptr++;
409a966c04fSmrg	b = ext->nlines; /* can we trust these values? */
410a966c04fSmrg	for (y = 0, line = ext->lines; y < b; y++, line++) {
411a966c04fSmrg	    strcpy(*dataptr, *line);
412a966c04fSmrg	    a++;
413a966c04fSmrg	    if (a < ext_nlines)
414a966c04fSmrg		*(dataptr + 1) = *dataptr + strlen(*line) + 1;
415a966c04fSmrg	    dataptr++;
416a966c04fSmrg	}
417a966c04fSmrg    }
418a966c04fSmrg    strcpy(*dataptr, "XPMENDEXT");
419a966c04fSmrg}
420