]> git.saurik.com Git - wxWidgets.git/commitdiff
Fixed bugs in, and added operators and copy constructors to, style
authorJulian Smart <julian@anthemion.co.uk>
Fri, 29 Sep 2006 08:53:23 +0000 (08:53 +0000)
committerJulian Smart <julian@anthemion.co.uk>
Fri, 29 Sep 2006 08:53:23 +0000 (08:53 +0000)
sheet classes.
Now merges base, paragraph and content styles dynamically on
display or layout so that we can distinguish between them. This
means appling a paragraph style that has character formatting
doesn't wipe out the original content formatting. The old-style
static method can be enabled by setting wxRICHTEXT_USE_DYNAMIC_STYLES
to 0 in richtextbuffer.h.
The default style is initially empty, so that adding text
reflects the base and paragraph styles. Setting the default style
doesn't merge with the previous setting, but BeginStyle does.
Adding new paragraphs is now sensitive to the previous paragraph's
style and also whether its style has a next-paragraph style indication.
Added wxRichTextCtrl::ApplyStyleSheet which reapplies styles to
paragraphs with named styles.
Added style application command to sample to demonstrate how
styles can be changed and reapplied without affecting content
character formatting.
Fixed some range bugs in UI feedback and clipboard copying and pasting.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@41501 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/richtext/richtextbuffer.h
include/wx/richtext/richtextctrl.h
include/wx/richtext/richtextstyles.h
samples/richtext/richtext.cpp
src/richtext/richtextbuffer.cpp
src/richtext/richtextctrl.cpp
src/richtext/richtextstyles.cpp

index fa9fd77144c48a47d71fd79861e184fd573e52b8..45eb308cfff92f308766e96599b03e18ca7a0fbb 100644 (file)
 #include "wx/cmdproc.h"
 #include "wx/txtstrm.h"
 
+// Experimental dynamic styles to avoid user-specific character styles from being
+// overwritten by paragraph styles.
+#define wxRICHTEXT_USE_DYNAMIC_STYLES 1
+
 /*!
  * File types
  */
@@ -161,6 +165,13 @@ class WXDLLIMPEXP_RICHTEXT wxTextAttrEx;
 #define wxRICHTEXT_FORMATTED        0x01
 #define wxRICHTEXT_UNFORMATTED      0x02
 
+/*!
+ * Flags for text insertion
+ */
+
+#define wxRICHTEXT_INSERT_NONE                              0x00
+#define wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE     0x01
+
 /*!
  * Extra formatting flags not in wxTextAttr
  */
@@ -378,6 +389,9 @@ public:
     // Assignment from a wxTextAttrEx object.
     void operator= (const wxTextAttrEx& attr);
 
+    // Equality test
+    bool operator== (const wxRichTextAttr& attr) const;
+
     // Making a wxTextAttrEx object.
     operator wxTextAttrEx () const ;
 
@@ -853,13 +867,13 @@ public:
     virtual void Reset();
 
     /// Convenience function to add a paragraph of text
-    virtual wxRichTextRange AddParagraph(const wxString& text);
+    virtual wxRichTextRange AddParagraph(const wxString& text, wxTextAttrEx* paraStyle = NULL);
 
     /// Convenience function to add an image
-    virtual wxRichTextRange AddImage(const wxImage& image);
+    virtual wxRichTextRange AddImage(const wxImage& image, wxTextAttrEx* paraStyle = NULL);
 
     /// Adds multiple paragraphs, based on newlines.
-    virtual wxRichTextRange AddParagraphs(const wxString& text);
+    virtual wxRichTextRange AddParagraphs(const wxString& text, wxTextAttrEx* 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.
@@ -916,10 +930,18 @@ public:
     virtual bool SetStyle(const wxRichTextRange& range, const wxRichTextAttr& style, bool withUndo = true);
     virtual bool SetStyle(const wxRichTextRange& range, const wxTextAttrEx& style, bool withUndo = true);
 
-    /// Get the text attributes for this position.
+    /// Get the conbined text attributes for this position.
     virtual bool GetStyle(long position, wxTextAttrEx& style);
     virtual bool GetStyle(long position, wxRichTextAttr& style);
 
+    /// Get the content (uncombined) attributes for this position.
+    virtual bool GetUncombinedStyle(long position, wxTextAttrEx& style);
+    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, wxTextAttrEx& style, bool combineStyles = true);
+
     /// 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
@@ -945,6 +967,9 @@ public:
     /// Make a copy of the fragment corresponding to the given range, putting it in 'fragment'.
     virtual bool CopyFragment(const wxRichTextRange& range, wxRichTextFragment& 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);
 
@@ -1161,7 +1186,7 @@ public:
 // Implementation
 
     /// Apply paragraph styles such as centering to the wrapped lines
-    virtual void ApplyParagraphStyle(const wxRect& rect);
+    virtual void ApplyParagraphStyle(const wxTextAttrEx& attr, const wxRect& rect);
 
     /// Insert text at the given position
     virtual bool InsertText(long pos, const wxString& text);
@@ -1196,6 +1221,13 @@ public:
     /// 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.
+    wxTextAttrEx GetCombinedAttributes(const wxTextAttr& contentStyle) const;
+
+    /// Get combined attributes of the base style and paragraph style.
+    wxTextAttrEx GetCombinedAttributes() const;
+
 protected:
     /// The lines that make up the wrapped paragraph
     wxRichTextLineList m_cachedLines;
@@ -1269,7 +1301,7 @@ public:
     /// 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 wxTextAttrEx& attr, const wxRect& rect, wxString& str, wxCoord& x, wxCoord& y, bool selected);
 
 protected:
     wxString    m_text;
@@ -1623,13 +1655,13 @@ public:
     virtual wxRichTextObject* Clone() const { return new wxRichTextBuffer(*this); }
 
     /// 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
-    bool InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl);
+    bool InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl, int flags = 0);
 
     /// 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);
 
     /// Submit command to delete this range
     bool DeleteRangeWithUndo(const wxRichTextRange& range, long initialCaretPosition, long newCaretPositon, wxRichTextCtrl* ctrl);
@@ -1638,6 +1670,11 @@ public:
     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) const;
+
     /// Dumps contents of buffer for debugging purposes
     virtual void Dump();
     virtual void Dump(wxTextOutputStream& stream) { wxRichTextParagraphLayoutBox::Dump(stream); }
index 9cad286cdec01e10195c214c1e37da555eb0b8ed..bf1e62bafddbd0e4c82526ae47b832927eb32326 100644 (file)
@@ -188,6 +188,12 @@ public:
     virtual bool GetStyle(long position, wxTextAttr& style);
     virtual bool GetStyle(long position, wxTextAttrEx& style);
     virtual bool GetStyle(long position, wxRichTextAttr& style);
+
+    /// Get the content (uncombined) attributes for this position.
+    virtual bool GetUncombinedStyle(long position, wxTextAttr& style);
+    virtual bool GetUncombinedStyle(long position, wxTextAttrEx& style);
+    virtual bool GetUncombinedStyle(long position, wxRichTextAttr& style);
+
     virtual bool SetDefaultStyle(const wxTextAttrEx& style);
     virtual bool SetDefaultStyle(const wxTextAttr& style);
 
@@ -530,6 +536,9 @@ public:
     void SetStyleSheet(wxRichTextStyleSheet* styleSheet) { GetBuffer().SetStyleSheet(styleSheet); }
     wxRichTextStyleSheet* GetStyleSheet() const { return GetBuffer().GetStyleSheet(); }
 
+    /// Apply the style sheet to the buffer, for example if the styles have changed.
+    bool ApplyStyleSheet(wxRichTextStyleSheet* styleSheet = NULL);
+
 // Command handlers
 
     void Command(wxCommandEvent& event);
@@ -595,8 +604,6 @@ public:
     /// Scrolling
     void OnScroll(wxScrollWinEvent& event);
 
-// Implementation
-
     /// Set font, and also default attributes
     virtual bool SetFont(const wxFont& font);
 
@@ -717,6 +724,8 @@ public:
         SetCaretPositionForDefaultStyle(GetCaretPosition());
     }
 
+// Implementation
+
 #if wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
      WX_FORWARD_TO_SCROLL_HELPER()
 #endif
@@ -845,4 +854,3 @@ typedef void (wxEvtHandler::*wxRichTextEventFunction)(wxRichTextEvent&);
 
 #endif
     // _WX_RICHTEXTCTRL_H_
-
index 997d3e97445963a4ddf2aca0cef759f2c7794ec1..89672946edd2e45953eb10557729d8ee738657cf 100644 (file)
@@ -47,10 +47,15 @@ public:
 
 // Constructors
 
+    wxRichTextStyleDefinition(const wxRichTextStyleDefinition& def) { Copy(def); }
     wxRichTextStyleDefinition(const wxString& name = wxEmptyString) { Init(); m_name = name; }
     virtual ~wxRichTextStyleDefinition() {}
 
     void Init() {}
+    void Copy(const wxRichTextStyleDefinition& def);
+    bool Eq(const wxRichTextStyleDefinition& def) const;
+    void operator =(const wxRichTextStyleDefinition& def) { Copy(def); }
+    bool operator ==(const wxRichTextStyleDefinition& def) const { return Eq(def); }
 
     /// The name of the style.
     void SetName(const wxString& name) { m_name = name; }
@@ -82,6 +87,7 @@ public:
 
 // Constructors
 
