Text stuff: Fixed various issues with editing.

* Insert/Remove now works for simple typing.
 * Inserting multiple paragaphs not yet tested.
 * Renamed TextSpan::CharCount() to CountChars() for consistency.
This commit is contained in:
Stephan Aßmus 2014-01-19 23:04:50 +01:00
parent 7e8dde4846
commit 300c690eb6
6 changed files with 127 additions and 43 deletions

View File

@ -105,9 +105,9 @@ Paragraph::Insert(int32 offset, const TextSpan& newSpan)
int32 index = 0;
while (index < fTextSpans.CountItems()) {
const TextSpan& span = fTextSpans.ItemAtFast(index);
if (offset - span.CharCount() < 0)
if (offset - span.CountChars() < 0)
break;
offset -= span.CharCount();
offset -= span.CountChars();
index++;
}
@ -126,7 +126,7 @@ Paragraph::Insert(int32 offset, const TextSpan& newSpan)
// Try to merge with TextSpan before if offset == 0 && index > 0
TextSpan span = fTextSpans.ItemAtFast(index - 1);
if (span.Style() == newSpan.Style()) {
span.Insert(span.CharCount(), newSpan.Text());
span.Insert(span.CountChars(), newSpan.Text());
return fTextSpans.Replace(index - 1, span);
}
}
@ -136,7 +136,7 @@ Paragraph::Insert(int32 offset, const TextSpan& newSpan)
// Split the span,
TextSpan spanBefore = span.SubSpan(0, offset);
TextSpan spanAfter = span.SubSpan(offset, span.CharCount() - offset);
TextSpan spanAfter = span.SubSpan(offset, span.CountChars() - offset);
return fTextSpans.Replace(index, spanBefore)
&& fTextSpans.Add(newSpan, index + 1)
@ -153,9 +153,9 @@ Paragraph::Remove(int32 offset, int32 length)
int32 index = 0;
while (index < fTextSpans.CountItems()) {
const TextSpan& span = fTextSpans.ItemAtFast(index);
if (offset - span.CharCount() < 0)
if (offset - span.CountChars() < 0)
break;
offset -= span.CharCount();
offset -= span.CountChars();
index++;
}
@ -163,7 +163,7 @@ Paragraph::Remove(int32 offset, int32 length)
return false;
TextSpan span(fTextSpans.ItemAtFast(index));
int32 removeLength = std::min(span.CharCount() - offset, length);
int32 removeLength = std::min(span.CountChars() - offset, length);
span.Remove(offset, removeLength);
fTextSpans.Replace(index, span);
length -= removeLength;
@ -171,7 +171,7 @@ Paragraph::Remove(int32 offset, int32 length)
// Remove more spans if necessary
while (length > 0 && index < fTextSpans.CountItems()) {
int32 spanLength = fTextSpans.ItemAtFast(index).CharCount();
int32 spanLength = fTextSpans.ItemAtFast(index).CountChars();
if (spanLength <= length) {
fTextSpans.Remove(index);
length -= spanLength;
@ -182,7 +182,7 @@ Paragraph::Remove(int32 offset, int32 length)
removeLength, spanLength - removeLength);
// Try to merge with first span, otherwise replace span at index
if (lastSpan.Style() == span.Style()) {
span.Insert(span.CharCount(), lastSpan.Text());
span.Insert(span.CountChars(), lastSpan.Text());
fTextSpans.Replace(index - 1, span);
} else {
fTextSpans.Replace(index, lastSpan);
@ -193,7 +193,7 @@ Paragraph::Remove(int32 offset, int32 length)
}
// See if anything from the TextSpan at offset remained
if (span.CharCount() == 0)
if (span.CountChars() == 0)
fTextSpans.Remove(index - 1);
return true;
@ -213,7 +213,7 @@ Paragraph::Length() const
int32 length = 0;
for (int32 i = fTextSpans.CountItems() - 1; i >= 0; i--) {
const TextSpan& span = fTextSpans.ItemAtFast(i);
length += span.CharCount();
length += span.CountChars();
}
return length;
}
@ -237,7 +237,7 @@ Paragraph::GetText(int32 start, int32 length) const
int32 count = fTextSpans.CountItems();
for (int32 i = 0; i < count; i++) {
const TextSpan& span = fTextSpans.ItemAtFast(i);
int32 spanLength = span.CharCount();
int32 spanLength = span.CountChars();
if (spanLength == 0)
continue;
if (start > spanLength) {

View File

@ -792,7 +792,7 @@ ParagraphLayout::_ApplyAlignment()
bool
ParagraphLayout::_AppendGlyphInfos(const TextSpan& span)
{
int charCount = span.CharCount();
int charCount = span.CountChars();
if (charCount == 0)
return true;
@ -861,7 +861,7 @@ ParagraphLayout::_FinalizeLine(int lineStart, int lineEnd, int lineIndex,
spanIndex++;
const TextSpan& span = fTextSpans.ItemAt(spanIndex);
spanStart = spanEnd;
spanEnd += span.CharCount();
spanEnd += span.CountChars();
addSpan = true;
}
@ -910,7 +910,7 @@ ParagraphLayout::_DrawLine(BView* view, const BPoint& offset,
for (int i = 0; i < spanCount; i++) {
const TextSpan& span = line.layoutedSpans.ItemAtFast(i);
_DrawSpan(view, offset, span, textOffset);
textOffset += span.CharCount();
textOffset += span.CountChars();
}
}

View File

@ -70,24 +70,102 @@ TextDocument::operator!=(const TextDocument& other) const
status_t
TextDocument::Insert(int32 offset, const BString& text)
TextDocument::Insert(int32 textOffset, const BString& text)
{
return Insert(offset, text, CharacterStyleAt(offset));
return Insert(textOffset, text, CharacterStyleAt(textOffset));
}
status_t
TextDocument::Insert(int32 offset, const BString& text, const CharacterStyle& style)
TextDocument::Insert(int32 textOffset, const BString& text,
const CharacterStyle& style)
{
return Insert(offset, text, style, ParagraphStyleAt(offset));
return Insert(textOffset, text, style, ParagraphStyleAt(textOffset));
}
status_t
TextDocument::Insert(int32 offset, const BString& text,
const CharacterStyle& CharacterStyle, const ParagraphStyle& paragraphStyle)
TextDocument::Insert(int32 textOffset, const BString& text,
const CharacterStyle& characterStyle, const ParagraphStyle& paragraphStyle)
{
return Replace(offset, 0, text, CharacterStyle, paragraphStyle);
int32 paragraphOffset;
int32 index = ParagraphIndexFor(textOffset, paragraphOffset);
if (index < 0)
return B_BAD_VALUE;
textOffset -= paragraphOffset;
bool hasLineBreaks = text.FindFirst('\n', 0) >= 0;
if (hasLineBreaks) {
// Split paragraph at textOffset
Paragraph paragraph1(ParagraphAt(index).Style());
Paragraph paragraph2(paragraphStyle);
const TextSpanList& textSpans = ParagraphAt(index).TextSpans();
int32 spanCount = textSpans.CountItems();
for (int32 i = 0; i < spanCount; i++) {
const TextSpan& span = textSpans.ItemAtFast(i);
int32 spanLength = span.CountChars();
if (textOffset >= spanLength) {
paragraph1.Append(span);
textOffset -= spanLength;
} else if (textOffset > 0) {
paragraph1.Append(
span.SubSpan(0, textOffset));
paragraph2.Append(
span.SubSpan(textOffset, spanLength - textOffset));
textOffset = 0;
} else {
paragraph2.Append(span);
}
}
fParagraphs.Remove(index);
// Insert TextSpans, splitting 'text' into Paragraphs at line breaks.
int32 length = text.CountChars();
int32 chunkStart = 0;
while (chunkStart < length) {
int32 chunkEnd = text.FindFirst('\n', chunkStart);
bool foundLineBreak = chunkEnd > chunkStart;
if (foundLineBreak)
chunkEnd++;
else
chunkEnd = length;
BString chunk;
text.CopyCharsInto(chunk, chunkStart, chunkEnd - chunkStart);
TextSpan span(chunk, characterStyle);
if (foundLineBreak) {
if (!paragraph1.Append(span))
return B_NO_MEMORY;
if (paragraph1.Length() > 0) {
if (!fParagraphs.Add(paragraph1, index))
return B_NO_MEMORY;
index++;
}
paragraph1 = Paragraph(paragraphStyle);
} else {
if (!paragraph2.Prepend(span))
return B_NO_MEMORY;
if (paragraph2.Length() > 0) {
if (!fParagraphs.Add(paragraph2, index))
return B_NO_MEMORY;
index++;
}
}
chunkStart = chunkEnd + 1;
}
} else {
Paragraph paragraph(ParagraphAt(index));
paragraph.Insert(textOffset, TextSpan(text, characterStyle));
if (!fParagraphs.Replace(index, paragraph))
return B_NO_MEMORY;
}
return B_OK;
}
@ -165,31 +243,30 @@ TextDocument::Remove(int32 textOffset, int32 length)
status_t
TextDocument::Replace(int32 offset, int32 length, const BString& text)
TextDocument::Replace(int32 textOffset, int32 length, const BString& text)
{
return Replace(offset, length, text, CharacterStyleAt(offset));
return Replace(textOffset, length, text, CharacterStyleAt(textOffset));
}
status_t
TextDocument::Replace(int32 offset, int32 length, const BString& text,
TextDocument::Replace(int32 textOffset, int32 length, const BString& text,
const CharacterStyle& style)
{
return Replace(offset, length, text, style, ParagraphStyleAt(offset));
return Replace(textOffset, length, text, style,
ParagraphStyleAt(textOffset));
}
status_t
TextDocument::Replace(int32 offset, int32 length, const BString& text,
const CharacterStyle& CharacterStyle, const ParagraphStyle& paragraphStyle)
TextDocument::Replace(int32 textOffset, int32 length, const BString& text,
const CharacterStyle& characterStyle, const ParagraphStyle& paragraphStyle)
{
status_t ret = Remove(offset, length);
status_t ret = Remove(textOffset, length);
if (ret != B_OK)
return ret;
// TODO: ...
return B_ERROR;
return Insert(textOffset, text, characterStyle, paragraphStyle);
}
@ -208,9 +285,10 @@ TextDocument::CharacterStyleAt(int32 textOffset) const
int32 index = 0;
while (index < spans.CountItems()) {
const TextSpan& span = spans.ItemAtFast(index);
if (textOffset - span.CharCount() < 0)
if (textOffset - span.CountChars() < 0)
return span.Style();
textOffset -= span.CharCount();
textOffset -= span.CountChars();
index++;
}
return fDefaultCharacterStyle;

View File

@ -28,21 +28,21 @@ public:
bool operator!=(const TextDocument& other) const;
// Text insertion and removing
status_t Insert(int32 offset, const BString& text);
status_t Insert(int32 offset, const BString& text,
status_t Insert(int32 textOffset, const BString& text);
status_t Insert(int32 textOffset, const BString& text,
const CharacterStyle& style);
status_t Insert(int32 offset, const BString& text,
status_t Insert(int32 textOffset, const BString& text,
const CharacterStyle& characterStyle,
const ParagraphStyle& paragraphStyle);
status_t Remove(int32 offset, int32 length);
status_t Remove(int32 textOffset, int32 length);
status_t Replace(int32 offset, int32 length,
status_t Replace(int32 textOffset, int32 length,
const BString& text);
status_t Replace(int32 offset, int32 length,
status_t Replace(int32 textOffset, int32 length,
const BString& text,
const CharacterStyle& style);
status_t Replace(int32 offset, int32 length,
status_t Replace(int32 textOffset, int32 length,
const BString& text,
const CharacterStyle& characterStyle,
const ParagraphStyle& paragraphStyle);
@ -68,7 +68,7 @@ public:
// Query information
int32 Length() const;
BString GetText(int32 start, int32 length) const;
BString GetText(int32 textOffset, int32 length) const;
private:
ParagraphList fParagraphs;

View File

@ -6,6 +6,7 @@
#include "TextEditor.h"
#include <algorithm>
#include <stdio.h>
TextEditor::TextEditor()
@ -230,6 +231,11 @@ TextEditor::KeyDown(KeyEvent event)
if (event.bytes != NULL && event.length > 0) {
// Handle null-termintating the string
BString text(event.bytes, event.length);
// Remove selection, if any
if (HasSelection())
Remove(SelectionStart(), SelectionLength());
Insert(fSelection.Caret(), text);
}
break;

View File

@ -30,7 +30,7 @@ public:
inline const CharacterStyle& Style() const
{ return fStyle; }
inline int32 CharCount() const
inline int32 CountChars() const
{ return fCharCount; }
bool Insert(int32 offset, const BString& text);