1 /* -*- tab-width: 4 -*-
2 *
3 * Electric(tm) VLSI Design System
4 *
5 * File: usrtrack.c
6 * User interface tool: cursor tracking routines
7 * Written by: Steven M. Rubin, Static Free Software
8 *
9 * Copyright (c) 2000 Static Free Software.
10 *
11 * Electric(tm) is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * Electric(tm) is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with Electric(tm); see the file COPYING. If not, write to
23 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
24 * Boston, Mass 02111-1307, USA.
25 *
26 * Static Free Software
27 * 4119 Alpine Road
28 * Portola Valley, California 94028
29 * info@staticfreesoft.com
30 */
31
32 /*
33 * the code in this module makes me quiver with trepidation whenever it
34 * breaks ... smr
35 */
36 #include "global.h"
37 #include "egraphics.h"
38 #include "usr.h"
39 #include "usrtrack.h"
40 #include "efunction.h"
41 #include "tecart.h"
42 #include "tecgen.h"
43 #include "sim.h"
44
45 #define MAXTRACE 400
46 #define MINSLIDEDELAY 60 /* ticks between shifts of window when dragging to edge */
47 static INTBIG us_tracelist;
48 static INTBIG us_tracedata[MAXTRACE];
49 static GRAPHICS us_highl = {LAYERH, 0, SOLIDC, SOLIDC,
50 {0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,
51 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF,0xFFFF}, NOVARIABLE, 0};
52
53 static INTBIG us_dragx, us_dragy, us_dragox, us_dragoy, us_dragoffx,
54 us_dragoffy, us_lastcurx, us_lastcury, us_dragpoint,
55 us_dragnodetotal, us_cantdrag, us_draglowval, us_draghighval, us_measureshown,
56 us_firstmeasurex, us_firstmeasurey, us_dragshown, us_dragangle, us_dragstate,
57 us_dragfport, us_dragextra, us_dragnobox, us_dragstayonhigh, us_dragstill,
58 us_dragcorner, us_dragspecial;
59 static BOOLEAN us_dragjoinfactor;
60 static BOOLEAN us_multidragshowinvpin, us_multidragshowoffset;
61 static INTBIG us_multidragmostzeros;
62 static UINTBIG us_dragdescript[TEXTDESCRIPTSIZE];
63 static INTBIG us_arrowamount; /* for slider tracking */
64 static INTBIG us_arrowlx, us_arrowhx, us_arrowly, us_arrowhy;
65 static WINDOWPART *us_dragwindow;
66 static POLYGON *us_dragpoly = NOPOLYGON;
67 static NODEPROTO *us_dragnodeproto;
68 static PORTPROTO *us_dragportproto, *us_dragfromport;
69 static NODEINST *us_dragnodeinst, **us_dragnodelist;
70 static ARCINST *us_dragarcinst;
71 static GEOM *us_dragobject, **us_dragobjectlist;
72 static GEOM *us_dragfromgeom;
73 static INTBIG us_dragaddr, us_dragtype;
74 static INTBIG us_dragstartx, us_dragstarty;
75 static INTBIG us_dragwirepathcount;
76 static INTBIG us_dragwirepath[8];
77 static HIGHLIGHT us_draghigh;
78 static CHAR us_dragmessage[100];
79 static UINTBIG us_beforepantime = 0;
80 static INTBIG us_initthumbcoord;
81 static WINDOWPART us_trackww;
82 static INTBIG us_dragtextcount;
83 static CHAR **us_dragtexts;
84 static void (*us_trackingcallback)(INTBIG);
85
86 /* prototypes for local routines */
87 static void us_finddoibegin(BOOLEAN);
88 static void us_multidragdraw(INTBIG, INTBIG, INTBIG);
89 static void us_invertstretch(void);
90 static void us_wanttoinvert(INTBIG fx, INTBIG fy, INTBIG tx, INTBIG ty, WINDOWPART *w);
91 static void us_drawdistance(void);
92 static void us_panatscreenedge(INTBIG *x, INTBIG *y);
93 static void us_wanttoinvert(INTBIG fx, INTBIG fy, INTBIG tx, INTBIG ty, WINDOWPART *w);
94
95 /************************* NODE TRACE *************************/
96
97 /* initialization routine when reading a cursor trace */
us_tracebegin(void)98 void us_tracebegin(void)
99 {
100 us_tracelist = 0;
101 us_highl.col = HIGHLIT;
102 }
103
104 /* cursor advance routine when reading a cursor trace */
us_tracedown(INTBIG x,INTBIG y)105 BOOLEAN us_tracedown(INTBIG x, INTBIG y)
106 {
107 INTBIG fx, fy, tx, ty;
108
109 if (us_tracelist >= MAXTRACE) return(TRUE);
110 if (us_tracelist != 0)
111 {
112 fx = us_tracedata[us_tracelist-2];
113 fy = us_tracedata[us_tracelist-1];
114 tx = x; ty = y;
115 if ((el_curwindowpart->state&INPLACEEDIT) != 0)
116 {
117 xform(fx, fy, &fx, &fy, el_curwindowpart->outofcell);
118 xform(tx, ty, &tx, &ty, el_curwindowpart->outofcell);
119 }
120 screendrawline(el_curwindowpart, fx, fy, tx, ty, &us_highl, 0);
121 }
122 us_tracedata[us_tracelist++] = x;
123 us_tracedata[us_tracelist++] = y;
124 return(FALSE);
125 }
126
127 /* termination routine when reading a cursor trace */
us_traceup(void)128 void us_traceup(void)
129 {
130 REGISTER INTBIG i;
131 INTBIG fx, fy, tx, ty;
132
133 if (us_tracelist == 0)
134 {
135 (void)setval((INTBIG)us_tool, VTOOL, us_commandvarname('T'), (INTBIG)x_("nothing"),
136 VSTRING|VDONTSAVE);
137 return;
138 }
139 (void)setval((INTBIG)us_tool, VTOOL, us_commandvarname('T'), (INTBIG)us_tracedata,
140 (INTBIG)(VINTEGER|VISARRAY|(us_tracelist<<VLENGTHSH)|VDONTSAVE));
141 us_highl.col = 0;
142 for(i=2; i<us_tracelist; i += 2)
143 {
144 fx = us_tracedata[us_tracelist-2];
145 fy = us_tracedata[us_tracelist-1];
146 tx = us_tracedata[us_tracelist];
147 ty = us_tracedata[us_tracelist+1];
148 if ((el_curwindowpart->state&INPLACEEDIT) != 0)
149 {
150 xform(fx, fy, &fx, &fy, el_curwindowpart->outofcell);
151 xform(tx, ty, &tx, &ty, el_curwindowpart->outofcell);
152 }
153 screendrawline(el_curwindowpart, us_tracedata[i-2], us_tracedata[i-1],
154 us_tracedata[i], us_tracedata[i+1], &us_highl, 0);
155 }
156 }
157
158 /* preinitialization routine when creating or moving a point on a node */
us_pointinit(NODEINST * node,INTBIG point)159 void us_pointinit(NODEINST *node, INTBIG point)
160 {
161 us_dragnodeinst = node;
162 us_dragpoint = point;
163 }
164
165 /* initialization routine when creating or moving a point on a node */
us_pointbegin(void)166 void us_pointbegin(void)
167 {
168 /* initialize polygon */
169 if (us_dragpoly == NOPOLYGON) us_dragpoly = allocpolygon(4, us_tool->cluster);
170 us_dragpoly->desc = &us_highl;
171
172 us_dragshown = 0;
173 (void)getxy(&us_dragx, &us_dragy);
174 us_dragwindow = el_curwindowpart;
175 }
176
177 /* initialization routine when finding and moving a point on a node */
us_findpointbegin(void)178 void us_findpointbegin(void)
179 {
180 REGISTER VARIABLE *highvar;
181 HIGHLIGHT newhigh;
182
183 /* initialize polygon */
184 if (us_dragpoly == NOPOLYGON) us_dragpoly = allocpolygon(4, us_tool->cluster);
185 us_dragpoly->desc = &us_highl;
186
187 us_dragshown = 0;
188 if (getxy(&us_dragx, &us_dragy)) return;
189 gridalign(&us_dragx, &us_dragy, 1, el_curlib->curnodeproto);
190 us_setcursorpos(NOWINDOWFRAME, us_dragx, us_dragy);
191 us_dragwindow = el_curwindowpart;
192
193 /* select the current point on the node */
194 highvar = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
195 if (highvar == NOVARIABLE) return;
196 (void)us_makehighlight(((CHAR **)highvar->addr)[0], &newhigh);
197 newhigh.fromport = NOPORTPROTO;
198 newhigh.cell = getcurcell();
199 us_setfind(&newhigh, 1, 0, 0, 0);
200
201 /* get the point to be moved */
202 highvar = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
203 if (highvar == NOVARIABLE) return;
204 (void)us_makehighlight(((CHAR **)highvar->addr)[0], &newhigh);
205 us_dragpoint = newhigh.frompoint;
206 }
207
208 /* cursor advance routine when creating a point on a node */
us_addpdown(INTBIG x,INTBIG y)209 BOOLEAN us_addpdown(INTBIG x, INTBIG y)
210 {
211 REGISTER INTBIG p, size;
212 REGISTER INTBIG cx, cy;
213 XARRAY trans;
214 REGISTER VARIABLE *var;
215
216 /* pan the screen if the edge was hit */
217 us_panatscreenedge(&x, &y);
218
219 /* grid align the cursor value */
220 if (us_setxy(x, y) || us_dragwindow != el_curwindowpart)
221 {
222 (void)us_setxy(us_lastcurx, us_lastcury);
223 return(FALSE);
224 }
225 (void)getxy(&us_lastcurx, &us_lastcury);
226 gridalign(&us_lastcurx, &us_lastcury, 1, el_curlib->curnodeproto);
227 us_setcursorpos(NOWINDOWFRAME, us_lastcurx, us_lastcury);
228
229 /* if the lines are already being shown, erase them */
230 if (us_dragshown != 0)
231 {
232 /* if it didn't actually move, go no further */
233 if (us_dragx == us_lastcurx && us_dragy == us_lastcury) return(FALSE);
234
235 /* undraw the box */
236 us_highl.col = 0;
237 us_showpoly(us_dragpoly, us_dragwindow);
238 }
239
240 makerot(us_dragnodeinst, trans);
241 var = gettrace(us_dragnodeinst);
242 if (var == NOVARIABLE)
243 {
244 us_dragpoly->xv[0] = us_lastcurx;
245 us_dragpoly->yv[0] = us_lastcury;
246 us_dragpoly->count = 1;
247 us_dragpoly->style = CROSS;
248 } else
249 {
250 size = getlength(var) / 2;
251 cx = (us_dragnodeinst->lowx + us_dragnodeinst->highx) / 2;
252 cy = (us_dragnodeinst->lowy + us_dragnodeinst->highy) / 2;
253 p = 0;
254 if (us_dragpoint > 0 && us_dragpoint <= size)
255 {
256 xform(((INTBIG *)var->addr)[(us_dragpoint-1)*2] + cx,
257 ((INTBIG *)var->addr)[(us_dragpoint-1)*2+1] + cy,
258 &us_dragpoly->xv[p], &us_dragpoly->yv[p], trans);
259 p++;
260 }
261 us_dragpoly->xv[p] = us_lastcurx;
262 us_dragpoly->yv[p] = us_lastcury;
263 p++;
264 if (us_dragpoint < size)
265 {
266 xform(((INTBIG *)var->addr)[us_dragpoint*2] + cx,
267 ((INTBIG *)var->addr)[us_dragpoint*2+1] + cy,
268 &us_dragpoly->xv[p], &us_dragpoly->yv[p], trans);
269 p++;
270 }
271 us_dragpoly->count = p;
272 us_dragpoly->style = OPENED;
273 }
274
275 us_dragx = us_lastcurx;
276 us_dragy = us_lastcury;
277
278 /* draw the new box */
279 us_highl.col = HIGHLIT;
280 us_showpoly(us_dragpoly, us_dragwindow);
281 us_dragshown = 1;
282 return(FALSE);
283 }
284
285 /* cursor advance routine when moving a point on a node */
us_movepdown(INTBIG x,INTBIG y)286 BOOLEAN us_movepdown(INTBIG x, INTBIG y)
287 {
288 REGISTER INTBIG p, size;
289 REGISTER INTBIG cx, cy;
290 XARRAY trans;
291 REGISTER VARIABLE *var;
292
293 /* pan the screen if the edge was hit */
294 us_panatscreenedge(&x, &y);
295
296 /* grid align the cursor value */
297 if (us_setxy(x, y) || us_dragwindow != el_curwindowpart)
298 {
299 (void)us_setxy(us_lastcurx, us_lastcury);
300 return(FALSE);
301 }
302 (void)getxy(&us_lastcurx, &us_lastcury);
303 gridalign(&us_lastcurx, &us_lastcury, 1, el_curlib->curnodeproto);
304 us_setcursorpos(NOWINDOWFRAME, us_lastcurx, us_lastcury);
305
306 /* if the lines are already being shown, erase them */
307 if (us_dragshown != 0)
308 {
309 /* if it didn't actually move, go no further */
310 if (us_dragx == us_lastcurx && us_dragy == us_lastcury) return(FALSE);
311
312 /* undraw the box */
313 us_highl.col = 0;
314 us_showpoly(us_dragpoly, us_dragwindow);
315 }
316
317 makerot(us_dragnodeinst, trans);
318 var = gettrace(us_dragnodeinst);
319 if (var == NOVARIABLE) return(FALSE);
320
321 size = getlength(var) / 2;
322 cx = (us_dragnodeinst->lowx + us_dragnodeinst->highx) / 2;
323 cy = (us_dragnodeinst->lowy + us_dragnodeinst->highy) / 2;
324 p = 0;
325 if (us_dragpoint > 1)
326 {
327 xform(((INTBIG *)var->addr)[(us_dragpoint-2)*2] + cx,
328 ((INTBIG *)var->addr)[(us_dragpoint-2)*2+1] + cy,
329 &us_dragpoly->xv[p], &us_dragpoly->yv[p], trans);
330 p++;
331 }
332 us_dragpoly->xv[p] = us_lastcurx;
333 us_dragpoly->yv[p] = us_lastcury;
334 p++;
335 if (us_dragpoint < size)
336 {
337 xform(((INTBIG *)var->addr)[us_dragpoint*2] + cx,
338 ((INTBIG *)var->addr)[us_dragpoint*2+1] + cy,
339 &us_dragpoly->xv[p], &us_dragpoly->yv[p], trans);
340 p++;
341 }
342 us_dragpoly->count = p;
343 us_dragpoly->style = OPENED;
344
345 us_dragx = us_lastcurx;
346 us_dragy = us_lastcury;
347
348 /* draw the new box */
349 us_highl.col = HIGHLIT;
350 us_showpoly(us_dragpoly, us_dragwindow);
351 us_dragshown = 1;
352 return(FALSE);
353 }
354
355 /************************* ARC CURVATURE *************************/
356
357 /* initialization routine when changing an arc's curvature */
us_arccurveinit(ARCINST * ai)358 void us_arccurveinit(ARCINST *ai)
359 {
360 us_dragarcinst = ai;
361 us_dragwindow = el_curwindowpart;
362 }
363
364 /*
365 * Routine for changing the curvature of an arc so that it pass through (x,y)
366 */
us_arccurvedown(INTBIG x,INTBIG y)367 BOOLEAN us_arccurvedown(INTBIG x, INTBIG y)
368 {
369 INTBIG xcur, ycur, r;
370
371 /* grid align the cursor value */
372 if (us_dragwindow != el_curwindowpart) return(FALSE);
373 if (us_setxy(x, y)) return(FALSE);
374 (void)getxy(&xcur, &ycur);
375
376 /* get radius that lets arc curve through this point */
377 r = us_curvearcthroughpoint(us_dragarcinst, xcur, ycur);
378
379 startobjectchange((INTBIG)us_dragarcinst, VARCINST);
380 (void)setvalkey((INTBIG)us_dragarcinst, VARCINST, el_arc_radius_key, r, VINTEGER);
381 (void)modifyarcinst(us_dragarcinst, 0, 0, 0, 0, 0);
382 endobjectchange((INTBIG)us_dragarcinst, VARCINST);
383 us_endchanges(NOWINDOWPART);
384 return(FALSE);
385 }
386
387 /*
388 * Routine for changing the curvature of an arc so that it curves around (x,y)
389 * (that coordinate is the center)
390 */
us_arccenterdown(INTBIG x,INTBIG y)391 BOOLEAN us_arccenterdown(INTBIG x, INTBIG y)
392 {
393 INTBIG xcur, ycur;
394 REGISTER INTBIG r;
395
396 /* grid align the cursor value */
397 if (us_dragwindow != el_curwindowpart) return(FALSE);
398 if (us_setxy(x, y)) return(FALSE);
399 (void)getxy(&xcur, &ycur);
400
401 /* get radius that lets arc curve about this point */
402 r = us_curvearcaboutpoint(us_dragarcinst, xcur, ycur);
403
404 startobjectchange((INTBIG)us_dragarcinst, VARCINST);
405 (void)setvalkey((INTBIG)us_dragarcinst, VARCINST, el_arc_radius_key, r, VINTEGER);
406 (void)modifyarcinst(us_dragarcinst, 0, 0, 0, 0, 0);
407 endobjectchange((INTBIG)us_dragarcinst, VARCINST);
408 us_endchanges(NOWINDOWPART);
409 return(FALSE);
410 }
411
412 /************************* TEXT GRAB-POINT *************************/
413
414 /* preinitialization routine when positioning text's grab point */
us_textgrabinit(UINTBIG * olddescript,INTBIG xw,INTBIG yw,INTBIG xc,INTBIG yc,GEOM * geom)415 void us_textgrabinit(UINTBIG *olddescript, INTBIG xw, INTBIG yw, INTBIG xc, INTBIG yc,
416 GEOM *geom)
417 {
418 /* save text extent information */
419 TDCOPY(us_dragdescript, olddescript);
420 us_dragx = xc; us_dragy = yc;
421 us_dragox = xw; us_dragoy = yw;
422 us_dragobject = geom;
423 }
424
425 /* initialization routine when positioning text's grab-point */
us_textgrabbegin(void)426 void us_textgrabbegin(void)
427 {
428 /* initialize polygon */
429 if (us_dragpoly == NOPOLYGON) us_dragpoly = allocpolygon(4, us_tool->cluster);
430 us_dragpoly->desc = &us_highl;
431
432 us_dragshown = 0;
433 us_dragwindow = el_curwindowpart;
434 }
435
436 /* cursor advance routine when positioning text's grab-point */
us_textgrabdown(INTBIG x,INTBIG y)437 BOOLEAN us_textgrabdown(INTBIG x, INTBIG y)
438 {
439 UINTBIG descript[TEXTDESCRIPTSIZE];
440 REGISTER INTBIG style;
441 REGISTER NODEINST *ni;
442 XARRAY trans;
443
444 /* get the cursor value */
445 if (us_setxy(x, y) || us_dragwindow != el_curwindowpart)
446 {
447 (void)us_setxy(us_lastcurx, us_lastcury);
448 return(FALSE);
449 }
450 (void)getxy(&us_lastcurx, &us_lastcury);
451
452 /* if the box is already being shown, erase it */
453 if (us_dragshown != 0)
454 {
455 /* undraw the box */
456 us_highl.col = 0;
457 us_showpoly(us_dragpoly, us_dragwindow);
458 }
459
460 /* convert the cursor position into a text descriptor */
461 TDCOPY(descript, us_dragdescript);
462 us_figuregrabpoint(descript, us_lastcurx, us_lastcury,
463 us_dragx, us_dragy, us_dragox, us_dragoy);
464 us_rotatedescriptI(us_dragobject, descript);
465
466 /* convert the text descriptor into a GRAPHICS style */
467 switch (TDGETPOS(descript))
468 {
469 case VTPOSCENT: style = TEXTCENT; break;
470 case VTPOSBOXED: style = TEXTBOX; break;
471 case VTPOSUP: style = TEXTBOT; break;
472 case VTPOSDOWN: style = TEXTTOP; break;
473 case VTPOSLEFT: style = TEXTRIGHT; break;
474 case VTPOSRIGHT: style = TEXTLEFT; break;
475 case VTPOSUPLEFT: style = TEXTBOTRIGHT; break;
476 case VTPOSUPRIGHT: style = TEXTBOTLEFT; break;
477 case VTPOSDOWNLEFT: style = TEXTTOPRIGHT; break;
478 case VTPOSDOWNRIGHT: style = TEXTTOPLEFT; break;
479 }
480 if (us_dragobject->entryisnode)
481 {
482 ni = us_dragobject->entryaddr.ni;
483 makeangle(ni->rotation, ni->transpose, trans);
484 style = rotatelabel(style, TDGETROTATION(descript), trans);
485 }
486
487 /* convert the text descriptor into a POLYGON */
488 us_buildtexthighpoly(us_dragobject->lowx, us_dragobject->highx,
489 us_dragobject->lowy, us_dragobject->highy, us_dragx, us_dragy, us_dragox, us_dragoy,
490 style, us_dragpoly);
491
492 /* draw the new box */
493 us_highl.col = HIGHLIT;
494 us_showpoly(us_dragpoly, us_dragwindow);
495 us_dragshown = 1;
496 return(FALSE);
497 }
498
499 /************************* ROTATE *************************/
500
501 /* preinitialization routine when rotating a node */
us_rotateinit(NODEINST * node)502 void us_rotateinit(NODEINST *node)
503 {
504 us_dragnodeinst = node;
505 }
506
507 /* initialization routine when rotating a node */
us_rotatebegin(void)508 void us_rotatebegin(void)
509 {
510 /* initialize polygon */
511 if (us_dragpoly == NOPOLYGON) us_dragpoly = allocpolygon(4, us_tool->cluster);
512 us_dragpoly->desc = &us_highl;
513
514 (void)getxy(&us_dragx, &us_dragy);
515 us_dragshown = 0;
516 us_dragwindow = el_curwindowpart;
517 us_dragangle = figureangle((us_dragnodeinst->lowx+us_dragnodeinst->highx)/2,
518 (us_dragnodeinst->lowy+us_dragnodeinst->highy)/2, us_dragx, us_dragy);
519 }
520
521 /* cursor advance routine when rotating the current node */
us_rotatedown(INTBIG x,INTBIG y)522 BOOLEAN us_rotatedown(INTBIG x, INTBIG y)
523 {
524 REGISTER INTBIG lx, hx, ly, hy;
525 REGISTER INTBIG newangle;
526 REGISTER INTSML saver, savet;
527 XARRAY trans;
528 INTBIG xl, yl, xh, yh;
529
530 /* grid align the cursor value */
531 if (us_setxy(x, y) || us_dragwindow != el_curwindowpart)
532 {
533 (void)us_setxy(us_lastcurx, us_lastcury);
534 return(FALSE);
535 }
536 (void)getxy(&us_lastcurx, &us_lastcury);
537
538 /* if the box is already being shown, erase it */
539 if (us_dragshown != 0)
540 {
541 /* undraw the box */
542 us_highl.col = 0;
543 us_showpoly(us_dragpoly, us_dragwindow);
544 }
545
546 /* compute new angle from node center to cursor */
547 newangle = figureangle((us_dragnodeinst->lowx+us_dragnodeinst->highx)/2,
548 (us_dragnodeinst->lowy+us_dragnodeinst->highy)/2, us_lastcurx, us_lastcury);
549
550 /* compute highlighted box about node */
551 nodesizeoffset(us_dragnodeinst, &xl, &yl, &xh, &yh);
552 lx = us_dragnodeinst->lowx+xl; hx = us_dragnodeinst->highx-xh;
553 ly = us_dragnodeinst->lowy+yl; hy = us_dragnodeinst->highy-yh;
554 makerot(us_dragnodeinst, trans);
555 maketruerectpoly(lx, hx, ly, hy, us_dragpoly);
556 us_dragpoly->style = CLOSEDRECT;
557 xformpoly(us_dragpoly, trans);
558
559 /* rotate this box according to the cursor */
560 saver = us_dragnodeinst->rotation;
561 savet = us_dragnodeinst->transpose;
562 us_dragnodeinst->transpose = 0;
563 us_dragnodeinst->rotation = (INTSML)(newangle-us_dragangle);
564 while (us_dragnodeinst->rotation < 0) us_dragnodeinst->rotation += 3600;
565 while (us_dragnodeinst->rotation > 3600) us_dragnodeinst->rotation -= 3600;
566 makerot(us_dragnodeinst, trans);
567 xformpoly(us_dragpoly, trans);
568 us_dragnodeinst->rotation = saver;
569 us_dragnodeinst->transpose = savet;
570
571 /* draw the new box */
572 us_highl.col = HIGHLIT;
573 us_showpoly(us_dragpoly, us_dragwindow);
574 us_dragshown = 1;
575 return(FALSE);
576 }
577
578 /************************* SIZE *************************/
579
580 /* preinitialization routine when changing the size of a node */
us_sizeinit(NODEINST * node)581 void us_sizeinit(NODEINST *node)
582 {
583 /* initialize polygon */
584 if (us_dragpoly == NOPOLYGON) us_dragpoly = allocpolygon(4, us_tool->cluster);
585 us_dragpoly->desc = &us_highl;
586 us_dragnodeinst = node;
587 us_dragshown = 0;
588 us_dragwindow = el_curwindowpart;
589 us_dragcorner = -1;
590 }
591
us_sizeterm(void)592 INTBIG us_sizeterm(void)
593 {
594 return(us_dragcorner);
595 }
596
597 /* preinitialization routine when changing the size of an arc */
us_sizeainit(ARCINST * arc)598 void us_sizeainit(ARCINST *arc)
599 {
600 us_dragarcinst = arc;
601 }
602
603 /* initialization routine when changing the size of an arc */
us_sizeabegin(void)604 void us_sizeabegin(void)
605 {
606 /* initialize polygon */
607 if (us_dragpoly == NOPOLYGON) us_dragpoly = allocpolygon(4, us_tool->cluster);
608 us_dragpoly->desc = &us_highl;
609
610 us_dragshown = 0;
611 us_dragwindow = el_curwindowpart;
612 }
613
614 /* cursor advance routine when stretching the current arc */
us_sizeadown(INTBIG x,INTBIG y)615 BOOLEAN us_sizeadown(INTBIG x, INTBIG y)
616 {
617 REGISTER INTBIG wid;
618
619 /* pan the screen if the edge was hit */
620 us_panatscreenedge(&x, &y);
621
622 /* grid align the cursor value */
623 if (us_setxy(x, y) || us_dragwindow != el_curwindowpart)
624 {
625 (void)us_setxy(us_lastcurx, us_lastcury);
626 return(FALSE);
627 }
628 (void)getxy(&us_lastcurx, &us_lastcury);
629 gridalign(&us_lastcurx, &us_lastcury, 2, el_curlib->curnodeproto);
630 us_setcursorpos(NOWINDOWFRAME, us_lastcurx, us_lastcury);
631
632 /* if the box is already being shown, erase it */
633 if (us_dragshown != 0)
634 {
635 /* if it didn't actually move, go no further */
636 if (us_dragx == us_lastcurx && us_dragy == us_lastcury) return(FALSE);
637
638 /* undraw the box */
639 us_highl.col = 0;
640 us_showpoly(us_dragpoly, us_dragwindow);
641 }
642
643 /* compute new size of the arcinst */
644 if (us_dragarcinst->end[0].xpos == us_dragarcinst->end[1].xpos)
645 wid = abs(us_lastcurx - us_dragarcinst->end[0].xpos) * 2; else
646 wid = abs(us_lastcury - us_dragarcinst->end[0].ypos) * 2;
647 makearcpoly(us_dragarcinst->length, wid, us_dragarcinst, us_dragpoly, CLOSED);
648 us_dragx = us_lastcurx;
649 us_dragy = us_lastcury;
650
651 /* draw the new box */
652 us_highl.col = HIGHLIT;
653 us_showpoly(us_dragpoly, us_dragwindow);
654 us_dragshown = 1;
655 return(FALSE);
656 }
657
658 /* cursor advance routine when stretching the current node about far corner */
us_sizedown(INTBIG x,INTBIG y)659 BOOLEAN us_sizedown(INTBIG x, INTBIG y)
660 {
661 REGISTER INTBIG lx, hx, ly, hy, otherx, othery, dist, bestdist;
662 INTBIG xl, xh, yl, yh, rx, ry;
663 REGISTER INTBIG corner, bits;
664 XARRAY trans;
665
666 /* pan the screen if the edge was hit */
667 us_panatscreenedge(&x, &y);
668
669 /* grid align the cursor value */
670 if (us_setxy(x, y) || us_dragwindow != el_curwindowpart)
671 {
672 (void)us_setxy(us_lastcurx, us_lastcury);
673 return(FALSE);
674 }
675 (void)getxy(&us_lastcurx, &us_lastcury);
676 gridalign(&us_lastcurx, &us_lastcury, 1, el_curlib->curnodeproto);
677 us_setcursorpos(NOWINDOWFRAME, us_lastcurx, us_lastcury);
678
679 /* if the box is already being shown, erase it */
680 if (us_dragshown != 0)
681 {
682 /* if it didn't actually move, go no further */
683 if (us_dragx == us_lastcurx && us_dragy == us_lastcury) return(FALSE);
684
685 /* undraw the box */
686 us_highl.col = 0;
687 us_showpoly(us_dragpoly, us_dragwindow);
688 }
689
690 nodesizeoffset(us_dragnodeinst, &xl, &yl, &xh, &yh);
691 lx = us_dragnodeinst->lowx+xl; hx = us_dragnodeinst->highx-xh;
692 ly = us_dragnodeinst->lowy+yl; hy = us_dragnodeinst->highy-yh;
693 makerot(us_dragnodeinst, trans);
694
695 /* determine which corner is fixed by finding farthest from cursor */
696 corner = us_dragcorner;
697 if (corner < 0)
698 {
699 xform(lx, ly, &rx, &ry, trans);
700 bestdist = abs(rx - us_lastcurx) + abs(ry - us_lastcury);
701 corner = 1; /* lower-left */
702 xform(hx, ly, &rx, &ry, trans);
703 dist = abs(rx - us_lastcurx) + abs(ry - us_lastcury);
704 if (dist < bestdist)
705 {
706 bestdist = dist; corner = 2; /* lower-right */
707 }
708 xform(lx, hy, &rx, &ry, trans);
709 dist = abs(rx - us_lastcurx) + abs(ry - us_lastcury);
710 if (dist < bestdist)
711 {
712 bestdist = dist; corner = 3; /* upper-left */
713 }
714 xform(hx, hy, &rx, &ry, trans);
715 dist = abs(rx - us_lastcurx) + abs(ry - us_lastcury);
716 if (dist < bestdist) corner = 4; /* upper-right */
717 if (us_dragcorner < 0) us_dragcorner = corner;
718 }
719
720 bits = getbuckybits();
721 switch (corner)
722 {
723 case 1: /* lower-left */
724 otherx = hx; othery = hy;
725 if ((bits&CONTROLDOWN) != 0)
726 {
727 xform(lx, ly, &rx, &ry, trans);
728 if (abs(rx-us_lastcurx) < abs(ry-us_lastcury)) us_lastcurx = rx; else
729 us_lastcury = ry;
730 }
731 break;
732 case 2: /* lower-right */
733 otherx = lx; othery = hy;
734 if ((bits&CONTROLDOWN) != 0)
735 {
736 xform(hx, ly, &rx, &ry, trans);
737 if (abs(rx-us_lastcurx) < abs(ry-us_lastcury)) us_lastcurx = rx; else
738 us_lastcury = ry;
739 }
740 break;
741 case 3: /* upper-left */
742 otherx = hx; othery = ly;
743 if ((bits&CONTROLDOWN) != 0)
744 {
745 xform(lx, hy, &rx, &ry, trans);
746 if (abs(rx-us_lastcurx) < abs(ry-us_lastcury)) us_lastcurx = rx; else
747 us_lastcury = ry;
748 }
749 break;
750 case 4: /* upper-right */
751 otherx = lx; othery = ly;
752 if ((bits&CONTROLDOWN) != 0)
753 {
754 xform(hx, hy, &rx, &ry, trans);
755 if (abs(rx-us_lastcurx) < abs(ry-us_lastcury)) us_lastcurx = rx; else
756 us_lastcury = ry;
757 }
758 break;
759 }
760 xform(otherx, othery, &rx, &ry, trans);
761 maketruerectpoly(mini(rx, us_lastcurx), maxi(rx, us_lastcurx),
762 mini(ry, us_lastcury), maxi(ry, us_lastcury), us_dragpoly);
763 us_dragpoly->style = CLOSEDRECT;
764 us_dragx = us_lastcurx;
765 us_dragy = us_lastcury;
766
767 /* draw the new box */
768 us_highl.col = HIGHLIT;
769 us_showpoly(us_dragpoly, us_dragwindow);
770 us_dragshown = 1;
771 return(FALSE);
772 }
773
774 /* cursor advance routine when stretching the current node about center */
us_sizecdown(INTBIG x,INTBIG y)775 BOOLEAN us_sizecdown(INTBIG x, INTBIG y)
776 {
777 REGISTER INTBIG dx, dy, cx, cy;
778
779 /* pan the screen if the edge was hit */
780 us_panatscreenedge(&x, &y);
781
782 /* grid align the cursor value */
783 if (us_setxy(x, y) || us_dragwindow != el_curwindowpart)
784 {
785 (void)us_setxy(us_lastcurx, us_lastcury);
786 return(FALSE);
787 }
788 (void)getxy(&us_lastcurx, &us_lastcury);
789 gridalign(&us_lastcurx, &us_lastcury, 2, el_curlib->curnodeproto);
790 us_setcursorpos(NOWINDOWFRAME, us_lastcurx, us_lastcury);
791
792 /* if the box is already being shown, erase it */
793 if (us_dragshown != 0)
794 {
795 /* if it didn't actually move, go no further */
796 if (us_dragx == us_lastcurx && us_dragy == us_lastcury) return(FALSE);
797
798 /* undraw the box */
799 us_highl.col = 0;
800 us_showpoly(us_dragpoly, us_dragwindow);
801 }
802
803 /* compute new size of the nodeinst */
804 cx = (us_dragnodeinst->lowx+us_dragnodeinst->highx) / 2;
805 cy = (us_dragnodeinst->lowy+us_dragnodeinst->highy) / 2;
806 dx = abs(cx - us_lastcurx);
807 dy = abs(cy - us_lastcury);
808
809 maketruerectpoly(cx-dx, cx+dx, cy-dy, cy+dy, us_dragpoly);
810 us_dragpoly->style = CLOSEDRECT;
811 us_dragx = us_lastcurx;
812 us_dragy = us_lastcury;
813
814 /* draw the new box */
815 us_highl.col = HIGHLIT;
816 us_showpoly(us_dragpoly, us_dragwindow);
817 us_dragshown = 1;
818 return(FALSE);
819 }
820
821 /************************* FIND AREA *************************/
822
823 /* pre-initialization routine when doing "find area-XXXX" */
us_findinit(INTBIG sizex,INTBIG sizey)824 void us_findinit(INTBIG sizex, INTBIG sizey)
825 {
826 us_dragox = sizex;
827 us_dragoy = sizey;
828 }
829
830 /* initialization routine when doing "find area-move" */
us_findmbegin(void)831 void us_findmbegin(void)
832 {
833 INTBIG xcur, ycur;
834
835 /* initialize polygon */
836 if (us_dragpoly == NOPOLYGON) us_dragpoly = allocpolygon(4, us_tool->cluster);
837 us_dragpoly->desc = &us_highl;
838
839 us_dragshown = 0;
840 (void)getxy(&xcur, &ycur);
841 maketruerectpoly(xcur, xcur+us_dragox, ycur, ycur+us_dragoy, us_dragpoly);
842 us_dragpoly->style = CLOSEDRECT;
843 us_dragx = xcur; us_dragy = ycur;
844 us_dragwindow = el_curwindowpart;
845 }
846
847 /* initialization routine when doing "find area-size" */
us_findsbegin(void)848 void us_findsbegin(void)
849 {
850 INTBIG xcur, ycur;
851
852 /* initialize polygon */
853 if (us_dragpoly == NOPOLYGON) us_dragpoly = allocpolygon(4, us_tool->cluster);
854 us_dragpoly->desc = &us_highl;
855
856 us_dragshown = 0;
857 (void)getxy(&xcur, &ycur);
858 maketruerectpoly(us_dragox, xcur, us_dragoy, ycur, us_dragpoly);
859 us_dragpoly->style = CLOSEDRECT;
860 us_dragx = xcur; us_dragy = ycur;
861 us_dragwindow = el_curwindowpart;
862 }
863
864 /* initialization routine when doing "find area-define" */
us_finddbegin(void)865 void us_finddbegin(void)
866 {
867 INTBIG xcur, ycur;
868
869 /* initialize polygon */
870 if (us_dragpoly == NOPOLYGON) us_dragpoly = allocpolygon(4, us_tool->cluster);
871 us_dragpoly->desc = &us_highl;
872
873 us_dragshown = 0;
874 (void)getxy(&xcur, &ycur);
875 us_setcursorpos(NOWINDOWFRAME, xcur, ycur);
876 us_dragox = xcur;
877 us_dragoy = ycur;
878 maketruerectpoly(us_dragox, xcur, us_dragoy, ycur, us_dragpoly);
879 us_dragpoly->style = CLOSEDRECT;
880 us_dragx = xcur; us_dragy = ycur;
881 us_dragwindow = el_curwindowpart;
882 }
883
884 /* posttermination routine when doing "find area-define" */
us_finddterm(INTBIG * x,INTBIG * y)885 void us_finddterm(INTBIG *x, INTBIG *y)
886 {
887 *x = us_dragox;
888 *y = us_dragoy;
889 }
890
891 /************************* FIND INTERACTIVE *************************/
892
us_findiinit(INTBIG findport,INTBIG extrainfo,INTBIG findangle,INTBIG stayonhighlighted,INTBIG findstill,INTBIG findnobox,INTBIG findspecial)893 void us_findiinit(INTBIG findport, INTBIG extrainfo, INTBIG findangle, INTBIG stayonhighlighted,
894 INTBIG findstill, INTBIG findnobox, INTBIG findspecial)
895 {
896 us_dragfport = findport;
897 us_dragextra = (extrainfo != 0 ? 1 : 0);
898 us_dragangle = findangle;
899 us_dragstill = findstill;
900 us_dragnobox = findnobox;
901 us_dragspecial = findspecial;
902 us_dragpoint = -1;
903 us_dragstayonhigh = stayonhighlighted;
904 }
905
us_findcibegin(void)906 void us_findcibegin(void)
907 {
908 us_finddoibegin(TRUE);
909 }
910
us_findibegin(void)911 void us_findibegin(void)
912 {
913 us_finddoibegin(FALSE);
914 }
915
916 static UINTBIG us_initialtime, us_motiondelayafterselection;
917
us_finddoibegin(BOOLEAN complement)918 void us_finddoibegin(BOOLEAN complement)
919 {
920 REGISTER VARIABLE *highvar;
921 REGISTER NODEINST *ni;
922 REGISTER PORTPROTO *pp;
923 REGISTER VARIABLE *var;
924 REGISTER INTBIG len, another;
925 HIGHLIGHT newhigh, oldhigh;
926 INTBIG i;
927 INTBIG xcur, ycur, dist, bestdist;
928
929 /* remember initial time of this action */
930 us_initialtime = ticktime();
931 var = getvalkey((INTBIG)us_tool, VTOOL, VFRACT, us_motiondelaykey);
932 if (var == NOVARIABLE) us_motiondelayafterselection = 30; else
933 us_motiondelayafterselection = var->addr * 30 / WHOLE;
934
935 /* initialize polygon */
936 (void)needstaticpolygon(&us_dragpoly, 4, us_tool->cluster);
937 us_dragpoly->desc = &us_highl;
938 us_dragstate = -1;
939 us_dragshown = 0;
940 us_dragtextcount = 0;
941 us_dragwindow = el_curwindowpart;
942
943 /* get cursor coordinates */
944 if (getxy(&xcur, &ycur)) return;
945 us_dragx = xcur; us_dragy = ycur;
946 us_dragox = us_dragx; us_dragoy = us_dragy;
947 us_dragnodeproto = getcurcell();
948
949 /* see what is highlighted */
950 highvar = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
951 if (highvar != NOVARIABLE)
952 {
953 len = getlength(highvar);
954 (void)us_makehighlight(((CHAR **)highvar->addr)[0], &newhigh);
955 } else
956 {
957 len = 0;
958 newhigh.status = 0;
959 newhigh.fromgeom = NOGEOM;
960 newhigh.fromport = NOPORTPROTO;
961 newhigh.fromvar = NOVARIABLE;
962 newhigh.fromvarnoeval = NOVARIABLE;
963 newhigh.frompoint = 0;
964 }
965
966 /* see what is under the cursor */
967 if (us_dragstayonhigh != 0 && highvar != NOVARIABLE)
968 {
969 /* see if the cursor is over something highlighted */
970 for(i=0; i<len; i++)
971 {
972 (void)us_makehighlight(((CHAR **)highvar->addr)[i], &oldhigh);
973 if (us_cursoroverhigh(&oldhigh, xcur, ycur, el_curwindowpart)) break;
974 }
975 if (i < len)
976 {
977 /* re-find the closest port when one node is selected */
978 (void)us_makehighlight(((CHAR **)highvar->addr)[i], &newhigh);
979 if (len == 1 && (newhigh.status&HIGHFROM) != 0 &&
980 newhigh.fromgeom->entryisnode)
981 {
982 ni = newhigh.fromgeom->entryaddr.ni;
983 newhigh.fromport = NOPORTPROTO;
984 for(pp = ni->proto->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
985 {
986 shapeportpoly(ni, pp, us_dragpoly, FALSE);
987 us_dragpoly->desc = &us_highl;
988
989 /* get distance of desired point to polygon */
990 dist = polydistance(us_dragpoly, xcur, ycur);
991 if (dist < 0)
992 {
993 newhigh.fromport = pp;
994 break;
995 }
996 if (newhigh.fromport == NOPORTPROTO) bestdist = dist;
997 if (dist > bestdist) continue;
998 bestdist = dist; newhigh.fromport = pp;
999 }
1000 }
1001 } else
1002 {
1003 /* control NOT held, nothing under cursor */
1004 us_findobject(xcur, ycur, el_curwindowpart, &newhigh, 0, 0, us_dragfport, 1, us_dragspecial);
1005 }
1006 } else
1007 {
1008 another = 0;
1009 if (complement)
1010 {
1011 /* control-shift held or nothing highlighted and shift held */
1012 if (len > 0)
1013 {
1014 for(i=0; i<len; i++)
1015 {
1016 (void)us_makehighlight(((CHAR **)highvar->addr)[i], &newhigh);
1017 if (us_cursoroverhigh(&newhigh, xcur, ycur, el_curwindowpart)) break;
1018 }
1019 if (i < len)
1020 {
1021 /* remove current highlight, find another */
1022 another = 1;
1023 us_delhighlight(&newhigh);
1024 highvar = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
1025 if (highvar == NOVARIABLE) len = 0; else
1026 len = getlength(highvar);
1027 }
1028 us_findobject(xcur, ycur, el_curwindowpart, &newhigh, 0, another, us_dragfport,
1029 1, us_dragspecial);
1030 }
1031 } else
1032 {
1033 /* control held or nothing highlighted */
1034 us_findobject(xcur, ycur, el_curwindowpart, &newhigh, 0, another, us_dragfport,
1035 1, us_dragspecial);
1036 }
1037 }
1038 if (newhigh.status == 0)
1039 {
1040 /* nothing under cursor: select an area */
1041 if (complement) us_dragstate = 2; else us_dragstate = 1;
1042 maketruerectpoly(us_dragx, us_dragx, us_dragy, us_dragy, us_dragpoly);
1043 us_dragpoly->style = CLOSEDRECT;
1044 return;
1045 }
1046
1047 /* grid the cursor coordinates when over something */
1048 gridalign(&us_dragx, &us_dragy, 1, us_dragnodeproto);
1049 us_setcursorpos(NOWINDOWFRAME, us_dragx, us_dragy);
1050 us_dragox = us_dragx; us_dragoy = us_dragy;
1051
1052 /* clear port info if not requested or multiple highlights */
1053 if (us_dragfport == 0) newhigh.fromport = NOPORTPROTO;
1054
1055 /* do not show invisible pins (text on them is shown separately) */
1056 us_multidragshowinvpin = FALSE;
1057
1058 /* see if object under cursor is already highlighted */
1059 for(i=0; i<len; i++)
1060 {
1061 if (us_makehighlight(((CHAR **)highvar->addr)[i], &oldhigh)) continue;
1062 if (oldhigh.cell != newhigh.cell) continue;
1063 if ((oldhigh.status&HIGHTYPE) != (newhigh.status&HIGHTYPE)) continue;
1064 if (oldhigh.fromgeom != newhigh.fromgeom) continue;
1065 if ((oldhigh.status&HIGHTYPE) == HIGHTEXT)
1066 {
1067 if (oldhigh.fromvar != newhigh.fromvar) continue;
1068 if (oldhigh.fromport != NOPORTPROTO && newhigh.fromport != NOPORTPROTO &&
1069 oldhigh.fromport != newhigh.fromport) continue;
1070 }
1071 break;
1072 }
1073
1074 /* is this a normal command or SHIFTed? */
1075 if (!complement)
1076 {
1077 /* normal find/move */
1078 newhigh.cell = getcurcell();
1079 if (i >= len || us_dragpoint >= 0)
1080 {
1081 /* object is not highlighted: select only it and move */
1082 us_setfind(&newhigh, (us_dragpoint < 0 ? 0 : 1),
1083 (us_dragextra != 0 ? HIGHEXTRA : 0), 0, us_dragnobox);
1084 } else
1085 {
1086 /* object is already highlighted: rehighlight and move */
1087 us_delhighlight(&newhigh);
1088 us_addhighlight(&newhigh);
1089 }
1090 } else
1091 {
1092 /* SHIFT held: find/move */
1093 if (i >= len)
1094 {
1095 /* object not highlighted: add it and move */
1096 newhigh.cell = getcurcell();
1097 us_setfind(&newhigh, 0, (us_dragextra != 0 ? HIGHEXTRA : 0), 1, us_dragnobox);
1098 } else
1099 {
1100 /* object highlighted: unhighlight it and quit */
1101 us_delhighlight(&newhigh);
1102 return;
1103 }
1104 }
1105
1106 /* can only drag if in "Mac" mode */
1107 us_cantdrag = 1;
1108 if (us_dragstayonhigh == 0) return;
1109
1110 /* do no motion if stillness requested */
1111 if (us_dragstill != 0 || (us_dragnodeproto->userbits&NPLOCKED) != 0)
1112 {
1113 us_dragstate = -1;
1114 return;
1115 }
1116
1117 /* get the objects to be moved */
1118 highvar = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
1119 if (highvar == NOVARIABLE) return;
1120
1121 /* get the selected nodes, arcs, and text (mark nodes with nonzero "temp1") */
1122 us_dragobjectlist = us_gethighlighted(WANTNODEINST | WANTARCINST,
1123 &us_dragtextcount, &us_dragtexts);
1124
1125 /* stop if nothing selected */
1126 if (us_dragobjectlist[0] == NOGEOM && us_dragtextcount == 0) return;
1127 us_cantdrag = 0;
1128
1129 /* stop if from different cells */
1130 for(i=0; us_dragobjectlist[i] != NOGEOM; i++)
1131 if (us_dragnodeproto != geomparent(us_dragobjectlist[i])) return;
1132
1133 /* count the number of nodes */
1134 us_dragnodetotal = 0;
1135 for(ni = us_dragnodeproto->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1136 if (ni->temp1 != 0) us_dragnodetotal++;
1137
1138 /* build a list that includes all nodes touching selected arcs */
1139 if (us_dragnodetotal != 0)
1140 {
1141 us_dragnodelist = (NODEINST **)emalloc((us_dragnodetotal * (sizeof (NODEINST *))),
1142 el_tempcluster);
1143 if (us_dragnodelist == 0) return;
1144 for(i=0, ni = us_dragnodeproto->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1145 {
1146 if (ni->temp1 != 0)
1147 us_dragnodelist[i++] = ni;
1148 }
1149 }
1150
1151 /* save and turn off all highlighting */
1152 us_pushhighlight();
1153 us_clearhighlightcount();
1154
1155 /* setup for moving */
1156 us_multidragbegin();
1157 us_multidragshowoffset = TRUE;
1158 us_dragstate = 0;
1159 }
1160
us_findidown(INTBIG x,INTBIG y)1161 BOOLEAN us_findidown(INTBIG x, INTBIG y)
1162 {
1163 REGISTER UINTBIG now;
1164 BOOLEAN ret;
1165
1166 /* make the drag */
1167 ret = TRUE;
1168 switch (us_dragstate)
1169 {
1170 case 0:
1171 /* pan the screen if the edge was hit */
1172 us_panatscreenedge(&x, &y);
1173 now = eventtime();
1174 if (now < us_initialtime + us_motiondelayafterselection) ret = 0; else
1175 ret = us_multidragdown(x, y);
1176 break;
1177 case 1:
1178 case 2:
1179 ret = us_stretchdown(x, y);
1180 break;
1181 }
1182 return(ret);
1183 }
1184
us_findiup(void)1185 void us_findiup(void)
1186 {
1187 INTBIG xcur, ycur;
1188 CHAR **list;
1189 REGISTER INTBIG i, len, k, slx, shx, sly, shy, bits, angle, total;
1190 REGISTER NODEINST *ni;
1191 REGISTER ARCINST *ai;
1192 REGISTER BOOLEAN domove;
1193 REGISTER UINTBIG now;
1194 HIGHLIGHT newhigh, oldhigh;
1195 REGISTER VARIABLE *highvar;
1196 static POLYGON *poly = NOPOLYGON;
1197
1198 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
1199 if (us_dragstate == 0)
1200 {
1201 us_multidragup();
1202 now = ticktime();
1203 if (now >= us_initialtime + us_motiondelayafterselection &&
1204 us_cantdrag == 0 && el_pleasestop == 0)
1205 {
1206 if (getxy(&xcur, &ycur)) return;
1207 gridalign(&xcur, &ycur, 1, us_dragnodeproto);
1208 us_setcursorpos(NOWINDOWFRAME, xcur, ycur);
1209 bits = getbuckybits();
1210 if ((bits&CONTROLDOWN) != 0) angle = us_dragangle; else angle = 0;
1211 us_getslide(angle, us_dragox, us_dragoy, xcur, ycur, &us_dragx, &us_dragy);
1212 if (us_dragx != us_dragox || us_dragy != us_dragoy)
1213 {
1214 /* eliminate locked nodes */
1215 domove = TRUE;
1216 for(i=0; i<us_dragnodetotal; i++)
1217 {
1218 ni = us_dragnodelist[i];
1219 if (us_cantedit(ni->parent, ni, TRUE)) { domove = FALSE; break; }
1220 }
1221
1222 /* also check for locked nodes at the end of selected arcs */
1223 if (domove)
1224 {
1225 for(i=0; us_dragobjectlist[i] != NOGEOM; i++)
1226 {
1227 if (!us_dragobjectlist[i]->entryisnode)
1228 {
1229 ai = us_dragobjectlist[i]->entryaddr.ai;
1230 if (us_cantedit(us_dragnodeproto, ai->end[0].nodeinst, TRUE) ||
1231 us_cantedit(us_dragnodeproto, ai->end[1].nodeinst, TRUE))
1232 {
1233 domove = FALSE;
1234 break;
1235 }
1236 }
1237 }
1238 }
1239
1240 /* do the move */
1241 if (domove)
1242 {
1243 us_manymove(us_dragobjectlist, us_dragnodelist, us_dragnodetotal,
1244 us_dragx-us_dragox, us_dragy-us_dragoy);
1245 us_moveselectedtext(us_dragtextcount, us_dragtexts,
1246 us_dragobjectlist, us_dragx - us_dragox, us_dragy - us_dragoy);
1247 }
1248 }
1249 }
1250 if (us_dragnodetotal > 0) efree((CHAR *)us_dragnodelist);
1251 us_pophighlight(TRUE);
1252 } else if (us_dragstate == 1)
1253 {
1254 /* get area of drag */
1255 us_invertdragup();
1256 slx = mini(us_dragox, us_dragx); shx = maxi(us_dragox, us_dragx);
1257 sly = mini(us_dragoy, us_dragy); shy = maxi(us_dragoy, us_dragy);
1258 us_clearhighlightcount();
1259
1260 total = us_selectarea(us_dragnodeproto, slx, shx, sly, shy, us_dragspecial,
1261 us_dragfport, us_dragnobox, &list);
1262 if (total > 0)
1263 (void)setvalkey((INTBIG)us_tool, VTOOL, us_highlightedkey, (INTBIG)list,
1264 VSTRING|VISARRAY|(total<<VLENGTHSH)|VDONTSAVE);
1265 } else if (us_dragstate == 2)
1266 {
1267 /* special case when complementing highlight */
1268 us_invertdragup();
1269 slx = mini(us_dragox, us_dragx); shx = maxi(us_dragox, us_dragx);
1270 sly = mini(us_dragoy, us_dragy); shy = maxi(us_dragoy, us_dragy);
1271 highvar = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
1272 if (highvar != NOVARIABLE) len = getlength(highvar); else len = 0;
1273
1274 total = us_selectarea(us_dragnodeproto, slx, shx, sly, shy, us_dragspecial,
1275 us_dragfport, us_dragnobox, &list);
1276
1277 for(i=0; i<total; i++)
1278 {
1279 if (us_makehighlight(list[i], &newhigh)) continue;
1280
1281 /* see if this object is already highlighted */
1282 for(k=0; k<len; k++)
1283 {
1284 if (us_makehighlight(((CHAR **)highvar->addr)[k], &oldhigh)) continue;
1285 if (oldhigh.cell != newhigh.cell) continue;
1286 if ((oldhigh.status&HIGHTYPE) != (newhigh.status&HIGHTYPE)) continue;
1287 if ((oldhigh.status&HIGHTYPE) == HIGHFROM)
1288 {
1289 if (oldhigh.fromgeom != newhigh.fromgeom) continue;
1290 } else if ((oldhigh.status&HIGHTYPE) == HIGHTEXT)
1291 {
1292 if (oldhigh.fromvar != newhigh.fromvar) continue;
1293 if (oldhigh.fromvar == NOVARIABLE)
1294 {
1295 if (oldhigh.fromgeom != newhigh.fromgeom) continue;
1296 if (oldhigh.fromport != newhigh.fromport) continue;
1297 }
1298 }
1299 break;
1300 }
1301 if (k < len) us_delhighlight(&newhigh); else
1302 us_addhighlight(&newhigh);
1303
1304 /* recache what is highlighted */
1305 highvar = getvalkey((INTBIG)us_tool, VTOOL, VSTRING|VISARRAY, us_highlightedkey);
1306 if (highvar != NOVARIABLE) len = getlength(highvar); else len = 0;
1307 }
1308 }
1309 }
1310
1311 /*
1312 * Routine to determine whether geometry object "geom" is inside the area
1313 * (slx <= X <= shx, sly <= Y <= shy). Returns true if so.
1314 */
us_geominrect(GEOM * geom,INTBIG slx,INTBIG shx,INTBIG sly,INTBIG shy)1315 BOOLEAN us_geominrect(GEOM *geom, INTBIG slx, INTBIG shx, INTBIG sly, INTBIG shy)
1316 {
1317 REGISTER NODEINST *ni;
1318 REGISTER ARCINST *ai;
1319 INTBIG plx, ply, phx, phy;
1320 REGISTER INTBIG wid, lx, hx, ly, hy;
1321 XARRAY trans;
1322 static POLYGON *poly = NOPOLYGON;
1323
1324 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
1325 if (geom->entryisnode)
1326 {
1327 /* handle nodes */
1328 ni = geom->entryaddr.ni;
1329 makerot(ni, trans);
1330
1331 /* get the true bounds of the node */
1332 nodesizeoffset(ni, &plx, &ply, &phx, &phy);
1333 lx = ni->lowx+plx; hx = ni->highx-phx;
1334 ly = ni->lowy+ply; hy = ni->highy-phy;
1335 maketruerectpoly(lx, hx, ly, hy, poly);
1336 poly->style = FILLEDRECT;
1337
1338 /* transform to account for node orientation */
1339 xformpoly(poly, trans);
1340
1341 /* see if it is in the selected area */
1342 if ((us_useroptions&MUSTENCLOSEALL) != 0)
1343 {
1344 getbbox(poly, &plx, &phx, &ply, &phy);
1345 if (plx < slx || phx > shx || ply < sly || phy > shy)
1346 return(FALSE);
1347 } else
1348 {
1349 if (!polyinrect(poly, slx, shx, sly, shy)) return(FALSE);
1350 }
1351 return(TRUE);
1352 }
1353
1354 /* handle arcs */
1355 ai = geom->entryaddr.ai;
1356 wid = ai->width - arcwidthoffset(ai);
1357 if (wid == 0) wid = lambdaofarc(ai);
1358 if (curvedarcoutline(ai, poly, FILLED, wid))
1359 makearcpoly(ai->length, wid, ai, poly, FILLED);
1360 if ((us_useroptions&MUSTENCLOSEALL) != 0)
1361 {
1362 getbbox(poly, &plx, &phx, &ply, &phy);
1363 if (plx < slx || phx > shx || ply < sly || phy > shy)
1364 return(FALSE);
1365 } else
1366 {
1367 if (!polyinrect(poly, slx, shx, sly, shy)) return(FALSE);
1368 }
1369 return(TRUE);
1370 }
1371
1372 /************************* CREATE INSERT/BREAKPOINT *************************/
1373
1374 /* pre-initialization routine when inserting type "np" in arc "ai" */
us_createinsinit(ARCINST * ai,NODEPROTO * np)1375 void us_createinsinit(ARCINST *ai, NODEPROTO *np)
1376 {
1377 us_dragarcinst = ai;
1378 us_dragnodeproto = np;
1379 }
1380
1381 /* initialization routine when inserting a breakpoint */
us_createinsbegin(void)1382 void us_createinsbegin(void)
1383 {
1384 XARRAY trans;
1385 INTBIG cx, cy, lx, ly, hx, hy, xcur, ycur, pxs, pys;
1386 BOOLEAN centeredprimitives;
1387 REGISTER NODEINST *ni;
1388 NODEINST node;
1389
1390 /* initialize polygon */
1391 if (us_dragpoly == NOPOLYGON) us_dragpoly = allocpolygon(4, us_tool->cluster);
1392 us_dragpoly->desc = &us_highl;
1393
1394 (void)getxy(&xcur, &ycur);
1395
1396 us_dragshown = 0;
1397 ni = &node; initdummynode(ni);
1398 ni->proto = us_dragnodeproto;
1399 ni->rotation = 0;
1400 ni->transpose = 0;
1401 defaultnodesize(us_dragnodeproto, &pxs, &pys);
1402 ni->lowx = xcur; ni->highx = xcur + pxs;
1403 ni->lowy = ycur; ni->highy = ycur + pys;
1404 makerot(ni, trans);
1405 nodeprotosizeoffset(us_dragnodeproto, &lx, &ly, &hx, &hy, el_curwindowpart->curnodeproto);
1406 maketruerectpoly(ni->lowx+lx, ni->highx-hx, ni->lowy+ly, ni->highy-hy, us_dragpoly);
1407 us_dragpoly->style = CLOSEDRECT;
1408 xformpoly(us_dragpoly, trans);
1409 if ((us_useroptions&CENTEREDPRIMITIVES) != 0) centeredprimitives = TRUE; else
1410 centeredprimitives = FALSE;
1411 corneroffset(NONODEINST, us_dragnodeproto, 0, 0, &cx, &cy,
1412 centeredprimitives);
1413 us_dragoffx = cx;
1414 us_dragoffy = cy;
1415 us_dragx = xcur; us_dragy = ycur;
1416 us_dragwindow = el_curwindowpart;
1417 us_dragobject = NOGEOM;
1418 us_dragportproto = NOPORTPROTO;
1419 }
1420
1421 /* cursor advance routine when creating inside an arc */
us_createinsdown(INTBIG x,INTBIG y)1422 BOOLEAN us_createinsdown(INTBIG x, INTBIG y)
1423 {
1424 REGISTER INTBIG i;
1425 INTBIG dx, dy, pxs, pys;
1426
1427 /* grid align the cursor value */
1428 if (us_setxy(x, y) || us_dragwindow != el_curwindowpart)
1429 {
1430 (void)us_setxy(us_lastcurx, us_lastcury);
1431 return(FALSE);
1432 }
1433 (void)getxy(&us_lastcurx, &us_lastcury);
1434 gridalign(&us_lastcurx, &us_lastcury, 1, el_curlib->curnodeproto);
1435 us_setcursorpos(NOWINDOWFRAME, us_lastcurx, us_lastcury);
1436
1437 /* find closest point along arc */
1438 dx = us_lastcurx; dy = us_lastcury;
1439 (void)closestpointtosegment(us_dragarcinst->end[0].xpos, us_dragarcinst->end[0].ypos,
1440 us_dragarcinst->end[1].xpos, us_dragarcinst->end[1].ypos, &dx, &dy);
1441 defaultnodesize(us_dragnodeproto, &pxs, &pys);
1442 dx -= pxs/2;
1443 dy -= pys/2;
1444
1445 /* if the box is already being shown, erase it */
1446 if (us_dragshown != 0)
1447 {
1448 /* if it didn't actually move, go no further */
1449 if (us_dragx == dx && us_dragy == dy) return(FALSE);
1450
1451 /* undraw the box */
1452 us_highl.col = 0;
1453 us_showpoly(us_dragpoly, us_dragwindow);
1454 }
1455
1456 /* advance the box */
1457 for(i = 0; i < us_dragpoly->count; i++)
1458 {
1459 us_dragpoly->xv[i] += dx - us_dragx;
1460 us_dragpoly->yv[i] += dy - us_dragy;
1461 }
1462 us_dragx = dx;
1463 us_dragy = dy;
1464
1465 /* draw the new box */
1466 us_highl.col = HIGHLIT;
1467 us_showpoly(us_dragpoly, us_dragwindow);
1468 us_dragshown = 1;
1469 return(FALSE);
1470 }
1471
1472 /************************* CREATE NODE *************************/
1473
1474 /* pre-initialization routine when creating an object */
us_createinit(INTBIG cornerx,INTBIG cornery,NODEPROTO * np,INTBIG angle,BOOLEAN join,GEOM * fromgeom,PORTPROTO * fromport)1475 void us_createinit(INTBIG cornerx, INTBIG cornery, NODEPROTO *np, INTBIG angle,
1476 BOOLEAN join, GEOM *fromgeom, PORTPROTO *fromport)
1477 {
1478 us_dragox = cornerx;
1479 us_dragoy = cornery;
1480 us_dragnodeproto = np;
1481 us_dragangle = angle;
1482 us_dragjoinfactor = join;
1483 us_dragfromgeom = fromgeom;
1484 us_dragfromport = fromport;
1485 }
1486
1487 /* initialization routine when creating an object */
us_createbegin(void)1488 void us_createbegin(void)
1489 {
1490 XARRAY trans;
1491 INTBIG cx, cy, lx, ly, hx, hy, xcur, ycur, pxs, pys;
1492 REGISTER NODEINST *ni;
1493 NODEINST node;
1494 BOOLEAN centeredprimitives;
1495 REGISTER WINDOWFRAME *curframe;
1496
1497 /* initialize polygon */
1498 (void)needstaticpolygon(&us_dragpoly, 4, us_tool->cluster);
1499 us_dragpoly->desc = &us_highl;
1500
1501 (void)getxy(&xcur, &ycur);
1502 curframe = getwindowframe(TRUE);
1503 if ((us_tool->toolstate&MENUON) != 0)
1504 {
1505 if (curframe == us_menuframe ||
1506 (us_menuframe == NOWINDOWFRAME && ycur >= us_menuly && ycur <= us_menuhy &&
1507 xcur >= us_menulx && xcur <= us_menuhx))
1508 {
1509 el_pleasestop = 1;
1510 }
1511 }
1512
1513 us_dragshown = 0;
1514 ni = &node; initdummynode(ni);
1515 ni->proto = us_dragnodeproto;
1516 ni->rotation = (INTSML)(us_dragangle%3600);
1517 ni->transpose = (INTSML)(us_dragangle/3600);
1518 defaultnodesize(us_dragnodeproto, &pxs, &pys);
1519 if ((us_useroptions&CENTEREDPRIMITIVES) != 0) centeredprimitives = TRUE; else
1520 centeredprimitives = FALSE;
1521 corneroffset(NONODEINST, us_dragnodeproto, us_dragangle%3600,
1522 us_dragangle/3600, &cx, &cy, centeredprimitives);
1523
1524 /* adjust size if technologies differ */
1525 us_adjustfornodeincell(us_dragnodeproto, el_curwindowpart->curnodeproto, &cx, &cy);
1526 us_adjustfornodeincell(us_dragnodeproto, el_curwindowpart->curnodeproto, &pxs, &pys);
1527 ni->lowx = xcur; ni->highx = xcur + pxs;
1528 ni->lowy = ycur; ni->highy = ycur + pys;
1529 makerot(ni, trans);
1530 nodeprotosizeoffset(us_dragnodeproto, &lx, &ly, &hx, &hy, el_curwindowpart->curnodeproto);
1531 maketruerectpoly(ni->lowx+lx, ni->highx-hx, ni->lowy+ly, ni->highy-hy, us_dragpoly);
1532 us_dragpoly->style = CLOSEDRECT;
1533 xformpoly(us_dragpoly, trans);
1534 us_dragx = xcur + cx; us_dragy = ycur + cy;
1535 us_dragwindow = el_curwindowpart;
1536 us_dragwirepathcount = 0;
1537 }
1538
1539 /* initialization routine when creating along an angle */
us_createabegin(void)1540 void us_createabegin(void)
1541 {
1542 XARRAY trans;
1543 INTBIG cx, cy, lx, ly, hx, hy, xcur, ycur, pxs, pys;
1544 REGISTER NODEINST *ni;
1545 NODEINST node;
1546 REGISTER BOOLEAN centeredprimitives;
1547
1548 /* initialize polygon */
1549 if (us_dragpoly == NOPOLYGON) us_dragpoly = allocpolygon(4, us_tool->cluster);
1550 us_dragpoly->desc = &us_highl;
1551
1552 (void)getxy(&xcur, &ycur);
1553
1554 /* determine starting coordinate */
1555 if ((us_dragfromport->userbits&PORTISOLATED) != 0)
1556 {
1557 /* use prefered location on isolated ports */
1558 us_dragpoly->xv[0] = xcur; us_dragpoly->yv[0] = ycur; us_dragpoly->count = 1;
1559 shapeportpoly(us_dragfromgeom->entryaddr.ni, us_dragfromport, us_dragpoly, TRUE);
1560 us_dragstartx = xcur; us_dragstarty = ycur;
1561 closestpoint(us_dragpoly, &us_dragstartx, &us_dragstarty);
1562 } else
1563 {
1564 us_portposition(us_dragfromgeom->entryaddr.ni, us_dragfromport,
1565 &us_dragstartx, &us_dragstarty);
1566 }
1567
1568 us_dragshown = 0;
1569 ni = &node; initdummynode(ni);
1570 ni->proto = us_dragnodeproto;
1571 ni->rotation = 0;
1572 ni->transpose = 0;
1573 defaultnodesize(us_dragnodeproto, &pxs, &pys);
1574 if ((us_useroptions&CENTEREDPRIMITIVES) != 0) centeredprimitives = TRUE; else
1575 centeredprimitives = FALSE;
1576 corneroffset(NONODEINST, us_dragnodeproto, 0, 0, &cx, &cy, centeredprimitives);
1577
1578 /* adjust size if technologies differ */
1579 us_adjustfornodeincell(us_dragnodeproto, us_dragwindow->curnodeproto, &cx, &cy);
1580 us_adjustfornodeincell(us_dragnodeproto, us_dragwindow->curnodeproto, &pxs, &pys);
1581
1582 ni->lowx = xcur; ni->highx = xcur + pxs;
1583 ni->lowy = ycur; ni->highy = ycur + pys;
1584 makerot(ni, trans);
1585 nodeprotosizeoffset(us_dragnodeproto, &lx, &ly, &hx, &hy, el_curwindowpart->curnodeproto);
1586 maketruerectpoly(ni->lowx+lx, ni->highx-hx, ni->lowy+ly, ni->highy-hy, us_dragpoly);
1587 us_dragpoly->style = CLOSEDRECT;
1588 xformpoly(us_dragpoly, trans);
1589
1590 us_dragoffx = cx;
1591 us_dragoffy = cy;
1592 us_dragx = xcur; us_dragy = ycur;
1593 us_dragwindow = el_curwindowpart;
1594 us_dragobject = NOGEOM;
1595 us_dragportproto = NOPORTPROTO;
1596 }
1597
1598 /* cursor advance routine when creating along an angle */
us_createadown(INTBIG x,INTBIG y)1599 BOOLEAN us_createadown(INTBIG x, INTBIG y)
1600 {
1601 REGISTER INTBIG dx, dy, dist, bestdist, count, samepath, alignment;
1602 REGISTER INTBIG i;
1603 INTBIG pxs, pys, unalx, unaly, fakecoords[8];
1604 REGISTER PORTPROTO *pp, *foundpp;
1605 REGISTER NODEINST *ni, *fakefromnode, *faketonode;
1606 ARCINST *ai1, *ai2, *ai3;
1607 NODEINST *con1, *con2;
1608 GEOM *fakefromgeom, *faketogeom;
1609 PORTPROTO *fakefromport, *faketoport;
1610 REGISTER GEOM *foundgeom;
1611 static POLYGON *poly = NOPOLYGON;
1612
1613 /* get the polygon */
1614 (void)needstaticpolygon(&poly, 4, us_tool->cluster);
1615
1616 /* pan the screen if the edge was hit */
1617 us_panatscreenedge(&x, &y);
1618
1619 /* grid align the cursor value */
1620 if (us_setxy(x, y) || us_dragwindow != el_curwindowpart)
1621 {
1622 (void)us_setxy(us_lastcurx, us_lastcury);
1623 return(FALSE);
1624 }
1625 (void)getxy(&us_lastcurx, &us_lastcury);
1626 unalx = us_lastcurx; unaly = us_lastcury;
1627 gridalign(&us_lastcurx, &us_lastcury, 1, us_dragwindow->curnodeproto);
1628 us_setcursorpos(NOWINDOWFRAME, us_lastcurx, us_lastcury);
1629
1630 us_getslide(us_dragangle, us_dragox, us_dragoy, us_lastcurx, us_lastcury, &pxs, &pys);
1631 dx = pxs - us_dragoffx;
1632 dy = pys - us_dragoffy;
1633
1634 /* find the object under the cursor */
1635 foundpp = NOPORTPROTO;
1636 foundgeom = NOGEOM;
1637 if (us_dragjoinfactor)
1638 {
1639 defaultnodesize(us_dragnodeproto, &pxs, &pys);
1640 us_adjustfornodeincell(us_dragnodeproto, us_dragwindow->curnodeproto, &pxs, &pys);
1641 alignment = muldiv(us_alignment_ratio, el_curlib->lambda[el_curtech->techindex], WHOLE);
1642 foundgeom = us_getclosest(us_lastcurx-us_dragoffx+pxs/2, us_lastcury-us_dragoffy+pys/2,
1643 alignment/2, us_dragwindow->curnodeproto);
1644
1645 /* determine closest port if a node was found */
1646 if (foundgeom != NOGEOM && foundgeom->entryisnode)
1647 {
1648 /* find the closest port if this is a nodeinst and no port hit directly */
1649 ni = foundgeom->entryaddr.ni;
1650 for(pp = ni->proto->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
1651 {
1652 shapeportpoly(ni, pp, poly, FALSE);
1653
1654 /* get distance of desired point to polygon */
1655 dist = polydistance(poly, unalx, unaly);
1656 if (dist < 0)
1657 {
1658 foundpp = pp;
1659 break;
1660 }
1661 if (foundpp == NOPORTPROTO) bestdist = dist;
1662 if (dist > bestdist) continue;
1663 bestdist = dist; foundpp = pp;
1664 }
1665 }
1666 }
1667
1668 /* determine what is being connected */
1669 count = 0;
1670 fakefromgeom = us_dragfromgeom; fakefromport = us_dragfromport;
1671 faketogeom = foundgeom; faketoport = foundpp;
1672 if (fakefromgeom == NOGEOM) fakefromnode = NONODEINST; else
1673 fakefromnode = us_getnodeonarcinst(&fakefromgeom, &fakefromport, faketogeom,
1674 faketoport, pxs, pys, 1);
1675 if (faketogeom == NOGEOM) faketonode = NONODEINST; else
1676 faketonode = us_getnodeonarcinst(&faketogeom, &faketoport, fakefromgeom,
1677 fakefromport, pxs, pys, 1);
1678 if (fakefromnode != NONODEINST && faketonode != NONODEINST)
1679 {
1680 if (!us_figuredrawpath(us_dragfromgeom, us_dragfromport,
1681 foundgeom, foundpp, &unalx, &unaly))
1682 {
1683 ai1 = us_makeconnection(fakefromnode, fakefromport,
1684 gen_universalarc, faketonode, faketoport, gen_universalarc,
1685 gen_univpinprim, unalx, unaly, &ai2, &ai3, &con1, &con2,
1686 us_dragangle, FALSE, fakecoords, TRUE);
1687 if (ai1 != NOARCINST) count = 4;
1688 if (ai2 != NOARCINST) count = 6;
1689 if (ai3 != NOARCINST) count = 8;
1690 }
1691 }
1692 if (count == 0)
1693 {
1694 /* should draw a line from the node to the new pin */
1695 if (us_dragfromgeom != NOGEOM && us_dragfromgeom->entryisnode)
1696 {
1697 fakecoords[0] = us_dragstartx;
1698 fakecoords[1] = us_dragstarty;
1699 fakecoords[2] = dx + us_dragoffx;
1700 fakecoords[3] = dy + us_dragoffy;
1701 count = 4;
1702 }
1703 }
1704
1705 /* see if the connection path is the same as before */
1706 samepath = 0;
1707 if (count == us_dragwirepathcount)
1708 {
1709 for(i=0; i<count; i++) if (fakecoords[i] != us_dragwirepath[i]) break;
1710 if (i >= count) samepath = 1;
1711 }
1712
1713 /* remove previous highlighting */
1714 if (us_dragobject != NOGEOM)
1715 {
1716 if (us_dragshown != 0)
1717 {
1718 /* undraw the box */
1719 us_highl.col = 0;
1720 us_showpoly(us_dragpoly, us_dragwindow);
1721 us_dragshown = 0;
1722 }
1723 if (us_dragobject == foundgeom && us_dragportproto == foundpp && samepath != 0) return(FALSE);
1724 us_highlighteverywhere(us_dragobject, us_dragportproto, 0, FALSE, ALLOFF, FALSE);
1725 } else
1726 {
1727 if (us_dragshown != 0)
1728 {
1729 /* if it didn't actually move, go no further */
1730 if (us_dragx == dx && us_dragy == dy && samepath != 0 &&
1731 us_dragobject == foundgeom) return(FALSE);
1732
1733 /* undraw the box */
1734 us_highl.col = 0;
1735 us_showpoly(us_dragpoly, us_dragwindow);
1736 us_dragshown = 0;
1737 }
1738 }
1739
1740 /* undraw the previous wire path */
1741 if (us_dragwirepathcount > 0)
1742 {
1743 poly->style = OPENED;
1744 poly->count = us_dragwirepathcount/2;
1745 for(i=0; i<poly->count; i++)
1746 {
1747 poly->xv[i] = us_dragwirepath[i*2];
1748 poly->yv[i] = us_dragwirepath[i*2+1];
1749 }
1750 poly->desc = &us_highl;
1751 us_highl.col = 0;
1752 us_showpoly(poly, us_dragwindow);
1753 }
1754
1755 /* advance the box */
1756 for(i = 0; i < us_dragpoly->count; i++)
1757 {
1758 us_dragpoly->xv[i] += dx - us_dragx;
1759 us_dragpoly->yv[i] += dy - us_dragy;
1760 }
1761 us_dragx = dx;
1762 us_dragy = dy;
1763
1764 /* include any wiring path */
1765 for(i=0; i<count; i++)
1766 us_dragwirepath[i] = fakecoords[i];
1767 us_dragwirepathcount = count;
1768
1769 /* set highlighted destination object */
1770 us_dragobject = foundgeom;
1771 us_dragportproto = foundpp;
1772
1773 /* draw the previous wire path */
1774 if (us_dragwirepathcount > 0)
1775 {
1776 poly->style = OPENED;
1777 poly->count = us_dragwirepathcount/2;
1778 for(i=0; i<poly->count; i++)
1779 {
1780 poly->xv[i] = us_dragwirepath[i*2];
1781 poly->yv[i] = us_dragwirepath[i*2+1];
1782 }
1783 poly->desc = &us_highl;
1784 us_highl.col = HIGHLIT;
1785 us_showpoly(poly, us_dragwindow);
1786 }
1787
1788 /* draw the new highlight */
1789 if (us_dragobject != NOGEOM)
1790 {
1791 us_highlighteverywhere(us_dragobject, us_dragportproto, 0, FALSE, HIGHLIT, FALSE);
1792 } else
1793 {
1794 us_highl.col = HIGHLIT;
1795 us_showpoly(us_dragpoly, us_dragwindow);
1796 us_dragshown = 1;
1797 }
1798 return(FALSE);
1799 }
1800
us_createajoinedobject(GEOM ** thegeom,PORTPROTO ** theport)1801 void us_createajoinedobject(GEOM **thegeom, PORTPROTO **theport)
1802 {
1803 *theport = us_dragportproto;
1804 *thegeom = us_dragobject;
1805 }
1806
1807 /* termination routine when creating along an angle */
us_createaup(void)1808 void us_createaup(void)
1809 {
1810 REGISTER INTBIG i;
1811
1812 if (us_dragshown != 0)
1813 {
1814 /* undraw the box */
1815 us_highl.col = 0;
1816 us_showpoly(us_dragpoly, us_dragwindow);
1817 }
1818 if (us_dragobject != NOGEOM)
1819 us_highlighteverywhere(us_dragobject, us_dragportproto, 0, FALSE, ALLOFF, FALSE);
1820
1821 /* undraw the previous wire path */
1822 if (us_dragwirepathcount > 0)
1823 {
1824 us_dragpoly->style = OPENED;
1825 us_dragpoly->count = us_dragwirepathcount/2;
1826 for(i=0; i<us_dragpoly->count; i++)
1827 {
1828 us_dragpoly->xv[i] = us_dragwirepath[i*2];
1829 us_dragpoly->yv[i] = us_dragwirepath[i*2+1];
1830 }
1831 us_highl.col = 0;
1832 us_showpoly(us_dragpoly, us_dragwindow);
1833 }
1834 }
1835
1836 /************************* DUPLICATE and multiple MOVE *************************/
1837
1838 /* preinitialization routine when duplicating objects */
us_multidraginit(INTBIG xc,INTBIG yc,GEOM ** geomlist,NODEINST ** nodelist,INTBIG total,INTBIG angle,BOOLEAN showoffset)1839 void us_multidraginit(INTBIG xc, INTBIG yc, GEOM **geomlist, NODEINST **nodelist,
1840 INTBIG total, INTBIG angle, BOOLEAN showoffset)
1841 {
1842 us_multidragshowoffset = showoffset;
1843 us_dragox = xc;
1844 us_dragoy = yc;
1845 us_dragobjectlist = geomlist;
1846 us_dragnodelist = nodelist;
1847 us_dragnodetotal = total;
1848 us_dragangle = angle;
1849 us_dragextra = 0;
1850 us_cantdrag = 0;
1851
1852 /* show invisible pins */
1853 us_multidragshowinvpin = TRUE;
1854 }
1855
1856 static INTBIG us_multidragoffx, us_multidragoffy;
1857
1858 /* initialization routine when duplicating objects */
us_multidragbegin(void)1859 void us_multidragbegin(void)
1860 {
1861 REGISTER INTBIG i;
1862 REGISTER PORTARCINST *pi;
1863 REGISTER ARCINST *ai;
1864
1865 /* initialize polygon */
1866 if (us_dragpoly == NOPOLYGON) us_dragpoly = allocpolygon(4, us_tool->cluster);
1867 us_dragpoly->desc = &us_highl;
1868
1869 (void)getxy(&us_dragx, &us_dragy);
1870 gridalign(&us_dragx, &us_dragy, 1, el_curlib->curnodeproto);
1871 us_setcursorpos(NOWINDOWFRAME, us_dragx, us_dragy);
1872 us_dragwindow = el_curwindowpart;
1873
1874 /* preprocess all arcs that stretch to moved nodes if in verbose mode */
1875 if (us_dragextra != 0)
1876 {
1877 /* reset clock (temp2) and clear display nature bits (temp1) on arcs */
1878 for(i=0; i<us_dragnodetotal; i++)
1879 for(pi = us_dragnodelist[i]->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
1880 {
1881 ai = pi->conarcinst;
1882 ai->temp1 = ai->temp2 = 0;
1883 }
1884
1885 /* mark number of ends that move on each arc */
1886 for(i=0; i<us_dragnodetotal; i++)
1887 for(pi = us_dragnodelist[i]->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
1888 pi->conarcinst->temp1++;
1889
1890 /* do not move arcs that are already in move list */
1891 for(i=0; us_dragobjectlist[i] != NOGEOM; i++)
1892 {
1893 if (us_dragobjectlist[i]->entryisnode) continue;
1894 ai = us_dragobjectlist[i]->entryaddr.ai;
1895 ai->temp1 = 0;
1896 }
1897 }
1898
1899 us_multidragmostzeros = -1;
1900 us_multidragoffx = us_dragx-us_dragox;
1901 us_multidragoffy = us_dragy-us_dragoy;
1902 us_multidragdraw(HIGHLIT, us_multidragoffx, us_multidragoffy);
1903 us_dragshown = 1;
1904 }
1905
1906 /* cursor advance routine when duplicating objects */
us_multidragdown(INTBIG x,INTBIG y)1907 BOOLEAN us_multidragdown(INTBIG x, INTBIG y)
1908 {
1909 INTBIG nx, ny, bits, angle;
1910
1911 /* pan the screen if the edge was hit */
1912 us_panatscreenedge(&x, &y);
1913
1914 /* grid align the cursor value */
1915 if (us_setxy(x, y) || us_dragwindow != el_curwindowpart)
1916 {
1917 (void)us_setxy(us_lastcurx, us_lastcury);
1918 return(FALSE);
1919 }
1920 (void)getxy(&us_lastcurx, &us_lastcury);
1921 gridalign(&us_lastcurx, &us_lastcury, 1, el_curlib->curnodeproto);
1922 us_setcursorpos(NOWINDOWFRAME, us_lastcurx, us_lastcury);
1923 bits = getbuckybits();
1924 if ((bits&CONTROLDOWN) != 0) angle = us_dragangle; else angle = 0;
1925 us_getslide(angle, us_dragox, us_dragoy, us_lastcurx, us_lastcury, &nx, &ny);
1926 us_lastcurx = nx; us_lastcury = ny;
1927
1928 /* warn if moving and can't */
1929 if (us_cantdrag != 0)
1930 {
1931 if (us_dragx != us_lastcurx || us_dragy != us_lastcury)
1932 {
1933 if (us_cantdrag == 1)
1934 us_abortcommand(_("Sorry, changes are currently disallowed"));
1935 us_cantdrag++;
1936 return(FALSE);
1937 }
1938 }
1939
1940 /* if the highlighting is already being shown, erase it */
1941 if (us_dragshown != 0)
1942 {
1943 /* if it didn't actually move, go no further */
1944 if (us_dragx == us_lastcurx && us_dragy == us_lastcury) return(FALSE);
1945
1946 /* undraw highlighting */
1947 us_multidragdraw(0, us_multidragoffx, us_multidragoffy);
1948 }
1949
1950 us_dragx = us_lastcurx;
1951 us_dragy = us_lastcury;
1952 us_multidragoffx = us_dragx-us_dragox;
1953 us_multidragoffy = us_dragy-us_dragoy;
1954 us_multidragdraw(HIGHLIT, us_multidragoffx, us_multidragoffy);
1955 us_dragshown = 1;
1956 return(FALSE);
1957 }
1958
us_multidragup(void)1959 void us_multidragup(void)
1960 {
1961 if (us_dragshown != 0)
1962 us_multidragdraw(0, us_multidragoffx, us_multidragoffy);
1963 }
1964
us_multidragdraw(INTBIG col,INTBIG dx,INTBIG dy)1965 void us_multidragdraw(INTBIG col, INTBIG dx, INTBIG dy)
1966 {
1967 REGISTER INTBIG i, thisend, portcount, endfixed, wid, xzeros, yzeros, savestate;
1968 INTBIG lx, ly, hx, hy, xc, yc, xw, yw, j;
1969 CHAR coords[100], xcoord[50], ycoord[50], *pt;
1970 XARRAY trans;
1971 REGISTER BOOLEAN moveotherx, moveothery;
1972 REGISTER NODEINST *ni;
1973 REGISTER ARCINST *ai;
1974 REGISTER PORTARCINST *pi;
1975 REGISTER PORTPROTO *pp;
1976 REGISTER TECHNOLOGY *tech;
1977
1978 us_highl.col = col;
1979 if (us_dragextra != 0) us_dragextra++;
1980 for(i=0; us_dragobjectlist[i] != NOGEOM; i++)
1981 {
1982 if (!us_dragobjectlist[i]->entryisnode) continue;
1983 ni = us_dragobjectlist[i]->entryaddr.ni;
1984
1985 /* if node is an invisible pin with text, ignore the pin */
1986 if (ni->proto == gen_invispinprim)
1987 {
1988 for(j=0; j<ni->numvar; j++)
1989 if ((ni->firstvar[j].type&VDISPLAY) != 0) break;
1990 if (j < ni->numvar)
1991 {
1992 if (us_multidragshowinvpin)
1993 {
1994 makerot(ni, trans);
1995 xform((ni->lowx+ni->highx)/2, (ni->lowy+ni->highy)/2,
1996 &us_dragpoly->xv[0], &us_dragpoly->yv[0], trans);
1997 us_dragpoly->xv[0] += dx;
1998 us_dragpoly->yv[0] += dy;
1999 us_dragpoly->count = 1;
2000 us_dragpoly->style = CROSS;
2001 us_showpoly(us_dragpoly, us_dragwindow);
2002 }
2003 continue;
2004 }
2005 }
2006
2007 makerot(ni, trans);
2008 nodesizeoffset(ni, &lx, &ly, &hx, &hy);
2009 maketruerectpoly(ni->lowx+lx, ni->highx-hx, ni->lowy+ly, ni->highy-hy, us_dragpoly);
2010 us_dragpoly->style = CLOSEDRECT;
2011 xformpoly(us_dragpoly, trans);
2012 for(j=0; j<us_dragpoly->count; j++)
2013 {
2014 us_dragpoly->xv[j] += dx;
2015 us_dragpoly->yv[j] += dy;
2016 }
2017 us_showpoly(us_dragpoly, us_dragwindow);
2018
2019 /* draw more if in verbose mode */
2020 if (us_dragextra != 0)
2021 {
2022 /* if only 1 node selected, show its ports */
2023 if (us_dragnodetotal == 1)
2024 {
2025 portcount = 0;
2026 for(pp = ni->proto->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
2027 {
2028 /* compute the port bounds */
2029 shapeportpoly(ni, pp, us_dragpoly, FALSE);
2030
2031 /* see if the polygon is a single point */
2032 for(j=1; j<us_dragpoly->count; j++)
2033 if (us_dragpoly->xv[j] != us_dragpoly->xv[j-1] ||
2034 us_dragpoly->yv[j] != us_dragpoly->yv[j-1]) break;
2035 if (j < us_dragpoly->count)
2036 {
2037 /* not a single point, draw its outline */
2038 switch (us_dragpoly->style)
2039 {
2040 case FILLEDRECT: us_dragpoly->style = CLOSEDRECT; break;
2041 case FILLED: us_dragpoly->style = CLOSED; break;
2042 case DISC: us_dragpoly->style = CIRCLE; break;
2043 case OPENEDT1:
2044 case OPENEDT2:
2045 case OPENEDT3:
2046 case OPENEDO1: us_dragpoly->style = OPENED; break;
2047 }
2048 } else
2049 {
2050 /* single point port: make it a cross */
2051 us_dragpoly->count = 1;
2052 us_dragpoly->style = CROSS;
2053 }
2054 for(j=0; j<us_dragpoly->count; j++)
2055 {
2056 us_dragpoly->xv[j] += dx;
2057 us_dragpoly->yv[j] += dy;
2058 }
2059
2060 /* draw the port */
2061 us_showpoly(us_dragpoly, us_dragwindow);
2062
2063 /* stop if interrupted */
2064 portcount++;
2065 if ((portcount%20) == 0)
2066 {
2067 if (stopping(STOPREASONDISPLAY)) break;
2068 }
2069 }
2070 }
2071
2072 /* rubber-band arcs to this node */
2073 for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
2074 {
2075 ai = pi->conarcinst;
2076
2077 /* ignore if not drawing this arc or already drawn */
2078 if (ai->temp1 == 0 || ai->temp2 == us_dragextra) continue;
2079 ai->temp2 = us_dragextra;
2080
2081 /* get original endpoint of arc */
2082 us_dragpoly->xv[0] = ai->end[0].xpos;
2083 us_dragpoly->yv[0] = ai->end[0].ypos;
2084 us_dragpoly->xv[1] = ai->end[1].xpos;
2085 us_dragpoly->yv[1] = ai->end[1].ypos;
2086 us_dragpoly->count = 2;
2087 us_dragpoly->style = OPENED;
2088
2089 /* offset this end by amount node moves */
2090 if (ai->end[0].portarcinst == pi) thisend = 0; else thisend = 1;
2091 us_dragpoly->xv[thisend] += dx;
2092 us_dragpoly->yv[thisend] += dy;
2093
2094 /* offset other end if both connect to moved nodes or arc rigid */
2095 endfixed = 0;
2096 if (ai->temp1 >= 2 || (ai->userbits&FIXED) != 0) endfixed = 1;
2097
2098 moveotherx = moveothery = FALSE;
2099 if (endfixed != 0)
2100 {
2101 moveotherx = moveothery = TRUE;
2102 } else if ((ai->userbits&FIXANG) != 0)
2103 {
2104 if (ai->end[0].xpos != ai->end[1].xpos && ai->end[0].ypos != ai->end[1].ypos)
2105 {
2106 moveotherx = moveothery = TRUE;
2107 } else
2108 {
2109 if (ai->end[0].xpos == ai->end[1].xpos) moveotherx = TRUE;
2110 if (ai->end[0].ypos == ai->end[1].ypos) moveothery = TRUE;
2111 }
2112 }
2113 if (moveotherx) us_dragpoly->xv[1-thisend] += dx;
2114 if (moveothery) us_dragpoly->yv[1-thisend] += dy;
2115
2116 /* draw line */
2117 us_showpoly(us_dragpoly, us_dragwindow);
2118 }
2119 }
2120 }
2121
2122 for(i=0; us_dragobjectlist[i] != NOGEOM; i++)
2123 {
2124 if (us_dragobjectlist[i]->entryisnode) continue;
2125 ai = us_dragobjectlist[i]->entryaddr.ai;
2126 wid = ai->width - arcwidthoffset(ai);
2127 makearcpoly(ai->length, wid, ai, us_dragpoly, CLOSED);
2128 for(j=0; j<us_dragpoly->count; j++)
2129 {
2130 us_dragpoly->xv[j] += dx;
2131 us_dragpoly->yv[j] += dy;
2132 }
2133 us_showpoly(us_dragpoly, us_dragwindow);
2134 }
2135
2136 /* update selected text, too */
2137 for(i=0; i<us_dragtextcount; i++)
2138 {
2139 (void)us_makehighlight(us_dragtexts[i], &us_draghigh);
2140 if ((us_draghigh.status&HIGHTYPE) != HIGHTEXT) continue;
2141
2142 /* get object and extent */
2143 us_gethighaddrtype(&us_draghigh, &us_dragaddr, &us_dragtype);
2144 tech = us_getobjectinfo(us_dragaddr, us_dragtype, &lx, &hx, &ly, &hy);
2145
2146 /* determine number of lines of text and text size */
2147 us_gethightextsize(&us_draghigh, &xw, &yw, el_curwindowpart);
2148 us_gethightextcenter(&us_draghigh, &xc, &yc, &j);
2149 us_dragpoly->style = j;
2150
2151 #if 0 /* clip range of text descriptor */
2152 lambda = el_curlib->lambda[tech->techindex];
2153 xcur = (us_lastcurx - us_dragx) * 4 / lambda;
2154 us_lastcurx = us_lastcurx - us_dragx + us_dragoffx;
2155 if (xcur > 1023)
2156 us_lastcurx = 1023 * lambda / 4 + us_dragoffx; else
2157 if (xcur < -1023)
2158 us_lastcurx = -1023 * lambda / 4 + us_dragoffx;
2159 ycur = (us_lastcury - us_dragy) * 4 / lambda;
2160 us_lastcury = us_lastcury - us_dragy + us_dragoffy;
2161 if (ycur > 1023)
2162 us_lastcury = 1023 * lambda / 4 + us_dragoffy; else
2163 if (ycur < -1023)
2164 us_lastcury = -1023 * lambda / 4 + us_dragoffy;
2165 #endif
2166
2167 /* draw the descriptor */
2168 us_buildtexthighpoly(lx, hx, ly, hy, xc+dx, yc+dy,
2169 xw, yw, us_dragpoly->style, us_dragpoly);
2170
2171 /* draw the new box */
2172 us_showpoly(us_dragpoly, us_dragwindow);
2173 }
2174
2175 /* show the distance moved */
2176 if (us_multidragshowoffset)
2177 {
2178 estrcpy(xcoord, latoa(dx, 0));
2179 for(pt = xcoord; *pt != 0; pt++) if (*pt == '.') break;
2180 if (*pt == 0) xzeros = -1; else xzeros = estrlen(pt) - 1;
2181 estrcpy(ycoord, latoa(dy, 0));
2182 for(pt = ycoord; *pt != 0; pt++) if (*pt == '.') break;
2183 if (*pt == 0) yzeros = -1; else yzeros = estrlen(pt) - 1;
2184 if (xzeros > us_multidragmostzeros) us_multidragmostzeros = xzeros;
2185 if (yzeros > us_multidragmostzeros) us_multidragmostzeros = yzeros;
2186 if (xzeros < us_multidragmostzeros)
2187 {
2188 if (xzeros < 0) { estrcat(xcoord, x_(".")); xzeros++; }
2189 for(i=xzeros; i<us_multidragmostzeros; i++) estrcat(xcoord, x_("0"));
2190 }
2191 if (yzeros < us_multidragmostzeros)
2192 {
2193 if (yzeros < 0) { estrcat(ycoord, x_(".")); yzeros++; }
2194 for(i=yzeros; i<us_multidragmostzeros; i++) estrcat(ycoord, x_("0"));
2195 }
2196
2197 esnprintf(coords, 100, x_("(%s,%s)"), xcoord, ycoord);
2198 TDCLEAR(us_dragpoly->textdescript);
2199 TDSETSIZE(us_dragpoly->textdescript, TXTSETPOINTS(20));
2200 us_dragpoly->style = TEXTCENT;
2201 us_dragpoly->count = 1;
2202 us_dragpoly->xv[0] = (us_dragwindow->screenlx + us_dragwindow->screenhx) / 2;
2203 us_dragpoly->yv[0] = (us_dragwindow->screenly + us_dragwindow->screenhy) / 2;
2204 us_dragpoly->string = coords;
2205 savestate = us_dragwindow->state;
2206 us_dragwindow->state &= ~INPLACEEDIT;
2207 us_showpoly(us_dragpoly, us_dragwindow);
2208 us_dragwindow->state = savestate;
2209 }
2210 }
2211
2212 /************************* DISTANCE TRACKING *************************/
2213
us_distanceinit(void)2214 void us_distanceinit(void)
2215 {
2216 us_measureshown = 0;
2217 us_dragwindow = el_curwindowpart;
2218 }
2219
us_distancedown(INTBIG x,INTBIG y)2220 BOOLEAN us_distancedown(INTBIG x, INTBIG y)
2221 {
2222 REGISTER INTBIG dist, lastshown;
2223
2224 /* initialize polygon */
2225 if (us_dragpoly == NOPOLYGON) us_dragpoly = allocpolygon(4, us_tool->cluster);
2226 us_dragpoly->desc = &us_highl;
2227
2228 /* pan the screen if the edge was hit */
2229 lastshown = us_measureshown;
2230 us_panatscreenedge(&x, &y);
2231 if (lastshown != us_measureshown)
2232 {
2233 us_highl.col = HIGHLIT;
2234 us_drawdistance();
2235 us_measureshown = 1;
2236 }
2237
2238 /* grid align the cursor value */
2239 if (us_setxy(x, y)) return(FALSE);
2240 if ((us_dragwindow->state&WINDOWTYPE) != DISPWINDOW ||
2241 us_dragwindow->curnodeproto == NONODEPROTO) return(FALSE);
2242 us_dragnodeproto = us_dragwindow->curnodeproto;
2243 (void)getxy(&us_dragx, &us_dragy);
2244 gridalign(&us_dragx, &us_dragy, 1, us_dragnodeproto);
2245 us_setcursorpos(NOWINDOWFRAME, us_dragx, us_dragy);
2246
2247 if (us_measureshown == 0)
2248 {
2249 us_firstmeasurex = us_dragx; us_firstmeasurey = us_dragy;
2250 } else
2251 {
2252 /* if it didn't actually move, go no further */
2253 if (us_dragx == us_lastcurx && us_dragy == us_lastcury) return(FALSE);
2254
2255 /* undraw the distance */
2256 us_highl.col = 0;
2257 us_drawdistance();
2258 }
2259
2260 /* remember this measured distance */
2261 us_lastmeasurex = us_dragx - us_firstmeasurex;
2262 us_lastmeasurey = us_dragy - us_firstmeasurey;
2263 us_validmesaure = TRUE;
2264
2265 /* draw crosses at the end */
2266 us_highl.col = HIGHLIT;
2267 us_lastcurx = us_dragx; us_lastcury = us_dragy;
2268 TDCLEAR(us_dragpoly->textdescript);
2269 TDSETSIZE(us_dragpoly->textdescript, TXTSETPOINTS(12));
2270 us_dragpoly->tech = el_curtech;
2271 dist = computedistance(us_firstmeasurex, us_firstmeasurey, us_dragx, us_dragy);
2272 (void)estrcpy(us_dragmessage, _("Distance: "));
2273 (void)estrcat(us_dragmessage, latoa(dist, 0));
2274 (void)estrcat(us_dragmessage, x_(" (dX="));
2275 (void)estrcat(us_dragmessage, latoa(us_dragx - us_firstmeasurex, 0));
2276 (void)estrcat(us_dragmessage, x_(" dY="));
2277 (void)estrcat(us_dragmessage, latoa(us_dragy - us_firstmeasurey, 0));
2278 (void)estrcat(us_dragmessage, x_(")"));
2279 us_dragpoly->string = us_dragmessage;
2280 us_drawdistance();
2281 us_measureshown = 1;
2282 return(FALSE);
2283 }
2284
us_drawdistance(void)2285 void us_drawdistance(void)
2286 {
2287 REGISTER WINDOWPART *w;
2288 INTBIG fx, fy, tx, ty;
2289
2290 us_dragpoly->count = 1;
2291 us_dragpoly->style = TEXTBOTLEFT;
2292 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2293 {
2294 if (w->curnodeproto != us_dragnodeproto) continue;
2295 fx = us_firstmeasurex; fy = us_firstmeasurey;
2296 tx = us_lastcurx; ty = us_lastcury;
2297 if (clipline(&fx, &fy, &tx, &ty, w->screenlx, w->screenhx,
2298 w->screenly, w->screenhy)) continue;
2299 us_dragpoly->xv[0] = (fx+tx) / 2;
2300 us_dragpoly->yv[0] = (fy+ty) / 2;
2301 us_showpoly(us_dragpoly, w);
2302 }
2303
2304 /* draw the line */
2305 us_dragpoly->xv[0] = us_firstmeasurex; us_dragpoly->yv[0] = us_firstmeasurey;
2306 us_dragpoly->xv[1] = us_lastcurx; us_dragpoly->yv[1] = us_lastcury;
2307 us_dragpoly->count = 2;
2308 us_dragpoly->style = OPENED;
2309 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2310 if (w->curnodeproto == us_dragnodeproto)
2311 us_showpoly(us_dragpoly, w);
2312
2313 /* draw crosses at the end */
2314 us_dragpoly->xv[0] = us_firstmeasurex; us_dragpoly->yv[0] = us_firstmeasurey;
2315 us_dragpoly->count = 1;
2316 us_dragpoly->style = CROSS;
2317 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2318 if (w->curnodeproto == us_dragnodeproto)
2319 us_showpoly(us_dragpoly, w);
2320 us_dragpoly->xv[0] = us_lastcurx; us_dragpoly->yv[0] = us_lastcury;
2321 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2322 if (w->curnodeproto == us_dragnodeproto)
2323 us_showpoly(us_dragpoly, w);
2324 }
2325
us_distanceup(void)2326 void us_distanceup(void)
2327 {
2328 if (us_measureshown != 0)
2329 {
2330 /* leave the results in the messages window */
2331 ttyputmsg(x_("%s"), us_dragpoly->string);
2332 }
2333 }
2334
2335 /************************* SLIDER THUMB TRACKING *************************/
2336
2337 /*
2338 * initialization method for tracking the horizontal thumb. The cursor X coordinate
2339 * is "x" and the window is "w". The horizontal slider's top side is "hy" and it
2340 * runs horizontally from "lx" to "hx" (including arrows). The routine "callback"
2341 * is invoked with the difference each time.
2342 */
us_hthumbbegin(INTBIG x,WINDOWPART * w,INTBIG hy,INTBIG lx,INTBIG hx,void (* callback)(INTBIG))2343 void us_hthumbbegin(INTBIG x, WINDOWPART *w, INTBIG hy, INTBIG lx, INTBIG hx,
2344 void (*callback)(INTBIG))
2345 {
2346 /* initialize polygon */
2347 if (us_dragpoly == NOPOLYGON) us_dragpoly = allocpolygon(4, us_tool->cluster);
2348 us_dragpoly->desc = &us_highl;
2349
2350 us_dragshown = 0;
2351 us_dragwindow = w;
2352 us_initthumbcoord = x;
2353 us_trackingcallback = callback;
2354
2355 us_trackww.screenlx = us_trackww.uselx = lx;
2356 us_trackww.screenhx = us_trackww.usehx = hx;
2357 us_trackww.screenly = us_trackww.usely = hy-DISPLAYSLIDERSIZE;
2358 us_trackww.screenhy = us_trackww.usehy = hy;
2359 us_trackww.frame = w->frame;
2360 us_trackww.state = DISPWINDOW;
2361 computewindowscale(&us_trackww);
2362 }
2363
2364 /* tracking method for the horizontal thumb */
us_hthumbdown(INTBIG x,INTBIG y)2365 BOOLEAN us_hthumbdown(INTBIG x, INTBIG y)
2366 {
2367 REGISTER INTBIG dx;
2368
2369 if (us_dragshown != 0)
2370 {
2371 /* if it didn't actually move, go no further */
2372 if (x == us_lastcurx) return(FALSE);
2373
2374 /* undraw the outline */
2375 us_highl.col = 0;
2376 us_dragpoly->xv[0] = us_dragwindow->thumblx + (us_lastcurx-us_initthumbcoord)+1;
2377 us_dragpoly->yv[0] = us_trackww.usehy-3;
2378 us_dragpoly->xv[1] = us_dragwindow->thumbhx + (us_lastcurx-us_initthumbcoord)-1;
2379 us_dragpoly->yv[1] = us_trackww.usehy-DISPLAYSLIDERSIZE+1;
2380 us_dragpoly->count = 2;
2381 us_dragpoly->style = FILLEDRECT;
2382 us_showpoly(us_dragpoly, &us_trackww);
2383 }
2384
2385 /* draw the outline */
2386 us_highl.col = HIGHLIT;
2387 if (us_dragwindow->thumblx + (x-us_initthumbcoord) <= us_trackww.uselx+DISPLAYSLIDERSIZE)
2388 x = us_trackww.uselx+DISPLAYSLIDERSIZE+1 - us_dragwindow->thumblx + us_initthumbcoord;
2389 if (us_dragwindow->thumbhx + (x-us_initthumbcoord) >= us_trackww.usehx-DISPLAYSLIDERSIZE)
2390 x = us_trackww.usehx-DISPLAYSLIDERSIZE-1 - us_dragwindow->thumbhx + us_initthumbcoord;
2391 us_dragpoly->xv[0] = us_dragwindow->thumblx + (x-us_initthumbcoord)+1;
2392 us_dragpoly->yv[0] = us_trackww.usehy-3;
2393 us_dragpoly->xv[1] = us_dragwindow->thumbhx + (x-us_initthumbcoord)-1;
2394 us_dragpoly->yv[1] = us_trackww.usehy-DISPLAYSLIDERSIZE+1;
2395 us_dragpoly->count = 2;
2396 us_dragpoly->style = FILLEDRECT;
2397 us_showpoly(us_dragpoly, &us_trackww);
2398
2399 us_dragshown = 1;
2400 us_lastcurx = x;
2401
2402 if (us_trackingcallback != 0)
2403 {
2404 dx = us_lastcurx-us_initthumbcoord;
2405 us_initthumbcoord = us_lastcurx;
2406 (*us_trackingcallback)(dx);
2407 }
2408 return(FALSE);
2409 }
2410
us_hthumbtrackingcallback(INTBIG delta)2411 void us_hthumbtrackingcallback(INTBIG delta)
2412 {
2413 REGISTER NODEPROTO *np;
2414 REGISTER INTBIG cellsizex, screensizex, thumbareax, dsx;
2415
2416 np = us_dragwindow->curnodeproto;
2417 if (np == NONODEPROTO) return;
2418 cellsizex = np->highx - np->lowx;
2419 screensizex = us_dragwindow->screenhx - us_dragwindow->screenlx;
2420 thumbareax = (us_dragwindow->usehx - us_dragwindow->uselx - DISPLAYSLIDERSIZE*2-4) / 2;
2421 if (cellsizex <= screensizex)
2422 {
2423 dsx = delta * (us_dragwindow->screenhx-us_dragwindow->screenlx) / thumbareax;
2424 } else
2425 {
2426 dsx = delta * (np->highx-np->lowx) / thumbareax;
2427 }
2428 us_slideleft(dsx);
2429 us_endbatch();
2430 }
2431
2432 /* completion method for tracking the horozintal thumb in a regular edit window */
us_hthumbdone(void)2433 void us_hthumbdone(void)
2434 {
2435 if (us_dragshown != 0)
2436 {
2437 /* undraw the outline */
2438 us_highl.col = 0;
2439 us_dragpoly->xv[0] = us_dragwindow->thumblx + (us_lastcurx-us_initthumbcoord)+1;
2440 us_dragpoly->yv[0] = us_trackww.usehy-3;
2441 us_dragpoly->xv[1] = us_dragwindow->thumbhx + (us_lastcurx-us_initthumbcoord)-1;
2442 us_dragpoly->yv[1] = us_trackww.usehy-DISPLAYSLIDERSIZE+1;
2443 us_dragpoly->count = 2;
2444 us_dragpoly->style = FILLEDRECT;
2445 us_showpoly(us_dragpoly, &us_trackww);
2446 }
2447 }
2448
2449 /*
2450 * initialization method for tracking the vertical thumb. The cursor Y coordinate
2451 * is "y" and the window is "w". The vertical slider's left side is "hx" and it
2452 * runs vertically from "ly" to "hy" (including arrows). The total number of
2453 * lines of text is "totallines" and the slider is on the left side if "onleft"
2454 * is nonzero.
2455 */
us_vthumbbegin(INTBIG y,WINDOWPART * w,INTBIG hx,INTBIG ly,INTBIG hy,BOOLEAN onleft,void (* callback)(INTBIG))2456 void us_vthumbbegin(INTBIG y, WINDOWPART *w, INTBIG hx, INTBIG ly, INTBIG hy,
2457 BOOLEAN onleft, void (*callback)(INTBIG))
2458 {
2459 /* initialize polygon */
2460 if (us_dragpoly == NOPOLYGON) us_dragpoly = allocpolygon(4, us_tool->cluster);
2461 us_dragpoly->desc = &us_highl;
2462
2463 us_dragshown = 0;
2464 us_dragwindow = w;
2465 us_initthumbcoord = y;
2466 us_dragpoint = -1;
2467 us_trackingcallback = callback;
2468
2469 if (onleft != 0)
2470 {
2471 /* slider is on the left (simulation window) */
2472 us_trackww.screenlx = us_trackww.uselx = hx;
2473 us_trackww.screenhx = us_trackww.usehx = w->usehx;
2474 us_dragoffx = hx-2;
2475 } else
2476 {
2477 /* slider is on the right (edit, text edit, and explorer window) */
2478 us_trackww.screenlx = us_trackww.uselx = w->uselx;
2479 us_trackww.screenhx = us_trackww.usehx = hx+DISPLAYSLIDERSIZE;
2480 us_dragoffx = hx;
2481 }
2482 us_trackww.screenly = ly;
2483 us_trackww.usely = ly;
2484 us_trackww.screenhy = hy;
2485 us_trackww.usehy = hy;
2486 us_trackww.frame = w->frame;
2487 us_trackww.state = DISPWINDOW;
2488 computewindowscale(&us_trackww);
2489 }
2490
2491 /* tracking method for the vertical thumb */
us_vthumbdown(INTBIG x,INTBIG y)2492 BOOLEAN us_vthumbdown(INTBIG x, INTBIG y)
2493 {
2494 REGISTER INTBIG dy;
2495
2496 if (us_dragshown != 0)
2497 {
2498 /* if it didn't actually move, go no further */
2499 if (y == us_lastcury) return(FALSE);
2500
2501 /* undraw the outline */
2502 us_highl.col = 0;
2503 us_dragpoly->xv[0] = us_dragoffx+3;
2504 us_dragpoly->yv[0] = us_dragwindow->thumbly + (us_lastcury-us_initthumbcoord)+1;
2505 us_dragpoly->yv[1] = us_dragwindow->thumbhy + (us_lastcury-us_initthumbcoord)-1;
2506 us_dragpoly->xv[1] = us_dragoffx+DISPLAYSLIDERSIZE-1;
2507 us_dragpoly->count = 2;
2508 us_dragpoly->style = FILLEDRECT;
2509 us_showpoly(us_dragpoly, &us_trackww);
2510 }
2511
2512 /* draw the outline */
2513 us_highl.col = HIGHLIT;
2514 if (us_dragwindow->thumbly + (y-us_initthumbcoord) <= us_trackww.usely+DISPLAYSLIDERSIZE)
2515 y = us_trackww.usely+DISPLAYSLIDERSIZE+1 - us_dragwindow->thumbly + us_initthumbcoord;
2516 if (us_dragwindow->thumbhy + (y-us_initthumbcoord) >= us_trackww.usehy-DISPLAYSLIDERSIZE)
2517 y = us_trackww.usehy-DISPLAYSLIDERSIZE-1 - us_dragwindow->thumbhy + us_initthumbcoord;
2518 us_dragpoly->xv[0] = us_dragoffx+3;
2519 us_dragpoly->yv[0] = us_dragwindow->thumbly + (y-us_initthumbcoord)+1;
2520 us_dragpoly->yv[1] = us_dragwindow->thumbhy + (y-us_initthumbcoord)-1;
2521 us_dragpoly->xv[1] = us_dragoffx+DISPLAYSLIDERSIZE-1;
2522 us_dragpoly->count = 2;
2523 us_dragpoly->style = FILLEDRECT;
2524 us_showpoly(us_dragpoly, &us_trackww);
2525
2526 us_dragshown = 1;
2527 us_lastcury = y;
2528
2529 if (us_trackingcallback != 0)
2530 {
2531 dy = us_lastcury-us_initthumbcoord;
2532 us_initthumbcoord = us_lastcury;
2533 (*us_trackingcallback)(dy);
2534 }
2535 return(FALSE);
2536 }
2537
us_vthumbtrackingcallback(INTBIG delta)2538 void us_vthumbtrackingcallback(INTBIG delta)
2539 {
2540 REGISTER NODEPROTO *np;
2541 REGISTER INTBIG cellsizey, screensizey, thumbareay, dsy;
2542
2543 /* adjust the screen */
2544 np = us_dragwindow->curnodeproto;
2545 if (np == NONODEPROTO) return;
2546 cellsizey = np->highy - np->lowy;
2547 screensizey = us_dragwindow->screenhy - us_dragwindow->screenly;
2548 thumbareay = (us_dragwindow->usehy - us_dragwindow->usely - DISPLAYSLIDERSIZE*2-4) / 2;
2549 if (cellsizey <= screensizey)
2550 {
2551 dsy = delta * (us_dragwindow->screenhy-us_dragwindow->screenly) / thumbareay;
2552 } else
2553 {
2554 dsy = delta * (np->highy-np->lowy) / thumbareay;
2555 }
2556 us_slideup(-dsy);
2557 us_endbatch();
2558 }
2559
2560 /* completion method for tracking the vertical thumb in regular edit window */
us_vthumbdone(void)2561 void us_vthumbdone(void)
2562 {
2563 if (us_dragshown != 0)
2564 {
2565 /* undraw the outline */
2566 us_highl.col = 0;
2567 us_dragpoly->xv[0] = us_dragoffx+3;
2568 us_dragpoly->yv[0] = us_dragwindow->thumbly + (us_lastcury-us_initthumbcoord)+1;
2569 us_dragpoly->yv[1] = us_dragwindow->thumbhy + (us_lastcury-us_initthumbcoord)-1;
2570 us_dragpoly->xv[1] = us_dragoffx+DISPLAYSLIDERSIZE-1;
2571 us_dragpoly->count = 2;
2572 us_dragpoly->style = FILLEDRECT;
2573 us_showpoly(us_dragpoly, &us_trackww);
2574 }
2575 }
2576
2577 /* initialization method for tracking the arrows on sliders */
us_arrowclickbegin(WINDOWPART * w,INTBIG lx,INTBIG hx,INTBIG ly,INTBIG hy,INTBIG amount)2578 void us_arrowclickbegin(WINDOWPART *w, INTBIG lx, INTBIG hx, INTBIG ly, INTBIG hy, INTBIG amount)
2579 {
2580 us_dragwindow = w;
2581 us_arrowlx = lx;
2582 us_arrowhx = hx;
2583 us_arrowly = ly;
2584 us_arrowhy = hy;
2585 us_arrowamount = amount;
2586 }
2587
us_varrowdown(INTBIG x,INTBIG y)2588 BOOLEAN us_varrowdown(INTBIG x, INTBIG y)
2589 {
2590 if (x < us_arrowlx || x > us_arrowhx) return(FALSE);
2591 if (y < us_arrowly || y > us_arrowhy) return(FALSE);
2592 if (y >= us_dragwindow->thumbly && y <= us_dragwindow->thumbhy) return(FALSE);
2593 us_slideup(us_arrowamount);
2594 us_endbatch();
2595 return(FALSE);
2596 }
2597
us_harrowdown(INTBIG x,INTBIG y)2598 BOOLEAN us_harrowdown(INTBIG x, INTBIG y)
2599 {
2600 if (x < us_arrowlx || x > us_arrowhx) return(FALSE);
2601 if (y < us_arrowly || y > us_arrowhy) return(FALSE);
2602 if (x >= us_dragwindow->thumblx && x <= us_dragwindow->thumbhx) return(FALSE);
2603 us_slideleft(us_arrowamount);
2604 us_endbatch();
2605 return(FALSE);
2606 }
2607
2608 /************************* WINDOW PARTITION DIVIDER TRACKING *************************/
2609
us_vpartdividerbegin(INTBIG x,INTBIG ly,INTBIG hy,WINDOWFRAME * wf)2610 void us_vpartdividerbegin(INTBIG x, INTBIG ly, INTBIG hy, WINDOWFRAME *wf)
2611 {
2612 /* initialize polygon */
2613 if (us_dragpoly == NOPOLYGON) us_dragpoly = allocpolygon(4, us_tool->cluster);
2614 us_dragpoly->desc = &us_highl;
2615
2616 us_dragshown = 0;
2617 us_initthumbcoord = x;
2618 us_draglowval = ly;
2619 us_draghighval = hy;
2620
2621 us_trackww.screenlx = us_trackww.uselx = 0;
2622 us_trackww.screenhx = us_trackww.usehx = wf->swid;
2623 us_trackww.screenly = us_trackww.usely = 0;
2624 us_trackww.screenhy = us_trackww.usehy = wf->shei;
2625 us_trackww.frame = wf;
2626 us_trackww.state = DISPWINDOW;
2627 computewindowscale(&us_trackww);
2628 }
2629
us_vpartdividerdown(INTBIG x,INTBIG y)2630 BOOLEAN us_vpartdividerdown(INTBIG x, INTBIG y)
2631 {
2632 if (us_dragshown != 0)
2633 {
2634 /* if it didn't actually move, go no further */
2635 if (x == us_lastcurx) return(FALSE);
2636
2637 /* undraw the line */
2638 us_highl.col = 0;
2639 us_dragpoly->xv[0] = us_lastcurx;
2640 us_dragpoly->yv[0] = us_draglowval;
2641 us_dragpoly->xv[1] = us_lastcurx;
2642 us_dragpoly->yv[1] = us_draghighval;
2643 us_dragpoly->count = 2;
2644 us_dragpoly->style = VECTORS;
2645 us_showpoly(us_dragpoly, &us_trackww);
2646 }
2647
2648 us_lastcurx = x;
2649 if (us_lastcurx >= us_trackww.usehx) us_lastcurx = us_trackww.usehx-1;
2650 if (us_lastcurx < us_trackww.uselx) us_lastcurx = us_trackww.uselx;
2651
2652 /* draw the outline */
2653 us_highl.col = HIGHLIT;
2654 us_dragpoly->xv[0] = us_lastcurx;
2655 us_dragpoly->yv[0] = us_draglowval;
2656 us_dragpoly->xv[1] = us_lastcurx;
2657 us_dragpoly->yv[1] = us_draghighval;
2658 us_dragpoly->count = 2;
2659 us_dragpoly->style = VECTORS;
2660 us_showpoly(us_dragpoly, &us_trackww);
2661
2662 us_dragshown = 1;
2663 return(FALSE);
2664 }
2665
us_vpartdividerdone(void)2666 void us_vpartdividerdone(void)
2667 {
2668 INTBIG lx, hx, ly, hy;
2669 REGISTER WINDOWPART *w;
2670
2671 if (us_dragshown != 0)
2672 {
2673 /* undraw the outline */
2674 us_highl.col = 0;
2675 us_dragpoly->xv[0] = us_lastcurx;
2676 us_dragpoly->yv[0] = us_draglowval;
2677 us_dragpoly->xv[1] = us_lastcurx;
2678 us_dragpoly->yv[1] = us_draghighval;
2679 us_dragpoly->count = 2;
2680 us_dragpoly->style = VECTORS;
2681 us_showpoly(us_dragpoly, &us_trackww);
2682
2683 /* adjust the screen */
2684 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2685 {
2686 if (w->frame != us_trackww.frame) continue;
2687 if (estrcmp(w->location, x_("entire")) == 0) continue;
2688
2689 us_gettruewindowbounds(w, &lx, &hx, &ly, &hy);
2690 lx--; hx++;
2691 ly--; hy++;
2692 if (us_initthumbcoord >= lx-2 && us_initthumbcoord <= lx+2)
2693 {
2694 w->hratio = ((hx - us_lastcurx) * w->hratio + (hx - lx)/2) / (hx - lx);
2695 if (w->hratio > 95)
2696 {
2697 el_curwindowpart = w;
2698 us_killcurrentwindow(FALSE);
2699 return;
2700 }
2701 if (w->hratio < 5)
2702 {
2703 el_curwindowpart = w;
2704 us_killcurrentwindow(TRUE);
2705 return;
2706 }
2707 }
2708 if (us_initthumbcoord >= hx-2 && us_initthumbcoord <= hx+2)
2709 {
2710 w->hratio = ((us_lastcurx - lx) * w->hratio + (hx - lx)/2) / (hx - lx);
2711 if (w->hratio > 95)
2712 {
2713 el_curwindowpart = w;
2714 us_killcurrentwindow(FALSE);
2715 return;
2716 }
2717 if (w->hratio < 5)
2718 {
2719 el_curwindowpart = w;
2720 us_killcurrentwindow(TRUE);
2721 return;
2722 }
2723 }
2724 }
2725
2726 /* remember the explorer percentage */
2727 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2728 {
2729 if ((w->state&WINDOWTYPE) != EXPLORERWINDOW) continue;
2730 us_explorerratio = w->hratio;
2731 }
2732 us_beginchanges();
2733 us_drawmenu(1, us_trackww.frame);
2734 us_endchanges(NOWINDOWPART);
2735 us_state |= HIGHLIGHTSET;
2736 us_showallhighlight();
2737 }
2738 }
2739
us_hpartdividerbegin(INTBIG y,INTBIG lx,INTBIG hx,WINDOWFRAME * wf)2740 void us_hpartdividerbegin(INTBIG y, INTBIG lx, INTBIG hx, WINDOWFRAME *wf)
2741 {
2742 /* initialize polygon */
2743 if (us_dragpoly == NOPOLYGON) us_dragpoly = allocpolygon(4, us_tool->cluster);
2744 us_dragpoly->desc = &us_highl;
2745
2746 us_dragshown = 0;
2747 us_initthumbcoord = y;
2748 us_draglowval = lx;
2749 us_draghighval = hx;
2750
2751 us_trackww.screenlx = us_trackww.uselx = 0;
2752 us_trackww.screenhx = us_trackww.usehx = wf->swid;
2753 us_trackww.screenly = us_trackww.usely = 0;
2754 us_trackww.screenhy = us_trackww.usehy = wf->shei;
2755 us_trackww.frame = wf;
2756 us_trackww.state = DISPWINDOW;
2757 computewindowscale(&us_trackww);
2758 }
2759
us_hpartdividerdown(INTBIG x,INTBIG y)2760 BOOLEAN us_hpartdividerdown(INTBIG x, INTBIG y)
2761 {
2762 if (us_dragshown != 0)
2763 {
2764 /* if it didn't actually move, go no further */
2765 if (y == us_lastcury) return(FALSE);
2766
2767 /* undraw the line */
2768 us_highl.col = 0;
2769 us_dragpoly->xv[0] = us_draglowval;
2770 us_dragpoly->yv[0] = us_lastcury;
2771 us_dragpoly->xv[1] = us_draghighval;
2772 us_dragpoly->yv[1] = us_lastcury;
2773 us_dragpoly->count = 2;
2774 us_dragpoly->style = VECTORS;
2775 us_showpoly(us_dragpoly, &us_trackww);
2776 }
2777
2778 us_lastcury = y;
2779 if (us_lastcury >= us_trackww.usehy) us_lastcury = us_trackww.usehy-1;
2780 if (us_lastcury < us_trackww.usely) us_lastcury = us_trackww.usely;
2781
2782 /* draw the outline */
2783 us_highl.col = HIGHLIT;
2784 us_dragpoly->xv[0] = us_draglowval;
2785 us_dragpoly->yv[0] = us_lastcury;
2786 us_dragpoly->xv[1] = us_draghighval;
2787 us_dragpoly->yv[1] = us_lastcury;
2788 us_dragpoly->count = 2;
2789 us_dragpoly->style = VECTORS;
2790 us_showpoly(us_dragpoly, &us_trackww);
2791
2792 us_dragshown = 1;
2793 return(FALSE);
2794 }
2795
us_hpartdividerdone(void)2796 void us_hpartdividerdone(void)
2797 {
2798 INTBIG lx, hx, ly, hy;
2799 REGISTER WINDOWPART *w;
2800
2801 if (us_dragshown != 0)
2802 {
2803 /* undraw the outline */
2804 us_highl.col = 0;
2805 us_dragpoly->xv[0] = us_draglowval;
2806 us_dragpoly->yv[0] = us_lastcury;
2807 us_dragpoly->xv[1] = us_draghighval;
2808 us_dragpoly->yv[1] = us_lastcury;
2809 us_dragpoly->count = 2;
2810 us_dragpoly->style = VECTORS;
2811 us_showpoly(us_dragpoly, &us_trackww);
2812
2813 /* adjust the screen */
2814 for(w = el_topwindowpart; w != NOWINDOWPART; w = w->nextwindowpart)
2815 {
2816 if (w->frame != us_trackww.frame) continue;
2817 if (estrcmp(w->location, x_("entire")) == 0) continue;
2818
2819 us_gettruewindowbounds(w, &lx, &hx, &ly, &hy);
2820 lx--; hx++;
2821 ly--; hy++;
2822 if (us_initthumbcoord >= ly-2 && us_initthumbcoord <= ly+2)
2823 {
2824 w->vratio = ((hy - us_lastcury) * w->vratio + (hy - ly)/2) / (hy - ly);
2825 if (w->vratio > 95)
2826 {
2827 el_curwindowpart = w;
2828 us_killcurrentwindow(FALSE);
2829 return;
2830 }
2831 if (w->vratio < 5)
2832 {
2833 el_curwindowpart = w;
2834 us_killcurrentwindow(TRUE);
2835 return;
2836 }
2837 }
2838 if (us_initthumbcoord >= hy-2 && us_initthumbcoord <= hy+2)
2839 {
2840 w->vratio = ((us_lastcury - ly) * w->vratio + (hy - ly)/2) / (hy - ly);
2841 if (w->vratio > 95)
2842 {
2843 el_curwindowpart = w;
2844 us_killcurrentwindow(FALSE);
2845 return;
2846 }
2847 if (w->vratio < 5)
2848 {
2849 el_curwindowpart = w;
2850 us_killcurrentwindow(TRUE);
2851 return;
2852 }
2853 }
2854 }
2855 us_beginchanges();
2856 us_drawmenu(1, us_trackww.frame);
2857 us_endchanges(NOWINDOWPART);
2858 us_state |= HIGHLIGHTSET;
2859 us_showallhighlight();
2860 }
2861 }
2862
2863 /************************* MISCELLANEOUS *************************/
2864
2865 /* cursor advance routine when stretching the highlight object */
us_stretchdown(INTBIG x,INTBIG y)2866 BOOLEAN us_stretchdown(INTBIG x, INTBIG y)
2867 {
2868 /* pan the screen if the edge was hit */
2869 us_panatscreenedge(&x, &y);
2870
2871 /* grid align the cursor value */
2872 if (us_setxy(x, y) || us_dragwindow != el_curwindowpart)
2873 {
2874 (void)us_setxy(us_lastcurx, us_lastcury);
2875 return(FALSE);
2876 }
2877 (void)getxy(&us_lastcurx, &us_lastcury);
2878 us_setcursorpos(NOWINDOWFRAME, us_lastcurx, us_lastcury);
2879
2880 /* if the box is already being shown, erase it */
2881 if (us_dragshown != 0)
2882 {
2883 /* if it didn't actually move, go no further */
2884 if (us_dragx == us_lastcurx && us_dragy == us_lastcury) return(FALSE);
2885
2886 /* undraw the box */
2887 us_invertstretch();
2888 }
2889
2890 /* advance the box */
2891 us_dragx = us_lastcurx;
2892 us_dragy = us_lastcury;
2893
2894 /* draw the new box */
2895 us_invertstretch();
2896 us_dragshown = 1;
2897 return(FALSE);
2898 }
2899
us_invertstretch(void)2900 void us_invertstretch(void)
2901 {
2902 us_wanttoinvert(us_dragox, us_dragoy, us_dragox, us_dragy, us_dragwindow);
2903 us_wanttoinvert(us_dragox, us_dragy, us_dragx, us_dragy, us_dragwindow);
2904 us_wanttoinvert(us_dragx, us_dragy, us_dragx, us_dragoy, us_dragwindow);
2905 us_wanttoinvert(us_dragx, us_dragoy, us_dragox, us_dragoy, us_dragwindow);
2906 }
2907
2908 /*
2909 * routine to clip and possibly draw a line from (fx,fy) to (tx,ty) in
2910 * window "w" with description "desc", texture "texture"
2911 */
us_wanttoinvert(INTBIG fx,INTBIG fy,INTBIG tx,INTBIG ty,WINDOWPART * w)2912 void us_wanttoinvert(INTBIG fx, INTBIG fy, INTBIG tx, INTBIG ty, WINDOWPART *w)
2913 {
2914 if ((w->state&INPLACEEDIT) != 0)
2915 {
2916 xform(fx, fy, &fx, &fy, w->outofcell);
2917 xform(tx, ty, &tx, &ty, w->outofcell);
2918 }
2919 fx = applyxscale(w, fx-w->screenlx) + w->uselx;
2920 fy = applyyscale(w, fy-w->screenly) + w->usely;
2921 tx = applyxscale(w, tx-w->screenlx) + w->uselx;
2922 ty = applyyscale(w, ty-w->screenly) + w->usely;
2923 if (clipline(&fx, &fy, &tx, &ty, w->uselx, w->usehx, w->usely, w->usehy)) return;
2924 screeninvertline(w, fx, fy, tx, ty);
2925 }
2926
2927 /* cursor advance routine when creating or moving an object */
us_dragdown(INTBIG x,INTBIG y)2928 BOOLEAN us_dragdown(INTBIG x, INTBIG y)
2929 {
2930 REGISTER INTBIG i;
2931
2932 if (el_pleasestop != 0) return(TRUE);
2933
2934 /* pan the screen if the edge was hit */
2935 us_panatscreenedge(&x, &y);
2936
2937 /* grid align the cursor value */
2938 if (us_setxy(x, y) || us_dragwindow != el_curwindowpart)
2939 {
2940 (void)us_setxy(us_lastcurx, us_lastcury);
2941 return(FALSE);
2942 }
2943 (void)getxy(&us_lastcurx, &us_lastcury);
2944 gridalign(&us_lastcurx, &us_lastcury, 1, us_dragwindow->curnodeproto);
2945 us_setcursorpos(NOWINDOWFRAME, us_lastcurx, us_lastcury);
2946
2947 /* if the box is already being shown, erase it */
2948 if (us_dragshown != 0)
2949 {
2950 /* if it didn't actually move, go no further */
2951 if (us_dragx == us_lastcurx && us_dragy == us_lastcury) return(FALSE);
2952
2953 /* undraw the box */
2954 us_highl.col = 0;
2955 us_showpoly(us_dragpoly, us_dragwindow);
2956 }
2957
2958 /* advance the box */
2959 for(i = 0; i < us_dragpoly->count; i++)
2960 {
2961 us_dragpoly->xv[i] += us_lastcurx - us_dragx;
2962 us_dragpoly->yv[i] += us_lastcury - us_dragy;
2963 }
2964 us_dragx = us_lastcurx;
2965 us_dragy = us_lastcury;
2966
2967 /* draw the new box */
2968 us_highl.col = HIGHLIT;
2969 us_showpoly(us_dragpoly, us_dragwindow);
2970 us_dragshown = 1;
2971 return(FALSE);
2972 }
2973
2974 /* termination routine when stretching an area */
us_invertdragup(void)2975 void us_invertdragup(void)
2976 {
2977 if (us_dragshown != 0) us_invertstretch();
2978 }
2979
2980 /* termination routine when creating or moving an object */
us_dragup(void)2981 void us_dragup(void)
2982 {
2983 if (us_dragshown != 0)
2984 {
2985 /* undraw the box */
2986 us_highl.col = 0;
2987 us_showpoly(us_dragpoly, us_dragwindow);
2988 }
2989 }
2990
2991 /*
2992 * Routine to pan the screen if the cursor at (x,y) hits the edge of window "us_dragwindow".
2993 * Adjusts the coordinates to be on the screen.
2994 */
us_panatscreenedge(INTBIG * x,INTBIG * y)2995 void us_panatscreenedge(INTBIG *x, INTBIG *y)
2996 {
2997 REGISTER UINTBIG now;
2998 REGISTER BOOLEAN didpan;
2999
3000 /* pan screen if drag went over edge */
3001 didpan = FALSE;
3002 if (*x >= us_dragwindow->usehx)
3003 {
3004 *x = us_dragwindow->usehx;
3005 now = ticktime();
3006 if (now - us_beforepantime >= MINSLIDEDELAY)
3007 {
3008 us_beforepantime = now;
3009 us_slideleft((us_dragwindow->screenhx - us_dragwindow->screenlx) / 10);
3010 didpan = TRUE;
3011 }
3012 }
3013 if (*x <= us_dragwindow->uselx)
3014 {
3015 *x = us_dragwindow->uselx;
3016 now = ticktime();
3017 if (now - us_beforepantime >= MINSLIDEDELAY)
3018 {
3019 us_beforepantime = now;
3020 us_slideleft(-(us_dragwindow->screenhx - us_dragwindow->screenlx) / 10);
3021 didpan = TRUE;
3022 }
3023 }
3024 if (*y >= us_dragwindow->usehy)
3025 {
3026 *y = us_dragwindow->usehy;
3027 now = ticktime();
3028 if (now - us_beforepantime >= MINSLIDEDELAY)
3029 {
3030 us_beforepantime = now;
3031 us_slideup(-(us_dragwindow->screenhy - us_dragwindow->screenly) / 10);
3032 didpan = TRUE;
3033 }
3034 }
3035 if (*y <= us_dragwindow->usely)
3036 {
3037 *y = us_dragwindow->usely;
3038 now = ticktime();
3039 if (now - us_beforepantime >= MINSLIDEDELAY)
3040 {
3041 us_beforepantime = now;
3042 us_slideup((us_dragwindow->screenhy - us_dragwindow->screenly) / 10);
3043 didpan = TRUE;
3044 }
3045 }
3046 if (didpan)
3047 {
3048 us_endchanges(NOWINDOWPART);
3049 us_dragshown = 0;
3050 }
3051 }
3052
us_nullup(INTBIG x,INTBIG y)3053 BOOLEAN us_nullup(INTBIG x, INTBIG y) { return(FALSE); }
3054
us_nullvoid(void)3055 void us_nullvoid(void) {}
3056
us_nullchar(INTBIG x,INTBIG y,INTSML ch)3057 BOOLEAN us_nullchar(INTBIG x, INTBIG y, INTSML ch) { return(FALSE); }
3058
3059 /*
3060 * routine to ignore all cursor motion while the button is up
3061 */
us_ignoreup(INTBIG x,INTBIG y)3062 BOOLEAN us_ignoreup(INTBIG x, INTBIG y)
3063 {
3064 gridalign(&x, &y, 1, el_curlib->curnodeproto);
3065 us_setcursorpos(NOWINDOWFRAME, x, y);
3066 return(FALSE);
3067 }
3068
3069 /*
3070 * routine to cause termination of tracking when a key is typed
3071 */
us_stoponchar(INTBIG x,INTBIG y,INTSML chr)3072 BOOLEAN us_stoponchar(INTBIG x, INTBIG y, INTSML chr)
3073 {
3074 if (chr == 'a' || chr == 'A')
3075 {
3076 el_pleasestop = 1;
3077 (void)stopping(STOPREASONTRACK);
3078 }
3079 return(TRUE);
3080 }
3081
3082 /*
3083 * routine to cause termination of tracking and pop stacked highlighting
3084 * when a key is typed
3085 */
us_stopandpoponchar(INTBIG x,INTBIG y,INTSML chr)3086 BOOLEAN us_stopandpoponchar(INTBIG x, INTBIG y, INTSML chr)
3087 {
3088 if (chr == 'a' || chr == 'A')
3089 {
3090 el_pleasestop = 1;
3091 (void)stopping(STOPREASONTRACK);
3092 us_pophighlight(FALSE);
3093 }
3094 return(TRUE);
3095 }
3096