#pragma hdrstop
#endif
+#if wxUSE_RICHTEXT
+
+#include "wx/richtext/richtextbuffer.h"
+
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
-#include "wx/image.h"
-
-#if wxUSE_RICHTEXT
-
#include "wx/filename.h"
#include "wx/clipbrd.h"
+#include "wx/dataobj.h"
#include "wx/wfstream.h"
#include "wx/module.h"
#include "wx/mstream.h"
#include "wx/sstream.h"
-#include "wx/richtext/richtextbuffer.h"
#include "wx/richtext/richtextctrl.h"
#include "wx/richtext/richtextstyles.h"
#include "wx/listimpl.cpp"
-WX_DEFINE_LIST(wxRichTextObjectList);
-WX_DEFINE_LIST(wxRichTextLineList);
+WX_DEFINE_LIST(wxRichTextObjectList)
+WX_DEFINE_LIST(wxRichTextLineList)
/*!
* wxRichTextObject
wxRichTextObjectList::compatibility_iterator node = m_children.Find(child);
if (node)
{
+ wxRichTextObject* obj = node->GetData();
+ m_children.Erase(node);
if (deleteChild)
- delete node->GetData();
- delete node;
+ delete obj;
return true;
}
child->Dereference(); // Only delete if reference count is zero
node = node->GetNext();
- delete oldNode;
+ m_children.Erase(oldNode);
}
return true;
if (child->CanMerge(nextChild) && child->Merge(nextChild))
{
nextChild->Dereference();
- delete node->GetNext();
+ m_children.Erase(node->GetNext());
// Don't set node -- we'll see if we can merge again with the next
// child.
/// Lay the item out
bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int style)
{
- wxRect availableSpace(rect.x + m_leftMargin,
+ wxRect availableSpace;
+ bool formatRect = (style & wxRICHTEXT_LAYOUT_SPECIFIED_RECT) == wxRICHTEXT_LAYOUT_SPECIFIED_RECT;
+
+ // If only laying out a specific area, the passed rect has a different meaning:
+ // the visible part of the buffer.
+ if (formatRect)
+ {
+ availableSpace = wxRect(0 + m_leftMargin,
+ 0 + m_topMargin,
+ rect.width - m_leftMargin - m_rightMargin,
+ rect.height);
+
+ // Invalidate the part of the buffer from the first visible line
+ // to the end. If other parts of the buffer are currently invalid,
+ // then they too will be taken into account if they are above
+ // the visible point.
+ long startPos = 0;
+ wxRichTextLine* line = GetLineAtYPosition(rect.y);
+ if (line)
+ startPos = line->GetAbsoluteRange().GetStart();
+
+ Invalidate(wxRichTextRange(startPos, GetRange().GetEnd()));
+ }
+ else
+ availableSpace = wxRect(rect.x + m_leftMargin,
rect.y + m_topMargin,
rect.width - m_leftMargin - m_rightMargin,
rect.height - m_topMargin - m_bottomMargin);
int maxWidth = 0;
wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
-
+
bool layoutAll = true;
// Get invalid range, rounding to paragraph start/end.
wxRichTextRange invalidRange = GetInvalidRange(true);
- if (invalidRange == wxRICHTEXT_NONE)
+ if (invalidRange == wxRICHTEXT_NONE && !formatRect)
return true;
if (invalidRange == wxRICHTEXT_ALL)
if (firstParagraph)
{
wxRichTextObjectList::compatibility_iterator firstNode = m_children.Find(firstParagraph);
- wxRichTextObjectList::compatibility_iterator previousNode = firstNode ? firstNode->GetPrevious() : (wxRichTextObjectList::compatibility_iterator) NULL;
+ wxRichTextObjectList::compatibility_iterator previousNode;
+ if ( firstNode )
+ previousNode = firstNode->GetPrevious();
if (firstNode && previousNode)
{
wxRichTextParagraph* previousParagraph = wxDynamicCast(previousNode->GetData(), wxRichTextParagraph);
}
}
+ // A way to force speedy rest-of-buffer layout (the 'else' below)
+ bool forceQuickLayout = false;
+
while (node)
{
// Assume this box only contains paragraphs
wxRichTextParagraph* child = wxDynamicCast(node->GetData(), wxRichTextParagraph);
- wxASSERT (child != NULL);
+ wxCHECK_MSG( child, false, _T("Unknown object in layout") );
// TODO: what if the child hasn't been laid out (e.g. involved in Undo) but still has 'old' lines
- if (child && (layoutAll || child->GetLines().GetCount() == 0 || !child->GetRange().IsOutside(invalidRange)))
+ if ( !forceQuickLayout &&
+ (layoutAll ||
+ child->GetLines().IsEmpty() ||
+ !child->GetRange().IsOutside(invalidRange)) )
{
child->Layout(dc, availableSpace, style);
// Layout must set the cached size
availableSpace.y += child->GetCachedSize().y;
maxWidth = wxMax(maxWidth, child->GetCachedSize().x);
+
+ // If we're just formatting the visible part of the buffer,
+ // and we're now past the bottom of the window, start quick
+ // layout.
+ if (formatRect && child->GetPosition().y > rect.GetBottom())
+ forceQuickLayout = true;
}
else
{
{
wxSize sz;
- wxRichTextObjectList::compatibility_iterator startPara = NULL;
- wxRichTextObjectList::compatibility_iterator endPara = NULL;
+ wxRichTextObjectList::compatibility_iterator startPara = wxRichTextObjectList::compatibility_iterator();
+ wxRichTextObjectList::compatibility_iterator endPara = wxRichTextObjectList::compatibility_iterator();
// First find the first paragraph whose starting position is within the range.
wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
return true;
}
-
- return false;
}
/// Make a copy of the fragment corresponding to the given range, putting it in 'fragment'.
}
wxRichTextObjectList::compatibility_iterator next1 = node1->GetNext();
- delete node1;
+ nextParagraph->GetChildren().Erase(node1);
node1 = next1;
}
wxRichTextObjectList::compatibility_iterator firstNode = newPara->GetChildren().Find(firstObject);
wxRichTextObjectList::compatibility_iterator lastNode = newPara->GetChildren().Find(lastObject);
- wxASSERT(firstNode != NULL);
- wxASSERT(lastNode != NULL);
+ wxASSERT(firstNode);
+ wxASSERT(lastNode);
wxRichTextObjectList::compatibility_iterator node2 = firstNode;
void wxRichTextParagraphLayoutBox::Invalidate(const wxRichTextRange& invalidRange)
{
SetDirty(true);
-
+
if (invalidRange == wxRICHTEXT_ALL)
{
m_invalidRange = wxRICHTEXT_ALL;
// Already invalidating everything
if (m_invalidRange == wxRICHTEXT_ALL)
return;
-
+
if ((invalidRange.GetStart() < m_invalidRange.GetStart()) || m_invalidRange.GetStart() == -1)
m_invalidRange.SetStart(invalidRange.GetStart());
if (invalidRange.GetEnd() > m_invalidRange.GetEnd())
{
if (m_invalidRange == wxRICHTEXT_ALL || m_invalidRange == wxRICHTEXT_NONE)
return m_invalidRange;
-
+
wxRichTextRange range = m_invalidRange;
-
+
if (wholeParagraphs)
{
wxRichTextParagraph* para1 = GetParagraphAtPosition(range.GetStart());
// Add a new line
wxRichTextLine* line = AllocateLine(lineCount);
-
+
// Set relative range so we won't have to change line ranges when paragraphs are moved
line->SetRange(wxRichTextRange(actualRange.GetStart() - GetRange().GetStart(), actualRange.GetEnd() - GetRange().GetStart()));
line->SetPosition(currentPosition);
bool wxRichTextParagraph::InsertText(long pos, const wxString& text)
{
wxRichTextObject* childToUse = NULL;
- wxRichTextObjectList::compatibility_iterator nodeToUse = NULL;
+ wxRichTextObjectList::compatibility_iterator nodeToUse = wxRichTextObjectList::compatibility_iterator();
wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
while (node)
if (pos == child->GetRange().GetStart())
{
if (previousObject)
- *previousObject = child;
+ {
+ if (node->GetPrevious())
+ *previousObject = node->GetPrevious()->GetData();
+ else
+ *previousObject = NULL;
+ }
return child;
}
/// Add content back from list
void wxRichTextParagraph::MoveFromList(wxList& list)
{
- for (wxNode* node = list.GetFirst(); node; node = node->GetNext())
+ for (wxList::compatibility_iterator node = list.GetFirst(); node; node = node->GetNext())
{
AppendChild((wxRichTextObject*) node->GetData());
}
/// End the style
bool wxRichTextBuffer::EndStyle()
{
- if (m_attributeStack.GetFirst() == NULL)
+ if (!m_attributeStack.GetFirst())
{
wxLogDebug(_("Too many EndStyle calls!"));
return false;
}
- wxNode* node = m_attributeStack.GetLast();
+ wxList::compatibility_iterator node = m_attributeStack.GetLast();
wxTextAttrEx* attr = (wxTextAttrEx*)node->GetData();
- delete node;
+ m_attributeStack.Erase(node);
SetDefaultStyle(*attr);
/// Clear the style stack
void wxRichTextBuffer::ClearStyleStack()
{
- for (wxNode* node = m_attributeStack.GetFirst(); node; node = node->GetNext())
+ for (wxList::compatibility_iterator node = m_attributeStack.GetFirst(); node; node = node->GetNext())
delete (wxTextAttrEx*) node->GetData();
m_attributeStack.Clear();
}
bool wxRichTextBuffer::CopyToClipboard(const wxRichTextRange& range)
{
bool success = false;
+#if wxUSE_CLIPBOARD && wxUSE_DATAOBJ
wxString text = GetTextForRange(range);
- if (wxTheClipboard->Open())
+ if (!wxTheClipboard->IsOpened() && wxTheClipboard->Open())
{
success = wxTheClipboard->SetData(new wxTextDataObject(text));
wxTheClipboard->Close();
}
+#else
+ wxUnusedVar(range);
+#endif
return success;
}
bool wxRichTextBuffer::PasteFromClipboard(long position)
{
bool success = false;
+#if wxUSE_CLIPBOARD && wxUSE_DATAOBJ
if (CanPasteFromClipboard())
{
if (wxTheClipboard->Open())
wxTextDataObject data;
wxTheClipboard->GetData(data);
wxString text(data.GetText());
+ text.Replace(_T("\r\n"), _T("\n"));
InsertTextWithUndo(position+1, text, GetRichTextCtrl());
wxTheClipboard->Close();
}
}
+#else
+ wxUnusedVar(position);
+#endif
return success;
}
bool wxRichTextBuffer::CanPasteFromClipboard() const
{
bool canPaste = false;
- if (wxTheClipboard->Open())
+#if wxUSE_CLIPBOARD && wxUSE_DATAOBJ
+ if (!wxTheClipboard->IsOpened() && wxTheClipboard->Open())
{
if (wxTheClipboard->IsSupported(wxDF_TEXT) || wxTheClipboard->IsSupported(wxDF_BITMAP))
{
}
wxTheClipboard->Close();
}
+#endif
return canPaste;
}
bool wxRichTextCommand::Do()
{
- for (wxNode* node = m_actions.GetFirst(); node; node = node->GetNext())
+ for (wxList::compatibility_iterator node = m_actions.GetFirst(); node; node = node->GetNext())
{
wxRichTextAction* action = (wxRichTextAction*) node->GetData();
action->Do();
bool wxRichTextCommand::Undo()
{
- for (wxNode* node = m_actions.GetLast(); node; node = node->GetPrevious())
+ for (wxList::compatibility_iterator node = m_actions.GetLast(); node; node = node->GetPrevious())
{
wxRichTextAction* action = (wxRichTextAction*) node->GetData();
action->Undo();
m_ctrl->SetCaretPosition(caretPosition);
if (!m_ctrl->IsFrozen())
{
- m_ctrl->Layout();
+ m_ctrl->LayoutContent();
m_ctrl->PositionCaret();
- m_ctrl->Refresh();
+ m_ctrl->Refresh(false);
if (sendUpdateEvent)
m_ctrl->SendUpdateEvent();
(attr1.GetRightIndent() != attr2.GetRightIndent()))
return false;
- if ((flags && wxTEXT_ATTR_PARA_SPACING_AFTER) &&
+ if ((flags & wxTEXT_ATTR_PARA_SPACING_AFTER) &&
(attr1.GetParagraphSpacingAfter() != attr2.GetParagraphSpacingAfter()))
return false;
- if ((flags && wxTEXT_ATTR_PARA_SPACING_BEFORE) &&
+ if ((flags & wxTEXT_ATTR_PARA_SPACING_BEFORE) &&
(attr1.GetParagraphSpacingBefore() != attr2.GetParagraphSpacingBefore()))
return false;
- if ((flags && wxTEXT_ATTR_LINE_SPACING) &&
+ if ((flags & wxTEXT_ATTR_LINE_SPACING) &&
(attr1.GetLineSpacing() != attr2.GetLineSpacing()))
return false;
- if ((flags && wxTEXT_ATTR_CHARACTER_STYLE_NAME) &&
+ if ((flags & wxTEXT_ATTR_CHARACTER_STYLE_NAME) &&
(attr1.GetCharacterStyleName() != attr2.GetCharacterStyleName()))
return false;
- if ((flags && wxTEXT_ATTR_PARAGRAPH_STYLE_NAME) &&
+ if ((flags & wxTEXT_ATTR_PARAGRAPH_STYLE_NAME) &&
(attr1.GetParagraphStyleName() != attr2.GetParagraphStyleName()))
return false;
(attr1.GetRightIndent() != attr2.GetRightIndent()))
return false;
- if ((flags && wxTEXT_ATTR_PARA_SPACING_AFTER) &&
+ if ((flags & wxTEXT_ATTR_PARA_SPACING_AFTER) &&
(attr1.GetParagraphSpacingAfter() != attr2.GetParagraphSpacingAfter()))
return false;
- if ((flags && wxTEXT_ATTR_PARA_SPACING_BEFORE) &&
+ if ((flags & wxTEXT_ATTR_PARA_SPACING_BEFORE) &&
(attr1.GetParagraphSpacingBefore() != attr2.GetParagraphSpacingBefore()))
return false;
- if ((flags && wxTEXT_ATTR_LINE_SPACING) &&
+ if ((flags & wxTEXT_ATTR_LINE_SPACING) &&
(attr1.GetLineSpacing() != attr2.GetLineSpacing()))
return false;
- if ((flags && wxTEXT_ATTR_CHARACTER_STYLE_NAME) &&
+ if ((flags & wxTEXT_ATTR_CHARACTER_STYLE_NAME) &&
(attr1.GetCharacterStyleName() != attr2.GetCharacterStyleName()))
return false;
- if ((flags && wxTEXT_ATTR_PARAGRAPH_STYLE_NAME) &&
+ if ((flags & wxTEXT_ATTR_PARAGRAPH_STYLE_NAME) &&
(attr1.GetParagraphStyleName() != attr2.GetParagraphStyleName()))
return false;
wxFont wxRichTextAttr::CreateFont() const
{
wxFont font(m_fontSize, wxDEFAULT, m_fontStyle, m_fontWeight, m_fontUnderlined, m_fontFaceName);
+#ifdef __WXMAC__
+ font.SetNoAntiAliasing(true);
+#endif
return font;
}
wxFFileInputStream stream(filename);
if (stream.Ok())
return LoadFile(buffer, stream);
- else
- return false;
+
+ return false;
}
bool wxRichTextFileHandler::SaveFile(wxRichTextBuffer *buffer, const wxString& filename)
wxFFileOutputStream stream(filename);
if (stream.Ok())
return SaveFile(buffer, stream);
- else
- return false;
+
+ return false;
}
#endif // wxUSE_STREAMS
{
if (ch == 10 && lastCh != 13)
str += wxT('\n');
-
+
if (ch > 0 && ch != 10)
str += wxChar(ch);
-
+
lastCh = ch;
}
}
void wxRichTextImageBlock::Clear()
{
- if (m_data)
- delete m_data;
+ delete[] m_data;
m_data = NULL;
m_dataSize = 0;
m_imageType = -1;
#endif
// wxUSE_RICHTEXT
-