summaryrefslogtreecommitdiff
path: root/src/xpm
diff options
context:
space:
mode:
Diffstat (limited to 'src/xpm')
-rw-r--r--src/xpm/Makefile28
-rw-r--r--src/xpm/XpmCrDataFI.c417
-rw-r--r--src/xpm/XpmCrDataFP.c75
-rw-r--r--src/xpm/XpmCrIFData.c52
-rw-r--r--src/xpm/XpmCrPFData.c92
-rw-r--r--src/xpm/XpmRdFToData.c115
-rw-r--r--src/xpm/XpmRdFToI.c110
-rw-r--r--src/xpm/XpmRdFToP.c92
-rw-r--r--src/xpm/XpmWrFFrData.c113
-rw-r--r--src/xpm/XpmWrFFrI.c341
-rw-r--r--src/xpm/XpmWrFFrP.c75
-rw-r--r--src/xpm/converters/ppm.README69
-rw-r--r--src/xpm/converters/ppmtoxpm.169
-rw-r--r--src/xpm/converters/ppmtoxpm.c481
-rw-r--r--src/xpm/converters/xpm1to3.pl90
-rw-r--r--src/xpm/converters/xpmtoppm.128
-rw-r--r--src/xpm/converters/xpmtoppm.c433
-rw-r--r--src/xpm/create.c963
-rw-r--r--src/xpm/data.c422
-rw-r--r--src/xpm/doc/CHANGES422
-rw-r--r--src/xpm/doc/COPYRIGHT30
-rw-r--r--src/xpm/doc/FILES42
-rw-r--r--src/xpm/doc/Imakefile59
-rw-r--r--src/xpm/doc/Makefile433
-rw-r--r--src/xpm/doc/Makefile.noXtree85
-rw-r--r--src/xpm/doc/README176
-rw-r--r--src/xpm/doc/colas.sty294
-rw-r--r--src/xpm/doc/name-3.0b-3.0c48
-rw-r--r--src/xpm/doc/name-3.0c-3.032
-rw-r--r--src/xpm/doc/plaid.xpm34
-rw-r--r--src/xpm/doc/plaid_mask.xpm35
-rw-r--r--src/xpm/doc/xpm.tex849
-rw-r--r--src/xpm/hashtable.c205
-rw-r--r--src/xpm/misc.c206
-rw-r--r--src/xpm/parse.c537
-rwxr-xr-xsrc/xpm/rename24
-rw-r--r--src/xpm/rgb.c136
-rw-r--r--src/xpm/scan.c567
-rw-r--r--src/xpm/sxpm.c580
-rw-r--r--src/xpm/sxpm.man89
-rw-r--r--src/xpm/xpm.h237
-rw-r--r--src/xpm/xpmP.h279
42 files changed, 9464 insertions, 0 deletions
diff --git a/src/xpm/Makefile b/src/xpm/Makefile
new file mode 100644
index 0000000..4dcbff5
--- /dev/null
+++ b/src/xpm/Makefile
@@ -0,0 +1,28 @@
+# Makefile for the C library part of XPM needed by Icon.
+# This file is a simplification of XPM's standard Makefile.
+
+include ../../Makedefs
+
+## if your system doesn't provide strcasecmp add -DNEED_STRCASECMP
+## if your system doesn't provide pipe remove -DZPIPE
+
+RM = rm -f
+AR = ar qc
+RANLIB = ranlib
+OBJS1 = data.o create.o misc.o rgb.o scan.o parse.o hashtable.o \
+ XpmWrFFrP.o XpmRdFToP.o XpmCrPFData.o XpmCrDataFP.o \
+ XpmWrFFrI.o XpmRdFToI.o XpmCrIFData.o XpmCrDataFI.o
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(XPMDEFS) $*.c
+
+
+libXpm.a: $(OBJS1)
+ $(RM) $@
+ $(AR) $@ $(OBJS1)
+ $(RANLIB) $@ 2>/dev/null || :
+
+$(OBJS1): xpmP.h xpm.h
+
+Clean:
+ rm *.o *.a
diff --git a/src/xpm/XpmCrDataFI.c b/src/xpm/XpmCrDataFI.c
new file mode 100644
index 0000000..81c742b
--- /dev/null
+++ b/src/xpm/XpmCrDataFI.c
@@ -0,0 +1,417 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* XpmCrDataFI.c: *
+* *
+* XPM library *
+* Scan an image and possibly its mask and create an XPM array *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+#include "xpmP.h"
+#ifdef VMS
+#include "sys$library:string.h"
+#else
+#if defined(SYSV) || defined(SVR4)
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#endif
+
+LFUNC(CreateTransparentColor, int, (char **dataptr, unsigned int *data_size,
+ char **colors, unsigned int cpp,
+ unsigned int mask_pixel,
+ char ***colorTable));
+
+LFUNC(CreateOtherColors, int, (char **dataptr, unsigned int *data_size,
+ char **colors, XColor *xcolors,
+ unsigned int ncolors, unsigned int cpp,
+ unsigned int mask_pixel, char ***colorTable,
+ unsigned int ncolors2, Pixel *pixels,
+ char *rgb_fname));
+
+LFUNC(CreatePixels, void, (char **dataptr, unsigned int width,
+ unsigned int height, unsigned int cpp,
+ unsigned int *pixels, char **colors));
+
+LFUNC(CountExtensions, void, (XpmExtension *ext, unsigned int num,
+ unsigned int *ext_size,
+ unsigned int *ext_nlines));
+
+LFUNC(CreateExtensions, void, (char **dataptr, unsigned int offset,
+ XpmExtension *ext, unsigned int num,
+ unsigned int ext_nlines));
+
+int
+XpmCreateDataFromImage(display, data_return, image, shapeimage, attributes)
+ Display *display;
+ char ***data_return;
+ XImage *image;
+ XImage *shapeimage;
+ XpmAttributes *attributes;
+{
+ int ErrorStatus;
+ xpmInternAttrib attrib;
+
+ /*
+ * initialize return values
+ */
+ if (data_return)
+ *data_return = NULL;
+
+ xpmInitInternAttrib(&attrib);
+
+ /*
+ * Scan image then create data
+ */
+ ErrorStatus = xpmScanImage(display, image, shapeimage,
+ attributes, &attrib);
+
+ if (ErrorStatus == XpmSuccess)
+ ErrorStatus = xpmCreateData(data_return, &attrib, attributes);
+
+ xpmFreeInternAttrib(&attrib);
+
+ return (ErrorStatus);
+}
+
+
+#undef RETURN
+#define RETURN(status) \
+ { if (header) { \
+ for (l = 0; l < header_nlines; l++) \
+ if (header[l]) \
+ free(header[l]); \
+ free(header); \
+ } \
+ return(status); }
+
+int
+xpmCreateData(data_return, attrib, attributes)
+ char ***data_return;
+ xpmInternAttrib *attrib;
+ XpmAttributes *attributes;
+{
+ /* calculation variables */
+ int ErrorStatus;
+ char buf[BUFSIZ];
+ char **header = NULL, **data, **sptr, **sptr2, *s;
+ unsigned int header_size, header_nlines;
+ unsigned int data_size, data_nlines;
+ unsigned int extensions = 0, ext_size = 0, ext_nlines = 0;
+ unsigned int infos = 0, offset, l, n;
+
+ *data_return = NULL;
+
+ infos = attributes && (attributes->valuemask & XpmInfos);
+ extensions = attributes && (attributes->valuemask & XpmExtensions)
+ && attributes->nextensions;
+
+ /* compute the number of extensions lines and size */
+ if (extensions)
+ CountExtensions(attributes->extensions, attributes->nextensions,
+ &ext_size, &ext_nlines);
+
+ /*
+ * alloc a temporary array of char pointer for the header section which
+ * is the hints line + the color table lines
+ */
+ header_nlines = 1 + attrib->ncolors;
+ header_size = sizeof(char *) * header_nlines;
+ header = (char **) calloc(header_size, sizeof(char *));
+ if (!header)
+ RETURN(XpmNoMemory);
+
+ /*
+ * print the hints line
+ */
+ s = buf;
+ sprintf(s, "%d %d %d %d", attrib->width, attrib->height,
+ attrib->ncolors, attrib->cpp);
+ s += strlen(s);
+
+ if (attributes && (attributes->valuemask & XpmHotspot)) {
+ sprintf(s, " %d %d", attributes->x_hotspot, attributes->y_hotspot);
+ s += strlen(s);
+ }
+
+ if (extensions)
+ sprintf(s, " XPMEXT");
+
+ l = strlen(buf) + 1;
+ *header = (char *) malloc(l);
+ if (!*header)
+ RETURN(XpmNoMemory);
+ header_size += l;
+ strcpy(*header, buf);
+
+ /*
+ * print colors
+ */
+
+ /* transparent color */
+ if (attrib->mask_pixel != UNDEF_PIXEL) {
+ ErrorStatus =
+ CreateTransparentColor(header + 1, &header_size,
+ attrib->colorStrings, attrib->cpp,
+ (infos ? attributes->mask_pixel : 0),
+ (infos ? attributes->colorTable : NULL));
+ if (ErrorStatus != XpmSuccess)
+ RETURN(ErrorStatus);
+
+ offset = 1;
+ } else
+ offset = 0;
+
+ /* other colors */
+ ErrorStatus =
+ CreateOtherColors(header + 1 + offset, &header_size,
+ attrib->colorStrings + offset,
+ attrib->xcolors + offset, attrib->ncolors - offset,
+ attrib->cpp, (infos ? attributes->mask_pixel : 0),
+ (infos ? attributes->colorTable : NULL),
+ (infos ? attributes->ncolors : 0),
+ (infos ? attributes->pixels : NULL),
+ (attributes &&
+ (attributes->valuemask & XpmRgbFilename) ?
+ attributes->rgb_fname : NULL));
+ if (ErrorStatus != XpmSuccess)
+ RETURN(ErrorStatus);
+
+ /*
+ * now we know the size needed, alloc the data and copy the header lines
+ */
+ offset = attrib->width * attrib->cpp + 1;
+ data_size = header_size + (attrib->height + ext_nlines) * sizeof(char *)
+ + attrib->height * offset + ext_size;
+
+ data = (char **) malloc(data_size);
+ if (!data)
+ RETURN(XpmNoMemory);
+
+ data_nlines = header_nlines + attrib->height + ext_nlines;
+ *data = (char *) (data + data_nlines);
+ n = attrib->ncolors;
+ for (l = 0, sptr = data, sptr2 = header; l <= n; l++, sptr++, sptr2++) {
+ strcpy(*sptr, *sptr2);
+ *(sptr + 1) = *sptr + strlen(*sptr2) + 1;
+ }
+
+ /*
+ * print pixels
+ */
+ data[header_nlines] = (char *) data + header_size +
+ (attrib->height + ext_nlines) * sizeof(char *);
+
+ CreatePixels(data + header_nlines, attrib->width, attrib->height,
+ attrib->cpp, attrib->pixelindex, attrib->colorStrings);
+
+ /*
+ * print extensions
+ */
+ if (extensions)
+ CreateExtensions(data + header_nlines + attrib->height - 1, offset,
+ attributes->extensions, attributes->nextensions,
+ ext_nlines);
+
+ *data_return = data;
+
+ RETURN(XpmSuccess);
+}
+
+
+static int
+CreateTransparentColor(dataptr, data_size, colors, cpp, mask_pixel, colorTable)
+char **dataptr;
+unsigned int *data_size;
+char **colors;
+unsigned int cpp;
+unsigned int mask_pixel;
+char ***colorTable;
+{
+ char buf[BUFSIZ];
+ unsigned int key, l;
+ char *s, *s2;
+
+ strncpy(buf, *colors, cpp);
+ s = buf + cpp;
+
+ if (colorTable && mask_pixel != UNDEF_PIXEL) {
+ for (key = 1; key <= NKEYS; key++) {
+ if (s2 = colorTable[mask_pixel][key]) {
+ sprintf(s, "\t%s %s", xpmColorKeys[key - 1], s2);
+ s += strlen(s);
+ }
+ }
+ } else
+ sprintf(s, "\tc %s", TRANSPARENT_COLOR);
+
+ l = strlen(buf) + 1;
+ s = (char *) malloc(l);
+ if (!s)
+ return(XpmNoMemory);
+ *data_size += l;
+ strcpy(s, buf);
+ *dataptr = s;
+ return(XpmSuccess);
+}
+
+static int
+CreateOtherColors(dataptr, data_size, colors, xcolors, ncolors, cpp,
+ mask_pixel, colorTable, ncolors2, pixels, rgb_fname)
+char **dataptr;
+unsigned int *data_size;
+char **colors;
+XColor *xcolors;
+unsigned int ncolors;
+unsigned int cpp;
+unsigned int mask_pixel;
+char ***colorTable;
+unsigned int ncolors2;
+Pixel *pixels;
+char *rgb_fname;
+{
+ char buf[BUFSIZ];
+ unsigned int a, b, c, d, key, l;
+ char *s, *s2, *colorname;
+ xpmRgbName rgbn[MAX_RGBNAMES];
+ int rgbn_max = 0;
+
+ /* read the rgb file if any was specified */
+ if (rgb_fname)
+ rgbn_max = xpmReadRgbNames(rgb_fname, rgbn);
+
+ for (a = 0; a < ncolors; a++, colors++, xcolors++, dataptr++) {
+
+ strncpy(buf, *colors, cpp);
+ s = buf + cpp;
+
+ c = 1;
+ if (colorTable) {
+ d = 0;
+ for (b = 0; b < ncolors2; b++) {
+ if (b == mask_pixel) {
+ d = 1;
+ continue;
+ }
+ if (pixels[b - d] == xcolors->pixel)
+ break;
+ }
+ if (b != ncolors2) {
+ c = 0;
+ for (key = 1; key <= NKEYS; key++) {
+ if (s2 = colorTable[b][key]) {
+ sprintf(s, "\t%s %s", xpmColorKeys[key - 1], s2);
+ s += strlen(s);
+ }
+ }
+ }
+ }
+ if (c) {
+ colorname = NULL;
+ if (rgbn_max)
+ colorname = xpmGetRgbName(rgbn, rgbn_max, xcolors->red,
+ xcolors->green, xcolors->blue);
+ if (colorname)
+ sprintf(s, "\tc %s", colorname);
+ else
+ sprintf(s, "\tc #%04X%04X%04X",
+ xcolors->red, xcolors->green, xcolors->blue);
+ s += strlen(s);
+ }
+ l = strlen(buf) + 1;
+ s = (char *) malloc(l);
+ if (!s)
+ return(XpmNoMemory);
+ *data_size += l;
+ strcpy(s, buf);
+ *dataptr = s;
+ }
+ xpmFreeRgbNames(rgbn, rgbn_max);
+ return(XpmSuccess);
+}
+
+static void
+CreatePixels(dataptr, width, height, cpp, pixels, colors)
+char **dataptr;
+unsigned int width;
+unsigned int height;
+unsigned int cpp;
+unsigned int *pixels;
+char **colors;
+{
+ char *s;
+ unsigned int x, y, h, offset;
+
+ h = height - 1;
+ offset = width * cpp + 1;
+ for (y = 0; /* test is inside loop */ ; y++, dataptr++) {
+ s = *dataptr;
+ for (x = 0; x < width; x++, pixels++) {
+ strncpy(s, colors[*pixels], cpp);
+ s += cpp;
+ }
+ *s = '\0';
+ if (y >= h)
+ break; /* LEAVE LOOP */
+ *(dataptr + 1) = *dataptr + offset;
+ }
+}
+
+static void
+CountExtensions(ext, num, ext_size, ext_nlines)
+XpmExtension *ext;
+unsigned int num;
+unsigned int *ext_size;
+unsigned int *ext_nlines;
+{
+ unsigned int x, y, a, size, nlines;
+ char **lines;
+
+ size = 0;
+ nlines = 0;
+ for (x = 0; x < num; x++, ext++) {
+ /* "+ 2" is for the name and the ending 0 */
+ nlines += ext->nlines + 2;
+ /* 8 = 7 (for "XPMEXT ") + 1 (for 0) */
+ size += strlen(ext->name) + 8;
+ a = ext->nlines;
+ for (y = 0, lines = ext->lines; y < a; y++, lines++)
+ size += strlen(*lines) + 1;
+ }
+ *ext_size = size;
+ *ext_nlines = nlines;
+}
+
+static void
+CreateExtensions(dataptr, offset, ext, num, ext_nlines)
+char **dataptr;
+unsigned int offset;
+XpmExtension *ext;
+unsigned int num;
+unsigned int ext_nlines;
+{
+ unsigned int x, y, a, b;
+ char **sptr;
+
+ *(dataptr + 1) = *dataptr + offset;
+ dataptr++;
+ a = 0;
+ for (x = 0; x < num; x++, ext++) {
+ sprintf(*dataptr, "XPMEXT %s", ext->name);
+ a++;
+ if (a < ext_nlines)
+ *(dataptr + 1) = *dataptr + strlen(ext->name) + 8;
+ dataptr++;
+ b = ext->nlines;
+ for (y = 0, sptr = ext->lines; y < b; y++, sptr++) {
+ strcpy(*dataptr, *sptr);
+ a++;
+ if (a < ext_nlines)
+ *(dataptr + 1) = *dataptr + strlen(*sptr) + 1;
+ dataptr++;
+ }
+ }
+ *dataptr = 0;
+}
diff --git a/src/xpm/XpmCrDataFP.c b/src/xpm/XpmCrDataFP.c
new file mode 100644
index 0000000..fd2e5e6
--- /dev/null
+++ b/src/xpm/XpmCrDataFP.c
@@ -0,0 +1,75 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* XpmCrDataFP.c: *
+* *
+* XPM library *
+* Scan a pixmap and possibly its mask and create an XPM array *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+#include "xpmP.h"
+#ifdef VMS
+#include "sys$library:string.h"
+#else
+#if defined(SYSV) || defined(SVR4)
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#endif
+
+int
+XpmCreateDataFromPixmap(display, data_return, pixmap, shapemask, attributes)
+ Display *display;
+ char ***data_return;
+ Pixmap pixmap;
+ Pixmap shapemask;
+ XpmAttributes *attributes;
+{
+ XImage *image = NULL;
+ XImage *shapeimage = NULL;
+ unsigned int width = 0;
+ unsigned int height = 0;
+ int ErrorStatus;
+ unsigned int dum;
+ int dummy;
+ Window win;
+
+ /*
+ * get geometry
+ */
+ if (attributes && attributes->valuemask & XpmSize) {
+ width = attributes->width;
+ height = attributes->height;
+ } else {
+ if (pixmap)
+ XGetGeometry(display, pixmap, &win, &dummy, &dummy,
+ &width, &height, &dum, &dum);
+ else if (shapemask)
+ XGetGeometry(display, shapemask, &win, &dummy, &dummy,
+ &width, &height, &dum, &dum);
+ }
+
+ /*
+ * get the images
+ */
+ if (pixmap)
+ image = XGetImage(display, pixmap, 0, 0, width, height,
+ AllPlanes, ZPixmap);
+ if (shapemask)
+ shapeimage = XGetImage(display, shapemask, 0, 0, width, height,
+ AllPlanes, ZPixmap);
+
+ /*
+ * create data from images
+ */
+ ErrorStatus = XpmCreateDataFromImage(display, data_return, image,
+ shapeimage, attributes);
+ if (image)
+ XDestroyImage(image);
+ if (shapeimage)
+ XDestroyImage(shapeimage);
+
+ return (ErrorStatus);
+}
diff --git a/src/xpm/XpmCrIFData.c b/src/xpm/XpmCrIFData.c
new file mode 100644
index 0000000..259bf47
--- /dev/null
+++ b/src/xpm/XpmCrIFData.c
@@ -0,0 +1,52 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* XpmCrIFData.c: *
+* *
+* XPM library *
+* Parse an Xpm array and create the image and possibly its mask *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+#include "xpmP.h"
+
+int
+XpmCreateImageFromData(display, data, image_return,
+ shapeimage_return, attributes)
+ Display *display;
+ char **data;
+ XImage **image_return;
+ XImage **shapeimage_return;
+ XpmAttributes *attributes;
+{
+ xpmData mdata;
+ int ErrorStatus;
+ xpmInternAttrib attrib;
+
+ /*
+ * initialize return values
+ */
+ if (image_return)
+ *image_return = NULL;
+ if (shapeimage_return)
+ *shapeimage_return = NULL;
+
+ xpmOpenArray(data, &mdata);
+ xpmInitInternAttrib(&attrib);
+
+ ErrorStatus = xpmParseData(&mdata, &attrib, attributes);
+
+ if (ErrorStatus == XpmSuccess)
+ ErrorStatus = xpmCreateImage(display, &attrib, image_return,
+ shapeimage_return, attributes);
+
+ if (ErrorStatus >= 0)
+ xpmSetAttributes(&attrib, attributes);
+ else if (attributes)
+ XpmFreeAttributes(attributes);
+
+ xpmFreeInternAttrib(&attrib);
+ XpmDataClose(&mdata);
+
+ return (ErrorStatus);
+}
diff --git a/src/xpm/XpmCrPFData.c b/src/xpm/XpmCrPFData.c
new file mode 100644
index 0000000..dddb90e
--- /dev/null
+++ b/src/xpm/XpmCrPFData.c
@@ -0,0 +1,92 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* XpmCrPFData.c: *
+* *
+* XPM library *
+* Parse an Xpm array and create the pixmap and possibly its mask *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+#include "xpmP.h"
+
+int
+XpmCreatePixmapFromData(display, d, data, pixmap_return,
+ shapemask_return, attributes)
+ Display *display;
+ Drawable d;
+ char **data;
+ Pixmap *pixmap_return;
+ Pixmap *shapemask_return;
+ XpmAttributes *attributes;
+{
+ XImage *image, **imageptr = NULL;
+ XImage *shapeimage, **shapeimageptr = NULL;
+ int ErrorStatus;
+ XGCValues gcv;
+ GC gc;
+
+ /*
+ * initialize return values
+ */
+ if (pixmap_return) {
+ *pixmap_return = 0;
+ imageptr = &image;
+ }
+ if (shapemask_return) {
+ *shapemask_return = 0;
+ shapeimageptr = &shapeimage;
+ }
+
+ /*
+ * create the images
+ */
+ ErrorStatus = XpmCreateImageFromData(display, data, imageptr,
+ shapeimageptr, attributes);
+ if (ErrorStatus < 0)
+ return (ErrorStatus);
+
+ /*
+ * create the pixmaps
+ */
+ if (imageptr && image) {
+ *pixmap_return = XCreatePixmap(display, d, image->width,
+ image->height, image->depth);
+ gcv.function = GXcopy;
+ gc = XCreateGC(display, *pixmap_return, GCFunction, &gcv);
+
+ XPutImage(display, *pixmap_return, gc, image, 0, 0, 0, 0,
+ image->width, image->height);
+
+#ifdef Debug
+ /*
+ * XDestroyImage free the image data but mnemosyne don't know about it
+ * so I free them by hand to avoid mnemalyse report it as lost data.
+ */
+ free(image->data);
+#endif
+ XDestroyImage(image);
+ XFreeGC(display, gc);
+ }
+ if (shapeimageptr && shapeimage) {
+ *shapemask_return = XCreatePixmap(display, d, shapeimage->width,
+ shapeimage->height,
+ shapeimage->depth);
+ gcv.function = GXcopy;
+ gc = XCreateGC(display, *shapemask_return, GCFunction, &gcv);
+
+ XPutImage(display, *shapemask_return, gc, shapeimage, 0, 0, 0, 0,
+ shapeimage->width, shapeimage->height);
+
+#ifdef Debug
+ /*
+ * XDestroyImage free the image data but mnemosyne don't know about it
+ * so I free them by hand to avoid mnemalyse report it as lost data.
+ */
+ free(shapeimage->data);
+#endif
+ XDestroyImage(shapeimage);
+ XFreeGC(display, gc);
+ }
+ return (ErrorStatus);
+}
diff --git a/src/xpm/XpmRdFToData.c b/src/xpm/XpmRdFToData.c
new file mode 100644
index 0000000..5d68e73
--- /dev/null
+++ b/src/xpm/XpmRdFToData.c
@@ -0,0 +1,115 @@
+/* Copyright 1990,91 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* XpmRdFToData.c: *
+* *
+* XPM library *
+* Parse an XPM file and create an array of strings corresponding to it. *
+* *
+* Developed by Dan Greening dgreen@cs.ucla.edu / dgreen@sti.com *
+\*****************************************************************************/
+
+#include "xpmP.h"
+
+int
+XpmReadFileToData(filename, data_return)
+ char *filename;
+ char ***data_return;
+{
+ xpmData mdata;
+ char buf[BUFSIZ];
+ int l, n = 0;
+ XpmAttributes attributes;
+ xpmInternAttrib attrib;
+ int ErrorStatus;
+ XGCValues gcv;
+ GC gc;
+
+ attributes.valuemask = XpmReturnPixels|XpmReturnInfos|XpmReturnExtensions;
+ /*
+ * initialize return values
+ */
+ if (data_return) {
+ *data_return = NULL;
+ }
+
+ if ((ErrorStatus = xpmReadFile(filename, &mdata)) != XpmSuccess)
+ return (ErrorStatus);
+ xpmInitInternAttrib(&attrib);
+ /*
+ * parse the header file
+ */
+ mdata.Bos = '\0';
+ mdata.Eos = '\n';
+ mdata.Bcmt = mdata.Ecmt = NULL;
+ xpmNextWord(&mdata, buf); /* skip the first word */
+ l = xpmNextWord(&mdata, buf); /* then get the second word */
+ if ((l == 3 && !strncmp("XPM", buf, 3)) ||
+ (l == 4 && !strncmp("XPM2", buf, 4))) {
+ if (l == 3)
+ n = 1; /* handle XPM as XPM2 C */
+ else {
+ l = xpmNextWord(&mdata, buf); /* get the type key word */
+
+ /*
+ * get infos about this type
+ */
+ while (xpmDataTypes[n].type
+ && strncmp(xpmDataTypes[n].type, buf, l))
+ n++;
+ }
+ if (xpmDataTypes[n].type) {
+ if (n == 0) { /* natural type */
+ mdata.Bcmt = xpmDataTypes[n].Bcmt;
+ mdata.Ecmt = xpmDataTypes[n].Ecmt;
+ xpmNextString(&mdata); /* skip the end of headerline */
+ mdata.Bos = xpmDataTypes[n].Bos;
+ } else {
+ xpmNextString(&mdata); /* skip the end of headerline */
+ mdata.Bcmt = xpmDataTypes[n].Bcmt;
+ mdata.Ecmt = xpmDataTypes[n].Ecmt;
+ mdata.Bos = xpmDataTypes[n].Bos;
+ mdata.Eos = '\0';
+ xpmNextString(&mdata); /* skip the assignment line */
+ }
+ mdata.Eos = xpmDataTypes[n].Eos;
+
+ ErrorStatus = xpmParseData(&mdata, &attrib, &attributes);
+ } else
+ ErrorStatus = XpmFileInvalid;
+ } else
+ ErrorStatus = XpmFileInvalid;
+
+ if (ErrorStatus == XpmSuccess) {
+ int i;
+
+ /* maximum of allocated pixels will be the number of colors */
+ attributes.pixels = (Pixel *) malloc(sizeof(Pixel) * attrib.ncolors);
+ attrib.xcolors = (XColor*) malloc(sizeof(XColor) * attrib.ncolors);
+
+ if (!attributes.pixels || !attrib.xcolors)
+ ErrorStatus = XpmNoMemory;
+ else {
+ for (i = 0; i < attrib.ncolors; i++) {
+ /* Fake colors */
+ attrib.xcolors[i].pixel = attributes.pixels[i] = i + 1;
+ }
+ xpmSetAttributes(&attrib, &attributes);
+ if (!(attrib.colorStrings =
+ (char**) malloc(attributes.ncolors * sizeof(char*))))
+ ErrorStatus = XpmNoMemory;
+ else {
+ attrib.ncolors = attributes.ncolors;
+ attributes.mask_pixel = attrib.mask_pixel;
+ for (i = 0; i < attributes.ncolors; i++)
+ attrib.colorStrings[i] = attributes.colorTable[i][0];
+ }
+ }
+ }
+ if (ErrorStatus == XpmSuccess)
+ ErrorStatus = xpmCreateData(data_return, &attrib, &attributes);
+ XpmFreeAttributes(&attributes);
+ xpmFreeInternAttrib(&attrib);
+ XpmDataClose(&mdata);
+
+ return (ErrorStatus);
+}
diff --git a/src/xpm/XpmRdFToI.c b/src/xpm/XpmRdFToI.c
new file mode 100644
index 0000000..af68f69
--- /dev/null
+++ b/src/xpm/XpmRdFToI.c
@@ -0,0 +1,110 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* XpmRdFToI.c: *
+* *
+* XPM library *
+* Parse an XPM file and create the image and possibly its mask *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+#include "xpmP.h"
+
+xpmDataType xpmDataTypes[] =
+{
+ "", "!", "\n", '\0', '\n', "", "", "", "", /* Natural type */
+ "C", "/*", "*/", '"', '"', ",\n", "static char *", "[] = {\n", "};\n",
+ "Lisp", ";", "\n", '"', '"', "\n", "(setq ", " '(\n", "))\n",
+#ifdef VMS
+ NULL
+#else
+ NULL, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL
+#endif
+};
+
+int
+XpmReadFileToImage(display, filename, image_return,
+ shapeimage_return, attributes)
+ Display *display;
+ char *filename;
+ XImage **image_return;
+ XImage **shapeimage_return;
+ XpmAttributes *attributes;
+{
+ xpmData mdata;
+ char buf[BUFSIZ];
+ int l, n = 0;
+ int ErrorStatus;
+ xpmInternAttrib attrib;
+
+ /*
+ * initialize return values
+ */
+ if (image_return)
+ *image_return = NULL;
+ if (shapeimage_return)
+ *shapeimage_return = NULL;
+
+ if ((ErrorStatus = xpmReadFile(filename, &mdata)) != XpmSuccess)
+ return (ErrorStatus);
+
+ xpmInitInternAttrib(&attrib);
+
+ /*
+ * parse the header file
+ */
+ mdata.Bos = '\0';
+ mdata.Eos = '\n';
+ mdata.Bcmt = mdata.Ecmt = NULL;
+ xpmNextWord(&mdata, buf); /* skip the first word */
+ l = xpmNextWord(&mdata, buf); /* then get the second word */
+ if ((l == 3 && !strncmp("XPM", buf, 3)) ||
+ (l == 4 && !strncmp("XPM2", buf, 4))) {
+ if (l == 3)
+ n = 1; /* handle XPM as XPM2 C */
+ else {
+ l = xpmNextWord(&mdata, buf); /* get the type key word */
+
+ /*
+ * get infos about this type
+ */
+ while (xpmDataTypes[n].type
+ && strncmp(xpmDataTypes[n].type, buf, l))
+ n++;
+ }
+ if (xpmDataTypes[n].type) {
+ if (n == 0) { /* natural type */
+ mdata.Bcmt = xpmDataTypes[n].Bcmt;
+ mdata.Ecmt = xpmDataTypes[n].Ecmt;
+ xpmNextString(&mdata); /* skip the end of headerline */
+ mdata.Bos = xpmDataTypes[n].Bos;
+ } else {
+ xpmNextString(&mdata); /* skip the end of headerline */
+ mdata.Bcmt = xpmDataTypes[n].Bcmt;
+ mdata.Ecmt = xpmDataTypes[n].Ecmt;
+ mdata.Bos = xpmDataTypes[n].Bos;
+ mdata.Eos = '\0';
+ xpmNextString(&mdata); /* skip the assignment line */
+ }
+ mdata.Eos = xpmDataTypes[n].Eos;
+
+ ErrorStatus = xpmParseData(&mdata, &attrib, attributes);
+
+ if (ErrorStatus == XpmSuccess)
+ ErrorStatus = xpmCreateImage(display, &attrib, image_return,
+ shapeimage_return, attributes);
+ } else
+ ErrorStatus = XpmFileInvalid;
+ } else
+ ErrorStatus = XpmFileInvalid;
+
+ if (ErrorStatus >= 0)
+ xpmSetAttributes(&attrib, attributes);
+ else if (attributes)
+ XpmFreeAttributes(attributes);
+
+ xpmFreeInternAttrib(&attrib);
+ XpmDataClose(&mdata);
+
+ return (ErrorStatus);
+}
diff --git a/src/xpm/XpmRdFToP.c b/src/xpm/XpmRdFToP.c
new file mode 100644
index 0000000..51732b5
--- /dev/null
+++ b/src/xpm/XpmRdFToP.c
@@ -0,0 +1,92 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* XpmRdFToP.c: *
+* *
+* XPM library *
+* Parse an XPM file and create the pixmap and possibly its mask *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+#include "xpmP.h"
+
+int
+XpmReadFileToPixmap(display, d, filename, pixmap_return,
+ shapemask_return, attributes)
+ Display *display;
+ Drawable d;
+ char *filename;
+ Pixmap *pixmap_return;
+ Pixmap *shapemask_return;
+ XpmAttributes *attributes;
+{
+ XImage *image, **imageptr = NULL;
+ XImage *shapeimage, **shapeimageptr = NULL;
+ int ErrorStatus;
+ XGCValues gcv;
+ GC gc;
+
+ /*
+ * initialize return values
+ */
+ if (pixmap_return) {
+ *pixmap_return = 0;
+ imageptr = &image;
+ }
+ if (shapemask_return) {
+ *shapemask_return = 0;
+ shapeimageptr = &shapeimage;
+ }
+
+ /*
+ * create the images
+ */
+ ErrorStatus = XpmReadFileToImage(display, filename, imageptr,
+ shapeimageptr, attributes);
+ if (ErrorStatus < 0)
+ return (ErrorStatus);
+
+ /*
+ * create the pixmaps
+ */
+ if (imageptr && image) {
+ *pixmap_return = XCreatePixmap(display, d, image->width,
+ image->height, image->depth);
+ gcv.function = GXcopy;
+ gc = XCreateGC(display, *pixmap_return, GCFunction, &gcv);
+
+ XPutImage(display, *pixmap_return, gc, image, 0, 0, 0, 0,
+ image->width, image->height);
+
+#ifdef Debug
+ /*
+ * XDestroyImage free the image data but mnemosyne don't know about it
+ * so I free them by hand to avoid mnemalyse report it as lost data.
+ */
+ free(image->data);
+#endif
+ XDestroyImage(image);
+ XFreeGC(display, gc);
+ }
+ if (shapeimageptr && shapeimage) {
+ *shapemask_return = XCreatePixmap(display, d, shapeimage->width,
+ shapeimage->height,
+ shapeimage->depth);
+ gcv.function = GXcopy;
+ gc = XCreateGC(display, *shapemask_return, GCFunction, &gcv);
+
+ XPutImage(display, *shapemask_return, gc, shapeimage, 0, 0, 0, 0,
+ shapeimage->width, shapeimage->height);
+
+#ifdef Debug
+ /*
+ * XDestroyImage free the image data but mnemosyne don't know about it
+ * so I free them by hand to avoid mnemalyse report it as lost data.
+ */
+ free(shapeimage->data);
+#endif
+ XDestroyImage(shapeimage);
+ XFreeGC(display, gc);
+ }
+ return (ErrorStatus);
+}
diff --git a/src/xpm/XpmWrFFrData.c b/src/xpm/XpmWrFFrData.c
new file mode 100644
index 0000000..3d567ec
--- /dev/null
+++ b/src/xpm/XpmWrFFrData.c
@@ -0,0 +1,113 @@
+/* Copyright 1990,91 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* XpmWrFFrData.c: *
+* *
+* XPM library *
+* Parse an Xpm array and write a file that corresponds to it. *
+* *
+* Developed by Dan Greening dgreen@cs.ucla.edu / dgreen@sti.com *
+\*****************************************************************************/
+
+#include "xpmP.h"
+#ifdef VMS
+#include "sys$library:string.h"
+#else
+#ifdef SYSV
+#include <string.h>
+#define index strchr
+#define rindex strrchr
+#else
+#include <strings.h>
+#endif
+#endif
+
+int
+XpmWriteFileFromData(filename, data)
+ char *filename;
+ char **data;
+{
+ xpmData mdata, mfile;
+ char *name, *dot, *s, *new_name = NULL;
+ int ErrorStatus;
+ XpmAttributes attributes;
+ xpmInternAttrib attrib;
+ int i;
+
+ attributes.valuemask = XpmReturnPixels|XpmReturnInfos|XpmReturnExtensions;
+ if ((ErrorStatus = xpmWriteFile(filename, &mfile)) != XpmSuccess)
+ return (ErrorStatus);
+
+ if (filename) {
+#ifdef VMS
+ name = filename;
+#else
+ if (!(name = rindex(filename, '/')))
+ name = filename;
+ else
+ name++;
+#endif
+ if (dot = index(name, '.')) {
+ new_name = (char*)strdup(name);
+ if (!new_name) {
+ new_name = NULL;
+ name = "image_name";
+ } else {
+ /* change '.' to '_' to get a valid C syntax name */
+ name = s = new_name;
+ while (dot = index(s, '.')) {
+ *dot = '_';
+ s = dot;
+ }
+ }
+ }
+ } else
+ name = "image_name";
+
+ xpmInitInternAttrib(&attrib);
+
+ /*
+ * Parse data then write it out
+ */
+
+ xpmOpenArray(data, &mdata);
+
+ ErrorStatus = xpmParseData(&mdata, &attrib, &attributes);
+ if (ErrorStatus == XpmSuccess) {
+ attributes.mask_pixel = UNDEF_PIXEL;
+
+ /* maximum of allocated pixels will be the number of colors */
+ attributes.pixels = (Pixel *) malloc(sizeof(Pixel) * attrib.ncolors);
+ attrib.xcolors = (XColor*) malloc(sizeof(XColor) * attrib.ncolors);
+
+ if (!attributes.pixels || !attrib.xcolors)
+ ErrorStatus == XpmNoMemory;
+ else {
+ int i;
+
+ for (i = 0; i < attrib.ncolors; i++) {
+ /* Fake colors */
+ attrib.xcolors[i].pixel = attributes.pixels[i] = i + 1;
+ }
+ xpmSetAttributes(&attrib, &attributes);
+ if (!(attrib.colorStrings =
+ (char**) malloc(attributes.ncolors * sizeof(char*))))
+ ErrorStatus == XpmNoMemory;
+ else {
+ attrib.ncolors = attributes.ncolors;
+ for (i = 0; i < attributes.ncolors; i++)
+ attrib.colorStrings[i] = attributes.colorTable[i][0];
+
+ attrib.name = name;
+ ErrorStatus = xpmWriteData(&mfile, &attrib, &attributes);
+ }
+ }
+ }
+ if (new_name)
+ free(name);
+ XpmFreeAttributes(&attributes);
+ xpmFreeInternAttrib(&attrib);
+ XpmDataClose(&mfile);
+ XpmDataClose(&mdata);
+
+ return (ErrorStatus);
+}
diff --git a/src/xpm/XpmWrFFrI.c b/src/xpm/XpmWrFFrI.c
new file mode 100644
index 0000000..5b3706c
--- /dev/null
+++ b/src/xpm/XpmWrFFrI.c
@@ -0,0 +1,341 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* XpmWrFFrI.c: *
+* *
+* XPM library *
+* Write an image and possibly its mask to an XPM file *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+#include "xpmP.h"
+#ifdef VMS
+#include "sys$library:string.h"
+#else
+#if defined(SYSV) || defined(SVR4)
+#include <string.h>
+#define index strchr
+#define rindex strrchr
+#else
+#include <strings.h>
+#endif
+#endif
+
+LFUNC(WriteTransparentColor, void, (FILE *file, char **colors,
+ unsigned int cpp, unsigned int mask_pixel,
+ char ***colorTable));
+
+LFUNC(WriteOtherColors, void, (FILE *file, char **colors, XColor *xcolors,
+ unsigned int ncolors, unsigned int cpp,
+ unsigned int mask_pixel, char ***colorTable,
+ unsigned int ncolors2, Pixel *pixels,
+ char *rgb_fname));
+
+LFUNC(WritePixels, int, (FILE *file, unsigned int width, unsigned int height,
+ unsigned int cpp, unsigned int *pixels,
+ char **colors));
+
+LFUNC(WriteExtensions, void, (FILE *file, XpmExtension *ext,
+ unsigned int num));
+
+int
+XpmWriteFileFromImage(display, filename, image, shapeimage, attributes)
+ Display *display;
+ char *filename;
+ XImage *image;
+ XImage *shapeimage;
+ XpmAttributes *attributes;
+{
+ xpmData mdata;
+ char *name, *dot, *s, *new_name = NULL;
+ int ErrorStatus;
+ xpmInternAttrib attrib;
+
+ if ((ErrorStatus = xpmWriteFile(filename, &mdata)) != XpmSuccess)
+ return (ErrorStatus);
+
+ if (filename) {
+#ifdef VMS
+ name = filename;
+#else
+ if (!(name = rindex(filename, '/')))
+ name = filename;
+ else
+ name++;
+#endif
+ if (dot = index(name, '.')) {
+ new_name = (char*)strdup(name);
+ if (!new_name) {
+ new_name = NULL;
+ name = "image_name";
+ } else {
+ /* change '.' to '_' to get a valid C syntax name */
+ name = s = new_name;
+ while (dot = index(s, '.')) {
+ *dot = '_';
+ s = dot;
+ }
+ }
+ }
+ } else
+ name = "image_name";
+
+ xpmInitInternAttrib(&attrib);
+
+ /*
+ * Scan image then write it out
+ */
+ ErrorStatus = xpmScanImage(display, image, shapeimage,
+ attributes, &attrib);
+
+ if (ErrorStatus == XpmSuccess) {
+ attrib.name = name;
+ ErrorStatus = xpmWriteData(&mdata, &attrib, attributes);
+ }
+ xpmFreeInternAttrib(&attrib);
+ XpmDataClose(&mdata);
+ if (new_name)
+ free(name);
+
+ return (ErrorStatus);
+}
+
+
+int
+xpmWriteData(mdata, attrib, attributes)
+ xpmData *mdata;
+ xpmInternAttrib *attrib;
+ XpmAttributes *attributes;
+{
+ /* calculation variables */
+ unsigned int offset, infos;
+ FILE *file;
+ int ErrorStatus;
+
+ /* store this to speed up */
+ file = mdata->stream.file;
+
+ infos = attributes && (attributes->valuemask & XpmInfos);
+
+ /*
+ * print the header line
+ */
+ fprintf(file, "/* XPM */\nstatic char * %s[] = {\n", attrib->name);
+
+ /*
+ * print the hints line
+ */
+ if (infos && attributes->hints_cmt)
+ fprintf(file, "/*%s*/\n", attributes->hints_cmt);
+
+ fprintf(file, "\"%d %d %d %d", attrib->width, attrib->height,
+ attrib->ncolors, attrib->cpp);
+
+ if (attributes && (attributes->valuemask & XpmHotspot))
+ fprintf(file, " %d %d", attributes->x_hotspot, attributes->y_hotspot);
+
+ if (attributes && (attributes->valuemask & XpmExtensions)
+ && attributes->nextensions)
+ fprintf(file, " XPMEXT");
+
+ fprintf(file, "\",\n");
+
+ /*
+ * print colors
+ */
+ if (infos && attributes->colors_cmt)
+ fprintf(file, "/*%s*/\n", attributes->colors_cmt);
+
+ /* transparent color */
+ if (attrib->mask_pixel != UNDEF_PIXEL) {
+ WriteTransparentColor(file, attrib->colorStrings, attrib->cpp,
+ (infos ? attributes->mask_pixel : 0),
+ (infos ? attributes->colorTable : NULL));
+ offset = 1;
+ } else
+ offset = 0;
+
+ /* other colors */
+ WriteOtherColors(file, attrib->colorStrings + offset,
+ attrib->xcolors + offset, attrib->ncolors - offset,
+ attrib->cpp, (infos ? attributes->mask_pixel : 0),
+ (infos ? attributes->colorTable : NULL),
+ (infos ? attributes->ncolors : 0),
+ (infos ? attributes->pixels : NULL),
+ (attributes && (attributes->valuemask & XpmRgbFilename) ?
+ attributes->rgb_fname : NULL));
+
+ /*
+ * print pixels
+ */
+ if (infos && attributes->pixels_cmt)
+ fprintf(file, "/*%s*/\n", attributes->pixels_cmt);
+
+ ErrorStatus = WritePixels(file, attrib->width, attrib->height, attrib->cpp,
+ attrib->pixelindex, attrib->colorStrings);
+ if (ErrorStatus != XpmSuccess)
+ return(ErrorStatus);
+
+ /*
+ * print extensions
+ */
+ if (attributes && (attributes->valuemask & XpmExtensions)
+ && attributes->nextensions)
+ WriteExtensions(file, attributes->extensions, attributes->nextensions);
+
+ /* close the array */
+ fprintf(file, "};\n");
+
+ return (XpmSuccess);
+}
+
+static void
+WriteTransparentColor(file, colors, cpp, mask_pixel, colorTable)
+FILE *file;
+char **colors;
+unsigned int cpp;
+unsigned int mask_pixel;
+char ***colorTable;
+{
+ unsigned int key, i;
+ char *s;
+
+ putc('"', file);
+ for (i = 0, s = *colors; i < cpp; i++, s++)
+ putc(*s, file);
+
+ if (colorTable && mask_pixel != UNDEF_PIXEL) {
+ for (key = 1; key <= NKEYS; key++) {
+ if (s = colorTable[mask_pixel][key])
+ fprintf(file, "\t%s %s", xpmColorKeys[key - 1], s);
+ }
+ } else
+ fprintf(file, "\tc %s", TRANSPARENT_COLOR);
+
+ fprintf(file, "\",\n");
+}
+
+static void
+WriteOtherColors(file, colors, xcolors, ncolors, cpp, mask_pixel, colorTable,
+ ncolors2, pixels, rgb_fname)
+FILE *file;
+char **colors;
+XColor *xcolors;
+unsigned int ncolors;
+unsigned int cpp;
+unsigned int mask_pixel;
+char ***colorTable;
+unsigned int ncolors2;
+Pixel *pixels;
+char *rgb_fname;
+{
+ unsigned int a, b, c, d, key;
+ char *s, *colorname;
+ xpmRgbName rgbn[MAX_RGBNAMES];
+ int rgbn_max = 0;
+
+ /* read the rgb file if any was specified */
+ if (rgb_fname)
+ rgbn_max = xpmReadRgbNames(rgb_fname, rgbn);
+
+ for (a = 0; a < ncolors; a++, colors++, xcolors++) {
+
+ putc('"', file);
+ for (b = 0, s = *colors; b < cpp; b++, s++)
+ putc(*s, file);
+
+ c = 1;
+ if (colorTable) {
+ d = 0;
+ for (b = 0; b < ncolors2; b++) {
+ if (b == mask_pixel) {
+ d = 1;
+ continue;
+ }
+ if (pixels[b - d] == xcolors->pixel)
+ break;
+ }
+ if (b != ncolors2) {
+ c = 0;
+ for (key = 1; key <= NKEYS; key++) {
+ if (s = colorTable[b][key])
+ fprintf(file, "\t%s %s", xpmColorKeys[key - 1], s);
+ }
+ }
+ }
+ if (c) {
+ colorname = NULL;
+ if (rgbn_max)
+ colorname = xpmGetRgbName(rgbn, rgbn_max, xcolors->red,
+ xcolors->green, xcolors->blue);
+ if (colorname)
+ fprintf(file, "\tc %s", colorname);
+ else
+ fprintf(file, "\tc #%04X%04X%04X", xcolors->red,
+ xcolors->green, xcolors->blue);
+ }
+ fprintf(file, "\",\n");
+ }
+ xpmFreeRgbNames(rgbn, rgbn_max);
+}
+
+
+static int
+WritePixels(file, width, height, cpp, pixels, colors)
+FILE *file;
+unsigned int width;
+unsigned int height;
+unsigned int cpp;
+unsigned int *pixels;
+char **colors;
+{
+ char *s, *p, *buf;
+ unsigned int x, y, h;
+
+ h = height - 1;
+ p = buf = (char *) malloc(width * cpp + 3);
+ *buf = '"';
+ if (!buf)
+ return(XpmNoMemory);
+ p++;
+ for (y = 0; y < h; y++) {
+ s = p;
+ for (x = 0; x < width; x++, pixels++) {
+ strncpy(s, colors[*pixels], cpp);
+ s += cpp;
+ }
+ *s++ = '"';
+ *s = '\0';
+ fprintf(file, "%s,\n", buf);
+ }
+ /* duplicate some code to avoid a test in the loop */
+ s = p;
+ for (x = 0; x < width; x++, pixels++) {
+ strncpy(s, colors[*pixels], cpp);
+ s += cpp;
+ }
+ *s++ = '"';
+ *s = '\0';
+ fprintf(file, "%s", buf);
+
+ free(buf);
+ return(XpmSuccess);
+}
+
+static void
+WriteExtensions(file, ext, num)
+FILE *file;
+XpmExtension *ext;
+unsigned int num;
+{
+ unsigned int x, y, n;
+ char **line;
+
+ for (x = 0; x < num; x++, ext++) {
+ fprintf(file, ",\n\"XPMEXT %s\"", ext->name);
+ n = ext->nlines;
+ for (y = 0, line = ext->lines; y < n; y++, line++)
+ fprintf(file, ",\n\"%s\"", *line);
+ }
+ fprintf(file, ",\n\"XPMENDEXT\"");
+}
diff --git a/src/xpm/XpmWrFFrP.c b/src/xpm/XpmWrFFrP.c
new file mode 100644
index 0000000..52eef29
--- /dev/null
+++ b/src/xpm/XpmWrFFrP.c
@@ -0,0 +1,75 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* XpmWrFFrP.c: *
+* *
+* XPM library *
+* Write a pixmap and possibly its mask to an XPM file *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+#include "xpmP.h"
+#ifdef VMS
+#include "sys$library:string.h"
+#else
+#if defined(SYSV) || defined(SVR4)
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#endif
+
+int
+XpmWriteFileFromPixmap(display, filename, pixmap, shapemask, attributes)
+ Display *display;
+ char *filename;
+ Pixmap pixmap;
+ Pixmap shapemask;
+ XpmAttributes *attributes;
+{
+ XImage *image = NULL;
+ XImage *shapeimage = NULL;
+ unsigned int width = 0;
+ unsigned int height = 0;
+ int ErrorStatus;
+ unsigned int dum;
+ int dummy;
+ Window win;
+
+ /*
+ * get geometry
+ */
+ if (attributes && attributes->valuemask & XpmSize) {
+ width = attributes->width;
+ height = attributes->height;
+ } else {
+ if (pixmap)
+ XGetGeometry(display, pixmap, &win, &dummy, &dummy,
+ &width, &height, &dum, &dum);
+ else if (shapemask)
+ XGetGeometry(display, shapemask, &win, &dummy, &dummy,
+ &width, &height, &dum, &dum);
+ }
+
+ /*
+ * get the images
+ */
+ if (pixmap)
+ image = XGetImage(display, pixmap, 0, 0, width, height,
+ AllPlanes, ZPixmap);
+ if (shapemask)
+ shapeimage = XGetImage(display, shapemask, 0, 0, width, height,
+ AllPlanes, ZPixmap);
+
+ /*
+ * write them out
+ */
+ ErrorStatus = XpmWriteFileFromImage(display, filename, image, shapeimage,
+ attributes);
+ if (image)
+ XDestroyImage(image);
+ if (shapeimage)
+ XDestroyImage(shapeimage);
+
+ return (ErrorStatus);
+}
diff --git a/src/xpm/converters/ppm.README b/src/xpm/converters/ppm.README
new file mode 100644
index 0000000..b5e254f
--- /dev/null
+++ b/src/xpm/converters/ppm.README
@@ -0,0 +1,69 @@
+PPM Stuff
+Convert portable pixmap to X11 Pixmap format (version 3) and vice versa
+-----------------------------------------------------------------------
+
+The program ppmtoxpm is a modified version of one sent out by Mark Snitily
+(mark@zok.uucp) and upgraded to XPM version 2 by Paul Breslaw
+(paul@mecazh.uu.ch).
+
+It converts Jeff Poskanzer's (jef@well.sf.ca.us) portable pixmap format
+(PBMPlus) into the new X11 pixmap format: XPM version 3 distributed by Arnaud
+Le Hors (lehors@mirsa.inria.fr).
+
+It is built using the PBMPlus libraries in the same way as any of the
+ppm utilities in the PBMPlus package.
+
+Paul Breslaw - Thu Nov 22 09:55:31 MET 1990
+--
+Paul Breslaw, Mecasoft SA, | telephone : 41 1 362 2040
+Guggachstrasse 10, CH-8057 Zurich, | e-mail : paul@mecazh.uu.ch
+Switzerland. | mcsun!chx400!mecazh!paul
+--
+
+The program xpmtoppm is a modified version of the one distributed in the
+PBMPlus package by Jeff Poskanzer's which converts XPM version 1 or 3 files
+into a portable pixmap format.
+
+Upgraded to XPM version 3 by
+ Arnaud LE HORS BULL Research France -- Koala Project
+ lehors@sa.inria.fr Phone:(33) 93 65 77 71 Fax:(33) 93 65 77 66
+ Inria Sophia Antipolis B.P.109 06561 Valbonne Cedex France
+
+
+Installation
+-----------
+You should copy The ppmtoxpm.c, ppmtoxpm.1 and xpmtoppm.c, xpmtoppm.1 into
+your .../pbmplus/ppm directory.
+
+
+Patches
+-------
+* Rainer Sinkwitz sinkwitz@ifi.unizh.ch - 21 Nov 91:
+
+xpmtoppm.c:
+ - Bug fix, no advance of read ptr, would not read
+ colors like "ac c black" because it would find
+ the "c" of "ac" and then had problems with "c"
+ as color.
+
+ - Now understands multword X11 color names
+
+ - Now reads multiple color keys. Takes the color
+ of the hightest available key. Lines no longer need
+ to begin with key 'c'.
+
+ - expanded line buffer to from 500 to 2048 for bigger files
+
+ppmtoxpm.c:
+ - Bug fix, should should malloc space for rgbn[j].name+1 in line 441
+ caused segmentation faults
+
+ - lowercase conversion of RGB names def'ed out,
+ considered harmful.
+
+Suggestions:
+ ppmtoxpm should read /usr/lib/X11/rgb.txt by default.
+ With the Imakefiles of pbmplus it even gets compiled
+ with -DRGB_DB=\"/usr/lib/X11/rgb.txt\"
+
+
diff --git a/src/xpm/converters/ppmtoxpm.1 b/src/xpm/converters/ppmtoxpm.1
new file mode 100644
index 0000000..2b35fa6
--- /dev/null
+++ b/src/xpm/converters/ppmtoxpm.1
@@ -0,0 +1,69 @@
+.TH ppmtoxpm 1 "Tue Apr 9 1991"
+.SH NAME
+ppmtoxpm - convert a portable pixmap into an X11 pixmap
+.SH SYNOPSIS
+ppmtoxpm [-name <xpmname>] [-rgb <rgb-textfile>] [<ppmfile>]
+.SH DESCRIPTION
+Reads a portable pixmap as input.
+Produces X11 pixmap (version 3) as output which
+can be loaded directly by the XPM library.
+.PP
+The \fB-name\f option allows one to specify the prefix string which is printed
+in the resulting XPM output. If not specified, will default to the
+filename (without extension) of the <ppmfile> argument.
+If \fB-name\f is not specified and <ppmfile>
+is not specified (i.e. piped input), the prefix string will default to
+the string "noname".
+.PP
+The \fB-rgb\f option allows one to specify an X11 rgb text file for the
+lookup of color name mnemonics. This rgb text file is typically the
+/usr/lib/X11/rgb.txt of the MIT X11 distribution, but any file using the
+same format may be used. When specified and
+a RGB value from the ppm input matches a RGB value from the <rgb-textfile>,
+then the corresponding color name mnemonic is printed in the XPM's colormap.
+If \fB-rgb\f is not specified, or if the RGB values don't match, then the color
+will be printed with the #RGB, #RRGGBB, #RRRGGGBBB, or #RRRRGGGGBBBB
+hexadecimal format.
+.PP
+All flags can be abbreviated to their shortest unique prefix.
+.PP
+For example, to convert the file "dot" (found in /usr/include/X11/bitmaps),
+from xbm to xpm one could specify
+.IP
+xbmtopbm dot | ppmtoxpm -name dot
+.PP
+or, with a rgb text file (in the local directory)
+.IP
+xbmtopbm dot | ppmtoxpm -name dot -rgb rgb.txt
+.SH BUGS
+An option to match the closest (rather than exact) color name mnemonic
+from the rgb text would be a desirable enhancement.
+.PP
+Truncation of the least significant bits of a RGB value may result in
+nonexact matches when performing color name mnemonic lookups.
+.SH "SEE ALSO"
+ppm(5)
+.br
+XPM Manual by Arnaud Le Hors lehors@mirsa.inria.fr
+.SH AUTHOR
+Copyright (C) 1990 by Mark W. Snitily.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted, provided
+that the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation. This software is provided "as is" without express or
+implied warranty.
+
+This tool was developed for Schlumberger Technologies, ATE Division, and
+with their permission is being made available to the public with the above
+copyright notice and permission notice.
+
+Upgraded to XPM2 by
+ Paul Breslaw, Mecasoft SA, Zurich, Switzerland (paul@mecazh.uu.ch)
+ Thu Nov 8 16:01:17 1990
+
+Upgraded to XPM version 3 by
+ Arnaud Le Hors (lehors@mirsa.inria.fr)
+ Tue Apr 9 1991
+
diff --git a/src/xpm/converters/ppmtoxpm.c b/src/xpm/converters/ppmtoxpm.c
new file mode 100644
index 0000000..395b4a8
--- /dev/null
+++ b/src/xpm/converters/ppmtoxpm.c
@@ -0,0 +1,481 @@
+/* ppmtoxpm.c - read a portable pixmap and produce a (version 3) X11 pixmap
+**
+** Copyright (C) 1990 by Mark W. Snitily
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+**
+** This tool was developed for Schlumberger Technologies, ATE Division, and
+** with their permission is being made available to the public with the above
+** copyright notice and permission notice.
+**
+** Upgraded to XPM2 by
+** Paul Breslaw, Mecasoft SA, Zurich, Switzerland (paul@mecazh.uu.ch)
+** Thu Nov 8 16:01:17 1990
+**
+** Upgraded to XPM version 3 by
+** Arnaud Le Hors (lehors@mirsa.inria.fr)
+** Tue Apr 9 1991
+**
+** Rainer Sinkwitz sinkwitz@ifi.unizh.ch - 21 Nov 91:
+** - Bug fix, should should malloc space for rgbn[j].name+1 in line 441
+** caused segmentation faults
+**
+** - lowercase conversion of RGB names def'ed out,
+** considered harmful.
+*/
+
+#include <stdio.h>
+#include <ctype.h>
+#include "ppm.h"
+#include "ppmcmap.h"
+
+#if defined(SYSV) || defined(SVR4)
+#include <string.h>
+#ifndef index
+#define index strchr
+#endif
+#else /* SYSV */
+#include <strings.h>
+#endif /* SYSV */
+
+/* Max number of colors allowed in ppm input. */
+#define MAXCOLORS 256
+
+/* Max number of rgb mnemonics allowed in rgb text file. */
+#define MAX_RGBNAMES 1024
+
+/* Lower bound and upper bound of character-pixels printed in XPM output.
+ Be careful, don't want the character '"' in this range. */
+/*#define LOW_CHAR '#' <-- minimum ascii character allowed */
+/*#define HIGH_CHAR '~' <-- maximum ascii character allowed */
+#define LOW_CHAR '`'
+#define HIGH_CHAR 'z'
+
+#define max(a,b) ((a) > (b) ? (a) : (b))
+
+void read_rgb_names(); /* forward reference */
+void gen_cmap(); /* forward reference */
+
+typedef struct { /* rgb values and ascii names (from
+ * rgb text file) */
+ int r, g, b; /* rgb values, range of 0 -> 65535 */
+ char *name; /* color mnemonic of rgb value */
+} rgb_names;
+
+typedef struct { /* character-pixel mapping */
+ char *cixel; /* character string printed for
+ * pixel */
+ char *rgbname; /* ascii rgb color, either color
+ * mnemonic or #rgb value */
+} cixel_map;
+
+pixel **pixels;
+
+main(argc, argv)
+ int argc;
+ char *argv[];
+
+{
+ FILE *ifd;
+ register pixel *pP;
+ int argn, rows, cols, ncolors, row, col, i;
+ pixval maxval; /* pixval == unsigned char or
+ * unsigned short */
+ colorhash_table cht;
+ colorhist_vector chv;
+
+ /* Used for rgb value -> rgb mnemonic mapping */
+ int map_rgb_names = 0;
+ rgb_names rgbn[MAX_RGBNAMES];
+ int rgbn_max;
+
+ /* Used for rgb value -> character-pixel string mapping */
+ cixel_map cmap[MAXCOLORS];
+ int charspp; /* chars per pixel */
+
+ char out_name[100], rgb_fname[100], *cp;
+ char *usage = "[-name <xpm-name>] [-rgb <rgb-textfile>] [ppmfile]";
+
+ ppm_init(&argc, argv);
+ out_name[0] = rgb_fname[0] = '\0';
+
+ argn = 1;
+
+ /* Check for command line options. */
+ while (argn < argc && argv[argn][0] == '-') {
+
+ /* Case "-", use stdin for input. */
+ if (argv[argn][1] == '\0')
+ break;
+
+ /* Case "-name <xpm-filename>", get output filename. */
+ if (strncmp(argv[argn], "-name", max(strlen(argv[argn]), 2)) == 0) {
+ argn++;
+ if (argn == argc || sscanf(argv[argn], "%s", out_name) != 1)
+ pm_usage(usage);
+ }
+ /* Case "-rgb <rgb-filename>", get rgb mnemonics filename. */
+ else if (strncmp(argv[argn], "-rgb", max(strlen(argv[argn]), 2)) == 0) {
+ argn++;
+ if (argn == argc || sscanf(argv[argn], "%s", rgb_fname) != 1)
+ pm_usage(usage);
+ map_rgb_names = 1;
+ }
+ /* Nothing else allowed... */
+ else
+ pm_usage(usage);
+
+ argn++;
+ }
+
+ /* Input file specified, open it and set output filename if necessary. */
+ if (argn < argc) {
+
+ /* Open the input file. */
+ ifd = pm_openr(argv[argn]);
+
+ /* If output filename not specified, use input filename as default. */
+ if (out_name[0] == '\0') {
+ strcpy(out_name, argv[argn]);
+ if (cp = index(out_name, '.'))
+ *cp = '\0'; /* remove extension */
+ }
+
+ /*
+ * If (1) input file was specified as "-" we're using stdin, or (2)
+ * output filename was specified as "-", set output filename to the
+ * default.
+ */
+ if (!strcmp(out_name, "-"))
+ strcpy(out_name, "noname");
+
+ argn++;
+ }
+ /* No input file specified. Using stdin so set default output filename. */
+ else {
+ ifd = stdin;
+ if (out_name[0] == '\0')
+ strcpy(out_name, "noname");
+ }
+
+ /* Only 0 or 1 input files allowed. */
+ if (argn != argc)
+ pm_usage(usage);
+
+ /*
+ * "maxval" is the largest value that can be be found in the ppm file.
+ * All pixel components are relative to this value.
+ */
+ pixels = ppm_readppm(ifd, &cols, &rows, &maxval);
+ pm_close(ifd);
+
+ /* Figure out the colormap. */
+ fprintf(stderr, "(Computing colormap...");
+ fflush(stderr);
+ chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &ncolors);
+ if (chv == (colorhist_vector) 0)
+ pm_error(
+ "too many colors - try running the pixmap through 'ppmquant 256'",
+ 0, 0, 0, 0, 0);
+ fprintf(stderr, " Done. %d colors found.)\n", ncolors);
+
+ /* Make a hash table for fast color lookup. */
+ cht = ppm_colorhisttocolorhash(chv, ncolors);
+
+ /*
+ * If a rgb text file was specified, read in the rgb mnemonics. Does not
+ * return if fatal error occurs.
+ */
+ if (map_rgb_names)
+ read_rgb_names(rgb_fname, rgbn, &rgbn_max);
+
+ /* Now generate the character-pixel colormap table. */
+ gen_cmap(chv, ncolors, maxval, map_rgb_names, rgbn, rgbn_max,
+ cmap, &charspp);
+
+ /* Write out the XPM file. */
+
+ printf("/* XPM */\n");
+ printf("static char *%s[] = {\n", out_name);
+ printf("/* width height ncolors chars_per_pixel */\n");
+ printf("\"%d %d %d %d\",\n", cols, rows, ncolors, charspp);
+ printf("/* colors */\n");
+ for (i = 0; i < ncolors; i++) {
+ printf("\"%s c %s\",\n", cmap[i].cixel, cmap[i].rgbname);
+ }
+ printf("/* pixels */\n");
+ for (row = 0; row < rows; row++) {
+ printf("\"");
+ for (col = 0, pP = pixels[row]; col < cols; col++, pP++) {
+ printf("%s", cmap[ppm_lookupcolor(cht, pP)].cixel);
+ }
+ printf("\"%s\n", (row == (rows - 1) ? "" : ","));
+ }
+ printf("};\n");
+
+ exit(0);
+
+} /* main */
+
+/*---------------------------------------------------------------------------*/
+/* This routine reads a rgb text file. It stores the rgb values (0->65535)
+ and the rgb mnemonics (malloc'ed) into the "rgbn" array. Returns the
+ number of entries stored in "rgbn_max". */
+void
+read_rgb_names(rgb_fname, rgbn, rgbn_max)
+ char *rgb_fname;
+ rgb_names rgbn[MAX_RGBNAMES];
+int *rgbn_max;
+
+{
+ FILE *rgbf;
+ int i, items, red, green, blue;
+ char line[512], name[512], *rgbname, *n, *m;
+
+ /* Open the rgb text file. Abort if error. */
+ if ((rgbf = fopen(rgb_fname, "r")) == NULL)
+ pm_error("error opening rgb text file \"%s\"", rgb_fname, 0, 0, 0, 0);
+
+ /* Loop reading each line in the file. */
+ for (i = 0; fgets(line, sizeof(line), rgbf); i++) {
+
+ /* Quit if rgb text file is too large. */
+ if (i == MAX_RGBNAMES) {
+ fprintf(stderr,
+ "Too many entries in rgb text file, truncated to %d entries.\n",
+ MAX_RGBNAMES);
+ fflush(stderr);
+ break;
+ }
+ /* Read the line. Skip if bad. */
+ items = sscanf(line, "%d %d %d %[^\n]\n", &red, &green, &blue, name);
+ if (items != 4) {
+ fprintf(stderr, "rgb text file syntax error on line %d\n", i + 1);
+ fflush(stderr);
+ i--;
+ continue;
+ }
+ /* Make sure rgb values are within 0->255 range. Skip if bad. */
+ if (red < 0 || red > 0xFF ||
+ green < 0 || green > 0xFF ||
+ blue < 0 || blue > 0xFF) {
+ fprintf(stderr, "rgb value for \"%s\" out of range, ignoring it\n",
+ name);
+ fflush(stderr);
+ i--;
+ continue;
+ }
+ /* Allocate memory for ascii name. Abort if error. */
+ if (!(rgbname = (char *) malloc(strlen(name) + 1)))
+ pm_error("out of memory allocating rgb name", 0, 0, 0, 0, 0);
+
+#ifdef NAMESLOWCASE
+ /* Copy string to ascii name and lowercase it. */
+ for (n = name, m = rgbname; *n; n++)
+ *m++ = isupper(*n) ? tolower(*n) : *n;
+ *m = '\0';
+#else
+ strcpy(rgbname, name);
+#endif
+
+ /* Save the rgb values and ascii name in the array. */
+ rgbn[i].r = red << 8;
+ rgbn[i].g = green << 8;
+ rgbn[i].b = blue << 8;
+ rgbn[i].name = rgbname;
+ }
+
+ /* Return the max number of rgb names. */
+ *rgbn_max = i - 1;
+
+ fclose(rgbf);
+
+} /* read_rgb_names */
+
+/*---------------------------------------------------------------------------*/
+/* Given a number and a base, (base == HIGH_CHAR-LOW_CHAR+1), this routine
+ prints the number into a malloc'ed string and returns it. The length of
+ the string is specified by "digits". The ascii characters of the printed
+ number range from LOW_CHAR to HIGH_CHAR. The string is LOW_CHAR filled,
+ (e.g. if LOW_CHAR==0, HIGH_CHAR==1, digits==5, i=3, routine would return
+ the malloc'ed string "00011"). */
+char *
+gen_numstr(i, base, digits)
+ int i, base, digits;
+{
+ char *str, *p;
+ int d;
+
+ /* Allocate memory for printed number. Abort if error. */
+ if (!(str = (char *) malloc(digits + 1)))
+ pm_error("out of memory", 0, 0, 0, 0, 0);
+
+ /* Generate characters starting with least significant digit. */
+ p = str + digits;
+ *p-- = '\0'; /* nul terminate string */
+ while (p >= str) {
+ d = i % base;
+ i /= base;
+ *p-- = (char) ((int) LOW_CHAR + d);
+ }
+
+ return str;
+
+} /* gen_numstr */
+
+/*---------------------------------------------------------------------------*/
+/* This routine generates the character-pixel colormap table. */
+void
+gen_cmap(chv, ncolors, maxval, map_rgb_names, rgbn, rgbn_max,
+ cmap, charspp)
+/* input: */
+ colorhist_vector chv; /* contains rgb values for colormap */
+ int ncolors; /* number of entries in colormap */
+ pixval maxval; /* largest color value, all rgb
+ * values relative to this, (pixval
+ * == unsigned short) */
+ int map_rgb_names; /* == 1 if mapping rgb values to rgb
+ * mnemonics */
+ rgb_names rgbn[MAX_RGBNAMES]; /* rgb mnemonics from rgb text file */
+int rgbn_max; /* number of rgb mnemonics in table */
+
+/* output: */
+cixel_map cmap[MAXCOLORS]; /* pixel strings and ascii rgb
+ * colors */
+int *charspp; /* characters per pixel */
+
+{
+ int i, j, base, cpp, mval, red, green, blue, r, g, b, matched;
+ char *str;
+
+ /*
+ * Figure out how many characters per pixel we'll be using. Don't want
+ * to be forced to link with libm.a, so using a division loop rather
+ * than a log function.
+ */
+ base = (int) HIGH_CHAR - (int) LOW_CHAR + 1;
+ for (cpp = 0, j = ncolors; j; cpp++)
+ j /= base;
+ *charspp = cpp;
+
+ /*
+ * Determine how many hex digits we'll be normalizing to if the rgb
+ * value doesn't match a color mnemonic.
+ */
+ mval = (int) maxval;
+ if (mval <= 0x000F)
+ mval = 0x000F;
+ else if (mval <= 0x00FF)
+ mval = 0x00FF;
+ else if (mval <= 0x0FFF)
+ mval = 0x0FFF;
+ else
+ mval = 0xFFFF;
+
+ /*
+ * Generate the character-pixel string and the rgb name for each
+ * colormap entry.
+ */
+ for (i = 0; i < ncolors; i++) {
+
+ /*
+ * The character-pixel string is simply a printed number in base
+ * "base" where the digits of the number range from LOW_CHAR to
+ * HIGH_CHAR and the printed length of the number is "cpp".
+ */
+ cmap[i].cixel = gen_numstr(i, base, cpp);
+
+ /* Fetch the rgb value of the current colormap entry. */
+ red = PPM_GETR(chv[i].color);
+ green = PPM_GETG(chv[i].color);
+ blue = PPM_GETB(chv[i].color);
+
+ /*
+ * If the ppm color components are not relative to 15, 255, 4095,
+ * 65535, normalize the color components here.
+ */
+ if (mval != (int) maxval) {
+ red = (red * mval) / (int) maxval;
+ green = (green * mval) / (int) maxval;
+ blue = (blue * mval) / (int) maxval;
+ }
+
+ /*
+ * If the "-rgb <rgbfile>" option was specified, attempt to map the
+ * rgb value to a color mnemonic.
+ */
+ if (map_rgb_names) {
+
+ /*
+ * The rgb values of the color mnemonics are normalized relative
+ * to 255 << 8, (i.e. 0xFF00). [That's how the original MIT
+ * code did it, really should have been "v * 65535 / 255"
+ * instead of "v << 8", but have to use the same scheme here or
+ * else colors won't match...] So, if our rgb values aren't
+ * already 16-bit values, need to shift left.
+ */
+ if (mval == 0x000F) {
+ r = red << 12;
+ g = green << 12;
+ b = blue << 12;
+ /* Special case hack for "white". */
+ if (0xF000 == r && r == g && g == b)
+ r = g = b = 0xFF00;
+ } else if (mval == 0x00FF) {
+ r = red << 8;
+ g = green << 8;
+ b = blue << 8;
+ } else if (mval == 0x0FFF) {
+ r = red << 4;
+ g = green << 4;
+ b = blue << 4;
+ } else {
+ r = red;
+ g = green;
+ b = blue;
+ }
+
+ /*
+ * Just perform a dumb linear search over the rgb values of the
+ * color mnemonics. One could speed things up by sorting the
+ * rgb values and using a binary search, or building a hash
+ * table, etc...
+ */
+ for (matched = 0, j = 0; j <= rgbn_max; j++)
+ if (r == rgbn[j].r && g == rgbn[j].g && b == rgbn[j].b) {
+
+ /* Matched. Allocate string, copy mnemonic, and exit. */
+ if (!(str = (char *) malloc(strlen(rgbn[j].name) + 1)))
+ pm_error("out of memory", 0, 0, 0, 0, 0);
+ strcpy(str, rgbn[j].name);
+ cmap[i].rgbname = str;
+ matched = 1;
+ break;
+ }
+ if (matched)
+ continue;
+ }
+
+ /*
+ * Either not mapping to color mnemonics, or didn't find a match.
+ * Generate an absolute #RGB value string instead.
+ */
+ if (!(str = (char *) malloc(mval == 0x000F ? 5 :
+ mval == 0x00FF ? 8 :
+ mval == 0x0FFF ? 11 :
+ 14)))
+ pm_error("out of memory", 0, 0, 0, 0, 0);
+
+ sprintf(str, mval == 0x000F ? "#%X%X%X" :
+ mval == 0x00FF ? "#%02X%02X%02X" :
+ mval == 0x0FFF ? "#%03X%03X%03X" :
+ "#%04X%04X%04X", red, green, blue);
+ cmap[i].rgbname = str;
+ }
+
+} /* gen_cmap */
diff --git a/src/xpm/converters/xpm1to3.pl b/src/xpm/converters/xpm1to3.pl
new file mode 100644
index 0000000..d102964
--- /dev/null
+++ b/src/xpm/converters/xpm1to3.pl
@@ -0,0 +1,90 @@
+#!/usr/local/bin/perl
+#
+# Usage: xpm1to3.pl xpmv1-file > xpmv3-file
+#
+# Note: perl (available by ftp on prep.ai.mit.edu) script to convert
+# "enhanced" xpm v1 X11 pixmap files to xpm v3 (C includable format)
+# pixmap files...
+# +---------------------------------------------------------------------------
+# WHO: Richard Hess CORP: Consilium
+# TITLE: Staff Engineer VOICE: [415] 691-6342
+# [ X-SWAT Team: Special Projects ] USNAIL: 640 Clyde Court
+# UUCP: ...!uunet!cimshop!rhess Mountain View, CA 94043
+# +---------------------------------------------------------------------------
+
+sub checkname {
+ if ($_[0] ne $_[1]) {
+ printf STDERR "warning, name inconsitencies in %s %s!=%s\n",
+ $_[2], $_[0], $_[1];
+ }
+}
+
+sub checkmono {
+ if ($_[0] ne $_[1]) { return 0; }
+ return 1;
+}
+
+printf "/* XPM */\n";
+($name, $format) = (<> =~ /^#define\s+(\w+)_format\s+(\d+)\s*$/);
+($name2, $width) = (<> =~ /^#define\s+(\w+)_width\s+(\d+)\s*$/);
+&checkname($name, $name2, "width");
+($name2, $height) = (<> =~ /^#define\s+(\w+)_height\s+(\d+)\s*$/);
+&checkname($name, $name2, "height");
+($name2, $ncolors) = (<> =~ /^#define\s+(\w+)_ncolors\s+(\d+)\s*$/);
+&checkname($name, $name2, "ncolors");
+($name2, $chars_per_pixel) = (<> =~
+/^#define\s+(\w+)_chars_per_pixel\s+(\d+)\s*$/);
+&checkname($name, $name2, "chars per pixel");
+
+($name2) = (<> =~ /^static char \*\s*(\w+)_mono\[]\s+=\s+{\s*$/);
+$mono = &checkmono($name, $name2);
+
+if ($mono) {
+ $idx = 0;
+ while ( ($_ = <>) =~ m/^\s*"[^"]+"\s*,\s*"[^"]+"(,)?\s*$/ ) {
+ ($codes[$idx], $mono_name[$idx]) = /^\s*"([^"]+)"\s*,\s*"([^"]+)"(,)?\s*$/;
+ $idx++;
+ }
+ if ($idx != $ncolors) {
+ printf STDERR "Warning, ncolors mismatch reading mono %d != %d\n",
+$ncolors, $idx;
+ }
+
+ ($name2) = (<> =~ /^static char \*\s*(\w+)_colors\[]\s+=\s+{\s*$/);
+ &checkname($name, $name2, "colors");
+}
+
+printf "static char * %s[] = {\n", $name;
+printf "/* %s pixmap\n * width height ncolors chars_per_pixel */\n", $name;
+printf "\"%s %s %s %s \",\n", $width, $height, $ncolors, $chars_per_pixel;
+
+$idx = 0;
+while ( ($_ = <>) =~ m/^\s*"[^"]+"\s*,\s*"[^"]+"(,)?\s*$/ ) {
+ ($codes[$idx], $color_name[$idx]) = /^\s*"([^"]+)"\s*,\s*"([^"]+)"(,)?\s*$/;
+ $idx++;
+}
+if ($idx != $ncolors) {
+ printf STDERR "Warning, ncolors mismatch reading color %d != %d\n",
+$ncolors, $idx;
+}
+
+for ($idx=0; $idx<$ncolors; $idx++) {
+ if ($mono) {
+ printf "\"%s m %s c %s \t s c%d \",\n", $codes[$idx],
+$mono_name[$idx], $color_name[$idx], $idx;
+ }
+ else {
+ printf "\"%s c %s \t s c%d \",\n", $codes[$idx], $color_name[$idx], $idx;
+ }
+}
+
+($name2) = ( <> =~ /^static char \*\s*(\w+)_pixels\[]\s+=\s+{\s*$/);
+&checkname($name, $name2, "pixels");
+
+printf "/* pixels */\n";
+while ( ! ( ($_ = <>) =~ /^}\s*;\s*$/) ) {
+ printf "%s", $_;
+}
+printf "} ;\n";
+
+# -----------------------------------------------------------------------<eof>
diff --git a/src/xpm/converters/xpmtoppm.1 b/src/xpm/converters/xpmtoppm.1
new file mode 100644
index 0000000..e4f414c
--- /dev/null
+++ b/src/xpm/converters/xpmtoppm.1
@@ -0,0 +1,28 @@
+.TH xpmtoppm 1 "16 August 1990"
+.SH NAME
+xpmtoppm - convert an X11 pixmap into a portable pixmap
+.SH SYNOPSIS
+.B xpmtoppm
+.RI [ xpmfile ]
+.SH DESCRIPTION
+Reads an X11 pixmap (XPM version 1 or 3) as input.
+Produces a portable pixmap as output.
+.SH KNOWN BUGS
+The support to XPM version 3 is limited. Comments can only be single lines
+and there must be for every pixel a default colorname for a color type visual.
+.SH "SEE ALSO"
+ppmtoxpm(1), ppm(5)
+.br
+XPM Manual by Arnaud Le Hors lehors@mirsa.inria.fr
+.SH AUTHOR
+Copyright (C) 1991 by Jef Poskanzer.
+.\" Permission to use, copy, modify, and distribute this software and its
+.\" documentation for any purpose and without fee is hereby granted, provided
+.\" that the above copyright notice appear in all copies and that both that
+.\" copyright notice and this permission notice appear in supporting
+.\" documentation. This software is provided "as is" without express or
+.\" implied warranty.
+
+Upgraded to support XPM version 3 by
+ Arnaud Le Hors (lehors@mirsa.inria.fr)
+ Tue Apr 9 1991
diff --git a/src/xpm/converters/xpmtoppm.c b/src/xpm/converters/xpmtoppm.c
new file mode 100644
index 0000000..9842267
--- /dev/null
+++ b/src/xpm/converters/xpmtoppm.c
@@ -0,0 +1,433 @@
+/* xpmtoppm.c - read an X11 pixmap file and produce a portable pixmap
+**
+** Copyright (C) 1991 by Jef Poskanzer.
+**
+** Permission to use, copy, modify, and distribute this software and its
+** documentation for any purpose and without fee is hereby granted, provided
+** that the above copyright notice appear in all copies and that both that
+** copyright notice and this permission notice appear in supporting
+** documentation. This software is provided "as is" without express or
+** implied warranty.
+**
+** Upgraded to support XPM version 3 by
+** Arnaud Le Hors (lehors@mirsa.inria.fr)
+** Tue Apr 9 1991
+**
+** Rainer Sinkwitz sinkwitz@ifi.unizh.ch - 21 Nov 91:
+** - Bug fix, no advance of read ptr, would not read
+** colors like "ac c black" because it would find
+** the "c" of "ac" and then had problems with "c"
+** as color.
+**
+** - Now understands multword X11 color names
+**
+** - Now reads multiple color keys. Takes the color
+** of the hightest available key. Lines no longer need
+** to begin with key 'c'.
+**
+** - expanded line buffer to from 500 to 2048 for bigger files
+*/
+
+#include "ppm.h"
+
+void ReadXPMFile();
+static void getline();
+
+/* number of xpmColorKeys */
+#define NKEYS 5
+
+char *xpmColorKeys[] =
+{
+ "s", /* key #1: symbol */
+ "m", /* key #2: mono visual */
+ "g4", /* key #3: 4 grays visual */
+ "g", /* key #4: gray visual */
+ "c", /* key #5: color visual */
+};
+
+#ifdef NEED_STRSTR
+/* for systems which do not provide it */
+static char *
+strstr(s1, s2)
+ char *s1, *s2;
+{
+ int ls2 = strlen(s2);
+
+ if (ls2 == 0)
+ return (s1);
+ while (strlen(s1) >= ls2) {
+ if (strncmp(s1, s2, ls2) == 0)
+ return (s1);
+ s1++;
+ }
+ return (0);
+}
+
+#endif
+
+void
+main(argc, argv)
+ int argc;
+ char *argv[];
+
+{
+ FILE *ifp;
+ pixel *pixrow, *colors;
+ register pixel *pP;
+ int rows, cols, ncolors, chars_per_pixel, row;
+ register int col;
+ int *data;
+ register int *ptr;
+
+ ppm_init(&argc, argv);
+
+ if (argc > 2)
+ pm_usage("[xpmfile]");
+
+ if (argc == 2)
+ ifp = pm_openr(argv[1]);
+ else
+ ifp = stdin;
+
+ ReadXPMFile(
+ ifp, &cols, &rows, &ncolors, &chars_per_pixel, &colors, &data);
+
+ pm_close(ifp);
+
+ ppm_writeppminit(stdout, cols, rows, (pixval) PPM_MAXMAXVAL, 0);
+ pixrow = ppm_allocrow(cols);
+
+ for (row = 0, ptr = data; row < rows; ++row) {
+ for (col = 0, pP = pixrow; col < cols; ++col, ++pP, ++ptr)
+ *pP = colors[*ptr];
+ ppm_writeppmrow(stdout, pixrow, cols, (pixval) PPM_MAXMAXVAL, 0);
+ }
+
+ exit(0);
+}
+
+#define MAX_LINE 2048
+
+void
+ReadXPMFile(stream, widthP, heightP, ncolorsP,
+ chars_per_pixelP, colorsP, dataP)
+ FILE *stream;
+ int *widthP;
+ int *heightP;
+ int *ncolorsP;
+ int *chars_per_pixelP;
+ pixel **colorsP;
+ int **dataP;
+{
+ char line[MAX_LINE], str1[MAX_LINE], str2[MAX_LINE];
+ char *t1;
+ char *t2;
+ int format, v, datasize;
+ int *ptr;
+ int *ptab;
+ register int i, j;
+ int flag;
+
+ unsigned int curkey, key, highkey; /* current color key */
+ unsigned int lastwaskey; /* key read */
+ char curbuf[BUFSIZ]; /* current buffer */
+
+ *widthP = *heightP = *ncolorsP = *chars_per_pixelP = format = -1;
+ flag = 0; /* to avoid getting twice a line */
+
+ /* First try to read as an XPM version 3 file */
+
+ /* Read the header line */
+ getline(line, sizeof(line), stream);
+ if (sscanf(line, "/* %s */", str1) == 1
+ && !strncmp(str1, "XPM", 3)) {
+
+ /* Read the assignment line */
+ getline(line, sizeof(line), stream);
+ if (strncmp(line, "static char", 11))
+ pm_error("error scanning assignment line", 0, 0, 0, 0, 0);
+
+ /* Read the hints line */
+ getline(line, sizeof(line), stream);
+ /* skip the comment line if any */
+ if (!strncmp(line, "/*", 2)) {
+ while (!strstr(line, "*/"))
+ getline(line, sizeof(line), stream);
+ getline(line, sizeof(line), stream);
+ }
+ if (sscanf(line, "\"%d %d %d %d\",", widthP, heightP,
+ ncolorsP, chars_per_pixelP) != 4)
+ pm_error("error scanning hints line", 0, 0, 0, 0, 0);
+
+ /* Allocate space for color table. */
+ if (*chars_per_pixelP <= 2) {
+ /* Up to two chars per pixel, we can use an indexed table. */
+ v = 1;
+ for (i = 0; i < *chars_per_pixelP; ++i)
+ v *= 256;
+ *colorsP = ppm_allocrow(v);
+ } else {
+ /* Over two chars per pixel, we fall back on linear search. */
+ *colorsP = ppm_allocrow(*ncolorsP);
+ ptab = (int *) malloc(*ncolorsP * sizeof(int));
+ }
+
+ /* Read the color table */
+ for (i = 0; i < *ncolorsP; i++) {
+ getline(line, sizeof(line), stream);
+ /* skip the comment line if any */
+ if (!strncmp(line, "/*", 2))
+ getline(line, sizeof(line), stream);
+
+ /* read the chars */
+ if ((t1 = index(line, '"')) == NULL)
+ pm_error("error scanning color table", 0, 0, 0, 0, 0);
+ else
+ t1++;
+ strncpy(str1, t1, *chars_per_pixelP);
+ str1[*chars_per_pixelP] = '\0';
+ t1++; t1++;
+
+ v = 0;
+ for (j = 0; j < *chars_per_pixelP; ++j)
+ v = (v << 8) + str1[j];
+ /*
+ * read color keys and values
+ */
+ curkey = 0;
+ highkey = 1;
+ lastwaskey = 0;
+ t2 = t1;
+ while ( 1 ) {
+ for (t1=t2 ;; t1++)
+ if (*t1 != ' ' && *t1 != ' ')
+ break;
+ for (t2 = t1;; t2++)
+ if (*t2 == ' ' || *t2 == ' ' || *t2 == '"')
+ break;
+ if (t2 == t1) break;
+ strncpy(str2, t1, t2 - t1);
+ str2[t2 - t1] = '\0';
+
+ if (!lastwaskey) {
+ for (key = 1; key < NKEYS + 1; key++)
+ if (!strcmp(xpmColorKeys[key - 1], str2))
+ break;
+ } else
+ key = NKEYS + 1;
+ if (key > NKEYS) { /* append name */
+ if (!curkey)
+ pm_error("error scanning color table", 0, 0, 0, 0, 0);
+ if (!lastwaskey)
+ strcat(curbuf, " "); /* append space */
+ strcat(curbuf, str2); /* append buf */
+ lastwaskey = 0;
+ }
+ if (key <= NKEYS) { /* new key */
+ if (curkey > highkey) { /* flush string */
+ if (*chars_per_pixelP <= 2)
+ /* Index into table. */
+ (*colorsP)[v] = ppm_parsecolor(curbuf,
+ (pixval) PPM_MAXMAXVAL);
+ else {
+ /* Set up linear search table. */
+ (*colorsP)[i] = ppm_parsecolor(curbuf,
+ (pixval) PPM_MAXMAXVAL);
+ ptab[i] = v;
+ }
+ highkey = curkey;
+ }
+ curkey = key; /* set new key */
+ curbuf[0] = '\0'; /* reset curbuf */
+ lastwaskey = 1;
+ }
+ if (*t2 == '"') break;
+ }
+ if (curkey > highkey) {
+ if (*chars_per_pixelP <= 2)
+ /* Index into table. */
+ (*colorsP)[v] = ppm_parsecolor(curbuf,
+ (pixval) PPM_MAXMAXVAL);
+ else {
+ /* Set up linear search table. */
+ (*colorsP)[i] = ppm_parsecolor(curbuf,
+ (pixval) PPM_MAXMAXVAL);
+ ptab[i] = v;
+ }
+ highkey = curkey;
+ }
+ if (highkey == 1)
+ pm_error("error scanning color table", 0, 0, 0, 0, 0);
+ }
+ /* Read pixels. */
+ getline(line, sizeof(line), stream);
+ /* skip the comment line if any */
+ if (!strncmp(line, "/*", 2))
+ getline(line, sizeof(line), stream);
+
+ } else { /* try as an XPM version 1 file */
+
+ /* Read the initial defines. */
+ for (;;) {
+ if (flag)
+ getline(line, sizeof(line), stream);
+ else
+ flag++;
+
+ if (sscanf(line, "#define %s %d", str1, &v) == 2) {
+ if ((t1 = rindex(str1, '_')) == NULL)
+ t1 = str1;
+ else
+ ++t1;
+ if (!strcmp(t1, "format"))
+ format = v;
+ else if (!strcmp(t1, "width"))
+ *widthP = v;
+ else if (!strcmp(t1, "height"))
+ *heightP = v;
+ else if (!strcmp(t1, "ncolors"))
+ *ncolorsP = v;
+ else if (!strcmp(t1, "pixel"))
+ *chars_per_pixelP = v;
+ } else if (!strncmp(line, "static char", 11)) {
+ if ((t1 = rindex(line, '_')) == NULL)
+ t1 = line;
+ else
+ ++t1;
+ break;
+ }
+ }
+ if (format == -1)
+ pm_error("missing or invalid format", 0, 0, 0, 0, 0);
+ if (format != 1)
+ pm_error("can't handle XPM version %d", format, 0, 0, 0, 0);
+ if (*widthP == -1)
+ pm_error("missing or invalid width", 0, 0, 0, 0, 0);
+ if (*heightP == -1)
+ pm_error("missing or invalid height", 0, 0, 0, 0, 0);
+ if (*ncolorsP == -1)
+ pm_error("missing or invalid ncolors", 0, 0, 0, 0, 0);
+ if (*chars_per_pixelP == -1)
+ pm_error("missing or invalid chars_per_pixel", 0, 0, 0, 0, 0);
+ if (*chars_per_pixelP > 2)
+ pm_message("warning, chars_per_pixel > 2 uses a lot of memory"
+ ,0, 0, 0, 0, 0);
+
+ /* If there's a monochrome color table, skip it. */
+ if (!strncmp(t1, "mono", 4)) {
+ for (;;) {
+ getline(line, sizeof(line), stream);
+ if (!strncmp(line, "static char", 11))
+ break;
+ }
+ }
+ /* Allocate space for color table. */
+ if (*chars_per_pixelP <= 2) {
+ /* Up to two chars per pixel, we can use an indexed table. */
+ v = 1;
+ for (i = 0; i < *chars_per_pixelP; ++i)
+ v *= 256;
+ *colorsP = ppm_allocrow(v);
+ } else {
+ /* Over two chars per pixel, we fall back on linear search. */
+ *colorsP = ppm_allocrow(*ncolorsP);
+ ptab = (int *) malloc(*ncolorsP * sizeof(int));
+ }
+
+ /* Read color table. */
+ for (i = 0; i < *ncolorsP; ++i) {
+ getline(line, sizeof(line), stream);
+
+ if ((t1 = index(line, '"')) == NULL)
+ pm_error("error scanning color table", 0, 0, 0, 0, 0);
+ if ((t2 = index(t1 + 1, '"')) == NULL)
+ pm_error("error scanning color table", 0, 0, 0, 0, 0);
+ if (t2 - t1 - 1 != *chars_per_pixelP)
+ pm_error("wrong number of chars per pixel in color table",
+ 0, 0, 0, 0, 0);
+ strncpy(str1, t1 + 1, t2 - t1 - 1);
+ str1[t2 - t1 - 1] = '\0';
+
+ if ((t1 = index(t2 + 1, '"')) == NULL)
+ pm_error("error scanning color table", 0, 0, 0, 0, 0);
+ if ((t2 = index(t1 + 1, '"')) == NULL)
+ pm_error("error scanning color table", 0, 0, 0, 0, 0);
+ strncpy(str2, t1 + 1, t2 - t1 - 1);
+ str2[t2 - t1 - 1] = '\0';
+
+ v = 0;
+ for (j = 0; j < *chars_per_pixelP; ++j)
+ v = (v << 8) + str1[j];
+ if (*chars_per_pixelP <= 2)
+ /* Index into table. */
+ (*colorsP)[v] = ppm_parsecolor(str2,
+ (pixval) PPM_MAXMAXVAL);
+ else {
+ /* Set up linear search table. */
+ (*colorsP)[i] = ppm_parsecolor(str2,
+ (pixval) PPM_MAXMAXVAL);
+ ptab[i] = v;
+ }
+ }
+
+ /* Read pixels. */
+ for (;;) {
+ getline(line, sizeof(line), stream);
+ if (!strncmp(line, "static char", 11))
+ break;
+ }
+ }
+ datasize = *widthP * *heightP;
+ *dataP = (int *) malloc(datasize * sizeof(int));
+ if (*dataP == 0)
+ pm_error("out of memory", 0, 0, 0, 0, 0);
+ i = 0;
+ ptr = *dataP;
+ for (;;) {
+ if (flag)
+ getline(line, sizeof(line), stream);
+ else
+ flag++;
+
+ /* Find the open quote. */
+ if ((t1 = index(line, '"')) == NULL)
+ pm_error("error scanning pixels", 0, 0, 0, 0, 0);
+ ++t1;
+
+ /* Handle pixels until a close quote or the end of the image. */
+ while (*t1 != '"') {
+ v = 0;
+ for (j = 0; j < *chars_per_pixelP; ++j)
+ v = (v << 8) + *t1++;
+ if (*chars_per_pixelP <= 2)
+ /* Index into table. */
+ *ptr++ = v;
+ else {
+ /* Linear search into table. */
+ for (j = 0; j < *ncolorsP; ++j)
+ if (ptab[j] == v)
+ goto gotit;
+ pm_error("unrecognized pixel in line \"%s\"", line,
+ 0, 0, 0, 0);
+ gotit:
+ *ptr++ = j;
+ }
+ ++i;
+ if (i >= datasize)
+ return;
+ }
+ }
+}
+
+
+static void
+getline(line, size, stream)
+ char *line;
+ int size;
+ FILE *stream;
+{
+ if (fgets(line, MAX_LINE, stream) == NULL)
+ pm_error("EOF / read error", 0, 0, 0, 0, 0);
+ if (strlen(line) == MAX_LINE - 1)
+ pm_error("line too long", 0, 0, 0, 0, 0);
+}
diff --git a/src/xpm/create.c b/src/xpm/create.c
new file mode 100644
index 0000000..238a2bb
--- /dev/null
+++ b/src/xpm/create.c
@@ -0,0 +1,963 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* create.c: *
+* *
+* XPM library *
+* Create an X image and possibly its related shape mask *
+* from the given xpmInternAttrib. *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+#include "xpmP.h"
+#ifdef VMS
+#include "sys$library:ctype.h"
+#else
+#include <ctype.h>
+#endif
+
+LFUNC(xpmVisualType, int, (Visual *visual));
+
+LFUNC(SetColor, int, (Display * display, Colormap colormap, char *colorname,
+ unsigned int color_index, Pixel * image_pixel,
+ Pixel * mask_pixel, unsigned int * mask_pixel_index,
+ Pixel ** pixels, unsigned int * npixels,
+ XpmAttributes *attributes));
+
+LFUNC(CreateColors, int, (Display *display, XpmAttributes *attributes,
+ char ***ct, unsigned int ncolors, Pixel *ip,
+ Pixel *mp, unsigned int *mask_pixel, Pixel **pixels,
+ unsigned int *npixels));
+
+LFUNC(CreateXImage, int, (Display * display, Visual * visual,
+ unsigned int depth, unsigned int width,
+ unsigned int height, XImage ** image_return));
+
+LFUNC(SetImagePixels, void, (XImage * image, unsigned int width,
+ unsigned int height, unsigned int *pixelindex,
+ Pixel * pixels));
+
+LFUNC(SetImagePixels32, void, (XImage * image, unsigned int width,
+ unsigned int height, unsigned int *pixelindex,
+ Pixel * pixels));
+
+LFUNC(SetImagePixels16, void, (XImage * image, unsigned int width,
+ unsigned int height, unsigned int *pixelindex,
+ Pixel * pixels));
+
+LFUNC(SetImagePixels8, void, (XImage * image, unsigned int width,
+ unsigned int height, unsigned int *pixelindex,
+ Pixel * pixels));
+
+LFUNC(SetImagePixels1, void, (XImage * image, unsigned int width,
+ unsigned int height, unsigned int *pixelindex,
+ Pixel * pixels));
+
+#ifdef NEED_STRCASECMP
+
+LFUNC(strcasecmp, int, (char *s1, char *s2));
+
+/*
+ * in case strcasecmp is not provided by the system here is one
+ * which does the trick
+ */
+static int
+strcasecmp(s1, s2)
+ register char *s1, *s2;
+{
+ register int c1, c2;
+
+ while (*s1 && *s2) {
+ c1 = isupper(*s1) ? tolower(*s1) : *s1;
+ c2 = isupper(*s2) ? tolower(*s2) : *s2;
+ if (c1 != c2)
+ return (1);
+ s1++;
+ s2++;
+ }
+ if (*s1 || *s2)
+ return (1);
+ return (0);
+}
+
+#endif
+
+/*
+ * return the default color key related to the given visual
+ */
+static int
+xpmVisualType(visual)
+ Visual *visual;
+{
+ switch (visual->class) {
+ case StaticGray:
+ case GrayScale:
+ switch (visual->map_entries) {
+ case 2:
+ return (MONO);
+ case 4:
+ return (GRAY4);
+ default:
+ return (GRAY);
+ }
+ default:
+ return (COLOR);
+ }
+}
+
+/*
+ * set the color pixel related to the given colorname,
+ * return 0 if success, 1 otherwise.
+ */
+
+static int
+SetColor(display, colormap, colorname, color_index,
+ image_pixel, mask_pixel, mask_pixel_index,
+ pixels, npixels, attributes)
+ Display *display;
+ Colormap colormap;
+ char *colorname;
+ unsigned int color_index;
+ Pixel *image_pixel, *mask_pixel;
+ unsigned int *mask_pixel_index;
+ Pixel **pixels;
+ unsigned int *npixels;
+ XpmAttributes *attributes;
+{
+ XColor xcolor;
+
+ if (strcasecmp(colorname, TRANSPARENT_COLOR)) {
+ if (!XParseColor(display, colormap, colorname, &xcolor)) return(1);
+ else if (!XAllocColor(display, colormap, &xcolor))
+ {
+ if (attributes && (attributes->valuemask & XpmCloseness) &&
+ attributes->closeness != 0)
+ {
+ XColor *cols;
+ unsigned int ncols,i,closepix;
+ long int closediff,closeness = attributes->closeness;
+
+ if (attributes && attributes->valuemask & XpmDepth)
+ ncols = 1 << attributes->depth;
+ else
+ ncols = 1 << DefaultDepth(display, DefaultScreen(display));
+
+ cols = (XColor*)calloc(ncols,sizeof(XColor));
+ for (i = 0; i < ncols; ++i) cols[i].pixel = i;
+ XQueryColors(display,colormap,cols,ncols);
+
+ for (i = 0, closediff = 0x7FFFFFFF; i < ncols; ++i)
+ {
+#define COLOR_FACTOR 3
+#define BRIGHTNESS_FACTOR 1
+
+ long int newclosediff =
+ COLOR_FACTOR * (
+ abs((long)xcolor.red - (long)cols[i].red) +
+ abs((long)xcolor.green - (long)cols[i].green) +
+ abs((long)xcolor.blue - (long)cols[i].blue)) +
+ BRIGHTNESS_FACTOR * abs(
+ ((long)xcolor.red+(long)xcolor.green+(long)xcolor.blue) -
+ ((long)cols[i].red+(long)cols[i].green+(long)cols[i].blue));
+
+ if (newclosediff < closediff)
+ { closepix = i; closediff = newclosediff; }
+ }
+
+ if ((long)cols[closepix].red >= (long)xcolor.red - closeness &&
+ (long)cols[closepix].red <= (long)xcolor.red + closeness &&
+ (long)cols[closepix].green >= (long)xcolor.green - closeness &&
+ (long)cols[closepix].green <= (long)xcolor.green + closeness &&
+ (long)cols[closepix].blue >= (long)xcolor.blue - closeness &&
+ (long)cols[closepix].blue <= (long)xcolor.blue + closeness)
+ {
+ xcolor = cols[closepix]; free(cols);
+ if (!XAllocColor(display, colormap, &xcolor)) return (1);
+ }
+ else { free(cols); return (1); }
+ }
+ else return (1);
+ }
+ *image_pixel = xcolor.pixel;
+ *mask_pixel = 1;
+ (*pixels)[*npixels] = xcolor.pixel;
+ (*npixels)++;
+ } else {
+ *image_pixel = 0;
+ *mask_pixel = 0;
+ *mask_pixel_index = color_index;/* store the color table index */
+ }
+ return (0);
+}
+
+static int
+CreateColors(display, attributes, ct, ncolors,
+ ip, mp, mask_pixel, pixels, npixels)
+ Display *display;
+ XpmAttributes *attributes;
+ char ***ct;
+ unsigned int ncolors;
+ Pixel *ip;
+ Pixel *mp;
+ unsigned int *mask_pixel; /* mask pixel index */
+ Pixel **pixels; /* allocated pixels */
+ unsigned int *npixels; /* number of allocated pixels */
+{
+ /* variables stored in the XpmAttributes structure */
+ Visual *visual;
+ Colormap colormap;
+ XpmColorSymbol *colorsymbols;
+ unsigned int numsymbols;
+
+ char *colorname;
+ unsigned int a, b, l;
+ Boolean pixel_defined;
+ unsigned int key;
+ XpmColorSymbol *cs;
+ char **cts;
+ int ErrorStatus = XpmSuccess;
+ char *s;
+ int cts_index;
+
+ /*
+ * retrieve information from the XpmAttributes
+ */
+ if (attributes && attributes->valuemask & XpmColorSymbols) {
+ colorsymbols = attributes->colorsymbols;
+ numsymbols = attributes->numsymbols;
+ } else
+ numsymbols = 0;
+
+ if (attributes && attributes->valuemask & XpmVisual)
+ visual = attributes->visual;
+ else
+ visual = DefaultVisual(display, DefaultScreen(display));
+
+ if (attributes && attributes->valuemask & XpmColormap)
+ colormap = attributes->colormap;
+ else
+ colormap = DefaultColormap(display, DefaultScreen(display));
+
+ key = xpmVisualType(visual);
+ switch(key)
+ {
+ case MONO: cts_index = 2; break;
+ case GRAY4: cts_index = 3; break;
+ case GRAY: cts_index = 4; break;
+ case COLOR: cts_index = 5; break;
+ }
+
+ for (a = 0; a < ncolors; a++, ct++, ip++, mp++) {
+ colorname = NULL;
+ pixel_defined = False;
+ cts = *ct;
+
+ /*
+ * look for a defined symbol
+ */
+ if (numsymbols && cts[1]) {
+ s = cts[1];
+ for (l = 0, cs = colorsymbols; l < numsymbols; l++, cs++)
+ if ((!cs->name && cs->value && cts[cts_index] &&
+ !strcasecmp(cs->value,cts[cts_index])) ||
+ cs->name && !strcmp(cs->name, s))
+ break;
+ if (l != numsymbols) {
+ if (cs->name && cs->value)
+ colorname = cs->value;
+ else
+ pixel_defined = True;
+ }
+ }
+ if (!pixel_defined) { /* pixel not given as symbol value */
+ if (colorname) { /* colorname given as symbol value */
+ if (!SetColor(display, colormap, colorname, a, ip, mp,
+ mask_pixel, pixels, npixels, attributes))
+ pixel_defined = True;
+ else
+ ErrorStatus = XpmColorError;
+ }
+ b = key;
+ while (!pixel_defined && b > 1) {
+ if (cts[b]) {
+ if (!SetColor(display, colormap, cts[b], a, ip, mp,
+ mask_pixel, pixels, npixels, attributes)) {
+ pixel_defined = True;
+ break;
+ } else
+ ErrorStatus = XpmColorError;
+ }
+ b--;
+ }
+ b = key + 1;
+ while (!pixel_defined && b < NKEYS + 1) {
+ if (cts[b]) {
+ if (!SetColor(display, colormap, cts[b], a, ip, mp,
+ mask_pixel, pixels, npixels, attributes)) {
+ pixel_defined = True;
+ break;
+ } else
+ ErrorStatus = XpmColorError;
+ }
+ b++;
+ }
+ if (!pixel_defined)
+ return (XpmColorFailed);
+ } else {
+ *ip = colorsymbols[l].pixel;
+ *mp = 1;
+ }
+ }
+ return (ErrorStatus);
+}
+
+/* function call in case of error, frees only locally allocated variables */
+#undef RETURN
+#ifdef Debug
+/*
+ * XDestroyImage free the image data but mnemosyne don't know about it
+ * so I free them by hand to avoid mnemalyse report it as lost data.
+ */
+#define RETURN(status) \
+ { if (image) { \
+ free(image->data); \
+ XDestroyImage(image); } \
+ if (shapeimage) { \
+ free(shapeimage->data); \
+ XDestroyImage(shapeimage); } \
+ if (image_pixels) free(image_pixels); \
+ if (mask_pixels) free(mask_pixels); \
+ if (npixels) XFreeColors(display, colormap, pixels, npixels, 0); \
+ if (pixels) free(pixels); \
+ return (status); }
+
+#else
+
+#define RETURN(status) \
+ { if (image) XDestroyImage(image); \
+ if (shapeimage) XDestroyImage(shapeimage); \
+ if (image_pixels) free(image_pixels); \
+ if (mask_pixels) free(mask_pixels); \
+ if (npixels) XFreeColors(display, colormap, pixels, npixels, 0); \
+ if (pixels) free(pixels); \
+ return (status); }
+
+#endif
+
+xpmCreateImage(display, attrib, image_return, shapeimage_return, attributes)
+ Display *display;
+ xpmInternAttrib *attrib;
+ XImage **image_return;
+ XImage **shapeimage_return;
+ XpmAttributes *attributes;
+{
+ /* variables stored in the XpmAttributes structure */
+ Visual *visual;
+ Colormap colormap;
+ unsigned int depth;
+
+ /* variables to return */
+ XImage *image = NULL;
+ XImage *shapeimage = NULL;
+ unsigned int mask_pixel;
+ int ErrorStatus;
+
+ /* calculation variables */
+ Pixel *image_pixels = NULL;
+ Pixel *mask_pixels = NULL;
+ Pixel *pixels = NULL; /* allocated pixels */
+ unsigned int npixels = 0; /* number of allocated pixels */
+
+ /*
+ * retrieve information from the XpmAttributes
+ */
+ if (attributes && attributes->valuemask & XpmVisual)
+ visual = attributes->visual;
+ else
+ visual = DefaultVisual(display, DefaultScreen(display));
+
+ if (attributes && attributes->valuemask & XpmColormap)
+ colormap = attributes->colormap;
+ else
+ colormap = DefaultColormap(display, DefaultScreen(display));
+
+ if (attributes && attributes->valuemask & XpmDepth)
+ depth = attributes->depth;
+ else
+ depth = DefaultDepth(display, DefaultScreen(display));
+
+ ErrorStatus = XpmSuccess;
+
+ /*
+ * malloc pixels index tables
+ */
+
+ image_pixels = (Pixel *) malloc(sizeof(Pixel) * attrib->ncolors);
+ if (!image_pixels)
+ return(XpmNoMemory);
+
+ mask_pixels = (Pixel *) malloc(sizeof(Pixel) * attrib->ncolors);
+ if (!mask_pixels)
+ RETURN(ErrorStatus);
+
+ mask_pixel = UNDEF_PIXEL;
+
+ /* maximum of allocated pixels will be the number of colors */
+ pixels = (Pixel *) malloc(sizeof(Pixel) * attrib->ncolors);
+ if (!pixels)
+ RETURN(ErrorStatus);
+
+ /*
+ * get pixel colors, store them in index tables
+ */
+
+ ErrorStatus = CreateColors(display, attributes, attrib->colorTable,
+ attrib->ncolors, image_pixels, mask_pixels,
+ &mask_pixel, &pixels, &npixels);
+ if (ErrorStatus != XpmSuccess && (ErrorStatus < 0 || attributes &&
+ (attributes->valuemask & XpmExactColors) && attributes->exactColors))
+ RETURN(ErrorStatus);
+
+ /*
+ * create the image
+ */
+ if (image_return) {
+ ErrorStatus = CreateXImage(display, visual, depth,
+ attrib->width, attrib->height, &image);
+ if (ErrorStatus != XpmSuccess)
+ RETURN(ErrorStatus);
+
+ /*
+ * set the image data
+ *
+ * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use
+ * optimized functions, otherwise use slower but sure general one.
+ *
+ */
+
+ if (image->depth == 1)
+ SetImagePixels1(image, attrib->width, attrib->height,
+ attrib->pixelindex, image_pixels);
+ else if (image->bits_per_pixel == 8)
+ SetImagePixels8(image, attrib->width, attrib->height,
+ attrib->pixelindex, image_pixels);
+ else if (image->bits_per_pixel == 16)
+ SetImagePixels16(image, attrib->width, attrib->height,
+ attrib->pixelindex, image_pixels);
+ else if (image->bits_per_pixel == 32)
+ SetImagePixels32(image, attrib->width, attrib->height,
+ attrib->pixelindex, image_pixels);
+ else
+ SetImagePixels(image, attrib->width, attrib->height,
+ attrib->pixelindex, image_pixels);
+ }
+
+ /*
+ * create the shape mask image
+ */
+ if (mask_pixel != UNDEF_PIXEL && shapeimage_return) {
+ ErrorStatus = CreateXImage(display, visual, 1, attrib->width,
+ attrib->height, &shapeimage);
+ if (ErrorStatus != XpmSuccess)
+ RETURN(ErrorStatus);
+
+ SetImagePixels1(shapeimage, attrib->width, attrib->height,
+ attrib->pixelindex, mask_pixels);
+ }
+ free(mask_pixels);
+ free(pixels);
+
+ /*
+ * if requested store used pixels in the XpmAttributes structure
+ */
+ if (attributes &&
+ (attributes->valuemask & XpmReturnInfos
+ || attributes->valuemask & XpmReturnPixels)) {
+ if (mask_pixel != UNDEF_PIXEL) {
+ Pixel *pixels, *p1, *p2;
+ unsigned int a;
+
+ attributes->npixels = attrib->ncolors - 1;
+ pixels = (Pixel *) malloc(sizeof(Pixel) * attributes->npixels);
+ if (pixels) {
+ p1 = image_pixels;
+ p2 = pixels;
+ for (a = 0; a < attrib->ncolors; a++, p1++)
+ if (a != mask_pixel)
+ *p2++ = *p1;
+ attributes->pixels = pixels;
+ } else {
+ /* if error just say we can't return requested data */
+ attributes->valuemask &= ~XpmReturnPixels;
+ attributes->valuemask &= ~XpmReturnInfos;
+ attributes->pixels = NULL;
+ attributes->npixels = 0;
+ }
+ free(image_pixels);
+ } else {
+ attributes->pixels = image_pixels;
+ attributes->npixels = attrib->ncolors;
+ }
+ attributes->mask_pixel = mask_pixel;
+ } else
+ free(image_pixels);
+
+
+ /*
+ * return created images
+ */
+ if (image_return)
+ *image_return = image;
+
+ if (shapeimage_return)
+ *shapeimage_return = shapeimage;
+
+ return (ErrorStatus);
+}
+
+
+/*
+ * Create an XImage
+ */
+static int
+CreateXImage(display, visual, depth, width, height, image_return)
+ Display *display;
+ Visual *visual;
+ unsigned int depth;
+ unsigned int width;
+ unsigned int height;
+ XImage **image_return;
+{
+ int bitmap_pad;
+
+ /* first get bitmap_pad */
+ if (depth > 16)
+ bitmap_pad = 32;
+ else if (depth > 8)
+ bitmap_pad = 16;
+ else
+ bitmap_pad = 8;
+
+ /* then create the XImage with data = NULL and bytes_per_line = 0 */
+
+ *image_return = XCreateImage(display, visual, depth, ZPixmap, 0, 0,
+ width, height, bitmap_pad, 0);
+ if (!*image_return)
+ return (XpmNoMemory);
+
+ /* now that bytes_per_line must have been set properly alloc data */
+
+ (*image_return)->data =
+ (char *) malloc((*image_return)->bytes_per_line * height);
+
+ if (!(*image_return)->data) {
+ XDestroyImage(*image_return);
+ *image_return = NULL;
+ return (XpmNoMemory);
+ }
+ return (XpmSuccess);
+}
+
+
+/*
+ * The functions below are written from X11R5 MIT's code (XImUtil.c)
+ *
+ * The idea is to have faster functions than the standard XPutPixel function
+ * to build the image data. Indeed we can speed up things by suppressing tests
+ * performed for each pixel. We do the same tests but at the image level.
+ * We also assume that we use only ZPixmap images with null offsets.
+ */
+
+LFUNC(_putbits, void, (register char *src, int dstoffset,
+ register int numbits, register char *dst));
+
+LFUNC(_XReverse_Bytes, int, (register unsigned char *bpt, register int nb));
+
+static unsigned char Const _reverse_byte[0x100] = {
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
+};
+
+static int
+_XReverse_Bytes(bpt, nb)
+ register unsigned char *bpt;
+ register int nb;
+{
+ do {
+ *bpt = _reverse_byte[*bpt];
+ bpt++;
+ } while (--nb > 0);
+ return 0;
+}
+
+
+void
+xpm_xynormalizeimagebits(bp, img)
+ register unsigned char *bp;
+ register XImage *img;
+{
+ register unsigned char c;
+
+ if (img->byte_order != img->bitmap_bit_order) {
+ switch (img->bitmap_unit) {
+
+ case 16:
+ c = *bp;
+ *bp = *(bp + 1);
+ *(bp + 1) = c;
+ break;
+
+ case 32:
+ c = *(bp + 3);
+ *(bp + 3) = *bp;
+ *bp = c;
+ c = *(bp + 2);
+ *(bp + 2) = *(bp + 1);
+ *(bp + 1) = c;
+ break;
+ }
+ }
+ if (img->bitmap_bit_order == MSBFirst)
+ _XReverse_Bytes(bp, img->bitmap_unit >> 3);
+}
+
+void
+xpm_znormalizeimagebits(bp, img)
+ register unsigned char *bp;
+ register XImage *img;
+{
+ register unsigned char c;
+
+ switch (img->bits_per_pixel) {
+
+ case 4:
+ *bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF);
+ break;
+
+ case 16:
+ c = *bp;
+ *bp = *(bp + 1);
+ *(bp + 1) = c;
+ break;
+
+ case 24:
+ c = *(bp + 2);
+ *(bp + 2) = *bp;
+ *bp = c;
+ break;
+
+ case 32:
+ c = *(bp + 3);
+ *(bp + 3) = *bp;
+ *bp = c;
+ c = *(bp + 2);
+ *(bp + 2) = *(bp + 1);
+ *(bp + 1) = c;
+ break;
+ }
+}
+
+static unsigned char Const _lomask[0x09] = {
+ 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
+static unsigned char Const _himask[0x09] = {
+ 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
+
+static void
+_putbits(src, dstoffset, numbits, dst)
+ register char *src; /* address of source bit string */
+ int dstoffset; /* bit offset into destination;
+ * range is 0-31 */
+ register int numbits; /* number of bits to copy to
+ * destination */
+ register char *dst; /* address of destination bit string */
+{
+ register unsigned char chlo, chhi;
+ int hibits;
+
+ dst = dst + (dstoffset >> 3);
+ dstoffset = dstoffset & 7;
+ hibits = 8 - dstoffset;
+ chlo = *dst & _lomask[dstoffset];
+ for (;;) {
+ chhi = (*src << dstoffset) & _himask[dstoffset];
+ if (numbits <= hibits) {
+ chhi = chhi & _lomask[dstoffset + numbits];
+ *dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi;
+ break;
+ }
+ *dst = chhi | chlo;
+ dst++;
+ numbits = numbits - hibits;
+ chlo = (unsigned char) (*src & _himask[hibits]) >> hibits;
+ src++;
+ if (numbits <= dstoffset) {
+ chlo = chlo & _lomask[numbits];
+ *dst = (*dst & _himask[numbits]) | chlo;
+ break;
+ }
+ numbits = numbits - dstoffset;
+ }
+}
+
+/*
+ * Default method to write pixels into a Z image data structure.
+ * The algorithm used is:
+ *
+ * copy the destination bitmap_unit or Zpixel to temp
+ * normalize temp if needed
+ * copy the pixel bits into the temp
+ * renormalize temp if needed
+ * copy the temp back into the destination image data
+ */
+
+static void
+SetImagePixels(image, width, height, pixelindex, pixels)
+ XImage *image;
+ unsigned int width;
+ unsigned int height;
+ unsigned int *pixelindex;
+ Pixel *pixels;
+{
+ register char *src;
+ register char *dst;
+ register unsigned int *iptr;
+ register int x, y, i;
+ register char *data;
+ Pixel pixel, px;
+ int nbytes, depth, ibu, ibpp;
+
+ data = image->data;
+ iptr = pixelindex;
+ depth = image->depth;
+ if (image->depth == 1) {
+ ibu = image->bitmap_unit;
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ pixel = pixels[*iptr];
+ for (i = 0, px = pixel;
+ i < sizeof(unsigned long); i++, px >>= 8)
+ ((unsigned char *) &pixel)[i] = px;
+ src = &data[XYINDEX(x, y, image)];
+ dst = (char *) &px;
+ px = 0;
+ nbytes = ibu >> 3;
+ for (i = nbytes; --i >= 0;)
+ *dst++ = *src++;
+ XYNORMALIZE(&px, image);
+ _putbits((char *) &pixel, (x % ibu), 1, (char *) &px);
+ XYNORMALIZE(&px, image);
+ src = (char *) &px;
+ dst = &data[XYINDEX(x, y, image)];
+ for (i = nbytes; --i >= 0;)
+ *dst++ = *src++;
+ }
+ } else {
+ ibpp = image->bits_per_pixel;
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ pixel = pixels[*iptr];
+ if (depth == 4)
+ pixel &= 0xf;
+ for (i = 0, px = pixel;
+ i < sizeof(unsigned long); i++, px >>= 8)
+ ((unsigned char *) &pixel)[i] = px;
+ src = &data[ZINDEX(x, y, image)];
+ dst = (char *) &px;
+ px = 0;
+ nbytes = (ibpp + 7) >> 3;
+ for (i = nbytes; --i >= 0;)
+ *dst++ = *src++;
+ ZNORMALIZE(&px, image);
+ _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
+ ZNORMALIZE(&px, image);
+ src = (char *) &px;
+ dst = &data[ZINDEX(x, y, image)];
+ for (i = nbytes; --i >= 0;)
+ *dst++ = *src++;
+ }
+ }
+}
+
+/*
+ * write pixels into a 32-bits Z image data structure
+ */
+
+#ifndef WORD64
+static unsigned long byteorderpixel = MSBFirst << 24;
+
+#endif
+
+static void
+SetImagePixels32(image, width, height, pixelindex, pixels)
+ XImage *image;
+ unsigned int width;
+ unsigned int height;
+ unsigned int *pixelindex;
+ Pixel *pixels;
+{
+ register unsigned char *addr;
+ register unsigned char *data;
+ register unsigned int *iptr;
+ register int x, y;
+ Pixel pixel;
+
+ data = (unsigned char *) image->data;
+ iptr = pixelindex;
+#ifndef WORD64
+ if (*((char *) &byteorderpixel) == image->byte_order) {
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ addr = &data[ZINDEX32(x, y, image)];
+ *((unsigned long *)addr) = pixels[*iptr];
+ }
+ } else
+#endif
+ if (image->byte_order == MSBFirst)
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ addr = &data[ZINDEX32(x, y, image)];
+ pixel = pixels[*iptr];
+ addr[0] = pixel >> 24;
+ addr[1] = pixel >> 16;
+ addr[2] = pixel >> 8;
+ addr[3] = pixel;
+ }
+ else
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ addr = &data[ZINDEX32(x, y, image)];
+ pixel = pixels[*iptr];
+ addr[0] = pixel;
+ addr[1] = pixel >> 8;
+ addr[2] = pixel >> 16;
+ addr[3] = pixel >> 24;
+ }
+}
+
+/*
+ * write pixels into a 16-bits Z image data structure
+ */
+
+static void
+SetImagePixels16(image, width, height, pixelindex, pixels)
+ XImage *image;
+ unsigned int width;
+ unsigned int height;
+ unsigned int *pixelindex;
+ Pixel *pixels;
+{
+ register unsigned char *addr;
+ register unsigned char *data;
+ register unsigned int *iptr;
+ register int x, y;
+
+ data = (unsigned char *) image->data;
+ iptr = pixelindex;
+ if (image->byte_order == MSBFirst)
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ addr = &data[ZINDEX16(x, y, image)];
+ addr[0] = pixels[*iptr] >> 8;
+ addr[1] = pixels[*iptr];
+ }
+ else
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ addr = &data[ZINDEX16(x, y, image)];
+ addr[0] = pixels[*iptr];
+ addr[1] = pixels[*iptr] >> 8;
+ }
+}
+
+/*
+ * write pixels into a 8-bits Z image data structure
+ */
+
+static void
+SetImagePixels8(image, width, height, pixelindex, pixels)
+ XImage *image;
+ unsigned int width;
+ unsigned int height;
+ unsigned int *pixelindex;
+ Pixel *pixels;
+{
+ register char *data;
+ register unsigned int *iptr;
+ register int x, y;
+
+ data = image->data;
+ iptr = pixelindex;
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++)
+ data[ZINDEX8(x, y, image)] = pixels[*iptr];
+}
+
+/*
+ * write pixels into a 1-bit depth image data structure and **offset null**
+ */
+
+static void
+SetImagePixels1(image, width, height, pixelindex, pixels)
+ XImage *image;
+ unsigned int width;
+ unsigned int height;
+ unsigned int *pixelindex;
+ Pixel *pixels;
+{
+ register unsigned int *iptr;
+ register int x, y;
+ register char *data;
+
+ if (image->byte_order != image->bitmap_bit_order)
+ SetImagePixels(image, width, height, pixelindex, pixels);
+ else {
+ data = image->data;
+ iptr = pixelindex;
+ if (image->bitmap_bit_order == MSBFirst)
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ if (pixels[*iptr] & 1)
+ data[ZINDEX1(x, y, image)] |= 0x80 >> (x & 7);
+ else
+ data[ZINDEX1(x, y, image)] &= ~(0x80 >> (x & 7));
+ }
+ else
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ if (pixels[*iptr] & 1)
+ data[ZINDEX1(x, y, image)] |= 1 << (x & 7);
+ else
+ data[ZINDEX1(x, y, image)] &= ~(1 << (x & 7));
+ }
+ }
+}
diff --git a/src/xpm/data.c b/src/xpm/data.c
new file mode 100644
index 0000000..87901d9
--- /dev/null
+++ b/src/xpm/data.c
@@ -0,0 +1,422 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* data.c: *
+* *
+* XPM library *
+* IO utilities *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+/* Official version number */
+static char *RCS_Version = "$XpmVersion: 3.2c $";
+
+/* Internal version number */
+static char *RCS_Id = "$Id: xpm.shar,v 3.13 1992/12/29 16:05:26 lehors Exp $";
+
+#include "xpmP.h"
+#ifdef VMS
+#include "sys$library:stat.h"
+#include "sys$library:ctype.h"
+#else
+#include <sys/stat.h>
+#include <ctype.h>
+#endif
+
+FUNC(atoui, unsigned int, (char *p, unsigned int l, unsigned int *ui_return));
+LFUNC(ParseComment, int, (xpmData *mdata));
+
+unsigned int
+atoui(p, l, ui_return)
+ register char *p;
+ unsigned int l;
+ unsigned int *ui_return;
+{
+ register int n, i;
+
+ n = 0;
+ for (i = 0; i < l; i++)
+ if (*p >= '0' && *p <= '9')
+ n = n * 10 + *p++ - '0';
+ else
+ break;
+
+ if (i != 0 && i == l) {
+ *ui_return = n;
+ return 1;
+ } else
+ return 0;
+}
+
+static int
+ParseComment(mdata)
+ xpmData *mdata;
+{
+ FILE *file = mdata->stream.file;
+ register int c;
+ register unsigned int n = 0, a;
+ unsigned int notend;
+ char *s, *s2;
+
+ s = mdata->Comment;
+ *s = mdata->Bcmt[0];
+
+ /* skip the string beginning comment */
+ s2 = mdata->Bcmt;
+ do {
+ c = getc(file);
+ *++s = c;
+ n++;
+ s2++;
+ } while (c == *s2 && *s2 != '\0'
+ && c != EOF && c != mdata->Bos);
+
+ if (*s2 != '\0') {
+ /* this wasn't the beginning of a comment */
+ /* put characters back in the order that we got them */
+ for (a = n; a > 0; a--, s--)
+ ungetc(*s, file);
+ return 0;
+ }
+
+ /* store comment */
+ mdata->Comment[0] = *s;
+ s = mdata->Comment;
+ notend = 1;
+ n = 0;
+ while (notend) {
+ s2 = mdata->Ecmt;
+ while (*s != *s2 && c != EOF && c != mdata->Bos) {
+ c = getc(file);
+ *++s = c;
+ n++;
+ }
+ mdata->CommentLength = n;
+ do {
+ c = getc(file);
+ n++;
+ *++s = c;
+ s2++;
+ } while (c == *s2 && *s2 != '\0'
+ && c != EOF && c != mdata->Bos);
+ if (*s2 == '\0') {
+ /* this is the end of the comment */
+ notend = 0;
+ ungetc(*s, file);
+ }
+ }
+}
+
+/*
+ * skip to the end of the current string and the beginning of the next one
+ */
+xpmNextString(mdata)
+ xpmData *mdata;
+{
+ if (!mdata->type)
+ mdata->cptr = (mdata->stream.data)[++mdata->line];
+ else {
+ register int c;
+ FILE *file = mdata->stream.file;
+
+ /* get to the end of the current string */
+ if (mdata->Eos)
+ while ((c = getc(file)) != mdata->Eos && c != EOF);
+
+ /* then get to the beginning of the next string
+ * looking for possible comment */
+ if (mdata->Bos) {
+ while ((c = getc(file)) != mdata->Bos && c != EOF)
+ if (mdata->Bcmt && c == mdata->Bcmt[0])
+ ParseComment(mdata);
+
+ } else { /* XPM2 natural */
+ while (mdata->Bcmt && (c = getc(file)) == mdata->Bcmt[0])
+ ParseComment(mdata);
+ ungetc(c, file);
+ }
+ }
+}
+
+
+/*
+ * skip whitespace and compute the following unsigned int,
+ * returns 1 if one is found and 0 if not
+ */
+int
+xpmNextUI(mdata, ui_return)
+ xpmData *mdata;
+ unsigned int *ui_return;
+{
+ char buf[BUFSIZ];
+ int l;
+
+ l = xpmNextWord(mdata, buf);
+ return atoui(buf, l, ui_return);
+}
+
+/*
+ * skip whitespace and return the following word
+ */
+unsigned int
+xpmNextWord(mdata, buf)
+ xpmData *mdata;
+ char *buf;
+{
+ register unsigned int n = 0;
+ int c;
+
+ if (!mdata->type) {
+ while (isspace(c = *mdata->cptr) && c != mdata->Eos)
+ mdata->cptr++;
+ do {
+ c = *mdata->cptr++;
+ *buf++ = c;
+ n++;
+ } while (!isspace(c) && c != mdata->Eos);
+ n--;
+ mdata->cptr--;
+ } else {
+ FILE *file = mdata->stream.file;
+ while (isspace(c = getc(file)) && c != mdata->Eos);
+ while (!isspace(c) && c != mdata->Eos && c != EOF) {
+ *buf++ = c;
+ n++;
+ c = getc(file);
+ }
+ ungetc(c, file);
+ }
+ return (n);
+}
+
+/*
+ * return end of string - WARNING: malloc!
+ */
+int
+xpmGetString(mdata, sptr, l)
+ xpmData *mdata;
+ char **sptr;
+ unsigned int *l;
+{
+ unsigned int i, n = 0;
+ int c;
+ char *p, *q, buf[BUFSIZ];
+
+ if (!mdata->type) {
+ if (mdata->cptr) {
+ char *start;
+ while (isspace(c = *mdata->cptr) && c != mdata->Eos)
+ mdata->cptr++;
+ start = mdata->cptr;
+ while (c = *mdata->cptr)
+ mdata->cptr++;
+ n = mdata->cptr - start + 1;
+ p = (char *) malloc(n);
+ if (!p)
+ return (XpmNoMemory);
+ strncpy(p, start, n);
+ }
+ } else {
+ FILE *file = mdata->stream.file;
+ while (isspace(c = getc(file)) && c != mdata->Eos);
+ if (c == EOF)
+ return (XpmFileInvalid);
+ p = NULL;
+ i = 0;
+ q = buf;
+ p = (char *) malloc(1);
+ while (c != mdata->Eos && c != EOF) {
+ if (i == BUFSIZ) {
+ /* get to the end of the buffer */
+ /* malloc needed memory */
+ q = (char *) realloc(p, n + i);
+ if (!q) {
+ free(p);
+ return (XpmNoMemory);
+ }
+ p = q;
+ q += n;
+ /* and copy what we already have */
+ strncpy(q, buf, i);
+ n += i;
+ i = 0;
+ q = buf;
+ }
+ *q++ = c;
+ i++;
+ c = getc(file);
+ }
+ if (c == EOF) {
+ free(p);
+ return (XpmFileInvalid);
+ }
+ if (n + i != 0) {
+ /* malloc needed memory */
+ q = (char *) realloc(p, n + i + 1);
+ if (!q) {
+ free(p);
+ return (XpmNoMemory);
+ }
+ p = q;
+ q += n;
+ /* and copy the buffer */
+ strncpy(q, buf, i);
+ n += i;
+ p[n++] = '\0';
+ } else {
+ *p = '\0';
+ n = 1;
+ }
+ ungetc(c, file);
+ }
+ *sptr = p;
+ *l = n;
+ return (XpmSuccess);
+}
+
+/*
+ * get the current comment line
+ */
+xpmGetCmt(mdata, cmt)
+ xpmData *mdata;
+ char **cmt;
+{
+ if (!mdata->type)
+ *cmt = NULL;
+ else
+ if (mdata->CommentLength) {
+ *cmt = (char *) malloc(mdata->CommentLength + 1);
+ strncpy(*cmt, mdata->Comment, mdata->CommentLength);
+ (*cmt)[mdata->CommentLength] = '\0';
+ mdata->CommentLength = 0;
+ } else
+ *cmt = NULL;
+}
+
+/*
+ * open the given file to be read as an xpmData which is returned.
+ */
+int
+xpmReadFile(filename, mdata)
+ char *filename;
+ xpmData *mdata;
+{
+ char *compressfile, buf[BUFSIZ];
+ struct stat status;
+
+ if (!filename) {
+ mdata->stream.file = (stdin);
+ mdata->type = XPMFILE;
+ } else {
+#ifdef ZPIPE
+ if (((int)strlen(filename) > 2) &&
+ !strcmp(".Z", filename + (strlen(filename) - 2))) {
+ mdata->type = XPMPIPE;
+ sprintf(buf, "uncompress -c %s", filename);
+ if (!(mdata->stream.file = popen(buf, "r")))
+ return (XpmOpenFailed);
+
+ } else {
+ if (!(compressfile = (char *) malloc(strlen(filename) + 3)))
+ return (XpmNoMemory);
+
+ strcpy(compressfile, filename);
+ strcat(compressfile, ".Z");
+ if (!stat(compressfile, &status)) {
+ sprintf(buf, "uncompress -c %s", compressfile);
+ if (!(mdata->stream.file = popen(buf, "r"))) {
+ free(compressfile);
+ return (XpmOpenFailed);
+ }
+ mdata->type = XPMPIPE;
+ } else {
+#endif
+ if (!(mdata->stream.file = fopen(filename, "r"))) {
+#ifdef ZPIPE
+ free(compressfile);
+#endif
+ return (XpmOpenFailed);
+ }
+ mdata->type = XPMFILE;
+#ifdef ZPIPE
+ }
+ free(compressfile);
+ }
+#endif
+ }
+ mdata->CommentLength = 0;
+ return (XpmSuccess);
+}
+
+/*
+ * open the given file to be written as an xpmData which is returned
+ */
+int
+xpmWriteFile(filename, mdata)
+ char *filename;
+ xpmData *mdata;
+{
+ char buf[BUFSIZ];
+
+ if (!filename) {
+ mdata->stream.file = (stdout);
+ mdata->type = XPMFILE;
+ } else {
+#ifdef ZPIPE
+ if ((int)strlen(filename) > 2
+ && !strcmp(".Z", filename + ((int)strlen(filename) - 2))) {
+ sprintf(buf, "compress > %s", filename);
+ if (!(mdata->stream.file = popen(buf, "w")))
+ return (XpmOpenFailed);
+
+ mdata->type = XPMPIPE;
+ } else {
+#endif
+ if (!(mdata->stream.file = fopen(filename, "w")))
+ return (XpmOpenFailed);
+
+ mdata->type = XPMFILE;
+#ifdef ZPIPE
+ }
+#endif
+ }
+ return (XpmSuccess);
+}
+
+/*
+ * open the given array to be read or written as an xpmData which is returned
+ */
+void
+xpmOpenArray(data, mdata)
+ char **data;
+ xpmData *mdata;
+{
+ mdata->type = XPMARRAY;
+ mdata->stream.data = data;
+ mdata->cptr = *data;
+ mdata->line = 0;
+ mdata->CommentLength = 0;
+ mdata->Bcmt = mdata->Ecmt = NULL;
+ mdata->Bos = mdata->Eos = '\0';
+}
+
+/*
+ * close the file related to the xpmData if any
+ */
+XpmDataClose(mdata)
+ xpmData *mdata;
+{
+ switch (mdata->type) {
+ case XPMARRAY:
+ break;
+ case XPMFILE:
+ if (mdata->stream.file != (stdout) && mdata->stream.file != (stdin))
+ fclose(mdata->stream.file);
+ break;
+#ifdef ZPIPE
+ case XPMPIPE:
+ pclose(mdata->stream.file);
+ break;
+#endif
+ }
+}
diff --git a/src/xpm/doc/CHANGES b/src/xpm/doc/CHANGES
new file mode 100644
index 0000000..22f28a5
--- /dev/null
+++ b/src/xpm/doc/CHANGES
@@ -0,0 +1,422 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/**************************************************************************\
+* *
+* HISTORY of user-visible changes *
+* *
+\**************************************************************************/
+
+3.2c (92/12/29)
+
+ ENHANCEMENTS:
+ - parsing optimized for single and double characters color
+ - patch originally from Martin Brunecky
+ marbru@build1.auto-trol.com
+
+ BUGS CORRECTED:
+ - XpmFreeExtensions was calling free on some argument without checking
+ it was not NULL.
+ - strdup was not correctly defined for systems which do not provide
+ it. - Hans-Peter Lichtin <lich@zellweger.ch>
+ - some bug in XpmCrDataFI.c
+ - Sven Delmas garfield@avalanche.cs.tu-berlin.de
+
+ NOTE:
+ - there is still a bug with the creation of the clipmask on display of
+ depth 2 but I can't find a fix because unfortunately I don't have such
+ a rendering system and nobody gets the time to investigate for me.
+
+3.2b (92/10/19)
+
+ ENHANCEMENTS:
+ - Create XpmReadFileToData and XpmWriteFileFromData
+ - Dan Greening <dgreen@sti.com>
+ - added "close colors" support and ability to redefine color values
+ as pixels at load time, as well as color names
+ - Jason Patterson <jasonp@fitmail.qut.edu.au>
+ - errors while parsing or allocating colors now revert to other
+ visual defaults, creating pixmap/image as expected, and returning
+ XpmSuccess. The old behaviour of XpmColorError being returned and no
+ pixmap/image being created can be retained by setting the
+ exactColors attribute.
+ - Jason Patterson <jasonp@fitmail.qut.edu.au>
+
+ BUGS CORRECTED:
+ - SVR4 defines for including <string.h> instead of <strings.h>
+ - Jason Patterson <jasonp@fitmail.qut.edu.au>
+ - attributes->extensions and attributes->nextensions fields were not
+ set correctly when no extensions present in file.
+ - Simon_Scott Cornish <cornish@ecr.mu.oz.au>
+
+3.2a (92/08/17)
+
+ ENHANCEMENTS:
+ - use the mock lisp hashing function instead of the gnu emacs one,
+ it is faster in some cases and never slower (I've not found any case).
+
+ BUGS CORRECTED:
+ - function prototypes for ansi compilers.
+ - some memory initialization bugs (purify is just great for this).
+ - empty strings in extensions are now correctly handled.
+
+3.2 (92/07/06)
+
+ NEW FEATURES:
+ - both format and functions handle extensions data. This allow people
+ to store additional data related to a pixmap. See documentation for
+ detail.
+ - sxpm supports the new option '-c' to use a private colormap. This is
+ useful when displaying pixmaps using a lot of colors.
+ - sxpm supports the new option '-v' (verbose) to get possible
+ extensions print out on standard error.
+
+ ENHANCEMENTS:
+ - most of the code has been reworked to be improved and thus almost
+ every function is faster. It takes less than 6 seconds of real time on
+ a sun4 to display, with sxpm, a 487x635 pixmap using 213 colors, while
+ it takes 32 seconds with the old library! It takes 18 seconds to
+ display a 1279x1023 screen dump using 14 colors while xwud takes 10
+ seconds.
+ Of course performance improvements are not always that great, they
+ depend on the size and number of colors but I'm sure everybody will
+ appreciate ;-)
+ I know how to improve it more but this will require changes in the
+ architecture so this is not for now. Some optimizations have been
+ contributed by gregor@kafka.saic.com (gregg hanna) and
+ jnc@csl.biosci.arizona.edu (John N. Calley).
+ - the Imakefile is modified to let you install sxpm - Rainer Klute
+ <klute@irb.informatik.uni-dortmund.de>
+ - xpmP.h declares popen for Sequent platforms - Clinton Jeffery
+ <cjeffery@cs.arizona.edu>
+ - XpmWriteFileFromImage/Pixmap rather than truncating the pixmap name
+ to the first dot changes dots to underscores to get a valid C syntax
+ name.
+
+
+ BUGS CORRECTED:
+ - there was a bug in the image creation function for some 24 bits
+ displays. It is fixed.
+ - allocated color pixels are now freed when an error occurs -
+ nusser@dec1.wu-wien.ac.at (Stefan Nusser)
+
+ CHANGES TO THE DOC:
+ - the documentation describes the new XpmExtension structure and how
+ to use it with read and write functions.
+
+3.1 (92/02/03)
+
+ ENHANCEMENTS:
+ - sxpm now have more standard options (mainly suggested by
+ Rainer Sinkwitz <sinkwitz@ifi.unizh.ch>):
+
+ Usage: sxpm [options...]
+ Where options are:
+
+ [-d host:display] Display to connect to.
+ [-g geom] Geometry of window.
+ [-hints] Set ResizeInc for window.
+ [-icon filename] Set pixmap for iconWindow.
+ [-s symbol_name color_name] Overwrite color defaults.
+ [-p symbol_name pixel_value] Overwrite color defaults.
+ [-plaid] Read the included plaid pixmap.
+ [filename] Read from file 'filename', and from
+ standard input if 'filename' is '-'.
+ [-o filename] Write to file 'filename', and to standard
+ output if 'filename' is '-'.
+ [-nod] Don't display in window.
+ [-rgb filename] Search color names in the rgb text file
+ 'filename'.
+
+ if no input is specified sxpm reads from stdandard input.
+
+
+ - Xpm functions and Ppm converters now deal with multiword colornames.
+ patches from Rainer Sinkwitz <sinkwitz@ifi.unizh.ch>.
+
+
+3.0 (91/10/03)
+
+ Functions name and defines have been modified again (sorry for that)
+ as follows:
+
+ XpmReadPixmapFile XpmReadFileToPixmap
+ XpmWritePixmapFile XpmWriteFileFromPixmap
+
+ XpmPixmapColorError XpmColorError
+ XpmPixmapSuccess XpmSuccess
+ XpmPixmapOpenFailed XpmOpenFailed
+ XpmPixmapFileInvalid XpmFileInvalid
+ XpmPixmapNoMemory XpmNoMemory
+ XpmPixmapColorFailed XpmColorFailed
+
+ To update code using Xpm you can use the included shell script called
+ rename with the sed commands files name-3.0b-3.0c and name-3.0c-3.0.
+ Old names still valid though.
+
+ NEW FEATURES:
+ - four new functions to work with images instead of pixmaps:
+
+ XpmReadFileToImage
+ XpmWriteFileFromImage
+ XpmCreateImageFromData
+ XpmCreateDataFromImage
+
+ ENHANCEMENTS:
+ Algorithms to create and scan images and pixmaps are based on the
+ MIT's R5 code, thus they are much cleaner than old ones and should
+ avoid any problem with any visual (yes, I trust MIT folks :-)
+
+ BUGS CORRECTED:
+ Imakefile use INCDIR instead of ROOTDIR.
+
+ CHANGES TO THE DOC:
+ - the documentation presents the four new functions.
+
+3.0c (91/09/18)
+
+ In answer to request of people functions, types and defines names have
+ been changed as follows:
+
+ XCreatePixmapFromData XpmCreatePixmapFromData
+ XCreateDataFromPixmap XpmCreateDataFromPixmap
+ XReadPixmapFile XpmReadPixmapFile
+ XWritePixmapFile XpmWritePixmapFile
+ XFreeXpmAttributes XpmFreeAttributes
+
+ PixmapColorError XpmPixmapColorError
+ PixmapSuccess XpmPixmapSuccess
+ PixmapOpenFailed XpmPixmapOpenFailed
+ PixmapFileInvalid XpmPixmapFileInvalid
+ PixmapNoMemory XpmPixmapNoMemory
+ PixmapColorFailed XpmPixmapColorFailed
+
+ ColorSymbol XpmColorSymbol
+
+ Generally speaking every public name begins with 'Xpm' and every
+ private one with 'xpm'. This should avoid any possible conflict.
+
+ Some files have also be renamed accordingly.
+
+ NEW FEATURES:
+ - support for VMS and two new options for sxpm: icon and hints (see
+ manual for details) Richard Hess <rhess%pleione%cimshop@uunet.UU.NET>
+ - DEFINES in Imakefile and Makefile.noXtree allows you to set the
+ following:
+
+ ZPIPE for un/compressing piped feature (default is on)
+ NEED_STRCASECMP for system which doesn't provide one (default
+ is off)
+
+ - xpmtoppm.c has is own strstr function which is used if NEED_STRSTR
+ is defined when compiling - Hugues.Leroy@irisa.fr (Hugues Leroy).
+
+ BUGS CORRECTED:
+ - many bugs have been fixed, especially for ansi compilers -
+ Doyle C. Davidson (doyle@doyled.b23b.ingr.com) and
+ Clifford D. Morrison (cdm%bigdaddy%edsr@uunet.UU.NET)
+ - parser is again a little more improved
+
+3.0b (91/09/12)
+
+ This is a complete new version with a new API and where files and
+ structures have been renamed. So this should be taken as a new
+ starting release.
+ This release should be quickly followed by the 3.0 because I'm planning
+ to send it for X11R5 contrib which ends October 5th.
+
+ NEW FEATURES:
+ - support for transparent color.
+ - support for hotspot.
+ - a new function: XCreateDataFromPixmap to create an XPM data from a
+ pixmap in order to be able to create a new pixmap from this data using
+ the XCreatePixmapFromData function later on.
+ - a new structure: XpmAttributes which replace the XpmInfo structure
+ and which leads to a much simpler API with less arguments.
+ - arguments such as visual, colormap and depth are optionnal, default
+ values are taken if omitted.
+ - parsing and allocating color failures don't simply break anymore. If
+ another default color can be found it is used and a PixmapColorError
+ is returned. In case no color can be found then it breaks and returns
+ PixmapColorFailed.
+ - for this reason the ErrorStatus codes are redefined as follows:
+
+ null if full success
+ positive if partial success
+ negative if failure
+
+ with:
+ #define PixmapColorError 1
+ #define PixmapSuccess 0
+ #define PixmapOpenFailed -1
+ #define PixmapFileInvalid -2
+ #define PixmapNoMemory -3
+ #define PixmapColorFailed -4
+
+ - sxpm prints out a warning when a requested color could not be parsed
+ or alloc'ed, and an error when none has been found.
+ - sxpm handles pixmap with transparent color. For this purpose the
+ plaid_mask.xpm is added to the distribution.
+
+ BUGS CORRECTED:
+ - I've again improved the memory management.
+ - the parser is also improved.
+ - when writting a pixmap to a file the variable name could be
+ "plaid.xpm" which is not valid in C. Now the extension name is cut off
+ to give "plaid" as variable name.
+ - reading multiple words colornames such as "peach puff" where leading
+ to non readable Xpm files. They are now skipped to have only single
+ word colorname. Lionel Mallet (mallet@ipvpel.unipv.it).
+ - parser was triggered by the "/" character inside string.
+ Doyle C. Davidson (doyle@doyled.b23b.ingr.com). This is corrected.
+ - sxpm maps the window only if the option "-nod" is not selected.
+
+ CHANGES TO THE DOC:
+ - the documentation presents the new API and features.
+
+3.0a (91/04/10)
+
+ This is an alpha version because it supports the new version of XPM,
+ but the library interface is still the same. Indeed it will change in
+ future release to get rid of obsolete stuff such as the type argument
+ of the XWritePixmapFile function.
+
+ ******************************* WARNING *********************************
+ The format is not anymore XPM2, it is XPM version 3 which is XPM2
+ limited to the C syntax with the key word "XPM" in place of "XPM2 C".
+ The interface library has not changed yet but the type argument of
+ XWritePixmapFile and the type member of XpmInfo are not used anymore.
+ Meanwhile the library which is now called libXpm.a is backward
+ compatible as XPM2 files can be read. But the XWritePixmapFile
+ function only writes out XPM version 3 files.
+ *************************************************************************
+
+ NEW FEATURES:
+ - the library doesn't use global variables anymore, thus it should be
+ able to share it.
+ - sxpm has been rewritten on top of Xt, it can be used to convert
+ files from XPM2 to XPM version 3.
+ - xpm1to2c.perl has been upgraded to the new XPM version and renamed
+ as xpm1to3.perl
+ - ppmtoxpm2.c and ppmtoxpm2.1 have been upgraded too and renamed
+ ppmtoxpm.c and ppmtoxpm.1. In addition the xpmtoppm.c and xpmtoppm.1
+ of the pbmplus package have been upgraded too. xpmtoppm can thus
+ convert XPM version 1 and 3 to a portable pixmap. These files should
+ replace the original ones which are part of the pbmplus package. See
+ the ppm.README file for more details.
+ - the library contains RCS variables which allows you to get revision
+ numbers with ident (which is part of the RCS package). The Id number
+ is an internal rcs number for my eyes only. The official one is found
+ in Version.
+
+ BUGS CORRECTED:
+ - the memory management has been much improved in order to avoid
+ memory leaks.
+ - the XImage building algorythm has been changed to support correctly
+ different visual depths. There is special code to handle depths 1, 4,
+ 6, 8, 24, and 32 to build the image and send it in one whack, and
+ other depths are supported by building the image with XPutPixel which
+ is slow but sure.
+ - similar algorithms are used to read pixmaps and write them out.
+
+ CHANGES TO THE DOC:
+ - the documentation presents the new XPM format.
+
+
+2.8 (90/12/19)
+
+ ******************************* WARNING *********************************
+ Since the last release two structures have been modified and have now
+ bigger sizes, so ANY CODE USING THE libXPM2 NEEDS TO BE RECOMPILED.
+ *************************************************************************
+
+ NEW FEATURES:
+ - the ColorSymbol struct contains the new member 'pixel' which allow
+ to override default colors by giving a pixel value (in such a case
+ symbol value must be set to NULL),
+ - the XpmInfo struct contains the new member 'rgb_fname' in which one
+ can specify an rgb text file name while writing a pixmap with the
+ XWritePixmapFile function (otherwise this member should be set to
+ NULL). This way colorname will be searched and written out if found
+ instead of the RGB value,
+ - Imakefile originally provided by stolcke@ICSI.Berkeley.EDU,
+ - the old Makefile is now distributed as Makefile.noXtree and presents
+ install targets,
+ - the demo application is renamed sxpm (Show XPM), creates a window of
+ the size of the pixmap if no geometry is specified, prints out
+ messages instead of status when an error occurs, handles the new
+ option -p for overriding colors by giving a pixel value (not really
+ useful but is just here to show this new feature), handles the new
+ option -rgb for specifying an rgb text file, and ends on
+ keypress as buttonpress,
+ - defines for SYSV have been provided by Paul Breslaw
+ <paul@mecazh.uucp>,
+ - the distribution includes a new directory called converters which
+ contains xpm1to2 and xpm1to2c perl converters and a ppmtoxpm2
+ converter provided by Paul Breslaw who upgraded the original ppmtoxpm
+ written by Mark W. Snitily <mark@zok.uucp>.
+
+ CHANGES TO THE DOC:
+ - this file is created and will give old users a quick reference to
+ changes made from one release to the next one,
+ - documentation is changed to present the new ColorSymbol structure
+ and the way to override colors by giving a pixel value, and to present
+ the new XpmInfo structure and how to use it,
+ - a man page for sxpm is added to the distrib,
+ - the README file talks about sxpm and no more demo, and have
+ reference to the different converters.
+
+2.7 (90/11/12)
+
+ NEW FEATURES:
+ - XReadPixmapFile reads from stdin if filename is NULL,
+ - XWritePixmapFile writes to stdin if filename is NULL,
+ - the demo application handles the new option -nod for no displaying
+ the pixmap in a window (useful when used as converter).
+
+ CHANGES TO THE DOC:
+ - documentation about the new feature.
+
+2.6 (90/10/29)
+
+ NEW FEATURES:
+ - from nazgul@alphalpha.com (Kee Hinckley): changes to make the
+ library usable as C++ code, and on Apollo without any warning.
+
+ BUGS CORRECTED:
+ - from nazgul@alphalpha.com (Kee Hinckley): the xpm include files was
+ declaring XWritePixmapFile as taking in arg a Pixmap pointer instead
+ of a Pixmap.
+
+2.5 (90/10/17)
+
+ BUGS CORRECTED:
+ - XWritePixmapFile was not closing the file while ending normaly.
+
+2.4 (90/09/06)
+
+ NEW FEATURES:
+ - XReadPixmapFile reads from a piped uncompress if the given filename
+ ends by .Z or if filename.Z exists,
+ - XWritePixmapFile writes to a piped compress if the given filename
+ ends by .Z.
+
+ BUGS CORRECTED:
+ - demo now deals with window manager.
+
+ CHANGES TO THE DOC:
+ - documentation about compressed files management.
+
+2.3 (90/08/30)
+
+ BUGS CORRECTED:
+ - handle monochrom display correctly,
+ - comments can be empty.
+
+2.2 (90/08/27)
+
+ BUGS CORRECTED:
+ - when reading some invalid free was dumping core on some machine.
+
+2.1 (90/08/24)
+
+ First distribution of XPM2.
+
diff --git a/src/xpm/doc/COPYRIGHT b/src/xpm/doc/COPYRIGHT
new file mode 100644
index 0000000..951b7c3
--- /dev/null
+++ b/src/xpm/doc/COPYRIGHT
@@ -0,0 +1,30 @@
+/*
+ * Copyright 1990-92 GROUPE BULL
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of GROUPE BULL not be used in advertising
+ * or publicity pertaining to distribution of the software without specific,
+ * written prior permission. GROUPE BULL makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * GROUPE BULL disclaims all warranties with regard to this software,
+ * including all implied warranties of merchantability and fitness,
+ * in no event shall GROUPE BULL be liable for any special,
+ * indirect or consequential damages or any damages
+ * whatsoever resulting from loss of use, data or profits,
+ * whether in an action of contract, negligence or other tortious
+ * action, arising out of or in connection with the use
+ * or performance of this software.
+ *
+ */
+
+Arnaud LE HORS BULL Research FRANCE -- Koala Project
+ (XPM - X PixMap format version 2 & 3)
+ Internet: lehors@sophia.inria.fr
+Surface Mail: Arnaud LE HORS, INRIA - Sophia Antipolis,
+ 2004, route des Lucioles, 06565 Valbonne Cedex -- FRANCE
+ Voice phone: (33) 93.65.77.71, Fax: (33) 93 65 77 66, Telex: 97 00 50 F
diff --git a/src/xpm/doc/FILES b/src/xpm/doc/FILES
new file mode 100644
index 0000000..1538e04
--- /dev/null
+++ b/src/xpm/doc/FILES
@@ -0,0 +1,42 @@
+CHANGES
+COPYRIGHT
+FILES
+Imakefile
+Makefile
+Makefile.noXtree
+README
+XpmCrDataFP.c
+XpmCrPFData.c
+XpmRdFToP.c
+XpmWrFFrP.c
+XpmCrDataFI.c
+XpmCrIFData.c
+XpmRdFToI.c
+XpmWrFFrI.c
+XpmRdFToData.c
+XpmWrFFrData.c
+colas.sty
+create.c
+data.c
+hashtable.c
+misc.c
+parse.c
+plaid.xpm
+plaid_mask.xpm
+rgb.c
+scan.c
+sxpm.c
+sxpm.man
+xpm.h
+xpm.tex
+xpmP.h
+converters
+converters/xpm1to3.pl
+converters/ppmtoxpm.1
+converters/ppmtoxpm.c
+converters/xpmtoppm.1
+converters/xpmtoppm.c
+converters/ppm.README
+rename
+name-3.0b-3.0c
+name-3.0c-3.0
diff --git a/src/xpm/doc/Imakefile b/src/xpm/doc/Imakefile
new file mode 100644
index 0000000..860aec4
--- /dev/null
+++ b/src/xpm/doc/Imakefile
@@ -0,0 +1,59 @@
+# Copyright 1990-92 GROUPE BULL -- See licence conditions in file COPYRIGHT
+#
+# XPM Imakefile - Arnaud LE HORS
+#
+
+
+#if (ProjectX < 5)
+ STD_DEFINES = LibraryDefines
+ CDEBUGFLAGS = LibraryCDebugFlags
+#else
+/* R5 needs another .tmpl file to find these #def's. This .tmpl file will */
+/* also set STD_DEFINES and CDEBUGFLAGS properly. */
+#include <Library.tmpl>
+#endif
+
+ INCLUDES = -I.
+ INSTALLFLAGS = $(INSTINCFLAGS)
+ LINTLIBS = $(LINTXTOLL) $(LINTXLIB)
+
+#ifdef OsNameDefines
+OS_NAME_DEFINES = OsNameDefines
+#endif
+
+## if your system doesn't provide strcasecmp add -DNEED_STRCASECMP
+## if your system doesn't provide strdup add -DNEED_STRDUP
+## if your system doesn't provide pipe remove -DZPIPE
+DEFINES = -DZPIPE
+
+HEADERS = xpm.h
+ SRCS1 = data.c create.c misc.c rgb.c scan.c parse.c \
+ XpmWrFFrP.c XpmRdFToP.c XpmCrPFData.c XpmCrDataFP.c \
+ XpmWrFFrI.c XpmRdFToI.c XpmCrIFData.c XpmCrDataFI.c \
+ hashtable.c XpmRdFToData.c XpmWrFFrData.c
+ SRCS = $(SRCS1) sxpm.c
+ OBJS1 = data.o create.o misc.o rgb.o scan.o parse.o \
+ XpmWrFFrP.o XpmRdFToP.o XpmCrPFData.o XpmCrDataFP.o \
+ XpmWrFFrI.o XpmRdFToI.o XpmCrIFData.o XpmCrDataFI.o \
+ hashtable.o XpmRdFToData.o XpmWrFFrData.o
+ OBJS = sxpm.o
+
+NormalLibraryObjectRule()
+
+NormalLibraryTarget(Xpm,$(OBJS1))
+LintLibraryTarget(Xpm,$(SRCS1))
+InstallLibrary(Xpm,$(USRLIBDIR))
+InstallLintLibrary(Xpm,$(LINTLIBDIR))
+
+InstallMultiple($(HEADERS),$(INCDIR))
+DependTarget()
+NormalLintTarget($(SRCS1))
+
+
+ DEPLIBS = libXpm.a $(DEPXTOOLLIB) $(DEPXLIB)
+LOCAL_LIBRARIES = libXpm.a $(XTOOLLIB) $(XLIB)
+
+ComplexProgramTarget(sxpm)
+
+clean::
+ $(RM) sxpmout.xpm
diff --git a/src/xpm/doc/Makefile b/src/xpm/doc/Makefile
new file mode 100644
index 0000000..4f08519
--- /dev/null
+++ b/src/xpm/doc/Makefile
@@ -0,0 +1,433 @@
+# Makefile generated by imake - do not edit!
+# $XConsortium: imake.c,v 1.65 91/07/25 17:50:17 rws Exp $
+#
+# The cpp used on this machine replaces all newlines and multiple tabs and
+# spaces in a macro expansion with a single space. Imake tries to compensate
+# for this, but is not always successful.
+#
+
+# -------------------------------------------------------------------------
+# Makefile generated from "Imake.tmpl" and </tmp/IIf.a10758>
+# $XConsortium: Imake.tmpl,v 1.139 91/09/16 08:52:48 rws Exp $
+#
+# Platform-specific parameters may be set in the appropriate <vendor>.cf
+# configuration files. Site-specific parameters should be set in the file
+# site.def. Full rebuilds are recommended if any parameters are changed.
+#
+# If your C preprocessor does not define any unique symbols, you will need
+# to set BOOTSTRAPCFLAGS when rebuilding imake (usually when doing
+# "make World" the first time).
+#
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that need to come before
+# the platform-specific parameters - edit site.def to change
+
+# site: $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+# -------------------------------------------------------------------------
+# platform-specific configuration parameters - edit sun.cf to change
+
+# platform: $XConsortium: sun.cf,v 1.72.1.1 92/03/18 13:13:37 rws Exp $
+
+# operating system: SunOS 4.1.1
+
+# $XConsortium: sunLib.rules,v 1.7 91/12/20 11:19:47 rws Exp $
+
+# -------------------------------------------------------------------------
+# site-specific configuration parameters that go after
+# the platform-specific parameters - edit site.def to change
+
+# site: $XConsortium: site.def,v 1.2 91/07/30 20:26:44 rws Exp $
+
+ TOP = .
+ CURRENT_DIR = .
+
+ AR = ar clq
+ BOOTSTRAPCFLAGS =
+ CC = cc
+ AS = as
+
+ COMPRESS = compress
+ CPP = /lib/cpp $(STD_CPP_DEFINES)
+ PREPROCESSCMD = cc -E $(STD_CPP_DEFINES)
+ INSTALL = install
+ LD = ld
+ LINT = lint
+ LINTLIBFLAG = -C
+ LINTOPTS = -axz
+ LN = ln -s
+ MV = mv
+ CP = cp
+
+ RANLIB = ranlib
+ RANLIBINSTFLAGS =
+
+ RM = rm -f
+ TROFF = ptroff -t
+ MSMACROS = -ms
+ TBL = tbl
+ EQN = eqn
+ STD_INCLUDES =
+ STD_CPP_DEFINES =
+ STD_DEFINES =
+ EXTRA_LOAD_FLAGS =
+ EXTRA_LIBRARIES =
+ TAGS = ctags
+
+ SHAREDCODEDEF = -DSHAREDCODE
+ SHLIBDEF = -DSUNSHLIB
+
+ PROTO_DEFINES =
+
+ INSTPGMFLAGS =
+
+ INSTBINFLAGS = -m 0755
+ INSTUIDFLAGS = -m 4755
+ INSTLIBFLAGS = -m 0644
+ INSTINCFLAGS = -m 0444
+ INSTMANFLAGS = -m 0444
+ INSTDATFLAGS = -m 0444
+ INSTKMEMFLAGS = -g kmem -m 2755
+
+ TOP_INCLUDES = -I$(INCROOT)
+
+ CDEBUGFLAGS = -O
+ CCOPTIONS = -pipe
+
+ ALLINCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) $(TOP_INCLUDES) $(STD_INCLUDES)
+ ALLDEFINES = $(ALLINCLUDES) $(STD_DEFINES) $(EXTRA_DEFINES) $(PROTO_DEFINES) $(DEFINES)
+ CFLAGS = $(CDEBUGFLAGS) $(CCOPTIONS) $(ALLDEFINES)
+ LINTFLAGS = $(LINTOPTS) -DLINT $(ALLDEFINES)
+
+ LDLIBS = $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+ LDOPTIONS = $(CDEBUGFLAGS) $(CCOPTIONS) $(LOCAL_LDFLAGS) -L$(USRLIBDIR)
+
+ LDCOMBINEFLAGS = -X -r
+ DEPENDFLAGS =
+
+ MACROFILE = sun.cf
+ RM_CMD = $(RM) *.CKP *.ln *.BAK *.bak *.o core errs ,* *~ *.a .emacs_* tags TAGS make.log MakeOut
+
+ IMAKE_DEFINES =
+
+ IRULESRC = $(CONFIGDIR)
+ IMAKE_CMD = $(IMAKE) -DUseInstalled -I$(IRULESRC) $(IMAKE_DEFINES)
+
+ ICONFIGFILES = $(IRULESRC)/Imake.tmpl $(IRULESRC)/Imake.rules \
+ $(IRULESRC)/Project.tmpl $(IRULESRC)/site.def \
+ $(IRULESRC)/$(MACROFILE) $(EXTRA_ICONFIGFILES)
+
+# -------------------------------------------------------------------------
+# X Window System Build Parameters
+# $XConsortium: Project.tmpl,v 1.138.1.1 92/11/11 09:49:19 rws Exp $
+
+# -------------------------------------------------------------------------
+# X Window System make variables; this need to be coordinated with rules
+
+ PATHSEP = /
+ USRLIBDIR = /usr/lib/X11R5
+ BINDIR = /usr/bin/X11R5
+ INCROOT = /usr/include/X11R5
+ BUILDINCROOT = $(TOP)
+ BUILDINCDIR = $(BUILDINCROOT)/X11
+ BUILDINCTOP = ..
+ INCDIR = $(INCROOT)/X11
+ ADMDIR = /usr/adm
+ LIBDIR = /usr/lib/X11R5
+ CONFIGDIR = $(LIBDIR)/config
+ LINTLIBDIR = $(USRLIBDIR)/lint
+
+ FONTDIR = $(LIBDIR)/fonts
+ XINITDIR = $(LIBDIR)/xinit
+ XDMDIR = $(LIBDIR)/xdm
+ TWMDIR = $(LIBDIR)/twm
+ MANPATH = /usr/man
+ MANSOURCEPATH = $(MANPATH)/man
+ MANSUFFIX = n
+ LIBMANSUFFIX = 3
+ MANDIR = $(MANSOURCEPATH)$(MANSUFFIX)
+ LIBMANDIR = $(MANSOURCEPATH)$(LIBMANSUFFIX)
+ NLSDIR = $(LIBDIR)/nls
+ PEXAPIDIR = $(LIBDIR)/PEX
+ XAPPLOADDIR = $(LIBDIR)/app-defaults
+ FONTCFLAGS = -t
+
+ INSTAPPFLAGS = $(INSTDATFLAGS)
+
+ IMAKE = imake
+ DEPEND = makedepend
+ RGB = rgb
+
+ FONTC = bdftopcf
+
+ MKFONTDIR = mkfontdir
+ MKDIRHIER = /bin/sh $(BINDIR)/mkdirhier
+
+ CONFIGSRC = $(TOP)/config
+ DOCUTILSRC = $(TOP)/doc/util
+ CLIENTSRC = $(TOP)/clients
+ DEMOSRC = $(TOP)/demos
+ LIBSRC = $(TOP)/lib
+ FONTSRC = $(TOP)/fonts
+ INCLUDESRC = $(TOP)/X11
+ SERVERSRC = $(TOP)/server
+ UTILSRC = $(TOP)/util
+ SCRIPTSRC = $(UTILSRC)/scripts
+ EXAMPLESRC = $(TOP)/examples
+ CONTRIBSRC = $(TOP)/../contrib
+ DOCSRC = $(TOP)/doc
+ RGBSRC = $(TOP)/rgb
+ DEPENDSRC = $(UTILSRC)/makedepend
+ IMAKESRC = $(CONFIGSRC)
+ XAUTHSRC = $(LIBSRC)/Xau
+ XLIBSRC = $(LIBSRC)/X
+ XMUSRC = $(LIBSRC)/Xmu
+ TOOLKITSRC = $(LIBSRC)/Xt
+ AWIDGETSRC = $(LIBSRC)/Xaw
+ OLDXLIBSRC = $(LIBSRC)/oldX
+ XDMCPLIBSRC = $(LIBSRC)/Xdmcp
+ BDFTOSNFSRC = $(FONTSRC)/bdftosnf
+ BDFTOSNFSRC = $(FONTSRC)/clients/bdftosnf
+ BDFTOPCFSRC = $(FONTSRC)/clients/bdftopcf
+ MKFONTDIRSRC = $(FONTSRC)/clients/mkfontdir
+ FSLIBSRC = $(FONTSRC)/lib/fs
+ FONTSERVERSRC = $(FONTSRC)/server
+ EXTENSIONSRC = $(TOP)/extensions
+ XILIBSRC = $(EXTENSIONSRC)/lib/xinput
+ PEXLIBSRC = $(EXTENSIONSRC)/lib/PEXlib
+ PHIGSLIBSRC = $(EXTENSIONSRC)/lib/PEX
+
+# $XConsortium: sunLib.tmpl,v 1.14.1.2 92/11/11 09:55:02 rws Exp $
+
+SHLIBLDFLAGS = -assert pure-text
+PICFLAGS = -pic
+
+ DEPEXTENSIONLIB =
+ EXTENSIONLIB = -lXext
+
+ DEPXLIB = $(DEPEXTENSIONLIB)
+ XLIB = $(EXTENSIONLIB) -lX11
+
+ DEPXMULIB = $(USRLIBDIR)/libXmu.sa.$(SOXMUREV)
+ XMULIBONLY = -lXmu
+ XMULIB = -lXmu
+
+ DEPOLDXLIB =
+ OLDXLIB = -loldX
+
+ DEPXTOOLLIB = $(USRLIBDIR)/libXt.sa.$(SOXTREV)
+ XTOOLLIB = -lXt
+
+ DEPXAWLIB = $(USRLIBDIR)/libXaw.sa.$(SOXAWREV)
+ XAWLIB = -lXaw
+
+ DEPXILIB =
+ XILIB = -lXi
+
+ DEPPEXLIB =
+ PEXLIB = -lPEX5
+
+ SOXLIBREV = 4.10
+ SOXTREV = 4.10
+ SOXAWREV = 5.0
+ SOOLDXREV = 4.10
+ SOXMUREV = 4.10
+ SOXEXTREV = 4.10
+ SOXINPUTREV = 4.10
+ SOPEXREV = 1.0
+
+ DEPXAUTHLIB = $(USRLIBDIR)/libXau.a
+ XAUTHLIB = -lXau
+ DEPXDMCPLIB = $(USRLIBDIR)/libXdmcp.a
+ XDMCPLIB = -lXdmcp
+
+ DEPPHIGSLIB = $(USRLIBDIR)/libphigs.a
+ PHIGSLIB = -lphigs
+
+ DEPXBSDLIB = $(USRLIBDIR)/libXbsd.a
+ XBSDLIB = -lXbsd
+
+ LINTEXTENSIONLIB = $(LINTLIBDIR)/llib-lXext.ln
+ LINTXLIB = $(LINTLIBDIR)/llib-lX11.ln
+ LINTXMU = $(LINTLIBDIR)/llib-lXmu.ln
+ LINTXTOOL = $(LINTLIBDIR)/llib-lXt.ln
+ LINTXAW = $(LINTLIBDIR)/llib-lXaw.ln
+ LINTXI = $(LINTLIBDIR)/llib-lXi.ln
+ LINTPEX = $(LINTLIBDIR)/llib-lPEX5.ln
+ LINTPHIGS = $(LINTLIBDIR)/llib-lphigs.ln
+
+ DEPLIBS = $(DEPXAWLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB)
+
+ DEPLIBS1 = $(DEPLIBS)
+ DEPLIBS2 = $(DEPLIBS)
+ DEPLIBS3 = $(DEPLIBS)
+
+# -------------------------------------------------------------------------
+# Imake rules for building libraries, programs, scripts, and data files
+# rules: $XConsortium: Imake.rules,v 1.123 91/09/16 20:12:16 rws Exp $
+
+# -------------------------------------------------------------------------
+# start of Imakefile
+
+# Copyright 1990-92 GROUPE BULL -- See licence conditions in file COPYRIGHT
+#
+# XPM Imakefile - Arnaud LE HORS
+#
+
+# $XConsortium: Library.tmpl,v 1.12 92/03/20 15:05:19 rws Exp $
+
+ CC = cc
+ CCOPTIONS =
+STD_DEFINES =
+CDEBUGFLAGS = -O
+
+ INCLUDES = -I.
+ INSTALLFLAGS = $(INSTINCFLAGS)
+ LINTLIBS = $(LINTXTOLL) $(LINTXLIB)
+
+OS_NAME_DEFINES =
+
+## if your system doesn't provide strcasecmp add -DNEED_STRCASECMP
+## if your system doesn't provide strdup add -DNEED_STRDUP
+## if your system doesn't provide pipe remove -DZPIPE
+DEFINES = -DZPIPE
+
+HEADERS = xpm.h
+ SRCS1 = data.c create.c misc.c rgb.c scan.c parse.c \
+ XpmWrFFrP.c XpmRdFToP.c XpmCrPFData.c XpmCrDataFP.c \
+ XpmWrFFrI.c XpmRdFToI.c XpmCrIFData.c XpmCrDataFI.c \
+ hashtable.c XpmRdFToData.c XpmWrFFrData.c
+ SRCS = $(SRCS1) sxpm.c
+ OBJS1 = data.o create.o misc.o rgb.o scan.o parse.o \
+ XpmWrFFrP.o XpmRdFToP.o XpmCrPFData.o XpmCrDataFP.o \
+ XpmWrFFrI.o XpmRdFToI.o XpmCrIFData.o XpmCrDataFI.o \
+ hashtable.o XpmRdFToData.o XpmWrFFrData.o
+ OBJS = sxpm.o
+
+.c.o:
+ $(RM) $@
+ $(CC) -c $(CFLAGS) $(_NOOP_) $*.c
+
+all:: libXpm.a
+
+libXpm.a: $(OBJS1)
+ $(RM) $@
+ $(AR) $@ $(OBJS1)
+ $(RANLIB) $@
+
+lintlib:: llib-lXpm.ln
+
+llib-lXpm.ln: $(SRCS1)
+ $(RM) $@
+ $(LINT) $(LINTLIBFLAG)Xpm $(LINTFLAGS) $(SRCS1)
+
+install:: libXpm.a
+ @if [ -d $(DESTDIR)$(USRLIBDIR) ]; then set +x; \
+ else (set -x; $(MKDIRHIER) $(DESTDIR)$(USRLIBDIR)); fi
+ $(INSTALL) -c $(INSTLIBFLAGS) libXpm.a $(DESTDIR)$(USRLIBDIR)
+ $(RANLIB) $(RANLIBINSTFLAGS) $(DESTDIR)$(USRLIBDIR)/libXpm.a
+
+install.ln:: llib-lXpm.ln
+ @if [ -d $(DESTDIR)$(LINTLIBDIR) ]; then set +x; \
+ else (set -x; $(MKDIRHIER) $(DESTDIR)$(LINTLIBDIR)); fi
+ $(INSTALL) -c $(INSTLIBFLAGS) llib-lXpm.ln $(DESTDIR)$(LINTLIBDIR)
+
+install:: $(HEADERS)
+ @if [ -d $(DESTDIR)$(INCDIR) ]; then set +x; \
+ else (set -x; $(MKDIRHIER) $(DESTDIR)$(INCDIR)); fi
+ @case '${MFLAGS}' in *[i]*) set +e;; esac; \
+ for i in $(HEADERS); do \
+ (set -x; $(INSTALL) -c $(INSTALLFLAGS) $$i $(DESTDIR)$(INCDIR)); \
+ done
+
+depend::
+ $(DEPEND) $(DEPENDFLAGS) -s "# DO NOT DELETE" -- $(ALLDEFINES) -- $(SRCS)
+
+lint:
+ $(LINT) $(LINTFLAGS) $(SRCS1) $(LINTLIBS)
+lint1:
+ $(LINT) $(LINTFLAGS) $(FILE) $(LINTLIBS)
+
+ DEPLIBS = libXpm.a $(DEPXTOOLLIB) $(DEPXLIB)
+LOCAL_LIBRARIES = libXpm.a $(XTOOLLIB) $(XLIB)
+
+ PROGRAM = sxpm
+
+all:: sxpm
+
+sxpm: $(OBJS) $(DEPLIBS)
+ $(RM) $@
+ $(CC) -o $@ $(OBJS) $(LDOPTIONS) $(LOCAL_LIBRARIES) $(LDLIBS) $(EXTRA_LOAD_FLAGS)
+
+saber_sxpm:: $(SRCS)
+ # load $(ALLDEFINES) $(SRCS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+osaber_sxpm:: $(OBJS)
+ # load $(ALLDEFINES) $(OBJS) $(LOCAL_LIBRARIES) $(SYS_LIBRARIES) $(EXTRA_LIBRARIES)
+
+install:: sxpm
+ @if [ -d $(DESTDIR)$(BINDIR) ]; then set +x; \
+ else (set -x; $(MKDIRHIER) $(DESTDIR)$(BINDIR)); fi
+ $(INSTALL) -c $(INSTPGMFLAGS) sxpm $(DESTDIR)$(BINDIR)
+
+install.man:: sxpm.man
+ @if [ -d $(DESTDIR)$(MANDIR) ]; then set +x; \
+ else (set -x; $(MKDIRHIER) $(DESTDIR)$(MANDIR)); fi
+ $(INSTALL) -c $(INSTMANFLAGS) sxpm.man $(DESTDIR)$(MANDIR)/sxpm.$(MANSUFFIX)
+
+depend::
+ $(DEPEND) $(DEPENDFLAGS) -s "# DO NOT DELETE" -- $(ALLDEFINES) -- $(SRCS)
+
+lint:
+ $(LINT) $(LINTFLAGS) $(SRCS) $(LINTLIBS)
+lint1:
+ $(LINT) $(LINTFLAGS) $(FILE) $(LINTLIBS)
+
+clean::
+ $(RM) $(PROGRAM)
+
+clean::
+ $(RM) sxpmout.xpm
+
+# -------------------------------------------------------------------------
+# common rules for all Makefiles - do not edit
+
+emptyrule::
+
+clean::
+ $(RM_CMD) "#"*
+
+Makefile::
+ -@if [ -f Makefile ]; then set -x; \
+ $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \
+ else exit 0; fi
+ $(IMAKE_CMD) -DTOPDIR=$(TOP) -DCURDIR=$(CURRENT_DIR)
+
+tags::
+ $(TAGS) -w *.[ch]
+ $(TAGS) -xw *.[ch] > TAGS
+
+saber:
+ # load $(ALLDEFINES) $(SRCS)
+
+osaber:
+ # load $(ALLDEFINES) $(OBJS)
+
+# -------------------------------------------------------------------------
+# empty rules for directories that do not have SUBDIRS - do not edit
+
+install::
+ @echo "install in $(CURRENT_DIR) done"
+
+install.man::
+ @echo "install.man in $(CURRENT_DIR) done"
+
+Makefiles::
+
+includes::
+
+# -------------------------------------------------------------------------
+# dependencies generated by makedepend
+
diff --git a/src/xpm/doc/Makefile.noXtree b/src/xpm/doc/Makefile.noXtree
new file mode 100644
index 0000000..1119883
--- /dev/null
+++ b/src/xpm/doc/Makefile.noXtree
@@ -0,0 +1,85 @@
+# Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT
+#
+# XPM Makefile - Arnaud LE HORS
+#
+
+AR = ar r
+CC = cc
+RANLIB = ranlib
+RM = rm -f
+# on sysV, define this as cp.
+INSTALL = install -c
+
+DVIPS = dvips
+
+CDEBUGFLAGS= -O
+
+# if your system doesn't provide strcasecmp add -DNEED_STRCASECMP
+# if your system doesn't provide strdup add -DNEED_STRDUP
+# if your system doesn't provide pipe remove -DZPIPE
+DEFINES = -DZPIPE
+
+DESTBINDIR=/usr/local/bin/X11
+DESTLIBDIR=/usr/local/lib/X11
+DESTINCLUDEDIR=$(DESTLIBDIR)/xpm-include
+MANDIR=/usr/man/manl
+
+LIBDIRS= -L/usr/lib/X11 -L.
+LIBS= -lXpm -lXext -lXt -lX11
+OBJS= data.o create.o misc.o rgb.o scan.o parse.o hashtable.o \
+ XpmWrFFrP.o XpmRdFToP.o XpmCrPFData.o XpmCrDataFP.o \
+ XpmWrFFrI.o XpmRdFToI.o XpmCrIFData.o XpmCrDataFI.o \
+ XpmRdFToData.o XpmWrFFrData.o
+
+CFLAGS= $(CDEBUGFLAGS) $(DEFINES)
+
+all: sxpm
+
+clean:
+ $(RM) *.o sxpm libXpm.a
+
+sxpm: libXpm.a sxpm.o
+ $(CC) $(CFLAGS) sxpm.o $(LIBDIRS) $(LIBS) -o sxpm
+
+libXpm.a: $(OBJS)
+ $(AR) libXpm.a $(OBJS)
+ $(RANLIB) libXpm.a
+
+install: install.lib install.sxpm install.man
+
+install.lib:
+ $(INSTALL) -m 0664 libXpm.a $(DESTLIBDIR)
+ cd $(DESTLIBDIR); $(RANLIB) libXpm.a
+ -mkdir $(DESTINCLUDEDIR)
+ -chmod ugo+rx $(DESTINCLUDEDIR)
+ $(INSTALL) -m 0444 xpm.h $(DESTINCLUDEDIR)
+
+install.sxpm:
+ $(INSTALL) -m 0755 sxpm $(DESTBINDIR)
+
+install.man:
+ $(INSTALL) -m 0644 sxpm.man $(MANDIR)/sxpm.l
+
+doc: xpm.ps
+
+xpm.ps: xpm.dvi
+ $(DVIPS) -o xpm.ps xpm
+
+xpm.dvi: xpm.tex
+ latex xpm
+ latex xpm
+
+print: xpm.ps
+ lpr xpm.ps
+
+# Other dependencies.
+scan.o: xpmP.h
+parse.o: xpmP.h
+data.o: xpmP.h
+create.o: xpmP.h
+free.o: xpmP.h
+rgb.o: xpmP.h
+XpmWrPixF.o: xpmP.h
+XpmRdPixF.o: xpmP.h
+XpmCrPFData.o: xpmP.h
+sxpm.o: xpm.h
diff --git a/src/xpm/doc/README b/src/xpm/doc/README
new file mode 100644
index 0000000..0807f5a
--- /dev/null
+++ b/src/xpm/doc/README
@@ -0,0 +1,176 @@
+** Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT **
+
+ XPM Version 3
+
+WHAT IS XPM?
+============
+
+XPM (X PixMap) is a format for storing/retrieving X pixmaps to/from files.
+
+Here is provided a library containing a set of four functions, similar to the
+X bitmap functions as defined in the Xlib: XpmCreatePixmapFromData,
+XpmCreateDataFromPixmap, XpmReadFileToPixmap and XpmWriteFileFromPixmap for
+respectively including, storing, reading and writing this format, plus four
+other: XpmCreateImageFromData, XpmCreateDataFromImage, XpmReadFileToImage and
+XpmWriteFileFromImage for working with images instead of pixmaps.
+
+This new version provides a C includable format, defaults for different types
+of display: monochrome/color/grayscale, hotspot coordinates and symbol names
+for colors for overriding default colors when creating the pixmap. It provides
+a mechanism for storing information while reading a file which is re-used
+while writing. This way comments, default colors and symbol names aren't lost.
+It also handles "transparent pixels" by returning a shape mask in addition to
+the created pixmap.
+
+See the XPM Manual for more details.
+
+HOW TO GET XPM?
+===============
+
+New xpm updates are announced on the comp.windows.x newsgroup, and on the
+"xpm-talk" list. All new "official" xpm releases can be found by ftp on:
+
+ export.lcs.mit.edu (18.30.0.238) contrib (Boston, USA)
+ avahi.inria.fr (192.5.60.47) pub (Sophia Antipolis, France)
+
+
+DOCUMENTATION:
+=============
+
+Old users might read the CHANGES file for a history of changes interesting
+the user.
+
+Read the docs (xpm.tex is the manual in LaTeX form). The documentation is in
+LaTeX format (IMPORTANT: see the Makefile to know how to print it. The LaTeX
+source should work with most dvi2ps or dvips programs. I use myself Tomas
+Rokicki's dvips v5.0 that you can get by anonymous ftp on
+labrea.stanford.edu). We can mail you a PostScript version of the
+documentation if you are not able to print it, or you can grab one on the ftp
+servers.
+
+INSTALLATION:
+============
+
+To obtain the XPM library, first uncompress and untar the compressed tar file
+in an approriate directory.
+
+Then you can either compile xpm via "imake" or in a stand-alone way.
+
+WITH IMAKE:
+
+ The Imakefile is provided. You should know how to use imake to build
+ the XPM Makefile, by executing "xmkmf" then do:
+
+ make depend
+ make
+
+ which will build the XPM library and sxpm application.
+ Then do:
+
+ make install
+ make install.man
+
+ which will install the library and the sxpm man page.
+
+ If it fails, you may edit the Imakefile to add compilation flags to
+ suit your machine.
+
+WITHOUT IMAKE:
+
+ To compile xpm, in the xpm directory you just created, do:
+
+ make -f Makefile.noXtree
+
+ Then to install it, do:
+
+ make -f Makefile.noXtree install
+
+NOTE: if you compile with gcc, use "gcc -traditional", otherwise you will
+ have compilation warnings (but the code will work Ok)
+
+SXPM:
+====
+
+In addition to the library the sxpm tool is provided to show XPM file and
+convert them from XPM2 to XPM version 3. If you have previously done 'make' or
+'make all' you should have it yet, otherwise just do:
+
+ make sxpm
+
+This application shows you most of the features of XPM and its source can be
+used to quickly see how to use the provided functions
+
+By executing 'sxpm' without any option you will get the usage.
+
+Executing 'sxpm -plaid' will show a demo of the XpmCreatePixmapFromData
+function. The pixmap is created from the static variable plaid defined in the
+sxpm.c file. Sxpm will end when you press the key Q in the created window.
+
+Executing 'sxpm -plaid -s lines_in_mix blue' will show the feature of
+overriding color symbols giving a colorname, and executing 'sxpm -p
+lines_in_mix 1' will show overriding giving pixel value.
+
+Then you should try 'sxpm -plaid -o output' to get an output file using the
+XpmWriteFileFromPixmap function.
+
+You can now try 'sxpm -plaid -o - -nod -rgb /usr/lib/X11/rgb.txt' to directly
+get the pixmap printed out on the standard output with colornames instead of
+rgb values.
+
+Then you should try 'sxpm plaid.xpm' to use the XpmReadFileToPixmap function,
+and 'cat plaid_mask.xpm|sxpm' to see how "transparent pixels" are handled.
+
+The XpmCreatePixmapFromData function is on purpose called without any Xpminfo
+pointer to show the utility of this one. Indeed, compare the color section of
+the two files foo and bar obtained from 'sxpm -nod -plaid -o foo' and
+'sxpm -nod plaid.xpm -o bar'.
+
+To end look at plaid_ext.xpm and try "sxpm -nod plaid_ext.xpm -v" to see how
+extensions are handled.
+
+Of course, other combinations are allowed and should be tried. Thus, 'sxpm
+plaid.xpm -o output -nod' will show you how to convert a file from XPM2 to a
+XPM version 3 using sxpm.
+
+See the manual page for more detail.
+
+CONVERTERS:
+==========
+
+In the converters directory you can find different converters about XPM.
+There is a perl script xpm1to3.pl to convert XPM1 format file to XPM version
+3. And there are files to build the converters ppmtoxpm and xpmtoppm; to get
+instructions about how to build them you should read the corresponding
+ppm.README file.
+
+KNOWN BUG:
+=========
+
+If two symbols get the same color pixel when reading a pixmap, one will be
+lost when writting it out.
+
+DISCUSSION:
+==========
+
+There is a mailing list to discuss about XPM which is xpm-talk@sophia.inria.fr.
+Any request to subscribe should be sent to xpm-talk-request@sophia.inria.fr.
+
+COPYRIGHT:
+==========
+
+ Copyright 1990-92 GROUPE BULL --
+ See license conditions in the COPYRIGHT file of the XPM distribution
+
+Please mail any bug reports or modifications done, comments, suggestions,
+requests for updates or patches to port on another machine to:
+
+lehors@sophia.inria.fr (INTERNET)
+
+33 (FRANCE) 93.65.77.71 (VOICE PHONE)
+
+Arnaud Le Hors (SURFACE MAIL)
+Bull c/o Inria BP. 109
+2004, Route des lucioles
+Sophia Antipolis
+06561 Valbonne Cedex
+FRANCE
diff --git a/src/xpm/doc/colas.sty b/src/xpm/doc/colas.sty
new file mode 100644
index 0000000..799e405
--- /dev/null
+++ b/src/xpm/doc/colas.sty
@@ -0,0 +1,294 @@
+% my add-on LaTeX macros
+% to be used like in:
+% \documentstyle[12pt,gwm]{report}
+
+% postscript inclusion:
+\def\texpsfig#1#2#3
+{\vbox{\kern #3pt\hbox{\special{psfile=#1}\kern #2pt}}\typeout{(#1)}}
+
+% RCS version stripping
+\def\RCSRevNum#1Revision: #2 ${#2}
+\def\RCSRevVersion#1Version: #2 ${#2}
+
+\newlength{\colaslength}
+\newlength{\colaslengthh}
+\newlength{\colasmargin}
+
+\def\exemplefont{\footnotesize}
+\def\usagefont{\large}
+\def\usageupspace{\vspace{0.1mm}}
+\newcommand{\Description}
+ {\list{}{\leftmargin 4cm \labelsep 0.1cm \labelwidth 3.9cm}}
+
+\def\descriptionlabel#1{\bf #1\hspace\labelsep\hfil}
+\def\description
+ {\list{}{\leftmargin 2.4cm \labelsep 0.1cm \labelwidth 2.3cm
+ \let\makelabel\descriptionlabel}}
+
+\def\upspace{\vspace{-2mm}}
+\def\undertablespace{\vspace{-3mm}}
+
+\def\Item#1#2{\upspace\pagebreak[1]\section*{\hspace{-7pt}
+ {\large\tt#1}{\normalsize\sf\quad ---\quad #2}}\vspace{-0.3cm}}
+
+\def\ITEMa#1#2{
+ \Item{#1}{#2}\markright{#1}
+ \label{#1}}
+\def\ITEMb#1#2#3{
+ \Item{\vbox{\hbox{#1}\hbox{#2}}}{#3}\markright{#1}
+ \label{#1} \label{#2}}
+\def\ITEMbi#1#2#3{
+ \Item{\vbox{\hbox{#1}\hbox{#2}}}{#3}\markright{#1}
+ \label{#2}}
+\def\ITEMc#1#2#3#4{
+ \Item{\vbox{\hbox{#1}\hbox{#2}\hbox{#3}}}{#4}\markright{#1}
+ \label{#1}\label{#2} \label{#3}}
+\def\ITEMci#1#2#3#4{
+ \Item{\vbox{\hbox{#1}\hbox{#2}\hbox{#3}}}{#4}\markright{#1}
+ \label{#2}\label{#3}}
+\def\ITEMd#1#2#3#4#5{
+ \Item{\vbox{\hbox{#1}\hbox{#2}\hbox{#3}\hbox{#4}}}{#5}\markright{#1}
+ \label{#1}\label{#2}\label{#3}\label{#4}}
+\def\ITEMe#1#2#3#4#5#6{
+ \Item{
+ \vbox{\hbox{#1}\hbox{#2}\hbox{#3}\hbox{#4}\hbox{#5}}}{#6}\markright{#1}
+ \label{#1}\label{#2}\label{#3}\label{#4}\label{#5}}
+\def\ITEMf#1#2#3#4#5#6#7{
+ \Item{
+ \vbox{\hbox{#1}\hbox{#2}\hbox{#3}\hbox{#4}\hbox{#5}\hbox{#6}}}{#7}
+ \markright{#1}
+ \label{#1}\label{#2}\label{#3}\label{#4}\label{#5}\label{#6}}
+
+\newcommand{\context}[1]{
+ Context used:
+ \begin{center}\begin{tabular}{@{\tt}l@{\hspace{1cm}}@{\rm}p{7cm}}
+ \multicolumn{1}{c}{\bf Variable}&\multicolumn{1}{c}{\bf used for}\\
+ \hline \multicolumn{2}{l}{\undertablespace}\\
+ #1
+ \end{tabular}\end{center}}
+
+\newcommand{\contextdim}[2]{
+ \setlength{\colaslength}{7cm}
+ \addtolength{\colaslength}{#1}
+ Context used:
+ \begin{center}\begin{tabular}{@{\tt}l@{\hspace{1cm}}@{\rm}p{\colaslength}}
+ \multicolumn{1}{c}{\bf Variable}&\multicolumn{1}{c}{\bf used for}\\
+ \hline \multicolumn{2}{l}{\undertablespace}\\
+ #2
+ \end{tabular}\end{center}}
+
+\newcommand{\desctable}[3]{
+ \begin{center}\begin{tabular}{@{\bf}l@{\hspace{1cm}}@{\rm}p{7cm}}
+ \multicolumn{1}{c}{\bf #1}&\multicolumn{1}{c}{\bf #2}\\
+ \hline \multicolumn{2}{l}{\undertablespace}\\
+ #3
+ \end{tabular}\end{center}}
+
+\newcommand{\desctabledim}[4]{
+ \setlength{\colaslength}{7cm}
+ \addtolength{\colaslength}{#1}
+ \begin{center}\begin{tabular}{@{\bf}l@{\hspace{1cm}}@{\rm}p{\colaslength}}
+ \multicolumn{1}{c}{\bf #2}&\multicolumn{1}{c}{\bf #3}\\
+ \hline \multicolumn{2}{l}{\undertablespace}\\
+ #4
+ \end{tabular}\end{center}}
+
+\newcommand{\exemples}[2]{
+ #1{\exemplefont
+ \begin{center}\begin{tabular}{@{\tt}l@{\hspace{1cm}}@{\rm}p{5cm}}
+ #2
+ \end{tabular}\end{center}}}
+
+\newcommand{\exemplesdim}[3]{
+ \setlength{\colaslength}{5cm}
+ \addtolength{\colaslength}{#1}
+ #2{\exemplefont
+ \begin{center}\begin{tabular}{@{\tt}l@{\hspace{1cm}}@{\rm}p{\colaslength}}
+ #3
+ \end{tabular}\end{center}}}
+
+\newcommand{\usagetype}[1]{{\sl #1}\vspace{0.2cm}}
+\newcommand{\usagetyped}[2]{{\sl #1}\quad{\it (#2)}\vspace{0.2cm}}
+\newcommand{\see}[1]{{\tt #1}}
+\newcommand{\seep}[1]{{\tt #1}, p~\pageref{#1}}
+\newcommand{\seensp}[1]{{\tt #1} (see p~\pageref{#1})}
+\newcommand{\seesnp}[1]{(see {\tt #1}, p~\pageref{#1})}
+\newcommand{\seeref}[1]{{\tt #1} (see \ref{#1}, p~\pageref{#1})}
+\newcommand{\seesp}[1]{(see \ref{#1}, p~\pageref{#1})}
+
+\def\smalldesc#1#2#3{#1&#3&#2\\}
+\newcommand{\bigdesc}[2]{
+ \setlength{\colaslength}{300pt}
+ \settowidth{\colaslengthh}{{\tt #1}}
+ \addtolength{\colaslength}{-\colaslengthh}
+ \begin{center}\begin{tabular}
+ {@{\tt}l@{\hspace{0.5cm}}@{\sf}p{\colaslength}@{\hspace{0.4cm}}@{\bf}r}
+ \multicolumn{1}{c}{\bf Object}&\multicolumn{1}{c}{\bf Description}&{\bf p}\\
+ \hline \multicolumn{3}{l}{\undertablespace}\\
+ #2
+ \end{tabular}\end{center}}
+
+\newcommand{\desc}[4]{
+ \setlength{\colaslength}{250pt}
+ \settowidth{\colaslengthh}{{\tt #1}}
+ \addtolength{\colaslength}{-\colaslengthh}
+ \begin{center}\begin{tabular}
+{@{\tt}l@{\hspace{0.5cm}}@{\sf}p{\colaslength}}
+ \multicolumn{1}{c}{\bf #2}&\multicolumn{1}{c}{\bf #3}\\
+ \hline \multicolumn{2}{l}{\undertablespace}\\
+ #4
+ \end{tabular}\end{center}}
+
+\newcommand{\contextdimtt}[2]{
+ \setlength{\colaslength}{250pt}
+ \settowidth{\colaslengthh}{{\tt #1}}
+ \addtolength{\colaslength}{-\colaslengthh}
+ Context used:
+ \begin{center}\begin{tabular}{@{\tt}l@{\hspace{1cm}}@{\rm}p{\colaslength}}
+ \multicolumn{1}{c}{\bf Variable}&\multicolumn{1}{c}{\bf used for}\\
+ \hline \multicolumn{2}{l}{\undertablespace}\\
+ #2
+ \end{tabular}\end{center}}
+
+\def\itemtt#1{\item[{\tt #1}]}
+\def\itemit#1{\item[{\it #1}]}
+
+
+% SIZE of page
+%=============
+
+\def\fullpage{\if@twoside \oddsidemargin 35pt \evensidemargin -8pt
+\marginparsep 10pt \marginparpush 10pt \marginparwidth 10pt
+\else \oddsidemargin 0pt \evensidemargin 0pt
+\marginparwidth 30pt\fi
+\textwidth 450pt \setlength{\colasmargin}{0pt}
+\def\colaspm{\hspace{0pt}}\def\colasmm{\hspace{0pt}}
+\def\colassmm{\hspace{0pt}}\def\colastitledisp{\hspace{0pt}}
+}
+\def\mediumpage{\if@twoside \oddsidemargin 75pt \evensidemargin 32pt
+\marginparsep 10pt \marginparpush 10pt \marginparwidth 40pt
+\else \oddsidemargin 43pt \evensidemargin 63pt
+\marginparwidth 30pt\fi
+\textwidth 410pt \setlength{\colasmargin}{0pt}
+\def\colaspm{\hspace{40pt}}\def\colasmm{\hspace{-40pt}}
+\def\colassmm{\hspace{-20pt}}\def\colastitledisp{\hspace{-45pt}}
+}
+\def\smallpage{\if@twoside \oddsidemargin 135pt \evensidemargin 92pt
+\marginparsep 10pt \marginparpush 10pt \marginparwidth 80pt
+\else \oddsidemargin 123pt \evensidemargin 123pt
+\marginparwidth 30pt \fi
+\textwidth 350pt
+\setlength{\colasmargin}{100pt}
+\def\colaspm{\hspace{100pt}}\def\colasmm{\hspace{-100pt}}
+\def\colassmm{\hspace{-60pt}}\def\colastitledisp{\hspace{-75pt}}
+}
+
+\smallpage
+\topmargin -30pt \headheight 12pt \headsep 25pt \footheight 12pt \footskip
+30pt
+\textheight 680pt \columnsep 10pt \columnseprule 0pt
+\footnotesep 12pt \skip\footins 6pt plus 2pt minus 2pt
+\floatsep 12pt plus 2pt minus 2pt \textfloatsep 20pt plus 2pt minus 4pt
+\intextsep 12pt plus 2pt minus 2pt \@maxsep 20pt \dblfloatsep 12pt plus 2pt
+minus 2pt \dbltextfloatsep 20pt plus 2pt minus 4pt \@dblmaxsep 20pt
+\@fptop 0pt plus 1fil \@fpsep 8pt plus 2fil \@fpbot 0pt plus 1fil
+\@dblfptop 0pt plus 1fil \@dblfpsep 8pt plus 2fil \@dblfpbot 0pt plus 1fil
+
+\parskip 5pt plus 1pt \parindent 0pt \topsep 2pt plus 1pt minus 1pt
+\partopsep 0pt plus 1pt minus 1pt \itemsep 2pt plus 1pt minus 1pt
+
+\reversemarginpar
+\@mparswitchfalse
+
+%% abbrevs
+
+\def\GWM{\sc Gwm}
+\def\WOOL{\sc Wool}
+
+%% fonts
+\def\Huge{\@setsize\Huge{30pt}\xxvpt\@xxvpt}
+
+%% chapter
+
+\def\@makechapterhead#1{ \vspace*{1pt} { \parindent 0pt \raggedright
+ \Huge\bf \colasmm
+ \ifnum \c@secnumdepth >\m@ne \thechapter \quad \fi
+ #1\par
+ \nobreak \vskip 20pt
+ \colasmm{\vbox{\hbox{\vrule height 5pt width450pt depth -3pt}
+ \vspace*{-1.1cm}
+ \hbox{\vrule height 0.0pt width450pt depth 0.4pt}}}
+ \nobreak \vskip 50pt \nobreak } }
+
+\def\@makeschapterhead#1{ \vspace*{1pt} { \parindent 0pt \raggedright
+ \Huge \bf \colasmm #1\par
+ \nobreak \vskip 80pt } }
+
+\def\chapter{\clearpage \thispagestyle{pagenum} \global\@topnum\z@
+\@afterindentfalse \secdef\@chapter\@schapter}
+\def\@chapter[#1]#2{\ifnum \c@secnumdepth >\m@ne
+ \refstepcounter{chapter}
+ \typeout{\@chapapp\space\thechapter.}
+ \addcontentsline{toc}{chapter}{\protect
+ \numberline{\thechapter}#1}\else
+ \addcontentsline{toc}{chapter}{#1}\fi
+ \chaptermark{#1}
+ \addtocontents{lof}{\protect\addvspace{10pt}}
+\addtocontents{lot}{\protect\addvspace{10pt}} \if@twocolumn
+\@topnewpage[\@makechapterhead{#2}]
+ \else \@makechapterhead{#2}
+ \@afterheading \fi}
+\def\@schapter#1{\if@twocolumn \@topnewpage[\@makeschapterhead{#1}]
+ \else \@makeschapterhead{#1}
+ \@afterheading\fi}
+
+%% sections
+
+\def\section{\@startsection {section}{1}{\z@}{-3.5ex plus -1ex minus
+ -.2ex}{2.3ex plus .2ex}{\Large\bf\colasmm}}
+\def\subsection{\@startsection{subsection}{2}{\z@}{-3.25ex plus -1ex minus
+ -.2ex}{1.5ex plus .2ex}{\large\bf\colassmm}}
+\def\subsubsection{\@startsection{subsubsection}{3}{\z@}{-3.25ex plus
+-1ex minus -.2ex}{1.5ex plus .2ex}{\normalsize\bf}}
+\def\paragraph{\@startsection
+ {paragraph}{4}{\z@}{3.25ex plus 1ex minus .2ex}{-1em}{\normalsize\bf}}
+\def\subparagraph{\@startsection
+ {subparagraph}{4}{\parindent}{3.25ex plus 1ex minus
+ .2ex}{-1em}{\normalsize\bf}}
+
+%% headings
+
+\if@twoside \def\ps@headings{\def\@oddfoot{}
+\def\@evenfoot{}\def\@evenhead{
+\colasmm\makebox[0pt][l]{\vrule height-4pt width450pt depth4.3pt}
+\bf\thepage\hfill \sl \leftmark}
+\def\@oddhead{
+\colasmm\makebox[0pt][l]{\vrule height-4pt width450pt depth4.3pt}
+\sl \rightmark \hfill\bf\thepage}
+\def\chaptermark##1{\markboth {\uppercase{\ifnum \c@secnumdepth
+>\m@ne
+ \@chapapp\ \thechapter. \ \fi ##1}}{}}\def\sectionmark##1{\markright
+{\uppercase{\ifnum \c@secnumdepth >\z@
+ \thesection. \ \fi ##1}}}}
+\else \def\ps@headings{\def\@oddfoot{}\def\@evenfoot{}\def\@oddhead{\hbox
+{}\sl \rightmark \hfill \rm\thepage}\def\chaptermark##1{\markright
+{\uppercase{\ifnum \c@secnumdepth >\m@ne
+ \@chapapp\ \thechapter. \ \fi ##1}}}}
+\fi
+
+\if@twoside \def\ps@pagenum{\def\@oddfoot{}
+\def\@evenfoot{}\def\@evenhead{
+\colasmm\bf\thepage\hfill}
+\def\@oddhead{
+\colasmm\hfill\bf\thepage}
+\def\chaptermark##1{\markboth {\uppercase{\ifnum \c@secnumdepth
+>\m@ne
+ \@chapapp\ \thechapter. \ \fi ##1}}{}}\def\sectionmark##1{\markright
+{\uppercase{\ifnum \c@secnumdepth >\z@
+ \thesection. \ \fi ##1}}}}
+\else \def\ps@pagenum{\def\@oddfoot{}\def\@evenfoot{}\def\@oddhead{\hbox
+{}\hfil \bf\thepage}\def\chaptermark##1{\markright
+{\uppercase{\ifnum \c@secnumdepth >\m@ne
+ \@chapapp\ \thechapter. \ \fi ##1}}}}
+\fi
+
diff --git a/src/xpm/doc/name-3.0b-3.0c b/src/xpm/doc/name-3.0b-3.0c
new file mode 100644
index 0000000..04c687b
--- /dev/null
+++ b/src/xpm/doc/name-3.0b-3.0c
@@ -0,0 +1,48 @@
+s/^XCreatePixmapFromData$/XpmCreatePixmapFromData/g
+s/^XCreatePixmapFromData\([^a-zA-Z_]\)/XpmCreatePixmapFromData\1/g
+s/\([^a-zA-Z_]\)XCreatePixmapFromData$/\1XpmCreatePixmapFromData/g
+s/\([^a-zA-Z_]\)XCreatePixmapFromData\([^a-zA-Z_]\)/\1XpmCreatePixmapFromData\2/g
+s/^XCreateDataFromPixmap$/XpmCreateDataFromPixmap/g
+s/^XCreateDataFromPixmap\([^a-zA-Z_]\)/XpmCreateDataFromPixmap\1/g
+s/\([^a-zA-Z_]\)XCreateDataFromPixmap$/\1XpmCreateDataFromPixmap/g
+s/\([^a-zA-Z_]\)XCreateDataFromPixmap\([^a-zA-Z_]\)/\1XpmCreateDataFromPixmap\2/g
+s/^XReadPixmapFile$/XpmReadPixmapFile/g
+s/^XReadPixmapFile\([^a-zA-Z_]\)/XpmReadPixmapFile\1/g
+s/\([^a-zA-Z_]\)XReadPixmapFile$/\1XpmReadPixmapFile/g
+s/\([^a-zA-Z_]\)XReadPixmapFile\([^a-zA-Z_]\)/\1XpmReadPixmapFile\2/g
+s/^XWritePixmapFile$/XpmWritePixmapFile/g
+s/^XWritePixmapFile\([^a-zA-Z_]\)/XpmWritePixmapFile\1/g
+s/\([^a-zA-Z_]\)XWritePixmapFile$/\1XpmWritePixmapFile/g
+s/\([^a-zA-Z_]\)XWritePixmapFile\([^a-zA-Z_]\)/\1XpmWritePixmapFile\2/g
+s/^XFreeXpmAttributes$/XpmFreeAttributes/g
+s/^XFreeXpmAttributes\([^a-zA-Z_]\)/XpmFreeAttributes\1/g
+s/\([^a-zA-Z_]\)XFreeXpmAttributes$/\1XpmFreeAttributes/g
+s/\([^a-zA-Z_]\)XFreeXpmAttributes\([^a-zA-Z_]\)/\1XpmFreeAttributes\2/g
+s/^PixmapColorError$/XpmPixmapColorError/g
+s/^PixmapColorError\([^a-zA-Z_]\)/XpmPixmapColorError\1/g
+s/\([^a-zA-Z_]\)PixmapColorError$/\1XpmPixmapColorError/g
+s/\([^a-zA-Z_]\)PixmapColorError\([^a-zA-Z_]\)/\1XpmPixmapColorError\2/g
+s/^PixmapSuccess$/XpmPixmapSuccess/g
+s/^PixmapSuccess\([^a-zA-Z_]\)/XpmPixmapSuccess\1/g
+s/\([^a-zA-Z_]\)PixmapSuccess$/\1XpmPixmapSuccess/g
+s/\([^a-zA-Z_]\)PixmapSuccess\([^a-zA-Z_]\)/\1XpmPixmapSuccess\2/g
+s/^PixmapOpenFailed$/XpmPixmapOpenFailed/g
+s/^PixmapOpenFailed\([^a-zA-Z_]\)/XpmPixmapOpenFailed\1/g
+s/\([^a-zA-Z_]\)PixmapOpenFailed$/\1XpmPixmapOpenFailed/g
+s/\([^a-zA-Z_]\)PixmapOpenFailed\([^a-zA-Z_]\)/\1XpmPixmapOpenFailed\2/g
+s/^PixmapFileInvalid$/XpmPixmapFileInvalid/g
+s/^PixmapFileInvalid\([^a-zA-Z_]\)/XpmPixmapFileInvalid\1/g
+s/\([^a-zA-Z_]\)PixmapFileInvalid$/\1XpmPixmapFileInvalid/g
+s/\([^a-zA-Z_]\)PixmapFileInvalid\([^a-zA-Z_]\)/\1XpmPixmapFileInvalid\2/g
+s/^PixmapNoMemory$/XpmPixmapNoMemory/g
+s/^PixmapNoMemory\([^a-zA-Z_]\)/XpmPixmapNoMemory\1/g
+s/\([^a-zA-Z_]\)PixmapNoMemory$/\1XpmPixmapNoMemory/g
+s/\([^a-zA-Z_]\)PixmapNoMemory\([^a-zA-Z_]\)/\1XpmPixmapNoMemory\2/g
+s/^PixmapColorFailed$/XpmPixmapColorFailed/g
+s/^PixmapColorFailed\([^a-zA-Z_]\)/XpmPixmapColorFailed\1/g
+s/\([^a-zA-Z_]\)PixmapColorFailed$/\1XpmPixmapColorFailed/g
+s/\([^a-zA-Z_]\)PixmapColorFailed\([^a-zA-Z_]\)/\1XpmPixmapColorFailed\2/g
+s/^ColorSymbol$/XpmColorSymbol/g
+s/^ColorSymbol\([^a-zA-Z_]\)/XpmColorSymbol\1/g
+s/\([^a-zA-Z_]\)ColorSymbol$/\1XpmColorSymbol/g
+s/\([^a-zA-Z_]\)ColorSymbol\([^a-zA-Z_]\)/\1XpmColorSymbol\2/g
diff --git a/src/xpm/doc/name-3.0c-3.0 b/src/xpm/doc/name-3.0c-3.0
new file mode 100644
index 0000000..3187d46
--- /dev/null
+++ b/src/xpm/doc/name-3.0c-3.0
@@ -0,0 +1,32 @@
+s/^XpmPixmapColorError$/XpmColorError/g
+s/^XpmPixmapColorError\([^a-zA-Z_]\)/XpmColorError\1/g
+s/\([^a-zA-Z_]\)XpmPixmapColorError$/\1XpmColorError/g
+s/\([^a-zA-Z_]\)XpmPixmapColorError\([^a-zA-Z_]\)/\1XpmColorError\2/g
+s/^XpmPixmapSuccess$/XpmSuccess/g
+s/^XpmPixmapSuccess\([^a-zA-Z_]\)/XpmSuccess\1/g
+s/\([^a-zA-Z_]\)XpmPixmapSuccess$/\1XpmSuccess/g
+s/\([^a-zA-Z_]\)XpmPixmapSuccess\([^a-zA-Z_]\)/\1XpmSuccess\2/g
+s/^XpmPixmapOpenFailed$/XpmOpenFailed/g
+s/^XpmPixmapOpenFailed\([^a-zA-Z_]\)/XpmOpenFailed\1/g
+s/\([^a-zA-Z_]\)XpmPixmapOpenFailed$/\1XpmOpenFailed/g
+s/\([^a-zA-Z_]\)XpmPixmapOpenFailed\([^a-zA-Z_]\)/\1XpmOpenFailed\2/g
+s/^XpmPixmapFileInvalid$/XpmFileInvalid/g
+s/^XpmPixmapFileInvalid\([^a-zA-Z_]\)/XpmFileInvalid\1/g
+s/\([^a-zA-Z_]\)XpmPixmapFileInvalid$/\1XpmFileInvalid/g
+s/\([^a-zA-Z_]\)XpmPixmapFileInvalid\([^a-zA-Z_]\)/\1XpmFileInvalid\2/g
+s/^XpmPixmapNoMemory$/XpmNoMemory/g
+s/^XpmPixmapNoMemory\([^a-zA-Z_]\)/XpmNoMemory\1/g
+s/\([^a-zA-Z_]\)XpmPixmapNoMemory$/\1XpmNoMemory/g
+s/\([^a-zA-Z_]\)XpmPixmapNoMemory\([^a-zA-Z_]\)/\1XpmNoMemory\2/g
+s/^XpmPixmapColorFailed$/XpmColorFailed/g
+s/^XpmPixmapColorFailed\([^a-zA-Z_]\)/XpmColorFailed\1/g
+s/\([^a-zA-Z_]\)XpmPixmapColorFailed$/\1XpmColorFailed/g
+s/\([^a-zA-Z_]\)XpmPixmapColorFailed\([^a-zA-Z_]\)/\1XpmColorFailed\2/g
+s/^XpmReadPixmapFile$/XpmReadFileToPixmap/g
+s/^XpmReadPixmapFile\([^a-zA-Z_]\)/XpmReadFileToPixmap\1/g
+s/\([^a-zA-Z_]\)XpmReadPixmapFile$/\1XpmReadFileToPixmap/g
+s/\([^a-zA-Z_]\)XpmReadPixmapFile\([^a-zA-Z_]\)/\1XpmReadFileToPixmap\2/g
+s/^XpmWritePixmapFile$/XpmWriteFileFromPixmap/g
+s/^XpmWritePixmapFile\([^a-zA-Z_]\)/XpmWriteFileFromPixmap\1/g
+s/\([^a-zA-Z_]\)XpmWritePixmapFile$/\1XpmWriteFileFromPixmap/g
+s/\([^a-zA-Z_]\)XpmWritePixmapFile\([^a-zA-Z_]\)/\1XpmWriteFileFromPixmap\2/g
diff --git a/src/xpm/doc/plaid.xpm b/src/xpm/doc/plaid.xpm
new file mode 100644
index 0000000..b0e9200
--- /dev/null
+++ b/src/xpm/doc/plaid.xpm
@@ -0,0 +1,34 @@
+/* XPM */
+static char * plaid[] = {
+/* plaid pixmap
+ * width height ncolors chars_per_pixel */
+"22 22 4 2 ",
+/* colors */
+" c red m white s light_color ",
+"Y c green m black s lines_in_mix ",
+"+ c yellow m white s lines_in_dark ",
+"x m black s dark_color ",
+/* pixels */
+"x x x x x x x x x x x x + x x x x x ",
+" x x x x x x x x x x x x x x x x ",
+"x x x x x x x x x x x x + x x x x x ",
+" x x x x x x x x x x x x x x x x ",
+"x x x x x x x x x x x x + x x x x x ",
+"Y Y Y Y Y x Y Y Y Y Y + x + x + x + x + x + ",
+"x x x x x x x x x x x x + x x x x x ",
+" x x x x x x x x x x x x x x x x ",
+"x x x x x x x x x x x x + x x x x x ",
+" x x x x x x x x x x x x x x x x ",
+"x x x x x x x x x x x x + x x x x x ",
+" x x x x Y x x x ",
+" x x x Y x x ",
+" x x x x Y x x x ",
+" x x x Y x x ",
+" x x x x Y x x x ",
+"x x x x x x x x x x x x x x x x x x x x x x ",
+" x x x x Y x x x ",
+" x x x Y x x ",
+" x x x x Y x x x ",
+" x x x Y x x ",
+" x x x x Y x x x "
+} ;
diff --git a/src/xpm/doc/plaid_mask.xpm b/src/xpm/doc/plaid_mask.xpm
new file mode 100644
index 0000000..167d338
--- /dev/null
+++ b/src/xpm/doc/plaid_mask.xpm
@@ -0,0 +1,35 @@
+/* XPM */
+static char * plaid[] = {
+/* plaid pixmap
+ * width height ncolors chars_per_pixel */
+"22 22 5 2",
+/* colors */
+". c red m white s light_color ",
+"Y c green m black s lines_in_mix ",
+"+ c yellow m white s lines_in_dark ",
+"x m black s dark_color ",
+" c none s mask ",
+/* pixels */
+" x x x x x + x x x x x ",
+" . x x x x x x x x x x x ",
+" . x x x x x x + x x x x x ",
+" . x . x x x x x x x x x x x ",
+" . x . x x x x x x + x x x x x ",
+" Y Y Y Y Y + x + x + x + x + x + ",
+" x x . x . x x x x x x + x x x x x ",
+" . x . x . x . x x x x x x x x x x x ",
+" . x x x . x . x x x x x x + x x x x x ",
+" . x . x . x . x . x x x x x x x x x x x ",
+" . x . x x x . x . x x x x x x + x x x x x ",
+". . . . . x . . . . . x . x . x Y x . x . x ",
+". . . . . x . . . . . . x . x . Y . x . x . ",
+". . . . . x . . . . . x . x . x Y x . x . x ",
+". . . . . x . . . . . . x . x . Y . x . x . ",
+". . . . . x . . . . . x . x . x Y x . x . x ",
+"x x x x x x x x x x x x x x x x x x x x x x ",
+". . . . . x . . . . . x . x . x Y x . x . x ",
+". . . . . x . . . . . . x . x . Y . x . x . ",
+". . . . . x . . . . . x . x . x Y x . x . x ",
+". . . . . x . . . . . . x . x . Y . x . x . ",
+". . . . . x . . . . . x . x . x Y x . x . x "
+} ;
diff --git a/src/xpm/doc/xpm.tex b/src/xpm/doc/xpm.tex
new file mode 100644
index 0000000..7614e89
--- /dev/null
+++ b/src/xpm/doc/xpm.tex
@@ -0,0 +1,849 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% XPM MANUAL %
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% adjust these for centering on the page:
+% upper-left corner of frame in title page must be at 60mm,60mm from
+% upper-left corner of the page
+
+% normal (A4) on our Apple Laserwriter with dvi2ps
+%\hoffset 0cm
+%\voffset 0cm
+% normal (A4 & Letter) on our Apple Laserwriter with dvips v5.0
+\hoffset -5.5mm
+\voffset 0cm
+% our imagen
+%\hoffset -0.9cm
+%\voffset -2.2cm
+
+% NOTE: the following line MUST be commented out!
+%\includeonly{standard}
+
+\makeindex
+
+\documentstyle[twoside,colas]{article}
+
+% IF YOUR DVI PRINTER CHOKES ON INCLUDED POSTSCRIPT FILES
+% by the \special command, uncomment the following line:
+% \def\texpsfig#1#2#3{\fbox{Figure ``#1''}}
+
+
+\pagestyle{headings}
+\begin{document}
+
+\thispagestyle{empty}
+\
+\hbox{\colastitledisp
+\vbox{
+\vspace{3cm}
+\begin{center}
+\fboxrule 0.4pt \fboxsep 1pt
+\fbox{\fboxrule 3pt \fboxsep 30pt \fbox{\Huge\bf XPM Manual}}
+\end{center}
+\vspace{2cm}
+\begin{center}
+\huge
+The {\bf X} {\bf P}ix{\bf M}ap Format
+\end{center}
+\vspace{2cm}
+\begin{center}
+\Large Version \RCSRevVersion$Version: 3.2c $\\
+\end{center}
+\vspace{2cm}
+\begin{center}
+\LARGE\sf Arnaud Le Hors\\
+\large\tt lehors@sophia.inria.fr
+\end{center}
+\vspace{1cm}
+\vspace{1cm}
+\begin{center}
+\copyright BULL 1990-92
+\end{center}
+}}
+
+\newpage
+
+\section*{Copyright restrictions}
+{\bf\begin{flushleft}
+Copyright 1990-92 GROUPE BULL\\
+\end{flushleft}}
+
+{\sf
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted, provided
+that the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of GROUPE BULL not be used in advertising
+or publicity pertaining to distribution of the software without specific,
+written prior permission. GROUPE BULL makes no representations about the
+suitability of this software for any purpose. It is provided ``as is''
+without express or implied warranty.
+
+GROUPE BULL disclaims all warranties with regard to this software,
+including all implied warranties of merchantability and fitness,
+in no event shall GROUPE BULL be liable for any special,
+indirect or consequential damages or any damages
+whatsoever resulting from loss of use, data or profits,
+whether in an action of contract, negligence or other tortious
+action, arising out of or in connection with the use
+or performance of this software.
+}
+
+\section*{Acknowledgements}
+
+I want to thank my team partner and friend Colas Nahaboo who proposed me this
+project, and who actively participates to its design. I also want to thank all
+the users who help me to improve the library by giving feed back and sending
+bug reports.
+
+\begin{flushright}
+{\Large Arnaud Le Hors.\quad}
+{\small
+KOALA Project -- BULL Research c/o INRIA\\
+2004 route des Lucioles -- 06565 Valbonne Cedex -- FRANCE\\
+}
+\end{flushright}
+
+\section*{Support}
+
+\sloppy
+You can mail any question or suggestion relative to {\bf XPM} by electronic
+mail to {\tt lehors@sophia.inria.fr}. There is also a mailing list, please
+mail requests to {\tt xpm-talk-request@sophia.inria.fr} to subscribe. You can
+find the latest release by anonymous ftp on avahi.inria.fr (138.96.24.30) or
+export.lcs.mit.edu (18.30.0.238), and also an archive of the mailing list on
+avahi.
+
+
+\newpage
+\section{Introduction}
+First, Why another image format? We (Koala team at Bull Research, France)
+felt that most images bundled with X applications will be small "icons", and
+that since many applications are color-customizable, existing image formats
+such as gif, tiff, iff, etc... were intended for big images with well-defined
+colors and so weren't adapted to the task. So {\bf XPM} was designed with
+these criterions in mind:
+\begin{itemize}
+\item be editable by hand (under emacs, vi...). Color pixmap editors aren't
+available everywhere.
+\item be includable in C code. It is unreasonable to load
+1000 pixmap files on each start of an application.
+\item be a portable, mailable ascii format.
+\item provide defaults for monochrome/color/grayscale renderings.
+\item provide overriding of colors. This way if the user wants your application
+to be bluish instead of greenish, you can use the SAME icon files.
+\item allow comments to be included in the file.
+\item compression must be managed apart of the format.
+\end{itemize}
+
+\newpage
+\section{The {\bf XPM} Format}
+
+The {\bf XPM} format presents a C syntax, in order to provide the ability to
+include {\bf XPM} files in C and C++ programs. It is in fact an array of
+strings composed of six different sections as follows:
+{\tt
+\begin{quote}
+/* XPM */
+static char* {\tt <variable\_name>}[] = \{
+
+<Values>
+
+<Colors>
+
+<Pixels>
+
+<Extensions>
+
+\};
+\end{quote}
+}
+
+The words are separated by a white space which can be composed of space and
+tabulation characters.
+
+The {\tt <Values>} section is a string containing four or six integers in base
+10 that correspond to: the pixmap width and height, the number of colors, the
+number of characters per pixel (so there is no limit on the number of colors),
+and, optionally the hotspot coordinates and the {\bf XPMEXT} tag if there is
+any extension following the {\tt <Pixels>} section.
+
+{\tt <width> <height> <ncolors> <cpp> [<x\_hotspot> <y\_hotspot>] [XPMEXT]}
+
+The {\tt Colors} section contains as many strings as there are colors, and
+each string is as follows:
+
+{\tt <chars> \{<key> <color>\}+}
+
+Where {\tt <chars>} is the {\tt <chars\_per\_pixel>} length string (not
+surrounded by anything) representing the pixels, {\tt <color>} is the
+specified color, and {\tt <key>} is a keyword describing in which context this
+color should be used. Currently the keys may have the following values:
+
+\begin{tabbing}
+\hspace{1cm}\= g4 \= for 4-level grayscale\kill
+\> m \>for mono visual\\
+\> s \> for symbolic name\\
+\> g4 \> for 4-level grayscale\\
+\> g \> for grayscale with more than 4 levels\\
+\> c \> for color visual
+\end{tabbing}
+
+Colors can be specified by giving the colorname, a \# foolwed by the RGB code,
+or a \% followed by the HSV code. The symbolic name provides the ability of
+specifying the colors at load time and not to hard-code them in the file.
+Also the string {\bf None} can be given as a colorname to mean
+``transparent''. Transparency is handled by providing a masking bitmap in
+addition to the pixmap.
+
+The {\tt <Pixels>} section is composed by {\tt <height>} strings of {\tt
+<width>} * {\tt <chars\_per\_pixel>} characters, where every {\tt
+<chars\_per\_pixel>} length string must be one of the previously defined
+groups in the {\tt <Colors>} section.
+
+Then follows the {\tt <Extensions>} section which must be labeled, if not
+empty, in the {\tt <Values>} section as previously described.
+This section may be composed by several {\tt <Extension>} subsections which
+may be of two types:
+
+\begin{itemize}
+\item[] one stand alone string composed as follows:
+
+{\tt XPMEXT <extension-name> <extension-data>}
+
+\item[] or a block composed by several strings:
+
+{\tt XPMEXT <extension-name>}
+
+{\tt <related extension-data composed of several strings>}
+
+\end{itemize}
+
+Finally, if not empty, this section must end by the following string:
+
+{\tt XPMENDEXT}
+
+To avoid possible conflicts with extension names in shared files, they should
+be prefixed by the name of the company. This would ensure unicity.
+
+\vspace{0.5cm}
+Below is an example which is the XPM file of a plaid pixmap. This is a 22x22
+pixmap, with 4 colors and 2 characters per pixel. The hotspot coordinates are
+(0, 0). There are symbols and default colors for color and monochrome visuals.
+Finally there are two extensions.
+
+{\small \begin{verbatim}
+
+/* XPM */
+static char * plaid[] = {
+/* plaid pixmap
+ * width height ncolors chars_per_pixel */
+"22 22 4 2 0 0 XPMEXT",
+/* colors */
+" c red m white s light_color ",
+"Y c green m black s lines_in_mix ",
+"+ c yellow m white s lines_in_dark ",
+"x m black s dark_color ",
+/* pixels */
+"x x x x x x x x x x x x + x x x x x ",
+" x x x x x x x x x x x x x x x x ",
+"x x x x x x x x x x x x + x x x x x ",
+" x x x x x x x x x x x x x x x x ",
+"x x x x x x x x x x x x + x x x x x ",
+"Y Y Y Y Y x Y Y Y Y Y + x + x + x + x + x + ",
+"x x x x x x x x x x x x + x x x x x ",
+" x x x x x x x x x x x x x x x x ",
+"x x x x x x x x x x x x + x x x x x ",
+" x x x x x x x x x x x x x x x x ",
+"x x x x x x x x x x x x + x x x x x ",
+" x x x x Y x x x ",
+" x x x Y x x ",
+" x x x x Y x x x ",
+" x x x Y x x ",
+" x x x x Y x x x ",
+"x x x x x x x x x x x x x x x x x x x x x x ",
+" x x x x Y x x x ",
+" x x x Y x x ",
+" x x x x Y x x x ",
+" x x x Y x x ",
+" x x x x Y x x x "
+"XPMEXT ext1 data1",
+"XPMEXT ext2",
+"data2_1",
+"data2_2",
+"XPMENDEXT"
+};
+
+\end{verbatim}}
+
+\newpage
+\section{The {\bf XPM} Library}
+
+The XPM library provides a set of Xlib-level functions which allows to deal
+with images, pixmaps, XPM file, and data (included XPM file) in many ways.
+This section describes these functions and how to use them.
+
+\vspace{.5cm}
+To provide a simple interface all these functions take, in addition to their
+main arguments such as the display, a structure called {\bf XpmAttributes}.
+This structure may be considered as composed of two different groups of
+members. The first one is composed of attributes to pass data such as colormap
+and visual and attributes to retrieve returned data such as pixmap's width and
+height. The second group provides a way to rewrite an {\bf XPM} file without
+losing information such as comments, color defaults and symbolic names which
+may exist in the original file (i.e. the {\bf XpmInfo} structure in {\bf XPM 2}).
+The {\bf XpmAttributes} structure is defined as follows:
+
+{\small \begin{tabbing}
+
+\hspace{1cm}\= XpmColorSymbol *colorsymbols; \=/* List of color symbols */\kill
+typedef struct \{ \\
+\> unsigned long valuemask; \>/* Specifies which attributes are defined */\\
+\\
+\> Visual *visual; \>/* Specifies the visual to use */ \\
+\> Colormap colormap; \>/* Specifies the colormap to use */ \\
+\> unsigned int depth; \>/* Specifies the depth */ \\
+\> unsigned int width; \>/* Returns the width of the created pixmap */\\
+\> unsigned int height; \>/* Returns the height of the created pixmap */\\
+\> unsigned int x\_hotspot; \>/* Returns the x hotspot's coordinate */\\
+\> unsigned int y\_hotspot; \>/* Returns the y hotspot's coordinate */ \\
+\> unsigned int cpp; \>/* Specifies the number of char per pixel */ \\
+\> Pixel *pixels; \>/* List of used color pixels */ \\
+\> unsigned int npixels; \>/* Number of pixels */\\
+\> XpmColorSymbol *colorsymbols;\>/* Array of color symbols to override */ \\
+\> unsigned int numsymbols; \>/* Number of symbols */ \\
+\> char *rgb\_fname; \>/* RGB text file name */ \\
+\> unsigned int nextensions; \>/* Number of extensions */ \\
+\> XpmExtension *extensions; \>/* Array of extensions */ \\
+\\
+\> /* Infos */ \\
+\> int ncolors; \>/* Number of colors */ \\
+\> char ***colorTable; \>/* Color table pointer */ \\
+\> char *hints\_cmt; \>/* Comment of the hints section */ \\
+\> char *colors\_cmt; \>/* Comment of the colors section */ \\
+\> char *pixels\_cmt; \>/* Comment of the pixels section */ \\
+\> unsigned int mask\_pixel; \>/* Transparent pixel's color table index */\\
+\\
+\> /* Color Allocation Directives */ \\
+\> unsigned int exactColors; \>/* Only use exact colors for visual */ \\
+\> unsigned int closeness; \>/* Allowable RGB deviation */ \\
+\\
+\} XpmAttributes;
+
+\end{tabbing}}
+
+The valuemask is the bitwise inclusive OR of the valid attribute mask bits. If
+the valuemask is zero, the attributes are ignored and not referenced. And
+default values are taken for needed attributes which are not specified.
+
+The colorTable is a two dimensional array of strings, organized as follows:
+\begin{flushleft}
+\hspace{.5cm}colorTable[color\#][0] points to the character string associated
+to the color.\\
+\hspace{.5cm}colorTable[color\#][1] points to the symbolic name of the color.\\
+\hspace{.5cm}colorTable[color\#][2] points to the default color for monochrome
+visuals.\\
+\hspace{.5cm}colorTable[color\#][3] points to the default color for 4-level
+grayscale visuals.\\
+\hspace{.5cm}colorTable[color\#][4] points to the default color for other
+grayscale visuals.\\
+\hspace{.5cm}colorTable[color\#][5] points to the default color for color
+visuals.
+\end{flushleft}
+
+Comments are limited to a single comment string by section. If more exist in
+the read file, then only the last comment of each section will be stored.
+
+To get information back while writing out to a file, you just have to set
+the mask bits {\bf XpmReturnInfos} to the valuemask of an {\bf XpmAttributes}
+structure that you pass to the {\bf XpmReadFileToPixmap} function while reading
+the file, and then give the structure back to the {\bf XpmWriteFileFromPixmap}
+function while writing.
+
+\vspace{.5cm}
+To allow overriding of colors at load time the {\bf XPM} library defines the
+{\bf XpmColorSymbol} structure which contains:
+
+\begin{tabbing}
+\hspace{1cm}\= char *value; \hspace{1.5cm}\= /* Color value */\kill
+typedef struct \{\\
+\> char *name; \> /* Symbolic color name */\\
+\> char *value;\> /* Color value */\\
+\> Pixel pixel;\> /* Color pixel */\\
+\} XpmColorSymbol;
+\end{tabbing}
+
+To override default colors at load time, you just have to pass, via the {\bf
+XpmAttributes} structure, a list of {\bf XpmColorSymbol} elements containing
+the desired colors to the {\bf XpmReadFileToPixmap} or {\bf
+XpmCreatePixmapFromData} {\bf XPM} functions. These colors can be specified by
+giving the color name in the value member or directly by giving the
+corresponding pixel in the pixel member. In the latter case the value member
+must be set to {\bf NULL} otherwise the given pixel will not be considered.
+
+In addition, is is possible to set the pixel for a specific color {\bf value}
+at load time by setting the color name to NULL, and setting the value and pixel
+fields appropriately. For example, by setting the color name to NULL, the
+value to ``red'' and the pixel to 51, all symbolic colors that are assigned to
+``red'' will be set to pixel 51. It is even possible to specify the pixel used
+for the transparent color ``none'' when no mask is required.
+
+\vspace{.5cm}
+To pass and retrieve extension data use the {\bf XpmExtension} structure which
+is defined below:
+
+\begin{tabbing}
+\hspace{1cm}\= unsigned int nlines; \hspace{1cm}\= /* */ \kill
+typedef struct \{ \\
+\> char *name; \> /* name of the extension */ \\
+\> unsigned int nlines; \> /* number of lines in this extension */ \\
+\> char **lines; \> /* pointer to the extension array of strings */ \\
+\} XpmExtension;
+\end{tabbing}
+
+To retrieve possible extension data stored in an {\bf XPM} file or data, you
+must set the mask bits {\bf XpmReturnExtensions} to the valuemask of an {\bf
+XpmAttributes} structure that you pass to the read function you use. Then the
+same structure may be passed the same way to any write function if you set the
+mask bits {\bf XpmExtensions} to the valuemask.
+
+\vspace{.5cm}
+To create a pixmap from an {\bf XPM} file, use {\bf XpmReadFileToPixmap}.
+
+\begin{flushleft}
+
+int XpmReadFileToPixmap({\it display, d, filename, \\
+\hspace{3cm}pixmap\_return, shapemask\_return, attributes})\\
+
+\hspace{1cm}Display {\it *display;}\\
+\hspace{1cm}Drawable {\it d;}\\
+\hspace{1cm}char {\it *filename;}\\
+\hspace{1cm}Pixmap {\it *pixmap\_return;}\\
+\hspace{1cm}Pixmap {\it *shapemask\_return;}\\
+\hspace{1cm}XpmAttributes {\it *attributes;}
+
+\end{flushleft}
+
+\begin{description}
+
+\itemit{display} Specifies the connection to the X server.
+\itemit{d} Specifies which screen the pixmap is created on.
+\itemit{filename} Specifies the file name to use.
+\itemit{pixmap\_return} Returns the pixmap which is created.
+\itemit{shapemask\_return} Returns the shapemask which is created, if any.
+\itemit{attributes} Specifies the location of an {\bf XpmAttributes} structure
+to get and store information.
+
+\end{description}
+
+The {\bf XpmReadFileToPixmap} function reads in a file containing a pixmap in
+the {\bf XPM} format. If the file cannot be opened, {\bf XpmReadFileToPixmap}
+returns {\bf XpmOpenFailed}. If the file can be opened but does not
+contain valid {\bf XPM} pixmap data, it returns {\bf XpmFileInvalid}. If
+insufficient working storage is allocated, it returns {\bf XpmNoMemory}.
+
+If the passed {\bf XpmAttributes} structure pointer is not {\bf NULL}, {\bf
+XpmReadFileToPixmap} looks for the following attributes: {\bf XpmVisual}, {\bf
+XpmColormap}, {\bf XpmDepth}, {\bf XpmColorSymbols}, {\bf XpmExactColors},
+{\bf XpmCloseness}, {\bf XpmReturnPixels}, {\bf XpmReturnExtensions},
+{\bf XpmReturnInfos}, and sets the {\bf XpmSize} and possibly the
+{\bf XpmHotspot} attributes when returning.
+
+{\bf XpmReadFileToPixmap} allocates colors, as read from the file or possibly
+overridden as specified in the {\bf XpmColorSymbols} attributes. The colors
+are allocated dependently on the type of visual and on the default colors. If
+no default value exits for the specified visual, it first looks for other
+defaults nearer to the monochrome visual type and secondly nearer to the color
+visual type. If the color which is found is not valid (cannot parse it), it
+looks for another default one according to the same algorithm.
+
+If allocating a color fails, and the {\bf closeness} attribute is set, it
+tries to find a color already in the colormap that is closest to the desired
+color, and uses that. If no color can be found that is within {\bf closeness}
+of the Red, Green and Blue components of the desired color, it reverts to
+trying other default values as explained above.
+
+The RGB Components are integers within the range 0 (black) to 65535 (white).
+A closeness of less than 10000, for example, will cause only quite close colors
+to be matched, while a closeness of more than 50000 will allow quite
+dissimilar colors to match. Specifying a closeness of more than 65535 will
+allow any color to match, thus forcing the icon to be drawn in color no matter
+how bad the colormap is. The value 40000 seems to be about right for many
+situations requiring reasonable but not perfect matches. With this setting the
+color must only be within the same general area of the RGB cube as the desired
+color.
+
+If the {\bf exactColors} attribute is set it then returns {\bf XpmColorError},
+otherwise it creates the pixmap and returns XpmSuccess. If no color is found,
+and no close color exists or is wanted, and all visuals have been exhausted,
+{\bf XpmColorFailed} is returned.
+
+{\bf XpmReadFileToPixmap} returns the created pixmap to pixmap\_return if not
+{\bf NULL} and possibly the created shapemask to shapemask\_return if not
+{\bf NULL}. If required it stores into the {\bf XpmAttributes} structure the
+list of the used pixels and possible comments, color defaults and symbols.
+When finished the caller must free the pixmaps using {\bf XFreePixmap}, the
+colors using {\bf XFreeColors}, and possibly the data returned into the
+{\bf XpmAttributes} using {\bf XpmFreeAttributes}.
+
+In addition on system which support such features {\bf XpmReadFileToPixmap}
+deals with compressed files by forking an uncompress process and reading from
+the piped result. It assumes that the specified file is compressed if the
+given file name ends by .Z. In case the file name does not end so, {\bf
+XpmReadFileToPixmap} first looks for a file of which the name is the given one
+followed by .Z; then if such a file does not exist, it looks for the given
+file (assumed as not compressed). And if instead of a file name {\bf NULL} is
+passed to {\bf XpmReadFileToPixmap}, it reads from the standard input.
+
+\vspace{.5cm}
+To write out a pixmap to an {\bf XPM} file, use {\bf XpmWriteFileFromPixmap}.
+
+\begin{flushleft}
+
+int XpmWriteFileFromPixmap({\it display, filename, pixmap, shapemask,\\
+\hspace{3cm}attributes})\\
+
+\hspace{1cm}Display {\it *display;}\\
+\hspace{1cm}char {\it *filename;}\\
+\hspace{1cm}Pixmap {\it pixmap;}\\
+\hspace{1cm}Pixmap {\it shapemask;}\\
+\hspace{1cm}XpmAttributes {\it *attributes;}
+
+\end{flushleft}
+
+\begin{description}
+
+\itemit{display} Specifies the connection to the X server.
+\itemit{filename} Specifies the file name to use.
+\itemit{pixmap} Specifies the pixmap.
+\itemit{shapemask} Specifies the shape mask pixmap.
+\itemit{attributes} Specifies the location of an {\bf XpmAttributes} structure
+containing information.
+
+\end{description}
+
+The {\bf XpmWriteFileFromPixmap} function writes a pixmap and its possible
+shapemask out to a file in the {\bf XPM} format. If the file cannot be opened,
+it returns {\bf XpmOpenFailed}. If insufficient working storage is
+allocated, it returns {\bf XpmNoMemory}. If no error occurs then it
+returns {\bf XpmSuccess}.
+
+If the passed {\bf XpmAttributes} structure pointer is not {\bf NULL}, {\bf
+XpmWriteFileFromPixmap} look for the following attributes: {\bf XpmColormap},
+{\bf XpmSize}, {\bf XpmHotspot}, {\bf XpmCharsPerPixel}, {\bf XpmRgbFilename},
+{\bf XpmInfos} and {\bf XpmExtensions}.
+
+If the {\bf XpmSize} attributes are not defined {\bf XpmWriteFileFromPixmap}
+performs an {\bf XGetGeometry} operation. If the filename contains an
+extension such as ``.xpm'' it is cut off when writing out to the pixmap
+variable name. If the {\bf XpmInfos} attributes are defined it writes out
+possible stored information such as comments, color defaults and symbol.
+Finally if the {\bf XpmRgbFilename} attribute is defined, {\bf
+XpmWriteFileFromPixmap} searches for color names in this file and if found
+writes them out instead of the rgb values.
+
+In addition on system which support such features if the given file name ends
+by .Z it is assumed to be a compressed file. Then, {\bf XpmWriteFileFromPixmap}
+writes to a piped compress process. And if instead of a file name {\bf NULL}
+is passed to {\bf XpmWriteFileFromPixmap}, it writes to the standard output.
+
+\vspace{.5cm}
+To create a pixmap from an {\bf XPM} file directly included in a program, use
+{\bf XpmCreatePixmapFromData}.
+
+\begin{flushleft}
+
+int XpmCreatePixmapFromData({\it display, d, data, \\
+\hspace{3cm}pixmap\_return, shapemask\_return, attributes})\\
+
+\hspace{1cm}Display {\it *display;}\\
+\hspace{1cm}Drawable {\it d;}\\
+\hspace{1cm}char {\it **data;}\\
+\hspace{1cm}Pixmap {\it *pixmap\_return;}\\
+\hspace{1cm}Pixmap {\it *shapemask\_return;}\\
+\hspace{1cm}XpmAttributes {\it *attributes;}
+
+\end{flushleft}
+
+\begin{description}
+
+\itemit{display} Specifies the connection to the X server.
+\itemit{d} Specifies which screen the pixmap is created on.
+\itemit{data} Specifies the location of the pixmap data.
+\itemit{pixmap\_return} Returns the pixmap which is created.
+\itemit{shapemask\_return} Returns the shape mask pixmap which is created if
+any.
+\itemit{attributes} Specifies the location of an {\bf XpmAttributes} structure
+to get and store information, or {\bf NULL}.
+
+\end{description}
+
+The {\bf XpmCreatePixmapFromData} function allows you to include in your C
+program an {\bf XPM} pixmap file which was written out by {\bf
+XpmWriteFileFromPixmap} without reading in the pixmap file.
+
+{\bf XpmCreatePixmapFromData} exactly works as {\bf
+Xpm\-Read\-File\-To\-Pixmap} does and returns the same way. It just reads data
+instead of a file. Here again, it is the caller's responsibility to free the
+pixmaps, the colors and possibly the data returned into the {\bf
+XpmAttributes} structure.
+
+\vspace{.5cm}
+In some cases, one may want to create an {\bf XPM} data from a pixmap in order
+to be able to create a pixmap from this data using the {\bf
+XpmCreatePixmapFromData} function later on. To do so use {\bf
+XpmCreateDataFromPixmap}.
+
+\begin{flushleft}
+
+int XpmCreateDataFromPixmap({\it display, data\_return, pixmap, shapemask,\\
+\hspace{3cm}attributes})\\
+
+\hspace{1cm}Display {\it *display;}\\
+\hspace{1cm}char {\it ***data\_return;}\\
+\hspace{1cm}Pixmap {\it pixmap;}\\
+\hspace{1cm}Pixmap {\it shapemask;}\\
+\hspace{1cm}XpmAttributes {\it *attributes;}
+
+\end{flushleft}
+
+\begin{description}
+
+\itemit{display} Specifies the connection to the X server.
+\itemit{data\_return} Returns the data which is created.
+\itemit{pixmap} Specifies the pixmap.
+\itemit{shapemask} Specifies the shape mask pixmap.
+\itemit{attributes} Specifies the location of an {\bf XpmAttributes} structure
+containing information.
+
+\end{description}
+
+The {\bf XpmCreateDataFromPixmap} function exactly works as {\bf
+Xpm\-Write\-File\-From\-Pixmap} does and returns the same way. It just writes
+to a single block malloc'ed data instead of to a file. It is the caller's
+responsibility to free the data when finished.
+
+\vspace{.5cm}
+To do the same than the four functions described above do but with images
+instead of pixmaps use the functions {\bf XpmReadFileToImage}, {\bf
+XpmWriteFileFromImage}, {\bf XpmCreateImageFromData}, {\bf
+XpmCreateDataFromImage}.
+
+\vspace{.2cm}
+{\bf XpmReadFileToImage} creates an image from an {\bf XPM} file.
+
+\begin{flushleft}
+
+int XpmReadFileToImage({\it display, filename, \\
+\hspace{3cm}image\_return, shapeimage\_return, attributes})\\
+
+\hspace{1cm}Display {\it *display;}\\
+\hspace{1cm}char {\it *filename;}\\
+\hspace{1cm}XImage {\it **image\_return;}\\
+\hspace{1cm}XImage {\it **shapeimage\_return;}\\
+\hspace{1cm}XpmAttributes {\it *attributes;}
+
+\end{flushleft}
+
+\begin{description}
+
+\itemit{display} Specifies the connection to the X server.
+\itemit{filename} Specifies the file name to use.
+\itemit{image\_return} Returns the image which is created.
+\itemit{shapeimage\_return} Returns the shape mask image which is created if
+any.
+\itemit{attributes} Specifies the location of an {\bf XpmAttributes} structure
+to get and store information.
+
+\end{description}
+
+\vspace{.5cm}
+{\bf XpmWriteFileFromImage} writes out an image to an {\bf XPM} file.
+
+\begin{flushleft}
+
+int XpmWriteFileFromImage({\it display, filename, image, shapeimage,\\
+\hspace{3cm}attributes})\\
+
+\hspace{1cm}Display {\it *display;}\\
+\hspace{1cm}char {\it *filename;}\\
+\hspace{1cm}XImage {\it *image;}\\
+\hspace{1cm}XImage {\it *shapeimage;}\\
+\hspace{1cm}XpmAttributes {\it *attributes;}
+
+\end{flushleft}
+
+\begin{description}
+
+\itemit{display} Specifies the connection to the X server.
+\itemit{filename} Specifies the file name to use.
+\itemit{image} Specifies the image.
+\itemit{shapeimage} Specifies the shape mask image.
+\itemit{attributes} Specifies the location of an {\bf XpmAttributes} structure
+containing information.
+
+\end{description}
+
+\vspace{.5cm}
+{\bf XpmCreateImageFromData} creates an image from an {\bf XPM} file directly included in a program.
+
+\begin{flushleft}
+
+int XpmCreateImageFromData({\it display, data, \\
+\hspace{3cm}image\_return, shapeimage\_return, attributes})\\
+
+\hspace{1cm}Display {\it *display;}\\
+\hspace{1cm}char {\it **data;}\\
+\hspace{1cm}XImage {\it **image\_return;}\\
+\hspace{1cm}XImage {\it **shapeimage\_return;}\\
+\hspace{1cm}XpmAttributes {\it *attributes;}
+
+\end{flushleft}
+
+\begin{description}
+
+\itemit{display} Specifies the connection to the X server.
+\itemit{data} Specifies the location of the image data.
+\itemit{image\_return} Returns the image which is created.
+\itemit{shapeimage\_return} Returns the shape mask image which is created if
+any.
+\itemit{attributes} Specifies the location of an {\bf XpmAttributes} structure
+to get and store information, or {\bf NULL}.
+
+\end{description}
+
+\vspace{.5cm}
+{\bf XpmCreateDataFromImage} creates an {\bf XPM} data from an image.
+
+\begin{flushleft}
+
+int XpmCreateDataFromImage({\it display, data\_return, image, shapeimage,\\
+\hspace{3cm}attributes})\\
+
+\hspace{1cm}Display {\it *display;}\\
+\hspace{1cm}char {\it ***data\_return;}\\
+\hspace{1cm}XImage {\it *image;}\\
+\hspace{1cm}XImage {\it *shapeimage;}\\
+\hspace{1cm}XpmAttributes {\it *attributes;}
+
+\end{flushleft}
+
+\begin{description}
+
+\itemit{display} Specifies the connection to the X server.
+\itemit{data\_return} Returns the data which is created.
+\itemit{image} Specifies the image.
+\itemit{shapeimage} Specifies the shape mask image.
+\itemit{attributes} Specifies the location of an {\bf XpmAttributes} structure
+containing information.
+
+\end{description}
+
+These four functions work exactly the same way than the four ones previously
+described.
+
+\vspace{.5cm}
+To directly tranform an {\bf XPM} file to and from an {\bf XPM} data
+array, without requiring an open X display, use {\bf
+XpmReadFileToData} and {\bf XpmWriteFileFromData}.
+
+\vspace{.2cm}
+{\bf XpmReadFileToData} allocates and fills an XPM data array from an {\bf XPM} file.
+
+\begin{flushleft}
+
+int XpmReadFileToData({\it filename, data\_return})\\
+
+\hspace{1cm}char {\it *filename;}\\
+\hspace{1cm}char {\it ***data\_return;}
+
+\end{flushleft}
+
+\begin{description}
+
+\itemit{filename} Specifies the file name to read.
+\itemit{data\_return} Returns the data array created.
+
+\end{description}
+
+\vspace{.5cm}
+{\bf XpmWriteFileFromData} writes an {\b XPM} data array to an {\bf XPM} file.
+
+\begin{flushleft}
+
+int XpmWriteFileFromData({\it filename, data})\\
+
+\hspace{1cm}char {\it *filename;}\\
+\hspace{1cm}char {\it **data;}
+
+\end{flushleft}
+
+\begin{description}
+
+\itemit{filename} Specifies the file name to write.
+\itemit{data} Specifies the {\b XPM} data array to read.
+
+\end{description}
+
+\vspace{.5cm}
+To free possible data stored into an {\bf XpmAttributes} structure use {\bf
+XpmFreeAttributes}.
+
+\begin{flushleft}
+
+int XpmFreeAttributes({\it attributes})\\
+
+\hspace{1cm}XpmAttributes {\it *attributes;}
+
+\end{flushleft}
+
+\begin{description}
+
+\itemit{attributes} Specifies the structure to free.
+
+\end{description}
+
+The {\bf XpmFreeAttributes} frees the structure members which have been
+malloc'ed: the pixels list and the infos members (comments strings and color
+table).
+
+\vspace{.5cm}
+To dynamically allocate an {\bf XpmAttributes} structure use the {\bf
+Xpm\-Attributes\-Size} function.
+
+\begin{flushleft}
+
+int XpmAttributesSize()
+
+\end{flushleft}
+
+The {\bf XpmAttributesSize} function provides application using dynamic
+libraries with a safe way to allocate and then refer to an {\bf XpmAttributes}
+structure, disregarding whether the {\bf XpmAttributes} structure size has
+changed or not since compiled.
+
+\vspace{.5cm}
+To free data possibly stored into an array of {\bf XpmExtension} use {\bf
+XpmFreeExtensions}.
+
+\begin{flushleft}
+
+int XpmFreeExtensions({\it extensions, nextensions})\\
+
+\hspace{1cm}XpmExtension {\it *extensions;}\\
+\hspace{1cm}int {\it nextensions;}
+
+\end{flushleft}
+
+\begin{description}
+
+\itemit{extensions} Specifies the array to free.
+\itemit{nextensions} Specifies the number of extensions.
+
+\end{description}
+
+This function frees all data stored in every extension and the array itself.
+Note that {\bf XpmFreeAttributes} call this function and thus most of the time
+it should not need to be explicitly called.
+
+\end{document}
diff --git a/src/xpm/hashtable.c b/src/xpm/hashtable.c
new file mode 100644
index 0000000..e457e26
--- /dev/null
+++ b/src/xpm/hashtable.c
@@ -0,0 +1,205 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* hashtable.c: *
+* *
+* XPM library *
+* *
+* Developed by Arnaud Le Hors *
+* this originaly comes from Colas Nahaboo as a part of Wool *
+* *
+\*****************************************************************************/
+
+#include "xpmP.h"
+
+LFUNC(AtomMake, xpmHashAtom, (char *name, void *data));
+LFUNC(HashTableGrows, int, (xpmHashTable *table));
+
+static xpmHashAtom
+AtomMake(name, data) /* makes an atom */
+ char *name; /* WARNING: is just pointed to */
+ void *data;
+{
+ xpmHashAtom object = (xpmHashAtom) malloc(sizeof(struct _xpmHashAtom));
+ if (object) {
+ object->name = name;
+ object->data = data;
+ }
+ return object;
+}
+
+/************************\
+* *
+* hash table routines *
+* *
+\************************/
+
+/*
+ * Hash function definition:
+ * HASH_FUNCTION: hash function, hash = hashcode, hp = pointer on char,
+ * hash2 = temporary for hashcode.
+ * INITIAL_TABLE_SIZE in slots
+ * HASH_TABLE_GROWS how hash table grows.
+ */
+
+/* Mock lisp function */
+#define HASH_FUNCTION hash = (hash << 5) - hash + *hp++;
+/* #define INITIAL_HASH_SIZE 2017 */
+#define INITIAL_HASH_SIZE 256 /* should be enough for colors */
+#define HASH_TABLE_GROWS size = size * 2;
+
+/* aho-sethi-ullman's HPJ (sizes should be primes)*/
+#ifdef notdef
+#define HASH_FUNCTION hash <<= 4; hash += *hp++; \
+ if(hash2 = hash & 0xf0000000) hash ^= (hash2 >> 24) ^ hash2;
+#define INITIAL_HASH_SIZE 4095 /* should be 2^n - 1 */
+#define HASH_TABLE_GROWS size = size << 1 + 1;
+#endif
+
+/* GNU emacs function */
+/*
+#define HASH_FUNCTION hash = (hash << 3) + (hash >> 28) + *hp++;
+#define INITIAL_HASH_SIZE 2017
+#define HASH_TABLE_GROWS size = size * 2;
+*/
+
+/* end of hash functions */
+
+/*
+ * The hash table is used to store atoms via their NAME:
+ *
+ * NAME --hash--> ATOM |--name--> "foo"
+ * |--data--> any value which has to be stored
+ *
+ */
+
+/*
+ * xpmHashSlot gives the slot (pointer to xpmHashAtom) of a name
+ * (slot points to NULL if it is not defined)
+ *
+ */
+
+xpmHashAtom *
+xpmHashSlot(table, s)
+ xpmHashTable *table;
+ char *s;
+{
+ xpmHashAtom *atomTable = table->atomTable;
+ unsigned int hash, hash2;
+ xpmHashAtom *p;
+ char *hp = s;
+ char *ns;
+
+ hash = 0;
+ while (*hp) { /* computes hash function */
+ HASH_FUNCTION
+ }
+ p = atomTable + hash % table->size;
+ while (*p) {
+ ns = (*p)->name;
+ if (ns[0] == s[0] && strcmp(ns, s) == 0)
+ break;
+ p--;
+ if (p < atomTable)
+ p = atomTable + table->size - 1;
+ }
+ return p;
+}
+
+static int
+HashTableGrows(table)
+ xpmHashTable *table;
+{
+ xpmHashAtom *atomTable = table->atomTable;
+ int size = table->size;
+ xpmHashAtom *t, *p;
+ int i;
+ int oldSize = size;
+
+ t = atomTable;
+ HASH_TABLE_GROWS
+ table->size = size;
+ table->limit = size / 3;
+ atomTable = (xpmHashAtom *) malloc(size * sizeof(*atomTable));
+ if (!atomTable)
+ return (XpmNoMemory);
+ table->atomTable = atomTable;
+ for (p = atomTable + size; p > atomTable;)
+ *--p = NULL;
+ for (i = 0, p = t; i < oldSize; i++, p++)
+ if (*p) {
+ xpmHashAtom *ps = xpmHashSlot(table, (*p)->name);
+ *ps = *p;
+ }
+ free(t);
+ return (XpmSuccess);
+}
+
+/*
+ * xpmHashIntern(table, name, data)
+ * an xpmHashAtom is created if name doesn't exist, with the given data.
+ */
+
+int
+xpmHashIntern(table, tag, data)
+ xpmHashTable *table;
+ char *tag;
+ void *data;
+{
+ xpmHashAtom *slot;
+
+ if (!*(slot = xpmHashSlot(table, tag))) {
+ /* undefined, make a new atom with the given data */
+ if (!(*slot = AtomMake(tag, data)))
+ return (XpmNoMemory);
+ if (table->used >= table->limit) {
+ int ErrorStatus;
+ xpmHashAtom new = *slot;
+ if ((ErrorStatus = HashTableGrows(table)) != XpmSuccess)
+ return(ErrorStatus);
+ table->used++;
+ return (XpmSuccess);
+ }
+ table->used++;
+ }
+ return (XpmSuccess);
+}
+
+/*
+ * must be called before allocating any atom
+ */
+
+int
+xpmHashTableInit(table)
+ xpmHashTable *table;
+{
+ xpmHashAtom *p;
+ xpmHashAtom *atomTable;
+
+ table->size = INITIAL_HASH_SIZE;
+ table->limit = table->size / 3;
+ table->used = 0;
+ atomTable = (xpmHashAtom *) malloc(table->size * sizeof(*atomTable));
+ if (!atomTable)
+ return (XpmNoMemory);
+ for (p = atomTable + table->size; p > atomTable;)
+ *--p = NULL;
+ table->atomTable = atomTable;
+ return (XpmSuccess);
+}
+
+/*
+ * frees a hashtable and all the stored atoms
+ */
+
+void
+xpmHashTableFree(table)
+ xpmHashTable *table;
+{
+ xpmHashAtom *p;
+ xpmHashAtom *atomTable = table->atomTable;
+ for (p = atomTable + table->size; p > atomTable;)
+ if (*--p)
+ free(*p);
+ free(atomTable);
+ table->atomTable = NULL;
+}
diff --git a/src/xpm/misc.c b/src/xpm/misc.c
new file mode 100644
index 0000000..a34608c
--- /dev/null
+++ b/src/xpm/misc.c
@@ -0,0 +1,206 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* misc.c: *
+* *
+* XPM library *
+* Miscellaneous utilities *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+#include "xpmP.h"
+
+/*
+ * Free the computed color table
+ */
+
+xpmFreeColorTable(colorTable, ncolors)
+ char ***colorTable;
+ int ncolors;
+{
+ int a, b;
+ char ***ct, **cts;
+
+ if (colorTable) {
+ for (a = 0, ct = colorTable; a < ncolors; a++, ct++)
+ if (*ct) {
+ for (b = 0, cts = *ct; b <= NKEYS; b++, cts++)
+ if (*cts)
+ free(*cts);
+ free(*ct);
+ }
+ free(colorTable);
+ }
+}
+
+
+/*
+ * Intialize the xpmInternAttrib pointers to Null to know
+ * which ones must be freed later on.
+ */
+
+xpmInitInternAttrib(attrib)
+ xpmInternAttrib *attrib;
+{
+ attrib->ncolors = 0;
+ attrib->colorTable = NULL;
+ attrib->pixelindex = NULL;
+ attrib->xcolors = NULL;
+ attrib->colorStrings = NULL;
+ attrib->mask_pixel = UNDEF_PIXEL;
+}
+
+
+/*
+ * Free the xpmInternAttrib pointers which have been allocated
+ */
+
+xpmFreeInternAttrib(attrib)
+ xpmInternAttrib *attrib;
+{
+ unsigned int a, ncolors;
+ char **sptr;
+
+ if (attrib->colorTable)
+ xpmFreeColorTable(attrib->colorTable, attrib->ncolors);
+ if (attrib->pixelindex)
+ free(attrib->pixelindex);
+ if (attrib->xcolors)
+ free(attrib->xcolors);
+ if (attrib->colorStrings) {
+ ncolors = attrib->ncolors;
+ for (a = 0, sptr = attrib->colorStrings; a < ncolors; a++, sptr++)
+ if (*sptr)
+ free(*sptr);
+ free(attrib->colorStrings);
+ }
+}
+
+
+/*
+ * Free array of extensions
+ */
+XpmFreeExtensions(extensions, nextensions)
+ XpmExtension *extensions;
+ int nextensions;
+{
+ unsigned int i, j, nlines;
+ XpmExtension *ext;
+ char **sptr;
+
+ if (extensions) {
+ for (i = 0, ext = extensions; i < nextensions; i++, ext++) {
+ if (ext->name)
+ free(ext->name);
+ nlines = ext->nlines;
+ for (j = 0, sptr = ext->lines; j < nlines; j++, sptr++)
+ if (*sptr)
+ free(*sptr);
+ if (ext->lines)
+ free(ext->lines);
+ }
+ free(extensions);
+ }
+}
+
+
+/*
+ * Return the XpmAttributes structure size
+ */
+
+XpmAttributesSize()
+{
+ return sizeof(XpmAttributes);
+}
+
+
+/*
+ * Free the XpmAttributes structure members
+ * but the structure itself
+ */
+
+XpmFreeAttributes(attributes)
+ XpmAttributes *attributes;
+{
+ if (attributes) {
+ if (attributes->valuemask & XpmReturnPixels && attributes->pixels) {
+ free(attributes->pixels);
+ attributes->pixels = NULL;
+ attributes->npixels = 0;
+ }
+ if (attributes->valuemask & XpmInfos) {
+ if (attributes->colorTable) {
+ xpmFreeColorTable(attributes->colorTable, attributes->ncolors);
+ attributes->colorTable = NULL;
+ attributes->ncolors = 0;
+ }
+ if (attributes->hints_cmt) {
+ free(attributes->hints_cmt);
+ attributes->hints_cmt = NULL;
+ }
+ if (attributes->colors_cmt) {
+ free(attributes->colors_cmt);
+ attributes->colors_cmt = NULL;
+ }
+ if (attributes->pixels_cmt) {
+ free(attributes->pixels_cmt);
+ attributes->pixels_cmt = NULL;
+ }
+ if (attributes->pixels) {
+ free(attributes->pixels);
+ attributes->pixels = NULL;
+ }
+ }
+ if (attributes->valuemask & XpmReturnExtensions
+ && attributes->nextensions) {
+ XpmFreeExtensions(attributes->extensions, attributes->nextensions);
+ attributes->nextensions = 0;
+ attributes->extensions = NULL;
+ }
+ attributes->valuemask = 0;
+ }
+}
+
+
+/*
+ * Store into the XpmAttributes structure the required informations stored in
+ * the xpmInternAttrib structure.
+ */
+
+xpmSetAttributes(attrib, attributes)
+ xpmInternAttrib *attrib;
+ XpmAttributes *attributes;
+{
+ if (attributes) {
+ if (attributes->valuemask & XpmReturnInfos) {
+ attributes->cpp = attrib->cpp;
+ attributes->ncolors = attrib->ncolors;
+ attributes->colorTable = attrib->colorTable;
+
+ attrib->ncolors = 0;
+ attrib->colorTable = NULL;
+ }
+ attributes->width = attrib->width;
+ attributes->height = attrib->height;
+ attributes->valuemask |= XpmSize;
+ }
+}
+
+#ifdef NEED_STRDUP
+
+/*
+ * in case strdup is not provided by the system here is one
+ * which does the trick
+ */
+char *
+strdup (s1)
+ char *s1;
+{
+ char *s2;
+ int l = strlen(s1) + 1;
+ if (s2 = (char *) malloc(l))
+ strncpy(s2, s1, l);
+ return s2;
+}
+
+#endif
diff --git a/src/xpm/parse.c b/src/xpm/parse.c
new file mode 100644
index 0000000..560b719
--- /dev/null
+++ b/src/xpm/parse.c
@@ -0,0 +1,537 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* parse.c: *
+* *
+* XPM library *
+* Parse an XPM file or array and store the found informations *
+* in an an xpmInternAttrib structure which is returned. *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+
+#include "xpmP.h"
+#ifdef VMS
+#include "sys$library:ctype.h"
+#else
+#include <ctype.h>
+#endif
+
+LFUNC(ParseValues, int, (xpmData *data, unsigned int *width,
+ unsigned int *height, unsigned int *ncolors,
+ unsigned int *cpp, unsigned int *x_hotspot,
+ unsigned int *y_hotspot, unsigned int *hotspot,
+ unsigned int *extensions));
+
+LFUNC(ParseColors, int, (xpmData *data, unsigned int ncolors, unsigned int cpp,
+ char ****colorTablePtr, xpmHashTable *hashtable));
+
+LFUNC(ParsePixels, int, (xpmData *data, unsigned int width,
+ unsigned int height, unsigned int ncolors,
+ unsigned int cpp, char ***colorTable,
+ xpmHashTable *hashtable, unsigned int **pixels));
+
+LFUNC(ParseExtensions, int, (xpmData *data, XpmExtension **extensions,
+ unsigned int *nextensions));
+
+char *xpmColorKeys[] =
+{
+ "s", /* key #1: symbol */
+ "m", /* key #2: mono visual */
+ "g4", /* key #3: 4 grays visual */
+ "g", /* key #4: gray visual */
+ "c", /* key #5: color visual */
+};
+
+
+/* function call in case of error, frees only locally allocated variables */
+#undef RETURN
+#define RETURN(status) \
+ { if (colorTable) xpmFreeColorTable(colorTable, ncolors); \
+ if (pixelindex) free(pixelindex); \
+ if (hints_cmt) free(hints_cmt); \
+ if (colors_cmt) free(colors_cmt); \
+ if (pixels_cmt) free(pixels_cmt); \
+ return(status); }
+
+/*
+ * This function parses an Xpm file or data and store the found informations
+ * in an an xpmInternAttrib structure which is returned.
+ */
+int
+xpmParseData(data, attrib_return, attributes)
+ xpmData *data;
+ xpmInternAttrib *attrib_return;
+ XpmAttributes *attributes;
+{
+ /* variables to return */
+ unsigned int width, height, ncolors, cpp;
+ unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0;
+ char ***colorTable = NULL;
+ unsigned int *pixelindex = NULL;
+ char *hints_cmt = NULL;
+ char *colors_cmt = NULL;
+ char *pixels_cmt = NULL;
+
+ int ErrorStatus;
+ xpmHashTable hashtable;
+
+ /*
+ * read values
+ */
+ ErrorStatus = ParseValues(data, &width, &height, &ncolors, &cpp,
+ &x_hotspot, &y_hotspot, &hotspot, &extensions);
+ if (ErrorStatus != XpmSuccess)
+ return(ErrorStatus);
+
+ /*
+ * store the hints comment line
+ */
+ if (attributes && (attributes->valuemask & XpmReturnInfos))
+ xpmGetCmt(data, &hints_cmt);
+
+ /*
+ * init the hastable
+ */
+ if (USE_HASHTABLE) {
+ ErrorStatus = xpmHashTableInit(&hashtable);
+ if (ErrorStatus != XpmSuccess)
+ return(ErrorStatus);
+ }
+
+ /*
+ * read colors
+ */
+ ErrorStatus = ParseColors(data, ncolors, cpp, &colorTable, &hashtable);
+ if (ErrorStatus != XpmSuccess)
+ RETURN(ErrorStatus);
+
+ /*
+ * store the colors comment line
+ */
+ if (attributes && (attributes->valuemask & XpmReturnInfos))
+ xpmGetCmt(data, &colors_cmt);
+
+ /*
+ * read pixels and index them on color number
+ */
+ ErrorStatus = ParsePixels(data, width, height, ncolors, cpp, colorTable,
+ &hashtable, &pixelindex);
+
+ /*
+ * free the hastable
+ */
+ if (USE_HASHTABLE)
+ xpmHashTableFree(&hashtable);
+
+ if (ErrorStatus != XpmSuccess)
+ RETURN(ErrorStatus);
+
+ /*
+ * store the pixels comment line
+ */
+ if (attributes && (attributes->valuemask & XpmReturnInfos))
+ xpmGetCmt(data, &pixels_cmt);
+
+ /*
+ * parse extensions
+ */
+ if (attributes && (attributes->valuemask & XpmReturnExtensions))
+ if (extensions) {
+ ErrorStatus = ParseExtensions(data, &attributes->extensions,
+ &attributes->nextensions);
+ if (ErrorStatus != XpmSuccess)
+ RETURN(ErrorStatus);
+ } else {
+ attributes->extensions = NULL;
+ attributes->nextensions = 0;
+ }
+
+ /*
+ * store found informations in the xpmInternAttrib structure
+ */
+ attrib_return->width = width;
+ attrib_return->height = height;
+ attrib_return->cpp = cpp;
+ attrib_return->ncolors = ncolors;
+ attrib_return->colorTable = colorTable;
+ attrib_return->pixelindex = pixelindex;
+
+ if (attributes) {
+ if (attributes->valuemask & XpmReturnInfos) {
+ attributes->hints_cmt = hints_cmt;
+ attributes->colors_cmt = colors_cmt;
+ attributes->pixels_cmt = pixels_cmt;
+ }
+ if (hotspot) {
+ attributes->x_hotspot = x_hotspot;
+ attributes->y_hotspot = y_hotspot;
+ attributes->valuemask |= XpmHotspot;
+ }
+ }
+ return (XpmSuccess);
+}
+
+static int
+ParseValues(data, width, height, ncolors, cpp,
+ x_hotspot, y_hotspot, hotspot, extensions)
+ xpmData *data;
+ unsigned int *width, *height, *ncolors, *cpp;
+ unsigned int *x_hotspot, *y_hotspot, *hotspot;
+ unsigned int *extensions;
+{
+ unsigned int l;
+ char buf[BUFSIZ];
+
+ /*
+ * read values: width, height, ncolors, chars_per_pixel
+ */
+ if (!(xpmNextUI(data, width) && xpmNextUI(data, height)
+ && xpmNextUI(data, ncolors) && xpmNextUI(data, cpp)))
+ return(XpmFileInvalid);
+
+ /*
+ * read optional information (hotspot and/or XPMEXT) if any
+ */
+ l = xpmNextWord(data, buf);
+ if (l) {
+ *extensions = l == 6 && !strncmp("XPMEXT", buf, 6);
+ if (*extensions)
+ *hotspot = xpmNextUI(data, x_hotspot)
+ && xpmNextUI(data, y_hotspot);
+ else {
+ *hotspot = atoui(buf, l, x_hotspot) && xpmNextUI(data, y_hotspot);
+ l = xpmNextWord(data, buf);
+ *extensions = l == 6 && !strncmp("XPMEXT", buf, 6);
+ }
+ }
+ return (XpmSuccess);
+}
+
+static int
+ParseColors(data, ncolors, cpp, colorTablePtr, hashtable)
+ xpmData *data;
+ unsigned int ncolors;
+ unsigned int cpp;
+ char ****colorTablePtr; /* Jee, that's something! */
+ xpmHashTable *hashtable;
+{
+ unsigned int key, l, a, b;
+ unsigned int curkey; /* current color key */
+ unsigned int lastwaskey; /* key read */
+ char buf[BUFSIZ];
+ char curbuf[BUFSIZ]; /* current buffer */
+ char ***ct, **cts, **sptr, *s;
+ char ***colorTable;
+ int ErrorStatus;
+
+ colorTable = (char ***) calloc(ncolors, sizeof(char **));
+ if (!colorTable)
+ return(XpmNoMemory);
+
+ for (a = 0, ct = colorTable; a < ncolors; a++, ct++) {
+ xpmNextString(data); /* skip the line */
+ cts = *ct = (char **) calloc((NKEYS + 1), sizeof(char *));
+ if (!cts) {
+ xpmFreeColorTable(colorTable, ncolors);
+ return(XpmNoMemory);
+ }
+
+ /*
+ * read pixel value
+ */
+ *cts = (char *) malloc(cpp + 1); /* + 1 for null terminated */
+ if (!*cts) {
+ xpmFreeColorTable(colorTable, ncolors);
+ return(XpmNoMemory);
+ }
+ for (b = 0, s = *cts; b < cpp; b++, s++)
+ *s = xpmGetC(data);
+ *s = '\0';
+
+ /*
+ * store the string in the hashtable with its color index number
+ */
+ if (USE_HASHTABLE) {
+ ErrorStatus = xpmHashIntern(hashtable, *cts, HashAtomData((long)a));
+ if (ErrorStatus != XpmSuccess) {
+ xpmFreeColorTable(colorTable, ncolors);
+ return(ErrorStatus);
+ }
+ }
+
+ /*
+ * read color keys and values
+ */
+ curkey = 0;
+ lastwaskey = 0;
+ while (l = xpmNextWord(data, buf)) {
+ if (!lastwaskey) {
+ for (key = 0, sptr = xpmColorKeys; key < NKEYS; key++, sptr++)
+ if ((strlen(*sptr) == l) && (!strncmp(*sptr, buf, l)))
+ break;
+ }
+ if (!lastwaskey && key < NKEYS) { /* open new key */
+ if (curkey) { /* flush string */
+ s = cts[curkey] = (char *) malloc(strlen(curbuf) + 1);
+ if (!s) {
+ xpmFreeColorTable(colorTable, ncolors);
+ return(XpmNoMemory);
+ }
+ strcpy(s, curbuf);
+ }
+ curkey = key + 1; /* set new key */
+ *curbuf = '\0'; /* reset curbuf */
+ lastwaskey = 1;
+ } else {
+ if (!curkey) { /* key without value */
+ xpmFreeColorTable(colorTable, ncolors);
+ return(XpmFileInvalid);
+ }
+ if (!lastwaskey)
+ strcat(curbuf, " "); /* append space */
+ buf[l] = '\0';
+ strcat(curbuf, buf); /* append buf */
+ lastwaskey = 0;
+ }
+ }
+ if (!curkey) { /* key without value */
+ xpmFreeColorTable(colorTable, ncolors);
+ return(XpmFileInvalid);
+ }
+ s = cts[curkey] = (char *) malloc(strlen(curbuf) + 1);
+ if (!s) {
+ xpmFreeColorTable(colorTable, ncolors);
+ return(XpmNoMemory);
+ }
+ strcpy(s, curbuf);
+ }
+ *colorTablePtr = colorTable;
+ return(XpmSuccess);
+}
+
+static int
+ParsePixels(data, width, height, ncolors, cpp, colorTable, hashtable, pixels)
+ xpmData *data;
+ unsigned int width;
+ unsigned int height;
+ unsigned int ncolors;
+ unsigned int cpp;
+ char ***colorTable;
+ xpmHashTable *hashtable;
+ unsigned int **pixels;
+{
+ unsigned int *iptr, *iptr2;
+ unsigned int a, x, y;
+
+ iptr2 = (unsigned int *) malloc(sizeof(unsigned int) * width * height);
+ if (!iptr2)
+ return(XpmNoMemory);
+
+ iptr = iptr2;
+
+ switch (cpp) {
+
+ case (1): /* Optimize for single character colors */
+ {
+ unsigned short colidx[256];
+
+ bzero(colidx, 256 * sizeof(short));
+ for (a = 0; a < ncolors; a++)
+ colidx[ colorTable[a][0][0] ] = a + 1;
+
+ for (y = 0; y < height; y++)
+ {
+ xpmNextString(data);
+ for (x = 0; x < width; x++, iptr++)
+ {
+ int idx = colidx[xpmGetC(data)];
+ if ( idx != 0 )
+ *iptr = idx - 1;
+ else {
+ free(iptr2);
+ return(XpmFileInvalid);
+ }
+ }
+ }
+ }
+ break;
+
+ case (2): /* Optimize for double character colors */
+ {
+ unsigned short cidx[256][256];
+
+ bzero(cidx, 256*256 * sizeof(short));
+ for (a = 0; a < ncolors; a++)
+ cidx [ colorTable[a][0][0] ][ colorTable[a][0][1] ] = a + 1;
+
+ for (y = 0; y < height; y++)
+ {
+ xpmNextString(data);
+ for (x = 0; x < width; x++, iptr++)
+ {
+ int cc1 = xpmGetC(data);
+ int idx = cidx[cc1][ xpmGetC(data) ];
+ if ( idx != 0 )
+ *iptr = idx - 1;
+ else {
+ free(iptr2);
+ return(XpmFileInvalid);
+ }
+ }
+ }
+ }
+ break;
+
+ default : /* Non-optimized case of long color names */
+ {
+ char *s;
+ char buf[BUFSIZ];
+
+ buf[cpp] = '\0';
+ if (USE_HASHTABLE) {
+ xpmHashAtom *slot;
+
+ for (y = 0; y < height; y++) {
+ xpmNextString(data);
+ for (x = 0; x < width; x++, iptr++) {
+ for (a = 0, s = buf; a < cpp; a++, s++)
+ *s = xpmGetC(data);
+ slot = xpmHashSlot(hashtable, buf);
+ if (!*slot) { /* no color matches */
+ free(iptr2);
+ return(XpmFileInvalid);
+ }
+ *iptr = HashColorIndex(slot);
+ }
+ }
+ } else {
+ for (y = 0; y < height; y++) {
+ xpmNextString(data);
+ for (x = 0; x < width; x++, iptr++) {
+ for (a = 0, s = buf; a < cpp; a++, s++)
+ *s = xpmGetC(data);
+ for (a = 0; a < ncolors; a++)
+ if (!strcmp(colorTable[a][0], buf))
+ break;
+ if (a == ncolors) { /* no color matches */
+ free(iptr2);
+ return(XpmFileInvalid);
+ }
+ *iptr = a;
+ }
+ }
+ }
+ }
+ break;
+ }
+ *pixels = iptr2;
+ return (XpmSuccess);
+}
+
+static int
+ParseExtensions(data, extensions, nextensions)
+ xpmData *data;
+ XpmExtension **extensions;
+ unsigned int *nextensions;
+{
+ XpmExtension *exts = NULL, *ext;
+ unsigned int num = 0;
+ unsigned int nlines, a, l, notstart, notend = 0;
+ int status;
+ char *string, *s, *s2, **sp;
+
+ xpmNextString(data);
+ exts = (XpmExtension *) malloc(sizeof(XpmExtension));
+ /* get the whole string */
+ status = xpmGetString(data, &string, &l);
+ if (status != XpmSuccess) {
+ free(exts);
+ return(status);
+ }
+ /* look for the key word XPMEXT, skip lines before this */
+ while ((notstart = strncmp("XPMEXT", string, 6))
+ && (notend = strncmp("XPMENDEXT", string, 9))) {
+ free(string);
+ xpmNextString(data);
+ status = xpmGetString(data, &string, &l);
+ if (status != XpmSuccess) {
+ free(exts);
+ return(status);
+ }
+ }
+ if (!notstart)
+ notend = strncmp("XPMENDEXT", string, 9);
+ while (!notstart && notend) {
+ /* there starts an extension */
+ ext = (XpmExtension *) realloc(exts, (num + 1) * sizeof(XpmExtension));
+ if (!ext) {
+ free(string);
+ XpmFreeExtensions(exts, num);
+ return(XpmNoMemory);
+ }
+ exts = ext;
+ ext += num;
+ /* skip whitespace and store its name */
+ s2 = s = string + 6;
+ while (isspace(*s2))
+ s2++;
+ a = s2 - s;
+ ext->name = (char *) malloc(l - a - 6);
+ if (!ext->name) {
+ free(string);
+ ext->lines = NULL;
+ ext->nlines = 0;
+ XpmFreeExtensions(exts, num + 1);
+ return(XpmNoMemory);
+ }
+ strncpy(ext->name, s + a, l - a - 6);
+ free(string);
+ /* now store the related lines */
+ xpmNextString(data);
+ status = xpmGetString(data, &string, &l);
+ if (status != XpmSuccess) {
+ ext->lines = NULL;
+ ext->nlines = 0;
+ XpmFreeExtensions(exts, num + 1);
+ return(status);
+ }
+ ext->lines = (char **) malloc(sizeof(char *));
+ nlines = 0;
+ while ((notstart = strncmp("XPMEXT", string, 6))
+ && (notend = strncmp("XPMENDEXT", string, 9))) {
+ sp = (char **) realloc(ext->lines, (nlines + 1) * sizeof(char *));
+ if (!sp) {
+ free(string);
+ ext->nlines = nlines;
+ XpmFreeExtensions(exts, num + 1);
+ return(XpmNoMemory);
+ }
+ ext->lines = sp;
+ ext->lines[nlines] = string;
+ nlines++;
+ xpmNextString(data);
+ status = xpmGetString(data, &string, &l);
+ if (status != XpmSuccess) {
+ ext->nlines = nlines;
+ XpmFreeExtensions(exts, num + 1);
+ return(status);
+ }
+ }
+ if (!nlines) {
+ free(ext->lines);
+ ext->lines = NULL;
+ }
+ ext->nlines = nlines;
+ num++;
+ }
+ if (!num) {
+ free(string);
+ free(exts);
+ exts = NULL;
+ } else if (!notend)
+ free(string);
+ *nextensions = num;
+ *extensions = exts;
+ return(XpmSuccess);
+}
diff --git a/src/xpm/rename b/src/xpm/rename
new file mode 100755
index 0000000..a767d5e
--- /dev/null
+++ b/src/xpm/rename
@@ -0,0 +1,24 @@
+#!/bin/sh
+# rename is provided to easily update code using sed-command files
+
+USAGE='rename sed-command-file file1 file2...
+ apply all sed-command-file to the files file1 file2
+'
+
+if test "$1" = '-?'; then echo "$USAGE";exit 1;fi
+commands=$1
+shift
+
+for i in $*
+do if test -f $i
+ then echo -n "$i: "
+ echo -n "."
+ sed -f $commands $i > /tmp/rename.sed.$$;
+ if test ! -s /tmp/rename.sed.$$; then rm /tmp/rename.sed.$$; exit 1;fi
+ if cmp /tmp/rename.sed.$$ $i >/dev/null; then echo
+ else cp $i $i.BAK; cp /tmp/rename.sed.$$ $i; echo " modified."
+ fi
+ fi
+done
+
+rm -f /tmp/rename.sed.$$ /tmp/rename.sed.$$.org
diff --git a/src/xpm/rgb.c b/src/xpm/rgb.c
new file mode 100644
index 0000000..6694a60
--- /dev/null
+++ b/src/xpm/rgb.c
@@ -0,0 +1,136 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* rgb.c: *
+* *
+* XPM library *
+* Rgb file utilities *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+/*
+ * Part of this code has been taken from the ppmtoxpm.c file written by Mark
+ * W. Snitily but has been modified for my special need
+ */
+
+#include "xpmP.h"
+#ifdef VMS
+#include "sys$library:ctype.h"
+#include "sys$library:string.h"
+#else
+#include <ctype.h>
+#if defined(SYSV) || defined(SVR4)
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#endif
+
+/*
+ * Read a rgb text file. It stores the rgb values (0->65535)
+ * and the rgb mnemonics (malloc'ed) into the "rgbn" array. Returns the
+ * number of entries stored.
+ */
+int
+xpmReadRgbNames(rgb_fname, rgbn)
+ char *rgb_fname;
+ xpmRgbName rgbn[];
+
+{
+ FILE *rgbf;
+ int i, items, red, green, blue;
+ char line[512], name[512], *rgbname, *n, *m;
+ xpmRgbName *rgb;
+
+ /* Open the rgb text file. Abort if error. */
+ if ((rgbf = fopen(rgb_fname, "r")) == NULL)
+ return 0;
+
+ /* Loop reading each line in the file. */
+ for (i = 0, rgb = rgbn; fgets(line, sizeof(line), rgbf); i++, rgb++) {
+
+ /* Quit if rgb text file is too large. */
+ if (i == MAX_RGBNAMES) {
+ /* Too many entries in rgb text file, give up here */
+ break;
+ }
+ /* Read the line. Skip silently if bad. */
+ items = sscanf(line, "%d %d %d %[^\n]\n", &red, &green, &blue, name);
+ if (items != 4) {
+ i--;
+ continue;
+ }
+
+ /*
+ * Make sure rgb values are within 0->255 range. Skip silently if
+ * bad.
+ */
+ if (red < 0 || red > 0xFF ||
+ green < 0 || green > 0xFF ||
+ blue < 0 || blue > 0xFF) {
+ i--;
+ continue;
+ }
+ /* Allocate memory for ascii name. If error give up here. */
+ if (!(rgbname = (char *) malloc(strlen(name) + 1)))
+ break;
+
+ /* Copy string to ascii name and lowercase it. */
+ for (n = name, m = rgbname; *n; n++)
+ *m++ = isupper(*n) ? tolower(*n) : *n;
+ *m = '\0';
+
+ /* Save the rgb values and ascii name in the array. */
+ rgb->r = red * 257; /* 65535/255 = 257 */
+ rgb->g = green * 257;
+ rgb->b = blue * 257;
+ rgb->name = rgbname;
+ }
+
+ fclose(rgbf);
+
+ /* Return the number of read rgb names. */
+ return i < 0 ? 0 : i;
+}
+
+/*
+ * Return the color name corresponding to the given rgb values
+ */
+char *
+xpmGetRgbName(rgbn, rgbn_max, red, green, blue)
+ xpmRgbName rgbn[]; /* rgb mnemonics from rgb text file */
+int rgbn_max; /* number of rgb mnemonics in table */
+int red, green, blue; /* rgb values */
+
+{
+ int i;
+ xpmRgbName *rgb;
+
+ /*
+ * Just perform a dumb linear search over the rgb values of the color
+ * mnemonics. One could speed things up by sorting the rgb values and
+ * using a binary search, or building a hash table, etc...
+ */
+ for (i = 0, rgb = rgbn; i < rgbn_max; i++, rgb++)
+ if (red == rgb->r && green == rgb->g && blue == rgb->b)
+ return rgb->name;
+
+ /* if not found return NULL */
+ return NULL;
+}
+
+/*
+ * Free the strings which have been malloc'ed in xpmReadRgbNames
+ */
+void
+xpmFreeRgbNames(rgbn, rgbn_max)
+ xpmRgbName rgbn[];
+int rgbn_max;
+
+{
+ int i;
+ xpmRgbName *rgb;
+
+ for (i = 0, rgb = rgbn; i < rgbn_max; i++, rgb++)
+ free(rgb->name);
+}
diff --git a/src/xpm/scan.c b/src/xpm/scan.c
new file mode 100644
index 0000000..2cee34c
--- /dev/null
+++ b/src/xpm/scan.c
@@ -0,0 +1,567 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* scan.c: *
+* *
+* XPM library *
+* Scanning utility for XPM file format *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+#include "xpmP.h"
+
+#define MAXPRINTABLE 93 /* number of printable ascii chars
+ * minus \ and " for string compat
+ * and / to avoid comment conflicts. */
+
+static char *printable =
+" .XoO+@#$%&*=-;:?>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZ\
+ASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
+
+ /*
+ * printable begin with a space, so in most case, due to my algorithm, when
+ * the number of different colors is less than MAXPRINTABLE, it will give a
+ * char follow by "nothing" (a space) in the readable xpm file
+ */
+
+
+typedef struct {
+ Pixel *pixels;
+ unsigned int *pixelindex;
+ unsigned int size;
+ unsigned int ncolors;
+ unsigned int mask_pixel; /* whether there is or not */
+} PixelsMap;
+
+LFUNC(storePixel, int, (Pixel pixel, PixelsMap * pmap,
+ unsigned int *index_return));
+
+LFUNC(storeMaskPixel, int, (Pixel pixel, PixelsMap * pmap,
+ unsigned int *index_return));
+
+LFUNC(GetImagePixels, int, (XImage * image, unsigned int width,
+ unsigned int height, PixelsMap * pmap));
+
+LFUNC(GetImagePixels32, int, (XImage * image, unsigned int width,
+ unsigned int height, PixelsMap * pmap));
+
+LFUNC(GetImagePixels16, int, (XImage * image, unsigned int width,
+ unsigned int height, PixelsMap * pmap));
+
+LFUNC(GetImagePixels8, int, (XImage * image, unsigned int width,
+ unsigned int height, PixelsMap * pmap));
+
+LFUNC(GetImagePixels1, int, (XImage * image, unsigned int width,
+ unsigned int height, PixelsMap * pmap,
+ int (*storeFunc) ()));
+
+/*
+ * This function stores the given pixel in the given arrays which are grown
+ * if not large enough.
+ */
+static int
+storePixel(pixel, pmap, index_return)
+ Pixel pixel;
+ PixelsMap *pmap;
+ unsigned int *index_return;
+{
+ register unsigned int a;
+ register Pixel *p;
+ register unsigned int ncolors;
+
+ if (*index_return) { /* this is a transparent pixel! */
+ *index_return = 0;
+ return 0;
+ }
+ ncolors = pmap->ncolors;
+ p = &(pmap->pixels[pmap->mask_pixel]);
+ for (a = pmap->mask_pixel; a < ncolors; a++, p++)
+ if (*p == pixel)
+ break;
+ if (a == ncolors) {
+ if (ncolors > pmap->size) {
+
+ pmap->size *= 2;
+ p = (Pixel *) realloc(pmap->pixels, sizeof(Pixel) * pmap->size);
+ if (!p)
+ return (1);
+ pmap->pixels = p;
+
+ }
+ (pmap->pixels)[ncolors] = pixel;
+ pmap->ncolors++;
+ }
+ *index_return = a;
+ return 0;
+}
+
+static int
+storeMaskPixel(pixel, pmap, index_return)
+ Pixel pixel;
+ PixelsMap *pmap;
+ unsigned int *index_return;
+{
+ if (!pixel) {
+ if (!pmap->ncolors) {
+ pmap->ncolors = 1;
+ (pmap->pixels)[0] = 0;
+ pmap->mask_pixel = 1;
+ }
+ *index_return = 1;
+ } else
+ *index_return = 0;
+ return 0;
+}
+
+/* function call in case of error, frees only locally allocated variables */
+#undef RETURN
+#define RETURN(status) \
+ { if (pmap.pixelindex) free(pmap.pixelindex); \
+ if (pmap.pixels) free(pmap.pixels); \
+ if (xcolors) free(xcolors); \
+ if (colorStrings) { \
+ for (a = 0; a < pmap.ncolors; a++) \
+ if (colorStrings[a]) \
+ free(colorStrings[a]); \
+ free(colorStrings); \
+ } \
+ return(status); }
+
+/*
+ * This function scans the given image and stores the found informations in
+ * the xpmInternAttrib structure which is returned.
+ */
+int
+xpmScanImage(display, image, shapeimage, attributes, attrib)
+ Display *display;
+ XImage *image;
+ XImage *shapeimage;
+ XpmAttributes *attributes;
+ xpmInternAttrib *attrib;
+
+{
+ /* variables stored in the XpmAttributes structure */
+ Colormap colormap;
+ unsigned int cpp;
+
+ /* variables to return */
+ PixelsMap pmap;
+ char **colorStrings = NULL;
+ XColor *xcolors = NULL;
+ int ErrorStatus;
+
+ /* calculation variables */
+ unsigned int width = 0;
+ unsigned int height = 0;
+ unsigned int cppm; /* minimum chars per pixel */
+ unsigned int a, b, c;
+ register char *s;
+
+ /* initialize pmap */
+ pmap.pixels = NULL;
+ pmap.pixelindex = NULL;
+ pmap.size = 256; /* should be enough most of the time */
+ pmap.ncolors = 0;
+ pmap.mask_pixel = 0;
+
+ /*
+ * get geometry
+ */
+ if (image) {
+ width = image->width;
+ height = image->height;
+ } else if (shapeimage) {
+ width = shapeimage->width;
+ height = shapeimage->height;
+ }
+
+ /*
+ * retrieve information from the XpmAttributes
+ */
+ if (attributes && attributes->valuemask & XpmColormap)
+ colormap = attributes->colormap;
+ else
+ colormap = DefaultColormap(display, DefaultScreen(display));
+
+ if (attributes && (attributes->valuemask & XpmCharsPerPixel
+ || attributes->valuemask & XpmInfos))
+ cpp = attributes->cpp;
+ else
+ cpp = 0;
+
+ pmap.pixelindex =
+ (unsigned int *) calloc(width * height, sizeof(unsigned int));
+ if (!pmap.pixelindex)
+ RETURN(XpmNoMemory);
+
+ pmap.pixels = (Pixel *) malloc(sizeof(Pixel) * pmap.size);
+ if (!pmap.pixels)
+ RETURN(XpmNoMemory);
+
+ /*
+ * scan shape mask if any
+ */
+ if (shapeimage) {
+ ErrorStatus = GetImagePixels1(shapeimage, width, height, &pmap,
+ storeMaskPixel);
+ if (ErrorStatus != XpmSuccess)
+ RETURN(ErrorStatus);
+ }
+
+ /*
+ * scan the image data
+ *
+ * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use optimized
+ * functions, otherwise use slower but sure general one.
+ *
+ */
+
+ if (image) {
+ if (image->depth == 1)
+ ErrorStatus = GetImagePixels1(image, width, height, &pmap,
+ storePixel);
+ else if (image->bits_per_pixel == 8)
+ ErrorStatus = GetImagePixels8(image, width, height, &pmap);
+ else if (image->bits_per_pixel == 16)
+ ErrorStatus = GetImagePixels16(image, width, height, &pmap);
+ else if (image->bits_per_pixel == 32)
+ ErrorStatus = GetImagePixels32(image, width, height, &pmap);
+ else
+ ErrorStatus = GetImagePixels(image, width, height, &pmap);
+
+ if (ErrorStatus != XpmSuccess)
+ RETURN(ErrorStatus);
+ }
+
+ /*
+ * get rgb values and a string of char for each color
+ */
+
+ xcolors = (XColor *) malloc(sizeof(XColor) * pmap.ncolors);
+ if (!xcolors)
+ RETURN(XpmNoMemory);
+ colorStrings = (char **) calloc(pmap.ncolors, sizeof(char *));
+ if (!colorStrings)
+ RETURN(XpmNoMemory);
+
+ for (cppm = 1, c = MAXPRINTABLE; pmap.ncolors > c; cppm++)
+ c *= MAXPRINTABLE;
+ if (cpp < cppm)
+ cpp = cppm;
+
+ for (a = 0; a < pmap.ncolors; a++) {
+ if (!(s = colorStrings[a] = (char *) malloc(cpp)))
+ RETURN(XpmNoMemory);
+ *s++ = printable[c = a % MAXPRINTABLE];
+ for (b = 1; b < cpp; b++, s++)
+ *s = printable[c = ((a - c) / MAXPRINTABLE) % MAXPRINTABLE];
+ xcolors[a].pixel = pmap.pixels[a];
+ }
+
+ XQueryColors(display, colormap, xcolors, pmap.ncolors);
+
+ /*
+ * store found informations in the xpmInternAttrib structure
+ */
+ attrib->width = width;
+ attrib->height = height;
+ attrib->cpp = cpp;
+ attrib->ncolors = pmap.ncolors;
+ attrib->mask_pixel = pmap.mask_pixel ? 0 : UNDEF_PIXEL;
+ attrib->pixelindex = pmap.pixelindex;
+ attrib->xcolors = xcolors;
+ attrib->colorStrings = colorStrings;
+
+ free(pmap.pixels);
+ return (XpmSuccess);
+}
+
+
+
+/*
+ * The functions below are written from X11R5 MIT's code (XImUtil.c)
+ *
+ * The idea is to have faster functions than the standard XGetPixel function
+ * to scan the image data. Indeed we can speed up things by suppressing tests
+ * performed for each pixel. We do exactly the same tests but at the image
+ * level. Assuming that we use only ZPixmap images.
+ */
+
+static unsigned long Const low_bits_table[] = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007,
+ 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
+ 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
+ 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
+ 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
+ 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
+ 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
+ 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
+ 0xffffffff
+};
+
+/*
+ * Default method to scan pixels of a Z image data structure.
+ * The algorithm used is:
+ *
+ * copy the source bitmap_unit or Zpixel into temp
+ * normalize temp if needed
+ * extract the pixel bits into return value
+ *
+ */
+
+static int
+GetImagePixels(image, width, height, pmap)
+ XImage *image;
+ unsigned int width;
+ unsigned int height;
+ PixelsMap *pmap;
+{
+ register char *src;
+ register char *dst;
+ register unsigned int *iptr;
+ register char *data;
+ register int x, y, i;
+ int bits, depth, ibu, ibpp;
+ unsigned long lbt;
+ Pixel pixel, px;
+
+ data = image->data;
+ iptr = pmap->pixelindex;
+ depth = image->depth;
+ lbt = low_bits_table[depth];
+ ibpp = image->bits_per_pixel;
+ if (image->depth == 1) {
+ ibu = image->bitmap_unit;
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ src = &data[XYINDEX(x, y, image)];
+ dst = (char *) &pixel;
+ pixel = 0;
+ for (i = ibu >> 3; --i >= 0;)
+ *dst++ = *src++;
+ XYNORMALIZE(&pixel, image);
+ bits = x % ibu;
+ pixel = ((((char *) &pixel)[bits >> 3]) >> (bits & 7)) & 1;
+ if (ibpp != depth)
+ pixel &= lbt;
+ if (storePixel(pixel, pmap, iptr))
+ return (XpmNoMemory);
+ }
+ } else {
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ src = &data[ZINDEX(x, y, image)];
+ dst = (char *) &px;
+ px = 0;
+ for (i = (ibpp + 7) >> 3; --i >= 0;)
+ *dst++ = *src++;
+ ZNORMALIZE(&px, image);
+ pixel = 0;
+ for (i = sizeof(unsigned long); --i >= 0;)
+ pixel = (pixel << 8) | ((unsigned char *) &px)[i];
+ if (ibpp == 4) {
+ if (x & 1)
+ pixel >>= 4;
+ else
+ pixel &= 0xf;
+ }
+ if (ibpp != depth)
+ pixel &= lbt;
+ if (storePixel(pixel, pmap, iptr))
+ return (XpmNoMemory);
+ }
+ }
+ return(XpmSuccess);
+}
+
+/*
+ * scan pixels of a 32-bits Z image data structure
+ */
+
+#ifndef WORD64
+static unsigned long byteorderpixel = MSBFirst << 24;
+
+#endif
+
+static int
+GetImagePixels32(image, width, height, pmap)
+ XImage *image;
+ unsigned int width;
+ unsigned int height;
+ PixelsMap *pmap;
+{
+ register unsigned char *addr;
+ register unsigned char *data;
+ register unsigned int *iptr;
+ register int x, y;
+ unsigned long lbt;
+ Pixel pixel;
+ int depth;
+
+ data = (unsigned char *) image->data;
+ iptr = pmap->pixelindex;
+ depth = image->depth;
+ lbt = low_bits_table[depth];
+#ifndef WORD64
+ if (*((char *) &byteorderpixel) == image->byte_order) {
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ addr = &data[ZINDEX32(x, y, image)];
+ pixel = *((unsigned long *)addr);
+ if (depth != 32)
+ pixel &= lbt;
+ if (storePixel(pixel, pmap, iptr))
+ return (XpmNoMemory);
+ }
+ } else
+#endif
+ if (image->byte_order == MSBFirst)
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ addr = &data[ZINDEX32(x, y, image)];
+ pixel = ((unsigned long) addr[0] << 24 |
+ (unsigned long) addr[1] << 16 |
+ (unsigned long) addr[2] << 8 |
+ addr[4]);
+ if (depth != 32)
+ pixel &= lbt;
+ if (storePixel(pixel, pmap, iptr))
+ return (XpmNoMemory);
+ }
+ else
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ addr = &data[ZINDEX32(x, y, image)];
+ pixel = (addr[0] |
+ (unsigned long) addr[1] << 8 |
+ (unsigned long) addr[2] << 16 |
+ (unsigned long) addr[3] << 24);
+ if (depth != 32)
+ pixel &= lbt;
+ if (storePixel(pixel, pmap, iptr))
+ return (XpmNoMemory);
+ }
+ return(XpmSuccess);
+}
+
+/*
+ * scan pixels of a 16-bits Z image data structure
+ */
+
+static int
+GetImagePixels16(image, width, height, pmap)
+ XImage *image;
+ unsigned int width;
+ unsigned int height;
+ PixelsMap *pmap;
+{
+ register unsigned char *addr;
+ register unsigned char *data;
+ register unsigned int *iptr;
+ register int x, y;
+ unsigned long lbt;
+ Pixel pixel;
+ int depth;
+
+ data = (unsigned char *) image->data;
+ iptr = pmap->pixelindex;
+ depth = image->depth;
+ lbt = low_bits_table[depth];
+ if (image->byte_order == MSBFirst)
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ addr = &data[ZINDEX16(x, y, image)];
+ pixel = addr[0] << 8 | addr[1];
+ if (depth != 16)
+ pixel &= lbt;
+ if (storePixel(pixel, pmap, iptr))
+ return (XpmNoMemory);
+ }
+ else
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ addr = &data[ZINDEX16(x, y, image)];
+ pixel = addr[0] | addr[1] << 8;
+ if (depth != 16)
+ pixel &= lbt;
+ if (storePixel(pixel, pmap, iptr))
+ return (XpmNoMemory);
+ }
+ return(XpmSuccess);
+}
+
+/*
+ * scan pixels of a 8-bits Z image data structure
+ */
+
+static int
+GetImagePixels8(image, width, height, pmap)
+ XImage *image;
+ unsigned int width;
+ unsigned int height;
+ PixelsMap *pmap;
+{
+ register unsigned int *iptr;
+ register unsigned char *data;
+ register int x, y;
+ unsigned long lbt;
+ Pixel pixel;
+ int depth;
+
+ data = (unsigned char *) image->data;
+ iptr = pmap->pixelindex;
+ depth = image->depth;
+ lbt = low_bits_table[depth];
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ pixel = data[ZINDEX8(x, y, image)];
+ if (depth != 8)
+ pixel &= lbt;
+ if (storePixel(pixel, pmap, iptr))
+ return (XpmNoMemory);
+ }
+ return(XpmSuccess);
+}
+
+/*
+ * scan pixels of a 1-bit depth Z image data structure
+ */
+
+static int
+GetImagePixels1(image, width, height, pmap, storeFunc)
+ XImage *image;
+ unsigned int width;
+ unsigned int height;
+ PixelsMap *pmap;
+ int (*storeFunc) ();
+
+{
+ register unsigned int *iptr;
+ register int x, y;
+ register char *data;
+ Pixel pixel;
+
+ if (image->byte_order != image->bitmap_bit_order)
+ return(GetImagePixels(image, width, height, pmap));
+ else {
+ data = image->data;
+ iptr = pmap->pixelindex;
+ if (image->bitmap_bit_order == MSBFirst)
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ pixel = (data[ZINDEX1(x, y, image)] & (0x80 >> (x & 7)))
+ ? 1 : 0;
+ if ((*storeFunc) (pixel, pmap, iptr))
+ return (XpmNoMemory);
+ }
+ else
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width; x++, iptr++) {
+ pixel = (data[ZINDEX1(x, y, image)] & (1 << (x & 7)))
+ ? 1 : 0;
+ if ((*storeFunc) (pixel, pmap, iptr))
+ return (XpmNoMemory);
+ }
+ }
+ return(XpmSuccess);
+}
diff --git a/src/xpm/sxpm.c b/src/xpm/sxpm.c
new file mode 100644
index 0000000..9ee3ad3
--- /dev/null
+++ b/src/xpm/sxpm.c
@@ -0,0 +1,580 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* sxpm.c: *
+* *
+* Show XPM File program *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+#ifdef VMS
+#include "decw$include:Xlib.h"
+#include "decw$include:Intrinsic.h"
+#include "decw$include:Shell.h"
+#include "decw$include:shape.h"
+#else
+#include <X11/StringDefs.h>
+#include <X11/Intrinsic.h>
+#include <X11/Shell.h>
+#include <X11/extensions/shape.h>
+#endif
+
+#include "xpm.h"
+
+#ifdef Debug
+/* memory leak control tool */
+#include <mnemosyne.h>
+#endif
+
+/* XPM */
+/* plaid pixmap */
+static char *plaid[] =
+{
+/* width height ncolors chars_per_pixel */
+ "22 22 4 2 XPMEXT",
+/* colors */
+ " c red m white s light_color",
+ "Y c green m black s lines_in_mix",
+ "+ c yellow m white s lines_in_dark",
+ "x m black s dark_color",
+/* pixels */
+ "x x x x x x x x x x x x + x x x x x ",
+ " x x x x x x x x x x x x x x x x ",
+ "x x x x x x x x x x x x + x x x x x ",
+ " x x x x x x x x x x x x x x x x ",
+ "x x x x x x x x x x x x + x x x x x ",
+ "Y Y Y Y Y x Y Y Y Y Y + x + x + x + x + x + ",
+ "x x x x x x x x x x x x + x x x x x ",
+ " x x x x x x x x x x x x x x x x ",
+ "x x x x x x x x x x x x + x x x x x ",
+ " x x x x x x x x x x x x x x x x ",
+ "x x x x x x x x x x x x + x x x x x ",
+ " x x x x Y x x x ",
+ " x x x Y x x ",
+ " x x x x Y x x x ",
+ " x x x Y x x ",
+ " x x x x Y x x x ",
+ "x x x x x x x x x x x x x x x x x x x x x x ",
+ " x x x x Y x x x ",
+ " x x x Y x x ",
+ " x x x x Y x x x ",
+ " x x x Y x x ",
+ " x x x x Y x x x ",
+"bullshit",
+"XPMEXT ext1 data1",
+"XPMEXT ext2",
+"data2_1",
+"data2_2",
+"XPMEXT",
+"foo",
+"",
+"XPMEXT ext3",
+"data3",
+"XPMENDEXT"
+};
+
+#define win XtWindow(topw)
+#define dpy XtDisplay(topw)
+#define screen XtScreen(topw)
+#define root XRootWindowOfScreen(screen)
+#define xrdb XtDatabase(dpy)
+static Colormap colormap;
+
+void Usage();
+void ErrorMessage();
+void Punt();
+void kinput();
+
+#define IWIDTH 50
+#define IHEIGHT 50
+
+typedef struct _XpmIcon {
+ Pixmap pixmap;
+ Pixmap mask;
+ XpmAttributes attributes;
+} XpmIcon;
+
+static char **command;
+static Widget topw;
+static XpmIcon view, icon;
+static XrmOptionDescRec options[] = {
+ {"-hints", ".hints", XrmoptionNoArg, (XtPointer) "True"},
+ {"-icon", ".icon", XrmoptionSepArg, (XtPointer) NULL},
+};
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int ErrorStatus;
+ unsigned int verbose = 0;
+ unsigned int stdinf = 1;
+ unsigned int stdoutf = 0;
+ unsigned int nod = 0;
+ unsigned int incResize = 0;
+ unsigned int resize = 0;
+ unsigned int w_rtn;
+ unsigned int h_rtn;
+ char *input = NULL;
+ char *output = NULL;
+ char *iconFile = NULL;
+ unsigned int numsymbols = 0;
+ XpmColorSymbol symbols[10];
+ char *stype;
+ XrmValue val;
+ unsigned long valuemask = 0;
+ int n;
+ Arg args[3];
+
+#ifdef Debug2
+ char **data;
+
+#endif
+
+ topw = XtInitialize(argv[0], "Sxpm",
+ options, XtNumber(options), &argc, argv);
+
+ if (!topw) {
+ fprintf(stderr, "Sxpm Error... [ Undefined DISPLAY ]\n");
+ exit(1);
+ }
+
+ colormap = XDefaultColormapOfScreen(screen);
+
+ /*
+ * geometry management
+ */
+
+ if (XrmGetResource(xrdb, NULL, "sxpm.geometry", &stype, &val)
+ || XrmGetResource(xrdb, NULL, "Sxpm.geometry", &stype, &val)) {
+
+ int flags;
+ int x_rtn;
+ int y_rtn;
+ char *geo = NULL;
+
+ geo = (char *) val.addr;
+ flags = XParseGeometry(geo, &x_rtn, &y_rtn,
+ (unsigned int *) &w_rtn,
+ (unsigned int *) &h_rtn);
+ if (!((WidthValue & flags) && (HeightValue & flags)))
+ resize = 1;
+ } else
+ resize = 1;
+
+ n = 0;
+ if (resize) {
+ w_rtn = 0;
+ h_rtn = 0;
+ XtSetArg(args[n], XtNwidth, 1);
+ n++;
+ XtSetArg(args[n], XtNheight, 1);
+ n++;
+ }
+ XtSetArg(args[n], XtNmappedWhenManaged, False);
+ n++;
+ XtSetValues(topw, args, n);
+
+ if ((XrmGetResource(xrdb, "sxpm.hints", "", &stype, &val)
+ || XrmGetResource(xrdb, "Sxpm.hints", "", &stype, &val))
+ && !strcmp((char *) val.addr, "True")) {
+ /* gotcha */
+ incResize = 1;
+ resize = 1;
+ }
+
+ /*
+ * icon management
+ */
+
+ if (XrmGetResource(xrdb, "sxpm.icon", "", &stype, &val) ||
+ XrmGetResource(xrdb, "Sxpm.icon", "", &stype, &val)) {
+ iconFile = (char *) val.addr;
+ }
+ if (iconFile) {
+
+ XColor color, junk;
+ Pixel bpix;
+ Window iconW;
+
+ if (XAllocNamedColor(dpy, colormap, "black", &color, &junk))
+ bpix = color.pixel;
+ else
+ bpix = XBlackPixelOfScreen(screen);
+
+ iconW = XCreateSimpleWindow(dpy, root, 0, 0,
+ IWIDTH, IHEIGHT, 1, bpix, bpix);
+
+ icon.attributes.valuemask = XpmReturnPixels;
+ ErrorStatus = XpmReadFileToPixmap(dpy, root, iconFile, &icon.pixmap,
+ &icon.mask, &icon.attributes);
+ ErrorMessage(ErrorStatus, "Icon");
+
+ XSetWindowBackgroundPixmap(dpy, iconW, icon.pixmap);
+
+ n = 0;
+ XtSetArg(args[n], XtNbackground, bpix);
+ n++;
+ XtSetArg(args[n], XtNiconWindow, iconW);
+ n++;
+ XtSetValues(topw, args, n);
+ }
+
+ /*
+ * arguments parsing
+ */
+
+ command = argv;
+ for (n = 1; n < argc; n++) {
+ if (strncmp(argv[n], "-plaid", 3) == 0) {
+ stdinf = 0;
+ continue;
+ }
+ if (argv[n][0] != '-') {
+ stdinf = 0;
+ input = argv[n];
+ continue;
+ }
+ if ((strlen(argv[n]) == 1) && (argv[n][0] == '-'))
+ /* stdin */
+ continue;
+ if (strncmp(argv[n], "-o", 2) == 0) {
+ if (n < argc - 1) {
+ if ((strlen(argv[n + 1]) == 1) && (argv[n + 1][0] == '-'))
+ stdoutf = 1;
+ else
+ output = argv[n + 1];
+ n++;
+ continue;
+ } else
+ Usage();
+ }
+ if (strncmp(argv[n], "-nod", 2) == 0) {
+ nod = 1;
+ continue;
+ }
+ if (strncmp(argv[n], "-s", 2) == 0) {
+ if (n < argc - 2) {
+ valuemask |= XpmColorSymbols;
+ symbols[numsymbols].name = argv[++n];
+ symbols[numsymbols++].value = argv[++n];
+ continue;
+ } else
+ Usage();
+ }
+ if (strncmp(argv[n], "-p", 2) == 0) {
+ if (n < argc - 2) {
+ valuemask |= XpmColorSymbols;
+ symbols[numsymbols].name = argv[++n];
+ symbols[numsymbols].value = NULL;
+ symbols[numsymbols++].pixel = atol(argv[++n]);
+ continue;
+ }
+ }
+ if (strcmp(argv[n], "-closecolors") == 0) {
+ valuemask |= XpmCloseness;
+ view.attributes.closeness = 40000;
+ continue;
+ }
+ if (strncmp(argv[n], "-rgb", 3) == 0) {
+ if (n < argc - 1) {
+ valuemask |= XpmRgbFilename;
+ view.attributes.rgb_fname = argv[++n];
+ continue;
+ } else
+ Usage();
+
+ }
+ if (strncmp(argv[n], "-v", 2) == 0) {
+ verbose = 1;
+ continue;
+ }
+ if (strncmp(argv[n], "-c", 2) == 0) {
+ valuemask |= XpmColormap;
+ continue;
+ }
+ Usage();
+ }
+
+ XtRealizeWidget(topw);
+ if (valuemask & XpmColormap) {
+ colormap = XCreateColormap(dpy, win,
+ DefaultVisual(dpy, DefaultScreen(dpy)),
+ AllocNone);
+ view.attributes.colormap = colormap;
+ XSetWindowColormap(dpy, win, colormap);
+ }
+ view.attributes.colorsymbols = symbols;
+ view.attributes.numsymbols = numsymbols;
+ view.attributes.valuemask = valuemask;
+
+#ifdef Debug2
+ /* this is just to test the XpmCreateDataFromPixmap function */
+
+ view.attributes.valuemask |= XpmReturnPixels;
+ view.attributes.valuemask |= XpmReturnExtensions;
+ ErrorStatus = XpmCreatePixmapFromData(dpy, win, plaid,
+ &view.pixmap, &view.mask,
+ &view.attributes);
+ ErrorMessage(ErrorStatus, "Plaid");
+
+ ErrorStatus = XpmCreateDataFromPixmap(dpy, &data, view.pixmap, view.mask,
+ &view.attributes);
+ ErrorMessage(ErrorStatus, "Data");
+ if (verbose && view.attributes.nextensions) {
+ unsigned int i, j;
+ for (i = 0; i < view.attributes.nextensions; i++) {
+ fprintf(stderr, "Xpm extension : %s\n",
+ view.attributes.extensions[i].name);
+ for (j = 0; j < view.attributes.extensions[i].nlines; j++)
+ fprintf(stderr, "\t\t%s\n",
+ view.attributes.extensions[i].lines[j]);
+ }
+ }
+
+ XFreePixmap(dpy, view.pixmap);
+ if (view.mask)
+ XFreePixmap(dpy, view.mask);
+
+ XFreeColors(dpy, colormap,
+ view.attributes.pixels, view.attributes.npixels, 0);
+
+ XpmFreeAttributes(&view.attributes);
+ view.attributes.valuemask = valuemask;
+#endif
+
+ if (input || stdinf) {
+ view.attributes.valuemask |= XpmReturnInfos;
+ view.attributes.valuemask |= XpmReturnPixels;
+ view.attributes.valuemask |= XpmReturnExtensions;
+
+#ifdef Debug2
+ free(data);
+
+ ErrorStatus = XpmReadFileToData(input, &data);
+ ErrorMessage(ErrorStatus, "ReadFileToData");
+ ErrorStatus = XpmCreatePixmapFromData(dpy, win, data,
+ &view.pixmap, &view.mask,
+ &view.attributes);
+ ErrorMessage(ErrorStatus, "CreatePixmapFromData");
+ ErrorStatus = XpmWriteFileFromData("sxpmout.xpm", data);
+ ErrorMessage(ErrorStatus, "WriteFileFromData");
+ free(data);
+#endif
+
+ ErrorStatus = XpmReadFileToPixmap(dpy, win, input,
+ &view.pixmap, &view.mask,
+ &view.attributes);
+ ErrorMessage(ErrorStatus, "Read");
+ if (verbose && view.attributes.nextensions) {
+ unsigned int i, j;
+ for (i = 0; i < view.attributes.nextensions; i++) {
+ fprintf(stderr, "Xpm extension : %s\n",
+ view.attributes.extensions[i].name);
+ for (j = 0; j < view.attributes.extensions[i].nlines; j++)
+ fprintf(stderr, "\t\t%s\n",
+ view.attributes.extensions[i].lines[j]);
+ }
+ }
+ } else {
+#ifdef Debug2
+ ErrorStatus = XpmCreatePixmapFromData(dpy, win, data,
+ &view.pixmap, &view.mask,
+ &view.attributes);
+ free(data);
+#else
+ ErrorStatus = XpmCreatePixmapFromData(dpy, win, plaid,
+ &view.pixmap, &view.mask,
+ &view.attributes);
+#endif
+ ErrorMessage(ErrorStatus, "Plaid");
+ }
+ if (output || stdoutf) {
+ ErrorStatus = XpmWriteFileFromPixmap(dpy, output, view.pixmap,
+ view.mask, &view.attributes);
+ ErrorMessage(ErrorStatus, "Write");
+ }
+ if (!nod) {
+
+ /*
+ * manage display if requested
+ */
+
+ XSizeHints size_hints;
+ char *xString = NULL;
+
+ if (w_rtn && h_rtn
+ && ((w_rtn < view.attributes.width)
+ || h_rtn < view.attributes.height)) {
+ resize = 1;
+ }
+ if (resize) {
+ XtResizeWidget(topw,
+ view.attributes.width, view.attributes.height, 1);
+ }
+ if (incResize) {
+ size_hints.flags = USSize | PMinSize | PResizeInc;
+ size_hints.height = view.attributes.height;
+ size_hints.width = view.attributes.width;
+ size_hints.height_inc = view.attributes.height;
+ size_hints.width_inc = view.attributes.width;
+ } else
+ size_hints.flags = PMinSize;
+
+ size_hints.min_height = view.attributes.height;
+ size_hints.min_width = view.attributes.width;
+ XSetWMNormalHints(dpy, win, &size_hints);
+
+ if (input) {
+ xString = (char *) XtMalloc((sizeof(char) * strlen(input)) + 20);
+ sprintf(xString, "Sxpm: %s\0", input);
+ XStoreName(dpy, XtWindow(topw), xString);
+ XSetIconName(dpy, XtWindow(topw), xString);
+ } else if (stdinf) {
+ XStoreName(dpy, XtWindow(topw), "Sxpm: stdin");
+ XSetIconName(dpy, XtWindow(topw), "Sxpm: stdin");
+ } else {
+ XStoreName(dpy, XtWindow(topw), "Sxpm");
+ XSetIconName(dpy, XtWindow(topw), "Sxpm");
+ }
+
+ XtAddEventHandler(topw, KeyPressMask, False,
+ (XtEventHandler) kinput, NULL);
+ XSetWindowBackgroundPixmap(dpy, win, view.pixmap);
+
+ if (view.mask)
+ XShapeCombineMask(dpy, win, ShapeBounding, 0, 0,
+ view.mask, ShapeSet);
+
+ XClearWindow(dpy, win);
+ XMapWindow(dpy, win);
+ if (xString)
+ XtFree(xString);
+ XtMainLoop();
+ }
+ Punt(0);
+}
+
+void
+Usage()
+{
+ fprintf(stderr, "\nUsage: %s [options...]\n", command[0]);
+ fprintf(stderr, "%s\n", "Where options are:");
+ fprintf(stderr, "\n%s\n",
+ "[-d host:display] Display to connect to.");
+ fprintf(stderr, "%s\n",
+ "[-g geom] Geometry of window.");
+ fprintf(stderr, "%s\n",
+ "[-hints] Set ResizeInc for window.");
+ fprintf(stderr, "%s\n",
+ "[-icon filename] Set pixmap for iconWindow.");
+ fprintf(stderr, "%s\n",
+ "[-s symbol_name color_name] Overwrite color defaults.");
+ fprintf(stderr, "%s\n",
+ "[-p symbol_name pixel_value] Overwrite color defaults.");
+ fprintf(stderr, "%s\n",
+ "[-closecolors] Try to use `close' colors.");
+ fprintf(stderr, "%s\n",
+ "[-plaid] Read the included plaid pixmap.");
+ fprintf(stderr, "%s\n",
+ "[filename] Read from file 'filename', and from \
+standard");
+ fprintf(stderr, "%s\n",
+ " input if 'filename' is '-'.");
+ fprintf(stderr, "%s\n",
+ "[-o filename] Write to file 'filename', and to \
+standard");
+ fprintf(stderr, "%s\n",
+ " output if 'filename' is '-'.");
+ fprintf(stderr, "%s\n",
+ "[-nod] Don't display in window.");
+ fprintf(stderr, "%s\n",
+ "[-rgb filename] Search color names in the \
+rgb text file 'filename'.");
+ fprintf(stderr, "%s\n",
+ "[-c] Use a private colormap.");
+ fprintf(stderr, "%s\n\n",
+ "[-v] Verbose - print out extensions.");
+ fprintf(stderr, "%s\n\n",
+ "if no input is specified sxpm reads from standard input.");
+ exit(0);
+}
+
+
+void
+ErrorMessage(ErrorStatus, tag)
+ int ErrorStatus;
+ char *tag;
+{
+ char *error = NULL;
+ char *warning = NULL;
+
+ switch (ErrorStatus) {
+ case XpmSuccess:
+ return;
+ case XpmColorError:
+ warning = "Could not parse or alloc requested color";
+ break;
+ case XpmOpenFailed:
+ error = "Cannot open file";
+ break;
+ case XpmFileInvalid:
+ error = "Invalid XPM file";
+ break;
+ case XpmNoMemory:
+ error = "Not enough memory";
+ break;
+ case XpmColorFailed:
+ error = "Failed to parse or alloc some color";
+ break;
+ }
+
+ if (warning)
+ printf("%s Xpm Warning: %s.\n", tag, warning);
+
+ if (error) {
+ printf("%s Xpm Error: %s.\n", tag, error);
+ Punt(1);
+ }
+}
+
+void
+Punt(i)
+ int i;
+{
+ if (icon.pixmap) {
+ XFreePixmap(dpy, icon.pixmap);
+ if (icon.mask)
+ XFreePixmap(dpy, icon.mask);
+
+ XFreeColors(dpy, colormap,
+ icon.attributes.pixels, icon.attributes.npixels, 0);
+
+ XpmFreeAttributes(&icon.attributes);
+ }
+ if (view.pixmap) {
+ XFreePixmap(dpy, view.pixmap);
+ if (view.mask)
+ XFreePixmap(dpy, view.mask);
+
+ XFreeColors(dpy, colormap,
+ view.attributes.pixels, view.attributes.npixels, 0);
+
+ XpmFreeAttributes(&view.attributes);
+ }
+ exit(i);
+}
+
+void
+kinput(widget, tag, xe, b)
+ Widget widget;
+ char *tag;
+ XEvent *xe;
+ Boolean *b;
+{
+ char c = '\0';
+
+ XLookupString(&(xe->xkey), &c, 1, NULL, NULL);
+ if (c == 'q' || c == 'Q')
+ Punt(0);
+}
diff --git a/src/xpm/sxpm.man b/src/xpm/sxpm.man
new file mode 100644
index 0000000..28b6d44
--- /dev/null
+++ b/src/xpm/sxpm.man
@@ -0,0 +1,89 @@
+.\"Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT
+.TH SXPM 1
+.PD
+.ad b
+.SH NAME
+sxpm \- Show an XPM (X PixMap) file and/or convert XPM2 files to XPM version 3.
+.SH SYNOPSIS
+\fBsxpm\fR
+[\|\fB-d\fR displayname\|]
+[\|\fB-g\fR geometry\|]
+[\|\fB-hints\fR\|]
+[\|\fB-icon\fR filename\|]
+[\|\fB-s\fR symbol color_name\|]
+[\|\fB-p\fR symbol pixel_value\|]
+[\|\fB-plaid\| | \|\fRfilename\| | \|-\|]
+[\|\fB-o\fR filename\| | \|\fB-o\fR -\|]
+[\|\fB-nod\fR\|]
+[\|\fB-rgb\fR filename\|]
+[\|\fB-c\fR\|]
+[\|\fB-v\fR\|]
+.SH DESCRIPTION
+.PP
+The \fIsxpm\fP program can be used to view any XPM (version 2 or 3) file and/or
+to convert a file from XPM2 to XPM version 3. If \fIsxpm\fP is run without any
+option specified, the usage is displayed. If no geometry is specified, the
+show window will have the size of the read pixmap. Pressing the key Q in the
+window will quit the program.
+.SH OPTIONS
+.TP 8
+.B \-d \fIdisplay\fP
+Specifies the display to connect to.
+.TP 8
+.B \-g \fIgeom\fP
+Window geometry (default is pixmap's size).
+.TP 8
+.B \-hints
+Set ResizeInc for window.
+.TP 8
+.B \-icon \fIfilename\fP
+Set icon to pixmap created from the file \fIfilename\fP.
+.TP 8
+.B \-s \fIsymbol colorname\fP
+Overwrite default color to \fIsymbol\fP to \fIcolorname\fp.
+.TP 8
+.B \-p \fIsymbol pixelvalue\fP
+Overwrite default color to \fIsymbol\fP to \fIpixelvalue\fp.
+.TP 8
+.B \-closecolors
+Try to use "close colors" before reverting to other visuals.
+.TP 8
+.B \-plaid
+Show the plaid pixmap which is stored as data\fP.
+.TP 8
+.B \fIfilename\fP
+Read from the file \fIfilename\fP and from standard input if \fIfilename\fP is '-'.
+If no input is specified sxpm reads from standard input.
+.TP 8
+.B \-o \fIfilename\fP
+Write to the file \fIfilename\fP (overwrite if it already exists) and to
+standard output if \fIfilename\fP is '-'.
+.TP 8
+.B \-nod
+Do not display the pixmap in a window. (Useful when using as converter)
+.TP 8
+.B \-rgb \fIfilename\fP
+Search color names in the file \fIfilename\fP and write them out instead of
+the rgb values.
+.TP 8
+.B \-c
+To use a private colormap.
+.TP 8
+.B \-v
+Verbose - to print out extensions (stderr).
+
+
+.SH KNOWN BUGS
+When converting a file from XPM2 to XPM version 3, if several pixels (symbols)
+get the same color only one will be in the file written out.
+.br
+Some window managers may not accept a pixmap which is not a bitmap as icon
+because this does not respect ICCCM, many of the well known ones will accept
+it though.
+
+.SH AUTHOR
+Arnaud Le Hors (lehors@sophia.inria.fr)
+.br
+Bull Research France
+.br
+Copyright (C) 1990-92,92 by Groupe Bull.
diff --git a/src/xpm/xpm.h b/src/xpm/xpm.h
new file mode 100644
index 0000000..e12b42c
--- /dev/null
+++ b/src/xpm/xpm.h
@@ -0,0 +1,237 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* xpm.h: *
+* *
+* XPM library *
+* Include file *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+#ifndef XPM_h
+#define XPM_h
+
+#ifdef VMS
+#include "decw$include:Xlib.h"
+#include "decw$include:Intrinsic.h"
+#include "sys$library:stdio.h"
+#else
+#include <stdio.h>
+#include <X11/Xlib.h>
+#include <X11/Intrinsic.h>
+#endif
+
+/* we keep the same codes as for Bitmap management */
+#ifndef _XUTIL_H_
+#ifdef VMS
+#include "decw$include:Xutil.h"
+#else
+#include <X11/Xutil.h>
+#endif
+#endif
+
+/* Return ErrorStatus codes:
+ * null if full success
+ * positive if partial success
+ * negative if failure
+ */
+
+#define XpmColorError 1
+#define XpmSuccess 0
+#define XpmOpenFailed -1
+#define XpmFileInvalid -2
+#define XpmNoMemory -3
+#define XpmColorFailed -4
+
+
+typedef struct {
+ char *name; /* Symbolic color name */
+ char *value; /* Color value */
+ Pixel pixel; /* Color pixel */
+} XpmColorSymbol;
+
+typedef struct {
+ char *name; /* name of the extension */
+ unsigned int nlines; /* number of lines in this extension */
+ char **lines; /* pointer to the extension array of
+ strings */
+} XpmExtension;
+
+typedef struct {
+ unsigned long valuemask; /* Specifies which attributes are
+ * defined */
+
+ Visual *visual; /* Specifies the visual to use */
+ Colormap colormap; /* Specifies the colormap to use */
+ unsigned int depth; /* Specifies the depth */
+ unsigned int width; /* Returns the width of the created
+ * pixmap */
+ unsigned int height; /* Returns the height of the created
+ * pixmap */
+ unsigned int x_hotspot; /* Returns the x hotspot's
+ * coordinate */
+ unsigned int y_hotspot; /* Returns the y hotspot's
+ * coordinate */
+ unsigned int cpp; /* Specifies the number of char per
+ * pixel */
+ Pixel *pixels; /* List of used color pixels */
+ unsigned int npixels; /* Number of pixels */
+ XpmColorSymbol *colorsymbols; /* Array of color symbols to
+ * override */
+ unsigned int numsymbols; /* Number of symbols */
+ char *rgb_fname; /* RGB text file name */
+ unsigned int nextensions; /* number of extensions */
+ XpmExtension *extensions; /* pointer to array of extensions */
+
+ /* Infos */
+ unsigned int ncolors; /* Number of colors */
+ char ***colorTable; /* Color table pointer */
+ char *hints_cmt; /* Comment of the hints section */
+ char *colors_cmt; /* Comment of the colors section */
+ char *pixels_cmt; /* Comment of the pixels section */
+ unsigned int mask_pixel; /* Transparent pixel's color table
+ * index */
+ /* Color Allocation Directives */
+ unsigned int exactColors; /* Only use exact colors for visual */
+ unsigned int closeness; /* Allowable RGB deviation */
+
+} XpmAttributes;
+
+/* Xpm attribute value masks bits */
+#define XpmVisual (1L<<0)
+#define XpmColormap (1L<<1)
+#define XpmDepth (1L<<2)
+#define XpmSize (1L<<3) /* width & height */
+#define XpmHotspot (1L<<4) /* x_hotspot & y_hotspot */
+#define XpmCharsPerPixel (1L<<5)
+#define XpmColorSymbols (1L<<6)
+#define XpmRgbFilename (1L<<7)
+#define XpmInfos (1L<<8) /* all infos members */
+#define XpmExtensions (1L<<10)
+
+#define XpmReturnPixels (1L<<9)
+#define XpmReturnInfos XpmInfos
+#define XpmReturnExtensions XpmExtensions
+
+#define XpmExactColors (1L<<11)
+#define XpmCloseness (1L<<12)
+
+/*
+ * minimal portability layer between ansi and KR C
+ */
+
+/* forward declaration of functions with prototypes */
+
+#if __STDC__ || defined(__cplusplus) || defined(c_plusplus)
+ /* ANSI || C++ */
+#define FUNC(f, t, p) extern t f p
+#define LFUNC(f, t, p) static t f p
+#else /* K&R */
+#define FUNC(f, t, p) extern t f()
+#define LFUNC(f, t, p) static t f()
+#endif /* end of K&R */
+
+
+/*
+ * functions declarations
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ FUNC(XpmCreatePixmapFromData, int, (Display * display,
+ Drawable d,
+ char **data,
+ Pixmap * pixmap_return,
+ Pixmap * shapemask_return,
+ XpmAttributes * attributes));
+
+ FUNC(XpmCreateDataFromPixmap, int, (Display * display,
+ char ***data_return,
+ Pixmap pixmap,
+ Pixmap shapemask,
+ XpmAttributes * attributes));
+
+ FUNC(XpmReadFileToPixmap, int, (Display * display,
+ Drawable d,
+ char *filename,
+ Pixmap * pixmap_return,
+ Pixmap * shapemask_return,
+ XpmAttributes * attributes));
+
+ FUNC(XpmWriteFileFromPixmap, int, (Display * display,
+ char *filename,
+ Pixmap pixmap,
+ Pixmap shapemask,
+ XpmAttributes * attributes));
+
+ FUNC(XpmCreateImageFromData, int, (Display * display,
+ char **data,
+ XImage ** image_return,
+ XImage ** shapemask_return,
+ XpmAttributes * attributes));
+
+ FUNC(XpmCreateDataFromImage, int, (Display * display,
+ char ***data_return,
+ XImage * image,
+ XImage * shapeimage,
+ XpmAttributes * attributes));
+
+ FUNC(XpmReadFileToImage, int, (Display * display,
+ char *filename,
+ XImage ** image_return,
+ XImage ** shapeimage_return,
+ XpmAttributes * attributes));
+
+ FUNC(XpmWriteFileFromImage, int, (Display * display,
+ char *filename,
+ XImage * image,
+ XImage * shapeimage,
+ XpmAttributes * attributes));
+
+ FUNC(XpmAttributesSize, int, ());
+ FUNC(XpmFreeAttributes, int, (XpmAttributes * attributes));
+ FUNC(XpmFreeExtensions, int, (XpmExtension * extensions, int nextensions));
+
+#ifdef __cplusplus
+} /* for C++ V2.0 */
+
+#endif
+
+
+/* backward compatibility */
+
+/* for version 3.0c */
+#define XpmPixmapColorError XpmColorError
+#define XpmPixmapSuccess XpmSuccess
+#define XpmPixmapOpenFailed XpmOpenFailed
+#define XpmPixmapFileInvalid XpmFileInvalid
+#define XpmPixmapNoMemory XpmNoMemory
+#define XpmPixmapColorFailed XpmColorFailed
+
+#define XpmReadPixmapFile(dpy, d, file, pix, mask, att) \
+ XpmReadFileToPixmap(dpy, d, file, pix, mask, att)
+#define XpmWritePixmapFile(dpy, file, pix, mask, att) \
+ XpmWriteFileFromPixmap(dpy, file, pix, mask, att)
+
+/* for version 3.0b */
+#define PixmapColorError XpmColorError
+#define PixmapSuccess XpmSuccess
+#define PixmapOpenFailed XpmOpenFailed
+#define PixmapFileInvalid XpmFileInvalid
+#define PixmapNoMemory XpmNoMemory
+#define PixmapColorFailed XpmColorFailed
+
+#define ColorSymbol XpmColorSymbol
+
+#define XReadPixmapFile(dpy, d, file, pix, mask, att) \
+ XpmReadFileToPixmap(dpy, d, file, pix, mask, att)
+#define XWritePixmapFile(dpy, file, pix, mask, att) \
+ XpmWriteFileFromPixmap(dpy, file, pix, mask, att)
+#define XCreatePixmapFromData(dpy, d, data, pix, mask, att) \
+ XpmCreatePixmapFromData(dpy, d, data, pix, mask, att)
+#define XCreateDataFromPixmap(dpy, data, pix, mask, att) \
+ XpmCreateDataFromPixmap(dpy, data, pix, mask, att)
+
+#endif
diff --git a/src/xpm/xpmP.h b/src/xpm/xpmP.h
new file mode 100644
index 0000000..e65a68c
--- /dev/null
+++ b/src/xpm/xpmP.h
@@ -0,0 +1,279 @@
+/* Copyright 1990-92 GROUPE BULL -- See license conditions in file COPYRIGHT */
+/*****************************************************************************\
+* xpmP.h: *
+* *
+* XPM library *
+* Private Include file *
+* *
+* Developed by Arnaud Le Hors *
+\*****************************************************************************/
+
+#ifndef XPMP_h
+#define XPMP_h
+
+#ifdef Debug
+/* memory leak control tool */
+#include <mnemosyne.h>
+#endif
+
+#ifdef VMS
+#include "decw$include:Xlib.h"
+#include "decw$include:Intrinsic.h"
+#include "sys$library:stdio.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Intrinsic.h>
+/* stdio.h doesn't declare popen on a Sequent DYNIX OS */
+#ifdef sequent
+extern FILE *popen();
+#endif
+#endif
+
+#include "xpm.h"
+
+/* we keep the same codes as for Bitmap management */
+#ifndef _XUTIL_H_
+#ifdef VMS
+#include "decw$include:Xutil.h"
+#else
+#include <X11/Xutil.h>
+#endif
+#endif
+
+#if defined(SYSV) || defined(SVR4)
+#define bcopy(source, dest, count) memcpy(dest, source, count)
+#define bzero(addr, count) memset(addr, 0, count)
+#endif
+
+typedef struct {
+ unsigned int type;
+ union {
+ FILE *file;
+ char **data;
+ } stream;
+ char *cptr;
+ unsigned int line;
+ int CommentLength;
+ char Comment[BUFSIZ];
+ char *Bcmt, *Ecmt, Bos, Eos;
+} xpmData;
+
+#define XPMARRAY 0
+#define XPMFILE 1
+#define XPMPIPE 2
+
+typedef unsigned char byte;
+
+#define EOL '\n'
+#define TAB '\t'
+#define SPC ' '
+
+typedef struct {
+ char *type; /* key word */
+ char *Bcmt; /* string beginning comments */
+ char *Ecmt; /* string ending comments */
+ char Bos; /* character beginning strings */
+ char Eos; /* character ending strings */
+ char *Strs; /* strings separator */
+ char *Dec; /* data declaration string */
+ char *Boa; /* string beginning assignment */
+ char *Eoa; /* string ending assignment */
+} xpmDataType;
+
+extern xpmDataType xpmDataTypes[];
+
+/*
+ * rgb values and ascii names (from rgb text file) rgb values,
+ * range of 0 -> 65535 color mnemonic of rgb value
+ */
+typedef struct {
+ int r, g, b;
+ char *name;
+} xpmRgbName;
+
+/* Maximum number of rgb mnemonics allowed in rgb text file. */
+#define MAX_RGBNAMES 1024
+
+extern char *xpmColorKeys[];
+
+#define TRANSPARENT_COLOR "None" /* this must be a string! */
+
+/* number of xpmColorKeys */
+#define NKEYS 5
+
+/*
+ * key numbers for visual type, they must fit along with the number key of
+ * each corresponding element in xpmColorKeys[] defined in xpm.h
+ */
+#define MONO 2
+#define GRAY4 3
+#define GRAY 4
+#define COLOR 5
+
+/* structure containing data related to an Xpm pixmap */
+typedef struct {
+ char *name;
+ unsigned int width;
+ unsigned int height;
+ unsigned int cpp;
+ unsigned int ncolors;
+ char ***colorTable;
+ unsigned int *pixelindex;
+ XColor *xcolors;
+ char **colorStrings;
+ unsigned int mask_pixel; /* mask pixel's colorTable index */
+} xpmInternAttrib;
+
+#define UNDEF_PIXEL 0x80000000
+
+/* XPM private routines */
+
+FUNC(xpmWriteData, int, (xpmData * mdata,
+ xpmInternAttrib * attrib, XpmAttributes * attributes));
+
+FUNC(xpmCreateData, int, (char ***data_return,
+ xpmInternAttrib * attrib, XpmAttributes * attributes));
+
+FUNC(xpmParseDataAndCreateImage, int, (xpmData * data,
+ Display * display,
+ XImage ** image_return,
+ XImage ** shapeimage_return,
+ xpmInternAttrib * attrib_return,
+ XpmAttributes * attributes));
+
+FUNC(xpmCreateImage, int, (Display * display,
+ xpmInternAttrib * attrib,
+ XImage ** image_return,
+ XImage ** shapeimage_return,
+ XpmAttributes * attributes));
+
+FUNC(xpmParseData, int, (xpmData * data,
+ xpmInternAttrib * attrib_return,
+ XpmAttributes * attributes));
+
+FUNC(xpmScanImage, int, (Display * display,
+ XImage * image,
+ XImage * shapeimage,
+ XpmAttributes * attributes,
+ xpmInternAttrib * attrib));
+
+FUNC(xpmFreeColorTable, int, (char ***colorTable, int ncolors));
+
+FUNC(xpmInitInternAttrib, int, (xpmInternAttrib * xmpdata));
+
+FUNC(xpmFreeInternAttrib, int, (xpmInternAttrib * xmpdata));
+
+FUNC(xpmSetAttributes, int, (xpmInternAttrib * attrib,
+ XpmAttributes * attributes));
+
+FUNC(xpmGetAttributes, int, (XpmAttributes * attributes,
+ xpmInternAttrib * attrib));
+
+/* I/O utility */
+
+FUNC(xpmNextString, int, (xpmData * mdata));
+FUNC(xpmNextUI, int, (xpmData * mdata, unsigned int *ui_return));
+
+#define xpmGetC(mdata) \
+ (mdata->type ? (getc(mdata->stream.file)) : (*mdata->cptr++))
+
+FUNC(xpmNextWord, unsigned int, (xpmData * mdata, char *buf));
+FUNC(xpmGetCmt, int, (xpmData * mdata, char **cmt));
+FUNC(xpmReadFile, int, (char *filename, xpmData * mdata));
+FUNC(xpmWriteFile, int, (char *filename, xpmData * mdata));
+FUNC(xpmOpenArray, void, (char **data, xpmData * mdata));
+FUNC(XpmDataClose, int, (xpmData * mdata));
+
+/* RGB utility */
+
+FUNC(xpmReadRgbNames, int, (char *rgb_fname, xpmRgbName * rgbn));
+FUNC(xpmGetRgbName, char *, (xpmRgbName * rgbn, int rgbn_max,
+ int red, int green, int blue));
+FUNC(xpmFreeRgbNames, void, (xpmRgbName * rgbn, int rgbn_max));
+
+FUNC(xpm_xynormalizeimagebits, void, (register unsigned char *bp,
+ register XImage * img));
+FUNC(xpm_znormalizeimagebits, void, (register unsigned char *bp,
+ register XImage * img));
+
+/*
+ * Macros
+ *
+ * The XYNORMALIZE macro determines whether XY format data requires
+ * normalization and calls a routine to do so if needed. The logic in
+ * this module is designed for LSBFirst byte and bit order, so
+ * normalization is done as required to present the data in this order.
+ *
+ * The ZNORMALIZE macro performs byte and nibble order normalization if
+ * required for Z format data.
+ *
+ * The XYINDEX macro computes the index to the starting byte (char) boundary
+ * for a bitmap_unit containing a pixel with coordinates x and y for image
+ * data in XY format.
+ *
+ * The ZINDEX* macros compute the index to the starting byte (char) boundary
+ * for a pixel with coordinates x and y for image data in ZPixmap format.
+ *
+ */
+
+#define XYNORMALIZE(bp, img) \
+ if ((img->byte_order == MSBFirst) || (img->bitmap_bit_order == MSBFirst)) \
+ xpm_xynormalizeimagebits((unsigned char *)(bp), img)
+
+#define ZNORMALIZE(bp, img) \
+ if (img->byte_order == MSBFirst) \
+ xpm_znormalizeimagebits((unsigned char *)(bp), img)
+
+#define XYINDEX(x, y, img) \
+ ((y) * img->bytes_per_line) + \
+ (((x) + img->xoffset) / img->bitmap_unit) * (img->bitmap_unit >> 3)
+
+#define ZINDEX(x, y, img) ((y) * img->bytes_per_line) + \
+ (((x) * img->bits_per_pixel) >> 3)
+
+#define ZINDEX32(x, y, img) ((y) * img->bytes_per_line) + ((x) << 2)
+
+#define ZINDEX16(x, y, img) ((y) * img->bytes_per_line) + ((x) << 1)
+
+#define ZINDEX8(x, y, img) ((y) * img->bytes_per_line) + (x)
+
+#define ZINDEX1(x, y, img) ((y) * img->bytes_per_line) + ((x) >> 3)
+
+#if __STDC__
+#define Const const
+#else
+#define Const /**/
+#endif
+
+/*
+ * there are structures and functions related to hastable code
+ */
+
+typedef struct _xpmHashAtom {
+ char *name;
+ void *data;
+} *xpmHashAtom;
+
+typedef struct {
+ int size;
+ int limit;
+ int used;
+ xpmHashAtom *atomTable;
+} xpmHashTable;
+
+FUNC(xpmHashTableInit, int, (xpmHashTable *table));
+FUNC(xpmHashTableFree, void, (xpmHashTable *table));
+FUNC(xpmHashSlot, xpmHashAtom *, (xpmHashTable *table, char *s));
+FUNC(xpmHashIntern, int, (xpmHashTable *table, char *tag, void *data));
+
+#define HashAtomData(i) ((void *)i)
+#define HashColorIndex(slot) ((unsigned int)(unsigned long)((*slot)->data))
+#define USE_HASHTABLE (cpp > 2 && ncolors > 4)
+
+#ifdef NEED_STRDUP
+FUNC(strdup, char *, (char *s1));
+#endif
+
+#endif