]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/grid.cpp
Fixes #10288: wxDataViewCtrl missing selection change event
[wxWidgets.git] / src / generic / grid.cpp
index 41fe1d6fc9ee6eebe486269ffca27033d7d05aa3..1b1ed6c60440501cf60210d6814030b51479323e 100644 (file)
 #include "wx/spinctrl.h"
 #include "wx/tokenzr.h"
 #include "wx/renderer.h"
+#include "wx/headerctrl.h"
 
 #include "wx/generic/gridsel.h"
 
-const wxChar wxGridNameStr[] = wxT("grid");
+const char wxGridNameStr[] = "grid";
 
 #if defined(__WXMOTIF__)
     #define WXUNUSED_MOTIF(identifier)  WXUNUSED(identifier)
@@ -145,6 +146,7 @@ DEFINE_EVENT_TYPE(wxEVT_GRID_LABEL_RIGHT_DCLICK)
 DEFINE_EVENT_TYPE(wxEVT_GRID_ROW_SIZE)
 DEFINE_EVENT_TYPE(wxEVT_GRID_COL_SIZE)
 DEFINE_EVENT_TYPE(wxEVT_GRID_COL_MOVE)
+DEFINE_EVENT_TYPE(wxEVT_GRID_COL_SORT)
 DEFINE_EVENT_TYPE(wxEVT_GRID_RANGE_SELECT)
 DEFINE_EVENT_TYPE(wxEVT_GRID_CELL_CHANGE)
 DEFINE_EVENT_TYPE(wxEVT_GRID_SELECT_CELL)
@@ -156,18 +158,195 @@ DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_CREATED)
 // private classes
 // ----------------------------------------------------------------------------
 
+// header column providing access to the column information stored in wxGrid
+// via wxHeaderColumn interface
+class wxGridHeaderColumn : public wxHeaderColumn
+{
+public:
+    wxGridHeaderColumn(wxGrid *grid, int col)
+        : m_grid(grid),
+          m_col(col)
+    {
+    }
+
+    virtual wxString GetTitle() const { return m_grid->GetColLabelValue(m_col); }
+    virtual wxBitmap GetBitmap() const { return wxNullBitmap; }
+    virtual int GetWidth() const { return m_grid->GetColSize(m_col); }
+    virtual int GetMinWidth() const { return 0; }
+    virtual wxAlignment GetAlignment() const
+    {
+        int horz,
+            vert;
+        m_grid->GetColLabelAlignment(&horz, &vert);
+
+        return static_cast<wxAlignment>(horz);
+    }
+
+    virtual int GetFlags() const
+    {
+        // we can't know in advance whether we can sort by this column or not
+        // with wxGrid API so suppose we can by default
+        int flags = wxCOL_SORTABLE;
+        if ( m_grid->CanDragColSize() )
+            flags |= wxCOL_RESIZABLE;
+        if ( m_grid->CanDragColMove() )
+            flags |= wxCOL_REORDERABLE;
+        if ( GetWidth() == 0 )
+            flags |= wxCOL_HIDDEN;
+
+        return flags;
+    }
+
+    virtual bool IsSortKey() const
+    {
+        return m_grid->IsSortingBy(m_col);
+    }
+
+    virtual bool IsSortOrderAscending() const
+    {
+        return m_grid->IsSortOrderAscending();
+    }
+
+private:
+    // these really should be const but are not because the column needs to be
+    // assignable to be used in a wxVector (in STL build, in non-STL build we
+    // avoid the need for this)
+    wxGrid *m_grid;
+    int m_col;
+};
+
+// header control retreiving column information from the grid
+class wxGridHeaderCtrl : public wxHeaderCtrl
+{
+public:
+    wxGridHeaderCtrl(wxGrid *owner)
+        : wxHeaderCtrl(owner,
+                       wxID_ANY,
+                       wxDefaultPosition,
+                       wxDefaultSize,
+                       wxHD_ALLOW_HIDE |
+                       (owner->CanDragColMove() ? wxHD_ALLOW_REORDER : 0))
+    {
+    }
+
+protected:
+    virtual const wxHeaderColumn& GetColumn(unsigned int idx) const
+    {
+        return m_columns[idx];
+    }
+
+private:
+    wxGrid *GetOwner() const { return static_cast<wxGrid *>(GetParent()); }
+
+    // override the base class method to update our m_columns array
+    virtual void OnColumnCountChanging(unsigned int count)
+    {
+        const unsigned countOld = m_columns.size();
+        if ( count < countOld )
+        {
+            // just discard the columns which don't exist any more (notice that
+            // we can't use resize() here as it would require the vector
+            // value_type, i.e. wxGridHeaderColumn to be default constructible,
+            // which it is not)
+            m_columns.erase(m_columns.begin() + count, m_columns.end());
+        }
+        else // new columns added
+        {
+            // add columns for the new elements
+            for ( unsigned n = countOld; n < count; n++ )
+                m_columns.push_back(wxGridHeaderColumn(GetOwner(), n));
+        }
+    }
+
+    // override to implement column auto sizing
+    virtual bool UpdateColumnWidthToFit(unsigned int idx, int widthTitle)
+    {
+        // TODO: currently grid doesn't support computing the column best width
+        //       from its contents so we just use the best label width as is
+        GetOwner()->SetColSize(idx, widthTitle);
+
+        return true;
+    }
+
+    // overridden to react to the actions using the columns popup menu
+    virtual void UpdateColumnVisibility(unsigned int idx, bool show)
+    {
+        GetOwner()->SetColSize(idx, show ? wxGRID_AUTOSIZE : 0);
+
+        // as this is done by the user we should notify the main program about
+        // it
+        GetOwner()->SendEvent(wxEVT_GRID_COL_SIZE, -1, idx);
+    }
+
+    // overridden to react to the columns order changes in the customization
+    // dialog
+    virtual void UpdateColumnsOrder(const wxArrayInt& order)
+    {
+        GetOwner()->SetColumnsOrder(order);
+    }
+
+
+    // event handlers forwarding wxHeaderCtrl events to wxGrid
+    void OnClick(wxHeaderCtrlEvent& event)
+    {
+        GetOwner()->DoColHeaderClick(event.GetColumn());
+    }
+
+    void OnBeginResize(wxHeaderCtrlEvent& event)
+    {
+        GetOwner()->DoStartResizeCol(event.GetColumn());
+
+        event.Skip();
+    }
+
+    void OnResizing(wxHeaderCtrlEvent& event)
+    {
+        GetOwner()->DoUpdateResizeColWidth(event.GetWidth());
+    }
+
+    void OnEndResize(wxHeaderCtrlEvent& event)
+    {
+        GetOwner()->DoEndDragResizeCol();
+
+        event.Skip();
+    }
+
+    void OnBeginReorder(wxHeaderCtrlEvent& event)
+    {
+        GetOwner()->DoStartMoveCol(event.GetColumn());
+    }
+
+    void OnEndReorder(wxHeaderCtrlEvent& event)
+    {
+        GetOwner()->DoEndMoveCol(event.GetNewOrder());
+    }
+
+    wxVector<wxGridHeaderColumn> m_columns;
+
+    DECLARE_EVENT_TABLE()
+    DECLARE_NO_COPY_CLASS(wxGridHeaderCtrl)
+};
+
+BEGIN_EVENT_TABLE(wxGridHeaderCtrl, wxHeaderCtrl)
+    EVT_HEADER_CLICK(wxID_ANY, wxGridHeaderCtrl::OnClick)
+
+    EVT_HEADER_BEGIN_RESIZE(wxID_ANY, wxGridHeaderCtrl::OnBeginResize)
+    EVT_HEADER_RESIZING(wxID_ANY, wxGridHeaderCtrl::OnResizing)
+    EVT_HEADER_END_RESIZE(wxID_ANY, wxGridHeaderCtrl::OnEndResize)
+
+    EVT_HEADER_BEGIN_REORDER(wxID_ANY, wxGridHeaderCtrl::OnBeginReorder)
+    EVT_HEADER_END_REORDER(wxID_ANY, wxGridHeaderCtrl::OnEndReorder)
+END_EVENT_TABLE()
+
 // common base class for various grid subwindows
 class WXDLLIMPEXP_ADV wxGridSubwindow : public wxWindow
 {
 public:
-    wxGridSubwindow() { m_owner = NULL; }
     wxGridSubwindow(wxGrid *owner,
-                    wxWindowID id,
-                    const wxPoint& pos,
-                    const wxSize& size,
                     int additionalStyle = 0,
                     const wxString& name = wxPanelNameStr)
-        : wxWindow(owner, id, pos, size,
+        : wxWindow(owner, wxID_ANY,
+                   wxDefaultPosition, wxDefaultSize,
                    wxBORDER_NONE | additionalStyle,
                    name)
     {
@@ -190,16 +369,17 @@ protected:
 class WXDLLIMPEXP_ADV wxGridRowLabelWindow : public wxGridSubwindow
 {
 public:
-    wxGridRowLabelWindow() { }
-    wxGridRowLabelWindow( wxGrid *parent, wxWindowID id,
-                          const wxPoint &pos, const wxSize &size );
+    wxGridRowLabelWindow(wxGrid *parent)
+      : wxGridSubwindow(parent)
+    {
+    }
+
 
 private:
     void OnPaint( wxPaintEvent& event );
     void OnMouseEvent( wxMouseEvent& event );
     void OnMouseWheel( wxMouseEvent& event );
 
-    DECLARE_DYNAMIC_CLASS(wxGridRowLabelWindow)
     DECLARE_EVENT_TABLE()
     DECLARE_NO_COPY_CLASS(wxGridRowLabelWindow)
 };
@@ -208,16 +388,17 @@ private:
 class WXDLLIMPEXP_ADV wxGridColLabelWindow : public wxGridSubwindow
 {
 public:
-    wxGridColLabelWindow() { }
-    wxGridColLabelWindow( wxGrid *parent, wxWindowID id,
-                          const wxPoint &pos, const wxSize &size );
+    wxGridColLabelWindow(wxGrid *parent)
+        : wxGridSubwindow(parent)
+    {
+    }
+
 
 private:
     void OnPaint( wxPaintEvent& event );
     void OnMouseEvent( wxMouseEvent& event );
     void OnMouseWheel( wxMouseEvent& event );
 
-    DECLARE_DYNAMIC_CLASS(wxGridColLabelWindow)
     DECLARE_EVENT_TABLE()
     DECLARE_NO_COPY_CLASS(wxGridColLabelWindow)
 };
@@ -226,16 +407,16 @@ private:
 class WXDLLIMPEXP_ADV wxGridCornerLabelWindow : public wxGridSubwindow
 {
 public:
-    wxGridCornerLabelWindow() { }
-    wxGridCornerLabelWindow( wxGrid *parent, wxWindowID id,
-                             const wxPoint &pos, const wxSize &size );
+    wxGridCornerLabelWindow(wxGrid *parent)
+        : wxGridSubwindow(parent)
+    {
+    }
 
 private:
     void OnMouseEvent( wxMouseEvent& event );
     void OnMouseWheel( wxMouseEvent& event );
     void OnPaint( wxPaintEvent& event );
 
-    DECLARE_DYNAMIC_CLASS(wxGridCornerLabelWindow)
     DECLARE_EVENT_TABLE()
     DECLARE_NO_COPY_CLASS(wxGridCornerLabelWindow)
 };
@@ -243,25 +424,19 @@ private:
 class WXDLLIMPEXP_ADV wxGridWindow : public wxGridSubwindow
 {
 public:
-    wxGridWindow()
+    wxGridWindow(wxGrid *parent)
+        : wxGridSubwindow(parent,
+                          wxWANTS_CHARS | wxCLIP_CHILDREN,
+                          "GridWindow")
     {
-        m_rowLabelWin = NULL;
-        m_colLabelWin = NULL;
     }
 
-    wxGridWindow( wxGrid *parent,
-                  wxGridRowLabelWindow *rowLblWin,
-                  wxGridColLabelWindow *colLblWin,
-                  wxWindowID id, const wxPoint &pos, const wxSize &size );
 
-    void ScrollWindow( int dx, int dy, const wxRect *rect );
+    virtual void ScrollWindow( int dx, int dy, const wxRect *rect );
 
     virtual bool AcceptsFocus() const { return true; }
 
 private:
-    wxGridRowLabelWindow     *m_rowLabelWin;
-    wxGridColLabelWindow     *m_colLabelWin;
-
     void OnPaint( wxPaintEvent &event );
     void OnMouseWheel( wxMouseEvent& event );
     void OnMouseEvent( wxMouseEvent& event );
@@ -271,7 +446,6 @@ private:
     void OnEraseBackground( wxEraseEvent& );
     void OnFocus( wxFocusEvent& );
 
-    DECLARE_DYNAMIC_CLASS(wxGridWindow)
     DECLARE_EVENT_TABLE()
     DECLARE_NO_COPY_CLASS(wxGridWindow)
 };
@@ -471,13 +645,22 @@ public:
 
 
     // Draws a line parallel to the row or column, i.e. horizontal or vertical:
-    // pos is the vertical or horizontal position of the line and start and end
+    // pos is the horizontal or vertical position of the line and start and end
     // are the coordinates of the line extremities in the other direction
     virtual void
         DrawParallelLine(wxDC& dc, int start, int end, int pos) const = 0;
 
+    // Draw a horizontal or vertical line across the given rectangle
+    // (this is implemented in terms of above and uses Select() to extract
+    // start and end from the given rectangle)
+    void DrawParallelLineInRect(wxDC& dc, const wxRect& rect, int pos) const
+    {
+        const int posStart = Select(rect.GetPosition());
+        DrawParallelLine(dc, posStart, posStart + Select(rect.GetSize()), pos);
+    }
+
 
-    // Return the row or column at the given pixel coordinate.
+    // Return the index of the row or column at the given pixel coordinate.
     virtual int
         PosToLine(const wxGrid *grid, int pos, bool clip = false) const = 0;
 
@@ -785,13 +968,22 @@ private:
 wxGridCellCoords wxGridNoCellCoords( -1, -1 );
 wxRect wxGridNoCellRect( -1, -1, -1, -1 );
 
+namespace
+{
+
 // scroll line size
-static const size_t GRID_SCROLL_LINE_X = 15;
-static const size_t GRID_SCROLL_LINE_Y = GRID_SCROLL_LINE_X;
+const size_t GRID_SCROLL_LINE_X = 15;
+const size_t GRID_SCROLL_LINE_Y = GRID_SCROLL_LINE_X;
 
 // the size of hash tables used a bit everywhere (the max number of elements
 // in these hash tables is the number of rows/columns)
-static const int GRID_HASH_SIZE = 100;
+const int GRID_HASH_SIZE = 100;
+
+// the minimal distance in pixels the mouse needs to move to start a drag
+// operation
+const int DRAG_SENSITIVITY = 3;
+
+} // anonymous namespace
 
 // ----------------------------------------------------------------------------
 // private helpers
@@ -947,32 +1139,19 @@ bool wxGridCellEditor::IsAcceptedKey(wxKeyEvent& event)
     if ((ctrl || alt) && !(ctrl && alt))
         return false;
 
-    int key = 0;
-    bool keyOk = true;
-
-#ifdef __WXGTK20__
-    // If it's a F-Key or other special key then it shouldn't start the
-    // editor.
-    if (event.GetKeyCode() >= WXK_START)
-        return false;
-#endif
 #if wxUSE_UNICODE
     // if the unicode key code is not really a unicode character (it may
     // be a function key or etc., the platforms appear to always give us a
     // small value in this case) then fallback to the ASCII key code but
     // don't do anything for function keys or etc.
-    key = event.GetUnicodeKey();
-    if (key <= 127)
-    {
-        key = event.GetKeyCode();
-        keyOk = (key <= 127);
-    }
+    if ( event.GetUnicodeKey() > 127 && event.GetKeyCode() > 127 )
+        return false;
 #else
-    key = event.GetKeyCode();
-    keyOk = (key <= 255);
+    if ( event.GetKeyCode() > 255 )
+        return false;
 #endif
 
-    return keyOk;
+    return true;
 }
 
 void wxGridCellEditor::StartingKey(wxKeyEvent& event)
@@ -3825,15 +4004,6 @@ void wxGridStringTable::SetValue( int row, int col, const wxString& value )
     m_data[row][col] = value;
 }
 
-bool wxGridStringTable::IsEmptyCell( int row, int col )
-{
-    wxCHECK_MSG( (row < GetNumberRows()) && (col < GetNumberCols()),
-                 true,
-                  _T("invalid row or column index in wxGridStringTable") );
-
-    return (m_data[row][col] == wxEmptyString);
-}
-
 void wxGridStringTable::Clear()
 {
     int row, col;
@@ -4161,22 +4331,12 @@ void wxGridSubwindow::OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event
     m_owner->CancelMouseCapture();
 }
 
-IMPLEMENT_DYNAMIC_CLASS( wxGridRowLabelWindow, wxWindow )
-
 BEGIN_EVENT_TABLE( wxGridRowLabelWindow, wxGridSubwindow )
     EVT_PAINT( wxGridRowLabelWindow::OnPaint )
     EVT_MOUSEWHEEL( wxGridRowLabelWindow::OnMouseWheel )
     EVT_MOUSE_EVENTS( wxGridRowLabelWindow::OnMouseEvent )
 END_EVENT_TABLE()
 
-wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid *parent,
-                                            wxWindowID id,
-                                            const wxPoint &pos, const wxSize &size )
-  : wxGridSubwindow(parent, id, pos, size)
-{
-    m_owner = parent;
-}
-
 void wxGridRowLabelWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
 {
     wxPaintDC dc(this);
@@ -4203,27 +4363,18 @@ void wxGridRowLabelWindow::OnMouseEvent( wxMouseEvent& event )
 
 void wxGridRowLabelWindow::OnMouseWheel( wxMouseEvent& event )
 {
-    m_owner->GetEventHandler()->ProcessEvent( event );
+    if (!m_owner->GetEventHandler()->ProcessEvent( event ))
+        event.Skip();
 }
 
 //////////////////////////////////////////////////////////////////////
 
-IMPLEMENT_DYNAMIC_CLASS( wxGridColLabelWindow, wxWindow )
-
 BEGIN_EVENT_TABLE( wxGridColLabelWindow, wxGridSubwindow )
     EVT_PAINT( wxGridColLabelWindow::OnPaint )
     EVT_MOUSEWHEEL( wxGridColLabelWindow::OnMouseWheel )
     EVT_MOUSE_EVENTS( wxGridColLabelWindow::OnMouseEvent )
 END_EVENT_TABLE()
 
-wxGridColLabelWindow::wxGridColLabelWindow( wxGrid *parent,
-                                            wxWindowID id,
-                                            const wxPoint &pos, const wxSize &size )
-  : wxGridSubwindow(parent, id, pos, size)
-{
-    m_owner = parent;
-}
-
 void wxGridColLabelWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
 {
     wxPaintDC dc(this);
@@ -4253,28 +4404,18 @@ void wxGridColLabelWindow::OnMouseEvent( wxMouseEvent& event )
 
 void wxGridColLabelWindow::OnMouseWheel( wxMouseEvent& event )
 {
-    m_owner->GetEventHandler()->ProcessEvent( event );
+    if (!m_owner->GetEventHandler()->ProcessEvent( event ))
+        event.Skip();
 }
 
 //////////////////////////////////////////////////////////////////////
 
-IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow, wxWindow )
-
 BEGIN_EVENT_TABLE( wxGridCornerLabelWindow, wxGridSubwindow )
     EVT_MOUSEWHEEL( wxGridCornerLabelWindow::OnMouseWheel )
     EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent )
     EVT_PAINT( wxGridCornerLabelWindow::OnPaint )
 END_EVENT_TABLE()
 
-wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid *parent,
-                                                  wxWindowID id,
-                                                  const wxPoint& pos,
-                                                  const wxSize& size )
-  : wxGridSubwindow(parent, id, pos, size)
-{
-    m_owner = parent;
-}
-
 void wxGridCornerLabelWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
 {
     wxPaintDC dc(this);
@@ -4289,13 +4430,12 @@ void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent& event )
 
 void wxGridCornerLabelWindow::OnMouseWheel( wxMouseEvent& event )
 {
-    m_owner->GetEventHandler()->ProcessEvent(event);
+    if (!m_owner->GetEventHandler()->ProcessEvent(event))
+        event.Skip();
 }
 
 //////////////////////////////////////////////////////////////////////
 
-IMPLEMENT_DYNAMIC_CLASS( wxGridWindow, wxWindow )
-
 BEGIN_EVENT_TABLE( wxGridWindow, wxGridSubwindow )
     EVT_PAINT( wxGridWindow::OnPaint )
     EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel )
@@ -4308,21 +4448,6 @@ BEGIN_EVENT_TABLE( wxGridWindow, wxGridSubwindow )
     EVT_ERASE_BACKGROUND( wxGridWindow::OnEraseBackground )
 END_EVENT_TABLE()
 
-wxGridWindow::wxGridWindow( wxGrid *parent,
-                            wxGridRowLabelWindow *rowLblWin,
-                            wxGridColLabelWindow *colLblWin,
-                            wxWindowID id,
-                            const wxPoint &pos,
-                            const wxSize &size )
-            : wxGridSubwindow(parent, id, pos, size,
-                              wxWANTS_CHARS | wxCLIP_CHILDREN,
-                              wxT("grid window") )
-{
-    m_owner = parent;
-    m_rowLabelWin = rowLblWin;
-    m_colLabelWin = colLblWin;
-}
-
 void wxGridWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
 {
     wxPaintDC dc( this );
@@ -4331,17 +4456,18 @@ void wxGridWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
     wxGridCellCoordsArray dirtyCells = m_owner->CalcCellsExposed( reg );
     m_owner->DrawGridCellArea( dc, dirtyCells );
 
+    m_owner->DrawGridSpace( dc );
+
     m_owner->DrawAllGridLines( dc, reg );
 
-    m_owner->DrawGridSpace( dc );
     m_owner->DrawHighlight( dc, dirtyCells );
 }
 
 void wxGridWindow::ScrollWindow( int dx, int dy, const wxRect *rect )
 {
     wxWindow::ScrollWindow( dx, dy, rect );
-    m_rowLabelWin->ScrollWindow( 0, dy, rect );
-    m_colLabelWin->ScrollWindow( dx, 0, rect );
+    m_owner->GetGridRowLabelWindow()->ScrollWindow( 0, dy, rect );
+    m_owner->GetGridColLabelWindow()->ScrollWindow( dx, 0, rect );
 }
 
 void wxGridWindow::OnMouseEvent( wxMouseEvent& event )
@@ -4354,7 +4480,8 @@ void wxGridWindow::OnMouseEvent( wxMouseEvent& event )
 
 void wxGridWindow::OnMouseWheel( wxMouseEvent& event )
 {
-    m_owner->GetEventHandler()->ProcessEvent( event );
+    if (!m_owner->GetEventHandler()->ProcessEvent( event ))
+        event.Skip();
 }
 
 // This seems to be required for wxMotif/wxGTK otherwise the mouse
@@ -4477,22 +4604,6 @@ BEGIN_EVENT_TABLE( wxGrid, wxScrolledWindow )
     EVT_ERASE_BACKGROUND( wxGrid::OnEraseBackground )
 END_EVENT_TABLE()
 
-wxGrid::wxGrid()
-{
-    InitVars();
-}
-
-wxGrid::wxGrid( wxWindow *parent,
-                 wxWindowID id,
-                 const wxPoint& pos,
-                 const wxSize& size,
-                 long style,
-                 const wxString& name )
-{
-    InitVars();
-    Create(parent, id, pos, size, style, name);
-}
-
 bool wxGrid::Create(wxWindow *parent, wxWindowID id,
                           const wxPoint& pos, const wxSize& size,
                           long style, const wxString& name)
@@ -4514,6 +4625,14 @@ bool wxGrid::Create(wxWindow *parent, wxWindowID id,
 
 wxGrid::~wxGrid()
 {
+    if ( m_winCapture )
+        m_winCapture->ReleaseMouse();
+
+    // Ensure that the editor control is destroyed before the grid is,
+    // otherwise we crash later when the editor tries to do something with the
+    // half destroyed grid
+    HideCellEditControl();
+
     // Must do this or ~wxScrollHelper will pop the wrong event handler
     SetTargetWindow(this);
     ClearAttrCache();
@@ -4581,31 +4700,11 @@ void wxGrid::Create()
     m_numCols = 0;
     m_currentCellCoords = wxGridNoCellCoords;
 
-    m_rowLabelWidth = WXGRID_DEFAULT_ROW_LABEL_WIDTH;
-    m_colLabelHeight = WXGRID_DEFAULT_COL_LABEL_HEIGHT;
-
     // subwindow components that make up the wxGrid
-    m_rowLabelWin = new wxGridRowLabelWindow( this,
-                                              wxID_ANY,
-                                              wxDefaultPosition,
-                                              wxDefaultSize );
-
-    m_colLabelWin = new wxGridColLabelWindow( this,
-                                              wxID_ANY,
-                                              wxDefaultPosition,
-                                              wxDefaultSize );
-
-    m_cornerLabelWin = new wxGridCornerLabelWindow( this,
-                                                    wxID_ANY,
-                                                    wxDefaultPosition,
-                                                    wxDefaultSize );
-
-    m_gridWin = new wxGridWindow( this,
-                                  m_rowLabelWin,
-                                  m_colLabelWin,
-                                  wxID_ANY,
-                                  wxDefaultPosition,
-                                  wxDefaultSize );
+    m_rowLabelWin = new wxGridRowLabelWindow(this);
+    CreateColumnWindow();
+    m_cornerLabelWin = new wxGridCornerLabelWindow(this);
+    m_gridWin = new wxGridWindow( this );
 
     SetTargetWindow( m_gridWin );
 
@@ -4625,13 +4724,38 @@ void wxGrid::Create()
     m_cornerLabelWin->SetOwnBackgroundColour(lbg);
     m_rowLabelWin->SetOwnForegroundColour(lfg);
     m_rowLabelWin->SetOwnBackgroundColour(lbg);
-    m_colLabelWin->SetOwnForegroundColour(lfg);
-    m_colLabelWin->SetOwnBackgroundColour(lbg);
+    m_colWindow->SetOwnForegroundColour(lfg);
+    m_colWindow->SetOwnBackgroundColour(lbg);
 
     m_gridWin->SetOwnForegroundColour(gfg);
     m_gridWin->SetOwnBackgroundColour(gbg);
 
-    Init();
+    m_labelBackgroundColour = m_rowLabelWin->GetBackgroundColour();
+    m_labelTextColour = m_rowLabelWin->GetForegroundColour();
+
+    // now that we have the grid window, use its font to compute the default
+    // row height
+    m_defaultRowHeight = m_gridWin->GetCharHeight();
+#if defined(__WXMOTIF__) || defined(__WXGTK__)  // see also text ctrl sizing in ShowCellEditControl()
+    m_defaultRowHeight += 8;
+#else
+    m_defaultRowHeight += 4;
+#endif
+
+}
+
+void wxGrid::CreateColumnWindow()
+{
+    if ( m_useNativeHeader )
+    {
+        m_colWindow = new wxGridHeaderCtrl(this);
+        m_colLabelHeight = m_colWindow->GetBestSize().y;
+    }
+    else // draw labels ourselves
+    {
+        m_colWindow = new wxGridColLabelWindow(this);
+        m_colLabelHeight = WXGRID_DEFAULT_COL_LABEL_HEIGHT;
+    }
 }
 
 bool wxGrid::CreateGrid( int numRows, int numCols,
@@ -4699,6 +4823,9 @@ wxGrid::SetTable(wxGridTableBase *table,
         m_numRows = table->GetNumberRows();
         m_numCols = table->GetNumberCols();
 
+        if ( m_useNativeHeader )
+            GetGridColHeader()->SetColumnCount(m_numCols);
+
         m_table = table;
         m_table->SetView( this );
         m_ownTable = takeOwnership;
@@ -4708,22 +4835,22 @@ wxGrid::SetTable(wxGridTableBase *table,
             // If the newly set table is smaller than the
             // original one current cell and selection regions
             // might be invalid,
-            m_selectingKeyboard = wxGridNoCellCoords;
+            m_selectedBlockCorner = wxGridNoCellCoords;
             m_currentCellCoords =
               wxGridCellCoords(wxMin(m_numRows, m_currentCellCoords.GetRow()),
                                wxMin(m_numCols, m_currentCellCoords.GetCol()));
-            if (m_selectingTopLeft.GetRow() >= m_numRows ||
-                m_selectingTopLeft.GetCol() >= m_numCols)
+            if (m_selectedBlockTopLeft.GetRow() >= m_numRows ||
+                m_selectedBlockTopLeft.GetCol() >= m_numCols)
             {
-                m_selectingTopLeft = wxGridNoCellCoords;
-                m_selectingBottomRight = wxGridNoCellCoords;
+                m_selectedBlockTopLeft = wxGridNoCellCoords;
+                m_selectedBlockBottomRight = wxGridNoCellCoords;
             }
             else
-                m_selectingBottomRight =
+                m_selectedBlockBottomRight =
                   wxGridCellCoords(wxMin(m_numRows,
-                                         m_selectingBottomRight.GetRow()),
+                                         m_selectedBlockBottomRight.GetRow()),
                                    wxMin(m_numCols,
-                                         m_selectingBottomRight.GetCol()));
+                                         m_selectedBlockBottomRight.GetCol()));
         }
         CalcDimensions();
 
@@ -4733,13 +4860,13 @@ wxGrid::SetTable(wxGridTableBase *table,
     return m_created;
 }
 
-void wxGrid::InitVars()
+void wxGrid::Init()
 {
     m_created = false;
 
     m_cornerLabelWin = NULL;
     m_rowLabelWin = NULL;
-    m_colLabelWin = NULL;
+    m_colWindow = NULL;
     m_gridWin = NULL;
 
     m_table = NULL;
@@ -4749,24 +4876,10 @@ void wxGrid::InitVars()
     m_defaultCellAttr = NULL;
     m_typeRegistry = NULL;
     m_winCapture = NULL;
-}
 
