]> git.saurik.com Git - wxWidgets.git/blobdiff - include/wx/richtext/richtextbuffer.h
adding backtab to exception list
[wxWidgets.git] / include / wx / richtext / richtextbuffer.h
index 8009ef9fe9adcbe6a53b131ff95059867a173822..afb4139089a2f51ec752e46ca3e637328e30a213 100644 (file)
@@ -22,9 +22,9 @@
 
   The top of the hierarchy is the buffer, a kind of wxRichTextParagraphLayoutBox.
   These boxes will allow flexible placement of text boxes on a page, but
 
   The top of the hierarchy is the buffer, a kind of wxRichTextParagraphLayoutBox.
   These boxes will allow flexible placement of text boxes on a page, but
-  for now there will be a single box representing the document,
-  and this box will a wxRichTextParagraphLayoutBox which contains further
-  wxRichTextParagraph objects, each of which can include text and images.
+  for now there is a single box representing the document, and this box is
+  a wxRichTextParagraphLayoutBox which contains further wxRichTextParagraph
+  objects, each of which can include text and images.
 
   Each object maintains a range (start and end position) measured
   from the start of the main parent box.
 
   Each object maintains a range (start and end position) measured
   from the start of the main parent box.
   a position relative to that text box. For now, we will not be dealing with
   embedded objects but it's something to bear in mind for later.
 
   a position relative to that text box. For now, we will not be dealing with
   embedded objects but it's something to bear in mind for later.
 
+  Note that internally, a range (5,5) represents a range of one character.
+  In the public wx[Rich]TextCtrl API, this would be passed to e.g. SetSelection
+  as (5,6). A paragraph with one character might have an internal range of (0, 1)
+  since the end of the paragraph takes up one position.
+
   Layout
   ======
 
   Layout
   ======
 
   in the vertical direction. The implementation of Layout can then
   cache the calculated size and position within the parent.
 
   in the vertical direction. The implementation of Layout can then
   cache the calculated size and position within the parent.
 
-  Note that position and size should be calculated separately, because
-  for example inserting a paragraph may result in the following paragraphs
-  moving down, but not changing in size.
-
-  Need to determine how objects specify their position. Absolute coordinates,
-  or relative to last object? May be hard to determine that. So should probably
-  be in absolute coordinates, in which case we'll need a Move virtual function
-  that allows quick movement of all elements without layout.
-
-  Let's work through a simple example of layout. Say we're laying out
-  a document with the buffer as the top box, with a wxRichTextParagraphLayoutBox
-  inside that that consists of wxRichTextParagraph objects.
-
-  We're in a mode whereby changes of window size change the width of the
-  page (useful for text editors, as opposed to word processors). The
-  window width is 600.
-
-  We pass (600, -1) to the top-level Layout (i.e. restrict size in horizontal
-  direction only). The wxRichTextBuffer box doesn't currently have
-  well-defined layout behaviour so we simply assume it has one child
-  that fills its parent (later we can define sizer-like box layout behaviour).
-  So it passes the same dimensions to the child, which is a wxRichTextParagraphLayoutBox.
-  This then looks at each child in turn (wxRichTextParagraph) and determines
-  the size the paragraph will take up, setting the cached size, and
-  splitting the paragraph into lines.
-
-  When the layout for one paragraph returns, the next paragraph is
-  fed the position of the previous, so it can position itself.
-
-  Each time Layout is called, the cached list of lines for each paragraph
-  is recreated, since it can change for example if the parent object width
-  changes.
-
-  Reporting size
-  ==============
-
-  Each object can report its size for a given range. It's important that
-  it can report a partial size, so that wrapping can be implemented,
-  hit test calculations performed, etc. So GetRangeSize must be implemented
-  for each object.
-
  */
 
 /*!
  */
 
 /*!
 #include "wx/image.h"
 #include "wx/cmdproc.h"
 #include "wx/txtstrm.h"
 #include "wx/image.h"
 #include "wx/cmdproc.h"
 #include "wx/txtstrm.h"
+#include "wx/variant.h"
+
+#if wxUSE_DATAOBJ
+#include "wx/dataobj.h"
+#endif
+
+// Compatibility
+//#define wxRichTextAttr wxTextAttr
+#define wxTextAttrEx wxTextAttr
+
+// Setting wxRICHTEXT_USE_OWN_CARET to 1 implements a
+// caret reliably without using wxClientDC in case there
+// are platform-specific problems with the generic caret.
+#if defined(__WXGTK__) || defined(__WXMAC__)
+#define wxRICHTEXT_USE_OWN_CARET 1
+#else
+#define wxRICHTEXT_USE_OWN_CARET 0
+#endif
+
+// Switch off for binary compatibility, on for faster drawing
+// Note: this seems to be buggy (overzealous use of extents) so
+// don't use for now
+#define wxRICHTEXT_USE_OPTIMIZED_LINE_DRAWING 0
+
+// The following two symbols determine whether an output implementation
+// is present. To switch the relevant one on, set wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT in
+// richtextxml.cpp. By default, the faster direct output implementation is used.
+
+// Include the wxXmlDocument implementation for output
+#define wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT 1
+
+// Include the faster, direct implementation for output
+#define wxRICHTEXT_HAVE_DIRECT_OUTPUT 1
 
 /*!
 
 /*!
- * File types
+ * Special characters
  */
 
  */
 
-#define wxRICHTEXT_TYPE_ANY             0
-#define wxRICHTEXT_TYPE_TEXT            1
-#define wxRICHTEXT_TYPE_XML             2
-#define wxRICHTEXT_TYPE_HTML            3
-#define wxRICHTEXT_TYPE_RTF             4
-#define wxRICHTEXT_TYPE_PDF             5
+extern WXDLLIMPEXP_RICHTEXT const wxChar wxRichTextLineBreakChar;
+
+/*!
+ * File types in wxRichText context.
+ */
+enum wxRichTextFileType
+{
+    wxRICHTEXT_TYPE_ANY = 0,
+    wxRICHTEXT_TYPE_TEXT,
+    wxRICHTEXT_TYPE_XML,
+    wxRICHTEXT_TYPE_HTML,
+    wxRICHTEXT_TYPE_RTF,
+    wxRICHTEXT_TYPE_PDF
+};
 
 /*!
  * Forward declarations
  */
 
 
 /*!
  * Forward declarations
  */
 
-class WXDLLIMPEXP_RICHTEXT wxRichTextCtrl;
-class WXDLLIMPEXP_RICHTEXT wxRichTextObject;
-class WXDLLIMPEXP_RICHTEXT wxRichTextCacheObject;
-class WXDLLIMPEXP_RICHTEXT wxRichTextObjectList;
-class WXDLLIMPEXP_RICHTEXT wxRichTextLine;
-class WXDLLIMPEXP_RICHTEXT wxRichTextParagraph;
-class WXDLLIMPEXP_RICHTEXT wxRichTextFragment;
-class WXDLLIMPEXP_RICHTEXT wxRichTextFileHandler;
-class WXDLLIMPEXP_RICHTEXT wxRichTextStyleSheet;
-class WXDLLIMPEXP_RICHTEXT wxTextAttrEx;
+class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextCtrl;
+class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextObject;
+class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextImage;
+class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextCacheObject;
+class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextObjectList;
+class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextLine;
+class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextParagraph;
+class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextFileHandler;
+class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextStyleSheet;
+class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextListStyleDefinition;
+class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextEvent;
+class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextRenderer;
+class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextBuffer;
+class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextXMLHandler;
+class WXDLLIMPEXP_FWD_XML      wxXmlNode;
+class                          wxRichTextFloatCollector;
 
 /*!
  * Flags determining the available space, passed to Layout
 
 /*!
  * Flags determining the available space, passed to Layout
@@ -141,18 +152,35 @@ class WXDLLIMPEXP_RICHTEXT wxTextAttrEx;
 // the rect passed to Layout.
 #define wxRICHTEXT_LAYOUT_SPECIFIED_RECT 0x10
 
 // the rect passed to Layout.
 #define wxRICHTEXT_LAYOUT_SPECIFIED_RECT 0x10
 
+/*!
+ * Flags to pass to Draw
+ */
+
+// Ignore paragraph cache optimization, e.g. for printing purposes
+// where one line may be drawn higher (on the next page) compared
+// with the previous line
+#define wxRICHTEXT_DRAW_IGNORE_CACHE    0x01
+
 /*!
  * Flags returned from hit-testing
  */
 /*!
  * Flags returned from hit-testing
  */
+enum wxRichTextHitTestFlags
+{
+    // The point was not on this object
+    wxRICHTEXT_HITTEST_NONE =    0x01,
 
 
-// The point was not on this object
-#define wxRICHTEXT_HITTEST_NONE     0x01
-// The point was before the position returned from HitTest
-#define wxRICHTEXT_HITTEST_BEFORE   0x02
-// The point was after the position returned from HitTest
-#define wxRICHTEXT_HITTEST_AFTER    0x04
-// The point was on the position returned from HitTest
-#define wxRICHTEXT_HITTEST_ON       0x08
+    // The point was before the position returned from HitTest
+    wxRICHTEXT_HITTEST_BEFORE =  0x02,
+
+    // The point was after the position returned from HitTest
+    wxRICHTEXT_HITTEST_AFTER =   0x04,
+
+    // The point was on the position returned from HitTest
+    wxRICHTEXT_HITTEST_ON =      0x08,
+
+    // The point was on space outside content
+    wxRICHTEXT_HITTEST_OUTSIDE = 0x10
+};
 
 /*!
  * Flags for GetRangeSize
 
 /*!
  * Flags for GetRangeSize
@@ -160,46 +188,682 @@ class WXDLLIMPEXP_RICHTEXT wxTextAttrEx;
 
 #define wxRICHTEXT_FORMATTED        0x01
 #define wxRICHTEXT_UNFORMATTED      0x02
 
 #define wxRICHTEXT_FORMATTED        0x01
 #define wxRICHTEXT_UNFORMATTED      0x02
+#define wxRICHTEXT_CACHE_SIZE       0x04
+#define wxRICHTEXT_HEIGHT_ONLY      0x08
 
 /*!
 
 /*!
- * Extra formatting flags not in wxTextAttr
+ * Flags for SetStyle/SetListStyle
  */
 
  */
 
-#define wxTEXT_ATTR_PARA_SPACING_AFTER      0x00000800
-#define wxTEXT_ATTR_PARA_SPACING_BEFORE     0x00001000
-#define wxTEXT_ATTR_LINE_SPACING            0x00002000
-#define wxTEXT_ATTR_CHARACTER_STYLE_NAME    0x00004000
-#define wxTEXT_ATTR_PARAGRAPH_STYLE_NAME    0x00008000
-#define wxTEXT_ATTR_BULLET_STYLE            0x00010000
-#define wxTEXT_ATTR_BULLET_NUMBER           0x00020000
-#define wxTEXT_ATTR_BULLET_SYMBOL           0x00040000
+#define wxRICHTEXT_SETSTYLE_NONE            0x00
+
+// Specifies that this operation should be undoable
+#define wxRICHTEXT_SETSTYLE_WITH_UNDO       0x01
+
+// Specifies that the style should not be applied if the
+// combined style at this point is already the style in question.
+#define wxRICHTEXT_SETSTYLE_OPTIMIZE        0x02
+
+// Specifies that the style should only be applied to paragraphs,
+// and not the content. This allows content styling to be
+// preserved independently from that of e.g. a named paragraph style.
+#define wxRICHTEXT_SETSTYLE_PARAGRAPHS_ONLY 0x04
+
+// Specifies that the style should only be applied to characters,
+// and not the paragraph. This allows content styling to be
+// preserved independently from that of e.g. a named paragraph style.
+#define wxRICHTEXT_SETSTYLE_CHARACTERS_ONLY 0x08
+
+// For SetListStyle only: specifies starting from the given number, otherwise
+// deduces number from existing attributes
+#define wxRICHTEXT_SETSTYLE_RENUMBER        0x10
+
+// For SetListStyle only: specifies the list level for all paragraphs, otherwise
+// the current indentation will be used
+#define wxRICHTEXT_SETSTYLE_SPECIFY_LEVEL   0x20
+
+// Resets the existing style before applying the new style
+#define wxRICHTEXT_SETSTYLE_RESET           0x40
+
+// Removes the given style instead of applying it
+#define wxRICHTEXT_SETSTYLE_REMOVE          0x80
 
 /*!
 
 /*!
- * Styles for wxTextAttrEx::SetBulletStyle
+ * Flags for text insertion
  */
 
  */
 
-#define wxTEXT_ATTR_BULLET_STYLE_NONE           0x0000
-#define wxTEXT_ATTR_BULLET_STYLE_ARABIC         0x0001
-#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_UPPER  0x0002
-#define wxTEXT_ATTR_BULLET_STYLE_LETTERS_LOWER  0x0004
-#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_UPPER    0x0008
-#define wxTEXT_ATTR_BULLET_STYLE_ROMAN_LOWER    0x0010
-#define wxTEXT_ATTR_BULLET_STYLE_SYMBOL         0x0020
-#define wxTEXT_ATTR_BULLET_STYLE_BITMAP         0x0040
-#define wxTEXT_ATTR_BULLET_STYLE_PARENTHESES    0x0080
-#define wxTEXT_ATTR_BULLET_STYLE_PERIOD         0x0100
+#define wxRICHTEXT_INSERT_NONE                              0x00
+#define wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE     0x01
+#define wxRICHTEXT_INSERT_INTERACTIVE                       0x02
+
+// A special flag telling the buffer to keep the first paragraph style
+// as-is, when deleting a paragraph marker. In future we might pass a
+// flag to InsertFragment and DeleteRange to indicate the appropriate mode.
+#define wxTEXT_ATTR_KEEP_FIRST_PARA_STYLE   0x10000000
 
 /*!
 
 /*!
- * Line spacing values
+ * Default superscript/subscript font multiplication factor
  */
 
  */
 
