| #include "mplot.h" | 
 | int mapminx, mapminy, mapmaxx, mapmaxy; | 
 | Image *offscreen; | 
 | /* | 
 |  * 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){ | 
 | 	draw(offscreen, 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){ | 
 | 	Point tsize; | 
 | 	USED(c); | 
 | 	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); | 
 | 	return y+tsize.y; | 
 | } | 
 | /* | 
 |  * 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){ | 
 | 	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; | 
 | } | 
 | /* | 
 |  * Startup initialization | 
 |  */ | 
 | void m_initialize(char *s){ | 
 | 	static int first=1; | 
 | 	int dx, dy; | 
 | 	USED(s); | 
 | 	if(first){ | 
 | 		if(initdraw(0,0,"plot") < 0) | 
 | 			sysfatal("plot: can't open display: %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; | 
 | 	} | 
 | } | 
 | /* | 
 |  * Clean up when finished | 
 |  */ | 
 | void m_finish(void){ | 
 | 	m_swapbuf(); | 
 | } | 
 | void m_swapbuf(void){ | 
 | 	if(offscreen!=screen) | 
 | 		draw(screen, offscreen->r, 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; | 
 | 		} | 
 | 	} | 
 | } | 
 | /* Assume colormap entry because | 
 |  * Use cache to avoid repeated allocation. | 
 |  */ | 
 | struct{ | 
 | 	int		v; | 
 | 	Image	*i; | 
 | }icache[32]; | 
 |  | 
 | Image* | 
 | getcolor(int v) | 
 | { | 
 | 	Image *i; | 
 | 	int j; | 
 |  | 
 | 	for(j=0; j<nelem(icache); j++) | 
 | 		if(icache[j].v==v && icache[j].i!=nil) | 
 | 			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"); | 
 | 	} | 
 | 	for(j=0; j<nelem(icache); j++) | 
 | 		if(icache[j].i == nil){ | 
 | 			icache[j].v = v; | 
 | 			icache[j].i = i; | 
 | 			break; | 
 | 		} | 
 |  | 
 | 	return i; | 
 | } |