diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt
index a719bb07d1..fe85ab80db 100644
--- a/eeschema/CMakeLists.txt
+++ b/eeschema/CMakeLists.txt
@@ -14,13 +14,11 @@ set(EESCHEMA_SRCS
     build_BOM.cpp
     busentry.cpp
     bus-wire-junction.cpp
-    class_BodyItem_Text.cpp
     class_drawsheet.cpp
     class_drawsheetpath.cpp
     class_drc_erc_item.cpp
     class_hierarchical_PIN_sheet.cpp
     class_libentry.cpp
-    class_libentry_fields.cpp
     class_library.cpp
     class_marker_sch.cpp
     class_netlist_object.cpp
@@ -77,7 +75,6 @@ set(EESCHEMA_SRCS
     edit_component_in_schematic.cpp
     edit_label.cpp
     eelayer.cpp
-    eelibs_draw_components.cpp
     eelibs_read_libraryfiles.cpp
     eeredraw.cpp
     eeschema.cpp
@@ -101,8 +98,10 @@ set(EESCHEMA_SRCS
     lib_circle.cpp
     lib_draw_item.cpp
     lib_export.cpp
+    lib_field.cpp
     lib_polyline.cpp
     lib_rectangle.cpp
+    lib_text.cpp
     libfield.cpp
     load_one_schematic_file.cpp
     locate.cpp
@@ -135,6 +134,7 @@ set(EESCHEMA_SRCS
     tool_lib.cpp
     tool_sch.cpp
     tool_viewlib.cpp
+    transform.cpp
     viewlib_frame.cpp
     viewlibs.cpp)
 
diff --git a/eeschema/block.cpp b/eeschema/block.cpp
index 5c6c6e4cde..1e07d72682 100644
--- a/eeschema/block.cpp
+++ b/eeschema/block.cpp
@@ -906,7 +906,8 @@ static LIB_PIN* GetNextPinPosition( SCH_COMPONENT* aDrawLibItem,
                                     bool           aSearchFirst )
 {
     static LIB_COMPONENT* Entry;
-    static int Multi, convert, TransMat[2][2];
+    static int Multi, convert;
+    TRANSFORM transform;
     static wxPoint CmpPosition;
     static LIB_PIN* Pin;
 
@@ -921,7 +922,7 @@ static LIB_PIN* GetNextPinPosition( SCH_COMPONENT* aDrawLibItem,
         Multi       = aDrawLibItem->m_Multi;
         convert     = aDrawLibItem->m_Convert;
         CmpPosition = aDrawLibItem->m_Pos;
-        memcpy( TransMat, aDrawLibItem->m_Transform, sizeof(TransMat) );
+        transform   = aDrawLibItem->m_Transform;
     }
     else
         Pin = Entry->GetNextPin( Pin );
@@ -938,7 +939,7 @@ static LIB_PIN* GetNextPinPosition( SCH_COMPONENT* aDrawLibItem,
 
         /* Calculate the pin position (according to the component orientation)
          */
-        aPosition = TransformCoordinate( TransMat, Pin->m_Pos ) + CmpPosition;
+        aPosition = DefaultTransform.TransformCoordinate( Pin->m_Pos ) + CmpPosition;
         return Pin;
     }
 
diff --git a/eeschema/block_libedit.cpp b/eeschema/block_libedit.cpp
index c7f8849e00..aafb51cb0b 100644
--- a/eeschema/block_libedit.cpp
+++ b/eeschema/block_libedit.cpp
@@ -16,8 +16,7 @@
 #include "libeditframe.h"
 
 
-static void DrawMovingBlockOutlines( WinEDA_DrawPanel* panel, wxDC* DC,
-                                     bool erase );
+static void DrawMovingBlockOutlines( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
 
 
 /*
@@ -102,8 +101,8 @@ int WinEDA_LibeditFrame::HandleBlockEnd( wxDC* DC )
     case BLOCK_COPY:        /* Copy */
         if ( m_component )
             ItemCount = m_component->SelectItems( GetScreen()->m_BlockLocate,
-                                              m_unit, m_convert,
-                                              g_EditPinByPinIsOn );
+                                                  m_unit, m_convert,
+                                                  g_EditPinByPinIsOn );
         if( ItemCount )
         {
             MustDoPlace = 1;
@@ -127,8 +126,8 @@ int WinEDA_LibeditFrame::HandleBlockEnd( wxDC* DC )
     case BLOCK_DELETE:     /* Delete */
         if ( m_component )
             ItemCount = m_component->SelectItems( GetScreen()->m_BlockLocate,
-                                              m_unit, m_convert,
-                                              g_EditPinByPinIsOn );
+                                                  m_unit, m_convert,
+                                                  g_EditPinByPinIsOn );
         if( ItemCount )
             SaveCopyInUndoList( m_component );
         if ( m_component )
@@ -146,8 +145,8 @@ int WinEDA_LibeditFrame::HandleBlockEnd( wxDC* DC )
     case BLOCK_MIRROR_Y:
         if ( m_component )
             ItemCount = m_component->SelectItems( GetScreen()->m_BlockLocate,
-                                              m_unit, m_convert,
-                                              g_EditPinByPinIsOn );
+                                                  m_unit, m_convert,
+                                                  g_EditPinByPinIsOn );
         if( ItemCount )
             SaveCopyInUndoList( m_component );
         pt = GetScreen()->m_BlockLocate.Centre();
@@ -169,7 +168,7 @@ int WinEDA_LibeditFrame::HandleBlockEnd( wxDC* DC )
 
     if( MustDoPlace <= 0 )
     {
-        if( GetScreen()->m_BlockLocate.m_Command  != BLOCK_SELECT_ITEMS_ONLY )
+        if( GetScreen()->m_BlockLocate.m_Command != BLOCK_SELECT_ITEMS_ONLY )
             if ( m_component )
                 m_component->ClearSelectedItems();
 
@@ -179,8 +178,7 @@ int WinEDA_LibeditFrame::HandleBlockEnd( wxDC* DC )
         DrawPanel->ManageCurseur = NULL;
         DrawPanel->ForceCloseManageCurseur = NULL;
         GetScreen()->SetCurItem( NULL );
-        SetToolID( m_ID_current_state, DrawPanel->m_PanelDefaultCursor,
-                   wxEmptyString );
+        SetToolID( m_ID_current_state, DrawPanel->m_PanelDefaultCursor, wxEmptyString );
         DrawPanel->Refresh( TRUE );
     }
 
@@ -269,8 +267,7 @@ void WinEDA_LibeditFrame::HandleBlockPlace( wxDC* DC )
     GetScreen()->SetCurItem( NULL );
     DrawPanel->Refresh( TRUE );
 
-    SetToolID( m_ID_current_state, DrawPanel->m_PanelDefaultCursor,
-               wxEmptyString );
+    SetToolID( m_ID_current_state, DrawPanel->m_PanelDefaultCursor, wxEmptyString );
 }
 
 
@@ -298,25 +295,19 @@ void DrawMovingBlockOutlines( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
 
     if( erase )
     {
-        PtBlock->Draw( panel, DC, PtBlock->m_MoveVector, g_XorMode,
-                       PtBlock->m_Color );
+        PtBlock->Draw( panel, DC, PtBlock->m_MoveVector, g_XorMode, PtBlock->m_Color );
 
         component->Draw( panel, DC, PtBlock->m_MoveVector, unit, convert,
-                         g_XorMode, -1, DefaultTransformMatrix,
-                         true, true, true );
+                         g_XorMode, -1, DefaultTransform, true, true, true );
     }
 
     /* Repaint new view */
-    PtBlock->m_MoveVector.x =
-        screen->m_Curseur.x - PtBlock->m_BlockLastCursorPosition.x;
-    PtBlock->m_MoveVector.y =
-        screen->m_Curseur.y - PtBlock->m_BlockLastCursorPosition.y;
+    PtBlock->m_MoveVector.x = screen->m_Curseur.x - PtBlock->m_BlockLastCursorPosition.x;
+    PtBlock->m_MoveVector.y = screen->m_Curseur.y - PtBlock->m_BlockLastCursorPosition.y;
 
     GRSetDrawMode( DC, g_XorMode );
-    PtBlock->Draw( panel, DC, PtBlock->m_MoveVector, g_XorMode,
-                   PtBlock->m_Color );
+    PtBlock->Draw( panel, DC, PtBlock->m_MoveVector, g_XorMode, PtBlock->m_Color );
 
     component->Draw( panel, DC, PtBlock->m_MoveVector, unit, convert,
-                     g_XorMode, -1, DefaultTransformMatrix,
-                     true, true, true );
+                     g_XorMode, -1, DefaultTransform, true, true, true );
 }
diff --git a/eeschema/class_libentry.cpp b/eeschema/class_libentry.cpp
index 372d805638..98a910ce29 100644
--- a/eeschema/class_libentry.cpp
+++ b/eeschema/class_libentry.cpp
@@ -293,12 +293,9 @@ wxString LIB_COMPONENT::ReturnSubReference( int aUnit )
 }
 
 
-void LIB_COMPONENT::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDc,
-                          const wxPoint& aOffset, int aMulti,
-                          int aConvert, int aDrawMode, int aColor,
-                          const int aTransformMatrix[2][2],
-                          bool aShowPinText, bool aDrawFields,
-                          bool aOnlySelected )
+void LIB_COMPONENT::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDc, const wxPoint& aOffset, int aMulti,
+                          int aConvert, int aDrawMode, int aColor, const TRANSFORM& aTransform,
+                          bool aShowPinText, bool aDrawFields, bool aOnlySelected )
 {
     BASE_SCREEN*   screen = aPanel->GetScreen();
 
@@ -336,14 +333,12 @@ void LIB_COMPONENT::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDc,
 
             if( drawItem.Type() == COMPONENT_FIELD_DRAW_TYPE )
             {
-                drawItem.Draw( aPanel, aDc, aOffset, aColor, aDrawMode,
-                               (void*) NULL, aTransformMatrix );
+                drawItem.Draw( aPanel, aDc, aOffset, aColor, aDrawMode, NULL, aTransform );
             }
 
             // Now, draw only the background for items with
             // m_Fill == FILLED_WITH_BG_BODYCOLOR:
-            drawItem.Draw( aPanel, aDc, aOffset, aColor, aDrawMode,
-                           (void*) false, aTransformMatrix );
+            drawItem.Draw( aPanel, aDc, aOffset, aColor, aDrawMode, false, aTransform );
         }
     }
 
@@ -368,19 +363,18 @@ void LIB_COMPONENT::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDc,
 
         if( drawItem.Type() == COMPONENT_PIN_DRAW_TYPE )
         {
-            drawItem.Draw( aPanel, aDc, aOffset, aColor, aDrawMode,
-                           (void*) aShowPinText, aTransformMatrix );
+            drawItem.Draw( aPanel, aDc, aOffset, aColor, aDrawMode, (void*) aShowPinText,
+                           aTransform );
         }
         else if( drawItem.Type() == COMPONENT_FIELD_DRAW_TYPE )
         {
-            drawItem.Draw( aPanel, aDc, aOffset, aColor, aDrawMode,
-                           (void*) NULL, aTransformMatrix );
+            drawItem.Draw( aPanel, aDc, aOffset, aColor, aDrawMode, (void*) NULL, aTransform );
         }
         else
         {
             bool forceNoFill = drawItem.m_Fill == FILLED_WITH_BG_BODYCOLOR;
-            drawItem.Draw( aPanel, aDc, aOffset, aColor, aDrawMode,
-                           (void*) forceNoFill, aTransformMatrix );
+            drawItem.Draw( aPanel, aDc, aOffset, aColor, aDrawMode, (void*) forceNoFill,
+                           aTransform );
         }
 
     }
@@ -409,7 +403,7 @@ void LIB_COMPONENT::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDc,
 
 
 void LIB_COMPONENT::Plot( PLOTTER* aPlotter, int aUnit, int aConvert,
-                          const wxPoint& aOffset, const int aTransform[2][2] )
+                          const wxPoint& aOffset, const TRANSFORM& aTransform )
 {
     wxASSERT( aPlotter != NULL );
 
@@ -451,7 +445,7 @@ from component %s in library %s." ),
     LIB_DRAW_ITEM_LIST::iterator i;
 
     if( aDc != NULL )
-        aItem->Draw( aPanel, aDc, wxPoint( 0, 0 ), -1, g_XorMode, NULL, DefaultTransformMatrix );
+        aItem->Draw( aPanel, aDc, wxPoint( 0, 0 ), -1, g_XorMode, NULL, DefaultTransform );
 
     for( i = drawings.begin(); i < drawings.end(); i++ )
     {
@@ -1383,30 +1377,33 @@ LIB_DRAW_ITEM* LIB_COMPONENT::LocateDrawItem( int aUnit, int aConvert,
  *                         Otherwise NULL.
  */
 LIB_DRAW_ITEM* LIB_COMPONENT::LocateDrawItem( int aUnit, int aConvert, KICAD_T aType,
-                                              const wxPoint& aPoint, const int aTransform[2][2] )
+                                              const wxPoint& aPoint, const TRANSFORM& aTransform )
 {
     /* we use LocateDrawItem( int aUnit, int convert, KICAD_T type, const
      * wxPoint& pt ) to search items.
      * because this function uses DefaultTransformMatrix as orient/mirror matrix
      * we temporary copy aTransMat in DefaultTransformMatrix
      */
-    LIB_DRAW_ITEM * item;
-    int matrix[2][2];
+    LIB_DRAW_ITEM* item;
+    TRANSFORM transform;
+
     for ( int ii = 0; ii < 2; ii++ )
     {
         for ( int jj = 0; jj < 2; jj++ )
         {
-            matrix[ii][jj] = aTransform[ii][jj];
-            EXCHG( matrix[ii][jj], DefaultTransformMatrix[ii][jj] );
+            transform = DefaultTransform;
+            DefaultTransform = aTransform;
         }
     }
+
     item = LocateDrawItem( aUnit, aConvert, aType, aPoint );
+
     //Restore matrix
     for ( int ii = 0; ii < 2; ii++ )
     {
         for ( int jj = 0; jj < 2; jj++ )
         {
-            EXCHG( matrix[ii][jj], DefaultTransformMatrix[ii][jj] );
+            DefaultTransform = transform;
         }
     }
 
diff --git a/eeschema/class_libentry.h b/eeschema/class_libentry.h
index 17cd76fc5c..97cf776681 100644
--- a/eeschema/class_libentry.h
+++ b/eeschema/class_libentry.h
@@ -6,7 +6,7 @@
 #define CLASS_LIBENTRY_H
 
 #include "lib_draw_item.h"
-#include "class_libentry_fields.h"
+#include "lib_field.h"
 
 #include <map>
 
@@ -14,6 +14,7 @@
 class CMP_LIBRARY;
 class LIB_ALIAS;
 
+
 /**
  * LIB_ALIAS map sorting.
  */
@@ -312,7 +313,7 @@ public:
      */
     void Draw( WinEDA_DrawPanel* aPanel, wxDC* aDc, const wxPoint& aOffset,
                int aMulti, int aConvert, int aDrawMode, int aColor = -1,
-               const int aTransform[2][2] = DefaultTransformMatrix,
+               const TRANSFORM& aTransform = DefaultTransform,
                bool aShowPinText = true, bool aDrawFields = true,
                bool aOnlySelected = false );
 
@@ -325,7 +326,7 @@ public:
      * @param aTransform - Component plot transform matrix.
      */
     void Plot( PLOTTER* aPlotter, int aUnit, int aConvert, const wxPoint& aOffset,
-               const int aTransform[2][2] );
+               const TRANSFORM& aTransform );
 
     /**
      * Add a new draw \a aItem to the draw object list.
@@ -493,7 +494,7 @@ public:
      * @return The draw object if found.  Otherwise NULL.
      */
     LIB_DRAW_ITEM* LocateDrawItem( int aUnit, int aConvert, KICAD_T aType,
-                                   const wxPoint& aPoint, const int aTransfrom[2][2] );
+                                   const wxPoint& aPoint, const TRANSFORM& aTransfrom );
 
     /**
      * Return a reference to the draw item list.
diff --git a/eeschema/class_pin.cpp b/eeschema/class_pin.cpp
index d47d6e664d..7e242bb3c9 100644
--- a/eeschema/class_pin.cpp
+++ b/eeschema/class_pin.cpp
@@ -17,6 +17,7 @@
 #include "libeditframe.h"
 #include "class_libentry.h"
 #include "class_pin.h"
+#include "transform.h"
 
 #include "bitmaps.h"
 
@@ -536,7 +537,7 @@ bool LIB_PIN::HitTest( const wxPoint& aRefPos )
     if( mindist < 3 )
         mindist = 3;        // = 3 mils
 
-    return HitTest( aRefPos, mindist, DefaultTransformMatrix );
+    return HitTest( aRefPos, mindist, DefaultTransform );
 }
 
 /** Function HitTest
@@ -545,11 +546,10 @@ bool LIB_PIN::HitTest( const wxPoint& aRefPos )
  * @param aThreshold = max distance to a segment
  * @param aTransMat = the transform matrix
  */
-bool LIB_PIN::HitTest( wxPoint aRefPos, int aThreshold,
-                       const int aTransMat[2][2] )
+bool LIB_PIN::HitTest( wxPoint aRefPos, int aThreshold, const TRANSFORM& aTransform )
 {
-    wxPoint pinPos = TransformCoordinate( aTransMat, m_Pos );
-    wxPoint pinEnd = TransformCoordinate( aTransMat, ReturnPinEndPoint() );
+    wxPoint pinPos = aTransform.TransformCoordinate( m_Pos );
+    wxPoint pinEnd = aTransform.TransformCoordinate( ReturnPinEndPoint() );
 
     return TestSegmentHit( aRefPos, pinPos, pinEnd, aThreshold );
 }
@@ -791,18 +791,17 @@ int LIB_PIN::GetPenSize()
 }
 
 
-void LIB_PIN::Draw( WinEDA_DrawPanel* aPanel,
-                    wxDC*             aDC,
-                    const wxPoint&    aOffset,
-                    int               aColor,
-                    int               aDrawMode,
-                    void*             aData,
-                    const int         aTransformMatrix[2][2] )
+void LIB_PIN::drawGraphic( WinEDA_DrawPanel* aPanel,
+                           wxDC*             aDC,
+                           const wxPoint&    aOffset,
+                           int               aColor,
+                           int               aDrawMode,
+                           void*             aData,
+                           const TRANSFORM&  aTransform )
 {
     // Invisible pins are only drawn on request.  In libedit they are drawn
     // in g_InvisibleItemColor because we must see them.
-    WinEDA_SchematicFrame* frame =
-        (WinEDA_SchematicFrame*) wxGetApp().GetTopWindow();
+    WinEDA_SchematicFrame* frame = (WinEDA_SchematicFrame*) wxGetApp().GetTopWindow();
 
     if( ( m_Attributs & PINNOTDRAW ) )
     {
@@ -819,10 +818,10 @@ void LIB_PIN::Draw( WinEDA_DrawPanel* aPanel,
         DrawPinText = false;
 
     /* Calculate pin orient taking in account the component orientation. */
-    int orient = ReturnPinDrawOrient( aTransformMatrix );
+    int orient = ReturnPinDrawOrient( aTransform );
 
     /* Calculate the pin position */
-    wxPoint pos1 = TransformCoordinate( aTransformMatrix, m_Pos ) + aOffset;
+    wxPoint pos1 = aTransform.TransformCoordinate( m_Pos ) + aOffset;
 
     /* Drawing from the pin and the special symbol combination */
     DrawPinSymbol( aPanel, aDC, pos1, orient, aDrawMode, aColor );
@@ -1476,7 +1475,7 @@ wxPoint LIB_PIN::ReturnPinEndPoint()
  *  according to its orientation and the matrix transform (rot, mirror) TransMat
  * @param  TransMat = transform matrix
  */
-int LIB_PIN::ReturnPinDrawOrient( const int TransMat[2][2] )
+int LIB_PIN::ReturnPinDrawOrient( const TRANSFORM& aTransform )
 {
     int     orient;
     wxPoint end;    // position of a end pin starting at 0,0 according to its orientation, lenght = 1
@@ -1497,7 +1496,7 @@ int LIB_PIN::ReturnPinDrawOrient( const int TransMat[2][2] )
     }
 
     // = pos of end point, according to the component orientation
-    end = TransformCoordinate( TransMat, end );
+    end = aTransform.TransformCoordinate( end );
     orient = PIN_UP;
     if( end.x == 0 )
     {
@@ -1653,14 +1652,14 @@ void LIB_PIN::DoMirrorHorizontal( const wxPoint& center )
 
 
 void LIB_PIN::DoPlot( PLOTTER* plotter, const wxPoint& offset, bool fill,
-                      const int transform[2][2] )
+                      const TRANSFORM& aTransform )
 {
     if( m_Attributs & PINNOTDRAW )
         return;
 
-    int orient = ReturnPinDrawOrient( transform );
+    int orient = ReturnPinDrawOrient( aTransform );
 
-    wxPoint pos = TransformCoordinate( transform, m_Pos ) + offset;
+    wxPoint pos = aTransform.TransformCoordinate( m_Pos ) + offset;
 
     plotter->set_current_line_width( GetPenSize() );
     PlotPinSymbol( plotter, pos, m_PinLen, orient, m_PinShape );
diff --git a/eeschema/class_pin.h b/eeschema/class_pin.h
index 92a3570408..79d8b38bbf 100644
--- a/eeschema/class_pin.h
+++ b/eeschema/class_pin.h
@@ -9,8 +9,8 @@
 
 #include "lib_draw_item.h"
 
-#define TARGET_PIN_DIAM     12  /* Circle diameter drawn at the active end of
-                                 * pins */
+
+#define TARGET_PIN_DIAM     12  /* Circle diameter drawn at the active end of pins */
 
 #define DEFAULT_TEXT_SIZE   50  /* Default size for field texts */
 #define PART_NAME_LEN       15  /* Maximum length of part name. */
@@ -80,6 +80,12 @@ enum DrawPinOrient {
 
 class LIB_PIN : public LIB_DRAW_ITEM
 {
+    /**
+     * Draw the pin.
+     */
+    void drawGraphic( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint& aOffset,
+                      int aColor, int aDrawMode, void* aData, const TRANSFORM& aTransform );
+
 public:
     int      m_PinLen;      /* Pin length */
     int      m_Orient;      /* Pin orientation (Up, Down, Left, Right) */
@@ -106,7 +112,7 @@ public:
     int      m_Width;       /* Line width */
 
 public:
-    LIB_PIN(LIB_COMPONENT * aParent);
+    LIB_PIN( LIB_COMPONENT * aParent );
     LIB_PIN( const LIB_PIN& aPin );
     ~LIB_PIN() { }
 
@@ -148,13 +154,13 @@ public:
      * @param aTransMat - the transform matrix
      * @return - true if the point aPosRef is near this object
      */
-    virtual bool HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] );
+    virtual bool HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform );
 
     virtual void DisplayInfo( WinEDA_DrawFrame* frame );
     virtual EDA_Rect GetBoundingBox();
     wxPoint ReturnPinEndPoint();
 
-    int ReturnPinDrawOrient( const int TransMat[2][2] );
+    int ReturnPinDrawOrient( const TRANSFORM& aTransform );
 
     /**
      * Fill a string buffer with pin number.
@@ -194,7 +200,7 @@ public:
     void SetName( const wxString& aName );
 
     /**
-     * Set the /a aSize of the pin name text.
+     * Set the \a aSize of the pin name text.
      *
      * This will also update the text size of the name of the pins marked
      * by EnableEditMode().
@@ -323,9 +329,6 @@ public:
      */
     virtual int GetPenSize();
 
-    void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset,
-               int aColor, int aDrawMode, void* aData, const int aTransformMatrix[2][2] );
-
     void DrawPinSymbol( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint& aPosition,
                         int aOrientation, int aDrawMode, int aColor = -1 );
 
@@ -438,7 +441,7 @@ protected:
     virtual wxPoint DoGetPosition() { return m_Pos; }
     virtual void DoMirrorHorizontal( const wxPoint& aCenter );
     virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
-                         const int aTransform[2][2] );
+                         const TRANSFORM& aTransform );
     virtual int DoGetWidth() { return m_Width; }
     virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; }
 };
diff --git a/eeschema/class_sch_cmp_field.cpp b/eeschema/class_sch_cmp_field.cpp
index b98a9a8997..d4a7942ca8 100644
--- a/eeschema/class_sch_cmp_field.cpp
+++ b/eeschema/class_sch_cmp_field.cpp
@@ -98,7 +98,7 @@ void SCH_FIELD::Draw( WinEDA_DrawPanel* panel, wxDC* DC,
     /* Calculate the text orientation, according to the component
      * orientation/mirror */
     orient = m_Orient;
-    if( parentComponent->m_Transform[0][1] )  // Rotate component 90 degrees.
+    if( parentComponent->m_Transform.y1 )  // Rotate component 90 degrees.
     {
         if( orient == TEXT_ORIENT_HORIZ )
             orient = TEXT_ORIENT_VERT;
@@ -245,11 +245,11 @@ EDA_Rect SCH_FIELD::GetBoundaryBox() const
     hjustify = m_HJustify;
     vjustify = m_VJustify;
 
-    pos2 = pos + TransformCoordinate( parentComponent->m_Transform, pos1 );
+    pos2 = pos + parentComponent->m_Transform.TransformCoordinate( pos1 );
 
     /* Calculate the text orientation, according to the component
      * orientation/mirror */
-    if( parentComponent->m_Transform[0][1] )
+    if( parentComponent->m_Transform.y1 )
     {
         if( orient == TEXT_ORIENT_HORIZ )
             orient = TEXT_ORIENT_VERT;
@@ -259,20 +259,20 @@ EDA_Rect SCH_FIELD::GetBoundaryBox() const
 
     /* Calculate the text justification, according to the component
      * orientation/mirror */
-    if( parentComponent->m_Transform[0][1] )
+    if( parentComponent->m_Transform.y1 )
     {
         /* is it mirrored (for text justify)*/
         EXCHG( hjustify, vjustify );
-        if( parentComponent->m_Transform[1][0] < 0 )
+        if( parentComponent->m_Transform.x2 < 0 )
             NEGATE( vjustify );
-        if( parentComponent->m_Transform[0][1] > 0 )
+        if( parentComponent->m_Transform.y1 > 0 )
             NEGATE( hjustify );
     }
     else    /* component horizontal: is it mirrored (for text justify)*/
     {
-        if( parentComponent->m_Transform[0][0] < 0 )
+        if( parentComponent->m_Transform.x1 < 0 )
             NEGATE( hjustify );
-        if( parentComponent->m_Transform[1][1] > 0 )
+        if( parentComponent->m_Transform.y2 > 0 )
             NEGATE( vjustify );
     }
 
diff --git a/eeschema/class_sch_component.cpp b/eeschema/class_sch_component.cpp
index 8c58be656b..1b61cb0487 100644
--- a/eeschema/class_sch_component.cpp
+++ b/eeschema/class_sch_component.cpp
@@ -151,10 +151,7 @@ void SCH_COMPONENT::Init( const wxPoint& pos )
     m_Convert = 0;  // De Morgan Handling
 
     // The rotation/mirror transformation matrix. pos normal
-    m_Transform[0][0] = 1;
-    m_Transform[0][1] = 0;
-    m_Transform[1][0] = 0;
-    m_Transform[1][1] = -1;
+    m_Transform = TRANSFORM();
 
     // construct only the mandatory fields, which are the first 4 only.
     for( int i = 0; i < MANDATORY_FIELDS; ++i )
@@ -578,10 +575,10 @@ EDA_Rect SCH_COMPONENT::GetBoundaryBox() const
     }
 
     /* Compute the real Boundary box (rotated, mirrored ...)*/
-    int x1 = m_Transform[0][0] *x0 + m_Transform[0][1] *y0;
-    int y1 = m_Transform[1][0] *x0 + m_Transform[1][1] *y0;
-    int x2 = m_Transform[0][0] *xm + m_Transform[0][1] *ym;
-    int y2 = m_Transform[1][0] *xm + m_Transform[1][1] *ym;
+    int x1 = m_Transform.x1 * x0 + m_Transform.y1 * y0;
+    int y1 = m_Transform.x2 * x0 + m_Transform.y2 * y0;
+    int x2 = m_Transform.x1 * xm + m_Transform.y1 * ym;
+    int y2 = m_Transform.x2 * xm + m_Transform.y2 * ym;
 
     // H and W must be > 0:
     if( x2 < x1 )
@@ -608,10 +605,10 @@ void SCH_COMPONENT::SwapData( SCH_COMPONENT* copyitem )
     EXCHG( m_Pos, copyitem->m_Pos );
     EXCHG( m_Multi, copyitem->m_Multi );
     EXCHG( m_Convert, copyitem->m_Convert );
-    EXCHG( m_Transform[0][0], copyitem->m_Transform[0][0] );
-    EXCHG( m_Transform[0][1], copyitem->m_Transform[0][1] );
-    EXCHG( m_Transform[1][0], copyitem->m_Transform[1][0] );
-    EXCHG( m_Transform[1][1], copyitem->m_Transform[1][1] );
+
+    TRANSFORM tmp = m_Transform;
+    m_Transform = copyitem->m_Transform;
+    copyitem->m_Transform = tmp;
 
     m_Fields.swap( copyitem->m_Fields );    // std::vector's swap()
 
@@ -727,44 +724,44 @@ void SCH_COMPONENT::ClearAnnotation( SCH_SHEET_PATH* aSheet )
 /*****************************************************************/
 void SCH_COMPONENT::SetOrientation( int aOrientation )
 {
-    int  TempMat[2][2];
-    bool Transform = FALSE;
+    TRANSFORM temp = TRANSFORM();
+    bool Transform = false;
 
     switch( aOrientation )
     {
     case CMP_ORIENT_0:
     case CMP_NORMAL:            /* Position Initiale */
-        m_Transform[0][0] = 1;
-        m_Transform[1][1] = -1;
-        m_Transform[1][0] = m_Transform[0][1] = 0;
+        m_Transform.x1 = 1;
+        m_Transform.y2 = -1;
+        m_Transform.x2 = m_Transform.y1 = 0;
         break;
 
     case CMP_ROTATE_CLOCKWISE:            /* Rotate + */
-        TempMat[0][0] = TempMat[1][1] = 0;
-        TempMat[0][1] = 1;
-        TempMat[1][0] = -1;
-        Transform     = TRUE;
+        temp.x1   = temp.y2 = 0;
+        temp.y1   = 1;
+        temp.x2   = -1;
+        Transform = true;
         break;
 
     case CMP_ROTATE_COUNTERCLOCKWISE:             /* Rotate - */
-        TempMat[0][0] = TempMat[1][1] = 0;
-        TempMat[0][1] = -1;
-        TempMat[1][0] = 1;
-        Transform     = TRUE;
+        temp.x1   = temp.y2 = 0;
+        temp.y1   = -1;
+        temp.x2   = 1;
+        Transform = true;
         break;
 
     case CMP_MIRROR_Y:          /* MirrorY */
-        TempMat[0][0] = -1;
-        TempMat[1][1] = 1;
-        TempMat[0][1] = TempMat[1][0] = 0;
-        Transform     = TRUE;
+        temp.x1   = -1;
+        temp.y2   = 1;
+        temp.y1   = temp.x2 = 0;
+        Transform = true;
         break;
 
     case CMP_MIRROR_X:            /* MirrorX */
-        TempMat[0][0] = 1;
-        TempMat[1][1] = -1;
-        TempMat[0][1] = TempMat[1][0] = 0;
-        Transform     = TRUE;
+        temp.x1   = 1;
+        temp.y2   = -1;
+        temp.y1   = temp.x2 = 0;
+        Transform = TRUE;
         break;
 
     case CMP_ORIENT_90:
@@ -841,24 +838,13 @@ void SCH_COMPONENT::SetOrientation( int aOrientation )
          *  have:
          *     transform coord = old_m_Transform * coord * TempMat
          */
-        int NewMatrix[2][2];
+        TRANSFORM newTransform;
 
-        NewMatrix[0][0] = m_Transform[0][0] *TempMat[0][0] +
-                          m_Transform[1][0] *TempMat[0][1];
-
-        NewMatrix[0][1] = m_Transform[0][1] *TempMat[0][0] +
-                          m_Transform[1][1] *TempMat[0][1];
-
-        NewMatrix[1][0] = m_Transform[0][0] *TempMat[1][0] +
-                          m_Transform[1][0] *TempMat[1][1];
-
-        NewMatrix[1][1] = m_Transform[0][1] *TempMat[1][0] +
-                          m_Transform[1][1] *TempMat[1][1];
-
-        m_Transform[0][0] = NewMatrix[0][0];
-        m_Transform[0][1] = NewMatrix[0][1];
-        m_Transform[1][0] = NewMatrix[1][0];
-        m_Transform[1][1] = NewMatrix[1][1];
+        newTransform.x1 = m_Transform.x1 * temp.x1 + m_Transform.x2 * temp.y1;
+        newTransform.y1 = m_Transform.y1 * temp.x1 + m_Transform.y2 * temp.y1;
+        newTransform.x2 = m_Transform.x1 * temp.x2 + m_Transform.x2 * temp.y2;
+        newTransform.y2 = m_Transform.y1 * temp.x2 + m_Transform.y2 * temp.y2;
+        m_Transform = newTransform;
     }
 }
 
@@ -879,7 +865,7 @@ void SCH_COMPONENT::SetOrientation( int aOrientation )
 int SCH_COMPONENT::GetOrientation()
 {
     int type_rotate = CMP_ORIENT_0;
-    int ComponentMatOrient[2][2];
+    TRANSFORM transform;
     int ii;
 
     #define ROTATE_VALUES_COUNT 12
@@ -896,20 +882,21 @@ int SCH_COMPONENT::GetOrientation()
     };
 
     // Try to find the current transform option:
-    memcpy( ComponentMatOrient, m_Transform, sizeof( ComponentMatOrient ) );
+    transform = m_Transform;
 
     for( ii = 0; ii < ROTATE_VALUES_COUNT; ii++ )
     {
         type_rotate = rotate_value[ii];
         SetOrientation( type_rotate );
-        if( memcmp( ComponentMatOrient, m_Transform,
-                   sizeof(ComponentMatOrient) ) == 0 )
+
+        if( transform == m_Transform )
             return type_rotate;
     }
 
     // Error: orientation not found in list (should not happen)
     wxMessageBox( wxT( "Component orientation matrix internal error" ) );
-    memcpy( m_Transform, ComponentMatOrient, sizeof( ComponentMatOrient ) );
+    m_Transform = transform;
+
     return CMP_NORMAL;
 }
 
@@ -921,11 +908,7 @@ int SCH_COMPONENT::GetOrientation()
  */
 wxPoint SCH_COMPONENT::GetScreenCoord( const wxPoint& coord )
 {
-    wxPoint screenpos;
-
-    screenpos.x = m_Transform[0][0] *coord.x + m_Transform[0][1] *coord.y;
-    screenpos.y = m_Transform[1][0] *coord.x + m_Transform[1][1] *coord.y;
-    return screenpos;
+    return m_Transform.TransformCoordinate( coord );
 }
 
 
@@ -1100,8 +1083,7 @@ bool SCH_COMPONENT::Save( FILE* f ) const
         return false;
 
     if( fprintf( f, "\t%-4d %-4d %-4d %-4d\n",
-                 m_Transform[0][0], m_Transform[0][1],
-                 m_Transform[1][0], m_Transform[1][1] ) == EOF )
+                 m_Transform.x1, m_Transform.y1, m_Transform.x2, m_Transform.y2 ) == EOF )
         return false;
 
     if( fprintf( f, "$EndComp\n" ) == EOF )
