]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/grid.cpp
fix crash when the user code refuses to validate the new text when editing the item...
[wxWidgets.git] / src / generic / grid.cpp
index 70a8efaf32cdf9dc2829053a8bf1b20c2ddd39ea..20389dfc4802a7435b0d1f0ae8fe1635a1fb64cf 100644 (file)
@@ -2,7 +2,7 @@
 // Name:        generic/grid.cpp
 // Purpose:     wxGrid and related classes
 // Author:      Michael Bedward (based on code by Julian Smart, Robin Dunn)
-// Modified by:
+// Modified by: Robin Dunn, Vadim Zeitlin
 // Created:     1/08/1999
 // RCS-ID:      $Id$
 // Copyright:   (c) Michael Bedward (mbedward@ozemail.com.au)
@@ -185,7 +185,7 @@ private:
     DECLARE_EVENT_TABLE()
 };
 
-class WXDLLEXPORT wxGridWindow : public wxPanel
+class WXDLLEXPORT wxGridWindow : public wxWindow
 {
 public:
     wxGridWindow()
@@ -388,13 +388,31 @@ wxRect           wxGridNoCellRect( -1, -1, -1, -1 );
 //       The scroll bars may be a little flakey once in a while, but that is
 //       surely much less horrible than having scroll lines of only 1!!!
 //       -- Robin
-static const size_t GRID_SCROLL_LINE = 15;  // 1;
-
+//
+//       Well, it's still seriously broken so it might be better but needs
+//       fixing anyhow
+//       -- Vadim
+static const size_t GRID_SCROLL_LINE_X = 15;  // 1;
+static 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;
 
+// ----------------------------------------------------------------------------
+// private functions
+// ----------------------------------------------------------------------------
+
+static inline int GetScrollX(int x)
+{
+    return (x + GRID_SCROLL_LINE_X - 1) / GRID_SCROLL_LINE_X;
+}
+
+static inline int GetScrollY(int y)
+{
+    return (y + GRID_SCROLL_LINE_Y - 1) / GRID_SCROLL_LINE_Y;
+}
+
 // ============================================================================
 // implementation
 // ============================================================================
@@ -690,73 +708,7 @@ bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent& event)
 
 void wxGridCellTextEditor::StartingKey(wxKeyEvent& event)
 {
-    // we don't check for !HasModifiers() because IsAcceptedKey() did it
-
-    // insert the key in the control
-    wxChar ch;
-    int keycode = event.GetKeyCode();
-    switch ( keycode )
-    {
-        case WXK_NUMPAD0:
-        case WXK_NUMPAD1:
-        case WXK_NUMPAD2:
-        case WXK_NUMPAD3:
-        case WXK_NUMPAD4:
-        case WXK_NUMPAD5:
-        case WXK_NUMPAD6:
-        case WXK_NUMPAD7:
-        case WXK_NUMPAD8:
-        case WXK_NUMPAD9:
-            ch = _T('0') + keycode - WXK_NUMPAD0;
-            break;
-
-        case WXK_MULTIPLY:
-        case WXK_NUMPAD_MULTIPLY:
-            ch = _T('*');
-            break;
-
-        case WXK_ADD:
-        case WXK_NUMPAD_ADD:
-            ch = _T('+');
-            break;
-
-        case WXK_SUBTRACT:
-        case WXK_NUMPAD_SUBTRACT:
-            ch = _T('-');
-            break;
-
-        case WXK_DECIMAL:
-        case WXK_NUMPAD_DECIMAL:
-            ch = _T('.');
-            break;
-
-        case WXK_DIVIDE:
-        case WXK_NUMPAD_DIVIDE:
-            ch = _T('/');
-            break;
-
-        default:
-            if ( keycode < 256 && keycode >= 0 && isprint(keycode) )
-            {
-                // FIXME this is not going to work for non letters...
-                if ( !event.ShiftDown() )
-                {
-                    keycode = tolower(keycode);
-                }
-
-                ch = (wxChar)keycode;
-            }
-            else
-            {
-                ch = _T('\0');
-            }
-    }
-
-    if ( ch )
-    {
-        Text()->AppendText(ch);
-    }
-    else
+    if ( !Text()->EmulateKeyPress(event) )
     {
         event.Skip();
     }
@@ -1880,9 +1832,24 @@ void wxGridCellBoolRenderer::Draw(wxGrid& grid,
 // wxGridCellAttr
 // ----------------------------------------------------------------------------
 
+void wxGridCellAttr::Init(wxGridCellAttr *attrDefault)
+{
+    m_nRef = 1;
+
+    m_isReadOnly = Unset;
+
+    m_renderer = NULL;
+    m_editor = NULL;
+
+    m_attrkind = wxGridCellAttr::Cell;
+
+    SetDefAttr(attrDefault);
+}
+
 wxGridCellAttr *wxGridCellAttr::Clone() const
 {
-    wxGridCellAttr *attr = new wxGridCellAttr;
+    wxGridCellAttr *attr = new wxGridCellAttr(m_defGridAttr);
+
     if ( HasTextColour() )
         attr->SetTextColour(GetTextColour());
     if ( HasBackgroundColour() )
@@ -1908,8 +1875,6 @@ wxGridCellAttr *wxGridCellAttr::Clone() const
 
     attr->SetKind( m_attrkind );
 
-    attr->SetDefAttr(m_defGridAttr);
-
     return attr;
 }
 
@@ -1953,7 +1918,7 @@ const wxColour& wxGridCellAttr::GetTextColour() const
     {
         return m_colText;
     }
-    else if (m_defGridAttr != this)
+    else if (m_defGridAttr && m_defGridAttr != this)
     {
         return m_defGridAttr->GetTextColour();
     }
@@ -1969,7 +1934,7 @@ const wxColour& wxGridCellAttr::GetBackgroundColour() const
 {
     if (HasBackgroundColour())
         return m_colBack;
-    else if (m_defGridAttr != this)
+    else if (m_defGridAttr && m_defGridAttr != this)
         return m_defGridAttr->GetBackgroundColour();
     else
     {
@@ -1983,7 +1948,7 @@ const wxFont& wxGridCellAttr::GetFont() const
 {
     if (HasFont())
         return m_font;
-    else if (m_defGridAttr != this)
+    else if (m_defGridAttr && m_defGridAttr != this)
         return m_defGridAttr->GetFont();
     else
     {
@@ -2000,7 +1965,7 @@ void wxGridCellAttr::GetAlignment(int *hAlign, int *vAlign) const
         if ( hAlign ) *hAlign = m_hAlign;
         if ( vAlign ) *vAlign = m_vAlign;
     }
-    else if (m_defGridAttr != this)
+    else if (m_defGridAttr && m_defGridAttr != this)
         m_defGridAttr->GetAlignment(hAlign, vAlign);
     else
     {
@@ -2018,59 +1983,96 @@ void wxGridCellAttr::GetAlignment(int *hAlign, int *vAlign) const
 
 wxGridCellRenderer* wxGridCellAttr::GetRenderer(wxGrid* grid, int row, int col) const
 {
-    wxGridCellRenderer* renderer = NULL;
+    wxGridCellRenderer *renderer;
 
-    if ( m_defGridAttr != this || grid == NULL )
+    if ( m_renderer && this != m_defGridAttr )
     {
-        renderer = m_renderer;      // use local attribute
-        if ( renderer )
-            renderer->IncRef();
+        // use the cells renderer if it has one
+        renderer = m_renderer;
+        renderer->IncRef();
     }
-
-    if ( !renderer && grid )        // get renderer for the data type
+    else // no non default cell renderer
     {
-        // GetDefaultRendererForCell() will do IncRef() for us
-        renderer = grid->GetDefaultRendererForCell(row, col);
-    }
+        // get default renderer for the data type
+        if ( grid )
+        {
+            // GetDefaultRendererForCell() will do IncRef() for us
+            renderer = grid->GetDefaultRendererForCell(row, col);
+        }
+        else
+        {
+            renderer = NULL;
+        }
 
-    if ( !renderer )
-    {
-        // if we still don't have one then use the grid default
-        // (no need for IncRef() here neither)
-        renderer = m_defGridAttr->GetRenderer(NULL,0,0);
+        if ( !renderer )
+        {
+            if (m_defGridAttr &&  this != m_defGridAttr )
+            {
+                // if we still don't have one then use the grid default
+                // (no need for IncRef() here neither)
+                renderer = m_defGridAttr->GetRenderer(NULL, 0, 0);
+            }
+            else // default grid attr
+            {
+                // use m_renderer which we had decided not to use initially
+                renderer = m_renderer;
+                if ( renderer )
+                    renderer->IncRef();
+            }
+        }
     }
 
-    if ( !renderer)
-    {
-        wxFAIL_MSG(wxT("Missing default cell attribute"));
-    }
+    // we're supposed to always find something
+    wxASSERT_MSG(renderer, wxT("Missing default cell renderer"));
 
     return renderer;
 }
 
+// same as above, except for s/renderer/editor/g
 wxGridCellEditor* wxGridCellAttr::GetEditor(wxGrid* grid, int row, int col) const
 {
-    wxGridCellEditor* editor = NULL;
+    wxGridCellEditor *editor;
 
-    if ( m_defGridAttr != this || grid == NULL )
+    if ( m_editor && this != m_defGridAttr )
     {
-        editor = m_editor;      // use local attribute
-        if ( editor )
-            editor->IncRef();
+        // use the cells editor if it has one
+        editor = m_editor;
+        editor->IncRef();
     }
-
-    if ( !editor && grid )                   // get renderer for the data type
-        editor = grid->GetDefaultEditorForCell(row, col);
-
-    if ( !editor )
-        // if we still don't have one then use the grid default
-        editor = m_defGridAttr->GetEditor(NULL,0,0);
-
-    if ( !editor )
+    else // no non default cell editor
     {
-        wxFAIL_MSG(wxT("Missing default cell attribute"));
+        // get default editor for the data type
+        if ( grid )
+        {
+            // GetDefaultEditorForCell() will do IncRef() for us
+            editor = grid->GetDefaultEditorForCell(row, col);
+        }
+        else
+        {
+            editor = NULL;
+        }
+
+        if ( !editor )
+        {
+            if ( m_defGridAttr && this != m_defGridAttr )
+            {
+                // if we still don't have one then use the grid default
+                // (no need for IncRef() here neither)
+                editor = m_defGridAttr->GetEditor(NULL, 0, 0);
+            }
+            else // default grid attr
+            {
+                // use m_editor which we had decided not to use initially
+                editor = m_editor;
+                if ( editor )
+                    editor->IncRef();
+            }
+        }
     }
 
+    // we're supposed to always find something
+    wxASSERT_MSG(editor, wxT("Missing default cell editor"));
+
     return editor;
 }
 
@@ -2088,6 +2090,9 @@ void wxGridCellAttrData::SetAttr(wxGridCellAttr *attr, int row, int col)
     }
     else
     {
+        // free the old attribute
+        m_attrs[(size_t)n].attr->DecRef();
+
         if ( attr )
         {
             // change the attribute
@@ -3140,7 +3145,7 @@ bool wxGridStringTable::DeleteCols( size_t pos, size_t numCols )
         {
             for ( n = 0;  n < numCols;  n++ )
             {
-                m_data[row].Remove( pos );
+                m_data[row].RemoveAt( pos );
             }
         }
     }
@@ -3415,9 +3420,9 @@ void wxGridCornerLabelWindow::OnKeyUp( wxKeyEvent& event )
 
 //////////////////////////////////////////////////////////////////////
 
-IMPLEMENT_DYNAMIC_CLASS( wxGridWindow, wxPanel )
+IMPLEMENT_DYNAMIC_CLASS( wxGridWindow, wxWindow )
 
-BEGIN_EVENT_TABLE( wxGridWindow, wxPanel )
+BEGIN_EVENT_TABLE( wxGridWindow, wxWindow )
     EVT_PAINT( wxGridWindow::OnPaint )
     EVT_MOUSEWHEEL( wxGridWindow::OnMouseWheel)
     EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent )
@@ -3430,12 +3435,12 @@ wxGridWindow::wxGridWindow( wxGrid *parent,
                             wxGridRowLabelWindow *rowLblWin,
                             wxGridColLabelWindow *colLblWin,
                             wxWindowID id, const wxPoint &pos, const wxSize &size )
-        : wxPanel( parent, id, pos, size, wxWANTS_CHARS, "grid window" )
+        : wxWindow( parent, id, pos, size, wxWANTS_CHARS, "grid window" )
 {
     m_owner = parent;
     m_rowLabelWin = rowLblWin;
     m_colLabelWin = colLblWin;
-    SetBackgroundColour( "WHITE" );
+    SetBackgroundColour(_T("WHITE"));
 }
 
 
@@ -3461,7 +3466,7 @@ void wxGridWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
 
 void wxGridWindow::ScrollWindow( int dx, int dy, const wxRect *rect )
 {
-    wxPanel::ScrollWindow( dx, dy, rect );
+    wxWindow::ScrollWindow( dx, dy, rect );
     m_rowLabelWin->ScrollWindow( 0, dy, rect );
     m_colLabelWin->ScrollWindow( dx, 0, rect );
 }
@@ -3497,6 +3502,23 @@ void wxGridWindow::OnEraseBackground( wxEraseEvent& WXUNUSED(event) )
 
 //////////////////////////////////////////////////////////////////////
 
+// Internal Helper function for computing 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 speed up the search!
+
+// Internal helper macros for simpler use of that function
+
+static int CoordToRowOrCol(int coord, int defaultDist, int minDist,
+                           const wxArrayInt& BorderArray, bool maxOnOverflow);
+
+#define internalXToCol(x) CoordToRowOrCol(x, m_defaultColWidth, \
+                                          WXGRID_MIN_COL_WIDTH, \
+                                          m_colRights, TRUE)
+#define internalYToRow(y) CoordToRowOrCol(y, m_defaultRowHeight, \
+                                          WXGRID_MIN_ROW_HEIGHT, \
+                                          m_rowBottoms, TRUE)
+/////////////////////////////////////////////////////////////////////
 
 IMPLEMENT_DYNAMIC_CLASS( wxGrid, wxScrolledWindow )
 
@@ -3558,17 +3580,17 @@ void wxGrid::Create()
 
     m_cellEditCtrlEnabled = FALSE;
 
-    m_defaultCellAttr = new wxGridCellAttr;
-    m_defaultCellAttr->SetDefAttr(m_defaultCellAttr);
+    m_defaultCellAttr = new wxGridCellAttr();
 
     // Set default cell attributes
+    m_defaultCellAttr->SetDefAttr(m_defaultCellAttr);
     m_defaultCellAttr->SetKind(wxGridCellAttr::Default);
     m_defaultCellAttr->SetFont(GetFont());
     m_defaultCellAttr->SetAlignment(wxALIGN_LEFT, wxALIGN_TOP);
     m_defaultCellAttr->SetTextColour(
-        wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOWTEXT));
+        wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT));
     m_defaultCellAttr->SetBackgroundColour(
-        wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW));
+        wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
     m_defaultCellAttr->SetRenderer(new wxGridCellStringRenderer);
     m_defaultCellAttr->SetEditor(new wxGridCellTextEditor);
 