-void wxGrid::Init()
-{
     m_rowLabelWidth  = WXGRID_DEFAULT_ROW_LABEL_WIDTH;
     m_colLabelHeight = WXGRID_DEFAULT_COL_LABEL_HEIGHT;
 
-    if ( m_rowLabelWin )
-    {
-        m_labelBackgroundColour = m_rowLabelWin->GetBackgroundColour();
-    }
-    else
-    {
-        m_labelBackgroundColour = *wxWHITE;
-    }
-
-    m_labelTextColour = *wxBLACK;
-
     // init attr cache
     m_attrCache.row = -1;
     m_attrCache.col = -1;
@@ -4783,19 +4896,15 @@ void wxGrid::Init()
     m_colLabelTextOrientation = wxHORIZONTAL;
 
     m_defaultColWidth  = WXGRID_DEFAULT_COL_WIDTH;
-    m_defaultRowHeight = m_gridWin->GetCharHeight();
+    m_defaultRowHeight = 0; // this will be initialized after creation
 
     m_minAcceptableColWidth  = WXGRID_MIN_COL_WIDTH;
     m_minAcceptableRowHeight = WXGRID_MIN_ROW_HEIGHT;
 
-#if defined(__WXMOTIF__) || defined(__WXGTK__)  // see also text ctrl sizing in ShowCellEditControl()
-    m_defaultRowHeight += 8;
-#else
-    m_defaultRowHeight += 4;
-#endif
-
     m_gridLineColour = wxColour( 192,192,192 );
     m_gridLinesEnabled = true;
+    m_gridLinesClipHorz =
+    m_gridLinesClipVert = true;
     m_cellHighlightColour = *wxBLACK;
     m_cellHighlightPenWidth = 2;
     m_cellHighlightROPenWidth = 1;
@@ -4812,6 +4921,11 @@ void wxGrid::Init()
     m_dragRowOrCol = -1;
     m_isDragging = false;
     m_startDragPos = wxDefaultPosition;
+
+    m_sortCol = wxNOT_FOUND;
+    m_sortIsAscending = true;
+
+    m_useNativeHeader =
     m_nativeColumnLabels = false;
 
     m_waitForSlowClick = false;
@@ -4821,7 +4935,9 @@ void wxGrid::Init()
 
     m_currentCellCoords = wxGridNoCellCoords;
 
-    ClearSelection();
+    m_selectedBlockTopLeft =
+    m_selectedBlockBottomRight =
+    m_selectedBlockCorner = wxGridNoCellCoords;
 
     m_selectionBackground = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
     m_selectionForeground = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
@@ -4877,10 +4993,9 @@ void wxGrid::InitColWidths()
 
     m_colWidths.Add( m_defaultColWidth, m_numCols );
 
-    int colRight = 0;
     for ( int i = 0; i < m_numCols; i++ )
     {
-        colRight = ( GetColPos( i ) + 1 ) * m_defaultColWidth;
+        int colRight = ( GetColPos( i ) + 1 ) * m_defaultColWidth;
         m_colRights.Add( colRight );
     }
 }
@@ -5002,8 +5117,8 @@ void wxGrid::CalcWindowSizes()
     if ( m_cornerLabelWin && m_cornerLabelWin->IsShown() )
         m_cornerLabelWin->SetSize( 0, 0, m_rowLabelWidth, m_colLabelHeight );
 
-    if ( m_colLabelWin && m_colLabelWin->IsShown() )
-        m_colLabelWin->SetSize( m_rowLabelWidth, 0, gw, m_colLabelHeight );
+    if ( m_colWindow && m_colWindow->IsShown() )
+        m_colWindow->SetSize( m_rowLabelWidth, 0, gw, m_colLabelHeight );
 
     if ( m_rowLabelWin && m_rowLabelWin->IsShown() )
         m_rowLabelWin->SetSize( 0, m_colLabelHeight, m_rowLabelWidth, gh );
@@ -5031,20 +5146,6 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
     // cell it might want to save that stuff to might no longer exist.
     HideCellEditControl();
 
-#if 0
-    // if we were using the default widths/heights so far, we must change them
-    // now
-    if ( m_colWidths.IsEmpty() )
-    {
-        InitColWidths();
-    }
-
-    if ( m_rowHeights.IsEmpty() )
-    {
-        InitRowHeights();
-    }
-#endif
-
     switch ( msg.GetId() )
     {
         case wxGRIDTABLE_NOTIFY_ROWS_INSERTED:
@@ -5195,6 +5296,9 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
             int numCols = msg.GetCommandInt2();
             m_numCols += numCols;
 
+            if ( m_useNativeHeader )
+                GetGridColHeader()->SetColumnCount(m_numCols);
+
             if ( !m_colAt.IsEmpty() )
             {
                 //Shift the column IDs
@@ -5249,7 +5353,7 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
             if ( !GetBatchCount() )
             {
                 CalcDimensions();
-                m_colLabelWin->Refresh();
+                m_colWindow->Refresh();
             }
         }
         result = true;
@@ -5260,6 +5364,8 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
             int numCols = msg.GetCommandInt();
             int oldNumCols = m_numCols;
             m_numCols += numCols;
+            if ( m_useNativeHeader )
+                GetGridColHeader()->SetColumnCount(m_numCols);
 
             if ( !m_colAt.IsEmpty() )
             {
@@ -5302,7 +5408,7 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
             if ( !GetBatchCount() )
             {
                 CalcDimensions();
-                m_colLabelWin->Refresh();
+                m_colWindow->Refresh();
             }
         }
         result = true;
@@ -5313,6 +5419,8 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
             size_t pos = msg.GetCommandInt();
             int numCols = msg.GetCommandInt2();
             m_numCols -= numCols;
+            if ( m_useNativeHeader )
+                GetGridColHeader()->SetColumnCount(m_numCols);
 
             if ( !m_colAt.IsEmpty() )
             {
@@ -5377,7 +5485,7 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
             if ( !GetBatchCount() )
             {
                 CalcDimensions();
-                m_colLabelWin->Refresh();
+                m_colWindow->Refresh();
             }
         }
         result = true;
@@ -5527,9 +5635,8 @@ wxGridCellCoordsArray wxGrid::CalcCellsExposed( const wxRegion& reg ) const
         CalcUnscrolledPosition( r.GetRight(), r.GetBottom(), &right, &bottom );
 
         // find the cells within these bounds
-        //
-        int row, col;
-        for ( row = internalYToRow(top); row < m_numRows; row++ )
+        wxArrayInt cols;
+        for ( int row = internalYToRow(top); row < m_numRows; row++ )
         {
             if ( GetRowBottom(row) <= top )
                 continue;
@@ -5537,19 +5644,23 @@ wxGridCellCoordsArray wxGrid::CalcCellsExposed( const wxRegion& reg ) const
             if ( GetRowTop(row) > bottom )
                 break;
 
-            int colPos;
-            for ( colPos = GetColPos( internalXToCol(left) ); colPos < m_numCols; colPos++ )
+            // add all dirty cells in this row: notice that the columns which
+            // are dirty don't depend on the row so we compute them only once
+            // for the first dirty row and then reuse for all the next ones
+            if ( cols.empty() )
             {
-                col = GetColAt( colPos );
-
-                if ( GetColRight(col) <= left )
-                    continue;
+                // do determine the dirty columns
+                for ( int pos = XToPos(left); pos <= XToPos(right); pos++ )
+                    cols.push_back(GetColAt(pos));
 
-                if ( GetColLeft(col) > right )
+                // if there are no dirty columns at all, nothing to do
+                if ( cols.empty() )
                     break;
-
-                cellsExposed.Add( wxGridCellCoords( row, col ) );
             }
+
+            const size_t count = cols.size();
+            for ( size_t n = 0; n < count; n++ )
+                cellsExposed.Add(wxGridCellCoords(row, cols[n]));
         }
 
         ++iter;
@@ -5603,13 +5714,7 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
                     if ( (row = YToRow( y )) >= 0 )
                     {
                         if ( m_selection )
-                        {
-                            m_selection->SelectRow( row,
-                                                    event.ControlDown(),
-                                                    event.ShiftDown(),
-                                                    event.AltDown(),
-                                                    event.MetaDown() );
-                        }
+                            m_selection->SelectRow(row, event);
                     }
                 }
                 break;
@@ -5660,22 +5765,16 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
                 {
                     if ( event.ShiftDown() )
                     {
-                        m_selection->SelectBlock( m_currentCellCoords.GetRow(),
-                                                  0,
-                                                  row,
-                                                  GetNumberCols() - 1,
-                                                  event.ControlDown(),
-                                                  event.ShiftDown(),
-                                                  event.AltDown(),
-                                                  event.MetaDown() );
+                        m_selection->SelectBlock
+                                     (
+                                        m_currentCellCoords.GetRow(), 0,
+                                        row, GetNumberCols() - 1,
+                                        event
+                                     );
                     }
                     else
                     {
-                        m_selection->SelectRow( row,
-                                                event.ControlDown(),
-                                                event.ShiftDown(),
-                                                event.AltDown(),
-                                                event.MetaDown() );
+                        m_selection->SelectRow(row, event);
                     }
                 }
 
@@ -5709,7 +5808,7 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
             // adjust row height depending on label text
             AutoSizeRowLabelSize( row );
 
-            ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, m_colLabelWin);
+            ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, GetColLabelWindow());
             m_dragLastPos = -1;
         }
     }
@@ -5777,21 +5876,107 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
     }
 }
 
+void wxGrid::UpdateColumnSortingIndicator(int col)
+{
+    wxCHECK_RET( col != wxNOT_FOUND, "invalid column index" );
+
+    if ( m_useNativeHeader )
+        GetGridColHeader()->UpdateColumn(col);
+    else if ( m_nativeColumnLabels )
+        m_colWindow->Refresh();
+    //else: sorting indicator display not yet implemented in grid version
+}
+
+void wxGrid::SetSortingColumn(int col, bool ascending)
+{
+    if ( col == m_sortCol )
+    {
+        // we are already using this column for sorting (or not sorting at all)
+        // but we might still change the sorting order, check for it
+        if ( m_sortCol != wxNOT_FOUND && ascending != m_sortIsAscending )
+        {
+            m_sortIsAscending = ascending;
+
+            UpdateColumnSortingIndicator(m_sortCol);
+        }
+    }
+    else // we're changing the column used for sorting
+    {
+        const int sortColOld = m_sortCol;
+
+        // change it before updating the column as we want GetSortingColumn()
+        // to return the correct new value
+        m_sortCol = col;
+
+        if ( sortColOld != wxNOT_FOUND )
+            UpdateColumnSortingIndicator(sortColOld);
+
+        if ( m_sortCol != wxNOT_FOUND )
+        {
+            m_sortIsAscending = ascending;
+            UpdateColumnSortingIndicator(m_sortCol);
+        }
+    }
+}
+
+void wxGrid::DoColHeaderClick(int col)
+{
+    // we consider that the grid was resorted if this event is processed and
+    // not vetoed
+    if ( SendEvent(wxEVT_GRID_COL_SORT, -1, col) == 1 )
+    {
+        SetSortingColumn(col, IsSortingBy(col) ? !m_sortIsAscending : true);
+        Refresh();
+    }
+}
+
+void wxGrid::DoStartResizeCol(int col)
+{
+    m_dragRowOrCol = col;
+    m_dragLastPos = -1;
+    DoUpdateResizeColWidth(GetColWidth(m_dragRowOrCol));
+}
+
+void wxGrid::DoUpdateResizeCol(int x)
+{
+    int cw, ch, dummy, top;
+    m_gridWin->GetClientSize( &cw, &ch );
+    CalcUnscrolledPosition( 0, 0, &dummy, &top );
+
+    wxClientDC dc( m_gridWin );
+    PrepareDC( dc );
+
+    x = wxMax( x, GetColLeft(m_dragRowOrCol) + GetColMinimalWidth(m_dragRowOrCol));
+    dc.SetLogicalFunction(wxINVERT);
+    if ( m_dragLastPos >= 0 )
+    {
+        dc.DrawLine( m_dragLastPos, top, m_dragLastPos, top + ch );
+    }
+    dc.DrawLine( x, top, x, top + ch );
+    m_dragLastPos = x;
+}
+
+void wxGrid::DoUpdateResizeColWidth(int w)
+{
+    DoUpdateResizeCol(GetColLeft(m_dragRowOrCol) + w);
+}
+
 void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
 {
-    int x, y, col;
+    int x, y;
     wxPoint pos( event.GetPosition() );
     CalcUnscrolledPosition( pos.x, pos.y, &x, &y );
 
+    int col = XToCol(x);
     if ( event.Dragging() )
     {
         if (!m_isDragging)
         {
             m_isDragging = true;
-            m_colLabelWin->CaptureMouse();
+            GetColLabelWindow()->CaptureMouse();
 
-            if ( m_cursorMode == WXGRID_CURSOR_MOVE_COL )
-                m_dragRowOrCol = XToCol( x );
+            if ( m_cursorMode == WXGRID_CURSOR_MOVE_COL && col != -1 )
+                DoStartMoveCol(col);
         }
 
         if ( event.LeftIsDown() )
@@ -5799,78 +5984,45 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
             switch ( m_cursorMode )
             {
                 case WXGRID_CURSOR_RESIZE_COL:
-                {
-                    int cw, ch, dummy, top;
-                    m_gridWin->GetClientSize( &cw, &ch );
-                    CalcUnscrolledPosition( 0, 0, &dummy, &top );
-
-                    wxClientDC dc( m_gridWin );
-                    PrepareDC( dc );
-
-                    x = wxMax( x, GetColLeft(m_dragRowOrCol) +
-                                  GetColMinimalWidth(m_dragRowOrCol));
-                    dc.SetLogicalFunction(wxINVERT);
-                    if ( m_dragLastPos >= 0 )
-                    {
-                        dc.DrawLine( m_dragLastPos, top, m_dragLastPos, top + ch );
-                    }
-                    dc.DrawLine( x, top, x, top + ch );
-                    m_dragLastPos = x;
-                }
-                break;
+                DoUpdateResizeCol(x);
+                break;
 
                 case WXGRID_CURSOR_SELECT_COL:
                 {
-                    if ( (col = XToCol( x )) >= 0 )
+                    if ( col != -1 )
                     {
                         if ( m_selection )
-                        {
-                            m_selection->SelectCol( col,
-                                                    event.ControlDown(),
-                                                    event.ShiftDown(),
-                                                    event.AltDown(),
-                                                    event.MetaDown() );
-                        }
+                            m_selection->SelectCol(col, event);
                     }
                 }
                 break;
 
                 case WXGRID_CURSOR_MOVE_COL:
                 {
-                    if ( x < 0 )
-                        m_moveToCol = GetColAt( 0 );
-                    else
-                        m_moveToCol = XToCol( x );
+                    int posNew = XToPos(x);
+                    int colNew = GetColAt(posNew);
 
+                    // determine the position of the drop marker
                     int markerX;
-
-                    if ( m_moveToCol < 0 )
-                        markerX = GetColRight( GetColAt( m_numCols - 1 ) );
-                    else if ( x >= (GetColLeft( m_moveToCol ) + (GetColWidth(m_moveToCol) / 2)) )
-                    {
-                        m_moveToCol = GetColAt( GetColPos( m_moveToCol ) + 1 );
-                        if ( m_moveToCol < 0 )
-                            markerX = GetColRight( GetColAt( m_numCols - 1 ) );
-                        else
-                            markerX = GetColLeft( m_moveToCol );
-                    }
+                    if ( x >= GetColLeft(colNew) + (GetColWidth(colNew) / 2) )
+                        markerX = GetColRight(colNew);
                     else
-                        markerX = GetColLeft( m_moveToCol );
+                        markerX = GetColLeft(colNew);
 
                     if ( markerX != m_dragLastPos )
                     {
-                        wxClientDC dc( m_colLabelWin );
+                        wxClientDC dc( GetColLabelWindow() );
                         DoPrepareDC(dc);
 
                         int cw, ch;
-                        m_colLabelWin->GetClientSize( &cw, &ch );
+                        GetColLabelWindow()->GetClientSize( &cw, &ch );
 
                         markerX++;
 
                         //Clean up the last indicator
                         if ( m_dragLastPos >= 0 )
                         {
-                            wxPen pen( m_colLabelWin->GetBackgroundColour(), 2 );
+                            wxPen pen( GetColLabelWindow()->GetBackgroundColour(), 2 );
                             dc.SetPen(pen);
                             dc.DrawLine( m_dragLastPos + 1, 0, m_dragLastPos + 1, ch );
                             dc.SetPen(wxNullPen);
@@ -5881,9 +6033,7 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
 
                         const wxColour *color;
                         //Moving to the same place? Don't draw a marker
-                        if ( (m_moveToCol == m_dragRowOrCol)
-                          || (GetColPos( m_moveToCol ) == GetColPos( m_dragRowOrCol ) + 1)
-                          || (m_moveToCol < 0 && m_dragRowOrCol == GetColAt( m_numCols - 1 )))
+                        if ( colNew == m_dragRowOrCol )
                             color = wxLIGHT_GREY;
                         else
                             color = wxBLUE;
@@ -5915,8 +6065,8 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
 
     if (m_isDragging)
     {
-        if (m_colLabelWin->HasCapture())
-            m_colLabelWin->ReleaseMouse();
+        if (GetColLabelWindow()->HasCapture())
+            GetColLabelWindow()->ReleaseMouse();
         m_isDragging = false;
     }
 
@@ -5924,7 +6074,7 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
     //
     if ( event.Entering() || event.Leaving() )
     {
-        ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, m_colLabelWin);
+        ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, GetColLabelWindow());
     }
 
     // ------------ Left button pressed
@@ -5937,21 +6087,20 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
         //
         if ( XToEdgeOfCol(x) < 0 )
         {
-            col = XToCol(x);
             if ( col >= 0 &&
                  !SendEvent( wxEVT_GRID_LABEL_LEFT_CLICK, -1, col, event ) )
             {
                 if ( m_canDragColMove )
                 {
                     //Show button as pressed
-                    wxClientDC dc( m_colLabelWin );
+                    wxClientDC dc( GetColLabelWindow() );
                     int colLeft = GetColLeft( col );
                     int colRight = GetColRight( col ) - 1;
-                    dc.SetPen( wxPen( m_colLabelWin->GetBackgroundColour(), 1 ) );
+                    dc.SetPen( wxPen( GetColLabelWindow()->GetBackgroundColour(), 1 ) );
                     dc.DrawLine( colLeft, 1, colLeft, m_colLabelHeight-1 );
                     dc.DrawLine( colLeft, 1, colRight, 1 );
 
-                    ChangeCursorMode(WXGRID_CURSOR_MOVE_COL, m_colLabelWin);
+                    ChangeCursorMode(WXGRID_CURSOR_MOVE_COL, GetColLabelWindow());
                 }
                 else
                 {
@@ -5961,25 +6110,20 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
                     {
                         if ( event.ShiftDown() )
                         {
-                            m_selection->SelectBlock( 0,
-                                                      m_currentCellCoords.GetCol(),
-                                                      GetNumberRows() - 1, col,
-                                                      event.ControlDown(),
-                                                      event.ShiftDown(),
-                                                      event.AltDown(),
-                                                      event.MetaDown() );
+                            m_selection->SelectBlock
+                                         (
+                                            0, m_currentCellCoords.GetCol(),
+                                            GetNumberRows() - 1, col,
+                                            event
+                                         );
                         }
                         else
                         {
-                            m_selection->SelectCol( col,
-                                                    event.ControlDown(),
-                                                    event.ShiftDown(),
-                                                    event.AltDown(),
-                                                    event.MetaDown() );
+                            m_selection->SelectCol(col, event);
                         }
                     }
 
-                    ChangeCursorMode(WXGRID_CURSOR_SELECT_COL, m_colLabelWin);
+                    ChangeCursorMode(WXGRID_CURSOR_SELECT_COL, GetColLabelWindow());
                 }
             }
         }
@@ -5988,7 +6132,7 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
             // starting to drag-resize a col
             //
             if ( CanDragColSize() )
-                ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL, m_colLabelWin);
+                ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL, GetColLabelWindow());
         }
     }
 