@@ -1292,7 +1274,7 @@ bool SCH_COMPONENT::Matches( wxFindReplaceData& aSearchData, void* aAuxData, wxP
                 if( aFindLocation )
                 {
                     wxPoint pinpos = pin->m_Pos;
-                    pinpos = TransformCoordinate( m_Transform, pinpos );
+                    pinpos = m_Transform.TransformCoordinate( pinpos );
                     *aFindLocation = pinpos + m_Pos;
                 }
                 return true;
diff --git a/eeschema/class_sch_component.h b/eeschema/class_sch_component.h
index 5dfc659fcc..6cc5801d73 100644
--- a/eeschema/class_sch_component.h
+++ b/eeschema/class_sch_component.h
@@ -8,6 +8,7 @@
 
 #include "class_sch_screen.h"
 #include "class_sch_cmp_field.h"
+#include "transform.h"
 
 
 class SCH_SHEET_PATH;
@@ -62,8 +63,8 @@ public:
 
     int m_Convert;                    /* Handle multiple shape (for instance
                                        * De Morgan conversion) */
-    int m_Transform[2][2];             /* The rotation/mirror transformation
-                                        * matrix. */
+    TRANSFORM m_Transform;            /* The rotation/mirror transformation
+                                       * matrix. */
 
 private:
 
diff --git a/eeschema/dangling_ends.cpp b/eeschema/dangling_ends.cpp
index cb0152a7ba..21ec6d5d2f 100644
--- a/eeschema/dangling_ends.cpp
+++ b/eeschema/dangling_ends.cpp
@@ -147,8 +147,7 @@ LIB_PIN* WinEDA_SchematicFrame::LocatePinEnd( SCH_ITEM*      DrawList,
                                 // and in schematic Y axis is top to bottom
 
     else                        // calculate the pin position in schematic
-        pinpos = TransformCoordinate( DrawLibItem->m_Transform, pinpos )
-                 + DrawLibItem->m_Pos;
+        pinpos = DrawLibItem->m_Transform.TransformCoordinate( pinpos ) + DrawLibItem->m_Pos;
 
     if( pos == pinpos )
         return Pin;
@@ -261,8 +260,7 @@ wxPoint ReturnPinPhysicalPosition( LIB_PIN* Pin, SCH_COMPONENT* DrawLibItem )
         NEGATE( PinPos.y );
 
     else
-        PinPos = TransformCoordinate( DrawLibItem->m_Transform,
-                                      Pin->m_Pos ) + DrawLibItem->m_Pos;
+        PinPos = DrawLibItem->m_Transform.TransformCoordinate( Pin->m_Pos ) + DrawLibItem->m_Pos;
 
     return PinPos;
 }
diff --git a/eeschema/edit_component_in_schematic.cpp b/eeschema/edit_component_in_schematic.cpp
index fcb7e514f5..4ef26cb0ee 100644
--- a/eeschema/edit_component_in_schematic.cpp
+++ b/eeschema/edit_component_in_schematic.cpp
@@ -51,10 +51,10 @@ void WinEDA_SchematicFrame::StartMoveCmpField( SCH_FIELD* aField, wxDC* DC )
     // under some circumstances, but that inversion is not preserved by all
     // combinations of mirroring and rotation.  The following clause is true
     // when the number of rotations and the number of mirrorings are both odd.
-    if( comp->m_Transform[1][0] * comp->m_Transform[0][1] < 0 )
+    if( comp->m_Transform.x2 * comp->m_Transform.y1 < 0 )
         NEGATE( newpos.y );
 
-    newpos = TransformCoordinate( comp->m_Transform, newpos ) + pos;
+    newpos = comp->m_Transform.TransformCoordinate( newpos ) + pos;
 
     DrawPanel->CursorOff( DC );
     GetScreen()->m_Curseur = newpos;
@@ -184,7 +184,6 @@ modified!\nYou must create a new power"  ) );
 static void MoveCmpField( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
 {
     wxPoint pos;
-    int x1, y1;
     int fieldNdx;
 
     WinEDA_SchematicFrame* frame = (WinEDA_SchematicFrame*) panel->GetParent();
@@ -205,13 +204,9 @@ static void MoveCmpField( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
     pos = ( (SCH_COMPONENT*) currentField->GetParent() )->m_Pos;
 
     /* Positions are calculated by the transpose matrix,  Rotating mirror. */
-    x1 = panel->GetScreen()->m_Curseur.x - pos.x;
-    y1 = panel->GetScreen()->m_Curseur.y - pos.y;
+    wxPoint pt( panel->GetScreen()->m_Curseur - pos );
 
-    currentField->m_Pos.x = pos.x + component->m_Transform[0][0] * x1 +
-                            component->m_Transform[1][0] * y1;
-    currentField->m_Pos.y = pos.y + component->m_Transform[0][1] * x1 +
-                            component->m_Transform[1][1] * y1;
+    currentField->m_Pos = pos + component->m_Transform.TransformCoordinate( pt );
 
     currentField->Draw( panel, DC, wxPoint( 0, 0 ), g_XorMode );
 }
diff --git a/eeschema/edit_graphic_bodyitem_text.cpp b/eeschema/edit_graphic_bodyitem_text.cpp
index b776a19ad0..3c5f1e723e 100644
--- a/eeschema/edit_graphic_bodyitem_text.cpp
+++ b/eeschema/edit_graphic_bodyitem_text.cpp
@@ -222,26 +222,23 @@ void Dialog_BodyGraphicText_Properties::OnOkClick( wxCommandEvent& event )
 
 
 
-void WinEDA_LibeditFrame::EditSymbolText(wxDC* DC, LIB_DRAW_ITEM* DrawItem)
+void WinEDA_LibeditFrame::EditSymbolText( wxDC* DC, LIB_DRAW_ITEM* DrawItem )
 {
     int DrawMode = g_XorMode;
 
-    if ( ( DrawItem == NULL )
-         || ( DrawItem->Type() != COMPONENT_GRAPHIC_TEXT_DRAW_TYPE ) )
+    if ( ( DrawItem == NULL ) || ( DrawItem->Type() != COMPONENT_GRAPHIC_TEXT_DRAW_TYPE ) )
         return;
 
     /* Deleting old text. */
-    if( DC)
-        DrawItem->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, DrawMode, NULL,
-                        DefaultTransformMatrix );
+    if( DC )
+        DrawItem->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, DrawMode, NULL, DefaultTransform );
 
 
     Dialog_BodyGraphicText_Properties * frame =
-            new Dialog_BodyGraphicText_Properties( this,
-                                                   (LIB_TEXT*) DrawItem );
+            new Dialog_BodyGraphicText_Properties( this, (LIB_TEXT*) DrawItem );
     frame->ShowModal();
     frame->Destroy();
-    OnModify( );
+    OnModify();
 
     /* Display new text. */
     if( DC )
@@ -249,42 +246,6 @@ void WinEDA_LibeditFrame::EditSymbolText(wxDC* DC, LIB_DRAW_ITEM* DrawItem)
         if ( ( DrawItem->m_Flags & IS_MOVED ) == 0 )
             DrawMode = GR_DEFAULT_DRAWMODE;
 
-        DrawItem->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, DrawMode, NULL,
-                        DefaultTransformMatrix );
+        DrawItem->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, DrawMode, NULL, DefaultTransform );
     }
 }
-
-
-/****************************************************/
-void WinEDA_LibeditFrame::RotateSymbolText(wxDC * DC)
-/****************************************************/
-/*
-    90 deg Graphic text Rotation .
-*/
-{
-    LIB_TEXT* DrawItem = (LIB_TEXT *) m_drawItem;
-
-    if( DrawItem == NULL )
-        return;
-
-    /* Erase drawing (can be within a move command) */
-    if ( DrawPanel->ManageCurseur == NULL)
-        DrawItem->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, g_XorMode, NULL,
-                        DefaultTransformMatrix );
-    else
-        DrawPanel->ManageCurseur( DrawPanel, DC, FALSE );
-
-    if( DrawItem->m_Orient == TEXT_ORIENT_HORIZ )
-        DrawItem->m_Orient = TEXT_ORIENT_VERT;
-    else
-        DrawItem->m_Orient = TEXT_ORIENT_HORIZ;
-
-    OnModify( );
-
-    /* Redraw item with new orient */
-    if ( DrawPanel->ManageCurseur == NULL )
-        DrawItem->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, GR_DEFAULT_DRAWMODE,
-                        NULL, DefaultTransformMatrix );
-    else
-        DrawPanel->ManageCurseur( DrawPanel, DC, FALSE );
-}
diff --git a/eeschema/eelibs_draw_components.cpp b/eeschema/eelibs_draw_components.cpp
deleted file mode 100644
index 0c2feeebd9..0000000000
--- a/eeschema/eelibs_draw_components.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-/****************************************/
-/* Modules to handle component drawing. */
-/****************************************/
-
-#include "fctsys.h"
-#include "gr_basic.h"
-#include "common.h"
-#include "class_drawpanel.h"
-
-#include "program.h"
-#include "general.h"
-#include "protos.h"
-#include "class_library.h"
-
-#include <boost/foreach.hpp>
-
-
-//#define DRAW_ARC_WITH_ANGLE       // Used to select function to draw arcs
-
-
-/***************************************************************************/
-/** Function TransformCoordinate
- * Calculate the wew coordinate from the old one, according to the transform
- * matrix.
- * @param aTransformMatrix = rotation, mirror .. matrix
- * @param aPosition = the position to transform
- * @return the new coordinate
- */
-/***************************************************************************/
-wxPoint TransformCoordinate( const int      aTransformMatrix[2][2],
-                             const wxPoint& aPosition )
-{
-    wxPoint new_pos;
-
-    new_pos.x = ( aTransformMatrix[0][0] * aPosition.x ) +
-        ( aTransformMatrix[0][1] * aPosition.y );
-    new_pos.y = ( aTransformMatrix[1][0] * aPosition.x ) +
-        ( aTransformMatrix[1][1] * aPosition.y );
-
-    return new_pos;
-}
-
-
-/*****************************************************************************
- * Routine to rotate the given angular direction by the given Transformation. *
- * Input (and output) angles must be as follows:                              *
- *  Unit is 0.1 degre                                                         *
- * Angle1 in [0..3600], Angle2 > Angle1 in [0..7200]. Arc is assumed to be    *
- * less  than 180.0 degrees.                                                  *
- * Algorithm:                                                                 *
- * Map the angles to a point on the unit circle which is mapped using the     *
- * transform (only mirror and rotate so it remains on the unit circle) to     *
- * a new point which is used to detect new angle.                             *
- *****************************************************************************/
-bool MapAngles( int* Angle1, int* Angle2, const int TransMat[2][2] )
-{
-    int    Angle, Delta;
-    double x, y, t;
-    bool   swap = FALSE;
-
-    Delta = *Angle2 - *Angle1;
-    if( Delta >= 1800 )
-    {
-        *Angle1 -= 1;
-        *Angle2 += 1;
-    }
-
-    x = cos( *Angle1 * M_PI / 1800.0 );
-    y = sin( *Angle1 * M_PI / 1800.0 );
-    t = x * TransMat[0][0] + y * TransMat[0][1];
-    y = x * TransMat[1][0] + y * TransMat[1][1];
-    x = t;
-    *Angle1 = (int) ( atan2( y, x ) * 1800.0 / M_PI + 0.5 );
-
-    x = cos( *Angle2 * M_PI / 1800.0 );
-    y = sin( *Angle2 * M_PI / 1800.0 );
-    t = x * TransMat[0][0] + y * TransMat[0][1];
-    y = x * TransMat[1][0] + y * TransMat[1][1];
-    x = t;
-    *Angle2 = (int) ( atan2( y, x ) * 1800.0 / M_PI + 0.5 );
-
-    NORMALIZE_ANGLE( *Angle1 );
-    NORMALIZE_ANGLE( *Angle2 );
-    if( *Angle2 < *Angle1 )
-        *Angle2 += 3600;
-
-    if( *Angle2 - *Angle1 > 1800 ) /* Need to swap the two angles. */
-    {
-        Angle   = (*Angle1);
-        *Angle1 = (*Angle2);
-        *Angle2 = Angle;
-
-        NORMALIZE_ANGLE( *Angle1 );
-        NORMALIZE_ANGLE( *Angle2 );
-        if( *Angle2 < *Angle1 )
-            *Angle2 += 3600;
-        swap = TRUE;
-    }
-
-    if( Delta >= 1800 )
-    {
-        *Angle1 += 1;
-        *Angle2 -= 1;
-    }
-
-    return swap;
-}
diff --git a/eeschema/eeschema.cpp b/eeschema/eeschema.cpp
index 6a13d93884..aa14d8edba 100644
--- a/eeschema/eeschema.cpp
+++ b/eeschema/eeschema.cpp
@@ -17,6 +17,8 @@
 #include "protos.h"
 #include "hotkeys.h"
 
+#include "transform.h"
+
 #include <wx/snglinst.h>
 
 
@@ -83,7 +85,7 @@ int g_ItemSelectetColor = BROWN;
 // in eeschema
 int g_InvisibleItemColor = DARKGRAY;
 
-int DefaultTransformMatrix[2][2] = { { 1, 0 }, { 0, -1 } };
+TRANSFORM DefaultTransform = TRANSFORM( 1, 0, 0, -1 );
 
 
 /************************************/
diff --git a/eeschema/find.cpp b/eeschema/find.cpp
index 4b4e8dcb5c..3dcd07855f 100644
--- a/eeschema/find.cpp
+++ b/eeschema/find.cpp
@@ -183,7 +183,7 @@ SCH_ITEM* WinEDA_SchematicFrame::FindComponentAndItem( const wxString& component
         }
         wxPoint delta;
         pos  -= Component->m_Pos;
-        delta = TransformCoordinate( Component->m_Transform, pos );
+        delta = Component->m_Transform.TransformCoordinate( pos );
         pos   = delta + Component->m_Pos;
 
         wxPoint old_cursor_position    = sheet->LastScreen()->m_Curseur;
