Back to index

plt-scheme  4.2.1
create.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 1989-95 GROUPE BULL
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a copy
00005  * of this software and associated documentation files (the "Software"), to
00006  * deal in the Software without restriction, including without limitation the
00007  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
00008  * sell copies of the Software, and to permit persons to whom the Software is
00009  * furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included in
00012  * all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00017  * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00018  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00019  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00020  *
00021  * Except as contained in this notice, the name of GROUPE BULL shall not be
00022  * used in advertising or otherwise to promote the sale, use or other dealings
00023  * in this Software without prior written authorization from GROUPE BULL.
00024  */
00025 
00026 /*****************************************************************************\
00027 * create.c:                                                                   *
00028 *                                                                             *
00029 *  XPM library                                                                *
00030 *  Create an X image and possibly its related shape mask                      *
00031 *  from the given XpmImage.                                                   *
00032 *                                                                             *
00033 *  Developed by Arnaud Le Hors                                                *
00034 \*****************************************************************************/
00035 
00036 /*
00037  * The code related to FOR_MSW has been added by
00038  * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
00039  */
00040 
00041 #include "xpmP.h"
00042 #include <ctype.h>
00043 #if defined(SYSV) || defined(SVR4) || defined(VMS) || defined(__GNUC__)
00044 #include <string.h>
00045 #else
00046 #include <strings.h>
00047 #endif
00048 
00049 LFUNC(xpmVisualType, int, (Visual *visual));
00050 
00051 #ifndef FOR_MSW
00052 LFUNC(SetCloseColor, int, (Display *display, Colormap colormap,
00053                         Visual *visual, XColor *col,
00054                         Pixel *image_pixel, Pixel *mask_pixel,
00055                         Pixel *alloc_pixels, unsigned int *nalloc_pixels,
00056                         XpmAttributes *attributes,
00057                         XColor *cols, int ncols));
00058 #else
00059 /* let the window system take care of close colors */
00060 #endif
00061 
00062 LFUNC(SetColor, int, (Display *display, Colormap colormap, Visual *visual,
00063                     char *colorname, unsigned int color_index,
00064                     Pixel *image_pixel, Pixel *mask_pixel,
00065                     unsigned int *mask_pixel_index,
00066                     Pixel *alloc_pixels, unsigned int *nalloc_pixels,
00067                     Pixel *used_pixels, unsigned int *nused_pixels,
00068                     XpmAttributes *attributes, XColor *cols, int ncols));
00069 
00070 LFUNC(CreateXImage, int, (Display *display, Visual *visual,
00071                        unsigned int depth, unsigned int width,
00072                        unsigned int height, XImage **image_return));
00073 
00074 LFUNC(CreateColors, int, (Display *display, XpmAttributes *attributes,
00075                        XpmColor *colors, unsigned int ncolors,
00076                        Pixel *image_pixels, Pixel *mask_pixels,
00077                        unsigned int *mask_pixel_index,
00078                        Pixel *alloc_pixels, unsigned int *nalloc_pixels,
00079                        Pixel *used_pixels, unsigned int *nused_pixels));
00080 
00081 #ifndef FOR_MSW
00082 /* XImage pixel routines */
00083 LFUNC(SetImagePixels, void, (XImage *image, unsigned int width,
00084                           unsigned int height, unsigned int *pixelindex,
00085                           Pixel *pixels));
00086 
00087 LFUNC(SetImagePixels32, void, (XImage *image, unsigned int width,
00088                             unsigned int height, unsigned int *pixelindex,
00089                             Pixel *pixels));
00090 
00091 LFUNC(SetImagePixels16, void, (XImage *image, unsigned int width,
00092                             unsigned int height, unsigned int *pixelindex,
00093                             Pixel *pixels));
00094 
00095 LFUNC(SetImagePixels8, void, (XImage *image, unsigned int width,
00096                            unsigned int height, unsigned int *pixelindex,
00097                            Pixel *pixels));
00098 
00099 LFUNC(SetImagePixels1, void, (XImage *image, unsigned int width,
00100                            unsigned int height, unsigned int *pixelindex,
00101                            Pixel *pixels));
00102 #else  /* ndef FOR_MSW */
00103 /* FOR_MSW pixel routine */
00104 LFUNC(MSWSetImagePixels, void, (Display *dc, XImage *image,
00105                             unsigned int width, unsigned int height,
00106                             unsigned int *pixelindex, Pixel *pixels));
00107 #endif /* ndef FOR_MSW */
00108 
00109 #ifdef NEED_STRCASECMP
00110 FUNC(strcasecmp, int, (char *s1, char *s2));
00111 
00112 /*
00113  * in case strcasecmp is not provided by the system here is one
00114  * which does the trick
00115  */
00116 int
00117 strcasecmp(s1, s2)
00118     register char *s1, *s2;
00119 {
00120     register int c1, c2;
00121 
00122     while (*s1 && *s2) {
00123        c1 = tolower(*s1);
00124        c2 = tolower(*s2);
00125        if (c1 != c2)
00126            return (c1 - c2);
00127        s1++;
00128        s2++;
00129     }
00130     return (int) (*s1 - *s2);
00131 }
00132 
00133 #endif
00134 
00135 /*
00136  * return the default color key related to the given visual
00137  */
00138 static int
00139 xpmVisualType(visual)
00140     Visual *visual;
00141 {
00142 #ifndef FOR_MSW
00143     switch (visual->class) {
00144     case StaticGray:
00145     case GrayScale:
00146        switch (visual->map_entries) {
00147        case 2:
00148            return (XPM_MONO);
00149        case 4:
00150            return (XPM_GRAY4);
00151        default:
00152            return (XPM_GRAY);
00153        }
00154     default:
00155        return (XPM_COLOR);
00156     }
00157 #else
00158     /* there should be a similar switch for MSW */
00159     return (XPM_COLOR);
00160 #endif
00161 }
00162 
00163 
00164 typedef struct {
00165     int cols_index;
00166     long closeness;
00167 }      CloseColor;
00168 
00169 static int
00170 closeness_cmp(a, b)
00171     Const void *a, *b;
00172 {
00173     CloseColor *x = (CloseColor *) a, *y = (CloseColor *) b;
00174 
00175     /* cast to int as qsort requires */
00176     return (int) (x->closeness - y->closeness);
00177 }
00178 
00179 #ifndef FOR_MSW
00180 /*
00181  * set a close color in case the exact one can't be set
00182  * return 0 if success, 1 otherwise.
00183  */
00184 
00185 static int
00186 SetCloseColor(display, colormap, visual, col, image_pixel, mask_pixel,
00187              alloc_pixels, nalloc_pixels, attributes, cols, ncols)
00188     Display *display;
00189     Colormap colormap;
00190     Visual *visual;
00191     XColor *col;
00192     Pixel *image_pixel, *mask_pixel;
00193     Pixel *alloc_pixels;
00194     unsigned int *nalloc_pixels;
00195     XpmAttributes *attributes;
00196     XColor *cols;
00197     int ncols;
00198 {
00199 
00200     /*
00201      * Allocation failed, so try close colors. To get here the visual must
00202      * be GreyScale, PseudoColor or DirectColor (or perhaps StaticColor?
00203      * What about sharing systems like QDSS?). Beware: we have to treat
00204      * DirectColor differently.
00205      */
00206 
00207 
00208     long int red_closeness, green_closeness, blue_closeness;
00209     int n;
00210 
00211     if (attributes && (attributes->valuemask & XpmCloseness))
00212        red_closeness = green_closeness = blue_closeness =
00213            attributes->closeness;
00214     else {
00215        red_closeness = attributes->red_closeness;
00216        green_closeness = attributes->green_closeness;
00217        blue_closeness = attributes->blue_closeness;
00218     }
00219 
00220 
00221     /*
00222      * We sort the colormap by closeness and try to allocate the color
00223      * closest to the target. If the allocation of this close color fails,
00224      * which almost never happens, then one of two scenarios is possible.
00225      * Either the colormap must have changed (since the last close color
00226      * allocation or possibly while we were sorting the colormap), or the
00227      * color is allocated as Read/Write by some other client. (Note: X
00228      * _should_ allow clients to check if a particular color is Read/Write,
00229      * but it doesn't! :-( ). We cannot determine which of these scenarios
00230      * occurred, so we try the next closest color, and so on, until no more
00231      * colors are within closeness of the target. If we knew that the
00232      * colormap had changed, we could skip this sequence.
00233      * 
00234      * If _none_ of the colors within closeness of the target can be allocated,
00235      * then we can finally be pretty sure that the colormap has actually
00236      * changed. In this case we try to allocate the original color (again),
00237      * then try the closecolor stuff (again)...
00238      * 
00239      * In theory it would be possible for an infinite loop to occur if another
00240      * process kept changing the colormap every time we sorted it, so we set
00241      * a maximum on the number of iterations. After this many tries, we use
00242      * XGrabServer() to ensure that the colormap remains unchanged.
00243      * 
00244      * This approach gives particularly bad worst case performance - as many as
00245      * <MaximumIterations> colormap reads and sorts may be needed, and as
00246      * many as <MaximumIterations> * <ColormapSize> attempted allocations
00247      * may fail. On an 8-bit system, this means as many as 3 colormap reads,
00248      * 3 sorts and 768 failed allocations per execution of this code!
00249      * Luckily, my experiments show that in general use in a typical 8-bit
00250      * color environment only about 1 in every 10000 allocations fails to
00251      * succeed in the fastest possible time. So virtually every time what
00252      * actually happens is a single sort followed by a successful allocate.
00253      * The very first allocation also costs a colormap read, but no further
00254      * reads are usually necessary.
00255      */
00256 
00257 #define ITERATIONS 2               /* more than one is almost never
00258                                     * necessary */
00259 
00260     for (n = 0; n <= ITERATIONS; ++n) {
00261        CloseColor *closenesses =
00262            (CloseColor *) XpmCalloc(ncols, sizeof(CloseColor));
00263        int i, c;
00264 
00265        for (i = 0; i < ncols; ++i) {      /* build & sort closenesses table */
00266 #define COLOR_FACTOR       3
00267 #define BRIGHTNESS_FACTOR  1
00268 
00269            closenesses[i].cols_index = i;
00270            closenesses[i].closeness =
00271               COLOR_FACTOR * (abs((long) col->red - (long) cols[i].red)
00272                             + abs((long) col->green - (long) cols[i].green)
00273                             + abs((long) col->blue - (long) cols[i].blue))
00274               + BRIGHTNESS_FACTOR * abs(((long) col->red +
00275                                       (long) col->green +
00276                                       (long) col->blue)
00277                                       - ((long) cols[i].red +
00278                                          (long) cols[i].green +
00279                                          (long) cols[i].blue));
00280        }
00281        qsort(closenesses, ncols, sizeof(CloseColor), closeness_cmp);
00282 
00283        i = 0;
00284        c = closenesses[i].cols_index;
00285        while ((long) cols[c].red >= (long) col->red - red_closeness &&
00286               (long) cols[c].red <= (long) col->red + red_closeness &&
00287               (long) cols[c].green >= (long) col->green - green_closeness &&
00288               (long) cols[c].green <= (long) col->green + green_closeness &&
00289               (long) cols[c].blue >= (long) col->blue - blue_closeness &&
00290               (long) cols[c].blue <= (long) col->blue + blue_closeness) {
00291            if (XAllocColor(display, colormap, &cols[c])) {
00292               if (n == ITERATIONS)
00293                   XUngrabServer(display);
00294               XpmFree(closenesses);
00295               *image_pixel = cols[c].pixel;
00296               *mask_pixel = 1;
00297               alloc_pixels[(*nalloc_pixels)++] = cols[c].pixel;
00298               return (0);
00299            } else {
00300               ++i;
00301               if (i == ncols)
00302                   break;
00303               c = closenesses[i].cols_index;
00304            }
00305        }
00306 
00307        /* Couldn't allocate _any_ of the close colors! */
00308 
00309        if (n == ITERATIONS)
00310            XUngrabServer(display);
00311        XpmFree(closenesses);
00312 
00313        if (i == 0 || i == ncols)   /* no color close enough or cannot */
00314            return (1);                    /* alloc any color (full of r/w's) */
00315 
00316        if (XAllocColor(display, colormap, col)) {
00317            *image_pixel = col->pixel;
00318            *mask_pixel = 1;
00319            alloc_pixels[(*nalloc_pixels)++] = col->pixel;
00320            return (0);
00321        } else {                    /* colormap has probably changed, so
00322                                     * re-read... */
00323            if (n == ITERATIONS - 1)
00324               XGrabServer(display);
00325 
00326 #if 0
00327            if (visual->class == DirectColor) {
00328               /* TODO */
00329            } else
00330 #endif
00331               XQueryColors(display, colormap, cols, ncols);
00332        }
00333     }
00334     return (1);
00335 }
00336 
00337 #define USE_CLOSECOLOR attributes && \
00338 (((attributes->valuemask & XpmCloseness) && attributes->closeness != 0) \
00339  || ((attributes->valuemask & XpmRGBCloseness) && \
00340      (attributes->red_closeness != 0 \
00341       || attributes->green_closeness != 0 \
00342       || attributes->blue_closeness != 0)))
00343 
00344 #else
00345     /* FOR_MSW part */
00346     /* nothing to do here, the window system does it */
00347 #endif
00348 
00349 /*
00350  * set the color pixel related to the given colorname,
00351  * return 0 if success, 1 otherwise.
00352  */
00353 
00354 static int
00355 SetColor(display, colormap, visual, colorname, color_index,
00356         image_pixel, mask_pixel, mask_pixel_index,
00357         alloc_pixels, nalloc_pixels, used_pixels, nused_pixels,
00358         attributes, cols, ncols)
00359     Display *display;
00360     Colormap colormap;
00361     Visual *visual;
00362     char *colorname;
00363     unsigned int color_index;
00364     Pixel *image_pixel, *mask_pixel;
00365     unsigned int *mask_pixel_index;
00366     Pixel *alloc_pixels;
00367     unsigned int *nalloc_pixels;
00368     Pixel *used_pixels;
00369     unsigned int *nused_pixels;
00370     XpmAttributes *attributes;
00371     XColor *cols;
00372     int ncols;
00373 {
00374     XColor xcolor;
00375 
00376     if (strcasecmp(colorname, TRANSPARENT_COLOR)) {
00377        if (!XParseColor(display, colormap, colorname, &xcolor))
00378            return (1);
00379        if (!XAllocColor(display, colormap, &xcolor)) {
00380 #ifndef FOR_MSW
00381            if (USE_CLOSECOLOR)
00382               return (SetCloseColor(display, colormap, visual, &xcolor,
00383                                   image_pixel, mask_pixel,
00384                                   alloc_pixels, nalloc_pixels,
00385                                   attributes, cols, ncols));
00386            else
00387 #endif /* ndef FOR_MSW */
00388               return (1);
00389        } else
00390            alloc_pixels[(*nalloc_pixels)++] = xcolor.pixel;
00391        *image_pixel = xcolor.pixel;
00392        *mask_pixel = 1;
00393        used_pixels[(*nused_pixels)++] = xcolor.pixel;
00394     } else {
00395        *image_pixel = 0;
00396        *mask_pixel = 0;
00397        /* store the color table index */
00398        *mask_pixel_index = color_index;
00399     }
00400     return (0);
00401 }
00402 
00403 
00404 static int
00405 CreateColors(display, attributes, colors, ncolors, image_pixels, mask_pixels,
00406             mask_pixel_index, alloc_pixels, nalloc_pixels,
00407             used_pixels, nused_pixels)
00408     Display *display;
00409     XpmAttributes *attributes;
00410     XpmColor *colors;
00411     unsigned int ncolors;
00412     Pixel *image_pixels;
00413     Pixel *mask_pixels;
00414     unsigned int *mask_pixel_index;
00415     Pixel *alloc_pixels;
00416     unsigned int *nalloc_pixels;
00417     Pixel *used_pixels;
00418     unsigned int *nused_pixels;
00419 {
00420     /* variables stored in the XpmAttributes structure */
00421     Visual *visual;
00422     Colormap colormap;
00423     XpmColorSymbol *colorsymbols;
00424     unsigned int numsymbols;
00425 
00426     char *colorname;
00427     unsigned int color, key;
00428     Bool pixel_defined;
00429     XpmColorSymbol *symbol;
00430     char **defaults;
00431     int ErrorStatus = XpmSuccess;
00432     char *s;
00433     int default_index;
00434 
00435     XColor *cols = NULL;
00436     unsigned int ncols = 0;
00437 
00438     /*
00439      * retrieve information from the XpmAttributes
00440      */
00441     if (attributes && attributes->valuemask & XpmColorSymbols) {
00442        colorsymbols = attributes->colorsymbols;
00443        numsymbols = attributes->numsymbols;
00444     } else
00445        numsymbols = 0;
00446 
00447     if (attributes && attributes->valuemask & XpmVisual)
00448        visual = attributes->visual;
00449     else
00450        visual = XDefaultVisual(display, XDefaultScreen(display));
00451 
00452     if (attributes && attributes->valuemask & XpmColormap)
00453        colormap = attributes->colormap;
00454     else
00455        colormap = XDefaultColormap(display, XDefaultScreen(display));
00456 
00457     if (attributes && attributes->valuemask & XpmColorKey)
00458        key = attributes->color_key;
00459     else
00460        key = xpmVisualType(visual);
00461 
00462 #ifndef FOR_MSW
00463     if (USE_CLOSECOLOR) {
00464        /* originally from SetCloseColor */
00465 #if 0
00466        if (visual->class == DirectColor) {
00467 
00468            /*
00469             * TODO: Implement close colors for DirectColor visuals. This is
00470             * difficult situation. Chances are that we will never get here,
00471             * because any machine that supports DirectColor will probably
00472             * also support TrueColor (and probably PseudoColor). Also,
00473             * DirectColor colormaps can be very large, so looking for close
00474             * colors may be too slow.
00475             */
00476        } else {
00477 #endif
00478            int i;
00479 
00480            ncols = visual->map_entries;
00481            cols = (XColor *) XpmCalloc(ncols, sizeof(XColor));
00482            for (i = 0; i < ncols; ++i)
00483               cols[i].pixel = i;
00484            XQueryColors(display, colormap, cols, ncols);
00485 #if 0
00486        }
00487 #endif
00488     }
00489 #endif /* ndef FOR_MSW */
00490 
00491     switch (key) {
00492     case XPM_MONO:
00493        default_index = 2;
00494        break;
00495     case XPM_GRAY4:
00496        default_index = 3;
00497        break;
00498     case XPM_GRAY:
00499        default_index = 4;
00500        break;
00501     case XPM_COLOR:
00502     default:
00503        default_index = 5;
00504        break;
00505     }
00506 
00507     for (color = 0; color < ncolors; color++, colors++,
00508                                     image_pixels++, mask_pixels++) {
00509        colorname = NULL;
00510        pixel_defined = False;
00511        defaults = (char **) colors;
00512 
00513        /*
00514         * look for a defined symbol
00515         */
00516        if (numsymbols) {
00517 
00518            unsigned int n;
00519 
00520            s = defaults[1];
00521            for (n = 0, symbol = colorsymbols; n < numsymbols; n++, symbol++) {
00522               if (symbol->name && s && !strcmp(symbol->name, s))
00523                   /* override name */
00524                   break;
00525               if (!symbol->name && symbol->value) {     /* override value */
00526                   int def_index = default_index;
00527 
00528                   while (defaults[def_index] == NULL)   /* find defined
00529                                                   * colorname */
00530                      --def_index;
00531                   if (def_index < 2) {/* nothing towards mono, so try
00532                                     * towards color */
00533                      def_index = default_index + 1;
00534                      while (def_index <= 5 && defaults[def_index] == NULL)
00535                          ++def_index;
00536                   }
00537                   if (def_index >= 2 && defaults[def_index] != NULL &&
00538                      !strcasecmp(symbol->value, defaults[def_index]))
00539                      break;
00540               }
00541            }
00542            if (n != numsymbols) {
00543               if (symbol->name && symbol->value)
00544                   colorname = symbol->value;
00545               else
00546                   pixel_defined = True;
00547            }
00548        }
00549        if (!pixel_defined) {              /* pixel not given as symbol value */
00550 
00551            unsigned int k;
00552 
00553            if (colorname) {        /* colorname given as symbol value */
00554               if (!SetColor(display, colormap, visual, colorname, color,
00555                            image_pixels, mask_pixels, mask_pixel_index,
00556                            alloc_pixels, nalloc_pixels, used_pixels,
00557                            nused_pixels, attributes, cols, ncols))
00558                   pixel_defined = True;
00559               else
00560                   ErrorStatus = XpmColorError;
00561            }
00562            k = key;
00563            while (!pixel_defined && k > 1) {
00564               if (defaults[k]) {
00565                   if (!SetColor(display, colormap, visual, defaults[k],
00566                               color, image_pixels, mask_pixels,
00567                               mask_pixel_index, alloc_pixels,
00568                               nalloc_pixels, used_pixels, nused_pixels,
00569                               attributes, cols, ncols)) {
00570                      pixel_defined = True;
00571                      break;
00572                   } else
00573                      ErrorStatus = XpmColorError;
00574               }
00575               k--;
00576            }
00577            k = key + 1;
00578            while (!pixel_defined && k < NKEYS + 1) {
00579               if (defaults[k]) {
00580                   if (!SetColor(display, colormap, visual, defaults[k],
00581                               color, image_pixels, mask_pixels,
00582                               mask_pixel_index, alloc_pixels,
00583                               nalloc_pixels, used_pixels, nused_pixels,
00584                               attributes, cols, ncols)) {
00585                      pixel_defined = True;
00586                      break;
00587                   } else
00588                      ErrorStatus = XpmColorError;
00589               }
00590               k++;
00591            }
00592            if (!pixel_defined) {
00593               if (cols)
00594                   XpmFree(cols);
00595               return (XpmColorFailed);
00596            }
00597        } else {
00598            /* simply use the given pixel */
00599            *image_pixels = symbol->pixel;
00600            /* the following makes the mask to be built even if none
00601               is given a particular pixel */
00602            if (symbol->value
00603               && !strcasecmp(symbol->value, TRANSPARENT_COLOR)) {
00604               *mask_pixels = 0;
00605               *mask_pixel_index = color;
00606            } else
00607               *mask_pixels = 1;
00608            used_pixels[(*nused_pixels)++] = *image_pixels;
00609        }
00610     }
00611     if (cols)
00612        XpmFree(cols);
00613     return (ErrorStatus);
00614 }
00615 
00616 
00617 /* function call in case of error, frees only locally allocated variables */
00618 #undef RETURN
00619 #define RETURN(status) \
00620 { \
00621     if (ximage) XDestroyImage(ximage); \
00622     if (shapeimage) XDestroyImage(shapeimage); \
00623     if (image_pixels) XpmFree(image_pixels); \
00624     if (mask_pixels) XpmFree(mask_pixels); \
00625     if (nalloc_pixels) \
00626        XFreeColors(display, colormap, alloc_pixels, nalloc_pixels, 0); \
00627     if (alloc_pixels) XpmFree(alloc_pixels); \
00628     if (used_pixels) XpmFree(used_pixels); \
00629     return (status); \
00630 }
00631 
00632 int
00633 XpmCreateImageFromXpmImage(display, image,
00634                         image_return, shapeimage_return, attributes)
00635     Display *display;
00636     XpmImage *image;
00637     XImage **image_return;
00638     XImage **shapeimage_return;
00639     XpmAttributes *attributes;
00640 {
00641     /* variables stored in the XpmAttributes structure */
00642     Visual *visual;
00643     Colormap colormap;
00644     unsigned int depth;
00645 
00646     /* variables to return */
00647     XImage *ximage = NULL;
00648     XImage *shapeimage = NULL;
00649     unsigned int mask_pixel_index = XpmUndefPixel;
00650     int ErrorStatus;
00651 
00652     /* calculation variables */
00653     Pixel *image_pixels = NULL;
00654     Pixel *mask_pixels = NULL;
00655     Pixel *alloc_pixels = NULL;
00656     Pixel *used_pixels = NULL;
00657     unsigned int nalloc_pixels = 0;
00658     unsigned int nused_pixels = 0;
00659 
00660     /* initialize return values */
00661     if (image_return)
00662        *image_return = NULL;
00663     if (shapeimage_return)
00664        *shapeimage_return = NULL;
00665 
00666     /* retrieve information from the XpmAttributes */
00667     if (attributes && (attributes->valuemask & XpmVisual))
00668        visual = attributes->visual;
00669     else
00670        visual = XDefaultVisual(display, XDefaultScreen(display));
00671 
00672     if (attributes && (attributes->valuemask & XpmColormap))
00673        colormap = attributes->colormap;
00674     else
00675        colormap = XDefaultColormap(display, XDefaultScreen(display));
00676 
00677     if (attributes && (attributes->valuemask & XpmDepth))
00678        depth = attributes->depth;
00679     else
00680        depth = XDefaultDepth(display, XDefaultScreen(display));
00681 
00682     ErrorStatus = XpmSuccess;
00683 
00684     /* malloc pixels index tables */
00685     image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
00686     if (!image_pixels)
00687        return (XpmNoMemory);
00688 
00689     mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
00690     if (!mask_pixels)
00691        RETURN(XpmNoMemory);
00692 
00693     /* maximum of allocated pixels will be the number of colors */
00694     alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
00695     if (!alloc_pixels)
00696        RETURN(XpmNoMemory);
00697 
00698     /* maximum of allocated pixels will be the number of colors */
00699     used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
00700     if (!used_pixels)
00701        RETURN(XpmNoMemory);
00702 
00703     /* get pixel colors, store them in index tables */
00704     ErrorStatus = CreateColors(display, attributes, image->colorTable,
00705                             image->ncolors, image_pixels, mask_pixels,
00706                             &mask_pixel_index, alloc_pixels, &nalloc_pixels,
00707                             used_pixels, &nused_pixels);
00708 
00709     if (ErrorStatus != XpmSuccess
00710        && (ErrorStatus < 0 || (attributes
00711                             && (attributes->valuemask & XpmExactColors)
00712                             && attributes->exactColors)))
00713        RETURN(ErrorStatus);
00714 
00715     /* create the ximage */
00716     if (image_return) {
00717        ErrorStatus = CreateXImage(display, visual, depth,
00718                                image->width, image->height, &ximage);
00719        if (ErrorStatus != XpmSuccess)
00720            RETURN(ErrorStatus);
00721 
00722 #ifndef FOR_MSW
00723 
00724        /*
00725         * set the ximage data
00726         * 
00727         * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use
00728         * optimized functions, otherwise use slower but sure general one.
00729         * 
00730         */
00731 
00732        if (ximage->depth == 1)
00733            SetImagePixels1(ximage, image->width, image->height,
00734                          image->data, image_pixels);
00735        else if (ximage->bits_per_pixel == 8)
00736            SetImagePixels8(ximage, image->width, image->height,
00737                          image->data, image_pixels);
00738        else if (ximage->bits_per_pixel == 16)
00739            SetImagePixels16(ximage, image->width, image->height,
00740                           image->data, image_pixels);
00741        else if (ximage->bits_per_pixel == 32)
00742            SetImagePixels32(ximage, image->width, image->height,
00743                           image->data, image_pixels);
00744        else
00745            SetImagePixels(ximage, image->width, image->height,
00746                         image->data, image_pixels);
00747 #else  /* FOR_MSW */
00748        MSWSetImagePixels(display, ximage, image->width, image->height,
00749                        image->data, image_pixels);
00750 #endif
00751     }
00752     /* create the shape mask image */
00753     if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
00754        ErrorStatus = CreateXImage(display, visual, 1, image->width,
00755                                image->height, &shapeimage);
00756        if (ErrorStatus != XpmSuccess)
00757            RETURN(ErrorStatus);
00758 
00759 #ifndef FOR_MSW
00760        SetImagePixels1(shapeimage, image->width, image->height,
00761                      image->data, mask_pixels);
00762 #else
00763        MSWSetImagePixels(display, shapeimage, image->width, image->height,
00764                        image->data, mask_pixels);
00765 #endif
00766 
00767     }
00768     XpmFree(image_pixels);
00769     XpmFree(mask_pixels);
00770 
00771     /* if requested return used pixels in the XpmAttributes structure */
00772     if (attributes && (attributes->valuemask & XpmReturnPixels ||
00773 /* 3.2 backward compatibility code */
00774        attributes->valuemask & XpmReturnInfos)) {
00775 /* end 3.2 bc */
00776        attributes->pixels = used_pixels;
00777        attributes->npixels = nused_pixels;
00778        attributes->mask_pixel = mask_pixel_index;
00779     } else
00780        XpmFree(used_pixels);
00781 
00782     /* if requested return alloc'ed pixels in the XpmAttributes structure */
00783     if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
00784        attributes->alloc_pixels = alloc_pixels;
00785        attributes->nalloc_pixels = nalloc_pixels;
00786     } else
00787        XpmFree(alloc_pixels);
00788 
00789     /* return created images */
00790     if (image_return)
00791        *image_return = ximage;
00792     if (shapeimage_return)
00793        *shapeimage_return = shapeimage;
00794 
00795     return (ErrorStatus);
00796 }
00797 
00798 
00799 /*
00800  * Create an XImage
00801  */
00802 static int
00803 CreateXImage(display, visual, depth, width, height, image_return)
00804     Display *display;
00805     Visual *visual;
00806     unsigned int depth;
00807     unsigned int width;
00808     unsigned int height;
00809     XImage **image_return;
00810 {
00811     int bitmap_pad;
00812 
00813     /* first get bitmap_pad */
00814     if (depth > 16)
00815        bitmap_pad = 32;
00816     else if (depth > 8)
00817        bitmap_pad = 16;
00818     else
00819        bitmap_pad = 8;
00820 
00821     /* then create the XImage with data = NULL and bytes_per_line = 0 */
00822     *image_return = XCreateImage(display, visual, depth, ZPixmap, 0, 0,
00823                              width, height, bitmap_pad, 0);
00824     if (!*image_return)
00825        return (XpmNoMemory);
00826 
00827 #ifndef FOR_MSW
00828     /* now that bytes_per_line must have been set properly alloc data */
00829     (*image_return)->data =
00830        (char *) XpmMalloc((*image_return)->bytes_per_line * height);
00831 
00832     if (!(*image_return)->data) {
00833        XDestroyImage(*image_return);
00834        *image_return = NULL;
00835        return (XpmNoMemory);
00836     }
00837 #else
00838     /* under FOR_MSW XCreateImage has done it all */
00839 #endif
00840     return (XpmSuccess);
00841 }
00842 
00843 #ifndef FOR_MSW
00844 /*
00845  * The functions below are written from X11R5 MIT's code (XImUtil.c)
00846  *
00847  * The idea is to have faster functions than the standard XPutPixel function
00848  * to build the image data. Indeed we can speed up things by suppressing tests
00849  * performed for each pixel. We do the same tests but at the image level.
00850  * We also assume that we use only ZPixmap images with null offsets.
00851  */
00852 
00853 LFUNC(_putbits, void, (register char *src, int dstoffset,
00854                      register int numbits, register char *dst));
00855 
00856 LFUNC(_XReverse_Bytes, int, (register unsigned char *bpt, register int nb));
00857 
00858 static unsigned char Const _reverse_byte[0x100] = {
00859     0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
00860     0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
00861     0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
00862     0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
00863     0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
00864     0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
00865     0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
00866     0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
00867     0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
00868     0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
00869     0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
00870     0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
00871     0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
00872     0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
00873     0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
00874     0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
00875     0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
00876     0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
00877     0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
00878     0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
00879     0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
00880     0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
00881     0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
00882     0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
00883     0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
00884     0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
00885     0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
00886     0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
00887     0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
00888     0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
00889     0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
00890     0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
00891 };
00892 
00893 static int
00894 _XReverse_Bytes(bpt, nb)
00895     register unsigned char *bpt;
00896     register int nb;
00897 {
00898     do {
00899        *bpt = _reverse_byte[*bpt];
00900        bpt++;
00901     } while (--nb > 0);
00902     return 0;
00903 }
00904 
00905 
00906 void
00907 xpm_xynormalizeimagebits(bp, img)
00908     register unsigned char *bp;
00909     register XImage *img;
00910 {
00911     register unsigned char c;
00912 
00913     if (img->byte_order != img->bitmap_bit_order) {
00914        switch (img->bitmap_unit) {
00915 
00916        case 16:
00917            c = *bp;
00918            *bp = *(bp + 1);
00919            *(bp + 1) = c;
00920            break;
00921 
00922        case 32:
00923            c = *(bp + 3);
00924            *(bp + 3) = *bp;
00925            *bp = c;
00926            c = *(bp + 2);
00927            *(bp + 2) = *(bp + 1);
00928            *(bp + 1) = c;
00929            break;
00930        }
00931     }
00932     if (img->bitmap_bit_order == MSBFirst)
00933        _XReverse_Bytes(bp, img->bitmap_unit >> 3);
00934 }
00935 
00936 void
00937 xpm_znormalizeimagebits(bp, img)
00938     register unsigned char *bp;
00939     register XImage *img;
00940 {
00941     register unsigned char c;
00942 
00943     switch (img->bits_per_pixel) {
00944 
00945     case 2:
00946        _XReverse_Bytes(bp, 1);
00947        break;
00948 
00949     case 4:
00950        *bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF);
00951        break;
00952 
00953     case 16:
00954        c = *bp;
00955        *bp = *(bp + 1);
00956        *(bp + 1) = c;
00957        break;
00958 
00959     case 24:
00960        c = *(bp + 2);
00961        *(bp + 2) = *bp;
00962        *bp = c;
00963        break;
00964 
00965     case 32:
00966        c = *(bp + 3);
00967        *(bp + 3) = *bp;
00968        *bp = c;
00969        c = *(bp + 2);
00970        *(bp + 2) = *(bp + 1);
00971        *(bp + 1) = c;
00972        break;
00973     }
00974 }
00975 
00976 static unsigned char Const _lomask[0x09] = {
00977 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
00978 static unsigned char Const _himask[0x09] = {
00979 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
00980 
00981 static void
00982 _putbits(src, dstoffset, numbits, dst)
00983     register char *src;                   /* address of source bit string */
00984     int dstoffset;                 /* bit offset into destination;
00985                                     * range is 0-31 */
00986     register int numbits;          /* number of bits to copy to
00987                                     * destination */
00988     register char *dst;                   /* address of destination bit string */
00989 {
00990     register unsigned char chlo, chhi;
00991     int hibits;
00992 
00993     dst = dst + (dstoffset >> 3);
00994     dstoffset = dstoffset & 7;
00995     hibits = 8 - dstoffset;
00996     chlo = *dst & _lomask[dstoffset];
00997     for (;;) {
00998        chhi = (*src << dstoffset) & _himask[dstoffset];
00999        if (numbits <= hibits) {
01000            chhi = chhi & _lomask[dstoffset + numbits];
01001            *dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi;
01002            break;
01003        }
01004        *dst = chhi | chlo;
01005        dst++;
01006        numbits = numbits - hibits;
01007        chlo = (unsigned char) (*src & _himask[hibits]) >> hibits;
01008        src++;
01009        if (numbits <= dstoffset) {
01010            chlo = chlo & _lomask[numbits];
01011            *dst = (*dst & _himask[numbits]) | chlo;
01012            break;
01013        }
01014        numbits = numbits - dstoffset;
01015     }
01016 }
01017 
01018 /*
01019  * Default method to write pixels into a Z image data structure.
01020  * The algorithm used is:
01021  *
01022  *     copy the destination bitmap_unit or Zpixel to temp
01023  *     normalize temp if needed
01024  *     copy the pixel bits into the temp
01025  *     renormalize temp if needed
01026  *     copy the temp back into the destination image data
01027  */
01028 
01029 static void
01030 SetImagePixels(image, width, height, pixelindex, pixels)
01031     XImage *image;
01032     unsigned int width;
01033     unsigned int height;
01034     unsigned int *pixelindex;
01035     Pixel *pixels;
01036 {
01037     register char *src;
01038     register char *dst;
01039     register unsigned int *iptr;
01040     register int x, y, i;
01041     register char *data;
01042     Pixel pixel, px;
01043     int nbytes, depth, ibu, ibpp;
01044 
01045     data = image->data;
01046     iptr = pixelindex;
01047     depth = image->depth;
01048     if (depth == 1) {
01049        ibu = image->bitmap_unit;
01050        for (y = 0; y < height; y++)
01051            for (x = 0; x < width; x++, iptr++) {
01052               pixel = pixels[*iptr];
01053               for (i = 0, px = pixel; i < sizeof(unsigned long);
01054                    i++, px >>= 8)
01055                   ((unsigned char *) &pixel)[i] = px;
01056               src = &data[XYINDEX(x, y, image)];
01057               dst = (char *) &px;
01058               px = 0;
01059               nbytes = ibu >> 3;
01060               for (i = nbytes; --i >= 0;)
01061                   *dst++ = *src++;
01062               XYNORMALIZE(&px, image);
01063               _putbits((char *) &pixel, (x % ibu), 1, (char *) &px);
01064               XYNORMALIZE(&px, image);
01065               src = (char *) &px;
01066               dst = &data[XYINDEX(x, y, image)];
01067               for (i = nbytes; --i >= 0;)
01068                   *dst++ = *src++;
01069            }
01070     } else {
01071        ibpp = image->bits_per_pixel;
01072        for (y = 0; y < height; y++)
01073            for (x = 0; x < width; x++, iptr++) {
01074               pixel = pixels[*iptr];
01075               if (depth == 4)
01076                   pixel &= 0xf;
01077               for (i = 0, px = pixel; i < sizeof(unsigned long); i++,
01078                    px >>= 8)
01079                   ((unsigned char *) &pixel)[i] = px;
01080               src = &data[ZINDEX(x, y, image)];
01081               dst = (char *) &px;
01082               px = 0;
01083               nbytes = (ibpp + 7) >> 3;
01084               for (i = nbytes; --i >= 0;)
01085                   *dst++ = *src++;
01086               ZNORMALIZE(&px, image);
01087               _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
01088               ZNORMALIZE(&px, image);
01089               src = (char *) &px;
01090               dst = &data[ZINDEX(x, y, image)];
01091               for (i = nbytes; --i >= 0;)
01092                   *dst++ = *src++;
01093            }
01094     }
01095 }
01096 
01097 /*
01098  * write pixels into a 32-bits Z image data structure
01099  */
01100 
01101 #if !defined(WORD64) && !defined(LONG64)
01102 /* this item is static but deterministic so let it slide; doesn't
01103  * hurt re-entrancy of this library. Note if it is actually const then would
01104  * be OK under rules of ANSI-C but probably not C++ which may not
01105  * want to allocate space for it.
01106  */
01107 static unsigned long /* constant */ RTXpm_byteorderpixel = MSBFirst << 24;
01108 
01109 #endif
01110 
01111 /*
01112    WITHOUT_SPEEDUPS is a flag to be turned on if you wish to use the original
01113    3.2e code - by default you get the speeded-up version.
01114 */
01115 
01116 static void
01117 SetImagePixels32(image, width, height, pixelindex, pixels)
01118     XImage *image;
01119     unsigned int width;
01120     unsigned int height;
01121     unsigned int *pixelindex;
01122     Pixel *pixels;
01123 {
01124     unsigned char *data;
01125     unsigned int *iptr;
01126     int y;
01127     Pixel pixel;
01128 
01129 #ifdef WITHOUT_SPEEDUPS
01130 
01131     int x;
01132     unsigned char *addr;
01133 
01134     data = (unsigned char *) image->data;
01135     iptr = pixelindex;
01136 #if !defined(WORD64) && !defined(LONG64)
01137     if (*((char *) &RTXpm_byteorderpixel) == image->byte_order) {
01138        for (y = 0; y < height; y++)
01139            for (x = 0; x < width; x++, iptr++) {
01140               addr = &data[ZINDEX32(x, y, image)];
01141               *((unsigned long *) addr) = pixels[*iptr];
01142            }
01143     } else
01144 #endif
01145     if (image->byte_order == MSBFirst)
01146        for (y = 0; y < height; y++)
01147            for (x = 0; x < width; x++, iptr++) {
01148               addr = &data[ZINDEX32(x, y, image)];
01149               pixel = pixels[*iptr];
01150               addr[0] = pixel >> 24;
01151               addr[1] = pixel >> 16;
01152               addr[2] = pixel >> 8;
01153               addr[3] = pixel;
01154            }
01155     else
01156        for (y = 0; y < height; y++)
01157            for (x = 0; x < width; x++, iptr++) {
01158               addr = &data[ZINDEX32(x, y, image)];
01159               pixel = pixels[*iptr];
01160               addr[0] = pixel;
01161               addr[1] = pixel >> 8;
01162               addr[2] = pixel >> 16;
01163               addr[3] = pixel >> 24;
01164            }
01165 
01166 #else  /* WITHOUT_SPEEDUPS */
01167 
01168     int bpl = image->bytes_per_line;
01169     unsigned char *data_ptr, *max_data;
01170 
01171     data = (unsigned char *) image->data;
01172     iptr = pixelindex;
01173 #if !defined(WORD64) && !defined(LONG64)
01174     if (*((char *) &RTXpm_byteorderpixel) == image->byte_order) {
01175        for (y = 0; y < height; y++) {
01176            data_ptr = data;
01177            max_data = data_ptr + (width << 2);
01178 
01179            while (data_ptr < max_data) {
01180               *((unsigned long *) data_ptr) = pixels[*(iptr++)];
01181               data_ptr += (1 << 2);
01182            }
01183            data += bpl;
01184        }
01185     } else
01186 #endif
01187     if (image->byte_order == MSBFirst)
01188        for (y = 0; y < height; y++) {
01189            data_ptr = data;
01190            max_data = data_ptr + (width << 2);
01191 
01192            while (data_ptr < max_data) {
01193               pixel = pixels[*(iptr++)];
01194 
01195               *data_ptr++ = pixel >> 24;
01196               *data_ptr++ = pixel >> 16;
01197               *data_ptr++ = pixel >> 8;
01198               *data_ptr++ = pixel;
01199 
01200            }
01201            data += bpl;
01202        }
01203     else
01204        for (y = 0; y < height; y++) {
01205            data_ptr = data;
01206            max_data = data_ptr + (width << 2);
01207 
01208            while (data_ptr < max_data) {
01209               pixel = pixels[*(iptr++)];
01210 
01211               *data_ptr++ = pixel;
01212               *data_ptr++ = pixel >> 8;
01213               *data_ptr++ = pixel >> 16;
01214               *data_ptr++ = pixel >> 24;
01215            }
01216            data += bpl;
01217        }
01218 
01219 #endif /* WITHOUT_SPEEDUPS */
01220 }
01221 
01222 /*
01223  * write pixels into a 16-bits Z image data structure
01224  */
01225 
01226 static void
01227 SetImagePixels16(image, width, height, pixelindex, pixels)
01228     XImage *image;
01229     unsigned int width;
01230     unsigned int height;
01231     unsigned int *pixelindex;
01232     Pixel *pixels;
01233 {
01234     unsigned char *data;
01235     unsigned int *iptr;
01236     int y;
01237 
01238 #ifdef WITHOUT_SPEEDUPS
01239 
01240     int x;
01241     unsigned char *addr;
01242 
01243     data = (unsigned char *) image->data;
01244     iptr = pixelindex;
01245     if (image->byte_order == MSBFirst)
01246        for (y = 0; y < height; y++)
01247            for (x = 0; x < width; x++, iptr++) {
01248               addr = &data[ZINDEX16(x, y, image)];
01249               addr[0] = pixels[*iptr] >> 8;
01250               addr[1] = pixels[*iptr];
01251            }
01252     else
01253        for (y = 0; y < height; y++)
01254            for (x = 0; x < width; x++, iptr++) {
01255               addr = &data[ZINDEX16(x, y, image)];
01256               addr[0] = pixels[*iptr];
01257               addr[1] = pixels[*iptr] >> 8;
01258            }
01259 
01260 #else  /* WITHOUT_SPEEDUPS */
01261 
01262     Pixel pixel;
01263 
01264     int bpl = image->bytes_per_line;
01265     unsigned char *data_ptr, *max_data;
01266 
01267     data = (unsigned char *) image->data;
01268     iptr = pixelindex;
01269     if (image->byte_order == MSBFirst)
01270        for (y = 0; y < height; y++) {
01271            data_ptr = data;
01272            max_data = data_ptr + (width << 1);
01273 
01274            while (data_ptr < max_data) {
01275               pixel = pixels[*(iptr++)];
01276 
01277               data_ptr[0] = pixel >> 8;
01278               data_ptr[1] = pixel;
01279 
01280               data_ptr += (1 << 1);
01281            }
01282            data += bpl;
01283        }
01284     else
01285        for (y = 0; y < height; y++) {
01286            data_ptr = data;
01287            max_data = data_ptr + (width << 1);
01288 
01289            while (data_ptr < max_data) {
01290               pixel = pixels[*(iptr++)];
01291 
01292               data_ptr[0] = pixel;
01293               data_ptr[1] = pixel >> 8;
01294 
01295               data_ptr += (1 << 1);
01296            }
01297            data += bpl;
01298        }
01299 
01300 #endif /* WITHOUT_SPEEDUPS */
01301 }
01302 
01303 /*
01304  * write pixels into a 8-bits Z image data structure
01305  */
01306 
01307 static void
01308 SetImagePixels8(image, width, height, pixelindex, pixels)
01309     XImage *image;
01310     unsigned int width;
01311     unsigned int height;
01312     unsigned int *pixelindex;
01313     Pixel *pixels;
01314 {
01315     char *data;
01316     unsigned int *iptr;
01317     int y;
01318 
01319 #ifdef WITHOUT_SPEEDUPS
01320 
01321     int x;
01322 
01323     data = image->data;
01324     iptr = pixelindex;
01325     for (y = 0; y < height; y++)
01326        for (x = 0; x < width; x++, iptr++)
01327            data[ZINDEX8(x, y, image)] = pixels[*iptr];
01328 
01329 #else  /* WITHOUT_SPEEDUPS */
01330 
01331     int bpl = image->bytes_per_line;
01332     char *data_ptr, *max_data;
01333 
01334     data = image->data;
01335     iptr = pixelindex;
01336 
01337     for (y = 0; y < height; y++) {
01338        data_ptr = data;
01339        max_data = data_ptr + width;
01340 
01341        while (data_ptr < max_data)
01342            *(data_ptr++) = pixels[*(iptr++)];
01343 
01344        data += bpl;
01345     }
01346 
01347 #endif /* WITHOUT_SPEEDUPS */
01348 }
01349 
01350 /*
01351  * write pixels into a 1-bit depth image data structure and **offset null**
01352  */
01353 
01354 static void
01355 SetImagePixels1(image, width, height, pixelindex, pixels)
01356     XImage *image;
01357     unsigned int width;
01358     unsigned int height;
01359     unsigned int *pixelindex;
01360     Pixel *pixels;
01361 {
01362     if (image->byte_order != image->bitmap_bit_order)
01363        SetImagePixels(image, width, height, pixelindex, pixels);
01364     else {
01365        unsigned int *iptr;
01366        int y;
01367        char *data;
01368 
01369 #ifdef WITHOUT_SPEEDUPS
01370 
01371        int x;
01372 
01373        data = image->data;
01374        iptr = pixelindex;
01375        if (image->bitmap_bit_order == MSBFirst)
01376            for (y = 0; y < height; y++)
01377               for (x = 0; x < width; x++, iptr++) {
01378                   if (pixels[*iptr] & 1)
01379                      data[ZINDEX1(x, y, image)] |= 0x80 >> (x & 7);
01380                   else
01381                      data[ZINDEX1(x, y, image)] &= ~(0x80 >> (x & 7));
01382               }
01383        else
01384            for (y = 0; y < height; y++)
01385               for (x = 0; x < width; x++, iptr++) {
01386                   if (pixels[*iptr] & 1)
01387                      data[ZINDEX1(x, y, image)] |= 1 << (x & 7);
01388                   else
01389                      data[ZINDEX1(x, y, image)] &= ~(1 << (x & 7));
01390               }
01391 
01392 #else  /* WITHOUT_SPEEDUPS */
01393 
01394        char value;
01395        char *data_ptr, *max_data;
01396        int bpl = image->bytes_per_line;
01397        int diff, count;
01398 
01399        data = image->data;
01400        iptr = pixelindex;
01401 
01402        diff = width & 7;
01403        width >>= 3;
01404 
01405        if (image->bitmap_bit_order == MSBFirst)
01406            for (y = 0; y < height; y++) {
01407               data_ptr = data;
01408               max_data = data_ptr + width;
01409               while (data_ptr < max_data) {
01410                   value = 0;
01411 
01412                   value = (value << 1) | (pixels[*(iptr++)] & 1);
01413                   value = (value << 1) | (pixels[*(iptr++)] & 1);
01414                   value = (value << 1) | (pixels[*(iptr++)] & 1);
01415                   value = (value << 1) | (pixels[*(iptr++)] & 1);
01416                   value = (value << 1) | (pixels[*(iptr++)] & 1);
01417                   value = (value << 1) | (pixels[*(iptr++)] & 1);
01418                   value = (value << 1) | (pixels[*(iptr++)] & 1);
01419                   value = (value << 1) | (pixels[*(iptr++)] & 1);
01420 
01421                   *(data_ptr++) = value;
01422               }
01423               if (diff) {
01424                   value = 0;
01425                   for (count = 0; count < diff; count++) {
01426                      if (pixels[*(iptr++)] & 1)
01427                          value |= (0x80 >> count);
01428                   }
01429                   *(data_ptr) = value;
01430               }
01431               data += bpl;
01432            }
01433        else
01434            for (y = 0; y < height; y++) {
01435               data_ptr = data;
01436               max_data = data_ptr + width;
01437               while (data_ptr < max_data) {
01438                   value = 0;
01439                   iptr += 8;
01440 
01441                   value = (value << 1) | (pixels[*(--iptr)] & 1);
01442                   value = (value << 1) | (pixels[*(--iptr)] & 1);
01443                   value = (value << 1) | (pixels[*(--iptr)] & 1);
01444                   value = (value << 1) | (pixels[*(--iptr)] & 1);
01445                   value = (value << 1) | (pixels[*(--iptr)] & 1);
01446                   value = (value << 1) | (pixels[*(--iptr)] & 1);
01447                   value = (value << 1) | (pixels[*(--iptr)] & 1);
01448                   value = (value << 1) | (pixels[*(--iptr)] & 1);
01449 
01450                   iptr += 8;
01451                   *(data_ptr++) = value;
01452               }
01453               if (diff) {
01454                   value = 0;
01455                   for (count = 0; count < diff; count++) {
01456                      if (pixels[*(iptr++)] & 1)
01457                          value |= (1 << count);
01458                   }
01459                   *(data_ptr) = value;
01460               }
01461               data += bpl;
01462            }
01463 
01464 #endif /* WITHOUT_SPEEDUPS */
01465     }
01466 }
01467 
01468 int
01469 XpmCreatePixmapFromXpmImage(display, d, image,
01470                          pixmap_return, shapemask_return, attributes)
01471     Display *display;
01472     Drawable d;
01473     XpmImage *image;
01474     Pixmap *pixmap_return;
01475     Pixmap *shapemask_return;
01476     XpmAttributes *attributes;
01477 {
01478     XImage *ximage, *shapeimage;
01479     int ErrorStatus;
01480 
01481     /* initialize return values */
01482     if (pixmap_return)
01483        *pixmap_return = 0;
01484     if (shapemask_return)
01485        *shapemask_return = 0;
01486 
01487     /* create the ximages */
01488     ErrorStatus = XpmCreateImageFromXpmImage(display, image,
01489                                         (pixmap_return ? &ximage : NULL),
01490                                         (shapemask_return ?
01491                                          &shapeimage : NULL),
01492                                         attributes);
01493     if (ErrorStatus < 0)
01494        return (ErrorStatus);
01495 
01496     /* create the pixmaps and destroy images */
01497     if (pixmap_return && ximage) {
01498        xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
01499        XDestroyImage(ximage);
01500     }
01501     if (shapemask_return && shapeimage) {
01502        xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
01503        XDestroyImage(shapeimage);
01504     }
01505     return (ErrorStatus);
01506 }
01507 
01508 #else  /* FOR_MSW part follows */
01509 static void
01510 MSWSetImagePixels(dc, image, width, height, pixelindex, pixels)
01511     Display *dc;
01512     XImage *image;
01513     unsigned int width;
01514     unsigned int height;
01515     unsigned int *pixelindex;
01516     Pixel *pixels;
01517 {
01518     unsigned int *data = pixelindex;
01519     unsigned int x, y;
01520 
01521     SelectObject(*dc, image->bitmap);
01522     for (y = 0; y < height; y++) {
01523        for (x = 0; x < width; x++) {
01524            SetPixel(*dc, x, y, pixels[*(data++)]); /* data is [x+y*width] */
01525        }
01526     }
01527 }
01528 
01529 #endif /* FOR_MSW */