@@ -5996,10 +6140,9 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
     //
     if ( event.LeftDClick() )
     {
-        col = XToEdgeOfCol(x);
-        if ( col < 0 )
+        const int colEdge = XToEdgeOfCol(x);
+        if ( colEdge == -1 )
         {
-            col = XToCol(x);
             if ( col >= 0 &&
                  ! SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK, -1, col, event ) )
             {
@@ -6009,9 +6152,9 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
         else
         {
             // adjust column width depending on label text
-            AutoSizeColLabelSize( col );
+            AutoSizeColLabelSize( colEdge );
 
-            ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, m_colLabelWin);
+            ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, GetColLabelWindow());
             m_dragLastPos = -1;
         }
     }
@@ -6024,28 +6167,32 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
         {
             case WXGRID_CURSOR_RESIZE_COL:
                 DoEndDragResizeCol();
-
-                // Note: we are ending the event *after* doing
-                // default processing in this case
-                //
-                SendEvent( wxEVT_GRID_COL_SIZE, -1, m_dragRowOrCol, event );
                 break;
 
             case WXGRID_CURSOR_MOVE_COL:
-                DoEndDragMoveCol();
-
-                SendEvent( wxEVT_GRID_COL_MOVE, -1, m_dragRowOrCol, event );
+                if ( m_dragLastPos == -1 || col == m_dragRowOrCol )
+                {
+                    // the column didn't actually move anywhere
+                    if ( col != -1 )
+                        DoColHeaderClick(col);
+                    m_colWindow->Refresh();   // "unpress" the column
+                }
+                else
+                {
+                    DoEndMoveCol(XToPos(x));
+                }
                 break;
 
             case WXGRID_CURSOR_SELECT_COL:
             case WXGRID_CURSOR_SELECT_CELL:
             case WXGRID_CURSOR_RESIZE_ROW:
             case WXGRID_CURSOR_SELECT_ROW:
-                // nothing to do (?)
+                if ( col != -1 )
+                    DoColHeaderClick(col);
                 break;
         }
 
-        ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, m_colLabelWin);
+        ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, GetColLabelWindow());
         m_dragLastPos = -1;
     }
 
@@ -6053,7 +6200,6 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
     //
     else if ( event.RightDown() )
     {
-        col = XToCol(x);
         if ( col >= 0 &&
              !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK, -1, col, event ) )
         {
@@ -6065,7 +6211,6 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
     //
     else if ( event.RightDClick() )
     {
-        col = XToCol(x);
         if ( col >= 0 &&
              !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK, -1, col, event ) )
         {
@@ -6084,12 +6229,12 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
             {
                 // don't capture the cursor yet
                 if ( CanDragColSize() )
-                    ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL, m_colLabelWin, false);
+                    ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL, GetColLabelWindow(), false);
             }
         }
         else if ( m_cursorMode != WXGRID_CURSOR_SELECT_CELL )
         {
-            ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, m_colLabelWin, false);
+            ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, GetColLabelWindow(), false);
         }
     }
 }