diff --git a/eeschema/getpart.cpp b/eeschema/getpart.cpp
index 9f63260856..576ae23530 100644
--- a/eeschema/getpart.cpp
+++ b/eeschema/getpart.cpp
@@ -23,8 +23,8 @@
 static void ShowWhileMoving( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
 static void ExitPlaceCmp( WinEDA_DrawPanel* Panel, wxDC* DC );
 
-static int     OldTransMat[2][2];
-static wxPoint OldPos;
+static TRANSFORM OldTransform;
+static wxPoint   OldPos;
 
 
 wxString WinEDA_SchematicFrame::SelectFromLibBrowser( void )
@@ -294,7 +294,7 @@ static void ExitPlaceCmp( WinEDA_DrawPanel* Panel, wxDC* DC )
     {
         wxPoint move_vector = OldPos - Component->m_Pos;
         Component->Move( move_vector );
-        memcpy( Component->m_Transform, OldTransMat, sizeof(OldTransMat) );
+        Component->m_Transform = OldTransform;
         Component->m_Flags = 0;
     }
 
@@ -401,8 +401,7 @@ void WinEDA_SchematicFrame::ConvertPart( SCH_COMPONENT* DrawComponent,
 }
 
 
-void WinEDA_SchematicFrame::StartMovePart( SCH_COMPONENT* Component,
-                                           wxDC*          DC )
+void WinEDA_SchematicFrame::StartMovePart( SCH_COMPONENT* Component, wxDC* DC )
 {
     if( Component == NULL )
         return;
@@ -426,7 +425,7 @@ void WinEDA_SchematicFrame::StartMovePart( SCH_COMPONENT* Component,
     DrawPanel->ForceCloseManageCurseur = ExitPlaceCmp;
     GetScreen()->SetCurItem( Component );
     OldPos = Component->m_Pos;
-    memcpy( OldTransMat, Component->m_Transform, sizeof(OldTransMat) );
+    OldTransform = Component->m_Transform;
 
 #if 1
 
diff --git a/eeschema/hotkeys.cpp b/eeschema/hotkeys.cpp
index 67eb1e117b..f12551a39a 100644
--- a/eeschema/hotkeys.cpp
+++ b/eeschema/hotkeys.cpp
@@ -88,16 +88,13 @@ static Ki_HotkeyInfo HkResetLocalCoord( wxT( "Reset local coord." ),
                                         HK_RESET_LOCAL_COORD, ' ' );
 
 /* Undo */
-static Ki_HotkeyInfo HkUndo( wxT( "Undo" ), HK_UNDO, GR_KB_CTRL + 'Z',
-                             (int) wxID_UNDO );
+static Ki_HotkeyInfo HkUndo( wxT( "Undo" ), HK_UNDO, GR_KB_CTRL + 'Z', (int) wxID_UNDO );
 
 /* Redo */
 #if !defined( __WXMAC__ )
-static Ki_HotkeyInfo HkRedo( wxT( "Redo" ), HK_REDO, GR_KB_CTRL + 'Y',
-                             (int) wxID_REDO );
+static Ki_HotkeyInfo HkRedo( wxT( "Redo" ), HK_REDO, GR_KB_CTRL + 'Y', (int) wxID_REDO );
 #else
-static Ki_HotkeyInfo HkRedo( wxT( "Redo" ), HK_REDO,
-                             GR_KB_SHIFT + GR_KB_CTRL + 'Z',
+static Ki_HotkeyInfo HkRedo( wxT( "Redo" ), HK_REDO, GR_KB_SHIFT + GR_KB_CTRL + 'Z',
                              (int) wxID_REDO );
 #endif
 
@@ -131,27 +128,21 @@ static Ki_HotkeyInfo HkCopyComponentOrText( wxT( "Copy Component or Label" ),
                                             HK_COPY_COMPONENT_OR_LABEL, 'C',
                                             ID_POPUP_SCH_COPY_ITEM );
 
-static Ki_HotkeyInfo HkDrag( wxT( "Drag Schematic Item" ),
-                             HK_DRAG, 'G',
+static Ki_HotkeyInfo HkDrag( wxT( "Drag Schematic Item" ), HK_DRAG, 'G',
                              ID_POPUP_SCH_DRAG_CMP_REQUEST );
 static Ki_HotkeyInfo HkMove2Drag( wxT( "Switch move block to drag block" ),
                                   HK_MOVEBLOCK_TO_DRAGBLOCK, '\t' );
-static Ki_HotkeyInfo HkInsert( wxT( "Repeat Last Item" ), HK_REPEAT_LAST,
-                               WXK_INSERT );
+static Ki_HotkeyInfo HkInsert( wxT( "Repeat Last Item" ), HK_REPEAT_LAST, WXK_INSERT );
 static Ki_HotkeyInfo HkDelete( wxT( "Delete Item" ), HK_DELETE, WXK_DELETE );
 
-static Ki_HotkeyInfo HkFindItem( wxT( "Find Item" ), HK_FIND_ITEM, 'F'
-                                 + GR_KB_CTRL );
-static Ki_HotkeyInfo HkFindNextItem( wxT( "Find Next Item" ), HK_FIND_NEXT_ITEM,
-                                     WXK_F5 );
+static Ki_HotkeyInfo HkFindItem( wxT( "Find Item" ), HK_FIND_ITEM, 'F' + GR_KB_CTRL );
+static Ki_HotkeyInfo HkFindNextItem( wxT( "Find Next Item" ), HK_FIND_NEXT_ITEM, WXK_F5 );
 static Ki_HotkeyInfo HkFindNextDrcMarker( wxT( "Find next DRC marker" ), HK_FIND_NEXT_DRC_MARKER,
                                           WXK_F5 + GR_KB_SHIFT );
 
 // Special keys for library editor:
-static Ki_HotkeyInfo HkCreatePin( wxT( "Create Pin" ),
-                                  HK_LIBEDIT_CREATE_PIN, 'P' );
-static Ki_HotkeyInfo HkInsertPin( wxT( "Repeat Pin" ), HK_REPEAT_LAST,
-                                  WXK_INSERT );
+static Ki_HotkeyInfo HkCreatePin( wxT( "Create Pin" ), HK_LIBEDIT_CREATE_PIN, 'P' );
+static Ki_HotkeyInfo HkInsertPin( wxT( "Repeat Pin" ), HK_REPEAT_LAST, WXK_INSERT );
 static Ki_HotkeyInfo HkMovePin( wxT( "Move Pin" ), HK_LIBEDIT_MOVE_GRAPHIC_ITEM, 'M' );
 
 
@@ -256,8 +247,7 @@ void WinEDA_SchematicFrame::OnHotKey( wxDC* DC, int hotkey,
 
     cmd.SetEventObject( this );
 
-    bool        ItemInEdit = GetScreen()->GetCurItem()
-                             && GetScreen()->GetCurItem()->m_Flags;
+    bool        ItemInEdit = GetScreen()->GetCurItem()&& GetScreen()->GetCurItem()->m_Flags;
     bool        RefreshToolBar = FALSE;
     SCH_SCREEN* screen = GetScreen();
 
@@ -272,8 +262,7 @@ void WinEDA_SchematicFrame::OnHotKey( wxDC* DC, int hotkey,
         hotkey += 'A' - 'a';
 
     // Search command from key :
-    Ki_HotkeyInfo* HK_Descr = GetDescriptorFromHotkey( hotkey,
-                                                       s_Common_Hotkey_List );
+    Ki_HotkeyInfo* HK_Descr = GetDescriptorFromHotkey( hotkey, s_Common_Hotkey_List );
     if( HK_Descr == NULL )
         HK_Descr = GetDescriptorFromHotkey( hotkey, s_Schematic_Hotkey_List );
     if( HK_Descr == NULL )
@@ -322,8 +311,7 @@ void WinEDA_SchematicFrame::OnHotKey( wxDC* DC, int hotkey,
     case HK_REDO:
         if( !ItemInEdit )
         {
-            wxCommandEvent event( wxEVT_COMMAND_TOOL_CLICKED,
-                                  HK_Descr->m_IdMenuEvent );
+            wxCommandEvent event( wxEVT_COMMAND_TOOL_CLICKED, HK_Descr->m_IdMenuEvent );
             wxPostEvent( this, event );
         }
         break;
@@ -383,8 +371,7 @@ void WinEDA_SchematicFrame::OnHotKey( wxDC* DC, int hotkey,
         {
             // switch to m_ID_current_state = ID_COMPONENT_BUTT;
             if( m_ID_current_state != ID_COMPONENT_BUTT )
-                SetToolID( ID_COMPONENT_BUTT, wxCURSOR_PENCIL,
-                          _( "Add Component" ) );
+                SetToolID( ID_COMPONENT_BUTT, wxCURSOR_PENCIL, _( "Add Component" ) );
             OnLeftClick( DC, MousePos );
         }
         break;
@@ -428,8 +415,7 @@ void WinEDA_SchematicFrame::OnHotKey( wxDC* DC, int hotkey,
         if( !ItemInEdit )
         {
             if( m_ID_current_state != ID_NOCONN_BUTT )
-                SetToolID( ID_NOCONN_BUTT, wxCURSOR_PENCIL,
-                          _( "Add \"NoNonnect\" Flags" ) );
+                SetToolID( ID_NOCONN_BUTT, wxCURSOR_PENCIL, _( "Add \"NoNonnect\" Flags" ) );
             OnLeftClick( DC, MousePos );
         }
         break;
@@ -439,7 +425,7 @@ void WinEDA_SchematicFrame::OnHotKey( wxDC* DC, int hotkey,
         {
             HandleBlockEndByPopUp(BLOCK_ROTATE, DC );
             break;
-        } 
+        }
         if( DrawStruct == NULL )
         {
             // Find the schematic object to rotate under the cursor
@@ -494,11 +480,11 @@ void WinEDA_SchematicFrame::OnHotKey( wxDC* DC, int hotkey,
         break;
 
     case HK_MIRROR_Y_COMPONENT:     // Mirror Y (Component)
-        if ( screen->m_BlockLocate.m_State != STATE_NO_BLOCK)
+        if ( screen->m_BlockLocate.m_State != STATE_NO_BLOCK )
         {
             HandleBlockEndByPopUp(BLOCK_MIRROR_Y, DC );
             break;
-        } 
+        }
         if( DrawStruct == NULL )
             DrawStruct = LocateSmallestComponent( (SCH_SCREEN*) GetScreen() );
         if( DrawStruct )
@@ -513,11 +499,11 @@ void WinEDA_SchematicFrame::OnHotKey( wxDC* DC, int hotkey,
         break;
 
     case HK_MIRROR_X_COMPONENT:     // Mirror X (Component)
-        if ( screen->m_BlockLocate.m_State != STATE_NO_BLOCK) //allows bloc operation on hotkey
+        if ( screen->m_BlockLocate.m_State != STATE_NO_BLOCK ) //allows bloc operation on hotkey
 		{
             HandleBlockEndByPopUp(BLOCK_MIRROR_X, DC );
             break;
-		} 
+		}
         if( DrawStruct == NULL )
             DrawStruct = LocateSmallestComponent( GetScreen() );
         if( DrawStruct )
@@ -567,7 +553,7 @@ void WinEDA_SchematicFrame::OnHotKey( wxDC* DC, int hotkey,
             {
                 // If it's a sheet, then check if a pinsheet is under the cursor
                 SCH_SHEET_PIN* slabel = LocateSheetLabel( (SCH_SHEET*) DrawStruct,
-                                                         GetScreen()->m_Curseur );
+                                                          GetScreen()->m_Curseur );
                 if( slabel )
                     DrawStruct = slabel;
             }
@@ -648,9 +634,8 @@ void WinEDA_SchematicFrame::OnHotKey( wxDC* DC, int hotkey,
             break;
         if( DrawStruct == NULL )
         {
-            DrawStruct = PickStruct( GetScreen()->m_Curseur,
-                                     GetScreen(), LIBITEM | TEXTITEM |
-                                     LABELITEM | SHEETITEM );
+            DrawStruct = PickStruct( GetScreen()->m_Curseur, GetScreen(),
+                                     LIBITEM | TEXTITEM | LABELITEM | SHEETITEM );
             if( DrawStruct == NULL )
                 break;
             if( DrawStruct->Type() == TYPE_SCH_COMPONENT )
@@ -721,8 +706,7 @@ void WinEDA_SchematicFrame::OnHotKey( wxDC* DC, int hotkey,
  * under the mouse cursor
  * Commands are case insensitive
  */
-void WinEDA_LibeditFrame::OnHotKey( wxDC* DC, int hotkey,
-                                    EDA_BaseStruct* DrawStruct )
+void WinEDA_LibeditFrame::OnHotKey( wxDC* DC, int hotkey, EDA_BaseStruct* DrawStruct )
 {
     wxCommandEvent cmd( wxEVT_COMMAND_MENU_SELECTED );
     wxCommandEvent toolCmd( wxEVT_COMMAND_TOOL_CLICKED );
@@ -730,8 +714,7 @@ void WinEDA_LibeditFrame::OnHotKey( wxDC* DC, int hotkey,
     cmd.SetEventObject( this );
 
     wxPoint MousePos   = GetScreen()->m_MousePosition;
-    bool    ItemInEdit = GetScreen()->GetCurItem()
-                         && GetScreen()->GetCurItem()->m_Flags;
+    bool    ItemInEdit = GetScreen()->GetCurItem()&& GetScreen()->GetCurItem()->m_Flags;
 
     if( hotkey == 0 )
         return;
@@ -740,8 +723,7 @@ void WinEDA_LibeditFrame::OnHotKey( wxDC* DC, int hotkey,
      * with non ascii codes like function keys */
     if( (hotkey >= 'a') && (hotkey <= 'z') )
         hotkey += 'A' - 'a';
-    Ki_HotkeyInfo* HK_Descr = GetDescriptorFromHotkey( hotkey,
-                                                       s_Common_Hotkey_List );
+    Ki_HotkeyInfo* HK_Descr = GetDescriptorFromHotkey( hotkey, s_Common_Hotkey_List );
     if( HK_Descr == NULL )
         HK_Descr = GetDescriptorFromHotkey( hotkey, s_LibEdit_Hotkey_List );
     if( HK_Descr == NULL )
@@ -843,7 +825,7 @@ void WinEDA_LibeditFrame::OnHotKey( wxDC* DC, int hotkey,
     case HK_ROTATE:
         m_drawItem = LocateItemUsingCursor();
 
-        if( m_drawItem )
+        if( m_drawItem && !m_drawItem->InEditMode() )
         {
             switch( m_drawItem->Type() )
             {
@@ -875,7 +857,7 @@ void WinEDA_LibeditFrame::OnHotKey( wxDC* DC, int hotkey,
     case HK_DELETE:
         m_drawItem = LocateItemUsingCursor();
 
-        if( m_drawItem )
+        if( m_drawItem && !m_drawItem->InEditMode() )
         {
             wxCommandEvent evt;
             evt.SetId( ID_POPUP_LIBEDIT_DELETE_ITEM );
@@ -886,7 +868,7 @@ void WinEDA_LibeditFrame::OnHotKey( wxDC* DC, int hotkey,
     case HK_LIBEDIT_MOVE_GRAPHIC_ITEM:
         m_drawItem = LocateItemUsingCursor();
 
-        if( m_drawItem )
+        if( m_drawItem && !m_drawItem->InEditMode() )
         {
             wxCommandEvent evt;
             evt.SetId( ID_POPUP_LIBEDIT_MOVE_ITEM_REQUEST );
@@ -897,7 +879,7 @@ void WinEDA_LibeditFrame::OnHotKey( wxDC* DC, int hotkey,
     case HK_DRAG:
         m_drawItem = LocateItemUsingCursor();
 
-        if( m_drawItem )
+        if( m_drawItem && !m_drawItem->InEditMode() )
         {
             wxCommandEvent evt;
             evt.SetId( ID_POPUP_LIBEDIT_MODIFY_ITEM );
diff --git a/eeschema/lib_arc.cpp b/eeschema/lib_arc.cpp
index 2b7c10998e..17ef313f83 100644
--- a/eeschema/lib_arc.cpp
+++ b/eeschema/lib_arc.cpp
@@ -12,17 +12,56 @@
 #include "general.h"
 #include "protos.h"
 #include "lib_arc.h"
+#include "transform.h"
+
+
+//! @brief Given three points A B C, compute the circumcenter of the resulting triangle
+//! reference: http://en.wikipedia.org/wiki/Circumscribed_circle
+//! Coordinates of circumcenter in Cartesian coordinates
+static wxPoint calcCenter( const wxPoint& A, const wxPoint& B, const wxPoint& C )
+{
+    double  circumCenterX, circumCenterY;
+    double  Ax = (double) A.x;
+    double  Ay = (double) A.y;
+    double  Bx = (double) B.x;
+    double  By = (double) B.y;
+    double  Cx = (double) C.x;
+    double  Cy = (double) C.y;
+
+    wxPoint circumCenter;
+
+    double  D = 2.0 * ( Ax * ( By - Cy ) + Bx * ( Cy - Ay ) + Cx * ( Ay - By ) );
+
+    // prevent division / 0
+    if( fabs( D ) < 1e-7 )
+        D = 1e-7;
+
+    circumCenterX = ( (Ay * Ay + Ax * Ax) * (By - Cy) +
+                      (By * By + Bx * Bx) * (Cy - Ay) +
+                      (Cy * Cy + Cx * Cx) * (Ay - By) ) / D;
+
+    circumCenterY = ( (Ay * Ay + Ax * Ax) * (Cx - Bx) +
+                      (By * By + Bx * Bx) * (Ax - Cx) +
+                      (Cy * Cy + Cx * Cx) * (Bx - Ax) ) / D;
+
+    circumCenter.x = (int) circumCenterX;
+    circumCenter.y = (int) circumCenterY;
+
+    return circumCenter;
+}
 
 
 LIB_ARC::LIB_ARC( LIB_COMPONENT* aParent ) : LIB_DRAW_ITEM( COMPONENT_ARC_DRAW_TYPE, aParent )
 {
-    m_Radius     = 0;
-    m_t1         = 0;
-    m_t2         = 0;
-    m_Width      = 0;
-    m_Fill       = NO_FILL;
-    m_isFillable = true;
-    m_typeName   = _( "Arc" );
+    m_Radius        = 0;
+    m_t1            = 0;
+    m_t2            = 0;
+    m_Width         = 0;
+    m_Fill          = NO_FILL;
+    m_isFillable    = true;
+    m_typeName      = _( "Arc" );
+    m_editState     = 0;
+    m_lastEditState = 0;
 }
 
 
@@ -130,7 +169,7 @@ bool LIB_ARC::HitTest( const wxPoint& aRefPoint )
     if( mindist < MINIMUM_SELECTION_DISTANCE )
         mindist = MINIMUM_SELECTION_DISTANCE;
 
-    return HitTest( aRefPoint, mindist, DefaultTransformMatrix );
+    return HitTest( aRefPoint, mindist, DefaultTransform );
 }
 
 /** Function HitTest
@@ -140,8 +179,7 @@ bool LIB_ARC::HitTest( const wxPoint& aRefPoint )
  *                     of a line)
  * @param aTransMat = the transform matrix
  */
-bool LIB_ARC::HitTest( wxPoint aReferencePoint, int aThreshold,
-                       const int aTransformationMatrix[2][2] )
+bool LIB_ARC::HitTest( wxPoint aReferencePoint, int aThreshold, const TRANSFORM& aTransform )
 {
 
     // TODO: use aTransMat to calculmates parameters
@@ -149,7 +187,7 @@ bool LIB_ARC::HitTest( wxPoint aReferencePoint, int aThreshold,
 
     NEGATE( relativePosition.y );       // reverse Y axis
 
-    int distance = wxRound( EuclideanNorm( TwoPointVector(m_Pos, relativePosition) ) );
+    int distance = wxRound( EuclideanNorm( TwoPointVector( m_Pos, relativePosition ) ) );
 
     if( abs( distance - m_Radius ) > aThreshold )
         return false;
@@ -160,8 +198,8 @@ bool LIB_ARC::HitTest( wxPoint aReferencePoint, int aThreshold,
     wxPoint startEndVector = TwoPointVector( m_ArcStart, m_ArcEnd);
     wxPoint startRelativePositionVector = TwoPointVector( m_ArcStart, relativePosition );
 
-    wxPoint centerStartVector = TwoPointVector( m_Pos, m_ArcStart);
-    wxPoint centerEndVector = TwoPointVector( m_Pos, m_ArcEnd);
+    wxPoint centerStartVector = TwoPointVector( m_Pos, m_ArcStart );
+    wxPoint centerEndVector = TwoPointVector( m_Pos, m_ArcEnd );
     wxPoint centerRelativePositionVector = TwoPointVector( m_Pos, relativePosition );
 
     // Compute the cross product to check if the point is in the sector
@@ -172,7 +210,7 @@ bool LIB_ARC::HitTest( wxPoint aReferencePoint, int aThreshold,
     // relative to the start point to end point vector lies
     if( CrossProduct( startEndVector, startRelativePositionVector ) < 0 )
     {
-    	EXCHG(crossProductStart, crossProductEnd);
+    	EXCHG( crossProductStart, crossProductEnd );
     }
 
     // When the cross products have a different sign, the point lies in sector
@@ -265,15 +303,15 @@ void LIB_ARC::DoMirrorHorizontal( const wxPoint& aCenter )
 
 
 void LIB_ARC::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
-                      const int aTransform[2][2] )
+                      const TRANSFORM& aTransform )
 {
     wxASSERT( aPlotter != NULL );
 
     int t1 = m_t1;
     int t2 = m_t2;
-    wxPoint pos = TransformCoordinate( aTransform, m_Pos ) + aOffset;
+    wxPoint pos = aTransform.TransformCoordinate( m_Pos ) + aOffset;
 
-    MapAngles( &t1, &t2, aTransform );
+    aTransform.MapAngles( &t1, &t2 );
 
     if( aFill && m_Fill == FILLED_WITH_BG_BODYCOLOR )
     {
@@ -295,12 +333,35 @@ int LIB_ARC::GetPenSize()
 }
 
 
-void LIB_ARC::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
-                    const wxPoint& aOffset, int aColor, int aDrawMode,
-                    void* aData, const int aTransformMatrix[2][2] )
+void LIB_ARC::drawEditGraphics( EDA_Rect* aClipBox, wxDC* aDC, int aColor )
 {
-    wxPoint pos1, pos2, posc;
+    // Thie edit indicators only get drawn when a new arc is being drawn.
+    if( ( m_Flags & IS_NEW ) == 0 )
+        return;
 
+    // Use the last edit state so when the drawing switches from the end mode to the center
+    // point mode, the last line between the center points gets erased.
+    if( m_lastEditState == 1 )
+    {
+        GRLine( aClipBox, aDC, m_ArcStart.x, -m_ArcStart.y, m_ArcEnd.x, -m_ArcEnd.y, 0, aColor );
+    }
+    else
+    {
+        GRDashedLine( aClipBox, aDC, m_ArcStart.x, -m_ArcStart.y, m_Pos.x, -m_Pos.y, 0, aColor );
+        GRDashedLine( aClipBox, aDC, m_ArcEnd.x, -m_ArcEnd.y, m_Pos.x, -m_Pos.y, 0, aColor );
+    }
+}
+
+
+void LIB_ARC::drawGraphic( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint& aOffset,
+                           int aColor, int aDrawMode, void* aData, const TRANSFORM& aTransform )
+{
+    // DOn't draw the arc until the end point is selected.  Only the edit indicators
+    // get drawn at this time.
+    if( ( m_Flags & IS_NEW ) && m_lastEditState == 1 )
+        return;
+
+    wxPoint pos1, pos2, posc;
     int     color = ReturnLayerColor( LAYER_DEVICE );
 
     if( aColor < 0 )       // Used normal color or selected color
@@ -309,14 +370,16 @@ void LIB_ARC::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
             color = g_ItemSelectetColor;
     }
     else
+    {
         color = aColor;
+    }
 
-    pos1 = TransformCoordinate( aTransformMatrix, m_ArcEnd ) + aOffset;
-    pos2 = TransformCoordinate( aTransformMatrix, m_ArcStart ) + aOffset;
-    posc = TransformCoordinate( aTransformMatrix, m_Pos ) + aOffset;
+    pos1 = aTransform.TransformCoordinate( m_ArcEnd ) + aOffset;
+    pos2 = aTransform.TransformCoordinate( m_ArcStart ) + aOffset;
+    posc = aTransform.TransformCoordinate( m_Pos ) + aOffset;
     int  pt1  = m_t1;
     int  pt2  = m_t2;
-    bool swap = MapAngles( &pt1, &pt2, aTransformMatrix );
+    bool swap = aTransform.MapAngles( &pt1, &pt2 );
     if( swap )
     {
         EXCHG( pos1.x, pos2.x );
@@ -335,18 +398,17 @@ void LIB_ARC::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
                      (m_Flags & IS_MOVED) ? color : ReturnLayerColor( LAYER_DEVICE_BACKGROUND ),
                      ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) );
     else if( fill == FILLED_SHAPE && !aData )
-        GRFilledArc( &aPanel->m_ClipBox, aDC, posc.x, posc.y, pt1, pt2,
-                     m_Radius, color, color );
+        GRFilledArc( &aPanel->m_ClipBox, aDC, posc.x, posc.y, pt1, pt2, m_Radius, color, color );
     else
     {
+
 #ifdef DRAW_ARC_WITH_ANGLE
 
-        GRArc( &aPanel->m_ClipBox, aDC, posc.x, posc.y, pt1, pt2,
-               m_Radius, GetPenSize( ), color );
+        GRArc( &aPanel->m_ClipBox, aDC, posc.x, posc.y, pt1, pt2, m_Radius, GetPenSize(), color );
 #else
 
         GRArc1( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y, pos2.x, pos2.y,
-                posc.x, posc.y, GetPenSize( ), color );
+                posc.x, posc.y, GetPenSize(), color );
 #endif
     }
 
@@ -360,6 +422,26 @@ void LIB_ARC::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
 }
 
 
+void LIB_ARC::saveAttributes()
+{
+    m_savedPos = m_Pos;
+    m_savedStartPos = m_ArcStart;
+    m_savedEndPos = m_ArcEnd;
+    m_savedAngle1 = m_t1;
+    m_savedAngle2 = m_t2;
+}
+
+
+void LIB_ARC::restoreAttributes()
+{
+    m_Pos = m_savedPos;
+    m_ArcStart = m_savedStartPos;
+    m_ArcEnd = m_savedEndPos;
+    m_t1 = m_savedAngle1;
+    m_t2 = m_savedAngle2;
+}
+
+
 EDA_Rect LIB_ARC::GetBoundingBox()
 {
     int      minX, minY, maxX, maxY, angleStart, angleEnd;
@@ -377,13 +459,13 @@ start(%d, %d), end(%d, %d), radius %d" ),
         return rect;
     }
 
-    endPos     = TransformCoordinate( DefaultTransformMatrix, m_ArcEnd );
-    startPos   = TransformCoordinate( DefaultTransformMatrix, m_ArcStart );
-    centerPos  = TransformCoordinate( DefaultTransformMatrix, m_Pos );
+    endPos     = DefaultTransform.TransformCoordinate( m_ArcEnd );
+    startPos   = DefaultTransform.TransformCoordinate( m_ArcStart );
+    centerPos  = DefaultTransform.TransformCoordinate( m_Pos );
     angleStart = m_t1;
     angleEnd   = m_t2;
 
-    if( MapAngles( &angleStart, &angleEnd, DefaultTransformMatrix ) )
+    if( DefaultTransform.MapAngles( &angleStart, &angleEnd ) )
     {
         EXCHG( endPos.x, startPos.x );
         EXCHG( endPos.y, startPos.y );
@@ -436,3 +518,259 @@ void LIB_ARC::DisplayInfo( WinEDA_DrawFrame* aFrame )
 
     aFrame->AppendMsgPanel( _( "Bounding box" ), msg, BROWN );
 }
+
+
+void LIB_ARC::BeginEdit( int aEditMode, const wxPoint aPosition )
+{
+    wxCHECK_RET( ( aEditMode & ( IS_NEW | IS_MOVED | IS_RESIZED ) ) != 0,
+                 wxT( "Invalid edit mode for LIB_ARC object." ) );
+
+    if( aEditMode == IS_NEW )
+    {
+        m_ArcStart  = m_ArcEnd = aPosition;
+        m_editState = m_lastEditState = 1;
+    }
+    else if( aEditMode == IS_MOVED )
+    {
+        m_initialPos = m_Pos;
+        m_initialCursorPos = aPosition;
+        saveAttributes();
+        SetEraseLastDrawItem();
+    }
+    else
+    {
+        // Save the current arc positions in case the resize ia aborted.
+        saveAttributes();
+
+        // The arc center point has to be rotated with while adjusting the
+        // start or end point, determine the side of this point and the distance
+        // from the start / end point
+        wxPoint middlePoint = wxPoint( (m_ArcStart.x + m_ArcEnd.x) / 2,
+                                       (m_ArcStart.y + m_ArcEnd.y) / 2 );
+        wxPoint centerVector   = m_Pos - middlePoint;
+        wxPoint startEndVector = TwoPointVector( m_ArcStart, m_ArcEnd );
+        m_editCenterDistance = EuclideanNorm( centerVector );
+
+        // Determine on which side is the center point
+        m_editDirection = CrossProduct( startEndVector, centerVector ) ? 1 : -1;
+
+        // Drag either the start, end point or the outline
+        if( HitTestPoints( m_ArcStart, aPosition, MINIMUM_SELECTION_DISTANCE ) )
+        {
+            m_editSelectPoint = START;
+        }
+        else if( HitTestPoints( m_ArcEnd, aPosition, MINIMUM_SELECTION_DISTANCE ) )
+        {
+            m_editSelectPoint = END;
+        }
+        else
+            m_editSelectPoint = OUTLINE;
+
+        m_editState = 0;
+        SetEraseLastDrawItem();
+    }
+
+    m_Flags = aEditMode;
+}
+
+
+bool LIB_ARC::ContinueEdit( const wxPoint aPosition )
+{
+    wxCHECK_MSG( ( m_Flags & ( IS_NEW | IS_MOVED | IS_RESIZED ) ) != 0, false,
+                   wxT( "Bad call to ContinueEdit().  LIB_ARC is not being edited." ) );
+
+    if( m_Flags == IS_NEW )
+    {
+        if( m_editState == 1 )        // Second position yields the arc segment length.
+        {
+            m_ArcEnd = aPosition;
+            m_editState = 2;
+            SetEraseLastDrawItem( false );
+            return true;              // Need third position to calculate center point.
+        }
+    }
+
+    return false;
+}
+
+
+void LIB_ARC::EndEdit( const wxPoint& aPosition, bool aAbort )
+{
+    wxCHECK_RET( ( m_Flags & ( IS_NEW | IS_MOVED | IS_RESIZED ) ) != 0,
+                   wxT( "Bad call to EndEdit().  LIB_ARC is not being edited." ) );
+
+    if( aAbort && !IsNew() )
+        restoreAttributes();
+
+    SetEraseLastDrawItem( false );
+    m_lastEditState = 0;
+    m_editState = 0;
+    m_Flags = 0;
+}
+
+
+void LIB_ARC::calcEdit( const wxPoint& aPosition )
+{
+    if( m_Flags == IS_RESIZED )
+    {
+        wxPoint newCenterPoint, startPos, endPos;
+
+        // Choose the point of the arc to be adjusted
+        if( m_editSelectPoint == START )
+        {
+            startPos = aPosition;
+            endPos   = m_ArcEnd;
+        }
+        else if( m_editSelectPoint == END )
+        {
+            endPos   = aPosition;
+            startPos = m_ArcStart;
+        }
+        else
+        {
+            // Use the cursor for adjusting the arc curvature
+            startPos = m_ArcStart;
+            endPos   = m_ArcEnd;
+
+            wxPoint middlePoint = wxPoint( (startPos.x + endPos.x) / 2,
+                                           (startPos.y + endPos.y) / 2 );
+
+
+            // If the distance is too small, use the old center point
+            // else the new center point is calculated over the three points start/end/cursor
+            if( DistanceLinePoint( startPos, endPos, aPosition ) > MINIMUM_SELECTION_DISTANCE )
+            {
+                newCenterPoint = calcCenter( startPos, aPosition, endPos );
+            }
+            else
+            {
+                newCenterPoint = m_Pos;
+            }
+
+            // Determine if the arc angle is larger than 180 degrees -> this happens if both
+            // points (cursor position, center point) lie on the same side of the vector
+            // start-end
+            int  crossA = CrossProduct( TwoPointVector( startPos, endPos ),
+                                        TwoPointVector( endPos, aPosition ) );
+            int  crossB = CrossProduct( TwoPointVector( startPos, endPos ),
+                                        TwoPointVector( endPos, newCenterPoint ) );
+
+            if( ( crossA < 0 && crossB < 0 ) || ( crossA >= 0 && crossB >= 0 ) )
+                newCenterPoint = m_Pos;
+        }
+
+        if( m_editSelectPoint == START || m_editSelectPoint == END )
+        {
+            // Compute the new center point when the start/end points are modified
+            wxPoint middlePoint = wxPoint( (startPos.x + endPos.x) / 2,
+                                           (startPos.y + endPos.y) / 2 );
+
+            wxPoint startEndVector = TwoPointVector( startPos, endPos );
+            wxPoint perpendicularVector = wxPoint( -startEndVector.y, startEndVector.x );
+            double  lengthPerpendicularVector = EuclideanNorm( perpendicularVector );
+
+            // prevent too large values, division / 0
+            if( lengthPerpendicularVector < 1e-1 )
+                lengthPerpendicularVector = 1e-1;
+
+            perpendicularVector.x = (int) ( (double) perpendicularVector.x *
+                                            m_editCenterDistance /
+                                            lengthPerpendicularVector ) * m_editDirection;
+            perpendicularVector.y = (int) ( (double) perpendicularVector.y *
+                                            m_editCenterDistance /
+                                            lengthPerpendicularVector ) * m_editDirection;
+
+            newCenterPoint = middlePoint + perpendicularVector;
+
+            m_ArcStart = startPos;
+            m_ArcEnd   = endPos;
+        }
+
+        m_Pos = newCenterPoint;
+        calcRadiusAngles();
+    }
+    else if( m_Flags == IS_NEW )
+    {
+        if( m_editState == 1 )
+        {
+            m_ArcEnd = aPosition;
+        }
+
+        if( m_editState != m_lastEditState )
+            m_lastEditState = m_editState;
+
+        // Keep the arc center point up to date.  Otherwise, there will be edit graphic
+        // artifacts left behind from the initial draw.
+        int dx, dy;
+        int cX, cY;
+        int angle;
+
+        cX = aPosition.x;
+        cY = aPosition.y;
+
+        dx = m_ArcEnd.x - m_ArcStart.x;
+        dy = m_ArcEnd.y - m_ArcStart.y;
+        cX -= m_ArcStart.x;
+        cY -= m_ArcStart.y;
+        angle = (int) ( atan2( (double) dy, (double) dx ) * 1800 / M_PI );
+        RotatePoint( &dx, &dy, angle );     /* The segment dx, dy is horizontal
+                                             * -> Length = dx, dy = 0 */
+        RotatePoint( &cX, &cY, angle );
+        cX = dx / 2;           /* cX, cY is on the median segment 0.0 a dx, 0 */
+
+        RotatePoint( &cX, &cY, -angle );
+        cX += m_ArcStart.x;
+        cY += m_ArcStart.y;
+        m_Pos.x = cX;
+        m_Pos.y = cY;
+        calcRadiusAngles();
+
+        SetEraseLastDrawItem();
+    }
+    else if( m_Flags == IS_MOVED )
+    {
+        Move( m_initialPos + aPosition - m_initialCursorPos );
+    }
+}
+
+
+void LIB_ARC::calcRadiusAngles()
+{
+    wxPoint centerStartVector = TwoPointVector( m_Pos, m_ArcStart );
+    wxPoint centerEndVector   = TwoPointVector( m_Pos, m_ArcEnd );
+
+    m_Radius = wxRound( EuclideanNorm( centerStartVector ) );
+
+    m_t1 = (int) ( atan2( (double) centerStartVector.y,
+                          (double) centerStartVector.x ) * 1800 / M_PI );
+
+    m_t2 = (int) ( atan2( (double) centerEndVector.y,
+                          (double) centerEndVector.x ) * 1800 / M_PI );
+
+    NORMALIZE_ANGLE( m_t1 );
+    NORMALIZE_ANGLE( m_t2 );  // angles = 0 .. 3600
+
+    // Restrict angle to less than 180 to avoid PBS display mirror Trace because it is
+    // assumed that the arc is less than 180 deg to find orientation after rotate or mirror.
+    if( (m_t2 - m_t1) > 1800 )
+        m_t2 -= 3600;
+    else if( (m_t2 - m_t1) <= -1800 )
+        m_t2 += 3600;
+
+    while( (m_t2 - m_t1) >= 1800 )
+    {
+        m_t2--;
+        m_t1++;
+    }
+
+    while( (m_t1 - m_t2) >= 1800 )
+    {
+        m_t2++;
+        m_t1--;
+    }
+
+    NORMALIZE_ANGLE( m_t1 );
+
+    if( !IsMoving() )
+        NORMALIZE_ANGLE( m_t2 );
+}
diff --git a/eeschema/lib_arc.h b/eeschema/lib_arc.h
index 45640dfd1b..73977703b8 100644
--- a/eeschema/lib_arc.h
+++ b/eeschema/lib_arc.h
@@ -9,8 +9,63 @@
 #include "lib_draw_item.h"
 
 
+class TRANSFORM;
+
+
 class LIB_ARC : public LIB_DRAW_ITEM
 {
+    enum SELECT_T
+    {
+        START,
+        END,
+        OUTLINE,
+    };
+
+    wxPoint  m_savedStartPos;
+    wxPoint  m_savedEndPos;
+    int      m_savedAngle1;
+    int      m_savedAngle2;
+    double   m_editCenterDistance;
+    SELECT_T m_editSelectPoint;
+    int      m_editState;
+    int      m_editDirection;
+    int      m_lastEditState;
+
+    /**
+     * Draws the arc.
+     */
+    void drawGraphic( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint& aOffset,
+                      int aColor, int aDrawMode, void* aData, const TRANSFORM& aTransform );
+
+    /**
+     * Draw the graphics when the arc is being edited.
+     */
+    void drawEditGraphics( EDA_Rect* aClipBox, wxDC* aDC, int aColor );
+
+    /**
+     * See LIB_DRAW_ITEM::saveAttributes().
+     */
+    void saveAttributes();
+
+    /**
+     * See LIB_DRAW_ITEM::restoreAttributes().
+     */
+    void restoreAttributes();
+
+    /**
+     * Calculates the center, radius, and angles at \a aPosition when the arc is being edited.
+     *
+     * Note: The center may not necessarily be on the grid.
+     *
+     * @param aPosition - The current mouse position in drawing coordinates.
+     */
+    void calcEdit( const wxPoint& aPosition );
+
+    /**
+     * Calculate the radius and angle of an arc using the start, end, and center points.
+     */
+    void calcRadiusAngles();
+
 public:
     int     m_Radius;
     int     m_t1;       /* First radius angle of the arc in 0.1 degrees. */
@@ -21,7 +76,7 @@ public:
     int     m_Width;    /* Line width */
 
 public:
-    LIB_ARC(LIB_COMPONENT * aParent);
+    LIB_ARC( LIB_COMPONENT * aParent );
     LIB_ARC( const LIB_ARC& aArc );
     ~LIB_ARC() { }
     virtual wxString GetClass() const
@@ -51,14 +106,10 @@ public:
      * @param aPosRef - a wxPoint to test
      * @param aThreshold - max distance to this object (usually the half
      *                     thickness of a line)
-     * @param aTransMat - the transform matrix
+     * @param aTransform - the transform matrix
      * @return - True if the point aPosRef is near this object
      */
-    virtual bool HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] );
-
-    void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset,
-               int aColor, int aDrawMode, void* aData,
-               const int aTransformMatrix[2][2] );
+    virtual bool HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform );
 
     virtual EDA_Rect GetBoundingBox();
     virtual void DisplayInfo( WinEDA_DrawFrame* frame );
@@ -68,6 +119,21 @@ public:
      */
     virtual int GetPenSize( );
 
+    /**
+     * See LIB_DRAW_ITEM::BeginEdit().
+     */
+    void BeginEdit( int aEditMode, const wxPoint aStartPoint = wxPoint( 0, 0 ) );
+
+    /**
+     * See LIB_DRAW_ITEM::ContinueEdit().
+     */
+    bool ContinueEdit( const wxPoint aNextPoint );
+
+    /**
+     * See LIB_DRAW_ITEM::AbortEdit().
+     */
+    void EndEdit( const wxPoint& aPosition, bool aAbort = false );
+
 protected:
     virtual LIB_DRAW_ITEM* DoGenCopy();
 
@@ -87,7 +153,7 @@ protected:
     virtual wxPoint DoGetPosition() { return m_Pos; }
     virtual void DoMirrorHorizontal( const wxPoint& aCenter );
     virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
-                         const int aTransform[2][2] );
+                         const TRANSFORM& aTransform );
     virtual int DoGetWidth() { return m_Width; }
     virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; }
 };
diff --git a/eeschema/lib_bezier.cpp b/eeschema/lib_bezier.cpp
index f4c6f91d1d..d76ed0a9ed 100644
--- a/eeschema/lib_bezier.cpp
+++ b/eeschema/lib_bezier.cpp
@@ -13,6 +13,7 @@
 #include "general.h"
 #include "protos.h"
 #include "lib_bezier.h"
+#include "transform.h"
 
 
 LIB_BEZIER::LIB_BEZIER( LIB_COMPONENT* aParent ) :
@@ -197,7 +198,7 @@ void LIB_BEZIER::DoMirrorHorizontal( const wxPoint& aCenter )
 
 
 void LIB_BEZIER::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
-                         const int aTransform[2][2] )
+                         const TRANSFORM& aTransform )
 {
     wxASSERT( aPlotter != NULL );
 
@@ -211,7 +212,7 @@ void LIB_BEZIER::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
     for( i = 0; i < m_PolyPoints.size(); i++ )
     {
         wxPoint pos = m_PolyPoints[i];
-        pos = TransformCoordinate( aTransform, pos ) + aOffset;
+        pos = aTransform.TransformCoordinate( pos ) + aOffset;
         Poly[i * 2]     = pos.x;
         Poly[i * 2 + 1] = pos.y;
     }
@@ -236,9 +237,8 @@ int LIB_BEZIER::GetPenSize()
     return ( m_Width == 0 ) ? g_DrawDefaultLineThickness : m_Width;
 }
 
-void LIB_BEZIER::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
-                       const wxPoint& aOffset, int aColor, int aDrawMode,
-                       void* aData, const int aTransformMatrix[2][2] )
+void LIB_BEZIER::drawGraphic( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint& aOffset,
+                              int aColor, int aDrawMode, void* aData, const TRANSFORM& aTransform )
 {
     wxPoint              pos1;
     std::vector<wxPoint> PolyPointsTraslated;
@@ -253,8 +253,8 @@ void LIB_BEZIER::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
     PolyPointsTraslated.clear();
 
     for( unsigned int i = 0; i < m_PolyPoints.size() ; i++ )
-        PolyPointsTraslated.push_back( TransformCoordinate( aTransformMatrix,
-                                                            m_PolyPoints[i] ) + aOffset );
+        PolyPointsTraslated.push_back( aTransform.TransformCoordinate( m_PolyPoints[i] ) +
+                                       aOffset );
 
     if( aColor < 0 )                // Used normal color or selected color
     {
@@ -305,7 +305,7 @@ bool LIB_BEZIER::HitTest( const wxPoint& aRefPos )
     // Have a minimal tolerance for hit test
     if ( mindist < MINIMUM_SELECTION_DISTANCE )
         mindist = MINIMUM_SELECTION_DISTANCE;
-    return HitTest( aRefPos, mindist, DefaultTransformMatrix );
+    return HitTest( aRefPos, mindist, DefaultTransform );
 }
 
 /** Function HitTest
@@ -314,14 +314,14 @@ bool LIB_BEZIER::HitTest( const wxPoint& aRefPos )
  * @param aThreshold = max distance to a segment
  * @param aTransMat = the transform matrix
  */
-bool LIB_BEZIER::HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] )
+bool LIB_BEZIER::HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform )
 {
     wxPoint ref, start, end;
 
     for( unsigned ii = 1; ii < GetCornerCount(); ii++ )
     {
-        start = TransformCoordinate( aTransMat, m_PolyPoints[ii - 1] );
-        end   = TransformCoordinate( aTransMat, m_PolyPoints[ii] );
+        start = aTransform.TransformCoordinate( m_PolyPoints[ii - 1] );
+        end   = aTransform.TransformCoordinate( m_PolyPoints[ii] );
 
         if ( TestSegmentHit( aPosRef, start, end, aThreshold ) )
             return true;
diff --git a/eeschema/lib_bezier.h b/eeschema/lib_bezier.h
index 1ed46e6f93..87fbd928d1 100644
--- a/eeschema/lib_bezier.h
+++ b/eeschema/lib_bezier.h
@@ -11,6 +11,12 @@
 /**************************************************/
 class LIB_BEZIER : public LIB_DRAW_ITEM
 {
+    /**
+     * Draw the bezier curve.
+     */
+    void drawGraphic( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint& aOffset,
+                      int aColor, int aDrawMode, void* aData, const TRANSFORM& aTransform );
+
 public:
     int m_Width;                            /* Line width */
     std::vector<wxPoint> m_BezierPoints;      // list of parameter (3|4)
@@ -54,10 +60,10 @@ public:
     /**
      * @param aPosRef = a wxPoint to test
      * @param aThreshold = max distance to a segment
-     * @param aTransMat = the transform matrix
+     * @param aTransform = the transform matrix
      * @return true if the point aPosRef is near a segment
      */
-    virtual bool HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] );
+    virtual bool HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform );
 
     /**
      * @return the boundary box for this, in library coordinates
@@ -69,10 +75,6 @@ public:
      */
     virtual int GetPenSize( );
 
-    void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset,
-               int aColor, int aDrawMode, void* aData,
-               const int aTransformMatrix[2][2] );
-
     virtual void DisplayInfo( WinEDA_DrawFrame* aFrame );
 
 protected:
@@ -93,7 +95,7 @@ protected:
     virtual wxPoint DoGetPosition() { return m_PolyPoints[0]; }
     virtual void DoMirrorHorizontal( const wxPoint& aCenter );
     virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
-                         const int aTransform[2][2] );
+                         const TRANSFORM& aTransform );
     virtual int DoGetWidth() { return m_Width; }
     virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; }
 };
diff --git a/eeschema/lib_circle.cpp b/eeschema/lib_circle.cpp
index 16b72efeaa..e0263d93a4 100644
--- a/eeschema/lib_circle.cpp
+++ b/eeschema/lib_circle.cpp
@@ -12,6 +12,7 @@
 #include "general.h"
 #include "protos.h"
 #include "lib_circle.h"
+#include "transform.h"
 
 
 LIB_CIRCLE::LIB_CIRCLE( LIB_COMPONENT* aParent ) :
@@ -79,7 +80,7 @@ bool LIB_CIRCLE::HitTest( const wxPoint& aPosRef )
     if( mindist < MINIMUM_SELECTION_DISTANCE )
         mindist = MINIMUM_SELECTION_DISTANCE;
 
-    return HitTest( aPosRef, mindist, DefaultTransformMatrix );
+    return HitTest( aPosRef, mindist, DefaultTransform );
 }
 
 
@@ -90,9 +91,9 @@ bool LIB_CIRCLE::HitTest( const wxPoint& aPosRef )
  *                     thickness of a line)
  * @param aTransMat = the transform matrix
  */
-bool LIB_CIRCLE::HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] )
+bool LIB_CIRCLE::HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform )
 {
-    wxPoint relpos = aPosRef - TransformCoordinate( aTransMat, m_Pos );
+    wxPoint relpos = aPosRef - aTransform.TransformCoordinate( m_Pos );
 
     int dist = wxRound( sqrt( ( (double) relpos.x * relpos.x ) +
                               ( (double) relpos.y * relpos.y ) ) );
@@ -169,9 +170,9 @@ void LIB_CIRCLE::DoMirrorHorizontal( const wxPoint& aCenter )
 
 
 void LIB_CIRCLE::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
-                         const int aTransform[2][2] )
+                         const TRANSFORM& aTransform )
 {
-    wxPoint pos = TransformCoordinate( aTransform, m_Pos ) + aOffset;
+    wxPoint pos = aTransform.TransformCoordinate( m_Pos ) + aOffset;
 
     if( aFill && m_Fill == FILLED_WITH_BG_BODYCOLOR )
     {
@@ -193,9 +194,8 @@ int LIB_CIRCLE::GetPenSize()
 }
 
 
-void LIB_CIRCLE::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
-                       const wxPoint& aOffset, int aColor, int aDrawMode,
-                       void* aData, const int aTransformMatrix[2][2] )
+void LIB_CIRCLE::drawGraphic( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint& aOffset,
+                              int aColor, int aDrawMode, void* aData, const TRANSFORM& aTransform )
 {
     wxPoint pos1;
 
@@ -209,7 +209,7 @@ void LIB_CIRCLE::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
     else
         color = aColor;
 
-    pos1 = TransformCoordinate( aTransformMatrix, m_Pos ) + aOffset;
+    pos1 = aTransform.TransformCoordinate( m_Pos ) + aOffset;
     GRSetDrawMode( aDC, aDrawMode );
 
     FILL_T fill = aData ? NO_FILL : m_Fill;
@@ -217,8 +217,7 @@ void LIB_CIRCLE::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
         fill = NO_FILL;
 
     if( fill == FILLED_WITH_BG_BODYCOLOR )
-        GRFilledCircle( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y,
-                        m_Radius, GetPenSize( ),
+        GRFilledCircle( &aPanel->m_ClipBox, aDC, pos1.x, pos1.y, m_Radius, GetPenSize(),
                         (m_Flags & IS_MOVED) ? color : ReturnLayerColor( LAYER_DEVICE_BACKGROUND ),
                         ReturnLayerColor( LAYER_DEVICE_BACKGROUND ) );
     else if( fill == FILLED_SHAPE )
@@ -236,6 +235,20 @@ void LIB_CIRCLE::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
 }
 
 
+void LIB_CIRCLE::saveAttributes()
+{
+    m_savedPos = m_Pos;
+    m_savedRadius = m_Radius;
+}
+
+
+void LIB_CIRCLE::restoreAttributes()
+{
+    m_Pos = m_savedPos;
+    m_Radius = m_savedRadius;
+}
+
+
 EDA_Rect LIB_CIRCLE::GetBoundingBox()
 {
     EDA_Rect rect;
@@ -267,3 +280,69 @@ void LIB_CIRCLE::DisplayInfo( WinEDA_DrawFrame* aFrame )
 
     aFrame->AppendMsgPanel( _( "Bounding box" ), msg, BROWN );
 }
+
+
+void LIB_CIRCLE::BeginEdit( int aEditMode, const wxPoint aPosition )
+{
+    wxCHECK_RET( ( aEditMode & ( IS_NEW | IS_MOVED | IS_RESIZED ) ) != 0,
+                 wxT( "Invalid edit mode for LIB_CIRCLE object." ) );
+
+    if( aEditMode == IS_NEW )
+    {
+        m_Pos = m_initialPos = aPosition;
+    }
+    else if( aEditMode == IS_MOVED )
+    {
+        m_initialPos = m_Pos;
+        m_initialCursorPos = aPosition;
+        saveAttributes();
+        SetEraseLastDrawItem();
+    }
+    else if( aEditMode == IS_RESIZED )
+    {
+        saveAttributes();
+        SetEraseLastDrawItem();
+    }
+
+    m_Flags = aEditMode;
+}
+
+
+bool LIB_CIRCLE::ContinueEdit( const wxPoint aPosition )
+{
+    wxCHECK_MSG( ( m_Flags & ( IS_NEW | IS_MOVED | IS_RESIZED ) ) != 0, false,
+                   wxT( "Bad call to ContinueEdit().  LIB_CIRCLE is not being edited." ) );
+
+    return false;
+}
+
+
+void LIB_CIRCLE::EndEdit( const wxPoint& aPosition, bool aAbort )
+{
+    wxCHECK_RET( ( m_Flags & ( IS_NEW | IS_MOVED | IS_RESIZED ) ) != 0,
+                   wxT( "Bad call to EndEdit().  LIB_CIRCLE is not being edited." ) );
+
+    if( aAbort && !IsNew() )
+        restoreAttributes();
+
+    SetEraseLastDrawItem( false );
+    m_Flags = 0;
+}
+
+
+void LIB_CIRCLE::calcEdit( const wxPoint& aPosition )
+{
+    if( m_Flags == IS_NEW || m_Flags == IS_RESIZED )
+    {
+        if( m_Flags == IS_NEW )
+            SetEraseLastDrawItem();
+
+        int dx = m_Pos.x - aPosition.x;
+        int dy = m_Pos.y - aPosition.y;
+        m_Radius = wxRound( sqrt( ( (double) dx * dx ) + ( (double) dy * dy ) ) );
+    }
+    else
+    {
+        Move( m_initialPos + aPosition - m_initialCursorPos );
+    }
+}
diff --git a/eeschema/lib_circle.h b/eeschema/lib_circle.h
index 89a18a3fe2..e85df25dda 100644
--- a/eeschema/lib_circle.h
+++ b/eeschema/lib_circle.h
@@ -11,13 +11,39 @@
 
 class LIB_CIRCLE : public LIB_DRAW_ITEM
 {
+    int m_savedRadius;    ///< Temporary storage of radius before editing begins.
+
+    /**
+     * Draws the arc.
+     */
+    void drawGraphic( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint& aOffset,
+                      int aColor, int aDrawMode, void* aData, const TRANSFORM& aTransform );
+
+    /**
+     * See LIB_DRAW_ITEM::saveAttributes().
+     */
+    void saveAttributes();
+
+    /**
+     * See LIB_DRAW_ITEM::restoreAttributes().
+     */
+    void restoreAttributes();
+
+    /**
+     * Calculate the new circle at \a aPosition when editing.
+     *
+     * @param aPosition - The position to edit the circle in drawing coordinates.
+     */
+    void calcEdit( const wxPoint& aPosition );
+
+
 public:
     int     m_Radius;
     wxPoint m_Pos;    /* Position or centre (Arc and Circle) or start point (segments) */
     int     m_Width;  /* Line width */
 
 public:
-    LIB_CIRCLE(LIB_COMPONENT * aParent);
+    LIB_CIRCLE( LIB_COMPONENT * aParent );
     LIB_CIRCLE( const LIB_CIRCLE& aCircle );
     ~LIB_CIRCLE() { }
     virtual wxString GetClass() const
@@ -47,23 +73,34 @@ public:
       * @param aPosRef - a wxPoint to test
       * @param aThreshold - max distance to this object (usually the half
       *                     thickness of a line)
-      * @param aTransMat - the transform matrix
+      * @param aTransform - the transform matrix
       * @return true if the point aPosRef is near this object
       */
-    virtual bool HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] );
+    virtual bool HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform );
 
     /**
      * @return the size of the "pen" that be used to draw or plot this item
      */
     virtual int GetPenSize( );
 
