diff --git a/common/legacy_gal/block.cpp b/common/legacy_gal/block.cpp
index d4c3f0f4f9..921d4c3be5 100644
--- a/common/legacy_gal/block.cpp
+++ b/common/legacy_gal/block.cpp
@@ -42,9 +42,11 @@
 BLOCK_SELECTOR::BLOCK_SELECTOR() :
     EDA_RECT()
 {
-    m_state   = STATE_NO_BLOCK; // State (enum BLOCK_STATE_T) of block.
-    m_command = BLOCK_IDLE;     // Type (enum BLOCK_COMMAND_T) of operation.
-    m_color   = BROWN;
+    m_state      = STATE_NO_BLOCK; // State (enum BLOCK_STATE_T) of block.
+    m_command    = BLOCK_IDLE;     // Type (enum BLOCK_COMMAND_T) of operation.
+    m_color      = BROWN;
+    m_appendUndo = false;          // Indicates at least one undo record has been saved and
+                                   // any additional undo records should be appended.
 }
 
 
@@ -97,19 +99,10 @@ void BLOCK_SELECTOR::SetMessageBlock( EDA_DRAW_FRAME* frame )
         msg = _( "Zoom to selection" );
         break;
 
-    case BLOCK_ROTATE:     // Rotate 90 deg
-        msg = _( "Block Rotate" );
-        break;
-
     case BLOCK_FLIP:     // Flip
         msg = _( "Block Flip" );
         break;
 
-    case BLOCK_MIRROR_X:
-    case BLOCK_MIRROR_Y:     // mirror
-        msg = _( "Block Mirror" );
-        break;
-
     case BLOCK_ABORT:
         break;
 
diff --git a/common/legacy_gal/eda_draw_frame.cpp b/common/legacy_gal/eda_draw_frame.cpp
index a71cc4fecc..ceed3354e4 100644
--- a/common/legacy_gal/eda_draw_frame.cpp
+++ b/common/legacy_gal/eda_draw_frame.cpp
@@ -943,11 +943,8 @@ bool EDA_DRAW_FRAME::HandleBlockBegin( wxDC* aDC, EDA_KEY aKey, const wxPoint& a
     case BLOCK_DUPLICATE_AND_INCREMENT: // Duplicate and increment relevant references
     case BLOCK_DELETE:              // Delete
     case BLOCK_COPY:                // Copy
-    case BLOCK_ROTATE:              // Rotate 90 deg
     case BLOCK_FLIP:                // Flip
     case BLOCK_ZOOM:                // Window Zoom
-    case BLOCK_MIRROR_X:
-    case BLOCK_MIRROR_Y:            // mirror
     case BLOCK_PRESELECT_MOVE:      // Move with preselection list
         block->InitData( m_canvas, aPosition );
         break;
diff --git a/common/legacy_wx/block.cpp b/common/legacy_wx/block.cpp
index 9c4847901c..c9bf56c92d 100644
--- a/common/legacy_wx/block.cpp
+++ b/common/legacy_wx/block.cpp
@@ -97,19 +97,10 @@ void BLOCK_SELECTOR::SetMessageBlock( EDA_DRAW_FRAME* frame )
         msg = _( "Zoom to selection" );
         break;
 
-    case BLOCK_ROTATE:     // Rotate 90 deg
-        msg = _( "Block Rotate" );
-        break;
-
     case BLOCK_FLIP:     // Flip
         msg = _( "Block Flip" );
         break;
 
-    case BLOCK_MIRROR_X:
-    case BLOCK_MIRROR_Y:     // mirror
-        msg = _( "Block Mirror" );
-        break;
-
     case BLOCK_ABORT:
         break;
 
diff --git a/common/legacy_wx/eda_draw_frame.cpp b/common/legacy_wx/eda_draw_frame.cpp
index f2e8fa50d6..eed91f5f5e 100644
--- a/common/legacy_wx/eda_draw_frame.cpp
+++ b/common/legacy_wx/eda_draw_frame.cpp
@@ -950,11 +950,8 @@ bool EDA_DRAW_FRAME::HandleBlockBegin( wxDC* aDC, EDA_KEY aKey, const wxPoint& a
     case BLOCK_DUPLICATE_AND_INCREMENT: // Duplicate and increment relevant references
     case BLOCK_DELETE:              // Delete
     case BLOCK_COPY:                // Copy
-    case BLOCK_ROTATE:              // Rotate 90 deg
     case BLOCK_FLIP:                // Flip
     case BLOCK_ZOOM:                // Window Zoom
-    case BLOCK_MIRROR_X:
-    case BLOCK_MIRROR_Y:            // mirror
     case BLOCK_PRESELECT_MOVE:      // Move with preselection list
         block->InitData( m_canvas, aPosition );
         break;
diff --git a/eeschema/block.cpp b/eeschema/block.cpp
index e82c7abba3..09f5696221 100644
--- a/eeschema/block.cpp
+++ b/eeschema/block.cpp
@@ -74,10 +74,6 @@ int SCH_EDIT_FRAME::BlockCommand( EDA_KEY key )
         cmd = BLOCK_DUPLICATE;
         break;
 
-    case GR_KB_ALT:
-        cmd = BLOCK_ROTATE;
-        break;
-
     case GR_KB_CTRL:
         cmd = BLOCK_DRAG;
         break;
@@ -136,19 +132,22 @@ void SCH_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
             return;
         }
 
-        SaveCopyInUndoList( block->GetItems(), UR_CHANGED, false, block->GetMoveVector() );
+        SaveCopyInUndoList( block->GetItems(), UR_CHANGED, block->AppendUndo(), block->GetMoveVector() );
+        block->SetAppendUndo();
         MoveItemsInList( block->GetItems(), block->GetMoveVector() );
         break;
 
     case BLOCK_DUPLICATE:           /* Duplicate */
     case BLOCK_PRESELECT_MOVE:      /* Move with preselection list*/
+    {
         if( m_canvas->IsMouseCaptured() )
             m_canvas->CallMouseCapture( DC, wxDefaultPosition, false );
 
         DuplicateItemsInList( GetScreen(), block->GetItems(), block->GetMoveVector() );
 
-        SaveCopyInUndoList( block->GetItems(),
-                            ( block->GetCommand() == BLOCK_PRESELECT_MOVE ) ? UR_CHANGED : UR_NEW );
+        UNDO_REDO_T operation = block->GetCommand() == BLOCK_PRESELECT_MOVE ? UR_CHANGED : UR_NEW;
+        SaveCopyInUndoList( block->GetItems(), operation, block->AppendUndo() );
+    }
         break;
 
     case BLOCK_PASTE:
@@ -195,7 +194,6 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
 
     auto panel =static_cast<SCH_DRAW_PANEL*>(m_canvas);
     auto view = panel->GetView();
-    auto area = view->GetSelectionArea();
 
     view->ShowSelectionArea( false );
     view->ClearHiddenFlags();
@@ -224,27 +222,6 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
             DisplayError( this, wxT( "Error in HandleBlockPLace()" ) );
             break;
 
-        case BLOCK_ROTATE:
-            GetScreen()->UpdatePickList();
-            DrawAndSizingBlockOutlines( m_canvas, aDC, wxDefaultPosition, false );
-
-            if( block->GetCount() )
-            {
-                // Compute the rotation center and put it on grid:
-                wxPoint rotationPoint = block->Centre();
-                rotationPoint = GetNearestGridPosition( rotationPoint );
-                SetCrossHairPosition( rotationPoint );
-                SaveCopyInUndoList( block->GetItems(), UR_ROTATED, false, rotationPoint );
-                RotateListOfItems( block->GetItems(), rotationPoint );
-                CheckListConnections( block->GetItems(), true );
-                SchematicCleanUp( true );
-                OnModify();
-            }
-
-            block->ClearItemsList();
-            GetScreen()->TestDanglingEnds();
-            break;
-
         case BLOCK_DRAG:
         case BLOCK_DRAG_ITEM:   // Drag from a drag command
         case BLOCK_MOVE:
@@ -333,46 +310,6 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
             zoom_command = true;
             break;
 
-        case BLOCK_MIRROR_X:
-            GetScreen()->UpdatePickList();
-            DrawAndSizingBlockOutlines( m_canvas, aDC, wxDefaultPosition, false );
-
-            if( block->GetCount() )
-            {
-                // Compute the mirror center and put it on grid.
-                wxPoint mirrorPoint = block->Centre();
-                mirrorPoint = GetNearestGridPosition( mirrorPoint );
-                SetCrossHairPosition( mirrorPoint );
-                SaveCopyInUndoList( block->GetItems(), UR_MIRRORED_X, false, mirrorPoint );
-                MirrorX( block->GetItems(), mirrorPoint );
-                SchematicCleanUp( true );
-                OnModify();
-            }
-
-            block->ClearItemsList();
-            GetScreen()->TestDanglingEnds();
-            break;
-
-        case BLOCK_MIRROR_Y:
-            GetScreen()->UpdatePickList();
-            DrawAndSizingBlockOutlines( m_canvas, aDC, wxDefaultPosition, false );
-
-            if( block->GetCount() )
-            {
-                // Compute the mirror center and put it on grid.
-                wxPoint mirrorPoint = block->Centre();
-                mirrorPoint = GetNearestGridPosition( mirrorPoint );
-                SetCrossHairPosition( mirrorPoint );
-                SaveCopyInUndoList( block->GetItems(), UR_MIRRORED_Y, false, mirrorPoint );
-                MirrorY( block->GetItems(), mirrorPoint );
-                SchematicCleanUp( true );
-                OnModify();
-            }
-
-            block->ClearItemsList();
-            GetScreen()->TestDanglingEnds();
-            break;
-
         default:
             break;
         }
