1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
25 #include <libgeda/libgeda.h>
27 #include "../include/globals.h"
28 #include "../include/prototype.h"
30 #ifdef HAVE_LIBDMALLOC
34 /*! \todo Finish function documentation!!!
36 * \par Function Description
39 void o_net_draw(TOPLEVEL
*w_current
, OBJECT
*o_current
)
42 int x1
, y1
, x2
, y2
; /* screen coords */
44 #if NET_DEBUG /* debug */
49 if (o_current
== NULL
) {
53 if (o_current
->line
== NULL
) {
57 /* reuse line's routine */
58 if ( (w_current
->DONT_REDRAW
== 1) ||
59 (!o_line_visible(w_current
, o_current
->line
, &x1
, &y1
, &x2
, &y2
)) ) {
64 printf("drawing net\n\n");
67 if (w_current
->net_style
== THICK
) {
68 size
= SCREENabs(w_current
, NET_WIDTH
);
73 gdk_gc_set_line_attributes(w_current
->gc
, size
,
78 gdk_gc_set_line_attributes(w_current
->bus_gc
, size
,
84 if (w_current
->override_color
!= -1 ) {
86 gdk_gc_set_foreground(w_current
->gc
,
87 x_get_color(w_current
->override_color
));
89 gdk_draw_line(w_current
->window
, w_current
->gc
,
91 gdk_draw_line(w_current
->backingstore
, w_current
->gc
,
95 gdk_gc_set_foreground(w_current
->gc
,
96 x_get_color(o_current
->color
));
97 gdk_draw_line(w_current
->window
, w_current
->gc
,
99 gdk_draw_line(w_current
->backingstore
, w_current
->gc
,
104 /* temp debug only */
105 font
= gdk_fontset_load ("10x20");
106 tempstring
= g_strdup_printf("%s", o_current
->name
);
107 gdk_draw_text (w_current
->window
,
113 gdk_draw_text (w_current
->backingstore
,
119 gdk_font_unref(font
);
125 printf("drew net\n\n");
128 /* yes zero is right for the width -> use hardware lines */
129 if (w_current
->net_style
== THICK
) {
130 gdk_gc_set_line_attributes(w_current
->gc
, 0,
135 gdk_gc_set_line_attributes(w_current
->bus_gc
, 0,
141 if (o_current
->draw_grips
&& w_current
->draw_grips
== TRUE
) {
143 /* pb20011109 - modified to use the new o_line_[draw|erase]_grips() */
144 /* reuse the line functions */
145 if (!o_current
->selected
) {
146 /* object is no more selected, erase the grips */
147 o_current
->draw_grips
= FALSE
;
148 o_line_erase_grips(w_current
, o_current
);
150 /* object is selected, draw the grips */
151 o_line_draw_grips(w_current
, o_current
);
157 /*! \todo Finish function documentation!!!
159 * \par Function Description
162 void o_net_erase(TOPLEVEL
*w_current
, OBJECT
*o_current
)
164 w_current
->override_color
= w_current
->background_color
;
165 o_net_draw(w_current
, o_current
);
166 w_current
->override_color
= -1;
169 /*! \todo Finish function documentation!!!
171 * \par Function Description
174 void o_net_draw_xor(TOPLEVEL
*w_current
, int dx
, int dy
, OBJECT
*o_current
)
180 if (o_current
->line
== NULL
) {
184 if (o_current
->saved_color
!= -1) {
185 color
= o_current
->saved_color
;
187 color
= o_current
->color
;
190 gdk_gc_set_foreground(w_current
->outline_xor_gc
,
191 x_get_darkcolor(color
));
193 if (w_current
->net_style
== THICK
) {
194 size
= SCREENabs(w_current
, NET_WIDTH
);
195 gdk_gc_set_line_attributes(w_current
->outline_xor_gc
, size
+1,
201 WORLDtoSCREEN( w_current
, o_current
->line
->x
[0], o_current
->line
->y
[0], &sx
[0], &sy
[0] );
202 WORLDtoSCREEN( w_current
, o_current
->line
->x
[1], o_current
->line
->y
[1], &sx
[1], &sy
[1] );
204 gdk_draw_line(w_current
->window
, w_current
->outline_xor_gc
,
209 /* backing store ? not approriate here */
211 if (w_current
->net_style
== THICK
) {
212 gdk_gc_set_line_attributes(w_current
->outline_xor_gc
, 0,
219 /*! \todo Finish function documentation!!!
221 * \par Function Description
224 void o_net_draw_xor_single(TOPLEVEL
*w_current
, int dx
, int dy
, int whichone
,
228 int dx1
= -1, dx2
= -1, dy1
= -1,dy2
= -1;
231 if (o_current
->line
== NULL
) {
235 if (o_current
->saved_color
!= -1) {
236 color
= o_current
->saved_color
;
238 color
= o_current
->color
;
241 gdk_gc_set_foreground(w_current
->outline_xor_gc
,
242 x_get_darkcolor(color
));
244 #if 0 /* if I had this enabled, than xoring would leave a lot of mouse drops */
245 if (w_current
->net_style
== THICK
) {
246 size
= SCREENabs(w_current
, NET_WIDTH
);
247 gdk_gc_set_line_attributes(w_current
->outline_xor_gc
, size
+1,
259 } else if (whichone
== 1) {
265 fprintf(stderr
, _("Got an invalid which one in o_net_draw_xor_single\n"));
268 WORLDtoSCREEN( w_current
, o_current
->line
->x
[0], o_current
->line
->y
[0], &sx
[0], &sy
[0] );
269 WORLDtoSCREEN( w_current
, o_current
->line
->x
[1], o_current
->line
->y
[1], &sx
[1], &sy
[1] );
271 gdk_draw_line(w_current
->window
, w_current
->outline_xor_gc
,
272 sx
[0]+dx1
, sy
[0]+dy1
,
273 sx
[1]+dx2
, sy
[1]+dy2
);
275 /* backing store ? not approriate here */
277 #if 0 /* if I had this enabled, than xoring would leave a lot of mouse drops */
278 if (w_current
->net_style
== THICK
) {
279 gdk_gc_set_line_attributes(w_current
->outline_xor_gc
, 0,
287 /*! \todo Finish function documentation!!!
289 * \par Function Description
292 void o_net_start(TOPLEVEL
*w_current
, int x
, int y
)
296 /* initalize all parameters used when drawing the new net */
297 w_current
->last_x
= w_current
->start_x
= w_current
->second_x
=
299 w_current
->last_y
= w_current
->start_y
= w_current
->second_y
=
302 #if 0 /* not ready for prime time use, this is the snap any point #if 0 */
308 o_current
= o_CONN_search_closest_range(w_current
,
309 w_current
->page_current
->object_head
,
310 w_current
->start_x
, w_current
->start_y
,
311 &temp_x
, &temp_y
, 200, NULL
, NULL
);
314 w_current
->last_x
= w_current
->start_x
= temp_x
;
315 w_current
->last_y
= w_current
->start_y
= temp_y
;
317 w_current
->last_x
= w_current
->start_x
= fix_x(w_current
, x
);
318 w_current
->last_y
= w_current
->start_y
= fix_y(w_current
, y
);
322 #if 0 /* not ready for prime time use */
323 /* new net extenstion stuff */
324 o_current
= (OBJECT
*) w_current
->page_current
->selection_list
->data
;
325 if (o_current
!= NULL
&& w_current
->event_state
== STARTDRAWNET
) {
326 if (o_current
->type
== OBJ_NET
) {
327 if (o_current
->line
) {
329 real
= o_list_sear( /* ch */
330 w_current
->page_current
->object_head
,
334 fprintf(stderr
, _("selected a nonexistant object!\n"));
338 real
->line
->screen_x
[0],
339 real
->line
->screen_y
[0],
340 w_current
->start_x
, w_current
->start_y
);
343 real
->line
->screen_x
[1],
344 real
->line
->screen_y
[1],
345 w_current
->start_x
, w_current
->start_y
);
347 printf("%d %d\n", distance1
, distance2
);
349 if (distance1
< distance2
) {
350 w_current
->last_x
= w_current
->start_x
=
351 real
->line
->screen_x
[0];
352 w_current
->last_y
= w_current
->start_y
=
353 real
->line
->screen_y
[0];
355 w_current
->last_x
= w_current
->start_x
=
356 real
->line
->screen_x
[1];
357 w_current
->last_y
= w_current
->start_y
=
358 real
->line
->screen_y
[1];
361 } else if (o_current
->type
== OBJ_COMPLEX
||
362 o_current
->type
== OBJ_PLACEHOLDER
) {
363 real
= o_list_sear( /* ch */
364 w_current
->page_current
->object_head
,
368 fprintf(stderr
, _("selected a nonexistant object!\n"));
372 o_CONN_search_closest(w_current
, o_current
->complex,
373 w_current
->start_x
, w_current
->start_y
,
374 &temp_x
, &temp_y
, NULL
);
375 w_current
->last_x
= w_current
->start_x
= temp_x
;
376 w_current
->last_y
= w_current
->start_y
= temp_y
;
382 if (w_current
->net_style
== THICK
) {
383 size
= SCREENabs(w_current
, NET_WIDTH
);
384 gdk_gc_set_line_attributes(w_current
->xor_gc
, size
,
390 gdk_gc_set_foreground(w_current
->xor_gc
,
391 x_get_darkcolor(w_current
->select_color
) );
392 gdk_draw_line(w_current
->window
, w_current
->xor_gc
,
393 w_current
->start_x
, w_current
->start_y
,
394 w_current
->last_x
, w_current
->last_y
);
396 if (w_current
->net_style
== THICK
) {
397 gdk_gc_set_line_attributes(w_current
->xor_gc
, 0,
404 /*! \todo Finish function documentation!!!
406 * \par Function Description
409 int o_net_end(TOPLEVEL
*w_current
, int x
, int y
)
416 int primary_zero_length
, secondary_zero_length
;
417 int found_primary_connection
= FALSE
;
420 /*int temp_x, temp_y;*/
421 /* OBJECT *o_current;*/
422 GList
*other_objects
= NULL
;
423 OBJECT
*new_net
= NULL
;
425 if (w_current
->inside_action
== 0) {
426 o_redraw(w_current
, w_current
->page_current
->object_head
, TRUE
);
430 if (w_current
->override_net_color
== -1) {
431 color
= w_current
->net_color
;
433 color
= w_current
->override_net_color
;
436 size
= SCREENabs(w_current
, NET_WIDTH
);
438 if (w_current
->net_style
== THICK
) {
439 gdk_gc_set_line_attributes(w_current
->xor_gc
, size
,
445 gdk_gc_set_foreground(w_current
->xor_gc
,
446 x_get_darkcolor(w_current
->select_color
) );
448 /* Erase primary rubber net line */
449 gdk_draw_line(w_current
->window
, w_current
->xor_gc
,
450 w_current
->start_x
, w_current
->start_y
,
451 w_current
->last_x
, w_current
->last_y
);
453 /* Erase secondary rubber net line */
454 gdk_draw_line(w_current
->window
, w_current
->xor_gc
,
455 w_current
->last_x
, w_current
->last_y
,
456 w_current
->second_x
, w_current
->second_y
);
458 if (w_current
->net_style
== THICK
) {
459 gdk_gc_set_line_attributes(w_current
->xor_gc
, 0,
461 GDK_CAP_NOT_LAST
, GDK_JOIN_MITER
);
462 gdk_gc_set_line_attributes(w_current
->gc
, size
,
464 GDK_CAP_NOT_LAST
, GDK_JOIN_MITER
);
468 /* See if either of the nets are zero length. We'll only add */
469 /* the non-zero ones */
470 primary_zero_length
= (w_current
->start_x
== w_current
->last_x
) &&
471 (w_current
->start_y
== w_current
->last_y
);
473 secondary_zero_length
= (w_current
->last_x
== w_current
->second_x
) &&
474 (w_current
->last_y
== w_current
->second_y
);
476 /* If both nets are zero length... */
477 /* this ends the net drawing behavior we want this? hack */
478 if ( primary_zero_length
&& secondary_zero_length
) {
479 w_current
->start_x
= (-1);
480 w_current
->start_y
= (-1);
481 w_current
->last_x
= (-1);
482 w_current
->last_y
= (-1);
483 w_current
->second_x
= (-1);
484 w_current
->second_y
= (-1);
485 w_current
->inside_action
= 0;
486 i_set_state(w_current
, STARTDRAWNET
);
487 o_net_eraserubber(w_current
);
491 #if 0 /* not ready for prime time use */
492 /* second attempt at all snapping */
493 o_current
= o_CONN_search_closest_range(w_current
,
494 w_current
->page_current
->
495 object_head
, w_current
->last_x
,
496 w_current
->last_y
, &temp_x
,
497 &temp_y
, 200, NULL
, NULL
);
500 w_current
->last_x
= temp_x
;
501 w_current
->last_y
= temp_y
;
503 w_current
->last_x
= fix_x(w_current
, x
);
504 w_current
->last_y
= fix_y(w_current
, y
);
509 /* Primary net runs from (x1,y1)-(x2,y2) */
510 /* Secondary net from (x2,y2)-(x3,y3) */
511 SCREENtoWORLD(w_current
, w_current
->start_x
, w_current
->start_y
, &x1
, &y1
);
512 SCREENtoWORLD(w_current
, w_current
->last_x
, w_current
->last_y
, &x2
, &y2
);
513 SCREENtoWORLD(w_current
, w_current
->second_x
, w_current
->second_y
, &x3
, &y3
);
515 /* Snap points to closest grid location */
516 x1
= snap_grid(w_current
, x1
);
517 y1
= snap_grid(w_current
, y1
);
518 x2
= snap_grid(w_current
, x2
);
519 y2
= snap_grid(w_current
, y2
);
520 x3
= snap_grid(w_current
, x3
);
521 y3
= snap_grid(w_current
, y3
);
523 w_current
->save_x
= w_current
->second_x
;
524 w_current
->save_y
= w_current
->second_y
;
526 if (!primary_zero_length
) {
527 /* create primary net */
528 w_current
->page_current
->object_tail
=
529 new_net
= o_net_add(w_current
,
530 w_current
->page_current
->object_tail
,
531 OBJ_NET
, color
, x1
, y1
, x2
, y2
);
535 other_objects
= s_conn_return_others(other_objects
,
536 w_current
->page_current
->
539 if (o_net_add_busrippers(w_current
, new_net
, other_objects
)) {
540 g_list_free(other_objects
);
541 other_objects
= NULL
;
542 other_objects
= s_conn_return_others(other_objects
, new_net
);
546 printf("primary:\n");
547 s_conn_print(new_net
->conn_list
);
550 WORLDtoSCREEN( w_current
, new_net
->line
->x
[0], new_net
->line
->y
[0], &sx
[0], &sy
[0] );
551 WORLDtoSCREEN( w_current
, new_net
->line
->x
[1], new_net
->line
->y
[1], &sx
[1], &sy
[1] );
553 gdk_gc_set_foreground(w_current
->gc
, x_get_color(color
));
554 gdk_draw_line(w_current
->window
, w_current
->gc
,
557 gdk_draw_line(w_current
->backingstore
, w_current
->gc
,
561 if (w_current
->net_style
== THICK
) {
562 gdk_gc_set_line_attributes(w_current
->gc
, 0,
564 GDK_CAP_NOT_LAST
, GDK_JOIN_MITER
);
567 o_cue_undraw_list(w_current
, other_objects
);
568 o_cue_draw_list(w_current
, other_objects
);
569 o_cue_draw_single(w_current
, new_net
);
571 /* Go off and search for valid connection on this newly created net */
572 found_primary_connection
= s_conn_net_search(new_net
, 1,
574 if (found_primary_connection
)
576 /* if a net connection is found, reset start point of next net */
577 w_current
->save_x
= w_current
->last_x
;
578 w_current
->save_y
= w_current
->last_y
;
581 /* you don't want to consolidate nets which are drawn non-ortho */
582 if (w_current
->net_consolidate
== TRUE
&& !w_current
->CONTROLKEY
) {
583 o_net_consolidate_segments(w_current
, new_net
);
588 /* If the second net is not zero length, add it as well */
589 /* Also, a valid net connection from the primary net was not found */
590 if (!secondary_zero_length
&& !found_primary_connection
) {
592 /* Add secondary net */
593 w_current
->page_current
->object_tail
=
594 new_net
= o_net_add(w_current
,
595 w_current
->page_current
->object_tail
,
596 OBJ_NET
, color
, x2
, y2
, x3
, y3
);
600 other_objects
= s_conn_return_others(other_objects
,
601 w_current
->page_current
->
604 if (o_net_add_busrippers(w_current
, new_net
, other_objects
)) {
605 g_list_free(other_objects
);
606 other_objects
= NULL
;
607 other_objects
= s_conn_return_others(other_objects
, new_net
);
610 s_conn_print(new_net
->conn_list
);
613 WORLDtoSCREEN( w_current
, new_net
->line
->x
[0], new_net
->line
->y
[0], &sx
[0], &sy
[0] );
614 WORLDtoSCREEN( w_current
, new_net
->line
->x
[1], new_net
->line
->y
[1], &sx
[1], &sy
[1] );
616 gdk_gc_set_foreground(w_current
->gc
, x_get_color(color
));
617 gdk_draw_line(w_current
->window
, w_current
->gc
,
620 gdk_draw_line(w_current
->backingstore
, w_current
->gc
,
624 if (w_current
->net_style
== THICK
) {
625 gdk_gc_set_line_attributes(w_current
->gc
, 0,
627 GDK_CAP_NOT_LAST
, GDK_JOIN_MITER
);
630 o_cue_undraw_list(w_current
, other_objects
);
631 o_cue_draw_list(w_current
, other_objects
);
632 o_cue_draw_single(w_current
, new_net
);
634 /* you don't want to consolidate nets which are drawn non-ortho */
635 if (w_current
->net_consolidate
== TRUE
&& !w_current
->CONTROLKEY
) {
636 o_net_consolidate_segments(w_current
, new_net
);
641 g_list_free(other_objects
);
643 w_current
->page_current
->CHANGED
= 1;
644 w_current
->start_x
= w_current
->save_x
;
645 w_current
->start_y
= w_current
->save_y
;
646 o_undo_savestate(w_current
, UNDO_ALL
);
648 #if 0 /* a false attempt at ending the rubberbanding.. */
650 w_current
->inside_action
= 0;
651 i_set_state(w_current
, STARTDRAWNET
);
652 o_net_eraserubber(w_current
);
659 /*! \todo Finish function documentation!!!
661 * \par Function Description
664 void o_net_rubbernet(TOPLEVEL
*w_current
, int x
, int y
)
670 if (w_current
->inside_action
== 0) {
671 o_redraw(w_current
, w_current
->page_current
->object_head
, TRUE
);
675 if (w_current
->net_style
== THICK
) {
676 size
= SCREENabs(w_current
, NET_WIDTH
);
677 gdk_gc_set_line_attributes(w_current
->xor_gc
, size
,
679 GDK_CAP_NOT_LAST
, GDK_JOIN_MITER
);
681 gdk_gc_set_foreground(w_current
->xor_gc
,
682 x_get_darkcolor(w_current
->select_color
));
684 /* Orthognal mode enabled when Control Key is NOT pressed */
685 ortho
= !w_current
->CONTROLKEY
;
687 /* Erase primary line */
688 gdk_draw_line(w_current
->window
, w_current
->xor_gc
,
689 w_current
->start_x
, w_current
->start_y
,
690 w_current
->last_x
, w_current
->last_y
);
691 /* Erase secondary line*/
692 if ( w_current
->second_x
!= -1 && w_current
->second_y
!= -1 ) {
693 gdk_draw_line(w_current
->window
, w_current
->xor_gc
,
694 w_current
->last_x
, w_current
->last_y
,
695 w_current
->second_x
, w_current
->second_y
);
698 /* In orthogonal mode secondary line is the same as the first */
701 w_current
->second_x
= w_current
->last_x
;
702 w_current
->second_y
= w_current
->last_y
;
705 w_current
->last_x
= fix_x(w_current
, x
);
706 w_current
->last_y
= fix_y(w_current
, y
);
708 /* If you press the control key then you can draw non-ortho nets */
710 diff_x
= abs(w_current
->last_x
- w_current
->start_x
);
711 diff_y
= abs(w_current
->last_y
- w_current
->start_y
);
713 /* calculate the co-ordinates necessary to draw the lines*/
714 /* Pressing the shift key will cause the vertical and horizontal lines to switch places */
715 if ( !w_current
->SHIFTKEY
) {
716 w_current
->last_y
= w_current
->start_y
;
717 w_current
->second_x
= w_current
->last_x
;
718 w_current
->second_y
= fix_y(w_current
,y
);
720 w_current
->last_x
= w_current
->start_x
;
721 w_current
->second_x
= fix_x(w_current
,x
);
722 w_current
->second_y
= w_current
->last_y
;
726 gdk_gc_set_foreground(w_current
->xor_gc
,
727 x_get_darkcolor(w_current
->select_color
));
729 /* draw primary line */
730 gdk_draw_line(w_current
->window
, w_current
->xor_gc
,
731 w_current
->start_x
, w_current
->start_y
,
732 w_current
->last_x
, w_current
->last_y
);
734 /* Draw secondary line */
735 gdk_draw_line(w_current
->window
, w_current
->xor_gc
,
736 w_current
->last_x
, w_current
->last_y
,
737 w_current
->second_x
, w_current
->second_y
);
739 if (w_current
->net_style
== THICK
) {
740 gdk_gc_set_line_attributes(w_current
->xor_gc
, 0,
742 GDK_CAP_NOT_LAST
, GDK_JOIN_MITER
);
746 /*! \todo Finish function documentation!!!
748 * \par Function Description
751 * used in button cancel code in x_events.c
753 void o_net_eraserubber(TOPLEVEL
*w_current
)
757 if (w_current
->net_style
== THICK
) {
758 size
= SCREENabs(w_current
, NET_WIDTH
);
763 gdk_gc_set_line_attributes(w_current
->xor_gc
, size
,
765 GDK_CAP_NOT_LAST
, GDK_JOIN_MITER
);
769 gdk_gc_set_foreground(w_current
->gc
,
770 x_get_color(w_current
->background_color
));
773 /* Erase primary primary rubber net line */
774 gdk_draw_line(w_current
->window
, w_current
->xor_gc
, w_current
->start_x
,
775 w_current
->start_y
, w_current
->last_x
, w_current
->last_y
);
777 /* Erase secondary rubber net line */
778 gdk_draw_line(w_current
->window
, w_current
->xor_gc
,
779 w_current
->last_x
, w_current
->last_y
,
780 w_current
->second_x
, w_current
->second_y
);
782 if (w_current
->net_style
== THICK
) {
783 gdk_gc_set_line_attributes(w_current
->xor_gc
, 0,
785 GDK_CAP_NOT_LAST
, GDK_JOIN_MITER
);
789 /*! \todo Finish function documentation!!!
791 * \par Function Description
794 * used in x_event_expose() in x_events.c
796 void o_net_xorrubber(TOPLEVEL
*w_current
)
800 if (w_current
->net_style
== THICK
) {
802 size
= SCREENabs(w_current
, NET_WIDTH
);
807 gdk_gc_set_line_attributes(w_current
->gc
, size
,
813 gdk_gc_set_foreground(w_current
->gc
,
814 x_get_darkcolor(w_current
->select_color
) );
815 gdk_draw_line(w_current
->window
, w_current
->gc
,
816 w_current
->start_x
, w_current
->start_y
,
817 w_current
->last_x
, w_current
->last_y
);
818 gdk_draw_line(w_current
->window
, w_current
->gc
,
819 w_current
->second_x
, w_current
->second_y
,
820 w_current
->last_x
, w_current
->last_y
);
822 if (w_current
->net_style
== THICK
) {
823 gdk_gc_set_line_attributes(w_current
->gc
, 0,
830 /*! \todo Finish function documentation!!!
832 * \par Function Description
835 int o_net_add_busrippers(TOPLEVEL
*w_current
, OBJECT
*net_obj
,
836 GList
*other_objects
)
840 GList
*cl_current
= NULL
;
841 OBJECT
*bus_object
= NULL
;
842 CONN
*found_conn
= NULL
;
845 BUS_RIPPER rippers
[2];
846 int ripper_count
= 0;
850 double distance1
, distance2
;
852 int made_changes
= FALSE
;
853 const int ripper_size
= w_current
->bus_ripper_size
;
854 int complex_angle
= 0;
855 const CLibSymbol
*rippersym
= NULL
;
857 length
= o_line_length(net_obj
);
859 if (!other_objects
) {
863 if (length
<= ripper_size
) {
867 if (w_current
->override_net_color
== -1) {
868 color
= w_current
->net_color
;
870 color
= w_current
->override_net_color
;
874 /* check for a bus connection and draw rippers if so */
875 cl_current
= other_objects
;
876 while (cl_current
!= NULL
) {
878 bus_object
= (OBJECT
*) cl_current
->data
;
879 if (bus_object
&& bus_object
->type
== OBJ_BUS
) {
880 /* yes, using the net routine is okay */
881 int bus_orientation
= o_net_orientation(bus_object
);
882 int net_orientation
= o_net_orientation(net_obj
);
884 /* find the CONN structure which is associated with this object */
885 GList
*cl_current2
= net_obj
->conn_list
;
887 while (cl_current2
!= NULL
&& !done
) {
888 CONN
*tmp_conn
= (CONN
*) cl_current2
->data
;
890 if (tmp_conn
&& tmp_conn
->other_object
&&
891 tmp_conn
->other_object
== bus_object
) {
893 found_conn
= tmp_conn
;
897 cl_current2
= cl_current2
->next
;
904 otherone
= !found_conn
->whichone
;
906 /* now deal with the found connection */
907 if (bus_orientation
== HORIZONTAL
&& net_orientation
== VERTICAL
) {
908 /* printf("found horiz bus %s %d!\n", bus_object->name,
909 found_conn->whichone);*/
911 sign
= bus_object
->bus_ripper_direction
;
913 if (bus_object
->line
->x
[0] < bus_object
->line
->x
[1]) {
921 distance1
= abs(bus_object
->line
->x
[first
] -
922 net_obj
->line
->x
[found_conn
->whichone
]);
923 distance2
= abs(bus_object
->line
->x
[second
] -
924 net_obj
->line
->x
[found_conn
->whichone
]);
926 if (distance1
<= distance2
) {
931 bus_object
->bus_ripper_direction
= sign
;
933 /* printf("hor sign: %d\n", sign); */
935 if (net_obj
->line
->y
[otherone
] < bus_object
->line
->y
[0]) {
936 /* new net is below bus */
937 /*printf("below\n");*/
939 if (ripper_count
>= 2) {
940 /* try to exit gracefully */
941 fprintf(stderr
, _("Tried to add more than two bus rippers. Internal gschem error.\n"));
942 made_changes
= FALSE
;
946 if (w_current
->bus_ripper_rotation
== NON_SYMMETRIC
) {
958 net_obj
->line
->y
[found_conn
->whichone
] -= ripper_size
;
959 o_net_recalc(w_current
, net_obj
);
960 rippers
[ripper_count
].x
[0] =
961 net_obj
->line
->x
[found_conn
->whichone
];
962 rippers
[ripper_count
].y
[0] =
963 net_obj
->line
->y
[found_conn
->whichone
];
964 rippers
[ripper_count
].x
[1] =
965 net_obj
->line
->x
[found_conn
->whichone
] + sign
*ripper_size
;
966 rippers
[ripper_count
].y
[1] =
967 net_obj
->line
->y
[found_conn
->whichone
] + ripper_size
;
969 /* printf("done\n"); */
973 /* new net is above bus */
974 /* printf("above\n"); */
976 if (ripper_count
>= 2) {
977 /* try to exit gracefully */
978 fprintf(stderr
, _("Tried to add more than two bus rippers. Internal gschem error.\n"));
979 made_changes
= FALSE
;
983 if (w_current
->bus_ripper_rotation
== NON_SYMMETRIC
) {
995 net_obj
->line
->y
[found_conn
->whichone
] += ripper_size
;
996 o_net_recalc(w_current
, net_obj
);
997 rippers
[ripper_count
].x
[0] =
998 net_obj
->line
->x
[found_conn
->whichone
];
999 rippers
[ripper_count
].y
[0] =
1000 net_obj
->line
->y
[found_conn
->whichone
];
1001 rippers
[ripper_count
].x
[1] =
1002 net_obj
->line
->x
[found_conn
->whichone
] + sign
*ripper_size
;
1003 rippers
[ripper_count
].y
[1] =
1004 net_obj
->line
->y
[found_conn
->whichone
] - ripper_size
;
1007 /* printf("done\n"); */
1012 } else if (bus_orientation
== VERTICAL
&&
1013 net_orientation
== HORIZONTAL
) {
1015 /* printf("found vert bus %s %d!\n", bus_object->name,
1016 found_conn->whichone); */
1018 sign
= bus_object
->bus_ripper_direction
;
1020 if (bus_object
->line
->y
[0] < bus_object
->line
->y
[1]) {
1028 distance1
= abs(bus_object
->line
->y
[first
] -
1029 net_obj
->line
->y
[found_conn
->whichone
]);
1030 distance2
= abs(bus_object
->line
->y
[second
] -
1031 net_obj
->line
->y
[found_conn
->whichone
]);
1033 if (distance1
<= distance2
) {
1038 bus_object
->bus_ripper_direction
= sign
;
1040 /* printf("ver sign: %d\n", sign); */
1043 if (net_obj
->line
->x
[otherone
] < bus_object
->line
->x
[0]) {
1044 /* new net is to the left of the bus */
1045 /* printf("left\n"); */
1047 if (ripper_count
>= 2) {
1048 /* try to exit gracefully */
1049 fprintf(stderr
, _("Tried to add more than two bus rippers. Internal gschem error.\n"));
1050 made_changes
= FALSE
;
1054 if (w_current
->bus_ripper_rotation
== NON_SYMMETRIC
) {
1059 complex_angle
= 270;
1063 complex_angle
= 270;
1066 net_obj
->line
->x
[found_conn
->whichone
] -= ripper_size
;
1067 o_net_recalc(w_current
, net_obj
);
1068 rippers
[ripper_count
].x
[0] =
1069 net_obj
->line
->x
[found_conn
->whichone
];
1070 rippers
[ripper_count
].y
[0] =
1071 net_obj
->line
->y
[found_conn
->whichone
];
1072 rippers
[ripper_count
].x
[1] =
1073 net_obj
->line
->x
[found_conn
->whichone
] + ripper_size
;
1074 rippers
[ripper_count
].y
[1] =
1075 net_obj
->line
->y
[found_conn
->whichone
] + sign
*ripper_size
;
1080 /* new net is to the right of the bus */
1081 /* printf("right\n"); */
1083 if (ripper_count
>= 2) {
1084 /* try to exit gracefully */
1085 fprintf(stderr
, _("Tried to add more than two bus rippers. Internal gschem error.\n"));
1086 made_changes
= FALSE
;
1090 if (w_current
->bus_ripper_rotation
== NON_SYMMETRIC
) {
1095 complex_angle
= 180;
1102 net_obj
->line
->x
[found_conn
->whichone
] += ripper_size
;
1103 o_net_recalc(w_current
, net_obj
);
1104 rippers
[ripper_count
].x
[0] =
1105 net_obj
->line
->x
[found_conn
->whichone
];
1106 rippers
[ripper_count
].y
[0] =
1107 net_obj
->line
->y
[found_conn
->whichone
];
1108 rippers
[ripper_count
].x
[1] =
1109 net_obj
->line
->x
[found_conn
->whichone
] - ripper_size
;
1110 rippers
[ripper_count
].y
[1] =
1111 net_obj
->line
->y
[found_conn
->whichone
] + sign
*ripper_size
;
1120 cl_current
= cl_current
->next
;
1124 s_conn_remove(w_current
, net_obj
);
1126 if (w_current
->bus_ripper_type
== COMP_BUS_RIPPER
) {
1128 s_clib_search (w_current
->bus_ripper_symname
, CLIB_EXACT
);
1129 if (symlist
!= NULL
) {
1130 rippersym
= (CLibSymbol
*) symlist
->data
;
1132 g_list_free (symlist
);
1135 for (i
= 0; i
< ripper_count
; i
++) {
1136 if (w_current
->bus_ripper_type
== NET_BUS_RIPPER
) {
1137 w_current
->page_current
->object_tail
=
1138 o_net_add(w_current
, w_current
->page_current
->object_tail
,
1140 rippers
[i
].x
[0], rippers
[i
].y
[0],
1141 rippers
[i
].x
[1], rippers
[i
].y
[1]);
1144 if (rippersym
!= NULL
) {
1145 w_current
->page_current
->object_tail
=
1146 (OBJECT
*) o_complex_add(
1148 w_current
->page_current
->object_tail
,
1151 rippers
[i
].x
[0], rippers
[i
].y
[0],
1154 w_current
->bus_ripper_symname
, 1, TRUE
);
1156 o_complex_draw(w_current
,w_current
->page_current
->object_tail
);
1158 s_log_message(_("Bus ripper symbol [%s] was not found in any component library\n"),
1159 w_current
->bus_ripper_symname
);
1164 s_conn_update_object(w_current
, net_obj
);