[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

gEDA-cvs: branch: master updated (1.1.2.20070818-95-g0b0d125)



The branch, master has been updated
       via  0b0d1259692ffe36e3bbc617af78bbf8a1c8f716 (commit)
       via  21a8790b0540c374b00cfc45ad79ab474a4655b0 (commit)
      from  626f5c071a1dfea55e0214f6064b29908152d792 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


=========
 Summary
=========

 gschem/include/prototype.h    |    6 +-
 gschem/src/i_callbacks.c      |    8 +-
 gschem/src/o_complex.c        |   91 -------
 gschem/src/o_misc.c           |  585 +++++++++++------------------------------
 gschem/src/x_event.c          |   15 +-
 libgeda/include/prototype.h   |   11 +-
 libgeda/src/o_basic.c         |   75 ++++++
 libgeda/src/o_complex_basic.c |  177 +++++--------
 libgeda/src/o_list.c          |   64 +++++
 libgeda/src/o_text_basic.c    |   57 +----
 10 files changed, 382 insertions(+), 707 deletions(-)


=================
 Commit Messages
=================

commit 0b0d1259692ffe36e3bbc617af78bbf8a1c8f716
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Sun Nov 18 21:34:57 2007 +0000

    Improve object mirroring API in libgeda + gschem
    
    Implements the o_mirror_world() function which rotates any object, and
    o_{glist,list}_mirror_world() functions which mirror lists of objects.
    
    Moves o_complex_mirror_world() from gschem into libgeda, and modifies
    appropriate places in libgeda + gschem to use the new API. The old
    gschem function o_mirror_world() becomes o_mirror_world_update(), a
    convenience function calling o_glist_mirror_world() and ensuring all
    necessary drawing and connection updates are made.
    
    Removes the o_complex_mirror_lowlevel() function which is made redundant
    by the above changes.

:100644 100644 d67b8bc... 77eda03... M	gschem/include/prototype.h
:100644 100644 c50cbc2... 10cbb59... M	gschem/src/i_callbacks.c
:100644 100644 914d5cb... 96575e0... M	gschem/src/o_complex.c
:100644 100644 83e978d... 12a0fed... M	gschem/src/o_misc.c
:100644 100644 c2cec06... 5f35bd4... M	gschem/src/x_event.c
:100644 100644 f662d88... f86e318... M	libgeda/include/prototype.h
:100644 100644 b84a7a7... aaafc3a... M	libgeda/src/o_basic.c
:100644 100644 c8ca460... 8edb84c... M	libgeda/src/o_complex_basic.c
:100644 100644 eaa4d63... 685f909... M	libgeda/src/o_list.c

commit 21a8790b0540c374b00cfc45ad79ab474a4655b0
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Sun Nov 18 21:34:35 2007 +0000

    Improve object rotation API in libgeda + gschem
    
    Implements the o_rotate_world() function which rotates any object, and
    o_{glist,list}_rotate_world() functions which rotate lists of objects.
    
    Moves o_complex_rotate_world() from gschem into libgeda, and modifies
    appropriate places in libgeda + gschem to use this new API. The gschem
    function o_rotate_90_world() is greatly simplified, becoming a
    convenience function calling o_glist_rotate_world() and ensuring all
    necessary drawing and connection updates are made. This function is
    renamed o_rotate_world_update().
    
    Removes the o_{complex,text}_rotate_lowlevel() functions which are made
    redundant with the above changes.

:100644 100644 df33d5f... d67b8bc... M	gschem/include/prototype.h
:100644 100644 f73b350... c50cbc2... M	gschem/src/i_callbacks.c
:100644 100644 055420b... 914d5cb... M	gschem/src/o_complex.c
:100644 100644 54052ce... 83e978d... M	gschem/src/o_misc.c
:100644 100644 94575d5... c2cec06... M	gschem/src/x_event.c
:100644 100644 96df3bb... f662d88... M	libgeda/include/prototype.h
:100644 100644 e55e161... b84a7a7... M	libgeda/src/o_basic.c
:100644 100644 e0b478b... c8ca460... M	libgeda/src/o_complex_basic.c
:100644 100644 d10a506... eaa4d63... M	libgeda/src/o_list.c
:100644 100644 5b8c679... 16cf56a... M	libgeda/src/o_text_basic.c

=========
 Changes
=========

commit 0b0d1259692ffe36e3bbc617af78bbf8a1c8f716
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Sun Nov 18 21:34:57 2007 +0000

    Improve object mirroring API in libgeda + gschem
    
    Implements the o_mirror_world() function which rotates any object, and
    o_{glist,list}_mirror_world() functions which mirror lists of objects.
    
    Moves o_complex_mirror_world() from gschem into libgeda, and modifies
    appropriate places in libgeda + gschem to use the new API. The old
    gschem function o_mirror_world() becomes o_mirror_world_update(), a
    convenience function calling o_glist_mirror_world() and ensuring all
    necessary drawing and connection updates are made.
    
    Removes the o_complex_mirror_lowlevel() function which is made redundant
    by the above changes.

diff --git a/gschem/include/prototype.h b/gschem/include/prototype.h
index d67b8bc..77eda03 100644
--- a/gschem/include/prototype.h
+++ b/gschem/include/prototype.h
@@ -546,7 +546,6 @@ void o_complex_place_rotate(GSCHEM_TOPLEVEL *w_current);
 void o_complex_end(GSCHEM_TOPLEVEL *w_current, int screen_x, int screen_y);
 void o_complex_rubbercomplex(GSCHEM_TOPLEVEL *w_current);
 void o_complex_translate_all(GSCHEM_TOPLEVEL *w_current, int offset);
-int o_complex_mirror_world(TOPLEVEL *toplevel, int centerx, int centery, OBJECT *object);
 /* o_copy.c */
 void o_copy_start(GSCHEM_TOPLEVEL *w_current, int x, int y);
 void o_copy_end(GSCHEM_TOPLEVEL *w_current);
@@ -621,7 +620,7 @@ void o_edit(GSCHEM_TOPLEVEL *w_current, GList *list);
 void o_lock(GSCHEM_TOPLEVEL *w_current);
 void o_unlock(GSCHEM_TOPLEVEL *w_current);
 void o_rotate_world_update(GSCHEM_TOPLEVEL *w_current, int centerx, int centery, int angle, GList *list);
-void o_mirror_world(GSCHEM_TOPLEVEL *w_current, GList *list, int centerx, int centery);
+void o_mirror_world_update(GSCHEM_TOPLEVEL *w_current, int centerx, int centery, GList *list);
 void o_edit_show_hidden_lowlevel(GSCHEM_TOPLEVEL *w_current, OBJECT *o_list);
 void o_edit_show_hidden(GSCHEM_TOPLEVEL *w_current, OBJECT *o_list);
 void o_edit_make_visible(GSCHEM_TOPLEVEL *w_current, OBJECT *o_list);
diff --git a/gschem/src/i_callbacks.c b/gschem/src/i_callbacks.c
index c50cbc2..10cbb59 100644
--- a/gschem/src/i_callbacks.c
+++ b/gschem/src/i_callbacks.c
@@ -929,9 +929,7 @@ DEFINE_I_CALLBACK(edit_mirror_hotkey)
     w_x = snap_grid(w_current->toplevel, w_x);
     w_y = snap_grid(w_current->toplevel, w_y);
 
-    o_mirror_world(w_current,
-                   object_list, 
-                   w_x, w_y);
+    o_mirror_world_update(w_current, w_x, w_y, object_list);
   }
 
   w_current->event_state = SELECT;
diff --git a/gschem/src/o_complex.c b/gschem/src/o_complex.c
index 914d5cb..96575e0 100644
--- a/gschem/src/o_complex.c
+++ b/gschem/src/o_complex.c
@@ -444,58 +444,3 @@ void o_complex_translate_all(GSCHEM_TOPLEVEL *w_current, int offset)
   o_undo_savestate(w_current, UNDO_ALL);
   i_update_menus(w_current);
 }