@@ -3582,7 +3604,8 @@ void wxGrid::Create()
 
     // create the type registry
     m_typeRegistry = new wxGridTypeRegistry;
-    m_selection = 0;
+    m_selection = NULL;
+
     // subwindow components that make up the wxGrid
     m_cornerLabelWin = new wxGridCornerLabelWindow( this,
                                                     -1,
@@ -3607,6 +3630,8 @@ void wxGrid::Create()
                                   wxDefaultSize );
 
     SetTargetWindow( m_gridWin );
+
+    Init();
 }
 
 
@@ -3624,7 +3649,9 @@ bool wxGrid::CreateGrid( int numRows, int numCols,
     m_table->SetView( this );
     m_ownTable = TRUE;
     m_selection = new wxGridSelection( this, selmode );
-    Init();
+
+    CalcDimensions();
+
     m_created = TRUE;
 
     return m_created;
@@ -3632,12 +3659,10 @@ bool wxGrid::CreateGrid( int numRows, int numCols,
 
 void wxGrid::SetSelectionMode(wxGrid::wxGridSelectionModes selmode)
 {
-    if ( !m_created )
-    {
-        wxFAIL_MSG( wxT("Called wxGrid::SetSelectionMode() before calling CreateGrid()") );
-    }
-    else
-        m_selection->SetSelectionMode( selmode );
+    wxCHECK_RET( m_created,
+                 wxT("Called wxGrid::SetSelectionMode() before calling CreateGrid()") );
+
+    m_selection->SetSelectionMode( selmode );
 }
 
 bool wxGrid::SetTable( wxGridTableBase *table, bool takeOwnership,
@@ -3646,9 +3671,9 @@ bool wxGrid::SetTable( wxGridTableBase *table, bool takeOwnership,
     if ( m_created )
     {
         // RD: Actually, this should probably be allowed.  I think it would be
-        // nice to be able to switch multiple Tables in and out of a single
-        // View at runtime.  Is there anything in the implmentation that would
-        // prevent this?
+        //     nice to be able to switch multiple Tables in and out of a single
+        //     View at runtime.  Is there anything in the implementation that
+        //     would prevent this?
 
         // At least, you now have to cope with m_selection
         wxFAIL_MSG( wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") );
@@ -3664,7 +3689,9 @@ bool wxGrid::SetTable( wxGridTableBase *table, bool takeOwnership,
         if (takeOwnership)
             m_ownTable = TRUE;
         m_selection = new wxGridSelection( this, selmode );
-        Init();
+
+        CalcDimensions();
+
         m_created = TRUE;
     }
 
@@ -3736,8 +3763,8 @@ void wxGrid::Init()
 
     m_selectingTopLeft = wxGridNoCellCoords;
     m_selectingBottomRight = wxGridNoCellCoords;
-    m_selectionBackground = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT);
-    m_selectionForeground = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
+    m_selectionBackground = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
+    m_selectionForeground = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
 
     m_editable = TRUE;  // default for whole grid
 
@@ -3745,9 +3772,7 @@ void wxGrid::Init()
     m_batchCount = 0;
 
     m_extraWidth =
-    m_extraHeight = 50;
-
-    CalcDimensions();
+    m_extraHeight = 0;
 }
 
 // ----------------------------------------------------------------------------
@@ -3832,9 +3857,9 @@ void wxGrid::CalcDimensions()
     int cw, ch;
     GetClientSize( &cw, &ch );
 
-    if ( m_colLabelWin->IsShown() )
-        cw -= m_rowLabelWidth;
     if ( m_rowLabelWin->IsShown() )
+        cw -= m_rowLabelWidth;
+    if ( m_colLabelWin->IsShown() )
         ch -= m_colLabelHeight;
 
     // grid total size
@@ -3844,32 +3869,38 @@ void wxGrid::CalcDimensions()
     // preserve (more or less) the previous position
     int x, y;
     GetViewStart( &x, &y );
-    // maybe we don't need scrollbars at all? and if we do, transform w and h
-    // from pixels into logical units
+
+    // maybe we don't need scrollbars at all?
+    //
+    // also adjust the position to be valid for the new scroll rangs
     if ( w <= cw )
     {
-        w = 0; x= 0;
+        w = = 0;
     }
     else
     {
-       w = (w + GRID_SCROLL_LINE - 1)/GRID_SCROLL_LINE;
-       if ( x >= w )
-           x = w - 1;
+        if ( x >= w )
+            x = w - 1;
     }
+
     if ( h <= ch )
     {
-       h = 0; y = 0;
+        h = y = 0;
     }
     else
     {
-       h = (h + GRID_SCROLL_LINE - 1)/GRID_SCROLL_LINE;
-       if ( y >= h )
-           y = h - 1;
+        if ( y >= h )
+            y = h - 1;
     }
 
     // do set scrollbar parameters
-    SetScrollbars( GRID_SCROLL_LINE, GRID_SCROLL_LINE,
-                  w, h, x, y, (GetBatchCount() != 0));
+    SetScrollbars( GRID_SCROLL_LINE_X, GRID_SCROLL_LINE_Y,
+                   GetScrollX(w), GetScrollY(h), x, y,
+                   GetBatchCount() != 0);
+
+    // if our OnSize() hadn't been called (it would if we have scrollbars), we
+    // still must reposition the children
+    CalcWindowSizes();
 }
 
 
@@ -3947,7 +3978,9 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
                 //
                 SetCurrentCell( 0, 0 );
             }
-            m_selection->UpdateRows( pos, numRows );
+
+            if ( m_selection )
+                m_selection->UpdateRows( pos, numRows );
             wxGridCellAttrProvider * attrProvider = m_table->GetAttrProvider();
             if (attrProvider)
                 attrProvider->UpdateAttrRows( pos, numRows );
@@ -4010,8 +4043,8 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
             {
                 for ( i = 0;  i < numRows;  i++ )
                 {
-                    m_rowHeights.Remove( pos );
-                    m_rowBottoms.Remove( pos );
+                    m_rowHeights.RemoveAt( pos );
+                    m_rowBottoms.RemoveAt( pos );
                 }
 
                 int h = 0;
@@ -4030,7 +4063,9 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
                 if ( m_currentCellCoords.GetRow() >= m_numRows )
                     m_currentCellCoords.Set( 0, 0 );
             }
-            m_selection->UpdateRows( pos, -((int)numRows) );
+
+            if ( m_selection )
+                m_selection->UpdateRows( pos, -((int)numRows) );
             wxGridCellAttrProvider * attrProvider = m_table->GetAttrProvider();
             if (attrProvider) {
                 attrProvider->UpdateAttrRows( pos, -((int)numRows) );
@@ -4084,7 +4119,9 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
                 //
                 SetCurrentCell( 0, 0 );
             }
-            m_selection->UpdateCols( pos, numCols );
+
+            if ( m_selection )
+                m_selection->UpdateCols( pos, numCols );
             wxGridCellAttrProvider * attrProvider = m_table->GetAttrProvider();
             if (attrProvider)
                 attrProvider->UpdateAttrCols( pos, numCols );
@@ -4146,8 +4183,8 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
             {
                 for ( i = 0;  i < numCols;  i++ )
                 {
-                    m_colWidths.Remove( pos );
-                    m_colRights.Remove( pos );
+                    m_colWidths.RemoveAt( pos );
+                    m_colRights.RemoveAt( pos );
                 }
 
                 int w = 0;
@@ -4166,7 +4203,9 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
                 if ( m_currentCellCoords.GetCol() >= m_numCols )
                   m_currentCellCoords.Set( 0, 0 );
             }
-            m_selection->UpdateCols( pos, -((int)numCols) );
+
+            if ( m_selection )
+                m_selection->UpdateCols( pos, -((int)numCols) );
             wxGridCellAttrProvider * attrProvider = m_table->GetAttrProvider();
             if (attrProvider) {
                 attrProvider->UpdateAttrCols( pos, -((int)numCols) );
@@ -4202,8 +4241,8 @@ wxArrayInt wxGrid::CalcRowLabelsExposed( const wxRegion& reg )
     wxRegionIterator iter( reg );
     wxRect r;
 
-    wxArrayInt  rowlabels;           
-        
+    wxArrayInt  rowlabels;
+
     int top, bottom;
     while ( iter )
     {
@@ -4230,7 +4269,7 @@ wxArrayInt wxGrid::CalcRowLabelsExposed( const wxRegion& reg )
         // find the row labels within these bounds
         //
         int row;
-        for ( row = 0;  row < m_numRows;  row++ )
+        for ( row = internalYToRow(top);  row < m_numRows;  row++ )
         {
             if ( GetRowBottom(row) < top )
                 continue;
@@ -4281,7 +4320,7 @@ wxArrayInt wxGrid::CalcColLabelsExposed( const wxRegion& reg )
         // find the cells within these bounds
         //
         int col;
-        for ( col = 0;  col < m_numCols;  col++ )
+        for ( col = internalXToCol(left);  col < m_numCols;  col++ )
         {
             if ( GetColRight(col) < left )
                 continue;
@@ -4332,7 +4371,7 @@ wxGridCellCoordsArray wxGrid::CalcCellsExposed( const wxRegion& reg )
         // find the cells within these bounds
         //
         int row, col;
-        for ( row = 0;  row < m_numRows;  row++ )
+        for ( row = internalYToRow(top);  row < m_numRows;  row++ )
         {
             if ( GetRowBottom(row) <= top )
                 continue;
@@ -4340,8 +4379,7 @@ wxGridCellCoordsArray wxGrid::CalcCellsExposed( const wxRegion& reg )
             if ( GetRowTop(row) > bottom )
                 break;
 
-
-            for ( col = 0;  col < m_numCols;  col++ )
+            for ( col = internalXToCol(left);  col < m_numCols;  col++ )
             {
                 if ( GetColRight(col) <= left )
                     continue;
@@ -4368,7 +4406,11 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
 
     if ( event.Dragging() )
     {
-        m_isDragging = TRUE;
+        if (!m_isDragging)
+        {
+            m_isDragging = TRUE;
+            m_rowLabelWin->CaptureMouse();
+        }
 
         if ( event.LeftIsDown() )
         {
@@ -4398,11 +4440,14 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
                 case WXGRID_CURSOR_SELECT_ROW:
                     if ( (row = YToRow( y )) >= 0 )
                     {
-                        m_selection->SelectRow( row,
-                                                event.ControlDown(),
-                                                event.ShiftDown(),
-                                                event.AltDown(),
-                                                event.MetaDown() );
+                        if ( m_selection )
+                        {
+                            m_selection->SelectRow( row,
+                                                    event.ControlDown(),
+                                                    event.ShiftDown(),
+                                                    event.AltDown(),
+                                                    event.MetaDown() );
+                        }
                     }
 
                 // default label to suppress warnings about "enumeration value
@@ -4414,8 +4459,14 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
         return;
     }
 
-    m_isDragging = FALSE;
+    if ( m_isDragging && (event.Entering() || event.Leaving()) )
+        return;
 
+    if (m_isDragging)
+    {
+        if (m_rowLabelWin->HasCapture()) m_rowLabelWin->ReleaseMouse();
+        m_isDragging = FALSE;
+    }
 
     // ------------ Entering or leaving the window
     //
@@ -4441,21 +4492,29 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
             {
                 if ( !event.ShiftDown() && !event.ControlDown() )
                     ClearSelection();
-                if ( event.ShiftDown() )
-                    m_selection->SelectBlock( m_currentCellCoords.GetRow(),
-                                              0,
-                                              row,
-                                              GetNumberCols() - 1,
-                                              event.ControlDown(),
-                                              event.ShiftDown(),
-                                              event.AltDown(),
-                                              event.MetaDown() );
-                else
-                    m_selection->SelectRow( row,
-                                            event.ControlDown(),
-                                            event.ShiftDown(),
-                                            event.AltDown(),
-                                            event.MetaDown() );
+                else if ( m_selection )
+                {
+                    if ( event.ShiftDown() )
+                    {
+                        m_selection->SelectBlock( m_currentCellCoords.GetRow(),
+                                                  0,
+                                                  row,
+                                                  GetNumberCols() - 1,
+                                                  event.ControlDown(),
+                                                  event.ShiftDown(),
+                                                  event.AltDown(),
+                                                  event.MetaDown() );
+                    }
+                    else
+                    {
+                        m_selection->SelectRow( row,
+                                                event.ControlDown(),
+                                                event.ShiftDown(),
+                                                event.AltDown(),
+                                                event.MetaDown() );
+                    }
+                }
+
                 ChangeCursorMode(WXGRID_CURSOR_SELECT_ROW, m_rowLabelWin);
             }
         }
@@ -4554,7 +4613,11 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
 
     if ( event.Dragging() )
     {
-        m_isDragging = TRUE;
+        if (!m_isDragging)
+        {
+            m_isDragging = TRUE;
+            m_colLabelWin->CaptureMouse();
+        }
 
         if ( event.LeftIsDown() )
         {
@@ -4584,11 +4647,14 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
                 case WXGRID_CURSOR_SELECT_COL:
                     if ( (col = XToCol( x )) >= 0 )
                     {
-                        m_selection->SelectCol( col,
-                                                event.ControlDown(),
-                                                event.ShiftDown(),
-                                                event.AltDown(),
-                                                event.MetaDown() );
+                        if ( m_selection )
+                        {
+                            m_selection->SelectCol( col,
+                                                    event.ControlDown(),
+                                                    event.ShiftDown(),
+                                                    event.AltDown(),
+                                                    event.MetaDown() );
+                        }
                     }
 
                 // default label to suppress warnings about "enumeration value
@@ -4600,8 +4666,14 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
         return;
     }
 
-    m_isDragging = FALSE;
+    if ( m_isDragging && (event.Entering() || event.Leaving()) )
+        return;
 
+    if (m_isDragging)
+    {
+        if (m_colLabelWin->HasCapture()) m_colLabelWin->ReleaseMouse();
+        m_isDragging = FALSE;
+    }
 
     // ------------ Entering or leaving the window
     //
@@ -4627,20 +4699,28 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
             {
                 if ( !event.ShiftDown() && !event.ControlDown() )
                     ClearSelection();
-                if ( event.ShiftDown() )
-                    m_selection->SelectBlock( 0,
-                                              m_currentCellCoords.GetCol(),
-                                              GetNumberRows() - 1, col,
-                                              event.ControlDown(),
-                                              event.ShiftDown(),
-                                              event.AltDown(),
-                                              event.MetaDown() );
-                else
-                    m_selection->SelectCol( col,
-                                            event.ControlDown(),
-                                            event.ShiftDown(),
-                                            event.AltDown(),
-                                            event.MetaDown() );
+                if ( m_selection )
+                {
+                    if ( event.ShiftDown() )
+                    {
+                        m_selection->SelectBlock( 0,
+                                                  m_currentCellCoords.GetCol(),
+                                                  GetNumberRows() - 1, col,
+                                                  event.ControlDown(),
+                                                  event.ShiftDown(),
+                                                  event.AltDown(),
+                                                  event.MetaDown() );
+                    }
+                    else
+                    {
+                        m_selection->SelectCol( col,
+                                                event.ControlDown(),
+                                                event.ShiftDown(),
+                                                event.AltDown(),
+                                                event.MetaDown() );
+                    }
+                }
+
                 ChangeCursorMode(WXGRID_CURSOR_SELECT_COL, m_colLabelWin);
             }
         }
@@ -4801,7 +4881,7 @@ void wxGrid::ChangeCursorMode(CursorMode mode,
 
     if ( m_winCapture )
     {
-        m_winCapture->ReleaseMouse();
+        if (m_winCapture->HasCapture()) m_winCapture->ReleaseMouse();
         m_winCapture = (wxWindow *)NULL;
     }
 
@@ -4972,14 +5052,17 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
                 ClearSelection();
             if ( event.ShiftDown() )
             {
-                m_selection->SelectBlock( m_currentCellCoords.GetRow(),
-                                          m_currentCellCoords.GetCol(),
-                                          coords.GetRow(),
-                                          coords.GetCol(),
-                                          event.ControlDown(),
-                                          event.ShiftDown(),
-                                          event.AltDown(),
-                                          event.MetaDown() );
+                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 )
@@ -5009,12 +5092,15 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
                 {
                     if ( event.ControlDown() )
                     {
-                        m_selection->ToggleCellSelection( coords.GetRow(),
-                                                          coords.GetCol(),
-                                                          event.ControlDown(),
-                                                          event.ShiftDown(),
-                                                          event.AltDown(),
-                                                          event.MetaDown() );
+                        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;
@@ -5022,9 +5108,14 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
                     else
                     {
                         SetCurrentCell( coords );
-                        if ( m_selection->GetSelectionMode()
-                             != wxGrid::wxGridSelectCells)
-                            HighlightBlock( coords, coords );
+                        if ( m_selection )
+                        {
+                            if ( m_selection->GetSelectionMode() != 
+                                    wxGrid::wxGridSelectCells )
+                            {
+                                HighlightBlock( coords, coords );
+                            }
+                        }
                     }
                     m_waitForSlowClick = TRUE;
                 }
@@ -5060,17 +5151,22 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
             {
                 if (m_winCapture)
                 {
-                    m_winCapture->ReleaseMouse();
+                    if (m_winCapture->HasCapture()) m_winCapture->ReleaseMouse();
                     m_winCapture = NULL;
                 }
-                m_selection->SelectBlock( m_selectingTopLeft.GetRow(),
-                                          m_selectingTopLeft.GetCol(),
-                                          m_selectingBottomRight.GetRow(),
-                                          m_selectingBottomRight.GetCol(),
-                                          event.ControlDown(),
-                                          event.ShiftDown(),
-                                          event.AltDown(),
-                                          event.MetaDown() );
+
+                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() );
+                }
+
                 m_selectingTopLeft = wxGridNoCellCoords;
                 m_selectingBottomRight = wxGridNoCellCoords;
             }
@@ -5449,66 +5545,80 @@ bool wxGrid::DeleteCols( int pos, int numCols, bool WXUNUSED(updateLabels) )
 // Generate a grid event based on a mouse event and
 // return the result of ProcessEvent()
 //
-bool wxGrid::SendEvent( const wxEventType type,
+int wxGrid::SendEvent( const wxEventType type,
                         int row, int col,
                         wxMouseEvent& mouseEv )
 {
-    if ( type == wxEVT_GRID_ROW_SIZE || type == wxEVT_GRID_COL_SIZE )
-    {
-        int rowOrCol = (row == -1 ? col : row);
-
-        wxGridSizeEvent gridEvt( GetId(),
-                                 type,
-                                 this,
-                                 rowOrCol,
-                                 mouseEv.GetX() + GetRowLabelSize(),
-                                 mouseEv.GetY() + GetColLabelSize(),
-                                 mouseEv.ControlDown(),
-                                 mouseEv.ShiftDown(),
-                                 mouseEv.AltDown(),
-                                 mouseEv.MetaDown() );
-        return GetEventHandler()->ProcessEvent(gridEvt);
-    }
-    else if ( type == wxEVT_GRID_RANGE_SELECT )
-    {
-        // Right now, it should _never_ end up here!
-        wxGridRangeSelectEvent gridEvt( GetId(),
-                                        type,
-                                        this,
-                                        m_selectingTopLeft,
-                                        m_selectingBottomRight,
-                                        TRUE,
-                                        mouseEv.ControlDown(),
-                                        mouseEv.ShiftDown(),
-                                        mouseEv.AltDown(),
-                                        mouseEv.MetaDown() );
-
-        return GetEventHandler()->ProcessEvent(gridEvt);
-    }
-    else
-    {
-        wxGridEvent gridEvt( GetId(),
-                             type,
-                             this,
-                             row, col,
-                             mouseEv.GetX() + GetRowLabelSize(),
-                             mouseEv.GetY() + GetColLabelSize(),
-                             FALSE,
-                             mouseEv.ControlDown(),
-                             mouseEv.ShiftDown(),
-                             mouseEv.AltDown(),
-                             mouseEv.MetaDown() );
-        return GetEventHandler()->ProcessEvent(gridEvt);
-    }
+   bool claimed;
+   bool vetoed= FALSE;
+
+   if ( type == wxEVT_GRID_ROW_SIZE || type == wxEVT_GRID_COL_SIZE )
+   {
+       int rowOrCol = (row == -1 ? col : row);
+
+       wxGridSizeEvent gridEvt( GetId(),
+               type,
+               this,
+               rowOrCol,
+               mouseEv.GetX() + GetRowLabelSize(),
+               mouseEv.GetY() + GetColLabelSize(),
+               mouseEv.ControlDown(),
+               mouseEv.ShiftDown(),
+               mouseEv.AltDown(),
+               mouseEv.MetaDown() );
+
+       claimed = GetEventHandler()->ProcessEvent(gridEvt);
+       vetoed = !gridEvt.IsAllowed();
+   }
+   else if ( type == wxEVT_GRID_RANGE_SELECT )
+   {
+       // Right now, it should _never_ end up here!
+       wxGridRangeSelectEvent gridEvt( GetId(),
+               type,
+               this,
+               m_selectingTopLeft,
+               m_selectingBottomRight,
+               TRUE,
+               mouseEv.ControlDown(),
+               mouseEv.ShiftDown(),
+               mouseEv.AltDown(),
+               mouseEv.MetaDown() );
+
+       claimed = GetEventHandler()->ProcessEvent(gridEvt);
+       vetoed = !gridEvt.IsAllowed();
+   }
+   else
+   {
+       wxGridEvent gridEvt( GetId(),
+               type,
+               this,
+               row, col,
+               mouseEv.GetX() + GetRowLabelSize(),
+               mouseEv.GetY() + GetColLabelSize(),
+               FALSE,
+               mouseEv.ControlDown(),
+               mouseEv.ShiftDown(),
+               mouseEv.AltDown(),
+               mouseEv.MetaDown() );
+       claimed = GetEventHandler()->ProcessEvent(gridEvt);
+       vetoed = !gridEvt.IsAllowed();
+   }
+
+   // A Veto'd event may not be `claimed' so test this first
+   if (vetoed) return -1;
+   return claimed ? 1 : 0;
 }
 
 
 // Generate a grid event of specified type and return the result
 // of ProcessEvent().
 //
-bool wxGrid::SendEvent( const wxEventType type,
+int wxGrid::SendEvent( const wxEventType type,
                         int row, int col )
 {
+   bool claimed;
+   bool vetoed= FALSE;
+
     if ( type == wxEVT_GRID_ROW_SIZE || type == wxEVT_GRID_COL_SIZE )
     {
         int rowOrCol = (row == -1 ? col : row);
@@ -5518,7 +5628,8 @@ bool wxGrid::SendEvent( const wxEventType type,
                                  this,
                                  rowOrCol );
 
-        return GetEventHandler()->ProcessEvent(gridEvt);
+        claimed = GetEventHandler()->ProcessEvent(gridEvt);
+        vetoed  = !gridEvt.IsAllowed();
     }
     else
     {
@@ -5527,8 +5638,13 @@ bool wxGrid::SendEvent( const wxEventType type,
                              this,
                              row, col );
 
-        return GetEventHandler()->ProcessEvent(gridEvt);
-    }
+        claimed = GetEventHandler()->ProcessEvent(gridEvt);
+        vetoed  = !gridEvt.IsAllowed();
+     }
+
+    // A Veto'd event may not be `claimed' so test this first
+    if (vetoed) return -1;
+    return claimed ? 1 : 0;
 }
 
 
@@ -5538,14 +5654,14 @@ void wxGrid::OnPaint( wxPaintEvent& WXUNUSED(event) )
 }
 
 
-// This is just here to make sure that CalcDimensions gets called when
-// the grid view is resized... then the size event is skipped to allow
-// the box sizers to handle everything
-//
-void wxGrid::OnSize( wxSizeEvent& WXUNUSED(event) )
+void wxGrid::OnSize( wxSizeEvent& event )
 {
+    // position the child windows
     CalcWindowSizes();
-    CalcDimensions();
+
+    // don't call CalcDimensions() from here, the base class handles the size
+    // changes itself
+    event.Skip();
 }
 
 
@@ -5706,12 +5822,15 @@ void wxGrid::OnKeyDown( wxKeyEvent& event )
             case WXK_SPACE:
                 if ( event.ControlDown() )
                 {
-                    m_selection->ToggleCellSelection( m_currentCellCoords.GetRow(),
-                                                      m_currentCellCoords.GetCol(),
-                                                      event.ControlDown(),
-                                                      event.ShiftDown(),
-                                                      event.AltDown(),
-                                                      event.MetaDown() );
+                    if ( m_selection )
+                    {
+                        m_selection->ToggleCellSelection( m_currentCellCoords.GetRow(),
+                                                          m_currentCellCoords.GetCol(),
+                                                          event.ControlDown(),
+                                                          event.ShiftDown(),
+                                                          event.AltDown(),
+                                                          event.MetaDown() );
+                    }
                     break;
                 }
                 if ( !IsEditable() )
@@ -5737,7 +5856,14 @@ void wxGrid::OnKeyDown( wxKeyEvent& event )
                          || editor->IsAcceptedKey(event) )
                     {
                         EnableCellEditControl();
-                        editor->StartingKey(event);
+
+                        // the editor could be not shown for a variety of
+                        // reasons (i.e. blocked by the app or whatever), so
+                        // check if it really was created
+                        if ( m_cellEditCtrlEnabled )
+                        {
+                            editor->StartingKey(event);
+                        }
                     }
                     else
                     {
@@ -5768,14 +5894,20 @@ void wxGrid::OnKeyUp( wxKeyEvent& event )
     {
         if ( m_selectingTopLeft != wxGridNoCellCoords &&
              m_selectingBottomRight != wxGridNoCellCoords )
-            m_selection->SelectBlock( m_selectingTopLeft.GetRow(),
-                                      m_selectingTopLeft.GetCol(),
-                                      m_selectingBottomRight.GetRow(),
-                                      m_selectingBottomRight.GetCol(),
-                                      event.ControlDown(),
-                                      TRUE,
-                                      event.AltDown(),
-                                      event.MetaDown() );
+        {
+            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_selectingTopLeft = wxGridNoCellCoords;
         m_selectingBottomRight = wxGridNoCellCoords;
         m_selectingKeyboard = wxGridNoCellCoords;
@@ -5818,7 +5950,7 @@ void wxGrid::SetCurrentCell( const wxGridCellCoords& coords )
 
             // Otherwise refresh redraws the highlight!
             m_currentCellCoords = coords;
-            
+
             DrawGridCellArea(dc,cells);
             DrawAllGridLines( dc, r );
         }
@@ -5837,16 +5969,20 @@ void wxGrid::HighlightBlock( int topRow, int leftCol, int bottomRow, int rightCo
     int temp;
     wxGridCellCoords updateTopLeft, updateBottomRight;
 
-    if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectRows )
+    if ( m_selection )
     {
-        leftCol = 0;
-        rightCol = GetNumberCols() - 1;
-    }
-    else if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectColumns )
-    {
-        topRow = 0;
-        bottomRow = GetNumberRows() - 1;
+        if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectRows )
+        {
+            leftCol = 0;
+            rightCol = GetNumberCols() - 1;
+        }
+        else if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectColumns )
+        {
+            topRow = 0;
+            bottomRow = GetNumberRows() - 1;
+        }
     }
+
     if ( topRow > bottomRow )
     {
         temp = topRow;
@@ -6254,7 +6390,7 @@ void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) )
     // horizontal grid lines
     //
     int i;
-    for ( i = 0; i < m_numRows; i++ )
+    for ( i = internalYToRow(top); i < m_numRows; i++ )
     {
         int bot = GetRowBottom(i) - 1;
 
@@ -6272,7 +6408,7 @@ void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) )
 
     // vertical grid lines
     //
-    for ( i = 0; i < m_numCols; i++ )
+    for ( i = internalXToCol(left); i < m_numCols; i++ )
     {
         int colRight = GetColRight(i) - 1;
         if ( colRight > right )
@@ -6578,11 +6714,11 @@ void wxGrid::EnableCellEditControl( bool enable )
 
     if ( enable != m_cellEditCtrlEnabled )
     {
-        // TODO allow the app to Veto() this event?
-        SendEvent(enable ? wxEVT_GRID_EDITOR_SHOWN : wxEVT_GRID_EDITOR_HIDDEN);
-
         if ( enable )
         {
+            if (SendEvent( wxEVT_GRID_EDITOR_SHOWN) <0)
+                return;
+
             // this should be checked by the caller!
             wxASSERT_MSG( CanEnableCellControl(),
                           _T("can't enable editing for this cell!") );
@@ -6594,6 +6730,9 @@ void wxGrid::EnableCellEditControl( bool enable )
         }
         else
         {
+            //FIXME:add veto support
+            SendEvent( wxEVT_GRID_EDITOR_HIDDEN);
+
             HideCellEditControl();
             SaveEditControlValue();
 
@@ -6682,8 +6821,13 @@ void wxGrid::ShowCellEditControl()
 #endif // 0
 
             // cell is shifted by one pixel
-            rect.x--;
-            rect.y--;
+            // However, don't allow x or y to become negative
+            // since the SetSize() method interprets that as
+            // "don't change."
+            if (rect.x > 0)
+                rect.x--;
+            if (rect.y > 0)
+                rect.y--;
 
             wxGridCellAttr* attr = GetCellAttr(row, col);
             wxGridCellEditor* editor = attr->GetEditor(this, row, col);
@@ -6740,6 +6884,8 @@ void wxGrid::SaveEditControlValue()
         int row = m_currentCellCoords.GetRow();
         int col = m_currentCellCoords.GetCol();
 
+        wxString oldval = GetCellValue(row,col);
+
         wxGridCellAttr* attr = GetCellAttr(row, col);
         wxGridCellEditor* editor = attr->GetEditor(this, row, col);
         bool changed = editor->EndEdit(row, col, this);
@@ -6749,9 +6895,13 @@ void wxGrid::SaveEditControlValue()
 
         if (changed)
         {
-            SendEvent( wxEVT_GRID_CELL_CHANGE,
+            if ( SendEvent( wxEVT_GRID_CELL_CHANGE,
                        m_currentCellCoords.GetRow(),
-                       m_currentCellCoords.GetCol() );
+                       m_currentCellCoords.GetCol() ) < 0 ) {
+
+                // Event has been vetoed, set the data back.
+                SetCellValue(row,col,oldval);
+            }
         }
     }
 }
@@ -6780,31 +6930,68 @@ void wxGrid::XYToCell( int x, int y, wxGridCellCoords& coords )
 }
 
 
-int wxGrid::YToRow( int y )
+// Internal Helper function for computing 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 speed up the search!
+
+static int CoordToRowOrCol(int coord, int defaultDist, int minDist,
+                           const wxArrayInt& BorderArray, bool maxOnOverflow)
 {
-    int i;
+    if (!defaultDist)
+        defaultDist = 1;
+    size_t i_max = coord / defaultDist,
+           i_min = 0;
+    if (BorderArray.IsEmpty())
+    {
+        return i_max;
+    }
 
-    for ( i = 0;  i < m_numRows;  i++ )
+    if ( i_max >= BorderArray.GetCount())
+        i_max = BorderArray.GetCount() - 1;
+    else
     {
-        if ( y < GetRowBottom(i) )
-            return i;
+        if ( coord >= BorderArray[i_max])
+        {
+            i_min = i_max;
+            i_max = coord / minDist;
+        }
+        if ( i_max >= BorderArray.GetCount())
+            i_max = BorderArray.GetCount() - 1;
     }
+    if ( coord >= BorderArray[i_max])
+        return maxOnOverflow ? (int)i_max : -1;
+    if ( coord < BorderArray[0] )
+        return 0;
 
-    return -1;
+    while ( i_max - i_min > 0 )
+    {
+        wxCHECK_MSG(BorderArray[i_min] <= coord && coord < BorderArray[i_max],
+                    0, _T("wxGrid: internal error in CoordToRowOrCol"));
+        if (coord >=  BorderArray[ i_max - 1])
+            return i_max;
+        else
+            i_max--;
+        int median = i_min + (i_max - i_min + 1) / 2;
+        if (coord < BorderArray[median])
+            i_max = median;
+        else
+            i_min = median;
+    }
+    return i_max;
 }
 
-
-int wxGrid::XToCol( int x )
+int wxGrid::YToRow( int y )
 {
-    int i;
+    return CoordToRowOrCol(y, m_defaultRowHeight,
+                           WXGRID_MIN_ROW_HEIGHT, m_rowBottoms, FALSE);
+}
 
-    for ( i = 0;  i < m_numCols;  i++ )
-    {
-        if ( x < GetColRight(i) )
-            return i;
-    }
 
-    return -1;
+int wxGrid::XToCol( int x )
+{
+    return CoordToRowOrCol(x, m_defaultColWidth,
+                           WXGRID_MIN_COL_WIDTH, m_colRights, FALSE);
 }
 
 
@@ -6813,16 +7000,17 @@ int wxGrid::XToCol( int x )
 //
 int wxGrid::YToEdgeOfRow( int y )
 {
-    int i, d;
+    int i;
+    i = internalYToRow(y);
 
-    for ( i = 0;  i < m_numRows;  i++ )
+    if ( GetRowHeight(i) > WXGRID_LABEL_EDGE_ZONE )
     {
-        if ( GetRowHeight(i) > WXGRID_LABEL_EDGE_ZONE )
-        {
-            d = abs( y - GetRowBottom(i) );
-            if ( d < WXGRID_LABEL_EDGE_ZONE )
-                return i;
-        }
+        // We know that we are in row i, test whether we are
+        // close enough to lower or upper border, respectively.
+        if ( abs(GetRowBottom(i) - y) < WXGRID_LABEL_EDGE_ZONE )
+            return i;
+        else if( i > 0 && y - GetRowTop(i) < WXGRID_LABEL_EDGE_ZONE )
+            return i - 1;
     }
 
     return -1;
@@ -6834,16 +7022,17 @@ int wxGrid::YToEdgeOfRow( int y )
 //
 int wxGrid::XToEdgeOfCol( int x )
 {
-    int i, d;
+    int i;
+    i = internalXToCol(x);
 
-    for ( i = 0;  i < m_numCols;  i++ )
+    if ( GetColWidth(i) > WXGRID_LABEL_EDGE_ZONE )
     {
-        if ( GetColWidth(i) > WXGRID_LABEL_EDGE_ZONE )
-        {
-            d = abs( x - GetColRight(i) );
-            if ( d < WXGRID_LABEL_EDGE_ZONE )
-                return i;
-        }
+        // We know that we are in column i,  test whether we are
+        // close enough to right or left border, respectively.
+        if ( abs(GetColRight(i) - x) < WXGRID_LABEL_EDGE_ZONE )
+            return i;
+        else if( i > 0 && x - GetColLeft(i) < WXGRID_LABEL_EDGE_ZONE )
+            return i - 1;
     }
 
     return -1;
@@ -6911,6 +7100,7 @@ bool wxGrid::IsVisible( int row, int col, bool wholeCellVisible )
 //
 void wxGrid::MakeCellVisible( int row, int col )
 {
+
     int i;
     int xpos = -1, ypos = -1;
 
@@ -6951,7 +7141,10 @@ void wxGrid::MakeCellVisible( int row, int col )
             // we divide it later by GRID_SCROLL_LINE, make sure that we don't
             // have rounding errors (this is important, because if we do, we
             // might not scroll at all and some cells won't be redrawn)
-            ypos += GRID_SCROLL_LINE / 2;
+            //
+            // Sometimes GRID_SCROLL_LINE/2 is not enough, so just add a full
+            // scroll unit...
+            ypos += GRID_SCROLL_LINE_Y;
         }
 
         if ( left < 0 )
@@ -6973,13 +7166,15 @@ void wxGrid::MakeCellVisible( int row, int col )
             }
 
             // see comment for ypos above
-            xpos += GRID_SCROLL_LINE / 2;
+            xpos += GRID_SCROLL_LINE_X;
         }
 
         if ( xpos != -1  ||  ypos != -1 )
         {
-            if ( xpos != -1 ) xpos /= GRID_SCROLL_LINE;
-            if ( ypos != -1 ) ypos /= GRID_SCROLL_LINE;
+            if ( xpos != -1 )
+                xpos /= GRID_SCROLL_LINE_X;
+            if ( ypos != -1 )
+                ypos /= GRID_SCROLL_LINE_Y;
             Scroll( xpos, ypos );
             AdjustScrollbars();
         }
@@ -8004,19 +8199,20 @@ wxGridCellAttr *wxGrid::GetCellAttr(int row, int col) const
 wxGridCellAttr *wxGrid::GetOrCreateCellAttr(int row, int col) const
 {
     wxGridCellAttr *attr = (wxGridCellAttr *)NULL;
-        wxASSERT_MSG( m_table,
-                      _T("we may only be called if CanHaveAttributes() returned TRUE and then m_table should be !NULL") );
 
-    attr = m_table->GetAttr(row, col, wxGridCellAttr::Cell );
-        if ( !attr )
-        {
-            attr = new wxGridCellAttr;
+    wxCHECK_MSG( m_table, attr,
+                  _T("we may only be called if CanHaveAttributes() returned TRUE and then m_table should be !NULL") );
+
+    attr = m_table->GetAttr(row, col, wxGridCellAttr::Cell);
+    if ( !attr )
+    {
+        attr = new wxGridCellAttr(m_defaultCellAttr);
+
+        // artificially inc the ref count to match DecRef() in caller
+        attr->IncRef();
+        m_table->SetAttr(attr, row, col);
+    }
 
-            // artificially inc the ref count to match DecRef() in caller
-            attr->IncRef();
-            m_table->SetAttr(attr, row, col);
-        }
-    attr->SetDefAttr(m_defaultCellAttr);
     return attr;
 }
 
@@ -8239,9 +8435,14 @@ void wxGrid::SetDefaultRowSize( int height, bool resizeExistingRows )
 
     if ( resizeExistingRows )
     {
-        InitRowHeights();
-       if ( !GetBatchCount() )
-           CalcDimensions();
+        // since we are resizing all rows to the default row size,
+        // we can simply clear the row heights and row bottoms
+        // arrays (which also allows us to take advantage of
+        // some speed optimisations)
+        m_rowHeights.Empty();
+        m_rowBottoms.Empty();
+        if ( !GetBatchCount() )
+            CalcDimensions();
     }
 }
 
@@ -8274,9 +8475,14 @@ void wxGrid::SetDefaultColSize( int width, bool resizeExistingCols )
 
     if ( resizeExistingCols )
     {
-        InitColWidths();
-       if ( !GetBatchCount() )
-           CalcDimensions();
+        // since we are resizing all columns to the default column size,
+        // we can simply clear the col widths and col rights
+        // arrays (which also allows us to take advantage of
+        // some speed optimisations)
+        m_colWidths.Empty();
+        m_colRights.Empty();
+        if ( !GetBatchCount() )
+            CalcDimensions();
     }
 }
 
@@ -8404,33 +8610,35 @@ void wxGrid::AutoSizeColOrRow( int colOrRow, bool setAsMin, bool column )
         }
     }
 