-#define wxTEXT_ATTR_LINE_SPACING_NORMAL         10
-#define wxTEXT_ATTR_LINE_SPACING_HALF           15
-#define wxTEXT_ATTR_LINE_SPACING_TWICE          20
+#define wxSCRIPT_MUL_FACTOR             1.5
+
+typedef unsigned short wxTextAttrDimensionFlags;
+
+// Miscelaneous text box flags
+enum wxTextBoxAttrFlags
+{
+    wxTEXT_BOX_ATTR_FLOAT                   = 0x00000001,
+    wxTEXT_BOX_ATTR_CLEAR                   = 0x00000002,
+    wxTEXT_BOX_ATTR_COLLAPSE_BORDERS        = 0x00000004
+};
+
+// Whether a value is present, used in dimension flags
+enum wxTextAttrValueFlags
+{
+    wxTEXT_ATTR_VALUE_PRESENT               = 0x1000,
+    wxTEXT_ATTR_VALUE_PRESENT_MASK          = 0x1000
+};
+
+// Units - included in the dimension value
+enum wxTextAttrUnits
+{
+    wxTEXT_ATTR_UNITS_TENTHS_MM             = 0x0001,
+    wxTEXT_ATTR_UNITS_PIXELS                = 0x0002,
+    wxTEXT_ATTR_UNITS_PERCENTAGE            = 0x0004,
+    wxTEXT_ATTR_UNITS_POINTS                = 0x0008,
+
+    wxTEXT_ATTR_UNITS_MASK                  = 0x000F
+};
+
+// Position - included in the dimension flags
+enum wxTextBoxAttrPosition
+{
+    wxTEXT_BOX_ATTR_POSITION_STATIC         = 0x0000, // Default is static, i.e. as per normal layout
+    wxTEXT_BOX_ATTR_POSITION_RELATIVE       = 0x0010,
+    wxTEXT_BOX_ATTR_POSITION_ABSOLUTE       = 0x0020,
+
+    wxTEXT_BOX_ATTR_POSITION_MASK           = 0x00F0
+};
+
+// Dimension, including units and position
+class WXDLLIMPEXP_RICHTEXT wxTextAttrDimension
+{
+public:
+    wxTextAttrDimension() { Reset(); }
+    wxTextAttrDimension(int value, wxTextAttrDimensionFlags flags = wxTEXT_ATTR_VALUE_PRESENT|wxTEXT_ATTR_UNITS_TENTHS_MM) { m_value = value; m_flags = flags; }
+    
+    void Reset() { m_value = 0; m_flags = 0; }
+
+    // Partial equality test
+    bool EqPartial(const wxTextAttrDimension& dim) const;
+
+    // Apply
+    bool Apply(const wxTextAttrDimension& dim, const wxTextAttrDimension* compareWith = NULL);
+
+    // Collects the attributes that are common to a range of content, building up a note of
+    // which attributes are absent in some objects and which clash in some objects.
+    void CollectCommonAttributes(const wxTextAttrDimension& attr, wxTextAttrDimension& clashingAttr, wxTextAttrDimension& absentAttr);
+
+    bool operator==(const wxTextAttrDimension& dim) const { return m_value == dim.m_value && m_flags == dim.m_flags; }
+    
+    int GetValue() const { return m_value; }
+    float GetValueMM() const { return float(m_value) / 10.0; }
+    void SetValueMM(float value) { m_value = (int) ((value * 10.0) + 0.5); m_flags |= wxTEXT_ATTR_VALUE_PRESENT; }
+    void SetValue(int value) { m_value = value; m_flags |= wxTEXT_ATTR_VALUE_PRESENT; }
+    void SetValue(int value, wxTextAttrDimensionFlags flags) { m_value = value; m_flags = flags; }
+    void SetValue(const wxTextAttrDimension& dim) { (*this) = dim; }
+    
+    wxTextAttrUnits GetUnits() const { return (wxTextAttrUnits) (m_flags & wxTEXT_ATTR_UNITS_MASK); }
+    void SetUnits(wxTextAttrUnits units) { m_flags &= ~wxTEXT_ATTR_UNITS_MASK; m_flags |= units; }
+    
+    wxTextBoxAttrPosition GetPosition() const { return (wxTextBoxAttrPosition) (m_flags & wxTEXT_BOX_ATTR_POSITION_MASK); }
+    void SetPosition(wxTextBoxAttrPosition pos) { m_flags &= ~wxTEXT_BOX_ATTR_POSITION_MASK; m_flags |= pos; }
+    
+    bool IsPresent() const { return (m_flags & wxTEXT_ATTR_VALUE_PRESENT) != 0; }
+    void SetPresent(bool b) { m_flags &= ~wxTEXT_ATTR_VALUE_PRESENT_MASK; m_flags |= (b ? wxTEXT_ATTR_VALUE_PRESENT : 0); }
+    
+    wxTextAttrDimensionFlags GetFlags() const { return m_flags; }
+    void SetFlags(wxTextAttrDimensionFlags flags) { m_flags = flags; }
+    
+    int                         m_value;
+    wxTextAttrDimensionFlags    m_flags;
+};
+
+// A class for left, right, top and bottom dimensions
+class WXDLLIMPEXP_RICHTEXT wxTextAttrDimensions
+{
+public:
+    void Reset() { m_left.Reset(); m_top.Reset(); m_right.Reset(); m_bottom.Reset(); }
+    
+    bool operator==(const wxTextAttrDimensions& dims) const { return m_left == dims.m_left && m_top == dims.m_top && m_right == dims.m_right && m_bottom == dims.m_bottom; }
+    
+    // Partial equality test
+    bool EqPartial(const wxTextAttrDimensions& dims) const;
+
+    // Apply border to 'this', but not if the same as compareWith
+    bool Apply(const wxTextAttrDimensions& dims, const wxTextAttrDimensions* compareWith = NULL);
+
+    // Collects the attributes that are common to a range of content, building up a note of
+    // which attributes are absent in some objects and which clash in some objects.
+    void CollectCommonAttributes(const wxTextAttrDimensions& attr, wxTextAttrDimensions& clashingAttr, wxTextAttrDimensions& absentAttr);
+
+    // Remove specified attributes from this object
+    bool RemoveStyle(const wxTextAttrDimensions& attr);
+
+    const wxTextAttrDimension& GetLeft() const { return m_left; }
+    wxTextAttrDimension& GetLeft() { return m_left; }
+
+    const wxTextAttrDimension& GetRight() const { return m_right; }
+    wxTextAttrDimension& GetRight() { return m_right; }
+
+    const wxTextAttrDimension& GetTop() const { return m_top; }
+    wxTextAttrDimension& GetTop() { return m_top; }
+
+    const wxTextAttrDimension& GetBottom() const { return m_bottom; }
+    wxTextAttrDimension& GetBottom() { return m_bottom; }
+
+    wxTextAttrDimension         m_left;
+    wxTextAttrDimension         m_top;
+    wxTextAttrDimension         m_right;
+    wxTextAttrDimension         m_bottom;
+};
+
+// A class to make it easier to convert dimensions
+class WXDLLIMPEXP_RICHTEXT wxTextAttrDimensionConverter
+{
+public:
+    wxTextAttrDimensionConverter(wxDC& dc, double scale = 1.0, const wxSize& parentSize = wxDefaultSize);
+    wxTextAttrDimensionConverter(int ppi, double scale = 1.0, const wxSize& parentSize = wxDefaultSize);
+    
+    int GetPixels(const wxTextAttrDimension& dim, int direction = wxHORIZONTAL) const;
+    int GetTenthsMM(const wxTextAttrDimension& dim) const;
+
+    int ConvertTenthsMMToPixels(int units) const;
+    int ConvertPixelsToTenthsMM(int pixels) const;
+
+    int     m_ppi;
+    double  m_scale;
+    wxSize  m_parentSize;
+};
+
+// Border styles
+enum wxTextAttrBorderStyle
+{
+    wxTEXT_BOX_ATTR_BORDER_NONE             = 0,
+    wxTEXT_BOX_ATTR_BORDER_SOLID            = 1,
+    wxTEXT_BOX_ATTR_BORDER_DOTTED           = 2,
+    wxTEXT_BOX_ATTR_BORDER_DASHED           = 3,
+    wxTEXT_BOX_ATTR_BORDER_DOUBLE           = 4,
+    wxTEXT_BOX_ATTR_BORDER_GROOVE           = 5,
+    wxTEXT_BOX_ATTR_BORDER_RIDGE            = 6,
+    wxTEXT_BOX_ATTR_BORDER_INSET            = 7,
+    wxTEXT_BOX_ATTR_BORDER_OUTSET           = 8
+};
+
+// Border style presence flags
+enum wxTextAttrBorderFlags
+{
+    wxTEXT_BOX_ATTR_BORDER_STYLE            = 0x0001,
+    wxTEXT_BOX_ATTR_BORDER_COLOUR           = 0x0002
+};
+
+// Border width symbols for qualitative widths
+enum wxTextAttrBorderWidth
+{
+    wxTEXT_BOX_ATTR_BORDER_THIN             = -1,
+    wxTEXT_BOX_ATTR_BORDER_MEDIUM           = -2,
+    wxTEXT_BOX_ATTR_BORDER_THICK            = -3
+};
+
+// Float styles
+enum wxTextBoxAttrFloatStyle
+{
+    wxTEXT_BOX_ATTR_FLOAT_NONE              = 0,
+    wxTEXT_BOX_ATTR_FLOAT_LEFT              = 1,
+    wxTEXT_BOX_ATTR_FLOAT_RIGHT             = 2
+};
+
+// Clear styles
+enum wxTextBoxAttrClearStyle
+{
+    wxTEXT_BOX_ATTR_CLEAR_NONE              = 0,
+    wxTEXT_BOX_ATTR_CLEAR_LEFT              = 1,
+    wxTEXT_BOX_ATTR_CLEAR_RIGHT             = 2,
+    wxTEXT_BOX_ATTR_CLEAR_BOTH              = 3
+};
+
+// Collapse mode styles. TODO: can they be switched on per side?
+enum wxTextBoxAttrCollapseMode
+{
+    wxTEXT_BOX_ATTR_COLLAPSE_NONE           = 0,
+    wxTEXT_BOX_ATTR_COLLAPSE_FULL           = 1
+};
+
+// Border
+class WXDLLIMPEXP_RICHTEXT wxTextAttrBorder
+{
+public:
+    wxTextAttrBorder() { Reset(); }
+    
+    bool operator==(const wxTextAttrBorder& border) const
+    {
+        return m_flags == border.m_flags && m_borderStyle == border.m_borderStyle &&
+               m_borderColour == border.m_borderColour && m_borderWidth == border.m_borderWidth;
+    }
+
+    void Reset() { m_borderStyle = 0; m_borderColour = 0; m_flags = 0; m_borderWidth.Reset(); }
+
+    // Partial equality test
+    bool EqPartial(const wxTextAttrBorder& border) const;
+
+    // Apply border to 'this', but not if the same as compareWith
+    bool Apply(const wxTextAttrBorder& border, const wxTextAttrBorder* compareWith = NULL);
+
+    // Remove specified attributes from this object
+    bool RemoveStyle(const wxTextAttrBorder& attr);
+
+    // Collects the attributes that are common to a range of content, building up a note of
+    // which attributes are absent in some objects and which clash in some objects.
+    void CollectCommonAttributes(const wxTextAttrBorder& attr, wxTextAttrBorder& clashingAttr, wxTextAttrBorder& absentAttr);
+
+    void SetStyle(int style) { m_borderStyle = style; m_flags |= wxTEXT_BOX_ATTR_BORDER_STYLE; }
+    int GetStyle() const { return m_borderStyle; }
+
+    void SetColour(unsigned long colour) { m_borderColour = colour; m_flags |= wxTEXT_BOX_ATTR_BORDER_COLOUR; }
+    void SetColour(const wxColour& colour) { m_borderColour = colour.GetRGB(); m_flags |= wxTEXT_BOX_ATTR_BORDER_COLOUR; }
+    unsigned long GetColourLong() const { return m_borderColour; }
+    wxColour GetColour() const { return wxColour(m_borderColour); }
+
+    wxTextAttrDimension& GetWidth() { return m_borderWidth; }
+    const wxTextAttrDimension& GetWidth() const { return m_borderWidth; }
+    void SetWidth(const wxTextAttrDimension& width) { m_borderWidth = width; }
+
+    bool HasStyle() const { return (m_flags & wxTEXT_BOX_ATTR_BORDER_STYLE) != 0; }
+    bool HasColour() const { return (m_flags & wxTEXT_BOX_ATTR_BORDER_COLOUR) != 0; }
+    bool HasWidth() const { return m_borderWidth.IsPresent(); }
+    
+    bool IsValid() const { return HasStyle() && HasColour() && HasWidth(); }
+    
+    int GetFlags() const { return m_flags; }
+    void SetFlags(int flags) { m_flags = flags; }
+    void AddFlag(int flag) { m_flags |= flag; }
+    void RemoveFlag(int flag) { m_flags &= ~flag; }
+
+    int                         m_borderStyle;
+    unsigned long               m_borderColour;
+    wxTextAttrDimension         m_borderWidth;
+    int                         m_flags;
+};
+
+// Borders
+class WXDLLIMPEXP_RICHTEXT wxTextAttrBorders
+{
+public:
+    wxTextAttrBorders() { }
+
+    bool operator==(const wxTextAttrBorders& borders) const
+    {
+        return m_left == borders.m_left && m_right == borders.m_right &&
+               m_top == borders.m_top && m_bottom == borders.m_bottom;
+    }
+
+    // Set style of all borders
+    void SetStyle(int style);
+
+    // Set colour of all borders
+    void SetColour(unsigned long colour);
+    void SetColour(const wxColour& colour);
+
+    // Set width of all borders
+    void SetWidth(const wxTextAttrDimension& width);
+    
+    // Reset
+    void Reset() { m_left.Reset(); m_right.Reset(); m_top.Reset(); m_bottom.Reset(); }
+
+    // Partial equality test
+    bool EqPartial(const wxTextAttrBorders& borders) const;
+
+    // Apply border to 'this', but not if the same as compareWith
+    bool Apply(const wxTextAttrBorders& borders, const wxTextAttrBorders* compareWith = NULL);
+
+    // Remove specified attributes from this object
+    bool RemoveStyle(const wxTextAttrBorders& attr);
+
+    // Collects the attributes that are common to a range of content, building up a note of
+    // which attributes are absent in some objects and which clash in some objects.
+    void CollectCommonAttributes(const wxTextAttrBorders& attr, wxTextAttrBorders& clashingAttr, wxTextAttrBorders& absentAttr);
+    
+    bool HasBorder() const { return m_left.IsValid() || m_right.IsValid() || m_top.IsValid() || m_bottom.IsValid(); }
+
+    const wxTextAttrBorder& GetLeft() const { return m_left; }
+    wxTextAttrBorder& GetLeft() { return m_left; }
+    
+    const wxTextAttrBorder& GetRight() const { return m_right; }
+    wxTextAttrBorder& GetRight() { return m_right; }
+    
+    const wxTextAttrBorder& GetTop() const { return m_top; }
+    wxTextAttrBorder& GetTop() { return m_top; }
+    
+    const wxTextAttrBorder& GetBottom() const { return m_bottom; }
+    wxTextAttrBorder& GetBottom() { return m_bottom; }
+    
+    wxTextAttrBorder m_left, m_right, m_top, m_bottom;
+
+};
+
+// ----------------------------------------------------------------------------
+// wxTextBoxAttr: a structure containing box attributes
+// ----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_RICHTEXT wxTextBoxAttr
+{
+public:
+    // ctors
+    wxTextBoxAttr() { Init(); }
+    wxTextBoxAttr(const wxTextBoxAttr& attr) { Init(); (*this) = attr; }
+
+    // Initialise this object.
+    void Init() { Reset(); }
+
+    // Reset this object.
+    void Reset();
+
+    // Copy. Unnecessary since we let it do a binary copy
+    //void Copy(const wxTextBoxAttr& attr);
+
+    // Assignment
+    //void operator= (const wxTextBoxAttr& attr);
+
+    // Equality test
+    bool operator== (const wxTextBoxAttr& attr) const;
+
+    // Partial equality test
+    bool EqPartial(const wxTextBoxAttr& attr) const;
+
+    // Merges the given attributes. If compareWith
+    // is non-NULL, then it will be used to mask out those attributes that are the same in style
+    // and compareWith, for situations where we don't want to explicitly set inherited attributes.
+    bool Apply(const wxTextBoxAttr& style, const wxTextBoxAttr* compareWith = NULL);
+    
+    // Collects the attributes that are common to a range of content, building up a note of
+    // which attributes are absent in some objects and which clash in some objects.
+    void CollectCommonAttributes(const wxTextBoxAttr& attr, wxTextBoxAttr& clashingAttr, wxTextBoxAttr& absentAttr);
+
+    // Remove specified attributes from this object
+    bool RemoveStyle(const wxTextBoxAttr& attr);
+
+    // Set flags
+    void SetFlags(int flags) { m_flags = flags; }
+
+    // Get flags
+    int GetFlags() const { return m_flags; }
+
+    // Is this flag present?
+    bool HasFlag(wxTextBoxAttrFlags flag) const { return (m_flags & flag) != 0; }
+
+    // Remove this flag
+    void RemoveFlag(wxTextBoxAttrFlags flag) { m_flags &= ~flag; }
+
+    // Add this flag
+    void AddFlag(wxTextBoxAttrFlags flag) { m_flags |= flag; }
+
+    // Is this default? I.e. no flags set
+    bool IsDefault() const;
+
+    // Float mode
+    short int GetFloatMode() const { return m_floatMode; }
+    void SetFloatMode(short int mode) { m_floatMode = mode; m_flags |= wxTEXT_BOX_ATTR_FLOAT; }
+    bool HasFloatMode() const { return HasFlag(wxTEXT_BOX_ATTR_FLOAT); }
+    bool IsFloating() const { return HasFloatMode() && GetFloatMode() != wxTEXT_BOX_ATTR_FLOAT_NONE; }
+
+    // Whether to wrap text after object
+    short int GetClearMode() const { return m_clearMode; }
+    void SetClearMode(short int mode) { m_clearMode = mode; m_flags |= wxTEXT_BOX_ATTR_CLEAR; }
+    bool HasClearMode() const { return HasFlag(wxTEXT_BOX_ATTR_CLEAR); }
+
+    // Whether to collapse borders
+    int GetCollapseBorders() const { return m_collapseMode ; }
+    void SetCollapseBorders(int collapse) { m_collapseMode = collapse; m_flags |= wxTEXT_BOX_ATTR_COLLAPSE_BORDERS; }
+    bool HasCollapseBorders() const { return HasFlag(wxTEXT_BOX_ATTR_COLLAPSE_BORDERS); }
+    
+    // Margins
+    
+    wxTextAttrDimensions& GetMargins() { return m_margins; }
+    const wxTextAttrDimensions& GetMargins() const { return m_margins; }
+
+    wxTextAttrDimension& GetLeftMargin() { return m_margins.m_left; }
+    const wxTextAttrDimension& GetLeftMargin() const { return m_margins.m_left; }
+
+    wxTextAttrDimension& GetRightMargin() { return m_margins.m_right; }
+    const wxTextAttrDimension& GetRightMargin() const { return m_margins.m_right; }
+
+    wxTextAttrDimension& GetTopMargin() { return m_margins.m_top; }
+    const wxTextAttrDimension& GetTopMargin() const { return m_margins.m_top; }
+    
+    wxTextAttrDimension& GetBottomMargin() { return m_margins.m_bottom; }
+    const wxTextAttrDimension& GetBottomMargin() const { return m_margins.m_bottom; }
+
+    // Position
+    
+    wxTextAttrDimensions& GetPosition() { return m_position; }
+    const wxTextAttrDimensions& GetPosition() const { return m_position; }
+
+    wxTextAttrDimension& GetLeft() { return m_position.m_left; }
+    const wxTextAttrDimension& GetLeft() const { return m_position.m_left; }
+
+    wxTextAttrDimension& GetRight() { return m_position.m_right; }
+    const wxTextAttrDimension& GetRight() const { return m_position.m_right; }
+
+    wxTextAttrDimension& GetTop() { return m_position.m_top; }
+    const wxTextAttrDimension& GetTop() const { return m_position.m_top; }
+    
+    wxTextAttrDimension& GetBottom() { return m_position.m_bottom; }
+    const wxTextAttrDimension& GetBottom() const { return m_position.m_bottom; }
+
+    // Padding
+    
+    wxTextAttrDimensions& GetPadding() { return m_padding; }
+    const wxTextAttrDimensions& GetPadding() const { return m_padding; }
+
+    wxTextAttrDimension& GetLeftPadding() { return m_padding.m_left; }
+    const wxTextAttrDimension& GetLeftPadding() const { return m_padding.m_left; }
+    
+    wxTextAttrDimension& GetRightPadding() { return m_padding.m_right; }
+    const wxTextAttrDimension& GetRightPadding() const { return m_padding.m_right; }
+    
+    wxTextAttrDimension& GetTopPadding() { return m_padding.m_top; }
+    const wxTextAttrDimension& GetTopPadding() const { return m_padding.m_top; }
+
+    wxTextAttrDimension& GetBottomPadding() { return m_padding.m_bottom; }
+    const wxTextAttrDimension& GetBottomPadding() const { return m_padding.m_bottom; }
+    
+    // Border
+
+    wxTextAttrBorders& GetBorder() { return m_border; }
+    const wxTextAttrBorders& GetBorder() const { return m_border; }
+
+    wxTextAttrBorder& GetLeftBorder() { return m_border.m_left; }
+    const wxTextAttrBorder& GetLeftBorder() const { return m_border.m_left; }
+
+    wxTextAttrBorder& GetTopBorder() { return m_border.m_top; }
+    const wxTextAttrBorder& GetTopBorder() const { return m_border.m_top; }
+
+    wxTextAttrBorder& GetRightBorder() { return m_border.m_right; }
+    const wxTextAttrBorder& GetRightBorder() const { return m_border.m_right; }
+
+    wxTextAttrBorder& GetBottomBorder() { return m_border.m_bottom; }
+    const wxTextAttrBorder& GetBottomBorder() const { return m_border.m_bottom; }
+    
+    // Outline
+
+    wxTextAttrBorders& GetOutline() { return m_outline; }
+    const wxTextAttrBorders& GetOutline() const { return m_outline; }
+
+    wxTextAttrBorder& GetLeftOutline() { return m_outline.m_left; }
+    const wxTextAttrBorder& GetLeftOutline() const { return m_outline.m_left; }
+
+    wxTextAttrBorder& GetTopOutline() { return m_outline.m_top; }
+    const wxTextAttrBorder& GetTopOutline() const { return m_outline.m_top; }
+
+    wxTextAttrBorder& GetRightOutline() { return m_outline.m_right; }
+    const wxTextAttrBorder& GetRightOutline() const { return m_outline.m_right; }
+
+    wxTextAttrBorder& GetBottomOutline() { return m_outline.m_bottom; }
+    const wxTextAttrBorder& GetBottomOutline() const { return m_outline.m_bottom; }
+
+
+    // Width and height
+    
+    wxTextAttrDimension& GetWidth() { return m_width; }
+    const wxTextAttrDimension& GetWidth() const { return m_width; }
+
+    wxTextAttrDimension& GetHeight() { return m_height; }
+    const wxTextAttrDimension& GetHeight() const { return m_height; }
+
+public:
+
+    int                         m_flags;
+    
+    wxTextAttrDimensions     m_margins;
+    wxTextAttrDimensions     m_padding;
+    wxTextAttrDimensions     m_position;
+
+    wxTextAttrDimension         m_width;
+    wxTextAttrDimension         m_height;    
+
+    wxTextAttrBorders        m_border;    
+    wxTextAttrBorders        m_outline;
+
+    short int                   m_floatMode;
+    short int                   m_clearMode;
+    short int                   m_collapseMode;
+};
+
+// ----------------------------------------------------------------------------
+// wxRichTextAttr: an enhanced attribute
+// ----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_RICHTEXT wxRichTextAttr: public wxTextAttr
+{
+public:
+    wxRichTextAttr(const wxTextAttr& attr) { wxTextAttr::Copy(attr); }
+    wxRichTextAttr(const wxRichTextAttr& attr) { Copy(attr); }
+    wxRichTextAttr() {}
+    
+    // Copy
+    void Copy(const wxRichTextAttr& attr);
+    
+    // Assignment
+    void operator=(const wxRichTextAttr& attr) { Copy(attr); }
+    void operator=(const wxTextAttr& attr) { wxTextAttr::Copy(attr); }
+    
+    // Equality test
+    bool operator==(const wxRichTextAttr& attr) const;
+
+    // Partial equality test taking comparison object into account
+    bool EqPartial(const wxRichTextAttr& attr) const;
+
+    // Merges the given attributes. If compareWith
+    // is non-NULL, then it will be used to mask out those attributes that are the same in style
+    // and compareWith, for situations where we don't want to explicitly set inherited attributes.
+    bool Apply(const wxRichTextAttr& style, const wxRichTextAttr* compareWith = NULL);
+
+    // Collects the attributes that are common to a range of content, building up a note of
+    // which attributes are absent in some objects and which clash in some objects.
+    void CollectCommonAttributes(const wxRichTextAttr& attr, wxRichTextAttr& clashingAttr, wxRichTextAttr& absentAttr);
+
+    // Remove specified attributes from this object
+    bool RemoveStyle(const wxRichTextAttr& attr);
+
+    wxTextBoxAttr& GetTextBoxAttr() { return m_textBoxAttr; }
+    const wxTextBoxAttr& GetTextBoxAttr() const { return m_textBoxAttr; }
+    void SetTextBoxAttr(const wxTextBoxAttr& attr) { m_textBoxAttr = attr; }
+    
+    wxTextBoxAttr    m_textBoxAttr;
+};
+
+WX_DECLARE_USER_EXPORTED_OBJARRAY(wxVariant, wxRichTextVariantArray, WXDLLIMPEXP_RICHTEXT);
+
+// ----------------------------------------------------------------------------
+// wxRichTextProperties - A simple property class using wxVariants
+// ----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_RICHTEXT wxRichTextProperties: public wxObject
+{
+DECLARE_DYNAMIC_CLASS(wxRichTextProperties)
+public:
+    wxRichTextProperties() {}
+    wxRichTextProperties(const wxRichTextProperties& props) { Copy(props); }
+
+    void operator=(const wxRichTextProperties& props) { Copy(props); }
+    bool operator==(const wxRichTextProperties& props) const;
+    void Copy(const wxRichTextProperties& props) { m_properties = props.m_properties; }
+    const wxVariant& operator[](size_t idx) const { return m_properties[idx]; }
+    wxVariant& operator[](size_t idx) { return m_properties[idx]; }
+    void Clear() { m_properties.Clear(); }
+
+    const wxRichTextVariantArray& GetProperties() const { return m_properties; }
+    wxRichTextVariantArray& GetProperties() { return m_properties; }
+    void SetProperties(const wxRichTextVariantArray& props) { m_properties = props; }
+
+    wxArrayString GetPropertyNames() const;
+
+    size_t GetCount() const { return m_properties.GetCount(); }
+
+    int HasProperty(const wxString& name) const { return Find(name) != -1; }
+
+    int Find(const wxString& name) const;
+    const wxVariant& GetProperty(const wxString& name) const;
+    wxVariant* FindOrCreateProperty(const wxString& name);
+
+    wxString GetPropertyString(const wxString& name) const;
+    long GetPropertyLong(const wxString& name) const;
+    bool GetPropertyBool(const wxString& name) const;
+    double GetPropertyDouble(const wxString& name) const;
+
+    void SetProperty(const wxVariant& variant);
+    void SetProperty(const wxString& name, const wxVariant& variant);
+    void SetProperty(const wxString& name, const wxString& value);
+    void SetProperty(const wxString& name, long value);
+    void SetProperty(const wxString& name, double value);
+    void SetProperty(const wxString& name, bool value);
+
+protected:
+    wxRichTextVariantArray  m_properties;
+};
+
+
+/*!
+ * wxRichTextFontTable
+ * Manages quick access to a pool of fonts for rendering rich text
+ */
+
+class WXDLLIMPEXP_RICHTEXT wxRichTextFontTable: public wxObject
+{
+public:
+    wxRichTextFontTable();
+
+    wxRichTextFontTable(const wxRichTextFontTable& table);
+    virtual ~wxRichTextFontTable();
+
+    bool IsOk() const { return m_refData != NULL; }
+
+    wxFont FindFont(const wxRichTextAttr& fontSpec);
+    void Clear();
+
+    void operator= (const wxRichTextFontTable& table);
+    bool operator == (const wxRichTextFontTable& table) const;
+    bool operator != (const wxRichTextFontTable& table) const { return !(*this == table); }
+
+protected:
+
+    DECLARE_DYNAMIC_CLASS(wxRichTextFontTable)
+};
 
 /*!
  * wxRichTextRange class declaration
  * This stores beginning and end positions for a range of data.
 
 /*!
  * wxRichTextRange class declaration
  * This stores beginning and end positions for a range of data.
+ * TODO: consider renaming wxTextRange and using for all text controls.
  */
 
 class WXDLLIMPEXP_RICHTEXT wxRichTextRange
  */
 
 class WXDLLIMPEXP_RICHTEXT wxRichTextRange