-    void Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint &aOffset,
-               int aColor, int aDrawMode, void* aData,
-               const int aTransformMatrix[2][2] );
-
     virtual EDA_Rect GetBoundingBox();
     virtual void DisplayInfo( WinEDA_DrawFrame* aFrame );
 
+    /**
+     * See LIB_DRAW_ITEM::BeginEdit().
+     */
+    void BeginEdit( int aEditMode, const wxPoint aStartPoint = wxPoint( 0, 0 ) );
+
+    /**
+     * See LIB_DRAW_ITEM::ContinueEdit().
+     */
+    bool ContinueEdit( const wxPoint aNextPoint );
+
+    /**
+     * See LIB_DRAW_ITEM::AbortEdit().
+     */
+    void EndEdit( const wxPoint& aPosition, bool aAbort = false );
+
 protected:
     virtual LIB_DRAW_ITEM* DoGenCopy();
 
@@ -83,7 +120,7 @@ protected:
     virtual wxPoint DoGetPosition() { return m_Pos; }
     virtual void DoMirrorHorizontal( const wxPoint& aCenter );
     virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
-                         const int aTransform[2][2] );
+                         const TRANSFORM& aTransform );
     virtual int DoGetWidth() { return m_Width; }
     virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; }
 };
diff --git a/eeschema/lib_draw_item.cpp b/eeschema/lib_draw_item.cpp
index 69c9ff9276..2164c0910a 100644
--- a/eeschema/lib_draw_item.cpp
+++ b/eeschema/lib_draw_item.cpp
@@ -4,17 +4,11 @@
 
 #include "fctsys.h"
 #include "gr_basic.h"
-#include "common.h"
 #include "class_drawpanel.h"
-#include "plot_common.h"
-#include "drawtxt.h"
-#include "trigo.h"
-#include "bezier_curves.h"
-#include "confirm.h"
+#include "wxstruct.h"
 
-#include "program.h"
-#include "general.h"
 #include "protos.h"
+#include "general.h"
 #include "lib_draw_item.h"
 
 const int fill_tab[3] = { 'N', 'F', 'f' };
@@ -30,12 +24,13 @@ LIB_DRAW_ITEM::LIB_DRAW_ITEM( KICAD_T        aType,
                               FILL_T         aFillType ) :
     EDA_BaseStruct( aType )
 {
-    m_Unit       = aUnit;
-    m_Convert    = aConvert;
-    m_Fill       = aFillType;
-    m_Parent     = (EDA_BaseStruct*) aComponent;
-    m_typeName   = _( "Undefined" );
-    m_isFillable = false;
+    m_Unit              = aUnit;
+    m_Convert           = aConvert;
+    m_Fill              = aFillType;
+    m_Parent            = (EDA_BaseStruct*) aComponent;
+    m_typeName          = _( "Undefined" );
+    m_isFillable        = false;
+    m_eraseLastDrawItem = false;
 }
 
 
@@ -111,3 +106,44 @@ bool LIB_DRAW_ITEM::operator<( const LIB_DRAW_ITEM& aOther ) const
 
     return ( DoCompare( aOther ) < 0 );
 }
+
+
+void LIB_DRAW_ITEM::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint& aOffset, int aColor,
+                          int aDrawMode, void* aData, const TRANSFORM& aTransform )
+{
+    if( InEditMode() )
+    {
+        // Temporarily disable filling while the item is being edited.
+        FILL_T fillMode = m_Fill;
+        int  color = GetDefaultColor();
+
+        m_Fill = NO_FILL;
+
+        // Erase the old items using the previous attributes.
+        if( m_eraseLastDrawItem )
+        {
+            GRSetDrawMode( aDC, g_XorMode );
+            drawEditGraphics( &aPanel->m_ClipBox, aDC, color );
+            drawGraphic( aPanel, aDC, wxPoint( 0, 0 ), color, g_XorMode, aData, aTransform );
+        }
+
+        // Calculte the new attributes at the current cursor position.
+        calcEdit( aOffset );
+
+        // Draw the items using the new attributes.
+        drawEditGraphics( &aPanel->m_ClipBox, aDC, color );
+        drawGraphic( aPanel, aDC, wxPoint( 0, 0 ), color, g_XorMode, aData, aTransform );
+
+        m_Fill = fillMode;
+    }
+    else
+    {
+        drawGraphic( aPanel, aDC, aOffset, aColor, aDrawMode, aData, aTransform );
+    }
+}
+
+
+int LIB_DRAW_ITEM::GetDefaultColor()
+{
+    return ReturnLayerColor( LAYER_DEVICE );
+}
diff --git a/eeschema/lib_draw_item.h b/eeschema/lib_draw_item.h
index e642a7f93c..c12e190832 100644
--- a/eeschema/lib_draw_item.h
+++ b/eeschema/lib_draw_item.h
@@ -8,6 +8,7 @@
 #define _LIB_DRAW_ITEM_H_
 
 #include "base_struct.h"
+#include "transform.h"
 
 #include <boost/ptr_container/ptr_vector.hpp>
 
@@ -20,6 +21,11 @@ class LIB_PIN;
 
 extern const int fill_tab[];
 
+// Set KICAD_USE_LIB_OJBECT_EDIT to 1 to use build in ojbect editing mode.
+#if !defined( KICAD_USE_LIB_OJBECT_EDIT )
+#undef KICAD_USE_LIB_OJBECT_EDIT
+#define KICAD_USE_LIB_OJBECT_EDIT 1
+#endif
 
 #define MINIMUM_SELECTION_DISTANCE 15 // Minimum selection distance in mils
 
@@ -51,7 +57,53 @@ typedef std::vector< LIB_PIN* > LIB_PIN_LIST;
  */
 class LIB_DRAW_ITEM : public EDA_BaseStruct
 {
-    wxPoint m_lastPosition;  ///< Last position when moving the draw item.
+    /**
+     * Draws the item.
+     */
+    virtual void drawGraphic( WinEDA_DrawPanel* aPanel, wxDC* aDC,
+                              const wxPoint& aOffset, int aColor,
+                              int aDrawMode, void* aData, const TRANSFORM& aTransform ) = 0;
+
+    /**
+     * Draw any editing specific graphics when the item is being edited.
+     *
+     * @param aClipBox - Clip box of the current device context.
+     * @param aDC - The device context to draw on.
+     * @param aColor - The index of the color to draw.
+     */
+    virtual void drawEditGraphics( EDA_Rect* aClipBox, wxDC* aDC, int aColor ) {}
+
+    /**
+     * Calculates the attributes of an item  at \a aPosition when it is being edited.
+     *
+     * This method gets called by the Draw() method when the item is being edited.  This
+     * probably should be a pure virtual method but bezier curves are not yet editable in
+     * the component library editor.  Therefore, the default method does nothing.
+     *
+     * @param aPosition - The current mouse position in drawing coordinates.
+     */
+    virtual void calcEdit( const wxPoint& aPosition ) {}
+
+
+    /**
+     * Save the current item attributes while editing.
+     *
+     * This method is used to save the drawing attributes of the item during editing.
+     * These values are restored when an edit is canceled by calling EndEdit().
+     */
+    virtual void saveAttributes() {}
+
+    /**
+     * Restore the saved attributes when an existing item edit is cancelled.
+     */
+    virtual void restoreAttributes() {}
+
+    bool    m_eraseLastDrawItem; ///< Used when editing a new draw item to prevent drawing
+                                 ///< artifacts.
+protected:
+    wxPoint m_savedPos;          ///< Temporary position when editng an existing item.
+    wxPoint m_initialPos;        ///< Temporary position when moving an existing item.
+    wxPoint m_initialCursorPos;  ///< Iniital cursor position at the begining of a move.
 
 public:
     /**
@@ -93,7 +145,7 @@ public:
     virtual ~LIB_DRAW_ITEM() { }
 
     /**
-     * Begin an editing a component library draw item in \a aEditMode at \a aStartPoint.
+     * Begin an editing a component library draw item in \a aEditMode at \a aPosition.
      *
      * This is used to start an editing action such as resize or move a draw object.
      * It typically would be called on a left click when a draw tool is selected in
@@ -103,30 +155,36 @@ public:
      *
      * @param aEditMode - The editing mode being performed.  See base_struct.h for a list
      *                    of mode flags.
-     * @param aStartPoint - The where the editing mode was started.  This may or may not
-     *                      be required depending on the item being edited and the edit
-     *                      mode.
+     * @param aPosition - The position in drawing coordinates where the editing mode was
+     *                    started.  This may or may not be required depending on the item
+     *                    being edited and the edit mode.
      */
-    virtual void BeginEdit( int aEditMode, const wxPoint aStartPoint = wxPoint( 0, 0 ) ) {}
+    virtual void BeginEdit( int aEditMode, const wxPoint aPosition = wxPoint( 0, 0 ) ) {}
 
     /**
-     * Continue an edit in progress at \a aNextPoint.
+     * Continue an edit in progress at \a aPosition.
      *
      * This is used to perform the next action while editing a draw item.  This would be
      * called for each additional left click when the mouse is captured while the item
      * is being edited.
+     *
+     * @param aPosition - The position of the mouse left click in drawing coordinates.
+     * @return True if additional mouse clicks are required to complete the edit in progress.
      */
-    virtual void ContinueEdit( const wxPoint aNextPoint ) {}
+    virtual bool ContinueEdit( const wxPoint aPosition ) { return false; }
 
     /**
      * End an object editing action.
      *
-     * This is used to abort an edit action in progress initiated by BeginEdit().
+     * This is used to end or abort an edit action in progress initiated by BeginEdit().
+     *
+     * @param aPosition - The position of the last edit event in drawing coordinates.
+     * @param aAbort - Set to true to abort the current edit in progress.
      */
-    virtual void AbortEdit() { m_Flags = 0; }
+    virtual void EndEdit( const wxPoint& aPosition, bool aAbort = false ) { m_Flags = 0; }
 
     /**
-     * Draw a body item
+     * Draw an item
      *
      * @param aPanel - DrawPanel to use (can be null) mainly used for clipping
      *                 purposes
@@ -140,11 +198,10 @@ public:
      *                to force no fill mode ( has meaning only for items what
      *                can be filled ). used in printing or moving objects mode
      *                or to pass reference to the lib component for pins
-     * @param aTransformMatrix - Transform Matrix (rotation, mirror ..)
+     * @param aTransform - Transform Matrix (rotation, mirror ..)
      */
-    virtual void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC,
-                       const wxPoint &aOffset, int aColor, int aDrawMode,
-                       void* aData, const int aTransformMatrix[2][2] ) = 0;
+    virtual void Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint &aOffset, int aColor,
+                       int aDrawMode, void* aData, const TRANSFORM& aTransform );
 
     /**
      * @return the size of the "pen" that be used to draw or plot this item
@@ -152,7 +209,7 @@ public:
     virtual int GetPenSize() = 0;
 
     /**
-     * Write draw item object to /a aFile in "*.lib" format.
+     * Write draw item object to \a aFile in "*.lib" format.
      *
      * @param aFile - The file to write to.
      * @param aErrorMsg - Error message if write fails.
@@ -183,10 +240,10 @@ public:
      * @param aPosRef - a wxPoint to test
      * @param aThreshold - max distance to this object (usually the half
      *                     thickness of a line)
-     * @param aTransMat - the transform matrix
+     * @param aTransform - the transform matrix
      * @return - true if the point aPosRef is near this object
      */
-    virtual bool HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] ) = 0;
+    virtual bool HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform ) = 0;
 
    /**
      * @return the boundary box for this, in library coordinates
@@ -247,7 +304,7 @@ public:
     bool Inside( EDA_Rect& aRect ) { return DoTestInside( aRect ); }
 
     /**
-     * Move a draw object to a new /a aPosition.
+     * Move a draw object to a new \a aPosition.
      *
      * The real work is done by the DoMove method for each derived object type.
      *
@@ -270,6 +327,11 @@ public:
         DoMirrorHorizontal( aCenter );
     }
 
+    /**
+     * Rotate the draw item.
+     */
+    virtual void Rotate() {}
+
     /**
      * Plot the draw item using the plot object.
      *
@@ -278,8 +340,7 @@ public:
      * @param aFill - Flag to indicate whether or not the object is filled.
      * @param aTransform - The plot transform.
      */
-    void Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
-               const int aTransform[2][2] )
+    void Plot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill, const TRANSFORM& aTransform )
     {
         DoPlot( aPlotter, aOffset, aFill, aTransform );
     }
@@ -315,6 +376,27 @@ public:
      * @return - True if the draw item has been added to the parent component.
      */
     bool IsNew() { return ( m_Flags & IS_NEW ) != 0; }
+    bool IsMoving() { return ( m_Flags & IS_MOVED ); }
+    bool IsResizing() { return ( m_Flags & IS_RESIZED ); }
+
+    /**
+     * Return the draw item editing mode status.
+     *
+     * @return - True if the item is being edited.
+     */
+    bool InEditMode() { return ( m_Flags & ( IS_NEW | IS_MOVED | IS_RESIZED ) ) != 0; }
+
+    void SetEraseLastDrawItem( bool aErase = true ) { m_eraseLastDrawItem = aErase; }
+
+    virtual int GetDefaultColor();
+
+    void SetUnit( int aUnit ) { m_Unit = aUnit; }
+
+    int GetUnit() { return m_Unit; }
+
+    void SetConvert( int aConvert ) { m_Convert = aConvert; }
+
+    int GetConvert() { return m_Convert; }
 
 protected:
     virtual LIB_DRAW_ITEM* DoGenCopy() = 0;
@@ -337,7 +419,7 @@ protected:
     virtual wxPoint DoGetPosition() = 0;
     virtual void DoMirrorHorizontal( const wxPoint& aCenter ) = 0;
     virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
-                         const int aTransform[2][2] ) = 0;
+                         const TRANSFORM& aTransform ) = 0;
     virtual int DoGetWidth() = 0;
     virtual void DoSetWidth( int aWidth ) = 0;
 
@@ -354,16 +436,42 @@ protected:
 /*********************************************/
 class LIB_TEXT : public LIB_DRAW_ITEM, public EDA_TextStruct
 {
+    int m_savedOrientation;       ///< Temporary storage for orientation when editing.
+    bool m_rotate;                ///< Flag to indicate a rotation occurred while editing.
+
+    /**
+     * Draw the polyline.
+     */
+    void drawGraphic( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint& aOffset,
+                      int aColor, int aDrawMode, void* aData, const TRANSFORM& aTransform );
+
+    /**
+     * See LIB_DRAW_ITEM::saveAttributes().
+     */
+    void saveAttributes();
+
+    /**
+     * See LIB_DRAW_ITEM::restoreAttributes().
+     */
+    void restoreAttributes();
+
+    /**
+     * Calculate the text attributes ralative to \a aPosition while editing.
+     *
+     * @param aPosition - Edit position in drawing units.
+     */
+    void calcEdit( const wxPoint& aPosition );
+
 public:
-    LIB_TEXT(LIB_COMPONENT * aParent);
+    LIB_TEXT( LIB_COMPONENT * aParent );
     LIB_TEXT( const LIB_TEXT& aText );
     ~LIB_TEXT() { }
+
     virtual wxString GetClass() const
     {
         return wxT( "LIB_TEXT" );
     }
 
-
     /**
      * Write text object out to a FILE in "*.lib" format.
      *
@@ -384,11 +492,10 @@ public:
      /**
       * @param aPosRef = a wxPoint to test, in eeschema coordinates
       * @param aThreshold = max distance to a segment
-      * @param aTransMat = the transform matrix
+      * @param aTransform = the transform matrix
       * @return true if the point aPosRef is near a segment
       */
-    virtual bool HitTest( wxPoint aPosRef, int aThreshold,
-                          const int aTransMat[2][2] );
+    virtual bool HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform );
 
     /**
      * Test if the given rectangle intersects this object.
@@ -408,14 +515,27 @@ public:
      */
     virtual int GetPenSize( );
 
-    void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset,
-               int aColor, int aDrawMode, void* aData,
-               const int aTransformMatrix[2][2] );
-
     virtual void DisplayInfo( WinEDA_DrawFrame* aFrame );
 
     virtual EDA_Rect GetBoundingBox();
 
+    void Rotate();
+
+    /**
+     * See LIB_DRAW_ITEM::BeginEdit().
+     */
+    void BeginEdit( int aEditMode, const wxPoint aStartPoint = wxPoint( 0, 0 ) );
+
+    /**
+     * See LIB_DRAW_ITEM::ContinueEdit().
+     */
+    bool ContinueEdit( const wxPoint aNextPoint );
+
+    /**
+     * See LIB_DRAW_ITEM::AbortEdit().
+     */
+    void EndEdit( const wxPoint& aPosition, bool aAbort = false );
+
 protected:
     virtual LIB_DRAW_ITEM* DoGenCopy();
 
@@ -437,7 +557,7 @@ protected:
     virtual wxPoint DoGetPosition() { return m_Pos; }
     virtual void DoMirrorHorizontal( const wxPoint& aCenter );
     virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
-                         const int aTransform[2][2] );
+                         const TRANSFORM& aTransform );
     virtual int DoGetWidth() { return m_Width; }
     virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; }
 };
diff --git a/eeschema/class_libentry_fields.cpp b/eeschema/lib_field.cpp
similarity index 80%
rename from eeschema/class_libentry_fields.cpp
rename to eeschema/lib_field.cpp
index e178ef728b..a8340d6aa3 100644
--- a/eeschema/class_libentry_fields.cpp
+++ b/eeschema/lib_field.cpp
@@ -17,15 +17,16 @@
 #include "general.h"
 #include "protos.h"
 #include "class_libentry.h"
+#include "transform.h"
 
 #include <wx/tokenzr.h>
 #include <wx/stream.h>
 #include <wx/txtstrm.h>
 
 
-/***************************/
-/* class LibraryFieldEntry */
-/***************************/
+/*******************/
+/* class LIB_FIELD */
+/*******************/
 
 /**
  * a Field is a string linked to a component.
@@ -82,6 +83,8 @@ void LIB_FIELD::Init( int id )
     m_FieldId = id;
     m_Size.x = m_Size.y = DEFAULT_SIZE_TEXT;
     m_typeName = _( "Field" );
+    m_Orient = TEXT_ORIENT_HORIZ;
+    m_rotate = false;
 
     // fields in RAM must always have names, because we are trying to get
     // less dependent on field ids and more dependent on names.
@@ -288,9 +291,8 @@ int LIB_FIELD::GetPenSize()
  * if aData not NULL, aData must point a wxString which is used instead of
  * the m_Text
  */
-void LIB_FIELD::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
-                      const wxPoint& aOffset, int aColor, int aDrawMode,
-                      void* aData, const int aTransformMatrix[2][2] )
+void LIB_FIELD::drawGraphic( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint& aOffset,
+                             int aColor, int aDrawMode, void* aData, const TRANSFORM& aTransform )
 {
     wxPoint  text_pos;
     int      color;
@@ -312,29 +314,22 @@ void LIB_FIELD::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
     }
 
     if( color < 0 )
-    {
-        switch( m_FieldId )
-        {
-        case REFERENCE:
-            color = ReturnLayerColor( LAYER_REFERENCEPART );
-            break;
+        color = GetDefaultColor();
 
-        case VALUE:
-            color = ReturnLayerColor( LAYER_VALUEPART );
-            break;
+    text_pos = aTransform.TransformCoordinate( m_Pos ) + aOffset;
 
-        default:
-            color = ReturnLayerColor( LAYER_FIELDS );
-            break;
-        }
-    }
+    wxString text;
+
+    if( aData )
+        text = *(wxString*)aData;
+    else if( InEditMode() )
+        text = GetFullText( m_Unit );
+    else
+        text = m_Text;
 
-    text_pos = TransformCoordinate( aTransformMatrix, m_Pos ) + aOffset;
-    wxString* text = aData ? (wxString*)aData : &m_Text;
     GRSetDrawMode( aDC, aDrawMode );
-    DrawGraphicText( aPanel, aDC, text_pos, (EDA_Colors) color, *text,
-                     m_Orient, m_Size, m_HJustify, m_VJustify, linewidth,
-                     m_Italic, m_Bold );
+    DrawGraphicText( aPanel, aDC, text_pos, (EDA_Colors) color, text, m_Orient, m_Size,
+                     m_HJustify, m_VJustify, linewidth, m_Italic, m_Bold );
 
     /* Set to one (1) to draw bounding box around field text to validate
      * bounding box calculation. */
@@ -350,6 +345,20 @@ void LIB_FIELD::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
 }
 
 
+void LIB_FIELD::saveAttributes()
+{
+    m_savedPos = m_Pos;
+    m_savedOrientation = m_Orient;
+}
+
+
+void LIB_FIELD::restoreAttributes()
+{
+    m_Pos = m_savedPos;
+    m_Orient = m_savedOrientation;
+}
+
+
 /**
  * Function HitTest
  * tests if the given wxPoint is within the bounds of this object.
@@ -358,7 +367,7 @@ void LIB_FIELD::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
  */
 bool LIB_FIELD::HitTest( const wxPoint& refPos )
 {
-    return HitTest( refPos, 0, DefaultTransformMatrix );
+    return HitTest( refPos, 0, DefaultTransform );
 }
 
 
@@ -369,8 +378,7 @@ bool LIB_FIELD::HitTest( const wxPoint& refPos )
  * @param aThreshold =  unused here (TextHitTest calculates its threshold )
  * @param aTransMat = the transform matrix
  */
-bool LIB_FIELD::HitTest( wxPoint aPosRef, int aThreshold,
-                         const int aTransMat[2][2] )
+bool LIB_FIELD::HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform )
 {
     int extraCharCount = 0;
     // Reference designator text has one or 2 additional character (displays
@@ -387,14 +395,14 @@ bool LIB_FIELD::HitTest( wxPoint aPosRef, int aThreshold,
         }
     }
 
-    wxPoint physicalpos = TransformCoordinate( aTransMat, m_Pos );
+    wxPoint physicalpos = aTransform.TransformCoordinate( m_Pos );
     wxPoint tmp = m_Pos;
     m_Pos = physicalpos;
     /* The text orientation may need to be flipped if the
      *  transformation matrix causes xy axes to be flipped.
      * this simple algo works only for schematic matrix (rot 90 or/and mirror)
     */
-    int t1 = ( aTransMat[0][0] != 0 ) ^ ( m_Orient != 0 );
+    int t1 = ( aTransform.x1 != 0 ) ^ ( m_Orient != 0 );
     int orient = t1 ? TEXT_ORIENT_HORIZ : TEXT_ORIENT_VERT;
     EXCHG( m_Orient, orient );
 
@@ -501,7 +509,7 @@ void LIB_FIELD::DoMirrorHorizontal( const wxPoint& center )
 
 
 void LIB_FIELD::DoPlot( PLOTTER* plotter, const wxPoint& offset, bool fill,
-                        const int transform[2][2] )
+                        const TRANSFORM& aTransform )
 {
 }
 
@@ -544,3 +552,101 @@ EDA_Rect LIB_FIELD::GetBoundingBox()
 
     return rect;
 }