-    if ( column ){
+    if ( column )
+    {
         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 );
-       }
-    }
-    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;
+            m_colLabelWin->Refresh( TRUE, &rect );
+        }
+    }
+    else
+    {
         SetRowSize(row, extentMax);
         if ( !GetBatchCount() )
         {
-           int cw, ch, dummy;
-           m_gridWin->GetClientSize( &cw, &ch );
-           wxRect rect ( CellToRect( row, 0 ) );
-           rect.x = 0;
-           CalcScrolledPosition(0, rect.y, &dummy, &rect.y);
-           rect.width = m_rowLabelWidth;
+            int cw, ch, dummy;
+            m_gridWin->GetClientSize( &cw, &ch );
+            wxRect rect ( CellToRect( row, 0 ) );
+            rect.x = 0;
+            CalcScrolledPosition(0, rect.y, &dummy, &rect.y);
+            rect.width = m_rowLabelWidth;
             rect.height = ch - rect.y;
-           m_rowLabelWin->Refresh( TRUE, &rect );
-       }
+            m_rowLabelWin->Refresh( TRUE, &rect );
+        }
     }
     if ( setAsMin )
     {
@@ -8447,6 +8655,7 @@ int wxGrid::SetOrCalcColumnSizes(bool calcOnly, bool setAsMin)
 
     if ( !calcOnly )
         BeginBatch();
+
     for ( int col = 0; col < m_numCols; col++ )
     {
         if ( !calcOnly )
@@ -8456,8 +8665,10 @@ int wxGrid::SetOrCalcColumnSizes(bool calcOnly, bool setAsMin)
 
         width += GetColWidth(col);
     }
+
     if ( !calcOnly )
         EndBatch();
+
     return width;
 }
 
