#ident "@(#)readfiles.c 1.12 91/04/03 XGRASP" /*- * readfiles.c - routines to load images, fonts, and execution files. * * Copyright (c) 1991 by Patrick J. Naughton * * 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 file is provided AS IS with no warranties of any kind. The author * shall have no liability with respect to the infringement of copyrights, * trade secrets or any patents by this file or any part thereof. In no * event will the author be liable for any lost revenue or profits or * other special, indirect and consequential damages. * * Comments and additions should be sent to the author: * * Patrick J. Naughton * Sun Microsystems * 2550 Garcia Ave, MS 10-20 * Mountain View, CA 94043 * (415) 336-1080 * */ #include "grasp.h" ImageStruct *image[MAXIMAGES]; int numimages = 0; FontStruct *font[MAXFONTS]; int numfonts = 0; ExecStruct *exec[MAXEXECS]; int numexecs = 0; extern ImageStruct *readgifimage(); void lowerstr(s) char *s; { while (*s) { if (*s >= 'A' && *s <= 'Z') *s = *s + 'a' - 'A'; s++; } } void hexdump(fp, n) FILE *fp; int n; { long ofs = ftell(fp); int i, j; u_char b[16]; for (j = 0; j < n; j++) { for (i = 0; i < 16; i++) { b[i] = GetByte(fp); printf("%02x ", b[i]); } printf(" "); for (i = 0; i < 16; i++) printf("%c ", isprint(b[i]) ? b[i] : '.'); printf("\n"); } fseek(fp, ofs, 0); } /*- Border Color Table Color Color Palette 1 2 3 ----- ----- ------- ----------------------------------- 0 Black 0 Green Red Brown 1 Blue 1 Cyan Magenta White 2 Green 2 Cyan Red White 3 Cyan 3 Bright Green Bright Red Yellow 4 Red 4 Bright Cyan Bright Magenta White 5 Magenta 5 Bright Cyan Bright Red White 6 Brown ------------------------------------------- 7 Grey 8 Dark Grey (Bright Black) 9 Bright Blue 10 Bright Green 11 Bright Cyan 12 Bright Red 13 Bright Magenta 14 Yellow (Bright Brown) 15 White (Bright Grey) */ u_short egapal[16][3] = { {0x0000, 0x0000, 0x0000}, {0x0000, 0x0000, 0xaaaa}, {0x0000, 0xaaaa, 0x0000}, {0x0000, 0xaaaa, 0xaaaa}, {0xaaaa, 0x0000, 0x0000}, {0xaaaa, 0x0000, 0xaaaa}, {0xaaaa, 0x5555, 0x0000}, {0xaaaa, 0xaaaa, 0xaaaa}, {0x5555, 0x5555, 0x5555}, {0x5555, 0x5555, 0xffff}, {0x5555, 0xffff, 0x5555}, {0x5555, 0xffff, 0xffff}, {0xffff, 0x5555, 0x5555}, {0xffff, 0x5555, 0xffff}, {0xffff, 0xffff, 0x5555}, {0xffff, 0xffff, 0xffff} }; int cgapal[3][6] = { {2, 3, 3, 10, 11, 11}, {4, 5, 4, 12, 13, 12}, {6, 15, 15, 14, 15, 15} }; Colormap CreateEGAcmap() { Colormap cmap; XColor colors[16]; u_long pixels[16]; u_long pmasks; int i; cmap = XCreateColormap(dsp, win, vis, AllocNone); XAllocColorCells(dsp, cmap, True, &pmasks, 0, pixels, 16); for (i = 0; i < 16; i++) { colors[i].pixel = pixels[i]; colors[i].red = egapal[i][0]; colors[i].green = egapal[i][1]; colors[i].blue = egapal[i][2]; colors[i].flags = DoRed | DoGreen | DoBlue; } XStoreColors(dsp, cmap, colors, 16); return cmap; } int findext(s) char *s; { int i; static char *exts[] = { "pic", "pcx", "pal", "clp", "gif", "set", "fnt", "txt" }; static int extcodes[] = { EXT_PIC, EXT_PCX, EXT_PAL, EXT_CLP, EXT_GIF, EXT_SET, EXT_FNT, EXT_TXT }; ++s; /* get past the dot */ for (i = 0; i < (sizeof exts / sizeof exts[0]); i++) if (!strcmp(s, exts[i])) return extcodes[i]; return -1; } void stringtofont(ex, i) ExecStruct *ex; { int k; char *s = strtok(ex->Code[i].val.s, "."); lowerstr(s); for (k = 0; k < numfonts; k++) { if (!strcmp(font[k]->name, s)) { free(ex->Code[i].val.s); ex->Code[i].token = FONTTYPE; ex->Code[i].val.font = font[k]; break; } } if (k == numfonts) { printf("font \"%s\" referenced but not in directory.\n", s); ex->Code[i].token = FONTTYPE; ex->Code[i].val.font = 0; } } void stringtoimage(ex, i, deftype) ExecStruct *ex; int i; int deftype; { int k; char *s = strtok(ex->Code[i].val.s, "."); char *ext = strrchr(ex->Code[i].val.s, '.'); if (ext) { int extcode = findext(ext); for (k = 0; k < numimages; k++) { if (!strcmp(image[k]->name, s) && image[k]->type == extcode) { free(ex->Code[i].val.s); ex->Code[i].token = IMAGE; ex->Code[i].val.image = image[k]; break; } } } else { for (k = 0; k < numimages; k++) { if (!strcmp(image[k]->name, s)) { /* * this might be the second time through here, so don't free * the string more than once... */ if (ex->Code[i].token == STRING) { free(ex->Code[i].val.s); ex->Code[i].token = IMAGE; } ex->Code[i].val.image = image[k]; if (image[k]->type == deftype) break; } } } if (ex->Code[i].token != IMAGE) error("%s: image \"%s\" referenced but not in directory.\n", s); } void stringtolabel(ex, i) ExecStruct *ex; int i; { int k; char *s = strtok(ex->Code[i].val.s, "."); lowerstr(s); for (k = 0; k < ex->numlabels; k++) { if (!strcmp(s, ex->label[k].string)) { free(ex->Code[i].val.s); ex->Code[i].token = INTEGER; ex->Code[i].val.i = ex->label[k].ipaddr; break; } if (k == ex->numlabels) error("%s: label \"%s\" referenced but not found.\n", s); } } void stringtoexec(ex, i) ExecStruct *ex; int i; { int k; char *s = strtok(ex->Code[i].val.s, "."); lowerstr(s); for (k = 0; k < numexecs; k++) { if (!strcmp(exec[k]->name, s)) { free(ex->Code[i].val.s); ex->Code[i].token = EXECTYPE; ex->Code[i].val.exec = exec[k]; break; } } if (k == numexecs) error("%s: exec \"%s\" referenced but not in directory.\n", s); } int calcwidth(data, width, height, left) u_char *data; int width; int height; int *left; { int bpsl = (width + 7) >> 3; int right; int mask; int i; int j; /*find left */ *left = 0; for (i = 0; i < bpsl; i++) { for (mask = 0x80; mask > 0; mask >>= 1) { for (j = 0; j < height; j++) { if (data[j * bpsl + i] & mask) goto calcright; } (*left)++; } } *left = 0; return width / 2; /* must be the space char... */ calcright:/* find right */ right = bpsl * 8; for (i = bpsl - 1; i >= 0; i--) { for (mask = 0x01; mask < 0x100; mask <<= 1) { for (j = 0; j < height; j++) { if (data[j * bpsl + i] & mask) return right - *left; } right--; } } error("%s: bad width calc."); } FontStruct * readfont(fp, dirent) FILE *fp; FilenameStruct *dirent; { FontStruct *font; XImage xim; int first; int num; int datasize; int i; char *data; fseek(fp, dirent->offset, 0); font = (FontStruct *) malloc(sizeof(FontStruct)); font->name = strtok(strdup(dirent->fname), "."); (void) GetLong(fp); /* skip file length */ (void) GetWord(fp); /* skip length */ if (imverbose) hexdump(fp, 4); num = GetByte(fp); /* hack for trashed fonts... */ if (num == -1) { free(font->name); free(font); return (FontStruct *) 0; } first = GetByte(fp); font->width = GetByte(fp); font->height = GetByte(fp); datasize = GetByte(fp); data = (char *) malloc(datasize); if (!data) error("%s: couldn't malloc glyph memory\n"); if (verbose) fprintf(stderr, "%s: (FNT) %d %dx%d,%d(%d) glyphs, from %d to %d\n", font->name, num, font->width, font->height, datasize, font->height * ((font->width + 7) >> 3), first, first + num - 1); xim.height = font->height; xim.width = font->width; xim.depth = 1; xim.xoffset = 0; xim.format = XYBitmap; xim.data = data; xim.byte_order = MSBFirst; xim.bitmap_unit = 8; xim.bitmap_bit_order = MSBFirst; xim.bitmap_pad = 8; xim.bytes_per_line = (font->width + 7) / 8; for (i = 0; i < 256; i++) { if (i >= first && i < first + num) { fread(data, datasize, 1, fp); font->glyphs[i].width = calcwidth(data, font->width, font->height, &font->glyphs[i].lbearing); font->glyphs[i].pix = XCreatePixmap(dsp, win, font->width, font->height, 1); XPutImage(dsp, font->glyphs[i].pix, gc1, &xim, 0, 0, 0, 0, font->width, font->height); } else { font->glyphs[i].pix = (Pixmap) 0; font->glyphs[i].width = 0; font->glyphs[i].lbearing = 0; } } free(data); return font; } FontStruct * readset(fp, dirent) FILE *fp; FilenameStruct *dirent; { FontStruct *font; XImage xim; int first; int num; int datasize; int i; char *data; char fontname[14]; int type; int checktype; int fontascent; int proportional; int bpsl; int lfgap; int italics; int fntinvert; int fnthbold; int fntvbold; int fnthmag; int fntvmag; int fnthfract; int fntvfract; int fntdirection; int fntrot90; int fnthflip; int fntvflip; int fntcolor; int fntsubtype; char unused[18]; int dataofs; int celloffs[256]; int cellwidth[256]; fseek(fp, dirent->offset, 0); (void) GetLong(fp); /* skip file length */ if (imverbose) hexdump(fp, 4); /* non-compressed type = 0x10 or compressed type = 0x14 */ type = GetByte(fp); if (type != 0x10 && type != 0x14) return readfont(fp, dirent); fread(fontname, 13, 1, fp); fontname[13] = 0; /* non-compressed font = 0xba, compressed font = 0xdc */ checktype = GetByte(fp); font = (FontStruct *) malloc(sizeof(FontStruct)); font->name = strtok(strdup(dirent->fname), "."); fontascent = GetByte(fp); num = GetByte(fp); /* limited to the lower 94 ASCII characters: 0x21 - 0x7E */ first = GetByte(fp) + 0x20; proportional = GetByte(fp); /* 0 = non-proportional */ font->width = GetByte(fp); font->height = GetByte(fp); bpsl = GetByte(fp); datasize = font->height * bpsl; spacegap = GetByte(fp); chargap = GetByte(fp); lfgap = GetByte(fp); (void) GetWord(fp); /* skip file length */ italics = GetByte(fp); fntinvert = GetByte(fp); /* 0 = dont invert, 1 = invert */ fnthbold = GetByte(fp); /* number of overlapping bits horizontal */ fntvbold = GetByte(fp); /* number of overlapping bits vertical */ fnthmag = GetByte(fp); /* integral horizontal bit magnification */ fntvmag = GetByte(fp); /* integral vertical bit magnification */ fnthfract = GetByte(fp); /* fractional horizontal bit magnification */ fntvfract = GetByte(fp); /* fractional vertical bit magnification */ fntdirection = GetByte(fp); /* Print direction 0 = left to right, 1...3 = * counterclock 1...3 */ fntrot90 = GetByte(fp); /* rotation 0 = up, 1...3 = counterclock 1...3 */ fnthflip = GetByte(fp); /* horizontal flip 0 = no, 1 = yes */ fntvflip = GetByte(fp); /* vertical flip 0 = no, 1 = yes */ fntcolor = GetByte(fp); /* color of font */ fntsubtype = GetByte(fp); /* subcategory type of this font */ fread(unused, 18, 1, fp); if (verbose) fprintf(stderr, "%s[%s]: (SET) %d %dx%d,%d %sglyphs, from %d to %d\n", font->name, fontname, num, font->width, font->height, datasize, proportional ? "var-" : "fixed-", first, first + num - 1); if (type == 0x10) { for (i = 0; i <= num; i++) celloffs[i] = GetWord(fp); if (proportional) { for (i = 0; i <= num; i++) cellwidth[i] = GetByte(fp); } dataofs = ftell(fp) - dirent->offset + 4; data = (char *) malloc(datasize * num); if (!data) error("%s: couldn't malloc glyph memory\n"); fread(data, num, datasize, fp); xim.width = font->width; xim.height = font->height; xim.depth = 1; xim.xoffset = 0; xim.format = XYBitmap; xim.data = 0; xim.byte_order = MSBFirst; xim.bitmap_unit = 8; xim.bitmap_bit_order = MSBFirst; xim.bitmap_pad = 8; xim.bytes_per_line = bpsl; for (i = 0; i < 256; i++) { font->glyphs[i].pix = (Pixmap) 0; font->glyphs[i].width = 0; font->glyphs[i].lbearing = 0; } for (i = 0; i <= num; i++) { int j = first + i - 1; font->glyphs[j].lbearing = 0; font->glyphs[j].width = proportional ? cellwidth[i] : font->width; font->glyphs[j].pix = XCreatePixmap(dsp, win, font->glyphs[j].width, font->height, 1); xim.data = &data[celloffs[i] - dataofs]; XPutImage(dsp, font->glyphs[j].pix, gc1, &xim, 0, 0, 0, 0, font->glyphs[j].width, font->height); } free(data); } else { printf("dont do compressed SET's yet.\n"); } return font; } ImageStruct * readimage(fp, dirent, filetype) FILE *fp; FilenameStruct *dirent; int filetype; { ImageStruct *im; XImage *xim; int i; int j; int format; int bpsl; int blocks; int datasize; long blockoffset; u_char *ptr; int bpp; int planes; int idx; int magic; int unknown; int type; int edesc; int exsize; int maxcolorval; u_long pixels[256]; u_long pmasks; int filelen; im = (ImageStruct *) malloc(sizeof(ImageStruct)); fseek(fp, dirent->offset, 0); filelen = GetLong(fp); /* length of whole image file... */ if (imverbose) hexdump(fp, 4); im->name = strtok(strdup(dirent->fname), "."); im->type = filetype; magic = GetWord(fp); if (magic != 0x1234) { /* I'm guessing here */ im->w = GetWord(fp); im->h = GetWord(fp); printf("%dx%d %d, %d, %d, %d\n", im->w, im->h, im->w * im->h / 4, magic - 6, ((im->w + 3) >> 2) * im->h, filelen - 6); im->xoff = 0; im->yoff = 0; bpp = 2; planes = 1; type = 'a'; edesc = 1; exsize = 0; } else { im->w = GetWord(fp); im->h = GetWord(fp); im->xoff = GetWord(fp); im->yoff = GetWord(fp); bpp = GetByte(fp); planes = ((bpp & 0xf0) >> 4) + 1; bpp &= 0x0f; if (GetByte(fp) != 0xff) error("%s: %s is corrupt\n", im->name); type = GetByte(fp); edesc = GetWord(fp); exsize = GetWord(fp); } if (bpp == 1 && planes == 1) { im->d = 1; format = XYBitmap; bpsl = (im->w + 7) >> 3; XSetForeground(dsp, gc, white); XSetBackground(dsp, gc, black); } else { im->d = 8; format = ZPixmap; bpsl = im->w; } datasize = bpsl * im->h; ptr = (u_char *) malloc(datasize); if (!ptr) error("%s: malloc failed on image data.\n"); if (verbose) printf( "%s: (PIC) %dx%dx%d(%1x:%1x) [%d,%d] sz=%d t=%c edesc=%02x ext=%d\n", im->name, im->w, im->h, im->d, bpp, planes, im->xoff, im->yoff, datasize, type, edesc, exsize); if (edesc != 0) im->cmap = XCreateColormap(dsp, win, vis, AllocNone); switch (edesc) { case 0: im->cmaplen = 0; im->cmap = (Colormap) 0; break; case 1: im->cmaplen = 4; break; case 2: im->cmaplen = 16; maxcolorval = 15; break; case 3: im->cmaplen = 16; maxcolorval = 63; break; case 4: im->cmaplen = 256; maxcolorval = 63; break; case 5: im->cmaplen = 16; maxcolorval = 63; break; default: error("%s: bad edesc: %d\n", edesc); } if (im->cmaplen > 0) XAllocColorCells(dsp, im->cmap, True, &pmasks, 0, pixels, im->cmaplen); switch (edesc) { case 0: break; case 1: { char pal; if (exsize != 2) error("%s: unexpected esize: %d\n", exsize); pal = GetByte(fp); j = GetByte(fp); i = 0; im->colors[i].pixel = pixels[i]; im->colors[i].red = egapal[j][0]; im->colors[i].green = egapal[j][1]; im->colors[i].blue = egapal[j][2]; im->colors[i].flags = DoRed | DoGreen | DoBlue; for (i = 1; i < im->cmaplen; i++) { j = cgapal[i - 1][pal]; im->colors[i].pixel = pixels[i]; im->colors[i].red = egapal[j][0]; im->colors[i].green = egapal[j][1]; im->colors[i].blue = egapal[j][2]; im->colors[i].flags = DoRed | DoGreen | DoBlue; } } break; case 2: case 3: if (exsize != im->cmaplen) error("%s: bad exsize: %d\n", exsize); for (i = 0; i < im->cmaplen; i++) { int pal = GetByte(fp); im->colors[i].pixel = pixels[i]; im->colors[i].red = decodepal(pal, 0x20, 0x04) << 8; im->colors[i].green = decodepal(pal, 0x10, 0x02) << 8; im->colors[i].blue = decodepal(pal, 0x08, 0x01) << 8; im->colors[i].flags = DoRed | DoGreen | DoBlue; } break; case 4: case 5: if (exsize != 0 && exsize != im->cmaplen * 3) printf("bad exsize: %d\n", exsize); for (i = 0; i < im->cmaplen; i++) { im->colors[i].pixel = pixels[i]; im->colors[i].red = (GetByte(fp) * 255 / maxcolorval) << 8; im->colors[i].green = (GetByte(fp) * 255 / maxcolorval) << 8; im->colors[i].blue = (GetByte(fp) * 255 / maxcolorval) << 8; im->colors[i].flags = DoRed | DoGreen | DoBlue; } break; } if (edesc > 0) { if (imverbose) { printf("%d colors\n", im->cmaplen); for (i = 0; i < im->cmaplen; i++) { printf("%02x%02x%02x ", im->colors[i].red >> 8, im->colors[i].green >> 8, im->colors[i].blue >> 8); if (!((i + 1) % 8)) printf("\n"); } } XStoreColors(dsp, im->cmap, im->colors, im->cmaplen); } if (magic != 0x1234) { /* BSAVE */ fread(ptr, filelen - 6, 1, fp); } else { blocks = GetWord(fp); if (blocks == 0) { if (imverbose) printf("unpacked data\n"); fread(ptr, datasize, 1, fp); } else { if (imverbose) { printf("%d image blocks\n", blocks); hexdump(fp, 4); } blockoffset = ftell(fp); idx = 0; for (i = 0; i < blocks; i++) { u_char esc; int rlebytes; int bufsize; fseek(fp, blockoffset, 0); rlebytes = GetWord(fp); bufsize = GetWord(fp); esc = GetByte(fp); blockoffset += rlebytes; if (imverbose) { printf("block: %d (len = %d) (bufsize = %d) (esc = %d)\n", i, rlebytes, bufsize, esc); hexdump(fp, 4); } rlebytes -= 5; while (rlebytes) { u_char c = GetByte(fp); rlebytes--; if (c == esc) { u_int count = GetByte(fp); rlebytes--; if (count == 0) { count = GetWord(fp); rlebytes -= 2; } c = GetByte(fp); rlebytes--; #if 1 if (idx + count > datasize) { fprintf(stderr, "*"); goto bailimage; } #endif memset(&ptr[idx], c, count); idx += count; } else { #if 1 if (idx + 1 > datasize) { fprintf(stderr, "*"); goto bailimage; } #endif ptr[idx] = c; idx++; } } } } } bailimage: switch (bpp) { case 1: switch (planes) { case 1: break; case 2: case 3: error("%s: %d plane decoding not implemented\n", planes); break; case 4: { u_char *dst; u_char *src; u_char *old; int srcbpsl = (im->w + 7) >> 3; int plane0 = srcbpsl * 0 * im->h; int plane1 = srcbpsl * 1 * im->h; int plane2 = srcbpsl * 2 * im->h; int plane3 = srcbpsl * 3 * im->h; src = old = ptr; dst = ptr = (u_char *) malloc(datasize); if (!dst) error("%s: malloc failed on image data.\n"); for (j = 0; j < im->h; j++) { int mask = 0x80; int addr = j * srcbpsl; for (i = 0; i < im->w; i++, mask >>= 1) { if (mask == 0) { mask = 0x80; addr++; } *dst++ = ((src[plane0 + addr] & mask) != 0) + 2 * ((src[plane1 + addr] & mask) != 0) + 4 * ((src[plane2 + addr] & mask) != 0) + 8 * ((src[plane3 + addr] & mask) != 0); } } free(old); } break; } break; case 2: switch (planes) { case 1: { u_char *dst; u_char *src; u_char *old; int rem; src = old = ptr; dst = ptr = (u_char *) malloc(datasize); if (!dst) error("%s: malloc failed on image data.\n"); rem = im->w & 3; for (i = 0; i < im->h; i++) { for (j = 0; j < im->w >> 2; j++) { *dst++ = *src >> 6 & 3; *dst++ = *src >> 4 & 3; *dst++ = *src >> 2 & 3; *dst++ = *src >> 0 & 3; src++; } switch (rem) { case 3: dst[2] = *src >> 2 & 3; case 2: dst[1] = *src >> 4 & 3; case 1: dst[0] = *src >> 6 & 3; src++; dst += rem; case 0: break; } } free(old); } break; default: error("%s: %d plane decoding not implemented\n", planes); break; } break; case 4: { u_char *dst; u_char *src; u_char *old; src = old = ptr; dst = ptr = (u_char *) malloc(datasize); if (!dst) error("%s: malloc failed on image data.\n"); for (i = 0; i < im->h; i++) { for (j = 0; j < im->w / 2; j++) { *dst++ = *src >> 4 & 0xf; *dst++ = *src >> 0 & 0xf; src++; } } free(old); } break; case 8: break; } /* invert the image top to bottom */ { u_char *buffer; buffer = (u_char *) malloc(bpsl); for (i = 0; i < im->h / 2; i++) { memcpy(buffer, ptr + (im->h - i - 1) * bpsl, bpsl); memcpy(ptr + (im->h - i - 1) * bpsl, ptr + i * bpsl, bpsl); memcpy(ptr + i * bpsl, buffer, bpsl); } free(buffer); } xim = XCreateImage(dsp, vis, im->d, format, 0, ptr, im->w, im->h, 8, bpsl); im->pix = XCreatePixmap(dsp, win, im->w, im->h, 8); XPutImage(dsp, im->pix, gc, xim, 0, 0, 0, 0, im->w, im->h); XSync(dsp, False); return im; } ImageStruct * readpcximage(fp, dirent) FILE *fp; FilenameStruct *dirent; { ImageStruct *im; XImage *xim; int i; int j; u_char pcxhd[128]; int magic; int version; int encoded; int bpp; int xmin, ymin, xmax, ymax; int planes; int bpsl; int datasize; u_char *ptr; int maxcolorval; u_long pixels[256]; u_long pmasks; int filelen; int format; im = (ImageStruct *) malloc(sizeof(ImageStruct)); fseek(fp, dirent->offset, 0); filelen = GetLong(fp); /* length of whole image file... */ if (imverbose) hexdump(fp, 4); im->name = strtok(strdup(dirent->fname), "."); im->type = EXT_PCX; fread(pcxhd, 128, 1, fp); magic = pcxhd[0]; if (magic != 0x0a) printf("I don't think this is really a .pcx file!\n"); version = pcxhd[1]; encoded = pcxhd[2]; xmin = pcxhd[4] + (256 * pcxhd[5]); ymin = pcxhd[6] + (256 * pcxhd[7]); xmax = pcxhd[8] + (256 * pcxhd[9]); ymax = pcxhd[10] + (256 * pcxhd[11]); im->w = xmax - xmin + 1; im->h = ymax - ymin + 1; im->xoff = im->yoff = 0; bpsl = pcxhd[66] + (256 * pcxhd[67]); bpp = pcxhd[3]; planes = pcxhd[65]; if (bpp == 1 && planes == 1) { im->d = 1; format = XYBitmap; XSetForeground(dsp, gc, white); XSetBackground(dsp, gc, black); } else { im->d = 8; format = ZPixmap; bpsl = im->w; } datasize = bpsl * im->h; ptr = (u_char *) malloc(datasize); if (!ptr) error("%s: malloc failed on image data.\n"); if (verbose) printf("%s: (PCX) %dx%dx%d(%1x:%1x) [%d,%d] sz=%d ver=%d enc=%d\n", im->name, im->w, im->h, im->d, bpp, planes, im->xoff, im->yoff, datasize, version, encoded); if (version != 0) im->cmap = XCreateColormap(dsp, win, vis, AllocNone); switch (version) { case 0: case 3: im->cmaplen = 0; im->cmap = (Colormap) 0; break; case 2: im->cmaplen = 16; maxcolorval = 255; break; case 5: im->cmaplen = 256; maxcolorval = 255; break; case 1: case 4: default: error("%s: bad pcx version: %d\n", version); } if (im->cmaplen > 0) XAllocColorCells(dsp, im->cmap, True, &pmasks, 0, pixels, im->cmaplen); switch (version) { case 0: case 3: break; case 2: /* I'm guessing here! */ for (i = 0; i < im->cmaplen; i++) { im->colors[i].pixel = pixels[i]; im->colors[i].red = pcxhd[16 + i + 0] << 8; im->colors[i].green = pcxhd[16 + i + 1] << 8; im->colors[i].blue = pcxhd[16 + i + 2] << 8; im->colors[i].flags = DoRed | DoGreen | DoBlue; } break; case 5: fseek(fp, dirent->offset + filelen + 4 - 769, 0); if (GetByte(fp) != 12) printf("I don't think this is a VGA palette.\n"); for (i = 0; i < im->cmaplen; i++) { im->colors[i].pixel = pixels[i]; im->colors[i].red = GetByte(fp) << 8; im->colors[i].green = GetByte(fp) << 8; im->colors[i].blue = GetByte(fp) << 8; im->colors[i].flags = DoRed | DoGreen | DoBlue; } fseek(fp, dirent->offset + 4 + 128, 0); break; } if (version > 0) { if (imverbose) { printf("%d colors\n", im->cmaplen); for (i = 0; i < im->cmaplen; i++) { printf("%02x%02x%02x ", im->colors[i].red >> 8, im->colors[i].green >> 8, im->colors[i].blue >> 8); if (!((i + 1) % 8)) printf("\n"); } } XStoreColors(dsp, im->cmap, im->colors, im->cmaplen); } if (encoded) { /* * Goes like this: Read a byte. If the two high bits are set, then the * low 6 bits contain a repeat count, and the byte to repeat is the * next byte in the file. If the two high bits are not set, then this * is the byte to write. */ int i = 0; while (i < datasize) { int byte = GetByte(fp); if ((byte & 0xc0) == 0xc0) { int count = byte & 0x3f; int value = GetByte(fp); if (i + count > datasize) count = datasize - i - 1; /* catch overflow */ memset(ptr + i, value, count); i += count; } else { ptr[i++] = byte; } } } else fread(ptr, datasize, 1, fp); /* * need to do planar -> chunky conversion here if we support > 1 plane pcx * files. */ xim = XCreateImage(dsp, vis, im->d, format, 0, ptr, im->w, im->h, 8, bpsl); im->pix = XCreatePixmap(dsp, win, im->w, im->h, 8); XPutImage(dsp, im->pix, gc, xim, 0, 0, 0, 0, im->w, im->h); XSync(dsp, False); return im; } void printcodes(ex) ExecStruct *ex; { int i; for (i = 0; i < ex->numcodes; i++) { printf("%4d: ", i); if (ex->Code[i].token < NTOKENS) printf("[TOK] %s (%d) (%d args)\n", tokens[ex->Code[i].token], ex->Code[i].token, ex->Code[i].val.i); else { switch (ex->Code[i].token) { case INTEGER: printf("[INT] %d\n", ex->Code[i].val.i); break; case STRING: printf("[STR] \"%s\"\n", ex->Code[i].val.s); break; case IMAGE: printf("[IMG] \"%s\"\n", ex->Code[i].val.image->name); break; case FONTTYPE: printf("[FNT] \"%s\"\n", ex->Code[i].val.font->name); break; case EXECTYPE: printf("[EXC] \"%s\"\n", ex->Code[i].val.exec->name); break; case WILDTYPE: printf("[WLD] \"@\"\n"); break; default: error("%s: printcodes bogosity (%d)\n", ex->Code[i].token); } } } printf("labels:\n"); for (i = 0; i < ex->numlabels; i++) printf("[LABEL] \"%s\" %d\n", ex->label[i].string, ex->label[i].ipaddr); } /* turn all cload and pload args into pointers to the * actual image structure instead of the filename * turn all fload args into pointers to the font structure * instead of the filename, and change the '@' string to a WILDTYPE. */ void converttypes(ex) ExecStruct *ex; { int i, j; for (i = 0; i < ex->numcodes; i++) { int t = ex->Code[i].token; char *s = ex->Code[i].val.s; char nargs = ex->Code[i].val.i; switch (t) { case STRING: if (s[0] == '@' && s[1] == 0) { ex->Code[i].token = WILDTYPE; ex->Code[i].val.i = 0; } break; case FLOAD: stringtofont(ex, i + 1); break; case CLOAD: stringtoimage(ex, i + 1, EXT_CLP); break; case PLOAD: stringtoimage(ex, i + 1, EXT_PIC); break; case LINK: case CALL: stringtoexec(ex, i + 1); if (nargs > 1) stringtolabel(ex, i + 2); break; case DATABEGIN: case GOTO: case GOSUB: stringtolabel(ex, i + 1); break; case IFKEY: for (j = 2; j <= nargs; j += 2) stringtolabel(ex, i + j); break; case IFMEM: case IFVIDEO: case WAITKEY: if (nargs > 1) stringtolabel(ex, i + 2); break; } } } ExecStruct * readtxt(fp, dir) FILE *fp; FilenameStruct *dir; { ExecStruct *ex; int len; char *txt; int i; ex = (ExecStruct *) malloc(sizeof(ExecStruct)); ex->name = strtok(strdup(dir->fname), "."); fseek(fp, dir->offset, 0); len = GetLong(fp); len &= 0x00ffffff; /* hack */ ex->txt = (char *) malloc(len + 1); fread(ex->txt, len, 1, fp); ex->txt[len] = 26; if (showtext) puts(ex->txt); return ex; } void readfiles(fp, dir, count) FILE *fp; FilenameStruct *dir; int count; { int i; for (i = 0; i < count; i++) { char *p = strrchr(dir[i].fname, '.'); int extcode; if (!p) error("%s: %s has no extension.\n", dir[i].fname); extcode = findext(p); switch (extcode) { case EXT_PCX: image[numimages++] = readpcximage(fp, &dir[i]); break; case EXT_PIC: case EXT_CLP: case EXT_PAL: image[numimages++] = readimage(fp, &dir[i], extcode); break; case EXT_GIF: image[numimages++] = readgifimage(fp, &dir[i]); break; case EXT_SET: font[numfonts++] = readset(fp, &dir[i]); if (font[numfonts - 1] == (FontStruct *) 0) --numfonts; break; case EXT_FNT: font[numfonts++] = readfont(fp, &dir[i]); if (font[numfonts - 1] == (FontStruct *) 0) --numfonts; break; case EXT_TXT: exec[numexecs++] = readtxt(fp, &dir[i]); break; default: printf("skipping %s: unknown extension.\n", dir[i].fname); } } for (i = 0; i < numexecs; i++) { ExecStruct *ex = exec[i]; parsefile(ex, ex->txt); converttypes(ex); if (printthecodes) printcodes(ex); } if (imageloop) { int im = 0; XMapWindow(dsp, win); XSync(dsp, False); while (1) { XEvent ev; XNextEvent(dsp, &ev); if (ev.type == ButtonPress) { if (++im >= numimages) im = 0; if (((XButtonEvent *) & ev)->button == Button3) break; XStoreName(dsp, win, image[im]->name); XSetWindowColormap(dsp, win, image[im]->cmap); XCopyArea(dsp, image[im]->pix, win, gc, 0, 0, image[im]->w, image[im]->h, 0, 0); } } } }