]> git.saurik.com Git - wxWidgets.git/blobdiff - src/generic/grid.cpp
fixed wxBase and GUI separation for sockets code
[wxWidgets.git] / src / generic / grid.cpp
index 846f80a8b03fee571132943cea79a14d0785b51a..43e4e40dc28a2a8775fe496ed5ced1bd658d87f5 100644 (file)
 
 #if wxUSE_GRID
 
-#if !defined(wxUSE_NEW_GRID) || !(wxUSE_NEW_GRID)
-    #include "gridg.cpp"
-#else // wxUSE_NEW_GRID
-
 #ifndef WX_PRECOMP
     #include "wx/utils.h"
     #include "wx/dcclient.h"
@@ -73,7 +69,8 @@
 // array classes
 // ----------------------------------------------------------------------------
 
-WX_DEFINE_EXPORTED_ARRAY(wxGridCellAttr *, wxArrayAttrs);
+WX_DEFINE_ARRAY_WITH_DECL_NO_PTR(wxGridCellAttr *, wxArrayAttrs,
+                                 class WXDLLIMPEXP_ADV);
 
 struct wxGridCellWithAttr
 {
@@ -89,9 +86,14 @@ struct wxGridCellWithAttr
 
     wxGridCellCoords coords;
     wxGridCellAttr  *attr;
+
+// Cannot do this:
+//  DECLARE_NO_COPY_CLASS(wxGridCellWithAttr)
+// without rewriting the macros, which require a public copy constructor.
 };
 
-WX_DECLARE_EXPORTED_OBJARRAY(wxGridCellWithAttr, wxGridCellWithAttrArray);
+WX_DECLARE_OBJARRAY_WITH_DECL(wxGridCellWithAttr, wxGridCellWithAttrArray,
+                              class WXDLLIMPEXP_ADV);
 
 #include "wx/arrimpl.cpp"
 
@@ -123,7 +125,7 @@ DEFINE_EVENT_TYPE(wxEVT_GRID_EDITOR_CREATED)
 // private classes
 // ----------------------------------------------------------------------------
 
-class WXDLLEXPORT wxGridRowLabelWindow : public wxWindow
+class WXDLLIMPEXP_ADV wxGridRowLabelWindow : public wxWindow
 {
 public:
     wxGridRowLabelWindow() { m_owner = (wxGrid *)NULL; }
@@ -141,10 +143,11 @@ private:
 
     DECLARE_DYNAMIC_CLASS(wxGridRowLabelWindow)
     DECLARE_EVENT_TABLE()
+    DECLARE_NO_COPY_CLASS(wxGridRowLabelWindow)
 };
 
 
-class WXDLLEXPORT wxGridColLabelWindow : public wxWindow
+class WXDLLIMPEXP_ADV wxGridColLabelWindow : public wxWindow
 {
 public:
     wxGridColLabelWindow() { m_owner = (wxGrid *)NULL; }
@@ -162,10 +165,11 @@ private:
 
     DECLARE_DYNAMIC_CLASS(wxGridColLabelWindow)
     DECLARE_EVENT_TABLE()
+    DECLARE_NO_COPY_CLASS(wxGridColLabelWindow)
 };
 
 
-class WXDLLEXPORT wxGridCornerLabelWindow : public wxWindow
+class WXDLLIMPEXP_ADV wxGridCornerLabelWindow : public wxWindow
 {
 public:
     wxGridCornerLabelWindow() { m_owner = (wxGrid *)NULL; }
@@ -183,9 +187,10 @@ private:
 
     DECLARE_DYNAMIC_CLASS(wxGridCornerLabelWindow)
     DECLARE_EVENT_TABLE()
+    DECLARE_NO_COPY_CLASS(wxGridCornerLabelWindow)
 };
 
-class WXDLLEXPORT wxGridWindow : public wxWindow
+class WXDLLIMPEXP_ADV wxGridWindow : public wxWindow
 {
 public:
     wxGridWindow()
@@ -203,6 +208,8 @@ public:
 
     void ScrollWindow( int dx, int dy, const wxRect *rect );
 
+    wxGrid* GetOwner() { return m_owner; }
+
 private:
     wxGrid                   *m_owner;
     wxGridRowLabelWindow     *m_rowLabelWin;
@@ -218,6 +225,7 @@ private:
 
     DECLARE_DYNAMIC_CLASS(wxGridWindow)
     DECLARE_EVENT_TABLE()
+    DECLARE_NO_COPY_CLASS(wxGridWindow)
 };
 
 
@@ -240,6 +248,7 @@ private:
     wxGridCellEditor*   m_editor;
     DECLARE_DYNAMIC_CLASS(wxGridCellEditorEvtHandler)
     DECLARE_EVENT_TABLE()
+    DECLARE_NO_COPY_CLASS(wxGridCellEditorEvtHandler)
 };
 
 
@@ -256,7 +265,7 @@ END_EVENT_TABLE()
 // ----------------------------------------------------------------------------
 
 // this class stores attributes set for cells
-class WXDLLEXPORT wxGridCellAttrData
+class WXDLLIMPEXP_ADV wxGridCellAttrData
 {
 public:
     void SetAttr(wxGridCellAttr *attr, int row, int col);
@@ -272,7 +281,7 @@ private:
 };
 
 // this class stores attributes set for rows or columns
-class WXDLLEXPORT wxGridRowOrColAttrData
+class WXDLLIMPEXP_ADV wxGridRowOrColAttrData
 {
 public:
     // empty ctor to suppress warnings
@@ -290,7 +299,7 @@ private:
 
 // NB: this is just a wrapper around 3 objects: one which stores cell
 //     attributes, and 2 others for row/col ones
-class WXDLLEXPORT wxGridCellAttrProviderData
+class WXDLLIMPEXP_ADV wxGridCellAttrProviderData
 {
 public:
     wxGridCellAttrData m_cellAttrs;
@@ -320,13 +329,16 @@ struct wxGridDataTypeInfo
     wxString            m_typeName;
     wxGridCellRenderer* m_renderer;
     wxGridCellEditor*   m_editor;
+
+    DECLARE_NO_COPY_CLASS(wxGridDataTypeInfo)
 };
 
 
-WX_DEFINE_EXPORTED_ARRAY(wxGridDataTypeInfo*, wxGridDataTypeInfoArray);
+WX_DEFINE_ARRAY_WITH_DECL_NO_PTR(wxGridDataTypeInfo*, wxGridDataTypeInfoArray,
+                                 class WXDLLIMPEXP_ADV);
 
 
-class WXDLLEXPORT wxGridTypeRegistry
+class WXDLLIMPEXP_ADV wxGridTypeRegistry
 {
 public:
   wxGridTypeRegistry() {}
@@ -424,6 +436,7 @@ static inline int GetScrollY(int y)
 wxGridCellEditor::wxGridCellEditor()
 {
     m_control = NULL;
+    m_attr = NULL;
 }
 
 
@@ -445,6 +458,10 @@ void wxGridCellEditor::PaintBackground(const wxRect& rectCell,
 {
     // erase the background because we might not fill the cell
     wxClientDC dc(m_control->GetParent());
+    wxGridWindow* gridWindow = wxDynamicCast(m_control->GetParent(), wxGridWindow);
+    if (gridWindow)
+        gridWindow->GetOwner()->PrepareDC(dc);
+
     dc.SetPen(*wxTRANSPARENT_PEN);
     dc.SetBrush(wxBrush(attr->GetBackgroundColour(), wxSOLID));
     dc.DrawRectangle(rectCell);
@@ -561,7 +578,11 @@ void wxGridCellTextEditor::Create(wxWindow* parent,
 #endif
                               );
 
-    // TODO: use m_maxChars
+    // set max length allowed in the textctrl, if the parameter was set
+    if (m_maxChars != 0)
+    {
+        ((wxTextCtrl*)m_control)->SetMaxLength(m_maxChars);
+    }
 
     wxGridCellEditor::Create(parent, id, evtHandler);
 }
@@ -629,6 +650,7 @@ void wxGridCellTextEditor::DoBeginEdit(const wxString& startValue)
 {
     Text()->SetValue(startValue);
     Text()->SetInsertionPointEnd();
+    Text()->SetSelection(-1,-1);
     Text()->SetFocus();
 }
 
@@ -698,7 +720,7 @@ bool wxGridCellTextEditor::IsAcceptedKey(wxKeyEvent& event)
 
             default:
                 // accept 8 bit chars too if isprint() agrees
-                if ( (keycode < 255) && (isprint(keycode)) )
+                if ( (keycode < 255) && (wxIsprint(keycode)) )
                     return TRUE;
         }
     }
@@ -721,7 +743,7 @@ void wxGridCellTextEditor::HandleReturn( wxKeyEvent&
     // wxMotif needs a little extra help...
     size_t pos = (size_t)( Text()->GetInsertionPoint() );
     wxString s( Text()->GetValue() );
-    s = s.Left(pos) + "\n" + s.Mid(pos);
+    s = s.Left(pos) + wxT("\n") + s.Mid(pos);
     Text()->SetValue(s);
     Text()->SetInsertionPoint( pos );
 #else
@@ -752,6 +774,12 @@ void wxGridCellTextEditor::SetParameters(const wxString& params)
     }
 }
 
+// return the value in the text control
+wxString wxGridCellTextEditor::GetValue() const
+{
+  return Text()->GetValue();
+}
+
 // ----------------------------------------------------------------------------
 // wxGridCellNumberEditor
 // ----------------------------------------------------------------------------
@@ -797,8 +825,9 @@ void wxGridCellNumberEditor::BeginEdit(int row, int col, wxGrid* grid)
     }
     else
     {
+        m_valueOld = 0;
         wxString sValue = table->GetValue(row, col);
-        if (! sValue.ToLong(&m_valueOld))
+        if (! sValue.ToLong(&m_valueOld) && ! sValue.IsEmpty())
         {
             wxFAIL_MSG( _T("this cell doesn't have numeric value") );
             return;
@@ -820,16 +849,20 @@ bool wxGridCellNumberEditor::EndEdit(int row, int col,
                                      wxGrid* grid)
 {
     bool changed;
-    long value;
+    long value = 0;
+    wxString text;
 
     if ( HasRange() )
     {
         value = Spin()->GetValue();
         changed = value != m_valueOld;
+        if (changed)
+            text = wxString::Format(wxT("%ld"), value);
     }
     else
     {
-        changed = Text()->GetValue().ToLong(&value) && (value != m_valueOld);
+        text = Text()->GetValue();
+        changed = (text.IsEmpty() || text.ToLong(&value)) && (value != m_valueOld);
     }
 
     if ( changed )
@@ -837,7 +870,7 @@ bool wxGridCellNumberEditor::EndEdit(int row, int col,
         if (grid->GetTable()->CanSetValueAs(row, col, wxGRID_VALUE_NUMBER))
             grid->GetTable()->SetValueAsLong(row, col, value);
         else
-            grid->GetTable()->SetValue(row, col, wxString::Format(wxT("%ld"), value));
+            grid->GetTable()->SetValue(row, col, text);
     }
 
     return changed;
@@ -881,7 +914,7 @@ bool wxGridCellNumberEditor::IsAcceptedKey(wxKeyEvent& event)
                 return TRUE;
 
             default:
-                if ( (keycode < 128) && isdigit(keycode) )
+                if ( (keycode < 128) && wxIsdigit(keycode) )
                     return TRUE;
         }
     }
@@ -893,8 +926,22 @@ void wxGridCellNumberEditor::StartingKey(wxKeyEvent& event)
 {
     if ( !HasRange() )
     {
-        int keycode = (int) event.KeyCode();
-        if ( isdigit(keycode) || keycode == '+' || keycode == '-' )
+        int keycode = event.GetKeyCode();
+        if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-'
+            || keycode ==  WXK_NUMPAD0
+            || keycode ==  WXK_NUMPAD1
+            || keycode ==  WXK_NUMPAD2
+            || keycode ==  WXK_NUMPAD3
+            || keycode ==  WXK_NUMPAD4
+            || keycode ==  WXK_NUMPAD5
+            || keycode ==  WXK_NUMPAD6
+            || keycode ==  WXK_NUMPAD7
+            || keycode ==  WXK_NUMPAD8
+            || keycode ==  WXK_NUMPAD9
+            || keycode ==  WXK_ADD
+            || keycode ==  WXK_NUMPAD_ADD
+            || keycode ==  WXK_SUBTRACT
+            || keycode ==  WXK_NUMPAD_SUBTRACT)
         {
             wxGridCellTextEditor::StartingKey(event);
 
@@ -934,6 +981,23 @@ void wxGridCellNumberEditor::SetParameters(const wxString& params)
     }
 }
 
+// return the value in the spin control if it is there (the text control otherwise)
+wxString wxGridCellNumberEditor::GetValue() const
+{
+  wxString s;
+
+  if( HasRange() )
+  {
+    long value = Spin()->GetValue();
+    s.Printf(wxT("%ld"), value);
+  }
+  else
+  {
+    s = Text()->GetValue();
+  }
+  return s;
+}
+
 // ----------------------------------------------------------------------------
 // wxGridCellFloatEditor
 // ----------------------------------------------------------------------------
@@ -965,8 +1029,9 @@ void wxGridCellFloatEditor::BeginEdit(int row, int col, wxGrid* grid)
     }
     else
     {
+        m_valueOld = 0.0;
         wxString sValue = table->GetValue(row, col);
-        if (! sValue.ToDouble(&m_valueOld))
+        if (! sValue.ToDouble(&m_valueOld) && ! sValue.IsEmpty())
         {
             wxFAIL_MSG( _T("this cell doesn't have float value") );
             return;
@@ -979,20 +1044,19 @@ void wxGridCellFloatEditor::BeginEdit(int row, int col, wxGrid* grid)
 bool wxGridCellFloatEditor::EndEdit(int row, int col,
                                      wxGrid* grid)
 {
-    double value;
-    if ( Text()->GetValue().ToDouble(&value) && (value != m_valueOld) )
+    double value = 0.0;
+    wxString text(Text()->GetValue());
+
+    if ( (text.IsEmpty() || text.ToDouble(&value)) && (value != m_valueOld) )
     {
         if (grid->GetTable()->CanSetValueAs(row, col, wxGRID_VALUE_FLOAT))
             grid->GetTable()->SetValueAsDouble(row, col, value);
         else
-            grid->GetTable()->SetValue(row, col, wxString::Format(wxT("%f"), value));
+            grid->GetTable()->SetValue(row, col, text);
 
         return TRUE;
     }
-    else
-    {
-        return FALSE;
-    }
+    return FALSE;
 }
 
 void wxGridCellFloatEditor::Reset()
@@ -1002,9 +1066,22 @@ void wxGridCellFloatEditor::Reset()
 
 void wxGridCellFloatEditor::StartingKey(wxKeyEvent& event)
 {
-    int keycode = (int)event.KeyCode();
-    if ( isdigit(keycode) ||
-         keycode == '+' || keycode == '-' || keycode == '.' )
+    int keycode = event.GetKeyCode();
+        if ( wxIsdigit(keycode) || keycode == '+' || keycode == '-' || keycode == '.'
+            || keycode ==  WXK_NUMPAD0
+            || keycode ==  WXK_NUMPAD1
+            || keycode ==  WXK_NUMPAD2
+            || keycode ==  WXK_NUMPAD3
+            || keycode ==  WXK_NUMPAD4
+            || keycode ==  WXK_NUMPAD5
+            || keycode ==  WXK_NUMPAD6
+            || keycode ==  WXK_NUMPAD7
+            || keycode ==  WXK_NUMPAD8
+            || keycode ==  WXK_NUMPAD9
+            || keycode ==  WXK_ADD
+            || keycode ==  WXK_NUMPAD_ADD
+            || keycode ==  WXK_SUBTRACT
+            || keycode ==  WXK_NUMPAD_SUBTRACT)
     {
         wxGridCellTextEditor::StartingKey(event);
 
@@ -1049,16 +1126,16 @@ wxString wxGridCellFloatEditor::GetString() const
     if ( m_width == -1 )
     {
         // default width/precision
-        fmt = _T("%g");
+        fmt = _T("%f");
     }
     else if ( m_precision == -1 )
     {
         // default precision
-        fmt.Printf(_T("%%%d.g"), m_width);
+        fmt.Printf(_T("%%%d.f"), m_width);
     }
     else
     {
-        fmt.Printf(_T("%%%d.%dg"), m_width, m_precision);
+        fmt.Printf(_T("%%%d.%df"), m_width, m_precision);
     }
 
     return wxString::Format(fmt, m_valueOld);
@@ -1092,7 +1169,7 @@ bool wxGridCellFloatEditor::IsAcceptedKey(wxKeyEvent& event)
             default:
                 // additionally accept 'e' as in '1e+6'
                 if ( (keycode < 128) &&
-                     (isdigit(keycode) || tolower(keycode) == 'e') )
+                     (wxIsdigit(keycode) || tolower(keycode) == 'e') )
                     return TRUE;
         }
     }
@@ -1160,7 +1237,32 @@ void wxGridCellBoolEditor::SetSize(const wxRect& r)
     size.y -= 2;
 #endif
 
-    m_control->Move(r.x + r.width/2 - size.x/2, r.y + r.height/2 - size.y/2);
+    int hAlign = wxALIGN_CENTRE;
+    int vAlign = wxALIGN_CENTRE;
+    if (GetCellAttr())
+        GetCellAttr()->GetAlignment(& hAlign, & vAlign);
+
+    int x = 0, y = 0;
+    if (hAlign == wxALIGN_LEFT)
+    {
+        x = r.x + 2;
+#ifdef __WXMSW__
+        x += 2;
+#endif
+        y = r.y + r.height/2 - size.y/2;
+    }
+    else if (hAlign == wxALIGN_RIGHT)
+    {
+        x = r.x + r.width - size.x - 2;
+        y = r.y + r.height/2 - size.y/2;
+    }
+    else if (hAlign == wxALIGN_CENTRE)
+    {
+        x = r.x + r.width/2 - size.x/2;
+        y = r.y + r.height/2 - size.y/2;
+    }
+
+    m_control->Move(x, y);
 }
 
 void wxGridCellBoolEditor::Show(bool show, wxGridCellAttr *attr)