@@ -8467,6 +8678,7 @@ int wxGrid::SetOrCalcRowSizes(bool calcOnly, bool setAsMin)
 
     if ( !calcOnly )
         BeginBatch();
+
     for ( int row = 0; row < m_numRows; row++ )
     {
         if ( !calcOnly )
@@ -8476,15 +8688,78 @@ int wxGrid::SetOrCalcRowSizes(bool calcOnly, bool setAsMin)
 
         height += GetRowHeight(row);
     }
+
     if ( !calcOnly )
         EndBatch();
+
     return height;
 }
 
 void wxGrid::AutoSize()
 {
-    // set the size too
-    SetClientSize(SetOrCalcColumnSizes(FALSE), SetOrCalcRowSizes(FALSE));
+    BeginBatch();
+
+    wxSize size(SetOrCalcColumnSizes(FALSE), SetOrCalcRowSizes(FALSE));
+
+    // round up the size to a multiple of scroll step - this ensures that we
+    // won't get the scrollbars if we're sized exactly to this width
+    wxSize sizeFit(GetScrollX(size.x) * GRID_SCROLL_LINE_X,
+                   GetScrollY(size.y) * GRID_SCROLL_LINE_Y);
+
+    // distribute the extra space between teh columns/rows to avoid having
+    // extra white space
+    wxCoord diff = sizeFit.x - size.x;
+    if ( diff )
+    {
+        // try to resize the columns uniformly
+        wxCoord diffPerCol = diff / m_numCols;
+        if ( diffPerCol )
+        {
+            for ( int col = 0; col < m_numCols; col++ )
+            {
+                SetColSize(col, GetColWidth(col) + diffPerCol);
+            }
+        }
+
+        // add remaining amount to the last columns
+        diff -= diffPerCol * m_numCols;
+        if ( diff )
+        {
+            for ( int col = m_numCols - 1; col >= m_numCols - diff; col-- )
+            {
+                SetColSize(col, GetColWidth(col) + 1);
+            }
+        }
+    }
+
+    // same for rows
+    diff = sizeFit.y - size.y;
+    if ( diff )
+    {
+        // try to resize the columns uniformly
+        wxCoord diffPerRow = diff / m_numRows;
+        if ( diffPerRow )
+        {
+            for ( int row = 0; row < m_numRows; row++ )
+            {
+                SetRowSize(row, GetRowHeight(row) + diffPerRow);
+            }
+        }
+
+        // add remaining amount to the last rows
+        diff -= diffPerRow * m_numRows;
+        if ( diff )
+        {
+            for ( int row = m_numRows - 1; row >= m_numRows - diff; row-- )
+            {
+                SetRowSize(row, GetRowHeight(row) + 1);
+            }
+        }
+    }
+
+    EndBatch();
+
+    SetClientSize(sizeFit);
 }
 
 wxSize wxGrid::DoGetBestSize() const
