Cleaned up and consolidated code which creates new pages.
[geda-gaf.git] / gschem / src / o_net.c
blob23c137098bb950605f34b157956a5ec4283765da
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
19 #include <config.h>
21 #include <stdio.h>
22 #include <math.h>
24 #include <libgeda/libgeda.h>
26 #include "../include/globals.h"
27 #include "../include/prototype.h"
29 #ifdef HAVE_LIBDMALLOC
30 #include <dmalloc.h>
31 #endif
33 /*! \todo Finish function documentation!!!
34 * \brief
35 * \par Function Description
38 void o_net_draw(TOPLEVEL *w_current, OBJECT *o_current)
40 int size;
41 int x1, y1, x2, y2; /* screen coords */
43 #if NET_DEBUG /* debug */
44 char *tempstring;
45 GdkFont *font;
46 #endif
48 if (o_current == NULL) {
49 return;
52 if (o_current->line == NULL) {
53 return;
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)) ) {
59 return;
62 #if DEBUG
63 printf("drawing net\n\n");
64 #endif
66 if (w_current->net_style == THICK ) {
67 size = SCREENabs(w_current, NET_WIDTH);
69 if (size < 0)
70 size=0;
72 gdk_gc_set_line_attributes(w_current->gc, size,
73 GDK_LINE_SOLID,
74 GDK_CAP_BUTT,
75 GDK_JOIN_MITER);
77 gdk_gc_set_line_attributes(w_current->bus_gc, size,
78 GDK_LINE_SOLID,
79 GDK_CAP_BUTT,
80 GDK_JOIN_MITER);
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,
89 x1, y1, x2, y2);
90 gdk_draw_line(w_current->backingstore, w_current->gc,
91 x1, y1, x2, y2);
92 } else {
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,
97 x1, y1, x2, y2);
98 gdk_draw_line(w_current->backingstore, w_current->gc,
99 x1, y1, x2, y2);
102 #if NET_DEBUG
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,
107 font,
108 w_current->gc,
109 x1+20, y1+20,
110 tempstring,
111 strlen(tempstring));
112 gdk_draw_text (w_current->backingstore,
113 font,
114 w_current->gc,
115 x1+20, y1+20,
116 tempstring,
117 strlen(tempstring));
118 gdk_font_unref(font);
119 g_free(tempstring);
120 #endif
123 #if DEBUG
124 printf("drew net\n\n");
125 #endif
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,
130 GDK_LINE_SOLID,
131 GDK_CAP_NOT_LAST,
132 GDK_JOIN_MITER);
134 gdk_gc_set_line_attributes(w_current->bus_gc, 0,
135 GDK_LINE_SOLID,
136 GDK_CAP_NOT_LAST,
137 GDK_JOIN_MITER);
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);
148 } else {
149 /* object is selected, draw the grips */
150 o_line_draw_grips(w_current, o_current);
156 /*! \todo Finish function documentation!!!
157 * \brief
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!!!
169 * \brief
170 * \par Function Description
173 void o_net_draw_xor(TOPLEVEL *w_current, int dx, int dy, OBJECT *o_current)
175 int size;
176 int color;
177 int sx[2], sy[2];
179 if (o_current->line == NULL) {
180 return;
183 if (o_current->saved_color != -1) {
184 color = o_current->saved_color;
185 } else {
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,
195 GDK_LINE_SOLID,
196 GDK_CAP_NOT_LAST,
197 GDK_JOIN_MITER);
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,
204 sx[0]+dx, sy[0]+dy,
205 sx[1]+dx, sy[1]+dy);
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,
212 GDK_LINE_SOLID,
213 GDK_CAP_NOT_LAST,
214 GDK_JOIN_MITER);
218 /*! \todo Finish function documentation!!!
219 * \brief
220 * \par Function Description
223 void o_net_draw_xor_single(TOPLEVEL *w_current, int dx, int dy, int whichone,
224 OBJECT *o_current)
226 int color;
227 int dx1 = -1, dx2 = -1, dy1 = -1,dy2 = -1;
228 int sx[2], sy[2];
230 if (o_current->line == NULL) {
231 return;
234 if (o_current->saved_color != -1) {
235 color = o_current->saved_color;
236 } else {
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,
247 GDK_LINE_SOLID,
248 GDK_CAP_NOT_LAST,
249 GDK_JOIN_MITER);
251 #endif
253 if (whichone == 0) {
254 dx1 = dx;
255 dy1 = dy;
256 dx2 = 0;
257 dy2 = 0;
258 } else if (whichone == 1) {
259 dx2 = dx;
260 dy2 = dy;
261 dx1 = 0;
262 dy1 = 0;
263 } else {
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,
279 GDK_LINE_SOLID,
280 GDK_CAP_NOT_LAST,
281 GDK_JOIN_MITER);
283 #endif
286 /*! \todo Finish function documentation!!!
287 * \brief
288 * \par Function Description
291 void o_net_start(TOPLEVEL *w_current, int x, int y)
293 int size;
295 /* initalize all parameters used when drawing the new net */
296 w_current->last_x = w_current->start_x = w_current->second_x =
297 fix_x(w_current, x);
298 w_current->last_y = w_current->start_y = w_current->second_y =
299 fix_y(w_current, y);
301 #if 0 /* not ready for prime time use, this is the snap any point #if 0 */
302 int distance1;
303 int distance2;
304 OBJECT *real;
305 OBJECT *o_current;
306 int temp_x, temp_y;
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);
312 if (o_current) {
313 w_current->last_x = w_current->start_x = temp_x;
314 w_current->last_y = w_current->start_y = temp_y;
315 } else {
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);
319 #endif
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,
330 o_current);
332 if (!real) {
333 fprintf(stderr, _("selected a nonexistant object!\n"));
334 exit(-1);
336 distance1 = dist(
337 real->line->screen_x[0],
338 real->line->screen_y[0],
339 w_current->start_x, w_current->start_y);
341 distance2 = dist(
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];
353 } else {
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,
364 o_current);
366 if (!real) {
367 fprintf(stderr, _("selected a nonexistant object!\n"));
368 exit(-1);
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;
379 #endif
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,
384 GDK_LINE_SOLID,
385 GDK_CAP_NOT_LAST,
386 GDK_JOIN_MITER);
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,
397 GDK_LINE_SOLID,
398 GDK_CAP_NOT_LAST,
399 GDK_JOIN_MITER);
403 /*! \todo Finish function documentation!!!
404 * \brief
405 * \par Function Description
408 int o_net_end(TOPLEVEL *w_current, int x, int y)
410 int x1, y1;
411 int x2, y2;
412 int x3, y3;
413 int color;
414 int size;
415 int primary_zero_length, secondary_zero_length;
416 int found_primary_connection = FALSE;
417 int sx[2], sy[2];
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);
426 return(FALSE);
429 if (w_current->override_net_color == -1) {
430 color = w_current->net_color;
431 } else {
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,
439 GDK_LINE_SOLID,
440 GDK_CAP_NOT_LAST,
441 GDK_JOIN_MITER);
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,
459 GDK_LINE_SOLID,
460 GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
461 gdk_gc_set_line_attributes(w_current->gc, size,
462 GDK_LINE_SOLID,
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);
488 return (FALSE);
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);
498 if (o_current) {
499 w_current->last_x = temp_x;
500 w_current->last_y = temp_y;
501 } else {
502 w_current->last_x = fix_x(w_current, x);
503 w_current->last_y = fix_y(w_current, y);
505 #endif
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);
532 /* conn stuff */
533 /* LEAK CHECK 1 */
534 other_objects = s_conn_return_others(other_objects,
535 w_current->page_current->
536 object_tail);
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);
544 #if DEBUG
545 printf("primary:\n");
546 s_conn_print(new_net->conn_list);
547 #endif
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,
554 sx[0], sy[0],
555 sx[1], sy[1]);
556 gdk_draw_line(w_current->backingstore, w_current->gc,
557 sx[0], sy[0],
558 sx[1], sy[1]);
560 if (w_current->net_style == THICK) {
561 gdk_gc_set_line_attributes(w_current->gc, 0,
562 GDK_LINE_SOLID,
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,
572 new_net->conn_list);
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);
597 /* conn stuff */
598 /* LEAK CHECK 2 */
599 other_objects = s_conn_return_others(other_objects,
600 w_current->page_current->
601 object_tail);
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);
608 #if DEBUG
609 s_conn_print(new_net->conn_list);
610 #endif
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,
617 sx[0], sy[0],
618 sx[1], sy[1]);
619 gdk_draw_line(w_current->backingstore, w_current->gc,
620 sx[0], sy[0],
621 sx[1], sy[1]);
623 if (w_current->net_style == THICK) {
624 gdk_gc_set_line_attributes(w_current->gc, 0,
625 GDK_LINE_SOLID,
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);
639 /* LEAK CHECK 3 */
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.. */
648 if (conn_count) {
649 w_current->inside_action = 0;
650 i_set_state(w_current, STARTDRAWNET);
651 o_net_eraserubber(w_current);
653 #endif
655 return (TRUE);
658 /*! \todo Finish function documentation!!!
659 * \brief
660 * \par Function Description
663 void o_net_rubbernet(TOPLEVEL *w_current, int x, int y)
665 int diff_x, diff_y;
666 int size;
667 int ortho;
669 if (w_current->inside_action == 0) {
670 o_redraw(w_current, w_current->page_current->object_head, TRUE);
671 return;
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,
677 GDK_LINE_SOLID,
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 */
698 if (!ortho)
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 */
708 if (ortho) {
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);
718 } else {
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,
740 GDK_LINE_SOLID,
741 GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
745 /*! \todo Finish function documentation!!!
746 * \brief
747 * \par Function Description
749 * \note
750 * used in button cancel code in x_events.c
752 void o_net_eraserubber(TOPLEVEL *w_current)
754 int size;
756 if (w_current->net_style == THICK) {
757 size = SCREENabs(w_current, NET_WIDTH);
759 if (size < 0)
760 size = 0;
762 gdk_gc_set_line_attributes(w_current->xor_gc, size,
763 GDK_LINE_SOLID,
764 GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
767 #if 0
768 gdk_gc_set_foreground(w_current->gc,
769 x_get_color(w_current->background_color));
770 #endif
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,
783 GDK_LINE_SOLID,
784 GDK_CAP_NOT_LAST, GDK_JOIN_MITER);
788 /*! \todo Finish function documentation!!!
789 * \brief
790 * \par Function Description
792 * \note
793 * used in x_event_expose() in x_events.c
795 void o_net_xorrubber(TOPLEVEL *w_current)
797 int size;
799 if (w_current->net_style == THICK ) {
801 size = SCREENabs(w_current, NET_WIDTH);
803 if (size < 0)
804 size=0;
806 gdk_gc_set_line_attributes(w_current->gc, size,
807 GDK_LINE_SOLID,
808 GDK_CAP_NOT_LAST,
809 GDK_JOIN_MITER);
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,
823 GDK_LINE_SOLID,
824 GDK_CAP_NOT_LAST,
825 GDK_JOIN_MITER);
829 /*! \todo Finish function documentation!!!
830 * \brief
831 * \par Function Description
834 int o_net_add_busrippers(TOPLEVEL *w_current, OBJECT *net_obj,
835 GList *other_objects)
838 int color;
839 GList *cl_current = NULL;
840 OBJECT *bus_object = NULL;
841 CONN *found_conn = NULL;
842 int done;
843 int otherone;
844 BUS_RIPPER rippers[2];
845 int ripper_count = 0;
846 int i;
847 double length;
848 int sign;
849 double distance1, distance2;
850 int first, second;
851 int made_changes = FALSE;
852 const int ripper_size = w_current->bus_ripper_size;
853 int complex_angle = 0;
854 char *clib = NULL;
856 length = o_line_length(net_obj);
858 if (!other_objects) {
859 return(FALSE);
862 if (length <= ripper_size) {
863 return(FALSE);
866 if (w_current->override_net_color == -1) {
867 color = w_current->net_color;
868 } else {
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;
885 done = FALSE;
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;
893 done = TRUE;
896 cl_current2 = cl_current2->next;
899 if (!found_conn) {
900 return(FALSE);
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;
911 if (!sign) {
912 if (bus_object->line->x[0] < bus_object->line->x[1]) {
913 first = 0;
914 second = 1;
915 } else {
916 first = 1;
917 second = 0;
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) {
926 sign = 1;
927 } else {
928 sign = -1;
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;
942 break;
945 if (w_current->bus_ripper_rotation == NON_SYMMETRIC) {
946 /* non-symmetric */
947 if (sign == 1) {
948 complex_angle = 0;
949 } else {
950 complex_angle = 90;
952 } else {
953 /* symmetric */
954 complex_angle = 0;
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;
967 ripper_count++;
968 /* printf("done\n"); */
969 made_changes++;
971 } else {
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;
979 break;
982 if (w_current->bus_ripper_rotation == NON_SYMMETRIC) {
983 /* non-symmetric */
984 if (sign == 1) {
985 complex_angle = 270;
986 } else {
987 complex_angle = 180;
989 } else {
990 /* symmetric */
991 complex_angle = 180;
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;
1004 ripper_count++;
1006 /* printf("done\n"); */
1007 made_changes++;
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;
1018 if (!sign) {
1019 if (bus_object->line->y[0] < bus_object->line->y[1]) {
1020 first = 0;
1021 second = 1;
1022 } else {
1023 first = 1;
1024 second = 0;
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) {
1033 sign = 1;
1034 } else {
1035 sign = -1;
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;
1050 break;
1053 if (w_current->bus_ripper_rotation == NON_SYMMETRIC) {
1054 /* non-symmetric */
1055 if (sign == 1) {
1056 complex_angle = 0;
1057 } else {
1058 complex_angle = 270;
1060 } else {
1061 /* symmetric */
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;
1075 ripper_count++;
1077 made_changes++;
1078 } else {
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;
1086 break;
1089 if (w_current->bus_ripper_rotation == NON_SYMMETRIC) {
1090 /* non-symmetric */
1091 if (sign == 1) {
1092 complex_angle = 90;
1093 } else {
1094 complex_angle = 180;
1096 } else {
1097 /* symmetric */
1098 complex_angle = 90;
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;
1111 ripper_count++;
1113 made_changes++;
1119 cl_current = cl_current->next;
1122 if (made_changes) {
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,
1136 OBJ_NET, color,
1137 rippers[i].x[0], rippers[i].y[0],
1138 rippers[i].x[1], rippers[i].y[1]);
1139 } else {
1141 if (clib) {
1142 w_current->page_current->object_tail =
1143 (OBJECT *) o_complex_add(
1144 w_current,
1145 w_current->page_current->object_tail,
1146 NULL,
1147 OBJ_COMPLEX, WHITE,
1148 rippers[i].x[0], rippers[i].y[0],
1149 complex_angle, 0,
1150 clib,
1151 w_current->bus_ripper_symname, 1, TRUE);
1153 o_complex_draw(w_current,w_current->page_current->object_tail);
1154 } else {
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);
1162 return(TRUE);
1165 return(FALSE);