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:
parent
7e8dde4846
commit
300c690eb6
@ -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) {
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user