#ident "@(#)exec.c 1.17 91/04/05 XGRASP" /*- * exec.c - grasp language execution routines. * * 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 #include #include "grasp.h" #include #define ESCAPE -3 #define DONE -2 #define CONT -1 #define intarg(ex,index) (ex)->Code[(index)].val.i #define strarg(ex,index) (ex)->Code[(index)].val.s #define imgarg(ex,index) (ex)->Code[(index)].val.image #define fntarg(ex,index) (ex)->Code[(index)].val.font #define excarg(ex,index) (ex)->Code[(index)].val.exec Colormap EGAcmap = (Colormap) 0; XRectangle window = { 0, 0, 0, 0 }; typedef struct { int count; int ipaddr; } stackent; #define STACKSIZE 16 stackent loopstack[STACKSIZE]; int loopstackptr = 0; int ipstack[STACKSIZE]; int ipstackptr = 0; ImageStruct *picreg[16]; ImageStruct *clipreg[128]; FontStruct *fontreg[16]; FontStruct *currentfont = 0; int fstyle = 0; int chargap = 1; int spacegap = -1; int currentcolor = 1; int currentbgcolor = 0; Colormap installedcmap; int palettenum = 0; int tranval = -1; int keypressed = -1; int videomode; long hundredthsofseconds() { struct timeval now; gettimeofday(&now, (struct timezone *) 0); return now.tv_sec * 100 + now.tv_usec / 10000; } void ExitEvent(ev) XClientMessageEvent *ev; { if (ev->message_type == protocol_atom && ev->data.l[0] == kill_atom) exit(0); } void exitcheck() { while (XPending(dsp)) { XEvent ev; XNextEvent(dsp, &ev); switch (ev.type) { case ClientMessage: ExitEvent(&ev); break; } } } /* * delay sleeps for 'd'/100'ths of a second * usleep() will have to be provided on non-sun platforms. */ void delay(d) int d; { int endtime = hundredthsofseconds() + d; while (1) { exitcheck(); usleep(10000); /* sleep for 1/100th of a second */ if (hundredthsofseconds() > endtime) return; } } /* * if ip is pointing at a wildcard '*' then resolvewild returns a pointer * to the object which is referenced by the current data pointer. * otherwise it checks the type of the ip to make sure it matches what * the caller expected, plus a little hack for zero's mistyped as oh's. */ void * resolvewild(ex, ip, type) ExecStruct *ex; int ip; int type; { int i; if (ex->Code[ip].token == WILDTYPE) { if (ex->currentdataptr == -1) error("%s: resolvewild no data\n"); i = ex->currentdataptr++; } else { i = ip; if (ex->Code[i].token != type) { /* hack for mistyped zero's as Oh's */ if (ex->Code[i].token == STRING && ex->Code[i].val.s[0] == 'o') { ex->Code[i].token = INTEGER; ex->Code[i].val.i = 0; } else error("%s: resolvewild type mismatch.\n"); } } switch (type) { case STRING: return (void *) ex->Code[i].val.s; break; case INTEGER: return (void *) ex->Code[i].val.i; break; case IMAGE: if (ex->Code[i].token == STRING) stringtoimage(i, EXT_CLP); return (void *) ex->Code[i].val.image; break; case FONTTYPE: if (ex->Code[i].token == STRING) stringtofont(i); return (void *) ex->Code[i].val.font; break; default: error("%s: resolvewild type failure\n"); } } /* * installs the colormap associated with the image argument. */ void installcmap(i) { ImageStruct *im; palettenum = i; im = picreg[i]; if (im) { installedcmap = im->cmap; XSetWindowColormap(dsp, win, im->cmap); } else { printf("no image at %d for colormap setting\n", i); installedcmap = (Colormap) 0; } } void setvideomode(c) char c; { int w, h; if (c >= 'A' && c <= 'Z') c += 'a' - 'A'; if (EGAcmap == (Colormap) 0) EGAcmap = CreateEGAcmap(); videomode = c; switch (c) { case '1': /* 80x25 text 16 color */ w = 80 * 8; h = 25 * 13 + 4; installedcmap = (Colormap) 0; palettenum = 0; XSetWindowColormap(dsp, win, EGAcmap); break; case 'a': /* 320x200 4 color */ w = 320; h = 200; break; case 'c': /* 640x200 2 color */ w = 640; h = 200; break; case 'e': /* 640x350 2 color */ w = 640; h = 350; break; case 'g': /* 640x350 16 colors */ w = 640; h = 350; break; case 'h': /* 720x384 2 colors */ w = 720; h = 384; break; case 'i': /* 640x350 16 colors */ w = 640; h = 350; break; case 'j': /* 640x480 16 colors */ w = 640; h = 480; break; case 'k': /* 640x350 16 colors */ w = 640; h = 350; break; default: case 'l': /* 320x200 256 color */ w = 320; h = 200; break; case 'm': /* 640x480 256 color */ w = 640; h = 480; break; case 'n': /* 720x348 16 color */ w = 720; h = 348; break; case 'o': /* 640x480 2 color */ w = 640; h = 480; break; case 'p': /* 800x600 2 color */ w = 800; h = 600; break; case 'q': /* 800x600 16 color */ w = 800; h = 600; break; case 'r': /* 800x600 256 color */ w = 640; h = 350; break; case 's': /* 800x600 256 color */ w = 640; h = 480; break; case 't': /* 800x600 256 color */ w = 800; h = 600; break; case 'w': /* 360x480 256 color */ w = 360; h = 480; break; } if (picreg[0] == 0 || picreg[0]->w != w || picreg[0]->h != h) { if (picreg[0] != 0) { XFreePixmap(dsp, picreg[0]->pix); if (picreg[0]->cmap) XFreeColormap(dsp, picreg[0]->cmap); free(picreg[0]); } picreg[0] = (ImageStruct *) malloc(sizeof(ImageStruct)); picreg[0]->name = "background"; picreg[0]->type = EXT_PIC; picreg[0]->w = w; picreg[0]->h = h; picreg[0]->d = 8; picreg[0]->xoff = 0; picreg[0]->yoff = 0; picreg[0]->pix = XCreatePixmap(dsp, win, w, h, 8); XSetForeground(dsp, gc, 0); XFillRectangle(dsp, picreg[0]->pix, gc, 0, 0, w, h); picreg[0]->cmap = (Colormap) 0; picreg[0]->cmaplen = 0; XResizeWindow(dsp, win, w, h); while (1) { XEvent ev; XNextEvent(dsp, &ev); if (ev.type == ConfigureNotify) break; } } window.x = window.y = 0; window.width = w; window.height = h; XSetClipMask(dsp, gc, None); XCopyArea(dsp, picreg[0]->pix, win, gc, 0, 0, picreg[0]->w, picreg[0]->h, 0, 0); XMapWindow(dsp, win); XSync(dsp, False); } int unimplemented(ex, ip) ExecStruct *ex; int ip; { printf("%s: ", tokens[ex->Code[ip - 1].token]); printf("unimplemented operator.\n"); return CONT; } #define defrect(r, X, Y, W, H) \ (r).x = X, (r).y = Y, (r).width = W, (r).height = H void drawWideRect(dpy, win, gc, x, y, w, h, thick) Display *dpy; Window win; GC gc; int x, y, w, h; int thick; { XRectangle rects[4]; int nrects, doublethick; if (w == 0 && h == 0) return; doublethick = 2 * thick; /* * if too small for box just draw one solid rect */ if (w <= doublethick || h <= doublethick) { defrect(rects[0], x, y, w, h); nrects = 1; /* else draw all 4 rects for the box */ } else { defrect(rects[0], x, y, w, thick); defrect(rects[1], x, y + h - thick, w, thick); defrect(rects[2], x, y + thick, thick, h - doublethick); defrect(rects[3], x + w - thick, y + thick, thick, h - doublethick); nrects = 4; } XFillRectangles(dpy, win, gc, rects, nrects); } /*- * BOX x1 y1 x2 y2 [thickness] * draws a hollow rectangle in the current color as thick as specified. */ int f_box(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int x1; int y1; int x2; int y2; int th; switch (nargs) { case 5: th = intarg(ex, ip + 4); break; case 4: th = 1; break; default: error("%s: argcount mismatch\n"); break; } x1 = intarg(ex, ip); y1 = intarg(ex, ip + 1); x2 = intarg(ex, ip + 2); y2 = intarg(ex, ip + 3); XSetForeground(dsp, gc, currentcolor); drawWideRect(dsp, win, gc, x1, YFLIP(y2), x2 - x1, y2 - y1, th); return CONT; } /*- * BREAK label * break out of a loop. */ int f_break(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * CALL file [label] */ int f_call(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { void execfile(); int label; switch (nargs) { case 2: label = intarg(ex, ip + 1); break; case 1: label = 0; break; default: error("%s: argcount mismatch\n"); break; } execfile(excarg(ex, ip), label); return CONT; } /*- * CFADE fadenumber x y [buffernumber] [speed] [delay] * fade the given buffer using the given fade number at x,y. */ int f_cfade(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int fadestyle; int x; int y; int buf = 1; int speed = 0; int d = 10; ImageStruct *im; switch (nargs) { case 6: d = intarg(ex, ip + 5); case 5: speed = intarg(ex, ip + 4); case 4: buf = intarg(ex, ip + 3); case 3: y = intarg(ex, ip + 2); x = intarg(ex, ip + 1); fadestyle = intarg(ex, ip); break; default: error("%s: argcount mismatch\n"); break; } im = clipreg[buf]; imagefade(fadestyle, clipreg[buf], x + im->xoff, YFLIPIM(y, im) + im->yoff, speed, 0); delay(d); return CONT; } /*- * CFREE buffer [buffer] ... * unload a clipping */ int f_cfree(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 0: error("%s: argcount mismatch\n"); break; default: break; } #endif /* NOP */ return CONT; } /*- * CGETBUF n [x1 y1 x2 y2] [noshift] [tran] * copy an area of the screen into a clip buffer */ int f_cgetbuf(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int clip; int x1; int y1; int x2; int y2; ImageStruct *im; XImage *xim; switch (nargs){ case 7: case 6: case 5: y2 = intarg(ex, ip + 4); x2 = intarg(ex, ip + 3); y1 = intarg(ex, ip + 2); x1 = intarg(ex, ip + 1); case 1: clip = intarg(ex, ip); break; default: error("%s: argcount mismatch\n"); break; } im = (ImageStruct *) malloc(sizeof(ImageStruct)); im->name = "getbuf"; im->w = x2 - x1; im->h = y2 - y1; im->d = 8; im->cmap = (Colormap) 0; im->cmaplen = 0; im->pix = XCreatePixmap(dsp, win, im->w, im->h, 8); xim = XGetImage(dsp, win, x1, y1, im->w, im->h, 0xff, ZPixmap); XPutImage(dsp, im->pix, gc, xim, 0, 0, 0, 0, im->w, im->h); clipreg[clip] = im; free(xim->data); free(xim); return CONT; } /*- * CHGCOLOR slot val [slot val] ... * change palette colors in EGA mode. */ int f_chgcolor(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int i; u_long pmasks; u_long pixels[16]; ImageStruct *im = picreg[0]; switch (nargs) { case 0: error("%s: argcount mismatch\n"); break; default: switch (nargs % 2) { case 1: error("%s: argcount mismatch\n"); break; default: break; } break; } im->cmaplen = 16; /* EGA hard-coded value */ if (!im->cmap) { im->cmap = XCreateColormap(dsp, win, vis, AllocNone); XAllocColorCells(dsp, im->cmap, True, &pmasks, 0, pixels, im->cmaplen); } for (i = 0; i < nargs; i += 2) { int slot = intarg(ex, ip + i); int pal = intarg(ex, ip + i + 1); im->colors[slot].pixel = slot; im->colors[slot].red = decodepal(pal, 0x20, 0x04) << 8; im->colors[slot].green = decodepal(pal, 0x10, 0x02) << 8; im->colors[slot].blue = decodepal(pal, 0x08, 0x01) << 8; im->colors[slot].flags = DoRed | DoGreen | DoBlue; XStoreColor(dsp, im->cmap, &(im->colors[slot])); } installcmap(0); return CONT; } /*- * CIRCLE x y xr [yr] [iris] * draw an ellipse */ int f_circle(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 5: case 4: case 3: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * CLEARSCR * paint entire screen */ int f_clearscr(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { switch (nargs) { case 0: break; default: error("%s: argcount mismatch\n"); break; } if (picreg[0] == 0) setvideomode('l'); XSetForeground(dsp, gc, currentcolor); XFillRectangle(dsp, picreg[0]->pix, gc, 0, 0, picreg[0]->w, picreg[0]->h); XCopyArea(dsp, picreg[0]->pix, win, gc, 0, 0, picreg[0]->w, picreg[0]->h, 0, 0); return CONT; } /*- * CLOAD name [buffer] [noshift] [tran] * load a clipping */ int f_cload(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int clip; switch (nargs) { case 4: case 3: case 2: clip = (int) resolvewild(ex, ip + 1, INTEGER); break; case 1: clip = 0; break; default: error("%s: argcount mismatch\n"); break; } clipreg[clip] = (ImageStruct *) resolvewild(ex, ip, IMAGE); return CONT; } /*- * CLOSEGL * close a library file */ int f_closegl(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 0: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * COLOR color1 [R] [color2] * set the drawing color, (not sure what the R is...) */ int f_color(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { switch (nargs) { case 2: currentbgcolor = intarg(ex, ip + 1); case 1: currentcolor = intarg(ex, ip); break; default: error("%s: argcount mismatch\n"); break; } return CONT; } /*- * CYCLE cycles start number [time] * rotate palette colors. */ int f_cycle(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int cycles; int start; int number; int d = 0; int i; int j; int end = start + number - 1; XColor *c = picreg[palettenum]->colors; unsigned long buffer; switch (nargs) { case 4: d = intarg(ex, ip + 3); case 3: number = intarg(ex, ip + 2); start = intarg(ex, ip + 1); cycles = intarg(ex, ip); break; default: error("%s: argcount mismatch\n"); break; } for (i = 0; i < cycles; i++) { buffer = c[start].pixel; for (j = start; j < end; j++) c[j].pixel = c[j + 1].pixel; c[end].pixel = buffer; XStoreColors(dsp, installedcmap, &c[start], number); XSync(dsp, False); if (d) delay(d); } return CONT; } /*- * DATA item [item] ... * define data elements */ int f_data(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { switch (nargs) { case 0: error("%s: argcount mismatch\n"); break; default: break; } ex->currentdataptr = ip; return CONT; } /*- * DATABEGIN * define data elements (multiple lines) */ int f_databegin(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { switch (nargs) { case 1: ex->currentdataptr = intarg(ex, ip); break; default: ex->currentdataptr = ip; break; } return CONT; } /*- * DATAEND * mark the end of a data block */ int f_dataend(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { switch (nargs) { case 0: break; default: error("%s: argcount mismatch\n"); break; } ex->currentdataend = ip - 2; return CONT; } /*- * DATASKIP n * skip n data elements in a block. */ f_dataskip(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { switch (nargs) { case 1: ex->currentdataptr += intarg(ex, ip); break; default: error("%s: argcount mismatch\n"); break; } return unimplemented(ex, ip); } /*- * DFREE buffer [buffer] ... * */ int f_dfree(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 0: error("%s: argcount mismatch\n"); break; default: break; } #endif return unimplemented(ex, ip); } /*- * DLOAD name [buffer] [disk] * load a differential animation file. */ int f_dload(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 3: case 2: case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * EDGE setting [color] * turn leading edge for fades on or off. */ int f_edge(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 2: case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * ELSE * target for IF condition not met. */ int f_else(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 0: error("%s: argcount mismatch\n"); break; default: break; } #endif return unimplemented(ex, ip); } /*- * ENDLFLOAT * clear the float background buffer. */ int f_endlfloat(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 0: error("%s: argcount mismatch\n"); break; default: break; } #endif return unimplemented(ex, ip); } /*- * ENDIF * mark the end of an if-else block */ int f_endif(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 0: error("%s: argcount mismatch\n"); break; default: break; } #endif return unimplemented(ex, ip); } /*- * EXEC name [options] * run a non-grasp program. */ int f_exec(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 2: case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * EXIT [value] * exit grasp or subprogram. */ int f_exit(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { switch (nargs) { case 1: case 0: break; default: error("%s: argcount mismatch\n"); break; } delay(100); return DONE; } /*- * FFREE buffer [buffer] ... * unload a font */ int f_ffree(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 0: break; default: error("%s: argcount mismatch\n"); break; } #endif /* NOP */ return CONT; } /*- * FGAPS char [space] * set letter and word spacing */ int f_fgaps(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { switch (nargs) { case 2: spacegap = intarg(ex, ip + 1); case 1: chargap = intarg(ex, ip); break; default: error("%s: argcount mismatch\n"); break; } return CONT; } /*- * FLOAD name [buffer] * load a font */ int f_fload(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { FontStruct *f; int reg = 1; switch (nargs) { case 2: reg = intarg(ex, ip + 1); case 1: f = fntarg(ex, ip); break; default: error("%s: argcount mismatch\n"); break; } fontreg[reg] = f; currentfont = f; chargap = 1; spacegap = f->glyphs[' '].width; return CONT; } /*- * FLOAT x1 y1 x2 y2 step delay buf [buf] ... * animate a clipping and preserve the background. */ int f_float(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int x1; int y1; int x2; int y2; int step; int d; int i; int image; int count; float x; float y; float dx; float dy; Window floatwin; ImageStruct *im; XSetWindowAttributes xswa; switch (nargs) { case 6: case 5: case 4: case 3: case 2: case 1: case 0: error("%s: argcount mismatch\n"); break; default: im = clipreg[intarg(ex, ip + 6)]; d = intarg(ex, ip + 5); step = intarg(ex, ip + 4); y2 = intarg(ex, ip + 3); x2 = intarg(ex, ip + 2); y1 = intarg(ex, ip + 1); x1 = intarg(ex, ip); break; } xswa.backing_store = Always; floatwin = XCreateWindow(dsp, win, x1, YFLIPIM(y1, im), im->w, im->h, 0, 8, InputOutput, vis, CWBackingStore, &xswa); XCopyArea(dsp, im->pix, floatwin, gc, 0, 0, im->w, im->h, 0, 0); XMapWindow(dsp, floatwin); if (x1 == x2 && y1 == y2 ) { for (image = 7; image < nargs; image++) { im = clipreg[intarg(ex, ip + image)]; XMoveResizeWindow(dsp, floatwin, x1, YFLIPIM(y1, im), im->w, im->h); XCopyArea(dsp, im->pix, floatwin, gc, 0, 0, im->w, im->h, 0, 0); XSync(dsp, False); delay(d); } } else { x = x1; y = y1; dx = (x2 - x1); dy = (y2 - y1); count = sqrt(dx * dx + dy * dy) / step; dx /= count; dy /= count; image = 7; for (i = 0; i <= count; i++) { if (nargs > 7) { im = clipreg[intarg(ex, ip + image)]; if (++image == nargs) image = 6; } XMoveResizeWindow(dsp, floatwin, (int) x, YFLIPIM((int) y, im), im->w, im->h); XCopyArea(dsp, im->pix, floatwin, gc, 0, 0, im->w, im->h, 0, 0); XSync(dsp, False); x += dx; y += dy; delay(d); } } XUnmapWindow(dsp, floatwin); XDestroyWindow(dsp, floatwin); return CONT; } /*- * FLY x1 y1 x2 y2 step delay buf [buf] ... * animate a clipping */ int f_fly(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int x1; int y1; int x2; int y2; int step; int d; int i; int image; int count; float x; float y; float dx; float dy; ImageStruct *im; switch (nargs) { case 6: case 5: case 4: case 3: case 2: case 1: case 0: error("%s: argcount mismatch\n"); break; default: im = clipreg[intarg(ex, ip + 6)]; d = intarg(ex, ip + 5); step = intarg(ex, ip + 4); y2 = intarg(ex, ip + 3); x2 = intarg(ex, ip + 2); y1 = intarg(ex, ip + 1); x1 = intarg(ex, ip); break; } XCopyArea(dsp, im->pix, win, gc, 0, 0, im->w, im->h, x1, YFLIPIM(y1, im)); if (x1 == x2 && y1 == y2 ) { for (image = 7; image < nargs; image++) { im = clipreg[intarg(ex, ip + image)]; XCopyArea(dsp, im->pix, win, gc, 0, 0, im->w, im->h, x1, YFLIPIM(y1, im)); XSync(dsp, False); delay(d); } } else { x = x1; y = y1; dx = (x2 - x1); dy = (y2 - y1); count = sqrt(dx * dx + dy * dy) / step; dx /= count; dy /= count; image = 7; for (i = 0; i <= count; i++) { if (nargs > 7) { im = clipreg[intarg(ex, ip + image)]; if (++image == nargs) image = 6; } XCopyArea(dsp, im->pix, win, gc, 0, 0, im->w, im->h, (int) x, YFLIPIM((int) y, im)); XSync(dsp, False); x += dx; y += dy; delay(d); } } return CONT; } /*- * FONT [buffer] * select a font */ int f_font(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { switch (nargs) { case 1: currentfont = fontreg[intarg(ex, ip)]; break; case 0: currentfont = fontreg[0]; break; default: error("%s: argcount mismatch\n"); break; } return CONT; } /*- * FSTYLE dir off1 [off2] * set character shading... (I think this changed between 1.1 and 3.0) */ int f_fstyle(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { switch (nargs) { case 1: fstyle = intarg(ex, ip); break; default: error("%s: argcount mismatch\n"); break; } return CONT; } /*- * GETCOLOR x y * set the drawing color equal to the screen pixel. */ int f_getcolor(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int x = intarg(ex, ip); int y = intarg(ex, ip + 1); XImage *xim; switch (nargs) { case 2: y = YFLIP(intarg(ex, ip + 1)); x = intarg(ex, ip); break; default: error("%s: argcount mismatch\n"); break; } xim = XGetImage(dsp, win, x, YFLIP(y), 1, 1, 0xff, ZPixmap); currentcolor = XGetPixel(xim, 0, 0); printf("getcolor %d,%d = %d\n", x, y, currentcolor); XDestroyImage(xim); return CONT; } /*- * GETKEY name * set a variable equal to a keystroke */ int f_getkey(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * GOSUB label [val] ... * execute a subroutine */ int f_gosub(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { switch (nargs) { case 2: case 1: break; default: error("%s: argcount mismatch\n"); break; } ipstack[loopstackptr] = ip + 1; if (++loopstackptr >= STACKSIZE) error("%s: ipstack overflow\n"); return intarg(ex, ip); } /*- * GOTO label * jump to a label */ int f_goto(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { switch (nargs) { case 1: break; default: error("%s: argcount mismatch\n"); break; } return intarg(ex, ip); } /*- * IF exp [label] * jump if condition is met, or start if-else block if no label. */ int f_if(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { switch (nargs) { case 2: case 1: break; default: error("%s: argcount mismatch\n"); break; } return unimplemented(ex, ip); } /*- * IFKEY key [label [key label] ... ] * check for specific keypress */ int f_ifkey(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int i; switch (nargs) { case 0: error("%s: argcount mismatch\n"); break; default: break; } for (i = 0; i < nargs; i += 2) { char *key = strarg(ex, ip + i); if (*key == keypressed) return intarg(ex, ip + i + 1); } return CONT; } /*- * IFMEM mem [label] * check available memory. */ int f_ifmem(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { /* ignore the memory value */ int label; switch (nargs) { case 2: label = intarg(ex, ip + 1); break; case 1: label = CONT; break; default: error("%s: argcount mismatch\n"); break; } return label; } /*- * IFMOUSE button [label1] [x y x1 y1] [color] [wait] [label2] * check for a mouse click (no idea how this one is supposed to work). */ int f_ifmouse(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 9: case 8: case 7: case 6: case 2: case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * IFVIDEO mode [label] * check whether video mode is available */ int f_ifvideo(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int label; switch (nargs) { case 2: label = intarg(ex, ip + 1); break; case 1: label = CONT; break; default: error("%s: argcount mismatch\n"); break; } return label; } /*- * INT num [ax] [bx] [cx] [dx] [si] [di] [ds] [es] * call an MSDOS interrupt... (yeah, right!) */ int f_int(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 9: case 8: case 7: case 6: case 5: case 4: case 3: case 2: case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } static int linex1 = 0; static int liney1 = 0; static int linex2 = 0; static int liney2 = 0; /*- * LINE x1 y1 x2 y2 [R] * draw a line, (possibly relative to the current point). */ int f_line(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { switch (nargs) { case 5: linex1 += intarg(ex, ip); liney1 += intarg(ex, ip + 1); linex2 += intarg(ex, ip + 2); liney2 += intarg(ex, ip + 3); break; case 4: linex1 = intarg(ex, ip); liney1 = intarg(ex, ip + 1); linex2 = intarg(ex, ip + 2); liney2 = intarg(ex, ip + 3); break; default: error("%s: argcount mismatch\n"); break; } XSetForeground(dsp, gc, currentcolor); XDrawLine(dsp, win, gc, linex1, YFLIP(liney1), linex2, YFLIP(liney2)); XSync(dsp, False); return CONT; } /*- * LINK name [label] * jump to another program */ int f_link(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { void execfile(); int label; switch (nargs) { case 2: label = intarg(ex, ip + 1); break; case 1: label = 0; break; default: error("%s: argcount mismatch\n"); break; } execfile(excarg(ex, ip), label); return DONE; } /*- * LOCAL var value * define a local variable */ int f_local(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 2: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * LOOP * define the end of a MARK'ed loop. */ int f_loop(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { switch (nargs) { case 0: break; default: error("%s: argcount mismatch\n"); break; } if (--loopstack[loopstackptr - 1].count == 0) { --loopstackptr; return CONT; } return loopstack[loopstackptr - 1].ipaddr; } /*- * MARK count [rand] * define the beggining of a loop. (not sure what rand is supposed to do.) */ int f_mark(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { switch (nargs) { case 2: case 1: break; default: error("%s: argcount mismatch\n"); break; } loopstack[loopstackptr].count = intarg(ex, ip); loopstack[loopstackptr].ipaddr = ip + 1; if (++loopstackptr >= STACKSIZE) error("%s: stack overflow\n"); return CONT; } /*- * MERGE name * add lines to the current program from another * (why is this different from CALL?) */ int f_merge(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * MODE color * change colors in 2 color CGA mode. */ int f_mode(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int color; int pal = 0; int i; u_long pmasks; u_long pixels[4]; ImageStruct *im = picreg[0]; switch (nargs) { case 1: color = intarg(ex, ip); break; default: error("%s: argcount mismatch\n"); break; } im->cmaplen = 4; if (nargs > 1) pal = intarg(ex, ip + 1); if (!im->cmap) { im->cmap = XCreateColormap(dsp, win, vis, AllocNone); XAllocColorCells(dsp, im->cmap, True, &pmasks, 0, pixels, im->cmaplen); } i = 0; im->colors[i].pixel = i; im->colors[i].red = egapal[color][0]; im->colors[i].green = egapal[color][1]; im->colors[i].blue = egapal[color][2]; im->colors[i].flags = DoRed | DoGreen | DoBlue; for (i = 1; i < 4; i++) { color = cgapal[i - 1][pal]; im->colors[i].pixel = i; im->colors[i].red = egapal[color][0]; im->colors[i].green = egapal[color][1]; im->colors[i].blue = egapal[color][2]; im->colors[i].flags = DoRed | DoGreen | DoBlue; } XStoreColors(dsp, im->cmap, im->colors, im->cmaplen); installcmap(0); return CONT; } /*- * MOUSE setting * turn mouse on/off */ int f_mouse(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * MOVE x1 y1 x2 y2 x3 y3 * move an area of the screen */ int f_move(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int x1; int y1; int x2; int y2; int w; int h; int x3; int y3; switch (nargs) { case 6: x1 = intarg(ex, ip); y1 = YFLIP(intarg(ex, ip + 1)); x2 = intarg(ex, ip + 2); y2 = YFLIP(intarg(ex, ip + 3)); w = x2 - x1; h = y2 - y1; x3 = intarg(ex, ip + 4); y3 = YFLIP(intarg(ex, ip + 5)) - h; break; default: error("%s: argcount mismatch\n"); break; } XCopyArea(dsp, win, win, gc, x1, y1, w, h, x3, y3); return CONT; } /*- * NOISE n m time * create a sound */ int f_noise(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { /* NOP */ switch (nargs) { case 3: break; default: error("%s: argcount mismatch\n"); break; } return CONT; } /*- * NOTE val tone time [R] * play a note */ int f_note(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { /* NOP */ switch (nargs) { case 4: case 3: break; default: error("%s: argcount mismatch\n"); break; } return CONT; } /*- * OFFSET x y [R] * change the screen coords for some other commands. */ int f_offset(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 3: case 2: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * OPENGL name * use files in a library file. */ int f_opengl(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * OUT dx al [ah] * output a value to an IBM PC hardware IO port (yeah, right!) */ int f_out(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 3: case 2: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * PALETTE buffer * set palette colors to match a given picture. */ int f_palette(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int cmap; switch (nargs) { case 1: cmap = intarg(ex, ip); break; default: error("%s: argcount mismatch\n"); break; } installcmap(cmap); return CONT; } /*- * PAN [x1 y1] x2 y2 [R] [speed] * pan across large picture in EGA mode. */ int f_pan(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * PFADE fade [buffer] [speed] [delay] * display a picture. */ int f_pfade(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int fadestyle; int buf = 0; int speed = 0; int d = 10; ImageStruct *im; switch (nargs) { case 4: d = (int) resolvewild(ex, ip + 3, INTEGER); case 3: speed = (int) resolvewild(ex, ip + 2, INTEGER); case 2: buf = (int) resolvewild(ex, ip + 1, INTEGER); case 1: fadestyle = (int) resolvewild(ex, ip, INTEGER); break; default: error("%s: argcount mismatch\n"); } im = picreg[buf]; if (buf == 0) { XSetForeground(dsp, gc, currentcolor); XFillRectangle(dsp, im->pix, gc, 0, 0, im->w, im->h); } if (im) imagefade(fadestyle, im, 0, 0, speed, 1); delay(d); return CONT; } /*- * PFREE buffer [buffer] ... * unload a picture. */ int f_pfree(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { /* NOP */ switch (nargs) { case 0: error("%s: argcount mismatch\n"); break; default: break; } return CONT; } /*- * PGETBUF n [x1 y1 x2 y2] * copy the screen into a picture buffer, (same as CGETBUF?) */ int f_pgetbuf(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 5: case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * PLOAD name [buffer] * load a picture. */ int f_pload(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { ImageStruct *im; int regnum; switch (nargs) { case 2: im = imgarg(ex, ip); regnum = intarg(ex, ip + 1); break; case 1: im = imgarg(ex, ip); regnum = 1; break; default: error("%s: argcount mismatch\n"); break; } picreg[regnum] = im; return CONT; } /*- * PNEWBUF buffer [x y] * create an empty picture buffer. (what is x, y? offset?) */ int f_pnewbuf(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 3: case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * POINT x y [rx ry] * draw a point (what are rx,ry?) */ int f_point(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int x = intarg(ex, ip); int y = YFLIP(intarg(ex, ip + 1)); switch (nargs) { case 4: case 2: x = intarg(ex, ip); y = YFLIP(intarg(ex, ip + 1)); break; default: error("%s: argcount mismatch\n"); break; } XSetForeground(dsp, gc, currentcolor); XDrawPoint(dsp, win, gc, x, y); XSync(dsp, False); return CONT; } /*- * POKE seg off byte [byte] ... * change 8-bit memory given 8088 seg:off address (yeah, right!) */ int f_poke(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 2: case 1: error("%s: argcount mismatch\n"); break; default: break; } #endif return unimplemented(ex, ip); } /*- * POKEL seg off byte [byte] ... * change 32-bit memory given 8088 seg:off address (yeah, right!) */ int f_pokel(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 2: case 1: error("%s: argcount mismatch\n"); break; default: break; } #endif return unimplemented(ex, ip); } /*- * POKEW seg off byte [byte] ... * change 16-bit memory given 8088 seg:off address (yeah, right!) */ int f_pokew(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 2: case 1: error("%s: argcount mismatch\n"); break; default: break; } #endif return unimplemented(ex, ip); } /*- * POP label * leave a subroutine and branch on return. */ int f_pop(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * POSITION buffer x y [R] * alter picture placement on the screen. */ int f_position(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int buf = intarg(ex, ip); int x = intarg(ex, ip + 1); int y = intarg(ex, ip + 2); int rel = 0; switch (nargs) { case 4: buf = intarg(ex, ip); picreg[buf]->xoff += intarg(ex, ip + 1); picreg[buf]->yoff += intarg(ex, ip + 2); break; case 3: buf = intarg(ex, ip); picreg[buf]->xoff = intarg(ex, ip + 1); picreg[buf]->yoff = intarg(ex, ip + 2); break; default: error("%s: argcount mismatch\n"); break; } return CONT; } /*- * PSAVE name [buffer] * save picture buffer to disk. */ int f_psave(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 2: case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * PSETBUF [buffer] * draw to picture buffer instead of screen. */ int f_psetbuf(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 1: case 0: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * PUTDFF [buffer] [delay] [start] [end] [x y] * play a differential animation file. */ int f_putdff(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 5: case 4: case 3: case 2: case 1: case 0: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * PUTUP x y [buffer] [delay] * display a clipping */ int f_putup(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int x = (int) resolvewild(ex, ip, INTEGER); int y = (int) resolvewild(ex, ip + 1, INTEGER); int clip = (int) resolvewild(ex, ip + 2, INTEGER); ImageStruct *im = clipreg[clip]; int d = 1; switch (nargs) { case 4: d = intarg(ex, ip + 3); case 3: clip = (int) resolvewild(ex, ip + 2, INTEGER); /* case 2: */ y = (int) resolvewild(ex, ip + 1, INTEGER); x = (int) resolvewild(ex, ip, INTEGER); break; default: error("%s: argcount mismatch\n"); break; } x += im->xoff; y += im->yoff; XCopyArea(dsp, im->pix, win, gc, 0, 0, im->w, im->h, x, YFLIPIM(y, im)); XSync(dsp, False); delay(d); return CONT; } /*- * RECT x1 y1 x2 y2 * draw a filled rectangle; */ int f_rect(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int x1; int y1; int x2; int y2; switch (nargs) { case 4: x1 = intarg(ex, ip); y1 = intarg(ex, ip + 1); x2 = intarg(ex, ip + 2); y2 = intarg(ex, ip + 3); break; default: error("%s: argcount mismatch\n"); break; } XSetForeground(dsp, gc, currentcolor); XFillRectangle(dsp, win, gc, x1, YFLIP(y2), x2 - x1, y2 - y1); return CONT; } /*- * RESETGL * close a library */ int f_resetgl(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 0: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * RESETSCR * reset normal screen size. */ int f_resetscr(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 0: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * RETURN [val] * return from a subroutine. */ int f_return(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { switch (nargs) { case 1: case 0: break; default: error("%s: argcount mismatch\n"); break; } if (--loopstackptr < 0) error("%s: ipstack underflow\n"); return ipstack[loopstackptr]; } /*- * REVPAGE * reverse viewing and drawing pages (for double buffering?) */ int f_revpage(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 0: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * SEND device string * send a character string to a device (yeah, right!) */ int f_send(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 2: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * SET function|feature|var value * alter system characteristics or alter text features or defines variables... */ int f_set(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 2: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * SETCOLOR val0 val1 val2 ... val16 * define palette in EGA mode */ int f_setcolor(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int i; u_long pmasks; u_long pixels[16]; ImageStruct *im = picreg[0]; switch (nargs) { case 16: break; default: error("%s: not 16 args to setcolor\n"); break; } im->cmaplen = nargs; if (!im->cmap) { im->cmap = XCreateColormap(dsp, win, vis, AllocNone); XAllocColorCells(dsp, im->cmap, True, &pmasks, 0, pixels, im->cmaplen); } for (i = 0; i < im->cmaplen; i++) { int pal = intarg(ex, ip + i); im->colors[i].pixel = 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; } XStoreColors(dsp, im->cmap, im->colors, im->cmaplen); installcmap(0); return CONT; } /*- * SETPAGE view draw * define viewing and drawing pages for double buffering. */ int f_setpage(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 2: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * SETRGB start r g b [R] rand * change color in VGA mode (not sure what R or rand do...) */ int f_setrgb(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int start; int r; int g; int b; XColor c; switch (nargs) { case 6: case 5: case 4: start = intarg(ex, ip); r = intarg(ex, ip + 1); g = intarg(ex, ip + 2); b = intarg(ex, ip + 3); break; default: error("%s: argcount mismatch\n"); break; } c.pixel = picreg[palettenum]->colors[start].pixel; c.red = r << 8; c.green = g << 8; c.blue = b << 8; c.flags = DoRed | DoGreen | DoBlue; XStoreColors(dsp, installedcmap, &c, 1); return CONT; } /*- * SETUPSCR buffer * create a virtual screen for panning. */ int f_setupscr(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * SPLIT line [R] * divide an EGA screen into two independant areas. */ int f_split(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 2: case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * SPREAD [pal1] pal2 [steps] * cross-fade between two VGA palettes. */ int f_spread(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int r1; int r2; ImageStruct *p1; ImageStruct *p2; int n = 1; XColor colors[256]; int i; int j; Colormap cmap; unsigned long pmasks; u_long pixels[256]; int len; switch (nargs) { case 3: n = intarg(ex, ip + 2); case 2: r2 = intarg(ex, ip + 1); r1 = intarg(ex, ip); p2 = picreg[r2]; p1 = picreg[r1]; break; default: error("%s: argcount mismatch\n"); break; } n = (n < 0) ? -n : n; len = p1->cmaplen; if (len != p2->cmaplen) error("%s: %d,%d spread length mismatch\n", len, p2->cmaplen); cmap = XCreateColormap(dsp, win, vis, AllocNone); XAllocColorCells(dsp, cmap, True, &pmasks, 0, pixels, len); for (i = 0; i < len; i++) { colors[i].pixel = pixels[i]; colors[i].red = p1->colors[i].red; colors[i].green = p1->colors[i].green; colors[i].blue = p1->colors[i].blue; colors[i].flags = DoRed | DoGreen | DoBlue; } XStoreColors(dsp, cmap, p1->colors, p1->cmaplen); XSetWindowColormap(dsp, win, cmap); #define lerp(a,b,step,nsteps) ((a)<(b) \ ? (a) + ((b) - (a)) * (step) / (nsteps) \ : (b) + ((a) - (b)) * (step) / (nsteps)) for (j = 1; j <= n; j++) { for (i = 0; i < len; i++) { XColor *c1 = &(p1->colors[i]); XColor *c2 = &(p2->colors[i]); colors[i].red = lerp(c1->red, c2->red, j, n); colors[i].green = lerp(c1->green, c2->green, j, n); colors[i].red = lerp(c1->red, c2->red, j, n); } XStoreColors(dsp, cmap, colors, p1->cmaplen); XSync(dsp, False); } installcmap(r2); XFreeColormap(dsp, cmap); XSync(dsp, False); return -1; } void displaystring(s, x, y) char *s; int x, y; { int i; for (i = 0; i < strlen(s); i++) { GlyphStruct *g = ¤tfont->glyphs[s[i]]; if (g->pix) { XSetStipple(dsp, gc, g->pix); XSetTSOrigin(dsp, gc, x - g->lbearing, y); XFillRectangle(dsp, win, gc, x, y, g->width, currentfont->height); x += g->width + chargap; } } } /*- * TEXT [x y] string [delay] * print characters on the screen. */ int f_text(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int x; int y; char *s; int d = 1; int i; switch (nargs) { case 4: d = intarg(ex, ip + 3); case 3: s = strarg(ex, ip + 2); y = intarg(ex, ip + 1); x = intarg(ex, ip); break; default: error("%s: argcount mismatch\n"); break; } if (!currentfont) { /* hack there should be a default font. */ XSetForeground(dsp, gc, currentcolor); XSetBackground(dsp, gc, currentbgcolor); XDrawString(dsp, win, gc, x, YFLIP(y), s, strlen(s)); goto text_exit; } currentfont->glyphs[' '].width = spacegap; y = YFLIP(y) - currentfont->height - 2; XSetFillStyle(dsp, gc, FillStippled); XSetForeground(dsp, gc, (fstyle > 2) ? currentbgcolor : currentcolor); switch (fstyle) { case 0: break; case 1: displaystring(s, x, y - 1); /* bold up */ break; case 2: displaystring(s, x + 1, y); /* bold right */ break; case 3: displaystring(s, x + 1, y - 1); /* shadow up right */ break; case 4: displaystring(s, x - 1, y - 1); /* shadow up left */ break; case 5: displaystring(s, x + 2, y - 2); /* shadow up right 2 pixels */ break; case 6: displaystring(s, x - 2, y - 2); /* shadow up left 2 pixels */ break; default: break; } XSetForeground(dsp, gc, currentcolor); displaystring(s, x, y); XSetFillStyle(dsp, gc, FillSolid); text_exit: XSync(dsp, False); delay(d); return CONT; } /*- * TILE buffer [bleed] * fill screen with copies of the clipping. */ int f_tile(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { ImageStruct *im; int x; int y; switch (nargs) { case 2: case 1: im = clipreg[intarg(ex, ip)]; break; default: error("%s: argcount mismatch\n"); break; } for (y = 0; y <= picreg[0]->h - im->h; y += im->h) for (x = 0; x <= picreg[0]->w - im->w; x += im->w) XCopyArea(dsp, im->pix, win, gc, 0, 0, im->w, im->h, x, y); delay(10); return CONT; } /*- * TIMER * set the system clock for execution timing (huh?) */ int f_timer(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 0: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * TRAN set [color] * set = "on"|"off", make color be transparent in clippings. */ int f_tran(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int tranval; switch (nargs) { case 2: case 1: tranval = intarg(ex, ip); break; default: error("%s: argcount mismatch\n"); break; } return -1; } /*- * VIDEO mode [x y] [init] * set the display mode (not sure what x and y and init are for) */ int f_video(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { char *s; char c; switch (nargs) { case 4: case 3: case 1: s = strarg(ex, ip); c = s[0]; break; default: error("%s: argcount mismatch\n"); break; } setvideomode(c); return CONT; } int KeyEvent(ev) XKeyEvent *ev; { KeySym keysym; XComposeStatus status; char string[2]; int len = XLookupString(ev, string, 1, &keysym, &status); keypressed = string[0]; if (keypressed == 27) /* Esc Key */ return -1; return len; } /*- * WAITKEY [time] [label] * wait for a keystroke or a given time, and jump to label on timeout. */ int f_waitkey(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int endtime; int retaddr = CONT; switch (nargs) { case 2: retaddr = intarg(ex, ip + 1); case 1: endtime = hundredthsofseconds() + intarg(ex, ip); break; case 0: break; default: error("%s: argcount mismatch\n"); break; } while (1) { if (nargs == 0 || XPending(dsp)) { XEvent ev; int key; XNextEvent(dsp, &ev); switch (ev.type) { case KeyPress: key = KeyEvent(&ev); if (key > 0) return CONT; if (key == -1) return ESCAPE; case ClientMessage: ExitEvent(&ev); break; default: break; } } else { usleep(10000); /* sleep for 1/100th of a second */ if (hundredthsofseconds() > endtime) return retaddr; } } } /*- * WHEN key [command] * set up an automatic response for given keystroke. */ int f_when(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { #ifdef UNIMPLEMENTED switch (nargs) { case 2: case 1: break; default: error("%s: argcount mismatch\n"); break; } #endif return unimplemented(ex, ip); } /*- * WINDOW x1 y1 x2 y2 [R] * limit screen changes to given area. */ int f_window(ex, ip, nargs) ExecStruct *ex; int ip; int nargs; { int offset_x; int offset_y; switch (nargs) { case 5: /* relative */ { offset_x = window.x; offset_y = YFLIP(window.y) - window.height; window.x = intarg(ex, ip); window.y = intarg(ex, ip + 1); window.width = intarg(ex, ip + 2) - window.x + 1; window.height = intarg(ex, ip + 3) - window.y + 1; window.x = window.x + offset_x; window.y = YFLIP(intarg(ex, ip + 3) + offset_y); break; } case 4: /* absolute */ window.x = intarg(ex, ip); window.y = intarg(ex, ip + 1); window.width = intarg(ex, ip + 2) - window.x + 1; window.height = intarg(ex, ip + 3) - window.y + 1; window.y = YFLIP(intarg(ex, ip + 3)); break; case 0: /* restore default */ window.x = 0; window.y = 0; window.width = picreg[0]->w; window.height = picreg[0]->h; break; default: error("%s: argcount mismatch\n"); } return CONT; } int (*funcs[]) () = { 0, f_box, f_break, f_call, f_cfade, f_cfree, f_cgetbuf, f_chgcolor, f_circle, f_clearscr, f_cload, f_closegl, f_color, f_cycle, f_data, f_databegin, f_dataend, f_dataskip, f_dfree, f_dload, f_edge, f_else, f_endlfloat, f_endif, f_exec, f_exit, f_ffree, f_fgaps, f_fload, f_float, f_fly, f_font, f_fstyle, f_getcolor, f_getkey, f_gosub, f_goto, f_if, f_ifkey, f_ifmem, f_ifmouse, f_ifvideo, f_int, f_line, f_link, f_local, f_loop, f_mark, f_merge, f_mode, f_mouse, f_move, f_noise, f_note, f_offset, f_opengl, f_out, f_palette, f_pan, f_pfade, f_pfree, f_pgetbuf, f_pload, f_pnewbuf, f_point, f_poke, f_pokel, f_pokew, f_pop, f_position, f_psave, f_psetbuf, f_putdff, f_putup, f_rect, f_resetgl, f_resetscr, f_return, f_revpage, f_send, f_set, f_setcolor, f_setpage, f_setrgb, f_setupscr, f_split, f_spread, f_text, f_tile, f_timer, f_tran, f_video, f_waitkey, f_when, f_window, f_pfade, f_waitkey }; void printexec(ex, nargs) ExecStruct *ex; int nargs; { int i; printf("executing: %s", tokens[ex->Code[ex->ip].token]); for (i = 1; i <= nargs; i++) switch (ex->Code[ex->ip + i].token) { case STRING: printf(" %s", ex->Code[ex->ip + i].val.s); break; case INTEGER: printf(" %d", ex->Code[ex->ip + i].val.i); break; case IMAGE: printf(" %s", ex->Code[ex->ip + i].val.image->name); break; case FONTTYPE: if (ex->Code[ex->ip + i].val.font) printf(" %s", ex->Code[ex->ip + i].val.font->name); else printf(" (nil)"); break; case EXECTYPE: printf(" %s", ex->Code[ex->ip + i].val.exec->name); break; case WILDTYPE: printf(" @"); break; default: error("%s: bogus token type.\n"); } printf("\n"); } void execfile(ex, ip) ExecStruct *ex; int ip; { ex->ip = ip; ex->currentdataptr = -1; ex->currentdataend = -1; while (1) { int nargs = ex->Code[ex->ip].val.i; int i = ex->Code[ex->ip].token; int retval; if (i > NTOKENS) { printf("skipping bogus token %s\n", ex->Code[ex->ip].val.s); ex->ip++; continue; } if (verbose) printexec(ex, nargs); switch (retval = funcs[i] (ex, ex->ip + 1, nargs)) { case DONE: return; case ESCAPE: exit(0); case CONT: if ((ex->ip += (nargs + 1)) >= ex->numcodes) return; break; default: ex->ip = retval; } exitcheck(); } }