+    wxRichTextCharacterStyleDefinition(const wxRichTextCharacterStyleDefinition& def): wxRichTextStyleDefinition(def) {}
     wxRichTextCharacterStyleDefinition(const wxString& name = wxEmptyString):
         wxRichTextStyleDefinition(name) {}
     virtual ~wxRichTextCharacterStyleDefinition() {}
@@ -100,6 +106,7 @@ public:
 
 // Constructors
 
+    wxRichTextParagraphStyleDefinition(const wxRichTextParagraphStyleDefinition& def): wxRichTextStyleDefinition(def) { m_nextStyle = def.m_nextStyle; }
     wxRichTextParagraphStyleDefinition(const wxString& name = wxEmptyString):
         wxRichTextStyleDefinition(name) {}
     virtual ~wxRichTextParagraphStyleDefinition() {}
@@ -108,6 +115,10 @@ public:
     void SetNextStyle(const wxString& name) { m_nextStyle = name; }
     const wxString& GetNextStyle() const { return m_nextStyle; }
 
+    void Copy(const wxRichTextParagraphStyleDefinition& def);
+    void operator =(const wxRichTextParagraphStyleDefinition& def) { Copy(def); }
+    bool operator ==(const wxRichTextParagraphStyleDefinition& def) const;
+
 protected:
 
     /// The next style to use when adding a paragraph after this style.
@@ -124,29 +135,39 @@ class WXDLLIMPEXP_RICHTEXT wxRichTextStyleSheet: public wxObject
 
 public:
     /// Constructors
+    wxRichTextStyleSheet(const wxRichTextStyleSheet& sheet) { Copy(sheet); }
     wxRichTextStyleSheet() { Init(); }
     virtual ~wxRichTextStyleSheet() { DeleteStyles(); }
 
     /// Initialisation
     void Init();
 
+    /// Copy
+    void Copy(const wxRichTextStyleSheet& sheet);
+
+    /// Assignment
+    void operator=(const wxRichTextStyleSheet& sheet) { Copy(sheet); }
+
+    /// Equality
+    bool operator==(const wxRichTextStyleSheet& sheet) const;
+
     /// Add a definition to the character style list
-    bool AddCharacterStyle(wxRichTextCharacterStyleDefinition* def) { return AddStyle(m_characterStyleDefinitions, def); }
+    bool AddCharacterStyle(wxRichTextCharacterStyleDefinition* def);
 
     /// Add a definition to the paragraph style list
-    bool AddParagraphStyle(wxRichTextParagraphStyleDefinition* def) { return AddStyle(m_paragraphStyleDefinitions, def); }
+    bool AddParagraphStyle(wxRichTextParagraphStyleDefinition* def);
 
     /// Remove a character style
     bool RemoveCharacterStyle(wxRichTextStyleDefinition* def, bool deleteStyle = false) { return RemoveStyle(m_characterStyleDefinitions, def, deleteStyle); }
 
     /// Remove a paragraph style
-    bool RemoveParagraphStyle(wxRichTextStyleDefinition* def, bool deleteStyle = false) { return RemoveStyle(m_characterStyleDefinitions, def, deleteStyle); }
+    bool RemoveParagraphStyle(wxRichTextStyleDefinition* def, bool deleteStyle = false) { return RemoveStyle(m_paragraphStyleDefinitions, def, deleteStyle); }
 
     /// Find a character definition by name
     wxRichTextCharacterStyleDefinition* FindCharacterStyle(const wxString& name) const { return (wxRichTextCharacterStyleDefinition*) FindStyle(m_characterStyleDefinitions, name); }
 
     /// Find a paragraph definition by name
-    wxRichTextParagraphStyleDefinition* FindParagraphStyle(const wxString& name) const { return (wxRichTextParagraphStyleDefinition*) FindStyle(m_characterStyleDefinitions, name); }
+    wxRichTextParagraphStyleDefinition* FindParagraphStyle(const wxString& name) const { return (wxRichTextParagraphStyleDefinition*) FindStyle(m_paragraphStyleDefinitions, name); }
 
     /// Return the number of character styes.
     size_t GetCharacterStyleCount() const { return m_characterStyleDefinitions.GetCount(); }
index e0a9968d1ea164b826d82aec8019568bbe0f3c82..152b07f68bb2c96d46343ece2c1c3aeffa35d28a 100644 (file)
@@ -139,6 +139,8 @@ public:
 
     void OnViewHTML(wxCommandEvent& event);
 
+    void OnSwitchStyleSheets(wxCommandEvent& event);
+
     // Forward command events to the current rich text control, if any
     bool ProcessEvent(wxEvent& event);
 
@@ -179,7 +181,12 @@ enum
     ID_FORMAT_LINE_SPACING_DOUBLE,
     ID_FORMAT_LINE_SPACING_SINGLE,
 
-    ID_VIEW_HTML
+    ID_VIEW_HTML,
+    ID_SWITCH_STYLE_SHEETS,
+
+    ID_RICHTEXT_CTRL,
+    ID_RICHTEXT_STYLE_LIST,
+    ID_RICHTEXT_STYLE_COMBO
 };
 
 // ----------------------------------------------------------------------------
@@ -225,6 +232,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame)
     EVT_MENU(ID_FORMAT_PARAGRAPH_SPACING_LESS,  MyFrame::OnParagraphSpacingLess)
 
     EVT_MENU(ID_VIEW_HTML, MyFrame::OnViewHTML)
+    EVT_MENU(ID_SWITCH_STYLE_SHEETS, MyFrame::OnSwitchStyleSheets)
 END_EVENT_TABLE()
 
 // Create a new application object: this macro will allow wxWidgets to create
@@ -442,6 +450,8 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
     formatMenu->Append(ID_FORMAT_LINE_SPACING_DOUBLE, _("Double Line Spacing"));
     formatMenu->AppendSeparator();
     formatMenu->Append(ID_FORMAT_FONT, _("&Font..."));
+    formatMenu->AppendSeparator();
+    formatMenu->Append(ID_SWITCH_STYLE_SHEETS, _("&Switch Style Sheets"));
 
     // now append the freshly created menu to the menu bar...
     wxMenuBar *menuBar = new wxMenuBar();
@@ -490,7 +500,7 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
     toolBar->AddSeparator();
     toolBar->AddTool(ID_FORMAT_FONT, wxBitmap(font_xpm), wxNullBitmap, false, -1, -1, (wxObject *) NULL, _("Font"));
 
-    wxRichTextStyleComboCtrl* combo = new wxRichTextStyleComboCtrl(toolBar, wxID_ANY, wxDefaultPosition, wxSize(200, -1));
+    wxRichTextStyleComboCtrl* combo = new wxRichTextStyleComboCtrl(toolBar, ID_RICHTEXT_STYLE_COMBO, wxDefaultPosition, wxSize(200, -1));
     toolBar->AddControl(combo);
 
     toolBar->Realize();
@@ -501,16 +511,18 @@ MyFrame::MyFrame(const wxString& title, wxWindowID id, const wxPoint& pos,
     wxFont boldFont = wxFont(12, wxROMAN, wxNORMAL, wxBOLD);
     wxFont italicFont = wxFont(12, wxROMAN, wxITALIC, wxNORMAL);
 
-    m_richTextCtrl = new wxRichTextCtrl(splitter, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(200, 200), wxVSCROLL|wxHSCROLL|wxNO_BORDER|wxWANTS_CHARS);
+    m_richTextCtrl = new wxRichTextCtrl(splitter, ID_RICHTEXT_CTRL, wxEmptyString, wxDefaultPosition, wxSize(200, 200), wxVSCROLL|wxHSCROLL|wxNO_BORDER|wxWANTS_CHARS);
     wxFont font(12, wxROMAN, wxNORMAL, wxNORMAL);
 
     m_richTextCtrl->SetFont(font);
 
+    m_richTextCtrl->SetStyleSheet(wxGetApp().GetStyleSheet());
+
     combo->SetStyleSheet(wxGetApp().GetStyleSheet());
     combo->SetRichTextCtrl(m_richTextCtrl);
     combo->UpdateStyles();
 
-    wxRichTextStyleListBox* styleListBox = new wxRichTextStyleListBox(splitter, wxID_ANY);
+    wxRichTextStyleListBox* styleListBox = new wxRichTextStyleListBox(splitter, ID_RICHTEXT_STYLE_LIST);
 
     wxSize display = wxGetDisplaySize();
     if ( is_pda && ( display.GetWidth() < display.GetHeight() ) )
@@ -1073,3 +1085,58 @@ void MyFrame::OnViewHTML(wxCommandEvent& WXUNUSED(event))
 
     dialog.ShowModal();
 }
