aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--cocoa/ScintillaCocoa.h2
-rw-r--r--cocoa/ScintillaCocoa.mm44
-rw-r--r--gtk/ScintillaGTK.cxx42
-rw-r--r--gtk/makefile2
-rw-r--r--qt/ScintillaEdit/ScintillaDocument.cpp1
-rw-r--r--qt/ScintillaEdit/ScintillaEdit.pro2
-rw-r--r--qt/ScintillaEditBase/ScintillaEditBase.pro5
-rw-r--r--qt/ScintillaEditBase/ScintillaQt.cpp45
-rw-r--r--qt/ScintillaEditBase/ScintillaQt.h2
-rw-r--r--scripts/GenerateCaseConvert.py122
-rw-r--r--src/CaseConvert.cxx620
-rw-r--r--src/CaseConvert.h47
-rw-r--r--src/CaseFolder.cxx68
-rw-r--r--src/CaseFolder.h45
-rw-r--r--src/Document.cxx42
-rw-r--r--src/Document.h18
-rw-r--r--src/Editor.cxx1
-rw-r--r--src/PositionCache.cxx1
-rw-r--r--src/ScintillaBase.cxx1
-rw-r--r--src/UnicodeFromUTF8.h19
-rw-r--r--test/simpleTests.py70
-rw-r--r--win32/ScintillaWin.cxx193
-rw-r--r--win32/makefile10
-rw-r--r--win32/scintilla.mak25
24 files changed, 1093 insertions, 334 deletions
diff --git a/cocoa/ScintillaCocoa.h b/cocoa/ScintillaCocoa.h
index b609f2343..9b2c9fa1e 100644
--- a/cocoa/ScintillaCocoa.h
+++ b/cocoa/ScintillaCocoa.h
@@ -44,12 +44,14 @@
#include "ViewStyle.h"
#include "CharClassify.h"
#include "Decoration.h"
+#include "CaseFolder.h"
#include "Document.h"
#include "Selection.h"
#include "PositionCache.h"
#include "Editor.h"
#include "ScintillaBase.h"
+#include "CaseConvert.h"
extern "C" NSString* ScintillaRecPboardType;
diff --git a/cocoa/ScintillaCocoa.mm b/cocoa/ScintillaCocoa.mm
index 3e5c46f00..3845bd5d0 100644
--- a/cocoa/ScintillaCocoa.mm
+++ b/cocoa/ScintillaCocoa.mm
@@ -522,37 +522,6 @@ static char *EncodedBytes(CFStringRef cfsRef, CFStringEncoding encoding) {
* Case folders.
*/
-class CaseFolderUTF8 : public CaseFolderTable {
-public:
- CaseFolderUTF8() {
- StandardASCII();
- }
- virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
- if ((lenMixed == 1) && (sizeFolded > 0)) {
- folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
- return 1;
- } else {
- CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault,
- reinterpret_cast<const UInt8 *>(mixed),
- lenMixed, kCFStringEncodingUTF8, false);
-
- NSString *sMapped = [(NSString *)cfsVal stringByFoldingWithOptions:NSCaseInsensitiveSearch
- locale:[NSLocale currentLocale]];
-
- const char *cpMapped = [sMapped UTF8String];
- size_t lenMapped = cpMapped ? strlen(cpMapped) : 0;
- if (lenMapped < sizeFolded) {
- memcpy(folded, cpMapped, lenMapped);
- } else {
- lenMapped = 0;
- }
- if (cfsVal)
- CFRelease(cfsVal);
- return lenMapped;
- }
- }
-};
-
class CaseFolderDBCS : public CaseFolderTable {
CFStringEncoding encoding;
public:
@@ -592,7 +561,7 @@ public:
CaseFolder *ScintillaCocoa::CaseFolderForEncoding() {
if (pdoc->dbcsCodePage == SC_CP_UTF8) {
- return new CaseFolderUTF8();
+ return new CaseFolderUnicode();
} else {
CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(),
vs.styles[STYLE_DEFAULT].characterSet);
@@ -637,6 +606,17 @@ CaseFolder *ScintillaCocoa::CaseFolderForEncoding() {
*/
std::string ScintillaCocoa::CaseMapString(const std::string &s, int caseMapping)
{
+ if ((s.size() == 0) || (caseMapping == cmSame))
+ return s;
+
+ if (IsUnicodeMode()) {
+ std::string retMapped(s.length() * maxExpansionCaseConversion, 0);
+ size_t lenMapped = CaseConvertString(&retMapped[0], retMapped.length(), s.c_str(), s.length(),
+ (caseMapping == cmUpper) ? CaseConversionUpper : CaseConversionLower);
+ retMapped.resize(lenMapped);
+ return retMapped;
+ }
+
CFStringEncoding encoding = EncodingFromCharacterSet(IsUnicodeMode(),
vs.styles[STYLE_DEFAULT].characterSet);
CFStringRef cfsVal = CFStringCreateWithBytes(kCFAllocatorDefault,
diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx
index 5f596e84c..82ca0b34e 100644
--- a/gtk/ScintillaGTK.cxx
+++ b/gtk/ScintillaGTK.cxx
@@ -46,12 +46,14 @@
#include "ViewStyle.h"
#include "Decoration.h"
#include "CharClassify.h"
+#include "CaseFolder.h"
#include "Document.h"
#include "Selection.h"
#include "PositionCache.h"
#include "Editor.h"
#include "ScintillaBase.h"
#include "UniConversion.h"
+#include "CaseConvert.h"
#include "scintilla-marshal.h"
@@ -1238,29 +1240,6 @@ const char *ScintillaGTK::CharacterSetID() const {
return ::CharacterSetID(vs.styles[STYLE_DEFAULT].characterSet);
}
-class CaseFolderUTF8 : public CaseFolderTable {
-public:
- CaseFolderUTF8() {
- StandardASCII();
- }
- virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
- if ((lenMixed == 1) && (sizeFolded > 0)) {
- folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
- return 1;
- } else {
- gchar *mapped = g_utf8_casefold(mixed, lenMixed);
- size_t lenMapped = strlen(mapped);
- if (lenMapped < sizeFolded) {
- memcpy(folded, mapped, lenMapped);
- } else {
- lenMapped = 0;
- }
- g_free(mapped);
- return lenMapped;
- }
- }
-};
-
class CaseFolderDBCS : public CaseFolderTable {
const char *charSet;
public:
@@ -1295,7 +1274,7 @@ public:
CaseFolder *ScintillaGTK::CaseFolderForEncoding() {
if (pdoc->dbcsCodePage == SC_CP_UTF8) {
- return new CaseFolderUTF8();
+ return new CaseFolderUnicode();
} else {
const char *charSetBuffer = CharacterSetID();
if (charSetBuffer) {
@@ -1349,15 +1328,20 @@ struct CaseMapper {
}
std::string ScintillaGTK::CaseMapString(const std::string &s, int caseMapping) {
- if (s.size() == 0)
- return std::string();
-
- if (caseMapping == cmSame)
+ if ((s.size() == 0) || (caseMapping == cmSame))
return s;
+ if (IsUnicodeMode()) {
+ std::string retMapped(s.length() * maxExpansionCaseConversion, 0);
+ size_t lenMapped = CaseConvertString(&retMapped[0], retMapped.length(), s.c_str(), s.length(),
+ (caseMapping == cmUpper) ? CaseConversionUpper : CaseConversionLower);
+ retMapped.resize(lenMapped);
+ return retMapped;
+ }
+
const char *charSetBuffer = CharacterSetID();
- if (IsUnicodeMode() || !*charSetBuffer) {
+ if (!*charSetBuffer) {
CaseMapper mapper(s, caseMapping == cmUpper);
return std::string(mapper.mapped, strlen(mapper.mapped));
} else {
diff --git a/gtk/makefile b/gtk/makefile
index 4a2ffd3c2..5bcea9af8 100644
--- a/gtk/makefile
+++ b/gtk/makefile
@@ -88,7 +88,7 @@ deps:
$(CC) -MM $(CONFIGFLAGS) $(CXXTFLAGS) *.cxx ../src/*.cxx | sed -e 's/\/usr.* //' | grep [a-zA-Z] >deps.mak
$(COMPLIB): Accessor.o CharacterSet.o LexerBase.o LexerModule.o LexerSimple.o StyleContext.o WordList.o \
- CharClassify.o Decoration.o Document.o PerLine.o Catalogue.o CallTip.o \
+ CharClassify.o Decoration.o Document.o PerLine.o Catalogue.o CallTip.o CaseConvert.o CaseFolder.o \
ScintillaBase.o ContractionState.o Editor.o ExternalLexer.o PropSetSimple.o PlatGTK.o \
KeyMap.o LineMarker.o PositionCache.o ScintillaGTK.o CellBuffer.o CharacterCategory.o ViewStyle.o \
RESearch.o RunStyles.o Selection.o Style.o Indicator.o AutoComplete.o UniConversion.o XPM.o \
diff --git a/qt/ScintillaEdit/ScintillaDocument.cpp b/qt/ScintillaEdit/ScintillaDocument.cpp
index 801f6a385..6240a7699 100644
--- a/qt/ScintillaEdit/ScintillaDocument.cpp
+++ b/qt/ScintillaEdit/ScintillaDocument.cpp
@@ -25,6 +25,7 @@
#include "ViewStyle.h"
#include "CharClassify.h"
#include "Decoration.h"
+#include "CaseFolder.h"
#include "Document.h"
class WatcherHelper : public DocWatcher {
diff --git a/qt/ScintillaEdit/ScintillaEdit.pro b/qt/ScintillaEdit/ScintillaEdit.pro
index 8c8dda39e..65aa9b2ae 100644
--- a/qt/ScintillaEdit/ScintillaEdit.pro
+++ b/qt/ScintillaEdit/ScintillaEdit.pro
@@ -40,6 +40,8 @@ SOURCES += \
../../src/CharClassify.cxx \
../../src/CellBuffer.cxx \
../../src/Catalogue.cxx \
+ ../../src/CaseFolder.cxx \
+ ../../src/CaseConvert.cxx \
../../src/CallTip.cxx \
../../src/AutoComplete.cxx \
../../lexlib/WordList.cxx \
diff --git a/qt/ScintillaEditBase/ScintillaEditBase.pro b/qt/ScintillaEditBase/ScintillaEditBase.pro
index 9aa5cd41a..df5e4adbc 100644
--- a/qt/ScintillaEditBase/ScintillaEditBase.pro
+++ b/qt/ScintillaEditBase/ScintillaEditBase.pro
@@ -38,6 +38,8 @@ SOURCES += \
../../src/CharClassify.cxx \
../../src/CellBuffer.cxx \
../../src/Catalogue.cxx \
+ ../../src/CaseFolder.cxx \
+ ../../src/CaseConvert.cxx \
../../src/CallTip.cxx \
../../src/AutoComplete.cxx \
../../lexlib/WordList.cxx \
@@ -59,6 +61,7 @@ HEADERS += \
../../src/XPM.h \
../../src/ViewStyle.h \
../../src/UniConversion.h \
+ ../../src/UnicodeFromUTF8.h \
../../src/Style.h \
../../src/SplitVector.h \
../../src/Selection.h \
@@ -80,6 +83,8 @@ HEADERS += \
../../src/CharClassify.h \
../../src/CellBuffer.h \
../../src/Catalogue.h \
+ ../../src/CaseFolder.h \
+ ../../src/CaseConvert.h \
../../src/CallTip.h \
../../src/AutoComplete.h \
../../include/Scintilla.h \
diff --git a/qt/ScintillaEditBase/ScintillaQt.cpp b/qt/ScintillaEditBase/ScintillaQt.cpp
index 4d0d62082..a956ff714 100644
--- a/qt/ScintillaEditBase/ScintillaQt.cpp
+++ b/qt/ScintillaEditBase/ScintillaQt.cpp
@@ -488,30 +488,6 @@ QByteArray ScintillaQt::BytesForDocument(const QString &text) const
}
-class CaseFolderUTF8 : public CaseFolderTable {
-public:
- CaseFolderUTF8() {
- StandardASCII();
- }
- virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
- if ((lenMixed == 1) && (sizeFolded > 0)) {
- folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
- return 1;
- } else {
- QString su = QString::fromUtf8(mixed, lenMixed);
- QString suFolded = su.toCaseFolded();
- QByteArray bytesFolded = suFolded.toUtf8();
- if (bytesFolded.length() < static_cast<int>(sizeFolded)) {
- memcpy(folded, bytesFolded, bytesFolded.length());
- return bytesFolded.length();
- } else {
- folded[0] = '\0';
- return 0;
- }
- }
- }
-};
-
class CaseFolderDBCS : public CaseFolderTable {
QTextCodec *codec;
public:
@@ -541,7 +517,7 @@ public:
CaseFolder *ScintillaQt::CaseFolderForEncoding()
{
if (pdoc->dbcsCodePage == SC_CP_UTF8) {
- return new CaseFolderUTF8();
+ return new CaseFolderUnicode();
} else {
const char *charSetBuffer = CharacterSetIDOfDocument();
if (charSetBuffer) {
@@ -571,21 +547,20 @@ CaseFolder *ScintillaQt::CaseFolderForEncoding()
std::string ScintillaQt::CaseMapString(const std::string &s, int caseMapping)
{
- if (s.size() == 0)
- return std::string();
-
- if (caseMapping == cmSame)
+ if ((s.size() == 0) || (caseMapping == cmSame))
return s;
- QTextCodec *codec = 0;
- QString text;
if (IsUnicodeMode()) {
- text = QString::fromUtf8(s.c_str(), s.length());
- } else {
- codec = QTextCodec::codecForName(CharacterSetIDOfDocument());
- text = codec->toUnicode(s.c_str(), s.length());
+ std::string retMapped(s.length() * maxExpansionCaseConversion, 0);
+ size_t lenMapped = CaseConvertString(&retMapped[0], retMapped.length(), s.c_str(), s.length(),
+ (caseMapping == cmUpper) ? CaseConversionUpper : CaseConversionLower);
+ retMapped.resize(lenMapped);
+ return retMapped;
}
+ QTextCodec *codec = QTextCodec::codecForName(CharacterSetIDOfDocument());
+ QString text = codec->toUnicode(s.c_str(), s.length());
+
if (caseMapping == cmUpper) {
text = text.toUpper();
} else {
diff --git a/qt/ScintillaEditBase/ScintillaQt.h b/qt/ScintillaEditBase/ScintillaQt.h
index f7f7fe3ee..d3c5be594 100644
--- a/qt/ScintillaEditBase/ScintillaQt.h
+++ b/qt/ScintillaEditBase/ScintillaQt.h
@@ -39,11 +39,13 @@
#include "ViewStyle.h"
#include "CharClassify.h"
#include "Decoration.h"
+#include "CaseFolder.h"
#include "Document.h"
#include "Selection.h"
#include "PositionCache.h"
#include "Editor.h"
#include "ScintillaBase.h"
+#include "CaseConvert.h"
#ifdef SCI_LEXER
#include "SciLexer.h"
diff --git a/scripts/GenerateCaseConvert.py b/scripts/GenerateCaseConvert.py
new file mode 100644
index 000000000..841cdcc51
--- /dev/null
+++ b/scripts/GenerateCaseConvert.py
@@ -0,0 +1,122 @@
+# Script to generate CaseConvert.cxx from Python's Unicode data
+# Should be run rarely when a Python with a new version of Unicode data is available.
+# Should not be run with old versions of Python.
+
+# Current best approach divides case conversions into two cases:
+# simple symmetric and complex.
+# Simple symmetric is where a lower and upper case pair convert to each
+# other and the folded form is the same as the lower case.
+# There are 1006 symmetric pairs.
+# These are further divided into ranges (stored as lower, upper, range length,
+# range pitch and singletons (stored as lower, upper).
+# Complex is for cases that don't fit the above: where there are multiple
+# characters in one of the forms or fold is different to lower or
+# lower(upper(x)) or upper(lower(x)) are not x. These are represented as UTF-8
+# strings with original, folded, upper, and lower separated by '|'.
+# There are 126 complex cases.
+
+import codecs, itertools, os, string, sys, unicodedata
+
+from FileGenerator import Regenerate
+
+def contiguousRanges(l, diff):
+ # l is s list of lists
+ # group into lists where first element of each element differs by diff
+ out = [[l[0]]]
+ for s in l[1:]:
+ if s[0] != out[-1][-1][0] + diff:
+ out.append([])
+ out[-1].append(s)
+ return out
+
+def flatten(listOfLists):
+ "Flatten one level of nesting"
+ return itertools.chain.from_iterable(listOfLists)
+
+def conversionSets():
+ # For all Unicode characters, see whether they have case conversions
+ # Return 2 sets: one of simple symmetric conversion cases and another
+ # with complex cases.
+ complexes = []
+ symmetrics = []
+ for ch in range(sys.maxunicode):
+ if ch >= 0xd800 and ch <= 0xDBFF:
+ continue
+ if ch >= 0xdc00 and ch <= 0xDFFF:
+ continue
+ uch = chr(ch)
+
+ fold = uch.casefold()
+ upper = uch.upper()
+ lower = uch.lower()
+ symmetric = False
+ if uch != upper and len(upper) == 1 and uch == lower and uch == fold:
+ lowerUpper = upper.lower()
+ foldUpper = upper.casefold()
+ if lowerUpper == foldUpper and lowerUpper == uch:
+ symmetric = True
+ symmetrics.append((ch, ord(upper), ch - ord(upper)))
+ if uch != lower and len(lower) == 1 and uch == upper and lower == fold:
+ upperLower = lower.upper()
+ if upperLower == uch:
+ symmetric = True
+
+ if fold == uch:
+ fold = ""
+ if upper == uch:
+ upper = ""
+ if lower == uch:
+ lower = ""
+
+ if (fold or upper or lower) and not symmetric:
+ complexes.append((uch, fold, upper, lower))
+
+ return symmetrics, complexes
+
+def groupRanges(symmetrics):
+ # Group the symmetrics into groups where possible, returning a list
+ # of ranges and a list of symmetrics that didn't fit into a range
+
+ def distance(s):
+ return s[2]
+
+ groups = []
+ uniquekeys = []
+ for k, g in itertools.groupby(symmetrics, distance):
+ groups.append(list(g)) # Store group iterator as a list
+ uniquekeys.append(k)
+
+ contiguousGroups = flatten([contiguousRanges(g, 1) for g in groups])
+ longGroups = [(x[0][0], x[0][1], len(x), 1) for x in contiguousGroups if len(x) > 4]
+
+ oneDiffs = [s for s in symmetrics if s[2] == 1]
+ contiguousOnes = flatten([contiguousRanges(g, 2) for g in [oneDiffs]])
+ longOneGroups = [(x[0][0], x[0][1], len(x), 2) for x in contiguousOnes if len(x) > 4]
+
+ rangeGroups = sorted(longGroups+longOneGroups, key=lambda s: s[0])
+
+ rangeCoverage = list(flatten([range(r[0], r[0]+r[2]*r[3], r[3]) for r in rangeGroups]))
+
+ nonRanges = [(l, u) for l, u, d in symmetrics if l not in rangeCoverage]
+
+ return rangeGroups, nonRanges
+
+def updateCaseConvert():
+ symmetrics, complexes = conversionSets()
+
+ rangeGroups, nonRanges = groupRanges(symmetrics)
+
+ print(len(rangeGroups), "ranges")
+ rangeLines = ["%d,%d,%d,%d, " % x for x in rangeGroups]
+
+ print(len(nonRanges), "non ranges")
+ nonRangeLines = ["%d,%d, " % x for x in nonRanges]
+
+ print(len(symmetrics), "symmetric")
+
+ complexLines = ['"%s|%s|%s|%s|"' % x for x in complexes]
+ print(len(complexLines), "complex")
+
+ Regenerate("../src/CaseConvert.cxx", "//", rangeLines, nonRangeLines, complexLines)
+
+updateCaseConvert()
diff --git a/src/CaseConvert.cxx b/src/CaseConvert.cxx
new file mode 100644
index 000000000..d9ecc3b68
--- /dev/null
+++ b/src/CaseConvert.cxx
@@ -0,0 +1,620 @@
+// Scintilla source code edit control
+// Encoding: UTF-8
+/** @file CaseConvert.cxx
+ ** Case fold characters and convert them to upper or lower case.
+ ** Tables automatically regenerated by scripts/GenerateCharacterCategory.py
+ ** Should only be rarely regenerated for new versions of Unicode.
+ **/
+// Copyright 2013 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <cstring>
+
+#include <vector>
+#include <algorithm>
+
+#include "CaseConvert.h"
+#include "UniConversion.h"
+#include "UnicodeFromUTF8.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+namespace {
+ // Use an unnamed namespace to protect the declarations from name conflicts
+
+// Unicode code points are ordered by groups and follow patterns.
+// Most characters (pitch==1) are in ranges for a particular alphabet and their
+// upper case forms are a fixed distance away.
+// Another pattern (pitch==2) is where each lower case letter is preceded by
+// the upper case form. These are also grouped into ranges.
+
+int symmetricCaseConversionRanges[] = {
+//lower, upper, range length, range pitch
+//++Autogenerated -- start of section automatically generated
+//**\(\*\n\)
+97,65,26,1,
+224,192,23,1,
+248,216,7,1,
+257,256,24,2,
+314,313,8,2,
+331,330,23,2,
+462,461,8,2,
+479,478,9,2,
+505,504,20,2,
+547,546,9,2,
+583,582,5,2,
+945,913,17,1,
+963,931,9,1,
+985,984,12,2,
+1072,1040,32,1,
+1104,1024,16,1,
+1121,1120,17,2,
+1163,1162,27,2,
+1218,1217,7,2,
+1233,1232,44,2,
+1377,1329,38,1,
+7681,7680,75,2,
+7841,7840,48,2,
+7936,7944,8,1,
+7952,7960,6,1,
+7968,7976,8,1,
+7984,7992,8,1,
+8000,8008,6,1,
+8032,8040,8,1,
+8560,8544,16,1,
+9424,9398,26,1,
+11312,11264,47,1,
+11393,11392,50,2,
+11520,4256,38,1,
+42561,42560,23,2,
+42625,42624,12,2,
+42787,42786,7,2,
+42803,42802,31,2,
+42879,42878,5,2,
+42913,42912,5,2,
+65345,65313,26,1,
+66600,66560,40,1,
+
+//--Autogenerated -- end of section automatically generated
+};
+
+// Code points that are symmetric but don't fit into a range of similar characters
+// are listed here.
+
+int symmetricCaseConversions[] = {
+//lower, upper
+//++Autogenerated -- start of section automatically generated
+//**1 \(\*\n\)
+255,376,
+307,306,
+309,308,
+311,310,
+378,377,
+380,379,
+382,381,
+384,579,
+387,386,
+389,388,
+392,391,
+396,395,
+402,401,
+405,502,
+409,408,
+410,573,
+414,544,
+417,416,
+419,418,
+421,420,
+424,423,
+429,428,
+432,431,
+436,435,
+438,437,
+441,440,
+445,444,
+447,503,
+454,452,
+457,455,
+460,458,
+477,398,
+499,497,
+501,500,
+572,571,
+575,11390,
+576,11391,
+578,577,
+592,11375,
+593,11373,
+594,11376,
+595,385,
+596,390,
+598,393,
+599,394,
+601,399,
+603,400,
+608,403,
+611,404,
+613,42893,
+614,42922,
+616,407,
+617,406,
+619,11362,
+623,412,
+625,11374,
+626,413,
+629,415,
+637,11364,
+640,422,
+643,425,
+648,430,
+649,580,
+650,433,
+651,434,
+652,581,
+658,439,
+881,880,
+883,882,
+887,886,
+891,1021,
+892,1022,
+893,1023,
+940,902,
+941,904,
+942,905,
+943,906,
+972,908,
+973,910,
+974,911,
+983,975,
+1010,1017,
+1016,1015,
+1019,1018,
+1231,1216,
+7545,42877,
+7549,11363,
+8017,8025,
+8019,8027,
+8021,8029,
+8023,8031,
+8048,8122,
+8049,8123,
+8050,8136,
+8051,8137,
+8052,8138,
+8053,8139,
+8054,8154,
+8055,8155,
+8056,8184,
+8057,8185,
+8058,8170,
+8059,8171,
+8060,8186,
+8061,8187,
+8112,8120,
+8113,8121,
+8144,8152,
+8145,8153,
+8160,8168,
+8161,8169,
+8165,8172,
+8526,8498,
+8580,8579,
+11361,11360,
+11365,570,
+11366,574,
+11368,11367,
+11370,11369,
+11372,11371,
+11379,11378,
+11382,11381,
+11500,11499,
+11502,11501,
+11507,11506,
+11559,4295,
+11565,4301,
+42874,42873,
+42876,42875,
+42892,42891,
+42897,42896,
+42899,42898,
+
+//--Autogenerated -- end of section automatically generated
+};
+
+// Characters that have complex case conversions are listed here.
+// This includes cases where more than one character is needed for a conversion,
+// folding is different to lowering, or (as appropriate) upper(lower(x)) != x or
+// lower(upper(x)) != x.
+
+const char *complexCaseConversions =
+// Original | Folded | Upper | Lower |
+//++Autogenerated -- start of section automatically generated
+//**2 \(\*\n\)
+"µ|μ|Μ||"
+"ß|ss|SS||"
+"İ|i̇||i̇|"
+"ı||I||"
+"ʼn|ʼn|ʼN||"
+"ſ|s|S||"
+"Dž|dž|DŽ|dž|"
+"Lj|lj|LJ|lj|"
+"Nj|nj|NJ|nj|"
+"ǰ|ǰ|J̌||"
+"Dz|dz|DZ|dz|"
+"ͅ|ι|Ι||"
+"ΐ|ΐ|Ϊ́||"
+"ΰ|ΰ|Ϋ́||"
+"ς|σ|Σ||"
+"ϐ|β|Β||"
+"ϑ|θ|Θ||"
+"ϕ|φ|Φ||"
+"ϖ|π|Π||"
+"ϰ|κ|Κ||"
+"ϱ|ρ|Ρ||"
+"ϴ|θ||θ|"
+"ϵ|ε|Ε||"
+"և|եւ|ԵՒ||"
+"ẖ|ẖ|H̱||"
+"ẗ|ẗ|T̈||"
+"ẘ|ẘ|W̊||"
+"ẙ|ẙ|Y̊||"
+"ẚ|aʾ|Aʾ||"
+"ẛ|ṡ|Ṡ||"
+"ẞ|ss||ß|"
+"ὐ|ὐ|Υ̓||"
+"ὒ|ὒ|Υ̓̀||"
+"ὔ|ὔ|Υ̓́||"
+"ὖ|ὖ|Υ̓͂||"
+"ᾀ|ἀι|ἈΙ||"
+"ᾁ|ἁι|ἉΙ||"
+"ᾂ|ἂι|ἊΙ||"
+"ᾃ|ἃι|ἋΙ||"
+"ᾄ|ἄι|ἌΙ||"
+"ᾅ|ἅι|ἍΙ||"
+"ᾆ|ἆι|ἎΙ||"
+"ᾇ|ἇι|ἏΙ||"
+"ᾈ|ἀι|ἈΙ|ᾀ|"
+"ᾉ|ἁι|ἉΙ|ᾁ|"
+"ᾊ|ἂι|ἊΙ|ᾂ|"
+"ᾋ|ἃι|ἋΙ|ᾃ|"
+"ᾌ|ἄι|ἌΙ|ᾄ|"
+"ᾍ|ἅι|ἍΙ|ᾅ|"
+"ᾎ|ἆι|ἎΙ|ᾆ|"
+"ᾏ|ἇι|ἏΙ|ᾇ|"
+"ᾐ|ἠι|ἨΙ||"
+"ᾑ|ἡι|ἩΙ||"
+"ᾒ|ἢι|ἪΙ||"
+"ᾓ|ἣι|ἫΙ||"
+"ᾔ|ἤι|ἬΙ||"
+"ᾕ|ἥι|ἭΙ||"
+"ᾖ|ἦι|ἮΙ||"
+"ᾗ|ἧι|ἯΙ||"
+"ᾘ|ἠι|ἨΙ|ᾐ|"
+"ᾙ|ἡι|ἩΙ|ᾑ|"
+"ᾚ|ἢι|ἪΙ|ᾒ|"
+"ᾛ|ἣι|ἫΙ|ᾓ|"
+"ᾜ|ἤι|ἬΙ|ᾔ|"
+"ᾝ|ἥι|ἭΙ|ᾕ|"
+"ᾞ|ἦι|ἮΙ|ᾖ|"
+"ᾟ|ἧι|ἯΙ|ᾗ|"
+"ᾠ|ὠι|ὨΙ||"
+"ᾡ|ὡι|ὩΙ||"
+"ᾢ|ὢι|ὪΙ||"
+"ᾣ|ὣι|ὫΙ||"
+"ᾤ|ὤι|ὬΙ||"
+"ᾥ|ὥι|ὭΙ||"
+"ᾦ|ὦι|ὮΙ||"
+"ᾧ|ὧι|ὯΙ||"
+"ᾨ|ὠι|ὨΙ|ᾠ|"
+"ᾩ|ὡι|ὩΙ|ᾡ|"
+"ᾪ|ὢι|ὪΙ|ᾢ|"
+"ᾫ|ὣι|ὫΙ|ᾣ|"
+"ᾬ|ὤι|ὬΙ|ᾤ|"
+"ᾭ|ὥι|ὭΙ|ᾥ|"
+"ᾮ|ὦι|ὮΙ|ᾦ|"
+"ᾯ|ὧι|ὯΙ|ᾧ|"
+"ᾲ|ὰι|ᾺΙ||"
+"ᾳ|αι|ΑΙ||"
+"ᾴ|άι|ΆΙ||"
+"ᾶ|ᾶ|Α͂||"
+"ᾷ|ᾶι|Α͂Ι||"
+"ᾼ|αι|ΑΙ|ᾳ|"
+"ι|ι|Ι||"
+"ῂ|ὴι|ῊΙ||"
+"ῃ|ηι|ΗΙ||"
+"ῄ|ήι|ΉΙ||"
+"ῆ|ῆ|Η͂||"
+"ῇ|ῆι|Η͂Ι||"
+"ῌ|ηι|ΗΙ|ῃ|"
+"ῒ|ῒ|Ϊ̀||"
+"ΐ|ΐ|Ϊ́||"
+"ῖ|ῖ|Ι͂||"
+"ῗ|ῗ|Ϊ͂||"
+"ῢ|ῢ|Ϋ̀||"
+"ΰ|ΰ|Ϋ́||"
+"ῤ|ῤ|Ρ̓||"
+"ῦ|ῦ|Υ͂||"
+"ῧ|ῧ|Ϋ͂||"
+"ῲ|ὼι|ῺΙ||"
+"ῳ|ωι|ΩΙ||"
+"ῴ|ώι|ΏΙ||"
+"ῶ|ῶ|Ω͂||"
+"ῷ|ῶι|Ω͂Ι||"
+"ῼ|ωι|ΩΙ|ῳ|"
+"Ω|ω||ω|"
+"K|k||k|"
+"Å|å||å|"
+"ff|ff|FF||"
+"fi|fi|FI||"
+"fl|fl|FL||"
+"ffi|ffi|FFI||"
+"ffl|ffl|FFL||"
+"ſt|st|ST||"
+"st|st|ST||"
+"ﬓ|մն|ՄՆ||"
+"ﬔ|մե|ՄԵ||"
+"ﬕ|մի|ՄԻ||"
+"ﬖ|վն|ՎՆ||"
+"ﬗ|մխ|ՄԽ||"
+
+//--Autogenerated -- end of section automatically generated
+;
+
+class CaseConverter : public ICaseConverter {
+ // Maximum length of a case conversion result is 6 bytes in UTF-8
+ enum { maxConversionLength=6 };
+ struct ConversionString {
+ char conversion[maxConversionLength+1];
+ };
+ // Conversions are initially store in a vector of structs but then decomposed into
+ // parallel arrays as that is about 10% faster to search.
+ struct CharacterConversion {
+ int character;
+ ConversionString conversion;
+ CharacterConversion(int character_=0, const char *conversion_="") : character(character_) {
+ strcpy(conversion.conversion, conversion_);
+ }
+ bool operator<(const CharacterConversion &other) const {
+ return character < other.character;
+ }
+ };
+ typedef std::vector<CharacterConversion> CharacterToConversion;
+ CharacterToConversion characterToConversion;
+ // The parallel arrays
+ std::vector<int> characters;
+ std::vector<ConversionString> conversions;
+
+public:
+ CaseConverter() {
+ }
+ bool Initialised() const {
+ return characters.size() > 0;
+ }
+ void Add(int character, const char *conversion) {
+ characterToConversion.push_back(CharacterConversion(character, conversion));
+ }
+ const char *Find(int character) {
+ const std::vector<int>::iterator it = std::lower_bound(characters.begin(), characters.end(), character);
+ if (*it == character)
+ return conversions[it - characters.begin()].conversion;
+ else
+ return 0;
+ }
+ size_t CaseConvertString(char *converted, size_t sizeConverted, const char *mixed, size_t lenMixed) {
+ size_t lenConverted = 0;
+ size_t mixedPos = 0;
+ unsigned char bytes[UTF8MaxBytes + 1];
+ while (mixedPos < lenMixed) {
+ const unsigned char leadByte = static_cast<unsigned char>(mixed[mixedPos]);
+ const char *caseConverted = 0;
+ size_t lenMixedChar = 1;
+ if (UTF8IsAscii(leadByte)) {
+ caseConverted = Find(leadByte);
+ } else {
+ bytes[0] = leadByte;
+ const int widthCharBytes = UTF8BytesOfLead[leadByte];
+ for (int b=1; b<widthCharBytes; b++) {
+ bytes[b] = (mixedPos+b < lenMixed) ? mixed[mixedPos+b] : 0;
+ }
+ int classified = UTF8Classify(bytes, widthCharBytes);
+ if (!(classified & UTF8MaskInvalid)) {
+ // valid UTF-8
+ lenMixedChar = classified & UTF8MaskWidth;
+ int character = UnicodeFromUTF8(bytes);
+ caseConverted = Find(character);
+ }
+ }
+ if (caseConverted) {
+ // Character has a conversion so copy that conversion in
+ while (*caseConverted) {
+ converted[lenConverted++] = *caseConverted++;
+ if (lenConverted >= sizeConverted)
+ return 0;
+ }
+ } else {
+ // Character has no conversion so copy the input to output
+ for (size_t i=0; i<lenMixedChar; i++) {
+ converted[lenConverted++] = mixed[mixedPos+i];
+ if (lenConverted >= sizeConverted)
+ return 0;
+ }
+ }
+ mixedPos += lenMixedChar;
+ }
+ return lenConverted;
+ }
+ void FinishedAdding() {
+ std::sort(characterToConversion.begin(), characterToConversion.end());
+ characters.reserve(characterToConversion.size());
+ conversions.reserve(characterToConversion.size());
+ for (CharacterToConversion::iterator it = characterToConversion.begin(); it != characterToConversion.end(); ++it) {
+ characters.push_back(it->character);
+ conversions.push_back(it->conversion);
+ }
+ // Empty the original calculated data completely
+ CharacterToConversion().swap(characterToConversion);
+ }
+};
+
+CaseConverter caseConvFold;
+CaseConverter caseConvUp;
+CaseConverter caseConvLow;
+
+void UTF8FromUTF32Character(int uch, char *putf) {
+ size_t k = 0;
+ if (uch < 0x80) {
+ putf[k++] = static_cast<char>(uch);
+ } else if (uch < 0x800) {
+ putf[k++] = static_cast<char>(0xC0 | (uch >> 6));
+ putf[k++] = static_cast<char>(0x80 | (uch & 0x3f));
+ } else if (uch < 0x10000) {
+ putf[k++] = static_cast<char>(0xE0 | (uch >> 12));
+ putf[k++] = static_cast<char>(0x80 | ((uch >> 6) & 0x3f));
+ putf[k++] = static_cast<char>(0x80 | (uch & 0x3f));
+ } else {
+ putf[k++] = static_cast<char>(0xF0 | (uch >> 18));
+ putf[k++] = static_cast<char>(0x80 | ((uch >> 12) & 0x3f));
+ putf[k++] = static_cast<char>(0x80 | ((uch >> 6) & 0x3f));
+ putf[k++] = static_cast<char>(0x80 | (uch & 0x3f));
+ }
+ putf[k] = 0;
+}
+
+void AddSymmetric(enum CaseConversion conversion, int lower,int upper) {
+ char lowerUTF8[UTF8MaxBytes+1];
+ UTF8FromUTF32Character(lower, lowerUTF8);
+ char upperUTF8[UTF8MaxBytes+1];
+ UTF8FromUTF32Character(upper, upperUTF8);
+
+ switch (conversion) {
+ case CaseConversionFold:
+ caseConvFold.Add(upper, lowerUTF8);
+ break;
+ case CaseConversionUpper:
+ caseConvUp.Add(lower, upperUTF8);
+ break;
+ case CaseConversionLower:
+ caseConvLow.Add(upper, lowerUTF8);
+ break;
+ }
+}
+
+void SetupConversions(enum CaseConversion conversion) {
+ // First initialize for the symmetric ranges
+ for (size_t i=0; i<sizeof(symmetricCaseConversionRanges)/sizeof(symmetricCaseConversionRanges[0]);) {
+ int lower = symmetricCaseConversionRanges[i++];
+ int upper = symmetricCaseConversionRanges[i++];
+ int length = symmetricCaseConversionRanges[i++];
+ int pitch = symmetricCaseConversionRanges[i++];
+ for (int j=0;j<length*pitch;j+=pitch) {
+ AddSymmetric(conversion, lower+j, upper+j);
+ }
+ }
+ // Add the symmetric singletons
+ for (size_t i=0; i<sizeof(symmetricCaseConversions)/sizeof(symmetricCaseConversions[0]);) {
+ int lower = symmetricCaseConversions[i++];
+ int upper = symmetricCaseConversions[i++];
+ AddSymmetric(conversion, lower, upper);
+ }
+ // Add the complex cases
+ const char *sComplex = complexCaseConversions;
+ while (*sComplex) {
+ // Longest ligature is 3 character so 5 for safety
+ const size_t lenUTF8 = 5*UTF8MaxBytes+1;
+ char originUTF8[lenUTF8];
+ char foldedUTF8[lenUTF8];
+ char lowerUTF8[lenUTF8];
+ char upperUTF8[lenUTF8];
+ size_t i = 0;
+ while (*sComplex && *sComplex != '|') {
+ originUTF8[i++] = *sComplex;
+ sComplex++;
+ }
+ sComplex++;
+ originUTF8[i] = 0;
+ i = 0;
+ while (*sComplex && *sComplex != '|') {
+ foldedUTF8[i++] = *sComplex;
+ sComplex++;
+ }
+ sComplex++;
+ foldedUTF8[i] = 0;
+ i = 0;
+ while (*sComplex && *sComplex != '|') {
+ upperUTF8[i++] = *sComplex;
+ sComplex++;
+ }
+ sComplex++;
+ upperUTF8[i] = 0;
+ i = 0;
+ while (*sComplex && *sComplex != '|') {
+ lowerUTF8[i++] = *sComplex;
+ sComplex++;
+ }
+ sComplex++;
+ lowerUTF8[i] = 0;
+
+ int character = UnicodeFromUTF8(reinterpret_cast<unsigned char *>(originUTF8));
+
+ if (conversion == CaseConversionFold && foldedUTF8[0]) {
+ caseConvFold.Add(character, foldedUTF8);
+ }
+
+ if (conversion == CaseConversionUpper && upperUTF8[0]) {
+ caseConvUp.Add(character, upperUTF8);
+ }
+
+ if (conversion == CaseConversionLower && lowerUTF8[0]) {
+ caseConvLow.Add(character, lowerUTF8);
+ }
+ }
+
+ switch (conversion) {
+ case CaseConversionFold:
+ caseConvFold.FinishedAdding();
+ break;
+ case CaseConversionUpper:
+ caseConvUp.FinishedAdding();
+ break;
+ case CaseConversionLower:
+ caseConvLow.FinishedAdding();
+ break;
+ }
+}
+
+CaseConverter *ConverterForConversion(enum CaseConversion conversion) {
+ switch (conversion) {
+ case CaseConversionFold:
+ return &caseConvFold;
+ case CaseConversionUpper:
+ return &caseConvUp;
+ case CaseConversionLower:
+ return &caseConvLow;
+ }
+ return 0;
+}
+
+}
+
+ICaseConverter *ConverterFor(enum CaseConversion conversion) {
+ CaseConverter *pCaseConv = ConverterForConversion(conversion);
+ if (!pCaseConv->Initialised())
+ SetupConversions(conversion);
+ return pCaseConv;
+}
+
+const char *CaseConvert(int character, enum CaseConversion conversion) {
+ CaseConverter *pCaseConv = ConverterForConversion(conversion);
+ if (!pCaseConv->Initialised())
+ SetupConversions(conversion);
+ return pCaseConv->Find(character);
+}
+
+size_t CaseConvertString(char *converted, size_t sizeConverted, const char *mixed, size_t lenMixed, enum CaseConversion conversion) {
+ CaseConverter *pCaseConv = ConverterForConversion(conversion);
+ if (!pCaseConv->Initialised())
+ SetupConversions(conversion);
+ return pCaseConv->CaseConvertString(converted, sizeConverted, mixed, lenMixed);
+}
diff --git a/src/CaseConvert.h b/src/CaseConvert.h
new file mode 100644
index 000000000..60de22799
--- /dev/null
+++ b/src/CaseConvert.h
@@ -0,0 +1,47 @@
+// Scintilla source code edit control
+// Encoding: UTF-8
+/** @file CaseConvert.h
+ ** Performs Unicode case conversions.
+ ** Does not handle locale-sensitive case conversion.
+ **/
+// Copyright 2013 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef CASECONVERT_H
+#define CASECONVERT_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+enum CaseConversion {
+ CaseConversionFold,
+ CaseConversionUpper,
+ CaseConversionLower
+};
+
+class ICaseConverter {
+public:
+ virtual size_t CaseConvertString(char *converted, size_t sizeConverted, const char *mixed, size_t lenMixed) = 0;
+};
+
+ICaseConverter *ConverterFor(enum CaseConversion conversion);
+
+// Returns a UTF-8 string. Empty when no conversion
+const char *CaseConvert(int character, enum CaseConversion conversion);
+
+// When performing CaseConvertString, the converted value may be up to 3 times longer than the input.
+// Ligatures are often decomposed into multiple characters and long cases include:
+// ΐ "\xce\x90" folds to ΐ "\xce\xb9\xcc\x88\xcc\x81"
+const int maxExpansionCaseConversion=3;
+
+// Converts a mixed case string using a particular conversion.
+// Result may be a different length to input and the length is the return value.
+// If there is not enough space then 0 is returned.
+size_t CaseConvertString(char *converted, size_t sizeConverted, const char *mixed, size_t lenMixed, enum CaseConversion conversion);
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/src/CaseFolder.cxx b/src/CaseFolder.cxx
new file mode 100644
index 000000000..44a94da6f
--- /dev/null
+++ b/src/CaseFolder.cxx
@@ -0,0 +1,68 @@
+// Scintilla source code edit control
+/** @file CaseFolder.cxx
+ ** Classes for case folding.
+ **/
+// Copyright 1998-2013 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <vector>
+#include <algorithm>
+
+#include "CaseConvert.h"
+#include "UniConversion.h"
+#include "CaseFolder.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+CaseFolder::~CaseFolder() {
+}
+
+CaseFolderTable::CaseFolderTable() {
+ for (size_t iChar=0; iChar<sizeof(mapping); iChar++) {
+ mapping[iChar] = static_cast<char>(iChar);
+ }
+}
+
+CaseFolderTable::~CaseFolderTable() {
+}
+
+size_t CaseFolderTable::Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
+ if (lenMixed > sizeFolded) {
+ return 0;
+ } else {
+ for (size_t i=0; i<lenMixed; i++) {
+ folded[i] = mapping[static_cast<unsigned char>(mixed[i])];
+ }
+ return lenMixed;
+ }
+}
+
+void CaseFolderTable::SetTranslation(char ch, char chTranslation) {
+ mapping[static_cast<unsigned char>(ch)] = chTranslation;
+}
+
+void CaseFolderTable::StandardASCII() {
+ for (size_t iChar=0; iChar<sizeof(mapping); iChar++) {
+ if (iChar >= 'A' && iChar <= 'Z') {
+ mapping[iChar] = static_cast<char>(iChar - 'A' + 'a');
+ } else {
+ mapping[iChar] = static_cast<char>(iChar);
+ }
+ }
+}
+
+CaseFolderUnicode::CaseFolderUnicode() {
+ StandardASCII();
+ converter = ConverterFor(CaseConversionFold);
+}
+
+size_t CaseFolderUnicode::Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
+ if ((lenMixed == 1) && (sizeFolded > 0)) {
+ folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
+ return 1;
+ } else {
+ return converter->CaseConvertString(folded, sizeFolded, mixed, lenMixed);
+ }
+}
diff --git a/src/CaseFolder.h b/src/CaseFolder.h
new file mode 100644
index 000000000..2d754d4f3
--- /dev/null
+++ b/src/CaseFolder.h
@@ -0,0 +1,45 @@
+// Scintilla source code edit control
+/** @file CaseFolder.h
+ ** Classes for case folding.
+ **/
+// Copyright 1998-2013 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef CASEFOLDER_H
+#define CASEFOLDER_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+class CaseFolder {
+public:
+ virtual ~CaseFolder();
+ virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) = 0;
+};
+
+class CaseFolderTable : public CaseFolder {
+protected:
+ char mapping[256];
+public:
+ CaseFolderTable();
+ virtual ~CaseFolderTable();
+ virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed);
+ void SetTranslation(char ch, char chTranslation);
+ void StandardASCII();
+};
+
+class ICaseConverter;
+
+class CaseFolderUnicode : public CaseFolderTable {
+ ICaseConverter *converter;
+public:
+ CaseFolderUnicode();
+ virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed);
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/src/Document.cxx b/src/Document.cxx
index a00fc9fc2..0637c8d50 100644
--- a/src/Document.cxx
+++ b/src/Document.cxx
@@ -28,6 +28,7 @@
#include "CharClassify.h"
#include "CharacterSet.h"
#include "Decoration.h"
+#include "CaseFolder.h"
#include "Document.h"
#include "RESearch.h"
#include "UniConversion.h"
@@ -1496,47 +1497,6 @@ bool Document::IsWordAt(int start, int end) const {
return IsWordStartAt(start) && IsWordEndAt(end);
}
-static inline char MakeLowerCase(char ch) {
- if (ch < 'A' || ch > 'Z')
- return ch;
- else
- return static_cast<char>(ch - 'A' + 'a');
-}
-
-CaseFolderTable::CaseFolderTable() {
- for (size_t iChar=0; iChar<sizeof(mapping); iChar++) {
- mapping[iChar] = static_cast<char>(iChar);
- }
-}
-
-CaseFolderTable::~CaseFolderTable() {
-}
-
-size_t CaseFolderTable::Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
- if (lenMixed > sizeFolded) {
- return 0;
- } else {
- for (size_t i=0; i<lenMixed; i++) {
- folded[i] = mapping[static_cast<unsigned char>(mixed[i])];
- }
- return lenMixed;
- }
-}
-
-void CaseFolderTable::SetTranslation(char ch, char chTranslation) {
- mapping[static_cast<unsigned char>(ch)] = chTranslation;
-}
-
-void CaseFolderTable::StandardASCII() {
- for (size_t iChar=0; iChar<sizeof(mapping); iChar++) {
- if (iChar >= 'A' && iChar <= 'Z') {
- mapping[iChar] = static_cast<char>(iChar - 'A' + 'a');
- } else {
- mapping[iChar] = static_cast<char>(iChar);
- }
- }
-}
-
bool Document::MatchesWordOptions(bool word, bool wordStart, int pos, int length) const {
return (!word && !wordStart) ||
(word && IsWordAt(pos, pos + length)) ||
diff --git a/src/Document.h b/src/Document.h
index 5c7e8f8a0..5147875b1 100644
--- a/src/Document.h
+++ b/src/Document.h
@@ -155,24 +155,6 @@ public:
bool isEnabled;
};
-class CaseFolder {
-public:
- virtual ~CaseFolder() {
- }
- virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) = 0;
-};
-
-class CaseFolderTable : public CaseFolder {
-protected:
- char mapping[256];
-public:
- CaseFolderTable();
- virtual ~CaseFolderTable();
- virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed);
- void SetTranslation(char ch, char chTranslation);
- void StandardASCII();
-};
-
class Document;
class LexInterface {
diff --git a/src/Editor.cxx b/src/Editor.cxx
index 16e3e8b56..acb840fdf 100644
--- a/src/Editor.cxx
+++ b/src/Editor.cxx
@@ -36,6 +36,7 @@
#include "ViewStyle.h"
#include "CharClassify.h"
#include "Decoration.h"
+#include "CaseFolder.h"
#include "Document.h"
#include "UniConversion.h"
#include "Selection.h"
diff --git a/src/PositionCache.cxx b/src/PositionCache.cxx
index 31eac8592..742a226b9 100644
--- a/src/PositionCache.cxx
+++ b/src/PositionCache.cxx
@@ -32,6 +32,7 @@
#include "CharClassify.h"
#include "Decoration.h"
#include "ILexer.h"
+#include "CaseFolder.h"
#include "Document.h"
#include "Selection.h"
#include "PositionCache.h"
diff --git a/src/ScintillaBase.cxx b/src/ScintillaBase.cxx
index 5d886f5a5..05768799d 100644
--- a/src/ScintillaBase.cxx
+++ b/src/ScintillaBase.cxx
@@ -42,6 +42,7 @@
#include "AutoComplete.h"
#include "CharClassify.h"
#include "Decoration.h"
+#include "CaseFolder.h"
#include "Document.h"
#include "Selection.h"
#include "PositionCache.h"
diff --git a/src/UnicodeFromUTF8.h b/src/UnicodeFromUTF8.h
new file mode 100644
index 000000000..24517e8a2
--- /dev/null
+++ b/src/UnicodeFromUTF8.h
@@ -0,0 +1,19 @@
+// Scintilla source code edit control
+/** @file UnicodeFromUTF8.h
+ ** Lexer infrastructure.
+ **/
+// Copyright 2013 by Neil Hodgson <neilh@scintilla.org>
+// This file is in the public domain.
+
+inline int UnicodeFromUTF8(const unsigned char *us) {
+ if (us[0] < 0xC2) {
+ return us[0];
+ } else if (us[0] < 0xE0) {
+ return ((us[0] & 0x1F) << 6) + (us[1] & 0x3F);
+ } else if (us[0] < 0xF0) {
+ return ((us[0] & 0xF) << 12) + ((us[1] & 0x3F) << 6) + (us[2] & 0x3F);
+ } else if (us[0] < 0xF5) {
+ return ((us[0] & 0x7) << 18) + ((us[1] & 0x3F) << 12) + ((us[2] & 0x3F) << 6) + (us[3] & 0x3F);
+ }
+ return us[0];
+}
diff --git a/test/simpleTests.py b/test/simpleTests.py
index 4c669f297..ed55a67f9 100644
--- a/test/simpleTests.py
+++ b/test/simpleTests.py
@@ -1414,39 +1414,35 @@ class TestCaseMapping(unittest.TestCase):
self.assertEquals(self.ed.Contents(), r)
def testUTFGrows(self):
- # FIXME: change to using Unicode compliant case conversion on Windows
- if sys.platform != "win32":
- # This crashed at one point in debug builds due to looking past end of shorter string
- self.ed.SetCodePage(65001)
- # ﬖ is a single character ligature taking 3 bytes in UTF8: EF AC 96
- t = 'ﬖﬖ'.encode("UTF-8")
- self.ed.SetContents(t)
- self.assertEquals(self.ed.Length, 6)
- self.ed.SetSel(0,self.ed.Length)
- self.ed.UpperCase()
- # To convert to upper case the ligature is separated into վ and ն then uppercased to Վ and Ն
- # each of which takes 2 bytes in UTF-8: D5 8E D5 86
- r = 'ՎՆՎՆ'.encode("UTF-8")
- self.assertEquals(self.ed.Length, 8)
- self.assertEquals(self.ed.Contents(), r)
- self.assertEquals(self.ed.SelectionEnd, self.ed.Length)
+ # This crashed at one point in debug builds due to looking past end of shorter string
+ self.ed.SetCodePage(65001)
+ # ﬖ is a single character ligature taking 3 bytes in UTF8: EF AC 96
+ t = 'ﬖﬖ'.encode("UTF-8")
+ self.ed.SetContents(t)
+ self.assertEquals(self.ed.Length, 6)
+ self.ed.SetSel(0,self.ed.Length)
+ self.ed.UpperCase()
+ # To convert to upper case the ligature is separated into վ and ն then uppercased to Վ and Ն
+ # each of which takes 2 bytes in UTF-8: D5 8E D5 86
+ r = 'ՎՆՎՆ'.encode("UTF-8")
+ self.assertEquals(self.ed.Length, 8)
+ self.assertEquals(self.ed.Contents(), r)
+ self.assertEquals(self.ed.SelectionEnd, self.ed.Length)
def testUTFShrinks(self):
- # FIXME: change to using Unicode compliant case conversion on Windows
- if sys.platform != "win32":
- self.ed.SetCodePage(65001)
- # fi is a single character ligature taking 3 bytes in UTF8: EF AC 81
- t = 'fifi'.encode("UTF-8")
- self.ed.SetContents(t)
- self.assertEquals(self.ed.Length, 6)
- self.ed.SetSel(0,self.ed.Length)
- self.ed.UpperCase()
- # To convert to upper case the ligature is separated into f and i then uppercased to F and I
- # each of which takes 1 byte in UTF-8: 46 49
- r = 'FIFI'.encode("UTF-8")
- self.assertEquals(self.ed.Length, 4)
- self.assertEquals(self.ed.Contents(), r)
- self.assertEquals(self.ed.SelectionEnd, self.ed.Length)
+ self.ed.SetCodePage(65001)
+ # fi is a single character ligature taking 3 bytes in UTF8: EF AC 81
+ t = 'fifi'.encode("UTF-8")
+ self.ed.SetContents(t)
+ self.assertEquals(self.ed.Length, 6)
+ self.ed.SetSel(0,self.ed.Length)
+ self.ed.UpperCase()
+ # To convert to upper case the ligature is separated into f and i then uppercased to F and I
+ # each of which takes 1 byte in UTF-8: 46 49
+ r = 'FIFI'.encode("UTF-8")
+ self.assertEquals(self.ed.Length, 4)
+ self.assertEquals(self.ed.Contents(), r)
+ self.assertEquals(self.ed.SelectionEnd, self.ed.Length)
class TestCaseInsensitiveSearch(unittest.TestCase):
def setUp(self):
@@ -1514,15 +1510,9 @@ class TestCaseInsensitiveSearch(unittest.TestCase):
def testUTFDifferentLength(self):
# Searching for a two byte string finds a single byte
self.ed.SetCodePage(65001)
- # The platforms currently have different folding behaviour (should be fixed)
- if sys.platform == "win32":
- # two byte string "İ" single byte "i"
- text = "Fråndi Ååİ $".encode("UTF-8")
- searchString = "İ".encode("UTF-8")
- else:
- # two byte string "ſ" single byte "s"
- text = "Frånds Ååſ $".encode("UTF-8")
- searchString = "ſ".encode("UTF-8")
+ # two byte string "ſ" single byte "s"
+ text = "Frånds Ååſ $".encode("UTF-8")
+ searchString = "ſ".encode("UTF-8")
firstPosition = len("Frånd".encode("UTF-8"))
self.assertEquals(len(searchString), 2)
self.ed.SetContents(text)
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx
index 8c08d6ea1..cf5750cde 100644
--- a/win32/ScintillaWin.cxx
+++ b/win32/ScintillaWin.cxx
@@ -60,12 +60,15 @@
#include "ViewStyle.h"
#include "CharClassify.h"
#include "Decoration.h"
+#include "CaseFolder.h"
#include "Document.h"
#include "Selection.h"
#include "PositionCache.h"
#include "Editor.h"
#include "ScintillaBase.h"
#include "UniConversion.h"
+#include "CaseConvert.h"
+
#include "PlatWin.h"
#ifdef SCI_LEXER
@@ -1443,55 +1446,6 @@ void ScintillaWin::NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt)
MAKELPARAM(pt.x, pt.y));
}
-class CaseFolderUTF8 : public CaseFolderTable {
- // Allocate the expandable storage here so that it does not need to be reallocated
- // for each call to Fold.
- std::vector<wchar_t> utf16Mixed;
- std::vector<wchar_t> utf16Folded;
-public:
- CaseFolderUTF8() {
- StandardASCII();
- }
- virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
- if ((lenMixed == 1) && (sizeFolded > 0)) {
- folded[0] = mapping[static_cast<unsigned char>(mixed[0])];
- return 1;
- } else {
- if (lenMixed > utf16Mixed.size()) {
- utf16Mixed.resize(lenMixed + 8);
- }
- size_t nUtf16Mixed = ::MultiByteToWideChar(65001, 0, mixed,
- static_cast<int>(lenMixed),
- &utf16Mixed[0],
- static_cast<int>(utf16Mixed.size()));
-
- if (nUtf16Mixed == 0) {
- // Failed to convert -> bad UTF-8
- folded[0] = '\0';
- return 1;
- }
-
- if (nUtf16Mixed * 4 > utf16Folded.size()) { // Maximum folding expansion factor of 4
- utf16Folded.resize(nUtf16Mixed * 4 + 8);
- }
- int lenFlat = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT,
- LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE,
- &utf16Mixed[0],
- static_cast<int>(nUtf16Mixed),
- &utf16Folded[0],
- static_cast<int>(utf16Folded.size()));
-
- size_t lenOut = UTF8Length(&utf16Folded[0], lenFlat);
- if (lenOut < sizeFolded) {
- UTF8FromUTF16(&utf16Folded[0], lenFlat, folded, static_cast<int>(lenOut));
- return lenOut;
- } else {
- return 0;
- }
- }
- }
-};
-
class CaseFolderDBCS : public CaseFolderTable {
// Allocate the expandable storage here so that it does not need to be reallocated
// for each call to Fold.
@@ -1521,15 +1475,23 @@ public:
return 1;
}
- if (nUtf16Mixed * 4 > utf16Folded.size()) { // Maximum folding expansion factor of 4
- utf16Folded.resize(nUtf16Mixed * 4 + 8);
+ unsigned int lenFlat = 0;
+ for (size_t mixIndex=0; mixIndex < nUtf16Mixed; mixIndex++) {
+ if ((lenFlat + 20) > utf16Folded.size())
+ utf16Folded.resize(lenFlat + 60);
+ const char *foldedUTF8 = CaseConvert(utf16Mixed[mixIndex], CaseConversionFold);
+ if (foldedUTF8) {
+ // Maximum length of a case conversion is 6 bytes, 3 characters
+ wchar_t wFolded[20];
+ unsigned int charsConverted = UTF16FromUTF8(foldedUTF8,
+ static_cast<unsigned int>(strlen(foldedUTF8)),
+ wFolded, sizeof(wFolded)/sizeof(wFolded[0]));
+ for (size_t j=0;j<charsConverted;j++)
+ utf16Folded[lenFlat++] = wFolded[j];
+ } else {
+ utf16Folded[lenFlat++] = utf16Mixed[mixIndex];
+ }
}
- int lenFlat = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT,
- LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE,
- &utf16Mixed[0],
- static_cast<int>(nUtf16Mixed),
- &utf16Folded[0],
- static_cast<int>(utf16Folded.size()));
size_t lenOut = ::WideCharToMultiByte(cp, 0,
&utf16Folded[0], lenFlat,
@@ -1550,7 +1512,7 @@ public:
CaseFolder *ScintillaWin::CaseFolderForEncoding() {
UINT cpDest = CodePageOfDocument();
if (cpDest == SC_CP_UTF8) {
- return new CaseFolderUTF8();
+ return new CaseFolderUnicode();
} else {
if (pdoc->dbcsCodePage == 0) {
CaseFolderTable *pcf = new CaseFolderTable();
@@ -1564,16 +1526,21 @@ CaseFolder *ScintillaWin::CaseFolderForEncoding() {
unsigned int lengthUTF16 = ::MultiByteToWideChar(cpDoc, 0, sCharacter, 1,
wCharacter, sizeof(wCharacter)/sizeof(wCharacter[0]));
if (lengthUTF16 == 1) {
- wchar_t wLower[20];
- int charsConverted = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT,
- LCMAP_LINGUISTIC_CASING | LCMAP_LOWERCASE,
- wCharacter, lengthUTF16, wLower, sizeof(wLower)/sizeof(wLower[0]));
- char sCharacterLowered[20];
- unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0,
- wLower, charsConverted,
- sCharacterLowered, sizeof(sCharacterLowered), NULL, 0);
- if ((lengthConverted == 1) && (sCharacter[0] != sCharacterLowered[0])) {
- pcf->SetTranslation(sCharacter[0], sCharacterLowered[0]);
+ const char *caseFolded = CaseConvert(wCharacter[0], CaseConversionFold);
+ if (caseFolded) {
+ wchar_t wLower[20];
+ unsigned int charsConverted = UTF16FromUTF8(caseFolded,
+ static_cast<unsigned int>(strlen(caseFolded)),
+ wLower, sizeof(wLower)/sizeof(wLower[0]));
+ if (charsConverted == 1) {
+ char sCharacterLowered[20];
+ unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0,
+ wLower, charsConverted,
+ sCharacterLowered, sizeof(sCharacterLowered), NULL, 0);
+ if ((lengthConverted == 1) && (sCharacter[0] != sCharacterLowered[0])) {
+ pcf->SetTranslation(sCharacter[0], sCharacterLowered[0]);
+ }
+ }
}
}
}
@@ -1585,13 +1552,17 @@ CaseFolder *ScintillaWin::CaseFolderForEncoding() {
}
std::string ScintillaWin::CaseMapString(const std::string &s, int caseMapping) {
- if (s.size() == 0)
- return std::string();
-
- if (caseMapping == cmSame)
+ if ((s.size() == 0) || (caseMapping == cmSame))
return s;
UINT cpDoc = CodePageOfDocument();
+ if (cpDoc == SC_CP_UTF8) {
+ std::string retMapped(s.length() * maxExpansionCaseConversion, 0);
+ size_t lenMapped = CaseConvertString(&retMapped[0], retMapped.length(), s.c_str(), s.length(),
+ (caseMapping == cmUpper) ? CaseConversionUpper : CaseConversionLower);
+ retMapped.resize(lenMapped);
+ return retMapped;
+ }
unsigned int lengthUTF16 = ::MultiByteToWideChar(cpDoc, 0, s.c_str(),
static_cast<int>(s.size()), NULL, 0);
@@ -1601,63 +1572,27 @@ std::string ScintillaWin::CaseMapString(const std::string &s, int caseMapping) {
DWORD mapFlags = LCMAP_LINGUISTIC_CASING |
((caseMapping == cmUpper) ? LCMAP_UPPERCASE : LCMAP_LOWERCASE);
- // Many conversions performed by search function are short so optimize this case.
- enum { shortSize=20 };
-
- if (s.size() > shortSize) {
- // Use dynamic allocations for long strings
-
- // Change text to UTF-16
- std::vector<wchar_t> vwcText(lengthUTF16);
- ::MultiByteToWideChar(cpDoc, 0, s.c_str(), static_cast<int>(s.size()), &vwcText[0], lengthUTF16);
-
- // Change case
- int charsConverted = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags,
- &vwcText[0], lengthUTF16, NULL, 0);
- std::vector<wchar_t> vwcConverted(charsConverted);
- ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags,
- &vwcText[0], lengthUTF16, &vwcConverted[0], charsConverted);
-
- // Change back to document encoding
- unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0,
- &vwcConverted[0], static_cast<int>(vwcConverted.size()),
- NULL, 0, NULL, 0);
- std::vector<char> vcConverted(lengthConverted);
- ::WideCharToMultiByte(cpDoc, 0,
- &vwcConverted[0], static_cast<int>(vwcConverted.size()),
- &vcConverted[0], static_cast<int>(vcConverted.size()), NULL, 0);
-
- return std::string(&vcConverted[0], vcConverted.size());
-
- } else {
- // Use static allocations for short strings as much faster
- // A factor of 15 for single character strings
-
- // Change text to UTF-16
- wchar_t vwcText[shortSize];
- ::MultiByteToWideChar(cpDoc, 0, s.c_str(), static_cast<int>(s.size()),
- vwcText, lengthUTF16);
-
- // Change case
- int charsConverted = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags,
- vwcText, lengthUTF16, NULL, 0);
- // Full mapping may produce up to 3 characters per input character
- wchar_t vwcConverted[shortSize*3];
- ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags, vwcText, lengthUTF16,
- vwcConverted, charsConverted);
-
- // Change back to document encoding
- unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0,
- vwcConverted, charsConverted,
- NULL, 0, NULL, 0);
- // Each UTF-16 code unit may need up to 3 bytes in UTF-8
- char vcConverted[shortSize * 3 * 3];
- ::WideCharToMultiByte(cpDoc, 0,
- vwcConverted, charsConverted,
- vcConverted, lengthConverted, NULL, 0);
-
- return std::string(vcConverted, lengthConverted);
- }
+ // Change text to UTF-16
+ std::vector<wchar_t> vwcText(lengthUTF16);
+ ::MultiByteToWideChar(cpDoc, 0, s.c_str(), static_cast<int>(s.size()), &vwcText[0], lengthUTF16);
+
+ // Change case
+ int charsConverted = ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags,
+ &vwcText[0], lengthUTF16, NULL, 0);
+ std::vector<wchar_t> vwcConverted(charsConverted);
+ ::LCMapStringW(LOCALE_SYSTEM_DEFAULT, mapFlags,
+ &vwcText[0], lengthUTF16, &vwcConverted[0], charsConverted);
+
+ // Change back to document encoding
+ unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0,
+ &vwcConverted[0], static_cast<int>(vwcConverted.size()),
+ NULL, 0, NULL, 0);
+ std::vector<char> vcConverted(lengthConverted);
+ ::WideCharToMultiByte(cpDoc, 0,
+ &vwcConverted[0], static_cast<int>(vwcConverted.size()),
+ &vcConverted[0], static_cast<int>(vcConverted.size()), NULL, 0);
+
+ return std::string(&vcConverted[0], vcConverted.size());
}
void ScintillaWin::Copy() {
diff --git a/win32/makefile b/win32/makefile
index efcb518cb..c9086969a 100644
--- a/win32/makefile
+++ b/win32/makefile
@@ -48,6 +48,8 @@ LEXOBJS:=$(addsuffix .o,$(basename $(notdir $(wildcard ../lexers/Lex*.cxx))))
BASEOBJS = \
AutoComplete.o \
CallTip.o \
+ CaseConvert.o \
+ CaseFolder.o \
CellBuffer.o \
CharacterCategory.o \
CharacterSet.o \
@@ -111,7 +113,7 @@ ScintillaBaseL.o: ScintillaBase.cxx Platform.h \
CharClassify.h Decoration.h Document.h \
Selection.h PositionCache.h Editor.h \
ScintillaBase.h LexAccessor.h Accessor.h \
- LexerModule.h Catalogue.h
+ LexerModule.h Catalogue.h CaseFolder.h
ScintillaWinL.o: ScintillaWin.cxx Platform.h \
ILexer.h Scintilla.h SplitVector.h \
@@ -122,7 +124,8 @@ ScintillaWinL.o: ScintillaWin.cxx Platform.h \
Document.h Selection.h PositionCache.h \
Editor.h ScintillaBase.h UniConversion.h \
LexAccessor.h Accessor.h \
- LexerModule.h Catalogue.h
+ LexerModule.h Catalogue.h CaseConvert.h \
+ CaseFolder.h
ScintillaWinS.o: ScintillaWin.cxx Platform.h \
ILexer.h Scintilla.h SplitVector.h \
@@ -131,7 +134,8 @@ ScintillaWinS.o: ScintillaWin.cxx Platform.h \
XPM.h LineMarker.h Style.h AutoComplete.h \
ViewStyle.h CharClassify.h Decoration.h \
Document.h Selection.h PositionCache.h \
- Editor.h ScintillaBase.h UniConversion.h
+ Editor.h ScintillaBase.h UniConversion.h \
+ CaseConvert.h CaseFolder.h
ScintillaBaseL.o:
$(CC) $(CXXFLAGS) -D SCI_LEXER -c $< -o $@
diff --git a/win32/scintilla.mak b/win32/scintilla.mak
index 742c2d3c0..13ecd43cc 100644
--- a/win32/scintilla.mak
+++ b/win32/scintilla.mak
@@ -60,6 +60,8 @@ clean:
SOBJS=\
$(DIR_O)\AutoComplete.obj \
$(DIR_O)\CallTip.obj \
+ $(DIR_O)\CaseConvert.obj \
+ $(DIR_O)\CaseFolder.obj \
$(DIR_O)\CellBuffer.obj \
$(DIR_O)\CharacterCategory.obj \
$(DIR_O)\CharacterSet.obj \
@@ -185,6 +187,8 @@ LOBJS=\
$(DIR_O)\Accessor.obj \
$(DIR_O)\AutoComplete.obj \
$(DIR_O)\CallTip.obj \
+ $(DIR_O)\CaseConvert.obj \
+ $(DIR_O)\CaseFolder.obj \
$(DIR_O)\Catalogue.obj \
$(DIR_O)\CellBuffer.obj \
$(DIR_O)\CharacterCategory.obj \
@@ -263,6 +267,10 @@ $(DIR_O)\AutoComplete.obj: ../src/AutoComplete.cxx ../include/Platform.h \
$(DIR_O)\Accessor.obj: ../lexlib/Accessor.cxx ../lexlib/Accessor.h
$(DIR_O)\CallTip.obj: ../src/CallTip.cxx ../include/Platform.h \
../include/Scintilla.h ../src/CallTip.h
+$(DIR_O)\CaseConvert.obj: ../src/CaseConvert.cxx ../src/CaseConvert.h \
+ ../src/UnicodeFromUTF8.h ../src/UniConversion.h
+$(DIR_O)\CaseFolder.obj: ../src/CaseFolder.cxx ../src/CaseFolder.h \
+ ../src/CaseConvert.h ../src/UniConversion.h
$(DIR_O)\CellBuffer.obj: ../src/CellBuffer.cxx ../include/Platform.h \
../include/Scintilla.h ../src/SplitVector.h \
../src/Partitioning.h ../src/CellBuffer.h
@@ -279,13 +287,14 @@ $(DIR_O)\Document.obj: ../src/Document.cxx ../include/Platform.h \
../include/Scintilla.h ../src/SplitVector.h \
../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
../src/CharClassify.h ../src/Decoration.h ../src/Document.h \
- ../src/RESearch.h ../src/PerLine.h
+ ../src/RESearch.h ../src/PerLine.h ../src/CaseFolder.h
$(DIR_O)\Editor.obj: ../src/Editor.cxx ../include/Platform.h ../include/Scintilla.h \
../src/ContractionState.h ../src/SplitVector.h \
../src/Partitioning.h ../src/CellBuffer.h ../src/KeyMap.h \
../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
- ../src/Decoration.h ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/PositionCache.h
+ ../src/Decoration.h ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/PositionCache.h \
+ ../src/CaseFolder.h
$(DIR_O)\ExternalLexer.obj: ../src/ExternalLexer.cxx ../include/Platform.h \
../include/Scintilla.h ../include/SciLexer.h \
../lexlib/Accessor.h ../src/ExternalLexer.h
@@ -495,7 +504,8 @@ $(DIR_O)\PositionCache.obj: ../src/PositionCache.cxx ../include/Platform.h ../in
../src/Partitioning.h ../src/CellBuffer.h ../src/KeyMap.h \
../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
- ../src/Decoration.h ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/PositionCache.h
+ ../src/Decoration.h ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/PositionCache.h \
+ ../src/CaseFolder.h
$(DIR_O)\PropSetSimple.obj: ../lexlib/PropSetSimple.cxx ../include/Platform.h
$(DIR_O)\RESearch.obj: ../src/RESearch.cxx ../src/CharClassify.h ../src/RESearch.h
$(DIR_O)\RunStyles.obj: ../src/RunStyles.cxx ../include/Platform.h \
@@ -508,7 +518,8 @@ $(DIR_O)\ScintillaBase.obj: ../src/ScintillaBase.cxx ../include/Platform.h \
../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \
../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \
../src/AutoComplete.h ../src/CharClassify.h ../src/Decoration.h \
- ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/ScintillaBase.h
+ ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/ScintillaBase.h \
+ ../src/CaseFolder.h
$(DIR_O)\ScintillaBaseL.obj: ../src/ScintillaBase.cxx ../include/Platform.h \
../include/Scintilla.h \
../src/ContractionState.h ../src/SplitVector.h \
@@ -516,7 +527,8 @@ $(DIR_O)\ScintillaBaseL.obj: ../src/ScintillaBase.cxx ../include/Platform.h \
../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \
../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \
../src/AutoComplete.h ../src/CharClassify.h ../src/Decoration.h \
- ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/ScintillaBase.h
+ ../src/Document.h ../src/Editor.h ../src/Selection.h ../src/ScintillaBase.h \
+ ../src/CaseFolder.h
$(DIR_O)\ScintillaWin.obj: ScintillaWin.cxx ../include/Platform.h \
../include/Scintilla.h ../src/ContractionState.h \
../src/SplitVector.h ../src/Partitioning.h \
@@ -524,7 +536,8 @@ $(DIR_O)\ScintillaWin.obj: ScintillaWin.cxx ../include/Platform.h \
../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
../src/AutoComplete.h ../src/ViewStyle.h ../src/CharClassify.h \
../src/Decoration.h ../src/Document.h ../src/Editor.h \
- ../src/ScintillaBase.h ../src/Selection.h ../src/UniConversion.h
+ ../src/ScintillaBase.h ../src/Selection.h ../src/UniConversion.h \
+ ../src/CaseConvert.h ../src/CaseFolder.h
$(DIR_O)\ScintillaWinS.obj: ScintillaWin.cxx ../include/Platform.h \
../include/Scintilla.h ../src/ContractionState.h \
../src/SplitVector.h ../src/Partitioning.h \