summaryrefslogtreecommitdiff
path: root/dviware/umddvi/dev/dmdslave.c
diff options
context:
space:
mode:
Diffstat (limited to 'dviware/umddvi/dev/dmdslave.c')
-rw-r--r--dviware/umddvi/dev/dmdslave.c1176
1 files changed, 1176 insertions, 0 deletions
diff --git a/dviware/umddvi/dev/dmdslave.c b/dviware/umddvi/dev/dmdslave.c
new file mode 100644
index 0000000000..ac1988379c
--- /dev/null
+++ b/dviware/umddvi/dev/dmdslave.c
@@ -0,0 +1,1176 @@
+/*
+ * Typesetter/Terminal Emulator for the DMD 5620
+ *
+ * Lou Salkind
+ * New York University
+ * Thu Apr 2 01:21:09 EST 1987
+ *
+ * This program was inspired by the DMD proof program
+ * and the Impress typesetting language. It is used by
+ * the TeX DVIDMD driver.
+ */
+
+#include <jerq.h>
+#include "layer.h"
+#include "font.h"
+#include "dmdcodes.h"
+
+#define MAXFAMILY 128 /* number of different fonts */
+#define MAXFONTNAME 16 /* maximum font string */
+#define PAGECHAR 8192 /* buffered characters to save */
+#define MAXPAGE 127
+
+#define SCROLLSIZE 20 /* scrolling border */
+#define PAGEPIXELS 1010 /* XXX - length of page (should be an argument) */
+#define NEWLINESIZE 16
+#define CURSOR '\01' /* cursor char in font */
+#define LINEBUFSIZE 100
+
+#define MOVED 256
+
+#ifdef PAGECHAR
+/* treatment of input characters */
+#define CHAR_DISCARD 0
+#define CHAR_STORE 1
+#define CHAR_FETCH 2
+
+int savechars;
+char savebuf[PAGECHAR];
+char *saveptr;
+#endif
+
+#define RoundUp(a, b) (((a) + (b) - 1) & ~((b) - 1))
+
+#ifdef MPX
+#undef cursinhibit
+#undef cursallow
+#define cursinhibit() {}
+#define cursallow() {}
+#endif
+
+static Texture16 prompt = {
+ 0x0000, 0x0000, 0x0000, 0x322E, 0x4B69, 0x4369, 0x42A9, 0x42A9,
+ 0x42A9, 0x4229, 0x4229, 0x4229, 0x322E, 0x0000, 0x0000, 0x0000
+};
+
+Point fudge = {5, 3}; /* DAG - offsets from corners */
+
+int dotypeset; /* 1==typesetter, 0==terminal */
+int cursvis; /* is cursor visible */
+Point org; /* current origin */
+Point typeorg; /* current typesetter origin */
+Point curpt; /* current typesetter point relative to origin */
+Point curpos; /* current ascii terminal position */
+
+struct line {
+ char buf[LINEBUFSIZE];
+ char *bufp;
+};
+
+struct line line;
+
+struct glyph {
+ Bitmap g_bitmap;
+ short g_pxwidth;
+ short g_xoffset;
+ short g_yoffset;
+};
+
+struct fontinfo {
+ char f_name[MAXFONTNAME];
+ struct glyph f_glyph[128];
+};
+
+struct fontinfo *ftbl[MAXFAMILY];
+struct fontinfo *curfont;
+Point inpoint();
+
+
+main()
+{
+ register int c;
+
+ resetmode(DMD_TERM);
+#ifdef MPX
+ P->state |= RESHAPED; /* set window parameters */
+#else
+ Drect = inset(Drect, 2);
+#endif /* MPX */
+ windowupdate();
+ for(;;) {
+ c = inchar();
+ if (dotypeset)
+ typeset(c);
+ else {
+ if(cursvis)
+ term(CURSOR, 0); /* undraw cursor */
+ term(c, 1);
+ while (own()&RCV)
+ term(inchar(), 1);
+ term(CURSOR, 0); /* draw at new spot */
+ cursvis = 1;
+ }
+ }
+}
+
+/* terminal emulation */
+term(c, advance)
+ register int c;
+{
+ register struct line *linep = &line;
+ register Point *pp = &curpos;
+ register Fontchar *fp;
+ Rectangle r;
+ Point p;
+
+ if (c & 0x80) {
+ if (c == DMD_TYPESET) {
+ resetmode(DMD_TYPESET);
+ send(DMD_ACK);
+ return;
+ }
+ c &= 0x7F;
+ }
+ switch(c) {
+ default:
+ fp = defont.info+c;
+ if (fp->width+pp->x >= Drect.corner.x)
+ newline(linep, pp);
+ p = *pp;
+ r.origin.x = fp->x;
+ r.corner.x = (fp+1)->x;
+ if (advance) {
+ r.origin.y = 0;
+ r.corner.y = defont.height;
+ bitblt(defont.bits, r, &display, p, F_STORE);
+ pp->x += fp->width;
+ if (linep->bufp < linep->buf+LINEBUFSIZE)
+ *linep->bufp++ = c;
+ } else {
+ r.origin.y = fp->top;
+ r.corner.y = fp->bottom;
+ p.y += fp->top;
+ bitblt(defont.bits, r, &display, p, F_XOR);
+ }
+ break;
+ case '\n':
+ newline(linep, pp);
+ break;
+ case '\7':
+ ringbell(); /* DAG -- should work? */
+ case 0:
+ break;
+ case '\r':
+ pp->x=Drect.origin.x+fudge.x; /* DAG -- changed 5 to fudge.x */
+ linep->bufp = linep->buf;
+ break;
+ case '\013': /* ^K: reverse linefeed */
+ if(pp->y>Drect.origin.y+fudge.y+defont.height)
+ pp->y-=NEWLINESIZE;
+ break;
+ case '\b':
+ backspace(linep, pp);
+ break;
+ case '\014':
+ formfeed(linep, pp);
+ break;
+ case '\t':
+ pp->x=nexttab(pp->x);
+ if(pp->x>=Drect.corner.x)
+ newline(linep, pp);
+ if(linep->bufp<linep->buf+LINEBUFSIZE)
+ *linep->bufp++=c;
+ break;
+ }
+}
+
+/*int eightspaces=8*dispatch[' '].c_wid;*/
+int eightspaces=72;
+
+nexttab(x)
+{
+ register int xx = x-Drect.origin.x-fudge.x;
+
+ return(xx-(xx%eightspaces)+eightspaces+Drect.origin.x+fudge.x);
+}
+
+backspace(linep, pp)
+ register struct line *linep;
+ register Point *pp;
+{
+ register char *p;
+ register int x = Drect.origin.x+fudge.x;
+
+ if (linep->bufp>linep->buf) {
+ for (p=linep->buf; p<linep->bufp-1; p++)
+ if (*p=='\t')
+ x = nexttab(x);
+ else
+ x += defont.info[*p].width;
+ pp->x = x;
+ --linep->bufp;
+ if (*p!='\t')
+ term(*p, 0);
+ }
+}
+
+newline(linep, pp)
+ struct line *linep;
+ register Point *pp;
+{
+ register cursoff=0;
+
+ if (pp->y+2*NEWLINESIZE > Drect.corner.y-fudge.y+1) {
+ /* weirdness is because the tail of the arrow may be anywhere */
+ if (rectXrect(Rect(mouse.xy.x-16, mouse.xy.y-16, mouse.xy.x+16,
+ mouse.xy.y+16), Drect)){
+ cursinhibit();
+ cursoff++;
+ }
+ lscroll();
+ if(cursoff)
+ cursallow();
+ } else
+ pp->y += NEWLINESIZE;
+ pp->x = Drect.origin.x+fudge.x;
+ linep->bufp = linep->buf;
+}
+
+lscroll()
+{
+ Rectangle r;
+
+ r = Drect;
+ r.origin.y += NEWLINESIZE;
+ bitblt(&display, r, &display, Pt(r.origin.x, r.origin.y-NEWLINESIZE), F_STORE);
+ stipple(Rpt(Pt(Drect.origin.x, Drect.corner.y-NEWLINESIZE), Drect.corner));
+}
+
+formfeed(linep, pp)
+ struct line *linep;
+ Point *pp;
+{
+ cursinhibit();
+ stipple(Drect);
+ cursallow();
+ *pp=add(Drect.origin, fudge);
+ linep->bufp=linep->buf;
+}
+
+stipple(r)
+ Rectangle r;
+{
+ cursinhibit();
+ rectf(&display, r, F_CLR);
+ cursallow();
+}
+
+/* routines to handle command input */
+
+inchar()
+{
+ register int c;
+
+#ifdef PAGECHAR
+ if (savechars == CHAR_FETCH)
+ return(*saveptr++ & 0377);
+#endif
+#ifdef MPX
+ wait(RCV);
+ if (P->state&(RESHAPED|MOVED))
+ windowupdate();
+ c = rcvchar();
+#else
+ for ( ; ; ) {
+ wait(RCV|KBD);
+ if (own() & RCV) {
+ c = rcvchar();
+ break;
+ }
+ if (!dotypeset)
+ send(kbdchar());
+ }
+#endif MPX
+#ifdef PAGECHAR
+ if (savechars == CHAR_STORE) {
+ if (saveptr < &savebuf[PAGECHAR])
+ *saveptr++ = c;
+ else
+ savechars = CHAR_DISCARD;
+ }
+#endif
+ return(c&0377);
+}
+
+insignchar()
+{
+ register int c;
+
+ c = inchar();
+ if (c > 127)
+ c -= 256;
+ return(c);
+}
+
+inshort()
+{
+ register short i;
+
+ i = inchar() << 8;
+ i |= inchar();
+ return(i);
+}
+
+Point
+inpoint()
+{
+ Point p;
+
+ p.x = inshort() + typeorg.x;
+ p.y = inshort() + typeorg.y;
+ return(p);
+}
+
+send(c)
+{
+ char cc = c;
+
+ sendnchars(1, &cc);
+}
+
+/* typesetter emulation */
+typeset(c)
+ register int c;
+{
+ register struct glyph *g;
+ register Bitmap *b;
+ Point pprime;
+ int old;
+
+ if (c <= 127) {
+ if (curfont == 0)
+ return;
+ g = &curfont->f_glyph[c];
+ b = &g->g_bitmap;
+ if (b->base == 0) {
+ curpt.x += g->g_pxwidth;
+ return;
+ }
+ pprime = add(curpt, typeorg);
+ pprime.x -= g->g_xoffset;
+ pprime.y -= g->g_yoffset;
+ bitblt(b, b->rect, &display, pprime, F_OR);
+ curpt.x += g->g_pxwidth;
+ return;
+ }
+
+ switch (c) {
+ case DMD_EXIT:
+ bye();
+ break;
+ case DMD_TERM:
+#ifdef PAGECHAR
+ savechars = CHAR_DISCARD;
+#endif
+ resetmode(DMD_TERM);
+ break;
+ case DMD_CLEAR:
+ stipple(Drect);
+ curpos = add(org, fudge);
+ break;
+ case DMD_TYPESET:
+ send(DMD_ACK);
+ break;
+ case DMD_ASCII:
+#ifdef PAGECHAR
+ if (savechars == CHAR_STORE)
+ saveptr--;
+ old = savechars;
+ savechars = CHAR_DISCARD;
+#endif
+ while (c = inchar())
+ term(c, 1);
+#ifdef PAGECHAR
+ savechars = old;
+#endif
+ break;
+ case DMD_RULE: {
+ short w, h;
+ Rectangle r;
+
+ w = inshort();
+ h = inshort();
+ pprime = add(curpt, typeorg);
+ pprime.y++;
+ r.origin = pprime;
+ r.origin.y = pprime.y - h;
+ r.corner = pprime;
+ r.corner.x = pprime.x + w;
+ rectf(&display, r, F_STORE);
+ break;
+ }
+ case DMD_FORW:
+ curpt.x++;
+ break;
+ case DMD_BACK:
+ curpt.x--;
+ break;
+ case DMD_HABS:
+ curpt.x = inshort();
+ break;
+ case DMD_HREL:
+ curpt.x += insignchar();
+ break;
+ case DMD_VABS:
+ curpt.y = inshort();
+ break;
+ case DMD_VREL:
+ curpt.y += insignchar();
+ break;
+ case DMD_PAGE:
+#ifdef PAGECHAR
+ saveptr = savebuf;
+ savechars = CHAR_STORE;
+#endif
+ stipple(Drect);
+ curpos = add(org, fudge);
+ curpt.x = curpt.y = 0;
+ break;
+ case DMD_ENDPAGE:
+ pagecmd();
+ break;
+ case DMD_SETFONT: {
+ int i;
+
+ i = inchar();
+ if (i < MAXFAMILY)
+ curfont = ftbl[i];
+ break;
+ }
+ case DMD_MKFONT:
+ case DMD_SGLYPH:
+ case DMD_BGLYPH:
+#ifdef PAGECHAR
+ if (savechars == CHAR_STORE)
+ saveptr--;
+ old = savechars;
+ savechars = CHAR_DISCARD;
+#endif
+ if (c == DMD_MKFONT)
+ ldfont();
+ else
+ ldglyph(c);
+#ifdef PAGECHAR
+ savechars = old;
+#endif
+ break;
+ case DMD_SEGMENT:
+ case DMD_SPLINE:
+ define_path(c);
+ break;
+ case DMD_CIRCLE:
+ define_circle();
+ break;
+ case DMD_ELLIPSE:
+ define_ellipse();
+ break;
+ case DMD_DRAWPATH:
+ draw_path();
+ break;
+ case DMD_FILLPATH:
+ fill_path();
+ break;
+ case DMD_PENSIZE:
+ set_pen();
+ break;
+ default:
+ break;
+ }
+}
+
+/* request an index number for a new font */
+ldfont()
+{
+ register struct fontinfo *f;
+ register int i, j;
+ register int x = -1;
+ char name[MAXFONTNAME];
+ register char *p;
+ char loaded[16];
+
+ p = name;
+ while (*p++ = inchar())
+ if (p >= &name[MAXFONTNAME]) {
+ while (inchar())
+ continue;
+ break;
+ }
+ for (i = 0; i < sizeof(loaded); i++)
+ loaded[i] = 0;
+ /* look for the font... */
+ for (i = 0; i < MAXFAMILY; i++) {
+ f = ftbl[i];
+ if (f && strncmp(f->f_name, name, sizeof(f->f_name)) == 0) {
+ for (j = 0; j < 128; j++) {
+ if (f->f_glyph[j].g_bitmap.base)
+ loaded[j>>3] |= 1 << (~j & 07);
+ }
+ send(i);
+ sendnchars(sizeof(loaded), loaded);
+ return;
+ }
+ if (x == -1 && f == 0)
+ x = i;
+ }
+ if (x == -1) {
+ send(-1);
+ return;
+ }
+ f = (struct fontinfo *)alloc(sizeof (struct fontinfo));
+ if (f == 0) {
+ send(-1);
+ return;
+ }
+ ftbl[x] = f;
+ strncpy(f->f_name, name, sizeof(f->f_name));
+ send(x);
+ sendnchars(sizeof(loaded), loaded);
+}
+
+/* download a particular character in a font */
+ldglyph(c)
+ int c;
+{
+ register struct glyph *g;
+ register int i, j;
+ register char *p;
+ short chr, fam, w;
+ int words;
+ int o;
+ short xs, ys;
+ int endb;
+ static struct glyph gdummy;
+
+ w = inshort();
+ fam = (w >> 7) & 0177;
+ chr = w & 0177;
+ if (ftbl[fam])
+ g = &(ftbl[fam]->f_glyph[chr]);
+ else {
+ ftbl[fam] = (struct fontinfo *)alloc(sizeof (struct fontinfo));
+ g = ftbl[fam] ? &(ftbl[fam]->f_glyph[chr]) : &gdummy;
+ }
+
+ if (c == DMD_SGLYPH) {
+ g->g_pxwidth = insignchar();
+ xs = inchar();
+ g->g_xoffset = insignchar();
+ ys = inchar();
+ g->g_yoffset = insignchar();
+ } else {
+ g->g_pxwidth = inshort();
+ xs = inshort();
+ g->g_xoffset = inshort();
+ ys = inshort();
+ g->g_yoffset = inshort();
+ }
+ words = RoundUp(xs, WORDSIZE) >> WORDSHIFT;
+ o = RoundUp(xs, 8) >> 3;
+ endb = words * sizeof(Word);
+ if (g->g_bitmap.base)
+ free(g->g_bitmap.base);
+ if (g == &gdummy || (p = alloc(ys * endb)) == 0) {
+ /* skip raster bytes */
+ j = o * ys;
+ for (i = 0; i < j; i++)
+ inchar();
+ } else {
+ /* read raster here */
+ g->g_bitmap.base = (Word *)p;
+ g->g_bitmap.width = words;
+ g->g_bitmap.rect.origin.x = 0;
+ g->g_bitmap.rect.origin.y = 0;
+ g->g_bitmap.rect.corner.x = xs;
+ g->g_bitmap.rect.corner.y = ys;
+ g->g_bitmap._null = 0;
+ p = (char *)g->g_bitmap.base;
+ for (j = 0; j < ys; j++) {
+ for (i = 0; i < o; i++)
+ *p++ = inchar();
+ for ( ; i < endb; i++)
+ *p++ = 0;
+ }
+ }
+}
+
+/* mouse and keyboard input routines at end of page */
+
+static char *b3m[] = {
+ "redraw",
+ "next",
+ "prev",
+ "quit",
+ "exit",
+ NULL
+};
+
+static Menu menu = { b3m };
+
+Texture16 ok = {
+ 0x1C44, 0x2248, 0x2250, 0x2270,
+ 0x2248, 0x1C44, 0x0000, 0x0380,
+ 0x0440, 0x0440, 0x0080, 0x0100,
+ 0x0100, 0x0100, 0x0000, 0x0100,
+};
+
+minkbd()
+{
+ Texture16 *t;
+ register int i;
+ int oscroll = 0;
+ register int inscroll = 0;
+ Point selpt;
+
+ while (i = wait(KBD|MOUSE|RCV)) {
+ if (i&KBD)
+ return(kbdchar());
+ else if (i&RCV)
+ return(rcvchar());
+ selpt = mouse.xy;
+ i = selpt.x - Drect.origin.x;
+ inscroll = 0;
+ if (i >= 0 && i < SCROLLSIZE)
+ inscroll += 1;
+ i = Drect.corner.y - selpt.y;
+ if (i >= 0 && i < SCROLLSIZE)
+ inscroll += 2;
+ if (inscroll != oscroll) {
+ cursswitch(inscroll ? &C_crosshair : &prompt);
+ oscroll = inscroll;
+ }
+ switch (inscroll) {
+ case 0:
+ if (!bttn3())
+ break;
+ switch (i = menuhit(&menu, 3)) {
+ case -1:
+ break;
+ case 4:
+ t = cursswitch(&ok);
+ while (!bttn123()) sleep(1);
+ i = bttn3();
+ while (bttn123()) sleep(1);
+ (void)cursswitch(t);
+ if (i)
+ return('x');
+ break;
+ default:
+ return("rnpq"[i]);
+ }
+ break;
+ case 1:
+ if (!bttn13())
+ break;
+ if (bttn1())
+ typeorg.y -= selpt.y - Drect.origin.y;
+ else
+ typeorg.y += selpt.y - Drect.origin.y;
+ /* primitive scroll for now */
+ while (bttn123());
+ return('s');
+ case 2:
+ if (!bttn13())
+ break;
+ if (bttn1())
+ typeorg.x -= selpt.x - Drect.origin.x;
+ else
+ typeorg.x += selpt.x - Drect.origin.x;
+ /* primitive scroll for now */
+ while (bttn123());
+ return('s');
+ case 3:
+ if (bttn1())
+ return('n');
+ else if (bttn2())
+ return('r');
+ else if (bttn3())
+ return('p');
+ break;
+ }
+ sleep(1);
+ }
+ /*NOT REACHED*/
+}
+
+pagecmd()
+{
+ register int i;
+ register Texture16 *t;
+ int cmd;
+ Point p1, p2;
+ int redraw;
+#ifdef PAGECHAR
+ int pagesaved;
+ char buf[40];
+
+ pagesaved = savechars != CHAR_DISCARD;
+#endif
+ t = cursswitch(&prompt);
+pgstart:
+ redraw = 0;
+ /*
+ * draw outlines of scroll bars. We will draw
+ * the whole lines when we can't write in the
+ * scroll area, but for now, do it this way.
+ */
+ p1 = Drect.origin;
+ p1.x += SCROLLSIZE;
+ p2.x = p1.x;
+ p2.y = p1.y + SCROLLSIZE;
+ segment(&display, p1, p2, F_STORE);
+ p1.y = Drect.corner.y - 2*SCROLLSIZE;
+ p2.y = Drect.corner.y;
+ segment(&display, p1, p2, F_STORE);
+ p1.y = Drect.corner.y - SCROLLSIZE;
+ p2.y = p1.y;
+ p1.x = Drect.origin.x;
+ p2.x = p1.x + 2*SCROLLSIZE;
+ segment(&display, p1, p2, F_STORE);
+ p1.x = Drect.corner.x - SCROLLSIZE;
+ p2.x = Drect.corner.x;
+ segment(&display, p1, p2, F_STORE);
+#ifdef PAGECHAR
+ savechars = CHAR_DISCARD;
+#ifdef DEBUG
+ sprintf(buf, "%d", saveptr-savebuf);
+ p1 = org;
+ p1.x += 20;
+ p1.y += 20;
+ string(&defont, buf, &display, p1, F_XOR);
+#endif
+#endif
+ switch (cmd = minkbd()) {
+ case 0177:
+ case 04:
+ case 'q':
+ send(DMD_EXIT);
+ resetmode(DMD_TERM);
+ t = 0;
+ break;
+ case 'x':
+ send(DMD_EXIT);
+ bye();
+ break;
+ case 'r':
+ case '\f':
+ typeorg = org;
+ /* fall into... */
+ case 's':
+ redraw = 1;
+ break;
+ case 'n':
+ case ' ':
+ typeorg.y -= Drect.corner.y - Drect.origin.y;
+ if (org.y - typeorg.y < PAGEPIXELS) {
+ redraw = 1;
+ break;
+ }
+ /* fall into... */
+ case '+':
+ case '\r':
+ case '\n':
+ typeorg = org;
+ send(DMD_PAGE);
+ send(1);
+ break;
+ case 'p':
+ typeorg.y += Drect.corner.y - Drect.origin.y;
+ if (org.y >= typeorg.y) {
+ redraw = 1;
+ break;
+ }
+ /* fall into... */
+ case '-':
+ typeorg = org;
+ send(DMD_PAGE);
+ send(-1);
+ break;
+ default:
+ /* ringbell(); */
+ goto pgstart;
+ }
+ if (redraw) {
+#ifdef PAGECHAR
+ if (pagesaved) {
+#ifdef MPX
+ if (P->state&(RESHAPED|MOVED))
+ windowupdate();
+#endif
+ typeset(DMD_PAGE);
+ saveptr = savebuf;
+ savechars = CHAR_FETCH;
+ while ((i = inchar()) != DMD_ENDPAGE)
+ typeset(i);
+ (void)cursswitch(&prompt);
+ goto pgstart;
+ }
+#endif
+ send(DMD_PAGE);
+ send(0);
+ }
+ (void)cursswitch(t);
+}
+
+inkbd()
+{
+ wait(RCV|KBD);
+ return((own()&KBD)? kbdchar():rcvchar());
+}
+
+bye()
+{
+ register int i;
+
+ for (i = 0; i < MAXFAMILY; i++) {
+ if (ftbl[i])
+ freefont(ftbl[i]);
+ }
+ exit();
+}
+
+freefont(f)
+ struct fontinfo *f;
+{
+ struct glyph *g;
+
+ for (g = f->f_glyph; g < &f->f_glyph[128]; g++)
+ if (g->g_bitmap.base)
+ free((char *)g->g_bitmap.base);
+ free((char *)f);
+}
+
+#ifdef notdef
+edit(s)
+ char *s;
+{
+ char buf[40];
+ Point p;
+ int c;
+ register i;
+
+ strcpy(buf, s);
+ p = mouse.xy;
+ disp(buf, p);
+ for(i = strlen(buf); (c = inkbd()) != '\r';)
+ {
+ disp(buf, p);
+ p = mouse.xy;
+ switch(c)
+ {
+ case '\b':
+ if((buf[i] != ' ') && (i > 0))
+ buf[--i] = 0;
+ break;
+ case '@':
+ while(buf[i] != ' ') i--;
+ buf[++i] = 0;
+ break;
+ default:
+ buf[i++] = c;
+ buf[i] = 0;
+ break;
+ }
+ disp(buf, p);
+ }
+ disp(buf, p);
+ strcpy(s, buf);
+}
+
+disp(s, p)
+ char *s;
+ Point p;
+{
+ string(&defont, "\001", &display,
+ string(&defont, s, &display, p, F_XOR), F_XOR);
+}
+#endif
+
+resetmode(c)
+ int c;
+{
+ if (c == DMD_TERM) {
+ cursvis = dotypeset = 0;
+#ifdef MPX
+ request(SEND|RCV);
+#else
+ request(SEND|RCV|KBD);
+#endif
+ curpos.x = org.x + fudge.x;
+ curpos.y = Drect.corner.y - fudge.y - defont.height;
+ } else {
+ dotypeset = 1;
+ request(SEND|RCV|KBD|MOUSE);
+ typeorg = org;
+ }
+}
+
+windowupdate()
+{
+#ifdef MPX
+ if (P->state&RESHAPED) {
+#endif
+ org = Drect.origin;
+ typeorg = org;
+ curpos = add(org, fudge);
+ line.bufp = line.buf;
+ if (cursvis) {
+ term(CURSOR, 0); /* flip state */
+ cursvis = 0;
+ }
+#ifdef MPX
+ } else {
+ curpos = add(sub(curpos, org), Drect.origin);
+ typeorg = add(sub(typeorg, org), Drect.origin);
+ org = Drect.origin;
+ }
+ P->state &= ~(MOVED|RESHAPED);
+#endif
+ artdeco();
+}
+
+static Texture16 vstripe = {
+ 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0,
+ 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0,
+ 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0,
+ 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0
+};
+
+static Texture16 hstripe = {
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x0000, 0x0000, 0x0000, 0x0000,
+ 0xffff, 0xffff, 0xffff, 0xffff,
+ 0x0000, 0x0000, 0x0000, 0x0000,
+};
+
+artdeco()
+{
+ texture16(&display, Rect(display.rect.origin.x, display.rect.origin.y,
+ display.rect.corner.x, Drect.origin.y), &vstripe, F_XOR);
+ texture16(&display, Rect(display.rect.origin.x, Drect.origin.y,
+ Drect.origin.x, Drect.corner.y), &hstripe, F_XOR);
+ texture16(&display, Rect(Drect.corner.x, Drect.origin.y,
+ display.rect.corner.x, Drect.corner.y), &hstripe, F_XOR);
+ texture16(&display, Rect(display.rect.origin.x, Drect.corner.y,
+ display.rect.corner.x, display.rect.corner.y), &vstripe, F_XOR);
+}
+
+/* graphics support; for now there are some unimplemented operations */
+
+#define MAXPOINTS 60
+
+#define PATH_NONE -1
+#define PATH_SEGMENT 0
+#define PATH_SPLINE 1
+#define PATH_CIRCLE 2
+#define PATH_ELLIPSE 3
+
+int path_type = PATH_NONE;
+int pen_size = 1;
+
+struct {
+ Point c_center;
+ Point c_start;
+ Point c_finish;
+} path_circle;
+
+struct {
+ Point e_center;
+ Point e_start;
+ Point e_finish;
+ short e_xradius;
+ short e_yradius;
+} path_ellipse;
+
+Point path_pts[MAXPOINTS+2];
+int path_len;
+
+define_path(c)
+{
+ register int i, n;
+ register Point *pp;
+
+ path_type = (c==DMD_SEGMENT) ? PATH_SEGMENT : PATH_SPLINE;
+ n = inshort();
+ path_len = n;
+ if (path_len > MAXPOINTS) {
+ path_len = MAXPOINTS;
+ for (i = path_len; i < n; i++)
+ (void)inpoint();
+ }
+ pp = &path_pts[1];
+ for (i = 0; i < path_len; i++)
+ *pp++ = inpoint();
+}
+
+define_circle()
+{
+ path_circle.c_center = inpoint();
+ path_circle.c_start = inpoint();
+ path_circle.c_finish = inpoint();
+ path_type = PATH_CIRCLE;
+}
+
+define_ellipse()
+{
+ path_ellipse.e_center = inpoint();
+ path_ellipse.e_start = inpoint();
+ path_ellipse.e_finish = inpoint();
+ path_ellipse.e_xradius = inshort();
+ path_ellipse.e_yradius = inshort();
+ path_type = PATH_ELLIPSE;
+}
+
+draw_path()
+{
+ int rop;
+
+ rop = inchar(); /* ignore for now */
+ switch (path_type) {
+ case PATH_SEGMENT:
+ draw_segment(F_OR);
+ break;
+ case PATH_SPLINE:
+ draw_spline(F_OR);
+ break;
+ case PATH_CIRCLE:
+ draw_circle(F_OR);
+ break;
+ case PATH_ELLIPSE:
+ draw_ellipse(F_OR);
+ break;
+ }
+}
+
+fill_path()
+{
+ int rop;
+
+ rop = inchar(); /* ignore for now */
+}
+
+set_pen()
+{
+ int i = inchar();
+
+ if (i < 1)
+ i = 1;
+ pen_size = i;
+}
+
+/* draw a spline path */
+draw_spline(f)
+ int f;
+{
+ register Point *pp = path_pts;
+ register long w, t1, t2, t3, scale=1000;
+ register int i, j, steps=10;
+ int n = path_len + 1;
+ Point p, q;
+
+ pp[0] = pp[1];
+ pp[n] = pp[n-1];
+ p = pp[0];
+ for (i = 0; i < n-1; i++) {
+ for (j = 0; j < steps; j++) {
+ w = scale * j / steps;
+ t1 = w * w / (2 * scale);
+ w = w - scale/2;
+ t2 = 3*scale/4 - w * w / scale;
+ w = w - scale/2;
+ t3 = w * w / (2*scale);
+ q.x = (t1*pp[i+2].x + t2*pp[i+1].x +
+ t3*pp[i].x + scale/2) / scale;
+ q.y = (t1*pp[i+2].y + t2*pp[i+1].y +
+ t3*pp[i].y + scale/2) / scale;
+ line_btw(p, q, f);
+ p = q;
+ }
+ }
+}
+
+/* draw a segment path */
+draw_segment(f)
+ int f;
+{
+ register Point *pp;
+ register int i;
+
+ pp = &path_pts[1];
+ if (path_len == 1) {
+ if (pen_size > 1)
+ disc(&display, pp[0], pen_size, f);
+ else
+ point(&display, pp[0], f);
+ } else {
+ for (i = 1; i < path_len; i++) {
+ line_btw(pp[0], pp[1], f);
+ pp++;
+ }
+ }
+}
+
+draw_circle(f)
+ int f;
+{
+ /* ignore pen size for now */
+
+ if (path_circle.c_center.x == path_circle.c_finish.x &&
+ path_circle.c_center.y == path_circle.c_finish.y) {
+ circle(&display, path_circle.c_center, path_circle.c_start.x, f);
+ } else {
+ arc(&display, path_circle.c_center, path_circle.c_start,
+ path_circle.c_finish, f);
+ }
+}
+
+draw_ellipse(f)
+ int f;
+{
+ /* ignore pen size for now */
+
+ if (path_ellipse.e_center.x == path_ellipse.e_finish.x &&
+ path_ellipse.e_center.y == path_ellipse.e_finish.y) {
+ ellipse(&display, path_ellipse.e_center, path_ellipse.e_xradius,
+ path_ellipse.e_yradius, f);
+ } else {
+ elarc(&display, path_ellipse.e_center, path_ellipse.e_xradius,
+ path_ellipse.e_yradius, path_ellipse.e_start,
+ path_ellipse.e_finish, f);
+ }
+}
+
+/* Draw a line on the screen. */
+line_btw(p0, p1, rop)
+ Point p0, p1;
+{
+ register int i;
+ register int incx;
+
+ if (abs(p1.y-p0.y) > abs(p1.x-p0.x)) {
+ incx = 1;
+ p0.x -= pen_size/2;
+ p1.x -= pen_size/2;
+ } else {
+ incx = 0;
+ p0.y -= pen_size/2;
+ p1.y -= pen_size/2;
+ }
+ for (i = 0; i < pen_size; i++) {
+ segment(&display, p0, p1, rop);
+ if (incx) {
+ p0.x++; p1.x++;
+ } else {
+ p0.y++; p1.y++;
+ }
+ }
+}