1 /* $XConsortium: Xpmcreate.c /main/8 1996/09/20 08:15:02 pascale $ */
2 /*
3  * Copyright (C) 1989-95 GROUPE BULL
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to
7  * deal in the Software without restriction, including without limitation the
8  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9  * sell copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18  * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * Except as contained in this notice, the name of GROUPE BULL shall not be
23  * used in advertising or otherwise to promote the sale, use or other dealings
24  * in this Software without prior written authorization from GROUPE BULL.
25  */
26 
27 /*****************************************************************************\
28 * create.c:                                                                   *
29 *                                                                             *
30 *  XPM library                                                                *
31 *  Create an X image and possibly its related shape mask                      *
32 *  from the given XpmImage.                                                   *
33 *                                                                             *
34 *  Developed by Arnaud Le Hors                                                *
35 \*****************************************************************************/
36 
37 /*
38  * The code related to FOR_MSW has been added by
39  * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
40  */
41 
42 #ifdef HAVE_CONFIG_H
43 #include <config.h>
44 #endif
45 
46 
47 /* October 2004, source code review by Thomas Biege <thomas@suse.de> */
48 
49 #include "XpmI.h"
50 #include <ctype.h>
51 
52 LFUNC(xpmVisualType, int, (Visual *visual));
53 
54 LFUNC(AllocColor, int, (Display *display, Colormap colormap,
55 			char *colorname, XColor *xcolor, void *closure));
56 LFUNC(FreeColors, int, (Display *display, Colormap colormap,
57 			Pixel *pixels, int n, void *closure));
58 
59 #ifndef FOR_MSW
60 LFUNC(SetCloseColor, int, (Display *display, Colormap colormap,
61 			   Visual *visual, XColor *col,
62 			   Pixel *image_pixel, Pixel *mask_pixel,
63 			   Pixel *alloc_pixels, unsigned int *nalloc_pixels,
64 			   XpmAttributes *attributes, XColor *cols, int ncols,
65 			   XpmAllocColorFunc allocColor, void *closure));
66 #else
67 /* let the window system take care of close colors */
68 #endif
69 
70 LFUNC(SetColor, int, (Display *display, Colormap colormap, Visual *visual,
71 		      char *colorname, unsigned int color_index,
72 		      Pixel *image_pixel, Pixel *mask_pixel,
73 		      unsigned int *mask_pixel_index,
74 		      Pixel *alloc_pixels, unsigned int *nalloc_pixels,
75 		      Pixel *used_pixels, unsigned int *nused_pixels,
76 		      XpmAttributes *attributes, XColor *cols, int ncols,
77 		      XpmAllocColorFunc allocColor, void *closure));
78 
79 LFUNC(CreateXImage, int, (Display *display, Visual *visual,
80 			  unsigned int depth, int format, unsigned int width,
81                           unsigned int height, XImage **image_return));
82 
83 LFUNC(CreateColors, int, (Display *display, XpmAttributes *attributes,
84                           XpmColor *colors, unsigned int ncolors,
85                           Pixel *image_pixels, Pixel *mask_pixels,
86                           unsigned int *mask_pixel_index,
87                           Pixel *alloc_pixels, unsigned int *nalloc_pixels,
88                           Pixel *used_pixels, unsigned int *nused_pixels));
89 
90 #ifndef FOR_MSW
91 LFUNC(ParseAndPutPixels, int, (xpmData *data, unsigned int width,
92 			       unsigned int height, unsigned int ncolors,
93 			       unsigned int cpp, XpmColor *colorTable,
94 			       xpmHashTable *hashtable,
95 			       XImage *image, Pixel *image_pixels,
96 			       XImage *mask, Pixel *mask_pixels));
97 #else  /* FOR_MSW */
98 LFUNC(ParseAndPutPixels, int, (Display *dc, xpmData *data, unsigned int width,
99 			       unsigned int height, unsigned int ncolors,
100 			       unsigned int cpp, XpmColor *colorTable,
101 			       xpmHashTable *hashtable,
102 			       XImage *image, Pixel *image_pixels,
103 			       XImage *mask, Pixel *mask_pixels));
104 #endif
105 
106 #ifndef FOR_MSW
107 /* XImage pixel routines */
108 LFUNC(PutImagePixels, void, (XImage *image, unsigned int width,
109 			     unsigned int height, unsigned int *pixelindex,
110 			     Pixel *pixels));
111 
112 LFUNC(PutImagePixels32, void, (XImage *image, unsigned int width,
113 			       unsigned int height, unsigned int *pixelindex,
114 			       Pixel *pixels));
115 
116 LFUNC(PutImagePixels16, void, (XImage *image, unsigned int width,
117 			       unsigned int height, unsigned int *pixelindex,
118 			       Pixel *pixels));
119 
120 LFUNC(PutImagePixels8, void, (XImage *image, unsigned int width,
121 			      unsigned int height, unsigned int *pixelindex,
122 			      Pixel *pixels));
123 
124 LFUNC(PutImagePixels1, void, (XImage *image, unsigned int width,
125 			      unsigned int height, unsigned int *pixelindex,
126 			      Pixel *pixels));
127 
128 LFUNC(PutPixel1, int, (XImage *ximage, int x, int y, unsigned long pixel));
129 LFUNC(PutPixel, int, (XImage *ximage, int x, int y, unsigned long pixel));
130 LFUNC(PutPixel32, int, (XImage *ximage, int x, int y, unsigned long pixel));
131 LFUNC(PutPixel32MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
132 LFUNC(PutPixel32LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
133 LFUNC(PutPixel16MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
134 LFUNC(PutPixel16LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
135 LFUNC(PutPixel8, int, (XImage *ximage, int x, int y, unsigned long pixel));
136 LFUNC(PutPixel1MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
137 LFUNC(PutPixel1LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
138 
139 #else  /* ndef FOR_MSW */
140 /* FOR_MSW pixel routine */
141 LFUNC(MSWPutImagePixels, void, (Display *dc, XImage *image,
142 				unsigned int width, unsigned int height,
143 				unsigned int *pixelindex, Pixel *pixels));
144 #endif /* ndef FOR_MSW */
145 
146 #ifdef NEED_STRCASECMP
147 FUNC(xpmstrcasecmp, int, (char *s1, char *s2));
148 
149 /*
150  * in case strcasecmp is not provided by the system here is one
151  * which does the trick
152  */
153 int
xpmstrcasecmp(s1,s2)154 xpmstrcasecmp(s1, s2)
155     register char *s1, *s2;
156 {
157     register int c1, c2;
158 
159     while (*s1 && *s2) {
160 	c1 = tolower(*s1);
161 	c2 = tolower(*s2);
162 	if (c1 != c2)
163 	    return (c1 - c2);
164 	s1++;
165 	s2++;
166     }
167     return (int) (*s1 - *s2);
168 }
169 
170 #endif
171 
172 /*
173  * return the default color key related to the given visual
174  */
175 static int
xpmVisualType(visual)176 xpmVisualType(visual)
177     Visual *visual;
178 {
179 #ifndef FOR_MSW
180     switch (visual->class) {
181     case StaticGray:
182     case GrayScale:
183 	switch (visual->map_entries) {
184 	case 2:
185 	    return (XPM_MONO);
186 	case 4:
187 	    return (XPM_GRAY4);
188 	default:
189 	    return (XPM_GRAY);
190 	}
191     default:
192 	return (XPM_COLOR);
193     }
194 #else
195     /* there should be a similar switch for MSW */
196     return (XPM_COLOR);
197 #endif
198 }
199 
200 
201 typedef struct {
202     int cols_index;
203     long closeness;
204 }      CloseColor;
205 
206 static int
closeness_cmp(a,b)207 closeness_cmp(a, b)
208     Const void *a, *b;
209 {
210     CloseColor *x = (CloseColor *) a, *y = (CloseColor *) b;
211 
212     /* cast to int as qsort requires */
213     return (int) (x->closeness - y->closeness);
214 }
215 
216 
217 /* default AllocColor function:
218  *   call XParseColor if colorname is given, return negative value if failure
219  *   call XAllocColor and return 0 if failure, positive otherwise
220  */
221 static int
AllocColor(display,colormap,colorname,xcolor,closure)222 AllocColor(display, colormap, colorname, xcolor, closure)
223     Display *display;
224     Colormap colormap;
225     char *colorname;
226     XColor *xcolor;
227     void *closure;		/* not used */
228 {
229     int status;
230     if (colorname)
231 	if (!XParseColor(display, colormap, colorname, xcolor))
232 	    return -1;
233     status = XAllocColor(display, colormap, xcolor);
234     return status != 0 ? 1 : 0;
235 }
236 
237 
238 #ifndef FOR_MSW
239 /*
240  * set a close color in case the exact one can't be set
241  * return 0 if success, 1 otherwise.
242  */
243 
244 static int
SetCloseColor(display,colormap,visual,col,image_pixel,mask_pixel,alloc_pixels,nalloc_pixels,attributes,cols,ncols,allocColor,closure)245 SetCloseColor(display, colormap, visual, col, image_pixel, mask_pixel,
246 	      alloc_pixels, nalloc_pixels, attributes, cols, ncols,
247 	      allocColor, closure)
248     Display *display;
249     Colormap colormap;
250     Visual *visual;
251     XColor *col;
252     Pixel *image_pixel, *mask_pixel;
253     Pixel *alloc_pixels;
254     unsigned int *nalloc_pixels;
255     XpmAttributes *attributes;
256     XColor *cols;
257     int ncols;
258     XpmAllocColorFunc allocColor;
259     void *closure;
260 {
261 
262     /*
263      * Allocation failed, so try close colors. To get here the visual must
264      * be GreyScale, PseudoColor or DirectColor (or perhaps StaticColor?
265      * What about sharing systems like QDSS?). Beware: we have to treat
266      * DirectColor differently.
267      */
268 
269 
270     long int red_closeness, green_closeness, blue_closeness;
271     int n;
272     Bool alloc_color;
273 
274     if (attributes && (attributes->valuemask & XpmCloseness))
275 	red_closeness = green_closeness = blue_closeness =
276 	    attributes->closeness;
277     else {
278 	red_closeness = attributes->red_closeness;
279 	green_closeness = attributes->green_closeness;
280 	blue_closeness = attributes->blue_closeness;
281     }
282     if (attributes && (attributes->valuemask & XpmAllocCloseColors))
283 	alloc_color = attributes->alloc_close_colors;
284     else
285 	alloc_color = True;
286 
287     /*
288      * We sort the colormap by closeness and try to allocate the color
289      * closest to the target. If the allocation of this close color fails,
290      * which almost never happens, then one of two scenarios is possible.
291      * Either the colormap must have changed (since the last close color
292      * allocation or possibly while we were sorting the colormap), or the
293      * color is allocated as Read/Write by some other client. (Note: X
294      * _should_ allow clients to check if a particular color is Read/Write,
295      * but it doesn't! :-( ). We cannot determine which of these scenarios
296      * occurred, so we try the next closest color, and so on, until no more
297      * colors are within closeness of the target. If we knew that the
298      * colormap had changed, we could skip this sequence.
299      *
300      * If _none_ of the colors within closeness of the target can be allocated,
301      * then we can finally be pretty sure that the colormap has actually
302      * changed. In this case we try to allocate the original color (again),
303      * then try the closecolor stuff (again)...
304      *
305      * In theory it would be possible for an infinite loop to occur if another
306      * process kept changing the colormap every time we sorted it, so we set
307      * a maximum on the number of iterations. After this many tries, we use
308      * XGrabServer() to ensure that the colormap remains unchanged.
309      *
310      * This approach gives particularly bad worst case performance - as many as
311      * <MaximumIterations> colormap reads and sorts may be needed, and as
312      * many as <MaximumIterations> * <ColormapSize> attempted allocations
313      * may fail. On an 8-bit system, this means as many as 3 colormap reads,
314      * 3 sorts and 768 failed allocations per execution of this code!
315      * Luckily, my experiments show that in general use in a typical 8-bit
316      * color environment only about 1 in every 10000 allocations fails to
317      * succeed in the fastest possible time. So virtually every time what
318      * actually happens is a single sort followed by a successful allocate.
319      * The very first allocation also costs a colormap read, but no further
320      * reads are usually necessary.
321      */
322 
323 #define ITERATIONS 2			/* more than one is almost never
324 					 * necessary */
325 
326     for (n = 0; n <= ITERATIONS; ++n) {
327 	CloseColor *closenesses =
328 	    (CloseColor *) XpmCalloc(ncols, sizeof(CloseColor));
329 	int i, c;
330 
331 	for (i = 0; i < ncols; ++i) {	/* build & sort closenesses table */
332 #define COLOR_FACTOR       3
333 #define BRIGHTNESS_FACTOR  1
334 
335 	    closenesses[i].cols_index = i;
336 	    closenesses[i].closeness =
337 		COLOR_FACTOR * (abs((long) col->red - (long) cols[i].red)
338 				+ abs((long) col->green - (long) cols[i].green)
339 				+ abs((long) col->blue - (long) cols[i].blue))
340 		+ BRIGHTNESS_FACTOR * abs(((long) col->red +
341 					   (long) col->green +
342 					   (long) col->blue)
343 					   - ((long) cols[i].red +
344 					      (long) cols[i].green +
345 					      (long) cols[i].blue));
346 	}
347 	qsort(closenesses, ncols, sizeof(CloseColor), closeness_cmp);
348 
349 	i = 0;
350 	c = closenesses[i].cols_index;
351 	while ((long) cols[c].red >= (long) col->red - red_closeness &&
352 	       (long) cols[c].red <= (long) col->red + red_closeness &&
353 	       (long) cols[c].green >= (long) col->green - green_closeness &&
354 	       (long) cols[c].green <= (long) col->green + green_closeness &&
355 	       (long) cols[c].blue >= (long) col->blue - blue_closeness &&
356 	       (long) cols[c].blue <= (long) col->blue + blue_closeness) {
357 	    if (alloc_color) {
358 		if ((*allocColor)(display, colormap, NULL, &cols[c], closure)){
359 		    if (n == ITERATIONS)
360 			XUngrabServer(display);
361 		    XpmFree(closenesses);
362 		    *image_pixel = cols[c].pixel;
363 		    *mask_pixel = 1;
364 		    alloc_pixels[(*nalloc_pixels)++] = cols[c].pixel;
365 		    return (0);
366 		} else {
367 		    ++i;
368 		    if (i == ncols)
369 			break;
370 		    c = closenesses[i].cols_index;
371 		}
372 	    } else {
373 		if (n == ITERATIONS)
374 		    XUngrabServer(display);
375 		XpmFree(closenesses);
376 		*image_pixel = cols[c].pixel;
377 		*mask_pixel = 1;
378 		return (0);
379 	    }
380 	}
381 
382 	/* Couldn't allocate _any_ of the close colors! */
383 
384 	if (n == ITERATIONS)
385 	    XUngrabServer(display);
386 	XpmFree(closenesses);
387 
388 	if (i == 0 || i == ncols)	/* no color close enough or cannot */
389 	    return (1);			/* alloc any color (full of r/w's) */
390 
391 	if ((*allocColor)(display, colormap, NULL, col, closure)) {
392 	    *image_pixel = col->pixel;
393 	    *mask_pixel = 1;
394 	    alloc_pixels[(*nalloc_pixels)++] = col->pixel;
395 	    return (0);
396 	} else {			/* colormap has probably changed, so
397 					 * re-read... */
398 	    if (n == ITERATIONS - 1)
399 		XGrabServer(display);
400 
401 #if 0
402 	    if (visual->class == DirectColor) {
403 		/* TODO */
404 	    } else
405 #endif
406 		XQueryColors(display, colormap, cols, ncols);
407 	}
408     }
409     return (1);
410 }
411 
412 #define USE_CLOSECOLOR attributes && \
413 (((attributes->valuemask & XpmCloseness) && attributes->closeness != 0) \
414  || ((attributes->valuemask & XpmRGBCloseness) && \
415      (attributes->red_closeness != 0 \
416       || attributes->green_closeness != 0 \
417       || attributes->blue_closeness != 0)))
418 
419 #else
420     /* FOR_MSW part */
421     /* nothing to do here, the window system does it */
422 #endif
423 
424 /*
425  * set the color pixel related to the given colorname,
426  * return 0 if success, 1 otherwise.
427  */
428 
429 static int
SetColor(display,colormap,visual,colorname,color_index,image_pixel,mask_pixel,mask_pixel_index,alloc_pixels,nalloc_pixels,used_pixels,nused_pixels,attributes,cols,ncols,allocColor,closure)430 SetColor(display, colormap, visual, colorname, color_index,
431 	 image_pixel, mask_pixel, mask_pixel_index,
432 	 alloc_pixels, nalloc_pixels, used_pixels, nused_pixels,
433 	 attributes, cols, ncols, allocColor, closure)
434     Display *display;
435     Colormap colormap;
436     Visual *visual;
437     char *colorname;
438     unsigned int color_index;
439     Pixel *image_pixel, *mask_pixel;
440     unsigned int *mask_pixel_index;
441     Pixel *alloc_pixels;
442     unsigned int *nalloc_pixels;
443     Pixel *used_pixels;
444     unsigned int *nused_pixels;
445     XpmAttributes *attributes;
446     XColor *cols;
447     int ncols;
448     XpmAllocColorFunc allocColor;
449     void *closure;
450 {
451     XColor xcolor;
452     int status;
453 
454     if (xpmstrcasecmp(colorname, TRANSPARENT_COLOR)) {
455 	status = (*allocColor)(display, colormap, colorname, &xcolor, closure);
456 	if (status < 0)		/* parse color failed */
457 	    return (1);
458 
459 	if (status == 0) {
460 #ifndef FOR_MSW
461 	    if (USE_CLOSECOLOR)
462 		return (SetCloseColor(display, colormap, visual, &xcolor,
463 				      image_pixel, mask_pixel,
464 				      alloc_pixels, nalloc_pixels,
465 				      attributes, cols, ncols,
466 				      allocColor, closure));
467 	    else
468 #endif /* ndef FOR_MSW */
469 		return (1);
470 	} else
471 	    alloc_pixels[(*nalloc_pixels)++] = xcolor.pixel;
472 	*image_pixel = xcolor.pixel;
473 	*mask_pixel = 1;
474 	used_pixels[(*nused_pixels)++] = xcolor.pixel;
475     } else {
476 	*image_pixel = 0;
477 	*mask_pixel = 0;
478 	/* store the color table index */
479 	*mask_pixel_index = color_index;
480     }
481     return (0);
482 }
483 
484 
485 static int
CreateColors(display,attributes,colors,ncolors,image_pixels,mask_pixels,mask_pixel_index,alloc_pixels,nalloc_pixels,used_pixels,nused_pixels)486 CreateColors(display, attributes, colors, ncolors, image_pixels, mask_pixels,
487              mask_pixel_index, alloc_pixels, nalloc_pixels,
488              used_pixels, nused_pixels)
489     Display *display;
490     XpmAttributes *attributes;
491     XpmColor *colors;
492     unsigned int ncolors;
493     Pixel *image_pixels;
494     Pixel *mask_pixels;
495     unsigned int *mask_pixel_index;
496     Pixel *alloc_pixels;
497     unsigned int *nalloc_pixels;
498     Pixel *used_pixels;
499     unsigned int *nused_pixels;
500 {
501     /* variables stored in the XpmAttributes structure */
502     Visual *visual;
503     Colormap colormap;
504     XpmColorSymbol *colorsymbols = NULL;
505     unsigned int numsymbols;
506     XpmAllocColorFunc allocColor;
507     void *closure;
508 
509     char *colorname;
510     unsigned int color, key;
511     Bool pixel_defined;
512     XpmColorSymbol *symbol = NULL;
513     char **defaults;
514     int ErrorStatus = XpmSuccess;
515     char *s;
516     int default_index;
517 
518     XColor *cols = NULL;
519     unsigned int ncols = 0;
520 
521     /*
522      * retrieve information from the XpmAttributes
523      */
524     if (attributes && attributes->valuemask & XpmColorSymbols) {
525 	colorsymbols = attributes->colorsymbols;
526 	numsymbols = attributes->numsymbols;
527     } else
528 	numsymbols = 0;
529 
530     if (attributes && attributes->valuemask & XpmVisual)
531 	visual = attributes->visual;
532     else
533 	visual = XDefaultVisual(display, XDefaultScreen(display));
534 
535     if (attributes && (attributes->valuemask & XpmColormap))
536 	colormap = attributes->colormap;
537     else
538 	colormap = XDefaultColormap(display, XDefaultScreen(display));
539 
540     if (attributes && (attributes->valuemask & XpmColorKey))
541 	key = attributes->color_key;
542     else
543 	key = xpmVisualType(visual);
544 
545     if (attributes && (attributes->valuemask & XpmAllocColor))
546 	allocColor = attributes->alloc_color;
547     else
548 	allocColor = AllocColor;
549     if (attributes && (attributes->valuemask & XpmColorClosure))
550 	closure = attributes->color_closure;
551     else
552 	closure = NULL;
553 
554 #ifndef FOR_MSW
555     if (USE_CLOSECOLOR) {
556 	/* originally from SetCloseColor */
557 #if 0
558 	if (visual->class == DirectColor) {
559 
560 	    /*
561 	     * TODO: Implement close colors for DirectColor visuals. This is
562 	     * difficult situation. Chances are that we will never get here,
563 	     * because any machine that supports DirectColor will probably
564 	     * also support TrueColor (and probably PseudoColor). Also,
565 	     * DirectColor colormaps can be very large, so looking for close
566 	     * colors may be too slow.
567 	     */
568 	} else {
569 #endif
570 	    unsigned int i;
571 
572 	    ncols = visual->map_entries;
573 	    cols = (XColor *) XpmCalloc(ncols, sizeof(XColor));
574 	    for (i = 0; i < ncols; ++i)
575 		cols[i].pixel = i;
576 	    XQueryColors(display, colormap, cols, ncols);
577 #if 0
578 	}
579 #endif
580     }
581 #endif /* ndef FOR_MSW */
582 
583     switch (key) {
584     case XPM_MONO:
585 	default_index = 2;
586 	break;
587     case XPM_GRAY4:
588 	default_index = 3;
589 	break;
590     case XPM_GRAY:
591 	default_index = 4;
592 	break;
593     case XPM_COLOR:
594     default:
595 	default_index = 5;
596 	break;
597     }
598 
599     for (color = 0; color < ncolors; color++, colors++,
600 					 image_pixels++, mask_pixels++) {
601 	colorname = NULL;
602 	pixel_defined = False;
603 	defaults = (char **) colors;
604 
605 	/*
606 	 * look for a defined symbol
607 	 */
608 	if (numsymbols) {
609 
610 	    unsigned int n;
611 
612 	    s = defaults[1];
613 	    for (n = 0, symbol = colorsymbols; n < numsymbols; n++, symbol++) {
614 		if (symbol->name && s && !strcmp(symbol->name, s))
615 		    /* override name */
616 		    break;
617 		if (!symbol->name && symbol->value) {	/* override value */
618 		    int def_index = default_index;
619 
620 		    while (defaults[def_index] == NULL)	/* find defined
621 							 * colorname */
622 			--def_index;
623 		    if (def_index < 2) {/* nothing towards mono, so try
624 					 * towards color */
625 			def_index = default_index + 1;
626 			while (def_index <= 5 && defaults[def_index] == NULL)
627 			    ++def_index;
628 		    }
629 		    if (def_index >= 2 && defaults[def_index] != NULL &&
630 			!xpmstrcasecmp(symbol->value, defaults[def_index]))
631 			break;
632 		}
633 	    }
634 	    if (n != numsymbols) {
635 		if (symbol->name && symbol->value)
636 		    colorname = symbol->value;
637 		else
638 		    pixel_defined = True;
639 	    }
640 	}
641 	if (!pixel_defined) {		/* pixel not given as symbol value */
642 
643 	    unsigned int k;
644 
645 	    if (colorname) {		/* colorname given as symbol value */
646 		if (!SetColor(display, colormap, visual, colorname, color,
647 			      image_pixels, mask_pixels, mask_pixel_index,
648 			      alloc_pixels, nalloc_pixels, used_pixels,
649 			      nused_pixels, attributes, cols, ncols,
650 			      allocColor, closure))
651 		    pixel_defined = True;
652 		else
653 		    ErrorStatus = XpmColorError;
654 	    }
655 	    k = key;
656 	    while (!pixel_defined && k > 1) {
657 		if (defaults[k]) {
658 		    if (!SetColor(display, colormap, visual, defaults[k],
659 				  color, image_pixels, mask_pixels,
660 				  mask_pixel_index, alloc_pixels,
661 				  nalloc_pixels, used_pixels, nused_pixels,
662 				  attributes, cols, ncols,
663 				  allocColor, closure)) {
664 			pixel_defined = True;
665 			break;
666 		    } else
667 			ErrorStatus = XpmColorError;
668 		}
669 		k--;
670 	    }
671 	    k = key + 1;
672 	    while (!pixel_defined && k < NKEYS + 1) {
673 		if (defaults[k]) {
674 		    if (!SetColor(display, colormap, visual, defaults[k],
675 				  color, image_pixels, mask_pixels,
676 				  mask_pixel_index, alloc_pixels,
677 				  nalloc_pixels, used_pixels, nused_pixels,
678 				  attributes, cols, ncols,
679 				  allocColor, closure)) {
680 			pixel_defined = True;
681 			break;
682 		    } else
683 			ErrorStatus = XpmColorError;
684 		}
685 		k++;
686 	    }
687 	    if (!pixel_defined) {
688 		if (cols)
689 		    XpmFree(cols);
690 		return (XpmColorFailed);
691 	    }
692 	} else {
693 	    /* simply use the given pixel */
694 	    *image_pixels = symbol->pixel;
695 	    /* the following makes the mask to be built even if none
696 	       is given a particular pixel */
697 	    if (symbol->value
698 		&& !xpmstrcasecmp(symbol->value, TRANSPARENT_COLOR)) {
699 		*mask_pixels = 0;
700 		*mask_pixel_index = color;
701 	    } else
702 		*mask_pixels = 1;
703 	    used_pixels[(*nused_pixels)++] = *image_pixels;
704 	}
705     }
706     if (cols)
707 	XpmFree(cols);
708     return (ErrorStatus);
709 }
710 
711 
712 /* default FreeColors function, simply call XFreeColors */
713 static int
FreeColors(display,colormap,pixels,n,closure)714 FreeColors(display, colormap, pixels, n, closure)
715     Display *display;
716     Colormap colormap;
717     Pixel *pixels;
718     int n;
719     void *closure;		/* not used */
720 {
721     return XFreeColors(display, colormap, pixels, n, 0);
722 }
723 
724 
725 /* function call in case of error, frees only locally allocated variables */
726 #undef RETURN
727 #define RETURN(status) \
728 do { \
729     if (ximage) XDestroyImage(ximage); \
730     if (shapeimage) XDestroyImage(shapeimage); \
731     if (image_pixels) XpmFree(image_pixels); \
732     if (mask_pixels) XpmFree(mask_pixels); \
733     if (nalloc_pixels) \
734 	(*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL); \
735     if (alloc_pixels) XpmFree(alloc_pixels); \
736     if (used_pixels) XpmFree(used_pixels); \
737     return (status); \
738 } while(0)
739 
740 int
XpmCreateImageFromXpmImage(display,image,image_return,shapeimage_return,attributes)741 XpmCreateImageFromXpmImage(display, image,
742 			   image_return, shapeimage_return, attributes)
743     Display *display;
744     XpmImage *image;
745     XImage **image_return;
746     XImage **shapeimage_return;
747     XpmAttributes *attributes;
748 {
749     /* variables stored in the XpmAttributes structure */
750     Visual *visual;
751     Colormap colormap;
752     unsigned int depth;
753     int bitmap_format;
754     XpmFreeColorsFunc freeColors;
755     void *closure;
756 
757     /* variables to return */
758     XImage *ximage = NULL;
759     XImage *shapeimage = NULL;
760     unsigned int mask_pixel_index = XpmUndefPixel;
761     int ErrorStatus;
762 
763     /* calculation variables */
764     Pixel *image_pixels = NULL;
765     Pixel *mask_pixels = NULL;
766     Pixel *alloc_pixels = NULL;
767     Pixel *used_pixels = NULL;
768     unsigned int nalloc_pixels = 0;
769     unsigned int nused_pixels = 0;
770 
771     /* initialize return values */
772     if (image_return)
773 	*image_return = NULL;
774     if (shapeimage_return)
775 	*shapeimage_return = NULL;
776 
777     /* retrieve information from the XpmAttributes */
778     if (attributes && (attributes->valuemask & XpmVisual))
779 	visual = attributes->visual;
780     else
781 	visual = XDefaultVisual(display, XDefaultScreen(display));
782 
783     if (attributes && (attributes->valuemask & XpmColormap))
784 	colormap = attributes->colormap;
785     else
786 	colormap = XDefaultColormap(display, XDefaultScreen(display));
787 
788     if (attributes && (attributes->valuemask & XpmDepth))
789 	depth = attributes->depth;
790     else
791 	depth = XDefaultDepth(display, XDefaultScreen(display));
792 
793     if (attributes && (attributes->valuemask & XpmBitmapFormat))
794 	bitmap_format = attributes->bitmap_format;
795     else
796 	bitmap_format = ZPixmap;
797 
798     if (attributes && (attributes->valuemask & XpmFreeColors))
799 	freeColors = attributes->free_colors;
800     else
801 	freeColors = FreeColors;
802     if (attributes && (attributes->valuemask & XpmColorClosure))
803 	closure = attributes->color_closure;
804     else
805 	closure = NULL;
806 
807     ErrorStatus = XpmSuccess;
808 
809     if (image->ncolors >= UINT_MAX / sizeof(Pixel))
810 	return (XpmNoMemory);
811 
812     /* malloc pixels index tables */
813     image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
814     if (!image_pixels)
815 	return (XpmNoMemory);
816 
817     mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
818     if (!mask_pixels)
819 	RETURN(XpmNoMemory);
820 
821     /* maximum of allocated pixels will be the number of colors */
822     alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
823     if (!alloc_pixels)
824 	RETURN(XpmNoMemory);
825 
826     /* maximum of allocated pixels will be the number of colors */
827     used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
828     if (!used_pixels)
829 	RETURN(XpmNoMemory);
830 
831     /* get pixel colors, store them in index tables */
832     ErrorStatus = CreateColors(display, attributes, image->colorTable,
833 			       image->ncolors, image_pixels, mask_pixels,
834 			       &mask_pixel_index, alloc_pixels, &nalloc_pixels,
835 			       used_pixels, &nused_pixels);
836 
837     if (ErrorStatus != XpmSuccess
838 	&& (ErrorStatus < 0 || (attributes
839 				&& (attributes->valuemask & XpmExactColors)
840 				&& attributes->exactColors)))
841 	RETURN(ErrorStatus);
842 
843     /* create the ximage */
844     if (image_return) {
845 	ErrorStatus = CreateXImage(display, visual, depth,
846 				   (depth == 1 ? bitmap_format : ZPixmap),
847 				   image->width, image->height, &ximage);
848 	if (ErrorStatus != XpmSuccess)
849 	    RETURN(ErrorStatus);
850 
851 #ifndef FOR_MSW
852 
853 	/*
854 	 * set the ximage data using optimized functions for ZPixmap
855 	 */
856 
857 	if (ximage->bits_per_pixel == 8)
858 	    PutImagePixels8(ximage, image->width, image->height,
859 			    image->data, image_pixels);
860 	else if (((ximage->bits_per_pixel | ximage->depth) == 1) &&
861 		 (ximage->byte_order == ximage->bitmap_bit_order))
862 	    PutImagePixels1(ximage, image->width, image->height,
863 			    image->data, image_pixels);
864 	else if (ximage->bits_per_pixel == 16)
865 	    PutImagePixels16(ximage, image->width, image->height,
866 			     image->data, image_pixels);
867 	else if (ximage->bits_per_pixel == 32)
868 	    PutImagePixels32(ximage, image->width, image->height,
869 			     image->data, image_pixels);
870 	else
871 	    PutImagePixels(ximage, image->width, image->height,
872 			   image->data, image_pixels);
873 #else  /* FOR_MSW */
874 	MSWPutImagePixels(display, ximage, image->width, image->height,
875 			  image->data, image_pixels);
876 #endif
877     }
878     /* create the shape mask image */
879     if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
880 	ErrorStatus = CreateXImage(display, visual, 1, bitmap_format,
881 				   image->width, image->height, &shapeimage);
882 	if (ErrorStatus != XpmSuccess)
883 	    RETURN(ErrorStatus);
884 
885 #ifndef FOR_MSW
886 	PutImagePixels1(shapeimage, image->width, image->height,
887 			image->data, mask_pixels);
888 #else
889 	MSWPutImagePixels(display, shapeimage, image->width, image->height,
890 			  image->data, mask_pixels);
891 #endif
892 
893     }
894     XpmFree(image_pixels);
895     XpmFree(mask_pixels);
896 
897     /* if requested return used pixels in the XpmAttributes structure */
898     if (attributes && (attributes->valuemask & XpmReturnPixels ||
899 /* 3.2 backward compatibility code */
900 	attributes->valuemask & XpmReturnInfos)) {
901 /* end 3.2 bc */
902 	attributes->pixels = used_pixels;
903 	attributes->npixels = nused_pixels;
904 	attributes->mask_pixel = mask_pixel_index;
905     } else
906 	XpmFree(used_pixels);
907 
908     /* if requested return alloc'ed pixels in the XpmAttributes structure */
909     if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
910 	attributes->alloc_pixels = alloc_pixels;
911 	attributes->nalloc_pixels = nalloc_pixels;
912     } else
913 	XpmFree(alloc_pixels);
914 
915     /* return created images */
916     if (image_return)
917 	*image_return = ximage;
918     if (shapeimage_return)
919 	*shapeimage_return = shapeimage;
920 
921     return (ErrorStatus);
922 }
923 
924 
925 /*
926  * Create an XImage with its data
927  */
928 static int
CreateXImage(display,visual,depth,format,width,height,image_return)929 CreateXImage(display, visual, depth, format, width, height, image_return)
930     Display *display;
931     Visual *visual;
932     unsigned int depth;
933     int format;
934     unsigned int width;
935     unsigned int height;
936     XImage **image_return;
937 {
938     int bitmap_pad;
939 
940     /* first get bitmap_pad */
941     if (depth > 16)
942 	bitmap_pad = 32;
943     else if (depth > 8)
944 	bitmap_pad = 16;
945     else
946 	bitmap_pad = 8;
947 
948     /* then create the XImage with data = NULL and bytes_per_line = 0 */
949     *image_return = XCreateImage(display, visual, depth, format, 0, 0,
950 				 width, height, bitmap_pad, 0);
951     if (!*image_return)
952 	return (XpmNoMemory);
953 
954 #ifndef FOR_MSW
955     if (height != 0 && (*image_return)->bytes_per_line >= INT_MAX / height) {
956   	XDestroyImage(*image_return);
957         return (XpmNoMemory);
958     }
959     if((*image_return)->bytes_per_line == 0 ||  height == 0)
960         return XpmNoMemory;
961     /* now that bytes_per_line must have been set properly alloc data */
962     (*image_return)->data =
963 	(char *) XpmMalloc((*image_return)->bytes_per_line * height);
964 
965     if (!(*image_return)->data) {
966 	XDestroyImage(*image_return);
967 	*image_return = NULL;
968 	return (XpmNoMemory);
969     }
970 #else
971     /* under FOR_MSW XCreateImage has done it all */
972 #endif
973     return (XpmSuccess);
974 }
975 
976 #ifndef FOR_MSW
977 /*
978  * The functions below are written from X11R5 MIT's code (XImUtil.c)
979  *
980  * The idea is to have faster functions than the standard XPutPixel function
981  * to build the image data. Indeed we can speed up things by suppressing tests
982  * performed for each pixel. We do the same tests but at the image level.
983  * We also assume that we use only ZPixmap images with null offsets.
984  */
985 
986 LFUNC(_putbits, void, (register char *src, int dstoffset,
987 		       register int numbits, register char *dst));
988 
989 LFUNC(_XReverse_Bytes, int, (register unsigned char *bpt, register unsigned int nb));
990 
991 static unsigned char Const _reverse_byte[0x100] = {
992     0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
993     0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
994     0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
995     0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
996     0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
997     0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
998     0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
999     0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1000     0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1001     0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1002     0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1003     0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1004     0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1005     0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1006     0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1007     0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1008     0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1009     0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1010     0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1011     0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1012     0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1013     0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1014     0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1015     0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1016     0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1017     0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1018     0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1019     0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1020     0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1021     0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1022     0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1023     0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
1024 };
1025 
1026 static int
_XReverse_Bytes(bpt,nb)1027 _XReverse_Bytes(bpt, nb)
1028     register unsigned char *bpt;
1029     register unsigned int nb;
1030 {
1031     do {
1032 	*bpt = _reverse_byte[*bpt];
1033 	bpt++;
1034     } while (--nb > 0); /* is nb user-controled? */
1035     return 0;
1036 }
1037 
1038 
1039 void
xpm_xynormalizeimagebits(bp,img)1040 xpm_xynormalizeimagebits(bp, img)
1041     register unsigned char *bp;
1042     register XImage *img;
1043 {
1044     register unsigned char c;
1045 
1046     if (img->byte_order != img->bitmap_bit_order) {
1047 	switch (img->bitmap_unit) {
1048 
1049 	case 16:
1050 	    c = *bp;
1051 	    *bp = *(bp + 1);
1052 	    *(bp + 1) = c;
1053 	    break;
1054 
1055 	case 32:
1056 	    c = *(bp + 3);
1057 	    *(bp + 3) = *bp;
1058 	    *bp = c;
1059 	    c = *(bp + 2);
1060 	    *(bp + 2) = *(bp + 1);
1061 	    *(bp + 1) = c;
1062 	    break;
1063 	}
1064     }
1065     if (img->bitmap_bit_order == MSBFirst)
1066 	_XReverse_Bytes(bp, img->bitmap_unit >> 3);
1067 }
1068 
1069 void
xpm_znormalizeimagebits(bp,img)1070 xpm_znormalizeimagebits(bp, img)
1071     register unsigned char *bp;
1072     register XImage *img;
1073 {
1074     register unsigned char c;
1075 
1076     switch (img->bits_per_pixel) {
1077 
1078     case 2:
1079 	_XReverse_Bytes(bp, 1);
1080 	break;
1081 
1082     case 4:
1083 	*bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF);
1084 	break;
1085 
1086     case 16:
1087 	c = *bp;
1088 	*bp = *(bp + 1);
1089 	*(bp + 1) = c;
1090 	break;
1091 
1092     case 24:
1093 	c = *(bp + 2);
1094 	*(bp + 2) = *bp;
1095 	*bp = c;
1096 	break;
1097 
1098     case 32:
1099 	c = *(bp + 3);
1100 	*(bp + 3) = *bp;
1101 	*bp = c;
1102 	c = *(bp + 2);
1103 	*(bp + 2) = *(bp + 1);
1104 	*(bp + 1) = c;
1105 	break;
1106     }
1107 }
1108 
1109 static unsigned char Const _lomask[0x09] = {
1110 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
1111 static unsigned char Const _himask[0x09] = {
1112 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
1113 
1114 static void
_putbits(src,dstoffset,numbits,dst)1115 _putbits(src, dstoffset, numbits, dst)
1116     register char *src;			/* address of source bit string */
1117     int dstoffset;			/* bit offset into destination;
1118 					 * range is 0-31 */
1119     register int numbits;		/* number of bits to copy to
1120 					 * destination */
1121     register char *dst;			/* address of destination bit string */
1122 {
1123     register unsigned char chlo, chhi;
1124     int hibits;
1125 
1126     dst = dst + (dstoffset >> 3);
1127     dstoffset = dstoffset & 7;
1128     hibits = 8 - dstoffset;
1129     chlo = *dst & _lomask[dstoffset];
1130     for (;;) {
1131 	chhi = (*src << dstoffset) & _himask[dstoffset];
1132 	if (numbits <= hibits) {
1133 	    chhi = chhi & _lomask[dstoffset + numbits];
1134 	    *dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi;
1135 	    break;
1136 	}
1137 	*dst = chhi | chlo;
1138 	dst++;
1139 	numbits = numbits - hibits;
1140 	chlo = (unsigned char) (*src & _himask[hibits]) >> hibits;
1141 	src++;
1142 	if (numbits <= dstoffset) {
1143 	    chlo = chlo & _lomask[numbits];
1144 	    *dst = (*dst & _himask[numbits]) | chlo;
1145 	    break;
1146 	}
1147 	numbits = numbits - dstoffset;
1148     }
1149 }
1150 
1151 /*
1152  * Default method to write pixels into a Z image data structure.
1153  * The algorithm used is:
1154  *
1155  *	copy the destination bitmap_unit or Zpixel to temp
1156  *	normalize temp if needed
1157  *	copy the pixel bits into the temp
1158  *	renormalize temp if needed
1159  *	copy the temp back into the destination image data
1160  */
1161 
1162 static void
PutImagePixels(image,width,height,pixelindex,pixels)1163 PutImagePixels(image, width, height, pixelindex, pixels)
1164     XImage *image;
1165     unsigned int width;
1166     unsigned int height;
1167     unsigned int *pixelindex;
1168     Pixel *pixels;
1169 {
1170     register char *src;
1171     register char *dst;
1172     register unsigned int *iptr;
1173     register unsigned int x, y;
1174     register char *data;
1175     Pixel pixel, px;
1176     int nbytes, depth, ibu, ibpp, i;
1177 
1178     data = image->data;
1179     iptr = pixelindex;
1180     depth = image->depth;
1181     if (depth == 1) {
1182 	ibu = image->bitmap_unit;
1183 	for (y = 0; y < height; y++) /* how can we trust height */
1184 	    for (x = 0; x < width; x++, iptr++) { /* how can we trust width */
1185 		pixel = pixels[*iptr];
1186 		for (i = 0, px = pixel; i < sizeof(unsigned long);
1187 		     i++, px >>= 8)
1188 		    ((unsigned char *) &pixel)[i] = px;
1189 		src = &data[XYINDEX(x, y, image)];
1190 		dst = (char *) &px;
1191 		px = 0;
1192 		nbytes = ibu >> 3;
1193 		for (i = nbytes; --i >= 0;)
1194 		    *dst++ = *src++;
1195 		XYNORMALIZE(&px, image);
1196 		_putbits((char *) &pixel, (x % ibu), 1, (char *) &px);
1197 		XYNORMALIZE(&px, image);
1198 		src = (char *) &px;
1199 		dst = &data[XYINDEX(x, y, image)];
1200 		for (i = nbytes; --i >= 0;)
1201 		    *dst++ = *src++;
1202 	    }
1203     } else {
1204 	ibpp = image->bits_per_pixel;
1205 	for (y = 0; y < height; y++)
1206 	    for (x = 0; x < width; x++, iptr++) {
1207 		pixel = pixels[*iptr];
1208 		if (depth == 4)
1209 		    pixel &= 0xf;
1210 		for (i = 0, px = pixel; i < sizeof(unsigned long); i++,
1211 		     px >>= 8)
1212 		    ((unsigned char *) &pixel)[i] = px;
1213 		src = &data[ZINDEX(x, y, image)];
1214 		dst = (char *) &px;
1215 		px = 0;
1216 		nbytes = (ibpp + 7) >> 3;
1217 		for (i = nbytes; --i >= 0;)
1218 		    *dst++ = *src++;
1219 		ZNORMALIZE(&px, image);
1220 		_putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
1221 		ZNORMALIZE(&px, image);
1222 		src = (char *) &px;
1223 		dst = &data[ZINDEX(x, y, image)];
1224 		for (i = nbytes; --i >= 0;)
1225 		    *dst++ = *src++;
1226 	    }
1227     }
1228 }
1229 
1230 /*
1231  * write pixels into a 32-bits Z image data structure
1232  */
1233 
1234 #if !defined(WORD64) && !defined(LONG64)
1235 /* this item is static but deterministic so let it slide; doesn't
1236  * hurt re-entrancy of this library. Note if it is actually const then would
1237  * be OK under rules of ANSI-C but probably not C++ which may not
1238  * want to allocate space for it.
1239  */
1240 static unsigned long byteorderpixel = MSBFirst << 24;
1241 
1242 #endif
1243 
1244 /*
1245    WITHOUT_SPEEDUPS is a flag to be turned on if you wish to use the original
1246    3.2e code - by default you get the speeded-up version.
1247 */
1248 
1249 static void
PutImagePixels32(image,width,height,pixelindex,pixels)1250 PutImagePixels32(image, width, height, pixelindex, pixels)
1251     XImage *image;
1252     unsigned int width;
1253     unsigned int height;
1254     unsigned int *pixelindex;
1255     Pixel *pixels;
1256 {
1257     unsigned char *data;
1258     unsigned int *iptr;
1259     unsigned int y;
1260     Pixel pixel;
1261 
1262 #ifdef WITHOUT_SPEEDUPS
1263 
1264     unsigned int x;
1265     unsigned char *addr;
1266 
1267     data = (unsigned char *) image->data;
1268     iptr = pixelindex;
1269 #if !defined(WORD64) && !defined(LONG64)
1270     if (*((char *) &byteorderpixel) == image->byte_order) {
1271 	for (y = 0; y < height; y++)
1272 	    for (x = 0; x < width; x++, iptr++) {
1273 		addr = &data[ZINDEX32(x, y, image)];
1274 		*((unsigned long *) addr) = pixels[*iptr];
1275 	    }
1276     } else
1277 #endif
1278     if (image->byte_order == MSBFirst)
1279 	for (y = 0; y < height; y++)
1280 	    for (x = 0; x < width; x++, iptr++) {
1281 		addr = &data[ZINDEX32(x, y, image)];
1282 		pixel = pixels[*iptr];
1283 		addr[0] = pixel >> 24;
1284 		addr[1] = pixel >> 16;
1285 		addr[2] = pixel >> 8;
1286 		addr[3] = pixel;
1287 	    }
1288     else
1289 	for (y = 0; y < height; y++)
1290 	    for (x = 0; x < width; x++, iptr++) {
1291 		addr = &data[ZINDEX32(x, y, image)];
1292 		pixel = pixels[*iptr];
1293 		addr[0] = pixel;
1294 		addr[1] = pixel >> 8;
1295 		addr[2] = pixel >> 16;
1296 		addr[3] = pixel >> 24;
1297 	    }
1298 
1299 #else  /* WITHOUT_SPEEDUPS */
1300 
1301     unsigned int bpl = image->bytes_per_line;
1302     unsigned char *data_ptr, *max_data;
1303 
1304     data = (unsigned char *) image->data;
1305     iptr = pixelindex;
1306 #if !defined(WORD64) && !defined(LONG64)
1307     if (*((char *) &byteorderpixel) == image->byte_order) {
1308 	for (y = 0; y < height; y++) {
1309 	    data_ptr = data;
1310 	    max_data = data_ptr + (width << 2);
1311 
1312 	    while (data_ptr < max_data) {
1313 		*((unsigned long *) data_ptr) = pixels[*(iptr++)];
1314 		data_ptr += (1 << 2);
1315 	    }
1316 	    data += bpl;
1317 	}
1318     } else
1319 #endif
1320     if (image->byte_order == MSBFirst)
1321 	for (y = 0; y < height; y++) {
1322 	    data_ptr = data;
1323 	    max_data = data_ptr + (width << 2);
1324 
1325 	    while (data_ptr < max_data) {
1326 		pixel = pixels[*(iptr++)];
1327 
1328 		*data_ptr++ = pixel >> 24;
1329 		*data_ptr++ = pixel >> 16;
1330 		*data_ptr++ = pixel >> 8;
1331 		*data_ptr++ = pixel;
1332 
1333 	    }
1334 	    data += bpl;
1335 	}
1336     else
1337 	for (y = 0; y < height; y++) {
1338 	    data_ptr = data;
1339 	    max_data = data_ptr + (width << 2);
1340 
1341 	    while (data_ptr < max_data) {
1342 		pixel = pixels[*(iptr++)];
1343 
1344 		*data_ptr++ = pixel;
1345 		*data_ptr++ = pixel >> 8;
1346 		*data_ptr++ = pixel >> 16;
1347 		*data_ptr++ = pixel >> 24;
1348 	    }
1349 	    data += bpl;
1350 	}
1351 
1352 #endif /* WITHOUT_SPEEDUPS */
1353 }
1354 
1355 /*
1356  * write pixels into a 16-bits Z image data structure
1357  */
1358 
1359 static void
PutImagePixels16(image,width,height,pixelindex,pixels)1360 PutImagePixels16(image, width, height, pixelindex, pixels)
1361     XImage *image;
1362     unsigned int width;
1363     unsigned int height;
1364     unsigned int *pixelindex;
1365     Pixel *pixels;
1366 {
1367     unsigned char *data;
1368     unsigned int *iptr;
1369     unsigned int y;
1370 
1371 #ifdef WITHOUT_SPEEDUPS
1372 
1373     unsigned int x;
1374     unsigned char *addr;
1375 
1376     data = (unsigned char *) image->data;
1377     iptr = pixelindex;
1378     if (image->byte_order == MSBFirst)
1379 	for (y = 0; y < height; y++)
1380 	    for (x = 0; x < width; x++, iptr++) {
1381 		addr = &data[ZINDEX16(x, y, image)];
1382 		addr[0] = pixels[*iptr] >> 8;
1383 		addr[1] = pixels[*iptr];
1384 	    }
1385     else
1386 	for (y = 0; y < height; y++)
1387 	    for (x = 0; x < width; x++, iptr++) {
1388 		addr = &data[ZINDEX16(x, y, image)];
1389 		addr[0] = pixels[*iptr];
1390 		addr[1] = pixels[*iptr] >> 8;
1391 	    }
1392 
1393 #else  /* WITHOUT_SPEEDUPS */
1394 
1395     Pixel pixel;
1396 
1397     unsigned int bpl = image->bytes_per_line;
1398     unsigned char *data_ptr, *max_data;
1399 
1400     data = (unsigned char *) image->data;
1401     iptr = pixelindex;
1402     if (image->byte_order == MSBFirst)
1403 	for (y = 0; y < height; y++) {
1404 	    data_ptr = data;
1405 	    max_data = data_ptr + (width << 1);
1406 
1407 	    while (data_ptr < max_data) {
1408 		pixel = pixels[*(iptr++)];
1409 
1410 		data_ptr[0] = pixel >> 8;
1411 		data_ptr[1] = pixel;
1412 
1413 		data_ptr += (1 << 1);
1414 	    }
1415 	    data += bpl;
1416 	}
1417     else
1418 	for (y = 0; y < height; y++) {
1419 	    data_ptr = data;
1420 	    max_data = data_ptr + (width << 1);
1421 
1422 	    while (data_ptr < max_data) {
1423 		pixel = pixels[*(iptr++)];
1424 
1425 		data_ptr[0] = pixel;
1426 		data_ptr[1] = pixel >> 8;
1427 
1428 		data_ptr += (1 << 1);
1429 	    }
1430 	    data += bpl;
1431 	}
1432 
1433 #endif /* WITHOUT_SPEEDUPS */
1434 }
1435 
1436 /*
1437  * write pixels into a 8-bits Z image data structure
1438  */
1439 
1440 static void
PutImagePixels8(image,width,height,pixelindex,pixels)1441 PutImagePixels8(image, width, height, pixelindex, pixels)
1442     XImage *image;
1443     unsigned int width;
1444     unsigned int height;
1445     unsigned int *pixelindex;
1446     Pixel *pixels;
1447 {
1448     char *data;
1449     unsigned int *iptr;
1450     unsigned int y;
1451 
1452 #ifdef WITHOUT_SPEEDUPS
1453 
1454     unsigned int x;
1455 
1456     data = image->data;
1457     iptr = pixelindex;
1458     for (y = 0; y < height; y++)
1459 	for (x = 0; x < width; x++, iptr++)
1460 	    data[ZINDEX8(x, y, image)] = pixels[*iptr];
1461 
1462 #else  /* WITHOUT_SPEEDUPS */
1463 
1464     unsigned int bpl = image->bytes_per_line;
1465     char *data_ptr, *max_data;
1466 
1467     data = image->data;
1468     iptr = pixelindex;
1469 
1470     for (y = 0; y < height; y++) {
1471 	data_ptr = data;
1472 	max_data = data_ptr + width;
1473 
1474 	while (data_ptr < max_data)
1475 	    *(data_ptr++) = pixels[*(iptr++)];
1476 
1477 	data += bpl;
1478     }
1479 
1480 #endif /* WITHOUT_SPEEDUPS */
1481 }
1482 
1483 /*
1484  * write pixels into a 1-bit depth image data structure and **offset null**
1485  */
1486 
1487 static void
PutImagePixels1(image,width,height,pixelindex,pixels)1488 PutImagePixels1(image, width, height, pixelindex, pixels)
1489     XImage *image;
1490     unsigned int width;
1491     unsigned int height;
1492     unsigned int *pixelindex;
1493     Pixel *pixels;
1494 {
1495     if (image->byte_order != image->bitmap_bit_order)
1496 	PutImagePixels(image, width, height, pixelindex, pixels);
1497     else {
1498 	unsigned int *iptr;
1499 	unsigned int y;
1500 	char *data;
1501 
1502 #ifdef WITHOUT_SPEEDUPS
1503 
1504 	unsigned int x;
1505 
1506 	data = image->data;
1507 	iptr = pixelindex;
1508 	if (image->bitmap_bit_order == MSBFirst)
1509 	    for (y = 0; y < height; y++)
1510 		for (x = 0; x < width; x++, iptr++) {
1511 		    if (pixels[*iptr] & 1)
1512 			data[ZINDEX1(x, y, image)] |= 0x80 >> (x & 7);
1513 		    else
1514 			data[ZINDEX1(x, y, image)] &= ~(0x80 >> (x & 7));
1515 		}
1516 	else
1517 	    for (y = 0; y < height; y++)
1518 		for (x = 0; x < width; x++, iptr++) {
1519 		    if (pixels[*iptr] & 1)
1520 			data[ZINDEX1(x, y, image)] |= 1 << (x & 7);
1521 		    else
1522 			data[ZINDEX1(x, y, image)] &= ~(1 << (x & 7));
1523 		}
1524 
1525 #else  /* WITHOUT_SPEEDUPS */
1526 
1527 	char value;
1528 	char *data_ptr, *max_data;
1529 	int bpl = image->bytes_per_line;
1530 	int diff, count;
1531 
1532 	data = image->data;
1533 	iptr = pixelindex;
1534 
1535 	diff = width & 7;
1536 	width >>= 3;
1537 
1538 	if (image->bitmap_bit_order == MSBFirst)
1539 	    for (y = 0; y < height; y++) {
1540 		data_ptr = data;
1541 		max_data = data_ptr + width;
1542 		while (data_ptr < max_data) {
1543 		    value = 0;
1544 
1545 		    value = (value << 1) | (pixels[*(iptr++)] & 1);
1546 		    value = (value << 1) | (pixels[*(iptr++)] & 1);
1547 		    value = (value << 1) | (pixels[*(iptr++)] & 1);
1548 		    value = (value << 1) | (pixels[*(iptr++)] & 1);
1549 		    value = (value << 1) | (pixels[*(iptr++)] & 1);
1550 		    value = (value << 1) | (pixels[*(iptr++)] & 1);
1551 		    value = (value << 1) | (pixels[*(iptr++)] & 1);
1552 		    value = (value << 1) | (pixels[*(iptr++)] & 1);
1553 
1554 		    *(data_ptr++) = value;
1555 		}
1556 		if (diff) {
1557 		    value = 0;
1558 		    for (count = 0; count < diff; count++) {
1559 			if (pixels[*(iptr++)] & 1)
1560 			    value |= (0x80 >> count);
1561 		    }
1562 		    *(data_ptr) = value;
1563 		}
1564 		data += bpl;
1565 	    }
1566 	else
1567 	    for (y = 0; y < height; y++) {
1568 		data_ptr = data;
1569 		max_data = data_ptr + width;
1570 		while (data_ptr < max_data) {
1571 		    value = 0;
1572 		    iptr += 8;
1573 
1574 		    value = (value << 1) | (pixels[*(--iptr)] & 1);
1575 		    value = (value << 1) | (pixels[*(--iptr)] & 1);
1576 		    value = (value << 1) | (pixels[*(--iptr)] & 1);
1577 		    value = (value << 1) | (pixels[*(--iptr)] & 1);
1578 		    value = (value << 1) | (pixels[*(--iptr)] & 1);
1579 		    value = (value << 1) | (pixels[*(--iptr)] & 1);
1580 		    value = (value << 1) | (pixels[*(--iptr)] & 1);
1581 		    value = (value << 1) | (pixels[*(--iptr)] & 1);
1582 
1583 		    iptr += 8;
1584 		    *(data_ptr++) = value;
1585 		}
1586 		if (diff) {
1587 		    value = 0;
1588 		    for (count = 0; count < diff; count++) {
1589 			if (pixels[*(iptr++)] & 1)
1590 			    value |= (1 << count);
1591 		    }
1592 		    *(data_ptr) = value;
1593 		}
1594 		data += bpl;
1595 	    }
1596 
1597 #endif /* WITHOUT_SPEEDUPS */
1598     }
1599 }
1600 
1601 int
XpmCreatePixmapFromXpmImage(display,d,image,pixmap_return,shapemask_return,attributes)1602 XpmCreatePixmapFromXpmImage(display, d, image,
1603 			    pixmap_return, shapemask_return, attributes)
1604     Display *display;
1605     Drawable d;
1606     XpmImage *image;
1607     Pixmap *pixmap_return;
1608     Pixmap *shapemask_return;
1609     XpmAttributes *attributes;
1610 {
1611     XImage *ximage, *shapeimage;
1612     int ErrorStatus;
1613 
1614     /* initialize return values */
1615     if (pixmap_return)
1616 	*pixmap_return = 0;
1617     if (shapemask_return)
1618 	*shapemask_return = 0;
1619 
1620     /* create the ximages */
1621     ErrorStatus = XpmCreateImageFromXpmImage(display, image,
1622 					     (pixmap_return ? &ximage : NULL),
1623 					     (shapemask_return ?
1624 					      &shapeimage : NULL),
1625 					     attributes);
1626     if (ErrorStatus < 0)
1627 	return (ErrorStatus);
1628 
1629     /* create the pixmaps and destroy images */
1630     if (pixmap_return && ximage) {
1631 	xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
1632 	XDestroyImage(ximage);
1633     }
1634     if (shapemask_return && shapeimage) {
1635 	xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
1636 	XDestroyImage(shapeimage);
1637     }
1638     return (ErrorStatus);
1639 }
1640 
1641 #else  /* FOR_MSW part follows */
1642 static void
MSWPutImagePixels(dc,image,width,height,pixelindex,pixels)1643 MSWPutImagePixels(dc, image, width, height, pixelindex, pixels)
1644     Display *dc;
1645     XImage *image;
1646     unsigned int width;
1647     unsigned int height;
1648     unsigned int *pixelindex;
1649     Pixel *pixels;
1650 {
1651     unsigned int *data = pixelindex;
1652     unsigned int x, y;
1653 
1654     SelectObject(*dc, image->bitmap);
1655     for (y = 0; y < height; y++) {
1656 	for (x = 0; x < width; x++) {
1657 	    SetPixel(*dc, x, y, pixels[*(data++)]); /* data is [x+y*width] */
1658 	}
1659     }
1660 }
1661 
1662 #endif /* FOR_MSW */
1663 
1664 
1665 
1666 #ifndef FOR_MSW
1667 
1668 static int
PutPixel1(ximage,x,y,pixel)1669 PutPixel1(ximage, x, y, pixel)
1670     register XImage *ximage;
1671     int x;
1672     int y;
1673     unsigned long pixel;
1674 {
1675     register char *src;
1676     register char *dst;
1677     register int i;
1678     register char *data;
1679     Pixel px;
1680     int nbytes;
1681 
1682     if(x < 0 || y < 0)
1683     	return 0;
1684 
1685     for (i=0, px=pixel; i<sizeof(unsigned long); i++, px>>=8)
1686 	((unsigned char *)&pixel)[i] = px;
1687     src = &ximage->data[XYINDEX(x, y, ximage)];
1688     dst = (char *)&px;
1689     px = 0;
1690     nbytes = ximage->bitmap_unit >> 3;
1691     for (i = nbytes; --i >= 0; ) *dst++ = *src++;
1692     XYNORMALIZE(&px, ximage);
1693     i = ((x + ximage->xoffset) % ximage->bitmap_unit);
1694     _putbits ((char *)&pixel, i, 1, (char *)&px);
1695     XYNORMALIZE(&px, ximage);
1696     src = (char *) &px;
1697     dst = &ximage->data[XYINDEX(x, y, ximage)];
1698     for (i = nbytes; --i >= 0; )
1699 	*dst++ = *src++;
1700 
1701     return 1;
1702 }
1703 
1704 static int
PutPixel(ximage,x,y,pixel)1705 PutPixel(ximage, x, y, pixel)
1706     register XImage *ximage;
1707     int x;
1708     int y;
1709     unsigned long pixel;
1710 {
1711     register char *src;
1712     register char *dst;
1713     register int i;
1714     register char *data;
1715     Pixel px;
1716     unsigned int nbytes, ibpp;
1717 
1718     if(x < 0 || y < 0)
1719     	return 0;
1720 
1721     ibpp = ximage->bits_per_pixel;
1722     if (ximage->depth == 4)
1723 	pixel &= 0xf;
1724     for (i = 0, px = pixel; i < sizeof(unsigned long); i++, px >>= 8)
1725 	((unsigned char *) &pixel)[i] = px;
1726     src = &ximage->data[ZINDEX(x, y, ximage)];
1727     dst = (char *) &px;
1728     px = 0;
1729     nbytes = (ibpp + 7) >> 3;
1730     for (i = nbytes; --i >= 0;)
1731 	*dst++ = *src++;
1732     ZNORMALIZE(&px, ximage);
1733     _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
1734     ZNORMALIZE(&px, ximage);
1735     src = (char *) &px;
1736     dst = &ximage->data[ZINDEX(x, y, ximage)];
1737     for (i = nbytes; --i >= 0;)
1738 	*dst++ = *src++;
1739 
1740     return 1;
1741 }
1742 
1743 static int
PutPixel32(ximage,x,y,pixel)1744 PutPixel32(ximage, x, y, pixel)
1745     register XImage *ximage;
1746     int x;
1747     int y;
1748     unsigned long pixel;
1749 {
1750     unsigned char *addr;
1751 
1752     if(x < 0 || y < 0)
1753     	return 0;
1754 
1755     addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1756     *((unsigned long *)addr) = pixel;
1757     return 1;
1758 }
1759 
1760 static int
PutPixel32MSB(ximage,x,y,pixel)1761 PutPixel32MSB(ximage, x, y, pixel)
1762     register XImage *ximage;
1763     int x;
1764     int y;
1765     unsigned long pixel;
1766 {
1767     unsigned char *addr;
1768 
1769     if(x < 0 || y < 0)
1770     	return 0;
1771 
1772     addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1773     addr[0] = pixel >> 24;
1774     addr[1] = pixel >> 16;
1775     addr[2] = pixel >> 8;
1776     addr[3] = pixel;
1777     return 1;
1778 }
1779 
1780 static int
PutPixel32LSB(ximage,x,y,pixel)1781 PutPixel32LSB(ximage, x, y, pixel)
1782     register XImage *ximage;
1783     int x;
1784     int y;
1785     unsigned long pixel;
1786 {
1787     unsigned char *addr;
1788 
1789     if(x < 0 || y < 0)
1790     	return 0;
1791 
1792     addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1793     addr[3] = pixel >> 24;
1794     addr[2] = pixel >> 16;
1795     addr[1] = pixel >> 8;
1796     addr[0] = pixel;
1797     return 1;
1798 }
1799 
1800 static int
PutPixel16MSB(ximage,x,y,pixel)1801 PutPixel16MSB(ximage, x, y, pixel)
1802     register XImage *ximage;
1803     int x;
1804     int y;
1805     unsigned long pixel;
1806 {
1807     unsigned char *addr;
1808 
1809     if(x < 0 || y < 0)
1810     	return 0;
1811 
1812     addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)];
1813     addr[0] = pixel >> 8;
1814     addr[1] = pixel;
1815     return 1;
1816 }
1817 
1818 static int
PutPixel16LSB(ximage,x,y,pixel)1819 PutPixel16LSB(ximage, x, y, pixel)
1820     register XImage *ximage;
1821     int x;
1822     int y;
1823     unsigned long pixel;
1824 {
1825     unsigned char *addr;
1826 
1827     if(x < 0 || y < 0)
1828     	return 0;
1829 
1830     addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)];
1831     addr[1] = pixel >> 8;
1832     addr[0] = pixel;
1833     return 1;
1834 }
1835 
1836 static int
PutPixel8(ximage,x,y,pixel)1837 PutPixel8(ximage, x, y, pixel)
1838     register XImage *ximage;
1839     int x;
1840     int y;
1841     unsigned long pixel;
1842 {
1843     if(x < 0 || y < 0)
1844     	return 0;
1845 
1846     ximage->data[ZINDEX8(x, y, ximage)] = pixel;
1847     return 1;
1848 }
1849 
1850 static int
PutPixel1MSB(ximage,x,y,pixel)1851 PutPixel1MSB(ximage, x, y, pixel)
1852     register XImage *ximage;
1853     int x;
1854     int y;
1855     unsigned long pixel;
1856 {
1857     if(x < 0 || y < 0)
1858     	return 0;
1859 
1860     if (pixel & 1)
1861 	ximage->data[ZINDEX1(x, y, ximage)] |= 0x80 >> (x & 7);
1862     else
1863 	ximage->data[ZINDEX1(x, y, ximage)] &= ~(0x80 >> (x & 7));
1864     return 1;
1865 }
1866 
1867 static int
PutPixel1LSB(ximage,x,y,pixel)1868 PutPixel1LSB(ximage, x, y, pixel)
1869     register XImage *ximage;
1870     int x;
1871     int y;
1872     unsigned long pixel;
1873 {
1874     if(x < 0 || y < 0)
1875     	return 0;
1876 
1877     if (pixel & 1)
1878 	ximage->data[ZINDEX1(x, y, ximage)] |= 1 << (x & 7);
1879     else
1880 	ximage->data[ZINDEX1(x, y, ximage)] &= ~(1 << (x & 7));
1881     return 1;
1882 }
1883 
1884 #endif /* FOR_MSW */
1885 
1886 /* function call in case of error, frees only locally allocated variables */
1887 #undef RETURN
1888 #define RETURN(status) \
1889 { \
1890     if (USE_HASHTABLE) xpmHashTableFree(&hashtable); \
1891     if (colorTable) xpmFreeColorTable(colorTable, ncolors); \
1892     if (hints_cmt)  XpmFree(hints_cmt); \
1893     if (colors_cmt) XpmFree(colors_cmt); \
1894     if (pixels_cmt) XpmFree(pixels_cmt); \
1895     if (ximage) XDestroyImage(ximage); \
1896     if (shapeimage) XDestroyImage(shapeimage); \
1897     if (image_pixels) XpmFree(image_pixels); \
1898     if (mask_pixels) XpmFree(mask_pixels); \
1899     if (nalloc_pixels) \
1900 	(*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL); \
1901     if (alloc_pixels) XpmFree(alloc_pixels); \
1902     if (used_pixels) XpmFree(used_pixels); \
1903     return(status); \
1904 }
1905 
1906 /*
1907  * This function parses an Xpm file or data and directly create an XImage
1908  */
1909 int
xpmParseDataAndCreate(display,data,image_return,shapeimage_return,image,info,attributes)1910 xpmParseDataAndCreate(display, data, image_return, shapeimage_return,
1911 		      image, info, attributes)
1912     Display *display;
1913     xpmData *data;
1914     XImage **image_return;
1915     XImage **shapeimage_return;
1916     XpmImage *image;
1917     XpmInfo *info;
1918     XpmAttributes *attributes;
1919 {
1920     /* variables stored in the XpmAttributes structure */
1921     Visual *visual;
1922     Colormap colormap;
1923     unsigned int depth;
1924     int bitmap_format;
1925     XpmFreeColorsFunc freeColors;
1926     void *closure;
1927 
1928     /* variables to return */
1929     XImage *ximage = NULL;
1930     XImage *shapeimage = NULL;
1931     unsigned int mask_pixel_index = XpmUndefPixel;
1932 
1933     /* calculation variables */
1934     Pixel *image_pixels = NULL;
1935     Pixel *mask_pixels = NULL;
1936     Pixel *alloc_pixels = NULL;
1937     Pixel *used_pixels = NULL;
1938     unsigned int nalloc_pixels = 0;
1939     unsigned int nused_pixels = 0;
1940     unsigned int width, height, ncolors, cpp;
1941     unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0;
1942     XpmColor *colorTable = NULL;
1943     char *hints_cmt = NULL;
1944     char *colors_cmt = NULL;
1945     char *pixels_cmt = NULL;
1946 
1947     unsigned int cmts;
1948     int ErrorStatus;
1949     xpmHashTable hashtable;
1950 
1951 
1952     /* initialize return values */
1953     if (image_return)
1954 	*image_return = NULL;
1955     if (shapeimage_return)
1956 	*shapeimage_return = NULL;
1957 
1958 
1959     /* retrieve information from the XpmAttributes */
1960     if (attributes && (attributes->valuemask & XpmVisual))
1961 	visual = attributes->visual;
1962     else
1963 	visual = XDefaultVisual(display, XDefaultScreen(display));
1964 
1965     if (attributes && (attributes->valuemask & XpmColormap))
1966 	colormap = attributes->colormap;
1967     else
1968 	colormap = XDefaultColormap(display, XDefaultScreen(display));
1969 
1970     if (attributes && (attributes->valuemask & XpmDepth))
1971 	depth = attributes->depth;
1972     else
1973 	depth = XDefaultDepth(display, XDefaultScreen(display));
1974 
1975     if (attributes && (attributes->valuemask & XpmBitmapFormat))
1976 	bitmap_format = attributes->bitmap_format;
1977     else
1978 	bitmap_format = ZPixmap;
1979 
1980     if (attributes && (attributes->valuemask & XpmFreeColors))
1981 	freeColors = attributes->free_colors;
1982     else
1983 	freeColors = FreeColors;
1984     if (attributes && (attributes->valuemask & XpmColorClosure))
1985 	closure = attributes->color_closure;
1986     else
1987 	closure = NULL;
1988 
1989     cmts = info && (info->valuemask & XpmReturnComments);
1990 
1991     /*
1992      * parse the header
1993      */
1994     ErrorStatus = xpmParseHeader(data);
1995     if (ErrorStatus != XpmSuccess)
1996 	return (ErrorStatus);
1997 
1998     /*
1999      * read values
2000      */
2001     ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp,
2002 				 &x_hotspot, &y_hotspot, &hotspot,
2003 				 &extensions);
2004     if (ErrorStatus != XpmSuccess)
2005 	return (ErrorStatus);
2006 
2007     /*
2008      * store the hints comment line
2009      */
2010     if (cmts)
2011 	xpmGetCmt(data, &hints_cmt);
2012 
2013     /*
2014      * init the hastable
2015      */
2016     if (USE_HASHTABLE) {
2017 	ErrorStatus = xpmHashTableInit(&hashtable);
2018 	if (ErrorStatus != XpmSuccess)
2019 	    return (ErrorStatus);
2020     }
2021 
2022     /*
2023      * read colors
2024      */
2025     ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable);
2026     if (ErrorStatus != XpmSuccess)
2027 	RETURN(ErrorStatus);
2028 
2029     /*
2030      * store the colors comment line
2031      */
2032     if (cmts)
2033 	xpmGetCmt(data, &colors_cmt);
2034 
2035     /* malloc pixels index tables */
2036     if (ncolors >= UINT_MAX / sizeof(Pixel))
2037       RETURN (XpmNoMemory);
2038 
2039     image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2040     if (!image_pixels)
2041 	RETURN(XpmNoMemory);
2042 
2043     mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2044     if (!mask_pixels)
2045 	RETURN(XpmNoMemory);
2046 
2047     /* maximum of allocated pixels will be the number of colors */
2048     alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2049     if (!alloc_pixels)
2050 	RETURN(XpmNoMemory);
2051 
2052     /* maximum of allocated pixels will be the number of colors */
2053     used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2054     if (!used_pixels)
2055 	RETURN(XpmNoMemory);
2056 
2057     /* get pixel colors, store them in index tables */
2058     ErrorStatus = CreateColors(display, attributes, colorTable, ncolors,
2059 			       image_pixels, mask_pixels, &mask_pixel_index,
2060 			       alloc_pixels, &nalloc_pixels, used_pixels,
2061 			       &nused_pixels);
2062 
2063     if (ErrorStatus != XpmSuccess
2064 	&& (ErrorStatus < 0 || (attributes
2065 				&& (attributes->valuemask & XpmExactColors)
2066 				&& attributes->exactColors)))
2067 	RETURN(ErrorStatus);
2068 
2069     /* now create the ximage */
2070     if (image_return) {
2071 	ErrorStatus = CreateXImage(display, visual, depth,
2072 				   (depth == 1 ? bitmap_format : ZPixmap),
2073 				   width, height, &ximage);
2074 	if (ErrorStatus != XpmSuccess)
2075 	    RETURN(ErrorStatus);
2076 
2077 #ifndef FOR_MSW
2078 
2079 	/*
2080 	 * set the XImage pointer function, to be used with XPutPixel,
2081 	 * to an internal optimized function
2082 	 */
2083 
2084 	if (ximage->bits_per_pixel == 8)
2085 	    ximage->f.put_pixel = PutPixel8;
2086 	else if (((ximage->bits_per_pixel | ximage->depth) == 1) &&
2087 		 (ximage->byte_order == ximage->bitmap_bit_order))
2088 	    if (ximage->bitmap_bit_order == MSBFirst)
2089 		ximage->f.put_pixel = PutPixel1MSB;
2090 	    else
2091 		ximage->f.put_pixel = PutPixel1LSB;
2092 	else if (ximage->bits_per_pixel == 16)
2093 	    if (ximage->bitmap_bit_order == MSBFirst)
2094 		ximage->f.put_pixel = PutPixel16MSB;
2095 	    else
2096 		ximage->f.put_pixel = PutPixel16LSB;
2097 	else if (ximage->bits_per_pixel == 32)
2098 #if !defined(WORD64) && !defined(LONG64)
2099 	    if (*((char *)&byteorderpixel) == ximage->byte_order)
2100 		ximage->f.put_pixel = PutPixel32;
2101 	    else
2102 #endif
2103 		if (ximage->bitmap_bit_order == MSBFirst)
2104 		    ximage->f.put_pixel = PutPixel32MSB;
2105 		else
2106 		    ximage->f.put_pixel = PutPixel32LSB;
2107 	else if ((ximage->bits_per_pixel | ximage->depth) == 1)
2108 	    ximage->f.put_pixel = PutPixel1;
2109 	else
2110 	    ximage->f.put_pixel = PutPixel;
2111 #endif
2112     }
2113     /* create the shape mask image */
2114     if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
2115 	ErrorStatus = CreateXImage(display, visual, 1, bitmap_format,
2116 				   width, height, &shapeimage);
2117 	if (ErrorStatus != XpmSuccess)
2118 	    RETURN(ErrorStatus);
2119 
2120 #ifndef FOR_MSW
2121 	if (shapeimage->bitmap_bit_order == MSBFirst)
2122 	    shapeimage->f.put_pixel = PutPixel1MSB;
2123 	else
2124 	    shapeimage->f.put_pixel = PutPixel1LSB;
2125 #endif
2126     }
2127 
2128     /*
2129      * read pixels and put them in the XImage
2130      */
2131 #ifndef FOR_MSW
2132     ErrorStatus = ParseAndPutPixels(data, width, height, ncolors, cpp,
2133 #else
2134     ErrorStatus = ParseAndPutPixels(display, data, width, height, ncolors, cpp,
2135 #endif
2136 				    colorTable, &hashtable,
2137 				    ximage, image_pixels,
2138 				    shapeimage, mask_pixels);
2139     XpmFree(image_pixels);
2140     image_pixels = NULL;
2141     XpmFree(mask_pixels);
2142     mask_pixels = NULL;
2143 
2144     /*
2145      * free the hastable
2146      */
2147     if (ErrorStatus != XpmSuccess)
2148 	RETURN(ErrorStatus)
2149     else if (USE_HASHTABLE)
2150 	xpmHashTableFree(&hashtable);
2151 
2152     /*
2153      * store the pixels comment line
2154      */
2155     if (cmts)
2156 	xpmGetCmt(data, &pixels_cmt);
2157 
2158     /*
2159      * parse extensions
2160      */
2161     if (info && (info->valuemask & XpmReturnExtensions))
2162     {
2163 	if (extensions) {
2164 	    ErrorStatus = xpmParseExtensions(data, &info->extensions,
2165 					     &info->nextensions);
2166 	    if (ErrorStatus != XpmSuccess)
2167 		RETURN(ErrorStatus);
2168 	} else {
2169 	    info->extensions = NULL;
2170 	    info->nextensions = 0;
2171 	}
2172     }
2173 
2174     /*
2175      * store found informations in the XpmImage structure
2176      */
2177     image->width = width;
2178     image->height = height;
2179     image->cpp = cpp;
2180     image->ncolors = ncolors;
2181     image->colorTable = colorTable;
2182     image->data = NULL;
2183 
2184     if (info) {
2185 	if (cmts) {
2186 	    info->hints_cmt = hints_cmt;
2187 	    info->colors_cmt = colors_cmt;
2188 	    info->pixels_cmt = pixels_cmt;
2189 	}
2190 	if (hotspot) {
2191 	    info->x_hotspot = x_hotspot;
2192 	    info->y_hotspot = y_hotspot;
2193 	    info->valuemask |= XpmHotspot;
2194 	}
2195     }
2196     /* if requested return used pixels in the XpmAttributes structure */
2197     if (attributes && (attributes->valuemask & XpmReturnPixels ||
2198 /* 3.2 backward compatibility code */
2199 	attributes->valuemask & XpmReturnInfos)) {
2200 /* end 3.2 bc */
2201 	attributes->pixels = used_pixels;
2202 	attributes->npixels = nused_pixels;
2203 	attributes->mask_pixel = mask_pixel_index;
2204     } else
2205 	XpmFree(used_pixels);
2206 
2207     /* if requested return alloc'ed pixels in the XpmAttributes structure */
2208     if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
2209 	attributes->alloc_pixels = alloc_pixels;
2210 	attributes->nalloc_pixels = nalloc_pixels;
2211     } else
2212 	XpmFree(alloc_pixels);
2213 
2214     /* return created images */
2215     if (image_return)
2216 	*image_return = ximage;
2217     if (shapeimage_return)
2218 	*shapeimage_return = shapeimage;
2219 
2220     return (XpmSuccess);
2221 }
2222 
2223 #ifndef FOR_MSW
2224 static int
ParseAndPutPixels(data,width,height,ncolors,cpp,colorTable,hashtable,image,image_pixels,shapeimage,shape_pixels)2225 ParseAndPutPixels(data, width, height, ncolors, cpp, colorTable, hashtable,
2226 		  image, image_pixels, shapeimage, shape_pixels)
2227 #else  /* FOR_MSW */
2228 static int
2229 ParseAndPutPixels(dc, data, width, height, ncolors, cpp, colorTable, hashtable,
2230 		  image, image_pixels, shapeimage, shape_pixels)
2231     Display *dc;
2232 #endif
2233     xpmData *data;
2234     unsigned int width;
2235     unsigned int height;
2236     unsigned int ncolors;
2237     unsigned int cpp;
2238     XpmColor *colorTable;
2239     xpmHashTable *hashtable;
2240     XImage *image;
2241     Pixel *image_pixels;
2242     XImage *shapeimage;
2243     Pixel *shape_pixels;
2244 {
2245     unsigned int a, x, y;
2246 
2247     switch (cpp) {
2248 
2249     case (1):				/* Optimize for single character
2250 					 * colors */
2251 	{
2252 	    unsigned short colidx[256];
2253 
2254  	    if (ncolors > 256)
2255  		return (XpmFileInvalid);
2256 
2257 	    bzero((char *)colidx, 256 * sizeof(short));
2258 	    for (a = 0; a < ncolors; a++)
2259 		colidx[(unsigned char)colorTable[a].string[0]] = a + 1;
2260 
2261 	    for (y = 0; y < height; y++) {
2262 		xpmNextString(data);
2263 		for (x = 0; x < width; x++) {
2264 		    int c = xpmGetC(data);
2265 
2266 		    if (c > 0 && c < 256 && colidx[c] != 0) {
2267 #ifndef FOR_MSW
2268 			XPutPixel(image, x, y, image_pixels[colidx[c] - 1]);
2269 			if (shapeimage)
2270 			    XPutPixel(shapeimage, x, y,
2271 				      shape_pixels[colidx[c] - 1]);
2272 #else
2273 			SelectObject(*dc, image->bitmap);
2274 			SetPixel(*dc, x, y, image_pixels[colidx[c] - 1]);
2275 			if (shapeimage) {
2276 			    SelectObject(*dc, shapeimage->bitmap);
2277 			    SetPixel(*dc, x, y, shape_pixels[colidx[c] - 1]);
2278 			}
2279 #endif
2280 		    } else
2281 			return (XpmFileInvalid);
2282 		}
2283 	    }
2284 	}
2285 	break;
2286 
2287     case (2):				/* Optimize for double character
2288 					 * colors */
2289 	{
2290 
2291 /* free all allocated pointers at all exits */
2292 #define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
2293 if (cidx[f]) XpmFree(cidx[f]);}
2294 
2295 	    /* array of pointers malloced by need */
2296 	    unsigned short *cidx[256];
2297 	    unsigned int char1;
2298 
2299 	    bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */
2300 	    for (a = 0; a < ncolors; a++) {
2301 		char1 = (unsigned char) colorTable[a].string[0];
2302 		if (cidx[char1] == NULL) { /* get new memory */
2303 		    cidx[char1] = (unsigned short *)
2304 			XpmCalloc(256, sizeof(unsigned short));
2305 		    if (cidx[char1] == NULL) { /* new block failed */
2306 			FREE_CIDX;
2307 			return (XpmNoMemory);
2308 		    }
2309 		}
2310 		cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1;
2311 	    }
2312 
2313 	    for (y = 0; y < height; y++) {
2314 		xpmNextString(data);
2315 		for (x = 0; x < width; x++) {
2316 		    int cc1 = xpmGetC(data);
2317 		    if (cc1 > 0 && cc1 < 256) {
2318 			int cc2 = xpmGetC(data);
2319 			if (cc2 > 0 && cc2 < 256 && cidx[cc1][cc2] != 0) {
2320 #ifndef FOR_MSW
2321 			    XPutPixel(image, x, y,
2322 				      image_pixels[cidx[cc1][cc2] - 1]);
2323 			    if (shapeimage)
2324 				XPutPixel(shapeimage, x, y,
2325 					  shape_pixels[cidx[cc1][cc2] - 1]);
2326 #else
2327 			SelectObject(*dc, image->bitmap);
2328 			SetPixel(*dc, x, y, image_pixels[cidx[cc1][cc2] - 1]);
2329 			if (shapeimage) {
2330 			    SelectObject(*dc, shapeimage->bitmap);
2331 			    SetPixel(*dc, x, y,
2332 				     shape_pixels[cidx[cc1][cc2] - 1]);
2333 			}
2334 #endif
2335 			} else {
2336 			    FREE_CIDX;
2337 			    return (XpmFileInvalid);
2338 			}
2339 		    } else {
2340 			FREE_CIDX;
2341 			return (XpmFileInvalid);
2342 		    }
2343 		}
2344 	    }
2345 	    FREE_CIDX;
2346 	}
2347 	break;
2348 
2349     default:				/* Non-optimized case of long color
2350 					 * names */
2351 	{
2352 	    char *s;
2353 	    char buf[BUFSIZ];
2354 
2355 	    if (cpp >= sizeof(buf))
2356 		return (XpmFileInvalid);
2357 
2358 	    buf[cpp] = '\0';
2359 	    if (USE_HASHTABLE) {
2360 		xpmHashAtom *slot;
2361 
2362 		for (y = 0; y < height; y++) {
2363 		    xpmNextString(data);
2364 		    for (x = 0; x < width; x++) {
2365 			for (a = 0, s = buf; a < cpp; a++, s++)
2366 			    *s = xpmGetC(data);
2367 			slot = xpmHashSlot(hashtable, buf);
2368 			if (!*slot)	/* no color matches */
2369 			    return (XpmFileInvalid);
2370 #ifndef FOR_MSW
2371 			XPutPixel(image, x, y,
2372 				  image_pixels[HashColorIndex(slot)]);
2373 			if (shapeimage)
2374 			    XPutPixel(shapeimage, x, y,
2375 				      shape_pixels[HashColorIndex(slot)]);
2376 #else
2377 			SelectObject(*dc, image->bitmap);
2378 			SetPixel(*dc, x, y,
2379 				 image_pixels[HashColorIndex(slot)]);
2380 			if (shapeimage) {
2381 			    SelectObject(*dc, shapeimage->bitmap);
2382 			    SetPixel(*dc, x, y,
2383 				     shape_pixels[HashColorIndex(slot)]);
2384 			}
2385 #endif
2386 		    }
2387 		}
2388 	    } else {
2389 		for (y = 0; y < height; y++) {
2390 		    xpmNextString(data);
2391 		    for (x = 0; x < width; x++) {
2392 			for (a = 0, s = buf; a < cpp; a++, s++)
2393 			    *s = xpmGetC(data);
2394 			for (a = 0; a < ncolors; a++)
2395 			    if (!strcmp(colorTable[a].string, buf))
2396 				break;
2397 			if (a == ncolors)	/* no color matches */
2398 			    return (XpmFileInvalid);
2399 #ifndef FOR_MSW
2400 			XPutPixel(image, x, y, image_pixels[a]);
2401 			if (shapeimage)
2402 			    XPutPixel(shapeimage, x, y, shape_pixels[a]);
2403 #else
2404 			SelectObject(*dc, image->bitmap);
2405 			SetPixel(*dc, x, y, image_pixels[a]);
2406 			if (shapeimage) {
2407 			    SelectObject(*dc, shapeimage->bitmap);
2408 			    SetPixel(*dc, x, y, shape_pixels[a]);
2409 			}
2410 #endif
2411 		    }
2412 		}
2413 	    }
2414 	}
2415 	break;
2416     }
2417     return (XpmSuccess);
2418 }
2419