]> git.saurik.com Git - wxWidgets.git/blobdiff - src/richtext/richtextbuffer.cpp
Fix wxOSX/Carbon compilation after wxListCtrlBase introduction.
[wxWidgets.git] / src / richtext / richtextbuffer.cpp
index ce0f18c0041d0373468b11b8e1d8fcaa8143a905..28d3e3fe610b571835339e737681684920e79c78 100644 (file)
@@ -696,7 +696,7 @@ bool wxRichTextObject::DrawBoxAttributes(wxDC& dc, wxRichTextBuffer* buffer, con
 
         dc.SetPen(pen);
         dc.SetBrush(brush);
-        dc.DrawRectangle(marginRect);
+        dc.DrawRectangle(borderRect);
     }
 
     if (flags & wxRICHTEXT_DRAW_GUIDELINES)
@@ -778,7 +778,7 @@ bool wxRichTextObject::DrawBorder(wxDC& dc, wxRichTextBuffer* buffer, const wxTe
             wxBrush brush(col);
             dc.SetPen(pen);
             dc.SetBrush(brush);
-            dc.DrawRectangle(rect.x - borderRight, rect.y, borderRight, rect.height);
+            dc.DrawRectangle(rect.x + rect.width - borderRight, rect.y, borderRight, rect.height);
         }
     }
 
@@ -835,7 +835,7 @@ bool wxRichTextObject::DrawBorder(wxDC& dc, wxRichTextBuffer* buffer, const wxTe
             wxBrush brush(col);
             dc.SetPen(pen);
             dc.SetBrush(brush);
-            dc.DrawRectangle(rect.x, rect.y - rect.height - borderBottom, rect.width, borderBottom);
+            dc.DrawRectangle(rect.x, rect.y + rect.height - borderBottom, rect.width, borderBottom);
         }
     }
 
