mirror of
https://github.com/Obfuscator-Collections/VMProtect.git
synced 2025-12-17 01:48:05 +03:00
first commit
Version 3.x.x
This commit is contained in:
72
third-party/scintilla/Accessor.cxx
vendored
Normal file
72
third-party/scintilla/Accessor.cxx
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file KeyWords.cxx
|
||||
** Colourise for particular languages.
|
||||
**/
|
||||
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "ILexer.h"
|
||||
#include "Scintilla.h"
|
||||
#include "SciLexer.h"
|
||||
|
||||
#include "PropSetSimple.h"
|
||||
#include "WordList.h"
|
||||
#include "LexAccessor.h"
|
||||
#include "Accessor.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
Accessor::Accessor(IDocument *pAccess_, PropSetSimple *pprops_) : LexAccessor(pAccess_), pprops(pprops_) {
|
||||
}
|
||||
|
||||
int Accessor::GetPropertyInt(const char *key, int defaultValue) const {
|
||||
return pprops->GetInt(key, defaultValue);
|
||||
}
|
||||
|
||||
int Accessor::IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader) {
|
||||
int end = Length();
|
||||
int spaceFlags = 0;
|
||||
|
||||
// Determines the indentation level of the current line and also checks for consistent
|
||||
// indentation compared to the previous line.
|
||||
// Indentation is judged consistent when the indentation whitespace of each line lines
|
||||
// the same or the indentation of one line is a prefix of the other.
|
||||
|
||||
int pos = LineStart(line);
|
||||
char ch = (*this)[pos];
|
||||
int indent = 0;
|
||||
bool inPrevPrefix = line > 0;
|
||||
int posPrev = inPrevPrefix ? LineStart(line-1) : 0;
|
||||
while ((ch == ' ' || ch == '\t') && (pos < end)) {
|
||||
if (inPrevPrefix) {
|
||||
char chPrev = (*this)[posPrev++];
|
||||
if (chPrev == ' ' || chPrev == '\t') {
|
||||
if (chPrev != ch)
|
||||
spaceFlags |= wsInconsistent;
|
||||
} else {
|
||||
inPrevPrefix = false;
|
||||
}
|
||||
}
|
||||
if (ch == ' ') {
|
||||
spaceFlags |= wsSpace;
|
||||
indent++;
|
||||
} else { // Tab
|
||||
spaceFlags |= wsTab;
|
||||
if (spaceFlags & wsSpace)
|
||||
spaceFlags |= wsSpaceTab;
|
||||
indent = (indent / 8 + 1) * 8;
|
||||
}
|
||||
ch = (*this)[++pos];
|
||||
}
|
||||
|
||||
*flags = spaceFlags;
|
||||
indent += SC_FOLDLEVELBASE;
|
||||
// if completely empty line or the start of a comment...
|
||||
if ((LineStart(line) == Length()) || (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') ||
|
||||
(pfnIsCommentLeader && (*pfnIsCommentLeader)(*this, pos, end-pos)))
|
||||
return indent | SC_FOLDLEVELWHITEFLAG;
|
||||
else
|
||||
return indent;
|
||||
}
|
||||
35
third-party/scintilla/Accessor.h
vendored
Normal file
35
third-party/scintilla/Accessor.h
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file Accessor.h
|
||||
** Interfaces between Scintilla and lexers.
|
||||
**/
|
||||
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef ACCESSOR_H
|
||||
#define ACCESSOR_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
enum { wsSpace = 1, wsTab = 2, wsSpaceTab = 4, wsInconsistent=8};
|
||||
|
||||
class Accessor;
|
||||
class WordList;
|
||||
class PropSetSimple;
|
||||
|
||||
typedef bool (*PFNIsCommentLeader)(Accessor &styler, int pos, int len);
|
||||
|
||||
class Accessor : public LexAccessor {
|
||||
public:
|
||||
PropSetSimple *pprops;
|
||||
Accessor(IDocument *pAccess_, PropSetSimple *pprops_);
|
||||
int GetPropertyInt(const char *, int defaultValue=0) const;
|
||||
int IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0);
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
283
third-party/scintilla/AutoComplete.cxx
vendored
Normal file
283
third-party/scintilla/AutoComplete.cxx
vendored
Normal file
@@ -0,0 +1,283 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file AutoComplete.cxx
|
||||
** Defines the auto completion list box.
|
||||
**/
|
||||
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "CharacterSet.h"
|
||||
#include "AutoComplete.h"
|
||||
#include "Scintilla.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
AutoComplete::AutoComplete() :
|
||||
active(false),
|
||||
separator(' '),
|
||||
typesep('?'),
|
||||
ignoreCase(false),
|
||||
chooseSingle(false),
|
||||
lb(0),
|
||||
posStart(0),
|
||||
startLen(0),
|
||||
cancelAtStartPos(true),
|
||||
autoHide(true),
|
||||
dropRestOfWord(false),
|
||||
ignoreCaseBehaviour(SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE),
|
||||
widthLBDefault(100),
|
||||
heightLBDefault(100),
|
||||
autoSort(SC_ORDER_PRESORTED) {
|
||||
lb = ListBox::Allocate();
|
||||
}
|
||||
|
||||
AutoComplete::~AutoComplete() {
|
||||
if (lb) {
|
||||
lb->Destroy();
|
||||
delete lb;
|
||||
lb = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool AutoComplete::Active() const {
|
||||
return active;
|
||||
}
|
||||
|
||||
void AutoComplete::Start(Window &parent, int ctrlID,
|
||||
int position, Point location, int startLen_,
|
||||
int lineHeight, bool unicodeMode, int technology) {
|
||||
if (active) {
|
||||
Cancel();
|
||||
}
|
||||
lb->Create(parent, ctrlID, location, lineHeight, unicodeMode, technology);
|
||||
lb->Clear();
|
||||
active = true;
|
||||
startLen = startLen_;
|
||||
posStart = position;
|
||||
}
|
||||
|
||||
void AutoComplete::SetStopChars(const char *stopChars_) {
|
||||
stopChars = stopChars_;
|
||||
}
|
||||
|
||||
bool AutoComplete::IsStopChar(char ch) {
|
||||
return ch && (stopChars.find(ch) != std::string::npos);
|
||||
}
|
||||
|
||||
void AutoComplete::SetFillUpChars(const char *fillUpChars_) {
|
||||
fillUpChars = fillUpChars_;
|
||||
}
|
||||
|
||||
bool AutoComplete::IsFillUpChar(char ch) {
|
||||
return ch && (fillUpChars.find(ch) != std::string::npos);
|
||||
}
|
||||
|
||||
void AutoComplete::SetSeparator(char separator_) {
|
||||
separator = separator_;
|
||||
}
|
||||
|
||||
char AutoComplete::GetSeparator() const {
|
||||
return separator;
|
||||
}
|
||||
|
||||
void AutoComplete::SetTypesep(char separator_) {
|
||||
typesep = separator_;
|
||||
}
|
||||
|
||||
char AutoComplete::GetTypesep() const {
|
||||
return typesep;
|
||||
}
|
||||
|
||||
struct Sorter {
|
||||
AutoComplete *ac;
|
||||
const char *list;
|
||||
std::vector<int> indices;
|
||||
|
||||
Sorter(AutoComplete *ac_, const char *list_) : ac(ac_), list(list_) {
|
||||
int i = 0;
|
||||
while (list[i]) {
|
||||
indices.push_back(i); // word start
|
||||
while (list[i] != ac->GetTypesep() && list[i] != ac->GetSeparator() && list[i])
|
||||
++i;
|
||||
indices.push_back(i); // word end
|
||||
if (list[i] == ac->GetTypesep()) {
|
||||
while (list[i] != ac->GetSeparator() && list[i])
|
||||
++i;
|
||||
}
|
||||
if (list[i] == ac->GetSeparator()) {
|
||||
++i;
|
||||
// preserve trailing separator as blank entry
|
||||
if (!list[i]) {
|
||||
indices.push_back(i);
|
||||
indices.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
indices.push_back(i); // index of last position
|
||||
}
|
||||
|
||||
bool operator()(int a, int b) {
|
||||
int lenA = indices[a * 2 + 1] - indices[a * 2];
|
||||
int lenB = indices[b * 2 + 1] - indices[b * 2];
|
||||
int len = std::min(lenA, lenB);
|
||||
int cmp;
|
||||
if (ac->ignoreCase)
|
||||
cmp = CompareNCaseInsensitive(list + indices[a * 2], list + indices[b * 2], len);
|
||||
else
|
||||
cmp = strncmp(list + indices[a * 2], list + indices[b * 2], len);
|
||||
if (cmp == 0)
|
||||
cmp = lenA - lenB;
|
||||
return cmp < 0;
|
||||
}
|
||||
};
|
||||
|
||||
void AutoComplete::SetList(const char *list) {
|
||||
if (autoSort == SC_ORDER_PRESORTED) {
|
||||
lb->SetList(list, separator, typesep);
|
||||
sortMatrix.clear();
|
||||
for (int i = 0; i < lb->Length(); ++i)
|
||||
sortMatrix.push_back(i);
|
||||
return;
|
||||
}
|
||||
|
||||
Sorter IndexSort(this, list);
|
||||
sortMatrix.clear();
|
||||
for (int i = 0; i < (int)IndexSort.indices.size() / 2; ++i)
|
||||
sortMatrix.push_back(i);
|
||||
std::sort(sortMatrix.begin(), sortMatrix.end(), IndexSort);
|
||||
if (autoSort == SC_ORDER_CUSTOM || sortMatrix.size() < 2) {
|
||||
lb->SetList(list, separator, typesep);
|
||||
PLATFORM_ASSERT(lb->Length() == static_cast<int>(sortMatrix.size()));
|
||||
return;
|
||||
}
|
||||
|
||||
std::string sortedList;
|
||||
char item[maxItemLen];
|
||||
for (size_t i = 0; i < sortMatrix.size(); ++i) {
|
||||
int wordLen = IndexSort.indices[sortMatrix[i] * 2 + 2] - IndexSort.indices[sortMatrix[i] * 2];
|
||||
strncpy(item, list + IndexSort.indices[sortMatrix[i] * 2], wordLen);
|
||||
if ((i+1) == sortMatrix.size()) {
|
||||
// Last item so remove separator if present
|
||||
if ((wordLen > 0) && (item[wordLen-1] == separator))
|
||||
wordLen--;
|
||||
} else {
|
||||
// Item before last needs a separator
|
||||
if ((wordLen == 0) || (item[wordLen-1] != separator)) {
|
||||
item[wordLen] = separator;
|
||||
wordLen++;
|
||||
}
|
||||
}
|
||||
item[wordLen] = '\0';
|
||||
sortedList += item;
|
||||
}
|
||||
for (int i = 0; i < (int)sortMatrix.size(); ++i)
|
||||
sortMatrix[i] = i;
|
||||
lb->SetList(sortedList.c_str(), separator, typesep);
|
||||
}
|
||||
|
||||
int AutoComplete::GetSelection() const {
|
||||
return lb->GetSelection();
|
||||
}
|
||||
|
||||
std::string AutoComplete::GetValue(int item) const {
|
||||
char value[maxItemLen];
|
||||
lb->GetValue(item, value, sizeof(value));
|
||||
return std::string(value);
|
||||
}
|
||||
|
||||
void AutoComplete::Show(bool show) {
|
||||
lb->Show(show);
|
||||
if (show)
|
||||
lb->Select(0);
|
||||
}
|
||||
|
||||
void AutoComplete::Cancel() {
|
||||
if (lb->Created()) {
|
||||
lb->Clear();
|
||||
lb->Destroy();
|
||||
active = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AutoComplete::Move(int delta) {
|
||||
int count = lb->Length();
|
||||
int current = lb->GetSelection();
|
||||
current += delta;
|
||||
if (current >= count)
|
||||
current = count - 1;
|
||||
if (current < 0)
|
||||
current = 0;
|
||||
lb->Select(current);
|
||||
}
|
||||
|
||||
void AutoComplete::Select(const char *word) {
|
||||
size_t lenWord = strlen(word);
|
||||
int location = -1;
|
||||
int start = 0; // lower bound of the api array block to search
|
||||
int end = lb->Length() - 1; // upper bound of the api array block to search
|
||||
while ((start <= end) && (location == -1)) { // Binary searching loop
|
||||
int pivot = (start + end) / 2;
|
||||
char item[maxItemLen];
|
||||
lb->GetValue(sortMatrix[pivot], item, maxItemLen);
|
||||
int cond;
|
||||
if (ignoreCase)
|
||||
cond = CompareNCaseInsensitive(word, item, lenWord);
|
||||
else
|
||||
cond = strncmp(word, item, lenWord);
|
||||
if (!cond) {
|
||||
// Find first match
|
||||
while (pivot > start) {
|
||||
lb->GetValue(sortMatrix[pivot-1], item, maxItemLen);
|
||||
if (ignoreCase)
|
||||
cond = CompareNCaseInsensitive(word, item, lenWord);
|
||||
else
|
||||
cond = strncmp(word, item, lenWord);
|
||||
if (0 != cond)
|
||||
break;
|
||||
--pivot;
|
||||
}
|
||||
location = pivot;
|
||||
if (ignoreCase
|
||||
&& ignoreCaseBehaviour == SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE) {
|
||||
// Check for exact-case match
|
||||
for (; pivot <= end; pivot++) {
|
||||
lb->GetValue(sortMatrix[pivot], item, maxItemLen);
|
||||
if (!strncmp(word, item, lenWord)) {
|
||||
location = pivot;
|
||||
break;
|
||||
}
|
||||
if (CompareNCaseInsensitive(word, item, lenWord))
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (cond < 0) {
|
||||
end = pivot - 1;
|
||||
} else if (cond > 0) {
|
||||
start = pivot + 1;
|
||||
}
|
||||
}
|
||||
if (location == -1) {
|
||||
if (autoHide)
|
||||
Cancel();
|
||||
else
|
||||
lb->Select(-1);
|
||||
} else {
|
||||
if (autoSort == SC_ORDER_CUSTOM) {
|
||||
// Check for a logically earlier match
|
||||
char item[maxItemLen];
|
||||
for (int i = location + 1; i <= end; ++i) {
|
||||
lb->GetValue(sortMatrix[i], item, maxItemLen);
|
||||
if (CompareNCaseInsensitive(word, item, lenWord))
|
||||
break;
|
||||
if (sortMatrix[i] < sortMatrix[location] && !strncmp(word, item, lenWord))
|
||||
location = i;
|
||||
}
|
||||
}
|
||||
lb->Select(sortMatrix[location]);
|
||||
}
|
||||
}
|
||||
|
||||
99
third-party/scintilla/AutoComplete.h
vendored
Normal file
99
third-party/scintilla/AutoComplete.h
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file AutoComplete.h
|
||||
** Defines the auto completion list box.
|
||||
**/
|
||||
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef AUTOCOMPLETE_H
|
||||
#define AUTOCOMPLETE_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
/**
|
||||
*/
|
||||
class AutoComplete {
|
||||
bool active;
|
||||
std::string stopChars;
|
||||
std::string fillUpChars;
|
||||
char separator;
|
||||
char typesep; // Type seperator
|
||||
enum { maxItemLen=1000 };
|
||||
std::vector<int> sortMatrix;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
AutoComplete(const AutoComplete &);
|
||||
AutoComplete &operator =(const AutoComplete &);
|
||||
|
||||
public:
|
||||
|
||||
bool ignoreCase;
|
||||
bool chooseSingle;
|
||||
ListBox *lb;
|
||||
int posStart;
|
||||
int startLen;
|
||||
/// Should autocompletion be canceled if editor's currentPos <= startPos?
|
||||
bool cancelAtStartPos;
|
||||
bool autoHide;
|
||||
bool dropRestOfWord;
|
||||
unsigned int ignoreCaseBehaviour;
|
||||
int widthLBDefault;
|
||||
int heightLBDefault;
|
||||
/** SC_ORDER_PRESORTED: Assume the list is presorted; selection will fail if it is not alphabetical<br />
|
||||
* SC_ORDER_PERFORMSORT: Sort the list alphabetically; start up performance cost for sorting<br />
|
||||
* SC_ORDER_CUSTOM: Handle non-alphabetical entries; start up performance cost for generating a sorted lookup table
|
||||
*/
|
||||
int autoSort;
|
||||
|
||||
AutoComplete();
|
||||
~AutoComplete();
|
||||
|
||||
/// Is the auto completion list displayed?
|
||||
bool Active() const;
|
||||
|
||||
/// Display the auto completion list positioned to be near a character position
|
||||
void Start(Window &parent, int ctrlID, int position, Point location,
|
||||
int startLen_, int lineHeight, bool unicodeMode, int technology);
|
||||
|
||||
/// The stop chars are characters which, when typed, cause the auto completion list to disappear
|
||||
void SetStopChars(const char *stopChars_);
|
||||
bool IsStopChar(char ch);
|
||||
|
||||
/// The fillup chars are characters which, when typed, fill up the selected word
|
||||
void SetFillUpChars(const char *fillUpChars_);
|
||||
bool IsFillUpChar(char ch);
|
||||
|
||||
/// The separator character is used when interpreting the list in SetList
|
||||
void SetSeparator(char separator_);
|
||||
char GetSeparator() const;
|
||||
|
||||
/// The typesep character is used for seperating the word from the type
|
||||
void SetTypesep(char separator_);
|
||||
char GetTypesep() const;
|
||||
|
||||
/// The list string contains a sequence of words separated by the separator character
|
||||
void SetList(const char *list);
|
||||
|
||||
/// Return the position of the currently selected list item
|
||||
int GetSelection() const;
|
||||
|
||||
/// Return the value of an item in the list
|
||||
std::string GetValue(int item) const;
|
||||
|
||||
void Show(bool show);
|
||||
void Cancel();
|
||||
|
||||
/// Move the current list element by delta, scrolling appropriately
|
||||
void Move(int delta);
|
||||
|
||||
/// Select a list element that starts with word as the current element
|
||||
void Select(const char *word);
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
327
third-party/scintilla/CallTip.cxx
vendored
Normal file
327
third-party/scintilla/CallTip.cxx
vendored
Normal file
@@ -0,0 +1,327 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file CallTip.cxx
|
||||
** Code for displaying call tips.
|
||||
**/
|
||||
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
#include "StringCopy.h"
|
||||
#include "CallTip.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
CallTip::CallTip() {
|
||||
wCallTip = 0;
|
||||
inCallTipMode = false;
|
||||
posStartCallTip = 0;
|
||||
rectUp = PRectangle(0,0,0,0);
|
||||
rectDown = PRectangle(0,0,0,0);
|
||||
lineHeight = 1;
|
||||
offsetMain = 0;
|
||||
startHighlight = 0;
|
||||
endHighlight = 0;
|
||||
tabSize = 0;
|
||||
above = false;
|
||||
useStyleCallTip = false; // for backwards compatibility
|
||||
|
||||
insetX = 5;
|
||||
widthArrow = 14;
|
||||
borderHeight = 2; // Extra line for border and an empty line at top and bottom.
|
||||
verticalOffset = 1;
|
||||
|
||||
#ifdef __APPLE__
|
||||
// proper apple colours for the default
|
||||
colourBG = ColourDesired(0xff, 0xff, 0xc6);
|
||||
colourUnSel = ColourDesired(0, 0, 0);
|
||||
#else
|
||||
colourBG = ColourDesired(0xff, 0xff, 0xff);
|
||||
colourUnSel = ColourDesired(0x80, 0x80, 0x80);
|
||||
#endif
|
||||
colourSel = ColourDesired(0, 0, 0x80);
|
||||
colourShade = ColourDesired(0, 0, 0);
|
||||
colourLight = ColourDesired(0xc0, 0xc0, 0xc0);
|
||||
codePage = 0;
|
||||
clickPlace = 0;
|
||||
}
|
||||
|
||||
CallTip::~CallTip() {
|
||||
font.Release();
|
||||
wCallTip.Destroy();
|
||||
}
|
||||
|
||||
// Although this test includes 0, we should never see a \0 character.
|
||||
static bool IsArrowCharacter(char ch) {
|
||||
return (ch == 0) || (ch == '\001') || (ch == '\002');
|
||||
}
|
||||
|
||||
// We ignore tabs unless a tab width has been set.
|
||||
bool CallTip::IsTabCharacter(char ch) const {
|
||||
return (tabSize > 0) && (ch == '\t');
|
||||
}
|
||||
|
||||
int CallTip::NextTabPos(int x) const {
|
||||
if (tabSize > 0) { // paranoia... not called unless this is true
|
||||
x -= insetX; // position relative to text
|
||||
x = (x + tabSize) / tabSize; // tab "number"
|
||||
return tabSize*x + insetX; // position of next tab
|
||||
} else {
|
||||
return x + 1; // arbitrary
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a section of the call tip that does not include \n in one colour.
|
||||
// The text may include up to numEnds tabs or arrow characters.
|
||||
void CallTip::DrawChunk(Surface *surface, int &x, const char *s,
|
||||
int posStart, int posEnd, int ytext, PRectangle rcClient,
|
||||
bool highlight, bool draw) {
|
||||
s += posStart;
|
||||
int len = posEnd - posStart;
|
||||
|
||||
// Divide the text into sections that are all text, or that are
|
||||
// single arrows or single tab characters (if tabSize > 0).
|
||||
int maxEnd = 0;
|
||||
const int numEnds = 10;
|
||||
int ends[numEnds + 2];
|
||||
for (int i=0; i<len; i++) {
|
||||
if ((maxEnd < numEnds) &&
|
||||
(IsArrowCharacter(s[i]) || IsTabCharacter(s[i]))) {
|
||||
if (i > 0)
|
||||
ends[maxEnd++] = i;
|
||||
ends[maxEnd++] = i+1;
|
||||
}
|
||||
}
|
||||
ends[maxEnd++] = len;
|
||||
int startSeg = 0;
|
||||
int xEnd;
|
||||
for (int seg = 0; seg<maxEnd; seg++) {
|
||||
int endSeg = ends[seg];
|
||||
if (endSeg > startSeg) {
|
||||
if (IsArrowCharacter(s[startSeg])) {
|
||||
xEnd = x + widthArrow;
|
||||
bool upArrow = s[startSeg] == '\001';
|
||||
rcClient.left = static_cast<XYPOSITION>(x);
|
||||
rcClient.right = static_cast<XYPOSITION>(xEnd);
|
||||
if (draw) {
|
||||
const int halfWidth = widthArrow / 2 - 3;
|
||||
const int quarterWidth = halfWidth / 2;
|
||||
const int centreX = x + widthArrow / 2 - 1;
|
||||
const int centreY = static_cast<int>(rcClient.top + rcClient.bottom) / 2;
|
||||
surface->FillRectangle(rcClient, colourBG);
|
||||
PRectangle rcClientInner(rcClient.left + 1, rcClient.top + 1,
|
||||
rcClient.right - 2, rcClient.bottom - 1);
|
||||
surface->FillRectangle(rcClientInner, colourUnSel);
|
||||
|
||||
if (upArrow) { // Up arrow
|
||||
Point pts[] = {
|
||||
Point::FromInts(centreX - halfWidth, centreY + quarterWidth),
|
||||
Point::FromInts(centreX + halfWidth, centreY + quarterWidth),
|
||||
Point::FromInts(centreX, centreY - halfWidth + quarterWidth),
|
||||
};
|
||||
surface->Polygon(pts, ELEMENTS(pts), colourBG, colourBG);
|
||||
} else { // Down arrow
|
||||
Point pts[] = {
|
||||
Point::FromInts(centreX - halfWidth, centreY - quarterWidth),
|
||||
Point::FromInts(centreX + halfWidth, centreY - quarterWidth),
|
||||
Point::FromInts(centreX, centreY + halfWidth - quarterWidth),
|
||||
};
|
||||
surface->Polygon(pts, ELEMENTS(pts), colourBG, colourBG);
|
||||
}
|
||||
}
|
||||
offsetMain = xEnd;
|
||||
if (upArrow) {
|
||||
rectUp = rcClient;
|
||||
} else {
|
||||
rectDown = rcClient;
|
||||
}
|
||||
} else if (IsTabCharacter(s[startSeg])) {
|
||||
xEnd = NextTabPos(x);
|
||||
} else {
|
||||
xEnd = x + RoundXYPosition(surface->WidthText(font, s + startSeg, endSeg - startSeg));
|
||||
if (draw) {
|
||||
rcClient.left = static_cast<XYPOSITION>(x);
|
||||
rcClient.right = static_cast<XYPOSITION>(xEnd);
|
||||
surface->DrawTextTransparent(rcClient, font, static_cast<XYPOSITION>(ytext),
|
||||
s+startSeg, endSeg - startSeg,
|
||||
highlight ? colourSel : colourUnSel);
|
||||
}
|
||||
}
|
||||
x = xEnd;
|
||||
startSeg = endSeg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CallTip::PaintContents(Surface *surfaceWindow, bool draw) {
|
||||
PRectangle rcClientPos = wCallTip.GetClientPosition();
|
||||
PRectangle rcClientSize(0.0f, 0.0f, rcClientPos.right - rcClientPos.left,
|
||||
rcClientPos.bottom - rcClientPos.top);
|
||||
PRectangle rcClient(1.0f, 1.0f, rcClientSize.right - 1, rcClientSize.bottom - 1);
|
||||
|
||||
// To make a nice small call tip window, it is only sized to fit most normal characters without accents
|
||||
int ascent = RoundXYPosition(surfaceWindow->Ascent(font) - surfaceWindow->InternalLeading(font));
|
||||
|
||||
// For each line...
|
||||
// Draw the definition in three parts: before highlight, highlighted, after highlight
|
||||
int ytext = static_cast<int>(rcClient.top) + ascent + 1;
|
||||
rcClient.bottom = ytext + surfaceWindow->Descent(font) + 1;
|
||||
const char *chunkVal = val.c_str();
|
||||
bool moreChunks = true;
|
||||
int maxWidth = 0;
|
||||
|
||||
while (moreChunks) {
|
||||
const char *chunkEnd = strchr(chunkVal, '\n');
|
||||
if (chunkEnd == NULL) {
|
||||
chunkEnd = chunkVal + strlen(chunkVal);
|
||||
moreChunks = false;
|
||||
}
|
||||
int chunkOffset = static_cast<int>(chunkVal - val.c_str());
|
||||
int chunkLength = static_cast<int>(chunkEnd - chunkVal);
|
||||
int chunkEndOffset = chunkOffset + chunkLength;
|
||||
int thisStartHighlight = Platform::Maximum(startHighlight, chunkOffset);
|
||||
thisStartHighlight = Platform::Minimum(thisStartHighlight, chunkEndOffset);
|
||||
thisStartHighlight -= chunkOffset;
|
||||
int thisEndHighlight = Platform::Maximum(endHighlight, chunkOffset);
|
||||
thisEndHighlight = Platform::Minimum(thisEndHighlight, chunkEndOffset);
|
||||
thisEndHighlight -= chunkOffset;
|
||||
rcClient.top = static_cast<XYPOSITION>(ytext - ascent - 1);
|
||||
|
||||
int x = insetX; // start each line at this inset
|
||||
|
||||
DrawChunk(surfaceWindow, x, chunkVal, 0, thisStartHighlight,
|
||||
ytext, rcClient, false, draw);
|
||||
DrawChunk(surfaceWindow, x, chunkVal, thisStartHighlight, thisEndHighlight,
|
||||
ytext, rcClient, true, draw);
|
||||
DrawChunk(surfaceWindow, x, chunkVal, thisEndHighlight, chunkLength,
|
||||
ytext, rcClient, false, draw);
|
||||
|
||||
chunkVal = chunkEnd + 1;
|
||||
ytext += lineHeight;
|
||||
rcClient.bottom += lineHeight;
|
||||
maxWidth = Platform::Maximum(maxWidth, x);
|
||||
}
|
||||
return maxWidth;
|
||||
}
|
||||
|
||||
void CallTip::PaintCT(Surface *surfaceWindow) {
|
||||
if (val.empty())
|
||||
return;
|
||||
PRectangle rcClientPos = wCallTip.GetClientPosition();
|
||||
PRectangle rcClientSize(0.0f, 0.0f, rcClientPos.right - rcClientPos.left,
|
||||
rcClientPos.bottom - rcClientPos.top);
|
||||
PRectangle rcClient(1.0f, 1.0f, rcClientSize.right - 1, rcClientSize.bottom - 1);
|
||||
|
||||
surfaceWindow->FillRectangle(rcClient, colourBG);
|
||||
|
||||
offsetMain = insetX; // initial alignment assuming no arrows
|
||||
PaintContents(surfaceWindow, true);
|
||||
|
||||
#ifndef __APPLE__
|
||||
// OSX doesn't put borders on "help tags"
|
||||
// Draw a raised border around the edges of the window
|
||||
surfaceWindow->MoveTo(0, static_cast<int>(rcClientSize.bottom) - 1);
|
||||
surfaceWindow->PenColour(colourShade);
|
||||
surfaceWindow->LineTo(static_cast<int>(rcClientSize.right) - 1, static_cast<int>(rcClientSize.bottom) - 1);
|
||||
surfaceWindow->LineTo(static_cast<int>(rcClientSize.right) - 1, 0);
|
||||
surfaceWindow->PenColour(colourLight);
|
||||
surfaceWindow->LineTo(0, 0);
|
||||
surfaceWindow->LineTo(0, static_cast<int>(rcClientSize.bottom) - 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CallTip::MouseClick(Point pt) {
|
||||
clickPlace = 0;
|
||||
if (rectUp.Contains(pt))
|
||||
clickPlace = 1;
|
||||
if (rectDown.Contains(pt))
|
||||
clickPlace = 2;
|
||||
}
|
||||
|
||||
PRectangle CallTip::CallTipStart(int pos, Point pt, int textHeight, const char *defn,
|
||||
const char *faceName, int size,
|
||||
int codePage_, int characterSet,
|
||||
int technology, Window &wParent) {
|
||||
clickPlace = 0;
|
||||
val = defn;
|
||||
codePage = codePage_;
|
||||
Surface *surfaceMeasure = Surface::Allocate(technology);
|
||||
if (!surfaceMeasure)
|
||||
return PRectangle();
|
||||
surfaceMeasure->Init(wParent.GetID());
|
||||
surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == codePage);
|
||||
surfaceMeasure->SetDBCSMode(codePage);
|
||||
startHighlight = 0;
|
||||
endHighlight = 0;
|
||||
inCallTipMode = true;
|
||||
posStartCallTip = pos;
|
||||
XYPOSITION deviceHeight = static_cast<XYPOSITION>(surfaceMeasure->DeviceHeightFont(size));
|
||||
FontParameters fp(faceName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, SC_WEIGHT_NORMAL, false, 0, technology, characterSet);
|
||||
font.Create(fp);
|
||||
// Look for multiple lines in the text
|
||||
// Only support \n here - simply means container must avoid \r!
|
||||
int numLines = 1;
|
||||
const char *newline;
|
||||
const char *look = val.c_str();
|
||||
rectUp = PRectangle(0,0,0,0);
|
||||
rectDown = PRectangle(0,0,0,0);
|
||||
offsetMain = insetX; // changed to right edge of any arrows
|
||||
int width = PaintContents(surfaceMeasure, false) + insetX;
|
||||
while ((newline = strchr(look, '\n')) != NULL) {
|
||||
look = newline + 1;
|
||||
numLines++;
|
||||
}
|
||||
lineHeight = RoundXYPosition(surfaceMeasure->Height(font));
|
||||
|
||||
// The returned
|
||||
// rectangle is aligned to the right edge of the last arrow encountered in
|
||||
// the tip text, else to the tip text left edge.
|
||||
int height = lineHeight * numLines - static_cast<int>(surfaceMeasure->InternalLeading(font)) + borderHeight * 2;
|
||||
delete surfaceMeasure;
|
||||
if (above) {
|
||||
return PRectangle(pt.x - offsetMain, pt.y - verticalOffset - height, pt.x + width - offsetMain, pt.y - verticalOffset);
|
||||
} else {
|
||||
return PRectangle(pt.x - offsetMain, pt.y + verticalOffset + textHeight, pt.x + width - offsetMain, pt.y + verticalOffset + textHeight + height);
|
||||
}
|
||||
}
|
||||
|
||||
void CallTip::CallTipCancel() {
|
||||
inCallTipMode = false;
|
||||
if (wCallTip.Created()) {
|
||||
wCallTip.Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void CallTip::SetHighlight(int start, int end) {
|
||||
// Avoid flashing by checking something has really changed
|
||||
if ((start != startHighlight) || (end != endHighlight)) {
|
||||
startHighlight = start;
|
||||
endHighlight = (end > start) ? end : start;
|
||||
if (wCallTip.Created()) {
|
||||
wCallTip.InvalidateAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the tab size (sizes > 0 enable the use of tabs). This also enables the
|
||||
// use of the STYLE_CALLTIP.
|
||||
void CallTip::SetTabSize(int tabSz) {
|
||||
tabSize = tabSz;
|
||||
useStyleCallTip = true;
|
||||
}
|
||||
|
||||
// Set the calltip position, below the text by default or if above is false
|
||||
// else above the text.
|
||||
void CallTip::SetPosition(bool aboveText) {
|
||||
above = aboveText;
|
||||
}
|
||||
|
||||
// It might be better to have two access functions for this and to use
|
||||
// them for all settings of colours.
|
||||
void CallTip::SetForeBack(const ColourDesired &fore, const ColourDesired &back) {
|
||||
colourBG = back;
|
||||
colourUnSel = fore;
|
||||
}
|
||||
93
third-party/scintilla/CallTip.h
vendored
Normal file
93
third-party/scintilla/CallTip.h
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file CallTip.h
|
||||
** Interface to the call tip control.
|
||||
**/
|
||||
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef CALLTIP_H
|
||||
#define CALLTIP_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
/**
|
||||
*/
|
||||
class CallTip {
|
||||
int startHighlight; // character offset to start and...
|
||||
int endHighlight; // ...end of highlighted text
|
||||
std::string val;
|
||||
Font font;
|
||||
PRectangle rectUp; // rectangle of last up angle in the tip
|
||||
PRectangle rectDown; // rectangle of last down arrow in the tip
|
||||
int lineHeight; // vertical line spacing
|
||||
int offsetMain; // The alignment point of the call tip
|
||||
int tabSize; // Tab size in pixels, <=0 no TAB expand
|
||||
bool useStyleCallTip; // if true, STYLE_CALLTIP should be used
|
||||
bool above; // if true, display calltip above text
|
||||
|
||||
// Private so CallTip objects can not be copied
|
||||
CallTip(const CallTip &);
|
||||
CallTip &operator=(const CallTip &);
|
||||
void DrawChunk(Surface *surface, int &x, const char *s,
|
||||
int posStart, int posEnd, int ytext, PRectangle rcClient,
|
||||
bool highlight, bool draw);
|
||||
int PaintContents(Surface *surfaceWindow, bool draw);
|
||||
bool IsTabCharacter(char c) const;
|
||||
int NextTabPos(int x) const;
|
||||
|
||||
public:
|
||||
Window wCallTip;
|
||||
Window wDraw;
|
||||
bool inCallTipMode;
|
||||
int posStartCallTip;
|
||||
ColourDesired colourBG;
|
||||
ColourDesired colourUnSel;
|
||||
ColourDesired colourSel;
|
||||
ColourDesired colourShade;
|
||||
ColourDesired colourLight;
|
||||
int codePage;
|
||||
int clickPlace;
|
||||
|
||||
int insetX; // text inset in x from calltip border
|
||||
int widthArrow;
|
||||
int borderHeight;
|
||||
int verticalOffset; // pixel offset up or down of the calltip with respect to the line
|
||||
|
||||
CallTip();
|
||||
~CallTip();
|
||||
|
||||
void PaintCT(Surface *surfaceWindow);
|
||||
|
||||
void MouseClick(Point pt);
|
||||
|
||||
/// Setup the calltip and return a rectangle of the area required.
|
||||
PRectangle CallTipStart(int pos, Point pt, int textHeight, const char *defn,
|
||||
const char *faceName, int size, int codePage_,
|
||||
int characterSet, int technology, Window &wParent);
|
||||
|
||||
void CallTipCancel();
|
||||
|
||||
/// Set a range of characters to be displayed in a highlight style.
|
||||
/// Commonly used to highlight the current parameter.
|
||||
void SetHighlight(int start, int end);
|
||||
|
||||
/// Set the tab size in pixels for the call tip. 0 or -ve means no tab expand.
|
||||
void SetTabSize(int tabSz);
|
||||
|
||||
/// Set calltip position.
|
||||
void SetPosition(bool aboveText);
|
||||
|
||||
/// Used to determine which STYLE_xxxx to use for call tip information
|
||||
bool UseStyleCallTip() const { return useStyleCallTip;}
|
||||
|
||||
// Modify foreground and background colours
|
||||
void SetForeBack(const ColourDesired &fore, const ColourDesired &back);
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
629
third-party/scintilla/CaseConvert.cxx
vendored
Normal file
629
third-party/scintilla/CaseConvert.cxx
vendored
Normal file
@@ -0,0 +1,629 @@
|
||||
// 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/GenerateCaseConvert.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 "StringCopy.h"
|
||||
#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\)
|
||||
"\xc2\xb5|\xce\xbc|\xce\x9c||"
|
||||
"\xc3\x9f|ss|SS||"
|
||||
"\xc4\xb0|i\xcc\x87||i\xcc\x87|"
|
||||
"\xc4\xb1||I||"
|
||||
"\xc5\x89|\xca\xbcn|\xca\xbcN||"
|
||||
"\xc5\xbf|s|S||"
|
||||
"\xc7\x85|\xc7\x86|\xc7\x84|\xc7\x86|"
|
||||
"\xc7\x88|\xc7\x89|\xc7\x87|\xc7\x89|"
|
||||
"\xc7\x8b|\xc7\x8c|\xc7\x8a|\xc7\x8c|"
|
||||
"\xc7\xb0|j\xcc\x8c|J\xcc\x8c||"
|
||||
"\xc7\xb2|\xc7\xb3|\xc7\xb1|\xc7\xb3|"
|
||||
"\xcd\x85|\xce\xb9|\xce\x99||"
|
||||
"\xce\x90|\xce\xb9\xcc\x88\xcc\x81|\xce\x99\xcc\x88\xcc\x81||"
|
||||
"\xce\xb0|\xcf\x85\xcc\x88\xcc\x81|\xce\xa5\xcc\x88\xcc\x81||"
|
||||
"\xcf\x82|\xcf\x83|\xce\xa3||"
|
||||
"\xcf\x90|\xce\xb2|\xce\x92||"
|
||||
"\xcf\x91|\xce\xb8|\xce\x98||"
|
||||
"\xcf\x95|\xcf\x86|\xce\xa6||"
|
||||
"\xcf\x96|\xcf\x80|\xce\xa0||"
|
||||
"\xcf\xb0|\xce\xba|\xce\x9a||"
|
||||
"\xcf\xb1|\xcf\x81|\xce\xa1||"
|
||||
"\xcf\xb4|\xce\xb8||\xce\xb8|"
|
||||
"\xcf\xb5|\xce\xb5|\xce\x95||"
|
||||
"\xd6\x87|\xd5\xa5\xd6\x82|\xd4\xb5\xd5\x92||"
|
||||
"\xe1\xba\x96|h\xcc\xb1|H\xcc\xb1||"
|
||||
"\xe1\xba\x97|t\xcc\x88|T\xcc\x88||"
|
||||
"\xe1\xba\x98|w\xcc\x8a|W\xcc\x8a||"
|
||||
"\xe1\xba\x99|y\xcc\x8a|Y\xcc\x8a||"
|
||||
"\xe1\xba\x9a|a\xca\xbe|A\xca\xbe||"
|
||||
"\xe1\xba\x9b|\xe1\xb9\xa1|\xe1\xb9\xa0||"
|
||||
"\xe1\xba\x9e|ss||\xc3\x9f|"
|
||||
"\xe1\xbd\x90|\xcf\x85\xcc\x93|\xce\xa5\xcc\x93||"
|
||||
"\xe1\xbd\x92|\xcf\x85\xcc\x93\xcc\x80|\xce\xa5\xcc\x93\xcc\x80||"
|
||||
"\xe1\xbd\x94|\xcf\x85\xcc\x93\xcc\x81|\xce\xa5\xcc\x93\xcc\x81||"
|
||||
"\xe1\xbd\x96|\xcf\x85\xcc\x93\xcd\x82|\xce\xa5\xcc\x93\xcd\x82||"
|
||||
"\xe1\xbe\x80|\xe1\xbc\x80\xce\xb9|\xe1\xbc\x88\xce\x99||"
|
||||
"\xe1\xbe\x81|\xe1\xbc\x81\xce\xb9|\xe1\xbc\x89\xce\x99||"
|
||||
"\xe1\xbe\x82|\xe1\xbc\x82\xce\xb9|\xe1\xbc\x8a\xce\x99||"
|
||||
"\xe1\xbe\x83|\xe1\xbc\x83\xce\xb9|\xe1\xbc\x8b\xce\x99||"
|
||||
"\xe1\xbe\x84|\xe1\xbc\x84\xce\xb9|\xe1\xbc\x8c\xce\x99||"
|
||||
"\xe1\xbe\x85|\xe1\xbc\x85\xce\xb9|\xe1\xbc\x8d\xce\x99||"
|
||||
"\xe1\xbe\x86|\xe1\xbc\x86\xce\xb9|\xe1\xbc\x8e\xce\x99||"
|
||||
"\xe1\xbe\x87|\xe1\xbc\x87\xce\xb9|\xe1\xbc\x8f\xce\x99||"
|
||||
"\xe1\xbe\x88|\xe1\xbc\x80\xce\xb9|\xe1\xbc\x88\xce\x99|\xe1\xbe\x80|"
|
||||
"\xe1\xbe\x89|\xe1\xbc\x81\xce\xb9|\xe1\xbc\x89\xce\x99|\xe1\xbe\x81|"
|
||||
"\xe1\xbe\x8a|\xe1\xbc\x82\xce\xb9|\xe1\xbc\x8a\xce\x99|\xe1\xbe\x82|"
|
||||
"\xe1\xbe\x8b|\xe1\xbc\x83\xce\xb9|\xe1\xbc\x8b\xce\x99|\xe1\xbe\x83|"
|
||||
"\xe1\xbe\x8c|\xe1\xbc\x84\xce\xb9|\xe1\xbc\x8c\xce\x99|\xe1\xbe\x84|"
|
||||
"\xe1\xbe\x8d|\xe1\xbc\x85\xce\xb9|\xe1\xbc\x8d\xce\x99|\xe1\xbe\x85|"
|
||||
"\xe1\xbe\x8e|\xe1\xbc\x86\xce\xb9|\xe1\xbc\x8e\xce\x99|\xe1\xbe\x86|"
|
||||
"\xe1\xbe\x8f|\xe1\xbc\x87\xce\xb9|\xe1\xbc\x8f\xce\x99|\xe1\xbe\x87|"
|
||||
"\xe1\xbe\x90|\xe1\xbc\xa0\xce\xb9|\xe1\xbc\xa8\xce\x99||"
|
||||
"\xe1\xbe\x91|\xe1\xbc\xa1\xce\xb9|\xe1\xbc\xa9\xce\x99||"
|
||||
"\xe1\xbe\x92|\xe1\xbc\xa2\xce\xb9|\xe1\xbc\xaa\xce\x99||"
|
||||
"\xe1\xbe\x93|\xe1\xbc\xa3\xce\xb9|\xe1\xbc\xab\xce\x99||"
|
||||
"\xe1\xbe\x94|\xe1\xbc\xa4\xce\xb9|\xe1\xbc\xac\xce\x99||"
|
||||
"\xe1\xbe\x95|\xe1\xbc\xa5\xce\xb9|\xe1\xbc\xad\xce\x99||"
|
||||
"\xe1\xbe\x96|\xe1\xbc\xa6\xce\xb9|\xe1\xbc\xae\xce\x99||"
|
||||
"\xe1\xbe\x97|\xe1\xbc\xa7\xce\xb9|\xe1\xbc\xaf\xce\x99||"
|
||||
"\xe1\xbe\x98|\xe1\xbc\xa0\xce\xb9|\xe1\xbc\xa8\xce\x99|\xe1\xbe\x90|"
|
||||
"\xe1\xbe\x99|\xe1\xbc\xa1\xce\xb9|\xe1\xbc\xa9\xce\x99|\xe1\xbe\x91|"
|
||||
"\xe1\xbe\x9a|\xe1\xbc\xa2\xce\xb9|\xe1\xbc\xaa\xce\x99|\xe1\xbe\x92|"
|
||||
"\xe1\xbe\x9b|\xe1\xbc\xa3\xce\xb9|\xe1\xbc\xab\xce\x99|\xe1\xbe\x93|"
|
||||
"\xe1\xbe\x9c|\xe1\xbc\xa4\xce\xb9|\xe1\xbc\xac\xce\x99|\xe1\xbe\x94|"
|
||||
"\xe1\xbe\x9d|\xe1\xbc\xa5\xce\xb9|\xe1\xbc\xad\xce\x99|\xe1\xbe\x95|"
|
||||
"\xe1\xbe\x9e|\xe1\xbc\xa6\xce\xb9|\xe1\xbc\xae\xce\x99|\xe1\xbe\x96|"
|
||||
"\xe1\xbe\x9f|\xe1\xbc\xa7\xce\xb9|\xe1\xbc\xaf\xce\x99|\xe1\xbe\x97|"
|
||||
"\xe1\xbe\xa0|\xe1\xbd\xa0\xce\xb9|\xe1\xbd\xa8\xce\x99||"
|
||||
"\xe1\xbe\xa1|\xe1\xbd\xa1\xce\xb9|\xe1\xbd\xa9\xce\x99||"
|
||||
"\xe1\xbe\xa2|\xe1\xbd\xa2\xce\xb9|\xe1\xbd\xaa\xce\x99||"
|
||||
"\xe1\xbe\xa3|\xe1\xbd\xa3\xce\xb9|\xe1\xbd\xab\xce\x99||"
|
||||
"\xe1\xbe\xa4|\xe1\xbd\xa4\xce\xb9|\xe1\xbd\xac\xce\x99||"
|
||||
"\xe1\xbe\xa5|\xe1\xbd\xa5\xce\xb9|\xe1\xbd\xad\xce\x99||"
|
||||
"\xe1\xbe\xa6|\xe1\xbd\xa6\xce\xb9|\xe1\xbd\xae\xce\x99||"
|
||||
"\xe1\xbe\xa7|\xe1\xbd\xa7\xce\xb9|\xe1\xbd\xaf\xce\x99||"
|
||||
"\xe1\xbe\xa8|\xe1\xbd\xa0\xce\xb9|\xe1\xbd\xa8\xce\x99|\xe1\xbe\xa0|"
|
||||
"\xe1\xbe\xa9|\xe1\xbd\xa1\xce\xb9|\xe1\xbd\xa9\xce\x99|\xe1\xbe\xa1|"
|
||||
"\xe1\xbe\xaa|\xe1\xbd\xa2\xce\xb9|\xe1\xbd\xaa\xce\x99|\xe1\xbe\xa2|"
|
||||
"\xe1\xbe\xab|\xe1\xbd\xa3\xce\xb9|\xe1\xbd\xab\xce\x99|\xe1\xbe\xa3|"
|
||||
"\xe1\xbe\xac|\xe1\xbd\xa4\xce\xb9|\xe1\xbd\xac\xce\x99|\xe1\xbe\xa4|"
|
||||
"\xe1\xbe\xad|\xe1\xbd\xa5\xce\xb9|\xe1\xbd\xad\xce\x99|\xe1\xbe\xa5|"
|
||||
"\xe1\xbe\xae|\xe1\xbd\xa6\xce\xb9|\xe1\xbd\xae\xce\x99|\xe1\xbe\xa6|"
|
||||
"\xe1\xbe\xaf|\xe1\xbd\xa7\xce\xb9|\xe1\xbd\xaf\xce\x99|\xe1\xbe\xa7|"
|
||||
"\xe1\xbe\xb2|\xe1\xbd\xb0\xce\xb9|\xe1\xbe\xba\xce\x99||"
|
||||
"\xe1\xbe\xb3|\xce\xb1\xce\xb9|\xce\x91\xce\x99||"
|
||||
"\xe1\xbe\xb4|\xce\xac\xce\xb9|\xce\x86\xce\x99||"
|
||||
"\xe1\xbe\xb6|\xce\xb1\xcd\x82|\xce\x91\xcd\x82||"
|
||||
"\xe1\xbe\xb7|\xce\xb1\xcd\x82\xce\xb9|\xce\x91\xcd\x82\xce\x99||"
|
||||
"\xe1\xbe\xbc|\xce\xb1\xce\xb9|\xce\x91\xce\x99|\xe1\xbe\xb3|"
|
||||
"\xe1\xbe\xbe|\xce\xb9|\xce\x99||"
|
||||
"\xe1\xbf\x82|\xe1\xbd\xb4\xce\xb9|\xe1\xbf\x8a\xce\x99||"
|
||||
"\xe1\xbf\x83|\xce\xb7\xce\xb9|\xce\x97\xce\x99||"
|
||||
"\xe1\xbf\x84|\xce\xae\xce\xb9|\xce\x89\xce\x99||"
|
||||
"\xe1\xbf\x86|\xce\xb7\xcd\x82|\xce\x97\xcd\x82||"
|
||||
"\xe1\xbf\x87|\xce\xb7\xcd\x82\xce\xb9|\xce\x97\xcd\x82\xce\x99||"
|
||||
"\xe1\xbf\x8c|\xce\xb7\xce\xb9|\xce\x97\xce\x99|\xe1\xbf\x83|"
|
||||
"\xe1\xbf\x92|\xce\xb9\xcc\x88\xcc\x80|\xce\x99\xcc\x88\xcc\x80||"
|
||||
"\xe1\xbf\x93|\xce\xb9\xcc\x88\xcc\x81|\xce\x99\xcc\x88\xcc\x81||"
|
||||
"\xe1\xbf\x96|\xce\xb9\xcd\x82|\xce\x99\xcd\x82||"
|
||||
"\xe1\xbf\x97|\xce\xb9\xcc\x88\xcd\x82|\xce\x99\xcc\x88\xcd\x82||"
|
||||
"\xe1\xbf\xa2|\xcf\x85\xcc\x88\xcc\x80|\xce\xa5\xcc\x88\xcc\x80||"
|
||||
"\xe1\xbf\xa3|\xcf\x85\xcc\x88\xcc\x81|\xce\xa5\xcc\x88\xcc\x81||"
|
||||
"\xe1\xbf\xa4|\xcf\x81\xcc\x93|\xce\xa1\xcc\x93||"
|
||||
"\xe1\xbf\xa6|\xcf\x85\xcd\x82|\xce\xa5\xcd\x82||"
|
||||
"\xe1\xbf\xa7|\xcf\x85\xcc\x88\xcd\x82|\xce\xa5\xcc\x88\xcd\x82||"
|
||||
"\xe1\xbf\xb2|\xe1\xbd\xbc\xce\xb9|\xe1\xbf\xba\xce\x99||"
|
||||
"\xe1\xbf\xb3|\xcf\x89\xce\xb9|\xce\xa9\xce\x99||"
|
||||
"\xe1\xbf\xb4|\xcf\x8e\xce\xb9|\xce\x8f\xce\x99||"
|
||||
"\xe1\xbf\xb6|\xcf\x89\xcd\x82|\xce\xa9\xcd\x82||"
|
||||
"\xe1\xbf\xb7|\xcf\x89\xcd\x82\xce\xb9|\xce\xa9\xcd\x82\xce\x99||"
|
||||
"\xe1\xbf\xbc|\xcf\x89\xce\xb9|\xce\xa9\xce\x99|\xe1\xbf\xb3|"
|
||||
"\xe2\x84\xa6|\xcf\x89||\xcf\x89|"
|
||||
"\xe2\x84\xaa|k||k|"
|
||||
"\xe2\x84\xab|\xc3\xa5||\xc3\xa5|"
|
||||
"\xef\xac\x80|ff|FF||"
|
||||
"\xef\xac\x81|fi|FI||"
|
||||
"\xef\xac\x82|fl|FL||"
|
||||
"\xef\xac\x83|ffi|FFI||"
|
||||
"\xef\xac\x84|ffl|FFL||"
|
||||
"\xef\xac\x85|st|ST||"
|
||||
"\xef\xac\x86|st|ST||"
|
||||
"\xef\xac\x93|\xd5\xb4\xd5\xb6|\xd5\x84\xd5\x86||"
|
||||
"\xef\xac\x94|\xd5\xb4\xd5\xa5|\xd5\x84\xd4\xb5||"
|
||||
"\xef\xac\x95|\xd5\xb4\xd5\xab|\xd5\x84\xd4\xbb||"
|
||||
"\xef\xac\x96|\xd5\xbe\xd5\xb6|\xd5\x8e\xd5\x86||"
|
||||
"\xef\xac\x97|\xd5\xb4\xd5\xad|\xd5\x84\xd4\xbd||"
|
||||
|
||||
//--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];
|
||||
ConversionString() {
|
||||
conversion[0] = '\0';
|
||||
}
|
||||
};
|
||||
// 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_) {
|
||||
StringCopy(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 == characters.end())
|
||||
return 0;
|
||||
else 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<ELEMENTS(symmetricCaseConversionRanges);) {
|
||||
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<ELEMENTS(symmetricCaseConversions);) {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
47
third-party/scintilla/CaseConvert.h
vendored
Normal file
47
third-party/scintilla/CaseConvert.h
vendored
Normal file
@@ -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
|
||||
65
third-party/scintilla/CaseFolder.cxx
vendored
Normal file
65
third-party/scintilla/CaseFolder.cxx
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
// 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 "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);
|
||||
}
|
||||
}
|
||||
45
third-party/scintilla/CaseFolder.h
vendored
Normal file
45
third-party/scintilla/CaseFolder.h
vendored
Normal file
@@ -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
|
||||
75
third-party/scintilla/Catalogue.cxx
vendored
Normal file
75
third-party/scintilla/Catalogue.cxx
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file Catalogue.cxx
|
||||
** Colourise for particular languages.
|
||||
**/
|
||||
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "ILexer.h"
|
||||
#include "Scintilla.h"
|
||||
#include "SciLexer.h"
|
||||
|
||||
#include "LexerModule.h"
|
||||
#include "Catalogue.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
static std::vector<LexerModule *> lexerCatalogue;
|
||||
static int nextLanguage = SCLEX_AUTOMATIC+1;
|
||||
|
||||
const LexerModule *Catalogue::Find(int language) {
|
||||
Scintilla_LinkLexers();
|
||||
for (std::vector<LexerModule *>::iterator it=lexerCatalogue.begin();
|
||||
it != lexerCatalogue.end(); ++it) {
|
||||
if ((*it)->GetLanguage() == language) {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const LexerModule *Catalogue::Find(const char *languageName) {
|
||||
Scintilla_LinkLexers();
|
||||
if (languageName) {
|
||||
for (std::vector<LexerModule *>::iterator it=lexerCatalogue.begin();
|
||||
it != lexerCatalogue.end(); ++it) {
|
||||
if ((*it)->languageName && (0 == strcmp((*it)->languageName, languageName))) {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Catalogue::AddLexerModule(LexerModule *plm) {
|
||||
if (plm->GetLanguage() == SCLEX_AUTOMATIC) {
|
||||
plm->language = nextLanguage;
|
||||
nextLanguage++;
|
||||
}
|
||||
lexerCatalogue.push_back(plm);
|
||||
}
|
||||
|
||||
// To add or remove a lexer, add or remove its file and run LexGen.py.
|
||||
|
||||
// Force a reference to all of the Scintilla lexers so that the linker will
|
||||
// not remove the code of the lexers.
|
||||
int Scintilla_LinkLexers() {
|
||||
|
||||
static int initialised = 0;
|
||||
if (initialised)
|
||||
return 0;
|
||||
initialised = 1;
|
||||
|
||||
// Shorten the code that declares a lexer and ensures it is linked in by calling a method.
|
||||
#define LINK_LEXER(lexer) extern LexerModule lexer; Catalogue::AddLexerModule(&lexer);
|
||||
|
||||
//++Autogenerated -- run scripts/LexGen.py to regenerate
|
||||
//**\(\tLINK_LEXER(\*);\n\)
|
||||
LINK_LEXER(lmLua);
|
||||
|
||||
//--Autogenerated -- end of automatically generated section
|
||||
|
||||
return 1;
|
||||
}
|
||||
26
third-party/scintilla/Catalogue.h
vendored
Normal file
26
third-party/scintilla/Catalogue.h
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file Catalogue.h
|
||||
** Lexer infrastructure.
|
||||
**/
|
||||
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef CATALOGUE_H
|
||||
#define CATALOGUE_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
class Catalogue {
|
||||
public:
|
||||
static const LexerModule *Find(int language);
|
||||
static const LexerModule *Find(const char *languageName);
|
||||
static void AddLexerModule(LexerModule *plm);
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
773
third-party/scintilla/CellBuffer.cxx
vendored
Normal file
773
third-party/scintilla/CellBuffer.cxx
vendored
Normal file
@@ -0,0 +1,773 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file CellBuffer.cxx
|
||||
** Manages a buffer of cells.
|
||||
**/
|
||||
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
#include "SplitVector.h"
|
||||
#include "Partitioning.h"
|
||||
#include "CellBuffer.h"
|
||||
#include "UniConversion.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
LineVector::LineVector() : starts(256), perLine(0) {
|
||||
Init();
|
||||
}
|
||||
|
||||
LineVector::~LineVector() {
|
||||
starts.DeleteAll();
|
||||
}
|
||||
|
||||
void LineVector::Init() {
|
||||
starts.DeleteAll();
|
||||
if (perLine) {
|
||||
perLine->Init();
|
||||
}
|
||||
}
|
||||
|
||||
void LineVector::SetPerLine(PerLine *pl) {
|
||||
perLine = pl;
|
||||
}
|
||||
|
||||
void LineVector::InsertText(int line, int delta) {
|
||||
starts.InsertText(line, delta);
|
||||
}
|
||||
|
||||
void LineVector::InsertLine(int line, int position, bool lineStart) {
|
||||
starts.InsertPartition(line, position);
|
||||
if (perLine) {
|
||||
if ((line > 0) && lineStart)
|
||||
line--;
|
||||
perLine->InsertLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
void LineVector::SetLineStart(int line, int position) {
|
||||
starts.SetPartitionStartPosition(line, position);
|
||||
}
|
||||
|
||||
void LineVector::RemoveLine(int line) {
|
||||
starts.RemovePartition(line);
|
||||
if (perLine) {
|
||||
perLine->RemoveLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
int LineVector::LineFromPosition(int pos) const {
|
||||
return starts.PartitionFromPosition(pos);
|
||||
}
|
||||
|
||||
Action::Action() {
|
||||
at = startAction;
|
||||
position = 0;
|
||||
data = 0;
|
||||
lenData = 0;
|
||||
mayCoalesce = false;
|
||||
}
|
||||
|
||||
Action::~Action() {
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void Action::Create(actionType at_, int position_, const char *data_, int lenData_, bool mayCoalesce_) {
|
||||
delete []data;
|
||||
data = NULL;
|
||||
position = position_;
|
||||
at = at_;
|
||||
if (lenData_) {
|
||||
data = new char[lenData_];
|
||||
memcpy(data, data_, lenData_);
|
||||
}
|
||||
lenData = lenData_;
|
||||
mayCoalesce = mayCoalesce_;
|
||||
}
|
||||
|
||||
void Action::Destroy() {
|
||||
delete []data;
|
||||
data = 0;
|
||||
}
|
||||
|
||||
void Action::Grab(Action *source) {
|
||||
delete []data;
|
||||
|
||||
position = source->position;
|
||||
at = source->at;
|
||||
data = source->data;
|
||||
lenData = source->lenData;
|
||||
mayCoalesce = source->mayCoalesce;
|
||||
|
||||
// Ownership of source data transferred to this
|
||||
source->position = 0;
|
||||
source->at = startAction;
|
||||
source->data = 0;
|
||||
source->lenData = 0;
|
||||
source->mayCoalesce = true;
|
||||
}
|
||||
|
||||
// The undo history stores a sequence of user operations that represent the user's view of the
|
||||
// commands executed on the text.
|
||||
// Each user operation contains a sequence of text insertion and text deletion actions.
|
||||
// All the user operations are stored in a list of individual actions with 'start' actions used
|
||||
// as delimiters between user operations.
|
||||
// Initially there is one start action in the history.
|
||||
// As each action is performed, it is recorded in the history. The action may either become
|
||||
// part of the current user operation or may start a new user operation. If it is to be part of the
|
||||
// current operation, then it overwrites the current last action. If it is to be part of a new
|
||||
// operation, it is appended after the current last action.
|
||||
// After writing the new action, a new start action is appended at the end of the history.
|
||||
// The decision of whether to start a new user operation is based upon two factors. If a
|
||||
// compound operation has been explicitly started by calling BeginUndoAction and no matching
|
||||
// EndUndoAction (these calls nest) has been called, then the action is coalesced into the current
|
||||
// operation. If there is no outstanding BeginUndoAction call then a new operation is started
|
||||
// unless it looks as if the new action is caused by the user typing or deleting a stream of text.
|
||||
// Sequences that look like typing or deletion are coalesced into a single user operation.
|
||||
|
||||
UndoHistory::UndoHistory() {
|
||||
|
||||
lenActions = 100;
|
||||
actions = new Action[lenActions];
|
||||
maxAction = 0;
|
||||
currentAction = 0;
|
||||
undoSequenceDepth = 0;
|
||||
savePoint = 0;
|
||||
|
||||
actions[currentAction].Create(startAction);
|
||||
}
|
||||
|
||||
UndoHistory::~UndoHistory() {
|
||||
delete []actions;
|
||||
actions = 0;
|
||||
}
|
||||
|
||||
void UndoHistory::EnsureUndoRoom() {
|
||||
// Have to test that there is room for 2 more actions in the array
|
||||
// as two actions may be created by the calling function
|
||||
if (currentAction >= (lenActions - 2)) {
|
||||
// Run out of undo nodes so extend the array
|
||||
int lenActionsNew = lenActions * 2;
|
||||
Action *actionsNew = new Action[lenActionsNew];
|
||||
for (int act = 0; act <= currentAction; act++)
|
||||
actionsNew[act].Grab(&actions[act]);
|
||||
delete []actions;
|
||||
lenActions = lenActionsNew;
|
||||
actions = actionsNew;
|
||||
}
|
||||
}
|
||||
|
||||
const char *UndoHistory::AppendAction(actionType at, int position, const char *data, int lengthData,
|
||||
bool &startSequence, bool mayCoalesce) {
|
||||
EnsureUndoRoom();
|
||||
//Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, lengthData, currentAction);
|
||||
//Platform::DebugPrintf("^ %d action %d %d\n", actions[currentAction - 1].at,
|
||||
// actions[currentAction - 1].position, actions[currentAction - 1].lenData);
|
||||
if (currentAction < savePoint) {
|
||||
savePoint = -1;
|
||||
}
|
||||
int oldCurrentAction = currentAction;
|
||||
if (currentAction >= 1) {
|
||||
if (0 == undoSequenceDepth) {
|
||||
// Top level actions may not always be coalesced
|
||||
int targetAct = -1;
|
||||
const Action *actPrevious = &(actions[currentAction + targetAct]);
|
||||
// Container actions may forward the coalesce state of Scintilla Actions.
|
||||
while ((actPrevious->at == containerAction) && actPrevious->mayCoalesce) {
|
||||
targetAct--;
|
||||
actPrevious = &(actions[currentAction + targetAct]);
|
||||
}
|
||||
// See if current action can be coalesced into previous action
|
||||
// Will work if both are inserts or deletes and position is same
|
||||
#if defined(_MSC_VER) && defined(_PREFAST_)
|
||||
// Visual Studio 2013 Code Analysis wrongly believes actions can be NULL at its next reference
|
||||
__analysis_assume(actions);
|
||||
#endif
|
||||
if (currentAction == savePoint) {
|
||||
currentAction++;
|
||||
} else if (!actions[currentAction].mayCoalesce) {
|
||||
// Not allowed to coalesce if this set
|
||||
currentAction++;
|
||||
} else if (!mayCoalesce || !actPrevious->mayCoalesce) {
|
||||
currentAction++;
|
||||
} else if (at == containerAction || actions[currentAction].at == containerAction) {
|
||||
; // A coalescible containerAction
|
||||
} else if ((at != actPrevious->at) && (actPrevious->at != startAction)) {
|
||||
currentAction++;
|
||||
} else if ((at == insertAction) &&
|
||||
(position != (actPrevious->position + actPrevious->lenData))) {
|
||||
// Insertions must be immediately after to coalesce
|
||||
currentAction++;
|
||||
} else if (at == removeAction) {
|
||||
if ((lengthData == 1) || (lengthData == 2)) {
|
||||
if ((position + lengthData) == actPrevious->position) {
|
||||
; // Backspace -> OK
|
||||
} else if (position == actPrevious->position) {
|
||||
; // Delete -> OK
|
||||
} else {
|
||||
// Removals must be at same position to coalesce
|
||||
currentAction++;
|
||||
}
|
||||
} else {
|
||||
// Removals must be of one character to coalesce
|
||||
currentAction++;
|
||||
}
|
||||
} else {
|
||||
// Action coalesced.
|
||||
}
|
||||
|
||||
} else {
|
||||
// Actions not at top level are always coalesced unless this is after return to top level
|
||||
if (!actions[currentAction].mayCoalesce)
|
||||
currentAction++;
|
||||
}
|
||||
} else {
|
||||
currentAction++;
|
||||
}
|
||||
startSequence = oldCurrentAction != currentAction;
|
||||
int actionWithData = currentAction;
|
||||
actions[currentAction].Create(at, position, data, lengthData, mayCoalesce);
|
||||
currentAction++;
|
||||
actions[currentAction].Create(startAction);
|
||||
maxAction = currentAction;
|
||||
return actions[actionWithData].data;
|
||||
}
|
||||
|
||||
void UndoHistory::BeginUndoAction() {
|
||||
EnsureUndoRoom();
|
||||
if (undoSequenceDepth == 0) {
|
||||
if (actions[currentAction].at != startAction) {
|
||||
currentAction++;
|
||||
actions[currentAction].Create(startAction);
|
||||
maxAction = currentAction;
|
||||
}
|
||||
actions[currentAction].mayCoalesce = false;
|
||||
}
|
||||
undoSequenceDepth++;
|
||||
}
|
||||
|
||||
void UndoHistory::EndUndoAction() {
|
||||
PLATFORM_ASSERT(undoSequenceDepth > 0);
|
||||
EnsureUndoRoom();
|
||||
undoSequenceDepth--;
|
||||
if (0 == undoSequenceDepth) {
|
||||
if (actions[currentAction].at != startAction) {
|
||||
currentAction++;
|
||||
actions[currentAction].Create(startAction);
|
||||
maxAction = currentAction;
|
||||
}
|
||||
actions[currentAction].mayCoalesce = false;
|
||||
}
|
||||
}
|
||||
|
||||
void UndoHistory::DropUndoSequence() {
|
||||
undoSequenceDepth = 0;
|
||||
}
|
||||
|
||||
void UndoHistory::DeleteUndoHistory() {
|
||||
for (int i = 1; i < maxAction; i++)
|
||||
actions[i].Destroy();
|
||||
maxAction = 0;
|
||||
currentAction = 0;
|
||||
actions[currentAction].Create(startAction);
|
||||
savePoint = 0;
|
||||
}
|
||||
|
||||
void UndoHistory::SetSavePoint() {
|
||||
savePoint = currentAction;
|
||||
}
|
||||
|
||||
bool UndoHistory::IsSavePoint() const {
|
||||
return savePoint == currentAction;
|
||||
}
|
||||
|
||||
bool UndoHistory::CanUndo() const {
|
||||
return (currentAction > 0) && (maxAction > 0);
|
||||
}
|
||||
|
||||
int UndoHistory::StartUndo() {
|
||||
// Drop any trailing startAction
|
||||
if (actions[currentAction].at == startAction && currentAction > 0)
|
||||
currentAction--;
|
||||
|
||||
// Count the steps in this action
|
||||
int act = currentAction;
|
||||
while (actions[act].at != startAction && act > 0) {
|
||||
act--;
|
||||
}
|
||||
return currentAction - act;
|
||||
}
|
||||
|
||||
const Action &UndoHistory::GetUndoStep() const {
|
||||
return actions[currentAction];
|
||||
}
|
||||
|
||||
void UndoHistory::CompletedUndoStep() {
|
||||
currentAction--;
|
||||
}
|
||||
|
||||
bool UndoHistory::CanRedo() const {
|
||||
return maxAction > currentAction;
|
||||
}
|
||||
|
||||
int UndoHistory::StartRedo() {
|
||||
// Drop any leading startAction
|
||||
if (actions[currentAction].at == startAction && currentAction < maxAction)
|
||||
currentAction++;
|
||||
|
||||
// Count the steps in this action
|
||||
int act = currentAction;
|
||||
while (actions[act].at != startAction && act < maxAction) {
|
||||
act++;
|
||||
}
|
||||
return act - currentAction;
|
||||
}
|
||||
|
||||
const Action &UndoHistory::GetRedoStep() const {
|
||||
return actions[currentAction];
|
||||
}
|
||||
|
||||
void UndoHistory::CompletedRedoStep() {
|
||||
currentAction++;
|
||||
}
|
||||
|
||||
CellBuffer::CellBuffer() {
|
||||
readOnly = false;
|
||||
utf8LineEnds = 0;
|
||||
collectingUndo = true;
|
||||
}
|
||||
|
||||
CellBuffer::~CellBuffer() {
|
||||
}
|
||||
|
||||
char CellBuffer::CharAt(int position) const {
|
||||
return substance.ValueAt(position);
|
||||
}
|
||||
|
||||
void CellBuffer::GetCharRange(char *buffer, int position, int lengthRetrieve) const {
|
||||
if (lengthRetrieve < 0)
|
||||
return;
|
||||
if (position < 0)
|
||||
return;
|
||||
if ((position + lengthRetrieve) > substance.Length()) {
|
||||
Platform::DebugPrintf("Bad GetCharRange %d for %d of %d\n", position,
|
||||
lengthRetrieve, substance.Length());
|
||||
return;
|
||||
}
|
||||
substance.GetRange(buffer, position, lengthRetrieve);
|
||||
}
|
||||
|
||||
char CellBuffer::StyleAt(int position) const {
|
||||
return style.ValueAt(position);
|
||||
}
|
||||
|
||||
void CellBuffer::GetStyleRange(unsigned char *buffer, int position, int lengthRetrieve) const {
|
||||
if (lengthRetrieve < 0)
|
||||
return;
|
||||
if (position < 0)
|
||||
return;
|
||||
if ((position + lengthRetrieve) > style.Length()) {
|
||||
Platform::DebugPrintf("Bad GetStyleRange %d for %d of %d\n", position,
|
||||
lengthRetrieve, style.Length());
|
||||
return;
|
||||
}
|
||||
style.GetRange(reinterpret_cast<char *>(buffer), position, lengthRetrieve);
|
||||
}
|
||||
|
||||
const char *CellBuffer::BufferPointer() {
|
||||
return substance.BufferPointer();
|
||||
}
|
||||
|
||||
const char *CellBuffer::RangePointer(int position, int rangeLength) {
|
||||
return substance.RangePointer(position, rangeLength);
|
||||
}
|
||||
|
||||
int CellBuffer::GapPosition() const {
|
||||
return substance.GapPosition();
|
||||
}
|
||||
|
||||
// The char* returned is to an allocation owned by the undo history
|
||||
const char *CellBuffer::InsertString(int position, const char *s, int insertLength, bool &startSequence) {
|
||||
// InsertString and DeleteChars are the bottleneck though which all changes occur
|
||||
const char *data = s;
|
||||
if (!readOnly) {
|
||||
if (collectingUndo) {
|
||||
// Save into the undo/redo stack, but only the characters - not the formatting
|
||||
// This takes up about half load time
|
||||
data = uh.AppendAction(insertAction, position, s, insertLength, startSequence);
|
||||
}
|
||||
|
||||
BasicInsertString(position, s, insertLength);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
bool CellBuffer::SetStyleAt(int position, char styleValue, char mask) {
|
||||
styleValue &= mask;
|
||||
char curVal = style.ValueAt(position);
|
||||
if ((curVal & mask) != styleValue) {
|
||||
style.SetValueAt(position, static_cast<char>((curVal & ~mask) | styleValue));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CellBuffer::SetStyleFor(int position, int lengthStyle, char styleValue, char mask) {
|
||||
bool changed = false;
|
||||
PLATFORM_ASSERT(lengthStyle == 0 ||
|
||||
(lengthStyle > 0 && lengthStyle + position <= style.Length()));
|
||||
while (lengthStyle--) {
|
||||
char curVal = style.ValueAt(position);
|
||||
if ((curVal & mask) != styleValue) {
|
||||
style.SetValueAt(position, static_cast<char>((curVal & ~mask) | styleValue));
|
||||
changed = true;
|
||||
}
|
||||
position++;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
// The char* returned is to an allocation owned by the undo history
|
||||
const char *CellBuffer::DeleteChars(int position, int deleteLength, bool &startSequence) {
|
||||
// InsertString and DeleteChars are the bottleneck though which all changes occur
|
||||
PLATFORM_ASSERT(deleteLength > 0);
|
||||
const char *data = 0;
|
||||
if (!readOnly) {
|
||||
if (collectingUndo) {
|
||||
// Save into the undo/redo stack, but only the characters - not the formatting
|
||||
// The gap would be moved to position anyway for the deletion so this doesn't cost extra
|
||||
data = substance.RangePointer(position, deleteLength);
|
||||
data = uh.AppendAction(removeAction, position, data, deleteLength, startSequence);
|
||||
}
|
||||
|
||||
BasicDeleteChars(position, deleteLength);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
int CellBuffer::Length() const {
|
||||
return substance.Length();
|
||||
}
|
||||
|
||||
void CellBuffer::Allocate(int newSize) {
|
||||
substance.ReAllocate(newSize);
|
||||
style.ReAllocate(newSize);
|
||||
}
|
||||
|
||||
void CellBuffer::SetLineEndTypes(int utf8LineEnds_) {
|
||||
if (utf8LineEnds != utf8LineEnds_) {
|
||||
utf8LineEnds = utf8LineEnds_;
|
||||
ResetLineEnds();
|
||||
}
|
||||
}
|
||||
|
||||
void CellBuffer::SetPerLine(PerLine *pl) {
|
||||
lv.SetPerLine(pl);
|
||||
}
|
||||
|
||||
int CellBuffer::Lines() const {
|
||||
return lv.Lines();
|
||||
}
|
||||
|
||||
int CellBuffer::LineStart(int line) const {
|
||||
if (line < 0)
|
||||
return 0;
|
||||
else if (line >= Lines())
|
||||
return Length();
|
||||
else
|
||||
return lv.LineStart(line);
|
||||
}
|
||||
|
||||
bool CellBuffer::IsReadOnly() const {
|
||||
return readOnly;
|
||||
}
|
||||
|
||||
void CellBuffer::SetReadOnly(bool set) {
|
||||
readOnly = set;
|
||||
}
|
||||
|
||||
void CellBuffer::SetSavePoint() {
|
||||
uh.SetSavePoint();
|
||||
}
|
||||
|
||||
bool CellBuffer::IsSavePoint() const {
|
||||
return uh.IsSavePoint();
|
||||
}
|
||||
|
||||
// Without undo
|
||||
|
||||
void CellBuffer::InsertLine(int line, int position, bool lineStart) {
|
||||
lv.InsertLine(line, position, lineStart);
|
||||
}
|
||||
|
||||
void CellBuffer::RemoveLine(int line) {
|
||||
lv.RemoveLine(line);
|
||||
}
|
||||
|
||||
bool CellBuffer::UTF8LineEndOverlaps(int position) const {
|
||||
unsigned char bytes[] = {
|
||||
static_cast<unsigned char>(substance.ValueAt(position-2)),
|
||||
static_cast<unsigned char>(substance.ValueAt(position-1)),
|
||||
static_cast<unsigned char>(substance.ValueAt(position)),
|
||||
static_cast<unsigned char>(substance.ValueAt(position+1)),
|
||||
};
|
||||
return UTF8IsSeparator(bytes) || UTF8IsSeparator(bytes+1) || UTF8IsNEL(bytes+1);
|
||||
}
|
||||
|
||||
void CellBuffer::ResetLineEnds() {
|
||||
// Reinitialize line data -- too much work to preserve
|
||||
lv.Init();
|
||||
|
||||
int position = 0;
|
||||
int length = Length();
|
||||
int lineInsert = 1;
|
||||
bool atLineStart = true;
|
||||
lv.InsertText(lineInsert-1, length);
|
||||
unsigned char chBeforePrev = 0;
|
||||
unsigned char chPrev = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
unsigned char ch = substance.ValueAt(position + i);
|
||||
if (ch == '\r') {
|
||||
InsertLine(lineInsert, (position + i) + 1, atLineStart);
|
||||
lineInsert++;
|
||||
} else if (ch == '\n') {
|
||||
if (chPrev == '\r') {
|
||||
// Patch up what was end of line
|
||||
lv.SetLineStart(lineInsert - 1, (position + i) + 1);
|
||||
} else {
|
||||
InsertLine(lineInsert, (position + i) + 1, atLineStart);
|
||||
lineInsert++;
|
||||
}
|
||||
} else if (utf8LineEnds) {
|
||||
unsigned char back3[3] = {chBeforePrev, chPrev, ch};
|
||||
if (UTF8IsSeparator(back3) || UTF8IsNEL(back3+1)) {
|
||||
InsertLine(lineInsert, (position + i) + 1, atLineStart);
|
||||
lineInsert++;
|
||||
}
|
||||
}
|
||||
chBeforePrev = chPrev;
|
||||
chPrev = ch;
|
||||
}
|
||||
}
|
||||
|
||||
void CellBuffer::BasicInsertString(int position, const char *s, int insertLength) {
|
||||
if (insertLength == 0)
|
||||
return;
|
||||
PLATFORM_ASSERT(insertLength > 0);
|
||||
|
||||
unsigned char chAfter = substance.ValueAt(position);
|
||||
bool breakingUTF8LineEnd = false;
|
||||
if (utf8LineEnds && UTF8IsTrailByte(chAfter)) {
|
||||
breakingUTF8LineEnd = UTF8LineEndOverlaps(position);
|
||||
}
|
||||
|
||||
substance.InsertFromArray(position, s, 0, insertLength);
|
||||
style.InsertValue(position, insertLength, 0);
|
||||
|
||||
int lineInsert = lv.LineFromPosition(position) + 1;
|
||||
bool atLineStart = lv.LineStart(lineInsert-1) == position;
|
||||
// Point all the lines after the insertion point further along in the buffer
|
||||
lv.InsertText(lineInsert-1, insertLength);
|
||||
unsigned char chBeforePrev = substance.ValueAt(position - 2);
|
||||
unsigned char chPrev = substance.ValueAt(position - 1);
|
||||
if (chPrev == '\r' && chAfter == '\n') {
|
||||
// Splitting up a crlf pair at position
|
||||
InsertLine(lineInsert, position, false);
|
||||
lineInsert++;
|
||||
}
|
||||
if (breakingUTF8LineEnd) {
|
||||
RemoveLine(lineInsert);
|
||||
}
|
||||
unsigned char ch = ' ';
|
||||
for (int i = 0; i < insertLength; i++) {
|
||||
ch = s[i];
|
||||
if (ch == '\r') {
|
||||
InsertLine(lineInsert, (position + i) + 1, atLineStart);
|
||||
lineInsert++;
|
||||
} else if (ch == '\n') {
|
||||
if (chPrev == '\r') {
|
||||
// Patch up what was end of line
|
||||
lv.SetLineStart(lineInsert - 1, (position + i) + 1);
|
||||
} else {
|
||||
InsertLine(lineInsert, (position + i) + 1, atLineStart);
|
||||
lineInsert++;
|
||||
}
|
||||
} else if (utf8LineEnds) {
|
||||
unsigned char back3[3] = {chBeforePrev, chPrev, ch};
|
||||
if (UTF8IsSeparator(back3) || UTF8IsNEL(back3+1)) {
|
||||
InsertLine(lineInsert, (position + i) + 1, atLineStart);
|
||||
lineInsert++;
|
||||
}
|
||||
}
|
||||
chBeforePrev = chPrev;
|
||||
chPrev = ch;
|
||||
}
|
||||
// Joining two lines where last insertion is cr and following substance starts with lf
|
||||
if (chAfter == '\n') {
|
||||
if (ch == '\r') {
|
||||
// End of line already in buffer so drop the newly created one
|
||||
RemoveLine(lineInsert - 1);
|
||||
}
|
||||
} else if (utf8LineEnds && !UTF8IsAscii(chAfter)) {
|
||||
// May have end of UTF-8 line end in buffer and start in insertion
|
||||
for (int j = 0; j < UTF8SeparatorLength-1; j++) {
|
||||
unsigned char chAt = substance.ValueAt(position + insertLength + j);
|
||||
unsigned char back3[3] = {chBeforePrev, chPrev, chAt};
|
||||
if (UTF8IsSeparator(back3)) {
|
||||
InsertLine(lineInsert, (position + insertLength + j) + 1, atLineStart);
|
||||
lineInsert++;
|
||||
}
|
||||
if ((j == 0) && UTF8IsNEL(back3+1)) {
|
||||
InsertLine(lineInsert, (position + insertLength + j) + 1, atLineStart);
|
||||
lineInsert++;
|
||||
}
|
||||
chBeforePrev = chPrev;
|
||||
chPrev = chAt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CellBuffer::BasicDeleteChars(int position, int deleteLength) {
|
||||
if (deleteLength == 0)
|
||||
return;
|
||||
|
||||
if ((position == 0) && (deleteLength == substance.Length())) {
|
||||
// If whole buffer is being deleted, faster to reinitialise lines data
|
||||
// than to delete each line.
|
||||
lv.Init();
|
||||
} else {
|
||||
// Have to fix up line positions before doing deletion as looking at text in buffer
|
||||
// to work out which lines have been removed
|
||||
|
||||
int lineRemove = lv.LineFromPosition(position) + 1;
|
||||
lv.InsertText(lineRemove-1, - (deleteLength));
|
||||
unsigned char chPrev = substance.ValueAt(position - 1);
|
||||
unsigned char chBefore = chPrev;
|
||||
unsigned char chNext = substance.ValueAt(position);
|
||||
bool ignoreNL = false;
|
||||
if (chPrev == '\r' && chNext == '\n') {
|
||||
// Move back one
|
||||
lv.SetLineStart(lineRemove, position);
|
||||
lineRemove++;
|
||||
ignoreNL = true; // First \n is not real deletion
|
||||
}
|
||||
if (utf8LineEnds && UTF8IsTrailByte(chNext)) {
|
||||
if (UTF8LineEndOverlaps(position)) {
|
||||
RemoveLine(lineRemove);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char ch = chNext;
|
||||
for (int i = 0; i < deleteLength; i++) {
|
||||
chNext = substance.ValueAt(position + i + 1);
|
||||
if (ch == '\r') {
|
||||
if (chNext != '\n') {
|
||||
RemoveLine(lineRemove);
|
||||
}
|
||||
} else if (ch == '\n') {
|
||||
if (ignoreNL) {
|
||||
ignoreNL = false; // Further \n are real deletions
|
||||
} else {
|
||||
RemoveLine(lineRemove);
|
||||
}
|
||||
} else if (utf8LineEnds) {
|
||||
if (!UTF8IsAscii(ch)) {
|
||||
unsigned char next3[3] = {ch, chNext,
|
||||
static_cast<unsigned char>(substance.ValueAt(position + i + 2))};
|
||||
if (UTF8IsSeparator(next3) || UTF8IsNEL(next3)) {
|
||||
RemoveLine(lineRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ch = chNext;
|
||||
}
|
||||
// May have to fix up end if last deletion causes cr to be next to lf
|
||||
// or removes one of a crlf pair
|
||||
char chAfter = substance.ValueAt(position + deleteLength);
|
||||
if (chBefore == '\r' && chAfter == '\n') {
|
||||
// Using lineRemove-1 as cr ended line before start of deletion
|
||||
RemoveLine(lineRemove - 1);
|
||||
lv.SetLineStart(lineRemove - 1, position + 1);
|
||||
}
|
||||
}
|
||||
substance.DeleteRange(position, deleteLength);
|
||||
style.DeleteRange(position, deleteLength);
|
||||
}
|
||||
|
||||
bool CellBuffer::SetUndoCollection(bool collectUndo) {
|
||||
collectingUndo = collectUndo;
|
||||
uh.DropUndoSequence();
|
||||
return collectingUndo;
|
||||
}
|
||||
|
||||
bool CellBuffer::IsCollectingUndo() const {
|
||||
return collectingUndo;
|
||||
}
|
||||
|
||||
void CellBuffer::BeginUndoAction() {
|
||||
uh.BeginUndoAction();
|
||||
}
|
||||
|
||||
void CellBuffer::EndUndoAction() {
|
||||
uh.EndUndoAction();
|
||||
}
|
||||
|
||||
void CellBuffer::AddUndoAction(int token, bool mayCoalesce) {
|
||||
bool startSequence;
|
||||
uh.AppendAction(containerAction, token, 0, 0, startSequence, mayCoalesce);
|
||||
}
|
||||
|
||||
void CellBuffer::DeleteUndoHistory() {
|
||||
uh.DeleteUndoHistory();
|
||||
}
|
||||
|
||||
bool CellBuffer::CanUndo() const {
|
||||
return uh.CanUndo();
|
||||
}
|
||||
|
||||
int CellBuffer::StartUndo() {
|
||||
return uh.StartUndo();
|
||||
}
|
||||
|
||||
const Action &CellBuffer::GetUndoStep() const {
|
||||
return uh.GetUndoStep();
|
||||
}
|
||||
|
||||
void CellBuffer::PerformUndoStep() {
|
||||
const Action &actionStep = uh.GetUndoStep();
|
||||
if (actionStep.at == insertAction) {
|
||||
BasicDeleteChars(actionStep.position, actionStep.lenData);
|
||||
} else if (actionStep.at == removeAction) {
|
||||
BasicInsertString(actionStep.position, actionStep.data, actionStep.lenData);
|
||||
}
|
||||
uh.CompletedUndoStep();
|
||||
}
|
||||
|
||||
bool CellBuffer::CanRedo() const {
|
||||
return uh.CanRedo();
|
||||
}
|
||||
|
||||
int CellBuffer::StartRedo() {
|
||||
return uh.StartRedo();
|
||||
}
|
||||
|
||||
const Action &CellBuffer::GetRedoStep() const {
|
||||
return uh.GetRedoStep();
|
||||
}
|
||||
|
||||
void CellBuffer::PerformRedoStep() {
|
||||
const Action &actionStep = uh.GetRedoStep();
|
||||
if (actionStep.at == insertAction) {
|
||||
BasicInsertString(actionStep.position, actionStep.data, actionStep.lenData);
|
||||
} else if (actionStep.at == removeAction) {
|
||||
BasicDeleteChars(actionStep.position, actionStep.lenData);
|
||||
}
|
||||
uh.CompletedRedoStep();
|
||||
}
|
||||
|
||||
222
third-party/scintilla/CellBuffer.h
vendored
Normal file
222
third-party/scintilla/CellBuffer.h
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file CellBuffer.h
|
||||
** Manages the text of the document.
|
||||
**/
|
||||
// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef CELLBUFFER_H
|
||||
#define CELLBUFFER_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
// Interface to per-line data that wants to see each line insertion and deletion
|
||||
class PerLine {
|
||||
public:
|
||||
virtual ~PerLine() {}
|
||||
virtual void Init()=0;
|
||||
virtual void InsertLine(int line)=0;
|
||||
virtual void RemoveLine(int line)=0;
|
||||
};
|
||||
|
||||
/**
|
||||
* The line vector contains information about each of the lines in a cell buffer.
|
||||
*/
|
||||
class LineVector {
|
||||
|
||||
Partitioning starts;
|
||||
PerLine *perLine;
|
||||
|
||||
public:
|
||||
|
||||
LineVector();
|
||||
~LineVector();
|
||||
void Init();
|
||||
void SetPerLine(PerLine *pl);
|
||||
|
||||
void InsertText(int line, int delta);
|
||||
void InsertLine(int line, int position, bool lineStart);
|
||||
void SetLineStart(int line, int position);
|
||||
void RemoveLine(int line);
|
||||
int Lines() const {
|
||||
return starts.Partitions();
|
||||
}
|
||||
int LineFromPosition(int pos) const;
|
||||
int LineStart(int line) const {
|
||||
return starts.PositionFromPartition(line);
|
||||
}
|
||||
|
||||
int MarkValue(int line);
|
||||
int AddMark(int line, int marker);
|
||||
void MergeMarkers(int pos);
|
||||
void DeleteMark(int line, int markerNum, bool all);
|
||||
void DeleteMarkFromHandle(int markerHandle);
|
||||
int LineFromHandle(int markerHandle);
|
||||
|
||||
void ClearLevels();
|
||||
int SetLevel(int line, int level);
|
||||
int GetLevel(int line);
|
||||
|
||||
int SetLineState(int line, int state);
|
||||
int GetLineState(int line);
|
||||
int GetMaxLineState();
|
||||
|
||||
};
|
||||
|
||||
enum actionType { insertAction, removeAction, startAction, containerAction };
|
||||
|
||||
/**
|
||||
* Actions are used to store all the information required to perform one undo/redo step.
|
||||
*/
|
||||
class Action {
|
||||
// no copy ctr or assignment op
|
||||
Action(const Action &);
|
||||
Action &operator =(const Action &);
|
||||
public:
|
||||
actionType at;
|
||||
int position;
|
||||
char *data;
|
||||
int lenData;
|
||||
bool mayCoalesce;
|
||||
|
||||
Action();
|
||||
~Action();
|
||||
void Create(actionType at_, int position_=0, const char *data_=0, int lenData_=0, bool mayCoalesce_=true);
|
||||
void Destroy();
|
||||
void Grab(Action *source);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class UndoHistory {
|
||||
Action *actions;
|
||||
int lenActions;
|
||||
int maxAction;
|
||||
int currentAction;
|
||||
int undoSequenceDepth;
|
||||
int savePoint;
|
||||
|
||||
void EnsureUndoRoom();
|
||||
|
||||
// no copy ctr or assignment op
|
||||
UndoHistory(const UndoHistory &);
|
||||
UndoHistory &operator =(const UndoHistory &);
|
||||
public:
|
||||
UndoHistory();
|
||||
~UndoHistory();
|
||||
|
||||
const char *AppendAction(actionType at, int position, const char *data, int length, bool &startSequence, bool mayCoalesce=true);
|
||||
|
||||
void BeginUndoAction();
|
||||
void EndUndoAction();
|
||||
void DropUndoSequence();
|
||||
void DeleteUndoHistory();
|
||||
|
||||
/// The save point is a marker in the undo stack where the container has stated that
|
||||
/// the buffer was saved. Undo and redo can move over the save point.
|
||||
void SetSavePoint();
|
||||
bool IsSavePoint() const;
|
||||
|
||||
/// To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is
|
||||
/// called that many times. Similarly for redo.
|
||||
bool CanUndo() const;
|
||||
int StartUndo();
|
||||
const Action &GetUndoStep() const;
|
||||
void CompletedUndoStep();
|
||||
bool CanRedo() const;
|
||||
int StartRedo();
|
||||
const Action &GetRedoStep() const;
|
||||
void CompletedRedoStep();
|
||||
};
|
||||
|
||||
/**
|
||||
* Holder for an expandable array of characters that supports undo and line markers.
|
||||
* Based on article "Data Structures in a Bit-Mapped Text Editor"
|
||||
* by Wilfred J. Hansen, Byte January 1987, page 183.
|
||||
*/
|
||||
class CellBuffer {
|
||||
private:
|
||||
SplitVector<char> substance;
|
||||
SplitVector<char> style;
|
||||
bool readOnly;
|
||||
int utf8LineEnds;
|
||||
|
||||
bool collectingUndo;
|
||||
UndoHistory uh;
|
||||
|
||||
LineVector lv;
|
||||
|
||||
bool UTF8LineEndOverlaps(int position) const;
|
||||
void ResetLineEnds();
|
||||
/// Actions without undo
|
||||
void BasicInsertString(int position, const char *s, int insertLength);
|
||||
void BasicDeleteChars(int position, int deleteLength);
|
||||
|
||||
public:
|
||||
|
||||
CellBuffer();
|
||||
~CellBuffer();
|
||||
|
||||
/// Retrieving positions outside the range of the buffer works and returns 0
|
||||
char CharAt(int position) const;
|
||||
void GetCharRange(char *buffer, int position, int lengthRetrieve) const;
|
||||
char StyleAt(int position) const;
|
||||
void GetStyleRange(unsigned char *buffer, int position, int lengthRetrieve) const;
|
||||
const char *BufferPointer();
|
||||
const char *RangePointer(int position, int rangeLength);
|
||||
int GapPosition() const;
|
||||
|
||||
int Length() const;
|
||||
void Allocate(int newSize);
|
||||
int GetLineEndTypes() const { return utf8LineEnds; }
|
||||
void SetLineEndTypes(int utf8LineEnds_);
|
||||
void SetPerLine(PerLine *pl);
|
||||
int Lines() const;
|
||||
int LineStart(int line) const;
|
||||
int LineFromPosition(int pos) const { return lv.LineFromPosition(pos); }
|
||||
void InsertLine(int line, int position, bool lineStart);
|
||||
void RemoveLine(int line);
|
||||
const char *InsertString(int position, const char *s, int insertLength, bool &startSequence);
|
||||
|
||||
/// Setting styles for positions outside the range of the buffer is safe and has no effect.
|
||||
/// @return true if the style of a character is changed.
|
||||
bool SetStyleAt(int position, char styleValue, char mask='\377');
|
||||
bool SetStyleFor(int position, int length, char styleValue, char mask);
|
||||
|
||||
const char *DeleteChars(int position, int deleteLength, bool &startSequence);
|
||||
|
||||
bool IsReadOnly() const;
|
||||
void SetReadOnly(bool set);
|
||||
|
||||
/// The save point is a marker in the undo stack where the container has stated that
|
||||
/// the buffer was saved. Undo and redo can move over the save point.
|
||||
void SetSavePoint();
|
||||
bool IsSavePoint() const;
|
||||
|
||||
bool SetUndoCollection(bool collectUndo);
|
||||
bool IsCollectingUndo() const;
|
||||
void BeginUndoAction();
|
||||
void EndUndoAction();
|
||||
void AddUndoAction(int token, bool mayCoalesce);
|
||||
void DeleteUndoHistory();
|
||||
|
||||
/// To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is
|
||||
/// called that many times. Similarly for redo.
|
||||
bool CanUndo() const;
|
||||
int StartUndo();
|
||||
const Action &GetUndoStep() const;
|
||||
void PerformUndoStep();
|
||||
bool CanRedo() const;
|
||||
int StartRedo();
|
||||
const Action &GetRedoStep() const;
|
||||
void PerformRedoStep();
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
61
third-party/scintilla/CharClassify.cxx
vendored
Normal file
61
third-party/scintilla/CharClassify.cxx
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file CharClassify.cxx
|
||||
** Character classifications used by Document and RESearch.
|
||||
**/
|
||||
// Copyright 2006 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "CharClassify.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
// Shut up annoying Visual C++ warnings:
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4514)
|
||||
#endif
|
||||
|
||||
CharClassify::CharClassify() {
|
||||
SetDefaultCharClasses(true);
|
||||
}
|
||||
|
||||
void CharClassify::SetDefaultCharClasses(bool includeWordClass) {
|
||||
// Initialize all char classes to default values
|
||||
for (int ch = 0; ch < 256; ch++) {
|
||||
if (ch == '\r' || ch == '\n')
|
||||
charClass[ch] = ccNewLine;
|
||||
else if (ch < 0x20 || ch == ' ')
|
||||
charClass[ch] = ccSpace;
|
||||
else if (includeWordClass && (ch >= 0x80 || isalnum(ch) || ch == '_'))
|
||||
charClass[ch] = ccWord;
|
||||
else
|
||||
charClass[ch] = ccPunctuation;
|
||||
}
|
||||
}
|
||||
|
||||
void CharClassify::SetCharClasses(const unsigned char *chars, cc newCharClass) {
|
||||
// Apply the newCharClass to the specifed chars
|
||||
if (chars) {
|
||||
while (*chars) {
|
||||
charClass[*chars] = static_cast<unsigned char>(newCharClass);
|
||||
chars++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CharClassify::GetCharsOfClass(cc characterClass, unsigned char *buffer) {
|
||||
// Get characters belonging to the given char class; return the number
|
||||
// of characters (if the buffer is NULL, don't write to it).
|
||||
int count = 0;
|
||||
for (int ch = maxChar - 1; ch >= 0; --ch) {
|
||||
if (charClass[ch] == characterClass) {
|
||||
++count;
|
||||
if (buffer) {
|
||||
*buffer = static_cast<unsigned char>(ch);
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
35
third-party/scintilla/CharClassify.h
vendored
Normal file
35
third-party/scintilla/CharClassify.h
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file CharClassify.h
|
||||
** Character classifications used by Document and RESearch.
|
||||
**/
|
||||
// Copyright 2006-2009 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef CHARCLASSIFY_H
|
||||
#define CHARCLASSIFY_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
class CharClassify {
|
||||
public:
|
||||
CharClassify();
|
||||
|
||||
enum cc { ccSpace, ccNewLine, ccWord, ccPunctuation };
|
||||
void SetDefaultCharClasses(bool includeWordClass);
|
||||
void SetCharClasses(const unsigned char *chars, cc newCharClass);
|
||||
int GetCharsOfClass(cc charClass, unsigned char *buffer);
|
||||
cc GetClass(unsigned char ch) const { return static_cast<cc>(charClass[ch]);}
|
||||
bool IsWord(unsigned char ch) const { return static_cast<cc>(charClass[ch]) == ccWord;}
|
||||
|
||||
private:
|
||||
enum { maxChar=256 };
|
||||
unsigned char charClass[maxChar]; // not type cc to save space
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
3302
third-party/scintilla/CharacterCategory.cxx
vendored
Normal file
3302
third-party/scintilla/CharacterCategory.cxx
vendored
Normal file
File diff suppressed because it is too large
Load Diff
31
third-party/scintilla/CharacterCategory.h
vendored
Normal file
31
third-party/scintilla/CharacterCategory.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file CharacterCategory.h
|
||||
** Returns the Unicode general category of a character.
|
||||
**/
|
||||
// Copyright 2013 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef CHARACTERCATEGORY_H
|
||||
#define CHARACTERCATEGORY_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
enum CharacterCategory {
|
||||
ccLu, ccLl, ccLt, ccLm, ccLo,
|
||||
ccMn, ccMc, ccMe,
|
||||
ccNd, ccNl, ccNo,
|
||||
ccPc, ccPd, ccPs, ccPe, ccPi, ccPf, ccPo,
|
||||
ccSm, ccSc, ccSk, ccSo,
|
||||
ccZs, ccZl, ccZp,
|
||||
ccCc, ccCf, ccCs, ccCo, ccCn
|
||||
};
|
||||
|
||||
CharacterCategory CategoriseCharacter(int character);
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
55
third-party/scintilla/CharacterSet.cxx
vendored
Normal file
55
third-party/scintilla/CharacterSet.cxx
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file CharacterSet.cxx
|
||||
** Simple case functions for ASCII.
|
||||
** Lexer infrastructure.
|
||||
**/
|
||||
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "CharacterSet.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
int CompareCaseInsensitive(const char *a, const char *b) {
|
||||
while (*a && *b) {
|
||||
if (*a != *b) {
|
||||
char upperA = MakeUpperCase(*a);
|
||||
char upperB = MakeUpperCase(*b);
|
||||
if (upperA != upperB)
|
||||
return upperA - upperB;
|
||||
}
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
// Either *a or *b is nul
|
||||
return *a - *b;
|
||||
}
|
||||
|
||||
int CompareNCaseInsensitive(const char *a, const char *b, size_t len) {
|
||||
while (*a && *b && len) {
|
||||
if (*a != *b) {
|
||||
char upperA = MakeUpperCase(*a);
|
||||
char upperB = MakeUpperCase(*b);
|
||||
if (upperA != upperB)
|
||||
return upperA - upperB;
|
||||
}
|
||||
a++;
|
||||
b++;
|
||||
len--;
|
||||
}
|
||||
if (len == 0)
|
||||
return 0;
|
||||
else
|
||||
// Either *a or *b is nul
|
||||
return *a - *b;
|
||||
}
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
177
third-party/scintilla/CharacterSet.h
vendored
Normal file
177
third-party/scintilla/CharacterSet.h
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file CharacterSet.h
|
||||
** Encapsulates a set of characters. Used to test if a character is within a set.
|
||||
**/
|
||||
// Copyright 2007 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef CHARACTERSET_H
|
||||
#define CHARACTERSET_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
class CharacterSet {
|
||||
int size;
|
||||
bool valueAfter;
|
||||
bool *bset;
|
||||
public:
|
||||
enum setBase {
|
||||
setNone=0,
|
||||
setLower=1,
|
||||
setUpper=2,
|
||||
setDigits=4,
|
||||
setAlpha=setLower|setUpper,
|
||||
setAlphaNum=setAlpha|setDigits
|
||||
};
|
||||
CharacterSet(setBase base=setNone, const char *initialSet="", int size_=0x80, bool valueAfter_=false) {
|
||||
size = size_;
|
||||
valueAfter = valueAfter_;
|
||||
bset = new bool[size];
|
||||
for (int i=0; i < size; i++) {
|
||||
bset[i] = false;
|
||||
}
|
||||
AddString(initialSet);
|
||||
if (base & setLower)
|
||||
AddString("abcdefghijklmnopqrstuvwxyz");
|
||||
if (base & setUpper)
|
||||
AddString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
if (base & setDigits)
|
||||
AddString("0123456789");
|
||||
}
|
||||
CharacterSet(const CharacterSet &other) {
|
||||
size = other.size;
|
||||
valueAfter = other.valueAfter;
|
||||
bset = new bool[size];
|
||||
for (int i=0; i < size; i++) {
|
||||
bset[i] = other.bset[i];
|
||||
}
|
||||
}
|
||||
~CharacterSet() {
|
||||
delete []bset;
|
||||
bset = 0;
|
||||
size = 0;
|
||||
}
|
||||
CharacterSet &operator=(const CharacterSet &other) {
|
||||
if (this != &other) {
|
||||
bool *bsetNew = new bool[other.size];
|
||||
for (int i=0; i < other.size; i++) {
|
||||
bsetNew[i] = other.bset[i];
|
||||
}
|
||||
delete []bset;
|
||||
size = other.size;
|
||||
valueAfter = other.valueAfter;
|
||||
bset = bsetNew;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
void Add(int val) {
|
||||
assert(val >= 0);
|
||||
assert(val < size);
|
||||
bset[val] = true;
|
||||
}
|
||||
void AddString(const char *setToAdd) {
|
||||
for (const char *cp=setToAdd; *cp; cp++) {
|
||||
int val = static_cast<unsigned char>(*cp);
|
||||
assert(val >= 0);
|
||||
assert(val < size);
|
||||
bset[val] = true;
|
||||
}
|
||||
}
|
||||
bool Contains(int val) const {
|
||||
assert(val >= 0);
|
||||
if (val < 0) return false;
|
||||
return (val < size) ? bset[val] : valueAfter;
|
||||
}
|
||||
};
|
||||
|
||||
// Functions for classifying characters
|
||||
|
||||
inline bool IsASpace(int ch) {
|
||||
return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
|
||||
}
|
||||
|
||||
inline bool IsASpaceOrTab(int ch) {
|
||||
return (ch == ' ') || (ch == '\t');
|
||||
}
|
||||
|
||||
inline bool IsADigit(int ch) {
|
||||
return (ch >= '0') && (ch <= '9');
|
||||
}
|
||||
|
||||
inline bool IsADigit(int ch, int base) {
|
||||
if (base <= 10) {
|
||||
return (ch >= '0') && (ch < '0' + base);
|
||||
} else {
|
||||
return ((ch >= '0') && (ch <= '9')) ||
|
||||
((ch >= 'A') && (ch < 'A' + base - 10)) ||
|
||||
((ch >= 'a') && (ch < 'a' + base - 10));
|
||||
}
|
||||
}
|
||||
|
||||
inline bool IsASCII(int ch) {
|
||||
return (ch >= 0) && (ch < 0x80);
|
||||
}
|
||||
|
||||
inline bool IsLowerCase(int ch) {
|
||||
return (ch >= 'a') && (ch <= 'z');
|
||||
}
|
||||
|
||||
inline bool IsUpperCase(int ch) {
|
||||
return (ch >= 'A') && (ch <= 'Z');
|
||||
}
|
||||
|
||||
inline bool IsAlphaNumeric(int ch) {
|
||||
return
|
||||
((ch >= '0') && (ch <= '9')) ||
|
||||
((ch >= 'a') && (ch <= 'z')) ||
|
||||
((ch >= 'A') && (ch <= 'Z'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a character is a space.
|
||||
* This is ASCII specific but is safe with chars >= 0x80.
|
||||
*/
|
||||
inline bool isspacechar(int ch) {
|
||||
return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
|
||||
}
|
||||
|
||||
inline bool iswordchar(int ch) {
|
||||
return IsAlphaNumeric(ch) || ch == '.' || ch == '_';
|
||||
}
|
||||
|
||||
inline bool iswordstart(int ch) {
|
||||
return IsAlphaNumeric(ch) || ch == '_';
|
||||
}
|
||||
|
||||
inline bool isoperator(int ch) {
|
||||
if (IsAlphaNumeric(ch))
|
||||
return false;
|
||||
if (ch == '%' || ch == '^' || ch == '&' || ch == '*' ||
|
||||
ch == '(' || ch == ')' || ch == '-' || ch == '+' ||
|
||||
ch == '=' || ch == '|' || ch == '{' || ch == '}' ||
|
||||
ch == '[' || ch == ']' || ch == ':' || ch == ';' ||
|
||||
ch == '<' || ch == '>' || ch == ',' || ch == '/' ||
|
||||
ch == '?' || ch == '!' || ch == '.' || ch == '~')
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Simple case functions for ASCII.
|
||||
|
||||
inline char MakeUpperCase(char ch) {
|
||||
if (ch < 'a' || ch > 'z')
|
||||
return ch;
|
||||
else
|
||||
return static_cast<char>(ch - 'a' + 'A');
|
||||
}
|
||||
|
||||
int CompareCaseInsensitive(const char *a, const char *b);
|
||||
int CompareNCaseInsensitive(const char *a, const char *b, size_t len);
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
280
third-party/scintilla/ContractionState.cxx
vendored
Normal file
280
third-party/scintilla/ContractionState.cxx
vendored
Normal file
@@ -0,0 +1,280 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file ContractionState.cxx
|
||||
** Manages visibility of lines for folding and wrapping.
|
||||
**/
|
||||
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "SplitVector.h"
|
||||
#include "Partitioning.h"
|
||||
#include "RunStyles.h"
|
||||
#include "ContractionState.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
ContractionState::ContractionState() : visible(0), expanded(0), heights(0), displayLines(0), linesInDocument(1) {
|
||||
//InsertLine(0);
|
||||
}
|
||||
|
||||
ContractionState::~ContractionState() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void ContractionState::EnsureData() {
|
||||
if (OneToOne()) {
|
||||
visible = new RunStyles();
|
||||
expanded = new RunStyles();
|
||||
heights = new RunStyles();
|
||||
displayLines = new Partitioning(4);
|
||||
InsertLines(0, linesInDocument);
|
||||
}
|
||||
}
|
||||
|
||||
void ContractionState::Clear() {
|
||||
delete visible;
|
||||
visible = 0;
|
||||
delete expanded;
|
||||
expanded = 0;
|
||||
delete heights;
|
||||
heights = 0;
|
||||
delete displayLines;
|
||||
displayLines = 0;
|
||||
linesInDocument = 1;
|
||||
}
|
||||
|
||||
int ContractionState::LinesInDoc() const {
|
||||
if (OneToOne()) {
|
||||
return linesInDocument;
|
||||
} else {
|
||||
return displayLines->Partitions() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
int ContractionState::LinesDisplayed() const {
|
||||
if (OneToOne()) {
|
||||
return linesInDocument;
|
||||
} else {
|
||||
return displayLines->PositionFromPartition(LinesInDoc());
|
||||
}
|
||||
}
|
||||
|
||||
int ContractionState::DisplayFromDoc(int lineDoc) const {
|
||||
if (OneToOne()) {
|
||||
return (lineDoc <= linesInDocument) ? lineDoc : linesInDocument;
|
||||
} else {
|
||||
if (lineDoc > displayLines->Partitions())
|
||||
lineDoc = displayLines->Partitions();
|
||||
return displayLines->PositionFromPartition(lineDoc);
|
||||
}
|
||||
}
|
||||
|
||||
int ContractionState::DisplayLastFromDoc(int lineDoc) const {
|
||||
return DisplayFromDoc(lineDoc) + GetHeight(lineDoc) - 1;
|
||||
}
|
||||
|
||||
int ContractionState::DocFromDisplay(int lineDisplay) const {
|
||||
if (OneToOne()) {
|
||||
return lineDisplay;
|
||||
} else {
|
||||
if (lineDisplay <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (lineDisplay > LinesDisplayed()) {
|
||||
return displayLines->PartitionFromPosition(LinesDisplayed());
|
||||
}
|
||||
int lineDoc = displayLines->PartitionFromPosition(lineDisplay);
|
||||
PLATFORM_ASSERT(GetVisible(lineDoc));
|
||||
return lineDoc;
|
||||
}
|
||||
}
|
||||
|
||||
void ContractionState::InsertLine(int lineDoc) {
|
||||
if (OneToOne()) {
|
||||
linesInDocument++;
|
||||
} else {
|
||||
visible->InsertSpace(lineDoc, 1);
|
||||
visible->SetValueAt(lineDoc, 1);
|
||||
expanded->InsertSpace(lineDoc, 1);
|
||||
expanded->SetValueAt(lineDoc, 1);
|
||||
heights->InsertSpace(lineDoc, 1);
|
||||
heights->SetValueAt(lineDoc, 1);
|
||||
int lineDisplay = DisplayFromDoc(lineDoc);
|
||||
displayLines->InsertPartition(lineDoc, lineDisplay);
|
||||
displayLines->InsertText(lineDoc, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ContractionState::InsertLines(int lineDoc, int lineCount) {
|
||||
for (int l = 0; l < lineCount; l++) {
|
||||
InsertLine(lineDoc + l);
|
||||
}
|
||||
Check();
|
||||
}
|
||||
|
||||
void ContractionState::DeleteLine(int lineDoc) {
|
||||
if (OneToOne()) {
|
||||
linesInDocument--;
|
||||
} else {
|
||||
if (GetVisible(lineDoc)) {
|
||||
displayLines->InsertText(lineDoc, -heights->ValueAt(lineDoc));
|
||||
}
|
||||
displayLines->RemovePartition(lineDoc);
|
||||
visible->DeleteRange(lineDoc, 1);
|
||||
expanded->DeleteRange(lineDoc, 1);
|
||||
heights->DeleteRange(lineDoc, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ContractionState::DeleteLines(int lineDoc, int lineCount) {
|
||||
for (int l = 0; l < lineCount; l++) {
|
||||
DeleteLine(lineDoc);
|
||||
}
|
||||
Check();
|
||||
}
|
||||
|
||||
bool ContractionState::GetVisible(int lineDoc) const {
|
||||
if (OneToOne()) {
|
||||
return true;
|
||||
} else {
|
||||
if (lineDoc >= visible->Length())
|
||||
return true;
|
||||
return visible->ValueAt(lineDoc) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible_) {
|
||||
if (OneToOne() && visible_) {
|
||||
return false;
|
||||
} else {
|
||||
EnsureData();
|
||||
int delta = 0;
|
||||
Check();
|
||||
if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < LinesInDoc())) {
|
||||
for (int line = lineDocStart; line <= lineDocEnd; line++) {
|
||||
if (GetVisible(line) != visible_) {
|
||||
int difference = visible_ ? heights->ValueAt(line) : -heights->ValueAt(line);
|
||||
visible->SetValueAt(line, visible_ ? 1 : 0);
|
||||
displayLines->InsertText(line, difference);
|
||||
delta += difference;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
Check();
|
||||
return delta != 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool ContractionState::HiddenLines() const {
|
||||
if (OneToOne()) {
|
||||
return false;
|
||||
} else {
|
||||
return !visible->AllSameAs(1);
|
||||
}
|
||||
}
|
||||
|
||||
bool ContractionState::GetExpanded(int lineDoc) const {
|
||||
if (OneToOne()) {
|
||||
return true;
|
||||
} else {
|
||||
Check();
|
||||
return expanded->ValueAt(lineDoc) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool ContractionState::SetExpanded(int lineDoc, bool expanded_) {
|
||||
if (OneToOne() && expanded_) {
|
||||
return false;
|
||||
} else {
|
||||
EnsureData();
|
||||
if (expanded_ != (expanded->ValueAt(lineDoc) == 1)) {
|
||||
expanded->SetValueAt(lineDoc, expanded_ ? 1 : 0);
|
||||
Check();
|
||||
return true;
|
||||
} else {
|
||||
Check();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ContractionState::ContractedNext(int lineDocStart) const {
|
||||
if (OneToOne()) {
|
||||
return -1;
|
||||
} else {
|
||||
Check();
|
||||
if (!expanded->ValueAt(lineDocStart)) {
|
||||
return lineDocStart;
|
||||
} else {
|
||||
int lineDocNextChange = expanded->EndRun(lineDocStart);
|
||||
if (lineDocNextChange < LinesInDoc())
|
||||
return lineDocNextChange;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ContractionState::GetHeight(int lineDoc) const {
|
||||
if (OneToOne()) {
|
||||
return 1;
|
||||
} else {
|
||||
return heights->ValueAt(lineDoc);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the number of display lines needed for this line.
|
||||
// Return true if this is a change.
|
||||
bool ContractionState::SetHeight(int lineDoc, int height) {
|
||||
if (OneToOne() && (height == 1)) {
|
||||
return false;
|
||||
} else if (lineDoc < LinesInDoc()) {
|
||||
EnsureData();
|
||||
if (GetHeight(lineDoc) != height) {
|
||||
if (GetVisible(lineDoc)) {
|
||||
displayLines->InsertText(lineDoc, height - GetHeight(lineDoc));
|
||||
}
|
||||
heights->SetValueAt(lineDoc, height);
|
||||
Check();
|
||||
return true;
|
||||
} else {
|
||||
Check();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ContractionState::ShowAll() {
|
||||
int lines = LinesInDoc();
|
||||
Clear();
|
||||
linesInDocument = lines;
|
||||
}
|
||||
|
||||
// Debugging checks
|
||||
|
||||
void ContractionState::Check() const {
|
||||
#ifdef CHECK_CORRECTNESS
|
||||
for (int vline = 0; vline < LinesDisplayed(); vline++) {
|
||||
const int lineDoc = DocFromDisplay(vline);
|
||||
PLATFORM_ASSERT(GetVisible(lineDoc));
|
||||
}
|
||||
for (int lineDoc = 0; lineDoc < LinesInDoc(); lineDoc++) {
|
||||
const int displayThis = DisplayFromDoc(lineDoc);
|
||||
const int displayNext = DisplayFromDoc(lineDoc + 1);
|
||||
const int height = displayNext - displayThis;
|
||||
PLATFORM_ASSERT(height >= 0);
|
||||
if (GetVisible(lineDoc)) {
|
||||
PLATFORM_ASSERT(GetHeight(lineDoc) == height);
|
||||
} else {
|
||||
PLATFORM_ASSERT(0 == height);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
73
third-party/scintilla/ContractionState.h
vendored
Normal file
73
third-party/scintilla/ContractionState.h
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file ContractionState.h
|
||||
** Manages visibility of lines for folding and wrapping.
|
||||
**/
|
||||
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef CONTRACTIONSTATE_H
|
||||
#define CONTRACTIONSTATE_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
/**
|
||||
*/
|
||||
class ContractionState {
|
||||
// These contain 1 element for every document line.
|
||||
RunStyles *visible;
|
||||
RunStyles *expanded;
|
||||
RunStyles *heights;
|
||||
Partitioning *displayLines;
|
||||
int linesInDocument;
|
||||
|
||||
void EnsureData();
|
||||
|
||||
bool OneToOne() const {
|
||||
// True when each document line is exactly one display line so need for
|
||||
// complex data structures.
|
||||
return visible == 0;
|
||||
}
|
||||
|
||||
// no copy ctr or assignment op
|
||||
ContractionState(const ContractionState &);
|
||||
ContractionState &operator =(const ContractionState &);
|
||||
|
||||
public:
|
||||
ContractionState();
|
||||
virtual ~ContractionState();
|
||||
|
||||
void Clear();
|
||||
|
||||
int LinesInDoc() const;
|
||||
int LinesDisplayed() const;
|
||||
int DisplayFromDoc(int lineDoc) const;
|
||||
int DisplayLastFromDoc(int lineDoc) const;
|
||||
int DocFromDisplay(int lineDisplay) const;
|
||||
|
||||
void InsertLine(int lineDoc);
|
||||
void InsertLines(int lineDoc, int lineCount);
|
||||
void DeleteLine(int lineDoc);
|
||||
void DeleteLines(int lineDoc, int lineCount);
|
||||
|
||||
bool GetVisible(int lineDoc) const;
|
||||
bool SetVisible(int lineDocStart, int lineDocEnd, bool visible);
|
||||
bool HiddenLines() const;
|
||||
|
||||
bool GetExpanded(int lineDoc) const;
|
||||
bool SetExpanded(int lineDoc, bool expanded);
|
||||
int ContractedNext(int lineDocStart) const;
|
||||
|
||||
int GetHeight(int lineDoc) const;
|
||||
bool SetHeight(int lineDoc, int height);
|
||||
|
||||
void ShowAll();
|
||||
void Check() const;
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
187
third-party/scintilla/Decoration.cxx
vendored
Normal file
187
third-party/scintilla/Decoration.cxx
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
/** @file Decoration.cxx
|
||||
** Visual elements added over text.
|
||||
**/
|
||||
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
#include "SplitVector.h"
|
||||
#include "Partitioning.h"
|
||||
#include "RunStyles.h"
|
||||
#include "Decoration.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
Decoration::Decoration(int indicator_) : next(0), indicator(indicator_) {
|
||||
}
|
||||
|
||||
Decoration::~Decoration() {
|
||||
}
|
||||
|
||||
bool Decoration::Empty() const {
|
||||
return (rs.Runs() == 1) && (rs.AllSameAs(0));
|
||||
}
|
||||
|
||||
DecorationList::DecorationList() : currentIndicator(0), currentValue(1), current(0),
|
||||
lengthDocument(0), root(0), clickNotified(false) {
|
||||
}
|
||||
|
||||
DecorationList::~DecorationList() {
|
||||
Decoration *deco = root;
|
||||
while (deco) {
|
||||
Decoration *decoNext = deco->next;
|
||||
delete deco;
|
||||
deco = decoNext;
|
||||
}
|
||||
root = 0;
|
||||
current = 0;
|
||||
}
|
||||
|
||||
Decoration *DecorationList::DecorationFromIndicator(int indicator) {
|
||||
for (Decoration *deco=root; deco; deco = deco->next) {
|
||||
if (deco->indicator == indicator) {
|
||||
return deco;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Decoration *DecorationList::Create(int indicator, int length) {
|
||||
currentIndicator = indicator;
|
||||
Decoration *decoNew = new Decoration(indicator);
|
||||
decoNew->rs.InsertSpace(0, length);
|
||||
|
||||
Decoration *decoPrev = 0;
|
||||
Decoration *deco = root;
|
||||
|
||||
while (deco && (deco->indicator < indicator)) {
|
||||
decoPrev = deco;
|
||||
deco = deco->next;
|
||||
}
|
||||
if (decoPrev == 0) {
|
||||
decoNew->next = root;
|
||||
root = decoNew;
|
||||
} else {
|
||||
decoNew->next = deco;
|
||||
decoPrev->next = decoNew;
|
||||
}
|
||||
return decoNew;
|
||||
}
|
||||
|
||||
void DecorationList::Delete(int indicator) {
|
||||
Decoration *decoToDelete = 0;
|
||||
if (root) {
|
||||
if (root->indicator == indicator) {
|
||||
decoToDelete = root;
|
||||
root = root->next;
|
||||
} else {
|
||||
Decoration *deco=root;
|
||||
while (deco->next && !decoToDelete) {
|
||||
if (deco->next && deco->next->indicator == indicator) {
|
||||
decoToDelete = deco->next;
|
||||
deco->next = decoToDelete->next;
|
||||
} else {
|
||||
deco = deco->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (decoToDelete) {
|
||||
delete decoToDelete;
|
||||
current = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DecorationList::SetCurrentIndicator(int indicator) {
|
||||
currentIndicator = indicator;
|
||||
current = DecorationFromIndicator(indicator);
|
||||
currentValue = 1;
|
||||
}
|
||||
|
||||
void DecorationList::SetCurrentValue(int value) {
|
||||
currentValue = value ? value : 1;
|
||||
}
|
||||
|
||||
bool DecorationList::FillRange(int &position, int value, int &fillLength) {
|
||||
if (!current) {
|
||||
current = DecorationFromIndicator(currentIndicator);
|
||||
if (!current) {
|
||||
current = Create(currentIndicator, lengthDocument);
|
||||
}
|
||||
}
|
||||
bool changed = current->rs.FillRange(position, value, fillLength);
|
||||
if (current->Empty()) {
|
||||
Delete(currentIndicator);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
void DecorationList::InsertSpace(int position, int insertLength) {
|
||||
const bool atEnd = position == lengthDocument;
|
||||
lengthDocument += insertLength;
|
||||
for (Decoration *deco=root; deco; deco = deco->next) {
|
||||
deco->rs.InsertSpace(position, insertLength);
|
||||
if (atEnd) {
|
||||
deco->rs.FillRange(position, 0, insertLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DecorationList::DeleteRange(int position, int deleteLength) {
|
||||
lengthDocument -= deleteLength;
|
||||
Decoration *deco;
|
||||
for (deco=root; deco; deco = deco->next) {
|
||||
deco->rs.DeleteRange(position, deleteLength);
|
||||
}
|
||||
DeleteAnyEmpty();
|
||||
}
|
||||
|
||||
void DecorationList::DeleteAnyEmpty() {
|
||||
Decoration *deco = root;
|
||||
while (deco) {
|
||||
if ((lengthDocument == 0) || deco->Empty()) {
|
||||
Delete(deco->indicator);
|
||||
deco = root;
|
||||
} else {
|
||||
deco = deco->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
int DecorationList::ValueAt(int indicator, int position) {
|
||||
Decoration *deco = DecorationFromIndicator(indicator);
|
||||
if (deco) {
|
||||
return deco->rs.ValueAt(position);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DecorationList::Start(int indicator, int position) {
|
||||
Decoration *deco = DecorationFromIndicator(indicator);
|
||||
if (deco) {
|
||||
return deco->rs.StartRun(position);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int DecorationList::End(int indicator, int position) {
|
||||
Decoration *deco = DecorationFromIndicator(indicator);
|
||||
if (deco) {
|
||||
return deco->rs.EndRun(position);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
68
third-party/scintilla/Decoration.h
vendored
Normal file
68
third-party/scintilla/Decoration.h
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
/** @file Decoration.h
|
||||
** Visual elements added over text.
|
||||
**/
|
||||
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef DECORATION_H
|
||||
#define DECORATION_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
class Decoration {
|
||||
public:
|
||||
Decoration *next;
|
||||
RunStyles rs;
|
||||
int indicator;
|
||||
|
||||
explicit Decoration(int indicator_);
|
||||
~Decoration();
|
||||
|
||||
bool Empty() const;
|
||||
};
|
||||
|
||||
class DecorationList {
|
||||
int currentIndicator;
|
||||
int currentValue;
|
||||
Decoration *current;
|
||||
int lengthDocument;
|
||||
Decoration *DecorationFromIndicator(int indicator);
|
||||
Decoration *Create(int indicator, int length);
|
||||
void Delete(int indicator);
|
||||
void DeleteAnyEmpty();
|
||||
|
||||
// no copy ctr or assignment op
|
||||
DecorationList(const DecorationList &);
|
||||
DecorationList &operator =(const DecorationList &);
|
||||
public:
|
||||
Decoration *root;
|
||||
bool clickNotified;
|
||||
|
||||
DecorationList();
|
||||
~DecorationList();
|
||||
|
||||
void SetCurrentIndicator(int indicator);
|
||||
int GetCurrentIndicator() const { return currentIndicator; }
|
||||
|
||||
void SetCurrentValue(int value);
|
||||
int GetCurrentValue() const { return currentValue; }
|
||||
|
||||
// Returns true if some values may have changed
|
||||
bool FillRange(int &position, int value, int &fillLength);
|
||||
|
||||
void InsertSpace(int position, int insertLength);
|
||||
void DeleteRange(int position, int deleteLength);
|
||||
|
||||
int AllOnFor(int position) const;
|
||||
int ValueAt(int indicator, int position);
|
||||
int Start(int indicator, int position);
|
||||
int End(int indicator, int position);
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
2305
third-party/scintilla/Document.cxx
vendored
Normal file
2305
third-party/scintilla/Document.cxx
vendored
Normal file
File diff suppressed because it is too large
Load Diff
517
third-party/scintilla/Document.h
vendored
Normal file
517
third-party/scintilla/Document.h
vendored
Normal file
@@ -0,0 +1,517 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file Document.h
|
||||
** Text document that handles notifications, DBCS, styling, words and end of line.
|
||||
**/
|
||||
// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef DOCUMENT_H
|
||||
#define DOCUMENT_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A Position is a position within a document between two characters or at the beginning or end.
|
||||
* Sometimes used as a character index where it identifies the character after the position.
|
||||
*/
|
||||
typedef int Position;
|
||||
const Position invalidPosition = -1;
|
||||
|
||||
enum EncodingFamily { efEightBit, efUnicode, efDBCS };
|
||||
|
||||
/**
|
||||
* The range class represents a range of text in a document.
|
||||
* The two values are not sorted as one end may be more significant than the other
|
||||
* as is the case for the selection where the end position is the position of the caret.
|
||||
* If either position is invalidPosition then the range is invalid and most operations will fail.
|
||||
*/
|
||||
class Range {
|
||||
public:
|
||||
Position start;
|
||||
Position end;
|
||||
|
||||
explicit Range(Position pos=0) :
|
||||
start(pos), end(pos) {
|
||||
}
|
||||
Range(Position start_, Position end_) :
|
||||
start(start_), end(end_) {
|
||||
}
|
||||
|
||||
bool Valid() const {
|
||||
return (start != invalidPosition) && (end != invalidPosition);
|
||||
}
|
||||
|
||||
Position First() const {
|
||||
return (start <= end) ? start : end;
|
||||
}
|
||||
|
||||
Position Last() const {
|
||||
return (start > end) ? start : end;
|
||||
}
|
||||
|
||||
// Is the position within the range?
|
||||
bool Contains(Position pos) const {
|
||||
if (start < end) {
|
||||
return (pos >= start && pos <= end);
|
||||
} else {
|
||||
return (pos <= start && pos >= end);
|
||||
}
|
||||
}
|
||||
|
||||
// Is the character after pos within the range?
|
||||
bool ContainsCharacter(Position pos) const {
|
||||
if (start < end) {
|
||||
return (pos >= start && pos < end);
|
||||
} else {
|
||||
return (pos < start && pos >= end);
|
||||
}
|
||||
}
|
||||
|
||||
bool Contains(Range other) const {
|
||||
return Contains(other.start) && Contains(other.end);
|
||||
}
|
||||
|
||||
bool Overlaps(Range other) const {
|
||||
return
|
||||
Contains(other.start) ||
|
||||
Contains(other.end) ||
|
||||
other.Contains(start) ||
|
||||
other.Contains(end);
|
||||
}
|
||||
};
|
||||
|
||||
class DocWatcher;
|
||||
class DocModification;
|
||||
class Document;
|
||||
|
||||
/**
|
||||
* Interface class for regular expression searching
|
||||
*/
|
||||
class RegexSearchBase {
|
||||
public:
|
||||
virtual ~RegexSearchBase() {}
|
||||
|
||||
virtual long FindText(Document *doc, int minPos, int maxPos, const char *s,
|
||||
bool caseSensitive, bool word, bool wordStart, int flags, int *length) = 0;
|
||||
|
||||
///@return String with the substitutions, must remain valid until the next call or destruction
|
||||
virtual const char *SubstituteByPosition(Document *doc, const char *text, int *length) = 0;
|
||||
};
|
||||
|
||||
/// Factory function for RegexSearchBase
|
||||
extern RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable);
|
||||
|
||||
struct StyledText {
|
||||
size_t length;
|
||||
const char *text;
|
||||
bool multipleStyles;
|
||||
size_t style;
|
||||
const unsigned char *styles;
|
||||
StyledText(size_t length_, const char *text_, bool multipleStyles_, int style_, const unsigned char *styles_) :
|
||||
length(length_), text(text_), multipleStyles(multipleStyles_), style(style_), styles(styles_) {
|
||||
}
|
||||
// Return number of bytes from start to before '\n' or end of text.
|
||||
// Return 1 when start is outside text
|
||||
size_t LineLength(size_t start) const {
|
||||
size_t cur = start;
|
||||
while ((cur < length) && (text[cur] != '\n'))
|
||||
cur++;
|
||||
return cur-start;
|
||||
}
|
||||
size_t StyleAt(size_t i) const {
|
||||
return multipleStyles ? styles[i] : style;
|
||||
}
|
||||
};
|
||||
|
||||
class HighlightDelimiter {
|
||||
public:
|
||||
HighlightDelimiter() : isEnabled(false) {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
beginFoldBlock = -1;
|
||||
endFoldBlock = -1;
|
||||
firstChangeableLineBefore = -1;
|
||||
firstChangeableLineAfter = -1;
|
||||
}
|
||||
|
||||
bool NeedsDrawing(int line) const {
|
||||
return isEnabled && (line <= firstChangeableLineBefore || line >= firstChangeableLineAfter);
|
||||
}
|
||||
|
||||
bool IsFoldBlockHighlighted(int line) const {
|
||||
return isEnabled && beginFoldBlock != -1 && beginFoldBlock <= line && line <= endFoldBlock;
|
||||
}
|
||||
|
||||
bool IsHeadOfFoldBlock(int line) const {
|
||||
return beginFoldBlock == line && line < endFoldBlock;
|
||||
}
|
||||
|
||||
bool IsBodyOfFoldBlock(int line) const {
|
||||
return beginFoldBlock != -1 && beginFoldBlock < line && line < endFoldBlock;
|
||||
}
|
||||
|
||||
bool IsTailOfFoldBlock(int line) const {
|
||||
return beginFoldBlock != -1 && beginFoldBlock < line && line == endFoldBlock;
|
||||
}
|
||||
|
||||
int beginFoldBlock; // Begin of current fold block
|
||||
int endFoldBlock; // End of current fold block
|
||||
int firstChangeableLineBefore; // First line that triggers repaint before starting line that determined current fold block
|
||||
int firstChangeableLineAfter; // First line that triggers repaint after starting line that determined current fold block
|
||||
bool isEnabled;
|
||||
};
|
||||
|
||||
class Document;
|
||||
|
||||
class LexInterface {
|
||||
protected:
|
||||
Document *pdoc;
|
||||
ILexer *instance;
|
||||
bool performingStyle; ///< Prevent reentrance
|
||||
public:
|
||||
explicit LexInterface(Document *pdoc_) : pdoc(pdoc_), instance(0), performingStyle(false) {
|
||||
}
|
||||
virtual ~LexInterface() {
|
||||
}
|
||||
void Colourise(int start, int end);
|
||||
int LineEndTypesSupported();
|
||||
bool UseContainerLexing() const {
|
||||
return instance == 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class Document : PerLine, public IDocumentWithLineEnd, public ILoader {
|
||||
|
||||
public:
|
||||
/** Used to pair watcher pointer with user data. */
|
||||
struct WatcherWithUserData {
|
||||
DocWatcher *watcher;
|
||||
void *userData;
|
||||
WatcherWithUserData(DocWatcher *watcher_=0, void *userData_=0) :
|
||||
watcher(watcher_), userData(userData_) {
|
||||
}
|
||||
bool operator==(const WatcherWithUserData &other) const {
|
||||
return (watcher == other.watcher) && (userData == other.userData);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
int refCount;
|
||||
CellBuffer cb;
|
||||
CharClassify charClass;
|
||||
CaseFolder *pcf;
|
||||
char stylingMask;
|
||||
int endStyled;
|
||||
int styleClock;
|
||||
int enteredModification;
|
||||
int enteredStyling;
|
||||
int enteredReadOnlyCount;
|
||||
|
||||
bool insertionSet;
|
||||
std::string insertion;
|
||||
std::vector<WatcherWithUserData> watchers;
|
||||
|
||||
// ldSize is not real data - it is for dimensions and loops
|
||||
enum lineData { ldMarkers, ldLevels, ldState, ldMargin, ldAnnotation, ldSize };
|
||||
PerLine *perLineData[ldSize];
|
||||
|
||||
bool matchesValid;
|
||||
RegexSearchBase *regex;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
Document(const Document &);
|
||||
Document &operator =(const Document &);
|
||||
|
||||
public:
|
||||
|
||||
LexInterface *pli;
|
||||
|
||||
int stylingBits;
|
||||
int stylingBitsMask;
|
||||
|
||||
int eolMode;
|
||||
/// Can also be SC_CP_UTF8 to enable UTF-8 mode
|
||||
int dbcsCodePage;
|
||||
int lineEndBitSet;
|
||||
int tabInChars;
|
||||
int indentInChars;
|
||||
int actualIndentInChars;
|
||||
bool useTabs;
|
||||
bool tabIndents;
|
||||
bool backspaceUnindents;
|
||||
|
||||
DecorationList decorations;
|
||||
|
||||
Document();
|
||||
virtual ~Document();
|
||||
|
||||
int AddRef();
|
||||
int SCI_METHOD Release();
|
||||
|
||||
virtual void Init();
|
||||
int LineEndTypesSupported() const;
|
||||
bool SetDBCSCodePage(int dbcsCodePage_);
|
||||
int GetLineEndTypesAllowed() const { return cb.GetLineEndTypes(); }
|
||||
bool SetLineEndTypesAllowed(int lineEndBitSet_);
|
||||
int GetLineEndTypesActive() const { return cb.GetLineEndTypes(); }
|
||||
virtual void InsertLine(int line);
|
||||
virtual void RemoveLine(int line);
|
||||
|
||||
int SCI_METHOD Version() const {
|
||||
return dvLineEnd;
|
||||
}
|
||||
|
||||
void SCI_METHOD SetErrorStatus(int status);
|
||||
|
||||
int SCI_METHOD LineFromPosition(int pos) const;
|
||||
int ClampPositionIntoDocument(int pos) const;
|
||||
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 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;
|
||||
int SCI_METHOD GetCharacterAndWidth(int position, int *pWidth) const;
|
||||
int SCI_METHOD CodePage() const;
|
||||
bool SCI_METHOD IsDBCSLeadByte(char ch) const;
|
||||
int SafeSegment(const char *text, int length, int lengthSegment) const;
|
||||
EncodingFamily CodePageFamily() const;
|
||||
|
||||
// Gateways to modifying document
|
||||
void ModifiedAt(int pos);
|
||||
void CheckReadOnly();
|
||||
bool DeleteChars(int pos, int len);
|
||||
int InsertString(int position, const char *s, int insertLength);
|
||||
void ChangeInsertion(const char *s, int length);
|
||||
int SCI_METHOD AddData(char *data, int length);
|
||||
void * SCI_METHOD ConvertToDocument();
|
||||
int Undo();
|
||||
int Redo();
|
||||
bool CanUndo() const { return cb.CanUndo(); }
|
||||
bool CanRedo() const { return cb.CanRedo(); }
|
||||
void DeleteUndoHistory() { cb.DeleteUndoHistory(); }
|
||||
bool SetUndoCollection(bool collectUndo) {
|
||||
return cb.SetUndoCollection(collectUndo);
|
||||
}
|
||||
bool IsCollectingUndo() const { return cb.IsCollectingUndo(); }
|
||||
void BeginUndoAction() { cb.BeginUndoAction(); }
|
||||
void EndUndoAction() { cb.EndUndoAction(); }
|
||||
void AddUndoAction(int token, bool mayCoalesce) { cb.AddUndoAction(token, mayCoalesce); }
|
||||
void SetSavePoint();
|
||||
bool IsSavePoint() const { return cb.IsSavePoint(); }
|
||||
const char * SCI_METHOD BufferPointer() { return cb.BufferPointer(); }
|
||||
const char *RangePointer(int position, int rangeLength) { return cb.RangePointer(position, rangeLength); }
|
||||
int GapPosition() const { return cb.GapPosition(); }
|
||||
|
||||
int SCI_METHOD GetLineIndentation(int line);
|
||||
int SetLineIndentation(int line, int indent);
|
||||
int GetLineIndentPosition(int line) const;
|
||||
int GetColumn(int position);
|
||||
int CountCharacters(int startPos, int endPos);
|
||||
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);
|
||||
void ConvertLineEnds(int eolModeSet);
|
||||
void SetReadOnly(bool set) { cb.SetReadOnly(set); }
|
||||
bool IsReadOnly() const { return cb.IsReadOnly(); }
|
||||
|
||||
void DelChar(int pos);
|
||||
void DelCharBack(int pos);
|
||||
|
||||
char CharAt(int position) const { return cb.CharAt(position); }
|
||||
void SCI_METHOD GetCharRange(char *buffer, int position, int lengthRetrieve) const {
|
||||
cb.GetCharRange(buffer, position, lengthRetrieve);
|
||||
}
|
||||
char SCI_METHOD StyleAt(int position) const { return cb.StyleAt(position); }
|
||||
void GetStyleRange(unsigned char *buffer, int position, int lengthRetrieve) const {
|
||||
cb.GetStyleRange(buffer, position, lengthRetrieve);
|
||||
}
|
||||
int GetMark(int line);
|
||||
int MarkerNext(int lineStart, int mask) const;
|
||||
int AddMark(int line, int markerNum);
|
||||
void AddMarkSet(int line, int valueSet);
|
||||
void DeleteMark(int line, int markerNum);
|
||||
void DeleteMarkFromHandle(int markerHandle);
|
||||
void DeleteAllMarks(int markerNum);
|
||||
int LineFromHandle(int markerHandle);
|
||||
int SCI_METHOD LineStart(int line) const;
|
||||
int SCI_METHOD LineEnd(int line) const;
|
||||
int LineEndPosition(int position) const;
|
||||
bool IsLineEndPosition(int position) const;
|
||||
bool IsPositionInLineEnd(int position) const;
|
||||
int VCHomePosition(int position) const;
|
||||
|
||||
int SCI_METHOD SetLevel(int line, int level);
|
||||
int SCI_METHOD GetLevel(int line) const;
|
||||
void ClearLevels();
|
||||
int GetLastChild(int lineParent, int level=-1, int lastLine=-1);
|
||||
int GetFoldParent(int line) const;
|
||||
void GetHighlightDelimiters(HighlightDelimiter &hDelimiter, int line, int lastLine);
|
||||
|
||||
void Indent(bool forwards);
|
||||
int ExtendWordSelect(int pos, int delta, bool onlyWordCharacters=false);
|
||||
int NextWordStart(int pos, int delta);
|
||||
int NextWordEnd(int pos, int delta);
|
||||
int SCI_METHOD Length() const { return cb.Length(); }
|
||||
void Allocate(int newSize) { cb.Allocate(newSize); }
|
||||
bool MatchesWordOptions(bool word, bool wordStart, int pos, int length) const;
|
||||
bool HasCaseFolder(void) const;
|
||||
void SetCaseFolder(CaseFolder *pcf_);
|
||||
long FindText(int minPos, int maxPos, const char *search, bool caseSensitive, bool word,
|
||||
bool wordStart, bool regExp, int flags, int *length);
|
||||
const char *SubstituteByPosition(const char *text, int *length);
|
||||
int LinesTotal() const;
|
||||
|
||||
void SetDefaultCharClasses(bool includeWordClass);
|
||||
void SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass);
|
||||
int GetCharsOfClass(CharClassify::cc charClass, unsigned char *buffer);
|
||||
void SetStylingBits(int bits);
|
||||
void SCI_METHOD StartStyling(int position, char mask);
|
||||
bool SCI_METHOD SetStyleFor(int length, char style);
|
||||
bool SCI_METHOD SetStyles(int length, const char *styles);
|
||||
int GetEndStyled() const { return endStyled; }
|
||||
void EnsureStyledTo(int pos);
|
||||
void LexerChanged();
|
||||
int GetStyleClock() const { return styleClock; }
|
||||
void IncrementStyleClock();
|
||||
void SCI_METHOD DecorationSetCurrentIndicator(int indicator) {
|
||||
decorations.SetCurrentIndicator(indicator);
|
||||
}
|
||||
void SCI_METHOD DecorationFillRange(int position, int value, int fillLength);
|
||||
|
||||
int SCI_METHOD SetLineState(int line, int state);
|
||||
int SCI_METHOD GetLineState(int line) const;
|
||||
int GetMaxLineState();
|
||||
void SCI_METHOD ChangeLexerState(int start, int end);
|
||||
|
||||
StyledText MarginStyledText(int line) const;
|
||||
void MarginSetStyle(int line, int style);
|
||||
void MarginSetStyles(int line, const unsigned char *styles);
|
||||
void MarginSetText(int line, const char *text);
|
||||
void MarginClearAll();
|
||||
|
||||
StyledText AnnotationStyledText(int line) const;
|
||||
void AnnotationSetText(int line, const char *text);
|
||||
void AnnotationSetStyle(int line, int style);
|
||||
void AnnotationSetStyles(int line, const unsigned char *styles);
|
||||
int AnnotationLines(int line) const;
|
||||
void AnnotationClearAll();
|
||||
|
||||
bool AddWatcher(DocWatcher *watcher, void *userData);
|
||||
bool RemoveWatcher(DocWatcher *watcher, void *userData);
|
||||
|
||||
CharClassify::cc WordCharClass(unsigned char ch) const;
|
||||
bool IsWordPartSeparator(char ch) const;
|
||||
int WordPartLeft(int pos);
|
||||
int WordPartRight(int pos);
|
||||
int ExtendStyleRange(int pos, int delta, bool singleLine = false);
|
||||
bool IsWhiteLine(int line) const;
|
||||
int ParaUp(int pos) const;
|
||||
int ParaDown(int pos) const;
|
||||
int IndentSize() const { return actualIndentInChars; }
|
||||
int BraceMatch(int position, int maxReStyle);
|
||||
|
||||
private:
|
||||
bool IsWordStartAt(int pos) const;
|
||||
bool IsWordEndAt(int pos) const;
|
||||
bool IsWordAt(int start, int end) const;
|
||||
|
||||
void NotifyModifyAttempt();
|
||||
void NotifySavePoint(bool atSavePoint);
|
||||
void NotifyModified(DocModification mh);
|
||||
};
|
||||
|
||||
class UndoGroup {
|
||||
Document *pdoc;
|
||||
bool groupNeeded;
|
||||
public:
|
||||
UndoGroup(Document *pdoc_, bool groupNeeded_=true) :
|
||||
pdoc(pdoc_), groupNeeded(groupNeeded_) {
|
||||
if (groupNeeded) {
|
||||
pdoc->BeginUndoAction();
|
||||
}
|
||||
}
|
||||
~UndoGroup() {
|
||||
if (groupNeeded) {
|
||||
pdoc->EndUndoAction();
|
||||
}
|
||||
}
|
||||
bool Needed() const {
|
||||
return groupNeeded;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* To optimise processing of document modifications by DocWatchers, a hint is passed indicating the
|
||||
* scope of the change.
|
||||
* If the DocWatcher is a document view then this can be used to optimise screen updating.
|
||||
*/
|
||||
class DocModification {
|
||||
public:
|
||||
int modificationType;
|
||||
int position;
|
||||
int length;
|
||||
int linesAdded; /**< Negative if lines deleted. */
|
||||
const char *text; /**< Only valid for changes to text, not for changes to style. */
|
||||
int line;
|
||||
int foldLevelNow;
|
||||
int foldLevelPrev;
|
||||
int annotationLinesAdded;
|
||||
int token;
|
||||
|
||||
DocModification(int modificationType_, int position_=0, int length_=0,
|
||||
int linesAdded_=0, const char *text_=0, int line_=0) :
|
||||
modificationType(modificationType_),
|
||||
position(position_),
|
||||
length(length_),
|
||||
linesAdded(linesAdded_),
|
||||
text(text_),
|
||||
line(line_),
|
||||
foldLevelNow(0),
|
||||
foldLevelPrev(0),
|
||||
annotationLinesAdded(0),
|
||||
token(0) {}
|
||||
|
||||
DocModification(int modificationType_, const Action &act, int linesAdded_=0) :
|
||||
modificationType(modificationType_),
|
||||
position(act.position),
|
||||
length(act.lenData),
|
||||
linesAdded(linesAdded_),
|
||||
text(act.data),
|
||||
line(0),
|
||||
foldLevelNow(0),
|
||||
foldLevelPrev(0),
|
||||
annotationLinesAdded(0),
|
||||
token(0) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* A class that wants to receive notifications from a Document must be derived from DocWatcher
|
||||
* and implement the notification methods. It can then be added to the watcher list with AddWatcher.
|
||||
*/
|
||||
class DocWatcher {
|
||||
public:
|
||||
virtual ~DocWatcher() {}
|
||||
|
||||
virtual void NotifyModifyAttempt(Document *doc, void *userData) = 0;
|
||||
virtual void NotifySavePoint(Document *doc, void *userData, bool atSavePoint) = 0;
|
||||
virtual void NotifyModified(Document *doc, DocModification mh, void *userData) = 0;
|
||||
virtual void NotifyDeleted(Document *doc, void *userData) = 0;
|
||||
virtual void NotifyStyleNeeded(Document *doc, void *userData, int endPos) = 0;
|
||||
virtual void NotifyLexerChanged(Document *doc, void *userData) = 0;
|
||||
virtual void NotifyErrorOccurred(Document *doc, void *userData, int status) = 0;
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
9732
third-party/scintilla/Editor.cxx
vendored
Normal file
9732
third-party/scintilla/Editor.cxx
vendored
Normal file
File diff suppressed because it is too large
Load Diff
702
third-party/scintilla/Editor.h
vendored
Normal file
702
third-party/scintilla/Editor.h
vendored
Normal file
@@ -0,0 +1,702 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file Editor.h
|
||||
** Defines the main editor class.
|
||||
**/
|
||||
// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef EDITOR_H
|
||||
#define EDITOR_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
/**
|
||||
*/
|
||||
class Caret {
|
||||
public:
|
||||
bool active;
|
||||
bool on;
|
||||
int period;
|
||||
|
||||
Caret();
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class Timer {
|
||||
public:
|
||||
bool ticking;
|
||||
int ticksToWait;
|
||||
enum {tickSize = 100};
|
||||
TickerID tickerID;
|
||||
|
||||
Timer();
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class Idler {
|
||||
public:
|
||||
bool state;
|
||||
IdlerID idlerID;
|
||||
|
||||
Idler();
|
||||
};
|
||||
|
||||
/**
|
||||
* When platform has a way to generate an event before painting,
|
||||
* accumulate needed styling range and other work items in
|
||||
* WorkNeeded to avoid unnecessary work inside paint handler
|
||||
*/
|
||||
class WorkNeeded {
|
||||
public:
|
||||
enum workItems {
|
||||
workNone=0,
|
||||
workStyle=1,
|
||||
workUpdateUI=2
|
||||
};
|
||||
bool active;
|
||||
enum workItems items;
|
||||
Position upTo;
|
||||
|
||||
WorkNeeded() : active(false), items(workNone), upTo(0) {}
|
||||
void Reset() {
|
||||
active = false;
|
||||
items = workNone;
|
||||
upTo = 0;
|
||||
}
|
||||
void Need(workItems items_, Position pos) {
|
||||
if ((items_ & workStyle) && (upTo < pos))
|
||||
upTo = pos;
|
||||
items = static_cast<workItems>(items | items_);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Hold a piece of text selected for copying or dragging, along with encoding and selection format information.
|
||||
*/
|
||||
class SelectionText {
|
||||
std::string s;
|
||||
public:
|
||||
bool rectangular;
|
||||
bool lineCopy;
|
||||
int codePage;
|
||||
int characterSet;
|
||||
SelectionText() : rectangular(false), lineCopy(false), codePage(0), characterSet(0) {}
|
||||
~SelectionText() {
|
||||
}
|
||||
void Clear() {
|
||||
s.clear();
|
||||
rectangular = false;
|
||||
lineCopy = false;
|
||||
codePage = 0;
|
||||
characterSet = 0;
|
||||
}
|
||||
void Copy(const std::string &s_, int codePage_, int characterSet_, bool rectangular_, bool lineCopy_) {
|
||||
s = s_;
|
||||
codePage = codePage_;
|
||||
characterSet = characterSet_;
|
||||
rectangular = rectangular_;
|
||||
lineCopy = lineCopy_;
|
||||
FixSelectionForClipboard();
|
||||
}
|
||||
void Copy(const SelectionText &other) {
|
||||
Copy(other.s, other.codePage, other.characterSet, other.rectangular, other.lineCopy);
|
||||
}
|
||||
const char *Data() const {
|
||||
return s.c_str();
|
||||
}
|
||||
size_t Length() const {
|
||||
return s.length();
|
||||
}
|
||||
size_t LengthWithTerminator() const {
|
||||
return s.length() + 1;
|
||||
}
|
||||
bool Empty() const {
|
||||
return s.empty();
|
||||
}
|
||||
private:
|
||||
void FixSelectionForClipboard() {
|
||||
// To avoid truncating the contents of the clipboard when pasted where the
|
||||
// clipboard contains NUL characters, replace NUL characters by spaces.
|
||||
std::replace(s.begin(), s.end(), '\0', ' ');
|
||||
}
|
||||
};
|
||||
|
||||
struct WrapPending {
|
||||
// The range of lines that need to be wrapped
|
||||
enum { lineLarge = 0x7ffffff };
|
||||
int start; // When there are wraps pending, will be in document range
|
||||
int end; // May be lineLarge to indicate all of document after start
|
||||
WrapPending() {
|
||||
start = lineLarge;
|
||||
end = lineLarge;
|
||||
}
|
||||
void Reset() {
|
||||
start = lineLarge;
|
||||
end = lineLarge;
|
||||
}
|
||||
void Wrapped(int line) {
|
||||
if (start == line)
|
||||
start++;
|
||||
}
|
||||
bool NeedsWrap() const {
|
||||
return start < end;
|
||||
}
|
||||
bool AddRange(int lineStart, int lineEnd) {
|
||||
const bool neededWrap = NeedsWrap();
|
||||
bool changed = false;
|
||||
if (start > lineStart) {
|
||||
start = lineStart;
|
||||
changed = true;
|
||||
}
|
||||
if ((end < lineEnd) || !neededWrap) {
|
||||
end = lineEnd;
|
||||
changed = true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
};
|
||||
|
||||
struct PrintParameters {
|
||||
int magnification;
|
||||
int colourMode;
|
||||
WrapMode wrapState;
|
||||
PrintParameters();
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class Editor : public DocWatcher {
|
||||
// Private so Editor objects can not be copied
|
||||
Editor(const Editor &);
|
||||
Editor &operator=(const Editor &);
|
||||
|
||||
protected: // ScintillaBase subclass needs access to much of Editor
|
||||
|
||||
/** On GTK+, Scintilla is a container widget holding two scroll bars
|
||||
* whereas on Windows there is just one window with both scroll bars turned on. */
|
||||
Window wMain; ///< The Scintilla parent window
|
||||
Window wMargin; ///< May be separate when using a scroll view for wMain
|
||||
|
||||
/** Style resources may be expensive to allocate so are cached between uses.
|
||||
* When a style attribute is changed, this cache is flushed. */
|
||||
bool stylesValid;
|
||||
ViewStyle vs;
|
||||
int technology;
|
||||
Point sizeRGBAImage;
|
||||
float scaleRGBAImage;
|
||||
|
||||
PrintParameters printParameters;
|
||||
|
||||
int cursorMode;
|
||||
|
||||
// Highlight current folding block
|
||||
HighlightDelimiter highlightDelimiter;
|
||||
|
||||
bool hasFocus;
|
||||
bool hideSelection;
|
||||
bool inOverstrike;
|
||||
bool drawOverstrikeCaret;
|
||||
bool mouseDownCaptures;
|
||||
|
||||
/** In bufferedDraw mode, graphics operations are drawn to a pixmap and then copied to
|
||||
* the screen. This avoids flashing but is about 30% slower. */
|
||||
bool bufferedDraw;
|
||||
/** In twoPhaseDraw mode, drawing is performed in two phases, first the background
|
||||
* and then the foreground. This avoids chopping off characters that overlap the next run. */
|
||||
bool twoPhaseDraw;
|
||||
|
||||
int xOffset; ///< Horizontal scrolled amount in pixels
|
||||
int xCaretMargin; ///< Ensure this many pixels visible on both sides of caret
|
||||
bool horizontalScrollBarVisible;
|
||||
int scrollWidth;
|
||||
bool trackLineWidth;
|
||||
int lineWidthMaxSeen;
|
||||
bool verticalScrollBarVisible;
|
||||
bool endAtLastLine;
|
||||
int caretSticky;
|
||||
int marginOptions;
|
||||
bool mouseSelectionRectangularSwitch;
|
||||
bool multipleSelection;
|
||||
bool additionalSelectionTyping;
|
||||
int multiPasteMode;
|
||||
bool additionalCaretsBlink;
|
||||
bool additionalCaretsVisible;
|
||||
|
||||
int virtualSpaceOptions;
|
||||
|
||||
Surface *pixmapLine;
|
||||
Surface *pixmapSelMargin;
|
||||
Surface *pixmapSelPattern;
|
||||
Surface *pixmapSelPatternOffset1;
|
||||
Surface *pixmapIndentGuide;
|
||||
Surface *pixmapIndentGuideHighlight;
|
||||
|
||||
LineLayoutCache llc;
|
||||
PositionCache posCache;
|
||||
SpecialRepresentations reprs;
|
||||
|
||||
KeyMap kmap;
|
||||
|
||||
Caret caret;
|
||||
Timer timer;
|
||||
Timer autoScrollTimer;
|
||||
enum { autoScrollDelay = 200 };
|
||||
|
||||
Idler idler;
|
||||
|
||||
Point lastClick;
|
||||
unsigned int lastClickTime;
|
||||
int dwellDelay;
|
||||
int ticksToDwell;
|
||||
bool dwelling;
|
||||
enum { selChar, selWord, selSubLine, selWholeLine } selectionType;
|
||||
Point ptMouseLast;
|
||||
enum { ddNone, ddInitial, ddDragging } inDragDrop;
|
||||
bool dropWentOutside;
|
||||
SelectionPosition posDrag;
|
||||
SelectionPosition posDrop;
|
||||
int hotSpotClickPos;
|
||||
int lastXChosen;
|
||||
int lineAnchorPos;
|
||||
int originalAnchorPos;
|
||||
int wordSelectAnchorStartPos;
|
||||
int wordSelectAnchorEndPos;
|
||||
int wordSelectInitialCaretPos;
|
||||
int targetStart;
|
||||
int targetEnd;
|
||||
int searchFlags;
|
||||
int topLine;
|
||||
int posTopLine;
|
||||
int lengthForEncode;
|
||||
|
||||
int needUpdateUI;
|
||||
Position braces[2];
|
||||
int bracesMatchStyle;
|
||||
int highlightGuideColumn;
|
||||
|
||||
enum { notPainting, painting, paintAbandoned } paintState;
|
||||
bool paintAbandonedByStyling;
|
||||
PRectangle rcPaint;
|
||||
bool paintingAllText;
|
||||
bool willRedrawAll;
|
||||
WorkNeeded workNeeded;
|
||||
|
||||
int modEventMask;
|
||||
|
||||
SelectionText drag;
|
||||
Selection sel;
|
||||
bool primarySelection;
|
||||
|
||||
int caretXPolicy;
|
||||
int caretXSlop; ///< Ensure this many pixels visible on both sides of caret
|
||||
|
||||
int caretYPolicy;
|
||||
int caretYSlop; ///< Ensure this many lines visible on both sides of caret
|
||||
|
||||
int visiblePolicy;
|
||||
int visibleSlop;
|
||||
|
||||
int searchAnchor;
|
||||
|
||||
bool recordingMacro;
|
||||
|
||||
int foldFlags;
|
||||
int foldAutomatic;
|
||||
ContractionState cs;
|
||||
|
||||
// Hotspot support
|
||||
int hsStart;
|
||||
int hsEnd;
|
||||
|
||||
// Wrapping support
|
||||
int wrapWidth;
|
||||
WrapPending wrapPending;
|
||||
|
||||
bool convertPastes;
|
||||
|
||||
Document *pdoc;
|
||||
|
||||
Editor();
|
||||
virtual ~Editor();
|
||||
virtual void Initialise() = 0;
|
||||
virtual void Finalise();
|
||||
|
||||
void InvalidateStyleData();
|
||||
void InvalidateStyleRedraw();
|
||||
void RefreshStyleData();
|
||||
void SetRepresentations();
|
||||
void DropGraphics(bool freeObjects);
|
||||
void AllocateGraphics();
|
||||
|
||||
// The top left visible point in main window coordinates. Will be 0,0 except for
|
||||
// scroll views where it will be equivalent to the current scroll position.
|
||||
virtual Point GetVisibleOriginInMain();
|
||||
Point DocumentPointFromView(Point ptView); // Convert a point from view space to document
|
||||
int TopLineOfMain() const; // Return the line at Main's y coordinate 0
|
||||
virtual PRectangle GetClientRectangle();
|
||||
virtual PRectangle GetClientDrawingRectangle();
|
||||
PRectangle GetTextRectangle();
|
||||
|
||||
int LinesOnScreen();
|
||||
int LinesToScroll();
|
||||
int MaxScrollPos();
|
||||
SelectionPosition ClampPositionIntoDocument(SelectionPosition sp) const;
|
||||
Point LocationFromPosition(SelectionPosition pos);
|
||||
Point LocationFromPosition(int pos);
|
||||
int XFromPosition(int pos);
|
||||
int XFromPosition(SelectionPosition sp);
|
||||
SelectionPosition SPositionFromLocation(Point pt, bool canReturnInvalid=false, bool charPosition=false, bool virtualSpace=true);
|
||||
int PositionFromLocation(Point pt, bool canReturnInvalid=false, bool charPosition=false);
|
||||
SelectionPosition SPositionFromLineX(int lineDoc, int x);
|
||||
int PositionFromLineX(int line, int x);
|
||||
int LineFromLocation(Point pt) const;
|
||||
void SetTopLine(int topLineNew);
|
||||
|
||||
virtual bool AbandonPaint();
|
||||
virtual void RedrawRect(PRectangle rc);
|
||||
virtual void DiscardOverdraw();
|
||||
virtual void Redraw();
|
||||
void RedrawSelMargin(int line=-1, bool allAfter=false);
|
||||
PRectangle RectangleFromRange(Range r);
|
||||
void InvalidateRange(int start, int end);
|
||||
|
||||
bool UserVirtualSpace() const {
|
||||
return ((virtualSpaceOptions & SCVS_USERACCESSIBLE) != 0);
|
||||
}
|
||||
int CurrentPosition() const;
|
||||
bool SelectionEmpty() const;
|
||||
SelectionPosition SelectionStart();
|
||||
SelectionPosition SelectionEnd();
|
||||
void SetRectangularRange();
|
||||
void ThinRectangularRange();
|
||||
void InvalidateSelection(SelectionRange newMain, bool invalidateWholeSelection=false);
|
||||
void SetSelection(SelectionPosition currentPos_, SelectionPosition anchor_);
|
||||
void SetSelection(int currentPos_, int anchor_);
|
||||
void SetSelection(SelectionPosition currentPos_);
|
||||
void SetSelection(int currentPos_);
|
||||
void SetEmptySelection(SelectionPosition currentPos_);
|
||||
void SetEmptySelection(int currentPos_);
|
||||
bool RangeContainsProtected(int start, int end) const;
|
||||
bool SelectionContainsProtected();
|
||||
int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true) const;
|
||||
SelectionPosition MovePositionOutsideChar(SelectionPosition pos, int moveDir, bool checkLineEnd=true) const;
|
||||
int MovePositionTo(SelectionPosition newPos, Selection::selTypes sel=Selection::noSel, bool ensureVisible=true);
|
||||
int MovePositionTo(int newPos, Selection::selTypes sel=Selection::noSel, bool ensureVisible=true);
|
||||
SelectionPosition MovePositionSoVisible(SelectionPosition pos, int moveDir);
|
||||
SelectionPosition MovePositionSoVisible(int pos, int moveDir);
|
||||
Point PointMainCaret();
|
||||
void SetLastXChosen();
|
||||
|
||||
void ScrollTo(int line, bool moveThumb=true);
|
||||
virtual void ScrollText(int linesToMove);
|
||||
void HorizontalScrollTo(int xPos);
|
||||
void VerticalCentreCaret();
|
||||
void MoveSelectedLines(int lineDelta);
|
||||
void MoveSelectedLinesUp();
|
||||
void MoveSelectedLinesDown();
|
||||
void MoveCaretInsideView(bool ensureVisible=true);
|
||||
int DisplayFromPosition(int pos);
|
||||
|
||||
struct XYScrollPosition {
|
||||
int xOffset;
|
||||
int topLine;
|
||||
XYScrollPosition(int xOffset_, int topLine_) : xOffset(xOffset_), topLine(topLine_) {}
|
||||
bool operator==(const XYScrollPosition &other) const {
|
||||
return (xOffset == other.xOffset) && (topLine == other.topLine);
|
||||
}
|
||||
};
|
||||
enum XYScrollOptions {
|
||||
xysUseMargin=0x1,
|
||||
xysVertical=0x2,
|
||||
xysHorizontal=0x4,
|
||||
xysDefault=xysUseMargin|xysVertical|xysHorizontal};
|
||||
XYScrollPosition XYScrollToMakeVisible(const SelectionRange &range, const XYScrollOptions options);
|
||||
void SetXYScroll(XYScrollPosition newXY);
|
||||
void EnsureCaretVisible(bool useMargin=true, bool vert=true, bool horiz=true);
|
||||
void ScrollRange(SelectionRange range);
|
||||
void ShowCaretAtCurrentPosition();
|
||||
void DropCaret();
|
||||
void CaretSetPeriod(int period);
|
||||
void InvalidateCaret();
|
||||
virtual void UpdateSystemCaret();
|
||||
|
||||
bool Wrapping() const;
|
||||
void NeedWrapping(int docLineStart=0, int docLineEnd=WrapPending::lineLarge);
|
||||
bool WrapOneLine(Surface *surface, int lineToWrap);
|
||||
enum wrapScope {wsAll, wsVisible, wsIdle};
|
||||
bool WrapLines(enum wrapScope ws);
|
||||
void LinesJoin();
|
||||
void LinesSplit(int pixelWidth);
|
||||
|
||||
int SubstituteMarkerIfEmpty(int markerCheck, int markerDefault) const;
|
||||
void PaintSelMargin(Surface *surface, PRectangle &rc);
|
||||
LineLayout *RetrieveLineLayout(int lineNumber);
|
||||
void LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll,
|
||||
int width=LineLayout::wrapWidthInfinite);
|
||||
ColourDesired SelectionBackground(ViewStyle &vsDraw, bool main) const;
|
||||
ColourDesired TextBackground(ViewStyle &vsDraw, bool overrideBackground, ColourDesired background, int inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll) const;
|
||||
void DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight);
|
||||
static void DrawWrapMarker(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourDesired wrapColour);
|
||||
void DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll,
|
||||
int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart,
|
||||
bool overrideBackground, ColourDesired background,
|
||||
bool drawWrapMark, ColourDesired wrapColour);
|
||||
static void DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, ViewStyle &vsDraw,
|
||||
int xStart, PRectangle rcLine, LineLayout *ll, int subLine);
|
||||
void DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
|
||||
PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under);
|
||||
void DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
|
||||
PRectangle rcLine, LineLayout *ll, int subLine);
|
||||
void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,
|
||||
PRectangle rcLine, LineLayout *ll, int subLine);
|
||||
void DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine,
|
||||
int xStart, int offset, int posCaret, PRectangle rcCaret, ColourDesired caretColour);
|
||||
void DrawCarets(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
|
||||
PRectangle rcLine, LineLayout *ll, int subLine);
|
||||
void RefreshPixMaps(Surface *surfaceWindow);
|
||||
void Paint(Surface *surfaceWindow, PRectangle rcArea);
|
||||
long FormatRange(bool draw, Sci_RangeToFormat *pfr);
|
||||
int TextWidth(int style, const char *text);
|
||||
|
||||
virtual void SetVerticalScrollPos() = 0;
|
||||
virtual void SetHorizontalScrollPos() = 0;
|
||||
virtual bool ModifyScrollBars(int nMax, int nPage) = 0;
|
||||
virtual void ReconfigureScrollBars();
|
||||
void SetScrollBars();
|
||||
void ChangeSize();
|
||||
|
||||
void FilterSelections();
|
||||
int InsertSpace(int position, unsigned int spaces);
|
||||
void AddChar(char ch);
|
||||
virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false);
|
||||
void InsertPaste(const char *text, int len);
|
||||
enum PasteShape { pasteStream=0, pasteRectangular = 1, pasteLine = 2 };
|
||||
void InsertPasteShape(const char *text, int len, PasteShape shape);
|
||||
void ClearSelection(bool retainMultipleSelections=false);
|
||||
void ClearAll();
|
||||
void ClearDocumentStyle();
|
||||
void Cut();
|
||||
void PasteRectangular(SelectionPosition pos, const char *ptr, int len);
|
||||
virtual void Copy() = 0;
|
||||
virtual void CopyAllowLine();
|
||||
virtual bool CanPaste();
|
||||
virtual void Paste() = 0;
|
||||
void Clear();
|
||||
void SelectAll();
|
||||
void Undo();
|
||||
void Redo();
|
||||
void DelChar();
|
||||
void DelCharBack(bool allowLineStartDeletion);
|
||||
virtual void ClaimSelection() = 0;
|
||||
|
||||
static int ModifierFlags(bool shift, bool ctrl, bool alt, bool meta=false);
|
||||
virtual void NotifyChange() = 0;
|
||||
virtual void NotifyFocus(bool focus);
|
||||
virtual void SetCtrlID(int identifier);
|
||||
virtual int GetCtrlID() { return ctrlID; }
|
||||
virtual void NotifyParent(SCNotification scn) = 0;
|
||||
virtual void NotifyStyleToNeeded(int endStyleNeeded);
|
||||
void NotifyChar(int ch);
|
||||
void NotifySavePoint(bool isSavePoint);
|
||||
void NotifyModifyAttempt();
|
||||
virtual void NotifyDoubleClick(Point pt, int modifiers);
|
||||
virtual void NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt);
|
||||
void NotifyHotSpotClicked(int position, int modifiers);
|
||||
void NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt);
|
||||
void NotifyHotSpotDoubleClicked(int position, int modifiers);
|
||||
void NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, bool alt);
|
||||
void NotifyHotSpotReleaseClick(int position, int modifiers);
|
||||
void NotifyHotSpotReleaseClick(int position, bool shift, bool ctrl, bool alt);
|
||||
bool NotifyUpdateUI();
|
||||
void NotifyPainted();
|
||||
void NotifyIndicatorClick(bool click, int position, int modifiers);
|
||||
void NotifyIndicatorClick(bool click, int position, bool shift, bool ctrl, bool alt);
|
||||
bool NotifyMarginClick(Point pt, int modifiers);
|
||||
bool NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt);
|
||||
void NotifyNeedShown(int pos, int len);
|
||||
void NotifyDwelling(Point pt, bool state);
|
||||
void NotifyZoom();
|
||||
|
||||
void NotifyModifyAttempt(Document *document, void *userData);
|
||||
void NotifySavePoint(Document *document, void *userData, bool atSavePoint);
|
||||
void CheckModificationForWrap(DocModification mh);
|
||||
void NotifyModified(Document *document, DocModification mh, void *userData);
|
||||
void NotifyDeleted(Document *document, void *userData);
|
||||
void NotifyStyleNeeded(Document *doc, void *userData, int endPos);
|
||||
void NotifyLexerChanged(Document *doc, void *userData);
|
||||
void NotifyErrorOccurred(Document *doc, void *userData, int status);
|
||||
void NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
|
||||
|
||||
void ContainerNeedsUpdate(int flags);
|
||||
void PageMove(int direction, Selection::selTypes sel=Selection::noSel, bool stuttered = false);
|
||||
enum { cmSame, cmUpper, cmLower };
|
||||
virtual std::string CaseMapString(const std::string &s, int caseMapping);
|
||||
void ChangeCaseOfSelection(int caseMapping);
|
||||
void LineTranspose();
|
||||
void Duplicate(bool forLine);
|
||||
virtual void CancelModes();
|
||||
void NewLine();
|
||||
void CursorUpOrDown(int direction, Selection::selTypes sel=Selection::noSel);
|
||||
void ParaUpOrDown(int direction, Selection::selTypes sel=Selection::noSel);
|
||||
int StartEndDisplayLine(int pos, bool start);
|
||||
virtual int KeyCommand(unsigned int iMessage);
|
||||
virtual int KeyDefault(int /* key */, int /*modifiers*/);
|
||||
int KeyDownWithModifiers(int key, int modifiers, bool *consumed);
|
||||
int KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed=0);
|
||||
|
||||
void Indent(bool forwards);
|
||||
|
||||
virtual CaseFolder *CaseFolderForEncoding();
|
||||
long FindText(uptr_t wParam, sptr_t lParam);
|
||||
void SearchAnchor();
|
||||
long SearchText(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
|
||||
long SearchInTarget(const char *text, int length);
|
||||
void GoToLine(int lineNo);
|
||||
|
||||
virtual void CopyToClipboard(const SelectionText &selectedText) = 0;
|
||||
std::string RangeText(int start, int end) const;
|
||||
void CopySelectionRange(SelectionText *ss, bool allowLineCopy=false);
|
||||
void CopyRangeToClipboard(int start, int end);
|
||||
void CopyText(int length, const char *text);
|
||||
void SetDragPosition(SelectionPosition newPos);
|
||||
virtual void DisplayCursor(Window::Cursor c);
|
||||
virtual bool DragThreshold(Point ptStart, Point ptNow);
|
||||
virtual void StartDrag();
|
||||
void DropAt(SelectionPosition position, const char *value, size_t lengthValue, bool moving, bool rectangular);
|
||||
void DropAt(SelectionPosition position, const char *value, bool moving, bool rectangular);
|
||||
/** PositionInSelection returns true if position in selection. */
|
||||
bool PositionInSelection(int pos);
|
||||
bool PointInSelection(Point pt);
|
||||
bool PointInSelMargin(Point pt);
|
||||
Window::Cursor GetMarginCursor(Point pt) const;
|
||||
void TrimAndSetSelection(int currentPos_, int anchor_);
|
||||
void LineSelection(int lineCurrentPos_, int lineAnchorPos_, bool wholeLine);
|
||||
void WordSelection(int pos);
|
||||
void DwellEnd(bool mouseMoved);
|
||||
void MouseLeave();
|
||||
virtual void ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifiers);
|
||||
virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt);
|
||||
void ButtonMoveWithModifiers(Point pt, int modifiers);
|
||||
void ButtonMove(Point pt);
|
||||
void ButtonUp(Point pt, unsigned int curTime, bool ctrl);
|
||||
|
||||
void Tick();
|
||||
bool Idle();
|
||||
virtual void SetTicking(bool on) = 0;
|
||||
virtual bool SetIdle(bool) { return false; }
|
||||
virtual void SetMouseCapture(bool on) = 0;
|
||||
virtual bool HaveMouseCapture() = 0;
|
||||
void SetFocusState(bool focusState);
|
||||
|
||||
int PositionAfterArea(PRectangle rcArea) const;
|
||||
void StyleToPositionInView(Position pos);
|
||||
virtual void IdleWork();
|
||||
virtual void QueueIdleWork(WorkNeeded::workItems items, int upTo=0);
|
||||
|
||||
virtual bool PaintContains(PRectangle rc);
|
||||
bool PaintContainsMargin();
|
||||
void CheckForChangeOutsidePaint(Range r);
|
||||
void SetBraceHighlight(Position pos0, Position pos1, int matchStyle);
|
||||
|
||||
void SetAnnotationHeights(int start, int end);
|
||||
virtual void SetDocPointer(Document *document);
|
||||
|
||||
void SetAnnotationVisible(int visible);
|
||||
|
||||
int ExpandLine(int line);
|
||||
void SetFoldExpanded(int lineDoc, bool expanded);
|
||||
void FoldLine(int line, int action);
|
||||
void FoldExpand(int line, int action, int level);
|
||||
int ContractedFoldNext(int lineStart) const;
|
||||
void EnsureLineVisible(int lineDoc, bool enforcePolicy);
|
||||
void FoldChanged(int line, int levelNow, int levelPrev);
|
||||
void NeedShown(int pos, int len);
|
||||
void FoldAll(int action);
|
||||
|
||||
int GetTag(char *tagValue, int tagNumber);
|
||||
int ReplaceTarget(bool replacePatterns, const char *text, int length=-1);
|
||||
|
||||
bool PositionIsHotspot(int position) const;
|
||||
bool PointIsHotspot(Point pt);
|
||||
void SetHotSpotRange(Point *pt);
|
||||
void GetHotSpotRange(int &hsStart, int &hsEnd) const;
|
||||
|
||||
int CodePage() const;
|
||||
virtual bool ValidCodePage(int /* codePage */) const { return true; }
|
||||
int WrapCount(int line);
|
||||
void AddStyledText(char *buffer, int appendLength);
|
||||
|
||||
virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) = 0;
|
||||
void StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
|
||||
sptr_t StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
|
||||
|
||||
static const char *StringFromEOLMode(int eolMode);
|
||||
|
||||
static sptr_t StringResult(sptr_t lParam, const char *val);
|
||||
static sptr_t BytesResult(sptr_t lParam, const unsigned char *val, size_t len);
|
||||
|
||||
public:
|
||||
// Public so the COM thunks can access it.
|
||||
bool IsUnicodeMode() const;
|
||||
// Public so scintilla_send_message can use it.
|
||||
virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
|
||||
// Public so scintilla_set_id can use it.
|
||||
int ctrlID;
|
||||
// Public so COM methods for drag and drop can set it.
|
||||
int errorStatus;
|
||||
friend class AutoSurface;
|
||||
friend class SelectionLineIterator;
|
||||
};
|
||||
|
||||
/**
|
||||
* A smart pointer class to ensure Surfaces are set up and deleted correctly.
|
||||
*/
|
||||
class AutoSurface {
|
||||
private:
|
||||
Surface *surf;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
AutoSurface(const AutoSurface &);
|
||||
AutoSurface &operator =(const AutoSurface &);
|
||||
|
||||
public:
|
||||
AutoSurface(Editor *ed, int technology = -1) : surf(0) {
|
||||
if (ed->wMain.GetID()) {
|
||||
surf = Surface::Allocate(technology != -1 ? technology : ed->technology);
|
||||
if (surf) {
|
||||
surf->Init(ed->wMain.GetID());
|
||||
surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage());
|
||||
surf->SetDBCSMode(ed->CodePage());
|
||||
}
|
||||
}
|
||||
}
|
||||
AutoSurface(SurfaceID sid, Editor *ed, int technology = -1) : surf(0) {
|
||||
if (ed->wMain.GetID()) {
|
||||
surf = Surface::Allocate(technology != -1 ? technology : ed->technology);
|
||||
if (surf) {
|
||||
surf->Init(sid, ed->wMain.GetID());
|
||||
surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage());
|
||||
surf->SetDBCSMode(ed->CodePage());
|
||||
}
|
||||
}
|
||||
}
|
||||
~AutoSurface() {
|
||||
delete surf;
|
||||
}
|
||||
Surface *operator->() const {
|
||||
return surf;
|
||||
}
|
||||
operator Surface *() const {
|
||||
return surf;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
183
third-party/scintilla/ExternalLexer.cxx
vendored
Normal file
183
third-party/scintilla/ExternalLexer.cxx
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file ExternalLexer.cxx
|
||||
** Support external lexers in DLLs.
|
||||
**/
|
||||
// Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "ILexer.h"
|
||||
#include "Scintilla.h"
|
||||
#include "SciLexer.h"
|
||||
|
||||
#include "LexerModule.h"
|
||||
#include "Catalogue.h"
|
||||
#include "ExternalLexer.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
LexerManager *LexerManager::theInstance = NULL;
|
||||
|
||||
//------------------------------------------
|
||||
//
|
||||
// ExternalLexerModule
|
||||
//
|
||||
//------------------------------------------
|
||||
|
||||
void ExternalLexerModule::SetExternal(GetLexerFactoryFunction fFactory, int index) {
|
||||
fneFactory = fFactory;
|
||||
fnFactory = fFactory(index);
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
//
|
||||
// LexerLibrary
|
||||
//
|
||||
//------------------------------------------
|
||||
|
||||
LexerLibrary::LexerLibrary(const char *ModuleName) {
|
||||
// Initialise some members...
|
||||
first = NULL;
|
||||
last = NULL;
|
||||
|
||||
// Load the DLL
|
||||
lib = DynamicLibrary::Load(ModuleName);
|
||||
if (lib->IsValid()) {
|
||||
m_sModuleName = ModuleName;
|
||||
//Cannot use reinterpret_cast because: ANSI C++ forbids casting between pointers to functions and objects
|
||||
GetLexerCountFn GetLexerCount = (GetLexerCountFn)(sptr_t)lib->FindFunction("GetLexerCount");
|
||||
|
||||
if (GetLexerCount) {
|
||||
ExternalLexerModule *lex;
|
||||
LexerMinder *lm;
|
||||
|
||||
// Find functions in the DLL
|
||||
GetLexerNameFn GetLexerName = (GetLexerNameFn)(sptr_t)lib->FindFunction("GetLexerName");
|
||||
GetLexerFactoryFunction fnFactory = (GetLexerFactoryFunction)(sptr_t)lib->FindFunction("GetLexerFactory");
|
||||
|
||||
int nl = GetLexerCount();
|
||||
|
||||
for (int i = 0; i < nl; i++) {
|
||||
// Assign a buffer for the lexer name.
|
||||
char lexname[100] = "";
|
||||
GetLexerName(i, lexname, sizeof(lexname));
|
||||
lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL);
|
||||
Catalogue::AddLexerModule(lex);
|
||||
|
||||
// Create a LexerMinder so we don't leak the ExternalLexerModule...
|
||||
lm = new LexerMinder;
|
||||
lm->self = lex;
|
||||
lm->next = NULL;
|
||||
if (first != NULL) {
|
||||
last->next = lm;
|
||||
last = lm;
|
||||
} else {
|
||||
first = lm;
|
||||
last = lm;
|
||||
}
|
||||
|
||||
// The external lexer needs to know how to call into its DLL to
|
||||
// do its lexing and folding, we tell it here.
|
||||
lex->SetExternal(fnFactory, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
next = NULL;
|
||||
}
|
||||
|
||||
LexerLibrary::~LexerLibrary() {
|
||||
Release();
|
||||
delete lib;
|
||||
}
|
||||
|
||||
void LexerLibrary::Release() {
|
||||
LexerMinder *lm;
|
||||
LexerMinder *lmNext;
|
||||
lm = first;
|
||||
while (NULL != lm) {
|
||||
lmNext = lm->next;
|
||||
delete lm->self;
|
||||
delete lm;
|
||||
lm = lmNext;
|
||||
}
|
||||
|
||||
first = NULL;
|
||||
last = NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
//
|
||||
// LexerManager
|
||||
//
|
||||
//------------------------------------------
|
||||
|
||||
/// Return the single LexerManager instance...
|
||||
LexerManager *LexerManager::GetInstance() {
|
||||
if (!theInstance)
|
||||
theInstance = new LexerManager;
|
||||
return theInstance;
|
||||
}
|
||||
|
||||
/// Delete any LexerManager instance...
|
||||
void LexerManager::DeleteInstance() {
|
||||
delete theInstance;
|
||||
theInstance = NULL;
|
||||
}
|
||||
|
||||
/// protected constructor - this is a singleton...
|
||||
LexerManager::LexerManager() {
|
||||
first = NULL;
|
||||
last = NULL;
|
||||
}
|
||||
|
||||
LexerManager::~LexerManager() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void LexerManager::Load(const char *path) {
|
||||
LoadLexerLibrary(path);
|
||||
}
|
||||
|
||||
void LexerManager::LoadLexerLibrary(const char *module) {
|
||||
for (LexerLibrary *ll = first; ll; ll= ll->next) {
|
||||
if (strcmp(ll->m_sModuleName.c_str(), module) == 0)
|
||||
return;
|
||||
}
|
||||
LexerLibrary *lib = new LexerLibrary(module);
|
||||
if (NULL != first) {
|
||||
last->next = lib;
|
||||
last = lib;
|
||||
} else {
|
||||
first = lib;
|
||||
last = lib;
|
||||
}
|
||||
}
|
||||
|
||||
void LexerManager::Clear() {
|
||||
if (NULL != first) {
|
||||
LexerLibrary *cur = first;
|
||||
LexerLibrary *next;
|
||||
while (cur) {
|
||||
next = cur->next;
|
||||
delete cur;
|
||||
cur = next;
|
||||
}
|
||||
first = NULL;
|
||||
last = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
//
|
||||
// LexerManager
|
||||
//
|
||||
//------------------------------------------
|
||||
|
||||
LMMinder::~LMMinder() {
|
||||
LexerManager::DeleteInstance();
|
||||
}
|
||||
|
||||
LMMinder minder;
|
||||
96
third-party/scintilla/ExternalLexer.h
vendored
Normal file
96
third-party/scintilla/ExternalLexer.h
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file ExternalLexer.h
|
||||
** Support external lexers in DLLs.
|
||||
**/
|
||||
// Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef EXTERNALLEXER_H
|
||||
#define EXTERNALLEXER_H
|
||||
|
||||
#if PLAT_WIN
|
||||
#define EXT_LEXER_DECL __stdcall
|
||||
#else
|
||||
#define EXT_LEXER_DECL
|
||||
#endif
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
typedef void*(EXT_LEXER_DECL *GetLexerFunction)(unsigned int Index);
|
||||
typedef int (EXT_LEXER_DECL *GetLexerCountFn)();
|
||||
typedef void (EXT_LEXER_DECL *GetLexerNameFn)(unsigned int Index, char *name, int buflength);
|
||||
typedef LexerFactoryFunction(EXT_LEXER_DECL *GetLexerFactoryFunction)(unsigned int Index);
|
||||
|
||||
/// Sub-class of LexerModule to use an external lexer.
|
||||
class ExternalLexerModule : public LexerModule {
|
||||
protected:
|
||||
GetLexerFactoryFunction fneFactory;
|
||||
std::string name;
|
||||
public:
|
||||
ExternalLexerModule(int language_, LexerFunction fnLexer_,
|
||||
const char *languageName_=0, LexerFunction fnFolder_=0) :
|
||||
LexerModule(language_, fnLexer_, 0, fnFolder_),
|
||||
fneFactory(0), name(languageName_){
|
||||
languageName = name.c_str();
|
||||
}
|
||||
virtual void SetExternal(GetLexerFactoryFunction fFactory, int index);
|
||||
};
|
||||
|
||||
/// LexerMinder points to an ExternalLexerModule - so we don't leak them.
|
||||
class LexerMinder {
|
||||
public:
|
||||
ExternalLexerModule *self;
|
||||
LexerMinder *next;
|
||||
};
|
||||
|
||||
/// LexerLibrary exists for every External Lexer DLL, contains LexerMinders.
|
||||
class LexerLibrary {
|
||||
DynamicLibrary *lib;
|
||||
LexerMinder *first;
|
||||
LexerMinder *last;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
LexerLibrary(const LexerLibrary &);
|
||||
LexerLibrary &operator =(const LexerLibrary &);
|
||||
|
||||
public:
|
||||
explicit LexerLibrary(const char *ModuleName);
|
||||
~LexerLibrary();
|
||||
void Release();
|
||||
|
||||
LexerLibrary *next;
|
||||
std::string m_sModuleName;
|
||||
};
|
||||
|
||||
/// LexerManager manages external lexers, contains LexerLibrarys.
|
||||
class LexerManager {
|
||||
public:
|
||||
~LexerManager();
|
||||
|
||||
static LexerManager *GetInstance();
|
||||
static void DeleteInstance();
|
||||
|
||||
void Load(const char *path);
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
LexerManager();
|
||||
static LexerManager *theInstance;
|
||||
|
||||
void LoadLexerLibrary(const char *module);
|
||||
LexerLibrary *first;
|
||||
LexerLibrary *last;
|
||||
};
|
||||
|
||||
class LMMinder {
|
||||
public:
|
||||
~LMMinder();
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
28
third-party/scintilla/FontQuality.h
vendored
Normal file
28
third-party/scintilla/FontQuality.h
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file FontQuality.h
|
||||
** Definitions to control font anti-aliasing.
|
||||
**/
|
||||
// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef FONTQUALITY_H
|
||||
#define FONTQUALITY_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
#define SC_EFF_QUALITY_MASK 0xF
|
||||
#define SC_EFF_QUALITY_DEFAULT 0
|
||||
#define SC_EFF_QUALITY_NON_ANTIALIASED 1
|
||||
#define SC_EFF_QUALITY_ANTIALIASED 2
|
||||
#define SC_EFF_QUALITY_LCD_OPTIMIZED 3
|
||||
|
||||
#define SCWIN_TECH_GDI 0
|
||||
#define SCWIN_TECH_DIRECTWRITE 1
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
98
third-party/scintilla/ILexer.h
vendored
Normal file
98
third-party/scintilla/ILexer.h
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file ILexer.h
|
||||
** Interface between Scintilla and lexers.
|
||||
**/
|
||||
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef ILEXER_H
|
||||
#define ILEXER_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define SCI_METHOD __stdcall
|
||||
#else
|
||||
#define SCI_METHOD
|
||||
#endif
|
||||
|
||||
enum { dvOriginal=0, dvLineEnd=1 };
|
||||
|
||||
class IDocument {
|
||||
public:
|
||||
virtual int SCI_METHOD Version() const = 0;
|
||||
virtual void SCI_METHOD SetErrorStatus(int status) = 0;
|
||||
virtual int SCI_METHOD Length() const = 0;
|
||||
virtual void SCI_METHOD GetCharRange(char *buffer, int position, int lengthRetrieve) const = 0;
|
||||
virtual char SCI_METHOD StyleAt(int position) const = 0;
|
||||
virtual int SCI_METHOD LineFromPosition(int position) const = 0;
|
||||
virtual int SCI_METHOD LineStart(int line) const = 0;
|
||||
virtual int SCI_METHOD GetLevel(int line) const = 0;
|
||||
virtual int SCI_METHOD SetLevel(int line, int level) = 0;
|
||||
virtual int SCI_METHOD GetLineState(int line) const = 0;
|
||||
virtual int SCI_METHOD SetLineState(int line, int state) = 0;
|
||||
virtual void SCI_METHOD StartStyling(int position, char mask) = 0;
|
||||
virtual bool SCI_METHOD SetStyleFor(int length, char style) = 0;
|
||||
virtual bool SCI_METHOD SetStyles(int length, const char *styles) = 0;
|
||||
virtual void SCI_METHOD DecorationSetCurrentIndicator(int indicator) = 0;
|
||||
virtual void SCI_METHOD DecorationFillRange(int position, int value, int fillLength) = 0;
|
||||
virtual void SCI_METHOD ChangeLexerState(int start, int end) = 0;
|
||||
virtual int SCI_METHOD CodePage() const = 0;
|
||||
virtual bool SCI_METHOD IsDBCSLeadByte(char ch) const = 0;
|
||||
virtual const char * SCI_METHOD BufferPointer() = 0;
|
||||
virtual int SCI_METHOD GetLineIndentation(int line) = 0;
|
||||
};
|
||||
|
||||
class IDocumentWithLineEnd : public IDocument {
|
||||
public:
|
||||
virtual int SCI_METHOD LineEnd(int line) const = 0;
|
||||
virtual int SCI_METHOD GetRelativePosition(int positionStart, int characterOffset) const = 0;
|
||||
virtual int SCI_METHOD GetCharacterAndWidth(int position, int *pWidth) const = 0;
|
||||
};
|
||||
|
||||
enum { lvOriginal=0, lvSubStyles=1 };
|
||||
|
||||
class ILexer {
|
||||
public:
|
||||
virtual int SCI_METHOD Version() const = 0;
|
||||
virtual void SCI_METHOD Release() = 0;
|
||||
virtual const char * SCI_METHOD PropertyNames() = 0;
|
||||
virtual int SCI_METHOD PropertyType(const char *name) = 0;
|
||||
virtual const char * SCI_METHOD DescribeProperty(const char *name) = 0;
|
||||
virtual int SCI_METHOD PropertySet(const char *key, const char *val) = 0;
|
||||
virtual const char * SCI_METHOD DescribeWordListSets() = 0;
|
||||
virtual int SCI_METHOD WordListSet(int n, const char *wl) = 0;
|
||||
virtual void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0;
|
||||
virtual void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0;
|
||||
virtual void * SCI_METHOD PrivateCall(int operation, void *pointer) = 0;
|
||||
};
|
||||
|
||||
class ILexerWithSubStyles : public ILexer {
|
||||
public:
|
||||
virtual int SCI_METHOD LineEndTypesSupported() = 0;
|
||||
virtual int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) = 0;
|
||||
virtual int SCI_METHOD SubStylesStart(int styleBase) = 0;
|
||||
virtual int SCI_METHOD SubStylesLength(int styleBase) = 0;
|
||||
virtual int SCI_METHOD StyleFromSubStyle(int subStyle) = 0;
|
||||
virtual int SCI_METHOD PrimaryStyleFromStyle(int style) = 0;
|
||||
virtual void SCI_METHOD FreeSubStyles() = 0;
|
||||
virtual void SCI_METHOD SetIdentifiers(int style, const char *identifiers) = 0;
|
||||
virtual int SCI_METHOD DistanceToSecondaryStyles() = 0;
|
||||
virtual const char * SCI_METHOD GetSubStyleBases() = 0;
|
||||
};
|
||||
|
||||
class ILoader {
|
||||
public:
|
||||
virtual int SCI_METHOD Release() = 0;
|
||||
// Returns a status code from SC_STATUS_*
|
||||
virtual int SCI_METHOD AddData(char *data, int length) = 0;
|
||||
virtual void * SCI_METHOD ConvertToDocument() = 0;
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
160
third-party/scintilla/Indicator.cxx
vendored
Normal file
160
third-party/scintilla/Indicator.cxx
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file Indicator.cxx
|
||||
** Defines the style of indicators which are text decorations such as underlining.
|
||||
**/
|
||||
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
#include "XPM.h"
|
||||
#include "Indicator.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
static PRectangle PixelGridAlign(const PRectangle &rc) {
|
||||
// Move left and right side to nearest pixel to avoid blurry visuals
|
||||
return PRectangle::FromInts(int(rc.left + 0.5), int(rc.top), int(rc.right + 0.5), int(rc.bottom));
|
||||
}
|
||||
|
||||
void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine) {
|
||||
surface->PenColour(fore);
|
||||
int ymid = static_cast<int>(rc.bottom + rc.top) / 2;
|
||||
if (style == INDIC_SQUIGGLE) {
|
||||
int x = int(rc.left+0.5);
|
||||
int xLast = int(rc.right+0.5);
|
||||
int y = 0;
|
||||
surface->MoveTo(x, static_cast<int>(rc.top) + y);
|
||||
while (x < xLast) {
|
||||
if ((x + 2) > xLast) {
|
||||
if (xLast > x)
|
||||
y = 1;
|
||||
x = xLast;
|
||||
} else {
|
||||
x += 2;
|
||||
y = 2 - y;
|
||||
}
|
||||
surface->LineTo(x, static_cast<int>(rc.top) + y);
|
||||
}
|
||||
} else if (style == INDIC_SQUIGGLEPIXMAP) {
|
||||
PRectangle rcSquiggle = PixelGridAlign(rc);
|
||||
|
||||
int width = Platform::Minimum(4000, static_cast<int>(rcSquiggle.Width()));
|
||||
RGBAImage image(width, 3, 1.0, 0);
|
||||
enum { alphaFull = 0xff, alphaSide = 0x2f, alphaSide2=0x5f };
|
||||
for (int x = 0; x < width; x++) {
|
||||
if (x%2) {
|
||||
// Two halfway columns have a full pixel in middle flanked by light pixels
|
||||
image.SetPixel(x, 0, fore, alphaSide);
|
||||
image.SetPixel(x, 1, fore, alphaFull);
|
||||
image.SetPixel(x, 2, fore, alphaSide);
|
||||
} else {
|
||||
// Extreme columns have a full pixel at bottom or top and a mid-tone pixel in centre
|
||||
image.SetPixel(x, (x%4) ? 0 : 2, fore, alphaFull);
|
||||
image.SetPixel(x, 1, fore, alphaSide2);
|
||||
}
|
||||
}
|
||||
surface->DrawRGBAImage(rcSquiggle, image.GetWidth(), image.GetHeight(), image.Pixels());
|
||||
} else if (style == INDIC_SQUIGGLELOW) {
|
||||
surface->MoveTo(static_cast<int>(rc.left), static_cast<int>(rc.top));
|
||||
int x = static_cast<int>(rc.left) + 3;
|
||||
int y = 0;
|
||||
while (x < rc.right) {
|
||||
surface->LineTo(x - 1, static_cast<int>(rc.top) + y);
|
||||
y = 1 - y;
|
||||
surface->LineTo(x, static_cast<int>(rc.top) + y);
|
||||
x += 3;
|
||||
}
|
||||
surface->LineTo(static_cast<int>(rc.right), static_cast<int>(rc.top) + y); // Finish the line
|
||||
} else if (style == INDIC_TT) {
|
||||
surface->MoveTo(static_cast<int>(rc.left), ymid);
|
||||
int x = static_cast<int>(rc.left) + 5;
|
||||
while (x < rc.right) {
|
||||
surface->LineTo(x, ymid);
|
||||
surface->MoveTo(x-3, ymid);
|
||||
surface->LineTo(x-3, ymid+2);
|
||||
x++;
|
||||
surface->MoveTo(x, ymid);
|
||||
x += 5;
|
||||
}
|
||||
surface->LineTo(static_cast<int>(rc.right), ymid); // Finish the line
|
||||
if (x - 3 <= rc.right) {
|
||||
surface->MoveTo(x-3, ymid);
|
||||
surface->LineTo(x-3, ymid+2);
|
||||
}
|
||||
} else if (style == INDIC_DIAGONAL) {
|
||||
int x = static_cast<int>(rc.left);
|
||||
while (x < rc.right) {
|
||||
surface->MoveTo(x, static_cast<int>(rc.top) + 2);
|
||||
int endX = x+3;
|
||||
int endY = static_cast<int>(rc.top) - 1;
|
||||
if (endX > rc.right) {
|
||||
endY += endX - static_cast<int>(rc.right);
|
||||
endX = static_cast<int>(rc.right);
|
||||
}
|
||||
surface->LineTo(endX, endY);
|
||||
x += 4;
|
||||
}
|
||||
} else if (style == INDIC_STRIKE) {
|
||||
surface->MoveTo(static_cast<int>(rc.left), static_cast<int>(rc.top) - 4);
|
||||
surface->LineTo(static_cast<int>(rc.right), static_cast<int>(rc.top) - 4);
|
||||
} else if (style == INDIC_HIDDEN) {
|
||||
// Draw nothing
|
||||
} else if (style == INDIC_BOX) {
|
||||
surface->MoveTo(static_cast<int>(rc.left), ymid + 1);
|
||||
surface->LineTo(static_cast<int>(rc.right), ymid + 1);
|
||||
surface->LineTo(static_cast<int>(rc.right), static_cast<int>(rcLine.top) + 1);
|
||||
surface->LineTo(static_cast<int>(rc.left), static_cast<int>(rcLine.top) + 1);
|
||||
surface->LineTo(static_cast<int>(rc.left), ymid + 1);
|
||||
} else if (style == INDIC_ROUNDBOX || style == INDIC_STRAIGHTBOX) {
|
||||
PRectangle rcBox = rcLine;
|
||||
rcBox.top = rcLine.top + 1;
|
||||
rcBox.left = rc.left;
|
||||
rcBox.right = rc.right;
|
||||
surface->AlphaRectangle(rcBox, (style == INDIC_ROUNDBOX) ? 1 : 0, fore, fillAlpha, fore, outlineAlpha, 0);
|
||||
} else if (style == INDIC_DOTBOX) {
|
||||
PRectangle rcBox = PixelGridAlign(rc);
|
||||
rcBox.top = rcLine.top + 1;
|
||||
rcBox.bottom = rcLine.bottom;
|
||||
// Cap width at 4000 to avoid large allocations when mistakes made
|
||||
int width = Platform::Minimum(static_cast<int>(rcBox.Width()), 4000);
|
||||
RGBAImage image(width, static_cast<int>(rcBox.Height()), 1.0, 0);
|
||||
// Draw horizontal lines top and bottom
|
||||
for (int x=0; x<width; x++) {
|
||||
for (int y = 0; y<static_cast<int>(rcBox.Height()); y += static_cast<int>(rcBox.Height()) - 1) {
|
||||
image.SetPixel(x, y, fore, ((x + y) % 2) ? outlineAlpha : fillAlpha);
|
||||
}
|
||||
}
|
||||
// Draw vertical lines left and right
|
||||
for (int y = 1; y<static_cast<int>(rcBox.Height()); y++) {
|
||||
for (int x=0; x<width; x += width-1) {
|
||||
image.SetPixel(x, y, fore, ((x + y) % 2) ? outlineAlpha : fillAlpha);
|
||||
}
|
||||
}
|
||||
surface->DrawRGBAImage(rcBox, image.GetWidth(), image.GetHeight(), image.Pixels());
|
||||
} else if (style == INDIC_DASH) {
|
||||
int x = static_cast<int>(rc.left);
|
||||
while (x < rc.right) {
|
||||
surface->MoveTo(x, ymid);
|
||||
surface->LineTo(Platform::Minimum(x + 4, static_cast<int>(rc.right)), ymid);
|
||||
x += 7;
|
||||
}
|
||||
} else if (style == INDIC_DOTS) {
|
||||
int x = static_cast<int>(rc.left);
|
||||
while (x < static_cast<int>(rc.right)) {
|
||||
PRectangle rcDot = PRectangle::FromInts(x, ymid, x + 1, ymid + 1);
|
||||
surface->FillRectangle(rcDot, fore);
|
||||
x += 2;
|
||||
}
|
||||
} else if (style == INDIC_COMPOSITIONTHICK) {
|
||||
PRectangle rcComposition(rc.left+1, rcLine.bottom-2, rc.right-1, rcLine.bottom);
|
||||
surface->FillRectangle(rcComposition, fore);
|
||||
} else { // Either INDIC_PLAIN or unknown
|
||||
surface->MoveTo(static_cast<int>(rc.left), ymid);
|
||||
surface->LineTo(static_cast<int>(rc.right), ymid);
|
||||
}
|
||||
}
|
||||
|
||||
33
third-party/scintilla/Indicator.h
vendored
Normal file
33
third-party/scintilla/Indicator.h
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file Indicator.h
|
||||
** Defines the style of indicators which are text decorations such as underlining.
|
||||
**/
|
||||
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef INDICATOR_H
|
||||
#define INDICATOR_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
/**
|
||||
*/
|
||||
class Indicator {
|
||||
public:
|
||||
int style;
|
||||
bool under;
|
||||
ColourDesired fore;
|
||||
int fillAlpha;
|
||||
int outlineAlpha;
|
||||
Indicator() : style(INDIC_PLAIN), under(false), fore(ColourDesired(0,0,0)), fillAlpha(30), outlineAlpha(50) {
|
||||
}
|
||||
void Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine);
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
155
third-party/scintilla/KeyMap.cxx
vendored
Normal file
155
third-party/scintilla/KeyMap.cxx
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file KeyMap.cxx
|
||||
** Defines a mapping between keystrokes and commands.
|
||||
**/
|
||||
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
|
||||
#include "KeyMap.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
KeyMap::KeyMap() {
|
||||
for (int i = 0; MapDefault[i].key; i++) {
|
||||
AssignCmdKey(MapDefault[i].key,
|
||||
MapDefault[i].modifiers,
|
||||
MapDefault[i].msg);
|
||||
}
|
||||
}
|
||||
|
||||
KeyMap::~KeyMap() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void KeyMap::Clear() {
|
||||
kmap.clear();
|
||||
}
|
||||
|
||||
void KeyMap::AssignCmdKey(int key, int modifiers, unsigned int msg) {
|
||||
kmap[KeyModifiers(key, modifiers)] = msg;
|
||||
}
|
||||
|
||||
unsigned int KeyMap::Find(int key, int modifiers) const {
|
||||
std::map<KeyModifiers, unsigned int>::const_iterator it = kmap.find(KeyModifiers(key, modifiers));
|
||||
return (it == kmap.end()) ? 0 : it->second;
|
||||
}
|
||||
|
||||
#if PLAT_GTK_MACOSX
|
||||
#define OS_X_KEYS 1
|
||||
#else
|
||||
#define OS_X_KEYS 0
|
||||
#endif
|
||||
|
||||
// Define a modifier that is exactly Ctrl key on all platforms
|
||||
// Most uses of Ctrl map to Cmd on OS X but some can't so use SCI_[S]CTRL_META
|
||||
#if OS_X_KEYS
|
||||
#define SCI_CTRL_META SCI_META
|
||||
#define SCI_SCTRL_META (SCI_META | SCI_SHIFT)
|
||||
#else
|
||||
#define SCI_CTRL_META SCI_CTRL
|
||||
#define SCI_SCTRL_META (SCI_CTRL | SCI_SHIFT)
|
||||
#endif
|
||||
|
||||
const KeyToCommand KeyMap::MapDefault[] = {
|
||||
|
||||
#if OS_X_KEYS
|
||||
{SCK_DOWN, SCI_CTRL, SCI_DOCUMENTEND},
|
||||
{SCK_DOWN, SCI_CSHIFT, SCI_DOCUMENTENDEXTEND},
|
||||
{SCK_UP, SCI_CTRL, SCI_DOCUMENTSTART},
|
||||
{SCK_UP, SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND},
|
||||
{SCK_LEFT, SCI_CTRL, SCI_VCHOME},
|
||||
{SCK_LEFT, SCI_CSHIFT, SCI_VCHOMEEXTEND},
|
||||
{SCK_RIGHT, SCI_CTRL, SCI_LINEEND},
|
||||
{SCK_RIGHT, SCI_CSHIFT, SCI_LINEENDEXTEND},
|
||||
#endif
|
||||
|
||||
{SCK_DOWN, SCI_NORM, SCI_LINEDOWN},
|
||||
{SCK_DOWN, SCI_SHIFT, SCI_LINEDOWNEXTEND},
|
||||
{SCK_DOWN, SCI_CTRL_META, SCI_LINESCROLLDOWN},
|
||||
{SCK_DOWN, SCI_ASHIFT, SCI_LINEDOWNRECTEXTEND},
|
||||
{SCK_UP, SCI_NORM, SCI_LINEUP},
|
||||
{SCK_UP, SCI_SHIFT, SCI_LINEUPEXTEND},
|
||||
{SCK_UP, SCI_CTRL_META, SCI_LINESCROLLUP},
|
||||
{SCK_UP, SCI_ASHIFT, SCI_LINEUPRECTEXTEND},
|
||||
{'[', SCI_CTRL, SCI_PARAUP},
|
||||
{'[', SCI_CSHIFT, SCI_PARAUPEXTEND},
|
||||
{']', SCI_CTRL, SCI_PARADOWN},
|
||||
{']', SCI_CSHIFT, SCI_PARADOWNEXTEND},
|
||||
{SCK_LEFT, SCI_NORM, SCI_CHARLEFT},
|
||||
{SCK_LEFT, SCI_SHIFT, SCI_CHARLEFTEXTEND},
|
||||
{SCK_LEFT, SCI_CTRL_META, SCI_WORDLEFT},
|
||||
{SCK_LEFT, SCI_SCTRL_META, SCI_WORDLEFTEXTEND},
|
||||
{SCK_LEFT, SCI_ASHIFT, SCI_CHARLEFTRECTEXTEND},
|
||||
{SCK_RIGHT, SCI_NORM, SCI_CHARRIGHT},
|
||||
{SCK_RIGHT, SCI_SHIFT, SCI_CHARRIGHTEXTEND},
|
||||
{SCK_RIGHT, SCI_CTRL_META, SCI_WORDRIGHT},
|
||||
{SCK_RIGHT, SCI_SCTRL_META, SCI_WORDRIGHTEXTEND},
|
||||
{SCK_RIGHT, SCI_ASHIFT, SCI_CHARRIGHTRECTEXTEND},
|
||||
{'/', SCI_CTRL, SCI_WORDPARTLEFT},
|
||||
{'/', SCI_CSHIFT, SCI_WORDPARTLEFTEXTEND},
|
||||
{'\\', SCI_CTRL, SCI_WORDPARTRIGHT},
|
||||
{'\\', SCI_CSHIFT, SCI_WORDPARTRIGHTEXTEND},
|
||||
{SCK_HOME, SCI_NORM, SCI_VCHOME},
|
||||
{SCK_HOME, SCI_SHIFT, SCI_VCHOMEEXTEND},
|
||||
{SCK_HOME, SCI_CTRL, SCI_DOCUMENTSTART},
|
||||
{SCK_HOME, SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND},
|
||||
{SCK_HOME, SCI_ALT, SCI_HOMEDISPLAY},
|
||||
{SCK_HOME, SCI_ASHIFT, SCI_VCHOMERECTEXTEND},
|
||||
{SCK_END, SCI_NORM, SCI_LINEEND},
|
||||
{SCK_END, SCI_SHIFT, SCI_LINEENDEXTEND},
|
||||
{SCK_END, SCI_CTRL, SCI_DOCUMENTEND},
|
||||
{SCK_END, SCI_CSHIFT, SCI_DOCUMENTENDEXTEND},
|
||||
{SCK_END, SCI_ALT, SCI_LINEENDDISPLAY},
|
||||
{SCK_END, SCI_ASHIFT, SCI_LINEENDRECTEXTEND},
|
||||
{SCK_PRIOR, SCI_NORM, SCI_PAGEUP},
|
||||
{SCK_PRIOR, SCI_SHIFT, SCI_PAGEUPEXTEND},
|
||||
{SCK_PRIOR, SCI_ASHIFT, SCI_PAGEUPRECTEXTEND},
|
||||
{SCK_NEXT, SCI_NORM, SCI_PAGEDOWN},
|
||||
{SCK_NEXT, SCI_SHIFT, SCI_PAGEDOWNEXTEND},
|
||||
{SCK_NEXT, SCI_ASHIFT, SCI_PAGEDOWNRECTEXTEND},
|
||||
{SCK_DELETE, SCI_NORM, SCI_CLEAR},
|
||||
{SCK_DELETE, SCI_SHIFT, SCI_CUT},
|
||||
{SCK_DELETE, SCI_CTRL, SCI_DELWORDRIGHT},
|
||||
{SCK_DELETE, SCI_CSHIFT, SCI_DELLINERIGHT},
|
||||
{SCK_INSERT, SCI_NORM, SCI_EDITTOGGLEOVERTYPE},
|
||||
{SCK_INSERT, SCI_SHIFT, SCI_PASTE},
|
||||
{SCK_INSERT, SCI_CTRL, SCI_COPY},
|
||||
{SCK_ESCAPE, SCI_NORM, SCI_CANCEL},
|
||||
{SCK_BACK, SCI_NORM, SCI_DELETEBACK},
|
||||
{SCK_BACK, SCI_SHIFT, SCI_DELETEBACK},
|
||||
{SCK_BACK, SCI_CTRL, SCI_DELWORDLEFT},
|
||||
{SCK_BACK, SCI_ALT, SCI_UNDO},
|
||||
{SCK_BACK, SCI_CSHIFT, SCI_DELLINELEFT},
|
||||
{'Z', SCI_CTRL, SCI_UNDO},
|
||||
#if OS_X_KEYS
|
||||
{'Z', SCI_CSHIFT, SCI_REDO},
|
||||
#else
|
||||
{'Y', SCI_CTRL, SCI_REDO},
|
||||
#endif
|
||||
{'X', SCI_CTRL, SCI_CUT},
|
||||
{'C', SCI_CTRL, SCI_COPY},
|
||||
{'V', SCI_CTRL, SCI_PASTE},
|
||||
{'A', SCI_CTRL, SCI_SELECTALL},
|
||||
{SCK_TAB, SCI_NORM, SCI_TAB},
|
||||
{SCK_TAB, SCI_SHIFT, SCI_BACKTAB},
|
||||
{SCK_RETURN, SCI_NORM, SCI_NEWLINE},
|
||||
{SCK_RETURN, SCI_SHIFT, SCI_NEWLINE},
|
||||
{SCK_ADD, SCI_CTRL, SCI_ZOOMIN},
|
||||
{SCK_SUBTRACT, SCI_CTRL, SCI_ZOOMOUT},
|
||||
{SCK_DIVIDE, SCI_CTRL, SCI_SETZOOM},
|
||||
{'L', SCI_CTRL, SCI_LINECUT},
|
||||
{'L', SCI_CSHIFT, SCI_LINEDELETE},
|
||||
{'T', SCI_CSHIFT, SCI_LINECOPY},
|
||||
{'T', SCI_CTRL, SCI_LINETRANSPOSE},
|
||||
{'D', SCI_CTRL, SCI_SELECTIONDUPLICATE},
|
||||
{'U', SCI_CTRL, SCI_LOWERCASE},
|
||||
{'U', SCI_CSHIFT, SCI_UPPERCASE},
|
||||
{0,0,0},
|
||||
};
|
||||
|
||||
66
third-party/scintilla/KeyMap.h
vendored
Normal file
66
third-party/scintilla/KeyMap.h
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file KeyMap.h
|
||||
** Defines a mapping between keystrokes and commands.
|
||||
**/
|
||||
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef KEYMAP_H
|
||||
#define KEYMAP_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
#define SCI_NORM 0
|
||||
#define SCI_SHIFT SCMOD_SHIFT
|
||||
#define SCI_CTRL SCMOD_CTRL
|
||||
#define SCI_ALT SCMOD_ALT
|
||||
#define SCI_META SCMOD_META
|
||||
#define SCI_CSHIFT (SCI_CTRL | SCI_SHIFT)
|
||||
#define SCI_ASHIFT (SCI_ALT | SCI_SHIFT)
|
||||
|
||||
/**
|
||||
*/
|
||||
class KeyModifiers {
|
||||
public:
|
||||
int key;
|
||||
int modifiers;
|
||||
KeyModifiers(int key_, int modifiers_) : key(key_), modifiers(modifiers_) {
|
||||
}
|
||||
bool operator<(const KeyModifiers &other) const {
|
||||
if (key == other.key)
|
||||
return modifiers < other.modifiers;
|
||||
else
|
||||
return key < other.key;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class KeyToCommand {
|
||||
public:
|
||||
int key;
|
||||
int modifiers;
|
||||
unsigned int msg;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class KeyMap {
|
||||
std::map<KeyModifiers, unsigned int> kmap;
|
||||
static const KeyToCommand MapDefault[];
|
||||
|
||||
public:
|
||||
KeyMap();
|
||||
~KeyMap();
|
||||
void Clear();
|
||||
void AssignCmdKey(int key, int modifiers, unsigned int msg);
|
||||
unsigned int Find(int key, int modifiers) const; // 0 returned on failure
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
213
third-party/scintilla/LexAccessor.h
vendored
Normal file
213
third-party/scintilla/LexAccessor.h
vendored
Normal file
@@ -0,0 +1,213 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file LexAccessor.h
|
||||
** Interfaces between Scintilla and lexers.
|
||||
**/
|
||||
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef LEXACCESSOR_H
|
||||
#define LEXACCESSOR_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
enum EncodingType { enc8bit, encUnicode, encDBCS };
|
||||
|
||||
class LexAccessor {
|
||||
private:
|
||||
IDocument *pAccess;
|
||||
enum {extremePosition=0x7FFFFFFF};
|
||||
/** @a bufferSize is a trade off between time taken to copy the characters
|
||||
* and retrieval overhead.
|
||||
* @a slopSize positions the buffer before the desired position
|
||||
* in case there is some backtracking. */
|
||||
enum {bufferSize=4000, slopSize=bufferSize/8};
|
||||
char buf[bufferSize+1];
|
||||
int startPos;
|
||||
int endPos;
|
||||
int codePage;
|
||||
enum EncodingType encodingType;
|
||||
int lenDoc;
|
||||
int mask;
|
||||
char styleBuf[bufferSize];
|
||||
int validLen;
|
||||
char chFlags;
|
||||
char chWhile;
|
||||
unsigned int startSeg;
|
||||
int startPosStyling;
|
||||
int documentVersion;
|
||||
|
||||
void Fill(int position) {
|
||||
startPos = position - slopSize;
|
||||
if (startPos + bufferSize > lenDoc)
|
||||
startPos = lenDoc - bufferSize;
|
||||
if (startPos < 0)
|
||||
startPos = 0;
|
||||
endPos = startPos + bufferSize;
|
||||
if (endPos > lenDoc)
|
||||
endPos = lenDoc;
|
||||
|
||||
pAccess->GetCharRange(buf, startPos, endPos-startPos);
|
||||
buf[endPos-startPos] = '\0';
|
||||
}
|
||||
|
||||
public:
|
||||
explicit LexAccessor(IDocument *pAccess_) :
|
||||
pAccess(pAccess_), startPos(extremePosition), endPos(0),
|
||||
codePage(pAccess->CodePage()),
|
||||
encodingType(enc8bit),
|
||||
lenDoc(pAccess->Length()),
|
||||
mask(127), validLen(0), chFlags(0), chWhile(0),
|
||||
startSeg(0), startPosStyling(0),
|
||||
documentVersion(pAccess->Version()) {
|
||||
switch (codePage) {
|
||||
case 65001:
|
||||
encodingType = encUnicode;
|
||||
break;
|
||||
case 932:
|
||||
case 936:
|
||||
case 949:
|
||||
case 950:
|
||||
case 1361:
|
||||
encodingType = encDBCS;
|
||||
}
|
||||
}
|
||||
char operator[](int position) {
|
||||
if (position < startPos || position >= endPos) {
|
||||
Fill(position);
|
||||
}
|
||||
return buf[position - startPos];
|
||||
}
|
||||
IDocumentWithLineEnd *MultiByteAccess() const {
|
||||
if (documentVersion >= dvLineEnd) {
|
||||
return static_cast<IDocumentWithLineEnd *>(pAccess);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/** Safe version of operator[], returning a defined value for invalid position. */
|
||||
char SafeGetCharAt(int position, char chDefault=' ') {
|
||||
if (position < startPos || position >= endPos) {
|
||||
Fill(position);
|
||||
if (position < startPos || position >= endPos) {
|
||||
// Position is outside range of document
|
||||
return chDefault;
|
||||
}
|
||||
}
|
||||
return buf[position - startPos];
|
||||
}
|
||||
bool IsLeadByte(char ch) const {
|
||||
return pAccess->IsDBCSLeadByte(ch);
|
||||
}
|
||||
EncodingType Encoding() const {
|
||||
return encodingType;
|
||||
}
|
||||
bool Match(int pos, const char *s) {
|
||||
for (int i=0; *s; i++) {
|
||||
if (*s != SafeGetCharAt(pos+i))
|
||||
return false;
|
||||
s++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
char StyleAt(int position) const {
|
||||
return static_cast<char>(pAccess->StyleAt(position) & mask);
|
||||
}
|
||||
int GetLine(int position) const {
|
||||
return pAccess->LineFromPosition(position);
|
||||
}
|
||||
int LineStart(int line) const {
|
||||
return pAccess->LineStart(line);
|
||||
}
|
||||
int LineEnd(int line) {
|
||||
if (documentVersion >= dvLineEnd) {
|
||||
return (static_cast<IDocumentWithLineEnd *>(pAccess))->LineEnd(line);
|
||||
} else {
|
||||
// Old interface means only '\r', '\n' and '\r\n' line ends.
|
||||
int startNext = pAccess->LineStart(line+1);
|
||||
char chLineEnd = SafeGetCharAt(startNext-1);
|
||||
if (chLineEnd == '\n' && (SafeGetCharAt(startNext-2) == '\r'))
|
||||
return startNext - 2;
|
||||
else
|
||||
return startNext - 1;
|
||||
}
|
||||
}
|
||||
int LevelAt(int line) const {
|
||||
return pAccess->GetLevel(line);
|
||||
}
|
||||
int Length() const {
|
||||
return lenDoc;
|
||||
}
|
||||
void Flush() {
|
||||
if (validLen > 0) {
|
||||
pAccess->SetStyles(validLen, styleBuf);
|
||||
startPosStyling += validLen;
|
||||
validLen = 0;
|
||||
}
|
||||
}
|
||||
int GetLineState(int line) const {
|
||||
return pAccess->GetLineState(line);
|
||||
}
|
||||
int SetLineState(int line, int state) {
|
||||
return pAccess->SetLineState(line, state);
|
||||
}
|
||||
// Style setting
|
||||
void StartAt(unsigned int start, char chMask=31) {
|
||||
// Store the mask specified for use with StyleAt.
|
||||
mask = chMask;
|
||||
pAccess->StartStyling(start, chMask);
|
||||
startPosStyling = start;
|
||||
}
|
||||
void SetFlags(char chFlags_, char chWhile_) {
|
||||
chFlags = chFlags_;
|
||||
chWhile = chWhile_;
|
||||
}
|
||||
unsigned int GetStartSegment() const {
|
||||
return startSeg;
|
||||
}
|
||||
void StartSegment(unsigned int pos) {
|
||||
startSeg = pos;
|
||||
}
|
||||
void ColourTo(unsigned int pos, int chAttr) {
|
||||
// Only perform styling if non empty range
|
||||
if (pos != startSeg - 1) {
|
||||
assert(pos >= startSeg);
|
||||
if (pos < startSeg) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (validLen + (pos - startSeg + 1) >= bufferSize)
|
||||
Flush();
|
||||
if (validLen + (pos - startSeg + 1) >= bufferSize) {
|
||||
// Too big for buffer so send directly
|
||||
pAccess->SetStyleFor(pos - startSeg + 1, static_cast<char>(chAttr));
|
||||
} else {
|
||||
if (chAttr != chWhile)
|
||||
chFlags = 0;
|
||||
chAttr = static_cast<char>(chAttr | chFlags);
|
||||
for (unsigned int i = startSeg; i <= pos; i++) {
|
||||
assert((startPosStyling + validLen) < Length());
|
||||
styleBuf[validLen++] = static_cast<char>(chAttr);
|
||||
}
|
||||
}
|
||||
}
|
||||
startSeg = pos+1;
|
||||
}
|
||||
void SetLevel(int line, int level) {
|
||||
pAccess->SetLevel(line, level);
|
||||
}
|
||||
void IndicatorFill(int start, int end, int indicator, int value) {
|
||||
pAccess->DecorationSetCurrentIndicator(indicator);
|
||||
pAccess->DecorationFillRange(start, value, end - start);
|
||||
}
|
||||
|
||||
void ChangeLexerState(int start, int end) {
|
||||
pAccess->ChangeLexerState(start, end);
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
429
third-party/scintilla/LexLua.cxx
vendored
Normal file
429
third-party/scintilla/LexLua.cxx
vendored
Normal file
@@ -0,0 +1,429 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file LexLua.cxx
|
||||
** Lexer for Lua language.
|
||||
**
|
||||
** Written by Paul Winwood.
|
||||
** Folder by Alexey Yutkin.
|
||||
** Modified by Marcos E. Wurzius & Philippe Lhoste
|
||||
**/
|
||||
|
||||
#include "ILexer.h"
|
||||
#include "Scintilla.h"
|
||||
#include "SciLexer.h"
|
||||
|
||||
#include "WordList.h"
|
||||
#include "LexAccessor.h"
|
||||
#include "Accessor.h"
|
||||
#include "StyleContext.h"
|
||||
#include "CharacterSet.h"
|
||||
#include "LexerModule.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
// Test for [=[ ... ]=] delimiters, returns 0 if it's only a [ or ],
|
||||
// return 1 for [[ or ]], returns >=2 for [=[ or ]=] and so on.
|
||||
// The maximum number of '=' characters allowed is 254.
|
||||
static int LongDelimCheck(StyleContext &sc) {
|
||||
int sep = 1;
|
||||
while (sc.GetRelative(sep) == '=' && sep < 0xFF)
|
||||
sep++;
|
||||
if (sc.GetRelative(sep) == sc.ch)
|
||||
return sep;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ColouriseLuaDoc(
|
||||
unsigned int startPos,
|
||||
int length,
|
||||
int initStyle,
|
||||
WordList *keywordlists[],
|
||||
Accessor &styler) {
|
||||
|
||||
WordList &keywords = *keywordlists[0];
|
||||
WordList &keywords2 = *keywordlists[1];
|
||||
WordList &keywords3 = *keywordlists[2];
|
||||
WordList &keywords4 = *keywordlists[3];
|
||||
WordList &keywords5 = *keywordlists[4];
|
||||
WordList &keywords6 = *keywordlists[5];
|
||||
WordList &keywords7 = *keywordlists[6];
|
||||
WordList &keywords8 = *keywordlists[7];
|
||||
|
||||
// Accepts accented characters
|
||||
CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
|
||||
CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true);
|
||||
// Not exactly following number definition (several dots are seen as OK, etc.)
|
||||
// but probably enough in most cases. [pP] is for hex floats.
|
||||
CharacterSet setNumber(CharacterSet::setDigits, ".-+abcdefpABCDEFP");
|
||||
CharacterSet setExponent(CharacterSet::setNone, "eEpP");
|
||||
CharacterSet setLuaOperator(CharacterSet::setNone, "*/-+()={}~[];<>,.^%:#");
|
||||
CharacterSet setEscapeSkip(CharacterSet::setNone, "\"'\\");
|
||||
|
||||
int currentLine = styler.GetLine(startPos);
|
||||
// Initialize long string [[ ... ]] or block comment --[[ ... ]] nesting level,
|
||||
// if we are inside such a string. Block comment was introduced in Lua 5.0,
|
||||
// blocks with separators [=[ ... ]=] in Lua 5.1.
|
||||
// Continuation of a string (\z whitespace escaping) is controlled by stringWs.
|
||||
int nestLevel = 0;
|
||||
int sepCount = 0;
|
||||
int stringWs = 0;
|
||||
if (initStyle == SCE_LUA_LITERALSTRING || initStyle == SCE_LUA_COMMENT ||
|
||||
initStyle == SCE_LUA_STRING || initStyle == SCE_LUA_CHARACTER) {
|
||||
int lineState = styler.GetLineState(currentLine - 1);
|
||||
nestLevel = lineState >> 9;
|
||||
sepCount = lineState & 0xFF;
|
||||
stringWs = lineState & 0x100;
|
||||
}
|
||||
|
||||
// Do not leak onto next line
|
||||
if (initStyle == SCE_LUA_STRINGEOL || initStyle == SCE_LUA_COMMENTLINE || initStyle == SCE_LUA_PREPROCESSOR) {
|
||||
initStyle = SCE_LUA_DEFAULT;
|
||||
}
|
||||
|
||||
StyleContext sc(startPos, length, initStyle, styler);
|
||||
if (startPos == 0 && sc.ch == '#') {
|
||||
// shbang line: # is a comment only if first char of the script
|
||||
sc.SetState(SCE_LUA_COMMENTLINE);
|
||||
}
|
||||
for (; sc.More(); sc.Forward()) {
|
||||
if (sc.atLineEnd) {
|
||||
// Update the line state, so it can be seen by next line
|
||||
currentLine = styler.GetLine(sc.currentPos);
|
||||
switch (sc.state) {
|
||||
case SCE_LUA_LITERALSTRING:
|
||||
case SCE_LUA_COMMENT:
|
||||
case SCE_LUA_STRING:
|
||||
case SCE_LUA_CHARACTER:
|
||||
// Inside a literal string, block comment or string, we set the line state
|
||||
styler.SetLineState(currentLine, (nestLevel << 9) | stringWs | sepCount);
|
||||
break;
|
||||
default:
|
||||
// Reset the line state
|
||||
styler.SetLineState(currentLine, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (sc.atLineStart && (sc.state == SCE_LUA_STRING)) {
|
||||
// Prevent SCE_LUA_STRINGEOL from leaking back to previous line
|
||||
sc.SetState(SCE_LUA_STRING);
|
||||
}
|
||||
|
||||
// Handle string line continuation
|
||||
if ((sc.state == SCE_LUA_STRING || sc.state == SCE_LUA_CHARACTER) &&
|
||||
sc.ch == '\\') {
|
||||
if (sc.chNext == '\n' || sc.chNext == '\r') {
|
||||
sc.Forward();
|
||||
if (sc.ch == '\r' && sc.chNext == '\n') {
|
||||
sc.Forward();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if the current state should terminate.
|
||||
if (sc.state == SCE_LUA_OPERATOR) {
|
||||
if (sc.ch == ':' && sc.chPrev == ':') { // :: <label> :: forward scan
|
||||
sc.Forward();
|
||||
int ln = 0;
|
||||
while (IsASpaceOrTab(sc.GetRelative(ln))) // skip over spaces/tabs
|
||||
ln++;
|
||||
int ws1 = ln;
|
||||
if (setWordStart.Contains(sc.GetRelative(ln))) {
|
||||
int c, i = 0;
|
||||
char s[100];
|
||||
while (setWord.Contains(c = sc.GetRelative(ln))) { // get potential label
|
||||
if (i < 90)
|
||||
s[i++] = static_cast<char>(c);
|
||||
ln++;
|
||||
}
|
||||
s[i] = '\0'; int lbl = ln;
|
||||
if (!keywords.InList(s)) {
|
||||
while (IsASpaceOrTab(sc.GetRelative(ln))) // skip over spaces/tabs
|
||||
ln++;
|
||||
int ws2 = ln - lbl;
|
||||
if (sc.GetRelative(ln) == ':' && sc.GetRelative(ln + 1) == ':') {
|
||||
// final :: found, complete valid label construct
|
||||
sc.ChangeState(SCE_LUA_LABEL);
|
||||
if (ws1) {
|
||||
sc.SetState(SCE_LUA_DEFAULT);
|
||||
sc.ForwardBytes(ws1);
|
||||
}
|
||||
sc.SetState(SCE_LUA_LABEL);
|
||||
sc.ForwardBytes(lbl - ws1);
|
||||
if (ws2) {
|
||||
sc.SetState(SCE_LUA_DEFAULT);
|
||||
sc.ForwardBytes(ws2);
|
||||
}
|
||||
sc.SetState(SCE_LUA_LABEL);
|
||||
sc.ForwardBytes(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sc.SetState(SCE_LUA_DEFAULT);
|
||||
} else if (sc.state == SCE_LUA_NUMBER) {
|
||||
// We stop the number definition on non-numerical non-dot non-eEpP non-sign non-hexdigit char
|
||||
if (!setNumber.Contains(sc.ch)) {
|
||||
sc.SetState(SCE_LUA_DEFAULT);
|
||||
} else if (sc.ch == '-' || sc.ch == '+') {
|
||||
if (!setExponent.Contains(sc.chPrev))
|
||||
sc.SetState(SCE_LUA_DEFAULT);
|
||||
}
|
||||
} else if (sc.state == SCE_LUA_IDENTIFIER) {
|
||||
if (!(setWord.Contains(sc.ch) || sc.ch == '.') || sc.Match('.', '.')) {
|
||||
char s[100];
|
||||
sc.GetCurrent(s, sizeof(s));
|
||||
if (keywords.InList(s)) {
|
||||
sc.ChangeState(SCE_LUA_WORD);
|
||||
if (strcmp(s, "goto") == 0) { // goto <label> forward scan
|
||||
sc.SetState(SCE_LUA_DEFAULT);
|
||||
while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd)
|
||||
sc.Forward();
|
||||
if (setWordStart.Contains(sc.ch)) {
|
||||
sc.SetState(SCE_LUA_LABEL);
|
||||
sc.Forward();
|
||||
while (setWord.Contains(sc.ch))
|
||||
sc.Forward();
|
||||
sc.GetCurrent(s, sizeof(s));
|
||||
if (keywords.InList(s))
|
||||
sc.ChangeState(SCE_LUA_WORD);
|
||||
}
|
||||
sc.SetState(SCE_LUA_DEFAULT);
|
||||
}
|
||||
} else if (keywords2.InList(s)) {
|
||||
sc.ChangeState(SCE_LUA_WORD2);
|
||||
} else if (keywords3.InList(s)) {
|
||||
sc.ChangeState(SCE_LUA_WORD3);
|
||||
} else if (keywords4.InList(s)) {
|
||||
sc.ChangeState(SCE_LUA_WORD4);
|
||||
} else if (keywords5.InList(s)) {
|
||||
sc.ChangeState(SCE_LUA_WORD5);
|
||||
} else if (keywords6.InList(s)) {
|
||||
sc.ChangeState(SCE_LUA_WORD6);
|
||||
} else if (keywords7.InList(s)) {
|
||||
sc.ChangeState(SCE_LUA_WORD7);
|
||||
} else if (keywords8.InList(s)) {
|
||||
sc.ChangeState(SCE_LUA_WORD8);
|
||||
}
|
||||
sc.SetState(SCE_LUA_DEFAULT);
|
||||
}
|
||||
} else if (sc.state == SCE_LUA_COMMENTLINE || sc.state == SCE_LUA_PREPROCESSOR) {
|
||||
if (sc.atLineEnd) {
|
||||
sc.ForwardSetState(SCE_LUA_DEFAULT);
|
||||
}
|
||||
} else if (sc.state == SCE_LUA_STRING) {
|
||||
if (stringWs) {
|
||||
if (!IsASpace(sc.ch))
|
||||
stringWs = 0;
|
||||
}
|
||||
if (sc.ch == '\\') {
|
||||
if (setEscapeSkip.Contains(sc.chNext)) {
|
||||
sc.Forward();
|
||||
} else if (sc.chNext == 'z') {
|
||||
sc.Forward();
|
||||
stringWs = 0x100;
|
||||
}
|
||||
} else if (sc.ch == '\"') {
|
||||
sc.ForwardSetState(SCE_LUA_DEFAULT);
|
||||
} else if (stringWs == 0 && sc.atLineEnd) {
|
||||
sc.ChangeState(SCE_LUA_STRINGEOL);
|
||||
sc.ForwardSetState(SCE_LUA_DEFAULT);
|
||||
}
|
||||
} else if (sc.state == SCE_LUA_CHARACTER) {
|
||||
if (stringWs) {
|
||||
if (!IsASpace(sc.ch))
|
||||
stringWs = 0;
|
||||
}
|
||||
if (sc.ch == '\\') {
|
||||
if (setEscapeSkip.Contains(sc.chNext)) {
|
||||
sc.Forward();
|
||||
} else if (sc.chNext == 'z') {
|
||||
sc.Forward();
|
||||
stringWs = 0x100;
|
||||
}
|
||||
} else if (sc.ch == '\'') {
|
||||
sc.ForwardSetState(SCE_LUA_DEFAULT);
|
||||
} else if (stringWs == 0 && sc.atLineEnd) {
|
||||
sc.ChangeState(SCE_LUA_STRINGEOL);
|
||||
sc.ForwardSetState(SCE_LUA_DEFAULT);
|
||||
}
|
||||
} else if (sc.state == SCE_LUA_LITERALSTRING || sc.state == SCE_LUA_COMMENT) {
|
||||
if (sc.ch == '[') {
|
||||
int sep = LongDelimCheck(sc);
|
||||
if (sep == 1 && sepCount == 1) { // [[-only allowed to nest
|
||||
nestLevel++;
|
||||
sc.Forward();
|
||||
}
|
||||
} else if (sc.ch == ']') {
|
||||
int sep = LongDelimCheck(sc);
|
||||
if (sep == 1 && sepCount == 1) { // un-nest with ]]-only
|
||||
nestLevel--;
|
||||
sc.Forward();
|
||||
if (nestLevel == 0) {
|
||||
sc.ForwardSetState(SCE_LUA_DEFAULT);
|
||||
}
|
||||
} else if (sep > 1 && sep == sepCount) { // ]=]-style delim
|
||||
sc.Forward(sep);
|
||||
sc.ForwardSetState(SCE_LUA_DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if a new state should be entered.
|
||||
if (sc.state == SCE_LUA_DEFAULT) {
|
||||
if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
|
||||
sc.SetState(SCE_LUA_NUMBER);
|
||||
if (sc.ch == '0' && toupper(sc.chNext) == 'X') {
|
||||
sc.Forward();
|
||||
}
|
||||
} else if (setWordStart.Contains(sc.ch)) {
|
||||
sc.SetState(SCE_LUA_IDENTIFIER);
|
||||
} else if (sc.ch == '\"') {
|
||||
sc.SetState(SCE_LUA_STRING);
|
||||
stringWs = 0;
|
||||
} else if (sc.ch == '\'') {
|
||||
sc.SetState(SCE_LUA_CHARACTER);
|
||||
stringWs = 0;
|
||||
} else if (sc.ch == '[') {
|
||||
sepCount = LongDelimCheck(sc);
|
||||
if (sepCount == 0) {
|
||||
sc.SetState(SCE_LUA_OPERATOR);
|
||||
} else {
|
||||
nestLevel = 1;
|
||||
sc.SetState(SCE_LUA_LITERALSTRING);
|
||||
sc.Forward(sepCount);
|
||||
}
|
||||
} else if (sc.Match('-', '-')) {
|
||||
sc.SetState(SCE_LUA_COMMENTLINE);
|
||||
if (sc.Match("--[")) {
|
||||
sc.Forward(2);
|
||||
sepCount = LongDelimCheck(sc);
|
||||
if (sepCount > 0) {
|
||||
nestLevel = 1;
|
||||
sc.ChangeState(SCE_LUA_COMMENT);
|
||||
sc.Forward(sepCount);
|
||||
}
|
||||
} else {
|
||||
sc.Forward();
|
||||
}
|
||||
} else if (sc.atLineStart && sc.Match('$')) {
|
||||
sc.SetState(SCE_LUA_PREPROCESSOR); // Obsolete since Lua 4.0, but still in old code
|
||||
} else if (setLuaOperator.Contains(sc.ch)) {
|
||||
sc.SetState(SCE_LUA_OPERATOR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (setWord.Contains(sc.chPrev) || sc.chPrev == '.') {
|
||||
char s[100];
|
||||
sc.GetCurrent(s, sizeof(s));
|
||||
if (keywords.InList(s)) {
|
||||
sc.ChangeState(SCE_LUA_WORD);
|
||||
} else if (keywords2.InList(s)) {
|
||||
sc.ChangeState(SCE_LUA_WORD2);
|
||||
} else if (keywords3.InList(s)) {
|
||||
sc.ChangeState(SCE_LUA_WORD3);
|
||||
} else if (keywords4.InList(s)) {
|
||||
sc.ChangeState(SCE_LUA_WORD4);
|
||||
} else if (keywords5.InList(s)) {
|
||||
sc.ChangeState(SCE_LUA_WORD5);
|
||||
} else if (keywords6.InList(s)) {
|
||||
sc.ChangeState(SCE_LUA_WORD6);
|
||||
} else if (keywords7.InList(s)) {
|
||||
sc.ChangeState(SCE_LUA_WORD7);
|
||||
} else if (keywords8.InList(s)) {
|
||||
sc.ChangeState(SCE_LUA_WORD8);
|
||||
}
|
||||
}
|
||||
|
||||
sc.Complete();
|
||||
}
|
||||
|
||||
static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
|
||||
Accessor &styler) {
|
||||
unsigned int lengthDoc = startPos + length;
|
||||
int visibleChars = 0;
|
||||
int lineCurrent = styler.GetLine(startPos);
|
||||
int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
|
||||
int levelCurrent = levelPrev;
|
||||
char chNext = styler[startPos];
|
||||
bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
|
||||
int styleNext = styler.StyleAt(startPos);
|
||||
|
||||
for (unsigned int i = startPos; i < lengthDoc; i++) {
|
||||
char ch = chNext;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
int style = styleNext;
|
||||
styleNext = styler.StyleAt(i + 1);
|
||||
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
|
||||
if (style == SCE_LUA_WORD) {
|
||||
if (ch == 'i' || ch == 'd' || ch == 'f' || ch == 'e' || ch == 'r' || ch == 'u') {
|
||||
char s[10] = "";
|
||||
for (unsigned int j = 0; j < 8; j++) {
|
||||
if (!iswordchar(styler[i + j])) {
|
||||
break;
|
||||
}
|
||||
s[j] = styler[i + j];
|
||||
s[j + 1] = '\0';
|
||||
}
|
||||
|
||||
if ((strcmp(s, "if") == 0) || (strcmp(s, "do") == 0) || (strcmp(s, "function") == 0) || (strcmp(s, "repeat") == 0)) {
|
||||
levelCurrent++;
|
||||
}
|
||||
if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0) || (strcmp(s, "until") == 0)) {
|
||||
levelCurrent--;
|
||||
}
|
||||
}
|
||||
} else if (style == SCE_LUA_OPERATOR) {
|
||||
if (ch == '{' || ch == '(') {
|
||||
levelCurrent++;
|
||||
} else if (ch == '}' || ch == ')') {
|
||||
levelCurrent--;
|
||||
}
|
||||
} else if (style == SCE_LUA_LITERALSTRING || style == SCE_LUA_COMMENT) {
|
||||
if (ch == '[') {
|
||||
levelCurrent++;
|
||||
} else if (ch == ']') {
|
||||
levelCurrent--;
|
||||
}
|
||||
}
|
||||
|
||||
if (atEOL) {
|
||||
int lev = levelPrev;
|
||||
if (visibleChars == 0 && foldCompact) {
|
||||
lev |= SC_FOLDLEVELWHITEFLAG;
|
||||
}
|
||||
if ((levelCurrent > levelPrev) && (visibleChars > 0)) {
|
||||
lev |= SC_FOLDLEVELHEADERFLAG;
|
||||
}
|
||||
if (lev != styler.LevelAt(lineCurrent)) {
|
||||
styler.SetLevel(lineCurrent, lev);
|
||||
}
|
||||
lineCurrent++;
|
||||
levelPrev = levelCurrent;
|
||||
visibleChars = 0;
|
||||
}
|
||||
if (!isspacechar(ch)) {
|
||||
visibleChars++;
|
||||
}
|
||||
}
|
||||
// Fill in the real level of the next line, keeping the current flags as they will be filled in later
|
||||
|
||||
int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
|
||||
styler.SetLevel(lineCurrent, levelPrev | flagsNext);
|
||||
}
|
||||
|
||||
static const char * const luaWordListDesc[] = {
|
||||
"Keywords",
|
||||
"Basic functions",
|
||||
"String, (table) & math functions",
|
||||
"(coroutines), I/O & system facilities",
|
||||
"user1",
|
||||
"user2",
|
||||
"user3",
|
||||
"user4",
|
||||
0
|
||||
};
|
||||
|
||||
LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc, luaWordListDesc);
|
||||
85
third-party/scintilla/LexerBase.cxx
vendored
Normal file
85
third-party/scintilla/LexerBase.cxx
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file LexerBase.cxx
|
||||
** A simple lexer with no state.
|
||||
**/
|
||||
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "ILexer.h"
|
||||
#include "Scintilla.h"
|
||||
#include "SciLexer.h"
|
||||
|
||||
#include "PropSetSimple.h"
|
||||
#include "WordList.h"
|
||||
#include "LexAccessor.h"
|
||||
#include "Accessor.h"
|
||||
#include "LexerModule.h"
|
||||
#include "LexerBase.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
LexerBase::LexerBase() {
|
||||
for (int wl = 0; wl < numWordLists; wl++)
|
||||
keyWordLists[wl] = new WordList;
|
||||
keyWordLists[numWordLists] = 0;
|
||||
}
|
||||
|
||||
LexerBase::~LexerBase() {
|
||||
for (int wl = 0; wl < numWordLists; wl++) {
|
||||
delete keyWordLists[wl];
|
||||
keyWordLists[wl] = 0;
|
||||
}
|
||||
keyWordLists[numWordLists] = 0;
|
||||
}
|
||||
|
||||
void SCI_METHOD LexerBase::Release() {
|
||||
delete this;
|
||||
}
|
||||
|
||||
int SCI_METHOD LexerBase::Version() const {
|
||||
return lvOriginal;
|
||||
}
|
||||
|
||||
const char * SCI_METHOD LexerBase::PropertyNames() {
|
||||
return "";
|
||||
}
|
||||
|
||||
int SCI_METHOD LexerBase::PropertyType(const char *) {
|
||||
return SC_TYPE_BOOLEAN;
|
||||
}
|
||||
|
||||
const char * SCI_METHOD LexerBase::DescribeProperty(const char *) {
|
||||
return "";
|
||||
}
|
||||
|
||||
int SCI_METHOD LexerBase::PropertySet(const char *key, const char *val) {
|
||||
const char *valOld = props.Get(key);
|
||||
if (strcmp(val, valOld) != 0) {
|
||||
props.Set(key, val);
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
const char * SCI_METHOD LexerBase::DescribeWordListSets() {
|
||||
return "";
|
||||
}
|
||||
|
||||
int SCI_METHOD LexerBase::WordListSet(int n, const char *wl) {
|
||||
if (n < numWordLists) {
|
||||
WordList wlNew;
|
||||
wlNew.Set(wl);
|
||||
if (*keyWordLists[n] != wlNew) {
|
||||
keyWordLists[n]->Set(wl);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void * SCI_METHOD LexerBase::PrivateCall(int, void *) {
|
||||
return 0;
|
||||
}
|
||||
41
third-party/scintilla/LexerBase.h
vendored
Normal file
41
third-party/scintilla/LexerBase.h
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file LexerBase.h
|
||||
** A simple lexer with no state.
|
||||
**/
|
||||
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef LEXERBASE_H
|
||||
#define LEXERBASE_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
// A simple lexer with no state
|
||||
class LexerBase : public ILexer {
|
||||
protected:
|
||||
PropSetSimple props;
|
||||
enum {numWordLists=KEYWORDSET_MAX+1};
|
||||
WordList *keyWordLists[numWordLists+1];
|
||||
public:
|
||||
LexerBase();
|
||||
virtual ~LexerBase();
|
||||
void SCI_METHOD Release();
|
||||
int SCI_METHOD Version() const;
|
||||
const char * SCI_METHOD PropertyNames();
|
||||
int SCI_METHOD PropertyType(const char *name);
|
||||
const char * SCI_METHOD DescribeProperty(const char *name);
|
||||
int SCI_METHOD PropertySet(const char *key, const char *val);
|
||||
const char * SCI_METHOD DescribeWordListSets();
|
||||
int SCI_METHOD WordListSet(int n, const char *wl);
|
||||
void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0;
|
||||
void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0;
|
||||
void * SCI_METHOD PrivateCall(int operation, void *pointer);
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
110
third-party/scintilla/LexerModule.cxx
vendored
Normal file
110
third-party/scintilla/LexerModule.cxx
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file LexerModule.cxx
|
||||
** Colourise for particular languages.
|
||||
**/
|
||||
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "ILexer.h"
|
||||
#include "Scintilla.h"
|
||||
#include "SciLexer.h"
|
||||
|
||||
#include "PropSetSimple.h"
|
||||
#include "WordList.h"
|
||||
#include "LexAccessor.h"
|
||||
#include "Accessor.h"
|
||||
#include "LexerModule.h"
|
||||
#include "LexerBase.h"
|
||||
#include "LexerSimple.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
LexerModule::LexerModule(int language_,
|
||||
LexerFunction fnLexer_,
|
||||
const char *languageName_,
|
||||
LexerFunction fnFolder_,
|
||||
const char *const wordListDescriptions_[],
|
||||
int styleBits_) :
|
||||
language(language_),
|
||||
fnLexer(fnLexer_),
|
||||
fnFolder(fnFolder_),
|
||||
fnFactory(0),
|
||||
wordListDescriptions(wordListDescriptions_),
|
||||
styleBits(styleBits_),
|
||||
languageName(languageName_) {
|
||||
}
|
||||
|
||||
LexerModule::LexerModule(int language_,
|
||||
LexerFactoryFunction fnFactory_,
|
||||
const char *languageName_,
|
||||
const char * const wordListDescriptions_[],
|
||||
int styleBits_) :
|
||||
language(language_),
|
||||
fnLexer(0),
|
||||
fnFolder(0),
|
||||
fnFactory(fnFactory_),
|
||||
wordListDescriptions(wordListDescriptions_),
|
||||
styleBits(styleBits_),
|
||||
languageName(languageName_) {
|
||||
}
|
||||
|
||||
int LexerModule::GetNumWordLists() const {
|
||||
if (wordListDescriptions == NULL) {
|
||||
return -1;
|
||||
} else {
|
||||
int numWordLists = 0;
|
||||
|
||||
while (wordListDescriptions[numWordLists]) {
|
||||
++numWordLists;
|
||||
}
|
||||
|
||||
return numWordLists;
|
||||
}
|
||||
}
|
||||
|
||||
const char *LexerModule::GetWordListDescription(int index) const {
|
||||
assert(index < GetNumWordLists());
|
||||
if (!wordListDescriptions || (index >= GetNumWordLists())) {
|
||||
return "";
|
||||
} else {
|
||||
return wordListDescriptions[index];
|
||||
}
|
||||
}
|
||||
|
||||
int LexerModule::GetStyleBitsNeeded() const {
|
||||
return styleBits;
|
||||
}
|
||||
|
||||
ILexer *LexerModule::Create() const {
|
||||
if (fnFactory)
|
||||
return fnFactory();
|
||||
else
|
||||
return new LexerSimple(this);
|
||||
}
|
||||
|
||||
void LexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
|
||||
WordList *keywordlists[], Accessor &styler) const {
|
||||
if (fnLexer)
|
||||
fnLexer(startPos, lengthDoc, initStyle, keywordlists, styler);
|
||||
}
|
||||
|
||||
void LexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
|
||||
WordList *keywordlists[], Accessor &styler) const {
|
||||
if (fnFolder) {
|
||||
int lineCurrent = styler.GetLine(startPos);
|
||||
// Move back one line in case deletion wrecked current line fold state
|
||||
if (lineCurrent > 0) {
|
||||
lineCurrent--;
|
||||
int newStartPos = styler.LineStart(lineCurrent);
|
||||
lengthDoc += startPos - newStartPos;
|
||||
startPos = newStartPos;
|
||||
initStyle = 0;
|
||||
if (startPos > 0) {
|
||||
initStyle = styler.StyleAt(startPos - 1);
|
||||
}
|
||||
}
|
||||
fnFolder(startPos, lengthDoc, initStyle, keywordlists, styler);
|
||||
}
|
||||
}
|
||||
82
third-party/scintilla/LexerModule.h
vendored
Normal file
82
third-party/scintilla/LexerModule.h
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file LexerModule.h
|
||||
** Colourise for particular languages.
|
||||
**/
|
||||
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef LEXERMODULE_H
|
||||
#define LEXERMODULE_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
class Accessor;
|
||||
class WordList;
|
||||
|
||||
typedef void (*LexerFunction)(unsigned int startPos, int lengthDoc, int initStyle,
|
||||
WordList *keywordlists[], Accessor &styler);
|
||||
typedef ILexer *(*LexerFactoryFunction)();
|
||||
|
||||
/**
|
||||
* A LexerModule is responsible for lexing and folding a particular language.
|
||||
* The class maintains a list of LexerModules which can be searched to find a
|
||||
* module appropriate to a particular language.
|
||||
*/
|
||||
class LexerModule {
|
||||
protected:
|
||||
int language;
|
||||
LexerFunction fnLexer;
|
||||
LexerFunction fnFolder;
|
||||
LexerFactoryFunction fnFactory;
|
||||
const char * const * wordListDescriptions;
|
||||
int styleBits;
|
||||
|
||||
public:
|
||||
const char *languageName;
|
||||
LexerModule(int language_,
|
||||
LexerFunction fnLexer_,
|
||||
const char *languageName_=0,
|
||||
LexerFunction fnFolder_=0,
|
||||
const char * const wordListDescriptions_[] = NULL,
|
||||
int styleBits_=5);
|
||||
LexerModule(int language_,
|
||||
LexerFactoryFunction fnFactory_,
|
||||
const char *languageName_,
|
||||
const char * const wordListDescriptions_[] = NULL,
|
||||
int styleBits_=8);
|
||||
virtual ~LexerModule() {
|
||||
}
|
||||
int GetLanguage() const { return language; }
|
||||
|
||||
// -1 is returned if no WordList information is available
|
||||
int GetNumWordLists() const;
|
||||
const char *GetWordListDescription(int index) const;
|
||||
|
||||
int GetStyleBitsNeeded() const;
|
||||
|
||||
ILexer *Create() const;
|
||||
|
||||
virtual void Lex(unsigned int startPos, int length, int initStyle,
|
||||
WordList *keywordlists[], Accessor &styler) const;
|
||||
virtual void Fold(unsigned int startPos, int length, int initStyle,
|
||||
WordList *keywordlists[], Accessor &styler) const;
|
||||
|
||||
friend class Catalogue;
|
||||
};
|
||||
|
||||
inline int Maximum(int a, int b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
// Shut up annoying Visual C++ warnings:
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4244 4309 4514 4710)
|
||||
#endif
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
48
third-party/scintilla/LexerSimple.cxx
vendored
Normal file
48
third-party/scintilla/LexerSimple.cxx
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file LexerSimple.cxx
|
||||
** A simple lexer with no state.
|
||||
**/
|
||||
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "ILexer.h"
|
||||
#include "Scintilla.h"
|
||||
#include "SciLexer.h"
|
||||
|
||||
#include "PropSetSimple.h"
|
||||
#include "WordList.h"
|
||||
#include "LexAccessor.h"
|
||||
#include "Accessor.h"
|
||||
#include "LexerModule.h"
|
||||
#include "LexerBase.h"
|
||||
#include "LexerSimple.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
LexerSimple::LexerSimple(const LexerModule *module_) : module(module_) {
|
||||
for (int wl = 0; wl < module->GetNumWordLists(); wl++) {
|
||||
if (!wordLists.empty())
|
||||
wordLists += "\n";
|
||||
wordLists += module->GetWordListDescription(wl);
|
||||
}
|
||||
}
|
||||
|
||||
const char * SCI_METHOD LexerSimple::DescribeWordListSets() {
|
||||
return wordLists.c_str();
|
||||
}
|
||||
|
||||
void SCI_METHOD LexerSimple::Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) {
|
||||
Accessor astyler(pAccess, &props);
|
||||
module->Lex(startPos, lengthDoc, initStyle, keyWordLists, astyler);
|
||||
astyler.Flush();
|
||||
}
|
||||
|
||||
void SCI_METHOD LexerSimple::Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) {
|
||||
if (props.GetInt("fold")) {
|
||||
Accessor astyler(pAccess, &props);
|
||||
module->Fold(startPos, lengthDoc, initStyle, keyWordLists, astyler);
|
||||
astyler.Flush();
|
||||
}
|
||||
}
|
||||
30
third-party/scintilla/LexerSimple.h
vendored
Normal file
30
third-party/scintilla/LexerSimple.h
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file LexerSimple.h
|
||||
** A simple lexer with no state.
|
||||
**/
|
||||
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef LEXERSIMPLE_H
|
||||
#define LEXERSIMPLE_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
// A simple lexer with no state
|
||||
class LexerSimple : public LexerBase {
|
||||
const LexerModule *module;
|
||||
std::string wordLists;
|
||||
public:
|
||||
explicit LexerSimple(const LexerModule *module_);
|
||||
const char * SCI_METHOD DescribeWordListSets();
|
||||
void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess);
|
||||
void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess);
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
386
third-party/scintilla/LineMarker.cxx
vendored
Normal file
386
third-party/scintilla/LineMarker.cxx
vendored
Normal file
@@ -0,0 +1,386 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file LineMarker.cxx
|
||||
** Defines the look of a line marker in the margin .
|
||||
**/
|
||||
// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
#include "StringCopy.h"
|
||||
#include "XPM.h"
|
||||
#include "LineMarker.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
void LineMarker::SetXPM(const char *textForm) {
|
||||
delete pxpm;
|
||||
pxpm = new XPM(textForm);
|
||||
markType = SC_MARK_PIXMAP;
|
||||
}
|
||||
|
||||
void LineMarker::SetXPM(const char *const *linesForm) {
|
||||
delete pxpm;
|
||||
pxpm = new XPM(linesForm);
|
||||
markType = SC_MARK_PIXMAP;
|
||||
}
|
||||
|
||||
void LineMarker::SetRGBAImage(Point sizeRGBAImage, float scale, const unsigned char *pixelsRGBAImage) {
|
||||
delete image;
|
||||
image = new RGBAImage(static_cast<int>(sizeRGBAImage.x), static_cast<int>(sizeRGBAImage.y), scale, pixelsRGBAImage);
|
||||
markType = SC_MARK_RGBAIMAGE;
|
||||
}
|
||||
|
||||
static void DrawBox(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore, ColourDesired back) {
|
||||
PRectangle rc = PRectangle::FromInts(
|
||||
centreX - armSize,
|
||||
centreY - armSize,
|
||||
centreX + armSize + 1,
|
||||
centreY + armSize + 1);
|
||||
surface->RectangleDraw(rc, back, fore); //inverted
|
||||
}
|
||||
|
||||
static void DrawCircle(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore, ColourDesired back) {
|
||||
PRectangle rcCircle = PRectangle::FromInts(
|
||||
centreX - armSize,
|
||||
centreY - armSize,
|
||||
centreX + armSize + 1,
|
||||
centreY + armSize + 1);
|
||||
surface->Ellipse(rcCircle, back, fore); //inverted
|
||||
}
|
||||
|
||||
static void DrawPlus(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore) {
|
||||
PRectangle rcV = PRectangle::FromInts(centreX, centreY - armSize + 2, centreX + 1, centreY + armSize - 2 + 1);
|
||||
surface->FillRectangle(rcV, fore);
|
||||
PRectangle rcH = PRectangle::FromInts(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY + 1);
|
||||
surface->FillRectangle(rcH, fore);
|
||||
}
|
||||
|
||||
static void DrawMinus(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore) {
|
||||
PRectangle rcH = PRectangle::FromInts(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY + 1);
|
||||
surface->FillRectangle(rcH, fore);
|
||||
}
|
||||
|
||||
void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, typeOfFold tFold, int marginStyle) {
|
||||
ColourDesired head = back;
|
||||
ColourDesired body = back;
|
||||
ColourDesired tail = back;
|
||||
|
||||
switch (tFold) {
|
||||
case LineMarker::head :
|
||||
case LineMarker::headWithTail :
|
||||
head = backSelected;
|
||||
tail = backSelected;
|
||||
break;
|
||||
case LineMarker::body :
|
||||
head = backSelected;
|
||||
body = backSelected;
|
||||
break;
|
||||
case LineMarker::tail :
|
||||
body = backSelected;
|
||||
tail = backSelected;
|
||||
break;
|
||||
default :
|
||||
// LineMarker::undefined
|
||||
break;
|
||||
}
|
||||
|
||||
if ((markType == SC_MARK_PIXMAP) && (pxpm)) {
|
||||
pxpm->Draw(surface, rcWhole);
|
||||
return;
|
||||
}
|
||||
if ((markType == SC_MARK_RGBAIMAGE) && (image)) {
|
||||
// Make rectangle just large enough to fit image centred on centre of rcWhole
|
||||
PRectangle rcImage;
|
||||
rcImage.top = ((rcWhole.top + rcWhole.bottom) - image->GetScaledHeight()) / 2;
|
||||
rcImage.bottom = rcImage.top + image->GetScaledHeight();
|
||||
rcImage.left = ((rcWhole.left + rcWhole.right) - image->GetScaledWidth()) / 2;
|
||||
rcImage.right = rcImage.left + image->GetScaledWidth();
|
||||
surface->DrawRGBAImage(rcImage, image->GetWidth(), image->GetHeight(), image->Pixels());
|
||||
return;
|
||||
}
|
||||
// Restrict most shapes a bit
|
||||
PRectangle rc = rcWhole;
|
||||
rc.top++;
|
||||
rc.bottom--;
|
||||
int minDim = Platform::Minimum(static_cast<int>(rc.Width()), static_cast<int>(rc.Height()));
|
||||
minDim--; // Ensure does not go beyond edge
|
||||
int centreX = static_cast<int>(floor((rc.right + rc.left) / 2.0));
|
||||
int centreY = static_cast<int>(floor((rc.bottom + rc.top) / 2.0));
|
||||
int dimOn2 = minDim / 2;
|
||||
int dimOn4 = minDim / 4;
|
||||
int blobSize = dimOn2-1;
|
||||
int armSize = dimOn2-2;
|
||||
if (marginStyle == SC_MARGIN_NUMBER || marginStyle == SC_MARGIN_TEXT || marginStyle == SC_MARGIN_RTEXT) {
|
||||
// On textual margins move marker to the left to try to avoid overlapping the text
|
||||
centreX = static_cast<int>(rc.left) + dimOn2 + 1;
|
||||
}
|
||||
if (markType == SC_MARK_ROUNDRECT) {
|
||||
PRectangle rcRounded = rc;
|
||||
rcRounded.left = rc.left + 1;
|
||||
rcRounded.right = rc.right - 1;
|
||||
surface->RoundedRectangle(rcRounded, fore, back);
|
||||
} else if (markType == SC_MARK_CIRCLE) {
|
||||
PRectangle rcCircle = PRectangle::FromInts(
|
||||
centreX - dimOn2,
|
||||
centreY - dimOn2,
|
||||
centreX + dimOn2,
|
||||
centreY + dimOn2);
|
||||
surface->Ellipse(rcCircle, fore, back);
|
||||
} else if (markType == SC_MARK_ARROW) {
|
||||
Point pts[] = {
|
||||
Point::FromInts(centreX - dimOn4, centreY - dimOn2),
|
||||
Point::FromInts(centreX - dimOn4, centreY + dimOn2),
|
||||
Point::FromInts(centreX + dimOn2 - dimOn4, centreY),
|
||||
};
|
||||
surface->Polygon(pts, ELEMENTS(pts), fore, back);
|
||||
|
||||
} else if (markType == SC_MARK_ARROWDOWN) {
|
||||
Point pts[] = {
|
||||
Point::FromInts(centreX - dimOn2, centreY - dimOn4),
|
||||
Point::FromInts(centreX + dimOn2, centreY - dimOn4),
|
||||
Point::FromInts(centreX, centreY + dimOn2 - dimOn4),
|
||||
};
|
||||
surface->Polygon(pts, ELEMENTS(pts), fore, back);
|
||||
|
||||
} else if (markType == SC_MARK_PLUS) {
|
||||
Point pts[] = {
|
||||
Point::FromInts(centreX - armSize, centreY - 1),
|
||||
Point::FromInts(centreX - 1, centreY - 1),
|
||||
Point::FromInts(centreX - 1, centreY - armSize),
|
||||
Point::FromInts(centreX + 1, centreY - armSize),
|
||||
Point::FromInts(centreX + 1, centreY - 1),
|
||||
Point::FromInts(centreX + armSize, centreY -1),
|
||||
Point::FromInts(centreX + armSize, centreY +1),
|
||||
Point::FromInts(centreX + 1, centreY + 1),
|
||||
Point::FromInts(centreX + 1, centreY + armSize),
|
||||
Point::FromInts(centreX - 1, centreY + armSize),
|
||||
Point::FromInts(centreX - 1, centreY + 1),
|
||||
Point::FromInts(centreX - armSize, centreY + 1),
|
||||
};
|
||||
surface->Polygon(pts, ELEMENTS(pts), fore, back);
|
||||
|
||||
} else if (markType == SC_MARK_MINUS) {
|
||||
Point pts[] = {
|
||||
Point::FromInts(centreX - armSize, centreY - 1),
|
||||
Point::FromInts(centreX + armSize, centreY -1),
|
||||
Point::FromInts(centreX + armSize, centreY +1),
|
||||
Point::FromInts(centreX - armSize, centreY + 1),
|
||||
};
|
||||
surface->Polygon(pts, ELEMENTS(pts), fore, back);
|
||||
|
||||
} else if (markType == SC_MARK_SMALLRECT) {
|
||||
PRectangle rcSmall;
|
||||
rcSmall.left = rc.left + 1;
|
||||
rcSmall.top = rc.top + 2;
|
||||
rcSmall.right = rc.right - 1;
|
||||
rcSmall.bottom = rc.bottom - 2;
|
||||
surface->RectangleDraw(rcSmall, fore, back);
|
||||
|
||||
} else if (markType == SC_MARK_EMPTY || markType == SC_MARK_BACKGROUND ||
|
||||
markType == SC_MARK_UNDERLINE || markType == SC_MARK_AVAILABLE) {
|
||||
// An invisible marker so don't draw anything
|
||||
|
||||
} else if (markType == SC_MARK_VLINE) {
|
||||
surface->PenColour(body);
|
||||
surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
|
||||
surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
|
||||
|
||||
} else if (markType == SC_MARK_LCORNER) {
|
||||
surface->PenColour(tail);
|
||||
surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
|
||||
surface->LineTo(centreX, centreY);
|
||||
surface->LineTo(static_cast<int>(rc.right) - 1, centreY);
|
||||
|
||||
} else if (markType == SC_MARK_TCORNER) {
|
||||
surface->PenColour(tail);
|
||||
surface->MoveTo(centreX, centreY);
|
||||
surface->LineTo(static_cast<int>(rc.right) - 1, centreY);
|
||||
|
||||
surface->PenColour(body);
|
||||
surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
|
||||
surface->LineTo(centreX, centreY + 1);
|
||||
|
||||
surface->PenColour(head);
|
||||
surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
|
||||
|
||||
} else if (markType == SC_MARK_LCORNERCURVE) {
|
||||
surface->PenColour(tail);
|
||||
surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
|
||||
surface->LineTo(centreX, centreY-3);
|
||||
surface->LineTo(centreX+3, centreY);
|
||||
surface->LineTo(static_cast<int>(rc.right) - 1, centreY);
|
||||
|
||||
} else if (markType == SC_MARK_TCORNERCURVE) {
|
||||
surface->PenColour(tail);
|
||||
surface->MoveTo(centreX, centreY-3);
|
||||
surface->LineTo(centreX+3, centreY);
|
||||
surface->LineTo(static_cast<int>(rc.right) - 1, centreY);
|
||||
|
||||
surface->PenColour(body);
|
||||
surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
|
||||
surface->LineTo(centreX, centreY-2);
|
||||
|
||||
surface->PenColour(head);
|
||||
surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
|
||||
|
||||
} else if (markType == SC_MARK_BOXPLUS) {
|
||||
DrawBox(surface, centreX, centreY, blobSize, fore, head);
|
||||
DrawPlus(surface, centreX, centreY, blobSize, tail);
|
||||
|
||||
} else if (markType == SC_MARK_BOXPLUSCONNECTED) {
|
||||
if (tFold == LineMarker::headWithTail)
|
||||
surface->PenColour(tail);
|
||||
else
|
||||
surface->PenColour(body);
|
||||
surface->MoveTo(centreX, centreY + blobSize);
|
||||
surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
|
||||
|
||||
surface->PenColour(body);
|
||||
surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
|
||||
surface->LineTo(centreX, centreY - blobSize);
|
||||
|
||||
DrawBox(surface, centreX, centreY, blobSize, fore, head);
|
||||
DrawPlus(surface, centreX, centreY, blobSize, tail);
|
||||
|
||||
if (tFold == LineMarker::body) {
|
||||
surface->PenColour(tail);
|
||||
surface->MoveTo(centreX + 1, centreY + blobSize);
|
||||
surface->LineTo(centreX + blobSize + 1, centreY + blobSize);
|
||||
|
||||
surface->MoveTo(centreX + blobSize, centreY + blobSize);
|
||||
surface->LineTo(centreX + blobSize, centreY - blobSize);
|
||||
|
||||
surface->MoveTo(centreX + 1, centreY - blobSize);
|
||||
surface->LineTo(centreX + blobSize + 1, centreY - blobSize);
|
||||
}
|
||||
} else if (markType == SC_MARK_BOXMINUS) {
|
||||
DrawBox(surface, centreX, centreY, blobSize, fore, head);
|
||||
DrawMinus(surface, centreX, centreY, blobSize, tail);
|
||||
|
||||
surface->PenColour(head);
|
||||
surface->MoveTo(centreX, centreY + blobSize);
|
||||
surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
|
||||
|
||||
} else if (markType == SC_MARK_BOXMINUSCONNECTED) {
|
||||
DrawBox(surface, centreX, centreY, blobSize, fore, head);
|
||||
DrawMinus(surface, centreX, centreY, blobSize, tail);
|
||||
|
||||
surface->PenColour(head);
|
||||
surface->MoveTo(centreX, centreY + blobSize);
|
||||
surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
|
||||
|
||||
surface->PenColour(body);
|
||||
surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
|
||||
surface->LineTo(centreX, centreY - blobSize);
|
||||
|
||||
if (tFold == LineMarker::body) {
|
||||
surface->PenColour(tail);
|
||||
surface->MoveTo(centreX + 1, centreY + blobSize);
|
||||
surface->LineTo(centreX + blobSize + 1, centreY + blobSize);
|
||||
|
||||
surface->MoveTo(centreX + blobSize, centreY + blobSize);
|
||||
surface->LineTo(centreX + blobSize, centreY - blobSize);
|
||||
|
||||
surface->MoveTo(centreX + 1, centreY - blobSize);
|
||||
surface->LineTo(centreX + blobSize + 1, centreY - blobSize);
|
||||
}
|
||||
} else if (markType == SC_MARK_CIRCLEPLUS) {
|
||||
DrawCircle(surface, centreX, centreY, blobSize, fore, head);
|
||||
DrawPlus(surface, centreX, centreY, blobSize, tail);
|
||||
|
||||
} else if (markType == SC_MARK_CIRCLEPLUSCONNECTED) {
|
||||
if (tFold == LineMarker::headWithTail)
|
||||
surface->PenColour(tail);
|
||||
else
|
||||
surface->PenColour(body);
|
||||
surface->MoveTo(centreX, centreY + blobSize);
|
||||
surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
|
||||
|
||||
surface->PenColour(body);
|
||||
surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
|
||||
surface->LineTo(centreX, centreY - blobSize);
|
||||
|
||||
DrawCircle(surface, centreX, centreY, blobSize, fore, head);
|
||||
DrawPlus(surface, centreX, centreY, blobSize, tail);
|
||||
|
||||
} else if (markType == SC_MARK_CIRCLEMINUS) {
|
||||
surface->PenColour(head);
|
||||
surface->MoveTo(centreX, centreY + blobSize);
|
||||
surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
|
||||
|
||||
DrawCircle(surface, centreX, centreY, blobSize, fore, head);
|
||||
DrawMinus(surface, centreX, centreY, blobSize, tail);
|
||||
|
||||
} else if (markType == SC_MARK_CIRCLEMINUSCONNECTED) {
|
||||
surface->PenColour(head);
|
||||
surface->MoveTo(centreX, centreY + blobSize);
|
||||
surface->LineTo(centreX, static_cast<int>(rcWhole.bottom));
|
||||
|
||||
surface->PenColour(body);
|
||||
surface->MoveTo(centreX, static_cast<int>(rcWhole.top));
|
||||
surface->LineTo(centreX, centreY - blobSize);
|
||||
|
||||
DrawCircle(surface, centreX, centreY, blobSize, fore, head);
|
||||
DrawMinus(surface, centreX, centreY, blobSize, tail);
|
||||
|
||||
} else if (markType >= SC_MARK_CHARACTER) {
|
||||
char character[1];
|
||||
character[0] = static_cast<char>(markType - SC_MARK_CHARACTER);
|
||||
XYPOSITION width = surface->WidthText(fontForCharacter, character, 1);
|
||||
rc.left += (rc.Width() - width) / 2;
|
||||
rc.right = rc.left + width;
|
||||
surface->DrawTextClipped(rc, fontForCharacter, rc.bottom - 2,
|
||||
character, 1, fore, back);
|
||||
|
||||
} else if (markType == SC_MARK_DOTDOTDOT) {
|
||||
XYPOSITION right = static_cast<XYPOSITION>(centreX - 6);
|
||||
for (int b=0; b<3; b++) {
|
||||
PRectangle rcBlob(right, rc.bottom - 4, right + 2, rc.bottom-2);
|
||||
surface->FillRectangle(rcBlob, fore);
|
||||
right += 5.0f;
|
||||
}
|
||||
} else if (markType == SC_MARK_ARROWS) {
|
||||
surface->PenColour(fore);
|
||||
int right = centreX - 2;
|
||||
const int armLength = dimOn2 - 1;
|
||||
for (int b = 0; b<3; b++) {
|
||||
surface->MoveTo(right, centreY);
|
||||
surface->LineTo(right - armLength, centreY - armLength);
|
||||
surface->MoveTo(right, centreY);
|
||||
surface->LineTo(right - armLength, centreY + armLength);
|
||||
right += 4;
|
||||
}
|
||||
} else if (markType == SC_MARK_SHORTARROW) {
|
||||
Point pts[] = {
|
||||
Point::FromInts(centreX, centreY + dimOn2),
|
||||
Point::FromInts(centreX + dimOn2, centreY),
|
||||
Point::FromInts(centreX, centreY - dimOn2),
|
||||
Point::FromInts(centreX, centreY - dimOn4),
|
||||
Point::FromInts(centreX - dimOn4, centreY - dimOn4),
|
||||
Point::FromInts(centreX - dimOn4, centreY + dimOn4),
|
||||
Point::FromInts(centreX, centreY + dimOn4),
|
||||
Point::FromInts(centreX, centreY + dimOn2),
|
||||
};
|
||||
surface->Polygon(pts, ELEMENTS(pts), fore, back);
|
||||
} else if (markType == SC_MARK_LEFTRECT) {
|
||||
PRectangle rcLeft = rcWhole;
|
||||
rcLeft.right = rcLeft.left + 4;
|
||||
surface->FillRectangle(rcLeft, back);
|
||||
} else if (markType == SC_MARK_BOOKMARK) {
|
||||
int halfHeight = minDim / 3;
|
||||
Point pts[] = {
|
||||
Point::FromInts(static_cast<int>(rc.left), centreY-halfHeight),
|
||||
Point::FromInts(static_cast<int>(rc.right) - 3, centreY - halfHeight),
|
||||
Point::FromInts(static_cast<int>(rc.right) - 3 - halfHeight, centreY),
|
||||
Point::FromInts(static_cast<int>(rc.right) - 3, centreY + halfHeight),
|
||||
Point::FromInts(static_cast<int>(rc.left), centreY + halfHeight),
|
||||
};
|
||||
surface->Polygon(pts, ELEMENTS(pts), fore, back);
|
||||
} else { // SC_MARK_FULLRECT
|
||||
surface->FillRectangle(rcWhole, back);
|
||||
}
|
||||
}
|
||||
76
third-party/scintilla/LineMarker.h
vendored
Normal file
76
third-party/scintilla/LineMarker.h
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file LineMarker.h
|
||||
** Defines the look of a line marker in the margin .
|
||||
**/
|
||||
// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef LINEMARKER_H
|
||||
#define LINEMARKER_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
/**
|
||||
*/
|
||||
class LineMarker {
|
||||
public:
|
||||
enum typeOfFold { undefined, head, body, tail, headWithTail };
|
||||
|
||||
int markType;
|
||||
ColourDesired fore;
|
||||
ColourDesired back;
|
||||
ColourDesired backSelected;
|
||||
int alpha;
|
||||
XPM *pxpm;
|
||||
RGBAImage *image;
|
||||
LineMarker() {
|
||||
markType = SC_MARK_CIRCLE;
|
||||
fore = ColourDesired(0,0,0);
|
||||
back = ColourDesired(0xff,0xff,0xff);
|
||||
backSelected = ColourDesired(0xff,0x00,0x00);
|
||||
alpha = SC_ALPHA_NOALPHA;
|
||||
pxpm = NULL;
|
||||
image = NULL;
|
||||
}
|
||||
LineMarker(const LineMarker &) {
|
||||
// Defined to avoid pxpm being blindly copied, not as a complete copy constructor
|
||||
markType = SC_MARK_CIRCLE;
|
||||
fore = ColourDesired(0,0,0);
|
||||
back = ColourDesired(0xff,0xff,0xff);
|
||||
backSelected = ColourDesired(0xff,0x00,0x00);
|
||||
alpha = SC_ALPHA_NOALPHA;
|
||||
pxpm = NULL;
|
||||
image = NULL;
|
||||
}
|
||||
~LineMarker() {
|
||||
delete pxpm;
|
||||
delete image;
|
||||
}
|
||||
LineMarker &operator=(const LineMarker &other) {
|
||||
// Defined to avoid pxpm being blindly copied, not as a complete assignment operator
|
||||
if (this != &other) {
|
||||
markType = SC_MARK_CIRCLE;
|
||||
fore = ColourDesired(0,0,0);
|
||||
back = ColourDesired(0xff,0xff,0xff);
|
||||
backSelected = ColourDesired(0xff,0x00,0x00);
|
||||
alpha = SC_ALPHA_NOALPHA;
|
||||
delete pxpm;
|
||||
pxpm = NULL;
|
||||
delete image;
|
||||
image = NULL;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
void SetXPM(const char *textForm);
|
||||
void SetXPM(const char *const *linesForm);
|
||||
void SetRGBAImage(Point sizeRGBAImage, float scale, const unsigned char *pixelsRGBAImage);
|
||||
void Draw(Surface *surface, PRectangle &rc, Font &fontForCharacter, typeOfFold tFold, int marginStyle);
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
142
third-party/scintilla/OptionSet.h
vendored
Normal file
142
third-party/scintilla/OptionSet.h
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file OptionSet.h
|
||||
** Manage descriptive information about an options struct for a lexer.
|
||||
** Hold the names, positions, and descriptions of boolean, integer and string options and
|
||||
** allow setting options and retrieving metadata about the options.
|
||||
**/
|
||||
// Copyright 2010 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef OPTIONSET_H
|
||||
#define OPTIONSET_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
class OptionSet {
|
||||
typedef T Target;
|
||||
typedef bool T::*plcob;
|
||||
typedef int T::*plcoi;
|
||||
typedef std::string T::*plcos;
|
||||
struct Option {
|
||||
int opType;
|
||||
union {
|
||||
plcob pb;
|
||||
plcoi pi;
|
||||
plcos ps;
|
||||
};
|
||||
std::string description;
|
||||
Option() :
|
||||
opType(SC_TYPE_BOOLEAN), pb(0), description("") {
|
||||
}
|
||||
Option(plcob pb_, std::string description_="") :
|
||||
opType(SC_TYPE_BOOLEAN), pb(pb_), description(description_) {
|
||||
}
|
||||
Option(plcoi pi_, std::string description_) :
|
||||
opType(SC_TYPE_INTEGER), pi(pi_), description(description_) {
|
||||
}
|
||||
Option(plcos ps_, std::string description_) :
|
||||
opType(SC_TYPE_STRING), ps(ps_), description(description_) {
|
||||
}
|
||||
bool Set(T *base, const char *val) const {
|
||||
switch (opType) {
|
||||
case SC_TYPE_BOOLEAN: {
|
||||
bool option = atoi(val) != 0;
|
||||
if ((*base).*pb != option) {
|
||||
(*base).*pb = option;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SC_TYPE_INTEGER: {
|
||||
int option = atoi(val);
|
||||
if ((*base).*pi != option) {
|
||||
(*base).*pi = option;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SC_TYPE_STRING: {
|
||||
if ((*base).*ps != val) {
|
||||
(*base).*ps = val;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
typedef std::map<std::string, Option> OptionMap;
|
||||
OptionMap nameToDef;
|
||||
std::string names;
|
||||
std::string wordLists;
|
||||
|
||||
void AppendName(const char *name) {
|
||||
if (!names.empty())
|
||||
names += "\n";
|
||||
names += name;
|
||||
}
|
||||
public:
|
||||
virtual ~OptionSet() {
|
||||
}
|
||||
void DefineProperty(const char *name, plcob pb, std::string description="") {
|
||||
nameToDef[name] = Option(pb, description);
|
||||
AppendName(name);
|
||||
}
|
||||
void DefineProperty(const char *name, plcoi pi, std::string description="") {
|
||||
nameToDef[name] = Option(pi, description);
|
||||
AppendName(name);
|
||||
}
|
||||
void DefineProperty(const char *name, plcos ps, std::string description="") {
|
||||
nameToDef[name] = Option(ps, description);
|
||||
AppendName(name);
|
||||
}
|
||||
const char *PropertyNames() const {
|
||||
return names.c_str();
|
||||
}
|
||||
int PropertyType(const char *name) {
|
||||
typename OptionMap::iterator it = nameToDef.find(name);
|
||||
if (it != nameToDef.end()) {
|
||||
return it->second.opType;
|
||||
}
|
||||
return SC_TYPE_BOOLEAN;
|
||||
}
|
||||
const char *DescribeProperty(const char *name) {
|
||||
typename OptionMap::iterator it = nameToDef.find(name);
|
||||
if (it != nameToDef.end()) {
|
||||
return it->second.description.c_str();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
bool PropertySet(T *base, const char *name, const char *val) {
|
||||
typename OptionMap::iterator it = nameToDef.find(name);
|
||||
if (it != nameToDef.end()) {
|
||||
return it->second.Set(base, val);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DefineWordListSets(const char * const wordListDescriptions[]) {
|
||||
if (wordListDescriptions) {
|
||||
for (size_t wl = 0; wordListDescriptions[wl]; wl++) {
|
||||
if (!wordLists.empty())
|
||||
wordLists += "\n";
|
||||
wordLists += wordListDescriptions[wl];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *DescribeWordListSets() const {
|
||||
return wordLists.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
202
third-party/scintilla/Partitioning.h
vendored
Normal file
202
third-party/scintilla/Partitioning.h
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file Partitioning.h
|
||||
** Data structure used to partition an interval. Used for holding line start/end positions.
|
||||
**/
|
||||
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef PARTITIONING_H
|
||||
#define PARTITIONING_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
/// A split vector of integers with a method for adding a value to all elements
|
||||
/// in a range.
|
||||
/// Used by the Partitioning class.
|
||||
|
||||
class SplitVectorWithRangeAdd : public SplitVector<int> {
|
||||
public:
|
||||
explicit SplitVectorWithRangeAdd(int growSize_) {
|
||||
SetGrowSize(growSize_);
|
||||
ReAllocate(growSize_);
|
||||
}
|
||||
~SplitVectorWithRangeAdd() {
|
||||
}
|
||||
void RangeAddDelta(int start, int end, int delta) {
|
||||
// end is 1 past end, so end-start is number of elements to change
|
||||
int i = 0;
|
||||
int rangeLength = end - start;
|
||||
int range1Length = rangeLength;
|
||||
int part1Left = part1Length - start;
|
||||
if (range1Length > part1Left)
|
||||
range1Length = part1Left;
|
||||
while (i < range1Length) {
|
||||
body[start++] += delta;
|
||||
i++;
|
||||
}
|
||||
start += gapLength;
|
||||
while (i < rangeLength) {
|
||||
body[start++] += delta;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Divide an interval into multiple partitions.
|
||||
/// Useful for breaking a document down into sections such as lines.
|
||||
/// A 0 length interval has a single 0 length partition, numbered 0
|
||||
/// If interval not 0 length then each partition non-zero length
|
||||
/// When needed, positions after the interval are considered part of the last partition
|
||||
/// but the end of the last partition can be found with PositionFromPartition(last+1).
|
||||
|
||||
class Partitioning {
|
||||
private:
|
||||
// To avoid calculating all the partition positions whenever any text is inserted
|
||||
// there may be a step somewhere in the list.
|
||||
int stepPartition;
|
||||
int stepLength;
|
||||
SplitVectorWithRangeAdd *body;
|
||||
|
||||
// Move step forward
|
||||
void ApplyStep(int partitionUpTo) {
|
||||
if (stepLength != 0) {
|
||||
body->RangeAddDelta(stepPartition+1, partitionUpTo + 1, stepLength);
|
||||
}
|
||||
stepPartition = partitionUpTo;
|
||||
if (stepPartition >= body->Length()-1) {
|
||||
stepPartition = body->Length()-1;
|
||||
stepLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Move step backward
|
||||
void BackStep(int partitionDownTo) {
|
||||
if (stepLength != 0) {
|
||||
body->RangeAddDelta(partitionDownTo+1, stepPartition+1, -stepLength);
|
||||
}
|
||||
stepPartition = partitionDownTo;
|
||||
}
|
||||
|
||||
void Allocate(int growSize) {
|
||||
body = new SplitVectorWithRangeAdd(growSize);
|
||||
stepPartition = 0;
|
||||
stepLength = 0;
|
||||
body->Insert(0, 0); // This value stays 0 for ever
|
||||
body->Insert(1, 0); // This is the end of the first partition and will be the start of the second
|
||||
}
|
||||
|
||||
// no copy ctr or assignment op
|
||||
Partitioning(const Partitioning &);
|
||||
Partitioning &operator =(const Partitioning &);
|
||||
|
||||
public:
|
||||
explicit Partitioning(int growSize) {
|
||||
Allocate(growSize);
|
||||
}
|
||||
|
||||
~Partitioning() {
|
||||
delete body;
|
||||
body = 0;
|
||||
}
|
||||
|
||||
int Partitions() const {
|
||||
return body->Length()-1;
|
||||
}
|
||||
|
||||
void InsertPartition(int partition, int pos) {
|
||||
if (stepPartition < partition) {
|
||||
ApplyStep(partition);
|
||||
}
|
||||
body->Insert(partition, pos);
|
||||
stepPartition++;
|
||||
}
|
||||
|
||||
void SetPartitionStartPosition(int partition, int pos) {
|
||||
ApplyStep(partition+1);
|
||||
if ((partition < 0) || (partition > body->Length())) {
|
||||
return;
|
||||
}
|
||||
body->SetValueAt(partition, pos);
|
||||
}
|
||||
|
||||
void InsertText(int partitionInsert, int delta) {
|
||||
// Point all the partitions after the insertion point further along in the buffer
|
||||
if (stepLength != 0) {
|
||||
if (partitionInsert >= stepPartition) {
|
||||
// Fill in up to the new insertion point
|
||||
ApplyStep(partitionInsert);
|
||||
stepLength += delta;
|
||||
} else if (partitionInsert >= (stepPartition - body->Length() / 10)) {
|
||||
// Close to step but before so move step back
|
||||
BackStep(partitionInsert);
|
||||
stepLength += delta;
|
||||
} else {
|
||||
ApplyStep(body->Length()-1);
|
||||
stepPartition = partitionInsert;
|
||||
stepLength = delta;
|
||||
}
|
||||
} else {
|
||||
stepPartition = partitionInsert;
|
||||
stepLength = delta;
|
||||
}
|
||||
}
|
||||
|
||||
void RemovePartition(int partition) {
|
||||
if (partition > stepPartition) {
|
||||
ApplyStep(partition);
|
||||
stepPartition--;
|
||||
} else {
|
||||
stepPartition--;
|
||||
}
|
||||
body->Delete(partition);
|
||||
}
|
||||
|
||||
int PositionFromPartition(int partition) const {
|
||||
PLATFORM_ASSERT(partition >= 0);
|
||||
PLATFORM_ASSERT(partition < body->Length());
|
||||
if ((partition < 0) || (partition >= body->Length())) {
|
||||
return 0;
|
||||
}
|
||||
int pos = body->ValueAt(partition);
|
||||
if (partition > stepPartition)
|
||||
pos += stepLength;
|
||||
return pos;
|
||||
}
|
||||
|
||||
/// Return value in range [0 .. Partitions() - 1] even for arguments outside interval
|
||||
int PartitionFromPosition(int pos) const {
|
||||
if (body->Length() <= 1)
|
||||
return 0;
|
||||
if (pos >= (PositionFromPartition(body->Length()-1)))
|
||||
return body->Length() - 1 - 1;
|
||||
int lower = 0;
|
||||
int upper = body->Length()-1;
|
||||
do {
|
||||
int middle = (upper + lower + 1) / 2; // Round high
|
||||
int posMiddle = body->ValueAt(middle);
|
||||
if (middle > stepPartition)
|
||||
posMiddle += stepLength;
|
||||
if (pos < posMiddle) {
|
||||
upper = middle - 1;
|
||||
} else {
|
||||
lower = middle;
|
||||
}
|
||||
} while (lower < upper);
|
||||
return lower;
|
||||
}
|
||||
|
||||
void DeleteAll() {
|
||||
int growSize = body->GetGrowSize();
|
||||
delete body;
|
||||
Allocate(growSize);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
482
third-party/scintilla/PerLine.cxx
vendored
Normal file
482
third-party/scintilla/PerLine.cxx
vendored
Normal file
@@ -0,0 +1,482 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file PerLine.cxx
|
||||
** Manages data associated with each line of the document
|
||||
**/
|
||||
// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
#include "SplitVector.h"
|
||||
#include "Partitioning.h"
|
||||
#include "CellBuffer.h"
|
||||
#include "PerLine.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
MarkerHandleSet::MarkerHandleSet() {
|
||||
root = 0;
|
||||
}
|
||||
|
||||
MarkerHandleSet::~MarkerHandleSet() {
|
||||
MarkerHandleNumber *mhn = root;
|
||||
while (mhn) {
|
||||
MarkerHandleNumber *mhnToFree = mhn;
|
||||
mhn = mhn->next;
|
||||
delete mhnToFree;
|
||||
}
|
||||
root = 0;
|
||||
}
|
||||
|
||||
int MarkerHandleSet::Length() const {
|
||||
int c = 0;
|
||||
MarkerHandleNumber *mhn = root;
|
||||
while (mhn) {
|
||||
c++;
|
||||
mhn = mhn->next;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
int MarkerHandleSet::MarkValue() const {
|
||||
unsigned int m = 0;
|
||||
MarkerHandleNumber *mhn = root;
|
||||
while (mhn) {
|
||||
m |= (1 << mhn->number);
|
||||
mhn = mhn->next;
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
bool MarkerHandleSet::Contains(int handle) const {
|
||||
MarkerHandleNumber *mhn = root;
|
||||
while (mhn) {
|
||||
if (mhn->handle == handle) {
|
||||
return true;
|
||||
}
|
||||
mhn = mhn->next;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MarkerHandleSet::InsertHandle(int handle, int markerNum) {
|
||||
MarkerHandleNumber *mhn = new MarkerHandleNumber;
|
||||
mhn->handle = handle;
|
||||
mhn->number = markerNum;
|
||||
mhn->next = root;
|
||||
root = mhn;
|
||||
return true;
|
||||
}
|
||||
|
||||
void MarkerHandleSet::RemoveHandle(int handle) {
|
||||
MarkerHandleNumber **pmhn = &root;
|
||||
while (*pmhn) {
|
||||
MarkerHandleNumber *mhn = *pmhn;
|
||||
if (mhn->handle == handle) {
|
||||
*pmhn = mhn->next;
|
||||
delete mhn;
|
||||
return;
|
||||
}
|
||||
pmhn = &((*pmhn)->next);
|
||||
}
|
||||
}
|
||||
|
||||
bool MarkerHandleSet::RemoveNumber(int markerNum, bool all) {
|
||||
bool performedDeletion = false;
|
||||
MarkerHandleNumber **pmhn = &root;
|
||||
while (*pmhn) {
|
||||
MarkerHandleNumber *mhn = *pmhn;
|
||||
if (mhn->number == markerNum) {
|
||||
*pmhn = mhn->next;
|
||||
delete mhn;
|
||||
performedDeletion = true;
|
||||
if (!all)
|
||||
break;
|
||||
} else {
|
||||
pmhn = &((*pmhn)->next);
|
||||
}
|
||||
}
|
||||
return performedDeletion;
|
||||
}
|
||||
|
||||
void MarkerHandleSet::CombineWith(MarkerHandleSet *other) {
|
||||
MarkerHandleNumber **pmhn = &root;
|
||||
while (*pmhn) {
|
||||
pmhn = &((*pmhn)->next);
|
||||
}
|
||||
*pmhn = other->root;
|
||||
other->root = 0;
|
||||
}
|
||||
|
||||
LineMarkers::~LineMarkers() {
|
||||
Init();
|
||||
}
|
||||
|
||||
void LineMarkers::Init() {
|
||||
for (int line = 0; line < markers.Length(); line++) {
|
||||
delete markers[line];
|
||||
markers[line] = 0;
|
||||
}
|
||||
markers.DeleteAll();
|
||||
}
|
||||
|
||||
void LineMarkers::InsertLine(int line) {
|
||||
if (markers.Length()) {
|
||||
markers.Insert(line, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void LineMarkers::RemoveLine(int line) {
|
||||
// Retain the markers from the deleted line by oring them into the previous line
|
||||
if (markers.Length()) {
|
||||
if (line > 0) {
|
||||
MergeMarkers(line - 1);
|
||||
}
|
||||
markers.Delete(line);
|
||||
}
|
||||
}
|
||||
|
||||
int LineMarkers::LineFromHandle(int markerHandle) {
|
||||
if (markers.Length()) {
|
||||
for (int line = 0; line < markers.Length(); line++) {
|
||||
if (markers[line]) {
|
||||
if (markers[line]->Contains(markerHandle)) {
|
||||
return line;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void LineMarkers::MergeMarkers(int pos) {
|
||||
if (markers[pos + 1] != NULL) {
|
||||
if (markers[pos] == NULL)
|
||||
markers[pos] = new MarkerHandleSet;
|
||||
markers[pos]->CombineWith(markers[pos + 1]);
|
||||
delete markers[pos + 1];
|
||||
markers[pos + 1] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int LineMarkers::MarkValue(int line) {
|
||||
if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line])
|
||||
return markers[line]->MarkValue();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LineMarkers::MarkerNext(int lineStart, int mask) const {
|
||||
if (lineStart < 0)
|
||||
lineStart = 0;
|
||||
int length = markers.Length();
|
||||
for (int iLine = lineStart; iLine < length; iLine++) {
|
||||
MarkerHandleSet *onLine = markers[iLine];
|
||||
if (onLine && ((onLine->MarkValue() & mask) != 0))
|
||||
//if ((pdoc->GetMark(iLine) & lParam) != 0)
|
||||
return iLine;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int LineMarkers::AddMark(int line, int markerNum, int lines) {
|
||||
handleCurrent++;
|
||||
if (!markers.Length()) {
|
||||
// No existing markers so allocate one element per line
|
||||
markers.InsertValue(0, lines, 0);
|
||||
}
|
||||
if (line >= markers.Length()) {
|
||||
return -1;
|
||||
}
|
||||
if (!markers[line]) {
|
||||
// Need new structure to hold marker handle
|
||||
markers[line] = new MarkerHandleSet();
|
||||
}
|
||||
markers[line]->InsertHandle(handleCurrent, markerNum);
|
||||
|
||||
return handleCurrent;
|
||||
}
|
||||
|
||||
bool LineMarkers::DeleteMark(int line, int markerNum, bool all) {
|
||||
bool someChanges = false;
|
||||
if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) {
|
||||
if (markerNum == -1) {
|
||||
someChanges = true;
|
||||
delete markers[line];
|
||||
markers[line] = NULL;
|
||||
} else {
|
||||
someChanges = markers[line]->RemoveNumber(markerNum, all);
|
||||
if (markers[line]->Length() == 0) {
|
||||
delete markers[line];
|
||||
markers[line] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return someChanges;
|
||||
}
|
||||
|
||||
void LineMarkers::DeleteMarkFromHandle(int markerHandle) {
|
||||
int line = LineFromHandle(markerHandle);
|
||||
if (line >= 0) {
|
||||
markers[line]->RemoveHandle(markerHandle);
|
||||
if (markers[line]->Length() == 0) {
|
||||
delete markers[line];
|
||||
markers[line] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LineLevels::~LineLevels() {
|
||||
}
|
||||
|
||||
void LineLevels::Init() {
|
||||
levels.DeleteAll();
|
||||
}
|
||||
|
||||
void LineLevels::InsertLine(int line) {
|
||||
if (levels.Length()) {
|
||||
int level = (line < levels.Length()) ? levels[line] : SC_FOLDLEVELBASE;
|
||||
levels.InsertValue(line, 1, level);
|
||||
}
|
||||
}
|
||||
|
||||
void LineLevels::RemoveLine(int line) {
|
||||
if (levels.Length()) {
|
||||
// Move up following lines but merge header flag from this line
|
||||
// to line before to avoid a temporary disappearence causing expansion.
|
||||
int firstHeader = levels[line] & SC_FOLDLEVELHEADERFLAG;
|
||||
levels.Delete(line);
|
||||
if (line == levels.Length()-1) // Last line loses the header flag
|
||||
levels[line-1] &= ~SC_FOLDLEVELHEADERFLAG;
|
||||
else if (line > 0)
|
||||
levels[line-1] |= firstHeader;
|
||||
}
|
||||
}
|
||||
|
||||
void LineLevels::ExpandLevels(int sizeNew) {
|
||||
levels.InsertValue(levels.Length(), sizeNew - levels.Length(), SC_FOLDLEVELBASE);
|
||||
}
|
||||
|
||||
void LineLevels::ClearLevels() {
|
||||
levels.DeleteAll();
|
||||
}
|
||||
|
||||
int LineLevels::SetLevel(int line, int level, int lines) {
|
||||
int prev = 0;
|
||||
if ((line >= 0) && (line < lines)) {
|
||||
if (!levels.Length()) {
|
||||
ExpandLevels(lines + 1);
|
||||
}
|
||||
prev = levels[line];
|
||||
if (prev != level) {
|
||||
levels[line] = level;
|
||||
}
|
||||
}
|
||||
return prev;
|
||||
}
|
||||
|
||||
int LineLevels::GetLevel(int line) const {
|
||||
if (levels.Length() && (line >= 0) && (line < levels.Length())) {
|
||||
return levels[line];
|
||||
} else {
|
||||
return SC_FOLDLEVELBASE;
|
||||
}
|
||||
}
|
||||
|
||||
LineState::~LineState() {
|
||||
}
|
||||
|
||||
void LineState::Init() {
|
||||
lineStates.DeleteAll();
|
||||
}
|
||||
|
||||
void LineState::InsertLine(int line) {
|
||||
if (lineStates.Length()) {
|
||||
lineStates.EnsureLength(line);
|
||||
int val = (line < lineStates.Length()) ? lineStates[line] : 0;
|
||||
lineStates.Insert(line, val);
|
||||
}
|
||||
}
|
||||
|
||||
void LineState::RemoveLine(int line) {
|
||||
if (lineStates.Length() > line) {
|
||||
lineStates.Delete(line);
|
||||
}
|
||||
}
|
||||
|
||||
int LineState::SetLineState(int line, int state) {
|
||||
lineStates.EnsureLength(line + 1);
|
||||
int stateOld = lineStates[line];
|
||||
lineStates[line] = state;
|
||||
return stateOld;
|
||||
}
|
||||
|
||||
int LineState::GetLineState(int line) {
|
||||
if (line < 0)
|
||||
return 0;
|
||||
lineStates.EnsureLength(line + 1);
|
||||
return lineStates[line];
|
||||
}
|
||||
|
||||
int LineState::GetMaxLineState() const {
|
||||
return lineStates.Length();
|
||||
}
|
||||
|
||||
static int NumberLines(const char *text) {
|
||||
if (text) {
|
||||
int newLines = 0;
|
||||
while (*text) {
|
||||
if (*text == '\n')
|
||||
newLines++;
|
||||
text++;
|
||||
}
|
||||
return newLines+1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Each allocated LineAnnotation is a char array which starts with an AnnotationHeader
|
||||
// and then has text and optional styles.
|
||||
|
||||
static const int IndividualStyles = 0x100;
|
||||
|
||||
struct AnnotationHeader {
|
||||
short style; // Style IndividualStyles implies array of styles
|
||||
short lines;
|
||||
int length;
|
||||
};
|
||||
|
||||
LineAnnotation::~LineAnnotation() {
|
||||
ClearAll();
|
||||
}
|
||||
|
||||
void LineAnnotation::Init() {
|
||||
ClearAll();
|
||||
}
|
||||
|
||||
void LineAnnotation::InsertLine(int line) {
|
||||
if (annotations.Length()) {
|
||||
annotations.EnsureLength(line);
|
||||
annotations.Insert(line, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void LineAnnotation::RemoveLine(int line) {
|
||||
if (annotations.Length() && (line > 0) && (line <= annotations.Length())) {
|
||||
delete []annotations[line-1];
|
||||
annotations.Delete(line-1);
|
||||
}
|
||||
}
|
||||
|
||||
bool LineAnnotation::MultipleStyles(int line) const {
|
||||
if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
|
||||
return reinterpret_cast<AnnotationHeader *>(annotations[line])->style == IndividualStyles;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LineAnnotation::Style(int line) const {
|
||||
if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
|
||||
return reinterpret_cast<AnnotationHeader *>(annotations[line])->style;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *LineAnnotation::Text(int line) const {
|
||||
if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
|
||||
return annotations[line]+sizeof(AnnotationHeader);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const unsigned char *LineAnnotation::Styles(int line) const {
|
||||
if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line] && MultipleStyles(line))
|
||||
return reinterpret_cast<unsigned char *>(annotations[line] + sizeof(AnnotationHeader) + Length(line));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *AllocateAnnotation(int length, int style) {
|
||||
size_t len = sizeof(AnnotationHeader) + length + ((style == IndividualStyles) ? length : 0);
|
||||
char *ret = new char[len];
|
||||
memset(ret, 0, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LineAnnotation::SetText(int line, const char *text) {
|
||||
if (text && (line >= 0)) {
|
||||
annotations.EnsureLength(line+1);
|
||||
int style = Style(line);
|
||||
if (annotations[line]) {
|
||||
delete []annotations[line];
|
||||
}
|
||||
annotations[line] = AllocateAnnotation(static_cast<int>(strlen(text)), style);
|
||||
AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]);
|
||||
pah->style = static_cast<short>(style);
|
||||
pah->length = static_cast<int>(strlen(text));
|
||||
pah->lines = static_cast<short>(NumberLines(text));
|
||||
memcpy(annotations[line]+sizeof(AnnotationHeader), text, pah->length);
|
||||
} else {
|
||||
if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) {
|
||||
delete []annotations[line];
|
||||
annotations[line] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LineAnnotation::ClearAll() {
|
||||
for (int line = 0; line < annotations.Length(); line++) {
|
||||
delete []annotations[line];
|
||||
annotations[line] = 0;
|
||||
}
|
||||
annotations.DeleteAll();
|
||||
}
|
||||
|
||||
void LineAnnotation::SetStyle(int line, int style) {
|
||||
annotations.EnsureLength(line+1);
|
||||
if (!annotations[line]) {
|
||||
annotations[line] = AllocateAnnotation(0, style);
|
||||
}
|
||||
reinterpret_cast<AnnotationHeader *>(annotations[line])->style = static_cast<short>(style);
|
||||
}
|
||||
|
||||
void LineAnnotation::SetStyles(int line, const unsigned char *styles) {
|
||||
if (line >= 0) {
|
||||
annotations.EnsureLength(line+1);
|
||||
if (!annotations[line]) {
|
||||
annotations[line] = AllocateAnnotation(0, IndividualStyles);
|
||||
} else {
|
||||
AnnotationHeader *pahSource = reinterpret_cast<AnnotationHeader *>(annotations[line]);
|
||||
if (pahSource->style != IndividualStyles) {
|
||||
char *allocation = AllocateAnnotation(pahSource->length, IndividualStyles);
|
||||
AnnotationHeader *pahAlloc = reinterpret_cast<AnnotationHeader *>(allocation);
|
||||
pahAlloc->length = pahSource->length;
|
||||
pahAlloc->lines = pahSource->lines;
|
||||
memcpy(allocation + sizeof(AnnotationHeader), annotations[line] + sizeof(AnnotationHeader), pahSource->length);
|
||||
delete []annotations[line];
|
||||
annotations[line] = allocation;
|
||||
}
|
||||
}
|
||||
AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]);
|
||||
pah->style = IndividualStyles;
|
||||
memcpy(annotations[line] + sizeof(AnnotationHeader) + pah->length, styles, pah->length);
|
||||
}
|
||||
}
|
||||
|
||||
int LineAnnotation::Length(int line) const {
|
||||
if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
|
||||
return reinterpret_cast<AnnotationHeader *>(annotations[line])->length;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LineAnnotation::Lines(int line) const {
|
||||
if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
|
||||
return reinterpret_cast<AnnotationHeader *>(annotations[line])->lines;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
123
third-party/scintilla/PerLine.h
vendored
Normal file
123
third-party/scintilla/PerLine.h
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file PerLine.h
|
||||
** Manages data associated with each line of the document
|
||||
**/
|
||||
// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef PERLINE_H
|
||||
#define PERLINE_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This holds the marker identifier and the marker type to display.
|
||||
* MarkerHandleNumbers are members of lists.
|
||||
*/
|
||||
struct MarkerHandleNumber {
|
||||
int handle;
|
||||
int number;
|
||||
MarkerHandleNumber *next;
|
||||
};
|
||||
|
||||
/**
|
||||
* A marker handle set contains any number of MarkerHandleNumbers.
|
||||
*/
|
||||
class MarkerHandleSet {
|
||||
MarkerHandleNumber *root;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
MarkerHandleSet(const MarkerHandleSet &);
|
||||
MarkerHandleSet &operator =(const MarkerHandleSet &);
|
||||
|
||||
public:
|
||||
MarkerHandleSet();
|
||||
~MarkerHandleSet();
|
||||
int Length() const;
|
||||
int MarkValue() const; ///< Bit set of marker numbers.
|
||||
bool Contains(int handle) const;
|
||||
bool InsertHandle(int handle, int markerNum);
|
||||
void RemoveHandle(int handle);
|
||||
bool RemoveNumber(int markerNum, bool all);
|
||||
void CombineWith(MarkerHandleSet *other);
|
||||
};
|
||||
|
||||
class LineMarkers : public PerLine {
|
||||
SplitVector<MarkerHandleSet *> markers;
|
||||
/// Handles are allocated sequentially and should never have to be reused as 32 bit ints are very big.
|
||||
int handleCurrent;
|
||||
public:
|
||||
LineMarkers() : handleCurrent(0) {
|
||||
}
|
||||
virtual ~LineMarkers();
|
||||
virtual void Init();
|
||||
virtual void InsertLine(int line);
|
||||
virtual void RemoveLine(int line);
|
||||
|
||||
int MarkValue(int line);
|
||||
int MarkerNext(int lineStart, int mask) const;
|
||||
int AddMark(int line, int marker, int lines);
|
||||
void MergeMarkers(int pos);
|
||||
bool DeleteMark(int line, int markerNum, bool all);
|
||||
void DeleteMarkFromHandle(int markerHandle);
|
||||
int LineFromHandle(int markerHandle);
|
||||
};
|
||||
|
||||
class LineLevels : public PerLine {
|
||||
SplitVector<int> levels;
|
||||
public:
|
||||
virtual ~LineLevels();
|
||||
virtual void Init();
|
||||
virtual void InsertLine(int line);
|
||||
virtual void RemoveLine(int line);
|
||||
|
||||
void ExpandLevels(int sizeNew=-1);
|
||||
void ClearLevels();
|
||||
int SetLevel(int line, int level, int lines);
|
||||
int GetLevel(int line) const;
|
||||
};
|
||||
|
||||
class LineState : public PerLine {
|
||||
SplitVector<int> lineStates;
|
||||
public:
|
||||
LineState() {
|
||||
}
|
||||
virtual ~LineState();
|
||||
virtual void Init();
|
||||
virtual void InsertLine(int line);
|
||||
virtual void RemoveLine(int line);
|
||||
|
||||
int SetLineState(int line, int state);
|
||||
int GetLineState(int line);
|
||||
int GetMaxLineState() const;
|
||||
};
|
||||
|
||||
class LineAnnotation : public PerLine {
|
||||
SplitVector<char *> annotations;
|
||||
public:
|
||||
LineAnnotation() {
|
||||
}
|
||||
virtual ~LineAnnotation();
|
||||
virtual void Init();
|
||||
virtual void InsertLine(int line);
|
||||
virtual void RemoveLine(int line);
|
||||
|
||||
bool MultipleStyles(int line) const;
|
||||
int Style(int line) const;
|
||||
const char *Text(int line) const;
|
||||
const unsigned char *Styles(int line) const;
|
||||
void SetText(int line, const char *text);
|
||||
void ClearAll();
|
||||
void SetStyle(int line, int style);
|
||||
void SetStyles(int line, const unsigned char *styles);
|
||||
int Length(int line) const;
|
||||
int Lines(int line) const;
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
1320
third-party/scintilla/PlatQt.cc
vendored
Normal file
1320
third-party/scintilla/PlatQt.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
121
third-party/scintilla/PlatQt.h
vendored
Normal file
121
third-party/scintilla/PlatQt.h
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
//
|
||||
// Copyright (c) 1990-2011, Scientific Toolworks, Inc.
|
||||
//
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
//
|
||||
// Author: Jason Haslam
|
||||
//
|
||||
// Additions Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware
|
||||
// Scintilla platform layer for Qt
|
||||
|
||||
#ifndef PLATQT_H
|
||||
#define PLATQT_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
const char *CharacterSetID(int characterSet);
|
||||
|
||||
inline QColor QColorFromCA(ColourDesired ca)
|
||||
{
|
||||
long c = ca.AsLong();
|
||||
return QColor(c & 0xff, (c >> 8) & 0xff, (c >> 16) & 0xff);
|
||||
}
|
||||
|
||||
inline QRect QRectFromPRect(PRectangle pr)
|
||||
{
|
||||
return QRect(pr.left, pr.top, pr.Width(), pr.Height());
|
||||
}
|
||||
|
||||
inline PRectangle PRectFromQRect(QRect qr)
|
||||
{
|
||||
return PRectangle(qr.x(), qr.y(), qr.x() + qr.width(), qr.y() + qr.height());
|
||||
}
|
||||
|
||||
inline Point PointFromQPoint(QPoint qp)
|
||||
{
|
||||
return Point(qp.x(), qp.y());
|
||||
}
|
||||
|
||||
class SurfaceImpl : public Surface {
|
||||
private:
|
||||
QPaintDevice *device;
|
||||
QPainter *painter;
|
||||
bool deviceOwned;
|
||||
bool painterOwned;
|
||||
float x, y;
|
||||
bool unicodeMode;
|
||||
int codePage;
|
||||
const char *codecName;
|
||||
QTextCodec *codec;
|
||||
|
||||
public:
|
||||
SurfaceImpl();
|
||||
virtual ~SurfaceImpl();
|
||||
|
||||
virtual void Init(WindowID wid);
|
||||
virtual void Init(SurfaceID sid, WindowID wid);
|
||||
virtual void InitPixMap(int width, int height,
|
||||
Surface *surface, WindowID wid);
|
||||
|
||||
virtual void Release();
|
||||
virtual bool Initialised();
|
||||
virtual void PenColour(ColourDesired fore);
|
||||
virtual int LogPixelsY();
|
||||
virtual int DeviceHeightFont(int points);
|
||||
virtual void MoveTo(int x, int y);
|
||||
virtual void LineTo(int x, int y);
|
||||
virtual void Polygon(Point *pts, int npts, ColourDesired fore,
|
||||
ColourDesired back);
|
||||
virtual void RectangleDraw(PRectangle rc, ColourDesired fore,
|
||||
ColourDesired back);
|
||||
virtual void FillRectangle(PRectangle rc, ColourDesired back);
|
||||
virtual void FillRectangle(PRectangle rc, Surface &surfacePattern);
|
||||
virtual void RoundedRectangle(PRectangle rc, ColourDesired fore,
|
||||
ColourDesired back);
|
||||
virtual void AlphaRectangle(PRectangle rc, int corner, ColourDesired fill,
|
||||
int alphaFill, ColourDesired outline, int alphaOutline, int flags);
|
||||
virtual void DrawRGBAImage(PRectangle rc, int width, int height,
|
||||
const unsigned char *pixelsImage);
|
||||
virtual void Ellipse(PRectangle rc, ColourDesired fore,
|
||||
ColourDesired back);
|
||||
virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource);
|
||||
|
||||
virtual void DrawTextNoClip(PRectangle rc, Font &font, XYPOSITION ybase,
|
||||
const char *s, int len, ColourDesired fore, ColourDesired back);
|
||||
virtual void DrawTextClipped(PRectangle rc, Font &font, XYPOSITION ybase,
|
||||
const char *s, int len, ColourDesired fore, ColourDesired back);
|
||||
virtual void DrawTextTransparent(PRectangle rc, Font &font, XYPOSITION ybase,
|
||||
const char *s, int len, ColourDesired fore);
|
||||
virtual void MeasureWidths(Font &font, const char *s, int len,
|
||||
XYPOSITION *positions);
|
||||
virtual XYPOSITION WidthText(Font &font, const char *s, int len);
|
||||
virtual XYPOSITION WidthChar(Font &font, char ch);
|
||||
virtual XYPOSITION Ascent(Font &font);
|
||||
virtual XYPOSITION Descent(Font &font);
|
||||
virtual XYPOSITION InternalLeading(Font &font);
|
||||
virtual XYPOSITION ExternalLeading(Font &font);
|
||||
virtual XYPOSITION Height(Font &font);
|
||||
virtual XYPOSITION AverageCharWidth(Font &font);
|
||||
|
||||
virtual void SetClip(PRectangle rc);
|
||||
virtual void FlushCachedState();
|
||||
|
||||
virtual void SetUnicodeMode(bool unicodeMode);
|
||||
virtual void SetDBCSMode(int codePage);
|
||||
|
||||
void BrushColour(ColourDesired back);
|
||||
void SetCodec(Font &font);
|
||||
void SetFont(Font &font);
|
||||
|
||||
QPaintDevice *GetPaintDevice();
|
||||
void SetPainter(QPainter *painter);
|
||||
QPainter *GetPainter();
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
563
third-party/scintilla/Platform.h
vendored
Normal file
563
third-party/scintilla/Platform.h
vendored
Normal file
@@ -0,0 +1,563 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file Platform.h
|
||||
** Interface to platform facilities. Also includes some basic utilities.
|
||||
** Implemented in PlatGTK.cxx for GTK+/Linux, PlatWin.cxx for Windows, and PlatWX.cxx for wxWindows.
|
||||
**/
|
||||
// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef PLATFORM_H
|
||||
#define PLATFORM_H
|
||||
|
||||
// PLAT_GTK = GTK+ on Linux or Win32
|
||||
// PLAT_GTK_WIN32 is defined additionally when running PLAT_GTK under Win32
|
||||
// PLAT_WIN = Win32 API on Win32 OS
|
||||
// PLAT_WX is wxWindows on any supported platform
|
||||
// PLAT_TK = Tcl/TK on Linux or Win32
|
||||
|
||||
#define PLAT_GTK 0
|
||||
#define PLAT_GTK_WIN32 0
|
||||
#define PLAT_GTK_MACOSX 0
|
||||
#define PLAT_MACOSX 0
|
||||
#define PLAT_WIN 0
|
||||
#define PLAT_WX 0
|
||||
#define PLAT_QT 0
|
||||
#define PLAT_FOX 0
|
||||
#define PLAT_CURSES 0
|
||||
#define PLAT_TK 0
|
||||
#define PLAT_UNIX 0
|
||||
|
||||
#if defined(FOX)
|
||||
#undef PLAT_FOX
|
||||
#define PLAT_FOX 1
|
||||
|
||||
#elif defined(__WX__)
|
||||
#undef PLAT_WX
|
||||
#define PLAT_WX 1
|
||||
|
||||
#elif defined(CURSES)
|
||||
#undef PLAT_CURSES
|
||||
#define PLAT_CURSES 1
|
||||
|
||||
#elif defined(SCINTILLA_QT)
|
||||
#undef PLAT_QT
|
||||
#define PLAT_QT 1
|
||||
|
||||
#elif defined(TK)
|
||||
#undef PLAT_TK
|
||||
#define PLAT_TK 1
|
||||
|
||||
#elif defined(GTK)
|
||||
#undef PLAT_GTK
|
||||
#define PLAT_GTK 1
|
||||
|
||||
#if defined(__WIN32__) || defined(_MSC_VER)
|
||||
#undef PLAT_GTK_WIN32
|
||||
#define PLAT_GTK_WIN32 1
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#undef PLAT_GTK_MACOSX
|
||||
#define PLAT_GTK_MACOSX 1
|
||||
#endif
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
#undef PLAT_MACOSX
|
||||
#define PLAT_MACOSX 1
|
||||
|
||||
#elif defined(__unix__)
|
||||
|
||||
#undef PLAT_UNIX
|
||||
#define PLAT_UNIX 1
|
||||
|
||||
#else
|
||||
#undef PLAT_WIN
|
||||
#define PLAT_WIN 1
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
typedef float XYPOSITION;
|
||||
typedef double XYACCUMULATOR;
|
||||
inline int RoundXYPosition(XYPOSITION xyPos) {
|
||||
return int(xyPos + 0.5);
|
||||
}
|
||||
|
||||
// Underlying the implementation of the platform classes are platform specific types.
|
||||
// Sometimes these need to be passed around by client code so they are defined here
|
||||
|
||||
typedef void *FontID;
|
||||
typedef void *SurfaceID;
|
||||
typedef void *WindowID;
|
||||
typedef void *MenuID;
|
||||
typedef void *TickerID;
|
||||
typedef void *Function;
|
||||
typedef void *IdlerID;
|
||||
|
||||
/**
|
||||
* A geometric point class.
|
||||
* Point is exactly the same as the Win32 POINT and GTK+ GdkPoint so can be used interchangeably.
|
||||
*/
|
||||
class Point {
|
||||
public:
|
||||
XYPOSITION x;
|
||||
XYPOSITION y;
|
||||
|
||||
explicit Point(XYPOSITION x_=0, XYPOSITION y_=0) : x(x_), y(y_) {
|
||||
}
|
||||
|
||||
static Point FromInts(int x_, int y_) {
|
||||
return Point(static_cast<XYPOSITION>(x_), static_cast<XYPOSITION>(y_));
|
||||
}
|
||||
// Other automatically defined methods (assignment, copy constructor, destructor) are fine
|
||||
|
||||
static Point FromLong(long lpoint);
|
||||
};
|
||||
|
||||
/**
|
||||
* A geometric rectangle class.
|
||||
* PRectangle is exactly the same as the Win32 RECT so can be used interchangeably.
|
||||
* PRectangles contain their top and left sides, but not their right and bottom sides.
|
||||
*/
|
||||
class PRectangle {
|
||||
public:
|
||||
XYPOSITION left;
|
||||
XYPOSITION top;
|
||||
XYPOSITION right;
|
||||
XYPOSITION bottom;
|
||||
|
||||
explicit PRectangle(XYPOSITION left_=0, XYPOSITION top_=0, XYPOSITION right_=0, XYPOSITION bottom_ = 0) :
|
||||
left(left_), top(top_), right(right_), bottom(bottom_) {
|
||||
}
|
||||
static PRectangle FromInts(int left_, int top_, int right_, int bottom_) {
|
||||
return PRectangle(static_cast<XYPOSITION>(left_), static_cast<XYPOSITION>(top_),
|
||||
static_cast<XYPOSITION>(right_), static_cast<XYPOSITION>(bottom_));
|
||||
}
|
||||
|
||||
// Other automatically defined methods (assignment, copy constructor, destructor) are fine
|
||||
|
||||
bool operator==(PRectangle &rc) const {
|
||||
return (rc.left == left) && (rc.right == right) &&
|
||||
(rc.top == top) && (rc.bottom == bottom);
|
||||
}
|
||||
bool Contains(Point pt) const {
|
||||
return (pt.x >= left) && (pt.x <= right) &&
|
||||
(pt.y >= top) && (pt.y <= bottom);
|
||||
}
|
||||
bool Contains(PRectangle rc) const {
|
||||
return (rc.left >= left) && (rc.right <= right) &&
|
||||
(rc.top >= top) && (rc.bottom <= bottom);
|
||||
}
|
||||
bool Intersects(PRectangle other) const {
|
||||
return (right > other.left) && (left < other.right) &&
|
||||
(bottom > other.top) && (top < other.bottom);
|
||||
}
|
||||
void Move(XYPOSITION xDelta, XYPOSITION yDelta) {
|
||||
left += xDelta;
|
||||
top += yDelta;
|
||||
right += xDelta;
|
||||
bottom += yDelta;
|
||||
}
|
||||
XYPOSITION Width() const { return right - left; }
|
||||
XYPOSITION Height() const { return bottom - top; }
|
||||
bool Empty() const {
|
||||
return (Height() <= 0) || (Width() <= 0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Holds a desired RGB colour.
|
||||
*/
|
||||
class ColourDesired {
|
||||
long co;
|
||||
public:
|
||||
ColourDesired(long lcol=0) {
|
||||
co = lcol;
|
||||
}
|
||||
|
||||
ColourDesired(unsigned int red, unsigned int green, unsigned int blue) {
|
||||
Set(red, green, blue);
|
||||
}
|
||||
|
||||
bool operator==(const ColourDesired &other) const {
|
||||
return co == other.co;
|
||||
}
|
||||
|
||||
void Set(long lcol) {
|
||||
co = lcol;
|
||||
}
|
||||
|
||||
void Set(unsigned int red, unsigned int green, unsigned int blue) {
|
||||
co = red | (green << 8) | (blue << 16);
|
||||
}
|
||||
|
||||
static inline unsigned int ValueOfHex(const char ch) {
|
||||
if (ch >= '0' && ch <= '9')
|
||||
return ch - '0';
|
||||
else if (ch >= 'A' && ch <= 'F')
|
||||
return ch - 'A' + 10;
|
||||
else if (ch >= 'a' && ch <= 'f')
|
||||
return ch - 'a' + 10;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Set(const char *val) {
|
||||
if (*val == '#') {
|
||||
val++;
|
||||
}
|
||||
unsigned int r = ValueOfHex(val[0]) * 16 + ValueOfHex(val[1]);
|
||||
unsigned int g = ValueOfHex(val[2]) * 16 + ValueOfHex(val[3]);
|
||||
unsigned int b = ValueOfHex(val[4]) * 16 + ValueOfHex(val[5]);
|
||||
Set(r, g, b);
|
||||
}
|
||||
|
||||
long AsLong() const {
|
||||
return co;
|
||||
}
|
||||
|
||||
unsigned int GetRed() const {
|
||||
return co & 0xff;
|
||||
}
|
||||
|
||||
unsigned int GetGreen() const {
|
||||
return (co >> 8) & 0xff;
|
||||
}
|
||||
|
||||
unsigned int GetBlue() const {
|
||||
return (co >> 16) & 0xff;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Font management.
|
||||
*/
|
||||
|
||||
struct FontParameters {
|
||||
const char *faceName;
|
||||
float size;
|
||||
int weight;
|
||||
bool italic;
|
||||
int extraFontFlag;
|
||||
int technology;
|
||||
int characterSet;
|
||||
|
||||
FontParameters(
|
||||
const char *faceName_,
|
||||
float size_=10,
|
||||
int weight_=400,
|
||||
bool italic_=false,
|
||||
int extraFontFlag_=0,
|
||||
int technology_=0,
|
||||
int characterSet_=0) :
|
||||
|
||||
faceName(faceName_),
|
||||
size(size_),
|
||||
weight(weight_),
|
||||
italic(italic_),
|
||||
extraFontFlag(extraFontFlag_),
|
||||
technology(technology_),
|
||||
characterSet(characterSet_)
|
||||
{
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class Font {
|
||||
protected:
|
||||
FontID fid;
|
||||
#if PLAT_WX
|
||||
int ascent;
|
||||
#endif
|
||||
// Private so Font objects can not be copied
|
||||
Font(const Font &);
|
||||
Font &operator=(const Font &);
|
||||
public:
|
||||
Font();
|
||||
virtual ~Font();
|
||||
|
||||
virtual void Create(const FontParameters &fp);
|
||||
virtual void Release();
|
||||
|
||||
FontID GetID() { return fid; }
|
||||
// Alias another font - caller guarantees not to Release
|
||||
void SetID(FontID fid_) { fid = fid_; }
|
||||
#if PLAT_WX
|
||||
void SetAscent(int ascent_) { ascent = ascent_; }
|
||||
#endif
|
||||
friend class Surface;
|
||||
friend class SurfaceImpl;
|
||||
};
|
||||
|
||||
/**
|
||||
* A surface abstracts a place to draw.
|
||||
*/
|
||||
class Surface {
|
||||
private:
|
||||
// Private so Surface objects can not be copied
|
||||
Surface(const Surface &) {}
|
||||
Surface &operator=(const Surface &) { return *this; }
|
||||
public:
|
||||
Surface() {}
|
||||
virtual ~Surface() {}
|
||||
static Surface *Allocate(int technology);
|
||||
|
||||
virtual void Init(WindowID wid)=0;
|
||||
virtual void Init(SurfaceID sid, WindowID wid)=0;
|
||||
virtual void InitPixMap(int width, int height, Surface *surface_, WindowID wid)=0;
|
||||
|
||||
virtual void Release()=0;
|
||||
virtual bool Initialised()=0;
|
||||
virtual void PenColour(ColourDesired fore)=0;
|
||||
virtual int LogPixelsY()=0;
|
||||
virtual int DeviceHeightFont(int points)=0;
|
||||
virtual void MoveTo(int x_, int y_)=0;
|
||||
virtual void LineTo(int x_, int y_)=0;
|
||||
virtual void Polygon(Point *pts, int npts, ColourDesired fore, ColourDesired back)=0;
|
||||
virtual void RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back)=0;
|
||||
virtual void FillRectangle(PRectangle rc, ColourDesired back)=0;
|
||||
virtual void FillRectangle(PRectangle rc, Surface &surfacePattern)=0;
|
||||
virtual void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back)=0;
|
||||
virtual void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill,
|
||||
ColourDesired outline, int alphaOutline, int flags)=0;
|
||||
virtual void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) = 0;
|
||||
virtual void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back)=0;
|
||||
virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource)=0;
|
||||
|
||||
virtual void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back)=0;
|
||||
virtual void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back)=0;
|
||||
virtual void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore)=0;
|
||||
virtual void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions)=0;
|
||||
virtual XYPOSITION WidthText(Font &font_, const char *s, int len)=0;
|
||||
virtual XYPOSITION WidthChar(Font &font_, char ch)=0;
|
||||
virtual XYPOSITION Ascent(Font &font_)=0;
|
||||
virtual XYPOSITION Descent(Font &font_)=0;
|
||||
virtual XYPOSITION InternalLeading(Font &font_)=0;
|
||||
virtual XYPOSITION ExternalLeading(Font &font_)=0;
|
||||
virtual XYPOSITION Height(Font &font_)=0;
|
||||
virtual XYPOSITION AverageCharWidth(Font &font_)=0;
|
||||
|
||||
virtual void SetClip(PRectangle rc)=0;
|
||||
virtual void FlushCachedState()=0;
|
||||
|
||||
virtual void SetUnicodeMode(bool unicodeMode_)=0;
|
||||
virtual void SetDBCSMode(int codePage)=0;
|
||||
};
|
||||
|
||||
/**
|
||||
* A simple callback action passing one piece of untyped user data.
|
||||
*/
|
||||
typedef void (*CallBackAction)(void*);
|
||||
|
||||
/**
|
||||
* Class to hide the details of window manipulation.
|
||||
* Does not own the window which will normally have a longer life than this object.
|
||||
*/
|
||||
class Window {
|
||||
protected:
|
||||
WindowID wid;
|
||||
#if PLAT_MACOSX
|
||||
void *windowRef;
|
||||
void *control;
|
||||
#endif
|
||||
public:
|
||||
Window() : wid(0), cursorLast(cursorInvalid) {
|
||||
#if PLAT_MACOSX
|
||||
windowRef = 0;
|
||||
control = 0;
|
||||
#endif
|
||||
}
|
||||
Window(const Window &source) : wid(source.wid), cursorLast(cursorInvalid) {
|
||||
#if PLAT_MACOSX
|
||||
windowRef = 0;
|
||||
control = 0;
|
||||
#endif
|
||||
}
|
||||
virtual ~Window();
|
||||
Window &operator=(WindowID wid_) {
|
||||
wid = wid_;
|
||||
return *this;
|
||||
}
|
||||
WindowID GetID() const { return wid; }
|
||||
bool Created() const { return wid != 0; }
|
||||
void Destroy();
|
||||
bool HasFocus();
|
||||
PRectangle GetPosition();
|
||||
void SetPosition(PRectangle rc);
|
||||
void SetPositionRelative(PRectangle rc, Window relativeTo);
|
||||
PRectangle GetClientPosition();
|
||||
void Show(bool show=true);
|
||||
void InvalidateAll();
|
||||
void InvalidateRectangle(PRectangle rc);
|
||||
virtual void SetFont(Font &font);
|
||||
enum Cursor { cursorInvalid, cursorText, cursorArrow, cursorUp, cursorWait, cursorHoriz, cursorVert, cursorReverseArrow, cursorHand };
|
||||
void SetCursor(Cursor curs);
|
||||
void SetTitle(const char *s);
|
||||
PRectangle GetMonitorRect(Point pt);
|
||||
#if PLAT_MACOSX
|
||||
void SetWindow(void *ref) { windowRef = ref; }
|
||||
void SetControl(void *_control) { control = _control; }
|
||||
#endif
|
||||
private:
|
||||
Cursor cursorLast;
|
||||
|
||||
// no assignment op
|
||||
Window &operator =(const Window &);
|
||||
};
|
||||
|
||||
/**
|
||||
* Listbox management.
|
||||
*/
|
||||
|
||||
class ListBox : public Window {
|
||||
public:
|
||||
ListBox();
|
||||
virtual ~ListBox();
|
||||
static ListBox *Allocate();
|
||||
|
||||
virtual void SetFont(Font &font)=0;
|
||||
virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_, int technology_)=0;
|
||||
virtual void SetAverageCharWidth(int width)=0;
|
||||
virtual void SetVisibleRows(int rows)=0;
|
||||
virtual int GetVisibleRows() const=0;
|
||||
virtual PRectangle GetDesiredRect()=0;
|
||||
virtual int CaretFromEdge()=0;
|
||||
virtual void Clear()=0;
|
||||
virtual void Append(char *s, int type = -1)=0;
|
||||
virtual int Length()=0;
|
||||
virtual void Select(int n)=0;
|
||||
virtual int GetSelection()=0;
|
||||
virtual int Find(const char *prefix)=0;
|
||||
virtual void GetValue(int n, char *value, int len)=0;
|
||||
virtual void RegisterImage(int type, const char *xpm_data)=0;
|
||||
virtual void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) = 0;
|
||||
virtual void ClearRegisteredImages()=0;
|
||||
virtual void SetDoubleClickAction(CallBackAction, void *)=0;
|
||||
virtual void SetList(const char* list, char separator, char typesep)=0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Menu management.
|
||||
*/
|
||||
class Menu {
|
||||
MenuID mid;
|
||||
public:
|
||||
Menu();
|
||||
MenuID GetID() { return mid; }
|
||||
void CreatePopUp();
|
||||
void Destroy();
|
||||
void Show(Point pt, Window &w);
|
||||
};
|
||||
|
||||
class ElapsedTime {
|
||||
long bigBit;
|
||||
long littleBit;
|
||||
public:
|
||||
ElapsedTime();
|
||||
double Duration(bool reset=false);
|
||||
};
|
||||
|
||||
/**
|
||||
* Dynamic Library (DLL/SO/...) loading
|
||||
*/
|
||||
class DynamicLibrary {
|
||||
public:
|
||||
virtual ~DynamicLibrary() {}
|
||||
|
||||
/// @return Pointer to function "name", or NULL on failure.
|
||||
virtual Function FindFunction(const char *name) = 0;
|
||||
|
||||
/// @return true if the library was loaded successfully.
|
||||
virtual bool IsValid() = 0;
|
||||
|
||||
/// @return An instance of a DynamicLibrary subclass with "modulePath" loaded.
|
||||
static DynamicLibrary *Load(const char *modulePath);
|
||||
};
|
||||
|
||||
#if defined(__clang__)
|
||||
# if __has_feature(attribute_analyzer_noreturn)
|
||||
# define CLANG_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
|
||||
# else
|
||||
# define CLANG_ANALYZER_NORETURN
|
||||
# endif
|
||||
#else
|
||||
# define CLANG_ANALYZER_NORETURN
|
||||
#endif
|
||||
/**
|
||||
* Platform class used to retrieve system wide parameters such as double click speed
|
||||
* and chrome colour. Not a creatable object, more of a module with several functions.
|
||||
*/
|
||||
class Platform {
|
||||
// Private so Platform objects can not be copied
|
||||
Platform(const Platform &) {}
|
||||
Platform &operator=(const Platform &) { return *this; }
|
||||
public:
|
||||
// Should be private because no new Platforms are ever created
|
||||
// but gcc warns about this
|
||||
Platform() {}
|
||||
~Platform() {}
|
||||
static ColourDesired Chrome();
|
||||
static ColourDesired ChromeHighlight();
|
||||
static const char *DefaultFont();
|
||||
static int DefaultFontSize();
|
||||
static unsigned int DoubleClickTime();
|
||||
static bool MouseButtonBounce();
|
||||
static void DebugDisplay(const char *s);
|
||||
static bool IsKeyDown(int key);
|
||||
static long SendScintilla(
|
||||
WindowID w, unsigned int msg, unsigned long wParam=0, long lParam=0);
|
||||
static long SendScintillaPointer(
|
||||
WindowID w, unsigned int msg, unsigned long wParam=0, void *lParam=0);
|
||||
static bool IsDBCSLeadByte(int codePage, char ch);
|
||||
static int DBCSCharLength(int codePage, const char *s);
|
||||
static int DBCSCharMaxLength();
|
||||
|
||||
// These are utility functions not really tied to a platform
|
||||
static int Minimum(int a, int b);
|
||||
static int Maximum(int a, int b);
|
||||
// Next three assume 16 bit shorts and 32 bit longs
|
||||
static long LongFromTwoShorts(short a,short b) {
|
||||
return (a) | ((b) << 16);
|
||||
}
|
||||
static short HighShortFromLong(long x) {
|
||||
return static_cast<short>(x >> 16);
|
||||
}
|
||||
static short LowShortFromLong(long x) {
|
||||
return static_cast<short>(x & 0xffff);
|
||||
}
|
||||
static void DebugPrintf(const char *format, ...);
|
||||
static bool ShowAssertionPopUps(bool assertionPopUps_);
|
||||
static void Assert(const char *c, const char *file, int line) CLANG_ANALYZER_NORETURN;
|
||||
static int Clamp(int val, int minVal, int maxVal);
|
||||
};
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define PLATFORM_ASSERT(c) ((void)0)
|
||||
#else
|
||||
#ifdef SCI_NAMESPACE
|
||||
#define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Scintilla::Platform::Assert(#c, __FILE__, __LINE__))
|
||||
#else
|
||||
#define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Platform::Assert(#c, __FILE__, __LINE__))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
// Shut up annoying Visual C++ warnings:
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4244 4309 4514 4710)
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(SCINTILLA_QT)
|
||||
#pragma GCC diagnostic ignored "-Wmissing-braces"
|
||||
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
#pragma GCC diagnostic ignored "-Wchar-subscripts"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
688
third-party/scintilla/PositionCache.cxx
vendored
Normal file
688
third-party/scintilla/PositionCache.cxx
vendored
Normal file
@@ -0,0 +1,688 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file PositionCache.cxx
|
||||
** Classes for caching layout information.
|
||||
**/
|
||||
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
|
||||
#include "SplitVector.h"
|
||||
#include "Partitioning.h"
|
||||
#include "RunStyles.h"
|
||||
#include "ContractionState.h"
|
||||
#include "CellBuffer.h"
|
||||
#include "KeyMap.h"
|
||||
#include "Indicator.h"
|
||||
#include "XPM.h"
|
||||
#include "LineMarker.h"
|
||||
#include "Style.h"
|
||||
#include "ViewStyle.h"
|
||||
#include "CharClassify.h"
|
||||
#include "Decoration.h"
|
||||
#include "ILexer.h"
|
||||
#include "CaseFolder.h"
|
||||
#include "Document.h"
|
||||
#include "UniConversion.h"
|
||||
#include "Selection.h"
|
||||
#include "PositionCache.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
LineLayout::LineLayout(int maxLineLength_) :
|
||||
lineStarts(0),
|
||||
lenLineStarts(0),
|
||||
lineNumber(-1),
|
||||
inCache(false),
|
||||
maxLineLength(-1),
|
||||
numCharsInLine(0),
|
||||
numCharsBeforeEOL(0),
|
||||
validity(llInvalid),
|
||||
xHighlightGuide(0),
|
||||
highlightColumn(0),
|
||||
psel(NULL),
|
||||
containsCaret(false),
|
||||
edgeColumn(0),
|
||||
chars(0),
|
||||
styles(0),
|
||||
styleBitsSet(0),
|
||||
indicators(0),
|
||||
positions(0),
|
||||
hsStart(0),
|
||||
hsEnd(0),
|
||||
widthLine(wrapWidthInfinite),
|
||||
lines(1),
|
||||
wrapIndent(0) {
|
||||
bracePreviousStyles[0] = 0;
|
||||
bracePreviousStyles[1] = 0;
|
||||
Resize(maxLineLength_);
|
||||
}
|
||||
|
||||
LineLayout::~LineLayout() {
|
||||
Free();
|
||||
}
|
||||
|
||||
void LineLayout::Resize(int maxLineLength_) {
|
||||
if (maxLineLength_ > maxLineLength) {
|
||||
Free();
|
||||
chars = new char[maxLineLength_ + 1];
|
||||
styles = new unsigned char[maxLineLength_ + 1];
|
||||
indicators = new char[maxLineLength_ + 1];
|
||||
// Extra position allocated as sometimes the Windows
|
||||
// GetTextExtentExPoint API writes an extra element.
|
||||
positions = new XYPOSITION[maxLineLength_ + 1 + 1];
|
||||
maxLineLength = maxLineLength_;
|
||||
}
|
||||
}
|
||||
|
||||
void LineLayout::Free() {
|
||||
delete []chars;
|
||||
chars = 0;
|
||||
delete []styles;
|
||||
styles = 0;
|
||||
delete []indicators;
|
||||
indicators = 0;
|
||||
delete []positions;
|
||||
positions = 0;
|
||||
delete []lineStarts;
|
||||
lineStarts = 0;
|
||||
}
|
||||
|
||||
void LineLayout::Invalidate(validLevel validity_) {
|
||||
if (validity > validity_)
|
||||
validity = validity_;
|
||||
}
|
||||
|
||||
int LineLayout::LineStart(int line) const {
|
||||
if (line <= 0) {
|
||||
return 0;
|
||||
} else if ((line >= lines) || !lineStarts) {
|
||||
return numCharsInLine;
|
||||
} else {
|
||||
return lineStarts[line];
|
||||
}
|
||||
}
|
||||
|
||||
int LineLayout::LineLastVisible(int line) const {
|
||||
if (line < 0) {
|
||||
return 0;
|
||||
} else if ((line >= lines-1) || !lineStarts) {
|
||||
return numCharsBeforeEOL;
|
||||
} else {
|
||||
return lineStarts[line+1];
|
||||
}
|
||||
}
|
||||
|
||||
Range LineLayout::SubLineRange(int subLine) const {
|
||||
return Range(LineStart(subLine), LineLastVisible(subLine));
|
||||
}
|
||||
|
||||
bool LineLayout::InLine(int offset, int line) const {
|
||||
return ((offset >= LineStart(line)) && (offset < LineStart(line + 1))) ||
|
||||
((offset == numCharsInLine) && (line == (lines-1)));
|
||||
}
|
||||
|
||||
void LineLayout::SetLineStart(int line, int start) {
|
||||
if ((line >= lenLineStarts) && (line != 0)) {
|
||||
int newMaxLines = line + 20;
|
||||
int *newLineStarts = new int[newMaxLines];
|
||||
for (int i = 0; i < newMaxLines; i++) {
|
||||
if (i < lenLineStarts)
|
||||
newLineStarts[i] = lineStarts[i];
|
||||
else
|
||||
newLineStarts[i] = 0;
|
||||
}
|
||||
delete []lineStarts;
|
||||
lineStarts = newLineStarts;
|
||||
lenLineStarts = newMaxLines;
|
||||
}
|
||||
lineStarts[line] = start;
|
||||
}
|
||||
|
||||
void LineLayout::SetBracesHighlight(Range rangeLine, Position braces[],
|
||||
char bracesMatchStyle, int xHighlight, bool ignoreStyle) {
|
||||
if (!ignoreStyle && rangeLine.ContainsCharacter(braces[0])) {
|
||||
int braceOffset = braces[0] - rangeLine.start;
|
||||
if (braceOffset < numCharsInLine) {
|
||||
bracePreviousStyles[0] = styles[braceOffset];
|
||||
styles[braceOffset] = bracesMatchStyle;
|
||||
}
|
||||
}
|
||||
if (!ignoreStyle && rangeLine.ContainsCharacter(braces[1])) {
|
||||
int braceOffset = braces[1] - rangeLine.start;
|
||||
if (braceOffset < numCharsInLine) {
|
||||
bracePreviousStyles[1] = styles[braceOffset];
|
||||
styles[braceOffset] = bracesMatchStyle;
|
||||
}
|
||||
}
|
||||
if ((braces[0] >= rangeLine.start && braces[1] <= rangeLine.end) ||
|
||||
(braces[1] >= rangeLine.start && braces[0] <= rangeLine.end)) {
|
||||
xHighlightGuide = xHighlight;
|
||||
}
|
||||
}
|
||||
|
||||
void LineLayout::RestoreBracesHighlight(Range rangeLine, Position braces[], bool ignoreStyle) {
|
||||
if (!ignoreStyle && rangeLine.ContainsCharacter(braces[0])) {
|
||||
int braceOffset = braces[0] - rangeLine.start;
|
||||
if (braceOffset < numCharsInLine) {
|
||||
styles[braceOffset] = bracePreviousStyles[0];
|
||||
}
|
||||
}
|
||||
if (!ignoreStyle && rangeLine.ContainsCharacter(braces[1])) {
|
||||
int braceOffset = braces[1] - rangeLine.start;
|
||||
if (braceOffset < numCharsInLine) {
|
||||
styles[braceOffset] = bracePreviousStyles[1];
|
||||
}
|
||||
}
|
||||
xHighlightGuide = 0;
|
||||
}
|
||||
|
||||
int LineLayout::FindBefore(XYPOSITION x, int lower, int upper) const {
|
||||
do {
|
||||
int middle = (upper + lower + 1) / 2; // Round high
|
||||
XYPOSITION posMiddle = positions[middle];
|
||||
if (x < posMiddle) {
|
||||
upper = middle - 1;
|
||||
} else {
|
||||
lower = middle;
|
||||
}
|
||||
} while (lower < upper);
|
||||
return lower;
|
||||
}
|
||||
|
||||
|
||||
int LineLayout::FindPositionFromX(XYPOSITION x, Range range, bool charPosition) const {
|
||||
int pos = FindBefore(x, range.start, range.end);
|
||||
while (pos < range.end) {
|
||||
if (charPosition) {
|
||||
if (x < (positions[pos + 1])) {
|
||||
return pos;
|
||||
}
|
||||
} else {
|
||||
if (x < ((positions[pos] + positions[pos + 1]) / 2)) {
|
||||
return pos;
|
||||
}
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
return range.end;
|
||||
}
|
||||
|
||||
Point LineLayout::PointFromPosition(int posInLine, int lineHeight) const {
|
||||
Point pt;
|
||||
// In case of very long line put x at arbitrary large position
|
||||
if (posInLine > maxLineLength) {
|
||||
pt.x = positions[maxLineLength] - positions[LineStart(lines)];
|
||||
}
|
||||
|
||||
for (int subLine = 0; subLine < lines; subLine++) {
|
||||
const Range rangeSubLine = SubLineRange(subLine);
|
||||
if (posInLine >= rangeSubLine.start) {
|
||||
pt.y = static_cast<XYPOSITION>(subLine*lineHeight);
|
||||
if (posInLine <= rangeSubLine.end) {
|
||||
pt.x = positions[posInLine] - positions[rangeSubLine.start];
|
||||
if (rangeSubLine.start != 0) // Wrapped lines may be indented
|
||||
pt.x += wrapIndent;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pt;
|
||||
}
|
||||
|
||||
int LineLayout::EndLineStyle() const {
|
||||
return styles[numCharsBeforeEOL > 0 ? numCharsBeforeEOL-1 : 0];
|
||||
}
|
||||
|
||||
LineLayoutCache::LineLayoutCache() :
|
||||
level(0),
|
||||
allInvalidated(false), styleClock(-1), useCount(0) {
|
||||
Allocate(0);
|
||||
}
|
||||
|
||||
LineLayoutCache::~LineLayoutCache() {
|
||||
Deallocate();
|
||||
}
|
||||
|
||||
void LineLayoutCache::Allocate(size_t length_) {
|
||||
PLATFORM_ASSERT(cache.empty());
|
||||
allInvalidated = false;
|
||||
cache.resize(length_);
|
||||
}
|
||||
|
||||
void LineLayoutCache::AllocateForLevel(int linesOnScreen, int linesInDoc) {
|
||||
PLATFORM_ASSERT(useCount == 0);
|
||||
size_t lengthForLevel = 0;
|
||||
if (level == llcCaret) {
|
||||
lengthForLevel = 1;
|
||||
} else if (level == llcPage) {
|
||||
lengthForLevel = linesOnScreen + 1;
|
||||
} else if (level == llcDocument) {
|
||||
lengthForLevel = linesInDoc;
|
||||
}
|
||||
if (lengthForLevel > cache.size()) {
|
||||
Deallocate();
|
||||
Allocate(lengthForLevel);
|
||||
} else {
|
||||
if (lengthForLevel < cache.size()) {
|
||||
for (size_t i = lengthForLevel; i < cache.size(); i++) {
|
||||
delete cache[i];
|
||||
cache[i] = 0;
|
||||
}
|
||||
}
|
||||
cache.resize(lengthForLevel);
|
||||
}
|
||||
PLATFORM_ASSERT(cache.size() == lengthForLevel);
|
||||
}
|
||||
|
||||
void LineLayoutCache::Deallocate() {
|
||||
PLATFORM_ASSERT(useCount == 0);
|
||||
for (size_t i = 0; i < cache.size(); i++)
|
||||
delete cache[i];
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
void LineLayoutCache::Invalidate(LineLayout::validLevel validity_) {
|
||||
if (!cache.empty() && !allInvalidated) {
|
||||
for (size_t i = 0; i < cache.size(); i++) {
|
||||
if (cache[i]) {
|
||||
cache[i]->Invalidate(validity_);
|
||||
}
|
||||
}
|
||||
if (validity_ == LineLayout::llInvalid) {
|
||||
allInvalidated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LineLayoutCache::SetLevel(int level_) {
|
||||
allInvalidated = false;
|
||||
if ((level_ != -1) && (level != level_)) {
|
||||
level = level_;
|
||||
Deallocate();
|
||||
}
|
||||
}
|
||||
|
||||
LineLayout *LineLayoutCache::Retrieve(int lineNumber, int lineCaret, int maxChars, int styleClock_,
|
||||
int linesOnScreen, int linesInDoc) {
|
||||
AllocateForLevel(linesOnScreen, linesInDoc);
|
||||
if (styleClock != styleClock_) {
|
||||
Invalidate(LineLayout::llCheckTextAndStyle);
|
||||
styleClock = styleClock_;
|
||||
}
|
||||
allInvalidated = false;
|
||||
int pos = -1;
|
||||
LineLayout *ret = 0;
|
||||
if (level == llcCaret) {
|
||||
pos = 0;
|
||||
} else if (level == llcPage) {
|
||||
if (lineNumber == lineCaret) {
|
||||
pos = 0;
|
||||
} else if (cache.size() > 1) {
|
||||
pos = 1 + (lineNumber % (cache.size() - 1));
|
||||
}
|
||||
} else if (level == llcDocument) {
|
||||
pos = lineNumber;
|
||||
}
|
||||
if (pos >= 0) {
|
||||
PLATFORM_ASSERT(useCount == 0);
|
||||
if (!cache.empty() && (pos < static_cast<int>(cache.size()))) {
|
||||
if (cache[pos]) {
|
||||
if ((cache[pos]->lineNumber != lineNumber) ||
|
||||
(cache[pos]->maxLineLength < maxChars)) {
|
||||
delete cache[pos];
|
||||
cache[pos] = 0;
|
||||
}
|
||||
}
|
||||
if (!cache[pos]) {
|
||||
cache[pos] = new LineLayout(maxChars);
|
||||
}
|
||||
cache[pos]->lineNumber = lineNumber;
|
||||
cache[pos]->inCache = true;
|
||||
ret = cache[pos];
|
||||
useCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
ret = new LineLayout(maxChars);
|
||||
ret->lineNumber = lineNumber;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LineLayoutCache::Dispose(LineLayout *ll) {
|
||||
allInvalidated = false;
|
||||
if (ll) {
|
||||
if (!ll->inCache) {
|
||||
delete ll;
|
||||
} else {
|
||||
useCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Simply pack the (maximum 4) character bytes into an int
|
||||
static inline int KeyFromString(const char *charBytes, size_t len) {
|
||||
PLATFORM_ASSERT(len <= 4);
|
||||
int k=0;
|
||||
for (size_t i=0; i<len && charBytes[i]; i++) {
|
||||
k = k * 0x100;
|
||||
k += static_cast<unsigned char>(charBytes[i]);
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
SpecialRepresentations::SpecialRepresentations() {
|
||||
std::fill(startByteHasReprs, startByteHasReprs+0x100, 0);
|
||||
}
|
||||
|
||||
void SpecialRepresentations::SetRepresentation(const char *charBytes, const char *value) {
|
||||
MapRepresentation::iterator it = mapReprs.find(KeyFromString(charBytes, UTF8MaxBytes));
|
||||
if (it == mapReprs.end()) {
|
||||
// New entry so increment for first byte
|
||||
startByteHasReprs[static_cast<unsigned char>(charBytes[0])]++;
|
||||
}
|
||||
mapReprs[KeyFromString(charBytes, UTF8MaxBytes)] = Representation(value);
|
||||
}
|
||||
|
||||
void SpecialRepresentations::ClearRepresentation(const char *charBytes) {
|
||||
MapRepresentation::iterator it = mapReprs.find(KeyFromString(charBytes, UTF8MaxBytes));
|
||||
if (it != mapReprs.end()) {
|
||||
mapReprs.erase(it);
|
||||
startByteHasReprs[static_cast<unsigned char>(charBytes[0])]--;
|
||||
}
|
||||
}
|
||||
|
||||
Representation *SpecialRepresentations::RepresentationFromCharacter(const char *charBytes, size_t len) {
|
||||
PLATFORM_ASSERT(len <= 4);
|
||||
if (!startByteHasReprs[static_cast<unsigned char>(charBytes[0])])
|
||||
return 0;
|
||||
MapRepresentation::iterator it = mapReprs.find(KeyFromString(charBytes, len));
|
||||
if (it != mapReprs.end()) {
|
||||
return &(it->second);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SpecialRepresentations::Contains(const char *charBytes, size_t len) const {
|
||||
PLATFORM_ASSERT(len <= 4);
|
||||
if (!startByteHasReprs[static_cast<unsigned char>(charBytes[0])])
|
||||
return false;
|
||||
MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes, len));
|
||||
return it != mapReprs.end();
|
||||
}
|
||||
|
||||
void SpecialRepresentations::Clear() {
|
||||
mapReprs.clear();
|
||||
std::fill(startByteHasReprs, startByteHasReprs+0x100, 0);
|
||||
}
|
||||
|
||||
void BreakFinder::Insert(int val) {
|
||||
if (val > nextBreak) {
|
||||
const std::vector<int>::iterator it = std::lower_bound(selAndEdge.begin(), selAndEdge.end(), val);
|
||||
if (it == selAndEdge.end()) {
|
||||
selAndEdge.push_back(val);
|
||||
} else if (*it != val) {
|
||||
selAndEdge.insert(it, 1, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_,
|
||||
int xStart, bool breakForSelection, Document *pdoc_, SpecialRepresentations *preprs_) :
|
||||
ll(ll_),
|
||||
lineStart(lineStart_),
|
||||
lineEnd(lineEnd_),
|
||||
posLineStart(posLineStart_),
|
||||
nextBreak(lineStart_),
|
||||
saeCurrentPos(0),
|
||||
saeNext(0),
|
||||
subBreak(-1),
|
||||
pdoc(pdoc_),
|
||||
encodingFamily(pdoc_->CodePageFamily()),
|
||||
preprs(preprs_) {
|
||||
|
||||
// Search for first visible break
|
||||
// First find the first visible character
|
||||
if (xStart > 0.0f)
|
||||
nextBreak = ll->FindBefore(static_cast<XYPOSITION>(xStart), lineStart, lineEnd);
|
||||
// Now back to a style break
|
||||
while ((nextBreak > lineStart) && (ll->styles[nextBreak] == ll->styles[nextBreak - 1])) {
|
||||
nextBreak--;
|
||||
}
|
||||
|
||||
if (breakForSelection) {
|
||||
SelectionPosition posStart(posLineStart);
|
||||
SelectionPosition posEnd(posLineStart + lineEnd);
|
||||
SelectionSegment segmentLine(posStart, posEnd);
|
||||
for (size_t r=0; r<ll->psel->Count(); r++) {
|
||||
SelectionSegment portion = ll->psel->Range(r).Intersect(segmentLine);
|
||||
if (!(portion.start == portion.end)) {
|
||||
if (portion.start.IsValid())
|
||||
Insert(portion.start.Position() - posLineStart);
|
||||
if (portion.end.IsValid())
|
||||
Insert(portion.end.Position() - posLineStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Insert(ll->edgeColumn);
|
||||
Insert(lineEnd);
|
||||
saeNext = (!selAndEdge.empty()) ? selAndEdge[0] : -1;
|
||||
}
|
||||
|
||||
BreakFinder::~BreakFinder() {
|
||||
}
|
||||
|
||||
TextSegment BreakFinder::Next() {
|
||||
if (subBreak == -1) {
|
||||
int prev = nextBreak;
|
||||
while (nextBreak < lineEnd) {
|
||||
int charWidth = 1;
|
||||
if (encodingFamily == efUnicode)
|
||||
charWidth = UTF8DrawBytes(reinterpret_cast<unsigned char *>(ll->chars) + nextBreak, lineEnd - nextBreak);
|
||||
else if (encodingFamily == efDBCS)
|
||||
charWidth = pdoc->IsDBCSLeadByte(ll->chars[nextBreak]) ? 2 : 1;
|
||||
Representation *repr = preprs->RepresentationFromCharacter(ll->chars + nextBreak, charWidth);
|
||||
if (((nextBreak > 0) && (ll->styles[nextBreak] != ll->styles[nextBreak - 1])) ||
|
||||
repr ||
|
||||
(nextBreak == saeNext)) {
|
||||
while ((nextBreak >= saeNext) && (saeNext < lineEnd)) {
|
||||
saeCurrentPos++;
|
||||
saeNext = (saeCurrentPos < selAndEdge.size()) ? selAndEdge[saeCurrentPos] : lineEnd;
|
||||
}
|
||||
if ((nextBreak > prev) || repr) {
|
||||
// Have a segment to report
|
||||
if (nextBreak == prev) {
|
||||
nextBreak += charWidth;
|
||||
} else {
|
||||
repr = 0; // Optimize -> should remember repr
|
||||
}
|
||||
if ((nextBreak - prev) < lengthStartSubdivision) {
|
||||
return TextSegment(prev, nextBreak - prev, repr);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
nextBreak += charWidth;
|
||||
}
|
||||
if ((nextBreak - prev) < lengthStartSubdivision) {
|
||||
return TextSegment(prev, nextBreak - prev);
|
||||
}
|
||||
subBreak = prev;
|
||||
}
|
||||
// Splitting up a long run from prev to nextBreak in lots of approximately lengthEachSubdivision.
|
||||
// For very long runs add extra breaks after spaces or if no spaces before low punctuation.
|
||||
int startSegment = subBreak;
|
||||
if ((nextBreak - subBreak) <= lengthEachSubdivision) {
|
||||
subBreak = -1;
|
||||
return TextSegment(startSegment, nextBreak - startSegment);
|
||||
} else {
|
||||
subBreak += pdoc->SafeSegment(ll->chars + subBreak, nextBreak-subBreak, lengthEachSubdivision);
|
||||
if (subBreak >= nextBreak) {
|
||||
subBreak = -1;
|
||||
return TextSegment(startSegment, nextBreak - startSegment);
|
||||
} else {
|
||||
return TextSegment(startSegment, subBreak - startSegment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BreakFinder::More() const {
|
||||
return (subBreak >= 0) || (nextBreak < lineEnd);
|
||||
}
|
||||
|
||||
PositionCacheEntry::PositionCacheEntry() :
|
||||
styleNumber(0), len(0), clock(0), positions(0) {
|
||||
}
|
||||
|
||||
void PositionCacheEntry::Set(unsigned int styleNumber_, const char *s_,
|
||||
unsigned int len_, XYPOSITION *positions_, unsigned int clock_) {
|
||||
Clear();
|
||||
styleNumber = styleNumber_;
|
||||
len = len_;
|
||||
clock = clock_;
|
||||
if (s_ && positions_) {
|
||||
positions = new XYPOSITION[len + (len / 4) + 1];
|
||||
for (unsigned int i=0; i<len; i++) {
|
||||
positions[i] = positions_[i];
|
||||
}
|
||||
memcpy(reinterpret_cast<char *>(positions + len), s_, len);
|
||||
}
|
||||
}
|
||||
|
||||
PositionCacheEntry::~PositionCacheEntry() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void PositionCacheEntry::Clear() {
|
||||
delete []positions;
|
||||
positions = 0;
|
||||
styleNumber = 0;
|
||||
len = 0;
|
||||
clock = 0;
|
||||
}
|
||||
|
||||
bool PositionCacheEntry::Retrieve(unsigned int styleNumber_, const char *s_,
|
||||
unsigned int len_, XYPOSITION *positions_) const {
|
||||
if ((styleNumber == styleNumber_) && (len == len_) &&
|
||||
(memcmp(reinterpret_cast<char *>(positions + len), s_, len)== 0)) {
|
||||
for (unsigned int i=0; i<len; i++) {
|
||||
positions_[i] = positions[i];
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int PositionCacheEntry::Hash(unsigned int styleNumber_, const char *s, unsigned int len_) {
|
||||
unsigned int ret = s[0] << 7;
|
||||
for (unsigned int i=0; i<len_; i++) {
|
||||
ret *= 1000003;
|
||||
ret ^= s[i];
|
||||
}
|
||||
ret *= 1000003;
|
||||
ret ^= len_;
|
||||
ret *= 1000003;
|
||||
ret ^= styleNumber_;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool PositionCacheEntry::NewerThan(const PositionCacheEntry &other) const {
|
||||
return clock > other.clock;
|
||||
}
|
||||
|
||||
void PositionCacheEntry::ResetClock() {
|
||||
if (clock > 0) {
|
||||
clock = 1;
|
||||
}
|
||||
}
|
||||
|
||||
PositionCache::PositionCache() {
|
||||
clock = 1;
|
||||
pces.resize(0x400);
|
||||
allClear = true;
|
||||
}
|
||||
|
||||
PositionCache::~PositionCache() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void PositionCache::Clear() {
|
||||
if (!allClear) {
|
||||
for (size_t i=0; i<pces.size(); i++) {
|
||||
pces[i].Clear();
|
||||
}
|
||||
}
|
||||
clock = 1;
|
||||
allClear = true;
|
||||
}
|
||||
|
||||
void PositionCache::SetSize(size_t size_) {
|
||||
Clear();
|
||||
pces.resize(size_);
|
||||
}
|
||||
|
||||
void PositionCache::MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber,
|
||||
const char *s, unsigned int len, XYPOSITION *positions, Document *pdoc) {
|
||||
|
||||
allClear = false;
|
||||
size_t probe = pces.size(); // Out of bounds
|
||||
if ((!pces.empty()) && (len < 30)) {
|
||||
// Only store short strings in the cache so it doesn't churn with
|
||||
// long comments with only a single comment.
|
||||
|
||||
// Two way associative: try two probe positions.
|
||||
unsigned int hashValue = PositionCacheEntry::Hash(styleNumber, s, len);
|
||||
probe = hashValue % pces.size();
|
||||
if (pces[probe].Retrieve(styleNumber, s, len, positions)) {
|
||||
return;
|
||||
}
|
||||
unsigned int probe2 = (hashValue * 37) % pces.size();
|
||||
if (pces[probe2].Retrieve(styleNumber, s, len, positions)) {
|
||||
return;
|
||||
}
|
||||
// Not found. Choose the oldest of the two slots to replace
|
||||
if (pces[probe].NewerThan(pces[probe2])) {
|
||||
probe = probe2;
|
||||
}
|
||||
}
|
||||
if (len > BreakFinder::lengthStartSubdivision) {
|
||||
// Break up into segments
|
||||
unsigned int startSegment = 0;
|
||||
XYPOSITION xStartSegment = 0;
|
||||
while (startSegment < len) {
|
||||
unsigned int lenSegment = pdoc->SafeSegment(s + startSegment, len - startSegment, BreakFinder::lengthEachSubdivision);
|
||||
surface->MeasureWidths(vstyle.styles[styleNumber].font, s + startSegment, lenSegment, positions + startSegment);
|
||||
for (unsigned int inSeg = 0; inSeg < lenSegment; inSeg++) {
|
||||
positions[startSegment + inSeg] += xStartSegment;
|
||||
}
|
||||
xStartSegment = positions[startSegment + lenSegment - 1];
|
||||
startSegment += lenSegment;
|
||||
}
|
||||
} else {
|
||||
surface->MeasureWidths(vstyle.styles[styleNumber].font, s, len, positions);
|
||||
}
|
||||
if (probe < pces.size()) {
|
||||
// Store into cache
|
||||
clock++;
|
||||
if (clock > 60000) {
|
||||
// Since there are only 16 bits for the clock, wrap it round and
|
||||
// reset all cache entries so none get stuck with a high clock.
|
||||
for (size_t i=0; i<pces.size(); i++) {
|
||||
pces[i].ResetClock();
|
||||
}
|
||||
clock = 2;
|
||||
}
|
||||
pces[probe].Set(styleNumber, s, len, positions, clock);
|
||||
}
|
||||
}
|
||||
215
third-party/scintilla/PositionCache.h
vendored
Normal file
215
third-party/scintilla/PositionCache.h
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file PositionCache.h
|
||||
** Classes for caching layout information.
|
||||
**/
|
||||
// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef POSITIONCACHE_H
|
||||
#define POSITIONCACHE_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
static inline bool IsEOLChar(char ch) {
|
||||
return (ch == '\r') || (ch == '\n');
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
class LineLayout {
|
||||
private:
|
||||
friend class LineLayoutCache;
|
||||
int *lineStarts;
|
||||
int lenLineStarts;
|
||||
/// Drawing is only performed for @a maxLineLength characters on each line.
|
||||
int lineNumber;
|
||||
bool inCache;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
LineLayout(const LineLayout &);
|
||||
LineLayout &operator =(const LineLayout &);
|
||||
|
||||
public:
|
||||
enum { wrapWidthInfinite = 0x7ffffff };
|
||||
int maxLineLength;
|
||||
int numCharsInLine;
|
||||
int numCharsBeforeEOL;
|
||||
enum validLevel { llInvalid, llCheckTextAndStyle, llPositions, llLines } validity;
|
||||
int xHighlightGuide;
|
||||
bool highlightColumn;
|
||||
Selection *psel;
|
||||
bool containsCaret;
|
||||
int edgeColumn;
|
||||
char *chars;
|
||||
unsigned char *styles;
|
||||
int styleBitsSet;
|
||||
char *indicators;
|
||||
XYPOSITION *positions;
|
||||
char bracePreviousStyles[2];
|
||||
|
||||
// Hotspot support
|
||||
int hsStart;
|
||||
int hsEnd;
|
||||
|
||||
// Wrapped line support
|
||||
int widthLine;
|
||||
int lines;
|
||||
XYPOSITION wrapIndent; // In pixels
|
||||
|
||||
explicit LineLayout(int maxLineLength_);
|
||||
virtual ~LineLayout();
|
||||
void Resize(int maxLineLength_);
|
||||
void Free();
|
||||
void Invalidate(validLevel validity_);
|
||||
int LineStart(int line) const;
|
||||
int LineLastVisible(int line) const;
|
||||
Range SubLineRange(int line) const;
|
||||
bool InLine(int offset, int line) const;
|
||||
void SetLineStart(int line, int start);
|
||||
void SetBracesHighlight(Range rangeLine, Position braces[],
|
||||
char bracesMatchStyle, int xHighlight, bool ignoreStyle);
|
||||
void RestoreBracesHighlight(Range rangeLine, Position braces[], bool ignoreStyle);
|
||||
int FindBefore(XYPOSITION x, int lower, int upper) const;
|
||||
int FindPositionFromX(XYPOSITION x, Range range, bool charPosition) const;
|
||||
Point PointFromPosition(int posInLine, int lineHeight) const;
|
||||
int EndLineStyle() const;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class LineLayoutCache {
|
||||
int level;
|
||||
std::vector<LineLayout *>cache;
|
||||
bool allInvalidated;
|
||||
int styleClock;
|
||||
int useCount;
|
||||
void Allocate(size_t length_);
|
||||
void AllocateForLevel(int linesOnScreen, int linesInDoc);
|
||||
public:
|
||||
LineLayoutCache();
|
||||
virtual ~LineLayoutCache();
|
||||
void Deallocate();
|
||||
enum {
|
||||
llcNone=SC_CACHE_NONE,
|
||||
llcCaret=SC_CACHE_CARET,
|
||||
llcPage=SC_CACHE_PAGE,
|
||||
llcDocument=SC_CACHE_DOCUMENT
|
||||
};
|
||||
void Invalidate(LineLayout::validLevel validity_);
|
||||
void SetLevel(int level_);
|
||||
int GetLevel() const { return level; }
|
||||
LineLayout *Retrieve(int lineNumber, int lineCaret, int maxChars, int styleClock_,
|
||||
int linesOnScreen, int linesInDoc);
|
||||
void Dispose(LineLayout *ll);
|
||||
};
|
||||
|
||||
class PositionCacheEntry {
|
||||
unsigned int styleNumber:8;
|
||||
unsigned int len:8;
|
||||
unsigned int clock:16;
|
||||
XYPOSITION *positions;
|
||||
public:
|
||||
PositionCacheEntry();
|
||||
~PositionCacheEntry();
|
||||
void Set(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_, unsigned int clock);
|
||||
void Clear();
|
||||
bool Retrieve(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_) const;
|
||||
static unsigned int Hash(unsigned int styleNumber_, const char *s, unsigned int len);
|
||||
bool NewerThan(const PositionCacheEntry &other) const;
|
||||
void ResetClock();
|
||||
};
|
||||
|
||||
class Representation {
|
||||
public:
|
||||
std::string stringRep;
|
||||
explicit Representation(const char *value="") : stringRep(value) {
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::map<int, Representation> MapRepresentation;
|
||||
|
||||
class SpecialRepresentations {
|
||||
MapRepresentation mapReprs;
|
||||
short startByteHasReprs[0x100];
|
||||
public:
|
||||
SpecialRepresentations();
|
||||
void SetRepresentation(const char *charBytes, const char *value);
|
||||
void ClearRepresentation(const char *charBytes);
|
||||
Representation *RepresentationFromCharacter(const char *charBytes, size_t len);
|
||||
bool Contains(const char *charBytes, size_t len) const;
|
||||
void Clear();
|
||||
};
|
||||
|
||||
struct TextSegment {
|
||||
int start;
|
||||
int length;
|
||||
Representation *representation;
|
||||
TextSegment(int start_=0, int length_=0, Representation *representation_=0) :
|
||||
start(start_), length(length_), representation(representation_) {
|
||||
}
|
||||
int end() const {
|
||||
return start + length;
|
||||
}
|
||||
};
|
||||
|
||||
// Class to break a line of text into shorter runs at sensible places.
|
||||
class BreakFinder {
|
||||
LineLayout *ll;
|
||||
int lineStart;
|
||||
int lineEnd;
|
||||
int posLineStart;
|
||||
int nextBreak;
|
||||
std::vector<int> selAndEdge;
|
||||
unsigned int saeCurrentPos;
|
||||
int saeNext;
|
||||
int subBreak;
|
||||
Document *pdoc;
|
||||
EncodingFamily encodingFamily;
|
||||
SpecialRepresentations *preprs;
|
||||
void Insert(int val);
|
||||
|
||||
// no copy ctr or assignment op
|
||||
BreakFinder(const BreakFinder &);
|
||||
BreakFinder &operator =(const BreakFinder &);
|
||||
public:
|
||||
// If a whole run is longer than lengthStartSubdivision then subdivide
|
||||
// into smaller runs at spaces or punctuation.
|
||||
enum { lengthStartSubdivision = 300 };
|
||||
// Try to make each subdivided run lengthEachSubdivision or shorter.
|
||||
enum { lengthEachSubdivision = 100 };
|
||||
BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_,
|
||||
int xStart, bool breakForSelection, Document *pdoc_, SpecialRepresentations *preprs_);
|
||||
~BreakFinder();
|
||||
TextSegment Next();
|
||||
bool More() const;
|
||||
};
|
||||
|
||||
class PositionCache {
|
||||
std::vector<PositionCacheEntry> pces;
|
||||
unsigned int clock;
|
||||
bool allClear;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
PositionCache(const PositionCache &);
|
||||
PositionCache &operator =(const PositionCache &);
|
||||
public:
|
||||
PositionCache();
|
||||
~PositionCache();
|
||||
void Clear();
|
||||
void SetSize(size_t size_);
|
||||
size_t GetSize() const { return pces.size(); }
|
||||
void MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber,
|
||||
const char *s, unsigned int len, XYPOSITION *positions, Document *pdoc);
|
||||
};
|
||||
|
||||
inline bool IsSpaceOrTab(int ch) {
|
||||
return ch == ' ' || ch == '\t';
|
||||
}
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
154
third-party/scintilla/PropSetSimple.cxx
vendored
Normal file
154
third-party/scintilla/PropSetSimple.cxx
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
// SciTE - Scintilla based Text Editor
|
||||
/** @file PropSetSimple.cxx
|
||||
** A Java style properties file module.
|
||||
**/
|
||||
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
// Maintain a dictionary of properties
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Visual C++ doesn't like unreachable code in its own headers.
|
||||
#pragma warning(disable: 4018 4100 4245 4511 4512 4663 4702)
|
||||
#endif
|
||||
|
||||
#include "PropSetSimple.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
typedef std::map<std::string, std::string> mapss;
|
||||
|
||||
PropSetSimple::PropSetSimple() {
|
||||
mapss *props = new mapss;
|
||||
impl = static_cast<void *>(props);
|
||||
}
|
||||
|
||||
PropSetSimple::~PropSetSimple() {
|
||||
mapss *props = static_cast<mapss *>(impl);
|
||||
delete props;
|
||||
impl = 0;
|
||||
}
|
||||
|
||||
void PropSetSimple::Set(const char *key, const char *val, int lenKey, int lenVal) {
|
||||
mapss *props = static_cast<mapss *>(impl);
|
||||
if (!*key) // Empty keys are not supported
|
||||
return;
|
||||
if (lenKey == -1)
|
||||
lenKey = static_cast<int>(strlen(key));
|
||||
if (lenVal == -1)
|
||||
lenVal = static_cast<int>(strlen(val));
|
||||
(*props)[std::string(key, lenKey)] = std::string(val, lenVal);
|
||||
}
|
||||
|
||||
static bool IsASpaceCharacter(unsigned int ch) {
|
||||
return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
|
||||
}
|
||||
|
||||
void PropSetSimple::Set(const char *keyVal) {
|
||||
while (IsASpaceCharacter(*keyVal))
|
||||
keyVal++;
|
||||
const char *endVal = keyVal;
|
||||
while (*endVal && (*endVal != '\n'))
|
||||
endVal++;
|
||||
const char *eqAt = strchr(keyVal, '=');
|
||||
if (eqAt) {
|
||||
Set(keyVal, eqAt + 1, static_cast<int>(eqAt-keyVal),
|
||||
static_cast<int>(endVal - eqAt - 1));
|
||||
} else if (*keyVal) { // No '=' so assume '=1'
|
||||
Set(keyVal, "1", static_cast<int>(endVal-keyVal), 1);
|
||||
}
|
||||
}
|
||||
|
||||
void PropSetSimple::SetMultiple(const char *s) {
|
||||
const char *eol = strchr(s, '\n');
|
||||
while (eol) {
|
||||
Set(s);
|
||||
s = eol + 1;
|
||||
eol = strchr(s, '\n');
|
||||
}
|
||||
Set(s);
|
||||
}
|
||||
|
||||
const char *PropSetSimple::Get(const char *key) const {
|
||||
mapss *props = static_cast<mapss *>(impl);
|
||||
mapss::const_iterator keyPos = props->find(std::string(key));
|
||||
if (keyPos != props->end()) {
|
||||
return keyPos->second.c_str();
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// There is some inconsistency between GetExpanded("foo") and Expand("$(foo)").
|
||||
// A solution is to keep a stack of variables that have been expanded, so that
|
||||
// recursive expansions can be skipped. For now I'll just use the C++ stack
|
||||
// for that, through a recursive function and a simple chain of pointers.
|
||||
|
||||
struct VarChain {
|
||||
VarChain(const char *var_=NULL, const VarChain *link_=NULL): var(var_), link(link_) {}
|
||||
|
||||
bool contains(const char *testVar) const {
|
||||
return (var && (0 == strcmp(var, testVar)))
|
||||
|| (link && link->contains(testVar));
|
||||
}
|
||||
|
||||
const char *var;
|
||||
const VarChain *link;
|
||||
};
|
||||
|
||||
static int ExpandAllInPlace(const PropSetSimple &props, std::string &withVars, int maxExpands, const VarChain &blankVars) {
|
||||
size_t varStart = withVars.find("$(");
|
||||
while ((varStart != std::string::npos) && (maxExpands > 0)) {
|
||||
size_t varEnd = withVars.find(')', varStart+2);
|
||||
if (varEnd == std::string::npos) {
|
||||
break;
|
||||
}
|
||||
|
||||
// For consistency, when we see '$(ab$(cde))', expand the inner variable first,
|
||||
// regardless whether there is actually a degenerate variable named 'ab$(cde'.
|
||||
size_t innerVarStart = withVars.find("$(", varStart+2);
|
||||
while ((innerVarStart != std::string::npos) && (innerVarStart > varStart) && (innerVarStart < varEnd)) {
|
||||
varStart = innerVarStart;
|
||||
innerVarStart = withVars.find("$(", varStart+2);
|
||||
}
|
||||
|
||||
std::string var(withVars.c_str(), varStart + 2, varEnd - varStart - 2);
|
||||
std::string val = props.Get(var.c_str());
|
||||
|
||||
if (blankVars.contains(var.c_str())) {
|
||||
val = ""; // treat blankVar as an empty string (e.g. to block self-reference)
|
||||
}
|
||||
|
||||
if (--maxExpands >= 0) {
|
||||
maxExpands = ExpandAllInPlace(props, val, maxExpands, VarChain(var.c_str(), &blankVars));
|
||||
}
|
||||
|
||||
withVars.erase(varStart, varEnd-varStart+1);
|
||||
withVars.insert(varStart, val.c_str(), val.length());
|
||||
|
||||
varStart = withVars.find("$(");
|
||||
}
|
||||
|
||||
return maxExpands;
|
||||
}
|
||||
|
||||
int PropSetSimple::GetExpanded(const char *key, char *result) const {
|
||||
std::string val = Get(key);
|
||||
ExpandAllInPlace(*this, val, 100, VarChain(key));
|
||||
const int n = static_cast<int>(val.size());
|
||||
if (result) {
|
||||
memcpy(result, val.c_str(), n+1);
|
||||
}
|
||||
return n; // Not including NUL
|
||||
}
|
||||
|
||||
int PropSetSimple::GetInt(const char *key, int defaultValue) const {
|
||||
std::string val = Get(key);
|
||||
ExpandAllInPlace(*this, val, 100, VarChain(key));
|
||||
if (!val.empty()) {
|
||||
return atoi(val.c_str());
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
37
third-party/scintilla/PropSetSimple.h
vendored
Normal file
37
third-party/scintilla/PropSetSimple.h
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file PropSetSimple.h
|
||||
** A basic string to string map.
|
||||
**/
|
||||
// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef PROPSETSIMPLE_H
|
||||
#define PROPSETSIMPLE_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
class PropSetSimple {
|
||||
void *impl;
|
||||
void Set(const char *keyVal);
|
||||
|
||||
// no copy ctr or assignment op
|
||||
PropSetSimple(const PropSetSimple &);
|
||||
PropSetSimple &operator =(const PropSetSimple &);
|
||||
|
||||
public:
|
||||
PropSetSimple();
|
||||
virtual ~PropSetSimple();
|
||||
void Set(const char *key, const char *val, int lenKey=-1, int lenVal=-1);
|
||||
void SetMultiple(const char *);
|
||||
const char *Get(const char *key) const;
|
||||
int GetExpanded(const char *key, char *result) const;
|
||||
int GetInt(const char *key, int defaultValue=0) const;
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
957
third-party/scintilla/RESearch.cxx
vendored
Normal file
957
third-party/scintilla/RESearch.cxx
vendored
Normal file
@@ -0,0 +1,957 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file RESearch.cxx
|
||||
** Regular expression search library.
|
||||
**/
|
||||
|
||||
/*
|
||||
* regex - Regular expression pattern matching and replacement
|
||||
*
|
||||
* By: Ozan S. Yigit (oz)
|
||||
* Dept. of Computer Science
|
||||
* York University
|
||||
*
|
||||
* Original code available from http://www.cs.yorku.ca/~oz/
|
||||
* Translation to C++ by Neil Hodgson neilh@scintilla.org
|
||||
* Removed all use of register.
|
||||
* Converted to modern function prototypes.
|
||||
* Put all global/static variables into an object so this code can be
|
||||
* used from multiple threads, etc.
|
||||
* Some extensions by Philippe Lhoste PhiLho(a)GMX.net
|
||||
* '?' extensions by Michael Mullin masmullin@gmail.com
|
||||
*
|
||||
* These routines are the PUBLIC DOMAIN equivalents of regex
|
||||
* routines as found in 4.nBSD UN*X, with minor extensions.
|
||||
*
|
||||
* These routines are derived from various implementations found
|
||||
* in software tools books, and Conroy's grep. They are NOT derived
|
||||
* from licensed/restricted software.
|
||||
* For more interesting/academic/complicated implementations,
|
||||
* see Henry Spencer's regexp routines, or GNU Emacs pattern
|
||||
* matching module.
|
||||
*
|
||||
* Modification history removed.
|
||||
*
|
||||
* Interfaces:
|
||||
* RESearch::Compile: compile a regular expression into a NFA.
|
||||
*
|
||||
* const char *RESearch::Compile(const char *pattern, int length,
|
||||
* bool caseSensitive, bool posix)
|
||||
*
|
||||
* Returns a short error string if they fail.
|
||||
*
|
||||
* RESearch::Execute: execute the NFA to match a pattern.
|
||||
*
|
||||
* int RESearch::Execute(characterIndexer &ci, int lp, int endp)
|
||||
*
|
||||
* re_fail: failure routine for RESearch::Execute. (no longer used)
|
||||
*
|
||||
* void re_fail(char *msg, char op)
|
||||
*
|
||||
* Regular Expressions:
|
||||
*
|
||||
* [1] char matches itself, unless it is a special
|
||||
* character (metachar): . \ [ ] * + ? ^ $
|
||||
* and ( ) if posix option.
|
||||
*
|
||||
* [2] . matches any character.
|
||||
*
|
||||
* [3] \ matches the character following it, except:
|
||||
* - \a, \b, \f, \n, \r, \t, \v match the corresponding C
|
||||
* escape char, respectively BEL, BS, FF, LF, CR, TAB and VT;
|
||||
* Note that \r and \n are never matched because Scintilla
|
||||
* regex searches are made line per line
|
||||
* (stripped of end-of-line chars).
|
||||
* - if not in posix mode, when followed by a
|
||||
* left or right round bracket (see [8]);
|
||||
* - when followed by a digit 1 to 9 (see [9]);
|
||||
* - when followed by a left or right angle bracket
|
||||
* (see [10]);
|
||||
* - when followed by d, D, s, S, w or W (see [11]);
|
||||
* - when followed by x and two hexa digits (see [12].
|
||||
* Backslash is used as an escape character for all
|
||||
* other meta-characters, and itself.
|
||||
*
|
||||
* [4] [set] matches one of the characters in the set.
|
||||
* If the first character in the set is "^",
|
||||
* it matches the characters NOT in the set, i.e.
|
||||
* complements the set. A shorthand S-E (start dash end)
|
||||
* is used to specify a set of characters S up to
|
||||
* E, inclusive. S and E must be characters, otherwise
|
||||
* the dash is taken literally (eg. in expression [\d-a]).
|
||||
* The special characters "]" and "-" have no special
|
||||
* meaning if they appear as the first chars in the set.
|
||||
* To include both, put - first: [-]A-Z]
|
||||
* (or just backslash them).
|
||||
* examples: match:
|
||||
*
|
||||
* [-]|] matches these 3 chars,
|
||||
*
|
||||
* []-|] matches from ] to | chars
|
||||
*
|
||||
* [a-z] any lowercase alpha
|
||||
*
|
||||
* [^-]] any char except - and ]
|
||||
*
|
||||
* [^A-Z] any char except uppercase
|
||||
* alpha
|
||||
*
|
||||
* [a-zA-Z] any alpha
|
||||
*
|
||||
* [5] * any regular expression form [1] to [4]
|
||||
* (except [8], [9] and [10] forms of [3]),
|
||||
* followed by closure char (*)
|
||||
* matches zero or more matches of that form.
|
||||
*
|
||||
* [6] + same as [5], except it matches one or more.
|
||||
*
|
||||
* [5-6] Both [5] and [6] are greedy (they match as much as possible).
|
||||
* Unless they are followed by the 'lazy' quantifier (?)
|
||||
* In which case both [5] and [6] try to match as little as possible
|
||||
*
|
||||
* [7] ? same as [5] except it matches zero or one.
|
||||
*
|
||||
* [8] a regular expression in the form [1] to [13], enclosed
|
||||
* as \(form\) (or (form) with posix flag) matches what
|
||||
* form matches. The enclosure creates a set of tags,
|
||||
* used for [9] and for pattern substitution.
|
||||
* The tagged forms are numbered starting from 1.
|
||||
*
|
||||
* [9] a \ followed by a digit 1 to 9 matches whatever a
|
||||
* previously tagged regular expression ([8]) matched.
|
||||
*
|
||||
* [10] \< a regular expression starting with a \< construct
|
||||
* \> and/or ending with a \> construct, restricts the
|
||||
* pattern matching to the beginning of a word, and/or
|
||||
* the end of a word. A word is defined to be a character
|
||||
* string beginning and/or ending with the characters
|
||||
* A-Z a-z 0-9 and _. Scintilla extends this definition
|
||||
* by user setting. The word must also be preceded and/or
|
||||
* followed by any character outside those mentioned.
|
||||
*
|
||||
* [11] \l a backslash followed by d, D, s, S, w or W,
|
||||
* becomes a character class (both inside and
|
||||
* outside sets []).
|
||||
* d: decimal digits
|
||||
* D: any char except decimal digits
|
||||
* s: whitespace (space, \t \n \r \f \v)
|
||||
* S: any char except whitespace (see above)
|
||||
* w: alphanumeric & underscore (changed by user setting)
|
||||
* W: any char except alphanumeric & underscore (see above)
|
||||
*
|
||||
* [12] \xHH a backslash followed by x and two hexa digits,
|
||||
* becomes the character whose Ascii code is equal
|
||||
* to these digits. If not followed by two digits,
|
||||
* it is 'x' char itself.
|
||||
*
|
||||
* [13] a composite regular expression xy where x and y
|
||||
* are in the form [1] to [12] matches the longest
|
||||
* match of x followed by a match for y.
|
||||
*
|
||||
* [14] ^ a regular expression starting with a ^ character
|
||||
* $ and/or ending with a $ character, restricts the
|
||||
* pattern matching to the beginning of the line,
|
||||
* or the end of line. [anchors] Elsewhere in the
|
||||
* pattern, ^ and $ are treated as ordinary characters.
|
||||
*
|
||||
*
|
||||
* Acknowledgements:
|
||||
*
|
||||
* HCR's Hugh Redelmeier has been most helpful in various
|
||||
* stages of development. He convinced me to include BOW
|
||||
* and EOW constructs, originally invented by Rob Pike at
|
||||
* the University of Toronto.
|
||||
*
|
||||
* References:
|
||||
* Software tools Kernighan & Plauger
|
||||
* Software tools in Pascal Kernighan & Plauger
|
||||
* Grep [rsx-11 C dist] David Conroy
|
||||
* ed - text editor Un*x Programmer's Manual
|
||||
* Advanced editing on Un*x B. W. Kernighan
|
||||
* RegExp routines Henry Spencer
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* This implementation uses a bit-set representation for character
|
||||
* classes for speed and compactness. Each character is represented
|
||||
* by one bit in a 256-bit block. Thus, CCL always takes a
|
||||
* constant 32 bytes in the internal nfa, and RESearch::Execute does a single
|
||||
* bit comparison to locate the character in the set.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* pattern: foo*.*
|
||||
* compile: CHR f CHR o CLO CHR o END CLO ANY END END
|
||||
* matches: fo foo fooo foobar fobar foxx ...
|
||||
*
|
||||
* pattern: fo[ob]a[rz]
|
||||
* compile: CHR f CHR o CCL bitset CHR a CCL bitset END
|
||||
* matches: fobar fooar fobaz fooaz
|
||||
*
|
||||
* pattern: foo\\+
|
||||
* compile: CHR f CHR o CHR o CHR \ CLO CHR \ END END
|
||||
* matches: foo\ foo\\ foo\\\ ...
|
||||
*
|
||||
* pattern: \(foo\)[1-3]\1 (same as foo[1-3]foo)
|
||||
* compile: BOT 1 CHR f CHR o CHR o EOT 1 CCL bitset REF 1 END
|
||||
* matches: foo1foo foo2foo foo3foo
|
||||
*
|
||||
* pattern: \(fo.*\)-\1
|
||||
* compile: BOT 1 CHR f CHR o CLO ANY END EOT 1 CHR - REF 1 END
|
||||
* matches: foo-foo fo-fo fob-fob foobar-foobar ...
|
||||
*/
|
||||
|
||||
#include "CharClassify.h"
|
||||
#include "RESearch.h"
|
||||
|
||||
// Shut up annoying Visual C++ warnings:
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4514)
|
||||
#endif
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
#define OKP 1
|
||||
#define NOP 0
|
||||
|
||||
#define CHR 1
|
||||
#define ANY 2
|
||||
#define CCL 3
|
||||
#define BOL 4
|
||||
#define EOL 5
|
||||
#define BOT 6
|
||||
#define EOT 7
|
||||
#define BOW 8
|
||||
#define EOW 9
|
||||
#define REF 10
|
||||
#define CLO 11
|
||||
#define CLQ 12 /* 0 to 1 closure */
|
||||
#define LCLO 13 /* lazy closure */
|
||||
|
||||
#define END 0
|
||||
|
||||
/*
|
||||
* The following defines are not meant to be changeable.
|
||||
* They are for readability only.
|
||||
*/
|
||||
#define BLKIND 0370
|
||||
#define BITIND 07
|
||||
|
||||
const char bitarr[] = { 1, 2, 4, 8, 16, 32, 64, char(128) };
|
||||
|
||||
#define badpat(x) (*nfa = END, x)
|
||||
|
||||
/*
|
||||
* Character classification table for word boundary operators BOW
|
||||
* and EOW is passed in by the creator of this object (Scintilla
|
||||
* Document). The Document default state is that word chars are:
|
||||
* 0-9, a-z, A-Z and _
|
||||
*/
|
||||
|
||||
RESearch::RESearch(CharClassify *charClassTable) {
|
||||
failure = 0;
|
||||
charClass = charClassTable;
|
||||
Init();
|
||||
}
|
||||
|
||||
RESearch::~RESearch() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void RESearch::Init() {
|
||||
sta = NOP; /* status of lastpat */
|
||||
bol = 0;
|
||||
for (int i = 0; i < MAXTAG; i++)
|
||||
pat[i].clear();
|
||||
for (int j = 0; j < BITBLK; j++)
|
||||
bittab[j] = 0;
|
||||
}
|
||||
|
||||
void RESearch::Clear() {
|
||||
for (int i = 0; i < MAXTAG; i++) {
|
||||
pat[i].clear();
|
||||
bopat[i] = NOTFOUND;
|
||||
eopat[i] = NOTFOUND;
|
||||
}
|
||||
}
|
||||
|
||||
void RESearch::GrabMatches(CharacterIndexer &ci) {
|
||||
for (unsigned int i = 0; i < MAXTAG; i++) {
|
||||
if ((bopat[i] != NOTFOUND) && (eopat[i] != NOTFOUND)) {
|
||||
unsigned int len = eopat[i] - bopat[i];
|
||||
pat[i] = std::string(len+1, '\0');
|
||||
for (unsigned int j = 0; j < len; j++)
|
||||
pat[i][j] = ci.CharAt(bopat[i] + j);
|
||||
pat[i][len] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RESearch::ChSet(unsigned char c) {
|
||||
bittab[((c) & BLKIND) >> 3] |= bitarr[(c) & BITIND];
|
||||
}
|
||||
|
||||
void RESearch::ChSetWithCase(unsigned char c, bool caseSensitive) {
|
||||
if (caseSensitive) {
|
||||
ChSet(c);
|
||||
} else {
|
||||
if ((c >= 'a') && (c <= 'z')) {
|
||||
ChSet(c);
|
||||
ChSet(static_cast<unsigned char>(c - 'a' + 'A'));
|
||||
} else if ((c >= 'A') && (c <= 'Z')) {
|
||||
ChSet(c);
|
||||
ChSet(static_cast<unsigned char>(c - 'A' + 'a'));
|
||||
} else {
|
||||
ChSet(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char escapeValue(unsigned char ch) {
|
||||
switch (ch) {
|
||||
case 'a': return '\a';
|
||||
case 'b': return '\b';
|
||||
case 'f': return '\f';
|
||||
case 'n': return '\n';
|
||||
case 'r': return '\r';
|
||||
case 't': return '\t';
|
||||
case 'v': return '\v';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int GetHexaChar(unsigned char hd1, unsigned char hd2) {
|
||||
int hexValue = 0;
|
||||
if (hd1 >= '0' && hd1 <= '9') {
|
||||
hexValue += 16 * (hd1 - '0');
|
||||
} else if (hd1 >= 'A' && hd1 <= 'F') {
|
||||
hexValue += 16 * (hd1 - 'A' + 10);
|
||||
} else if (hd1 >= 'a' && hd1 <= 'f') {
|
||||
hexValue += 16 * (hd1 - 'a' + 10);
|
||||
} else
|
||||
return -1;
|
||||
if (hd2 >= '0' && hd2 <= '9') {
|
||||
hexValue += hd2 - '0';
|
||||
} else if (hd2 >= 'A' && hd2 <= 'F') {
|
||||
hexValue += hd2 - 'A' + 10;
|
||||
} else if (hd2 >= 'a' && hd2 <= 'f') {
|
||||
hexValue += hd2 - 'a' + 10;
|
||||
} else
|
||||
return -1;
|
||||
return hexValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the parser finds a backslash not followed
|
||||
* by a valid expression (like \( in non-Posix mode).
|
||||
* @param pattern: pointer on the char after the backslash.
|
||||
* @param incr: (out) number of chars to skip after expression evaluation.
|
||||
* @return the char if it resolves to a simple char,
|
||||
* or -1 for a char class. In this case, bittab is changed.
|
||||
*/
|
||||
int RESearch::GetBackslashExpression(
|
||||
const char *pattern,
|
||||
int &incr) {
|
||||
// Since error reporting is primitive and messages are not used anyway,
|
||||
// I choose to interpret unexpected syntax in a logical way instead
|
||||
// of reporting errors. Otherwise, we can stick on, eg., PCRE behavior.
|
||||
incr = 0; // Most of the time, will skip the char "naturally".
|
||||
int c;
|
||||
int result = -1;
|
||||
unsigned char bsc = *pattern;
|
||||
if (!bsc) {
|
||||
// Avoid overrun
|
||||
result = '\\'; // \ at end of pattern, take it literally
|
||||
return result;
|
||||
}
|
||||
|
||||
switch (bsc) {
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'n':
|
||||
case 'f':
|
||||
case 'r':
|
||||
case 't':
|
||||
case 'v':
|
||||
result = escapeValue(bsc);
|
||||
break;
|
||||
case 'x': {
|
||||
unsigned char hd1 = *(pattern + 1);
|
||||
unsigned char hd2 = *(pattern + 2);
|
||||
int hexValue = GetHexaChar(hd1, hd2);
|
||||
if (hexValue >= 0) {
|
||||
result = hexValue;
|
||||
incr = 2; // Must skip the digits
|
||||
} else {
|
||||
result = 'x'; // \x without 2 digits: see it as 'x'
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
for (c = '0'; c <= '9'; c++) {
|
||||
ChSet(static_cast<unsigned char>(c));
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
for (c = 0; c < MAXCHR; c++) {
|
||||
if (c < '0' || c > '9') {
|
||||
ChSet(static_cast<unsigned char>(c));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
ChSet(' ');
|
||||
ChSet('\t');
|
||||
ChSet('\n');
|
||||
ChSet('\r');
|
||||
ChSet('\f');
|
||||
ChSet('\v');
|
||||
break;
|
||||
case 'S':
|
||||
for (c = 0; c < MAXCHR; c++) {
|
||||
if (c != ' ' && !(c >= 0x09 && c <= 0x0D)) {
|
||||
ChSet(static_cast<unsigned char>(c));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'w':
|
||||
for (c = 0; c < MAXCHR; c++) {
|
||||
if (iswordc(static_cast<unsigned char>(c))) {
|
||||
ChSet(static_cast<unsigned char>(c));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'W':
|
||||
for (c = 0; c < MAXCHR; c++) {
|
||||
if (!iswordc(static_cast<unsigned char>(c))) {
|
||||
ChSet(static_cast<unsigned char>(c));
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
result = bsc;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const char *RESearch::Compile(const char *pattern, int length, bool caseSensitive, bool posix) {
|
||||
char *mp=nfa; /* nfa pointer */
|
||||
char *lp; /* saved pointer */
|
||||
char *sp=nfa; /* another one */
|
||||
char *mpMax = mp + MAXNFA - BITBLK - 10;
|
||||
|
||||
int tagi = 0; /* tag stack index */
|
||||
int tagc = 1; /* actual tag count */
|
||||
|
||||
int n;
|
||||
char mask; /* xor mask -CCL/NCL */
|
||||
int c1, c2, prevChar;
|
||||
|
||||
if (!pattern || !length) {
|
||||
if (sta)
|
||||
return 0;
|
||||
else
|
||||
return badpat("No previous regular expression");
|
||||
}
|
||||
sta = NOP;
|
||||
|
||||
const char *p=pattern; /* pattern pointer */
|
||||
for (int i=0; i<length; i++, p++) {
|
||||
if (mp > mpMax)
|
||||
return badpat("Pattern too long");
|
||||
lp = mp;
|
||||
switch (*p) {
|
||||
|
||||
case '.': /* match any char */
|
||||
*mp++ = ANY;
|
||||
break;
|
||||
|
||||
case '^': /* match beginning */
|
||||
if (p == pattern)
|
||||
*mp++ = BOL;
|
||||
else {
|
||||
*mp++ = CHR;
|
||||
*mp++ = *p;
|
||||
}
|
||||
break;
|
||||
|
||||
case '$': /* match endofline */
|
||||
if (!*(p+1))
|
||||
*mp++ = EOL;
|
||||
else {
|
||||
*mp++ = CHR;
|
||||
*mp++ = *p;
|
||||
}
|
||||
break;
|
||||
|
||||
case '[': /* match char class */
|
||||
*mp++ = CCL;
|
||||
prevChar = 0;
|
||||
|
||||
i++;
|
||||
if (*++p == '^') {
|
||||
mask = '\377';
|
||||
i++;
|
||||
p++;
|
||||
} else
|
||||
mask = 0;
|
||||
|
||||
if (*p == '-') { /* real dash */
|
||||
i++;
|
||||
prevChar = *p;
|
||||
ChSet(*p++);
|
||||
}
|
||||
if (*p == ']') { /* real brace */
|
||||
i++;
|
||||
prevChar = *p;
|
||||
ChSet(*p++);
|
||||
}
|
||||
while (*p && *p != ']') {
|
||||
if (*p == '-') {
|
||||
if (prevChar < 0) {
|
||||
// Previous def. was a char class like \d, take dash literally
|
||||
prevChar = *p;
|
||||
ChSet(*p);
|
||||
} else if (*(p+1)) {
|
||||
if (*(p+1) != ']') {
|
||||
c1 = prevChar + 1;
|
||||
i++;
|
||||
c2 = static_cast<unsigned char>(*++p);
|
||||
if (c2 == '\\') {
|
||||
if (!*(p+1)) // End of RE
|
||||
return badpat("Missing ]");
|
||||
else {
|
||||
i++;
|
||||
p++;
|
||||
int incr;
|
||||
c2 = GetBackslashExpression(p, incr);
|
||||
i += incr;
|
||||
p += incr;
|
||||
if (c2 >= 0) {
|
||||
// Convention: \c (c is any char) is case sensitive, whatever the option
|
||||
ChSet(static_cast<unsigned char>(c2));
|
||||
prevChar = c2;
|
||||
} else {
|
||||
// bittab is already changed
|
||||
prevChar = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (prevChar < 0) {
|
||||
// Char after dash is char class like \d, take dash literally
|
||||
prevChar = '-';
|
||||
ChSet('-');
|
||||
} else {
|
||||
// Put all chars between c1 and c2 included in the char set
|
||||
while (c1 <= c2) {
|
||||
ChSetWithCase(static_cast<unsigned char>(c1++), caseSensitive);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Dash before the ], take it literally
|
||||
prevChar = *p;
|
||||
ChSet(*p);
|
||||
}
|
||||
} else {
|
||||
return badpat("Missing ]");
|
||||
}
|
||||
} else if (*p == '\\' && *(p+1)) {
|
||||
i++;
|
||||
p++;
|
||||
int incr;
|
||||
int c = GetBackslashExpression(p, incr);
|
||||
i += incr;
|
||||
p += incr;
|
||||
if (c >= 0) {
|
||||
// Convention: \c (c is any char) is case sensitive, whatever the option
|
||||
ChSet(static_cast<unsigned char>(c));
|
||||
prevChar = c;
|
||||
} else {
|
||||
// bittab is already changed
|
||||
prevChar = -1;
|
||||
}
|
||||
} else {
|
||||
prevChar = static_cast<unsigned char>(*p);
|
||||
ChSetWithCase(*p, caseSensitive);
|
||||
}
|
||||
i++;
|
||||
p++;
|
||||
}
|
||||
if (!*p)
|
||||
return badpat("Missing ]");
|
||||
|
||||
for (n = 0; n < BITBLK; bittab[n++] = 0)
|
||||
*mp++ = static_cast<char>(mask ^ bittab[n]);
|
||||
|
||||
break;
|
||||
|
||||
case '*': /* match 0 or more... */
|
||||
case '+': /* match 1 or more... */
|
||||
case '?':
|
||||
if (p == pattern)
|
||||
return badpat("Empty closure");
|
||||
lp = sp; /* previous opcode */
|
||||
if (*lp == CLO || *lp == LCLO) /* equivalence... */
|
||||
break;
|
||||
switch (*lp) {
|
||||
|
||||
case BOL:
|
||||
case BOT:
|
||||
case EOT:
|
||||
case BOW:
|
||||
case EOW:
|
||||
case REF:
|
||||
return badpat("Illegal closure");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (*p == '+')
|
||||
for (sp = mp; lp < sp; lp++)
|
||||
*mp++ = *lp;
|
||||
|
||||
*mp++ = END;
|
||||
*mp++ = END;
|
||||
sp = mp;
|
||||
|
||||
while (--mp > lp)
|
||||
*mp = mp[-1];
|
||||
if (*p == '?') *mp = CLQ;
|
||||
else if (*(p+1) == '?') *mp = LCLO;
|
||||
else *mp = CLO;
|
||||
|
||||
mp = sp;
|
||||
break;
|
||||
|
||||
case '\\': /* tags, backrefs... */
|
||||
i++;
|
||||
switch (*++p) {
|
||||
case '<':
|
||||
*mp++ = BOW;
|
||||
break;
|
||||
case '>':
|
||||
if (*sp == BOW)
|
||||
return badpat("Null pattern inside \\<\\>");
|
||||
*mp++ = EOW;
|
||||
break;
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
n = *p-'0';
|
||||
if (tagi > 0 && tagstk[tagi] == n)
|
||||
return badpat("Cyclical reference");
|
||||
if (tagc > n) {
|
||||
*mp++ = static_cast<char>(REF);
|
||||
*mp++ = static_cast<char>(n);
|
||||
} else
|
||||
return badpat("Undetermined reference");
|
||||
break;
|
||||
default:
|
||||
if (!posix && *p == '(') {
|
||||
if (tagc < MAXTAG) {
|
||||
tagstk[++tagi] = tagc;
|
||||
*mp++ = BOT;
|
||||
*mp++ = static_cast<char>(tagc++);
|
||||
} else
|
||||
return badpat("Too many \\(\\) pairs");
|
||||
} else if (!posix && *p == ')') {
|
||||
if (*sp == BOT)
|
||||
return badpat("Null pattern inside \\(\\)");
|
||||
if (tagi > 0) {
|
||||
*mp++ = static_cast<char>(EOT);
|
||||
*mp++ = static_cast<char>(tagstk[tagi--]);
|
||||
} else
|
||||
return badpat("Unmatched \\)");
|
||||
} else {
|
||||
int incr;
|
||||
int c = GetBackslashExpression(p, incr);
|
||||
i += incr;
|
||||
p += incr;
|
||||
if (c >= 0) {
|
||||
*mp++ = CHR;
|
||||
*mp++ = static_cast<unsigned char>(c);
|
||||
} else {
|
||||
*mp++ = CCL;
|
||||
mask = 0;
|
||||
for (n = 0; n < BITBLK; bittab[n++] = 0)
|
||||
*mp++ = static_cast<char>(mask ^ bittab[n]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default : /* an ordinary char */
|
||||
if (posix && *p == '(') {
|
||||
if (tagc < MAXTAG) {
|
||||
tagstk[++tagi] = tagc;
|
||||
*mp++ = BOT;
|
||||
*mp++ = static_cast<char>(tagc++);
|
||||
} else
|
||||
return badpat("Too many () pairs");
|
||||
} else if (posix && *p == ')') {
|
||||
if (*sp == BOT)
|
||||
return badpat("Null pattern inside ()");
|
||||
if (tagi > 0) {
|
||||
*mp++ = static_cast<char>(EOT);
|
||||
*mp++ = static_cast<char>(tagstk[tagi--]);
|
||||
} else
|
||||
return badpat("Unmatched )");
|
||||
} else {
|
||||
unsigned char c = *p;
|
||||
if (!c) // End of RE
|
||||
c = '\\'; // We take it as raw backslash
|
||||
if (caseSensitive || !iswordc(c)) {
|
||||
*mp++ = CHR;
|
||||
*mp++ = c;
|
||||
} else {
|
||||
*mp++ = CCL;
|
||||
mask = 0;
|
||||
ChSetWithCase(c, false);
|
||||
for (n = 0; n < BITBLK; bittab[n++] = 0)
|
||||
*mp++ = static_cast<char>(mask ^ bittab[n]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
sp = lp;
|
||||
}
|
||||
if (tagi > 0)
|
||||
return badpat((posix ? "Unmatched (" : "Unmatched \\("));
|
||||
*mp = END;
|
||||
sta = OKP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* RESearch::Execute:
|
||||
* execute nfa to find a match.
|
||||
*
|
||||
* special cases: (nfa[0])
|
||||
* BOL
|
||||
* Match only once, starting from the
|
||||
* beginning.
|
||||
* CHR
|
||||
* First locate the character without
|
||||
* calling PMatch, and if found, call
|
||||
* PMatch for the remaining string.
|
||||
* END
|
||||
* RESearch::Compile failed, poor luser did not
|
||||
* check for it. Fail fast.
|
||||
*
|
||||
* If a match is found, bopat[0] and eopat[0] are set
|
||||
* to the beginning and the end of the matched fragment,
|
||||
* respectively.
|
||||
*
|
||||
*/
|
||||
int RESearch::Execute(CharacterIndexer &ci, int lp, int endp) {
|
||||
unsigned char c;
|
||||
int ep = NOTFOUND;
|
||||
char *ap = nfa;
|
||||
|
||||
bol = lp;
|
||||
failure = 0;
|
||||
|
||||
Clear();
|
||||
|
||||
switch (*ap) {
|
||||
|
||||
case BOL: /* anchored: match from BOL only */
|
||||
ep = PMatch(ci, lp, endp, ap);
|
||||
break;
|
||||
case EOL: /* just searching for end of line normal path doesn't work */
|
||||
if (*(ap+1) == END) {
|
||||
lp = endp;
|
||||
ep = lp;
|
||||
break;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
case CHR: /* ordinary char: locate it fast */
|
||||
c = *(ap+1);
|
||||
while ((lp < endp) && (static_cast<unsigned char>(ci.CharAt(lp)) != c))
|
||||
lp++;
|
||||
if (lp >= endp) /* if EOS, fail, else fall through. */
|
||||
return 0;
|
||||
default: /* regular matching all the way. */
|
||||
while (lp < endp) {
|
||||
ep = PMatch(ci, lp, endp, ap);
|
||||
if (ep != NOTFOUND)
|
||||
break;
|
||||
lp++;
|
||||
}
|
||||
break;
|
||||
case END: /* munged automaton. fail always */
|
||||
return 0;
|
||||
}
|
||||
if (ep == NOTFOUND)
|
||||
return 0;
|
||||
|
||||
bopat[0] = lp;
|
||||
eopat[0] = ep;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* PMatch: internal routine for the hard part
|
||||
*
|
||||
* This code is partly snarfed from an early grep written by
|
||||
* David Conroy. The backref and tag stuff, and various other
|
||||
* innovations are by oz.
|
||||
*
|
||||
* special case optimizations: (nfa[n], nfa[n+1])
|
||||
* CLO ANY
|
||||
* We KNOW .* will match everything upto the
|
||||
* end of line. Thus, directly go to the end of
|
||||
* line, without recursive PMatch calls. As in
|
||||
* the other closure cases, the remaining pattern
|
||||
* must be matched by moving backwards on the
|
||||
* string recursively, to find a match for xy
|
||||
* (x is ".*" and y is the remaining pattern)
|
||||
* where the match satisfies the LONGEST match for
|
||||
* x followed by a match for y.
|
||||
* CLO CHR
|
||||
* We can again scan the string forward for the
|
||||
* single char and at the point of failure, we
|
||||
* execute the remaining nfa recursively, same as
|
||||
* above.
|
||||
*
|
||||
* At the end of a successful match, bopat[n] and eopat[n]
|
||||
* are set to the beginning and end of subpatterns matched
|
||||
* by tagged expressions (n = 1 to 9).
|
||||
*/
|
||||
|
||||
extern void re_fail(char *,char);
|
||||
|
||||
#define isinset(x,y) ((x)[((y)&BLKIND)>>3] & bitarr[(y)&BITIND])
|
||||
|
||||
/*
|
||||
* skip values for CLO XXX to skip past the closure
|
||||
*/
|
||||
|
||||
#define ANYSKIP 2 /* [CLO] ANY END */
|
||||
#define CHRSKIP 3 /* [CLO] CHR chr END */
|
||||
#define CCLSKIP 34 /* [CLO] CCL 32 bytes END */
|
||||
|
||||
int RESearch::PMatch(CharacterIndexer &ci, int lp, int endp, char *ap) {
|
||||
int op, c, n;
|
||||
int e; /* extra pointer for CLO */
|
||||
int bp; /* beginning of subpat... */
|
||||
int ep; /* ending of subpat... */
|
||||
int are; /* to save the line ptr. */
|
||||
int llp; /* lazy lp for LCLO */
|
||||
|
||||
while ((op = *ap++) != END)
|
||||
switch (op) {
|
||||
|
||||
case CHR:
|
||||
if (ci.CharAt(lp++) != *ap++)
|
||||
return NOTFOUND;
|
||||
break;
|
||||
case ANY:
|
||||
if (lp++ >= endp)
|
||||
return NOTFOUND;
|
||||
break;
|
||||
case CCL:
|
||||
if (lp >= endp)
|
||||
return NOTFOUND;
|
||||
c = ci.CharAt(lp++);
|
||||
if (!isinset(ap,c))
|
||||
return NOTFOUND;
|
||||
ap += BITBLK;
|
||||
break;
|
||||
case BOL:
|
||||
if (lp != bol)
|
||||
return NOTFOUND;
|
||||
break;
|
||||
case EOL:
|
||||
if (lp < endp)
|
||||
return NOTFOUND;
|
||||
break;
|
||||
case BOT:
|
||||
bopat[static_cast<int>(*ap++)] = lp;
|
||||
break;
|
||||
case EOT:
|
||||
eopat[static_cast<int>(*ap++)] = lp;
|
||||
break;
|
||||
case BOW:
|
||||
if ((lp!=bol && iswordc(ci.CharAt(lp-1))) || !iswordc(ci.CharAt(lp)))
|
||||
return NOTFOUND;
|
||||
break;
|
||||
case EOW:
|
||||
if (lp==bol || !iswordc(ci.CharAt(lp-1)) || iswordc(ci.CharAt(lp)))
|
||||
return NOTFOUND;
|
||||
break;
|
||||
case REF:
|
||||
n = *ap++;
|
||||
bp = bopat[n];
|
||||
ep = eopat[n];
|
||||
while (bp < ep)
|
||||
if (ci.CharAt(bp++) != ci.CharAt(lp++))
|
||||
return NOTFOUND;
|
||||
break;
|
||||
case LCLO:
|
||||
case CLQ:
|
||||
case CLO:
|
||||
are = lp;
|
||||
switch (*ap) {
|
||||
|
||||
case ANY:
|
||||
if (op == CLO || op == LCLO)
|
||||
while (lp < endp)
|
||||
lp++;
|
||||
else if (lp < endp)
|
||||
lp++;
|
||||
|
||||
n = ANYSKIP;
|
||||
break;
|
||||
case CHR:
|
||||
c = *(ap+1);
|
||||
if (op == CLO || op == LCLO)
|
||||
while ((lp < endp) && (c == ci.CharAt(lp)))
|
||||
lp++;
|
||||
else if ((lp < endp) && (c == ci.CharAt(lp)))
|
||||
lp++;
|
||||
n = CHRSKIP;
|
||||
break;
|
||||
case CCL:
|
||||
while ((lp < endp) && isinset(ap+1,ci.CharAt(lp)))
|
||||
lp++;
|
||||
n = CCLSKIP;
|
||||
break;
|
||||
default:
|
||||
failure = true;
|
||||
//re_fail("closure: bad nfa.", *ap);
|
||||
return NOTFOUND;
|
||||
}
|
||||
ap += n;
|
||||
|
||||
llp = lp;
|
||||
e = NOTFOUND;
|
||||
while (llp >= are) {
|
||||
int q;
|
||||
if ((q = PMatch(ci, llp, endp, ap)) != NOTFOUND) {
|
||||
e = q;
|
||||
lp = llp;
|
||||
if (op != LCLO) return e;
|
||||
}
|
||||
if (*ap == END) return e;
|
||||
--llp;
|
||||
}
|
||||
if (*ap == EOT)
|
||||
PMatch(ci, lp, endp, ap);
|
||||
return e;
|
||||
default:
|
||||
//re_fail("RESearch::Execute: bad nfa.", static_cast<char>(op));
|
||||
return NOTFOUND;
|
||||
}
|
||||
return lp;
|
||||
}
|
||||
|
||||
|
||||
74
third-party/scintilla/RESearch.h
vendored
Normal file
74
third-party/scintilla/RESearch.h
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file RESearch.h
|
||||
** Interface to the regular expression search library.
|
||||
**/
|
||||
// Written by Neil Hodgson <neilh@scintilla.org>
|
||||
// Based on the work of Ozan S. Yigit.
|
||||
// This file is in the public domain.
|
||||
|
||||
#ifndef RESEARCH_H
|
||||
#define RESEARCH_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following defines are not meant to be changeable.
|
||||
* They are for readability only.
|
||||
*/
|
||||
#define MAXCHR 256
|
||||
#define CHRBIT 8
|
||||
#define BITBLK MAXCHR/CHRBIT
|
||||
|
||||
class CharacterIndexer {
|
||||
public:
|
||||
virtual char CharAt(int index)=0;
|
||||
virtual ~CharacterIndexer() {
|
||||
}
|
||||
};
|
||||
|
||||
class RESearch {
|
||||
|
||||
public:
|
||||
explicit RESearch(CharClassify *charClassTable);
|
||||
~RESearch();
|
||||
void GrabMatches(CharacterIndexer &ci);
|
||||
const char *Compile(const char *pattern, int length, bool caseSensitive, bool posix);
|
||||
int Execute(CharacterIndexer &ci, int lp, int endp);
|
||||
|
||||
enum { MAXTAG=10 };
|
||||
enum { MAXNFA=2048 };
|
||||
enum { NOTFOUND=-1 };
|
||||
|
||||
int bopat[MAXTAG];
|
||||
int eopat[MAXTAG];
|
||||
std::string pat[MAXTAG];
|
||||
|
||||
private:
|
||||
void Init();
|
||||
void Clear();
|
||||
void ChSet(unsigned char c);
|
||||
void ChSetWithCase(unsigned char c, bool caseSensitive);
|
||||
int GetBackslashExpression(const char *pattern, int &incr);
|
||||
|
||||
int PMatch(CharacterIndexer &ci, int lp, int endp, char *ap);
|
||||
|
||||
int bol;
|
||||
int tagstk[MAXTAG]; /* subpat tag stack */
|
||||
char nfa[MAXNFA]; /* automaton */
|
||||
int sta;
|
||||
unsigned char bittab[BITBLK]; /* bit table for CCL pre-set bits */
|
||||
int failure;
|
||||
CharClassify *charClass;
|
||||
bool iswordc(unsigned char x) const {
|
||||
return charClass->IsWord(x);
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
280
third-party/scintilla/RunStyles.cxx
vendored
Normal file
280
third-party/scintilla/RunStyles.cxx
vendored
Normal file
@@ -0,0 +1,280 @@
|
||||
/** @file RunStyles.cxx
|
||||
** Data structure used to store sparse styles.
|
||||
**/
|
||||
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
#include "SplitVector.h"
|
||||
#include "Partitioning.h"
|
||||
#include "RunStyles.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
// Find the first run at a position
|
||||
int RunStyles::RunFromPosition(int position) const {
|
||||
int run = starts->PartitionFromPosition(position);
|
||||
// Go to first element with this position
|
||||
while ((run > 0) && (position == starts->PositionFromPartition(run-1))) {
|
||||
run--;
|
||||
}
|
||||
return run;
|
||||
}
|
||||
|
||||
// If there is no run boundary at position, insert one continuing style.
|
||||
int RunStyles::SplitRun(int position) {
|
||||
int run = RunFromPosition(position);
|
||||
int posRun = starts->PositionFromPartition(run);
|
||||
if (posRun < position) {
|
||||
int runStyle = ValueAt(position);
|
||||
run++;
|
||||
starts->InsertPartition(run, position);
|
||||
styles->InsertValue(run, 1, runStyle);
|
||||
}
|
||||
return run;
|
||||
}
|
||||
|
||||
void RunStyles::RemoveRun(int run) {
|
||||
starts->RemovePartition(run);
|
||||
styles->DeleteRange(run, 1);
|
||||
}
|
||||
|
||||
void RunStyles::RemoveRunIfEmpty(int run) {
|
||||
if ((run < starts->Partitions()) && (starts->Partitions() > 1)) {
|
||||
if (starts->PositionFromPartition(run) == starts->PositionFromPartition(run+1)) {
|
||||
RemoveRun(run);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RunStyles::RemoveRunIfSameAsPrevious(int run) {
|
||||
if ((run > 0) && (run < starts->Partitions())) {
|
||||
if (styles->ValueAt(run-1) == styles->ValueAt(run)) {
|
||||
RemoveRun(run);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RunStyles::RunStyles() {
|
||||
starts = new Partitioning(8);
|
||||
styles = new SplitVector<int>();
|
||||
styles->InsertValue(0, 2, 0);
|
||||
}
|
||||
|
||||
RunStyles::~RunStyles() {
|
||||
delete starts;
|
||||
starts = NULL;
|
||||
delete styles;
|
||||
styles = NULL;
|
||||
}
|
||||
|
||||
int RunStyles::Length() const {
|
||||
return starts->PositionFromPartition(starts->Partitions());
|
||||
}
|
||||
|
||||
int RunStyles::ValueAt(int position) const {
|
||||
return styles->ValueAt(starts->PartitionFromPosition(position));
|
||||
}
|
||||
|
||||
int RunStyles::FindNextChange(int position, int end) const {
|
||||
int run = starts->PartitionFromPosition(position);
|
||||
if (run < starts->Partitions()) {
|
||||
int runChange = starts->PositionFromPartition(run);
|
||||
if (runChange > position)
|
||||
return runChange;
|
||||
int nextChange = starts->PositionFromPartition(run + 1);
|
||||
if (nextChange > position) {
|
||||
return nextChange;
|
||||
} else if (position < end) {
|
||||
return end;
|
||||
} else {
|
||||
return end + 1;
|
||||
}
|
||||
} else {
|
||||
return end + 1;
|
||||
}
|
||||
}
|
||||
|
||||
int RunStyles::StartRun(int position) const {
|
||||
return starts->PositionFromPartition(starts->PartitionFromPosition(position));
|
||||
}
|
||||
|
||||
int RunStyles::EndRun(int position) const {
|
||||
return starts->PositionFromPartition(starts->PartitionFromPosition(position) + 1);
|
||||
}
|
||||
|
||||
bool RunStyles::FillRange(int &position, int value, int &fillLength) {
|
||||
if (fillLength <= 0) {
|
||||
return false;
|
||||
}
|
||||
int end = position + fillLength;
|
||||
if (end > Length()) {
|
||||
return false;
|
||||
}
|
||||
int runEnd = RunFromPosition(end);
|
||||
if (styles->ValueAt(runEnd) == value) {
|
||||
// End already has value so trim range.
|
||||
end = starts->PositionFromPartition(runEnd);
|
||||
if (position >= end) {
|
||||
// Whole range is already same as value so no action
|
||||
return false;
|
||||
}
|
||||
fillLength = end - position;
|
||||
} else {
|
||||
runEnd = SplitRun(end);
|
||||
}
|
||||
int runStart = RunFromPosition(position);
|
||||
if (styles->ValueAt(runStart) == value) {
|
||||
// Start is in expected value so trim range.
|
||||
runStart++;
|
||||
position = starts->PositionFromPartition(runStart);
|
||||
fillLength = end - position;
|
||||
} else {
|
||||
if (starts->PositionFromPartition(runStart) < position) {
|
||||
runStart = SplitRun(position);
|
||||
runEnd++;
|
||||
}
|
||||
}
|
||||
if (runStart < runEnd) {
|
||||
styles->SetValueAt(runStart, value);
|
||||
// Remove each old run over the range
|
||||
for (int run=runStart+1; run<runEnd; run++) {
|
||||
RemoveRun(runStart+1);
|
||||
}
|
||||
runEnd = RunFromPosition(end);
|
||||
RemoveRunIfSameAsPrevious(runEnd);
|
||||
RemoveRunIfSameAsPrevious(runStart);
|
||||
runEnd = RunFromPosition(end);
|
||||
RemoveRunIfEmpty(runEnd);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void RunStyles::SetValueAt(int position, int value) {
|
||||
int len = 1;
|
||||
FillRange(position, value, len);
|
||||
}
|
||||
|
||||
void RunStyles::InsertSpace(int position, int insertLength) {
|
||||
int runStart = RunFromPosition(position);
|
||||
if (starts->PositionFromPartition(runStart) == position) {
|
||||
int runStyle = ValueAt(position);
|
||||
// Inserting at start of run so make previous longer
|
||||
if (runStart == 0) {
|
||||
// Inserting at start of document so ensure 0
|
||||
if (runStyle) {
|
||||
styles->SetValueAt(0, 0);
|
||||
starts->InsertPartition(1, 0);
|
||||
styles->InsertValue(1, 1, runStyle);
|
||||
starts->InsertText(0, insertLength);
|
||||
} else {
|
||||
starts->InsertText(runStart, insertLength);
|
||||
}
|
||||
} else {
|
||||
if (runStyle) {
|
||||
starts->InsertText(runStart-1, insertLength);
|
||||
} else {
|
||||
// Insert at end of run so do not extend style
|
||||
starts->InsertText(runStart, insertLength);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
starts->InsertText(runStart, insertLength);
|
||||
}
|
||||
}
|
||||
|
||||
void RunStyles::DeleteAll() {
|
||||
delete starts;
|
||||
starts = NULL;
|
||||
delete styles;
|
||||
styles = NULL;
|
||||
starts = new Partitioning(8);
|
||||
styles = new SplitVector<int>();
|
||||
styles->InsertValue(0, 2, 0);
|
||||
}
|
||||
|
||||
void RunStyles::DeleteRange(int position, int deleteLength) {
|
||||
int end = position + deleteLength;
|
||||
int runStart = RunFromPosition(position);
|
||||
int runEnd = RunFromPosition(end);
|
||||
if (runStart == runEnd) {
|
||||
// Deleting from inside one run
|
||||
starts->InsertText(runStart, -deleteLength);
|
||||
RemoveRunIfEmpty(runStart);
|
||||
} else {
|
||||
runStart = SplitRun(position);
|
||||
runEnd = SplitRun(end);
|
||||
starts->InsertText(runStart, -deleteLength);
|
||||
// Remove each old run over the range
|
||||
for (int run=runStart; run<runEnd; run++) {
|
||||
RemoveRun(runStart);
|
||||
}
|
||||
RemoveRunIfEmpty(runStart);
|
||||
RemoveRunIfSameAsPrevious(runStart);
|
||||
}
|
||||
}
|
||||
|
||||
int RunStyles::Runs() const {
|
||||
return starts->Partitions();
|
||||
}
|
||||
|
||||
bool RunStyles::AllSame() const {
|
||||
for (int run = 1; run < starts->Partitions(); run++) {
|
||||
if (styles->ValueAt(run) != styles->ValueAt(run - 1))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RunStyles::AllSameAs(int value) const {
|
||||
return AllSame() && (styles->ValueAt(0) == value);
|
||||
}
|
||||
|
||||
int RunStyles::Find(int value, int start) const {
|
||||
if (start < Length()) {
|
||||
int run = start ? RunFromPosition(start) : 0;
|
||||
if (styles->ValueAt(run) == value)
|
||||
return start;
|
||||
run++;
|
||||
while (run < starts->Partitions()) {
|
||||
if (styles->ValueAt(run) == value)
|
||||
return starts->PositionFromPartition(run);
|
||||
run++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void RunStyles::Check() const {
|
||||
if (Length() < 0) {
|
||||
throw std::runtime_error("RunStyles: Length can not be negative.");
|
||||
}
|
||||
if (starts->Partitions() < 1) {
|
||||
throw std::runtime_error("RunStyles: Must always have 1 or more partitions.");
|
||||
}
|
||||
if (starts->Partitions() != styles->Length()-1) {
|
||||
throw std::runtime_error("RunStyles: Partitions and styles different lengths.");
|
||||
}
|
||||
int start=0;
|
||||
while (start < Length()) {
|
||||
int end = EndRun(start);
|
||||
if (start >= end) {
|
||||
throw std::runtime_error("RunStyles: Partition is 0 length.");
|
||||
}
|
||||
start = end;
|
||||
}
|
||||
if (styles->ValueAt(styles->Length()-1) != 0) {
|
||||
throw std::runtime_error("RunStyles: Unused style at end changed.");
|
||||
}
|
||||
for (int j=1; j<styles->Length()-1; j++) {
|
||||
if (styles->ValueAt(j) == styles->ValueAt(j-1)) {
|
||||
throw std::runtime_error("RunStyles: Style of a partition same as previous.");
|
||||
}
|
||||
}
|
||||
}
|
||||
56
third-party/scintilla/RunStyles.h
vendored
Normal file
56
third-party/scintilla/RunStyles.h
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/** @file RunStyles.h
|
||||
** Data structure used to store sparse styles.
|
||||
**/
|
||||
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
/// Styling buffer using one element for each run rather than using
|
||||
/// a filled buffer.
|
||||
|
||||
#ifndef RUNSTYLES_H
|
||||
#define RUNSTYLES_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
class RunStyles {
|
||||
private:
|
||||
Partitioning *starts;
|
||||
SplitVector<int> *styles;
|
||||
int RunFromPosition(int position) const;
|
||||
int SplitRun(int position);
|
||||
void RemoveRun(int run);
|
||||
void RemoveRunIfEmpty(int run);
|
||||
void RemoveRunIfSameAsPrevious(int run);
|
||||
|
||||
// no copy ctr or assignment op
|
||||
RunStyles(const RunStyles &);
|
||||
RunStyles &operator =(const RunStyles &);
|
||||
public:
|
||||
RunStyles();
|
||||
~RunStyles();
|
||||
int Length() const;
|
||||
int ValueAt(int position) const;
|
||||
int FindNextChange(int position, int end) const;
|
||||
int StartRun(int position) const;
|
||||
int EndRun(int position) const;
|
||||
// Returns true if some values may have changed
|
||||
bool FillRange(int &position, int value, int &fillLength);
|
||||
void SetValueAt(int position, int value);
|
||||
void InsertSpace(int position, int insertLength);
|
||||
void DeleteAll();
|
||||
void DeleteRange(int position, int deleteLength);
|
||||
int Runs() const;
|
||||
bool AllSame() const;
|
||||
bool AllSameAs(int value) const;
|
||||
int Find(int value, int start) const;
|
||||
|
||||
void Check() const;
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
1718
third-party/scintilla/SciLexer.h
vendored
Normal file
1718
third-party/scintilla/SciLexer.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6
third-party/scintilla/SciTE.properties
vendored
Normal file
6
third-party/scintilla/SciTE.properties
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# SciTE.properties is the per directory local options file and can be used to override
|
||||
# settings made in SciTEGlobal.properties
|
||||
command.build.directory.*.cxx=..\win32
|
||||
command.build.directory.*.h=..\win32
|
||||
command.build.*.cxx=nmake -f scintilla.mak QUIET=1
|
||||
command.build.*.h=nmake -f scintilla.mak QUIET=1
|
||||
1124
third-party/scintilla/Scintilla.h
vendored
Normal file
1124
third-party/scintilla/Scintilla.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1025
third-party/scintilla/ScintillaBase.cxx
vendored
Normal file
1025
third-party/scintilla/ScintillaBase.cxx
vendored
Normal file
File diff suppressed because it is too large
Load Diff
101
third-party/scintilla/ScintillaBase.h
vendored
Normal file
101
third-party/scintilla/ScintillaBase.h
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file ScintillaBase.h
|
||||
** Defines an enhanced subclass of Editor with calltips, autocomplete and context menu.
|
||||
**/
|
||||
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef SCINTILLABASE_H
|
||||
#define SCINTILLABASE_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
#ifdef SCI_LEXER
|
||||
class LexState;
|
||||
#endif
|
||||
|
||||
/**
|
||||
*/
|
||||
class ScintillaBase : public Editor {
|
||||
// Private so ScintillaBase objects can not be copied
|
||||
ScintillaBase(const ScintillaBase &);
|
||||
ScintillaBase &operator=(const ScintillaBase &);
|
||||
|
||||
protected:
|
||||
/** Enumeration of commands and child windows. */
|
||||
enum {
|
||||
idCallTip=1,
|
||||
idAutoComplete=2,
|
||||
|
||||
idcmdUndo=10,
|
||||
idcmdRedo=11,
|
||||
idcmdCut=12,
|
||||
idcmdCopy=13,
|
||||
idcmdPaste=14,
|
||||
idcmdDelete=15,
|
||||
idcmdSelectAll=16
|
||||
};
|
||||
|
||||
bool displayPopupMenu;
|
||||
Menu popup;
|
||||
AutoComplete ac;
|
||||
|
||||
CallTip ct;
|
||||
|
||||
int listType; ///< 0 is an autocomplete list
|
||||
int maxListWidth; /// Maximum width of list, in average character widths
|
||||
|
||||
#ifdef SCI_LEXER
|
||||
LexState *DocumentLexState();
|
||||
void SetLexer(uptr_t wParam);
|
||||
void SetLexerLanguage(const char *languageName);
|
||||
void Colourise(int start, int end);
|
||||
#endif
|
||||
|
||||
ScintillaBase();
|
||||
virtual ~ScintillaBase();
|
||||
virtual void Initialise() = 0;
|
||||
virtual void Finalise();
|
||||
|
||||
virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false);
|
||||
void Command(int cmdId);
|
||||
virtual void CancelModes();
|
||||
virtual int KeyCommand(unsigned int iMessage);
|
||||
|
||||
void AutoCompleteInsert(Position startPos, int removeLen, const char *text, int textLen);
|
||||
void AutoCompleteStart(int lenEntered, const char *list);
|
||||
void AutoCompleteCancel();
|
||||
void AutoCompleteMove(int delta);
|
||||
int AutoCompleteGetCurrent() const;
|
||||
int AutoCompleteGetCurrentText(char *buffer) const;
|
||||
void AutoCompleteCharacterAdded(char ch);
|
||||
void AutoCompleteCharacterDeleted();
|
||||
void AutoCompleteCompleted();
|
||||
void AutoCompleteMoveToCurrentWord();
|
||||
static void AutoCompleteDoubleClick(void *p);
|
||||
|
||||
void CallTipClick();
|
||||
void CallTipShow(Point pt, const char *defn);
|
||||
virtual void CreateCallTipWindow(PRectangle rc) = 0;
|
||||
|
||||
virtual void AddToPopUp(const char *label, int cmd=0, bool enabled=true) = 0;
|
||||
void ContextMenu(Point pt);
|
||||
|
||||
virtual void ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifiers);
|
||||
virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt);
|
||||
|
||||
void NotifyStyleToNeeded(int endStyleNeeded);
|
||||
void NotifyLexerChanged(Document *doc, void *userData);
|
||||
|
||||
public:
|
||||
// Public so scintilla_send_message can use it
|
||||
virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
650
third-party/scintilla/ScintillaEditBase.cc
vendored
Normal file
650
third-party/scintilla/ScintillaEditBase.cc
vendored
Normal file
@@ -0,0 +1,650 @@
|
||||
//
|
||||
// Copyright (c) 1990-2011, Scientific Toolworks, Inc.
|
||||
//
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
//
|
||||
// Author: Jason Haslam
|
||||
//
|
||||
// Additions Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware
|
||||
// ScintillaEditBase.cpp - Qt widget that wraps ScintillaQt and provides events and scrolling
|
||||
|
||||
#define INDIC_INPUTMETHOD 24
|
||||
|
||||
#include "../../VMProtect/moc/moc_ScintillaEditBase.cc"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
ScintillaEditBase::ScintillaEditBase(QWidget *parent)
|
||||
: QAbstractScrollArea(parent), sqt(0), preeditPos(-1), wheelDelta(0)
|
||||
{
|
||||
sqt = new ScintillaQt(this);
|
||||
|
||||
time.start();
|
||||
|
||||
// Set Qt defaults.
|
||||
setAcceptDrops(true);
|
||||
setMouseTracking(true);
|
||||
setAutoFillBackground(false);
|
||||
setFrameStyle(QFrame::NoFrame);
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
setAttribute(Qt::WA_StaticContents);
|
||||
viewport()->setAttribute(Qt::WA_OpaquePaintEvent);
|
||||
setAttribute(Qt::WA_KeyCompression);
|
||||
setAttribute(Qt::WA_InputMethodEnabled);
|
||||
|
||||
connect(sqt, SIGNAL(notifyParent(SCNotification)),
|
||||
this, SLOT(notifyParent(SCNotification)));
|
||||
|
||||
// Connect scroll bars.
|
||||
connect(verticalScrollBar(), SIGNAL(valueChanged(int)),
|
||||
this, SLOT(scrollVertical(int)));
|
||||
connect(horizontalScrollBar(), SIGNAL(valueChanged(int)),
|
||||
this, SLOT(scrollHorizontal(int)));
|
||||
|
||||
// Connect pass-through signals.
|
||||
connect(sqt, SIGNAL(horizontalRangeChanged(int,int)),
|
||||
this, SIGNAL(horizontalRangeChanged(int,int)));
|
||||
connect(sqt, SIGNAL(verticalRangeChanged(int,int)),
|
||||
this, SIGNAL(verticalRangeChanged(int,int)));
|
||||
connect(sqt, SIGNAL(horizontalScrolled(int)),
|
||||
this, SIGNAL(horizontalScrolled(int)));
|
||||
connect(sqt, SIGNAL(verticalScrolled(int)),
|
||||
this, SIGNAL(verticalScrolled(int)));
|
||||
|
||||
connect(sqt, SIGNAL(notifyChange()),
|
||||
this, SIGNAL(notifyChange()));
|
||||
|
||||
connect(sqt, SIGNAL(command(uptr_t, sptr_t)),
|
||||
this, SLOT(event_command(uptr_t, sptr_t)));
|
||||
|
||||
connect(sqt, SIGNAL(aboutToCopy(QMimeData *)),
|
||||
this, SIGNAL(aboutToCopy(QMimeData *)));
|
||||
}
|
||||
|
||||
ScintillaEditBase::~ScintillaEditBase() {}
|
||||
|
||||
sptr_t ScintillaEditBase::send(
|
||||
unsigned int iMessage,
|
||||
uptr_t wParam,
|
||||
sptr_t lParam) const
|
||||
{
|
||||
return sqt->WndProc(iMessage, wParam, lParam);
|
||||
}
|
||||
|
||||
sptr_t ScintillaEditBase::sends(
|
||||
unsigned int iMessage,
|
||||
uptr_t wParam,
|
||||
const char *s) const
|
||||
{
|
||||
return sqt->WndProc(iMessage, wParam, (sptr_t)s);
|
||||
}
|
||||
|
||||
void ScintillaEditBase::scrollHorizontal(int value)
|
||||
{
|
||||
sqt->HorizontalScrollTo(value);
|
||||
}
|
||||
|
||||
void ScintillaEditBase::scrollVertical(int value)
|
||||
{
|
||||
sqt->ScrollTo(value);
|
||||
}
|
||||
|
||||
bool ScintillaEditBase::event(QEvent *event)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
// Circumvent the tab focus convention.
|
||||
keyPressEvent(static_cast<QKeyEvent *>(event));
|
||||
result = event->isAccepted();
|
||||
} else if (event->type() == QEvent::Hide) {
|
||||
setMouseTracking(false);
|
||||
result = QAbstractScrollArea::event(event);
|
||||
} else {
|
||||
result = QAbstractScrollArea::event(event);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ScintillaEditBase::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
sqt->PartialPaint(PRectFromQRect(event->rect()));
|
||||
}
|
||||
|
||||
void ScintillaEditBase::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
if (event->orientation() == Qt::Horizontal) {
|
||||
if (horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOff)
|
||||
event->ignore();
|
||||
else
|
||||
QAbstractScrollArea::wheelEvent(event);
|
||||
} else {
|
||||
if (QApplication::keyboardModifiers() & Qt::ControlModifier) {
|
||||
// Zoom! We play with the font sizes in the styles.
|
||||
// Number of steps/line is ignored, we just care if sizing up or down
|
||||
if (event->delta() > 0) {
|
||||
sqt->KeyCommand(SCI_ZOOMIN);
|
||||
} else {
|
||||
sqt->KeyCommand(SCI_ZOOMOUT);
|
||||
}
|
||||
} else {
|
||||
// Ignore wheel events when the scroll bars are disabled.
|
||||
if (verticalScrollBarPolicy() == Qt::ScrollBarAlwaysOff) {
|
||||
event->ignore();
|
||||
} else {
|
||||
// Scroll
|
||||
QAbstractScrollArea::wheelEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScintillaEditBase::focusInEvent(QFocusEvent *event)
|
||||
{
|
||||
sqt->SetFocusState(true);
|
||||
emit updateUi();
|
||||
|
||||
QAbstractScrollArea::focusInEvent(event);
|
||||
}
|
||||
|
||||
void ScintillaEditBase::focusOutEvent(QFocusEvent *event)
|
||||
{
|
||||
sqt->SetFocusState(false);
|
||||
|
||||
QAbstractScrollArea::focusOutEvent(event);
|
||||
}
|
||||
|
||||
void ScintillaEditBase::resizeEvent(QResizeEvent *)
|
||||
{
|
||||
sqt->ChangeSize();
|
||||
emit resized();
|
||||
}
|
||||
|
||||
void ScintillaEditBase::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
// All keystrokes containing the meta modifier are
|
||||
// assumed to be shortcuts not handled by scintilla.
|
||||
if (QApplication::keyboardModifiers() & Qt::MetaModifier) {
|
||||
QAbstractScrollArea::keyPressEvent(event);
|
||||
emit keyPressed(event);
|
||||
return;
|
||||
}
|
||||
|
||||
int key = 0;
|
||||
switch (event->key()) {
|
||||
case Qt::Key_Down: key = SCK_DOWN; break;
|
||||
case Qt::Key_Up: key = SCK_UP; break;
|
||||
case Qt::Key_Left: key = SCK_LEFT; break;
|
||||
case Qt::Key_Right: key = SCK_RIGHT; break;
|
||||
case Qt::Key_Home: key = SCK_HOME; break;
|
||||
case Qt::Key_End: key = SCK_END; break;
|
||||
case Qt::Key_PageUp: key = SCK_PRIOR; break;
|
||||
case Qt::Key_PageDown: key = SCK_NEXT; break;
|
||||
case Qt::Key_Delete: key = SCK_DELETE; break;
|
||||
case Qt::Key_Insert: key = SCK_INSERT; break;
|
||||
case Qt::Key_Escape: key = SCK_ESCAPE; break;
|
||||
case Qt::Key_Backspace: key = SCK_BACK; break;
|
||||
case Qt::Key_Plus: key = SCK_ADD; break;
|
||||
case Qt::Key_Minus: key = SCK_SUBTRACT; break;
|
||||
case Qt::Key_Backtab: // fall through
|
||||
case Qt::Key_Tab: key = SCK_TAB; break;
|
||||
case Qt::Key_Enter: // fall through
|
||||
case Qt::Key_Return: key = SCK_RETURN; break;
|
||||
case Qt::Key_Control: key = 0; break;
|
||||
case Qt::Key_Alt: key = 0; break;
|
||||
case Qt::Key_Shift: key = 0; break;
|
||||
case Qt::Key_Meta: key = 0; break;
|
||||
default: key = event->key(); break;
|
||||
}
|
||||
|
||||
bool shift = QApplication::keyboardModifiers() & Qt::ShiftModifier;
|
||||
bool ctrl = QApplication::keyboardModifiers() & Qt::ControlModifier;
|
||||
bool alt = QApplication::keyboardModifiers() & Qt::AltModifier;
|
||||
|
||||
bool consumed = false;
|
||||
bool added = sqt->KeyDown(key, shift, ctrl, alt, &consumed) != 0;
|
||||
if (!consumed)
|
||||
consumed = added;
|
||||
|
||||
if (!consumed) {
|
||||
// Don't insert text if the control key was pressed unless
|
||||
// it was pressed in conjunction with alt for AltGr emulation.
|
||||
bool input = (!ctrl || alt);
|
||||
|
||||
// Additionally, on non-mac platforms, don't insert text
|
||||
// if the alt key was pressed unless control is also present.
|
||||
// On mac alt can be used to insert special characters.
|
||||
#ifndef Q_WS_MAC
|
||||
input &= (!alt || ctrl);
|
||||
#endif
|
||||
|
||||
QString text = event->text();
|
||||
if (input && !text.isEmpty() && text[0].isPrint()) {
|
||||
QByteArray utext = sqt->BytesForDocument(text);
|
||||
sqt->AddCharUTF(utext.data(), utext.size());
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
emit keyPressed(event);
|
||||
}
|
||||
|
||||
#ifdef Q_WS_X11
|
||||
static int modifierTranslated(int sciModifier)
|
||||
{
|
||||
switch (sciModifier) {
|
||||
case SCMOD_SHIFT:
|
||||
return Qt::ShiftModifier;
|
||||
case SCMOD_CTRL:
|
||||
return Qt::ControlModifier;
|
||||
case SCMOD_ALT:
|
||||
return Qt::AltModifier;
|
||||
case SCMOD_SUPER:
|
||||
return Qt::MetaModifier;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void ScintillaEditBase::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
Point pos = PointFromQPoint(event->pos());
|
||||
|
||||
emit buttonPressed(event);
|
||||
|
||||
if (event->button() == Qt::MidButton) {
|
||||
QClipboard *cb = QApplication::clipboard();
|
||||
if (cb && cb->supportsSelection()) {
|
||||
SelectionPosition selPos = sqt->SPositionFromLocation(
|
||||
pos, false, false, sqt->UserVirtualSpace());
|
||||
sqt->sel.Clear();
|
||||
sqt->SetSelection(selPos, selPos);
|
||||
sqt->PasteFromMode(QClipboard::Selection);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool button = event->button() == Qt::LeftButton;
|
||||
|
||||
if (button) {
|
||||
bool shift = QApplication::keyboardModifiers() & Qt::ShiftModifier;
|
||||
bool ctrl = QApplication::keyboardModifiers() & Qt::ControlModifier;
|
||||
#ifdef Q_WS_X11
|
||||
// On X allow choice of rectangular modifier since most window
|
||||
// managers grab alt + click for moving windows.
|
||||
bool alt = QApplication::keyboardModifiers() & modifierTranslated(sqt->rectangularSelectionModifier);
|
||||
#else
|
||||
bool alt = QApplication::keyboardModifiers() & Qt::AltModifier;
|
||||
#endif
|
||||
|
||||
sqt->ButtonDown(pos, time.elapsed(), shift, ctrl, alt);
|
||||
}
|
||||
}
|
||||
|
||||
void ScintillaEditBase::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
Point point = PointFromQPoint(event->pos());
|
||||
bool ctrl = QApplication::keyboardModifiers() & Qt::ControlModifier;
|
||||
if (event->button() == Qt::LeftButton)
|
||||
sqt->ButtonUp(point, time.elapsed(), ctrl);
|
||||
|
||||
int pos = send(SCI_POSITIONFROMPOINT, point.x, point.y);
|
||||
int line = send(SCI_LINEFROMPOSITION, pos);
|
||||
int modifiers = QApplication::keyboardModifiers();
|
||||
|
||||
emit textAreaClicked(line, modifiers);
|
||||
emit buttonReleased(event);
|
||||
}
|
||||
|
||||
void ScintillaEditBase::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
{
|
||||
// Scintilla does its own double-click detection.
|
||||
mousePressEvent(event);
|
||||
}
|
||||
|
||||
void ScintillaEditBase::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
Point pos = PointFromQPoint(event->pos());
|
||||
|
||||
bool shift = QApplication::keyboardModifiers() & Qt::ShiftModifier;
|
||||
bool ctrl = QApplication::keyboardModifiers() & Qt::ControlModifier;
|
||||
#ifdef Q_WS_X11
|
||||
// On X allow choice of rectangular modifier since most window
|
||||
// managers grab alt + click for moving windows.
|
||||
bool alt = QApplication::keyboardModifiers() & modifierTranslated(sqt->rectangularSelectionModifier);
|
||||
#else
|
||||
bool alt = QApplication::keyboardModifiers() & Qt::AltModifier;
|
||||
#endif
|
||||
|
||||
int modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) | (alt ? SCI_ALT : 0);
|
||||
|
||||
sqt->ButtonMoveWithModifiers(pos, modifiers);
|
||||
}
|
||||
|
||||
void ScintillaEditBase::contextMenuEvent(QContextMenuEvent *event)
|
||||
{
|
||||
Point pos = PointFromQPoint(event->globalPos());
|
||||
Point pt = PointFromQPoint(event->pos());
|
||||
if (!sqt->PointInSelection(pt))
|
||||
sqt->SetEmptySelection(sqt->PositionFromLocation(pt));
|
||||
sqt->ContextMenu(pos);
|
||||
}
|
||||
|
||||
void ScintillaEditBase::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
if (event->mimeData()->hasText()) {
|
||||
event->acceptProposedAction();
|
||||
|
||||
Point point = PointFromQPoint(event->pos());
|
||||
sqt->DragEnter(point);
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
void ScintillaEditBase::dragLeaveEvent(QDragLeaveEvent * /* event */)
|
||||
{
|
||||
sqt->DragLeave();
|
||||
}
|
||||
|
||||
void ScintillaEditBase::dragMoveEvent(QDragMoveEvent *event)
|
||||
{
|
||||
if (event->mimeData()->hasText()) {
|
||||
event->acceptProposedAction();
|
||||
|
||||
Point point = PointFromQPoint(event->pos());
|
||||
sqt->DragMove(point);
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
void ScintillaEditBase::dropEvent(QDropEvent *event)
|
||||
{
|
||||
if (event->mimeData()->hasText()) {
|
||||
event->acceptProposedAction();
|
||||
|
||||
Point point = PointFromQPoint(event->pos());
|
||||
bool move = (event->source() == this &&
|
||||
event->proposedAction() == Qt::MoveAction);
|
||||
sqt->Drop(point, event->mimeData(), move);
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
void ScintillaEditBase::inputMethodEvent(QInputMethodEvent *event)
|
||||
{
|
||||
// Clear the current selection.
|
||||
sqt->ClearSelection();
|
||||
if (preeditPos >= 0)
|
||||
sqt->SetSelection(preeditPos, preeditPos);
|
||||
|
||||
// Insert the commit string.
|
||||
if (!event->commitString().isEmpty() || event->replacementLength()) {
|
||||
// Select the text to be removed.
|
||||
int commitPos = send(SCI_GETCURRENTPOS);
|
||||
int start = commitPos + event->replacementStart();
|
||||
int end = start + event->replacementLength();
|
||||
sqt->SetSelection(start, end);
|
||||
|
||||
// Replace the selection with the commit string.
|
||||
QByteArray commitBytes = sqt->BytesForDocument(event->commitString());
|
||||
char *commitData = commitBytes.data();
|
||||
sqt->AddCharUTF(commitData, static_cast<unsigned int>(strlen(commitData)));
|
||||
}
|
||||
|
||||
// Select the previous preedit string.
|
||||
int pos = send(SCI_GETCURRENTPOS);
|
||||
int length = sqt->BytesForDocument(preeditString).length();
|
||||
sqt->SetSelection(pos, pos + length);
|
||||
|
||||
// Replace the selection with the new preedit string.
|
||||
QByteArray bytes = sqt->BytesForDocument(event->preeditString());
|
||||
char *data = bytes.data();
|
||||
bool recording = sqt->recordingMacro;
|
||||
sqt->recordingMacro = false;
|
||||
send(SCI_SETUNDOCOLLECTION, false);
|
||||
sqt->AddCharUTF(data, static_cast<unsigned int>(strlen(data)));
|
||||
send(SCI_SETUNDOCOLLECTION, true);
|
||||
sqt->recordingMacro = recording;
|
||||
sqt->SetSelection(pos, pos);
|
||||
|
||||
// Store the state of the current preedit string.
|
||||
preeditString = event->preeditString();
|
||||
preeditPos = !preeditString.isEmpty() ? send(SCI_GETCURRENTPOS) : -1;
|
||||
|
||||
if (!preeditString.isEmpty()) {
|
||||
// Apply attributes to the preedit string.
|
||||
int indicNum = 0;
|
||||
sqt->ShowCaretAtCurrentPosition();
|
||||
foreach (QInputMethodEvent::Attribute a, event->attributes()) {
|
||||
QString prefix = preeditString.left(a.start);
|
||||
QByteArray prefixBytes = sqt->BytesForDocument(prefix);
|
||||
int prefixLength = prefixBytes.length();
|
||||
int caretPos = preeditPos + prefixLength;
|
||||
|
||||
if (a.type == QInputMethodEvent::Cursor) {
|
||||
sqt->SetSelection(caretPos, caretPos);
|
||||
if (!a.length)
|
||||
sqt->DropCaret();
|
||||
|
||||
} else if (a.type == QInputMethodEvent::TextFormat) {
|
||||
Q_ASSERT(a.value.canConvert(QVariant::TextFormat));
|
||||
QTextFormat format = a.value.value<QTextFormat>();
|
||||
Q_ASSERT(format.isCharFormat());
|
||||
QTextCharFormat charFormat = format.toCharFormat();
|
||||
|
||||
QString sub = preeditString.mid(a.start, a.length);
|
||||
QByteArray subBytes = sqt->BytesForDocument(sub);
|
||||
int subLength = subBytes.length();
|
||||
|
||||
if (charFormat.underlineStyle() != QTextCharFormat::NoUnderline) {
|
||||
// Set temporary indicator for underline style.
|
||||
QColor uc = charFormat.underlineColor();
|
||||
int style = INDIC_PLAIN;
|
||||
if (charFormat.underlineStyle() == QTextCharFormat::DashUnderline)
|
||||
style = INDIC_DASH;
|
||||
send(SCI_INDICSETSTYLE, INDIC_INPUTMETHOD + indicNum, style);
|
||||
send(SCI_INDICSETFORE, INDIC_INPUTMETHOD + indicNum, uc.rgb());
|
||||
send(SCI_SETINDICATORCURRENT, INDIC_INPUTMETHOD + indicNum);
|
||||
send(SCI_INDICATORFILLRANGE, caretPos, subLength);
|
||||
indicNum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVariant ScintillaEditBase::inputMethodQuery(Qt::InputMethodQuery query) const
|
||||
{
|
||||
int pos = send(SCI_GETCURRENTPOS);
|
||||
int line = send(SCI_LINEFROMPOSITION, pos);
|
||||
|
||||
switch (query) {
|
||||
case Qt::ImMicroFocus:
|
||||
{
|
||||
int startPos = (preeditPos >= 0) ? preeditPos : pos;
|
||||
Point pt = sqt->LocationFromPosition(startPos);
|
||||
int width = send(SCI_GETCARETWIDTH);
|
||||
int height = send(SCI_TEXTHEIGHT, line);
|
||||
return QRect(pt.x, pt.y, width, height);
|
||||
}
|
||||
|
||||
case Qt::ImFont:
|
||||
{
|
||||
char fontName[64];
|
||||
int style = send(SCI_GETSTYLEAT, pos);
|
||||
int len = send(SCI_STYLEGETFONT, style, (sptr_t)fontName);
|
||||
int size = send(SCI_STYLEGETSIZE, style);
|
||||
bool italic = send(SCI_STYLEGETITALIC, style);
|
||||
int weight = send(SCI_STYLEGETBOLD, style) ? QFont::Bold : -1;
|
||||
return QFont(QString::fromUtf8(fontName, len), size, weight, italic);
|
||||
}
|
||||
|
||||
case Qt::ImCursorPosition:
|
||||
{
|
||||
int paraStart = sqt->pdoc->ParaUp(pos);
|
||||
return pos - paraStart;
|
||||
}
|
||||
|
||||
case Qt::ImSurroundingText:
|
||||
{
|
||||
int paraStart = sqt->pdoc->ParaUp(pos);
|
||||
int paraEnd = sqt->pdoc->ParaDown(pos);
|
||||
QVarLengthArray<char,1024> buffer(paraEnd - paraStart + 1);
|
||||
|
||||
Sci_CharacterRange charRange;
|
||||
charRange.cpMin = paraStart;
|
||||
charRange.cpMax = paraEnd;
|
||||
|
||||
Sci_TextRange textRange;
|
||||
textRange.chrg = charRange;
|
||||
textRange.lpstrText = buffer.data();
|
||||
|
||||
send(SCI_GETTEXTRANGE, 0, (sptr_t)&textRange);
|
||||
|
||||
return sqt->StringFromDocument(buffer.constData());
|
||||
}
|
||||
|
||||
case Qt::ImCurrentSelection:
|
||||
{
|
||||
QVarLengthArray<char,1024> buffer(send(SCI_GETSELTEXT));
|
||||
send(SCI_GETSELTEXT, 0, (sptr_t)buffer.data());
|
||||
|
||||
return sqt->StringFromDocument(buffer.constData());
|
||||
}
|
||||
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
void ScintillaEditBase::notifyParent(SCNotification scn)
|
||||
{
|
||||
emit notify(&scn);
|
||||
switch (scn.nmhdr.code) {
|
||||
case SCN_STYLENEEDED:
|
||||
emit styleNeeded(scn.position);
|
||||
break;
|
||||
|
||||
case SCN_CHARADDED:
|
||||
emit charAdded(scn.ch);
|
||||
break;
|
||||
|
||||
case SCN_SAVEPOINTREACHED:
|
||||
emit savePointChanged(false);
|
||||
break;
|
||||
|
||||
case SCN_SAVEPOINTLEFT:
|
||||
emit savePointChanged(true);
|
||||
break;
|
||||
|
||||
case SCN_MODIFYATTEMPTRO:
|
||||
emit modifyAttemptReadOnly();
|
||||
break;
|
||||
|
||||
case SCN_KEY:
|
||||
emit key(scn.ch);
|
||||
break;
|
||||
|
||||
case SCN_DOUBLECLICK:
|
||||
emit doubleClick(scn.position, scn.line);
|
||||
break;
|
||||
|
||||
case SCN_UPDATEUI:
|
||||
emit updateUi();
|
||||
break;
|
||||
|
||||
case SCN_MODIFIED:
|
||||
{
|
||||
bool added = scn.modificationType & SC_MOD_INSERTTEXT;
|
||||
bool deleted = scn.modificationType & SC_MOD_DELETETEXT;
|
||||
|
||||
int length = send(SCI_GETTEXTLENGTH);
|
||||
bool firstLineAdded = (added && length == 1) ||
|
||||
(deleted && length == 0);
|
||||
|
||||
if (scn.linesAdded != 0) {
|
||||
emit linesAdded(scn.linesAdded);
|
||||
} else if (firstLineAdded) {
|
||||
emit linesAdded(added ? 1 : -1);
|
||||
}
|
||||
|
||||
const QByteArray bytes = QByteArray::fromRawData(scn.text, scn.length);
|
||||
emit modified(scn.modificationType, scn.position, scn.length,
|
||||
scn.linesAdded, bytes, scn.line,
|
||||
scn.foldLevelNow, scn.foldLevelPrev);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCN_MACRORECORD:
|
||||
emit macroRecord(scn.message, scn.wParam, scn.lParam);
|
||||
break;
|
||||
|
||||
case SCN_MARGINCLICK:
|
||||
emit marginClicked(scn.position, scn.modifiers, scn.margin);
|
||||
break;
|
||||
|
||||
case SCN_NEEDSHOWN:
|
||||
emit needShown(scn.position, scn.length);
|
||||
break;
|
||||
|
||||
case SCN_PAINTED:
|
||||
emit painted();
|
||||
break;
|
||||
|
||||
case SCN_USERLISTSELECTION:
|
||||
emit userListSelection();
|
||||
break;
|
||||
|
||||
case SCN_URIDROPPED:
|
||||
emit uriDropped();
|
||||
break;
|
||||
|
||||
case SCN_DWELLSTART:
|
||||
emit dwellStart(scn.x, scn.y);
|
||||
break;
|
||||
|
||||
case SCN_DWELLEND:
|
||||
emit dwellEnd(scn.x, scn.y);
|
||||
break;
|
||||
|
||||
case SCN_ZOOM:
|
||||
emit zoom(send(SCI_GETZOOM));
|
||||
break;
|
||||
|
||||
case SCN_HOTSPOTCLICK:
|
||||
emit hotSpotClick(scn.position, scn.modifiers);
|
||||
break;
|
||||
|
||||
case SCN_HOTSPOTDOUBLECLICK:
|
||||
emit hotSpotDoubleClick(scn.position, scn.modifiers);
|
||||
break;
|
||||
|
||||
case SCN_CALLTIPCLICK:
|
||||
emit callTipClick();
|
||||
break;
|
||||
|
||||
case SCN_AUTOCSELECTION:
|
||||
emit autoCompleteSelection(scn.lParam, QString::fromUtf8(scn.text));
|
||||
break;
|
||||
|
||||
case SCN_AUTOCCANCELLED:
|
||||
emit autoCompleteCancelled();
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void ScintillaEditBase::event_command(uptr_t wParam, sptr_t lParam)
|
||||
{
|
||||
emit command(wParam, lParam);
|
||||
}
|
||||
133
third-party/scintilla/ScintillaEditBase.h
vendored
Normal file
133
third-party/scintilla/ScintillaEditBase.h
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
//
|
||||
// Copyright (c) 1990-2011, Scientific Toolworks, Inc.
|
||||
//
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
//
|
||||
// Author: Jason Haslam
|
||||
//
|
||||
// Additions Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware
|
||||
// ScintillaWidget.h - Qt widget that wraps ScintillaQt and provides events and scrolling
|
||||
|
||||
|
||||
#ifndef SCINTILLAEDITBASE_H
|
||||
#define SCINTILLAEDITBASE_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
class ScintillaQt;
|
||||
class SurfaceImpl;
|
||||
struct SCNotification;
|
||||
|
||||
class ScintillaEditBase : public QAbstractScrollArea {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScintillaEditBase(QWidget *parent = 0);
|
||||
virtual ~ScintillaEditBase();
|
||||
|
||||
virtual sptr_t send(
|
||||
unsigned int iMessage,
|
||||
uptr_t wParam = 0,
|
||||
sptr_t lParam = 0) const;
|
||||
|
||||
virtual sptr_t sends(
|
||||
unsigned int iMessage,
|
||||
uptr_t wParam = 0,
|
||||
const char *s = 0) const;
|
||||
|
||||
public slots:
|
||||
// Scroll events coming from GUI to be sent to Scintilla.
|
||||
void scrollHorizontal(int value);
|
||||
void scrollVertical(int value);
|
||||
|
||||
// Emit Scintilla notifications as signals.
|
||||
void notifyParent(SCNotification scn);
|
||||
void event_command(uptr_t wParam, sptr_t lParam);
|
||||
|
||||
signals:
|
||||
void horizontalScrolled(int value);
|
||||
void verticalScrolled(int value);
|
||||
void horizontalRangeChanged(int max, int page);
|
||||
void verticalRangeChanged(int max, int page);
|
||||
void notifyChange();
|
||||
void linesAdded(int linesAdded);
|
||||
|
||||
// Clients can use this hook to add additional
|
||||
// formats (e.g. rich text) to the MIME data.
|
||||
void aboutToCopy(QMimeData *data);
|
||||
|
||||
// Scintilla Notifications
|
||||
void styleNeeded(int position);
|
||||
void charAdded(int ch);
|
||||
void savePointChanged(bool dirty);
|
||||
void modifyAttemptReadOnly();
|
||||
void key(int key);
|
||||
void doubleClick(int position, int line);
|
||||
void updateUi();
|
||||
void modified(int type, int position, int length, int linesAdded,
|
||||
const QByteArray &text, int line, int foldNow, int foldPrev);
|
||||
void macroRecord(int message, uptr_t wParam, sptr_t lParam);
|
||||
void marginClicked(int position, int modifiers, int margin);
|
||||
void textAreaClicked(int line, int modifiers);
|
||||
void needShown(int position, int length);
|
||||
void painted();
|
||||
void userListSelection(); // Wants some args.
|
||||
void uriDropped(); // Wants some args.
|
||||
void dwellStart(int x, int y);
|
||||
void dwellEnd(int x, int y);
|
||||
void zoom(int zoom);
|
||||
void hotSpotClick(int position, int modifiers);
|
||||
void hotSpotDoubleClick(int position, int modifiers);
|
||||
void callTipClick();
|
||||
void autoCompleteSelection(int position, const QString &text);
|
||||
void autoCompleteCancelled();
|
||||
|
||||
// Base notifications for compatibility with other Scintilla implementations
|
||||
void notify(SCNotification *pscn);
|
||||
void command(uptr_t wParam, sptr_t lParam);
|
||||
|
||||
// GUI event notifications needed under Qt
|
||||
void buttonPressed(QMouseEvent *event);
|
||||
void buttonReleased(QMouseEvent *event);
|
||||
void keyPressed(QKeyEvent *event);
|
||||
void resized();
|
||||
|
||||
protected:
|
||||
virtual bool event(QEvent *event);
|
||||
virtual void paintEvent(QPaintEvent *event);
|
||||
virtual void wheelEvent(QWheelEvent *event);
|
||||
virtual void focusInEvent(QFocusEvent *event);
|
||||
virtual void focusOutEvent(QFocusEvent *event);
|
||||
virtual void resizeEvent(QResizeEvent *event);
|
||||
virtual void keyPressEvent(QKeyEvent *event);
|
||||
virtual void mousePressEvent(QMouseEvent *event);
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event);
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event);
|
||||
virtual void mouseMoveEvent(QMouseEvent *event);
|
||||
virtual void contextMenuEvent(QContextMenuEvent *event);
|
||||
virtual void dragEnterEvent(QDragEnterEvent *event);
|
||||
virtual void dragLeaveEvent(QDragLeaveEvent *event);
|
||||
virtual void dragMoveEvent(QDragMoveEvent *event);
|
||||
virtual void dropEvent(QDropEvent *event);
|
||||
virtual void inputMethodEvent(QInputMethodEvent *event);
|
||||
virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
|
||||
virtual void scrollContentsBy(int, int) {}
|
||||
|
||||
private:
|
||||
ScintillaQt *sqt;
|
||||
|
||||
QTime time;
|
||||
|
||||
int preeditPos;
|
||||
QString preeditString;
|
||||
|
||||
int wheelDelta;
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SCINTILLAEDITBASE_H */
|
||||
741
third-party/scintilla/ScintillaQt.cc
vendored
Normal file
741
third-party/scintilla/ScintillaQt.cc
vendored
Normal file
@@ -0,0 +1,741 @@
|
||||
//
|
||||
// Copyright (c) 1990-2011, Scientific Toolworks, Inc.
|
||||
//
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
//
|
||||
// Author: Jason Haslam
|
||||
//
|
||||
// Additions Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware
|
||||
// ScintillaQt.cpp - Qt specific subclass of ScintillaBase
|
||||
|
||||
#include "PlatQt.h"
|
||||
#include "ScintillaQt.h"
|
||||
#ifdef SCI_LEXER
|
||||
#include "LexerModule.h"
|
||||
#include "ExternalLexer.h"
|
||||
#endif
|
||||
|
||||
#include "../../VMProtect/moc/moc_ScintillaQt.cc"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
ScintillaQt::ScintillaQt(QAbstractScrollArea *parent)
|
||||
: QObject(parent), scrollArea(parent), vMax(0), hMax(0), vPage(0), hPage(0),
|
||||
haveMouseCapture(false), dragWasDropped(false)
|
||||
{
|
||||
|
||||
wMain = scrollArea->viewport();
|
||||
|
||||
// On OS X drawing text into a pixmap moves it around 1 pixel to
|
||||
// the right compared to drawing it directly onto a window.
|
||||
// Buffered drawing turned off by default to avoid this.
|
||||
WndProc(SCI_SETBUFFEREDDRAW, false, 0);
|
||||
|
||||
Initialise();
|
||||
}
|
||||
|
||||
ScintillaQt::~ScintillaQt()
|
||||
{
|
||||
SetTicking(false);
|
||||
SetIdle(false);
|
||||
}
|
||||
|
||||
void ScintillaQt::tick()
|
||||
{
|
||||
Tick();
|
||||
}
|
||||
|
||||
void ScintillaQt::execCommand(QAction *action)
|
||||
{
|
||||
int command = action->data().toInt();
|
||||
Command(command);
|
||||
}
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
static const QString sMSDEVColumnSelect("MSDEVColumnSelect");
|
||||
static const QString sWrappedMSDEVColumnSelect("application/x-qt-windows-mime;value=\"MSDEVColumnSelect\"");
|
||||
#elif defined(Q_OS_MAC)
|
||||
static const QString sScintillaRecPboardType("com.scintilla.utf16-plain-text.rectangular");
|
||||
static const QString sScintillaRecMimeType("text/x-scintilla.utf16-plain-text.rectangular");
|
||||
#else
|
||||
// Linux
|
||||
static const QString sMimeRectangularMarker("text/x-rectangular-marker");
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_MAC) && QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
||||
|
||||
class ScintillaRectangularMime : public QMacPasteboardMime {
|
||||
public:
|
||||
ScintillaRectangularMime() : QMacPasteboardMime(MIME_ALL) {
|
||||
}
|
||||
|
||||
QString convertorName() {
|
||||
return QString("ScintillaRectangularMime");
|
||||
}
|
||||
|
||||
bool canConvert(const QString &mime, QString flav) {
|
||||
return mimeFor(flav) == mime;
|
||||
}
|
||||
|
||||
QString mimeFor(QString flav) {
|
||||
if (flav == sScintillaRecPboardType)
|
||||
return sScintillaRecMimeType;
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString flavorFor(const QString &mime) {
|
||||
if (mime == sScintillaRecMimeType)
|
||||
return sScintillaRecPboardType;
|
||||
return QString();
|
||||
}
|
||||
|
||||
QVariant convertToMime(const QString & /* mime */, QList<QByteArray> data, QString /* flav */) {
|
||||
QByteArray all;
|
||||
foreach (QByteArray i, data) {
|
||||
all += i;
|
||||
}
|
||||
return QVariant(all);
|
||||
}
|
||||
|
||||
QList<QByteArray> convertFromMime(const QString & /* mime */, QVariant data, QString /* flav */) {
|
||||
QByteArray a = data.toByteArray();
|
||||
QList<QByteArray> l;
|
||||
l.append(a);
|
||||
return l;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// The Mime object registers itself but only want one for all Scintilla instances.
|
||||
// Should delete at exit to help memory leak detection but that would be extra work
|
||||
// and, since the clipboard exists after last Scintilla instance, may be complex.
|
||||
static ScintillaRectangularMime *singletonMime = 0;
|
||||
|
||||
#endif
|
||||
|
||||
void ScintillaQt::Initialise()
|
||||
{
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
||||
rectangularSelectionModifier = SCMOD_ALT;
|
||||
#else
|
||||
rectangularSelectionModifier = SCMOD_CTRL;
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_MAC) && QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
|
||||
if (!singletonMime) {
|
||||
singletonMime = new ScintillaRectangularMime();
|
||||
|
||||
QStringList slTypes(sScintillaRecPboardType);
|
||||
qRegisterDraggedTypes(slTypes);
|
||||
}
|
||||
#endif
|
||||
|
||||
connect(QApplication::clipboard(), SIGNAL(selectionChanged()),
|
||||
this, SLOT(SelectionChanged()));
|
||||
}
|
||||
|
||||
void ScintillaQt::Finalise()
|
||||
{
|
||||
SetTicking(false);
|
||||
ScintillaBase::Finalise();
|
||||
}
|
||||
|
||||
void ScintillaQt::SelectionChanged()
|
||||
{
|
||||
QClipboard *cb = QApplication::clipboard();
|
||||
if (!cb) return;
|
||||
|
||||
bool nowPrimary = cb->ownsSelection();
|
||||
if (nowPrimary != primarySelection) {
|
||||
primarySelection = nowPrimary;
|
||||
Redraw();
|
||||
}
|
||||
}
|
||||
|
||||
bool ScintillaQt::DragThreshold(Point ptStart, Point ptNow)
|
||||
{
|
||||
int xMove = abs(ptStart.x - ptNow.x);
|
||||
int yMove = abs(ptStart.y - ptNow.y);
|
||||
return (xMove > QApplication::startDragDistance()) ||
|
||||
(yMove > QApplication::startDragDistance());
|
||||
}
|
||||
|
||||
static QString StringFromSelectedText(const SelectionText &selectedText)
|
||||
{
|
||||
if (selectedText.codePage == SC_CP_UTF8) {
|
||||
return QString::fromUtf8(selectedText.Data(), static_cast<int>(selectedText.Length()));
|
||||
} else {
|
||||
QTextCodec *codec = QTextCodec::codecForName(
|
||||
CharacterSetID(selectedText.characterSet));
|
||||
return codec->toUnicode(selectedText.Data(), static_cast<int>(selectedText.Length()));
|
||||
}
|
||||
}
|
||||
|
||||
static void AddRectangularToMime(QMimeData *mimeData, QString su)
|
||||
{
|
||||
#if defined(Q_OS_WIN)
|
||||
// Add an empty marker
|
||||
mimeData->setData(sMSDEVColumnSelect, QByteArray());
|
||||
#elif defined(Q_OS_MAC)
|
||||
// OS X gets marker + data to work with other implementations.
|
||||
// Don't understand how this works but it does - the
|
||||
// clipboard format is supposed to be UTF-16, not UTF-8.
|
||||
mimeData->setData(sScintillaRecMimeType, su.toUtf8());
|
||||
#else
|
||||
Q_UNUSED(su);
|
||||
// Linux
|
||||
// Add an empty marker
|
||||
mimeData->setData(sMimeRectangularMarker, QByteArray());
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool IsRectangularInMime(const QMimeData *mimeData)
|
||||
{
|
||||
QStringList formats = mimeData->formats();
|
||||
for (int i = 0; i < formats.size(); ++i) {
|
||||
#if defined(Q_OS_WIN)
|
||||
// Windows rectangular markers
|
||||
// If rectangular copies made by this application, see base name.
|
||||
if (formats[i] == sMSDEVColumnSelect)
|
||||
return true;
|
||||
// Otherwise see wrapped name.
|
||||
if (formats[i] == sWrappedMSDEVColumnSelect)
|
||||
return true;
|
||||
#elif defined(Q_OS_MAC)
|
||||
if (formats[i] == sScintillaRecMimeType)
|
||||
return true;
|
||||
#else
|
||||
// Linux
|
||||
if (formats[i] == sMimeRectangularMarker)
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ScintillaQt::ValidCodePage(int codePage) const
|
||||
{
|
||||
return codePage == 0
|
||||
|| codePage == SC_CP_UTF8
|
||||
|| codePage == 932
|
||||
|| codePage == 936
|
||||
|| codePage == 949
|
||||
|| codePage == 950
|
||||
|| codePage == 1361;
|
||||
}
|
||||
|
||||
|
||||
void ScintillaQt::ScrollText(int linesToMove)
|
||||
{
|
||||
int dy = vs.lineHeight * (linesToMove);
|
||||
scrollArea->viewport()->scroll(0, dy);
|
||||
}
|
||||
|
||||
void ScintillaQt::SetVerticalScrollPos()
|
||||
{
|
||||
scrollArea->verticalScrollBar()->setValue(topLine);
|
||||
emit verticalScrolled(topLine);
|
||||
}
|
||||
|
||||
void ScintillaQt::SetHorizontalScrollPos()
|
||||
{
|
||||
scrollArea->horizontalScrollBar()->setValue(xOffset);
|
||||
emit horizontalScrolled(xOffset);
|
||||
}
|
||||
|
||||
bool ScintillaQt::ModifyScrollBars(int nMax, int nPage)
|
||||
{
|
||||
bool modified = false;
|
||||
|
||||
int vNewPage = nPage;
|
||||
int vNewMax = nMax - vNewPage + 1;
|
||||
if (vMax != vNewMax || vPage != vNewPage) {
|
||||
vMax = vNewMax;
|
||||
vPage = vNewPage;
|
||||
modified = true;
|
||||
|
||||
scrollArea->verticalScrollBar()->setMaximum(vMax);
|
||||
scrollArea->verticalScrollBar()->setPageStep(vPage);
|
||||
emit verticalRangeChanged(vMax, vPage);
|
||||
}
|
||||
|
||||
int hNewPage = GetTextRectangle().Width();
|
||||
int hNewMax = (scrollWidth > hNewPage) ? scrollWidth - hNewPage : 0;
|
||||
int charWidth = vs.styles[STYLE_DEFAULT].aveCharWidth;
|
||||
if (hMax != hNewMax || hPage != hNewPage ||
|
||||
scrollArea->horizontalScrollBar()->singleStep() != charWidth) {
|
||||
hMax = hNewMax;
|
||||
hPage = hNewPage;
|
||||
modified = true;
|
||||
|
||||
scrollArea->horizontalScrollBar()->setMaximum(hMax);
|
||||
scrollArea->horizontalScrollBar()->setPageStep(hPage);
|
||||
scrollArea->horizontalScrollBar()->setSingleStep(charWidth);
|
||||
emit horizontalRangeChanged(hMax, hPage);
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
void ScintillaQt::ReconfigureScrollBars()
|
||||
{
|
||||
if (verticalScrollBarVisible) {
|
||||
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
} else {
|
||||
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
}
|
||||
|
||||
if (horizontalScrollBarVisible && !Wrapping()) {
|
||||
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
|
||||
} else {
|
||||
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
}
|
||||
}
|
||||
|
||||
void ScintillaQt::CopyToModeClipboard(const SelectionText &selectedText, QClipboard::Mode clipboardMode_)
|
||||
{
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
if (clipboard) {
|
||||
clipboard->clear(clipboardMode_);
|
||||
QString su = StringFromSelectedText(selectedText);
|
||||
QMimeData *mimeData = new QMimeData();
|
||||
mimeData->setText(su);
|
||||
if (selectedText.rectangular) {
|
||||
AddRectangularToMime(mimeData, su);
|
||||
}
|
||||
|
||||
// Allow client code to add additional data (e.g rich text).
|
||||
emit aboutToCopy(mimeData);
|
||||
|
||||
clipboard->setMimeData(mimeData, clipboardMode_);
|
||||
}
|
||||
}
|
||||
|
||||
void ScintillaQt::Copy()
|
||||
{
|
||||
if (!sel.Empty()) {
|
||||
SelectionText st;
|
||||
CopySelectionRange(&st);
|
||||
CopyToClipboard(st);
|
||||
}
|
||||
}
|
||||
|
||||
void ScintillaQt::CopyToClipboard(const SelectionText &selectedText)
|
||||
{
|
||||
CopyToModeClipboard(selectedText, QClipboard::Clipboard);
|
||||
}
|
||||
|
||||
void ScintillaQt::PasteFromMode(QClipboard::Mode clipboardMode_)
|
||||
{
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
if (!clipboard) return;
|
||||
|
||||
const QMimeData *mimeData = clipboard->mimeData(clipboardMode_);
|
||||
bool isRectangular = mimeData && IsRectangularInMime(mimeData);
|
||||
QString text = clipboard->text(clipboardMode_);
|
||||
QByteArray utext = BytesForDocument(text);
|
||||
std::string dest(utext.constData(), utext.length());
|
||||
SelectionText selText;
|
||||
selText.Copy(dest, pdoc->dbcsCodePage, CharacterSetOfDocument(), isRectangular, false);
|
||||
|
||||
UndoGroup ug(pdoc);
|
||||
ClearSelection(multiPasteMode == SC_MULTIPASTE_EACH);
|
||||
InsertPasteShape(selText.Data(), static_cast<int>(selText.Length()),
|
||||
selText.rectangular ? pasteRectangular : pasteStream);
|
||||
EnsureCaretVisible();
|
||||
}
|
||||
|
||||
void ScintillaQt::Paste()
|
||||
{
|
||||
PasteFromMode(QClipboard::Clipboard);
|
||||
}
|
||||
|
||||
void ScintillaQt::ClaimSelection()
|
||||
{
|
||||
QClipboard *cb = QApplication::clipboard();
|
||||
|
||||
if (cb && cb->supportsSelection()) {
|
||||
// X Windows has a 'primary selection' as well as the clipboard.
|
||||
// Whenever the user selects some text, we become the primary selection
|
||||
if (!sel.Empty()) {
|
||||
primarySelection = true;
|
||||
SelectionText st;
|
||||
CopySelectionRange(&st);
|
||||
CopyToModeClipboard(st, QClipboard::Selection);
|
||||
} else {
|
||||
primarySelection = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScintillaQt::NotifyChange()
|
||||
{
|
||||
emit notifyChange();
|
||||
emit command(
|
||||
Platform::LongFromTwoShorts(GetCtrlID(), SCEN_CHANGE),
|
||||
reinterpret_cast<sptr_t>(wMain.GetID()));
|
||||
}
|
||||
|
||||
void ScintillaQt::NotifyFocus(bool focus)
|
||||
{
|
||||
emit command(
|
||||
Platform::LongFromTwoShorts
|
||||
(GetCtrlID(), focus ? SCEN_SETFOCUS : SCEN_KILLFOCUS),
|
||||
reinterpret_cast<sptr_t>(wMain.GetID()));
|
||||
|
||||
Editor::NotifyFocus(focus);
|
||||
}
|
||||
|
||||
void ScintillaQt::NotifyParent(SCNotification scn)
|
||||
{
|
||||
scn.nmhdr.hwndFrom = wMain.GetID();
|
||||
scn.nmhdr.idFrom = GetCtrlID();
|
||||
emit notifyParent(scn);
|
||||
}
|
||||
|
||||
void ScintillaQt::SetTicking(bool on)
|
||||
{
|
||||
QTimer *qTimer;
|
||||
if (timer.ticking != on) {
|
||||
timer.ticking = on;
|
||||
if (timer.ticking) {
|
||||
qTimer = new QTimer;
|
||||
connect(qTimer, SIGNAL(timeout()), this, SLOT(tick()));
|
||||
qTimer->start(timer.tickSize);
|
||||
timer.tickerID = qTimer;
|
||||
} else {
|
||||
qTimer = static_cast<QTimer *>(timer.tickerID);
|
||||
qTimer->stop();
|
||||
disconnect(qTimer, SIGNAL(timeout()), 0, 0);
|
||||
delete qTimer;
|
||||
timer.tickerID = 0;
|
||||
}
|
||||
}
|
||||
timer.ticksToWait = caret.period;
|
||||
}
|
||||
|
||||
void ScintillaQt::onIdle()
|
||||
{
|
||||
bool continueIdling = Idle();
|
||||
if (!continueIdling) {
|
||||
SetIdle(false);
|
||||
}
|
||||
}
|
||||
|
||||
bool ScintillaQt::SetIdle(bool on)
|
||||
{
|
||||
QTimer *qIdle;
|
||||
if (on) {
|
||||
// Start idler, if it's not running.
|
||||
if (!idler.state) {
|
||||
idler.state = true;
|
||||
qIdle = new QTimer;
|
||||
connect(qIdle, SIGNAL(timeout()), this, SLOT(onIdle()));
|
||||
qIdle->start(0);
|
||||
idler.idlerID = qIdle;
|
||||
}
|
||||
} else {
|
||||
// Stop idler, if it's running
|
||||
if (idler.state) {
|
||||
idler.state = false;
|
||||
qIdle = static_cast<QTimer *>(idler.idlerID);
|
||||
qIdle->stop();
|
||||
disconnect(qIdle, SIGNAL(timeout()), 0, 0);
|
||||
delete qIdle;
|
||||
idler.idlerID = 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int ScintillaQt::CharacterSetOfDocument() const
|
||||
{
|
||||
return vs.styles[STYLE_DEFAULT].characterSet;
|
||||
}
|
||||
|
||||
const char *ScintillaQt::CharacterSetIDOfDocument() const
|
||||
{
|
||||
return CharacterSetID(CharacterSetOfDocument());
|
||||
}
|
||||
|
||||
QString ScintillaQt::StringFromDocument(const char *s) const
|
||||
{
|
||||
if (IsUnicodeMode()) {
|
||||
return QString::fromUtf8(s);
|
||||
} else {
|
||||
QTextCodec *codec = QTextCodec::codecForName(
|
||||
CharacterSetID(CharacterSetOfDocument()));
|
||||
return codec->toUnicode(s);
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray ScintillaQt::BytesForDocument(const QString &text) const
|
||||
{
|
||||
if (IsUnicodeMode()) {
|
||||
return text.toUtf8();
|
||||
} else {
|
||||
QTextCodec *codec = QTextCodec::codecForName(
|
||||
CharacterSetID(CharacterSetOfDocument()));
|
||||
return codec ? codec->fromUnicode(text) : QByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class CaseFolderDBCS : public CaseFolderTable {
|
||||
QTextCodec *codec;
|
||||
public:
|
||||
CaseFolderDBCS(QTextCodec *codec_) : codec(codec_) {
|
||||
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 (codec) {
|
||||
QString su = codec->toUnicode(mixed, static_cast<int>(lenMixed));
|
||||
QString suFolded = su.toCaseFolded();
|
||||
QByteArray bytesFolded = codec->fromUnicode(suFolded);
|
||||
|
||||
if (bytesFolded.length() < static_cast<int>(sizeFolded)) {
|
||||
memcpy(folded, bytesFolded, bytesFolded.length());
|
||||
return bytesFolded.length();
|
||||
}
|
||||
}
|
||||
// Something failed so return a single NUL byte
|
||||
folded[0] = '\0';
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
CaseFolder *ScintillaQt::CaseFolderForEncoding()
|
||||
{
|
||||
if (pdoc->dbcsCodePage == SC_CP_UTF8) {
|
||||
return new CaseFolderUnicode();
|
||||
} else {
|
||||
const char *charSetBuffer = CharacterSetIDOfDocument();
|
||||
if (charSetBuffer) {
|
||||
if (pdoc->dbcsCodePage == 0) {
|
||||
CaseFolderTable *pcf = new CaseFolderTable();
|
||||
pcf->StandardASCII();
|
||||
QTextCodec *codec = QTextCodec::codecForName(charSetBuffer);
|
||||
// Only for single byte encodings
|
||||
for (int i=0x80; i<0x100; i++) {
|
||||
char sCharacter[2] = "A";
|
||||
sCharacter[0] = i;
|
||||
QString su = codec->toUnicode(sCharacter, 1);
|
||||
QString suFolded = su.toCaseFolded();
|
||||
QByteArray bytesFolded = codec->fromUnicode(suFolded);
|
||||
if (bytesFolded.length() == 1) {
|
||||
pcf->SetTranslation(sCharacter[0], bytesFolded[0]);
|
||||
}
|
||||
}
|
||||
return pcf;
|
||||
} else {
|
||||
return new CaseFolderDBCS(QTextCodec::codecForName(charSetBuffer));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string ScintillaQt::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;
|
||||
}
|
||||
|
||||
QTextCodec *codec = QTextCodec::codecForName(CharacterSetIDOfDocument());
|
||||
QString text = codec->toUnicode(s.c_str(), static_cast<int>(s.length()));
|
||||
|
||||
if (caseMapping == cmUpper) {
|
||||
text = text.toUpper();
|
||||
} else {
|
||||
text = text.toLower();
|
||||
}
|
||||
|
||||
QByteArray bytes = BytesForDocument(text);
|
||||
return std::string(bytes.data(), bytes.length());
|
||||
}
|
||||
|
||||
void ScintillaQt::SetMouseCapture(bool on)
|
||||
{
|
||||
// This is handled automatically by Qt
|
||||
if (mouseDownCaptures) {
|
||||
haveMouseCapture = on;
|
||||
}
|
||||
}
|
||||
|
||||
bool ScintillaQt::HaveMouseCapture()
|
||||
{
|
||||
return haveMouseCapture;
|
||||
}
|
||||
|
||||
void ScintillaQt::StartDrag()
|
||||
{
|
||||
inDragDrop = ddDragging;
|
||||
dropWentOutside = true;
|
||||
if (drag.Length()) {
|
||||
QMimeData *mimeData = new QMimeData;
|
||||
QString sText = StringFromSelectedText(drag);
|
||||
mimeData->setText(sText);
|
||||
if (drag.rectangular) {
|
||||
AddRectangularToMime(mimeData, sText);
|
||||
}
|
||||
// This QDrag is not freed as that causes a crash on Linux
|
||||
QDrag *dragon = new QDrag(scrollArea);
|
||||
dragon->setMimeData(mimeData);
|
||||
|
||||
Qt::DropAction dropAction = dragon->exec(Qt::CopyAction|Qt::MoveAction);
|
||||
if ((dropAction == Qt::MoveAction) && dropWentOutside) {
|
||||
// Remove dragged out text
|
||||
ClearSelection();
|
||||
}
|
||||
}
|
||||
inDragDrop = ddNone;
|
||||
SetDragPosition(SelectionPosition(invalidPosition));
|
||||
}
|
||||
|
||||
void ScintillaQt::CreateCallTipWindow(PRectangle rc)
|
||||
{
|
||||
|
||||
if (!ct.wCallTip.Created()) {
|
||||
QWidget *pCallTip = new QWidget(0, Qt::ToolTip);
|
||||
ct.wCallTip = pCallTip;
|
||||
pCallTip->move(rc.left, rc.top);
|
||||
pCallTip->resize(rc.Width(), rc.Height());
|
||||
}
|
||||
}
|
||||
|
||||
void ScintillaQt::AddToPopUp(const char *label,
|
||||
int cmd,
|
||||
bool enabled)
|
||||
{
|
||||
QMenu *menu = static_cast<QMenu *>(popup.GetID());
|
||||
QString text(label);
|
||||
|
||||
if (text.isEmpty()) {
|
||||
menu->addSeparator();
|
||||
} else {
|
||||
QAction *action = menu->addAction(text);
|
||||
action->setData(cmd);
|
||||
action->setEnabled(enabled);
|
||||
}
|
||||
|
||||
// Make sure the menu's signal is connected only once.
|
||||
menu->disconnect();
|
||||
connect(menu, SIGNAL(triggered(QAction *)),
|
||||
this, SLOT(execCommand(QAction *)));
|
||||
}
|
||||
|
||||
sptr_t ScintillaQt::WndProc(unsigned int message, uptr_t wParam, sptr_t lParam)
|
||||
{
|
||||
try {
|
||||
switch (message) {
|
||||
|
||||
case SCI_GRABFOCUS:
|
||||
scrollArea->setFocus(Qt::OtherFocusReason);
|
||||
break;
|
||||
|
||||
case SCI_GETDIRECTFUNCTION:
|
||||
return reinterpret_cast<sptr_t>(DirectFunction);
|
||||
|
||||
case SCI_GETDIRECTPOINTER:
|
||||
return reinterpret_cast<sptr_t>(this);
|
||||
|
||||
#ifdef SCI_LEXER
|
||||
case SCI_LOADLEXERLIBRARY:
|
||||
LexerManager::GetInstance()->Load(reinterpret_cast<const char *>(lParam));
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return ScintillaBase::WndProc(message, wParam, lParam);
|
||||
}
|
||||
} catch (std::bad_alloc &) {
|
||||
errorStatus = SC_STATUS_BADALLOC;
|
||||
} catch (...) {
|
||||
errorStatus = SC_STATUS_FAILURE;
|
||||
}
|
||||
return 0l;
|
||||
}
|
||||
|
||||
sptr_t ScintillaQt::DefWndProc(unsigned int, uptr_t, sptr_t)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
sptr_t ScintillaQt::DirectFunction(
|
||||
ScintillaQt *sciThis, unsigned int iMessage, uptr_t wParam, sptr_t lParam)
|
||||
{
|
||||
return sciThis->WndProc(iMessage, wParam, lParam);
|
||||
}
|
||||
|
||||
// Additions to merge in Scientific Toolworks widget structure
|
||||
|
||||
void ScintillaQt::PartialPaint(const PRectangle &rect)
|
||||
{
|
||||
rcPaint = rect;
|
||||
paintState = painting;
|
||||
PRectangle rcClient = GetClientRectangle();
|
||||
paintingAllText = rcPaint.Contains(rcClient);
|
||||
|
||||
AutoSurface surface(this);
|
||||
Paint(surface, rcPaint);
|
||||
surface->Release();
|
||||
|
||||
if (paintState == paintAbandoned) {
|
||||
// FIXME_later: Failure to paint the requested rectangle in each
|
||||
// paint event causes flicker on some platforms (Mac?)
|
||||
// Paint rect immediately.
|
||||
paintState = painting;
|
||||
paintingAllText = true;
|
||||
|
||||
AutoSurface surface(this);
|
||||
Paint(surface, rcPaint);
|
||||
surface->Release();
|
||||
|
||||
// Queue a full repaint.
|
||||
scrollArea->viewport()->update();
|
||||
}
|
||||
|
||||
paintState = notPainting;
|
||||
}
|
||||
|
||||
void ScintillaQt::DragEnter(const Point &point)
|
||||
{
|
||||
SetDragPosition(SPositionFromLocation(point,
|
||||
false, false, UserVirtualSpace()));
|
||||
}
|
||||
|
||||
void ScintillaQt::DragMove(const Point &point)
|
||||
{
|
||||
SetDragPosition(SPositionFromLocation(point,
|
||||
false, false, UserVirtualSpace()));
|
||||
}
|
||||
|
||||
void ScintillaQt::DragLeave()
|
||||
{
|
||||
SetDragPosition(SelectionPosition(invalidPosition));
|
||||
}
|
||||
|
||||
void ScintillaQt::Drop(const Point &point, const QMimeData *data, bool move)
|
||||
{
|
||||
QString text = data->text();
|
||||
bool rectangular = IsRectangularInMime(data);
|
||||
QByteArray bytes = BytesForDocument(text);
|
||||
int len = bytes.length();
|
||||
|
||||
SelectionPosition movePos = SPositionFromLocation(point,
|
||||
false, false, UserVirtualSpace());
|
||||
|
||||
DropAt(movePos, bytes, len, move, rectangular);
|
||||
}
|
||||
144
third-party/scintilla/ScintillaQt.h
vendored
Normal file
144
third-party/scintilla/ScintillaQt.h
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
//
|
||||
// Copyright (c) 1990-2011, Scientific Toolworks, Inc.
|
||||
//
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
//
|
||||
// Author: Jason Haslam
|
||||
//
|
||||
// Additions Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware
|
||||
// ScintillaQt.h - Qt specific subclass of ScintillaBase
|
||||
|
||||
#ifndef SCINTILLAQT_H
|
||||
#define SCINTILLAQT_H
|
||||
|
||||
#include "Scintilla.h"
|
||||
#include "Platform.h"
|
||||
#include "ILexer.h"
|
||||
#include "SplitVector.h"
|
||||
#include "Partitioning.h"
|
||||
#include "RunStyles.h"
|
||||
#include "ContractionState.h"
|
||||
#include "CellBuffer.h"
|
||||
#include "CallTip.h"
|
||||
#include "KeyMap.h"
|
||||
#include "Indicator.h"
|
||||
#include "XPM.h"
|
||||
#include "LineMarker.h"
|
||||
#include "Style.h"
|
||||
#include "AutoComplete.h"
|
||||
#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"
|
||||
#include "PropSetSimple.h"
|
||||
#endif
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
class ScintillaQt : public QObject, public ScintillaBase {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ScintillaQt(QAbstractScrollArea *parent);
|
||||
virtual ~ScintillaQt();
|
||||
|
||||
signals:
|
||||
void horizontalScrolled(int value);
|
||||
void verticalScrolled(int value);
|
||||
void horizontalRangeChanged(int max, int page);
|
||||
void verticalRangeChanged(int max, int page);
|
||||
|
||||
void notifyParent(SCNotification scn);
|
||||
void notifyChange();
|
||||
|
||||
// Clients can use this hook to add additional
|
||||
// formats (e.g. rich text) to the MIME data.
|
||||
void aboutToCopy(QMimeData *data);
|
||||
|
||||
void command(uptr_t wParam, sptr_t lParam);
|
||||
|
||||
private slots:
|
||||
void tick();
|
||||
void onIdle();
|
||||
void execCommand(QAction *action);
|
||||
void SelectionChanged();
|
||||
|
||||
private:
|
||||
virtual void Initialise();
|
||||
virtual void Finalise();
|
||||
virtual bool DragThreshold(Point ptStart, Point ptNow);
|
||||
virtual bool ValidCodePage(int codePage) const;
|
||||
|
||||
private:
|
||||
virtual void ScrollText(int linesToMove);
|
||||
virtual void SetVerticalScrollPos();
|
||||
virtual void SetHorizontalScrollPos();
|
||||
virtual bool ModifyScrollBars(int nMax, int nPage);
|
||||
virtual void ReconfigureScrollBars();
|
||||
void CopyToModeClipboard(const SelectionText &selectedText, QClipboard::Mode clipboardMode_);
|
||||
virtual void Copy();
|
||||
virtual void CopyToClipboard(const SelectionText &selectedText);
|
||||
void PasteFromMode(QClipboard::Mode clipboardMode_);
|
||||
virtual void Paste();
|
||||
virtual void ClaimSelection();
|
||||
virtual void NotifyChange();
|
||||
virtual void NotifyFocus(bool focus);
|
||||
virtual void NotifyParent(SCNotification scn);
|
||||
virtual void SetTicking(bool on);
|
||||
virtual bool SetIdle(bool on);
|
||||
virtual void SetMouseCapture(bool on);
|
||||
virtual bool HaveMouseCapture();
|
||||
virtual void StartDrag();
|
||||
int CharacterSetOfDocument() const;
|
||||
const char *CharacterSetIDOfDocument() const;
|
||||
QString StringFromDocument(const char *s) const;
|
||||
QByteArray BytesForDocument(const QString &text) const;
|
||||
virtual CaseFolder *CaseFolderForEncoding();
|
||||
virtual std::string CaseMapString(const std::string &s, int caseMapping);
|
||||
|
||||
virtual void CreateCallTipWindow(PRectangle rc);
|
||||
virtual void AddToPopUp(const char *label, int cmd = 0, bool enabled = true);
|
||||
virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
|
||||
virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
|
||||
|
||||
static sptr_t DirectFunction(ScintillaQt *sciThis,
|
||||
unsigned int iMessage, uptr_t wParam, sptr_t lParam);
|
||||
|
||||
protected:
|
||||
|
||||
void PartialPaint(const PRectangle &rect);
|
||||
|
||||
void DragEnter(const Point &point);
|
||||
void DragMove(const Point &point);
|
||||
void DragLeave();
|
||||
void Drop(const Point &point, const QMimeData *data, bool move);
|
||||
|
||||
private:
|
||||
QAbstractScrollArea *scrollArea;
|
||||
|
||||
int vMax, hMax; // Scroll bar maximums.
|
||||
int vPage, hPage; // Scroll bar page sizes.
|
||||
|
||||
bool haveMouseCapture;
|
||||
bool dragWasDropped;
|
||||
int rectangularSelectionModifier;
|
||||
|
||||
friend class ScintillaEditBase;
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SCINTILLAQT_H
|
||||
51
third-party/scintilla/ScintillaWidget.h
vendored
Normal file
51
third-party/scintilla/ScintillaWidget.h
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
/* Scintilla source code edit control */
|
||||
/** @file ScintillaWidget.h
|
||||
** Definition of Scintilla widget for GTK+.
|
||||
** Only needed by GTK+ code but is harmless on other platforms.
|
||||
**/
|
||||
/* Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
|
||||
* The License.txt file describes the conditions under which this software may be distributed. */
|
||||
|
||||
#ifndef SCINTILLAWIDGET_H
|
||||
#define SCINTILLAWIDGET_H
|
||||
|
||||
#if defined(GTK)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SCINTILLA(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, scintilla_get_type (), ScintillaObject)
|
||||
#define SCINTILLA_CLASS(klass) G_TYPE_CHECK_CLASS_CAST (klass, scintilla_get_type (), ScintillaClass)
|
||||
#define IS_SCINTILLA(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, scintilla_get_type ())
|
||||
|
||||
typedef struct _ScintillaObject ScintillaObject;
|
||||
typedef struct _ScintillaClass ScintillaClass;
|
||||
|
||||
struct _ScintillaObject {
|
||||
GtkContainer cont;
|
||||
void *pscin;
|
||||
};
|
||||
|
||||
struct _ScintillaClass {
|
||||
GtkContainerClass parent_class;
|
||||
|
||||
void (* command) (ScintillaObject *ttt);
|
||||
void (* notify) (ScintillaObject *ttt);
|
||||
};
|
||||
|
||||
GType scintilla_get_type (void);
|
||||
GtkWidget* scintilla_new (void);
|
||||
void scintilla_set_id (ScintillaObject *sci, uptr_t id);
|
||||
sptr_t scintilla_send_message (ScintillaObject *sci,unsigned int iMessage, uptr_t wParam, sptr_t lParam);
|
||||
void scintilla_release_resources(void);
|
||||
|
||||
#define SCINTILLA_NOTIFY "sci-notify"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
398
third-party/scintilla/Selection.cxx
vendored
Normal file
398
third-party/scintilla/Selection.cxx
vendored
Normal file
@@ -0,0 +1,398 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file Selection.cxx
|
||||
** Classes maintaining the selection.
|
||||
**/
|
||||
// Copyright 2009 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
|
||||
#include "Selection.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
void SelectionPosition::MoveForInsertDelete(bool insertion, int startChange, int length) {
|
||||
if (insertion) {
|
||||
if (position == startChange) {
|
||||
int virtualLengthRemove = std::min(length, virtualSpace);
|
||||
virtualSpace -= virtualLengthRemove;
|
||||
position += virtualLengthRemove;
|
||||
} else if (position > startChange) {
|
||||
position += length;
|
||||
}
|
||||
} else {
|
||||
if (position == startChange) {
|
||||
virtualSpace = 0;
|
||||
}
|
||||
if (position > startChange) {
|
||||
int endDeletion = startChange + length;
|
||||
if (position > endDeletion) {
|
||||
position -= length;
|
||||
} else {
|
||||
position = startChange;
|
||||
virtualSpace = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SelectionPosition::operator <(const SelectionPosition &other) const {
|
||||
if (position == other.position)
|
||||
return virtualSpace < other.virtualSpace;
|
||||
else
|
||||
return position < other.position;
|
||||
}
|
||||
|
||||
bool SelectionPosition::operator >(const SelectionPosition &other) const {
|
||||
if (position == other.position)
|
||||
return virtualSpace > other.virtualSpace;
|
||||
else
|
||||
return position > other.position;
|
||||
}
|
||||
|
||||
bool SelectionPosition::operator <=(const SelectionPosition &other) const {
|
||||
if (position == other.position && virtualSpace == other.virtualSpace)
|
||||
return true;
|
||||
else
|
||||
return other > *this;
|
||||
}
|
||||
|
||||
bool SelectionPosition::operator >=(const SelectionPosition &other) const {
|
||||
if (position == other.position && virtualSpace == other.virtualSpace)
|
||||
return true;
|
||||
else
|
||||
return *this > other;
|
||||
}
|
||||
|
||||
int SelectionRange::Length() const {
|
||||
if (anchor > caret) {
|
||||
return anchor.Position() - caret.Position();
|
||||
} else {
|
||||
return caret.Position() - anchor.Position();
|
||||
}
|
||||
}
|
||||
|
||||
bool SelectionRange::Contains(int pos) const {
|
||||
if (anchor > caret)
|
||||
return (pos >= caret.Position()) && (pos <= anchor.Position());
|
||||
else
|
||||
return (pos >= anchor.Position()) && (pos <= caret.Position());
|
||||
}
|
||||
|
||||
bool SelectionRange::Contains(SelectionPosition sp) const {
|
||||
if (anchor > caret)
|
||||
return (sp >= caret) && (sp <= anchor);
|
||||
else
|
||||
return (sp >= anchor) && (sp <= caret);
|
||||
}
|
||||
|
||||
bool SelectionRange::ContainsCharacter(int posCharacter) const {
|
||||
if (anchor > caret)
|
||||
return (posCharacter >= caret.Position()) && (posCharacter < anchor.Position());
|
||||
else
|
||||
return (posCharacter >= anchor.Position()) && (posCharacter < caret.Position());
|
||||
}
|
||||
|
||||
SelectionSegment SelectionRange::Intersect(SelectionSegment check) const {
|
||||
SelectionSegment inOrder(caret, anchor);
|
||||
if ((inOrder.start <= check.end) || (inOrder.end >= check.start)) {
|
||||
SelectionSegment portion = check;
|
||||
if (portion.start < inOrder.start)
|
||||
portion.start = inOrder.start;
|
||||
if (portion.end > inOrder.end)
|
||||
portion.end = inOrder.end;
|
||||
if (portion.start > portion.end)
|
||||
return SelectionSegment();
|
||||
else
|
||||
return portion;
|
||||
} else {
|
||||
return SelectionSegment();
|
||||
}
|
||||
}
|
||||
|
||||
bool SelectionRange::Trim(SelectionRange range) {
|
||||
SelectionPosition startRange = range.Start();
|
||||
SelectionPosition endRange = range.End();
|
||||
SelectionPosition start = Start();
|
||||
SelectionPosition end = End();
|
||||
PLATFORM_ASSERT(start <= end);
|
||||
PLATFORM_ASSERT(startRange <= endRange);
|
||||
if ((startRange <= end) && (endRange >= start)) {
|
||||
if ((start > startRange) && (end < endRange)) {
|
||||
// Completely covered by range -> empty at start
|
||||
end = start;
|
||||
} else if ((start < startRange) && (end > endRange)) {
|
||||
// Completely covers range -> empty at start
|
||||
end = start;
|
||||
} else if (start <= startRange) {
|
||||
// Trim end
|
||||
end = startRange;
|
||||
} else { //
|
||||
PLATFORM_ASSERT(end >= endRange);
|
||||
// Trim start
|
||||
start = endRange;
|
||||
}
|
||||
if (anchor > caret) {
|
||||
caret = start;
|
||||
anchor = end;
|
||||
} else {
|
||||
anchor = start;
|
||||
caret = end;
|
||||
}
|
||||
return Empty();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If range is all virtual collapse to start of virtual space
|
||||
void SelectionRange::MinimizeVirtualSpace() {
|
||||
if (caret.Position() == anchor.Position()) {
|
||||
int virtualSpace = caret.VirtualSpace();
|
||||
if (virtualSpace > anchor.VirtualSpace())
|
||||
virtualSpace = anchor.VirtualSpace();
|
||||
caret.SetVirtualSpace(virtualSpace);
|
||||
anchor.SetVirtualSpace(virtualSpace);
|
||||
}
|
||||
}
|
||||
|
||||
Selection::Selection() : mainRange(0), moveExtends(false), tentativeMain(false), selType(selStream) {
|
||||
AddSelection(SelectionRange(SelectionPosition(0)));
|
||||
}
|
||||
|
||||
Selection::~Selection() {
|
||||
}
|
||||
|
||||
bool Selection::IsRectangular() const {
|
||||
return (selType == selRectangle) || (selType == selThin);
|
||||
}
|
||||
|
||||
int Selection::MainCaret() const {
|
||||
return ranges[mainRange].caret.Position();
|
||||
}
|
||||
|
||||
int Selection::MainAnchor() const {
|
||||
return ranges[mainRange].anchor.Position();
|
||||
}
|
||||
|
||||
SelectionRange &Selection::Rectangular() {
|
||||
return rangeRectangular;
|
||||
}
|
||||
|
||||
SelectionSegment Selection::Limits() const {
|
||||
if (ranges.empty()) {
|
||||
return SelectionSegment();
|
||||
} else {
|
||||
SelectionSegment sr(ranges[0].anchor, ranges[0].caret);
|
||||
for (size_t i=1; i<ranges.size(); i++) {
|
||||
sr.Extend(ranges[i].anchor);
|
||||
sr.Extend(ranges[i].caret);
|
||||
}
|
||||
return sr;
|
||||
}
|
||||
}
|
||||
|
||||
SelectionSegment Selection::LimitsForRectangularElseMain() const {
|
||||
if (IsRectangular()) {
|
||||
return Limits();
|
||||
} else {
|
||||
return SelectionSegment(ranges[mainRange].caret, ranges[mainRange].anchor);
|
||||
}
|
||||
}
|
||||
|
||||
size_t Selection::Count() const {
|
||||
return ranges.size();
|
||||
}
|
||||
|
||||
size_t Selection::Main() const {
|
||||
return mainRange;
|
||||
}
|
||||
|
||||
void Selection::SetMain(size_t r) {
|
||||
PLATFORM_ASSERT(r < ranges.size());
|
||||
mainRange = r;
|
||||
}
|
||||
|
||||
SelectionRange &Selection::Range(size_t r) {
|
||||
return ranges[r];
|
||||
}
|
||||
|
||||
SelectionRange &Selection::RangeMain() {
|
||||
return ranges[mainRange];
|
||||
}
|
||||
|
||||
SelectionPosition Selection::Start() const {
|
||||
if (IsRectangular()) {
|
||||
return rangeRectangular.Start();
|
||||
} else {
|
||||
return ranges[mainRange].Start();
|
||||
}
|
||||
}
|
||||
|
||||
bool Selection::MoveExtends() const {
|
||||
return moveExtends;
|
||||
}
|
||||
|
||||
void Selection::SetMoveExtends(bool moveExtends_) {
|
||||
moveExtends = moveExtends_;
|
||||
}
|
||||
|
||||
bool Selection::Empty() const {
|
||||
for (size_t i=0; i<ranges.size(); i++) {
|
||||
if (!ranges[i].Empty())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SelectionPosition Selection::Last() const {
|
||||
SelectionPosition lastPosition;
|
||||
for (size_t i=0; i<ranges.size(); i++) {
|
||||
if (lastPosition < ranges[i].caret)
|
||||
lastPosition = ranges[i].caret;
|
||||
if (lastPosition < ranges[i].anchor)
|
||||
lastPosition = ranges[i].anchor;
|
||||
}
|
||||
return lastPosition;
|
||||
}
|
||||
|
||||
int Selection::Length() const {
|
||||
int len = 0;
|
||||
for (size_t i=0; i<ranges.size(); i++) {
|
||||
len += ranges[i].Length();
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void Selection::MovePositions(bool insertion, int startChange, int length) {
|
||||
for (size_t i=0; i<ranges.size(); i++) {
|
||||
ranges[i].caret.MoveForInsertDelete(insertion, startChange, length);
|
||||
ranges[i].anchor.MoveForInsertDelete(insertion, startChange, length);
|
||||
}
|
||||
}
|
||||
|
||||
void Selection::TrimSelection(SelectionRange range) {
|
||||
for (size_t i=0; i<ranges.size();) {
|
||||
if ((i != mainRange) && (ranges[i].Trim(range))) {
|
||||
// Trimmed to empty so remove
|
||||
for (size_t j=i; j<ranges.size()-1; j++) {
|
||||
ranges[j] = ranges[j+1];
|
||||
if (j == mainRange-1)
|
||||
mainRange--;
|
||||
}
|
||||
ranges.pop_back();
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Selection::SetSelection(SelectionRange range) {
|
||||
ranges.clear();
|
||||
ranges.push_back(range);
|
||||
mainRange = ranges.size() - 1;
|
||||
}
|
||||
|
||||
void Selection::AddSelection(SelectionRange range) {
|
||||
TrimSelection(range);
|
||||
ranges.push_back(range);
|
||||
mainRange = ranges.size() - 1;
|
||||
}
|
||||
|
||||
void Selection::AddSelectionWithoutTrim(SelectionRange range) {
|
||||
ranges.push_back(range);
|
||||
mainRange = ranges.size() - 1;
|
||||
}
|
||||
|
||||
void Selection::DropSelection(size_t r) {
|
||||
if ((ranges.size() > 1) && (r < ranges.size())) {
|
||||
size_t mainNew = mainRange;
|
||||
if (mainNew >= r) {
|
||||
if (mainNew == 0) {
|
||||
mainNew = ranges.size() - 2;
|
||||
} else {
|
||||
mainNew--;
|
||||
}
|
||||
}
|
||||
ranges.erase(ranges.begin() + r);
|
||||
mainRange = mainNew;
|
||||
}
|
||||
}
|
||||
|
||||
void Selection::TentativeSelection(SelectionRange range) {
|
||||
if (!tentativeMain) {
|
||||
rangesSaved = ranges;
|
||||
}
|
||||
ranges = rangesSaved;
|
||||
AddSelection(range);
|
||||
TrimSelection(ranges[mainRange]);
|
||||
tentativeMain = true;
|
||||
}
|
||||
|
||||
void Selection::CommitTentative() {
|
||||
rangesSaved.clear();
|
||||
tentativeMain = false;
|
||||
}
|
||||
|
||||
int Selection::CharacterInSelection(int posCharacter) const {
|
||||
for (size_t i=0; i<ranges.size(); i++) {
|
||||
if (ranges[i].ContainsCharacter(posCharacter))
|
||||
return i == mainRange ? 1 : 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Selection::InSelectionForEOL(int pos) const {
|
||||
for (size_t i=0; i<ranges.size(); i++) {
|
||||
if (!ranges[i].Empty() && (pos > ranges[i].Start().Position()) && (pos <= ranges[i].End().Position()))
|
||||
return i == mainRange ? 1 : 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Selection::VirtualSpaceFor(int pos) const {
|
||||
int virtualSpace = 0;
|
||||
for (size_t i=0; i<ranges.size(); i++) {
|
||||
if ((ranges[i].caret.Position() == pos) && (virtualSpace < ranges[i].caret.VirtualSpace()))
|
||||
virtualSpace = ranges[i].caret.VirtualSpace();
|
||||
if ((ranges[i].anchor.Position() == pos) && (virtualSpace < ranges[i].anchor.VirtualSpace()))
|
||||
virtualSpace = ranges[i].anchor.VirtualSpace();
|
||||
}
|
||||
return virtualSpace;
|
||||
}
|
||||
|
||||
void Selection::Clear() {
|
||||
ranges.clear();
|
||||
ranges.push_back(SelectionRange());
|
||||
mainRange = ranges.size() - 1;
|
||||
selType = selStream;
|
||||
moveExtends = false;
|
||||
ranges[mainRange].Reset();
|
||||
rangeRectangular.Reset();
|
||||
}
|
||||
|
||||
void Selection::RemoveDuplicates() {
|
||||
for (size_t i=0; i<ranges.size()-1; i++) {
|
||||
if (ranges[i].Empty()) {
|
||||
size_t j=i+1;
|
||||
while (j<ranges.size()) {
|
||||
if (ranges[i] == ranges[j]) {
|
||||
ranges.erase(ranges.begin() + j);
|
||||
if (mainRange >= j)
|
||||
mainRange--;
|
||||
} else {
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Selection::RotateMain() {
|
||||
mainRange = (mainRange + 1) % ranges.size();
|
||||
}
|
||||
|
||||
190
third-party/scintilla/Selection.h
vendored
Normal file
190
third-party/scintilla/Selection.h
vendored
Normal file
@@ -0,0 +1,190 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file Selection.h
|
||||
** Classes maintaining the selection.
|
||||
**/
|
||||
// Copyright 2009 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef SELECTION_H
|
||||
#define SELECTION_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
class SelectionPosition {
|
||||
int position;
|
||||
int virtualSpace;
|
||||
public:
|
||||
explicit SelectionPosition(int position_=INVALID_POSITION, int virtualSpace_=0) : position(position_), virtualSpace(virtualSpace_) {
|
||||
PLATFORM_ASSERT(virtualSpace < 800000);
|
||||
if (virtualSpace < 0)
|
||||
virtualSpace = 0;
|
||||
}
|
||||
void Reset() {
|
||||
position = 0;
|
||||
virtualSpace = 0;
|
||||
}
|
||||
void MoveForInsertDelete(bool insertion, int startChange, int length);
|
||||
bool operator ==(const SelectionPosition &other) const {
|
||||
return position == other.position && virtualSpace == other.virtualSpace;
|
||||
}
|
||||
bool operator <(const SelectionPosition &other) const;
|
||||
bool operator >(const SelectionPosition &other) const;
|
||||
bool operator <=(const SelectionPosition &other) const;
|
||||
bool operator >=(const SelectionPosition &other) const;
|
||||
int Position() const {
|
||||
return position;
|
||||
}
|
||||
void SetPosition(int position_) {
|
||||
position = position_;
|
||||
virtualSpace = 0;
|
||||
}
|
||||
int VirtualSpace() const {
|
||||
return virtualSpace;
|
||||
}
|
||||
void SetVirtualSpace(int virtualSpace_) {
|
||||
PLATFORM_ASSERT(virtualSpace_ < 800000);
|
||||
if (virtualSpace_ >= 0)
|
||||
virtualSpace = virtualSpace_;
|
||||
}
|
||||
void Add(int increment) {
|
||||
position = position + increment;
|
||||
}
|
||||
bool IsValid() const {
|
||||
return position >= 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Ordered range to make drawing simpler
|
||||
struct SelectionSegment {
|
||||
SelectionPosition start;
|
||||
SelectionPosition end;
|
||||
SelectionSegment() : start(), end() {
|
||||
}
|
||||
SelectionSegment(SelectionPosition a, SelectionPosition b) {
|
||||
if (a < b) {
|
||||
start = a;
|
||||
end = b;
|
||||
} else {
|
||||
start = b;
|
||||
end = a;
|
||||
}
|
||||
}
|
||||
bool Empty() const {
|
||||
return start == end;
|
||||
}
|
||||
void Extend(SelectionPosition p) {
|
||||
if (start > p)
|
||||
start = p;
|
||||
if (end < p)
|
||||
end = p;
|
||||
}
|
||||
};
|
||||
|
||||
struct SelectionRange {
|
||||
SelectionPosition caret;
|
||||
SelectionPosition anchor;
|
||||
|
||||
SelectionRange() : caret(), anchor() {
|
||||
}
|
||||
explicit SelectionRange(SelectionPosition single) : caret(single), anchor(single) {
|
||||
}
|
||||
explicit SelectionRange(int single) : caret(single), anchor(single) {
|
||||
}
|
||||
SelectionRange(SelectionPosition caret_, SelectionPosition anchor_) : caret(caret_), anchor(anchor_) {
|
||||
}
|
||||
SelectionRange(int caret_, int anchor_) : caret(caret_), anchor(anchor_) {
|
||||
}
|
||||
bool Empty() const {
|
||||
return anchor == caret;
|
||||
}
|
||||
int Length() const;
|
||||
// int Width() const; // Like Length but takes virtual space into account
|
||||
bool operator ==(const SelectionRange &other) const {
|
||||
return caret == other.caret && anchor == other.anchor;
|
||||
}
|
||||
bool operator <(const SelectionRange &other) const {
|
||||
return caret < other.caret || ((caret == other.caret) && (anchor < other.anchor));
|
||||
}
|
||||
void Reset() {
|
||||
anchor.Reset();
|
||||
caret.Reset();
|
||||
}
|
||||
void ClearVirtualSpace() {
|
||||
anchor.SetVirtualSpace(0);
|
||||
caret.SetVirtualSpace(0);
|
||||
}
|
||||
bool Contains(int pos) const;
|
||||
bool Contains(SelectionPosition sp) const;
|
||||
bool ContainsCharacter(int posCharacter) const;
|
||||
SelectionSegment Intersect(SelectionSegment check) const;
|
||||
SelectionPosition Start() const {
|
||||
return (anchor < caret) ? anchor : caret;
|
||||
}
|
||||
SelectionPosition End() const {
|
||||
return (anchor < caret) ? caret : anchor;
|
||||
}
|
||||
bool Trim(SelectionRange range);
|
||||
// If range is all virtual collapse to start of virtual space
|
||||
void MinimizeVirtualSpace();
|
||||
};
|
||||
|
||||
class Selection {
|
||||
std::vector<SelectionRange> ranges;
|
||||
std::vector<SelectionRange> rangesSaved;
|
||||
SelectionRange rangeRectangular;
|
||||
size_t mainRange;
|
||||
bool moveExtends;
|
||||
bool tentativeMain;
|
||||
public:
|
||||
enum selTypes { noSel, selStream, selRectangle, selLines, selThin };
|
||||
selTypes selType;
|
||||
|
||||
Selection();
|
||||
~Selection();
|
||||
bool IsRectangular() const;
|
||||
int MainCaret() const;
|
||||
int MainAnchor() const;
|
||||
SelectionRange &Rectangular();
|
||||
SelectionSegment Limits() const;
|
||||
// This is for when you want to move the caret in response to a
|
||||
// user direction command - for rectangular selections, use the range
|
||||
// that covers all selected text otherwise return the main selection.
|
||||
SelectionSegment LimitsForRectangularElseMain() const;
|
||||
size_t Count() const;
|
||||
size_t Main() const;
|
||||
void SetMain(size_t r);
|
||||
SelectionRange &Range(size_t r);
|
||||
SelectionRange &RangeMain();
|
||||
SelectionPosition Start() const;
|
||||
bool MoveExtends() const;
|
||||
void SetMoveExtends(bool moveExtends_);
|
||||
bool Empty() const;
|
||||
SelectionPosition Last() const;
|
||||
int Length() const;
|
||||
void MovePositions(bool insertion, int startChange, int length);
|
||||
void TrimSelection(SelectionRange range);
|
||||
void SetSelection(SelectionRange range);
|
||||
void AddSelection(SelectionRange range);
|
||||
void AddSelectionWithoutTrim(SelectionRange range);
|
||||
void DropSelection(size_t r);
|
||||
void TentativeSelection(SelectionRange range);
|
||||
void CommitTentative();
|
||||
int CharacterInSelection(int posCharacter) const;
|
||||
int InSelectionForEOL(int pos) const;
|
||||
int VirtualSpaceFor(int pos) const;
|
||||
void Clear();
|
||||
void RemoveDuplicates();
|
||||
void RotateMain();
|
||||
bool Tentative() const { return tentativeMain; }
|
||||
std::vector<SelectionRange> RangesCopy() const {
|
||||
return ranges;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
110
third-party/scintilla/SparseState.h
vendored
Normal file
110
third-party/scintilla/SparseState.h
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file SparseState.h
|
||||
** Hold lexer state that may change rarely.
|
||||
** This is often per-line state such as whether a particular type of section has been entered.
|
||||
** A state continues until it is changed.
|
||||
**/
|
||||
// Copyright 2011 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef SPARSESTATE_H
|
||||
#define SPARSESTATE_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
class SparseState {
|
||||
struct State {
|
||||
int position;
|
||||
T value;
|
||||
State(int position_, T value_) : position(position_), value(value_) {
|
||||
}
|
||||
inline bool operator<(const State &other) const {
|
||||
return position < other.position;
|
||||
}
|
||||
inline bool operator==(const State &other) const {
|
||||
return (position == other.position) && (value == other.value);
|
||||
}
|
||||
};
|
||||
int positionFirst;
|
||||
typedef std::vector<State> stateVector;
|
||||
stateVector states;
|
||||
|
||||
typename stateVector::iterator Find(int position) {
|
||||
State searchValue(position, T());
|
||||
return std::lower_bound(states.begin(), states.end(), searchValue);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit SparseState(int positionFirst_=-1) {
|
||||
positionFirst = positionFirst_;
|
||||
}
|
||||
void Set(int position, T value) {
|
||||
Delete(position);
|
||||
if (states.empty() || (value != states[states.size()-1].value)) {
|
||||
states.push_back(State(position, value));
|
||||
}
|
||||
}
|
||||
T ValueAt(int position) {
|
||||
if (states.empty())
|
||||
return T();
|
||||
if (position < states[0].position)
|
||||
return T();
|
||||
typename stateVector::iterator low = Find(position);
|
||||
if (low == states.end()) {
|
||||
return states[states.size()-1].value;
|
||||
} else {
|
||||
if (low->position > position) {
|
||||
--low;
|
||||
}
|
||||
return low->value;
|
||||
}
|
||||
}
|
||||
bool Delete(int position) {
|
||||
typename stateVector::iterator low = Find(position);
|
||||
if (low != states.end()) {
|
||||
states.erase(low, states.end());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
size_t size() const {
|
||||
return states.size();
|
||||
}
|
||||
|
||||
// Returns true if Merge caused a significant change
|
||||
bool Merge(const SparseState<T> &other, int ignoreAfter) {
|
||||
// Changes caused beyond ignoreAfter are not significant
|
||||
Delete(ignoreAfter+1);
|
||||
|
||||
bool different = true;
|
||||
bool changed = false;
|
||||
typename stateVector::iterator low = Find(other.positionFirst);
|
||||
if (static_cast<size_t>(states.end() - low) == other.states.size()) {
|
||||
// Same number in other as after positionFirst in this
|
||||
different = !std::equal(low, states.end(), other.states.begin());
|
||||
}
|
||||
if (different) {
|
||||
if (low != states.end()) {
|
||||
states.erase(low, states.end());
|
||||
changed = true;
|
||||
}
|
||||
typename stateVector::const_iterator startOther = other.states.begin();
|
||||
if (!states.empty() && !other.states.empty() && states.back().value == startOther->value)
|
||||
++startOther;
|
||||
if (startOther != other.states.end()) {
|
||||
states.insert(states.end(), startOther, other.states.end());
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
291
third-party/scintilla/SplitVector.h
vendored
Normal file
291
third-party/scintilla/SplitVector.h
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file SplitVector.h
|
||||
** Main data structure for holding arrays that handle insertions
|
||||
** and deletions efficiently.
|
||||
**/
|
||||
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef SPLITVECTOR_H
|
||||
#define SPLITVECTOR_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
class SplitVector {
|
||||
protected:
|
||||
T *body;
|
||||
int size;
|
||||
int lengthBody;
|
||||
int part1Length;
|
||||
int gapLength; /// invariant: gapLength == size - lengthBody
|
||||
int growSize;
|
||||
|
||||
/// Move the gap to a particular position so that insertion and
|
||||
/// deletion at that point will not require much copying and
|
||||
/// hence be fast.
|
||||
void GapTo(int position) {
|
||||
if (position != part1Length) {
|
||||
if (position < part1Length) {
|
||||
memmove(
|
||||
body + position + gapLength,
|
||||
body + position,
|
||||
sizeof(T) * (part1Length - position));
|
||||
} else { // position > part1Length
|
||||
memmove(
|
||||
body + part1Length,
|
||||
body + part1Length + gapLength,
|
||||
sizeof(T) * (position - part1Length));
|
||||
}
|
||||
part1Length = position;
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that there is room in the buffer for an insertion,
|
||||
/// reallocating if more space needed.
|
||||
void RoomFor(int insertionLength) {
|
||||
if (gapLength <= insertionLength) {
|
||||
while (growSize < size / 6)
|
||||
growSize *= 2;
|
||||
ReAllocate(size + insertionLength + growSize);
|
||||
}
|
||||
}
|
||||
|
||||
void Init() {
|
||||
body = NULL;
|
||||
growSize = 8;
|
||||
size = 0;
|
||||
lengthBody = 0;
|
||||
part1Length = 0;
|
||||
gapLength = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
/// Construct a split buffer.
|
||||
SplitVector() {
|
||||
Init();
|
||||
}
|
||||
|
||||
~SplitVector() {
|
||||
delete []body;
|
||||
body = 0;
|
||||
}
|
||||
|
||||
int GetGrowSize() const {
|
||||
return growSize;
|
||||
}
|
||||
|
||||
void SetGrowSize(int growSize_) {
|
||||
growSize = growSize_;
|
||||
}
|
||||
|
||||
/// Reallocate the storage for the buffer to be newSize and
|
||||
/// copy exisiting contents to the new buffer.
|
||||
/// Must not be used to decrease the size of the buffer.
|
||||
void ReAllocate(int newSize) {
|
||||
if (newSize > size) {
|
||||
// Move the gap to the end
|
||||
GapTo(lengthBody);
|
||||
T *newBody = new T[newSize];
|
||||
if ((size != 0) && (body != 0)) {
|
||||
memmove(newBody, body, sizeof(T) * lengthBody);
|
||||
delete []body;
|
||||
}
|
||||
body = newBody;
|
||||
gapLength += newSize - size;
|
||||
size = newSize;
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve the character at a particular position.
|
||||
/// Retrieving positions outside the range of the buffer returns 0.
|
||||
/// The assertions here are disabled since calling code can be
|
||||
/// simpler if out of range access works and returns 0.
|
||||
T ValueAt(int position) const {
|
||||
if (position < part1Length) {
|
||||
//PLATFORM_ASSERT(position >= 0);
|
||||
if (position < 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return body[position];
|
||||
}
|
||||
} else {
|
||||
//PLATFORM_ASSERT(position < lengthBody);
|
||||
if (position >= lengthBody) {
|
||||
return 0;
|
||||
} else {
|
||||
return body[gapLength + position];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetValueAt(int position, T v) {
|
||||
if (position < part1Length) {
|
||||
PLATFORM_ASSERT(position >= 0);
|
||||
if (position < 0) {
|
||||
;
|
||||
} else {
|
||||
body[position] = v;
|
||||
}
|
||||
} else {
|
||||
PLATFORM_ASSERT(position < lengthBody);
|
||||
if (position >= lengthBody) {
|
||||
;
|
||||
} else {
|
||||
body[gapLength + position] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
T &operator[](int position) const {
|
||||
PLATFORM_ASSERT(position >= 0 && position < lengthBody);
|
||||
if (position < part1Length) {
|
||||
return body[position];
|
||||
} else {
|
||||
return body[gapLength + position];
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve the length of the buffer.
|
||||
int Length() const {
|
||||
return lengthBody;
|
||||
}
|
||||
|
||||
/// Insert a single value into the buffer.
|
||||
/// Inserting at positions outside the current range fails.
|
||||
void Insert(int position, T v) {
|
||||
PLATFORM_ASSERT((position >= 0) && (position <= lengthBody));
|
||||
if ((position < 0) || (position > lengthBody)) {
|
||||
return;
|
||||
}
|
||||
RoomFor(1);
|
||||
GapTo(position);
|
||||
body[part1Length] = v;
|
||||
lengthBody++;
|
||||
part1Length++;
|
||||
gapLength--;
|
||||
}
|
||||
|
||||
/// Insert a number of elements into the buffer setting their value.
|
||||
/// Inserting at positions outside the current range fails.
|
||||
void InsertValue(int position, int insertLength, T v) {
|
||||
PLATFORM_ASSERT((position >= 0) && (position <= lengthBody));
|
||||
if (insertLength > 0) {
|
||||
if ((position < 0) || (position > lengthBody)) {
|
||||
return;
|
||||
}
|
||||
RoomFor(insertLength);
|
||||
GapTo(position);
|
||||
std::fill(&body[part1Length], &body[part1Length + insertLength], v);
|
||||
lengthBody += insertLength;
|
||||
part1Length += insertLength;
|
||||
gapLength -= insertLength;
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensure at least length elements allocated,
|
||||
/// appending zero valued elements if needed.
|
||||
void EnsureLength(int wantedLength) {
|
||||
if (Length() < wantedLength) {
|
||||
InsertValue(Length(), wantedLength - Length(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert text into the buffer from an array.
|
||||
void InsertFromArray(int positionToInsert, const T s[], int positionFrom, int insertLength) {
|
||||
PLATFORM_ASSERT((positionToInsert >= 0) && (positionToInsert <= lengthBody));
|
||||
if (insertLength > 0) {
|
||||
if ((positionToInsert < 0) || (positionToInsert > lengthBody)) {
|
||||
return;
|
||||
}
|
||||
RoomFor(insertLength);
|
||||
GapTo(positionToInsert);
|
||||
memmove(body + part1Length, s + positionFrom, sizeof(T) * insertLength);
|
||||
lengthBody += insertLength;
|
||||
part1Length += insertLength;
|
||||
gapLength -= insertLength;
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete one element from the buffer.
|
||||
void Delete(int position) {
|
||||
PLATFORM_ASSERT((position >= 0) && (position < lengthBody));
|
||||
if ((position < 0) || (position >= lengthBody)) {
|
||||
return;
|
||||
}
|
||||
DeleteRange(position, 1);
|
||||
}
|
||||
|
||||
/// Delete a range from the buffer.
|
||||
/// Deleting positions outside the current range fails.
|
||||
void DeleteRange(int position, int deleteLength) {
|
||||
PLATFORM_ASSERT((position >= 0) && (position + deleteLength <= lengthBody));
|
||||
if ((position < 0) || ((position + deleteLength) > lengthBody)) {
|
||||
return;
|
||||
}
|
||||
if ((position == 0) && (deleteLength == lengthBody)) {
|
||||
// Full deallocation returns storage and is faster
|
||||
delete []body;
|
||||
Init();
|
||||
} else if (deleteLength > 0) {
|
||||
GapTo(position);
|
||||
lengthBody -= deleteLength;
|
||||
gapLength += deleteLength;
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete all the buffer contents.
|
||||
void DeleteAll() {
|
||||
DeleteRange(0, lengthBody);
|
||||
}
|
||||
|
||||
// Retrieve a range of elements into an array
|
||||
void GetRange(T *buffer, int position, int retrieveLength) const {
|
||||
// Split into up to 2 ranges, before and after the split then use memcpy on each.
|
||||
int range1Length = 0;
|
||||
if (position < part1Length) {
|
||||
int part1AfterPosition = part1Length - position;
|
||||
range1Length = retrieveLength;
|
||||
if (range1Length > part1AfterPosition)
|
||||
range1Length = part1AfterPosition;
|
||||
}
|
||||
memcpy(buffer, body + position, range1Length * sizeof(T));
|
||||
buffer += range1Length;
|
||||
position = position + range1Length + gapLength;
|
||||
int range2Length = retrieveLength - range1Length;
|
||||
memcpy(buffer, body + position, range2Length * sizeof(T));
|
||||
}
|
||||
|
||||
T *BufferPointer() {
|
||||
RoomFor(1);
|
||||
GapTo(lengthBody);
|
||||
body[lengthBody] = 0;
|
||||
return body;
|
||||
}
|
||||
|
||||
T *RangePointer(int position, int rangeLength) {
|
||||
if (position < part1Length) {
|
||||
if ((position + rangeLength) > part1Length) {
|
||||
// Range overlaps gap, so move gap to start of range.
|
||||
GapTo(position);
|
||||
return body + position + gapLength;
|
||||
} else {
|
||||
return body + position ;
|
||||
}
|
||||
} else {
|
||||
return body + position + gapLength;
|
||||
}
|
||||
}
|
||||
|
||||
int GapPosition() const {
|
||||
return part1Length;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
36
third-party/scintilla/StringCopy.h
vendored
Normal file
36
third-party/scintilla/StringCopy.h
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file StringCopy.h
|
||||
** Safe string copy function which always NUL terminates.
|
||||
** ELEMENTS macro for determining array sizes.
|
||||
**/
|
||||
// Copyright 2013 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef STRINGCOPY_H
|
||||
#define STRINGCOPY_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
// Safer version of string copy functions like strcpy, wcsncpy, etc.
|
||||
// Instantiate over fixed length strings of both char and wchar_t.
|
||||
// May truncate if source doesn't fit into dest with room for NUL.
|
||||
|
||||
template <typename T, size_t count>
|
||||
void StringCopy(T (&dest)[count], const T* source) {
|
||||
for (size_t i=0; i<count; i++) {
|
||||
dest[i] = source[i];
|
||||
if (!source[i])
|
||||
break;
|
||||
}
|
||||
dest[count-1] = 0;
|
||||
}
|
||||
|
||||
#define ELEMENTS(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
164
third-party/scintilla/Style.cxx
vendored
Normal file
164
third-party/scintilla/Style.cxx
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file Style.cxx
|
||||
** Defines the font and colour style for a class of text.
|
||||
**/
|
||||
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
#include "Style.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
FontAlias::FontAlias() {
|
||||
}
|
||||
|
||||
FontAlias::~FontAlias() {
|
||||
SetID(0);
|
||||
// ~Font will not release the actual font resource since it is now 0
|
||||
}
|
||||
|
||||
void FontAlias::MakeAlias(Font &fontOrigin) {
|
||||
SetID(fontOrigin.GetID());
|
||||
}
|
||||
|
||||
void FontAlias::ClearFont() {
|
||||
SetID(0);
|
||||
}
|
||||
|
||||
bool FontSpecification::operator==(const FontSpecification &other) const {
|
||||
return fontName == other.fontName &&
|
||||
weight == other.weight &&
|
||||
italic == other.italic &&
|
||||
size == other.size &&
|
||||
characterSet == other.characterSet &&
|
||||
extraFontFlag == other.extraFontFlag;
|
||||
}
|
||||
|
||||
bool FontSpecification::operator<(const FontSpecification &other) const {
|
||||
if (fontName != other.fontName)
|
||||
return fontName < other.fontName;
|
||||
if (weight != other.weight)
|
||||
return weight < other.weight;
|
||||
if (italic != other.italic)
|
||||
return italic == false;
|
||||
if (size != other.size)
|
||||
return size < other.size;
|
||||
if (characterSet != other.characterSet)
|
||||
return characterSet < other.characterSet;
|
||||
if (extraFontFlag != other.extraFontFlag)
|
||||
return extraFontFlag < other.extraFontFlag;
|
||||
return false;
|
||||
}
|
||||
|
||||
FontMeasurements::FontMeasurements() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void FontMeasurements::Clear() {
|
||||
ascent = 1;
|
||||
descent = 1;
|
||||
aveCharWidth = 1;
|
||||
spaceWidth = 1;
|
||||
sizeZoomed = 2;
|
||||
}
|
||||
|
||||
Style::Style() : FontSpecification() {
|
||||
Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
|
||||
Platform::DefaultFontSize() * SC_FONT_SIZE_MULTIPLIER, 0, SC_CHARSET_DEFAULT,
|
||||
SC_WEIGHT_NORMAL, false, false, false, caseMixed, true, true, false);
|
||||
}
|
||||
|
||||
Style::Style(const Style &source) : FontSpecification(), FontMeasurements() {
|
||||
Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
|
||||
0, 0, 0,
|
||||
SC_WEIGHT_NORMAL, false, false, false, caseMixed, true, true, false);
|
||||
fore = source.fore;
|
||||
back = source.back;
|
||||
characterSet = source.characterSet;
|
||||
weight = source.weight;
|
||||
italic = source.italic;
|
||||
size = source.size;
|
||||
fontName = source.fontName;
|
||||
eolFilled = source.eolFilled;
|
||||
underline = source.underline;
|
||||
caseForce = source.caseForce;
|
||||
visible = source.visible;
|
||||
changeable = source.changeable;
|
||||
hotspot = source.hotspot;
|
||||
}
|
||||
|
||||
Style::~Style() {
|
||||
}
|
||||
|
||||
Style &Style::operator=(const Style &source) {
|
||||
if (this == &source)
|
||||
return * this;
|
||||
Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff),
|
||||
0, 0, SC_CHARSET_DEFAULT,
|
||||
SC_WEIGHT_NORMAL, false, false, false, caseMixed, true, true, false);
|
||||
fore = source.fore;
|
||||
back = source.back;
|
||||
characterSet = source.characterSet;
|
||||
weight = source.weight;
|
||||
italic = source.italic;
|
||||
size = source.size;
|
||||
fontName = source.fontName;
|
||||
eolFilled = source.eolFilled;
|
||||
underline = source.underline;
|
||||
caseForce = source.caseForce;
|
||||
visible = source.visible;
|
||||
changeable = source.changeable;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Style::Clear(ColourDesired fore_, ColourDesired back_, int size_,
|
||||
const char *fontName_, int characterSet_,
|
||||
int weight_, bool italic_, bool eolFilled_,
|
||||
bool underline_, ecaseForced caseForce_,
|
||||
bool visible_, bool changeable_, bool hotspot_) {
|
||||
fore = fore_;
|
||||
back = back_;
|
||||
characterSet = characterSet_;
|
||||
weight = weight_;
|
||||
italic = italic_;
|
||||
size = size_;
|
||||
fontName = fontName_;
|
||||
eolFilled = eolFilled_;
|
||||
underline = underline_;
|
||||
caseForce = caseForce_;
|
||||
visible = visible_;
|
||||
changeable = changeable_;
|
||||
hotspot = hotspot_;
|
||||
font.ClearFont();
|
||||
FontMeasurements::Clear();
|
||||
}
|
||||
|
||||
void Style::ClearTo(const Style &source) {
|
||||
Clear(
|
||||
source.fore,
|
||||
source.back,
|
||||
source.size,
|
||||
source.fontName,
|
||||
source.characterSet,
|
||||
source.weight,
|
||||
source.italic,
|
||||
source.eolFilled,
|
||||
source.underline,
|
||||
source.caseForce,
|
||||
source.visible,
|
||||
source.changeable,
|
||||
source.hotspot);
|
||||
}
|
||||
|
||||
void Style::Copy(Font &font_, const FontMeasurements &fm_) {
|
||||
font.MakeAlias(font_);
|
||||
#if PLAT_WX
|
||||
font.SetAscent(fm_.ascent);
|
||||
#endif
|
||||
(FontMeasurements &)(*this) = fm_;
|
||||
}
|
||||
91
third-party/scintilla/Style.h
vendored
Normal file
91
third-party/scintilla/Style.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file Style.h
|
||||
** Defines the font and colour style for a class of text.
|
||||
**/
|
||||
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef STYLE_H
|
||||
#define STYLE_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
struct FontSpecification {
|
||||
const char *fontName;
|
||||
int weight;
|
||||
bool italic;
|
||||
int size;
|
||||
int characterSet;
|
||||
int extraFontFlag;
|
||||
FontSpecification() :
|
||||
fontName(0),
|
||||
weight(SC_WEIGHT_NORMAL),
|
||||
italic(false),
|
||||
size(10 * SC_FONT_SIZE_MULTIPLIER),
|
||||
characterSet(0),
|
||||
extraFontFlag(0) {
|
||||
}
|
||||
bool operator==(const FontSpecification &other) const;
|
||||
bool operator<(const FontSpecification &other) const;
|
||||
};
|
||||
|
||||
// Just like Font but only has a copy of the FontID so should not delete it
|
||||
class FontAlias : public Font {
|
||||
// Private so FontAlias objects can not be copied
|
||||
FontAlias(const FontAlias &);
|
||||
FontAlias &operator=(const FontAlias &);
|
||||
public:
|
||||
FontAlias();
|
||||
virtual ~FontAlias();
|
||||
void MakeAlias(Font &fontOrigin);
|
||||
void ClearFont();
|
||||
};
|
||||
|
||||
struct FontMeasurements {
|
||||
unsigned int ascent;
|
||||
unsigned int descent;
|
||||
XYPOSITION aveCharWidth;
|
||||
XYPOSITION spaceWidth;
|
||||
int sizeZoomed;
|
||||
FontMeasurements();
|
||||
void Clear();
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class Style : public FontSpecification, public FontMeasurements {
|
||||
public:
|
||||
ColourDesired fore;
|
||||
ColourDesired back;
|
||||
bool eolFilled;
|
||||
bool underline;
|
||||
enum ecaseForced {caseMixed, caseUpper, caseLower};
|
||||
ecaseForced caseForce;
|
||||
bool visible;
|
||||
bool changeable;
|
||||
bool hotspot;
|
||||
|
||||
FontAlias font;
|
||||
|
||||
Style();
|
||||
Style(const Style &source);
|
||||
~Style();
|
||||
Style &operator=(const Style &source);
|
||||
void Clear(ColourDesired fore_, ColourDesired back_,
|
||||
int size_,
|
||||
const char *fontName_, int characterSet_,
|
||||
int weight_, bool italic_, bool eolFilled_,
|
||||
bool underline_, ecaseForced caseForce_,
|
||||
bool visible_, bool changeable_, bool hotspot_);
|
||||
void ClearTo(const Style &source);
|
||||
void Copy(Font &font_, const FontMeasurements &fm_);
|
||||
bool IsProtected() const { return !(changeable && visible);}
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
50
third-party/scintilla/StyleContext.cxx
vendored
Normal file
50
third-party/scintilla/StyleContext.cxx
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file StyleContext.cxx
|
||||
** Lexer infrastructure.
|
||||
**/
|
||||
// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
|
||||
// This file is in the public domain.
|
||||
|
||||
#include "ILexer.h"
|
||||
|
||||
#include "LexAccessor.h"
|
||||
#include "Accessor.h"
|
||||
#include "StyleContext.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
static void getRange(unsigned int start,
|
||||
unsigned int end,
|
||||
LexAccessor &styler,
|
||||
char *s,
|
||||
unsigned int len) {
|
||||
unsigned int i = 0;
|
||||
while ((i < end - start + 1) && (i < len-1)) {
|
||||
s[i] = styler[start + i];
|
||||
i++;
|
||||
}
|
||||
s[i] = '\0';
|
||||
}
|
||||
|
||||
void StyleContext::GetCurrent(char *s, unsigned int len) {
|
||||
getRange(styler.GetStartSegment(), currentPos - 1, styler, s, len);
|
||||
}
|
||||
|
||||
static void getRangeLowered(unsigned int start,
|
||||
unsigned int end,
|
||||
LexAccessor &styler,
|
||||
char *s,
|
||||
unsigned int len) {
|
||||
unsigned int i = 0;
|
||||
while ((i < end - start + 1) && (i < len-1)) {
|
||||
s[i] = static_cast<char>(tolower(styler[start + i]));
|
||||
i++;
|
||||
}
|
||||
s[i] = '\0';
|
||||
}
|
||||
|
||||
void StyleContext::GetCurrentLowered(char *s, unsigned int len) {
|
||||
getRangeLowered(styler.GetStartSegment(), currentPos - 1, styler, s, len);
|
||||
}
|
||||
232
third-party/scintilla/StyleContext.h
vendored
Normal file
232
third-party/scintilla/StyleContext.h
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file StyleContext.h
|
||||
** Lexer infrastructure.
|
||||
**/
|
||||
// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
|
||||
// This file is in the public domain.
|
||||
|
||||
#ifndef STYLECONTEXT_H
|
||||
#define STYLECONTEXT_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
static inline int MakeLowerCase(int ch) {
|
||||
if (ch < 'A' || ch > 'Z')
|
||||
return ch;
|
||||
else
|
||||
return ch - 'A' + 'a';
|
||||
}
|
||||
|
||||
// All languages handled so far can treat all characters >= 0x80 as one class
|
||||
// which just continues the current token or starts an identifier if in default.
|
||||
// DBCS treated specially as the second character can be < 0x80 and hence
|
||||
// syntactically significant. UTF-8 avoids this as all trail bytes are >= 0x80
|
||||
class StyleContext {
|
||||
LexAccessor &styler;
|
||||
IDocumentWithLineEnd *multiByteAccess;
|
||||
unsigned int endPos;
|
||||
unsigned int lengthDocument;
|
||||
|
||||
// Used for optimizing GetRelativeCharacter
|
||||
unsigned int posRelative;
|
||||
unsigned int currentPosLastRelative;
|
||||
int offsetRelative;
|
||||
|
||||
StyleContext(const StyleContext &src);
|
||||
StyleContext &operator=(const StyleContext &);
|
||||
|
||||
void GetNextChar() {
|
||||
if (multiByteAccess) {
|
||||
chNext = multiByteAccess->GetCharacterAndWidth(currentPos+width, &widthNext);
|
||||
} else {
|
||||
chNext = static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+width, 0));
|
||||
widthNext = 1;
|
||||
}
|
||||
// End of line determined from line end position, allowing CR, LF,
|
||||
// CRLF and Unicode line ends as set by document.
|
||||
if (currentLine < lineDocEnd)
|
||||
atLineEnd = static_cast<int>(currentPos) >= (lineStartNext-1);
|
||||
else // Last line
|
||||
atLineEnd = static_cast<int>(currentPos) >= lineStartNext;
|
||||
}
|
||||
|
||||
public:
|
||||
unsigned int currentPos;
|
||||
int currentLine;
|
||||
int lineDocEnd;
|
||||
int lineStartNext;
|
||||
bool atLineStart;
|
||||
bool atLineEnd;
|
||||
int state;
|
||||
int chPrev;
|
||||
int ch;
|
||||
int width;
|
||||
int chNext;
|
||||
int widthNext;
|
||||
|
||||
StyleContext(unsigned int startPos, unsigned int length,
|
||||
int initStyle, LexAccessor &styler_, char chMask=31) :
|
||||
styler(styler_),
|
||||
multiByteAccess(0),
|
||||
endPos(startPos + length),
|
||||
posRelative(0),
|
||||
currentPosLastRelative(0x7FFFFFFF),
|
||||
offsetRelative(0),
|
||||
currentPos(startPos),
|
||||
currentLine(-1),
|
||||
lineStartNext(-1),
|
||||
atLineEnd(false),
|
||||
state(initStyle & chMask), // Mask off all bits which aren't in the chMask.
|
||||
chPrev(0),
|
||||
ch(0),
|
||||
width(0),
|
||||
chNext(0),
|
||||
widthNext(1) {
|
||||
if (styler.Encoding() != enc8bit) {
|
||||
multiByteAccess = styler.MultiByteAccess();
|
||||
}
|
||||
styler.StartAt(startPos, chMask);
|
||||
styler.StartSegment(startPos);
|
||||
currentLine = styler.GetLine(startPos);
|
||||
lineStartNext = styler.LineStart(currentLine+1);
|
||||
lengthDocument = static_cast<unsigned int>(styler.Length());
|
||||
if (endPos == lengthDocument)
|
||||
endPos++;
|
||||
lineDocEnd = styler.GetLine(lengthDocument);
|
||||
atLineStart = static_cast<unsigned int>(styler.LineStart(currentLine)) == startPos;
|
||||
|
||||
// Variable width is now 0 so GetNextChar gets the char at currentPos into chNext/widthNext
|
||||
width = 0;
|
||||
GetNextChar();
|
||||
ch = chNext;
|
||||
width = widthNext;
|
||||
|
||||
GetNextChar();
|
||||
}
|
||||
void Complete() {
|
||||
styler.ColourTo(currentPos - ((currentPos > lengthDocument) ? 2 : 1), state);
|
||||
styler.Flush();
|
||||
}
|
||||
bool More() const {
|
||||
return currentPos < endPos;
|
||||
}
|
||||
void Forward() {
|
||||
if (currentPos < endPos) {
|
||||
atLineStart = atLineEnd;
|
||||
if (atLineStart) {
|
||||
currentLine++;
|
||||
lineStartNext = styler.LineStart(currentLine+1);
|
||||
}
|
||||
chPrev = ch;
|
||||
currentPos += width;
|
||||
ch = chNext;
|
||||
width = widthNext;
|
||||
GetNextChar();
|
||||
} else {
|
||||
atLineStart = false;
|
||||
chPrev = ' ';
|
||||
ch = ' ';
|
||||
chNext = ' ';
|
||||
atLineEnd = true;
|
||||
}
|
||||
}
|
||||
void Forward(int nb) {
|
||||
for (int i = 0; i < nb; i++) {
|
||||
Forward();
|
||||
}
|
||||
}
|
||||
void ForwardBytes(int nb) {
|
||||
size_t forwardPos = currentPos + nb;
|
||||
while (forwardPos > currentPos) {
|
||||
Forward();
|
||||
}
|
||||
}
|
||||
void ChangeState(int state_) {
|
||||
state = state_;
|
||||
}
|
||||
void SetState(int state_) {
|
||||
styler.ColourTo(currentPos - ((currentPos > lengthDocument) ? 2 : 1), state);
|
||||
state = state_;
|
||||
}
|
||||
void ForwardSetState(int state_) {
|
||||
Forward();
|
||||
styler.ColourTo(currentPos - ((currentPos > lengthDocument) ? 2 : 1), state);
|
||||
state = state_;
|
||||
}
|
||||
int LengthCurrent() const {
|
||||
return currentPos - styler.GetStartSegment();
|
||||
}
|
||||
int GetRelative(int n) {
|
||||
return static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n, 0));
|
||||
}
|
||||
int GetRelativeCharacter(int n) {
|
||||
if (n == 0)
|
||||
return ch;
|
||||
if (multiByteAccess) {
|
||||
if ((currentPosLastRelative != currentPos) ||
|
||||
((n > 0) && ((offsetRelative < 0) || (n < offsetRelative))) ||
|
||||
((n < 0) && ((offsetRelative > 0) || (n > offsetRelative)))) {
|
||||
posRelative = currentPos;
|
||||
offsetRelative = 0;
|
||||
}
|
||||
int diffRelative = n - offsetRelative;
|
||||
int posNew = multiByteAccess->GetRelativePosition(posRelative, diffRelative);
|
||||
int chReturn = multiByteAccess->GetCharacterAndWidth(posNew, 0);
|
||||
posRelative = posNew;
|
||||
currentPosLastRelative = currentPos;
|
||||
offsetRelative = n;
|
||||
return chReturn;
|
||||
} else {
|
||||
// fast version for single byte encodings
|
||||
return static_cast<unsigned char>(styler.SafeGetCharAt(currentPos + n, 0));
|
||||
}
|
||||
}
|
||||
bool Match(char ch0) const {
|
||||
return ch == static_cast<unsigned char>(ch0);
|
||||
}
|
||||
bool Match(char ch0, char ch1) const {
|
||||
return (ch == static_cast<unsigned char>(ch0)) && (chNext == static_cast<unsigned char>(ch1));
|
||||
}
|
||||
bool Match(const char *s) {
|
||||
if (ch != static_cast<unsigned char>(*s))
|
||||
return false;
|
||||
s++;
|
||||
if (!*s)
|
||||
return true;
|
||||
if (chNext != static_cast<unsigned char>(*s))
|
||||
return false;
|
||||
s++;
|
||||
for (int n=2; *s; n++) {
|
||||
if (*s != styler.SafeGetCharAt(currentPos+n, 0))
|
||||
return false;
|
||||
s++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool MatchIgnoreCase(const char *s) {
|
||||
if (MakeLowerCase(ch) != static_cast<unsigned char>(*s))
|
||||
return false;
|
||||
s++;
|
||||
if (MakeLowerCase(chNext) != static_cast<unsigned char>(*s))
|
||||
return false;
|
||||
s++;
|
||||
for (int n=2; *s; n++) {
|
||||
if (static_cast<unsigned char>(*s) !=
|
||||
MakeLowerCase(static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n, 0))))
|
||||
return false;
|
||||
s++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Non-inline
|
||||
void GetCurrent(char *s, unsigned int len);
|
||||
void GetCurrentLowered(char *s, unsigned int len);
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
177
third-party/scintilla/SubStyles.h
vendored
Normal file
177
third-party/scintilla/SubStyles.h
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file SubStyles.h
|
||||
** Manage substyles for a lexer.
|
||||
**/
|
||||
// Copyright 2012 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef SUBSTYLES_H
|
||||
#define SUBSTYLES_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
class WordClassifier {
|
||||
int baseStyle;
|
||||
int firstStyle;
|
||||
int lenStyles;
|
||||
std::map<std::string, int> wordToStyle;
|
||||
|
||||
public:
|
||||
|
||||
explicit WordClassifier(int baseStyle_) : baseStyle(baseStyle_), firstStyle(0), lenStyles(0) {
|
||||
}
|
||||
|
||||
void Allocate(int firstStyle_, int lenStyles_) {
|
||||
firstStyle = firstStyle_;
|
||||
lenStyles = lenStyles_;
|
||||
wordToStyle.clear();
|
||||
}
|
||||
|
||||
int Base() const {
|
||||
return baseStyle;
|
||||
}
|
||||
|
||||
int Start() const {
|
||||
return firstStyle;
|
||||
}
|
||||
|
||||
int Length() const {
|
||||
return lenStyles;
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
firstStyle = 0;
|
||||
lenStyles = 0;
|
||||
wordToStyle.clear();
|
||||
}
|
||||
|
||||
int ValueFor(const std::string &s) const {
|
||||
std::map<std::string, int>::const_iterator it = wordToStyle.find(s);
|
||||
if (it != wordToStyle.end())
|
||||
return it->second;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool IncludesStyle(int style) const {
|
||||
return (style >= firstStyle) && (style < (firstStyle + lenStyles));
|
||||
}
|
||||
|
||||
void SetIdentifiers(int style, const char *identifiers) {
|
||||
while (*identifiers) {
|
||||
const char *cpSpace = identifiers;
|
||||
while (*cpSpace && !(*cpSpace == ' ' || *cpSpace == '\t' || *cpSpace == '\r' || *cpSpace == '\n'))
|
||||
cpSpace++;
|
||||
if (cpSpace > identifiers) {
|
||||
std::string word(identifiers, cpSpace - identifiers);
|
||||
wordToStyle[word] = style;
|
||||
}
|
||||
identifiers = cpSpace;
|
||||
if (*identifiers)
|
||||
identifiers++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SubStyles {
|
||||
int classifications;
|
||||
const char *baseStyles;
|
||||
int styleFirst;
|
||||
int stylesAvailable;
|
||||
int secondaryDistance;
|
||||
int allocated;
|
||||
std::vector<WordClassifier> classifiers;
|
||||
|
||||
int BlockFromBaseStyle(int baseStyle) const {
|
||||
for (int b=0; b < classifications; b++) {
|
||||
if (baseStyle == baseStyles[b])
|
||||
return b;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int BlockFromStyle(int style) const {
|
||||
int b = 0;
|
||||
for (std::vector<WordClassifier>::const_iterator it=classifiers.begin(); it != classifiers.end(); ++it) {
|
||||
if (it->IncludesStyle(style))
|
||||
return b;
|
||||
b++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
SubStyles(const char *baseStyles_, int styleFirst_, int stylesAvailable_, int secondaryDistance_) :
|
||||
classifications(0),
|
||||
baseStyles(baseStyles_),
|
||||
styleFirst(styleFirst_),
|
||||
stylesAvailable(stylesAvailable_),
|
||||
secondaryDistance(secondaryDistance_),
|
||||
allocated(0) {
|
||||
while (baseStyles[classifications]) {
|
||||
classifiers.push_back(WordClassifier(baseStyles[classifications]));
|
||||
classifications++;
|
||||
}
|
||||
}
|
||||
|
||||
int Allocate(int styleBase, int numberStyles) {
|
||||
int block = BlockFromBaseStyle(styleBase);
|
||||
if (block >= 0) {
|
||||
if ((allocated + numberStyles) > stylesAvailable)
|
||||
return -1;
|
||||
int startBlock = styleFirst + allocated;
|
||||
allocated += numberStyles;
|
||||
classifiers[block].Allocate(startBlock, numberStyles);
|
||||
return startBlock;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int Start(int styleBase) {
|
||||
int block = BlockFromBaseStyle(styleBase);
|
||||
return (block >= 0) ? classifiers[block].Start() : -1;
|
||||
}
|
||||
|
||||
int Length(int styleBase) {
|
||||
int block = BlockFromBaseStyle(styleBase);
|
||||
return (block >= 0) ? classifiers[block].Length() : 0;
|
||||
}
|
||||
|
||||
int BaseStyle(int subStyle) const {
|
||||
int block = BlockFromStyle(subStyle);
|
||||
if (block >= 0)
|
||||
return classifiers[block].Base();
|
||||
else
|
||||
return subStyle;
|
||||
}
|
||||
|
||||
int DistanceToSecondaryStyles() const {
|
||||
return secondaryDistance;
|
||||
}
|
||||
|
||||
void SetIdentifiers(int style, const char *identifiers) {
|
||||
int block = BlockFromStyle(style);
|
||||
if (block >= 0)
|
||||
classifiers[block].SetIdentifiers(style, identifiers);
|
||||
}
|
||||
|
||||
void Free() {
|
||||
allocated = 0;
|
||||
for (std::vector<WordClassifier>::iterator it=classifiers.begin(); it != classifiers.end(); ++it)
|
||||
it->Clear();
|
||||
}
|
||||
|
||||
const WordClassifier &Classifier(int baseStyle) const {
|
||||
return classifiers[BlockFromBaseStyle(baseStyle)];
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
263
third-party/scintilla/UniConversion.cxx
vendored
Normal file
263
third-party/scintilla/UniConversion.cxx
vendored
Normal file
@@ -0,0 +1,263 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file UniConversion.cxx
|
||||
** Functions to handle UTF-8 and UTF-16 strings.
|
||||
**/
|
||||
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "UniConversion.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
enum { SURROGATE_LEAD_FIRST = 0xD800 };
|
||||
enum { SURROGATE_TRAIL_FIRST = 0xDC00 };
|
||||
enum { SURROGATE_TRAIL_LAST = 0xDFFF };
|
||||
|
||||
unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen) {
|
||||
unsigned int len = 0;
|
||||
for (unsigned int i = 0; i < tlen && uptr[i];) {
|
||||
unsigned int uch = uptr[i];
|
||||
if (uch < 0x80) {
|
||||
len++;
|
||||
} else if (uch < 0x800) {
|
||||
len += 2;
|
||||
} else if ((uch >= SURROGATE_LEAD_FIRST) &&
|
||||
(uch <= SURROGATE_TRAIL_LAST)) {
|
||||
len += 4;
|
||||
i++;
|
||||
} else {
|
||||
len += 3;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len) {
|
||||
int k = 0;
|
||||
for (unsigned int i = 0; i < tlen && uptr[i];) {
|
||||
unsigned int uch = uptr[i];
|
||||
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 >= SURROGATE_LEAD_FIRST) &&
|
||||
(uch <= SURROGATE_TRAIL_LAST)) {
|
||||
// Half a surrogate pair
|
||||
i++;
|
||||
unsigned int xch = 0x10000 + ((uch & 0x3ff) << 10) + (uptr[i] & 0x3ff);
|
||||
putf[k++] = static_cast<char>(0xF0 | (xch >> 18));
|
||||
putf[k++] = static_cast<char>(0x80 | ((xch >> 12) & 0x3f));
|
||||
putf[k++] = static_cast<char>(0x80 | ((xch >> 6) & 0x3f));
|
||||
putf[k++] = static_cast<char>(0x80 | (xch & 0x3f));
|
||||
} else {
|
||||
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));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
putf[len] = '\0';
|
||||
}
|
||||
|
||||
unsigned int UTF8CharLength(unsigned char ch) {
|
||||
if (ch < 0x80) {
|
||||
return 1;
|
||||
} else if (ch < 0x80 + 0x40 + 0x20) {
|
||||
return 2;
|
||||
} else if (ch < 0x80 + 0x40 + 0x20 + 0x10) {
|
||||
return 3;
|
||||
} else {
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int UTF16Length(const char *s, unsigned int len) {
|
||||
unsigned int ulen = 0;
|
||||
unsigned int charLen;
|
||||
for (unsigned int i=0; i<len;) {
|
||||
unsigned char ch = static_cast<unsigned char>(s[i]);
|
||||
if (ch < 0x80) {
|
||||
charLen = 1;
|
||||
} else if (ch < 0x80 + 0x40 + 0x20) {
|
||||
charLen = 2;
|
||||
} else if (ch < 0x80 + 0x40 + 0x20 + 0x10) {
|
||||
charLen = 3;
|
||||
} else {
|
||||
charLen = 4;
|
||||
ulen++;
|
||||
}
|
||||
i += charLen;
|
||||
ulen++;
|
||||
}
|
||||
return ulen;
|
||||
}
|
||||
|
||||
unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *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++];
|
||||
if (ch < 0x80) {
|
||||
tbuf[ui] = ch;
|
||||
} else if (ch < 0x80 + 0x40 + 0x20) {
|
||||
tbuf[ui] = static_cast<wchar_t>((ch & 0x1F) << 6);
|
||||
ch = us[i++];
|
||||
tbuf[ui] = static_cast<wchar_t>(tbuf[ui] + (ch & 0x7F));
|
||||
} else if (ch < 0x80 + 0x40 + 0x20 + 0x10) {
|
||||
tbuf[ui] = static_cast<wchar_t>((ch & 0xF) << 12);
|
||||
ch = us[i++];
|
||||
tbuf[ui] = static_cast<wchar_t>(tbuf[ui] + ((ch & 0x7F) << 6));
|
||||
ch = us[i++];
|
||||
tbuf[ui] = static_cast<wchar_t>(tbuf[ui] + (ch & 0x7F));
|
||||
} else {
|
||||
// Outside the BMP so need two surrogates
|
||||
int val = (ch & 0x7) << 18;
|
||||
ch = us[i++];
|
||||
val += (ch & 0x3F) << 12;
|
||||
ch = us[i++];
|
||||
val += (ch & 0x3F) << 6;
|
||||
ch = us[i++];
|
||||
val += (ch & 0x3F);
|
||||
tbuf[ui] = static_cast<wchar_t>(((val - 0x10000) >> 10) + SURROGATE_LEAD_FIRST);
|
||||
ui++;
|
||||
tbuf[ui] = static_cast<wchar_t>((val & 0x3ff) + SURROGATE_TRAIL_FIRST);
|
||||
}
|
||||
ui++;
|
||||
}
|
||||
return ui;
|
||||
}
|
||||
|
||||
int UTF8BytesOfLead[256];
|
||||
static bool initialisedBytesOfLead = false;
|
||||
|
||||
static int BytesFromLead(int leadByte) {
|
||||
if (leadByte < 0xC2) {
|
||||
// Single byte or invalid
|
||||
return 1;
|
||||
} else if (leadByte < 0xE0) {
|
||||
return 2;
|
||||
} else if (leadByte < 0xF0) {
|
||||
return 3;
|
||||
} else if (leadByte < 0xF5) {
|
||||
return 4;
|
||||
} else {
|
||||
// Characters longer than 4 bytes not possible in current UTF-8
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void UTF8BytesOfLeadInitialise() {
|
||||
if (!initialisedBytesOfLead) {
|
||||
for (int i=0;i<256;i++) {
|
||||
UTF8BytesOfLead[i] = BytesFromLead(i);
|
||||
}
|
||||
initialisedBytesOfLead = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Return both the width of the first character in the string and a status
|
||||
// saying whether it is valid or invalid.
|
||||
// Most invalid sequences return a width of 1 so are treated as isolated bytes but
|
||||
// the non-characters *FFFE, *FFFF and FDD0 .. FDEF return 3 or 4 as they can be
|
||||
// reasonably treated as code points in some circumstances. They will, however,
|
||||
// not have associated glyphs.
|
||||
int UTF8Classify(const unsigned char *us, int len) {
|
||||
// For the rules: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
if (*us < 0x80) {
|
||||
// Single bytes easy
|
||||
return 1;
|
||||
} else if (*us > 0xf4) {
|
||||
// Characters longer than 4 bytes not possible in current UTF-8
|
||||
return UTF8MaskInvalid | 1;
|
||||
} else if (*us >= 0xf0) {
|
||||
// 4 bytes
|
||||
if (len < 4)
|
||||
return UTF8MaskInvalid | 1;
|
||||
if (UTF8IsTrailByte(us[1]) && UTF8IsTrailByte(us[2]) && UTF8IsTrailByte(us[3])) {
|
||||
if (((us[1] & 0xf) == 0xf) && (us[2] == 0xbf) && ((us[3] == 0xbe) || (us[3] == 0xbf))) {
|
||||
// *FFFE or *FFFF non-character
|
||||
return UTF8MaskInvalid | 4;
|
||||
}
|
||||
if (*us == 0xf4) {
|
||||
// Check if encoding a value beyond the last Unicode character 10FFFF
|
||||
if (us[1] > 0x8f) {
|
||||
return UTF8MaskInvalid | 1;
|
||||
} else if (us[1] == 0x8f) {
|
||||
if (us[2] > 0xbf) {
|
||||
return UTF8MaskInvalid | 1;
|
||||
} else if (us[2] == 0xbf) {
|
||||
if (us[3] > 0xbf) {
|
||||
return UTF8MaskInvalid | 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ((*us == 0xf0) && ((us[1] & 0xf0) == 0x80)) {
|
||||
// Overlong
|
||||
return UTF8MaskInvalid | 1;
|
||||
}
|
||||
return 4;
|
||||
} else {
|
||||
return UTF8MaskInvalid | 1;
|
||||
}
|
||||
} else if (*us >= 0xe0) {
|
||||
// 3 bytes
|
||||
if (len < 3)
|
||||
return UTF8MaskInvalid | 1;
|
||||
if (UTF8IsTrailByte(us[1]) && UTF8IsTrailByte(us[2])) {
|
||||
if ((*us == 0xe0) && ((us[1] & 0xe0) == 0x80)) {
|
||||
// Overlong
|
||||
return UTF8MaskInvalid | 1;
|
||||
}
|
||||
if ((*us == 0xed) && ((us[1] & 0xe0) == 0xa0)) {
|
||||
// Surrogate
|
||||
return UTF8MaskInvalid | 1;
|
||||
}
|
||||
if ((*us == 0xef) && (us[1] == 0xbf) && (us[2] == 0xbe)) {
|
||||
// U+FFFE non-character - 3 bytes long
|
||||
return UTF8MaskInvalid | 3;
|
||||
}
|
||||
if ((*us == 0xef) && (us[1] == 0xbf) && (us[2] == 0xbf)) {
|
||||
// U+FFFF non-character - 3 bytes long
|
||||
return UTF8MaskInvalid | 3;
|
||||
}
|
||||
if ((*us == 0xef) && (us[1] == 0xb7) && (((us[2] & 0xf0) == 0x90) || ((us[2] & 0xf0) == 0xa0))) {
|
||||
// U+FDD0 .. U+FDEF
|
||||
return UTF8MaskInvalid | 3;
|
||||
}
|
||||
return 3;
|
||||
} else {
|
||||
return UTF8MaskInvalid | 1;
|
||||
}
|
||||
} else if (*us >= 0xc2) {
|
||||
// 2 bytes
|
||||
if (len < 2)
|
||||
return UTF8MaskInvalid | 1;
|
||||
if (UTF8IsTrailByte(us[1])) {
|
||||
return 2;
|
||||
} else {
|
||||
return UTF8MaskInvalid | 1;
|
||||
}
|
||||
} else {
|
||||
// 0xc0 .. 0xc1 is overlong encoding
|
||||
// 0x80 .. 0xbf is trail byte
|
||||
return UTF8MaskInvalid | 1;
|
||||
}
|
||||
}
|
||||
|
||||
int UTF8DrawBytes(const unsigned char *us, int len) {
|
||||
int utf8StatusNext = UTF8Classify(us, len);
|
||||
return (utf8StatusNext & UTF8MaskInvalid) ? 1 : (utf8StatusNext & UTF8MaskWidth);
|
||||
}
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
58
third-party/scintilla/UniConversion.h
vendored
Normal file
58
third-party/scintilla/UniConversion.h
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file UniConversion.h
|
||||
** Functions to handle UTF-8 and UTF-16 strings.
|
||||
**/
|
||||
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef UNICONVERSION_H
|
||||
#define UNICONVERSION_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
const int UTF8MaxBytes = 4;
|
||||
|
||||
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);
|
||||
|
||||
extern int UTF8BytesOfLead[256];
|
||||
void UTF8BytesOfLeadInitialise();
|
||||
|
||||
inline bool UTF8IsTrailByte(int ch) {
|
||||
return (ch >= 0x80) && (ch < 0xc0);
|
||||
}
|
||||
|
||||
inline bool UTF8IsAscii(int ch) {
|
||||
return ch < 0x80;
|
||||
}
|
||||
|
||||
enum { UTF8MaskWidth=0x7, UTF8MaskInvalid=0x8 };
|
||||
int UTF8Classify(const unsigned char *us, int len);
|
||||
|
||||
// Similar to UTF8Classify but returns a length of 1 for invalid bytes
|
||||
// instead of setting the invalid flag
|
||||
int UTF8DrawBytes(const unsigned char *us, int len);
|
||||
|
||||
// Line separator is U+2028 \xe2\x80\xa8
|
||||
// Paragraph separator is U+2029 \xe2\x80\xa9
|
||||
const int UTF8SeparatorLength = 3;
|
||||
inline bool UTF8IsSeparator(const unsigned char *us) {
|
||||
return (us[0] == 0xe2) && (us[1] == 0x80) && ((us[2] == 0xa8) || (us[2] == 0xa9));
|
||||
}
|
||||
|
||||
// NEL is U+0085 \xc2\x85
|
||||
const int UTF8NELLength = 2;
|
||||
inline bool UTF8IsNEL(const unsigned char *us) {
|
||||
return (us[0] == 0xc2) && (us[1] == 0x85);
|
||||
}
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
32
third-party/scintilla/UnicodeFromUTF8.h
vendored
Normal file
32
third-party/scintilla/UnicodeFromUTF8.h
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
// 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.
|
||||
|
||||
#ifndef UNICODEFROMUTF8_H
|
||||
#define UNICODEFROMUTF8_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
522
third-party/scintilla/ViewStyle.cxx
vendored
Normal file
522
third-party/scintilla/ViewStyle.cxx
vendored
Normal file
@@ -0,0 +1,522 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file ViewStyle.cxx
|
||||
** Store information on how the document is to be viewed.
|
||||
**/
|
||||
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
#include "SplitVector.h"
|
||||
#include "Partitioning.h"
|
||||
#include "RunStyles.h"
|
||||
#include "Indicator.h"
|
||||
#include "XPM.h"
|
||||
#include "LineMarker.h"
|
||||
#include "Style.h"
|
||||
#include "ViewStyle.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
MarginStyle::MarginStyle() :
|
||||
style(SC_MARGIN_SYMBOL), width(0), mask(0), sensitive(false), cursor(SC_CURSORREVERSEARROW) {
|
||||
}
|
||||
|
||||
// A list of the fontnames - avoids wasting space in each style
|
||||
FontNames::FontNames() {
|
||||
}
|
||||
|
||||
FontNames::~FontNames() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void FontNames::Clear() {
|
||||
for (std::vector<char *>::const_iterator it=names.begin(); it != names.end(); ++it) {
|
||||
delete []*it;
|
||||
}
|
||||
names.clear();
|
||||
}
|
||||
|
||||
const char *FontNames::Save(const char *name) {
|
||||
if (!name)
|
||||
return 0;
|
||||
|
||||
for (std::vector<char *>::const_iterator it=names.begin(); it != names.end(); ++it) {
|
||||
if (strcmp(*it, name) == 0) {
|
||||
return *it;
|
||||
}
|
||||
}
|
||||
const size_t lenName = strlen(name) + 1;
|
||||
char *nameSave = new char[lenName];
|
||||
memcpy(nameSave, name, lenName);
|
||||
names.push_back(nameSave);
|
||||
return nameSave;
|
||||
}
|
||||
|
||||
FontRealised::FontRealised() {
|
||||
}
|
||||
|
||||
FontRealised::~FontRealised() {
|
||||
font.Release();
|
||||
}
|
||||
|
||||
void FontRealised::Realise(Surface &surface, int zoomLevel, int technology, const FontSpecification &fs) {
|
||||
PLATFORM_ASSERT(fs.fontName);
|
||||
sizeZoomed = fs.size + zoomLevel * SC_FONT_SIZE_MULTIPLIER;
|
||||
if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1
|
||||
sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER;
|
||||
|
||||
float deviceHeight = static_cast<float>(surface.DeviceHeightFont(sizeZoomed));
|
||||
FontParameters fp(fs.fontName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, fs.weight, fs.italic, fs.extraFontFlag, technology, fs.characterSet);
|
||||
font.Create(fp);
|
||||
|
||||
ascent = static_cast<unsigned int>(surface.Ascent(font));
|
||||
descent = static_cast<unsigned int>(surface.Descent(font));
|
||||
aveCharWidth = surface.AverageCharWidth(font);
|
||||
spaceWidth = surface.WidthChar(font, ' ');
|
||||
}
|
||||
|
||||
ViewStyle::ViewStyle() {
|
||||
Init();
|
||||
}
|
||||
|
||||
ViewStyle::ViewStyle(const ViewStyle &source) {
|
||||
Init(source.styles.size());
|
||||
for (unsigned int sty=0; sty<source.styles.size(); sty++) {
|
||||
styles[sty] = source.styles[sty];
|
||||
// Can't just copy fontname as its lifetime is relative to its owning ViewStyle
|
||||
styles[sty].fontName = fontNames.Save(source.styles[sty].fontName);
|
||||
}
|
||||
nextExtendedStyle = source.nextExtendedStyle;
|
||||
for (int mrk=0; mrk<=MARKER_MAX; mrk++) {
|
||||
markers[mrk] = source.markers[mrk];
|
||||
}
|
||||
CalcLargestMarkerHeight();
|
||||
for (int ind=0; ind<=INDIC_MAX; ind++) {
|
||||
indicators[ind] = source.indicators[ind];
|
||||
}
|
||||
|
||||
selColours = source.selColours;
|
||||
selAdditionalForeground = source.selAdditionalForeground;
|
||||
selAdditionalBackground = source.selAdditionalBackground;
|
||||
selBackground2 = source.selBackground2;
|
||||
selAlpha = source.selAlpha;
|
||||
selAdditionalAlpha = source.selAdditionalAlpha;
|
||||
selEOLFilled = source.selEOLFilled;
|
||||
|
||||
foldmarginColour = source.foldmarginColour;
|
||||
foldmarginHighlightColour = source.foldmarginHighlightColour;
|
||||
|
||||
hotspotColours = source.hotspotColours;
|
||||
hotspotUnderline = source.hotspotUnderline;
|
||||
hotspotSingleLine = source.hotspotSingleLine;
|
||||
|
||||
whitespaceColours = source.whitespaceColours;
|
||||
controlCharSymbol = source.controlCharSymbol;
|
||||
controlCharWidth = source.controlCharWidth;
|
||||
selbar = source.selbar;
|
||||
selbarlight = source.selbarlight;
|
||||
caretcolour = source.caretcolour;
|
||||
additionalCaretColour = source.additionalCaretColour;
|
||||
showCaretLineBackground = source.showCaretLineBackground;
|
||||
alwaysShowCaretLineBackground = source.alwaysShowCaretLineBackground;
|
||||
caretLineBackground = source.caretLineBackground;
|
||||
caretLineAlpha = source.caretLineAlpha;
|
||||
edgecolour = source.edgecolour;
|
||||
edgeState = source.edgeState;
|
||||
caretStyle = source.caretStyle;
|
||||
caretWidth = source.caretWidth;
|
||||
someStylesProtected = false;
|
||||
someStylesForceCase = false;
|
||||
leftMarginWidth = source.leftMarginWidth;
|
||||
rightMarginWidth = source.rightMarginWidth;
|
||||
for (int margin=0; margin <= SC_MAX_MARGIN; margin++) {
|
||||
ms[margin] = source.ms[margin];
|
||||
}
|
||||
maskInLine = source.maskInLine;
|
||||
fixedColumnWidth = source.fixedColumnWidth;
|
||||
marginInside = source.marginInside;
|
||||
textStart = source.textStart;
|
||||
zoomLevel = source.zoomLevel;
|
||||
viewWhitespace = source.viewWhitespace;
|
||||
whitespaceSize = source.whitespaceSize;
|
||||
viewIndentationGuides = source.viewIndentationGuides;
|
||||
viewEOL = source.viewEOL;
|
||||
extraFontFlag = source.extraFontFlag;
|
||||
extraAscent = source.extraAscent;
|
||||
extraDescent = source.extraDescent;
|
||||
marginStyleOffset = source.marginStyleOffset;
|
||||
annotationVisible = source.annotationVisible;
|
||||
annotationStyleOffset = source.annotationStyleOffset;
|
||||
braceHighlightIndicatorSet = source.braceHighlightIndicatorSet;
|
||||
braceHighlightIndicator = source.braceHighlightIndicator;
|
||||
braceBadLightIndicatorSet = source.braceBadLightIndicatorSet;
|
||||
braceBadLightIndicator = source.braceBadLightIndicator;
|
||||
|
||||
theEdge = source.theEdge;
|
||||
|
||||
marginNumberPadding = source.marginNumberPadding;
|
||||
ctrlCharPadding = source.ctrlCharPadding;
|
||||
lastSegItalicsOffset = source.lastSegItalicsOffset;
|
||||
|
||||
wrapState = source.wrapState;
|
||||
wrapVisualFlags = source.wrapVisualFlags;
|
||||
wrapVisualFlagsLocation = source.wrapVisualFlagsLocation;
|
||||
wrapVisualStartIndent = source.wrapVisualStartIndent;
|
||||
wrapIndentMode = source.wrapIndentMode;
|
||||
}
|
||||
|
||||
ViewStyle::~ViewStyle() {
|
||||
styles.clear();
|
||||
for (FontMap::iterator it = fonts.begin(); it != fonts.end(); ++it) {
|
||||
delete it->second;
|
||||
}
|
||||
fonts.clear();
|
||||
}
|
||||
|
||||
void ViewStyle::Init(size_t stylesSize_) {
|
||||
AllocStyles(stylesSize_);
|
||||
nextExtendedStyle = 256;
|
||||
fontNames.Clear();
|
||||
ResetDefaultStyle();
|
||||
|
||||
// There are no image markers by default, so no need for calling CalcLargestMarkerHeight()
|
||||
largestMarkerHeight = 0;
|
||||
|
||||
indicators[0].style = INDIC_SQUIGGLE;
|
||||
indicators[0].under = false;
|
||||
indicators[0].fore = ColourDesired(0, 0x7f, 0);
|
||||
indicators[1].style = INDIC_TT;
|
||||
indicators[1].under = false;
|
||||
indicators[1].fore = ColourDesired(0, 0, 0xff);
|
||||
indicators[2].style = INDIC_PLAIN;
|
||||
indicators[2].under = false;
|
||||
indicators[2].fore = ColourDesired(0xff, 0, 0);
|
||||
|
||||
technology = SC_TECHNOLOGY_DEFAULT;
|
||||
lineHeight = 1;
|
||||
maxAscent = 1;
|
||||
maxDescent = 1;
|
||||
aveCharWidth = 8;
|
||||
spaceWidth = 8;
|
||||
tabWidth = spaceWidth * 8;
|
||||
|
||||
selColours.fore = ColourOptional(ColourDesired(0xff, 0, 0));
|
||||
selColours.back = ColourOptional(ColourDesired(0xc0, 0xc0, 0xc0), true);
|
||||
selAdditionalForeground = ColourDesired(0xff, 0, 0);
|
||||
selAdditionalBackground = ColourDesired(0xd7, 0xd7, 0xd7);
|
||||
selBackground2 = ColourDesired(0xb0, 0xb0, 0xb0);
|
||||
selAlpha = SC_ALPHA_NOALPHA;
|
||||
selAdditionalAlpha = SC_ALPHA_NOALPHA;
|
||||
selEOLFilled = false;
|
||||
|
||||
foldmarginColour = ColourOptional(ColourDesired(0xff, 0, 0));
|
||||
foldmarginHighlightColour = ColourOptional(ColourDesired(0xc0, 0xc0, 0xc0));
|
||||
|
||||
whitespaceColours.fore = ColourOptional();
|
||||
whitespaceColours.back = ColourOptional(ColourDesired(0xff, 0xff, 0xff));
|
||||
controlCharSymbol = 0; /* Draw the control characters */
|
||||
controlCharWidth = 0;
|
||||
selbar = Platform::Chrome();
|
||||
selbarlight = Platform::ChromeHighlight();
|
||||
styles[STYLE_LINENUMBER].fore = ColourDesired(0, 0, 0);
|
||||
styles[STYLE_LINENUMBER].back = Platform::Chrome();
|
||||
caretcolour = ColourDesired(0, 0, 0);
|
||||
additionalCaretColour = ColourDesired(0x7f, 0x7f, 0x7f);
|
||||
showCaretLineBackground = false;
|
||||
alwaysShowCaretLineBackground = false;
|
||||
caretLineBackground = ColourDesired(0xff, 0xff, 0);
|
||||
caretLineAlpha = SC_ALPHA_NOALPHA;
|
||||
edgecolour = ColourDesired(0xc0, 0xc0, 0xc0);
|
||||
edgeState = EDGE_NONE;
|
||||
caretStyle = CARETSTYLE_LINE;
|
||||
caretWidth = 1;
|
||||
someStylesProtected = false;
|
||||
someStylesForceCase = false;
|
||||
|
||||
hotspotColours.fore = ColourOptional(ColourDesired(0, 0, 0xff));
|
||||
hotspotColours.back = ColourOptional(ColourDesired(0xff, 0xff, 0xff));
|
||||
hotspotUnderline = true;
|
||||
hotspotSingleLine = true;
|
||||
|
||||
leftMarginWidth = 1;
|
||||
rightMarginWidth = 1;
|
||||
ms[0].style = SC_MARGIN_NUMBER;
|
||||
ms[0].width = 0;
|
||||
ms[0].mask = 0;
|
||||
ms[1].style = SC_MARGIN_SYMBOL;
|
||||
ms[1].width = 16;
|
||||
ms[1].mask = ~SC_MASK_FOLDERS;
|
||||
ms[2].style = SC_MARGIN_SYMBOL;
|
||||
ms[2].width = 0;
|
||||
ms[2].mask = 0;
|
||||
marginInside = true;
|
||||
fixedColumnWidth = marginInside ? leftMarginWidth : 0;
|
||||
maskInLine = 0xffffffff;
|
||||
for (int margin=0; margin <= SC_MAX_MARGIN; margin++) {
|
||||
fixedColumnWidth += ms[margin].width;
|
||||
if (ms[margin].width > 0)
|
||||
maskInLine &= ~ms[margin].mask;
|
||||
}
|
||||
textStart = marginInside ? fixedColumnWidth : leftMarginWidth;
|
||||
zoomLevel = 0;
|
||||
viewWhitespace = wsInvisible;
|
||||
whitespaceSize = 1;
|
||||
viewIndentationGuides = ivNone;
|
||||
viewEOL = false;
|
||||
extraFontFlag = 0;
|
||||
extraAscent = 0;
|
||||
extraDescent = 0;
|
||||
marginStyleOffset = 0;
|
||||
annotationVisible = ANNOTATION_HIDDEN;
|
||||
annotationStyleOffset = 0;
|
||||
braceHighlightIndicatorSet = false;
|
||||
braceHighlightIndicator = 0;
|
||||
braceBadLightIndicatorSet = false;
|
||||
braceBadLightIndicator = 0;
|
||||
|
||||
theEdge = 0;
|
||||
|
||||
marginNumberPadding = 3;
|
||||
ctrlCharPadding = 3; // +3 For a blank on front and rounded edge each side
|
||||
lastSegItalicsOffset = 2;
|
||||
|
||||
wrapState = eWrapNone;
|
||||
wrapVisualFlags = 0;
|
||||
wrapVisualFlagsLocation = 0;
|
||||
wrapVisualStartIndent = 0;
|
||||
wrapIndentMode = SC_WRAPINDENT_FIXED;
|
||||
}
|
||||
|
||||
void ViewStyle::Refresh(Surface &surface, int tabInChars) {
|
||||
for (FontMap::iterator it = fonts.begin(); it != fonts.end(); ++it) {
|
||||
delete it->second;
|
||||
}
|
||||
fonts.clear();
|
||||
|
||||
selbar = Platform::Chrome();
|
||||
selbarlight = Platform::ChromeHighlight();
|
||||
|
||||
for (unsigned int i=0; i<styles.size(); i++) {
|
||||
styles[i].extraFontFlag = extraFontFlag;
|
||||
}
|
||||
|
||||
CreateAndAddFont(styles[STYLE_DEFAULT]);
|
||||
for (unsigned int j=0; j<styles.size(); j++) {
|
||||
CreateAndAddFont(styles[j]);
|
||||
}
|
||||
|
||||
for (FontMap::iterator it = fonts.begin(); it != fonts.end(); ++it) {
|
||||
it->second->Realise(surface, zoomLevel, technology, it->first);
|
||||
}
|
||||
|
||||
for (unsigned int k=0; k<styles.size(); k++) {
|
||||
FontRealised *fr = Find(styles[k]);
|
||||
styles[k].Copy(fr->font, *fr);
|
||||
}
|
||||
maxAscent = 1;
|
||||
maxDescent = 1;
|
||||
FindMaxAscentDescent();
|
||||
maxAscent += extraAscent;
|
||||
maxDescent += extraDescent;
|
||||
lineHeight = maxAscent + maxDescent;
|
||||
|
||||
someStylesProtected = false;
|
||||
someStylesForceCase = false;
|
||||
for (unsigned int l=0; l<styles.size(); l++) {
|
||||
if (styles[l].IsProtected()) {
|
||||
someStylesProtected = true;
|
||||
}
|
||||
if (styles[l].caseForce != Style::caseMixed) {
|
||||
someStylesForceCase = true;
|
||||
}
|
||||
}
|
||||
|
||||
aveCharWidth = styles[STYLE_DEFAULT].aveCharWidth;
|
||||
spaceWidth = styles[STYLE_DEFAULT].spaceWidth;
|
||||
tabWidth = spaceWidth * tabInChars;
|
||||
|
||||
controlCharWidth = 0.0;
|
||||
if (controlCharSymbol >= 32) {
|
||||
controlCharWidth = surface.WidthChar(styles[STYLE_CONTROLCHAR].font, static_cast<char>(controlCharSymbol));
|
||||
}
|
||||
|
||||
fixedColumnWidth = marginInside ? leftMarginWidth : 0;
|
||||
maskInLine = 0xffffffff;
|
||||
for (int margin=0; margin <= SC_MAX_MARGIN; margin++) {
|
||||
fixedColumnWidth += ms[margin].width;
|
||||
if (ms[margin].width > 0)
|
||||
maskInLine &= ~ms[margin].mask;
|
||||
}
|
||||
textStart = marginInside ? fixedColumnWidth : leftMarginWidth;
|
||||
}
|
||||
|
||||
void ViewStyle::ReleaseAllExtendedStyles() {
|
||||
nextExtendedStyle = 256;
|
||||
}
|
||||
|
||||
int ViewStyle::AllocateExtendedStyles(int numberStyles) {
|
||||
int startRange = static_cast<int>(nextExtendedStyle);
|
||||
nextExtendedStyle += numberStyles;
|
||||
EnsureStyle(nextExtendedStyle);
|
||||
for (size_t i=startRange; i<nextExtendedStyle; i++) {
|
||||
styles[i].ClearTo(styles[STYLE_DEFAULT]);
|
||||
}
|
||||
return startRange;
|
||||
}
|
||||
|
||||
void ViewStyle::EnsureStyle(size_t index) {
|
||||
if (index >= styles.size()) {
|
||||
AllocStyles(index+1);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewStyle::ResetDefaultStyle() {
|
||||
styles[STYLE_DEFAULT].Clear(ColourDesired(0,0,0),
|
||||
ColourDesired(0xff,0xff,0xff),
|
||||
Platform::DefaultFontSize() * SC_FONT_SIZE_MULTIPLIER, fontNames.Save(Platform::DefaultFont()),
|
||||
SC_CHARSET_DEFAULT,
|
||||
SC_WEIGHT_NORMAL, false, false, false, Style::caseMixed, true, true, false);
|
||||
}
|
||||
|
||||
void ViewStyle::ClearStyles() {
|
||||
// Reset all styles to be like the default style
|
||||
for (unsigned int i=0; i<styles.size(); i++) {
|
||||
if (i != STYLE_DEFAULT) {
|
||||
styles[i].ClearTo(styles[STYLE_DEFAULT]);
|
||||
}
|
||||
}
|
||||
styles[STYLE_LINENUMBER].back = Platform::Chrome();
|
||||
|
||||
// Set call tip fore/back to match the values previously set for call tips
|
||||
styles[STYLE_CALLTIP].back = ColourDesired(0xff, 0xff, 0xff);
|
||||
styles[STYLE_CALLTIP].fore = ColourDesired(0x80, 0x80, 0x80);
|
||||
}
|
||||
|
||||
void ViewStyle::SetStyleFontName(int styleIndex, const char *name) {
|
||||
styles[styleIndex].fontName = fontNames.Save(name);
|
||||
}
|
||||
|
||||
bool ViewStyle::ProtectionActive() const {
|
||||
return someStylesProtected;
|
||||
}
|
||||
|
||||
int ViewStyle::ExternalMarginWidth() const {
|
||||
return marginInside ? 0 : fixedColumnWidth;
|
||||
}
|
||||
|
||||
bool ViewStyle::ValidStyle(size_t styleIndex) const {
|
||||
return styleIndex < styles.size();
|
||||
}
|
||||
|
||||
void ViewStyle::CalcLargestMarkerHeight() {
|
||||
largestMarkerHeight = 0;
|
||||
for (int m = 0; m <= MARKER_MAX; ++m) {
|
||||
switch (markers[m].markType) {
|
||||
case SC_MARK_PIXMAP:
|
||||
if (markers[m].pxpm && markers[m].pxpm->GetHeight() > largestMarkerHeight)
|
||||
largestMarkerHeight = markers[m].pxpm->GetHeight();
|
||||
break;
|
||||
case SC_MARK_RGBAIMAGE:
|
||||
if (markers[m].image && markers[m].image->GetHeight() > largestMarkerHeight)
|
||||
largestMarkerHeight = markers[m].image->GetHeight();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColourDesired ViewStyle::WrapColour() const {
|
||||
if (whitespaceColours.fore.isSet)
|
||||
return whitespaceColours.fore;
|
||||
else
|
||||
return styles[STYLE_DEFAULT].fore;
|
||||
}
|
||||
|
||||
bool ViewStyle::SetWrapState(int wrapState_) {
|
||||
WrapMode wrapStateWanted;
|
||||
switch (wrapState_) {
|
||||
case SC_WRAP_WORD:
|
||||
wrapStateWanted = eWrapWord;
|
||||
break;
|
||||
case SC_WRAP_CHAR:
|
||||
wrapStateWanted = eWrapChar;
|
||||
break;
|
||||
case SC_WRAP_WHITESPACE:
|
||||
wrapStateWanted = eWrapWhitespace;
|
||||
break;
|
||||
default:
|
||||
wrapStateWanted = eWrapNone;
|
||||
break;
|
||||
}
|
||||
bool changed = wrapState != wrapStateWanted;
|
||||
wrapState = wrapStateWanted;
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool ViewStyle::SetWrapVisualFlags(int wrapVisualFlags_) {
|
||||
bool changed = wrapVisualFlags != wrapVisualFlags_;
|
||||
wrapVisualFlags = wrapVisualFlags_;
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool ViewStyle::SetWrapVisualFlagsLocation(int wrapVisualFlagsLocation_) {
|
||||
bool changed = wrapVisualFlagsLocation != wrapVisualFlagsLocation_;
|
||||
wrapVisualFlagsLocation = wrapVisualFlagsLocation_;
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool ViewStyle::SetWrapVisualStartIndent(int wrapVisualStartIndent_) {
|
||||
bool changed = wrapVisualStartIndent != wrapVisualStartIndent_;
|
||||
wrapVisualStartIndent = wrapVisualStartIndent_;
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool ViewStyle::SetWrapIndentMode(int wrapIndentMode_) {
|
||||
bool changed = wrapIndentMode != wrapIndentMode_;
|
||||
wrapIndentMode = wrapIndentMode_;
|
||||
return changed;
|
||||
}
|
||||
|
||||
void ViewStyle::AllocStyles(size_t sizeNew) {
|
||||
size_t i=styles.size();
|
||||
styles.resize(sizeNew);
|
||||
if (styles.size() > STYLE_DEFAULT) {
|
||||
for (; i<sizeNew; i++) {
|
||||
if (i != STYLE_DEFAULT) {
|
||||
styles[i].ClearTo(styles[STYLE_DEFAULT]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ViewStyle::CreateAndAddFont(const FontSpecification &fs) {
|
||||
if (fs.fontName) {
|
||||
FontMap::iterator it = fonts.find(fs);
|
||||
if (it == fonts.end()) {
|
||||
fonts[fs] = new FontRealised();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FontRealised *ViewStyle::Find(const FontSpecification &fs) {
|
||||
if (!fs.fontName) // Invalid specification so return arbitrary object
|
||||
return fonts.begin()->second;
|
||||
FontMap::iterator it = fonts.find(fs);
|
||||
if (it != fonts.end()) {
|
||||
// Should always reach here since map was just set for all styles
|
||||
return it->second;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ViewStyle::FindMaxAscentDescent() {
|
||||
for (FontMap::const_iterator it = fonts.begin(); it != fonts.end(); ++it) {
|
||||
if (maxAscent < it->second->ascent)
|
||||
maxAscent = it->second->ascent;
|
||||
if (maxDescent < it->second->descent)
|
||||
maxDescent = it->second->descent;
|
||||
}
|
||||
}
|
||||
193
third-party/scintilla/ViewStyle.h
vendored
Normal file
193
third-party/scintilla/ViewStyle.h
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file ViewStyle.h
|
||||
** Store information on how the document is to be viewed.
|
||||
**/
|
||||
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef VIEWSTYLE_H
|
||||
#define VIEWSTYLE_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
/**
|
||||
*/
|
||||
class MarginStyle {
|
||||
public:
|
||||
int style;
|
||||
int width;
|
||||
int mask;
|
||||
bool sensitive;
|
||||
int cursor;
|
||||
MarginStyle();
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class FontNames {
|
||||
private:
|
||||
std::vector<char *> names;
|
||||
|
||||
// no copy ctr or assignment op
|
||||
FontNames(const FontNames &);
|
||||
FontNames &operator =(const FontNames &);
|
||||
public:
|
||||
FontNames();
|
||||
~FontNames();
|
||||
void Clear();
|
||||
const char *Save(const char *name);
|
||||
};
|
||||
|
||||
class FontRealised : public FontMeasurements {
|
||||
// Private so FontRealised objects can not be copied
|
||||
FontRealised(const FontRealised &);
|
||||
FontRealised &operator=(const FontRealised &);
|
||||
public:
|
||||
Font font;
|
||||
FontRealised();
|
||||
virtual ~FontRealised();
|
||||
void Realise(Surface &surface, int zoomLevel, int technology, const FontSpecification &fs);
|
||||
};
|
||||
|
||||
enum IndentView {ivNone, ivReal, ivLookForward, ivLookBoth};
|
||||
|
||||
enum WhiteSpaceVisibility {wsInvisible=0, wsVisibleAlways=1, wsVisibleAfterIndent=2};
|
||||
|
||||
typedef std::map<FontSpecification, FontRealised *> FontMap;
|
||||
|
||||
enum WrapMode { eWrapNone, eWrapWord, eWrapChar, eWrapWhitespace };
|
||||
|
||||
class ColourOptional : public ColourDesired {
|
||||
public:
|
||||
bool isSet;
|
||||
ColourOptional(ColourDesired colour_=ColourDesired(0,0,0), bool isSet_=false) : ColourDesired(colour_), isSet(isSet_) {
|
||||
}
|
||||
ColourOptional(uptr_t wParam, sptr_t lParam) : ColourDesired(static_cast<long>(lParam)), isSet(wParam != 0) {
|
||||
}
|
||||
};
|
||||
|
||||
struct ForeBackColours {
|
||||
ColourOptional fore;
|
||||
ColourOptional back;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class ViewStyle {
|
||||
FontNames fontNames;
|
||||
FontMap fonts;
|
||||
public:
|
||||
std::vector<Style> styles;
|
||||
size_t nextExtendedStyle;
|
||||
LineMarker markers[MARKER_MAX + 1];
|
||||
int largestMarkerHeight;
|
||||
Indicator indicators[INDIC_MAX + 1];
|
||||
int technology;
|
||||
int lineHeight;
|
||||
unsigned int maxAscent;
|
||||
unsigned int maxDescent;
|
||||
XYPOSITION aveCharWidth;
|
||||
XYPOSITION spaceWidth;
|
||||
XYPOSITION tabWidth;
|
||||
ForeBackColours selColours;
|
||||
ColourDesired selAdditionalForeground;
|
||||
ColourDesired selAdditionalBackground;
|
||||
ColourDesired selBackground2;
|
||||
int selAlpha;
|
||||
int selAdditionalAlpha;
|
||||
bool selEOLFilled;
|
||||
ForeBackColours whitespaceColours;
|
||||
int controlCharSymbol;
|
||||
XYPOSITION controlCharWidth;
|
||||
ColourDesired selbar;
|
||||
ColourDesired selbarlight;
|
||||
ColourOptional foldmarginColour;
|
||||
ColourOptional foldmarginHighlightColour;
|
||||
ForeBackColours hotspotColours;
|
||||
bool hotspotUnderline;
|
||||
bool hotspotSingleLine;
|
||||
/// Margins are ordered: Line Numbers, Selection Margin, Spacing Margin
|
||||
int leftMarginWidth; ///< Spacing margin on left of text
|
||||
int rightMarginWidth; ///< Spacing margin on right of text
|
||||
int maskInLine; ///< Mask for markers to be put into text because there is nowhere for them to go in margin
|
||||
MarginStyle ms[SC_MAX_MARGIN+1];
|
||||
int fixedColumnWidth; ///< Total width of margins
|
||||
bool marginInside; ///< true: margin included in text view, false: separate views
|
||||
int textStart; ///< Starting x position of text within the view
|
||||
int zoomLevel;
|
||||
WhiteSpaceVisibility viewWhitespace;
|
||||
int whitespaceSize;
|
||||
IndentView viewIndentationGuides;
|
||||
bool viewEOL;
|
||||
ColourDesired caretcolour;
|
||||
ColourDesired additionalCaretColour;
|
||||
bool showCaretLineBackground;
|
||||
bool alwaysShowCaretLineBackground;
|
||||
ColourDesired caretLineBackground;
|
||||
int caretLineAlpha;
|
||||
ColourDesired edgecolour;
|
||||
int edgeState;
|
||||
int caretStyle;
|
||||
int caretWidth;
|
||||
bool someStylesProtected;
|
||||
bool someStylesForceCase;
|
||||
int extraFontFlag;
|
||||
int extraAscent;
|
||||
int extraDescent;
|
||||
int marginStyleOffset;
|
||||
int annotationVisible;
|
||||
int annotationStyleOffset;
|
||||
bool braceHighlightIndicatorSet;
|
||||
int braceHighlightIndicator;
|
||||
bool braceBadLightIndicatorSet;
|
||||
int braceBadLightIndicator;
|
||||
int theEdge;
|
||||
int marginNumberPadding; // the right-side padding of the number margin
|
||||
int ctrlCharPadding; // the padding around control character text blobs
|
||||
int lastSegItalicsOffset; // the offset so as not to clip italic characters at EOLs
|
||||
|
||||
// Wrapping support
|
||||
WrapMode wrapState;
|
||||
int wrapVisualFlags;
|
||||
int wrapVisualFlagsLocation;
|
||||
int wrapVisualStartIndent;
|
||||
int wrapIndentMode; // SC_WRAPINDENT_FIXED, _SAME, _INDENT
|
||||
|
||||
ViewStyle();
|
||||
ViewStyle(const ViewStyle &source);
|
||||
~ViewStyle();
|
||||
void Init(size_t stylesSize_=64);
|
||||
void Refresh(Surface &surface, int tabInChars);
|
||||
void ReleaseAllExtendedStyles();
|
||||
int AllocateExtendedStyles(int numberStyles);
|
||||
void EnsureStyle(size_t index);
|
||||
void ResetDefaultStyle();
|
||||
void ClearStyles();
|
||||
void SetStyleFontName(int styleIndex, const char *name);
|
||||
bool ProtectionActive() const;
|
||||
int ExternalMarginWidth() const;
|
||||
bool ValidStyle(size_t styleIndex) const;
|
||||
void CalcLargestMarkerHeight();
|
||||
ColourDesired WrapColour() const;
|
||||
bool SetWrapState(int wrapState_);
|
||||
bool SetWrapVisualFlags(int wrapVisualFlags_);
|
||||
bool SetWrapVisualFlagsLocation(int wrapVisualFlagsLocation_);
|
||||
bool SetWrapVisualStartIndent(int wrapVisualStartIndent_);
|
||||
bool SetWrapIndentMode(int wrapIndentMode_);
|
||||
|
||||
private:
|
||||
void AllocStyles(size_t sizeNew);
|
||||
void CreateAndAddFont(const FontSpecification &fs);
|
||||
FontRealised *Find(const FontSpecification &fs);
|
||||
void FindMaxAscentDescent();
|
||||
// Private so can only be copied through copy constructor which ensures font names initialised correctly
|
||||
ViewStyle &operator=(const ViewStyle &);
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
233
third-party/scintilla/WordList.cxx
vendored
Normal file
233
third-party/scintilla/WordList.cxx
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file KeyWords.cxx
|
||||
** Colourise for particular languages.
|
||||
**/
|
||||
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "StringCopy.h"
|
||||
#include "WordList.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Creates an array that points into each word in the string and puts \0 terminators
|
||||
* after each word.
|
||||
*/
|
||||
static char **ArrayFromWordList(char *wordlist, int *len, bool onlyLineEnds = false) {
|
||||
const unsigned char cr = '\r', lf = '\n', tab = '\t', space = ' ';
|
||||
int prev = '\n';
|
||||
int words = 0;
|
||||
// For rapid determination of whether a character is a separator, build
|
||||
// a look up table.
|
||||
bool wordSeparator[256];
|
||||
for (int i=0; i<256; i++) {
|
||||
wordSeparator[i] = false;
|
||||
}
|
||||
wordSeparator[cr] = true;
|
||||
wordSeparator[lf] = true;
|
||||
if (!onlyLineEnds) {
|
||||
wordSeparator[space] = true;
|
||||
wordSeparator[tab] = true;
|
||||
}
|
||||
for (int j = 0; wordlist[j]; j++) {
|
||||
int curr = static_cast<unsigned char>(wordlist[j]);
|
||||
if (!wordSeparator[curr] && wordSeparator[prev])
|
||||
words++;
|
||||
prev = curr;
|
||||
}
|
||||
char **keywords = new char *[words + 1];
|
||||
int wordsStore = 0;
|
||||
const size_t slen = strlen(wordlist);
|
||||
if (words) {
|
||||
prev = '\0';
|
||||
for (size_t k = 0; k < slen; k++) {
|
||||
if (!wordSeparator[static_cast<unsigned char>(wordlist[k])]) {
|
||||
if (!prev) {
|
||||
keywords[wordsStore] = &wordlist[k];
|
||||
wordsStore++;
|
||||
}
|
||||
} else {
|
||||
wordlist[k] = '\0';
|
||||
}
|
||||
prev = wordlist[k];
|
||||
}
|
||||
}
|
||||
keywords[wordsStore] = &wordlist[slen];
|
||||
*len = wordsStore;
|
||||
return keywords;
|
||||
}
|
||||
|
||||
WordList::WordList(bool onlyLineEnds_) :
|
||||
words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_) {
|
||||
}
|
||||
|
||||
WordList::~WordList() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
WordList::operator bool() const {
|
||||
return len ? true : false;
|
||||
}
|
||||
|
||||
bool WordList::operator!=(const WordList &other) const {
|
||||
if (len != other.len)
|
||||
return true;
|
||||
for (int i=0; i<len; i++) {
|
||||
if (strcmp(words[i], other.words[i]) != 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int WordList::Length() const {
|
||||
return len;
|
||||
}
|
||||
|
||||
void WordList::Clear() {
|
||||
delete []list;
|
||||
delete []words;
|
||||
words = 0;
|
||||
list = 0;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
static bool cmpWords(const char *a, const char *b) {
|
||||
return strcmp(a, b) < 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int cmpWords(const void *a, const void *b) {
|
||||
return strcmp(*static_cast<const char * const *>(a), *static_cast<const char * const *>(b));
|
||||
}
|
||||
|
||||
static void SortWordList(char **words, unsigned int len) {
|
||||
qsort(reinterpret_cast<void *>(words), len, sizeof(*words), cmpWords);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void WordList::Set(const char *s) {
|
||||
Clear();
|
||||
const size_t lenS = strlen(s) + 1;
|
||||
list = new char[lenS];
|
||||
memcpy(list, s, lenS);
|
||||
words = ArrayFromWordList(list, &len, onlyLineEnds);
|
||||
#ifdef _MSC_VER
|
||||
std::sort(words, words + len, cmpWords);
|
||||
#else
|
||||
SortWordList(words, len);
|
||||
#endif
|
||||
for (unsigned int k = 0; k < ELEMENTS(starts); k++)
|
||||
starts[k] = -1;
|
||||
for (int l = len - 1; l >= 0; l--) {
|
||||
unsigned char indexChar = words[l][0];
|
||||
starts[indexChar] = l;
|
||||
}
|
||||
}
|
||||
|
||||
/** Check whether a string is in the list.
|
||||
* List elements are either exact matches or prefixes.
|
||||
* Prefix elements start with '^' and match all strings that start with the rest of the element
|
||||
* so '^GTK_' matches 'GTK_X', 'GTK_MAJOR_VERSION', and 'GTK_'.
|
||||
*/
|
||||
bool WordList::InList(const char *s) const {
|
||||
if (0 == words)
|
||||
return false;
|
||||
unsigned char firstChar = s[0];
|
||||
const unsigned char roof = '^';
|
||||
int j = starts[firstChar];
|
||||
if (j >= 0) {
|
||||
while (static_cast<unsigned char>(words[j][0]) == firstChar) {
|
||||
if (s[1] == words[j][1]) {
|
||||
const char *a = words[j] + 1;
|
||||
const char *b = s + 1;
|
||||
while (*a && *a == *b) {
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
if (!*a && !*b)
|
||||
return true;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
j = starts[roof];
|
||||
if (j >= 0) {
|
||||
while (words[j][0] == (char)roof) {
|
||||
const char *a = words[j] + 1;
|
||||
const char *b = s;
|
||||
while (*a && *a == *b) {
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
if (!*a)
|
||||
return true;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** similar to InList, but word s can be a substring of keyword.
|
||||
* eg. the keyword define is defined as def~ine. This means the word must start
|
||||
* with def to be a keyword, but also defi, defin and define are valid.
|
||||
* The marker is ~ in this case.
|
||||
*/
|
||||
bool WordList::InListAbbreviated(const char *s, const char marker) const {
|
||||
if (0 == words)
|
||||
return false;
|
||||
unsigned char firstChar = s[0];
|
||||
const unsigned char roof = '^';
|
||||
int j = starts[firstChar];
|
||||
if (j >= 0) {
|
||||
while (static_cast<unsigned char>(words[j][0]) == firstChar) {
|
||||
bool isSubword = false;
|
||||
int start = 1;
|
||||
if (words[j][1] == marker) {
|
||||
isSubword = true;
|
||||
start++;
|
||||
}
|
||||
if (s[1] == words[j][start]) {
|
||||
const char *a = words[j] + start;
|
||||
const char *b = s + 1;
|
||||
while (*a && *a == *b) {
|
||||
a++;
|
||||
if (*a == marker) {
|
||||
isSubword = true;
|
||||
a++;
|
||||
}
|
||||
b++;
|
||||
}
|
||||
if ((!*a || isSubword) && !*b)
|
||||
return true;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
j = starts[roof];
|
||||
if (j >= 0) {
|
||||
while (words[j][0] == (char)roof) {
|
||||
const char *a = words[j] + 1;
|
||||
const char *b = s;
|
||||
while (*a && *a == *b) {
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
if (!*a)
|
||||
return true;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *WordList::WordAt(int n) const {
|
||||
return words[n];
|
||||
}
|
||||
|
||||
46
third-party/scintilla/WordList.h
vendored
Normal file
46
third-party/scintilla/WordList.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file WordList.h
|
||||
** Hold a list of words.
|
||||
**/
|
||||
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef WORDLIST_H
|
||||
#define WORDLIST_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
/**
|
||||
*/
|
||||
class WordList {
|
||||
// Each word contains at least one character - a empty word acts as sentinel at the end.
|
||||
char **words;
|
||||
char *list;
|
||||
int len;
|
||||
bool onlyLineEnds; ///< Delimited by any white space or only line ends
|
||||
int starts[256];
|
||||
|
||||
// no copy ctr or assignment op
|
||||
WordList(const WordList &);
|
||||
WordList &operator =(const WordList &);
|
||||
|
||||
public:
|
||||
explicit WordList(bool onlyLineEnds_ = false);
|
||||
~WordList();
|
||||
operator bool() const;
|
||||
bool operator!=(const WordList &other) const;
|
||||
int Length() const;
|
||||
void Clear();
|
||||
void Set(const char *s);
|
||||
bool InList(const char *s) const;
|
||||
bool InListAbbreviated(const char *s, const char marker) const;
|
||||
const char *WordAt(int n) const;
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
302
third-party/scintilla/XPM.cxx
vendored
Normal file
302
third-party/scintilla/XPM.cxx
vendored
Normal file
@@ -0,0 +1,302 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file XPM.cxx
|
||||
** Define a class that holds data in the X Pixmap (XPM) format.
|
||||
**/
|
||||
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "XPM.h"
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
using namespace Scintilla;
|
||||
#endif
|
||||
|
||||
static const char *NextField(const char *s) {
|
||||
// In case there are leading spaces in the string
|
||||
while (*s && *s == ' ') {
|
||||
s++;
|
||||
}
|
||||
while (*s && *s != ' ') {
|
||||
s++;
|
||||
}
|
||||
while (*s && *s == ' ') {
|
||||
s++;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// Data lines in XPM can be terminated either with NUL or "
|
||||
static size_t MeasureLength(const char *s) {
|
||||
size_t i = 0;
|
||||
while (s[i] && (s[i] != '\"'))
|
||||
i++;
|
||||
return i;
|
||||
}
|
||||
|
||||
ColourDesired XPM::ColourFromCode(int ch) const {
|
||||
return colourCodeTable[ch];
|
||||
}
|
||||
|
||||
void XPM::FillRun(Surface *surface, int code, int startX, int y, int x) {
|
||||
if ((code != codeTransparent) && (startX != x)) {
|
||||
PRectangle rc = PRectangle::FromInts(startX, y, x, y + 1);
|
||||
surface->FillRectangle(rc, ColourFromCode(code));
|
||||
}
|
||||
}
|
||||
|
||||
XPM::XPM(const char *textForm) {
|
||||
Init(textForm);
|
||||
}
|
||||
|
||||
XPM::XPM(const char *const *linesForm) {
|
||||
Init(linesForm);
|
||||
}
|
||||
|
||||
XPM::~XPM() {
|
||||
}
|
||||
|
||||
void XPM::Init(const char *textForm) {
|
||||
// Test done is two parts to avoid possibility of overstepping the memory
|
||||
// if memcmp implemented strangely. Must be 4 bytes at least at destination.
|
||||
if ((0 == memcmp(textForm, "/* X", 4)) && (0 == memcmp(textForm, "/* XPM */", 9))) {
|
||||
// Build the lines form out of the text form
|
||||
std::vector<const char *> linesForm = LinesFormFromTextForm(textForm);
|
||||
if (!linesForm.empty()) {
|
||||
Init(&linesForm[0]);
|
||||
}
|
||||
} else {
|
||||
// It is really in line form
|
||||
Init(reinterpret_cast<const char * const *>(textForm));
|
||||
}
|
||||
}
|
||||
|
||||
void XPM::Init(const char *const *linesForm) {
|
||||
height = 1;
|
||||
width = 1;
|
||||
nColours = 1;
|
||||
pixels.clear();
|
||||
codeTransparent = ' ';
|
||||
if (!linesForm)
|
||||
return;
|
||||
|
||||
std::fill(colourCodeTable, colourCodeTable+256, 0);
|
||||
const char *line0 = linesForm[0];
|
||||
width = atoi(line0);
|
||||
line0 = NextField(line0);
|
||||
height = atoi(line0);
|
||||
// limit to 8640p
|
||||
if (width > 15360) width = 15360;
|
||||
if (height > 8640) height = 8640;
|
||||
|
||||
pixels.resize(width*height);
|
||||
line0 = NextField(line0);
|
||||
nColours = atoi(line0);
|
||||
if (nColours > 65536) nColours = 65536;
|
||||
line0 = NextField(line0);
|
||||
if (atoi(line0) != 1) {
|
||||
// Only one char per pixel is supported
|
||||
return;
|
||||
}
|
||||
|
||||
for (int c=0; c<nColours; c++) {
|
||||
const char *colourDef = linesForm[c+1];
|
||||
int code = static_cast<unsigned char>(colourDef[0]);
|
||||
colourDef += 4;
|
||||
ColourDesired colour(0xff, 0xff, 0xff);
|
||||
if (*colourDef == '#') {
|
||||
colour.Set(colourDef);
|
||||
} else {
|
||||
codeTransparent = static_cast<char>(code);
|
||||
}
|
||||
colourCodeTable[code] = colour;
|
||||
}
|
||||
|
||||
for (int y=0; y<height; y++) {
|
||||
const char *lform = linesForm[y+nColours+1];
|
||||
size_t len = MeasureLength(lform);
|
||||
for (size_t x = 0; x<len; x++)
|
||||
pixels[y * width + x] = static_cast<unsigned char>(lform[x]);
|
||||
}
|
||||
}
|
||||
|
||||
void XPM::Draw(Surface *surface, PRectangle &rc) {
|
||||
if (pixels.empty()) {
|
||||
return;
|
||||
}
|
||||
// Centre the pixmap
|
||||
int startY = static_cast<int>(rc.top + (rc.Height() - height) / 2);
|
||||
int startX = static_cast<int>(rc.left + (rc.Width() - width) / 2);
|
||||
for (int y=0; y<height; y++) {
|
||||
int prevCode = 0;
|
||||
int xStartRun = 0;
|
||||
for (int x=0; x<width; x++) {
|
||||
int code = pixels[y * width + x];
|
||||
if (code != prevCode) {
|
||||
FillRun(surface, prevCode, startX + xStartRun, startY + y, startX + x);
|
||||
xStartRun = x;
|
||||
prevCode = code;
|
||||
}
|
||||
}
|
||||
FillRun(surface, prevCode, startX + xStartRun, startY + y, startX + width);
|
||||
}
|
||||
}
|
||||
|
||||
void XPM::PixelAt(int x, int y, ColourDesired &colour, bool &transparent) const {
|
||||
if (pixels.empty() || (x<0) || (x >= width) || (y<0) || (y >= height)) {
|
||||
colour = 0;
|
||||
transparent = true;
|
||||
return;
|
||||
}
|
||||
int code = pixels[y * width + x];
|
||||
transparent = code == codeTransparent;
|
||||
if (transparent) {
|
||||
colour = 0;
|
||||
} else {
|
||||
colour = ColourFromCode(code).AsLong();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<const char *> XPM::LinesFormFromTextForm(const char *textForm) {
|
||||
// Build the lines form out of the text form
|
||||
std::vector<const char *> linesForm;
|
||||
int countQuotes = 0;
|
||||
int strings=1;
|
||||
int j=0;
|
||||
for (; countQuotes < (2*strings) && textForm[j] != '\0'; j++) {
|
||||
if (textForm[j] == '\"') {
|
||||
if (countQuotes == 0) {
|
||||
// First field: width, height, number of colors, chars per pixel
|
||||
const char *line0 = textForm + j + 1;
|
||||
// Skip width
|
||||
line0 = NextField(line0);
|
||||
// Add 1 line for each pixel of height
|
||||
strings += atoi(line0);
|
||||
line0 = NextField(line0);
|
||||
// Add 1 line for each colour
|
||||
strings += atoi(line0);
|
||||
}
|
||||
if (countQuotes / 2 >= strings) {
|
||||
break; // Bad height or number of colors!
|
||||
}
|
||||
if ((countQuotes & 1) == 0) {
|
||||
linesForm.push_back(textForm + j + 1);
|
||||
}
|
||||
countQuotes++;
|
||||
}
|
||||
}
|
||||
if (textForm[j] == '\0' || countQuotes / 2 > strings) {
|
||||
// Malformed XPM! Height + number of colors too high or too low
|
||||
linesForm.clear();
|
||||
}
|
||||
return linesForm;
|
||||
}
|
||||
|
||||
RGBAImage::RGBAImage(int width_, int height_, float scale_, const unsigned char *pixels_) :
|
||||
height(height_), width(width_), scale(scale_) {
|
||||
if (pixels_) {
|
||||
pixelBytes.assign(pixels_, pixels_ + CountBytes());
|
||||
} else {
|
||||
pixelBytes.resize(CountBytes());
|
||||
}
|
||||
}
|
||||
|
||||
RGBAImage::RGBAImage(const XPM &xpm) {
|
||||
height = xpm.GetHeight();
|
||||
width = xpm.GetWidth();
|
||||
scale = 1;
|
||||
pixelBytes.resize(CountBytes());
|
||||
for (int y=0; y<height; y++) {
|
||||
for (int x=0; x<width; x++) {
|
||||
ColourDesired colour;
|
||||
bool transparent = false;
|
||||
xpm.PixelAt(x, y, colour, transparent);
|
||||
SetPixel(x, y, colour, transparent ? 0 : 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RGBAImage::~RGBAImage() {
|
||||
}
|
||||
|
||||
int RGBAImage::CountBytes() const {
|
||||
return width * height * 4;
|
||||
}
|
||||
|
||||
const unsigned char *RGBAImage::Pixels() const {
|
||||
return &pixelBytes[0];
|
||||
}
|
||||
|
||||
void RGBAImage::SetPixel(int x, int y, ColourDesired colour, int alpha) {
|
||||
unsigned char *pixel = &pixelBytes[0] + (y*width+x) * 4;
|
||||
// RGBA
|
||||
pixel[0] = static_cast<unsigned char>(colour.GetRed());
|
||||
pixel[1] = static_cast<unsigned char>(colour.GetGreen());
|
||||
pixel[2] = static_cast<unsigned char>(colour.GetBlue());
|
||||
pixel[3] = static_cast<unsigned char>(alpha);
|
||||
}
|
||||
|
||||
RGBAImageSet::RGBAImageSet() : height(-1), width(-1){
|
||||
}
|
||||
|
||||
RGBAImageSet::~RGBAImageSet() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
/// Remove all images.
|
||||
void RGBAImageSet::Clear() {
|
||||
for (ImageMap::iterator it=images.begin(); it != images.end(); ++it) {
|
||||
delete it->second;
|
||||
it->second = 0;
|
||||
}
|
||||
images.clear();
|
||||
height = -1;
|
||||
width = -1;
|
||||
}
|
||||
|
||||
/// Add an image.
|
||||
void RGBAImageSet::Add(int ident, RGBAImage *image) {
|
||||
ImageMap::iterator it=images.find(ident);
|
||||
if (it == images.end()) {
|
||||
images[ident] = image;
|
||||
} else {
|
||||
delete it->second;
|
||||
it->second = image;
|
||||
}
|
||||
height = -1;
|
||||
width = -1;
|
||||
}
|
||||
|
||||
/// Get image by id.
|
||||
RGBAImage *RGBAImageSet::Get(int ident) {
|
||||
ImageMap::iterator it = images.find(ident);
|
||||
if (it != images.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Give the largest height of the set.
|
||||
int RGBAImageSet::GetHeight() const {
|
||||
if (height < 0) {
|
||||
for (ImageMap::const_iterator it=images.begin(); it != images.end(); ++it) {
|
||||
if (height < it->second->GetHeight()) {
|
||||
height = it->second->GetHeight();
|
||||
}
|
||||
}
|
||||
}
|
||||
return (height > 0) ? height : 0;
|
||||
}
|
||||
|
||||
/// Give the largest width of the set.
|
||||
int RGBAImageSet::GetWidth() const {
|
||||
if (width < 0) {
|
||||
for (ImageMap::const_iterator it=images.begin(); it != images.end(); ++it) {
|
||||
if (width < it->second->GetWidth()) {
|
||||
width = it->second->GetWidth();
|
||||
}
|
||||
}
|
||||
}
|
||||
return (width > 0) ? width : 0;
|
||||
}
|
||||
94
third-party/scintilla/XPM.h
vendored
Normal file
94
third-party/scintilla/XPM.h
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file XPM.h
|
||||
** Define a classes to hold image data in the X Pixmap (XPM) and RGBA formats.
|
||||
**/
|
||||
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef XPM_H
|
||||
#define XPM_H
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
namespace Scintilla {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Hold a pixmap in XPM format.
|
||||
*/
|
||||
class XPM {
|
||||
int height;
|
||||
int width;
|
||||
int nColours;
|
||||
std::vector<unsigned char> pixels;
|
||||
ColourDesired colourCodeTable[256];
|
||||
char codeTransparent;
|
||||
ColourDesired ColourFromCode(int ch) const;
|
||||
void FillRun(Surface *surface, int code, int startX, int y, int x);
|
||||
public:
|
||||
explicit XPM(const char *textForm);
|
||||
explicit XPM(const char *const *linesForm);
|
||||
~XPM();
|
||||
void Init(const char *textForm);
|
||||
void Init(const char *const *linesForm);
|
||||
/// Decompose image into runs and use FillRectangle for each run
|
||||
void Draw(Surface *surface, PRectangle &rc);
|
||||
int GetHeight() const { return height; }
|
||||
int GetWidth() const { return width; }
|
||||
void PixelAt(int x, int y, ColourDesired &colour, bool &transparent) const;
|
||||
private:
|
||||
static std::vector<const char *>LinesFormFromTextForm(const char *textForm);
|
||||
};
|
||||
|
||||
/**
|
||||
* A translucent image stored as a sequence of RGBA bytes.
|
||||
*/
|
||||
class RGBAImage {
|
||||
// Private so RGBAImage objects can not be copied
|
||||
RGBAImage(const RGBAImage &);
|
||||
RGBAImage &operator=(const RGBAImage &);
|
||||
int height;
|
||||
int width;
|
||||
float scale;
|
||||
std::vector<unsigned char> pixelBytes;
|
||||
public:
|
||||
RGBAImage(int width_, int height_, float scale_, const unsigned char *pixels_);
|
||||
explicit RGBAImage(const XPM &xpm);
|
||||
virtual ~RGBAImage();
|
||||
int GetHeight() const { return height; }
|
||||
int GetWidth() const { return width; }
|
||||
float GetScale() const { return scale; }
|
||||
float GetScaledHeight() const { return height / scale; }
|
||||
float GetScaledWidth() const { return width / scale; }
|
||||
int CountBytes() const;
|
||||
const unsigned char *Pixels() const;
|
||||
void SetPixel(int x, int y, ColourDesired colour, int alpha=0xff);
|
||||
};
|
||||
|
||||
/**
|
||||
* A collection of RGBAImage pixmaps indexed by integer id.
|
||||
*/
|
||||
class RGBAImageSet {
|
||||
typedef std::map<int, RGBAImage*> ImageMap;
|
||||
ImageMap images;
|
||||
mutable int height; ///< Memorize largest height of the set.
|
||||
mutable int width; ///< Memorize largest width of the set.
|
||||
public:
|
||||
RGBAImageSet();
|
||||
~RGBAImageSet();
|
||||
/// Remove all images.
|
||||
void Clear();
|
||||
/// Add an image.
|
||||
void Add(int ident, RGBAImage *image);
|
||||
/// Get image by id.
|
||||
RGBAImage *Get(int ident);
|
||||
/// Give the largest height of the set.
|
||||
int GetHeight() const;
|
||||
/// Give the largest width of the set.
|
||||
int GetWidth() const;
|
||||
};
|
||||
|
||||
#ifdef SCI_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user