+static bool wxHasStyle(long flags, long style)
+{
+ return (flags & style) != 0;
+}
+
+/// Combines 'style' with 'currentStyle' for the purpose of summarising the attributes of a range of
+/// content.
+bool wxRichTextParagraphLayoutBox::CollectStyle(wxTextAttrEx& currentStyle, const wxTextAttrEx& style, long& multipleStyleAttributes)
+{
+ if (style.HasFont())
+ {
+ if (style.HasSize() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_FONT_SIZE))
+ {
+ if (currentStyle.GetFont().Ok() && currentStyle.HasSize())
+ {
+ if (currentStyle.GetFont().GetPointSize() != style.GetFont().GetPointSize())
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_FONT_SIZE;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_FONT_SIZE);
+ }
+ }
+ else
+ {
+ if (!currentStyle.GetFont().Ok())
+ wxSetFontPreservingStyles(currentStyle, *wxNORMAL_FONT);
+ wxFont font(currentStyle.GetFont());
+ font.SetPointSize(style.GetFont().GetPointSize());
+
+ wxSetFontPreservingStyles(currentStyle, font);
+ currentStyle.SetFlags(currentStyle.GetFlags() | wxTEXT_ATTR_FONT_SIZE);
+ }
+ }
+
+ if (style.HasItalic() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_FONT_ITALIC))
+ {
+ if (currentStyle.GetFont().Ok() && currentStyle.HasItalic())
+ {
+ if (currentStyle.GetFont().GetStyle() != style.GetFont().GetStyle())
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_FONT_ITALIC;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_FONT_ITALIC);
+ }
+ }
+ else
+ {
+ if (!currentStyle.GetFont().Ok())
+ wxSetFontPreservingStyles(currentStyle, *wxNORMAL_FONT);
+ wxFont font(currentStyle.GetFont());
+ font.SetStyle(style.GetFont().GetStyle());
+ wxSetFontPreservingStyles(currentStyle, font);
+ currentStyle.SetFlags(currentStyle.GetFlags() | wxTEXT_ATTR_FONT_ITALIC);
+ }
+ }
+
+ if (style.HasWeight() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_FONT_WEIGHT))
+ {
+ if (currentStyle.GetFont().Ok() && currentStyle.HasWeight())
+ {
+ if (currentStyle.GetFont().GetWeight() != style.GetFont().GetWeight())
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_FONT_WEIGHT;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_FONT_WEIGHT);
+ }
+ }
+ else
+ {
+ if (!currentStyle.GetFont().Ok())
+ wxSetFontPreservingStyles(currentStyle, *wxNORMAL_FONT);
+ wxFont font(currentStyle.GetFont());
+ font.SetWeight(style.GetFont().GetWeight());
+ wxSetFontPreservingStyles(currentStyle, font);
+ currentStyle.SetFlags(currentStyle.GetFlags() | wxTEXT_ATTR_FONT_WEIGHT);
+ }
+ }
+
+ if (style.HasFaceName() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_FONT_FACE))
+ {
+ if (currentStyle.GetFont().Ok() && currentStyle.HasFaceName())
+ {
+ wxString faceName1(currentStyle.GetFont().GetFaceName());
+ wxString faceName2(style.GetFont().GetFaceName());
+
+ if (faceName1 != faceName2)
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_FONT_FACE;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_FONT_FACE);
+ }
+ }
+ else
+ {
+ if (!currentStyle.GetFont().Ok())
+ wxSetFontPreservingStyles(currentStyle, *wxNORMAL_FONT);
+ wxFont font(currentStyle.GetFont());
+ font.SetFaceName(style.GetFont().GetFaceName());
+ wxSetFontPreservingStyles(currentStyle, font);
+ currentStyle.SetFlags(currentStyle.GetFlags() | wxTEXT_ATTR_FONT_FACE);
+ }
+ }
+
+ if (style.HasUnderlined() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_FONT_UNDERLINE))
+ {
+ if (currentStyle.GetFont().Ok() && currentStyle.HasUnderlined())
+ {
+ if (currentStyle.GetFont().GetUnderlined() != style.GetFont().GetUnderlined())
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_FONT_UNDERLINE;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_FONT_UNDERLINE);
+ }
+ }
+ else
+ {
+ if (!currentStyle.GetFont().Ok())
+ wxSetFontPreservingStyles(currentStyle, *wxNORMAL_FONT);
+ wxFont font(currentStyle.GetFont());
+ font.SetUnderlined(style.GetFont().GetUnderlined());
+ wxSetFontPreservingStyles(currentStyle, font);
+ currentStyle.SetFlags(currentStyle.GetFlags() | wxTEXT_ATTR_FONT_UNDERLINE);
+ }
+ }
+ }
+
+ if (style.HasTextColour() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_TEXT_COLOUR))
+ {
+ if (currentStyle.HasTextColour())
+ {
+ if (currentStyle.GetTextColour() != style.GetTextColour())
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_TEXT_COLOUR;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_TEXT_COLOUR);
+ }
+ }
+ else
+ currentStyle.SetTextColour(style.GetTextColour());
+ }
+
+ if (style.HasBackgroundColour() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_BACKGROUND_COLOUR))
+ {
+ if (currentStyle.HasBackgroundColour())
+ {
+ if (currentStyle.GetBackgroundColour() != style.GetBackgroundColour())
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_BACKGROUND_COLOUR;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_BACKGROUND_COLOUR);
+ }
+ }
+ else
+ currentStyle.SetBackgroundColour(style.GetBackgroundColour());
+ }
+
+ if (style.HasAlignment() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_ALIGNMENT))
+ {
+ if (currentStyle.HasAlignment())
+ {
+ if (currentStyle.GetAlignment() != style.GetAlignment())
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_ALIGNMENT;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_ALIGNMENT);
+ }
+ }
+ else
+ currentStyle.SetAlignment(style.GetAlignment());
+ }
+
+ if (style.HasTabs() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_TABS))
+ {
+ if (currentStyle.HasTabs())
+ {
+ if (!wxRichTextTabsEq(currentStyle.GetTabs(), style.GetTabs()))
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_TABS;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_TABS);
+ }
+ }
+ else
+ currentStyle.SetTabs(style.GetTabs());
+ }
+
+ if (style.HasLeftIndent() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_LEFT_INDENT))
+ {
+ if (currentStyle.HasLeftIndent())
+ {
+ if (currentStyle.GetLeftIndent() != style.GetLeftIndent() || currentStyle.GetLeftSubIndent() != style.GetLeftSubIndent())
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_LEFT_INDENT;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_LEFT_INDENT);
+ }
+ }
+ else
+ currentStyle.SetLeftIndent(style.GetLeftIndent(), style.GetLeftSubIndent());
+ }
+
+ if (style.HasRightIndent() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_RIGHT_INDENT))
+ {
+ if (currentStyle.HasRightIndent())
+ {
+ if (currentStyle.GetRightIndent() != style.GetRightIndent())
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_RIGHT_INDENT;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_RIGHT_INDENT);
+ }
+ }
+ else
+ currentStyle.SetRightIndent(style.GetRightIndent());
+ }
+
+ if (style.HasParagraphSpacingAfter() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_PARA_SPACING_AFTER))
+ {
+ if (currentStyle.HasParagraphSpacingAfter())
+ {
+ if (currentStyle.HasParagraphSpacingAfter() != style.HasParagraphSpacingAfter())
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_PARA_SPACING_AFTER;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_PARA_SPACING_AFTER);
+ }
+ }
+ else
+ currentStyle.SetParagraphSpacingAfter(style.GetParagraphSpacingAfter());
+ }
+
+ if (style.HasParagraphSpacingBefore() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_PARA_SPACING_BEFORE))
+ {
+ if (currentStyle.HasParagraphSpacingBefore())
+ {
+ if (currentStyle.HasParagraphSpacingBefore() != style.HasParagraphSpacingBefore())
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_PARA_SPACING_BEFORE;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_PARA_SPACING_BEFORE);
+ }
+ }
+ else
+ currentStyle.SetParagraphSpacingBefore(style.GetParagraphSpacingBefore());
+ }
+
+ if (style.HasLineSpacing() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_LINE_SPACING))
+ {
+ if (currentStyle.HasLineSpacing())
+ {
+ if (currentStyle.HasLineSpacing() != style.HasLineSpacing())
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_LINE_SPACING;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_LINE_SPACING);
+ }
+ }
+ else
+ currentStyle.SetLineSpacing(style.GetLineSpacing());
+ }
+
+ if (style.HasCharacterStyleName() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_CHARACTER_STYLE_NAME))
+ {
+ if (currentStyle.HasCharacterStyleName())
+ {
+ if (currentStyle.HasCharacterStyleName() != style.HasCharacterStyleName())
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_CHARACTER_STYLE_NAME;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_CHARACTER_STYLE_NAME);
+ }
+ }
+ else
+ currentStyle.SetCharacterStyleName(style.GetCharacterStyleName());
+ }
+
+ if (style.HasParagraphStyleName() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_PARAGRAPH_STYLE_NAME))
+ {
+ if (currentStyle.HasParagraphStyleName())
+ {
+ if (currentStyle.HasParagraphStyleName() != style.HasParagraphStyleName())
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_PARAGRAPH_STYLE_NAME;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_PARAGRAPH_STYLE_NAME);
+ }
+ }
+ else
+ currentStyle.SetParagraphStyleName(style.GetParagraphStyleName());
+ }
+
+ if (style.HasBulletStyle() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_BULLET_STYLE))
+ {
+ if (currentStyle.HasBulletStyle())
+ {
+ if (currentStyle.HasBulletStyle() != style.HasBulletStyle())
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_BULLET_STYLE;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_BULLET_STYLE);
+ }
+ }
+ else
+ currentStyle.SetBulletStyle(style.GetBulletStyle());
+ }
+
+ if (style.HasBulletNumber() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_BULLET_NUMBER))
+ {
+ if (currentStyle.HasBulletNumber())
+ {
+ if (currentStyle.HasBulletNumber() != style.HasBulletNumber())
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_BULLET_NUMBER;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_BULLET_NUMBER);
+ }
+ }
+ else
+ currentStyle.SetBulletNumber(style.GetBulletNumber());
+ }
+
+ if (style.HasBulletSymbol() && !wxHasStyle(multipleStyleAttributes, wxTEXT_ATTR_BULLET_SYMBOL))
+ {
+ if (currentStyle.HasBulletSymbol())
+ {
+ if (currentStyle.HasBulletSymbol() != style.HasBulletSymbol())
+ {
+ // Clash of style - mark as such
+ multipleStyleAttributes |= wxTEXT_ATTR_BULLET_SYMBOL;
+ currentStyle.SetFlags(currentStyle.GetFlags() & ~wxTEXT_ATTR_BULLET_SYMBOL);
+ }
+ }
+ else
+ {
+ currentStyle.SetBulletSymbol(style.GetBulletSymbol());
+ currentStyle.SetBulletFont(style.GetBulletFont());
+ }
+ }
+
+ return true;
+}
+
+/// Get the combined style for a range - if any attribute is different within the range,
+/// that attribute is not present within the flags.
+/// *** Note that this is not recursive, and so assumes that content inside a paragraph is not itself
+/// nested.
+bool wxRichTextParagraphLayoutBox::GetStyleForRange(const wxRichTextRange& range, wxTextAttrEx& style)
+{
+ style = wxTextAttrEx();
+
+ // The attributes that aren't valid because of multiple styles within the range
+ long multipleStyleAttributes = 0;
+
+ wxRichTextObjectList::compatibility_iterator node = GetChildren().GetFirst();
+ while (node)
+ {
+ wxRichTextParagraph* para = (wxRichTextParagraph*) node->GetData();
+ if (!(para->GetRange().GetStart() > range.GetEnd() || para->GetRange().GetEnd() < range.GetStart()))
+ {
+ if (para->GetChildren().GetCount() == 0)
+ {
+ wxTextAttrEx paraStyle = para->GetCombinedAttributes();
+
+ CollectStyle(style, paraStyle, multipleStyleAttributes);
+ }
+ else
+ {
+ wxRichTextRange paraRange(para->GetRange());
+ paraRange.LimitTo(range);
+
+ // First collect paragraph attributes only
+ wxTextAttrEx paraStyle = para->GetCombinedAttributes();
+ paraStyle.SetFlags(paraStyle.GetFlags() & wxTEXT_ATTR_PARAGRAPH);
+ CollectStyle(style, paraStyle, multipleStyleAttributes);
+
+ wxRichTextObjectList::compatibility_iterator childNode = para->GetChildren().GetFirst();
+
+ while (childNode)
+ {
+ wxRichTextObject* child = childNode->GetData();
+ if (!(child->GetRange().GetStart() > range.GetEnd() || child->GetRange().GetEnd() < range.GetStart()))
+ {
+ wxTextAttrEx childStyle = para->GetCombinedAttributes(child->GetAttributes());
+
+ // Now collect character attributes only
+ childStyle.SetFlags(childStyle.GetFlags() & wxTEXT_ATTR_CHARACTER);
+
+ CollectStyle(style, childStyle, multipleStyleAttributes);
+ }
+
+ childNode = childNode->GetNext();
+ }
+ }
+ }
+ node = node->GetNext();
+ }
+ return true;
+}
+