summaryrefslogtreecommitdiffstats
path: root/scintilla/src/CellBuffer.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'scintilla/src/CellBuffer.cxx')
-rw-r--r--scintilla/src/CellBuffer.cxx114
1 files changed, 107 insertions, 7 deletions
diff --git a/scintilla/src/CellBuffer.cxx b/scintilla/src/CellBuffer.cxx
index 003710f..7c1b42c 100644
--- a/scintilla/src/CellBuffer.cxx
+++ b/scintilla/src/CellBuffer.cxx
@@ -16,6 +16,7 @@
#include "SplitVector.h"
#include "Partitioning.h"
#include "CellBuffer.h"
+#include "UniConversion.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
@@ -331,6 +332,7 @@ void UndoHistory::CompletedRedoStep() {
CellBuffer::CellBuffer() {
readOnly = false;
+ utf8LineEnds = 0;
collectingUndo = true;
}
@@ -458,6 +460,13 @@ void CellBuffer::Allocate(int newSize) {
style.ReAllocate(newSize);
}
+void CellBuffer::SetLineEndTypes(int utf8LineEnds_) {
+ if (utf8LineEnds != utf8LineEnds_) {
+ utf8LineEnds = utf8LineEnds_;
+ ResetLineEnds();
+ }
+}
+
void CellBuffer::SetPerLine(PerLine *pl) {
lv.SetPerLine(pl);
}
@@ -501,11 +510,63 @@ void CellBuffer::RemoveLine(int line) {
lv.RemoveLine(line);
}
+bool CellBuffer::UTF8LineEndOverlaps(int position) const {
+ unsigned char bytes[] = {
+ static_cast<unsigned char>(substance.ValueAt(position-2)),
+ static_cast<unsigned char>(substance.ValueAt(position-1)),
+ static_cast<unsigned char>(substance.ValueAt(position)),
+ static_cast<unsigned char>(substance.ValueAt(position+1)),
+ };
+ return UTF8IsSeparator(bytes) || UTF8IsSeparator(bytes+1) || UTF8IsNEL(bytes+1);
+}
+
+void CellBuffer::ResetLineEnds() {
+ // Reinitialize line data -- too much work to preserve
+ lv.Init();
+
+ int position = 0;
+ int length = Length();
+ int lineInsert = 1;
+ bool atLineStart = true;
+ lv.InsertText(lineInsert-1, length);
+ unsigned char chBeforePrev = 0;
+ unsigned char chPrev = 0;
+ for (int i = 0; i < length; i++) {
+ unsigned char ch = substance.ValueAt(position + i);
+ if (ch == '\r') {
+ InsertLine(lineInsert, (position + i) + 1, atLineStart);
+ lineInsert++;
+ } else if (ch == '\n') {
+ if (chPrev == '\r') {
+ // Patch up what was end of line
+ lv.SetLineStart(lineInsert - 1, (position + i) + 1);
+ } else {
+ InsertLine(lineInsert, (position + i) + 1, atLineStart);
+ lineInsert++;
+ }
+ } else if (utf8LineEnds) {
+ unsigned char back3[3] = {chBeforePrev, chPrev, ch};
+ if (UTF8IsSeparator(back3) || UTF8IsNEL(back3+1)) {
+ InsertLine(lineInsert, (position + i) + 1, atLineStart);
+ lineInsert++;
+ }
+ }
+ chBeforePrev = chPrev;
+ chPrev = ch;
+ }
+}
+
void CellBuffer::BasicInsertString(int position, const char *s, int insertLength) {
if (insertLength == 0)
return;
PLATFORM_ASSERT(insertLength > 0);
+ unsigned char chAfter = substance.ValueAt(position);
+ bool breakingUTF8LineEnd = false;
+ if (utf8LineEnds && UTF8IsTrailByte(chAfter)) {
+ breakingUTF8LineEnd = UTF8LineEndOverlaps(position);
+ }
+
substance.InsertFromArray(position, s, 0, insertLength);
style.InsertValue(position, insertLength, 0);
@@ -513,14 +574,17 @@ void CellBuffer::BasicInsertString(int position, const char *s, int insertLength
bool atLineStart = lv.LineStart(lineInsert-1) == position;
// Point all the lines after the insertion point further along in the buffer
lv.InsertText(lineInsert-1, insertLength);
- char chPrev = substance.ValueAt(position - 1);
- char chAfter = substance.ValueAt(position + insertLength);
+ unsigned char chBeforePrev = substance.ValueAt(position - 2);
+ unsigned char chPrev = substance.ValueAt(position - 1);
if (chPrev == '\r' && chAfter == '\n') {
// Splitting up a crlf pair at position
InsertLine(lineInsert, position, false);
lineInsert++;
}
- char ch = ' ';
+ if (breakingUTF8LineEnd) {
+ RemoveLine(lineInsert);
+ }
+ unsigned char ch = ' ';
for (int i = 0; i < insertLength; i++) {
ch = s[i];
if (ch == '\r') {
@@ -534,7 +598,14 @@ void CellBuffer::BasicInsertString(int position, const char *s, int insertLength
InsertLine(lineInsert, (position + i) + 1, atLineStart);
lineInsert++;
}
+ } else if (utf8LineEnds) {
+ unsigned char back3[3] = {chBeforePrev, chPrev, ch};
+ if (UTF8IsSeparator(back3) || UTF8IsNEL(back3+1)) {
+ InsertLine(lineInsert, (position + i) + 1, atLineStart);
+ lineInsert++;
+ }
}
+ chBeforePrev = chPrev;
chPrev = ch;
}
// Joining two lines where last insertion is cr and following substance starts with lf
@@ -543,6 +614,22 @@ void CellBuffer::BasicInsertString(int position, const char *s, int insertLength
// End of line already in buffer so drop the newly created one
RemoveLine(lineInsert - 1);
}
+ } else if (utf8LineEnds && !UTF8IsAscii(chAfter)) {
+ // May have end of UTF-8 line end in buffer and start in insertion
+ for (int j = 0; j < UTF8SeparatorLength-1; j++) {
+ unsigned char chAt = substance.ValueAt(position + insertLength + j);
+ unsigned char back3[3] = {chBeforePrev, chPrev, chAt};
+ if (UTF8IsSeparator(back3)) {
+ InsertLine(lineInsert, (position + insertLength + j) + 1, atLineStart);
+ lineInsert++;
+ }
+ if ((j == 0) && UTF8IsNEL(back3+1)) {
+ InsertLine(lineInsert, (position + insertLength + j) + 1, atLineStart);
+ lineInsert++;
+ }
+ chBeforePrev = chPrev;
+ chPrev = chAt;
+ }
}
}
@@ -560,9 +647,9 @@ void CellBuffer::BasicDeleteChars(int position, int deleteLength) {
int lineRemove = lv.LineFromPosition(position) + 1;
lv.InsertText(lineRemove-1, - (deleteLength));
- char chPrev = substance.ValueAt(position - 1);
- char chBefore = chPrev;
- char chNext = substance.ValueAt(position);
+ unsigned char chPrev = substance.ValueAt(position - 1);
+ unsigned char chBefore = chPrev;
+ unsigned char chNext = substance.ValueAt(position);
bool ignoreNL = false;
if (chPrev == '\r' && chNext == '\n') {
// Move back one
@@ -570,8 +657,13 @@ void CellBuffer::BasicDeleteChars(int position, int deleteLength) {
lineRemove++;
ignoreNL = true; // First \n is not real deletion
}
+ if (utf8LineEnds && UTF8IsTrailByte(chNext)) {
+ if (UTF8LineEndOverlaps(position)) {
+ RemoveLine(lineRemove);
+ }
+ }
- char ch = chNext;
+ unsigned char ch = chNext;
for (int i = 0; i < deleteLength; i++) {
chNext = substance.ValueAt(position + i + 1);
if (ch == '\r') {
@@ -584,6 +676,14 @@ void CellBuffer::BasicDeleteChars(int position, int deleteLength) {
} else {
RemoveLine(lineRemove);
}
+ } else if (utf8LineEnds) {
+ if (!UTF8IsAscii(ch)) {
+ unsigned char next3[3] = {ch, chNext,
+ static_cast<unsigned char>(substance.ValueAt(position + i + 2))};
+ if (UTF8IsSeparator(next3) || UTF8IsNEL(next3)) {
+ RemoveLine(lineRemove);
+ }
+ }
}
ch = chNext;