xref: /plan9-contrib/sys/src/cmd/plot/libplot/machdep.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include "mplot.h"
2 Bitmap *offscreen=&screen;
3 /*
4  * Clear the window from x0, y0 to x1, y1 (inclusive) to color c
5  */
6 void m_clrwin(int x0, int y0, int x1, int y1, int c){
7 	int y, hgt;
8 	x1++;
9 	y1++;
10 	if(c<=0)
11 		bitblt(offscreen, Pt(x0, y0), offscreen, Rect(x0, y0, x1, y1), Zero);
12 	else if(c>=(2<<screen.ldepth)-1)
13 		bitblt(offscreen, Pt(x0, y0), offscreen, Rect(x0, y0, x1, y1), F);
14 	else{
15 		segment(offscreen, Pt(x0, y0), Pt(x1, y0), c, S);
16 		for(y=y0+1,hgt=1;y<y1;y+=hgt,hgt*=2){
17 			if(y+hgt>y1) hgt=y1-y;
18 			bitblt(offscreen, Pt(x0, y), offscreen, Rect(x0, y0, x1, y0+hgt), S);
19 		}
20 	}
21 }
22 /*
23  * Draw text between pointers p and q with first character centered at x, y.
24  * Use color c.  Centered if cen is non-zero, right-justified if right is non-zero.
25  * Returns the y coordinate for any following line of text.
26  * Bug: color is ignored.
27  */
28 int m_text(int x, int y, char *p, char *q, int c, int cen, int right){
29 	Point tsize;
30 	USED(c);
31 	*q='\0';
32 	tsize=strsize(font, p);
33 	if(cen) x -= tsize.x/2;
34 	else if(right) x -= tsize.x;
35 	string(offscreen, Pt(x, y-tsize.y/2), font, p, S|D);
36 	return y+tsize.y;
37 }
38 /*
39  * Draw the vector from x0, y0 to x1, y1 in color c.
40  * Clipped by caller
41  */
42 void m_vector(int x0, int y0, int x1, int y1, int c){
43 	if(c<0) c=0;
44 	if(c>(1<<(1<<screen.ldepth))-1) c=(2<<screen.ldepth)-1;
45 	segment(offscreen, Pt(x0, y0), Pt(x1, y1), c, S);
46 }
47 Rectangle scr;
48 int scrset=0;
49 char *scanint(char *s, int *n){
50 	while(*s<'0' || '9'<*s){
51 		if(*s=='\0'){
52 			fprint(2, "plot: bad -Wxmin,ymin,xmax,ymax\n");
53 			exits("bad arg");
54 		}
55 		s++;
56 	}
57 	*n=0;
58 	while('0'<=*s && *s<='9'){
59 		*n=*n*10+*s-'0';
60 		s++;
61 	}
62 	return s;
63 }
64 void setwindow(char *s){
65 	s=scanint(s, &scr.min.x);
66 	s=scanint(s, &scr.min.y);
67 	s=scanint(s, &scr.max.x);
68 	scanint(s, &scr.max.y);
69 	scrset=1;
70 }
71 Rectangle getscr(void){
72 	int fd;
73 	char buf[12*5];
74 	fd=open("/dev/screen", OREAD);
75 	if(fd==-1) fd=open("/mnt/term/dev/screen", OREAD);
76 	if(fd==-1) return Rect(0,0,1024,1024);
77 	if(read(fd, buf, sizeof buf)!=sizeof buf){
78 		fprint(2, "Can't read /dev/screen: %r\n");
79 		exits("screen read");
80 	}
81 	return Rect(atoi(buf+12), atoi(buf+24), atoi(buf+36), atoi(buf+48));
82 }
83 char *rdenv(char *name){
84 	char *v;
85 	int fd, size;
86 	fd=open(name, OREAD);
87 	if(fd<0) return 0;
88 	size=seek(fd, 0, 2);
89 	v=malloc(size+1);
90 	if(v==0){
91 		fprint(2, "Can't malloc: %r\n");
92 		exits("no mem");
93 	}
94 	seek(fd, 0, 0);
95 	read(fd, v, size);
96 	v[size]=0;
97 	close(fd);
98 	return v;
99 }
100 void winit(void (*errfun)(char *), char *font, char *label, Rectangle r){
101 	char *srv, *mntsrv;
102 	char spec[100];
103 	int srvfd, cons, pid;
104 	switch(rfork(RFFDG|RFPROC|RFNAMEG|RFENVG|RFNOTEG|RFNOWAIT)){
105 	case -1:
106 		fprint(2, "Can't fork: %r\n");
107 		exits("no fork");
108 	case 0:
109 		break;
110 	default:
111 		exits(0);
112 	}
113 	srv=rdenv("/env/8½srv");
114 	if(srv==0){
115 		free(srv);
116 		mntsrv=rdenv("/mnt/term/env/8½srv");
117 		srv=malloc(strlen(mntsrv)+10);
118 		sprint(srv, "/mnt/term%s", mntsrv);
119 		free(mntsrv);
120 		pid=0;		/* 8½srv can't send notes to remote processes! */
121 	}
122 	else pid=getpid();
123 	srvfd=open(srv, ORDWR);
124 	free(srv);
125 	if(srvfd==-1){
126 		fprint(2, "Can't open %s: %r\n", srv);
127 		exits("no srv");
128 	}
129 	sprint(spec, "N%d,%d,%d,%d,%d\n", pid, r.min.x, r.min.y, r.max.x, r.max.y);
130 	if(mount(srvfd, "/mnt/8½", 0, spec)==-1){
131 		fprint(2, "Can't mount: %r\n");
132 		exits("no mount");
133 	}
134 	close(srvfd);
135 	bind("/mnt/8½", "/dev", MBEFORE);
136 	cons=open("/dev/cons", OREAD);
137 	if(cons==-1){
138 	NoCons:
139 		fprint(2, "Can't open /dev/cons: %r");
140 		exits("no cons");
141 	}
142 	dup(cons, 0);
143 	close(cons);
144 	cons=open("/dev/cons", OWRITE);
145 	if(cons==-1) goto NoCons;
146 	dup(cons, 1);
147 	dup(cons, 2);
148 	close(cons);
149 	binit(errfun, font, label);
150 }
151 /*
152  * Startup initialization
153  */
154 void m_initialize(char *s){
155 	static int first=1;
156 	int dx, dy;
157 	USED(s);
158 	if(first){
159 		if(!scrset){
160 			scr=getscr();
161 			scr.min=div(sub(add(scr.min, scr.max), Pt(520, 520)), 2);
162 			scr.max=add(scr.min, Pt(520, 520));
163 		}
164 		winit(0,0,0,scr);
165 		clipminx=mapminx=screen.r.min.x+4;
166 		clipminy=mapminy=screen.r.min.y+4;
167 		clipmaxx=mapmaxx=screen.r.max.x-5;
168 		clipmaxy=mapmaxy=screen.r.max.y-5;
169 		dx=clipmaxx-clipminx;
170 		dy=clipmaxy-clipminy;
171 		if(dx>dy){
172 			mapminx+=(dx-dy)/2;
173 			mapmaxx=mapminx+dy;
174 		}
175 		else{
176 			mapminy+=(dy-dx)/2;
177 			mapmaxy=mapminy+dx;
178 		}
179 		first=0;
180 	}
181 }
182 /*
183  * Clean up when finished
184  */
185 void m_finish(void){
186 	m_swapbuf();
187 }
188 void m_swapbuf(void){
189 	if(offscreen!=&screen)
190 		bitblt(&screen, offscreen->r.min, offscreen, offscreen->r, S);
191 	bflush();
192 }
193 void m_dblbuf(void){
194 	if(offscreen==&screen){
195 		offscreen=balloc(inset(screen.r, 4), screen.ldepth);
196 		if(offscreen==0){
197 			fprintf(stderr, "Can't double buffer\n");
198 			offscreen=&screen;
199 		}
200 	}
201 }
202