Blame


1 e2713e92 2004-04-24 devnull #include <u.h>
2 e2713e92 2004-04-24 devnull #include <libc.h>
3 e2713e92 2004-04-24 devnull #include <ctype.h>
4 e2713e92 2004-04-24 devnull #include <draw.h>
5 e2713e92 2004-04-24 devnull #include <event.h>
6 e2713e92 2004-04-24 devnull #include <cursor.h>
7 e2713e92 2004-04-24 devnull #include <stdio.h>
8 e2713e92 2004-04-24 devnull
9 e2713e92 2004-04-24 devnull #define Never 0xffffffff /* Maximum ulong */
10 e2713e92 2004-04-24 devnull #define LOG2 0.301029995664
11 e2713e92 2004-04-24 devnull #define Button_bit(b) (1 << ((b)-1))
12 e2713e92 2004-04-24 devnull
13 e2713e92 2004-04-24 devnull enum {
14 e2713e92 2004-04-24 devnull But1 = Button_bit(1),/* mouse buttons for events */
15 e2713e92 2004-04-24 devnull But2 = Button_bit(2),
16 e2713e92 2004-04-24 devnull But3 = Button_bit(3),
17 e2713e92 2004-04-24 devnull };
18 e2713e92 2004-04-24 devnull int cantmv = 1; /* disallow rotate and move? 0..1 */
19 e2713e92 2004-04-24 devnull int top_border, bot_border, lft_border, rt_border;
20 e2713e92 2004-04-24 devnull int lft_border0; /* lft_border for y-axis labels >0 */
21 e2713e92 2004-04-24 devnull int top_left, top_right; /* edges of top line free space */
22 e2713e92 2004-04-24 devnull int Mv_delay = 400; /* msec for button click vs. button hold down */
23 e2713e92 2004-04-24 devnull int Dotrad = 2; /* dot radius in pixels */
24 e2713e92 2004-04-24 devnull int framewd=1; /* line thickness for frame (pixels) */
25 e2713e92 2004-04-24 devnull int framesep=1; /* distance between frame and surrounding text */
26 e2713e92 2004-04-24 devnull int outersep=1; /* distance: surrounding text to screen edge */
27 e2713e92 2004-04-24 devnull Point sdigit; /* size of a digit in the font */
28 e2713e92 2004-04-24 devnull Point smaxch; /* assume any character in font fits in this */
29 e2713e92 2004-04-24 devnull double underscan = .05; /* fraction of frame initially unused per side */
30 e2713e92 2004-04-24 devnull double fuzz = 6; /* selection tolerance in pixels */
31 e2713e92 2004-04-24 devnull int tick_len = 15; /* length of axis label tick mark in pixels */
32 e2713e92 2004-04-24 devnull FILE* logfil = 0; /* dump selected points here if nonzero */
33 e2713e92 2004-04-24 devnull
34 e2713e92 2004-04-24 devnull #define labdigs 3 /* allow this many sig digits in axis labels */
35 e2713e92 2004-04-24 devnull #define digs10pow 1000 /* pow(10,labdigs) */
36 e2713e92 2004-04-24 devnull #define axis_color clr_im(DLtblue)
37 e2713e92 2004-04-24 devnull
38 e2713e92 2004-04-24 devnull
39 e2713e92 2004-04-24 devnull
40 e2713e92 2004-04-24 devnull
41 e2713e92 2004-04-24 devnull /********************************* Utilities *********************************/
42 e2713e92 2004-04-24 devnull
43 e2713e92 2004-04-24 devnull /* Prepend string s to null-terminated string in n-byte buffer buf[], truncating if
44 e2713e92 2004-04-24 devnull necessary and using a space to separate s from the rest of buf[].
45 e2713e92 2004-04-24 devnull */
46 e2713e92 2004-04-24 devnull char* str_insert(char* buf, char* s, int n)
47 e2713e92 2004-04-24 devnull {
48 e2713e92 2004-04-24 devnull int blen, slen = strlen(s) + 1;
49 e2713e92 2004-04-24 devnull if (slen >= n)
50 e2713e92 2004-04-24 devnull {strncpy(buf,s,n); buf[n-1]='\0'; return buf;}
51 e2713e92 2004-04-24 devnull blen = strlen(buf);
52 e2713e92 2004-04-24 devnull if (blen >= n-slen)
53 e2713e92 2004-04-24 devnull buf[blen=n-slen-1] = '\0';
54 e2713e92 2004-04-24 devnull memmove(buf+slen, buf, slen+blen+1);
55 e2713e92 2004-04-24 devnull memcpy(buf, s, slen-1);
56 e2713e92 2004-04-24 devnull buf[slen-1] = ' ';
57 e2713e92 2004-04-24 devnull return buf;
58 e2713e92 2004-04-24 devnull }
59 e2713e92 2004-04-24 devnull
60 e2713e92 2004-04-24 devnull /* Alter string smain (without lengthening it) so as to remove the first occurrence of
61 e2713e92 2004-04-24 devnull ssub, assuming ssub is ASCII. Return nonzero (true) if string smain had to be changed.
62 e2713e92 2004-04-24 devnull In spite of the ASCII-centric appearance, I think this can handle UTF in smain.
63 e2713e92 2004-04-24 devnull */
64 e2713e92 2004-04-24 devnull int remove_substr(char* smain, char* ssub)
65 e2713e92 2004-04-24 devnull {
66 e2713e92 2004-04-24 devnull char *ss, *s = strstr(smain, ssub);
67 e2713e92 2004-04-24 devnull int n = strlen(ssub);
68 e2713e92 2004-04-24 devnull if (s==0)
69 e2713e92 2004-04-24 devnull return 0;
70 3bd56b04 2005-09-09 devnull if (islower((uchar)s[n]))
71 e2713e92 2004-04-24 devnull s[0] ^= 32; /* probably tolower(s[0]) or toupper(s[0]) */
72 e2713e92 2004-04-24 devnull else {
73 e2713e92 2004-04-24 devnull for (ss=s+n; *ss!=0; s++, ss++)
74 e2713e92 2004-04-24 devnull *s = *ss;
75 e2713e92 2004-04-24 devnull *s = '\0';
76 e2713e92 2004-04-24 devnull }
77 e2713e92 2004-04-24 devnull return 1;
78 e2713e92 2004-04-24 devnull }
79 e2713e92 2004-04-24 devnull
80 e2713e92 2004-04-24 devnull void adjust_border(Font* f)
81 e2713e92 2004-04-24 devnull {
82 e2713e92 2004-04-24 devnull int sep = framesep + outersep;
83 e2713e92 2004-04-24 devnull sdigit = stringsize(f, "8");
84 e2713e92 2004-04-24 devnull smaxch = stringsize(f, "MMMg");
85 e2713e92 2004-04-24 devnull smaxch.x = (smaxch.x + 3)/4;
86 e2713e92 2004-04-24 devnull lft_border0 = (1+labdigs)*sdigit.x + framewd + sep;
87 e2713e92 2004-04-24 devnull rt_border = (lft_border0 - sep)/2 + outersep;
88 e2713e92 2004-04-24 devnull bot_border = sdigit.y + framewd + sep;
89 e2713e92 2004-04-24 devnull top_border = smaxch.y + framewd + sep;
90 e2713e92 2004-04-24 devnull lft_border = lft_border0; /* this gets reset later */
91 e2713e92 2004-04-24 devnull }
92 e2713e92 2004-04-24 devnull
93 e2713e92 2004-04-24 devnull
94 e2713e92 2004-04-24 devnull int is_off_screen(Point p)
95 e2713e92 2004-04-24 devnull {
96 e2713e92 2004-04-24 devnull const Rectangle* r = &(screen->r);
97 e2713e92 2004-04-24 devnull return p.x-r->min.x<lft_border || r->max.x-p.x<rt_border
98 e2713e92 2004-04-24 devnull || p.y-r->min.y<=top_border || r->max.y-p.y<=bot_border;
99 e2713e92 2004-04-24 devnull }
100 e2713e92 2004-04-24 devnull
101 e2713e92 2004-04-24 devnull
102 e2713e92 2004-04-24 devnull Cursor bullseye =
103 e2713e92 2004-04-24 devnull {
104 e2713e92 2004-04-24 devnull {-7, -7},
105 e2713e92 2004-04-24 devnull {
106 e2713e92 2004-04-24 devnull 0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0xFB, 0xDF,
107 e2713e92 2004-04-24 devnull 0xF3, 0xCF, 0xE3, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF,
108 e2713e92 2004-04-24 devnull 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC7, 0xF3, 0xCF,
109 e2713e92 2004-04-24 devnull 0x7B, 0xDF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8,
110 e2713e92 2004-04-24 devnull },
111 e2713e92 2004-04-24 devnull {
112 e2713e92 2004-04-24 devnull 0x00, 0x00, 0x0F, 0xF0, 0x31, 0x8C, 0x21, 0x84,
113 e2713e92 2004-04-24 devnull 0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 0x7F, 0xFE,
114 e2713e92 2004-04-24 devnull 0x7F, 0xFE, 0x41, 0x82, 0x41, 0x82, 0x41, 0x82,
115 e2713e92 2004-04-24 devnull 0x21, 0x84, 0x31, 0x8C, 0x0F, 0xF0, 0x00, 0x00,
116 e2713e92 2004-04-24 devnull }
117 e2713e92 2004-04-24 devnull };
118 e2713e92 2004-04-24 devnull
119 e2713e92 2004-04-24 devnull int get_1click(int but, Mouse* m, Cursor* curs)
120 e2713e92 2004-04-24 devnull {
121 e2713e92 2004-04-24 devnull if (curs)
122 e2713e92 2004-04-24 devnull esetcursor(curs);
123 e2713e92 2004-04-24 devnull while (m->buttons==0)
124 e2713e92 2004-04-24 devnull *m = emouse();
125 e2713e92 2004-04-24 devnull if (curs)
126 e2713e92 2004-04-24 devnull esetcursor(0);
127 e2713e92 2004-04-24 devnull return (m->buttons==Button_bit(but));
128 e2713e92 2004-04-24 devnull }
129 e2713e92 2004-04-24 devnull
130 e2713e92 2004-04-24 devnull
131 e2713e92 2004-04-24 devnull /* Wait until but goes up or until a mouse event's msec passes tlimit.
132 e2713e92 2004-04-24 devnull Return a boolean result that tells whether the button went up.
133 e2713e92 2004-04-24 devnull */
134 e2713e92 2004-04-24 devnull int lift_button(int but, Mouse* m, int tlimit)
135 e2713e92 2004-04-24 devnull {
136 e2713e92 2004-04-24 devnull do { *m = emouse();
137 e2713e92 2004-04-24 devnull if (m->msec >= tlimit)
138 e2713e92 2004-04-24 devnull return 0;
139 e2713e92 2004-04-24 devnull } while (m->buttons & Button_bit(but));
140 e2713e92 2004-04-24 devnull return 1;
141 e2713e92 2004-04-24 devnull }
142 e2713e92 2004-04-24 devnull
143 e2713e92 2004-04-24 devnull
144 e2713e92 2004-04-24 devnull /* Set *m to the last pending mouse event, or the first one where but is up.
145 e2713e92 2004-04-24 devnull If no mouse events are pending, wait for the next one.
146 e2713e92 2004-04-24 devnull */
147 e2713e92 2004-04-24 devnull void latest_mouse(int but, Mouse* m)
148 e2713e92 2004-04-24 devnull {
149 e2713e92 2004-04-24 devnull int bbit = Button_bit(but);
150 e2713e92 2004-04-24 devnull do { *m = emouse();
151 e2713e92 2004-04-24 devnull } while ((m->buttons & bbit) && ecanmouse());
152 e2713e92 2004-04-24 devnull }
153 e2713e92 2004-04-24 devnull
154 e2713e92 2004-04-24 devnull
155 e2713e92 2004-04-24 devnull
156 e2713e92 2004-04-24 devnull /*********************************** Colors ***********************************/
157 e2713e92 2004-04-24 devnull
158 d7925b13 2005-01-14 devnull #define DOrange 0xFFAA00FF
159 d7925b13 2005-01-14 devnull #define Dgray 0xBBBBBBFF
160 d7925b13 2005-01-14 devnull #define DDkgreen 0x009900FF
161 d7925b13 2005-01-14 devnull #define DDkred 0xCC0000FF
162 d7925b13 2005-01-14 devnull #define DViolet 0x990099FF
163 d7925b13 2005-01-14 devnull #define DDkyellow 0xAAAA00FF
164 d7925b13 2005-01-14 devnull #define DLtblue 0xAAAAFFFF
165 d7925b13 2005-01-14 devnull #define DPink 0xFFAAAAFF
166 d7925b13 2005-01-14 devnull
167 d7925b13 2005-01-14 devnull /* draw.h sets DBlack, DBlue, DRed, DYellow, DGreen,
168 e2713e92 2004-04-24 devnull DCyan, DMagenta, DWhite */
169 e2713e92 2004-04-24 devnull
170 e2713e92 2004-04-24 devnull typedef struct color_ref {
171 e2713e92 2004-04-24 devnull ulong c; /* RGBA pixel color */
172 e2713e92 2004-04-24 devnull char* nam; /* ASCII name (matched to input, used in output)*/
173 e2713e92 2004-04-24 devnull Image* im; /* replicated solid-color image */
174 e2713e92 2004-04-24 devnull } color_ref;
175 e2713e92 2004-04-24 devnull
176 e2713e92 2004-04-24 devnull color_ref clrtab[] = {
177 e2713e92 2004-04-24 devnull DRed, "Red", 0,
178 e2713e92 2004-04-24 devnull DPink, "Pink", 0,
179 e2713e92 2004-04-24 devnull DDkred, "Dkred", 0,
180 e2713e92 2004-04-24 devnull DOrange, "Orange", 0,
181 e2713e92 2004-04-24 devnull DYellow, "Yellow", 0,
182 e2713e92 2004-04-24 devnull DDkyellow, "Dkyellow", 0,
183 e2713e92 2004-04-24 devnull DGreen, "Green", 0,
184 e2713e92 2004-04-24 devnull DDkgreen, "Dkgreen", 0,
185 e2713e92 2004-04-24 devnull DCyan, "Cyan", 0,
186 e2713e92 2004-04-24 devnull DBlue, "Blue", 0,
187 e2713e92 2004-04-24 devnull DLtblue, "Ltblue", 0,
188 e2713e92 2004-04-24 devnull DMagenta, "Magenta", 0,
189 e2713e92 2004-04-24 devnull DViolet, "Violet", 0,
190 e2713e92 2004-04-24 devnull Dgray, "Gray", 0,
191 e2713e92 2004-04-24 devnull DBlack, "Black", 0,
192 e2713e92 2004-04-24 devnull DWhite, "White", 0,
193 e2713e92 2004-04-24 devnull DNofill, 0, 0 /* DNofill means "end of data" */
194 e2713e92 2004-04-24 devnull };
195 e2713e92 2004-04-24 devnull
196 e2713e92 2004-04-24 devnull
197 e2713e92 2004-04-24 devnull void init_clrtab(void)
198 e2713e92 2004-04-24 devnull {
199 e2713e92 2004-04-24 devnull int i;
200 e2713e92 2004-04-24 devnull Rectangle r = Rect(0,0,1,1);
201 e2713e92 2004-04-24 devnull for (i=0; clrtab[i].c!=DNofill; i++)
202 e2713e92 2004-04-24 devnull clrtab[i].im = allocimage(display, r, CMAP8, 1, clrtab[i].c);
203 e2713e92 2004-04-24 devnull /* should check for 0 result? */
204 e2713e92 2004-04-24 devnull }
205 e2713e92 2004-04-24 devnull
206 e2713e92 2004-04-24 devnull
207 e2713e92 2004-04-24 devnull int clrim_id(Image* clr)
208 e2713e92 2004-04-24 devnull {
209 e2713e92 2004-04-24 devnull int i;
210 e2713e92 2004-04-24 devnull for (i=0; clrtab[i].im!=clr; i++)
211 e2713e92 2004-04-24 devnull if (clrtab[i].c==DNofill)
212 e2713e92 2004-04-24 devnull exits("bad image color");
213 e2713e92 2004-04-24 devnull return i;
214 e2713e92 2004-04-24 devnull }
215 e2713e92 2004-04-24 devnull
216 e2713e92 2004-04-24 devnull int clr_id(int clr)
217 e2713e92 2004-04-24 devnull {
218 e2713e92 2004-04-24 devnull int i;
219 e2713e92 2004-04-24 devnull for (i=0; clrtab[i].c!=clr; i++)
220 e2713e92 2004-04-24 devnull if (clrtab[i].c==DNofill)
221 e2713e92 2004-04-24 devnull exits("bad color");
222 e2713e92 2004-04-24 devnull return i;
223 e2713e92 2004-04-24 devnull }
224 e2713e92 2004-04-24 devnull
225 e2713e92 2004-04-24 devnull #define clr_im(clr) clrtab[clr_id(clr)].im
226 e2713e92 2004-04-24 devnull
227 e2713e92 2004-04-24 devnull
228 e2713e92 2004-04-24 devnull /* This decides what color to use for a polyline based on the label it has in the
229 e2713e92 2004-04-24 devnull input file. Whichever color name comes first is the winner, otherwise return black.
230 e2713e92 2004-04-24 devnull */
231 e2713e92 2004-04-24 devnull Image* nam2clr(const char* nam, int *idxdest)
232 e2713e92 2004-04-24 devnull {
233 e2713e92 2004-04-24 devnull char *c, *cbest=(char*)nam;
234 e2713e92 2004-04-24 devnull int i, ibest=-1;
235 e2713e92 2004-04-24 devnull if (*nam!=0)
236 e2713e92 2004-04-24 devnull for (i=0; clrtab[i].nam!=0; i++) {
237 e2713e92 2004-04-24 devnull c = strstr(nam,clrtab[i].nam);
238 e2713e92 2004-04-24 devnull if (c!=0 && (ibest<0 || c<cbest))
239 e2713e92 2004-04-24 devnull {ibest=i; cbest=c;}
240 e2713e92 2004-04-24 devnull }
241 e2713e92 2004-04-24 devnull if (idxdest!=0)
242 e2713e92 2004-04-24 devnull *idxdest = (ibest<0) ? clr_id(DBlack) : ibest;
243 e2713e92 2004-04-24 devnull return (ibest<0) ? clr_im(DBlack) : clrtab[ibest].im;
244 e2713e92 2004-04-24 devnull }
245 e2713e92 2004-04-24 devnull
246 e2713e92 2004-04-24 devnull /* A polyline is initial drawn in thick mode iff its label in the file contains "Thick" */
247 e2713e92 2004-04-24 devnull int nam2thick(const char* nam)
248 e2713e92 2004-04-24 devnull {
249 e2713e92 2004-04-24 devnull return strstr(nam,"Thick")==0 ? 0 : 1;
250 e2713e92 2004-04-24 devnull }
251 e2713e92 2004-04-24 devnull
252 e2713e92 2004-04-24 devnull
253 e2713e92 2004-04-24 devnull /* Alter string nam so that nam2thick() and nam2clr() agree with th and clr, using
254 e2713e92 2004-04-24 devnull buf[] (a buffer of length bufn) to store the result if it differs from nam.
255 e2713e92 2004-04-24 devnull We go to great pains to perform this alteration in a manner that will seem natural
256 e2713e92 2004-04-24 devnull to the user, i.e., we try removing a suitably isolated color name before inserting
257 e2713e92 2004-04-24 devnull a new one.
258 e2713e92 2004-04-24 devnull */
259 e2713e92 2004-04-24 devnull char* nam_with_thclr(char* nam, int th, Image* clr, char* buf, int bufn)
260 e2713e92 2004-04-24 devnull {
261 e2713e92 2004-04-24 devnull int clr0i, th0=nam2thick(nam);
262 e2713e92 2004-04-24 devnull Image* clr0 = nam2clr(nam, &clr0i);
263 e2713e92 2004-04-24 devnull char *clr0s;
264 e2713e92 2004-04-24 devnull if (th0==th && clr0==clr)
265 e2713e92 2004-04-24 devnull return nam;
266 e2713e92 2004-04-24 devnull clr0s = clrtab[clr0i].nam;
267 e2713e92 2004-04-24 devnull if (strlen(nam)<bufn) strcpy(buf,nam);
268 e2713e92 2004-04-24 devnull else {strncpy(buf,nam,bufn); buf[bufn-1]='\0';}
269 e2713e92 2004-04-24 devnull if (clr0 != clr)
270 e2713e92 2004-04-24 devnull remove_substr(buf, clr0s);
271 e2713e92 2004-04-24 devnull if (th0 > th)
272 e2713e92 2004-04-24 devnull while (remove_substr(buf, "Thick"))
273 e2713e92 2004-04-24 devnull /* do nothing */;
274 e2713e92 2004-04-24 devnull if (nam2clr(buf,0) != clr)
275 e2713e92 2004-04-24 devnull str_insert(buf, clrtab[clrim_id(clr)].nam, bufn);
276 e2713e92 2004-04-24 devnull if (th0 < th)
277 e2713e92 2004-04-24 devnull str_insert(buf, "Thick", bufn);
278 e2713e92 2004-04-24 devnull return buf;
279 e2713e92 2004-04-24 devnull }
280 e2713e92 2004-04-24 devnull
281 e2713e92 2004-04-24 devnull
282 e2713e92 2004-04-24 devnull
283 e2713e92 2004-04-24 devnull /****************************** Data structures ******************************/
284 e2713e92 2004-04-24 devnull
285 e2713e92 2004-04-24 devnull Image* mv_bkgd; /* Background image (usually 0) */
286 e2713e92 2004-04-24 devnull
287 e2713e92 2004-04-24 devnull typedef struct fpoint {
288 e2713e92 2004-04-24 devnull double x, y;
289 e2713e92 2004-04-24 devnull } fpoint;
290 e2713e92 2004-04-24 devnull
291 e2713e92 2004-04-24 devnull typedef struct frectangle {
292 e2713e92 2004-04-24 devnull fpoint min, max;
293 e2713e92 2004-04-24 devnull } frectangle;
294 e2713e92 2004-04-24 devnull
295 e2713e92 2004-04-24 devnull frectangle empty_frect = {1e30, 1e30, -1e30, -1e30};
296 e2713e92 2004-04-24 devnull
297 e2713e92 2004-04-24 devnull
298 e2713e92 2004-04-24 devnull /* When *r2 is transformed by y=y-x*slant, might it intersect *r1 ?
299 e2713e92 2004-04-24 devnull */
300 e2713e92 2004-04-24 devnull int fintersects(const frectangle* r1, const frectangle* r2, double slant)
301 e2713e92 2004-04-24 devnull {
302 e2713e92 2004-04-24 devnull double x2min=r2->min.x, x2max=r2->max.x;
303 e2713e92 2004-04-24 devnull if (r1->max.x <= x2min || x2max <= r1->min.x)
304 e2713e92 2004-04-24 devnull return 0;
305 e2713e92 2004-04-24 devnull if (slant >=0)
306 e2713e92 2004-04-24 devnull {x2min*=slant; x2max*=slant;}
307 e2713e92 2004-04-24 devnull else {double t=x2min*slant; x2min=x2max*slant; x2max=t;}
308 e2713e92 2004-04-24 devnull return r1->max.y > r2->min.y-x2max && r2->max.y-x2min > r1->min.y;
309 e2713e92 2004-04-24 devnull }
310 e2713e92 2004-04-24 devnull
311 e2713e92 2004-04-24 devnull int fcontains(const frectangle* r, fpoint p)
312 e2713e92 2004-04-24 devnull {
313 e2713e92 2004-04-24 devnull return r->min.x <=p.x && p.x<= r->max.x && r->min.y <=p.y && p.y<= r->max.y;
314 e2713e92 2004-04-24 devnull }
315 e2713e92 2004-04-24 devnull
316 e2713e92 2004-04-24 devnull
317 e2713e92 2004-04-24 devnull void grow_bb(frectangle* dest, const frectangle* r)
318 e2713e92 2004-04-24 devnull {
319 e2713e92 2004-04-24 devnull if (r->min.x < dest->min.x) dest->min.x=r->min.x;
320 e2713e92 2004-04-24 devnull if (r->min.y < dest->min.y) dest->min.y=r->min.y;
321 e2713e92 2004-04-24 devnull if (r->max.x > dest->max.x) dest->max.x=r->max.x;
322 e2713e92 2004-04-24 devnull if (r->max.y > dest->max.y) dest->max.y=r->max.y;
323 e2713e92 2004-04-24 devnull }
324 e2713e92 2004-04-24 devnull
325 e2713e92 2004-04-24 devnull
326 e2713e92 2004-04-24 devnull void slant_frect(frectangle *r, double sl)
327 e2713e92 2004-04-24 devnull {
328 e2713e92 2004-04-24 devnull r->min.y += sl*r->min.x;
329 e2713e92 2004-04-24 devnull r->max.y += sl*r->max.x;
330 e2713e92 2004-04-24 devnull }
331 e2713e92 2004-04-24 devnull
332 e2713e92 2004-04-24 devnull
333 e2713e92 2004-04-24 devnull fpoint fcenter(const frectangle* r)
334 e2713e92 2004-04-24 devnull {
335 e2713e92 2004-04-24 devnull fpoint c;
336 e2713e92 2004-04-24 devnull c.x = .5*(r->max.x + r->min.x);
337 e2713e92 2004-04-24 devnull c.y = .5*(r->max.y + r->min.y);
338 e2713e92 2004-04-24 devnull return c;
339 e2713e92 2004-04-24 devnull }
340 e2713e92 2004-04-24 devnull
341 e2713e92 2004-04-24 devnull
342 e2713e92 2004-04-24 devnull typedef struct fpolygon {
343 e2713e92 2004-04-24 devnull fpoint* p; /* a malloc'ed array */
344 e2713e92 2004-04-24 devnull int n; /* p[] has n elements: p[0..n] */
345 e2713e92 2004-04-24 devnull frectangle bb; /* bounding box */
346 e2713e92 2004-04-24 devnull char* nam; /* name of this polygon (malloc'ed) */
347 e2713e92 2004-04-24 devnull int thick; /* use 1+2*thick pixel wide lines */
348 e2713e92 2004-04-24 devnull Image* clr; /* Color to use when drawing this */
349 e2713e92 2004-04-24 devnull struct fpolygon* link;
350 e2713e92 2004-04-24 devnull } fpolygon;
351 e2713e92 2004-04-24 devnull
352 e2713e92 2004-04-24 devnull typedef struct fpolygons {
353 e2713e92 2004-04-24 devnull fpolygon* p; /* the head of a linked list */
354 e2713e92 2004-04-24 devnull frectangle bb; /* overall bounding box */
355 e2713e92 2004-04-24 devnull frectangle disp; /* part being mapped onto screen->r */
356 e2713e92 2004-04-24 devnull double slant_ht; /* controls how disp is slanted */
357 e2713e92 2004-04-24 devnull } fpolygons;
358 e2713e92 2004-04-24 devnull
359 e2713e92 2004-04-24 devnull
360 e2713e92 2004-04-24 devnull fpolygons univ = { /* everything there is to display */
361 e2713e92 2004-04-24 devnull 0,
362 e2713e92 2004-04-24 devnull 1e30, 1e30, -1e30, -1e30,
363 e2713e92 2004-04-24 devnull 0, 0, 0, 0,
364 e2713e92 2004-04-24 devnull 2*1e30
365 e2713e92 2004-04-24 devnull };
366 e2713e92 2004-04-24 devnull
367 e2713e92 2004-04-24 devnull
368 e2713e92 2004-04-24 devnull void set_default_clrs(fpolygons* fps, fpolygon* fpstop)
369 e2713e92 2004-04-24 devnull {
370 e2713e92 2004-04-24 devnull fpolygon* fp;
371 e2713e92 2004-04-24 devnull for (fp=fps->p; fp!=0 && fp!=fpstop; fp=fp->link) {
372 e2713e92 2004-04-24 devnull fp->clr = nam2clr(fp->nam,0);
373 e2713e92 2004-04-24 devnull fp->thick = nam2thick(fp->nam);
374 e2713e92 2004-04-24 devnull }
375 e2713e92 2004-04-24 devnull }
376 e2713e92 2004-04-24 devnull
377 e2713e92 2004-04-24 devnull
378 e2713e92 2004-04-24 devnull void fps_invert(fpolygons* fps)
379 e2713e92 2004-04-24 devnull {
380 e2713e92 2004-04-24 devnull fpolygon *p, *r=0;
381 e2713e92 2004-04-24 devnull for (p=fps->p; p!=0;) {
382 e2713e92 2004-04-24 devnull fpolygon* q = p;
383 e2713e92 2004-04-24 devnull p = p->link;
384 e2713e92 2004-04-24 devnull q->link = r;
385 e2713e92 2004-04-24 devnull r = q;
386 e2713e92 2004-04-24 devnull }
387 e2713e92 2004-04-24 devnull fps->p = r;
388 e2713e92 2004-04-24 devnull }
389 e2713e92 2004-04-24 devnull
390 e2713e92 2004-04-24 devnull
391 e2713e92 2004-04-24 devnull void fp_remove(fpolygons* fps, fpolygon* fp)
392 e2713e92 2004-04-24 devnull {
393 e2713e92 2004-04-24 devnull fpolygon *q, **p = &fps->p;
394 e2713e92 2004-04-24 devnull while (*p!=fp)
395 e2713e92 2004-04-24 devnull if (*p==0)
396 e2713e92 2004-04-24 devnull return;
397 e2713e92 2004-04-24 devnull else p = &(*p)->link;
398 e2713e92 2004-04-24 devnull *p = fp->link;
399 e2713e92 2004-04-24 devnull fps->bb = empty_frect;
400 e2713e92 2004-04-24 devnull for (q=fps->p; q!=0; q=q->link)
401 e2713e92 2004-04-24 devnull grow_bb(&fps->bb, &q->bb);
402 e2713e92 2004-04-24 devnull }
403 e2713e92 2004-04-24 devnull
404 e2713e92 2004-04-24 devnull
405 e2713e92 2004-04-24 devnull /* The transform maps abstract fpoint coordinates (the ones used in the input)
406 e2713e92 2004-04-24 devnull to the current screen coordinates. The do_untransform() macros reverses this.
407 e2713e92 2004-04-24 devnull If univ.slant_ht is not the height of univ.disp, the actual region in the
408 e2713e92 2004-04-24 devnull abstract coordinates is a parallelogram inscribed in univ.disp with two
409 e2713e92 2004-04-24 devnull vertical edges and two slanted slanted edges: slant_ht>0 means that the
410 e2713e92 2004-04-24 devnull vertical edges have height slant_ht and the parallelogram touches the lower
411 e2713e92 2004-04-24 devnull left and upper right corners of univ.disp; slant_ht<0 refers to a parallelogram
412 e2713e92 2004-04-24 devnull of height -slant_ht that touches the other two corners of univ.disp.
413 e2713e92 2004-04-24 devnull NOTE: the ytransform macro assumes that tr->sl times the x coordinate has
414 e2713e92 2004-04-24 devnull already been subtracted from yy.
415 e2713e92 2004-04-24 devnull */
416 e2713e92 2004-04-24 devnull typedef struct transform {
417 e2713e92 2004-04-24 devnull double sl;
418 e2713e92 2004-04-24 devnull fpoint o, sc; /* (x,y):->(o.x+sc.x*x, o.y+sc.y*y+sl*x) */
419 e2713e92 2004-04-24 devnull } transform;
420 e2713e92 2004-04-24 devnull
421 e2713e92 2004-04-24 devnull #define do_transform(d,tr,s) ((d)->x = (tr)->o.x + (tr)->sc.x*(s)->x, \
422 e2713e92 2004-04-24 devnull (d)->y = (tr)->o.y + (tr)->sc.y*(s)->y \
423 e2713e92 2004-04-24 devnull + (tr)->sl*(s)->x)
424 e2713e92 2004-04-24 devnull #define do_untransform(d,tr,s) ((d)->x = (.5+(s)->x-(tr)->o.x)/(tr)->sc.x, \
425 e2713e92 2004-04-24 devnull (d)->y = (.5+(s)->y-(tr)->sl*(d)->x-(tr)->o.y) \
426 e2713e92 2004-04-24 devnull /(tr)->sc.y)
427 e2713e92 2004-04-24 devnull #define xtransform(tr,xx) ((tr)->o.x + (tr)->sc.x*(xx))
428 e2713e92 2004-04-24 devnull #define ytransform(tr,yy) ((tr)->o.y + (tr)->sc.y*(yy))
429 e2713e92 2004-04-24 devnull #define dxuntransform(tr,xx) ((xx)/(tr)->sc.x)
430 e2713e92 2004-04-24 devnull #define dyuntransform(tr,yy) ((yy)/(tr)->sc.y)
431 e2713e92 2004-04-24 devnull
432 e2713e92 2004-04-24 devnull
433 e2713e92 2004-04-24 devnull transform cur_trans(void)
434 e2713e92 2004-04-24 devnull {
435 e2713e92 2004-04-24 devnull transform t;
436 e2713e92 2004-04-24 devnull Rectangle d = screen->r;
437 e2713e92 2004-04-24 devnull const frectangle* s = &univ.disp;
438 e2713e92 2004-04-24 devnull double sh = univ.slant_ht;
439 e2713e92 2004-04-24 devnull d.min.x += lft_border;
440 e2713e92 2004-04-24 devnull d.min.y += top_border;
441 e2713e92 2004-04-24 devnull d.max.x -= rt_border;
442 e2713e92 2004-04-24 devnull d.max.y -= bot_border;
443 e2713e92 2004-04-24 devnull t.sc.x = (d.max.x - d.min.x)/(s->max.x - s->min.x);
444 e2713e92 2004-04-24 devnull t.sc.y = -(d.max.y - d.min.y)/fabs(sh);
445 e2713e92 2004-04-24 devnull if (sh > 0) {
446 e2713e92 2004-04-24 devnull t.sl = -t.sc.y*(s->max.y-s->min.y-sh)/(s->max.x - s->min.x);
447 e2713e92 2004-04-24 devnull t.o.y = d.min.y - t.sc.y*s->max.y - t.sl*s->max.x;
448 e2713e92 2004-04-24 devnull } else {
449 e2713e92 2004-04-24 devnull t.sl = t.sc.y*(s->max.y-s->min.y+sh)/(s->max.x - s->min.x);
450 e2713e92 2004-04-24 devnull t.o.y = d.min.y - t.sc.y*s->max.y - t.sl*s->min.x;
451 e2713e92 2004-04-24 devnull }
452 e2713e92 2004-04-24 devnull t.o.x = d.min.x - t.sc.x*s->min.x;
453 e2713e92 2004-04-24 devnull return t;
454 e2713e92 2004-04-24 devnull }
455 e2713e92 2004-04-24 devnull
456 e2713e92 2004-04-24 devnull
457 e2713e92 2004-04-24 devnull double u_slant_amt(fpolygons *u)
458 e2713e92 2004-04-24 devnull {
459 e2713e92 2004-04-24 devnull double sh=u->slant_ht, dy=u->disp.max.y - u->disp.min.y;
460 e2713e92 2004-04-24 devnull double dx = u->disp.max.x - u->disp.min.x;
461 e2713e92 2004-04-24 devnull return (sh>0) ? (dy-sh)/dx : -(dy+sh)/dx;
462 e2713e92 2004-04-24 devnull }
463 e2713e92 2004-04-24 devnull
464 e2713e92 2004-04-24 devnull
465 e2713e92 2004-04-24 devnull /* Set *y0 and *y1 to the lower and upper bounds of the set of y-sl*x values that
466 e2713e92 2004-04-24 devnull *u says to display, where sl is the amount of slant.
467 e2713e92 2004-04-24 devnull */
468 e2713e92 2004-04-24 devnull double set_unslanted_y(fpolygons *u, double *y0, double *y1)
469 e2713e92 2004-04-24 devnull {
470 e2713e92 2004-04-24 devnull double yy1, sl=u_slant_amt(u);
471 e2713e92 2004-04-24 devnull if (u->slant_ht > 0) {
472 e2713e92 2004-04-24 devnull *y0 = u->disp.min.y - sl*u->disp.min.x;
473 e2713e92 2004-04-24 devnull yy1 = *y0 + u->slant_ht;
474 e2713e92 2004-04-24 devnull } else {
475 e2713e92 2004-04-24 devnull yy1 = u->disp.max.y - sl*u->disp.min.x;
476 e2713e92 2004-04-24 devnull *y0 = yy1 + u->slant_ht;
477 e2713e92 2004-04-24 devnull }
478 e2713e92 2004-04-24 devnull if (y1 != 0)
479 e2713e92 2004-04-24 devnull *y1 = yy1;
480 e2713e92 2004-04-24 devnull return sl;
481 e2713e92 2004-04-24 devnull }
482 e2713e92 2004-04-24 devnull
483 e2713e92 2004-04-24 devnull
484 e2713e92 2004-04-24 devnull
485 e2713e92 2004-04-24 devnull
486 e2713e92 2004-04-24 devnull /*************************** The region to display ****************************/
487 e2713e92 2004-04-24 devnull
488 e2713e92 2004-04-24 devnull void nontrivial_interval(double *lo, double *hi)
489 e2713e92 2004-04-24 devnull {
490 e2713e92 2004-04-24 devnull if (*lo >= *hi) {
491 e2713e92 2004-04-24 devnull double mid = .5*(*lo + *hi);
492 e2713e92 2004-04-24 devnull double tweak = 1e-6 + 1e-6*fabs(mid);
493 e2713e92 2004-04-24 devnull *lo = mid - tweak;
494 e2713e92 2004-04-24 devnull *hi = mid + tweak;
495 e2713e92 2004-04-24 devnull }
496 e2713e92 2004-04-24 devnull }
497 e2713e92 2004-04-24 devnull
498 e2713e92 2004-04-24 devnull
499 e2713e92 2004-04-24 devnull void init_disp(void)
500 e2713e92 2004-04-24 devnull {
501 e2713e92 2004-04-24 devnull double dw = (univ.bb.max.x - univ.bb.min.x)*underscan;
502 e2713e92 2004-04-24 devnull double dh = (univ.bb.max.y - univ.bb.min.y)*underscan;
503 e2713e92 2004-04-24 devnull univ.disp.min.x = univ.bb.min.x - dw;
504 e2713e92 2004-04-24 devnull univ.disp.min.y = univ.bb.min.y - dh;
505 e2713e92 2004-04-24 devnull univ.disp.max.x = univ.bb.max.x + dw;
506 e2713e92 2004-04-24 devnull univ.disp.max.y = univ.bb.max.y + dh;
507 e2713e92 2004-04-24 devnull nontrivial_interval(&univ.disp.min.x, &univ.disp.max.x);
508 e2713e92 2004-04-24 devnull nontrivial_interval(&univ.disp.min.y, &univ.disp.max.y);
509 e2713e92 2004-04-24 devnull univ.slant_ht = univ.disp.max.y - univ.disp.min.y; /* means no slant */
510 e2713e92 2004-04-24 devnull }
511 e2713e92 2004-04-24 devnull
512 e2713e92 2004-04-24 devnull
513 e2713e92 2004-04-24 devnull void recenter_disp(Point c)
514 e2713e92 2004-04-24 devnull {
515 e2713e92 2004-04-24 devnull transform tr = cur_trans();
516 e2713e92 2004-04-24 devnull fpoint cc, off;
517 e2713e92 2004-04-24 devnull do_untransform(&cc, &tr, &c);
518 e2713e92 2004-04-24 devnull off.x = cc.x - .5*(univ.disp.min.x + univ.disp.max.x);
519 e2713e92 2004-04-24 devnull off.y = cc.y - .5*(univ.disp.min.y + univ.disp.max.y);
520 e2713e92 2004-04-24 devnull univ.disp.min.x += off.x;
521 e2713e92 2004-04-24 devnull univ.disp.min.y += off.y;
522 e2713e92 2004-04-24 devnull univ.disp.max.x += off.x;
523 e2713e92 2004-04-24 devnull univ.disp.max.y += off.y;
524 e2713e92 2004-04-24 devnull }
525 e2713e92 2004-04-24 devnull
526 e2713e92 2004-04-24 devnull
527 e2713e92 2004-04-24 devnull /* Find the upper-left and lower-right corners of the bounding box of the
528 e2713e92 2004-04-24 devnull parallelogram formed by untransforming the rectangle rminx, rminy, ... (given
529 e2713e92 2004-04-24 devnull in screen coordinates), and return the height of the parallelogram (negated
530 e2713e92 2004-04-24 devnull if it slopes downward).
531 e2713e92 2004-04-24 devnull */
532 e2713e92 2004-04-24 devnull double untransform_corners(double rminx, double rminy, double rmaxx, double rmaxy,
533 e2713e92 2004-04-24 devnull fpoint *ul, fpoint *lr)
534 e2713e92 2004-04-24 devnull {
535 e2713e92 2004-04-24 devnull fpoint r_ur, r_ul, r_ll, r_lr; /* corners of the given recangle */
536 e2713e92 2004-04-24 devnull fpoint ur, ll; /* untransformed versions of r_ur, r_ll */
537 e2713e92 2004-04-24 devnull transform tr = cur_trans();
538 e2713e92 2004-04-24 devnull double ht;
539 e2713e92 2004-04-24 devnull r_ur.x=rmaxx; r_ur.y=rminy;
540 e2713e92 2004-04-24 devnull r_ul.x=rminx; r_ul.y=rminy;
541 e2713e92 2004-04-24 devnull r_ll.x=rminx; r_ll.y=rmaxy;
542 e2713e92 2004-04-24 devnull r_lr.x=rmaxx; r_lr.y=rmaxy;
543 e2713e92 2004-04-24 devnull do_untransform(ul, &tr, &r_ul);
544 e2713e92 2004-04-24 devnull do_untransform(lr, &tr, &r_lr);
545 e2713e92 2004-04-24 devnull do_untransform(&ur, &tr, &r_ur);
546 e2713e92 2004-04-24 devnull do_untransform(&ll, &tr, &r_ll);
547 e2713e92 2004-04-24 devnull ht = ur.y - lr->y;
548 e2713e92 2004-04-24 devnull if (ll.x < ul->x)
549 e2713e92 2004-04-24 devnull ul->x = ll.x;
550 e2713e92 2004-04-24 devnull if (ur.y > ul->y)
551 e2713e92 2004-04-24 devnull ul->y = ur.y;
552 e2713e92 2004-04-24 devnull else ht = -ht;
553 e2713e92 2004-04-24 devnull if (ur.x > lr->x)
554 e2713e92 2004-04-24 devnull lr->x = ur.x;
555 e2713e92 2004-04-24 devnull if (ll.y < lr->y)
556 e2713e92 2004-04-24 devnull lr->y = ll.y;
557 e2713e92 2004-04-24 devnull return ht;
558 e2713e92 2004-04-24 devnull }
559 e2713e92 2004-04-24 devnull
560 e2713e92 2004-04-24 devnull
561 e2713e92 2004-04-24 devnull void disp_dozoom(double rminx, double rminy, double rmaxx, double rmaxy)
562 e2713e92 2004-04-24 devnull {
563 e2713e92 2004-04-24 devnull fpoint ul, lr;
564 e2713e92 2004-04-24 devnull double sh = untransform_corners(rminx, rminy, rmaxx, rmaxy, &ul, &lr);
565 e2713e92 2004-04-24 devnull if (ul.x==lr.x || ul.y==lr.y)
566 e2713e92 2004-04-24 devnull return;
567 e2713e92 2004-04-24 devnull univ.slant_ht = sh;
568 e2713e92 2004-04-24 devnull univ.disp.min.x = ul.x;
569 e2713e92 2004-04-24 devnull univ.disp.max.y = ul.y;
570 e2713e92 2004-04-24 devnull univ.disp.max.x = lr.x;
571 e2713e92 2004-04-24 devnull univ.disp.min.y = lr.y;
572 e2713e92 2004-04-24 devnull nontrivial_interval(&univ.disp.min.x, &univ.disp.max.x);
573 e2713e92 2004-04-24 devnull nontrivial_interval(&univ.disp.min.y, &univ.disp.max.y);
574 e2713e92 2004-04-24 devnull }
575 e2713e92 2004-04-24 devnull
576 e2713e92 2004-04-24 devnull
577 e2713e92 2004-04-24 devnull void disp_zoomin(Rectangle r)
578 e2713e92 2004-04-24 devnull {
579 e2713e92 2004-04-24 devnull disp_dozoom(r.min.x, r.min.y, r.max.x, r.max.y);
580 e2713e92 2004-04-24 devnull }
581 e2713e92 2004-04-24 devnull
582 e2713e92 2004-04-24 devnull
583 e2713e92 2004-04-24 devnull void disp_zoomout(Rectangle r)
584 e2713e92 2004-04-24 devnull {
585 e2713e92 2004-04-24 devnull double qminx, qminy, qmaxx, qmaxy;
586 e2713e92 2004-04-24 devnull double scx, scy;
587 e2713e92 2004-04-24 devnull Rectangle s = screen->r;
588 e2713e92 2004-04-24 devnull if (r.min.x==r.max.x || r.min.y==r.max.y)
589 e2713e92 2004-04-24 devnull return;
590 e2713e92 2004-04-24 devnull s.min.x += lft_border;
591 e2713e92 2004-04-24 devnull s.min.y += top_border;
592 e2713e92 2004-04-24 devnull s.max.x -= rt_border;
593 e2713e92 2004-04-24 devnull s.max.y -= bot_border;
594 e2713e92 2004-04-24 devnull scx = (s.max.x - s.min.x)/(r.max.x - r.min.x);
595 e2713e92 2004-04-24 devnull scy = (s.max.y - s.min.y)/(r.max.y - r.min.y);
596 e2713e92 2004-04-24 devnull qminx = s.min.x + scx*(s.min.x - r.min.x);
597 e2713e92 2004-04-24 devnull qmaxx = s.max.x + scx*(s.max.x - r.max.x);
598 e2713e92 2004-04-24 devnull qminy = s.min.y + scy*(s.min.y - r.min.y);
599 e2713e92 2004-04-24 devnull qmaxy = s.max.y + scy*(s.max.y - r.max.y);
600 e2713e92 2004-04-24 devnull disp_dozoom(qminx, qminy, qmaxx, qmaxy);
601 e2713e92 2004-04-24 devnull }
602 e2713e92 2004-04-24 devnull
603 e2713e92 2004-04-24 devnull
604 e2713e92 2004-04-24 devnull void expand2(double* a, double* b, double f)
605 e2713e92 2004-04-24 devnull {
606 e2713e92 2004-04-24 devnull double mid = .5*(*a + *b);
607 e2713e92 2004-04-24 devnull *a = mid + f*(*a - mid);
608 e2713e92 2004-04-24 devnull *b = mid + f*(*b - mid);
609 e2713e92 2004-04-24 devnull }
610 e2713e92 2004-04-24 devnull
611 e2713e92 2004-04-24 devnull void disp_squareup(void)
612 e2713e92 2004-04-24 devnull {
613 e2713e92 2004-04-24 devnull double dx = univ.disp.max.x - univ.disp.min.x;
614 e2713e92 2004-04-24 devnull double dy = univ.disp.max.y - univ.disp.min.y;
615 e2713e92 2004-04-24 devnull dx /= screen->r.max.x - lft_border - screen->r.min.x - rt_border;
616 e2713e92 2004-04-24 devnull dy /= screen->r.max.y - bot_border - screen->r.min.y - top_border;
617 e2713e92 2004-04-24 devnull if (dx > dy)
618 e2713e92 2004-04-24 devnull expand2(&univ.disp.min.y, &univ.disp.max.y, dx/dy);
619 e2713e92 2004-04-24 devnull else expand2(&univ.disp.min.x, &univ.disp.max.x, dy/dx);
620 e2713e92 2004-04-24 devnull univ.slant_ht = univ.disp.max.y - univ.disp.min.y;
621 e2713e92 2004-04-24 devnull }
622 e2713e92 2004-04-24 devnull
623 e2713e92 2004-04-24 devnull
624 e2713e92 2004-04-24 devnull /* Slant so that p and q appear at the same height on the screen and the
625 e2713e92 2004-04-24 devnull screen contains the smallest possible superset of what its previous contents.
626 e2713e92 2004-04-24 devnull */
627 e2713e92 2004-04-24 devnull void slant_disp(fpoint p, fpoint q)
628 e2713e92 2004-04-24 devnull {
629 e2713e92 2004-04-24 devnull double yll, ylr, yul, yur; /* corner y coords of displayed parallelogram */
630 e2713e92 2004-04-24 devnull double sh, dy;
631 e2713e92 2004-04-24 devnull if (p.x == q.x)
632 e2713e92 2004-04-24 devnull return;
633 e2713e92 2004-04-24 devnull sh = univ.slant_ht;
634 e2713e92 2004-04-24 devnull if (sh > 0) {
635 e2713e92 2004-04-24 devnull yll=yul=univ.disp.min.y; yul+=sh;
636 e2713e92 2004-04-24 devnull ylr=yur=univ.disp.max.y; ylr-=sh;
637 e2713e92 2004-04-24 devnull } else {
638 e2713e92 2004-04-24 devnull yll=yul=univ.disp.max.y; yll+=sh;
639 e2713e92 2004-04-24 devnull ylr=yur=univ.disp.min.y; yur-=sh;
640 e2713e92 2004-04-24 devnull }
641 e2713e92 2004-04-24 devnull dy = (univ.disp.max.x-univ.disp.min.x)*(q.y - p.y)/(q.x - p.x);
642 e2713e92 2004-04-24 devnull dy -= ylr - yll;
643 e2713e92 2004-04-24 devnull if (dy > 0)
644 e2713e92 2004-04-24 devnull {yll-=dy; yur+=dy;}
645 e2713e92 2004-04-24 devnull else {yul-=dy; ylr+=dy;}
646 e2713e92 2004-04-24 devnull if (ylr > yll) {
647 e2713e92 2004-04-24 devnull univ.disp.min.y = yll;
648 e2713e92 2004-04-24 devnull univ.disp.max.y = yur;
649 e2713e92 2004-04-24 devnull univ.slant_ht = yur - ylr;
650 e2713e92 2004-04-24 devnull } else {
651 e2713e92 2004-04-24 devnull univ.disp.max.y = yul;
652 e2713e92 2004-04-24 devnull univ.disp.min.y = ylr;
653 e2713e92 2004-04-24 devnull univ.slant_ht = ylr - yur;
654 e2713e92 2004-04-24 devnull }
655 e2713e92 2004-04-24 devnull }
656 e2713e92 2004-04-24 devnull
657 e2713e92 2004-04-24 devnull
658 e2713e92 2004-04-24 devnull
659 e2713e92 2004-04-24 devnull
660 e2713e92 2004-04-24 devnull /******************************** Ascii input ********************************/
661 e2713e92 2004-04-24 devnull
662 e2713e92 2004-04-24 devnull void set_fbb(fpolygon* fp)
663 e2713e92 2004-04-24 devnull {
664 e2713e92 2004-04-24 devnull fpoint lo=fp->p[0], hi=fp->p[0];
665 e2713e92 2004-04-24 devnull const fpoint *q, *qtop;
666 e2713e92 2004-04-24 devnull for (qtop=(q=fp->p)+fp->n; ++q<=qtop;) {
667 e2713e92 2004-04-24 devnull if (q->x < lo.x) lo.x=q->x;
668 e2713e92 2004-04-24 devnull if (q->y < lo.y) lo.y=q->y;
669 e2713e92 2004-04-24 devnull if (q->x > hi.x) hi.x=q->x;
670 e2713e92 2004-04-24 devnull if (q->y > hi.y) hi.y=q->y;
671 e2713e92 2004-04-24 devnull }
672 e2713e92 2004-04-24 devnull fp->bb.min = lo;
673 e2713e92 2004-04-24 devnull fp->bb.max = hi;
674 e2713e92 2004-04-24 devnull }
675 e2713e92 2004-04-24 devnull
676 e2713e92 2004-04-24 devnull char* mystrdup(char* s)
677 e2713e92 2004-04-24 devnull {
678 e2713e92 2004-04-24 devnull char *r, *t = strrchr(s,'"');
679 e2713e92 2004-04-24 devnull if (t==0) {
680 e2713e92 2004-04-24 devnull t = s + strlen(s);
681 e2713e92 2004-04-24 devnull while (t>s && (t[-1]=='\n' || t[-1]=='\r'))
682 e2713e92 2004-04-24 devnull t--;
683 e2713e92 2004-04-24 devnull }
684 e2713e92 2004-04-24 devnull r = malloc(1+(t-s));
685 e2713e92 2004-04-24 devnull memcpy(r, s, t-s);
686 e2713e92 2004-04-24 devnull r[t-s] = 0;
687 e2713e92 2004-04-24 devnull return r;
688 e2713e92 2004-04-24 devnull }
689 e2713e92 2004-04-24 devnull
690 e2713e92 2004-04-24 devnull int is_valid_label(char* lab)
691 e2713e92 2004-04-24 devnull {
692 e2713e92 2004-04-24 devnull char* t;
693 e2713e92 2004-04-24 devnull if (lab[0]=='"')
694 e2713e92 2004-04-24 devnull return (t=strrchr(lab,'"'))!=0 && t!=lab && strspn(t+1," \t\r\n")==strlen(t+1);
695 e2713e92 2004-04-24 devnull return strcspn(lab," \t")==strlen(lab);
696 e2713e92 2004-04-24 devnull }
697 e2713e92 2004-04-24 devnull
698 e2713e92 2004-04-24 devnull /* Read a polyline and update the number of lines read. A zero result indicates bad
699 e2713e92 2004-04-24 devnull syntax if *lineno increases; otherwise it indicates end of file.
700 e2713e92 2004-04-24 devnull */
701 e2713e92 2004-04-24 devnull fpolygon* rd_fpoly(FILE* fin, int *lineno)
702 e2713e92 2004-04-24 devnull {
703 7575a9e1 2006-02-14 devnull char buf[1024], junk[2];
704 e2713e92 2004-04-24 devnull fpoint q;
705 e2713e92 2004-04-24 devnull fpolygon* fp;
706 e2713e92 2004-04-24 devnull int allocn;
707 7575a9e1 2006-02-14 devnull if (!fgets(buf,sizeof buf,fin))
708 e2713e92 2004-04-24 devnull return 0;
709 e2713e92 2004-04-24 devnull (*lineno)++;
710 e2713e92 2004-04-24 devnull if (sscanf(buf,"%lg%lg%1s",&q.x,&q.y,junk) != 2)
711 e2713e92 2004-04-24 devnull return 0;
712 e2713e92 2004-04-24 devnull fp = malloc(sizeof(fpolygon));
713 e2713e92 2004-04-24 devnull allocn = 16;
714 e2713e92 2004-04-24 devnull fp->p = malloc(allocn*sizeof(fpoint));
715 e2713e92 2004-04-24 devnull fp->p[0] = q;
716 e2713e92 2004-04-24 devnull fp->n = 0;
717 e2713e92 2004-04-24 devnull fp->nam = "";
718 e2713e92 2004-04-24 devnull fp->thick = 0;
719 e2713e92 2004-04-24 devnull fp->clr = clr_im(DBlack);
720 7575a9e1 2006-02-14 devnull while (fgets(buf,sizeof buf,fin)) {
721 e2713e92 2004-04-24 devnull (*lineno)++;
722 e2713e92 2004-04-24 devnull if (sscanf(buf,"%lg%lg%1s",&q.x,&q.y,junk) != 2) {
723 e2713e92 2004-04-24 devnull if (!is_valid_label(buf))
724 e2713e92 2004-04-24 devnull {free(fp->p); free(fp); return 0;}
725 e2713e92 2004-04-24 devnull fp->nam = (buf[0]=='"') ? buf+1 : buf;
726 e2713e92 2004-04-24 devnull break;
727 e2713e92 2004-04-24 devnull }
728 e2713e92 2004-04-24 devnull if (++(fp->n) == allocn)
729 e2713e92 2004-04-24 devnull fp->p = realloc(fp->p, (allocn<<=1)*sizeof(fpoint));
730 e2713e92 2004-04-24 devnull fp->p[fp->n] = q;
731 e2713e92 2004-04-24 devnull }
732 e2713e92 2004-04-24 devnull fp->nam = mystrdup(fp->nam);
733 e2713e92 2004-04-24 devnull set_fbb(fp);
734 e2713e92 2004-04-24 devnull fp->link = 0;
735 e2713e92 2004-04-24 devnull return fp;
736 e2713e92 2004-04-24 devnull }
737 e2713e92 2004-04-24 devnull
738 e2713e92 2004-04-24 devnull
739 e2713e92 2004-04-24 devnull /* Read input into *fps and return 0 or a line number where there's a syntax error */
740 e2713e92 2004-04-24 devnull int rd_fpolys(FILE* fin, fpolygons* fps)
741 e2713e92 2004-04-24 devnull {
742 e2713e92 2004-04-24 devnull fpolygon *fp, *fp0=fps->p;
743 e2713e92 2004-04-24 devnull int lineno=0, ok_upto=0;
744 e2713e92 2004-04-24 devnull while ((fp=rd_fpoly(fin,&lineno)) != 0) {
745 e2713e92 2004-04-24 devnull ok_upto = lineno;
746 e2713e92 2004-04-24 devnull fp->link = fps->p;
747 e2713e92 2004-04-24 devnull fps->p = fp;
748 e2713e92 2004-04-24 devnull grow_bb(&fps->bb, &fp->bb);
749 e2713e92 2004-04-24 devnull }
750 e2713e92 2004-04-24 devnull set_default_clrs(fps, fp0);
751 e2713e92 2004-04-24 devnull return (ok_upto==lineno) ? 0 : lineno;
752 e2713e92 2004-04-24 devnull }
753 e2713e92 2004-04-24 devnull
754 e2713e92 2004-04-24 devnull
755 e2713e92 2004-04-24 devnull /* Read input from file fnam and return an error line no., -1 for "can't open"
756 e2713e92 2004-04-24 devnull or 0 for success.
757 e2713e92 2004-04-24 devnull */
758 e2713e92 2004-04-24 devnull int doinput(char* fnam)
759 e2713e92 2004-04-24 devnull {
760 e2713e92 2004-04-24 devnull FILE* fin = strcmp(fnam,"-")==0 ? stdin : fopen(fnam, "r");
761 e2713e92 2004-04-24 devnull int errline_or0;
762 e2713e92 2004-04-24 devnull if (fin==0)
763 e2713e92 2004-04-24 devnull return -1;
764 e2713e92 2004-04-24 devnull errline_or0 = rd_fpolys(fin, &univ);
765 e2713e92 2004-04-24 devnull fclose(fin);
766 e2713e92 2004-04-24 devnull return errline_or0;
767 e2713e92 2004-04-24 devnull }
768 e2713e92 2004-04-24 devnull
769 e2713e92 2004-04-24 devnull
770 e2713e92 2004-04-24 devnull
771 e2713e92 2004-04-24 devnull /******************************** Ascii output ********************************/
772 e2713e92 2004-04-24 devnull
773 e2713e92 2004-04-24 devnull fpolygon* fp_reverse(fpolygon* fp)
774 e2713e92 2004-04-24 devnull {
775 e2713e92 2004-04-24 devnull fpolygon* r = 0;
776 e2713e92 2004-04-24 devnull while (fp!=0) {
777 e2713e92 2004-04-24 devnull fpolygon* q = fp->link;
778 e2713e92 2004-04-24 devnull fp->link = r;
779 e2713e92 2004-04-24 devnull r = fp;
780 e2713e92 2004-04-24 devnull fp = q;
781 e2713e92 2004-04-24 devnull }
782 e2713e92 2004-04-24 devnull return r;
783 e2713e92 2004-04-24 devnull }
784 e2713e92 2004-04-24 devnull
785 e2713e92 2004-04-24 devnull void wr_fpoly(FILE* fout, const fpolygon* fp)
786 e2713e92 2004-04-24 devnull {
787 7575a9e1 2006-02-14 devnull char buf[1024];
788 e2713e92 2004-04-24 devnull int i;
789 e2713e92 2004-04-24 devnull for (i=0; i<=fp->n; i++)
790 e2713e92 2004-04-24 devnull fprintf(fout,"%.12g\t%.12g\n", fp->p[i].x, fp->p[i].y);
791 e2713e92 2004-04-24 devnull fprintf(fout,"\"%s\"\n", nam_with_thclr(fp->nam, fp->thick, fp->clr, buf, 256));
792 e2713e92 2004-04-24 devnull }
793 e2713e92 2004-04-24 devnull
794 e2713e92 2004-04-24 devnull void wr_fpolys(FILE* fout, fpolygons* fps)
795 e2713e92 2004-04-24 devnull {
796 e2713e92 2004-04-24 devnull fpolygon* fp;
797 e2713e92 2004-04-24 devnull fps->p = fp_reverse(fps->p);
798 e2713e92 2004-04-24 devnull for (fp=fps->p; fp!=0; fp=fp->link)
799 e2713e92 2004-04-24 devnull wr_fpoly(fout, fp);
800 e2713e92 2004-04-24 devnull fps->p = fp_reverse(fps->p);
801 e2713e92 2004-04-24 devnull }
802 e2713e92 2004-04-24 devnull
803 e2713e92 2004-04-24 devnull
804 e2713e92 2004-04-24 devnull int dooutput(char* fnam)
805 e2713e92 2004-04-24 devnull {
806 e2713e92 2004-04-24 devnull FILE* fout = fopen(fnam, "w");
807 e2713e92 2004-04-24 devnull if (fout==0)
808 e2713e92 2004-04-24 devnull return 0;
809 e2713e92 2004-04-24 devnull wr_fpolys(fout, &univ);
810 e2713e92 2004-04-24 devnull fclose(fout);
811 e2713e92 2004-04-24 devnull return 1;
812 e2713e92 2004-04-24 devnull }
813 e2713e92 2004-04-24 devnull
814 e2713e92 2004-04-24 devnull
815 e2713e92 2004-04-24 devnull
816 e2713e92 2004-04-24 devnull
817 e2713e92 2004-04-24 devnull /************************ Clipping to screen rectangle ************************/
818 e2713e92 2004-04-24 devnull
819 e2713e92 2004-04-24 devnull /* Find the t values, 0<=t<=1 for which x0+t*(x1-x0) is between xlo and xhi,
820 e2713e92 2004-04-24 devnull or return 0 to indicate no such t values exist. If returning 1, set *t0 and
821 e2713e92 2004-04-24 devnull *t1 to delimit the t interval.
822 e2713e92 2004-04-24 devnull */
823 e2713e92 2004-04-24 devnull int do_xory(double x0, double x1, double xlo, double xhi, double* t0, double* t1)
824 e2713e92 2004-04-24 devnull {
825 e2713e92 2004-04-24 devnull *t1 = 1.0;
826 e2713e92 2004-04-24 devnull if (x0<xlo) {
827 e2713e92 2004-04-24 devnull if (x1<xlo) return 0;
828 e2713e92 2004-04-24 devnull *t0 = (xlo-x0)/(x1-x0);
829 e2713e92 2004-04-24 devnull if (x1>xhi) *t1 = (xhi-x0)/(x1-x0);
830 e2713e92 2004-04-24 devnull } else if (x0>xhi) {
831 e2713e92 2004-04-24 devnull if (x1>xhi) return 0;
832 e2713e92 2004-04-24 devnull *t0 = (xhi-x0)/(x1-x0);
833 e2713e92 2004-04-24 devnull if (x1<xlo) *t1 = (xlo-x0)/(x1-x0);
834 e2713e92 2004-04-24 devnull } else {
835 e2713e92 2004-04-24 devnull *t0 = 0.0;
836 e2713e92 2004-04-24 devnull if (x1>xhi) *t1 = (xhi-x0)/(x1-x0);
837 e2713e92 2004-04-24 devnull else if (x1<xlo) *t1 = (xlo-x0)/(x1-x0);
838 e2713e92 2004-04-24 devnull else *t1 = 1.0;
839 e2713e92 2004-04-24 devnull }
840 e2713e92 2004-04-24 devnull return 1;
841 e2713e92 2004-04-24 devnull }
842 e2713e92 2004-04-24 devnull
843 e2713e92 2004-04-24 devnull
844 e2713e92 2004-04-24 devnull /* After mapping y to y-slope*x, what initial fraction of the *p to *q edge is
845 e2713e92 2004-04-24 devnull outside of *r? Note that the edge could start outside *r, pass through *r,
846 e2713e92 2004-04-24 devnull and wind up outside again.
847 e2713e92 2004-04-24 devnull */
848 e2713e92 2004-04-24 devnull double frac_outside(const fpoint* p, const fpoint* q, const frectangle* r,
849 e2713e92 2004-04-24 devnull double slope)
850 e2713e92 2004-04-24 devnull {
851 e2713e92 2004-04-24 devnull double t0, t1, tt0, tt1;
852 e2713e92 2004-04-24 devnull double px=p->x, qx=q->x;
853 e2713e92 2004-04-24 devnull if (!do_xory(px, qx, r->min.x, r->max.x, &t0, &t1))
854 e2713e92 2004-04-24 devnull return 1;
855 e2713e92 2004-04-24 devnull if (!do_xory(p->y-slope*px, q->y-slope*qx, r->min.y, r->max.y, &tt0, &tt1))
856 e2713e92 2004-04-24 devnull return 1;
857 e2713e92 2004-04-24 devnull if (tt0 > t0)
858 e2713e92 2004-04-24 devnull t0 = tt0;
859 e2713e92 2004-04-24 devnull if (t1<=t0 || tt1<=t0)
860 e2713e92 2004-04-24 devnull return 1;
861 e2713e92 2004-04-24 devnull return t0;
862 e2713e92 2004-04-24 devnull }
863 e2713e92 2004-04-24 devnull
864 e2713e92 2004-04-24 devnull
865 e2713e92 2004-04-24 devnull /* Think of p0..pn as piecewise-linear function F(t) for t=0..pn-p0, and find
866 e2713e92 2004-04-24 devnull the maximum tt such that F(0..tt) is all inside of r, assuming p0 is inside.
867 e2713e92 2004-04-24 devnull Coordinates are transformed by y=y-x*slope before testing against r.
868 e2713e92 2004-04-24 devnull */
869 e2713e92 2004-04-24 devnull double in_length(const fpoint* p0, const fpoint* pn, frectangle r, double slope)
870 e2713e92 2004-04-24 devnull {
871 e2713e92 2004-04-24 devnull const fpoint* p = p0;
872 e2713e92 2004-04-24 devnull double px, py;
873 e2713e92 2004-04-24 devnull do if (++p > pn)
874 e2713e92 2004-04-24 devnull return pn - p0;
875 e2713e92 2004-04-24 devnull while (r.min.x<=(px=p->x) && px<=r.max.x
876 e2713e92 2004-04-24 devnull && r.min.y<=(py=p->y-slope*px) && py<=r.max.y);
877 e2713e92 2004-04-24 devnull return (p - p0) - frac_outside(p, p-1, &r, slope);
878 e2713e92 2004-04-24 devnull }
879 e2713e92 2004-04-24 devnull
880 e2713e92 2004-04-24 devnull
881 e2713e92 2004-04-24 devnull /* Think of p0..pn as piecewise-linear function F(t) for t=0..pn-p0, and find
882 e2713e92 2004-04-24 devnull the maximum tt such that F(0..tt) is all outside of *r. Coordinates are
883 e2713e92 2004-04-24 devnull transformed by y=y-x*slope before testing against r.
884 e2713e92 2004-04-24 devnull */
885 e2713e92 2004-04-24 devnull double out_length(const fpoint* p0, const fpoint* pn, frectangle r, double slope)
886 e2713e92 2004-04-24 devnull {
887 e2713e92 2004-04-24 devnull const fpoint* p = p0;
888 e2713e92 2004-04-24 devnull double fr;
889 e2713e92 2004-04-24 devnull do { if (p->x < r.min.x)
890 e2713e92 2004-04-24 devnull do if (++p>pn) return pn-p0;
891 e2713e92 2004-04-24 devnull while (p->x <= r.min.x);
892 e2713e92 2004-04-24 devnull else if (p->x > r.max.x)
893 e2713e92 2004-04-24 devnull do if (++p>pn) return pn-p0;
894 e2713e92 2004-04-24 devnull while (p->x >= r.max.x);
895 e2713e92 2004-04-24 devnull else if (p->y-slope*p->x < r.min.y)
896 e2713e92 2004-04-24 devnull do if (++p>pn) return pn-p0;
897 e2713e92 2004-04-24 devnull while (p->y-slope*p->x <= r.min.y);
898 e2713e92 2004-04-24 devnull else if (p->y-slope*p->x > r.max.y)
899 e2713e92 2004-04-24 devnull do if (++p>pn) return pn-p0;
900 e2713e92 2004-04-24 devnull while (p->y-slope*p->x >= r.max.y);
901 e2713e92 2004-04-24 devnull else return p - p0;
902 e2713e92 2004-04-24 devnull } while ((fr=frac_outside(p-1,p,&r,slope)) == 1);
903 e2713e92 2004-04-24 devnull return (p - p0) + fr-1;
904 e2713e92 2004-04-24 devnull }
905 e2713e92 2004-04-24 devnull
906 e2713e92 2004-04-24 devnull
907 e2713e92 2004-04-24 devnull
908 e2713e92 2004-04-24 devnull /*********************** Drawing frame and axis labels ***********************/
909 e2713e92 2004-04-24 devnull
910 e2713e92 2004-04-24 devnull #define Nthous 7
911 e2713e92 2004-04-24 devnull #define Len_thous 30 /* bound on strlen(thous_nam[i]) */
912 e2713e92 2004-04-24 devnull char* thous_nam[Nthous] = {
913 e2713e92 2004-04-24 devnull "one", "thousand", "million", "billion",
914 e2713e92 2004-04-24 devnull "trillion", "quadrillion", "quintillion",
915 e2713e92 2004-04-24 devnull };
916 e2713e92 2004-04-24 devnull
917 e2713e92 2004-04-24 devnull
918 e2713e92 2004-04-24 devnull typedef struct lab_interval {
919 e2713e92 2004-04-24 devnull double sep; /* separation between tick marks */
920 e2713e92 2004-04-24 devnull double unit; /* power of 1000 divisor */
921 e2713e92 2004-04-24 devnull int logunit; /* log base 1000 of of this divisor */
922 e2713e92 2004-04-24 devnull double off; /* offset to subtract before dividing */
923 e2713e92 2004-04-24 devnull } lab_interval;
924 e2713e92 2004-04-24 devnull
925 e2713e92 2004-04-24 devnull
926 e2713e92 2004-04-24 devnull char* abbrev_num(double x, const lab_interval* iv)
927 e2713e92 2004-04-24 devnull {
928 e2713e92 2004-04-24 devnull static char buf[16];
929 e2713e92 2004-04-24 devnull double dx = x - iv->off;
930 e2713e92 2004-04-24 devnull dx = iv->sep * floor(dx/iv->sep + .5);
931 e2713e92 2004-04-24 devnull sprintf(buf,"%g", dx/iv->unit);
932 e2713e92 2004-04-24 devnull return buf;
933 e2713e92 2004-04-24 devnull }
934 e2713e92 2004-04-24 devnull
935 e2713e92 2004-04-24 devnull
936 e2713e92 2004-04-24 devnull double lead_digits(double n, double r) /* n truncated to power of 10 above r */
937 e2713e92 2004-04-24 devnull {
938 e2713e92 2004-04-24 devnull double rr = pow(10, ceil(log10(r)));
939 e2713e92 2004-04-24 devnull double nn = (n<rr) ? 0.0 : rr*floor(n/rr);
940 e2713e92 2004-04-24 devnull if (n+r-nn >= digs10pow) {
941 e2713e92 2004-04-24 devnull rr /= 10;
942 e2713e92 2004-04-24 devnull nn = (n<rr) ? 0.0 : rr*floor(n/rr);
943 e2713e92 2004-04-24 devnull }
944 e2713e92 2004-04-24 devnull return nn;
945 e2713e92 2004-04-24 devnull }
946 e2713e92 2004-04-24 devnull
947 e2713e92 2004-04-24 devnull
948 e2713e92 2004-04-24 devnull lab_interval next_larger(double s0, double xlo, double xhi)
949 e2713e92 2004-04-24 devnull {
950 e2713e92 2004-04-24 devnull double nlo, nhi;
951 e2713e92 2004-04-24 devnull lab_interval r;
952 e2713e92 2004-04-24 devnull r.logunit = (int) floor(log10(s0) + LOG2);
953 e2713e92 2004-04-24 devnull r.unit = pow(10, r.logunit);
954 e2713e92 2004-04-24 devnull nlo = xlo/r.unit;
955 e2713e92 2004-04-24 devnull nhi = xhi/r.unit;
956 e2713e92 2004-04-24 devnull if (nhi >= digs10pow)
957 e2713e92 2004-04-24 devnull r.off = r.unit*lead_digits(nlo, nhi-nlo);
958 e2713e92 2004-04-24 devnull else if (nlo <= -digs10pow)
959 e2713e92 2004-04-24 devnull r.off = -r.unit*lead_digits(-nhi, nhi-nlo);
960 e2713e92 2004-04-24 devnull else r.off = 0;
961 e2713e92 2004-04-24 devnull r.sep = (s0<=r.unit) ? r.unit : (s0<2*r.unit ? 2*r.unit : 5*r.unit);
962 e2713e92 2004-04-24 devnull switch (r.logunit%3) {
963 e2713e92 2004-04-24 devnull case 1: r.unit*=.1; r.logunit--;
964 e2713e92 2004-04-24 devnull break;
965 e2713e92 2004-04-24 devnull case -1: case 2:
966 e2713e92 2004-04-24 devnull r.unit*=10; r.logunit++;
967 e2713e92 2004-04-24 devnull break;
968 e2713e92 2004-04-24 devnull case -2: r.unit*=100; r.logunit+=2;
969 e2713e92 2004-04-24 devnull }
970 e2713e92 2004-04-24 devnull r.logunit /= 3;
971 e2713e92 2004-04-24 devnull return r;
972 e2713e92 2004-04-24 devnull }
973 e2713e92 2004-04-24 devnull
974 e2713e92 2004-04-24 devnull
975 e2713e92 2004-04-24 devnull double min_hsep(const transform* tr)
976 e2713e92 2004-04-24 devnull {
977 e2713e92 2004-04-24 devnull double s = (2+labdigs)*sdigit.x;
978 e2713e92 2004-04-24 devnull double ss = (univ.disp.min.x<0) ? s+sdigit.x : s;
979 e2713e92 2004-04-24 devnull return dxuntransform(tr, ss);
980 e2713e92 2004-04-24 devnull }
981 e2713e92 2004-04-24 devnull
982 e2713e92 2004-04-24 devnull
983 e2713e92 2004-04-24 devnull lab_interval mark_x_axis(const transform* tr)
984 e2713e92 2004-04-24 devnull {
985 e2713e92 2004-04-24 devnull fpoint p = univ.disp.min;
986 e2713e92 2004-04-24 devnull Point q, qtop, qbot, tmp;
987 e2713e92 2004-04-24 devnull double x0=univ.disp.min.x, x1=univ.disp.max.x;
988 e2713e92 2004-04-24 devnull double seps0, nseps, seps;
989 e2713e92 2004-04-24 devnull lab_interval iv = next_larger(min_hsep(tr), x0, x1);
990 e2713e92 2004-04-24 devnull set_unslanted_y(&univ, &p.y, 0);
991 e2713e92 2004-04-24 devnull q.y = ytransform(tr, p.y) + .5;
992 e2713e92 2004-04-24 devnull qtop.y = q.y - tick_len;
993 e2713e92 2004-04-24 devnull qbot.y = q.y + framewd + framesep;
994 e2713e92 2004-04-24 devnull seps0 = ceil(x0/iv.sep);
995 e2713e92 2004-04-24 devnull for (seps=0, nseps=floor(x1/iv.sep)-seps0; seps<=nseps; seps+=1) {
996 e2713e92 2004-04-24 devnull char* num = abbrev_num((p.x=iv.sep*(seps0+seps)), &iv);
997 e2713e92 2004-04-24 devnull Font* f = display->defaultfont;
998 e2713e92 2004-04-24 devnull q.x = qtop.x = qbot.x = xtransform(tr, p.x);
999 e2713e92 2004-04-24 devnull line(screen, qtop, q, Enddisc, Enddisc, 0, axis_color, q);
1000 e2713e92 2004-04-24 devnull tmp = stringsize(f, num);
1001 e2713e92 2004-04-24 devnull qbot.x -= tmp.x/2;
1002 e2713e92 2004-04-24 devnull string(screen, qbot, display->black, qbot, f, num);
1003 e2713e92 2004-04-24 devnull }
1004 e2713e92 2004-04-24 devnull return iv;
1005 e2713e92 2004-04-24 devnull }
1006 e2713e92 2004-04-24 devnull
1007 e2713e92 2004-04-24 devnull
1008 e2713e92 2004-04-24 devnull lab_interval mark_y_axis(const transform* tr)
1009 e2713e92 2004-04-24 devnull {
1010 e2713e92 2004-04-24 devnull Font* f = display->defaultfont;
1011 e2713e92 2004-04-24 devnull fpoint p = univ.disp.min;
1012 e2713e92 2004-04-24 devnull Point q, qrt, qlft;
1013 e2713e92 2004-04-24 devnull double y0, y1, seps0, nseps, seps;
1014 e2713e92 2004-04-24 devnull lab_interval iv;
1015 e2713e92 2004-04-24 devnull set_unslanted_y(&univ, &y0, &y1);
1016 e2713e92 2004-04-24 devnull iv = next_larger(dyuntransform(tr,-f->height), y0, y1);
1017 e2713e92 2004-04-24 devnull q.x = xtransform(tr, p.x) - .5;
1018 e2713e92 2004-04-24 devnull qrt.x = q.x + tick_len;
1019 e2713e92 2004-04-24 devnull qlft.x = q.x - (framewd + framesep);
1020 e2713e92 2004-04-24 devnull seps0 = ceil(y0/iv.sep);
1021 e2713e92 2004-04-24 devnull for (seps=0, nseps=floor(y1/iv.sep)-seps0; seps<=nseps; seps+=1) {
1022 e2713e92 2004-04-24 devnull char* num = abbrev_num((p.y=iv.sep*(seps0+seps)), &iv);
1023 e2713e92 2004-04-24 devnull Point qq = stringsize(f, num);
1024 e2713e92 2004-04-24 devnull q.y = qrt.y = qlft.y = ytransform(tr, p.y);
1025 e2713e92 2004-04-24 devnull line(screen, qrt, q, Enddisc, Enddisc, 0, axis_color, q);
1026 e2713e92 2004-04-24 devnull qq.x = qlft.x - qq.x;
1027 e2713e92 2004-04-24 devnull qq.y = qlft.y - qq.y/2;
1028 e2713e92 2004-04-24 devnull string(screen, qq, display->black, qq, f, num);
1029 e2713e92 2004-04-24 devnull }
1030 e2713e92 2004-04-24 devnull return iv;
1031 e2713e92 2004-04-24 devnull }
1032 e2713e92 2004-04-24 devnull
1033 e2713e92 2004-04-24 devnull
1034 e2713e92 2004-04-24 devnull void lab_iv_info(const lab_interval *iv, double slant, char* buf, int *n)
1035 e2713e92 2004-04-24 devnull {
1036 e2713e92 2004-04-24 devnull if (iv->off > 0)
1037 e2713e92 2004-04-24 devnull (*n) += sprintf(buf+*n,"-%.12g",iv->off);
1038 e2713e92 2004-04-24 devnull else if (iv->off < 0)
1039 e2713e92 2004-04-24 devnull (*n) += sprintf(buf+*n,"+%.12g",-iv->off);
1040 e2713e92 2004-04-24 devnull if (slant>0)
1041 e2713e92 2004-04-24 devnull (*n) += sprintf(buf+*n,"-%.6gx", slant);
1042 e2713e92 2004-04-24 devnull else if (slant<0)
1043 e2713e92 2004-04-24 devnull (*n) += sprintf(buf+*n,"+%.6gx", -slant);
1044 e2713e92 2004-04-24 devnull if (abs(iv->logunit) >= Nthous)
1045 e2713e92 2004-04-24 devnull (*n) += sprintf(buf+*n," in 1e%d units", 3*iv->logunit);
1046 e2713e92 2004-04-24 devnull else if (iv->logunit > 0)
1047 e2713e92 2004-04-24 devnull (*n) += sprintf(buf+*n," in %ss", thous_nam[iv->logunit]);
1048 e2713e92 2004-04-24 devnull else if (iv->logunit < 0)
1049 e2713e92 2004-04-24 devnull (*n) += sprintf(buf+*n," in %sths", thous_nam[-iv->logunit]);
1050 e2713e92 2004-04-24 devnull }
1051 e2713e92 2004-04-24 devnull
1052 e2713e92 2004-04-24 devnull
1053 e2713e92 2004-04-24 devnull void draw_xy_ranges(const lab_interval *xiv, const lab_interval *yiv)
1054 e2713e92 2004-04-24 devnull {
1055 e2713e92 2004-04-24 devnull Point p;
1056 e2713e92 2004-04-24 devnull char buf[2*(19+Len_thous+8)+50];
1057 e2713e92 2004-04-24 devnull int bufn = 0;
1058 e2713e92 2004-04-24 devnull buf[bufn++] = 'x';
1059 e2713e92 2004-04-24 devnull lab_iv_info(xiv, 0, buf, &bufn);
1060 e2713e92 2004-04-24 devnull bufn += sprintf(buf+bufn, "; y");
1061 e2713e92 2004-04-24 devnull lab_iv_info(yiv, u_slant_amt(&univ), buf, &bufn);
1062 e2713e92 2004-04-24 devnull buf[bufn] = '\0';
1063 e2713e92 2004-04-24 devnull p = stringsize(display->defaultfont, buf);
1064 e2713e92 2004-04-24 devnull top_left = screen->r.min.x + lft_border;
1065 e2713e92 2004-04-24 devnull p.x = top_right = screen->r.max.x - rt_border - p.x;
1066 e2713e92 2004-04-24 devnull p.y = screen->r.min.y + outersep;
1067 e2713e92 2004-04-24 devnull string(screen, p, display->black, p, display->defaultfont, buf);
1068 e2713e92 2004-04-24 devnull }
1069 e2713e92 2004-04-24 devnull
1070 e2713e92 2004-04-24 devnull
1071 e2713e92 2004-04-24 devnull transform draw_frame(void)
1072 e2713e92 2004-04-24 devnull {
1073 e2713e92 2004-04-24 devnull lab_interval x_iv, y_iv;
1074 e2713e92 2004-04-24 devnull transform tr;
1075 e2713e92 2004-04-24 devnull Rectangle r = screen->r;
1076 e2713e92 2004-04-24 devnull lft_border = (univ.disp.min.y<0) ? lft_border0+sdigit.x : lft_border0;
1077 e2713e92 2004-04-24 devnull tr = cur_trans();
1078 e2713e92 2004-04-24 devnull r.min.x += lft_border;
1079 e2713e92 2004-04-24 devnull r.min.y += top_border;
1080 e2713e92 2004-04-24 devnull r.max.x -= rt_border;
1081 e2713e92 2004-04-24 devnull r.max.y -= bot_border;
1082 e2713e92 2004-04-24 devnull border(screen, r, -framewd, axis_color, r.min);
1083 e2713e92 2004-04-24 devnull x_iv = mark_x_axis(&tr);
1084 e2713e92 2004-04-24 devnull y_iv = mark_y_axis(&tr);
1085 e2713e92 2004-04-24 devnull draw_xy_ranges(&x_iv, &y_iv);
1086 e2713e92 2004-04-24 devnull return tr;
1087 e2713e92 2004-04-24 devnull }
1088 e2713e92 2004-04-24 devnull
1089 e2713e92 2004-04-24 devnull
1090 e2713e92 2004-04-24 devnull
1091 e2713e92 2004-04-24 devnull /*************************** Finding the selection ***************************/
1092 e2713e92 2004-04-24 devnull
1093 e2713e92 2004-04-24 devnull typedef struct pt_on_fpoly {
1094 e2713e92 2004-04-24 devnull fpoint p; /* the point */
1095 e2713e92 2004-04-24 devnull fpolygon* fp; /* the fpolygon it lies on */
1096 e2713e92 2004-04-24 devnull double t; /* how many knots from the beginning */
1097 e2713e92 2004-04-24 devnull } pt_on_fpoly;
1098 e2713e92 2004-04-24 devnull
1099 e2713e92 2004-04-24 devnull
1100 e2713e92 2004-04-24 devnull static double myx, myy;
1101 e2713e92 2004-04-24 devnull #define mydist(p,o,sl,xwt,ywt) (myx=(p).x-(o).x, myy=(p).y-sl*(p).x-(o).y, \
1102 e2713e92 2004-04-24 devnull xwt*myx*myx + ywt*myy*myy)
1103 e2713e92 2004-04-24 devnull
1104 e2713e92 2004-04-24 devnull /* At what fraction of the way from p0[0] to p0[1] is mydist(p,ctr,slant,xwt,ywt)
1105 e2713e92 2004-04-24 devnull minimized?
1106 e2713e92 2004-04-24 devnull */
1107 e2713e92 2004-04-24 devnull double closest_time(const fpoint* p0, const fpoint* ctr, double slant,
1108 e2713e92 2004-04-24 devnull double xwt, double ywt)
1109 e2713e92 2004-04-24 devnull {
1110 e2713e92 2004-04-24 devnull double p00y=p0[0].y-slant*p0[0].x, p01y=p0[1].y-slant*p0[1].x;
1111 e2713e92 2004-04-24 devnull double dx=p0[1].x-p0[0].x, dy=p01y-p00y;
1112 e2713e92 2004-04-24 devnull double x0=p0[0].x-ctr->x, y0=p00y-ctr->y;
1113 e2713e92 2004-04-24 devnull double bot = xwt*dx*dx + ywt*dy*dy;
1114 e2713e92 2004-04-24 devnull if (bot==0)
1115 e2713e92 2004-04-24 devnull return 0;
1116 e2713e92 2004-04-24 devnull return -(xwt*x0*dx + ywt*y0*dy)/bot;
1117 e2713e92 2004-04-24 devnull }
1118 e2713e92 2004-04-24 devnull
1119 e2713e92 2004-04-24 devnull
1120 e2713e92 2004-04-24 devnull /* Scan the polygonal path of length len knots starting at p0, and find the
1121 e2713e92 2004-04-24 devnull point that the transformation y=y-x*slant makes closest to the center of *r,
1122 e2713e92 2004-04-24 devnull where *r itself defines the distance metric. Knots get higher priority than
1123 e2713e92 2004-04-24 devnull points between knots. If psel->t is negative, always update *psel; otherwise
1124 e2713e92 2004-04-24 devnull update *psel only if the scan can improve it. Return a boolean that says
1125 e2713e92 2004-04-24 devnull whether *psel was updated.
1126 e2713e92 2004-04-24 devnull Note that *r is a very tiny rectangle (tiny when converted screen pixels)
1127 e2713e92 2004-04-24 devnull such that anything in *r is considered close enough to match the mouse click.
1128 e2713e92 2004-04-24 devnull The purpose of this routine is to be careful in case there is a lot of hidden
1129 e2713e92 2004-04-24 devnull detail in the tiny rectangle *r.
1130 e2713e92 2004-04-24 devnull */
1131 e2713e92 2004-04-24 devnull int improve_pt(fpoint* p0, double len, const frectangle* r, double slant,
1132 e2713e92 2004-04-24 devnull pt_on_fpoly* psel)
1133 e2713e92 2004-04-24 devnull {
1134 e2713e92 2004-04-24 devnull fpoint ctr = fcenter(r);
1135 e2713e92 2004-04-24 devnull double x_wt=2/(r->max.x-r->min.x), y_wt=2/(r->max.y-r->min.y);
1136 e2713e92 2004-04-24 devnull double xwt=x_wt*x_wt, ywt=y_wt*y_wt;
1137 e2713e92 2004-04-24 devnull double d, dbest = (psel->t <0) ? 1e30 : mydist(psel->p,ctr,slant,xwt,ywt);
1138 e2713e92 2004-04-24 devnull double tt, dbest0 = dbest;
1139 e2713e92 2004-04-24 devnull fpoint pp;
1140 e2713e92 2004-04-24 devnull int ilen = (int) len;
1141 e2713e92 2004-04-24 devnull if (len==0 || ilen>0) {
1142 e2713e92 2004-04-24 devnull int i;
1143 e2713e92 2004-04-24 devnull for (i=(len==0 ? 0 : 1); i<=ilen; i++) {
1144 e2713e92 2004-04-24 devnull d = mydist(p0[i], ctr, slant, xwt, ywt);
1145 e2713e92 2004-04-24 devnull if (d < dbest)
1146 e2713e92 2004-04-24 devnull {psel->p=p0[i]; psel->t=i; dbest=d;}
1147 e2713e92 2004-04-24 devnull }
1148 e2713e92 2004-04-24 devnull return (dbest < dbest0);
1149 e2713e92 2004-04-24 devnull }
1150 e2713e92 2004-04-24 devnull tt = closest_time(p0, &ctr, slant, xwt, ywt);
1151 e2713e92 2004-04-24 devnull if (tt > len)
1152 e2713e92 2004-04-24 devnull tt = len;
1153 e2713e92 2004-04-24 devnull pp.x = p0[0].x + tt*(p0[1].x - p0[0].x);
1154 e2713e92 2004-04-24 devnull pp.y = p0[0].y + tt*(p0[1].y - p0[0].y);
1155 e2713e92 2004-04-24 devnull if (mydist(pp, ctr, slant, xwt, ywt) < dbest) {
1156 e2713e92 2004-04-24 devnull psel->p = pp;
1157 e2713e92 2004-04-24 devnull psel->t = tt;
1158 e2713e92 2004-04-24 devnull return 1;
1159 e2713e92 2004-04-24 devnull }
1160 e2713e92 2004-04-24 devnull return 0;
1161 e2713e92 2004-04-24 devnull }
1162 e2713e92 2004-04-24 devnull
1163 e2713e92 2004-04-24 devnull
1164 e2713e92 2004-04-24 devnull /* Test *fp against *r after transforming by y=y-x*slope, and set *psel accordingly.
1165 e2713e92 2004-04-24 devnull */
1166 e2713e92 2004-04-24 devnull void select_in_fpoly(fpolygon* fp, const frectangle* r, double slant,
1167 e2713e92 2004-04-24 devnull pt_on_fpoly* psel)
1168 e2713e92 2004-04-24 devnull {
1169 e2713e92 2004-04-24 devnull fpoint *p0=fp->p, *pn=fp->p+fp->n;
1170 e2713e92 2004-04-24 devnull double l1, l2;
1171 e2713e92 2004-04-24 devnull if (p0==pn)
1172 e2713e92 2004-04-24 devnull {improve_pt(p0, 0, r, slant, psel); psel->fp=fp; return;}
1173 e2713e92 2004-04-24 devnull while ((l1=out_length(p0,pn,*r,slant)) < pn-p0) {
1174 e2713e92 2004-04-24 devnull fpoint p0sav;
1175 e2713e92 2004-04-24 devnull int i1 = (int) l1;
1176 e2713e92 2004-04-24 devnull p0+=i1; l1-=i1;
1177 e2713e92 2004-04-24 devnull p0sav = *p0;
1178 e2713e92 2004-04-24 devnull p0[0].x += l1*(p0[1].x - p0[0].x);
1179 e2713e92 2004-04-24 devnull p0[0].y += l1*(p0[1].y - p0[0].y);
1180 e2713e92 2004-04-24 devnull l2 = in_length(p0, pn, *r, slant);
1181 e2713e92 2004-04-24 devnull if (improve_pt(p0, l2, r, slant, psel)) {
1182 e2713e92 2004-04-24 devnull if (l1==0 && psel->t!=((int) psel->t)) {
1183 e2713e92 2004-04-24 devnull psel->t = 0;
1184 e2713e92 2004-04-24 devnull psel->p = *p0;
1185 e2713e92 2004-04-24 devnull } else if (psel->t < 1)
1186 e2713e92 2004-04-24 devnull psel->t += l1*(1 - psel->t);
1187 e2713e92 2004-04-24 devnull psel->t += p0 - fp->p;
1188 e2713e92 2004-04-24 devnull psel->fp = fp;
1189 e2713e92 2004-04-24 devnull }
1190 e2713e92 2004-04-24 devnull *p0 = p0sav;
1191 e2713e92 2004-04-24 devnull p0 += (l2>0) ? ((int) ceil(l2)) : 1;
1192 e2713e92 2004-04-24 devnull }
1193 e2713e92 2004-04-24 devnull }
1194 e2713e92 2004-04-24 devnull
1195 e2713e92 2004-04-24 devnull
1196 e2713e92 2004-04-24 devnull /* Test all the fpolygons against *r after transforming by y=y-x*slope, and return
1197 e2713e92 2004-04-24 devnull the resulting selection, if any.
1198 e2713e92 2004-04-24 devnull */
1199 e2713e92 2004-04-24 devnull pt_on_fpoly* select_in_univ(const frectangle* r, double slant)
1200 e2713e92 2004-04-24 devnull {
1201 e2713e92 2004-04-24 devnull static pt_on_fpoly answ;
1202 e2713e92 2004-04-24 devnull fpolygon* fp;
1203 e2713e92 2004-04-24 devnull answ.t = -1;
1204 e2713e92 2004-04-24 devnull for (fp=univ.p; fp!=0; fp=fp->link)
1205 e2713e92 2004-04-24 devnull if (fintersects(r, &fp->bb, slant))
1206 e2713e92 2004-04-24 devnull select_in_fpoly(fp, r, slant, &answ);
1207 e2713e92 2004-04-24 devnull if (answ.t < 0)
1208 e2713e92 2004-04-24 devnull return 0;
1209 e2713e92 2004-04-24 devnull return &answ;
1210 e2713e92 2004-04-24 devnull }
1211 e2713e92 2004-04-24 devnull
1212 e2713e92 2004-04-24 devnull
1213 e2713e92 2004-04-24 devnull
1214 e2713e92 2004-04-24 devnull /**************************** Using the selection ****************************/
1215 e2713e92 2004-04-24 devnull
1216 e2713e92 2004-04-24 devnull pt_on_fpoly cur_sel; /* current selection if cur_sel.t>=0 */
1217 e2713e92 2004-04-24 devnull pt_on_fpoly prev_sel; /* previous selection if prev_sel.t>=0 (for slant) */
1218 e2713e92 2004-04-24 devnull Image* sel_bkg = 0; /* what's behind the red dot */
1219 e2713e92 2004-04-24 devnull
1220 e2713e92 2004-04-24 devnull
1221 e2713e92 2004-04-24 devnull void clear_txt(void)
1222 e2713e92 2004-04-24 devnull {
1223 e2713e92 2004-04-24 devnull Rectangle r;
1224 e2713e92 2004-04-24 devnull r.min = screen->r.min;
1225 e2713e92 2004-04-24 devnull r.min.x += lft_border;
1226 e2713e92 2004-04-24 devnull r.min.y += outersep;
1227 e2713e92 2004-04-24 devnull r.max.x = top_left;
1228 e2713e92 2004-04-24 devnull r.max.y = r.min.y + smaxch.y;
1229 e2713e92 2004-04-24 devnull draw(screen, r, display->white, display->opaque, r.min);
1230 e2713e92 2004-04-24 devnull top_left = r.min.x;
1231 e2713e92 2004-04-24 devnull }
1232 e2713e92 2004-04-24 devnull
1233 e2713e92 2004-04-24 devnull
1234 e2713e92 2004-04-24 devnull Rectangle sel_dot_box(const transform* tr)
1235 e2713e92 2004-04-24 devnull {
1236 e2713e92 2004-04-24 devnull Point ctr;
1237 e2713e92 2004-04-24 devnull Rectangle r;
1238 e2713e92 2004-04-24 devnull if (tr==0)
1239 e2713e92 2004-04-24 devnull ctr.x = ctr.y = Dotrad;
1240 e2713e92 2004-04-24 devnull else do_transform(&ctr, tr, &cur_sel.p);
1241 e2713e92 2004-04-24 devnull r.min.x=ctr.x-Dotrad; r.max.x=ctr.x+Dotrad+1;
1242 e2713e92 2004-04-24 devnull r.min.y=ctr.y-Dotrad; r.max.y=ctr.y+Dotrad+1;
1243 e2713e92 2004-04-24 devnull return r;
1244 e2713e92 2004-04-24 devnull }
1245 e2713e92 2004-04-24 devnull
1246 e2713e92 2004-04-24 devnull
1247 e2713e92 2004-04-24 devnull void unselect(const transform* tr)
1248 e2713e92 2004-04-24 devnull {
1249 e2713e92 2004-04-24 devnull transform tra;
1250 e2713e92 2004-04-24 devnull if (sel_bkg==0)
1251 e2713e92 2004-04-24 devnull sel_bkg = allocimage(display, sel_dot_box(0), CMAP8, 0, DWhite);
1252 e2713e92 2004-04-24 devnull clear_txt();
1253 e2713e92 2004-04-24 devnull if (cur_sel.t < 0)
1254 e2713e92 2004-04-24 devnull return;
1255 e2713e92 2004-04-24 devnull prev_sel = cur_sel;
1256 e2713e92 2004-04-24 devnull if (tr==0)
1257 e2713e92 2004-04-24 devnull {tra=cur_trans(); tr=&tra;}
1258 e2713e92 2004-04-24 devnull draw(screen, sel_dot_box(tr), sel_bkg, display->opaque, ZP);
1259 e2713e92 2004-04-24 devnull cur_sel.t = -1;
1260 e2713e92 2004-04-24 devnull }
1261 e2713e92 2004-04-24 devnull
1262 e2713e92 2004-04-24 devnull
1263 e2713e92 2004-04-24 devnull /* Text at top right is written first and this low-level routine clobbers it if
1264 e2713e92 2004-04-24 devnull the new top-left text would overwrite it. However, users of this routine should
1265 e2713e92 2004-04-24 devnull try to keep the new text short enough to avoid this.
1266 e2713e92 2004-04-24 devnull */
1267 e2713e92 2004-04-24 devnull void show_mytext(char* msg)
1268 e2713e92 2004-04-24 devnull {
1269 e2713e92 2004-04-24 devnull Point tmp, pt = screen->r.min;
1270 e2713e92 2004-04-24 devnull int siz;
1271 e2713e92 2004-04-24 devnull tmp = stringsize(display->defaultfont, msg);
1272 e2713e92 2004-04-24 devnull siz = tmp.x;
1273 e2713e92 2004-04-24 devnull pt.x=top_left; pt.y+=outersep;
1274 e2713e92 2004-04-24 devnull if (top_left+siz > top_right) {
1275 e2713e92 2004-04-24 devnull Rectangle r;
1276 e2713e92 2004-04-24 devnull r.min.y = pt.y;
1277 e2713e92 2004-04-24 devnull r.min.x = top_right;
1278 e2713e92 2004-04-24 devnull r.max.y = r.min.y + smaxch.y;
1279 e2713e92 2004-04-24 devnull r.max.x = top_left+siz;
1280 e2713e92 2004-04-24 devnull draw(screen, r, display->white, display->opaque, r.min);
1281 e2713e92 2004-04-24 devnull top_right = top_left+siz;
1282 e2713e92 2004-04-24 devnull }
1283 e2713e92 2004-04-24 devnull string(screen, pt, display->black, ZP, display->defaultfont, msg);
1284 e2713e92 2004-04-24 devnull top_left += siz;
1285 e2713e92 2004-04-24 devnull }
1286 e2713e92 2004-04-24 devnull
1287 e2713e92 2004-04-24 devnull
1288 e2713e92 2004-04-24 devnull double rnd(double x, double tol) /* round to enough digits for accuracy tol */
1289 e2713e92 2004-04-24 devnull {
1290 e2713e92 2004-04-24 devnull double t = pow(10, floor(log10(tol)));
1291 e2713e92 2004-04-24 devnull return t * floor(x/t + .5);
1292 e2713e92 2004-04-24 devnull }
1293 e2713e92 2004-04-24 devnull
1294 e2713e92 2004-04-24 devnull double t_tol(double xtol, double ytol)
1295 e2713e92 2004-04-24 devnull {
1296 e2713e92 2004-04-24 devnull int t = (int) floor(cur_sel.t);
1297 e2713e92 2004-04-24 devnull fpoint* p = cur_sel.fp->p;
1298 e2713e92 2004-04-24 devnull double dx, dy;
1299 e2713e92 2004-04-24 devnull if (t==cur_sel.t)
1300 e2713e92 2004-04-24 devnull return 1;
1301 e2713e92 2004-04-24 devnull dx = fabs(p[t+1].x - p[t].x);
1302 e2713e92 2004-04-24 devnull dy = fabs(p[t+1].y - p[t].y);
1303 e2713e92 2004-04-24 devnull xtol /= (xtol>dx) ? xtol : dx;
1304 e2713e92 2004-04-24 devnull ytol /= (ytol>dy) ? ytol : dy;
1305 e2713e92 2004-04-24 devnull return (xtol<ytol) ? xtol : ytol;
1306 e2713e92 2004-04-24 devnull }
1307 e2713e92 2004-04-24 devnull
1308 e2713e92 2004-04-24 devnull void say_where(const transform* tr)
1309 e2713e92 2004-04-24 devnull {
1310 e2713e92 2004-04-24 devnull double xtol=dxuntransform(tr,1), ytol=dyuntransform(tr,-1);
1311 e2713e92 2004-04-24 devnull char buf[100];
1312 e2713e92 2004-04-24 devnull int n, nmax = (top_right - top_left)/smaxch.x;
1313 e2713e92 2004-04-24 devnull if (nmax >= 100)
1314 e2713e92 2004-04-24 devnull nmax = 100-1;
1315 e2713e92 2004-04-24 devnull n = sprintf(buf,"(%.14g,%.14g) at t=%.14g",
1316 e2713e92 2004-04-24 devnull rnd(cur_sel.p.x,xtol), rnd(cur_sel.p.y,ytol),
1317 e2713e92 2004-04-24 devnull rnd(cur_sel.t, t_tol(xtol,ytol)));
1318 e2713e92 2004-04-24 devnull if (cur_sel.fp->nam[0] != 0)
1319 e2713e92 2004-04-24 devnull sprintf(buf+n," %.*s", nmax-n-1, cur_sel.fp->nam);
1320 e2713e92 2004-04-24 devnull show_mytext(buf);
1321 e2713e92 2004-04-24 devnull }
1322 e2713e92 2004-04-24 devnull
1323 e2713e92 2004-04-24 devnull
1324 e2713e92 2004-04-24 devnull void reselect(const transform* tr) /* uselect(); set cur_sel; call this */
1325 e2713e92 2004-04-24 devnull {
1326 e2713e92 2004-04-24 devnull Point pt2, pt3;
1327 e2713e92 2004-04-24 devnull fpoint p2;
1328 e2713e92 2004-04-24 devnull transform tra;
1329 e2713e92 2004-04-24 devnull if (cur_sel.t < 0)
1330 e2713e92 2004-04-24 devnull return;
1331 e2713e92 2004-04-24 devnull if (tr==0)
1332 e2713e92 2004-04-24 devnull {tra=cur_trans(); tr=&tra;}
1333 e2713e92 2004-04-24 devnull do_transform(&p2, tr, &cur_sel.p);
1334 e2713e92 2004-04-24 devnull if (fabs(p2.x)+fabs(p2.y)>1e8 || (pt2.x=p2.x, pt2.y=p2.y, is_off_screen(pt2)))
1335 e2713e92 2004-04-24 devnull {cur_sel.t= -1; return;}
1336 e2713e92 2004-04-24 devnull pt3.x=pt2.x-Dotrad; pt3.y=pt2.y-Dotrad;
1337 e2713e92 2004-04-24 devnull draw(sel_bkg, sel_dot_box(0), screen, display->opaque, pt3);
1338 e2713e92 2004-04-24 devnull fillellipse(screen, pt2, Dotrad, Dotrad, clr_im(DRed), pt2);
1339 e2713e92 2004-04-24 devnull say_where(tr);
1340 e2713e92 2004-04-24 devnull }
1341 e2713e92 2004-04-24 devnull
1342 e2713e92 2004-04-24 devnull
1343 e2713e92 2004-04-24 devnull void do_select(Point pt)
1344 e2713e92 2004-04-24 devnull {
1345 e2713e92 2004-04-24 devnull transform tr = cur_trans();
1346 e2713e92 2004-04-24 devnull fpoint pt1, pt2, ctr;
1347 e2713e92 2004-04-24 devnull frectangle r;
1348 e2713e92 2004-04-24 devnull double slant;
1349 e2713e92 2004-04-24 devnull pt_on_fpoly* psel;
1350 e2713e92 2004-04-24 devnull unselect(&tr);
1351 e2713e92 2004-04-24 devnull do_untransform(&ctr, &tr, &pt);
1352 e2713e92 2004-04-24 devnull pt1.x=pt.x-fuzz; pt1.y=pt.y+fuzz;
1353 e2713e92 2004-04-24 devnull pt2.x=pt.x+fuzz; pt2.y=pt.y-fuzz;
1354 e2713e92 2004-04-24 devnull do_untransform(&r.min, &tr, &pt1);
1355 e2713e92 2004-04-24 devnull do_untransform(&r.max, &tr, &pt2);
1356 e2713e92 2004-04-24 devnull slant = u_slant_amt(&univ);
1357 e2713e92 2004-04-24 devnull slant_frect(&r, -slant);
1358 e2713e92 2004-04-24 devnull psel = select_in_univ(&r, slant);
1359 e2713e92 2004-04-24 devnull if (psel==0)
1360 e2713e92 2004-04-24 devnull return;
1361 e2713e92 2004-04-24 devnull if (logfil!=0) {
1362 e2713e92 2004-04-24 devnull fprintf(logfil,"%.14g\t%.14g\n", psel->p.x, psel->p.y);
1363 e2713e92 2004-04-24 devnull fflush(logfil);
1364 e2713e92 2004-04-24 devnull }
1365 e2713e92 2004-04-24 devnull cur_sel = *psel;
1366 e2713e92 2004-04-24 devnull reselect(&tr);
1367 e2713e92 2004-04-24 devnull }
1368 e2713e92 2004-04-24 devnull
1369 e2713e92 2004-04-24 devnull
1370 e2713e92 2004-04-24 devnull /***************************** Prompting for text *****************************/
1371 e2713e92 2004-04-24 devnull
1372 e2713e92 2004-04-24 devnull void unshow_mytext(char* msg)
1373 e2713e92 2004-04-24 devnull {
1374 e2713e92 2004-04-24 devnull Rectangle r;
1375 e2713e92 2004-04-24 devnull Point siz = stringsize(display->defaultfont, msg);
1376 e2713e92 2004-04-24 devnull top_left -= siz.x;
1377 e2713e92 2004-04-24 devnull r.min.y = screen->r.min.y + outersep;
1378 e2713e92 2004-04-24 devnull r.min.x = top_left;
1379 e2713e92 2004-04-24 devnull r.max.y = r.min.y + siz.y;
1380 e2713e92 2004-04-24 devnull r.max.x = r.min.x + siz.x;
1381 e2713e92 2004-04-24 devnull draw(screen, r, display->white, display->opaque, r.min);
1382 e2713e92 2004-04-24 devnull }
1383 e2713e92 2004-04-24 devnull
1384 e2713e92 2004-04-24 devnull
1385 e2713e92 2004-04-24 devnull /* Show the given prompt and read a line of user input. The text appears at the
1386 e2713e92 2004-04-24 devnull top left. If it runs into the top right text, we stop echoing but let the user
1387 e2713e92 2004-04-24 devnull continue typing blind if he wants to.
1388 e2713e92 2004-04-24 devnull */
1389 e2713e92 2004-04-24 devnull char* prompt_text(char* prompt)
1390 e2713e92 2004-04-24 devnull {
1391 e2713e92 2004-04-24 devnull static char buf[200];
1392 e2713e92 2004-04-24 devnull int n0, n=0, nshown=0;
1393 e2713e92 2004-04-24 devnull Rune c;
1394 e2713e92 2004-04-24 devnull unselect(0);
1395 e2713e92 2004-04-24 devnull show_mytext(prompt);
1396 e2713e92 2004-04-24 devnull while (n<200-1-UTFmax && (c=ekbd())!='\n') {
1397 e2713e92 2004-04-24 devnull if (c=='\b') {
1398 e2713e92 2004-04-24 devnull buf[n] = 0;
1399 e2713e92 2004-04-24 devnull if (n > 0)
1400 e2713e92 2004-04-24 devnull do n--;
1401 e2713e92 2004-04-24 devnull while (n>0 && (buf[n-1]&0xc0)==0x80);
1402 e2713e92 2004-04-24 devnull if (n < nshown)
1403 e2713e92 2004-04-24 devnull {unshow_mytext(buf+n); nshown=n;}
1404 e2713e92 2004-04-24 devnull } else {
1405 e2713e92 2004-04-24 devnull n0 = n;
1406 e2713e92 2004-04-24 devnull n += runetochar(buf+n, &c);
1407 e2713e92 2004-04-24 devnull buf[n] = 0;
1408 e2713e92 2004-04-24 devnull if (nshown==n0 && top_right-top_left >= smaxch.x)
1409 e2713e92 2004-04-24 devnull {show_mytext(buf+n0); nshown=n;}
1410 e2713e92 2004-04-24 devnull }
1411 e2713e92 2004-04-24 devnull }
1412 e2713e92 2004-04-24 devnull buf[n] = 0;
1413 e2713e92 2004-04-24 devnull while (ecanmouse())
1414 e2713e92 2004-04-24 devnull emouse();
1415 e2713e92 2004-04-24 devnull return buf;
1416 e2713e92 2004-04-24 devnull }
1417 e2713e92 2004-04-24 devnull
1418 e2713e92 2004-04-24 devnull
1419 e2713e92 2004-04-24 devnull /**************************** Redrawing the screen ****************************/
1420 e2713e92 2004-04-24 devnull
1421 e2713e92 2004-04-24 devnull /* Let p0 and its successors define a piecewise-linear function of a paramter t,
1422 e2713e92 2004-04-24 devnull and draw the 0<=t<=n1 portion using transform *tr.
1423 e2713e92 2004-04-24 devnull */
1424 e2713e92 2004-04-24 devnull void draw_fpts(const fpoint* p0, double n1, const transform* tr, int thick,
1425 e2713e92 2004-04-24 devnull Image* clr)
1426 e2713e92 2004-04-24 devnull {
1427 e2713e92 2004-04-24 devnull int n = (int) n1;
1428 e2713e92 2004-04-24 devnull const fpoint* p = p0 + n;
1429 e2713e92 2004-04-24 devnull fpoint pp;
1430 e2713e92 2004-04-24 devnull Point qq, q;
1431 e2713e92 2004-04-24 devnull if (n1 > n) {
1432 e2713e92 2004-04-24 devnull pp.x = p[0].x + (n1-n)*(p[1].x - p[0].x);
1433 e2713e92 2004-04-24 devnull pp.y = p[0].y + (n1-n)*(p[1].y - p[0].y);
1434 e2713e92 2004-04-24 devnull } else pp = *p--;
1435 e2713e92 2004-04-24 devnull do_transform(&qq, tr, &pp);
1436 e2713e92 2004-04-24 devnull if (n1==0)
1437 e2713e92 2004-04-24 devnull fillellipse(screen, qq, 1+thick, 1+thick, clr, qq);
1438 e2713e92 2004-04-24 devnull for (; p>=p0; p--) {
1439 e2713e92 2004-04-24 devnull do_transform(&q, tr, p);
1440 e2713e92 2004-04-24 devnull line(screen, qq, q, Enddisc, Enddisc, thick, clr, qq);
1441 e2713e92 2004-04-24 devnull qq = q;
1442 e2713e92 2004-04-24 devnull }
1443 e2713e92 2004-04-24 devnull }
1444 e2713e92 2004-04-24 devnull
1445 e2713e92 2004-04-24 devnull void draw_1fpoly(const fpolygon* fp, const transform* tr, Image* clr,
1446 e2713e92 2004-04-24 devnull const frectangle *udisp, double slant)
1447 e2713e92 2004-04-24 devnull {
1448 e2713e92 2004-04-24 devnull fpoint *p0=fp->p, *pn=fp->p+fp->n;
1449 e2713e92 2004-04-24 devnull double l1, l2;
1450 e2713e92 2004-04-24 devnull if (p0==pn && fcontains(udisp,*p0))
1451 e2713e92 2004-04-24 devnull {draw_fpts(p0, 0, tr, fp->thick, clr); return;}
1452 e2713e92 2004-04-24 devnull while ((l1=out_length(p0,pn,*udisp,slant)) < pn-p0) {
1453 e2713e92 2004-04-24 devnull fpoint p0sav;
1454 e2713e92 2004-04-24 devnull int i1 = (int) l1;
1455 e2713e92 2004-04-24 devnull p0+=i1; l1-=i1;
1456 e2713e92 2004-04-24 devnull p0sav = *p0;
1457 e2713e92 2004-04-24 devnull p0[0].x += l1*(p0[1].x - p0[0].x);
1458 e2713e92 2004-04-24 devnull p0[0].y += l1*(p0[1].y - p0[0].y);
1459 e2713e92 2004-04-24 devnull l2 = in_length(p0, pn, *udisp, slant);
1460 e2713e92 2004-04-24 devnull draw_fpts(p0, l2, tr, fp->thick, clr);
1461 e2713e92 2004-04-24 devnull *p0 = p0sav;
1462 e2713e92 2004-04-24 devnull p0 += (l2>0) ? ((int) ceil(l2)) : 1;
1463 e2713e92 2004-04-24 devnull }
1464 e2713e92 2004-04-24 devnull }
1465 e2713e92 2004-04-24 devnull
1466 e2713e92 2004-04-24 devnull
1467 e2713e92 2004-04-24 devnull double get_clip_data(const fpolygons *u, frectangle *r)
1468 e2713e92 2004-04-24 devnull {
1469 e2713e92 2004-04-24 devnull double slant = set_unslanted_y((fpolygons*)u, &r->min.y, &r->max.y);
1470 e2713e92 2004-04-24 devnull r->min.x = u->disp.min.x;
1471 e2713e92 2004-04-24 devnull r->max.x = u->disp.max.x;
1472 e2713e92 2004-04-24 devnull return slant;
1473 e2713e92 2004-04-24 devnull }
1474 e2713e92 2004-04-24 devnull
1475 e2713e92 2004-04-24 devnull
1476 e2713e92 2004-04-24 devnull void draw_fpoly(const fpolygon* fp, const transform* tr, Image* clr)
1477 e2713e92 2004-04-24 devnull {
1478 e2713e92 2004-04-24 devnull frectangle r;
1479 e2713e92 2004-04-24 devnull double slant = get_clip_data(&univ, &r);
1480 e2713e92 2004-04-24 devnull draw_1fpoly(fp, tr, clr, &r, slant);
1481 e2713e92 2004-04-24 devnull }
1482 e2713e92 2004-04-24 devnull
1483 e2713e92 2004-04-24 devnull
1484 e2713e92 2004-04-24 devnull void eresized(int new)
1485 e2713e92 2004-04-24 devnull {
1486 e2713e92 2004-04-24 devnull transform tr;
1487 e2713e92 2004-04-24 devnull fpolygon* fp;
1488 e2713e92 2004-04-24 devnull frectangle clipr;
1489 e2713e92 2004-04-24 devnull double slant;
1490 e2713e92 2004-04-24 devnull if(new && getwindow(display, Refmesg) < 0) {
1491 e2713e92 2004-04-24 devnull fprintf(stderr,"can't reattach to window\n");
1492 e2713e92 2004-04-24 devnull exits("reshap");
1493 e2713e92 2004-04-24 devnull }
1494 e2713e92 2004-04-24 devnull draw(screen, screen->r, display->white, display->opaque, screen->r.min);
1495 e2713e92 2004-04-24 devnull tr = draw_frame();
1496 e2713e92 2004-04-24 devnull slant = get_clip_data(&univ, &clipr);
1497 e2713e92 2004-04-24 devnull for (fp=univ.p; fp!=0; fp=fp->link)
1498 e2713e92 2004-04-24 devnull if (fintersects(&clipr, &fp->bb, slant))
1499 e2713e92 2004-04-24 devnull draw_1fpoly(fp, &tr, fp->clr, &clipr, slant);
1500 e2713e92 2004-04-24 devnull reselect(0);
1501 e2713e92 2004-04-24 devnull if (mv_bkgd!=0 && mv_bkgd->repl==0) {
1502 e2713e92 2004-04-24 devnull freeimage(mv_bkgd);
1503 e2713e92 2004-04-24 devnull mv_bkgd = display->white;
1504 e2713e92 2004-04-24 devnull }
1505 e2713e92 2004-04-24 devnull flushimage(display, 1);
1506 e2713e92 2004-04-24 devnull }
1507 e2713e92 2004-04-24 devnull
1508 e2713e92 2004-04-24 devnull
1509 e2713e92 2004-04-24 devnull
1510 e2713e92 2004-04-24 devnull
1511 e2713e92 2004-04-24 devnull /********************************* Recoloring *********************************/
1512 e2713e92 2004-04-24 devnull
1513 e2713e92 2004-04-24 devnull int draw_palette(int n) /* n is number of colors; returns patch dy */
1514 e2713e92 2004-04-24 devnull {
1515 e2713e92 2004-04-24 devnull int y0 = screen->r.min.y + top_border;
1516 e2713e92 2004-04-24 devnull int dy = (screen->r.max.y - bot_border - y0)/n;
1517 e2713e92 2004-04-24 devnull Rectangle r;
1518 e2713e92 2004-04-24 devnull int i;
1519 e2713e92 2004-04-24 devnull r.min.y = y0;
1520 e2713e92 2004-04-24 devnull r.min.x = screen->r.max.x - rt_border + framewd;
1521 e2713e92 2004-04-24 devnull r.max.y = y0 + dy;
1522 e2713e92 2004-04-24 devnull r.max.x = screen->r.max.x;
1523 e2713e92 2004-04-24 devnull for (i=0; i<n; i++) {
1524 e2713e92 2004-04-24 devnull draw(screen, r, clrtab[i].im, display->opaque, r.min);
1525 e2713e92 2004-04-24 devnull r.min.y = r.max.y;
1526 e2713e92 2004-04-24 devnull r.max.y += dy;
1527 e2713e92 2004-04-24 devnull }
1528 e2713e92 2004-04-24 devnull return dy;
1529 e2713e92 2004-04-24 devnull }
1530 e2713e92 2004-04-24 devnull
1531 e2713e92 2004-04-24 devnull
1532 e2713e92 2004-04-24 devnull Image* palette_color(Point pt, int dy, int n)
1533 e2713e92 2004-04-24 devnull { /* mouse at pt, patch size dy, n colors */
1534 e2713e92 2004-04-24 devnull int yy;
1535 e2713e92 2004-04-24 devnull if (screen->r.max.x - pt.x > rt_border - framewd)
1536 e2713e92 2004-04-24 devnull return 0;
1537 e2713e92 2004-04-24 devnull yy = pt.y - (screen->r.min.y + top_border);
1538 e2713e92 2004-04-24 devnull if (yy<0 || yy>=n*dy)
1539 e2713e92 2004-04-24 devnull return 0;
1540 e2713e92 2004-04-24 devnull return clrtab[yy/dy].im;
1541 e2713e92 2004-04-24 devnull }
1542 e2713e92 2004-04-24 devnull
1543 e2713e92 2004-04-24 devnull
1544 e2713e92 2004-04-24 devnull void all_set_clr(fpolygons* fps, Image* clr)
1545 e2713e92 2004-04-24 devnull {
1546 e2713e92 2004-04-24 devnull fpolygon* p;
1547 e2713e92 2004-04-24 devnull for (p=fps->p; p!=0; p=p->link)
1548 e2713e92 2004-04-24 devnull p->clr = clr;
1549 e2713e92 2004-04-24 devnull }
1550 e2713e92 2004-04-24 devnull
1551 e2713e92 2004-04-24 devnull
1552 e2713e92 2004-04-24 devnull void do_recolor(int but, Mouse* m, int alluniv)
1553 e2713e92 2004-04-24 devnull {
1554 e2713e92 2004-04-24 devnull int nclr = clr_id(DWhite);
1555 e2713e92 2004-04-24 devnull int dy = draw_palette(nclr);
1556 e2713e92 2004-04-24 devnull Image* clr;
1557 e2713e92 2004-04-24 devnull if (!get_1click(but, m, 0)) {
1558 e2713e92 2004-04-24 devnull eresized(0);
1559 e2713e92 2004-04-24 devnull return;
1560 e2713e92 2004-04-24 devnull }
1561 e2713e92 2004-04-24 devnull clr = palette_color(m->xy, dy, nclr);
1562 e2713e92 2004-04-24 devnull if (clr != 0) {
1563 e2713e92 2004-04-24 devnull if (alluniv)
1564 e2713e92 2004-04-24 devnull all_set_clr(&univ, clr);
1565 e2713e92 2004-04-24 devnull else cur_sel.fp->clr = clr;
1566 e2713e92 2004-04-24 devnull }
1567 e2713e92 2004-04-24 devnull eresized(0);
1568 e2713e92 2004-04-24 devnull lift_button(but, m, Never);
1569 e2713e92 2004-04-24 devnull }
1570 e2713e92 2004-04-24 devnull
1571 e2713e92 2004-04-24 devnull
1572 e2713e92 2004-04-24 devnull /****************************** Move and rotate ******************************/
1573 e2713e92 2004-04-24 devnull
1574 e2713e92 2004-04-24 devnull void prepare_mv(const fpolygon* fp)
1575 e2713e92 2004-04-24 devnull {
1576 e2713e92 2004-04-24 devnull Rectangle r = screen->r;
1577 e2713e92 2004-04-24 devnull Image* scr0;
1578 e2713e92 2004-04-24 devnull int dt = 1 + fp->thick;
1579 e2713e92 2004-04-24 devnull r.min.x+=lft_border-dt; r.min.y+=top_border-dt;
1580 e2713e92 2004-04-24 devnull r.max.x-=rt_border-dt; r.max.y-=bot_border-dt;
1581 e2713e92 2004-04-24 devnull if (mv_bkgd!=0 && mv_bkgd->repl==0)
1582 e2713e92 2004-04-24 devnull freeimage(mv_bkgd);
1583 e2713e92 2004-04-24 devnull mv_bkgd = allocimage(display, r, CMAP8, 0, DNofill);
1584 e2713e92 2004-04-24 devnull if (mv_bkgd==0)
1585 e2713e92 2004-04-24 devnull mv_bkgd = display->white;
1586 e2713e92 2004-04-24 devnull else { transform tr = cur_trans();
1587 e2713e92 2004-04-24 devnull draw(mv_bkgd, r, screen, display->opaque, r.min);
1588 e2713e92 2004-04-24 devnull draw(mv_bkgd, sel_dot_box(&tr), sel_bkg, display->opaque, ZP);
1589 e2713e92 2004-04-24 devnull scr0 = screen;
1590 e2713e92 2004-04-24 devnull screen = mv_bkgd;
1591 e2713e92 2004-04-24 devnull draw_fpoly(fp, &tr, display->white);
1592 e2713e92 2004-04-24 devnull screen = scr0;
1593 e2713e92 2004-04-24 devnull }
1594 e2713e92 2004-04-24 devnull }
1595 e2713e92 2004-04-24 devnull
1596 e2713e92 2004-04-24 devnull
1597 e2713e92 2004-04-24 devnull void move_fp(fpolygon* fp, double dx, double dy)
1598 e2713e92 2004-04-24 devnull {
1599 e2713e92 2004-04-24 devnull fpoint *p, *pn=fp->p+fp->n;
1600 e2713e92 2004-04-24 devnull for (p=fp->p; p<=pn; p++) {
1601 e2713e92 2004-04-24 devnull (p->x) += dx;
1602 e2713e92 2004-04-24 devnull (p->y) += dy;
1603 e2713e92 2004-04-24 devnull }
1604 e2713e92 2004-04-24 devnull (fp->bb.min.x)+=dx; (fp->bb.min.y)+=dy;
1605 e2713e92 2004-04-24 devnull (fp->bb.max.x)+=dx; (fp->bb.max.y)+=dy;
1606 e2713e92 2004-04-24 devnull }
1607 e2713e92 2004-04-24 devnull
1608 e2713e92 2004-04-24 devnull
1609 e2713e92 2004-04-24 devnull void rotate_fp(fpolygon* fp, fpoint o, double theta)
1610 e2713e92 2004-04-24 devnull {
1611 e2713e92 2004-04-24 devnull double s=sin(theta), c=cos(theta);
1612 e2713e92 2004-04-24 devnull fpoint *p, *pn=fp->p+fp->n;
1613 e2713e92 2004-04-24 devnull for (p=fp->p; p<=pn; p++) {
1614 e2713e92 2004-04-24 devnull double x=p->x-o.x, y=p->y-o.y;
1615 e2713e92 2004-04-24 devnull (p->x) = o.x + c*x - s*y;
1616 e2713e92 2004-04-24 devnull (p->y) = o.y + s*x + c*y;
1617 e2713e92 2004-04-24 devnull }
1618 e2713e92 2004-04-24 devnull set_fbb(fp);
1619 e2713e92 2004-04-24 devnull }
1620 e2713e92 2004-04-24 devnull
1621 e2713e92 2004-04-24 devnull
1622 e2713e92 2004-04-24 devnull /* Move the selected fpolygon so the selected point tracks the mouse, and return
1623 e2713e92 2004-04-24 devnull the total amount of movement. Button but has already been held down for at
1624 e2713e92 2004-04-24 devnull least Mv_delay milliseconds and the mouse might have moved some distance.
1625 e2713e92 2004-04-24 devnull */
1626 e2713e92 2004-04-24 devnull fpoint do_move(int but, Mouse* m)
1627 e2713e92 2004-04-24 devnull {
1628 e2713e92 2004-04-24 devnull transform tr = cur_trans();
1629 e2713e92 2004-04-24 devnull int bbit = Button_bit(but);
1630 e2713e92 2004-04-24 devnull fpolygon* fp = cur_sel.fp;
1631 e2713e92 2004-04-24 devnull fpoint loc, loc0=cur_sel.p;
1632 e2713e92 2004-04-24 devnull double tsav = cur_sel.t;
1633 e2713e92 2004-04-24 devnull unselect(&tr);
1634 e2713e92 2004-04-24 devnull do { latest_mouse(but, m);
1635 e2713e92 2004-04-24 devnull (fp->thick)++; /* line() DISAGREES WITH ITSELF */
1636 e2713e92 2004-04-24 devnull draw_fpoly(fp, &tr, mv_bkgd);
1637 e2713e92 2004-04-24 devnull (fp->thick)--;
1638 e2713e92 2004-04-24 devnull do_untransform(&loc, &tr, &m->xy);
1639 e2713e92 2004-04-24 devnull move_fp(fp, loc.x-cur_sel.p.x, loc.y-cur_sel.p.y);
1640 e2713e92 2004-04-24 devnull cur_sel.p = loc;
1641 e2713e92 2004-04-24 devnull draw_fpoly(fp, &tr, fp->clr);
1642 e2713e92 2004-04-24 devnull } while (m->buttons & bbit);
1643 e2713e92 2004-04-24 devnull cur_sel.t = tsav;
1644 e2713e92 2004-04-24 devnull reselect(&tr);
1645 e2713e92 2004-04-24 devnull loc.x -= loc0.x;
1646 e2713e92 2004-04-24 devnull loc.y -= loc0.y;
1647 e2713e92 2004-04-24 devnull return loc;
1648 e2713e92 2004-04-24 devnull }
1649 e2713e92 2004-04-24 devnull
1650 e2713e92 2004-04-24 devnull
1651 e2713e92 2004-04-24 devnull double dir_angle(const Point* pt, const transform* tr)
1652 e2713e92 2004-04-24 devnull {
1653 e2713e92 2004-04-24 devnull fpoint p;
1654 e2713e92 2004-04-24 devnull double dy, dx;
1655 e2713e92 2004-04-24 devnull do_untransform(&p, tr, pt);
1656 e2713e92 2004-04-24 devnull dy=p.y-cur_sel.p.y; dx=p.x-cur_sel.p.x;
1657 e2713e92 2004-04-24 devnull return (dx==0 && dy==0) ? 0.0 : atan2(dy, dx);
1658 e2713e92 2004-04-24 devnull }
1659 e2713e92 2004-04-24 devnull
1660 e2713e92 2004-04-24 devnull
1661 e2713e92 2004-04-24 devnull /* Rotate the selected fpolygon around the selection point so as to track the
1662 e2713e92 2004-04-24 devnull direction angle from the selected point to m->xy. Stop when button but goes
1663 e2713e92 2004-04-24 devnull up and return the total amount of rotation in radians.
1664 e2713e92 2004-04-24 devnull */
1665 e2713e92 2004-04-24 devnull double do_rotate(int but, Mouse* m)
1666 e2713e92 2004-04-24 devnull {
1667 e2713e92 2004-04-24 devnull transform tr = cur_trans();
1668 e2713e92 2004-04-24 devnull int bbit = Button_bit(but);
1669 e2713e92 2004-04-24 devnull fpolygon* fp = cur_sel.fp;
1670 e2713e92 2004-04-24 devnull double theta0 = dir_angle(&m->xy, &tr);
1671 e2713e92 2004-04-24 devnull double th, theta = theta0;
1672 e2713e92 2004-04-24 devnull do { latest_mouse(but, m);
1673 e2713e92 2004-04-24 devnull (fp->thick)++; /* line() DISAGREES WITH ITSELF */
1674 e2713e92 2004-04-24 devnull draw_fpoly(fp, &tr, mv_bkgd);
1675 e2713e92 2004-04-24 devnull (fp->thick)--;
1676 e2713e92 2004-04-24 devnull th = dir_angle(&m->xy, &tr);
1677 e2713e92 2004-04-24 devnull rotate_fp(fp, cur_sel.p, th-theta);
1678 e2713e92 2004-04-24 devnull theta = th;
1679 e2713e92 2004-04-24 devnull draw_fpoly(fp, &tr, fp->clr);
1680 e2713e92 2004-04-24 devnull } while (m->buttons & bbit);
1681 e2713e92 2004-04-24 devnull unselect(&tr);
1682 e2713e92 2004-04-24 devnull cur_sel = prev_sel;
1683 e2713e92 2004-04-24 devnull reselect(&tr);
1684 e2713e92 2004-04-24 devnull return theta - theta0;
1685 e2713e92 2004-04-24 devnull }
1686 e2713e92 2004-04-24 devnull
1687 e2713e92 2004-04-24 devnull
1688 e2713e92 2004-04-24 devnull
1689 e2713e92 2004-04-24 devnull /********************************* Edit menu *********************************/
1690 e2713e92 2004-04-24 devnull
1691 e2713e92 2004-04-24 devnull typedef enum e_index {
1692 e2713e92 2004-04-24 devnull Erecolor, Ethick, Edelete, Eundo, Erotate, Eoptions,
1693 e2713e92 2004-04-24 devnull Emove
1694 e2713e92 2004-04-24 devnull } e_index;
1695 e2713e92 2004-04-24 devnull
1696 e2713e92 2004-04-24 devnull char* e_items[Eoptions+1];
1697 e2713e92 2004-04-24 devnull
1698 e2713e92 2004-04-24 devnull Menu e_menu = {e_items, 0, 0};
1699 e2713e92 2004-04-24 devnull
1700 e2713e92 2004-04-24 devnull
1701 e2713e92 2004-04-24 devnull typedef struct e_action {
1702 e2713e92 2004-04-24 devnull e_index typ; /* What type of action */
1703 e2713e92 2004-04-24 devnull fpolygon* fp; /* fpolygon the action applies to */
1704 e2713e92 2004-04-24 devnull Image* clr; /* color to use if typ==Erecolor */
1705 e2713e92 2004-04-24 devnull double amt; /* rotation angle or line thickness */
1706 e2713e92 2004-04-24 devnull fpoint pt; /* movement vector or rotation center */
1707 e2713e92 2004-04-24 devnull struct e_action* link; /* next in a stack */
1708 e2713e92 2004-04-24 devnull } e_action;
1709 e2713e92 2004-04-24 devnull
1710 e2713e92 2004-04-24 devnull e_action* unact = 0; /* heads a linked list of actions */
1711 e2713e92 2004-04-24 devnull e_action* do_undo(e_action*); /* pop off an e_action and (un)do it */
1712 e2713e92 2004-04-24 devnull e_action* save_act(e_action*,e_index); /* append new e_action for status quo */
1713 e2713e92 2004-04-24 devnull
1714 e2713e92 2004-04-24 devnull
1715 e2713e92 2004-04-24 devnull void save_mv(fpoint movement)
1716 e2713e92 2004-04-24 devnull {
1717 e2713e92 2004-04-24 devnull unact = save_act(unact, Emove);
1718 e2713e92 2004-04-24 devnull unact->pt = movement;
1719 e2713e92 2004-04-24 devnull }
1720 e2713e92 2004-04-24 devnull
1721 e2713e92 2004-04-24 devnull
1722 e2713e92 2004-04-24 devnull void init_e_menu(void)
1723 e2713e92 2004-04-24 devnull {
1724 e2713e92 2004-04-24 devnull char* u = "can't undo";
1725 e2713e92 2004-04-24 devnull e_items[Erecolor] = "recolor";
1726 e2713e92 2004-04-24 devnull e_items[Edelete] = "delete";
1727 e2713e92 2004-04-24 devnull e_items[Erotate] = "rotate";
1728 e2713e92 2004-04-24 devnull e_items[Eoptions-cantmv] = 0;
1729 e2713e92 2004-04-24 devnull e_items[Ethick] = (cur_sel.fp->thick >0) ? "thin" : "thick";
1730 e2713e92 2004-04-24 devnull if (unact!=0)
1731 e2713e92 2004-04-24 devnull switch (unact->typ) {
1732 e2713e92 2004-04-24 devnull case Erecolor: u="uncolor"; break;
1733 e2713e92 2004-04-24 devnull case Ethick: u=(unact->fp->thick==0) ? "unthin" : "unthicken";
1734 e2713e92 2004-04-24 devnull break;
1735 e2713e92 2004-04-24 devnull case Edelete: u="undelete"; break;
1736 e2713e92 2004-04-24 devnull case Emove: u="unmove"; break;
1737 e2713e92 2004-04-24 devnull case Erotate: u="unrotate"; break;
1738 e2713e92 2004-04-24 devnull }
1739 e2713e92 2004-04-24 devnull e_items[Eundo] = u;
1740 e2713e92 2004-04-24 devnull }
1741 e2713e92 2004-04-24 devnull
1742 e2713e92 2004-04-24 devnull
1743 e2713e92 2004-04-24 devnull void do_emenu(int but, Mouse* m)
1744 e2713e92 2004-04-24 devnull {
1745 e2713e92 2004-04-24 devnull int h;
1746 e2713e92 2004-04-24 devnull if (cur_sel.t < 0)
1747 e2713e92 2004-04-24 devnull return;
1748 e2713e92 2004-04-24 devnull init_e_menu();
1749 e2713e92 2004-04-24 devnull h = emenuhit(but, m, &e_menu);
1750 e2713e92 2004-04-24 devnull switch(h) {
1751 e2713e92 2004-04-24 devnull case Ethick: unact = save_act(unact, h);
1752 e2713e92 2004-04-24 devnull cur_sel.fp->thick ^= 1;
1753 e2713e92 2004-04-24 devnull eresized(0);
1754 e2713e92 2004-04-24 devnull break;
1755 e2713e92 2004-04-24 devnull case Edelete: unact = save_act(unact, h);
1756 e2713e92 2004-04-24 devnull fp_remove(&univ, cur_sel.fp);
1757 e2713e92 2004-04-24 devnull unselect(0);
1758 e2713e92 2004-04-24 devnull eresized(0);
1759 e2713e92 2004-04-24 devnull break;
1760 e2713e92 2004-04-24 devnull case Erecolor: unact = save_act(unact, h);
1761 e2713e92 2004-04-24 devnull do_recolor(but, m, 0);
1762 e2713e92 2004-04-24 devnull break;
1763 e2713e92 2004-04-24 devnull case Erotate: unact = save_act(unact, h);
1764 e2713e92 2004-04-24 devnull prepare_mv(cur_sel.fp);
1765 e2713e92 2004-04-24 devnull if (get_1click(but, m, 0)) {
1766 e2713e92 2004-04-24 devnull unact->pt = cur_sel.p;
1767 e2713e92 2004-04-24 devnull unact->amt = do_rotate(but, m);
1768 e2713e92 2004-04-24 devnull }
1769 e2713e92 2004-04-24 devnull break;
1770 e2713e92 2004-04-24 devnull case Eundo: unact = do_undo(unact);
1771 e2713e92 2004-04-24 devnull break;
1772 e2713e92 2004-04-24 devnull }
1773 e2713e92 2004-04-24 devnull }
1774 e2713e92 2004-04-24 devnull
1775 e2713e92 2004-04-24 devnull
1776 e2713e92 2004-04-24 devnull
1777 e2713e92 2004-04-24 devnull /******************************* Undoing edits *******************************/
1778 e2713e92 2004-04-24 devnull
1779 e2713e92 2004-04-24 devnull e_action* save_act(e_action* a0, e_index typ)
1780 e2713e92 2004-04-24 devnull { /* append new e_action for status quo */
1781 e2713e92 2004-04-24 devnull e_action* a = malloc(sizeof(e_action));
1782 e2713e92 2004-04-24 devnull a->link = a0;
1783 e2713e92 2004-04-24 devnull a->pt.x = a->pt.y = 0.0;
1784 e2713e92 2004-04-24 devnull a->amt = cur_sel.fp->thick;
1785 e2713e92 2004-04-24 devnull a->clr = cur_sel.fp->clr;
1786 e2713e92 2004-04-24 devnull a->fp = cur_sel.fp;
1787 e2713e92 2004-04-24 devnull a->typ = typ;
1788 e2713e92 2004-04-24 devnull return a;
1789 e2713e92 2004-04-24 devnull }
1790 e2713e92 2004-04-24 devnull
1791 e2713e92 2004-04-24 devnull
1792 e2713e92 2004-04-24 devnull /* This would be trivial except it's nice to preserve the selection in order to make
1793 e2713e92 2004-04-24 devnull it easy to undo a series of moves. (There's no do_unrotate() because it's harder
1794 e2713e92 2004-04-24 devnull and less important to preserve the selection in that case.)
1795 e2713e92 2004-04-24 devnull */
1796 e2713e92 2004-04-24 devnull void do_unmove(e_action* a)
1797 e2713e92 2004-04-24 devnull {
1798 e2713e92 2004-04-24 devnull double tsav = cur_sel.t;
1799 e2713e92 2004-04-24 devnull unselect(0);
1800 e2713e92 2004-04-24 devnull move_fp(a->fp, -a->pt.x, -a->pt.y);
1801 e2713e92 2004-04-24 devnull if (a->fp == cur_sel.fp) {
1802 e2713e92 2004-04-24 devnull cur_sel.p.x -= a->pt.x;
1803 e2713e92 2004-04-24 devnull cur_sel.p.y -= a->pt.y;
1804 e2713e92 2004-04-24 devnull }
1805 e2713e92 2004-04-24 devnull cur_sel.t = tsav;
1806 e2713e92 2004-04-24 devnull reselect(0);
1807 e2713e92 2004-04-24 devnull }
1808 e2713e92 2004-04-24 devnull
1809 e2713e92 2004-04-24 devnull
1810 e2713e92 2004-04-24 devnull e_action* do_undo(e_action* a0) /* pop off an e_action and (un)do it */
1811 e2713e92 2004-04-24 devnull {
1812 e2713e92 2004-04-24 devnull e_action* a = a0;
1813 e2713e92 2004-04-24 devnull if (a==0)
1814 e2713e92 2004-04-24 devnull return 0;
1815 e2713e92 2004-04-24 devnull switch(a->typ) {
1816 e2713e92 2004-04-24 devnull case Ethick: a->fp->thick = a->amt;
1817 e2713e92 2004-04-24 devnull eresized(0);
1818 e2713e92 2004-04-24 devnull break;
1819 e2713e92 2004-04-24 devnull case Erecolor: a->fp->clr = a->clr;
1820 e2713e92 2004-04-24 devnull eresized(0);
1821 e2713e92 2004-04-24 devnull break;
1822 e2713e92 2004-04-24 devnull case Edelete:
1823 e2713e92 2004-04-24 devnull a->fp->link = univ.p;
1824 e2713e92 2004-04-24 devnull univ.p = a->fp;
1825 e2713e92 2004-04-24 devnull grow_bb(&univ.bb, &a->fp->bb);
1826 e2713e92 2004-04-24 devnull eresized(0);
1827 e2713e92 2004-04-24 devnull break;
1828 e2713e92 2004-04-24 devnull case Emove:
1829 e2713e92 2004-04-24 devnull do_unmove(a);
1830 e2713e92 2004-04-24 devnull eresized(0);
1831 e2713e92 2004-04-24 devnull break;
1832 e2713e92 2004-04-24 devnull case Erotate:
1833 e2713e92 2004-04-24 devnull unselect(0);
1834 e2713e92 2004-04-24 devnull rotate_fp(a->fp, a->pt, -a->amt);
1835 e2713e92 2004-04-24 devnull eresized(0);
1836 e2713e92 2004-04-24 devnull break;
1837 e2713e92 2004-04-24 devnull }
1838 e2713e92 2004-04-24 devnull a0 = a->link;
1839 e2713e92 2004-04-24 devnull free(a);
1840 e2713e92 2004-04-24 devnull return a0;
1841 e2713e92 2004-04-24 devnull }
1842 e2713e92 2004-04-24 devnull
1843 e2713e92 2004-04-24 devnull
1844 e2713e92 2004-04-24 devnull
1845 e2713e92 2004-04-24 devnull /********************************* Main menu *********************************/
1846 e2713e92 2004-04-24 devnull
1847 e2713e92 2004-04-24 devnull enum m_index { Mzoom_in, Mzoom_out, Munzoom, Mslant, Munslant,
1848 e2713e92 2004-04-24 devnull Msquare_up, Mrecenter, Mrecolor, Mrestack, Mread,
1849 e2713e92 2004-04-24 devnull Mwrite, Mexit};
1850 e2713e92 2004-04-24 devnull char* m_items[] = {"zoom in", "zoom out", "unzoom", "slant", "unslant",
1851 e2713e92 2004-04-24 devnull "square up", "recenter", "recolor", "restack", "read",
1852 e2713e92 2004-04-24 devnull "write", "exit", 0};
1853 e2713e92 2004-04-24 devnull
1854 e2713e92 2004-04-24 devnull Menu m_menu = {m_items, 0, 0};
1855 e2713e92 2004-04-24 devnull
1856 e2713e92 2004-04-24 devnull
1857 e2713e92 2004-04-24 devnull void do_mmenu(int but, Mouse* m)
1858 e2713e92 2004-04-24 devnull {
1859 e2713e92 2004-04-24 devnull int e, h = emenuhit(but, m, &m_menu);
1860 e2713e92 2004-04-24 devnull switch (h) {
1861 e2713e92 2004-04-24 devnull case Mzoom_in:
1862 e2713e92 2004-04-24 devnull disp_zoomin(egetrect(but,m));
1863 e2713e92 2004-04-24 devnull eresized(0);
1864 e2713e92 2004-04-24 devnull break;
1865 e2713e92 2004-04-24 devnull case Mzoom_out:
1866 e2713e92 2004-04-24 devnull disp_zoomout(egetrect(but,m));
1867 e2713e92 2004-04-24 devnull eresized(0);
1868 e2713e92 2004-04-24 devnull break;
1869 e2713e92 2004-04-24 devnull case Msquare_up:
1870 e2713e92 2004-04-24 devnull disp_squareup();
1871 e2713e92 2004-04-24 devnull eresized(0);
1872 e2713e92 2004-04-24 devnull break;
1873 e2713e92 2004-04-24 devnull case Munzoom:
1874 e2713e92 2004-04-24 devnull init_disp();
1875 e2713e92 2004-04-24 devnull eresized(0);
1876 e2713e92 2004-04-24 devnull break;
1877 e2713e92 2004-04-24 devnull case Mrecenter:
1878 e2713e92 2004-04-24 devnull if (get_1click(but, m, &bullseye)) {
1879 e2713e92 2004-04-24 devnull recenter_disp(m->xy);
1880 e2713e92 2004-04-24 devnull eresized(0);
1881 e2713e92 2004-04-24 devnull lift_button(but, m, Never);
1882 e2713e92 2004-04-24 devnull }
1883 e2713e92 2004-04-24 devnull break;
1884 e2713e92 2004-04-24 devnull case Mslant:
1885 e2713e92 2004-04-24 devnull if (cur_sel.t>=0 && prev_sel.t>=0) {
1886 e2713e92 2004-04-24 devnull slant_disp(prev_sel.p, cur_sel.p);
1887 e2713e92 2004-04-24 devnull eresized(0);
1888 e2713e92 2004-04-24 devnull }
1889 e2713e92 2004-04-24 devnull break;
1890 e2713e92 2004-04-24 devnull case Munslant:
1891 e2713e92 2004-04-24 devnull univ.slant_ht = univ.disp.max.y - univ.disp.min.y;
1892 e2713e92 2004-04-24 devnull eresized(0);
1893 e2713e92 2004-04-24 devnull break;
1894 e2713e92 2004-04-24 devnull case Mrecolor:
1895 e2713e92 2004-04-24 devnull do_recolor(but, m, 1);
1896 e2713e92 2004-04-24 devnull break;
1897 e2713e92 2004-04-24 devnull case Mrestack:
1898 e2713e92 2004-04-24 devnull fps_invert(&univ);
1899 e2713e92 2004-04-24 devnull eresized(0);
1900 e2713e92 2004-04-24 devnull break;
1901 e2713e92 2004-04-24 devnull case Mread:
1902 e2713e92 2004-04-24 devnull e = doinput(prompt_text("File:"));
1903 e2713e92 2004-04-24 devnull if (e==0)
1904 e2713e92 2004-04-24 devnull eresized(0);
1905 e2713e92 2004-04-24 devnull else if (e<0)
1906 e2713e92 2004-04-24 devnull show_mytext(" - can't read");
1907 e2713e92 2004-04-24 devnull else {
1908 e2713e92 2004-04-24 devnull char ebuf[80];
1909 e2713e92 2004-04-24 devnull snprintf(ebuf, 80, " - error line %d", e);
1910 e2713e92 2004-04-24 devnull show_mytext(ebuf);
1911 e2713e92 2004-04-24 devnull }
1912 e2713e92 2004-04-24 devnull break;
1913 e2713e92 2004-04-24 devnull case Mwrite:
1914 e2713e92 2004-04-24 devnull if (!dooutput(prompt_text("File:")))
1915 e2713e92 2004-04-24 devnull show_mytext(" - can't write");
1916 e2713e92 2004-04-24 devnull break;
1917 e2713e92 2004-04-24 devnull case Mexit:
1918 e2713e92 2004-04-24 devnull exits("");
1919 e2713e92 2004-04-24 devnull }
1920 e2713e92 2004-04-24 devnull }
1921 e2713e92 2004-04-24 devnull
1922 e2713e92 2004-04-24 devnull
1923 e2713e92 2004-04-24 devnull
1924 e2713e92 2004-04-24 devnull /****************************** Handling events ******************************/
1925 e2713e92 2004-04-24 devnull
1926 e2713e92 2004-04-24 devnull void doevent(void)
1927 e2713e92 2004-04-24 devnull {
1928 e2713e92 2004-04-24 devnull ulong etype;
1929 e2713e92 2004-04-24 devnull int mobile;
1930 e2713e92 2004-04-24 devnull ulong mvtime;
1931 e2713e92 2004-04-24 devnull Event ev;
1932 e2713e92 2004-04-24 devnull
1933 e2713e92 2004-04-24 devnull etype = eread(Emouse|Ekeyboard, &ev);
1934 e2713e92 2004-04-24 devnull if(etype & Emouse) {
1935 e2713e92 2004-04-24 devnull if (ev.mouse.buttons & But1) {
1936 e2713e92 2004-04-24 devnull do_select(ev.mouse.xy);
1937 e2713e92 2004-04-24 devnull mvtime = Never;
1938 e2713e92 2004-04-24 devnull mobile = !cantmv && cur_sel.t>=0;
1939 e2713e92 2004-04-24 devnull if (mobile) {
1940 e2713e92 2004-04-24 devnull mvtime = ev.mouse.msec + Mv_delay;
1941 e2713e92 2004-04-24 devnull prepare_mv(cur_sel.fp);
1942 b1455f33 2004-04-30 devnull if (!lift_button(1, &ev.mouse, mvtime))
1943 b1455f33 2004-04-30 devnull save_mv(do_move(1, &ev.mouse));
1944 e2713e92 2004-04-24 devnull }
1945 e2713e92 2004-04-24 devnull } else if (ev.mouse.buttons & But2)
1946 e2713e92 2004-04-24 devnull do_emenu(2, &ev.mouse);
1947 e2713e92 2004-04-24 devnull else if (ev.mouse.buttons & But3)
1948 e2713e92 2004-04-24 devnull do_mmenu(3, &ev.mouse);
1949 e2713e92 2004-04-24 devnull }
1950 e2713e92 2004-04-24 devnull /* no need to check (etype & Ekeyboard)--there are no keyboard commands */
1951 e2713e92 2004-04-24 devnull }
1952 e2713e92 2004-04-24 devnull
1953 e2713e92 2004-04-24 devnull
1954 e2713e92 2004-04-24 devnull
1955 e2713e92 2004-04-24 devnull /******************************** Main program ********************************/
1956 e2713e92 2004-04-24 devnull
1957 e2713e92 2004-04-24 devnull extern char* argv0;
1958 e2713e92 2004-04-24 devnull
1959 e2713e92 2004-04-24 devnull void usage(void)
1960 e2713e92 2004-04-24 devnull {
1961 e2713e92 2004-04-24 devnull int i;
1962 e2713e92 2004-04-24 devnull fprintf(stderr,"Usage %s [options] [infile]\n", argv0);
1963 e2713e92 2004-04-24 devnull fprintf(stderr,
1964 be36ff68 2004-04-29 devnull "option ::= -W winsize | -l logfile | -m\n"
1965 e2713e92 2004-04-24 devnull "\n"
1966 e2713e92 2004-04-24 devnull "Read a polygonal line graph in an ASCII format (one x y pair per line, delimited\n"
1967 e2713e92 2004-04-24 devnull "by spaces with a label after each polyline), and view it interactively. Use\n"
1968 e2713e92 2004-04-24 devnull "standard input if no infile is specified.\n"
1969 e2713e92 2004-04-24 devnull "Option -l specifies a file in which to log the coordinates of each point selected.\n"
1970 e2713e92 2004-04-24 devnull "(Clicking a point with button one selects it and displays its coordinates and\n"
1971 e2713e92 2004-04-24 devnull "the label of its polylone.) Option -m allows polylines to be moved and rotated.\n"
1972 e2713e92 2004-04-24 devnull "The polyline labels can use the following color names:"
1973 e2713e92 2004-04-24 devnull );
1974 e2713e92 2004-04-24 devnull for (i=0; clrtab[i].c!=DNofill; i++)
1975 e2713e92 2004-04-24 devnull fprintf(stderr,"%s%8s", (i%8==0 ? "\n" : " "), clrtab[i].nam);
1976 e2713e92 2004-04-24 devnull fputc('\n', stderr);
1977 e2713e92 2004-04-24 devnull exits("usage");
1978 e2713e92 2004-04-24 devnull }
1979 e2713e92 2004-04-24 devnull
1980 e2713e92 2004-04-24 devnull void main(int argc, char *argv[])
1981 e2713e92 2004-04-24 devnull {
1982 e2713e92 2004-04-24 devnull int e;
1983 e2713e92 2004-04-24 devnull
1984 e2713e92 2004-04-24 devnull ARGBEGIN {
1985 e2713e92 2004-04-24 devnull case 'm': cantmv=0;
1986 e2713e92 2004-04-24 devnull break;
1987 e2713e92 2004-04-24 devnull case 'l': logfil = fopen(ARGF(),"w");
1988 e2713e92 2004-04-24 devnull break;
1989 be36ff68 2004-04-29 devnull case 'W':
1990 be36ff68 2004-04-29 devnull winsize = EARGF(usage());
1991 be36ff68 2004-04-29 devnull break;
1992 e2713e92 2004-04-24 devnull default: usage();
1993 e2713e92 2004-04-24 devnull } ARGEND
1994 e2713e92 2004-04-24 devnull
1995 e2713e92 2004-04-24 devnull if(initdraw(0, 0, "gview") < 0)
1996 e2713e92 2004-04-24 devnull exits("initdraw");
1997 e2713e92 2004-04-24 devnull einit(Emouse|Ekeyboard);
1998 e2713e92 2004-04-24 devnull
1999 e2713e92 2004-04-24 devnull e = doinput(*argv ? *argv : "-");
2000 e2713e92 2004-04-24 devnull if (e < 0) {
2001 e2713e92 2004-04-24 devnull fprintf(stderr,"Cannot read input file %s\n", *argv);
2002 e2713e92 2004-04-24 devnull exits("no valid input file");
2003 e2713e92 2004-04-24 devnull } else if (e > 0) {
2004 e2713e92 2004-04-24 devnull fprintf(stderr,"Bad syntax at line %d in input file\n", e);
2005 e2713e92 2004-04-24 devnull exits("bad syntax in input");
2006 e2713e92 2004-04-24 devnull }
2007 e2713e92 2004-04-24 devnull init_disp();
2008 e2713e92 2004-04-24 devnull init_clrtab();
2009 e2713e92 2004-04-24 devnull set_default_clrs(&univ, 0);
2010 e2713e92 2004-04-24 devnull adjust_border(display->defaultfont);
2011 e2713e92 2004-04-24 devnull cur_sel.t = prev_sel.t = -1;
2012 e2713e92 2004-04-24 devnull eresized(0);
2013 e2713e92 2004-04-24 devnull for(;;)
2014 e2713e92 2004-04-24 devnull doevent();
2015 e2713e92 2004-04-24 devnull }