@@ -6132,6 +6277,8 @@ void wxGrid::CancelMouseCapture()
     if ( m_winCapture )
     {
         m_isDragging = false;
+        m_startDragPos = wxDefaultPosition;
+
         m_cursorMode = WXGRID_CURSOR_SELECT_CELL;
         m_winCapture->SetCursor( *wxSTANDARD_CURSOR );
         m_winCapture = NULL;
@@ -6158,9 +6305,9 @@ void wxGrid::ChangeCursorMode(CursorMode mode,
 
     wxLogTrace(_T("grid"),
                _T("wxGrid cursor mode (mouse capture for %s): %s -> %s"),
-               win == m_colLabelWin ? _T("colLabelWin")
-                                    : win ? _T("rowLabelWin")
-                                          : _T("gridWin"),
+               win == m_colWindow ? _T("colLabelWin")
+                                  : win ? _T("rowLabelWin")
+                                        : _T("gridWin"),
                cursorModes[m_cursorMode], cursorModes[mode]);
 #endif
 
@@ -6177,8 +6324,7 @@ void wxGrid::ChangeCursorMode(CursorMode mode,
 
     if ( m_winCapture )
     {
-        if (m_winCapture->HasCapture())
-            m_winCapture->ReleaseMouse();
+        m_winCapture->ReleaseMouse();
         m_winCapture = NULL;
     }
 
@@ -6214,387 +6360,376 @@ void wxGrid::ChangeCursorMode(CursorMode mode,
     }
 }
 
-void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
-{
-    int x, y;
-    wxPoint pos( event.GetPosition() );
-    CalcUnscrolledPosition( pos.x, pos.y, &x, &y );
+// ----------------------------------------------------------------------------
+// grid mouse event processing
+// ----------------------------------------------------------------------------
 
-    wxGridCellCoords coords;
-    XYToCell( x, y, coords );
+void
+wxGrid::DoGridCellDrag(wxMouseEvent& event,
+                       const wxGridCellCoords& coords,
+                       bool isFirstDrag)
+{
+    if ( coords == wxGridNoCellCoords )
+        return; // we're outside any valid cell
 
-    int cell_rows, cell_cols;
-    bool isFirstDrag = !m_isDragging;
-    GetCellSize( coords.GetRow(), coords.GetCol(), &cell_rows, &cell_cols );
-    if ((cell_rows < 0) || (cell_cols < 0))
+    // Hide the edit control, so it won't interfere with drag-shrinking.
+    if ( IsCellEditControlShown() )
     {
-        coords.SetRow(coords.GetRow() + cell_rows);
-        coords.SetCol(coords.GetCol() + cell_cols);
+        HideCellEditControl();
+        SaveEditControlValue();
     }
 
-    if ( event.Dragging() )
+    switch ( event.GetModifiers() )
     {
-        //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol());
-
-        // Don't start doing anything until the mouse has been dragged at
-        // least 3 pixels in any direction...
-        if (! m_isDragging)
-        {
-            if (m_startDragPos == wxDefaultPosition)
-            {
-                m_startDragPos = pos;
-                return;
-            }
-            if (abs(m_startDragPos.x - pos.x) < 4 && abs(m_startDragPos.y - pos.y) < 4)
-                return;
-        }
-
-        m_isDragging = true;
-        if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
-        {
-            // Hide the edit control, so it
-            // won't interfere with drag-shrinking.
-            if ( IsCellEditControlShown() )
-            {
-                HideCellEditControl();
-                SaveEditControlValue();
-            }
+        case wxMOD_CMD:
+            if ( m_selectedBlockCorner == wxGridNoCellCoords)
+                m_selectedBlockCorner = coords;
+            UpdateBlockBeingSelected(m_selectedBlockCorner, coords);
+            break;
 
-            if ( coords != wxGridNoCellCoords )
+        case wxMOD_NONE:
+            if ( CanDragCell() )
             {
-                if ( event.CmdDown() )
+                if ( isFirstDrag )
                 {
-                    if ( m_selectingKeyboard == wxGridNoCellCoords)
-                        m_selectingKeyboard = coords;
-                    HighlightBlock( m_selectingKeyboard, coords );
-                }
-                else if ( CanDragCell() )
-                {
-                    if ( isFirstDrag )
-                    {
-                        if ( m_selectingKeyboard == wxGridNoCellCoords)
-                            m_selectingKeyboard = coords;
-
-                        SendEvent( wxEVT_GRID_CELL_BEGIN_DRAG,
-                                   coords.GetRow(),
-                                   coords.GetCol(),
-                                   event );
-                        return;
-                    }
-                }
-                else
-                {
-                    if ( !IsSelection() )
-                    {
-                        HighlightBlock( coords, coords );
-                    }
-                    else
-                    {
-                        HighlightBlock( m_currentCellCoords, coords );
-                    }
-                }
+                    if ( m_selectedBlockCorner == wxGridNoCellCoords)
+                        m_selectedBlockCorner = coords;
 
-                if (! IsVisible(coords))
-                {
-                    MakeCellVisible(coords);
-                    // TODO: need to introduce a delay or something here.  The
-                    // scrolling is way too fast, at least under MSW and GTK.
+                    SendEvent(wxEVT_GRID_CELL_BEGIN_DRAG, coords, event);
+                    return;
                 }
             }
-            // Have we captured the mouse yet?
-            if (! m_winCapture)
-            {
-                m_winCapture = m_gridWin;
-                m_winCapture->CaptureMouse();
-            }
 
+            UpdateBlockBeingSelected(m_currentCellCoords, coords);
+            break;
 
-        }
-        else if ( event.LeftIsDown() &&
-                  m_cursorMode == WXGRID_CURSOR_RESIZE_ROW )
-        {
-            int cw, ch, left, dummy;
-            m_gridWin->GetClientSize( &cw, &ch );
-            CalcUnscrolledPosition( 0, 0, &left, &dummy );
+        default:
+            // we don't handle the other key modifiers
+            event.Skip();
+    }
+}
 
-            wxClientDC dc( m_gridWin );
-            PrepareDC( dc );
-            y = wxMax( y, GetRowTop(m_dragRowOrCol) +
-                          GetRowMinimalHeight(m_dragRowOrCol) );
-            dc.SetLogicalFunction(wxINVERT);
-            if ( m_dragLastPos >= 0 )
-            {
-                dc.DrawLine( left, m_dragLastPos, left+cw, m_dragLastPos );
-            }
-            dc.DrawLine( left, y, left+cw, y );
-            m_dragLastPos = y;
-        }
-        else if ( event.LeftIsDown() &&
-                  m_cursorMode == WXGRID_CURSOR_RESIZE_COL )
-        {
-            int cw, ch, dummy, top;
-            m_gridWin->GetClientSize( &cw, &ch );
-            CalcUnscrolledPosition( 0, 0, &dummy, &top );
+void wxGrid::DoGridLineDrag(wxMouseEvent& event, const wxGridOperations& oper)
+{
+    wxClientDC dc(m_gridWin);
+    PrepareDC(dc);
+    dc.SetLogicalFunction(wxINVERT);
 
-            wxClientDC dc( m_gridWin );
-            PrepareDC( dc );
-            x = wxMax( x, GetColLeft(m_dragRowOrCol) +
-                          GetColMinimalWidth(m_dragRowOrCol) );
-            dc.SetLogicalFunction(wxINVERT);
-            if ( m_dragLastPos >= 0 )
-            {
-                dc.DrawLine( m_dragLastPos, top, m_dragLastPos, top + ch );
-            }
-            dc.DrawLine( x, top, x, top + ch );
-            m_dragLastPos = x;
+    const wxRect rectWin(CalcUnscrolledPosition(wxPoint(0, 0)),
+                         m_gridWin->GetClientSize());
+
+    // erase the previously drawn line, if any
+    if ( m_dragLastPos >= 0 )
+        oper.DrawParallelLineInRect(dc, rectWin, m_dragLastPos);
+
+    // we need the vertical position for rows and horizontal for columns here
+    m_dragLastPos = oper.Dual().Select(CalcUnscrolledPosition(event.GetPosition()));
+
+    // don't allow resizing beneath the minimal size
+    const int posMin = oper.GetLineStartPos(this, m_dragRowOrCol) +
+                        oper.GetMinimalLineSize(this, m_dragRowOrCol);
+    if ( m_dragLastPos < posMin )
+        m_dragLastPos = posMin;
+
+    // and draw it at the new position
+    oper.DrawParallelLineInRect(dc, rectWin, m_dragLastPos);
+}
+
+void wxGrid::DoGridDragEvent(wxMouseEvent& event, const wxGridCellCoords& coords)
+{
+    if ( !m_isDragging )
+    {
+        // Don't start doing anything until the mouse has been dragged far
+        // enough
+        const wxPoint& pt = event.GetPosition();
+        if ( m_startDragPos == wxDefaultPosition )
+        {
+            m_startDragPos = pt;
+            return;
         }
 
-        return;
+        if ( abs(m_startDragPos.x - pt.x) <= DRAG_SENSITIVITY &&
+                abs(m_startDragPos.y - pt.y) <= DRAG_SENSITIVITY )
+            return;
     }
 
-    m_isDragging = false;
-    m_startDragPos = wxDefaultPosition;
+    const bool isFirstDrag = !m_isDragging;
+    m_isDragging = true;
 
-    // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL
-    //     immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under
-    //     wxGTK
-#if 0
-    if ( event.Entering() || event.Leaving() )
+    switch ( m_cursorMode )
     {
-        ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
-        m_gridWin->SetCursor( *wxSTANDARD_CURSOR );
+        case WXGRID_CURSOR_SELECT_CELL:
+            DoGridCellDrag(event, coords, isFirstDrag);
+            break;
+
+        case WXGRID_CURSOR_RESIZE_ROW:
+            DoGridLineDrag(event, wxGridRowOperations());
+            break;
+
+        case WXGRID_CURSOR_RESIZE_COL:
+            DoGridLineDrag(event, wxGridColumnOperations());
+            break;
+
+        default:
+            event.Skip();
     }
-    else
-#endif // 0
 
-    // ------------ Left button pressed
-    //
-    if ( event.LeftDown() && coords != wxGridNoCellCoords )
+    if ( isFirstDrag )
     {
-        if ( !SendEvent( wxEVT_GRID_CELL_LEFT_CLICK,
-                       coords.GetRow(),
-                       coords.GetCol(),
-                       event ) )
-        {
-            if ( !event.CmdDown() )
-                ClearSelection();
-            if ( event.ShiftDown() )
-            {
-                if ( m_selection )
-                {
-                    m_selection->SelectBlock( m_currentCellCoords.GetRow(),
-                                              m_currentCellCoords.GetCol(),
-                                              coords.GetRow(),
-                                              coords.GetCol(),
-                                              event.ControlDown(),
-                                              event.ShiftDown(),
-                                              event.AltDown(),
-                                              event.MetaDown() );
-                }
-            }
-            else if ( XToEdgeOfCol(x) < 0 &&
-                      YToEdgeOfRow(y) < 0 )
-            {
-                DisableCellEditControl();
-                MakeCellVisible( coords );
+        m_winCapture = m_gridWin;
+        m_winCapture->CaptureMouse();
+    }
+}
 
-                if ( event.CmdDown() )
-                {
-                    if ( m_selection )
-                    {
-                        m_selection->ToggleCellSelection( coords.GetRow(),
-                                                          coords.GetCol(),
-                                                          event.ControlDown(),
-                                                          event.ShiftDown(),
-                                                          event.AltDown(),
-                                                          event.MetaDown() );
-                    }
-                    m_selectingTopLeft = wxGridNoCellCoords;
-                    m_selectingBottomRight = wxGridNoCellCoords;
-                    m_selectingKeyboard = coords;
-                }
-                else
-                {
-                    m_waitForSlowClick = m_currentCellCoords == coords &&
-                                                coords != wxGridNoCellCoords;
-                    SetCurrentCell( coords );
-                }
-            }
-        }
+void
+wxGrid::DoGridCellLeftDown(wxMouseEvent& event,
+                           const wxGridCellCoords& coords,
+                           const wxPoint& pos)
+{
+    if ( SendEvent(wxEVT_GRID_CELL_LEFT_CLICK, coords, event) )
+    {
+        // event handled by user code, no need to do anything here
+        return;
     }
 
-    // ------------ Left double click
-    //
-    else if ( event.LeftDClick() && coords != wxGridNoCellCoords )
+    if ( !event.CmdDown() )
+        ClearSelection();
+
+    if ( event.ShiftDown() )
+    {
+        if ( m_selection )
+        {
+            m_selection->SelectBlock(m_currentCellCoords, coords, event);
+            m_selectedBlockCorner = coords;
+        }
+    }
+    else if ( XToEdgeOfCol(pos.x) < 0 && YToEdgeOfRow(pos.y) < 0 )
     {
         DisableCellEditControl();
+        MakeCellVisible( coords );
 
-        if ( XToEdgeOfCol(x) < 0 && YToEdgeOfRow(y) < 0 )
+        if ( event.CmdDown() )
         {
-            if ( !SendEvent( wxEVT_GRID_CELL_LEFT_DCLICK,
-                             coords.GetRow(),
-                             coords.GetCol(),
-                             event ) )
+            if ( m_selection )
             {
-                // we want double click to select a cell and start editing
-                // (i.e. to behave in same way as sequence of two slow clicks):
-                m_waitForSlowClick = true;
+                m_selection->ToggleCellSelection(coords, event);
             }
+
+            m_selectedBlockTopLeft = wxGridNoCellCoords;
+            m_selectedBlockBottomRight = wxGridNoCellCoords;
+            m_selectedBlockCorner = coords;
+        }
+        else
+        {
+            m_waitForSlowClick = m_currentCellCoords == coords &&
+                                        coords != wxGridNoCellCoords;
+            SetCurrentCell( coords );
         }
     }
+}
 
-    // ------------ Left button released
-    //
-    else if ( event.LeftUp() )
+void
+wxGrid::DoGridCellLeftDClick(wxMouseEvent& event,
+                             const wxGridCellCoords& coords,
+                             const wxPoint& pos)
+{
+    if ( XToEdgeOfCol(pos.x) < 0 && YToEdgeOfRow(pos.y) < 0 )
     {
-        if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
+        if ( !SendEvent(wxEVT_GRID_CELL_LEFT_DCLICK, coords, event) )
         {
-            if (m_winCapture)
-            {
-                if (m_winCapture->HasCapture())
-                    m_winCapture->ReleaseMouse();
-                m_winCapture = NULL;
-            }
-
-            if ( coords == m_currentCellCoords && m_waitForSlowClick && CanEnableCellControl() )
-            {
-                ClearSelection();
-                EnableCellEditControl();
+            // we want double click to select a cell and start editing
+            // (i.e. to behave in same way as sequence of two slow clicks):
+            m_waitForSlowClick = true;
+        }
+    }
+}
 
-                wxGridCellAttr *attr = GetCellAttr(coords);
-                wxGridCellEditor *editor = attr->GetEditor(this, coords.GetRow(), coords.GetCol());
-                editor->StartingClick();
-                editor->DecRef();
-                attr->DecRef();
+void
+wxGrid::DoGridCellLeftUp(wxMouseEvent& event, const wxGridCellCoords& coords)
+{
+    if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
+    {
+        if (m_winCapture)
+        {
+            m_winCapture->ReleaseMouse();
+            m_winCapture = NULL;
+        }
 
-                m_waitForSlowClick = false;
-            }
-            else if ( m_selectingTopLeft != wxGridNoCellCoords &&
-                 m_selectingBottomRight != wxGridNoCellCoords )
-            {
-                if ( m_selection )
-                {
-                    m_selection->SelectBlock( m_selectingTopLeft.GetRow(),
-                                              m_selectingTopLeft.GetCol(),
-                                              m_selectingBottomRight.GetRow(),
-                                              m_selectingBottomRight.GetCol(),
-                                              event.ControlDown(),
-                                              event.ShiftDown(),
-                                              event.AltDown(),
-                                              event.MetaDown() );
-                }
+        if ( coords == m_currentCellCoords && m_waitForSlowClick && CanEnableCellControl() )
+        {
+            ClearSelection();
+            EnableCellEditControl();
 
-                m_selectingTopLeft = wxGridNoCellCoords;
-                m_selectingBottomRight = wxGridNoCellCoords;
+            wxGridCellAttr *attr = GetCellAttr(coords);
+            wxGridCellEditor *editor = attr->GetEditor(this, coords.GetRow(), coords.GetCol());
+            editor->StartingClick();
+            editor->DecRef();
+            attr->DecRef();
 
-                // Show the edit control, if it has been hidden for
-                // drag-shrinking.
-                ShowCellEditControl();
-            }
+            m_waitForSlowClick = false;
         }
-        else if ( m_cursorMode == WXGRID_CURSOR_RESIZE_ROW )
+        else if ( m_selectedBlockTopLeft != wxGridNoCellCoords &&
+             m_selectedBlockBottomRight != wxGridNoCellCoords )
         {
-            ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
-            DoEndDragResizeRow();
+            if ( m_selection )
+            {
+                m_selection->SelectBlock( m_selectedBlockTopLeft,
+                                          m_selectedBlockBottomRight,
+                                          event );
+            }
 
-            // Note: we are ending the event *after* doing
-            // default processing in this case
-            //
-            SendEvent( wxEVT_GRID_ROW_SIZE, m_dragRowOrCol, -1, event );
-        }
-        else if ( m_cursorMode == WXGRID_CURSOR_RESIZE_COL )
-        {
-            ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
-            DoEndDragResizeCol();
+            m_selectedBlockTopLeft = wxGridNoCellCoords;
+            m_selectedBlockBottomRight = wxGridNoCellCoords;
 
-            // Note: we are ending the event *after* doing
-            // default processing in this case
-            //
-            SendEvent( wxEVT_GRID_COL_SIZE, -1, m_dragRowOrCol, event );
+            // Show the edit control, if it has been hidden for
+            // drag-shrinking.
+            ShowCellEditControl();
         }
+    }
+    else if ( m_cursorMode == WXGRID_CURSOR_RESIZE_ROW )
+    {
+        ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
+        DoEndDragResizeRow();
 
-        m_dragLastPos = -1;
+        // Note: we are ending the event *after* doing
+        // default processing in this case
+        //
+        SendEvent( wxEVT_GRID_ROW_SIZE, m_dragRowOrCol, -1, event );
+    }
+    else if ( m_cursorMode == WXGRID_CURSOR_RESIZE_COL )
+    {
+        ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
+        DoEndDragResizeCol();
     }
 
-    // ------------ Right button down
-    //
-    else if ( event.RightDown() && coords != wxGridNoCellCoords )
+    m_dragLastPos = -1;
+}
+
+void
+wxGrid::DoGridMouseMoveEvent(wxMouseEvent& WXUNUSED(event),
+                             const wxGridCellCoords& coords,
+                             const wxPoint& pos)
+{
+    if ( coords.GetRow() < 0 || coords.GetCol() < 0 )
     {
-        DisableCellEditControl();
-        if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_CLICK,
-                         coords.GetRow(),
-                         coords.GetCol(),
-                         event ) )
-        {
-            // no default action at the moment
-        }
+        // out of grid cell area
+        ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
+        return;
     }
 
-    // ------------ Right double click
+    int dragRow = YToEdgeOfRow( pos.y );
+    int dragCol = XToEdgeOfCol( pos.x );
+
+    // Dragging on the corner of a cell to resize in both
+    // directions is not implemented yet...
     //
-    else if ( event.RightDClick() && coords != wxGridNoCellCoords )
+    if ( dragRow >= 0 && dragCol >= 0 )
     {
-        DisableCellEditControl();
-        if ( !SendEvent( wxEVT_GRID_CELL_RIGHT_DCLICK,
-                         coords.GetRow(),
-                         coords.GetCol(),
-                         event ) )
+        ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
+        return;
+    }
+
+    if ( dragRow >= 0 )
+    {
+        m_dragRowOrCol = dragRow;
+
+        if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
         {
-            // no default action at the moment
+            if ( CanDragRowSize() && CanDragGridSize() )
+                ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW, NULL, false);
         }
     }
+    // When using the native header window we can only resize the columns by
+    // dragging the dividers in it because we can't make it enter into the
+    // column resizing mode programmatically
+    else if ( dragCol >= 0 && !m_useNativeHeader )
+    {
+        m_dragRowOrCol = dragCol;
 
-    // ------------ Moving and no button action
-    //
-    else if ( event.Moving() && !event.IsButton() )
+        if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
+        {
+            if ( CanDragColSize() && CanDragGridSize() )
+                ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL, NULL, false);
+        }
+    }
+    else // Neither on a row or col edge
     {
-        if ( coords.GetRow() < 0 || coords.GetCol() < 0 )
+        if ( m_cursorMode != WXGRID_CURSOR_SELECT_CELL )
         {
-            // out of grid cell area
             ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
-            return;
         }
+    }
+}
 
