]> git.saurik.com Git - wxWidgets.git/blobdiff - src/richtext/richtextbuffer.cpp
[ 1563875 ] wxTreeCtrl::FindItem asserts when item not found
[wxWidgets.git] / src / richtext / richtextbuffer.cpp
index e6de20bf169c61be400cbf198ffd21dea2e0c519..bc16bc9efdb6758dbdb7c4b30866c46f15aa7a78 100644 (file)
@@ -1,10 +1,10 @@
 /////////////////////////////////////////////////////////////////////////////
 /////////////////////////////////////////////////////////////////////////////
-// Name:        richtextbuffer.cpp
+// Name:        src/richtext/richtextbuffer.cpp
 // Purpose:     Buffer for wxRichTextCtrl
 // Author:      Julian Smart
 // Purpose:     Buffer for wxRichTextCtrl
 // Author:      Julian Smart
-// Modified by: 
+// Modified by:
 // Created:     2005-09-30
 // Created:     2005-09-30
-// RCS-ID:      
+// RCS-ID:      $Id$
 // Copyright:   (c) Julian Smart
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 // Copyright:   (c) Julian Smart
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
-  #pragma hdrstop
+    #pragma hdrstop
 #endif
 
 #endif
 
-#ifndef WX_PRECOMP
-  #include "wx/wx.h"
-#endif
+#if wxUSE_RICHTEXT
 
 
-#include "wx/image.h"
+#include "wx/richtext/richtextbuffer.h"
 
 
-#if wxUSE_RICHTEXT
+#ifndef WX_PRECOMP
+    #include "wx/dc.h"
+    #include "wx/intl.h"
+    #include "wx/log.h"
+    #include "wx/dataobj.h"
+    #include "wx/module.h"
+#endif
 
 #include "wx/filename.h"
 #include "wx/clipbrd.h"
 #include "wx/wfstream.h"
 
 #include "wx/filename.h"
 #include "wx/clipbrd.h"
 #include "wx/wfstream.h"
-#include "wx/module.h"
 #include "wx/mstream.h"
 #include "wx/sstream.h"
 
 #include "wx/mstream.h"
 #include "wx/sstream.h"
 
-#include "wx/richtext/richtextbuffer.h"
 #include "wx/richtext/richtextctrl.h"
 #include "wx/richtext/richtextstyles.h"
 
 #include "wx/listimpl.cpp"
 
 #include "wx/richtext/richtextctrl.h"
 #include "wx/richtext/richtextstyles.h"
 
 #include "wx/listimpl.cpp"
 