@@ -409,14 +346,13 @@ bool SCH_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
 static void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
                                      bool aErase )
 {
-    auto panel =static_cast<SCH_DRAW_PANEL*>(aPanel);
-    auto view = panel->GetView();
+    SCH_DRAW_PANEL*    panel =static_cast<SCH_DRAW_PANEL*>( aPanel );
+    KIGFX::SCH_VIEW*   view = panel->GetView();
+    KIGFX::VIEW_GROUP* preview = view->GetPreview();
 
-    auto preview = view->GetPreview();
-
-    BASE_SCREEN*    screen = aPanel->GetScreen();
-    BLOCK_SELECTOR* block = &screen->m_BlockLocate;
-    SCH_ITEM*       schitem;
+    BASE_SCREEN*       screen = aPanel->GetScreen();
+    BLOCK_SELECTOR*    block = &screen->m_BlockLocate;
+    SCH_ITEM*          schitem;
 
     block->SetMoveVector( panel->GetParent()->GetCrossHairPosition() - block->GetLastCursorPosition() );
 
@@ -426,7 +362,7 @@ static void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wx
     for( unsigned ii = 0; ii < block->GetCount(); ii++ )
     {
         schitem = (SCH_ITEM*) block->GetItem( ii );
-        SCH_ITEM *copy = static_cast<SCH_ITEM*>( schitem->Clone() );
+        SCH_ITEM* copy = static_cast<SCH_ITEM*>( schitem->Clone() );
         copy->Move( block->GetMoveVector() );
         preview->Add( copy );
 
diff --git a/eeschema/hotkeys.cpp b/eeschema/hotkeys.cpp
index edb4b2707f..c248411119 100644
--- a/eeschema/hotkeys.cpp
+++ b/eeschema/hotkeys.cpp
@@ -769,21 +769,13 @@ bool LIB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition,
         break;
 
     case HK_ROTATE:
-        if( blocInProgress )
-        {
-            GetScreen()->m_BlockLocate.SetCommand( BLOCK_ROTATE );
-            HandleBlockPlace( aDC );
-        }
-        else
-        {
-            if ( !itemInEdit )
-                SetDrawItem( LocateItemUsingCursor( aPosition ) );
+        if ( !itemInEdit && !blocInProgress )
+            SetDrawItem( LocateItemUsingCursor( aPosition ) );
 
-            if( GetDrawItem() )
-            {
-                cmd.SetId( ID_LIBEDIT_ROTATE_ITEM );
-                GetEventHandler()->ProcessEvent( cmd );
-            }
+        if( blocInProgress || GetDrawItem() )
+        {
+            cmd.SetId( ID_LIBEDIT_ROTATE_ITEM );
+            OnRotate( cmd );
         }
         break;
 
@@ -847,7 +839,7 @@ bool LIB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition,
         if( blocInProgress || GetDrawItem() )
         {
             cmd.SetId( ID_LIBEDIT_MIRROR_Y );
-            GetEventHandler()->ProcessEvent( cmd );
+            OnOrient( cmd );
         }
         break;
 
@@ -858,7 +850,7 @@ bool LIB_EDIT_FRAME::OnHotKey( wxDC* aDC, int aHotKey, const wxPoint& aPosition,
         if( blocInProgress || GetDrawItem() )
         {
             cmd.SetId( ID_LIBEDIT_MIRROR_X );
-            GetEventHandler()->ProcessEvent( cmd );
+            OnOrient( cmd );
         }
         break;
     }
diff --git a/eeschema/libedit/block_libedit.cpp b/eeschema/libedit/block_libedit.cpp
index 1bc517e078..2f6446899f 100644
--- a/eeschema/libedit/block_libedit.cpp
+++ b/eeschema/libedit/block_libedit.cpp
@@ -273,137 +273,126 @@ bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
     {
         BLOCK_STATE_T state     = block->GetState();
         BLOCK_COMMAND_T command = block->GetCommand();
+
         m_canvas->CallEndMouseCapture( aDC );
+
         block->SetState( state );
         block->SetCommand( command );
         m_canvas->SetMouseCapture( DrawAndSizingBlockOutlines, AbortBlockCurrentCommand );
-        SetCrossHairPosition( wxPoint( block->GetRight(),
-                                       block->GetBottom() ) );
-        m_canvas->MoveCursorToCrossHair();
+        SetCrossHairPosition( wxPoint( block->GetRight(), block->GetBottom() ) );
+
+        if( block->GetCommand() != BLOCK_ABORT )
+            m_canvas->MoveCursorToCrossHair();
     }
 
-    switch( block->GetCommand() )
+    if( m_canvas->IsMouseCaptured() )
     {
-    case  BLOCK_IDLE:
-        DisplayError( this, wxT( "Error in HandleBlockPLace" ) );
-        break;
-
-    case BLOCK_DRAG:        // Drag
-    case BLOCK_DRAG_ITEM:
-    case BLOCK_MOVE:        // Move
-    case BLOCK_DUPLICATE:   // Duplicate
-
-        if( GetCurPart() )
-            ItemCount = BlockSelectItems( GetCurPart(), block, m_unit, m_convert, m_syncPinEdit );
-        
-        if( ItemCount )
+        switch( block->GetCommand() )
         {
-            nextCmd = true;
+        case  BLOCK_IDLE:
+            DisplayError( this, wxT( "Error in HandleBlockPLace" ) );
+            break;
 
-            if( m_canvas->IsMouseCaptured() )
+        case BLOCK_DRAG:        // Drag
+        case BLOCK_DRAG_ITEM:
+        case BLOCK_MOVE:        // Move
+        case BLOCK_DUPLICATE:   // Duplicate
+            if( GetCurPart() )
+                ItemCount = BlockSelectItems( GetCurPart(), block, m_unit, m_convert, m_syncPinEdit );
+
+            if( ItemCount )
             {
+                nextCmd = true;
+                block->SetFlags( IS_MOVED );
+
                 m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false );
                 m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines );
                 m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false );
+                block->SetState( STATE_BLOCK_MOVE );
+            }
+            else
+            {
+                m_canvas->CallMouseCapture( aDC, wxDefaultPosition, false );
+                m_canvas->SetMouseCapture( NULL, NULL );
+            }
+            break;
+
+        case BLOCK_COPY:    // Save a copy of items in the clipboard buffer
+        case BLOCK_CUT:
+            if( GetCurPart() )
+                ItemCount = BlockSelectItems( GetCurPart(), block, m_unit, m_convert, m_syncPinEdit );
+
+            if( ItemCount )
+            {
+                copySelectedItems();
+                auto cmd = block->GetCommand();
+
+                if( cmd == BLOCK_COPY )
+                {
+                    BlockClearSelectedItems( GetCurPart(), block );
+                    block->ClearItemsList();
+                }
+                else if( cmd == BLOCK_CUT )
+                {
+                    if( block->AppendUndo() )
+                        ; // UR_LIBEDIT saves entire state, so no need to append anything more
+                    else
+                    {
+                        SaveCopyInUndoList( GetCurPart(), UR_LIBEDIT );
+                        block->SetAppendUndo();
+                    }
+
+                    BlockDeleteSelectedItems( GetCurPart(), block );
+                    OnModify();
+                }
+            }
+            break;
+
+        case BLOCK_DELETE:     // Delete
+            if( GetCurPart() )
+                ItemCount = BlockSelectItems( GetCurPart(), block, m_unit, m_convert, m_syncPinEdit );
+
+            if( block->AppendUndo() )
+                ; // UR_LIBEDIT saves entire state, so no need to append anything more
+            else if( ItemCount )
+            {
+                SaveCopyInUndoList( GetCurPart(), UR_LIBEDIT );
+                block->SetAppendUndo();
             }
 
-            block->SetState( STATE_BLOCK_MOVE );
-            m_canvas->Refresh( true );
-        }
-        break;
-
-    case BLOCK_PRESELECT_MOVE:     // Move with preselection list
-        nextCmd = true;
-        m_canvas->SetMouseCaptureCallback( DrawMovingBlockOutlines );
-        block->SetState( STATE_BLOCK_MOVE );
-        break;
-
-    case BLOCK_COPY:    // Save a copy of items in the clipboard buffer
-    case BLOCK_CUT:
-        if( GetCurPart() )
-            ItemCount = BlockSelectItems( GetCurPart(), block, m_unit, m_convert, m_syncPinEdit );
-        
-        if( ItemCount )
-        {
-            copySelectedItems();
-            auto cmd = block->GetCommand();
-
-            if( cmd == BLOCK_COPY )
+            if( GetCurPart() )
             {
-                BlockClearSelectedItems( GetCurPart(), block );
-                block->ClearItemsList();
-            }
-            else if( cmd == BLOCK_CUT )
-            {
-                SaveCopyInUndoList( GetCurPart() );
                 BlockDeleteSelectedItems( GetCurPart(), block );
                 OnModify();
             }
+            break;
+
+        case BLOCK_PASTE:
+            wxFAIL; // should not happen
+            break;
+
+        case BLOCK_FLIP:
+            break;
+
+        case BLOCK_ZOOM:     // Window Zoom
+            Window_Zoom( *block );
+            break;
+
+        case BLOCK_ABORT:
+            break;
+
+        case BLOCK_SELECT_ITEMS_ONLY:
+            break;
+
+        case BLOCK_DUPLICATE_AND_INCREMENT: // not used in Eeschema
+        case BLOCK_MOVE_EXACT:              // not used in Eeschema
+            break;
         }
-        break;
+    }
 