-        int dragRow = YToEdgeOfRow( y );
-        int dragCol = XToEdgeOfCol( x );
+void wxGrid::ProcessGridCellMouseEvent(wxMouseEvent& event)
+{
+    const wxPoint pos = CalcUnscrolledPosition(event.GetPosition());
 
-        // Dragging on the corner of a cell to resize in both
-        // directions is not implemented yet...
-        //
-        if ( dragRow >= 0 && dragCol >= 0 )
-        {
-            ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
-            return;
-        }
+    // coordinates of the cell under mouse
+    wxGridCellCoords coords = XYToCell(pos);
 
-        if ( dragRow >= 0 )
-        {
-            m_dragRowOrCol = dragRow;
+    int cell_rows, cell_cols;
+    GetCellSize( coords.GetRow(), coords.GetCol(), &cell_rows, &cell_cols );
+    if ( (cell_rows < 0) || (cell_cols < 0) )
+    {
+        coords.SetRow(coords.GetRow() + cell_rows);
+        coords.SetCol(coords.GetCol() + cell_cols);
+    }
 
-            if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
-            {
-                if ( CanDragRowSize() && CanDragGridSize() )
-                    ChangeCursorMode(WXGRID_CURSOR_RESIZE_ROW, NULL, false);
-            }
-        }
-        else if ( dragCol >= 0 )
+    if ( event.Dragging() )
+    {
+        if ( event.LeftIsDown() )
+            DoGridDragEvent(event, coords);
+        else
+            event.Skip();
+        return;
+    }
+
+    m_isDragging = false;
+    m_startDragPos = wxDefaultPosition;
+
+    // VZ: if we do this, the mode is reset to WXGRID_CURSOR_SELECT_CELL
+    //     immediately after it becomes WXGRID_CURSOR_RESIZE_ROW/COL under
+    //     wxGTK
+#if 0
+    if ( event.Entering() || event.Leaving() )
+    {
+        ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
+        m_gridWin->SetCursor( *wxSTANDARD_CURSOR );
+    }
+#endif // 0
+
+    // deal with various button presses
+    if ( event.IsButton() )
+    {
+        if ( coords != wxGridNoCellCoords )
         {
-            m_dragRowOrCol = dragCol;
+            DisableCellEditControl();
 
-            if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
-            {
-                if ( CanDragColSize() && CanDragGridSize() )
-                    ChangeCursorMode(WXGRID_CURSOR_RESIZE_COL, NULL, false);
-            }
+            if ( event.LeftDown() )
+                DoGridCellLeftDown(event, coords, pos);
+            else if ( event.LeftDClick() )
+                DoGridCellLeftDClick(event, coords, pos);
+            else if ( event.RightDown() )
+                SendEvent(wxEVT_GRID_CELL_RIGHT_CLICK, coords, event);
+            else if ( event.RightDClick() )
+                SendEvent(wxEVT_GRID_CELL_RIGHT_DCLICK, coords, event);
         }
-        else // Neither on a row or col edge
+
+        // this one should be called even if we're not over any cell
+        if ( event.LeftUp() )
         {
-            if ( m_cursorMode != WXGRID_CURSOR_SELECT_CELL )
-            {
-                ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
-            }
+            DoGridCellLeftUp(event, coords);
         }
     }
+    else if ( event.Moving() )
+    {
+        DoGridMouseMoveEvent(event, coords, pos);
+    }
+    else // unknown mouse event?
+    {
+        event.Skip();
+    }
 }
 
 void wxGrid::DoEndDragResizeLine(const wxGridOperations& oper)
@@ -6628,6 +6763,8 @@ void wxGrid::DoEndDragResizeLine(const wxGridOperations& oper)
                      wxMax(m_dragLastPos - lineStart,
                            oper.GetMinimalLineSize(this, m_dragRowOrCol)));
 
+    m_dragLastPos = -1;
+
     // refresh now if we're not frozen
     if ( !GetBatchCount() )
     {
@@ -6694,114 +6831,113 @@ void wxGrid::DoEndDragResizeRow()
     DoEndDragResizeLine(wxGridRowOperations());
 }
 
-void wxGrid::DoEndDragResizeCol()
+void wxGrid::DoEndDragResizeCol(wxMouseEvent *event)
 {
     DoEndDragResizeLine(wxGridColumnOperations());
+
+    // Note: we are ending the event *after* doing
+    // default processing in this case
+    //
+    if ( event )
+        SendEvent( wxEVT_GRID_COL_SIZE, -1, m_dragRowOrCol, *event );
+    else
+        SendEvent( wxEVT_GRID_COL_SIZE, -1, m_dragRowOrCol );
 }
 
-void wxGrid::DoEndDragMoveCol()
+void wxGrid::DoStartMoveCol(int col)
 {
-    //The user clicked on the column but didn't actually drag
-    if ( m_dragLastPos < 0 )
-    {
-        m_colLabelWin->Refresh();   //Do this to "unpress" the column
-        return;
-    }
+    m_dragRowOrCol = col;
+}
 
-    int newPos;
-    if ( m_moveToCol == -1 )
-        newPos = m_numCols - 1;
-    else
-    {
-        newPos = GetColPos( m_moveToCol );
-        if ( newPos > GetColPos( m_dragRowOrCol ) )
-            newPos--;
-    }
+void wxGrid::DoEndMoveCol(int pos)
+{
+    wxASSERT_MSG( m_dragRowOrCol != -1, "no matching DoStartMoveCol?" );
+
+    if ( SendEvent(wxEVT_GRID_COL_MOVE, -1, m_dragRowOrCol) != -1 )
+        SetColPos(m_dragRowOrCol, pos);
+    //else: vetoed by user
 
-    SetColPos( m_dragRowOrCol, newPos );
+    m_dragRowOrCol = -1;
 }
 
-void wxGrid::SetColPos( int colID, int newPos )
+void wxGrid::RefreshAfterColPosChange()
 {
-    if ( m_colAt.IsEmpty() )
+    // recalculate the column rights as the column positions have changed,
+    // unless we calculate them dynamically because all columns widths are the
+    // same and it's easy to do
+    if ( !m_colWidths.empty() )
     {
-        m_colAt.Alloc( m_numCols );
-
-        int i;
-        for ( i = 0; i < m_numCols; i++ )
+        int colRight = 0;
+        for ( int colPos = 0; colPos < m_numCols; colPos++ )
         {
-            m_colAt.Add( i );
+            int colID = GetColAt( colPos );
+
+            colRight += m_colWidths[colID];
+            m_colRights[colID] = colRight;
         }
     }
 
-    int oldPos = GetColPos( colID );
-
-    //Reshuffle the m_colAt array
-    if ( newPos > oldPos )
+    // and make the changes visible
+    if ( m_useNativeHeader )
     {
-        int i;
-        for ( i = oldPos; i < newPos; i++ )
-        {
-            m_colAt[i] = m_colAt[i+1];
-        }
+        if ( m_colAt.empty() )
+            GetGridColHeader()->ResetColumnsOrder();
+        else
+            GetGridColHeader()->SetColumnsOrder(m_colAt);
     }
     else
     {
-        int i;
-        for ( i = oldPos; i > newPos; i-- )
-        {
-            m_colAt[i] = m_colAt[i-1];
-        }
+        m_colWindow->Refresh();
     }
+    m_gridWin->Refresh();
+}
 
-    m_colAt[newPos] = colID;
+void wxGrid::SetColumnsOrder(const wxArrayInt& order)
+{
+    m_colAt = order;
 
-    //Recalculate the column rights
-    if ( !m_colWidths.IsEmpty() )
-    {
-        int colRight = 0;
-        int colPos;
-        for ( colPos = 0; colPos < m_numCols; colPos++ )
-        {
-            int colID = GetColAt( colPos );
+    RefreshAfterColPosChange();
+}
 
-            colRight += m_colWidths[colID];
-            m_colRights[colID] = colRight;
-        }
+void wxGrid::SetColPos(int idx, int pos)
+{
+    // we're going to need m_colAt now, initialize it if needed
+    if ( m_colAt.empty() )
+    {
+        m_colAt.reserve(m_numCols);
+        for ( int i = 0; i < m_numCols; i++ )
+            m_colAt.push_back(i);
     }
 
-    m_colLabelWin->Refresh();
-    m_gridWin->Refresh();
+    wxHeaderCtrl::MoveColumnInOrderArray(m_colAt, idx, pos);
+
+    RefreshAfterColPosChange();
 }
 
+void wxGrid::ResetColPos()
+{
+    m_colAt.clear();
 
+    RefreshAfterColPosChange();
+}
 
 void wxGrid::EnableDragColMove( bool enable )
 {
     if ( m_canDragColMove == enable )
         return;
 
-    m_canDragColMove = enable;
-
-    if ( !m_canDragColMove )
+    if ( m_useNativeHeader )
     {
-        m_colAt.Clear();
+        // update all columns to make them [not] reorderable
+        GetGridColHeader()->SetColumnCount(m_numCols);
+    }
 
-        //Recalculate the column rights
-        if ( !m_colWidths.IsEmpty() )
-        {
-            int colRight = 0;
-            int colPos;
-            for ( colPos = 0; colPos < m_numCols; colPos++ )
-            {
-                colRight += m_colWidths[colPos];
-                m_colRights[colPos] = colRight;
-            }
-        }
+    m_canDragColMove = enable;
 
-        m_colLabelWin->Refresh();
-        m_gridWin->Refresh();
-    }
+    // we use to call ResetColPos() from here if !enable but this doesn't seem
+    // right as it would mean there would be no way to "freeze" the current
+    // columns order by disabling moving them after putting them in the desired
+    // order, whereas now you can always call ResetColPos() manually if needed
 }
 
 
@@ -6883,12 +7019,14 @@ wxGrid::DoAppendLines(bool (wxGridTableBase::*funcAppend)(size_t),
 // ----- event handlers
 //
 
-// Generate a grid event based on a mouse event and
-// return the result of ProcessEvent()
-//
-int wxGrid::SendEvent( const wxEventType type,
-                        int row, int col,
-                        wxMouseEvent& mouseEv )
+// Generate a grid event based on a mouse event and return:
+//  -1 if the event was vetoed
+//  +1 if the event was processed (but not vetoed)
+//   0 if the event wasn't handled
+int
+wxGrid::SendEvent(const wxEventType type,
+                  int row, int col,
+                  wxMouseEvent& mouseEv)
 {
    bool claimed, vetoed;
 
@@ -6902,10 +7040,7 @@ int wxGrid::SendEvent( const wxEventType type,
                rowOrCol,
                mouseEv.GetX() + GetRowLabelSize(),
                mouseEv.GetY() + GetColLabelSize(),
-               mouseEv.ControlDown(),
-               mouseEv.ShiftDown(),
-               mouseEv.AltDown(),
-               mouseEv.MetaDown() );
+               mouseEv);
 
        claimed = GetEventHandler()->ProcessEvent(gridEvt);
        vetoed = !gridEvt.IsAllowed();
@@ -6916,13 +7051,10 @@ int wxGrid::SendEvent( const wxEventType type,
        wxGridRangeSelectEvent gridEvt( GetId(),
                type,
                this,
-               m_selectingTopLeft,
-               m_selectingBottomRight,
+               m_selectedBlockTopLeft,
+               m_selectedBlockBottomRight,
                true,
-               mouseEv.ControlDown(),
-               mouseEv.ShiftDown(),
-               mouseEv.AltDown(),
-               mouseEv.MetaDown() );
+               mouseEv);
 
        claimed = GetEventHandler()->ProcessEvent(gridEvt);
        vetoed = !gridEvt.IsAllowed();
@@ -6946,10 +7078,7 @@ int wxGrid::SendEvent( const wxEventType type,
                pos.x,
                pos.y,
                false,
-               mouseEv.ControlDown(),
-               mouseEv.ShiftDown(),
-               mouseEv.AltDown(),
-               mouseEv.MetaDown() );
+               mouseEv);
        claimed = GetEventHandler()->ProcessEvent(gridEvt);
        vetoed = !gridEvt.IsAllowed();
    }
@@ -6962,10 +7091,7 @@ int wxGrid::SendEvent( const wxEventType type,
                mouseEv.GetX() + GetRowLabelSize(),
                mouseEv.GetY() + GetColLabelSize(),
                false,
-               mouseEv.ControlDown(),
-               mouseEv.ShiftDown(),
-               mouseEv.AltDown(),
-               mouseEv.MetaDown() );
+               mouseEv);
        claimed = GetEventHandler()->ProcessEvent(gridEvt);
        vetoed = !gridEvt.IsAllowed();
    }
@@ -6977,11 +7103,9 @@ int wxGrid::SendEvent( const wxEventType type,
    return claimed ? 1 : 0;
 }
 
-// Generate a grid event of specified type and return the result
-// of ProcessEvent().
+// Generate a grid event of specified type, return value same as above
 //
-int wxGrid::SendEvent( const wxEventType type,
-                        int row, int col )
+int wxGrid::SendEvent(const wxEventType type, int row, int col)
 {
    bool claimed, vetoed;
 
@@ -7077,7 +7201,7 @@ void wxGrid::Refresh(bool eraseb, const wxRect* rect)
             if ( width_cell > 0 && height_label > 0 )
             {
                 wxRect anotherrect(x, rect_y, width_cell, height_label);
-                m_colLabelWin->Refresh(eraseb, &anotherrect);
+                m_colWindow->Refresh(eraseb, &anotherrect);
             }
 
             // Paint row labels part intersecting rect.
@@ -7097,7 +7221,7 @@ void wxGrid::Refresh(bool eraseb, const wxRect* rect)
         else
         {
             m_cornerLabelWin->Refresh(eraseb, NULL);
-            m_colLabelWin->Refresh(eraseb, NULL);
+            m_colWindow->Refresh(eraseb, NULL);
             m_rowLabelWin->Refresh(eraseb, NULL);
             m_gridWin->Refresh(eraseb, NULL);
         }
@@ -7224,8 +7348,7 @@ void wxGrid::OnKeyDown( wxKeyEvent& event )
             case WXK_HOME:
                 if ( event.ControlDown() )
                 {
-                    MakeCellVisible( 0, 0 );
-                    SetCurrentCell( 0, 0 );
+                    GoToCell(0, 0);
                 }
                 else
                 {
@@ -7236,8 +7359,7 @@ void wxGrid::OnKeyDown( wxKeyEvent& event )
             case WXK_END:
                 if ( event.ControlDown() )
                 {
-                    MakeCellVisible( m_numRows - 1, m_numCols - 1 );
-                    SetCurrentCell( m_numRows - 1, m_numCols - 1 );
+                    GoToCell(m_numRows - 1, m_numCols - 1);
                 }
                 else
                 {
@@ -7299,26 +7421,21 @@ void wxGrid::OnKeyUp( wxKeyEvent& event )
     //
     if ( event.GetKeyCode() == WXK_SHIFT )
     {
-        if ( m_selectingTopLeft != wxGridNoCellCoords &&
-             m_selectingBottomRight != wxGridNoCellCoords )
+        if ( m_selectedBlockTopLeft != wxGridNoCellCoords &&
+             m_selectedBlockBottomRight != wxGridNoCellCoords )
         {
             if ( m_selection )
             {
                 m_selection->SelectBlock(
-                    m_selectingTopLeft.GetRow(),
-                    m_selectingTopLeft.GetCol(),
-                    m_selectingBottomRight.GetRow(),
-                    m_selectingBottomRight.GetCol(),
-                    event.ControlDown(),
-                    true,
-                    event.AltDown(),
-                    event.MetaDown() );
+                    m_selectedBlockTopLeft,
+                    m_selectedBlockBottomRight,
+                    event);
             }
         }
 
-        m_selectingTopLeft = wxGridNoCellCoords;
-        m_selectingBottomRight = wxGridNoCellCoords;
-        m_selectingKeyboard = wxGridNoCellCoords;
+        m_selectedBlockTopLeft = wxGridNoCellCoords;
+        m_selectedBlockBottomRight = wxGridNoCellCoords;
+        m_selectedBlockCorner = wxGridNoCellCoords;
     }
 }
 
@@ -7367,12 +7484,12 @@ void wxGrid::OnEraseBackground(wxEraseEvent&)
 {
 }
 
-void wxGrid::SetCurrentCell( const wxGridCellCoords& coords )
+bool wxGrid::SetCurrentCell( const wxGridCellCoords& coords )
 {
-    if ( SendEvent( wxEVT_GRID_SELECT_CELL, coords.GetRow(), coords.GetCol() ) )
+    if ( SendEvent(wxEVT_GRID_SELECT_CELL, coords) == -1 )
     {
-        // the event has been intercepted - do nothing
-        return;
+        // the event has been vetoed - do nothing
+        return false;
     }
 
 #if !defined(__WXMAC__)
@@ -7417,35 +7534,62 @@ void wxGrid::SetCurrentCell( const wxGridCellCoords& coords )
     DrawCellHighlight( dc, attr );
 #endif
     attr->DecRef();
+
+    return true;
 }
 
-void wxGrid::HighlightBlock(int topRow, int leftCol, int bottomRow, int rightCol)
+void
+wxGrid::UpdateBlockBeingSelected(int topRow, int leftCol,
+                                 int bottomRow, int rightCol)
 {
-    wxGridCellCoords updateTopLeft, updateBottomRight;
-
     if ( m_selection )
     {
-        if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectRows )
-        {
-            leftCol = 0;
-            rightCol = GetNumberCols() - 1;
-        }
-        else if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectColumns )
+        switch ( m_selection->GetSelectionMode() )
         {
-            topRow = 0;
-            bottomRow = GetNumberRows() - 1;
+            default:
+                wxFAIL_MSG( "unknown selection mode" );
+                // fall through
+
+            case wxGridSelectCells:
+                // arbitrary blocks selection allowed so just use the cell
+                // coordinates as is
+                break;
+
+            case wxGridSelectRows:
+                // only full rows selection allowd, ensure that we do select
+                // full rows
+                leftCol = 0;
+                rightCol = GetNumberCols() - 1;
+                break;
+
+            case wxGridSelectColumns:
+                // same as above but for columns
+                topRow = 0;
+                bottomRow = GetNumberRows() - 1;
+                break;
+
+            case wxGridSelectRowsOrColumns:
+                // in this mode we can select only full rows or full columns so
+                // it doesn't make sense to select blocks at all (and we can't
+                // extend the block because there is no preferred direction, we
+                // could only extend it to cover the entire grid but this is
+                // not useful)
+                return;
         }
     }
 