@@ -864,7 +864,7 @@ bool wxRichTextObject::GetBoxRects(wxDC& dc, wxRichTextBuffer* buffer, const wxR
         marginRight = converter.GetPixels(attr.GetTextBoxAttr().GetMargins().GetRight());
     if (attr.GetTextBoxAttr().GetMargins().GetTop().IsValid())
         marginTop = converter.GetPixels(attr.GetTextBoxAttr().GetMargins().GetTop());
-    if (attr.GetTextBoxAttr().GetMargins().GetLeft().IsValid())
+    if (attr.GetTextBoxAttr().GetMargins().GetBottom().IsValid())
         marginBottom = converter.GetPixels(attr.GetTextBoxAttr().GetMargins().GetBottom());
 
     if (attr.GetTextBoxAttr().GetBorder().GetLeft().GetWidth().IsValid())
@@ -873,7 +873,7 @@ bool wxRichTextObject::GetBoxRects(wxDC& dc, wxRichTextBuffer* buffer, const wxR
         borderRight = converter.GetPixels(attr.GetTextBoxAttr().GetBorder().GetRight().GetWidth());
     if (attr.GetTextBoxAttr().GetBorder().GetTop().GetWidth().IsValid())
         borderTop = converter.GetPixels(attr.GetTextBoxAttr().GetBorder().GetTop().GetWidth());
-    if (attr.GetTextBoxAttr().GetBorder().GetLeft().GetWidth().IsValid())
+    if (attr.GetTextBoxAttr().GetBorder().GetBottom().GetWidth().IsValid())
         borderBottom = converter.GetPixels(attr.GetTextBoxAttr().GetBorder().GetBottom().GetWidth());
 
     if (attr.GetTextBoxAttr().GetPadding().GetLeft().IsValid())
@@ -1914,6 +1914,20 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl
     // A way to force speedy rest-of-buffer layout (the 'else' below)
     bool forceQuickLayout = false;
 
+    // First get the size of the paragraphs we won't be laying out
+    wxRichTextObjectList::compatibility_iterator n = m_children.GetFirst();
+    while (n && n != node)
+    {
+        wxRichTextParagraph* child = wxDynamicCast(n->GetData(), wxRichTextParagraph);
+        if (child)
+        {
+            maxWidth = wxMax(maxWidth, child->GetCachedSize().x);
+            maxMinWidth = wxMax(maxMinWidth, child->GetMinSize().x);
+            maxMaxWidth = wxMax(maxMaxWidth, child->GetMaxSize().x);
+        }
+        n = n->GetNext();
+    }
+
     while (node)
     {
         // Assume this box only contains paragraphs
@@ -2676,7 +2690,7 @@ bool wxRichTextParagraphLayoutBox::CopyFragment(const wxRichTextRange& range, wx
             topTailRange.SetEnd(fragment.GetOwnRange().GetEnd());
         }
 
-        if (topTailRange.GetStart() < (lastPara->GetRange().GetEnd()-1))
+        if (topTailRange.GetStart() < lastPara->GetRange().GetEnd())
         {
             lastPara->DeleteRange(topTailRange);
 
@@ -4338,7 +4352,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
     int lineSpacing = 0;
 
     // Let's assume line spacing of 10 is normal, 15 is 1.5, 20 is 2, etc.
-    if (attr.HasLineSpacing() && attr.GetLineSpacing() > 0 && attr.GetFont().Ok())
+    if (attr.HasLineSpacing() && attr.GetLineSpacing() > 0 && attr.GetFont().IsOk())
     {
         wxCheckSetFont(dc, attr.GetFont());
         lineSpacing = (int) (double(dc.GetCharHeight()) * (double(attr.GetLineSpacing())/10.0 - 1.0));
@@ -4722,7 +4736,7 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
     // this size. TODO: take into account line breaks.
     {
         wxRect marginRect, borderRect, contentRect, paddingRect, outlineRect;
-        contentRect = wxRect(wxPoint(0, 0), wxSize(paraSize.x, currentPosition.y + spaceAfterPara));
+        contentRect = wxRect(wxPoint(0, 0), wxSize(paraSize.x + wxMax(leftIndent, leftIndent + leftSubIndent) + rightIndent, currentPosition.y + spaceAfterPara));
         GetBoxRects(dc, buffer, GetAttributes(), marginRect, borderRect, contentRect, paddingRect, outlineRect);
         SetMaxSize(marginRect.GetSize());
     }
@@ -5949,7 +5963,7 @@ bool wxRichTextPlainText::Draw(wxDC& dc, const wxRichTextRange& range, const wxR
     int charHeight = dc.GetCharHeight();
 
     int x, y;
-    if ( textFont.Ok() )
+    if ( textFont.IsOk() )
     {
         if ( textAttr.HasTextEffects() && (textAttr.GetTextEffects() & wxTEXT_ATTR_EFFECT_SUPERSCRIPT) )
         {
@@ -6248,7 +6262,7 @@ bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& siz
 
     bool bScript(false);
     wxFont font(GetBuffer()->GetFontTable().FindFont(textAttr));
-    if (font.Ok())
+    if (font.IsOk())
     {
         if ( textAttr.HasTextEffects() && ( (textAttr.GetTextEffects() & wxTEXT_ATTR_EFFECT_SUPERSCRIPT)
             || (textAttr.GetTextEffects() & wxTEXT_ATTR_EFFECT_SUBSCRIPT) ) )
@@ -6610,11 +6624,11 @@ wxRichTextStyleSheet* wxRichTextBuffer::PopStyleSheet()
 /// Submit command to insert paragraphs
 bool wxRichTextBuffer::InsertParagraphsWithUndo(long pos, const wxRichTextParagraphLayoutBox& paragraphs, wxRichTextCtrl* ctrl, int flags)
 {
-    return ctrl->GetFocusObject()->InsertParagraphsWithUndo(pos, paragraphs, ctrl, this, flags);
+    return ctrl->GetFocusObject()->InsertParagraphsWithUndo(this, pos, paragraphs, ctrl, flags);
 }
 
 /// Submit command to insert paragraphs
-bool wxRichTextParagraphLayoutBox::InsertParagraphsWithUndo(long pos, const wxRichTextParagraphLayoutBox& paragraphs, wxRichTextCtrl* ctrl, wxRichTextBuffer* buffer, int WXUNUSED(flags))
+bool wxRichTextParagraphLayoutBox::InsertParagraphsWithUndo(wxRichTextBuffer* buffer, long pos, const wxRichTextParagraphLayoutBox& paragraphs, wxRichTextCtrl* ctrl, int WXUNUSED(flags))
 {
     wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Text"), wxRICHTEXT_INSERT, buffer, this, ctrl, false);
 
@@ -6637,11 +6651,11 @@ bool wxRichTextParagraphLayoutBox::InsertParagraphsWithUndo(long pos, const wxRi
 /// Submit command to insert the given text
 bool wxRichTextBuffer::InsertTextWithUndo(long pos, const wxString& text, wxRichTextCtrl* ctrl, int flags)
 {
-    return ctrl->GetFocusObject()->InsertTextWithUndo(pos, text, ctrl, this, flags);
+    return ctrl->GetFocusObject()->InsertTextWithUndo(this, pos, text, ctrl, flags);
 }
 
 /// Submit command to insert the given text
-bool wxRichTextParagraphLayoutBox::InsertTextWithUndo(long pos, const wxString& text, wxRichTextCtrl* ctrl, wxRichTextBuffer* buffer, int flags)
+bool wxRichTextParagraphLayoutBox::InsertTextWithUndo(wxRichTextBuffer* buffer, long pos, const wxString& text, wxRichTextCtrl* ctrl, int flags)
 {
     wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Text"), wxRICHTEXT_INSERT, buffer, this, ctrl, false);
 
@@ -6681,11 +6695,11 @@ bool wxRichTextParagraphLayoutBox::InsertTextWithUndo(long pos, const wxString&
 /// Submit command to insert the given text
 bool wxRichTextBuffer::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl, int flags)
 {
-    return ctrl->GetFocusObject()->InsertNewlineWithUndo(pos, ctrl, this, flags);
+    return ctrl->GetFocusObject()->InsertNewlineWithUndo(this, pos, ctrl, flags);
 }
 
 /// Submit command to insert the given text
-bool wxRichTextParagraphLayoutBox::InsertNewlineWithUndo(long pos, wxRichTextCtrl* ctrl, wxRichTextBuffer* buffer, int flags)
+bool wxRichTextParagraphLayoutBox::InsertNewlineWithUndo(wxRichTextBuffer* buffer, long pos, wxRichTextCtrl* ctrl, int flags)
 {
     wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Text"), wxRICHTEXT_INSERT, buffer, this, ctrl, false);
 
@@ -6761,12 +6775,12 @@ bool wxRichTextParagraphLayoutBox::InsertNewlineWithUndo(long pos, wxRichTextCtr
 bool wxRichTextBuffer::InsertImageWithUndo(long pos, const wxRichTextImageBlock& imageBlock, wxRichTextCtrl* ctrl, int flags,
                                             const wxRichTextAttr& textAttr)
 {
-    return ctrl->GetFocusObject()->InsertImageWithUndo(pos, imageBlock, ctrl, this, flags, textAttr);
+    return ctrl->GetFocusObject()->InsertImageWithUndo(this, pos, imageBlock, ctrl, flags, textAttr);
 }
 
 /// Submit command to insert the given image
-bool wxRichTextParagraphLayoutBox::InsertImageWithUndo(long pos, const wxRichTextImageBlock& imageBlock,
-                                                        wxRichTextCtrl* ctrl, wxRichTextBuffer* buffer, int flags,
+bool wxRichTextParagraphLayoutBox::InsertImageWithUndo(wxRichTextBuffer* buffer, long pos, const wxRichTextImageBlock& imageBlock,
+                                                        wxRichTextCtrl* ctrl, int flags,
                                                         const wxRichTextAttr& textAttr)
 {
     wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Image"), wxRICHTEXT_INSERT, buffer, this, ctrl, false);
@@ -6807,11 +6821,11 @@ bool wxRichTextParagraphLayoutBox::InsertImageWithUndo(long pos, const wxRichTex
 // Insert an object with no change of it
 wxRichTextObject* wxRichTextBuffer::InsertObjectWithUndo(long pos, wxRichTextObject *object, wxRichTextCtrl* ctrl, int flags)
 {
-    return ctrl->GetFocusObject()->InsertObjectWithUndo(pos, object, ctrl, this, flags);
+    return ctrl->GetFocusObject()->InsertObjectWithUndo(this, pos, object, ctrl, flags);
 }
 
 // Insert an object with no change of it
-wxRichTextObject* wxRichTextParagraphLayoutBox::InsertObjectWithUndo(long pos, wxRichTextObject *object, wxRichTextCtrl* ctrl, wxRichTextBuffer* buffer, int flags)
+wxRichTextObject* wxRichTextParagraphLayoutBox::InsertObjectWithUndo(wxRichTextBuffer* buffer, long pos, wxRichTextObject *object, wxRichTextCtrl* ctrl, int flags)
 {
     wxRichTextAction* action = new wxRichTextAction(NULL, _("Insert Object"), wxRICHTEXT_INSERT, buffer, this, ctrl, false);
 
@@ -7579,7 +7593,7 @@ bool wxRichTextBuffer::PasteFromClipboard(long position)
                 wxRichTextBuffer* richTextBuffer = data.GetRichTextBuffer();
                 if (richTextBuffer)
                 {
-                    container->InsertParagraphsWithUndo(position+1, *richTextBuffer, GetRichTextCtrl(), this, 0);
+                    container->InsertParagraphsWithUndo(this, position+1, *richTextBuffer, GetRichTextCtrl(), 0);
                     if (GetRichTextCtrl())
                         GetRichTextCtrl()->ShowPosition(position + richTextBuffer->GetOwnRange().GetEnd());
                     delete richTextBuffer;
@@ -7607,7 +7621,7 @@ bool wxRichTextBuffer::PasteFromClipboard(long position)
 #else
                 wxString text2 = text;
 #endif
-                container->InsertTextWithUndo(position+1, text2, GetRichTextCtrl(), this, wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE);
+                container->InsertTextWithUndo(this, position+1, text2, GetRichTextCtrl(), wxRICHTEXT_INSERT_WITH_PREVIOUS_PARAGRAPH_STYLE);
 
                 if (GetRichTextCtrl())
                     GetRichTextCtrl()->ShowPosition(position + text2.Length());
@@ -7792,7 +7806,7 @@ int wxRichTextBuffer::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition, w
 
 bool wxRichTextStdRenderer::DrawStandardBullet(wxRichTextParagraph* paragraph, wxDC& dc, const wxRichTextAttr& bulletAttr, const wxRect& rect)
 {
-    if (bulletAttr.GetTextColour().Ok())
+    if (bulletAttr.GetTextColour().IsOk())
     {
         wxCheckSetPen(dc, wxPen(bulletAttr.GetTextColour()));
         wxCheckSetBrush(dc, wxBrush(bulletAttr.GetTextColour()));
@@ -7892,7 +7906,7 @@ bool wxRichTextStdRenderer::DrawTextBullet(wxRichTextParagraph* paragraph, wxDC&
 
         wxCheckSetFont(dc, font);
 
-        if (attr.GetTextColour().Ok())
+        if (attr.GetTextColour().IsOk())
             dc.SetTextForeground(attr.GetTextColour());
 
         dc.SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
@@ -8138,15 +8152,11 @@ bool wxRichTextTable::Layout(wxDC& dc, const wxRect& rect, int style)
     }
 
     // Get internal padding
-    int paddingLeft = 0, paddingRight = 0, paddingTop = 0, paddingBottom = 0;
+    int paddingLeft = 0, paddingTop = 0;
     if (GetAttributes().GetTextBoxAttr().GetPadding().GetLeft().IsValid())
         paddingLeft = converter.GetPixels(GetAttributes().GetTextBoxAttr().GetPadding().GetLeft());
-    if (GetAttributes().GetTextBoxAttr().GetPadding().GetRight().IsValid())
-        paddingRight = converter.GetPixels(GetAttributes().GetTextBoxAttr().GetPadding().GetRight());
     if (GetAttributes().GetTextBoxAttr().GetPadding().GetTop().IsValid())
         paddingTop = converter.GetPixels(GetAttributes().GetTextBoxAttr().GetPadding().GetTop());
-    if (GetAttributes().GetTextBoxAttr().GetPadding().GetLeft().IsValid())
-        paddingBottom = converter.GetPixels(GetAttributes().GetTextBoxAttr().GetPadding().GetBottom());
 
     // Assume that left and top padding are also used for inter-cell padding.
     int paddingX = paddingLeft;
@@ -9911,7 +9921,7 @@ bool wxRichTextImage::Draw(wxDC& dc, const wxRichTextRange& range, const wxRichT
     if (!LoadImageCache(dc))
         return false;
 
-    DrawBoxAttributes(dc, GetBuffer(), GetAttributes(), wxRect(GetPosition(), GetCachedSize()));
+    DrawBoxAttributes(dc, GetBuffer(), GetAttributes(), wxRect(rect.GetPosition(), GetCachedSize()));
 
 #if 0
     int y = rect.y + (rect.height - m_imageCache.GetHeight());
@@ -10153,7 +10163,7 @@ IMPLEMENT_CLASS(wxRichTextFileHandler, wxObject)
 bool wxRichTextFileHandler::LoadFile(wxRichTextBuffer *buffer, const wxString& filename)
 {
     wxFFileInputStream stream(filename);
-    if (stream.Ok())
+    if (stream.IsOk())
         return LoadFile(buffer, stream);
 
     return false;
@@ -10162,7 +10172,7 @@ bool wxRichTextFileHandler::LoadFile(wxRichTextBuffer *buffer, const wxString& f
 bool wxRichTextFileHandler::SaveFile(wxRichTextBuffer *buffer, const wxString& filename)
 {
     wxFFileOutputStream stream(filename);
-    if (stream.Ok())
+    if (stream.IsOk())
         return SaveFile(buffer, stream);
 
     return false;
@@ -10421,8 +10431,8 @@ bool wxRichTextImageBlock::WriteHex(wxOutputStream& stream)
         return true;
 
     int bufSize = 100000;
-    if (int(m_dataSize+1) < bufSize)
-        bufSize = m_dataSize+1;
+    if (int(2*m_dataSize) < bufSize)
+        bufSize = 2*m_dataSize;
     char* buf = new char[bufSize+1];
 
     int left = m_dataSize;
@@ -10496,7 +10506,7 @@ unsigned char* wxRichTextImageBlock::ReadBlock(wxInputStream& stream, size_t siz
 unsigned char* wxRichTextImageBlock::ReadBlock(const wxString& filename, size_t size)
 {
     wxFileInputStream stream(filename);
-    if (!stream.Ok())
+    if (!stream.IsOk())
         return NULL;
 
     return ReadBlock(stream, size);
@@ -10514,7 +10524,7 @@ bool wxRichTextImageBlock::WriteBlock(wxOutputStream& stream, unsigned char* blo
 bool wxRichTextImageBlock::WriteBlock(const wxString& filename, unsigned char* block, size_t size)
 {
     wxFileOutputStream outStream(filename);
-    if (!outStream.Ok())
+    if (!outStream.IsOk())
         return false;
 
     return WriteBlock(outStream, block, size);
@@ -10736,6 +10746,7 @@ void wxTextBoxAttr::Reset()
     m_clearMode = wxTEXT_BOX_ATTR_CLEAR_NONE;
     m_collapseMode = wxTEXT_BOX_ATTR_COLLAPSE_NONE;
     m_verticalAlignment = wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_NONE;
+    m_boxStyleName = wxEmptyString;
 
     m_margins.Reset();
     m_padding.Reset();
@@ -10764,7 +10775,9 @@ bool wxTextBoxAttr::operator== (const wxTextBoxAttr& attr) const
         m_size == attr.m_size &&
 
         m_border == attr.m_border &&
-        m_outline == attr.m_outline
+        m_outline == attr.m_outline &&
+
+        m_boxStyleName == attr.m_boxStyleName
         );
 }
 
@@ -10783,6 +10796,9 @@ bool wxTextBoxAttr::EqPartial(const wxTextBoxAttr& attr) const
     if (attr.HasVerticalAlignment() && HasVerticalAlignment() && (attr.GetVerticalAlignment() != GetVerticalAlignment()))
         return false;
 
+    if (attr.HasBoxStyleName() && HasBoxStyleName() && (attr.GetBoxStyleName() != GetBoxStyleName()))
+        return false;
+
     // Position
 
     if (!m_position.EqPartial(attr.m_position))
@@ -10840,6 +10856,12 @@ bool wxTextBoxAttr::Apply(const wxTextBoxAttr& attr, const wxTextBoxAttr* compar
             SetVerticalAlignment(attr.GetVerticalAlignment());
     }
 
+    if (attr.HasBoxStyleName())
+    {
+        if (!(compareWith && compareWith->HasBoxStyleName() && compareWith->GetBoxStyleName() == attr.GetBoxStyleName()))
+            SetBoxStyleName(attr.GetBoxStyleName());
+    }
+
     m_margins.Apply(attr.m_margins, compareWith ? (& attr.m_margins) : (const wxTextAttrDimensions*) NULL);
     m_padding.Apply(attr.m_padding, compareWith ? (& attr.m_padding) : (const wxTextAttrDimensions*) NULL);
     m_position.Apply(attr.m_position, compareWith ? (& attr.m_position) : (const wxTextAttrDimensions*) NULL);
@@ -10867,6 +10889,12 @@ bool wxTextBoxAttr::RemoveStyle(const wxTextBoxAttr& attr)
     if (attr.HasVerticalAlignment())
         RemoveFlag(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT);
 
+    if (attr.HasBoxStyleName())
+    {
+        SetBoxStyleName(wxEmptyString);
+        RemoveFlag(wxTEXT_BOX_ATTR_BOX_STYLE_NAME);
+    }
+
     m_margins.RemoveStyle(attr.m_margins);
     m_padding.RemoveStyle(attr.m_padding);
     m_position.RemoveStyle(attr.m_position);
@@ -10959,6 +10987,25 @@ void wxTextBoxAttr::CollectCommonAttributes(const wxTextBoxAttr& attr, wxTextBox
     else
         absentAttr.AddFlag(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT);
 
+    if (attr.HasBoxStyleName())
+    {
+        if (!clashingAttr.HasBoxStyleName() && !absentAttr.HasBoxStyleName())
+        {
+            if (HasBoxStyleName())
+            {
+                if (GetBoxStyleName() != attr.GetBoxStyleName())
+                {
+                    clashingAttr.AddFlag(wxTEXT_BOX_ATTR_BOX_STYLE_NAME);
+                    RemoveFlag(wxTEXT_BOX_ATTR_BOX_STYLE_NAME);
+                }
+            }
+            else
+                SetBoxStyleName(attr.GetBoxStyleName());
+        }
+    }
+    else
+        absentAttr.AddFlag(wxTEXT_BOX_ATTR_BOX_STYLE_NAME);
+
     m_margins.CollectCommonAttributes(attr.m_margins, clashingAttr.m_margins, absentAttr.m_margins);
     m_padding.CollectCommonAttributes(attr.m_padding, clashingAttr.m_padding, absentAttr.m_padding);
     m_position.CollectCommonAttributes(attr.m_position, clashingAttr.m_position, absentAttr.m_position);
@@ -10969,6 +11016,13 @@ void wxTextBoxAttr::CollectCommonAttributes(const wxTextBoxAttr& attr, wxTextBox
     m_outline.CollectCommonAttributes(attr.m_outline, clashingAttr.m_outline, absentAttr.m_outline);
 }
 
+bool wxTextBoxAttr::IsDefault() const
+{
+    return GetFlags() == 0 && !m_border.IsValid() && !m_outline.IsValid() &&
+        !m_size.GetWidth().IsValid() && !m_size.GetHeight().IsValid() &&
+        !m_position.IsValid() && !m_padding.IsValid() && !m_margins.IsValid();
+}
+
 // wxRichTextAttr
 
 void wxRichTextAttr::Copy(const wxRichTextAttr& attr)