+
+// Demonstrates how you can change the style sheets and have the changes
+// reflected in the control content without wiping out character formatting.
+
+void MyFrame::OnSwitchStyleSheets(wxCommandEvent& WXUNUSED(event))
+{
+    static wxRichTextStyleSheet* gs_AlternateStyleSheet = NULL;
+
+    wxRichTextCtrl* ctrl = (wxRichTextCtrl*) FindWindow(ID_RICHTEXT_CTRL);
+    wxRichTextStyleListBox* styleList = (wxRichTextStyleListBox*) FindWindow(ID_RICHTEXT_STYLE_LIST);
+    wxRichTextStyleComboCtrl* styleCombo = (wxRichTextStyleComboCtrl*) FindWindow(ID_RICHTEXT_STYLE_COMBO);
+
+    wxRichTextStyleSheet* sheet = ctrl->GetStyleSheet();
+
+    // One-time creation of an alternate style sheet
+    if (!gs_AlternateStyleSheet)
+    {
+        gs_AlternateStyleSheet = new wxRichTextStyleSheet(*sheet);
+
+        // Make some modifications
+        for (int i = 0; i < (int) gs_AlternateStyleSheet->GetParagraphStyleCount(); i++)
+        {
+            wxRichTextParagraphStyleDefinition* def = gs_AlternateStyleSheet->GetParagraphStyle(i);
+
+            if (def->GetStyle().HasTextColour())
+                def->GetStyle().SetTextColour(*wxBLUE);
+
+            if (def->GetStyle().HasAlignment())
+            {
+                if (def->GetStyle().GetAlignment() == wxTEXT_ALIGNMENT_CENTRE)
+                    def->GetStyle().SetAlignment(wxTEXT_ALIGNMENT_RIGHT);
+                else if (def->GetStyle().GetAlignment() == wxTEXT_ALIGNMENT_LEFT)
+                    def->GetStyle().SetAlignment(wxTEXT_ALIGNMENT_CENTRE);
+            }
+            if (def->GetStyle().HasLeftIndent())
+            {
+                def->GetStyle().SetLeftIndent(def->GetStyle().GetLeftIndent() * 2);
+            }
+        }
+    }
+
+    // Switch sheets
+    wxRichTextStyleSheet* tmp = gs_AlternateStyleSheet;
+    gs_AlternateStyleSheet = sheet;
+    sheet = tmp;
+
+    ctrl->SetStyleSheet(sheet);
+    ctrl->ApplyStyleSheet(sheet); // Makes the control reflect the new style definitions
+
+    styleList->SetStyleSheet(sheet);
+    styleList->UpdateStyles();
+
+    styleCombo->SetStyleSheet(sheet);
+    styleCombo->UpdateStyles();
+}
index bc16bc9efdb6758dbdb7c4b30866c46f15aa7a78..ce8a05534de816e467769645ab0a1ea9b1151363 100644 (file)
@@ -81,11 +81,12 @@ void wxRichTextObject::Copy(const wxRichTextObject& obj)
     m_range = obj.m_range;
     m_attributes = obj.m_attributes;
     m_descent = obj.m_descent;
-
+/*
     if (!m_attributes.GetFont().Ok())
         wxLogDebug(wxT("No font!"));
     if (!obj.m_attributes.GetFont().Ok())
         wxLogDebug(wxT("Parent has no font!"));
+*/
 }
 
 void wxRichTextObject::SetMargins(int margin)
@@ -221,7 +222,9 @@ void wxRichTextCompositeObject::Copy(const wxRichTextCompositeObject& obj)
     while (node)
     {
         wxRichTextObject* child = node->GetData();
-        m_children.Append(child->Clone());
+        wxRichTextObject* newChild = child->Clone();
+        newChild->SetParent(this);
+        m_children.Append(newChild);
 
         node = node->GetNext();
     }