-    case BLOCK_DELETE:     // Delete
-        if( GetCurPart() )
-            ItemCount = BlockSelectItems( GetCurPart(), block, m_unit, m_convert, m_syncPinEdit );
-        
-        if( ItemCount )
-            SaveCopyInUndoList( GetCurPart() );
-
-        if( GetCurPart() )
-        {
-            BlockDeleteSelectedItems( GetCurPart(), block );
-            OnModify();
-        }
-        break;
-
-    case BLOCK_PASTE:
-        wxFAIL; // should not happen
-        break;
-
-    case BLOCK_FLIP:
-        break;
-
-    case BLOCK_ROTATE:
-    case BLOCK_MIRROR_X:
-    case BLOCK_MIRROR_Y:
-        if( GetCurPart() )
-            ItemCount = BlockSelectItems( GetCurPart(), block, m_unit, m_convert, m_syncPinEdit );
-        
-        if( ItemCount )
-            SaveCopyInUndoList( GetCurPart() );
-
-        pt = block->Centre();
-        pt = GetNearestGridPosition( pt );
-        pt.y = -pt.y;
-
-        if( GetCurPart() )
-        {
-            OnModify();
-            int block_cmd = block->GetCommand();
-
-            if( block_cmd == BLOCK_MIRROR_Y)
-                BlockMirrorSelectedItemsH( pt, GetCurPart(), block );
-            else if( block_cmd == BLOCK_MIRROR_X)
-                BlockMirrorSelectedItemsV( pt, GetCurPart(), block );
-            else if( block_cmd == BLOCK_ROTATE )
-                BlockRotateSelectedItems( pt, GetCurPart(), block );
-        }
-
-        break;
-
-    case BLOCK_ZOOM:     // Window Zoom
-        Window_Zoom( *block );
-        break;
-
-    case BLOCK_ABORT:
-        break;
-
-    case BLOCK_SELECT_ITEMS_ONLY:
-        break;
-
-    case BLOCK_DUPLICATE_AND_INCREMENT: // not used in Eeschema
-    case BLOCK_MOVE_EXACT:              // not used in Eeschema
-        break;
+    if( block->GetCommand() == BLOCK_ABORT )
+    {
+        GetScreen()->ClearDrawingState();
     }
 
     if( !nextCmd )
