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