#include "defs.h" /* * write text large if zoomed in */ wwtext(v, t) DL v; STRING t; { style((gscale)? 16: 0, -1, 0); wtext(v, t); } /* * Draw text vertically. * * p = position of the lower left corner of the first character * cp = string */ vtext(p, cp) DL p; REG STRING cp; { DL1 at; char pc[2]; style((gscale)? 16: 0, -1, 0); pc[1] = 0; copypt(p, at); while(pc[0] = *cp++){ at->y -= 160; mode(GRAPH); if (wvec(at)) textat(dtow(at), pc); } } /* * write text at given virtual position. * * v = position of lower left corner of first character * t = string to write */ wtext(v, t) DL v; REG STRING t; { char pc[2]; DL1 at; if (gscale == 0) textat(dtow(v), t); else { pc[1] = 0; copypt(v, at); while(pc[0] = *t++){ mode(GRAPH); if (wvec(at)) textat(dtow(at), pc); at->x += 128; } } } wchar(p, c) DL p; CHAR c; { CHAR s[1]; s[0]=c; s[1]=0; wtext(roffset(p, -48, -64), s); } LOC DL radial(); /* * move virtual drawing beam to given position * * if in GRAPH mode, all wvec calls after the first * draw a line segment, or as much as fit on the screen. * In PPLOT mode, each call generates a single visible * point if it is on the screen. * return 1 if displayed, zero if not. */ wvec(v) DL v; { LOC DL1 p1, p2; REG DL pp, p; INT nm; REG INT out; pp = p1; if (gscale == 0){ copypt(v, pp); vector(dtow(pp)); return(1); } nm = newmode || (lastmode != GRAPH); newmode = 0; copypt(v, p2); p = p2; out = winddir(p); if (pp->type == 0 || nm){ if (!out) goto pendown; else if (!nm) vector(dtow(radial(pp, p, out))); goto penup; } if (!out){ vector(dtow(radial(p, pp, pp->type))); goto pendown; } if (p->x == pp->x && (out | pp->type) == 014){ vector(dtow(point(p->x, wind1->y))); vector(dtow(point(p->x, wind2->y))); } else if (p->y == pp->y && (out | pp->type) == 3){ vector(dtow(point(wind1->x, p->y))); vector(dtow(point(wind2->x, p->y))); } penup: mode(GRAPH); newmode = 0; pp->type = out; copypt(p, pp); return(0); pendown: pp->type = 0; copypt(p, pp); vector(dtow(p)); return(1); } /* * return point where line intersects window boundary * * pi is point within the boundary. * px is point outside the boundary. * tx is type of point px: */ LOC DL radial(pi, px, tx) REG DL pi, px; { LOC DL1 pt; REG INT w; INT flag; flag = 0; switch(tx){ case 5: case 9: flag++; case 1: w = wind1->x; break; case 6: case 10: flag++; case 2: w = wind2->x; break; case 4: w = wind1->y; break; case 8: w = wind2->y; } if (tx & 3){ pt->x = w - pi->x; pt->y = scale(px->y - pi->y, pt->x, px->x - pi->x); } else { pt->y = w - pi->y; pt->x = scale(px->x - pi->x, pt->y, px->y - pi->y); } pt->x += pi->x; pt->y += pi->y; if (flag){ if (w = winddir(pt) & ~3) return(radial(pi, point(pt->x, pt->y), w)); } return(pt); } /* * restore display window * * if (f) set max window size */ scaledown(f) { if (f || ogscale == 0){ copypt(point(0, 0), wind1); copypt(point(maxx, maxy), wind2); gscale = 0; } else { copypt(owind1, wind1); copypt(owind2, wind2); gscale = ogscale; } ogscale = 0; } /* * set window and display scale factor */ setscale() { DL1 p1, p2; REG INT dx, dy, i; DL p; markarea(p1, p2); dx = abs(p2->x - p1->x); dy = abs(p2->y - p1->y); if (dx == 0 || dy == 0) error("empty window"); if (ogscale == 0){ copypt(wind1, owind1); copypt(wind2, owind2); ogscale = gscale; } for(i = 0; dx <= (maxx >> 1); i++) dx = dx << 1; gscale = i; for (i = 0; dy <= (maxy >> 1); i++) dy = dy << 1; if (i > gscale) i = gscale; if (i > MAXG) i = MAXG; gscale = i; p = midpt(p1, p2); dx = maxx >> (i+1); dy = maxy >> (i+1); copypt(offset(p, -dx, -dy), wind1); copypt(offset(p, dx, dy), wind2); windmv(0, 0); } /* * move display window */ mvwind() { DL1 p1, p2; must(cursor(p1)); wchar(p1, '+'); must(cursor(p2)); windmv(p1->x - p2->x, p1->y - p2->y); } /* * return relationship of point p to display window * * +1 if to left, +2 if to right, * +4 if below, +8 if above. */ winddir(p) REG DL p; { return(((p->x < wind1->x)? 001 : ((p->x >= wind2->x)? 002 : 0)) + ((p->y < wind1->y)? 004 : ((p->y >= wind2->y)? 010 : 0))); } /* * move window distance dx, dy * modify distance to make sure there is a drawing surface * behind all parts of the screen. Also make offset * a multiple of MAXG so cursor rounding is to grid point. */ windmv(dx, dy) int dx, dy; { REG INT p, d; p = ((wind1->x + wind2->x) / 2) + dx; d = maxx >> (gscale + 1); if (p < d) p = d; if ((maxx - p) < d) p = maxx - d; p = (p - d) & ~MASKG; wind1->x = p; wind2->x = p + (2 * d); p = ((wind1->y + wind2->y) / 2) + dy; d = maxy >> (gscale + 1); if (p < d) p = d; if ((maxy - p) < d) p = maxy - d; p = (p - d) & ~MASKG; wind1->y = p; wind2->y = p + (2 * d); }