From 1e967276d8bce0ea59924f71ed00962ce19a742e Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Thu, 20 Oct 2005 12:55:53 +0000 Subject: [PATCH] Efficiency measures; file loading bug fix git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@35955 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/richtext/richtextbuffer.h | 25 +++- samples/richtext/richtext.cpp | 17 ++- src/richtext/richtextbuffer.cpp | 187 ++++++++++++++++++++------- src/richtext/richtextctrl.cpp | 86 ++++++------ src/richtext/richtextxml.cpp | 9 ++ 5 files changed, 230 insertions(+), 94 deletions(-) diff --git a/include/wx/richtext/richtextbuffer.h b/include/wx/richtext/richtextbuffer.h index 2e6f9f3752..97469190c8 100644 --- a/include/wx/richtext/richtextbuffer.h +++ b/include/wx/richtext/richtextbuffer.h @@ -244,6 +244,9 @@ protected: long m_end; }; +#define wxRICHTEXT_ALL wxRichTextRange(-2, -2) +#define wxRICHTEXT_NONE wxRichTextRange(-1, -1) + /*! * wxTextAttrEx is an extended version of wxTextAttr with more paragraph attributes. */ @@ -931,7 +934,7 @@ public: virtual const wxTextAttrEx& GetBasicStyle() const { return m_attributes; } /// Invalidate the buffer. With no argument, invalidates whole buffer. - void Invalidate(const wxRichTextRange& invalidRange = wxRichTextRange(-1, -1)); + void Invalidate(const wxRichTextRange& invalidRange = wxRICHTEXT_ALL); /// Get invalid range, rounding to entire paragraphs if argument is true. wxRichTextRange GetInvalidRange(bool wholeParagraphs = false) const; @@ -997,7 +1000,7 @@ public: // Constructors wxRichTextLine(wxRichTextParagraph* parent); - wxRichTextLine(const wxRichTextLine& obj) { Init(); Copy(obj); } + wxRichTextLine(const wxRichTextLine& obj) { Init( NULL); Copy(obj); } virtual ~wxRichTextLine() {} // Overrideables @@ -1015,6 +1018,9 @@ public: const wxRichTextRange& GetRange() const { return m_range; } wxRichTextRange& GetRange() { return m_range; } + /// Get the absolute range + wxRichTextRange GetAbsoluteRange() const; + /// Get/set the line size as calculated by Layout. virtual wxSize GetSize() const { return m_size; } virtual void SetSize(const wxSize& sz) { m_size = sz; } @@ -1036,7 +1042,7 @@ public: // Operations /// Initialisation - void Init(); + void Init(wxRichTextParagraph* parent); /// Copy void Copy(const wxRichTextLine& obj); @@ -1047,6 +1053,7 @@ public: protected: /// The range of the line (start position to end position) + /// This is relative to the parent paragraph. wxRichTextRange m_range; /// Size and position measured relative to top of paragraph @@ -1148,6 +1155,12 @@ public: /// Get the bullet text for this paragraph. wxString GetBulletText(); + /// Allocate or reuse a line object + wxRichTextLine* AllocateLine(int pos); + + /// Clear remaining unused line objects, if any + bool ClearUnusedLines(int lineCount); + protected: /// The lines that make up the wrapped paragraph wxRichTextLineList m_cachedLines; @@ -1616,8 +1629,10 @@ public: /// Finds a handler by type static wxRichTextFileHandler *FindHandler(int imageType); - /// Gets a wildcard incorporating all visible handlers - static wxString GetExtWildcard(bool combine = false, bool save = false); + /// Gets a wildcard incorporating all visible handlers. If 'types' is present, + /// will be filled with the file type corresponding to each filter. This can be + /// used to determine the type to pass to LoadFile given a selected filter. + static wxString GetExtWildcard(bool combine = false, bool save = false, wxArrayInt* types = NULL); /// Clean up handlers static void CleanUpHandlers(); diff --git a/samples/richtext/richtext.cpp b/samples/richtext/richtext.cpp index 43871e3b9f..c4c1cd66e9 100644 --- a/samples/richtext/richtext.cpp +++ b/samples/richtext/richtext.cpp @@ -698,14 +698,15 @@ bool MyFrame::ProcessEvent(wxEvent& event) void MyFrame::OnOpen(wxCommandEvent& WXUNUSED(event)) { - wxString filter = wxRichTextBuffer::GetExtWildcard(false, false); + wxString path = wxEmptyString; + wxString filename = wxEmptyString; + wxArrayInt fileTypes; + + wxString filter = wxRichTextBuffer::GetExtWildcard(false, false, & fileTypes); if (!filter.IsEmpty()) filter += wxT("|"); filter += wxT("All files (*.*)|*.*"); - wxString path = wxEmptyString; - wxString filename = wxEmptyString; - wxFileDialog dialog(this, _("Choose a filename"), path, @@ -719,7 +720,13 @@ void MyFrame::OnOpen(wxCommandEvent& WXUNUSED(event)) if (!path.IsEmpty()) { - m_richTextCtrl->LoadFile(path); + int fileType = 0; + int filterIndex = dialog.GetFilterIndex(); + if (filterIndex < (int) fileTypes.GetCount()) + fileType = fileTypes[filterIndex]; + else + fileType = wxRICHTEXT_TYPE_TEXT; + m_richTextCtrl->LoadFile(path, fileType); } } } diff --git a/src/richtext/richtextbuffer.cpp b/src/richtext/richtextbuffer.cpp index aa12d8a7b4..e5fa616f93 100644 --- a/src/richtext/richtextbuffer.cpp +++ b/src/richtext/richtextbuffer.cpp @@ -526,12 +526,15 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl wxRichTextObjectList::compatibility_iterator node = m_children.GetFirst(); bool layoutAll = true; - + // Get invalid range, rounding to paragraph start/end. wxRichTextRange invalidRange = GetInvalidRange(true); - if (invalidRange == wxRichTextRange(-1, -1)) - layoutAll = true; + if (invalidRange == wxRICHTEXT_NONE) + return true; + + if (invalidRange == wxRICHTEXT_ALL) + layoutAll = true; else // If we know what range is affected, start laying out from that point on. if (invalidRange.GetStart() > GetRange().GetStart()) { @@ -539,7 +542,7 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl if (firstParagraph) { wxRichTextObjectList::compatibility_iterator firstNode = m_children.Find(firstParagraph); - wxRichTextObjectList::compatibility_iterator previousNode = firstNode ? node->GetPrevious() : (wxRichTextObjectList::compatibility_iterator) NULL; + wxRichTextObjectList::compatibility_iterator previousNode = firstNode ? firstNode->GetPrevious() : (wxRichTextObjectList::compatibility_iterator) NULL; if (firstNode && previousNode) { wxRichTextParagraph* previousParagraph = wxDynamicCast(previousNode->GetData(), wxRichTextParagraph); @@ -547,6 +550,8 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl // Now we're going to start iterating from the first affected paragraph. node = firstNode; + + layoutAll = false; } } } @@ -558,7 +563,8 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl wxRichTextParagraph* child = wxDynamicCast(node->GetData(), wxRichTextParagraph); wxASSERT (child != NULL); - if (child && (layoutAll || !child->GetRange().IsOutside(invalidRange))) + // 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))) { child->Layout(dc, availableSpace, style); @@ -600,7 +606,7 @@ bool wxRichTextParagraphLayoutBox::Layout(wxDC& dc, const wxRect& rect, int styl SetCachedSize(wxSize(maxWidth, availableSpace.y)); m_dirty = false; - m_invalidRange = wxRichTextRange(-1, -1); + m_invalidRange = wxRICHTEXT_NONE; return true; } @@ -729,11 +735,13 @@ wxRichTextLine* wxRichTextParagraphLayoutBox::GetLineAtPosition(long pos, bool c { wxRichTextLine* line = node2->GetData(); - if (line->GetRange().Contains(pos) || + wxRichTextRange range = line->GetAbsoluteRange(); + + if (range.Contains(pos) || // If the position is end-of-paragraph, then return the last line of // of the paragraph. - (line->GetRange().GetEnd() == child->GetRange().GetEnd()-1) && (pos == child->GetRange().GetEnd())) + (range.GetEnd() == child->GetRange().GetEnd()-1) && (pos == child->GetRange().GetEnd())) return line; node2 = node2->GetNext(); @@ -803,7 +811,7 @@ int wxRichTextParagraphLayoutBox::GetLineCount() const /// Get the paragraph for a given line wxRichTextParagraph* wxRichTextParagraphLayoutBox::GetParagraphForLine(wxRichTextLine* line) const { - return GetParagraphAtPosition(line->GetRange().GetStart()); + return GetParagraphAtPosition(line->GetAbsoluteRange().GetStart()); } /// Get the line size at the given position @@ -1182,13 +1190,14 @@ long wxRichTextParagraphLayoutBox::GetVisibleLineNumber(long pos, bool caretPosi while (node2) { wxRichTextLine* line = node2->GetData(); + wxRichTextRange lineRange = line->GetAbsoluteRange(); - if (line->GetRange().Contains(pos)) + if (lineRange.Contains(pos)) { // If the caret is displayed at the end of the previous wrapped line, // we want to return the line it's _displayed_ at (not the actual line // containing the position). - if (line->GetRange().GetStart() == pos && !startOfLine && child->GetRange().GetStart() != pos) + if (lineRange.GetStart() == pos && !startOfLine && child->GetRange().GetStart() != pos) return lineCount - 1; else return lineCount; @@ -1735,13 +1744,17 @@ void wxRichTextParagraphLayoutBox::Invalidate(const wxRichTextRange& invalidRang { SetDirty(true); - if (invalidRange == wxRichTextRange(-1, -1)) + if (invalidRange == wxRICHTEXT_ALL) { - m_invalidRange = invalidRange; + m_invalidRange = wxRICHTEXT_ALL; return; } + + // Already invalidating everything + if (m_invalidRange == wxRICHTEXT_ALL) + return; - if (invalidRange.GetStart() < m_invalidRange.GetStart()) + if ((invalidRange.GetStart() < m_invalidRange.GetStart()) || m_invalidRange.GetStart() == -1) m_invalidRange.SetStart(invalidRange.GetStart()); if (invalidRange.GetEnd() > m_invalidRange.GetEnd()) m_invalidRange.SetEnd(invalidRange.GetEnd()); @@ -1750,7 +1763,7 @@ void wxRichTextParagraphLayoutBox::Invalidate(const wxRichTextRange& invalidRang /// Get invalid range, rounding to entire paragraphs if argument is true. wxRichTextRange wxRichTextParagraphLayoutBox::GetInvalidRange(bool wholeParagraphs) const { - if (m_invalidRange == wxRichTextRange(-1, -1)) + if (m_invalidRange == wxRICHTEXT_ALL || m_invalidRange == wxRICHTEXT_NONE) return m_invalidRange; wxRichTextRange range = m_invalidRange; @@ -1886,6 +1899,7 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range), while (node) { wxRichTextLine* line = node->GetData(); + wxRichTextRange lineRange = line->GetAbsoluteRange(); int maxDescent = line->GetDescent(); @@ -1899,11 +1913,11 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range), while (node2) { wxRichTextObject* child = node2->GetData(); - if (!child->GetRange().IsOutside(line->GetRange())) + if (!child->GetRange().IsOutside(lineRange)) { // Draw this part of the line at the correct position wxRichTextRange objectRange(child->GetRange()); - objectRange.LimitTo(line->GetRange()); + objectRange.LimitTo(lineRange); wxSize objectSize; int descent = 0; @@ -1915,7 +1929,7 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range), objectPosition.x += objectSize.x; } - else if (child->GetRange().GetStart() > line->GetRange().GetEnd()) + else if (child->GetRange().GetStart() > lineRange.GetEnd()) // Can break out of inner loop now since we've passed this line's range break; @@ -1931,8 +1945,6 @@ bool wxRichTextParagraph::Draw(wxDC& dc, const wxRichTextRange& WXUNUSED(range), /// 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()); @@ -2049,14 +2061,14 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) maxDescent = wxMax(childDescent, maxDescent); // Add a new line - wxRichTextLine* line = new wxRichTextLine(this); - line->SetRange(actualRange); + 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); line->SetSize(wxSize(currentWidth, lineHeight)); line->SetDescent(maxDescent); - m_cachedLines.Append(line); - // Now move down a line. TODO: add margins, spacing currentPosition.y += lineHeight; currentPosition.y += lineSpacing; @@ -2101,9 +2113,13 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) { currentPosition.x = (lineCount == 0 ? startPositionFirstLine : startPositionSubsequentLines); - wxRichTextLine* line = new wxRichTextLine(this); + wxRichTextLine* line = AllocateLine(lineCount); + + wxRichTextRange actualRange(lastCompletedEndPos+1, GetRange().GetEnd()-1); + + // 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->SetRange(lastCompletedEndPos+1, GetRange().GetEnd()-1); line->SetPosition(currentPosition); if (lineHeight == 0) @@ -2123,10 +2139,11 @@ bool wxRichTextParagraph::Layout(wxDC& dc, const wxRect& rect, int style) currentPosition.y += lineHeight; currentPosition.y += lineSpacing; lineCount ++; - - m_cachedLines.Append(line); } + // Remove remaining unused line objects, if any + ClearUnusedLines(lineCount); + // Apply styles to wrapped lines ApplyParagraphStyle(rect); @@ -2302,7 +2319,8 @@ bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& siz while (node) { wxRichTextLine* line = node->GetData(); - if (!line->GetRange().IsOutside(range)) + wxRichTextRange lineRange = line->GetAbsoluteRange(); + if (!lineRange.IsOutside(range)) { wxSize lineSize; @@ -2311,9 +2329,9 @@ bool wxRichTextParagraph::GetRangeSize(const wxRichTextRange& range, wxSize& siz { wxRichTextObject* child = node2->GetData(); - if (!child->GetRange().IsOutside(line->GetRange())) + if (!child->GetRange().IsOutside(lineRange)) { - wxRichTextRange rangeToUse = line->GetRange(); + wxRichTextRange rangeToUse = lineRange; rangeToUse.LimitTo(child->GetRange()); wxSize childSize; @@ -2392,12 +2410,13 @@ bool wxRichTextParagraph::FindPosition(wxDC& dc, long index, wxPoint& pt, int* h while (node) { wxRichTextLine* line = node->GetData(); - if (index >= line->GetRange().GetStart() && index <= line->GetRange().GetEnd()) + wxRichTextRange lineRange = line->GetAbsoluteRange(); + if (index >= lineRange.GetStart() && index <= lineRange.GetEnd()) { // If this is the last point in the line, and we're forcing the // returned value to be the start of the next line, do the required // thing. - if (index == line->GetRange().GetEnd() && forceLineStart) + if (index == lineRange.GetEnd() && forceLineStart) { if (node->GetNext()) { @@ -2410,7 +2429,7 @@ bool wxRichTextParagraph::FindPosition(wxDC& dc, long index, wxPoint& pt, int* h pt.y = line->GetPosition().y + GetPosition().y; - wxRichTextRange r(line->GetRange().GetStart(), index); + wxRichTextRange r(lineRange.GetStart(), index); wxSize rangeSize; int descent = 0; @@ -2446,29 +2465,30 @@ int wxRichTextParagraph::HitTest(wxDC& dc, const wxPoint& pt, long& textPosition wxRichTextLine* line = node->GetData(); wxPoint linePos = paraPos + line->GetPosition(); wxSize lineSize = line->GetSize(); + wxRichTextRange lineRange = line->GetAbsoluteRange(); if (pt.y >= linePos.y && pt.y <= linePos.y + lineSize.y) { if (pt.x < linePos.x) { - textPosition = line->GetRange().GetStart(); + textPosition = lineRange.GetStart(); return wxRICHTEXT_HITTEST_BEFORE; } else if (pt.x >= (linePos.x + lineSize.x)) { - textPosition = line->GetRange().GetEnd(); + textPosition = lineRange.GetEnd(); return wxRICHTEXT_HITTEST_AFTER; } else { long i; int lastX = linePos.x; - for (i = line->GetRange().GetStart(); i <= line->GetRange().GetEnd(); i++) + for (i = lineRange.GetStart(); i <= lineRange.GetEnd(); i++) { wxSize childSize; int descent = 0; - wxRichTextRange rangeToUse(line->GetRange().GetStart(), i); + wxRichTextRange rangeToUse(lineRange.GetStart(), i); GetRangeSize(rangeToUse, childSize, descent, dc, wxRICHTEXT_UNFORMATTED); @@ -2763,6 +2783,40 @@ wxString wxRichTextParagraph::GetBulletText() return text; } +/// Allocate or reuse a line object +wxRichTextLine* wxRichTextParagraph::AllocateLine(int pos) +{ + if (pos < (int) m_cachedLines.GetCount()) + { + wxRichTextLine* line = m_cachedLines.Item(pos)->GetData(); + line->Init(this); + return line; + } + else + { + wxRichTextLine* line = new wxRichTextLine(this); + m_cachedLines.Append(line); + return line; + } +} + +/// Clear remaining unused line objects, if any +bool wxRichTextParagraph::ClearUnusedLines(int lineCount) +{ + int cachedLineCount = m_cachedLines.GetCount(); + if ((int) cachedLineCount > lineCount) + { + for (int i = 0; i < (int) (cachedLineCount - lineCount); i ++) + { + wxRichTextLineList::compatibility_iterator node = m_cachedLines.GetLast(); + wxRichTextLine* line = node->GetData(); + m_cachedLines.Erase(node); + delete line; + } + } + return true; +} + /*! * wxRichTextLine @@ -2773,15 +2827,16 @@ wxString wxRichTextParagraph::GetBulletText() wxRichTextLine::wxRichTextLine(wxRichTextParagraph* parent) { - Init(); - - m_parent = parent; + Init(parent); } /// Initialisation -void wxRichTextLine::Init() +void wxRichTextLine::Init(wxRichTextParagraph* parent) { - m_parent = NULL; + m_parent = parent; + m_range.SetRange(-1, -1); + m_pos = wxPoint(0, 0); + m_size = wxSize(0, 0); m_descent = 0; } @@ -2797,6 +2852,14 @@ wxPoint wxRichTextLine::GetAbsolutePosition() const return m_parent->GetPosition() + m_pos; } +/// Get the absolute range +wxRichTextRange wxRichTextLine::GetAbsoluteRange() const +{ + wxRichTextRange range(m_range.GetStart() + m_parent->GetRange().GetStart(), 0); + range.SetEnd(range.GetStart() + m_range.GetLength()-1); + return range; +} + /*! * wxRichTextPlainText * This object represents a single piece of text. @@ -3095,6 +3158,7 @@ void wxRichTextBuffer::Clear() DeleteChildren(); GetCommandProcessor()->ClearCommands(); Modify(false); + Invalidate(wxRICHTEXT_ALL); } void wxRichTextBuffer::Reset() @@ -3103,6 +3167,7 @@ void wxRichTextBuffer::Reset() AddParagraph(wxEmptyString); GetCommandProcessor()->ClearCommands(); Modify(false); + Invalidate(wxRICHTEXT_ALL); } /// Submit command to insert the given text @@ -3614,8 +3679,11 @@ void wxRichTextBuffer::CleanUpHandlers() sm_handlers.Clear(); } -wxString wxRichTextBuffer::GetExtWildcard(bool combine, bool save) +wxString wxRichTextBuffer::GetExtWildcard(bool combine, bool save, wxArrayInt* types) { + if (types) + types->Clear(); + wxString wildcard; wxList::compatibility_iterator node = GetHandlers().GetFirst(); @@ -3642,6 +3710,8 @@ wxString wxRichTextBuffer::GetExtWildcard(bool combine, bool save) wildcard += handler->GetExtension(); wildcard += wxT(")|*."); wildcard += handler->GetExtension(); + if (types) + types->Add(handler->GetType()); } count ++; } @@ -3659,7 +3729,13 @@ bool wxRichTextBuffer::LoadFile(const wxString& filename, int type) { wxRichTextFileHandler* handler = FindHandlerFilenameOrType(filename, type); if (handler) - return handler->LoadFile(this, filename); + { + SetDefaultStyle(wxTextAttrEx()); + + bool success = handler->LoadFile(this, filename); + Invalidate(wxRICHTEXT_ALL); + return success; + } else return false; } @@ -3679,7 +3755,12 @@ bool wxRichTextBuffer::LoadFile(wxInputStream& stream, int type) { wxRichTextFileHandler* handler = FindHandler(type); if (handler) - return handler->LoadFile(this, stream); + { + SetDefaultStyle(wxTextAttrEx()); + bool success = handler->LoadFile(this, stream); + Invalidate(wxRICHTEXT_ALL); + return success; + } else return false; } @@ -3886,6 +3967,7 @@ bool wxRichTextAction::Do() { m_buffer->InsertFragment(GetPosition(), m_newParagraphs); m_buffer->UpdateRanges(); + m_buffer->Invalidate(GetRange()); long newCaretPosition = GetPosition() + m_newParagraphs.GetRange().GetLength() - 1; if (m_newParagraphs.GetPartialParagraph()) @@ -3899,6 +3981,7 @@ bool wxRichTextAction::Do() { m_buffer->DeleteRange(GetRange()); m_buffer->UpdateRanges(); + m_buffer->Invalidate(wxRichTextRange(GetRange().GetStart(), GetRange().GetStart())); UpdateAppearance(GetRange().GetStart()-1, true /* send update event */); @@ -3907,6 +3990,7 @@ bool wxRichTextAction::Do() case wxRICHTEXT_CHANGE_STYLE: { ApplyParagraphs(GetNewParagraphs()); + m_buffer->Invalidate(GetRange()); UpdateAppearance(GetPosition()); @@ -3929,6 +4013,7 @@ bool wxRichTextAction::Undo() { m_buffer->DeleteRange(GetRange()); m_buffer->UpdateRanges(); + m_buffer->Invalidate(wxRichTextRange(GetRange().GetStart(), GetRange().GetStart())); long newCaretPosition = GetPosition() - 1; // if (m_newParagraphs.GetPartialParagraph()) @@ -3942,6 +4027,7 @@ bool wxRichTextAction::Undo() { m_buffer->InsertFragment(GetRange().GetStart(), m_oldParagraphs); m_buffer->UpdateRanges(); + m_buffer->Invalidate(GetRange()); UpdateAppearance(GetPosition(), true /* send update event */); @@ -3950,6 +4036,7 @@ bool wxRichTextAction::Undo() case wxRICHTEXT_CHANGE_STYLE: { ApplyParagraphs(GetOldParagraphs()); + m_buffer->Invalidate(GetRange()); UpdateAppearance(GetPosition()); @@ -4763,13 +4850,19 @@ bool wxRichTextPlainTextHandler::DoLoadFile(wxRichTextBuffer *buffer, wxInputStr wxString str; int ch = 0; + int lastCh = 0; while (!stream.Eof()) { ch = stream.GetC(); - if (ch > 0) + if (ch == 10 && lastCh != 13) + str += wxT('\n'); + + if (ch > 0 && ch != 10) str += wxChar(ch); + + lastCh = ch; } buffer->Clear(); diff --git a/src/richtext/richtextctrl.cpp b/src/richtext/richtextctrl.cpp index fb944cfe31..057deed1fa 100644 --- a/src/richtext/richtextctrl.cpp +++ b/src/richtext/richtextctrl.cpp @@ -291,7 +291,7 @@ void wxRichTextCtrl::OnLeftClick(wxMouseEvent& event) wxRichTextParagraph* para = GetBuffer().GetParagraphAtPosition(position); wxRichTextLine* line = GetBuffer().GetLineAtPosition(position); - if (line && para && line->GetRange().GetStart() == position && para->GetRange().GetStart() != position) + if (line && para && line->GetAbsoluteRange().GetStart() == position && para->GetRange().GetStart() != position) caretAtLineStart = true; position --; } @@ -358,7 +358,7 @@ void wxRichTextCtrl::OnMoveMouse(wxMouseEvent& event) wxRichTextParagraph* para = GetBuffer().GetParagraphAtPosition(position); wxRichTextLine* line = GetBuffer().GetLineAtPosition(position); - if (line && para && line->GetRange().GetStart() == position && para->GetRange().GetStart() != position) + if (line && para && line->GetAbsoluteRange().GetStart() == position && para->GetRange().GetStart() != position) caretAtLineStart = true; position --; } @@ -792,10 +792,12 @@ void wxRichTextCtrl::MoveCaretForward(long oldPosition) if (line) { + wxRichTextRange lineRange = line->GetAbsoluteRange(); + // We're at the end of a line. See whether we need to // stay at the same actual caret position but change visual // position, or not. - if (oldPosition == line->GetRange().GetEnd()) + if (oldPosition == lineRange.GetEnd()) { if (m_caretAtLineStart) { @@ -835,16 +837,18 @@ void wxRichTextCtrl::MoveCaretBack(long oldPosition) if (line) { + wxRichTextRange lineRange = line->GetAbsoluteRange(); + // We're at the start of a line. See whether we need to // stay at the same actual caret position but change visual // position, or not. - if (oldPosition == line->GetRange().GetStart()) + if (oldPosition == lineRange.GetStart()) { m_caretPosition = oldPosition-1; m_caretAtLineStart = true; return; } - else if (oldPosition == line->GetRange().GetEnd()) + else if (oldPosition == lineRange.GetEnd()) { if (m_caretAtLineStart) { @@ -985,13 +989,14 @@ bool wxRichTextCtrl::MoveDown(int noLines, int flags) if (hitTest == wxRICHTEXT_HITTEST_BEFORE) { wxRichTextLine* thisLine = GetBuffer().GetLineAtPosition(newPos-1); - if (thisLine && (newPos-1) == thisLine->GetRange().GetEnd()) + wxRichTextRange lineRange; + if (thisLine) + lineRange = thisLine->GetAbsoluteRange(); + + if (thisLine && (newPos-1) == lineRange.GetEnd()) { - // if (para->GetRange().GetStart() != thisLine->GetRange().GetStart()) - { - newPos --; - caretLineStart = true; - } + newPos --; + caretLineStart = true; } else { @@ -1069,7 +1074,8 @@ bool wxRichTextCtrl::MoveToLineEnd(int flags) if (line) { - long newPos = line->GetRange().GetEnd(); + wxRichTextRange lineRange = line->GetAbsoluteRange(); + long newPos = lineRange.GetEnd(); if (!ExtendSelection(m_caretPosition, newPos, flags)) SelectNone(); @@ -1091,14 +1097,15 @@ bool wxRichTextCtrl::MoveToLineStart(int flags) wxRichTextLine* line = GetVisibleLineForCaretPosition(m_caretPosition); if (line) { - long newPos = line->GetRange().GetStart()-1; + wxRichTextRange lineRange = line->GetAbsoluteRange(); + long newPos = lineRange.GetStart()-1; if (!ExtendSelection(m_caretPosition, newPos, flags)) SelectNone(); wxRichTextParagraph* para = GetBuffer().GetParagraphForLine(line); - SetCaretPosition(newPos, para->GetRange().GetStart() != line->GetRange().GetStart()); + SetCaretPosition(newPos, para->GetRange().GetStart() != lineRange.GetStart()); PositionCaret(); SetDefaultStyleToCursorStyle(); @@ -1171,7 +1178,8 @@ bool wxRichTextCtrl::PageDown(int noPages, int flags) wxRichTextLine* newLine = GetBuffer().GetLineAtYPosition(newY); if (newLine) { - long pos = newLine->GetRange().GetStart()-1; + wxRichTextRange lineRange = newLine->GetAbsoluteRange(); + long pos = lineRange.GetStart()-1; if (pos != m_caretPosition) { wxRichTextParagraph* para = GetBuffer().GetParagraphForLine(newLine); @@ -1179,7 +1187,7 @@ bool wxRichTextCtrl::PageDown(int noPages, int flags) if (!ExtendSelection(m_caretPosition, pos, flags)) SelectNone(); - SetCaretPosition(pos, para->GetRange().GetStart() != newLine->GetRange().GetStart()); + SetCaretPosition(pos, para->GetRange().GetStart() != lineRange.GetStart()); PositionCaret(); SetDefaultStyleToCursorStyle(); @@ -1315,7 +1323,7 @@ bool wxRichTextCtrl::WordRight(int WXUNUSED(n), int flags) /// Sizing void wxRichTextCtrl::OnSize(wxSizeEvent& event) { - GetBuffer().SetDirty(true); + GetBuffer().Invalidate(wxRICHTEXT_ALL); RecreateBuffer(); @@ -2171,8 +2179,9 @@ wxRichTextLine* wxRichTextCtrl::GetVisibleLineForCaretPosition(long caretPositio wxRichTextParagraph* para = GetBuffer().GetParagraphAtPosition(caretPosition, true); if (line) { - if (caretPosition == line->GetRange().GetStart()-1 && - (para->GetRange().GetStart() != line->GetRange().GetStart())) + wxRichTextRange lineRange = line->GetAbsoluteRange(); + if (caretPosition == lineRange.GetStart()-1 && + (para->GetRange().GetStart() != lineRange.GetStart())) { if (!m_caretAtLineStart) line = GetBuffer().GetLineAtPosition(caretPosition-1, true); @@ -2204,24 +2213,27 @@ bool wxRichTextCtrl::MoveCaret(long pos, bool showAtLineStart) /// setting the caret position. bool wxRichTextCtrl::Layout() { - wxRect availableSpace(GetClientSize()); - if (availableSpace.width == 0) - availableSpace.width = 10; - if (availableSpace.height == 0) - availableSpace.height = 10; - - wxClientDC dc(this); - dc.SetFont(GetFont()); - - PrepareDC(dc); - - GetBuffer().Defragment(); - GetBuffer().UpdateRanges(); // If items were deleted, ranges need recalculation - GetBuffer().Layout(dc, availableSpace, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT); - GetBuffer().SetDirty(false); - - if (!IsFrozen()) - SetupScrollbars(); + if (GetBuffer().GetDirty()) + { + wxRect availableSpace(GetClientSize()); + if (availableSpace.width == 0) + availableSpace.width = 10; + if (availableSpace.height == 0) + availableSpace.height = 10; + + wxClientDC dc(this); + dc.SetFont(GetFont()); + + PrepareDC(dc); + + GetBuffer().Defragment(); + GetBuffer().UpdateRanges(); // If items were deleted, ranges need recalculation + GetBuffer().Layout(dc, availableSpace, wxRICHTEXT_FIXED_WIDTH|wxRICHTEXT_VARIABLE_HEIGHT); + GetBuffer().SetDirty(false); + + if (!IsFrozen()) + SetupScrollbars(); + } return true; } diff --git a/src/richtext/richtextxml.cpp b/src/richtext/richtextxml.cpp index 516fb41a28..f8d267d2e4 100644 --- a/src/richtext/richtextxml.cpp +++ b/src/richtext/richtextxml.cpp @@ -257,6 +257,15 @@ wxString wxRichTextXMLHandler::GetText(wxXmlNode *node, const wxString& param, b return str1; } +// For use with earlier versions of wxWidgets +#ifndef WXUNUSED_IN_UNICODE +#if wxUSE_UNICODE +#define WXUNUSED_IN_UNICODE(x) WXUNUSED(x) +#else +#define WXUNUSED_IN_UNICODE(x) x +#endif +#endif + // write string to output: inline static void OutputString(wxOutputStream& stream, const wxString& str, wxMBConv *WXUNUSED_IN_UNICODE(convMem) = NULL, wxMBConv *convFile = NULL) -- 2.45.2