+
+
+int LIB_FIELD::GetDefaultColor()
+{
+    int color;
+
+    switch( m_FieldId )
+    {
+    case REFERENCE:
+        color = ReturnLayerColor( LAYER_REFERENCEPART );
+        break;
+
+    case VALUE:
+        color = ReturnLayerColor( LAYER_VALUEPART );
+        break;
+
+    default:
+        color = ReturnLayerColor( LAYER_FIELDS );
+        break;
+    }
+
+    return color;
+}
+
+
+void LIB_FIELD::Rotate()
+{
+    if( InEditMode() )
+    {
+        m_rotate = true;
+    }
+    else
+    {
+        m_Orient = ( m_Orient == TEXT_ORIENT_VERT ) ? TEXT_ORIENT_HORIZ : TEXT_ORIENT_VERT;
+    }
+}
+
+
+void LIB_FIELD::BeginEdit( int aEditMode, const wxPoint aPosition )
+{
+    wxCHECK_RET( ( aEditMode & ( IS_NEW | IS_MOVED ) ) != 0,
+                 wxT( "Invalid edit mode for LIB_FIELD object." ) );
+
+    if( aEditMode == IS_MOVED )
+    {
+        m_initialPos = m_Pos;
+        m_initialCursorPos = aPosition;
+        saveAttributes();
+        SetEraseLastDrawItem();
+    }
+    else
+    {
+        m_Pos = aPosition;
+    }
+
+    m_Flags = aEditMode;
+}
+
+
+bool LIB_FIELD::ContinueEdit( const wxPoint aPosition )
+{
+    wxCHECK_MSG( ( m_Flags & ( IS_NEW | IS_MOVED ) ) != 0, false,
+                   wxT( "Bad call to ContinueEdit().  Text is not being edited." ) );
+
+    return false;
+}
+
+
+void LIB_FIELD::EndEdit( const wxPoint& aPosition, bool aAbort )
+{
+    wxCHECK_RET( ( m_Flags & ( IS_NEW | IS_MOVED ) ) != 0,
+                   wxT( "Bad call to EndEdit().  Text is not being edited." ) );
+
+    if( aAbort && !IsNew() )
+        restoreAttributes();
+
+    m_Flags = 0;
+    SetEraseLastDrawItem( false );
+}
+
+
+void LIB_FIELD::calcEdit( const wxPoint& aPosition )
+{
+    if( m_rotate )
+    {
+        m_Orient = ( m_Orient == TEXT_ORIENT_VERT ) ? TEXT_ORIENT_HORIZ : TEXT_ORIENT_VERT;
+        m_rotate = false;
+    }
+
+    if( m_Flags == IS_NEW )
+    {
+        m_Pos = aPosition;
+    }
+    else if( m_Flags == IS_MOVED )
+    {
+        Move( m_initialPos + aPosition - m_initialCursorPos );
+    }
+}
diff --git a/eeschema/class_libentry_fields.h b/eeschema/lib_field.h
similarity index 78%
rename from eeschema/class_libentry_fields.h
rename to eeschema/lib_field.h
index c25bcd6a0c..3848f188c9 100644
--- a/eeschema/class_libentry_fields.h
+++ b/eeschema/lib_field.h
@@ -18,6 +18,32 @@
  */
 class LIB_FIELD : public LIB_DRAW_ITEM, public EDA_TextStruct
 {
+    int m_savedOrientation;
+    bool m_rotate;                ///< Flag to indicate a rotation occurred while editing.
+
+    /**
+     * Draw the field.
+     */
+    void drawGraphic( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint& aOffset,
+                      int aColor, int aDrawMode, void* aData, const TRANSFORM& aTransform );
+
+    /**
+     * See LIB_DRAW_ITEM::saveAttributes().
+     */
+    void saveAttributes();
+
+    /**
+     * See LIB_DRAW_ITEM::restoreAttributes().
+     */
+    void restoreAttributes();
+
+    /**
+     * Calculate the new circle at \a aPosition when editing.
+     *
+     * @param aPosition - The position to edit the circle in drawing coordinates.
+     */
+    void calcEdit( const wxPoint& aPosition );
+
 public:
     int         m_FieldId;  ///< @see enum NumFieldType
 
@@ -67,10 +93,6 @@ public:
 
     void          SetFields( const std::vector <LIB_FIELD> aFields );
 
-    void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset,
-               int aColor, int aDrawMode, void* aData,
-               const int aTransformMatrix[2][2] );
-
     /**
      * Function IsVisible
      * @return true is this field is visible, false if flagged invisible
@@ -98,11 +120,10 @@ public:
       * @param aPosRef = a wxPoint to test
       * @param aThreshold = max distance to this object (usually the half
       *                     thickness of a line)
-      * @param aTransMat = the transform matrix
+      * @param aTransform = the transform matrix
       * @return True if the point aPosRef is near this object
       */
-    virtual bool HitTest( wxPoint aPosRef, int aThreshold,
-                          const int aTransMat[2][2] );
+    virtual bool HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform );
 
     void operator=( const LIB_FIELD& field )
     {
@@ -134,6 +155,25 @@ public:
      */
     wxString GetFullText( int unit = 1 );
 
+    int GetDefaultColor();
+
+    /**
+     * See LIB_DRAW_ITEM::BeginEdit().
+     */
+    void BeginEdit( int aEditMode, const wxPoint aStartPoint = wxPoint( 0, 0 ) );
+
+    /**
+     * See LIB_DRAW_ITEM::ContinueEdit().
+     */
+    bool ContinueEdit( const wxPoint aNextPoint );
+
+    /**
+     * See LIB_DRAW_ITEM::AbortEdit().
+     */
+    void EndEdit( const wxPoint& aPosition, bool aAbort = false );
+
+    void Rotate();
+
 protected:
     virtual LIB_DRAW_ITEM* DoGenCopy();
 
@@ -157,7 +197,7 @@ protected:
     virtual wxPoint DoGetPosition( void ) { return m_Pos; }
     virtual void DoMirrorHorizontal( const wxPoint& center );
     virtual void DoPlot( PLOTTER* plotter, const wxPoint& offset, bool fill,
-                         const int transform[2][2] );
+                         const TRANSFORM& aTransform );
     virtual int DoGetWidth( void ) { return m_Width; }
     virtual void DoSetWidth( int width ) { m_Width = width; }
 };
diff --git a/eeschema/lib_polyline.cpp b/eeschema/lib_polyline.cpp
index 850b0ff402..d19f19e925 100644
--- a/eeschema/lib_polyline.cpp
+++ b/eeschema/lib_polyline.cpp
@@ -13,6 +13,7 @@
 #include "general.h"
 #include "protos.h"
 #include "lib_polyline.h"
+#include "transform.h"
 
 
 LIB_POLYLINE::LIB_POLYLINE( LIB_COMPONENT* aParent ) :
@@ -186,7 +187,7 @@ void LIB_POLYLINE::DoMirrorHorizontal( const wxPoint& aCenter )
 
 
 void LIB_POLYLINE::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
-                           const int aTransform[2][2] )
+                           const TRANSFORM& aTransform )
 {
     wxASSERT( aPlotter != NULL );
 
@@ -200,7 +201,7 @@ void LIB_POLYLINE::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill
     for( i = 0; i < m_PolyPoints.size(); i++ )
     {
         wxPoint pos = m_PolyPoints[i];
-        pos = TransformCoordinate( aTransform, pos ) + aOffset;
+        pos =  aTransform.TransformCoordinate(pos ) + aOffset;
         Poly[i * 2]     = pos.x;
         Poly[i * 2 + 1] = pos.y;
     }
@@ -232,9 +233,9 @@ int LIB_POLYLINE::GetPenSize()
 }
 
 
-void LIB_POLYLINE::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
-                         const wxPoint& aOffset, int aColor, int aDrawMode,
-                         void* aData, const int aTransformMatrix[2][2] )
+void LIB_POLYLINE::drawGraphic( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint& aOffset,
+                                int aColor, int aDrawMode, void* aData,
+                                const TRANSFORM& aTransform )
 {
     wxPoint         pos1;
     int             color = ReturnLayerColor( LAYER_DEVICE );
@@ -273,8 +274,7 @@ void LIB_POLYLINE::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
 
     for( unsigned ii = 0; ii < m_PolyPoints.size(); ii++ )
     {
-        Buf_Poly_Drawings[ii] = TransformCoordinate( aTransformMatrix,
-                                                     m_PolyPoints[ii] ) + aOffset;
+        Buf_Poly_Drawings[ii] = aTransform.TransformCoordinate( m_PolyPoints[ii] ) + aOffset;
     }
 
     FILL_T fill = aData ? NO_FILL : m_Fill;
@@ -306,6 +306,18 @@ void LIB_POLYLINE::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
 }
 
 
+void LIB_POLYLINE::saveAttributes()
+{
+    m_savedPolyPoints = m_PolyPoints;
+}
+
+
+void LIB_POLYLINE::restoreAttributes()
+{
+    m_PolyPoints = m_savedPolyPoints;
+}
+
+
 /**
  * Function HitTest
  * tests if the given wxPoint is within the bounds of this object.
@@ -319,7 +331,7 @@ bool LIB_POLYLINE::HitTest( const wxPoint& aRefPos )
     // Have a minimal tolerance for hit test
     if( mindist < MINIMUM_SELECTION_DISTANCE )
         mindist = MINIMUM_SELECTION_DISTANCE;
-    return HitTest( aRefPos, mindist, DefaultTransformMatrix );
+    return HitTest( aRefPos, mindist, DefaultTransform );
 }
 
 
@@ -329,14 +341,14 @@ bool LIB_POLYLINE::HitTest( const wxPoint& aRefPos )
  * @param aThreshold = max distance to a segment
  * @param aTransMat = the transform matrix
  */
-bool LIB_POLYLINE::HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] )
+bool LIB_POLYLINE::HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform )
 {
     wxPoint ref, start, end;
 
     for( unsigned ii = 1; ii < GetCornerCount(); ii++ )
     {
-        start = TransformCoordinate( aTransMat, m_PolyPoints[ii - 1] );
-        end   = TransformCoordinate( aTransMat, m_PolyPoints[ii] );
+        start = aTransform.TransformCoordinate( m_PolyPoints[ii - 1] );
+        end   = aTransform.TransformCoordinate( m_PolyPoints[ii] );
 
         if( TestSegmentHit( aPosRef, start, end, aThreshold ) )
             return true;
@@ -373,6 +385,22 @@ EDA_Rect LIB_POLYLINE::GetBoundingBox()
 }
 
 
+void LIB_POLYLINE::DeleteSegment( const wxPoint aPosition )
+{
+    // First segment is kept, only its end point is changed
+    while( GetCornerCount() > 2 )
+    {
+        m_PolyPoints.pop_back();
+
+        if( m_PolyPoints[ GetCornerCount() - 1 ] != aPosition )
+        {
+            m_PolyPoints[ GetCornerCount() - 1 ] = aPosition;
+            break;
+        }
+    }
+}
+
+
 void LIB_POLYLINE::DisplayInfo( WinEDA_DrawFrame* aFrame )
 {
     wxString msg;
@@ -380,8 +408,7 @@ void LIB_POLYLINE::DisplayInfo( WinEDA_DrawFrame* aFrame )
 
     LIB_DRAW_ITEM::DisplayInfo( aFrame );
 
-    msg = ReturnStringFromValue( g_UserUnit, m_Width,
-                                 EESCHEMA_INTERNAL_UNIT, true );
+    msg = ReturnStringFromValue( g_UserUnit, m_Width, EESCHEMA_INTERNAL_UNIT, true );
 
     aFrame->AppendMsgPanel(_( "Line width" ), msg, BLUE );
 
@@ -390,3 +417,108 @@ void LIB_POLYLINE::DisplayInfo( WinEDA_DrawFrame* aFrame )
 
     aFrame->AppendMsgPanel( _( "Bounding box" ), msg, BROWN );
 }
+
+
+void LIB_POLYLINE::BeginEdit( int aEditMode, const wxPoint aPosition )
+{
+    wxCHECK_RET( ( aEditMode & ( IS_NEW | IS_MOVED | IS_RESIZED ) ) != 0,
+                 wxT( "Invalid edit mode for LIB_POLYLINE object." ) );
+
+    if( aEditMode == IS_NEW )
+    {
+        m_PolyPoints.push_back( aPosition );  // Start point of first segment.
+        m_PolyPoints.push_back( aPosition );  // End point of first segment.
+    }
+    else if( aEditMode == IS_RESIZED )
+    {
+        saveAttributes();
+
+        // Drag one edge point of the polyline
+        // Find the nearest edge point to be dragged
+        wxPoint startPoint = m_PolyPoints[0];
+
+        // Begin with the first list point as nearest point
+        int index = 0;
+        m_ModifyIndex = 0;
+        m_initialPos = startPoint;
+
+        // First distance is the current minimum distance
+        int distanceMin = (aPosition - startPoint).x * (aPosition - startPoint).x
+                          + (aPosition - startPoint).y * (aPosition - startPoint).y;
+
+        // Find the right index of the point to be dragged
+        BOOST_FOREACH( wxPoint point, m_PolyPoints )
+        {
+            int distancePoint = (aPosition - point).x * (aPosition - point).x +
+                                (aPosition - point).y * (aPosition - point).y;
+
+            if( distancePoint < distanceMin )
+            {
+                // Save point.
+                m_initialPos = point;
+                m_ModifyIndex = index;
+                distanceMin = distancePoint;
+                break;
+            }
+
+            index++;
+        }
+
+        SetEraseLastDrawItem();
+    }
+    else if( aEditMode == IS_MOVED )
+    {
+        m_initialCursorPos = aPosition;
+        m_initialPos = m_PolyPoints[0];
+        saveAttributes();
+        SetEraseLastDrawItem();
+    }
+
+    m_Flags = aEditMode;
+}
+
+
+bool LIB_POLYLINE::ContinueEdit( const wxPoint aPosition )
+{
+    wxCHECK_MSG( ( m_Flags & ( IS_NEW | IS_MOVED | IS_RESIZED ) ) != 0, false,
+                   wxT( "Bad call to ContinueEdit().  LIB_POLYLINE is not being edited." ) );
+
+    if( m_Flags == IS_NEW )
+    {
+        m_PolyPoints.push_back( aPosition );
+        return true;
+    }
+
+    return false;
+}
+
+
+void LIB_POLYLINE::EndEdit( const wxPoint& aPosition, bool aAbort )
+{
+    wxCHECK_RET( ( m_Flags & ( IS_NEW | IS_MOVED | IS_RESIZED ) ) != 0,
+                   wxT( "Bad call to EndEdit().  LIB_POLYLINE is not being edited." ) );
+
+    if( aAbort && !IsNew() )
+        restoreAttributes();
+
+    m_Flags = 0;
+    SetEraseLastDrawItem( false );
+}
+
+
+void LIB_POLYLINE::calcEdit( const wxPoint& aPosition )
+{
+    if( m_Flags == IS_NEW )
+    {
+        m_PolyPoints[ GetCornerCount() - 1 ] = aPosition;
+        SetEraseLastDrawItem();
+    }
+    else if( m_Flags == IS_RESIZED )
+    {
+        m_PolyPoints[ m_ModifyIndex ] = aPosition;
+    }
+    else if( m_Flags == IS_MOVED )
+    {
+        Move( m_initialPos + aPosition - m_initialCursorPos );
+    }
+}
diff --git a/eeschema/lib_polyline.h b/eeschema/lib_polyline.h
index 898d803ed0..ed4f957b33 100644
--- a/eeschema/lib_polyline.h
+++ b/eeschema/lib_polyline.h
@@ -11,13 +11,38 @@
 
 class LIB_POLYLINE : public LIB_DRAW_ITEM
 {
+    std::vector<wxPoint> m_savedPolyPoints;
+
+    /**
+     * Draw the polyline.
+     */
+    void drawGraphic( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint& aOffset,
+                      int aColor, int aDrawMode, void* aData, const TRANSFORM& aTransform );
+
+    /**
+     * See LIB_DRAW_ITEM::saveAttributes().
+     */
+    void saveAttributes();
+
+    /**
+     * See LIB_DRAW_ITEM::restoreAttributes().
+     */
+    void restoreAttributes();
+
+    /**
+     * Calculate the polyline attributes ralative to \a aPosition while editing.
+     *
+     * @param aPosition - Edit position in drawing units.
+     */
+    void calcEdit( const wxPoint& aPosition );
+
 public:
     int m_Width;                            /* Line width */
     std::vector<wxPoint> m_PolyPoints;      // list of points (>= 2)
     int m_ModifyIndex;						// Index of the polyline point to modify
 
 public:
-    LIB_POLYLINE(LIB_COMPONENT * aParent);
+    LIB_POLYLINE( LIB_COMPONENT * aParent );
     LIB_POLYLINE( const LIB_POLYLINE& aPolyline );
     ~LIB_POLYLINE() { }
 
@@ -38,6 +63,11 @@ public:
 
     void AddPoint( const wxPoint& aPoint );
 
+    /**
+     * Delete the segment at \a aPosition.
+     */
+    void DeleteSegment( const wxPoint aPosition );
+
     /**
      * @return the number of corners
      */
@@ -54,11 +84,10 @@ public:
     /**
      * @param aPosRef = a wxPoint to test
      * @param aThreshold = max distance to a segment
-     * @param aTransMat = the transform matrix
+     * @param aTransform = the transform matrix
      * @return true if the point aPosRef is near a segment
      */
-    virtual bool HitTest( wxPoint aPosRef, int aThreshold,
-                          const int aTransMat[2][2] );
+    virtual bool HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform );
 
     /**
      * @return the boundary box for this, in library coordinates
@@ -70,12 +99,23 @@ public:
      */
     virtual int GetPenSize( );
 
-    void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset,
-               int aColor, int aDrawMode, void* aData,
-               const int aTransformMatrix[2][2] );
-
     virtual void DisplayInfo( WinEDA_DrawFrame* aFrame );
 
+    /**
+     * See LIB_DRAW_ITEM::BeginEdit().
+     */
+    void BeginEdit( int aEditMode, const wxPoint aStartPoint = wxPoint( 0, 0 ) );
+
+    /**
+     * See LIB_DRAW_ITEM::ContinueEdit().
+     */
+    bool ContinueEdit( const wxPoint aNextPoint );
+
+    /**
+     * See LIB_DRAW_ITEM::AbortEdit().
+     */
+    void EndEdit( const wxPoint& aPosition, bool aAbort = false );
+
 protected:
     virtual LIB_DRAW_ITEM* DoGenCopy();
 
@@ -94,10 +134,10 @@ protected:
     virtual wxPoint DoGetPosition() { return m_PolyPoints[0]; }
     virtual void DoMirrorHorizontal( const wxPoint& aCenter );
     virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
-                         const int aTransform[2][2] );
+                         const TRANSFORM& aTransform );
     virtual int DoGetWidth() { return m_Width; }
     virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; }
 };
 
 
-#endif   // _LIB_POLYLIN_H_
+#endif   // _LIB_POLYLINE_H_
diff --git a/eeschema/lib_rectangle.cpp b/eeschema/lib_rectangle.cpp
index 58cb6ee4d1..467cb79396 100644
--- a/eeschema/lib_rectangle.cpp
+++ b/eeschema/lib_rectangle.cpp
@@ -12,6 +12,7 @@
 #include "general.h"
 #include "protos.h"
 #include "lib_rectangle.h"
+#include "transform.h"
 
 
 LIB_RECTANGLE::LIB_RECTANGLE( LIB_COMPONENT* aParent ) :
@@ -141,12 +142,12 @@ void LIB_RECTANGLE::DoMirrorHorizontal( const wxPoint& aCenter )
 
 
 void LIB_RECTANGLE::DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
-                            const int aTransform[2][2] )
+                            const TRANSFORM& aTransform )
 {
     wxASSERT( aPlotter != NULL );
 
-    wxPoint pos = TransformCoordinate( aTransform, m_Pos ) + aOffset;
-    wxPoint end = TransformCoordinate( aTransform, m_End ) + aOffset;
+    wxPoint pos = aTransform.TransformCoordinate( m_Pos ) + aOffset;
+    wxPoint end = aTransform.TransformCoordinate( m_End ) + aOffset;
 
     if( aFill && m_Fill == FILLED_WITH_BG_BODYCOLOR )
     {
@@ -167,9 +168,9 @@ int LIB_RECTANGLE::GetPenSize()
     return ( m_Width == 0 ) ? g_DrawDefaultLineThickness : m_Width;
 }
 
-void LIB_RECTANGLE::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
-                          const wxPoint& aOffset, int aColor, int aDrawMode,
-                          void* aData, const int aTransformMatrix[2][2] )
+void LIB_RECTANGLE::drawGraphic( WinEDA_DrawPanel* aPanel, wxDC* aDC,
+                                 const wxPoint& aOffset, int aColor, int aDrawMode,
+                                 void* aData, const TRANSFORM& aTransform )
 {
     wxPoint pos1, pos2;
 
@@ -183,8 +184,8 @@ void LIB_RECTANGLE::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
     else
         color = aColor;
 
-    pos1 = TransformCoordinate( aTransformMatrix, m_Pos ) + aOffset;
-    pos2 = TransformCoordinate( aTransformMatrix, m_End ) + aOffset;
+    pos1 = aTransform.TransformCoordinate( m_Pos ) + aOffset;
+    pos2 = aTransform.TransformCoordinate( m_End ) + aOffset;
 
     FILL_T fill = aData ? NO_FILL : m_Fill;
     if( aColor >= 0 )
@@ -213,6 +214,20 @@ void LIB_RECTANGLE::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
 }
 
 
+void LIB_RECTANGLE::saveAttributes()
+{
+    m_savedPos = m_Pos;
+    m_savedEndPos = m_End;
+}
+
+
+void LIB_RECTANGLE::restoreAttributes()
+{
+    m_Pos = m_savedPos;
+    m_End = m_savedEndPos;
+}
+
+
 void LIB_RECTANGLE::DisplayInfo( WinEDA_DrawFrame* aFrame )
 {
     wxString msg;
@@ -250,7 +265,7 @@ bool LIB_RECTANGLE::HitTest( const wxPoint& aRefPoint )
     if( mindist < MINIMUM_SELECTION_DISTANCE )
         mindist = MINIMUM_SELECTION_DISTANCE;
 
-    return HitTest( aRefPoint, mindist, DefaultTransformMatrix );
+    return HitTest( aRefPoint, mindist, DefaultTransform );
 }
 
 
@@ -261,10 +276,10 @@ bool LIB_RECTANGLE::HitTest( const wxPoint& aRefPoint )
  *                     of a line)
  * @param aTransMat = the transform matrix
  */
-bool LIB_RECTANGLE::HitTest( wxPoint aRefPoint, int aThreshold, const int aTransMat[2][2] )
+bool LIB_RECTANGLE::HitTest( wxPoint aRefPoint, int aThreshold, const TRANSFORM& aTransform )
 {
-    wxPoint actualStart = TransformCoordinate( aTransMat, m_Pos );
-    wxPoint actualEnd   = TransformCoordinate( aTransMat, m_End );
+    wxPoint actualStart = aTransform.TransformCoordinate( m_Pos );
+    wxPoint actualEnd   = aTransform.TransformCoordinate( m_End );
 
     // locate lower segment
     wxPoint start, end;
@@ -296,3 +311,105 @@ bool LIB_RECTANGLE::HitTest( wxPoint aRefPoint, int aThreshold, const int aTrans
 
     return false;
 }
+
+
+void LIB_RECTANGLE::BeginEdit( int aEditMode, const wxPoint aPosition )
+{
+    wxCHECK_RET( ( aEditMode & ( IS_NEW | IS_MOVED | IS_RESIZED ) ) != 0,
+                 wxT( "Invalid edit mode for LIB_RECTANGLE object." ) );
+
+    if( aEditMode == IS_NEW )
+    {
+        m_Pos = m_End = aPosition;
+    }
+    else if( aEditMode == IS_RESIZED )
+    {
+        m_isStartPointSelected = abs( m_Pos.x - aPosition.x ) < MINIMUM_SELECTION_DISTANCE
+            || abs( m_Pos.y - aPosition.y ) < MINIMUM_SELECTION_DISTANCE;
+
+        if( m_isStartPointSelected )
+        {
+            m_isWidthLocked = abs( m_Pos.x - aPosition.x ) >= MINIMUM_SELECTION_DISTANCE;
+            m_isHeightLocked = abs( m_Pos.y - aPosition.y ) >= MINIMUM_SELECTION_DISTANCE;
+        }
+        else
+        {
+            m_isWidthLocked = abs( m_End.x - aPosition.x ) >= MINIMUM_SELECTION_DISTANCE;
+            m_isHeightLocked = abs( m_End.y - aPosition.y ) >= MINIMUM_SELECTION_DISTANCE;
+        }
+
+        saveAttributes();
+        SetEraseLastDrawItem();
+    }
+    else if( aEditMode == IS_MOVED )
+    {
+        m_initialPos = m_Pos;
+        m_initialCursorPos = aPosition;
+        saveAttributes();
+        SetEraseLastDrawItem();
+    }
+
+    m_Flags = aEditMode;
+}
+
+
+bool LIB_RECTANGLE::ContinueEdit( const wxPoint aPosition )
+{
+    wxCHECK_MSG( ( m_Flags & ( IS_NEW | IS_MOVED | IS_RESIZED ) ) != 0, false,
+                   wxT( "Bad call to ContinueEdit().  LIB_RECTANGLE is not being edited." ) );
+
+    return false;
+}
+
+
+void LIB_RECTANGLE::EndEdit( const wxPoint& aPosition, bool aAbort )
+{
+    wxCHECK_RET( ( m_Flags & ( IS_NEW | IS_MOVED | IS_RESIZED ) ) != 0,
+                   wxT( "Bad call to EndEdit().  LIB_RECTANGLE is not being edited." ) );
+
+    if( aAbort && !IsNew() )
+        restoreAttributes();
+
+    m_Flags = 0;
+    m_isHeightLocked = false;
+    m_isWidthLocked  = false;
+    SetEraseLastDrawItem( false );
+}
+
+
+void LIB_RECTANGLE::calcEdit( const wxPoint& aPosition )
+{
+    if( m_Flags == IS_NEW )
+    {
+        m_End = aPosition;
+        SetEraseLastDrawItem();
+    }
+    else if( m_Flags == IS_RESIZED )
+    {
+        if( m_isHeightLocked )
+        {
+            if( m_isStartPointSelected )
+                m_Pos.x = aPosition.x;
+            else
+                m_End.x = aPosition.x;
+        }
+        else if( m_isWidthLocked )
+        {
+            if( m_isStartPointSelected )
+                m_Pos.y = aPosition.y;
+            else
+                m_End.y = aPosition.y;
+        }
+        else
+        {
+            if( m_isStartPointSelected )
+                m_Pos = aPosition;
+            else
+                m_End = aPosition;
+        }
+    }
+    else if( m_Flags == IS_MOVED )
+    {
+        Move( m_initialPos + aPosition - m_initialCursorPos );
+    }
+}
diff --git a/eeschema/lib_rectangle.h b/eeschema/lib_rectangle.h
index f51dcbe702..0c31248702 100644
--- a/eeschema/lib_rectangle.h
+++ b/eeschema/lib_rectangle.h
@@ -11,6 +11,31 @@
 
 class LIB_RECTANGLE  : public LIB_DRAW_ITEM
 {
+    wxPoint m_savedEndPos;   ///< Tempory storage of the current end position before editing.
+
+    /**
+     * Draw the rectangle.
+     */
+    void drawGraphic( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint& aOffset,
+                      int aColor, int aDrawMode, void* aData, const TRANSFORM& aTransform );
+
+    /**
+     * See LIB_DRAW_ITEM::saveAttributes().
+     */
+    void saveAttributes();
+
+    /**
+     * See LIB_DRAW_ITEM::restoreAttributes().
+     */
+    void restoreAttributes();
+
+    /**
+     * Calculate the rectangle attrubites ralative to \a aPosition while editing.
+     *
+     * @param aPosition - Edit position in drawing units.
+     */
+    void calcEdit( const wxPoint& aPosition );
+
 public:
     wxPoint m_End;     /* Rectangle end point. */
     wxPoint m_Pos;     /* Rectangle start point. */
@@ -20,7 +45,7 @@ public:
     bool	m_isStartPointSelected; /* Flag: is the upper left edge selected ? */
 
 public:
-    LIB_RECTANGLE(LIB_COMPONENT * aParent);
+    LIB_RECTANGLE( LIB_COMPONENT * aParent );
     LIB_RECTANGLE( const LIB_RECTANGLE& aRect );
     ~LIB_RECTANGLE() { }
     virtual wxString GetClass() const
@@ -50,23 +75,34 @@ public:
      * @param aPosRef - a wxPoint to test
      * @param aThreshold - max distance to this object (usually the half
      *                     thickness of a line)
-     * @param aTransMat - the transform matrix
+     * @param aTransform - the transform matrix
      * @return true if the point aPosRef is near this object
      */
-    virtual bool HitTest( wxPoint aPosRef, int aThreshold, const int aTransMat[2][2] );
+    virtual bool HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform );
 
     /**
      * @return the size of the "pen" that be used to draw or plot this item
      */
     virtual int GetPenSize( );
 
-    void Draw( WinEDA_DrawPanel * aPanel, wxDC * aDC, const wxPoint &aOffset,
-               int aColor, int aDrawMode, void* aData,
-               const int aTransformMatrix[2][2] );
-
     virtual EDA_Rect GetBoundingBox();
     virtual void DisplayInfo( WinEDA_DrawFrame* aFrame );
 
+    /**
+     * See LIB_DRAW_ITEM::BeginEdit().
+     */
+    void BeginEdit( int aEditMode, const wxPoint aStartPoint = wxPoint( 0, 0 ) );
+
+    /**
+     * See LIB_DRAW_ITEM::ContinueEdit().
+     */
+    bool ContinueEdit( const wxPoint aNextPoint );
+
+    /**
+     * See LIB_DRAW_ITEM::AbortEdit().
+     */
+    void EndEdit( const wxPoint& aPosition, bool aAbort = false );
+
 protected:
     virtual LIB_DRAW_ITEM* DoGenCopy();
 
@@ -87,7 +123,7 @@ protected:
     virtual wxPoint DoGetPosition() { return m_Pos; }
     virtual void DoMirrorHorizontal( const wxPoint& aCenter );
     virtual void DoPlot( PLOTTER* aPlotter, const wxPoint& aOffset, bool aFill,
-                         const int aTransform[2][2] );
+                         const TRANSFORM& aTransform );
     virtual int DoGetWidth() { return m_Width; }
     virtual void DoSetWidth( int aWidth ) { m_Width = aWidth; }
 };
diff --git a/eeschema/class_BodyItem_Text.cpp b/eeschema/lib_text.cpp
similarity index 73%
rename from eeschema/class_BodyItem_Text.cpp
rename to eeschema/lib_text.cpp
index 5e43533ce7..2b5c0886c3 100644
--- a/eeschema/class_BodyItem_Text.cpp
+++ b/eeschema/lib_text.cpp
@@ -19,6 +19,7 @@
 #include "lib_draw_item.h"
 #include "general.h"
 #include "protos.h"
+#include "transform.h"
 
 
 LIB_TEXT::LIB_TEXT(LIB_COMPONENT * aParent) :
@@ -27,6 +28,7 @@ LIB_TEXT::LIB_TEXT(LIB_COMPONENT * aParent) :
 {
     m_Size     = wxSize( 50, 50 );
     m_typeName = _( "Text" );
+    m_rotate   = false;
 }
 
 
@@ -38,9 +40,8 @@ bool LIB_TEXT::Save( FILE* ExportFile )
     // changed to '~'
     text.Replace( wxT( " " ), wxT( "~" ) );
 
-    if( fprintf( ExportFile, "T %d %d %d %d %d %d %d %s ", m_Orient,
-                 m_Pos.x, m_Pos.y, m_Size.x, m_Attributs, m_Unit, m_Convert,
-                 CONV_TO_UTF8( text ) ) < 0 )
+    if( fprintf( ExportFile, "T %d %d %d %d %d %d %d %s ", m_Orient, m_Pos.x, m_Pos.y,
+                 m_Size.x, m_Attributs, m_Unit, m_Convert, CONV_TO_UTF8( text ) ) < 0 )
         return false;
     if( fprintf( ExportFile, " %s %d", m_Italic ? "Italic" : "Normal",
                  ( m_Bold > 0 ) ? 1 : 0 ) < 0 )
@@ -82,8 +83,7 @@ bool LIB_TEXT::Load( char* line, wxString& errorMsg )
 
     if( cnt < 8 )
     {
-        errorMsg.Printf( _( "text only had %d parameters of the required 8" ),
-                         cnt );
+        errorMsg.Printf( _( "text only had %d parameters of the required 8" ), cnt );
         return false;
     }
 
