diff options
author | nyamatongwe <devnull@localhost> | 2013-01-19 11:40:47 +1100 |
---|---|---|
committer | nyamatongwe <devnull@localhost> | 2013-01-19 11:40:47 +1100 |
commit | d6ac5bf56d40512ac0634d7a5bee6f7328b7d41f (patch) | |
tree | c8a0a61379695115cde7c7423ce4308f4c195336 /src/CellBuffer.cxx | |
parent | 46ff1fe3d148b9d131788be6b4d7da8daa65189c (diff) | |
download | scintilla-mirror-d6ac5bf56d40512ac0634d7a5bee6f7328b7d41f.tar.gz |
Support the three Unicode line ends NEL, LS, and PS in CellBuffer, Document,
Editor and the message interface.
Will only be turned on for lexers that support Unicode line ends.
Diffstat (limited to 'src/CellBuffer.cxx')
-rw-r--r-- | src/CellBuffer.cxx | 115 |
1 files changed, 108 insertions, 7 deletions
diff --git a/src/CellBuffer.cxx b/src/CellBuffer.cxx index 11b8b4acd..7bb96ca76 100644 --- a/src/CellBuffer.cxx +++ b/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,64 @@ 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; + unsigned char ch = ' '; + for (int i = 0; i < length; i++) { + 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 +575,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 +599,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 +615,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 +648,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 +658,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 +677,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; |