@@ -869,16 +872,23 @@ wxSize wxRichTextParagraphLayoutBox::GetLineSizeAtPosition(long pos, bool caretP
 
 
 /// Convenience function to add a paragraph of text
-wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraph(const wxString& text)
+wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraph(const wxString& text, wxTextAttrEx* paraStyle)
 {
+#if wxRICHTEXT_USE_DYNAMIC_STYLES
+    // Don't use the base style, just the default style, and the base style will
+    // be combined at display time
+    wxTextAttrEx style(GetDefaultStyle());
+#else
     wxTextAttrEx style(GetAttributes());
 
     // Apply default style. If the style has no attributes set,
     // then the attributes will remain the 'basic style' (i.e. the
     // layout box's style).
     wxRichTextApplyStyle(style, GetDefaultStyle());
-
+#endif
     wxRichTextParagraph* para = new wxRichTextParagraph(text, this, & style);
+    if (paraStyle)
+        para->SetAttributes(*paraStyle);
 
     AppendChild(para);
 
@@ -889,9 +899,15 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraph(const wxString& text)
 }
 
 /// Adds multiple paragraphs, based on newlines.
-wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text)
+wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text, wxTextAttrEx* paraStyle)
 {
+#if wxRICHTEXT_USE_DYNAMIC_STYLES
+    // Don't use the base style, just the default style, and the base style will
+    // be combined at display time
+    wxTextAttrEx style(GetDefaultStyle());
+#else
     wxTextAttrEx style(GetAttributes());
+
     //wxLogDebug("Initial style = %s", style.GetFont().GetFaceName());
     //wxLogDebug("Initial size = %d", style.GetFont().GetPointSize());
 
@@ -902,6 +918,7 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text
 
     //wxLogDebug("Style after applying default style = %s", style.GetFont().GetFaceName());
     //wxLogDebug("Size after applying default style = %d", style.GetFont().GetPointSize());
+#endif
 
     wxRichTextParagraph* firstPara = NULL;
     wxRichTextParagraph* lastPara = NULL;
@@ -916,6 +933,8 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text
         if (ch == wxT('\n') || ch == wxT('\r'))
         {
             wxRichTextParagraph* para = new wxRichTextParagraph(line, this, & style);
+            if (paraStyle)
+                para->SetAttributes(*paraStyle);
 
             AppendChild(para);
             if (!firstPara)
@@ -931,6 +950,9 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text
     if (!line.empty())
     {
         lastPara = new wxRichTextParagraph(line, this, & style);
+        if (paraStyle)
+            lastPara->SetAttributes(*paraStyle);
+
         //wxLogDebug("Para Face = %s", lastPara->GetAttributes().GetFont().GetFaceName());
         AppendChild(lastPara);
     }
@@ -952,19 +974,28 @@ wxRichTextRange wxRichTextParagraphLayoutBox::AddParagraphs(const wxString& text
 }
 
 /// Convenience function to add an image
-wxRichTextRange wxRichTextParagraphLayoutBox::AddImage(const wxImage& image)
+wxRichTextRange wxRichTextParagraphLayoutBox::AddImage(const wxImage& image, wxTextAttrEx* paraStyle)
 {
+#if wxRICHTEXT_USE_DYNAMIC_STYLES
+    // Don't use the base style, just the default style, and the base style will
+    // be combined at display time
+    wxTextAttrEx style(GetDefaultStyle());
+#else
     wxTextAttrEx style(GetAttributes());
 
     // Apply default style. If the style has no attributes set,
     // then the attributes will remain the 'basic style' (i.e. the
     // layout box's style).
     wxRichTextApplyStyle(style, GetDefaultStyle());
+#endif
 
     wxRichTextParagraph* para = new wxRichTextParagraph(this, & style);
     AppendChild(para);
     para->AppendChild(new wxRichTextImage(image, this));
 
+    if (paraStyle)
+        para->SetAttributes(*paraStyle);
+
     UpdateRanges();
     SetDirty(true);
 
@@ -1112,7 +1143,9 @@ bool wxRichTextParagraphLayoutBox::InsertFragment(long position, wxRichTextFragm
                 if (finalPara->GetChildCount() == 0)
                 {
                     wxRichTextPlainText* text = new wxRichTextPlainText(wxEmptyString);
+#if !wxRICHTEXT_USE_DYNAMIC_STYLES
                     text->SetAttributes(finalPara->GetAttributes());
+#endif
 
                     finalPara->AppendChild(text);
                 }
@@ -1387,8 +1420,8 @@ wxString wxRichTextParagraphLayoutBox::GetTextForRange(const wxRichTextRange& ra
         wxRichTextObject* child = node->GetData();
         if (!child->GetRange().IsOutside(range))
         {
-            if (lineCount > 0)
-                text += wxT("\n");
+//            if (lineCount > 0)
+//                text += wxT("\n");
             wxRichTextRange childRange = range;
             childRange.LimitTo(child->GetRange());
 
@@ -1396,6 +1429,9 @@ wxString wxRichTextParagraphLayoutBox::GetTextForRange(const wxRichTextRange& ra
 
             text += childText;
 
+            if (childRange.GetEnd() == child->GetRange().GetEnd())
+                text += wxT("\n");
+
             lineCount ++;
         }
         node = node->GetNext();
@@ -1557,7 +1593,15 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const
                 if (paragraphStyle)
                     wxRichTextApplyStyle(newPara->GetAttributes(), style);
 
+#if wxRICHTEXT_USE_DYNAMIC_STYLES
+                // If applying paragraph styles dynamically, don't change the text objects' attributes
+                // since they will computed as needed. Only apply the character styling if it's _only_
+                // character styling. This policy is subject to change and might be put under user control.
+
+                if (!paragraphStyle && characterStyle && range.GetStart() != newPara->GetRange().GetEnd())
+#else
                 if (characterStyle && range.GetStart() != newPara->GetRange().GetEnd())
+#endif
                 {
                     wxRichTextRange childRange(range);
                     childRange.LimitTo(newPara->GetRange());
@@ -1635,44 +1679,102 @@ bool wxRichTextParagraphLayoutBox::SetStyle(const wxRichTextRange& range, const
 /// Get the text attributes for this position.
 bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxTextAttrEx& style)
 {
-    wxRichTextObject* obj wxDUMMY_INITIALIZE(NULL);
+    return DoGetStyle(position, style, true);
+}
 
-    if (style.IsParagraphStyle())
-        obj = GetParagraphAtPosition(position);
+/// Get the text attributes for this position.
+bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxRichTextAttr& style)
+{
+    wxTextAttrEx textAttrEx(style);
+    if (GetStyle(position, textAttrEx))
+    {
+        style = textAttrEx;
+        return true;
+    }
     else
-        obj = GetLeafObjectAtPosition(position);
+        return false;
+}
 
-    if (obj)
+/// Get the content (uncombined) attributes for this position.
+bool wxRichTextParagraphLayoutBox::GetUncombinedStyle(long position, wxTextAttrEx& style)
+{
+    return DoGetStyle(position, style, false);
+}
+
+bool wxRichTextParagraphLayoutBox::GetUncombinedStyle(long position, wxRichTextAttr& style)
+{
+    wxTextAttrEx textAttrEx(style);
+    if (GetUncombinedStyle(position, textAttrEx))
     {
-        style = obj->GetAttributes();
+        style = textAttrEx;
         return true;
     }
     else
         return false;
 }
 
-/// Get the text attributes for this position.
-bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxRichTextAttr& style)
+/// Implementation helper for GetStyle. If combineStyles is true, combine base, paragraph and
+/// context attributes.
+bool wxRichTextParagraphLayoutBox::DoGetStyle(long position, wxTextAttrEx& style, bool combineStyles)
 {
     wxRichTextObject* obj wxDUMMY_INITIALIZE(NULL);
 
     if (style.IsParagraphStyle())
+    {
         obj = GetParagraphAtPosition(position);
-    else
-        obj = GetLeafObjectAtPosition(position);
+        if (obj)
+        {
+#if wxRICHTEXT_USE_DYNAMIC_STYLES
+            if (combineStyles)
+            {
+                // Start with the base style
+                style = GetAttributes();
 
-    if (obj)
-    {
-        style = obj->GetAttributes();
-        return true;
+                // Apply the paragraph style
+                wxRichTextApplyStyle(style, obj->GetAttributes());
+            }
+            else
+                style = obj->GetAttributes();
+#else
+            style = obj->GetAttributes();
+#endif
+            return true;
+        }
+        else
+            return false;
     }
     else
-        return false;
+    {
+        obj = GetLeafObjectAtPosition(position);
+        if (obj)
+        {
+#if wxRICHTEXT_USE_DYNAMIC_STYLES
+            if (combineStyles)
+            {
+                wxRichTextParagraph* para = wxDynamicCast(obj->GetParent(), wxRichTextParagraph);
+                style = para ? para->GetCombinedAttributes(obj->GetAttributes()) : obj->GetAttributes();
+            }
+            else
+                style = obj->GetAttributes();
+#else
+            style = obj->GetAttributes();
+#endif
+            return true;
+        }
+        else
+            return false;
+    }
+    return false;
 }
 
 /// Set default style
 bool wxRichTextParagraphLayoutBox::SetDefaultStyle(const wxTextAttrEx& style)
 {
+    // I don't think the default style should be combined with the previous
+    // default style.
+    m_defaultAttributes = style;
+
+#if 0
     // keep the old attributes if the new style doesn't specify them unless the
     // new style is empty - then reset m_defaultStyle (as there is no other way
     // to do it)
@@ -1680,7 +1782,7 @@ bool wxRichTextParagraphLayoutBox::SetDefaultStyle(const wxTextAttrEx& style)
         m_defaultAttributes = style;
     else
         m_defaultAttributes = wxTextAttrEx::CombineEx(style, m_defaultAttributes, NULL);
-
+#endif
     return true;
 }
 
@@ -1715,7 +1817,12 @@ bool wxRichTextParagraphLayoutBox::HasCharacterAttributes(const wxRichTextRange&
                     if (!child->GetRange().IsOutside(range) && child->IsKindOf(CLASSINFO(wxRichTextPlainText)))
                     {
                         foundCount ++;
-                        if (wxTextAttrEqPartial(child->GetAttributes(), style, style.GetFlags()))
+#if wxRICHTEXT_USE_DYNAMIC_STYLES
+                        wxTextAttrEx textAttr = para->GetCombinedAttributes(child->GetAttributes());
+#else
+                        const wxTextAttrEx& textAttr = child->GetAttributes();
+#endif
+                        if (wxTextAttrEqPartial(textAttr, style, style.GetFlags()))
                             matchingCount ++;
                     }
 
@@ -1759,8 +1866,16 @@ bool wxRichTextParagraphLayoutBox::HasParagraphAttributes(const wxRichTextRange&
 
             if (!para->GetRange().IsOutside(range))
             {
+#if wxRICHTEXT_USE_DYNAMIC_STYLES
+                wxTextAttrEx textAttr = GetAttributes();
+                // Apply the paragraph style
+                wxRichTextApplyStyle(textAttr, para->GetAttributes());
+
+#else
+                const wxTextAttrEx& textAttr = para->GetAttributes();
+#endif
                 foundCount ++;
-                if (wxTextAttrEqPartial(para->GetAttributes(), style, style.GetFlags()))
+                if (wxTextAttrEqPartial(textAttr, style, style.GetFlags()))
                     matchingCount ++;
             }
         }
@@ -1829,6 +1944,40 @@ wxRichTextRange wxRichTextParagraphLayoutBox::GetInvalidRange(bool wholeParagrap
     return range;
 }
 
+/// Apply the style sheet to the buffer, for example if the styles have changed.
+bool wxRichTextParagraphLayoutBox::ApplyStyleSheet(wxRichTextStyleSheet* styleSheet)
+{
+    wxASSERT(styleSheet != NULL);
+    if (!styleSheet)
+        return false;
+
+    int foundCount = 0;
+
+    wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
+    while (node)
+    {
+        wxRichTextParagraph* para = wxDynamicCast(node->GetData(), wxRichTextParagraph);
+        wxASSERT (para != NULL);
+
+        if (para)
+        {
+            if (!para->GetAttributes().GetParagraphStyleName().IsEmpty())
+            {
+                wxRichTextParagraphStyleDefinition* def = styleSheet->FindParagraphStyle(para->GetAttributes().GetParagraphStyleName());
+                if (def)
+                {
+                    para->GetAttributes() = def->GetStyle();
+                    foundCount ++;
+                }
+            }
+        }
+
+        node = node->GetNext();
+    }
+    return foundCount != 0;
+}
+
+
 /*!
  * wxRichTextFragment class declaration
  * This is a lind of paragraph layout box used for storing
@@ -1886,18 +2035,24 @@ wxRichTextParagraph::~wxRichTextParagraph()
 /// Draw the item
 bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range), const wxRichTextRange& selectionRange, const wxRect& WXUNUSED(rect), int WXUNUSED(descent), int style)
 {
+#if wxRICHTEXT_USE_DYNAMIC_STYLES
+    wxTextAttrEx attr = GetCombinedAttributes();
+#else
+    const wxTextAttrEx& attr = GetAttributes();
+#endif
+
     // Draw the bullet, if any
-    if (GetAttributes().GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE)
+    if (attr.GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE)
     {
-        if (GetAttributes().GetLeftSubIndent() != 0)
+        if (attr.GetLeftSubIndent() != 0)
         {
-            int spaceBeforePara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingBefore());
-            // int spaceAfterPara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingAfter());
-            int leftIndent = ConvertTenthsMMToPixels(dc, GetAttributes().GetLeftIndent());
-            // int leftSubIndent = ConvertTenthsMMToPixels(dc, GetAttributes().GetLeftSubIndent());
-            // int rightIndent = ConvertTenthsMMToPixels(dc, GetAttributes().GetRightIndent());
+            int spaceBeforePara = ConvertTenthsMMToPixels(dc, attr.GetParagraphSpacingBefore());
+            // int spaceAfterPara = ConvertTenthsMMToPixels(dc, attr.GetParagraphSpacingAfter());
+            int leftIndent = ConvertTenthsMMToPixels(dc, attr.GetLeftIndent());
+            // int leftSubIndent = ConvertTenthsMMToPixels(dc, attr.GetLeftSubIndent());
+            // int rightIndent = ConvertTenthsMMToPixels(dc, attr.GetRightIndent());
 
-            if (GetAttributes().GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_BITMAP)
+            if (attr.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_BITMAP)
             {
                 // TODO
             }
@@ -1906,11 +2061,11 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range),
                 wxString bulletText = GetBulletText();
                 if (!bulletText.empty())
                 {
-                    if (GetAttributes().GetFont().Ok())
-                        dc.SetFont(GetAttributes().GetFont());
+                    if (attr.GetFont().Ok())
+                        dc.SetFont(attr.GetFont());
 
-                    if (GetAttributes().GetTextColour().Ok())
-                        dc.SetTextForeground(GetAttributes().GetTextColour());
+                    if (attr.GetTextColour().Ok())
+                        dc.SetTextForeground(attr.GetTextColour());
 
                     dc.SetBackgroundMode(wxTRANSPARENT);
 
@@ -1994,29 +2149,35 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range),
 /// Lay the item out
 bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
 {
+#if wxRICHTEXT_USE_DYNAMIC_STYLES
+    wxTextAttrEx attr = GetCombinedAttributes();
+#else
+    const wxTextAttrEx& attr = GetAttributes();
+#endif
+
     // ClearLines();
 
     // Increase the size of the paragraph due to spacing
-    int spaceBeforePara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingBefore());
-    int spaceAfterPara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingAfter());
-    int leftIndent = ConvertTenthsMMToPixels(dc, GetAttributes().GetLeftIndent());
-    int leftSubIndent = ConvertTenthsMMToPixels(dc, GetAttributes().GetLeftSubIndent());
-    int rightIndent = ConvertTenthsMMToPixels(dc, GetAttributes().GetRightIndent());
+    int spaceBeforePara = ConvertTenthsMMToPixels(dc, attr.GetParagraphSpacingBefore());
+    int spaceAfterPara = ConvertTenthsMMToPixels(dc, attr.GetParagraphSpacingAfter());
+    int leftIndent = ConvertTenthsMMToPixels(dc, attr.GetLeftIndent());
+    int leftSubIndent = ConvertTenthsMMToPixels(dc, attr.GetLeftSubIndent());
+    int rightIndent = ConvertTenthsMMToPixels(dc, attr.GetRightIndent());
 
     int lineSpacing = 0;
 
     // Let's assume line spacing of 10 is normal, 15 is 1.5, 20 is 2, etc.
-    if (GetAttributes().GetLineSpacing() > 10 && GetAttributes().GetFont().Ok())
+    if (attr.GetLineSpacing() > 10 && attr.GetFont().Ok())
     {
-        dc.SetFont(GetAttributes().GetFont());
-        lineSpacing = (ConvertTenthsMMToPixels(dc, dc.GetCharHeight()) * GetAttributes().GetLineSpacing())/10;
+        dc.SetFont(attr.GetFont());
+        lineSpacing = (ConvertTenthsMMToPixels(dc, dc.GetCharHeight()) * attr.GetLineSpacing())/10;
     }
 
     // Available space for text on each line differs.
     int availableTextSpaceFirstLine = rect.GetWidth() - leftIndent - rightIndent;
 
     // Bullets start the text at the same position as subsequent lines
-    if (GetAttributes().GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE)
+    if (attr.GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE)
         availableTextSpaceFirstLine -= leftSubIndent;
 
     int availableTextSpaceSubsequentLines = rect.GetWidth() - leftIndent - rightIndent - leftSubIndent;
@@ -2027,7 +2188,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
 
     // If we have a bullet in this paragraph, the start position for the first line's text
     // is actually leftIndent + leftSubIndent.
-    if (GetAttributes().GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE)
+    if (attr.GetBulletStyle() != wxTEXT_ATTR_BULLET_STYLE_NONE)
         startPositionFirstLine = startPositionSubsequentLines;
 
     //bool restrictWidth = wxRichTextHasStyle(style, wxRICHTEXT_FIXED_WIDTH);
@@ -2175,8 +2336,8 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
 
         if (lineHeight == 0)
         {
-            if (GetAttributes().GetFont().Ok())
-                dc.SetFont(GetAttributes().GetFont());
+            if (attr.GetFont().Ok())
+                dc.SetFont(attr.GetFont());
             lineHeight = dc.GetCharHeight();
         }
         if (maxDescent == 0)
@@ -2196,7 +2357,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
     ClearUnusedLines(lineCount);
 
     // Apply styles to wrapped lines
-    ApplyParagraphStyle(rect);
+    ApplyParagraphStyle(attr, rect);
 
     SetCachedSize(wxSize(maxWidth, currentPosition.y + spaceBeforePara + spaceAfterPara));
 
@@ -2206,9 +2367,9 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
 }
 
 /// Apply paragraph styles, such as centering, to wrapped lines
-void wxRichTextParagraph::ApplyParagraphStyle(const wxRect& rect)
+void wxRichTextParagraph::ApplyParagraphStyle(const wxTextAttrEx& attr, const wxRect& rect)
 {
-    if (!GetAttributes().HasAlignment())
+    if (!attr.HasAlignment())
         return;
 
     wxRichTextLineList::compatibility_iterator node = m_cachedLines.GetFirst();
@@ -2220,12 +2381,12 @@ void wxRichTextParagraph::ApplyParagraphStyle(const wxRect& rect)
         wxSize size = line->GetSize();
 
         // centering, right-justification
-        if (GetAttributes().HasAlignment() && GetAttributes().GetAlignment() == wxTEXT_ALIGNMENT_CENTRE)
+        if (attr.HasAlignment() && GetAttributes().GetAlignment() == wxTEXT_ALIGNMENT_CENTRE)
         {
             pos.x = (rect.GetWidth() - size.x)/2 + pos.x;
             line->SetPosition(pos);
         }
-        else if (GetAttributes().HasAlignment() && GetAttributes().GetAlignment() == wxTEXT_ALIGNMENT_RIGHT)
+        else if (attr.HasAlignment() && GetAttributes().GetAlignment() == wxTEXT_ALIGNMENT_RIGHT)
         {
             pos.x = rect.GetRight() - size.x;
             line->SetPosition(pos);
@@ -2873,6 +3034,39 @@ bool wxRichTextParagraph::ClearUnusedLines(int lineCount)
     return true;
 }
 
+/// Get combined attributes of the base style, paragraph style and character style. We use this to dynamically
+/// retrieve the actual style.
+wxTextAttrEx wxRichTextParagraph::GetCombinedAttributes(const wxTextAttr& contentStyle) const
+{
+    wxTextAttrEx attr;
+    wxRichTextBuffer* buf = wxDynamicCast(GetParent(), wxRichTextBuffer);
+    if (buf)
+    {
+        attr = buf->GetBasicStyle();
+        wxRichTextApplyStyle(attr, GetAttributes());
+    }
+    else
+        attr = GetAttributes();
+
+    wxRichTextApplyStyle(attr, contentStyle);
+    return attr;
+}
+
+/// Get combined attributes of the base style and paragraph style.
+wxTextAttrEx wxRichTextParagraph::GetCombinedAttributes() const
+{
+    wxTextAttrEx attr;
+    wxRichTextBuffer* buf = wxDynamicCast(GetParent(), wxRichTextBuffer);
+    if (buf)
+    {
+        attr = buf->GetBasicStyle();
+        wxRichTextApplyStyle(attr, GetAttributes());
+    }
+    else
+        attr = GetAttributes();
+
+    return attr;
+}
 
 /*!
  * wxRichTextLine
@@ -2937,6 +3131,15 @@ wxRichTextPlainText::wxRichTextPlainText(const wxString& text, wxRichTextObject*
 /// Draw the item
 bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichTextRange& selectionRange, const wxRect& rect, int descent, int WXUNUSED(style))
 {
+#if wxRICHTEXT_USE_DYNAMIC_STYLES
+    wxRichTextParagraph* para = wxDynamicCast(GetParent(), wxRichTextParagraph);
+    wxASSERT (para != NULL);
+
+    wxTextAttrEx textAttr(para ? para->GetCombinedAttributes(GetAttributes()) : GetAttributes());
+#else
+    wxTextAttrEx textAttr(GetAttributes());
+#endif
+
     int offset = GetRange().GetStart();
 
     long len = range.GetLength();
@@ -2950,19 +3153,19 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
     // Test for the optimized situations where all is selected, or none
     // is selected.
 
-    if (GetAttributes().GetFont().Ok())
-        dc.SetFont(GetAttributes().GetFont());
+    if (textAttr.GetFont().Ok())
+        dc.SetFont(textAttr.GetFont());
 
     // (a) All selected.
     if (selectionRange.GetStart() <= range.GetStart() && selectionRange.GetEnd() >= range.GetEnd())
     {
-        DrawTabbedString(dc, rect,stringChunk, x, y, true);
+        DrawTabbedString(dc, textAttr, rect, stringChunk, x, y, true);
     }
     // (b) None selected.
     else if (selectionRange.GetEnd() < range.GetStart() || selectionRange.GetStart() > range.GetEnd())
     {
         // Draw all unselected
-        DrawTabbedString(dc, rect,stringChunk, x, y, false);
+        DrawTabbedString(dc, textAttr, rect, stringChunk, x, y, false);
     }
     else
     {
@@ -2981,7 +3184,7 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
                 wxLogDebug(wxT("Mid(%d, %d"), (int)(r1 - offset), (int)fragmentLen);
             wxString stringFragment = m_text.Mid(r1 - offset, fragmentLen);
 
-            DrawTabbedString(dc, rect,stringFragment, x, y, false);
+            DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, false);
         }
 
         // 2. Selected chunk, if any.
@@ -2995,7 +3198,7 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
                 wxLogDebug(wxT("Mid(%d, %d"), (int)(s1 - offset), (int)fragmentLen);
             wxString stringFragment = m_text.Mid(s1 - offset, fragmentLen);
 
-            DrawTabbedString(dc, rect,stringFragment, x, y, true);
+            DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, true);
         }
 
         // 3. Remaining unselected chunk, if any
@@ -3009,16 +3212,16 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
                 wxLogDebug(wxT("Mid(%d, %d"), (int)(s2 - offset), (int)fragmentLen);
             wxString stringFragment = m_text.Mid(s2 - offset, fragmentLen);
 
-            DrawTabbedString(dc, rect,stringFragment, x, y, false);
+            DrawTabbedString(dc, textAttr, rect, stringFragment, x, y, false);
         }
     }
 
     return true;
 }
 
-bool wxRichTextPlainText::DrawTabbedString(wxDC& dc,const wxRect& rect,wxString& str, wxCoord& x, wxCoord& y, bool selected)
+bool wxRichTextPlainText::DrawTabbedString(wxDC& dc, const wxTextAttrEx& attr, const wxRect& rect,wxString& str, wxCoord& x, wxCoord& y, bool selected)
 {
-    wxArrayInt tab_array =  GetAttributes().GetTabs();
+    wxArrayInt tab_array =  attr.GetTabs();
     if (tab_array.IsEmpty())
     {
         // create a default tab list at 10 mm each.
@@ -3049,7 +3252,7 @@ bool wxRichTextPlainText::DrawTabbedString(wxDC& dc,const wxRect& rect,wxString&
     }
     else
     {
-        dc.SetTextForeground(GetAttributes().GetTextColour());
+        dc.SetTextForeground(attr.GetTextColour());
         dc.SetBackgroundMode(wxTRANSPARENT);
     }
 
@@ -3091,11 +3294,21 @@ bool wxRichTextPlainText::DrawTabbedString(wxDC& dc,const wxRect& rect,wxString&
     return true;
 
 }
+
 /// Lay the item out
 bool wxRichTextPlainText::Layout(wxDC& dc, const wxRect& WXUNUSED(rect), int WXUNUSED(style))
 {
-    if (GetAttributes().GetFont().Ok())
-        dc.SetFont(GetAttributes().GetFont());
+#if wxRICHTEXT_USE_DYNAMIC_STYLES
+    wxRichTextParagraph* para = wxDynamicCast(GetParent(), wxRichTextParagraph);
+    wxASSERT (para != NULL);
+
+    wxTextAttrEx textAttr(para ? para->GetCombinedAttributes(GetAttributes()) : GetAttributes());
+#else
+    wxTextAttrEx textAttr(GetAttributes());
+#endif
+
+    if (textAttr.GetFont().Ok())
+        dc.SetFont(textAttr.GetFont());
 
     wxCoord w, h;
     dc.GetTextExtent(m_text, & w, & h, & m_descent);
@@ -3119,12 +3332,21 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz
     if (!range.IsWithin(GetRange()))
         return false;
 
+#if wxRICHTEXT_USE_DYNAMIC_STYLES
+    wxRichTextParagraph* para = wxDynamicCast(GetParent(), wxRichTextParagraph);
+    wxASSERT (para != NULL);
+
+    wxTextAttrEx textAttr(para ? para->GetCombinedAttributes(GetAttributes()) : GetAttributes());
+#else
+    wxTextAttrEx textAttr(GetAttributes());
+#endif
+
     // Always assume unformatted text, since at this level we have no knowledge
     // of line breaks - and we don't need it, since we'll calculate size within
     // formatted text by doing it in chunks according to the line ranges
 
-    if (GetAttributes().GetFont().Ok())
-        dc.SetFont(GetAttributes().GetFont());
+    if (textAttr.GetFont().Ok())
+        dc.SetFont(textAttr.GetFont());
 
     int startPos = range.GetStart() - GetRange().GetStart();
     long len = range.GetLength();
@@ -3134,7 +3356,7 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz
     if (stringChunk.Find(wxT('\t')) >= 0)
     {
         // the string has a tab
-        wxArrayInt tab_array =  GetAttributes().GetTabs();
+        wxArrayInt tab_array =  textAttr.GetTabs();
         if (tab_array.IsEmpty())
         {
             // create a default tab list at 10 mm each.
@@ -3322,12 +3544,28 @@ void wxRichTextBuffer::Reset()
 }
 
 /// Submit command to insert the given text
-bool wxRichTextBuffer::InsertTextWithUndo(long pos, const wxString& text, wxRichTextCtrl* ctrl)
+bool wxRichTextBuffer::InsertTextWithUndo(long pos, const wxString& text, wxRichTextCtrl* ctrl, int flags)
 {
     wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Text"), wxRICHTEXT_INSERT, this, ctrl, false);
 
-    action->GetNewParagraphs().AddParagraphs(text);
-    if (action->GetNewParagraphs().GetChildCount() == 1)
+    wxTextAttrEx* p = NULL;
+    wxTextAttrEx paraAttr;
+    if (flags & wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE)
+    {
+        paraAttr = GetStyleForNewParagraph(pos);
+        if (!paraAttr.IsDefault())
+            p = & paraAttr;
+    }
+
+#if wxRICHTEXT_USE_DYNAMIC_STYLES
+    wxTextAttrEx attr(GetDefaultStyle());
+#else
+    wxTextAttrEx attr(GetBasicStyle());
+    wxRichTextApplyStyle(attr, GetDefaultStyle());
+#endif
+
+    action->GetNewParagraphs().AddParagraphs(text, p);
+    if (action->GetNewParagraphs().GetChildCount() == 1 && text.Find(wxT("\n")) == wxNOT_FOUND)
         action->GetNewParagraphs().SetPartialParagraph(true);
 
     action->SetPosition(pos);
@@ -3341,12 +3579,25 @@ bool wxRichTextBuffer::InsertTextWithUndo(long pos, const wxString& text, wxRich
 }
 
 /// Submit command to insert the given text
-bool wxRichTextBuffer::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl)
+bool wxRichTextBuffer::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl, int flags)
 {
     wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Text"), wxRICHTEXT_INSERT, this, ctrl, false);
 
+    wxTextAttrEx* p = NULL;
+    wxTextAttrEx paraAttr;
+    if (flags & wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE)
+    {
+        paraAttr = GetStyleForNewParagraph(pos);
+        if (!paraAttr.IsDefault())
+            p = & paraAttr;
+    }
+
+#if wxRICHTEXT_USE_DYNAMIC_STYLES
+    wxTextAttrEx attr(GetDefaultStyle());
+#else
     wxTextAttrEx attr(GetBasicStyle());
     wxRichTextApplyStyle(attr, GetDefaultStyle());
+#endif
 
     wxRichTextParagraph* newPara = new wxRichTextParagraph(wxEmptyString, this, & attr);
     action->GetNewParagraphs().AppendChild(newPara);
@@ -3354,6 +3605,9 @@ bool wxRichTextBuffer::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl)
     action->GetNewParagraphs().SetPartialParagraph(false);
     action->SetPosition(pos);
 
+    if (p)
+        newPara->SetAttributes(*p);
+
     // Set the range we'll need to delete in Undo
     action->SetRange(wxRichTextRange(pos, pos));
 
@@ -3363,14 +3617,30 @@ bool wxRichTextBuffer::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl)
 }
 
 /// Submit command to insert the given image
-bool wxRichTextBuffer::InsertImageWithUndo(long pos, const wxRichTextImageBlock& imageBlock, wxRichTextCtrl* ctrl)
+bool wxRichTextBuffer::InsertImageWithUndo(long pos, const wxRichTextImageBlock& imageBlock, wxRichTextCtrl* ctrl, int flags)
 {
     wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Image"), wxRICHTEXT_INSERT, this, ctrl, false);
 
+    wxTextAttrEx* p = NULL;
+    wxTextAttrEx paraAttr;
+    if (flags & wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE)
+    {
+        paraAttr = GetStyleForNewParagraph(pos);
+        if (!paraAttr.IsDefault())
+            p = & paraAttr;
+    }
+
+#if wxRICHTEXT_USE_DYNAMIC_STYLES
+    wxTextAttrEx attr(GetDefaultStyle());
+#else
     wxTextAttrEx attr(GetBasicStyle());
     wxRichTextApplyStyle(attr, GetDefaultStyle());
+#endif
 
     wxRichTextParagraph* newPara = new wxRichTextParagraph(this, & attr);
+    if (p)
+        newPara->SetAttributes(*p);
+
     wxRichTextImage* imageObject = new wxRichTextImage(imageBlock, newPara);
     newPara->AppendChild(imageObject);
     action->GetNewParagraphs().AppendChild(newPara);
@@ -3388,6 +3658,39 @@ bool wxRichTextBuffer::InsertImageWithUndo(long pos, const wxRichTextImageBlock&
     return true;
 }
 
+/// 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 wxRichTextBuffer::GetStyleForNewParagraph(long pos, bool caretPosition) const
+{
+    wxRichTextParagraph* para = GetParagraphAtPosition(pos, caretPosition);
+    if (para)
+    {
+        if (!para->GetAttributes().GetParagraphStyleName().IsEmpty() && GetStyleSheet())
+        {
+            wxRichTextParagraphStyleDefinition* paraDef = GetStyleSheet()->FindParagraphStyle(para->GetAttributes().GetParagraphStyleName());
+            if (paraDef && !paraDef->GetNextStyle().IsEmpty())
+            {
+                wxRichTextParagraphStyleDefinition* nextParaDef = GetStyleSheet()->FindParagraphStyle(paraDef->GetNextStyle());
+                if (nextParaDef)
+                    return nextParaDef->GetStyle();
+            }
+        }
+        wxRichTextAttr attr(para->GetAttributes());
+        int flags = attr.GetFlags();
+
+        // Eliminate character styles
+        flags &= ( (~ wxTEXT_ATTR_FONT) |
+                    (~ wxTEXT_ATTR_TEXT_COLOUR) |
+                    (~ wxTEXT_ATTR_BACKGROUND_COLOUR) );
+        attr.SetFlags(flags);
+
+        return attr;
+    }
+    else
+        return wxRichTextAttr();
+}
+
 /// Submit command to delete this range
 bool wxRichTextBuffer::DeleteRangeWithUndo(const wxRichTextRange& range, long initialCaretPosition, long WXUNUSED(newCaretPositon), wxRichTextCtrl* ctrl)
 {
@@ -4611,22 +4914,43 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxTextAttrEx& style)
         wxFont font = destStyle.GetFont();
 
         if (style.GetFlags() & wxTEXT_ATTR_FONT_FACE)
+        {
+            destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_FACE);
             font.SetFaceName(style.GetFont().GetFaceName());
+        }
 
         if (style.GetFlags() & wxTEXT_ATTR_FONT_SIZE)
+        {
+            destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_SIZE);
             font.SetPointSize(style.GetFont().GetPointSize());
+        }
 
         if (style.GetFlags() & wxTEXT_ATTR_FONT_ITALIC)
+        {
+            destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_ITALIC);
             font.SetStyle(style.GetFont().GetStyle());
+        }
 
         if (style.GetFlags() & wxTEXT_ATTR_FONT_WEIGHT)
+        {
+            destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_WEIGHT);
             font.SetWeight(style.GetFont().GetWeight());
+        }
 
         if (style.GetFlags() & wxTEXT_ATTR_FONT_UNDERLINE)
+        {
+            destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_UNDERLINE);
             font.SetUnderlined(style.GetFont().GetUnderlined());
+        }
 
         if (font != destStyle.GetFont())
+        {
+            int oldFlags = destStyle.GetFlags();
+
             destStyle.SetFont(font);
+
+            destStyle.SetFlags(oldFlags);
+        }
     }
 
     if ( style.GetTextColour().Ok() && style.HasTextColour())
@@ -4685,7 +5009,6 @@ bool wxRichTextApplyStyle(wxRichTextAttr& destStyle, const wxTextAttrEx& style)
 
 bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style)
 {
-
     // Whole font. Avoiding setting individual attributes if possible, since
     // it recreates the font each time.
     if ((style.GetFlags() & (wxTEXT_ATTR_FONT)) == (wxTEXT_ATTR_FONT))
@@ -4698,22 +5021,43 @@ bool wxRichTextApplyStyle(wxTextAttrEx& destStyle, const wxRichTextAttr& style)
         wxFont font = destStyle.GetFont();
 
         if (style.GetFlags() & wxTEXT_ATTR_FONT_FACE)
+        {
+            destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_FACE);
             font.SetFaceName(style.GetFontFaceName());
+        }
 
         if (style.GetFlags() & wxTEXT_ATTR_FONT_SIZE)
+        {
+            destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_SIZE);
             font.SetPointSize(style.GetFontSize());
+        }
 
         if (style.GetFlags() & wxTEXT_ATTR_FONT_ITALIC)
+        {
+            destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_ITALIC);
             font.SetStyle(style.GetFontStyle());
+        }
 
         if (style.GetFlags() & wxTEXT_ATTR_FONT_WEIGHT)
+        {
+            destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_WEIGHT);
             font.SetWeight(style.GetFontWeight());
+        }
 
         if (style.GetFlags() & wxTEXT_ATTR_FONT_UNDERLINE)
+        {
+            destStyle.SetFlags(destStyle.GetFlags() | wxTEXT_ATTR_FONT_UNDERLINE);
             font.SetUnderlined(style.GetFontUnderlined());
+        }
 
         if (font != destStyle.GetFont())
+        {
+            int oldFlags = destStyle.GetFlags();
+
             destStyle.SetFont(font);
+
+            destStyle.SetFlags(oldFlags);
+        }
     }
 
     if ( style.GetTextColour().Ok() && style.HasTextColour())
@@ -4867,6 +5211,33 @@ wxRichTextAttr::operator wxTextAttrEx () const
     return attr;
 }
 
+// Equality test
+bool wxRichTextAttr::operator== (const wxRichTextAttr& attr) const
+{
+    return  GetFlags() == attr.GetFlags() &&
+
+            GetTextColour() == attr.GetTextColour() &&
+            GetBackgroundColour() == attr.GetBackgroundColour() &&
+
+            GetAlignment() == attr.GetAlignment() &&
+            GetLeftIndent() == attr.GetLeftIndent() &&
+            GetLeftSubIndent() == attr.GetLeftSubIndent() &&
+            GetRightIndent() == attr.GetRightIndent() &&
+            //GetTabs() == attr.GetTabs() &&
+
+            GetParagraphSpacingAfter() == attr.GetParagraphSpacingAfter() &&
+            GetParagraphSpacingBefore() == attr.GetParagraphSpacingBefore() &&
+            GetLineSpacing() == attr.GetLineSpacing() &&
+            GetCharacterStyleName() == attr.GetCharacterStyleName() &&
+            GetParagraphStyleName() == attr.GetParagraphStyleName() &&
+
+            m_fontSize == attr.m_fontSize &&
+            m_fontStyle == attr.m_fontStyle &&
+            m_fontWeight == attr.m_fontWeight &&
+            m_fontUnderlined == attr.m_fontUnderlined &&
+            m_fontFaceName == attr.m_fontFaceName;
+}
+
 // Copy to a wxTextAttr
 void wxRichTextAttr::CopyTo(wxTextAttrEx& attr) const
 {
@@ -4877,7 +5248,6 @@ void wxRichTextAttr::CopyTo(wxTextAttrEx& attr) const
     attr.SetLeftIndent(GetLeftIndent(), GetLeftSubIndent());
     attr.SetRightIndent(GetRightIndent());
     attr.SetFont(CreateFont());
-    attr.SetFlags(GetFlags()); // Important: set after SetFont, since SetFont sets flags
 
     attr.SetParagraphSpacingAfter(m_paragraphSpacingAfter);
     attr.SetParagraphSpacingBefore(m_paragraphSpacingBefore);
@@ -4888,6 +5258,7 @@ void wxRichTextAttr::CopyTo(wxTextAttrEx& attr) const
     attr.SetCharacterStyleName(m_characterStyleName);
     attr.SetParagraphStyleName(m_paragraphStyleName);
 
+    attr.SetFlags(GetFlags()); // Important: set after SetFont and others, since they set flags
 }
 
 // Create font from font attributes.
index bb941820ce2123255b903effd21f850bae18d04f..b77d1a2fc1866ee7d813af565a9293caa93ebbbd 100644 (file)
 #include "wx/richtext/richtextstyles.h"
 
 #ifndef WX_PRECOMP
+    #include "wx/wx.h"
     #include "wx/settings.h"
-    #include "wx/menu.h"
-    #include "wx/intl.h"
-    #include "wx/log.h"
-    #include "wx/stopwatch.h"
 #endif
 
 #include "wx/textfile.h"
@@ -145,10 +142,13 @@ bool wxRichTextCtrl::Create( wxWindow* parent, wxWindowID id, const wxString& va
     attributes.SetBackgroundColour(*wxWHITE);
     attributes.SetAlignment(wxTEXT_ALIGNMENT_LEFT);
     attributes.SetFlags(wxTEXT_ATTR_ALL);
-
-    SetDefaultStyle(attributes);
     SetBasicStyle(attributes);
 
+    // The default attributes will be merged with base attributes, so
+    // can be empty to begin with
+    wxTextAttrEx defaultAttributes;
+    SetDefaultStyle(defaultAttributes);
+
     SetBackgroundColour(*wxWHITE);
     SetBackgroundStyle(wxBG_STYLE_CUSTOM);
 
@@ -466,7 +466,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
 
         DeleteSelectedContent(& newPos);
 
-        GetBuffer().InsertNewlineWithUndo(newPos+1, this);
+        GetBuffer().InsertNewlineWithUndo(newPos+1, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE);
 
         wxRichTextEvent cmdEvent(
             wxEVT_COMMAND_RICHTEXT_RETURN,
@@ -545,7 +545,7 @@ void wxRichTextCtrl::OnChar(wxKeyEvent& event)
         DeleteSelectedContent(& newPos);
 
         wxString str = (wxChar) event.GetKeyCode();
-        GetBuffer().InsertTextWithUndo(newPos+1, str, this);
+        GetBuffer().InsertTextWithUndo(newPos+1, str, this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE);
 
         EndBatchUndo();
 
@@ -1528,7 +1528,7 @@ bool wxRichTextCtrl::RecreateBuffer(const wxSize& size)
 #if !wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
 bool wxRichTextCtrl::LoadFile(const wxString& filename, int fileType)
 {
-    return DoLoadFile(filename, fileType);    
+    return DoLoadFile(filename, fileType);
 }
 
 bool wxRichTextCtrl::SaveFile(const wxString& filename, int fileType)
@@ -1744,6 +1744,7 @@ void wxRichTextCtrl::WriteText(const wxString& value)
 void wxRichTextCtrl::DoWriteText(const wxString& value, bool WXUNUSED(selectionOnly))
 {
     wxString valueDos = wxTextFile::Translate(value, wxTextFileType_Unix);
+
     GetBuffer().InsertTextWithUndo(m_caretPosition+1, valueDos, this);
 }
 
@@ -1811,7 +1812,7 @@ void wxRichTextCtrl::Copy()
 {
     if (CanCopy())
     {
-        wxRichTextRange range = GetSelectionRange();
+        wxRichTextRange range = GetInternalSelectionRange();
         GetBuffer().CopyToClipboard(range);
     }
 }
@@ -1820,7 +1821,7 @@ void wxRichTextCtrl::Cut()
 {
     if (CanCut())
     {
-        wxRichTextRange range = GetSelectionRange();
+        wxRichTextRange range = GetInternalSelectionRange();
         GetBuffer().CopyToClipboard(range);
 
         DeleteSelectedContent();
@@ -2258,7 +2259,7 @@ const wxTextAttr& wxRichTextCtrl::GetDefaultStyle() const
 
 bool wxRichTextCtrl::GetStyle(long position, wxTextAttr& style)
 {
-    wxTextAttrEx attr;
+    wxTextAttrEx attr(style);
     if (GetBuffer().GetStyle(position, attr))
     {
         style = attr;
@@ -2278,6 +2279,30 @@ bool wxRichTextCtrl::GetStyle(long position, wxRichTextAttr& style)
     return GetBuffer().GetStyle(position, style);
 }
 
+/// Get the content (uncombined) attributes for this position.
+
+bool wxRichTextCtrl::GetUncombinedStyle(long position, wxTextAttr& style)
+{
+    wxTextAttrEx attr(style);
+    if (GetBuffer().GetUncombinedStyle(position, attr))
+    {
+        style = attr;
+        return true;
+    }
+    else
+        return false;
+}
+
+bool wxRichTextCtrl::GetUncombinedStyle(long position, wxTextAttrEx& style)
+{
+    return GetBuffer().GetUncombinedStyle(position, style);
+}
+
+bool wxRichTextCtrl::GetUncombinedStyle(long position, wxRichTextAttr& style)
+{
+    return GetBuffer().GetUncombinedStyle(position, style);
+}
+
 /// Set font, and also the buffer attributes
 bool wxRichTextCtrl::SetFont(const wxFont& font)
 {
@@ -2290,7 +2315,15 @@ bool wxRichTextCtrl::SetFont(const wxFont& font)
     wxTextAttrEx attr = GetBuffer().GetAttributes();
     attr.SetFont(font);
     GetBuffer().SetBasicStyle(attr);
+
+#if !wxRICHTEXT_DERIVES_FROM_TEXTCTRLBASE
+    // Don't set the default style, since it will be inherited from
+    // the basic style.
     GetBuffer().SetDefaultStyle(attr);
+#endif
+
+    GetBuffer().Invalidate(wxRICHTEXT_ALL);
+    Refresh(false);
 
     return true;
 }
@@ -2508,8 +2541,8 @@ bool wxRichTextCtrl::IsSelectionUnderlined()
         // to see what the effect would be if we started typing.
         wxRichTextAttr attr;
         attr.SetFlags(wxTEXT_ATTR_FONT_UNDERLINE);
-
         long pos = GetAdjustedCaretPosition(GetCaretPosition());
+
         if (GetStyle(pos, attr))
         {
             if (IsDefaultStyleShowing())
@@ -2618,6 +2651,24 @@ void wxRichTextCtrl::ApplyStyle(wxRichTextStyleDefinition* def)
         SetAndShowDefaultStyle(attr);
 }
 
+/// Apply the style sheet to the buffer, for example if the styles have changed.
+bool wxRichTextCtrl::ApplyStyleSheet(wxRichTextStyleSheet* styleSheet)
+{
+    if (!styleSheet)
+        styleSheet = GetBuffer().GetStyleSheet();
+    if (!styleSheet)
+        return false;
+
+    if (GetBuffer().ApplyStyleSheet(styleSheet))
+    {
+        GetBuffer().Invalidate(wxRICHTEXT_ALL);
+        Refresh(false);
+        return true;
+    }
+    else
+        return false;
+}
+
 /// Sets the default style to the style under the cursor
 bool wxRichTextCtrl::SetDefaultStyleToCursorStyle()
 {
@@ -2627,7 +2678,11 @@ bool wxRichTextCtrl::SetDefaultStyleToCursorStyle()
     // If at the start of a paragraph, use the next position.
     long pos = GetAdjustedCaretPosition(GetCaretPosition());
 
+#if wxRICHTEXT_USE_DYNAMIC_STYLES
+    if (GetUncombinedStyle(pos, attr))
+#else
     if (GetStyle(pos, attr))
+#endif
     {
         SetDefaultStyle(attr);
         return true;
@@ -2676,7 +2731,7 @@ void wxRichTextCtrl::SetSelectionRange(const wxRichTextRange& range)
         range1.SetEnd(range1.GetEnd() - 1);
 
     wxASSERT( range1.GetStart() > range1.GetEnd() );
-    
+
     SetInternalSelectionRange(range1);
 }
 
index 183daea53a2c4174575064ca874e0f656ec7870d..ada328a49e6221e1e01b8c432ba7f3169bc18ea0 100644 (file)
@@ -13,7 +13,7 @@
 #include "wx/wxprec.h"
 
 #ifdef __BORLANDC__
-    #pragma hdrstop
+  #pragma hdrstop
 #endif
 
 #if wxUSE_RICHTEXT
@@ -21,8 +21,7 @@
 #include "wx/richtext/richtextstyles.h"
 
 #ifndef WX_PRECOMP
-    #include "wx/dcclient.h"
-    #include "wx/module.h"
+  #include "wx/wx.h"
 #endif
 
 #include "wx/filename.h"
@@ -35,6 +34,38 @@ IMPLEMENT_CLASS(wxRichTextStyleDefinition, wxObject)
 IMPLEMENT_CLASS(wxRichTextCharacterStyleDefinition, wxRichTextStyleDefinition)
 IMPLEMENT_CLASS(wxRichTextParagraphStyleDefinition, wxRichTextStyleDefinition)
 
+/*!
+ * A definition
+ */
+
+void wxRichTextStyleDefinition::Copy(const wxRichTextStyleDefinition& def)
+{
+    m_name = def.m_name;
+    m_baseStyle = def.m_baseStyle;
+    m_style = def.m_style;
+}
+
+bool wxRichTextStyleDefinition::Eq(const wxRichTextStyleDefinition& def) const
+{
+    return (m_name == def.m_name && m_baseStyle == def.m_baseStyle && m_style == def.m_style);
+}
+
+/*!
+ * Paragraph style definition
+ */
+
+void wxRichTextParagraphStyleDefinition::Copy(const wxRichTextParagraphStyleDefinition& def)
+{
+    wxRichTextStyleDefinition::Copy(def);
+
+    m_nextStyle = def.m_nextStyle;
+}
+
+bool wxRichTextParagraphStyleDefinition::operator ==(const wxRichTextParagraphStyleDefinition& def) const
+{
+    return (Eq(def) && m_nextStyle == def.m_nextStyle);
+}
+
 /*!
  * The style manager
  */
@@ -89,6 +120,48 @@ void wxRichTextStyleSheet::DeleteStyles()
     WX_CLEAR_LIST(wxList, m_paragraphStyleDefinitions);
 }
 
+/// Add a definition to the character style list
+bool wxRichTextStyleSheet::AddCharacterStyle(wxRichTextCharacterStyleDefinition* def)
+{
+    def->GetStyle().SetCharacterStyleName(def->GetName());
+    return AddStyle(m_characterStyleDefinitions, def);
+}
+
+/// Add a definition to the paragraph style list
+bool wxRichTextStyleSheet::AddParagraphStyle(wxRichTextParagraphStyleDefinition* def)
+{
+    def->GetStyle().SetParagraphStyleName(def->GetName());
+    return AddStyle(m_paragraphStyleDefinitions, def);
+}
+
+/// Copy
+void wxRichTextStyleSheet::Copy(const wxRichTextStyleSheet& sheet)
+{
+    DeleteStyles();
+
+    wxList::compatibility_iterator node;
+
+    for (node = sheet.m_characterStyleDefinitions.GetFirst(); node; node = node->GetNext())
+    {
+        wxRichTextCharacterStyleDefinition* def = (wxRichTextCharacterStyleDefinition*) node->GetData();
+        AddCharacterStyle(new wxRichTextCharacterStyleDefinition(*def));
+    }
+
+    for (node = sheet.m_paragraphStyleDefinitions.GetFirst(); node; node = node->GetNext())
+    {
+        wxRichTextParagraphStyleDefinition* def = (wxRichTextParagraphStyleDefinition*) node->GetData();
+        AddParagraphStyle(new wxRichTextParagraphStyleDefinition(*def));
+    }
+}
+
+/// Equality
+bool wxRichTextStyleSheet::operator==(const wxRichTextStyleSheet& WXUNUSED(sheet)) const
+{
+    // TODO
+    return false;
+}
+
+
 #if wxUSE_HTML
 /*!
  * wxRichTextStyleListBox class declaration
@@ -316,8 +389,10 @@ void wxRichTextStyleListBox::OnIdle(wxIdleEvent& event)
 {
     if (CanAutoSetSelection() && GetRichTextCtrl())
     {
-        wxRichTextParagraph* para = GetRichTextCtrl()->GetBuffer().GetParagraphAtPosition(GetRichTextCtrl()->GetCaretPosition());
-        wxRichTextObject* obj = GetRichTextCtrl()->GetBuffer().GetLeafObjectAtPosition(GetRichTextCtrl()->GetCaretPosition());
+        int adjustedCaretPos = GetRichTextCtrl()->GetAdjustedCaretPosition(GetRichTextCtrl()->GetCaretPosition());
+
+        wxRichTextParagraph* para = GetRichTextCtrl()->GetBuffer().GetParagraphAtPosition(adjustedCaretPos);
+        wxRichTextObject* obj = GetRichTextCtrl()->GetBuffer().GetLeafObjectAtPosition(adjustedCaretPos);
 
         wxString styleName;
 
@@ -483,8 +558,10 @@ void wxRichTextStyleComboCtrl::OnIdle(wxIdleEvent& event)
 {
     if (GetRichTextCtrl() && !IsPopupShown())
     {
-        wxRichTextParagraph* para = GetRichTextCtrl()->GetBuffer().GetParagraphAtPosition(GetRichTextCtrl()->GetCaretPosition());
-        wxRichTextObject* obj = GetRichTextCtrl()->GetBuffer().GetLeafObjectAtPosition(GetRichTextCtrl()->GetCaretPosition());
+        int adjustedCaretPos = GetRichTextCtrl()->GetAdjustedCaretPosition(GetRichTextCtrl()->GetCaretPosition());
+
+        wxRichTextParagraph* para = GetRichTextCtrl()->GetBuffer().GetParagraphAtPosition(adjustedCaretPos);
+        wxRichTextObject* obj = GetRichTextCtrl()->GetBuffer().GetLeafObjectAtPosition(adjustedCaretPos);
 
         wxString styleName;