@@ -214,6 +878,7 @@ public:
 
     void operator =(const wxRichTextRange& range) { m_start = range.m_start; m_end = range.m_end; }
     bool operator ==(const wxRichTextRange& range) const { return (m_start == range.m_start && m_end == range.m_end); }
 
     void operator =(const wxRichTextRange& range) { m_start = range.m_start; m_end = range.m_end; }
     bool operator ==(const wxRichTextRange& range) const { return (m_start == range.m_start && m_end == range.m_end); }
+    bool operator !=(const wxRichTextRange& range) const { return (m_start != range.m_start || m_end != range.m_end); }
     wxRichTextRange operator -(const wxRichTextRange& range) const { return wxRichTextRange(m_start - range.m_start, m_end - range.m_end); }
     wxRichTextRange operator +(const wxRichTextRange& range) const { return wxRichTextRange(m_start + range.m_start, m_end + range.m_end); }
 
     wxRichTextRange operator -(const wxRichTextRange& range) const { return wxRichTextRange(m_start - range.m_start, m_end - range.m_end); }
     wxRichTextRange operator +(const wxRichTextRange& range) const { return wxRichTextRange(m_start + range.m_start, m_end + range.m_end); }
 
@@ -246,6 +911,12 @@ public:
     /// Swaps the start and end
     void Swap() { long tmp = m_start; m_start = m_end; m_end = tmp; }
 
     /// Swaps the start and end
     void Swap() { long tmp = m_start; m_start = m_end; m_end = tmp; }
 
+    /// Convert to internal form: (n, n) is the range of a single character.
+    wxRichTextRange ToInternal() const { return wxRichTextRange(m_start, m_end-1); }
+
+    /// Convert from internal to public API form: (n, n+1) is the range of a single character.
+    wxRichTextRange FromInternal() const { return wxRichTextRange(m_start, m_end+1); }
+
 protected:
     long m_start;
     long m_end;
 protected:
     long m_start;
     long m_end;
@@ -254,273 +925,6 @@ protected:
 #define wxRICHTEXT_ALL  wxRichTextRange(-2, -2)
 #define wxRICHTEXT_NONE  wxRichTextRange(-1, -1)
 
 #define wxRICHTEXT_ALL  wxRichTextRange(-2, -2)
 #define wxRICHTEXT_NONE  wxRichTextRange(-1, -1)
 
