create.c revision 2f9f5fec
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
54LFUNC(xpmVisualType, int, (Visual *visual));
55
56LFUNC(AllocColor, int, (Display *display, Colormap colormap,
57			char *colorname, XColor *xcolor, void *closure));
58LFUNC(FreeColors, int, (Display *display, Colormap colormap,
59			Pixel *pixels, int n, void *closure));
60
61#ifndef FOR_MSW
62LFUNC(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
72LFUNC(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
81LFUNC(CreateXImage, int, (Display *display, Visual *visual,
82			  unsigned int depth, int format, unsigned int width,
83                          unsigned int height, XImage **image_return));
84
85LFUNC(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
93LFUNC(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 */
100LFUNC(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 */
111LFUNC(PutImagePixels, void, (XImage *image, unsigned int width,
112			     unsigned int height, unsigned int *pixelindex,
113			     Pixel *pixels));
114
115LFUNC(PutImagePixels32, void, (XImage *image, unsigned int width,
116			       unsigned int height, unsigned int *pixelindex,
117			       Pixel *pixels));
118
119LFUNC(PutImagePixels16, void, (XImage *image, unsigned int width,
120			       unsigned int height, unsigned int *pixelindex,
121			       Pixel *pixels));
122
123LFUNC(PutImagePixels8, void, (XImage *image, unsigned int width,
124			      unsigned int height, unsigned int *pixelindex,
125			      Pixel *pixels));
126
127LFUNC(PutImagePixels1, void, (XImage *image, unsigned int width,
128			      unsigned int height, unsigned int *pixelindex,
129			      Pixel *pixels));
130
131LFUNC(PutPixel1, int, (XImage *ximage, int x, int y, unsigned long pixel));
132LFUNC(PutPixel, int, (XImage *ximage, int x, int y, unsigned long pixel));
133#if !defined(WORD64) && !defined(LONG64)
134LFUNC(PutPixel32, int, (XImage *ximage, int x, int y, unsigned long pixel));
135#endif
136LFUNC(PutPixel32MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
137LFUNC(PutPixel32LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
138LFUNC(PutPixel16MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
139LFUNC(PutPixel16LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
140LFUNC(PutPixel8, int, (XImage *ximage, int x, int y, unsigned long pixel));
141LFUNC(PutPixel1MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
142LFUNC(PutPixel1LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
143
144# else /* AMIGA */
145LFUNC(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 */
151LFUNC(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
157FUNC(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 */
163int
164xpmstrcasecmp(
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 */
186static int
187xpmVisualType(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
216typedef struct {
217    int cols_index;
218    long closeness;
219}      CloseColor;
220
221static int
222closeness_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 */
235static int
236AllocColor(
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
258static int
259SetCloseColor(
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
442static int
443SetColor(
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
504static int
505CreateColors(
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 && defaults[def_index] != NULL &&
651			!xpmstrcasecmp(symbol->value, defaults[def_index]))
652			break;
653		}
654	    }
655	    if (n != numsymbols) {
656		if (symbol->name && symbol->value)
657		    colorname = symbol->value;
658		else
659		    pixel_defined = True;
660	    }
661	}
662	if (!pixel_defined) {		/* pixel not given as symbol value */
663
664	    unsigned int k;
665
666	    if (colorname) {		/* colorname given as symbol value */
667		if (!SetColor(display, colormap, visual, colorname, color,
668			      image_pixels, mask_pixels, mask_pixel_index,
669			      alloc_pixels, nalloc_pixels, used_pixels,
670			      nused_pixels, attributes, cols, ncols,
671			      allocColor, closure))
672		    pixel_defined = True;
673		else
674		    ErrorStatus = XpmColorError;
675	    }
676	    k = key;
677	    while (!pixel_defined && k > 1) {
678		if (defaults[k]) {
679		    if (!SetColor(display, colormap, visual, defaults[k],
680				  color, image_pixels, mask_pixels,
681				  mask_pixel_index, alloc_pixels,
682				  nalloc_pixels, used_pixels, nused_pixels,
683				  attributes, cols, ncols,
684				  allocColor, closure)) {
685			pixel_defined = True;
686			break;
687		    } else
688			ErrorStatus = XpmColorError;
689		}
690		k--;
691	    }
692	    k = key + 1;
693	    while (!pixel_defined && k < NKEYS + 1) {
694		if (defaults[k]) {
695		    if (!SetColor(display, colormap, visual, defaults[k],
696				  color, image_pixels, mask_pixels,
697				  mask_pixel_index, alloc_pixels,
698				  nalloc_pixels, used_pixels, nused_pixels,
699				  attributes, cols, ncols,
700				  allocColor, closure)) {
701			pixel_defined = True;
702			break;
703		    } else
704			ErrorStatus = XpmColorError;
705		}
706		k++;
707	    }
708	    if (!pixel_defined) {
709		if (cols)
710		    XpmFree(cols);
711		return (XpmColorFailed);
712	    }
713	} else {
714	    /* simply use the given pixel */
715	    *image_pixels = symbol->pixel;
716	    /* the following makes the mask to be built even if none
717	       is given a particular pixel */
718	    if (symbol->value
719		&& !xpmstrcasecmp(symbol->value, TRANSPARENT_COLOR)) {
720		*mask_pixels = 0;
721		*mask_pixel_index = color;
722	    } else
723		*mask_pixels = 1;
724	    used_pixels[(*nused_pixels)++] = *image_pixels;
725	}
726    }
727    if (cols)
728	XpmFree(cols);
729    return (ErrorStatus);
730}
731
732
733/* default FreeColors function, simply call XFreeColors */
734static int
735FreeColors(
736    Display	*display,
737    Colormap	 colormap,
738    Pixel	*pixels,
739    int		 n,
740    void	*closure)		/* not used */
741{
742    return XFreeColors(display, colormap, pixels, n, 0);
743}
744
745
746/* function call in case of error */
747
748#undef RETURN
749#define RETURN(status) \
750do \
751{ \
752      ErrorStatus = status; \
753      goto error; \
754} while(0)
755
756int
757XpmCreateImageFromXpmImage(
758    Display		 *display,
759    XpmImage		 *image,
760    XImage		**image_return,
761    XImage		**shapeimage_return,
762    XpmAttributes	 *attributes)
763{
764    /* variables stored in the XpmAttributes structure */
765    Visual *visual;
766    Colormap colormap;
767    unsigned int depth;
768    int bitmap_format;
769    XpmFreeColorsFunc freeColors;
770
771    /* variables to return */
772    XImage *ximage = NULL;
773    XImage *shapeimage = NULL;
774    unsigned int mask_pixel_index = XpmUndefPixel;
775    int ErrorStatus;
776
777    /* calculation variables */
778    Pixel *image_pixels = NULL;
779    Pixel *mask_pixels = NULL;
780    Pixel *alloc_pixels = NULL;
781    Pixel *used_pixels = NULL;
782    unsigned int nalloc_pixels = 0;
783    unsigned int nused_pixels = 0;
784
785    /* initialize return values */
786    if (image_return)
787	*image_return = NULL;
788    if (shapeimage_return)
789	*shapeimage_return = NULL;
790
791    /* retrieve information from the XpmAttributes */
792    if (attributes && (attributes->valuemask & XpmVisual))
793	visual = attributes->visual;
794    else
795	visual = XDefaultVisual(display, XDefaultScreen(display));
796
797    if (attributes && (attributes->valuemask & XpmColormap))
798	colormap = attributes->colormap;
799    else
800	colormap = XDefaultColormap(display, XDefaultScreen(display));
801
802    if (attributes && (attributes->valuemask & XpmDepth))
803	depth = attributes->depth;
804    else
805	depth = XDefaultDepth(display, XDefaultScreen(display));
806
807    if (attributes && (attributes->valuemask & XpmBitmapFormat))
808	bitmap_format = attributes->bitmap_format;
809    else
810	bitmap_format = ZPixmap;
811
812    if (attributes && (attributes->valuemask & XpmFreeColors))
813	freeColors = attributes->free_colors;
814    else
815	freeColors = FreeColors;
816
817    ErrorStatus = XpmSuccess;
818
819    if (image->ncolors >= UINT_MAX / sizeof(Pixel))
820	return (XpmNoMemory);
821
822    /* malloc pixels index tables */
823    image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
824    if (!image_pixels)
825	return (XpmNoMemory);
826
827    mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
828    if (!mask_pixels)
829	RETURN(XpmNoMemory);
830
831    /* maximum of allocated pixels will be the number of colors */
832    alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
833    if (!alloc_pixels)
834	RETURN(XpmNoMemory);
835
836    /* maximum of allocated pixels will be the number of colors */
837    used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
838    if (!used_pixels)
839	RETURN(XpmNoMemory);
840
841    /* get pixel colors, store them in index tables */
842    ErrorStatus = CreateColors(display, attributes, image->colorTable,
843			       image->ncolors, image_pixels, mask_pixels,
844			       &mask_pixel_index, alloc_pixels, &nalloc_pixels,
845			       used_pixels, &nused_pixels);
846
847    if (ErrorStatus != XpmSuccess
848	&& (ErrorStatus < 0 || (attributes
849				&& (attributes->valuemask & XpmExactColors)
850				&& attributes->exactColors)))
851	RETURN(ErrorStatus);
852
853    /* create the ximage */
854    if (image_return) {
855	ErrorStatus = CreateXImage(display, visual, depth,
856				   (depth == 1 ? bitmap_format : ZPixmap),
857				   image->width, image->height, &ximage);
858	if (ErrorStatus != XpmSuccess)
859	    RETURN(ErrorStatus);
860
861#ifndef FOR_MSW
862# ifndef AMIGA
863
864	/*
865	 * set the ximage data using optimized functions for ZPixmap
866	 */
867
868	if (ximage->bits_per_pixel == 8)
869	    PutImagePixels8(ximage, image->width, image->height,
870			    image->data, image_pixels);
871	else if (((ximage->bits_per_pixel | ximage->depth) == 1) &&
872		 (ximage->byte_order == ximage->bitmap_bit_order))
873	    PutImagePixels1(ximage, image->width, image->height,
874			    image->data, image_pixels);
875	else if (ximage->bits_per_pixel == 16)
876	    PutImagePixels16(ximage, image->width, image->height,
877			     image->data, image_pixels);
878	else if (ximage->bits_per_pixel == 32)
879	    PutImagePixels32(ximage, image->width, image->height,
880			     image->data, image_pixels);
881	else
882	    PutImagePixels(ximage, image->width, image->height,
883			   image->data, image_pixels);
884# else /* AMIGA */
885	APutImagePixels(ximage, image->width, image->height,
886			image->data, image_pixels);
887# endif
888#else  /* FOR_MSW */
889	MSWPutImagePixels(display, ximage, image->width, image->height,
890			  image->data, image_pixels);
891#endif
892    }
893    /* create the shape mask image */
894    if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
895	ErrorStatus = CreateXImage(display, visual, 1, bitmap_format,
896				   image->width, image->height, &shapeimage);
897	if (ErrorStatus != XpmSuccess)
898	    RETURN(ErrorStatus);
899
900#ifndef FOR_MSW
901# ifndef AMIGA
902	PutImagePixels1(shapeimage, image->width, image->height,
903			image->data, mask_pixels);
904# else /* AMIGA */
905	APutImagePixels(shapeimage, image->width, image->height,
906			image->data, mask_pixels);
907# endif
908#else  /* FOR_MSW */
909	MSWPutImagePixels(display, shapeimage, image->width, image->height,
910			  image->data, mask_pixels);
911#endif
912
913    }
914    XpmFree(image_pixels);
915    XpmFree(mask_pixels);
916
917    /* if requested return used pixels in the XpmAttributes structure */
918    if (attributes && (attributes->valuemask & XpmReturnPixels ||
919/* 3.2 backward compatibility code */
920	attributes->valuemask & XpmReturnInfos)) {
921/* end 3.2 bc */
922	attributes->pixels = used_pixels;
923	attributes->npixels = nused_pixels;
924	attributes->mask_pixel = mask_pixel_index;
925    } else
926	XpmFree(used_pixels);
927
928    /* if requested return alloc'ed pixels in the XpmAttributes structure */
929    if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
930	attributes->alloc_pixels = alloc_pixels;
931	attributes->nalloc_pixels = nalloc_pixels;
932    } else
933	XpmFree(alloc_pixels);
934
935    /* return created images */
936    if (image_return)
937	*image_return = ximage;
938    if (shapeimage_return)
939	*shapeimage_return = shapeimage;
940
941    return (ErrorStatus);
942
943/* exit point in case of error, free only locally allocated variables */
944error:
945    if (ximage)
946	XDestroyImage(ximage);
947    if (shapeimage)
948	XDestroyImage(shapeimage);
949    if (image_pixels)
950	XpmFree(image_pixels);
951    if (mask_pixels)
952	XpmFree(mask_pixels);
953    if (nalloc_pixels)
954	(*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL);
955    if (alloc_pixels)
956	XpmFree(alloc_pixels);
957    if (used_pixels)
958	XpmFree(used_pixels);
959
960    return (ErrorStatus);
961}
962
963
964/*
965 * Create an XImage with its data
966 */
967static int
968CreateXImage(
969    Display	 *display,
970    Visual	 *visual,
971    unsigned int  depth,
972    int		  format,
973    unsigned int  width,
974    unsigned int  height,
975    XImage	**image_return)
976{
977    int bitmap_pad;
978
979    /* first get bitmap_pad */
980    if (depth > 16)
981	bitmap_pad = 32;
982    else if (depth > 8)
983	bitmap_pad = 16;
984    else
985	bitmap_pad = 8;
986
987    /* then create the XImage with data = NULL and bytes_per_line = 0 */
988    *image_return = XCreateImage(display, visual, depth, format, 0, 0,
989				 width, height, bitmap_pad, 0);
990    if (!*image_return)
991	return (XpmNoMemory);
992
993#if !defined(FOR_MSW) && !defined(AMIGA)
994    if (height != 0 && (*image_return)->bytes_per_line >= INT_MAX / height) {
995	XDestroyImage(*image_return);
996	return XpmNoMemory;
997    }
998    /* now that bytes_per_line must have been set properly alloc data */
999    if((*image_return)->bytes_per_line == 0 ||  height == 0)
1000    	return XpmNoMemory;
1001    (*image_return)->data =
1002	(char *) XpmMalloc((*image_return)->bytes_per_line * height);
1003
1004    if (!(*image_return)->data) {
1005	XDestroyImage(*image_return);
1006	*image_return = NULL;
1007	return (XpmNoMemory);
1008    }
1009#else
1010    /* under FOR_MSW and AMIGA XCreateImage has done it all */
1011#endif
1012    return (XpmSuccess);
1013}
1014
1015#ifndef FOR_MSW
1016# ifndef AMIGA
1017/*
1018 * The functions below are written from X11R5 MIT's code (XImUtil.c)
1019 *
1020 * The idea is to have faster functions than the standard XPutPixel function
1021 * to build the image data. Indeed we can speed up things by suppressing tests
1022 * performed for each pixel. We do the same tests but at the image level.
1023 * We also assume that we use only ZPixmap images with null offsets.
1024 */
1025
1026LFUNC(_putbits, void, (register char *src, int dstoffset,
1027		       register int numbits, register char *dst));
1028
1029LFUNC(_XReverse_Bytes, int, (register unsigned char *bpt, register unsigned int nb));
1030
1031static unsigned char const _reverse_byte[0x100] = {
1032    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
1033    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1034    0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1035    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1036    0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
1037    0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1038    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
1039    0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1040    0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1041    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1042    0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1043    0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1044    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1045    0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1046    0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1047    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1048    0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1049    0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1050    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1051    0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1052    0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1053    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1054    0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1055    0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1056    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1057    0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1058    0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1059    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1060    0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1061    0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1062    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1063    0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
1064};
1065
1066static int
1067_XReverse_Bytes(
1068    register unsigned char	*bpt,
1069    register unsigned int	 nb)
1070{
1071    do {
1072	*bpt = _reverse_byte[*bpt];
1073	bpt++;
1074    } while (--nb > 0); /* is nb user-controled? */
1075    return 0;
1076}
1077
1078
1079void
1080xpm_xynormalizeimagebits(
1081    register unsigned char	*bp,
1082    register XImage		*img)
1083{
1084    register unsigned char c;
1085
1086    if (img->byte_order != img->bitmap_bit_order) {
1087	switch (img->bitmap_unit) {
1088
1089	case 16:
1090	    c = *bp;
1091	    *bp = *(bp + 1);
1092	    *(bp + 1) = c;
1093	    break;
1094
1095	case 32:
1096	    c = *(bp + 3);
1097	    *(bp + 3) = *bp;
1098	    *bp = c;
1099	    c = *(bp + 2);
1100	    *(bp + 2) = *(bp + 1);
1101	    *(bp + 1) = c;
1102	    break;
1103	}
1104    }
1105    if (img->bitmap_bit_order == MSBFirst)
1106	_XReverse_Bytes(bp, img->bitmap_unit >> 3);
1107}
1108
1109void
1110xpm_znormalizeimagebits(
1111    register unsigned char	*bp,
1112    register XImage		*img)
1113{
1114    register unsigned char c;
1115
1116    switch (img->bits_per_pixel) {
1117
1118    case 2:
1119	_XReverse_Bytes(bp, 1);
1120	break;
1121
1122    case 4:
1123	*bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF);
1124	break;
1125
1126    case 16:
1127	c = *bp;
1128	*bp = *(bp + 1);
1129	*(bp + 1) = c;
1130	break;
1131
1132    case 24:
1133	c = *(bp + 2);
1134	*(bp + 2) = *bp;
1135	*bp = c;
1136	break;
1137
1138    case 32:
1139	c = *(bp + 3);
1140	*(bp + 3) = *bp;
1141	*bp = c;
1142	c = *(bp + 2);
1143	*(bp + 2) = *(bp + 1);
1144	*(bp + 1) = c;
1145	break;
1146    }
1147}
1148
1149static unsigned char const _lomask[0x09] = {
11500x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
1151static unsigned char const _himask[0x09] = {
11520xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
1153
1154static void
1155_putbits(
1156    register char	*src,		/* address of source bit string */
1157    int			 dstoffset,	/* bit offset into destination;
1158					 * range is 0-31 */
1159    register int	 numbits,	/* number of bits to copy to
1160					 * destination */
1161    register char	*dst)		/* address of destination bit string */
1162{
1163    register unsigned char chlo, chhi;
1164    int hibits;
1165
1166    dst = dst + (dstoffset >> 3);
1167    dstoffset = dstoffset & 7;
1168    hibits = 8 - dstoffset;
1169    chlo = *dst & _lomask[dstoffset];
1170    for (;;) {
1171	chhi = (*src << dstoffset) & _himask[dstoffset];
1172	if (numbits <= hibits) {
1173	    chhi = chhi & _lomask[dstoffset + numbits];
1174	    *dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi;
1175	    break;
1176	}
1177	*dst = chhi | chlo;
1178	dst++;
1179	numbits = numbits - hibits;
1180	chlo = (unsigned char) (*src & _himask[hibits]) >> hibits;
1181	src++;
1182	if (numbits <= dstoffset) {
1183	    chlo = chlo & _lomask[numbits];
1184	    *dst = (*dst & _himask[numbits]) | chlo;
1185	    break;
1186	}
1187	numbits = numbits - dstoffset;
1188    }
1189}
1190
1191/*
1192 * Default method to write pixels into a Z image data structure.
1193 * The algorithm used is:
1194 *
1195 *	copy the destination bitmap_unit or Zpixel to temp
1196 *	normalize temp if needed
1197 *	copy the pixel bits into the temp
1198 *	renormalize temp if needed
1199 *	copy the temp back into the destination image data
1200 */
1201
1202static void
1203PutImagePixels(
1204    XImage		*image,
1205    unsigned int	 width,
1206    unsigned int	 height,
1207    unsigned int	*pixelindex,
1208    Pixel		*pixels)
1209{
1210    register char *src;
1211    register char *dst;
1212    register unsigned int *iptr;
1213    register unsigned int x, y;
1214    register char *data;
1215    Pixel pixel, px;
1216    int nbytes, depth, ibu, ibpp, i;
1217
1218    data = image->data;
1219    iptr = pixelindex;
1220    depth = image->depth;
1221    if (depth == 1) {
1222	ibu = image->bitmap_unit;
1223	for (y = 0; y < height; y++) /* how can we trust height */
1224	    for (x = 0; x < width; x++, iptr++) { /* how can we trust width */
1225		pixel = pixels[*iptr];
1226		for (i = 0, px = pixel; i < sizeof(unsigned long);
1227		     i++, px >>= 8)
1228		    ((unsigned char *) &pixel)[i] = px;
1229		src = &data[XYINDEX(x, y, image)];
1230		dst = (char *) &px;
1231		px = 0;
1232		nbytes = ibu >> 3;
1233		for (i = nbytes; --i >= 0;)
1234		    *dst++ = *src++;
1235		XYNORMALIZE(&px, image);
1236		_putbits((char *) &pixel, (x % ibu), 1, (char *) &px);
1237		XYNORMALIZE(&px, image);
1238		src = (char *) &px;
1239		dst = &data[XYINDEX(x, y, image)];
1240		for (i = nbytes; --i >= 0;)
1241		    *dst++ = *src++;
1242	    }
1243    } else {
1244	ibpp = image->bits_per_pixel;
1245	for (y = 0; y < height; y++)
1246	    for (x = 0; x < width; x++, iptr++) {
1247		pixel = pixels[*iptr];
1248		if (depth == 4)
1249		    pixel &= 0xf;
1250		for (i = 0, px = pixel; i < sizeof(unsigned long); i++,
1251		     px >>= 8)
1252		    ((unsigned char *) &pixel)[i] = px;
1253		src = &data[ZINDEX(x, y, image)];
1254		dst = (char *) &px;
1255		px = 0;
1256		nbytes = (ibpp + 7) >> 3;
1257		for (i = nbytes; --i >= 0;)
1258		    *dst++ = *src++;
1259		ZNORMALIZE(&px, image);
1260		_putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
1261		ZNORMALIZE(&px, image);
1262		src = (char *) &px;
1263		dst = &data[ZINDEX(x, y, image)];
1264		for (i = nbytes; --i >= 0;)
1265		    *dst++ = *src++;
1266	    }
1267    }
1268}
1269
1270/*
1271 * write pixels into a 32-bits Z image data structure
1272 */
1273
1274#if !defined(WORD64) && !defined(LONG64)
1275/* this item is static but deterministic so let it slide; doesn't
1276 * hurt re-entrancy of this library. Note if it is actually const then would
1277 * be OK under rules of ANSI-C but probably not C++ which may not
1278 * want to allocate space for it.
1279 */
1280static unsigned long byteorderpixel = MSBFirst << 24;
1281
1282#endif
1283
1284/*
1285   WITHOUT_SPEEDUPS is a flag to be turned on if you wish to use the original
1286   3.2e code - by default you get the speeded-up version.
1287*/
1288
1289static void
1290PutImagePixels32(
1291    XImage		*image,
1292    unsigned int	 width,
1293    unsigned int	 height,
1294    unsigned int	*pixelindex,
1295    Pixel		*pixels)
1296{
1297    unsigned char *data;
1298    unsigned int *iptr;
1299    unsigned int y;
1300    Pixel pixel;
1301
1302#ifdef WITHOUT_SPEEDUPS
1303
1304    unsigned int x;
1305    unsigned char *addr;
1306
1307    data = (unsigned char *) image->data;
1308    iptr = pixelindex;
1309#if !defined(WORD64) && !defined(LONG64)
1310    if (*((char *) &byteorderpixel) == image->byte_order) {
1311	for (y = 0; y < height; y++)
1312	    for (x = 0; x < width; x++, iptr++) {
1313		addr = &data[ZINDEX32(x, y, image)];
1314		*((unsigned long *) addr) = pixels[*iptr];
1315	    }
1316    } else
1317#endif
1318    if (image->byte_order == MSBFirst)
1319	for (y = 0; y < height; y++)
1320	    for (x = 0; x < width; x++, iptr++) {
1321		addr = &data[ZINDEX32(x, y, image)];
1322		pixel = pixels[*iptr];
1323		addr[0] = pixel >> 24;
1324		addr[1] = pixel >> 16;
1325		addr[2] = pixel >> 8;
1326		addr[3] = pixel;
1327	    }
1328    else
1329	for (y = 0; y < height; y++)
1330	    for (x = 0; x < width; x++, iptr++) {
1331		addr = &data[ZINDEX32(x, y, image)];
1332		pixel = pixels[*iptr];
1333		addr[0] = pixel;
1334		addr[1] = pixel >> 8;
1335		addr[2] = pixel >> 16;
1336		addr[3] = pixel >> 24;
1337	    }
1338
1339#else  /* WITHOUT_SPEEDUPS */
1340
1341    unsigned int bpl = image->bytes_per_line;
1342    unsigned char *data_ptr, *max_data;
1343
1344    data = (unsigned char *) image->data;
1345    iptr = pixelindex;
1346#if !defined(WORD64) && !defined(LONG64)
1347    if (*((char *) &byteorderpixel) == image->byte_order) {
1348	for (y = 0; y < height; y++) {
1349	    data_ptr = data;
1350	    max_data = data_ptr + (width << 2);
1351
1352	    while (data_ptr < max_data) {
1353		*((unsigned long *) data_ptr) = pixels[*(iptr++)];
1354		data_ptr += (1 << 2);
1355	    }
1356	    data += bpl;
1357	}
1358    } else
1359#endif
1360    if (image->byte_order == MSBFirst)
1361	for (y = 0; y < height; y++) {
1362	    data_ptr = data;
1363	    max_data = data_ptr + (width << 2);
1364
1365	    while (data_ptr < max_data) {
1366		pixel = pixels[*(iptr++)];
1367
1368		*data_ptr++ = pixel >> 24;
1369		*data_ptr++ = pixel >> 16;
1370		*data_ptr++ = pixel >> 8;
1371		*data_ptr++ = pixel;
1372
1373	    }
1374	    data += bpl;
1375	}
1376    else
1377	for (y = 0; y < height; y++) {
1378	    data_ptr = data;
1379	    max_data = data_ptr + (width << 2);
1380
1381	    while (data_ptr < max_data) {
1382		pixel = pixels[*(iptr++)];
1383
1384		*data_ptr++ = pixel;
1385		*data_ptr++ = pixel >> 8;
1386		*data_ptr++ = pixel >> 16;
1387		*data_ptr++ = pixel >> 24;
1388	    }
1389	    data += bpl;
1390	}
1391
1392#endif /* WITHOUT_SPEEDUPS */
1393}
1394
1395/*
1396 * write pixels into a 16-bits Z image data structure
1397 */
1398
1399static void
1400PutImagePixels16(
1401    XImage		*image,
1402    unsigned int	 width,
1403    unsigned int	 height,
1404    unsigned int	*pixelindex,
1405    Pixel		*pixels)
1406{
1407    unsigned char *data;
1408    unsigned int *iptr;
1409    unsigned int y;
1410
1411#ifdef WITHOUT_SPEEDUPS
1412
1413    unsigned int x;
1414    unsigned char *addr;
1415
1416    data = (unsigned char *) image->data;
1417    iptr = pixelindex;
1418    if (image->byte_order == MSBFirst)
1419	for (y = 0; y < height; y++)
1420	    for (x = 0; x < width; x++, iptr++) {
1421		addr = &data[ZINDEX16(x, y, image)];
1422		addr[0] = pixels[*iptr] >> 8;
1423		addr[1] = pixels[*iptr];
1424	    }
1425    else
1426	for (y = 0; y < height; y++)
1427	    for (x = 0; x < width; x++, iptr++) {
1428		addr = &data[ZINDEX16(x, y, image)];
1429		addr[0] = pixels[*iptr];
1430		addr[1] = pixels[*iptr] >> 8;
1431	    }
1432
1433#else  /* WITHOUT_SPEEDUPS */
1434
1435    Pixel pixel;
1436
1437    unsigned int bpl = image->bytes_per_line;
1438    unsigned char *data_ptr, *max_data;
1439
1440    data = (unsigned char *) image->data;
1441    iptr = pixelindex;
1442    if (image->byte_order == MSBFirst)
1443	for (y = 0; y < height; y++) {
1444	    data_ptr = data;
1445	    max_data = data_ptr + (width << 1);
1446
1447	    while (data_ptr < max_data) {
1448		pixel = pixels[*(iptr++)];
1449
1450		data_ptr[0] = pixel >> 8;
1451		data_ptr[1] = pixel;
1452
1453		data_ptr += (1 << 1);
1454	    }
1455	    data += bpl;
1456	}
1457    else
1458	for (y = 0; y < height; y++) {
1459	    data_ptr = data;
1460	    max_data = data_ptr + (width << 1);
1461
1462	    while (data_ptr < max_data) {
1463		pixel = pixels[*(iptr++)];
1464
1465		data_ptr[0] = pixel;
1466		data_ptr[1] = pixel >> 8;
1467
1468		data_ptr += (1 << 1);
1469	    }
1470	    data += bpl;
1471	}
1472
1473#endif /* WITHOUT_SPEEDUPS */
1474}
1475
1476/*
1477 * write pixels into a 8-bits Z image data structure
1478 */
1479
1480static void
1481PutImagePixels8(
1482    XImage		*image,
1483    unsigned int	 width,
1484    unsigned int	 height,
1485    unsigned int	*pixelindex,
1486    Pixel		*pixels)
1487{
1488    char *data;
1489    unsigned int *iptr;
1490    unsigned int y;
1491
1492#ifdef WITHOUT_SPEEDUPS
1493
1494    unsigned int x;
1495
1496    data = image->data;
1497    iptr = pixelindex;
1498    for (y = 0; y < height; y++)
1499	for (x = 0; x < width; x++, iptr++)
1500	    data[ZINDEX8(x, y, image)] = pixels[*iptr];
1501
1502#else  /* WITHOUT_SPEEDUPS */
1503
1504    unsigned int bpl = image->bytes_per_line;
1505    char *data_ptr, *max_data;
1506
1507    data = image->data;
1508    iptr = pixelindex;
1509
1510    for (y = 0; y < height; y++) {
1511	data_ptr = data;
1512	max_data = data_ptr + width;
1513
1514	while (data_ptr < max_data)
1515	    *(data_ptr++) = pixels[*(iptr++)];
1516
1517	data += bpl;
1518    }
1519
1520#endif /* WITHOUT_SPEEDUPS */
1521}
1522
1523/*
1524 * write pixels into a 1-bit depth image data structure and **offset null**
1525 */
1526
1527static void
1528PutImagePixels1(
1529    XImage		*image,
1530    unsigned int	 width,
1531    unsigned int	 height,
1532    unsigned int	*pixelindex,
1533    Pixel		*pixels)
1534{
1535    if (image->byte_order != image->bitmap_bit_order)
1536	PutImagePixels(image, width, height, pixelindex, pixels);
1537    else {
1538	unsigned int *iptr;
1539	unsigned int y;
1540	char *data;
1541
1542#ifdef WITHOUT_SPEEDUPS
1543
1544	unsigned int x;
1545
1546	data = image->data;
1547	iptr = pixelindex;
1548	if (image->bitmap_bit_order == MSBFirst)
1549	    for (y = 0; y < height; y++)
1550		for (x = 0; x < width; x++, iptr++) {
1551		    if (pixels[*iptr] & 1)
1552			data[ZINDEX1(x, y, image)] |= 0x80 >> (x & 7);
1553		    else
1554			data[ZINDEX1(x, y, image)] &= ~(0x80 >> (x & 7));
1555		}
1556	else
1557	    for (y = 0; y < height; y++)
1558		for (x = 0; x < width; x++, iptr++) {
1559		    if (pixels[*iptr] & 1)
1560			data[ZINDEX1(x, y, image)] |= 1 << (x & 7);
1561		    else
1562			data[ZINDEX1(x, y, image)] &= ~(1 << (x & 7));
1563		}
1564
1565#else  /* WITHOUT_SPEEDUPS */
1566
1567	char value;
1568	char *data_ptr, *max_data;
1569	int bpl = image->bytes_per_line;
1570	int diff, count;
1571
1572	data = image->data;
1573	iptr = pixelindex;
1574
1575	diff = width & 7;
1576	width >>= 3;
1577
1578	if (image->bitmap_bit_order == MSBFirst)
1579	    for (y = 0; y < height; y++) {
1580		data_ptr = data;
1581		max_data = data_ptr + width;
1582		while (data_ptr < max_data) {
1583		    value = 0;
1584
1585		    value = (value << 1) | (pixels[*(iptr++)] & 1);
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
1594		    *(data_ptr++) = value;
1595		}
1596		if (diff) {
1597		    value = 0;
1598		    for (count = 0; count < diff; count++) {
1599			if (pixels[*(iptr++)] & 1)
1600			    value |= (0x80 >> count);
1601		    }
1602		    *(data_ptr) = value;
1603		}
1604		data += bpl;
1605	    }
1606	else
1607	    for (y = 0; y < height; y++) {
1608		data_ptr = data;
1609		max_data = data_ptr + width;
1610		while (data_ptr < max_data) {
1611		    value = 0;
1612		    iptr += 8;
1613
1614		    value = (value << 1) | (pixels[*(--iptr)] & 1);
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
1623		    iptr += 8;
1624		    *(data_ptr++) = value;
1625		}
1626		if (diff) {
1627		    value = 0;
1628		    for (count = 0; count < diff; count++) {
1629			if (pixels[*(iptr++)] & 1)
1630			    value |= (1 << count);
1631		    }
1632		    *(data_ptr) = value;
1633		}
1634		data += bpl;
1635	    }
1636
1637#endif /* WITHOUT_SPEEDUPS */
1638    }
1639}
1640
1641int
1642XpmCreatePixmapFromXpmImage(
1643    Display		*display,
1644    Drawable		 d,
1645    XpmImage		*image,
1646    Pixmap		*pixmap_return,
1647    Pixmap		*shapemask_return,
1648    XpmAttributes	*attributes)
1649{
1650    XImage *ximage, *shapeimage;
1651    int ErrorStatus;
1652
1653    /* initialize return values */
1654    if (pixmap_return)
1655	*pixmap_return = 0;
1656    if (shapemask_return)
1657	*shapemask_return = 0;
1658
1659    /* create the ximages */
1660    ErrorStatus = XpmCreateImageFromXpmImage(display, image,
1661					     (pixmap_return ? &ximage : NULL),
1662					     (shapemask_return ?
1663					      &shapeimage : NULL),
1664					     attributes);
1665    if (ErrorStatus < 0)
1666	return (ErrorStatus);
1667
1668    /* create the pixmaps and destroy images */
1669    if (pixmap_return && ximage) {
1670	xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
1671	XDestroyImage(ximage);
1672    }
1673    if (shapemask_return && shapeimage) {
1674	xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
1675	XDestroyImage(shapeimage);
1676    }
1677    return (ErrorStatus);
1678}
1679
1680# else /* AMIGA */
1681
1682static void
1683APutImagePixels (
1684    XImage        *image,
1685    unsigned int   width,
1686    unsigned int   height,
1687    unsigned int  *pixelindex,
1688    Pixel         *pixels)
1689{
1690    unsigned int   *data = pixelindex;
1691    unsigned int    x, y;
1692    unsigned char  *array;
1693    XImage         *tmp_img;
1694    BOOL            success = FALSE;
1695
1696    array = XpmMalloc ((((width+15)>>4)<<4)*sizeof (*array));
1697    if (array != NULL)
1698    {
1699	tmp_img = AllocXImage ((((width+15)>>4)<<4), 1,
1700			       image->rp->BitMap->Depth);
1701	if (tmp_img != NULL)
1702	{
1703	    for (y = 0; y < height; ++y)
1704	    {
1705		for (x = 0; x < width; ++x)
1706		    array[x] = pixels[*(data++)];
1707		WritePixelLine8 (image->rp, 0, y, width, array, tmp_img->rp);
1708	    }
1709	    FreeXImage (tmp_img);
1710	    success = TRUE;
1711	}
1712	XpmFree (array);
1713    }
1714
1715    if (!success)
1716    {
1717	for (y = 0; y < height; ++y)
1718	    for (x = 0; x < width; ++x)
1719		XPutPixel (image, x, y, pixels[*(data++)]);
1720    }
1721}
1722
1723# endif/* AMIGA */
1724#else  /* FOR_MSW part follows */
1725static void
1726MSWPutImagePixels(
1727    Display		*dc,
1728    XImage		*image,
1729    unsigned int	 width,
1730    unsigned int	 height,
1731    unsigned int	*pixelindex,
1732    Pixel		*pixels)
1733{
1734    unsigned int *data = pixelindex;
1735    unsigned int x, y;
1736    HBITMAP obm;
1737
1738    obm = SelectObject(*dc, image->bitmap);
1739    for (y = 0; y < height; y++) {
1740	for (x = 0; x < width; x++) {
1741	    SetPixel(*dc, x, y, pixels[*(data++)]); /* data is [x+y*width] */
1742	}
1743    }
1744    SelectObject(*dc, obm);
1745}
1746
1747#endif /* FOR_MSW */
1748
1749
1750
1751#if !defined(FOR_MSW) && !defined(AMIGA)
1752
1753static int
1754PutPixel1(
1755    register XImage	*ximage,
1756    int			 x,
1757    int			 y,
1758    unsigned long	 pixel)
1759{
1760    register char *src;
1761    register char *dst;
1762    register int i;
1763    Pixel px;
1764    int nbytes;
1765
1766    if(x < 0 || y < 0)
1767    	return 0;
1768
1769    for (i=0, px=pixel; i<sizeof(unsigned long); i++, px>>=8)
1770	((unsigned char *)&pixel)[i] = px;
1771    src = &ximage->data[XYINDEX(x, y, ximage)];
1772    dst = (char *)&px;
1773    px = 0;
1774    nbytes = ximage->bitmap_unit >> 3;
1775    for (i = nbytes; --i >= 0; ) *dst++ = *src++;
1776    XYNORMALIZE(&px, ximage);
1777    i = ((x + ximage->xoffset) % ximage->bitmap_unit);
1778    _putbits ((char *)&pixel, i, 1, (char *)&px);
1779    XYNORMALIZE(&px, ximage);
1780    src = (char *) &px;
1781    dst = &ximage->data[XYINDEX(x, y, ximage)];
1782    for (i = nbytes; --i >= 0; )
1783	*dst++ = *src++;
1784
1785    return 1;
1786}
1787
1788static int
1789PutPixel(
1790    register XImage	*ximage,
1791    int			 x,
1792    int			 y,
1793    unsigned long	 pixel)
1794{
1795    register char *src;
1796    register char *dst;
1797    register int i;
1798    Pixel px;
1799    unsigned int nbytes, ibpp;
1800
1801    if(x < 0 || y < 0)
1802    	return 0;
1803
1804    ibpp = ximage->bits_per_pixel;
1805    if (ximage->depth == 4)
1806	pixel &= 0xf;
1807    for (i = 0, px = pixel; i < sizeof(unsigned long); i++, px >>= 8)
1808	((unsigned char *) &pixel)[i] = px;
1809    src = &ximage->data[ZINDEX(x, y, ximage)];
1810    dst = (char *) &px;
1811    px = 0;
1812    nbytes = (ibpp + 7) >> 3;
1813    for (i = nbytes; --i >= 0;)
1814	*dst++ = *src++;
1815    ZNORMALIZE(&px, ximage);
1816    _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
1817    ZNORMALIZE(&px, ximage);
1818    src = (char *) &px;
1819    dst = &ximage->data[ZINDEX(x, y, ximage)];
1820    for (i = nbytes; --i >= 0;)
1821	*dst++ = *src++;
1822
1823    return 1;
1824}
1825
1826#if !defined(WORD64) && !defined(LONG64)
1827static int
1828PutPixel32(
1829    register XImage	*ximage,
1830    int			 x,
1831    int			 y,
1832    unsigned long	 pixel)
1833{
1834    unsigned char *addr;
1835
1836    if(x < 0 || y < 0)
1837    	return 0;
1838
1839    addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1840    *((unsigned long *)addr) = pixel;
1841    return 1;
1842}
1843#endif
1844
1845static int
1846PutPixel32MSB(
1847    register XImage	*ximage,
1848    int			 x,
1849    int			 y,
1850    unsigned long	 pixel)
1851{
1852    unsigned char *addr;
1853
1854    if(x < 0 || y < 0)
1855    	return 0;
1856
1857    addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1858    addr[0] = pixel >> 24;
1859    addr[1] = pixel >> 16;
1860    addr[2] = pixel >> 8;
1861    addr[3] = pixel;
1862    return 1;
1863}
1864
1865static int
1866PutPixel32LSB(
1867    register XImage	*ximage,
1868    int			 x,
1869    int			 y,
1870    unsigned long	 pixel)
1871{
1872    unsigned char *addr;
1873
1874    if(x < 0 || y < 0)
1875    	return 0;
1876
1877    addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1878    addr[3] = pixel >> 24;
1879    addr[2] = pixel >> 16;
1880    addr[1] = pixel >> 8;
1881    addr[0] = pixel;
1882    return 1;
1883}
1884
1885static int
1886PutPixel16MSB(
1887    register XImage	*ximage,
1888    int			 x,
1889    int			 y,
1890    unsigned long	 pixel)
1891{
1892    unsigned char *addr;
1893
1894    if(x < 0 || y < 0)
1895    	return 0;
1896
1897    addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)];
1898    addr[0] = pixel >> 8;
1899    addr[1] = pixel;
1900    return 1;
1901}
1902
1903static int
1904PutPixel16LSB(
1905    register XImage	*ximage,
1906    int			 x,
1907    int			 y,
1908    unsigned long	 pixel)
1909{
1910    unsigned char *addr;
1911
1912    if(x < 0 || y < 0)
1913    	return 0;
1914
1915    addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)];
1916    addr[1] = pixel >> 8;
1917    addr[0] = pixel;
1918    return 1;
1919}
1920
1921static int
1922PutPixel8(
1923    register XImage	*ximage,
1924    int			 x,
1925    int			 y,
1926    unsigned long	 pixel)
1927{
1928    if(x < 0 || y < 0)
1929    	return 0;
1930
1931    ximage->data[ZINDEX8(x, y, ximage)] = pixel;
1932    return 1;
1933}
1934
1935static int
1936PutPixel1MSB(
1937    register XImage	*ximage,
1938    int			 x,
1939    int			 y,
1940    unsigned long	 pixel)
1941{
1942    if(x < 0 || y < 0)
1943    	return 0;
1944
1945    if (pixel & 1)
1946	ximage->data[ZINDEX1(x, y, ximage)] |= 0x80 >> (x & 7);
1947    else
1948	ximage->data[ZINDEX1(x, y, ximage)] &= ~(0x80 >> (x & 7));
1949    return 1;
1950}
1951
1952static int
1953PutPixel1LSB(
1954    register XImage	*ximage,
1955    int			 x,
1956    int			 y,
1957    unsigned long	 pixel)
1958{
1959    if(x < 0 || y < 0)
1960    	return 0;
1961
1962    if (pixel & 1)
1963	ximage->data[ZINDEX1(x, y, ximage)] |= 1 << (x & 7);
1964    else
1965	ximage->data[ZINDEX1(x, y, ximage)] &= ~(1 << (x & 7));
1966    return 1;
1967}
1968
1969#endif /* not FOR_MSW && not AMIGA */
1970
1971/*
1972 * This function parses an Xpm file or data and directly create an XImage
1973 */
1974int
1975xpmParseDataAndCreate(
1976    Display		 *display,
1977    xpmData		 *data,
1978    XImage		**image_return,
1979    XImage		**shapeimage_return,
1980    XpmImage		 *image,
1981    XpmInfo		 *info,
1982    XpmAttributes	 *attributes)
1983{
1984    /* variables stored in the XpmAttributes structure */
1985    Visual *visual;
1986    Colormap colormap;
1987    unsigned int depth;
1988    int bitmap_format;
1989    XpmFreeColorsFunc freeColors;
1990
1991    /* variables to return */
1992    XImage *ximage = NULL;
1993    XImage *shapeimage = NULL;
1994    unsigned int mask_pixel_index = XpmUndefPixel;
1995
1996    /* calculation variables */
1997    Pixel *image_pixels = NULL;
1998    Pixel *mask_pixels = NULL;
1999    Pixel *alloc_pixels = NULL;
2000    Pixel *used_pixels = NULL;
2001    unsigned int nalloc_pixels = 0;
2002    unsigned int nused_pixels = 0;
2003    unsigned int width, height, ncolors, cpp;
2004    unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0;
2005    XpmColor *colorTable = NULL;
2006    char *hints_cmt = NULL;
2007    char *colors_cmt = NULL;
2008    char *pixels_cmt = NULL;
2009
2010    unsigned int cmts;
2011    int ErrorStatus;
2012    xpmHashTable hashtable;
2013
2014
2015    /* initialize return values */
2016    if (image_return)
2017	*image_return = NULL;
2018    if (shapeimage_return)
2019	*shapeimage_return = NULL;
2020
2021
2022    /* retrieve information from the XpmAttributes */
2023    if (attributes && (attributes->valuemask & XpmVisual))
2024	visual = attributes->visual;
2025    else
2026	visual = XDefaultVisual(display, XDefaultScreen(display));
2027
2028    if (attributes && (attributes->valuemask & XpmColormap))
2029	colormap = attributes->colormap;
2030    else
2031	colormap = XDefaultColormap(display, XDefaultScreen(display));
2032
2033    if (attributes && (attributes->valuemask & XpmDepth))
2034	depth = attributes->depth;
2035    else
2036	depth = XDefaultDepth(display, XDefaultScreen(display));
2037
2038    if (attributes && (attributes->valuemask & XpmBitmapFormat))
2039	bitmap_format = attributes->bitmap_format;
2040    else
2041	bitmap_format = ZPixmap;
2042
2043    if (attributes && (attributes->valuemask & XpmFreeColors))
2044	freeColors = attributes->free_colors;
2045    else
2046	freeColors = FreeColors;
2047
2048    cmts = info && (info->valuemask & XpmReturnComments);
2049
2050    /*
2051     * parse the header
2052     */
2053    ErrorStatus = xpmParseHeader(data);
2054    if (ErrorStatus != XpmSuccess)
2055	return (ErrorStatus);
2056
2057    /*
2058     * read values
2059     */
2060    ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp,
2061				 &x_hotspot, &y_hotspot, &hotspot,
2062				 &extensions);
2063    if (ErrorStatus != XpmSuccess)
2064	return (ErrorStatus);
2065
2066    /*
2067     * store the hints comment line
2068     */
2069    if (cmts)
2070	xpmGetCmt(data, &hints_cmt);
2071
2072    /*
2073     * init the hashtable
2074     */
2075    if (USE_HASHTABLE) {
2076	ErrorStatus = xpmHashTableInit(&hashtable);
2077	if (ErrorStatus != XpmSuccess)
2078	    RETURN(ErrorStatus);
2079    }
2080
2081    /*
2082     * read colors
2083     */
2084    ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable);
2085    if (ErrorStatus != XpmSuccess)
2086	RETURN(ErrorStatus);
2087
2088    /*
2089     * store the colors comment line
2090     */
2091    if (cmts)
2092	xpmGetCmt(data, &colors_cmt);
2093
2094    /* malloc pixels index tables */
2095    if (ncolors >= UINT_MAX / sizeof(Pixel))
2096	RETURN(XpmNoMemory);
2097
2098    image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2099    if (!image_pixels)
2100	RETURN(XpmNoMemory);
2101
2102    mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2103    if (!mask_pixels)
2104	RETURN(XpmNoMemory);
2105
2106    /* maximum of allocated pixels will be the number of colors */
2107    alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2108    if (!alloc_pixels)
2109	RETURN(XpmNoMemory);
2110
2111    /* maximum of allocated pixels will be the number of colors */
2112    used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2113    if (!used_pixels)
2114	RETURN(XpmNoMemory);
2115
2116    /* get pixel colors, store them in index tables */
2117    ErrorStatus = CreateColors(display, attributes, colorTable, ncolors,
2118			       image_pixels, mask_pixels, &mask_pixel_index,
2119			       alloc_pixels, &nalloc_pixels, used_pixels,
2120			       &nused_pixels);
2121
2122    if (ErrorStatus != XpmSuccess
2123	&& (ErrorStatus < 0 || (attributes
2124				&& (attributes->valuemask & XpmExactColors)
2125				&& attributes->exactColors)))
2126	RETURN(ErrorStatus);
2127
2128    /* now create the ximage */
2129    if (image_return) {
2130	ErrorStatus = CreateXImage(display, visual, depth,
2131				   (depth == 1 ? bitmap_format : ZPixmap),
2132				   width, height, &ximage);
2133	if (ErrorStatus != XpmSuccess)
2134	    RETURN(ErrorStatus);
2135
2136#if !defined(FOR_MSW) && !defined(AMIGA)
2137
2138	/*
2139	 * set the XImage pointer function, to be used with XPutPixel,
2140	 * to an internal optimized function
2141	 */
2142
2143	if (ximage->bits_per_pixel == 8)
2144	    ximage->f.put_pixel = PutPixel8;
2145	else if (((ximage->bits_per_pixel | ximage->depth) == 1) &&
2146		 (ximage->byte_order == ximage->bitmap_bit_order))
2147	    if (ximage->bitmap_bit_order == MSBFirst)
2148		ximage->f.put_pixel = PutPixel1MSB;
2149	    else
2150		ximage->f.put_pixel = PutPixel1LSB;
2151	else if (ximage->bits_per_pixel == 16)
2152	    if (ximage->bitmap_bit_order == MSBFirst)
2153		ximage->f.put_pixel = PutPixel16MSB;
2154	    else
2155		ximage->f.put_pixel = PutPixel16LSB;
2156	else if (ximage->bits_per_pixel == 32)
2157#if !defined(WORD64) && !defined(LONG64)
2158	    if (*((char *)&byteorderpixel) == ximage->byte_order)
2159		ximage->f.put_pixel = PutPixel32;
2160	    else
2161#endif
2162		if (ximage->bitmap_bit_order == MSBFirst)
2163		    ximage->f.put_pixel = PutPixel32MSB;
2164		else
2165		    ximage->f.put_pixel = PutPixel32LSB;
2166	else if ((ximage->bits_per_pixel | ximage->depth) == 1)
2167	    ximage->f.put_pixel = PutPixel1;
2168	else
2169	    ximage->f.put_pixel = PutPixel;
2170#endif /* not FOR_MSW && not AMIGA */
2171    }
2172
2173    /* create the shape mask image */
2174    if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
2175	ErrorStatus = CreateXImage(display, visual, 1, bitmap_format,
2176				   width, height, &shapeimage);
2177	if (ErrorStatus != XpmSuccess)
2178	    RETURN(ErrorStatus);
2179
2180#if !defined(FOR_MSW) && !defined(AMIGA)
2181	if (shapeimage->bitmap_bit_order == MSBFirst)
2182	    shapeimage->f.put_pixel = PutPixel1MSB;
2183	else
2184	    shapeimage->f.put_pixel = PutPixel1LSB;
2185#endif
2186    }
2187
2188    /*
2189     * read pixels and put them in the XImage
2190     */
2191    ErrorStatus = ParseAndPutPixels(
2192#ifdef FOR_MSW
2193				    display,
2194#endif
2195				    data, width, height, ncolors, cpp,
2196				    colorTable, &hashtable,
2197				    ximage, image_pixels,
2198				    shapeimage, mask_pixels);
2199    XpmFree(image_pixels);
2200    image_pixels = NULL;
2201    XpmFree(mask_pixels);
2202    mask_pixels = NULL;
2203
2204    /*
2205     * free the hastable
2206     */
2207    if (ErrorStatus != XpmSuccess)
2208	RETURN(ErrorStatus);
2209    else if (USE_HASHTABLE)
2210	xpmHashTableFree(&hashtable);
2211
2212    /*
2213     * store the pixels comment line
2214     */
2215    if (cmts)
2216	xpmGetCmt(data, &pixels_cmt);
2217
2218    /*
2219     * parse extensions
2220     */
2221    if (info && (info->valuemask & XpmReturnExtensions)) {
2222	if (extensions) {
2223	    ErrorStatus = xpmParseExtensions(data, &info->extensions,
2224					     &info->nextensions);
2225	    if (ErrorStatus != XpmSuccess)
2226		RETURN(ErrorStatus);
2227	} else {
2228	    info->extensions = NULL;
2229	    info->nextensions = 0;
2230	}
2231    }
2232    /*
2233     * store found informations in the XpmImage structure
2234     */
2235    image->width = width;
2236    image->height = height;
2237    image->cpp = cpp;
2238    image->ncolors = ncolors;
2239    image->colorTable = colorTable;
2240    image->data = NULL;
2241
2242    if (info) {
2243	if (cmts) {
2244	    info->hints_cmt = hints_cmt;
2245	    info->colors_cmt = colors_cmt;
2246	    info->pixels_cmt = pixels_cmt;
2247	}
2248	if (hotspot) {
2249	    info->x_hotspot = x_hotspot;
2250	    info->y_hotspot = y_hotspot;
2251	    info->valuemask |= XpmHotspot;
2252	}
2253    }
2254    /* if requested return used pixels in the XpmAttributes structure */
2255    if (attributes && (attributes->valuemask & XpmReturnPixels ||
2256/* 3.2 backward compatibility code */
2257	attributes->valuemask & XpmReturnInfos)) {
2258/* end 3.2 bc */
2259	attributes->pixels = used_pixels;
2260	attributes->npixels = nused_pixels;
2261	attributes->mask_pixel = mask_pixel_index;
2262    } else
2263	XpmFree(used_pixels);
2264
2265    /* if requested return alloc'ed pixels in the XpmAttributes structure */
2266    if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
2267	attributes->alloc_pixels = alloc_pixels;
2268	attributes->nalloc_pixels = nalloc_pixels;
2269    } else
2270	XpmFree(alloc_pixels);
2271
2272    /* return created images */
2273    if (image_return)
2274	*image_return = ximage;
2275    if (shapeimage_return)
2276	*shapeimage_return = shapeimage;
2277
2278    return (XpmSuccess);
2279
2280/* exit point in case of error, free only locally allocated variables */
2281error:
2282    if (USE_HASHTABLE)
2283	xpmHashTableFree(&hashtable);
2284    if (colorTable)
2285	xpmFreeColorTable(colorTable, ncolors);
2286    if (hints_cmt)
2287	XpmFree(hints_cmt);
2288    if (colors_cmt)
2289	XpmFree(colors_cmt);
2290    if (pixels_cmt)
2291	XpmFree(pixels_cmt);
2292    if (ximage)
2293	XDestroyImage(ximage);
2294    if (shapeimage)
2295	XDestroyImage(shapeimage);
2296    if (image_pixels)
2297	XpmFree(image_pixels);
2298    if (mask_pixels)
2299	XpmFree(mask_pixels);
2300    if (nalloc_pixels)
2301	(*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL);
2302    if (alloc_pixels)
2303	XpmFree(alloc_pixels);
2304    if (used_pixels)
2305	XpmFree(used_pixels);
2306
2307    return (ErrorStatus);
2308}
2309
2310static int
2311ParseAndPutPixels(
2312#ifdef FOR_MSW
2313    Display		*dc,
2314#endif
2315    xpmData		*data,
2316    unsigned int	 width,
2317    unsigned int	 height,
2318    unsigned int	 ncolors,
2319    unsigned int	 cpp,
2320    XpmColor		*colorTable,
2321    xpmHashTable	*hashtable,
2322    XImage		*image,
2323    Pixel		*image_pixels,
2324    XImage		*shapeimage,
2325    Pixel		*shape_pixels)
2326{
2327    unsigned int a, x, y;
2328
2329    switch (cpp) {
2330
2331    case (1):				/* Optimize for single character
2332					 * colors */
2333	{
2334	    unsigned short colidx[256];
2335#ifdef FOR_MSW
2336	    HDC shapedc;
2337	    HBITMAP obm, sobm;
2338
2339	    if ( shapeimage ) {
2340		shapedc = CreateCompatibleDC(*dc);
2341		sobm = SelectObject(shapedc, shapeimage->bitmap);
2342	    } else {
2343	        shapedc = NULL;
2344	    }
2345	    obm = SelectObject(*dc, image->bitmap);
2346#endif
2347	    if (ncolors > 256)
2348		return (XpmFileInvalid);
2349
2350	    bzero((char *)colidx, 256 * sizeof(short));
2351	    for (a = 0; a < ncolors; a++)
2352		colidx[(unsigned char)colorTable[a].string[0]] = a + 1;
2353
2354	    for (y = 0; y < height; y++) {
2355		xpmNextString(data);
2356		for (x = 0; x < width; x++) {
2357		    int c = xpmGetC(data);
2358
2359		    if (c > 0 && c < 256 && colidx[c] != 0) {
2360#ifndef FOR_MSW
2361			XPutPixel(image, x, y, image_pixels[colidx[c] - 1]);
2362			if (shapeimage)
2363			    XPutPixel(shapeimage, x, y,
2364				      shape_pixels[colidx[c] - 1]);
2365#else
2366			SetPixel(*dc, x, y, image_pixels[colidx[c] - 1]);
2367			if (shapedc) {
2368			    SetPixel(shapedc, x, y, shape_pixels[colidx[c] - 1]);
2369			}
2370#endif
2371		    } else
2372			return (XpmFileInvalid);
2373		}
2374	    }
2375#ifdef FOR_MSW
2376	    if ( shapedc ) {
2377	        SelectObject(shapedc, sobm);
2378		DeleteDC(shapedc);
2379	    }
2380	    SelectObject(*dc, obm);
2381#endif
2382	}
2383	break;
2384
2385    case (2):				/* Optimize for double character
2386					 * colors */
2387	{
2388
2389/* free all allocated pointers at all exits */
2390#define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
2391if (cidx[f]) XpmFree(cidx[f]);}
2392
2393	    /* array of pointers malloced by need */
2394	    unsigned short *cidx[256];
2395	    unsigned int char1;
2396
2397	    bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */
2398	    for (a = 0; a < ncolors; a++) {
2399		char1 = (unsigned char) colorTable[a].string[0];
2400		if (cidx[char1] == NULL) { /* get new memory */
2401		    cidx[char1] = (unsigned short *)
2402			XpmCalloc(256, sizeof(unsigned short));
2403		    if (cidx[char1] == NULL) { /* new block failed */
2404			FREE_CIDX;
2405			return (XpmNoMemory);
2406		    }
2407		}
2408		cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1;
2409	    }
2410
2411	    for (y = 0; y < height; y++) {
2412		xpmNextString(data);
2413		for (x = 0; x < width; x++) {
2414		    int cc1 = xpmGetC(data);
2415		    if (cc1 > 0 && cc1 < 256) {
2416			int cc2 = xpmGetC(data);
2417			if (cc2 > 0 && cc2 < 256 &&
2418			    cidx[cc1] && cidx[cc1][cc2] != 0) {
2419#ifndef FOR_MSW
2420			    XPutPixel(image, x, y,
2421				      image_pixels[cidx[cc1][cc2] - 1]);
2422			    if (shapeimage)
2423				XPutPixel(shapeimage, x, y,
2424					  shape_pixels[cidx[cc1][cc2] - 1]);
2425#else
2426			SelectObject(*dc, image->bitmap);
2427			SetPixel(*dc, x, y, image_pixels[cidx[cc1][cc2] - 1]);
2428			if (shapeimage) {
2429			    SelectObject(*dc, shapeimage->bitmap);
2430			    SetPixel(*dc, x, y,
2431				     shape_pixels[cidx[cc1][cc2] - 1]);
2432			}
2433#endif
2434			} else {
2435			    FREE_CIDX;
2436			    return (XpmFileInvalid);
2437			}
2438		    } else {
2439			FREE_CIDX;
2440			return (XpmFileInvalid);
2441		    }
2442		}
2443	    }
2444	    FREE_CIDX;
2445	}
2446	break;
2447
2448    default:				/* Non-optimized case of long color
2449					 * names */
2450	{
2451	    char *s;
2452	    char buf[BUFSIZ];
2453
2454	    if (cpp >= sizeof(buf))
2455		return (XpmFileInvalid);
2456
2457	    buf[cpp] = '\0';
2458	    if (USE_HASHTABLE) {
2459		xpmHashAtom *slot;
2460
2461		for (y = 0; y < height; y++) {
2462		    xpmNextString(data);
2463		    for (x = 0; x < width; x++) {
2464			for (a = 0, s = buf; a < cpp; a++, s++)
2465			    *s = xpmGetC(data);
2466			slot = xpmHashSlot(hashtable, buf);
2467			if (!*slot)	/* no color matches */
2468			    return (XpmFileInvalid);
2469#ifndef FOR_MSW
2470			XPutPixel(image, x, y,
2471				  image_pixels[HashColorIndex(slot)]);
2472			if (shapeimage)
2473			    XPutPixel(shapeimage, x, y,
2474				      shape_pixels[HashColorIndex(slot)]);
2475#else
2476			SelectObject(*dc, image->bitmap);
2477			SetPixel(*dc, x, y,
2478				 image_pixels[HashColorIndex(slot)]);
2479			if (shapeimage) {
2480			    SelectObject(*dc, shapeimage->bitmap);
2481			    SetPixel(*dc, x, y,
2482				     shape_pixels[HashColorIndex(slot)]);
2483			}
2484#endif
2485		    }
2486		}
2487	    } else {
2488		for (y = 0; y < height; y++) {
2489		    xpmNextString(data);
2490		    for (x = 0; x < width; x++) {
2491			for (a = 0, s = buf; a < cpp; a++, s++)
2492			    *s = xpmGetC(data);
2493			for (a = 0; a < ncolors; a++)
2494			    if (!strcmp(colorTable[a].string, buf))
2495				break;
2496			if (a == ncolors)	/* no color matches */
2497			    return (XpmFileInvalid);
2498#ifndef FOR_MSW
2499			XPutPixel(image, x, y, image_pixels[a]);
2500			if (shapeimage)
2501			    XPutPixel(shapeimage, x, y, shape_pixels[a]);
2502#else
2503			SelectObject(*dc, image->bitmap);
2504			SetPixel(*dc, x, y, image_pixels[a]);
2505			if (shapeimage) {
2506			    SelectObject(*dc, shapeimage->bitmap);
2507			    SetPixel(*dc, x, y, shape_pixels[a]);
2508			}
2509#endif
2510		    }
2511		}
2512	    }
2513	}
2514	break;
2515    }
2516    return (XpmSuccess);
2517}
2518