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