create.c revision 2e2dd055
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
1662e2dd055Smrgxpmstrcasecmp(
1672e2dd055Smrg    register char	*s1,
1682e2dd055Smrg    register char	*s2)
169a966c04fSmrg{
170a966c04fSmrg    register int c1, c2;
171a966c04fSmrg
172a966c04fSmrg    while (*s1 && *s2) {
173a966c04fSmrg	c1 = tolower(*s1);
174a966c04fSmrg	c2 = tolower(*s2);
175a966c04fSmrg	if (c1 != c2)
176a966c04fSmrg	    return (c1 - c2);
177a966c04fSmrg	s1++;
178a966c04fSmrg	s2++;
179a966c04fSmrg    }
180a966c04fSmrg    return (int) (*s1 - *s2);
181a966c04fSmrg}
182a966c04fSmrg
183a966c04fSmrg#endif
184a966c04fSmrg
185a966c04fSmrg/*
186a966c04fSmrg * return the default color key related to the given visual
187a966c04fSmrg */
188a966c04fSmrgstatic int
1892e2dd055SmrgxpmVisualType(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
2382e2dd055SmrgAllocColor(
2392e2dd055Smrg    Display	*display,
2402e2dd055Smrg    Colormap	 colormap,
2412e2dd055Smrg    char	*colorname,
2422e2dd055Smrg    XColor	*xcolor,
2432e2dd055Smrg    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
2612e2dd055SmrgSetCloseColor(
2622e2dd055Smrg    Display		*display,
2632e2dd055Smrg    Colormap		 colormap,
2642e2dd055Smrg    Visual		*visual,
2652e2dd055Smrg    XColor		*col,
2662e2dd055Smrg    Pixel		*image_pixel,
2672e2dd055Smrg    Pixel		*mask_pixel,
2682e2dd055Smrg    Pixel		*alloc_pixels,
2692e2dd055Smrg    unsigned int	*nalloc_pixels,
2702e2dd055Smrg    XpmAttributes	*attributes,
2712e2dd055Smrg    XColor		*cols,
2722e2dd055Smrg    int			 ncols,
2732e2dd055Smrg    XpmAllocColorFunc	 allocColor,
2742e2dd055Smrg    void		*closure)
275a966c04fSmrg{
276a966c04fSmrg
277a966c04fSmrg    /*
278a966c04fSmrg     * Allocation failed, so try close colors. To get here the visual must
279a966c04fSmrg     * be GreyScale, PseudoColor or DirectColor (or perhaps StaticColor?
280a966c04fSmrg     * What about sharing systems like QDSS?). Beware: we have to treat
281a966c04fSmrg     * DirectColor differently.
282a966c04fSmrg     */
283a966c04fSmrg
284a966c04fSmrg
285a966c04fSmrg    long int red_closeness, green_closeness, blue_closeness;
286a966c04fSmrg    int n;
287a966c04fSmrg    Bool alloc_color;
288a966c04fSmrg
289a966c04fSmrg    if (attributes && (attributes->valuemask & XpmCloseness))
290a966c04fSmrg	red_closeness = green_closeness = blue_closeness =
291a966c04fSmrg	    attributes->closeness;
292a966c04fSmrg    else {
293a966c04fSmrg	red_closeness = attributes->red_closeness;
294a966c04fSmrg	green_closeness = attributes->green_closeness;
295a966c04fSmrg	blue_closeness = attributes->blue_closeness;
296a966c04fSmrg    }
297a966c04fSmrg    if (attributes && (attributes->valuemask & XpmAllocCloseColors))
298a966c04fSmrg	alloc_color = attributes->alloc_close_colors;
299a966c04fSmrg    else
300a966c04fSmrg	alloc_color = True;
301a966c04fSmrg
302a966c04fSmrg    /*
303a966c04fSmrg     * We sort the colormap by closeness and try to allocate the color
304a966c04fSmrg     * closest to the target. If the allocation of this close color fails,
305a966c04fSmrg     * which almost never happens, then one of two scenarios is possible.
306a966c04fSmrg     * Either the colormap must have changed (since the last close color
307a966c04fSmrg     * allocation or possibly while we were sorting the colormap), or the
308a966c04fSmrg     * color is allocated as Read/Write by some other client. (Note: X
309a966c04fSmrg     * _should_ allow clients to check if a particular color is Read/Write,
310a966c04fSmrg     * but it doesn't! :-( ). We cannot determine which of these scenarios
311a966c04fSmrg     * occurred, so we try the next closest color, and so on, until no more
312a966c04fSmrg     * colors are within closeness of the target. If we knew that the
313a966c04fSmrg     * colormap had changed, we could skip this sequence.
314a966c04fSmrg     *
315a966c04fSmrg     * If _none_ of the colors within closeness of the target can be allocated,
316a966c04fSmrg     * then we can finally be pretty sure that the colormap has actually
317a966c04fSmrg     * changed. In this case we try to allocate the original color (again),
318a966c04fSmrg     * then try the closecolor stuff (again)...
319a966c04fSmrg     *
320a966c04fSmrg     * In theory it would be possible for an infinite loop to occur if another
321a966c04fSmrg     * process kept changing the colormap every time we sorted it, so we set
322a966c04fSmrg     * a maximum on the number of iterations. After this many tries, we use
323a966c04fSmrg     * XGrabServer() to ensure that the colormap remains unchanged.
324a966c04fSmrg     *
325a966c04fSmrg     * This approach gives particularly bad worst case performance - as many as
326a966c04fSmrg     * <MaximumIterations> colormap reads and sorts may be needed, and as
327a966c04fSmrg     * many as <MaximumIterations> * <ColormapSize> attempted allocations
328a966c04fSmrg     * may fail. On an 8-bit system, this means as many as 3 colormap reads,
329a966c04fSmrg     * 3 sorts and 768 failed allocations per execution of this code!
330a966c04fSmrg     * Luckily, my experiments show that in general use in a typical 8-bit
331a966c04fSmrg     * color environment only about 1 in every 10000 allocations fails to
332a966c04fSmrg     * succeed in the fastest possible time. So virtually every time what
333a966c04fSmrg     * actually happens is a single sort followed by a successful allocate.
334a966c04fSmrg     * The very first allocation also costs a colormap read, but no further
335a966c04fSmrg     * reads are usually necessary.
336a966c04fSmrg     */
337a966c04fSmrg
338a966c04fSmrg#define ITERATIONS 2			/* more than one is almost never
339a966c04fSmrg					 * necessary */
340a966c04fSmrg
341a966c04fSmrg    for (n = 0; n <= ITERATIONS; ++n) {
342a966c04fSmrg	CloseColor *closenesses =
343a966c04fSmrg	    (CloseColor *) XpmCalloc(ncols, sizeof(CloseColor));
344a966c04fSmrg	int i, c;
345a966c04fSmrg
346a966c04fSmrg	for (i = 0; i < ncols; ++i) {	/* build & sort closenesses table */
347a966c04fSmrg#define COLOR_FACTOR       3
348a966c04fSmrg#define BRIGHTNESS_FACTOR  1
349a966c04fSmrg
350a966c04fSmrg	    closenesses[i].cols_index = i;
351a966c04fSmrg	    closenesses[i].closeness =
352a966c04fSmrg		COLOR_FACTOR * (abs((long) col->red - (long) cols[i].red)
353a966c04fSmrg				+ abs((long) col->green - (long) cols[i].green)
354a966c04fSmrg				+ abs((long) col->blue - (long) cols[i].blue))
355a966c04fSmrg		+ BRIGHTNESS_FACTOR * abs(((long) col->red +
356a966c04fSmrg					   (long) col->green +
357a966c04fSmrg					   (long) col->blue)
358a966c04fSmrg					   - ((long) cols[i].red +
359a966c04fSmrg					      (long) cols[i].green +
360a966c04fSmrg					      (long) cols[i].blue));
361a966c04fSmrg	}
362a966c04fSmrg	qsort(closenesses, ncols, sizeof(CloseColor), closeness_cmp);
363a966c04fSmrg
364a966c04fSmrg	i = 0;
365a966c04fSmrg	c = closenesses[i].cols_index;
366a966c04fSmrg	while ((long) cols[c].red >= (long) col->red - red_closeness &&
367a966c04fSmrg	       (long) cols[c].red <= (long) col->red + red_closeness &&
368a966c04fSmrg	       (long) cols[c].green >= (long) col->green - green_closeness &&
369a966c04fSmrg	       (long) cols[c].green <= (long) col->green + green_closeness &&
370a966c04fSmrg	       (long) cols[c].blue >= (long) col->blue - blue_closeness &&
371a966c04fSmrg	       (long) cols[c].blue <= (long) col->blue + blue_closeness) {
372a966c04fSmrg	    if (alloc_color) {
373a966c04fSmrg		if ((*allocColor)(display, colormap, NULL, &cols[c], closure)){
374a966c04fSmrg		    if (n == ITERATIONS)
375a966c04fSmrg			XUngrabServer(display);
376a966c04fSmrg		    XpmFree(closenesses);
377a966c04fSmrg		    *image_pixel = cols[c].pixel;
378a966c04fSmrg		    *mask_pixel = 1;
379a966c04fSmrg		    alloc_pixels[(*nalloc_pixels)++] = cols[c].pixel;
380a966c04fSmrg		    return (0);
381a966c04fSmrg		} else {
382a966c04fSmrg		    ++i;
383a966c04fSmrg		    if (i == ncols)
384a966c04fSmrg			break;
385a966c04fSmrg		    c = closenesses[i].cols_index;
386a966c04fSmrg		}
387a966c04fSmrg	    } else {
388a966c04fSmrg		if (n == ITERATIONS)
389a966c04fSmrg		    XUngrabServer(display);
390a966c04fSmrg		XpmFree(closenesses);
391a966c04fSmrg		*image_pixel = cols[c].pixel;
392a966c04fSmrg		*mask_pixel = 1;
393a966c04fSmrg		return (0);
394a966c04fSmrg	    }
395a966c04fSmrg	}
396a966c04fSmrg
397a966c04fSmrg	/* Couldn't allocate _any_ of the close colors! */
398a966c04fSmrg
399a966c04fSmrg	if (n == ITERATIONS)
400a966c04fSmrg	    XUngrabServer(display);
401a966c04fSmrg	XpmFree(closenesses);
402a966c04fSmrg
403a966c04fSmrg	if (i == 0 || i == ncols)	/* no color close enough or cannot */
404a966c04fSmrg	    return (1);			/* alloc any color (full of r/w's) */
405a966c04fSmrg
406a966c04fSmrg	if ((*allocColor)(display, colormap, NULL, col, closure)) {
407a966c04fSmrg	    *image_pixel = col->pixel;
408a966c04fSmrg	    *mask_pixel = 1;
409a966c04fSmrg	    alloc_pixels[(*nalloc_pixels)++] = col->pixel;
410a966c04fSmrg	    return (0);
411a966c04fSmrg	} else {			/* colormap has probably changed, so
412a966c04fSmrg					 * re-read... */
413a966c04fSmrg	    if (n == ITERATIONS - 1)
414a966c04fSmrg		XGrabServer(display);
415a966c04fSmrg
416a966c04fSmrg#if 0
417a966c04fSmrg	    if (visual->class == DirectColor) {
418a966c04fSmrg		/* TODO */
419a966c04fSmrg	    } else
420a966c04fSmrg#endif
421a966c04fSmrg		XQueryColors(display, colormap, cols, ncols);
422a966c04fSmrg	}
423a966c04fSmrg    }
424a966c04fSmrg    return (1);
425a966c04fSmrg}
426a966c04fSmrg
427a966c04fSmrg#define USE_CLOSECOLOR attributes && \
428a966c04fSmrg(((attributes->valuemask & XpmCloseness) && attributes->closeness != 0) \
429a966c04fSmrg || ((attributes->valuemask & XpmRGBCloseness) && \
430a966c04fSmrg     (attributes->red_closeness != 0 \
431a966c04fSmrg      || attributes->green_closeness != 0 \
432a966c04fSmrg      || attributes->blue_closeness != 0)))
433a966c04fSmrg
434a966c04fSmrg#else
435a966c04fSmrg    /* FOR_MSW part */
436a966c04fSmrg    /* nothing to do here, the window system does it */
437a966c04fSmrg#endif
438a966c04fSmrg
439a966c04fSmrg/*
440a966c04fSmrg * set the color pixel related to the given colorname,
441a966c04fSmrg * return 0 if success, 1 otherwise.
442a966c04fSmrg */
443a966c04fSmrg
444a966c04fSmrgstatic int
4452e2dd055SmrgSetColor(
4462e2dd055Smrg    Display		*display,
4472e2dd055Smrg    Colormap		 colormap,
4482e2dd055Smrg    Visual		*visual,
4492e2dd055Smrg    char		*colorname,
4502e2dd055Smrg    unsigned int	 color_index,
4512e2dd055Smrg    Pixel		*image_pixel,
4522e2dd055Smrg    Pixel		*mask_pixel,
4532e2dd055Smrg    unsigned int	*mask_pixel_index,
4542e2dd055Smrg    Pixel		*alloc_pixels,
4552e2dd055Smrg    unsigned int	*nalloc_pixels,
4562e2dd055Smrg    Pixel		*used_pixels,
4572e2dd055Smrg    unsigned int	*nused_pixels,
4582e2dd055Smrg    XpmAttributes	*attributes,
4592e2dd055Smrg    XColor		*cols,
4602e2dd055Smrg    int			 ncols,
4612e2dd055Smrg    XpmAllocColorFunc	 allocColor,
4622e2dd055Smrg    void		*closure)
463a966c04fSmrg{
464a966c04fSmrg    XColor xcolor;
465a966c04fSmrg    int status;
466a966c04fSmrg
467a966c04fSmrg    if (xpmstrcasecmp(colorname, TRANSPARENT_COLOR)) {
468a966c04fSmrg	status = (*allocColor)(display, colormap, colorname, &xcolor, closure);
469a966c04fSmrg	if (status < 0)		/* parse color failed */
470a966c04fSmrg	    return (1);
471a966c04fSmrg
472a966c04fSmrg	if (status == 0) {
473a966c04fSmrg#ifndef FOR_MSW
474a966c04fSmrg	    if (USE_CLOSECOLOR)
475a966c04fSmrg		return (SetCloseColor(display, colormap, visual, &xcolor,
476a966c04fSmrg				      image_pixel, mask_pixel,
477a966c04fSmrg				      alloc_pixels, nalloc_pixels,
478a966c04fSmrg				      attributes, cols, ncols,
479a966c04fSmrg				      allocColor, closure));
480a966c04fSmrg	    else
481a966c04fSmrg#endif /* ndef FOR_MSW */
482a966c04fSmrg		return (1);
483a966c04fSmrg	} else
484a966c04fSmrg	    alloc_pixels[(*nalloc_pixels)++] = xcolor.pixel;
485a966c04fSmrg	*image_pixel = xcolor.pixel;
486a966c04fSmrg#ifndef FOR_MSW
487a966c04fSmrg	*mask_pixel = 1;
488a966c04fSmrg#else
489a966c04fSmrg	*mask_pixel = RGB(0,0,0);
490a966c04fSmrg#endif
491a966c04fSmrg	used_pixels[(*nused_pixels)++] = xcolor.pixel;
492a966c04fSmrg    } else {
493a966c04fSmrg	*image_pixel = 0;
494a966c04fSmrg#ifndef FOR_MSW
495a966c04fSmrg	*mask_pixel = 0;
496a966c04fSmrg#else
497a966c04fSmrg  	*mask_pixel = RGB(255,255,255);
498a966c04fSmrg#endif
499a966c04fSmrg	/* store the color table index */
500a966c04fSmrg	*mask_pixel_index = color_index;
501a966c04fSmrg    }
502a966c04fSmrg    return (0);
503a966c04fSmrg}
504a966c04fSmrg
505a966c04fSmrg
506a966c04fSmrgstatic int
5072e2dd055SmrgCreateColors(
5082e2dd055Smrg    Display		*display,
5092e2dd055Smrg    XpmAttributes	*attributes,
5102e2dd055Smrg    XpmColor		*colors,
5112e2dd055Smrg    unsigned int	 ncolors,
5122e2dd055Smrg    Pixel		*image_pixels,
5132e2dd055Smrg    Pixel		*mask_pixels,
5142e2dd055Smrg    unsigned int	*mask_pixel_index,
5152e2dd055Smrg    Pixel		*alloc_pixels,
5162e2dd055Smrg    unsigned int	*nalloc_pixels,
5172e2dd055Smrg    Pixel		*used_pixels,
5182e2dd055Smrg    unsigned int	*nused_pixels)
519a966c04fSmrg{
520a966c04fSmrg    /* variables stored in the XpmAttributes structure */
521a966c04fSmrg    Visual *visual;
522a966c04fSmrg    Colormap colormap;
523a966c04fSmrg    XpmColorSymbol *colorsymbols = NULL;
524a966c04fSmrg    unsigned int numsymbols;
525a966c04fSmrg    XpmAllocColorFunc allocColor;
526a966c04fSmrg    void *closure;
527a966c04fSmrg
528a966c04fSmrg    char *colorname;
529a966c04fSmrg    unsigned int color, key;
530a966c04fSmrg    Bool pixel_defined;
531a966c04fSmrg    XpmColorSymbol *symbol = NULL;
532a966c04fSmrg    char **defaults;
533a966c04fSmrg    int ErrorStatus = XpmSuccess;
534a966c04fSmrg    char *s;
535a966c04fSmrg    int default_index;
536a966c04fSmrg
537a966c04fSmrg    XColor *cols = NULL;
538a966c04fSmrg    unsigned int ncols = 0;
539a966c04fSmrg
540a966c04fSmrg    /*
541a966c04fSmrg     * retrieve information from the XpmAttributes
542a966c04fSmrg     */
543a966c04fSmrg    if (attributes && attributes->valuemask & XpmColorSymbols) {
544a966c04fSmrg	colorsymbols = attributes->colorsymbols;
545a966c04fSmrg	numsymbols = attributes->numsymbols;
546a966c04fSmrg    } else
547a966c04fSmrg	numsymbols = 0;
548a966c04fSmrg
549a966c04fSmrg    if (attributes && attributes->valuemask & XpmVisual)
550a966c04fSmrg	visual = attributes->visual;
551a966c04fSmrg    else
552a966c04fSmrg	visual = XDefaultVisual(display, XDefaultScreen(display));
553a966c04fSmrg
554a966c04fSmrg    if (attributes && (attributes->valuemask & XpmColormap))
555a966c04fSmrg	colormap = attributes->colormap;
556a966c04fSmrg    else
557a966c04fSmrg	colormap = XDefaultColormap(display, XDefaultScreen(display));
558a966c04fSmrg
559a966c04fSmrg    if (attributes && (attributes->valuemask & XpmColorKey))
560a966c04fSmrg	key = attributes->color_key;
561a966c04fSmrg    else
562a966c04fSmrg	key = xpmVisualType(visual);
563a966c04fSmrg
564a966c04fSmrg    if (attributes && (attributes->valuemask & XpmAllocColor))
565a966c04fSmrg	allocColor = attributes->alloc_color;
566a966c04fSmrg    else
567a966c04fSmrg	allocColor = AllocColor;
568a966c04fSmrg    if (attributes && (attributes->valuemask & XpmColorClosure))
569a966c04fSmrg	closure = attributes->color_closure;
570a966c04fSmrg    else
571a966c04fSmrg	closure = NULL;
572a966c04fSmrg
573a966c04fSmrg#ifndef FOR_MSW
574a966c04fSmrg    if (USE_CLOSECOLOR) {
575a966c04fSmrg	/* originally from SetCloseColor */
576a966c04fSmrg#if 0
577a966c04fSmrg	if (visual->class == DirectColor) {
578a966c04fSmrg
579a966c04fSmrg	    /*
580a966c04fSmrg	     * TODO: Implement close colors for DirectColor visuals. This is
581a966c04fSmrg	     * difficult situation. Chances are that we will never get here,
582a966c04fSmrg	     * because any machine that supports DirectColor will probably
583a966c04fSmrg	     * also support TrueColor (and probably PseudoColor). Also,
584a966c04fSmrg	     * DirectColor colormaps can be very large, so looking for close
585a966c04fSmrg	     * colors may be too slow.
586a966c04fSmrg	     */
587a966c04fSmrg	} else {
588a966c04fSmrg#endif
589a966c04fSmrg	    unsigned int i;
590a966c04fSmrg
591a966c04fSmrg#ifndef AMIGA
592a966c04fSmrg	    ncols = visual->map_entries;
593a966c04fSmrg#else
594a966c04fSmrg	    ncols = colormap->Count;
595a966c04fSmrg#endif
596a966c04fSmrg	    cols = (XColor *) XpmCalloc(ncols, sizeof(XColor));
597a966c04fSmrg	    for (i = 0; i < ncols; ++i)
598a966c04fSmrg		cols[i].pixel = i;
599a966c04fSmrg	    XQueryColors(display, colormap, cols, ncols);
600a966c04fSmrg#if 0
601a966c04fSmrg	}
602a966c04fSmrg#endif
603a966c04fSmrg    }
604a966c04fSmrg#endif /* ndef FOR_MSW */
605a966c04fSmrg
606a966c04fSmrg    switch (key) {
607a966c04fSmrg    case XPM_MONO:
608a966c04fSmrg	default_index = 2;
609a966c04fSmrg	break;
610a966c04fSmrg    case XPM_GRAY4:
611a966c04fSmrg	default_index = 3;
612a966c04fSmrg	break;
613a966c04fSmrg    case XPM_GRAY:
614a966c04fSmrg	default_index = 4;
615a966c04fSmrg	break;
616a966c04fSmrg    case XPM_COLOR:
617a966c04fSmrg    default:
618a966c04fSmrg	default_index = 5;
619a966c04fSmrg	break;
620a966c04fSmrg    }
621a966c04fSmrg
622a966c04fSmrg    for (color = 0; color < ncolors; color++, colors++,
623a966c04fSmrg					 image_pixels++, mask_pixels++) {
624a966c04fSmrg	colorname = NULL;
625a966c04fSmrg	pixel_defined = False;
626a966c04fSmrg	defaults = (char **) colors;
627a966c04fSmrg
628a966c04fSmrg	/*
629a966c04fSmrg	 * look for a defined symbol
630a966c04fSmrg	 */
631a966c04fSmrg	if (numsymbols) {
632a966c04fSmrg
633a966c04fSmrg	    unsigned int n;
634a966c04fSmrg
635a966c04fSmrg	    s = defaults[1];
636a966c04fSmrg	    for (n = 0, symbol = colorsymbols; n < numsymbols; n++, symbol++) {
637a966c04fSmrg		if (symbol->name && s && !strcmp(symbol->name, s))
638a966c04fSmrg		    /* override name */
639a966c04fSmrg		    break;
640a966c04fSmrg		if (!symbol->name && symbol->value) {	/* override value */
641a966c04fSmrg		    int def_index = default_index;
642a966c04fSmrg
643a966c04fSmrg		    while (defaults[def_index] == NULL)	/* find defined
644a966c04fSmrg							 * colorname */
645a966c04fSmrg			--def_index;
646a966c04fSmrg		    if (def_index < 2) {/* nothing towards mono, so try
647a966c04fSmrg					 * towards color */
648a966c04fSmrg			def_index = default_index + 1;
649a966c04fSmrg			while (def_index <= 5 && defaults[def_index] == NULL)
650a966c04fSmrg			    ++def_index;
651a966c04fSmrg		    }
652a966c04fSmrg		    if (def_index >= 2 && defaults[def_index] != NULL &&
653a966c04fSmrg			!xpmstrcasecmp(symbol->value, defaults[def_index]))
654a966c04fSmrg			break;
655a966c04fSmrg		}
656a966c04fSmrg	    }
657a966c04fSmrg	    if (n != numsymbols) {
658a966c04fSmrg		if (symbol->name && symbol->value)
659a966c04fSmrg		    colorname = symbol->value;
660a966c04fSmrg		else
661a966c04fSmrg		    pixel_defined = True;
662a966c04fSmrg	    }
663a966c04fSmrg	}
664a966c04fSmrg	if (!pixel_defined) {		/* pixel not given as symbol value */
665a966c04fSmrg
666a966c04fSmrg	    unsigned int k;
667a966c04fSmrg
668a966c04fSmrg	    if (colorname) {		/* colorname given as symbol value */
669a966c04fSmrg		if (!SetColor(display, colormap, visual, colorname, color,
670a966c04fSmrg			      image_pixels, mask_pixels, mask_pixel_index,
671a966c04fSmrg			      alloc_pixels, nalloc_pixels, used_pixels,
672a966c04fSmrg			      nused_pixels, attributes, cols, ncols,
673a966c04fSmrg			      allocColor, closure))
674a966c04fSmrg		    pixel_defined = True;
675a966c04fSmrg		else
676a966c04fSmrg		    ErrorStatus = XpmColorError;
677a966c04fSmrg	    }
678a966c04fSmrg	    k = key;
679a966c04fSmrg	    while (!pixel_defined && k > 1) {
680a966c04fSmrg		if (defaults[k]) {
681a966c04fSmrg		    if (!SetColor(display, colormap, visual, defaults[k],
682a966c04fSmrg				  color, image_pixels, mask_pixels,
683a966c04fSmrg				  mask_pixel_index, alloc_pixels,
684a966c04fSmrg				  nalloc_pixels, used_pixels, nused_pixels,
685a966c04fSmrg				  attributes, cols, ncols,
686a966c04fSmrg				  allocColor, closure)) {
687a966c04fSmrg			pixel_defined = True;
688a966c04fSmrg			break;
689a966c04fSmrg		    } else
690a966c04fSmrg			ErrorStatus = XpmColorError;
691a966c04fSmrg		}
692a966c04fSmrg		k--;
693a966c04fSmrg	    }
694a966c04fSmrg	    k = key + 1;
695a966c04fSmrg	    while (!pixel_defined && k < NKEYS + 1) {
696a966c04fSmrg		if (defaults[k]) {
697a966c04fSmrg		    if (!SetColor(display, colormap, visual, defaults[k],
698a966c04fSmrg				  color, image_pixels, mask_pixels,
699a966c04fSmrg				  mask_pixel_index, alloc_pixels,
700a966c04fSmrg				  nalloc_pixels, used_pixels, nused_pixels,
701a966c04fSmrg				  attributes, cols, ncols,
702a966c04fSmrg				  allocColor, closure)) {
703a966c04fSmrg			pixel_defined = True;
704a966c04fSmrg			break;
705a966c04fSmrg		    } else
706a966c04fSmrg			ErrorStatus = XpmColorError;
707a966c04fSmrg		}
708a966c04fSmrg		k++;
709a966c04fSmrg	    }
710a966c04fSmrg	    if (!pixel_defined) {
711a966c04fSmrg		if (cols)
712a966c04fSmrg		    XpmFree(cols);
713a966c04fSmrg		return (XpmColorFailed);
714a966c04fSmrg	    }
715a966c04fSmrg	} else {
716a966c04fSmrg	    /* simply use the given pixel */
717a966c04fSmrg	    *image_pixels = symbol->pixel;
718a966c04fSmrg	    /* the following makes the mask to be built even if none
719a966c04fSmrg	       is given a particular pixel */
720a966c04fSmrg	    if (symbol->value
721a966c04fSmrg		&& !xpmstrcasecmp(symbol->value, TRANSPARENT_COLOR)) {
722a966c04fSmrg		*mask_pixels = 0;
723a966c04fSmrg		*mask_pixel_index = color;
724a966c04fSmrg	    } else
725a966c04fSmrg		*mask_pixels = 1;
726a966c04fSmrg	    used_pixels[(*nused_pixels)++] = *image_pixels;
727a966c04fSmrg	}
728a966c04fSmrg    }
729a966c04fSmrg    if (cols)
730a966c04fSmrg	XpmFree(cols);
731a966c04fSmrg    return (ErrorStatus);
732a966c04fSmrg}
733a966c04fSmrg
734a966c04fSmrg
735a966c04fSmrg/* default FreeColors function, simply call XFreeColors */
736a966c04fSmrgstatic int
7372e2dd055SmrgFreeColors(
7382e2dd055Smrg    Display	*display,
7392e2dd055Smrg    Colormap	 colormap,
7402e2dd055Smrg    Pixel	*pixels,
7412e2dd055Smrg    int		 n,
7422e2dd055Smrg    void	*closure)		/* not used */
743a966c04fSmrg{
744a966c04fSmrg    return XFreeColors(display, colormap, pixels, n, 0);
745a966c04fSmrg}
746a966c04fSmrg
747a966c04fSmrg
748a966c04fSmrg/* function call in case of error */
749a966c04fSmrg
750a966c04fSmrg#undef RETURN
751a966c04fSmrg#define RETURN(status) \
752a966c04fSmrgdo \
753a966c04fSmrg{ \
754a966c04fSmrg      ErrorStatus = status; \
755a966c04fSmrg      goto error; \
756a966c04fSmrg} while(0)
757a966c04fSmrg
758a966c04fSmrgint
7592e2dd055SmrgXpmCreateImageFromXpmImage(
7602e2dd055Smrg    Display		 *display,
7612e2dd055Smrg    XpmImage		 *image,
7622e2dd055Smrg    XImage		**image_return,
7632e2dd055Smrg    XImage		**shapeimage_return,
7642e2dd055Smrg    XpmAttributes	 *attributes)
765a966c04fSmrg{
766a966c04fSmrg    /* variables stored in the XpmAttributes structure */
767a966c04fSmrg    Visual *visual;
768a966c04fSmrg    Colormap colormap;
769a966c04fSmrg    unsigned int depth;
770a966c04fSmrg    int bitmap_format;
771a966c04fSmrg    XpmFreeColorsFunc freeColors;
772a966c04fSmrg
773a966c04fSmrg    /* variables to return */
774a966c04fSmrg    XImage *ximage = NULL;
775a966c04fSmrg    XImage *shapeimage = NULL;
776a966c04fSmrg    unsigned int mask_pixel_index = XpmUndefPixel;
777a966c04fSmrg    int ErrorStatus;
778a966c04fSmrg
779a966c04fSmrg    /* calculation variables */
780a966c04fSmrg    Pixel *image_pixels = NULL;
781a966c04fSmrg    Pixel *mask_pixels = NULL;
782a966c04fSmrg    Pixel *alloc_pixels = NULL;
783a966c04fSmrg    Pixel *used_pixels = NULL;
784a966c04fSmrg    unsigned int nalloc_pixels = 0;
785a966c04fSmrg    unsigned int nused_pixels = 0;
786a966c04fSmrg
787a966c04fSmrg    /* initialize return values */
788a966c04fSmrg    if (image_return)
789a966c04fSmrg	*image_return = NULL;
790a966c04fSmrg    if (shapeimage_return)
791a966c04fSmrg	*shapeimage_return = NULL;
792a966c04fSmrg
793a966c04fSmrg    /* retrieve information from the XpmAttributes */
794a966c04fSmrg    if (attributes && (attributes->valuemask & XpmVisual))
795a966c04fSmrg	visual = attributes->visual;
796a966c04fSmrg    else
797a966c04fSmrg	visual = XDefaultVisual(display, XDefaultScreen(display));
798a966c04fSmrg
799a966c04fSmrg    if (attributes && (attributes->valuemask & XpmColormap))
800a966c04fSmrg	colormap = attributes->colormap;
801a966c04fSmrg    else
802a966c04fSmrg	colormap = XDefaultColormap(display, XDefaultScreen(display));
803a966c04fSmrg
804a966c04fSmrg    if (attributes && (attributes->valuemask & XpmDepth))
805a966c04fSmrg	depth = attributes->depth;
806a966c04fSmrg    else
807a966c04fSmrg	depth = XDefaultDepth(display, XDefaultScreen(display));
808a966c04fSmrg
809a966c04fSmrg    if (attributes && (attributes->valuemask & XpmBitmapFormat))
810a966c04fSmrg	bitmap_format = attributes->bitmap_format;
811a966c04fSmrg    else
812a966c04fSmrg	bitmap_format = ZPixmap;
813a966c04fSmrg
814a966c04fSmrg    if (attributes && (attributes->valuemask & XpmFreeColors))
815a966c04fSmrg	freeColors = attributes->free_colors;
816a966c04fSmrg    else
817a966c04fSmrg	freeColors = FreeColors;
818a966c04fSmrg
819a966c04fSmrg    ErrorStatus = XpmSuccess;
820a966c04fSmrg
821a966c04fSmrg    if (image->ncolors >= UINT_MAX / sizeof(Pixel))
822a966c04fSmrg	return (XpmNoMemory);
823a966c04fSmrg
824a966c04fSmrg    /* malloc pixels index tables */
825a966c04fSmrg    image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
826a966c04fSmrg    if (!image_pixels)
827a966c04fSmrg	return (XpmNoMemory);
828a966c04fSmrg
829a966c04fSmrg    mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
830a966c04fSmrg    if (!mask_pixels)
831a966c04fSmrg	RETURN(XpmNoMemory);
832a966c04fSmrg
833a966c04fSmrg    /* maximum of allocated pixels will be the number of colors */
834a966c04fSmrg    alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
835a966c04fSmrg    if (!alloc_pixels)
836a966c04fSmrg	RETURN(XpmNoMemory);
837a966c04fSmrg
838a966c04fSmrg    /* maximum of allocated pixels will be the number of colors */
839a966c04fSmrg    used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
840a966c04fSmrg    if (!used_pixels)
841a966c04fSmrg	RETURN(XpmNoMemory);
842a966c04fSmrg
843a966c04fSmrg    /* get pixel colors, store them in index tables */
844a966c04fSmrg    ErrorStatus = CreateColors(display, attributes, image->colorTable,
845a966c04fSmrg			       image->ncolors, image_pixels, mask_pixels,
846a966c04fSmrg			       &mask_pixel_index, alloc_pixels, &nalloc_pixels,
847a966c04fSmrg			       used_pixels, &nused_pixels);
848a966c04fSmrg
849a966c04fSmrg    if (ErrorStatus != XpmSuccess
850a966c04fSmrg	&& (ErrorStatus < 0 || (attributes
851a966c04fSmrg				&& (attributes->valuemask & XpmExactColors)
852a966c04fSmrg				&& attributes->exactColors)))
853a966c04fSmrg	RETURN(ErrorStatus);
854a966c04fSmrg
855a966c04fSmrg    /* create the ximage */
856a966c04fSmrg    if (image_return) {
857a966c04fSmrg	ErrorStatus = CreateXImage(display, visual, depth,
858a966c04fSmrg				   (depth == 1 ? bitmap_format : ZPixmap),
859a966c04fSmrg				   image->width, image->height, &ximage);
860a966c04fSmrg	if (ErrorStatus != XpmSuccess)
861a966c04fSmrg	    RETURN(ErrorStatus);
862a966c04fSmrg
863a966c04fSmrg#ifndef FOR_MSW
864a966c04fSmrg# ifndef AMIGA
865a966c04fSmrg
866a966c04fSmrg	/*
867a966c04fSmrg	 * set the ximage data using optimized functions for ZPixmap
868a966c04fSmrg	 */
869a966c04fSmrg
870a966c04fSmrg	if (ximage->bits_per_pixel == 8)
871a966c04fSmrg	    PutImagePixels8(ximage, image->width, image->height,
872a966c04fSmrg			    image->data, image_pixels);
873a966c04fSmrg	else if (((ximage->bits_per_pixel | ximage->depth) == 1) &&
874a966c04fSmrg		 (ximage->byte_order == ximage->bitmap_bit_order))
875a966c04fSmrg	    PutImagePixels1(ximage, image->width, image->height,
876a966c04fSmrg			    image->data, image_pixels);
877a966c04fSmrg	else if (ximage->bits_per_pixel == 16)
878a966c04fSmrg	    PutImagePixels16(ximage, image->width, image->height,
879a966c04fSmrg			     image->data, image_pixels);
880a966c04fSmrg	else if (ximage->bits_per_pixel == 32)
881a966c04fSmrg	    PutImagePixels32(ximage, image->width, image->height,
882a966c04fSmrg			     image->data, image_pixels);
883a966c04fSmrg	else
884a966c04fSmrg	    PutImagePixels(ximage, image->width, image->height,
885a966c04fSmrg			   image->data, image_pixels);
886a966c04fSmrg# else /* AMIGA */
887a966c04fSmrg	APutImagePixels(ximage, image->width, image->height,
888a966c04fSmrg			image->data, image_pixels);
889a966c04fSmrg# endif
890a966c04fSmrg#else  /* FOR_MSW */
891a966c04fSmrg	MSWPutImagePixels(display, ximage, image->width, image->height,
892a966c04fSmrg			  image->data, image_pixels);
893a966c04fSmrg#endif
894a966c04fSmrg    }
895a966c04fSmrg    /* create the shape mask image */
896a966c04fSmrg    if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
897a966c04fSmrg	ErrorStatus = CreateXImage(display, visual, 1, bitmap_format,
898a966c04fSmrg				   image->width, image->height, &shapeimage);
899a966c04fSmrg	if (ErrorStatus != XpmSuccess)
900a966c04fSmrg	    RETURN(ErrorStatus);
901a966c04fSmrg
902a966c04fSmrg#ifndef FOR_MSW
903a966c04fSmrg# ifndef AMIGA
904a966c04fSmrg	PutImagePixels1(shapeimage, image->width, image->height,
905a966c04fSmrg			image->data, mask_pixels);
906a966c04fSmrg# else /* AMIGA */
907a966c04fSmrg	APutImagePixels(shapeimage, image->width, image->height,
908a966c04fSmrg			image->data, mask_pixels);
909a966c04fSmrg# endif
910a966c04fSmrg#else  /* FOR_MSW */
911a966c04fSmrg	MSWPutImagePixels(display, shapeimage, image->width, image->height,
912a966c04fSmrg			  image->data, mask_pixels);
913a966c04fSmrg#endif
914a966c04fSmrg
915a966c04fSmrg    }
916a966c04fSmrg    XpmFree(image_pixels);
917a966c04fSmrg    XpmFree(mask_pixels);
918a966c04fSmrg
919a966c04fSmrg    /* if requested return used pixels in the XpmAttributes structure */
920a966c04fSmrg    if (attributes && (attributes->valuemask & XpmReturnPixels ||
921a966c04fSmrg/* 3.2 backward compatibility code */
922a966c04fSmrg	attributes->valuemask & XpmReturnInfos)) {
923a966c04fSmrg/* end 3.2 bc */
924a966c04fSmrg	attributes->pixels = used_pixels;
925a966c04fSmrg	attributes->npixels = nused_pixels;
926a966c04fSmrg	attributes->mask_pixel = mask_pixel_index;
927a966c04fSmrg    } else
928a966c04fSmrg	XpmFree(used_pixels);
929a966c04fSmrg
930a966c04fSmrg    /* if requested return alloc'ed pixels in the XpmAttributes structure */
931a966c04fSmrg    if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
932a966c04fSmrg	attributes->alloc_pixels = alloc_pixels;
933a966c04fSmrg	attributes->nalloc_pixels = nalloc_pixels;
934a966c04fSmrg    } else
935a966c04fSmrg	XpmFree(alloc_pixels);
936a966c04fSmrg
937a966c04fSmrg    /* return created images */
938a966c04fSmrg    if (image_return)
939a966c04fSmrg	*image_return = ximage;
940a966c04fSmrg    if (shapeimage_return)
941a966c04fSmrg	*shapeimage_return = shapeimage;
942a966c04fSmrg
943a966c04fSmrg    return (ErrorStatus);
944a966c04fSmrg
945a966c04fSmrg/* exit point in case of error, free only locally allocated variables */
946a966c04fSmrgerror:
947a966c04fSmrg    if (ximage)
948a966c04fSmrg	XDestroyImage(ximage);
949a966c04fSmrg    if (shapeimage)
950a966c04fSmrg	XDestroyImage(shapeimage);
951a966c04fSmrg    if (image_pixels)
952a966c04fSmrg	XpmFree(image_pixels);
953a966c04fSmrg    if (mask_pixels)
954a966c04fSmrg	XpmFree(mask_pixels);
955a966c04fSmrg    if (nalloc_pixels)
956a966c04fSmrg	(*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL);
957a966c04fSmrg    if (alloc_pixels)
958a966c04fSmrg	XpmFree(alloc_pixels);
959a966c04fSmrg    if (used_pixels)
960a966c04fSmrg	XpmFree(used_pixels);
961a966c04fSmrg
962a966c04fSmrg    return (ErrorStatus);
963a966c04fSmrg}
964a966c04fSmrg
965a966c04fSmrg
966a966c04fSmrg/*
967a966c04fSmrg * Create an XImage with its data
968a966c04fSmrg */
969a966c04fSmrgstatic int
9702e2dd055SmrgCreateXImage(
9712e2dd055Smrg    Display	 *display,
9722e2dd055Smrg    Visual	 *visual,
9732e2dd055Smrg    unsigned int  depth,
9742e2dd055Smrg    int		  format,
9752e2dd055Smrg    unsigned int  width,
9762e2dd055Smrg    unsigned int  height,
9772e2dd055Smrg    XImage	**image_return)
978a966c04fSmrg{
979a966c04fSmrg    int bitmap_pad;
980a966c04fSmrg
981a966c04fSmrg    /* first get bitmap_pad */
982a966c04fSmrg    if (depth > 16)
983a966c04fSmrg	bitmap_pad = 32;
984a966c04fSmrg    else if (depth > 8)
985a966c04fSmrg	bitmap_pad = 16;
986a966c04fSmrg    else
987a966c04fSmrg	bitmap_pad = 8;
988a966c04fSmrg
989a966c04fSmrg    /* then create the XImage with data = NULL and bytes_per_line = 0 */
990a966c04fSmrg    *image_return = XCreateImage(display, visual, depth, format, 0, 0,
991a966c04fSmrg				 width, height, bitmap_pad, 0);
992a966c04fSmrg    if (!*image_return)
993a966c04fSmrg	return (XpmNoMemory);
994a966c04fSmrg
995a966c04fSmrg#if !defined(FOR_MSW) && !defined(AMIGA)
996a966c04fSmrg    if (height != 0 && (*image_return)->bytes_per_line >= INT_MAX / height) {
997a966c04fSmrg	XDestroyImage(*image_return);
998a966c04fSmrg	return XpmNoMemory;
999a966c04fSmrg    }
1000a966c04fSmrg    /* now that bytes_per_line must have been set properly alloc data */
1001a966c04fSmrg    if((*image_return)->bytes_per_line == 0 ||  height == 0)
1002a966c04fSmrg    	return XpmNoMemory;
1003a966c04fSmrg    (*image_return)->data =
1004a966c04fSmrg	(char *) XpmMalloc((*image_return)->bytes_per_line * height);
1005a966c04fSmrg
1006a966c04fSmrg    if (!(*image_return)->data) {
1007a966c04fSmrg	XDestroyImage(*image_return);
1008a966c04fSmrg	*image_return = NULL;
1009a966c04fSmrg	return (XpmNoMemory);
1010a966c04fSmrg    }
1011a966c04fSmrg#else
1012a966c04fSmrg    /* under FOR_MSW and AMIGA XCreateImage has done it all */
1013a966c04fSmrg#endif
1014a966c04fSmrg    return (XpmSuccess);
1015a966c04fSmrg}
1016a966c04fSmrg
1017a966c04fSmrg#ifndef FOR_MSW
1018a966c04fSmrg# ifndef AMIGA
1019a966c04fSmrg/*
1020a966c04fSmrg * The functions below are written from X11R5 MIT's code (XImUtil.c)
1021a966c04fSmrg *
1022a966c04fSmrg * The idea is to have faster functions than the standard XPutPixel function
1023a966c04fSmrg * to build the image data. Indeed we can speed up things by suppressing tests
1024a966c04fSmrg * performed for each pixel. We do the same tests but at the image level.
1025a966c04fSmrg * We also assume that we use only ZPixmap images with null offsets.
1026a966c04fSmrg */
1027a966c04fSmrg
1028a966c04fSmrgLFUNC(_putbits, void, (register char *src, int dstoffset,
1029a966c04fSmrg		       register int numbits, register char *dst));
1030a966c04fSmrg
1031a966c04fSmrgLFUNC(_XReverse_Bytes, int, (register unsigned char *bpt, register unsigned int nb));
1032a966c04fSmrg
1033a966c04fSmrgstatic unsigned char Const _reverse_byte[0x100] = {
1034a966c04fSmrg    0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
1035a966c04fSmrg    0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1036a966c04fSmrg    0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1037a966c04fSmrg    0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1038a966c04fSmrg    0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
1039a966c04fSmrg    0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1040a966c04fSmrg    0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
1041a966c04fSmrg    0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1042a966c04fSmrg    0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1043a966c04fSmrg    0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1044a966c04fSmrg    0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1045a966c04fSmrg    0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1046a966c04fSmrg    0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1047a966c04fSmrg    0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1048a966c04fSmrg    0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1049a966c04fSmrg    0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1050a966c04fSmrg    0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1051a966c04fSmrg    0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1052a966c04fSmrg    0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1053a966c04fSmrg    0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1054a966c04fSmrg    0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1055a966c04fSmrg    0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1056a966c04fSmrg    0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1057a966c04fSmrg    0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1058a966c04fSmrg    0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1059a966c04fSmrg    0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1060a966c04fSmrg    0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1061a966c04fSmrg    0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1062a966c04fSmrg    0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1063a966c04fSmrg    0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1064a966c04fSmrg    0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1065a966c04fSmrg    0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
1066a966c04fSmrg};
1067a966c04fSmrg
1068a966c04fSmrgstatic int
10692e2dd055Smrg_XReverse_Bytes(
10702e2dd055Smrg    register unsigned char	*bpt,
10712e2dd055Smrg    register unsigned int	 nb)
1072a966c04fSmrg{
1073a966c04fSmrg    do {
1074a966c04fSmrg	*bpt = _reverse_byte[*bpt];
1075a966c04fSmrg	bpt++;
1076a966c04fSmrg    } while (--nb > 0); /* is nb user-controled? */
1077a966c04fSmrg    return 0;
1078a966c04fSmrg}
1079a966c04fSmrg
1080a966c04fSmrg
1081a966c04fSmrgvoid
10822e2dd055Smrgxpm_xynormalizeimagebits(
10832e2dd055Smrg    register unsigned char	*bp,
10842e2dd055Smrg    register XImage		*img)
1085a966c04fSmrg{
1086a966c04fSmrg    register unsigned char c;
1087a966c04fSmrg
1088a966c04fSmrg    if (img->byte_order != img->bitmap_bit_order) {
1089a966c04fSmrg	switch (img->bitmap_unit) {
1090a966c04fSmrg
1091a966c04fSmrg	case 16:
1092a966c04fSmrg	    c = *bp;
1093a966c04fSmrg	    *bp = *(bp + 1);
1094a966c04fSmrg	    *(bp + 1) = c;
1095a966c04fSmrg	    break;
1096a966c04fSmrg
1097a966c04fSmrg	case 32:
1098a966c04fSmrg	    c = *(bp + 3);
1099a966c04fSmrg	    *(bp + 3) = *bp;
1100a966c04fSmrg	    *bp = c;
1101a966c04fSmrg	    c = *(bp + 2);
1102a966c04fSmrg	    *(bp + 2) = *(bp + 1);
1103a966c04fSmrg	    *(bp + 1) = c;
1104a966c04fSmrg	    break;
1105a966c04fSmrg	}
1106a966c04fSmrg    }
1107a966c04fSmrg    if (img->bitmap_bit_order == MSBFirst)
1108a966c04fSmrg	_XReverse_Bytes(bp, img->bitmap_unit >> 3);
1109a966c04fSmrg}
1110a966c04fSmrg
1111a966c04fSmrgvoid
11122e2dd055Smrgxpm_znormalizeimagebits(
11132e2dd055Smrg    register unsigned char	*bp,
11142e2dd055Smrg    register XImage		*img)
1115a966c04fSmrg{
1116a966c04fSmrg    register unsigned char c;
1117a966c04fSmrg
1118a966c04fSmrg    switch (img->bits_per_pixel) {
1119a966c04fSmrg
1120a966c04fSmrg    case 2:
1121a966c04fSmrg	_XReverse_Bytes(bp, 1);
1122a966c04fSmrg	break;
1123a966c04fSmrg
1124a966c04fSmrg    case 4:
1125a966c04fSmrg	*bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF);
1126a966c04fSmrg	break;
1127a966c04fSmrg
1128a966c04fSmrg    case 16:
1129a966c04fSmrg	c = *bp;
1130a966c04fSmrg	*bp = *(bp + 1);
1131a966c04fSmrg	*(bp + 1) = c;
1132a966c04fSmrg	break;
1133a966c04fSmrg
1134a966c04fSmrg    case 24:
1135a966c04fSmrg	c = *(bp + 2);
1136a966c04fSmrg	*(bp + 2) = *bp;
1137a966c04fSmrg	*bp = c;
1138a966c04fSmrg	break;
1139a966c04fSmrg
1140a966c04fSmrg    case 32:
1141a966c04fSmrg	c = *(bp + 3);
1142a966c04fSmrg	*(bp + 3) = *bp;
1143a966c04fSmrg	*bp = c;
1144a966c04fSmrg	c = *(bp + 2);
1145a966c04fSmrg	*(bp + 2) = *(bp + 1);
1146a966c04fSmrg	*(bp + 1) = c;
1147a966c04fSmrg	break;
1148a966c04fSmrg    }
1149a966c04fSmrg}
1150a966c04fSmrg
1151a966c04fSmrgstatic unsigned char Const _lomask[0x09] = {
1152a966c04fSmrg0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
1153a966c04fSmrgstatic unsigned char Const _himask[0x09] = {
1154a966c04fSmrg0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
1155a966c04fSmrg
1156a966c04fSmrgstatic void
11572e2dd055Smrg_putbits(
11582e2dd055Smrg    register char	*src,		/* address of source bit string */
11592e2dd055Smrg    int			 dstoffset,	/* bit offset into destination;
1160a966c04fSmrg					 * range is 0-31 */
11612e2dd055Smrg    register int	 numbits,	/* number of bits to copy to
1162a966c04fSmrg					 * destination */
11632e2dd055Smrg    register char	*dst)		/* address of destination bit string */
1164a966c04fSmrg{
1165a966c04fSmrg    register unsigned char chlo, chhi;
1166a966c04fSmrg    int hibits;
1167a966c04fSmrg
1168a966c04fSmrg    dst = dst + (dstoffset >> 3);
1169a966c04fSmrg    dstoffset = dstoffset & 7;
1170a966c04fSmrg    hibits = 8 - dstoffset;
1171a966c04fSmrg    chlo = *dst & _lomask[dstoffset];
1172a966c04fSmrg    for (;;) {
1173a966c04fSmrg	chhi = (*src << dstoffset) & _himask[dstoffset];
1174a966c04fSmrg	if (numbits <= hibits) {
1175a966c04fSmrg	    chhi = chhi & _lomask[dstoffset + numbits];
1176a966c04fSmrg	    *dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi;
1177a966c04fSmrg	    break;
1178a966c04fSmrg	}
1179a966c04fSmrg	*dst = chhi | chlo;
1180a966c04fSmrg	dst++;
1181a966c04fSmrg	numbits = numbits - hibits;
1182a966c04fSmrg	chlo = (unsigned char) (*src & _himask[hibits]) >> hibits;
1183a966c04fSmrg	src++;
1184a966c04fSmrg	if (numbits <= dstoffset) {
1185a966c04fSmrg	    chlo = chlo & _lomask[numbits];
1186a966c04fSmrg	    *dst = (*dst & _himask[numbits]) | chlo;
1187a966c04fSmrg	    break;
1188a966c04fSmrg	}
1189a966c04fSmrg	numbits = numbits - dstoffset;
1190a966c04fSmrg    }
1191a966c04fSmrg}
1192a966c04fSmrg
1193a966c04fSmrg/*
1194a966c04fSmrg * Default method to write pixels into a Z image data structure.
1195a966c04fSmrg * The algorithm used is:
1196a966c04fSmrg *
1197a966c04fSmrg *	copy the destination bitmap_unit or Zpixel to temp
1198a966c04fSmrg *	normalize temp if needed
1199a966c04fSmrg *	copy the pixel bits into the temp
1200a966c04fSmrg *	renormalize temp if needed
1201a966c04fSmrg *	copy the temp back into the destination image data
1202a966c04fSmrg */
1203a966c04fSmrg
1204a966c04fSmrgstatic void
12052e2dd055SmrgPutImagePixels(
12062e2dd055Smrg    XImage		*image,
12072e2dd055Smrg    unsigned int	 width,
12082e2dd055Smrg    unsigned int	 height,
12092e2dd055Smrg    unsigned int	*pixelindex,
12102e2dd055Smrg    Pixel		*pixels)
1211a966c04fSmrg{
1212a966c04fSmrg    register char *src;
1213a966c04fSmrg    register char *dst;
1214a966c04fSmrg    register unsigned int *iptr;
1215a966c04fSmrg    register unsigned int x, y;
1216a966c04fSmrg    register char *data;
1217a966c04fSmrg    Pixel pixel, px;
1218a966c04fSmrg    int nbytes, depth, ibu, ibpp, i;
1219a966c04fSmrg
1220a966c04fSmrg    data = image->data;
1221a966c04fSmrg    iptr = pixelindex;
1222a966c04fSmrg    depth = image->depth;
1223a966c04fSmrg    if (depth == 1) {
1224a966c04fSmrg	ibu = image->bitmap_unit;
1225a966c04fSmrg	for (y = 0; y < height; y++) /* how can we trust height */
1226a966c04fSmrg	    for (x = 0; x < width; x++, iptr++) { /* how can we trust width */
1227a966c04fSmrg		pixel = pixels[*iptr];
1228a966c04fSmrg		for (i = 0, px = pixel; i < sizeof(unsigned long);
1229a966c04fSmrg		     i++, px >>= 8)
1230a966c04fSmrg		    ((unsigned char *) &pixel)[i] = px;
1231a966c04fSmrg		src = &data[XYINDEX(x, y, image)];
1232a966c04fSmrg		dst = (char *) &px;
1233a966c04fSmrg		px = 0;
1234a966c04fSmrg		nbytes = ibu >> 3;
1235a966c04fSmrg		for (i = nbytes; --i >= 0;)
1236a966c04fSmrg		    *dst++ = *src++;
1237a966c04fSmrg		XYNORMALIZE(&px, image);
1238a966c04fSmrg		_putbits((char *) &pixel, (x % ibu), 1, (char *) &px);
1239a966c04fSmrg		XYNORMALIZE(&px, image);
1240a966c04fSmrg		src = (char *) &px;
1241a966c04fSmrg		dst = &data[XYINDEX(x, y, image)];
1242a966c04fSmrg		for (i = nbytes; --i >= 0;)
1243a966c04fSmrg		    *dst++ = *src++;
1244a966c04fSmrg	    }
1245a966c04fSmrg    } else {
1246a966c04fSmrg	ibpp = image->bits_per_pixel;
1247a966c04fSmrg	for (y = 0; y < height; y++)
1248a966c04fSmrg	    for (x = 0; x < width; x++, iptr++) {
1249a966c04fSmrg		pixel = pixels[*iptr];
1250a966c04fSmrg		if (depth == 4)
1251a966c04fSmrg		    pixel &= 0xf;
1252a966c04fSmrg		for (i = 0, px = pixel; i < sizeof(unsigned long); i++,
1253a966c04fSmrg		     px >>= 8)
1254a966c04fSmrg		    ((unsigned char *) &pixel)[i] = px;
1255a966c04fSmrg		src = &data[ZINDEX(x, y, image)];
1256a966c04fSmrg		dst = (char *) &px;
1257a966c04fSmrg		px = 0;
1258a966c04fSmrg		nbytes = (ibpp + 7) >> 3;
1259a966c04fSmrg		for (i = nbytes; --i >= 0;)
1260a966c04fSmrg		    *dst++ = *src++;
1261a966c04fSmrg		ZNORMALIZE(&px, image);
1262a966c04fSmrg		_putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
1263a966c04fSmrg		ZNORMALIZE(&px, image);
1264a966c04fSmrg		src = (char *) &px;
1265a966c04fSmrg		dst = &data[ZINDEX(x, y, image)];
1266a966c04fSmrg		for (i = nbytes; --i >= 0;)
1267a966c04fSmrg		    *dst++ = *src++;
1268a966c04fSmrg	    }
1269a966c04fSmrg    }
1270a966c04fSmrg}
1271a966c04fSmrg
1272a966c04fSmrg/*
1273a966c04fSmrg * write pixels into a 32-bits Z image data structure
1274a966c04fSmrg */
1275a966c04fSmrg
1276a966c04fSmrg#if !defined(WORD64) && !defined(LONG64)
1277a966c04fSmrg/* this item is static but deterministic so let it slide; doesn't
1278a966c04fSmrg * hurt re-entrancy of this library. Note if it is actually const then would
1279a966c04fSmrg * be OK under rules of ANSI-C but probably not C++ which may not
1280a966c04fSmrg * want to allocate space for it.
1281a966c04fSmrg */
1282a966c04fSmrgstatic unsigned long byteorderpixel = MSBFirst << 24;
1283a966c04fSmrg
1284a966c04fSmrg#endif
1285a966c04fSmrg
1286a966c04fSmrg/*
1287a966c04fSmrg   WITHOUT_SPEEDUPS is a flag to be turned on if you wish to use the original
1288a966c04fSmrg   3.2e code - by default you get the speeded-up version.
1289a966c04fSmrg*/
1290a966c04fSmrg
1291a966c04fSmrgstatic void
12922e2dd055SmrgPutImagePixels32(
12932e2dd055Smrg    XImage		*image,
12942e2dd055Smrg    unsigned int	 width,
12952e2dd055Smrg    unsigned int	 height,
12962e2dd055Smrg    unsigned int	*pixelindex,
12972e2dd055Smrg    Pixel		*pixels)
1298a966c04fSmrg{
1299a966c04fSmrg    unsigned char *data;
1300a966c04fSmrg    unsigned int *iptr;
1301a966c04fSmrg    unsigned int y;
1302a966c04fSmrg    Pixel pixel;
1303a966c04fSmrg
1304a966c04fSmrg#ifdef WITHOUT_SPEEDUPS
1305a966c04fSmrg
1306a966c04fSmrg    unsigned int x;
1307a966c04fSmrg    unsigned char *addr;
1308a966c04fSmrg
1309a966c04fSmrg    data = (unsigned char *) image->data;
1310a966c04fSmrg    iptr = pixelindex;
1311a966c04fSmrg#if !defined(WORD64) && !defined(LONG64)
1312a966c04fSmrg    if (*((char *) &byteorderpixel) == image->byte_order) {
1313a966c04fSmrg	for (y = 0; y < height; y++)
1314a966c04fSmrg	    for (x = 0; x < width; x++, iptr++) {
1315a966c04fSmrg		addr = &data[ZINDEX32(x, y, image)];
1316a966c04fSmrg		*((unsigned long *) addr) = pixels[*iptr];
1317a966c04fSmrg	    }
1318a966c04fSmrg    } else
1319a966c04fSmrg#endif
1320a966c04fSmrg    if (image->byte_order == MSBFirst)
1321a966c04fSmrg	for (y = 0; y < height; y++)
1322a966c04fSmrg	    for (x = 0; x < width; x++, iptr++) {
1323a966c04fSmrg		addr = &data[ZINDEX32(x, y, image)];
1324a966c04fSmrg		pixel = pixels[*iptr];
1325a966c04fSmrg		addr[0] = pixel >> 24;
1326a966c04fSmrg		addr[1] = pixel >> 16;
1327a966c04fSmrg		addr[2] = pixel >> 8;
1328a966c04fSmrg		addr[3] = pixel;
1329a966c04fSmrg	    }
1330a966c04fSmrg    else
1331a966c04fSmrg	for (y = 0; y < height; y++)
1332a966c04fSmrg	    for (x = 0; x < width; x++, iptr++) {
1333a966c04fSmrg		addr = &data[ZINDEX32(x, y, image)];
1334a966c04fSmrg		pixel = pixels[*iptr];
1335a966c04fSmrg		addr[0] = pixel;
1336a966c04fSmrg		addr[1] = pixel >> 8;
1337a966c04fSmrg		addr[2] = pixel >> 16;
1338a966c04fSmrg		addr[3] = pixel >> 24;
1339a966c04fSmrg	    }
1340a966c04fSmrg
1341a966c04fSmrg#else  /* WITHOUT_SPEEDUPS */
1342a966c04fSmrg
1343a966c04fSmrg    unsigned int bpl = image->bytes_per_line;
1344a966c04fSmrg    unsigned char *data_ptr, *max_data;
1345a966c04fSmrg
1346a966c04fSmrg    data = (unsigned char *) image->data;
1347a966c04fSmrg    iptr = pixelindex;
1348a966c04fSmrg#if !defined(WORD64) && !defined(LONG64)
1349a966c04fSmrg    if (*((char *) &byteorderpixel) == image->byte_order) {
1350a966c04fSmrg	for (y = 0; y < height; y++) {
1351a966c04fSmrg	    data_ptr = data;
1352a966c04fSmrg	    max_data = data_ptr + (width << 2);
1353a966c04fSmrg
1354a966c04fSmrg	    while (data_ptr < max_data) {
1355a966c04fSmrg		*((unsigned long *) data_ptr) = pixels[*(iptr++)];
1356a966c04fSmrg		data_ptr += (1 << 2);
1357a966c04fSmrg	    }
1358a966c04fSmrg	    data += bpl;
1359a966c04fSmrg	}
1360a966c04fSmrg    } else
1361a966c04fSmrg#endif
1362a966c04fSmrg    if (image->byte_order == MSBFirst)
1363a966c04fSmrg	for (y = 0; y < height; y++) {
1364a966c04fSmrg	    data_ptr = data;
1365a966c04fSmrg	    max_data = data_ptr + (width << 2);
1366a966c04fSmrg
1367a966c04fSmrg	    while (data_ptr < max_data) {
1368a966c04fSmrg		pixel = pixels[*(iptr++)];
1369a966c04fSmrg
1370a966c04fSmrg		*data_ptr++ = pixel >> 24;
1371a966c04fSmrg		*data_ptr++ = pixel >> 16;
1372a966c04fSmrg		*data_ptr++ = pixel >> 8;
1373a966c04fSmrg		*data_ptr++ = pixel;
1374a966c04fSmrg
1375a966c04fSmrg	    }
1376a966c04fSmrg	    data += bpl;
1377a966c04fSmrg	}
1378a966c04fSmrg    else
1379a966c04fSmrg	for (y = 0; y < height; y++) {
1380a966c04fSmrg	    data_ptr = data;
1381a966c04fSmrg	    max_data = data_ptr + (width << 2);
1382a966c04fSmrg
1383a966c04fSmrg	    while (data_ptr < max_data) {
1384a966c04fSmrg		pixel = pixels[*(iptr++)];
1385a966c04fSmrg
1386a966c04fSmrg		*data_ptr++ = pixel;
1387a966c04fSmrg		*data_ptr++ = pixel >> 8;
1388a966c04fSmrg		*data_ptr++ = pixel >> 16;
1389a966c04fSmrg		*data_ptr++ = pixel >> 24;
1390a966c04fSmrg	    }
1391a966c04fSmrg	    data += bpl;
1392a966c04fSmrg	}
1393a966c04fSmrg
1394a966c04fSmrg#endif /* WITHOUT_SPEEDUPS */
1395a966c04fSmrg}
1396a966c04fSmrg
1397a966c04fSmrg/*
1398a966c04fSmrg * write pixels into a 16-bits Z image data structure
1399a966c04fSmrg */
1400a966c04fSmrg
1401a966c04fSmrgstatic void
14022e2dd055SmrgPutImagePixels16(
14032e2dd055Smrg    XImage		*image,
14042e2dd055Smrg    unsigned int	 width,
14052e2dd055Smrg    unsigned int	 height,
14062e2dd055Smrg    unsigned int	*pixelindex,
14072e2dd055Smrg    Pixel		*pixels)
1408a966c04fSmrg{
1409a966c04fSmrg    unsigned char *data;
1410a966c04fSmrg    unsigned int *iptr;
1411a966c04fSmrg    unsigned int y;
1412a966c04fSmrg
1413a966c04fSmrg#ifdef WITHOUT_SPEEDUPS
1414a966c04fSmrg
1415a966c04fSmrg    unsigned int x;
1416a966c04fSmrg    unsigned char *addr;
1417a966c04fSmrg
1418a966c04fSmrg    data = (unsigned char *) image->data;
1419a966c04fSmrg    iptr = pixelindex;
1420a966c04fSmrg    if (image->byte_order == MSBFirst)
1421a966c04fSmrg	for (y = 0; y < height; y++)
1422a966c04fSmrg	    for (x = 0; x < width; x++, iptr++) {
1423a966c04fSmrg		addr = &data[ZINDEX16(x, y, image)];
1424a966c04fSmrg		addr[0] = pixels[*iptr] >> 8;
1425a966c04fSmrg		addr[1] = pixels[*iptr];
1426a966c04fSmrg	    }
1427a966c04fSmrg    else
1428a966c04fSmrg	for (y = 0; y < height; y++)
1429a966c04fSmrg	    for (x = 0; x < width; x++, iptr++) {
1430a966c04fSmrg		addr = &data[ZINDEX16(x, y, image)];
1431a966c04fSmrg		addr[0] = pixels[*iptr];
1432a966c04fSmrg		addr[1] = pixels[*iptr] >> 8;
1433a966c04fSmrg	    }
1434a966c04fSmrg
1435a966c04fSmrg#else  /* WITHOUT_SPEEDUPS */
1436a966c04fSmrg
1437a966c04fSmrg    Pixel pixel;
1438a966c04fSmrg
1439a966c04fSmrg    unsigned int bpl = image->bytes_per_line;
1440a966c04fSmrg    unsigned char *data_ptr, *max_data;
1441a966c04fSmrg
1442a966c04fSmrg    data = (unsigned char *) image->data;
1443a966c04fSmrg    iptr = pixelindex;
1444a966c04fSmrg    if (image->byte_order == MSBFirst)
1445a966c04fSmrg	for (y = 0; y < height; y++) {
1446a966c04fSmrg	    data_ptr = data;
1447a966c04fSmrg	    max_data = data_ptr + (width << 1);
1448a966c04fSmrg
1449a966c04fSmrg	    while (data_ptr < max_data) {
1450a966c04fSmrg		pixel = pixels[*(iptr++)];
1451a966c04fSmrg
1452a966c04fSmrg		data_ptr[0] = pixel >> 8;
1453a966c04fSmrg		data_ptr[1] = pixel;
1454a966c04fSmrg
1455a966c04fSmrg		data_ptr += (1 << 1);
1456a966c04fSmrg	    }
1457a966c04fSmrg	    data += bpl;
1458a966c04fSmrg	}
1459a966c04fSmrg    else
1460a966c04fSmrg	for (y = 0; y < height; y++) {
1461a966c04fSmrg	    data_ptr = data;
1462a966c04fSmrg	    max_data = data_ptr + (width << 1);
1463a966c04fSmrg
1464a966c04fSmrg	    while (data_ptr < max_data) {
1465a966c04fSmrg		pixel = pixels[*(iptr++)];
1466a966c04fSmrg
1467a966c04fSmrg		data_ptr[0] = pixel;
1468a966c04fSmrg		data_ptr[1] = pixel >> 8;
1469a966c04fSmrg
1470a966c04fSmrg		data_ptr += (1 << 1);
1471a966c04fSmrg	    }
1472a966c04fSmrg	    data += bpl;
1473a966c04fSmrg	}
1474a966c04fSmrg
1475a966c04fSmrg#endif /* WITHOUT_SPEEDUPS */
1476a966c04fSmrg}
1477a966c04fSmrg
1478a966c04fSmrg/*
1479a966c04fSmrg * write pixels into a 8-bits Z image data structure
1480a966c04fSmrg */
1481a966c04fSmrg
1482a966c04fSmrgstatic void
14832e2dd055SmrgPutImagePixels8(
14842e2dd055Smrg    XImage		*image,
14852e2dd055Smrg    unsigned int	 width,
14862e2dd055Smrg    unsigned int	 height,
14872e2dd055Smrg    unsigned int	*pixelindex,
14882e2dd055Smrg    Pixel		*pixels)
1489a966c04fSmrg{
1490a966c04fSmrg    char *data;
1491a966c04fSmrg    unsigned int *iptr;
1492a966c04fSmrg    unsigned int y;
1493a966c04fSmrg
1494a966c04fSmrg#ifdef WITHOUT_SPEEDUPS
1495a966c04fSmrg
1496a966c04fSmrg    unsigned int x;
1497a966c04fSmrg
1498a966c04fSmrg    data = image->data;
1499a966c04fSmrg    iptr = pixelindex;
1500a966c04fSmrg    for (y = 0; y < height; y++)
1501a966c04fSmrg	for (x = 0; x < width; x++, iptr++)
1502a966c04fSmrg	    data[ZINDEX8(x, y, image)] = pixels[*iptr];
1503a966c04fSmrg
1504a966c04fSmrg#else  /* WITHOUT_SPEEDUPS */
1505a966c04fSmrg
1506a966c04fSmrg    unsigned int bpl = image->bytes_per_line;
1507a966c04fSmrg    char *data_ptr, *max_data;
1508a966c04fSmrg
1509a966c04fSmrg    data = image->data;
1510a966c04fSmrg    iptr = pixelindex;
1511a966c04fSmrg
1512a966c04fSmrg    for (y = 0; y < height; y++) {
1513a966c04fSmrg	data_ptr = data;
1514a966c04fSmrg	max_data = data_ptr + width;
1515a966c04fSmrg
1516a966c04fSmrg	while (data_ptr < max_data)
1517a966c04fSmrg	    *(data_ptr++) = pixels[*(iptr++)];
1518a966c04fSmrg
1519a966c04fSmrg	data += bpl;
1520a966c04fSmrg    }
1521a966c04fSmrg
1522a966c04fSmrg#endif /* WITHOUT_SPEEDUPS */
1523a966c04fSmrg}
1524a966c04fSmrg
1525a966c04fSmrg/*
1526a966c04fSmrg * write pixels into a 1-bit depth image data structure and **offset null**
1527a966c04fSmrg */
1528a966c04fSmrg
1529a966c04fSmrgstatic void
15302e2dd055SmrgPutImagePixels1(
15312e2dd055Smrg    XImage		*image,
15322e2dd055Smrg    unsigned int	 width,
15332e2dd055Smrg    unsigned int	 height,
15342e2dd055Smrg    unsigned int	*pixelindex,
15352e2dd055Smrg    Pixel		*pixels)
1536a966c04fSmrg{
1537a966c04fSmrg    if (image->byte_order != image->bitmap_bit_order)
1538a966c04fSmrg	PutImagePixels(image, width, height, pixelindex, pixels);
1539a966c04fSmrg    else {
1540a966c04fSmrg	unsigned int *iptr;
1541a966c04fSmrg	unsigned int y;
1542a966c04fSmrg	char *data;
1543a966c04fSmrg
1544a966c04fSmrg#ifdef WITHOUT_SPEEDUPS
1545a966c04fSmrg
1546a966c04fSmrg	unsigned int x;
1547a966c04fSmrg
1548a966c04fSmrg	data = image->data;
1549a966c04fSmrg	iptr = pixelindex;
1550a966c04fSmrg	if (image->bitmap_bit_order == MSBFirst)
1551a966c04fSmrg	    for (y = 0; y < height; y++)
1552a966c04fSmrg		for (x = 0; x < width; x++, iptr++) {
1553a966c04fSmrg		    if (pixels[*iptr] & 1)
1554a966c04fSmrg			data[ZINDEX1(x, y, image)] |= 0x80 >> (x & 7);
1555a966c04fSmrg		    else
1556a966c04fSmrg			data[ZINDEX1(x, y, image)] &= ~(0x80 >> (x & 7));
1557a966c04fSmrg		}
1558a966c04fSmrg	else
1559a966c04fSmrg	    for (y = 0; y < height; y++)
1560a966c04fSmrg		for (x = 0; x < width; x++, iptr++) {
1561a966c04fSmrg		    if (pixels[*iptr] & 1)
1562a966c04fSmrg			data[ZINDEX1(x, y, image)] |= 1 << (x & 7);
1563a966c04fSmrg		    else
1564a966c04fSmrg			data[ZINDEX1(x, y, image)] &= ~(1 << (x & 7));
1565a966c04fSmrg		}
1566a966c04fSmrg
1567a966c04fSmrg#else  /* WITHOUT_SPEEDUPS */
1568a966c04fSmrg
1569a966c04fSmrg	char value;
1570a966c04fSmrg	char *data_ptr, *max_data;
1571a966c04fSmrg	int bpl = image->bytes_per_line;
1572a966c04fSmrg	int diff, count;
1573a966c04fSmrg
1574a966c04fSmrg	data = image->data;
1575a966c04fSmrg	iptr = pixelindex;
1576a966c04fSmrg
1577a966c04fSmrg	diff = width & 7;
1578a966c04fSmrg	width >>= 3;
1579a966c04fSmrg
1580a966c04fSmrg	if (image->bitmap_bit_order == MSBFirst)
1581a966c04fSmrg	    for (y = 0; y < height; y++) {
1582a966c04fSmrg		data_ptr = data;
1583a966c04fSmrg		max_data = data_ptr + width;
1584a966c04fSmrg		while (data_ptr < max_data) {
1585a966c04fSmrg		    value = 0;
1586a966c04fSmrg
1587a966c04fSmrg		    value = (value << 1) | (pixels[*(iptr++)] & 1);
1588a966c04fSmrg		    value = (value << 1) | (pixels[*(iptr++)] & 1);
1589a966c04fSmrg		    value = (value << 1) | (pixels[*(iptr++)] & 1);
1590a966c04fSmrg		    value = (value << 1) | (pixels[*(iptr++)] & 1);
1591a966c04fSmrg		    value = (value << 1) | (pixels[*(iptr++)] & 1);
1592a966c04fSmrg		    value = (value << 1) | (pixels[*(iptr++)] & 1);
1593a966c04fSmrg		    value = (value << 1) | (pixels[*(iptr++)] & 1);
1594a966c04fSmrg		    value = (value << 1) | (pixels[*(iptr++)] & 1);
1595a966c04fSmrg
1596a966c04fSmrg		    *(data_ptr++) = value;
1597a966c04fSmrg		}
1598a966c04fSmrg		if (diff) {
1599a966c04fSmrg		    value = 0;
1600a966c04fSmrg		    for (count = 0; count < diff; count++) {
1601a966c04fSmrg			if (pixels[*(iptr++)] & 1)
1602a966c04fSmrg			    value |= (0x80 >> count);
1603a966c04fSmrg		    }
1604a966c04fSmrg		    *(data_ptr) = value;
1605a966c04fSmrg		}
1606a966c04fSmrg		data += bpl;
1607a966c04fSmrg	    }
1608a966c04fSmrg	else
1609a966c04fSmrg	    for (y = 0; y < height; y++) {
1610a966c04fSmrg		data_ptr = data;
1611a966c04fSmrg		max_data = data_ptr + width;
1612a966c04fSmrg		while (data_ptr < max_data) {
1613a966c04fSmrg		    value = 0;
1614a966c04fSmrg		    iptr += 8;
1615a966c04fSmrg
1616a966c04fSmrg		    value = (value << 1) | (pixels[*(--iptr)] & 1);
1617a966c04fSmrg		    value = (value << 1) | (pixels[*(--iptr)] & 1);
1618a966c04fSmrg		    value = (value << 1) | (pixels[*(--iptr)] & 1);
1619a966c04fSmrg		    value = (value << 1) | (pixels[*(--iptr)] & 1);
1620a966c04fSmrg		    value = (value << 1) | (pixels[*(--iptr)] & 1);
1621a966c04fSmrg		    value = (value << 1) | (pixels[*(--iptr)] & 1);
1622a966c04fSmrg		    value = (value << 1) | (pixels[*(--iptr)] & 1);
1623a966c04fSmrg		    value = (value << 1) | (pixels[*(--iptr)] & 1);
1624a966c04fSmrg
1625a966c04fSmrg		    iptr += 8;
1626a966c04fSmrg		    *(data_ptr++) = value;
1627a966c04fSmrg		}
1628a966c04fSmrg		if (diff) {
1629a966c04fSmrg		    value = 0;
1630a966c04fSmrg		    for (count = 0; count < diff; count++) {
1631a966c04fSmrg			if (pixels[*(iptr++)] & 1)
1632a966c04fSmrg			    value |= (1 << count);
1633a966c04fSmrg		    }
1634a966c04fSmrg		    *(data_ptr) = value;
1635a966c04fSmrg		}
1636a966c04fSmrg		data += bpl;
1637a966c04fSmrg	    }
1638a966c04fSmrg
1639a966c04fSmrg#endif /* WITHOUT_SPEEDUPS */
1640a966c04fSmrg    }
1641a966c04fSmrg}
1642a966c04fSmrg
1643a966c04fSmrgint
16442e2dd055SmrgXpmCreatePixmapFromXpmImage(
16452e2dd055Smrg    Display		*display,
16462e2dd055Smrg    Drawable		 d,
16472e2dd055Smrg    XpmImage		*image,
16482e2dd055Smrg    Pixmap		*pixmap_return,
16492e2dd055Smrg    Pixmap		*shapemask_return,
16502e2dd055Smrg    XpmAttributes	*attributes)
1651a966c04fSmrg{
1652a966c04fSmrg    XImage *ximage, *shapeimage;
1653a966c04fSmrg    int ErrorStatus;
1654a966c04fSmrg
1655a966c04fSmrg    /* initialize return values */
1656a966c04fSmrg    if (pixmap_return)
1657a966c04fSmrg	*pixmap_return = 0;
1658a966c04fSmrg    if (shapemask_return)
1659a966c04fSmrg	*shapemask_return = 0;
1660a966c04fSmrg
1661a966c04fSmrg    /* create the ximages */
1662a966c04fSmrg    ErrorStatus = XpmCreateImageFromXpmImage(display, image,
1663a966c04fSmrg					     (pixmap_return ? &ximage : NULL),
1664a966c04fSmrg					     (shapemask_return ?
1665a966c04fSmrg					      &shapeimage : NULL),
1666a966c04fSmrg					     attributes);
1667a966c04fSmrg    if (ErrorStatus < 0)
1668a966c04fSmrg	return (ErrorStatus);
1669a966c04fSmrg
1670a966c04fSmrg    /* create the pixmaps and destroy images */
1671a966c04fSmrg    if (pixmap_return && ximage) {
1672a966c04fSmrg	xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
1673a966c04fSmrg	XDestroyImage(ximage);
1674a966c04fSmrg    }
1675a966c04fSmrg    if (shapemask_return && shapeimage) {
1676a966c04fSmrg	xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
1677a966c04fSmrg	XDestroyImage(shapeimage);
1678a966c04fSmrg    }
1679a966c04fSmrg    return (ErrorStatus);
1680a966c04fSmrg}
1681a966c04fSmrg
1682a966c04fSmrg# else /* AMIGA */
1683a966c04fSmrg
1684a966c04fSmrgstatic void
1685a966c04fSmrgAPutImagePixels (
1686a966c04fSmrg    XImage        *image,
1687a966c04fSmrg    unsigned int   width,
1688a966c04fSmrg    unsigned int   height,
1689a966c04fSmrg    unsigned int  *pixelindex,
1690a966c04fSmrg    Pixel         *pixels)
1691a966c04fSmrg{
1692a966c04fSmrg    unsigned int   *data = pixelindex;
1693a966c04fSmrg    unsigned int    x, y;
1694a966c04fSmrg    unsigned char  *array;
1695a966c04fSmrg    XImage         *tmp_img;
1696a966c04fSmrg    BOOL            success = FALSE;
1697a966c04fSmrg
1698a966c04fSmrg    array = XpmMalloc ((((width+15)>>4)<<4)*sizeof (*array));
1699a966c04fSmrg    if (array != NULL)
1700a966c04fSmrg    {
1701a966c04fSmrg	tmp_img = AllocXImage ((((width+15)>>4)<<4), 1,
1702a966c04fSmrg			       image->rp->BitMap->Depth);
1703a966c04fSmrg	if (tmp_img != NULL)
1704a966c04fSmrg	{
1705a966c04fSmrg	    for (y = 0; y < height; ++y)
1706a966c04fSmrg	    {
1707a966c04fSmrg		for (x = 0; x < width; ++x)
1708a966c04fSmrg		    array[x] = pixels[*(data++)];
1709a966c04fSmrg		WritePixelLine8 (image->rp, 0, y, width, array, tmp_img->rp);
1710a966c04fSmrg	    }
1711a966c04fSmrg	    FreeXImage (tmp_img);
1712a966c04fSmrg	    success = TRUE;
1713a966c04fSmrg	}
1714a966c04fSmrg	XpmFree (array);
1715a966c04fSmrg    }
1716a966c04fSmrg
1717a966c04fSmrg    if (!success)
1718a966c04fSmrg    {
1719a966c04fSmrg	for (y = 0; y < height; ++y)
1720a966c04fSmrg	    for (x = 0; x < width; ++x)
1721a966c04fSmrg		XPutPixel (image, x, y, pixels[*(data++)]);
1722a966c04fSmrg    }
1723a966c04fSmrg}
1724a966c04fSmrg
1725a966c04fSmrg# endif/* AMIGA */
1726a966c04fSmrg#else  /* FOR_MSW part follows */
1727a966c04fSmrgstatic void
17282e2dd055SmrgMSWPutImagePixels(
17292e2dd055Smrg    Display		*dc,
17302e2dd055Smrg    XImage		*image,
17312e2dd055Smrg    unsigned int	 width,
17322e2dd055Smrg    unsigned int	 height,
17332e2dd055Smrg    unsigned int	*pixelindex,
17342e2dd055Smrg    Pixel		*pixels)
1735a966c04fSmrg{
1736a966c04fSmrg    unsigned int *data = pixelindex;
1737a966c04fSmrg    unsigned int x, y;
1738a966c04fSmrg    HBITMAP obm;
1739a966c04fSmrg
1740a966c04fSmrg    obm = SelectObject(*dc, image->bitmap);
1741a966c04fSmrg    for (y = 0; y < height; y++) {
1742a966c04fSmrg	for (x = 0; x < width; x++) {
1743a966c04fSmrg	    SetPixel(*dc, x, y, pixels[*(data++)]); /* data is [x+y*width] */
1744a966c04fSmrg	}
1745a966c04fSmrg    }
1746a966c04fSmrg    SelectObject(*dc, obm);
1747a966c04fSmrg}
1748a966c04fSmrg
1749a966c04fSmrg#endif /* FOR_MSW */
1750a966c04fSmrg
1751a966c04fSmrg
1752a966c04fSmrg
1753a966c04fSmrg#if !defined(FOR_MSW) && !defined(AMIGA)
1754a966c04fSmrg
1755a966c04fSmrgstatic int
17562e2dd055SmrgPutPixel1(
17572e2dd055Smrg    register XImage	*ximage,
17582e2dd055Smrg    int			 x,
17592e2dd055Smrg    int			 y,
17602e2dd055Smrg    unsigned long	 pixel)
1761a966c04fSmrg{
1762a966c04fSmrg    register char *src;
1763a966c04fSmrg    register char *dst;
1764a966c04fSmrg    register int i;
1765a966c04fSmrg    Pixel px;
1766a966c04fSmrg    int nbytes;
1767a966c04fSmrg
1768a966c04fSmrg    if(x < 0 || y < 0)
1769a966c04fSmrg    	return 0;
1770a966c04fSmrg
1771a966c04fSmrg    for (i=0, px=pixel; i<sizeof(unsigned long); i++, px>>=8)
1772a966c04fSmrg	((unsigned char *)&pixel)[i] = px;
1773a966c04fSmrg    src = &ximage->data[XYINDEX(x, y, ximage)];
1774a966c04fSmrg    dst = (char *)&px;
1775a966c04fSmrg    px = 0;
1776a966c04fSmrg    nbytes = ximage->bitmap_unit >> 3;
1777a966c04fSmrg    for (i = nbytes; --i >= 0; ) *dst++ = *src++;
1778a966c04fSmrg    XYNORMALIZE(&px, ximage);
1779a966c04fSmrg    i = ((x + ximage->xoffset) % ximage->bitmap_unit);
1780a966c04fSmrg    _putbits ((char *)&pixel, i, 1, (char *)&px);
1781a966c04fSmrg    XYNORMALIZE(&px, ximage);
1782a966c04fSmrg    src = (char *) &px;
1783a966c04fSmrg    dst = &ximage->data[XYINDEX(x, y, ximage)];
1784a966c04fSmrg    for (i = nbytes; --i >= 0; )
1785a966c04fSmrg	*dst++ = *src++;
1786a966c04fSmrg
1787a966c04fSmrg    return 1;
1788a966c04fSmrg}
1789a966c04fSmrg
1790a966c04fSmrgstatic int
17912e2dd055SmrgPutPixel(
17922e2dd055Smrg    register XImage	*ximage,
17932e2dd055Smrg    int			 x,
17942e2dd055Smrg    int			 y,
17952e2dd055Smrg    unsigned long	 pixel)
1796a966c04fSmrg{
1797a966c04fSmrg    register char *src;
1798a966c04fSmrg    register char *dst;
1799a966c04fSmrg    register int i;
1800a966c04fSmrg    Pixel px;
1801a966c04fSmrg    unsigned int nbytes, ibpp;
1802a966c04fSmrg
1803a966c04fSmrg    if(x < 0 || y < 0)
1804a966c04fSmrg    	return 0;
1805a966c04fSmrg
1806a966c04fSmrg    ibpp = ximage->bits_per_pixel;
1807a966c04fSmrg    if (ximage->depth == 4)
1808a966c04fSmrg	pixel &= 0xf;
1809a966c04fSmrg    for (i = 0, px = pixel; i < sizeof(unsigned long); i++, px >>= 8)
1810a966c04fSmrg	((unsigned char *) &pixel)[i] = px;
1811a966c04fSmrg    src = &ximage->data[ZINDEX(x, y, ximage)];
1812a966c04fSmrg    dst = (char *) &px;
1813a966c04fSmrg    px = 0;
1814a966c04fSmrg    nbytes = (ibpp + 7) >> 3;
1815a966c04fSmrg    for (i = nbytes; --i >= 0;)
1816a966c04fSmrg	*dst++ = *src++;
1817a966c04fSmrg    ZNORMALIZE(&px, ximage);
1818a966c04fSmrg    _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
1819a966c04fSmrg    ZNORMALIZE(&px, ximage);
1820a966c04fSmrg    src = (char *) &px;
1821a966c04fSmrg    dst = &ximage->data[ZINDEX(x, y, ximage)];
1822a966c04fSmrg    for (i = nbytes; --i >= 0;)
1823a966c04fSmrg	*dst++ = *src++;
1824a966c04fSmrg
1825a966c04fSmrg    return 1;
1826a966c04fSmrg}
1827a966c04fSmrg
1828a966c04fSmrg#if !defined(WORD64) && !defined(LONG64)
1829a966c04fSmrgstatic int
18302e2dd055SmrgPutPixel32(
18312e2dd055Smrg    register XImage	*ximage,
18322e2dd055Smrg    int			 x,
18332e2dd055Smrg    int			 y,
18342e2dd055Smrg    unsigned long	 pixel)
1835a966c04fSmrg{
1836a966c04fSmrg    unsigned char *addr;
1837a966c04fSmrg
1838a966c04fSmrg    if(x < 0 || y < 0)
1839a966c04fSmrg    	return 0;
1840a966c04fSmrg
1841a966c04fSmrg    addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1842a966c04fSmrg    *((unsigned long *)addr) = pixel;
1843a966c04fSmrg    return 1;
1844a966c04fSmrg}
1845a966c04fSmrg#endif
1846a966c04fSmrg
1847a966c04fSmrgstatic int
18482e2dd055SmrgPutPixel32MSB(
18492e2dd055Smrg    register XImage	*ximage,
18502e2dd055Smrg    int			 x,
18512e2dd055Smrg    int			 y,
18522e2dd055Smrg    unsigned long	 pixel)
1853a966c04fSmrg{
1854a966c04fSmrg    unsigned char *addr;
1855a966c04fSmrg
1856a966c04fSmrg    if(x < 0 || y < 0)
1857a966c04fSmrg    	return 0;
1858a966c04fSmrg
1859a966c04fSmrg    addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1860a966c04fSmrg    addr[0] = pixel >> 24;
1861a966c04fSmrg    addr[1] = pixel >> 16;
1862a966c04fSmrg    addr[2] = pixel >> 8;
1863a966c04fSmrg    addr[3] = pixel;
1864a966c04fSmrg    return 1;
1865a966c04fSmrg}
1866a966c04fSmrg
1867a966c04fSmrgstatic int
18682e2dd055SmrgPutPixel32LSB(
18692e2dd055Smrg    register XImage	*ximage,
18702e2dd055Smrg    int			 x,
18712e2dd055Smrg    int			 y,
18722e2dd055Smrg    unsigned long	 pixel)
1873a966c04fSmrg{
1874a966c04fSmrg    unsigned char *addr;
1875a966c04fSmrg
1876a966c04fSmrg    if(x < 0 || y < 0)
1877a966c04fSmrg    	return 0;
1878a966c04fSmrg
1879a966c04fSmrg    addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1880a966c04fSmrg    addr[3] = pixel >> 24;
1881a966c04fSmrg    addr[2] = pixel >> 16;
1882a966c04fSmrg    addr[1] = pixel >> 8;
1883a966c04fSmrg    addr[0] = pixel;
1884a966c04fSmrg    return 1;
1885a966c04fSmrg}
1886a966c04fSmrg
1887a966c04fSmrgstatic int
18882e2dd055SmrgPutPixel16MSB(
18892e2dd055Smrg    register XImage	*ximage,
18902e2dd055Smrg    int			 x,
18912e2dd055Smrg    int			 y,
18922e2dd055Smrg    unsigned long	 pixel)
1893a966c04fSmrg{
1894a966c04fSmrg    unsigned char *addr;
1895a966c04fSmrg
1896a966c04fSmrg    if(x < 0 || y < 0)
1897a966c04fSmrg    	return 0;
1898a966c04fSmrg
1899a966c04fSmrg    addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)];
1900a966c04fSmrg    addr[0] = pixel >> 8;
1901a966c04fSmrg    addr[1] = pixel;
1902a966c04fSmrg    return 1;
1903a966c04fSmrg}
1904a966c04fSmrg
1905a966c04fSmrgstatic int
19062e2dd055SmrgPutPixel16LSB(
19072e2dd055Smrg    register XImage	*ximage,
19082e2dd055Smrg    int			 x,
19092e2dd055Smrg    int			 y,
19102e2dd055Smrg    unsigned long	 pixel)
1911a966c04fSmrg{
1912a966c04fSmrg    unsigned char *addr;
1913a966c04fSmrg
1914a966c04fSmrg    if(x < 0 || y < 0)
1915a966c04fSmrg    	return 0;
1916a966c04fSmrg
1917a966c04fSmrg    addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)];
1918a966c04fSmrg    addr[1] = pixel >> 8;
1919a966c04fSmrg    addr[0] = pixel;
1920a966c04fSmrg    return 1;
1921a966c04fSmrg}
1922a966c04fSmrg
1923a966c04fSmrgstatic int
19242e2dd055SmrgPutPixel8(
19252e2dd055Smrg    register XImage	*ximage,
19262e2dd055Smrg    int			 x,
19272e2dd055Smrg    int			 y,
19282e2dd055Smrg    unsigned long	 pixel)
1929a966c04fSmrg{
1930a966c04fSmrg    if(x < 0 || y < 0)
1931a966c04fSmrg    	return 0;
1932a966c04fSmrg
1933a966c04fSmrg    ximage->data[ZINDEX8(x, y, ximage)] = pixel;
1934a966c04fSmrg    return 1;
1935a966c04fSmrg}
1936a966c04fSmrg
1937a966c04fSmrgstatic int
19382e2dd055SmrgPutPixel1MSB(
19392e2dd055Smrg    register XImage	*ximage,
19402e2dd055Smrg    int			 x,
19412e2dd055Smrg    int			 y,
19422e2dd055Smrg    unsigned long	 pixel)
1943a966c04fSmrg{
1944a966c04fSmrg    if(x < 0 || y < 0)
1945a966c04fSmrg    	return 0;
1946a966c04fSmrg
1947a966c04fSmrg    if (pixel & 1)
1948a966c04fSmrg	ximage->data[ZINDEX1(x, y, ximage)] |= 0x80 >> (x & 7);
1949a966c04fSmrg    else
1950a966c04fSmrg	ximage->data[ZINDEX1(x, y, ximage)] &= ~(0x80 >> (x & 7));
1951a966c04fSmrg    return 1;
1952a966c04fSmrg}
1953a966c04fSmrg
1954a966c04fSmrgstatic int
19552e2dd055SmrgPutPixel1LSB(
19562e2dd055Smrg    register XImage	*ximage,
19572e2dd055Smrg    int			 x,
19582e2dd055Smrg    int			 y,
19592e2dd055Smrg    unsigned long	 pixel)
1960a966c04fSmrg{
1961a966c04fSmrg    if(x < 0 || y < 0)
1962a966c04fSmrg    	return 0;
1963a966c04fSmrg
1964a966c04fSmrg    if (pixel & 1)
1965a966c04fSmrg	ximage->data[ZINDEX1(x, y, ximage)] |= 1 << (x & 7);
1966a966c04fSmrg    else
1967a966c04fSmrg	ximage->data[ZINDEX1(x, y, ximage)] &= ~(1 << (x & 7));
1968a966c04fSmrg    return 1;
1969a966c04fSmrg}
1970a966c04fSmrg
1971a966c04fSmrg#endif /* not FOR_MSW && not AMIGA */
1972a966c04fSmrg
1973a966c04fSmrg/*
1974a966c04fSmrg * This function parses an Xpm file or data and directly create an XImage
1975a966c04fSmrg */
1976a966c04fSmrgint
19772e2dd055SmrgxpmParseDataAndCreate(
19782e2dd055Smrg    Display		 *display,
19792e2dd055Smrg    xpmData		 *data,
19802e2dd055Smrg    XImage		**image_return,
19812e2dd055Smrg    XImage		**shapeimage_return,
19822e2dd055Smrg    XpmImage		 *image,
19832e2dd055Smrg    XpmInfo		 *info,
19842e2dd055Smrg    XpmAttributes	 *attributes)
1985a966c04fSmrg{
1986a966c04fSmrg    /* variables stored in the XpmAttributes structure */
1987a966c04fSmrg    Visual *visual;
1988a966c04fSmrg    Colormap colormap;
1989a966c04fSmrg    unsigned int depth;
1990a966c04fSmrg    int bitmap_format;
1991a966c04fSmrg    XpmFreeColorsFunc freeColors;
1992a966c04fSmrg
1993a966c04fSmrg    /* variables to return */
1994a966c04fSmrg    XImage *ximage = NULL;
1995a966c04fSmrg    XImage *shapeimage = NULL;
1996a966c04fSmrg    unsigned int mask_pixel_index = XpmUndefPixel;
1997a966c04fSmrg
1998a966c04fSmrg    /* calculation variables */
1999a966c04fSmrg    Pixel *image_pixels = NULL;
2000a966c04fSmrg    Pixel *mask_pixels = NULL;
2001a966c04fSmrg    Pixel *alloc_pixels = NULL;
2002a966c04fSmrg    Pixel *used_pixels = NULL;
2003a966c04fSmrg    unsigned int nalloc_pixels = 0;
2004a966c04fSmrg    unsigned int nused_pixels = 0;
2005a966c04fSmrg    unsigned int width, height, ncolors, cpp;
2006a966c04fSmrg    unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0;
2007a966c04fSmrg    XpmColor *colorTable = NULL;
2008a966c04fSmrg    char *hints_cmt = NULL;
2009a966c04fSmrg    char *colors_cmt = NULL;
2010a966c04fSmrg    char *pixels_cmt = NULL;
2011a966c04fSmrg
2012a966c04fSmrg    unsigned int cmts;
2013a966c04fSmrg    int ErrorStatus;
2014a966c04fSmrg    xpmHashTable hashtable;
2015a966c04fSmrg
2016a966c04fSmrg
2017a966c04fSmrg    /* initialize return values */
2018a966c04fSmrg    if (image_return)
2019a966c04fSmrg	*image_return = NULL;
2020a966c04fSmrg    if (shapeimage_return)
2021a966c04fSmrg	*shapeimage_return = NULL;
2022a966c04fSmrg
2023a966c04fSmrg
2024a966c04fSmrg    /* retrieve information from the XpmAttributes */
2025a966c04fSmrg    if (attributes && (attributes->valuemask & XpmVisual))
2026a966c04fSmrg	visual = attributes->visual;
2027a966c04fSmrg    else
2028a966c04fSmrg	visual = XDefaultVisual(display, XDefaultScreen(display));
2029a966c04fSmrg
2030a966c04fSmrg    if (attributes && (attributes->valuemask & XpmColormap))
2031a966c04fSmrg	colormap = attributes->colormap;
2032a966c04fSmrg    else
2033a966c04fSmrg	colormap = XDefaultColormap(display, XDefaultScreen(display));
2034a966c04fSmrg
2035a966c04fSmrg    if (attributes && (attributes->valuemask & XpmDepth))
2036a966c04fSmrg	depth = attributes->depth;
2037a966c04fSmrg    else
2038a966c04fSmrg	depth = XDefaultDepth(display, XDefaultScreen(display));
2039a966c04fSmrg
2040a966c04fSmrg    if (attributes && (attributes->valuemask & XpmBitmapFormat))
2041a966c04fSmrg	bitmap_format = attributes->bitmap_format;
2042a966c04fSmrg    else
2043a966c04fSmrg	bitmap_format = ZPixmap;
2044a966c04fSmrg
2045a966c04fSmrg    if (attributes && (attributes->valuemask & XpmFreeColors))
2046a966c04fSmrg	freeColors = attributes->free_colors;
2047a966c04fSmrg    else
2048a966c04fSmrg	freeColors = FreeColors;
2049a966c04fSmrg
2050a966c04fSmrg    cmts = info && (info->valuemask & XpmReturnComments);
2051a966c04fSmrg
2052a966c04fSmrg    /*
2053a966c04fSmrg     * parse the header
2054a966c04fSmrg     */
2055a966c04fSmrg    ErrorStatus = xpmParseHeader(data);
2056a966c04fSmrg    if (ErrorStatus != XpmSuccess)
2057a966c04fSmrg	return (ErrorStatus);
2058a966c04fSmrg
2059a966c04fSmrg    /*
2060a966c04fSmrg     * read values
2061a966c04fSmrg     */
2062a966c04fSmrg    ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp,
2063a966c04fSmrg				 &x_hotspot, &y_hotspot, &hotspot,
2064a966c04fSmrg				 &extensions);
2065a966c04fSmrg    if (ErrorStatus != XpmSuccess)
2066a966c04fSmrg	return (ErrorStatus);
2067a966c04fSmrg
2068a966c04fSmrg    /*
2069a966c04fSmrg     * store the hints comment line
2070a966c04fSmrg     */
2071a966c04fSmrg    if (cmts)
2072a966c04fSmrg	xpmGetCmt(data, &hints_cmt);
2073a966c04fSmrg
2074a966c04fSmrg    /*
2075a966c04fSmrg     * init the hashtable
2076a966c04fSmrg     */
2077a966c04fSmrg    if (USE_HASHTABLE) {
2078a966c04fSmrg	ErrorStatus = xpmHashTableInit(&hashtable);
2079a966c04fSmrg	if (ErrorStatus != XpmSuccess)
2080a966c04fSmrg	    RETURN(ErrorStatus);
2081a966c04fSmrg    }
2082a966c04fSmrg
2083a966c04fSmrg    /*
2084a966c04fSmrg     * read colors
2085a966c04fSmrg     */
2086a966c04fSmrg    ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable);
2087a966c04fSmrg    if (ErrorStatus != XpmSuccess)
2088a966c04fSmrg	RETURN(ErrorStatus);
2089a966c04fSmrg
2090a966c04fSmrg    /*
2091a966c04fSmrg     * store the colors comment line
2092a966c04fSmrg     */
2093a966c04fSmrg    if (cmts)
2094a966c04fSmrg	xpmGetCmt(data, &colors_cmt);
2095a966c04fSmrg
2096a966c04fSmrg    /* malloc pixels index tables */
2097a966c04fSmrg    if (ncolors >= UINT_MAX / sizeof(Pixel))
2098a966c04fSmrg	RETURN(XpmNoMemory);
2099a966c04fSmrg
2100a966c04fSmrg    image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2101a966c04fSmrg    if (!image_pixels)
2102a966c04fSmrg	RETURN(XpmNoMemory);
2103a966c04fSmrg
2104a966c04fSmrg    mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2105a966c04fSmrg    if (!mask_pixels)
2106a966c04fSmrg	RETURN(XpmNoMemory);
2107a966c04fSmrg
2108a966c04fSmrg    /* maximum of allocated pixels will be the number of colors */
2109a966c04fSmrg    alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2110a966c04fSmrg    if (!alloc_pixels)
2111a966c04fSmrg	RETURN(XpmNoMemory);
2112a966c04fSmrg
2113a966c04fSmrg    /* maximum of allocated pixels will be the number of colors */
2114a966c04fSmrg    used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2115a966c04fSmrg    if (!used_pixels)
2116a966c04fSmrg	RETURN(XpmNoMemory);
2117a966c04fSmrg
2118a966c04fSmrg    /* get pixel colors, store them in index tables */
2119a966c04fSmrg    ErrorStatus = CreateColors(display, attributes, colorTable, ncolors,
2120a966c04fSmrg			       image_pixels, mask_pixels, &mask_pixel_index,
2121a966c04fSmrg			       alloc_pixels, &nalloc_pixels, used_pixels,
2122a966c04fSmrg			       &nused_pixels);
2123a966c04fSmrg
2124a966c04fSmrg    if (ErrorStatus != XpmSuccess
2125a966c04fSmrg	&& (ErrorStatus < 0 || (attributes
2126a966c04fSmrg				&& (attributes->valuemask & XpmExactColors)
2127a966c04fSmrg				&& attributes->exactColors)))
2128a966c04fSmrg	RETURN(ErrorStatus);
2129a966c04fSmrg
2130a966c04fSmrg    /* now create the ximage */
2131a966c04fSmrg    if (image_return) {
2132a966c04fSmrg	ErrorStatus = CreateXImage(display, visual, depth,
2133a966c04fSmrg				   (depth == 1 ? bitmap_format : ZPixmap),
2134a966c04fSmrg				   width, height, &ximage);
2135a966c04fSmrg	if (ErrorStatus != XpmSuccess)
2136a966c04fSmrg	    RETURN(ErrorStatus);
2137a966c04fSmrg
2138a966c04fSmrg#if !defined(FOR_MSW) && !defined(AMIGA)
2139a966c04fSmrg
2140a966c04fSmrg	/*
2141a966c04fSmrg	 * set the XImage pointer function, to be used with XPutPixel,
2142a966c04fSmrg	 * to an internal optimized function
2143a966c04fSmrg	 */
2144a966c04fSmrg
2145a966c04fSmrg	if (ximage->bits_per_pixel == 8)
2146a966c04fSmrg	    ximage->f.put_pixel = PutPixel8;
2147a966c04fSmrg	else if (((ximage->bits_per_pixel | ximage->depth) == 1) &&
2148a966c04fSmrg		 (ximage->byte_order == ximage->bitmap_bit_order))
2149a966c04fSmrg	    if (ximage->bitmap_bit_order == MSBFirst)
2150a966c04fSmrg		ximage->f.put_pixel = PutPixel1MSB;
2151a966c04fSmrg	    else
2152a966c04fSmrg		ximage->f.put_pixel = PutPixel1LSB;
2153a966c04fSmrg	else if (ximage->bits_per_pixel == 16)
2154a966c04fSmrg	    if (ximage->bitmap_bit_order == MSBFirst)
2155a966c04fSmrg		ximage->f.put_pixel = PutPixel16MSB;
2156a966c04fSmrg	    else
2157a966c04fSmrg		ximage->f.put_pixel = PutPixel16LSB;
2158a966c04fSmrg	else if (ximage->bits_per_pixel == 32)
2159a966c04fSmrg#if !defined(WORD64) && !defined(LONG64)
2160a966c04fSmrg	    if (*((char *)&byteorderpixel) == ximage->byte_order)
2161a966c04fSmrg		ximage->f.put_pixel = PutPixel32;
2162a966c04fSmrg	    else
2163a966c04fSmrg#endif
2164a966c04fSmrg		if (ximage->bitmap_bit_order == MSBFirst)
2165a966c04fSmrg		    ximage->f.put_pixel = PutPixel32MSB;
2166a966c04fSmrg		else
2167a966c04fSmrg		    ximage->f.put_pixel = PutPixel32LSB;
2168a966c04fSmrg	else if ((ximage->bits_per_pixel | ximage->depth) == 1)
2169a966c04fSmrg	    ximage->f.put_pixel = PutPixel1;
2170a966c04fSmrg	else
2171a966c04fSmrg	    ximage->f.put_pixel = PutPixel;
2172a966c04fSmrg#endif /* not FOR_MSW && not AMIGA */
2173a966c04fSmrg    }
2174a966c04fSmrg
2175a966c04fSmrg    /* create the shape mask image */
2176a966c04fSmrg    if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
2177a966c04fSmrg	ErrorStatus = CreateXImage(display, visual, 1, bitmap_format,
2178a966c04fSmrg				   width, height, &shapeimage);
2179a966c04fSmrg	if (ErrorStatus != XpmSuccess)
2180a966c04fSmrg	    RETURN(ErrorStatus);
2181a966c04fSmrg
2182a966c04fSmrg#if !defined(FOR_MSW) && !defined(AMIGA)
2183a966c04fSmrg	if (shapeimage->bitmap_bit_order == MSBFirst)
2184a966c04fSmrg	    shapeimage->f.put_pixel = PutPixel1MSB;
2185a966c04fSmrg	else
2186a966c04fSmrg	    shapeimage->f.put_pixel = PutPixel1LSB;
2187a966c04fSmrg#endif
2188a966c04fSmrg    }
2189a966c04fSmrg
2190a966c04fSmrg    /*
2191a966c04fSmrg     * read pixels and put them in the XImage
2192a966c04fSmrg     */
2193a966c04fSmrg    ErrorStatus = ParseAndPutPixels(
2194a966c04fSmrg#ifdef FOR_MSW
2195a966c04fSmrg				    display,
2196a966c04fSmrg#endif
2197a966c04fSmrg				    data, width, height, ncolors, cpp,
2198a966c04fSmrg				    colorTable, &hashtable,
2199a966c04fSmrg				    ximage, image_pixels,
2200a966c04fSmrg				    shapeimage, mask_pixels);
2201a966c04fSmrg    XpmFree(image_pixels);
2202a966c04fSmrg    image_pixels = NULL;
2203a966c04fSmrg    XpmFree(mask_pixels);
2204a966c04fSmrg    mask_pixels = NULL;
2205a966c04fSmrg
2206a966c04fSmrg    /*
2207a966c04fSmrg     * free the hastable
2208a966c04fSmrg     */
2209a966c04fSmrg    if (ErrorStatus != XpmSuccess)
2210a966c04fSmrg	RETURN(ErrorStatus);
2211a966c04fSmrg    else if (USE_HASHTABLE)
2212a966c04fSmrg	xpmHashTableFree(&hashtable);
2213a966c04fSmrg
2214a966c04fSmrg    /*
2215a966c04fSmrg     * store the pixels comment line
2216a966c04fSmrg     */
2217a966c04fSmrg    if (cmts)
2218a966c04fSmrg	xpmGetCmt(data, &pixels_cmt);
2219a966c04fSmrg
2220a966c04fSmrg    /*
2221a966c04fSmrg     * parse extensions
2222a966c04fSmrg     */
2223a966c04fSmrg    if (info && (info->valuemask & XpmReturnExtensions)) {
2224a966c04fSmrg	if (extensions) {
2225a966c04fSmrg	    ErrorStatus = xpmParseExtensions(data, &info->extensions,
2226a966c04fSmrg					     &info->nextensions);
2227a966c04fSmrg	    if (ErrorStatus != XpmSuccess)
2228a966c04fSmrg		RETURN(ErrorStatus);
2229a966c04fSmrg	} else {
2230a966c04fSmrg	    info->extensions = NULL;
2231a966c04fSmrg	    info->nextensions = 0;
2232a966c04fSmrg	}
2233a966c04fSmrg    }
2234a966c04fSmrg    /*
2235a966c04fSmrg     * store found informations in the XpmImage structure
2236a966c04fSmrg     */
2237a966c04fSmrg    image->width = width;
2238a966c04fSmrg    image->height = height;
2239a966c04fSmrg    image->cpp = cpp;
2240a966c04fSmrg    image->ncolors = ncolors;
2241a966c04fSmrg    image->colorTable = colorTable;
2242a966c04fSmrg    image->data = NULL;
2243a966c04fSmrg
2244a966c04fSmrg    if (info) {
2245a966c04fSmrg	if (cmts) {
2246a966c04fSmrg	    info->hints_cmt = hints_cmt;
2247a966c04fSmrg	    info->colors_cmt = colors_cmt;
2248a966c04fSmrg	    info->pixels_cmt = pixels_cmt;
2249a966c04fSmrg	}
2250a966c04fSmrg	if (hotspot) {
2251a966c04fSmrg	    info->x_hotspot = x_hotspot;
2252a966c04fSmrg	    info->y_hotspot = y_hotspot;
2253a966c04fSmrg	    info->valuemask |= XpmHotspot;
2254a966c04fSmrg	}
2255a966c04fSmrg    }
2256a966c04fSmrg    /* if requested return used pixels in the XpmAttributes structure */
2257a966c04fSmrg    if (attributes && (attributes->valuemask & XpmReturnPixels ||
2258a966c04fSmrg/* 3.2 backward compatibility code */
2259a966c04fSmrg	attributes->valuemask & XpmReturnInfos)) {
2260a966c04fSmrg/* end 3.2 bc */
2261a966c04fSmrg	attributes->pixels = used_pixels;
2262a966c04fSmrg	attributes->npixels = nused_pixels;
2263a966c04fSmrg	attributes->mask_pixel = mask_pixel_index;
2264a966c04fSmrg    } else
2265a966c04fSmrg	XpmFree(used_pixels);
2266a966c04fSmrg
2267a966c04fSmrg    /* if requested return alloc'ed pixels in the XpmAttributes structure */
2268a966c04fSmrg    if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
2269a966c04fSmrg	attributes->alloc_pixels = alloc_pixels;
2270a966c04fSmrg	attributes->nalloc_pixels = nalloc_pixels;
2271a966c04fSmrg    } else
2272a966c04fSmrg	XpmFree(alloc_pixels);
2273a966c04fSmrg
2274a966c04fSmrg    /* return created images */
2275a966c04fSmrg    if (image_return)
2276a966c04fSmrg	*image_return = ximage;
2277a966c04fSmrg    if (shapeimage_return)
2278a966c04fSmrg	*shapeimage_return = shapeimage;
2279a966c04fSmrg
2280a966c04fSmrg    return (XpmSuccess);
2281a966c04fSmrg
2282a966c04fSmrg/* exit point in case of error, free only locally allocated variables */
2283a966c04fSmrgerror:
2284a966c04fSmrg    if (USE_HASHTABLE)
2285a966c04fSmrg	xpmHashTableFree(&hashtable);
2286a966c04fSmrg    if (colorTable)
2287a966c04fSmrg	xpmFreeColorTable(colorTable, ncolors);
2288a966c04fSmrg    if (hints_cmt)
2289a966c04fSmrg	XpmFree(hints_cmt);
2290a966c04fSmrg    if (colors_cmt)
2291a966c04fSmrg	XpmFree(colors_cmt);
2292a966c04fSmrg    if (pixels_cmt)
2293a966c04fSmrg	XpmFree(pixels_cmt);
2294a966c04fSmrg    if (ximage)
2295a966c04fSmrg	XDestroyImage(ximage);
2296a966c04fSmrg    if (shapeimage)
2297a966c04fSmrg	XDestroyImage(shapeimage);
2298a966c04fSmrg    if (image_pixels)
2299a966c04fSmrg	XpmFree(image_pixels);
2300a966c04fSmrg    if (mask_pixels)
2301a966c04fSmrg	XpmFree(mask_pixels);
2302a966c04fSmrg    if (nalloc_pixels)
2303a966c04fSmrg	(*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL);
2304a966c04fSmrg    if (alloc_pixels)
2305a966c04fSmrg	XpmFree(alloc_pixels);
2306a966c04fSmrg    if (used_pixels)
2307a966c04fSmrg	XpmFree(used_pixels);
2308a966c04fSmrg
2309a966c04fSmrg    return (ErrorStatus);
2310a966c04fSmrg}
2311a966c04fSmrg
2312a966c04fSmrgstatic int
2313a966c04fSmrgParseAndPutPixels(
2314a966c04fSmrg#ifdef FOR_MSW
23152e2dd055Smrg    Display		*dc,
2316a966c04fSmrg#endif
23172e2dd055Smrg    xpmData		*data,
23182e2dd055Smrg    unsigned int	 width,
23192e2dd055Smrg    unsigned int	 height,
23202e2dd055Smrg    unsigned int	 ncolors,
23212e2dd055Smrg    unsigned int	 cpp,
23222e2dd055Smrg    XpmColor		*colorTable,
23232e2dd055Smrg    xpmHashTable	*hashtable,
23242e2dd055Smrg    XImage		*image,
23252e2dd055Smrg    Pixel		*image_pixels,
23262e2dd055Smrg    XImage		*shapeimage,
23272e2dd055Smrg    Pixel		*shape_pixels)
2328a966c04fSmrg{
2329a966c04fSmrg    unsigned int a, x, y;
2330a966c04fSmrg
2331a966c04fSmrg    switch (cpp) {
2332a966c04fSmrg
2333a966c04fSmrg    case (1):				/* Optimize for single character
2334a966c04fSmrg					 * colors */
2335a966c04fSmrg	{
2336a966c04fSmrg	    unsigned short colidx[256];
2337a966c04fSmrg#ifdef FOR_MSW
2338a966c04fSmrg	    HDC shapedc;
2339a966c04fSmrg	    HBITMAP obm, sobm;
2340a966c04fSmrg
2341a966c04fSmrg	    if ( shapeimage ) {
2342a966c04fSmrg		shapedc = CreateCompatibleDC(*dc);
2343a966c04fSmrg		sobm = SelectObject(shapedc, shapeimage->bitmap);
2344a966c04fSmrg	    } else {
2345a966c04fSmrg	        shapedc = NULL;
2346a966c04fSmrg	    }
2347a966c04fSmrg	    obm = SelectObject(*dc, image->bitmap);
2348a966c04fSmrg#endif
2349a966c04fSmrg	    if (ncolors > 256)
2350a966c04fSmrg		return (XpmFileInvalid);
2351a966c04fSmrg
2352a966c04fSmrg	    bzero((char *)colidx, 256 * sizeof(short));
2353a966c04fSmrg	    for (a = 0; a < ncolors; a++)
2354a966c04fSmrg		colidx[(unsigned char)colorTable[a].string[0]] = a + 1;
2355a966c04fSmrg
2356a966c04fSmrg	    for (y = 0; y < height; y++) {
2357a966c04fSmrg		xpmNextString(data);
2358a966c04fSmrg		for (x = 0; x < width; x++) {
2359a966c04fSmrg		    int c = xpmGetC(data);
2360a966c04fSmrg
2361a966c04fSmrg		    if (c > 0 && c < 256 && colidx[c] != 0) {
2362a966c04fSmrg#ifndef FOR_MSW
2363a966c04fSmrg			XPutPixel(image, x, y, image_pixels[colidx[c] - 1]);
2364a966c04fSmrg			if (shapeimage)
2365a966c04fSmrg			    XPutPixel(shapeimage, x, y,
2366a966c04fSmrg				      shape_pixels[colidx[c] - 1]);
2367a966c04fSmrg#else
2368a966c04fSmrg			SetPixel(*dc, x, y, image_pixels[colidx[c] - 1]);
2369a966c04fSmrg			if (shapedc) {
2370a966c04fSmrg			    SetPixel(shapedc, x, y, shape_pixels[colidx[c] - 1]);
2371a966c04fSmrg			}
2372a966c04fSmrg#endif
2373a966c04fSmrg		    } else
2374a966c04fSmrg			return (XpmFileInvalid);
2375a966c04fSmrg		}
2376a966c04fSmrg	    }
2377a966c04fSmrg#ifdef FOR_MSW
2378a966c04fSmrg	    if ( shapedc ) {
2379a966c04fSmrg	        SelectObject(shapedc, sobm);
2380a966c04fSmrg		DeleteDC(shapedc);
2381a966c04fSmrg	    }
2382a966c04fSmrg	    SelectObject(*dc, obm);
2383a966c04fSmrg#endif
2384a966c04fSmrg	}
2385a966c04fSmrg	break;
2386a966c04fSmrg
2387a966c04fSmrg    case (2):				/* Optimize for double character
2388a966c04fSmrg					 * colors */
2389a966c04fSmrg	{
2390a966c04fSmrg
2391a966c04fSmrg/* free all allocated pointers at all exits */
2392a966c04fSmrg#define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
2393a966c04fSmrgif (cidx[f]) XpmFree(cidx[f]);}
2394a966c04fSmrg
2395a966c04fSmrg	    /* array of pointers malloced by need */
2396a966c04fSmrg	    unsigned short *cidx[256];
2397a966c04fSmrg	    unsigned int char1;
2398a966c04fSmrg
2399a966c04fSmrg	    bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */
2400a966c04fSmrg	    for (a = 0; a < ncolors; a++) {
2401a966c04fSmrg		char1 = (unsigned char) colorTable[a].string[0];
2402a966c04fSmrg		if (cidx[char1] == NULL) { /* get new memory */
2403a966c04fSmrg		    cidx[char1] = (unsigned short *)
2404a966c04fSmrg			XpmCalloc(256, sizeof(unsigned short));
2405a966c04fSmrg		    if (cidx[char1] == NULL) { /* new block failed */
2406a966c04fSmrg			FREE_CIDX;
2407a966c04fSmrg			return (XpmNoMemory);
2408a966c04fSmrg		    }
2409a966c04fSmrg		}
2410a966c04fSmrg		cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1;
2411a966c04fSmrg	    }
2412a966c04fSmrg
2413a966c04fSmrg	    for (y = 0; y < height; y++) {
2414a966c04fSmrg		xpmNextString(data);
2415a966c04fSmrg		for (x = 0; x < width; x++) {
2416a966c04fSmrg		    int cc1 = xpmGetC(data);
2417a966c04fSmrg		    if (cc1 > 0 && cc1 < 256) {
2418a966c04fSmrg			int cc2 = xpmGetC(data);
2419a966c04fSmrg			if (cc2 > 0 && cc2 < 256 &&
2420a966c04fSmrg			    cidx[cc1] && cidx[cc1][cc2] != 0) {
2421a966c04fSmrg#ifndef FOR_MSW
2422a966c04fSmrg			    XPutPixel(image, x, y,
2423a966c04fSmrg				      image_pixels[cidx[cc1][cc2] - 1]);
2424a966c04fSmrg			    if (shapeimage)
2425a966c04fSmrg				XPutPixel(shapeimage, x, y,
2426a966c04fSmrg					  shape_pixels[cidx[cc1][cc2] - 1]);
2427a966c04fSmrg#else
2428a966c04fSmrg			SelectObject(*dc, image->bitmap);
2429a966c04fSmrg			SetPixel(*dc, x, y, image_pixels[cidx[cc1][cc2] - 1]);
2430a966c04fSmrg			if (shapeimage) {
2431a966c04fSmrg			    SelectObject(*dc, shapeimage->bitmap);
2432a966c04fSmrg			    SetPixel(*dc, x, y,
2433a966c04fSmrg				     shape_pixels[cidx[cc1][cc2] - 1]);
2434a966c04fSmrg			}
2435a966c04fSmrg#endif
2436a966c04fSmrg			} else {
2437a966c04fSmrg			    FREE_CIDX;
2438a966c04fSmrg			    return (XpmFileInvalid);
2439a966c04fSmrg			}
2440a966c04fSmrg		    } else {
2441a966c04fSmrg			FREE_CIDX;
2442a966c04fSmrg			return (XpmFileInvalid);
2443a966c04fSmrg		    }
2444a966c04fSmrg		}
2445a966c04fSmrg	    }
2446a966c04fSmrg	    FREE_CIDX;
2447a966c04fSmrg	}
2448a966c04fSmrg	break;
2449a966c04fSmrg
2450a966c04fSmrg    default:				/* Non-optimized case of long color
2451a966c04fSmrg					 * names */
2452a966c04fSmrg	{
2453a966c04fSmrg	    char *s;
2454a966c04fSmrg	    char buf[BUFSIZ];
2455a966c04fSmrg
2456a966c04fSmrg	    if (cpp >= sizeof(buf))
2457a966c04fSmrg		return (XpmFileInvalid);
2458a966c04fSmrg
2459a966c04fSmrg	    buf[cpp] = '\0';
2460a966c04fSmrg	    if (USE_HASHTABLE) {
2461a966c04fSmrg		xpmHashAtom *slot;
2462a966c04fSmrg
2463a966c04fSmrg		for (y = 0; y < height; y++) {
2464a966c04fSmrg		    xpmNextString(data);
2465a966c04fSmrg		    for (x = 0; x < width; x++) {
2466a966c04fSmrg			for (a = 0, s = buf; a < cpp; a++, s++)
2467a966c04fSmrg			    *s = xpmGetC(data);
2468a966c04fSmrg			slot = xpmHashSlot(hashtable, buf);
2469a966c04fSmrg			if (!*slot)	/* no color matches */
2470a966c04fSmrg			    return (XpmFileInvalid);
2471a966c04fSmrg#ifndef FOR_MSW
2472a966c04fSmrg			XPutPixel(image, x, y,
2473a966c04fSmrg				  image_pixels[HashColorIndex(slot)]);
2474a966c04fSmrg			if (shapeimage)
2475a966c04fSmrg			    XPutPixel(shapeimage, x, y,
2476a966c04fSmrg				      shape_pixels[HashColorIndex(slot)]);
2477a966c04fSmrg#else
2478a966c04fSmrg			SelectObject(*dc, image->bitmap);
2479a966c04fSmrg			SetPixel(*dc, x, y,
2480a966c04fSmrg				 image_pixels[HashColorIndex(slot)]);
2481a966c04fSmrg			if (shapeimage) {
2482a966c04fSmrg			    SelectObject(*dc, shapeimage->bitmap);
2483a966c04fSmrg			    SetPixel(*dc, x, y,
2484a966c04fSmrg				     shape_pixels[HashColorIndex(slot)]);
2485a966c04fSmrg			}
2486a966c04fSmrg#endif
2487a966c04fSmrg		    }
2488a966c04fSmrg		}
2489a966c04fSmrg	    } else {
2490a966c04fSmrg		for (y = 0; y < height; y++) {
2491a966c04fSmrg		    xpmNextString(data);
2492a966c04fSmrg		    for (x = 0; x < width; x++) {
2493a966c04fSmrg			for (a = 0, s = buf; a < cpp; a++, s++)
2494a966c04fSmrg			    *s = xpmGetC(data);
2495a966c04fSmrg			for (a = 0; a < ncolors; a++)
2496a966c04fSmrg			    if (!strcmp(colorTable[a].string, buf))
2497a966c04fSmrg				break;
2498a966c04fSmrg			if (a == ncolors)	/* no color matches */
2499a966c04fSmrg			    return (XpmFileInvalid);
2500a966c04fSmrg#ifndef FOR_MSW
2501a966c04fSmrg			XPutPixel(image, x, y, image_pixels[a]);
2502a966c04fSmrg			if (shapeimage)
2503a966c04fSmrg			    XPutPixel(shapeimage, x, y, shape_pixels[a]);
2504a966c04fSmrg#else
2505a966c04fSmrg			SelectObject(*dc, image->bitmap);
2506a966c04fSmrg			SetPixel(*dc, x, y, image_pixels[a]);
2507a966c04fSmrg			if (shapeimage) {
2508a966c04fSmrg			    SelectObject(*dc, shapeimage->bitmap);
2509a966c04fSmrg			    SetPixel(*dc, x, y, shape_pixels[a]);
2510a966c04fSmrg			}
2511a966c04fSmrg#endif
2512a966c04fSmrg		    }
2513a966c04fSmrg		}
2514a966c04fSmrg	    }
2515a966c04fSmrg	}
2516a966c04fSmrg	break;
2517a966c04fSmrg    }
2518a966c04fSmrg    return (XpmSuccess);
2519a966c04fSmrg}
2520