-/*!
- * wxTextAttrEx is an extended version of wxTextAttr with more paragraph attributes.
- */
-
-class WXDLLIMPEXP_RICHTEXT wxTextAttrEx: public wxTextAttr
-{
-public:
-    // ctors
-    wxTextAttrEx(const wxTextAttrEx& attr);
-    wxTextAttrEx(const wxTextAttr& attr) { Init(); (*this) = attr; }
-    wxTextAttrEx() { Init(); }
-
-    // Initialise this object.
-    void Init();
-
-    // Assignment from a wxTextAttrEx object
-    void operator= (const wxTextAttrEx& attr);
-
-    // Assignment from a wxTextAttr object.
-    void operator= (const wxTextAttr& attr);
-
-    // setters
-    void SetCharacterStyleName(const wxString& name) { m_characterStyleName = name; SetFlags(GetFlags() | wxTEXT_ATTR_CHARACTER_STYLE_NAME); }
-    void SetParagraphStyleName(const wxString& name) { m_paragraphStyleName = name; SetFlags(GetFlags() | wxTEXT_ATTR_PARAGRAPH_STYLE_NAME); }
-    void SetParagraphSpacingAfter(int spacing) { m_paragraphSpacingAfter = spacing; SetFlags(GetFlags() | wxTEXT_ATTR_PARA_SPACING_AFTER); }
-    void SetParagraphSpacingBefore(int spacing) { m_paragraphSpacingBefore = spacing; SetFlags(GetFlags() | wxTEXT_ATTR_PARA_SPACING_BEFORE); }
-    void SetLineSpacing(int spacing) { m_lineSpacing = spacing; SetFlags(GetFlags() | wxTEXT_ATTR_LINE_SPACING); }
-    void SetBulletStyle(int style) { m_bulletStyle = style; SetFlags(GetFlags() | wxTEXT_ATTR_BULLET_STYLE); }
-    void SetBulletNumber(int n) { m_bulletNumber = n; SetFlags(GetFlags() | wxTEXT_ATTR_BULLET_NUMBER); }
-    void SetBulletSymbol(wxChar symbol) { m_bulletSymbol = symbol; SetFlags(GetFlags() | wxTEXT_ATTR_BULLET_SYMBOL); }
-
-    const wxString& GetCharacterStyleName() const { return m_characterStyleName; }
-    const wxString& GetParagraphStyleName() const { return m_paragraphStyleName; }
-    int GetParagraphSpacingAfter() const { return m_paragraphSpacingAfter; }
-    int GetParagraphSpacingBefore() const { return m_paragraphSpacingBefore; }
-    int GetLineSpacing() const { return m_lineSpacing; }
-    int GetBulletStyle() const { return m_bulletStyle; }
-    int GetBulletNumber() const { return m_bulletNumber; }
-    wxChar GetBulletSymbol() const { return m_bulletSymbol; }
-
-    bool HasWeight() const { return (GetFlags() & wxTEXT_ATTR_FONT_WEIGHT) != 0; }
-    bool HasSize() const { return (GetFlags() & wxTEXT_ATTR_FONT_SIZE) != 0; }
-    bool HasItalic() const { return (GetFlags() & wxTEXT_ATTR_FONT_ITALIC) != 0; }
-    bool HasUnderlined() const { return (GetFlags() & wxTEXT_ATTR_FONT_UNDERLINE) != 0; }
-    bool HasFaceName() const { return (GetFlags() & wxTEXT_ATTR_FONT_FACE) != 0; }
-
-    bool HasParagraphSpacingAfter() const { return HasFlag(wxTEXT_ATTR_PARA_SPACING_AFTER); }
-    bool HasParagraphSpacingBefore() const { return HasFlag(wxTEXT_ATTR_PARA_SPACING_BEFORE); }
-    bool HasLineSpacing() const { return HasFlag(wxTEXT_ATTR_LINE_SPACING); }
-    bool HasCharacterStyleName() const { return HasFlag(wxTEXT_ATTR_CHARACTER_STYLE_NAME); }
-    bool HasParagraphStyleName() const { return HasFlag(wxTEXT_ATTR_PARAGRAPH_STYLE_NAME); }
-    bool HasBulletStyle() const { return HasFlag(wxTEXT_ATTR_BULLET_STYLE); }
-    bool HasBulletNumber() const { return HasFlag(wxTEXT_ATTR_BULLET_NUMBER); }
-    bool HasBulletSymbol() const { return HasFlag(wxTEXT_ATTR_BULLET_SYMBOL); }
-
-    // Is this a character style?
-    bool IsCharacterStyle() const { return (0 != (GetFlags() & (wxTEXT_ATTR_FONT | wxTEXT_ATTR_BACKGROUND_COLOUR | wxTEXT_ATTR_TEXT_COLOUR))); }
-    bool IsParagraphStyle() const { return (0 != (GetFlags() & (wxTEXT_ATTR_ALIGNMENT|wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT|wxTEXT_ATTR_TABS|
-                            wxTEXT_ATTR_PARA_SPACING_BEFORE|wxTEXT_ATTR_PARA_SPACING_AFTER|wxTEXT_ATTR_LINE_SPACING|
-                            wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER))); }
-
-    // returns false if we have any attributes set, true otherwise
-    bool IsDefault() const
-    {
-        return !HasTextColour() && !HasBackgroundColour() && !HasFont() && !HasAlignment() &&
-               !HasTabs() && !HasLeftIndent() && !HasRightIndent() &&
-               !HasParagraphSpacingAfter() && !HasParagraphSpacingBefore() && !HasLineSpacing() &&
-               !HasCharacterStyleName() && !HasParagraphStyleName() && !HasBulletNumber() && !HasBulletStyle() && !HasBulletSymbol();
-    }
-
-    // return the attribute having the valid font and colours: it uses the
-    // attributes set in attr and falls back first to attrDefault and then to
-    // the text control font/colours for those attributes which are not set
-    static wxTextAttrEx CombineEx(const wxTextAttrEx& attr,
-                              const wxTextAttrEx& attrDef,
-                              const wxTextCtrlBase *text);
-
-private:
-    // Paragraph styles
-    int                 m_paragraphSpacingAfter;
-    int                 m_paragraphSpacingBefore;
-    int                 m_lineSpacing;
-    int                 m_bulletStyle;
-    int                 m_bulletNumber;
-    wxChar              m_bulletSymbol;
-
-    // Character style
-    wxString            m_characterStyleName;
-
-    // Paragraph style
-    wxString            m_paragraphStyleName;
-};
-
-/*!
- * wxRichTextAttr stores attributes without a wxFont object, so is a much more
- * efficient way to query styles.
- */
-
-class WXDLLIMPEXP_RICHTEXT wxRichTextAttr
-{
-public:
-    // ctors
-    wxRichTextAttr(const wxTextAttrEx& attr);
-    wxRichTextAttr() { Init(); }
-    wxRichTextAttr(const wxColour& colText,
-               const wxColour& colBack = wxNullColour,
-               wxTextAttrAlignment alignment = wxTEXT_ALIGNMENT_DEFAULT);
-
-    // Initialise this object.
-    void Init();
-
-    // Assignment from a wxRichTextAttr object.
-    void operator= (const wxRichTextAttr& attr);
-
-    // Assignment from a wxTextAttrEx object.
-    void operator= (const wxTextAttrEx& attr);
-
-    // Making a wxTextAttrEx object.
-    operator wxTextAttrEx () const ;
-
-    // Copy to a wxTextAttr
-    void CopyTo(wxTextAttrEx& attr) const;
-
-    // Create font from font attributes.
-    wxFont CreateFont() const;
-
-    // Get attributes from font.
-    bool GetFontAttributes(const wxFont& font);
-
-    // setters
-    void SetTextColour(const wxColour& colText) { m_colText = colText; m_flags |= wxTEXT_ATTR_TEXT_COLOUR; }
-    void SetBackgroundColour(const wxColour& colBack) { m_colBack = colBack; m_flags |= wxTEXT_ATTR_BACKGROUND_COLOUR; }
-    void SetAlignment(wxTextAttrAlignment alignment) { m_textAlignment = alignment; m_flags |= wxTEXT_ATTR_ALIGNMENT; }
-    void SetTabs(const wxArrayInt& tabs) { m_tabs = tabs; m_flags |= wxTEXT_ATTR_TABS; }
-    void SetLeftIndent(int indent, int subIndent = 0) { m_leftIndent = indent; m_leftSubIndent = subIndent; m_flags |= wxTEXT_ATTR_LEFT_INDENT; }
-    void SetRightIndent(int indent) { m_rightIndent = indent; m_flags |= wxTEXT_ATTR_RIGHT_INDENT; }
-
-    void SetFontSize(int pointSize) { m_fontSize = pointSize; m_flags |= wxTEXT_ATTR_FONT_SIZE; }
-    void SetFontStyle(int fontStyle) { m_fontStyle = fontStyle; m_flags |= wxTEXT_ATTR_FONT_ITALIC; }
-    void SetFontWeight(int fontWeight) { m_fontWeight = fontWeight; m_flags |= wxTEXT_ATTR_FONT_WEIGHT; }
-    void SetFontFaceName(const wxString& faceName) { m_fontFaceName = faceName; m_flags |= wxTEXT_ATTR_FONT_FACE; }
-    void SetFontUnderlined(bool underlined) { m_fontUnderlined = underlined; m_flags |= wxTEXT_ATTR_FONT_UNDERLINE; }
-
-    void SetFlags(long flags) { m_flags = flags; }
-
-    void SetCharacterStyleName(const wxString& name) { m_characterStyleName = name; }
-    void SetParagraphStyleName(const wxString& name) { m_paragraphStyleName = name; }
-    void SetParagraphSpacingAfter(int spacing) { m_paragraphSpacingAfter = spacing; }
-    void SetParagraphSpacingBefore(int spacing) { m_paragraphSpacingBefore = spacing; }
-    void SetLineSpacing(int spacing) { m_lineSpacing = spacing; }
-    void SetBulletStyle(int style) { m_bulletStyle = style; }
-    void SetBulletNumber(int n) { m_bulletNumber = n; }
-    void SetBulletSymbol(wxChar symbol) { m_bulletSymbol = symbol; }
-
-    const wxColour& GetTextColour() const { return m_colText; }
-    const wxColour& GetBackgroundColour() const { return m_colBack; }
-    wxTextAttrAlignment GetAlignment() const { return m_textAlignment; }
-    const wxArrayInt& GetTabs() const { return m_tabs; }
-    long GetLeftIndent() const { return m_leftIndent; }
-    long GetLeftSubIndent() const { return m_leftSubIndent; }
-    long GetRightIndent() const { return m_rightIndent; }
-    long GetFlags() const { return m_flags; }
-
-    int GetFontSize() const { return m_fontSize; }
-    int GetFontStyle() const { return m_fontStyle; }
-    int GetFontWeight() const { return m_fontWeight; }
-    bool GetFontUnderlined() const { return m_fontUnderlined; }
-    const wxString& GetFontFaceName() const { return m_fontFaceName; }
-
-    const wxString& GetCharacterStyleName() const { return m_characterStyleName; }
-    const wxString& GetParagraphStyleName() const { return m_paragraphStyleName; }
-    int GetParagraphSpacingAfter() const { return m_paragraphSpacingAfter; }
-    int GetParagraphSpacingBefore() const { return m_paragraphSpacingBefore; }
-    int GetLineSpacing() const { return m_lineSpacing; }
-    int GetBulletStyle() const { return m_bulletStyle; }
-    int GetBulletNumber() const { return m_bulletNumber; }
-    wxChar GetBulletSymbol() const { return m_bulletSymbol; }
-
-    // accessors
-    bool HasTextColour() const { return m_colText.Ok() && HasFlag(wxTEXT_ATTR_TEXT_COLOUR) ; }
-    bool HasBackgroundColour() const { return m_colBack.Ok() && HasFlag(wxTEXT_ATTR_BACKGROUND_COLOUR) ; }
-    bool HasAlignment() const { return (m_textAlignment != wxTEXT_ALIGNMENT_DEFAULT) || ((m_flags & wxTEXT_ATTR_ALIGNMENT) != 0) ; }
-    bool HasTabs() const { return (m_flags & wxTEXT_ATTR_TABS) != 0 ; }
-    bool HasLeftIndent() const { return (m_flags & wxTEXT_ATTR_LEFT_INDENT) != 0 ; }
-    bool HasRightIndent() const { return (m_flags & wxTEXT_ATTR_RIGHT_INDENT) != 0 ; }
-    bool HasWeight() const { return (m_flags & wxTEXT_ATTR_FONT_WEIGHT) != 0; }
-    bool HasSize() const { return (m_flags & wxTEXT_ATTR_FONT_SIZE) != 0; }
-    bool HasItalic() const { return (m_flags & wxTEXT_ATTR_FONT_ITALIC) != 0; }
-    bool HasUnderlined() const { return (m_flags & wxTEXT_ATTR_FONT_UNDERLINE) != 0; }
-    bool HasFaceName() const { return (m_flags & wxTEXT_ATTR_FONT_FACE) != 0; }
-    bool HasFont() const { return (m_flags & (wxTEXT_ATTR_FONT)) != 0; }
-
-    bool HasParagraphSpacingAfter() const { return (m_flags & wxTEXT_ATTR_PARA_SPACING_AFTER) != 0; }
-    bool HasParagraphSpacingBefore() const { return (m_flags & wxTEXT_ATTR_PARA_SPACING_BEFORE) != 0; }
-    bool HasLineSpacing() const { return (m_flags & wxTEXT_ATTR_LINE_SPACING) != 0; }
-    bool HasCharacterStyleName() const { return (m_flags & wxTEXT_ATTR_CHARACTER_STYLE_NAME) != 0; }
-    bool HasParagraphStyleName() const { return (m_flags & wxTEXT_ATTR_PARAGRAPH_STYLE_NAME) != 0; }
-    bool HasBulletStyle() const { return (m_flags & wxTEXT_ATTR_BULLET_STYLE) != 0; }
-    bool HasBulletNumber() const { return (m_flags & wxTEXT_ATTR_BULLET_NUMBER) != 0; }
-    bool HasBulletSymbol() const { return (m_flags & wxTEXT_ATTR_BULLET_SYMBOL) != 0; }
-
-    bool HasFlag(long flag) const { return (m_flags & flag) != 0; }
-
-    // Is this a character style?
-    bool IsCharacterStyle() const { return (0 != (GetFlags() & (wxTEXT_ATTR_FONT | wxTEXT_ATTR_BACKGROUND_COLOUR | wxTEXT_ATTR_TEXT_COLOUR))); }
-    bool IsParagraphStyle() const { return (0 != (GetFlags() & (wxTEXT_ATTR_ALIGNMENT|wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT|wxTEXT_ATTR_TABS|
-                            wxTEXT_ATTR_PARA_SPACING_BEFORE|wxTEXT_ATTR_PARA_SPACING_AFTER|wxTEXT_ATTR_LINE_SPACING|
-                            wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER))); }
-
-    // returns false if we have any attributes set, true otherwise
-    bool IsDefault() const
-    {
-        return !HasTextColour() && !HasBackgroundColour() && !HasFont() && !HasAlignment() &&
-               !HasTabs() && !HasLeftIndent() && !HasRightIndent() &&
-               !HasParagraphSpacingAfter() && !HasParagraphSpacingBefore() && !HasLineSpacing() &&
-               !HasCharacterStyleName() && !HasParagraphStyleName() && !HasBulletNumber() && !HasBulletStyle() && !HasBulletSymbol();
-    }
-
-    // return the attribute having the valid font and colours: it uses the
-    // attributes set in attr and falls back first to attrDefault and then to
-    // the text control font/colours for those attributes which are not set
-    static wxRichTextAttr Combine(const wxRichTextAttr& attr,
-                              const wxRichTextAttr& attrDef,
-                              const wxTextCtrlBase *text);
-private:
-    long                m_flags;
-
-    // Paragraph styles
-    wxArrayInt          m_tabs; // array of int: tab stops in 1/10 mm
-    int                 m_leftIndent; // left indent in 1/10 mm
-    int                 m_leftSubIndent; // left indent for all but the first
-                                         // line in a paragraph relative to the
-                                         // first line, in 1/10 mm
-    int                 m_rightIndent; // right indent in 1/10 mm
-    wxTextAttrAlignment m_textAlignment;
-
-    int                 m_paragraphSpacingAfter;
-    int                 m_paragraphSpacingBefore;
-    int                 m_lineSpacing;
-    int                 m_bulletStyle;
-    int                 m_bulletNumber;
-    wxChar              m_bulletSymbol;
-
-    // Character styles
-    wxColour            m_colText,
-                        m_colBack;
-    int                 m_fontSize;
-    int                 m_fontStyle;
-    int                 m_fontWeight;
-    bool                m_fontUnderlined;
-    wxString            m_fontFaceName;
-
-    // Character style
-    wxString            m_characterStyleName;
-
-    // Paragraph style
-    wxString            m_paragraphStyleName;
-};
-
-#define wxTEXT_ATTR_CHARACTER (wxTEXT_ATTR_FONT | wxTEXT_ATTR_BACKGROUND_COLOUR | wxTEXT_ATTR_TEXT_COLOUR)
-
-#define wxTEXT_ATTR_PARAGRAPH (wxTEXT_ATTR_ALIGNMENT|wxTEXT_ATTR_LEFT_INDENT|wxTEXT_ATTR_RIGHT_INDENT|wxTEXT_ATTR_TABS|\
-    wxTEXT_ATTR_PARA_SPACING_BEFORE|wxTEXT_ATTR_PARA_SPACING_AFTER|wxTEXT_ATTR_LINE_SPACING|\
-    wxTEXT_ATTR_BULLET_STYLE|wxTEXT_ATTR_BULLET_NUMBER|wxTEXT_ATTR_BULLET_SYMBOL)
-
-#define wxTEXT_ATTR_ALL (wxTEXT_ATTR_CHARACTER|wxTEXT_ATTR_PARAGRAPH)
-
 /*!
  * wxRichTextObject class declaration
  * This is the base for drawable objects.
 /*!
  * wxRichTextObject class declaration
  * This is the base for drawable objects.
@@ -559,7 +963,7 @@ public:
 
     /// Get the object size for the given range. Returns false if the range
     /// is invalid for this object.
 
     /// Get the object size for the given range. Returns false if the range
     /// is invalid for this object.
-    virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0)) const  = 0;
+    virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const  = 0;
 
     /// Do a split, returning an object containing the second part, and setting
     /// the first part in 'this'.
 
     /// Do a split, returning an object containing the second part, and setting
     /// the first part in 'this'.
@@ -574,6 +978,18 @@ public:
     /// Returns true if the object is empty
     virtual bool IsEmpty() const { return false; }
 
     /// Returns true if the object is empty
     virtual bool IsEmpty() const { return false; }
 
+    /// Whether this object floatable
+    virtual bool IsFloatable() const { return false; }
+
+    /// Whether this object is currently floating
+    virtual bool IsFloating() const { return GetAttributes().GetTextBoxAttr().IsFloating(); }
+
+    /// Whether this object is a place holding one
+    // virtual bool IsPlaceHolding() const { return false; }
+
+    /// The floating direction
+    virtual int GetFloatDirection() const { return GetAttributes().GetTextBoxAttr().GetFloatMode(); }
+
     /// Get any text in this object for the given range
     virtual wxString GetTextForRange(const wxRichTextRange& WXUNUSED(range)) const { return wxEmptyString; }
 
     /// Get any text in this object for the given range
     virtual wxString GetTextForRange(const wxRichTextRange& WXUNUSED(range)) const { return wxEmptyString; }
 
@@ -587,6 +1003,33 @@ public:
     /// Dump to output stream for debugging
     virtual void Dump(wxTextOutputStream& stream);
 
     /// Dump to output stream for debugging
     virtual void Dump(wxTextOutputStream& stream);
 
+    /// Can we edit properties via a GUI?
+    virtual bool CanEditProperties() const { return false; }
+
+    /// Edit properties via a GUI
+    virtual bool EditProperties(wxWindow* WXUNUSED(parent), wxRichTextBuffer* WXUNUSED(buffer)) { return false; }
+
+#if wxUSE_XML
+    /// Import this object from XML
+    virtual bool ImportFromXML(wxRichTextBuffer* buffer, wxXmlNode* node, wxRichTextXMLHandler* handler);
+#endif
+
+#if wxRICHTEXT_HAVE_DIRECT_OUTPUT
+    /// Export this object directly to the given stream.
+    virtual bool ExportXML(wxOutputStream& stream, int indent, wxRichTextXMLHandler* handler);
+#endif
+
+#if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
+    /// Export this object to the given parent node, usually creating at least one child node.
+    virtual bool ExportXML(wxXmlNode* parent, wxRichTextXMLHandler* handler);
+#endif
+
+    /// Does this object take note of paragraph attributes? Text and image objects don't.
+    virtual bool UsesParagraphAttributes() const { return true; }
+    
+    /// What is the XML node name of this object?
+    virtual wxString GetXMLNodeName() const { return wxT("unknown"); }
+
 // Accessors
 
     /// Get/set the cached object size as calculated by Layout.
 // Accessors
 
     /// Get/set the cached object size as calculated by Layout.
@@ -626,15 +1069,23 @@ public:
     virtual int GetTopMargin() const { return m_topMargin; }
     virtual int GetBottomMargin() const { return m_bottomMargin; }
 
     virtual int GetTopMargin() const { return m_topMargin; }
     virtual int GetBottomMargin() const { return m_bottomMargin; }
 
-    /// Set attributes object
-    void SetAttributes(const wxTextAttrEx& attr) { m_attributes = attr; }
-    const wxTextAttrEx& GetAttributes() const { return m_attributes; }
-    wxTextAttrEx& GetAttributes() { return m_attributes; }
+    /// Set/get attributes object
+    void SetAttributes(const wxRichTextAttr& attr) { m_attributes = attr; }
+    const wxRichTextAttr& GetAttributes() const { return m_attributes; }
+    wxRichTextAttr& GetAttributes() { return m_attributes; }
+    
+    /// Set/get properties
+    wxRichTextProperties& GetProperties() { return m_properties; }
+    const wxRichTextProperties& GetProperties() const { return m_properties; }
+    void SetProperties(const wxRichTextProperties& props) { m_properties = props; }
 
     /// Set/get stored descent
     void SetDescent(int descent) { m_descent = descent; }
     int GetDescent() const { return m_descent; }
 
 
     /// Set/get stored descent
     void SetDescent(int descent) { m_descent = descent; }
     int GetDescent() const { return m_descent; }
 
+    /// Gets the containing buffer
+    wxRichTextBuffer* GetBuffer() const;
+
 // Operations
 
     /// Clone the object
 // Operations
 
     /// Clone the object
@@ -648,8 +1099,27 @@ public:
     void Reference() { m_refCount ++; }
     void Dereference();
 
     void Reference() { m_refCount ++; }
     void Dereference();
 
-    /// Convert units in tends of a millimetre to device units
-    int ConvertTenthsMMToPixels(wxDC& dc, int units);
+    /// Convert units in tenths of a millimetre to device units
+    int ConvertTenthsMMToPixels(wxDC& dc, int units) const;
+    static int ConvertTenthsMMToPixels(int ppi, int units, double scale = 1.0);
+
+    /// Convert units in pixels to tenths of a millimetre
+    int ConvertPixelsToTenthsMM(wxDC& dc, int pixels) const;
+    static int ConvertPixelsToTenthsMM(int ppi, int pixels, double scale = 1.0);
+    
+    /// Draw the borders and background for the given rectangle and attributes.
+    /// Width and height are taken to be the content size, so excluding any
+    /// border, margin and padding.
+    static bool DrawBoxAttributes(wxDC& dc, const wxRichTextAttr& attr, const wxRect& boxRect);
+
+    /// Draw a border
+    static bool DrawBorder(wxDC& dc, const wxTextAttrBorders& attr, const wxRect& rect);
+
+    /// Get the various rectangles of the box model in pixels. You can either specify contentRect (inner)
+    /// or marginRect (outer), and the other must be the default rectangle (no width or height).
+    /// Note that the outline doesn't affect the position of the rectangle, it's drawn in whatever space
+    /// is available.
+    static bool GetBoxRects(wxDC& dc, const wxRichTextAttr& attr, wxRect& marginRect, wxRect& borderRect, wxRect& contentRect, wxRect& paddingRect, wxRect& outlineRect);
 
 protected:
     wxSize                  m_size;
 
 protected:
     wxSize                  m_size;
@@ -669,7 +1139,10 @@ protected:
     int                     m_bottomMargin;
 
     /// Attributes
     int                     m_bottomMargin;
 
     /// Attributes
-    wxTextAttrEx            m_attributes;
+    wxRichTextAttr          m_attributes;
+    
+    /// Properties
+    wxRichTextProperties    m_properties;
 };
 
 WX_DECLARE_LIST_WITH_DECL( wxRichTextObject, wxRichTextObjectList, class WXDLLIMPEXP_RICHTEXT );
 };
 
 WX_DECLARE_LIST_WITH_DECL( wxRichTextObject, wxRichTextObjectList, class WXDLLIMPEXP_RICHTEXT );
@@ -736,6 +1209,9 @@ public:
     /// Copy
     void Copy(const wxRichTextCompositeObject& obj);
 
     /// Copy
     void Copy(const wxRichTextCompositeObject& obj);
 
+    /// Assignment
+    void operator= (const wxRichTextCompositeObject& obj) { Copy(obj); }
+
     /// Append a child, returning the position
     size_t AppendChild(wxRichTextObject* child) ;
 
     /// Append a child, returning the position
     size_t AppendChild(wxRichTextObject* child) ;
 
@@ -749,67 +1225,33 @@ public:
     bool DeleteChildren() ;
 
     /// Recursively merge all pieces that can be merged.
     bool DeleteChildren() ;
 
     /// Recursively merge all pieces that can be merged.
-    bool Defragment();
+    bool Defragment(const wxRichTextRange& range = wxRICHTEXT_ALL);
 
 protected:
     wxRichTextObjectList    m_children;
 };
 
 
 protected:
     wxRichTextObjectList    m_children;
 };
 
-/*!
- * wxRichTextBox class declaration
- * This defines a 2D space to lay out objects
- */
-
-class WXDLLIMPEXP_RICHTEXT wxRichTextBox: public wxRichTextCompositeObject
-{
-    DECLARE_DYNAMIC_CLASS(wxRichTextBox)
-public:
-// Constructors
-
-    wxRichTextBox(wxRichTextObject* parent = NULL);
-    wxRichTextBox(const wxRichTextBox& obj): wxRichTextCompositeObject() { Copy(obj); }
-
-// Overrideables
-
-    /// Draw the item
-    virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int style);
-
-    /// Lay the item out
-    virtual bool Layout(wxDC& dc, const wxRect& rect, int style);
-
-    /// Get/set the object size for the given range. Returns false if the range
-    /// is invalid for this object.
-    virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0)) const;
-
-// Accessors
-
-// Operations
-
-    /// Clone
-    virtual wxRichTextObject* Clone() const { return new wxRichTextBox(*this); }
-
-    /// Copy
-    void Copy(const wxRichTextBox& obj);
-
-protected:
-};
-
 /*!
  * wxRichTextParagraphBox class declaration
  * This box knows how to lay out paragraphs.
  */
 
 /*!
  * wxRichTextParagraphBox class declaration
  * This box knows how to lay out paragraphs.
  */
 
