summaryrefslogtreecommitdiffstats
path: root/scintilla/src
diff options
context:
space:
mode:
authorXhmikosR <xhmikosr@gmail.com>2014-11-29 09:03:13 +0200
committerXhmikosR <xhmikosr@gmail.com>2014-12-02 08:23:18 +0200
commit2e039e98e11ee39865953a2e187c2f8120e80309 (patch)
treeeadb80c7163cf56614e340ca42861562c050cbb0 /scintilla/src
parent7862c2ee763d360931aacba8d2517d3739f0d98a (diff)
downloadnotepad2-mod-2e039e98e11ee39865953a2e187c2f8120e80309.zip
notepad2-mod-2e039e98e11ee39865953a2e187c2f8120e80309.tar.gz
notepad2-mod-2e039e98e11ee39865953a2e187c2f8120e80309.tar.bz2
Update scintilla to 3.5.2 [a797ff].
Diffstat (limited to 'scintilla/src')
-rw-r--r--scintilla/src/CellBuffer.cxx2
-rw-r--r--scintilla/src/Decoration.cxx4
-rw-r--r--scintilla/src/Document.cxx504
-rw-r--r--scintilla/src/Document.h19
-rw-r--r--scintilla/src/EditModel.cxx1
-rw-r--r--scintilla/src/EditView.cxx45
-rw-r--r--scintilla/src/EditView.h10
-rw-r--r--scintilla/src/Editor.cxx105
-rw-r--r--scintilla/src/Editor.h1
-rw-r--r--scintilla/src/LineMarker.cxx5
-rw-r--r--scintilla/src/LineMarker.h10
-rw-r--r--scintilla/src/MarginView.cxx11
-rw-r--r--scintilla/src/MarginView.h9
-rw-r--r--scintilla/src/PositionCache.cxx1
-rw-r--r--scintilla/src/RESearch.h2
-rw-r--r--scintilla/src/ScintillaBase.cxx1
-rw-r--r--scintilla/src/UniConversion.cxx46
-rw-r--r--scintilla/src/UniConversion.h4
18 files changed, 677 insertions, 103 deletions
diff --git a/scintilla/src/CellBuffer.cxx b/scintilla/src/CellBuffer.cxx
index b765187..f69ab62 100644
--- a/scintilla/src/CellBuffer.cxx
+++ b/scintilla/src/CellBuffer.cxx
@@ -378,7 +378,7 @@ char CellBuffer::CharAt(int position) const {
}
void CellBuffer::GetCharRange(char *buffer, int position, int lengthRetrieve) const {
- if (lengthRetrieve < 0)
+ if (lengthRetrieve <= 0)
return;
if (position < 0)
return;
diff --git a/scintilla/src/Decoration.cxx b/scintilla/src/Decoration.cxx
index dde4223..4ffbcff 100644
--- a/scintilla/src/Decoration.cxx
+++ b/scintilla/src/Decoration.cxx
@@ -163,7 +163,9 @@ int DecorationList::AllOnFor(int position) const {
int mask = 0;
for (Decoration *deco=root; deco; deco = deco->next) {
if (deco->rs.ValueAt(position)) {
- mask |= 1 << deco->indicator;
+ if (deco->indicator < INDIC_IME) {
+ mask |= 1 << deco->indicator;
+ }
}
}
return mask;
diff --git a/scintilla/src/Document.cxx b/scintilla/src/Document.cxx
index 3ffda0c..8bb1b7a 100644
--- a/scintilla/src/Document.cxx
+++ b/scintilla/src/Document.cxx
@@ -11,10 +11,15 @@
#include <assert.h>
#include <ctype.h>
+#include <stdexcept>
#include <string>
#include <vector>
#include <algorithm>
+#ifdef CXX11_REGEX
+#include <regex>
+#endif
+
#include "Platform.h"
#include "ILexer.h"
@@ -335,6 +340,10 @@ int SCI_METHOD Document::LineStart(int line) const {
return cb.LineStart(line);
}
+bool Document::IsLineStartPosition(int position) const {
+ return LineStart(LineFromPosition(position)) == position;
+}
+
int SCI_METHOD Document::LineEnd(int line) const {
if (line >= LinesTotal() - 1) {
return LineStart(line + 1);
@@ -601,7 +610,7 @@ bool Document::InGoodUTF8(int pos, int &start, int &end) const {
// When lines are terminated with \r\n pairs which should be treated as one character.
// When displaying DBCS text such as Japanese.
// If moving, move the position in the indicated direction.
-int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) {
+int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) const {
//Platform::DebugPrintf("NoCRLF %d %d\n", pos, moveDir);
// If out of range, just return minimum/maximum value.
if (pos <= 0)
@@ -1297,7 +1306,7 @@ int Document::GetColumn(int pos) {
return column;
}
-int Document::CountCharacters(int startPos, int endPos) {
+int Document::CountCharacters(int startPos, int endPos) const {
startPos = MovePositionOutsideChar(startPos, 1, false);
endPos = MovePositionOutsideChar(endPos, -1, false);
int count = 0;
@@ -1586,6 +1595,25 @@ void Document::SetCaseFolder(CaseFolder *pcf_) {
pcf = pcf_;
}
+Document::CharacterExtracted Document::ExtractCharacter(int position) const {
+ const unsigned char leadByte = static_cast<unsigned char>(cb.CharAt(position));
+ if (UTF8IsAscii(leadByte)) {
+ // Common case: ASCII character
+ return CharacterExtracted(leadByte, 1);
+ }
+ const int widthCharBytes = UTF8BytesOfLead[leadByte];
+ unsigned char charBytes[UTF8MaxBytes] = { leadByte, 0, 0, 0 };
+ for (int b=1; b<widthCharBytes; b++)
+ charBytes[b] = static_cast<unsigned char>(cb.CharAt(position + b));
+ int utf8status = UTF8Classify(charBytes, widthCharBytes);
+ if (utf8status & UTF8MaskInvalid) {
+ // Treat as invalid and use up just one byte
+ return CharacterExtracted(unicodeReplacementChar, 1);
+ } else {
+ return CharacterExtracted(UnicodeFromBytes(charBytes), utf8status & UTF8MaskWidth);
+ }
+}
+
/**
* Find text in document, supporting both forward and backward
* searches (just pass minPos > maxPos to do a backward search)
@@ -2177,6 +2205,61 @@ private:
std::string substituted;
};
+namespace {
+
+/**
+* RESearchRange keeps track of search range.
+*/
+class RESearchRange {
+public:
+ const Document *doc;
+ int increment;
+ int startPos;
+ int endPos;
+ int lineRangeStart;
+ int lineRangeEnd;
+ int lineRangeBreak;
+ RESearchRange(const Document *doc_, int minPos, int maxPos) : doc(doc_) {
+ increment = (minPos <= maxPos) ? 1 : -1;
+
+ // Range endpoints should not be inside DBCS characters, but just in case, move them.
+ startPos = doc->MovePositionOutsideChar(minPos, 1, false);
+ endPos = doc->MovePositionOutsideChar(maxPos, 1, false);
+
+ lineRangeStart = doc->LineFromPosition(startPos);
+ lineRangeEnd = doc->LineFromPosition(endPos);
+ if ((increment == 1) &&
+ (startPos >= doc->LineEnd(lineRangeStart)) &&
+ (lineRangeStart < lineRangeEnd)) {
+ // the start position is at end of line or between line end characters.
+ lineRangeStart++;
+ startPos = doc->LineStart(lineRangeStart);
+ } else if ((increment == -1) &&
+ (startPos <= doc->LineStart(lineRangeStart)) &&
+ (lineRangeStart > lineRangeEnd)) {
+ // the start position is at beginning of line.
+ lineRangeStart--;
+ startPos = doc->LineEnd(lineRangeStart);
+ }
+ lineRangeBreak = lineRangeEnd + increment;
+ }
+ Range LineRange(int line) const {
+ Range range(doc->LineStart(line), doc->LineEnd(line));
+ if (increment == 1) {
+ if (line == lineRangeStart)
+ range.start = startPos;
+ if (line == lineRangeEnd)
+ range.end = endPos;
+ } else {
+ if (line == lineRangeEnd)
+ range.start = endPos;
+ if (line == lineRangeStart)
+ range.end = startPos;
+ }
+ return range;
+ }
+};
+
// Define a way for the Regular Expression code to access the document
class DocumentIndexer : public CharacterIndexer {
Document *pdoc;
@@ -2197,18 +2280,375 @@ public:
}
};
+#ifdef CXX11_REGEX
+
+class ByteIterator : public std::iterator<std::bidirectional_iterator_tag, char> {
+public:
+ const Document *doc;
+ Position position;
+ ByteIterator(const Document *doc_ = 0, Position position_ = 0) : doc(doc_), position(position_) {
+ }
+ ByteIterator(const ByteIterator &other) {
+ doc = other.doc;
+ position = other.position;
+ }
+ ByteIterator &operator=(const ByteIterator &other) {
+ if (this != &other) {
+ doc = other.doc;
+ position = other.position;
+ }
+ return *this;
+ }
+ char operator*() const {
+ return doc->CharAt(position);
+ }
+ ByteIterator &operator++() {
+ position++;
+ return *this;
+ }
+ ByteIterator operator++(int) {
+ ByteIterator retVal(*this);
+ position++;
+ return retVal;
+ }
+ ByteIterator &operator--() {
+ position--;
+ return *this;
+ }
+ bool operator==(const ByteIterator &other) const {
+ return doc == other.doc && position == other.position;
+ }
+ bool operator!=(const ByteIterator &other) const {
+ return doc != other.doc || position != other.position;
+ }
+ int Pos() const {
+ return position;
+ }
+ int PosRoundUp() const {
+ return position;
+ }
+};
+
+// On Windows, wchar_t is 16 bits wide and on Unix it is 32 bits wide.
+// Would be better to use sizeof(wchar_t) or similar to differentiate
+// but easier for now to hard-code platforms.
+// C++11 has char16_t and char32_t but neither Clang nor Visual C++
+// appear to allow specializing basic_regex over these.
+
+#ifdef _WIN32
+#define WCHAR_T_IS_16 1
+#else
+#define WCHAR_T_IS_16 0
+#endif
+
+#if WCHAR_T_IS_16
+
+// On Windows, report non-BMP characters as 2 separate surrogates as that
+// matches wregex since it is based on wchar_t.
+class UTF8Iterator : public std::iterator<std::bidirectional_iterator_tag, wchar_t> {
+ // These 3 fields determine the iterator position and are used for comparisons
+ const Document *doc;
+ Position position;
+ size_t characterIndex;
+ // Remaining fields are derived from the determining fields so are excluded in comparisons
+ unsigned int lenBytes;
+ size_t lenCharacters;
+ wchar_t buffered[2];
+public:
+ UTF8Iterator(const Document *doc_ = 0, Position position_ = 0) :
+ doc(doc_), position(position_), characterIndex(0), lenBytes(0), lenCharacters(0) {
+ buffered[0] = 0;
+ buffered[1] = 0;
+ }
+ UTF8Iterator(const UTF8Iterator &other) {
+ doc = other.doc;
+ position = other.position;
+ characterIndex = other.characterIndex;
+ lenBytes = other.lenBytes;
+ lenCharacters = other.lenCharacters;
+ buffered[0] = other.buffered[0];
+ buffered[1] = other.buffered[1];
+ }
+ UTF8Iterator &operator=(const UTF8Iterator &other) {
+ if (this != &other) {
+ doc = other.doc;
+ position = other.position;
+ characterIndex = other.characterIndex;
+ lenBytes = other.lenBytes;
+ lenCharacters = other.lenCharacters;
+ buffered[0] = other.buffered[0];
+ buffered[1] = other.buffered[1];
+ }
+ return *this;
+ }
+ wchar_t operator*() {
+ if (lenCharacters == 0) {
+ ReadCharacter();
+ }
+ return buffered[characterIndex];
+ }
+ UTF8Iterator &operator++() {
+ if ((characterIndex + 1) < (lenCharacters)) {
+ characterIndex++;
+ } else {
+ position += lenBytes;
+ ReadCharacter();
+ characterIndex = 0;
+ }
+ return *this;
+ }
+ UTF8Iterator operator++(int) {
+ UTF8Iterator retVal(*this);
+ if ((characterIndex + 1) < (lenCharacters)) {
+ characterIndex++;
+ } else {
+ position += lenBytes;
+ ReadCharacter();
+ characterIndex = 0;
+ }
+ return retVal;
+ }
+ UTF8Iterator &operator--() {
+ if (characterIndex) {
+ characterIndex--;
+ } else {
+ position = doc->NextPosition(position, -1);
+ ReadCharacter();
+ characterIndex = lenCharacters - 1;
+ }
+ return *this;
+ }
+ bool operator==(const UTF8Iterator &other) const {
+ // Only test the determining fields, not the character widths and values derived from this
+ return doc == other.doc &&
+ position == other.position &&
+ characterIndex == other.characterIndex;
+ }
+ bool operator!=(const UTF8Iterator &other) const {
+ // Only test the determining fields, not the character widths and values derived from this
+ return doc != other.doc ||
+ position != other.position ||
+ characterIndex != other.characterIndex;
+ }
+ int Pos() const {
+ return position;
+ }
+ int PosRoundUp() const {
+ if (characterIndex)
+ return position + lenBytes; // Force to end of character
+ else
+ return position;
+ }
+private:
+ void ReadCharacter() {
+ Document::CharacterExtracted charExtracted = doc->ExtractCharacter(position);
+ lenBytes = charExtracted.widthBytes;
+ if (charExtracted.character == unicodeReplacementChar) {
+ lenCharacters = 1;
+ buffered[0] = static_cast<wchar_t>(charExtracted.character);
+ } else {
+ lenCharacters = UTF16FromUTF32Character(charExtracted.character, buffered);
+ }
+ }
+};
+
+#else
+
+// On Unix, report non-BMP characters as single characters
+
+class UTF8Iterator : public std::iterator<std::bidirectional_iterator_tag, wchar_t> {
+ const Document *doc;
+ Position position;
+public:
+ UTF8Iterator(const Document *doc_=0, Position position_=0) : doc(doc_), position(position_) {
+ }
+ UTF8Iterator(const UTF8Iterator &other) {
+ doc = other.doc;
+ position = other.position;
+ }
+ UTF8Iterator &operator=(const UTF8Iterator &other) {
+ if (this != &other) {
+ doc = other.doc;
+ position = other.position;
+ }
+ return *this;
+ }
+ wchar_t operator*() const {
+ Document::CharacterExtracted charExtracted = doc->ExtractCharacter(position);
+ return charExtracted.character;
+ }
+ UTF8Iterator &operator++() {
+ position = doc->NextPosition(position, 1);
+ return *this;
+ }
+ UTF8Iterator operator++(int) {
+ UTF8Iterator retVal(*this);
+ position = doc->NextPosition(position, 1);
+ return retVal;
+ }
+ UTF8Iterator &operator--() {
+ position = doc->NextPosition(position, -1);
+ return *this;
+ }
+ bool operator==(const UTF8Iterator &other) const {
+ return doc == other.doc && position == other.position;
+ }
+ bool operator!=(const UTF8Iterator &other) const {
+ return doc != other.doc || position != other.position;
+ }
+ int Pos() const {
+ return position;
+ }
+ int PosRoundUp() const {
+ return position;
+ }
+};
+
+#endif
+
+std::regex_constants::match_flag_type MatchFlags(const Document *doc, int startPos, int endPos) {
+ std::regex_constants::match_flag_type flagsMatch = std::regex_constants::match_default;
+ if (!doc->IsLineStartPosition(startPos))
+ flagsMatch |= std::regex_constants::match_not_bol;
+ if (!doc->IsLineEndPosition(endPos))
+ flagsMatch |= std::regex_constants::match_not_eol;
+ return flagsMatch;
+}
+
+template<typename Iterator, typename Regex>
+bool MatchOnLines(const Document *doc, const Regex &regexp, const RESearchRange &resr, RESearch &search) {
+ bool matched = false;
+ std::match_results<Iterator> match;
+
+ // MSVC and libc++ have problems with ^ and $ matching line ends inside a range
+ // If they didn't then the line by line iteration could be removed for the forwards
+ // case and replaced with the following 4 lines:
+ // Iterator uiStart(doc, startPos);
+ // Iterator uiEnd(doc, endPos);
+ // flagsMatch = MatchFlags(doc, startPos, endPos);
+ // matched = std::regex_search(uiStart, uiEnd, match, regexp, flagsMatch);
+
+ // Line by line.
+ for (int line = resr.lineRangeStart; line != resr.lineRangeBreak; line += resr.increment) {
+ const Range lineRange = resr.LineRange(line);
+ Iterator itStart(doc, lineRange.start);
+ Iterator itEnd(doc, lineRange.end);
+ std::regex_constants::match_flag_type flagsMatch = MatchFlags(doc, lineRange.start, lineRange.end);
+ matched = std::regex_search(itStart, itEnd, match, regexp, flagsMatch);
+ // Check for the last match on this line.
+ if (matched) {
+ if (resr.increment == -1) {
+ while (matched) {
+ Iterator itNext(doc, match[0].second.PosRoundUp());
+ flagsMatch = MatchFlags(doc, itNext.Pos(), lineRange.end);
+ std::match_results<Iterator> matchNext;
+ matched = std::regex_search(itNext, itEnd, matchNext, regexp, flagsMatch);
+ if (matched) {
+ if (match[0].first == match[0].second) {
+ // Empty match means failure so exit
+ return false;
+ }
+ match = matchNext;
+ }
+ }
+ matched = true;
+ }
+ break;
+ }
+ }
+ if (matched) {
+ for (size_t co = 0; co < match.size(); co++) {
+ search.bopat[co] = match[co].first.Pos();
+ search.eopat[co] = match[co].second.PosRoundUp();
+ size_t lenMatch = search.eopat[co] - search.bopat[co];
+ search.pat[co].resize(lenMatch);
+ for (size_t iPos = 0; iPos < lenMatch; iPos++) {
+ search.pat[co][iPos] = doc->CharAt(iPos + search.bopat[co]);
+ }
+ }
+ }
+ return matched;
+}
+
+long Cxx11RegexFindText(Document *doc, int minPos, int maxPos, const char *s,
+ bool caseSensitive, int *length, RESearch &search) {
+ const RESearchRange resr(doc, minPos, maxPos);
+ try {
+ //ElapsedTime et;
+ std::regex::flag_type flagsRe = std::regex::ECMAScript;
+ // Flags that apper to have no effect:
+ // | std::regex::collate | std::regex::extended;
+ if (!caseSensitive)
+ flagsRe = flagsRe | std::regex::icase;
+
+ // Clear the RESearch so can fill in matches
+ search.Clear();
+
+ bool matched = false;
+ if (SC_CP_UTF8 == doc->dbcsCodePage) {
+ unsigned int lenS = static_cast<unsigned int>(strlen(s));
+ std::vector<wchar_t> ws(lenS + 1);
+#if WCHAR_T_IS_16
+ size_t outLen = UTF16FromUTF8(s, lenS, &ws[0], lenS);
+#else
+ size_t outLen = UTF32FromUTF8(s, lenS, reinterpret_cast<unsigned int *>(&ws[0]), lenS);
+#endif
+ ws[outLen] = 0;
+ std::wregex regexp;
+#if defined(__APPLE__)
+ // Using a UTF-8 locale doesn't change to Unicode over a byte buffer so '.'
+ // is one byte not one character.
+ // However, on OS X this makes wregex act as Unicode
+ std::locale localeU("en_US.UTF-8");
+ regexp.imbue(localeU);
+#endif
+ regexp.assign(&ws[0], flagsRe);
+ matched = MatchOnLines<UTF8Iterator>(doc, regexp, resr, search);
+
+ } else {
+ std::regex regexp;
+ regexp.assign(s, flagsRe);
+ matched = MatchOnLines<ByteIterator>(doc, regexp, resr, search);
+ }
+
+ int posMatch = -1;
+ if (matched) {
+ posMatch = search.bopat[0];
+ *length = search.eopat[0] - search.bopat[0];
+ }
+ // Example - search in doc/ScintillaHistory.html for
+ // [[:upper:]]eta[[:space:]]
+ // On MacBook, normally around 1 second but with locale imbued -> 14 seconds.
+ //double durSearch = et.Duration(true);
+ //Platform::DebugPrintf("Search:%9.6g \n", durSearch);
+ return posMatch;
+ } catch (std::regex_error &) {
+ // Failed to create regular expression
+ throw RegexError();
+ } catch (...) {
+ // Failed in some other way
+ return -1;
+ }
+}
+
+#endif
+
+}
+
long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s,
bool caseSensitive, bool, bool, int flags,
int *length) {
- const bool posix = (flags & SCFIND_POSIX) != 0;
- const int increment = (minPos <= maxPos) ? 1 : -1;
- int startPos = minPos;
- int endPos = maxPos;
+#ifdef CXX11_REGEX
+ if (flags & SCFIND_CXX11REGEX) {
+ return Cxx11RegexFindText(doc, minPos, maxPos, s,
+ caseSensitive, length, search);
+ }
+#endif
- // Range endpoints should not be inside DBCS characters, but just in case, move them.
- startPos = doc->MovePositionOutsideChar(startPos, 1, false);
- endPos = doc->MovePositionOutsideChar(endPos, 1, false);
+ const RESearchRange resr(doc, minPos, maxPos);
+
+ const bool posix = (flags & SCFIND_POSIX) != 0;
const char *errmsg = search.Compile(s, *length, caseSensitive, posix);
if (errmsg) {
@@ -2218,50 +2658,34 @@ long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s
// Replace first '.' with '-' in each property file variable reference:
// Search: \$(\([A-Za-z0-9_-]+\)\.\([A-Za-z0-9_.]+\))
// Replace: $(\1-\2)
- int lineRangeStart = doc->LineFromPosition(startPos);
- const int lineRangeEnd = doc->LineFromPosition(endPos);
- if ((increment == 1) &&
- (startPos >= doc->LineEnd(lineRangeStart)) &&
- (lineRangeStart < lineRangeEnd)) {
- // the start position is at end of line or between line end characters.
- lineRangeStart++;
- startPos = doc->LineStart(lineRangeStart);
- } else if ((increment == -1) &&
- (startPos <= doc->LineStart(lineRangeStart)) &&
- (lineRangeStart > lineRangeEnd)) {
- // the start position is at beginning of line.
- lineRangeStart--;
- startPos = doc->LineEnd(lineRangeStart);
- }
int pos = -1;
int lenRet = 0;
const char searchEnd = s[*length - 1];
const char searchEndPrev = (*length > 1) ? s[*length - 2] : '\0';
- const int lineRangeBreak = lineRangeEnd + increment;
- for (int line = lineRangeStart; line != lineRangeBreak; line += increment) {
+ for (int line = resr.lineRangeStart; line != resr.lineRangeBreak; line += resr.increment) {
int startOfLine = doc->LineStart(line);
int endOfLine = doc->LineEnd(line);
- if (increment == 1) {
- if (line == lineRangeStart) {
- if ((startPos != startOfLine) && (s[0] == '^'))
+ if (resr.increment == 1) {
+ if (line == resr.lineRangeStart) {
+ if ((resr.startPos != startOfLine) && (s[0] == '^'))
continue; // Can't match start of line if start position after start of line
- startOfLine = startPos;
+ startOfLine = resr.startPos;
}
- if (line == lineRangeEnd) {
- if ((endPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\\'))
+ if (line == resr.lineRangeEnd) {
+ if ((resr.endPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\\'))
continue; // Can't match end of line if end position before end of line
- endOfLine = endPos;
+ endOfLine = resr.endPos;
}
} else {
- if (line == lineRangeEnd) {
- if ((endPos != startOfLine) && (s[0] == '^'))
+ if (line == resr.lineRangeEnd) {
+ if ((resr.endPos != startOfLine) && (s[0] == '^'))
continue; // Can't match start of line if end position after start of line
- startOfLine = endPos;
+ startOfLine = resr.endPos;
}
- if (line == lineRangeStart) {
- if ((startPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\\'))
+ if (line == resr.lineRangeStart) {
+ if ((resr.startPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\\'))
continue; // Can't match end of line if start position before end of line
- endOfLine = startPos;
+ endOfLine = resr.startPos;
}
}
@@ -2273,7 +2697,7 @@ long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s
search.eopat[0] = doc->MovePositionOutsideChar(search.eopat[0], 1, false);
lenRet = search.eopat[0] - search.bopat[0];
// There can be only one start of a line, so no need to look for last match in line
- if ((increment == -1) && (s[0] != '^')) {
+ if ((resr.increment == -1) && (s[0] != '^')) {
// Check for the last match on this line.
int repetitions = 1000; // Break out of infinite loop
while (success && (search.eopat[0] <= endOfLine) && (repetitions--)) {
diff --git a/scintilla/src/Document.h b/scintilla/src/Document.h
index 1ad1146..a518c94 100644
--- a/scintilla/src/Document.h
+++ b/scintilla/src/Document.h
@@ -188,6 +188,10 @@ public:
}
};
+struct RegexError : public std::runtime_error {
+ RegexError() : std::runtime_error("regex failure") {}
+};
+
/**
*/
class Document : PerLine, public IDocumentWithLineEnd, public ILoader {
@@ -271,7 +275,7 @@ public:
bool IsCrLf(int pos) const;
int LenChar(int pos);
bool InGoodUTF8(int pos, int &start, int &end) const;
- int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true);
+ int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true) const;
int NextPosition(int pos, int moveDir) const;
bool NextCharacter(int &pos, int moveDir) const; // Returns true if pos changed
int SCI_METHOD GetRelativePosition(int positionStart, int characterOffset) const;
@@ -317,7 +321,7 @@ public:
int SetLineIndentation(int line, int indent);
int GetLineIndentPosition(int line) const;
int GetColumn(int position);
- int CountCharacters(int startPos, int endPos);
+ int CountCharacters(int startPos, int endPos) const;
int FindColumn(int line, int column);
void Indent(bool forwards, int lineBottom, int lineTop);
static std::string TransformLineEnds(const char *s, size_t len, int eolModeWanted);
@@ -345,6 +349,7 @@ public:
void DeleteAllMarks(int markerNum);
int LineFromHandle(int markerHandle);
int SCI_METHOD LineStart(int line) const;
+ bool IsLineStartPosition(int position) const;
int SCI_METHOD LineEnd(int line) const;
int LineEndPosition(int position) const;
bool IsLineEndPosition(int position) const;
@@ -364,6 +369,16 @@ public:
int NextWordEnd(int pos, int delta);
int SCI_METHOD Length() const { return cb.Length(); }
void Allocate(int newSize) { cb.Allocate(newSize); }
+
+ struct CharacterExtracted {
+ unsigned int character;
+ unsigned int widthBytes;
+ CharacterExtracted(unsigned int character_, unsigned int widthBytes_) :
+ character(character_), widthBytes(widthBytes_) {
+ }
+ };
+ CharacterExtracted ExtractCharacter(int position) const;
+
bool MatchesWordOptions(bool word, bool wordStart, int pos, int length) const;
bool HasCaseFolder(void) const;
void SetCaseFolder(CaseFolder *pcf_);
diff --git a/scintilla/src/EditModel.cxx b/scintilla/src/EditModel.cxx
index 8f66da4..fe65a8b 100644
--- a/scintilla/src/EditModel.cxx
+++ b/scintilla/src/EditModel.cxx
@@ -12,6 +12,7 @@
#include <assert.h>
#include <ctype.h>
+#include <stdexcept>
#include <string>
#include <vector>
#include <map>
diff --git a/scintilla/src/EditView.cxx b/scintilla/src/EditView.cxx
index 7d5860e..4976d36 100644
--- a/scintilla/src/EditView.cxx
+++ b/scintilla/src/EditView.cxx
@@ -12,6 +12,7 @@
#include <assert.h>
#include <ctype.h>
+#include <stdexcept>
#include <string>
#include <vector>
#include <map>
@@ -185,6 +186,9 @@ EditView::EditView() {
pixmapIndentGuideHighlight = 0;
llc.SetLevel(LineLayoutCache::llcCaret);
posCache.SetSize(0x400);
+ tabArrowHeight = 4;
+ customDrawTabArrow = NULL;
+ customDrawWrapMarker = NULL;
}
EditView::~EditView() {
@@ -927,7 +931,11 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle
rcPlace.right = rcLine.right;
rcPlace.left = rcPlace.right - vsDraw.aveCharWidth;
}
- DrawWrapMarker(surface, rcPlace, true, vsDraw.WrapColour());
+ if (customDrawWrapMarker == NULL) {
+ DrawWrapMarker(surface, rcPlace, true, vsDraw.WrapColour());
+ } else {
+ customDrawWrapMarker(surface, rcPlace, true, vsDraw.WrapColour());
+ }
}
}
@@ -991,6 +999,10 @@ static void DrawIndicators(Surface *surface, const EditModel &model, const ViewS
}
}
+static bool AnnotationBoxedOrIndented(int annotationVisible) {
+ return annotationVisible == ANNOTATION_BOXED || annotationVisible == ANNOTATION_INDENTED;
+}
+
void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
int line, int xStart, PRectangle rcLine, int subLine, DrawPhase phase) {
int indent = static_cast<int>(model.pdoc->GetLineIndentation(line) * vsDraw.spaceWidth);
@@ -1002,18 +1014,16 @@ void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const Vi
surface->FillRectangle(rcSegment, vsDraw.styles[0].back);
}
rcSegment.left = static_cast<XYPOSITION>(xStart);
- if (model.trackLineWidth || (vsDraw.annotationVisible == ANNOTATION_BOXED)) {
- // Only care about calculating width if tracking or need to draw box
+ if (model.trackLineWidth || AnnotationBoxedOrIndented(vsDraw.annotationVisible)) {
+ // Only care about calculating width if tracking or need to draw indented box
int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation);
- if (vsDraw.annotationVisible == ANNOTATION_BOXED) {
+ if (AnnotationBoxedOrIndented(vsDraw.annotationVisible)) {
widthAnnotation += static_cast<int>(vsDraw.spaceWidth * 2); // Margins
- }
- if (widthAnnotation > lineWidthMaxSeen)
- lineWidthMaxSeen = widthAnnotation;
- if (vsDraw.annotationVisible == ANNOTATION_BOXED) {
rcSegment.left = static_cast<XYPOSITION>(xStart + indent);
rcSegment.right = rcSegment.left + widthAnnotation;
}
+ if (widthAnnotation > lineWidthMaxSeen)
+ lineWidthMaxSeen = widthAnnotation;
}
const int annotationLines = model.pdoc->AnnotationLines(line);
size_t start = 0;
@@ -1025,7 +1035,7 @@ void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const Vi
lineInAnnotation++;
}
PRectangle rcText = rcSegment;
- if ((phase & drawBack) && (vsDraw.annotationVisible == ANNOTATION_BOXED)) {
+ if ((phase & drawBack) && AnnotationBoxedOrIndented(vsDraw.annotationVisible)) {
surface->FillRectangle(rcText,
vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back);
rcText.left += vsDraw.spaceWidth;
@@ -1201,7 +1211,7 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt
}
static void DrawWrapIndentAndMarker(Surface *surface, const ViewStyle &vsDraw, const LineLayout *ll,
- int xStart, PRectangle rcLine, ColourOptional background) {
+ int xStart, PRectangle rcLine, ColourOptional background, DrawWrapMarkerFn customDrawWrapMarker) {
// default bgnd here..
surface->FillRectangle(rcLine, background.isSet ? background :
vsDraw.styles[STYLE_DEFAULT].back);
@@ -1219,7 +1229,11 @@ static void DrawWrapIndentAndMarker(Surface *surface, const ViewStyle &vsDraw, c
else
rcPlace.right = rcPlace.left + vsDraw.aveCharWidth;
- DrawWrapMarker(surface, rcPlace, false, vsDraw.WrapColour());
+ if (customDrawWrapMarker == NULL) {
+ DrawWrapMarker(surface, rcPlace, false, vsDraw.WrapColour());
+ } else {
+ customDrawWrapMarker(surface, rcPlace, false, vsDraw.WrapColour());
+ }
}
}
@@ -1463,9 +1477,12 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
if (vsDraw.whitespaceColours.fore.isSet)
textFore = vsDraw.whitespaceColours.fore;
surface->PenColour(textFore);
- PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4,
+ PRectangle rcTab(rcSegment.left + 1, rcSegment.top + tabArrowHeight,
rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
- DrawTabArrow(surface, rcTab, static_cast<int>(rcSegment.top + vsDraw.lineHeight / 2));
+ if (customDrawTabArrow == NULL)
+ DrawTabArrow(surface, rcTab, static_cast<int>(rcSegment.top + vsDraw.lineHeight / 2));
+ else
+ customDrawTabArrow(surface, rcTab, static_cast<int>(rcSegment.top + vsDraw.lineHeight / 2));
}
}
} else {
@@ -1632,7 +1649,7 @@ void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyl
if ((ll->wrapIndent != 0) && (subLine > 0)) {
if (phase & drawBack) {
- DrawWrapIndentAndMarker(surface, vsDraw, ll, xStart, rcLine, background);
+ DrawWrapIndentAndMarker(surface, vsDraw, ll, xStart, rcLine, background, customDrawWrapMarker);
}
xStart += static_cast<int>(ll->wrapIndent);
}
diff --git a/scintilla/src/EditView.h b/scintilla/src/EditView.h
index 733612e..70af6b2 100644
--- a/scintilla/src/EditView.h
+++ b/scintilla/src/EditView.h
@@ -42,6 +42,8 @@ void DrawTextNoClipPhase(Surface *surface, PRectangle rc, const Style &style, XY
void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText,
const StyledText &st, size_t start, size_t length, DrawPhase phase);
+typedef void (*DrawTabArrowFn)(Surface *surface, PRectangle rcTab, int ymid);
+
/**
* EditView draws the main text area.
*/
@@ -78,6 +80,14 @@ public:
LineLayoutCache llc;
PositionCache posCache;
+ int tabArrowHeight; // draw arrow heads this many pixels above/below line midpoint
+ /** Some platforms, notably PLAT_CURSES, do not support Scintilla's native
+ * DrawTabArrow function for drawing tab characters. Allow those platforms to
+ * override it instead of creating a new method in the Surface class that
+ * existing platforms must implement as empty. */
+ DrawTabArrowFn customDrawTabArrow;
+ DrawWrapMarkerFn customDrawWrapMarker;
+
EditView();
virtual ~EditView();
diff --git a/scintilla/src/Editor.cxx b/scintilla/src/Editor.cxx
index c2631e7..3a8b2fa 100644
--- a/scintilla/src/Editor.cxx
+++ b/scintilla/src/Editor.cxx
@@ -12,6 +12,7 @@
#include <assert.h>
#include <ctype.h>
+#include <stdexcept>
#include <string>
#include <vector>
#include <map>
@@ -112,6 +113,7 @@ Editor::Editor() {
mouseDownCaptures = true;
lastClickTime = 0;
+ doubleClickCloseThreshold = Point(3, 3);
dwellDelay = SC_TIME_FOREVER;
ticksToDwell = SC_TIME_FOREVER;
dwelling = false;
@@ -1789,12 +1791,15 @@ void Editor::AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS) {
{
UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty() || inOverstrike);
+ // Vector elements point into selection in order to change selection.
std::vector<SelectionRange *> selPtrs;
for (size_t r = 0; r < sel.Count(); r++) {
selPtrs.push_back(&sel.Range(r));
}
+ // Order selections by position in document.
std::sort(selPtrs.begin(), selPtrs.end(), cmpSelPtrs);
+ // Loop in reverse to avoid disturbing positions of selections yet to be processed.
for (std::vector<SelectionRange *>::reverse_iterator rit = selPtrs.rbegin();
rit != selPtrs.rend(); ++rit) {
SelectionRange *currentSel = *rit;
@@ -2105,6 +2110,7 @@ void Editor::Clear() {
ClearSelection();
}
sel.RemoveDuplicates();
+ ShowCaretAtCurrentPosition(); // Avoid blinking
}
void Editor::SelectAll() {
@@ -3654,18 +3660,23 @@ long Editor::FindText(
int lengthFound = istrlen(ft->lpstrText);
if (!pdoc->HasCaseFolder())
pdoc->SetCaseFolder(CaseFolderForEncoding());
- int pos = pdoc->FindText(ft->chrg.cpMin, ft->chrg.cpMax, ft->lpstrText,
- (wParam & SCFIND_MATCHCASE) != 0,
- (wParam & SCFIND_WHOLEWORD) != 0,
- (wParam & SCFIND_WORDSTART) != 0,
- (wParam & SCFIND_REGEXP) != 0,
- static_cast<int>(wParam),
- &lengthFound);
- if (pos != -1) {
- ft->chrgText.cpMin = pos;
- ft->chrgText.cpMax = pos + lengthFound;
+ try {
+ int pos = pdoc->FindText(ft->chrg.cpMin, ft->chrg.cpMax, ft->lpstrText,
+ (wParam & SCFIND_MATCHCASE) != 0,
+ (wParam & SCFIND_WHOLEWORD) != 0,
+ (wParam & SCFIND_WORDSTART) != 0,
+ (wParam & SCFIND_REGEXP) != 0,
+ static_cast<int>(wParam),
+ &lengthFound);
+ if (pos != -1) {
+ ft->chrgText.cpMin = pos;
+ ft->chrgText.cpMax = pos + lengthFound;
+ }
+ return pos;
+ } catch (RegexError &) {
+ errorStatus = SC_STATUS_WARN_REGEX;
+ return -1;
}
- return pos;
}
/**
@@ -3699,22 +3710,27 @@ long Editor::SearchText(
int lengthFound = istrlen(txt);
if (!pdoc->HasCaseFolder())
pdoc->SetCaseFolder(CaseFolderForEncoding());
- if (iMessage == SCI_SEARCHNEXT) {
- pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt,
- (wParam & SCFIND_MATCHCASE) != 0,
- (wParam & SCFIND_WHOLEWORD) != 0,
- (wParam & SCFIND_WORDSTART) != 0,
- (wParam & SCFIND_REGEXP) != 0,
- static_cast<int>(wParam),
- &lengthFound);
- } else {
- pos = pdoc->FindText(searchAnchor, 0, txt,
- (wParam & SCFIND_MATCHCASE) != 0,
- (wParam & SCFIND_WHOLEWORD) != 0,
- (wParam & SCFIND_WORDSTART) != 0,
- (wParam & SCFIND_REGEXP) != 0,
- static_cast<int>(wParam),
- &lengthFound);
+ try {
+ if (iMessage == SCI_SEARCHNEXT) {
+ pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt,
+ (wParam & SCFIND_MATCHCASE) != 0,
+ (wParam & SCFIND_WHOLEWORD) != 0,
+ (wParam & SCFIND_WORDSTART) != 0,
+ (wParam & SCFIND_REGEXP) != 0,
+ static_cast<int>(wParam),
+ &lengthFound);
+ } else {
+ pos = pdoc->FindText(searchAnchor, 0, txt,
+ (wParam & SCFIND_MATCHCASE) != 0,
+ (wParam & SCFIND_WHOLEWORD) != 0,
+ (wParam & SCFIND_WORDSTART) != 0,
+ (wParam & SCFIND_REGEXP) != 0,
+ static_cast<int>(wParam),
+ &lengthFound);
+ }
+ } catch (RegexError &) {
+ errorStatus = SC_STATUS_WARN_REGEX;
+ return -1;
}
if (pos != -1) {
SetSelection(pos, pos + lengthFound);
@@ -3749,18 +3765,23 @@ long Editor::SearchInTarget(const char *text, int length) {
if (!pdoc->HasCaseFolder())
pdoc->SetCaseFolder(CaseFolderForEncoding());
- int pos = pdoc->FindText(targetStart, targetEnd, text,
- (searchFlags & SCFIND_MATCHCASE) != 0,
- (searchFlags & SCFIND_WHOLEWORD) != 0,
- (searchFlags & SCFIND_WORDSTART) != 0,
- (searchFlags & SCFIND_REGEXP) != 0,
- searchFlags,
- &lengthFound);
- if (pos != -1) {
- targetStart = pos;
- targetEnd = pos + lengthFound;
+ try {
+ int pos = pdoc->FindText(targetStart, targetEnd, text,
+ (searchFlags & SCFIND_MATCHCASE) != 0,
+ (searchFlags & SCFIND_WHOLEWORD) != 0,
+ (searchFlags & SCFIND_WORDSTART) != 0,
+ (searchFlags & SCFIND_REGEXP) != 0,
+ searchFlags,
+ &lengthFound);
+ if (pos != -1) {
+ targetStart = pos;
+ targetEnd = pos + lengthFound;
+ }
+ return pos;
+ } catch (RegexError &) {
+ errorStatus = SC_STATUS_WARN_REGEX;
+ return -1;
}
- return pos;
}
void Editor::GoToLine(int lineNo) {
@@ -3773,10 +3794,10 @@ void Editor::GoToLine(int lineNo) {
EnsureCaretVisible();
}
-static bool Close(Point pt1, Point pt2) {
- if (abs(pt1.x - pt2.x) > 3)
+static bool Close(Point pt1, Point pt2, Point threshold) {
+ if (abs(pt1.x - pt2.x) > threshold.x)
return false;
- if (abs(pt1.y - pt2.y) > 3)
+ if (abs(pt1.y - pt2.y) > threshold.y)
return false;
return true;
}
@@ -4132,7 +4153,7 @@ void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifie
if (shift && !inSelMargin) {
SetSelection(newPos);
}
- if (((curTime - lastClickTime) < Platform::DoubleClickTime()) && Close(pt, lastClick)) {
+ if (((curTime - lastClickTime) < Platform::DoubleClickTime()) && Close(pt, lastClick, doubleClickCloseThreshold)) {
//Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime);
SetMouseCapture(true);
if (FineTickerAvailable()) {
diff --git a/scintilla/src/Editor.h b/scintilla/src/Editor.h
index 58e67a0..132204a 100644
--- a/scintilla/src/Editor.h
+++ b/scintilla/src/Editor.h
@@ -203,6 +203,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
Point lastClick;
unsigned int lastClickTime;
+ Point doubleClickCloseThreshold;
int dwellDelay;
int ticksToDwell;
bool dwelling;
diff --git a/scintilla/src/LineMarker.cxx b/scintilla/src/LineMarker.cxx
index e55e95d..f6a0490 100644
--- a/scintilla/src/LineMarker.cxx
+++ b/scintilla/src/LineMarker.cxx
@@ -72,6 +72,11 @@ static void DrawMinus(Surface *surface, int centreX, int centreY, int armSize, C
}
void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, typeOfFold tFold, int marginStyle) const {
+ if (customDraw != NULL) {
+ customDraw(surface, rcWhole, fontForCharacter, tFold, marginStyle, this);
+ return;
+ }
+
ColourDesired colourHead = back;
ColourDesired colourBody = back;
ColourDesired colourTail = back;
diff --git a/scintilla/src/LineMarker.h b/scintilla/src/LineMarker.h
index 3363fc7..da2898a 100644
--- a/scintilla/src/LineMarker.h
+++ b/scintilla/src/LineMarker.h
@@ -12,6 +12,8 @@
namespace Scintilla {
#endif
+typedef void (*DrawLineMarkerFn)(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, int tFold, int marginStyle, const void *lineMarker);
+
/**
*/
class LineMarker {
@@ -25,6 +27,11 @@ public:
int alpha;
XPM *pxpm;
RGBAImage *image;
+ /** Some platforms, notably PLAT_CURSES, do not support Scintilla's native
+ * Draw function for drawing line markers. Allow those platforms to override
+ * it instead of creating a new method(s) in the Surface class that existing
+ * platforms must implement as empty. */
+ DrawLineMarkerFn customDraw;
LineMarker() {
markType = SC_MARK_CIRCLE;
fore = ColourDesired(0,0,0);
@@ -33,6 +40,7 @@ public:
alpha = SC_ALPHA_NOALPHA;
pxpm = NULL;
image = NULL;
+ customDraw = NULL;
}
LineMarker(const LineMarker &) {
// Defined to avoid pxpm being blindly copied, not as a complete copy constructor
@@ -43,6 +51,7 @@ public:
alpha = SC_ALPHA_NOALPHA;
pxpm = NULL;
image = NULL;
+ customDraw = NULL;
}
~LineMarker() {
delete pxpm;
@@ -60,6 +69,7 @@ public:
pxpm = NULL;
delete image;
image = NULL;
+ customDraw = NULL;
}
return *this;
}
diff --git a/scintilla/src/MarginView.cxx b/scintilla/src/MarginView.cxx
index 9297eb4..b7ef485 100644
--- a/scintilla/src/MarginView.cxx
+++ b/scintilla/src/MarginView.cxx
@@ -12,6 +12,7 @@
#include <assert.h>
#include <ctype.h>
+#include <stdexcept>
#include <string>
#include <vector>
#include <map>
@@ -102,6 +103,8 @@ MarginView::MarginView() {
pixmapSelMargin = 0;
pixmapSelPattern = 0;
pixmapSelPatternOffset1 = 0;
+ wrapMarkerPaddingRight = 3;
+ customDrawWrapMarker = NULL;
}
void MarginView::DropGraphics(bool freeObjects) {
@@ -391,9 +394,13 @@ void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRect
rcNumber.top + vs.maxAscent, number, static_cast<int>(strlen(number)), drawAll);
} else if (vs.wrapVisualFlags & SC_WRAPVISUALFLAG_MARGIN) {
PRectangle rcWrapMarker = rcMarker;
- rcWrapMarker.right -= 3;
+ rcWrapMarker.right -= wrapMarkerPaddingRight;
rcWrapMarker.left = rcWrapMarker.right - vs.styles[STYLE_LINENUMBER].aveCharWidth;
- DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore);
+ if (customDrawWrapMarker == NULL) {
+ DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore);
+ } else {
+ customDrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore);
+ }
}
} else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) {
if (firstSubLine) {
diff --git a/scintilla/src/MarginView.h b/scintilla/src/MarginView.h
index 465095f..ff55646 100644
--- a/scintilla/src/MarginView.h
+++ b/scintilla/src/MarginView.h
@@ -14,6 +14,8 @@ namespace Scintilla {
void DrawWrapMarker(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourDesired wrapColour);
+typedef void (*DrawWrapMarkerFn)(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourDesired wrapColour);
+
/**
* MarginView draws the margins.
*/
@@ -25,6 +27,13 @@ public:
// Highlight current folding block
HighlightDelimiter highlightDelimiter;
+ int wrapMarkerPaddingRight; // right-most pixel padding of wrap markers
+ /** Some platforms, notably PLAT_CURSES, do not support Scintilla's native
+ * DrawWrapMarker function for drawing wrap markers. Allow those platforms to
+ * override it instead of creating a new method in the Surface class that
+ * existing platforms must implement as empty. */
+ DrawWrapMarkerFn customDrawWrapMarker;
+
MarginView();
void DropGraphics(bool freeObjects);
diff --git a/scintilla/src/PositionCache.cxx b/scintilla/src/PositionCache.cxx
index 007f57e..7418389 100644
--- a/scintilla/src/PositionCache.cxx
+++ b/scintilla/src/PositionCache.cxx
@@ -10,6 +10,7 @@
#include <stdio.h>
#include <ctype.h>
+#include <stdexcept>
#include <string>
#include <vector>
#include <map>
diff --git a/scintilla/src/RESearch.h b/scintilla/src/RESearch.h
index bfcdf5d..7421178 100644
--- a/scintilla/src/RESearch.h
+++ b/scintilla/src/RESearch.h
@@ -33,6 +33,7 @@ class RESearch {
public:
explicit RESearch(CharClassify *charClassTable);
~RESearch();
+ void Clear();
void GrabMatches(CharacterIndexer &ci);
const char *Compile(const char *pattern, int length, bool caseSensitive, bool posix);
int Execute(CharacterIndexer &ci, int lp, int endp);
@@ -46,7 +47,6 @@ public:
std::string pat[MAXTAG];
private:
- void Clear();
void ChSet(unsigned char c);
void ChSetWithCase(unsigned char c, bool caseSensitive);
int GetBackslashExpression(const char *pattern, int &incr);
diff --git a/scintilla/src/ScintillaBase.cxx b/scintilla/src/ScintillaBase.cxx
index dd286a2..516a559 100644
--- a/scintilla/src/ScintillaBase.cxx
+++ b/scintilla/src/ScintillaBase.cxx
@@ -11,6 +11,7 @@
#include <assert.h>
#include <ctype.h>
+#include <stdexcept>
#include <string>
#include <vector>
#include <map>
diff --git a/scintilla/src/UniConversion.cxx b/scintilla/src/UniConversion.cxx
index 1af5a7d..58651bc 100644
--- a/scintilla/src/UniConversion.cxx
+++ b/scintilla/src/UniConversion.cxx
@@ -20,6 +20,7 @@ namespace Scintilla {
enum { SURROGATE_LEAD_FIRST = 0xD800 };
enum { SURROGATE_TRAIL_FIRST = 0xDC00 };
enum { SURROGATE_TRAIL_LAST = 0xDFFF };
+enum { SUPPLEMENTAL_PLANE_FIRST = 0x10000 };
unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen) {
unsigned int len = 0;
@@ -138,6 +139,51 @@ unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsig
return ui;
}
+unsigned int UTF32FromUTF8(const char *s, unsigned int len, unsigned int *tbuf, unsigned int tlen) {
+ unsigned int ui=0;
+ const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
+ unsigned int i=0;
+ while ((i<len) && (ui<tlen)) {
+ unsigned char ch = us[i++];
+ wchar_t value = 0;
+ if (ch < 0x80) {
+ value = ch;
+ } else if (((len-i) >= 1) && (ch < 0x80 + 0x40 + 0x20)) {
+ value = (ch & 0x1F) << 6;
+ ch = us[i++];
+ value += ch & 0x7F;
+ } else if (((len-i) >= 2) && (ch < 0x80 + 0x40 + 0x20 + 0x10)) {
+ value = (ch & 0xF) << 12;
+ ch = us[i++];
+ value += (ch & 0x7F) << 6;
+ ch = us[i++];
+ value += ch & 0x7F;
+ } else if ((len-i) >= 3) {
+ value = (ch & 0x7) << 18;
+ ch = us[i++];
+ value += (ch & 0x3F) << 12;
+ ch = us[i++];
+ value += (ch & 0x3F) << 6;
+ ch = us[i++];
+ value += ch & 0x3F;
+ }
+ tbuf[ui] = value;
+ ui++;
+ }
+ return ui;
+}
+
+unsigned int UTF16FromUTF32Character(unsigned int val, wchar_t *tbuf) {
+ if (val < SUPPLEMENTAL_PLANE_FIRST) {
+ tbuf[0] = static_cast<wchar_t>(val);
+ return 1;
+ } else {
+ tbuf[0] = static_cast<wchar_t>(((val - SUPPLEMENTAL_PLANE_FIRST) >> 10) + SURROGATE_LEAD_FIRST);
+ tbuf[1] = static_cast<wchar_t>((val & 0x3ff) + SURROGATE_TRAIL_FIRST);
+ return 2;
+ }
+}
+
int UTF8BytesOfLead[256];
static bool initialisedBytesOfLead = false;
diff --git a/scintilla/src/UniConversion.h b/scintilla/src/UniConversion.h
index 573ff28..9b302b1 100644
--- a/scintilla/src/UniConversion.h
+++ b/scintilla/src/UniConversion.h
@@ -14,11 +14,15 @@ namespace Scintilla {
const int UTF8MaxBytes = 4;
+const int unicodeReplacementChar = 0xFFFD;
+
unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen);
void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len);
unsigned int UTF8CharLength(unsigned char ch);
unsigned int UTF16Length(const char *s, unsigned int len);
unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsigned int tlen);
+unsigned int UTF32FromUTF8(const char *s, unsigned int len, unsigned int *tbuf, unsigned int tlen);
+unsigned int UTF16FromUTF32Character(unsigned int val, wchar_t *tbuf);
extern int UTF8BytesOfLead[256];
void UTF8BytesOfLeadInitialise();