From 2c906df2174c1d0c8befc67cb0b61e789dd2eb82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Sun, 19 Jan 2014 16:33:36 +0100 Subject: [PATCH] Text stuff: Bugfixes in Insert and Remove methods Still not well tested. Also some way to trigger the layouts to adopt to the changed document paragraphs. Not yet via the new TextListener. --- src/apps/haiku-depot/textview/Paragraph.cpp | 22 ++++++++++----- .../haiku-depot/textview/TextDocument.cpp | 4 +-- .../textview/TextDocumentLayout.cpp | 28 +++++++++++++++++++ .../haiku-depot/textview/TextDocumentLayout.h | 3 ++ src/apps/haiku-depot/textview/TextEditor.cpp | 6 ++++ 5 files changed, 54 insertions(+), 9 deletions(-) diff --git a/src/apps/haiku-depot/textview/Paragraph.cpp b/src/apps/haiku-depot/textview/Paragraph.cpp index 2c4f401027..d3b8a163cd 100644 --- a/src/apps/haiku-depot/textview/Paragraph.cpp +++ b/src/apps/haiku-depot/textview/Paragraph.cpp @@ -92,6 +92,7 @@ Paragraph::Insert(int32 offset, const TextSpan& newSpan) if (offset - span.CharCount() < 0) break; offset -= span.CharCount(); + index++; } if (fTextSpans.CountItems() == index) @@ -139,25 +140,28 @@ Paragraph::Remove(int32 offset, int32 length) if (offset - span.CharCount() < 0) break; offset -= span.CharCount(); + index++; } if (index >= fTextSpans.CountItems()) return false; - - TextSpan span = fTextSpans.ItemAtFast(index).SubSpan(0, offset); + + TextSpan span(fTextSpans.ItemAtFast(index)); + int32 removeLength = std::min(span.CharCount() - offset, length); + span.Remove(offset, removeLength); fTextSpans.Replace(index, span); + length -= removeLength; index += 1; - if (index >= fTextSpans.CountItems()) - return true; - - while (length > 0) { + + // Remove more spans if necessary + while (length > 0 && index < fTextSpans.CountItems()) { int32 spanLength = fTextSpans.ItemAtFast(index).CharCount(); if (spanLength <= length) { fTextSpans.Remove(index); length -= spanLength; } else { // Reached last span - int32 removeLength = std::min(length, spanLength); + removeLength = std::min(length, spanLength); TextSpan lastSpan = fTextSpans.ItemAtFast(index).SubSpan( removeLength, spanLength - removeLength); // Try to merge with first span, otherwise replace span at index @@ -172,6 +176,10 @@ Paragraph::Remove(int32 offset, int32 length) } } + // See if anything from the TextSpan at offset remained + if (span.CharCount() == 0) + fTextSpans.Remove(index - 1); + return true; } diff --git a/src/apps/haiku-depot/textview/TextDocument.cpp b/src/apps/haiku-depot/textview/TextDocument.cpp index 6eba25c590..02043814f6 100644 --- a/src/apps/haiku-depot/textview/TextDocument.cpp +++ b/src/apps/haiku-depot/textview/TextDocument.cpp @@ -125,7 +125,7 @@ TextDocument::Remove(int32 textOffset, int32 length) textOffset = 0; - while (length > 0) { + while (length > 0 && index + 1 < fParagraphs.CountItems()) { const Paragraph& paragraph = ParagraphAt(index + 1); paragraphLength = paragraph.Length(); // Remove paragraph in any case. If some of it remains, the last @@ -238,10 +238,10 @@ TextDocument::ParagraphIndexFor(int32 textOffset, int32& paragraphOffset) const int32 count = fParagraphs.CountItems(); for (int32 i = 0; i < count; i++) { const Paragraph& paragraph = fParagraphs.ItemAtFast(i); - paragraphOffset = textOffset - textLength; int32 paragraphLength = paragraph.Length(); if (textLength + paragraphLength > textOffset) return i; + paragraphOffset += paragraphLength; textLength += paragraphLength; } return -1; diff --git a/src/apps/haiku-depot/textview/TextDocumentLayout.cpp b/src/apps/haiku-depot/textview/TextDocumentLayout.cpp index afea2f6fe2..cc98029e76 100644 --- a/src/apps/haiku-depot/textview/TextDocumentLayout.cpp +++ b/src/apps/haiku-depot/textview/TextDocumentLayout.cpp @@ -61,6 +61,34 @@ TextDocumentLayout::SetTextDocument(const TextDocumentRef& document) } +void +TextDocumentLayout::Invalidate() +{ + InvalidateParagraphs(0, fParagraphLayouts.CountItems()); +} + + +void +TextDocumentLayout::InvalidateParagraphs(int32 start, int32 count) +{ + if (start < 0 || fDocument.Get() == NULL) + return; + + const ParagraphList& paragraphs = fDocument->Paragraphs(); + + while (count > 0) { + if (start >= fParagraphLayouts.CountItems()) + break; + + const Paragraph& paragraph = paragraphs.ItemAtFast(start); + const ParagraphLayoutInfo& info = fParagraphLayouts.ItemAtFast(start); + info.layout->SetParagraph(paragraph); + + start++; + } +} + + void TextDocumentLayout::SetWidth(float width) { diff --git a/src/apps/haiku-depot/textview/TextDocumentLayout.h b/src/apps/haiku-depot/textview/TextDocumentLayout.h index 8d439582f5..2e3df4bdfb 100644 --- a/src/apps/haiku-depot/textview/TextDocumentLayout.h +++ b/src/apps/haiku-depot/textview/TextDocumentLayout.h @@ -78,6 +78,9 @@ public: void SetTextDocument( const TextDocumentRef& document); + void Invalidate(); + void InvalidateParagraphs(int32 start, int32 count); + void SetWidth(float width); float Width() const { return fWidth; } diff --git a/src/apps/haiku-depot/textview/TextEditor.cpp b/src/apps/haiku-depot/textview/TextEditor.cpp index ec034a4df8..2c803e9d00 100644 --- a/src/apps/haiku-depot/textview/TextEditor.cpp +++ b/src/apps/haiku-depot/textview/TextEditor.cpp @@ -243,6 +243,9 @@ TextEditor::Insert(int32 offset, const BString& string) if (!fEditingEnabled || fDocument.Get() == NULL) return B_ERROR; + // TODO: Via listener, and only affected paragraphs + fLayout->Invalidate(); + return fDocument->Insert(offset, string, fStyleAtCaret); } @@ -253,6 +256,9 @@ TextEditor::Remove(int32 offset, int32 length) if (!fEditingEnabled || fDocument.Get() == NULL) return B_ERROR; + // TODO: Via listener, and only affected paragraphs + fLayout->Invalidate(); + return fDocument->Remove(offset, length); }