home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
x
/
xgrasp.zip
/
READFILE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-04
|
33KB
|
1,315 lines
#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)
*/
unsigned 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);
}
}
}
}