+/*
+ * wxRichTextFontTable
+ * Manages quick access to a pool of fonts for rendering rich text
+ */
+
+WX_DECLARE_STRING_HASH_MAP_WITH_DECL(wxFont, wxRichTextFontTableHashMap, class WXDLLIMPEXP_RICHTEXT);
+
+class wxRichTextFontTableData: public wxObjectRefData
+{
+public:
+ wxRichTextFontTableData() {}
+
+ wxFont FindFont(const wxRichTextAttr& fontSpec);
+
+ wxRichTextFontTableHashMap m_hashMap;
+};
+
+wxFont wxRichTextFontTableData::FindFont(const wxRichTextAttr& fontSpec)
+{
+ wxString facename(fontSpec.GetFontFaceName());
+ wxString spec(wxString::Format(wxT("%d-%d-%d-%d-%s-%d"), fontSpec.GetFontSize(), fontSpec.GetFontStyle(), fontSpec.GetFontWeight(), (int) fontSpec.GetFontUnderlined(), facename.c_str(), (int) fontSpec.GetFontEncoding()));
+ wxRichTextFontTableHashMap::iterator entry = m_hashMap.find(spec);
+
+ if ( entry == m_hashMap.end() )
+ {
+ wxFont font(fontSpec.GetFontSize(), wxDEFAULT, fontSpec.GetFontStyle(), fontSpec.GetFontWeight(), fontSpec.GetFontUnderlined(), facename.c_str());
+ m_hashMap[spec] = font;
+ return font;
+ }
+ else
+ {
+ return entry->second;
+ }
+}
+
+IMPLEMENT_DYNAMIC_CLASS(wxRichTextFontTable, wxObject)
+
+wxRichTextFontTable::wxRichTextFontTable()
+{
+ m_refData = new wxRichTextFontTableData;
+}
+
+wxRichTextFontTable::wxRichTextFontTable(const wxRichTextFontTable& table)
+ : wxObject()
+{
+ (*this) = table;
+}
+
+wxRichTextFontTable::~wxRichTextFontTable()
+{
+ UnRef();
+}
+
+bool wxRichTextFontTable::operator == (const wxRichTextFontTable& table) const
+{
+ return (m_refData == table.m_refData);
+}
+
+void wxRichTextFontTable::operator= (const wxRichTextFontTable& table)
+{
+ Ref(table);
+}
+
+wxFont wxRichTextFontTable::FindFont(const wxRichTextAttr& fontSpec)
+{
+ wxRichTextFontTableData* data = (wxRichTextFontTableData*) m_refData;
+ if (data)
+ return data->FindFont(fontSpec);
+ else
+ return wxFont();
+}
+
+void wxRichTextFontTable::Clear()
+{
+ wxRichTextFontTableData* data = (wxRichTextFontTableData*) m_refData;
+ if (data)
+ data->m_hashMap.clear();
+}
+
+// wxTextBoxAttr
+
+
+void wxTextBoxAttr::Reset()
+{
+ m_flags = 0;
+ m_floatMode = 0;
+ m_clearMode = 0;
+ m_collapseMode = 0;
+
+ m_margins.Reset();
+ m_padding.Reset();
+ m_position.Reset();
+
+ m_width.Reset();
+ m_height.Reset();
+
+ m_border.Reset();
+ m_outline.Reset();
+}
+
+// Equality test
+bool wxTextBoxAttr::operator== (const wxTextBoxAttr& attr) const
+{
+ return (
+ m_flags == attr.m_flags &&
+ m_floatMode == attr.m_floatMode &&
+ m_clearMode == attr.m_clearMode &&
+ m_collapseMode == attr.m_collapseMode &&
+
+ m_margins == attr.m_margins &&
+ m_padding == attr.m_padding &&
+ m_position == attr.m_position &&
+
+ m_width == attr.m_width &&
+ m_height == attr.m_height &&
+
+ m_border == attr.m_border &&
+ m_outline == attr.m_outline
+ );
+}
+
+// Partial equality test
+bool wxTextBoxAttr::EqPartial(const wxTextBoxAttr& attr) const
+{
+ if (attr.HasFloatMode() && HasFloatMode() && (GetFloatMode() != attr.GetFloatMode()))
+ return false;
+
+ if (attr.HasClearMode() && HasClearMode() && (GetClearMode() != attr.GetClearMode()))
+ return false;
+
+ if (attr.HasCollapseBorders() && HasCollapseBorders() && (attr.GetCollapseBorders() != GetCollapseBorders()))
+ return false;
+
+ // Position
+
+ if (!m_position.EqPartial(attr.m_position))
+ return false;
+
+ // Margins
+
+ if (!m_margins.EqPartial(attr.m_margins))
+ return false;
+
+ // Padding
+
+ if (!m_padding.EqPartial(attr.m_padding))
+ return false;
+
+ // Border
+
+ if (!GetBorder().EqPartial(attr.GetBorder()))
+ return false;
+
+ // Outline
+
+ if (!GetOutline().EqPartial(attr.GetOutline()))
+ return false;
+
+ return true;
+}
+
+// Merges the given attributes. If compareWith
+// is non-NULL, then it will be used to mask out those attributes that are the same in style
+// and compareWith, for situations where we don't want to explicitly set inherited attributes.
+bool wxTextBoxAttr::Apply(const wxTextBoxAttr& attr, const wxTextBoxAttr* compareWith)
+{
+ if (attr.HasFloatMode())
+ {
+ if (!(compareWith && compareWith->HasFloatMode() && compareWith->GetFloatMode() == attr.GetFloatMode()))
+ SetFloatMode(attr.GetFloatMode());
+ }
+
+ if (attr.HasClearMode())
+ {
+ if (!(compareWith && compareWith->HasClearMode() && compareWith->GetClearMode() == attr.GetClearMode()))
+ SetClearMode(attr.GetClearMode());
+ }
+
+ if (attr.HasCollapseBorders())
+ {
+ if (!(compareWith && compareWith->HasCollapseBorders() && compareWith->GetCollapseBorders() == attr.GetCollapseBorders()))
+ SetCollapseBorders(true);
+ }
+
+ 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);
+
+ m_width.Apply(attr.m_width, compareWith ? (& attr.m_width) : (const wxTextAttrDimension*) NULL);
+ m_height.Apply(attr.m_height, compareWith ? (& attr.m_height) : (const wxTextAttrDimension*) NULL);
+
+ m_border.Apply(attr.m_border, compareWith ? (& attr.m_border) : (const wxTextAttrBorders*) NULL);
+ m_outline.Apply(attr.m_outline, compareWith ? (& attr.m_outline) : (const wxTextAttrBorders*) NULL);
+
+ return true;
+}
+
+// Remove specified attributes from this object
+bool wxTextBoxAttr::RemoveStyle(const wxTextBoxAttr& attr)
+{
+ if (attr.HasFloatMode())
+ RemoveFlag(wxTEXT_BOX_ATTR_FLOAT);
+
+ if (attr.HasClearMode())
+ RemoveFlag(wxTEXT_BOX_ATTR_CLEAR);
+
+ if (attr.HasCollapseBorders())
+ RemoveFlag(wxTEXT_BOX_ATTR_COLLAPSE_BORDERS);
+
+ m_margins.RemoveStyle(attr.m_margins);
+ m_padding.RemoveStyle(attr.m_padding);
+ m_position.RemoveStyle(attr.m_position);
+
+ if (attr.m_width.IsPresent())
+ m_width.Reset();
+ if (attr.m_height.IsPresent())
+ m_height.Reset();
+
+ m_border.RemoveStyle(attr.m_border);
+ m_outline.RemoveStyle(attr.m_outline);
+
+ return true;
+}
+
+// Collects the attributes that are common to a range of content, building up a note of
+// which attributes are absent in some objects and which clash in some objects.
+void wxTextBoxAttr::CollectCommonAttributes(const wxTextBoxAttr& attr, wxTextBoxAttr& clashingAttr, wxTextBoxAttr& absentAttr)
+{
+ if (attr.HasFloatMode())
+ {
+ if (!clashingAttr.HasFloatMode() && !absentAttr.HasFloatMode())
+ {
+ if (HasFloatMode())
+ {
+ if (GetFloatMode() != attr.GetFloatMode())
+ {
+ clashingAttr.AddFlag(wxTEXT_BOX_ATTR_FLOAT);
+ RemoveFlag(wxTEXT_BOX_ATTR_FLOAT);
+ }
+ }
+ else
+ SetFloatMode(attr.GetFloatMode());
+ }
+ }
+ else
+ absentAttr.AddFlag(wxTEXT_BOX_ATTR_FLOAT);
+
+ if (attr.HasClearMode())
+ {
+ if (!clashingAttr.HasClearMode() && !absentAttr.HasClearMode())
+ {
+ if (HasClearMode())
+ {
+ if (GetClearMode() != attr.GetClearMode())
+ {
+ clashingAttr.AddFlag(wxTEXT_BOX_ATTR_CLEAR);
+ RemoveFlag(wxTEXT_BOX_ATTR_CLEAR);
+ }
+ }
+ else
+ SetClearMode(attr.GetClearMode());
+ }
+ }
+ else
+ absentAttr.AddFlag(wxTEXT_BOX_ATTR_CLEAR);
+
+ if (attr.HasCollapseBorders())
+ {
+ if (!clashingAttr.HasCollapseBorders() && !absentAttr.HasCollapseBorders())
+ {
+ if (HasCollapseBorders())
+ {
+ if (GetCollapseBorders() != attr.GetCollapseBorders())
+ {
+ clashingAttr.AddFlag(wxTEXT_BOX_ATTR_COLLAPSE_BORDERS);
+ RemoveFlag(wxTEXT_BOX_ATTR_COLLAPSE_BORDERS);
+ }
+ }
+ else
+ SetCollapseBorders(attr.GetCollapseBorders());
+ }
+ }
+ else
+ absentAttr.AddFlag(wxTEXT_BOX_ATTR_COLLAPSE_BORDERS);
+
+ 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);
+
+ m_width.CollectCommonAttributes(attr.m_width, clashingAttr.m_width, absentAttr.m_width);
+ m_height.CollectCommonAttributes(attr.m_height, clashingAttr.m_height, absentAttr.m_height);
+
+ m_border.CollectCommonAttributes(attr.m_border, clashingAttr.m_border, absentAttr.m_border);
+ m_outline.CollectCommonAttributes(attr.m_outline, clashingAttr.m_outline, absentAttr.m_outline);
+}
+
+// wxRichTextAttr
+
+void wxRichTextAttr::Copy(const wxRichTextAttr& attr)
+{
+ wxTextAttr::Copy(attr);
+
+ m_textBoxAttr = attr.m_textBoxAttr;
+}
+
+bool wxRichTextAttr::operator==(const wxRichTextAttr& attr) const
+{
+ if (!(wxTextAttr::operator==(attr)))
+ return false;
+
+ return (m_textBoxAttr == attr.m_textBoxAttr);
+}
+
+// Partial equality test taking comparison object into account
+bool wxRichTextAttr::EqPartial(const wxRichTextAttr& attr) const
+{
+ if (!(wxTextAttr::EqPartial(attr)))
+ return false;
+
+ return m_textBoxAttr.EqPartial(attr.m_textBoxAttr);
+}
+
+// Merges the given attributes. If compareWith
+// is non-NULL, then it will be used to mask out those attributes that are the same in style
+// and compareWith, for situations where we don't want to explicitly set inherited attributes.
+bool wxRichTextAttr::Apply(const wxRichTextAttr& style, const wxRichTextAttr* compareWith)
+{
+ wxTextAttr::Apply(style, compareWith);
+
+ return m_textBoxAttr.Apply(style.m_textBoxAttr, compareWith ? (& compareWith->m_textBoxAttr) : (const wxTextBoxAttr*) NULL);
+}
+
+// Remove specified attributes from this object
+bool wxRichTextAttr::RemoveStyle(const wxRichTextAttr& attr)
+{
+ wxTextAttr::RemoveStyle(*this, attr);
+
+ return m_textBoxAttr.RemoveStyle(attr.m_textBoxAttr);
+}
+
+// Collects the attributes that are common to a range of content, building up a note of
+// which attributes are absent in some objects and which clash in some objects.
+void wxRichTextAttr::CollectCommonAttributes(const wxRichTextAttr& attr, wxRichTextAttr& clashingAttr, wxRichTextAttr& absentAttr)
+{
+ wxTextAttrCollectCommonAttributes(*this, attr, clashingAttr, absentAttr);
+
+ m_textBoxAttr.CollectCommonAttributes(attr.m_textBoxAttr, clashingAttr.m_textBoxAttr, absentAttr.m_textBoxAttr);
+}
+
+// Partial equality test
+bool wxTextAttrBorder::EqPartial(const wxTextAttrBorder& border) const
+{
+ if (border.HasStyle() && !HasStyle() && (border.GetStyle() != GetStyle()))
+ return false;
+
+ if (border.HasColour() && !HasColour() && (border.GetColourLong() != GetColourLong()))
+ return false;
+
+ if (border.HasWidth() && !HasWidth() && !(border.GetWidth() == GetWidth()))
+ return false;
+
+ return true;
+}
+
+// Apply border to 'this', but not if the same as compareWith
+bool wxTextAttrBorder::Apply(const wxTextAttrBorder& border, const wxTextAttrBorder* compareWith)
+{
+ if (border.HasStyle())
+ {
+ if (!(compareWith && (border.GetStyle() == compareWith->GetStyle())))
+ SetStyle(border.GetStyle());
+ }
+ if (border.HasColour())
+ {
+ if (!(compareWith && (border.GetColourLong() == compareWith->GetColourLong())))
+ SetColour(border.GetColourLong());
+ }
+ if (border.HasWidth())
+ {
+ if (!(compareWith && (border.GetWidth() == compareWith->GetWidth())))
+ SetWidth(border.GetWidth());
+ }
+
+ return true;
+}
+
+// Remove specified attributes from this object
+bool wxTextAttrBorder::RemoveStyle(const wxTextAttrBorder& attr)
+{
+ if (attr.HasStyle() && HasStyle())
+ SetFlags(GetFlags() & ~wxTEXT_BOX_ATTR_BORDER_STYLE);
+ if (attr.HasColour() && HasColour())
+ SetFlags(GetFlags() & ~wxTEXT_BOX_ATTR_BORDER_COLOUR);
+ if (attr.HasWidth() && HasWidth())
+ m_borderWidth.Reset();
+
+ return true;
+}
+
+// Collects the attributes that are common to a range of content, building up a note of
+// which attributes are absent in some objects and which clash in some objects.
+void wxTextAttrBorder::CollectCommonAttributes(const wxTextAttrBorder& attr, wxTextAttrBorder& clashingAttr, wxTextAttrBorder& absentAttr)
+{
+ if (attr.HasStyle())
+ {
+ if (!clashingAttr.HasStyle() && !absentAttr.HasStyle())
+ {
+ if (HasStyle())
+ {
+ if (GetStyle() != attr.GetStyle())
+ {
+ clashingAttr.AddFlag(wxTEXT_BOX_ATTR_BORDER_STYLE);
+ RemoveFlag(wxTEXT_BOX_ATTR_BORDER_STYLE);
+ }
+ }
+ else
+ SetStyle(attr.GetStyle());
+ }
+ }
+ else
+ absentAttr.AddFlag(wxTEXT_BOX_ATTR_BORDER_STYLE);
+
+ if (attr.HasColour())
+ {
+ if (!clashingAttr.HasColour() && !absentAttr.HasColour())
+ {
+ if (HasColour())
+ {
+ if (GetColour() != attr.GetColour())
+ {
+ clashingAttr.AddFlag(wxTEXT_BOX_ATTR_BORDER_COLOUR);
+ RemoveFlag(wxTEXT_BOX_ATTR_BORDER_COLOUR);
+ }
+ }
+ else
+ SetColour(attr.GetColourLong());
+ }
+ }
+ else
+ absentAttr.AddFlag(wxTEXT_BOX_ATTR_BORDER_COLOUR);
+
+ m_borderWidth.CollectCommonAttributes(attr.m_borderWidth, clashingAttr.m_borderWidth, absentAttr.m_borderWidth);
+}
+
+// Partial equality test
+bool wxTextAttrBorders::EqPartial(const wxTextAttrBorders& borders) const
+{
+ return m_left.EqPartial(borders.m_left) && m_right.EqPartial(borders.m_right) &&
+ m_top.EqPartial(borders.m_top) && m_bottom.EqPartial(borders.m_bottom);
+}
+
+// Apply border to 'this', but not if the same as compareWith
+bool wxTextAttrBorders::Apply(const wxTextAttrBorders& borders, const wxTextAttrBorders* compareWith)
+{
+ m_left.Apply(borders.m_left, compareWith ? (& compareWith->m_left) : (const wxTextAttrBorder*) NULL);
+ m_right.Apply(borders.m_right, compareWith ? (& compareWith->m_right) : (const wxTextAttrBorder*) NULL);
+ m_top.Apply(borders.m_top, compareWith ? (& compareWith->m_top) : (const wxTextAttrBorder*) NULL);
+ m_bottom.Apply(borders.m_bottom, compareWith ? (& compareWith->m_bottom) : (const wxTextAttrBorder*) NULL);
+ return true;
+}
+
+// Remove specified attributes from this object
+bool wxTextAttrBorders::RemoveStyle(const wxTextAttrBorders& attr)
+{
+ m_left.RemoveStyle(attr.m_left);
+ m_right.RemoveStyle(attr.m_right);
+ m_top.RemoveStyle(attr.m_top);
+ m_bottom.RemoveStyle(attr.m_bottom);
+ return true;
+}
+
+// Collects the attributes that are common to a range of content, building up a note of
+// which attributes are absent in some objects and which clash in some objects.
+void wxTextAttrBorders::CollectCommonAttributes(const wxTextAttrBorders& attr, wxTextAttrBorders& clashingAttr, wxTextAttrBorders& absentAttr)
+{
+ m_left.CollectCommonAttributes(attr.m_left, clashingAttr.m_left, absentAttr.m_left);
+ m_right.CollectCommonAttributes(attr.m_right, clashingAttr.m_right, absentAttr.m_right);
+ m_top.CollectCommonAttributes(attr.m_top, clashingAttr.m_top, absentAttr.m_top);
+ m_bottom.CollectCommonAttributes(attr.m_bottom, clashingAttr.m_bottom, absentAttr.m_bottom);
+}
+
+// Set style of all borders
+void wxTextAttrBorders::SetStyle(int style)
+{
+ m_left.SetStyle(style);
+ m_right.SetStyle(style);
+ m_top.SetStyle(style);
+ m_bottom.SetStyle(style);
+}
+
+// Set colour of all borders
+void wxTextAttrBorders::SetColour(unsigned long colour)
+{
+ m_left.SetColour(colour);
+ m_right.SetColour(colour);
+ m_top.SetColour(colour);
+ m_bottom.SetColour(colour);
+}
+
+void wxTextAttrBorders::SetColour(const wxColour& colour)
+{
+ m_left.SetColour(colour);
+ m_right.SetColour(colour);
+ m_top.SetColour(colour);
+ m_bottom.SetColour(colour);
+}
+
+// Set width of all borders
+void wxTextAttrBorders::SetWidth(const wxTextAttrDimension& width)
+{
+ m_left.SetWidth(width);
+ m_right.SetWidth(width);
+ m_top.SetWidth(width);
+ m_bottom.SetWidth(width);
+}
+
+// Partial equality test
+bool wxTextAttrDimension::EqPartial(const wxTextAttrDimension& dim) const
+{
+ if (dim.IsPresent() && IsPresent() && !((*this) == dim))
+ return false;
+ else
+ return true;
+}
+
+bool wxTextAttrDimension::Apply(const wxTextAttrDimension& dim, const wxTextAttrDimension* compareWith)
+{
+ if (dim.IsPresent())
+ {
+ if (!(compareWith && dim == (*compareWith)))
+ (*this) = dim;
+ }
+
+ return true;
+}
+
+// Collects the attributes that are common to a range of content, building up a note of
+// which attributes are absent in some objects and which clash in some objects.
+void wxTextAttrDimension::CollectCommonAttributes(const wxTextAttrDimension& attr, wxTextAttrDimension& clashingAttr, wxTextAttrDimension& absentAttr)
+{
+ if (attr.IsPresent())
+ {
+ if (!clashingAttr.IsPresent() && !absentAttr.IsPresent())
+ {
+ if (IsPresent())
+ {
+ if (!((*this) == attr))
+ {
+ clashingAttr.SetPresent(true);
+ SetPresent(false);
+ }
+ }
+ else
+ (*this) = attr;
+ }
+ }
+ else
+ absentAttr.SetPresent(true);
+}
+
+wxTextAttrDimensionConverter::wxTextAttrDimensionConverter(wxDC& dc, double scale, const wxSize& parentSize)
+{
+ m_ppi = dc.GetPPI().x; m_scale = scale; m_parentSize = parentSize;
+}
+
+wxTextAttrDimensionConverter::wxTextAttrDimensionConverter(int ppi, double scale, const wxSize& parentSize)
+{
+ m_ppi = ppi; m_scale = scale; m_parentSize = parentSize;
+}
+
+int wxTextAttrDimensionConverter::ConvertTenthsMMToPixels(int units) const
+{
+ return wxRichTextObject::ConvertTenthsMMToPixels(m_ppi, units, m_scale);
+}
+
+int wxTextAttrDimensionConverter::ConvertPixelsToTenthsMM(int pixels) const
+{
+ return wxRichTextObject::ConvertPixelsToTenthsMM(m_ppi, pixels, m_scale);
+}
+
+int wxTextAttrDimensionConverter::GetPixels(const wxTextAttrDimension& dim, int direction) const
+{
+ if (dim.GetUnits() == wxTEXT_ATTR_UNITS_TENTHS_MM)
+ return ConvertTenthsMMToPixels(dim.GetValue());
+ else if (dim.GetUnits() == wxTEXT_ATTR_UNITS_PIXELS)
+ return dim.GetValue();
+ else if (dim.GetUnits() == wxTEXT_ATTR_UNITS_PERCENTAGE)
+ {
+ wxASSERT(m_parentSize != wxDefaultSize);
+ if (direction == wxHORIZONTAL)
+ return (int) (double(m_parentSize.x) * double(dim.GetValue()) / 100.0);
+ else
+ return (int) (double(m_parentSize.y) * double(dim.GetValue()) / 100.0);
+ }
+ else
+ {
+ wxASSERT(false);
+ return 0;
+ }
+}
+
+int wxTextAttrDimensionConverter::GetTenthsMM(const wxTextAttrDimension& dim) const
+{
+ if (dim.GetUnits() == wxTEXT_ATTR_UNITS_TENTHS_MM)
+ return dim.GetValue();
+ else if (dim.GetUnits() == wxTEXT_ATTR_UNITS_PIXELS)
+ return ConvertPixelsToTenthsMM(dim.GetValue());
+ else
+ {
+ wxASSERT(false);
+ return 0;
+ }
+}
+
+// Partial equality test
+bool wxTextAttrDimensions::EqPartial(const wxTextAttrDimensions& dims) const
+{
+ if (!m_left.EqPartial(dims.m_left))
+ return false;
+
+ if (!m_right.EqPartial(dims.m_right))
+ return false;
+
+ if (!m_top.EqPartial(dims.m_top))
+ return false;
+
+ if (!m_bottom.EqPartial(dims.m_bottom))
+ return false;
+
+ return true;
+}
+
+// Apply border to 'this', but not if the same as compareWith
+bool wxTextAttrDimensions::Apply(const wxTextAttrDimensions& dims, const wxTextAttrDimensions* compareWith)
+{
+ m_left.Apply(dims.m_left, compareWith ? (& compareWith->m_left) : (const wxTextAttrDimension*) NULL);
+ m_right.Apply(dims.m_right, compareWith ? (& compareWith->m_right): (const wxTextAttrDimension*) NULL);
+ m_top.Apply(dims.m_top, compareWith ? (& compareWith->m_top): (const wxTextAttrDimension*) NULL);
+ m_bottom.Apply(dims.m_bottom, compareWith ? (& compareWith->m_bottom): (const wxTextAttrDimension*) NULL);
+
+ return true;
+}
+
+// Remove specified attributes from this object
+bool wxTextAttrDimensions::RemoveStyle(const wxTextAttrDimensions& attr)
+{
+ if (attr.m_left.IsPresent())
+ m_left.Reset();
+ if (attr.m_right.IsPresent())
+ m_right.Reset();
+ if (attr.m_top.IsPresent())
+ m_top.Reset();
+ if (attr.m_bottom.IsPresent())
+ m_bottom.Reset();
+
+ return true;
+}
+
+// Collects the attributes that are common to a range of content, building up a note of
+// which attributes are absent in some objects and which clash in some objects.
+void wxTextAttrDimensions::CollectCommonAttributes(const wxTextAttrDimensions& attr, wxTextAttrDimensions& clashingAttr, wxTextAttrDimensions& absentAttr)
+{
+ m_left.CollectCommonAttributes(attr.m_left, clashingAttr.m_left, absentAttr.m_left);
+ m_right.CollectCommonAttributes(attr.m_right, clashingAttr.m_right, absentAttr.m_right);
+ m_top.CollectCommonAttributes(attr.m_top, clashingAttr.m_top, absentAttr.m_top);
+ m_bottom.CollectCommonAttributes(attr.m_bottom, clashingAttr.m_bottom, absentAttr.m_bottom);
+}
+
+// Collects the attributes that are common to a range of content, building up a note of
+// which attributes are absent in some objects and which clash in some objects.
+void wxTextAttrCollectCommonAttributes(wxTextAttr& currentStyle, const wxTextAttr& attr, wxTextAttr& clashingAttr, wxTextAttr& absentAttr)
+{
+ absentAttr.SetFlags(absentAttr.GetFlags() | (~attr.GetFlags() & wxTEXT_ATTR_ALL));
+ absentAttr.SetTextEffectFlags(absentAttr.GetTextEffectFlags() | (~attr.GetTextEffectFlags() & 0xFFFF));
+
+ long forbiddenFlags = clashingAttr.GetFlags()|absentAttr.GetFlags();
+
+ if (attr.HasFont())
+ {
+ if (attr.HasFontSize() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_FONT_SIZE))
+ {
+ if (currentStyle.HasFontSize())
+ {
+ if (currentStyle.GetFontSize() != attr.GetFontSize())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_FONT_SIZE);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_FONT_SIZE);
+ }
+ }
+ else
+ currentStyle.SetFontSize(attr.GetFontSize());
+ }
+
+ if (attr.HasFontItalic() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_FONT_ITALIC))
+ {
+ if (currentStyle.HasFontItalic())
+ {
+ if (currentStyle.GetFontStyle() != attr.GetFontStyle())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_FONT_ITALIC);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_FONT_ITALIC);
+ }
+ }
+ else
+ currentStyle.SetFontStyle(attr.GetFontStyle());
+ }
+
+ if (attr.HasFontFamily() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_FONT_FAMILY))
+ {
+ if (currentStyle.HasFontFamily())
+ {
+ if (currentStyle.GetFontFamily() != attr.GetFontFamily())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_FONT_FAMILY);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_FONT_FAMILY);
+ }
+ }
+ else
+ currentStyle.SetFontFamily(attr.GetFontFamily());
+ }
+
+ if (attr.HasFontWeight() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_FONT_WEIGHT))
+ {
+ if (currentStyle.HasFontWeight())
+ {
+ if (currentStyle.GetFontWeight() != attr.GetFontWeight())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_FONT_WEIGHT);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_FONT_WEIGHT);
+ }
+ }
+ else
+ currentStyle.SetFontWeight(attr.GetFontWeight());
+ }
+
+ if (attr.HasFontFaceName() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_FONT_FACE))
+ {
+ if (currentStyle.HasFontFaceName())
+ {
+ wxString faceName1(currentStyle.GetFontFaceName());
+ wxString faceName2(attr.GetFontFaceName());
+
+ if (faceName1 != faceName2)
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_FONT_FACE);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_FONT_FACE);
+ }
+ }
+ else
+ currentStyle.SetFontFaceName(attr.GetFontFaceName());
+ }
+
+ if (attr.HasFontUnderlined() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_FONT_UNDERLINE))
+ {
+ if (currentStyle.HasFontUnderlined())
+ {
+ if (currentStyle.GetFontUnderlined() != attr.GetFontUnderlined())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_FONT_UNDERLINE);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_FONT_UNDERLINE);
+ }
+ }
+ else
+ currentStyle.SetFontUnderlined(attr.GetFontUnderlined());
+ }
+ }
+
+ if (attr.HasTextColour() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_TEXT_COLOUR))
+ {
+ if (currentStyle.HasTextColour())
+ {
+ if (currentStyle.GetTextColour() != attr.GetTextColour())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_TEXT_COLOUR);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_TEXT_COLOUR);
+ }
+ }
+ else
+ currentStyle.SetTextColour(attr.GetTextColour());
+ }
+
+ if (attr.HasBackgroundColour() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_BACKGROUND_COLOUR))
+ {
+ if (currentStyle.HasBackgroundColour())
+ {
+ if (currentStyle.GetBackgroundColour() != attr.GetBackgroundColour())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_BACKGROUND_COLOUR);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_BACKGROUND_COLOUR);
+ }
+ }
+ else
+ currentStyle.SetBackgroundColour(attr.GetBackgroundColour());
+ }
+
+ if (attr.HasAlignment() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_ALIGNMENT))
+ {
+ if (currentStyle.HasAlignment())
+ {
+ if (currentStyle.GetAlignment() != attr.GetAlignment())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_ALIGNMENT);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_ALIGNMENT);
+ }
+ }
+ else
+ currentStyle.SetAlignment(attr.GetAlignment());
+ }
+
+ if (attr.HasTabs() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_TABS))
+ {
+ if (currentStyle.HasTabs())
+ {
+ if (!wxRichTextTabsEq(currentStyle.GetTabs(), attr.GetTabs()))
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_TABS);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_TABS);
+ }
+ }
+ else
+ currentStyle.SetTabs(attr.GetTabs());
+ }
+
+ if (attr.HasLeftIndent() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_LEFT_INDENT))
+ {
+ if (currentStyle.HasLeftIndent())
+ {
+ if (currentStyle.GetLeftIndent() != attr.GetLeftIndent() || currentStyle.GetLeftSubIndent() != attr.GetLeftSubIndent())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_LEFT_INDENT);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_LEFT_INDENT);
+ }
+ }
+ else
+ currentStyle.SetLeftIndent(attr.GetLeftIndent(), attr.GetLeftSubIndent());
+ }
+
+ if (attr.HasRightIndent() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_RIGHT_INDENT))
+ {
+ if (currentStyle.HasRightIndent())
+ {
+ if (currentStyle.GetRightIndent() != attr.GetRightIndent())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_RIGHT_INDENT);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_RIGHT_INDENT);
+ }
+ }
+ else
+ currentStyle.SetRightIndent(attr.GetRightIndent());
+ }
+
+ if (attr.HasParagraphSpacingAfter() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_PARA_SPACING_AFTER))
+ {
+ if (currentStyle.HasParagraphSpacingAfter())
+ {
+ if (currentStyle.GetParagraphSpacingAfter() != attr.GetParagraphSpacingAfter())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_PARA_SPACING_AFTER);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_PARA_SPACING_AFTER);
+ }
+ }
+ else
+ currentStyle.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter());
+ }
+
+ if (attr.HasParagraphSpacingBefore() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_PARA_SPACING_BEFORE))
+ {
+ if (currentStyle.HasParagraphSpacingBefore())
+ {
+ if (currentStyle.GetParagraphSpacingBefore() != attr.GetParagraphSpacingBefore())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_PARA_SPACING_BEFORE);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_PARA_SPACING_BEFORE);
+ }
+ }
+ else
+ currentStyle.SetParagraphSpacingBefore(attr.GetParagraphSpacingBefore());
+ }
+
+ if (attr.HasLineSpacing() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_LINE_SPACING))
+ {
+ if (currentStyle.HasLineSpacing())
+ {
+ if (currentStyle.GetLineSpacing() != attr.GetLineSpacing())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_LINE_SPACING);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_LINE_SPACING);
+ }
+ }
+ else
+ currentStyle.SetLineSpacing(attr.GetLineSpacing());
+ }
+
+ if (attr.HasCharacterStyleName() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_CHARACTER_STYLE_NAME))
+ {
+ if (currentStyle.HasCharacterStyleName())
+ {
+ if (currentStyle.GetCharacterStyleName() != attr.GetCharacterStyleName())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_CHARACTER_STYLE_NAME);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_CHARACTER_STYLE_NAME);
+ }
+ }
+ else
+ currentStyle.SetCharacterStyleName(attr.GetCharacterStyleName());
+ }
+
+ if (attr.HasParagraphStyleName() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_PARAGRAPH_STYLE_NAME))
+ {
+ if (currentStyle.HasParagraphStyleName())
+ {
+ if (currentStyle.GetParagraphStyleName() != attr.GetParagraphStyleName())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_PARAGRAPH_STYLE_NAME);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_PARAGRAPH_STYLE_NAME);
+ }
+ }
+ else
+ currentStyle.SetParagraphStyleName(attr.GetParagraphStyleName());
+ }
+
+ if (attr.HasListStyleName() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_LIST_STYLE_NAME))
+ {
+ if (currentStyle.HasListStyleName())
+ {
+ if (currentStyle.GetListStyleName() != attr.GetListStyleName())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_LIST_STYLE_NAME);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_LIST_STYLE_NAME);
+ }
+ }
+ else
+ currentStyle.SetListStyleName(attr.GetListStyleName());
+ }
+
+ if (attr.HasBulletStyle() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_BULLET_STYLE))
+ {
+ if (currentStyle.HasBulletStyle())
+ {
+ if (currentStyle.GetBulletStyle() != attr.GetBulletStyle())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_BULLET_STYLE);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_BULLET_STYLE);
+ }
+ }
+ else
+ currentStyle.SetBulletStyle(attr.GetBulletStyle());
+ }
+
+ if (attr.HasBulletNumber() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_BULLET_NUMBER))
+ {
+ if (currentStyle.HasBulletNumber())
+ {
+ if (currentStyle.GetBulletNumber() != attr.GetBulletNumber())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_BULLET_NUMBER);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_BULLET_NUMBER);
+ }
+ }
+ else
+ currentStyle.SetBulletNumber(attr.GetBulletNumber());
+ }
+
+ if (attr.HasBulletText() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_BULLET_TEXT))
+ {
+ if (currentStyle.HasBulletText())
+ {
+ if (currentStyle.GetBulletText() != attr.GetBulletText())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_BULLET_TEXT);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_BULLET_TEXT);
+ }
+ }
+ else
+ {
+ currentStyle.SetBulletText(attr.GetBulletText());
+ currentStyle.SetBulletFont(attr.GetBulletFont());
+ }
+ }
+
+ if (attr.HasBulletName() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_BULLET_NAME))
+ {
+ if (currentStyle.HasBulletName())
+ {
+ if (currentStyle.GetBulletName() != attr.GetBulletName())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_BULLET_NAME);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_BULLET_NAME);
+ }
+ }
+ else
+ {
+ currentStyle.SetBulletName(attr.GetBulletName());
+ }
+ }
+
+ if (attr.HasURL() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_URL))
+ {
+ if (currentStyle.HasURL())
+ {
+ if (currentStyle.GetURL() != attr.GetURL())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_URL);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_URL);
+ }
+ }
+ else
+ {
+ currentStyle.SetURL(attr.GetURL());
+ }
+ }
+
+ if (attr.HasTextEffects() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_EFFECTS))
+ {
+ if (currentStyle.HasTextEffects())
+ {
+ // We need to find the bits in the new attr that are different:
+ // just look at those bits that are specified by the new attr.
+
+ // We need to remove the bits and flags that are not common between current attr
+ // and new attr. In so doing we need to take account of the styles absent from one or more of the
+ // previous styles.
+
+ int currentRelevantTextEffects = currentStyle.GetTextEffects() & attr.GetTextEffectFlags();
+ int newRelevantTextEffects = attr.GetTextEffects() & attr.GetTextEffectFlags();
+
+ if (currentRelevantTextEffects != newRelevantTextEffects)
+ {
+ // Find the text effects that were different, using XOR
+ int differentEffects = currentRelevantTextEffects ^ newRelevantTextEffects;
+
+ // Clash of attr - mark as such
+ clashingAttr.SetTextEffectFlags(clashingAttr.GetTextEffectFlags() | differentEffects);
+ currentStyle.SetTextEffectFlags(currentStyle.GetTextEffectFlags() & ~differentEffects);
+ }
+ }
+ else
+ {
+ currentStyle.SetTextEffects(attr.GetTextEffects());
+ currentStyle.SetTextEffectFlags(attr.GetTextEffectFlags());
+ }
+
+ // Mask out the flags and values that cannot be common because they were absent in one or more objecrs
+ // that we've looked at so far
+ currentStyle.SetTextEffects(currentStyle.GetTextEffects() & ~absentAttr.GetTextEffectFlags());
+ currentStyle.SetTextEffectFlags(currentStyle.GetTextEffectFlags() & ~absentAttr.GetTextEffectFlags());
+
+ if (currentStyle.GetTextEffectFlags() == 0)
+ currentStyle.RemoveFlag(wxTEXT_ATTR_EFFECTS);
+ }
+
+ if (attr.HasOutlineLevel() && !wxHasStyle(forbiddenFlags, wxTEXT_ATTR_OUTLINE_LEVEL))
+ {
+ if (currentStyle.HasOutlineLevel())
+ {
+ if (currentStyle.GetOutlineLevel() != attr.GetOutlineLevel())
+ {
+ // Clash of attr - mark as such
+ clashingAttr.AddFlag(wxTEXT_ATTR_OUTLINE_LEVEL);
+ currentStyle.RemoveFlag(wxTEXT_ATTR_OUTLINE_LEVEL);
+ }
+ }
+ else
+ currentStyle.SetOutlineLevel(attr.GetOutlineLevel());
+ }
+}
+
+WX_DEFINE_OBJARRAY(wxRichTextVariantArray);
+
+IMPLEMENT_DYNAMIC_CLASS(wxRichTextProperties, wxObject)
+
+bool wxRichTextProperties::operator==(const wxRichTextProperties& props) const
+{
+ if (m_properties.GetCount() != props.GetCount())
+ return false;
+
+ size_t i;
+ for (i = 0; i < m_properties.GetCount(); i++)
+ {
+ const wxVariant& var1 = m_properties[i];
+ int idx = props.Find(var1.GetName());
+ if (idx == -1)
+ return false;
+ const wxVariant& var2 = props.m_properties[idx];
+ if (!(var1 == var2))
+ return false;
+ }
+
+ return true;
+}
+
+wxArrayString wxRichTextProperties::GetPropertyNames() const
+{
+ wxArrayString arr;
+ size_t i;
+ for (i = 0; i < m_properties.GetCount(); i++)
+ {
+ arr.Add(m_properties[i].GetName());
+ }
+ return arr;
+}
+
+int wxRichTextProperties::Find(const wxString& name) const
+{
+ size_t i;
+ for (i = 0; i < m_properties.GetCount(); i++)
+ {
+ if (m_properties[i].GetName() == name)
+ return (int) i;
+ }
+ return -1;
+}
+
+wxVariant* wxRichTextProperties::FindOrCreateProperty(const wxString& name)
+{
+ int idx = Find(name);
+ if (idx == wxNOT_FOUND)
+ SetProperty(name, wxString());
+ idx = Find(name);
+ if (idx != wxNOT_FOUND)
+ {
+ return & (*this)[idx];
+ }
+ else
+ return NULL;
+}
+
+const wxVariant& wxRichTextProperties::GetProperty(const wxString& name) const
+{
+ static const wxVariant nullVariant;
+ int idx = Find(name);
+ if (idx != -1)
+ return m_properties[idx];
+ else
+ return nullVariant;
+}
+
+wxString wxRichTextProperties::GetPropertyString(const wxString& name) const
+{
+ return GetProperty(name).GetString();
+}
+
+long wxRichTextProperties::GetPropertyLong(const wxString& name) const
+{
+ return GetProperty(name).GetLong();
+}
+
+bool wxRichTextProperties::GetPropertyBool(const wxString& name) const
+{
+ return GetProperty(name).GetBool();
+}
+
+double wxRichTextProperties::GetPropertyDouble(const wxString& name) const
+{
+ return GetProperty(name).GetDouble();
+}
+
+void wxRichTextProperties::SetProperty(const wxVariant& variant)
+{
+ wxASSERT(!variant.GetName().IsEmpty());
+
+ int idx = Find(variant.GetName());
+
+ if (idx == -1)
+ m_properties.Add(variant);
+ else
+ m_properties[idx] = variant;
+}
+
+void wxRichTextProperties::SetProperty(const wxString& name, const wxVariant& variant)
+{
+ int idx = Find(name);
+ wxVariant var(variant);
+ var.SetName(name);
+
+ if (idx == -1)
+ m_properties.Add(var);
+ else
+ m_properties[idx] = var;
+}
+
+void wxRichTextProperties::SetProperty(const wxString& name, const wxString& value)
+{
+ SetProperty(name, wxVariant(value, name));
+}
+
+void wxRichTextProperties::SetProperty(const wxString& name, long value)
+{
+ SetProperty(name, wxVariant(value, name));
+}
+
+void wxRichTextProperties::SetProperty(const wxString& name, double value)
+{
+ SetProperty(name, wxVariant(value, name));
+}
+
+void wxRichTextProperties::SetProperty(const wxString& name, bool value)
+{
+ SetProperty(name, wxVariant(value, name));
+}
+
+#endif
+ // wxUSE_RICHTEXT