@@ -1184,7 +1286,7 @@ void wxGridCellBoolEditor::BeginEdit(int row, int col, wxGrid* grid)
     else
     {
         wxString cellval( grid->GetTable()->GetValue(row, col) );
-        m_startValue = !( !cellval || (cellval == "0") );
+        m_startValue = !( !cellval || (cellval == wxT("0")) );
     }
     CBox()->SetValue(m_startValue);
     CBox()->SetFocus();
@@ -1248,6 +1350,13 @@ bool wxGridCellBoolEditor::IsAcceptedKey(wxKeyEvent& event)
     return FALSE;
 }
 
+// return the value as "1" for true and the empty string for false
+wxString wxGridCellBoolEditor::GetValue() const
+{
+  bool bSet = CBox()->GetValue();
+  return bSet ? _T("1") : wxEmptyString;
+}
+
 #endif // wxUSE_CHECKBOX
 
 #if wxUSE_COMBOBOX
@@ -1320,15 +1429,15 @@ void wxGridCellChoiceEditor::BeginEdit(int row, int col, wxGrid* grid)
 
     m_startValue = grid->GetTable()->GetValue(row, col);
 
-    Combo()->SetValue(m_startValue);
-    size_t count = m_choices.GetCount();
-    for (size_t i=0; i<count; i++)
+    if (m_allowOthers)
+        Combo()->SetValue(m_startValue);
+    else
     {
-        if (m_startValue == m_choices[i])
-        {
-            Combo()->SetSelection(i);
-            break;
-        }
+        // find the right position, or default to the first if not found
+        int pos = Combo()->FindString(m_startValue);
+        if (pos == -1)
+            pos = 0;
+        Combo()->SetSelection(pos);
     }
     Combo()->SetInsertionPointEnd();
     Combo()->SetFocus();
@@ -1344,7 +1453,10 @@ bool wxGridCellChoiceEditor::EndEdit(int row, int col,
         grid->GetTable()->SetValue(row, col, value);
 
     m_startValue = wxEmptyString;
-    Combo()->SetValue(m_startValue);
+    if (m_allowOthers)
+        Combo()->SetValue(m_startValue);
+    else
+        Combo()->SetSelection(0);
 
     return changed;
 }
@@ -1372,6 +1484,12 @@ void wxGridCellChoiceEditor::SetParameters(const wxString& params)
     }
 }
 
+// return the value in the text control
+wxString wxGridCellChoiceEditor::GetValue() const
+{
+  return Combo()->GetValue();
+}
+
 #endif // wxUSE_COMBOBOX
 
 // ----------------------------------------------------------------------------
