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