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
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_move_start(TOPLEVEL
* w_current
, int x
, int y
)
40 if ( geda_list_get_glist( w_current
->page_current
->selection_list
) != NULL
) {
42 /* Save the current state. When rotating the selection when moving,
43 we have to come back to here */
44 o_undo_savestate(w_current
, UNDO_ALL
);
45 w_current
->last_drawb_mode
= -1;
46 w_current
->event_state
= MOVE
;
48 w_current
->last_x
= w_current
->start_x
= fix_x(w_current
, x
);
49 w_current
->last_y
= w_current
->start_y
= fix_y(w_current
, y
);
51 o_erase_selected(w_current
);
53 o_drawbounding(w_current
, NULL
,
54 geda_list_get_glist( w_current
->page_current
->selection_list
),
55 x_get_darkcolor(w_current
->bb_color
), TRUE
);
57 if (w_current
->netconn_rubberband
) {
58 o_move_prep_rubberband(w_current
);
59 o_move_stretch_rubberband(w_current
);
62 o_select_move_to_place_list(w_current
);
63 w_current
->inside_action
= 1;
70 /*! \todo Finish function documentation!!!
72 * \par Function Description
75 * type can be SINGLE or COMPLEX
76 * which basically controls if this is a single object or a complex
78 void o_move_end_lowlevel(TOPLEVEL
* w_current
, OBJECT
* list
, int type
,
79 int diff_x
, int diff_y
,
80 GList
** other_objects
, GList
** connected_objects
)
86 while (o_current
!= NULL
) {
89 switch (object
->type
) {
92 /* save the other objects and remove object's connections */
93 *other_objects
= s_conn_return_others(*other_objects
, object
);
94 s_conn_remove(w_current
, object
);
96 /* do the actual translation */
97 o_net_translate_world(w_current
, diff_x
, diff_y
, object
);
98 s_conn_update_object(w_current
, object
);
99 *connected_objects
= s_conn_return_others(*connected_objects
, object
);
103 /* save the other objects and remove object's connections */
104 *other_objects
= s_conn_return_others(*other_objects
, object
);
105 s_conn_remove(w_current
, object
);
107 o_bus_translate_world(w_current
, diff_x
, diff_y
, object
);
108 s_conn_update_object(w_current
, object
);
109 *connected_objects
= s_conn_return_others(*connected_objects
, object
);
113 /* save the other objects and remove object's connections */
114 *other_objects
= s_conn_return_others(*other_objects
, object
);
115 s_conn_remove(w_current
, object
);
117 o_pin_translate_world(w_current
, diff_x
, diff_y
, object
);
118 s_conn_update_object(w_current
, object
);
119 *connected_objects
= s_conn_return_others(*connected_objects
, object
);
123 o_line_translate_world(w_current
, diff_x
, diff_y
, object
);
127 o_box_translate_world(w_current
, diff_x
, diff_y
, object
);
131 o_picture_translate_world(w_current
, diff_x
, diff_y
, object
);
135 o_circle_translate_world(w_current
, diff_x
, diff_y
, object
);
139 o_text_translate_world(w_current
, diff_x
, diff_y
, object
);
143 o_arc_translate_world(w_current
, diff_x
, diff_y
, object
);
147 case (OBJ_PLACEHOLDER
):
148 o_complex_world_translate (w_current
, diff_x
, diff_y
,
149 object
->complex->prim_objs
);
153 if (type
== COMPLEX
) {
154 o_current
= o_current
->next
;
162 /*! \todo Finish function documentation!!!
164 * \par Function Description
167 void o_move_end(TOPLEVEL
* w_current
)
169 GList
*s_current
= NULL
;
174 int left
, top
, right
, bottom
;
175 GList
*other_objects
= NULL
;
176 GList
*connected_objects
= NULL
;
177 GList
*rubbernet_objects
= NULL
;
178 GList
*rubbernet_other_objects
= NULL
;
179 GList
*rubbernet_connected_objects
= NULL
;
181 object
= o_select_return_first_object(w_current
);
184 /* actually this is an error condition hack */
185 w_current
->inside_action
= 0;
186 i_set_state(w_current
, SELECT
);
191 SCREENtoWORLD(w_current
, w_current
->last_x
, w_current
->last_y
,
193 SCREENtoWORLD(w_current
, w_current
->start_x
, w_current
->start_y
,
195 lx
= snap_grid(w_current
, lx
);
196 ly
= snap_grid(w_current
, ly
);
197 sx
= snap_grid(w_current
, sx
);
198 sy
= snap_grid(w_current
, sy
);
203 if (w_current
->netconn_rubberband
)
205 o_move_end_rubberband(w_current
, diff_x
, diff_y
,
206 &rubbernet_objects
, &rubbernet_other_objects
,
207 &rubbernet_connected_objects
);
210 if (w_current
->actionfeedback_mode
== OUTLINE
) {
211 o_drawbounding(w_current
, NULL
,
212 geda_list_get_glist( w_current
->page_current
->selection_list
),
213 x_get_darkcolor(w_current
->bb_color
), TRUE
);
216 /* skip over head node */
217 s_current
= geda_list_get_glist( w_current
->page_current
->selection_list
);
219 while (s_current
!= NULL
) {
221 object
= (OBJECT
*) s_current
->data
;
223 if (object
== NULL
) {
224 fprintf(stderr
, _("ERROR: NULL object in o_move_end!\n"));
229 switch (object
->type
) {
239 o_move_end_lowlevel(w_current
, object
, SINGLE
, diff_x
, diff_y
,
240 &other_objects
, &connected_objects
);
244 case (OBJ_PLACEHOLDER
):
246 if (scm_hook_empty_p(move_component_hook
) == SCM_BOOL_F
&&
248 scm_run_hook(move_component_hook
,
249 scm_cons (g_make_attrib_smob_list
250 (w_current
, object
), SCM_EOL
));
253 /* this next section of code is from */
254 /* o_complex_world_translate_toplevel */
255 object
->complex->x
= object
->complex->x
+ diff_x
;
256 object
->complex->y
= object
->complex->y
+ diff_y
;
258 o_move_end_lowlevel(w_current
, object
->complex->prim_objs
,
259 COMPLEX
, diff_x
, diff_y
,
260 &other_objects
, &connected_objects
);
263 world_get_object_list_bounds(w_current
, object
->complex->prim_objs
,
264 &left
, &top
, &right
, &bottom
);
266 object
->w_left
= left
;
268 object
->w_right
= right
;
269 object
->w_bottom
= bottom
;
274 s_current
= s_current
->next
;
277 /* Remove the undo saved in o_move_start */
278 o_undo_remove_last_undo(w_current
);
280 /* erase the bounding box */
281 if (w_current
->actionfeedback_mode
== BOUNDINGBOX
) {
282 o_drawbounding(w_current
, NULL
,
283 geda_list_get_glist( w_current
->page_current
->selection_list
),
284 x_get_darkcolor(w_current
->bb_color
), FALSE
);
287 /* Draw the objects that were moved (and connected/disconnected objects) */
288 o_draw_selected(w_current
);
289 o_cue_undraw_list(w_current
, other_objects
);
290 o_cue_draw_list(w_current
, other_objects
);
291 o_cue_undraw_list(w_current
, connected_objects
);
292 o_cue_draw_list(w_current
, connected_objects
);
294 /* Draw the connected nets/buses that were also changed */
295 o_draw_list(w_current
, rubbernet_objects
);
296 o_cue_undraw_list(w_current
, rubbernet_objects
);
297 o_cue_draw_list(w_current
, rubbernet_objects
);
298 o_cue_undraw_list(w_current
, rubbernet_other_objects
);
299 o_cue_draw_list(w_current
, rubbernet_other_objects
);
300 o_cue_undraw_list(w_current
, rubbernet_connected_objects
);
301 o_cue_draw_list(w_current
, rubbernet_connected_objects
);
303 w_current
->page_current
->CHANGED
= 1;
304 o_undo_savestate(w_current
, UNDO_ALL
);
306 g_list_free(other_objects
);
307 g_list_free(connected_objects
);
308 g_list_free(rubbernet_objects
);
309 g_list_free(rubbernet_other_objects
);
310 g_list_free(rubbernet_connected_objects
);
312 g_list_free(w_current
->page_current
->complex_place_list
);
313 w_current
->page_current
->complex_place_list
= NULL
;
316 /*! \todo Finish function documentation!!!
318 * \par Function Description
321 int o_move_return_whichone(OBJECT
* object
, int x
, int y
)
323 if (object
->line
->x
[0] == x
&& object
->line
->y
[0] == y
) {
327 if (object
->line
->x
[1] == x
&& object
->line
->y
[1] == y
) {
332 _("DOH! tried to find the whichone, but didn't find it!\n"));
336 /*! \todo Finish function documentation!!!
338 * \par Function Description
341 void o_move_check_endpoint(TOPLEVEL
* w_current
, OBJECT
* object
)
350 if (object
->type
!= OBJ_NET
&& object
->type
!= OBJ_PIN
&&
351 object
->type
!= OBJ_BUS
) {
353 _("Got a non line object in o_move_check_endpoint\n"));
357 cl_current
= object
->conn_list
;
358 while (cl_current
!= NULL
) {
360 c_current
= (CONN
*) cl_current
->data
;
362 if (c_current
->other_object
!= NULL
) {
364 /* really make sure that the object is not selected */
365 if (c_current
->other_object
->saved_color
== -1 &&
366 c_current
->other_object
->selected
== FALSE
) {
368 if (c_current
->type
== CONN_ENDPOINT
||
369 (c_current
->type
== CONN_MIDPOINT
&&
370 c_current
->other_whichone
!= -1)) {
373 o_move_return_whichone(c_current
->other_object
,
374 c_current
->x
, c_current
->y
);
378 ("FOUND: %s type: %d, whichone: %d, x,y: %d %d\n",
379 c_current
->other_object
->name
, c_current
->type
,
380 whichone
, c_current
->x
, c_current
->y
);
384 printf("other x,y: %d %d\n", c_current
->x
,
386 printf("type: %d return: %d real: [ %d %d ]\n",
387 c_current
->type
, whichone
, c_current
->whichone
,
388 c_current
->other_whichone
);
391 if (whichone
>= 0 && whichone
<= 1) {
392 w_current
->page_current
->stretch_tail
=
393 s_stretch_add(w_current
->page_current
->
395 c_current
->other_object
,
396 c_current
, whichone
);
398 if (c_current
->other_object
->type
== OBJ_NET
||
399 c_current
->other_object
->type
== OBJ_BUS
) {
400 o_erase_single(w_current
, c_current
->other_object
);
407 cl_current
= cl_current
->next
;
412 /*! \todo Finish function documentation!!!
414 * \par Function Description
417 void o_move_prep_rubberband(TOPLEVEL
* w_current
)
423 s_stretch_remove_most(w_current
,
424 w_current
->page_current
->stretch_head
);
425 w_current
->page_current
->stretch_tail
=
426 w_current
->page_current
->stretch_head
;
430 s_stretch_print_all(w_current
->page_current
->stretch_head
);
434 s_current
= geda_list_get_glist( w_current
->page_current
->selection_list
);
435 while (s_current
!= NULL
) {
436 object
= (OBJECT
*) s_current
->data
;
438 switch (object
->type
) {
442 o_move_check_endpoint(w_current
, object
);
446 case (OBJ_PLACEHOLDER
):
447 o_current
= object
->complex->prim_objs
;
448 while (o_current
!= NULL
) {
450 if (o_current
->type
== OBJ_PIN
) {
451 o_move_check_endpoint(w_current
, o_current
);
454 o_current
= o_current
->next
;
461 s_current
= s_current
->next
;
465 printf("\n\n\n\nfinished building scretch list:\n");
466 s_stretch_print_all(w_current
->page_current
->stretch_head
);
470 /*! \todo Finish function documentation!!!
472 * \par Function Description
475 int o_move_zero_length(OBJECT
* object
)
478 printf("x: %d %d y: %d %d\n",
479 object
->line
->x
[0], object
->line
->x
[1],
480 object
->line
->y
[0], object
->line
->y
[1]);
483 if (object
->line
->x
[0] == object
->line
->x
[1] &&
484 object
->line
->y
[0] == object
->line
->y
[1]) {
491 /*! \todo Finish function documentation!!!
493 * \par Function Description
496 void o_move_end_rubberband(TOPLEVEL
* w_current
, int world_diff_x
,
499 GList
** other_objects
, GList
** connected_objects
)
507 s_current
= w_current
->page_current
->stretch_head
->next
;
509 while (s_current
!= NULL
) {
511 object
= s_current
->object
;
513 whichone
= s_current
->whichone
;
515 switch (object
->type
) {
519 /* save the other objects and remove object's connections */
521 s_conn_return_others(*other_objects
, object
);
522 s_conn_remove(w_current
, object
);
524 x
= object
->line
->x
[whichone
];
525 y
= object
->line
->y
[whichone
];
528 printf("OLD: %d, %d\n", x
, y
);
529 printf("diff: %d, %d\n", world_diff_x
, world_diff_y
);
532 x
= x
+ world_diff_x
;
533 y
= y
+ world_diff_y
;
536 printf("NEW: %d, %d\n", x
, y
);
539 object
->line
->x
[whichone
] = x
;
540 object
->line
->y
[whichone
] = y
;
543 if (o_move_zero_length(object
)) {
544 o_delete_net(w_current
, object
);
546 o_net_recalc(w_current
, object
);
547 s_tile_update_object(w_current
, object
);
548 s_conn_update_object(w_current
, object
);
550 s_conn_return_others(*connected_objects
, object
);
551 *objects
= g_list_append(*objects
, object
);
558 /* not valid to do with pins */
564 /* save the other objects and remove object's connections */
566 s_conn_return_others(*other_objects
, object
);
567 s_conn_remove(w_current
, object
);
569 x
= object
->line
->x
[whichone
];
570 y
= object
->line
->y
[whichone
];
573 printf("OLD: %d, %d\n", x
, y
);
574 printf("diff: %d, %d\n", world_diff_x
, world_diff_y
);
576 x
= x
+ world_diff_x
;
577 y
= y
+ world_diff_y
;
580 printf("NEW: %d, %d\n", x
, y
);
582 object
->line
->x
[whichone
] = x
;
583 object
->line
->y
[whichone
] = y
;
585 if (o_move_zero_length(object
)) {
586 o_delete_bus(w_current
, object
);
588 o_bus_recalc(w_current
, object
);
589 s_tile_update_object(w_current
, object
);
590 s_conn_update_object(w_current
, object
);
592 s_conn_return_others(*connected_objects
, object
);
593 *objects
= g_list_append(*objects
, object
);
600 s_current
= s_current
->next
;
604 /*! \bug FIXME: moved_objects doesn't exist? */
605 /*printf("%d\n", g_list_length(*moved_objects));*/
606 printf("%d\n", g_list_length(*other_objects
));
607 printf("%d\n", g_list_length(*connected_objects
));
612 /*! \todo Finish function documentation!!!
614 * \par Function Description
617 void o_move_stretch_rubberband(TOPLEVEL
* w_current
)
625 diff_x
= w_current
->last_x
- w_current
->start_x
;
626 diff_y
= w_current
->last_y
- w_current
->start_y
;
630 s_current
= w_current
->page_current
->stretch_head
->next
;
631 while (s_current
!= NULL
) {
633 object
= s_current
->object
;
635 whichone
= s_current
->whichone
;
636 switch (object
->type
) {
638 o_net_draw_xor_single(w_current
,
639 diff_x
, diff_y
, whichone
, object
);
643 o_bus_draw_xor_single(w_current
,
644 diff_x
, diff_y
, whichone
, object
);
648 s_current
= s_current
->next
;