@@ -1380,7 +1498,7 @@ void wxGridCellChoiceEditor::SetParameters(const wxString& params)
 
 void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent& event)
 {
-    switch ( event.KeyCode() )
+    switch ( event.GetKeyCode() )
     {
         case WXK_ESCAPE:
             m_editor->Reset();
@@ -1405,7 +1523,7 @@ void wxGridCellEditorEvtHandler::OnKeyDown(wxKeyEvent& event)
 
 void wxGridCellEditorEvtHandler::OnChar(wxKeyEvent& event)
 {
-    switch ( event.KeyCode() )
+    switch ( event.GetKeyCode() )
     {
         case WXK_ESCAPE:
         case WXK_TAB:
@@ -1449,13 +1567,21 @@ void wxGridCellRenderer::Draw(wxGrid& grid,
 {
     dc.SetBackgroundMode( wxSOLID );
 
-    if ( isSelected )
+    // grey out fields if the grid is disabled
+    if( grid.IsEnabled() )
     {
-        dc.SetBrush( wxBrush(grid.GetSelectionBackground(), wxSOLID) );
+      if ( isSelected )
+      {
+          dc.SetBrush( wxBrush(grid.GetSelectionBackground(), wxSOLID) );
+      }
+      else
+      {
+          dc.SetBrush( wxBrush(attr.GetBackgroundColour(), wxSOLID) );
+      }
     }
     else
     {
-        dc.SetBrush( wxBrush(attr.GetBackgroundColour(), wxSOLID) );
+      dc.SetBrush(wxBrush(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE), wxSOLID));
     }
 
     dc.SetPen( *wxTRANSPARENT_PEN );
@@ -1475,15 +1601,24 @@ void wxGridCellStringRenderer::SetTextColoursAndFont(wxGrid& grid,
 
     // TODO some special colours for attr.IsReadOnly() case?
 
-    if ( isSelected )
+    // different coloured text when the grid is disabled
+    if( grid.IsEnabled() )
     {
-        dc.SetTextBackground( grid.GetSelectionBackground() );
-        dc.SetTextForeground( grid.GetSelectionForeground() );
+      if ( isSelected )
+      {
+          dc.SetTextBackground( grid.GetSelectionBackground() );
+          dc.SetTextForeground( grid.GetSelectionForeground() );
+      }
+      else
+      {
+          dc.SetTextBackground( attr.GetBackgroundColour() );
+          dc.SetTextForeground( attr.GetTextColour() );
+      }
     }
     else
     {
-        dc.SetTextBackground( attr.GetBackgroundColour() );
-        dc.SetTextForeground( attr.GetTextColour() );
+      dc.SetTextBackground(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_BTNFACE));
+      dc.SetTextForeground(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_GRAYTEXT));
     }
 
     dc.SetFont( attr.GetFont() );
@@ -1522,16 +1657,85 @@ void wxGridCellStringRenderer::Draw(wxGrid& grid,
                                     int row, int col,
                                     bool isSelected)
 {
-    wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
+    wxRect rect = rectCell;
+    rect.Inflate(-1);
 
-    // now we only have to draw the text
-    SetTextColoursAndFont(grid, attr, dc, isSelected);
+    // erase only this cells background, overflow cells should have been erased
+    wxGridCellRenderer::Draw(grid, attr, dc, rectCell, row, col, isSelected);
 
     int hAlign, vAlign;
     attr.GetAlignment(&hAlign, &vAlign);
 
-    wxRect rect = rectCell;
-    rect.Inflate(-1);
+    int overflowCols = 0;
+
+    if (attr.GetOverflow())
+    {
+        int cols = grid.GetNumberCols();
+        int best_width = GetBestSize(grid,attr,dc,row,col).GetWidth();
+        int cell_rows, cell_cols;
+        attr.GetSize( &cell_rows, &cell_cols ); // shouldn't get here if <=0
+        if ((best_width > rectCell.width) && (col < cols) && grid.GetTable())
+        {
+            int i, c_cols, c_rows;
+            for (i = col+cell_cols; i < cols; i++)
+            {
+                bool is_empty = TRUE;
+                for (int j=row; j<row+cell_rows; j++)
+                {
+                    // check w/ anchor cell for multicell block
+                    grid.GetCellSize(j, i, &c_rows, &c_cols);
+                    if (c_rows > 0) c_rows = 0;
+                    if (!grid.GetTable()->IsEmptyCell(j+c_rows, i))
+                    {
+                        is_empty = FALSE;
+                        break;
+                    }
+                }
+                if (is_empty)
+                    rect.width += grid.GetColSize(i);
+                else
+                {
+                    i--;
+                    break;
+                }
+                if (rect.width >= best_width) break;
+            }
+            overflowCols = i - col - cell_cols + 1;
+            if (overflowCols >= cols) overflowCols = cols - 1;
+        }
+
+        if (overflowCols > 0) // redraw overflow cells w/ proper hilight
+        {
+            hAlign = wxALIGN_LEFT; // if oveflowed then it's left aligned
+            wxRect clip = rect;
+            clip.x += rectCell.width;
+            // draw each overflow cell individually
+            int col_end = col+cell_cols+overflowCols;
+            if (col_end >= grid.GetNumberCols())
+                col_end = grid.GetNumberCols() - 1;
+            for (int i = col+cell_cols; i <= col_end; i++)
+            {
+                clip.width = grid.GetColSize(i) - 1;
+                dc.DestroyClippingRegion();
+                dc.SetClippingRegion(clip);
+
+                SetTextColoursAndFont(grid, attr, dc,
+                        grid.IsInSelection(row,i));
+
+                grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
+                        rect, hAlign, vAlign);
+                clip.x += grid.GetColSize(i) - 1;
+            }
+
+            rect = rectCell;
+            rect.Inflate(-1);
+            rect.width++;
+            dc.DestroyClippingRegion();
+        }
+    }
+
+    // now we only have to draw the text
+    SetTextColoursAndFont(grid, attr, dc, isSelected);
 
     grid.DrawTextRectangle(dc, grid.GetCellValue(row, col),
                            rect, hAlign, vAlign);
@@ -1633,9 +1837,9 @@ wxString wxGridCellFloatRenderer::GetString(wxGrid& grid, int row, int col)
             {
                 if ( m_precision == -1 )
                 {
-                // default width/precision
-                m_format = _T("%f");
-            }
+                    // default width/precision
+                    m_format = _T("%f");
+                }
                 else
                 {
                     m_format.Printf(_T("%%.%df"), m_precision);
@@ -1792,11 +1996,31 @@ void wxGridCellBoolRenderer::Draw(wxGrid& grid,
     }
 
     // draw a border around checkmark
+    int vAlign, hAlign;
+    attr.GetAlignment(& hAlign, &vAlign);
+
     wxRect rectBorder;
-    rectBorder.x = rect.x + rect.width/2 - size.x/2;
-    rectBorder.y = rect.y + rect.height/2 - size.y/2;
-    rectBorder.width = size.x;
-    rectBorder.height = size.y;
+    if (hAlign == wxALIGN_CENTRE)
+    {
+        rectBorder.x = rect.x + rect.width/2 - size.x/2;
+        rectBorder.y = rect.y + rect.height/2 - size.y/2;
+        rectBorder.width = size.x;
+        rectBorder.height = size.y;
+    }
+    else if (hAlign == wxALIGN_LEFT)
+    {
+        rectBorder.x = rect.x + 2;
+        rectBorder.y = rect.y + rect.height/2 - size.y/2;
+        rectBorder.width = size.x;
+        rectBorder.height = size.y;
+    }
+    else if (hAlign == wxALIGN_RIGHT)
+    {
+        rectBorder.x = rect.x + rect.width - size.x - 2;
+        rectBorder.y = rect.y + rect.height/2 - size.y/2;
+        rectBorder.width = size.x;
+        rectBorder.height = size.y;
+    }
 
     bool value;
     if ( grid.GetTable()->CanGetValueAs(row, col, wxGRID_VALUE_BOOL) )
@@ -1804,7 +2028,7 @@ void wxGridCellBoolRenderer::Draw(wxGrid& grid,
     else
     {
         wxString cellval( grid.GetTable()->GetValue(row, col) );
-        value = !( !cellval || (cellval == "0") );
+        value = !( !cellval || (cellval == wxT("0")) );
     }
 
     if ( value )
@@ -1843,6 +2067,9 @@ void wxGridCellAttr::Init(wxGridCellAttr *attrDefault)
 
     m_attrkind = wxGridCellAttr::Cell;
 
+    m_sizeRows = m_sizeCols = 1;
+    m_overflow = UnsetOverflow;
+
     SetDefAttr(attrDefault);
 }
 
@@ -1859,6 +2086,8 @@ wxGridCellAttr *wxGridCellAttr::Clone() const
     if ( HasAlignment() )
         attr->SetAlignment(m_hAlign, m_vAlign);
 
+    attr->SetSize( m_sizeRows, m_sizeCols );
+
     if ( m_renderer )
     {
         attr->SetRenderer(m_renderer);
@@ -1886,12 +2115,14 @@ void wxGridCellAttr::MergeWith(wxGridCellAttr *mergefrom)
         SetBackgroundColour(mergefrom->GetBackgroundColour());
     if ( !HasFont() && mergefrom->HasFont() )
         SetFont(mergefrom->GetFont());
-    if ( !!HasAlignment() && mergefrom->HasAlignment() ){
+    if ( !HasAlignment() && mergefrom->HasAlignment() ){
         int hAlign, vAlign;
         mergefrom->GetAlignment( &hAlign, &vAlign);
         SetAlignment(hAlign, vAlign);
     }
 
+    mergefrom->GetSize( &m_sizeRows, &m_sizeCols );
+
     // Directly access member functions as GetRender/Editor don't just return
     // m_renderer/m_editor
     //
@@ -1909,9 +2140,33 @@ void wxGridCellAttr::MergeWith(wxGridCellAttr *mergefrom)
     if ( !HasReadWriteMode()  && mergefrom->HasReadWriteMode() )
         SetReadOnly(mergefrom->IsReadOnly());
 
+    if (!HasOverflowMode()  && mergefrom->HasOverflowMode() )
+        SetOverflow(mergefrom->GetOverflow());
+
     SetDefAttr(mergefrom->m_defGridAttr);
 }
 
+void wxGridCellAttr::SetSize(int num_rows, int num_cols)
+{
+    // The size of a cell is normally 1,1
+
+    // If this cell is larger (2,2) then this is the top left cell
+    // the other cells that will be covered (lower right cells) must be
+    // set to negative or zero values such that
+    // row + num_rows of the covered cell points to the larger cell (this cell)
+    // same goes for the col + num_cols.
+
+    // Size of 0,0 is NOT valid, neither is <=0 and any positive value
+
+    wxASSERT_MSG( (!((num_rows>0)&&(num_cols<=0)) ||
+                  !((num_rows<=0)&&(num_cols>0)) ||
+                  !((num_rows==0)&&(num_cols==0))),
+                  wxT("wxGridCellAttr::SetSize only takes two postive values or negative/zero values"));
+
+    m_sizeRows = num_rows;
+    m_sizeCols = num_cols;
+}
+
 const wxColour& wxGridCellAttr::GetTextColour() const
 {
     if (HasTextColour())
@@ -1973,6 +2228,11 @@ void wxGridCellAttr::GetAlignment(int *hAlign, int *vAlign) const
     }
 }
 
+void wxGridCellAttr::GetSize( int *num_rows, int *num_cols ) const
+{
+    if ( num_rows ) *num_rows = m_sizeRows;
+    if ( num_cols ) *num_cols = m_sizeCols;
+}
 
 // GetRenderer and GetEditor use a slightly different decision path about
 // which attribute to use.  If a non-default attr object has one then it is
@@ -2850,21 +3110,13 @@ wxGridStringTable::wxGridStringTable()
 wxGridStringTable::wxGridStringTable( int numRows, int numCols )
         : wxGridTableBase()
 {
-    int row, col;
-
     m_data.Alloc( numRows );
 
     wxArrayString sa;
     sa.Alloc( numCols );
-    for ( col = 0;  col < numCols;  col++ )
-    {
-        sa.Add( wxEmptyString );
-    }
+    sa.Add( wxEmptyString, numCols );
 
-    for ( row = 0;  row < numRows;  row++ )
-    {
-        m_data.Add( sa );
-    }
+    m_data.Add( sa, numRows );
 }
 
 wxGridStringTable::~wxGridStringTable()
@@ -2931,8 +3183,6 @@ void wxGridStringTable::Clear()
 
 bool wxGridStringTable::InsertRows( size_t pos, size_t numRows )
 {
-    size_t row, col;
-
     size_t curNumRows = m_data.GetCount();
     size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() :
                           ( GetView() ? GetView()->GetNumberCols() : 0 ) );
@@ -2944,15 +3194,8 @@ bool wxGridStringTable::InsertRows( size_t pos, size_t numRows )
 
     wxArrayString sa;
     sa.Alloc( curNumCols );
-    for ( col = 0;  col < curNumCols;  col++ )
-    {
-        sa.Add( wxEmptyString );
-    }
-
-    for ( row = pos;  row < pos + numRows;  row++ )
-    {
-        m_data.Insert( sa, row );
-    }
+    sa.Add( wxEmptyString, curNumCols );
+    m_data.Insert( sa, pos, numRows );
     if ( GetView() )
     {
         wxGridTableMessage msg( this,
@@ -2968,8 +3211,6 @@ bool wxGridStringTable::InsertRows( size_t pos, size_t numRows )
 
 bool wxGridStringTable::AppendRows( size_t numRows )
 {
-    size_t row, col;
-
     size_t curNumRows = m_data.GetCount();
     size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() :
                           ( GetView() ? GetView()->GetNumberCols() : 0 ) );
@@ -2978,16 +3219,10 @@ bool wxGridStringTable::AppendRows( size_t numRows )
     if ( curNumCols > 0 )
     {
         sa.Alloc( curNumCols );
-        for ( col = 0;  col < curNumCols;  col++ )
-        {
-            sa.Add( wxEmptyString );
-        }
+        sa.Add( wxEmptyString, curNumCols );
     }
 
-    for ( row = 0;  row < numRows;  row++ )
-    {
-        m_data.Add( sa );
-    }
+    m_data.Add( sa, numRows );
 
     if ( GetView() )
     {
@@ -3003,16 +3238,18 @@ bool wxGridStringTable::AppendRows( size_t numRows )
 
 bool wxGridStringTable::DeleteRows( size_t pos, size_t numRows )
 {
-    size_t n;
-
     size_t curNumRows = m_data.GetCount();
 
     if ( pos >= curNumRows )
     {
-        wxString errmsg;
-        errmsg.Printf(wxT("Called wxGridStringTable::DeleteRows(pos=%d, N=%d)\nPos value is invalid for present table with %d rows"),
-                      pos, numRows, curNumRows );
-        wxFAIL_MSG( errmsg );
+        wxFAIL_MSG( wxString::Format
+                    (
+                        wxT("Called wxGridStringTable::DeleteRows(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu rows"),
+                        (unsigned long)pos,
+                        (unsigned long)numRows,
+                        (unsigned long)curNumRows
+                    ) );
+
         return FALSE;
     }
 
@@ -3023,14 +3260,11 @@ bool wxGridStringTable::DeleteRows( size_t pos, size_t numRows )
 
     if ( numRows >= curNumRows )
     {
-        m_data.Empty();  // don't release memory just yet
+        m_data.Clear();
     }
     else
     {
-        for ( n = 0;  n < numRows;  n++ )
-        {
-            m_data.RemoveAt( pos );
-        }
+        m_data.RemoveAt( pos, numRows );
     }
     if ( GetView() )
     {
@@ -3080,7 +3314,7 @@ bool wxGridStringTable::InsertCols( size_t pos, size_t numCols )
 
 bool wxGridStringTable::AppendCols( size_t numCols )
 {
-    size_t row, n;
+    size_t row;
 
     size_t curNumRows = m_data.GetCount();
 #if 0
@@ -3095,10 +3329,7 @@ bool wxGridStringTable::AppendCols( size_t numCols )
 
     for ( row = 0;  row < curNumRows;  row++ )
     {
-        for ( n = 0;  n < numCols;  n++ )
-        {
-            m_data[row].Add( wxEmptyString );
-        }
+        m_data[row].Add( wxEmptyString, numCols );
     }
 
     if ( GetView() )
@@ -3115,7 +3346,7 @@ bool wxGridStringTable::AppendCols( size_t numCols )
 
 bool wxGridStringTable::DeleteCols( size_t pos, size_t numCols )
 {
-    size_t row, n;
+    size_t row;
 
     size_t curNumRows = m_data.GetCount();
     size_t curNumCols = ( curNumRows > 0 ? m_data[0].GetCount() :
@@ -3123,10 +3354,13 @@ bool wxGridStringTable::DeleteCols( size_t pos, size_t numCols )
 
     if ( pos >= curNumCols )
     {
-        wxString errmsg;
-        errmsg.Printf( wxT("Called wxGridStringTable::DeleteCols(pos=%d, N=%d)...\nPos value is invalid for present table with %d cols"),
-                        pos, numCols, curNumCols );
-        wxFAIL_MSG( errmsg );
+        wxFAIL_MSG( wxString::Format
+                    (
+                        wxT("Called wxGridStringTable::DeleteCols(pos=%lu, N=%lu)\nPos value is invalid for present table with %lu cols"),
+                        (unsigned long)pos,
+                        (unsigned long)numCols,
+                        (unsigned long)curNumCols
+                    ) );
         return FALSE;
     }
 
@@ -3143,10 +3377,7 @@ bool wxGridStringTable::DeleteCols( size_t pos, size_t numCols )
         }
         else
         {
-            for ( n = 0;  n < numCols;  n++ )
-            {
-                m_data[row].RemoveAt( pos );
-            }
+            m_data[row].RemoveAt( pos, numCols );
         }
     }
     if ( GetView() )
@@ -3238,7 +3469,7 @@ END_EVENT_TABLE()
 wxGridRowLabelWindow::wxGridRowLabelWindow( wxGrid *parent,
                                             wxWindowID id,
                                             const wxPoint &pos, const wxSize &size )
-  : wxWindow( parent, id, pos, size, wxWANTS_CHARS )
+  : wxWindow( parent, id, pos, size, wxWANTS_CHARS|wxBORDER_NONE )
 {
     m_owner = parent;
 }
@@ -3304,7 +3535,7 @@ END_EVENT_TABLE()
 wxGridColLabelWindow::wxGridColLabelWindow( wxGrid *parent,
                                             wxWindowID id,
                                             const wxPoint &pos, const wxSize &size )
-  : wxWindow( parent, id, pos, size, wxWANTS_CHARS )
+  : wxWindow( parent, id, pos, size, wxWANTS_CHARS|wxBORDER_NONE )
 {
     m_owner = parent;
 }
@@ -3369,7 +3600,7 @@ END_EVENT_TABLE()
 wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid *parent,
                                                   wxWindowID id,
                                                   const wxPoint &pos, const wxSize &size )
-  : wxWindow( parent, id, pos, size, wxWANTS_CHARS )
+  : wxWindow( parent, id, pos, size, wxWANTS_CHARS|wxBORDER_NONE )
 {
     m_owner = parent;
 }
@@ -3382,13 +3613,15 @@ void wxGridCornerLabelWindow::OnPaint( wxPaintEvent& WXUNUSED(event) )
     int client_width = 0;
     GetClientSize( &client_width, &client_height );
 
-    dc.SetPen( *wxBLACK_PEN );
+    dc.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW),1, wxSOLID) );
     dc.DrawLine( client_width-1, client_height-1, client_width-1, 0 );
     dc.DrawLine( client_width-1, client_height-1, 0, client_height-1 );
-
-    dc.SetPen( *wxWHITE_PEN );
     dc.DrawLine( 0, 0, client_width, 0 );
     dc.DrawLine( 0, 0, 0, client_height );
+
+    dc.SetPen( *wxWHITE_PEN );
+    dc.DrawLine( 1, 1, client_width-1, 1 );
+    dc.DrawLine( 1, 1, 1, client_height-1 );
 }
 
 
@@ -3434,8 +3667,12 @@ END_EVENT_TABLE()
 wxGridWindow::wxGridWindow( wxGrid *parent,
                             wxGridRowLabelWindow *rowLblWin,
                             wxGridColLabelWindow *colLblWin,
-                            wxWindowID id, const wxPoint &pos, const wxSize &size )
-        : wxWindow( parent, id, pos, size, wxWANTS_CHARS, "grid window" )
+                            wxWindowID id,
+                            const wxPoint &pos,
+                            const wxSize &size )
+            : wxWindow( parent, id, pos, size, wxWANTS_CHARS | wxBORDER_NONE | wxCLIP_CHILDREN,
+                        wxT("grid window") )
+
 {
     m_owner = parent;
     m_rowLabelWin = rowLblWin;
@@ -3504,20 +3741,21 @@ 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 
+// 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);
+                           const wxArrayInt& BorderArray, int nMax,
+                           bool clipToMinMax);
 
 #define internalXToCol(x) CoordToRowOrCol(x, m_defaultColWidth, \
-                                          WXGRID_MIN_COL_WIDTH, \
-                                          m_colRights, TRUE)
+                                          m_minAcceptableColWidth, \
+                                          m_colRights, m_numCols, TRUE)
 #define internalYToRow(y) CoordToRowOrCol(y, m_defaultRowHeight, \
-                                          WXGRID_MIN_ROW_HEIGHT, \
-                                          m_rowBottoms, TRUE)
+                                          m_minAcceptableRowHeight, \
+                                          m_rowBottoms, m_numRows, TRUE)
 /////////////////////////////////////////////////////////////////////
 
 IMPLEMENT_DYNAMIC_CLASS( wxGrid, wxScrolledWindow )
@@ -3665,21 +3903,36 @@ void wxGrid::SetSelectionMode(wxGrid::wxGridSelectionModes selmode)
     m_selection->SetSelectionMode( selmode );
 }
 
+wxGrid::wxGridSelectionModes wxGrid::GetSelectionMode() const
+{
+    wxCHECK_MSG( m_created, wxGrid::wxGridSelectCells,
+                 wxT("Called wxGrid::GetSelectionMode() before calling CreateGrid()") );
+
+    return m_selection->GetSelectionMode();
+}
+
 bool wxGrid::SetTable( wxGridTableBase *table, bool takeOwnership,
                        wxGrid::wxGridSelectionModes selmode )
 {
     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 implementation that
-        //     would prevent this?
+        // stop all processing 
+        m_created = FALSE; 
 
-        // At least, you now have to cope with m_selection
-        wxFAIL_MSG( wxT("wxGrid::CreateGrid or wxGrid::SetTable called more than once") );
-        return FALSE;
+        if (m_ownTable)
+        {
+            wxGridTableBase *t=m_table;
+            m_table=0;
+            delete t; 
+        }
+        delete m_selection; 
+        m_table=0; 
+        m_selection=0; 
+        m_numRows=0; 
+        m_numCols=0; 
     }