-class WXDLLIMPEXP_RICHTEXT wxRichTextParagraphLayoutBox: public wxRichTextBox
+class WXDLLIMPEXP_RICHTEXT wxRichTextParagraphLayoutBox: public wxRichTextCompositeObject
 {
     DECLARE_DYNAMIC_CLASS(wxRichTextParagraphLayoutBox)
 public:
 // Constructors
 
     wxRichTextParagraphLayoutBox(wxRichTextObject* parent = NULL);
 {
     DECLARE_DYNAMIC_CLASS(wxRichTextParagraphLayoutBox)
 public:
 // Constructors
 
     wxRichTextParagraphLayoutBox(wxRichTextObject* parent = NULL);
-    wxRichTextParagraphLayoutBox(const wxRichTextParagraphLayoutBox& obj):wxRichTextBox() { Init(); Copy(obj); }
+    wxRichTextParagraphLayoutBox(const wxRichTextParagraphLayoutBox& obj): wxRichTextCompositeObject() { Init(); Copy(obj); }
+    ~wxRichTextParagraphLayoutBox();
 
 // Overrideables
 
 
 // Overrideables
 
+    /// Hit-testing: returns a flag indicating hit test details, plus
+    /// information about position
+    virtual int HitTest(wxDC& dc, const wxPoint& pt, long& textPosition);
+
     /// Draw the item
     virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int style);
 
     /// Draw the item
     virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int style);
 
@@ -818,7 +1260,7 @@ public:
 
     /// 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.
-    virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0)) const;
+    virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const;
 
     /// Delete range
     virtual bool DeleteRange(const wxRichTextRange& range);
 
     /// Delete range
     virtual bool DeleteRange(const wxRichTextRange& range);
@@ -826,6 +1268,24 @@ public:
     /// Get any text in this object for the given range
     virtual wxString GetTextForRange(const wxRichTextRange& range) const;
 
     /// Get any text in this object for the given range
     virtual wxString GetTextForRange(const wxRichTextRange& range) const;
 
+#if wxUSE_XML
+    /// Import this object from XML
+    virtual bool ImportFromXML(wxRichTextBuffer* buffer, wxXmlNode* node, wxRichTextXMLHandler* handler);
+#endif
+
+#if wxRICHTEXT_HAVE_DIRECT_OUTPUT
+    /// Export this object directly to the given stream.
+    virtual bool ExportXML(wxOutputStream& stream, int indent, wxRichTextXMLHandler* handler);
+#endif
+
+#if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
+    /// Export this object to the given parent node, usually creating at least one child node.
+    virtual bool ExportXML(wxXmlNode* parent, wxRichTextXMLHandler* handler);
+#endif
+
+    /// What is the XML node name of this object?
+    virtual wxString GetXMLNodeName() const { return wxT("paragraphlayout"); }
+
 // Accessors
 
     /// Associate a control with the buffer, for operations that for example require refreshing the window.
 // Accessors
 
     /// Associate a control with the buffer, for operations that for example require refreshing the window.
@@ -834,7 +1294,20 @@ public:
     /// Get the associated control.
     wxRichTextCtrl* GetRichTextCtrl() const { return m_ctrl; }
 
     /// Get the associated control.
     wxRichTextCtrl* GetRichTextCtrl() const { return m_ctrl; }
 
+    /// Get/set whether the last paragraph is partial or complete
+    void SetPartialParagraph(bool partialPara) { m_partialParagraph = partialPara; }
+    bool GetPartialParagraph() const { return m_partialParagraph; }
+
+    /// If this is a buffer, returns the current style sheet. The base layout box
+    /// class doesn't have an associated style sheet.
+    virtual wxRichTextStyleSheet* GetStyleSheet() const { return NULL; }
+
 // Operations
 // Operations
+    /// Draw the floats of this buffer
+    void DrawFloats(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int style);
+
+    /// Move an anchored object to another paragraph
+    void MoveAnchoredObjectToParagraph(wxRichTextParagraph* from, wxRichTextParagraph* to, wxRichTextObject* obj);
 
     /// Initialize the object.
     void Init();
 
     /// Initialize the object.
     void Init();
@@ -846,13 +1319,13 @@ public:
     virtual void Reset();
 
     /// Convenience function to add a paragraph of text
     virtual void Reset();
 
     /// Convenience function to add a paragraph of text
-    virtual wxRichTextRange AddParagraph(const wxString& text);
+    virtual wxRichTextRange AddParagraph(const wxString& text, wxRichTextAttr* paraStyle = NULL);
 
     /// Convenience function to add an image
 
     /// Convenience function to add an image
-    virtual wxRichTextRange AddImage(const wxImage& image);
+    virtual wxRichTextRange AddImage(const wxImage& image, wxRichTextAttr* paraStyle = NULL);
 
     /// Adds multiple paragraphs, based on newlines.
 
     /// Adds multiple paragraphs, based on newlines.
-    virtual wxRichTextRange AddParagraphs(const wxString& text);
+    virtual wxRichTextRange AddParagraphs(const wxString& text, wxRichTextAttr* paraStyle = NULL);
 
     /// Get the line at the given position. If caretPosition is true, the position is
     /// a caret position, which is normally a smaller number.
 
     /// Get the line at the given position. If caretPosition is true, the position is
     /// a caret position, which is normally a smaller number.
@@ -891,7 +1364,7 @@ public:
     virtual int GetParagraphLength(long paragraphNumber) const;
 
     /// Get the number of paragraphs
     virtual int GetParagraphLength(long paragraphNumber) const;
 
     /// Get the number of paragraphs
-    virtual int GetParagraphCount() const { return GetChildCount(); }
+    virtual int GetParagraphCount() const { return static_cast<int>(GetChildCount()); }
 
     /// Get the number of visible lines
     virtual int GetLineCount() const;
 
     /// Get the number of visible lines
     virtual int GetLineCount() const;
@@ -906,25 +1379,63 @@ public:
     virtual bool PositionToXY(long pos, long* x, long* y) const;
 
     /// Set text attributes: character and/or paragraph styles.
     virtual bool PositionToXY(long pos, long* x, long* y) const;
 
     /// Set text attributes: character and/or paragraph styles.
-    virtual bool SetStyle(const wxRichTextRange& range, const wxRichTextAttr& style, bool withUndo = true);
-    virtual bool SetStyle(const wxRichTextRange& range, const wxTextAttrEx& style, bool withUndo = true);
+    virtual bool SetStyle(const wxRichTextRange& range, const wxRichTextAttr& style, int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO);
+
+    /// Set image attribute
+    void SetImageStyle(wxRichTextImage *image, const wxRichTextAttr& textAttr, int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO);
+
+    /// Get the conbined text attributes for this position.
+    virtual bool GetStyle(long position, wxRichTextAttr& style);
 
 
-    /// Get the text attributes for this position.
-    virtual bool GetStyle(long position, wxTextAttrEx& style) const;
-    virtual bool GetStyle(long position, wxRichTextAttr& style) const;
+    /// Get the content (uncombined) attributes for this position.
+    virtual bool GetUncombinedStyle(long position, wxRichTextAttr& style);
+
+    /// Implementation helper for GetStyle. If combineStyles is true, combine base, paragraph and
+    /// context attributes.
+    virtual bool DoGetStyle(long position, wxRichTextAttr& style, bool combineStyles = true);
+
+    /// Get the combined style for a range - if any attribute is different within the range,
+    /// that attribute is not present within the flags
+    virtual bool GetStyleForRange(const wxRichTextRange& range, wxRichTextAttr& style);
+
+    /// Combines 'style' with 'currentStyle' for the purpose of summarising the attributes of a range of
+    /// content.
+    bool CollectStyle(wxRichTextAttr& currentStyle, const wxRichTextAttr& style, wxRichTextAttr& clashingAttr, wxRichTextAttr& absentAttr);
+
+    /// Set list style
+    virtual bool SetListStyle(const wxRichTextRange& range, wxRichTextListStyleDefinition* def, int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO, int startFrom = 1, int specifiedLevel = -1);
+    virtual bool SetListStyle(const wxRichTextRange& range, const wxString& defName, int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO, int startFrom = 1, int specifiedLevel = -1);
+
+    /// Clear list for given range
+    virtual bool ClearListStyle(const wxRichTextRange& range, int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO);
+
+    /// Number/renumber any list elements in the given range.
+    /// def/defName can be NULL/empty to indicate that the existing list style should be used.
+    virtual bool NumberList(const wxRichTextRange& range, wxRichTextListStyleDefinition* def = NULL, int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO, int startFrom = 1, int specifiedLevel = -1);
+    virtual bool NumberList(const wxRichTextRange& range, const wxString& defName, int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO, int startFrom = 1, int specifiedLevel = -1);
+
+    /// Promote the list items within the given range. promoteBy can be a positive or negative number, e.g. 1 or -1
+    /// def/defName can be NULL/empty to indicate that the existing list style should be used.
+    virtual bool PromoteList(int promoteBy, const wxRichTextRange& range, wxRichTextListStyleDefinition* def = NULL, int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO, int specifiedLevel = -1);
+    virtual bool PromoteList(int promoteBy, const wxRichTextRange& range, const wxString& defName, int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO, int specifiedLevel = -1);
+
+    /// Helper for NumberList and PromoteList, that does renumbering and promotion simultaneously
+    /// def/defName can be NULL/empty to indicate that the existing list style should be used.
+    virtual bool DoNumberList(const wxRichTextRange& range, const wxRichTextRange& promotionRange, int promoteBy, wxRichTextListStyleDefinition* def, int flags = wxRICHTEXT_SETSTYLE_WITH_UNDO, int startFrom = 1, int specifiedLevel = -1);
+
+    /// Fills in the attributes for numbering a paragraph after previousParagraph.
+    virtual bool FindNextParagraphNumber(wxRichTextParagraph* previousParagraph, wxRichTextAttr& attr) const;
 
     /// Test if this whole range has character attributes of the specified kind. If any
     /// of the attributes are different within the range, the test fails. You
     /// can use this to implement, for example, bold button updating. style must have
     /// flags indicating which attributes are of interest.
 
     /// Test if this whole range has character attributes of the specified kind. If any
     /// of the attributes are different within the range, the test fails. You
     /// can use this to implement, for example, bold button updating. style must have
     /// flags indicating which attributes are of interest.
-    virtual bool HasCharacterAttributes(const wxRichTextRange& range, const wxTextAttrEx& style) const;
     virtual bool HasCharacterAttributes(const wxRichTextRange& range, const wxRichTextAttr& style) const;
 
     /// Test if this whole range has paragraph attributes of the specified kind. If any
     /// of the attributes are different within the range, the test fails. You
     /// can use this to implement, for example, centering button updating. style must have
     /// flags indicating which attributes are of interest.
     virtual bool HasCharacterAttributes(const wxRichTextRange& range, const wxRichTextAttr& style) const;
 
     /// Test if this whole range has paragraph attributes of the specified kind. If any
     /// of the attributes are different within the range, the test fails. You
     /// can use this to implement, for example, centering button updating. style must have
     /// flags indicating which attributes are of interest.
-    virtual bool HasParagraphAttributes(const wxRichTextRange& range, const wxTextAttrEx& style) const;
     virtual bool HasParagraphAttributes(const wxRichTextRange& range, const wxRichTextAttr& style) const;
 
     /// Clone
     virtual bool HasParagraphAttributes(const wxRichTextRange& range, const wxRichTextAttr& style) const;
 
     /// Clone
@@ -933,14 +1444,20 @@ public:
     /// Insert fragment into this box at the given position. If partialParagraph is true,
     /// it is assumed that the last (or only) paragraph is just a piece of data with no paragraph
     /// marker.
     /// Insert fragment into this box at the given position. If partialParagraph is true,
     /// it is assumed that the last (or only) paragraph is just a piece of data with no paragraph
     /// marker.
-    virtual bool InsertFragment(long position, wxRichTextFragment& fragment);
+    virtual bool InsertFragment(long position, wxRichTextParagraphLayoutBox& fragment);
 
     /// 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'.
-    virtual bool CopyFragment(const wxRichTextRange& range, wxRichTextFragment& fragment);
+    virtual bool CopyFragment(const wxRichTextRange& range, wxRichTextParagraphLayoutBox& fragment);
+
+    /// Apply the style sheet to the buffer, for example if the styles have changed.
+    virtual bool ApplyStyleSheet(wxRichTextStyleSheet* styleSheet);
 
     /// Copy
     void Copy(const wxRichTextParagraphLayoutBox& obj);
 
 
     /// Copy
     void Copy(const wxRichTextParagraphLayoutBox& obj);
 
+    /// Assignment
+    void operator= (const wxRichTextParagraphLayoutBox& obj) { Copy(obj); }
+
     /// Calculate ranges
     virtual void UpdateRanges() { long end; CalculateRange(0, end); }
 
     /// Calculate ranges
     virtual void UpdateRanges() { long end; CalculateRange(0, end); }
 
@@ -949,70 +1466,82 @@ public:
 
     /// Set default style for new content. Setting it to a default attribute
     /// makes new content take on the 'basic' style.
 
     /// Set default style for new content. Setting it to a default attribute
     /// makes new content take on the 'basic' style.
-    virtual bool SetDefaultStyle(const wxTextAttrEx& style);
+    virtual bool SetDefaultStyle(const wxRichTextAttr& style);
 
     /// Get default style
 
     /// Get default style
-    virtual const wxTextAttrEx& GetDefaultStyle() const { return m_defaultAttributes; }
+    virtual const wxRichTextAttr& GetDefaultStyle() const { return m_defaultAttributes; }
 
     /// Set basic (overall) style
 
     /// Set basic (overall) style
-    virtual void SetBasicStyle(const wxTextAttrEx& style) { m_attributes = style; }
-    virtual void SetBasicStyle(const wxRichTextAttr& style) { style.CopyTo(m_attributes); }
+    virtual void SetBasicStyle(const wxRichTextAttr& style) { m_attributes = style; }
 
     /// Get basic (overall) style
 
     /// Get basic (overall) style
-    virtual const wxTextAttrEx& GetBasicStyle() const { return m_attributes; }
+    virtual const wxRichTextAttr& GetBasicStyle() const { return m_attributes; }
 
     /// Invalidate the buffer. With no argument, invalidates whole buffer.
     void Invalidate(const wxRichTextRange& invalidRange = wxRICHTEXT_ALL);
 
 
     /// Invalidate the buffer. With no argument, invalidates whole buffer.
     void Invalidate(const wxRichTextRange& invalidRange = wxRICHTEXT_ALL);
 
