Bumped versions to 1.1.2/20070818/30:2:0 for the next development snapshot
[geda-gaf/whiteaudio.git] / gschem / src / o_move.c
blobd15fad2abd66ad8d4c99f26920b10ae9c6b3404d
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>
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_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;
67 #define SINGLE 0
68 #define COMPLEX 1
70 /*! \todo Finish function documentation!!!
71 * \brief
72 * \par Function Description
74 * \note
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)
82 OBJECT *o_current;
83 OBJECT *object;
85 o_current = list;
86 while (o_current != NULL) {
88 object = o_current;
89 switch (object->type) {
91 case (OBJ_NET):
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);
100 break;
102 case (OBJ_BUS):
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);
110 break;
112 case (OBJ_PIN):
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);
120 break;
122 case (OBJ_LINE):
123 o_line_translate_world(w_current, diff_x, diff_y, object);
124 break;
126 case (OBJ_BOX):
127 o_box_translate_world(w_current, diff_x, diff_y, object);
128 break;
130 case (OBJ_PICTURE):
131 o_picture_translate_world(w_current, diff_x, diff_y, object);
132 break;
134 case (OBJ_CIRCLE):
135 o_circle_translate_world(w_current, diff_x, diff_y, object);
136 break;
138 case (OBJ_TEXT):
139 o_text_translate_world(w_current, diff_x, diff_y, object);
140 break;
142 case (OBJ_ARC):
143 o_arc_translate_world(w_current, diff_x, diff_y, object);
144 break;
146 case (OBJ_COMPLEX):
147 case (OBJ_PLACEHOLDER):
148 o_complex_world_translate (w_current, diff_x, diff_y,
149 object->complex->prim_objs);
150 break;
153 if (type == COMPLEX) {
154 o_current = o_current->next;
155 } else {
156 o_current = NULL;
162 /*! \todo Finish function documentation!!!
163 * \brief
164 * \par Function Description
167 void o_move_end(TOPLEVEL * w_current)
169 GList *s_current = NULL;
170 OBJECT *object;
171 int diff_x, diff_y;
172 int lx, ly;
173 int sx, sy;
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);
183 if (!object) {
184 /* actually this is an error condition hack */
185 w_current->inside_action = 0;
186 i_set_state(w_current, SELECT);
187 return;
191 SCREENtoWORLD(w_current, w_current->last_x, w_current->last_y,
192 &lx, &ly);
193 SCREENtoWORLD(w_current, w_current->start_x, w_current->start_y,
194 &sx, &sy);
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);
200 diff_x = lx - sx;
201 diff_y = ly - 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"));
225 exit(-1);
229 switch (object->type) {
230 case (OBJ_NET):
231 case (OBJ_PIN):
232 case (OBJ_BUS):
233 case (OBJ_LINE):
234 case (OBJ_BOX):
235 case (OBJ_PICTURE):
236 case (OBJ_CIRCLE):
237 case (OBJ_ARC):
238 case (OBJ_TEXT):
239 o_move_end_lowlevel(w_current, object, SINGLE, diff_x, diff_y,
240 &other_objects, &connected_objects);
241 break;
243 case (OBJ_COMPLEX):
244 case (OBJ_PLACEHOLDER):
246 if (scm_hook_empty_p(move_component_hook) == SCM_BOOL_F &&
247 object != NULL) {
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;
267 object->w_top = top;
268 object->w_right = right;
269 object->w_bottom = bottom;
271 break;
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!!!
317 * \brief
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) {
324 return (0);
327 if (object->line->x[1] == x && object->line->y[1] == y) {
328 return (1);
331 fprintf(stderr,
332 _("DOH! tried to find the whichone, but didn't find it!\n"));
333 return (-1);
336 /*! \todo Finish function documentation!!!
337 * \brief
338 * \par Function Description
341 void o_move_check_endpoint(TOPLEVEL * w_current, OBJECT * object)
343 GList *cl_current;
344 CONN *c_current;
345 int whichone;
347 if (!object)
348 return;
350 if (object->type != OBJ_NET && object->type != OBJ_PIN &&
351 object->type != OBJ_BUS) {
352 fprintf(stderr,
353 _("Got a non line object in o_move_check_endpoint\n"));
354 return;
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)) {
372 whichone =
373 o_move_return_whichone(c_current->other_object,
374 c_current->x, c_current->y);
376 #if DEBUG
377 printf
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);
381 #endif
383 #if DEBUG
384 printf("other x,y: %d %d\n", c_current->x,
385 c_current->y);
386 printf("type: %d return: %d real: [ %d %d ]\n",
387 c_current->type, whichone, c_current->whichone,
388 c_current->other_whichone);
389 #endif
391 if (whichone >= 0 && whichone <= 1) {
392 w_current->page_current->stretch_tail =
393 s_stretch_add(w_current->page_current->
394 stretch_head,
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!!!
413 * \brief
414 * \par Function Description
417 void o_move_prep_rubberband(TOPLEVEL * w_current)
419 GList *s_current;
420 OBJECT *object;
421 OBJECT *o_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;
428 #if DEBUG
429 printf("\n\n\n");
430 s_stretch_print_all(w_current->page_current->stretch_head);
431 printf("\n\n\n");
432 #endif
434 s_current = geda_list_get_glist( w_current->page_current->selection_list );
435 while (s_current != NULL) {
436 object = (OBJECT *) s_current->data;
437 if (object) {
438 switch (object->type) {
439 case (OBJ_NET):
440 case (OBJ_PIN):
441 case (OBJ_BUS):
442 o_move_check_endpoint(w_current, object);
443 break;
445 case (OBJ_COMPLEX):
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;
457 break;
461 s_current = s_current->next;
464 #if DEBUG
465 printf("\n\n\n\nfinished building scretch list:\n");
466 s_stretch_print_all(w_current->page_current->stretch_head);
467 #endif
470 /*! \todo Finish function documentation!!!
471 * \brief
472 * \par Function Description
475 int o_move_zero_length(OBJECT * object)
477 #if DEBUG
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]);
481 #endif
483 if (object->line->x[0] == object->line->x[1] &&
484 object->line->y[0] == object->line->y[1]) {
485 return TRUE;
486 } else {
487 return FALSE;
491 /*! \todo Finish function documentation!!!
492 * \brief
493 * \par Function Description
496 void o_move_end_rubberband(TOPLEVEL * w_current, int world_diff_x,
497 int world_diff_y,
498 GList** objects,
499 GList** other_objects, GList** connected_objects)
501 STRETCH *s_current;
502 OBJECT *object;
503 int x, y;
504 int whichone;
506 /* skip over head */
507 s_current = w_current->page_current->stretch_head->next;
509 while (s_current != NULL) {
511 object = s_current->object;
512 if (object) {
513 whichone = s_current->whichone;
515 switch (object->type) {
517 case (OBJ_NET):
519 /* save the other objects and remove object's connections */
520 *other_objects =
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];
527 #if DEBUG
528 printf("OLD: %d, %d\n", x, y);
529 printf("diff: %d, %d\n", world_diff_x, world_diff_y);
530 #endif
532 x = x + world_diff_x;
533 y = y + world_diff_y;
535 #if DEBUG
536 printf("NEW: %d, %d\n", x, y);
537 #endif
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);
545 } else {
546 o_net_recalc(w_current, object);
547 s_tile_update_object(w_current, object);
548 s_conn_update_object(w_current, object);
549 *connected_objects =
550 s_conn_return_others(*connected_objects, object);
551 *objects = g_list_append(*objects, object);
554 break;
556 case (OBJ_PIN):
558 /* not valid to do with pins */
560 break;
562 case (OBJ_BUS):
564 /* save the other objects and remove object's connections */
565 *other_objects =
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];
572 #if DEBUG
573 printf("OLD: %d, %d\n", x, y);
574 printf("diff: %d, %d\n", world_diff_x, world_diff_y);
575 #endif
576 x = x + world_diff_x;
577 y = y + world_diff_y;
579 #if DEBUG
580 printf("NEW: %d, %d\n", x, y);
581 #endif
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);
587 } else {
588 o_bus_recalc(w_current, object);
589 s_tile_update_object(w_current, object);
590 s_conn_update_object(w_current, object);
591 *connected_objects =
592 s_conn_return_others(*connected_objects, object);
593 *objects = g_list_append(*objects, object);
596 break;
600 s_current = s_current->next;
603 #if DEBUG
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));
608 #endif
612 /*! \todo Finish function documentation!!!
613 * \brief
614 * \par Function Description
617 void o_move_stretch_rubberband(TOPLEVEL * w_current)
620 STRETCH *s_current;
621 OBJECT *object;
622 int diff_x, diff_y;
623 int whichone;
625 diff_x = w_current->last_x - w_current->start_x;
626 diff_y = w_current->last_y - w_current->start_y;
629 /* skip over head */
630 s_current = w_current->page_current->stretch_head->next;
631 while (s_current != NULL) {
633 object = s_current->object;
634 if (object) {
635 whichone = s_current->whichone;
636 switch (object->type) {
637 case (OBJ_NET):
638 o_net_draw_xor_single(w_current,
639 diff_x, diff_y, whichone, object);
640 break;
642 case (OBJ_BUS):
643 o_bus_draw_xor_single(w_current,
644 diff_x, diff_y, whichone, object);
645 break;
648 s_current = s_current->next;