-    else
+    if (table)
     {
         m_numRows = table->GetNumberRows();
         m_numCols = table->GetNumberCols();
@@ -3717,30 +3970,36 @@ void wxGrid::Init()
 
     // init attr cache
     m_attrCache.row = -1;
+    m_attrCache.col = -1;
+    m_attrCache.attr = NULL;
 
     // TODO: something better than this ?
     //
     m_labelFont = this->GetFont();
-    m_labelFont.SetWeight( m_labelFont.GetWeight() + 2 );
+    m_labelFont.SetWeight( wxBOLD );
 
-    m_rowLabelHorizAlign = wxALIGN_LEFT;
+    m_rowLabelHorizAlign = wxALIGN_CENTRE;
     m_rowLabelVertAlign  = wxALIGN_CENTRE;
 
     m_colLabelHorizAlign = wxALIGN_CENTRE;
-    m_colLabelVertAlign  = wxALIGN_TOP;
+    m_colLabelVertAlign  = wxALIGN_CENTRE;
+    m_colLabelTextOrientation = wxHORIZONTAL;
 
     m_defaultColWidth  = WXGRID_DEFAULT_COL_WIDTH;
     m_defaultRowHeight = m_gridWin->GetCharHeight();
 
+    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( 128, 128, 255 );
+    m_gridLineColour = wxColour( 192,192,192 );
     m_gridLinesEnabled = TRUE;
-    m_cellHighlightColour = m_gridLineColour;
+    m_cellHighlightColour = *wxBLACK;
     m_cellHighlightPenWidth = 2;
     m_cellHighlightROPenWidth = 1;
 
@@ -3794,9 +4053,11 @@ void wxGrid::InitRowHeights()
     m_rowBottoms.Alloc( m_numRows );
 
     int rowBottom = 0;
+
+    m_rowHeights.Add( m_defaultRowHeight, m_numRows );
+
     for ( int i = 0;  i < m_numRows;  i++ )
     {
-        m_rowHeights.Add( m_defaultRowHeight );
         rowBottom += m_defaultRowHeight;
         m_rowBottoms.Add( rowBottom );
     }
@@ -3810,9 +4071,11 @@ void wxGrid::InitColWidths()
     m_colWidths.Alloc( m_numCols );
     m_colRights.Alloc( m_numCols );
     int colRight = 0;
+
+    m_colWidths.Add( m_defaultColWidth, m_numCols );
+
     for ( int i = 0;  i < m_numCols;  i++ )
     {
-        m_colWidths.Add( m_defaultColWidth );
         colRight += m_defaultColWidth;
         m_colRights.Add( colRight );
     }
@@ -3866,6 +4129,27 @@ void wxGrid::CalcDimensions()
     int w = m_numCols > 0 ? GetColRight(m_numCols - 1) + m_extraWidth + 1 : 0;
     int h = m_numRows > 0 ? GetRowBottom(m_numRows - 1) + m_extraHeight + 1 : 0;
 
+    // take into account editor if shown
+    if( IsCellEditControlShown() )
+    {
+      int w2, h2;
+      int r = m_currentCellCoords.GetRow();
+      int c = m_currentCellCoords.GetCol();
+      int x = GetColLeft(c);
+      int y = GetRowTop(r);
+
+      // how big is the editor
+      wxGridCellAttr* attr = GetCellAttr(r, c);
+      wxGridCellEditor* editor = attr->GetEditor(this, r, c);
+      editor->GetControl()->GetSize(&w2, &h2);
+      w2 += x;
+      h2 += y;
+      if( w2 > w ) w = w2;
+      if( h2 > h ) h = h2;
+      editor->DecRef();
+      attr->DecRef();
+    }
+
     // preserve (more or less) the previous position
     int x, y;
     GetViewStart( &x, &y );
@@ -3931,6 +4215,15 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
     int i;
     bool result = FALSE;
 
+    // Clear the attribute cache as the attribute might refer to a different
+    // cell than stored in the cache after adding/removing rows/columns.
+    ClearAttrCache();
+    // By the same reasoning, the editor should be dismissed if columns are
+    // added or removed. And for consistency, it should IMHO always be
+    // removed, not only if the cell "underneath" it actually changes.
+    // For now, I intentionally do not save the editor's content as the
+    // 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
@@ -3956,11 +4249,8 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
 
             if ( !m_rowHeights.IsEmpty() )
             {
-                for ( i = 0;  i < numRows;  i++ )
-                {
-                    m_rowHeights.Insert( m_defaultRowHeight, pos );
-                    m_rowBottoms.Insert( 0, pos );
-                }
+                m_rowHeights.Insert( m_defaultRowHeight, pos, numRows );
+                m_rowBottoms.Insert( 0, pos, numRows );
 
                 int bottom = 0;
                 if ( pos > 0 ) bottom = m_rowBottoms[pos-1];
@@ -4002,11 +4292,8 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
 
             if ( !m_rowHeights.IsEmpty() )
             {
-                for ( i = 0;  i < numRows;  i++ )
-                {
-                    m_rowHeights.Add( m_defaultRowHeight );
-                    m_rowBottoms.Add( 0 );
-                }
+                m_rowHeights.Add( m_defaultRowHeight, numRows );
+                m_rowBottoms.Add( 0, numRows );
 
                 int bottom = 0;
                 if ( oldNumRows > 0 ) bottom = m_rowBottoms[oldNumRows-1];
@@ -4041,11 +4328,8 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
 
             if ( !m_rowHeights.IsEmpty() )
             {
-                for ( i = 0;  i < numRows;  i++ )
-                {
-                    m_rowHeights.RemoveAt( pos );
-                    m_rowBottoms.RemoveAt( pos );
-                }
+                m_rowHeights.RemoveAt( pos, numRows );
+                m_rowBottoms.RemoveAt( pos, numRows );
 
                 int h = 0;
                 for ( i = 0;  i < m_numRows;  i++ )
@@ -4097,11 +4381,8 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
 
             if ( !m_colWidths.IsEmpty() )
             {
-                for ( i = 0;  i < numCols;  i++ )
-                {
-                    m_colWidths.Insert( m_defaultColWidth, pos );
-                    m_colRights.Insert( 0, pos );
-                }
+                m_colWidths.Insert( m_defaultColWidth, pos, numCols );
+                m_colRights.Insert( 0, pos, numCols );
 
                 int right = 0;
                 if ( pos > 0 ) right = m_colRights[pos-1];
@@ -4142,11 +4423,8 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
             m_numCols += numCols;
             if ( !m_colWidths.IsEmpty() )
             {
-                for ( i = 0;  i < numCols;  i++ )
-                {
-                    m_colWidths.Add( m_defaultColWidth );
-                    m_colRights.Add( 0 );
-                }
+                m_colWidths.Add( m_defaultColWidth, numCols );
+                m_colRights.Add( 0, numCols );
 
                 int right = 0;
                 if ( oldNumCols > 0 ) right = m_colRights[oldNumCols-1];
@@ -4181,11 +4459,8 @@ bool wxGrid::Redimension( wxGridTableMessage& msg )
 
             if ( !m_colWidths.IsEmpty() )
             {
-                for ( i = 0;  i < numCols;  i++ )
-                {
-                    m_colWidths.RemoveAt( pos );
-                    m_colRights.RemoveAt( pos );
-                }
+                m_colWidths.RemoveAt( pos, numCols );
+                m_colRights.RemoveAt( pos, numCols );
 
                 int w = 0;
                 for ( i = 0;  i < m_numCols;  i++ )
@@ -4464,7 +4739,7 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
 
     if (m_isDragging)
     {
-        m_rowLabelWin->ReleaseMouse();
+        if (m_rowLabelWin->HasCapture()) m_rowLabelWin->ReleaseMouse();
         m_isDragging = FALSE;
     }
 
@@ -4492,7 +4767,7 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
             {
                 if ( !event.ShiftDown() && !event.ControlDown() )
                     ClearSelection();
-                else if ( m_selection )
+                if ( m_selection )
                 {
                     if ( event.ShiftDown() )
                     {
@@ -4532,10 +4807,23 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
     //
     else if (event.LeftDClick() )
     {
-        if ( YToEdgeOfRow(y) < 0 )
+        int row = YToEdgeOfRow(y);
+        if ( row < 0 )
         {
             row = YToRow(y);
-            SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK, row, -1, event );
+            if ( row >=0 &&
+                !SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK, row, -1, event ) )
+           {
+                // no default action at the moment
+           }
+        }
+        else
+        {
+            // adjust row height depending on label text
+            AutoSizeRowLabelSize( row );
+
+            ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, m_colLabelWin);
+            m_dragLastPos  = -1;
         }
     }
 
@@ -4564,7 +4852,8 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
     else if ( event.RightDown() )
     {
         row = YToRow(y);
-        if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK, row, -1, event ) )
+        if ( row >=0 &&
+           !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK, row, -1, event ) )
         {
             // no default action at the moment
         }
@@ -4576,7 +4865,8 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event )
     else if ( event.RightDClick() )
     {
         row = YToRow(y);
-        if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK, row, -1, event ) )
+        if ( row >= 0 &&
+            !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK, row, -1, event ) )
         {
             // no default action at the moment
         }
@@ -4671,7 +4961,7 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
 
     if (m_isDragging)
     {
-        m_colLabelWin->ReleaseMouse();
+        if (m_colLabelWin->HasCapture()) m_colLabelWin->ReleaseMouse();
         m_isDragging = FALSE;
     }
 
@@ -4738,10 +5028,23 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
     //
     if ( event.LeftDClick() )
     {
-        if ( XToEdgeOfCol(x) < 0 )
+        int col = XToEdgeOfCol(x);
+        if ( col < 0 )
         {
             col = XToCol(x);
-            SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK, -1, col, event );
+            if ( col >= 0 &&
+                 ! SendEvent( wxEVT_GRID_LABEL_LEFT_DCLICK, -1, col, event ) )
+            {
+               // no default action at the moment
+            }
+        }
+        else
+        {
+            // adjust column width depending on label text
+            AutoSizeColLabelSize( col );
+
+            ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL, m_colLabelWin);
+            m_dragLastPos  = -1;
         }
     }
 
@@ -4770,7 +5073,8 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
     else if ( event.RightDown() )
     {
         col = XToCol(x);
-        if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK, -1, col, event ) )
+        if ( col >= 0 &&
+            !SendEvent( wxEVT_GRID_LABEL_RIGHT_CLICK, -1, col, event ) )
         {
             // no default action at the moment
         }
@@ -4782,7 +5086,8 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event )
     else if ( event.RightDClick() )
     {
         col = XToCol(x);
-        if ( !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK, -1, col, event ) )
+        if ( col >= 0 &&
+            !SendEvent( wxEVT_GRID_LABEL_RIGHT_DCLICK, -1, col, event ) )
         {
             // no default action at the moment
         }
@@ -4881,7 +5186,7 @@ void wxGrid::ChangeCursorMode(CursorMode mode,
 
     if ( m_winCapture )
     {
-        m_winCapture->ReleaseMouse();
+        if (m_winCapture->HasCapture()) m_winCapture->ReleaseMouse();
         m_winCapture = (wxWindow *)NULL;
     }
 
@@ -4921,6 +5226,14 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
     wxGridCellCoords coords;
     XYToCell( x, y, coords );
 
+    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 ( event.Dragging() )
     {
         //wxLogDebug("pos(%d, %d) coords(%d, %d)", pos.x, pos.y, coords.GetRow(), coords.GetCol());
@@ -5070,54 +5383,33 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
                 DisableCellEditControl();
                 MakeCellVisible( coords );
 
-                // if this is the second click on this cell then start
-                // the edit control
-                if ( m_waitForSlowClick &&
-                     (coords == m_currentCellCoords) &&
-                     CanEnableCellControl())
+                if ( event.ControlDown() )
                 {
-                    EnableCellEditControl();
-
-                    wxGridCellAttr* attr = GetCellAttr(m_currentCellCoords);
-                    wxGridCellEditor *editor = attr->GetEditor(this,
-                                                               coords.GetRow(),
-                                                               coords.GetCol());
-                    editor->StartingClick();
-                    editor->DecRef();
-                    attr->DecRef();
-
-                    m_waitForSlowClick = FALSE;
+                    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
                 {
-                    if ( event.ControlDown() )
-                    {
-                        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 );
+                    if ( m_selection )
                     {
-                        SetCurrentCell( coords );
-                        if ( m_selection )
+                        if ( m_selection->GetSelectionMode() !=
+                                wxGrid::wxGridSelectCells )
                         {
-                            if ( m_selection->GetSelectionMode() != 
-                                    wxGrid::wxGridSelectCells )
-                            {
-                                HighlightBlock( coords, coords );
-                            }
+                            HighlightBlock( coords, coords );
                         }
                     }
-                    m_waitForSlowClick = TRUE;
                 }
             }
         }
@@ -5146,15 +5438,28 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
     {
         if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL )
         {
-            if ( m_selectingTopLeft != wxGridNoCellCoords &&
-                 m_selectingBottomRight != wxGridNoCellCoords )
+            if (m_winCapture)
             {
-                if (m_winCapture)
-                {
-                    m_winCapture->ReleaseMouse();
-                    m_winCapture = NULL;
-                }
+                if (m_winCapture->HasCapture()) m_winCapture->ReleaseMouse();
+                m_winCapture = NULL;
+            }
+
+            if ( coords == m_currentCellCoords && m_waitForSlowClick && CanEnableCellControl())
+            {
+                ClearSelection();
+                EnableCellEditControl();
+
+                wxGridCellAttr* attr = GetCellAttr(coords);
+                wxGridCellEditor *editor = attr->GetEditor(this, coords.GetRow(), coords.GetCol());
+                editor->StartingClick();
+                editor->DecRef();
+                attr->DecRef();
 
+                m_waitForSlowClick = FALSE;
+            }
+            else if ( m_selectingTopLeft != wxGridNoCellCoords &&
+                 m_selectingBottomRight != wxGridNoCellCoords )
+            {
                 if ( m_selection )
                 {
                     m_selection->SelectBlock( m_selectingTopLeft.GetRow(),
@@ -5169,11 +5474,11 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
 
                 m_selectingTopLeft = wxGridNoCellCoords;
                 m_selectingBottomRight = wxGridNoCellCoords;
-            }
 
-            // Show the edit control, if it has been hidden for
-            // drag-shrinking.
-            ShowCellEditControl();
+                // Show the edit control, if it has been hidden for
+                // drag-shrinking.
+                ShowCellEditControl();
+            }
         }
         else if ( m_cursorMode == WXGRID_CURSOR_RESIZE_ROW )
         {
@@ -5233,6 +5538,13 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event )
     //
     else if ( event.Moving() && !event.IsButton() )
     {
+        if( coords.GetRow() < 0 || coords.GetCol() < 0 )
+        {
+            // out of grid cell area
+            ChangeCursorMode(WXGRID_CURSOR_SELECT_CELL);
+            return;
+        }
+
         int dragRow = YToEdgeOfRow( y );
         int dragCol = XToEdgeOfCol( x );
 
@@ -5305,7 +5617,7 @@ void wxGrid::DoEndDragResizeRow()
 
         int rowTop = GetRowTop(m_dragRowOrCol);
         SetRowSize( m_dragRowOrCol,
-                    wxMax( m_dragLastPos - rowTop, WXGRID_MIN_ROW_HEIGHT ) );
+                    wxMax( m_dragLastPos - rowTop, m_minAcceptableRowHeight ) );
 
         if ( !GetBatchCount() )
         {
@@ -5317,6 +5629,25 @@ void wxGrid::DoEndDragResizeRow()
             rect.height = ch - rect.y;
             m_rowLabelWin->Refresh( TRUE, &rect );
             rect.width = cw;
+            // if there is a multicell block, paint all of it
+            if (m_table)
+            {
+                int i, cell_rows, cell_cols, subtract_rows = 0;
+                int leftCol = XToCol(left);
+                int rightCol = internalXToCol(left+cw);
+                if (leftCol >= 0)
+                {
+                    for (i=leftCol; i<rightCol; i++)
+                    {
+                        GetCellSize(m_dragRowOrCol, i, &cell_rows, &cell_cols);
+                        if (cell_rows < subtract_rows)
+                            subtract_rows = cell_rows;
+                    }
+                    rect.y = GetRowTop(m_dragRowOrCol + subtract_rows);
+                    CalcScrolledPosition(0, rect.y, &dummy, &rect.y);
+                    rect.height = ch - rect.y;
+                }
+            }
             m_gridWin->Refresh( FALSE, &rect );
         }
 
@@ -5357,6 +5688,25 @@ void wxGrid::DoEndDragResizeCol()
             rect.height = m_colLabelHeight;
             m_colLabelWin->Refresh( TRUE, &rect );
             rect.height = ch;
+            // if there is a multicell block, paint all of it
+            if (m_table)
+            {
+                int i, cell_rows, cell_cols, subtract_cols = 0;
+                int topRow = YToRow(top);
+                int bottomRow = internalYToRow(top+cw);
+                if (topRow >= 0)
+                {
+                    for (i=topRow; i<bottomRow; i++)
+                    {
+                        GetCellSize(i, m_dragRowOrCol, &cell_rows, &cell_cols);
+                        if (cell_cols < subtract_cols)
+                            subtract_cols = cell_cols;
+                    }
+                    rect.x = GetColLeft(m_dragRowOrCol + subtract_cols);
+                    CalcScrolledPosition(rect.x, 0, &rect.x, &dummy);
+                    rect.width = cw - rect.x;
+                }
+            }
             m_gridWin->Refresh( FALSE, &rect );
         }
 
@@ -5427,7 +5777,8 @@ bool wxGrid::InsertRows( int pos, int numRows, bool WXUNUSED(updateLabels) )
         if (IsCellEditControlEnabled())
             DisableCellEditControl();
 
-        return m_table->InsertRows( pos, numRows );
+        bool done = m_table->InsertRows( pos, numRows );
+        return done;
 
         // the table will have sent the results of the insert row
         // operation to this view object as a grid table message
@@ -5446,9 +5797,14 @@ bool wxGrid::AppendRows( int numRows, bool WXUNUSED(updateLabels) )
         return FALSE;
     }
 