+    m_selectedBlockCorner = wxGridCellCoords(bottomRow, rightCol);
+    MakeCellVisible(m_selectedBlockCorner);
+
     EnsureFirstLessThanSecond(topRow, bottomRow);
     EnsureFirstLessThanSecond(leftCol, rightCol);
 
-    updateTopLeft = wxGridCellCoords( topRow, leftCol );
-    updateBottomRight = wxGridCellCoords( bottomRow, rightCol );
+    wxGridCellCoords updateTopLeft = wxGridCellCoords(topRow, leftCol),
+                     updateBottomRight = wxGridCellCoords(bottomRow, rightCol);
 
     // First the case that we selected a completely new area
-    if ( m_selectingTopLeft == wxGridNoCellCoords ||
-         m_selectingBottomRight == wxGridNoCellCoords )
+    if ( m_selectedBlockTopLeft == wxGridNoCellCoords ||
+         m_selectedBlockBottomRight == wxGridNoCellCoords )
     {
         wxRect rect;
         rect = BlockToDeviceRect( wxGridCellCoords ( topRow, leftCol ),
@@ -7454,8 +7598,8 @@ void wxGrid::HighlightBlock(int topRow, int leftCol, int bottomRow, int rightCol
     }
 
     // Now handle changing an existing selection area.
-    else if ( m_selectingTopLeft != updateTopLeft ||
-              m_selectingBottomRight != updateBottomRight )
+    else if ( m_selectedBlockTopLeft != updateTopLeft ||
+              m_selectedBlockBottomRight != updateBottomRight )
     {
         // Compute two optimal update rectangles:
         // Either one rectangle is a real subset of the
@@ -7469,10 +7613,10 @@ void wxGrid::HighlightBlock(int topRow, int leftCol, int bottomRow, int rightCol
         int     i;
 
         // Store intermediate values
-        wxCoord oldLeft = m_selectingTopLeft.GetCol();
-        wxCoord oldTop = m_selectingTopLeft.GetRow();
-        wxCoord oldRight = m_selectingBottomRight.GetCol();
-        wxCoord oldBottom = m_selectingBottomRight.GetRow();
+        wxCoord oldLeft = m_selectedBlockTopLeft.GetCol();
+        wxCoord oldTop = m_selectedBlockTopLeft.GetRow();
+        wxCoord oldRight = m_selectedBlockBottomRight.GetCol();
+        wxCoord oldBottom = m_selectedBlockBottomRight.GetRow();
 
         // Determine the outer/inner coordinates.
         EnsureFirstLessThanSecond(oldLeft, leftCol);
@@ -7531,8 +7675,8 @@ void wxGrid::HighlightBlock(int topRow, int leftCol, int bottomRow, int rightCol
     }
 
     // change selection
-    m_selectingTopLeft = updateTopLeft;
-    m_selectingBottomRight = updateBottomRight;
+    m_selectedBlockTopLeft = updateTopLeft;
+    m_selectedBlockBottomRight = updateBottomRight;
 }
 
 //
@@ -7908,7 +8052,7 @@ void wxGrid::DrawHighlight(wxDC& dc, const wxGridCellCoordsArray& cells)
 //
 void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) )
 {
-    if ( !m_gridLinesEnabled || !m_numRows || !m_numCols )
+    if ( !m_gridLinesEnabled )
          return;
 
     int top, bottom, left, right;
@@ -7919,9 +8063,25 @@ void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) )
     CalcUnscrolledPosition( cw, ch, &right, &bottom );
 
     // avoid drawing grid lines past the last row and col
-    //
-    right = wxMin( right, GetColRight(GetColAt( m_numCols - 1 )) );
-    bottom = wxMin( bottom, GetRowBottom(m_numRows - 1) );
+    if ( m_gridLinesClipHorz )
+    {
+        if ( !m_numCols )
+            return;
+
+        const int lastColRight = GetColRight(GetColAt(m_numCols - 1));
+        if ( right > lastColRight )
+            right = lastColRight;
+    }
+
+    if ( m_gridLinesClipVert )
+    {
+        if ( !m_numRows )
+            return;
+
+        const int lastRowBottom = GetRowBottom(m_numRows - 1);
+        if ( bottom > lastRowBottom )
+            bottom = lastRowBottom;
+    }
 
     // no gridlines inside multicells, clip them out
     int leftCol = GetColPos( internalXToCol(left) );
@@ -8043,8 +8203,26 @@ void wxGrid::DrawRowLabel( wxDC& dc, int row )
     DrawTextRectangle( dc, GetRowLabelValue( row ), rect, hAlign, vAlign );
 }
 
+void wxGrid::UseNativeColHeader(bool native)
+{
+    if ( native == m_useNativeHeader )
+        return;
+
+    delete m_colWindow;
+    m_useNativeHeader = native;
+
+    CreateColumnWindow();
+
+    if ( m_useNativeHeader )
+        GetGridColHeader()->SetColumnCount(m_numCols);
+    CalcWindowSizes();
+}
+
 void wxGrid::SetUseNativeColLabels( bool native )
 {
+    wxASSERT_MSG( !m_useNativeHeader,
+                  "doesn't make sense when using native header" );
+
     m_nativeColumnLabels = native;
     if (native)
     {
@@ -8052,7 +8230,7 @@ void wxGrid::SetUseNativeColLabels( bool native )
         SetColLabelSize( height );
     }
 
-    m_colLabelWin->Refresh();
+    GetColLabelWindow()->Refresh();
     m_cornerLabelWin->Refresh();
 }
 
@@ -8104,7 +8282,18 @@ void wxGrid::DrawColLabel(wxDC& dc, int col)
 
     if ( m_nativeColumnLabels )
     {
-        wxRendererNative::Get().DrawHeaderButton(m_colLabelWin, dc, rect, 0);
+        wxRendererNative::Get().DrawHeaderButton
+                                (
+                                    GetColLabelWindow(),
+                                    dc,
+                                    rect,
+                                    0,
+                                    IsSortingBy(col)
+                                        ? IsSortOrderAscending()
+                                            ? wxHDR_SORT_ICON_UP
+                                            : wxHDR_SORT_ICON_DOWN
+                                        : wxHDR_SORT_ICON_NONE
+                                );
     }
     else
     {
@@ -8320,7 +8509,7 @@ void wxGrid::EndBatch()
         {
             CalcDimensions();
             m_rowLabelWin->Refresh();
-            m_colLabelWin->Refresh();
+            m_colWindow->Refresh();
             m_cornerLabelWin->Refresh();
             m_gridWin->Refresh();
         }
@@ -8371,7 +8560,7 @@ void wxGrid::EnableCellEditControl( bool enable )
     {
         if ( enable )
         {
-            if (SendEvent( wxEVT_GRID_EDITOR_SHOWN) <0)
+            if ( SendEvent(wxEVT_GRID_EDITOR_SHOWN) == -1 )
                 return;
 
             // this should be checked by the caller!
@@ -8385,7 +8574,7 @@ void wxGrid::EnableCellEditControl( bool enable )
         else
         {
             //FIXME:add veto support
-            SendEvent( wxEVT_GRID_EDITOR_HIDDEN );
+            SendEvent(wxEVT_GRID_EDITOR_HIDDEN);
 
             HideCellEditControl();
             SaveEditControlValue();
@@ -8624,9 +8813,7 @@ void wxGrid::SaveEditControlValue()
 
         if (changed)
         {
-            if ( SendEvent( wxEVT_GRID_CELL_CHANGE,
-                       m_currentCellCoords.GetRow(),
-                       m_currentCellCoords.GetCol() ) < 0 )
+            if ( SendEvent(wxEVT_GRID_CELL_CHANGE) == -1 )
             {
                 // Event has been vetoed, set the data back.
                 SetCellValue(row, col, oldval);
@@ -8642,34 +8829,27 @@ void wxGrid::SaveEditControlValue()
 //  coordinates for mouse events etc.
 //
 
-void wxGrid::XYToCell( int x, int y, wxGridCellCoords& coords ) const
+wxGridCellCoords wxGrid::XYToCell(int x, int y) const
 {
     int row = YToRow(y);
     int col = XToCol(x);
 
-    if ( row == -1 || col == -1 )
-    {
-        coords = wxGridNoCellCoords;
-    }
-    else
-    {
-        coords.Set( row, col );
-    }
+    return row == -1 || col == -1 ? wxGridNoCellCoords
+                                  : wxGridCellCoords(row, col);
 }
 
 // compute row or column from some (unscrolled) coordinate value, using either
 // m_defaultRowHeight/m_defaultColWidth or binary search on array of
 // m_rowBottoms/m_colRights to do it quickly (linear search shouldn't be used
 // for large grids)
-int
-wxGrid::PosToLine(int coord,
-                  bool clipToMinMax,
-                  const wxGridOperations& oper) const
+int wxGrid::PosToLinePos(int coord,
+                         bool clipToMinMax,
+                         const wxGridOperations& oper) const
 {
     const int numLines = oper.GetNumberOfLines(this);
 
     if ( coord < 0 )
-        return clipToMinMax && numLines > 0 ? oper.GetLineAt(this, 0) : -1;
+        return clipToMinMax && numLines > 0 ? 0 : wxNOT_FOUND;
 
     const int defaultLineSize = oper.GetDefaultLineSize(this);
     wxCHECK_MSG( defaultLineSize, -1, "can't have 0 default line size" );
@@ -8713,12 +8893,12 @@ wxGrid::PosToLine(int coord,
     // check if the position is beyond the last column
     const int lineAtMaxPos = oper.GetLineAt(this, maxPos);
     if ( coord >= lineEnds[lineAtMaxPos] )
-        return clipToMinMax ? lineAtMaxPos : -1;
+        return clipToMinMax ? maxPos : -1;
 
     // or before the first one
     const int lineAt0 = oper.GetLineAt(this, 0);
     if ( coord < lineEnds[lineAt0] )
-        return lineAt0;
+        return 0;
 
 
     // finally do perform the binary search
@@ -8727,10 +8907,10 @@ wxGrid::PosToLine(int coord,
         wxCHECK_MSG( lineEnds[oper.GetLineAt(this, minPos)] <= coord &&
                         coord < lineEnds[oper.GetLineAt(this, maxPos)],
                      -1,
-                     "wxGrid: internal error in PosToLine()" );
+                     "wxGrid: internal error in PosToLinePos()" );
 
         if ( coord >= lineEnds[oper.GetLineAt(this, maxPos - 1)] )
-            return oper.GetLineAt(this, maxPos);
+            return maxPos;
         else
             maxPos--;
 
@@ -8741,7 +8921,17 @@ wxGrid::PosToLine(int coord,
             minPos = median;
     }
 
-    return oper.GetLineAt(this, maxPos);
+    return maxPos;
+}
+
+int
+wxGrid::PosToLine(int coord,
+                  bool clipToMinMax,
+                  const wxGridOperations& oper) const
+{
+    int pos = PosToLinePos(coord, clipToMinMax, oper);
+
+    return pos == wxNOT_FOUND ? wxNOT_FOUND : oper.GetLineAt(this, pos);
 }
 
 int wxGrid::YToRow(int y, bool clipToMinMax) const
@@ -8754,6 +8944,11 @@ int wxGrid::XToCol(int x, bool clipToMinMax) const
     return PosToLine(x, clipToMinMax, wxGridColumnOperations());
 }
 
+int wxGrid::XToPos(int x) const
+{
+    return PosToLinePos(x, true /* clip */, wxGridColumnOperations());
+}
+
 // return the row number that that the y coord is near the edge of, or -1 if
 // not near an edge.
 //
@@ -8957,28 +9152,28 @@ wxGrid::DoMoveCursor(bool expandSelection,
 
     if ( expandSelection )
     {
-        if ( m_selectingKeyboard == wxGridNoCellCoords )
-            m_selectingKeyboard = m_currentCellCoords;
+        wxGridCellCoords coords = m_selectedBlockCorner;
+        if ( coords == wxGridNoCellCoords )
+            coords = m_currentCellCoords;
 
-        if ( diroper.IsAtBoundary(m_selectingKeyboard) )
+        if ( diroper.IsAtBoundary(coords) )
             return false;
 
-        diroper.Advance(m_selectingKeyboard);
+        diroper.Advance(coords);
 
-        MakeCellVisible(m_selectingKeyboard);
-        HighlightBlock(m_currentCellCoords, m_selectingKeyboard);
+        UpdateBlockBeingSelected(m_currentCellCoords, coords);
     }
-    else
+    else // don't expand selection
     {
+        ClearSelection();
+
         if ( diroper.IsAtBoundary(m_currentCellCoords) )
             return false;
 
-        ClearSelection();
-
         wxGridCellCoords coords = m_currentCellCoords;
         diroper.Advance(coords);
-        MakeCellVisible(coords);
-        SetCurrentCell(coords);
+
+        GoToCell(coords);
     }
 
     return true;
@@ -9025,8 +9220,7 @@ bool wxGrid::DoMoveCursorByPage(const wxGridDirectionOperations& diroper)
         newRow = coords.GetRow();
     }
 
-    MakeCellVisible(newRow, m_currentCellCoords.GetCol());
-    SetCurrentCell(newRow, m_currentCellCoords.GetCol());
+    GoToCell(newRow, m_currentCellCoords.GetCol());
 
     return true;
 }
@@ -9040,7 +9234,7 @@ bool wxGrid::MovePageUp()
 bool wxGrid::MovePageDown()
 {
     return DoMoveCursorByPage(
-                wxGridForwardOperations(this, wxGridColumnOperations()));
+                wxGridForwardOperations(this, wxGridRowOperations()));
 }
 
 // helper of DoMoveCursorByBlock(): advance the cell coordinates using diroper
@@ -9097,16 +9291,14 @@ wxGrid::DoMoveCursorByBlock(bool expandSelection,
         }
     }
 
-    MakeCellVisible(coords);
     if ( expandSelection )
     {
-        m_selectingKeyboard = coords;
-        HighlightBlock(m_currentCellCoords, m_selectingKeyboard);
+        UpdateBlockBeingSelected(m_currentCellCoords, coords);
     }
     else
     {
         ClearSelection();
-        SetCurrentCell(coords);
+        GoToCell(coords);
     }
 
     return true;
@@ -9239,12 +9431,12 @@ void wxGrid::SetColLabelSize( int height )
     {
         if ( height == 0 )
         {
-            m_colLabelWin->Show( false );
+            m_colWindow->Show( false );
             m_cornerLabelWin->Show( false );
         }
         else if ( m_colLabelHeight == 0 )
         {
-            m_colLabelWin->Show( true );
+            m_colWindow->Show( true );
             if ( m_rowLabelWidth > 0 )
                 m_cornerLabelWin->Show( true );
         }
@@ -9261,13 +9453,13 @@ void wxGrid::SetLabelBackgroundColour( const wxColour& colour )
     {
         m_labelBackgroundColour = colour;
         m_rowLabelWin->SetBackgroundColour( colour );
-        m_colLabelWin->SetBackgroundColour( colour );
+        m_colWindow->SetBackgroundColour( colour );
         m_cornerLabelWin->SetBackgroundColour( colour );
 
         if ( !GetBatchCount() )
         {
             m_rowLabelWin->Refresh();
-            m_colLabelWin->Refresh();
+            m_colWindow->Refresh();
             m_cornerLabelWin->Refresh();
         }
     }
@@ -9281,7 +9473,7 @@ void wxGrid::SetLabelTextColour( const wxColour& colour )
         if ( !GetBatchCount() )
         {
             m_rowLabelWin->Refresh();
-            m_colLabelWin->Refresh();
+            m_colWindow->Refresh();
         }
     }
 }
@@ -9292,7 +9484,7 @@ void wxGrid::SetLabelFont( const wxFont& font )
     if ( !GetBatchCount() )
     {
         m_rowLabelWin->Refresh();
-        m_colLabelWin->Refresh();
+        m_colWindow->Refresh();
     }
 }
 
@@ -9358,7 +9550,7 @@ void wxGrid::SetColLabelAlignment( int horiz, int vert )
 
     if ( !GetBatchCount() )
     {
-        m_colLabelWin->Refresh();
+        m_colWindow->Refresh();
     }
 }
 