@@ -141,7 +141,7 @@ bool LIB_TEXT::Load( char* line, wxString& errorMsg )
  */
 bool LIB_TEXT::HitTest( const wxPoint& refPos )
 {
-    return HitTest( refPos, 0, DefaultTransformMatrix );
+    return HitTest( refPos, 0, DefaultTransform );
 }
 
 
@@ -151,20 +151,20 @@ bool LIB_TEXT::HitTest( const wxPoint& refPos )
  * @param aThreshold = unused here (TextHitTest calculates its threshold )
  * @param aTransMat = the transform matrix
  */
-bool LIB_TEXT::HitTest( wxPoint aPosRef, int aThreshold,
-                        const int aTransMat[2][2] )
+bool LIB_TEXT::HitTest( wxPoint aPosRef, int aThreshold, const TRANSFORM& aTransform )
 {
-    wxPoint physicalpos = TransformCoordinate( aTransMat, m_Pos );
+    wxPoint physicalpos = aTransform.TransformCoordinate( m_Pos );
     wxPoint tmp = m_Pos;
     m_Pos = physicalpos;
+
     /* The text orientation may need to be flipped if the
      *  transformation matrix causes xy axes to be flipped.
      * this simple algo works only for schematic matrix (rot 90 or/and mirror)
-    */
-    int t1 = ( aTransMat[0][0] != 0 ) ^ ( m_Orient != 0 );
+     */
+    int t1 = ( aTransform.x1 != 0 ) ^ ( m_Orient != 0 );
     int orient = t1 ? TEXT_ORIENT_HORIZ : TEXT_ORIENT_VERT;
     EXCHG( m_Orient, orient );
-    bool hit = TextHitTest(aPosRef);
+    bool hit = TextHitTest( aPosRef );
     EXCHG( m_Orient, orient );
     m_Pos = tmp;
     return hit;
@@ -250,14 +250,14 @@ void LIB_TEXT::DoMirrorHorizontal( const wxPoint& center )
 
 
 void LIB_TEXT::DoPlot( PLOTTER* plotter, const wxPoint& offset, bool fill,
-                       const int transform[2][2] )
+                       const TRANSFORM& aTransform )
 {
     wxASSERT( plotter != NULL );
 
     /* The text orientation may need to be flipped if the
      * transformation matrix causes xy axes to be flipped. */
-    int t1  = ( transform[0][0] != 0 ) ^ ( m_Orient != 0 );
-    wxPoint pos = TransformCoordinate( transform, m_Pos ) + offset;
+    int t1  = ( aTransform.x1 != 0 ) ^ ( m_Orient != 0 );
+    wxPoint pos = aTransform.TransformCoordinate( m_Pos ) + offset;
 
     plotter->text( pos, UNSPECIFIED_COLOR, m_Text,
                    t1 ? TEXT_ORIENT_HORIZ : TEXT_ORIENT_VERT,
@@ -285,13 +285,13 @@ int LIB_TEXT::GetPenSize( )
     return pensize;
 }
 
-void LIB_TEXT::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
-                     const wxPoint& aOffset, int aColor, int aDrawMode,
-                     void* aData, const int aTransformMatrix[2][2] )
+
+void LIB_TEXT::drawGraphic( WinEDA_DrawPanel* aPanel, wxDC* aDC, const wxPoint& aOffset,
+                            int aColor, int aDrawMode, void* aData, const TRANSFORM& aTransform )
 {
     wxPoint pos1, pos2;
 
-    int     color = ReturnLayerColor( LAYER_DEVICE );
+    int     color = GetDefaultColor();
 
     if( aColor < 0 )       // Used normal color or selected color
     {
@@ -301,7 +301,7 @@ void LIB_TEXT::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
     else
         color = aColor;
 
-    pos1 = TransformCoordinate( aTransformMatrix, m_Pos ) + aOffset;
+    pos1 = aTransform.TransformCoordinate( m_Pos ) + aOffset;
 
     GRSetDrawMode( aDC, aDrawMode );
 
@@ -309,7 +309,7 @@ void LIB_TEXT::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
      * orientation/mirror (needed when draw text in schematic)
      */
     int orient = m_Orient;
-    if( aTransformMatrix[0][1] )  // Rotate component 90 degrees.
+    if( aTransform.y1 )  // Rotate component 90 degrees.
     {
         if( orient == TEXT_ORIENT_HORIZ )
             orient = TEXT_ORIENT_VERT;
@@ -329,27 +329,28 @@ void LIB_TEXT::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
      * and use GetBoundaryBox to know the text coordinate considered as centered
     */
     EDA_Rect bBox = GetBoundingBox();
-    pos1 = bBox.Centre();   // this is the coordinates of the graphic text relative to the component position
-                            // in schematic Y axis orientation
+    pos1 = bBox.Centre();   // this is the coordinates of the graphic text relative to the
+                            // component position in schematic Y axis orientation.
+
     /* convert y coordinate from schematic to library Y axis orientation
      * because we want to call TransformCoordinate to calculate real coordinates
      */
     NEGATE( pos1.y );
-    pos1 = TransformCoordinate( aTransformMatrix, pos1 ) + aOffset;
-    DrawGraphicText( aPanel, aDC, pos1, (EDA_Colors) color, m_Text,
-                     orient, m_Size, GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER,
-                     GetPenSize( ), m_Italic, m_Bold );
+    pos1 = aTransform.TransformCoordinate( pos1 ) + aOffset;
+    DrawGraphicText( aPanel, aDC, pos1, (EDA_Colors) color, m_Text, orient, m_Size,
+                     GR_TEXT_HJUSTIFY_CENTER, GR_TEXT_VJUSTIFY_CENTER, GetPenSize(),
+                     m_Italic, m_Bold );
+
 
-    
     /* Enable this to draw the bounding box around the text field to validate
      * the bounding box calculations.
-    */
+     */
 #if 0
     EDA_Rect grBox;
     bBox.SetY( -bBox.GetY() );
     bBox.SetHeight( -bBox.GetHeight());
-    grBox.SetOrigin( TransformCoordinate( aTransformMatrix, bBox.GetOrigin() ) );
-    grBox.SetEnd( TransformCoordinate( aTransformMatrix, bBox.GetEnd() ) );
+    grBox.SetOrigin( aTransform.TransformCoordinate( bBox.GetOrigin() ) );
+    grBox.SetEnd( aTransform.TransformCoordinate( bBox.GetEnd() ) );
     grBox.Move( aOffset );
     GRRect( &aPanel->m_ClipBox, aDC, grBox.GetOrigin().x, grBox.GetOrigin().y,
             grBox.GetEnd().x, grBox.GetEnd().y, 0, LIGHTMAGENTA );
@@ -357,14 +358,27 @@ void LIB_TEXT::Draw( WinEDA_DrawPanel* aPanel, wxDC* aDC,
 }
 
 
+void LIB_TEXT::saveAttributes()
+{
+    m_savedPos = m_Pos;
+    m_savedOrientation = m_Orient;
+}
+
+
+void LIB_TEXT::restoreAttributes()
+{
+    m_Pos = m_savedPos;
+    m_Orient = m_savedOrientation;
+}
+
+
 void LIB_TEXT::DisplayInfo( WinEDA_DrawFrame* frame )
 {
     wxString msg;
 
     LIB_DRAW_ITEM::DisplayInfo( frame );
 
-    msg = ReturnStringFromValue( g_UserUnit, m_Width,
-                                 EESCHEMA_INTERNAL_UNIT, true );
+    msg = ReturnStringFromValue( g_UserUnit, m_Width, EESCHEMA_INTERNAL_UNIT, true );
 
     frame->AppendMsgPanel( _( "Line width" ), msg, BLUE );
 }
@@ -394,3 +408,79 @@ EDA_Rect LIB_TEXT::GetBoundingBox()
     rect.Normalize();
     return rect;
 }
+
+
+void LIB_TEXT::Rotate()
+{
+    if( InEditMode() )
+    {
+        m_rotate = true;
+    }
+    else
+    {
+        m_Orient = ( m_Orient == TEXT_ORIENT_VERT ) ? TEXT_ORIENT_HORIZ : TEXT_ORIENT_VERT;
+    }
+}
+
+
+void LIB_TEXT::BeginEdit( int aEditMode, const wxPoint aPosition )
+{
+    wxCHECK_RET( ( aEditMode & ( IS_NEW | IS_MOVED ) ) != 0,
+                 wxT( "Invalid edit mode for LIB_TEXT object." ) );
+
+    if( aEditMode == IS_MOVED )
+    {
+        m_initialPos = m_Pos;
+        m_initialCursorPos = aPosition;
+        saveAttributes();
+        SetEraseLastDrawItem();
+    }
+    else
+    {
+        m_Pos = aPosition;
+    }
+
+    m_Flags = aEditMode;
+}
+
+
+bool LIB_TEXT::ContinueEdit( const wxPoint aPosition )
+{
+    wxCHECK_MSG( ( m_Flags & ( IS_NEW | IS_MOVED ) ) != 0, false,
+                   wxT( "Bad call to ContinueEdit().  Text is not being edited." ) );
+
+    return false;
+}
+
+
+void LIB_TEXT::EndEdit( const wxPoint& aPosition, bool aAbort )
+{
+    wxCHECK_RET( ( m_Flags & ( IS_NEW | IS_MOVED ) ) != 0,
+                   wxT( "Bad call to EndEdit().  Text is not being edited." ) );
+
+    if( aAbort && !IsNew() )
+        restoreAttributes();
+
+    m_Flags = 0;
+    SetEraseLastDrawItem( false );
+}
+
+
+void LIB_TEXT::calcEdit( const wxPoint& aPosition )
+{
+    if( m_rotate )
+    {
+        m_Orient = ( m_Orient == TEXT_ORIENT_VERT ) ? TEXT_ORIENT_HORIZ : TEXT_ORIENT_VERT;
+        m_rotate = false;
+    }
+
+    if( m_Flags == IS_NEW )
+    {
+        SetEraseLastDrawItem();
+        m_Pos = aPosition;
+    }
+    else if( m_Flags == IS_MOVED )
+    {
+        Move( m_initialPos + aPosition - m_initialCursorPos );
+    }
+}
diff --git a/eeschema/libedit_onleftclick.cpp b/eeschema/libedit_onleftclick.cpp
index d6418163d3..6eed34b261 100644
--- a/eeschema/libedit_onleftclick.cpp
+++ b/eeschema/libedit_onleftclick.cpp
@@ -30,17 +30,8 @@ void WinEDA_LibeditFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
     {
         if( DrawEntry && DrawEntry->m_Flags )
         {
-        	// Don't put copy in undo list while resizing (because it's already done)
-        	if (!(DrawEntry->m_Flags & IS_RESIZED))
-        		SaveCopyInUndoList( m_component );
-
             switch( DrawEntry->Type() )
             {
-            case COMPONENT_FIELD_DRAW_TYPE:
-                PlaceField( DC, (LIB_FIELD*) DrawEntry );
-                DrawEntry = NULL;
-                break;
-
             case COMPONENT_PIN_DRAW_TYPE:
                 PlacePin( DC );
                 DrawEntry = NULL;
@@ -53,16 +44,13 @@ void WinEDA_LibeditFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
         }
         else
         {
-            DrawEntry =
-                m_component->LocateDrawItem( m_unit, m_convert, TYPE_NOT_INIT,
-                                             GetScreen()->m_MousePosition );
+            DrawEntry = m_component->LocateDrawItem( m_unit, m_convert, TYPE_NOT_INIT,
+                                                     GetScreen()->m_MousePosition );
 
             if( DrawEntry == NULL )
             {
-                DrawEntry =
-                    m_component->LocateDrawItem( m_unit, m_convert,
-                                                 TYPE_NOT_INIT,
-                                                 GetScreen()->m_Curseur );
+                DrawEntry = m_component->LocateDrawItem( m_unit, m_convert, TYPE_NOT_INIT,
+                                                         GetScreen()->m_Curseur );
             }
 
             if( DrawEntry )
@@ -106,35 +94,32 @@ void WinEDA_LibeditFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
                 if( m_drawItem->m_Flags & IS_NEW )
                     GraphicItemBeginDraw( DC );
                 else
-                {
-                    SaveCopyInUndoList( m_component );
                     EndDrawGraphicItem( DC );
-                }
             }
             break;
 
         case ID_LIBEDIT_DELETE_ITEM_BUTT:
-            DrawEntry =
-                m_component->LocateDrawItem( m_unit, m_convert, TYPE_NOT_INIT,
-                                             GetScreen()->m_MousePosition );
+            DrawEntry = m_component->LocateDrawItem( m_unit, m_convert, TYPE_NOT_INIT,
+                                                     GetScreen()->m_MousePosition );
 
             if( DrawEntry == NULL )
             {
-                DrawEntry =
-                    m_component->LocateDrawItem( m_unit, m_convert,
-                                                 TYPE_NOT_INIT,
-                                                 GetScreen()->m_Curseur );
+                DrawEntry = m_component->LocateDrawItem( m_unit, m_convert, TYPE_NOT_INIT,
+                                                         GetScreen()->m_Curseur );
             }
             if( DrawEntry == NULL )
             {
                 DisplayCmpDoc();
                 break;
             }
+
             SaveCopyInUndoList( m_component );
+
             if( DrawEntry->Type() == COMPONENT_PIN_DRAW_TYPE )
                 DeletePin( DC, m_component, (LIB_PIN*) DrawEntry );
             else
                 m_component->RemoveDrawItem( DrawEntry, DrawPanel, DC );
+
             DrawEntry = NULL;
             OnModify( );
             break;
@@ -145,10 +130,8 @@ void WinEDA_LibeditFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
             SetToolID( 0, wxCURSOR_ARROW, wxEmptyString );
             break;
 
-
         default:
-            DisplayError( this,
-                          wxT( "WinEDA_LibeditFrame::OnLeftClick error" ) );
+            DisplayError( this, wxT( "WinEDA_LibeditFrame::OnLeftClick error" ) );
             SetToolID( 0, wxCURSOR_ARROW, wxEmptyString );
             break;
         }
@@ -163,7 +146,7 @@ void WinEDA_LibeditFrame::OnLeftClick( wxDC* DC, const wxPoint& MousePos )
  */
 void WinEDA_LibeditFrame::OnLeftDClick( wxDC* DC, const wxPoint& MousePos )
 {
-    wxPoint        pos = GetPosition();
+    wxPoint pos = GetPosition();
 
     if( m_component == NULL )
         return;
@@ -175,9 +158,8 @@ void WinEDA_LibeditFrame::OnLeftDClick( wxDC* DC, const wxPoint& MousePos )
                                          GetScreen()->m_MousePosition );
         if( m_drawItem == NULL )
         {
-            m_drawItem =
-                m_component->LocateDrawItem( m_unit, m_convert, TYPE_NOT_INIT,
-                                             GetScreen()->m_Curseur );
+            m_drawItem = m_component->LocateDrawItem( m_unit, m_convert, TYPE_NOT_INIT,
+                                                      GetScreen()->m_Curseur );
         }
         if( m_drawItem == NULL )
         {
@@ -241,8 +223,7 @@ void WinEDA_LibeditFrame::OnLeftDClick( wxDC* DC, const wxPoint& MousePos )
 
     default:
         wxString msg;
-        msg.Printf( wxT( "WinEDA_LibeditFrame::OnLeftDClick Error: unknown \
-StructType %d" ),
+        msg.Printf( wxT( "WinEDA_LibeditFrame::OnLeftDClick Error: unknown StructType %d" ),
                     m_drawItem->Type() );
         DisplayError( this, msg );
         break;
diff --git a/eeschema/libeditframe.cpp b/eeschema/libeditframe.cpp
index 12015442ad..a7255ba7ce 100644
--- a/eeschema/libeditframe.cpp
+++ b/eeschema/libeditframe.cpp
@@ -11,6 +11,7 @@
 #include "confirm.h"
 #include "eda_doc.h"
 #include "bitmaps.h"
+#include "gr_basic.h"
 
 #include "program.h"
 #include "general.h"
@@ -18,6 +19,7 @@
 #include "eeschema_id.h"
 #include "libeditframe.h"
 #include "class_library.h"
+#include "lib_polyline.h"
 
 #include "kicad_device_context.h"
 #include "hotkeys.h"
@@ -163,6 +165,7 @@ WinEDA_LibeditFrame::WinEDA_LibeditFrame( WinEDA_SchematicFrame* aParent,
     SetShowDeMorgan( false );
     m_drawSpecificConvert = true;
     m_drawSpecificUnit    = false;
+    m_savedComponent      = NULL;
     m_HotkeysZoomAndGridList = s_Libedit_Hokeys_Descr;
 
     // Give an icon
@@ -743,13 +746,20 @@ void WinEDA_LibeditFrame::Process_Special_Functions( wxCommandEvent& event )
 
 
     case ID_POPUP_LIBEDIT_DELETE_CURRENT_POLY_SEGMENT:
-
+    {
         // Delete the last created segment, while creating a polyline draw item
         if( m_drawItem == NULL )
             break;
+
         DrawPanel->MouseToCursorSchema();
-        DeleteDrawPoly( &dc );
+        int oldFlags = m_drawItem->GetFlags();
+        m_drawItem->SetFlags( 0 );
+        m_drawItem->Draw( DrawPanel, &dc, wxPoint( 0, 0 ), -1, g_XorMode, NULL, DefaultTransform );
+        ( (LIB_POLYLINE*) m_drawItem )->DeleteSegment( GetScreen()->GetCursorDrawPosition() );
+        m_drawItem->Draw( DrawPanel, &dc, wxPoint( 0, 0 ), -1, g_XorMode, NULL, DefaultTransform );
+        m_drawItem->SetFlags( oldFlags );
         break;
+    }
 
     case ID_POPUP_LIBEDIT_DELETE_ITEM:
         if( m_drawItem == NULL )
@@ -780,8 +790,6 @@ void WinEDA_LibeditFrame::Process_Special_Functions( wxCommandEvent& event )
         DrawPanel->MouseToCursorSchema();
         if( m_drawItem->Type() == COMPONENT_PIN_DRAW_TYPE )
             StartMovePin( &dc );
-        else if( m_drawItem->Type() == COMPONENT_FIELD_DRAW_TYPE )
-            StartMoveField( &dc, (LIB_FIELD*) m_drawItem );
         else
             StartMoveDrawSymbol( &dc );
         break;
@@ -798,35 +806,63 @@ void WinEDA_LibeditFrame::Process_Special_Functions( wxCommandEvent& event )
             || m_drawItem->Type() == COMPONENT_ARC_DRAW_TYPE
             )
         {
-            SaveCopyInUndoList( m_component );
             StartModifyDrawSymbol( &dc );
         }
 
         break;
 
     case ID_POPUP_LIBEDIT_ROTATE_GRAPHIC_TEXT:
-        if( m_drawItem == NULL )
+        if( m_drawItem == NULL && m_drawItem->Type() != COMPONENT_GRAPHIC_TEXT_DRAW_TYPE )
             break;
         DrawPanel->CursorOff( &dc );
         DrawPanel->MouseToCursorSchema();
-        if( (m_drawItem->m_Flags & IS_NEW) == 0 )
+        if( !m_drawItem->InEditMode() )
+        {
             SaveCopyInUndoList( m_component );
-        RotateSymbolText( &dc );
+            m_drawItem->SetUnit( m_unit );
+            m_drawItem->Draw( DrawPanel, &dc, wxPoint( 0, 0 ), -1, g_XorMode, NULL,
+                              DefaultTransform );
+        }
+
+        m_drawItem->Rotate();
+
+        if( !m_drawItem->InEditMode() )
+        {
+            m_drawItem->Draw( DrawPanel, &dc, wxPoint( 0, 0 ), -1, g_XorMode, NULL,
+                              DefaultTransform );
+            DrawPanel->Refresh();
+        }
+
         DrawPanel->CursorOn( &dc );
         break;
 
     case ID_POPUP_LIBEDIT_FIELD_ROTATE_ITEM:
-        if( m_drawItem == NULL )
+    {
+        if( m_drawItem == NULL || ( m_drawItem->Type() != COMPONENT_FIELD_DRAW_TYPE ) )
             break;
         DrawPanel->CursorOff( &dc );
         DrawPanel->MouseToCursorSchema();
-        if( m_drawItem->Type() == COMPONENT_FIELD_DRAW_TYPE )
+
+        if( !m_drawItem->InEditMode() )
         {
             SaveCopyInUndoList( m_component );
-            RotateField( &dc, (LIB_FIELD*) m_drawItem );
+            m_drawItem->SetUnit( m_unit );
+            m_drawItem->Draw( DrawPanel, &dc, wxPoint( 0, 0 ), -1, g_XorMode, NULL,
+                              DefaultTransform );
         }
+
+        m_drawItem->Rotate();
+
+        if( !m_drawItem->InEditMode() )
+        {
+            m_drawItem->Draw( DrawPanel, &dc, wxPoint( 0, 0 ), -1, g_XorMode, NULL,
+                              DefaultTransform );
+            DrawPanel->Refresh();
+        }
+
         DrawPanel->CursorOn( &dc );
         break;
+    }
 
     case ID_POPUP_LIBEDIT_FIELD_EDIT_ITEM:
         if( m_drawItem == NULL )
@@ -925,9 +961,20 @@ void WinEDA_LibeditFrame::EnsureActiveLibExists()
         m_library = NULL;
 }
 
+
 void WinEDA_LibeditFrame::SetLanguage( wxCommandEvent& event )
 {
     WinEDA_BasicFrame::SetLanguage( event );
     WinEDA_SchematicFrame *parent = (WinEDA_SchematicFrame *)GetParent();
     parent->WinEDA_BasicFrame::SetLanguage( event );
 }
+
+
+void WinEDA_LibeditFrame::DeleteSavedComponent()
+{
+    if( m_savedComponent )
+    {
+        delete m_savedComponent;
+        m_savedComponent = NULL;
+    }
+}
diff --git a/eeschema/libeditframe.h b/eeschema/libeditframe.h
index 86cfa5375d..7c511fddbd 100644
--- a/eeschema/libeditframe.h
+++ b/eeschema/libeditframe.h
@@ -22,6 +22,8 @@ class Dialog_BodyGraphicText_Properties;
  */
 class WinEDA_LibeditFrame : public WinEDA_DrawFrame
 {
+    LIB_COMPONENT*   m_savedComponent;  ///< Temporary copy of current component during edit.
+
 public:
     WinEDAChoiceBox* m_SelpartBox;      // a Box to select a part to edit (if any)
     WinEDAChoiceBox* m_SelAliasBox;     // a box to select the alias to edit (if any)
@@ -94,11 +96,9 @@ public:
     void OnLeftDClick( wxDC* DC, const wxPoint& MousePos );
 
     SCH_SCREEN* GetScreen() { return (SCH_SCREEN*) GetBaseScreen(); }
-    void OnHotKey( wxDC* DC, int hotkey,
-                   EDA_BaseStruct* DrawStruct );
+    void OnHotKey( wxDC* DC, int hotkey, EDA_BaseStruct* DrawStruct );
 
-    void GeneralControle( wxDC*   DC,
-                          wxPoint MousePositionInPixels );
+    void GeneralControle( wxDC* DC, wxPoint MousePositionInPixels );
 
     void LoadSettings();
     void SaveSettings();
@@ -167,6 +167,8 @@ public:
 
     FILL_T         GetFillStyle( void ) { return m_drawFillStyle; }
 
+    void           DeleteSavedComponent();
+
 private:
 
     /**
@@ -182,16 +184,14 @@ private:
     void           SelectActiveLibrary();
     void           SaveActiveLibrary( wxCommandEvent& event );
 
-    bool           LoadOneLibraryPartAux( CMP_LIB_ENTRY* LibEntry,
-                                          CMP_LIBRARY*   Library );
+    bool           LoadOneLibraryPartAux( CMP_LIB_ENTRY* LibEntry, CMP_LIBRARY* Library );
 
     void           DisplayCmpDoc();
     void           EditComponentProperties();
 
     // General editing
 public:
-    void           SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy,
-                                       int             flag_type_command = 0 );
+    void           SaveCopyInUndoList( EDA_BaseStruct* ItemToCopy, int flag_type_command = 0 );
 
 private:
     void           GetComponentFromUndoList( wxCommandEvent& event );
@@ -199,9 +199,7 @@ private:
 
     // Editing pins
     void           CreatePin( wxDC* DC );
-    void           DeletePin( wxDC*          DC,
-                              LIB_COMPONENT* LibEntry,
-                              LIB_PIN*       Pin );
+    void           DeletePin( wxDC* DC, LIB_COMPONENT* LibEntry, LIB_PIN* Pin );
     void           StartMovePin( wxDC* DC );
 
     // Editing anchor
@@ -215,16 +213,10 @@ private:
     void           EndDrawGraphicItem( wxDC* DC );
     void           LoadOneSymbol();
     void           SaveOneSymbol();
-    void           EditGraphicSymbol( wxDC*          DC,
-                                      LIB_DRAW_ITEM* DrawItem );
+    void           EditGraphicSymbol( wxDC* DC, LIB_DRAW_ITEM* DrawItem );
     void           EditSymbolText( wxDC* DC, LIB_DRAW_ITEM* DrawItem );
-    void           RotateSymbolText( wxDC* DC );
-    void           DeleteDrawPoly( wxDC* DC );
     LIB_DRAW_ITEM* LocateItemUsingCursor();
-    void           RotateField( wxDC* DC, LIB_FIELD* Field );
-    void           PlaceField( wxDC* DC, LIB_FIELD* Field );
     void           EditField( wxDC* DC, LIB_FIELD* Field );
-    void           StartMoveField( wxDC* DC, LIB_FIELD* field );
 
 public:
     /* Block commands: */
@@ -311,9 +303,8 @@ protected:
      * @param aPrintMirrorMode = not used here (Set when printing in mirror mode)
      * @param aData = a pointer on an auxiliary data (not always used, NULL if not used)
      */
-    virtual void PrintPage( wxDC* aDC, bool aPrint_Sheet_Ref,
-                    int aPrintMask, bool aPrintMirrorMode,
-                    void * aData = NULL);
+    virtual void PrintPage( wxDC* aDC, bool aPrint_Sheet_Ref, int aPrintMask,
+                            bool aPrintMirrorMode, void * aData = NULL);
 
     /** function SVG_Print_component
      * Creates the SVG print file for the current edited component.
diff --git a/eeschema/libfield.cpp b/eeschema/libfield.cpp
index 855e5547c5..7c92badecb 100644
--- a/eeschema/libfield.cpp
+++ b/eeschema/libfield.cpp
@@ -15,120 +15,7 @@
 #include "class_library.h"
 
 
-static void ShowMoveField( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
-
-
 extern int     m_unit;
-static wxPoint s_InitialPosition, s_LastPosition;
-
-
-static void AbortMoveField( WinEDA_DrawPanel* Panel, wxDC* DC )
-{
-    Panel->ManageCurseur = NULL;
-    Panel->ForceCloseManageCurseur = NULL;
-
-    WinEDA_LibeditFrame* parent = (WinEDA_LibeditFrame*) Panel->GetParent();
-
-    if( parent == NULL )
-        return;
-
-    LIB_DRAW_ITEM* item = parent->GetDrawItem();
-
-    if( item == NULL )
-        return;
-
-    wxPoint             curpos = Panel->GetScreen()->m_Curseur;
-
-    Panel->GetScreen()->m_Curseur = s_InitialPosition;
-    ShowMoveField( Panel, DC, true );
-    Panel->GetScreen()->m_Curseur = curpos;
-    item->m_Flags = 0;
-    parent->SetDrawItem( NULL );
-}
-
-
-void WinEDA_LibeditFrame::StartMoveField( wxDC* DC, LIB_FIELD* field )
-{
-    wxPoint startPos;
-
-    if( ( m_component == NULL ) || ( field == NULL ) )
-        return;
-
-    m_drawItem = field;
-    s_InitialPosition = field->m_Pos;
-    NEGATE( s_InitialPosition.y );
-    m_drawItem->m_Flags |= IS_MOVED;
-
-    DrawPanel->CursorOff( DC );
-    s_LastPosition = s_InitialPosition;
-    GetScreen()->m_Curseur = s_InitialPosition;
-    DrawPanel->MouseToCursorSchema();
-
-    DrawPanel->ManageCurseur = ShowMoveField;
-    DrawPanel->ForceCloseManageCurseur = AbortMoveField;
-    DrawPanel->ManageCurseur( DrawPanel, DC, true );
-    s_InitialPosition = GetScreen()->m_Curseur;
-
-    DrawPanel->CursorOn( DC );
-}
-
-
-/*
- * Routine to display text 'Field' on the move.
- * Normally called by cursor management code.
- */
-static void ShowMoveField( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
-{
-    WinEDA_LibeditFrame* parent = (WinEDA_LibeditFrame*) panel->GetParent();
-
-    if( parent == NULL )
-        return;
-
-    LIB_FIELD* Field = (LIB_FIELD*) parent->GetDrawItem();
-
-    if( Field == NULL )
-        return;
-
-    wxString text = Field->GetFullText( parent->GetUnit() );
-    wxPoint  offset;
-    offset.x = s_LastPosition.x - Field->m_Pos.x;
-    offset.y = s_LastPosition.y + Field->m_Pos.y;
-
-    if( erase )
-        Field->Draw( panel, DC, offset, -1, g_XorMode, &text,
-                     DefaultTransformMatrix );
-
-    s_LastPosition = panel->GetScreen()->m_Curseur;
-    offset.x = s_LastPosition.x - Field->m_Pos.x;
-    offset.y = s_LastPosition.y + Field->m_Pos.y;
-
-    Field->Draw( panel, DC, offset, -1, g_XorMode, &text,
-                 DefaultTransformMatrix );
-}
-
-
-void WinEDA_LibeditFrame::PlaceField( wxDC* DC, LIB_FIELD* Field )
-{
-    if( Field == NULL )
-        return;
-
-    Field->m_Flags = 0;
-    Field->m_Pos.x = GetScreen()->m_Curseur.x;
-    Field->m_Pos.y = -GetScreen()->m_Curseur.y;
-    DrawPanel->CursorOff( DC );
-
-    wxString fieldText = Field->GetFullText( m_unit );
-
-    Field->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, GR_DEFAULT_DRAWMODE,
-                 &fieldText, DefaultTransformMatrix );
-
-    DrawPanel->CursorOn( DC );
-    OnModify();
-    DrawPanel->ManageCurseur = NULL;
-    DrawPanel->ForceCloseManageCurseur = NULL;
-    m_drawItem = NULL;
-}
-
 
 void WinEDA_LibeditFrame::EditField( wxDC* DC, LIB_FIELD* Field )
 {
@@ -202,12 +89,11 @@ names in the alias list." ),
          */
         if( m_library && m_library->FindEntry( Text ) != NULL )
         {
-            msg.Printf( _(
-                           "The field name <%s> conflicts with an existing \
+            msg.Printf( _( "The field name <%s> conflicts with an existing \
 entry in the component library <%s>.\nPlease choose another name that does \
-not conflict with any library entries."                                                                                                                                                           ),
-                       GetChars( Text ),
-                       GetChars( m_library->GetName() ) );
+not conflict with any library entries." ),
+                        GetChars( Text ),
+                        GetChars( m_library->GetName() ) );
             DisplayError( this, msg );
             return;
         }
@@ -217,8 +103,8 @@ not conflict with any library entries."
         Field->GetParent()->SetName( Text );
     }
 
-    Field->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, g_XorMode, &fieldText,
-                 DefaultTransformMatrix );
+    ( ( LIB_DRAW_ITEM* )Field )->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, g_XorMode,
+                                       &fieldText, DefaultTransform );
 
     if( !Text.IsEmpty() )
     {
@@ -237,57 +123,14 @@ not conflict with any library entries."
     if( Field->m_Flags == 0 )
         drawMode = GR_DEFAULT_DRAWMODE;
 
-    Field->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, drawMode, &fieldText,
-                 DefaultTransformMatrix );
+    ( ( LIB_DRAW_ITEM* )Field )->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, drawMode,
+                                       &fieldText, DefaultTransform );
 
     OnModify();
     UpdateAliasSelectList();
 }
 
 
-/*
- * Rotate a field horizontally or vertically.
- *
- * If a field is being edited, rotate.
- * Otherwise rotate the field at the current cursor position.
- */
-void WinEDA_LibeditFrame::RotateField( wxDC* DC, LIB_FIELD* Field )
-{
-    if( Field == NULL )
-        return;
-
-    OnModify();
-    DrawPanel->CursorOff( DC );
-    GRSetDrawMode( DC, g_XorMode );
-
-    wxString fieldText = Field->GetFullText( m_unit );
-
-    if( (Field->m_Flags & IS_MOVED) )
-        ShowMoveField( DrawPanel, DC, false );
-    else
-        Field->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, g_XorMode, &fieldText,
-                     DefaultTransformMatrix );
-
-    if( Field->m_Orient ==  TEXT_ORIENT_VERT )
-        Field->m_Orient = TEXT_ORIENT_HORIZ;
-    else
-        Field->m_Orient = TEXT_ORIENT_VERT;
-
-    int drawMode = g_XorMode;
-
-    if( Field->m_Flags == 0 )
-        drawMode = GR_DEFAULT_DRAWMODE;
-
-    if( (Field->m_Flags & IS_MOVED) )
-        ShowMoveField( DrawPanel, DC, false );
-    else
-        Field->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, drawMode, &fieldText,
-                     DefaultTransformMatrix );
-
-    DrawPanel->CursorOn( DC );
-}
-
-
 LIB_DRAW_ITEM* WinEDA_LibeditFrame::LocateItemUsingCursor()
 {
     if( m_component == NULL )
@@ -295,13 +138,11 @@ LIB_DRAW_ITEM* WinEDA_LibeditFrame::LocateItemUsingCursor()
 
     if( ( m_drawItem == NULL ) || ( m_drawItem->m_Flags == 0 ) )
     {
-        m_drawItem = m_component->LocateDrawItem( m_unit, m_convert,
-                                                  TYPE_NOT_INIT,
+        m_drawItem = m_component->LocateDrawItem( m_unit, m_convert, TYPE_NOT_INIT,
                                                   GetScreen()->m_MousePosition );
 
         if( m_drawItem == NULL )
-            m_drawItem = m_component->LocateDrawItem( m_unit, m_convert,
-                                                      TYPE_NOT_INIT,
+            m_drawItem = m_component->LocateDrawItem( m_unit, m_convert, TYPE_NOT_INIT,
                                                       GetScreen()->m_Curseur );
     }
 
diff --git a/eeschema/netlist.cpp b/eeschema/netlist.cpp
index 47dfc961ff..2e1076f552 100644
--- a/eeschema/netlist.cpp
+++ b/eeschema/netlist.cpp
@@ -602,9 +602,8 @@ static void AddConnectedObjects( SCH_SHEET_PATH*               sheetlist,
                         ( pin->m_Convert != DrawLibItem->m_Convert ) )
                     continue;
 
-                wxPoint pos2 =
-                    TransformCoordinate( DrawLibItem->m_Transform,
-                                         pin->m_Pos ) + DrawLibItem->m_Pos;
+                wxPoint pos2 = DrawLibItem->m_Transform.TransformCoordinate( pin->m_Pos ) +
+                    DrawLibItem->m_Pos;
 
                 new_item = new NETLIST_OBJECT();
                 new_item->m_SheetListInclude = *sheetlist;
diff --git a/eeschema/pinedit.cpp b/eeschema/pinedit.cpp
index 85869b1e37..fb5824abe1 100644
--- a/eeschema/pinedit.cpp
+++ b/eeschema/pinedit.cpp
@@ -275,7 +275,7 @@ another pin. Continue?" ) );
     DrawPanel->CursorOff( DC );
     bool showPinText = true;
     CurrentPin->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, GR_DEFAULT_DRAWMODE,
-                      &showPinText, DefaultTransformMatrix );
+                      &showPinText, DefaultTransform );
     DrawPanel->CursorOn( DC );
 
     m_drawItem = NULL;
@@ -346,14 +346,13 @@ static void DrawMovePin( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
     {
         CurrentPin->m_Pos = PinPreviousPos;
         CurrentPin->Draw( panel, DC, wxPoint( 0, 0 ), -1, g_XorMode,
-                          &showPinText, DefaultTransformMatrix );
+                          &showPinText, DefaultTransform );
     }
 
     /* Redraw pin in new position */
     CurrentPin->m_Pos.x = panel->GetScreen()->m_Curseur.x;
     CurrentPin->m_Pos.y = -panel->GetScreen()->m_Curseur.y;
-    CurrentPin->Draw( panel, DC, wxPoint( 0, 0 ), -1, g_XorMode,
-                      &showPinText, DefaultTransformMatrix );
+    CurrentPin->Draw( panel, DC, wxPoint( 0, 0 ), -1, g_XorMode, &showPinText, DefaultTransform );
 
     PinPreviousPos = CurrentPin->m_Pos;
 
@@ -471,14 +470,13 @@ void WinEDA_LibeditFrame::CreatePin( wxDC* DC )
         DrawPanel->ForceCloseManageCurseur = AbortPinMove;
         if( DC )
             pin->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, wxCOPY, &showPinText,
-                       DefaultTransformMatrix );
+                       DefaultTransform );
 
     }
 }
 
 
