#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.
}
/// Get/set the size for the given range. Assume only has one child.
-bool wxRichTextBox::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags) const
+bool wxRichTextBox::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position) const
{
wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst();
if (node)
{
wxRichTextObject* child = node->GetData();
- return child->GetRangeSize(range, size, descent, dc, flags);
+ return child->GetRangeSize(range, size, descent, dc, flags, position);
}
else
return false;
/// 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
{
}
/// Get/set the size for the given range.
-bool wxRichTextParagraphLayoutBox::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags) const
+bool wxRichTextParagraphLayoutBox::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position) const
{
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();
wxSize childSize;
int childDescent = 0;
- child->GetRangeSize(rangeToFind, childSize, childDescent, dc, flags);
+ child->GetRangeSize(rangeToFind, childSize, childDescent, dc, flags, position);
descent = wxMax(childDescent, descent);
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;
}
/// Get the paragraph by number
wxRichTextParagraph* wxRichTextParagraphLayoutBox::GetParagraphAtLine(long paragraphNumber) const
{
- if ((size_t) paragraphNumber <= GetChildCount())
+ if ((size_t) paragraphNumber >= GetChildCount())
return NULL;
return (wxRichTextParagraph*) GetChild((size_t) paragraphNumber);
{
// We'll be using a copy of the paragraph to make style changes,
// not updating the buffer directly.
- wxRichTextParagraph* newPara = NULL;
+ wxRichTextParagraph* newPara wxDUMMY_INITIALIZE(NULL);
if (haveControl && withUndo)
{
// we can start applying a different style.
// TODO: check that the style actually changes or is different
// from style outside of range
- wxRichTextObject* firstObject = NULL;
- wxRichTextObject* lastObject = NULL;
+ wxRichTextObject* firstObject wxDUMMY_INITIALIZE(NULL);
+ wxRichTextObject* lastObject wxDUMMY_INITIALIZE(NULL);
if (childRange.GetStart() == newPara->GetRange().GetStart())
firstObject = newPara->GetChildren().GetFirst()->GetData();
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;
/// Get the text attributes for this position.
bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxTextAttrEx& style) const
{
- wxRichTextObject* obj = NULL;
+ wxRichTextObject* obj wxDUMMY_INITIALIZE(NULL);
+
if (style.IsParagraphStyle())
obj = GetParagraphAtPosition(position);
else
obj = GetLeafObjectAtPosition(position);
+
if (obj)
{
style = obj->GetAttributes();
/// Get the text attributes for this position.
bool wxRichTextParagraphLayoutBox::GetStyle(long position, wxRichTextAttr& style) const
{
- wxRichTextObject* obj = NULL;
+ wxRichTextObject* obj wxDUMMY_INITIALIZE(NULL);
+
if (style.IsParagraphStyle())
obj = GetParagraphAtPosition(position);
else
obj = GetLeafObjectAtPosition(position);
+
if (obj)
{
style = obj->GetAttributes();
/// Set default style
bool wxRichTextParagraphLayoutBox::SetDefaultStyle(const wxTextAttrEx& style)
{
- m_defaultAttributes = style;
+ // keep the old attributes if the new style doesn't specify them unless the
+ // new style is empty - then reset m_defaultStyle (as there is no other way
+ // to do it)
+ if ( style.IsDefault() )
+ m_defaultAttributes = style;
+ else
+ m_defaultAttributes = wxTextAttrEx::CombineEx(style, m_defaultAttributes, NULL);
return true;
}
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());
wxRichTextLine* line = m_cachedLines.GetFirst() ? (wxRichTextLine* ) m_cachedLines.GetFirst()->GetData() : (wxRichTextLine*) NULL;
wxPoint linePos;
- int lineHeight = 0;
+ int lineHeight wxDUMMY_INITIALIZE(0);
if (line)
{
lineHeight = line->GetSize().y;
wxSize objectSize;
int descent = 0;
- child->GetRangeSize(objectRange, objectSize, descent, dc, wxRICHTEXT_UNFORMATTED);
+ child->GetRangeSize(objectRange, objectSize, descent, dc, wxRICHTEXT_UNFORMATTED, objectPosition);
// Use the child object's width, but the whole line's height
wxRect childRect(objectPosition, wxSize(objectSize.x, line->GetSize().y));
/// Lay the item out
bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style)
{
+ // ClearLines();
+
// Increase the size of the paragraph due to spacing
int spaceBeforePara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingBefore());
int spaceAfterPara = ConvertTenthsMMToPixels(dc, GetAttributes().GetParagraphSpacingAfter());
childDescent = child->GetDescent();
}
else
- GetRangeSize(wxRichTextRange(lastEndPos+1, child->GetRange().GetEnd()), childSize, childDescent, dc, wxRICHTEXT_UNFORMATTED);
+ GetRangeSize(wxRichTextRange(lastEndPos+1, child->GetRange().GetEnd()), childSize, childDescent, dc, wxRICHTEXT_UNFORMATTED,rect.GetPosition());
if (childSize.x + currentWidth > availableSpaceForText)
{
// 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)
/// Get/set the object size for the given range. Returns false if the range
/// is invalid for this object.
-bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags) const
+bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int flags, wxPoint position) const
{
if (!range.IsWithin(GetRange()))
return false;
rangeToUse.LimitTo(child->GetRange());
int childDescent = 0;
- if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, flags))
+ if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, flags, position))
{
sz.y = wxMax(sz.y, childSize.y);
sz.x += childSize.x;
wxSize childSize;
int childDescent = 0;
- if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, flags))
+ if (child->GetRangeSize(rangeToUse, childSize, childDescent, dc, flags, position))
{
lineSize.y = wxMax(lineSize.y, childSize.y);
lineSize.x += childSize.x;
// then we can add this size to the line start position and
// paragraph start position to find the actual position.
- if (GetRangeSize(r, rangeSize, descent, dc, wxRICHTEXT_UNFORMATTED))
+ if (GetRangeSize(r, rangeSize, descent, dc, wxRICHTEXT_UNFORMATTED, line->GetPosition()+ GetPosition()))
{
pt.x = line->GetPosition().x + GetPosition().x + rangeSize.x;
*height = line->GetSize().y;
wxRichTextRange rangeToUse(lineRange.GetStart(), i);
- GetRangeSize(rangeToUse, childSize, descent, dc, wxRICHTEXT_UNFORMATTED);
+ GetRangeSize(rangeToUse, childSize, descent, dc, wxRICHTEXT_UNFORMATTED, linePos);
int nextX = childSize.x + linePos.x;
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());
}
// (a) All selected.
if (selectionRange.GetStart() <= range.GetStart() && selectionRange.GetEnd() >= range.GetEnd())
- {
+ {/*
// Draw all selected
dc.SetBrush(*wxBLACK_BRUSH);
dc.SetPen(*wxBLACK_PEN);
dc.DrawRectangle(selRect);
dc.SetTextForeground(*wxWHITE);
dc.SetBackgroundMode(wxTRANSPARENT);
- dc.DrawText(stringChunk, x, y);
+ dc.DrawText(stringChunk, x, y);*/
+ DrawTabbedString(dc, rect,stringChunk, x, y, true);
}
// (b) None selected.
else if (selectionRange.GetEnd() < range.GetStart() || selectionRange.GetStart() > range.GetEnd())
{
// Draw all unselected
+ /*
dc.SetTextForeground(GetAttributes().GetTextColour());
dc.SetBackgroundMode(wxTRANSPARENT);
- dc.DrawText(stringChunk, x, y);
+ dc.DrawText(stringChunk, x, y);*/
+ DrawTabbedString(dc, rect,stringChunk, x, y, false);
}
else
{
if (fragmentLen < 0)
wxLogDebug(wxT("Mid(%d, %d"), (int)(r1 - offset), (int)fragmentLen);
wxString stringFragment = m_text.Mid(r1 - offset, fragmentLen);
-
+/*
dc.SetTextForeground(GetAttributes().GetTextColour());
dc.DrawText(stringFragment, x, y);
wxCoord w, h;
dc.GetTextExtent(stringFragment, & w, & h);
- x += w;
+ x += w;*/
+ DrawTabbedString(dc, rect,stringFragment, x, y, false);
}
// 2. Selected chunk, if any.
if (fragmentLen < 0)
wxLogDebug(wxT("Mid(%d, %d"), (int)(s1 - offset), (int)fragmentLen);
wxString stringFragment = m_text.Mid(s1 - offset, fragmentLen);
-
+/*
wxCoord w, h;
dc.GetTextExtent(stringFragment, & w, & h);
wxRect selRect(x, rect.y, w, rect.GetHeight());
dc.SetTextForeground(*wxWHITE);
dc.DrawText(stringFragment, x, y);
- x += w;
+ x += w;*/
+ DrawTabbedString(dc, rect,stringFragment, x, y, true);
}
// 3. Remaining unselected chunk, if any
if (fragmentLen < 0)
wxLogDebug(wxT("Mid(%d, %d"), (int)(s2 - offset), (int)fragmentLen);
wxString stringFragment = m_text.Mid(s2 - offset, fragmentLen);
-
+/*
dc.SetTextForeground(GetAttributes().GetTextColour());
- dc.DrawText(stringFragment, x, y);
+ dc.DrawText(stringFragment, x, y);*/
+ DrawTabbedString(dc, rect,stringFragment, x, y, false);
}
}
return true;
}
+
+bool wxRichTextPlainText::DrawTabbedString(wxDC& dc,const wxRect& rect,wxString& str, wxCoord& x, wxCoord& y, bool selected)
+{
+ wxArrayInt tab_array = GetAttributes().GetTabs();
+ if(tab_array.IsEmpty()){// create a default tab list at 10 mm each.
+ for( int i = 0; i < 20; ++i){
+ tab_array.Add(i*100);
+ }
+ }
+ int map_mode = dc.GetMapMode();
+ dc.SetMapMode(wxMM_LOMETRIC );
+ int num_tabs = tab_array.GetCount();
+ for( int i = 0; i < num_tabs; ++i){
+ tab_array[i] = dc.LogicalToDeviceXRel(tab_array[i]);
+ }
+ dc.SetMapMode(map_mode );
+ int next_tab_pos = -1;
+ int tab_pos = -1;
+ wxCoord w, h;
+ if(selected){
+ dc.SetBrush(*wxBLACK_BRUSH);
+ dc.SetPen(*wxBLACK_PEN);
+ dc.SetTextForeground(*wxWHITE);
+ dc.SetBackgroundMode(wxTRANSPARENT);
+ }
+ else{
+ dc.SetTextForeground(GetAttributes().GetTextColour());
+ dc.SetBackgroundMode(wxTRANSPARENT);
+ }
+ while(str.Find(wxT('\t')) >= 0){// the string has a tab
+ // break up the string at the Tab
+ wxString stringChunk = str.BeforeFirst(wxT('\t'));
+ str = str.AfterFirst(wxT('\t'));
+ dc.GetTextExtent(stringChunk, & w, & h);
+ tab_pos = x + w;
+ bool not_found = true;
+ for( int i = 0; i < num_tabs && not_found; ++i){
+ next_tab_pos = tab_array.Item(i);
+ if( next_tab_pos > tab_pos){
+ not_found = false;
+ if(selected){
+ w = next_tab_pos - x;
+ wxRect selRect(x, rect.y, w, rect.GetHeight());
+ dc.DrawRectangle(selRect);
+ }
+ dc.DrawText(stringChunk, x, y);
+ x = next_tab_pos;
+ }
+ }
+ }
+
+ dc.GetTextExtent(str, & w, & h);
+ if(selected){
+ wxRect selRect(x, rect.y, w, rect.GetHeight());
+ dc.DrawRectangle(selRect);
+ }
+ dc.DrawText(str, x, y);
+ x += w;
+ return true;
+}
/// Lay the item out
bool wxRichTextPlainText::Layout(wxDC& dc, const wxRect& WXUNUSED(rect), int WXUNUSED(style))
{
/// Get/set the object size for the given range. Returns false if the range
/// is invalid for this object.
-bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int WXUNUSED(flags)) const
+bool wxRichTextPlainText::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& descent, wxDC& dc, int WXUNUSED(flags), wxPoint position) const
{
if (!range.IsWithin(GetRange()))
return false;
long len = range.GetLength();
wxString stringChunk = m_text.Mid(startPos, (size_t) len);
wxCoord w, h;
+ int width = 0;
+ if(stringChunk.Find(wxT('\t')) >= 0){// the string has a tab
+ wxArrayInt tab_array = GetAttributes().GetTabs();
+ if(tab_array.IsEmpty()){// create a default tab list at 10 mm each.
+ for( int i = 0; i < 20; ++i){
+ tab_array.Add(i*100);
+ }
+ }
+ int map_mode = dc.GetMapMode();
+ dc.SetMapMode(wxMM_LOMETRIC );
+ int num_tabs = tab_array.GetCount();
+ for( int i = 0; i < num_tabs; ++i){
+ tab_array[i] = dc.LogicalToDeviceXRel(tab_array[i]);
+ }
+ dc.SetMapMode(map_mode );
+ int next_tab_pos = -1;
+
+ while(stringChunk.Find(wxT('\t')) >= 0){// the string has a tab
+ // break up the string at the Tab
+ wxString stringFragment = stringChunk.BeforeFirst(wxT('\t'));
+ stringChunk = stringChunk.AfterFirst(wxT('\t'));
+ dc.GetTextExtent(stringFragment, & w, & h);
+ width += w;
+ int absolute_width = width + position.x;
+ bool not_found = true;
+ for( int i = 0; i < num_tabs && not_found; ++i){
+ next_tab_pos = tab_array.Item(i);
+ if( next_tab_pos > absolute_width){
+ not_found = false;
+ width = next_tab_pos - position.x;
+ }
+ }
+ }
+ }
dc.GetTextExtent(stringChunk, & w, & h, & descent);
- size = wxSize(w, dc.GetCharHeight());
-
+ width += w;
+ size = wxSize(width, dc.GetCharHeight());
+
return true;
}
/// 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();
/// Get/set the object size for the given range. Returns false if the range
/// is invalid for this object.
-bool wxRichTextImage::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& WXUNUSED(descent), wxDC& WXUNUSED(dc), int WXUNUSED(flags)) const
+bool wxRichTextImage::GetRangeSize(const wxRichTextRange& range, wxSize& size, int& WXUNUSED(descent), wxDC& WXUNUSED(dc), int WXUNUSED(flags), wxPoint WXUNUSED(position)) const
{
if (!range.IsWithin(GetRange()))
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;
(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;
}
return true;
}
+wxRichTextAttr wxRichTextAttr::Combine(const wxRichTextAttr& attr,
+ const wxRichTextAttr& attrDef,
+ const wxTextCtrlBase *text)
+{
+ wxColour colFg = attr.GetTextColour();
+ if ( !colFg.Ok() )
+ {
+ colFg = attrDef.GetTextColour();
+
+ if ( text && !colFg.Ok() )
+ colFg = text->GetForegroundColour();
+ }
+
+ wxColour colBg = attr.GetBackgroundColour();
+ if ( !colBg.Ok() )
+ {
+ colBg = attrDef.GetBackgroundColour();
+
+ if ( text && !colBg.Ok() )
+ colBg = text->GetBackgroundColour();
+ }
+
+ wxRichTextAttr newAttr(colFg, colBg);
+
+ if (attr.HasWeight())
+ newAttr.SetFontWeight(attr.GetFontWeight());
+
+ if (attr.HasSize())
+ newAttr.SetFontSize(attr.GetFontSize());
+
+ if (attr.HasItalic())
+ newAttr.SetFontStyle(attr.GetFontStyle());
+
+ if (attr.HasUnderlined())
+ newAttr.SetFontUnderlined(attr.GetFontUnderlined());
+
+ if (attr.HasFaceName())
+ newAttr.SetFontFaceName(attr.GetFontFaceName());
+
+ if (attr.HasAlignment())
+ newAttr.SetAlignment(attr.GetAlignment());
+ else if (attrDef.HasAlignment())
+ newAttr.SetAlignment(attrDef.GetAlignment());
+
+ if (attr.HasTabs())
+ newAttr.SetTabs(attr.GetTabs());
+ else if (attrDef.HasTabs())
+ newAttr.SetTabs(attrDef.GetTabs());
+
+ if (attr.HasLeftIndent())
+ newAttr.SetLeftIndent(attr.GetLeftIndent(), attr.GetLeftSubIndent());
+ else if (attrDef.HasLeftIndent())
+ newAttr.SetLeftIndent(attrDef.GetLeftIndent(), attr.GetLeftSubIndent());
+
+ if (attr.HasRightIndent())
+ newAttr.SetRightIndent(attr.GetRightIndent());
+ else if (attrDef.HasRightIndent())
+ newAttr.SetRightIndent(attrDef.GetRightIndent());
+
+ // NEW ATTRIBUTES
+
+ if (attr.HasParagraphSpacingAfter())
+ newAttr.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter());
+
+ if (attr.HasParagraphSpacingBefore())
+ newAttr.SetParagraphSpacingBefore(attr.GetParagraphSpacingBefore());
+
+ if (attr.HasLineSpacing())
+ newAttr.SetLineSpacing(attr.GetLineSpacing());
+
+ if (attr.HasCharacterStyleName())
+ newAttr.SetCharacterStyleName(attr.GetCharacterStyleName());
+
+ if (attr.HasParagraphStyleName())
+ newAttr.SetParagraphStyleName(attr.GetParagraphStyleName());
+
+ if (attr.HasBulletStyle())
+ newAttr.SetBulletStyle(attr.GetBulletStyle());
+
+ if (attr.HasBulletNumber())
+ newAttr.SetBulletNumber(attr.GetBulletNumber());
+
+ if (attr.HasBulletSymbol())
+ newAttr.SetBulletSymbol(attr.GetBulletSymbol());
+
+ return newAttr;
+}
+
/*!
* wxTextAttrEx is an extended version of wxTextAttr with more paragraph attributes.
*/
wxTextAttr::operator= (attr);
}
+wxTextAttrEx wxTextAttrEx::CombineEx(const wxTextAttrEx& attr,
+ const wxTextAttrEx& attrDef,
+ const wxTextCtrlBase *text)
+{
+ wxTextAttrEx newAttr;
+
+ // If attr specifies the complete font, just use that font, overriding all
+ // default font attributes.
+ if ((attr.GetFlags() & wxTEXT_ATTR_FONT) == wxTEXT_ATTR_FONT)
+ newAttr.SetFont(attr.GetFont());
+ else
+ {
+ // First find the basic, default font
+ long flags = 0;
+
+ wxFont font;
+ if (attrDef.HasFont())
+ {
+ flags = (attrDef.GetFlags() & wxTEXT_ATTR_FONT);
+ font = attrDef.GetFont();
+ }
+ else
+ {
+ if (text)
+ font = text->GetFont();
+
+ // We leave flags at 0 because no font attributes have been specified yet
+ }
+ if (!font.Ok())
+ font = *wxNORMAL_FONT;
+
+ // Otherwise, if there are font attributes in attr, apply them
+ if (attr.HasFont())
+ {
+ if (attr.HasSize())
+ {
+ flags |= wxTEXT_ATTR_FONT_SIZE;
+ font.SetPointSize(attr.GetFont().GetPointSize());
+ }
+ if (attr.HasItalic())
+ {
+ flags |= wxTEXT_ATTR_FONT_ITALIC;;
+ font.SetStyle(attr.GetFont().GetStyle());
+ }
+ if (attr.HasWeight())
+ {
+ flags |= wxTEXT_ATTR_FONT_WEIGHT;
+ font.SetWeight(attr.GetFont().GetWeight());
+ }
+ if (attr.HasFaceName())
+ {
+ flags |= wxTEXT_ATTR_FONT_FACE;
+ font.SetFaceName(attr.GetFont().GetFaceName());
+ }
+ if (attr.HasUnderlined())
+ {
+ flags |= wxTEXT_ATTR_FONT_UNDERLINE;
+ font.SetUnderlined(attr.GetFont().GetUnderlined());
+ }
+ newAttr.SetFont(font);
+ newAttr.SetFlags(newAttr.GetFlags()|flags);
+ }
+ }
+
+ // TODO: should really check we are specifying these in the flags,
+ // before setting them, as per above; or we will set them willy-nilly.
+ // However, we should also check whether this is the intention
+ // as per wxTextAttr::Combine, i.e. always to have valid colours
+ // in the style.
+ wxColour colFg = attr.GetTextColour();
+ if ( !colFg.Ok() )
+ {
+ colFg = attrDef.GetTextColour();
+
+ if ( text && !colFg.Ok() )
+ colFg = text->GetForegroundColour();
+ }
+
+ wxColour colBg = attr.GetBackgroundColour();
+ if ( !colBg.Ok() )
+ {
+ colBg = attrDef.GetBackgroundColour();
+
+ if ( text && !colBg.Ok() )
+ colBg = text->GetBackgroundColour();
+ }
+
+ newAttr.SetTextColour(colFg);
+ newAttr.SetBackgroundColour(colBg);
+
+ if (attr.HasAlignment())
+ newAttr.SetAlignment(attr.GetAlignment());
+ else if (attrDef.HasAlignment())
+ newAttr.SetAlignment(attrDef.GetAlignment());
+
+ if (attr.HasTabs())
+ newAttr.SetTabs(attr.GetTabs());
+ else if (attrDef.HasTabs())
+ newAttr.SetTabs(attrDef.GetTabs());
+
+ if (attr.HasLeftIndent())
+ newAttr.SetLeftIndent(attr.GetLeftIndent(), attr.GetLeftSubIndent());
+ else if (attrDef.HasLeftIndent())
+ newAttr.SetLeftIndent(attrDef.GetLeftIndent(), attr.GetLeftSubIndent());
+
+ if (attr.HasRightIndent())
+ newAttr.SetRightIndent(attr.GetRightIndent());
+ else if (attrDef.HasRightIndent())
+ newAttr.SetRightIndent(attrDef.GetRightIndent());
+
+ // NEW ATTRIBUTES
+
+ if (attr.HasParagraphSpacingAfter())
+ newAttr.SetParagraphSpacingAfter(attr.GetParagraphSpacingAfter());
+
+ if (attr.HasParagraphSpacingBefore())
+ newAttr.SetParagraphSpacingBefore(attr.GetParagraphSpacingBefore());
+
+ if (attr.HasLineSpacing())
+ newAttr.SetLineSpacing(attr.GetLineSpacing());
+
+ if (attr.HasCharacterStyleName())
+ newAttr.SetCharacterStyleName(attr.GetCharacterStyleName());
+
+ if (attr.HasParagraphStyleName())
+ newAttr.SetParagraphStyleName(attr.GetParagraphStyleName());
+
+ if (attr.HasBulletStyle())
+ newAttr.SetBulletStyle(attr.GetBulletStyle());
+
+ if (attr.HasBulletNumber())
+ newAttr.SetBulletNumber(attr.GetBulletNumber());
+
+ if (attr.HasBulletSymbol())
+ newAttr.SetBulletSymbol(attr.GetBulletSymbol());
+
+ return newAttr;
+}
+
+
/*!
* wxRichTextFileHandler
* Base class for file handlers
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
return false;
wxString str;
- int ch = 0;
int lastCh = 0;
while (!stream.Eof())
{
- ch = stream.GetC();
+ int ch = stream.GetC();
- if (ch == 10 && lastCh != 13)
- str += wxT('\n');
+ if (!stream.Eof())
+ {
+ if (ch == 10 && lastCh != 13)
+ str += wxT('\n');
- if (ch > 0 && ch != 10)
- str += wxChar(ch);
+ if (ch > 0 && ch != 10)
+ str += wxChar(ch);
- lastCh = ch;
+ lastCh = ch;
+ }
}
buffer->Clear();
void wxRichTextImageBlock::Clear()
{
- if (m_data)
- delete m_data;
+ delete[] m_data;
m_data = NULL;
m_dataSize = 0;
m_imageType = -1;
#endif
// wxUSE_RICHTEXT
-