-    return ( m_table && m_table->AppendRows( numRows ) );
-    // the table will have sent the results of the append row
-    // operation to this view object as a grid table message
+    if ( m_table )
+    {
+        bool done = m_table && m_table->AppendRows( numRows );
+        return done;
+        // the table will have sent the results of the append row
+        // operation to this view object as a grid table message
+    }
+    return FALSE;
 }
 
 
@@ -5467,7 +5823,8 @@ bool wxGrid::DeleteRows( int pos, int numRows, bool WXUNUSED(updateLabels) )
         if (IsCellEditControlEnabled())
             DisableCellEditControl();
 
-        return (m_table->DeleteRows( pos, numRows ));
+        bool done = m_table->DeleteRows( pos, numRows );
+        return done;
         // the table will have sent the results of the delete row
         // operation to this view object as a grid table message
     }
@@ -5490,7 +5847,8 @@ bool wxGrid::InsertCols( int pos, int numCols, bool WXUNUSED(updateLabels) )
         if (IsCellEditControlEnabled())
             DisableCellEditControl();
 
-        return m_table->InsertCols( pos, numCols );
+        bool done = m_table->InsertCols( pos, numCols );
+        return done;
         // the table will have sent the results of the insert col
         // operation to this view object as a grid table message
     }
@@ -5508,13 +5866,18 @@ bool wxGrid::AppendCols( int numCols, bool WXUNUSED(updateLabels) )
         return FALSE;
     }
 
-    return ( m_table && m_table->AppendCols( numCols ) );
-    // the table will have sent the results of the append col
-    // operation to this view object as a grid table message
-}
-
-
-bool wxGrid::DeleteCols( int pos, int numCols, bool WXUNUSED(updateLabels) )
+    if ( m_table )
+    {
+        bool done = m_table->AppendCols( numCols );
+        return done;
+        // the table will have sent the results of the append col
+        // operation to this view object as a grid table message
+    }
+    return FALSE;
+}
+
+
+bool wxGrid::DeleteCols( int pos, int numCols, bool WXUNUSED(updateLabels) )
 {
     // TODO: something with updateLabels flag
 
@@ -5529,7 +5892,8 @@ bool wxGrid::DeleteCols( int pos, int numCols, bool WXUNUSED(updateLabels) )
         if (IsCellEditControlEnabled())
             DisableCellEditControl();
 
-        return ( m_table->DeleteCols( pos, numCols ) );
+        bool done = m_table->DeleteCols( pos, numCols );
+        return done;
         // the table will have sent the results of the delete col
         // operation to this view object as a grid table message
     }
@@ -5653,6 +6017,92 @@ void wxGrid::OnPaint( wxPaintEvent& WXUNUSED(event) )
     wxPaintDC dc(this);  // needed to prevent zillions of paint events on MSW
 }
 