@@ -8546,7 +8821,8 @@ void wxGrid::SelectRow( int row, bool addToSelected )
     if ( IsSelection() && !addToSelected )
         ClearSelection();
 
-    m_selection->SelectRow( row, FALSE, addToSelected );
+    if ( m_selection )
+        m_selection->SelectRow( row, FALSE, addToSelected );
 }
 
 
@@ -8555,7 +8831,8 @@ void wxGrid::SelectCol( int col, bool addToSelected )
     if ( IsSelection() && !addToSelected )
         ClearSelection();
 
-    m_selection->SelectCol( col, FALSE, addToSelected );
+    if ( m_selection )
+        m_selection->SelectCol( col, FALSE, addToSelected );
 }
 
 
@@ -8565,15 +8842,19 @@ void wxGrid::SelectBlock( int topRow, int leftCol, int bottomRow, int rightCol,
     if ( IsSelection() && !addToSelected )
         ClearSelection();
 
-    m_selection->SelectBlock( topRow, leftCol, bottomRow, rightCol,
-                              FALSE, addToSelected );
+    if ( m_selection )
+        m_selection->SelectBlock( topRow, leftCol, bottomRow, rightCol,
+                                  FALSE, addToSelected );
 }
 
 
 void wxGrid::SelectAll()
 {
     if ( m_numRows > 0 && m_numCols > 0 )
-        m_selection->SelectBlock( 0, 0, m_numRows-1, m_numCols-1 );
+    {
+        if ( m_selection )
+            m_selection->SelectBlock( 0, 0, m_numRows-1, m_numCols-1 );
+    }
 }
 
 //