-static void CreateImagePins( LIB_PIN* Pin, int unit, int convert,
-                             bool asDeMorgan )
+static void CreateImagePins( LIB_PIN* Pin, int unit, int convert, bool asDeMorgan )
 {
     int      ii;
     LIB_PIN* NewPin;
@@ -556,8 +554,7 @@ void WinEDA_LibeditFrame::GlobalSetPins( wxDC* DC, LIB_PIN* MasterPin, int id )
         if( selected && ( Pin->m_Selected & IS_SELECTED ) == 0 )
             continue;
 
-        Pin->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, g_XorMode,
-                   &showPinText, DefaultTransformMatrix );
+        Pin->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, g_XorMode, &showPinText, DefaultTransform );
 
         switch( id )
         {
@@ -574,8 +571,8 @@ void WinEDA_LibeditFrame::GlobalSetPins( wxDC* DC, LIB_PIN* MasterPin, int id )
             break;
         }
 
-        Pin->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, GR_DEFAULT_DRAWMODE,
-                   &showPinText, DefaultTransformMatrix );
+        ( ( LIB_DRAW_ITEM* )Pin )->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, GR_DEFAULT_DRAWMODE,
+                                         &showPinText, DefaultTransform );
     }
 }
 
diff --git a/eeschema/plot.cpp b/eeschema/plot.cpp
index 7952045f7d..10045c0e60 100644
--- a/eeschema/plot.cpp
+++ b/eeschema/plot.cpp
@@ -40,18 +40,18 @@ static void PlotNoConnectStruct( PLOTTER* plotter, SCH_NO_CONNECT* Struct )
 static void PlotLibPart( PLOTTER* plotter, SCH_COMPONENT* DrawLibItem )
 {
     LIB_COMPONENT* Entry;
-    int            TransMat[2][2];
+    TRANSFORM temp = TRANSFORM();
 
     Entry = CMP_LIBRARY::FindLibraryComponent( DrawLibItem->m_ChipName );
 
     if( Entry == NULL )
         return;;
 
-    memcpy( TransMat, DrawLibItem->m_Transform, sizeof(TransMat) );
+    temp = DrawLibItem->m_Transform;
 
-    Entry->Plot( plotter, DrawLibItem->m_Multi, DrawLibItem->m_Convert,
-                 DrawLibItem->m_Pos, TransMat );
+    Entry->Plot( plotter, DrawLibItem->m_Multi, DrawLibItem->m_Convert, DrawLibItem->m_Pos, temp );
     bool isMulti = Entry->GetPartCount() > 1;
+
     for( int fieldId = 0; fieldId < DrawLibItem->GetFieldCount(); fieldId++ )
     {
         PlotTextField( plotter, DrawLibItem, fieldId, isMulti, 0 );
@@ -85,7 +85,7 @@ static void PlotTextField( PLOTTER* plotter, SCH_COMPONENT* DrawLibItem,
     /* Calculate the text orientation, according to the component
      * orientation/mirror */
     int orient = field->m_Orient;
-    if( DrawLibItem->m_Transform[0][1] )  // Rotate component 90 deg.
+    if( DrawLibItem->m_Transform.y1 )  // Rotate component 90 deg.
     {
         if( orient == TEXT_ORIENT_HORIZ )
             orient = TEXT_ORIENT_VERT;
diff --git a/eeschema/program.h b/eeschema/program.h
index c7f2771733..377774077d 100644
--- a/eeschema/program.h
+++ b/eeschema/program.h
@@ -5,14 +5,18 @@
 #ifndef PROGRAM_H
 #define PROGRAM_H
 
+
+class TRANSFORM;
+
+
 #define HIGHLIGHT_COLOR WHITE
 #define TEXT_NO_VISIBLE 1
 
 #include "wxEeschemaStruct.h"
 #include "macros.h"
 #include "base_struct.h"
-#include "sch_item_struct.h"
 
+#include "sch_item_struct.h"
 #include "class_sch_component.h"
 #include "class_sch_screen.h"
 #include "class_drawsheet.h"
@@ -26,10 +30,8 @@
  * a defualt matix ( no rotation, no mirror but Y axis is bottom to top, and
  * Y draw axis is to to bottom so we must have a default matix that reverses
  * the Y coordinate and keeps the X coordiate
- *      DefaultTransformMatrix[0][0] = 1; DefaultTransformMatrix[1][1] = -1;
- *      DefaultTransformMatrix[1][0] = DefaultTransformMatrix[0][1] = 0;
  */
-extern int DefaultTransformMatrix[2][2];
+extern TRANSFORM DefaultTransform;
 
 #define MIN_BUSLINES_THICKNESS 12   // min bus lines and entries thickness
 
diff --git a/eeschema/protos.h b/eeschema/protos.h
index 5c1ddab8e3..c13a2128cf 100644
--- a/eeschema/protos.h
+++ b/eeschema/protos.h
@@ -50,19 +50,6 @@ void IncrementLabelMember( wxString& name );
 /****************/
 void InstallCmpeditFrame( WinEDA_SchematicFrame* parent, wxPoint& pos, SCH_COMPONENT* m_Cmp );
 
-
-bool MapAngles( int* Angle1, int* Angle2, const int TransMat[2][2] );
-
-
-/**
- * Calculate new coordinate according to the transform matrix.
- *
- * @param aTransformMatrix = rotation, mirror .. matrix
- * @param aPosition = the position to transform
- * @return the new coordinate
- */
-wxPoint        TransformCoordinate( const int aTransformMatrix[2][2], const wxPoint& aPosition );
-
 void           SnapLibItemPoint( int            OrigX,
                                  int            OrigY,
                                  int*           ClosestX,
diff --git a/eeschema/read_from_file_schematic_items_descriptions.cpp b/eeschema/read_from_file_schematic_items_descriptions.cpp
index 659009ba6b..db8cee467c 100644
--- a/eeschema/read_from_file_schematic_items_descriptions.cpp
+++ b/eeschema/read_from_file_schematic_items_descriptions.cpp
@@ -809,14 +809,12 @@ int ReadPartDescr( wxWindow* frame, char* Line, FILE* f, wxString& aMsgDiag,
     *aLineNum++;
     if( ( fgets( Line, 256 - 1, f ) == NULL )
        || ( sscanf( Line, "%d %d %d %d",
-                    &component->m_Transform[0][0],
-                    &component->m_Transform[0][1],
-                    &component->m_Transform[1][0],
-                    &component->m_Transform[1][1] ) != 4 ) )
+                    &component->m_Transform.x1,
+                    &component->m_Transform.y1,
+                    &component->m_Transform.x2,
+                    &component->m_Transform.y2 ) != 4 ) )
     {
-        aMsgDiag.Printf(
-            wxT( "Component orient error at line %d, aborted" ),
-            *aLineNum );
+        aMsgDiag.Printf( wxT( "Component orient error at line %d, aborted" ), *aLineNum );
         Failed = TRUE;
         return Failed;
     }
diff --git a/eeschema/symbdraw.cpp b/eeschema/symbdraw.cpp
index d19ed57df2..ec96ac6125 100644
--- a/eeschema/symbdraw.cpp
+++ b/eeschema/symbdraw.cpp
@@ -6,16 +6,11 @@
 
 #include "fctsys.h"
 #include "gr_basic.h"
-#include "appl_wxstruct.h"
-#include "common.h"
 #include "class_drawpanel.h"
 #include "confirm.h"
-#include "eeschema_id.h"
 
+#include "eeschema_id.h"
 #include "program.h"
-#include "general.h"
-#include "trigo.h"
-#include "protos.h"
 #include "libeditframe.h"
 #include "class_libentry.h"
 #include "dialog_lib_edit_draw_item.h"
@@ -24,38 +19,10 @@
 #include "lib_polyline.h"
 #include "lib_rectangle.h"
 
-#include <boost/foreach.hpp>
 
-static void    SymbolDisplayDraw( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
-static void    ComputeArc( LIB_ARC* DrawItem, wxPoint ArcCentre );
-static void    ComputeArcRadiusAngles( LIB_ARC* arc );
-static wxPoint ComputeCircumCenter( wxPoint A, wxPoint B, wxPoint C );
-static void    RedrawWhileMovingCursor( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
+static void SymbolDisplayDraw( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
+static void RedrawWhileMovingCursor( WinEDA_DrawPanel* panel, wxDC* DC, bool erase );
 
-static wxPoint InitPosition, StartCursor, ItemPreviousPos;
-
-typedef enum {
-    START_POINT, END_POINT, OUTLINE
-} SelectedPoint;
-
-// Attributes of the arc in edit
-static struct
-{
-    wxPoint       startPoint, endPoint; //!< Start, end coordinates
-    int           stateDrawArc;         //!< The actual drawing state
-    double        distanceCenter;       //!< Distance from arc center to middle of start-/end-point
-    SelectedPoint selectedPoint;        //!< The selected point while modifying
-    int           direction;            //!< Determines the side of the center point relative to start/end point
-} arcState;
-
-// Structure for saving attributes before modifying graphics objects
-static struct
-{
-    wxPoint startPoint;
-    wxPoint endPoint;
-    wxPoint centerPoint;
-    int     radius;
-} savedAttributes;
 
 /*
  * Show the dialog box for editing a graphical item properties
@@ -65,7 +32,7 @@ void WinEDA_LibeditFrame::EditGraphicSymbol( wxDC* DC, LIB_DRAW_ITEM* DrawItem )
     if( DrawItem == NULL )
         return;
 
-    LIB_COMPONENT*            component = DrawItem->GetParent();
+    LIB_COMPONENT* component = DrawItem->GetParent();
 
     DIALOG_LIB_EDIT_DRAW_ITEM dialog( this, DrawItem->m_typeName );
 
@@ -129,75 +96,29 @@ void WinEDA_LibeditFrame::EditGraphicSymbol( wxDC* DC, LIB_DRAW_ITEM* DrawItem )
 
 static void AbortSymbolTraceOn( WinEDA_DrawPanel* Panel, wxDC* DC )
 {
-    LIB_DRAW_ITEM*       item;
     WinEDA_LibeditFrame* parent = (WinEDA_LibeditFrame*) Panel->GetParent();
-
-    item = parent->GetDrawItem();
+    LIB_DRAW_ITEM*       item   = parent->GetDrawItem();
 
     if( item == NULL )
         return;
 
-    arcState.stateDrawArc = 0;
     Panel->ManageCurseur  = NULL;
     Panel->ForceCloseManageCurseur = NULL;
 
-    if( item->m_Flags & IS_NEW )
+    bool deleteItem = item->IsNew();
+    item->EndEdit( parent->GetScreen()->GetCursorDrawPosition(), true );
+
+    // This draw is required to restore the item to it's last state.
+    item->Draw( Panel, DC, wxPoint( 0, 0 ), -1, g_XorMode, NULL, DefaultTransform );
+
+    if( deleteItem )
     {
         SAFE_DELETE( item );
         parent->SetDrawItem( NULL );
     }
-    else
-    {
-        // Restore old attributes, when the item was modified
-        if( item->m_Flags == IS_RESIZED )
-        {
-            item->Draw( Panel, DC, wxPoint( 0, 0 ), -1, g_XorMode, NULL, DefaultTransformMatrix );
 
-            switch( item->Type() )
-            {
-            case COMPONENT_CIRCLE_DRAW_TYPE:
-                ( (LIB_CIRCLE*) item )->m_Radius = savedAttributes.radius;
-                break;
-
-            case COMPONENT_RECT_DRAW_TYPE:
-                ( (LIB_RECTANGLE*) item )->m_Pos = savedAttributes.startPoint;
-                ( (LIB_RECTANGLE*) item )->m_End = savedAttributes.endPoint;
-                break;
-
-            case COMPONENT_POLYLINE_DRAW_TYPE:
-            {
-                wxPoint point = savedAttributes.startPoint;
-                int     index = ( (LIB_POLYLINE*) item )->m_ModifyIndex;
-                ( ( (LIB_POLYLINE*) item )->m_PolyPoints )[index] = point;
-            }
-            break;
-
-            case COMPONENT_ARC_DRAW_TYPE:
-                ( (LIB_ARC*) item )->m_ArcStart = savedAttributes.startPoint;
-                ( (LIB_ARC*) item )->m_ArcEnd   = savedAttributes.endPoint;
-                ( (LIB_ARC*) item )->m_Pos = savedAttributes.centerPoint;
-
-                ComputeArcRadiusAngles( (LIB_ARC*) item );
-
-                break;
-
-            default:
-                break;
-            }
-
-            item->m_Flags = 0;
-        }
-        else
-        {
-            wxPoint             curpos    = Panel->GetScreen()->m_Curseur;
-            Panel->GetScreen()->m_Curseur = StartCursor;
-            RedrawWhileMovingCursor( Panel, DC, TRUE );
-            Panel->GetScreen()->m_Curseur = curpos;
-        }
-        item->m_Flags = 0;
-    }
-
-    Panel->Refresh( );
+    parent->DeleteSavedComponent();
+    Panel->Refresh();
 }
 
 
@@ -205,69 +126,32 @@ LIB_DRAW_ITEM* WinEDA_LibeditFrame::CreateGraphicItem( LIB_COMPONENT* LibEntry,
 {
     DrawPanel->ManageCurseur = SymbolDisplayDraw;
     DrawPanel->ForceCloseManageCurseur = AbortSymbolTraceOn;
+    wxPoint drawPos = GetScreen()->GetCursorDrawPosition();
 
     switch( m_ID_current_state )
     {
     case ID_LIBEDIT_BODY_ARC_BUTT:
     {
-        LIB_ARC* Arc = new LIB_ARC( LibEntry );
-
-        m_drawItem = Arc;
-        arcState.startPoint.x = arcState.endPoint.x = GetScreen()->m_Curseur.x;
-        arcState.startPoint.y = arcState.endPoint.y = -( GetScreen()->m_Curseur.y );
-        arcState.stateDrawArc = 1;
-        Arc->m_Fill  = m_drawFillStyle;
-        Arc->m_Width = m_drawLineWidth;
+        m_drawItem = new LIB_ARC( LibEntry );
+        break;
     }
-    break;
-
     case ID_LIBEDIT_BODY_CIRCLE_BUTT:
-    {
-        LIB_CIRCLE* Circle = new LIB_CIRCLE( LibEntry );
-
-        m_drawItem    = Circle;
-        Circle->m_Pos = GetScreen()->m_Curseur;
-        NEGATE( Circle->m_Pos.y );
-        Circle->m_Fill  = m_drawFillStyle;
-        Circle->m_Width = m_drawLineWidth;
-    }
-    break;
+        m_drawItem = new LIB_CIRCLE( LibEntry );
+        break;
 
     case ID_LIBEDIT_BODY_RECT_BUTT:
-    {
-        LIB_RECTANGLE* Square = new LIB_RECTANGLE( LibEntry );
-
-        m_drawItem    = Square;
-        Square->m_Pos = GetScreen()->m_Curseur;
-        NEGATE( Square->m_Pos.y );
-        Square->m_End   = Square->m_Pos;
-        Square->m_Fill  = m_drawFillStyle;
-        Square->m_Width = m_drawLineWidth;
-    }
-    break;
+        m_drawItem = new LIB_RECTANGLE( LibEntry );
+        break;
 
     case ID_LIBEDIT_BODY_LINE_BUTT:
-    {
-        LIB_POLYLINE* polyline = new LIB_POLYLINE( LibEntry );
-        m_drawItem = polyline;
-        wxPoint       point = GetScreen()->m_Curseur;
-        NEGATE( point.y );
-        polyline->AddPoint( point );    // Start point of the current segment
-        polyline->AddPoint( point );    // End point of the current segment
-        polyline->m_Fill  = m_drawFillStyle;
-        polyline->m_Width = m_drawLineWidth;
-    }
-    break;
+        m_drawItem = new LIB_POLYLINE( LibEntry );
+        break;
 
     case ID_LIBEDIT_BODY_TEXT_BUTT:
     {
         LIB_TEXT* Text = new LIB_TEXT( LibEntry );
-
-        m_drawItem     = Text;
         Text->m_Size.x = Text->m_Size.y = m_textSize;
         Text->m_Orient = m_textOrientation;
-        Text->m_Pos    = GetScreen()->m_Curseur;
-        NEGATE( Text->m_Pos.y );
 
         // Enter the graphic text info
         DrawPanel->m_IgnoreMouseEvents = true;
@@ -279,18 +163,13 @@ LIB_DRAW_ITEM* WinEDA_LibeditFrame::CreateGraphicItem( LIB_COMPONENT* LibEntry,
         {
             SAFE_DELETE( Text );
             m_drawItem = NULL;
-            DrawPanel->ManageCurseur = NULL;
-            DrawPanel->ForceCloseManageCurseur = NULL;
         }
         else
         {
-            StartMoveDrawSymbol( DC );
-            Text->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, g_XorMode, NULL,
-                        DefaultTransformMatrix );
+            m_drawItem = Text;
         }
+        break;
     }
-    break;
-
     default:
         DisplayError( this, wxT( "WinEDA_LibeditFrame::CreateGraphicItem() error" ) );
         return NULL;
@@ -298,11 +177,22 @@ LIB_DRAW_ITEM* WinEDA_LibeditFrame::CreateGraphicItem( LIB_COMPONENT* LibEntry,
 
     if( m_drawItem )
     {
-        m_drawItem->m_Flags |= IS_NEW;
+        m_drawItem->BeginEdit( IS_NEW, drawPos );
+        m_drawItem->SetWidth( m_drawLineWidth );
+        m_drawItem->m_Fill  = m_drawFillStyle;
+
         if( m_drawSpecificUnit )
             m_drawItem->m_Unit = m_unit;
         if( m_drawSpecificConvert )
             m_drawItem->m_Convert = m_convert;
+
+        m_savedComponent = new LIB_COMPONENT( *m_component );
+    }
+    else
+    {
+        DrawPanel->ManageCurseur = NULL;
+        DrawPanel->ForceCloseManageCurseur = NULL;
+        return NULL;
     }
 
     DrawPanel->MouseToCursorSchema();
@@ -319,43 +209,15 @@ void WinEDA_LibeditFrame::GraphicItemBeginDraw( wxDC* DC )
     if( m_drawItem == NULL )
         return;
 
-    switch( m_drawItem->Type() )
-    {
-    case COMPONENT_ARC_DRAW_TYPE:
-        if( arcState.stateDrawArc == 1 )
-        {
-            SymbolDisplayDraw( DrawPanel, DC, FALSE );
-            arcState.stateDrawArc = 2;
-            SymbolDisplayDraw( DrawPanel, DC, FALSE );
-            break;
-        }
-        if( arcState.stateDrawArc > 1 )
-        {
-            EndDrawGraphicItem( DC );
-            return;
-        }
-        break;
+    wxPoint pos = GetScreen()->GetCursorDrawPosition();
 
-    case COMPONENT_CIRCLE_DRAW_TYPE:
-    case COMPONENT_RECT_DRAW_TYPE:
-    case COMPONENT_GRAPHIC_TEXT_DRAW_TYPE:
-        EndDrawGraphicItem( DC );
+    if( m_drawItem->ContinueEdit( pos ) )
+    {
+        m_drawItem->Draw( DrawPanel, DC, pos, -1, g_XorMode, NULL, DefaultTransform );
         return;
-
-    case COMPONENT_POLYLINE_DRAW_TYPE:
-    {
-        wxPoint pos = GetScreen()->m_Curseur;
-        NEGATE( pos.y );
-        ( (LIB_POLYLINE*) m_drawItem )->AddPoint( pos );
     }
-    break;
 
-    case COMPONENT_LINE_DRAW_TYPE:
-        break;
-
-    default:
-        ;
-    }
+    EndDrawGraphicItem( DC );
 }
 
 
@@ -372,19 +234,9 @@ static void RedrawWhileMovingCursor( WinEDA_DrawPanel* panel, wxDC* DC, bool era
         return;
 
     BASE_SCREEN* Screen = panel->GetScreen();
-    wxPoint      pos;
 
-    /* Erase shape in the old position*/
-    if( erase )
-    {
-        pos = ItemPreviousPos - StartCursor;
-        item->Draw( panel, DC, pos, -1, g_XorMode, NULL, DefaultTransformMatrix );
-    }
-
-    /* Redraw moved shape */
-    pos = Screen->m_Curseur - StartCursor;
-    item->Draw( panel, DC, pos, -1, g_XorMode, NULL, DefaultTransformMatrix );
-    ItemPreviousPos = Screen->m_Curseur;
+    item->Draw( panel, DC, Screen->GetCursorDrawPosition(), -1, g_XorMode, NULL,
+                DefaultTransform );
 }
 
 
@@ -395,13 +247,14 @@ void WinEDA_LibeditFrame::StartMoveDrawSymbol( wxDC* DC )
 
     SetCursor( wxCURSOR_HAND );
 
-    m_drawItem->m_Flags |= IS_MOVED;
-    StartCursor     = GetScreen()->m_Curseur;
-    InitPosition    = m_drawItem->GetPosition();
-    ItemPreviousPos = GetScreen()->m_Curseur;
+    if( m_drawItem->m_Unit != m_unit )
+        m_drawItem->m_Unit = m_unit;
+
+    m_savedComponent = new LIB_COMPONENT( *m_component );
+    m_drawItem->BeginEdit( IS_MOVED, GetScreen()->GetCursorDrawPosition() );
     DrawPanel->ManageCurseur = RedrawWhileMovingCursor;
     DrawPanel->ForceCloseManageCurseur = AbortSymbolTraceOn;
-    DrawPanel->ManageCurseur( DrawPanel, DC, TRUE );
+    DrawPanel->ManageCurseur( DrawPanel, DC, true );
 }
 
 
@@ -411,400 +264,25 @@ void WinEDA_LibeditFrame::StartModifyDrawSymbol( wxDC* DC )
     if( m_drawItem == NULL )
         return;
 
-    // TODO Check if this is really required
-    StartCursor     = GetScreen()->m_Curseur;
-    InitPosition    = m_drawItem->GetPosition();
-    ItemPreviousPos = GetScreen()->m_Curseur;
-
-    switch( m_drawItem->Type() )
-    {
-    case COMPONENT_ARC_DRAW_TYPE:
-    {
-        wxPoint cursor = StartCursor;
-        cursor.y = -cursor.y;
-
-        // The arc center point has to be rotated with while adjusting the
-        // start or end point, determine the side of this point and the distance
-        // from the start / end point
-        wxPoint startPoint  = ( (LIB_ARC*) m_drawItem )->m_ArcStart;
-        wxPoint endPoint    = ( (LIB_ARC*) m_drawItem )->m_ArcEnd;
-        wxPoint centerPoint = ( (LIB_ARC*) m_drawItem )->m_Pos;
-        wxPoint middlePoint = wxPoint( (startPoint.x + endPoint.x) / 2,
-                                       (startPoint.y + endPoint.y) / 2 );
-        wxPoint centerVector   = centerPoint - middlePoint;
-        wxPoint startEndVector = TwoPointVector( startPoint, endPoint );
-        arcState.distanceCenter = EuclideanNorm( centerVector );
-
-        // Determine on which side is the center point
-        arcState.direction = CrossProduct( startEndVector, centerVector ) ? 1 : -1;
-
-        arcState.startPoint = startPoint;
-        arcState.endPoint   = endPoint;
-
-        // Save the old values
-        savedAttributes.startPoint  = startPoint;
-        savedAttributes.endPoint    = endPoint;
-        savedAttributes.centerPoint = centerPoint;
-
-        // Drag either the start, end point or the outline
-        if( HitTestPoints( startPoint, cursor, MINIMUM_SELECTION_DISTANCE ) )
-        {
-            arcState.selectedPoint = START_POINT;
-        }
-        else if( HitTestPoints( endPoint, cursor, MINIMUM_SELECTION_DISTANCE ) )
-        {
-            arcState.selectedPoint = END_POINT;
-        }
-        else
-            arcState.selectedPoint = OUTLINE;
-
-        arcState.stateDrawArc = 0;
-
-        m_drawItem->m_Flags |= IS_RESIZED;
-    }
-    break;
-
-    case COMPONENT_RECT_DRAW_TYPE:
-    {
-        // Save old attributes
-        savedAttributes.startPoint = ( (LIB_RECTANGLE*) m_drawItem )->m_Pos;
-        savedAttributes.endPoint   = ( (LIB_RECTANGLE*) m_drawItem )->m_End;
-
-        // Resize rectangle
-        m_drawItem->m_Flags |= IS_RESIZED;
-
-        // If the cursor is not on the rectangle edge point,
-        // lock the width or height
-
-        wxPoint rectEnd   = ( (LIB_RECTANGLE*) m_drawItem )->m_End;
-        wxPoint rectStart = ( (LIB_RECTANGLE*) m_drawItem )->m_Pos;
-        wxPoint cursor    = StartCursor;
-        cursor.y = -cursor.y;
-
-        ( (LIB_RECTANGLE*) m_drawItem )->m_isStartPointSelected =
-            abs( rectStart.x - cursor.x ) < MINIMUM_SELECTION_DISTANCE
-            || abs( rectStart.y - cursor.y ) < MINIMUM_SELECTION_DISTANCE;
-
-        if( ( (LIB_RECTANGLE*) m_drawItem )->m_isStartPointSelected )
-        {
-            ( (LIB_RECTANGLE*) m_drawItem )->m_isWidthLocked =
-                abs( rectStart.x - cursor.x ) >= MINIMUM_SELECTION_DISTANCE;
-
-            ( (LIB_RECTANGLE*) m_drawItem )->m_isHeightLocked =
-                abs( rectStart.y - cursor.y ) >= MINIMUM_SELECTION_DISTANCE;
-        }
-        else
-        {
-            ( (LIB_RECTANGLE*) m_drawItem )->m_isWidthLocked =
-                abs( rectEnd.x - cursor.x ) >= MINIMUM_SELECTION_DISTANCE;
-
-            ( (LIB_RECTANGLE*) m_drawItem )->m_isHeightLocked =
-                abs( rectEnd.y - cursor.y ) >= MINIMUM_SELECTION_DISTANCE;
-        }
-    }
-    break;
-
-    case COMPONENT_CIRCLE_DRAW_TYPE:
-        savedAttributes.radius = ( (LIB_CIRCLE*) m_drawItem )->m_Radius;
-        m_drawItem->m_Flags   |= IS_RESIZED;
-        break;
-
-    case COMPONENT_POLYLINE_DRAW_TYPE:
-    {
-        // Drag one edge point of the polyline
-
-        m_drawItem->m_Flags |= IS_RESIZED;
-
-        // Find the nearest edge point to be dragged
-        wxPoint cursor     = StartCursor;
-        wxPoint startPoint = ( ( (LIB_POLYLINE*) m_drawItem )->m_PolyPoints )[0];
-        cursor.y = NEGATE( cursor.y );
-
-        // Begin with the first list point as nearest point
-        int index = 0;
-        ( (LIB_POLYLINE*) m_drawItem )->m_ModifyIndex = 0;
-        savedAttributes.startPoint = startPoint;
-
-        // First distance is the current minimum distance
-        int distanceMin = (cursor - startPoint).x * (cursor - startPoint).x
-                          + (cursor - startPoint).y * (cursor - startPoint).y;
-
-        // Find the right index of the point to be dragged
-        BOOST_FOREACH( wxPoint point, ( ( (LIB_POLYLINE*) m_drawItem )->m_PolyPoints ) )
-        {
-            int distancePoint = (cursor - point).x * (cursor - point).x +
-                                (cursor - point).y * (cursor - point).y;
-
-            if( distancePoint < distanceMin )
-            {
-                // Save point
-                savedAttributes.startPoint = point;
-
-                ( (LIB_POLYLINE*) m_drawItem )->m_ModifyIndex = index;
-                distanceMin = distancePoint;
-            }
-            index++;
-        }
-    }
-    break;
-
-    default:
-        break;
-    }
-
+    m_savedComponent = new LIB_COMPONENT( *m_component );
+    m_drawItem->BeginEdit( IS_RESIZED, GetScreen()->GetCursorDrawPosition() );
     DrawPanel->ManageCurseur = SymbolDisplayDraw;
     DrawPanel->ForceCloseManageCurseur = AbortSymbolTraceOn;
-    DrawPanel->ManageCurseur( DrawPanel, DC, TRUE );
+    DrawPanel->ManageCurseur( DrawPanel, DC, true );
 }
 
 
 //! @brief Manage mouse events when creating new graphic object or modifying an graphic object.
 static void SymbolDisplayDraw( WinEDA_DrawPanel* panel, wxDC* DC, bool erase )
 {
-    int            dx, dy;
-    int            DrawMode = g_XorMode;
     BASE_SCREEN*   Screen   = panel->GetScreen();
-    wxPoint        currentCursorPosition = Screen->m_Curseur;
-    FILL_T         fillStyle = NO_FILL;
-    LIB_DRAW_ITEM* item;
-
-    item = ( (WinEDA_LibeditFrame*) panel->GetParent() )->GetDrawItem();
+    LIB_DRAW_ITEM* item = ( (WinEDA_LibeditFrame*) panel->GetParent() )->GetDrawItem();
 
     if( item == NULL )
         return;
 
-    fillStyle = ( (WinEDA_LibeditFrame*) panel->GetParent() )->GetFillStyle();
-
-    NEGATE( currentCursorPosition.y );
-
-    GRSetDrawMode( DC, DrawMode );
-
-    if( erase )
-    {
-        if( arcState.stateDrawArc == 1 )
-        {
-            int Color = ReturnLayerColor( LAYER_DEVICE );
-            GRLine( &panel->m_ClipBox, DC, arcState.startPoint.x, -arcState.startPoint.y,
-                    arcState.endPoint.x, -arcState.endPoint.y, 0, Color );
-        }
-        else
-        {
-            item->Draw( panel, DC, wxPoint( 0, 0 ), -1, DrawMode, NULL,
-                        DefaultTransformMatrix );
-
-            if( item->Type() == COMPONENT_ARC_DRAW_TYPE  && item->m_Flags != IS_RESIZED )
-            {
-                int Color = ReturnLayerColor( LAYER_DEVICE );
-                GRDashedLine( &panel->m_ClipBox, DC, arcState.startPoint.x, -arcState.startPoint.y,
-                              ( (LIB_ARC*) item )->m_Pos.x,
-                              -( (LIB_ARC*) item )->m_Pos.y,
-                              0, Color );
-                GRDashedLine( &panel->m_ClipBox, DC, arcState.endPoint.x, -arcState.endPoint.y,
-                              ( (LIB_ARC*) item )->m_Pos.x,
-                              -( (LIB_ARC*) item )->m_Pos.y,
-                              0, Color );
-            }
-        }
-    }
-
-    switch( item->Type() )
-    {
-    case COMPONENT_ARC_DRAW_TYPE:
-        if( item->m_Flags == IS_RESIZED )
-        {
-            wxPoint newCenterPoint;
-
-            // Choose the point of the arc to be adjusted
-            if( arcState.selectedPoint == START_POINT )
-            {
-                arcState.startPoint = currentCursorPosition;
-                arcState.endPoint   = ( (LIB_ARC*) item )->m_ArcEnd;
-            }
-            else if( arcState.selectedPoint == END_POINT )
-            {
-                arcState.endPoint   = currentCursorPosition;
-                arcState.startPoint = ( (LIB_ARC*) item )->m_ArcStart;
-            }
-            else
-            {
-                // Use the cursor for adjusting the arc curvature
-                arcState.startPoint = ( (LIB_ARC*) item )->m_ArcStart;
-                arcState.endPoint   = ( (LIB_ARC*) item )->m_ArcEnd;
-
-                wxPoint middlePoint = wxPoint( (arcState.startPoint.x + arcState.endPoint.x) / 2,
-                                               (arcState.startPoint.y + arcState.endPoint.y) / 2 );
-
-
-                // If the distance is too small, use the old center point
-                // else the new center point is calculated over the three points start/end/cursor
-                if( DistanceLinePoint( arcState.startPoint, arcState.endPoint,
-                                       currentCursorPosition )
-                    > MINIMUM_SELECTION_DISTANCE )
-                {
-                    newCenterPoint = ComputeCircumCenter( arcState.startPoint,
-                                                          currentCursorPosition,
-                                                          arcState.endPoint );
-                }
-                else
-                {
-                    newCenterPoint = ( (LIB_ARC*) item )->m_Pos;
-                }
-
-                // Determine if the arc angle is larger than 180 degrees -> this happens if both
-                // points (cursor position, center point) lie on the same side of the vector
-                // start-end
-                int  crossA = CrossProduct( TwoPointVector( arcState.startPoint,
-                                                            arcState.endPoint ),
-                                            TwoPointVector( arcState.endPoint,
-                                                            currentCursorPosition ) );
-                int  crossB = CrossProduct( TwoPointVector( arcState.startPoint,
-                                                            arcState.endPoint ),
-                                            TwoPointVector( arcState.endPoint, newCenterPoint ) );
-
-                bool isLarger180degrees = ( crossA < 0 && crossB < 0 ) ||
-                    ( crossA >= 0 && crossB >= 0 );
-
-                if( isLarger180degrees )
-                    newCenterPoint = ( (LIB_ARC*) item )->m_Pos;
-            }
-
-            if( arcState.selectedPoint == START_POINT || arcState.selectedPoint == END_POINT )
-            {
-                // Compute the new center point when the start/end points are modified
-                wxPoint middlePoint = wxPoint( (arcState.startPoint.x + arcState.endPoint.x) / 2,
-                                               (arcState.startPoint.y + arcState.endPoint.y) / 2 );
-
-                wxPoint startEndVector = TwoPointVector( arcState.startPoint, arcState.endPoint );
-                wxPoint perpendicularVector = wxPoint( -startEndVector.y, startEndVector.x );
-
-                double  lengthPerpendicularVector = EuclideanNorm( perpendicularVector );
-
-                // prevent too large values, division / 0
-                if( lengthPerpendicularVector < 1e-1 )
-                    lengthPerpendicularVector = 1e-1;
-
-                perpendicularVector.x = (int) ( (double) perpendicularVector.x *
-                                                arcState.distanceCenter /
-                                                lengthPerpendicularVector ) * arcState.direction;
-                perpendicularVector.y = (int) ( (double) perpendicularVector.y *
-                                                arcState.distanceCenter /
-                                                lengthPerpendicularVector ) * arcState.direction;
-
-                newCenterPoint = middlePoint + perpendicularVector;
-
-                ( (LIB_ARC*) item )->m_ArcStart = arcState.startPoint;
-                ( (LIB_ARC*) item )->m_ArcEnd   = arcState.endPoint;
-            }
-
-            ( (LIB_ARC*) item )->m_Pos = newCenterPoint;
-            ComputeArcRadiusAngles( (LIB_ARC*) item );
-        }
-        else
-        {
-            if( arcState.stateDrawArc == 1 )
-            {
-                arcState.endPoint.x = currentCursorPosition.x;
-                arcState.endPoint.y = currentCursorPosition.y;
-            }
-
-            if( arcState.stateDrawArc == 2 )
-            {
-                ComputeArc( (LIB_ARC*) item, Screen->m_Curseur );
-            }
-            item->m_Fill = fillStyle;
-        }
-        break;
-
-    case COMPONENT_CIRCLE_DRAW_TYPE:
-        dx = ( (LIB_CIRCLE*) item )->m_Pos.x - currentCursorPosition.x;
-        dy = ( (LIB_CIRCLE*) item )->m_Pos.y - currentCursorPosition.y;
-        ( (LIB_CIRCLE*) item )->m_Radius =
-            (int) sqrt( ( (double) dx * dx ) + ( (double) dy * dy ) );
-        item->m_Fill = fillStyle;
-        break;
-
-    case COMPONENT_RECT_DRAW_TYPE:
-        if( ( (LIB_RECTANGLE*) item )->m_isHeightLocked )
-        {
-            if( ( (LIB_RECTANGLE*) item )->m_isStartPointSelected )
-            {
-                ( (LIB_RECTANGLE*) item )->m_Pos.x = currentCursorPosition.x;
-            }
-            else
-            {
-                ( (LIB_RECTANGLE*) item )->m_End.x = currentCursorPosition.x;
-            }
-        }
-        else if( ( (LIB_RECTANGLE*) item )->m_isWidthLocked )
-        {
-            if( ( (LIB_RECTANGLE*) item )->m_isStartPointSelected )
-            {
-                ( (LIB_RECTANGLE*) item )->m_Pos.y = currentCursorPosition.y;
-            }
-            else
-            {
-                ( (LIB_RECTANGLE*) item )->m_End.y = currentCursorPosition.y;
-            }
-        }
-        else
-        {
-            if( ( (LIB_RECTANGLE*) item )->m_isStartPointSelected )
-            {
-                ( (LIB_RECTANGLE*) item )->m_Pos = currentCursorPosition;
-            }
-            else
-            {
-                ( (LIB_RECTANGLE*) item )->m_End = currentCursorPosition;
-            }
-        }
-
-        item->m_Fill = fillStyle;
-        break;
-
-    case COMPONENT_POLYLINE_DRAW_TYPE:
-    {
-        unsigned idx;
-
-        if( item->m_Flags == IS_RESIZED )
-            idx = ( (LIB_POLYLINE*) item )->m_ModifyIndex;
-        else
-            idx = ( (LIB_POLYLINE*) item )->GetCornerCount() - 1;
-
-        ( (LIB_POLYLINE*) item )->m_PolyPoints[idx] = currentCursorPosition;
-        item->m_Fill = fillStyle;
-    }
-    break;
-
-    case COMPONENT_GRAPHIC_TEXT_DRAW_TYPE:
-        break;
-
-    default:
-        ;
-    }
-
-    if( arcState.stateDrawArc == 1 )
-    {
-        int Color = ReturnLayerColor( LAYER_DEVICE );
-        GRLine( &panel->m_ClipBox, DC, arcState.startPoint.x, -arcState.startPoint.y,
-                arcState.endPoint.x, -arcState.endPoint.y, 0, Color );
-    }
-    else
-    {
-        item->Draw( panel, DC, wxPoint( 0, 0 ), -1, DrawMode, NULL, DefaultTransformMatrix );
-
-        if( item->Type() == COMPONENT_ARC_DRAW_TYPE && item->m_Flags != IS_RESIZED )
-        {
-            int Color = ReturnLayerColor( LAYER_DEVICE );
-            GRDashedLine( &panel->m_ClipBox, DC, arcState.startPoint.x, -arcState.startPoint.y,
-                          ( (LIB_ARC*) item )->m_Pos.x,
-                          -( (LIB_ARC*) item )->m_Pos.y,
-                          0, Color );
-            GRDashedLine( &panel->m_ClipBox, DC, arcState.endPoint.x, -arcState.endPoint.y,
-                          ( (LIB_ARC*) item )->m_Pos.x,
-                          -( (LIB_ARC*) item )->m_Pos.y,
-                          0, Color );
-        }
-    }
+    item->Draw( panel, DC, Screen->GetCursorDrawPosition(), -1, g_XorMode, NULL,
+                DefaultTransform );
 }
 
 
@@ -816,282 +294,24 @@ void WinEDA_LibeditFrame::EndDrawGraphicItem( wxDC* DC )
     if( m_component == NULL || m_drawItem == NULL )
         return;
 
-    if( m_drawItem->Type() == COMPONENT_ARC_DRAW_TYPE )
-    {
-        if( arcState.stateDrawArc == 1 ) /* Trace arc under way must be completed. */
-        {
-            DisplayError( this, wxT( "Arc in progress.." ) );
-            return;
-        }
-        else
-        {
-            if( ( m_drawItem->m_Flags & IS_MOVED ) == 0 )
-                SymbolDisplayDraw( DrawPanel, DC, FALSE );
-        }
-    }
-
-    arcState.stateDrawArc = 0;
-
-    if( m_drawItem->m_Flags & IS_NEW )
-    {
-        SaveCopyInUndoList( m_component );
-        m_component->AddDrawItem( m_drawItem );
-
-        switch( m_drawItem->Type() )
-        {
-        case COMPONENT_ARC_DRAW_TYPE:
-            ( (LIB_ARC*) m_drawItem )->m_Fill = m_drawFillStyle;
-            break;
-
-        case COMPONENT_CIRCLE_DRAW_TYPE:
-            ( (LIB_CIRCLE*) m_drawItem )->m_Fill = m_drawFillStyle;
-            break;
-
-        case COMPONENT_RECT_DRAW_TYPE:
-            ( (LIB_RECTANGLE*) m_drawItem )->m_Fill = m_drawFillStyle;
-            ( (LIB_RECTANGLE*) m_drawItem )->m_isHeightLocked = false;
-            ( (LIB_RECTANGLE*) m_drawItem )->m_isWidthLocked  = false;
-            break;
-
-        case COMPONENT_POLYLINE_DRAW_TYPE:
-            ( (LIB_POLYLINE*) m_drawItem )->m_Fill = m_drawFillStyle;
-            break;
-
-        case COMPONENT_PIN_DRAW_TYPE:
-        case COMPONENT_LINE_DRAW_TYPE:
-        case COMPONENT_GRAPHIC_TEXT_DRAW_TYPE:
-            break;
-
-        default:
-            ;
-        }
-    }
-
     if( m_ID_current_state )
         SetCursor( wxCURSOR_PENCIL );
     else
         SetCursor( wxCURSOR_ARROW );
 
-    if( m_drawItem->m_Flags & IS_MOVED )
-    {
-        wxPoint pos;
-        pos.x = GetScreen()->m_Curseur.x + InitPosition.x - StartCursor.x,
-        pos.y = GetScreen()->m_Curseur.y - InitPosition.y - StartCursor.y;
-        NEGATE( pos.y );
-        m_drawItem->Move( pos );
-    }
+    SaveCopyInUndoList( m_savedComponent );
+    DeleteSavedComponent();
 
-    m_component->Draw( DrawPanel, DC, wxPoint( 0, 0 ), m_unit, m_convert, GR_DEFAULT_DRAWMODE );
+    if( m_drawItem->IsNew() )
+        m_component->AddDrawItem( m_drawItem );
+
+    m_drawItem->EndEdit( GetScreen()->GetCursorDrawPosition() );
 
-    m_drawItem->m_Flags = 0;
     m_drawItem = NULL;
 
-    OnModify( );
+    OnModify();
 
     DrawPanel->ManageCurseur = NULL;
     DrawPanel->ForceCloseManageCurseur = NULL;
-}
-
-
-//! @brief Compute the missing attributes (angles, radius),
-// when the three points (start, end, center) given
-//! @param arc Arc to be modified
-static void ComputeArcRadiusAngles( LIB_ARC* arc )
-{
-    wxPoint centerStartVector = TwoPointVector( arc->m_Pos, arc->m_ArcStart );
-    wxPoint centerEndVector   = TwoPointVector( arc->m_Pos, arc->m_ArcEnd );
-
-    arc->m_Radius = wxRound( EuclideanNorm( centerStartVector ) );
-
-    arc->m_t1 = (int) ( atan2( (double) centerStartVector.y,
-                               (double) centerStartVector.x ) * 1800 / M_PI );
-
-    arc->m_t2 = (int) ( atan2( (double) centerEndVector.y,
-                               (double) centerEndVector.x ) * 1800 / M_PI );
-
-    NORMALIZE_ANGLE( arc->m_t1 );
-    NORMALIZE_ANGLE( arc->m_t2 );  // angles = 0 .. 3600
-
-    // Restrict angle to less than 180 to avoid PBS display mirror
-    // Trace because it is assumed that the arc is less than 180 deg to find
-    // orientation after rotate or mirror.
-    if( (arc->m_t2 - arc->m_t1) > 1800 )
-        arc->m_t2 -= 3600;
-    else if( (arc->m_t2 - arc->m_t1) <= -1800 )
-        arc->m_t2 += 3600;
-
-    wxString msg;
-    int      angle = arc->m_t2 - arc->m_t1;
-    msg.Printf( _( "Arc %.1f deg" ), (float) angle / 10 );
-    WinEDA_SchematicFrame* frame = (WinEDA_SchematicFrame*) wxGetApp().GetTopWindow();
-    frame->m_LibeditFrame->PrintMsg( msg );
-
-    while( (arc->m_t2 - arc->m_t1) >= 1800 )
-    {
-        arc->m_t2--;
-        arc->m_t1++;
-    }
-
-    while( (arc->m_t1 - arc->m_t2) >= 1800 )
-    {
-        arc->m_t2++;
-        arc->m_t1--;
-    }
-
-    NORMALIZE_ANGLE( arc->m_t1 );
-}
-
-
-/*
- * Routine for adjusting the parameters of the arc currently being drawn.
- * Calculates the center, radius, angles for the arc current
- * Passes through the points arcState.startPoint.x, arcState.endPoint.x Y and Y with the
- * nearest center of the mouse position.
- * Note: The center is obviously not on the grid
- */
-static void ComputeArc( LIB_ARC* DrawItem, wxPoint ArcCentre )
-{
-    int dx, dy;
-    int cX, cY;
-    int angle;
-
-    cX = ArcCentre.x;
-    cY = ArcCentre.y;
-
-    cY = -cY;   /* Attention to the orientation of the axis Y. */
-
-    /* Calculating cX and cY for the arc passes through arcState.startPoint.x, arcState.endPoint.x,
-     * X and Y */
-    dx    = arcState.endPoint.x - arcState.startPoint.x;
-    dy    = arcState.endPoint.y - arcState.startPoint.y;
-    cX   -= arcState.startPoint.x;
-    cY   -= arcState.startPoint.y;
-    angle = (int) ( atan2( (double) dy, (double) dx ) * 1800 / M_PI );
-    RotatePoint( &dx, &dy, angle );     /* The segment dx, dy is horizontal
-                                         * -> Length = dx, dy = 0 */
-    RotatePoint( &cX, &cY, angle );
-    cX = dx / 2;           /* cX, cY is on the median segment 0.0 a dx, 0 */
-
-    RotatePoint( &cX, &cY, -angle );
-    cX += arcState.startPoint.x;
-    cY += arcState.startPoint.y;
-    DrawItem->m_Pos.x = cX;
-    DrawItem->m_Pos.y = cY;
-
-    dx = arcState.startPoint.x - DrawItem->m_Pos.x;
-    dy = arcState.startPoint.y - DrawItem->m_Pos.y;
-
-    DrawItem->m_Radius = (int) sqrt( ( (double) dx * dx ) + ( (double) dy * dy ) );
-
-    DrawItem->m_t1 = (int) ( atan2( (double) dy, (double) dx ) * 1800 / M_PI );
-
-    dx = arcState.endPoint.x - DrawItem->m_Pos.x;
-    dy = arcState.endPoint.y - DrawItem->m_Pos.y;
-
-    DrawItem->m_t2 = (int) ( atan2( (double) dy, (double) dx ) * 1800 / M_PI );
-
-    DrawItem->m_ArcStart.x = arcState.startPoint.x;
-    DrawItem->m_ArcStart.y = arcState.startPoint.y;
-    DrawItem->m_ArcEnd.x   = arcState.endPoint.x;
-    DrawItem->m_ArcEnd.y   = arcState.endPoint.y;
-
-    NORMALIZE_ANGLE( DrawItem->m_t1 );
-    NORMALIZE_ANGLE( DrawItem->m_t2 );  // angles = 0 .. 3600
-
-    // Restrict angle to less than 180 to avoid PBS display mirror
-    // Trace because it is assumed that the arc is less than 180 deg to find
-    // orientation after rotate or mirror.
-    if( (DrawItem->m_t2 - DrawItem->m_t1) > 1800 )
-        DrawItem->m_t2 -= 3600;
-    else if( (DrawItem->m_t2 - DrawItem->m_t1) <= -1800 )
-        DrawItem->m_t2 += 3600;
-
-    wxString msg;
-    angle = DrawItem->m_t2 - DrawItem->m_t1;
-    msg.Printf( _( "Arc %.1f deg" ), (float) angle / 10 );
-    WinEDA_SchematicFrame* frame = (WinEDA_SchematicFrame*) wxGetApp().GetTopWindow();
-    frame->m_LibeditFrame->PrintMsg( msg );
-
-    while( (DrawItem->m_t2 - DrawItem->m_t1) >= 1800 )
-    {
-        DrawItem->m_t2--;
-        DrawItem->m_t1++;
-    }
-
-    while( (DrawItem->m_t1 - DrawItem->m_t2) >= 1800 )
-    {
-        DrawItem->m_t2++;
-        DrawItem->m_t1--;
-    }
-
-    NORMALIZE_ANGLE( DrawItem->m_t1 );
-    NORMALIZE_ANGLE( DrawItem->m_t2 );
-}
-
-
-//! @brief Given three points A B C, compute the circumcenter of the resulting triangle
-//! reference: http://en.wikipedia.org/wiki/Circumscribed_circle
-//! Coordinates of circumcenter in Cartesian coordinates
-static wxPoint ComputeCircumCenter( wxPoint A, wxPoint B, wxPoint C )
-{
-    double  circumCenterX, circumCenterY;
-    double  Ax = (double) A.x;
-    double  Ay = (double) A.y;
-    double  Bx = (double) B.x;
-    double  By = (double) B.y;
-    double  Cx = (double) C.x;
-    double  Cy = (double) C.y;
-
-    wxPoint circumCenter;
-
-    double  D = 2.0 * ( Ax * ( By - Cy ) + Bx * ( Cy - Ay ) + Cx * ( Ay - By ) );
-
-    // prevent division / 0
-    if( fabs( D ) < 1e-7 )
-        D = 1e-7;
-
-    circumCenterX = ( (Ay * Ay + Ax * Ax) * (By - Cy) +
-                      (By * By + Bx * Bx) * (Cy - Ay) +
-                      (Cy * Cy + Cx * Cx) * (Ay - By) ) / D;
-
-    circumCenterY = ( (Ay * Ay + Ax * Ax) * (Cx - Bx) +
-                      (By * By + Bx * Bx) * (Ax - Cx) +
-                      (Cy * Cy + Cx * Cx) * (Bx - Ax) ) / D;
-
-    circumCenter.x = (int) circumCenterX;
-    circumCenter.y = (int) circumCenterY;
-
-    return circumCenter;
-}
-
-
-/*
- * Used for deleting last entered segment while creating a Polyline
- */
-void WinEDA_LibeditFrame::DeleteDrawPoly( wxDC* DC )
-{
-    if( m_drawItem == NULL || m_drawItem->Type() != COMPONENT_POLYLINE_DRAW_TYPE )
-        return;
-
-    LIB_POLYLINE* Poly = (LIB_POLYLINE*) m_drawItem;
-
-    m_drawItem->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, g_XorMode, NULL,
-                      DefaultTransformMatrix );
-
-    // First segment is kept, only its end point is changed
-    while( Poly->GetCornerCount() > 2 )
-    {
-        Poly->m_PolyPoints.pop_back();
-        unsigned idx   = Poly->GetCornerCount() - 1;
-        wxPoint  point = GetScreen()->m_Curseur;
-        NEGATE( point.y );
-        if( Poly->m_PolyPoints[idx] != point )
-        {
-            Poly->m_PolyPoints[idx] = point;
-            break;
-        }
-    }
-
-    m_drawItem->Draw( DrawPanel, DC, wxPoint( 0, 0 ), -1, g_XorMode, NULL,
-                      DefaultTransformMatrix );
+    DrawPanel->Refresh();
 }
diff --git a/eeschema/transform.cpp b/eeschema/transform.cpp
new file mode 100644
index 0000000000..3eba67c633
--- /dev/null
+++ b/eeschema/transform.cpp
@@ -0,0 +1,90 @@
+
+#include "macros.h"
+#include "transform.h"
+
+
+TRANSFORM& TRANSFORM::operator=( const TRANSFORM& aTransform )
+{
+    if( this == &aTransform )       // Check for self assingnemt;
+        return *this;
+
+    x1 = aTransform.x1;
+    y1 = aTransform.y1;
+    x2 = aTransform.x2;
+    y2 = aTransform.y2;
+    return *this;
+}
+
+
+bool TRANSFORM::operator==( const TRANSFORM& aTransform ) const
+{
+    return ( x1 == aTransform.x1 &&
+             y1 == aTransform.y1 &&
+             x2 == aTransform.x2 &&
+             y2 == aTransform.y2 );
+}
+
+
+wxPoint TRANSFORM::TransformCoordinate( const wxPoint& aPoint ) const
+{
+    return wxPoint( ( x1 * aPoint.x ) + ( y1 * aPoint.y ),
+                    ( x2 * aPoint.x ) + ( y2 * aPoint.y ) );
+}
+
+
+bool TRANSFORM::MapAngles( int* aAngle1, int* aAngle2 ) const
+{
+    wxCHECK_MSG( aAngle1 != NULL && aAngle2 != NULL, false,
+                 wxT( "Cannot map NULL point angles." ) );
+
+    int    Angle, Delta;
+    double x, y, t;
+    bool   swap = false;
+
+    Delta = *aAngle2 - *aAngle1;
+    if( Delta >= 1800 )
+    {
+        *aAngle1 -= 1;
+        *aAngle2 += 1;
+    }
+
+    x = cos( *aAngle1 * M_PI / 1800.0 );
+    y = sin( *aAngle1 * M_PI / 1800.0 );
+    t = x * x1 + y * y1;
+    y = x * x2 + y * y2;
+    x = t;
+    *aAngle1 = (int) ( atan2( y, x ) * 1800.0 / M_PI + 0.5 );
+
+    x = cos( *aAngle2 * M_PI / 1800.0 );
+    y = sin( *aAngle2 * M_PI / 1800.0 );
+    t = x * x1 + y * y1;
+    y = x * x2 + y * y2;
+    x = t;
+    *aAngle2 = (int) ( atan2( y, x ) * 1800.0 / M_PI + 0.5 );
+
+    NORMALIZE_ANGLE( *aAngle1 );
+    NORMALIZE_ANGLE( *aAngle2 );
+    if( *aAngle2 < *aAngle1 )
+        *aAngle2 += 3600;
+
+    if( *aAngle2 - *aAngle1 > 1800 ) /* Need to swap the two angles. */
+    {
+        Angle   = (*aAngle1);
+        *aAngle1 = (*aAngle2);
+        *aAngle2 = Angle;
+
+        NORMALIZE_ANGLE( *aAngle1 );
+        NORMALIZE_ANGLE( *aAngle2 );
+        if( *aAngle2 < *aAngle1 )
+            *aAngle2 += 3600;
+        swap = true;
+    }
+
+    if( Delta >= 1800 )
+    {
+        *aAngle1 += 1;
+        *aAngle2 -= 1;
+    }
+
+    return swap;
+}
diff --git a/eeschema/transform.h b/eeschema/transform.h
new file mode 100644
index 0000000000..82bfdbf4c3
--- /dev/null
+++ b/eeschema/transform.h
@@ -0,0 +1,78 @@
+
+/*
+ * This program source code file is part of KICAD, a free EDA CAD application.
+ *
+ * Copyright (C) 2007-2010 Wayne Stambaugh <stambaughw@verizon.net>
+ * Copyright (C) 2007 Kicad Developers, see change_log.txt for contributors.
+ *
+ * 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, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+
+#ifndef _TRANSFORM_H_
+#define _TRANSFORM_H_
+
+#include <wx/gdicmn.h>
+
+/**
+ * Class for tranforming drawing coordinates for a wxDC device context.
+ *
+ * This probably should be a base class with all pure methods and a derived class
+ * named WXDC_TRANFORM be created.  Then in the future if some new device context
+ * is used, a new transform could be derived from the base class and all the drawable
+ * objects would have to do is provide overloaded draw methods to use the new transorm.
+ */
+class TRANSFORM
+{
+public:
+    int x1;
+    int y1;
+    int x2;
+    int y2;
+
+    /**
+     * The default construct creates a tranform that draws object is the normal orientation.
+     */
+    TRANSFORM() : x1( 1 ), y1( 0 ), x2( 0 ), y2( -1 ) {}
+
+    TRANSFORM( int x1, int y1, int x2, int y2 ) : x1( x1 ), y1( y1 ), x2( x2 ), y2( y2 ) {}
+
+    TRANSFORM& operator=( const TRANSFORM& aTransform );
+
+    bool operator==( const TRANSFORM& aTransform ) const;
+
+   /**
+    * Calculate new coordinate according to the transform.
+    *
+    * @param aPosition = The position to transform
+    * @return The transformed coordinate.
+    */
+    wxPoint TransformCoordinate( const wxPoint& aPoint ) const;
+
+   /**
+    * Calculate new angles according to the transform.
+    *
+    * @param aAngle1 = The first angle to transform
+    * @param aAngle2 = The second angle to transform
+    * @return True if the angles were swapped during the transform.
+    */
+    bool MapAngles( int* aAngle1, int* aAngle2 ) const;
+};
+
+
+#endif    // _TRANSFORM_H_
diff --git a/include/base_struct.h b/include/base_struct.h
index d7c88c5dec..7410c3fccf 100644
--- a/include/base_struct.h
+++ b/include/base_struct.h
@@ -373,6 +373,9 @@ public:
         m_Status = new_status;
     }
 
+    void SetFlags( int aFlags ) { m_Flags = aFlags; }
+
+    int GetFlags() { return m_Flags; }
 
     /**
      * Function DisplayInfo
diff --git a/include/class_base_screen.h b/include/class_base_screen.h
index e3a72ca69a..3be3e2ab57 100644
--- a/include/class_base_screen.h
+++ b/include/class_base_screen.h
@@ -167,6 +167,16 @@ public:
      */
     wxPoint      CursorRealPosition( const wxPoint& ScreenPos );
 
+    /**
+     * Return the current cursor position in drawing coordinates.
+     *
+     * This call inverts the Y axis coordinated of m_Curseur to correct for the difference
+     * between the wxWidgets GDI and the Kicad drawing coordinates.
+     *
+     * @return - The cursor position in drawing coordinates.
+     */
+    wxPoint      GetCursorDrawPosition() { return wxPoint( m_Curseur.x, -m_Curseur.y ); }
+
     /* general Undo/Redo command control */
 
     /** function ClearUndoORRedoList (virtual).
@@ -180,10 +190,7 @@ public:
      *                     old commands this will empty the list of commands.
      *  Commands are deleted from the older to the last.
      */
-    virtual void ClearUndoORRedoList(
-        UNDO_REDO_CONTAINER& aList,
-        int
-                             aItemCount = -1 ) = 0;
+    virtual void ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount = -1 ) = 0;
 
     /** Function ClearUndoRedoList
      * clear undo and redo list, using ClearUndoORRedoList()
diff --git a/include/macros.h b/include/macros.h
index 63a1e4460e..ead43473dd 100644
--- a/include/macros.h
+++ b/include/macros.h
@@ -5,6 +5,9 @@
 #ifndef MACROS_H
 #define MACROS_H
 
+#include <wx/wx.h>
+
+
 #if wxUSE_UNICODE
 #define CONV_TO_UTF8( wxstring )     ( (const char*) wxConvCurrent->cWX2MB( wxstring ) )
 #define CONV_FROM_UTF8( utf8string ) ( wxConvCurrent->cMB2WC( utf8string ) )