+void wxGrid::Refresh(bool eraseb, const wxRect* rect)
+{
+    // Don't do anything if between Begin/EndBatch...
+    // EndBatch() will do all this on the last nested one anyway.
+    if (! GetBatchCount())
+    {
+        // Refresh to get correct scrolled position:
+        wxScrolledWindow::Refresh(eraseb,rect);
+
+        if (rect)
+        {
+            int rect_x, rect_y, rectWidth, rectHeight;
+            int width_label, width_cell, height_label, height_cell;
+            int x, y;
+
+            //Copy rectangle can get scroll offsets..
+            rect_x = rect->GetX();
+            rect_y = rect->GetY();
+            rectWidth = rect->GetWidth();
+            rectHeight = rect->GetHeight();
+
+            width_label = m_rowLabelWidth - rect_x;
+            if (width_label > rectWidth) width_label = rectWidth;
+
+            height_label = m_colLabelHeight - rect_y;
+            if (height_label > rectHeight) height_label = rectHeight;
+
+            if (rect_x > m_rowLabelWidth)
+            {
+                x = rect_x - m_rowLabelWidth;
+                width_cell = rectWidth;
+            }
+            else
+            {
+                x = 0;
+                width_cell = rectWidth - (m_rowLabelWidth - rect_x);
+            }
+
+            if (rect_y > m_colLabelHeight)
+            {
+                y = rect_y - m_colLabelHeight;
+                height_cell = rectHeight;
+            }
+            else
+            {
+                y = 0;
+                height_cell = rectHeight - (m_colLabelHeight - rect_y);
+            }
+
+            // Paint corner label part intersecting rect.
+            if ( width_label > 0 && height_label > 0 )
+            {
+                wxRect anotherrect(rect_x, rect_y, width_label, height_label);
+                m_cornerLabelWin->Refresh(eraseb, &anotherrect);
+            }
+
+            // Paint col labels part intersecting rect.
+            if ( width_cell > 0 && height_label > 0 )
+            {
+                wxRect anotherrect(x, rect_y, width_cell, height_label);
+                m_colLabelWin->Refresh(eraseb, &anotherrect);
+            }
+
+            // Paint row labels part intersecting rect.
+            if ( width_label > 0 && height_cell > 0 )
+            {
+                wxRect anotherrect(rect_x, y, width_label, height_cell);
+                m_rowLabelWin->Refresh(eraseb, &anotherrect);
+            }
+
+            // Paint cell area part intersecting rect.
+            if ( width_cell > 0 && height_cell > 0 )
+            {
+                wxRect anotherrect(x, y, width_cell, height_cell);
+                m_gridWin->Refresh(eraseb, &anotherrect);
+            }
+        }
+        else
+        {
+            m_cornerLabelWin->Refresh(eraseb, NULL);
+            m_colLabelWin->Refresh(eraseb, NULL);
+            m_rowLabelWin->Refresh(eraseb, NULL);
+            m_gridWin->Refresh(eraseb, NULL);
+        }
+    }
+}
 
 void wxGrid::OnSize( wxSizeEvent& event )
 {
@@ -5687,7 +6137,7 @@ void wxGrid::OnKeyDown( wxKeyEvent& event )
 
         // try local handlers
         //
-        switch ( event.KeyCode() )
+        switch ( event.GetKeyCode() )
         {
             case WXK_UP:
                 if ( event.ControlDown() )
@@ -5852,18 +6302,18 @@ void wxGrid::OnKeyDown( wxKeyEvent& event )
 
                     // <F2> is special and will always start editing, for
                     // other keys - ask the editor itself
-                    if ( (event.KeyCode() == WXK_F2 && !event.HasModifiers())
+                    if ( (event.GetKeyCode() == WXK_F2 && !event.HasModifiers())
                          || editor->IsAcceptedKey(event) )
                     {
+                        // ensure cell is visble
+                        MakeCellVisible(row, col);
                         EnableCellEditControl();
 
-                        // 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);
-                        }
+                        // a problem can arise if the cell is not completely
+                        // visible (even after calling MakeCellVisible the
+                        // control is not created and calling StartingKey will
+                        // crash the app
+                        if( editor->IsCreated() && m_cellEditCtrlEnabled ) editor->StartingKey(event);
                     }
                     else
                     {
@@ -5890,7 +6340,7 @@ void wxGrid::OnKeyUp( wxKeyEvent& event )
 {
     // try local handlers
     //
-    if ( event.KeyCode() == WXK_SHIFT )
+    if ( event.GetKeyCode() == WXK_SHIFT )
     {
         if ( m_selectingTopLeft != wxGridNoCellCoords &&
              m_selectingBottomRight != wxGridNoCellCoords )
@@ -5937,7 +6387,7 @@ void wxGrid::SetCurrentCell( const wxGridCellCoords& coords )
         if ( IsVisible( m_currentCellCoords, FALSE ) )
         {
             wxRect r;
-            r = BlockToDeviceRect(m_currentCellCoords, coords);
+            r = BlockToDeviceRect(m_currentCellCoords, m_currentCellCoords);
             if ( !m_gridLinesEnabled )
             {
                 r.x--;
@@ -5946,7 +6396,7 @@ void wxGrid::SetCurrentCell( const wxGridCellCoords& coords )
                 r.height++;
             }
 
-             wxGridCellCoordsArray cells = CalcCellsExposed( r );
+            wxGridCellCoordsArray cells = CalcCellsExposed( r );
 
             // Otherwise refresh redraws the highlight!
             m_currentCellCoords = coords;
@@ -6000,8 +6450,18 @@ void wxGrid::HighlightBlock( int topRow, int leftCol, int bottomRow, int rightCo
     updateTopLeft = wxGridCellCoords( topRow, leftCol );
     updateBottomRight = wxGridCellCoords( bottomRow, rightCol );
 
-    if ( m_selectingTopLeft != updateTopLeft ||
-         m_selectingBottomRight != updateBottomRight )
+    // First the case that we selected a completely new area
+    if ( m_selectingTopLeft == wxGridNoCellCoords ||
+         m_selectingBottomRight == wxGridNoCellCoords )
+    {
+        wxRect rect;
+        rect = BlockToDeviceRect( wxGridCellCoords ( topRow, leftCol ),
+                                  wxGridCellCoords ( bottomRow, rightCol ) );
+        m_gridWin->Refresh( FALSE, &rect );
+    }
+    // Now handle changing an existing selection area.
+    else if ( m_selectingTopLeft != updateTopLeft ||
+              m_selectingBottomRight != updateBottomRight )
     {
         // Compute two optimal update rectangles:
         // Either one rectangle is a real subset of the
@@ -6052,6 +6512,8 @@ void wxGrid::HighlightBlock( int topRow, int leftCol, int bottomRow, int rightCo
 
         if ( oldLeft < leftCol )
         {
+            // Refresh the newly selected or deselected
+            // area to the left of the old or new selection.
             need_refresh[0] = TRUE;
             rect[0] = BlockToDeviceRect( wxGridCellCoords ( oldTop,
                                                             oldLeft ),
@@ -6061,6 +6523,8 @@ void wxGrid::HighlightBlock( int topRow, int leftCol, int bottomRow, int rightCo
 
         if ( oldTop  < topRow )
         {
+            // Refresh the newly selected or deselected
+            // area above the old or new selection.
             need_refresh[1] = TRUE;
             rect[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop,
                                                             leftCol ),
@@ -6070,6 +6534,8 @@ void wxGrid::HighlightBlock( int topRow, int leftCol, int bottomRow, int rightCo
 
         if ( oldRight > rightCol )
         {
+            // Refresh the newly selected or deselected
+            // area to the right of the old or new selection.
             need_refresh[2] = TRUE;
             rect[2] = BlockToDeviceRect( wxGridCellCoords ( oldTop,
                                                             rightCol + 1 ),
@@ -6079,6 +6545,8 @@ void wxGrid::HighlightBlock( int topRow, int leftCol, int bottomRow, int rightCo
 
         if ( oldBottom > bottomRow )
         {
+            // Refresh the newly selected or deselected
+            // area below the old or new selection.
             need_refresh[3] = TRUE;
             rect[3] = BlockToDeviceRect( wxGridCellCoords ( bottomRow + 1,
                                                             leftCol ),
@@ -6086,20 +6554,14 @@ void wxGrid::HighlightBlock( int topRow, int leftCol, int bottomRow, int rightCo
                                                             rightCol ) );
         }
 
-
-        // Change Selection
-        m_selectingTopLeft = updateTopLeft;
-        m_selectingBottomRight = updateBottomRight;
-
         // various Refresh() calls
         for (i = 0; i < 4; i++ )
             if ( need_refresh[i] && rect[i] != wxGridNoCellRect )
                 m_gridWin->Refresh( FALSE, &(rect[i]) );
     }
-
-    // never generate an event as it will be generated from
-    // wxGridSelection::SelectBlock!
-    // (old comment from when this was the body of SelectBlock)
+    // Change Selection
+    m_selectingTopLeft = updateTopLeft;
+    m_selectingBottomRight = updateBottomRight;
 }
 
 //
@@ -6108,6 +6570,9 @@ void wxGrid::HighlightBlock( int topRow, int leftCol, int bottomRow, int rightCo
 
 bool wxGrid::GetModelValues()
 {
+    // Hide the editor, so it won't hide a changed value.
+    HideCellEditControl();
+
     if ( m_table )
     {
         // all we need to do is repaint the grid
@@ -6124,6 +6589,11 @@ bool wxGrid::SetModelValues()
 {
     int row, col;
 
+    // Disable the editor, so it won't hide a changed value.
+    // Do we also want to save the current value of the editor first?
+    // I think so ...
+    DisableCellEditControl();
+
     if ( m_table )
     {
         for ( row = 0;  row < m_numRows;  row++ )
@@ -6150,13 +6620,104 @@ void wxGrid::DrawGridCellArea( wxDC& dc, const wxGridCellCoordsArray& cells )
 {
     if ( !m_numRows || !m_numCols ) return;
 
-    size_t i;
-    size_t numCells = cells.GetCount();
+    int i, numCells = cells.GetCount();
+    int row, col, cell_rows, cell_cols;
+    wxGridCellCoordsArray redrawCells;
 
-    for ( i = 0;  i < numCells;  i++ )
+    for ( i = numCells-1; i >= 0;  i-- )
     {
+        row = cells[i].GetRow();
+        col = cells[i].GetCol();
+        GetCellSize( row, col, &cell_rows, &cell_cols );
+
+        // If this cell is part of a multicell block, find owner for repaint
+        if ( cell_rows <= 0 || cell_cols <= 0 )
+        {
+            wxGridCellCoords cell(row+cell_rows, col+cell_cols);
+            bool marked = FALSE;
+            for ( int j = 0;  j < numCells;  j++ )
+            {
+                if ( cell == cells[j] )
+                {
+                    marked = TRUE;
+                    break;
+                }
+            }
+            if (!marked)
+            {
+                int count = redrawCells.GetCount();
+                for (int j = 0; j < count; j++)
+                {
+                    if ( cell == redrawCells[j] )
+                    {
+                        marked = TRUE;
+                        break;
+                    }
+                }
+                if (!marked) redrawCells.Add( cell );
+            }
+            continue; // don't bother drawing this cell
+        }
+
+        // If this cell is empty, find cell to left that might want to overflow
+        if (m_table && m_table->IsEmptyCell(row, col))
+        {
+            for ( int l = 0; l < cell_rows; l++ )
+            {
+                // find a cell in this row to left alreay marked for repaint
+                int left = col;
+                for (int k = 0; k < int(redrawCells.GetCount()); k++)
+                    if ((redrawCells[k].GetCol() < left) &&
+                        (redrawCells[k].GetRow() == row))
+                        left=redrawCells[k].GetCol();
+
+                if (left == col) left = 0; // oh well
+
+                for (int j = col-1; j >= left; j--)
+                {
+                    if (!m_table->IsEmptyCell(row+l, j))
+                    {
+                        if (GetCellOverflow(row+l, j))
+                        {
+                            wxGridCellCoords cell(row+l, j);
+                            bool marked = FALSE;
+
+                            for (int k = 0; k < numCells; k++)
+                            {
+                                if ( cell == cells[k] )
+                                {
+                                    marked = TRUE;
+                                    break;
+                                }
+                            }
+                            if (!marked)
+                            {
+                                int count = redrawCells.GetCount();
+                                for (int k = 0; k < count; k++)
+                                {
+                                    if ( cell == redrawCells[k] )
+                                    {
+                                        marked = TRUE;
+                                        break;
+                                    }
+                                }
+                                if (!marked) redrawCells.Add( cell );
+                            }
+                        }
+                        break;
+                    }
+                }
+            }
+        }
         DrawCell( dc, cells[i] );
     }
+
+    numCells = redrawCells.GetCount();
+
+    for ( i = numCells - 1; i >= 0;  i-- )
+    {
+        DrawCell( dc, redrawCells[i] );
+    }
 }
 
 
@@ -6248,8 +6809,8 @@ void wxGrid::DrawCellHighlight( wxDC& dc, const wxGridCellAttr *attr )
 
     int penWidth = attr->IsReadOnly() ? m_cellHighlightROPenWidth : m_cellHighlightPenWidth;
 
-    if (penWidth > 0) {
-
+    if (penWidth > 0)
+    {
         // The center of th drawn line is where the position/width/height of
         // the rectangle is actually at, (on wxMSW atr least,) so we will
         // reduce the size of the rectangle to compensate for the thickness of
@@ -6262,7 +6823,9 @@ void wxGrid::DrawCellHighlight( wxDC& dc, const wxGridCellAttr *attr )
 
 
         // Now draw the rectangle
-        dc.SetPen(wxPen(m_cellHighlightColour, penWidth, wxSOLID));
+        // use the cellHighlightColour if the cell is inside a selection, this
+        // will ensure the cell is always visible.
+        dc.SetPen(wxPen(IsInSelection(row,col)?m_selectionForeground:m_cellHighlightColour, penWidth, wxSOLID));
         dc.SetBrush(*wxTRANSPARENT_BRUSH);
         dc.DrawRectangle(rect);
     }
@@ -6299,15 +6862,17 @@ void wxGrid::DrawCellBorder( wxDC& dc, const wxGridCellCoords& coords )
 
     dc.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID) );
 
+    wxRect rect = CellToRect( row, col );
+
     // right hand border
     //
-    dc.DrawLine( GetColRight(col), GetRowTop(row),
-                 GetColRight(col), GetRowBottom(row) );
+    dc.DrawLine( rect.x + rect.width, rect.y,
+                 rect.x + rect.width, rect.y + rect.height + 1 );
 
     // bottom border
     //
-    dc.DrawLine( GetColLeft(col), GetRowBottom(row),
-                 GetColRight(col), GetRowBottom(row) );
+    dc.DrawLine( rect.x,              rect.y + rect.height,
+                 rect.x + rect.width, rect.y + rect.height);
 }
 
 void wxGrid::DrawHighlight(wxDC& dc,const  wxGridCellCoordsArray& cells)
@@ -6349,6 +6914,10 @@ void wxGrid::DrawHighlight(wxDC& dc,const  wxGridCellCoordsArray& cells)
 //
 void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) )
 {
+#if !WXGRID_DRAW_LINES
+    return;
+#endif
+
     if ( !m_gridLinesEnabled ||
          !m_numRows ||
          !m_numCols ) return;
@@ -6385,11 +6954,43 @@ void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) )
     right = wxMin( right, GetColRight(m_numCols - 1) );
     bottom = wxMin( bottom, GetRowBottom(m_numRows - 1) );
 
+    // no gridlines inside multicells, clip them out
+    int leftCol   = internalXToCol(left);
+    int topRow    = internalYToRow(top);
+    int rightCol  = internalXToCol(right);
+    int bottomRow = internalYToRow(bottom);
+    wxRegion clippedcells(0, 0, cw, ch);
+
+
+    int i, j, cell_rows, cell_cols;
+    wxRect rect;
+
+    for (j=topRow; j<bottomRow; j++)
+    {
+        for (i=leftCol; i<rightCol; i++)
+        {
+            GetCellSize( j, i, &cell_rows, &cell_cols );
+            if ((cell_rows > 1) || (cell_cols > 1))
+            {
+                rect = CellToRect(j,i);
+                CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
+                clippedcells.Subtract(rect);
+            }
+            else if ((cell_rows < 0) || (cell_cols < 0))
+            {
+                rect = CellToRect(j+cell_rows, i+cell_cols);
+                CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
+                clippedcells.Subtract(rect);
+            }
+        }
+    }
+    dc.SetClippingRegion( clippedcells );
+
     dc.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID) );
 
     // horizontal grid lines
     //
-    int i;
+    // already declared above - int i;
     for ( i = internalYToRow(top); i < m_numRows; i++ )
     {
         int bot = GetRowBottom(i) - 1;
@@ -6421,6 +7022,7 @@ void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) )
             dc.DrawLine( colRight, top, colRight, bottom );
         }
     }
+    dc.DestroyClippingRegion();
 }
 
 
@@ -6446,15 +7048,17 @@ void wxGrid::DrawRowLabel( wxDC& dc, int row )
     int rowTop = GetRowTop(row),
         rowBottom = GetRowBottom(row) - 1;
 
-    dc.SetPen( *wxBLACK_PEN );
+    dc.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW),1, wxSOLID) );
     dc.DrawLine( m_rowLabelWidth-1, rowTop,
                  m_rowLabelWidth-1, rowBottom );
 
-    dc.DrawLine( 0, rowBottom, m_rowLabelWidth-1, rowBottom );
+    dc.DrawLine( 0, rowTop, 0, rowBottom );
+
+    dc.DrawLine( 0, rowBottom, m_rowLabelWidth, rowBottom );
 
     dc.SetPen( *wxWHITE_PEN );
-    dc.DrawLine( 0, rowTop, 0, rowBottom );
-    dc.DrawLine( 0, rowTop, m_rowLabelWidth-1, rowTop );
+    dc.DrawLine( 1, rowTop, 1, rowBottom );
+    dc.DrawLine( 1, rowTop, m_rowLabelWidth-1, rowTop );
 
     dc.SetBackgroundMode( wxTRANSPARENT );
     dc.SetTextForeground( GetLabelTextColour() );
@@ -6494,111 +7098,148 @@ void wxGrid::DrawColLabel( wxDC& dc, int col )
     int colLeft = GetColLeft(col),
         colRight = GetColRight(col) - 1;
 
-    dc.SetPen( *wxBLACK_PEN );
+    dc.SetPen( wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DDKSHADOW),1, wxSOLID) );
     dc.DrawLine( colRight, 0,
                  colRight, m_colLabelHeight-1 );
 
+    dc.DrawLine( colLeft, 0, colRight, 0 );
+
     dc.DrawLine( colLeft, m_colLabelHeight-1,
-                 colRight, m_colLabelHeight-1 );
+                 colRight+1, m_colLabelHeight-1 );
 
     dc.SetPen( *wxWHITE_PEN );
-    dc.DrawLine( colLeft, 0, colLeft, m_colLabelHeight-1 );
-    dc.DrawLine( colLeft, 0, colRight, 0 );
-
-    dc.SetBackgroundMode( wxTRANSPARENT );
-    dc.SetTextForeground( GetLabelTextColour() );
-    dc.SetFont( GetLabelFont() );
+    dc.DrawLine( colLeft, 1, colLeft, m_colLabelHeight-1 );
+    dc.DrawLine( colLeft, 1, colRight, 1 );
 
     dc.SetBackgroundMode( wxTRANSPARENT );
     dc.SetTextForeground( GetLabelTextColour() );
     dc.SetFont( GetLabelFont() );
 
-    int hAlign, vAlign;
+    int hAlign, vAlign, orient;
     GetColLabelAlignment( &hAlign, &vAlign );
+    orient = GetColLabelTextOrientation();
 
     wxRect rect;
     rect.SetX( colLeft + 2 );
     rect.SetY( 2 );
     rect.SetWidth( GetColWidth(col) - 4 );
     rect.SetHeight( m_colLabelHeight - 4 );
-    DrawTextRectangle( dc, GetColLabelValue( col ), rect, hAlign, vAlign );
+    DrawTextRectangle( dc, GetColLabelValue( col ), rect, hAlign, vAlign, orient );
 }
 
 void wxGrid::DrawTextRectangle( wxDC& dc,
                                 const wxString& value,
                                 const wxRect& rect,
                                 int horizAlign,
-                                int vertAlign )
+                                int vertAlign,
+                                int textOrientation )
 {
     wxArrayString lines;
 
-    dc.SetClippingRegion( rect );
     StringToLines( value, lines );
 
 
     //Forward to new API.
     DrawTextRectangle(  dc,
-                        lines,
-                        rect,
-                        horizAlign,
-                        vertAlign );
+        lines,
+        rect,
+        horizAlign,
+        vertAlign,
+        textOrientation );
 
 }
 
 void wxGrid::DrawTextRectangle( wxDC& dc,
-                                const wxArrayString& lines,
-                                const wxRect& rect,
-                                int horizAlign,
-                                int vertAlign )
+                               const wxArrayString& lines,
+                               const wxRect& rect,
+                               int horizAlign,
+                               int vertAlign,
+                               int textOrientation )
 {
     long textWidth, textHeight;
     long lineWidth, lineHeight;
+    int nLines;
 
-    if ( lines.GetCount() )
+    dc.SetClippingRegion( rect );
+
+    nLines = lines.GetCount();
+    if( nLines > 0 )
     {
-        GetTextBoxSize( dc, lines, &textWidth, &textHeight );
-        dc.GetTextExtent( lines[0], &lineWidth, &lineHeight );
+        int l;
+        float x = 0.0, y = 0.0;
+
+        if( textOrientation == wxHORIZONTAL )
+            GetTextBoxSize(dc, lines, &textWidth, &textHeight);
+        else
+            GetTextBoxSize( dc, lines, &textHeight, &textWidth );
 
-        float x, y;
-        switch ( horizAlign )
+        switch( vertAlign )
         {
-            case wxALIGN_RIGHT:
-                x = rect.x + (rect.width - textWidth - 1);
-                break;
+        case wxALIGN_BOTTOM:
+            if( textOrientation == wxHORIZONTAL )
+                y = rect.y + (rect.height - textHeight - 1);
+            else
+                x = rect.x + rect.width - textWidth;
+            break;
 
-            case wxALIGN_CENTRE:
+        case wxALIGN_CENTRE:
+            if( textOrientation == wxHORIZONTAL )
+                y = rect.y + ((rect.height - textHeight)/2);
+            else
                 x = rect.x + ((rect.width - textWidth)/2);
-                break;
+            break;
 
-            case wxALIGN_LEFT:
-            default:
+        case wxALIGN_TOP:
+        default:
+            if( textOrientation == wxHORIZONTAL )
+                y = rect.y + 1;
+            else
                 x = rect.x + 1;
-                break;
+            break;
         }
 
-        switch ( vertAlign )
+        // Align each line of a multi-line label
+        for( l = 0; l < nLines; l++ )
         {
-            case wxALIGN_BOTTOM:
-                y = rect.y + (rect.height - textHeight - 1);
+            dc.GetTextExtent(lines[l], &lineWidth, &lineHeight);
+
+            switch( horizAlign )
+            {
+            case wxALIGN_RIGHT:
+                if( textOrientation == wxHORIZONTAL )
+                    x = rect.x + (rect.width - lineWidth - 1);
+                else
+                    y = rect.y + lineWidth + 1;
                 break;
 
             case wxALIGN_CENTRE:
-                y = rect.y + ((rect.height - textHeight)/2);
+                if( textOrientation == wxHORIZONTAL )
+                    x = rect.x + ((rect.width - lineWidth)/2);
+                else
+                    y = rect.y + rect.height - ((rect.height - lineWidth)/2);
                 break;
 
-            case wxALIGN_TOP:
+            case wxALIGN_LEFT:
             default:
-                y = rect.y + 1;
+                if( textOrientation == wxHORIZONTAL )
+                    x = rect.x + 1;
+                else
+                    y = rect.y + rect.height - 1;
                 break;
-        }
+            }
 
-        for ( size_t i = 0;  i < lines.GetCount();  i++ )
-        {
-            dc.DrawText( lines[i], (int)x, (int)y );
-            y += lineHeight;
+            if( textOrientation == wxHORIZONTAL )
+            {
+                dc.DrawText( lines[l], (int)x, (int)y );
+                y += lineHeight;
+            }
+            else
+            {
+                dc.DrawRotatedText( lines[l], (int)x, (int)y, 90.0 );
+                x += lineHeight;
+            }
         }
     }
-
     dc.DestroyClippingRegion();
 }
 
@@ -6805,6 +7446,17 @@ void wxGrid::ShowCellEditControl()
             int row = m_currentCellCoords.GetRow();
             int col = m_currentCellCoords.GetCol();
 
+            // if this is part of a multicell, find owner (topleft)
+            int cell_rows, cell_cols;
+            GetCellSize( row, col, &cell_rows, &cell_cols );
+            if ( cell_rows <= 0 || cell_cols <= 0 )
+            {
+                row += cell_rows;
+                col += cell_cols;
+                m_currentCellCoords.SetRow( row );
+                m_currentCellCoords.SetCol( col );
+            }
+
             // convert to scrolled coords
             //
             CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
@@ -6822,7 +7474,7 @@ void wxGrid::ShowCellEditControl()
 
             // cell is shifted by one pixel
             // However, don't allow x or y to become negative
-            // since the SetSize() method interprets that as 
+            // since the SetSize() method interprets that as
             // "don't change."
             if (rect.x > 0)
                 rect.x--;
@@ -6845,15 +7497,54 @@ void wxGrid::ShowCellEditControl()
                 GetEventHandler()->ProcessEvent(evt);
             }
 