-
-
-/*! \todo Finish function documentation!!!
- *  \brief
- *  \par Function Description
- *
- */
-int o_complex_mirror_world(TOPLEVEL *toplevel, int world_centerx, int world_centery,
-		     OBJECT *object)
-{
-  int x, y;
-  int newx, newy;
-  int origx, origy;
-  int change = 0;
-
-  origx = object->complex->x;
-  origy = object->complex->y;
-
-  x = object->complex->x + (-world_centerx);
-  y = object->complex->y + (-world_centery);
-
-  newx = -x;
-  newy = y;
-
-  x = newx + (world_centerx);
-  y = newy + (world_centery);
-
-  o_complex_translate_world(toplevel,
-                            -object->complex->x,
-                            -object->complex->y, object);
-
-  o_complex_mirror_lowlevel(toplevel, 0, 0, object);
-
-  switch(object->complex->angle) {
-    case(90):
-      object->complex->angle = 270;
-      change = 1;
-      break;
-
-    case(270):
-      object->complex->angle = 90;
-      change = 1;
-      break;
-
-  }
-
-  object->complex->mirror = !object->complex->mirror;
-
-  o_complex_translate_world(toplevel, x, y, object);
-
-#if DEBUG
-  printf("final res %d %d\n", object->complex->x,  object->complex->y);
-#endif
-  return(change);
-}
diff --git a/gschem/src/o_misc.c b/gschem/src/o_misc.c
index 83e978d..12a0fed 100644
--- a/gschem/src/o_misc.c
+++ b/gschem/src/o_misc.c
@@ -339,12 +339,11 @@ void o_rotate_world_update(GSCHEM_TOPLEVEL *w_current,
  *  \par Function Description
  *
  */
-void o_mirror_world(GSCHEM_TOPLEVEL *w_current, GList *list, int centerx, int centery)
+void o_mirror_world_update(GSCHEM_TOPLEVEL *w_current, int centerx, int centery, GList *list)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
-  OBJECT *object;
-  GList *s_current;
-  OBJECT *o_current = NULL;
+  OBJECT *o_current;
+  GList *o_iter;
   GList *other_objects=NULL;
   GList *connected_objects=NULL;
 
@@ -354,204 +353,96 @@ void o_mirror_world(GSCHEM_TOPLEVEL *w_current, GList *list, int centerx, int ce
     return;
   }
 
-  s_current = list;
-
-  while (s_current != NULL) {
-
-    object = (OBJECT *) s_current->data;
-
-    if (!object) {
-      fprintf(stderr, _("ERROR: NULL object in o_mirror!\n"));
-      return;
-    }
-
-    g_list_free(other_objects);
-    other_objects = NULL;
-    g_list_free(connected_objects);
-    connected_objects = NULL;
-
-    switch(object->type) {
-
-
-      case(OBJ_NET):
-        o_cue_undraw(w_current, object);
-        o_net_erase(w_current, object);
-        o_line_erase_grips(w_current, object);
-
-        other_objects = s_conn_return_others(other_objects, object);
-        s_conn_remove(toplevel, object);
-
-        o_net_mirror_world(toplevel, centerx, centery, object);
-        s_conn_update_object(toplevel, object);
-        o_net_draw(w_current, object);
-
-        /* draw the other objects */
-        o_cue_undraw_list(w_current, other_objects);
-        o_cue_draw_list(w_current, other_objects);
-
-        /* get other connected objects and redraw */
-        connected_objects = s_conn_return_others(connected_objects, object);
-        o_cue_undraw_list(w_current, connected_objects);
-        o_cue_draw_list(w_current, connected_objects);
-
-        /* finally redraw the cues on the current object */
-        o_cue_draw_single(w_current, object);
-        break;
-
-      case(OBJ_PIN):
-        o_cue_undraw(w_current, object);
-        o_pin_erase(w_current, object);
-        o_line_erase_grips(w_current, object);
-
-        other_objects = s_conn_return_others(other_objects, object);
-        s_conn_remove(toplevel, object);
-
-        o_pin_mirror_world(toplevel, centerx, centery, object);
-        s_conn_update_object(toplevel, object);
-        o_pin_draw(w_current, object);
-
-        /* draw the other objects */
-        o_cue_undraw_list(w_current, other_objects);
-        o_cue_draw_list(w_current, other_objects);
-
-        /* get other connected objects and redraw */
-        connected_objects = s_conn_return_others(connected_objects, object);
-        o_cue_undraw_list(w_current, connected_objects);
-        o_cue_draw_list(w_current, connected_objects);
-
-        /* finally redraw the cues on the current object */
-        o_cue_draw_single(w_current, object);
-        break;
-
-      case(OBJ_BUS):
-        o_bus_erase(w_current, object);
-        o_line_erase_grips(w_current, object);
-
-        other_objects = s_conn_return_others(other_objects, object);
-        s_conn_remove(toplevel, object);
-
-        o_bus_mirror_world(toplevel, centerx, centery, object);
-        s_conn_update_object(toplevel, object);
-        o_bus_draw(w_current, object);
+  o_cue_undraw_list (w_current, list);
+  o_erase_list (w_current, list);
 
-        /* draw the other objects */
-        o_cue_undraw_list(w_current, other_objects);
-        o_cue_draw_list(w_current, other_objects);
-
-        /* get other connected objects and redraw */
-        connected_objects = s_conn_return_others(connected_objects, object);
-        o_cue_undraw_list(w_current, connected_objects);
-        o_cue_draw_list(w_current, connected_objects);
-
-        /* finally redraw the cues on the current object */
-        o_cue_draw_single(w_current, object);
-        break;
-
-      case(OBJ_COMPLEX):
-        o_cue_undraw_objects(w_current, object->complex->prim_objs);
-        /* erase the current selection */
-        o_complex_erase(w_current, object);
-
-        other_objects = s_conn_return_complex_others(other_objects, object);
-
-        /* remove all conn references */
-        o_current = object->complex->prim_objs;
-        while(o_current != NULL) {
-          s_conn_remove(toplevel, o_current);
-          o_current = o_current->next;
-        }
-
-        o_complex_mirror_world(toplevel, centerx, centery, object);
-        s_conn_update_complex(toplevel, object->complex->prim_objs);
-        o_complex_draw(w_current, object);
-
-        o_cue_undraw_list(w_current, other_objects);
-        o_cue_draw_list(w_current, other_objects);
-
-        /* now draw the newly connected objects */
-        connected_objects = s_conn_return_complex_others(connected_objects,
-                                                         object);
-        o_cue_undraw_list(w_current, connected_objects);
-        o_cue_draw_list(w_current, connected_objects);
-        break;
-
-      case(OBJ_LINE):
-        o_line_erase_grips(w_current, object);
-        o_line_erase(w_current, object);
-        o_line_mirror_world(toplevel, centerx, centery, object);
-        o_line_draw(w_current, object);
-        break;
-
-      case(OBJ_BOX):
-        o_box_erase_grips(w_current, object);
-        o_box_erase(w_current, object);
-        o_box_mirror_world(toplevel, centerx, centery, object);
-        o_box_draw(w_current, object);
+  /* Find connected objects, removing each object in turn from the
+   * connection list. We only _really_ want those objects connected
+   * to the selection, not those within in it. The extra redraws
+   * don't _really_ hurt though. */
+  o_iter = list;
+  while (o_iter != NULL) {
+    o_current = o_iter->data;
+    switch (o_current->type) {
+      case OBJ_COMPLEX:
+      case OBJ_PLACEHOLDER:
+        other_objects =
+          s_conn_return_complex_others(other_objects, o_current);
+        s_conn_remove_complex (toplevel, o_current);
         break;
-
-      case(OBJ_PICTURE):
-        o_picture_erase_grips(w_current, object);
-        o_picture_erase(w_current, object);
-        o_picture_mirror_world(toplevel, centerx, centery, object);
-        o_picture_draw(w_current, object);
+      case OBJ_NET:
+      case OBJ_PIN:
+      case OBJ_BUS:
+        other_objects = s_conn_return_others(other_objects, o_current);
+        s_conn_remove (toplevel, o_current);
         break;
+    }
+    o_iter = g_list_next (o_iter);
+  }
 
-      case(OBJ_CIRCLE):
-        o_circle_erase_grips(w_current, object);
-        o_circle_erase(w_current, object);
-        o_circle_mirror_world(toplevel, centerx, centery, object);
-        o_circle_draw(w_current, object);
-        break;
+  o_glist_mirror_world( toplevel, centerx, centery, list );
 
-      case(OBJ_ARC):
-        o_arc_erase(w_current, object);
-        o_arc_mirror_world(toplevel, centerx, centery, object);
-        o_arc_draw(w_current, object);
+  /* Find connected objects, adding each object in turn back to the
+   * connection list. We only _really_ want those objects connected
+   * to the selection, not those within in it. The extra redraws dont
+   * _really_ hurt though. */
+  o_iter = list;
+  while (o_iter != NULL) {
+    o_current = o_iter->data;
+    switch (o_current->type) {
+      case OBJ_COMPLEX:
+      case OBJ_PLACEHOLDER:
+        s_conn_update_complex(toplevel, o_current->complex->prim_objs);
+        connected_objects =
+          s_conn_return_complex_others(connected_objects, o_current);
         break;
-
-      case(OBJ_TEXT):
-        o_text_erase(w_current, object);
-        o_text_mirror_world(toplevel,
-                      centerx, centery, object);
-        o_text_draw(w_current, object);
+      case OBJ_NET:
+      case OBJ_PIN:
+      case OBJ_BUS:
+        s_conn_update_object(toplevel, o_current);
+        connected_objects = s_conn_return_others(connected_objects, o_current);
         break;
-
     }
+    o_iter = g_list_next (o_iter);
+  }
 
-    s_current = g_list_next(s_current);
+  o_draw_list (w_current, list);
+  o_cue_undraw_list(w_current, other_objects);
+  o_cue_draw_list(w_current, other_objects);
+  o_cue_undraw_list(w_current, connected_objects);
+  o_cue_draw_list(w_current, connected_objects);
+  o_cue_draw_list(w_current, list);
 
-  }
+  g_list_free (other_objects);
+  other_objects = NULL;
+  g_list_free (connected_objects);
+  connected_objects = NULL;
 
-  /* All objects were rotated. Do a 2nd pass to run the rotate hooks */
+  /* All objects were mirrored. Do a 2nd pass to run the mirror hooks */
   /* Do not run any hooks for simple objects here, like text, since they
-     were rotated in the previous pass, and the selection list can contain
+     were mirrored in the previous pass, and the selection list can contain
      an object and all its attributes (text) */
-  s_current = list;
-  while (s_current != NULL) {
-    object = (OBJECT *) s_current->data;
-
-    if (!object) {
-      fprintf(stderr, _("ERROR: NULL object in o_rotate_90!\n"));
-      return;
-    }
+  o_iter = list;
+  while (o_iter != NULL) {
+    o_current = (OBJECT *) o_iter->data;
 
-    switch(object->type) {
+    switch(o_current->type) {
       case(OBJ_PIN):
-        /* Run the rotate pin hook */
+        /* Run the mirror pin hook */
         if (scm_hook_empty_p(mirror_pin_hook) == SCM_BOOL_F &&
-            object != NULL) {
-          scm_run_hook(rotate_pin_hook,
-                       scm_cons(g_make_object_smob(toplevel, object),
+            o_current != NULL) {
+          scm_run_hook(mirror_pin_hook,
+                       scm_cons(g_make_object_smob(toplevel, o_current),
                                 SCM_EOL));
         }
         break;
 
       case (OBJ_COMPLEX):
-        /* Run the rotate pin hook */
-        if (scm_hook_empty_p(rotate_component_object_hook) == SCM_BOOL_F &&
-            object != NULL) {
+        /* Run the mirror pin hook */
+        if (scm_hook_empty_p(mirror_component_object_hook) == SCM_BOOL_F &&
+            o_current != NULL) {
           scm_run_hook(mirror_component_object_hook,
-                       scm_cons(g_make_object_smob(toplevel, object),
+                       scm_cons(g_make_object_smob(toplevel, o_current),
                                 SCM_EOL));
         }
         break;
@@ -559,10 +450,9 @@ void o_mirror_world(GSCHEM_TOPLEVEL *w_current, GList *list, int centerx, int ce
         break;
     }
 
-    s_current = g_list_next(s_current);
+    o_iter = g_list_next(o_iter);
   }
 
-
   toplevel->page_current->CHANGED=1;
   o_undo_savestate(w_current, UNDO_ALL);
 }
diff --git a/gschem/src/x_event.c b/gschem/src/x_event.c
index c2cec06..5f35bd4 100644
--- a/gschem/src/x_event.c
+++ b/gschem/src/x_event.c
@@ -435,9 +435,9 @@ gint x_event_button_pressed(GtkWidget *widget, GdkEventButton *event,
         w_x = snap_grid(toplevel, w_x);
         w_y = snap_grid(toplevel, w_y);
 
-        o_mirror_world(w_current,
-                       geda_list_get_glist( toplevel->page_current->selection_list ),
-                       w_x, w_y);
+        o_mirror_world_update(w_current, w_x, w_y,
+                              geda_list_get_glist(
+                                toplevel->page_current->selection_list ));
 
         w_current->inside_action = 0;
         i_set_state(w_current, SELECT);
diff --git a/libgeda/include/prototype.h b/libgeda/include/prototype.h
index f662d88..f86e318 100644
--- a/libgeda/include/prototype.h
+++ b/libgeda/include/prototype.h
@@ -197,6 +197,7 @@ void o_set_line_options(TOPLEVEL *toplevel, OBJECT *o_current, OBJECT_END end, O
 void o_set_fill_options(TOPLEVEL *toplevel, OBJECT *o_current, OBJECT_FILLING type, int width, int pitch1, int angle1, int pitch2, int angle2);
 void o_translate_world (TOPLEVEL *toplevel, gint dx, gint dy, OBJECT *object);
 void o_rotate_world(TOPLEVEL *toplevel, int world_centerx, int world_centery, int angle, OBJECT *object);
+void o_mirror_world(TOPLEVEL *toplevel, int world_centerx, int world_centery, OBJECT *object);
 /* o_box_basic.c */
 OBJECT *o_box_add(TOPLEVEL *toplevel, OBJECT *object_list, char type, int color, int x1, int y1, int x2, int y2);
 OBJECT *o_box_copy(TOPLEVEL *toplevel, OBJECT *list_tail, OBJECT *o_current);
@@ -293,7 +294,7 @@ void o_complex_unset_color_single(OBJECT *o_current);
 void o_complex_set_saved_color_only(OBJECT *complex, int color);
 OBJECT *o_complex_return_nth_pin(OBJECT *o_list, int counter);
 void o_complex_rotate_world(TOPLEVEL *toplevel, int world_centerx, int world_centery, int angle, OBJECT *object);
-void o_complex_mirror_lowlevel(TOPLEVEL *toplevel, int world_centerx, int world_centery, OBJECT *object);
+void o_complex_mirror_world(TOPLEVEL *toplevel, int world_centerx, int world_centery, OBJECT *object);
 OBJECT *o_complex_return_pin_object(OBJECT *object, char *pin);
 int  o_complex_count_pins(OBJECT *object);
 void o_complex_check_symversion(TOPLEVEL* toplevel, OBJECT* object);
@@ -334,6 +335,8 @@ void o_list_translate_world(TOPLEVEL *toplevel, int x, int y, OBJECT *list);
 void o_glist_translate_world(TOPLEVEL *toplevel, int x, int y, GList *list);
 void o_list_rotate_world(TOPLEVEL *toplevel, int x, int y, int angle, OBJECT *list);
 void o_glist_rotate_world(TOPLEVEL *toplevel, int x, int y, int angle, GList *list);
+void o_list_mirror_world(TOPLEVEL *toplevel, int x, int y, OBJECT *list);
+void o_glist_mirror_world(TOPLEVEL *toplevel, int x, int y, GList *list);
 
 /* o_net_basic.c */
 void world_get_net_bounds(TOPLEVEL *toplevel, OBJECT *object, int *left, int *top, int *right, int *bottom);
diff --git a/libgeda/src/o_basic.c b/libgeda/src/o_basic.c
index b84a7a7..aaafc3a 100644
--- a/libgeda/src/o_basic.c
+++ b/libgeda/src/o_basic.c
@@ -335,3 +335,40 @@ void o_rotate_world (TOPLEVEL *toplevel, int world_centerx, int world_centery, i
     (*func) (toplevel, world_centerx, world_centery, angle, object);
   }
 }
+
+
+/*! \brief Mirrors an object in world coordinates
+ *  \par Function Description
+ *  This function mirrors an object about the point
+ *  (<B>world_centerx</B>,<B>world_centery</B>) in world units.
+ *
+ *  \param [in]     toplevel       The TOPLEVEL object.
+ *  \param [in]     world_centerx  Origin x coordinate in WORLD units.
+ *  \param [in]     world_centery  Origin y coordinate in WORLD units.
+ *  \param [in,out] object         The OBJECT to mirror.
+ */
+void o_mirror_world (TOPLEVEL *toplevel, int world_centerx, int world_centery, OBJECT *object)
+{
+  void (*func) (TOPLEVEL*, int, int, OBJECT*) = NULL;
+
+  switch (object->type) {
+      case OBJ_HEAD:    /* Do nothing for head nodes */   break;
+      case OBJ_LINE:    func = o_line_mirror_world;       break;
+      case OBJ_NET:     func = o_net_mirror_world;        break;
+      case OBJ_BUS:     func = o_bus_mirror_world;        break;
+      case OBJ_BOX:     func = o_box_mirror_world;        break;
+      case OBJ_PICTURE: func = o_picture_mirror_world;    break;
+      case OBJ_CIRCLE:  func = o_circle_mirror_world;     break;
+      case OBJ_PLACEHOLDER:
+      case OBJ_COMPLEX: func = o_complex_mirror_world;    break;
+      case OBJ_TEXT:    func = o_text_mirror_world;       break;
+      case OBJ_PIN:     func = o_pin_mirror_world;        break;
+      case OBJ_ARC:     func = o_arc_mirror_world;        break;
+      default:
+        g_assert_not_reached ();
+  }
+
+  if (func != NULL) {
+    (*func) (toplevel, world_centerx, world_centery, object);
+  }
+}
diff --git a/libgeda/src/o_complex_basic.c b/libgeda/src/o_complex_basic.c
index c8ca460..8edb84c 100644
--- a/libgeda/src/o_complex_basic.c
+++ b/libgeda/src/o_complex_basic.c
@@ -601,7 +601,7 @@ OBJECT *o_complex_add(TOPLEVEL *toplevel, OBJECT *object_list,
    */
   if (loaded_normally == TRUE) {
     if (mirror) {
-      o_complex_mirror_lowlevel(toplevel, x, y, new_node);
+      o_complex_mirror_world(toplevel, 0, 0, new_node);
     }
 
     o_list_rotate_world(toplevel, 0, 0, angle, prim_objs);
@@ -1280,76 +1280,55 @@ void o_complex_rotate_world(TOPLEVEL *toplevel,
 }
 
 
-/*! \brief
+/*! \todo Finish function documentation!!!
+ *  \brief
  *  \par Function Description
  *
  */
-/* pass in top level object */
-void o_complex_mirror_lowlevel(TOPLEVEL *toplevel,
-			       int world_centerx, int world_centery,
-			       OBJECT *object)
+void o_complex_mirror_world(TOPLEVEL *toplevel,
+                            int world_centerx, int world_centery,
+                            OBJECT *object)
 {
-  OBJECT *o_current=NULL;
-
-  g_return_if_fail(object != NULL);
-  g_return_if_fail(((object->type == OBJ_COMPLEX) ||
-		    (object->type == OBJ_PLACEHOLDER)));
-  g_return_if_fail(object->complex != NULL);
-
-  /* do individual complex objects */
-  o_current = object->complex->prim_objs;
-
-  while ( o_current != NULL ) {
-    switch(o_current->type) {
-      case(OBJ_LINE):
-        o_line_mirror_world(toplevel, 0, 0, o_current);
-        break;
+  int x, y;
+  int newx, newy;
 
-      case(OBJ_NET):
-        o_net_mirror_world(toplevel, 0, 0, o_current);
-        break;
+  g_return_if_fail( object != NULL );
+  g_return_if_fail( (object->type == OBJ_COMPLEX ||
+                     object->type == OBJ_PLACEHOLDER) );
+  g_return_if_fail( object->complex != NULL );
 
-      case(OBJ_BUS):
-        o_bus_mirror_world(toplevel, 0, 0, o_current);
-        break;
-	
-      case(OBJ_BOX):
-        o_box_mirror_world(toplevel, 0, 0, o_current);
-        break;
+  x = object->complex->x + (-world_centerx);
+  y = object->complex->y + (-world_centery);
 
-      case(OBJ_PICTURE):
-        o_picture_mirror_world(toplevel, 0, 0, o_current);
-        break;
+  newx = -x;
+  newy = y;
 
-      case(OBJ_CIRCLE):
-        o_circle_mirror_world(toplevel, 0, 0, o_current);
-        break;
+  x = newx + (world_centerx);
+  y = newy + (world_centery);
 
-      case(OBJ_PIN):
-        o_pin_mirror_world(toplevel, 0, 0, o_current);
-        break;
+  o_complex_translate_world(toplevel,
+                            -object->complex->x,
+                            -object->complex->y, object);
 
-      case(OBJ_ARC):
-        o_arc_mirror_world(toplevel, 0, 0, o_current);
-        break;
+  o_list_mirror_world( toplevel, 0, 0, object->complex->prim_objs );
 
-      case(OBJ_COMPLEX):
-      case(OBJ_PLACEHOLDER):
-	o_complex_mirror_lowlevel(toplevel, 0, 0, o_current);
-	break;
+  switch(object->complex->angle) {
+    case(90):
+      object->complex->angle = 270;
+      break;
 
-      case(OBJ_TEXT):
-        o_text_mirror_world(toplevel, 0, 0, o_current);
-        break;
+    case(270):
+      object->complex->angle = 90;
+      break;
 
-    }
-    o_current=o_current->next;
   }
 
-  /* mirror origin point */
-  /*	object->x = -object->x;*/
+  object->complex->mirror = !object->complex->mirror;
+
+  o_complex_translate_world(toplevel, x, y, object);
 }
 
+
 /*! \brief
  *  \par Function Description
  *
diff --git a/libgeda/src/o_list.c b/libgeda/src/o_list.c
index eaa4d63..685f909 100644
--- a/libgeda/src/o_list.c
+++ b/libgeda/src/o_list.c
@@ -485,3 +485,34 @@ void o_glist_rotate_world (TOPLEVEL *toplevel, int x, int y, int angle, GList *l
   }
 }
 
+
+/*! \todo Finish function description!!!
+ *  \brief
+ *  \par Function Description
+ */
+void o_list_mirror_world (TOPLEVEL *toplevel, int x, int y, OBJECT *list)
+{
+  OBJECT *o_current = list;
+
+  while ( o_current != NULL ) {
+    o_mirror_world (toplevel, x, y, o_current);
+    o_current = o_current->next;
+  }
+}
+
+
+/*! \todo Finish function description!!!
+ *  \brief
+ *  \par Function Description
+ */
+void o_glist_mirror_world (TOPLEVEL *toplevel, int x, int y, GList *list)
+{
+  GList *iter = list;
+  OBJECT *o_current;
+
+  while ( iter != NULL ) {
+    o_current = (OBJECT *)iter->data;
+    o_mirror_world (toplevel, x, y, o_current);
+    iter = g_list_next (iter);
+  }
+}

commit 21a8790b0540c374b00cfc45ad79ab474a4655b0
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Sun Nov 18 21:34:35 2007 +0000

    Improve object rotation API in libgeda + gschem
    
    Implements the o_rotate_world() function which rotates any object, and
    o_{glist,list}_rotate_world() functions which rotate lists of objects.
    
    Moves o_complex_rotate_world() from gschem into libgeda, and modifies
    appropriate places in libgeda + gschem to use this new API. The gschem
    function o_rotate_90_world() is greatly simplified, becoming a
    convenience function calling o_glist_rotate_world() and ensuring all
    necessary drawing and connection updates are made. This function is
    renamed o_rotate_world_update().
    
    Removes the o_{complex,text}_rotate_lowlevel() functions which are made
    redundant with the above changes.

diff --git a/gschem/include/prototype.h b/gschem/include/prototype.h
index df33d5f..d67b8bc 100644
--- a/gschem/include/prototype.h
+++ b/gschem/include/prototype.h
@@ -546,7 +546,6 @@ void o_complex_place_rotate(GSCHEM_TOPLEVEL *w_current);
 void o_complex_end(GSCHEM_TOPLEVEL *w_current, int screen_x, int screen_y);
 void o_complex_rubbercomplex(GSCHEM_TOPLEVEL *w_current);
 void o_complex_translate_all(GSCHEM_TOPLEVEL *w_current, int offset);
-void o_complex_rotate_world(TOPLEVEL *toplevel, int centerx, int centery, int angle, OBJECT *object);
 int o_complex_mirror_world(TOPLEVEL *toplevel, int centerx, int centery, OBJECT *object);
 /* o_copy.c */
 void o_copy_start(GSCHEM_TOPLEVEL *w_current, int x, int y);
@@ -621,7 +620,7 @@ void o_line_erase_grips(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current);
 void o_edit(GSCHEM_TOPLEVEL *w_current, GList *list);
 void o_lock(GSCHEM_TOPLEVEL *w_current);
 void o_unlock(GSCHEM_TOPLEVEL *w_current);
-void o_rotate_90_world(GSCHEM_TOPLEVEL *w_current, GList *list, int centerx, int centery);
+void o_rotate_world_update(GSCHEM_TOPLEVEL *w_current, int centerx, int centery, int angle, GList *list);
 void o_mirror_world(GSCHEM_TOPLEVEL *w_current, GList *list, int centerx, int centery);
 void o_edit_show_hidden_lowlevel(GSCHEM_TOPLEVEL *w_current, OBJECT *o_list);
 void o_edit_show_hidden(GSCHEM_TOPLEVEL *w_current, OBJECT *o_list);
diff --git a/gschem/src/i_callbacks.c b/gschem/src/i_callbacks.c
index f73b350..c50cbc2 100644
--- a/gschem/src/i_callbacks.c
+++ b/gschem/src/i_callbacks.c
@@ -875,13 +875,13 @@ DEFINE_I_CALLBACK(edit_rotate_90_hotkey)
   if (object_list) {
     i_update_middle_button(w_current,
                            i_callback_edit_rotate_90_hotkey, _("Rotate"));
-    /* Allow o_rotate_90_world to redraw the objects */
+    /* Allow o_rotate_world_update to redraw the objects */
     w_current->toplevel->DONT_REDRAW = 0;
     SCREENtoWORLD( w_current->toplevel, mouse_x, mouse_y, &w_x, &w_y );
     w_x = snap_grid(w_current->toplevel, w_x);
     w_y = snap_grid(w_current->toplevel, w_y);
 
-    o_rotate_90_world(w_current, object_list, w_x, w_y);
+    o_rotate_world_update(w_current, w_x, w_y, 90, object_list);
   }
 
   w_current->event_state = SELECT;
diff --git a/gschem/src/o_complex.c b/gschem/src/o_complex.c
index 055420b..914d5cb 100644
--- a/gschem/src/o_complex.c
+++ b/gschem/src/o_complex.c
@@ -445,42 +445,6 @@ void o_complex_translate_all(GSCHEM_TOPLEVEL *w_current, int offset)
   i_update_menus(w_current);
 }
 
-/*! \todo Finish function documentation!!!
- *  \brief
- *  \par Function Description
- *
- */
-void o_complex_rotate_world(TOPLEVEL *toplevel,
-                            int centerx, int centery,
-                            int angle, OBJECT *object)
-{
-  int x, y;
-  int newx, newy;
-
-  x = object->complex->x + (-centerx);
-  y = object->complex->y + (-centery);
-
-  rotate_point_90(x, y, angle, &newx, &newy);
-
-  x = newx + (centerx);
-  y = newy + (centery);
-
-  o_complex_translate_world(toplevel,
-                            -object->complex->x,
-                            -object->complex->y, object);
-  o_complex_rotate_lowlevel(toplevel, 0, 0, angle, object);
-
-  object->complex->x = 0;
-  object->complex->y = 0;
-
-  o_complex_translate_world(toplevel, x, y, object);
-
-  object->complex->angle = ( object->complex->angle + angle ) % 360;
-
-#if DEBUG
-  printf("setting final rotated angle to: %d\n\n", object->angle);
-#endif
-}
 
 /*! \todo Finish function documentation!!!
  *  \brief
diff --git a/gschem/src/o_misc.c b/gschem/src/o_misc.c
index 54052ce..83e978d 100644
--- a/gschem/src/o_misc.c
+++ b/gschem/src/o_misc.c
@@ -191,28 +191,28 @@ void o_unlock(GSCHEM_TOPLEVEL *w_current)
 
 /*! \brief Rotate all objects in list.
  *  \par Function Description
- *  Given the selection <B>list</B>, and the center of rotation
+ *  Given an object <B>list</B>, and the center of rotation
  *  (<B>centerx</B>,<B>centery</B>, this function traverses all the selection
- *  list, rotating each object.
- *  The selection list contains a given object and all its attributes
+ *  list, rotating each object through angle <B>angle</B>.
+ *  The list contains a given object and all its attributes
  *  (refdes, pinname, pinlabel, ...).
  *  There is a second pass to run the rotate hooks of non-simple objects,
  *  like pin or complex objects, for example.
  *
  *  \param [in] w_current  The GSCHEM_TOPLEVEL object.
- *  \param [in] list       The list of objects to rotate.
  *  \param [in] centerx    Center x coordinate of rotation.
  *  \param [in] centery    Center y coordinate of rotation.
+ *  \param [in] angle      Angle to rotate the objects through.
+ *  \param [in] list       The list of objects to rotate.
  */
-void o_rotate_90_world(GSCHEM_TOPLEVEL *w_current, GList *list,
-                       int centerx, int centery)
+void o_rotate_world_update(GSCHEM_TOPLEVEL *w_current,
+                           int centerx, int centery, int angle, GList *list)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
-  OBJECT *object;
-  GList *s_current;
+  OBJECT *o_current;
+  GList *o_iter;
   GList *other_objects=NULL;
   GList *connected_objects=NULL;
-  OBJECT *o_current=NULL;
 
   /* this is okay if you just hit rotate and have nothing selected */
   if (list == NULL) {
@@ -221,261 +221,90 @@ void o_rotate_90_world(GSCHEM_TOPLEVEL *w_current, GList *list,
     return;
   }
 
-  s_current = list;
-
-  while (s_current != NULL) {
-    object = (OBJECT *) s_current->data;
-
-    if (!object) {
-      fprintf(stderr, _("ERROR: NULL object in o_rotate_90!\n"));
-      return;
-    }
-
-    g_list_free(other_objects);
-    other_objects = NULL;
-    g_list_free(connected_objects);
-    connected_objects = NULL;
-
-    switch(object->type) {
-
-
-      case(OBJ_NET):
-        if (!toplevel->DONT_REDRAW) {
-          o_cue_undraw(w_current, object);
-          o_net_erase(w_current, object);
-          o_line_erase_grips(w_current, object);
-        }
-
-        /* save the other objects */
-        other_objects = s_conn_return_others(other_objects, object);
-        s_conn_remove(toplevel, object);
-
-        o_net_rotate_world(toplevel, centerx, centery, 90, object);
-        s_conn_update_object(toplevel, object);
-        if (!toplevel->DONT_REDRAW) {
-          o_net_draw(w_current, object);
-
-          /* draw the other objects */
-          o_cue_undraw_list(w_current, other_objects);
-          o_cue_draw_list(w_current, other_objects);
-        }
-
-        /* get other connected objects and redraw */
-        connected_objects = s_conn_return_others(connected_objects, object);
-        if (!toplevel->DONT_REDRAW) {
-          o_cue_undraw_list(w_current, connected_objects);
-          o_cue_draw_list(w_current, connected_objects);
-
-          /* finally redraw the cues on the current object */
-          o_cue_draw_single(w_current, object);
-        }
-        break;
-
-      case(OBJ_BUS):
-        if (!toplevel->DONT_REDRAW) {
-          o_cue_undraw(w_current, object);
-          o_bus_erase(w_current, object);
-          o_line_erase_grips(w_current, object);
-        }
-
-        other_objects = s_conn_return_others(other_objects, object);
-        s_conn_remove(toplevel, object);
-
-        o_bus_rotate_world(toplevel, centerx, centery, 90, object);
-        s_conn_update_object(toplevel, object);
-        if (!toplevel->DONT_REDRAW) {
-          o_bus_draw(w_current, object);
-
-          /* draw the other objects */
-          o_cue_undraw_list(w_current, other_objects);
-          o_cue_draw_list(w_current, other_objects);
-        }
-
-        /* get other connected objects and redraw */
-        connected_objects = s_conn_return_others(connected_objects, object);
-        if (!toplevel->DONT_REDRAW) {
-          o_cue_undraw_list(w_current, connected_objects);
-          o_cue_draw_list(w_current, connected_objects);
-
-          /* finally redraw the cues on the current object */
-          o_cue_draw_single(w_current, object);
-        }
-        break;
-
-      case(OBJ_PIN):
-        if (!toplevel->DONT_REDRAW) {
-          o_cue_undraw(w_current, object);
-          o_pin_erase(w_current, object);
-          o_line_erase_grips(w_current, object);
-        }
-
-        other_objects = s_conn_return_others(other_objects, object);
-        s_conn_remove(toplevel, object);
-
-        o_pin_rotate_world(toplevel, centerx, centery, 90, object);
-        s_conn_update_object(toplevel, object);
-        if (!toplevel->DONT_REDRAW) {
-          o_pin_draw(w_current, object);
-
-          /* draw the other objects */
-          o_cue_undraw_list(w_current, other_objects);
-          o_cue_draw_list(w_current, other_objects);
-        }
-
-        /* get other connected objects and redraw */
-        connected_objects = s_conn_return_others(connected_objects, object);
-        if (!toplevel->DONT_REDRAW) {
-          o_cue_undraw_list(w_current, connected_objects);
-          o_cue_draw_list(w_current, connected_objects);
-
-          /* finally redraw the cues on the current object */
-          o_cue_draw_single(w_current, object);
-        }
-        break;
-
-      case(OBJ_COMPLEX):
-        if (!toplevel->DONT_REDRAW) {
-          o_cue_undraw_objects(w_current, object->complex->prim_objs);
-          /* erase the current selection */
-          o_complex_erase(w_current, object);
-        }
-
-        other_objects = s_conn_return_complex_others(other_objects, object);
-
-        /* remove all conn references */
-        o_current = object->complex->prim_objs;
-        while(o_current != NULL) {
-          s_conn_remove(toplevel, o_current);
-          o_current = o_current->next;
-        }
-
-        /* do the rotate */
-        /*toplevel->ADDING_SEL=1; NEWSEL: needed? */
-        o_complex_rotate_world(toplevel, centerx, centery, 90, object);
-        /*toplevel->ADDING_SEL = 0; NEWSEL: needed? */
-        s_conn_update_complex(toplevel, object->complex->prim_objs);
-        if (!toplevel->DONT_REDRAW) {
-          o_complex_draw(w_current, object);
-
-          o_cue_undraw_list(w_current, other_objects);
-          o_cue_draw_list(w_current, other_objects);
-        }
-
-        /* now draw the newly connected objects */
-        connected_objects = s_conn_return_complex_others(connected_objects,
-                                                         object);
-        if (!toplevel->DONT_REDRAW) {
-          o_cue_undraw_list(w_current, connected_objects);
-          o_cue_draw_list(w_current, connected_objects);
-        }
-        break;
-
-      case(OBJ_LINE):
-        if (!toplevel->DONT_REDRAW) {
-          o_line_erase_grips(w_current, object);
-          o_line_erase(w_current, object);
-        }
-
-        o_line_rotate_world(toplevel, centerx, centery,
-                      90, object);
-
-        if (!toplevel->DONT_REDRAW) {
-          o_line_draw(w_current, object);
-        }
-        break;
-
-      case(OBJ_BOX):
-        /* erase the current selection */
-        if (!toplevel->DONT_REDRAW) {
-          o_box_erase_grips(w_current, object);
-          o_box_erase(w_current, object);
-        }
-
-        o_box_rotate_world(toplevel, centerx, centery,
-                     90, object);
-
-        if (!toplevel->DONT_REDRAW) {
-          o_box_draw(w_current, object);
-        }
-        break;
-
-      case(OBJ_PICTURE):
-        /* erase the current selection */
-
-        if (!toplevel->DONT_REDRAW) {
-          o_picture_erase_grips(w_current, object);
-          o_picture_erase(w_current, object);
-        }
-
-        o_picture_rotate_world(toplevel, centerx, centery,
-                     90, object);
+  if (!toplevel->DONT_REDRAW) {
+    o_cue_undraw_list (w_current, list);
+    o_erase_list (w_current, list);
+  }
 
-        if (!toplevel->DONT_REDRAW) {
-          o_picture_draw(w_current, object);
-        }
+  /* Find connected objects, removing each object in turn from the
+   * connection list. We only _really_ want those objects connected
+   * to the selection, not those within in it. The extra redraws
+   * don't _really_ hurt though. */
+  o_iter = list;
+  while (o_iter != NULL) {
+    o_current = o_iter->data;
+    switch (o_current->type) {
+      case OBJ_COMPLEX:
+      case OBJ_PLACEHOLDER:
+        other_objects =
+          s_conn_return_complex_others(other_objects, o_current);
+        s_conn_remove_complex (toplevel, o_current);
         break;
-
-      case(OBJ_CIRCLE):
-        if (!toplevel->DONT_REDRAW) {
-          o_circle_erase_grips(w_current, object);
-          o_circle_erase(w_current, object);
-        }
-
-        o_circle_rotate_world(toplevel, centerx, centery,
-                        90, object);
-
-        if (!toplevel->DONT_REDRAW) {
-          o_circle_draw(w_current, object);
-        }
+      case OBJ_NET:
+      case OBJ_PIN:
+      case OBJ_BUS:
+        other_objects = s_conn_return_others(other_objects, o_current);
+        s_conn_remove (toplevel, o_current);
         break;
+    }
+    o_iter = g_list_next (o_iter);
+  }
 
-      case(OBJ_ARC):
-        if (!toplevel->DONT_REDRAW) {
-          o_arc_erase(w_current, object);
-        }
-
-        o_arc_rotate_world(toplevel, centerx, centery, 90, object);
-        if (!toplevel->DONT_REDRAW) {
-          o_arc_draw(w_current, object);
-        }
+  o_glist_rotate_world( toplevel, centerx, centery, angle, list );
+
+  /* Find connected objects, adding each object in turn back to the
+   * connection list. We only _really_ want those objects connected
+   * to the selection, not those within in it. The extra redraws dont
+   * _really_ hurt though. */
+  o_iter = list;
+  while (o_iter != NULL) {
+    o_current = o_iter->data;
+    switch (o_current->type) {
+      case OBJ_COMPLEX:
+      case OBJ_PLACEHOLDER:
+        s_conn_update_complex(toplevel, o_current->complex->prim_objs);
+        connected_objects =
+          s_conn_return_complex_others(connected_objects, o_current);
         break;
-
-      case(OBJ_TEXT):
-        /* erase the current selection */
-        if (!toplevel->DONT_REDRAW) {
-          o_text_erase(w_current, object);
-        }
-
-        o_text_rotate_world(toplevel, centerx, centery, 90, object);
-
-        if (!toplevel->DONT_REDRAW) {
-          o_text_draw(w_current, object);
-        }
+      case OBJ_NET:
+      case OBJ_PIN:
+      case OBJ_BUS:
+        s_conn_update_object(toplevel, o_current);
+        connected_objects = s_conn_return_others(connected_objects, o_current);
         break;
     }
-    s_current = g_list_next(s_current);
+    o_iter = g_list_next (o_iter);
   }
 
+  if (!toplevel->DONT_REDRAW) {
+    o_draw_list (w_current, list);
+    o_cue_undraw_list(w_current, other_objects);
+    o_cue_draw_list(w_current, other_objects);
+    o_cue_undraw_list(w_current, connected_objects);
+    o_cue_draw_list(w_current, connected_objects);
+    o_cue_draw_list(w_current, list);
+  }
+
+  g_list_free (other_objects);
+  other_objects = NULL;
+  g_list_free (connected_objects);
+  connected_objects = NULL;
+
   /* All objects were rotated. Do a 2nd pass to run the rotate hooks */
   /* Do not run any hooks for simple objects here, like text, since they
      were rotated in the previous pass, and the selection list can contain
      an object and all its attributes (text) */
-  s_current = list;
-  while (s_current != NULL) {
-    object = (OBJECT *) s_current->data;
+  o_iter = list;
+  while (o_iter != NULL) {
+    o_current = o_iter->data;
 
-    if (!object) {
-      fprintf(stderr, _("ERROR: NULL object in o_rotate_90!\n"));
-      return;
-    }
-
-    switch(object->type) {
+    switch(o_current->type) {
       case(OBJ_PIN):
         /* Run the rotate pin hook */
         if (scm_hook_empty_p(rotate_pin_hook) == SCM_BOOL_F &&
-            object != NULL) {
+            o_current != NULL) {
           scm_run_hook(rotate_pin_hook,
-                       scm_cons(g_make_object_smob(toplevel, object),
+                       scm_cons(g_make_object_smob(toplevel, o_current),
                                 SCM_EOL));
         }
         break;
@@ -483,9 +312,9 @@ void o_rotate_90_world(GSCHEM_TOPLEVEL *w_current, GList *list,
       case (OBJ_COMPLEX):
         /* Run the rotate hook */
         if (scm_hook_empty_p(rotate_component_object_hook) == SCM_BOOL_F &&
-            object != NULL) {
+            o_current != NULL) {
           scm_run_hook(rotate_component_object_hook,
-                       scm_cons(g_make_object_smob(toplevel, object),
+                       scm_cons(g_make_object_smob(toplevel, o_current),
                                 SCM_EOL));
         }
         break;
@@ -493,7 +322,7 @@ void o_rotate_90_world(GSCHEM_TOPLEVEL *w_current, GList *list,
         break;
     }
 
-    s_current = g_list_next(s_current);
+    o_iter = g_list_next(o_iter);
   }
 
   /* Don't save the undo state if we are inside an action */
diff --git a/gschem/src/x_event.c b/gschem/src/x_event.c
index 94575d5..c2cec06 100644
--- a/gschem/src/x_event.c
+++ b/gschem/src/x_event.c
@@ -418,10 +418,8 @@ gint x_event_button_pressed(GtkWidget *widget, GdkEventButton *event,
         w_x = snap_grid(toplevel, w_x);
         w_y = snap_grid(toplevel, w_y);
 
-        o_rotate_90_world(
-                    w_current,
-                    geda_list_get_glist( toplevel->page_current->selection_list ),
-                    w_x, w_y);
+        o_rotate_world_update(w_current, w_x, w_y, 90,
+          geda_list_get_glist(toplevel->page_current->selection_list ));
         toplevel->DONT_REDRAW = prev_state;
 
         w_current->inside_action = 0;
@@ -826,7 +824,8 @@ gint x_event_button_released(GtkWidget *widget, GdkEventButton *event,
                        &w_x, &w_y );
         w_x = snap_grid(toplevel, w_x);
         w_y = snap_grid(toplevel, w_y);
-	o_rotate_90_world(w_current, toplevel->page_current->complex_place_list, w_x, w_y );
+        o_rotate_world_update(w_current, w_x, w_y, 90,
+                              toplevel->page_current->complex_place_list );
 	toplevel->DONT_REDRAW = redraw_state;
 	w_current->rotated_inside ++;	
 	w_current->event_state = prev_state;
diff --git a/libgeda/include/prototype.h b/libgeda/include/prototype.h
index 96df3bb..f662d88 100644
--- a/libgeda/include/prototype.h
+++ b/libgeda/include/prototype.h
@@ -196,6 +196,7 @@ void o_recalc_object_glist(TOPLEVEL *toplevel, GList *object_glist);
 void o_set_line_options(TOPLEVEL *toplevel, OBJECT *o_current, OBJECT_END end, OBJECT_TYPE type, int width, int length, int space);
 void o_set_fill_options(TOPLEVEL *toplevel, OBJECT *o_current, OBJECT_FILLING type, int width, int pitch1, int angle1, int pitch2, int angle2);
 void o_translate_world (TOPLEVEL *toplevel, gint dx, gint dy, OBJECT *object);
+void o_rotate_world(TOPLEVEL *toplevel, int world_centerx, int world_centery, int angle, OBJECT *object);
 /* o_box_basic.c */
 OBJECT *o_box_add(TOPLEVEL *toplevel, OBJECT *object_list, char type, int color, int x1, int y1, int x2, int y2);
 OBJECT *o_box_copy(TOPLEVEL *toplevel, OBJECT *list_tail, OBJECT *o_current);
@@ -291,7 +292,7 @@ void o_complex_unset_color(OBJECT *complex);
 void o_complex_unset_color_single(OBJECT *o_current);
 void o_complex_set_saved_color_only(OBJECT *complex, int color);
 OBJECT *o_complex_return_nth_pin(OBJECT *o_list, int counter);
-void o_complex_rotate_lowlevel(TOPLEVEL *toplevel, int world_centerx, int world_centery, int angle, OBJECT *object);
+void o_complex_rotate_world(TOPLEVEL *toplevel, int world_centerx, int world_centery, int angle, OBJECT *object);
 void o_complex_mirror_lowlevel(TOPLEVEL *toplevel, int world_centerx, int world_centery, OBJECT *object);
 OBJECT *o_complex_return_pin_object(OBJECT *object, char *pin);
 int  o_complex_count_pins(OBJECT *object);
@@ -331,6 +332,8 @@ void o_list_delete(TOPLEVEL *toplevel, OBJECT *list, OBJECT *delete);
 void o_list_delete_rest(TOPLEVEL *toplevel, OBJECT *list);
 void o_list_translate_world(TOPLEVEL *toplevel, int x, int y, OBJECT *list);
 void o_glist_translate_world(TOPLEVEL *toplevel, int x, int y, GList *list);
+void o_list_rotate_world(TOPLEVEL *toplevel, int x, int y, int angle, OBJECT *list);
+void o_glist_rotate_world(TOPLEVEL *toplevel, int x, int y, int angle, GList *list);
 
 /* o_net_basic.c */
 void world_get_net_bounds(TOPLEVEL *toplevel, OBJECT *object, int *left, int *top, int *right, int *bottom);
@@ -425,7 +428,6 @@ void o_text_print_text_height(FILE *fp, int size);
 void o_text_print_text_height_full(FILE *fp, char *string, int size);
 void o_text_print_text_string(FILE *fp, char *string, int unicode_count, gunichar *unicode_table);
 void o_text_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current, int origin_x, int origin_y, int unicode_count, gunichar *unicode_table);
-void o_text_rotate_lowlevel(TOPLEVEL *toplevel, int world_centerx, int world_centery, int angle, OBJECT *object);
 void o_text_rotate_world(TOPLEVEL *toplevel, int world_centerx, int world_centery, int angle, OBJECT *object);
 void o_text_mirror_world(TOPLEVEL *toplevel, int world_centerx, int world_centery, OBJECT *object);
 
diff --git a/libgeda/src/o_basic.c b/libgeda/src/o_basic.c
index e55e161..b84a7a7 100644
--- a/libgeda/src/o_basic.c
+++ b/libgeda/src/o_basic.c
@@ -297,3 +297,41 @@ void o_translate_world (TOPLEVEL *toplevel, gint dx, gint dy, OBJECT *object)
     (*func) (toplevel, dx, dy, object);
   }
 }
+
+
+/*! \brief Rotates an object in world coordinates
+ *  \par Function Description
+ *  This function rotates the object <B>object</B> about the coordinates
+ *  <B>world_centerx</B> and <B>world_centery</B>, by <B>angle</B>degrees.
+ *
+ *  \param [in] toplevel The toplevel environment.
+ *  \param [in] world_centerx  X coordinate of rotation center (world coords)
+ *  \param [in] world_centery  Y coordinate of rotation center (world coords)
+ *  \param [in] angle          Angle of rotation (degrees)
+ *  \param [in] object         The object to rotate.
+ */
+void o_rotate_world (TOPLEVEL *toplevel, int world_centerx, int world_centery, int angle, OBJECT *object)
+{
+  void (*func) (TOPLEVEL*, int, int, int, OBJECT*) = NULL;
+
+  switch (object->type) {
+      case OBJ_HEAD:    /* Do nothing for head nodes */   break;
+      case OBJ_LINE:    func = o_line_rotate_world;       break;
+      case OBJ_NET:     func = o_net_rotate_world;        break;
+      case OBJ_BUS:     func = o_bus_rotate_world;        break;
+      case OBJ_BOX:     func = o_box_rotate_world;        break;
+      case OBJ_PICTURE: func = o_picture_rotate_world;    break;
+      case OBJ_CIRCLE:  func = o_circle_rotate_world;     break;
+      case OBJ_PLACEHOLDER:
+      case OBJ_COMPLEX: func = o_complex_rotate_world;    break;
+      case OBJ_TEXT:    func = o_text_rotate_world;       break;
+      case OBJ_PIN:     func = o_pin_rotate_world;        break;
+      case OBJ_ARC:     func = o_arc_rotate_world;        break;
+      default:
+        g_assert_not_reached ();
+  }
+
+  if (func != NULL) {
+    (*func) (toplevel, world_centerx, world_centery, angle, object);
+  }
+}
diff --git a/libgeda/src/o_complex_basic.c b/libgeda/src/o_complex_basic.c
index e0b478b..c8ca460 100644
--- a/libgeda/src/o_complex_basic.c
+++ b/libgeda/src/o_complex_basic.c
@@ -602,9 +602,9 @@ OBJECT *o_complex_add(TOPLEVEL *toplevel, OBJECT *object_list,
   if (loaded_normally == TRUE) {
     if (mirror) {
       o_complex_mirror_lowlevel(toplevel, x, y, new_node);
-    } 
-    
-    o_complex_rotate_lowlevel(toplevel, x, y, angle, new_node);
+    }
+
+    o_list_rotate_world(toplevel, 0, 0, angle, prim_objs);
     o_list_translate_world(toplevel, x, y, prim_objs);
 
     if (!toplevel->ADDING_SEL) {
@@ -1241,79 +1241,45 @@ OBJECT *o_complex_return_nth_pin(OBJECT *o_list, int counter)
   return(NULL);
 }
 
-/*! \brief
+
+/*! \todo Finish function documentation!!!
+ *  \brief
  *  \par Function Description
  *
  */
-/* pass in top level object */
-void o_complex_rotate_lowlevel(TOPLEVEL *toplevel, int world_centerx,
-                               int world_centery,
-                               int angle,
-                               OBJECT *object)
+void o_complex_rotate_world(TOPLEVEL *toplevel,
+                            int centerx, int centery,
+                            int angle, OBJECT *object)
 {
-  OBJECT *o_current=NULL;
-
-#if DEBUG 
-  printf("------- a %d\n", angle);
-#endif
-
-  g_return_if_fail(object != NULL);
-  g_return_if_fail(((object->type == OBJ_COMPLEX) ||
-		    (object->type == OBJ_PLACEHOLDER)));
-  g_return_if_fail(object->complex != NULL);
-
-
-  /* do individual complex objects */
-  o_current = object->complex->prim_objs;
-
-  while ( o_current != NULL ) {
-    switch(o_current->type) {
-      case(OBJ_LINE):
-        o_line_rotate_world(toplevel, 0, 0, angle, o_current);
-        break;
+  int x, y;
+  int newx, newy;
 
-      case(OBJ_NET):
-        o_net_rotate_world(toplevel, 0, 0, angle, o_current);
-        break;
-
-      case(OBJ_BUS):
-        o_bus_rotate_world(toplevel, 0, 0, angle, o_current);
-        break;
-	
-      case(OBJ_BOX):
-        o_box_rotate_world(toplevel, 0, 0, angle, o_current);
-        break;
+  g_assert(object != NULL);
+  g_assert(((object->type == OBJ_COMPLEX) ||
+            (object->type == OBJ_PLACEHOLDER)));
 
-      case(OBJ_PICTURE):
-        o_picture_rotate_world(toplevel, 0, 0, angle, o_current);
-        break;
+  x = object->complex->x + (-centerx);
+  y = object->complex->y + (-centery);
 
-      case(OBJ_CIRCLE):
-        o_circle_rotate_world(toplevel, 0, 0, angle, o_current);
-        break;
+  rotate_point_90(x, y, angle, &newx, &newy);
 
-      case(OBJ_PIN):
-        o_pin_rotate_world(toplevel, 0, 0, angle, o_current);
-        break;
+  x = newx + (centerx);
+  y = newy + (centery);
 
-      case(OBJ_ARC):
-        o_arc_rotate_world(toplevel, 0, 0, angle, o_current);
-        break;
+  o_complex_translate_world(toplevel,
+                            -object->complex->x,
+                            -object->complex->y, object);
+  o_list_rotate_world(toplevel, 0, 0, angle, object->complex->prim_objs);
 
-      case(OBJ_COMPLEX):
-      case(OBJ_PLACEHOLDER):
-        o_complex_rotate_lowlevel(toplevel, 0, 0, angle, o_current);
-        break; 
+  object->complex->x = 0;
+  object->complex->y = 0;
 
-      case(OBJ_TEXT):
-        o_text_rotate_world(toplevel, 0, 0, angle, o_current);
-        break;
+  o_complex_translate_world(toplevel, x, y, object);
 
-    }
-    o_current=o_current->next;
-  }
+  object->complex->angle = ( object->complex->angle + angle ) % 360;
 }
 
+
 /*! \brief
  *  \par Function Description
  *
diff --git a/libgeda/src/o_list.c b/libgeda/src/o_list.c
index d10a506..eaa4d63 100644
--- a/libgeda/src/o_list.c
+++ b/libgeda/src/o_list.c
@@ -452,3 +452,36 @@ void o_glist_translate_world (TOPLEVEL *toplevel, int x, int y, GList *list)
   }
 }
 
+
+
+/*! \todo Finish function description!!!
+ *  \brief
+ *  \par Function Description
+ */
+void o_list_rotate_world (TOPLEVEL *toplevel, int x, int y, int angle, OBJECT *list)
+{
+  OBJECT *o_current = list;
+
+  while ( o_current != NULL ) {
+    o_rotate_world (toplevel, x, y, angle, o_current);
+    o_current = o_current->next;
+  }
+}
+
+
+/*! \todo Finish function description!!!
+ *  \brief
+ *  \par Function Description
+ */
+void o_glist_rotate_world (TOPLEVEL *toplevel, int x, int y, int angle, GList *list)
+{
+  GList *iter = list;
+  OBJECT *o_current;
+
+  while ( iter != NULL ) {
+    o_current = (OBJECT *)iter->data;
+    o_rotate_world (toplevel, x, y, angle, o_current);
+    iter = g_list_next (iter);
+  }
+}
+
diff --git a/libgeda/src/o_text_basic.c b/libgeda/src/o_text_basic.c
index 5b8c679..16cf56a 100644
--- a/libgeda/src/o_text_basic.c
+++ b/libgeda/src/o_text_basic.c
@@ -655,10 +655,8 @@ OBJECT *o_text_create_string(TOPLEVEL *toplevel, OBJECT *object_list,
 	  /* do this if you want to stack chars */
 	  /* we don't want to do that for now */
 	  /* Rotate and translate the character to its world position */
-	  o_text_rotate_lowlevel(toplevel, x, y, angle, start_of_char);
-	  o_list_translate_world(toplevel,
-	                         x_offset, y_offset,
-	                         start_of_char);
+	  o_list_rotate_world(toplevel, 0, 0, angle, start_of_char);
+	  o_list_translate_world(toplevel, x_offset, y_offset, start_of_char);
 	  
 	  /* Reset the escapes counter after being processed. Otherwise, 
 	     if the next character is also a backslash, it will
@@ -1752,35 +1750,6 @@ void o_text_print(TOPLEVEL *toplevel, FILE *fp, OBJECT *o_current,
   if (value) g_free(value);
 }
 
-/*! \todo Finish function documentation!!!
- *  \brief
- *  \par Function Description
- *
- */
-/* takes world coords as the center point as well as a true angle */
-void o_text_rotate_lowlevel(TOPLEVEL *toplevel, int world_centerx,
-			    int world_centery, int angle, OBJECT *object)
-{
-  OBJECT *o_current=NULL;
-
-  /* translate object to origin */
-  /* o_text_translate_world(toplevel, -world_centerx, -world_centery, object);*/
-
-  /* rotate_point_90(object->text->x, object->text->y, &newx, &newy);*/
-	
-  /* o_text_translate_world(toplevel, world_centerx, world_centery, object);*/
-	
-  o_current = object;
-
-  while ( o_current != NULL ) {
-    switch(o_current->type) {
-      case(OBJ_LINE):
-        o_line_rotate_world(toplevel, 0, 0, angle, o_current);
-        break;
-    }
-    o_current=o_current->next;
-  }
-}
 
 /*! \todo Finish function documentation!!!
  *  \brief
@@ -1789,30 +1758,24 @@ void o_text_rotate_lowlevel(TOPLEVEL *toplevel, int world_centerx,
  */
 void o_text_rotate_world(TOPLEVEL *toplevel,
                          int world_centerx, int world_centery,
-                        int angle, OBJECT *object)
+                         int angle, OBJECT *object)
 {
-  int newx, newy;
-  int origx, origy;
   int x, y;
-	
-  origx = object->text->x;
-  origy = object->text->y;
+  int newx, newy;
+
+  g_assert(object != NULL);
+  g_assert(object->type == OBJ_TEXT);
 
   object->text->angle = ( object->text->angle + angle ) % 360;
 
-#if DEBUG 
-  printf("rotating text angle: %d\n", angle);
-  printf("final text angle: %d\n",  object->text->angle);
-#endif
+  x = object->text->x + (-world_centerx);
+  y = object->text->y + (-world_centery);
 
-  x = origx + (-world_centerx);
-  y = origy + (-world_centery);
-	
   rotate_point_90(x, y, angle, &newx, &newy);
 
   x = newx + (world_centerx);
   y = newy + (world_centery);
-	
+
   o_text_translate_world(toplevel, x-object->text->x, y-object->text->y, object);
 
   o_text_recreate(toplevel, object);




_______________________________________________
geda-cvs mailing list
geda-cvs@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-cvs