+ n = left*2; left = 0;
+ }
+
+ char* b = buf;
+ for (i = 0; i < (n/2); i++)
+ {
+ wxDecToHex(m_data[j], b, b+1);
+ b += 2; j ++;
+ }
+
+ buf[n] = 0;
+ stream.Write((const char*) buf, n);
+ }
+ return true;
+}
+
+// Read data in hex from a stream
+bool wxRichTextImageBlock::ReadHex(wxInputStream& stream, int length, wxBitmapType imageType)
+{
+ int dataSize = length/2;
+
+ if (m_data)
+ delete[] m_data;
+
+ // create a null terminated temporary string:
+ char str[3];
+ str[2] = '\0';
+
+ m_data = new unsigned char[dataSize];
+ int i;
+ for (i = 0; i < dataSize; i ++)
+ {
+ str[0] = (char)stream.GetC();
+ str[1] = (char)stream.GetC();
+
+ m_data[i] = (unsigned char)wxHexToDec(str);
+ }
+
+ m_dataSize = dataSize;
+ m_imageType = imageType;
+
+ return true;
+}
+
+// Allocate and read from stream as a block of memory
+unsigned char* wxRichTextImageBlock::ReadBlock(wxInputStream& stream, size_t size)
+{
+ unsigned char* block = new unsigned char[size];
+ if (!block)
+ return NULL;
+
+ stream.Read(block, size);
+
+ return block;
+}
+
+unsigned char* wxRichTextImageBlock::ReadBlock(const wxString& filename, size_t size)
+{
+ wxFileInputStream stream(filename);
+ if (!stream.Ok())
+ return NULL;
+
+ return ReadBlock(stream, size);
+}
+
+// Write memory block to stream
+bool wxRichTextImageBlock::WriteBlock(wxOutputStream& stream, unsigned char* block, size_t size)
+{
+ stream.Write((void*) block, size);
+ return stream.IsOk();
+
+}
+
+// Write memory block to file
+bool wxRichTextImageBlock::WriteBlock(const wxString& filename, unsigned char* block, size_t size)
+{
+ wxFileOutputStream outStream(filename);
+ if (!outStream.Ok())
+ return false;
+
+ return WriteBlock(outStream, block, size);
+}
+
+// Gets the extension for the block's type
+wxString wxRichTextImageBlock::GetExtension() const
+{
+ wxImageHandler* handler = wxImage::FindHandler(GetImageType());
+ if (handler)
+ return handler->GetExtension();
+ else
+ return wxEmptyString;
+}
+
+#if wxUSE_DATAOBJ
+
+/*!
+ * The data object for a wxRichTextBuffer
+ */
+
+const wxChar *wxRichTextBufferDataObject::ms_richTextBufferFormatId = wxT("wxShape");
+
+wxRichTextBufferDataObject::wxRichTextBufferDataObject(wxRichTextBuffer* richTextBuffer)
+{
+ m_richTextBuffer = richTextBuffer;
+
+ // this string should uniquely identify our format, but is otherwise
+ // arbitrary
+ m_formatRichTextBuffer.SetId(GetRichTextBufferFormatId());
+
+ SetFormat(m_formatRichTextBuffer);
+}
+
+wxRichTextBufferDataObject::~wxRichTextBufferDataObject()
+{
+ delete m_richTextBuffer;
+}
+
+// after a call to this function, the richTextBuffer is owned by the caller and it
+// is responsible for deleting it!
+wxRichTextBuffer* wxRichTextBufferDataObject::GetRichTextBuffer()
+{
+ wxRichTextBuffer* richTextBuffer = m_richTextBuffer;
+ m_richTextBuffer = NULL;
+
+ return richTextBuffer;
+}
+
+wxDataFormat wxRichTextBufferDataObject::GetPreferredFormat(Direction WXUNUSED(dir)) const
+{
+ return m_formatRichTextBuffer;
+}
+
+size_t wxRichTextBufferDataObject::GetDataSize() const
+{
+ if (!m_richTextBuffer)
+ return 0;
+
+ wxString bufXML;
+
+ {
+ wxStringOutputStream stream(& bufXML);
+ if (!m_richTextBuffer->SaveFile(stream, wxRICHTEXT_TYPE_XML))
+ {
+ wxLogError(wxT("Could not write the buffer to an XML stream.\nYou may have forgotten to add the XML file handler."));
+ return 0;
+ }
+ }
+
+#if wxUSE_UNICODE
+ wxCharBuffer buffer = bufXML.mb_str(wxConvUTF8);
+ return strlen(buffer) + 1;
+#else
+ return bufXML.Length()+1;
+#endif
+}
+
+bool wxRichTextBufferDataObject::GetDataHere(void *pBuf) const
+{
+ if (!pBuf || !m_richTextBuffer)
+ return false;
+
+ wxString bufXML;
+
+ {
+ wxStringOutputStream stream(& bufXML);
+ if (!m_richTextBuffer->SaveFile(stream, wxRICHTEXT_TYPE_XML))
+ {
+ wxLogError(wxT("Could not write the buffer to an XML stream.\nYou may have forgotten to add the XML file handler."));
+ return 0;
+ }
+ }
+
+#if wxUSE_UNICODE
+ wxCharBuffer buffer = bufXML.mb_str(wxConvUTF8);
+ size_t len = strlen(buffer);
+ memcpy((char*) pBuf, (const char*) buffer, len);
+ ((char*) pBuf)[len] = 0;
+#else
+ size_t len = bufXML.Length();
+ memcpy((char*) pBuf, (const char*) bufXML.c_str(), len);
+ ((char*) pBuf)[len] = 0;
+#endif
+
+ return true;
+}
+
+bool wxRichTextBufferDataObject::SetData(size_t WXUNUSED(len), const void *buf)
+{
+ wxDELETE(m_richTextBuffer);
+
+ wxString bufXML((const char*) buf, wxConvUTF8);
+
+ m_richTextBuffer = new wxRichTextBuffer;
+
+ wxStringInputStream stream(bufXML);
+ if (!m_richTextBuffer->LoadFile(stream, wxRICHTEXT_TYPE_XML))
+ {
+ wxLogError(wxT("Could not read the buffer from an XML stream.\nYou may have forgotten to add the XML file handler."));
+
+ wxDELETE(m_richTextBuffer);
+
+ return false;
+ }
+ return true;
+}
+
+#endif
+ // wxUSE_DATAOBJ
+
+
+/*
+ * 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);
+ }