-            editor->Show( TRUE, attr );
 
+            // resize editor to overflow into righthand cells if allowed
+            int maxWidth = rect.width;
+            wxString value = GetCellValue(row, col);
+            if ( (value != wxEmptyString) && (attr->GetOverflow()) )
+            {
+                int y;
+                GetTextExtent(value, &maxWidth, &y,
+                        NULL, NULL, &attr->GetFont());
+                if (maxWidth < rect.width) maxWidth = rect.width;
+            }
+            int client_right = m_gridWin->GetClientSize().GetWidth();
+            if (rect.x+maxWidth > client_right)
+                maxWidth = client_right - rect.x;
+
+            if ((maxWidth > rect.width) && (col < m_numCols) && m_table)
+            {
+                GetCellSize( row, col, &cell_rows, &cell_cols );
+                // may have changed earlier
+                for (int i = col+cell_cols; i < m_numCols; i++)
+                {
+                    int c_rows, c_cols;
+                    GetCellSize( row, i, &c_rows, &c_cols );
+                    // looks weird going over a multicell
+                    if (m_table->IsEmptyCell(row,i) &&
+                            (rect.width < maxWidth) && (c_rows == 1))
+                        rect.width += GetColWidth(i);
+                    else
+                        break;
+                }
+                if (rect.GetRight() > client_right)
+                    rect.SetRight(client_right-1);
+            }
+
+            editor->SetCellAttr(attr);
             editor->SetSize( rect );
+            editor->Show( TRUE, attr );
+
+            // recalc dimensions in case we need to
+            // expand the scrolled window to account for editor
+            CalcDimensions();
 
             editor->BeginEdit(row, col, this);
+            editor->SetCellAttr(NULL);
 
             editor->DecRef();
             attr->DecRef();
-         }
+        }
     }
 }
 
@@ -6871,7 +7562,10 @@ void wxGrid::HideCellEditControl()
         editor->DecRef();
         attr->DecRef();
         m_gridWin->SetFocus();
-        wxRect rect( CellToRect( row, col ) );
+        // refresh whole row to the right
+        wxRect rect( CellToRect(row, col) );
+        CalcScrolledPosition(rect.x, rect.y, &rect.x, &rect.y );
+        rect.width = m_gridWin->GetClientSize().GetWidth() - rect.x;
         m_gridWin->Refresh( FALSE, &rect );
     }
 }
@@ -6932,24 +7626,34 @@ void wxGrid::XYToCell( int x, int y, wxGridCellCoords& coords )
 
 // Internal Helper function for computing row or column from some
 // (unscrolled) coordinate value, using either
-// m_defaultRowHeight/m_defaultColWidth or binary search on array 
+// 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)
+                           const wxArrayInt& BorderArray, int nMax,
+                           bool clipToMinMax)
 {
+
+    if (coord < 0)
+        return clipToMinMax && (nMax > 0) ? 0 : -1;
+
+
     if (!defaultDist)
         defaultDist = 1;
+
     size_t i_max = coord / defaultDist,
            i_min = 0;
+
     if (BorderArray.IsEmpty())
     {
-        return i_max;
+        if((int) i_max < nMax)
+            return i_max;
+        return clipToMinMax ? nMax - 1 : -1;
     }
 
     if ( i_max >= BorderArray.GetCount())
         i_max = BorderArray.GetCount() - 1;
-    else 
+    else
     {
         if ( coord >= BorderArray[i_max])
         {
@@ -6960,7 +7664,7 @@ static int CoordToRowOrCol(int coord, int defaultDist, int minDist,
             i_max = BorderArray.GetCount() - 1;
     }
     if ( coord >= BorderArray[i_max])
-        return maxOnOverflow ? (int)i_max : -1;
+        return clipToMinMax ? (int)i_max : -1;
     if ( coord < BorderArray[0] )
         return 0;
 
@@ -6984,14 +7688,14 @@ static int CoordToRowOrCol(int coord, int defaultDist, int minDist,
 int wxGrid::YToRow( int y )
 {
     return CoordToRowOrCol(y, m_defaultRowHeight,
-                           WXGRID_MIN_ROW_HEIGHT, m_rowBottoms, FALSE);
+                           m_minAcceptableRowHeight, m_rowBottoms, m_numRows, FALSE);
 }
 
 
 int wxGrid::XToCol( int x )
 {
     return CoordToRowOrCol(x, m_defaultColWidth,
-                           WXGRID_MIN_COL_WIDTH, m_colRights, FALSE);
+                           m_minAcceptableColWidth, m_colRights, m_numCols, FALSE);
 }
 
 
@@ -7046,10 +7750,20 @@ wxRect wxGrid::CellToRect( int row, int col )
     if ( row >= 0  &&  row < m_numRows  &&
          col >= 0  &&  col < m_numCols )
     {
+        int i, cell_rows, cell_cols;
+        rect.width = rect.height = 0;
+        GetCellSize( row, col, &cell_rows, &cell_cols );
+        // if negative then find multicell owner
+        if (cell_rows < 0) row += cell_rows;
+        if (cell_cols < 0) col += cell_cols;
+        GetCellSize( row, col, &cell_rows, &cell_cols );
+
         rect.x = GetColLeft(col);
         rect.y = GetRowTop(row);
-        rect.width = GetColWidth(col);
-        rect.height = GetRowHeight(row);
+        for (i=col; i<col+cell_cols; i++)
+            rect.width  += GetColWidth(i);
+        for (i=row; i<row+cell_rows; i++)
+            rect.height += GetRowHeight(i);
     }
 
     // if grid lines are enabled, then the area of the cell is a bit smaller
@@ -7153,17 +7867,10 @@ void wxGrid::MakeCellVisible( int row, int col )
         }
         else if ( right > cw )
         {
-            int w = r.GetWidth();
-            xpos = r.GetLeft();
-            for ( i = col-1;  i >= 0;  i-- )
-            {
-                int colWidth = GetColWidth(i);
-                if ( w + colWidth > cw )
-                    break;
-
-                w += colWidth;
-                xpos -= colWidth;
-            }
+            // position the view so that the cell is on the right
+            int x0, y0;
+            CalcUnscrolledPosition(0, 0, &x0, &y0);
+            xpos = x0 + (right - cw);
 
             // see comment for ypos above
             xpos += GRID_SCROLL_LINE_X;
@@ -7333,13 +8040,11 @@ bool wxGrid::MovePageUp()
         m_gridWin->GetClientSize( &cw, &ch );
 
         int y = GetRowTop(row);
-        int newRow = YToRow( y - ch + 1 );
-        if ( newRow == -1 )
-        {
-            newRow = 0;
-        }
-        else if ( newRow == row )
+        int newRow = internalYToRow( y - ch + 1 );
+
+        if ( newRow == row )
         {
+           //row > 0 , so newrow can never be less than 0 here.
             newRow = row - 1;
         }
 
@@ -7357,20 +8062,17 @@ bool wxGrid::MovePageDown()
     if ( m_currentCellCoords == wxGridNoCellCoords ) return FALSE;
 
     int row = m_currentCellCoords.GetRow();
-    if ( row < m_numRows )
+    if ( (row+1) < m_numRows )
     {
         int cw, ch;
         m_gridWin->GetClientSize( &cw, &ch );
 
         int y = GetRowTop(row);
-        int newRow = YToRow( y + ch );
-        if ( newRow == -1 )
+        int newRow = internalYToRow( y + ch );
+        if ( newRow == row )
         {
-            newRow = m_numRows - 1;
-        }
-        else if ( newRow == row )
-        {
-            newRow = row + 1;
+            // row < m_numRows , so newrow can't overflow here.
+           newRow = row + 1;
         }
 
         MakeCellVisible( newRow, m_currentCellCoords.GetCol() );
@@ -7655,6 +8357,11 @@ void wxGrid::GetColLabelAlignment( int *horiz, int *vert )
     *vert  = m_colLabelVertAlign;
 }
 
+int wxGrid::GetColLabelTextOrientation()
+{
+    return m_colLabelTextOrientation;
+}
+
 wxString wxGrid::GetRowLabelValue( int row )
 {
     if ( m_table )
@@ -7702,7 +8409,7 @@ void wxGrid::SetRowLabelSize( int width )
 
         m_rowLabelWidth = width;
         CalcWindowSizes();
-        Refresh( TRUE );
+        wxScrolledWindow::Refresh( TRUE );
     }
 }
 
@@ -7725,7 +8432,7 @@ void wxGrid::SetColLabelSize( int height )
 
         m_colLabelHeight = height;
         CalcWindowSizes();
-        Refresh( TRUE );
+        wxScrolledWindow::Refresh( TRUE );
     }
 }
 
@@ -7837,6 +8544,26 @@ void wxGrid::SetColLabelAlignment( int horiz, int vert )
     }
 }
 
+// Note:       under MSW, the default column label font must be changed because it
+//                             does not support vertical printing
+//
+// Example: wxFont font(9, wxSWISS, wxNORMAL, wxBOLD);
+//                             pGrid->SetLabelFont(font);
+//             pGrid->SetColLabelTextOrientation(wxVERTICAL);
+//
+void wxGrid::SetColLabelTextOrientation( int textOrientation )
+{
+    if( textOrientation == wxHORIZONTAL || textOrientation == wxVERTICAL )
+    {
+        m_colLabelTextOrientation = textOrientation;
+    }
+
+    if ( !GetBatchCount() )
+    {
+        m_colLabelWin->Refresh();
+    }
+}
+
 void wxGrid::SetRowLabelValue( int row, const wxString& s )
 {
     if ( m_table )
@@ -8008,6 +8735,11 @@ void wxGrid::SetDefaultCellAlignment( int horiz, int vert )
     m_defaultCellAttr->SetAlignment(horiz, vert);
 }
 
+void wxGrid::SetDefaultCellOverflow( bool allow )
+{
+    m_defaultCellAttr->SetOverflow(allow);
+}
+
 void wxGrid::SetDefaultCellFont( const wxFont& font )
 {
     m_defaultCellAttr->SetFont(font);
@@ -8047,6 +8779,11 @@ void wxGrid::GetDefaultCellAlignment( int *horiz, int *vert )
     m_defaultCellAttr->GetAlignment(horiz, vert);
 }
 
+bool wxGrid::GetDefaultCellOverflow()
+{
+    return m_defaultCellAttr->GetOverflow();
+}
+
 wxGridCellRenderer *wxGrid::GetDefaultRenderer() const
 {
     return m_defaultCellAttr->GetRenderer(NULL, 0, 0);
@@ -8092,6 +8829,21 @@ void wxGrid::GetCellAlignment( int row, int col, int *horiz, int *vert )
     attr->DecRef();
 }
 