@@ -8582,6 +8863,9 @@ void wxGrid::SelectAll()
 
 void wxGrid::DeselectRow( int row )
 {
+    if ( !m_selection )
+        return;
+
     if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectRows )
     {
         if ( m_selection->IsInSelection(row, 0 ) )
@@ -8600,6 +8884,9 @@ void wxGrid::DeselectRow( int row )
 
 void wxGrid::DeselectCol( int col )
 {
+    if ( !m_selection )
+        return;
+
     if ( m_selection->GetSelectionMode() == wxGrid::wxGridSelectColumns )
     {
         if ( m_selection->IsInSelection(0, col ) )
@@ -8618,31 +8905,32 @@ void wxGrid::DeselectCol( int col )
 
 void wxGrid::DeselectCell( int row, int col )
 {
-    if ( m_selection->IsInSelection(row, col) )
+    if ( m_selection && m_selection->IsInSelection(row, col) )
         m_selection->ToggleCellSelection(row, col);
 }
 
 bool wxGrid::IsSelection()
 {
-    return ( m_selection->IsSelection() ||
+    return ( m_selection && (m_selection->IsSelection() ||
              ( m_selectingTopLeft != wxGridNoCellCoords &&
-               m_selectingBottomRight != wxGridNoCellCoords ) );
+               m_selectingBottomRight != wxGridNoCellCoords) ) );
 }
 
 bool wxGrid::IsInSelection( int row, int col )
 {
-    return ( m_selection->IsInSelection( row, col ) ||
+    return ( m_selection && (m_selection->IsInSelection( row, col ) ||
              ( row >= m_selectingTopLeft.GetRow() &&
                col >= m_selectingTopLeft.GetCol() &&
                row <= m_selectingBottomRight.GetRow() &&
-               col <= m_selectingBottomRight.GetCol() ) );
+               col <= m_selectingBottomRight.GetCol() )) );
 }
 
 void wxGrid::ClearSelection()
 {
     m_selectingTopLeft = wxGridNoCellCoords;
     m_selectingBottomRight = wxGridNoCellCoords;
-    m_selection->ClearSelection();
+    if ( m_selection )
+        m_selection->ClearSelection();
 }