Updated copyright text/header in most source files.
[geda-gaf.git] / gschem / src / o_net.c
blob96a7f231c5aaaa88b07b2f4b9ba97bf5e7f3989a
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
20 #include <config.h>
22 #include <stdio.h>
23 #include <math.h>
25 #include <libgeda/libgeda.h>
27 #include "../include/globals.h"
28 #include "../include/prototype.h"
30 #ifdef HAVE_LIBDMALLOC
31 #include <dmalloc.h>
32 #endif
34 /*! \todo Finish function documentation!!!
35 * \brief
36 * \par Function Description
39 void o_net_draw(TOPLEVEL *w_current, OBJECT *o_current)
41 int size;
42 int x1, y1, x2, y2; /* screen coords */
44 #if NET_DEBUG /* debug */
45 char *tempstring;
46 GdkFont *font;
47 #endif
49 if (o_current == NULL) {
50 return;
53 if (o_current->line == NULL) {
54 return;
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)) ) {
60 return;
63 #if DEBUG
64 printf("drawing net\n\n");
65 #endif
67 if (w_current->net_style == THICK ) {
68 size = SCREENabs(w_current, NET_WIDTH);
70 if (size < 0)
71 size=0;
73 gdk_gc_set_line_attributes(w_current->gc, size,
74 GDK_LINE_SOLID,
75 GDK_CAP_BUTT,
76 GDK_JOIN_MITER);
78 gdk_gc_set_line_attributes(w_current->bus_gc, size,
79 GDK_LINE_SOLID,
80 GDK_CAP_BUTT,
81 GDK_JOIN_MITER);
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,
90 x1, y1, x2, y2);
91 gdk_draw_line(w_current->backingstore, w_current->gc,
92 x1, y1, x2, y2);
93 } else {
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,
98 x1, y1, x2, y2);
99 gdk_draw_line(w_current->backingstore, w_current->gc,
100 x1, y1, x2, y2);
103 #if NET_DEBUG
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,
108 font,
109 w_current->gc,
110 x1+20, y1+20,
111 tempstring,
112 strlen(tempstring));
113 gdk_draw_text (w_current->backingstore,
114 font,
115 w_current->gc,
116 x1+20, y1+20,
117 tempstring,
118 strlen(tempstring));
119 gdk_font_unref(font);
120 g_free(tempstring);
121 #endif
124 #if DEBUG
125 printf("drew net\n\n");
126 #endif
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,
131 GDK_LINE_SOLID,
132 GDK_CAP_NOT_LAST,
133 GDK_JOIN_MITER);
135 gdk_gc_set_line_attributes(w_current->bus_gc, 0,
136 GDK_LINE_SOLID,
137 GDK_CAP_NOT_LAST,
138 GDK_JOIN_MITER);
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);
149 } else {
150 /* object is selected, draw the grips */
151 o_line_draw_grips(w_current, o_current);
157 /*! \todo Finish function documentation!!!
158 * \brief
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!!!
170 * \brief
171 * \par Function Description
174 void o_net_draw_xor(TOPLEVEL *w_current, int dx, int dy, OBJECT *o_current)
176 int size;
177 int color;
178 int sx[2], sy[2];
180 if (o_current->line == NULL) {
181 return;
184 if (o_current->saved_color != -1) {
185 color = o_current->saved_color;
186 } else {
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,
196 GDK_LINE_SOLID,
197 GDK_CAP_NOT_LAST,
198 GDK_JOIN_MITER);
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,
205 sx[0]+dx, sy[0]+dy,
206 sx[1]+dx, sy[1]+dy);
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,
213 GDK_LINE_SOLID,
214 GDK_CAP_NOT_LAST,
215 GDK_JOIN_MITER);
219 /*! \todo Finish function documentation!!!
220 * \brief
221 * \par Function Description
224 void o_net_draw_xor_single(TOPLEVEL *w_current, int dx, int dy, int whichone,
225 OBJECT *o_current)
227 int color;
228 int dx1 = -1, dx2 = -1, dy1 = -1,dy2 = -1;
229 int sx[2], sy[2];
231 if (o_current->line == NULL) {
232 return;
235 if (o_current->saved_color != -1) {
236 color = o_current->saved_color;
237 } else {
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,
248 GDK_LINE_SOLID,
249 GDK_CAP_NOT_LAST,
250 GDK_JOIN_MITER);
252 #endif
254 if (whichone == 0) {
255 dx1 = dx;
256 dy1 = dy;
257 dx2 = 0;
258 dy2 = 0;
259 } else if (whichone == 1) {
260 dx2 = dx;
261 dy2 = dy;
262 dx1 = 0;
263 dy1 = 0;
264 } else {
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,
280 GDK_LINE_SOLID,
281 GDK_CAP_NOT_LAST,
282 GDK_JOIN_MITER);
284 #endif
287 /*! \todo Finish function documentation!!!
288 * \brief
289 * \par Function Description
292 void o_net_start(TOPLEVEL *w_current, int x, int y)
294 int size;
296 /* initalize all parameters used when drawing the new net */
297 w_current->last_x = w_current->start_x = w_current->second_x =
298 fix_x(w_current, x);
299 w_current->last_y = w_current->start_y = w_current->second_y =
300 fix_y(w_current, y);
302 #if 0 /* not ready for prime time use, this is the snap any point #if 0 */
303 int distance1;
304 int distance2;
305 OBJECT *real;
306 OBJECT *o_current;
307 int temp_x, temp_y;
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);
313 if (o_current) {
314 w_current->last_x = w_current->start_x = temp_x;
315 w_current->last_y = w_current->start_y = temp_y;
316 } else {
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);
320 #endif
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,
331 o_current);
333 if (!real) {
334 fprintf(stderr, _("selected a nonexistant object!\n"));
335 exit(-1);
337 distance1 = dist(
338 real->line->screen_x[0],
339 real->line->screen_y[0],
340 w_current->start_x, w_current->start_y);
342 distance2 = dist(
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];
354 } else {
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,
365 o_current);
367 if (!real) {
368 fprintf(stderr, _("selected a nonexistant object!\n"));
369 exit(-1);
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;
380 #endif
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,
385 GDK_LINE_SOLID,
386 GDK_CAP_NOT_LAST,
387 GDK_JOIN_MITER);
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,
398 GDK_LINE_SOLID,
399 GDK_CAP_NOT_LAST,
400 GDK_JOIN_MITER);
404 /*! \todo Finish function documentation!!!
405 * \brief
406 * \par Function Description
409 int o_net_end(TOPLEVEL *w_current, int x, int y)
411 int x1, y1;
412 int x2, y2;
413 int x3, y3;
414 int color;
415 int size;
416 int primary_zero_length, secondary_zero_length;
417 int found_primary_connection = FALSE;
418 int sx[2], sy[2];
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);
427 return(FALSE);
430 if (w_current->override_net_color == -1) {
431 color = w_current->net_color;
432 } else {
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,
440 GDK_LINE_SOLID,
441 GDK_CAP_NOT_LAST,
442 GDK_JOIN_MITER);
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,
460 GDK_LINE_SOLID,
461 GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
462 gdk_gc_set_line_attributes(w_current->gc, size,
463 GDK_LINE_SOLID,
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);
489 return (FALSE);
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);
499 if (o_current) {
500 w_current->last_x = temp_x;
501 w_current->last_y = temp_y;
502 } else {
503 w_current->last_x = fix_x(w_current, x);
504 w_current->last_y = fix_y(w_current, y);
506 #endif
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);
533 /* conn stuff */
534 /* LEAK CHECK 1 */
535 other_objects = s_conn_return_others(other_objects,
536 w_current->page_current->
537 object_tail);
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);
545 #if DEBUG
546 printf("primary:\n");
547 s_conn_print(new_net->conn_list);
548 #endif
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,
555 sx[0], sy[0],
556 sx[1], sy[1]);
557 gdk_draw_line(w_current->backingstore, w_current->gc,
558 sx[0], sy[0],
559 sx[1], sy[1]);
561 if (w_current->net_style == THICK) {
562 gdk_gc_set_line_attributes(w_current->gc, 0,
563 GDK_LINE_SOLID,
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,
573 new_net->conn_list);
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);
598 /* conn stuff */
599 /* LEAK CHECK 2 */
600 other_objects = s_conn_return_others(other_objects,
601 w_current->page_current->
602 object_tail);
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);
609 #if DEBUG
610 s_conn_print(new_net->conn_list);
611 #endif
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,
618 sx[0], sy[0],
619 sx[1], sy[1]);
620 gdk_draw_line(w_current->backingstore, w_current->gc,
621 sx[0], sy[0],
622 sx[1], sy[1]);
624 if (w_current->net_style == THICK) {
625 gdk_gc_set_line_attributes(w_current->gc, 0,
626 GDK_LINE_SOLID,
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);
640 /* LEAK CHECK 3 */
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.. */
649 if (conn_count) {
650 w_current->inside_action = 0;
651 i_set_state(w_current, STARTDRAWNET);
652 o_net_eraserubber(w_current);
654 #endif
656 return (TRUE);
659 /*! \todo Finish function documentation!!!
660 * \brief
661 * \par Function Description
664 void o_net_rubbernet(TOPLEVEL *w_current, int x, int y)
666 int diff_x, diff_y;
667 int size;
668 int ortho;
670 if (w_current->inside_action == 0) {
671 o_redraw(w_current, w_current->page_current->object_head, TRUE);
672 return;
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,
678 GDK_LINE_SOLID,
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 */
699 if (!ortho)
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 */
709 if (ortho) {
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);
719 } else {
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,
741 GDK_LINE_SOLID,
742 GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
746 /*! \todo Finish function documentation!!!
747 * \brief
748 * \par Function Description
750 * \note
751 * used in button cancel code in x_events.c
753 void o_net_eraserubber(TOPLEVEL *w_current)
755 int size;
757 if (w_current->net_style == THICK) {
758 size = SCREENabs(w_current, NET_WIDTH);
760 if (size < 0)
761 size = 0;
763 gdk_gc_set_line_attributes(w_current->xor_gc, size,
764 GDK_LINE_SOLID,
765 GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
768 #if 0
769 gdk_gc_set_foreground(w_current->gc,
770 x_get_color(w_current->background_color));
771 #endif
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,
784 GDK_LINE_SOLID,
785 GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
789 /*! \todo Finish function documentation!!!
790 * \brief
791 * \par Function Description
793 * \note
794 * used in x_event_expose() in x_events.c
796 void o_net_xorrubber(TOPLEVEL *w_current)
798 int size;
800 if (w_current->net_style == THICK ) {
802 size = SCREENabs(w_current, NET_WIDTH);
804 if (size < 0)
805 size=0;
807 gdk_gc_set_line_attributes(w_current->gc, size,
808 GDK_LINE_SOLID,
809 GDK_CAP_NOT_LAST,
810 GDK_JOIN_MITER);
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,
824 GDK_LINE_SOLID,
825 GDK_CAP_NOT_LAST,
826 GDK_JOIN_MITER);
830 /*! \todo Finish function documentation!!!
831 * \brief
832 * \par Function Description
835 int o_net_add_busrippers(TOPLEVEL *w_current, OBJECT *net_obj,
836 GList *other_objects)
839 int color;
840 GList *cl_current = NULL;
841 OBJECT *bus_object = NULL;
842 CONN *found_conn = NULL;
843 int done;
844 int otherone;
845 BUS_RIPPER rippers[2];
846 int ripper_count = 0;
847 int i;
848 double length;
849 int sign;
850 double distance1, distance2;
851 int first, second;
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) {
860 return(FALSE);
863 if (length <= ripper_size) {
864 return(FALSE);
867 if (w_current->override_net_color == -1) {
868 color = w_current->net_color;
869 } else {
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;
886 done = FALSE;
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;
894 done = TRUE;
897 cl_current2 = cl_current2->next;
900 if (!found_conn) {
901 return(FALSE);
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;
912 if (!sign) {
913 if (bus_object->line->x[0] < bus_object->line->x[1]) {
914 first = 0;
915 second = 1;
916 } else {
917 first = 1;
918 second = 0;
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) {
927 sign = 1;
928 } else {
929 sign = -1;
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;
943 break;
946 if (w_current->bus_ripper_rotation == NON_SYMMETRIC) {
947 /* non-symmetric */
948 if (sign == 1) {
949 complex_angle = 0;
950 } else {
951 complex_angle = 90;
953 } else {
954 /* symmetric */
955 complex_angle = 0;
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;
968 ripper_count++;
969 /* printf("done\n"); */
970 made_changes++;
972 } else {
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;
980 break;
983 if (w_current->bus_ripper_rotation == NON_SYMMETRIC) {
984 /* non-symmetric */
985 if (sign == 1) {
986 complex_angle = 270;
987 } else {
988 complex_angle = 180;
990 } else {
991 /* symmetric */
992 complex_angle = 180;
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;
1005 ripper_count++;
1007 /* printf("done\n"); */
1008 made_changes++;
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;
1019 if (!sign) {
1020 if (bus_object->line->y[0] < bus_object->line->y[1]) {
1021 first = 0;
1022 second = 1;
1023 } else {
1024 first = 1;
1025 second = 0;
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) {
1034 sign = 1;
1035 } else {
1036 sign = -1;
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;
1051 break;
1054 if (w_current->bus_ripper_rotation == NON_SYMMETRIC) {
1055 /* non-symmetric */
1056 if (sign == 1) {
1057 complex_angle = 0;
1058 } else {
1059 complex_angle = 270;
1061 } else {
1062 /* symmetric */
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;
1076 ripper_count++;
1078 made_changes++;
1079 } else {
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;
1087 break;
1090 if (w_current->bus_ripper_rotation == NON_SYMMETRIC) {
1091 /* non-symmetric */
1092 if (sign == 1) {
1093 complex_angle = 90;
1094 } else {
1095 complex_angle = 180;
1097 } else {
1098 /* symmetric */
1099 complex_angle = 90;
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;
1112 ripper_count++;
1114 made_changes++;
1120 cl_current = cl_current->next;
1123 if (made_changes) {
1124 s_conn_remove(w_current, net_obj);
1126 if (w_current->bus_ripper_type == COMP_BUS_RIPPER) {
1127 GList *symlist =
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,
1139 OBJ_NET, color,
1140 rippers[i].x[0], rippers[i].y[0],
1141 rippers[i].x[1], rippers[i].y[1]);
1142 } else {
1144 if (rippersym != NULL) {
1145 w_current->page_current->object_tail =
1146 (OBJECT *) o_complex_add(
1147 w_current,
1148 w_current->page_current->object_tail,
1149 NULL,
1150 OBJ_COMPLEX, WHITE,
1151 rippers[i].x[0], rippers[i].y[0],
1152 complex_angle, 0,
1153 rippersym,
1154 w_current->bus_ripper_symname, 1, TRUE);
1156 o_complex_draw(w_current,w_current->page_current->object_tail);
1157 } else {
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);
1165 return(TRUE);
1168 return(FALSE);