1 #include "mplot.h" 2 Image *offscreen; 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 draw(offscreen, Rect(x0, y0, x1+1, y1+1), getcolor(c), nil, ZP); 8 } 9 /* 10 * Draw text between pointers p and q with first character centered at x, y. 11 * Use color c. Centered if cen is non-zero, right-justified if right is non-zero. 12 * Returns the y coordinate for any following line of text. 13 */ 14 int m_text(int x, int y, char *p, char *q, int c, int cen, int right){ 15 Point tsize; 16 USED(c); 17 tsize=stringsize(font, p); 18 if(cen) x -= tsize.x/2; 19 else if(right) x -= tsize.x; 20 stringn(offscreen, Pt(x, y-tsize.y/2), getcolor(c), ZP, font, p, q-p); 21 return y+tsize.y; 22 } 23 /* 24 * Draw the vector from x0, y0 to x1, y1 in color c. 25 * Clipped by caller 26 */ 27 void m_vector(int x0, int y0, int x1, int y1, int c){ 28 line(offscreen, Pt(x0, y0), Pt(x1, y1), Endsquare, Endsquare, 0, getcolor(c), ZP); 29 } 30 char *scanint(char *s, int *n){ 31 while(*s<'0' || '9'<*s){ 32 if(*s=='\0'){ 33 fprint(2, "plot: bad -Wxmin,ymin,xmax,ymax\n"); 34 exits("bad arg"); 35 } 36 s++; 37 } 38 *n=0; 39 while('0'<=*s && *s<='9'){ 40 *n=*n*10+*s-'0'; 41 s++; 42 } 43 return s; 44 } 45 char *rdenv(char *name){ 46 char *v; 47 int fd, size; 48 fd=open(name, OREAD); 49 if(fd<0) return 0; 50 size=seek(fd, 0, 2); 51 v=malloc(size+1); 52 if(v==0){ 53 fprint(2, "Can't malloc: %r\n"); 54 exits("no mem"); 55 } 56 seek(fd, 0, 0); 57 read(fd, v, size); 58 v[size]=0; 59 close(fd); 60 return v; 61 } 62 /* 63 * Startup initialization 64 */ 65 void m_initialize(char *s){ 66 static int first=1; 67 int dx, dy; 68 USED(s); 69 if(first){ 70 initdraw(0,0,"plot"); 71 einit(Emouse); 72 clipminx=mapminx=screen->r.min.x+4; 73 clipminy=mapminy=screen->r.min.y+4; 74 clipmaxx=mapmaxx=screen->r.max.x-5; 75 clipmaxy=mapmaxy=screen->r.max.y-5; 76 dx=clipmaxx-clipminx; 77 dy=clipmaxy-clipminy; 78 if(dx>dy){ 79 mapminx+=(dx-dy)/2; 80 mapmaxx=mapminx+dy; 81 } 82 else{ 83 mapminy+=(dy-dx)/2; 84 mapmaxy=mapminy+dx; 85 } 86 first=0; 87 offscreen = screen; 88 } 89 } 90 /* 91 * Clean up when finished 92 */ 93 void m_finish(void){ 94 m_swapbuf(); 95 } 96 void m_swapbuf(void){ 97 if(offscreen!=screen) 98 draw(screen, offscreen->r, offscreen, nil, offscreen->r.min); 99 flushimage(display, 1); 100 } 101 void m_dblbuf(void){ 102 if(offscreen==screen){ 103 offscreen=allocimage(display, insetrect(screen->r, 4), screen->chan, 0, -1); 104 if(offscreen==0){ 105 fprintf(stderr, "Can't double buffer\n"); 106 offscreen=screen; 107 } 108 } 109 } 110 /* Assume colormap entry because 111 * Use cache to avoid repeated allocation. 112 */ 113 struct{ 114 int v; 115 Image *i; 116 }icache[32]; 117 118 Image* 119 getcolor(int v) 120 { 121 Image *i; 122 int j; 123 124 for(j=0; j<nelem(icache); j++) 125 if(icache[j].v==v && icache[j].i!=nil) 126 return icache[j].i; 127 128 i = allocimage(display, Rect(0, 0, 1, 1), RGB24, 1, v); 129 if(i == nil){ 130 fprint(2, "plot: can't allocate image for color: %r\n"); 131 exits("allocimage"); 132 } 133 for(j=0; j<nelem(icache); j++) 134 if(icache[j].i == nil){ 135 icache[j].v = v; 136 icache[j].i = i; 137 break; 138 } 139 140 return i; 141 } 142