+    /// Gather information about floating objects. If untilObj is non-NULL,
+    /// will stop getting information if the current object is this, since we
+    /// will collect the rest later.
+    virtual bool UpdateFloatingObjects(int width, wxRichTextObject* untilObj = NULL);
+
     /// Get invalid range, rounding to entire paragraphs if argument is true.
     wxRichTextRange GetInvalidRange(bool wholeParagraphs = false) const;
 
     /// Get invalid range, rounding to entire paragraphs if argument is true.
     wxRichTextRange GetInvalidRange(bool wholeParagraphs = false) const;
 
+    /// Get the wxRichTextFloatCollector of this object
+    wxRichTextFloatCollector* GetFloatCollector() { return m_floatCollector; }
+
 protected:
     wxRichTextCtrl* m_ctrl;
 protected:
     wxRichTextCtrl* m_ctrl;
-    wxTextAttrEx    m_defaultAttributes;
+    wxRichTextAttr  m_defaultAttributes;
 
     /// The invalidated range that will need full layout
 
     /// The invalidated range that will need full layout
-    wxRichTextRange         m_invalidRange;
+    wxRichTextRange m_invalidRange;
+
+    // Is the last paragraph partial or complete?
+    bool            m_partialParagraph;
+
+    // The floating layout state
+    wxRichTextFloatCollector* m_floatCollector;
 };
 
 /*!
 };
 
 /*!
- * wxRichTextFragment class declaration
- * This is a lind of paragraph layout box used for storing
- * paragraphs for Undo/Redo, for example.
+ * wxRichTextBox class declaration
+ * TODO: a floating text box
  */
 
  */
 
-class WXDLLIMPEXP_RICHTEXT wxRichTextFragment: public wxRichTextParagraphLayoutBox
+class WXDLLIMPEXP_RICHTEXT wxRichTextBox: public wxRichTextCompositeObject
 {
 {
-    DECLARE_DYNAMIC_CLASS(wxRichTextFragment)
+    DECLARE_DYNAMIC_CLASS(wxRichTextBox)
 public:
 // Constructors
 
 public:
 // Constructors
 
-    wxRichTextFragment() { Init(); }
-    wxRichTextFragment(const wxRichTextFragment& obj):wxRichTextParagraphLayoutBox() { Init(); Copy(obj); }
+    wxRichTextBox(wxRichTextObject* parent = NULL);
+    wxRichTextBox(const wxRichTextBox& obj): wxRichTextCompositeObject() { Copy(obj); }
 
 
-// Accessors
+// Overrideables
 
 
-    /// Get/set whether the last paragraph is partial or complete
-    void SetPartialParagraph(bool partialPara) { m_partialParagraph = partialPara; }
-    bool GetPartialParagraph() const { return m_partialParagraph; }
+    /// Draw the item
+    virtual bool Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int style);
 
 
-// Overrideables
+    /// Lay the item out
+    virtual bool Layout(wxDC& dc, const wxRect& rect, int style);
 
 
-// Operations
+    /// Get/set the object size for the given range. Returns false if the range
+    /// is invalid for this object.
+    virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const;
 
 
-    /// Initialise
-    void Init();
+// Accessors
 
 
-    /// Copy
-    void Copy(const wxRichTextFragment& obj);
+// Operations
 
     /// Clone
 
     /// Clone
-    virtual wxRichTextObject* Clone() const { return new wxRichTextFragment(*this); }
+    virtual wxRichTextObject* Clone() const { return new wxRichTextBox(*this); }
 
 
-protected:
+    /// Copy
+    void Copy(const wxRichTextBox& obj);
 
 
-    // Is the last paragraph partial or complete?
-    bool        m_partialParagraph;
+protected:
 };
 
 /*!
 };
 
 /*!
@@ -1067,6 +1596,11 @@ public:
     void SetDescent(int descent) { m_descent = descent; }
     int GetDescent() const { return m_descent; }
 
     void SetDescent(int descent) { m_descent = descent; }
     int GetDescent() const { return m_descent; }
 
+#if wxRICHTEXT_USE_OPTIMIZED_LINE_DRAWING
+    wxArrayInt& GetObjectSizes() { return m_objectSizes; }
+    const wxArrayInt& GetObjectSizes() const { return m_objectSizes; }
+#endif
+
 // Operations
 
     /// Initialisation
 // Operations
 
     /// Initialisation
@@ -1093,6 +1627,10 @@ protected:
 
     // The parent object
     wxRichTextParagraph* m_parent;
 
     // The parent object
     wxRichTextParagraph* m_parent;
+
+#if wxRICHTEXT_USE_OPTIMIZED_LINE_DRAWING
+    wxArrayInt          m_objectSizes;
+#endif
 };
 
 WX_DECLARE_LIST_WITH_DECL( wxRichTextLine, wxRichTextLineList , class WXDLLIMPEXP_RICHTEXT );
 };
 
 WX_DECLARE_LIST_WITH_DECL( wxRichTextLine, wxRichTextLineList , class WXDLLIMPEXP_RICHTEXT );
@@ -1108,10 +1646,10 @@ class WXDLLIMPEXP_RICHTEXT wxRichTextParagraph: public wxRichTextBox
 public:
 // Constructors
 
 public:
 // Constructors
 
-    wxRichTextParagraph(wxRichTextObject* parent = NULL, wxTextAttrEx* style = NULL);
-    wxRichTextParagraph(const wxString& text, wxRichTextObject* parent = NULL, wxTextAttrEx* style = NULL);
+    wxRichTextParagraph(wxRichTextObject* parent = NULL, wxRichTextAttr* style = NULL);
+    wxRichTextParagraph(const wxString& text, wxRichTextObject* parent = NULL, wxRichTextAttr* paraStyle = NULL, wxRichTextAttr* charStyle = NULL);
     virtual ~wxRichTextParagraph();
     virtual ~wxRichTextParagraph();
-    wxRichTextParagraph(const wxRichTextParagraph& obj):wxRichTextBox() { Copy(obj); }
+    wxRichTextParagraph(const wxRichTextParagraph& obj): wxRichTextBox() { Copy(obj); }
 
 // Overrideables
 
 
 // Overrideables
 
@@ -1123,7 +1661,7 @@ public:
 
     /// 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.
-    virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0)) const;
+    virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const;
 
     /// Finds the absolute position and row height for the given character position
     virtual bool FindPosition(wxDC& dc, long index, wxPoint& pt, int* height, bool forceLineStart);
 
     /// Finds the absolute position and row height for the given character position
     virtual bool FindPosition(wxDC& dc, long index, wxPoint& pt, int* height, bool forceLineStart);
@@ -1135,6 +1673,9 @@ public:
     /// Calculate range
     virtual void CalculateRange(long start, long& end);
 
     /// Calculate range
     virtual void CalculateRange(long start, long& end);
 
+    /// What is the XML node name of this object?
+    virtual wxString GetXMLNodeName() const { return wxT("paragraph"); }
+
 // Accessors
 
     /// Get the cached lines
 // Accessors
 
     /// Get the cached lines
@@ -1154,7 +1695,7 @@ public:
 // Implementation
 
     /// Apply paragraph styles such as centering to the wrapped lines
 // Implementation
 
     /// Apply paragraph styles such as centering to the wrapped lines
-    virtual void ApplyParagraphStyle(const wxRect& rect);
+    virtual void ApplyParagraphStyle(const wxRichTextAttr& attr, const wxRect& rect, wxDC& dc);
 
     /// Insert text at the given position
     virtual bool InsertText(long pos, const wxString& text);
 
     /// Insert text at the given position
     virtual bool InsertText(long pos, const wxString& text);
@@ -1175,7 +1716,7 @@ public:
 
     /// Find a suitable wrap position. wrapPosition is the last position in the line to the left
     /// of the split.
 
     /// Find a suitable wrap position. wrapPosition is the last position in the line to the left
     /// of the split.
-    bool FindWrapPosition(const wxRichTextRange& range, wxDC& dc, int availableSpace, long& wrapPosition);
+    bool FindWrapPosition(const wxRichTextRange& range, wxDC& dc, int availableSpace, long& wrapPosition, wxArrayInt* partialExtents);
 
     /// Find the object at the given position
     wxRichTextObject* FindObjectAtPosition(long position);
 
     /// Find the object at the given position
     wxRichTextObject* FindObjectAtPosition(long position);
@@ -1189,9 +1730,36 @@ public:
     /// Clear remaining unused line objects, if any
     bool ClearUnusedLines(int lineCount);
 
     /// Clear remaining unused line objects, if any
     bool ClearUnusedLines(int lineCount);
 
+    /// Get combined attributes of the base style, paragraph style and character style. We use this to dynamically
+    /// retrieve the actual style.
+    wxRichTextAttr GetCombinedAttributes(const wxRichTextAttr& contentStyle) const;
+
+    /// Get combined attributes of the base style and paragraph style.
+    wxRichTextAttr GetCombinedAttributes() const;
+
+    /// Get the first position from pos that has a line break character.
+    long GetFirstLineBreakPosition(long pos);
+
+    /// Create default tabstop array
+    static void InitDefaultTabs();
+
+    /// Clear default tabstop array
+    static void ClearDefaultTabs();
+
+    /// Get default tabstop array
+    static const wxArrayInt& GetDefaultTabs() { return sm_defaultTabs; }
+
+    /// Layout the floats object
+    void LayoutFloat(wxDC& dc, const wxRect& rect, int style, wxRichTextFloatCollector* floatCollector);
+
 protected:
     /// The lines that make up the wrapped paragraph
     wxRichTextLineList m_cachedLines;
 protected:
     /// The lines that make up the wrapped paragraph
     wxRichTextLineList m_cachedLines;
+
+    /// Default tabstops
+    static wxArrayInt  sm_defaultTabs;
+
+friend class wxRichTextFloatCollector;
 };
 
 /*!
 };
 
 /*!
@@ -1205,8 +1773,8 @@ class WXDLLIMPEXP_RICHTEXT wxRichTextPlainText: public wxRichTextObject
 public:
 // Constructors
 
 public:
 // Constructors
 
-    wxRichTextPlainText(const wxString& text = wxEmptyString, wxRichTextObject* parent = NULL, wxTextAttrEx* style = NULL);
-    wxRichTextPlainText(const wxRichTextPlainText& obj):wxRichTextObject() { Copy(obj); }
+    wxRichTextPlainText(const wxString& text = wxEmptyString, wxRichTextObject* parent = NULL, wxRichTextAttr* style = NULL);
+    wxRichTextPlainText(const wxRichTextPlainText& obj): wxRichTextObject() { Copy(obj); }
 
 // Overrideables
 
 
 // Overrideables
 
@@ -1218,7 +1786,7 @@ public:
 
     /// 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.
-    virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position/* = wxPoint(0,0)*/) const;
+    virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const;
 
     /// Get any text in this object for the given range
     virtual wxString GetTextForRange(const wxRichTextRange& range) const;
 
     /// Get any text in this object for the given range
     virtual wxString GetTextForRange(const wxRichTextRange& range) const;
@@ -1246,6 +1814,30 @@ public:
     /// Dump to output stream for debugging
     virtual void Dump(wxTextOutputStream& stream);
 
     /// Dump to output stream for debugging
     virtual void Dump(wxTextOutputStream& stream);
 
+    /// Get the first position from pos that has a line break character.
+    long GetFirstLineBreakPosition(long pos);
+
+    /// Does this object take note of paragraph attributes? Text and image objects don't.
+    virtual bool UsesParagraphAttributes() const { return false; }
+
+#if wxUSE_XML
+    /// Import this object from XML
+    virtual bool ImportFromXML(wxRichTextBuffer* buffer, wxXmlNode* node, wxRichTextXMLHandler* handler);
+#endif
+
+#if wxRICHTEXT_HAVE_DIRECT_OUTPUT
+    /// Export this object directly to the given stream.
+    virtual bool ExportXML(wxOutputStream& stream, int indent, wxRichTextXMLHandler* handler);
+#endif
+
+#if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
+    /// Export this object to the given parent node, usually creating at least one child node.
+    virtual bool ExportXML(wxXmlNode* parent, wxRichTextXMLHandler* handler);
+#endif
+
+    /// What is the XML node name of this object?
+    virtual wxString GetXMLNodeName() const { return wxT("text"); }
+
 // Accessors
 
     /// Get the text
 // Accessors
 
     /// Get the text
@@ -1262,7 +1854,7 @@ public:
     /// Clone
     virtual wxRichTextObject* Clone() const { return new wxRichTextPlainText(*this); }
 private:
     /// Clone
     virtual wxRichTextObject* Clone() const { return new wxRichTextPlainText(*this); }
 private:
-    bool DrawTabbedString(wxDC& dc,const wxRect& rect,wxString& str, wxCoord& x, wxCoord& y, bool selected);
+    bool DrawTabbedString(wxDC& dc, const wxRichTextAttr& attr, const wxRect& rect, wxString& str, wxCoord& x, wxCoord& y, bool selected);
 
 protected:
     wxString    m_text;
 
 protected:
     wxString    m_text;
@@ -1272,8 +1864,8 @@ protected:
  * wxRichTextImageBlock stores information about an image, in binary in-memory form
  */
 
  * wxRichTextImageBlock stores information about an image, in binary in-memory form
  */
 
-class WXDLLIMPEXP_BASE wxDataInputStream;
-class WXDLLIMPEXP_BASE wxDataOutputStream;
+class WXDLLIMPEXP_FWD_BASE wxDataInputStream;
+class WXDLLIMPEXP_FWD_BASE wxDataOutputStream;
 
 class WXDLLIMPEXP_RICHTEXT wxRichTextImageBlock: public wxObject
 {
 
 class WXDLLIMPEXP_RICHTEXT wxRichTextImageBlock: public wxObject
 {
@@ -1290,11 +1882,18 @@ public:
     // to conserve space.
     // If it's not a JPEG we can make use of 'image', already scaled, so we don't have to
     // load the image a 2nd time.
     // to conserve space.
     // If it's not a JPEG we can make use of 'image', already scaled, so we don't have to
     // load the image a 2nd time.
-    virtual bool MakeImageBlock(const wxString& filename, int imageType, wxImage& image, bool convertToJPEG = true);
+    virtual bool MakeImageBlock(const wxString& filename, wxBitmapType imageType,
+                                wxImage& image, bool convertToJPEG = true);
 
     // Make an image block from the wxImage in the given
     // format.
 
     // Make an image block from the wxImage in the given
     // format.
-    virtual bool MakeImageBlock(wxImage& image, int imageType, int quality = 80);
+    virtual bool MakeImageBlock(wxImage& image, wxBitmapType imageType, int quality = 80);
+
+    // Uses a const wxImage for efficiency, but can't set quality (only relevant for JPEG)
+    virtual bool MakeImageBlockDefaultQuality(const wxImage& image, wxBitmapType imageType);
+
+    // Makes the image block
+    virtual bool DoMakeImageBlock(const wxImage& image, wxBitmapType imageType);
 
     // Write to a file
     bool Write(const wxString& filename);
 
     // Write to a file
     bool Write(const wxString& filename);
@@ -1303,7 +1902,7 @@ public:
     bool WriteHex(wxOutputStream& stream);
 
     // Read data in hex from a stream
     bool WriteHex(wxOutputStream& stream);
 
     // Read data in hex from a stream
-    bool ReadHex(wxInputStream& stream, int length, int imageType);
+    bool ReadHex(wxInputStream& stream, int length, wxBitmapType imageType);
 
     // Copy from 'block'
     void Copy(const wxRichTextImageBlock& block);
 
     // Copy from 'block'
     void Copy(const wxRichTextImageBlock& block);
@@ -1318,17 +1917,21 @@ public:
 
     unsigned char* GetData() const { return m_data; }
     size_t GetDataSize() const { return m_dataSize; }
 
     unsigned char* GetData() const { return m_data; }
     size_t GetDataSize() const { return m_dataSize; }
-    int GetImageType() const { return m_imageType; }
+    wxBitmapType GetImageType() const { return m_imageType; }
 
     void SetData(unsigned char* image) { m_data = image; }
     void SetDataSize(size_t size) { m_dataSize = size; }
 
     void SetData(unsigned char* image) { m_data = image; }
     void SetDataSize(size_t size) { m_dataSize = size; }
-    void SetImageType(int imageType) { m_imageType = imageType; }
+    void SetImageType(wxBitmapType imageType) { m_imageType = imageType; }
 
 
-    bool Ok() const { return GetData() != NULL; }
+    bool Ok() const { return IsOk(); }
+    bool IsOk() const { return GetData() != NULL; }
+
+    // Gets the extension for the block's type
+    wxString GetExtension() const;
 
 /// Implementation
 
 
 /// Implementation
 
-    /// Allocate and read from stream as a block of memory
+    // Allocate and read from stream as a block of memory
     static unsigned char* ReadBlock(wxInputStream& stream, size_t size);
     static unsigned char* ReadBlock(const wxString& filename, size_t size);
 
     static unsigned char* ReadBlock(wxInputStream& stream, size_t size);
     static unsigned char* ReadBlock(const wxString& filename, size_t size);
 
@@ -1343,10 +1946,9 @@ protected:
     // This is in the raw, original form such as a JPEG file.
     unsigned char*      m_data;
     size_t              m_dataSize;
     // This is in the raw, original form such as a JPEG file.
     unsigned char*      m_data;
     size_t              m_dataSize;
-    int                 m_imageType; // wxWin type id
+    wxBitmapType        m_imageType;
 };
 
 };
 
