/* xpixmap.c: * * This has been mangled to work with Chimera. It has also been "fixed" * so that it handles XPM3 according to the document on ftp.x.org. * this code is really slow...probably because it asks the server about * every color. * john@cs.unlv.edu * * XPixMap format file read and identify routines. these can handle any * "format 1" XPixmap file with up to BUFSIZ - 1 chars per pixel. it's * not nearly as picky as it might be. * * unlike most image loading routines, this is X specific since it * requires X color name parsing. * * Copyright 1989 Jim Frost. See included file "copyright.h" for complete * copyright information. */ #include "common.h" #include "copyright.h" #include "xloadimage.h" /* SUPPRESS 530 */ /* SUPPRESS 560 */ static unsigned char *xpixmap_data; static int xpixmap_datalen; static int xpixmap_pos; /* * read data */ static int xpixmap_read(b, blen) unsigned char *b; int blen; { if (xpixmap_datalen < blen + xpixmap_pos) return(0); memcpy(b, xpixmap_data + xpixmap_pos, blen); xpixmap_pos += blen; return(blen); } /* * xpixmap_gets */ static int xpixmap_gets(b, blen) unsigned char *b; int blen; { int i; unsigned char x; for (i = 0; i < blen - 1; i++) { if (xpixmap_read(&x, 1) == 0) return(0); if (x == '\r') { xpixmap_read(&x, 1); break; } else if (x == '\n') break; b[i] = x; } b[i] = '\0'; return(i); } /* * xpixmap_getc */ static int xpixmap_getc() { unsigned char b; if (xpixmap_read(&b, 1) == 1) return((int)b); return(EOF); } Image *xpixmapLoad(Disp, Scrn, data, datalen, bg) Display *Disp; int Scrn; unsigned char *data; int datalen; RGBColor *bg; { char buf[BUFSIZ]; char cval[BUFSIZ]; char key; char pixel[BUFSIZ]; unsigned int value; unsigned int w, h; /* image dimensions */ unsigned int cpp; /* chars per pixel */ unsigned int ncolors; /* number of colors */ unsigned int hx, hy; /* hot spot */ unsigned int depth; /* depth of image */ char **ctable; /* color table */ Image *image; XColor xcolor; unsigned int a, x, y; int c; byte *dptr; /* read #defines until we have all that are necessary or until we * get an error */ xpixmap_data = data; xpixmap_datalen = datalen; xpixmap_pos = 0; /* header */ if (xpixmap_gets(buf, BUFSIZ - 1) == 0) return(NULL); if (strcmp(buf, "/* XPM */") != 0) return(NULL); /* declaration and beginning of assignment line */ if (xpixmap_gets(buf, BUFSIZ - 1) == 0) return(NULL); /* values */ for (;;) { if (xpixmap_gets(buf, BUFSIZ - 1) == 0) return(NULL); if (buf[0] == '"') break; } w = h = ncolors = cpp = hx = hy = 0; sscanf(buf, "\"%d %d %d %d %d %d\",", &w, &h, &ncolors, &cpp, &hx, &hy); if (w == 0 || h == 0 || ncolors == 0 || cpp == 0) return(NULL); for (depth= 1, value= 2; value < ncolors; value <<= 1, depth++) ; image = newRGBImage(w, h, depth); image->rgb.used = ncolors; /* colors */ /* values */ for (;;) { if (xpixmap_gets(buf, BUFSIZ - 1) == 0) return(NULL); if (buf[0] == '"') break; } ctable= (char **)alloc_mem(sizeof(char *) * ncolors); xcolor.flags= DoRed | DoGreen | DoBlue; for (a = 0; a < ncolors; a++) { *(ctable + a)= (char *)alloc_mem(cpp); buf[strlen(buf) - 2] = '\0'; sscanf(buf + 1, "%s %s %s", pixel, &key, cval); strncpy(*(ctable + a), pixel, cpp); if (Disp) { if (strcasecmp(cval, "None") == 0 ) { *(image->rgb.red + a) = bg->red; *(image->rgb.green + a) = bg->green; *(image->rgb.blue + a) = bg->blue; } else if (!XParseColor(Disp, DefaultColormap(Disp, Scrn), cval, &xcolor)) { return(NULL); } else { *(image->rgb.red + a) = xcolor.red; *(image->rgb.green + a) = xcolor.green; *(image->rgb.blue + a) = xcolor.blue; } } if (xpixmap_gets(buf, BUFSIZ - 1) == 0) return(NULL); } /* pixels */ dptr= image->data; for (y= 0; y < h; y++) { while (((c = xpixmap_getc()) != EOF) && (c != '"')) ; for (x = 0; x < w; x++) { for (a = 0; a < cpp; a++) { if ((c = xpixmap_getc()) == '\\') c = xpixmap_getc(); if (c == EOF) return(NULL); buf[a] = (char)c; } for (a = 0; a < ncolors; a++) { if (!strncmp(*(ctable + a), buf, cpp)) break; } if (a == ncolors) return(NULL); valToMem((unsigned long)a, dptr, image->pixlen); dptr += image->pixlen; } if ((c = xpixmap_getc()) != '"') return(NULL); } return(image); }