+bool wxGrid::GetCellOverflow( int row, int col )
+{
+    wxGridCellAttr *attr = GetCellAttr(row, col);
+    bool allow = attr->GetOverflow();
+    attr->DecRef();
+    return allow;
+}
+
+void wxGrid::GetCellSize( int row, int col, int *num_rows, int *num_cols )
+{
+    wxGridCellAttr *attr = GetCellAttr(row, col);
+    attr->GetSize( num_rows, num_cols );
+    attr->DecRef();
+}
+
 wxGridCellRenderer* wxGrid::GetCellRenderer(int row, int col)
 {
     wxGridCellAttr* attr = GetCellAttr(row, col);
@@ -8144,13 +8896,16 @@ void wxGrid::ClearAttrCache()
 
 void wxGrid::CacheAttr(int row, int col, wxGridCellAttr *attr) const
 {
-    wxGrid *self = (wxGrid *)this;  // const_cast
+    if ( attr != NULL )
+    {
+        wxGrid *self = (wxGrid *)this;  // const_cast
 
-    self->ClearAttrCache();
-    self->m_attrCache.row = row;
-    self->m_attrCache.col = col;
-    self->m_attrCache.attr = attr;
-    wxSafeIncRef(attr);
+        self->ClearAttrCache();
+        self->m_attrCache.row = row;
+        self->m_attrCache.col = col;
+        self->m_attrCache.attr = attr;
+        wxSafeIncRef(attr);
+    }
 }
 
 bool wxGrid::LookupAttr(int row, int col, wxGridCellAttr **attr) const
@@ -8177,11 +8932,17 @@ bool wxGrid::LookupAttr(int row, int col, wxGridCellAttr **attr) const
 
 wxGridCellAttr *wxGrid::GetCellAttr(int row, int col) const
 {
-    wxGridCellAttr *attr;
-    if ( !LookupAttr(row, col, &attr) )
+    wxGridCellAttr *attr = NULL;
+    // Additional test to avoid looking at the cache e.g. for
+    // wxNoCellCoords, as this will confuse memory management.
+    if ( row >= 0 )
     {
-        attr = m_table ? m_table->GetAttr(row, col , wxGridCellAttr::Any) : (wxGridCellAttr *)NULL;
-        CacheAttr(row, col, attr);
+        if ( !LookupAttr(row, col, &attr) )
+        {
+            attr = m_table ? m_table->GetAttr(row, col , wxGridCellAttr::Any)
+                           : (wxGridCellAttr *)NULL;
+            CacheAttr(row, col, attr);
+        }
     }
     if (attr)
     {
@@ -8259,6 +9020,19 @@ void wxGrid::SetColFormatCustom(int col, const wxString& typeName)
 // setting cell attributes: this is forwarded to the table
 // ----------------------------------------------------------------------------
 
+void wxGrid::SetAttr(int row, int col, wxGridCellAttr *attr)
+{
+    if ( CanHaveAttributes() )
+    {
+        m_table->SetAttr(attr, row, col);
+        ClearAttrCache();
+    }
+    else
+    {
+        wxSafeDecRef(attr);
+    }
+}
+
 void wxGrid::SetRowAttr(int row, wxGridCellAttr *attr)
 {
     if ( CanHaveAttributes() )
@@ -8325,6 +9099,75 @@ void wxGrid::SetCellAlignment( int row, int col, int horiz, int vert )
     }
 }
 
+void wxGrid::SetCellOverflow( int row, int col, bool allow )
+{
+    if ( CanHaveAttributes() )
+    {
+        wxGridCellAttr *attr = GetOrCreateCellAttr(row, col);
+        attr->SetOverflow(allow);
+        attr->DecRef();
+    }
+}
+
+void wxGrid::SetCellSize( int row, int col, int num_rows, int num_cols )
+{
+    if ( CanHaveAttributes() )
+    {
+        int cell_rows, cell_cols;
+
+        wxGridCellAttr *attr = GetOrCreateCellAttr(row, col);
+        attr->GetSize(&cell_rows, &cell_cols);
+        attr->SetSize(num_rows, num_cols);
+        attr->DecRef();
+
+        // Cannot set the size of a cell to 0 or negative values
+        // While it is perfectly legal to do that, this function cannot
+        // handle all the possibilies, do it by hand by getting the CellAttr.
+        // You can only set the size of a cell to 1,1 or greater with this fn
+        wxASSERT_MSG( !((cell_rows < 1) || (cell_cols < 1)),
+                      wxT("wxGrid::SetCellSize setting cell size that is already part of another cell"));
+        wxASSERT_MSG( !((num_rows < 1) || (num_cols < 1)),
+                      wxT("wxGrid::SetCellSize setting cell size to < 1"));
+
+        // if this was already a multicell then "turn off" the other cells first
+        if ((cell_rows > 1) || (cell_rows > 1))
+        {
+            int i, j;
+            for (j=row; j<row+cell_rows; j++)
+            {
+                for (i=col; i<col+cell_cols; i++)
+                {
+                    if ((i != col) || (j != row))
+                    {
+                        wxGridCellAttr *attr_stub = GetOrCreateCellAttr(j, i);
+                        attr_stub->SetSize( 1, 1 );
+                        attr_stub->DecRef();
+                    }
+                }
+            }
+        }
+
+        // mark the cells that will be covered by this cell to
+        // negative or zero values to point back at this cell
+        if (((num_rows > 1) || (num_cols > 1)) && (num_rows >= 1) && (num_cols >= 1))
+        {
+            int i, j;
+            for (j=row; j<row+num_rows; j++)
+            {
+                for (i=col; i<col+num_cols; i++)
+                {
+                    if ((i != col) || (j != row))
+                    {
+                        wxGridCellAttr *attr_stub = GetOrCreateCellAttr(j, i);
+                        attr_stub->SetSize( row-j, col-i );
+                        attr_stub->DecRef();
+                    }
+                }
+            }
+        }
+    }
+}
+
 void wxGrid::SetCellRenderer(int row, int col, wxGridCellRenderer *renderer)
 {
     if ( CanHaveAttributes() )
@@ -8431,7 +9274,7 @@ void wxGrid::EnableDragGridSize( bool enable )
 
 void wxGrid::SetDefaultRowSize( int height, bool resizeExistingRows )
 {
-    m_defaultRowHeight = wxMax( height, WXGRID_MIN_ROW_HEIGHT );
+    m_defaultRowHeight = wxMax( height, m_minAcceptableRowHeight );
 
     if ( resizeExistingRows )
     {
@@ -8450,6 +9293,9 @@ void wxGrid::SetRowSize( int row, int height )
 {
     wxCHECK_RET( row >= 0 && row < m_numRows, _T("invalid row index") );
 
+    // See comment in SetColSize
+    if ( height < GetRowMinimalAcceptableHeight()) { return; }
+
     if ( m_rowHeights.IsEmpty() )
     {
         // need to really create the array
@@ -8471,7 +9317,7 @@ void wxGrid::SetRowSize( int row, int height )
 
 void wxGrid::SetDefaultColSize( int width, bool resizeExistingCols )
 {
-    m_defaultColWidth = wxMax( width, WXGRID_MIN_COL_WIDTH );
+    m_defaultColWidth = wxMax( width, m_minAcceptableColWidth );
 
     if ( resizeExistingCols )
     {
@@ -8491,13 +9337,32 @@ void wxGrid::SetColSize( int col, int width )
     wxCHECK_RET( col >= 0 && col < m_numCols, _T("invalid column index") );
 
     // 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 whe should test against the weaker 
+    // constariant of minimalAcceptableWidth, as this breaks rendering
+    // 
+    // This test then fixes sf.net bug #645734
+    
+    if ( width < GetColMinimalAcceptableWidth()) { return; }
+    
     if ( m_colWidths.IsEmpty() )
     {
         // need to really create the array
         InitColWidths();
     }
 
+    // if < 0 calc new width from label
+    if( width < 0 )
+    {
+      long w, h;
+      wxArrayString lines;
+      wxClientDC dc(m_colLabelWin);
+      dc.SetFont(GetLabelFont());
+      StringToLines(GetColLabelValue(col), lines);
+      GetTextBoxSize(dc, lines, &w, &h);
+      width = w + 6;
+    }
     int w = wxMax( 0, width );
     int diff = w - m_colWidths[col];
     m_colWidths[col] = w;
@@ -8514,24 +9379,52 @@ void wxGrid::SetColSize( int col, int width )
 
 void wxGrid::SetColMinimalWidth( int col, int width )
 {
-    m_colMinWidths.Put(col, width);
+    if (width > GetColMinimalAcceptableWidth()) {
+        m_colMinWidths[col] = width;
+    }
 }
 
 void wxGrid::SetRowMinimalHeight( int row, int width )
 {
-    m_rowMinHeights.Put(row, width);
+    if (width > GetRowMinimalAcceptableHeight()) {
+       m_rowMinHeights[row] = width;
+    }
 }
 
 int wxGrid::GetColMinimalWidth(int col) const
 {
-    long value = m_colMinWidths.Get(col);
-    return value != wxNOT_FOUND ? (int)value : WXGRID_MIN_COL_WIDTH;
+    wxLongToLongHashMap::const_iterator it = m_colMinWidths.find(col);
+    return it != m_colMinWidths.end() ? (int)it->second : m_minAcceptableColWidth;
 }
 
 int wxGrid::GetRowMinimalHeight(int row) const
 {
-    long value = m_rowMinHeights.Get(row);
-    return value != wxNOT_FOUND ? (int)value : WXGRID_MIN_ROW_HEIGHT;
+    wxLongToLongHashMap::const_iterator it = m_rowMinHeights.find(row);
+    return it != m_rowMinHeights.end() ? (int)it->second : m_minAcceptableRowHeight;
+}
+
+void wxGrid::SetColMinimalAcceptableWidth( int width )
+{
+    if ( width<1 )
+        return;
+    m_minAcceptableColWidth = width;
+}
+
+void wxGrid::SetRowMinimalAcceptableHeight( int height )
+{
+    if ( height<1 )
+        return;
+    m_minAcceptableRowHeight = height;
+};
+
+int  wxGrid::GetColMinimalAcceptableWidth() const
+{
+    return m_minAcceptableColWidth;
+}
+
+int  wxGrid::GetRowMinimalAcceptableHeight() const
+{
+    return m_minAcceptableRowHeight;
 }
 
 // ----------------------------------------------------------------------------
@@ -8581,7 +9474,11 @@ void wxGrid::AutoSizeColOrRow( int colOrRow, bool setAsMin, bool column )
     dc.SetFont( GetLabelFont() );
 
     if ( column )
+    {
         dc.GetTextExtent( GetColLabelValue(col), &w, &h );
+        if( GetColLabelTextOrientation() == wxVERTICAL )
+            w = h;
+    }
     else
         dc.GetTextExtent( GetRowLabelValue(row), &w, &h );
 
@@ -8703,13 +9600,17 @@ void wxGrid::AutoSize()
 
     // 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);
+    // CalcDimension adds m_extraWidth + 1 etc. to calculate the necessary
+    // scrollbar steps
+    wxSize sizeFit(GetScrollX(size.x + m_extraWidth + 1) * GRID_SCROLL_LINE_X,
+                   GetScrollY(size.y + m_extraHeight + 1) * GRID_SCROLL_LINE_Y);
 
-    // distribute the extra space between teh columns/rows to avoid having
+    // distribute the extra space between the columns/rows to avoid having
     // extra white space
-    wxCoord diff = sizeFit.x - size.x;
-    if ( diff )
+
+    // Remove the extra m_extraWidth + 1 added above
+    wxCoord diff = sizeFit.x - size.x + (m_extraWidth + 1);
+    if ( diff && m_numCols )
     {
         // try to resize the columns uniformly
         wxCoord diffPerCol = diff / m_numCols;
@@ -8733,8 +9634,8 @@ void wxGrid::AutoSize()
     }
 
     // same for rows
-    diff = sizeFit.y - size.y;
-    if ( diff )
+    diff = sizeFit.y - size.y - (m_extraHeight + 1);
+    if ( diff && m_numRows )
     {
         // try to resize the columns uniformly
         wxCoord diffPerRow = diff / m_numRows;
@@ -8762,13 +9663,71 @@ void wxGrid::AutoSize()
     SetClientSize(sizeFit);
 }
 
+void wxGrid::AutoSizeRowLabelSize( int row )
+{
+    wxArrayString lines;
+    long w, h;
+
+    // Hide the edit control, so it
+    // won't interfer with drag-shrinking.
+    if( IsCellEditControlShown() )
+    {
+        HideCellEditControl();
+        SaveEditControlValue();
+    }
+
+    // autosize row height depending on label text
+    StringToLines( GetRowLabelValue( row ), lines );
+    wxClientDC dc( m_rowLabelWin );
+    GetTextBoxSize( dc, lines, &w, &h);
+    if( h < m_defaultRowHeight )
+        h = m_defaultRowHeight;
+    SetRowSize(row, h);
+    ForceRefresh();
+}
+
+void wxGrid::AutoSizeColLabelSize( int col )
+{
+    wxArrayString lines;
+    long w, h;
+
+    // Hide the edit control, so it
+    // won't interfer with drag-shrinking.
+    if( IsCellEditControlShown() )
+    {
+        HideCellEditControl();
+        SaveEditControlValue();
+    }
+
+    // autosize column width depending on label text
+    StringToLines( GetColLabelValue( col ), lines );
+    wxClientDC dc( m_colLabelWin );
+    if( GetColLabelTextOrientation() == wxHORIZONTAL )
+        GetTextBoxSize( dc, lines, &w, &h);
+    else
+        GetTextBoxSize( dc, lines, &h, &w);
+    if( w < m_defaultColWidth )
+        w = m_defaultColWidth;
+    SetColSize(col, w);
+    ForceRefresh();
+}
+
 wxSize wxGrid::DoGetBestSize() const
 {
     // don't set sizes, only calculate them
     wxGrid *self = (wxGrid *)this;  // const_cast
 
-    return wxSize(self->SetOrCalcColumnSizes(TRUE),
-                  self->SetOrCalcRowSizes(TRUE));
+    int width, height;
+    width = self->SetOrCalcColumnSizes(TRUE);
+    height = self->SetOrCalcRowSizes(TRUE);
+
+    int maxwidth, maxheight;
+    wxDisplaySize( & maxwidth, & maxheight );
+
+    if ( width > maxwidth ) width = maxwidth;
+    if ( height > maxheight ) height = maxheight;
+
+    return wxSize( width, height );
 }
 
 void wxGrid::Fit()
@@ -8793,9 +9752,12 @@ void wxGrid::SetCellValue( int row, int col, const wxString& s )
         m_table->SetValue( row, col, s );
         if ( !GetBatchCount() )
         {
-            wxClientDC dc( m_gridWin );
-            PrepareDC( dc );
-            DrawCell( dc, wxGridCellCoords(row, col) );
+            int dummy;
+            wxRect rect( CellToRect( row, col ) );
+            rect.x = 0;
+            rect.width = m_gridWin->GetClientSize().GetWidth();
+            CalcScrolledPosition(0, rect.y, &dummy, &rect.y);
+            m_gridWin->Refresh( FALSE, &rect );
         }
 
         if ( m_currentCellCoords.GetRow() == row &&
@@ -8916,7 +9878,7 @@ bool wxGrid::IsSelection()
                m_selectingBottomRight != wxGridNoCellCoords) ) );
 }
 
-bool wxGrid::IsInSelection( int row, int col )
+bool wxGrid::IsInSelection( int row, int col ) const
 {
     return ( m_selection && (m_selection->IsInSelection( row, col ) ||
              ( row >= m_selectingTopLeft.GetRow() &&
@@ -8925,6 +9887,33 @@ bool wxGrid::IsInSelection( int row, int col )
                col <= m_selectingBottomRight.GetCol() )) );
 }
 
+wxGridCellCoordsArray wxGrid::GetSelectedCells() const
+{
+    if (!m_selection) { wxGridCellCoordsArray a; return a; }
+    return m_selection->m_cellSelection;
+}
+wxGridCellCoordsArray wxGrid::GetSelectionBlockTopLeft() const
+{
+    if (!m_selection) { wxGridCellCoordsArray a; return a; }
+    return m_selection->m_blockSelectionTopLeft;
+}
+wxGridCellCoordsArray wxGrid::GetSelectionBlockBottomRight() const
+{
+    if (!m_selection) { wxGridCellCoordsArray a; return a; }
+    return m_selection->m_blockSelectionBottomRight;
+}
+wxArrayInt wxGrid::GetSelectedRows() const
+{
+    if (!m_selection) { wxArrayInt a; return a; }
+    return m_selection->m_rowSelection;
+}
+wxArrayInt wxGrid::GetSelectedCols() const
+{
+    if (!m_selection) { wxArrayInt a; return a; }
+    return m_selection->m_colSelection;
+}
+
+
 void wxGrid::ClearSelection()
 {
     m_selectingTopLeft = wxGridNoCellCoords;
@@ -8963,11 +9952,63 @@ wxRect wxGrid::BlockToDeviceRect( const wxGridCellCoords &topLeft,
         return wxGridNoCellRect;
     }
 
+    int i, j;
+    int left = rect.GetLeft();
+    int top = rect.GetTop();
+    int right = rect.GetRight();
+    int bottom = rect.GetBottom();
+
+    int leftCol = topLeft.GetCol();
+    int topRow = topLeft.GetRow();
+    int rightCol = bottomRight.GetCol();
+    int bottomRow = bottomRight.GetRow();
+
+    if (left > right)
+    {
+        i = left;
+        left = right;
+        right = i;
+        i = leftCol;
+        leftCol=rightCol;
+        rightCol = i;
+    }
+
+    if (top > bottom)
+    {
+        i = top;
+        top = bottom;
+        bottom = i;
+        i = topRow;
+        topRow = bottomRow;
+        bottomRow = i;
+    }
+
+
+    for ( j = topRow; j <= bottomRow; j++ )
+    {
+        for ( i = leftCol; i <= rightCol; i++ )
+        {
+            if ((j==topRow) || (j==bottomRow) || (i==leftCol) || (i==rightCol))
+            {
+                cellRect = CellToRect( j, i );
+
+                if (cellRect.x < left)
+                    left = cellRect.x;
+                if (cellRect.y < top)
+                    top = cellRect.y;
+                if (cellRect.x + cellRect.width > right)
+                    right = cellRect.x + cellRect.width;
+                if (cellRect.y + cellRect.height > bottom)
+                    bottom = cellRect.y + cellRect.height;
+            }
+            else i = rightCol; // jump over inner cells.
+        }
+    }
+
     // convert to scrolled coords
     //
-    int left, top, right, bottom;
-    CalcScrolledPosition( rect.GetLeft(), rect.GetTop(), &left, &top );
-    CalcScrolledPosition( rect.GetRight(), rect.GetBottom(), &right, &bottom );
+    CalcScrolledPosition( left, top, &left, &top );
+    CalcScrolledPosition( right, bottom, &right, &bottom );
 
     int cw, ch;
     m_gridWin->GetClientSize( &cw, &ch );
@@ -8983,8 +10024,6 @@ wxRect wxGrid::BlockToDeviceRect( const wxGridCellCoords &topLeft,
     return rect;
 }
 
-
-
 //
 // ------ Grid event classes
 //
@@ -9063,8 +10102,5 @@ wxGridEditorCreatedEvent::wxGridEditorCreatedEvent(int id, wxEventType type,
     m_ctrl = ctrl;
 }
 
-
-#endif // !wxUSE_NEW_GRID/wxUSE_NEW_GRID
-
 #endif // wxUSE_GRID