-WX_DEFINE_LIST(wxRichTextObjectList);
-WX_DEFINE_LIST(wxRichTextLineList);
+WX_DEFINE_LIST(wxRichTextObjectList)
+WX_DEFINE_LIST(wxRichTextLineList)
 
 /*!
  * wxRichTextObject
 
 /*!
  * wxRichTextObject
@@ -174,9 +176,10 @@ bool wxRichTextCompositeObject::RemoveChild(wxRichTextObject* child, bool delete
     wxRichTextObjectList::compatibility_iterator node = m_children.Find(child);
     if (node)
     {
     wxRichTextObjectList::compatibility_iterator node = m_children.Find(child);
     if (node)
     {
+        wxRichTextObject* obj = node->GetData();
+        m_children.Erase(node);
         if (deleteChild)
         if (deleteChild)
-            delete node->GetData();
-        delete node;
+            delete obj;
 
         return true;
     }
 
         return true;
     }
@@ -195,7 +198,7 @@ bool wxRichTextCompositeObject::DeleteChildren()
         child->Dereference(); // Only delete if reference count is zero
 
         node = node->GetNext();
         child->Dereference(); // Only delete if reference count is zero
 
         node = node->GetNext();
-        delete oldNode;
+        m_children.Erase(oldNode);
     }
 
     return true;
     }
 
     return true;
@@ -293,12 +296,12 @@ void wxRichTextCompositeObject::CalculateRange(long start, long& end)
 bool wxRichTextCompositeObject::DeleteRange(const wxRichTextRange& range)
 {
     wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
 bool wxRichTextCompositeObject::DeleteRange(const wxRichTextRange& range)
 {
     wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
-    
+
     while (node)
     {
         wxRichTextObject* obj = (wxRichTextObject*) node->GetData();
         wxRichTextObjectList::compatibility_iterator next = node->GetNext();
     while (node)
     {
         wxRichTextObject* obj = (wxRichTextObject*) node->GetData();
         wxRichTextObjectList::compatibility_iterator next = node->GetNext();
-        
+
         // Delete the range in each paragraph
 
         // When a chunk has been deleted, internally the content does not
         // Delete the range in each paragraph
 
         // When a chunk has been deleted, internally the content does not
@@ -307,7 +310,7 @@ bool wxRichTextCompositeObject::DeleteRange(const wxRichTextRange& range)
         // If you may delete content from the same object twice, recalculate
         // the ranges inbetween DeleteRange calls by calling CalculateRanges, and
         // adjust the range you're deleting accordingly.
         // If you may delete content from the same object twice, recalculate
         // the ranges inbetween DeleteRange calls by calling CalculateRanges, and
         // adjust the range you're deleting accordingly.
-        
+
         if (!obj->GetRange().IsOutside(range))
         {
             obj->DeleteRange(range);
         if (!obj->GetRange().IsOutside(range))
         {
             obj->DeleteRange(range);
@@ -318,13 +321,13 @@ bool wxRichTextCompositeObject::DeleteRange(const wxRichTextRange& range)
             {
                 // An empty paragraph has length 1, so won't be deleted unless the
                 // whole range is deleted.
             {
                 // An empty paragraph has length 1, so won't be deleted unless the
                 // whole range is deleted.
-                RemoveChild(obj, true);       
+                RemoveChild(obj, true);
             }
         }
             }
         }
-        
+
         node = next;
     }
         node = next;
     }
-    
+
     return true;
 }
 
     return true;
 }
 
@@ -340,9 +343,9 @@ wxString wxRichTextCompositeObject::GetTextForRange(const wxRichTextRange& range
         if (!child->GetRange().IsOutside(range))
         {
             childRange.LimitTo(child->GetRange());
         if (!child->GetRange().IsOutside(range))
         {
             childRange.LimitTo(child->GetRange());
-            
+
             wxString childText = child->GetTextForRange(childRange);
             wxString childText = child->GetTextForRange(childRange);
-            
+
             text += childText;
         }
         node = node->GetNext();
             text += childText;
         }
         node = node->GetNext();
@@ -359,7 +362,7 @@ bool wxRichTextCompositeObject::Defragment()
     {
         wxRichTextObject* child = node->GetData();
         wxRichTextCompositeObject* composite = wxDynamicCast(child, wxRichTextCompositeObject);
     {
         wxRichTextObject* child = node->GetData();
         wxRichTextCompositeObject* composite = wxDynamicCast(child, wxRichTextCompositeObject);
-        if (composite)        
+        if (composite)
             composite->Defragment();
 
         if (node->GetNext())
             composite->Defragment();
 
         if (node->GetNext())
@@ -368,7 +371,7 @@ bool wxRichTextCompositeObject::Defragment()
             if (child->CanMerge(nextChild) && child->Merge(nextChild))
             {
                 nextChild->Dereference();
             if (child->CanMerge(nextChild) && child->Merge(nextChild))
             {
                 nextChild->Dereference();
-                delete node->GetNext();
+                m_children.Erase(node->GetNext());
 
                 // Don't set node -- we'll see if we can merge again with the next
                 // child.
 
                 // Don't set node -- we'll see if we can merge again with the next
                 // child.
@@ -425,13 +428,13 @@ bool wxRichTextBox::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTex
 }
 
 /// Lay the item out
 }
 
 /// Lay the item out
-bool wxRichTextBox::Layout(wxDC& dc, const wxRect& rect, const wxRichTextRange& affected, int style)
+bool wxRichTextBox::Layout(wxDC& dc, const wxRect& rect, int style)
 {
     wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
     while (node)
     {
         wxRichTextObject* child = node->GetData();
 {
     wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
     while (node)
     {
         wxRichTextObject* child = node->GetData();
-        child->Layout(dc, rect, affected, style);
+        child->Layout(dc, rect, style);
 
         node = node->GetNext();
     }
 
         node = node->GetNext();
     }
@@ -440,13 +443,13 @@ bool wxRichTextBox::Layout(wxDC& dc, const wxRect& rect, const wxRichTextRange&
 }
 
 /// Get/set the size for the given range. Assume only has one child.
 }
 
 /// Get/set the size for the given range. Assume only has one child.
-bool wxRichTextBox::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags) const
+bool wxRichTextBox::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position) const
 {
     wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
     if (node)
     {
         wxRichTextObject* child = node->GetData();
 {
     wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
     if (node)
     {
         wxRichTextObject* child = node->GetData();
-        return child->GetRangeSize(range, size, descent, dc, flags);
+        return child->GetRangeSize(range, size, descent, dc, flags, position);
     }
     else
         return false;
     }
     else
         return false;
@@ -480,6 +483,7 @@ void wxRichTextParagraphLayoutBox::Init()
     // For now, assume is the only box and has no initial size.
     m_range = wxRichTextRange(0, -1);
 
     // For now, assume is the only box and has no initial size.
     m_range = wxRichTextRange(0, -1);
 
+    m_invalidRange.SetRange(-1, -1);
     m_leftMargin = 4;
     m_rightMargin = 4;
     m_topMargin = 4;
     m_leftMargin = 4;
     m_rightMargin = 4;
     m_topMargin = 4;
@@ -494,11 +498,11 @@ bool wxRichTextParagraphLayoutBox::Draw(wxDC& dc, const wxRichTextRange& range,
     {
         wxRichTextParagraph* child = wxDynamicCast(node->GetData(), wxRichTextParagraph);
         wxASSERT (child != NULL);
     {
         wxRichTextParagraph* child = wxDynamicCast(node->GetData(), wxRichTextParagraph);
         wxASSERT (child != NULL);
-        
+
         if (child && !child->GetRange().IsOutside(range))
         {
             wxRect childRect(child->GetPosition(), child->GetCachedSize());
         if (child && !child->GetRange().IsOutside(range))
         {
             wxRect childRect(child->GetPosition(), child->GetCachedSize());
-            
+
             if (childRect.GetTop() > rect.GetBottom() || childRect.GetBottom() < rect.GetTop())
             {
                 // Skip
             if (childRect.GetTop() > rect.GetBottom() || childRect.GetBottom() < rect.GetTop())
             {
                 // Skip
@@ -513,50 +517,101 @@ bool wxRichTextParagraphLayoutBox::Draw(wxDC& dc, const wxRichTextRange& range,
 }
 
 /// Lay the item out
 }
 
 /// Lay the item out
-bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, const wxRichTextRange& affected, int style)
+bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int style)
 {
 {
-    wxRect availableSpace(rect.x + m_leftMargin,
+    wxRect availableSpace;
+    bool formatRect = (style & wxRICHTEXT_LAYOUT_SPECIFIED_RECT) == wxRICHTEXT_LAYOUT_SPECIFIED_RECT;
+
+    // If only laying out a specific area, the passed rect has a different meaning:
+    // the visible part of the buffer.
+    if (formatRect)
+    {
+        availableSpace = wxRect(0 + m_leftMargin,
+                          0 + m_topMargin,
+                          rect.width - m_leftMargin - m_rightMargin,
+                          rect.height);
+
+        // Invalidate the part of the buffer from the first visible line
+        // to the end. If other parts of the buffer are currently invalid,
+        // then they too will be taken into account if they are above
+        // the visible point.
+        long startPos = 0;
+        wxRichTextLine* line = GetLineAtYPosition(rect.y);
+        if (line)
+            startPos = line->GetAbsoluteRange().GetStart();
+
+        Invalidate(wxRichTextRange(startPos, GetRange().GetEnd()));
+    }
+    else
+        availableSpace = wxRect(rect.x + m_leftMargin,
                           rect.y + m_topMargin,
                           rect.width - m_leftMargin - m_rightMargin,
                           rect.height - m_topMargin - m_bottomMargin);
 
     int maxWidth = 0;
                           rect.y + m_topMargin,
                           rect.width - m_leftMargin - m_rightMargin,
                           rect.height - m_topMargin - m_bottomMargin);
 
     int maxWidth = 0;
-    
+
     wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
     wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
-    
-    // If we know what range is affected, start laying out from that point on.
-    if (affected.GetStart() > GetRange().GetStart())
+
+    bool layoutAll = true;
+
+    // Get invalid range, rounding to paragraph start/end.
+    wxRichTextRange invalidRange = GetInvalidRange(true);
+
+    if (invalidRange == wxRICHTEXT_NONE && !formatRect)
+        return true;
+
+    if (invalidRange == wxRICHTEXT_ALL)
+        layoutAll = true;
+    else    // If we know what range is affected, start laying out from that point on.
+        if (invalidRange.GetStart() > GetRange().GetStart())
     {
     {
-        wxRichTextParagraph* firstParagraph = GetParagraphAtPosition(affected.GetStart());
+        wxRichTextParagraph* firstParagraph = GetParagraphAtPosition(invalidRange.GetStart());
         if (firstParagraph)
         {
             wxRichTextObjectList::compatibility_iterator firstNode = m_children.Find(firstParagraph);
         if (firstParagraph)
         {
             wxRichTextObjectList::compatibility_iterator firstNode = m_children.Find(firstParagraph);
-            wxRichTextObjectList::compatibility_iterator previousNode = firstNode ? node->GetPrevious() : (wxRichTextObjectList::compatibility_iterator) NULL;
+            wxRichTextObjectList::compatibility_iterator previousNode;
+            if ( firstNode )
+                previousNode = firstNode->GetPrevious();
             if (firstNode && previousNode)
             {
                 wxRichTextParagraph* previousParagraph = wxDynamicCast(previousNode->GetData(), wxRichTextParagraph);
                 availableSpace.y = previousParagraph->GetPosition().y + previousParagraph->GetCachedSize().y;
             if (firstNode && previousNode)
             {
                 wxRichTextParagraph* previousParagraph = wxDynamicCast(previousNode->GetData(), wxRichTextParagraph);
                 availableSpace.y = previousParagraph->GetPosition().y + previousParagraph->GetCachedSize().y;
-                
+
                 // Now we're going to start iterating from the first affected paragraph.
                 node = firstNode;
                 // Now we're going to start iterating from the first affected paragraph.
                 node = firstNode;
+
+                layoutAll = false;
             }
         }
     }
 
             }
         }
     }
 
+    // A way to force speedy rest-of-buffer layout (the 'else' below)
+    bool forceQuickLayout = false;
+
     while (node)
     {
         // Assume this box only contains paragraphs
 
         wxRichTextParagraph* child = wxDynamicCast(node->GetData(), wxRichTextParagraph);
     while (node)
     {
         // Assume this box only contains paragraphs
 
         wxRichTextParagraph* child = wxDynamicCast(node->GetData(), wxRichTextParagraph);
-        wxASSERT (child != NULL);
-        
-        if (child && !child->GetRange().IsOutside(affected))
+        wxCHECK_MSG( child, false, _T("Unknown object in layout") );
+
+        // TODO: what if the child hasn't been laid out (e.g. involved in Undo) but still has 'old' lines
+        if ( !forceQuickLayout &&
+                (layoutAll ||
+                    child->GetLines().IsEmpty() ||
+                        !child->GetRange().IsOutside(invalidRange)) )
         {
         {
-            child->Layout(dc, availableSpace, affected, style);
+            child->Layout(dc, availableSpace, style);
 
             // Layout must set the cached size
             availableSpace.y += child->GetCachedSize().y;
             maxWidth = wxMax(maxWidth, child->GetCachedSize().x);
 
             // Layout must set the cached size
             availableSpace.y += child->GetCachedSize().y;
             maxWidth = wxMax(maxWidth, child->GetCachedSize().x);
+
+            // If we're just formatting the visible part of the buffer,
+            // and we're now past the bottom of the window, start quick
+            // layout.
+            if (formatRect && child->GetPosition().y > rect.GetBottom())
+                forceQuickLayout = true;
         }
         else
         {
         }
         else
         {
@@ -564,24 +619,24 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, const wx
             // move everything up or down. This assumes that all the children have previously
             // been laid out and have wrapped line lists associated with them.
             // TODO: check all paragraphs before the affected range.
             // move everything up or down. This assumes that all the children have previously
             // been laid out and have wrapped line lists associated with them.
             // TODO: check all paragraphs before the affected range.
-            
+
             int inc = availableSpace.y - child->GetPosition().y;
             int inc = availableSpace.y - child->GetPosition().y;
-            
+
             while (node)
             {
                 wxRichTextParagraph* child = wxDynamicCast(node->GetData(), wxRichTextParagraph);
                 if (child)
                 {
                     if (child->GetLines().GetCount() == 0)
             while (node)
             {
                 wxRichTextParagraph* child = wxDynamicCast(node->GetData(), wxRichTextParagraph);
                 if (child)
                 {
                     if (child->GetLines().GetCount() == 0)
-                        child->Layout(dc, availableSpace, affected, style);
+                        child->Layout(dc, availableSpace, style);
                     else
                         child->SetPosition(wxPoint(child->GetPosition().x, child->GetPosition().y + inc));
                     else
                         child->SetPosition(wxPoint(child->GetPosition().x, child->GetPosition().y + inc));
-                
+
                     availableSpace.y += child->GetCachedSize().y;
                     maxWidth = wxMax(maxWidth, child->GetCachedSize().x);
                 }
                     availableSpace.y += child->GetCachedSize().y;
                     maxWidth = wxMax(maxWidth, child->GetCachedSize().x);
                 }
-                
-                node = node->GetNext();                
+
+                node = node->GetNext();
             }
             break;
         }
             }
             break;
         }
@@ -592,6 +647,7 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, const wx
     SetCachedSize(wxSize(maxWidth, availableSpace.y));
 
     m_dirty = false;
     SetCachedSize(wxSize(maxWidth, availableSpace.y));
 
     m_dirty = false;
+    m_invalidRange = wxRICHTEXT_NONE;
 
     return true;
 }
 
     return true;
 }
@@ -603,12 +659,12 @@ void wxRichTextParagraphLayoutBox::Copy(const wxRichTextParagraphLayoutBox& obj)
 }
 
 /// Get/set the size for the given range.
 }
 
 /// Get/set the size for the given range.
-bool wxRichTextParagraphLayoutBox::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags) const
+bool wxRichTextParagraphLayoutBox::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position) const
 {
     wxSize sz;
 
 {
     wxSize sz;
 
-    wxRichTextObjectList::compatibility_iterator startPara = NULL;
-    wxRichTextObjectList::compatibility_iterator endPara = NULL;
+    wxRichTextObjectList::compatibility_iterator startPara = wxRichTextObjectList::compatibility_iterator();
+    wxRichTextObjectList::compatibility_iterator endPara = wxRichTextObjectList::compatibility_iterator();
 
     // First find the first paragraph whose starting position is within the range.
     wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
 
     // First find the first paragraph whose starting position is within the range.
     wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
@@ -659,7 +715,7 @@ bool wxRichTextParagraphLayoutBox::GetRangeSize(const wxRichTextRange& range, wx
         wxSize childSize;
 
         int childDescent = 0;
         wxSize childSize;
 
         int childDescent = 0;
-        child->GetRangeSize(rangeToFind, childSize, childDescent, dc, flags);
+        child->GetRangeSize(rangeToFind, childSize, childDescent, dc, flags, position);
 
         descent = wxMax(childDescent, descent);
 
 
         descent = wxMax(childDescent, descent);
 
@@ -720,15 +776,17 @@ wxRichTextLine* wxRichTextParagraphLayoutBox::GetLineAtPosition(long pos, bool c
         {
             wxRichTextLine* line = node2->GetData();
 
         {
             wxRichTextLine* line = node2->GetData();
 
-            if (line->GetRange().Contains(pos) ||
+            wxRichTextRange range = line->GetAbsoluteRange();
+
+            if (range.Contains(pos) ||
 
                 // If the position is end-of-paragraph, then return the last line of
                 // of the paragraph.
 
                 // If the position is end-of-paragraph, then return the last line of
                 // of the paragraph.
-                (line->GetRange().GetEnd() == child->GetRange().GetEnd()-1) && (pos == child->GetRange().GetEnd()))
+                (range.GetEnd() == child->GetRange().GetEnd()-1) && (pos == child->GetRange().GetEnd()))
                 return line;
 
             node2 = node2->GetNext();
                 return line;
 
             node2 = node2->GetNext();
-        }          
+        }
 
         node = node->GetNext();
     }
 
         node = node->GetNext();
     }
@@ -760,7 +818,7 @@ wxRichTextLine* wxRichTextParagraphLayoutBox::GetLineAtYPosition(int y) const
                 return line;
 
             node2 = node2->GetNext();
                 return line;
 
             node2 = node2->GetNext();
-        }          
+        }
 
         node = node->GetNext();
     }
 
         node = node->GetNext();
     }
@@ -794,7 +852,7 @@ int wxRichTextParagraphLayoutBox::GetLineCount() const
 /// Get the paragraph for a given line
 wxRichTextParagraph* wxRichTextParagraphLayoutBox::GetParagraphForLine(wxRichTextLine* line) const
 {
 /// Get the paragraph for a given line
 wxRichTextParagraph* wxRichTextParagraphLayoutBox::GetParagraphForLine(wxRichTextLine* line) const
 {
-    return GetParagraphAtPosition(line->GetRange().GetStart());
+    return GetParagraphAtPosition(line->GetAbsoluteRange().GetStart());
 }
 
 /// Get the line size at the given position
 }
 
 /// Get the line size at the given position
@@ -850,7 +908,7 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text
 
     wxRichTextRange range(-1, -1);
     size_t i = 0;
 
     wxRichTextRange range(-1, -1);
     size_t i = 0;
-    size_t len = text.Length();
+    size_t len = text.length();
     wxString line;
     while (i < len)
     {
     wxString line;
     while (i < len)
     {
@@ -870,7 +928,7 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text
 
         i ++;
     }
 
         i ++;
     }
-    if (!line.IsEmpty())
+    if (!line.empty())
     {
         lastPara = new wxRichTextParagraph(line, this, & style);
         //wxLogDebug("Para Face = %s", lastPara->GetAttributes().GetFont().GetFaceName());
     {
         lastPara = new wxRichTextParagraph(line, this, & style);
         //wxLogDebug("Para Face = %s", lastPara->GetAttributes().GetFont().GetFaceName());
@@ -952,7 +1010,7 @@ bool wxRichTextParagraphLayoutBox::InsertFragment(long position, wxRichTextFragm
             while (objectNode)
             {
                 wxRichTextObject* newObj = objectNode->GetData()->Clone();
             while (objectNode)
             {
                 wxRichTextObject* newObj = objectNode->GetData()->Clone();
-                
+
                 if (!nextObject)
                 {
                     // Append
                 if (!nextObject)
                 {
                     // Append
@@ -963,7 +1021,7 @@ bool wxRichTextParagraphLayoutBox::InsertFragment(long position, wxRichTextFragm
                     // Insert before nextObject
                     para->InsertChild(newObj, nextObject);
                 }
                     // Insert before nextObject
                     para->InsertChild(newObj, nextObject);
                 }
-                
+
                 objectNode = objectNode->GetNext();
             }
 
                 objectNode = objectNode->GetNext();
             }
 
@@ -999,10 +1057,10 @@ bool wxRichTextParagraphLayoutBox::InsertFragment(long position, wxRichTextFragm
             while (objectNode)
             {
                 wxRichTextObject* newObj = objectNode->GetData()->Clone();
             while (objectNode)
             {
                 wxRichTextObject* newObj = objectNode->GetData()->Clone();
-                
+
                 // Append
                 para->AppendChild(newObj);
                 // Append
                 para->AppendChild(newObj);
-                
+
                 objectNode = objectNode->GetNext();
             }
 
                 objectNode = objectNode->GetNext();
             }
 
@@ -1028,7 +1086,7 @@ bool wxRichTextParagraphLayoutBox::InsertFragment(long position, wxRichTextFragm
                 if (nextParagraph)
                     InsertChild(finalPara, nextParagraph);
                 else
                 if (nextParagraph)
                     InsertChild(finalPara, nextParagraph);
                 else
-                    AppendChild(finalPara);                
+                    AppendChild(finalPara);
             }
             else while (i)
             {
             }
             else while (i)
             {
@@ -1041,7 +1099,7 @@ bool wxRichTextParagraphLayoutBox::InsertFragment(long position, wxRichTextFragm
                     InsertChild(finalPara, nextParagraph);
                 else
                     AppendChild(finalPara);
                     InsertChild(finalPara, nextParagraph);
                 else
                     AppendChild(finalPara);
-                
+
                 i = i->GetNext();
             }
 
                 i = i->GetNext();
             }
 
@@ -1053,7 +1111,7 @@ bool wxRichTextParagraphLayoutBox::InsertFragment(long position, wxRichTextFragm
                 // Ensure there's at least one object
                 if (finalPara->GetChildCount() == 0)
                 {
                 // Ensure there's at least one object
                 if (finalPara->GetChildCount() == 0)
                 {
-                    wxRichTextPlainText* text = new wxRichTextPlainText(wxT(""));
+                    wxRichTextPlainText* text = new wxRichTextPlainText(wxEmptyString);
                     text->SetAttributes(finalPara->GetAttributes());
 
                     finalPara->AppendChild(text);
                     text->SetAttributes(finalPara->GetAttributes());
 
                     finalPara->AppendChild(text);
@@ -1071,16 +1129,14 @@ bool wxRichTextParagraphLayoutBox::InsertFragment(long position, wxRichTextFragm
         {
             wxRichTextParagraph* para = wxDynamicCast(i->GetData(), wxRichTextParagraph);
             wxASSERT( para != NULL );
         {
             wxRichTextParagraph* para = wxDynamicCast(i->GetData(), wxRichTextParagraph);
             wxASSERT( para != NULL );
-            
+
             AppendChild(para->Clone());
             AppendChild(para->Clone());
-            
+
             i = i->GetNext();
         }
 
         return true;
     }
             i = i->GetNext();
         }
 
         return true;
     }
-
-    return false;
 }
 
 /// Make a copy of the fragment corresponding to the given range, putting it in 'fragment'.
 }
 
 /// Make a copy of the fragment corresponding to the given range, putting it in 'fragment'.
@@ -1096,7 +1152,7 @@ bool wxRichTextParagraphLayoutBox::CopyFragment(const wxRichTextRange& range, wx
         if (!para->GetRange().IsOutside(range))
         {
             fragment.AppendChild(para->Clone());
         if (!para->GetRange().IsOutside(range))
         {
             fragment.AppendChild(para->Clone());
-        }        
+        }
         i = i->GetNext();
     }
 
         i = i->GetNext();
     }
 
@@ -1173,20 +1229,21 @@ long wxRichTextParagraphLayoutBox::GetVisibleLineNumber(long pos, bool caretPosi
             while (node2)
             {
                 wxRichTextLine* line = node2->GetData();
             while (node2)
             {
                 wxRichTextLine* line = node2->GetData();
-                
-                if (line->GetRange().Contains(pos))
+                wxRichTextRange lineRange = line->GetAbsoluteRange();
+
+                if (lineRange.Contains(pos))
                 {
                     // If the caret is displayed at the end of the previous wrapped line,
                     // we want to return the line it's _displayed_ at (not the actual line
                     // containing the position).
                 {
                     // If the caret is displayed at the end of the previous wrapped line,
                     // we want to return the line it's _displayed_ at (not the actual line
                     // containing the position).
-                    if (line->GetRange().GetStart() == pos && !startOfLine && child->GetRange().GetStart() != pos)
+                    if (lineRange.GetStart() == pos && !startOfLine && child->GetRange().GetStart() != pos)
                         return lineCount - 1;
                     else
                         return lineCount;
                 }
 
                 lineCount ++;
                         return lineCount - 1;
                     else
                         return lineCount;
                 }
 
                 lineCount ++;
-                
+
                 node2 = node2->GetNext();
             }
             // If we didn't find it in the lines, it must be
                 node2 = node2->GetNext();
             }
             // If we didn't find it in the lines, it must be
@@ -1220,14 +1277,14 @@ wxRichTextLine* wxRichTextParagraphLayoutBox::GetLineForVisibleLineNumber(long l
             while (node2)
             {
                 wxRichTextLine* line = node2->GetData();
             while (node2)
             {
                 wxRichTextLine* line = node2->GetData();
-                
+
                 if (lineCount == lineNumber)
                     return line;
 
                 lineCount ++;
                 if (lineCount == lineNumber)
                     return line;
 
                 lineCount ++;
-                
+
                 node2 = node2->GetNext();
                 node2 = node2->GetNext();
-            }          
+            }
         }
         else
             lineCount += child->GetLines().GetCount();
         }
         else
             lineCount += child->GetLines().GetCount();
@@ -1243,14 +1300,14 @@ wxRichTextLine* wxRichTextParagraphLayoutBox::GetLineForVisibleLineNumber(long l
 bool wxRichTextParagraphLayoutBox::DeleteRange(const wxRichTextRange& range)
 {
     wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
 bool wxRichTextParagraphLayoutBox::DeleteRange(const wxRichTextRange& range)
 {
     wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
-    
+
     while (node)
     {
         wxRichTextParagraph* obj = wxDynamicCast(node->GetData(), wxRichTextParagraph);
         wxASSERT (obj != NULL);
 
         wxRichTextObjectList::compatibility_iterator next = node->GetNext();
     while (node)
     {
         wxRichTextParagraph* obj = wxDynamicCast(node->GetData(), wxRichTextParagraph);
         wxASSERT (obj != NULL);
 
         wxRichTextObjectList::compatibility_iterator next = node->GetNext();
-        
+
         // Delete the range in each paragraph
 
         if (!obj->GetRange().IsOutside(range))
         // Delete the range in each paragraph
 
         if (!obj->GetRange().IsOutside(range))
@@ -1299,7 +1356,7 @@ bool wxRichTextParagraphLayoutBox::DeleteRange(const wxRichTextRange& range)
                             }
 
                             wxRichTextObjectList::compatibility_iterator next1 = node1->GetNext();
                             }
 
                             wxRichTextObjectList::compatibility_iterator next1 = node1->GetNext();
-                            delete node1;
+                            nextParagraph->GetChildren().Erase(node1);
 
                             node1 = next1;
                         }
 
                             node1 = next1;
                         }
@@ -1308,14 +1365,14 @@ bool wxRichTextParagraphLayoutBox::DeleteRange(const wxRichTextRange& range)
                         RemoveChild(nextParagraph, true);
 
                     }
                         RemoveChild(nextParagraph, true);
 
                     }
-                }                
+                }
 
             }
         }
 
             }
         }
-        
+
         node = next;
     }
         node = next;
     }
-    
+
     return true;
 }
 
     return true;
 }
 
@@ -1334,9 +1391,9 @@ wxString wxRichTextParagraphLayoutBox::GetTextForRange(const wxRichTextRange& ra
                 text += wxT("\n");
             wxRichTextRange childRange = range;
             childRange.LimitTo(child->GetRange());
                 text += wxT("\n");
             wxRichTextRange childRange = range;
             childRange.LimitTo(child->GetRange());
-            
+
             wxString childText = child->GetTextForRange(childRange);
             wxString childText = child->GetTextForRange(childRange);
-            
+
             text += childText;
 
             lineCount ++;
             text += childText;
 
             lineCount ++;
@@ -1356,7 +1413,7 @@ wxString wxRichTextParagraphLayoutBox::GetText() const
 /// Get the paragraph by number
 wxRichTextParagraph* wxRichTextParagraphLayoutBox::GetParagraphAtLine(long paragraphNumber) const
 {
 /// Get the paragraph by number
 wxRichTextParagraph* wxRichTextParagraphLayoutBox::GetParagraphAtLine(long paragraphNumber) const
 {
-    if ((size_t) paragraphNumber <= GetChildCount())
+    if ((size_t) paragraphNumber >= GetChildCount())
         return NULL;
 
     return (wxRichTextParagraph*) GetChild((size_t) paragraphNumber);
         return NULL;
 
     return (wxRichTextParagraph*) GetChild((size_t) paragraphNumber);
@@ -1428,13 +1485,13 @@ wxRichTextObject* wxRichTextParagraphLayoutBox::GetLeafObjectAtPosition(long pos
     if (para)
     {
         wxRichTextObjectList::compatibility_iterator node = para->GetChildren().GetFirst();
     if (para)
     {
         wxRichTextObjectList::compatibility_iterator node = para->GetChildren().GetFirst();
-        
+
         while (node)
         {
             wxRichTextObject* child = node->GetData();
             if (child->GetRange().Contains(position))
                 return child;
         while (node)
         {
             wxRichTextObject* child = node->GetData();
             if (child->GetRange().Contains(position))
                 return child;
-            
+
             node = node->GetNext();
         }
         if (position == para->GetRange().GetEnd() && para->GetChildCount() > 0)
             node = node->GetNext();
         }
         if (position == para->GetRange().GetEnd() && para->GetChildCount() > 0)
@@ -1460,7 +1517,7 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const
     bool haveControl = (GetRichTextCtrl() != NULL);
 
     wxRichTextAction* action = NULL;
     bool haveControl = (GetRichTextCtrl() != NULL);
 
     wxRichTextAction* action = NULL;
-    
+
     if (haveControl && withUndo)
     {
         action = new wxRichTextAction(NULL, _("Change Style"), wxRICHTEXT_CHANGE_STYLE, & GetRichTextCtrl()->GetBuffer(), GetRichTextCtrl());
     if (haveControl && withUndo)
     {
         action = new wxRichTextAction(NULL, _("Change Style"), wxRICHTEXT_CHANGE_STYLE, & GetRichTextCtrl()->GetBuffer(), GetRichTextCtrl());
@@ -1484,8 +1541,8 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const
             {
                 // We'll be using a copy of the paragraph to make style changes,
                 // not updating the buffer directly.
             {
                 // We'll be using a copy of the paragraph to make style changes,
                 // not updating the buffer directly.
-                wxRichTextParagraph* newPara = NULL;
-                
+                wxRichTextParagraph* newPara wxDUMMY_INITIALIZE(NULL);
+
                 if (haveControl && withUndo)
                 {
                     newPara = new wxRichTextParagraph(*para);
                 if (haveControl && withUndo)
                 {
                     newPara = new wxRichTextParagraph(*para);
@@ -1504,24 +1561,24 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const
                 {
                     wxRichTextRange childRange(range);
                     childRange.LimitTo(newPara->GetRange());
                 {
                     wxRichTextRange childRange(range);
                     childRange.LimitTo(newPara->GetRange());
-                    
+
                     // Find the starting position and if necessary split it so
                     // we can start applying a different style.
                     // TODO: check that the style actually changes or is different
                     // from style outside of range
                     // Find the starting position and if necessary split it so
                     // we can start applying a different style.
                     // TODO: check that the style actually changes or is different
                     // from style outside of range
-                    wxRichTextObject* firstObject = NULL;
-                    wxRichTextObject* lastObject = NULL;
-                    
+                    wxRichTextObject* firstObject wxDUMMY_INITIALIZE(NULL);
+                    wxRichTextObject* lastObject wxDUMMY_INITIALIZE(NULL);
+
                     if (childRange.GetStart() == newPara->GetRange().GetStart())
                         firstObject = newPara->GetChildren().GetFirst()->GetData();
                     else
                         firstObject = newPara->SplitAt(range.GetStart());
                     if (childRange.GetStart() == newPara->GetRange().GetStart())
                         firstObject = newPara->GetChildren().GetFirst()->GetData();
                     else
                         firstObject = newPara->SplitAt(range.GetStart());
-                    
+
                     // Increment by 1 because we're apply the style one _after_ the split point
                     long splitPoint = childRange.GetEnd();
                     if (splitPoint != newPara->GetRange().GetEnd())
                         splitPoint ++;
                     // Increment by 1 because we're apply the style one _after_ the split point
                     long splitPoint = childRange.GetEnd();
                     if (splitPoint != newPara->GetRange().GetEnd())
                         splitPoint ++;
-                    
+
                     // Find last object
                     if (splitPoint == newPara->GetRange().GetEnd() || splitPoint == (newPara->GetRange().GetEnd() - 1))
                         lastObject = newPara->GetChildren().GetLast()->GetData();
                     // Find last object
                     if (splitPoint == newPara->GetRange().GetEnd() || splitPoint == (newPara->GetRange().GetEnd() - 1))
                         lastObject = newPara->GetChildren().GetLast()->GetData();
@@ -1529,29 +1586,29 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const
                         // lastObject is set as a side-effect of splitting. It's
                         // returned as the object before the new object.
                         (void) newPara->SplitAt(splitPoint, & lastObject);
                         // lastObject is set as a side-effect of splitting. It's
                         // returned as the object before the new object.
                         (void) newPara->SplitAt(splitPoint, & lastObject);
-                    
+
                     wxASSERT(firstObject != NULL);
                     wxASSERT(lastObject != NULL);
                     wxASSERT(firstObject != NULL);
                     wxASSERT(lastObject != NULL);
-                    
+
                     if (!firstObject || !lastObject)
                         continue;
                     if (!firstObject || !lastObject)
                         continue;
-                    
+
                     wxRichTextObjectList::compatibility_iterator firstNode = newPara->GetChildren().Find(firstObject);
                     wxRichTextObjectList::compatibility_iterator lastNode = newPara->GetChildren().Find(lastObject);
                     wxRichTextObjectList::compatibility_iterator firstNode = newPara->GetChildren().Find(firstObject);
                     wxRichTextObjectList::compatibility_iterator lastNode = newPara->GetChildren().Find(lastObject);
-                    
-                    wxASSERT(firstNode != NULL);
-                    wxASSERT(lastNode != NULL);
-                    
+
+                    wxASSERT(firstNode);
+                    wxASSERT(lastNode);
+
                     wxRichTextObjectList::compatibility_iterator node2 = firstNode;
                     wxRichTextObjectList::compatibility_iterator node2 = firstNode;
-                    
+
                     while (node2)
                     {
                         wxRichTextObject* child = node2->GetData();
                     while (node2)
                     {
                         wxRichTextObject* child = node2->GetData();
-                        
+
                         wxRichTextApplyStyle(child->GetAttributes(), style);
                         if (node2 == lastNode)
                             break;
                         wxRichTextApplyStyle(child->GetAttributes(), style);
                         if (node2 == lastNode)
                             break;
-                        
+
                         node2 = node2->GetNext();
                     }
                 }
                         node2 = node2->GetNext();
                     }
                 }
@@ -1576,13 +1633,15 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const
 }
 
 /// Get the text attributes for this position.
 }
 
 /// Get the text attributes for this position.
-bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxTextAttrEx& style) const
+bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxTextAttrEx& style)
 {
 {
-    wxRichTextObject* obj = NULL;
+    wxRichTextObject* obj wxDUMMY_INITIALIZE(NULL);
+
     if (style.IsParagraphStyle())
         obj = GetParagraphAtPosition(position);
     else
         obj = GetLeafObjectAtPosition(position);
     if (style.IsParagraphStyle())
         obj = GetParagraphAtPosition(position);
     else
         obj = GetLeafObjectAtPosition(position);
+
     if (obj)
     {
         style = obj->GetAttributes();
     if (obj)
     {
         style = obj->GetAttributes();
@@ -1593,13 +1652,15 @@ bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxTextAttrEx& style)
 }
 
 /// Get the text attributes for this position.
 }
 
 /// Get the text attributes for this position.
-bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxRichTextAttr& style) const
+bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxRichTextAttr& style)
 {
 {
-    wxRichTextObject* obj = NULL;
+    wxRichTextObject* obj wxDUMMY_INITIALIZE(NULL);
+
     if (style.IsParagraphStyle())
         obj = GetParagraphAtPosition(position);
     else
         obj = GetLeafObjectAtPosition(position);
     if (style.IsParagraphStyle())
         obj = GetParagraphAtPosition(position);
     else
         obj = GetLeafObjectAtPosition(position);
+
     if (obj)
     {
         style = obj->GetAttributes();
     if (obj)
     {
         style = obj->GetAttributes();
@@ -1612,7 +1673,13 @@ bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxRichTextAttr& style
 /// Set default style
 bool wxRichTextParagraphLayoutBox::SetDefaultStyle(const wxTextAttrEx& style)
 {
 /// Set default style
 bool wxRichTextParagraphLayoutBox::SetDefaultStyle(const wxTextAttrEx& style)
 {
-    m_defaultAttributes = style;
+    // keep the old attributes if the new style doesn't specify them unless the
+    // new style is empty - then reset m_defaultStyle (as there is no other way
+    // to do it)
+    if ( style.IsDefault() )
+        m_defaultAttributes = style;
+    else
+        m_defaultAttributes = wxTextAttrEx::CombineEx(style, m_defaultAttributes, NULL);
 
     return true;
 }
 
     return true;
 }
@@ -1718,7 +1785,48 @@ void wxRichTextParagraphLayoutBox::Reset()
 {
     Clear();
 
 {
     Clear();
 
-    AddParagraph(wxT(""));
+    AddParagraph(wxEmptyString);
+}
+
+/// Invalidate the buffer. With no argument, invalidates whole buffer.
+void wxRichTextParagraphLayoutBox::Invalidate(const wxRichTextRange& invalidRange)
+{
+    SetDirty(true);
+
+    if (invalidRange == wxRICHTEXT_ALL)
+    {
+        m_invalidRange = wxRICHTEXT_ALL;
+        return;
+    }
+
+    // Already invalidating everything
+    if (m_invalidRange == wxRICHTEXT_ALL)
+        return;
+
+    if ((invalidRange.GetStart() < m_invalidRange.GetStart()) || m_invalidRange.GetStart() == -1)
+        m_invalidRange.SetStart(invalidRange.GetStart());
+    if (invalidRange.GetEnd() > m_invalidRange.GetEnd())
+        m_invalidRange.SetEnd(invalidRange.GetEnd());
+}
+
+/// Get invalid range, rounding to entire paragraphs if argument is true.
+wxRichTextRange wxRichTextParagraphLayoutBox::GetInvalidRange(bool wholeParagraphs) const
+{
+    if (m_invalidRange == wxRICHTEXT_ALL || m_invalidRange == wxRICHTEXT_NONE)
+        return m_invalidRange;
+
+    wxRichTextRange range = m_invalidRange;
+
+    if (wholeParagraphs)
+    {
+        wxRichTextParagraph* para1 = GetParagraphAtPosition(range.GetStart());
+        wxRichTextParagraph* para2 = GetParagraphAtPosition(range.GetEnd());
+        if (para1)
+            range.SetStart(para1->GetRange().GetStart());
+        if (para2)
+            range.SetEnd(para2->GetRange().GetEnd());
+    }
+    return range;
 }
 
 /*!
 }
 
 /*!
@@ -1796,21 +1904,21 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range),
             else
             {
                 wxString bulletText = GetBulletText();
             else
             {
                 wxString bulletText = GetBulletText();
-                if (!bulletText.IsEmpty())
+                if (!bulletText.empty())
                 {
                     if (GetAttributes().GetFont().Ok())
                         dc.SetFont(GetAttributes().GetFont());
                 {
                     if (GetAttributes().GetFont().Ok())
                         dc.SetFont(GetAttributes().GetFont());
-                    
+
                     if (GetAttributes().GetTextColour().Ok())
                         dc.SetTextForeground(GetAttributes().GetTextColour());
                     if (GetAttributes().GetTextColour().Ok())
                         dc.SetTextForeground(GetAttributes().GetTextColour());
-                    
+
                     dc.SetBackgroundMode(wxTRANSPARENT);
                     dc.SetBackgroundMode(wxTRANSPARENT);
-                    
+
                     // Get line height from first line, if any
                     wxRichTextLine* line = m_cachedLines.GetFirst() ? (wxRichTextLine* ) m_cachedLines.GetFirst()->GetData() : (wxRichTextLine*) NULL;
                     // Get line height from first line, if any
                     wxRichTextLine* line = m_cachedLines.GetFirst() ? (wxRichTextLine* ) m_cachedLines.GetFirst()->GetData() : (wxRichTextLine*) NULL;
-                    
+
                     wxPoint linePos;
                     wxPoint linePos;
-                    int lineHeight = 0;
+                    int lineHeight wxDUMMY_INITIALIZE(0);
                     if (line)
                     {
                         lineHeight = line->GetSize().y;
                     if (line)
                     {
                         lineHeight = line->GetSize().y;
@@ -1822,24 +1930,25 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range),
                         linePos = GetPosition();
                         linePos.y += spaceBeforePara;
                     }
                         linePos = GetPosition();
                         linePos.y += spaceBeforePara;
                     }
-                    
+
                     int charHeight = dc.GetCharHeight();
                     int charHeight = dc.GetCharHeight();
-                    
+
                     int x = GetPosition().x + leftIndent;
                     int y = linePos.y + (lineHeight - charHeight);
                     int x = GetPosition().x + leftIndent;
                     int y = linePos.y + (lineHeight - charHeight);
-                    
+
                     dc.DrawText(bulletText, x, y);
                 }
             }
         }
     }
                     dc.DrawText(bulletText, x, y);
                 }
             }
         }
     }
-    
+
     // Draw the range for each line, one object at a time.
 
     wxRichTextLineList::compatibility_iterator node = m_cachedLines.GetFirst();
     while (node)
     {
         wxRichTextLine* line = node->GetData();
     // Draw the range for each line, one object at a time.
 
     wxRichTextLineList::compatibility_iterator node = m_cachedLines.GetFirst();
     while (node)
     {
         wxRichTextLine* line = node->GetData();
+        wxRichTextRange lineRange = line->GetAbsoluteRange();
 
         int maxDescent = line->GetDescent();
 
 
         int maxDescent = line->GetDescent();
 
@@ -1853,15 +1962,15 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range),
         while (node2)
         {
             wxRichTextObject* child = node2->GetData();
         while (node2)
         {
             wxRichTextObject* child = node2->GetData();
-            if (!child->GetRange().IsOutside(line->GetRange()))
+            if (!child->GetRange().IsOutside(lineRange))
             {
                 // Draw this part of the line at the correct position
                 wxRichTextRange objectRange(child->GetRange());
             {
                 // Draw this part of the line at the correct position
                 wxRichTextRange objectRange(child->GetRange());
-                objectRange.LimitTo(line->GetRange());
+                objectRange.LimitTo(lineRange);
 
                 wxSize objectSize;
                 int descent = 0;
 
                 wxSize objectSize;
                 int descent = 0;
-                child->GetRangeSize(objectRange, objectSize, descent, dc, wxRICHTEXT_UNFORMATTED);
+                child->GetRangeSize(objectRange, objectSize, descent, dc, wxRICHTEXT_UNFORMATTED, objectPosition);
 
                 // Use the child object's width, but the whole line's height
                 wxRect childRect(objectPosition, wxSize(objectSize.x, line->GetSize().y));
 
                 // Use the child object's width, but the whole line's height
                 wxRect childRect(objectPosition, wxSize(objectSize.x, line->GetSize().y));
@@ -1869,7 +1978,7 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range),
 
                 objectPosition.x += objectSize.x;
             }
 
                 objectPosition.x += objectSize.x;
             }
-            else if (child->GetRange().GetStart() > line->GetRange().GetEnd())
+            else if (child->GetRange().GetStart() > lineRange.GetEnd())
                 // Can break out of inner loop now since we've passed this line's range
                 break;
 
                 // Can break out of inner loop now since we've passed this line's range
                 break;
 
@@ -1877,15 +1986,15 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range),
         }
 
         node = node->GetNext();
         }
 
         node = node->GetNext();
-    }    
+    }
 
     return true;
 }
 
 /// Lay the item out
 
     return true;
 }
 
 /// Lay the item out
-bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRichTextRange& affected, int style)
+bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
 {
 {
-    ClearLines();
+    // ClearLines();
 
     // Increase the size of the paragraph due to spacing
     int spaceBeforePara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingBefore());
 
     // Increase the size of the paragraph due to spacing
     int spaceBeforePara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingBefore());
@@ -1955,7 +2064,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRichTextR
         // can't tell the position until the size is determined. So possibly introduce
         // another layout phase.
 
         // can't tell the position until the size is determined. So possibly introduce
         // another layout phase.
 
-        child->Layout(dc, rect, affected, style);
+        child->Layout(dc, rect, style);
 
         // Available width depends on whether we're on the first or subsequent lines
         int availableSpaceForText = (lineCount == 0 ? availableTextSpaceFirstLine : availableTextSpaceSubsequentLines);
 
         // Available width depends on whether we're on the first or subsequent lines
         int availableSpaceForText = (lineCount == 0 ? availableTextSpaceFirstLine : availableTextSpaceSubsequentLines);
@@ -1974,7 +2083,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRichTextR
             childDescent = child->GetDescent();
         }
         else
             childDescent = child->GetDescent();
         }
         else
-            GetRangeSize(wxRichTextRange(lastEndPos+1, child->GetRange().GetEnd()), childSize, childDescent, dc, wxRICHTEXT_UNFORMATTED);
+            GetRangeSize(wxRichTextRange(lastEndPos+1, child->GetRange().GetEnd()), childSize, childDescent, dc, wxRICHTEXT_UNFORMATTED,rect.GetPosition());
 
         if (childSize.x + currentWidth > availableSpaceForText)
         {
 
         if (childSize.x + currentWidth > availableSpaceForText)
         {
@@ -1993,7 +2102,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRichTextR
                 wrapPosition = wxMax(lastCompletedEndPos+1,child->GetRange().GetEnd());
 
             // wxLogDebug(wxT("Split at %ld"), wrapPosition);
                 wrapPosition = wxMax(lastCompletedEndPos+1,child->GetRange().GetEnd());
 
             // wxLogDebug(wxT("Split at %ld"), wrapPosition);
-            
+
             // Let's find the actual size of the current line now
             wxSize actualSize;
             wxRichTextRange actualRange(lastCompletedEndPos+1, wrapPosition);
             // Let's find the actual size of the current line now
             wxSize actualSize;
             wxRichTextRange actualRange(lastCompletedEndPos+1, wrapPosition);
@@ -2001,28 +2110,28 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRichTextR
             currentWidth = actualSize.x;
             lineHeight = wxMax(lineHeight, actualSize.y);
             maxDescent = wxMax(childDescent, maxDescent);
             currentWidth = actualSize.x;
             lineHeight = wxMax(lineHeight, actualSize.y);
             maxDescent = wxMax(childDescent, maxDescent);
-            
+
             // Add a new line
             // Add a new line
-            wxRichTextLine* line = new wxRichTextLine(this);            
-            line->SetRange(actualRange);
+            wxRichTextLine* line = AllocateLine(lineCount);
+
+            // Set relative range so we won't have to change line ranges when paragraphs are moved
+            line->SetRange(wxRichTextRange(actualRange.GetStart() - GetRange().GetStart(), actualRange.GetEnd() - GetRange().GetStart()));
             line->SetPosition(currentPosition);
             line->SetSize(wxSize(currentWidth, lineHeight));
             line->SetDescent(maxDescent);
 
             line->SetPosition(currentPosition);
             line->SetSize(wxSize(currentWidth, lineHeight));
             line->SetDescent(maxDescent);
 
-            m_cachedLines.Append(line);
-            
             // Now move down a line. TODO: add margins, spacing
             currentPosition.y += lineHeight;
             currentPosition.y += lineSpacing;
             currentWidth = 0;
             maxDescent = 0;
             // Now move down a line. TODO: add margins, spacing
             currentPosition.y += lineHeight;
             currentPosition.y += lineSpacing;
             currentWidth = 0;
             maxDescent = 0;
-            maxWidth = wxMax(maxWidth, currentWidth); 
-            
+            maxWidth = wxMax(maxWidth, currentWidth);
+
             lineCount ++;
 
             // TODO: account for zero-length objects, such as fields
             wxASSERT(wrapPosition > lastCompletedEndPos);
             lineCount ++;
 
             // TODO: account for zero-length objects, such as fields
             wxASSERT(wrapPosition > lastCompletedEndPos);
-            
+
             lastEndPos = wrapPosition;
             lastCompletedEndPos = lastEndPos;
 
             lastEndPos = wrapPosition;
             lastCompletedEndPos = lastEndPos;
 
@@ -2055,9 +2164,13 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRichTextR
     {
         currentPosition.x = (lineCount == 0 ? startPositionFirstLine : startPositionSubsequentLines);
 
     {
         currentPosition.x = (lineCount == 0 ? startPositionFirstLine : startPositionSubsequentLines);
 
-        wxRichTextLine* line = new wxRichTextLine(this);
-        
-        line->SetRange(lastCompletedEndPos+1, GetRange().GetEnd()-1);
+        wxRichTextLine* line = AllocateLine(lineCount);
+
+        wxRichTextRange actualRange(lastCompletedEndPos+1, GetRange().GetEnd()-1);
+
+        // Set relative range so we won't have to change line ranges when paragraphs are moved
+        line->SetRange(wxRichTextRange(actualRange.GetStart() - GetRange().GetStart(), actualRange.GetEnd() - GetRange().GetStart()));
+
         line->SetPosition(currentPosition);
 
         if (lineHeight == 0)
         line->SetPosition(currentPosition);
 
         if (lineHeight == 0)
@@ -2077,10 +2190,11 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, const wxRichTextR
         currentPosition.y += lineHeight;
         currentPosition.y += lineSpacing;
         lineCount ++;
         currentPosition.y += lineHeight;
         currentPosition.y += lineSpacing;
         lineCount ++;
-        
-        m_cachedLines.Append(line);
     }
 
     }
 
+    // Remove remaining unused line objects, if any
+    ClearUnusedLines(lineCount);
+
     // Apply styles to wrapped lines
     ApplyParagraphStyle(rect);
 
     // Apply styles to wrapped lines
     ApplyParagraphStyle(rect);
 
@@ -2125,7 +2239,7 @@ void wxRichTextParagraph::ApplyParagraphStyle(const wxRect& rect)
 bool wxRichTextParagraph::InsertText(long pos, const wxString& text)
 {
     wxRichTextObject* childToUse = NULL;
 bool wxRichTextParagraph::InsertText(long pos, const wxString& text)
 {
     wxRichTextObject* childToUse = NULL;
-    wxRichTextObjectList::compatibility_iterator nodeToUse = NULL;
+    wxRichTextObjectList::compatibility_iterator nodeToUse = wxRichTextObjectList::compatibility_iterator();
 
     wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
     while (node)
 
     wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
     while (node)
@@ -2152,7 +2266,7 @@ bool wxRichTextParagraph::InsertText(long pos, const wxString& text)
                                text + textObject->GetText().Mid(posInString);
             textObject->SetText(newText);
 
                                text + textObject->GetText().Mid(posInString);
             textObject->SetText(newText);
 
-            int textLength = text.Length();
+            int textLength = text.length();
 
             textObject->SetRange(wxRichTextRange(textObject->GetRange().GetStart(),
                                                  textObject->GetRange().GetEnd() + textLength));
 
             textObject->SetRange(wxRichTextRange(textObject->GetRange().GetStart(),
                                                  textObject->GetRange().GetEnd() + textLength));
@@ -2166,7 +2280,7 @@ bool wxRichTextParagraph::InsertText(long pos, const wxString& text)
                 wxRichTextObject* child = node->GetData();
                 child->SetRange(wxRichTextRange(textObject->GetRange().GetStart() + textLength,
                                                  textObject->GetRange().GetEnd() + textLength));
                 wxRichTextObject* child = node->GetData();
                 child->SetRange(wxRichTextRange(textObject->GetRange().GetStart() + textLength,
                                                  textObject->GetRange().GetEnd() + textLength));
-                
+
                 node = node->GetNext();
             }
 
                 node = node->GetNext();
             }
 
@@ -2204,7 +2318,7 @@ void wxRichTextParagraph::ClearLines()
 
 /// Get/set the object size for the given range. Returns false if the range
 /// is invalid for this object.
 
 /// Get/set the object size for the given range. Returns false if the range
 /// is invalid for this object.
-bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags) const
+bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position) const
 {
     if (!range.IsWithin(GetRange()))
         return false;
 {
     if (!range.IsWithin(GetRange()))
         return false;
@@ -2223,12 +2337,12 @@ bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& siz
             if (!child->GetRange().IsOutside(range))
             {
                 wxSize childSize;
             if (!child->GetRange().IsOutside(range))
             {
                 wxSize childSize;
-                
+
                 wxRichTextRange rangeToUse = range;
                 rangeToUse.LimitTo(child->GetRange());
                 int childDescent = 0;
                 wxRichTextRange rangeToUse = range;
                 rangeToUse.LimitTo(child->GetRange());
                 int childDescent = 0;
-                
-                if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, flags))
+
+                if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, flags, position))
                 {
                     sz.y = wxMax(sz.y, childSize.y);
                     sz.x += childSize.x;
                 {
                     sz.y = wxMax(sz.y, childSize.y);
                     sz.x += childSize.x;
@@ -2256,30 +2370,31 @@ bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& siz
         while (node)
         {
             wxRichTextLine* line = node->GetData();
         while (node)
         {
             wxRichTextLine* line = node->GetData();
-            if (!line->GetRange().IsOutside(range))
+            wxRichTextRange lineRange = line->GetAbsoluteRange();
+            if (!lineRange.IsOutside(range))
             {
                 wxSize lineSize;
             {
                 wxSize lineSize;
-                        
+
                 wxRichTextObjectList::compatibility_iterator node2 = m_children.GetFirst();
                 while (node2)
                 {
                     wxRichTextObject* child = node2->GetData();
                 wxRichTextObjectList::compatibility_iterator node2 = m_children.GetFirst();
                 while (node2)
                 {
                     wxRichTextObject* child = node2->GetData();
-                    
-                    if (!child->GetRange().IsOutside(line->GetRange()))
+
+                    if (!child->GetRange().IsOutside(lineRange))
                     {
                     {
-                        wxRichTextRange rangeToUse = line->GetRange();
+                        wxRichTextRange rangeToUse = lineRange;
                         rangeToUse.LimitTo(child->GetRange());
                         rangeToUse.LimitTo(child->GetRange());
-                        
+
                         wxSize childSize;
                         int childDescent = 0;
                         wxSize childSize;
                         int childDescent = 0;
-                        if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, flags))
+                        if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, flags, position))
                         {
                             lineSize.y = wxMax(lineSize.y, childSize.y);
                             lineSize.x += childSize.x;
                         }
                         descent = wxMax(descent, childDescent);
                     }
                         {
                             lineSize.y = wxMax(lineSize.y, childSize.y);
                             lineSize.x += childSize.x;
                         }
                         descent = wxMax(descent, childDescent);
                     }
-                    
+
                     node2 = node2->GetNext();
                 }
 
                     node2 = node2->GetNext();
                 }
 
@@ -2346,12 +2461,13 @@ bool wxRichTextParagraph::FindPosition(wxDC& dc, long index, wxPoint& pt, int* h
     while (node)
     {
         wxRichTextLine* line = node->GetData();
     while (node)
     {
         wxRichTextLine* line = node->GetData();
-        if (index >= line->GetRange().GetStart() && index <= line->GetRange().GetEnd())
+        wxRichTextRange lineRange = line->GetAbsoluteRange();
+        if (index >= lineRange.GetStart() && index <= lineRange.GetEnd())
         {
             // If this is the last point in the line, and we're forcing the
             // returned value to be the start of the next line, do the required
             // thing.
         {
             // If this is the last point in the line, and we're forcing the
             // returned value to be the start of the next line, do the required
             // thing.
-            if (index == line->GetRange().GetEnd() && forceLineStart)
+            if (index == lineRange.GetEnd() && forceLineStart)
             {
                 if (node->GetNext())
                 {
             {
                 if (node->GetNext())
                 {
@@ -2364,7 +2480,7 @@ bool wxRichTextParagraph::FindPosition(wxDC& dc, long index, wxPoint& pt, int* h
 
             pt.y = line->GetPosition().y + GetPosition().y;
 
 
             pt.y = line->GetPosition().y + GetPosition().y;
 
-            wxRichTextRange r(line->GetRange().GetStart(), index);
+            wxRichTextRange r(lineRange.GetStart(), index);
             wxSize rangeSize;
             int descent = 0;
 
             wxSize rangeSize;
             int descent = 0;
 
@@ -2372,7 +2488,7 @@ bool wxRichTextParagraph::FindPosition(wxDC& dc, long index, wxPoint& pt, int* h
             // then we can add this size to the line start position and
             // paragraph start position to find the actual position.
 
             // then we can add this size to the line start position and
             // paragraph start position to find the actual position.
 
-            if (GetRangeSize(r, rangeSize, descent, dc, wxRICHTEXT_UNFORMATTED))
+            if (GetRangeSize(r, rangeSize, descent, dc, wxRICHTEXT_UNFORMATTED, line->GetPosition()+ GetPosition()))
             {
                 pt.x = line->GetPosition().x + GetPosition().x + rangeSize.x;
                 *height = line->GetSize().y;
             {
                 pt.x = line->GetPosition().x + GetPosition().x + rangeSize.x;
                 *height = line->GetSize().y;
@@ -2400,31 +2516,32 @@ int wxRichTextParagraph::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition
         wxRichTextLine* line = node->GetData();
         wxPoint linePos = paraPos + line->GetPosition();
         wxSize lineSize = line->GetSize();
         wxRichTextLine* line = node->GetData();
         wxPoint linePos = paraPos + line->GetPosition();
         wxSize lineSize = line->GetSize();
+        wxRichTextRange lineRange = line->GetAbsoluteRange();
 
         if (pt.y >= linePos.y && pt.y <= linePos.y + lineSize.y)
         {
             if (pt.x < linePos.x)
             {
 
         if (pt.y >= linePos.y && pt.y <= linePos.y + lineSize.y)
         {
             if (pt.x < linePos.x)
             {
-                textPosition = line->GetRange().GetStart();
+                textPosition = lineRange.GetStart();
                 return wxRICHTEXT_HITTEST_BEFORE;
             }
             else if (pt.x >= (linePos.x + lineSize.x))
             {
                 return wxRICHTEXT_HITTEST_BEFORE;
             }
             else if (pt.x >= (linePos.x + lineSize.x))
             {
-                textPosition = line->GetRange().GetEnd();
+                textPosition = lineRange.GetEnd();
                 return wxRICHTEXT_HITTEST_AFTER;
             }
             else
             {
                 long i;
                 int lastX = linePos.x;
                 return wxRICHTEXT_HITTEST_AFTER;
             }
             else
             {
                 long i;
                 int lastX = linePos.x;
-                for (i = line->GetRange().GetStart(); i <= line->GetRange().GetEnd(); i++)
+                for (i = lineRange.GetStart(); i <= lineRange.GetEnd(); i++)
                 {
                     wxSize childSize;
                     int descent = 0;
                 {
                     wxSize childSize;
                     int descent = 0;
-                    
-                    wxRichTextRange rangeToUse(line->GetRange().GetStart(), i);
-                    
-                    GetRangeSize(rangeToUse, childSize, descent, dc, wxRICHTEXT_UNFORMATTED);
+
+                    wxRichTextRange rangeToUse(lineRange.GetStart(), i);
+
+                    GetRangeSize(rangeToUse, childSize, descent, dc, wxRICHTEXT_UNFORMATTED, linePos);
 
                     int nextX = childSize.x + linePos.x;
 
 
                     int nextX = childSize.x + linePos.x;
 
@@ -2449,7 +2566,7 @@ int wxRichTextParagraph::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition
                 }
             }
         }
                 }
             }
         }
-        
+
         node = node->GetNext();
     }
 
         node = node->GetNext();
     }
 
@@ -2468,7 +2585,12 @@ wxRichTextObject* wxRichTextParagraph::SplitAt(long pos, wxRichTextObject** prev
         if (pos == child->GetRange().GetStart())
         {
             if (previousObject)
         if (pos == child->GetRange().GetStart())
         {
             if (previousObject)
-                *previousObject = child;
+            {
+                if (node->GetPrevious())
+                    *previousObject = node->GetPrevious()->GetData();
+                else
+                    *previousObject = NULL;
+            }
 
             return child;
         }
 
             return child;
         }
@@ -2528,7 +2650,7 @@ void wxRichTextParagraph::MoveToList(wxRichTextObject* obj, wxList& list)
 /// Add content back from list
 void wxRichTextParagraph::MoveFromList(wxList& list)
 {
 /// Add content back from list
 void wxRichTextParagraph::MoveFromList(wxList& list)
 {
-    for (wxNode* node = list.GetFirst(); node; node = node->GetNext())
+    for (wxList::compatibility_iterator node = list.GetFirst(); node; node = node->GetNext())
     {
         AppendChild((wxRichTextObject*) node->GetData());
     }
     {
         AppendChild((wxRichTextObject*) node->GetData());
     }
@@ -2554,7 +2676,7 @@ wxRichTextObject* wxRichTextParagraph::FindObjectAtPosition(long position)
         wxRichTextObject* obj = node->GetData();
         if (obj->GetRange().Contains(position))
             return obj;
         wxRichTextObject* obj = node->GetData();
         if (obj->GetRange().Contains(position))
             return obj;
-        
+
         node = node->GetNext();
     }
     return NULL;
         node = node->GetNext();
     }
     return NULL;
@@ -2638,7 +2760,7 @@ bool wxRichTextParagraph::FindWrapPosition(const wxRichTextRange& range, wxDC& d
         int spacePos = plainText.Find(wxT(' '), true);
         if (spacePos != wxNOT_FOUND)
         {
         int spacePos = plainText.Find(wxT(' '), true);
         if (spacePos != wxNOT_FOUND)
         {
-            int positionsFromEndOfString = plainText.Length() - spacePos - 1;
+            int positionsFromEndOfString = plainText.length() - spacePos - 1;
             breakPosition = breakPosition - positionsFromEndOfString;
         }
     }
             breakPosition = breakPosition - positionsFromEndOfString;
         }
     }
@@ -2717,6 +2839,40 @@ wxString wxRichTextParagraph::GetBulletText()
     return text;
 }
 
     return text;
 }
 
+/// Allocate or reuse a line object
+wxRichTextLine* wxRichTextParagraph::AllocateLine(int pos)
+{
+    if (pos < (int) m_cachedLines.GetCount())
+    {
+        wxRichTextLine* line = m_cachedLines.Item(pos)->GetData();
+        line->Init(this);
+        return line;
+    }
+    else
+    {
+        wxRichTextLine* line = new wxRichTextLine(this);
+        m_cachedLines.Append(line);
+        return line;
+    }
+}
+
+/// Clear remaining unused line objects, if any
+bool wxRichTextParagraph::ClearUnusedLines(int lineCount)
+{
+    int cachedLineCount = m_cachedLines.GetCount();
+    if ((int) cachedLineCount > lineCount)
+    {
+        for (int i = 0; i < (int) (cachedLineCount - lineCount); i ++)
+        {
+            wxRichTextLineList::compatibility_iterator node = m_cachedLines.GetLast();
+            wxRichTextLine* line = node->GetData();
+            m_cachedLines.Erase(node);
+            delete line;
+        }
+    }
+    return true;
+}
+
 
 /*!
  * wxRichTextLine
 
 /*!
  * wxRichTextLine
@@ -2727,15 +2883,16 @@ wxString wxRichTextParagraph::GetBulletText()
 
 wxRichTextLine::wxRichTextLine(wxRichTextParagraph* parent)
 {
 
 wxRichTextLine::wxRichTextLine(wxRichTextParagraph* parent)
 {
-    Init();
-
-    m_parent = parent;
+    Init(parent);
 }
 
 /// Initialisation
 }
 
 /// Initialisation
-void wxRichTextLine::Init()
+void wxRichTextLine::Init(wxRichTextParagraph* parent)
 {
 {
-    m_parent = NULL;
+    m_parent = parent;
+    m_range.SetRange(-1, -1);
+    m_pos = wxPoint(0, 0);
+    m_size = wxSize(0, 0);
     m_descent = 0;
 }
 
     m_descent = 0;
 }
 
@@ -2751,6 +2908,14 @@ wxPoint wxRichTextLine::GetAbsolutePosition() const
     return m_parent->GetPosition() + m_pos;
 }
 
     return m_parent->GetPosition() + m_pos;
 }
 
+/// Get the absolute range
+wxRichTextRange wxRichTextLine::GetAbsoluteRange() const
+{
+    wxRichTextRange range(m_range.GetStart() + m_parent->GetRange().GetStart(), 0);
+    range.SetEnd(range.GetStart() + m_range.GetLength()-1);
+    return range;
+}
+
 /*!
  * wxRichTextPlainText
  * This object represents a single piece of text.
 /*!
  * wxRichTextPlainText
  * This object represents a single piece of text.
@@ -2791,24 +2956,13 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
     // (a) All selected.
     if (selectionRange.GetStart() <= range.GetStart() && selectionRange.GetEnd() >= range.GetEnd())
     {
     // (a) All selected.
     if (selectionRange.GetStart() <= range.GetStart() && selectionRange.GetEnd() >= range.GetEnd())
     {
-        // Draw all selected
-        dc.SetBrush(*wxBLACK_BRUSH);
-        dc.SetPen(*wxBLACK_PEN);
-        wxCoord w, h;
-        dc.GetTextExtent(stringChunk, & w, & h);
-        wxRect selRect(x, rect.y, w, rect.GetHeight());
-        dc.DrawRectangle(selRect);
-        dc.SetTextForeground(*wxWHITE);
-        dc.SetBackgroundMode(wxTRANSPARENT);
-        dc.DrawText(stringChunk, x, y);
+        DrawTabbedString(dc, rect,stringChunk, x, y, true);
     }
     // (b) None selected.
     else if (selectionRange.GetEnd() < range.GetStart() || selectionRange.GetStart() > range.GetEnd())
     {
         // Draw all unselected
     }
     // (b) None selected.
     else if (selectionRange.GetEnd() < range.GetStart() || selectionRange.GetStart() > range.GetEnd())
     {
         // Draw all unselected
-        dc.SetTextForeground(GetAttributes().GetTextColour());
-        dc.SetBackgroundMode(wxTRANSPARENT);
-        dc.DrawText(stringChunk, x, y);
+        DrawTabbedString(dc, rect,stringChunk, x, y, false);
     }
     else
     {
     }
     else
     {
@@ -2816,7 +2970,7 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
         // Let's draw unselected chunk, selected chunk, then unselected chunk.
 
         dc.SetBackgroundMode(wxTRANSPARENT);
         // Let's draw unselected chunk, selected chunk, then unselected chunk.
 
         dc.SetBackgroundMode(wxTRANSPARENT);
-    
+
         // 1. Initial unselected chunk, if any, up until start of selection.
         if (selectionRange.GetStart() > range.GetStart() && selectionRange.GetStart() <= range.GetEnd())
         {
         // 1. Initial unselected chunk, if any, up until start of selection.
         if (selectionRange.GetStart() > range.GetStart() && selectionRange.GetStart() <= range.GetEnd())
         {
@@ -2827,12 +2981,7 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
                 wxLogDebug(wxT("Mid(%d, %d"), (int)(r1 - offset), (int)fragmentLen);
             wxString stringFragment = m_text.Mid(r1 - offset, fragmentLen);
 
                 wxLogDebug(wxT("Mid(%d, %d"), (int)(r1 - offset), (int)fragmentLen);
             wxString stringFragment = m_text.Mid(r1 - offset, fragmentLen);
 
-            dc.SetTextForeground(GetAttributes().GetTextColour());
-            dc.DrawText(stringFragment, x, y);
-
-            wxCoord w, h;
-            dc.GetTextExtent(stringFragment, & w, & h);
-            x += w;
+            DrawTabbedString(dc, rect,stringFragment, x, y, false);
         }
 
         // 2. Selected chunk, if any.
         }
 
         // 2. Selected chunk, if any.
@@ -2846,17 +2995,7 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
                 wxLogDebug(wxT("Mid(%d, %d"), (int)(s1 - offset), (int)fragmentLen);
             wxString stringFragment = m_text.Mid(s1 - offset, fragmentLen);
 
                 wxLogDebug(wxT("Mid(%d, %d"), (int)(s1 - offset), (int)fragmentLen);
             wxString stringFragment = m_text.Mid(s1 - offset, fragmentLen);
 
-            wxCoord w, h;
-            dc.GetTextExtent(stringFragment, & w, & h);
-            wxRect selRect(x, rect.y, w, rect.GetHeight());
-
-            dc.SetBrush(*wxBLACK_BRUSH);
-            dc.SetPen(*wxBLACK_PEN);
-            dc.DrawRectangle(selRect);
-            dc.SetTextForeground(*wxWHITE);
-            dc.DrawText(stringFragment, x, y);
-
-            x += w;
+            DrawTabbedString(dc, rect,stringFragment, x, y, true);
         }
 
         // 3. Remaining unselected chunk, if any
         }
 
         // 3. Remaining unselected chunk, if any
@@ -2870,16 +3009,90 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
                 wxLogDebug(wxT("Mid(%d, %d"), (int)(s2 - offset), (int)fragmentLen);
             wxString stringFragment = m_text.Mid(s2 - offset, fragmentLen);
 
                 wxLogDebug(wxT("Mid(%d, %d"), (int)(s2 - offset), (int)fragmentLen);
             wxString stringFragment = m_text.Mid(s2 - offset, fragmentLen);
 
-            dc.SetTextForeground(GetAttributes().GetTextColour());
-            dc.DrawText(stringFragment, x, y);
-        }        
+            DrawTabbedString(dc, rect,stringFragment, x, y, false);
+        }
     }
 
     return true;
 }
 
     }
 
     return true;
 }
 
+bool wxRichTextPlainText::DrawTabbedString(wxDC& dc,const wxRect& rect,wxString& str, wxCoord& x, wxCoord& y, bool selected)
+{
+    wxArrayInt tab_array =  GetAttributes().GetTabs();
+    if (tab_array.IsEmpty())
+    {
+        // create a default tab list at 10 mm each.
+        for (int i = 0; i < 20; ++i)
+        {
+            tab_array.Add(i*100);
+        }
+    }
+    int map_mode = dc.GetMapMode();
+    dc.SetMapMode(wxMM_LOMETRIC );
+    int num_tabs = tab_array.GetCount();
+    for (int i = 0; i < num_tabs; ++i)
+    {
+       tab_array[i] = dc.LogicalToDeviceXRel(tab_array[i]);
+    }
+
+    dc.SetMapMode(map_mode );
+    int next_tab_pos = -1;
+    int tab_pos = -1;
+    wxCoord w, h;
+
+    if(selected)
+    {
+        dc.SetBrush(*wxBLACK_BRUSH);
+        dc.SetPen(*wxBLACK_PEN);
+        dc.SetTextForeground(*wxWHITE);
+        dc.SetBackgroundMode(wxTRANSPARENT);
+    }
+    else
+    {
+        dc.SetTextForeground(GetAttributes().GetTextColour());
+        dc.SetBackgroundMode(wxTRANSPARENT);
+    }
+
+    while (str.Find(wxT('\t')) >= 0)
+    {
+        // the string has a tab
+        // break up the string at the Tab
+        wxString stringChunk = str.BeforeFirst(wxT('\t'));
+        str = str.AfterFirst(wxT('\t'));
+        dc.GetTextExtent(stringChunk, & w, & h);
+        tab_pos = x + w;
+        bool not_found = true;
+        for (int i = 0; i < num_tabs && not_found; ++i)
+        {
+            next_tab_pos = tab_array.Item(i);
+            if (next_tab_pos > tab_pos)
+            {
+                not_found = false;
+                if (selected)
+                {
+                    w = next_tab_pos - x;
+                    wxRect selRect(x, rect.y, w, rect.GetHeight());
+                    dc.DrawRectangle(selRect);
+                }
+                dc.DrawText(stringChunk, x, y);
+                x = next_tab_pos;
+            }
+        }
+    }
+
+    dc.GetTextExtent(str, & w, & h);
+    if (selected)
+    {
+        wxRect selRect(x, rect.y, w, rect.GetHeight());
+        dc.DrawRectangle(selRect);
+    }
+    dc.DrawText(str, x, y);
+    x += w;
+    return true;
+
+}
 /// Lay the item out
 /// Lay the item out
-bool wxRichTextPlainText::Layout(wxDC& dc, const wxRect& WXUNUSED(rect), const wxRichTextRange& WXUNUSED(affected), int WXUNUSED(style))
+bool wxRichTextPlainText::Layout(wxDC& dc, const wxRect& WXUNUSED(rect), int WXUNUSED(style))
 {
     if (GetAttributes().GetFont().Ok())
         dc.SetFont(GetAttributes().GetFont());
 {
     if (GetAttributes().GetFont().Ok())
         dc.SetFont(GetAttributes().GetFont());
@@ -2901,7 +3114,7 @@ void wxRichTextPlainText::Copy(const wxRichTextPlainText& obj)
 
 /// Get/set the object size for the given range. Returns false if the range
 /// is invalid for this object.
 
 /// Get/set the object size for the given range. Returns false if the range
 /// is invalid for this object.
-bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int WXUNUSED(flags)) const
+bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int WXUNUSED(flags), wxPoint position) const
 {
     if (!range.IsWithin(GetRange()))
         return false;
 {
     if (!range.IsWithin(GetRange()))
         return false;
@@ -2917,8 +3130,55 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz
     long len = range.GetLength();
     wxString stringChunk = m_text.Mid(startPos, (size_t) len);
     wxCoord w, h;
     long len = range.GetLength();
     wxString stringChunk = m_text.Mid(startPos, (size_t) len);
     wxCoord w, h;
+    int width = 0;
+    if (stringChunk.Find(wxT('\t')) >= 0)
+    {
+        // the string has a tab
+        wxArrayInt tab_array =  GetAttributes().GetTabs();
+        if (tab_array.IsEmpty())
+        {
+            // create a default tab list at 10 mm each.
+            for (int i = 0; i < 20; ++i)
+            {
+                tab_array.Add(i*100);
+            }
+        }
+
+        int map_mode = dc.GetMapMode();
+        dc.SetMapMode(wxMM_LOMETRIC );
+        int num_tabs = tab_array.GetCount();
+
+        for (int i = 0; i < num_tabs; ++i)
+        {
+            tab_array[i] = dc.LogicalToDeviceXRel(tab_array[i]);
+        }
+        dc.SetMapMode(map_mode );
+        int next_tab_pos = -1;
+
+        while (stringChunk.Find(wxT('\t')) >= 0)
+        {
+            // the string has a tab
+            // break up the string at the Tab
+            wxString stringFragment = stringChunk.BeforeFirst(wxT('\t'));
+            stringChunk = stringChunk.AfterFirst(wxT('\t'));
+            dc.GetTextExtent(stringFragment, & w, & h);
+            width += w;
+            int absolute_width = width + position.x;
+            bool not_found = true;
+            for (int i = 0; i < num_tabs && not_found; ++i)
+            {
+                next_tab_pos = tab_array.Item(i);
+                if (next_tab_pos > absolute_width)
+                {
+                    not_found = false;
+                    width = next_tab_pos - position.x;
+                }
+            }
+        }
+    }
     dc.GetTextExtent(stringChunk, & w, & h, & descent);
     dc.GetTextExtent(stringChunk, & w, & h, & descent);
-    size = wxSize(w, dc.GetCharHeight());
+    width += w;
+    size = wxSize(width, dc.GetCharHeight());
 
     return true;
 }
 
     return true;
 }
@@ -2928,7 +3188,7 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz
 wxRichTextObject* wxRichTextPlainText::DoSplit(long pos)
 {
     int index = pos - GetRange().GetStart();
 wxRichTextObject* wxRichTextPlainText::DoSplit(long pos)
 {
     int index = pos - GetRange().GetStart();
-    if (index < 0 || index >= (int) m_text.Length())
+    if (index < 0 || index >= (int) m_text.length())
         return NULL;
 
     wxString firstPart = m_text.Mid(0, index);
         return NULL;
 
     wxString firstPart = m_text.Mid(0, index);
@@ -2948,7 +3208,7 @@ wxRichTextObject* wxRichTextPlainText::DoSplit(long pos)
 /// Calculate range
 void wxRichTextPlainText::CalculateRange(long start, long& end)
 {
 /// Calculate range
 void wxRichTextPlainText::CalculateRange(long start, long& end)
 {
-    end = start + m_text.Length() - 1;
+    end = start + m_text.length() - 1;
     m_range.SetRange(start, end);
 }
 
     m_range.SetRange(start, end);
 }
 
@@ -2989,7 +3249,7 @@ wxString wxRichTextPlainText::GetTextForRange(const wxRichTextRange& range) cons
 bool wxRichTextPlainText::CanMerge(wxRichTextObject* object) const
 {
     return object->GetClassInfo() == CLASSINFO(wxRichTextPlainText) &&
 bool wxRichTextPlainText::CanMerge(wxRichTextObject* object) const
 {
     return object->GetClassInfo() == CLASSINFO(wxRichTextPlainText) &&
-        (m_text.IsEmpty() || wxTextAttrEq(GetAttributes(), object->GetAttributes()));
+        (m_text.empty() || wxTextAttrEq(GetAttributes(), object->GetAttributes()));
 }
 
 /// Returns true if this object merged itself with the given one.
 }
 
 /// Returns true if this object merged itself with the given one.
@@ -3049,14 +3309,16 @@ void wxRichTextBuffer::Clear()
     DeleteChildren();
     GetCommandProcessor()->ClearCommands();
     Modify(false);
     DeleteChildren();
     GetCommandProcessor()->ClearCommands();
     Modify(false);
+    Invalidate(wxRICHTEXT_ALL);
 }
 
 void wxRichTextBuffer::Reset()
 {
     DeleteChildren();
 }
 
 void wxRichTextBuffer::Reset()
 {
     DeleteChildren();
-    AddParagraph(wxT(""));
+    AddParagraph(wxEmptyString);
     GetCommandProcessor()->ClearCommands();
     Modify(false);
     GetCommandProcessor()->ClearCommands();
     Modify(false);
+    Invalidate(wxRICHTEXT_ALL);
 }
 
 /// Submit command to insert the given text
 }
 
 /// Submit command to insert the given text
@@ -3071,10 +3333,10 @@ bool wxRichTextBuffer::InsertTextWithUndo(long pos, const wxString& text, wxRich
     action->SetPosition(pos);
 
     // Set the range we'll need to delete in Undo
     action->SetPosition(pos);
 
     // Set the range we'll need to delete in Undo
-    action->SetRange(wxRichTextRange(pos, pos + text.Length() - 1));
-    
+    action->SetRange(wxRichTextRange(pos, pos + text.length() - 1));
+
     SubmitAction(action);
     SubmitAction(action);
-        
+
     return true;
 }
 
     return true;
 }
 
@@ -3085,8 +3347,8 @@ bool wxRichTextBuffer::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl)
 
     wxTextAttrEx attr(GetBasicStyle());
     wxRichTextApplyStyle(attr, GetDefaultStyle());
 
     wxTextAttrEx attr(GetBasicStyle());
     wxRichTextApplyStyle(attr, GetDefaultStyle());
-    
-    wxRichTextParagraph* newPara = new wxRichTextParagraph(wxT(""), this, & attr);
+
+    wxRichTextParagraph* newPara = new wxRichTextParagraph(wxEmptyString, this, & attr);
     action->GetNewParagraphs().AppendChild(newPara);
     action->GetNewParagraphs().UpdateRanges();
     action->GetNewParagraphs().SetPartialParagraph(false);
     action->GetNewParagraphs().AppendChild(newPara);
     action->GetNewParagraphs().UpdateRanges();
     action->GetNewParagraphs().SetPartialParagraph(false);
@@ -3094,9 +3356,9 @@ bool wxRichTextBuffer::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl)
 
     // Set the range we'll need to delete in Undo
     action->SetRange(wxRichTextRange(pos, pos));
 
     // Set the range we'll need to delete in Undo
     action->SetRange(wxRichTextRange(pos, pos));
-    
+
     SubmitAction(action);
     SubmitAction(action);
-        
+
     return true;
 }
 
     return true;
 }
 
@@ -3107,7 +3369,7 @@ bool wxRichTextBuffer::InsertImageWithUndo(long pos, const wxRichTextImageBlock&
 
     wxTextAttrEx attr(GetBasicStyle());
     wxRichTextApplyStyle(attr, GetDefaultStyle());
 
     wxTextAttrEx attr(GetBasicStyle());
     wxRichTextApplyStyle(attr, GetDefaultStyle());
-    
+
     wxRichTextParagraph* newPara = new wxRichTextParagraph(this, & attr);
     wxRichTextImage* imageObject = new wxRichTextImage(imageBlock, newPara);
     newPara->AppendChild(imageObject);
     wxRichTextParagraph* newPara = new wxRichTextParagraph(this, & attr);
     wxRichTextImage* imageObject = new wxRichTextImage(imageBlock, newPara);
     newPara->AppendChild(imageObject);
@@ -3120,9 +3382,9 @@ bool wxRichTextBuffer::InsertImageWithUndo(long pos, const wxRichTextImageBlock&
 
     // Set the range we'll need to delete in Undo
     action->SetRange(wxRichTextRange(pos, pos));
 
     // Set the range we'll need to delete in Undo
     action->SetRange(wxRichTextRange(pos, pos));
-    
+
     SubmitAction(action);
     SubmitAction(action);
-        
+
     return true;
 }
 
     return true;
 }
 
@@ -3130,12 +3392,12 @@ bool wxRichTextBuffer::InsertImageWithUndo(long pos, const wxRichTextImageBlock&
 bool wxRichTextBuffer::DeleteRangeWithUndo(const wxRichTextRange& range, long initialCaretPosition, long WXUNUSED(newCaretPositon), wxRichTextCtrl* ctrl)
 {
     wxRichTextAction* action = new wxRichTextAction(NULL, _("Delete"), wxRICHTEXT_DELETE, this, ctrl);
 bool wxRichTextBuffer::DeleteRangeWithUndo(const wxRichTextRange& range, long initialCaretPosition, long WXUNUSED(newCaretPositon), wxRichTextCtrl* ctrl)
 {
     wxRichTextAction* action = new wxRichTextAction(NULL, _("Delete"), wxRICHTEXT_DELETE, this, ctrl);
-    
+
     action->SetPosition(initialCaretPosition);
 
     // Set the range to delete
     action->SetRange(range);
     action->SetPosition(initialCaretPosition);
 
     // Set the range to delete
     action->SetRange(range);
-    
+
     // Copy the fragment that we'll need to restore in Undo
     CopyFragment(range, action->GetOldParagraphs());
 
     // Copy the fragment that we'll need to restore in Undo
     CopyFragment(range, action->GetOldParagraphs());
 
@@ -3160,7 +3422,7 @@ bool wxRichTextBuffer::DeleteRangeWithUndo(const wxRichTextRange& range, long in
     }
 
     SubmitAction(action);
     }
 
     SubmitAction(action);
-        
+
     return true;
 }
 
     return true;
 }
 
@@ -3177,7 +3439,7 @@ bool wxRichTextBuffer::BeginBatchUndo(const wxString& cmdName)
         m_batchedCommand = new wxRichTextCommand(cmdName);
     }
 
         m_batchedCommand = new wxRichTextCommand(cmdName);
     }
 
-    m_batchedCommandDepth ++;    
+    m_batchedCommandDepth ++;
 
     return true;
 }
 
     return true;
 }
@@ -3219,7 +3481,7 @@ bool wxRichTextBuffer::SubmitAction(wxRichTextAction* action)
 /// Begin suppressing undo/redo commands.
 bool wxRichTextBuffer::BeginSuppressUndo()
 {
 /// Begin suppressing undo/redo commands.
 bool wxRichTextBuffer::BeginSuppressUndo()
 {
-    m_suppressUndo ++;    
+    m_suppressUndo ++;
 
     return true;
 }
 
     return true;
 }
@@ -3227,7 +3489,7 @@ bool wxRichTextBuffer::BeginSuppressUndo()
 /// End suppressing undo/redo commands.
 bool wxRichTextBuffer::EndSuppressUndo()
 {
 /// End suppressing undo/redo commands.
 bool wxRichTextBuffer::EndSuppressUndo()
 {
-    m_suppressUndo --;    
+    m_suppressUndo --;
 
     return true;
 }
 
     return true;
 }
@@ -3253,15 +3515,15 @@ bool wxRichTextBuffer::BeginStyle(const wxTextAttrEx& style)
 /// End the style
 bool wxRichTextBuffer::EndStyle()
 {
 /// End the style
 bool wxRichTextBuffer::EndStyle()
 {
-    if (m_attributeStack.GetFirst() == NULL)
+    if (!m_attributeStack.GetFirst())
     {
         wxLogDebug(_("Too many EndStyle calls!"));
         return false;
     }
 
     {
         wxLogDebug(_("Too many EndStyle calls!"));
         return false;
     }
 
-    wxNode* node = m_attributeStack.GetLast();
+    wxList::compatibility_iterator node = m_attributeStack.GetLast();
     wxTextAttrEx* attr = (wxTextAttrEx*)node->GetData();
     wxTextAttrEx* attr = (wxTextAttrEx*)node->GetData();
-    delete node;
+    m_attributeStack.Erase(node);
 
     SetDefaultStyle(*attr);
 
 
     SetDefaultStyle(*attr);
 
@@ -3280,7 +3542,7 @@ bool wxRichTextBuffer::EndAllStyles()
 /// Clear the style stack
 void wxRichTextBuffer::ClearStyleStack()
 {
 /// Clear the style stack
 void wxRichTextBuffer::ClearStyleStack()
 {
-    for (wxNode* node = m_attributeStack.GetFirst(); node; node = node->GetNext())
+    for (wxList::compatibility_iterator node = m_attributeStack.GetFirst(); node; node = node->GetNext())
         delete (wxTextAttrEx*) node->GetData();
     m_attributeStack.Clear();
 }
         delete (wxTextAttrEx*) node->GetData();
     m_attributeStack.Clear();
 }
@@ -3293,7 +3555,7 @@ bool wxRichTextBuffer::BeginBold()
 
     wxTextAttrEx attr;
     attr.SetFont(font,wxTEXT_ATTR_FONT_WEIGHT);
 
     wxTextAttrEx attr;
     attr.SetFont(font,wxTEXT_ATTR_FONT_WEIGHT);
-    
+
     return BeginStyle(attr);
 }
 
     return BeginStyle(attr);
 }
 
@@ -3305,7 +3567,7 @@ bool wxRichTextBuffer::BeginItalic()
 
     wxTextAttrEx attr;
     attr.SetFont(font, wxTEXT_ATTR_FONT_ITALIC);
 
     wxTextAttrEx attr;
     attr.SetFont(font, wxTEXT_ATTR_FONT_ITALIC);
-    
+
     return BeginStyle(attr);
 }
 
     return BeginStyle(attr);
 }
 
@@ -3317,7 +3579,7 @@ bool wxRichTextBuffer::BeginUnderline()
 
     wxTextAttrEx attr;
     attr.SetFont(font, wxTEXT_ATTR_FONT_UNDERLINE);
 
     wxTextAttrEx attr;
     attr.SetFont(font, wxTEXT_ATTR_FONT_UNDERLINE);
-    
+
     return BeginStyle(attr);
 }
 
     return BeginStyle(attr);
 }
 
@@ -3329,7 +3591,7 @@ bool wxRichTextBuffer::BeginFontSize(int pointSize)
 
     wxTextAttrEx attr;
     attr.SetFont(font, wxTEXT_ATTR_FONT_SIZE);
 
     wxTextAttrEx attr;
     attr.SetFont(font, wxTEXT_ATTR_FONT_SIZE);
-    
+
     return BeginStyle(attr);
 }
 
     return BeginStyle(attr);
 }
 
@@ -3339,7 +3601,7 @@ bool wxRichTextBuffer::BeginFont(const wxFont& font)
     wxTextAttrEx attr;
     attr.SetFlags(wxTEXT_ATTR_FONT);
     attr.SetFont(font);
     wxTextAttrEx attr;
     attr.SetFlags(wxTEXT_ATTR_FONT);
     attr.SetFont(font);
-    
+
     return BeginStyle(attr);
 }
 
     return BeginStyle(attr);
 }
 
@@ -3349,7 +3611,7 @@ bool wxRichTextBuffer::BeginTextColour(const wxColour& colour)
     wxTextAttrEx attr;
     attr.SetFlags(wxTEXT_ATTR_TEXT_COLOUR);
     attr.SetTextColour(colour);
     wxTextAttrEx attr;
     attr.SetFlags(wxTEXT_ATTR_TEXT_COLOUR);
     attr.SetTextColour(colour);
-    
+
     return BeginStyle(attr);
 }
 
     return BeginStyle(attr);
 }
 
@@ -3359,7 +3621,7 @@ bool wxRichTextBuffer::BeginAlignment(wxTextAttrAlignment alignment)
     wxTextAttrEx attr;
     attr.SetFlags(wxTEXT_ATTR_ALIGNMENT);
     attr.SetAlignment(alignment);
     wxTextAttrEx attr;
     attr.SetFlags(wxTEXT_ATTR_ALIGNMENT);
     attr.SetAlignment(alignment);
-    
+
     return BeginStyle(attr);
 }
 
     return BeginStyle(attr);
 }
 
@@ -3369,7 +3631,7 @@ bool wxRichTextBuffer::BeginLeftIndent(int leftIndent, int leftSubIndent)
     wxTextAttrEx attr;
     attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT);
     attr.SetLeftIndent(leftIndent, leftSubIndent);
     wxTextAttrEx attr;
     attr.SetFlags(wxTEXT_ATTR_LEFT_INDENT);
     attr.SetLeftIndent(leftIndent, leftSubIndent);
-    
+
     return BeginStyle(attr);
 }
 
     return BeginStyle(attr);
 }
 
@@ -3379,7 +3641,7 @@ bool wxRichTextBuffer::BeginRightIndent(int rightIndent)
     wxTextAttrEx attr;
     attr.SetFlags(wxTEXT_ATTR_RIGHT_INDENT);
     attr.SetRightIndent(rightIndent);
     wxTextAttrEx attr;
     attr.SetFlags(wxTEXT_ATTR_RIGHT_INDENT);
     attr.SetRightIndent(rightIndent);
-    
+
     return BeginStyle(attr);
 }
 
     return BeginStyle(attr);
 }
 
@@ -3396,7 +3658,7 @@ bool wxRichTextBuffer::BeginParagraphSpacing(int before, int after)
     attr.SetFlags(flags);
     attr.SetParagraphSpacingBefore(before);
     attr.SetParagraphSpacingAfter(after);
     attr.SetFlags(flags);
     attr.SetParagraphSpacingBefore(before);
     attr.SetParagraphSpacingAfter(after);
-    
+
     return BeginStyle(attr);
 }
 
     return BeginStyle(attr);
 }
 
@@ -3406,7 +3668,7 @@ bool wxRichTextBuffer::BeginLineSpacing(int lineSpacing)
     wxTextAttrEx attr;
     attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
     attr.SetLineSpacing(lineSpacing);
     wxTextAttrEx attr;
     attr.SetFlags(wxTEXT_ATTR_LINE_SPACING);
     attr.SetLineSpacing(lineSpacing);
-    
+
     return BeginStyle(attr);
 }
 
     return BeginStyle(attr);
 }
 
@@ -3418,7 +3680,7 @@ bool wxRichTextBuffer::BeginNumberedBullet(int bulletNumber, int leftIndent, int
     attr.SetBulletStyle(bulletStyle);
     attr.SetBulletNumber(bulletNumber);
     attr.SetLeftIndent(leftIndent, leftSubIndent);
     attr.SetBulletStyle(bulletStyle);
     attr.SetBulletNumber(bulletNumber);
     attr.SetLeftIndent(leftIndent, leftSubIndent);
-    
+
     return BeginStyle(attr);
 }
 
     return BeginStyle(attr);
 }
 
@@ -3430,7 +3692,7 @@ bool wxRichTextBuffer::BeginSymbolBullet(wxChar symbol, int leftIndent, int left
     attr.SetBulletStyle(bulletStyle);
     attr.SetLeftIndent(leftIndent, leftSubIndent);
     attr.SetBulletSymbol(symbol);
     attr.SetBulletStyle(bulletStyle);
     attr.SetLeftIndent(leftIndent, leftSubIndent);
     attr.SetBulletSymbol(symbol);
-    
+
     return BeginStyle(attr);
 }
 
     return BeginStyle(attr);
 }
 
@@ -3568,8 +3830,11 @@ void wxRichTextBuffer::CleanUpHandlers()
     sm_handlers.Clear();
 }
 
     sm_handlers.Clear();
 }
 
-wxString wxRichTextBuffer::GetExtWildcard(bool combine, bool save)
+wxString wxRichTextBuffer::GetExtWildcard(bool combine, bool save, wxArrayInt* types)
 {
 {
+    if (types)
+        types->Clear();
+
     wxString wildcard;
 
     wxList::compatibility_iterator node = GetHandlers().GetFirst();
     wxString wildcard;
 
     wxList::compatibility_iterator node = GetHandlers().GetFirst();
@@ -3596,6 +3861,8 @@ wxString wxRichTextBuffer::GetExtWildcard(bool combine, bool save)
                 wildcard += handler->GetExtension();
                 wildcard += wxT(")|*.");
                 wildcard += handler->GetExtension();
                 wildcard += handler->GetExtension();
                 wildcard += wxT(")|*.");
                 wildcard += handler->GetExtension();
+                if (types)
+                    types->Add(handler->GetType());
             }
             count ++;
         }
             }
             count ++;
         }
@@ -3613,7 +3880,13 @@ bool wxRichTextBuffer::LoadFile(const wxString& filename, int type)
 {
     wxRichTextFileHandler* handler = FindHandlerFilenameOrType(filename, type);
     if (handler)
 {
     wxRichTextFileHandler* handler = FindHandlerFilenameOrType(filename, type);
     if (handler)
-        return handler->LoadFile(this, filename);
+    {
+        SetDefaultStyle(wxTextAttrEx());
+
+        bool success = handler->LoadFile(this, filename);
+        Invalidate(wxRICHTEXT_ALL);
+        return success;
+    }
     else
         return false;
 }
     else
         return false;
 }
@@ -3633,7 +3906,12 @@ bool wxRichTextBuffer::LoadFile(wxInputStream& stream, int type)
 {
     wxRichTextFileHandler* handler = FindHandler(type);
     if (handler)
 {
     wxRichTextFileHandler* handler = FindHandler(type);
     if (handler)
-        return handler->LoadFile(this, stream);
+    {
+        SetDefaultStyle(wxTextAttrEx());
+        bool success = handler->LoadFile(this, stream);
+        Invalidate(wxRICHTEXT_ALL);
+        return success;
+    }
     else
         return false;
 }
     else
         return false;
 }
@@ -3652,12 +3930,16 @@ bool wxRichTextBuffer::SaveFile(wxOutputStream& stream, int type)
 bool wxRichTextBuffer::CopyToClipboard(const wxRichTextRange& range)
 {
     bool success = false;
 bool wxRichTextBuffer::CopyToClipboard(const wxRichTextRange& range)
 {
     bool success = false;
+#if wxUSE_CLIPBOARD && wxUSE_DATAOBJ
     wxString text = GetTextForRange(range);
     wxString text = GetTextForRange(range);
-    if (wxTheClipboard->Open())
-    {        
+    if (!wxTheClipboard->IsOpened() && wxTheClipboard->Open())
+    {
         success = wxTheClipboard->SetData(new wxTextDataObject(text));
         wxTheClipboard->Close();
     }
         success = wxTheClipboard->SetData(new wxTextDataObject(text));
         wxTheClipboard->Close();
     }
+#else
+    wxUnusedVar(range);
+#endif
     return success;
 }
 
     return success;
 }
 
@@ -3665,6 +3947,7 @@ bool wxRichTextBuffer::CopyToClipboard(const wxRichTextRange& range)
 bool wxRichTextBuffer::PasteFromClipboard(long position)
 {
     bool success = false;
 bool wxRichTextBuffer::PasteFromClipboard(long position)
 {
     bool success = false;
+#if wxUSE_CLIPBOARD && wxUSE_DATAOBJ
     if (CanPasteFromClipboard())
     {
         if (wxTheClipboard->Open())
     if (CanPasteFromClipboard())
     {
         if (wxTheClipboard->Open())
@@ -3674,9 +3957,10 @@ bool wxRichTextBuffer::PasteFromClipboard(long position)
                 wxTextDataObject data;
                 wxTheClipboard->GetData(data);
                 wxString text(data.GetText());
                 wxTextDataObject data;
                 wxTheClipboard->GetData(data);
                 wxString text(data.GetText());
+                text.Replace(_T("\r\n"), _T("\n"));
 
                 InsertTextWithUndo(position+1, text, GetRichTextCtrl());
 
                 InsertTextWithUndo(position+1, text, GetRichTextCtrl());
-                
+
                 success = true;
             }
             else if (wxTheClipboard->IsSupported(wxDF_BITMAP))
                 success = true;
             }
             else if (wxTheClipboard->IsSupported(wxDF_BITMAP))
@@ -3687,17 +3971,17 @@ bool wxRichTextBuffer::PasteFromClipboard(long position)
                 wxImage image(bitmap.ConvertToImage());
 
                 wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Image"), wxRICHTEXT_INSERT, this, GetRichTextCtrl(), false);
                 wxImage image(bitmap.ConvertToImage());
 
                 wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Image"), wxRICHTEXT_INSERT, this, GetRichTextCtrl(), false);
-                
+
                 action->GetNewParagraphs().AddImage(image);
 
                 if (action->GetNewParagraphs().GetChildCount() == 1)
                     action->GetNewParagraphs().SetPartialParagraph(true);
                 action->GetNewParagraphs().AddImage(image);
 
                 if (action->GetNewParagraphs().GetChildCount() == 1)
                     action->GetNewParagraphs().SetPartialParagraph(true);
-                
+
                 action->SetPosition(position);
                 action->SetPosition(position);
-                
+
                 // Set the range we'll need to delete in Undo
                 action->SetRange(wxRichTextRange(position, position));
                 // Set the range we'll need to delete in Undo
                 action->SetRange(wxRichTextRange(position, position));
-                
+
                 SubmitAction(action);
 
                 success = true;
                 SubmitAction(action);
 
                 success = true;
@@ -3705,21 +3989,26 @@ bool wxRichTextBuffer::PasteFromClipboard(long position)
             wxTheClipboard->Close();
         }
     }
             wxTheClipboard->Close();
         }
     }
+#else
+    wxUnusedVar(position);
+#endif
     return success;
 }
 
 /// Can we paste from the clipboard?
 bool wxRichTextBuffer::CanPasteFromClipboard() const
 {
     return success;
 }
 
 /// Can we paste from the clipboard?
 bool wxRichTextBuffer::CanPasteFromClipboard() const
 {
-    bool canPaste = FALSE;
-    if (wxTheClipboard->Open())
+    bool canPaste = false;
+#if wxUSE_CLIPBOARD && wxUSE_DATAOBJ
+    if (!wxTheClipboard->IsOpened() && wxTheClipboard->Open())
     {
         if (wxTheClipboard->IsSupported(wxDF_TEXT) || wxTheClipboard->IsSupported(wxDF_BITMAP))
         {
     {
         if (wxTheClipboard->IsSupported(wxDF_TEXT) || wxTheClipboard->IsSupported(wxDF_BITMAP))
         {
-            canPaste = TRUE;
+            canPaste = true;
         }
         wxTheClipboard->Close();
     }
         }
         wxTheClipboard->Close();
     }
+#endif
     return canPaste;
 }
 
     return canPaste;
 }
 
@@ -3759,12 +4048,12 @@ IMPLEMENT_DYNAMIC_CLASS(wxRichTextModule, wxModule)
  */
 
 wxRichTextCommand::wxRichTextCommand(const wxString& name, wxRichTextCommandId id, wxRichTextBuffer* buffer,
  */
 
 wxRichTextCommand::wxRichTextCommand(const wxString& name, wxRichTextCommandId id, wxRichTextBuffer* buffer,
-                                     wxRichTextCtrl* ctrl, bool ignoreFirstTime): wxCommand(TRUE, name)
+                                     wxRichTextCtrl* ctrl, bool ignoreFirstTime): wxCommand(true, name)
 {
     /* wxRichTextAction* action = */ new wxRichTextAction(this, name, id, buffer, ctrl, ignoreFirstTime);
 }
 
 {
     /* wxRichTextAction* action = */ new wxRichTextAction(this, name, id, buffer, ctrl, ignoreFirstTime);
 }
 
