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