@@ -9375,7 +9567,7 @@ void wxGrid::SetColLabelTextOrientation( int textOrientation )
         m_colLabelTextOrientation = textOrientation;
 
     if ( !GetBatchCount() )
-        m_colLabelWin->Refresh();
+        m_colWindow->Refresh();
 }
 
 void wxGrid::SetRowLabelValue( int row, const wxString& s )
@@ -9404,13 +9596,20 @@ void wxGrid::SetColLabelValue( int col, const wxString& s )
         m_table->SetColLabelValue( col, s );
         if ( !GetBatchCount() )
         {
-            wxRect rect = CellToRect( 0, col );
-            if ( rect.width > 0 )
+            if ( m_useNativeHeader )
             {
-                CalcScrolledPosition(rect.x, 0, &rect.x, &rect.y);
-                rect.y = 0;
-                rect.height = m_colLabelHeight;
-                m_colLabelWin->Refresh( true, &rect );
+                GetGridColHeader()->UpdateColumn(col);
+            }
+            else
+            {
+                wxRect rect = CellToRect( 0, col );
+                if ( rect.width > 0 )
+                {
+                    CalcScrolledPosition(rect.x, 0, &rect.x, &rect.y);
+                    rect.y = 0;
+                    rect.height = m_colLabelHeight;
+                    GetColLabelWindow()->Refresh( true, &rect );
+                }
             }
         }
     }
@@ -9422,9 +9621,8 @@ void wxGrid::SetGridLineColour( const wxColour& colour )
     {
         m_gridLineColour = colour;
 
-        wxClientDC dc( m_gridWin );
-        PrepareDC( dc );
-        DrawAllGridLines( dc, wxRegion() );
+        if ( GridLinesEnabled() )
+            RedrawGridLines();
     }
 }
 
@@ -9479,25 +9677,42 @@ void wxGrid::SetCellHighlightROPenWidth(int width)
     }
 }
 
+void wxGrid::RedrawGridLines()
+{
+    // the lines will be redrawn when the window is thawn
+    if ( GetBatchCount() )
+        return;
+
+    if ( GridLinesEnabled() )
+    {
+        wxClientDC dc( m_gridWin );
+        PrepareDC( dc );
+        DrawAllGridLines( dc, wxRegion() );
+    }
+    else // remove the grid lines
+    {
+        m_gridWin->Refresh();
+    }
+}
+
 void wxGrid::EnableGridLines( bool enable )
 {
     if ( enable != m_gridLinesEnabled )
     {
         m_gridLinesEnabled = enable;
 
-        if ( !GetBatchCount() )
-        {
-            if ( enable )
-            {
-                wxClientDC dc( m_gridWin );
-                PrepareDC( dc );
-                DrawAllGridLines( dc, wxRegion() );
-            }
-            else
-            {
-                m_gridWin->Refresh();
-            }
-        }
+        RedrawGridLines();
+    }
+}
+
+void wxGrid::DoClipGridLines(bool& var, bool clip)
+{
+    if ( clip != var )
+    {
+        var = clip;
+
+        if ( GridLinesEnabled() )
+            RedrawGridLines();
     }
 }
 
@@ -10195,7 +10410,7 @@ void wxGrid::SetColSize( int col, int width )
     {
         long w, h;
         wxArrayString lines;
-        wxClientDC dc(m_colLabelWin);
+        wxClientDC dc(m_colWindow);
         dc.SetFont(GetLabelFont());
         StringToLines(GetColLabelValue(col), lines);
         if ( GetColLabelTextOrientation() == wxHORIZONTAL )
@@ -10207,15 +10422,12 @@ void wxGrid::SetColSize( int col, int width )
         width = wxMax(width, GetColMinimalAcceptableWidth());
     }
 
-    // should we check that it's bigger than GetColMinimalWidth(col) here?
-    //                                                                 (VZ)
-    // No, because it is reasonable to assume the library user know's
-    // what he is doing. However we should test against the weaker
-    // constraint of minimalAcceptableWidth, as this breaks rendering
-    //
-    // This test then fixes sf.net bug #645734
-
-    if ( width < GetColMinimalAcceptableWidth() )
+    // we intentionally don't test whether the width is less than
+    // GetColMinimalWidth() here but we do compare it with
+    // GetColMinimalAcceptableWidth() as otherwise things currently break (see
+    // #651) -- and we also always allow the width of 0 as it has the special
+    // sense of hiding the column
+    if ( width > 0 && width < GetColMinimalAcceptableWidth() )
         return;
 
     if ( m_colWidths.IsEmpty() )
@@ -10224,9 +10436,11 @@ void wxGrid::SetColSize( int col, int width )
         InitColWidths();
     }
 
-    int w = wxMax( 0, width );
-    int diff = w - m_colWidths[col];
-    m_colWidths[col] = w;
+    const int diff = width - m_colWidths[col];
+    m_colWidths[col] = width;
+    if ( m_useNativeHeader )
+        GetGridColHeader()->UpdateColumn(col);
+    //else: will be refreshed when the header is redrawn
 
     for ( int colPos = GetColPos(col); colPos < m_numCols; colPos++ )
     {
@@ -10234,7 +10448,10 @@ void wxGrid::SetColSize( int col, int width )
     }
 
     if ( !GetBatchCount() )
+    {
         CalcDimensions();
+        Refresh();
+    }
 }
 
 void wxGrid::SetColMinimalWidth( int col, int width )
@@ -10387,14 +10604,21 @@ wxGrid::AutoSizeColOrRow(int colOrRow, bool setAsMin, wxGridDirection direction)
         SetColSize( col, extentMax );
         if ( !GetBatchCount() )
         {
-            int cw, ch, dummy;
-            m_gridWin->GetClientSize( &cw, &ch );
-            wxRect rect ( CellToRect( 0, col ) );
-            rect.y = 0;
-            CalcScrolledPosition(rect.x, 0, &rect.x, &dummy);
-            rect.width = cw - rect.x;
-            rect.height = m_colLabelHeight;
-            m_colLabelWin->Refresh( true, &rect );
+            if ( m_useNativeHeader )
+            {
+                GetGridColHeader()->UpdateColumn(col);
+            }
+            else
+            {
+                int cw, ch, dummy;
+                m_gridWin->GetClientSize( &cw, &ch );
+                wxRect rect ( CellToRect( 0, col ) );
+                rect.y = 0;
+                CalcScrolledPosition(rect.x, 0, &rect.x, &dummy);
+                rect.width = cw - rect.x;
+                rect.height = m_colLabelHeight;
+                GetColLabelWindow()->Refresh( true, &rect );
+            }
         }
     }
     else
@@ -10633,31 +10857,36 @@ void wxGrid::SetCellValue( int row, int col, const wxString& s )
 
 void wxGrid::SelectRow( int row, bool addToSelected )
 {
-    if ( IsSelection() && !addToSelected )
+    if ( !m_selection )
+        return;
+
+    if ( !addToSelected )
         ClearSelection();
 
-    if ( m_selection )
-        m_selection->SelectRow( row, false, addToSelected );
+    m_selection->SelectRow(row);
 }
 
 void wxGrid::SelectCol( int col, bool addToSelected )
 {
-    if ( IsSelection() && !addToSelected )
+    if ( !m_selection )
+        return;
+
+    if ( !addToSelected )
         ClearSelection();
 
-    if ( m_selection )
-        m_selection->SelectCol( col, false, addToSelected );
+    m_selection->SelectCol(col);
 }
 
-void wxGrid::SelectBlock( int topRow, int leftCol, int bottomRow, int rightCol,
-                          bool addToSelected )
+void wxGrid::SelectBlock(int topRow, int leftCol, int bottomRow, int rightCol,
+                         bool addToSelected)
 {
-    if ( IsSelection() && !addToSelected )
+    if ( !m_selection )
+        return;
+
+    if ( !addToSelected )
         ClearSelection();
 
-    if ( m_selection )
-        m_selection->SelectBlock( topRow, leftCol, bottomRow, rightCol,
-                                  false, addToSelected );
+    m_selection->SelectBlock(topRow, leftCol, bottomRow, rightCol);
 }
 
 void wxGrid::SelectAll()
@@ -10718,17 +10947,17 @@ void wxGrid::DeselectCell( int row, int col )
 bool wxGrid::IsSelection() const
 {
     return ( m_selection && (m_selection->IsSelection() ||
-             ( m_selectingTopLeft != wxGridNoCellCoords &&
-               m_selectingBottomRight != wxGridNoCellCoords) ) );
+             ( m_selectedBlockTopLeft != wxGridNoCellCoords &&
+               m_selectedBlockBottomRight != wxGridNoCellCoords) ) );
 }
 
 bool wxGrid::IsInSelection( int row, int col ) const
 {
     return ( m_selection && (m_selection->IsInSelection( row, col ) ||
-             ( row >= m_selectingTopLeft.GetRow() &&
-               col >= m_selectingTopLeft.GetCol() &&
-               row <= m_selectingBottomRight.GetRow() &&
-               col <= m_selectingBottomRight.GetCol() )) );
+             ( row >= m_selectedBlockTopLeft.GetRow() &&
+               col >= m_selectedBlockTopLeft.GetCol() &&
+               row <= m_selectedBlockBottomRight.GetRow() &&
+               col <= m_selectedBlockBottomRight.GetCol() )) );
 }
 
 wxGridCellCoordsArray wxGrid::GetSelectedCells() const
@@ -10788,13 +11017,18 @@ wxArrayInt wxGrid::GetSelectedCols() const
 
 void wxGrid::ClearSelection()
 {
-    wxRect r1 = BlockToDeviceRect( m_selectingTopLeft, m_selectingBottomRight);
-    wxRect r2 = BlockToDeviceRect( m_currentCellCoords, m_selectingKeyboard );
-    m_selectingTopLeft =
-    m_selectingBottomRight =
-    m_selectingKeyboard = wxGridNoCellCoords;
+    wxRect r1 = BlockToDeviceRect(m_selectedBlockTopLeft,
+                                  m_selectedBlockBottomRight);
+    wxRect r2 = BlockToDeviceRect(m_currentCellCoords,
+                                  m_selectedBlockCorner);
+
+    m_selectedBlockTopLeft =
+    m_selectedBlockBottomRight =
+    m_selectedBlockCorner = wxGridNoCellCoords;
+
     Refresh( false, &r1 );
     Refresh( false, &r2 );
+
     if ( m_selection )
         m_selection->ClearSelection();
 }
@@ -10948,36 +11182,23 @@ IMPLEMENT_DYNAMIC_CLASS( wxGridEvent, wxNotifyEvent )
 wxGridEvent::wxGridEvent( int id, wxEventType type, wxObject* obj,
                           int row, int col, int x, int y, bool sel,
                           bool control, bool shift, bool alt, bool meta )
-        : wxNotifyEvent( type, id )
+        : wxNotifyEvent( type, id ),
+          wxKeyboardState(control, shift, alt, meta)
 {
-    m_row = row;
-    m_col = col;
-    m_x = x;
-    m_y = y;
-    m_selecting = sel;
-    m_control = control;
-    m_shift = shift;
-    m_alt = alt;
-    m_meta = meta;
+    Init(row, col, x, y, sel);
 
     SetEventObject(obj);
 }
 
-
 IMPLEMENT_DYNAMIC_CLASS( wxGridSizeEvent, wxNotifyEvent )
 
 wxGridSizeEvent::wxGridSizeEvent( int id, wxEventType type, wxObject* obj,
                                   int rowOrCol, int x, int y,
                                   bool control, bool shift, bool alt, bool meta )
-        : wxNotifyEvent( type, id )
+        : wxNotifyEvent( type, id ),
+          wxKeyboardState(control, shift, alt, meta)
 {
-    m_rowOrCol = rowOrCol;
-    m_x = x;
-    m_y = y;
-    m_control = control;
-    m_shift = shift;
-    m_alt = alt;
-    m_meta = meta;
+    Init(rowOrCol, x, y);
 
     SetEventObject(obj);
 }
@@ -10990,15 +11211,10 @@ wxGridRangeSelectEvent::wxGridRangeSelectEvent(int id, wxEventType type, wxObjec
                                                const wxGridCellCoords& bottomRight,
                                                bool sel, bool control,
                                                bool shift, bool alt, bool meta )
-        : wxNotifyEvent( type, id )
-{
-    m_topLeft = topLeft;
-    m_bottomRight = bottomRight;
-    m_selecting = sel;
-    m_control = control;
-    m_shift = shift;
-    m_alt = alt;
-    m_meta = meta;
+        : wxNotifyEvent( type, id ),
+          wxKeyboardState(control, shift, alt, meta)
+{
+    Init(topLeft, bottomRight, sel);
 
     SetEventObject(obj);
 }