@@ -416,7 +405,6 @@ bool LIB_EDIT_FRAME::HandleBlockEnd( wxDC* aDC )
         GetScreen()->SetCurItem( NULL );
         m_canvas->EndMouseCapture( GetToolId(), GetGalCanvas()->GetCurrentCursor(), wxEmptyString,
                                    false );
-        m_canvas->Refresh( true );
     }
 
     view->ShowPreview( false );
@@ -450,7 +438,7 @@ void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
     case BLOCK_PRESELECT_MOVE:      // Move with preselection list
         block->ClearItemsList();
 
-        if( GetCurPart() )
+        if( GetCurPart() && !block->AppendUndo() )
             SaveCopyInUndoList( GetCurPart() );
 
         pt = block->GetMoveVector();
@@ -465,7 +453,7 @@ void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
     case BLOCK_DUPLICATE:           // Duplicate
         block->ClearItemsList();
 
-        if( GetCurPart() )
+        if( GetCurPart() && !block->AppendUndo() )
             SaveCopyInUndoList( GetCurPart() );
 
         pt = block->GetMoveVector();
@@ -488,30 +476,6 @@ void LIB_EDIT_FRAME::HandleBlockPlace( wxDC* DC )
         pasteClipboard( pt );
         break;
 
-    case BLOCK_ROTATE:      // Invert by popup menu, from block move
-    case BLOCK_MIRROR_X:    // Invert by popup menu, from block move
-    case BLOCK_MIRROR_Y:    // Invert by popup menu, from block move
-        if( GetCurPart() )
-            SaveCopyInUndoList( GetCurPart() );
-
-        pt = block->Centre();
-        pt = GetNearestGridPosition( pt );
-        //pt.y = -pt.y;
-
-        if( GetCurPart() )
-        {
-            int block_cmd = block->GetCommand();
-
-            if( block_cmd == BLOCK_MIRROR_Y)
-                 BlockMirrorSelectedItemsH( pt, GetCurPart(), block );
-            else if( block_cmd == BLOCK_MIRROR_X)
-                 BlockMirrorSelectedItemsV( pt, GetCurPart(), block );
-            else if( block_cmd == BLOCK_ROTATE )
-                 BlockRotateSelectedItems( pt, GetCurPart(), block );
-        }
-
-        break;
-
     case BLOCK_ZOOM:        // Handled by HandleBlockEnd
     case BLOCK_DELETE:
     case BLOCK_COPY:
@@ -606,43 +570,34 @@ void LIB_EDIT_FRAME::pasteClipboard( const wxPoint& aOffset )
 void DrawMovingBlockOutlines( EDA_DRAW_PANEL* aPanel, wxDC* aDC, const wxPoint& aPosition,
                               bool aErase )
 {
-    auto panel = static_cast<SCH_DRAW_PANEL*>(aPanel);
-    auto view = panel->GetView();
-    auto preview = view->GetPreview();
+    SCH_DRAW_PANEL*    panel =static_cast<SCH_DRAW_PANEL*>( aPanel );
+    LIB_EDIT_FRAME*    frame = (LIB_EDIT_FRAME*) aPanel->GetParent();
+    KIGFX::SCH_VIEW*   view = panel->GetView();
+    KIGFX::VIEW_GROUP* preview = view->GetPreview();
 
-    BASE_SCREEN* screen = aPanel->GetScreen();
-    BLOCK_SELECTOR* block = &screen->m_BlockLocate;
-
-    LIB_EDIT_FRAME* parent = (LIB_EDIT_FRAME*) aPanel->GetParent();
-    wxASSERT( parent != NULL );
-
-    LIB_PART* component = parent->GetCurPart();
+    BASE_SCREEN*       screen = aPanel->GetScreen();
+    BLOCK_SELECTOR*    block = &screen->m_BlockLocate;
+    LIB_PART*          component = frame->GetCurPart();
 
     if( component == NULL )
         return;
 
-    auto cp =  parent->GetCrossHairPosition( true );
-    auto lcp = block->GetLastCursorPosition();
-
-    printf("cp %d %d\n", cp.x, cp.y);
-    printf("lcp %d %d\n", lcp.x, lcp.y);
-    
-    block->SetMoveVector( cp - lcp );
+    block->SetMoveVector( frame->GetCrossHairPosition( true ) - block->GetLastCursorPosition() );
     
     preview->Clear();
+    view->SetVisible( preview, true );
 
     for( unsigned ii = 0; ii < block->GetCount(); ii++ )
     {
         LIB_ITEM* libItem = (LIB_ITEM*) block->GetItem( ii );
         LIB_ITEM* copy = static_cast<LIB_ITEM*>( libItem->Clone() );
-//        if( copy->Type() != LIB_PIN_T )
-         copy->Move( copy->GetPosition() + block->GetMoveVector() );
-
+        copy->Move( copy->GetPosition() + block->GetMoveVector() );
+        copy->SetFlags( IS_MOVED );
         preview->Add( copy );
-        view->Hide( libItem );
+
+        if( block->GetCommand() != BLOCK_DUPLICATE )
+            view->Hide( libItem );
     }
 
-    view->SetVisible( preview, true );
-    view->Hide( preview, false );
     view->Update( preview );
 }
diff --git a/eeschema/libedit/lib_edit_frame.cpp b/eeschema/libedit/lib_edit_frame.cpp
index a5f3640784..5ad63c9ea6 100644
--- a/eeschema/libedit/lib_edit_frame.cpp
+++ b/eeschema/libedit/lib_edit_frame.cpp
@@ -53,7 +53,7 @@
 #include <widgets/symbol_tree_pane.h>
 #include <widgets/lib_tree.h>
 #include <symbol_lib_table.h>
-
+#include <list_operations.h>
 #include <kicad_device_context.h>
 #include <hotkeys.h>
 #include <eeschema_config.h>
@@ -157,7 +157,7 @@ BEGIN_EVENT_TABLE( LIB_EDIT_FRAME, EDA_DRAW_FRAME )
 
     // Context menu events and commands.
     EVT_MENU( ID_LIBEDIT_EDIT_PIN, LIB_EDIT_FRAME::OnEditPin )
-    EVT_MENU( ID_LIBEDIT_ROTATE_ITEM, LIB_EDIT_FRAME::OnRotateItem )
+    EVT_MENU( ID_LIBEDIT_ROTATE_ITEM, LIB_EDIT_FRAME::OnRotate )
 
     EVT_MENU_RANGE( ID_POPUP_LIBEDIT_PIN_GLOBAL_CHANGE_ITEM,
                     ID_POPUP_LIBEDIT_DELETE_CURRENT_POLY_SEGMENT,
@@ -263,8 +263,7 @@ LIB_EDIT_FRAME::LIB_EDIT_FRAME( KIWAY* aKiway, wxWindow* aParent ) :
                       .Caption( _( "Libraries" ) ).MinSize( 250, -1 ).Resizable() );
     m_auimgr.AddPane( m_drawToolBar, EDA_PANE().VToolbar().Name( "ToolsToolbar" ).Right().Layer(1) );
 
-    m_auimgr.AddPane( m_canvas->GetWindow(),
-                      wxAuiPaneInfo().Name( "DrawFrame" ).CentrePane() );
+    m_auimgr.AddPane( m_canvas->GetWindow(), wxAuiPaneInfo().Name( "DrawFrame" ).CentrePane() );
 
     m_auimgr.Update();
 
@@ -835,25 +834,13 @@ void LIB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
         HandleBlockEnd( nullptr );
         break;
 
-    case ID_POPUP_MIRROR_Y_BLOCK:
-        m_canvas->SetAutoPanRequest( false );
-        block.SetCommand( BLOCK_MIRROR_Y );
-        m_canvas->MoveCursorToCrossHair();
-        HandleBlockPlace( nullptr );
-        break;
-
     case ID_POPUP_MIRROR_X_BLOCK:
-        m_canvas->SetAutoPanRequest( false );
-        block.SetCommand( BLOCK_MIRROR_X );
-        m_canvas->MoveCursorToCrossHair();
-        HandleBlockPlace( nullptr );
+    case ID_POPUP_MIRROR_Y_BLOCK:
+        OnOrient( event );
         break;
 
     case ID_POPUP_ROTATE_BLOCK:
-        m_canvas->SetAutoPanRequest( false );
-        block.SetCommand( BLOCK_ROTATE );
-        m_canvas->MoveCursorToCrossHair();
-        HandleBlockPlace( nullptr );
+        OnRotate( event );
         break;
 
     case ID_POPUP_PLACE_BLOCK:
@@ -882,7 +869,7 @@ void LIB_EDIT_FRAME::Process_Special_Functions( wxCommandEvent& event )
         break;
 
     default:
-        DisplayError( this, "LIB_EDIT_FRAME::Process_Special_Functions error" );
+        wxFAIL_MSG( "LIB_EDIT_FRAME::Process_Special_Functions error" );
         break;
     }
 
