1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2000 Ales V. Hvezda
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
24 #include <libgeda/libgeda.h>
26 #include "../include/globals.h"
27 #include "../include/prototype.h"
29 #ifdef HAVE_LIBDMALLOC
33 /*! \todo Finish function documentation!!!
35 * \par Function Description
38 void o_net_draw(TOPLEVEL
*w_current
, OBJECT
*o_current
)
41 int x1
, y1
, x2
, y2
; /* screen coords */
43 #if NET_DEBUG /* debug */
48 if (o_current
== NULL
) {
52 if (o_current
->line
== NULL
) {
56 /* reuse line's routine */
57 if ( (w_current
->DONT_REDRAW
== 1) ||
58 (!o_line_visible(w_current
, o_current
->line
, &x1
, &y1
, &x2
, &y2
)) ) {
63 printf("drawing net\n\n");
66 if (w_current
->net_style
== THICK
) {
67 size
= SCREENabs(w_current
, NET_WIDTH
);
72 gdk_gc_set_line_attributes(w_current
->gc
, size
,
77 gdk_gc_set_line_attributes(w_current
->bus_gc
, size
,
83 if (w_current
->override_color
!= -1 ) {
85 gdk_gc_set_foreground(w_current
->gc
,
86 x_get_color(w_current
->override_color
));
88 gdk_draw_line(w_current
->window
, w_current
->gc
,
90 gdk_draw_line(w_current
->backingstore
, w_current
->gc
,
94 gdk_gc_set_foreground(w_current
->gc
,
95 x_get_color(o_current
->color
));
96 gdk_draw_line(w_current
->window
, w_current
->gc
,
98 gdk_draw_line(w_current
->backingstore
, w_current
->gc
,
103 /* temp debug only */
104 font
= gdk_fontset_load ("10x20");
105 tempstring
= g_strdup_printf("%s", o_current
->name
);
106 gdk_draw_text (w_current
->window
,
112 gdk_draw_text (w_current
->backingstore
,
118 gdk_font_unref(font
);
124 printf("drew net\n\n");
127 /* yes zero is right for the width -> use hardware lines */
128 if (w_current
->net_style
== THICK
) {
129 gdk_gc_set_line_attributes(w_current
->gc
, 0,
134 gdk_gc_set_line_attributes(w_current
->bus_gc
, 0,
140 if (o_current
->draw_grips
&& w_current
->draw_grips
== TRUE
) {
142 /* pb20011109 - modified to use the new o_line_[draw|erase]_grips() */
143 /* reuse the line functions */
144 if (!o_current
->selected
) {
145 /* object is no more selected, erase the grips */
146 o_current
->draw_grips
= FALSE
;
147 o_line_erase_grips(w_current
, o_current
);
149 /* object is selected, draw the grips */
150 o_line_draw_grips(w_current
, o_current
);
156 /*! \todo Finish function documentation!!!
158 * \par Function Description
161 void o_net_erase(TOPLEVEL
*w_current
, OBJECT
*o_current
)
163 w_current
->override_color
= w_current
->background_color
;
164 o_net_draw(w_current
, o_current
);
165 w_current
->override_color
= -1;
168 /*! \todo Finish function documentation!!!
170 * \par Function Description
173 void o_net_draw_xor(TOPLEVEL
*w_current
, int dx
, int dy
, OBJECT
*o_current
)
179 if (o_current
->line
== NULL
) {
183 if (o_current
->saved_color
!= -1) {
184 color
= o_current
->saved_color
;
186 color
= o_current
->color
;
189 gdk_gc_set_foreground(w_current
->outline_xor_gc
,
190 x_get_darkcolor(color
));
192 if (w_current
->net_style
== THICK
) {
193 size
= SCREENabs(w_current
, NET_WIDTH
);
194 gdk_gc_set_line_attributes(w_current
->outline_xor_gc
, size
+1,
200 WORLDtoSCREEN( w_current
, o_current
->line
->x
[0], o_current
->line
->y
[0], &sx
[0], &sy
[0] );
201 WORLDtoSCREEN( w_current
, o_current
->line
->x
[1], o_current
->line
->y
[1], &sx
[1], &sy
[1] );
203 gdk_draw_line(w_current
->window
, w_current
->outline_xor_gc
,
208 /* backing store ? not approriate here */
210 if (w_current
->net_style
== THICK
) {
211 gdk_gc_set_line_attributes(w_current
->outline_xor_gc
, 0,
218 /*! \todo Finish function documentation!!!
220 * \par Function Description
223 void o_net_draw_xor_single(TOPLEVEL
*w_current
, int dx
, int dy
, int whichone
,
227 int dx1
= -1, dx2
= -1, dy1
= -1,dy2
= -1;
230 if (o_current
->line
== NULL
) {
234 if (o_current
->saved_color
!= -1) {
235 color
= o_current
->saved_color
;
237 color
= o_current
->color
;
240 gdk_gc_set_foreground(w_current
->outline_xor_gc
,
241 x_get_darkcolor(color
));
243 #if 0 /* if I had this enabled, than xoring would leave a lot of mouse drops */
244 if (w_current
->net_style
== THICK
) {
245 size
= SCREENabs(w_current
, NET_WIDTH
);
246 gdk_gc_set_line_attributes(w_current
->outline_xor_gc
, size
+1,
258 } else if (whichone
== 1) {
264 fprintf(stderr
, _("Got an invalid which one in o_net_draw_xor_single\n"));
267 WORLDtoSCREEN( w_current
, o_current
->line
->x
[0], o_current
->line
->y
[0], &sx
[0], &sy
[0] );
268 WORLDtoSCREEN( w_current
, o_current
->line
->x
[1], o_current
->line
->y
[1], &sx
[1], &sy
[1] );
270 gdk_draw_line(w_current
->window
, w_current
->outline_xor_gc
,
271 sx
[0]+dx1
, sy
[0]+dy1
,
272 sx
[1]+dx2
, sy
[1]+dy2
);
274 /* backing store ? not approriate here */
276 #if 0 /* if I had this enabled, than xoring would leave a lot of mouse drops */
277 if (w_current
->net_style
== THICK
) {
278 gdk_gc_set_line_attributes(w_current
->outline_xor_gc
, 0,
286 /*! \todo Finish function documentation!!!
288 * \par Function Description
291 void o_net_start(TOPLEVEL
*w_current
, int x
, int y
)
295 /* initalize all parameters used when drawing the new net */
296 w_current
->last_x
= w_current
->start_x
= w_current
->second_x
=
298 w_current
->last_y
= w_current
->start_y
= w_current
->second_y
=
301 #if 0 /* not ready for prime time use, this is the snap any point #if 0 */
307 o_current
= o_CONN_search_closest_range(w_current
,
308 w_current
->page_current
->object_head
,
309 w_current
->start_x
, w_current
->start_y
,
310 &temp_x
, &temp_y
, 200, NULL
, NULL
);
313 w_current
->last_x
= w_current
->start_x
= temp_x
;
314 w_current
->last_y
= w_current
->start_y
= temp_y
;
316 w_current
->last_x
= w_current
->start_x
= fix_x(w_current
, x
);
317 w_current
->last_y
= w_current
->start_y
= fix_y(w_current
, y
);
321 #if 0 /* not ready for prime time use */
322 /* new net extenstion stuff */
323 o_current
= (OBJECT
*) w_current
->page_current
->selection_list
->data
;
324 if (o_current
!= NULL
&& w_current
->event_state
== STARTDRAWNET
) {
325 if (o_current
->type
== OBJ_NET
) {
326 if (o_current
->line
) {
328 real
= o_list_sear( /* ch */
329 w_current
->page_current
->object_head
,
333 fprintf(stderr
, _("selected a nonexistant object!\n"));
337 real
->line
->screen_x
[0],
338 real
->line
->screen_y
[0],
339 w_current
->start_x
, w_current
->start_y
);
342 real
->line
->screen_x
[1],
343 real
->line
->screen_y
[1],
344 w_current
->start_x
, w_current
->start_y
);
346 printf("%d %d\n", distance1
, distance2
);
348 if (distance1
< distance2
) {
349 w_current
->last_x
= w_current
->start_x
=
350 real
->line
->screen_x
[0];
351 w_current
->last_y
= w_current
->start_y
=
352 real
->line
->screen_y
[0];
354 w_current
->last_x
= w_current
->start_x
=
355 real
->line
->screen_x
[1];
356 w_current
->last_y
= w_current
->start_y
=
357 real
->line
->screen_y
[1];
360 } else if (o_current
->type
== OBJ_COMPLEX
||
361 o_current
->type
== OBJ_PLACEHOLDER
) {
362 real
= o_list_sear( /* ch */
363 w_current
->page_current
->object_head
,
367 fprintf(stderr
, _("selected a nonexistant object!\n"));
371 o_CONN_search_closest(w_current
, o_current
->complex,
372 w_current
->start_x
, w_current
->start_y
,
373 &temp_x
, &temp_y
, NULL
);
374 w_current
->last_x
= w_current
->start_x
= temp_x
;
375 w_current
->last_y
= w_current
->start_y
= temp_y
;
381 if (w_current
->net_style
== THICK
) {
382 size
= SCREENabs(w_current
, NET_WIDTH
);
383 gdk_gc_set_line_attributes(w_current
->xor_gc
, size
,
389 gdk_gc_set_foreground(w_current
->xor_gc
,
390 x_get_darkcolor(w_current
->select_color
) );
391 gdk_draw_line(w_current
->window
, w_current
->xor_gc
,
392 w_current
->start_x
, w_current
->start_y
,
393 w_current
->last_x
, w_current
->last_y
);
395 if (w_current
->net_style
== THICK
) {
396 gdk_gc_set_line_attributes(w_current
->xor_gc
, 0,
403 /*! \todo Finish function documentation!!!
405 * \par Function Description
408 int o_net_end(TOPLEVEL
*w_current
, int x
, int y
)
415 int primary_zero_length
, secondary_zero_length
;
416 int found_primary_connection
= FALSE
;
419 /*int temp_x, temp_y;*/
420 /* OBJECT *o_current;*/
421 GList
*other_objects
= NULL
;
422 OBJECT
*new_net
= NULL
;
424 if (w_current
->inside_action
== 0) {
425 o_redraw(w_current
, w_current
->page_current
->object_head
, TRUE
);
429 if (w_current
->override_net_color
== -1) {
430 color
= w_current
->net_color
;
432 color
= w_current
->override_net_color
;
435 size
= SCREENabs(w_current
, NET_WIDTH
);
437 if (w_current
->net_style
== THICK
) {
438 gdk_gc_set_line_attributes(w_current
->xor_gc
, size
,
444 gdk_gc_set_foreground(w_current
->xor_gc
,
445 x_get_darkcolor(w_current
->select_color
) );
447 /* Erase primary rubber net line */
448 gdk_draw_line(w_current
->window
, w_current
->xor_gc
,
449 w_current
->start_x
, w_current
->start_y
,
450 w_current
->last_x
, w_current
->last_y
);
452 /* Erase secondary rubber net line */
453 gdk_draw_line(w_current
->window
, w_current
->xor_gc
,
454 w_current
->last_x
, w_current
->last_y
,
455 w_current
->second_x
, w_current
->second_y
);
457 if (w_current
->net_style
== THICK
) {
458 gdk_gc_set_line_attributes(w_current
->xor_gc
, 0,
460 GDK_CAP_NOT_LAST
, GDK_JOIN_MITER
);
461 gdk_gc_set_line_attributes(w_current
->gc
, size
,
463 GDK_CAP_NOT_LAST
, GDK_JOIN_MITER
);
467 /* See if either of the nets are zero length. We'll only add */
468 /* the non-zero ones */
469 primary_zero_length
= (w_current
->start_x
== w_current
->last_x
) &&
470 (w_current
->start_y
== w_current
->last_y
);
472 secondary_zero_length
= (w_current
->last_x
== w_current
->second_x
) &&
473 (w_current
->last_y
== w_current
->second_y
);
475 /* If both nets are zero length... */
476 /* this ends the net drawing behavior we want this? hack */
477 if ( primary_zero_length
&& secondary_zero_length
) {
478 w_current
->start_x
= (-1);
479 w_current
->start_y
= (-1);
480 w_current
->last_x
= (-1);
481 w_current
->last_y
= (-1);
482 w_current
->second_x
= (-1);
483 w_current
->second_y
= (-1);
484 w_current
->inside_action
= 0;
485 i_set_state(w_current
, STARTDRAWNET
);
486 o_net_eraserubber(w_current
);
490 #if 0 /* not ready for prime time use */
491 /* second attempt at all snapping */
492 o_current
= o_CONN_search_closest_range(w_current
,
493 w_current
->page_current
->
494 object_head
, w_current
->last_x
,
495 w_current
->last_y
, &temp_x
,
496 &temp_y
, 200, NULL
, NULL
);
499 w_current
->last_x
= temp_x
;
500 w_current
->last_y
= temp_y
;
502 w_current
->last_x
= fix_x(w_current
, x
);
503 w_current
->last_y
= fix_y(w_current
, y
);
508 /* Primary net runs from (x1,y1)-(x2,y2) */
509 /* Secondary net from (x2,y2)-(x3,y3) */
510 SCREENtoWORLD(w_current
, w_current
->start_x
, w_current
->start_y
, &x1
, &y1
);
511 SCREENtoWORLD(w_current
, w_current
->last_x
, w_current
->last_y
, &x2
, &y2
);
512 SCREENtoWORLD(w_current
, w_current
->second_x
, w_current
->second_y
, &x3
, &y3
);
514 /* Snap points to closest grid location */
515 x1
= snap_grid(w_current
, x1
);
516 y1
= snap_grid(w_current
, y1
);
517 x2
= snap_grid(w_current
, x2
);
518 y2
= snap_grid(w_current
, y2
);
519 x3
= snap_grid(w_current
, x3
);
520 y3
= snap_grid(w_current
, y3
);
522 w_current
->save_x
= w_current
->second_x
;
523 w_current
->save_y
= w_current
->second_y
;
525 if (!primary_zero_length
) {
526 /* create primary net */
527 w_current
->page_current
->object_tail
=
528 new_net
= o_net_add(w_current
,
529 w_current
->page_current
->object_tail
,
530 OBJ_NET
, color
, x1
, y1
, x2
, y2
);
534 other_objects
= s_conn_return_others(other_objects
,
535 w_current
->page_current
->
538 if (o_net_add_busrippers(w_current
, new_net
, other_objects
)) {
539 g_list_free(other_objects
);
540 other_objects
= NULL
;
541 other_objects
= s_conn_return_others(other_objects
, new_net
);
545 printf("primary:\n");
546 s_conn_print(new_net
->conn_list
);
549 WORLDtoSCREEN( w_current
, new_net
->line
->x
[0], new_net
->line
->y
[0], &sx
[0], &sy
[0] );
550 WORLDtoSCREEN( w_current
, new_net
->line
->x
[1], new_net
->line
->y
[1], &sx
[1], &sy
[1] );
552 gdk_gc_set_foreground(w_current
->gc
, x_get_color(color
));
553 gdk_draw_line(w_current
->window
, w_current
->gc
,
556 gdk_draw_line(w_current
->backingstore
, w_current
->gc
,
560 if (w_current
->net_style
== THICK
) {
561 gdk_gc_set_line_attributes(w_current
->gc
, 0,
563 GDK_CAP_NOT_LAST
, GDK_JOIN_MITER
);
566 o_cue_undraw_list(w_current
, other_objects
);
567 o_cue_draw_list(w_current
, other_objects
);
568 o_cue_draw_single(w_current
, new_net
);
570 /* Go off and search for valid connection on this newly created net */
571 found_primary_connection
= s_conn_net_search(new_net
, 1,
573 if (found_primary_connection
)
575 /* if a net connection is found, reset start point of next net */
576 w_current
->save_x
= w_current
->last_x
;
577 w_current
->save_y
= w_current
->last_y
;
580 /* you don't want to consolidate nets which are drawn non-ortho */
581 if (w_current
->net_consolidate
== TRUE
&& !w_current
->CONTROLKEY
) {
582 o_net_consolidate_segments(w_current
, new_net
);
587 /* If the second net is not zero length, add it as well */
588 /* Also, a valid net connection from the primary net was not found */
589 if (!secondary_zero_length
&& !found_primary_connection
) {
591 /* Add secondary net */
592 w_current
->page_current
->object_tail
=
593 new_net
= o_net_add(w_current
,
594 w_current
->page_current
->object_tail
,
595 OBJ_NET
, color
, x2
, y2
, x3
, y3
);
599 other_objects
= s_conn_return_others(other_objects
,
600 w_current
->page_current
->
603 if (o_net_add_busrippers(w_current
, new_net
, other_objects
)) {
604 g_list_free(other_objects
);
605 other_objects
= NULL
;
606 other_objects
= s_conn_return_others(other_objects
, new_net
);
609 s_conn_print(new_net
->conn_list
);
612 WORLDtoSCREEN( w_current
, new_net
->line
->x
[0], new_net
->line
->y
[0], &sx
[0], &sy
[0] );
613 WORLDtoSCREEN( w_current
, new_net
->line
->x
[1], new_net
->line
->y
[1], &sx
[1], &sy
[1] );
615 gdk_gc_set_foreground(w_current
->gc
, x_get_color(color
));
616 gdk_draw_line(w_current
->window
, w_current
->gc
,
619 gdk_draw_line(w_current
->backingstore
, w_current
->gc
,
623 if (w_current
->net_style
== THICK
) {
624 gdk_gc_set_line_attributes(w_current
->gc
, 0,
626 GDK_CAP_NOT_LAST
, GDK_JOIN_MITER
);
629 o_cue_undraw_list(w_current
, other_objects
);
630 o_cue_draw_list(w_current
, other_objects
);
631 o_cue_draw_single(w_current
, new_net
);
633 /* you don't want to consolidate nets which are drawn non-ortho */
634 if (w_current
->net_consolidate
== TRUE
&& !w_current
->CONTROLKEY
) {
635 o_net_consolidate_segments(w_current
, new_net
);
640 g_list_free(other_objects
);
642 w_current
->page_current
->CHANGED
= 1;
643 w_current
->start_x
= w_current
->save_x
;
644 w_current
->start_y
= w_current
->save_y
;
645 o_undo_savestate(w_current
, UNDO_ALL
);
647 #if 0 /* a false attempt at ending the rubberbanding.. */
649 w_current
->inside_action
= 0;
650 i_set_state(w_current
, STARTDRAWNET
);
651 o_net_eraserubber(w_current
);
658 /*! \todo Finish function documentation!!!
660 * \par Function Description
663 void o_net_rubbernet(TOPLEVEL
*w_current
, int x
, int y
)
669 if (w_current
->inside_action
== 0) {
670 o_redraw(w_current
, w_current
->page_current
->object_head
, TRUE
);
674 if (w_current
->net_style
== THICK
) {
675 size
= SCREENabs(w_current
, NET_WIDTH
);
676 gdk_gc_set_line_attributes(w_current
->xor_gc
, size
,
678 GDK_CAP_NOT_LAST
, GDK_JOIN_MITER
);
680 gdk_gc_set_foreground(w_current
->xor_gc
,
681 x_get_darkcolor(w_current
->select_color
));
683 /* Orthognal mode enabled when Control Key is NOT pressed */
684 ortho
= !w_current
->CONTROLKEY
;
686 /* Erase primary line */
687 gdk_draw_line(w_current
->window
, w_current
->xor_gc
,
688 w_current
->start_x
, w_current
->start_y
,
689 w_current
->last_x
, w_current
->last_y
);
690 /* Erase secondary line*/
691 if ( w_current
->second_x
!= -1 && w_current
->second_y
!= -1 ) {
692 gdk_draw_line(w_current
->window
, w_current
->xor_gc
,
693 w_current
->last_x
, w_current
->last_y
,
694 w_current
->second_x
, w_current
->second_y
);
697 /* In orthogonal mode secondary line is the same as the first */
700 w_current
->second_x
= w_current
->last_x
;
701 w_current
->second_y
= w_current
->last_y
;
704 w_current
->last_x
= fix_x(w_current
, x
);
705 w_current
->last_y
= fix_y(w_current
, y
);
707 /* If you press the control key then you can draw non-ortho nets */
709 diff_x
= abs(w_current
->last_x
- w_current
->start_x
);
710 diff_y
= abs(w_current
->last_y
- w_current
->start_y
);
712 /* calculate the co-ordinates necessary to draw the lines*/
713 /* Pressing the shift key will cause the vertical and horizontal lines to switch places */
714 if ( !w_current
->SHIFTKEY
) {
715 w_current
->last_y
= w_current
->start_y
;
716 w_current
->second_x
= w_current
->last_x
;
717 w_current
->second_y
= fix_y(w_current
,y
);
719 w_current
->last_x
= w_current
->start_x
;
720 w_current
->second_x
= fix_x(w_current
,x
);
721 w_current
->second_y
= w_current
->last_y
;
725 gdk_gc_set_foreground(w_current
->xor_gc
,
726 x_get_darkcolor(w_current
->select_color
));
728 /* draw primary line */
729 gdk_draw_line(w_current
->window
, w_current
->xor_gc
,
730 w_current
->start_x
, w_current
->start_y
,
731 w_current
->last_x
, w_current
->last_y
);
733 /* Draw secondary line */
734 gdk_draw_line(w_current
->window
, w_current
->xor_gc
,
735 w_current
->last_x
, w_current
->last_y
,
736 w_current
->second_x
, w_current
->second_y
);
738 if (w_current
->net_style
== THICK
) {
739 gdk_gc_set_line_attributes(w_current
->xor_gc
, 0,
741 GDK_CAP_NOT_LAST
, GDK_JOIN_MITER
);
745 /*! \todo Finish function documentation!!!
747 * \par Function Description
750 * used in button cancel code in x_events.c
752 void o_net_eraserubber(TOPLEVEL
*w_current
)
756 if (w_current
->net_style
== THICK
) {
757 size
= SCREENabs(w_current
, NET_WIDTH
);
762 gdk_gc_set_line_attributes(w_current
->xor_gc
, size
,
764 GDK_CAP_NOT_LAST
, GDK_JOIN_MITER
);
768 gdk_gc_set_foreground(w_current
->gc
,
769 x_get_color(w_current
->background_color
));
772 /* Erase primary primary rubber net line */
773 gdk_draw_line(w_current
->window
, w_current
->xor_gc
, w_current
->start_x
,
774 w_current
->start_y
, w_current
->last_x
, w_current
->last_y
);
776 /* Erase secondary rubber net line */
777 gdk_draw_line(w_current
->window
, w_current
->xor_gc
,
778 w_current
->last_x
, w_current
->last_y
,
779 w_current
->second_x
, w_current
->second_y
);
781 if (w_current
->net_style
== THICK
) {
782 gdk_gc_set_line_attributes(w_current
->xor_gc
, 0,
784 GDK_CAP_NOT_LAST
, GDK_JOIN_MITER
);
788 /*! \todo Finish function documentation!!!
790 * \par Function Description
793 * used in x_event_expose() in x_events.c
795 void o_net_xorrubber(TOPLEVEL
*w_current
)
799 if (w_current
->net_style
== THICK
) {
801 size
= SCREENabs(w_current
, NET_WIDTH
);
806 gdk_gc_set_line_attributes(w_current
->gc
, size
,
812 gdk_gc_set_foreground(w_current
->gc
,
813 x_get_darkcolor(w_current
->select_color
) );
814 gdk_draw_line(w_current
->window
, w_current
->gc
,
815 w_current
->start_x
, w_current
->start_y
,
816 w_current
->last_x
, w_current
->last_y
);
817 gdk_draw_line(w_current
->window
, w_current
->gc
,
818 w_current
->second_x
, w_current
->second_y
,
819 w_current
->last_x
, w_current
->last_y
);
821 if (w_current
->net_style
== THICK
) {
822 gdk_gc_set_line_attributes(w_current
->gc
, 0,
829 /*! \todo Finish function documentation!!!
831 * \par Function Description
834 int o_net_add_busrippers(TOPLEVEL
*w_current
, OBJECT
*net_obj
,
835 GList
*other_objects
)
839 GList
*cl_current
= NULL
;
840 OBJECT
*bus_object
= NULL
;
841 CONN
*found_conn
= NULL
;
844 BUS_RIPPER rippers
[2];
845 int ripper_count
= 0;
849 double distance1
, distance2
;
851 int made_changes
= FALSE
;
852 const int ripper_size
= w_current
->bus_ripper_size
;
853 int complex_angle
= 0;
856 length
= o_line_length(net_obj
);
858 if (!other_objects
) {
862 if (length
<= ripper_size
) {
866 if (w_current
->override_net_color
== -1) {
867 color
= w_current
->net_color
;
869 color
= w_current
->override_net_color
;
873 /* check for a bus connection and draw rippers if so */
874 cl_current
= other_objects
;
875 while (cl_current
!= NULL
) {
877 bus_object
= (OBJECT
*) cl_current
->data
;
878 if (bus_object
&& bus_object
->type
== OBJ_BUS
) {
879 /* yes, using the net routine is okay */
880 int bus_orientation
= o_net_orientation(bus_object
);
881 int net_orientation
= o_net_orientation(net_obj
);
883 /* find the CONN structure which is associated with this object */
884 GList
*cl_current2
= net_obj
->conn_list
;
886 while (cl_current2
!= NULL
&& !done
) {
887 CONN
*tmp_conn
= (CONN
*) cl_current2
->data
;
889 if (tmp_conn
&& tmp_conn
->other_object
&&
890 tmp_conn
->other_object
== bus_object
) {
892 found_conn
= tmp_conn
;
896 cl_current2
= cl_current2
->next
;
903 otherone
= !found_conn
->whichone
;
905 /* now deal with the found connection */
906 if (bus_orientation
== HORIZONTAL
&& net_orientation
== VERTICAL
) {
907 /* printf("found horiz bus %s %d!\n", bus_object->name,
908 found_conn->whichone);*/
910 sign
= bus_object
->bus_ripper_direction
;
912 if (bus_object
->line
->x
[0] < bus_object
->line
->x
[1]) {
920 distance1
= abs(bus_object
->line
->x
[first
] -
921 net_obj
->line
->x
[found_conn
->whichone
]);
922 distance2
= abs(bus_object
->line
->x
[second
] -
923 net_obj
->line
->x
[found_conn
->whichone
]);
925 if (distance1
<= distance2
) {
930 bus_object
->bus_ripper_direction
= sign
;
932 /* printf("hor sign: %d\n", sign); */
934 if (net_obj
->line
->y
[otherone
] < bus_object
->line
->y
[0]) {
935 /* new net is below bus */
936 /*printf("below\n");*/
938 if (ripper_count
>= 2) {
939 /* try to exit gracefully */
940 fprintf(stderr
, _("Tried to add more than two bus rippers. Internal gschem error.\n"));
941 made_changes
= FALSE
;
945 if (w_current
->bus_ripper_rotation
== NON_SYMMETRIC
) {
957 net_obj
->line
->y
[found_conn
->whichone
] -= ripper_size
;
958 o_net_recalc(w_current
, net_obj
);
959 rippers
[ripper_count
].x
[0] =
960 net_obj
->line
->x
[found_conn
->whichone
];
961 rippers
[ripper_count
].y
[0] =
962 net_obj
->line
->y
[found_conn
->whichone
];
963 rippers
[ripper_count
].x
[1] =
964 net_obj
->line
->x
[found_conn
->whichone
] + sign
*ripper_size
;
965 rippers
[ripper_count
].y
[1] =
966 net_obj
->line
->y
[found_conn
->whichone
] + ripper_size
;
968 /* printf("done\n"); */
972 /* new net is above bus */
973 /* printf("above\n"); */
975 if (ripper_count
>= 2) {
976 /* try to exit gracefully */
977 fprintf(stderr
, _("Tried to add more than two bus rippers. Internal gschem error.\n"));
978 made_changes
= FALSE
;
982 if (w_current
->bus_ripper_rotation
== NON_SYMMETRIC
) {
994 net_obj
->line
->y
[found_conn
->whichone
] += ripper_size
;
995 o_net_recalc(w_current
, net_obj
);
996 rippers
[ripper_count
].x
[0] =
997 net_obj
->line
->x
[found_conn
->whichone
];
998 rippers
[ripper_count
].y
[0] =
999 net_obj
->line
->y
[found_conn
->whichone
];
1000 rippers
[ripper_count
].x
[1] =
1001 net_obj
->line
->x
[found_conn
->whichone
] + sign
*ripper_size
;
1002 rippers
[ripper_count
].y
[1] =
1003 net_obj
->line
->y
[found_conn
->whichone
] - ripper_size
;
1006 /* printf("done\n"); */
1011 } else if (bus_orientation
== VERTICAL
&&
1012 net_orientation
== HORIZONTAL
) {
1014 /* printf("found vert bus %s %d!\n", bus_object->name,
1015 found_conn->whichone); */
1017 sign
= bus_object
->bus_ripper_direction
;
1019 if (bus_object
->line
->y
[0] < bus_object
->line
->y
[1]) {
1027 distance1
= abs(bus_object
->line
->y
[first
] -
1028 net_obj
->line
->y
[found_conn
->whichone
]);
1029 distance2
= abs(bus_object
->line
->y
[second
] -
1030 net_obj
->line
->y
[found_conn
->whichone
]);
1032 if (distance1
<= distance2
) {
1037 bus_object
->bus_ripper_direction
= sign
;
1039 /* printf("ver sign: %d\n", sign); */
1042 if (net_obj
->line
->x
[otherone
] < bus_object
->line
->x
[0]) {
1043 /* new net is to the left of the bus */
1044 /* printf("left\n"); */
1046 if (ripper_count
>= 2) {
1047 /* try to exit gracefully */
1048 fprintf(stderr
, _("Tried to add more than two bus rippers. Internal gschem error.\n"));
1049 made_changes
= FALSE
;
1053 if (w_current
->bus_ripper_rotation
== NON_SYMMETRIC
) {
1058 complex_angle
= 270;
1062 complex_angle
= 270;
1065 net_obj
->line
->x
[found_conn
->whichone
] -= ripper_size
;
1066 o_net_recalc(w_current
, net_obj
);
1067 rippers
[ripper_count
].x
[0] =
1068 net_obj
->line
->x
[found_conn
->whichone
];
1069 rippers
[ripper_count
].y
[0] =
1070 net_obj
->line
->y
[found_conn
->whichone
];
1071 rippers
[ripper_count
].x
[1] =
1072 net_obj
->line
->x
[found_conn
->whichone
] + ripper_size
;
1073 rippers
[ripper_count
].y
[1] =
1074 net_obj
->line
->y
[found_conn
->whichone
] + sign
*ripper_size
;
1079 /* new net is to the right of the bus */
1080 /* printf("right\n"); */
1082 if (ripper_count
>= 2) {
1083 /* try to exit gracefully */
1084 fprintf(stderr
, _("Tried to add more than two bus rippers. Internal gschem error.\n"));
1085 made_changes
= FALSE
;
1089 if (w_current
->bus_ripper_rotation
== NON_SYMMETRIC
) {
1094 complex_angle
= 180;
1101 net_obj
->line
->x
[found_conn
->whichone
] += ripper_size
;
1102 o_net_recalc(w_current
, net_obj
);
1103 rippers
[ripper_count
].x
[0] =
1104 net_obj
->line
->x
[found_conn
->whichone
];
1105 rippers
[ripper_count
].y
[0] =
1106 net_obj
->line
->y
[found_conn
->whichone
];
1107 rippers
[ripper_count
].x
[1] =
1108 net_obj
->line
->x
[found_conn
->whichone
] - ripper_size
;
1109 rippers
[ripper_count
].y
[1] =
1110 net_obj
->line
->y
[found_conn
->whichone
] + sign
*ripper_size
;
1119 cl_current
= cl_current
->next
;
1123 s_conn_remove(w_current
, net_obj
);
1125 if (w_current
->bus_ripper_type
== COMP_BUS_RIPPER
) {
1126 const GSList
*clibs
= s_clib_search_basename (w_current
->bus_ripper_symname
);
1127 if (clibs
!= NULL
) {
1128 clib
= (gchar
*)clibs
->data
;
1132 for (i
= 0; i
< ripper_count
; i
++) {
1133 if (w_current
->bus_ripper_type
== NET_BUS_RIPPER
) {
1134 w_current
->page_current
->object_tail
=
1135 o_net_add(w_current
, w_current
->page_current
->object_tail
,
1137 rippers
[i
].x
[0], rippers
[i
].y
[0],
1138 rippers
[i
].x
[1], rippers
[i
].y
[1]);
1142 w_current
->page_current
->object_tail
=
1143 (OBJECT
*) o_complex_add(
1145 w_current
->page_current
->object_tail
,
1148 rippers
[i
].x
[0], rippers
[i
].y
[0],
1151 w_current
->bus_ripper_symname
, 1, TRUE
);
1153 o_complex_draw(w_current
,w_current
->page_current
->object_tail
);
1155 s_log_message(_("Could not find %s in any component-library\n"),
1156 w_current
->bus_ripper_symname
);
1161 s_conn_update_object(w_current
, net_obj
);