1 /*
2 * Author: William Chia-Wei Cheng (bill.cheng@acm.org)
3 *
4 * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5 *
6 * This file may be distributed under the terms of the Q Public License
7 * as defined by Trolltech AS of Norway and appearing in the file
8 * LICENSE.QPL included in the packaging of this file.
9 *
10 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * @(#)$Header: /mm2/home/cvs/bc-src/tgif/pin.c,v 1.6 2011/05/16 16:21:58 william Exp $
19 */
20
21 #define _INCLUDE_FROM_PIN_C_
22
23 #include "tgifdefs.h"
24
25 #include "auxtext.e"
26 #include "choice.e"
27 #include "color.e"
28 #include "dialog.e"
29 #include "drawing.e"
30 #include "mainloop.e"
31 #include "msg.e"
32 #include "navigate.e"
33 #include "obj.e"
34 #include "pin.e"
35 #include "poly.e"
36 #include "raster.e"
37 #include "rect.e"
38 #include "select.e"
39 #include "setup.e"
40 #include "strtbl.e"
41
42 int drawPolyToConnectPins=0;
43
44 struct ObjRec *gpStartPin=NULL, *gpEndPin=NULL;
45
46 static struct SelRec *topPinSel=NULL, *botPinSel=NULL;
47
48 static struct ObjRec *gpHighLightedPin=NULL;
49
50 static
CleanUpPinInfo()51 void CleanUpPinInfo()
52 {
53 struct SelRec *next_sel=NULL;
54
55 for ( ; topPinSel != NULL; topPinSel=next_sel) {
56 next_sel = topPinSel->next;
57 free(topPinSel);
58 }
59 topPinSel = botPinSel = NULL;
60 gpStartPin = gpEndPin = NULL;
61 }
62
63 static
CachePin(ObjPtr)64 void CachePin(ObjPtr)
65 struct ObjRec *ObjPtr;
66 {
67 struct SelRec *sel_ptr=(struct SelRec *)malloc(sizeof(struct SelRec));
68
69 if (sel_ptr == NULL) FailAllocMessage();
70 memset(sel_ptr, 0, sizeof(struct SelRec));
71 sel_ptr->obj = ObjPtr;
72 sel_ptr->next = topPinSel;
73 sel_ptr->prev = NULL;
74 if (topPinSel == NULL) {
75 botPinSel = sel_ptr;
76 } else {
77 topPinSel->prev = sel_ptr;
78 }
79 topPinSel = sel_ptr;
80 }
81
82 static
PreparePinInfoForAnObject(ObjPtr,nInsideAnIcon)83 void PreparePinInfoForAnObject(ObjPtr, nInsideAnIcon)
84 struct ObjRec *ObjPtr;
85 int nInsideAnIcon;
86 {
87 struct ObjRec *obj_ptr=NULL;
88
89 switch (ObjPtr->type) {
90 case OBJ_GROUP:
91 case OBJ_SYM:
92 for (obj_ptr=ObjPtr->detail.r->last; obj_ptr != NULL;
93 obj_ptr=obj_ptr->prev) {
94 if (colorLayers && !ObjInVisibleLayer(obj_ptr)) {
95 continue;
96 }
97 PreparePinInfoForAnObject(obj_ptr, nInsideAnIcon);
98 }
99 break;
100 case OBJ_ICON:
101 if (nInsideAnIcon) return;
102 for (obj_ptr=ObjPtr->detail.r->last; obj_ptr != NULL;
103 obj_ptr=obj_ptr->prev) {
104 if (colorLayers && !ObjInVisibleLayer(obj_ptr)) {
105 continue;
106 }
107 PreparePinInfoForAnObject(obj_ptr, TRUE);
108 }
109 break;
110 case OBJ_PIN:
111 CachePin(ObjPtr);
112 break;
113 default: return;
114 }
115 }
116
117 static
PreparePinInfo()118 void PreparePinInfo()
119 {
120 struct ObjRec *obj_ptr=NULL;
121
122 gpStartPin = gpEndPin = NULL;
123 for (obj_ptr=botObj; obj_ptr != NULL; obj_ptr=obj_ptr->prev) {
124 obj_ptr->tmp_child = NULL;
125 obj_ptr->tmp_parent = NULL;
126 if (colorLayers && !ObjInVisibleLayer(obj_ptr)) {
127 continue;
128 }
129 PreparePinInfoForAnObject(obj_ptr, FALSE);
130 }
131 }
132
133 static
GetPins(pObj,ppTopSel,ppBotSel)134 int GetPins(pObj, ppTopSel, ppBotSel)
135 struct ObjRec *pObj;
136 struct SelRec **ppTopSel, **ppBotSel;
137 {
138 switch (pObj->type) {
139 case OBJ_GROUP: break;
140 case OBJ_SYM: break;
141 case OBJ_ICON: break;
142 case OBJ_PIN: break;
143 default: return FALSE;
144 }
145 topPinSel = botPinSel = NULL;
146 if (pObj->type == OBJ_PIN) {
147 PreparePinInfoForAnObject(pObj, FALSE);
148 } else {
149 struct ObjRec *pSubObj=NULL;
150 int nInsideAnIcon=(pObj->type==OBJ_ICON);
151
152 for (pSubObj=pObj->detail.r->first; pSubObj != NULL;
153 pSubObj=pSubObj->next) {
154 PreparePinInfoForAnObject(pSubObj, nInsideAnIcon);
155 }
156 }
157 if (topPinSel == NULL) return FALSE;
158
159 if (ppTopSel != NULL) *ppTopSel = topPinSel;
160 if (ppBotSel != NULL) *ppBotSel = botPinSel;
161 topPinSel = botPinSel = NULL;
162 return TRUE;
163 }
164
165 static
AddObjToSorted(pObj,ppTopSel,ppBotSel)166 int AddObjToSorted(pObj, ppTopSel, ppBotSel)
167 struct ObjRec *pObj;
168 struct SelRec **ppTopSel, **ppBotSel;
169 {
170 int nIndex=(int)(long)(pObj->userdata);
171 struct SelRec *pSel=NULL;
172
173 for (pSel=(*ppTopSel); pSel != NULL; pSel=pSel->next) {
174 if (nIndex > (int)(long)(pSel->obj->userdata)) {
175 return (AddObjIntoSel(pObj, pSel->prev, pSel, ppTopSel, ppBotSel) !=
176 NULL);
177 }
178 }
179 return (AddObjIntoSel(pObj, (*ppBotSel), NULL, ppTopSel, ppBotSel) != NULL);
180 }
181
FindExtraPoly(pTopSel,pBotSel,ppTopSel,ppBotSel,pnCount,pBBox)182 int FindExtraPoly(pTopSel, pBotSel, ppTopSel, ppBotSel, pnCount, pBBox)
183 struct SelRec *pTopSel, *pBotSel;
184 struct SelRec **ppTopSel, **ppBotSel;
185 int *pnCount;
186 struct BBRec *pBBox;
187 {
188 struct SelRec *pSel=NULL, *first_poly_sel=NULL, *last_poly_sel=NULL;
189
190 pBBox->ltx = pTopSel->obj->bbox.ltx;
191 pBBox->lty = pTopSel->obj->bbox.lty;
192 pBBox->rbx = pTopSel->obj->bbox.rbx;
193 pBBox->rby = pTopSel->obj->bbox.rby;
194 if (pnCount != NULL) (*pnCount) = 0;
195 for (pSel=pTopSel; pSel != NULL; pSel=pSel->next) {
196 struct SelRec *top_pin_sel=NULL, *bot_pin_sel=NULL;
197
198 if (GetPins(pSel->obj, &top_pin_sel, &bot_pin_sel)) {
199 struct SelRec *pin_sel_ptr=NULL;
200
201 for (pin_sel_ptr=top_pin_sel; pin_sel_ptr != NULL;
202 pin_sel_ptr=pin_sel_ptr->next) {
203 struct ConnRec *conn_ptr=NULL;
204
205 for (conn_ptr=pin_sel_ptr->obj->detail.r->first_conn;
206 conn_ptr != NULL; conn_ptr=conn_ptr->next) {
207 if (FindObjInSel(conn_ptr->poly_obj,
208 first_poly_sel, last_poly_sel) == NULL) {
209 PrependObjToSel(conn_ptr->poly_obj, &first_poly_sel,
210 &last_poly_sel);
211 }
212 }
213 }
214 JustFreeSel(top_pin_sel, bot_pin_sel);
215 }
216 }
217 if (first_poly_sel == NULL) {
218 return FALSE;
219 } else {
220 struct SelRec *pPolySel=NULL, *pNextPolySel=NULL;
221 struct SelRec *pTopSortedSel=NULL, *pBotSortedSel=NULL;
222
223 for (pPolySel=first_poly_sel; pPolySel != NULL; pPolySel=pNextPolySel) {
224 struct ObjRec *pPolyObj=pPolySel->obj;
225
226 pNextPolySel = pPolySel->next;
227 for (pSel=pTopSel; pSel != NULL; pSel=pSel->next) {
228 if (pSel->obj == pPolyObj) {
229 UnlinkSel(pPolySel, &first_poly_sel, &last_poly_sel);
230 free(pPolySel);
231 break;
232 }
233 }
234 if (pSel == NULL) {
235 struct ObjRec *pObj=NULL;
236 int nIndex=0;
237
238 for (pObj=topObj; pObj != NULL; pObj=pObj->next, nIndex++) {
239 if (pObj == pPolyObj) {
240 pPolyObj->userdata = (void*)(long)nIndex;
241 if (AddObjToSorted(pPolyObj,
242 &pTopSortedSel, &pBotSortedSel)) {
243 }
244 if (pnCount != NULL) (*pnCount)++;
245 ExpandBBox(&pPolyObj->bbox, pBBox);
246 break;
247 }
248 }
249 }
250 }
251 JustFreeSel(first_poly_sel, last_poly_sel);
252 first_poly_sel = pTopSortedSel;
253 last_poly_sel = pBotSortedSel;
254 }
255 if (first_poly_sel == NULL) return FALSE;
256
257 if (ppTopSel != NULL) *ppTopSel = first_poly_sel;
258 if (ppBotSel != NULL) *ppBotSel = last_poly_sel;
259 return TRUE;
260 }
261
262 static
FindPinObj(AbsX,AbsY)263 struct ObjRec *FindPinObj(AbsX, AbsY)
264 int AbsX, AbsY;
265 {
266 struct SelRec *sel_ptr=NULL;
267
268 for (sel_ptr=topPinSel; sel_ptr != NULL; sel_ptr=sel_ptr->next) {
269 if (PointInBBox(AbsX, AbsY, sel_ptr->obj->obbox)) {
270 return sel_ptr->obj;
271 }
272 }
273 return NULL;
274 }
275
HighLightAPin(forward)276 void HighLightAPin(forward)
277 int forward;
278 {
279 if (drawPolyHighlightedNode != NULL) {
280 SelBox(drawWindow, revGrayGC,
281 OFFSET_X(drawPolyHighlightedNode->obbox.ltx)-2,
282 OFFSET_Y(drawPolyHighlightedNode->obbox.lty)-2,
283 OFFSET_X(drawPolyHighlightedNode->obbox.rbx)+2,
284 OFFSET_Y(drawPolyHighlightedNode->obbox.rby)+2);
285 if (forward) {
286 gpHighLightedPin = drawPolyHighlightedNode;
287 } else {
288 gpHighLightedPin = NULL;
289 }
290 }
291 }
292
HandlePinHighlights(MouseX,MouseY)293 void HandlePinHighlights(MouseX, MouseY)
294 int MouseX, MouseY;
295 {
296 int need_to_highlight=FALSE, something_changed=FALSE;
297 struct ObjRec *obj_under_cursor=NULL;
298
299 obj_under_cursor = FindPinObj(ABS_X(MouseX), ABS_Y(MouseY));
300 if (drawPolyHighlightedNode != NULL) {
301 if (obj_under_cursor != drawPolyHighlightedNode) {
302 /* un-highlight */
303 HighLightAPin(FALSE);
304 if (obj_under_cursor != NULL) {
305 drawPolyHighlightedNode = obj_under_cursor;
306 /* may need to call something like SetWiringNodeInfo()!? */
307 } else {
308 drawPolyHighlightedNode = NULL;
309 /* may need to call something like SetWiringNodeInfo()!? */
310 }
311 if (drawPolyHighlightedNode != NULL) {
312 need_to_highlight = TRUE;
313 }
314 something_changed = TRUE;
315 }
316 } else {
317 if (obj_under_cursor != NULL) {
318 drawPolyHighlightedNode = obj_under_cursor;
319 /* may need to call something like SetWiringNodeInfo()!? */
320 need_to_highlight = TRUE;
321 something_changed = TRUE;
322 }
323 }
324 if (need_to_highlight) {
325 HighLightAPin(TRUE);
326 }
327 }
328
329 static
AppendConnToPin(pPinObj,pConn,pPolyObj)330 void AppendConnToPin(pPinObj, pConn, pPolyObj)
331 struct ObjRec *pPinObj, *pPolyObj;
332 struct ConnRec *pConn;
333 {
334 pPinObj->detail.r->pin_connected++;
335
336 pConn->pin_obj = pPinObj;
337 pConn->poly_obj = pPolyObj;
338
339 pConn->prev = pPinObj->detail.r->last_conn;
340 pConn->next = NULL;
341 if (pPinObj->detail.r->last_conn == NULL) {
342 pPinObj->detail.r->first_conn = pConn;
343 } else {
344 pPinObj->detail.r->last_conn->next = pConn;
345 }
346 pPinObj->detail.r->last_conn = pConn;
347 }
348
349 static
CreateConnection(pStartPin,pEndPin)350 void CreateConnection(pStartPin, pEndPin)
351 struct ObjRec *pStartPin, *pEndPin;
352 {
353 struct ConnRec *pStartConn=NULL, *pEndConn=NULL;
354
355 pStartConn = (struct ConnRec *)malloc(sizeof(struct ConnRec));
356 pEndConn = (struct ConnRec *)malloc(sizeof(struct ConnRec));
357 if (pStartConn == NULL || pEndConn == NULL) {
358 FailAllocMessage();
359 if (pStartConn != NULL) free(pStartConn);
360 if (pEndConn != NULL) free(pEndConn);
361 return;
362 }
363 memset(pStartConn, 0, sizeof(struct ConnRec));
364 memset(pEndConn, 0, sizeof(struct ConnRec));
365
366 topObj->detail.p->start_conn = pStartConn;
367 topObj->detail.p->end_conn = pEndConn;
368
369 pStartConn->at_start = TRUE;
370 pEndConn->at_start = FALSE;
371
372 AppendConnToPin(pStartPin, pStartConn, topObj);
373 AppendConnToPin(pEndPin, pEndConn, topObj);
374 }
375
ConnectPins()376 void ConnectPins()
377 {
378 int already_in_hyperspace=inHyperSpace, connecting=TRUE;
379 XGCValues values;
380
381 PreparePinInfo();
382 if (topPinSel == NULL) {
383 MsgBox(TgLoadString(STID_NO_PINS_FOUND_IN_CUR_DRAWING), TOOL_NAME,
384 INFO_MB);
385 return;
386 }
387 MakeQuiescent();
388
389 ResetWiringNodeInfo();
390 values.line_width = 3;
391 XChangeGC(mainDisplay, revGrayGC, GCLineWidth, &values);
392
393 SetCurChoice(DRAWPOLY);
394 gstWiringInfo.num_ports_to_connect = 0;
395
396 while (connecting) {
397 drawPolyToConnectPins = 2;
398 drawPolyHighlightedNode = gpHighLightedPin = NULL;
399 gpStartPin = gpEndPin = NULL;
400 SetStringStatus(TgLoadCachedString(CSTID_SEL_A_PIN_ESC_TO_END_DOTS));
401 for (;;) {
402 XEvent input;
403
404 XNextEvent(mainDisplay, &input);
405 if (input.type == Expose) {
406 ExposeEventHandler(&input, TRUE);
407 } else if (input.type == KeyPress) {
408 if (KeyPressEventIsEscape(&input.xkey)) {
409 connecting = FALSE;
410 break;
411 }
412 } else if (input.xany.window == drawWindow) {
413 polyDrawn = FALSE;
414 DrawingEventHandler(&input);
415 if (curChoice == DRAWPOLY) {
416 if (polyDrawn) {
417 break;
418 } else if (drawPolyToConnectPins == (-1)) {
419 break;
420 }
421 } else {
422 polyDrawn = FALSE;
423 break;
424 }
425 }
426 }
427 drawPolyToConnectPins = 0;
428 if (gpHighLightedPin != NULL) {
429 drawPolyHighlightedNode = gpHighLightedPin;
430 /* may need to call something like SetWiringNodeInfo()!? */
431 HighLightAPin(FALSE);
432 }
433 drawPolyHighlightedNode = gpHighLightedPin = NULL;
434
435 if (gpStartPin != NULL && gpEndPin != NULL) {
436 CreateConnection(gpStartPin, gpEndPin);
437 }
438 }
439 SetCurChoice(NOTHING);
440
441 values.line_width = 1;
442 XChangeGC(mainDisplay, revGrayGC, GCLineWidth, &values);
443 if (already_in_hyperspace && !inHyperSpace) ToggleHyperSpace(TRUE);
444
445 CleanUpPinInfo();
446 }
447
FreeConn(pConn)448 void FreeConn(pConn)
449 struct ConnRec *pConn;
450 {
451 free(pConn);
452 }
453
454 static
UnlinkConn(pConn)455 void UnlinkConn(pConn)
456 struct ConnRec *pConn;
457 {
458 struct GroupRec *pGroup=pConn->pin_obj->detail.r;
459
460 if (pGroup->first_conn == pConn) {
461 pGroup->first_conn = pConn->next;
462 } else {
463 pConn->prev->next = pConn->next;
464 }
465 if (pGroup->last_conn == pConn) {
466 pGroup->last_conn = pConn->prev;
467 } else {
468 pConn->next->prev = pConn->prev;
469 }
470 pGroup->pin_connected--;
471 pConn->pin_obj = NULL;
472 }
473
DelConnFromPoly(pConn)474 void DelConnFromPoly(pConn)
475 struct ConnRec *pConn;
476 {
477 pConn->poly_obj = NULL;
478 UnlinkConn(pConn);
479 FreeConn(pConn);
480 }
481
DelConnFromPin(pConn)482 void DelConnFromPin(pConn)
483 struct ConnRec *pConn;
484 {
485 /* struct ObjRec *pPinObj=pConn->pin_obj; */
486 struct ObjRec *pPolyObj=pConn->poly_obj;
487
488 if (pConn->at_start) {
489 pPolyObj->detail.p->start_conn = NULL;
490 } else {
491 pPolyObj->detail.p->end_conn = NULL;
492 }
493 UnlinkConn(pConn);
494 FreeConn(pConn);
495
496 DelObj(pPolyObj);
497 }
498
CleanUpPins()499 void CleanUpPins()
500 {
501 }
502
InitPins()503 int InitPins()
504 {
505 return TRUE;
506 }
507
508