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