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

gEDA-cvs: gaf.git: branch: master updated (1.5.0-20080706-57-g0eea758)



The branch, master has been updated
       via  0eea7587957ef3e01c2d1942d7bc6c940c237e4a (commit)
       via  1e4eb30f7cab3f3cb9e49478ed05d24cba99858b (commit)
       via  aa7fb5c523e57cf7e3bbb4224e0ffbbf524ab95e (commit)
       via  e931091e28f90e7bd0f755ee30665cc5b7461b74 (commit)
      from  d0d18117a483029a61077a792203df5bd1a7f22a (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/gschem_struct.h |    3 -
 gschem/include/prototype.h     |   23 +--
 gschem/src/Makefile.am         |    2 +-
 gschem/src/gschem_toplevel.c   |    2 -
 gschem/src/i_callbacks.c       |   30 +---
 gschem/src/o_basic.c           |   27 +--
 gschem/src/o_buffer.c          |  145 +++------------
 gschem/src/o_complex.c         |  329 +++++++++++----------------------
 gschem/src/o_copy.c            |  406 ++++------------------------------------
 gschem/src/o_move.c            |   14 +-
 gschem/src/o_place.c           |  179 ++++++++++++++++++
 gschem/src/o_select.c          |   21 +--
 gschem/src/o_text.c            |  168 ++---------------
 gschem/src/x_compselect.c      |   11 +-
 gschem/src/x_dialog.c          |   55 +++---
 gschem/src/x_event.c           |   87 +++------
 libgeda/include/struct.h       |    3 +-
 libgeda/src/s_page.c           |   13 +-
 18 files changed, 465 insertions(+), 1053 deletions(-)
 create mode 100644 gschem/src/o_place.c


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

commit 0eea7587957ef3e01c2d1942d7bc6c940c237e4a
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Tue Jul 29 03:05:11 2008 +0100

    Remove un-necessary variable w_current->rotated_inside.
    
    The rotation of placed objects is always started at zero degrees, and
    since the rework of the copy / place code, is done on the fly. Remove
    the old code to track the angle rotated during placement.
    need to track the rotation angle

:100644 100644 149deb4... 1d5fa93... M	gschem/include/gschem_struct.h
:100644 100644 95907c5... c05c933... M	gschem/src/gschem_toplevel.c
:100644 100644 ef1459a... fe3038d... M	gschem/src/o_move.c
:100644 100644 b357dd8... 184e285... M	gschem/src/x_event.c

commit 1e4eb30f7cab3f3cb9e49478ed05d24cba99858b
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Tue Jul 29 03:05:02 2008 +0100

    Remove un-necessary variable w_current->complex_rotate.
    
    The rotation of placed objects is always started at zero degrees, and
    since the rework of the copy / place code, is done on the fly. Remove
    the old code to track the angle rotated during placement.
    need to track the rotation angle

:100644 100644 8a5179f... 149deb4... M	gschem/include/gschem_struct.h
:100644 100644 a108247... 95907c5... M	gschem/src/gschem_toplevel.c
:100644 100644 ff2875a... ce7ba56... M	gschem/src/o_complex.c
:100644 100644 ec3641c... de4fb64... M	gschem/src/o_text.c
:100644 100644 1603717... b357dd8... M	gschem/src/x_event.c

commit aa7fb5c523e57cf7e3bbb4224e0ffbbf524ab95e
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Tue Jul 29 03:04:24 2008 +0100

    Consolidate specialised o_..._rubber...() and o_..._rubber...__xor()
    
    Since these operations now use the same place list, we can share code.

:100644 100644 ccab460... 482a799... M	gschem/include/prototype.h
:100644 100644 45c1140... fe866f5... M	gschem/src/i_callbacks.c
:100644 100644 1bac51a... 3adf35e... M	gschem/src/o_basic.c
:100644 100644 f7eb287... 3ca1a56... M	gschem/src/o_buffer.c
:100644 100644 690ce08... ff2875a... M	gschem/src/o_complex.c
:100644 100644 66c9c04... aafa430... M	gschem/src/o_copy.c
:100644 100644 62d45fc... ec3641c... M	gschem/src/o_text.c
:100644 100644 669c869... 9050f73... M	gschem/src/x_compselect.c
:100644 100644 ef537a8... 1603717... M	gschem/src/x_event.c

commit e931091e28f90e7bd0f755ee30665cc5b7461b74
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Tue Jul 29 03:00:59 2008 +0100

    gschem: Combine code for operations which handle placement of OBJECTs.
    
    Replaces duplicated code related to component / text placement, copying /
    multi-copying objects and pasting from buffers with a common set of
    routines in the new file, gschem/src/o_place.c
    
    This refactoring lays the foundation to allow rotatation / mirroring whilst
    performing any kind of place action, without extensive duplicate code.
    
    All of the above operations now use a new PAGE variable, "place_list",
    rather than previous specialised variants complex_place_list, and
    attrib_place_list. Paste-buffer contents are copied into the place list,
    rather than placing directly from the paste-buffer, ensuring that any
    rotation / mirroring of the place-buffer does not change the paste-buffer.
    
    Helper functions, o_text_prepare_place() and o_complex_prepare_place() are
    added to load the place list with appropriate text, or a symbol. These are
    passed as arguments to the respective functions, avoiding the use of state
    stored in toplevel->current_attribute and toplevel->internal_symbol_name.

:100644 100644 743e725... ccab460... M	gschem/include/prototype.h
:100644 100644 8072874... 0a01fa1... M	gschem/src/Makefile.am
:100644 100644 5547090... 45c1140... M	gschem/src/i_callbacks.c
:100644 100644 37d6688... 1bac51a... M	gschem/src/o_basic.c
:100644 100644 3c73532... f7eb287... M	gschem/src/o_buffer.c
:100644 100644 0962d9b... 690ce08... M	gschem/src/o_complex.c
:100644 100644 c423734... 66c9c04... M	gschem/src/o_copy.c
:100644 100644 a86dd71... ef1459a... M	gschem/src/o_move.c
:000000 100644 0000000... 6637baf... A	gschem/src/o_place.c
:100644 100644 7875866... ccf448a... M	gschem/src/o_select.c
:100644 100644 83f8e97... 62d45fc... M	gschem/src/o_text.c
:100644 100644 f7ff80b... 669c869... M	gschem/src/x_compselect.c
:100644 100644 fa580b5... eb2f45e... M	gschem/src/x_dialog.c
:100644 100644 5d276ed... ef537a8... M	gschem/src/x_event.c
:100644 100644 be99ef0... 6aaf3c0... M	libgeda/include/struct.h
:100644 100644 bbec414... d79c1b9... M	libgeda/src/s_page.c

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

commit 0eea7587957ef3e01c2d1942d7bc6c940c237e4a
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Tue Jul 29 03:05:11 2008 +0100

    Remove un-necessary variable w_current->rotated_inside.
    
    The rotation of placed objects is always started at zero degrees, and
    since the rework of the copy / place code, is done on the fly. Remove
    the old code to track the angle rotated during placement.
    need to track the rotation angle

diff --git a/gschem/include/gschem_struct.h b/gschem/include/gschem_struct.h
index 149deb4..1d5fa93 100644
--- a/gschem/include/gschem_struct.h
+++ b/gschem/include/gschem_struct.h
@@ -94,8 +94,6 @@ struct st_gschem_toplevel {
   int magnetic_wx, magnetic_wy;         /* Position of the magnetic marker*/
   int distance;
   int inside_action;                    /* Are we doing an action? */
-  int rotated_inside;                   /* Was the selection rotated
-                                           inside an action? */
   int rubber_visible;                   /* Are there any rubber lines on
 					   the screen? */
   int magnetic_visible;                 /* Is the magnetic marker visible */
diff --git a/gschem/src/gschem_toplevel.c b/gschem/src/gschem_toplevel.c
index 95907c5..c05c933 100644
--- a/gschem/src/gschem_toplevel.c
+++ b/gschem/src/gschem_toplevel.c
@@ -119,7 +119,6 @@ GSCHEM_TOPLEVEL *gschem_toplevel_new ()
   w_current->magnetic_wx = -1;
   w_current->magnetic_wy = -1;
   w_current->inside_action = 0;
-  w_current->rotated_inside = 0;
   w_current->rubber_visible = 0;
   w_current->magnetic_visible = 0;
   w_current->net_direction = 0;
diff --git a/gschem/src/o_move.c b/gschem/src/o_move.c
index ef1459a..fe3038d 100644
--- a/gschem/src/o_move.c
+++ b/gschem/src/o_move.c
@@ -289,7 +289,6 @@ void o_move_cancel (GSCHEM_TOPLEVEL *w_current)
   g_list_free(w_current->toplevel->page_current->place_list);
   w_current->toplevel->page_current->place_list = NULL;
   o_undo_callback(w_current, UNDO_ACTION);
-  w_current->rotated_inside = 0;
 
   s_stretch_remove_most(toplevel, toplevel->page_current->stretch_head);
   toplevel->page_current->stretch_tail = toplevel->page_current->stretch_head;
diff --git a/gschem/src/x_event.c b/gschem/src/x_event.c
index b357dd8..184e285 100644
--- a/gschem/src/x_event.c
+++ b/gschem/src/x_event.c
@@ -139,7 +139,6 @@ gint x_event_button_pressed(GtkWidget *widget, GdkEventButton *event,
 
       case(STARTCOPY):
         if (o_select_selected(w_current)) {
-          w_current->rotated_inside = 0;
           o_copy_start(w_current, w_x, w_y);
           w_current->event_state = COPY;
           w_current->inside_action = 1;
@@ -148,7 +147,6 @@ gint x_event_button_pressed(GtkWidget *widget, GdkEventButton *event,
 
       case(STARTMCOPY):
         if (o_select_selected(w_current)) {
-          w_current->rotated_inside = 0;
           o_copy_start(w_current, w_x, w_y);
           w_current->event_state = MCOPY;
           w_current->inside_action = 1;
@@ -157,7 +155,6 @@ gint x_event_button_pressed(GtkWidget *widget, GdkEventButton *event,
 
       case(STARTMOVE):
         if (o_select_selected(w_current)) {
-          w_current->rotated_inside = 0;
           o_move_start(w_current, w_x, w_y);
           w_current->event_state = MOVE;
           w_current->inside_action = 1;
@@ -653,7 +650,6 @@ gint x_event_button_released(GtkWidget *widget, GdkEventButton *event,
                                          w_current->first_wy, 90,
                               toplevel->page_current->place_list );
         toplevel->DONT_REDRAW = redraw_state;
-        w_current->rotated_inside ++;
         w_current->event_state = prev_state;
 
         o_move_rubbermove_xor (w_current, TRUE);
@@ -825,7 +821,6 @@ gint x_event_motion(GtkWidget *widget, GdkEventMotion *event,
       break;
     } else {
       /* Start the object movement */
-      w_current->rotated_inside = 0;
       o_move_start(w_current, w_x, w_y);
       w_current->event_state = ENDMOVE;
       w_current->inside_action = 1;

commit 1e4eb30f7cab3f3cb9e49478ed05d24cba99858b
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Tue Jul 29 03:05:02 2008 +0100

    Remove un-necessary variable w_current->complex_rotate.
    
    The rotation of placed objects is always started at zero degrees, and
    since the rework of the copy / place code, is done on the fly. Remove
    the old code to track the angle rotated during placement.
    need to track the rotation angle

diff --git a/gschem/include/gschem_struct.h b/gschem/include/gschem_struct.h
index 8a5179f..149deb4 100644
--- a/gschem/include/gschem_struct.h
+++ b/gschem/include/gschem_struct.h
@@ -119,7 +119,6 @@ struct st_gschem_toplevel {
   int ALTKEY;                           /* alt key pressed? */
   int doing_pan;                        /* mouse pan status flag */
   int buffer_number;                    /* current paste buffer in use */
-  int complex_rotate;                   /* Rotation of an object being placed */
   void (*last_callback)();              /* Last i_call* cmd executed */
 
   /* ------------------ */
diff --git a/gschem/src/gschem_toplevel.c b/gschem/src/gschem_toplevel.c
index a108247..95907c5 100644
--- a/gschem/src/gschem_toplevel.c
+++ b/gschem/src/gschem_toplevel.c
@@ -143,7 +143,6 @@ GSCHEM_TOPLEVEL *gschem_toplevel_new ()
   w_current->ALTKEY     = 0;
   w_current->doing_pan = 0;
   w_current->buffer_number = 0;
-  w_current->complex_rotate = 0;
   w_current->last_callback = NULL;
 
   /* ------------------ */
diff --git a/gschem/src/o_complex.c b/gschem/src/o_complex.c
index ff2875a..ce7ba56 100644
--- a/gschem/src/o_complex.c
+++ b/gschem/src/o_complex.c
@@ -79,7 +79,6 @@ void o_complex_prepare_place(GSCHEM_TOPLEVEL *w_current, const char *sym_name)
   OBJECT *o_current;
   OBJECT *o_start;
   char *buffer;
-  int i, temp;
   const CLibSymbol *sym;
   int redraw_state;
 
@@ -147,14 +146,6 @@ void o_complex_prepare_place(GSCHEM_TOPLEVEL *w_current, const char *sym_name)
     }
   }
 
-  /* Rotate the place list if we start with any accumulated rotation */
-  if (w_current->complex_rotate) {
-    temp = w_current->complex_rotate / 90;
-    for (i = 0; i < temp; i++) {
-      o_place_rotate(w_current);
-    }
-  }
-
   /* Run the complex place list changed hook without redrawing */
   /* since the place list is going to be redrawn afterwards */
   redraw_state = toplevel->DONT_REDRAW;
diff --git a/gschem/src/o_text.c b/gschem/src/o_text.c
index ec3641c..de4fb64 100644
--- a/gschem/src/o_text.c
+++ b/gschem/src/o_text.c
@@ -279,7 +279,6 @@ void o_text_draw_xor(GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_curre
 void o_text_prepare_place(GSCHEM_TOPLEVEL *w_current, char *text)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
-  int temp, i;
 
   /* Insert the new object into the buffer at world coordinates (0,0).
    * It will be translated to the mouse coordinates during placement. */
@@ -305,13 +304,6 @@ void o_text_prepare_place(GSCHEM_TOPLEVEL *w_current, char *text)
                              /* visibility is set when you create the object */
                              VISIBLE, SHOW_NAME_VALUE));
 
-  if (w_current->complex_rotate) {
-    temp = w_current->complex_rotate / 90;
-    for (i = 0; i < temp; i++) {
-      o_place_rotate(w_current);
-    }
-  }
-
   w_current->inside_action = 1;
   i_set_state(w_current, DRAWTEXT);
 }
diff --git a/gschem/src/x_event.c b/gschem/src/x_event.c
index 1603717..b357dd8 100644
--- a/gschem/src/x_event.c
+++ b/gschem/src/x_event.c
@@ -619,9 +619,6 @@ gint x_event_button_released(GtkWidget *widget, GdkEventButton *event,
       if (w_current->event_state == ENDCOMP) {
         o_place_rubberplace_xor (w_current, FALSE);
 
-        w_current->complex_rotate =
-          (w_current->complex_rotate + 90) % 360;
-
         o_place_rotate(w_current);
 
         /* Run the complex place list changed hook without redrawing */
@@ -636,9 +633,6 @@ gint x_event_button_released(GtkWidget *widget, GdkEventButton *event,
       } else if (w_current->event_state == ENDTEXT) {
         o_place_rubberplace_xor (w_current, FALSE);
 
-        w_current->complex_rotate =
-        (w_current->complex_rotate + 90) % 360;
-
         o_place_rotate(w_current);
 
         o_place_rubberplace_xor (w_current, TRUE);
@@ -893,14 +887,12 @@ gint x_event_motion(GtkWidget *widget, GdkEventMotion *event,
     break;
 
     case(DRAWCOMP):
-    w_current->complex_rotate = 0; /* reset to known state */
     o_complex_start(w_current, w_x, w_y);
     w_current->event_state = ENDCOMP;
     w_current->inside_action = 1;
     break;
 
     case(DRAWTEXT):
-    w_current->complex_rotate = 0; /* reset to known state */
     o_text_start(w_current, w_x, w_y);
     w_current->event_state = ENDTEXT;
     w_current->inside_action = 1;

commit aa7fb5c523e57cf7e3bbb4224e0ffbbf524ab95e
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Tue Jul 29 03:04:24 2008 +0100

    Consolidate specialised o_..._rubber...() and o_..._rubber...__xor()
    
    Since these operations now use the same place list, we can share code.

diff --git a/gschem/include/prototype.h b/gschem/include/prototype.h
index ccab460..482a799 100644
--- a/gschem/include/prototype.h
+++ b/gschem/include/prototype.h
@@ -513,8 +513,6 @@ void o_box_erase_grips(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current);
 void o_buffer_copy(GSCHEM_TOPLEVEL *w_current, int buf_num);
 void o_buffer_cut(GSCHEM_TOPLEVEL *w_current, int buf_num);
 void o_buffer_paste_start(GSCHEM_TOPLEVEL *w_current, int x, int y, int buf_num);
-void o_buffer_paste_rubberpaste(GSCHEM_TOPLEVEL *w_current, int x, int y);
-void o_buffer_paste_rubberpaste_xor(GSCHEM_TOPLEVEL *w_current, int drawing);
 void o_buffer_init(void);
 void o_buffer_free(GSCHEM_TOPLEVEL *w_current);
 /* o_bus.c */
@@ -547,15 +545,11 @@ void o_complex_prepare_place(GSCHEM_TOPLEVEL *w_current, const char *sym_name);
 void o_complex_start(GSCHEM_TOPLEVEL *w_current, int x, int y);
 void o_complex_place_changed_run_hook(GSCHEM_TOPLEVEL *w_current);
 void o_complex_end(GSCHEM_TOPLEVEL *w_current, int x, int y, int continue_placing);
-void o_complex_rubbercomplex(GSCHEM_TOPLEVEL *w_current, int x, int y);
-void o_complex_rubbercomplex_xor(GSCHEM_TOPLEVEL *w_current, int drawing);
 void o_complex_translate_all(GSCHEM_TOPLEVEL *w_current, int offset);
 /* o_copy.c */
 void o_copy_start(GSCHEM_TOPLEVEL *w_current, int x, int y);
 void o_copy_end(GSCHEM_TOPLEVEL *w_current);
 void o_copy_multiple_end(GSCHEM_TOPLEVEL *w_current);
-void o_copy_rubbercopy(GSCHEM_TOPLEVEL *w_current, int x, int y);
-void o_copy_rubbercopy_xor(GSCHEM_TOPLEVEL *w_current, int drawing);
 /* o_cue.c */
 void o_cue_redraw_all(GSCHEM_TOPLEVEL *w_current, OBJECT *head, gboolean draw_selected);
 void o_cue_draw_lowlevel(GSCHEM_TOPLEVEL *w_current, OBJECT *object, int whichone);
@@ -714,8 +708,6 @@ void o_text_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current);
 void o_text_draw_xor(GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_current);
 void o_text_prepare_place(GSCHEM_TOPLEVEL *w_current, char *text);
 void o_text_start(GSCHEM_TOPLEVEL *w_current, int x, int y);
-void o_text_rubberattrib(GSCHEM_TOPLEVEL *w_current, int x, int y);
-void o_text_rubberattrib_xor(GSCHEM_TOPLEVEL *w_current, int drawing);
 void o_text_edit(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current);
 void o_text_edit_end(GSCHEM_TOPLEVEL *w_current, char *string, int len, int text_size, int text_alignment);
 void o_text_change(GSCHEM_TOPLEVEL *w_current, OBJECT *object, char *string, int visibility, int show);
diff --git a/gschem/src/i_callbacks.c b/gschem/src/i_callbacks.c
index 45c1140..fe866f5 100644
--- a/gschem/src/i_callbacks.c
+++ b/gschem/src/i_callbacks.c
@@ -3526,7 +3526,7 @@ DEFINE_I_CALLBACK(cancel)
     /* user hit escape key when placing components */
 
     /* Undraw any XOR outline of the place list */
-    o_complex_rubbercomplex_xor(w_current, FALSE);
+    o_place_rubberplace_xor(w_current, FALSE);
 
     /* De-select the lists in the component selector */
     x_compselect_deselect (w_current);
diff --git a/gschem/src/o_basic.c b/gschem/src/o_basic.c
index 1bac51a..3adf35e 100644
--- a/gschem/src/o_basic.c
+++ b/gschem/src/o_basic.c
@@ -67,19 +67,10 @@ void o_redraw_all(GSCHEM_TOPLEVEL *w_current)
 
       case(ENDCOPY):
       case(ENDMCOPY):
-        o_copy_rubbercopy_xor (w_current, TRUE);
-        break;
-
       case(ENDCOMP):
-        o_complex_rubbercomplex_xor (w_current, TRUE);
-        break;
-
       case(ENDTEXT):
-        o_text_rubberattrib_xor (w_current, TRUE);
-        break;
-
       case(ENDPASTE):
-        o_buffer_paste_rubberpaste_xor (w_current, TRUE);
+        o_place_rubberplace_xor (w_current, TRUE);
         break;
 
       case(STARTDRAWNET):
diff --git a/gschem/src/o_buffer.c b/gschem/src/o_buffer.c
index f7eb287..3ca1a56 100644
--- a/gschem/src/o_buffer.c
+++ b/gschem/src/o_buffer.c
@@ -151,28 +151,6 @@ void o_buffer_paste_start(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y,
  *  \par Function Description
  *
  */
-void o_buffer_paste_rubberpaste (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
-{
-  o_place_rubberplace (w_current, w_x, w_y);
-}
-
-
-/*! \todo Finish function documentation!!!
- *  \brief
- *  \par Function Description
- *
- */
-void o_buffer_paste_rubberpaste_xor(GSCHEM_TOPLEVEL *w_current, int drawing)
-{
-  o_place_rubberplace_xor (w_current, drawing);
-}
-
-
-/*! \todo Finish function documentation!!!
- *  \brief
- *  \par Function Description
- *
- */
 void o_buffer_init(void)
 {
   int i;
diff --git a/gschem/src/o_complex.c b/gschem/src/o_complex.c
index 690ce08..ff2875a 100644
--- a/gschem/src/o_complex.c
+++ b/gschem/src/o_complex.c
@@ -251,28 +251,6 @@ void o_complex_end(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y, int continue_pl
  *  \brief
  *  \par Function Description
  *
- */
-void o_complex_rubbercomplex (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
-{
-  o_place_rubberplace (w_current, w_x, w_y);
-}
-
-
-/*! \todo Finish function documentation!!!
- *  \brief
- *  \par Function Description
- *
- */
-void o_complex_rubbercomplex_xor (GSCHEM_TOPLEVEL *w_current, int drawing)
-{
-  o_place_rubberplace_xor (w_current, drawing);
-}
-
-
-/*! \todo Finish function documentation!!!
- *  \brief
- *  \par Function Description
- *
  *  \note
  *  don't know if this belongs yet
  */
diff --git a/gschem/src/o_copy.c b/gschem/src/o_copy.c
index 66c9c04..aafa430 100644
--- a/gschem/src/o_copy.c
+++ b/gschem/src/o_copy.c
@@ -120,25 +120,3 @@ void o_copy_multiple_end(GSCHEM_TOPLEVEL *w_current)
 {
   o_copy_end_generic (w_current, TRUE);
 }
-
-
-/*! \todo Finish function documentation!!!
- *  \brief
- *  \par Function Description
- *
- */
-void o_copy_rubbercopy (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
-{
-  o_place_rubberplace (w_current, w_x, w_y);
-}
-
-
-/*! \todo Finish function documentation!!!
- *  \brief
- *  \par Function Description
- *
- */
-void o_copy_rubbercopy_xor (GSCHEM_TOPLEVEL *w_current, int drawing)
-{
-  o_place_rubberplace_xor (w_current, drawing);
-}
diff --git a/gschem/src/o_text.c b/gschem/src/o_text.c
index 62d45fc..ec3641c 100644
--- a/gschem/src/o_text.c
+++ b/gschem/src/o_text.c
@@ -333,28 +333,6 @@ void o_text_start (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
  *  \par Function Description
  *
  */
-void o_text_rubberattrib(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
-{
-  o_place_rubberplace (w_current, w_x, w_y);
-}
-
-
-/*! \todo Finish function documentation!!!
- *  \brief
- *  \par Function Description
- *
- */
-void o_text_rubberattrib_xor(GSCHEM_TOPLEVEL *w_current, int drawing)
-{
-  o_place_rubberplace_xor (w_current, drawing);
-}
-
-
-/*! \todo Finish function documentation!!!
- *  \brief
- *  \par Function Description
- *
- */
 void o_text_edit(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
 {
   /* you need to check to make sure only one object is selected */
diff --git a/gschem/src/x_compselect.c b/gschem/src/x_compselect.c
index 669c869..9050f73 100644
--- a/gschem/src/x_compselect.c
+++ b/gschem/src/x_compselect.c
@@ -145,7 +145,7 @@ x_compselect_callback_response (GtkDialog *dialog,
         switch (w_current->event_state) {
           case ENDCOMP:
             /* Undraw the component which was being placed */
-            o_complex_rubbercomplex_xor (w_current, FALSE);
+            o_place_rubberplace_xor(w_current, FALSE);
             /* Fall through */
           case DRAWCOMP:
             s_delete_object_glist(toplevel,
diff --git a/gschem/src/x_event.c b/gschem/src/x_event.c
index ef537a8..1603717 100644
--- a/gschem/src/x_event.c
+++ b/gschem/src/x_event.c
@@ -288,7 +288,7 @@ gint x_event_button_pressed(GtkWidget *widget, GdkEventButton *event,
           i_set_state(w_current, SELECT);
           i_update_toolbar(w_current);
         } else {
-          o_complex_rubbercomplex_xor (w_current, TRUE);
+          o_place_rubberplace_xor (w_current, TRUE);
         }
         break;
 
@@ -578,7 +578,7 @@ gint x_event_button_released(GtkWidget *widget, GdkEventButton *event,
         /* having this stay in copy was driving me nuts*/
         w_current->inside_action = 1;
         /* Keep the state and the inside_action, as the copy has not finished. */
-        o_complex_rubbercomplex_xor (w_current, TRUE);
+        o_place_rubberplace_xor (w_current, TRUE);
         i_set_state(w_current, ENDMCOPY);
         i_update_toolbar(w_current);
         o_undo_savestate(w_current, UNDO_ALL);
@@ -617,7 +617,7 @@ gint x_event_button_released(GtkWidget *widget, GdkEventButton *event,
 
     if (w_current->inside_action) {
       if (w_current->event_state == ENDCOMP) {
-        o_complex_rubbercomplex_xor (w_current, FALSE);
+        o_place_rubberplace_xor (w_current, FALSE);
 
         w_current->complex_rotate =
           (w_current->complex_rotate + 90) % 360;
@@ -631,24 +631,24 @@ gint x_event_button_released(GtkWidget *widget, GdkEventButton *event,
         o_complex_place_changed_run_hook (w_current);
         toplevel->DONT_REDRAW = prev_state;
 
-        o_complex_rubbercomplex_xor (w_current, TRUE);
+        o_place_rubberplace_xor (w_current, TRUE);
         return(0);
       } else if (w_current->event_state == ENDTEXT) {
-        o_text_rubberattrib_xor (w_current, FALSE);
+        o_place_rubberplace_xor (w_current, FALSE);
 
         w_current->complex_rotate =
         (w_current->complex_rotate + 90) % 360;
 
         o_place_rotate(w_current);
 
-        o_text_rubberattrib_xor (w_current, TRUE);
+        o_place_rubberplace_xor (w_current, TRUE);
         return(0);
 
       }
       else if (w_current->event_state == ENDMOVE) {
         prev_state = w_current->event_state;
 
-        o_complex_rubbercomplex_xor (w_current, FALSE);
+        o_move_rubbermove_xor (w_current, FALSE);
 
         /* Don't allow o_rotate_90 to erase the selection, neither to
            redraw the objects after rotating */
@@ -662,7 +662,7 @@ gint x_event_button_released(GtkWidget *widget, GdkEventButton *event,
         w_current->rotated_inside ++;
         w_current->event_state = prev_state;
 
-        o_complex_rubbercomplex_xor (w_current, TRUE);
+        o_move_rubbermove_xor (w_current, TRUE);
 
         return(0);
       }
@@ -843,14 +843,6 @@ gint x_event_motion(GtkWidget *widget, GdkEventMotion *event,
       o_move_rubbermove(w_current, w_x, w_y);
     break;
 
-    case(ENDCOPY):
-    case(COPY):
-    case(ENDMCOPY):
-    case(MCOPY):
-    if (w_current->inside_action)
-      o_copy_rubbercopy(w_current, w_x, w_y);
-    break;
-
     case(ENDLINE):
     if (w_current->inside_action)
       o_line_rubberline(w_current, w_x, w_y);
@@ -907,14 +899,6 @@ gint x_event_motion(GtkWidget *widget, GdkEventMotion *event,
     w_current->inside_action = 1;
     break;
 
-    case(ENDCOMP):
-    o_complex_rubbercomplex(w_current, w_x, w_y);
-    break;
-
-    case(ENDPASTE):
-    o_buffer_paste_rubberpaste(w_current, w_x, w_y);
-    break;
-
     case(DRAWTEXT):
     w_current->complex_rotate = 0; /* reset to known state */
     o_text_start(w_current, w_x, w_y);
@@ -922,8 +906,14 @@ gint x_event_motion(GtkWidget *widget, GdkEventMotion *event,
     w_current->inside_action = 1;
     break;
 
+    case(COPY):
+    case(MCOPY):
+    case(ENDCOPY):
+    case(ENDMCOPY):
+    case(ENDCOMP):
+    case(ENDPASTE):
     case(ENDTEXT):
-    o_text_rubberattrib(w_current, w_x, w_y);
+    o_place_rubberplace(w_current, w_x, w_y);
     break;
 
     case(SBOX):

commit e931091e28f90e7bd0f755ee30665cc5b7461b74
Author: Peter Clifton <pcjc2@xxxxxxxxx>
Date:   Tue Jul 29 03:00:59 2008 +0100

    gschem: Combine code for operations which handle placement of OBJECTs.
    
    Replaces duplicated code related to component / text placement, copying /
    multi-copying objects and pasting from buffers with a common set of
    routines in the new file, gschem/src/o_place.c
    
    This refactoring lays the foundation to allow rotatation / mirroring whilst
    performing any kind of place action, without extensive duplicate code.
    
    All of the above operations now use a new PAGE variable, "place_list",
    rather than previous specialised variants complex_place_list, and
    attrib_place_list. Paste-buffer contents are copied into the place list,
    rather than placing directly from the paste-buffer, ensuring that any
    rotation / mirroring of the place-buffer does not change the paste-buffer.
    
    Helper functions, o_text_prepare_place() and o_complex_prepare_place() are
    added to load the place list with appropriate text, or a symbol. These are
    passed as arguments to the respective functions, avoiding the use of state
    stored in toplevel->current_attribute and toplevel->internal_symbol_name.

diff --git a/gschem/include/prototype.h b/gschem/include/prototype.h
index 743e725..ccab460 100644
--- a/gschem/include/prototype.h
+++ b/gschem/include/prototype.h
@@ -513,9 +513,8 @@ void o_box_erase_grips(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current);
 void o_buffer_copy(GSCHEM_TOPLEVEL *w_current, int buf_num);
 void o_buffer_cut(GSCHEM_TOPLEVEL *w_current, int buf_num);
 void o_buffer_paste_start(GSCHEM_TOPLEVEL *w_current, int x, int y, int buf_num);
-void o_buffer_paste_end(GSCHEM_TOPLEVEL *w_current, int x, int y, int buf_num);
-void o_buffer_paste_rubberpaste(GSCHEM_TOPLEVEL *w_current, int buf_num, int x, int y);
-void o_buffer_paste_rubberpaste_xor(GSCHEM_TOPLEVEL *w_current, int buf_num, int drawing);
+void o_buffer_paste_rubberpaste(GSCHEM_TOPLEVEL *w_current, int x, int y);
+void o_buffer_paste_rubberpaste_xor(GSCHEM_TOPLEVEL *w_current, int drawing);
 void o_buffer_init(void);
 void o_buffer_free(GSCHEM_TOPLEVEL *w_current);
 /* o_bus.c */
@@ -544,16 +543,17 @@ void o_circle_erase_grips(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current);
 /* o_complex.c */
 void o_complex_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current);
 void o_complex_draw_xor(GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *complex);
+void o_complex_prepare_place(GSCHEM_TOPLEVEL *w_current, const char *sym_name);
 void o_complex_start(GSCHEM_TOPLEVEL *w_current, int x, int y);
 void o_complex_place_changed_run_hook(GSCHEM_TOPLEVEL *w_current);
-void o_complex_place_rotate(GSCHEM_TOPLEVEL *w_current);
-void o_complex_end(GSCHEM_TOPLEVEL *w_current, int x, int y);
+void o_complex_end(GSCHEM_TOPLEVEL *w_current, int x, int y, int continue_placing);
 void o_complex_rubbercomplex(GSCHEM_TOPLEVEL *w_current, int x, int y);
 void o_complex_rubbercomplex_xor(GSCHEM_TOPLEVEL *w_current, int drawing);
 void o_complex_translate_all(GSCHEM_TOPLEVEL *w_current, int offset);
 /* o_copy.c */
 void o_copy_start(GSCHEM_TOPLEVEL *w_current, int x, int y);
 void o_copy_end(GSCHEM_TOPLEVEL *w_current);
+void o_copy_multiple_end(GSCHEM_TOPLEVEL *w_current);
 void o_copy_rubbercopy(GSCHEM_TOPLEVEL *w_current, int x, int y);
 void o_copy_rubbercopy_xor(GSCHEM_TOPLEVEL *w_current, int drawing);
 /* o_cue.c */
@@ -685,6 +685,12 @@ void o_pin_end(GSCHEM_TOPLEVEL *w_current, int x, int y);
 void o_pin_rubberpin(GSCHEM_TOPLEVEL *w_current, int x, int y);
 void o_pin_rubberpin_xor(GSCHEM_TOPLEVEL *w_current);
 void o_pin_eraserubber(GSCHEM_TOPLEVEL *w_current);
+/* o_place.c */
+void o_place_start(GSCHEM_TOPLEVEL *w_current, int x, int y);
+void o_place_end(GSCHEM_TOPLEVEL *w_current, int x, int y, int continue_placing, GList **ret_new_objects);
+void o_place_rubberplace(GSCHEM_TOPLEVEL *w_current, int x, int y);
+void o_place_rubberplace_xor(GSCHEM_TOPLEVEL *w_current, int drawing);
+void o_place_rotate(GSCHEM_TOPLEVEL *w_current);
 /* o_select.c */
 void o_select_run_hooks(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, int flag);
 void o_select_object(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, int type, int count);
@@ -706,14 +712,13 @@ void o_text_draw_lowlevel(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current);
 void o_text_draw_rectangle(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current);
 void o_text_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current);
 void o_text_draw_xor(GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_current);
+void o_text_prepare_place(GSCHEM_TOPLEVEL *w_current, char *text);
 void o_text_start(GSCHEM_TOPLEVEL *w_current, int x, int y);
-void o_text_end(GSCHEM_TOPLEVEL *w_current);
 void o_text_rubberattrib(GSCHEM_TOPLEVEL *w_current, int x, int y);
 void o_text_rubberattrib_xor(GSCHEM_TOPLEVEL *w_current, int drawing);
 void o_text_edit(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current);
 void o_text_edit_end(GSCHEM_TOPLEVEL *w_current, char *string, int len, int text_size, int text_alignment);
 void o_text_change(GSCHEM_TOPLEVEL *w_current, OBJECT *object, char *string, int visibility, int show);
-void o_text_place_rotate(GSCHEM_TOPLEVEL *w_current);
 /* o_undo.c */
 void o_undo_init(void);
 void o_undo_savestate(GSCHEM_TOPLEVEL *w_current, int flag);
diff --git a/gschem/src/Makefile.am b/gschem/src/Makefile.am
index 8072874..0a01fa1 100644
--- a/gschem/src/Makefile.am
+++ b/gschem/src/Makefile.am
@@ -16,7 +16,7 @@ gschem_SOURCES = \
 	o_slot.c o_grips.c \
 	o_arc.c o_box.c o_circle.c o_complex.c o_select.c o_find.c \
 	o_line.c o_net.c o_text.c o_pin.c o_bus.c o_buffer.c o_undo.c \
-	o_picture.c \
+	o_picture.c o_place.c \
 	x_autonumber.c x_basic.c x_dialog.c \
 	x_event.c x_grid.c x_log.c x_menus.c x_script.c \
 	x_pagesel.c x_print.c x_window.c x_stroke.c x_image.c x_color.c \
diff --git a/gschem/src/i_callbacks.c b/gschem/src/i_callbacks.c
index 5547090..45c1140 100644
--- a/gschem/src/i_callbacks.c
+++ b/gschem/src/i_callbacks.c
@@ -3516,6 +3516,7 @@ DEFINE_I_CALLBACK(misc3)
 DEFINE_I_CALLBACK(cancel)
 {
   GSCHEM_TOPLEVEL *w_current = (GSCHEM_TOPLEVEL*) data;
+  TOPLEVEL *toplevel = w_current->toplevel;
   GValue value = { 0, };
 
   exit_if_null(w_current);
@@ -3527,11 +3528,6 @@ DEFINE_I_CALLBACK(cancel)
     /* Undraw any XOR outline of the place list */
     o_complex_rubbercomplex_xor(w_current, FALSE);
 
-    /* Free the complex place list and its contents */
-    s_delete_object_glist(w_current->toplevel,
-                          w_current->toplevel->page_current->complex_place_list);
-    w_current->toplevel->page_current->complex_place_list = NULL;
-
     /* De-select the lists in the component selector */
     x_compselect_deselect (w_current);
 
@@ -3549,6 +3545,12 @@ DEFINE_I_CALLBACK(cancel)
     o_move_cancel (w_current);
   }
 
+  /* Free the place list and its contents. If we were in a move
+   * action, the list (refering to objects on the page) would
+   * already have been cleared in o_move_cancel(), so this is OK. */
+  s_delete_object_glist(toplevel, toplevel->page_current->place_list);
+  toplevel->page_current->place_list = NULL;
+
   /* leave this on for now... but it might have to change */
   /* this is problematic since we don't know what the right mode */
   /* (when you cancel inside an action) should be */
@@ -3562,22 +3564,6 @@ DEFINE_I_CALLBACK(cancel)
      o_redraw_all(w_current); 
   }
 
-  /* it is possible to cancel in the middle of a complex place
-   * so lets be sure to clean up the complex_place_list
-   * structure and also clean up the attrib_place_list.
-   * remember these don't remove the head structure */
-
-  /* Free the complex place list and its contents. If we were in a
-   * move action, the list (refering to objects on the page) would
-   * already have been cleared in o_move_cancel(), so this is OK. */
-  s_delete_object_glist(w_current->toplevel,
-                        w_current->toplevel->page_current->complex_place_list);
-  w_current->toplevel->page_current->complex_place_list = NULL;
-
-  s_delete_object_glist(w_current->toplevel,
-                        w_current->toplevel->page_current->attrib_place_list);
-  w_current->toplevel->page_current->attrib_place_list = NULL;
-
   /* also free internal current_attribute */
   o_attrib_free_current(w_current->toplevel);
 
diff --git a/gschem/src/o_basic.c b/gschem/src/o_basic.c
index 37d6688..1bac51a 100644
--- a/gschem/src/o_basic.c
+++ b/gschem/src/o_basic.c
@@ -79,7 +79,7 @@ void o_redraw_all(GSCHEM_TOPLEVEL *w_current)
         break;
 
       case(ENDPASTE):
-        o_buffer_paste_rubberpaste_xor (w_current, w_current->buffer_number, TRUE);
+        o_buffer_paste_rubberpaste_xor (w_current, TRUE);
         break;
 
       case(STARTDRAWNET):
@@ -531,8 +531,7 @@ int o_redraw_cleanstates(GSCHEM_TOPLEVEL *w_current)
     case(NETCONT):
     case(ZOOMBOXEND):
       /* it is possible to cancel in the middle of a place,
-       * so lets be sure to clean up the complex_place_list
-       * structure and also clean up the attrib_place_list. */
+       * so lets be sure to clean up the place_list structure */
 
       /* If we're cancelling from a move action, re-wind the
        * page contents back to their state before we started. */
@@ -541,16 +540,11 @@ int o_redraw_cleanstates(GSCHEM_TOPLEVEL *w_current)
         o_move_cancel (w_current);
       }
 
-      /* Free the complex place list and its contents. If we were in a
-       * move action, the list (refering to objects on the page) would
+      /* Free the place list and its contents. If we were in a move
+       * action, the list (refering to objects on the page) would
        * already have been cleared in o_move_cancel(), so this is OK. */
-      s_delete_object_glist(toplevel,
-                            toplevel->page_current->complex_place_list);
-      toplevel->page_current->complex_place_list = NULL;
-
-      s_delete_object_glist (toplevel,
-                             toplevel->page_current->attrib_place_list);
-      toplevel->page_current->attrib_place_list = NULL;
+      s_delete_object_glist(toplevel, toplevel->page_current->place_list);
+      toplevel->page_current->place_list = NULL;
 
       /* also free internal current_attribute */
       o_attrib_free_current(toplevel);
diff --git a/gschem/src/o_buffer.c b/gschem/src/o_buffer.c
index 3c73532..f7eb287 100644
--- a/gschem/src/o_buffer.c
+++ b/gschem/src/o_buffer.c
@@ -106,114 +106,43 @@ void o_buffer_paste_start(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y,
     return;
   }
 
-  if (!world_get_object_glist_bounds(toplevel, object_buffer[buf_num],
+  w_current->last_drawb_mode = -1;
+
+  /* remove the old place list if it exists */
+  s_delete_object_glist(toplevel, toplevel->page_current->place_list);
+  toplevel->page_current->place_list = NULL;
+
+  toplevel->ADDING_SEL = 1;
+  toplevel->page_current->place_list =
+    o_glist_copy_all_to_glist(toplevel, object_buffer[buf_num],
+                              toplevel->page_current->place_list,
+                              SELECTION_FLAG);
+
+  if (!world_get_object_glist_bounds (toplevel,
+                                      toplevel->page_current->place_list,
                                      &rleft, &rtop,
                                      &rright, &rbottom)) {
-    /* If the paste buffer doesn't have any objects
+    /* If the place buffer doesn't have any objects
      * to define its any bounds, we drop out here */
     return;
   }
 
-  w_current->first_wx = w_current->second_wx = w_x;
-  w_current->first_wy = w_current->second_wy = w_y;
-  /* store the buffer number for future use */
-  w_current->buffer_number = buf_num;
+  /* Place the objects into the buffer at the mouse origin, (w_x, w_y). */
+
+  w_current->first_wx = w_x;
+  w_current->first_wy = w_y;
 
   /* snap x and y to the grid, pointed out by Martin Benes */
   x = snap_grid(toplevel, rleft);
   y = snap_grid(toplevel, rtop);
 
-  toplevel->ADDING_SEL = 1;
-  o_glist_translate_world(toplevel, -x, -y, object_buffer[buf_num]);
+  o_glist_translate_world (toplevel, w_x - x, w_y - y,
+                           toplevel->page_current->place_list);
   toplevel->ADDING_SEL = 0;
 
-  toplevel->ADDING_SEL = 1;
-  o_glist_translate_world(toplevel, w_x, w_y, object_buffer[buf_num]);
-  toplevel->ADDING_SEL = 0;
-
-  w_current->event_state = ENDPASTE;
   w_current->inside_action = 1;
-
-  o_buffer_paste_rubberpaste_xor (w_current, buf_num, TRUE);
-}
-
-/*! \todo Finish function documentation!!!
- *  \brief
- *  \par Function Description
- *
- */
-void o_buffer_paste_end(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y,
-                        int buf_num)
-{
-  TOPLEVEL *toplevel = w_current->toplevel;
-  int w_diff_x, w_diff_y;
-  OBJECT *o_current;
-  OBJECT *o_saved;
-  SELECTION *temp_list = o_selection_new();
-  PAGE *p_current;
-  GList *connected_objects = NULL;
-
-  if (buf_num < 0 || buf_num > MAX_BUFFERS) {
-    fprintf(stderr, _("Got an invalid buffer_number [o_buffer_paste_end]\n"));
-    return;
-  }
-
-  /* erase old image */
-  o_buffer_paste_rubberpaste_xor (w_current, buf_num, FALSE);
-
-  /* calc and translate objects to their final position */
-  w_diff_x = w_current->second_wx - w_current->first_wx;
-  w_diff_y = w_current->second_wy - w_current->first_wy;
-
-#if DEBUG
-  printf("%d %d\n", w_diff_x, w_diff_y);
-#endif
-
-  toplevel->ADDING_SEL = 1;
-  o_glist_translate_world(toplevel, w_diff_x, w_diff_y,
-                          object_buffer[buf_num]);
-  toplevel->ADDING_SEL = 0;
-
-  o_current = object_buffer[buf_num]->data;
-  p_current = toplevel->page_current;
-
-  o_saved = p_current->object_tail;
-  o_list_copy_all(toplevel, o_current, p_current->object_tail,
-                  NORMAL_FLAG);
-
-  p_current->object_tail = return_tail(p_current->object_head);
-  o_current = o_saved->next;
-
-  /* now add new objects to the selection list */
-  while (o_current != NULL) {
-    o_selection_add( temp_list, o_current );
-    s_conn_update_object(toplevel, o_current);
-    if (o_current->type == OBJ_COMPLEX || o_current->type == OBJ_PLACEHOLDER) {
-      connected_objects = s_conn_return_complex_others(
-                                                       connected_objects,
-                                                       o_current);
-    } else {
-      connected_objects = s_conn_return_others(connected_objects,
-                                               o_current);
-    }
-    o_current = o_current->next;
-  }
-
-  o_cue_redraw_all(w_current, o_saved->next, TRUE);
-  o_cue_undraw_list(w_current, connected_objects);
-  o_cue_draw_list(w_current, connected_objects);
-  g_list_free(connected_objects);
-  connected_objects = NULL;
-
-  o_select_unselect_all( w_current );
-  geda_list_add_glist( toplevel->page_current->selection_list, geda_list_get_glist( temp_list ) );
-
-  g_object_unref( temp_list );
-
-  toplevel->page_current->CHANGED = 1;
-  o_redraw(w_current, o_saved->next, TRUE); /* only redraw new objects */
-  o_undo_savestate(w_current, UNDO_ALL);
-  i_update_menus(w_current);
+  i_set_state(w_current, ENDPASTE);
+  o_place_start (w_current, w_x, w_y);
 }
 
 
@@ -222,13 +151,9 @@ void o_buffer_paste_end(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y,
  *  \par Function Description
  *
  */
-void o_buffer_paste_rubberpaste (GSCHEM_TOPLEVEL *w_current, int buf_num,
-                                 int w_x, int w_y)
+void o_buffer_paste_rubberpaste (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
 {
-  o_buffer_paste_rubberpaste_xor (w_current, buf_num, FALSE);
-  w_current->second_wx = w_x;
-  w_current->second_wy = w_y;
-  o_buffer_paste_rubberpaste_xor (w_current, buf_num, TRUE);
+  o_place_rubberplace (w_current, w_x, w_y);
 }
 
 
@@ -237,11 +162,9 @@ void o_buffer_paste_rubberpaste (GSCHEM_TOPLEVEL *w_current, int buf_num,
  *  \par Function Description
  *
  */
-void o_buffer_paste_rubberpaste_xor(GSCHEM_TOPLEVEL *w_current, int buf_num,
-                                    int drawing)
+void o_buffer_paste_rubberpaste_xor(GSCHEM_TOPLEVEL *w_current, int drawing)
 {
-  o_drawbounding(w_current, object_buffer[buf_num],
-                 x_get_darkcolor(w_current->bb_color), drawing);
+  o_place_rubberplace_xor (w_current, drawing);
 }
 
 
diff --git a/gschem/src/o_complex.c b/gschem/src/o_complex.c
index 0962d9b..690ce08 100644
--- a/gschem/src/o_complex.c
+++ b/gschem/src/o_complex.c
@@ -65,50 +65,119 @@ void o_complex_draw_xor(GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *obje
   o_list_draw_xor( w_current, dx, dy, object->complex->prim_objs);
 }
 
+
 /*! \todo Finish function documentation!!!
  *  \brief
  *  \par Function Description
  *
  */
-void o_complex_start(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
+void o_complex_prepare_place(GSCHEM_TOPLEVEL *w_current, const char *sym_name)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
+  OBJECT *temp_parent;
+  OBJECT *temp_list;
+  OBJECT *o_current;
+  OBJECT *o_start;
+  char *buffer;
   int i, temp;
   const CLibSymbol *sym;
   int redraw_state;
 
-  w_current->first_wx = w_current->second_wx = w_x;
-  w_current->first_wy = w_current->second_wy = w_y;
-  w_current->last_drawb_mode = -1;
-
-  /* make sure list is null first, so that you don't have a mem
-   * leak */
-  toplevel->ADDING_SEL = 1; /* reuse this flag, rename later hack */
-  sym = s_clib_get_symbol_by_name (toplevel->internal_symbol_name);
-  o_complex_add(toplevel, NULL,
-		&(toplevel->page_current->complex_place_list),
-		OBJ_COMPLEX, WHITE, w_x, w_y, 0, 0,
-		sym, toplevel->internal_symbol_name,
-		1, TRUE);
-  toplevel->ADDING_SEL = 0;
+  /* remove the old place list if it exists */
+  s_delete_object_glist(toplevel, toplevel->page_current->place_list);
+  toplevel->page_current->place_list = NULL;
+
+  /* Insert the new object into the buffer at world coordinates (0,0).
+   * It will be translated to the mouse coordinates during placement. */
+
+  w_current->first_wx = 0;
+  w_current->first_wy = 0;
+
+  if (w_current->include_complex) {
+
+    o_start = temp_list = add_head();
+
+    /* Reset the object_parent pointer so attribute
+     * attachment works in this temporary list. */
+    temp_parent = toplevel->page_current->object_parent;
+    toplevel->page_current->object_parent = temp_list;
+
+    toplevel->ADDING_SEL=1;
+    buffer = s_clib_symbol_get_data_by_name (sym_name);
+    temp_list = o_read_buffer (toplevel,
+                               temp_list,
+                               buffer, -1,
+                               sym_name);
+    g_free (buffer);
+    toplevel->ADDING_SEL=0;
+
+    /* Put object_parent back where it should be */
+    toplevel->page_current->object_parent = temp_parent;
+
+    /* Take the added objects, severing them from the HEAD node */
+    o_current = o_start->next;
+    o_current->prev = NULL;
+    o_start->next = NULL;
+
+    /* Delete the HEAD node */
+    s_delete_list_fromstart (toplevel, o_start);
+
+    while (o_current != NULL) {
+      toplevel->page_current->place_list =
+        g_list_prepend (toplevel->page_current->place_list, o_current);
+      o_current = o_current->next;
+    }
+    toplevel->page_current->place_list =
+      g_list_reverse (toplevel->page_current->place_list);
+
+  } else { /* if (w_current->include_complex) {..} else { */
+
+    toplevel->ADDING_SEL = 1; /* reuse this flag, rename later hack */
+    sym = s_clib_get_symbol_by_name (sym_name);
+    o_complex_add(toplevel, NULL,
+                  &(toplevel->page_current->place_list),
+                  OBJ_COMPLEX, WHITE, 0, 0, 0, 0,
+                  sym, sym_name, 1, TRUE);
+    toplevel->ADDING_SEL = 0;
+
+    /* Flag the symbol as embedded if necessary */
+    o_current = (g_list_last (toplevel->page_current->place_list))->data;
+    if (w_current->embed_complex) {
+      o_current->complex_embedded = TRUE;
+    }
+  }
 
+  /* Rotate the place list if we start with any accumulated rotation */
   if (w_current->complex_rotate) {
     temp = w_current->complex_rotate / 90;
     for (i = 0; i < temp; i++) {
-      o_complex_place_rotate(w_current);
+      o_place_rotate(w_current);
     }
   }
 
   /* Run the complex place list changed hook without redrawing */
-  /* since the complex place list is going to be redrawn afterwards */
+  /* since the place list is going to be redrawn afterwards */
   redraw_state = toplevel->DONT_REDRAW;
   toplevel->DONT_REDRAW = 1;
   o_complex_place_changed_run_hook (w_current);
   toplevel->DONT_REDRAW = redraw_state;
 
-  o_complex_rubbercomplex_xor (w_current, TRUE);
+  w_current->inside_action = 1;
+  i_set_state(w_current, DRAWCOMP);
+}
+
+
+/*! \todo Finish function documentation!!!
+*  \brief
+*  \par Function Description
+*
+*/
+void o_complex_start(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
+{
+  o_place_start (w_current, w_x, w_y);
 }
 
+
 /*! \brief Run the complex place list changed hook. 
  *  \par Function Description
  *  The complex place list is usually used when placing new components
@@ -123,8 +192,8 @@ void o_complex_place_changed_run_hook(GSCHEM_TOPLEVEL *w_current) {
 
   /* Run the complex place list changed hook */
   if (scm_hook_empty_p(complex_place_list_changed_hook) == SCM_BOOL_F &&
-      toplevel->page_current->complex_place_list != NULL) {
-    ptr = toplevel->page_current->complex_place_list;
+      toplevel->page_current->place_list != NULL) {
+    ptr = toplevel->page_current->place_list;
     while (ptr) {
       scm_run_hook(complex_place_list_changed_hook, 
 		   scm_cons (g_make_object_smob
@@ -136,198 +205,48 @@ void o_complex_place_changed_run_hook(GSCHEM_TOPLEVEL *w_current) {
   }
 }
 
-/*! \todo Finish function documentation!!!
- *  \brief
- *  \par Function Description
- *
- */
-void o_complex_place_rotate(GSCHEM_TOPLEVEL *w_current)
-{
-  TOPLEVEL *toplevel = w_current->toplevel;
-  OBJECT *o_current;
-  GList *ptr;
-  int x_local = -1;
-  int y_local = -1;
-
-  ptr = toplevel->page_current->complex_place_list;
-  while(ptr) {
-    o_current = (OBJECT *) ptr->data;
-    switch(o_current->type) {	
-      case(OBJ_COMPLEX):
-        x_local = o_current->complex->x; 
-        y_local = o_current->complex->y;
-        break;
-    }
-    ptr = g_list_next(ptr);
-  }
-
-  if (x_local == -1) {
-    printf(_("Could not find complex in new component placement!\n"));
-    return;
-  }
-
-  ptr = toplevel->page_current->complex_place_list;
-  while(ptr) {
-    o_current = (OBJECT *) ptr->data;
-    switch(o_current->type) {	
-
-      case(OBJ_TEXT):
-        o_text_rotate_world(toplevel, x_local, y_local, 90, o_current);
-        break;
-
-      case(OBJ_COMPLEX):
-        o_complex_rotate_world(toplevel, x_local, y_local, 90, o_current);
-        break;
-
-    }
-    ptr = g_list_next(ptr);
-  }
-
-}
 
 /*! \todo Finish function documentation!!!
  *  \brief
  *  \par Function Description
  *
  */
-void o_complex_end(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
+void o_complex_end(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y, int continue_placing)
 {
-  TOPLEVEL *toplevel = w_current->toplevel;
+  GList *new_objects;
+  GList *iter;
   OBJECT *o_current;
-  OBJECT *o_start;
-  OBJECT *o_temp;
-  char *buffer;
-  int temp, i;
-  GList *connected_objects=NULL;
-  const CLibSymbol *sym;
-
-#if DEBUG
-  printf("place_basename: %s\n",internal_basename);
-  printf("place_clib: %s\n",internal_clib);
-#endif
-
-  w_current->second_wx = w_x;
-  w_current->second_wy = w_y;
 
-  o_complex_rubbercomplex_xor (w_current, FALSE);
+  o_place_end (w_current, w_x, w_y, continue_placing, &new_objects);
 
   if (w_current->include_complex) {
-    buffer = s_clib_symbol_get_data_by_name (toplevel->internal_symbol_name);
-
-    toplevel->ADDING_SEL=1;
-    o_start = toplevel->page_current->object_tail;
-    toplevel->page_current->object_tail =
-      o_read_buffer(toplevel,
-		    toplevel->page_current->object_tail,
-		    buffer, -1,
-		    toplevel->internal_symbol_name);
-    o_start = o_start->next;
-    toplevel->ADDING_SEL=0;
-    
-    o_list_translate_world(toplevel, w_x, w_y, o_start);
-
-    o_temp = o_start;
-    while (o_temp != NULL) {
-      if (o_temp->type == OBJ_NET || o_temp->type == OBJ_PIN ||
-          o_temp->type == OBJ_BUS) {
-        s_conn_update_object(toplevel, o_temp);
-                  
-        connected_objects = s_conn_return_others(connected_objects,
-                                                 o_temp);
-      }
-      o_temp = o_temp->next;
-    }
-    o_cue_undraw_list(w_current, connected_objects);
-    o_cue_draw_list(w_current, connected_objects);
-    g_list_free(connected_objects);
-
-    g_free(buffer);
-
-    o_redraw(w_current, o_start, TRUE);
-    toplevel->page_current->CHANGED = 1;
-    o_undo_savestate(w_current, UNDO_ALL);
-    i_update_menus(w_current);
-    s_delete_object_glist(toplevel, toplevel->page_current->
-                          complex_place_list);
-    toplevel->page_current->complex_place_list = NULL;
+    g_list_free (new_objects);
     return;
   }
 
-  o_temp = toplevel->page_current->object_tail;
-  sym = s_clib_get_symbol_by_name (toplevel->internal_symbol_name);
-  toplevel->page_current->object_tail =
-    o_complex_add(toplevel,
-                  toplevel->page_current->object_tail, NULL,
-                  OBJ_COMPLEX, WHITE, w_x, w_y, w_current->complex_rotate, 0,
-                  sym, toplevel->internal_symbol_name,
-		  1, TRUE);
-
-  /* complex rotate post processing */
-  o_temp = o_temp->next; /* skip over last object */
-  while (o_temp != NULL) {
-    switch(o_temp->type) {
-      case(OBJ_TEXT):
-        temp = w_current->complex_rotate / 90;
-        for (i = 0; i < temp; i++) {
-          o_text_rotate_world(toplevel, w_x, w_y, 90, o_temp);
-        }
-        break;
-    }
-		
-    o_temp = o_temp->next;
-  }
-
-  /* 1 should be define fix everywhere hack */
-  o_current = toplevel->page_current->object_tail;
+  /* Run the add component hook for the new component */
+  for (iter = new_objects;
+       iter != NULL;
+       iter = g_list_next (iter)) {
+    o_current = iter->data;
 
-  if (scm_hook_empty_p(add_component_hook) == SCM_BOOL_F &&
-      o_current != NULL) {
-    scm_run_hook(add_component_hook,
-                 scm_cons(g_make_attrib_smob_list(w_current, o_current),
-                          SCM_EOL));
-  }
-
-  if (scm_hook_empty_p(add_component_object_hook) == SCM_BOOL_F &&
-      o_current != NULL) {
-    scm_run_hook(add_component_object_hook,
-		 scm_cons(g_make_object_smob(toplevel, o_current),
-			  SCM_EOL));
-  }
+    if (scm_hook_empty_p(add_component_hook) == SCM_BOOL_F) {
+      scm_run_hook(add_component_hook,
+                   scm_cons(g_make_attrib_smob_list(w_current, o_current),
+                            SCM_EOL));
+    }
 
-  /* put code here to deal with emebedded stuff */
-  if (w_current->embed_complex) {
-    o_current->complex_embedded = TRUE;
+    if (scm_hook_empty_p(add_component_object_hook) == SCM_BOOL_F) {
+      scm_run_hook(add_component_object_hook,
+                   scm_cons(g_make_object_smob(w_current->toplevel,
+                                               o_current), SCM_EOL));
+    }
   }
 
-  /*! \todo redraw has to happen at the end of all this hack or
-   * maybe not? */
-  s_delete_object_glist(toplevel, toplevel->page_current->
-                        complex_place_list);
-  toplevel->page_current->complex_place_list = NULL;
-
-  /* This doesn't allow anything else to be in the selection
-   * list when you add a component */
-
-  o_select_unselect_list( w_current, toplevel->page_current->selection_list );
-  o_selection_add( toplevel->page_current->selection_list, toplevel->page_current->object_tail);
-  /* the o_redraw_selected is in x_events.c after this call
-   * returns */
-  o_attrib_add_selected(w_current, toplevel->page_current->selection_list,
-                        toplevel->page_current->object_tail);
-
-  s_conn_update_complex(toplevel, o_current->complex->prim_objs);
-  connected_objects = s_conn_return_complex_others(connected_objects,
-                                                   o_current);
-  o_cue_undraw_list(w_current, connected_objects);
-  o_cue_draw_list(w_current, connected_objects);
-  g_list_free(connected_objects);
-  o_cue_draw_single(w_current, toplevel->page_current->object_tail);
-        
-  toplevel->page_current->CHANGED = 1;
-  o_undo_savestate(w_current, UNDO_ALL);
-  i_update_menus(w_current);
+  g_list_free (new_objects);
 }
 
+
 /*! \todo Finish function documentation!!!
  *  \brief
  *  \par Function Description
@@ -335,10 +254,7 @@ void o_complex_end(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
  */
 void o_complex_rubbercomplex (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
 {
-  o_complex_rubbercomplex_xor (w_current, FALSE);
-  w_current->second_wx = w_x;
-  w_current->second_wy = w_y;
-  o_complex_rubbercomplex_xor (w_current, TRUE);
+  o_place_rubberplace (w_current, w_x, w_y);
 }
 
 
@@ -349,9 +265,7 @@ void o_complex_rubbercomplex (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
  */
 void o_complex_rubbercomplex_xor (GSCHEM_TOPLEVEL *w_current, int drawing)
 {
-  o_drawbounding (w_current,
-                  w_current->toplevel->page_current->complex_place_list,
-                  x_get_darkcolor (w_current->bb_color), drawing);
+  o_place_rubberplace_xor (w_current, drawing);
 }
 
 
diff --git a/gschem/src/o_copy.c b/gschem/src/o_copy.c
index c423734..66c9c04 100644
--- a/gschem/src/o_copy.c
+++ b/gschem/src/o_copy.c
@@ -32,391 +32,93 @@
 #include <dmalloc.h>
 #endif
 
-/*! \todo Finish function documentation!!!
- *  \brief
- *  \par Function Description
- *
- */
-void o_copy_start(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
-{
-  if (o_select_selected (w_current)) {
-
-  /* This is commented out since it breaks the copy of objects.  See below. */
-#if 0
-    /* Save the current state. When rotating the selection when copying,
-       we have to come back to here */
-    o_undo_savestate(w_current, UNDO_ALL);
-#endif
-
-    w_current->first_wx = w_current->second_wx = w_x;
-    w_current->first_wy = w_current->second_wy = w_y;
-    o_copy_rubbercopy_xor (w_current, TRUE);
-  }
-}
 
 /*! \todo Finish function documentation!!!
  *  \brief
  *  \par Function Description
  *
  */
-void o_copy_end(GSCHEM_TOPLEVEL *w_current)
+void o_copy_start(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
-  SELECTION *temp_list = o_selection_new();
-  GList *s_current = NULL;
-  GList *new_objects = NULL;
-  GList *connected_objects=NULL;
-  OBJECT *new_object = NULL;
-  OBJECT *complex_object = NULL;
-  OBJECT *new_objects_head = NULL;
-  OBJECT *object;
-  int diff_x, diff_y;
-  int color;
-  /* int redraw_state;  not needed for now */
+  GList *s_current;
 
-  object = o_select_return_first_object(w_current);
+  /* Copy the objects into the buffer at their current position,
+   * with future motion relative to the mouse origin, (w_x, w_y). */
 
-  if (object == NULL) {
-    /*! \todo error condition */
-    w_current->inside_action = 0;
-    i_set_state(w_current, SELECT);
-    return;
-  }
+  w_current->first_wx = w_x;
+  w_current->first_wy = w_y;
 
-  diff_x = w_current->second_wx - w_current->first_wx;
-  diff_y = w_current->second_wy - w_current->first_wy;
-
-  /* erase the bounding box */
-  o_copy_rubbercopy_xor (w_current, FALSE);
+  if (!o_select_selected (w_current))
+    return;
 
   s_current = geda_list_get_glist( toplevel->page_current->selection_list );
-  new_objects_head = s_basic_init_object("object_head");
-
-  while(s_current != NULL) {
-
-    object = (OBJECT *) s_current->data;
-
-    if (object == NULL) {
-      fprintf(stderr, _("ERROR: NULL object in o_copy_end!\n"));
-      exit(-1);
-    }
-
-    switch(object->type) {
-
-      case(OBJ_NET):
-
-        /* ADDING_SEL is a bad name, rename hack */
-        /* basically I don't want to add the */
-        /* connections till much later */
-        toplevel->ADDING_SEL=1;
-        new_object = (OBJECT *) o_net_copy( toplevel,
-                                            return_tail(new_objects_head),
-                                            object );
-        toplevel->ADDING_SEL=0;
-        o_translate_world(toplevel, diff_x, diff_y, new_object);
-
-        o_selection_add( temp_list, new_object );
-        new_object->saved_color = object->saved_color;
-        o_net_draw(w_current, new_object);
-
-        s_conn_update_object(toplevel, new_object);
-        new_objects = g_list_append(new_objects, new_object);
-        connected_objects = s_conn_return_others(connected_objects,
-                                                 new_object);
-        break;
-
-      case(OBJ_PIN):
-        /* ADDING_SEL is a bad name, rename hack */
-        /* basically I don't want to add the */
-        /* connections till much later */
-        toplevel->ADDING_SEL=1;
-        new_object = (OBJECT *) o_pin_copy(toplevel,
-                                           return_tail(new_objects_head), 
-                                           object);
-        toplevel->ADDING_SEL=0;
-        o_translate_world(toplevel, diff_x, diff_y, new_object);
-
-        o_selection_add( temp_list, new_object );
-        new_object->saved_color = object->saved_color;
-        o_pin_draw(w_current, new_object);
-
-        s_conn_update_object(toplevel, new_object);
-        new_objects = g_list_append(new_objects, new_object);
-        connected_objects = s_conn_return_others(connected_objects,
-                                                 new_object);
-        break;
-
-      case(OBJ_BUS):
-        /* ADDING_SEL is a bad name, rename hack */
-        /* basically I don't want to add the */
-        /* connections till much later */
-        toplevel->ADDING_SEL=1;
-        new_object = (OBJECT *) o_bus_copy(toplevel,
-                                           return_tail(new_objects_head),
-                                           object);
-        toplevel->ADDING_SEL=0;
-        o_translate_world(toplevel, diff_x, diff_y, new_object);
-
-        o_selection_add( temp_list, new_object );
-        new_object->saved_color = object->saved_color;
-        o_bus_draw(w_current, new_object);
-
-        s_conn_update_object(toplevel, new_object);
-        new_objects = g_list_append(new_objects, new_object);
-        connected_objects = s_conn_return_others(connected_objects,
-                                                 new_object);
-        break;
-
-      case(OBJ_COMPLEX):
-      case(OBJ_PLACEHOLDER):
-        toplevel->ADDING_SEL=1;
-        if (o_complex_is_embedded(object)) {
-
-          new_object = (OBJECT *) 
-            o_complex_copy_embedded(toplevel,
-                                    return_tail(new_objects_head),
-                                    object);
-
-        } else {
-          new_object = (OBJECT *) o_complex_copy(toplevel,
-                                                 return_tail(new_objects_head),
-                                                 object);
-        }
-        toplevel->ADDING_SEL=0;
-
-        complex_object = new_object;
-        o_translate_world(toplevel, diff_x, diff_y, new_object);
-
-        o_selection_add( temp_list, new_object );
-
-        /* NEWSEL: this needs to be fixed too */
-        /* this may not be needed anymore? */
-        o_attrib_slot_copy(toplevel, object,
-                           new_object);
-        new_object->saved_color = object->saved_color;
-        o_redraw_single(w_current, new_object);
-
-        s_conn_update_complex(toplevel, new_object->complex->prim_objs);
-        new_objects = g_list_append(new_objects, new_object);
-        connected_objects = s_conn_return_complex_others(connected_objects,
-                                                         new_object);
-        break;
-
-      case(OBJ_LINE):
-        new_object = (OBJECT *) o_line_copy(toplevel,
-                                            return_tail(new_objects_head),
-                                            object);
-        toplevel->ADDING_SEL=1;
-        o_translate_world(toplevel, diff_x, diff_y, new_object);
-        toplevel->ADDING_SEL=0;
-
-        o_selection_add( temp_list, new_object );
-        new_object->saved_color = object->saved_color;
-        o_line_draw(w_current, new_object);
-        break;
-
-      case(OBJ_BOX):
-        new_object = (OBJECT *) o_box_copy(toplevel,
-                                           return_tail(new_objects_head),
-                                           object);
-        toplevel->ADDING_SEL=1;
-        o_translate_world(toplevel, diff_x, diff_y, new_object);
-        toplevel->ADDING_SEL=0;
-
-        o_selection_add( temp_list, new_object );
-        new_object->saved_color = object->saved_color;
-        o_box_draw(w_current, new_object);
-
-        break;
-
-      case(OBJ_PICTURE):
-        new_object = (OBJECT *) o_picture_copy(toplevel,
-                                               return_tail(new_objects_head),
-                                               object);
-        toplevel->ADDING_SEL=1;
-        o_translate_world(toplevel, diff_x, diff_y, new_object);
-        toplevel->ADDING_SEL=0;
-
-        o_selection_add( temp_list, new_object );
-        new_object->saved_color = object->saved_color;
-        o_picture_draw(w_current, new_object);
-
-        break;
-
-      case(OBJ_CIRCLE):
-        new_object = (OBJECT *) o_circle_copy(toplevel,
-                                              return_tail(new_objects_head),
-                                              object);
-        toplevel->ADDING_SEL=1;
-        o_translate_world(toplevel, diff_x, diff_y, new_object);
-        toplevel->ADDING_SEL=0;
-
-        o_selection_add( temp_list, new_object );
-        new_object->saved_color = object->saved_color;
-        o_circle_draw(w_current, new_object);
-        break;
-
-      case(OBJ_ARC):
-        new_object = (OBJECT *) o_arc_copy( toplevel,
-                                            return_tail(new_objects_head),
-                                            object );
-        toplevel->ADDING_SEL=1;
-        o_translate_world(toplevel, diff_x, diff_y, new_object);
-        toplevel->ADDING_SEL=0;
 
-        o_selection_add( temp_list, new_object );
-        new_object->saved_color = object->saved_color;
-        o_arc_draw(w_current, new_object);
-        break;
-
-    }
-
-  /* Store a reference in the copied object to where it was copied.
-   * Used to retain associations when copying attributes */
-  object->copied_to = new_object;
-
-    toplevel->page_current->object_tail =
-      (OBJECT *) return_tail(toplevel->page_current->
-                             object_head);
-    s_current = g_list_next(s_current);
+  if (toplevel->page_current->place_list != NULL) {
+    s_delete_object_glist(toplevel, toplevel->page_current->place_list);
+    toplevel->page_current->place_list = NULL;
   }
 
-  s_current = geda_list_get_glist( toplevel->page_current->selection_list );
-  while(s_current != NULL) {
-
-    object = (OBJECT *) s_current->data;
-
-    if (object == NULL) {
-      fprintf(stderr, _("ERROR: NULL object in o_copy_end!\n"));
-      exit(-1);
-    }
-
-    switch(object->type) {
-
-      case(OBJ_TEXT):
-        toplevel->ADDING_SEL=1;
-        new_object = (OBJECT *) o_text_copy(toplevel,
-                                            return_tail(new_objects_head),
-                                            object);
-        toplevel->ADDING_SEL=0;
-
-	/* this is also okay NEWSEL new_obj is single */
-        if (object->attached_to) {
-          if (object->attached_to->copied_to) {
-            o_attrib_attach(toplevel, new_objects_head,
-                            new_object, object->attached_to-> copied_to);
-
-            /*! \todo I have no idea if this is
-               really needed.... ? */
-#if 0
-            o_attrib_slot_update(
-                                 w_current,
-                                 object->attached_to->copied_to);
-#endif
-          }
-        }
-        toplevel->ADDING_SEL=1;
-        o_translate_world(toplevel, diff_x, diff_y, new_object);
-        toplevel->ADDING_SEL=0;
-
-        /* old object was attr */
-        if (!new_object->attribute &&
-            object->attribute) {
-          new_object->color = toplevel->detachedattr_color;
-          o_complex_set_color(new_object, new_object->color);
-          new_object->visibility = VISIBLE;
-          color = new_object->color;
-        } else {
-          color = object->saved_color;
-        }
-
-        o_selection_add( temp_list, new_object );
-        new_object->saved_color = color;
-
-        /* signify that object is no longer an attribute */
-        o_text_draw(w_current, new_object);
-
-        o_complex_set_saved_color_only( new_object->text->prim_objs, 
-                                        color);
-        break;
-    }
-
-    toplevel->page_current->object_tail =
-      (OBJECT *) return_tail( toplevel->page_current->object_head );
-    s_current = g_list_next(s_current);
-  }
+  toplevel->page_current->place_list =
+    o_glist_copy_all_to_glist(toplevel, s_current,
+                              toplevel->page_current->place_list,
+                              SELECTION_FLAG);
 
-  /* Clean up dangling ATTRIB.copied_to pointers */
-  s_current = geda_list_get_glist( toplevel->page_current->selection_list );
-  while(s_current != NULL) {
-    object = s_current->data;
-    object->copied_to = NULL;
-    s_current = g_list_next (s_current);
-  }
+  w_current->inside_action = 1;
+  i_set_state(w_current, COPY);
+  o_place_start (w_current, w_x, w_y);
+}
 
-  /* This is commented out since it breaks the copy of objects.  */
-  /* Required connection information is thrown away for some reason */
-  /* Of course, commenting this out, will probably break the rotation */
-  /* that this supported. */
-#if 0 
-  /* Go back to the state before copying, to restore possible rotations
-     of the selection */
-  redraw_state = toplevel->DONT_REDRAW;
-  toplevel->DONT_REDRAW = 0;
-  o_undo_callback(w_current, UNDO_ACTION);
-  toplevel->DONT_REDRAW = redraw_state;
-#endif
 
-  /* Add the new objects */
-  toplevel->page_current->object_tail = (OBJECT *)
-    return_tail(toplevel->page_current->object_head);
+/*! \todo Finish function documentation!!!
+ *  \brief
+ *  \par Function Description
+ *
+ */
+static void o_copy_end_generic(GSCHEM_TOPLEVEL *w_current, int multiple)
+{
+  GList *new_objects;
+  GList *iter;
+  OBJECT *object;
 
-  s_basic_link_object(new_objects_head, toplevel->page_current->object_tail);
+  o_place_end (w_current, w_current->second_wx, w_current->second_wy, multiple, &new_objects);
 
-  /* Run the copy component hook */
-  object = new_objects_head->next;
-  while (object != NULL) {
+  /* Run the copy component hook for all new components */
+  for (iter = new_objects;
+       iter != NULL;
+       iter = g_list_next (iter)) {
+    object = iter->data;
     if ( (object->type == OBJ_COMPLEX) &&
          (scm_hook_empty_p(copy_component_hook) == SCM_BOOL_F)) {
       scm_run_hook(copy_component_hook,
                    scm_cons (g_make_attrib_smob_list(w_current, object),
                    SCM_EOL));
     }
-    object = object->next;
-  }
-
-  /* And redraw them */
-  object = new_objects_head;
-  while (object) {
-    o_redraw_single(w_current, object);
-    object=object->next;
   }
 
-  /* Delete the new object head */
-  /*  new_objects_head->next = NULL;
-      s_delete_list_fromstart(toplevel, new_objects_head); */
-
-  toplevel->page_current->object_tail = (OBJECT *)
-  return_tail(toplevel->page_current->object_head);
-
-  o_select_unselect_all( w_current );
-  geda_list_add_glist( toplevel->page_current->selection_list, geda_list_get_glist( temp_list ) );
-
-  g_object_unref( temp_list );
+  g_list_free (new_objects);
+}
 
-  toplevel->page_current->CHANGED = 1;
 
-  /* not needed o_redraw(w_current, toplevel->page_current->object_head); */
-  o_cue_draw_list(w_current, new_objects);
-  o_cue_undraw_list(w_current, connected_objects);
-  o_cue_draw_list(w_current, connected_objects);
+/*! \todo Finish function documentation!!!
+ *  \brief
+ *  \par Function Description
+ *
+ */
+void o_copy_end(GSCHEM_TOPLEVEL *w_current)
+{
+  o_copy_end_generic (w_current, FALSE);
+}
 
-  g_list_free(new_objects);
-  g_list_free(connected_objects);
-  new_objects = NULL;
-  connected_objects = NULL;
 
-  o_undo_savestate(w_current, UNDO_ALL);
+/*! \todo Finish function documentation!!!
+ *  \brief
+ *  \par Function Description
+ *
+ */
+void o_copy_multiple_end(GSCHEM_TOPLEVEL *w_current)
+{
+  o_copy_end_generic (w_current, TRUE);
 }
 
 
@@ -427,10 +129,7 @@ void o_copy_end(GSCHEM_TOPLEVEL *w_current)
  */
 void o_copy_rubbercopy (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
 {
-  o_copy_rubbercopy_xor (w_current, FALSE);
-  w_current->second_wx = w_x;
-  w_current->second_wy = w_y;
-  o_copy_rubbercopy_xor (w_current, TRUE);
+  o_place_rubberplace (w_current, w_x, w_y);
 }
 
 
@@ -441,8 +140,5 @@ void o_copy_rubbercopy (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
  */
 void o_copy_rubbercopy_xor (GSCHEM_TOPLEVEL *w_current, int drawing)
 {
-  TOPLEVEL *toplevel = w_current->toplevel;
-  o_drawbounding (w_current,
-                  geda_list_get_glist (toplevel->page_current->selection_list),
-                  x_get_darkcolor (w_current->bb_color), drawing);
+  o_place_rubberplace_xor (w_current, drawing);
 }
diff --git a/gschem/src/o_move.c b/gschem/src/o_move.c
index a86dd71..ef1459a 100644
--- a/gschem/src/o_move.c
+++ b/gschem/src/o_move.c
@@ -261,8 +261,8 @@ void o_move_end(GSCHEM_TOPLEVEL *w_current)
   g_list_free(rubbernet_other_objects);
   g_list_free(rubbernet_connected_objects);
 
-  g_list_free(toplevel->page_current->complex_place_list);
-  toplevel->page_current->complex_place_list = NULL;
+  g_list_free(toplevel->page_current->place_list);
+  toplevel->page_current->place_list = NULL;
 
   s_stretch_remove_most(toplevel, toplevel->page_current->stretch_head);
   toplevel->page_current->stretch_tail = toplevel->page_current->stretch_head;
@@ -286,8 +286,8 @@ void o_move_cancel (GSCHEM_TOPLEVEL *w_current)
     st_current->object->dont_redraw = FALSE;
     st_current = st_current->next;
   }
-  g_list_free(w_current->toplevel->page_current->complex_place_list);
-  w_current->toplevel->page_current->complex_place_list = NULL;
+  g_list_free(w_current->toplevel->page_current->place_list);
+  w_current->toplevel->page_current->place_list = NULL;
   o_undo_callback(w_current, UNDO_ACTION);
   w_current->rotated_inside = 0;
 
@@ -317,10 +317,7 @@ void o_move_rubbermove(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
  */
 void o_move_rubbermove_xor (GSCHEM_TOPLEVEL *w_current, int drawing)
 {
-  TOPLEVEL *toplevel = w_current->toplevel;
-  o_drawbounding (w_current,
-                  geda_list_get_glist (toplevel->page_current->selection_list),
-                  x_get_darkcolor (w_current->bb_color), drawing);
+  o_place_rubberplace_xor (w_current, drawing);
   if (w_current->netconn_rubberband)
     o_move_stretch_rubberband(w_current);
 }
diff --git a/gschem/src/o_place.c b/gschem/src/o_place.c
new file mode 100644
index 0000000..6637baf
--- /dev/null
+++ b/gschem/src/o_place.c
@@ -0,0 +1,179 @@
+/* gEDA - GPL Electronic Design Automation
+ * gschem - gEDA Schematic Capture
+ * Copyright (C) 1998-2007 Ales Hvezda
+ * Copyright (C) 1998-2007 gEDA Contributors (see ChangeLog for details)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+#include <stdio.h>
+
+#include <libgeda/libgeda.h>
+
+#include "../include/gschem_struct.h"
+#include "../include/globals.h"
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \todo Finish function documentation!!!
+ *  \brief
+ *  \par Function Description
+ *
+ */
+void o_place_start (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
+{
+  w_current->second_wx = w_x;
+  w_current->second_wy = w_y;
+
+  o_place_rubberplace_xor (w_current, TRUE);
+}
+
+/*! \todo Finish function documentation!!!
+ *  \brief
+ *  \par Function Description
+ *
+ */
+void o_place_end (GSCHEM_TOPLEVEL *w_current,
+                  int w_x, int w_y,
+                  int continue_placing,
+                  GList **ret_new_objects)
+{
+  TOPLEVEL *toplevel = w_current->toplevel;
+  int w_diff_x, w_diff_y;
+  OBJECT *o_current;
+  OBJECT *o_saved;
+  PAGE *p_current;
+  GList *temp_dest_list = NULL;
+  GList *connected_objects = NULL;
+  GList *iter;
+
+  /* erase old image */
+  o_place_rubberplace_xor (w_current, FALSE);
+
+  /* Calc final object positions */
+  w_current->second_wx = w_x;
+  w_current->second_wy = w_y;
+
+  w_diff_x = w_current->second_wx - w_current->first_wx;
+  w_diff_y = w_current->second_wy - w_current->first_wy;
+
+  if (continue_placing) {
+    /* Make a copy of the place list if we want to keep it afterwards */
+    temp_dest_list =
+      o_glist_copy_all_to_glist (toplevel, toplevel->page_current->place_list,
+                                           temp_dest_list, SELECTION_FLAG);
+  } else {
+    /* Otherwise just take it */
+    temp_dest_list = toplevel->page_current->place_list;
+    toplevel->page_current->place_list = NULL;
+  }
+
+  if (ret_new_objects != NULL) {
+    *ret_new_objects = g_list_copy (temp_dest_list);
+  }
+
+  /* Translate with ADDING_SEL=0, so connectable objects (nets, pins, buses)
+   * get referenced and updated in the page's tile system. */
+  toplevel->ADDING_SEL = 0;
+  o_glist_translate_world(toplevel, w_diff_x, w_diff_y, temp_dest_list);
+
+  /* Clear the old selection list */
+  o_select_unselect_all (w_current);
+
+  /* Attach each item back onto the page's object list. Update object
+   * connectivity and add the new objects to the selection list.*/
+  p_current = toplevel->page_current;
+  o_saved = p_current->object_tail;
+
+  for (iter = temp_dest_list; iter != NULL; iter = g_list_next (iter)) {
+    o_current = iter->data;
+
+    o_current->next = NULL; /* In case it isn't linked properly */
+    p_current->object_tail =
+      s_basic_link_object (o_current, p_current->object_tail);
+
+    o_selection_add (toplevel->page_current->selection_list, o_current);
+
+    /* Update object connectivity */
+    if (o_current->type == OBJ_COMPLEX || o_current->type == OBJ_PLACEHOLDER) {
+      s_conn_update_complex(toplevel, o_current->complex->prim_objs);
+      connected_objects =
+        s_conn_return_complex_others (connected_objects, o_current);
+    } else {
+      s_conn_update_object(toplevel, o_current);
+      connected_objects = s_conn_return_others (connected_objects, o_current);
+    }
+  }
+
+  g_list_free (temp_dest_list);
+
+  o_cue_redraw_all (w_current, o_saved->next, TRUE);
+  o_cue_undraw_list (w_current, connected_objects);
+  o_cue_draw_list (w_current, connected_objects);
+  g_list_free (connected_objects);
+  connected_objects = NULL;
+
+  toplevel->page_current->CHANGED = 1;
+  o_redraw (w_current, o_saved->next, TRUE); /* only redraw new objects */
+  o_undo_savestate (w_current, UNDO_ALL);
+  i_update_menus (w_current);
+}
+
+/*! \todo Finish function documentation!!!
+ *  \brief
+ *  \par Function Description
+ *
+ */
+void o_place_rubberplace (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
+{
+  o_place_rubberplace_xor (w_current, FALSE);
+  w_current->second_wx = w_x;
+  w_current->second_wy = w_y;
+  o_place_rubberplace_xor (w_current, TRUE);
+}
+
+
+/*! \todo Finish function documentation!!!
+ *  \brief
+ *  \par Function Description
+ *
+ */
+void o_place_rubberplace_xor (GSCHEM_TOPLEVEL *w_current, int drawing)
+{
+  o_drawbounding(w_current, w_current->toplevel->page_current->place_list,
+                 x_get_darkcolor (w_current->bb_color), drawing);
+}
+
+
+/*! \todo Finish function documentation!!!
+ *  \brief
+ *  \par Function Description
+ *
+ */
+void o_place_rotate (GSCHEM_TOPLEVEL *w_current)
+{
+  TOPLEVEL *toplevel = w_current->toplevel;
+  int savestate;
+
+  savestate = toplevel->DONT_REDRAW;
+  toplevel->DONT_REDRAW = 1;
+  o_rotate_world_update (w_current,
+                         w_current->first_wx, w_current->first_wy,
+                         90, toplevel->page_current->place_list);
+  toplevel->DONT_REDRAW = savestate;
+}
diff --git a/gschem/src/o_select.c b/gschem/src/o_select.c
index 7875866..ccf448a 100644
--- a/gschem/src/o_select.c
+++ b/gschem/src/o_select.c
@@ -438,20 +438,13 @@ o_select_move_to_place_list(GSCHEM_TOPLEVEL *w_current)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
   GList *selection;
-  OBJECT *o_current;
+  GList *selection_copy;
 
-  selection = geda_list_get_glist( toplevel->page_current->selection_list );
-
-  if (!selection) {
-    return;
-  }
+  /* remove the old place list if it exists */
+  s_delete_object_glist(toplevel, toplevel->page_current->place_list);
+  toplevel->page_current->place_list = NULL;
 
-  while (selection) {
-    o_current = (OBJECT *) selection->data;
-    if (o_current) {
-      toplevel->page_current->complex_place_list = g_list_append(toplevel->page_current->complex_place_list,
-								  o_current);
-    }
-    selection = g_list_next(selection);
-  }
+  selection = geda_list_get_glist( toplevel->page_current->selection_list );
+  selection_copy = g_list_copy( selection );
+  toplevel->page_current->place_list = selection_copy;
 }
diff --git a/gschem/src/o_text.c b/gschem/src/o_text.c
index 83f8e97..62d45fc 100644
--- a/gschem/src/o_text.c
+++ b/gschem/src/o_text.c
@@ -276,47 +276,30 @@ void o_text_draw_xor(GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_curre
  *  \par Function Description
  *
  */
-void o_text_start(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
+void o_text_prepare_place(GSCHEM_TOPLEVEL *w_current, char *text)
 {
   TOPLEVEL *toplevel = w_current->toplevel;
   int temp, i;
-  char *value;
 
-  w_current->first_wx = w_current->second_wx = w_x;
-  w_current->first_wy = w_current->second_wy = w_y;
+  /* Insert the new object into the buffer at world coordinates (0,0).
+   * It will be translated to the mouse coordinates during placement. */
+
+  w_current->first_wx = 0;
+  w_current->first_wy = 0;
 
   w_current->last_drawb_mode = -1;
 
-  /* remove the old attrib list if it exists */
-  s_delete_object_glist(toplevel, toplevel->page_current->attrib_place_list);
-  toplevel->page_current->attrib_place_list = NULL;
-
-  switch(w_current->text_caps) {
-    case(LOWER):
-      value = toplevel->current_attribute;
-      toplevel->current_attribute = g_utf8_strdown (value, -1);
-      g_free (value);
-      break;
-
-    case(UPPER):
-      value = toplevel->current_attribute;
-      toplevel->current_attribute = g_utf8_strup (value, -1);
-      g_free (value);
-      break;
-
-    case(BOTH):
-    default:
-      /* do nothing */
-      break;
-  }
+  /* remove the old place list if it exists */
+  s_delete_object_glist(toplevel, toplevel->page_current->place_list);
+  toplevel->page_current->place_list = NULL;
 
   /* here you need to add OBJ_TEXT when it's done */
-  toplevel->page_current->attrib_place_list =
-    g_list_append(toplevel->page_current->attrib_place_list,
+  toplevel->page_current->place_list =
+    g_list_append(toplevel->page_current->place_list,
                   o_text_add(toplevel, NULL,
                              OBJ_TEXT, w_current->text_color,
-                             w_x, w_y, LOWER_LEFT, 0, /* zero is angle */
-                             toplevel->current_attribute,
+                             0, 0, LOWER_LEFT, 0, /* zero is angle */
+                             text,
                              w_current->text_size,
                              /* has to be visible so you can place it */
                              /* visibility is set when you create the object */
@@ -325,55 +308,23 @@ void o_text_start(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
   if (w_current->complex_rotate) {
     temp = w_current->complex_rotate / 90;
     for (i = 0; i < temp; i++) {
-      o_text_place_rotate(w_current);
+      o_place_rotate(w_current);
     }
   }
 
-  o_text_rubberattrib_xor (w_current, TRUE);
+  w_current->inside_action = 1;
+  i_set_state(w_current, DRAWTEXT);
 }
 
+
 /*! \todo Finish function documentation!!!
  *  \brief
- *  \par Function Description
- *
- */
-void o_text_end(GSCHEM_TOPLEVEL *w_current)
+*  \par Function Description
+*
+*/
+void o_text_start (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
 {
-  TOPLEVEL *toplevel = w_current->toplevel;
-
-  /* erase the old bounding box / outline */
-  o_text_rubberattrib_xor (w_current, FALSE);
-
-  /* here you need to add OBJ_TEXT when it's done */
-  /*! \todo make this VIS and SHOW default configurable */
-  toplevel->page_current->object_tail =
-  o_text_add(toplevel, toplevel->page_current->object_tail,
-             /* type changed from TEXT to TEXT */
-             OBJ_TEXT,
-             w_current->text_color,
-             w_current->second_wx, w_current->second_wy, LOWER_LEFT,
-             w_current->complex_rotate,
-             toplevel->current_attribute,
-             w_current->text_size,
-             VISIBLE, SHOW_NAME_VALUE);
-
-  toplevel->override_color = -1;
-
-  toplevel->page_current->CHANGED=1;
-  o_select_unselect_all( w_current );
-  o_selection_add( toplevel->page_current->selection_list, toplevel->page_current->object_tail );
-
-  /* object_tail is the object that was just added */
-  if (toplevel->page_current->object_tail->draw_func != NULL &&
-      toplevel->page_current->object_tail->type != OBJ_HEAD) {
-    (*toplevel->page_current->object_tail->draw_func)(
-                                                       w_current,
-                                                       toplevel->page_current->object_tail);
-  }
-
-  toplevel->override_color = -1;
-  o_undo_savestate(w_current, UNDO_ALL);
-  i_update_menus(w_current);
+  o_place_start (w_current, w_x, w_y);
 }
 
 
@@ -384,10 +335,7 @@ void o_text_end(GSCHEM_TOPLEVEL *w_current)
  */
 void o_text_rubberattrib(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
 {
-  o_text_rubberattrib_xor (w_current, FALSE);
-  w_current->second_wx = w_x;
-  w_current->second_wy = w_y;
-  o_text_rubberattrib_xor (w_current, TRUE);
+  o_place_rubberplace (w_current, w_x, w_y);
 }
 
 
@@ -398,9 +346,7 @@ void o_text_rubberattrib(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
  */
 void o_text_rubberattrib_xor(GSCHEM_TOPLEVEL *w_current, int drawing)
 {
-  o_drawbounding(w_current,
-                 w_current->toplevel->page_current->attrib_place_list,
-                 x_get_darkcolor(w_current->bb_color), drawing);
+  o_place_rubberplace_xor (w_current, drawing);
 }
 
 
@@ -511,47 +457,3 @@ void o_text_change(GSCHEM_TOPLEVEL *w_current, OBJECT *object, char *string,
 
   toplevel->page_current->CHANGED = 1;
 }
-
-/*! \todo Finish function documentation!!!
- *  \brief
- *  \par Function Description
- *
- */
-void o_text_place_rotate(GSCHEM_TOPLEVEL *w_current)
-{
-  TOPLEVEL *toplevel = w_current->toplevel;
-  OBJECT *o_current;
-  GList *iter;
-
-  int x_local = -1;
-  int y_local = -1;
-
-  for (iter = toplevel->page_current->attrib_place_list;
-       iter != NULL;
-       iter = g_list_next(iter)) {
-    o_current = iter->data;
-    switch(o_current->type) {	
-      case(OBJ_TEXT):
-        x_local = o_current->text->x;
-        y_local = o_current->text->y;
-        break;
-    }
-  }
-
-  if (x_local == -1) {
-    printf("Could not find text obj in new text placement!\n");
-    return;
-  }
-
-  for (iter = toplevel->page_current->attrib_place_list;
-       iter != NULL;
-       iter = g_list_next(iter)) {
-    o_current = iter->data;
-    switch(o_current->type) {	
-
-      case(OBJ_TEXT):
-        o_text_rotate_world(toplevel, x_local, y_local, 90, o_current);
-        break;
-    }
-  }
-}
diff --git a/gschem/src/x_compselect.c b/gschem/src/x_compselect.c
index f7ff80b..669c869 100644
--- a/gschem/src/x_compselect.c
+++ b/gschem/src/x_compselect.c
@@ -149,8 +149,8 @@ x_compselect_callback_response (GtkDialog *dialog,
             /* Fall through */
           case DRAWCOMP:
             s_delete_object_glist(toplevel,
-                                  toplevel->page_current->complex_place_list);
-            toplevel->page_current->complex_place_list = NULL;
+                                  toplevel->page_current->place_list);
+            toplevel->page_current->place_list = NULL;
             break;
 
           default:
@@ -163,8 +163,7 @@ x_compselect_callback_response (GtkDialog *dialog,
           w_current->event_state = SELECT;
         } else {
           /* Otherwise set the new symbol to place */
-          o_complex_set_filename(toplevel, s_clib_symbol_get_name (symbol));
-          w_current->event_state = DRAWCOMP;
+          o_complex_prepare_place(w_current, s_clib_symbol_get_name (symbol));
         }
         break;
       }
@@ -173,7 +172,7 @@ x_compselect_callback_response (GtkDialog *dialog,
         /* Response when clicking on the "hide" button */
 
         /* If there is no component in the complex place list, set the current one */
-        if (toplevel->page_current->complex_place_list == NULL) {
+        if (toplevel->page_current->place_list == NULL) {
           gtk_dialog_response (GTK_DIALOG (compselect),
                                COMPSELECT_RESPONSE_PLACE);
         }
diff --git a/gschem/src/x_dialog.c b/gschem/src/x_dialog.c
index fa580b5..eb2f45e 100644
--- a/gschem/src/x_dialog.c
+++ b/gschem/src/x_dialog.c
@@ -106,9 +106,8 @@ char generic_textstring[256] = "refdes=R";
  */
 void text_input_dialog_apply(GtkWidget *w, GSCHEM_TOPLEVEL *w_current)
 {
-  int len;
-  TOPLEVEL *toplevel = w_current->toplevel;
-  char *string = NULL;
+  gchar *string = NULL;
+  gchar *tmp = NULL;
   GtkWidget *tientry;
   GtkTextBuffer *textbuffer;
   GtkTextIter start, end;
@@ -119,37 +118,33 @@ void text_input_dialog_apply(GtkWidget *w, GSCHEM_TOPLEVEL *w_current)
   gtk_text_buffer_get_bounds (textbuffer, &start, &end);
   string =  gtk_text_iter_get_text (&start, &end);
 
-  if (string[0] != '\0' ) {
-    gchar *tmp = NULL;
-    len = strlen(string);
-#if DEBUG
-    printf("text was: _%s_ %d\n", string, len);
-#endif
-    switch(w_current->text_caps) {
-      case(LOWER):
-        tmp = g_utf8_strdown (string, -1);
-        break;
+  if (string[0] == '\0' )
+    return;
 
-      case(UPPER):
-        tmp = g_utf8_strup (string, -1);
-        break;
-
-      case(BOTH):
-      default:
-        /* do nothing */
-        break;
-    }
+  switch(w_current->text_caps) {
+    case(LOWER):
+      tmp = g_utf8_strdown (string, -1);
+      break;
 
-    /* select the text, so you can continue immediatly writing the next text */
-    select_all_text_in_textview(GTK_TEXT_VIEW(tientry));
-    gtk_widget_grab_focus(tientry);
+    case(UPPER):
+      tmp = g_utf8_strup (string, -1);
+      break;
 
-    o_attrib_set_string(toplevel, tmp == NULL ? string : tmp);
-    g_free (tmp);
-    toplevel->page_current->CHANGED=1;
-    w_current->event_state = DRAWTEXT;
-    w_current->inside_action = 1;
+    case(BOTH):
+    default:
+      /* do nothing */
+      break;
   }
+
+  /* select the text, so you can continue immediatly writing the next text */
+  select_all_text_in_textview(GTK_TEXT_VIEW(tientry));
+  gtk_widget_grab_focus(tientry);
+
+  w_current->toplevel->page_current->CHANGED=1;
+
+  o_text_prepare_place (w_current, tmp == NULL ? string : tmp);
+  g_free (string);
+  g_free (tmp);
 }
 
 /*! \brief response function for the text entry dialog
diff --git a/gschem/src/x_event.c b/gschem/src/x_event.c
index 5d276ed..ef537a8 100644
--- a/gschem/src/x_event.c
+++ b/gschem/src/x_event.c
@@ -281,23 +281,19 @@ gint x_event_button_pressed(GtkWidget *widget, GdkEventButton *event,
           i_set_state(w_current, STARTDRAWBUS);
         }
         break;
-
       case(ENDCOMP):
-        o_complex_end(w_current, w_x, w_y);
-        o_redraw_single(w_current, toplevel->page_current->
-                        object_tail);
-        if (w_current->continue_component_place) {
-          o_complex_start(w_current, w_x, w_y);
-        } else {
+        o_complex_end(w_current, w_x, w_y, w_current->continue_component_place);
+        if (!w_current->continue_component_place) {
           w_current->inside_action = 0;
           i_set_state(w_current, SELECT);
           i_update_toolbar(w_current);
+        } else {
+          o_complex_rubbercomplex_xor (w_current, TRUE);
         }
         break;
 
       case(ENDPASTE):
-        o_buffer_paste_end(w_current, w_x, w_y,
-                           w_current->buffer_number);
+        o_place_end(w_current, w_x, w_y, FALSE, NULL);
         w_current->inside_action = 0;
         i_set_state(w_current, SELECT);
         i_update_toolbar(w_current);
@@ -326,18 +322,13 @@ gint x_event_button_pressed(GtkWidget *widget, GdkEventButton *event,
         break;
 
       case(ENDTEXT):
-        o_text_end(w_current);
-                                /* not sure on this one either... */
-                                /* keep it as well */
+        o_place_end(w_current, w_x, w_y, FALSE, NULL);
         w_current->inside_action = 0;
         i_set_state(w_current, SELECT);
         i_update_toolbar(w_current);
-                                /* the following happen inside attrib_end */
-                                /* therefore they are commeneted out here */
-                                /* o_redraw_single(object_tail);*/
-                                /* o_redraw_selected(); not sure on this */
         break;
 
+
       case(STARTPAN):
         a_pan(w_current, w_x, w_y);
         i_set_state(w_current, SELECT);
@@ -549,7 +540,6 @@ gint x_event_button_released(GtkWidget *widget, GdkEventButton *event,
       case(SELECT):
         /* do nothing */
         break;
-
       case(MOVE):
         w_current->event_state = ENDMOVE;
         break;
@@ -561,14 +551,12 @@ gint x_event_button_released(GtkWidget *widget, GdkEventButton *event,
       case(MCOPY):
         w_current->event_state = ENDMCOPY;
         break;
-
       case(GRIPS):
         o_grips_end(w_current),
         w_current->inside_action = 0;
         i_set_state(w_current, SELECT);
         i_update_toolbar(w_current);
         break;
-
       case(ENDMOVE):
         o_move_end(w_current);
         /* having this stay in copy was driving me nuts*/
@@ -586,12 +574,10 @@ gint x_event_button_released(GtkWidget *widget, GdkEventButton *event,
         break;
 
       case(ENDMCOPY):
-        o_copy_end(w_current);
+        o_copy_multiple_end(w_current);
         /* having this stay in copy was driving me nuts*/
         w_current->inside_action = 1;
         /* Keep the state and the inside_action, as the copy has not finished. */
-        w_current->first_wx = w_current->second_wx = w_x;
-        w_current->first_wy = w_current->second_wy = w_y;
         o_complex_rubbercomplex_xor (w_current, TRUE);
         i_set_state(w_current, ENDMCOPY);
         i_update_toolbar(w_current);
@@ -636,7 +622,7 @@ gint x_event_button_released(GtkWidget *widget, GdkEventButton *event,
         w_current->complex_rotate =
           (w_current->complex_rotate + 90) % 360;
 
-        o_complex_place_rotate(w_current);
+        o_place_rotate(w_current);
 
         /* Run the complex place list changed hook without redrawing */
         /* since all objects are being redrawn afterwards */
@@ -653,7 +639,7 @@ gint x_event_button_released(GtkWidget *widget, GdkEventButton *event,
         w_current->complex_rotate =
         (w_current->complex_rotate + 90) % 360;
 
-        o_text_place_rotate(w_current);
+        o_place_rotate(w_current);
 
         o_text_rubberattrib_xor (w_current, TRUE);
         return(0);
@@ -671,7 +657,7 @@ gint x_event_button_released(GtkWidget *widget, GdkEventButton *event,
         toplevel->DONT_REDRAW = 1;
         o_rotate_world_update(w_current, w_current->first_wx,
                                          w_current->first_wy, 90,
-                              toplevel->page_current->complex_place_list );
+                              toplevel->page_current->place_list );
         toplevel->DONT_REDRAW = redraw_state;
         w_current->rotated_inside ++;
         w_current->event_state = prev_state;
@@ -926,7 +912,7 @@ gint x_event_motion(GtkWidget *widget, GdkEventMotion *event,
     break;
 
     case(ENDPASTE):
-    o_buffer_paste_rubberpaste(w_current, w_current->buffer_number, w_x, w_y);
+    o_buffer_paste_rubberpaste(w_current, w_x, w_y);
     break;
 
     case(DRAWTEXT):
diff --git a/libgeda/include/struct.h b/libgeda/include/struct.h
index be99ef0..6aaf3c0 100644
--- a/libgeda/include/struct.h
+++ b/libgeda/include/struct.h
@@ -344,8 +344,7 @@ struct st_page {
   OBJECT *object_tail;
   OBJECT *object_parent;
   SELECTION *selection_list; /* new selection mechanism */
-  GList *complex_place_list;
-  GList *attrib_place_list;
+  GList *place_list;
   OBJECT *object_lastplace;
   STRETCH *stretch_head; 
   STRETCH *stretch_tail; 
diff --git a/libgeda/src/s_page.c b/libgeda/src/s_page.c
index bbec414..d79c1b9 100644
--- a/libgeda/src/s_page.c
+++ b/libgeda/src/s_page.c
@@ -91,8 +91,7 @@ PAGE *s_page_new (TOPLEVEL *toplevel, const gchar *filename)
   /* net/pin/bus stretch when doing moves */
   page->stretch_head = page->stretch_tail = s_stretch_new_head();
 
-  page->complex_place_list = NULL;
-  page->attrib_place_list = NULL;
+  page->place_list = NULL;
 
   /* do this just to be sure that object tail is truely correct */
   page->object_tail = return_tail(page->object_head);
@@ -170,13 +169,9 @@ void s_page_delete (TOPLEVEL *toplevel, PAGE *page)
   /* then delete objects of page */
   s_delete_list_fromstart (toplevel, page->object_head);
 
-  /* The complex place list contain a reference to the objects in the page */
-  /* So don't free the objects there. */
-  g_list_free (page->complex_place_list);
-  page->complex_place_list = NULL;
-  /* Free the objects in the attrib place list. */
-  s_delete_object_glist (toplevel, page->attrib_place_list);
-  page->attrib_place_list = NULL;
+  /* Free the objects in the place list. */
+  s_delete_object_glist (toplevel, page->place_list);
+  page->place_list = NULL;
 
 #if DEBUG
   printf("Freeing page: %s\n", page->page_filename);




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