-wxRichTextCommand::wxRichTextCommand(const wxString& name): wxCommand(TRUE, name)
+wxRichTextCommand::wxRichTextCommand(const wxString& name): wxCommand(true, name)
 {
 }
 
 {
 }
 
@@ -3781,7 +4070,7 @@ void wxRichTextCommand::AddAction(wxRichTextAction* action)
 
 bool wxRichTextCommand::Do()
 {
 
 bool wxRichTextCommand::Do()
 {
-    for (wxNode* node = m_actions.GetFirst(); node; node = node->GetNext())
+    for (wxList::compatibility_iterator node = m_actions.GetFirst(); node; node = node->GetNext())
     {
         wxRichTextAction* action = (wxRichTextAction*) node->GetData();
         action->Do();
     {
         wxRichTextAction* action = (wxRichTextAction*) node->GetData();
         action->Do();
@@ -3792,7 +4081,7 @@ bool wxRichTextCommand::Do()
 
 bool wxRichTextCommand::Undo()
 {
 
 bool wxRichTextCommand::Undo()
 {
-    for (wxNode* node = m_actions.GetLast(); node; node = node->GetPrevious())
+    for (wxList::compatibility_iterator node = m_actions.GetLast(); node; node = node->GetPrevious())
     {
         wxRichTextAction* action = (wxRichTextAction*) node->GetData();
         action->Undo();
     {
         wxRichTextAction* action = (wxRichTextAction*) node->GetData();
         action->Undo();
@@ -3840,6 +4129,7 @@ bool wxRichTextAction::Do()
         {
             m_buffer->InsertFragment(GetPosition(), m_newParagraphs);
             m_buffer->UpdateRanges();
         {
             m_buffer->InsertFragment(GetPosition(), m_newParagraphs);
             m_buffer->UpdateRanges();
+            m_buffer->Invalidate(GetRange());
 
             long newCaretPosition = GetPosition() + m_newParagraphs.GetRange().GetLength() - 1;
             if (m_newParagraphs.GetPartialParagraph())
 
             long newCaretPosition = GetPosition() + m_newParagraphs.GetRange().GetLength() - 1;
             if (m_newParagraphs.GetPartialParagraph())
@@ -3853,6 +4143,7 @@ bool wxRichTextAction::Do()
         {
             m_buffer->DeleteRange(GetRange());
             m_buffer->UpdateRanges();
         {
             m_buffer->DeleteRange(GetRange());
             m_buffer->UpdateRanges();
+            m_buffer->Invalidate(wxRichTextRange(GetRange().GetStart(), GetRange().GetStart()));
 
             UpdateAppearance(GetRange().GetStart()-1, true /* send update event */);
 
 
             UpdateAppearance(GetRange().GetStart()-1, true /* send update event */);
 
@@ -3861,6 +4152,7 @@ bool wxRichTextAction::Do()
     case wxRICHTEXT_CHANGE_STYLE:
         {
             ApplyParagraphs(GetNewParagraphs());
     case wxRICHTEXT_CHANGE_STYLE:
         {
             ApplyParagraphs(GetNewParagraphs());
+            m_buffer->Invalidate(GetRange());
 
             UpdateAppearance(GetPosition());
 
 
             UpdateAppearance(GetPosition());
 
@@ -3883,6 +4175,7 @@ bool wxRichTextAction::Undo()
         {
             m_buffer->DeleteRange(GetRange());
             m_buffer->UpdateRanges();
         {
             m_buffer->DeleteRange(GetRange());
             m_buffer->UpdateRanges();
+            m_buffer->Invalidate(wxRichTextRange(GetRange().GetStart(), GetRange().GetStart()));
 
             long newCaretPosition = GetPosition() - 1;
             // if (m_newParagraphs.GetPartialParagraph())
 
             long newCaretPosition = GetPosition() - 1;
             // if (m_newParagraphs.GetPartialParagraph())
@@ -3896,6 +4189,7 @@ bool wxRichTextAction::Undo()
         {
             m_buffer->InsertFragment(GetRange().GetStart(), m_oldParagraphs);
             m_buffer->UpdateRanges();
         {
             m_buffer->InsertFragment(GetRange().GetStart(), m_oldParagraphs);
             m_buffer->UpdateRanges();
+            m_buffer->Invalidate(GetRange());
 
             UpdateAppearance(GetPosition(), true /* send update event */);
 
 
             UpdateAppearance(GetPosition(), true /* send update event */);
 
@@ -3904,6 +4198,7 @@ bool wxRichTextAction::Undo()
     case wxRICHTEXT_CHANGE_STYLE:
         {
             ApplyParagraphs(GetOldParagraphs());
     case wxRICHTEXT_CHANGE_STYLE:
         {
             ApplyParagraphs(GetOldParagraphs());
+            m_buffer->Invalidate(GetRange());
 
             UpdateAppearance(GetPosition());
 
 
             UpdateAppearance(GetPosition());
 
@@ -3924,14 +4219,14 @@ void wxRichTextAction::UpdateAppearance(long caretPosition, bool sendUpdateEvent
         m_ctrl->SetCaretPosition(caretPosition);
         if (!m_ctrl->IsFrozen())
         {
         m_ctrl->SetCaretPosition(caretPosition);
         if (!m_ctrl->IsFrozen())
         {
-            m_ctrl->Layout();
+            m_ctrl->LayoutContent();
             m_ctrl->PositionCaret();
             m_ctrl->PositionCaret();
-            m_ctrl->Refresh();
+            m_ctrl->Refresh(false);
 
             if (sendUpdateEvent)
                 m_ctrl->SendUpdateEvent();
         }
 
             if (sendUpdateEvent)
                 m_ctrl->SendUpdateEvent();
         }
-    }    
+    }
 }
 
 /// Replace the buffer paragraphs with the new ones.
 }
 
 /// Replace the buffer paragraphs with the new ones.
@@ -4052,7 +4347,7 @@ bool wxRichTextImage::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichT
 }
 
 /// Lay the item out
 }
 
 /// Lay the item out
-bool wxRichTextImage::Layout(wxDC& WXUNUSED(dc), const wxRect& rect, const wxRichTextRange& WXUNUSED(affected), int WXUNUSED(style))
+bool wxRichTextImage::Layout(wxDC& WXUNUSED(dc), const wxRect& rect, int WXUNUSED(style))
 {
     if (!m_image.Ok())
         LoadFromBlock();
 {
     if (!m_image.Ok())
         LoadFromBlock();
@@ -4068,7 +4363,7 @@ bool wxRichTextImage::Layout(wxDC& WXUNUSED(dc), const wxRect& rect, const wxRic
 
 /// Get/set the object size for the given range. Returns false if the range
 /// is invalid for this object.
 
 /// Get/set the object size for the given range. Returns false if the range
 /// is invalid for this object.
-bool wxRichTextImage::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& WXUNUSED(descent), wxDC& WXUNUSED(dc), int WXUNUSED(flags)) const
+bool wxRichTextImage::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& WXUNUSED(descent), wxDC& WXUNUSED(dc), int WXUNUSED(flags), wxPoint WXUNUSED(position)) const
 {
     if (!range.IsWithin(GetRange()))
         return false;
 {
     if (!range.IsWithin(GetRange()))
         return false;
@@ -4182,23 +4477,23 @@ bool wxTextAttrEqPartial(const wxTextAttrEx& attr1, const wxTextAttrEx& attr2, i
         (attr1.GetRightIndent() != attr2.GetRightIndent()))
         return false;
 
         (attr1.GetRightIndent() != attr2.GetRightIndent()))
         return false;
 
-    if ((flags && wxTEXT_ATTR_PARA_SPACING_AFTER) &&
+    if ((flags & wxTEXT_ATTR_PARA_SPACING_AFTER) &&
         (attr1.GetParagraphSpacingAfter() != attr2.GetParagraphSpacingAfter()))
         return false;
 
         (attr1.GetParagraphSpacingAfter() != attr2.GetParagraphSpacingAfter()))
         return false;
 
-    if ((flags && wxTEXT_ATTR_PARA_SPACING_BEFORE) &&
+    if ((flags & wxTEXT_ATTR_PARA_SPACING_BEFORE) &&
         (attr1.GetParagraphSpacingBefore() != attr2.GetParagraphSpacingBefore()))
         return false;
 
         (attr1.GetParagraphSpacingBefore() != attr2.GetParagraphSpacingBefore()))
         return false;
 
-    if ((flags && wxTEXT_ATTR_LINE_SPACING) &&
+    if ((flags & wxTEXT_ATTR_LINE_SPACING) &&
         (attr1.GetLineSpacing() != attr2.GetLineSpacing()))
         return false;
 
         (attr1.GetLineSpacing() != attr2.GetLineSpacing()))
         return false;
 
-    if ((flags && wxTEXT_ATTR_CHARACTER_STYLE_NAME) &&
+    if ((flags & wxTEXT_ATTR_CHARACTER_STYLE_NAME) &&
         (attr1.GetCharacterStyleName() != attr2.GetCharacterStyleName()))
         return false;
 
         (attr1.GetCharacterStyleName() != attr2.GetCharacterStyleName()))
         return false;
 
-    if ((flags && wxTEXT_ATTR_PARAGRAPH_STYLE_NAME) &&
+    if ((flags & wxTEXT_ATTR_PARAGRAPH_STYLE_NAME) &&
         (attr1.GetParagraphStyleName() != attr2.GetParagraphStyleName()))
         return false;
 
         (attr1.GetParagraphStyleName() != attr2.GetParagraphStyleName()))
         return false;
 
@@ -4264,23 +4559,23 @@ bool wxTextAttrEqPartial(const wxTextAttrEx& attr1, const wxRichTextAttr& attr2,
         (attr1.GetRightIndent() != attr2.GetRightIndent()))
         return false;
 
         (attr1.GetRightIndent() != attr2.GetRightIndent()))
         return false;
 
-    if ((flags && wxTEXT_ATTR_PARA_SPACING_AFTER) &&
+    if ((flags & wxTEXT_ATTR_PARA_SPACING_AFTER) &&
         (attr1.GetParagraphSpacingAfter() != attr2.GetParagraphSpacingAfter()))
         return false;
 
         (attr1.GetParagraphSpacingAfter() != attr2.GetParagraphSpacingAfter()))
         return false;
 
-    if ((flags && wxTEXT_ATTR_PARA_SPACING_BEFORE) &&
+    if ((flags & wxTEXT_ATTR_PARA_SPACING_BEFORE) &&
         (attr1.GetParagraphSpacingBefore() != attr2.GetParagraphSpacingBefore()))
         return false;
 
         (attr1.GetParagraphSpacingBefore() != attr2.GetParagraphSpacingBefore()))
         return false;
 
-    if ((flags && wxTEXT_ATTR_LINE_SPACING) &&
+    if ((flags & wxTEXT_ATTR_LINE_SPACING) &&
         (attr1.GetLineSpacing() != attr2.GetLineSpacing()))
         return false;
 
         (attr1.GetLineSpacing() != attr2.GetLineSpacing()))
         return false;
 
-    if ((flags && wxTEXT_ATTR_CHARACTER_STYLE_NAME) &&
+    if ((flags & wxTEXT_ATTR_CHARACTER_STYLE_NAME) &&
         (attr1.GetCharacterStyleName() != attr2.GetCharacterStyleName()))
         return false;
 
         (attr1.GetCharacterStyleName() != attr2.GetCharacterStyleName()))
         return false;
 
-    if ((flags && wxTEXT_ATTR_PARAGRAPH_STYLE_NAME) &&
+    if ((flags & wxTEXT_ATTR_PARAGRAPH_STYLE_NAME) &&
         (attr1.GetParagraphStyleName() != attr2.GetParagraphStyleName()))
         return false;
 
         (attr1.GetParagraphStyleName() != attr2.GetParagraphStyleName()))
         return false;
 
@@ -4390,7 +4685,7 @@ bool wxRichTextApplyStyle(wxRichTextAttr& destStyle, const wxTextAttrEx& style)
 
 bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style)
 {
 
 bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style)
 {
-    
+
     // Whole font. Avoiding setting individual attributes if possible, since
     // it recreates the font each time.
     if ((style.GetFlags() & (wxTEXT_ATTR_FONT)) == (wxTEXT_ATTR_FONT))
     // Whole font. Avoiding setting individual attributes if possible, since
     // it recreates the font each time.
     if ((style.GetFlags() & (wxTEXT_ATTR_FONT)) == (wxTEXT_ATTR_FONT))
@@ -4404,16 +4699,16 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style)
 
         if (style.GetFlags() & wxTEXT_ATTR_FONT_FACE)
             font.SetFaceName(style.GetFontFaceName());
 
         if (style.GetFlags() & wxTEXT_ATTR_FONT_FACE)
             font.SetFaceName(style.GetFontFaceName());
-        
+
         if (style.GetFlags() & wxTEXT_ATTR_FONT_SIZE)
             font.SetPointSize(style.GetFontSize());
         if (style.GetFlags() & wxTEXT_ATTR_FONT_SIZE)
             font.SetPointSize(style.GetFontSize());
-        
+
         if (style.GetFlags() & wxTEXT_ATTR_FONT_ITALIC)
             font.SetStyle(style.GetFontStyle());
         if (style.GetFlags() & wxTEXT_ATTR_FONT_ITALIC)
             font.SetStyle(style.GetFontStyle());
-        
+
         if (style.GetFlags() & wxTEXT_ATTR_FONT_WEIGHT)
             font.SetWeight(style.GetFontWeight());
         if (style.GetFlags() & wxTEXT_ATTR_FONT_WEIGHT)
             font.SetWeight(style.GetFontWeight());
-        
+
         if (style.GetFlags() & wxTEXT_ATTR_FONT_UNDERLINE)
             font.SetUnderlined(style.GetFontUnderlined());
 
         if (style.GetFlags() & wxTEXT_ATTR_FONT_UNDERLINE)
             font.SetUnderlined(style.GetFontUnderlined());
 
@@ -4599,6 +4894,9 @@ void wxRichTextAttr::CopyTo(wxTextAttrEx& attr) const
 wxFont wxRichTextAttr::CreateFont() const
 {
     wxFont font(m_fontSize, wxDEFAULT, m_fontStyle, m_fontWeight, m_fontUnderlined, m_fontFaceName);
 wxFont wxRichTextAttr::CreateFont() const
 {
     wxFont font(m_fontSize, wxDEFAULT, m_fontStyle, m_fontWeight, m_fontUnderlined, m_fontFaceName);
+#ifdef __WXMAC__
+    font.SetNoAntiAliasing(true);
+#endif
     return font;
 }
 
     return font;
 }
 
@@ -4617,6 +4915,94 @@ bool wxRichTextAttr::GetFontAttributes(const wxFont& font)
     return true;
 }
 
     return true;
 }
 
+wxRichTextAttr wxRichTextAttr::Combine(const wxRichTextAttr& attr,
+                               const wxRichTextAttr& attrDef,
+                               const wxTextCtrlBase *text)
+{
+    wxColour colFg = attr.GetTextColour();
+    if ( !colFg.Ok() )
+    {
+        colFg = attrDef.GetTextColour();
+
+        if ( text && !colFg.Ok() )
+            colFg = text->GetForegroundColour();
+    }
+
+    wxColour colBg = attr.GetBackgroundColour();
+    if ( !colBg.Ok() )
+    {
+        colBg = attrDef.GetBackgroundColour();
+
+        if ( text && !colBg.Ok() )
+            colBg = text->GetBackgroundColour();
+    }
+
+    wxRichTextAttr newAttr(colFg, colBg);
+
+    if (attr.HasWeight())
+        newAttr.SetFontWeight(attr.GetFontWeight());
+
+    if (attr.HasSize())
+        newAttr.SetFontSize(attr.GetFontSize());
+
+    if (attr.HasItalic())
+        newAttr.SetFontStyle(attr.GetFontStyle());
+
+    if (attr.HasUnderlined())
+        newAttr.SetFontUnderlined(attr.GetFontUnderlined());
+
+    if (attr.HasFaceName())
+        newAttr.SetFontFaceName(attr.GetFontFaceName());
+
+    if (attr.HasAlignment())
+        newAttr.SetAlignment(attr.GetAlignment());
+    else if (attrDef.HasAlignment())
+        newAttr.SetAlignment(attrDef.GetAlignment());
+
+    if (attr.HasTabs())
+        newAttr.SetTabs(attr.GetTabs());
+    else if (attrDef.HasTabs())
+        newAttr.SetTabs(attrDef.GetTabs());
+
+    if (attr.HasLeftIndent())
+        newAttr.SetLeftIndent(attr.GetLeftIndent(), attr.GetLeftSubIndent());
+    else if (attrDef.HasLeftIndent())
+        newAttr.SetLeftIndent(attrDef.GetLeftIndent(), attr.GetLeftSubIndent());
+
+    if (attr.HasRightIndent())
+        newAttr.SetRightIndent(attr.GetRightIndent());
+    else if (attrDef.HasRightIndent())
+        newAttr.SetRightIndent(attrDef.GetRightIndent());
+
+    // NEW ATTRIBUTES
+
+    if (attr.HasParagraphSpacingAfter())
+        newAttr.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter());
+
+    if (attr.HasParagraphSpacingBefore())
+        newAttr.SetParagraphSpacingBefore(attr.GetParagraphSpacingBefore());
+
+    if (attr.HasLineSpacing())
+        newAttr.SetLineSpacing(attr.GetLineSpacing());
+
+    if (attr.HasCharacterStyleName())
+        newAttr.SetCharacterStyleName(attr.GetCharacterStyleName());
+
+    if (attr.HasParagraphStyleName())
+        newAttr.SetParagraphStyleName(attr.GetParagraphStyleName());
+
+    if (attr.HasBulletStyle())
+        newAttr.SetBulletStyle(attr.GetBulletStyle());
+
+    if (attr.HasBulletNumber())
+        newAttr.SetBulletNumber(attr.GetBulletNumber());
+
+    if (attr.HasBulletSymbol())
+        newAttr.SetBulletSymbol(attr.GetBulletSymbol());
+
+    return newAttr;
+}
+
 /*!
  * wxTextAttrEx is an extended version of wxTextAttr with more paragraph attributes.
  */
 /*!
  * wxTextAttrEx is an extended version of wxTextAttr with more paragraph attributes.
  */
@@ -4666,6 +5052,146 @@ void wxTextAttrEx::operator= (const wxTextAttr& attr)
     wxTextAttr::operator= (attr);
 }
 
     wxTextAttr::operator= (attr);
 }
 
+wxTextAttrEx wxTextAttrEx::CombineEx(const wxTextAttrEx& attr,
+                               const wxTextAttrEx& attrDef,
+                               const wxTextCtrlBase *text)
+{
+    wxTextAttrEx newAttr;
+
+    // If attr specifies the complete font, just use that font, overriding all
+    // default font attributes.
+    if ((attr.GetFlags() & wxTEXT_ATTR_FONT) == wxTEXT_ATTR_FONT)
+        newAttr.SetFont(attr.GetFont());
+    else
+    {
+        // First find the basic, default font
+        long flags = 0;
+
+        wxFont font;
+        if (attrDef.HasFont())
+        {
+            flags = (attrDef.GetFlags() & wxTEXT_ATTR_FONT);
+            font = attrDef.GetFont();
+        }
+        else
+        {
+            if (text)
+                font = text->GetFont();
+
+            // We leave flags at 0 because no font attributes have been specified yet
+        }
+        if (!font.Ok())
+            font = *wxNORMAL_FONT;
+
+        // Otherwise, if there are font attributes in attr, apply them
+        if (attr.HasFont())
+        {
+            if (attr.HasSize())
+            {
+                flags |= wxTEXT_ATTR_FONT_SIZE;
+                font.SetPointSize(attr.GetFont().GetPointSize());
+            }
+            if (attr.HasItalic())
+            {
+                flags |= wxTEXT_ATTR_FONT_ITALIC;;
+                font.SetStyle(attr.GetFont().GetStyle());
+            }
+            if (attr.HasWeight())
+            {
+                flags |= wxTEXT_ATTR_FONT_WEIGHT;
+                font.SetWeight(attr.GetFont().GetWeight());
+            }
+            if (attr.HasFaceName())
+            {
+                flags |= wxTEXT_ATTR_FONT_FACE;
+                font.SetFaceName(attr.GetFont().GetFaceName());
+            }
+            if (attr.HasUnderlined())
+            {
+                flags |= wxTEXT_ATTR_FONT_UNDERLINE;
+                font.SetUnderlined(attr.GetFont().GetUnderlined());
+            }
+            newAttr.SetFont(font);
+            newAttr.SetFlags(newAttr.GetFlags()|flags);
+        }
+    }
+
+    // TODO: should really check we are specifying these in the flags,
+    // before setting them, as per above; or we will set them willy-nilly.
+    // However, we should also check whether this is the intention
+    // as per wxTextAttr::Combine, i.e. always to have valid colours
+    // in the style.
+    wxColour colFg = attr.GetTextColour();
+    if ( !colFg.Ok() )
+    {
+        colFg = attrDef.GetTextColour();
+
+        if ( text && !colFg.Ok() )
+            colFg = text->GetForegroundColour();
+    }
+
+    wxColour colBg = attr.GetBackgroundColour();
+    if ( !colBg.Ok() )
+    {
+        colBg = attrDef.GetBackgroundColour();
+
+        if ( text && !colBg.Ok() )
+            colBg = text->GetBackgroundColour();
+    }
+
+    newAttr.SetTextColour(colFg);
+    newAttr.SetBackgroundColour(colBg);
+
+    if (attr.HasAlignment())
+        newAttr.SetAlignment(attr.GetAlignment());
+    else if (attrDef.HasAlignment())
+        newAttr.SetAlignment(attrDef.GetAlignment());
+
+    if (attr.HasTabs())
+        newAttr.SetTabs(attr.GetTabs());
+    else if (attrDef.HasTabs())
+        newAttr.SetTabs(attrDef.GetTabs());
+
+    if (attr.HasLeftIndent())
+        newAttr.SetLeftIndent(attr.GetLeftIndent(), attr.GetLeftSubIndent());
+    else if (attrDef.HasLeftIndent())
+        newAttr.SetLeftIndent(attrDef.GetLeftIndent(), attr.GetLeftSubIndent());
+
+    if (attr.HasRightIndent())
+        newAttr.SetRightIndent(attr.GetRightIndent());
+    else if (attrDef.HasRightIndent())
+        newAttr.SetRightIndent(attrDef.GetRightIndent());
+
+    // NEW ATTRIBUTES
+
+    if (attr.HasParagraphSpacingAfter())
+        newAttr.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter());
+
+    if (attr.HasParagraphSpacingBefore())
+        newAttr.SetParagraphSpacingBefore(attr.GetParagraphSpacingBefore());
+
+    if (attr.HasLineSpacing())
+        newAttr.SetLineSpacing(attr.GetLineSpacing());
+
+    if (attr.HasCharacterStyleName())
+        newAttr.SetCharacterStyleName(attr.GetCharacterStyleName());
+
+    if (attr.HasParagraphStyleName())
+        newAttr.SetParagraphStyleName(attr.GetParagraphStyleName());
+
+    if (attr.HasBulletStyle())
+        newAttr.SetBulletStyle(attr.GetBulletStyle());
+
+    if (attr.HasBulletNumber())
+        newAttr.SetBulletNumber(attr.GetBulletNumber());
+
+    if (attr.HasBulletSymbol())
+        newAttr.SetBulletSymbol(attr.GetBulletSymbol());
+
+    return newAttr;
+}
+
+
 /*!
  * wxRichTextFileHandler
  * Base class for file handlers
 /*!
  * wxRichTextFileHandler
  * Base class for file handlers
@@ -4673,13 +5199,14 @@ void wxTextAttrEx::operator= (const wxTextAttr& attr)
 
 IMPLEMENT_CLASS(wxRichTextFileHandler, wxObject)
 
 
 IMPLEMENT_CLASS(wxRichTextFileHandler, wxObject)
 
+#if wxUSE_STREAMS
 bool wxRichTextFileHandler::LoadFile(wxRichTextBuffer *buffer, const wxString& filename)
 {
     wxFFileInputStream stream(filename);
     if (stream.Ok())
         return LoadFile(buffer, stream);
 bool wxRichTextFileHandler::LoadFile(wxRichTextBuffer *buffer, const wxString& filename)
 {
     wxFFileInputStream stream(filename);
     if (stream.Ok())
         return LoadFile(buffer, stream);
-    else
-        return false;
+
+    return false;
 }
 
 bool wxRichTextFileHandler::SaveFile(wxRichTextBuffer *buffer, const wxString& filename)
 }
 
 bool wxRichTextFileHandler::SaveFile(wxRichTextBuffer *buffer, const wxString& filename)
@@ -4687,9 +5214,10 @@ bool wxRichTextFileHandler::SaveFile(wxRichTextBuffer *buffer, const wxString& f
     wxFFileOutputStream stream(filename);
     if (stream.Ok())
         return SaveFile(buffer, stream);
     wxFFileOutputStream stream(filename);
     if (stream.Ok())
         return SaveFile(buffer, stream);
-    else
-        return false;
+
+    return false;
 }
 }
+#endif // wxUSE_STREAMS
 
 /// Can we handle this filename (if using files)? By default, checks the extension.
 bool wxRichTextFileHandler::CanHandle(const wxString& filename) const
 
 /// Can we handle this filename (if using files)? By default, checks the extension.
 bool wxRichTextFileHandler::CanHandle(const wxString& filename) const
@@ -4708,20 +5236,28 @@ bool wxRichTextFileHandler::CanHandle(const wxString& filename) const
 IMPLEMENT_CLASS(wxRichTextPlainTextHandler, wxRichTextFileHandler)
 
 #if wxUSE_STREAMS
 IMPLEMENT_CLASS(wxRichTextPlainTextHandler, wxRichTextFileHandler)
 
 #if wxUSE_STREAMS
-bool wxRichTextPlainTextHandler::LoadFile(wxRichTextBuffer *buffer, wxInputStream& stream)
+bool wxRichTextPlainTextHandler::DoLoadFile(wxRichTextBuffer *buffer, wxInputStream& stream)
 {
     if (!stream.IsOk())
         return false;
 
     wxString str;
 {
     if (!stream.IsOk())
         return false;
 
     wxString str;
-    int ch = 0;
+    int lastCh = 0;
 
     while (!stream.Eof())
     {
 
     while (!stream.Eof())
     {
-        ch = stream.GetC();
+        int ch = stream.GetC();
+
+        if (!stream.Eof())
+        {
+            if (ch == 10 && lastCh != 13)
+                str += wxT('\n');
 
 
-        if (ch > 0)
-            str += ch;
+            if (ch > 0 && ch != 10)
+                str += wxChar(ch);
+
+            lastCh = ch;
+        }
     }
 
     buffer->Clear();
     }
 
     buffer->Clear();
@@ -4732,7 +5268,7 @@ bool wxRichTextPlainTextHandler::LoadFile(wxRichTextBuffer *buffer, wxInputStrea
 
 }
 
 
 }
 
-bool wxRichTextPlainTextHandler::SaveFile(wxRichTextBuffer *buffer, wxOutputStream& stream)
+bool wxRichTextPlainTextHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream& stream)
 {
     if (!stream.IsOk())
         return false;
 {
     if (!stream.IsOk())
         return false;
@@ -4740,11 +5276,10 @@ bool wxRichTextPlainTextHandler::SaveFile(wxRichTextBuffer *buffer, wxOutputStre
     wxString text = buffer->GetText();
     wxCharBuffer buf = text.ToAscii();
 
     wxString text = buffer->GetText();
     wxCharBuffer buf = text.ToAscii();
 
-    stream.Write((const char*) buf, text.Length());
+    stream.Write((const char*) buf, text.length());
     return true;
 }
     return true;
 }
-
-#endif
+#endif // wxUSE_STREAMS
 
 /*
  * Stores information about an image, in binary in-memory form
 
 /*
  * Stores information about an image, in binary in-memory form
@@ -4779,8 +5314,7 @@ void wxRichTextImageBlock::Init()
 
 void wxRichTextImageBlock::Clear()
 {
 
 void wxRichTextImageBlock::Clear()
 {
-    if (m_data)
-        delete m_data;
+    delete[] m_data;
     m_data = NULL;
     m_dataSize = 0;
     m_imageType = -1;
     m_data = NULL;
     m_dataSize = 0;
     m_imageType = -1;
@@ -4798,10 +5332,10 @@ bool wxRichTextImageBlock::MakeImageBlock(const wxString& filename, int imageTyp
     m_imageType = imageType;
 
     wxString filenameToRead(filename);
     m_imageType = imageType;
 
     wxString filenameToRead(filename);
-    bool removeFile = FALSE;
+    bool removeFile = false;
 
     if (imageType == -1)
 
     if (imageType == -1)
-        return FALSE; // Could not determine image type
+        return false; // Could not determine image type
 
     if ((imageType != wxBITMAP_TYPE_JPEG) && convertToJPEG)
     {
 
     if ((imageType != wxBITMAP_TYPE_JPEG) && convertToJPEG)
     {
@@ -4814,13 +5348,13 @@ bool wxRichTextImageBlock::MakeImageBlock(const wxString& filename, int imageTyp
 
         image.SaveFile(tempFile, wxBITMAP_TYPE_JPEG);
         filenameToRead = tempFile;
 
         image.SaveFile(tempFile, wxBITMAP_TYPE_JPEG);
         filenameToRead = tempFile;
-        removeFile = TRUE;
+        removeFile = true;
 
         m_imageType = wxBITMAP_TYPE_JPEG;
     }
     wxFile file;
     if (!file.Open(filenameToRead))
 
         m_imageType = wxBITMAP_TYPE_JPEG;
     }
     wxFile file;
     if (!file.Open(filenameToRead))
-        return FALSE;
+        return false;
 
     m_dataSize = (size_t) file.Length();
     file.Close();
 
     m_dataSize = (size_t) file.Length();
     file.Close();
@@ -4843,24 +5377,24 @@ bool wxRichTextImageBlock::MakeImageBlock(wxImage& image, int imageType, int qua
     image.SetOption(wxT("quality"), quality);
 
     if (imageType == -1)
     image.SetOption(wxT("quality"), quality);
 
     if (imageType == -1)
-        return FALSE; // Could not determine image type
+        return false; // Could not determine image type
 
     wxString tempFile;
     bool success = wxGetTempFileName(_("image"), tempFile) ;
 
     wxString tempFile;
     bool success = wxGetTempFileName(_("image"), tempFile) ;
-    
+
     wxASSERT(success);
     wxUnusedVar(success);
     wxASSERT(success);
     wxUnusedVar(success);
-    
+
     if (!image.SaveFile(tempFile, m_imageType))
     {
         if (wxFileExists(tempFile))
             wxRemoveFile(tempFile);
     if (!image.SaveFile(tempFile, m_imageType))
     {
         if (wxFileExists(tempFile))
             wxRemoveFile(tempFile);
-        return FALSE;
+        return false;
     }
 
     wxFile file;
     if (!file.Open(tempFile))
     }
 
     wxFile file;
     if (!file.Open(tempFile))
-        return FALSE;
+        return false;
 
     m_dataSize = (size_t) file.Length();
     file.Close();
 
     m_dataSize = (size_t) file.Length();
     file.Close();
@@ -4909,7 +5443,7 @@ void wxRichTextImageBlock::operator=(const wxRichTextImageBlock& block)
 bool wxRichTextImageBlock::Load(wxImage& image)
 {
     if (!m_data)
 bool wxRichTextImageBlock::Load(wxImage& image)
 {
     if (!m_data)
-        return FALSE;
+        return false;
 
     // Read in the image.
 #if 1
 
     // Read in the image.
 #if 1
@@ -4922,7 +5456,7 @@ bool wxRichTextImageBlock::Load(wxImage& image)
 
     if (!WriteBlock(tempFile, m_data, m_dataSize))
     {
 
     if (!WriteBlock(tempFile, m_data, m_dataSize))
     {
-        return FALSE;
+        return false;
     }
     success = image.LoadFile(tempFile, GetImageType());
     wxRemoveFile(tempFile);
     }
     success = image.LoadFile(tempFile, GetImageType());
     wxRemoveFile(tempFile);
@@ -4940,8 +5474,8 @@ bool wxRichTextImageBlock::WriteHex(wxOutputStream& stream)
     {
         hex = wxDecToHex(m_data[i]);
         wxCharBuffer buf = hex.ToAscii();
     {
         hex = wxDecToHex(m_data[i]);
         wxCharBuffer buf = hex.ToAscii();
-        
-        stream.Write((const char*) buf, hex.Length());
+
+        stream.Write((const char*) buf, hex.length());
     }
 
     return true;
     }
 
     return true;
@@ -4963,7 +5497,7 @@ bool wxRichTextImageBlock::ReadHex(wxInputStream& stream, int length, int imageT
         str[0] = stream.GetC();
         str[1] = stream.GetC();
 
         str[0] = stream.GetC();
         str[1] = stream.GetC();
 
-        m_data[i] = wxHexToDec(str);
+        m_data[i] = (unsigned char)wxHexToDec(str);
     }
 
     m_dataSize = dataSize;
     }
 
     m_dataSize = dataSize;
@@ -5007,11 +5541,10 @@ bool wxRichTextImageBlock::WriteBlock(const wxString& filename, unsigned char* b
 {
     wxFileOutputStream outStream(filename);
     if (!outStream.Ok())
 {
     wxFileOutputStream outStream(filename);
     if (!outStream.Ok())
-        return FALSE;
+        return false;
 
     return WriteBlock(outStream, block, size);
 }
 
 #endif
     // wxUSE_RICHTEXT
 
     return WriteBlock(outStream, block, size);
 }
 
 #endif
     // wxUSE_RICHTEXT
-