diff options
Diffstat (limited to 'dviware/umddvi/dev/dmdslave.c')
-rw-r--r-- | dviware/umddvi/dev/dmdslave.c | 1176 |
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++; + } + } +} |