123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575 |
- #include <u.h>
- #include <libc.h>
- #include <draw.h>
- #include <cursor.h>
- #include <event.h>
- #include <bio.h>
- #include "proof.h"
- int res;
- int hpos;
- int vpos;
- int DIV = 11;
- Point offset;
- Point xyoffset = { 0,0 };
- Rectangle view[MAXVIEW];
- Rectangle bound[MAXVIEW]; /* extreme points */
- int nview = 1;
- int lastp; /* last page number we were on */
- #define NPAGENUMS 200
- struct pagenum {
- int num;
- long adr;
- } pagenums[NPAGENUMS];
- int npagenums;
- int curfont, cursize;
- char *getcmdstr(void);
- static void initpage(void);
- static void view_setup(int);
- static Point scale(Point);
- static void clearview(Rectangle);
- static int addpage(int);
- static void spline(Image *, int, Point *);
- static int skipto(int, int);
- static void wiggly(int);
- static void devcntrl(void);
- static void eatline(void);
- static int getn(void);
- static int botpage(int);
- static void getstr(char *);
- static void getutf(char *);
- #define Do screen->r.min
- #define Dc screen->r.max
- /* declarations and definitions of font stuff are in font.c and main.c */
- static void
- initpage(void)
- {
- int i;
- view_setup(nview);
- for (i = 0; i < nview-1; i++)
- draw(screen, view[i], screen, nil, view[i+1].min);
- clearview(view[nview-1]);
- offset = view[nview-1].min;
- vpos = 0;
- }
- static void
- view_setup(int n)
- {
- int i, j, v, dx, dy, r, c;
- switch (n) {
- case 1: r = 1; c = 1; break;
- case 2: r = 1; c = 2; break;
- case 3: r = 1; c = 3; break;
- case 4: r = 2; c = 2; break;
- case 5: case 6: r = 2; c = 3; break;
- case 7: case 8: case 9: r = 3; c = 3; break;
- default: r = (n+2)/3; c = 3; break; /* finking out */
- }
- dx = (Dc.x - Do.x) / c;
- dy = (Dc.y - Do.y) / r;
- v = 0;
- for (i = 0; i < r && v < n; i++)
- for (j = 0; j < c && v < n; j++) {
- view[v] = screen->r;
- view[v].min.x = Do.x + j * dx;
- view[v].max.x = Do.x + (j+1) * dx;
- view[v].min.y = Do.y + i * dy;
- view[v].max.y = Do.y + (i+1) * dy;
- v++;
- }
- }
- static void
- clearview(Rectangle r)
- {
- draw(screen, r, display->white, nil, r.min);
- }
- int resized;
- void eresized(int new)
- {
- /* this is called if we are resized */
- if(new && getwindow(display, Refnone) < 0)
- drawerror(display, "can't reattach to window");
- initpage();
- resized = 1;
- }
- static Point
- scale(Point p)
- {
- p.x /= DIV;
- p.y /= DIV;
- return addpt(xyoffset, addpt(offset,p));
- }
- static int
- addpage(int n)
- {
- int i;
- for (i = 0; i < npagenums; i++)
- if (n == pagenums[i].num)
- return i;
- if (npagenums < NPAGENUMS-1) {
- pagenums[npagenums].num = n;
- pagenums[npagenums].adr = offsetc();
- npagenums++;
- }
- return npagenums;
- }
- void
- readpage(void)
- {
- int c, i, a, alpha, phi;
- static int first = 0;
- int m, n, gonow = 1;
- Rune r[32], t;
- Point p,q,qq;
- offset = screen->clipr.min;
- esetcursor(&deadmouse);
- while (gonow)
- {
- c = getc();
- switch (c)
- {
- case -1:
- esetcursor(0);
- if (botpage(lastp+1)) {
- initpage();
- break;
- }
- exits(0);
- case 'p': /* new page */
- lastp = getn();
- addpage(lastp);
- if (first++ > 0) {
- esetcursor(0);
- botpage(lastp);
- esetcursor(&deadmouse);
- }
- initpage();
- break;
- case '\n': /* when input is text */
- case ' ':
- case 0: /* occasional noise creeps in */
- break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- /* two motion digits plus a character */
- hpos += (c-'0')*10 + getc()-'0';
- /* FALLS THROUGH */
- case 'c': /* single ascii character */
- r[0] = getrune();
- r[1] = 0;
- dochar(r);
- break;
- case 'C':
- for(i=0; ; i++){
- t = getrune();
- if(isspace(t))
- break;
- r[i] = t;
- }
- r[i] = 0;
- dochar(r);
- break;
- case 'N':
- r[0] = getn();
- r[1] = 0;
- dochar(r);
- break;
- case 'D': /* draw function */
- switch (getc())
- {
- case 'l': /* draw a line */
- n = getn();
- m = getn();
- p = Pt(hpos,vpos);
- q = addpt(p, Pt(n,m));
- hpos += n;
- vpos += m;
- line(screen, scale(p), scale(q), 0, 0, 0, display->black, ZP);
- break;
- case 'c': /* circle */
- /*nop*/
- m = getn()/2;
- p = Pt(hpos+m,vpos);
- hpos += 2*m;
- ellipse(screen, scale(p), m/DIV, m/DIV, 0, display->black, ZP);
- /* p=currentpt; p.x+=dmap(m/2);circle bp,p,a,ONES,Mode*/
- break;
- case 'e': /* ellipse */
- /*nop*/
- m = getn()/2;
- n = getn()/2;
- p = Pt(hpos+m,vpos);
- hpos += 2*m;
- ellipse(screen, scale(p), m/DIV, n/DIV, 0, display->black, ZP);
- break;
- case 'a': /* arc */
- p = scale(Pt(hpos,vpos));
- n = getn();
- m = getn();
- hpos += n;
- vpos += m;
- q = scale(Pt(hpos,vpos));
- n = getn();
- m = getn();
- hpos += n;
- vpos += m;
- qq = scale(Pt(hpos,vpos));
- /*
- * tricky: convert from 3-point clockwise to
- * center, angle1, delta-angle counterclockwise.
- */
- a = hypot(qq.x-q.x, qq.y-q.y);
- phi = atan2(q.y-p.y, p.x-q.x)*180./PI;
- alpha = atan2(q.y-qq.y, qq.x-q.x)*180./PI - phi;
- if(alpha < 0)
- alpha += 360;
- arc(screen, q, a, a, 0, display->black, ZP, phi, alpha);
- break;
- case '~': /* wiggly line */
- wiggly(0);
- break;
- default:
- break;
- }
- eatline();
- break;
- case 's':
- n = getn(); /* ignore fractional sizes */
- if (cursize == n)
- break;
- cursize = n;
- if (cursize >= NFONT)
- cursize = NFONT-1;
- break;
- case 'f':
- curfont = getn();
- break;
- case 'H': /* absolute horizontal motion */
- hpos = getn();
- break;
- case 'h': /* relative horizontal motion */
- hpos += getn();
- break;
- case 'w': /* word space */
- break;
- case 'V':
- vpos = getn();
- break;
- case 'v':
- vpos += getn();
- break;
- case '#': /* comment */
- case 'n': /* end of line */
- eatline();
- break;
- case 'x': /* device control */
- devcntrl();
- break;
- default:
- fprint(2, "unknown input character %o %c at offset %lud\n", c, c, offsetc());
- exits("bad char");
- }
- }
- esetcursor(0);
- }
- static void
- spline(Image *b, int n, Point *pp)
- {
- long w, t1, t2, t3, fac=1000;
- int i, j, steps=10;
- Point p, q;
- for (i = n; i > 0; i--)
- pp[i] = pp[i-1];
- pp[n+1] = pp[n];
- n += 2;
- p = pp[0];
- for(i = 0; i < n-2; i++)
- {
- for(j = 0; j < steps; j++)
- {
- w = fac * j / steps;
- t1 = w * w / (2 * fac);
- w = w - fac/2;
- t2 = 3*fac/4 - w * w / fac;
- w = w - fac/2;
- t3 = w * w / (2*fac);
- q.x = (t1*pp[i+2].x + t2*pp[i+1].x +
- t3*pp[i].x + fac/2) / fac;
- q.y = (t1*pp[i+2].y + t2*pp[i+1].y +
- t3*pp[i].y + fac/2) / fac;
- line(b, p, q, 0, 0, 0, display->black, ZP);
- p = q;
- }
- }
- }
- /* Have to parse skipped pages, to find out what fonts are loaded. */
- static int
- skipto(int gotop, int curp)
- {
- char *p;
- int i;
- if (gotop == curp)
- return 1;
- for (i = 0; i < npagenums; i++)
- if (pagenums[i].num == gotop) {
- if (seekc(pagenums[i].adr) == Beof) {
- fprint(2, "can't rewind input\n");
- return 0;
- }
- return 1;
- }
- if (gotop <= curp) {
- restart:
- if (seekc(0) == Beof) {
- fprint(2, "can't rewind input\n");
- return 0;
- }
- }
- for(;;){
- p = rdlinec();
- if (p == 0) {
- if(gotop>curp){
- gotop = curp;
- goto restart;
- }
- return 0;
- } else if (*p == 'p') {
- lastp = curp = atoi(p+1);
- addpage(lastp); /* maybe 1 too high */
- if (curp>=gotop)
- return 1;
- }
- }
- }
- static void
- wiggly(int skip)
- {
- Point p[300];
- int c,i,n;
- for (n = 1; (c = getc()) != '\n' && c>=0; n++) {
- ungetc();
- p[n].x = getn();
- p[n].y = getn();
- }
- p[0] = Pt(hpos, vpos);
- for (i = 1; i < n; i++)
- p[i] = addpt(p[i],p[i-1]);
- hpos = p[n-1].x;
- vpos = p[n-1].y;
- for (i = 0; i < n; i++)
- p[i] = scale(p[i]);
- if (!skip)
- spline(screen,n,p);
- }
- static void
- devcntrl(void) /* interpret device control functions */
- {
- char str[80];
- int n;
- getstr(str);
- switch (str[0]) { /* crude for now */
- case 'i': /* initialize */
- break;
- case 'T': /* device name */
- getstr(devname);
- break;
- case 't': /* trailer */
- break;
- case 'p': /* pause -- can restart */
- break;
- case 's': /* stop */
- break;
- case 'r': /* resolution assumed when prepared */
- res=getn();
- DIV = floor(.5 + res/(100.0*mag));
- if (DIV < 1)
- DIV = 1;
- mag = res/(100.0*DIV); /* adjust mag according to DIV coarseness */
- break;
- case 'f': /* font used */
- n = getn();
- getstr(str);
- loadfontname(n, str);
- break;
- /* these don't belong here... */
- case 'H': /* char height */
- break;
- case 'S': /* slant */
- break;
- case 'X':
- break;
- }
- eatline();
- }
- int
- isspace(int c)
- {
- return c==' ' || c=='\t' || c=='\n';
- }
- static void
- getstr(char *is)
- {
- uchar *s = (uchar *) is;
- for (*s = getc(); isspace(*s); *s = getc())
- ;
- for (; !isspace(*s); *++s = getc())
- ;
- ungetc();
- *s = 0;
- }
- static void
- getutf(char *s) /* get next utf char, as bytes */
- {
- int c, i;
- for (i=0;;) {
- c = getc();
- if (c < 0)
- return;
- s[i++] = c;
- if (fullrune(s, i)) {
- s[i] = 0;
- return;
- }
- }
- }
- static void
- eatline(void)
- {
- int c;
- while ((c=getc()) != '\n' && c >= 0)
- ;
- }
- static int
- getn(void)
- {
- int n, c, sign;
- while (c = getc())
- if (!isspace(c))
- break;
- if(c == '-'){
- sign = -1;
- c = getc();
- }else
- sign = 1;
- for (n = 0; '0'<=c && c<='9'; c = getc())
- n = n*10 + c - '0';
- while (c == ' ')
- c = getc();
- ungetc();
- return(n*sign);
- }
- static int
- botpage(int np) /* called at bottom of page np-1 == top of page np */
- {
- char *p;
- int n;
- while (p = getcmdstr()) {
- if (*p == '\0')
- return 0;
- if (*p == 'q')
- exits(p);
- if (*p == 'c') /* nop */
- continue;
- if (*p == 'm') {
- mag = atof(p+1);
- if (mag <= .1 || mag >= 10)
- mag = DEFMAG;
- allfree(); /* zap fonts */
- DIV = floor(.5 + res/(100.0*mag));
- if (DIV < 1)
- DIV = 1;
- mag = res/(100.0*DIV);
- return skipto(np-1, np); /* reprint the page */
- }
- if (*p == 'x') {
- xyoffset.x += atoi(p+1)*100;
- skipto(np-1, np);
- return 1;
- }
- if (*p == 'y') {
- xyoffset.y += atoi(p+1)*100;
- skipto(np-1, np);
- return 1;
- }
- if (*p == '/') { /* divide into n pieces */
- nview = atoi(p+1);
- if (nview < 1)
- nview = 1;
- else if (nview > MAXVIEW)
- nview = MAXVIEW;
- return skipto(np-1, np);
- }
- if (*p == 'p') {
- if (p[1] == '\0'){ /* bare 'p' */
- if(skipto(np-1, np))
- return 1;
- continue;
- }
- p++;
- }
- if ('0'<=*p && *p<='9') {
- n = atoi(p);
- if(skipto(n, np))
- return 1;
- continue;
- }
- if (*p == '-' || *p == '+') {
- n = atoi(p);
- if (n == 0)
- n = *p == '-' ? -1 : 1;
- if(skipto(np - 1 + n, np))
- return 1;
- continue;
- }
- if (*p == 'd') {
- dbg = 1 - dbg;
- continue;
- }
- fprint(2, "illegal; try q, 17, +2, -1, p, m.7, /2, x1, y-.5 or return\n");
- }
- return 0;
- }
|