-
 /*!
  * wxRichTextImage class declaration
  * This object represents an image.
 /*!
  * wxRichTextImage class declaration
  * This object represents an image.
@@ -1358,10 +1960,10 @@ class WXDLLIMPEXP_RICHTEXT wxRichTextImage: public wxRichTextObject
 public:
 // Constructors
 
 public:
 // Constructors
 
-    wxRichTextImage(wxRichTextObject* parent = NULL):wxRichTextObject(parent) { }
-    wxRichTextImage(const wxImage& image, wxRichTextObject* parent = NULL);
-    wxRichTextImage(const wxRichTextImageBlock& imageBlock, wxRichTextObject* parent = NULL);
-    wxRichTextImage(const wxRichTextImage& obj):wxRichTextObject() { Copy(obj); }
+    wxRichTextImage(wxRichTextObject* parent = NULL): wxRichTextObject(parent) { }
+    wxRichTextImage(const wxImage& image, wxRichTextObject* parent = NULL, wxRichTextAttr* charStyle = NULL);
+    wxRichTextImage(const wxRichTextImageBlock& imageBlock, wxRichTextObject* parent = NULL, wxRichTextAttr* charStyle = NULL);
+    wxRichTextImage(const wxRichTextImage& obj): wxRichTextObject(obj) { Copy(obj); }
 
 // Overrideables
 
 
 // Overrideables
 
@@ -1373,18 +1975,51 @@ public:
 
     /// Get the object size for the given range. Returns false if the range
     /// is invalid for this object.
 
     /// Get the object size for the given range. Returns false if the range
     /// is invalid for this object.
-    virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0)) const;
+    virtual bool GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position = wxPoint(0,0), wxArrayInt* partialExtents = NULL) const;
 
 
-    /// Returns true if the object is empty
-    virtual bool IsEmpty() const { return !m_image.Ok(); }
+    /// Returns true if the object is empty. An image is never empty; if the image is broken, that's not the same thing as empty.
+    virtual bool IsEmpty() const { return false; /* !m_imageBlock.Ok(); */ }
+
+    /// Can we edit properties via a GUI?
+    virtual bool CanEditProperties() const { return true; }
+
+    /// Edit properties via a GUI
+    virtual bool EditProperties(wxWindow* parent, wxRichTextBuffer* buffer);
+
+    /// Does this object take note of paragraph attributes? Text and image objects don't.
+    virtual bool UsesParagraphAttributes() const { return false; }
+
+#if wxUSE_XML
+    /// Import this object from XML
+    virtual bool ImportFromXML(wxRichTextBuffer* buffer, wxXmlNode* node, wxRichTextXMLHandler* handler);
+#endif
+
+#if wxRICHTEXT_HAVE_DIRECT_OUTPUT
+    /// Export this object directly to the given stream.
+    virtual bool ExportXML(wxOutputStream& stream, int indent, wxRichTextXMLHandler* handler);
+#endif
+
+#if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
+    /// Export this object to the given parent node, usually creating at least one child node.
+    virtual bool ExportXML(wxXmlNode* parent, wxRichTextXMLHandler* handler);
+#endif
+
+    // Images can be floatable (optionally).
+    virtual bool IsFloatable() const { return true; }
+
+    /// What is the XML node name of this object?
+    virtual wxString GetXMLNodeName() const { return wxT("image"); }
 
 // Accessors
 
 
 // Accessors
 
-    /// Get the image
-    const wxImage& GetImage() const { return m_image; }
+    /// Get the image cache (scaled bitmap)
+    const wxBitmap& GetImageCache() const { return m_imageCache; }
 
 
-    /// Set the image
-    void SetImage(const wxImage& image) { m_image = image; }
+    /// Set the image cache
+    void SetImageCache(const wxBitmap& bitmap) { m_imageCache = bitmap; }
+
+    /// Reset the image cache
+    void ResetImageCache() { m_imageCache = wxNullBitmap; }
 
     /// Get the image block containing the raw data
     wxRichTextImageBlock& GetImageBlock() { return m_imageBlock; }
 
     /// Get the image block containing the raw data
     wxRichTextImageBlock& GetImageBlock() { return m_imageBlock; }
@@ -1397,17 +2032,12 @@ public:
     /// Clone
     virtual wxRichTextObject* Clone() const { return new wxRichTextImage(*this); }
 
     /// Clone
     virtual wxRichTextObject* Clone() const { return new wxRichTextImage(*this); }
 
-    /// Load wxImage from the block
-    virtual bool LoadFromBlock();
-
-    /// Make block from the wxImage
-    virtual bool MakeBlock();
+    /// Create a cached image at the required size
+    virtual bool LoadImageCache(wxDC& dc, bool resetCache = false);
 
 protected:
 
 protected:
-    // TODO: reduce the multiple representations of data
-    wxImage                 m_image;
-    wxBitmap                m_bitmap;
     wxRichTextImageBlock    m_imageBlock;
     wxRichTextImageBlock    m_imageBlock;
+    wxBitmap                m_imageCache;
 };
 
 
 };
 
 
@@ -1416,8 +2046,8 @@ protected:
  * This is a kind of box, used to represent the whole buffer
  */
 
  * This is a kind of box, used to represent the whole buffer
  */
 
-class WXDLLIMPEXP_RICHTEXT wxRichTextCommand;
-class WXDLLIMPEXP_RICHTEXT wxRichTextAction;
+class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextCommand;
+class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextAction;
 
 class WXDLLIMPEXP_RICHTEXT wxRichTextBuffer: public wxRichTextParagraphLayoutBox
 {
 
 class WXDLLIMPEXP_RICHTEXT wxRichTextBuffer: public wxRichTextParagraphLayoutBox
 {
@@ -1426,7 +2056,7 @@ public:
 // Constructors
 
     wxRichTextBuffer() { Init(); }
 // Constructors
 
     wxRichTextBuffer() { Init(); }
-    wxRichTextBuffer(const wxRichTextBuffer& obj):wxRichTextParagraphLayoutBox() { Init(); Copy(obj); }
+    wxRichTextBuffer(const wxRichTextBuffer& obj): wxRichTextParagraphLayoutBox() { Init(); Copy(obj); }
     virtual ~wxRichTextBuffer() ;
 
 // Accessors
     virtual ~wxRichTextBuffer() ;
 
 // Accessors
@@ -1436,33 +2066,50 @@ public:
 
     /// Set style sheet, if any.
     void SetStyleSheet(wxRichTextStyleSheet* styleSheet) { m_styleSheet = styleSheet; }
 
     /// Set style sheet, if any.
     void SetStyleSheet(wxRichTextStyleSheet* styleSheet) { m_styleSheet = styleSheet; }
-    wxRichTextStyleSheet* GetStyleSheet() const { return m_styleSheet; }
+    virtual wxRichTextStyleSheet* GetStyleSheet() const { return m_styleSheet; }
+
+    /// Set style sheet and notify of the change
+    bool SetStyleSheetAndNotify(wxRichTextStyleSheet* sheet);
+
+    /// Push style sheet to top of stack
+    bool PushStyleSheet(wxRichTextStyleSheet* styleSheet);
+
+    /// Pop style sheet from top of stack
+    wxRichTextStyleSheet* PopStyleSheet();
+
+    /// Set/get table storing fonts
+    wxRichTextFontTable& GetFontTable() { return m_fontTable; }
+    const wxRichTextFontTable& GetFontTable() const { return m_fontTable; }
+    void SetFontTable(const wxRichTextFontTable& table) { m_fontTable = table; }
 
 // Operations
 
     /// Initialisation
     void Init();
 
 
 // Operations
 
     /// Initialisation
     void Init();
 
-    /// Clears the buffer and resets the command processor
-    virtual void Clear();
-
-    /// The same as Clear, and adds an empty paragraph.
-    virtual void Reset();
+    /// Clears the buffer, adds an empty paragraph, and clears the command processor.
+    virtual void ResetAndClearCommands();
 
     /// Load a file
 
     /// Load a file
-    virtual bool LoadFile(const wxString& filename, int type = wxRICHTEXT_TYPE_ANY);
+    virtual bool LoadFile(const wxString& filename, wxRichTextFileType type = wxRICHTEXT_TYPE_ANY);
 
     /// Save a file
 
     /// Save a file
-    virtual bool SaveFile(const wxString& filename, int type = wxRICHTEXT_TYPE_ANY);
+    virtual bool SaveFile(const wxString& filename, wxRichTextFileType type = wxRICHTEXT_TYPE_ANY);
 
     /// Load from a stream
 
     /// Load from a stream
-    virtual bool LoadFile(wxInputStream& stream, int type = wxRICHTEXT_TYPE_ANY);
+    virtual bool LoadFile(wxInputStream& stream, wxRichTextFileType type = wxRICHTEXT_TYPE_ANY);
 
     /// Save to a stream
 
     /// Save to a stream
-    virtual bool SaveFile(wxOutputStream& stream, int type = wxRICHTEXT_TYPE_ANY);
+    virtual bool SaveFile(wxOutputStream& stream, wxRichTextFileType type = wxRICHTEXT_TYPE_ANY);
+
+    /// Set the handler flags, controlling loading and saving
+    void SetHandlerFlags(int flags) { m_handlerFlags = flags; }
+
+    /// Get the handler flags, controlling loading and saving
+    int GetHandlerFlags() const { return m_handlerFlags; }
 
     /// Convenience function to add a paragraph of text
 
     /// Convenience function to add a paragraph of text
-    virtual wxRichTextRange AddParagraph(const wxString& text) { Modify(); return wxRichTextParagraphLayoutBox::AddParagraph(text); }
+    virtual wxRichTextRange AddParagraph(const wxString& text, wxRichTextAttr* paraStyle = NULL) { Modify(); return wxRichTextParagraphLayoutBox::AddParagraph(text, paraStyle); }
 
     /// Begin collapsing undo/redo commands. Note that this may not work properly
     /// if combining commands that delete or insert content, changing ranges for
 
     /// Begin collapsing undo/redo commands. Note that this may not work properly
     /// if combining commands that delete or insert content, changing ranges for
@@ -1503,7 +2150,7 @@ public:
     virtual bool CanPasteFromClipboard() const;
 
     /// Begin using a style
     virtual bool CanPasteFromClipboard() const;
 
     /// Begin using a style
-    virtual bool BeginStyle(const wxTextAttrEx& style);
+    virtual bool BeginStyle(const wxRichTextAttr& style);
 
     /// End the style
     virtual bool EndStyle();
 
     /// End the style
     virtual bool EndStyle();
@@ -1590,11 +2237,17 @@ public:
     bool EndNumberedBullet() { return EndStyle(); }
 
     /// Begin symbol bullet
     bool EndNumberedBullet() { return EndStyle(); }
 
     /// Begin symbol bullet
-    bool BeginSymbolBullet(wxChar symbol, int leftIndent, int leftSubIndent, int bulletStyle = wxTEXT_ATTR_BULLET_STYLE_SYMBOL);
+    bool BeginSymbolBullet(const wxString& symbol, int leftIndent, int leftSubIndent, int bulletStyle = wxTEXT_ATTR_BULLET_STYLE_SYMBOL);
 
     /// End symbol bullet
     bool EndSymbolBullet() { return EndStyle(); }
 
 
     /// End symbol bullet
     bool EndSymbolBullet() { return EndStyle(); }
 
+    /// Begin standard bullet
+    bool BeginStandardBullet(const wxString& bulletName, int leftIndent, int leftSubIndent, int bulletStyle = wxTEXT_ATTR_BULLET_STYLE_STANDARD);
+
+    /// End standard bullet
+    bool EndStandardBullet() { return EndStyle(); }
+
     /// Begin named character style
     bool BeginCharacterStyle(const wxString& characterStyle);
 
     /// Begin named character style
     bool BeginCharacterStyle(const wxString& characterStyle);
 
@@ -1607,30 +2260,72 @@ public:
     /// End named character style
     bool EndParagraphStyle() { return EndStyle(); }
 
     /// End named character style
     bool EndParagraphStyle() { return EndStyle(); }
 
+    /// Begin named list style
+    bool BeginListStyle(const wxString& listStyle, int level = 1, int number = 1);
+
+    /// End named character style
+    bool EndListStyle() { return EndStyle(); }
+
+    /// Begin URL
+    bool BeginURL(const wxString& url, const wxString& characterStyle = wxEmptyString);
+
+    /// End URL
+    bool EndURL() { return EndStyle(); }
+
+// Event handling
+
+    /// Add an event handler
+    bool AddEventHandler(wxEvtHandler* handler);
+
+    /// Remove an event handler
+    bool RemoveEventHandler(wxEvtHandler* handler, bool deleteHandler = false);
+
+    /// Clear event handlers
+    void ClearEventHandlers();
+
+    /// Send event to event handlers. If sendToAll is true, will send to all event handlers,
+    /// otherwise will stop at the first successful one.
+    bool SendEvent(wxEvent& event, bool sendToAll = true);
+
 // Implementation
 
     /// Copy
 // Implementation
 
     /// Copy
-    void Copy(const wxRichTextBuffer& obj) { wxRichTextBox::Copy(obj); }
+    void Copy(const wxRichTextBuffer& obj);
+
+    /// Assignment
+    void operator= (const wxRichTextBuffer& obj) { Copy(obj); }
 
     /// Clone
     virtual wxRichTextObject* Clone() const { return new wxRichTextBuffer(*this); }
 
 
     /// Clone
     virtual wxRichTextObject* Clone() const { return new wxRichTextBuffer(*this); }
 
+    /// Submit command to insert paragraphs
+    bool InsertParagraphsWithUndo(long pos, const wxRichTextParagraphLayoutBox& paragraphs, wxRichTextCtrl* ctrl, int flags = 0);
+
     /// Submit command to insert the given text
     /// Submit command to insert the given text
-    bool InsertTextWithUndo(long pos, const wxString& text, wxRichTextCtrl* ctrl);
+    bool InsertTextWithUndo(long pos, const wxString& text, wxRichTextCtrl* ctrl, int flags = 0);
 
     /// Submit command to insert a newline
 
     /// Submit command to insert a newline
-    bool InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl);
+    bool InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl, int flags = 0);
 
     /// Submit command to insert the given image
 
     /// Submit command to insert the given image
-    bool InsertImageWithUndo(long pos, const wxRichTextImageBlock& imageBlock, wxRichTextCtrl* ctrl);
+    bool InsertImageWithUndo(long pos, const wxRichTextImageBlock& imageBlock, wxRichTextCtrl* ctrl, int flags = 0,
+            const wxRichTextAttr& textAttr = wxRichTextAttr());
+
+    /// Submit command to insert an object
+    bool InsertObjectWithUndo(long pos, wxRichTextObject *object, wxRichTextCtrl* ctrl, int flags);
 
     /// Submit command to delete this range
 
     /// Submit command to delete this range
-    bool DeleteRangeWithUndo(const wxRichTextRange& range, long initialCaretPosition, long newCaretPositon, wxRichTextCtrl* ctrl);
+    bool DeleteRangeWithUndo(const wxRichTextRange& range, wxRichTextCtrl* ctrl);
 
     /// Mark modified
     void Modify(bool modify = true) { m_modified = modify; }
     bool IsModified() const { return m_modified; }
 
 
     /// Mark modified
     void Modify(bool modify = true) { m_modified = modify; }
     bool IsModified() const { return m_modified; }
 
+    /// Get the style that is appropriate for a new paragraph at this position.
+    /// If the previous paragraph has a paragraph style name, look up the next-paragraph
+    /// style.
+    wxRichTextAttr GetStyleForNewParagraph(long pos, bool caretPosition = false, bool lookUpNewParaStyle=false) const;
+
     /// Dumps contents of buffer for debugging purposes
     virtual void Dump();
     virtual void Dump(wxTextOutputStream& stream) { wxRichTextParagraphLayoutBox::Dump(stream); }
     /// Dumps contents of buffer for debugging purposes
     virtual void Dump();
     virtual void Dump(wxTextOutputStream& stream) { wxRichTextParagraphLayoutBox::Dump(stream); }
@@ -1651,13 +2346,14 @@ public:
     static wxRichTextFileHandler *FindHandler(const wxString& name);
 
     /// Finds a handler by extension and type
     static wxRichTextFileHandler *FindHandler(const wxString& name);
 
     /// Finds a handler by extension and type
-    static wxRichTextFileHandler *FindHandler(const wxString& extension, int imageType);
+    static wxRichTextFileHandler *FindHandler(const wxString& extension, wxRichTextFileType imageType);
 
     /// Finds a handler by filename or, if supplied, type
 
     /// Finds a handler by filename or, if supplied, type
-    static wxRichTextFileHandler *FindHandlerFilenameOrType(const wxString& filename, int imageType);
+    static wxRichTextFileHandler *FindHandlerFilenameOrType(const wxString& filename,
+                                                            wxRichTextFileType imageType);
 
     /// Finds a handler by type
 
     /// Finds a handler by type
-    static wxRichTextFileHandler *FindHandler(int imageType);
+    static wxRichTextFileHandler *FindHandler(wxRichTextFileType imageType);
 
     /// Gets a wildcard incorporating all visible handlers. If 'types' is present,
     /// will be filled with the file type corresponding to each filter. This can be
 
     /// Gets a wildcard incorporating all visible handlers. If 'types' is present,
     /// will be filled with the file type corresponding to each filter. This can be
@@ -1670,11 +2366,32 @@ public:
     /// Initialise the standard handlers
     static void InitStandardHandlers();
 
     /// Initialise the standard handlers
     static void InitStandardHandlers();
 
