#include "mplot.h"
void dpoint(double x, double y){
- draw(screen, Rect(SCX(x), SCY(y), SCX(x)+1, SCY(y)+1), getcolor(e1->foregr),
- nil, ZP);
+ m_dpt(x, y);
move(x, y);
}
edges=(Edge *)malloc(nvert*sizeof(Edge));
if(edges==0){
NoSpace:
- fprintf(stderr, "polygon: no space\n");
- exits("malloc failed");
+ sysfatal("polygon: no space");
}
ylist=(Edge **)malloc(Dy(screen->r)*sizeof(Edge *));
if(ylist==0) goto NoSpace;
#include "mplot.h"
Image *offscreen;
+static int buffer;
+
+static Point
+xlp(Point p)
+{
+ p.x += screen->r.min.x + 4 - offscreen->r.min.x;
+ p.y += screen->r.min.y + 4 - offscreen->r.min.y;
+ return p;
+}
+
+static Rectangle
+xlr(Rectangle r)
+{
+ int dx, dy;
+
+ dx = screen->r.min.x + 4 - offscreen->r.min.x;
+ dy = screen->r.min.y + 4 - offscreen->r.min.y;
+ r.min.x += dx;
+ r.min.y += dy;
+ r.max.x += dx;
+ r.max.y += dy;
+ return r;
+}
+
/*
* Clear the window from x0, y0 to x1, y1 (inclusive) to color c
*/
-void m_clrwin(int x0, int y0, int x1, int y1, int c){
+void
+m_clrwin(int x0, int y0, int x1, int y1, int c)
+{
draw(offscreen, Rect(x0, y0, x1+1, y1+1), getcolor(c), nil, ZP);
+ if(offscreen != screen && !buffer)
+ draw(screen, xlr(Rect(x0, y0, x1+1, y1+1)), getcolor(c), nil, ZP);
}
/*
* Draw text between pointers p and q with first character centered at x, y.
* Use color c. Centered if cen is non-zero, right-justified if right is non-zero.
* Returns the y coordinate for any following line of text.
*/
-int m_text(int x, int y, char *p, char *q, int c, int cen, int right){
+int
+m_text(int x, int y, char *p, char *q, int c, int cen, int right)
+{
Point tsize;
- USED(c);
- tsize=stringsize(font, p);
- if(cen) x -= tsize.x/2;
- else if(right) x -= tsize.x;
+
+ tsize = stringsize(font, p);
+ if(cen)
+ x -= tsize.x/2;
+ else if(right)
+ x -= tsize.x;
stringn(offscreen, Pt(x, y-tsize.y/2), getcolor(c), ZP, font, p, q-p);
+ if(offscreen != screen && !buffer)
+ stringn(screen, xlp(Pt(x, y-tsize.y/2)), getcolor(c), ZP, font, p, q-p);
return y+tsize.y;
}
+/*
+ * draw point x, y
+ */
+void
+m_dpt(double x, double y)
+{
+ Image *c;
+
+ c = getcolor(e1->foregr);
+ draw(offscreen, Rect(SCX(x), SCY(y), SCX(x)+1, SCY(y)+1), c, nil, ZP);
+ if(offscreen != screen && !buffer)
+ draw(screen, xlr(Rect(SCX(x), SCY(y), SCX(x)+1, SCY(y)+1)), c, nil, ZP);
+}
+
/*
* Draw the vector from x0, y0 to x1, y1 in color c.
* Clipped by caller
*/
-void m_vector(int x0, int y0, int x1, int y1, int c){
+void
+m_vector(int x0, int y0, int x1, int y1, int c)
+{
line(offscreen, Pt(x0, y0), Pt(x1, y1), Endsquare, Endsquare, 0, getcolor(c), ZP);
-}
-char *scanint(char *s, int *n){
- while(*s<'0' || '9'<*s){
- if(*s=='\0'){
- fprint(2, "plot: bad -Wxmin,ymin,xmax,ymax\n");
- exits("bad arg");
- }
- s++;
- }
- *n=0;
- while('0'<=*s && *s<='9'){
- *n=*n*10+*s-'0';
- s++;
- }
- return s;
-}
-char *rdenv(char *name){
- char *v;
- int fd, size;
- fd=open(name, OREAD);
- if(fd<0) return 0;
- size=seek(fd, 0, 2);
- v=malloc(size+1);
- if(v==0){
- fprint(2, "Can't malloc: %r\n");
- exits("no mem");
- }
- seek(fd, 0, 0);
- read(fd, v, size);
- v[size]=0;
- close(fd);
- return v;
+ if(offscreen != screen && !buffer)
+ line(screen, xlp(Pt(x0, y0)), xlp(Pt(x1, y1)), Endsquare, Endsquare, 0, getcolor(c), ZP);
}
/*
* Startup initialization
*/
-void m_initialize(char *s){
- static int first=1;
+void m_initialize(char*)
+{
+ static int once;
int dx, dy;
- USED(s);
- if(first){
- if(initdraw(0,0,"plot") < 0)
- sysfatal("initdraw: %r");
- einit(Emouse);
- clipminx=mapminx=screen->r.min.x+4;
- clipminy=mapminy=screen->r.min.y+4;
- clipmaxx=mapmaxx=screen->r.max.x-5;
- clipmaxy=mapmaxy=screen->r.max.y-5;
- dx=clipmaxx-clipminx;
- dy=clipmaxy-clipminy;
- if(dx>dy){
- mapminx+=(dx-dy)/2;
- mapmaxx=mapminx+dy;
- }
- else{
- mapminy+=(dy-dx)/2;
- mapmaxy=mapminy+dx;
- }
- first=0;
- offscreen = screen;
+
+ if(once)
+ return;
+ once = 1;
+
+ if(initdraw(nil, nil, "plot") < 0)
+ sysfatal("initdraw: %r");
+///// einit(Emouse);
+ offscreen = allocimage(display, insetrect(screen->r, 4), screen->chan, 0, -1);
+ if(offscreen == nil)
+ sysfatal("Can't double buffer\n");
+ clipminx = mapminx = screen->r.min.x+4;
+ clipminy = mapminy = screen->r.min.y+4;
+ clipmaxx = mapmaxx = screen->r.max.x-5;
+ clipmaxy = mapmaxy = screen->r.max.y-5;
+ dx = clipmaxx-clipminx;
+ dy = clipmaxy-clipminy;
+ if(dx>dy){
+ mapminx += (dx-dy)/2;
+ mapmaxx = mapminx+dy;
+ }
+ else{
+ mapminy += (dy-dx)/2;
+ mapmaxy = mapminy+dx;
}
}
/*
* Clean up when finished
*/
-void m_finish(void){
+void m_finish(void)
+{
m_swapbuf();
}
-void m_swapbuf(void){
- if(offscreen!=screen)
- draw(screen, offscreen->r, offscreen, nil, offscreen->r.min);
+void m_swapbuf(void)
+{
+ draw(screen, insetrect(screen->r, 4), offscreen, nil, offscreen->r.min);
flushimage(display, 1);
}
-void m_dblbuf(void){
- if(offscreen==screen){
- offscreen=allocimage(display, insetrect(screen->r, 4), screen->chan, 0, -1);
- if(offscreen==0){
- fprintf(stderr, "Can't double buffer\n");
- offscreen=screen;
- }
- }
+void m_dblbuf(void)
+{
+ buffer = 1;
}
-/* Assume colormap entry because
+
+/*
* Use cache to avoid repeated allocation.
*/
struct{
return icache[j].i;
i = allocimage(display, Rect(0, 0, 1, 1), RGB24, 1, v);
- if(i == nil){
- fprint(2, "plot: can't allocate image for color: %r\n");
- exits("allocimage");
- }
+ if(i == nil)
+ sysfatal("plot: can't allocate image for color: %r");
for(j=0; j<nelem(icache); j++)
if(icache[j].i == nil){
icache[j].v = v;
icache[j].i = i;
break;
}
-
+if(j == nelem(icache))sysfatal("icache: too small");
return i;
}
#include <u.h>
#include <libc.h>
-#include <stdio.h>
+//#include <stdio.h>
#include <draw.h>
#include <event.h>
#define SCX(A) ((((A) - e1->xmin)*e1->scalex + e1->left)+.5)
void m_finish(void);
void m_initialize(char *);
int m_text(int, int, char *, char *, int, int, int);
+void m_dpt(double, double);
void m_vector(int, int, int, int, int);
void m_swapbuf(void);
void m_dblbuf(void);
#include "mplot.h"
void ppause(void){
char aa[4];
- fflush(stdout);
read(0, aa, 4);
erase();
}
#include "mplot.h"
void
pprompt(void){
- fprintf(stderr, ":");
+ fprint(2, ":");
}
#include <bio.h>
#include "plot.h"
#include <draw.h>
-#include <event.h>
+#include <thread.h>
+#include <mouse.h>
+#include <keyboard.h>
void define(char*);
void call(char*);
#define NFSTACK 50
struct fstack{
+ char name[128];
int peekc;
int lineno;
char *corebuf;
int cnt[NPTS]; /* control-polygon vertex counts */
double *pts[NPTS]; /* control-polygon vertex pointers */
-void eresized(int new){
- if(new && getwindow(display, Refnone) < 0){
- fprint(2, "Can't reattach to window: %r\n");
- exits("resize");
+extern void m_swapbuf(void); /* reaching into implementation. ick. */
+extern Image *offscreen;
+
+void
+resize(Point p)
+{
+ int fd;
+
+ fd = open("/dev/wctl", OWRITE);
+ if(fd >= 0){
+ fprint(fd, "resize -dx %d -dy %d", p.x+4*2, p.y+4*2);
+ close(fd);
}
}
+
+void
+resizeto(Point p)
+{
+ Point s;
+
+ s = (Point){Dx(screen->r), Dy(screen->r)};
+ if(eqpt(p, s))
+ return;
+ resize(p);
+}
+
+void
+eresized(int new)
+{
+ if(new && getwindow(display, Refnone) < 0)
+ sysfatal("plot: can't reattach to window: %r\n");
+// resizeto((Point){Dx(offscreen->r)+4, Dy(offscreen->r)+4});
+ m_swapbuf();
+}
+
char *items[]={
"exit",
0
};
Menu menu={items};
+
+void
+mouseproc(void*)
+{
+ void *v;
+ Rune r;
+ Alt alts[4];
+ Keyboardctl *k;
+ Mousectl *m;
+ Mouse mc;
+ enum{Amouse, Akbd, Aresize, Aend};
+
+ m = initmouse(nil, screen);
+ k = initkeyboard(nil);
+
+ memset(alts, 0, sizeof alts);
+ alts[Amouse].c = m->c;
+ alts[Amouse].v = &mc;
+ alts[Amouse].op = CHANRCV;
+
+ alts[Akbd].c = k->c;
+ alts[Akbd].v = &r;
+ alts[Akbd].op = CHANRCV;
+
+ alts[Aresize].c = m->resizec;
+ alts[Aresize].v = &v;
+ alts[Aresize].op = CHANRCV;
+
+ alts[Aend].op = CHANEND;
+
+ for(;;)
+ switch(alt(alts)){
+ default:
+ sysfatal("mouse!");
+ case Amouse:
+ if(mc.buttons & 4) {
+ if(menuhit(3, m, &menu, nil) == 0)
+ threadexitsall("");
+ }
+ break;
+ case Akbd:
+ switch(r){
+ case 'q':
+ case 0x7f:
+ case 0x04:
+ threadexitsall("");
+ }
+ break;
+ case Aresize:
+ eresized(1);
+ ;
+ }
+}
+
void
-main(int arc, char *arv[]){
+threadmain(int arc, char *arv[]){
char *ap;
Biobuf *bp;
int fd;
int i;
int dflag;
char *oflag;
- Mouse m;
+
bp = 0;
fd = dup(0, -1); /* because openpl will close 0! */
dflag=0;
oflag="";
+ argv0 = arv[0];
for(i=1;i!=arc;i++) if(arv[i][0]=='-') switch(arv[i][1]){
case 'd': dflag=1; break;
case 'o': oflag=arv[i]+2; break;
case 's': fd=server(); break;
}
openpl(oflag);
- if(dflag) doublebuffer();
+ proccreate(mouseproc, nil, 32*1024);
+ if(dflag)
+ doublebuffer();
for (; arc > 1; arc--, arv++) {
if (arv[1][0] == '-') {
ap = arv[1];
}
closepl();
flushimage(display, 1);
- for(;;){
- m=emouse();
- if(m.buttons&4 && emenuhit(3, &m, &menu)==0) exits(0);
- }
+ for(;;)
+ sleep(1000);
}
int isalpha(int c)
{
c=nextc();
}while(strchr(" \t\n", c) || c!='.' && c!='+' && c!='-' && ispunct(c));
fsp->peekc=c;
- if(!numstring()){
- fprint(2, "line %d: number expected\n", fsp->lineno);
- exits("input error");
- }
+ if(!numstring())
+ sysfatal("%s:%d: number expected\n", fsp->name, fsp->lineno);
x[i]=atof(argstr)*fsp->scale;
}
}
c=nextc();
if(c==r){
if(*cntp){
- if(*cntp&1){
- fprint(2, "line %d: phase error\n",
- fsp->lineno);
- exits("bad input");
- }
+ if(*cntp&1)
+ sysfatal("%s:%d: phase error", fsp->name, fsp->lineno);
*cntp/=2;
- if(ptsp==&pts[NPTS]){
- fprint(2, "line %d: out of polygons\n",
- fsp->lineno);
- exits("exceeded limit");
- }
+ if(ptsp==&pts[NPTS])
+ sysfatal("%s:%d: out of polygons", fsp->name, fsp->lineno);
*++ptsp=xp;
*++cntp=0;
}
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
fsp->peekc=c;
- if(!numstring()){
- fprint(2, "line %d: expected number\n", fsp->lineno);
- exits("bad input");
- }
- if(xp==&x[NX]){
- fprint(2, "line %d: out of space\n", fsp->lineno);
- exits("exceeded limit");
- }
+ if(!numstring())
+ sysfatal("%s:%d: expected number", fsp->name, fsp->lineno);
+ if(xp==&x[NX])
+ sysfatal("%s:%d: out of space", fsp->name, fsp->lineno);
*xp++=atof(argstr);
++*cntp;
break;
for(pplots=plots;pplots->cc;pplots++)
if(strncmp(argstr, pplots->cc, pplots->numc)==0)
break;
- if(pplots->cc==0){
- fprint(2, "line %d, %s unknown\n", fsp->lineno,
- argstr);
- exits("bad command");
- }
+ if(pplots->cc==0)
+ sysfatal("%s:%d: %s unknown", fsp->name, fsp->lineno, argstr);
}
else{
fsp->peekc=c;
}
- if(!pplots){
- fprint(2, "line %d, no command!\n", fsp->lineno);
- exits("no command");
- }
+ if(!pplots)
+ sysfatal("%s:%d: no command\n", fsp->name, fsp->lineno);
switch(pplots-plots){
case ARC: numargs(7); rarc(x[0],x[1],x[2],x[3],x[4],x[5],x[6]); break;
case BOX: numargs(4); box(x[0], x[1], x[2], x[3]); break;
case TEXT: strarg(); text(argstr); pplots=0; break;
case VEC: numargs(2); vec(x[0], x[1]); break;
default:
- fprint(2, "plot: missing case %ld\n", pplots-plots);
- exits("internal error");
+ sysfatal("%s:%d: plot: missing case %ld\n", fsp->name, fsp->lineno, pplots-plots);
}
}
return 1;
int curly = 0;
ap = a;
while(isalpha(*ap))ap++;
- if(ap == a){
- fprint(2,"no name with define\n");
- exits("define");
- }
+ if(ap == a)
+ sysfatal("plot: no name with define\n");
i = ap - a;
if(names+i+1 > enames){
names = malloc((unsigned)512);
fptr->stash = nstash;
while(*ap != '{')
if(*ap == '\n'){
- if((ap=Brdline(fsp->fd, '\n'))==0){
- fprint(2,"unexpected end of file\n");
- exits("eof");
- }
+ if((ap=Brdline(fsp->fd, '\n'))==0)
+ sysfatal("plot: unexpected eof");
}
else ap++;
while((j=Bgetc(fsp->fd))!= Beof){
free(bstash);
size += 1024;
bstash = realloc(bstash,size);
+ if(bstash == nil)
+ sysfatal("plot: realloc: %r");
estash = bstash+size;
}
}
*nstash++ = '\0';
- if(fptr++ >= &flibr[MAXL]){
- fprint(2,"Too many objects\n");
- exits("too many objects");
- }
+ if(fptr++ >= &flibr[MAXL])
+ sysfatal("too many objects");
}
void call(char *a){
char *ap;
if (!(strcmp(a, f->name)))
break;
}
- if(f == fptr){
- fprint(2, "object %s not defined\n",a);
- exits("undefined");
- }
+ if(f == fptr)
+ sysfatal("plot: object %s not defined",a);
*ap = sav;
while (isspace(*ap) || *ap == ',')
ap++;
if (*ap != '\0')
SC = atof(ap);
else SC = 1.;
- if(++fsp==&fstack[NFSTACK]){
- fprint(2, "input stack overflow\n");
- exits("blew stack");
- }
+ if(++fsp==&fstack[NFSTACK])
+ sysfatal("plot: input stack overflow");
+ snprint(fsp->name, sizeof fsp->name, "call %s", f->name);
fsp->peekc=Beof;
fsp->lineno=1;
fsp->corebuf=f->stash;
void include(char *a){
Biobuf *fd;
fd=Bopen(a, OREAD);
- if(fd==0){
- perror(a);
- exits("can't include");
- }
- if(++fsp==&fstack[NFSTACK]){
- fprint(2, "input stack overflow\n");
- exits("blew stack");
- }
+ if(fd==0)
+ sysfatal("plot: cant include %s: %r", a);
+ if(++fsp==&fstack[NFSTACK])
+ sysfatal("plot: input stack overflow");
+ snprint(fsp->name, sizeof fsp->name, "%s", a);
fsp->peekc=Beof;
fsp->lineno=1;
fsp->corebuf=0;