@@ -1161,67 +1148,111 @@ void LIB_EDIT_FRAME::OnSelectTool( wxCommandEvent& aEvent )
 }
 
 
-void LIB_EDIT_FRAME::OnRotateItem( wxCommandEvent& aEvent )
+void LIB_EDIT_FRAME::OnRotate( wxCommandEvent& aEvent )
 {
-    LIB_ITEM* item = GetDrawItem();
+    LIB_PART*       part = GetCurPart();
+    BLOCK_SELECTOR& block = GetScreen()->m_BlockLocate;
+    LIB_ITEM*       item = GetDrawItem();
 
-    if( item == NULL )
-        return;
-
-    if( !item->InEditMode() )
+    // Allows block rotate operation on hot key.
+    if( block.GetState() != STATE_NO_BLOCK )
     {
-        LIB_PART*      part = GetCurPart();
+        // Compute the rotation center and put it on grid:
+        wxPoint rotationPoint = block.Centre();
+        rotationPoint = GetNearestGridPosition( rotationPoint );
+        SetCrossHairPosition( rotationPoint );
 
-        SaveCopyInUndoList( part );
-        item->SetUnit( m_unit );
+        if( block.AppendUndo() )
+            ; // UR_LIBEDIT saves entire state, so no need to append anything more
+        else
+        {
+            SaveCopyInUndoList( part, UR_LIBEDIT );
+            block.SetAppendUndo();
+        }
+
+        for( unsigned ii = 0; ii < block.GetCount(); ii++ )
+        {
+            item = dynamic_cast<LIB_ITEM*>( block.GetItem( ii ) );
+            item->Rotate( rotationPoint );
+        }
+
+        GetCanvas()->CallMouseCapture( nullptr, wxDefaultPosition, false );
     }
+    else if( item )
+    {
+        wxPoint rotationPoint = item->GetBoundingBox().Centre();
+        rotationPoint = GetNearestGridPosition( rotationPoint );
+        SetCrossHairPosition( rotationPoint );
 
-    item->Rotate();
-    OnModify();
+        if( !item->InEditMode() )
+            SaveCopyInUndoList( part, UR_LIBEDIT );
 
-    if( !item->InEditMode() )
-        item->ClearFlags();
+        item->Rotate( rotationPoint );
+        OnModify();
 
-    if( GetToolId() == ID_NO_TOOL_SELECTED )
-        m_lastDrawItem = NULL;
+        if( !item->InEditMode() )
+            item->ClearFlags();
+
+        if( GetToolId() == ID_NO_TOOL_SELECTED )
+            m_lastDrawItem = NULL;
+    }
 }
 
 
 void LIB_EDIT_FRAME::OnOrient( wxCommandEvent& aEvent )
 {
-    SCH_SCREEN* screen = GetScreen();
-    BLOCK_SELECTOR& block = screen->m_BlockLocate;
-
-    // Change the current item to a block selection, if there were no items in the block selector
-    if( screen->GetCurItem() && block.GetState() == STATE_NO_BLOCK )
-    {
-        ITEM_PICKER picker( screen->GetCurItem() );
-        block.PushItem( picker );
-        block.SetState( STATE_BLOCK_INIT );
-
-        const wxPoint& cursorPos = GetCrossHairPosition();
-        block.SetLastCursorPosition( cursorPos );
-        block.SetOrigin( cursorPos );
-        block.SetEnd( cursorPos );
-    }
+    LIB_PART*       part = GetCurPart();
+    BLOCK_SELECTOR& block = GetScreen()->m_BlockLocate;
+    LIB_ITEM*       item = GetDrawItem();
 
     // Allows block rotate operation on hot key.
     if( block.GetState() != STATE_NO_BLOCK )
     {
-        if( aEvent.GetId() == ID_LIBEDIT_MIRROR_X )
+        // Compute the mirror center and put it on grid.
+        wxPoint mirrorPoint = block.Centre();
+        mirrorPoint = GetNearestGridPosition( mirrorPoint );
+        SetCrossHairPosition( mirrorPoint );
+
+        if( block.AppendUndo() )
+            ; // UR_LIBEDIT saves entire state, so no need to append anything more
+        else
         {
-            m_canvas->MoveCursorToCrossHair();
-            block.SetMessageBlock( this );
-            block.SetCommand( BLOCK_MIRROR_X );
-            HandleBlockEnd( nullptr );
+            SaveCopyInUndoList( part, UR_LIBEDIT );
+            block.SetAppendUndo();
         }
-        else if( aEvent.GetId() == ID_LIBEDIT_MIRROR_Y )
+
+        for( unsigned ii = 0; ii < block.GetCount(); ii++ )
         {
-            m_canvas->MoveCursorToCrossHair();
-            block.SetMessageBlock( this );
-            block.SetCommand( BLOCK_MIRROR_Y );
-            HandleBlockEnd( nullptr );
+            item = dynamic_cast<LIB_ITEM*>( block.GetItem( ii ) );
+
+            if( aEvent.GetId() == ID_LIBEDIT_MIRROR_X || aEvent.GetId() == ID_POPUP_MIRROR_X_BLOCK )
+                item->MirrorHorizontal( mirrorPoint );
+            else
+                item->MirrorVertical( mirrorPoint );
         }
+
+        m_canvas->CallMouseCapture( nullptr, wxDefaultPosition, false );
+    }
+    else if( item )
+    {
+        wxPoint mirrorPoint = item->GetBoundingBox().Centre();
+        mirrorPoint = GetNearestGridPosition( mirrorPoint );
+        SetCrossHairPosition( mirrorPoint );
+
+        if( !item->InEditMode() )
+            SaveCopyInUndoList( part, UR_LIBEDIT );
+
+        if( aEvent.GetId() == ID_LIBEDIT_MIRROR_X || aEvent.GetId() == ID_POPUP_MIRROR_X_BLOCK )
+            item->MirrorHorizontal( mirrorPoint );
+        else
+            item->MirrorVertical( mirrorPoint );
+        OnModify();
+
+        if( !item->InEditMode() )
+            item->ClearFlags();
+
+        if( GetToolId() == ID_NO_TOOL_SELECTED )
+            m_lastDrawItem = NULL;
     }
 }
 