+    /// Get renderer
+    static wxRichTextRenderer* GetRenderer() { return sm_renderer; }
+
+    /// Set renderer, deleting old one
+    static void SetRenderer(wxRichTextRenderer* renderer);
+
+    /// Minimum margin between bullet and paragraph in 10ths of a mm
+    static int GetBulletRightMargin() { return sm_bulletRightMargin; }
+    static void SetBulletRightMargin(int margin) { sm_bulletRightMargin = margin; }
+
+    /// Factor to multiply by character height to get a reasonable bullet size
+    static float GetBulletProportion() { return sm_bulletProportion; }
+    static void SetBulletProportion(float prop) { sm_bulletProportion = prop; }
+
+    /// Scale factor for calculating dimensions
+    double GetScale() const { return m_scale; }
+    void SetScale(double scale) { m_scale = scale; }
+
 protected:
 
     /// Command processor
     wxCommandProcessor*     m_commandProcessor;
 
 protected:
 
     /// Command processor
     wxCommandProcessor*     m_commandProcessor;
 
+    /// Table storing fonts
+    wxRichTextFontTable     m_fontTable;
+
     /// Has been modified?
     bool                    m_modified;
 
     /// Has been modified?
     bool                    m_modified;
 
@@ -1693,11 +2410,29 @@ protected:
     /// Style sheet, if any
     wxRichTextStyleSheet*   m_styleSheet;
 
     /// Style sheet, if any
     wxRichTextStyleSheet*   m_styleSheet;
 
+    /// List of event handlers that will be notified of events
+    wxList                  m_eventHandlers;
+
     /// Stack of attributes for convenience functions
     wxList                  m_attributeStack;
 
     /// Stack of attributes for convenience functions
     wxList                  m_attributeStack;
 
+    /// Flags to be passed to handlers
+    int                     m_handlerFlags;
+
     /// File handlers
     static wxList           sm_handlers;
     /// File handlers
     static wxList           sm_handlers;
+
+    /// Renderer
+    static wxRichTextRenderer* sm_renderer;
+
+    /// Minimum margin between bullet and paragraph in 10ths of a mm
+    static int              sm_bulletRightMargin;
+
+    /// Factor to multiply by character height to get a reasonable bullet size
+    static float            sm_bulletProportion;
+
+    /// Scaling factor in use: needed to calculate correct dimensions when printing
+    double                  m_scale;
 };
 
 /*!
 };
 
 /*!
@@ -1717,7 +2452,7 @@ enum wxRichTextCommandId
  *
  */
 
  *
  */
 
-class WXDLLIMPEXP_RICHTEXT wxRichTextAction;
+class WXDLLIMPEXP_FWD_RICHTEXT wxRichTextAction;
 class WXDLLIMPEXP_RICHTEXT wxRichTextCommand: public wxCommand
 {
 public:
 class WXDLLIMPEXP_RICHTEXT wxRichTextCommand: public wxCommand
 {
 public:
@@ -1760,14 +2495,18 @@ public:
     bool Undo();
 
     /// Update the control appearance
     bool Undo();
 
     /// Update the control appearance
-    void UpdateAppearance(long caretPosition, bool sendUpdateEvent = false);
+    void UpdateAppearance(long caretPosition, bool sendUpdateEvent = false,
+                            wxArrayInt* optimizationLineCharPositions = NULL, wxArrayInt* optimizationLineYPositions = NULL, bool isDoCmd = true);
 
     /// Replace the buffer paragraphs with the given fragment.
 
     /// Replace the buffer paragraphs with the given fragment.
-    void ApplyParagraphs(const wxRichTextFragment& fragment);
+    void ApplyParagraphs(const wxRichTextParagraphLayoutBox& fragment);
 
     /// Get the fragments
 
     /// Get the fragments
-    wxRichTextFragment& GetNewParagraphs() { return m_newParagraphs; }
-    wxRichTextFragment& GetOldParagraphs() { return m_oldParagraphs; }
+    wxRichTextParagraphLayoutBox& GetNewParagraphs() { return m_newParagraphs; }
+    wxRichTextParagraphLayoutBox& GetOldParagraphs() { return m_oldParagraphs; }
+
+    /// Calculate arrays for refresh optimization
+    void CalculateRefreshOptimizations(wxArrayInt& optimizationLineCharPositions, wxArrayInt& optimizationLineYPositions);
 
     /// Set/get the position used for e.g. insertion
     void SetPosition(long pos) { m_position = pos; }
 
     /// Set/get the position used for e.g. insertion
     void SetPosition(long pos) { m_position = pos; }
@@ -1791,10 +2530,10 @@ protected:
     wxRichTextCtrl*                 m_ctrl;
 
     // Stores the new paragraphs
     wxRichTextCtrl*                 m_ctrl;
 
     // Stores the new paragraphs
-    wxRichTextFragment              m_newParagraphs;
+    wxRichTextParagraphLayoutBox    m_newParagraphs;
 
     // Stores the old paragraphs
 
     // Stores the old paragraphs
-    wxRichTextFragment              m_oldParagraphs;
+    wxRichTextParagraphLayoutBox    m_oldParagraphs;
 
     // The affected range
     wxRichTextRange                 m_range;
 
     // The affected range
     wxRichTextRange                 m_range;
@@ -1809,6 +2548,30 @@ protected:
     wxRichTextCommandId             m_cmdId;
 };
 
     wxRichTextCommandId             m_cmdId;
 };
 
+/*!
+ * Handler flags
+ */
+
+// Include style sheet when loading and saving
+#define wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET       0x0001
+
+// Save images to memory file system in HTML handler
+#define wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_MEMORY    0x0010
+
+// Save images to files in HTML handler
+#define wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_FILES     0x0020
+
+// Save images as inline base64 data in HTML handler
+#define wxRICHTEXT_HANDLER_SAVE_IMAGES_TO_BASE64    0x0040
+
+// Don't write header and footer (or BODY), so we can include the fragment
+// in a larger document
+#define wxRICHTEXT_HANDLER_NO_HEADER_FOOTER         0x0080
+
+// Convert the more common face names to names that will work on the current platform
+// in a larger document
+#define wxRICHTEXT_HANDLER_CONVERT_FACENAMES        0x0100
+
 /*!
  * wxRichTextFileHandler
  * Base class for file handlers
 /*!
  * wxRichTextFileHandler
  * Base class for file handlers
@@ -1819,7 +2582,7 @@ class WXDLLIMPEXP_RICHTEXT wxRichTextFileHandler: public wxObject
     DECLARE_CLASS(wxRichTextFileHandler)
 public:
     wxRichTextFileHandler(const wxString& name = wxEmptyString, const wxString& ext = wxEmptyString, int type = 0)
     DECLARE_CLASS(wxRichTextFileHandler)
 public:
     wxRichTextFileHandler(const wxString& name = wxEmptyString, const wxString& ext = wxEmptyString, int type = 0)
-        : m_name(name), m_extension(ext), m_type(type), m_visible(true)
+        : m_name(name), m_extension(ext), m_type(type), m_flags(0), m_visible(true)
         { }
 
 #if wxUSE_STREAMS
         { }
 
 #if wxUSE_STREAMS
@@ -1829,8 +2592,10 @@ public:
     { return DoSaveFile(buffer, stream); }
 #endif
 
     { return DoSaveFile(buffer, stream); }
 #endif
 
-    bool LoadFile(wxRichTextBuffer *buffer, const wxString& filename);
-    bool SaveFile(wxRichTextBuffer *buffer, const wxString& filename);
+#if wxUSE_FFILE && wxUSE_STREAMS
+    virtual bool LoadFile(wxRichTextBuffer *buffer, const wxString& filename);
+    virtual bool SaveFile(wxRichTextBuffer *buffer, const wxString& filename);
+#endif // wxUSE_STREAMS && wxUSE_STREAMS
 
     /// Can we handle this filename (if using files)? By default, checks the extension.
     virtual bool CanHandle(const wxString& filename) const;
 
     /// Can we handle this filename (if using files)? By default, checks the extension.
     virtual bool CanHandle(const wxString& filename) const;
@@ -1857,6 +2622,10 @@ public:
     void SetType(int type) { m_type = type; }
     int GetType() const { return m_type; }
 
     void SetType(int type) { m_type = type; }
     int GetType() const { return m_type; }
 
+    /// Flags controlling how loading and saving is done
+    void SetFlags(int flags) { m_flags = flags; }
+    int GetFlags() const { return m_flags; }
+
     /// Encoding to use when saving a file. If empty, a suitable encoding is chosen
     void SetEncoding(const wxString& encoding) { m_encoding = encoding; }
     const wxString& GetEncoding() const { return m_encoding; }
     /// Encoding to use when saving a file. If empty, a suitable encoding is chosen
     void SetEncoding(const wxString& encoding) { m_encoding = encoding; }
     const wxString& GetEncoding() const { return m_encoding; }
@@ -1872,6 +2641,7 @@ protected:
     wxString  m_encoding;
     wxString  m_extension;
     int       m_type;
     wxString  m_encoding;
     wxString  m_extension;
     int       m_type;
+    int       m_flags;
     bool      m_visible;
 };
 
     bool      m_visible;
 };
 
@@ -1884,7 +2654,9 @@ class WXDLLIMPEXP_RICHTEXT wxRichTextPlainTextHandler: public wxRichTextFileHand
 {
     DECLARE_CLASS(wxRichTextPlainTextHandler)
 public:
 {
     DECLARE_CLASS(wxRichTextPlainTextHandler)
 public:
-    wxRichTextPlainTextHandler(const wxString& name = wxT("Text"), const wxString& ext = wxT("txt"), int type = wxRICHTEXT_TYPE_TEXT)
+    wxRichTextPlainTextHandler(const wxString& name = wxT("Text"),
+                               const wxString& ext = wxT("txt"),
+                               wxRichTextFileType type = wxRICHTEXT_TYPE_TEXT)
         : wxRichTextFileHandler(name, ext, type)
         { }
 
         : wxRichTextFileHandler(name, ext, type)
         { }
 
@@ -1903,6 +2675,93 @@ protected:
 
 };
 
 
 };
 
+#if wxUSE_DATAOBJ
+
+/*!
+ * The data object for a wxRichTextBuffer
+ */
+
+class WXDLLIMPEXP_RICHTEXT wxRichTextBufferDataObject: public wxDataObjectSimple
+{
+public:
+    // ctor doesn't copy the pointer, so it shouldn't go away while this object
+    // is alive
+    wxRichTextBufferDataObject(wxRichTextBuffer* richTextBuffer = NULL);
+    virtual ~wxRichTextBufferDataObject();
+
+    // after a call to this function, the buffer is owned by the caller and it
+    // is responsible for deleting it
+    wxRichTextBuffer* GetRichTextBuffer();
+
+    // Returns the id for the new data format
+    static const wxChar* GetRichTextBufferFormatId() { return ms_richTextBufferFormatId; }
+
+    // base class pure virtuals
+
+    virtual wxDataFormat GetPreferredFormat(Direction dir) const;
+    virtual size_t GetDataSize() const;
+    virtual bool GetDataHere(void *pBuf) const;
+    virtual bool SetData(size_t len, const void *buf);
+
+    // prevent warnings
+
+    virtual size_t GetDataSize(const wxDataFormat&) const { return GetDataSize(); }
+    virtual bool GetDataHere(const wxDataFormat&, void *buf) const { return GetDataHere(buf); }
+    virtual bool SetData(const wxDataFormat&, size_t len, const void *buf) { return SetData(len, buf); }
+
+private:
+    wxDataFormat            m_formatRichTextBuffer;     // our custom format
+    wxRichTextBuffer*       m_richTextBuffer;           // our data
+    static const wxChar*    ms_richTextBufferFormatId;  // our format id
+};
+
+#endif
+
+/*!
+ * wxRichTextRenderer isolates common drawing functionality
+ */
+
+class WXDLLIMPEXP_RICHTEXT wxRichTextRenderer: public wxObject
+{
+public:
+    wxRichTextRenderer() {}
+    virtual ~wxRichTextRenderer() {}
+
+    /// Draw a standard bullet, as specified by the value of GetBulletName
+    virtual bool DrawStandardBullet(wxRichTextParagraph* paragraph, wxDC& dc, const wxRichTextAttr& attr, const wxRect& rect) = 0;
+
+    /// Draw a bullet that can be described by text, such as numbered or symbol bullets
+    virtual bool DrawTextBullet(wxRichTextParagraph* paragraph, wxDC& dc, const wxRichTextAttr& attr, const wxRect& rect, const wxString& text) = 0;
+
+    /// Draw a bitmap bullet, where the bullet bitmap is specified by the value of GetBulletName
+    virtual bool DrawBitmapBullet(wxRichTextParagraph* paragraph, wxDC& dc, const wxRichTextAttr& attr, const wxRect& rect) = 0;
+
+    /// Enumerate the standard bullet names currently supported
+    virtual bool EnumerateStandardBulletNames(wxArrayString& bulletNames) = 0;
+};
+
+/*!
+ * wxRichTextStdRenderer: standard renderer
+ */
+
+class WXDLLIMPEXP_RICHTEXT wxRichTextStdRenderer: public wxRichTextRenderer
+{
+public:
+    wxRichTextStdRenderer() {}
+
+    /// Draw a standard bullet, as specified by the value of GetBulletName
+    virtual bool DrawStandardBullet(wxRichTextParagraph* paragraph, wxDC& dc, const wxRichTextAttr& attr, const wxRect& rect);
+
+    /// Draw a bullet that can be described by text, such as numbered or symbol bullets
+    virtual bool DrawTextBullet(wxRichTextParagraph* paragraph, wxDC& dc, const wxRichTextAttr& attr, const wxRect& rect, const wxString& text);
+
+    /// Draw a bitmap bullet, where the bullet bitmap is specified by the value of GetBulletName
+    virtual bool DrawBitmapBullet(wxRichTextParagraph* paragraph, wxDC& dc, const wxRichTextAttr& attr, const wxRect& rect);
+
+    /// Enumerate the standard bullet names currently supported
+    virtual bool EnumerateStandardBulletNames(wxArrayString& bulletNames);
+};
+
 /*!
  * Utilities
  *
 /*!
  * Utilities
  *
@@ -1914,21 +2773,43 @@ inline bool wxRichTextHasStyle(int flags, int style)
 }
 
 /// Compare two attribute objects
 }
 
 /// Compare two attribute objects
-bool wxTextAttrEq(const wxTextAttrEx& attr1, const wxTextAttrEx& attr2);
-bool wxTextAttrEq(const wxTextAttr& attr1, const wxRichTextAttr& attr2);
+WXDLLIMPEXP_RICHTEXT bool wxTextAttrEq(const wxRichTextAttr& attr1, const wxRichTextAttr& attr2);
+WXDLLIMPEXP_RICHTEXT bool wxTextAttrEq(const wxRichTextAttr& attr1, const wxRichTextAttr& attr2);
 
 /// Compare two attribute objects, but take into account the flags
 /// specifying attributes of interest.
 
 /// Compare two attribute objects, but take into account the flags
 /// specifying attributes of interest.
-bool wxTextAttrEqPartial(const wxTextAttrEx& attr1, const wxTextAttrEx& attr2, int flags);
-bool wxTextAttrEqPartial(const wxTextAttrEx& attr1, const wxRichTextAttr& attr2, int flags);
+WXDLLIMPEXP_RICHTEXT bool wxTextAttrEqPartial(const wxRichTextAttr& attr1, const wxRichTextAttr& attr2);
 
 /// Apply one style to another
 
 /// Apply one style to another
-bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxTextAttrEx& style);
-bool wxRichTextApplyStyle(wxRichTextAttr& destStyle, const wxTextAttrEx& style);
-bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style);
+WXDLLIMPEXP_RICHTEXT bool wxRichTextApplyStyle(wxRichTextAttr& destStyle, const wxRichTextAttr& style, wxRichTextAttr* compareWith = NULL);
+
+// Remove attributes
+WXDLLIMPEXP_RICHTEXT bool wxRichTextRemoveStyle(wxRichTextAttr& destStyle, const wxRichTextAttr& style);
+
+/// Combine two bitlists
+WXDLLIMPEXP_RICHTEXT bool wxRichTextCombineBitlists(int& valueA, int valueB, int& flagsA, int flagsB);
+
+/// Compare two bitlists
+WXDLLIMPEXP_RICHTEXT bool wxRichTextBitlistsEqPartial(int valueA, int valueB, int flags);
+
+/// Split into paragraph and character styles
+WXDLLIMPEXP_RICHTEXT bool wxRichTextSplitParaCharStyles(const wxRichTextAttr& style, wxRichTextAttr& parStyle, wxRichTextAttr& charStyle);
+
+/// Compare tabs
+WXDLLIMPEXP_RICHTEXT bool wxRichTextTabsEq(const wxArrayInt& tabs1, const wxArrayInt& tabs2);
+
+/// Convert a decimal to Roman numerals
+WXDLLIMPEXP_RICHTEXT wxString wxRichTextDecimalToRoman(long n);
+
+// Collects the attributes that are common to a range of content, building up a note of
+// which attributes are absent in some objects and which clash in some objects.
+WXDLLIMPEXP_RICHTEXT void wxTextAttrCollectCommonAttributes(wxTextAttr& currentStyle, const wxTextAttr& attr, wxTextAttr& clashingAttr, wxTextAttr& absentAttr);
+
+WXDLLIMPEXP_RICHTEXT void wxRichTextModuleInit();
 
 #endif
     // wxUSE_RICHTEXT
 
 #endif
     // _WX_RICHTEXTBUFFER_H_
 
 #endif
     // wxUSE_RICHTEXT
 
 #endif
     // _WX_RICHTEXTBUFFER_H_
+