diff --git a/eeschema/libedit/lib_edit_frame.h b/eeschema/libedit/lib_edit_frame.h
index 615622477a..039247a8e3 100644
--- a/eeschema/libedit/lib_edit_frame.h
+++ b/eeschema/libedit/lib_edit_frame.h
@@ -528,7 +528,7 @@ private:
     /**
      * Rotates the current item.
      */
-    void OnRotateItem( wxCommandEvent& aEvent );
+    void OnRotate( wxCommandEvent& aEvent );
 
     /**
      * Handles the ID_LIBEDIT_MIRROR_X and ID_LIBEDIT_MIRROR_Y events.
diff --git a/eeschema/operations_on_items_lists.cpp b/eeschema/operations_on_items_lists.cpp
index e79fed0d5a..9af95ad97b 100644
--- a/eeschema/operations_on_items_lists.cpp
+++ b/eeschema/operations_on_items_lists.cpp
@@ -76,7 +76,7 @@ void RotateListOfItems( PICKED_ITEMS_LIST& aItemsList, const wxPoint& rotationPo
 {
     for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
     {
-        SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii );
+        SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItemsList.GetPickedItem( ii ) );
         item->Rotate( rotationPoint );      // Place it in its new position.
         item->ClearFlags();
     }
@@ -87,7 +87,7 @@ void MirrorY( PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMirrorPoint )
 {
     for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
     {
-        SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii );
+        SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItemsList.GetPickedItem( ii ) );
         item->MirrorY( aMirrorPoint.x );      // Place it in its new position.
         item->ClearFlags();
     }
@@ -98,7 +98,7 @@ void MirrorX( PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMirrorPoint )
 {
     for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
     {
-        SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii );
+        SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItemsList.GetPickedItem( ii ) );
         item->MirrorX( aMirrorPoint.y );      // Place it in its new position.
         item->ClearFlags();
     }
@@ -109,7 +109,7 @@ void MoveItemsInList( PICKED_ITEMS_LIST& aItemsList, const wxPoint& aMoveVector
 {
     for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
     {
-        SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii );
+        SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItemsList.GetPickedItem( ii ) );
         item->Move( aMoveVector );
     }
 }
@@ -123,7 +123,7 @@ void SCH_EDIT_FRAME::CheckListConnections( PICKED_ITEMS_LIST& aItemsList, bool a
     GetSchematicConnections( connections );
     for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
     {
-        SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii );
+        SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItemsList.GetPickedItem( ii ) );
         std::vector< wxPoint > new_pts;
 
         if( !item->IsConnectable() )
@@ -175,7 +175,7 @@ void SCH_EDIT_FRAME::DeleteItemsInList( PICKED_ITEMS_LIST& aItemsList, bool aApp
 {
     for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
     {
-        SCH_ITEM* item = (SCH_ITEM*) aItemsList.GetPickedItem( ii );
+        SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( aItemsList.GetPickedItem( ii ) );
 
         if( item->GetFlags() & STRUCT_DELETED )
             continue;
@@ -246,7 +246,7 @@ void SCH_EDIT_FRAME::DuplicateItemsInList( SCH_SCREEN* screen, PICKED_ITEMS_LIST
 
     for( unsigned ii = 0; ii < aItemsList.GetCount(); ii++ )
     {
-        newitem = DuplicateStruct( (SCH_ITEM*) aItemsList.GetPickedItem( ii ) );
+        newitem = DuplicateStruct( dynamic_cast<SCH_ITEM*>( aItemsList.GetPickedItem( ii ) ) );
         aItemsList.SetPickedItem( newitem, ii );
         aItemsList.SetPickedItemStatus( UR_NEW, ii );
         {
diff --git a/eeschema/sch_base_frame.cpp b/eeschema/sch_base_frame.cpp
index 930e51bcca..d118d5f313 100644
--- a/eeschema/sch_base_frame.cpp
+++ b/eeschema/sch_base_frame.cpp
@@ -486,7 +486,6 @@ bool SCH_BASE_FRAME::HandleBlockBegin( wxDC* aDC, EDA_KEY aKey, const wxPoint& a
     case BLOCK_DUPLICATE_AND_INCREMENT: // Duplicate and increment relevant references
     case BLOCK_DELETE:              // Delete
     case BLOCK_COPY:                // Copy
-    case BLOCK_ROTATE:              // Rotate 90 deg
     case BLOCK_FLIP:                // Flip
     case BLOCK_ZOOM:                // Window Zoom
     case BLOCK_MIRROR_X:
diff --git a/eeschema/sch_painter.cpp b/eeschema/sch_painter.cpp
index 2334564569..9ad02240a7 100644
--- a/eeschema/sch_painter.cpp
+++ b/eeschema/sch_painter.cpp
@@ -516,6 +516,9 @@ void SCH_PAINTER::draw( LIB_PIN *aPin, int aLayer, bool isDangling, bool isMovin
     if( !isUnitAndConversionShown( aPin ) )
         return;
 
+    if( aPin->IsMoving() )
+        isMoving = true;
+
     COLOR4D color = m_schSettings.GetLayerColor( LAYER_PIN );
 
     if( !aPin->IsVisible() )
@@ -718,6 +721,11 @@ void SCH_PAINTER::draw( LIB_PIN *aPin, int aLayer, bool isDangling, bool isMovin
         for( COLOR4D& c : colour )
             c = m_schSettings.GetLayerColor( LAYER_HIDDEN );
     }
+    else if( isMoving )
+    {
+        for( COLOR4D& c : colour )
+            c = selectedBrightening( c );
+    }
 
     int insideOffset = textOffset;
     int outsideOffset = 10;
diff --git a/eeschema/schedit.cpp b/eeschema/schedit.cpp
index 3e7c9ff558..55e249ebef 100644
--- a/eeschema/schedit.cpp
+++ b/eeschema/schedit.cpp
@@ -839,20 +839,22 @@ void SCH_EDIT_FRAME::SelectAllFromSheet( wxCommandEvent& aEvent )
 
 void SCH_EDIT_FRAME::OnRotate( wxCommandEvent& aEvent )
 {
-    SCH_SCREEN* screen = GetScreen();
-    SCH_ITEM*   item = screen->GetCurItem();
+    SCH_SCREEN*     screen = GetScreen();
+    SCH_ITEM*       item = screen->GetCurItem();
+    BLOCK_SELECTOR& block = screen->m_BlockLocate;
 
     // Allows block rotate operation on hot key.
-    if( screen->m_BlockLocate.GetState() != STATE_NO_BLOCK )
+    if( block.GetState() != STATE_NO_BLOCK )
     {
         // Compute the rotation center and put it on grid:
-        wxPoint rotationPoint = screen->m_BlockLocate.Centre();
+        wxPoint rotationPoint = block.Centre();
         rotationPoint = GetNearestGridPosition( rotationPoint );
         SetCrossHairPosition( rotationPoint );
 
-        SaveCopyInUndoList( screen->m_BlockLocate.GetItems(), UR_ROTATED, false, rotationPoint );
-        RotateListOfItems( screen->m_BlockLocate.GetItems(), rotationPoint );
-        
+        SaveCopyInUndoList( block.GetItems(), UR_ROTATED, block.AppendUndo(), rotationPoint );
+        block.SetAppendUndo();
+        RotateListOfItems( block.GetItems(), rotationPoint );
+
         m_canvas->CallMouseCapture( nullptr, wxDefaultPosition, false );
         return;
     }
@@ -1162,8 +1164,6 @@ void SCH_EDIT_FRAME::OnDragItem( wxCommandEvent& aEvent )
 
         if( screen->m_BlockLocate.GetState() == STATE_NO_BLOCK )
         {
-//            INSTALL_UNBUFFERED_DC( dc, m_canvas );
-//
             if( !HandleBlockBegin( nullptr, dragType, GetCrossHairPosition() ) )
                 break;
 
@@ -1183,27 +1183,40 @@ void SCH_EDIT_FRAME::OnDragItem( wxCommandEvent& aEvent )
 
 void SCH_EDIT_FRAME::OnOrient( wxCommandEvent& aEvent )
 {
-    SCH_SCREEN* screen = GetScreen();
-    SCH_ITEM*   item   = screen->GetCurItem();
-
-//    INSTALL_UNBUFFERED_DC( dc, m_canvas );
+    SCH_SCREEN* screen    = GetScreen();
+    SCH_ITEM*   item      = screen->GetCurItem();
+    BLOCK_SELECTOR& block = screen->m_BlockLocate;
 
     // Allows block rotate operation on hot key.
-    if( screen->m_BlockLocate.GetState() != STATE_NO_BLOCK )
+    if( block.GetState() != STATE_NO_BLOCK )
     {
         if( aEvent.GetId() == ID_SCH_MIRROR_X )
         {
-            m_canvas->MoveCursorToCrossHair();
-            screen->m_BlockLocate.SetMessageBlock( this );
-            screen->m_BlockLocate.SetCommand( BLOCK_MIRROR_X );
-            HandleBlockEnd( nullptr );
+            // Compute the mirror center and put it on grid.
+            wxPoint mirrorPoint = block.Centre();
+            mirrorPoint = GetNearestGridPosition( mirrorPoint );
+            SetCrossHairPosition( mirrorPoint );
+
+            SaveCopyInUndoList( block.GetItems(), UR_MIRRORED_X, block.AppendUndo(), mirrorPoint );
+            block.SetAppendUndo();
+            MirrorX( block.GetItems(), mirrorPoint );
+
+            m_canvas->CallMouseCapture( nullptr, wxDefaultPosition, false );
+            return;
         }
         else if( aEvent.GetId() == ID_SCH_MIRROR_Y )
         {
-            m_canvas->MoveCursorToCrossHair();
-            screen->m_BlockLocate.SetMessageBlock( this );
-            screen->m_BlockLocate.SetCommand( BLOCK_MIRROR_Y );
-            HandleBlockEnd( nullptr );
+            // Compute the mirror center and put it on grid.
+            wxPoint mirrorPoint = block.Centre();
+            mirrorPoint = GetNearestGridPosition( mirrorPoint );
+            SetCrossHairPosition( mirrorPoint );
+
+            SaveCopyInUndoList( block.GetItems(), UR_MIRRORED_Y, block.AppendUndo(), mirrorPoint );
+            block.SetAppendUndo();
+            MirrorY( block.GetItems(), mirrorPoint );
+
+            m_canvas->CallMouseCapture( nullptr, wxDefaultPosition, false );
+            return;
         }
         else
         {
diff --git a/include/block_commande.h b/include/block_commande.h
index f13fb0f0ef..363e1ddd4e 100644
--- a/include/block_commande.h
+++ b/include/block_commande.h
@@ -82,6 +82,9 @@ class BLOCK_SELECTOR : public EDA_RECT
     wxPoint           m_lastCursorPosition;       //< Last Mouse position in block command
                                                   //< last cursor position in move commands
                                                   //< 0,0 in paste command.
+    bool              m_appendUndo;               //< indicates that at least one undo record
+                                                  //< has been saved and further undo records
+                                                  //< should be appended
 
 public:
     BLOCK_SELECTOR();
@@ -99,6 +102,10 @@ public:
 
     COLOR4D GetColor() const { return m_color; }
 
+    bool AppendUndo() const { return m_appendUndo; }
+
+    void SetAppendUndo() { m_appendUndo = true; }
+
     /**
      * Function SetLastCursorPosition
      * sets the last cursor position to \a aPosition.
diff --git a/pcbnew/block.cpp b/pcbnew/block.cpp
index b73e6c6c00..ed417861f4 100644
--- a/pcbnew/block.cpp
+++ b/pcbnew/block.cpp
@@ -588,6 +588,8 @@ void PCB_EDIT_FRAME::Block_Delete()
 
 void PCB_EDIT_FRAME::Block_Rotate()
 {
+    // 6.0 TODO: This is the legacy toolset version
+
     wxPoint centre;                     // rotation cent-re for the rotation transform
     int     rotAngle = m_rotationAngle; // rotation angle in 0.1 deg.