mirror of
https://github.com/NohamR/Reclass.git
synced 2026-05-10 19:59:21 +00:00
Initial commit: ReclassX structured binary editor
This commit is contained in:
293
third_party/qscintilla/scintilla/src/AutoComplete.cpp
vendored
Normal file
293
third_party/qscintilla/scintilla/src/AutoComplete.cpp
vendored
Normal file
@@ -0,0 +1,293 @@
|
||||
// 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 <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
#include "CharacterSet.h"
|
||||
#include "Position.h"
|
||||
#include "AutoComplete.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
AutoComplete::AutoComplete() :
|
||||
active(false),
|
||||
separator(' '),
|
||||
typesep('?'),
|
||||
ignoreCase(false),
|
||||
chooseSingle(false),
|
||||
posStart(0),
|
||||
startLen(0),
|
||||
cancelAtStartPos(true),
|
||||
autoHide(true),
|
||||
dropRestOfWord(false),
|
||||
ignoreCaseBehaviour(SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE),
|
||||
widthLBDefault(100),
|
||||
heightLBDefault(100),
|
||||
autoSort(SC_ORDER_PRESORTED) {
|
||||
lb.reset(ListBox::Allocate());
|
||||
}
|
||||
|
||||
AutoComplete::~AutoComplete() {
|
||||
if (lb) {
|
||||
lb->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
bool AutoComplete::Active() const noexcept {
|
||||
return active;
|
||||
}
|
||||
|
||||
void AutoComplete::Start(Window &parent, int ctrlID,
|
||||
Sci::Position position, Point location, Sci::Position 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) const noexcept {
|
||||
return ch && (stopChars.find(ch) != std::string::npos);
|
||||
}
|
||||
|
||||
void AutoComplete::SetFillUpChars(const char *fillUpChars_) {
|
||||
fillUpChars = fillUpChars_;
|
||||
}
|
||||
|
||||
bool AutoComplete::IsFillUpChar(char ch) const noexcept {
|
||||
return ch && (fillUpChars.find(ch) != std::string::npos);
|
||||
}
|
||||
|
||||
void AutoComplete::SetSeparator(char separator_) {
|
||||
separator = separator_;
|
||||
}
|
||||
|
||||
char AutoComplete::GetSeparator() const noexcept {
|
||||
return separator;
|
||||
}
|
||||
|
||||
void AutoComplete::SetTypesep(char separator_) {
|
||||
typesep = separator_;
|
||||
}
|
||||
|
||||
char AutoComplete::GetTypesep() const noexcept {
|
||||
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) {
|
||||
const int lenA = indices[a * 2 + 1] - indices[a * 2];
|
||||
const int lenB = indices[b * 2 + 1] - indices[b * 2];
|
||||
const 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 < static_cast<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];
|
||||
if (wordLen > maxItemLen-2)
|
||||
wordLen = maxItemLen - 2;
|
||||
memcpy(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 < static_cast<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) {
|
||||
const 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) {
|
||||
const 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]);
|
||||
}
|
||||
}
|
||||
|
||||
91
third_party/qscintilla/scintilla/src/AutoComplete.h
vendored
Normal file
91
third_party/qscintilla/scintilla/src/AutoComplete.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
/**
|
||||
*/
|
||||
class AutoComplete {
|
||||
bool active;
|
||||
std::string stopChars;
|
||||
std::string fillUpChars;
|
||||
char separator;
|
||||
char typesep; // Type seperator
|
||||
enum { maxItemLen=1000 };
|
||||
std::vector<int> sortMatrix;
|
||||
|
||||
public:
|
||||
|
||||
bool ignoreCase;
|
||||
bool chooseSingle;
|
||||
std::unique_ptr<ListBox> lb;
|
||||
Sci::Position posStart;
|
||||
Sci::Position 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 noexcept;
|
||||
|
||||
/// Display the auto completion list positioned to be near a character position
|
||||
void Start(Window &parent, int ctrlID, Sci::Position position, Point location,
|
||||
Sci::Position 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) const noexcept;
|
||||
|
||||
/// The fillup chars are characters which, when typed, fill up the selected word
|
||||
void SetFillUpChars(const char *fillUpChars_);
|
||||
bool IsFillUpChar(char ch) const noexcept;
|
||||
|
||||
/// The separator character is used when interpreting the list in SetList
|
||||
void SetSeparator(char separator_);
|
||||
char GetSeparator() const noexcept;
|
||||
|
||||
/// The typesep character is used for separating the word from the type
|
||||
void SetTypesep(char separator_);
|
||||
char GetTypesep() const noexcept;
|
||||
|
||||
/// 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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
332
third_party/qscintilla/scintilla/src/CallTip.cpp
vendored
Normal file
332
third_party/qscintilla/scintilla/src/CallTip.cpp
vendored
Normal file
@@ -0,0 +1,332 @@
|
||||
// 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 <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
|
||||
#include "StringCopy.h"
|
||||
#include "Position.h"
|
||||
#include "IntegerRectangle.h"
|
||||
#include "CallTip.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
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;
|
||||
const 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++) {
|
||||
const int endSeg = ends[seg];
|
||||
if (endSeg > startSeg) {
|
||||
if (IsArrowCharacter(s[startSeg])) {
|
||||
xEnd = x + widthArrow;
|
||||
const 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);
|
||||
const 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 + static_cast<int>(lround(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) {
|
||||
const PRectangle rcClientPos = wCallTip.GetClientPosition();
|
||||
const 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
|
||||
const int ascent = static_cast<int>(lround(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) {
|
||||
chunkEnd = chunkVal + strlen(chunkVal);
|
||||
moreChunks = false;
|
||||
}
|
||||
const int chunkOffset = static_cast<int>(chunkVal - val.c_str());
|
||||
const int chunkLength = static_cast<int>(chunkEnd - chunkVal);
|
||||
const int chunkEndOffset = chunkOffset + chunkLength;
|
||||
int thisStartHighlight = std::max(startHighlight, chunkOffset);
|
||||
thisStartHighlight = std::min(thisStartHighlight, chunkEndOffset);
|
||||
thisStartHighlight -= chunkOffset;
|
||||
int thisEndHighlight = std::max(endHighlight, chunkOffset);
|
||||
thisEndHighlight = std::min(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 = std::max(maxWidth, x);
|
||||
}
|
||||
return maxWidth;
|
||||
}
|
||||
|
||||
void CallTip::PaintCT(Surface *surfaceWindow) {
|
||||
if (val.empty())
|
||||
return;
|
||||
const PRectangle rcClientPos = wCallTip.GetClientPosition();
|
||||
const PRectangle rcClientSize(0.0f, 0.0f, rcClientPos.right - rcClientPos.left,
|
||||
rcClientPos.bottom - rcClientPos.top);
|
||||
const 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
|
||||
const IntegerRectangle ircClientSize(rcClientSize);
|
||||
surfaceWindow->MoveTo(0, ircClientSize.bottom - 1);
|
||||
surfaceWindow->PenColour(colourShade);
|
||||
surfaceWindow->LineTo(ircClientSize.right - 1, ircClientSize.bottom - 1);
|
||||
surfaceWindow->LineTo(ircClientSize.right - 1, 0);
|
||||
surfaceWindow->PenColour(colourLight);
|
||||
surfaceWindow->LineTo(0, 0);
|
||||
surfaceWindow->LineTo(0, ircClientSize.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(Sci::Position pos, Point pt, int textHeight, const char *defn,
|
||||
const char *faceName, int size,
|
||||
int codePage_, int characterSet,
|
||||
int technology, const Window &wParent) {
|
||||
clickPlace = 0;
|
||||
val = defn;
|
||||
codePage = codePage_;
|
||||
std::unique_ptr<Surface> surfaceMeasure(Surface::Allocate(technology));
|
||||
surfaceMeasure->Init(wParent.GetID());
|
||||
surfaceMeasure->SetUnicodeMode(SC_CP_UTF8 == codePage);
|
||||
surfaceMeasure->SetDBCSMode(codePage);
|
||||
startHighlight = 0;
|
||||
endHighlight = 0;
|
||||
inCallTipMode = true;
|
||||
posStartCallTip = pos;
|
||||
const XYPOSITION deviceHeight = static_cast<XYPOSITION>(surfaceMeasure->DeviceHeightFont(size));
|
||||
const 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!
|
||||
const int numLines = 1 + static_cast<int>(std::count(val.begin(), val.end(), '\n'));
|
||||
rectUp = PRectangle(0,0,0,0);
|
||||
rectDown = PRectangle(0,0,0,0);
|
||||
offsetMain = insetX; // changed to right edge of any arrows
|
||||
const int width = PaintContents(surfaceMeasure.get(), false) + insetX;
|
||||
lineHeight = static_cast<int>(lround(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.
|
||||
const int height = lineHeight * numLines - static_cast<int>(surfaceMeasure->InternalLeading(font)) + borderHeight * 2;
|
||||
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;
|
||||
}
|
||||
91
third_party/qscintilla/scintilla/src/CallTip.h
vendored
Normal file
91
third_party/qscintilla/scintilla/src/CallTip.h
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
/**
|
||||
*/
|
||||
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
|
||||
|
||||
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 ch) const;
|
||||
int NextTabPos(int x) const;
|
||||
|
||||
public:
|
||||
Window wCallTip;
|
||||
Window wDraw;
|
||||
bool inCallTipMode;
|
||||
Sci::Position 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();
|
||||
// Deleted so CallTip objects can not be copied.
|
||||
CallTip(const CallTip &) = delete;
|
||||
CallTip(CallTip &&) = delete;
|
||||
CallTip &operator=(const CallTip &) = delete;
|
||||
CallTip &operator=(CallTip &&) = delete;
|
||||
~CallTip();
|
||||
|
||||
void PaintCT(Surface *surfaceWindow);
|
||||
|
||||
void MouseClick(Point pt);
|
||||
|
||||
/// Setup the calltip and return a rectangle of the area required.
|
||||
PRectangle CallTipStart(Sci::Position pos, Point pt, int textHeight, const char *defn,
|
||||
const char *faceName, int size, int codePage_,
|
||||
int characterSet, int technology, const 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);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
819
third_party/qscintilla/scintilla/src/CaseConvert.cpp
vendored
Normal file
819
third_party/qscintilla/scintilla/src/CaseConvert.cpp
vendored
Normal file
@@ -0,0 +1,819 @@
|
||||
// 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 <cstring>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "StringCopy.h"
|
||||
#include "CaseConvert.h"
|
||||
#include "UniConversion.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
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,48,2,
|
||||
1377,1329,38,1,
|
||||
4304,7312,43,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,14,2,
|
||||
42787,42786,7,2,
|
||||
42803,42802,31,2,
|
||||
42879,42878,5,2,
|
||||
42903,42902,10,2,
|
||||
65345,65313,26,1,
|
||||
66600,66560,40,1,
|
||||
66776,66736,36,1,
|
||||
68800,68736,51,1,
|
||||
71872,71840,32,1,
|
||||
93792,93760,32,1,
|
||||
125218,125184,34,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,
|
||||
604,42923,
|
||||
608,403,
|
||||
609,42924,
|
||||
611,404,
|
||||
613,42893,
|
||||
614,42922,
|
||||
616,407,
|
||||
617,406,
|
||||
618,42926,
|
||||
619,11362,
|
||||
620,42925,
|
||||
623,412,
|
||||
625,11374,
|
||||
626,413,
|
||||
629,415,
|
||||
637,11364,
|
||||
640,422,
|
||||
643,425,
|
||||
647,42929,
|
||||
648,430,
|
||||
649,580,
|
||||
650,433,
|
||||
651,434,
|
||||
652,581,
|
||||
658,439,
|
||||
669,42930,
|
||||
670,42928,
|
||||
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,
|
||||
1011,895,
|
||||
1016,1015,
|
||||
1019,1018,
|
||||
1231,1216,
|
||||
4349,7357,
|
||||
4350,7358,
|
||||
4351,7359,
|
||||
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,
|
||||
42933,42932,
|
||||
42935,42934,
|
||||
42937,42936,
|
||||
43859,42931,
|
||||
|
||||
//--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\x8e\xa0|||\xea\xad\xb0|"
|
||||
"\xe1\x8e\xa1|||\xea\xad\xb1|"
|
||||
"\xe1\x8e\xa2|||\xea\xad\xb2|"
|
||||
"\xe1\x8e\xa3|||\xea\xad\xb3|"
|
||||
"\xe1\x8e\xa4|||\xea\xad\xb4|"
|
||||
"\xe1\x8e\xa5|||\xea\xad\xb5|"
|
||||
"\xe1\x8e\xa6|||\xea\xad\xb6|"
|
||||
"\xe1\x8e\xa7|||\xea\xad\xb7|"
|
||||
"\xe1\x8e\xa8|||\xea\xad\xb8|"
|
||||
"\xe1\x8e\xa9|||\xea\xad\xb9|"
|
||||
"\xe1\x8e\xaa|||\xea\xad\xba|"
|
||||
"\xe1\x8e\xab|||\xea\xad\xbb|"
|
||||
"\xe1\x8e\xac|||\xea\xad\xbc|"
|
||||
"\xe1\x8e\xad|||\xea\xad\xbd|"
|
||||
"\xe1\x8e\xae|||\xea\xad\xbe|"
|
||||
"\xe1\x8e\xaf|||\xea\xad\xbf|"
|
||||
"\xe1\x8e\xb0|||\xea\xae\x80|"
|
||||
"\xe1\x8e\xb1|||\xea\xae\x81|"
|
||||
"\xe1\x8e\xb2|||\xea\xae\x82|"
|
||||
"\xe1\x8e\xb3|||\xea\xae\x83|"
|
||||
"\xe1\x8e\xb4|||\xea\xae\x84|"
|
||||
"\xe1\x8e\xb5|||\xea\xae\x85|"
|
||||
"\xe1\x8e\xb6|||\xea\xae\x86|"
|
||||
"\xe1\x8e\xb7|||\xea\xae\x87|"
|
||||
"\xe1\x8e\xb8|||\xea\xae\x88|"
|
||||
"\xe1\x8e\xb9|||\xea\xae\x89|"
|
||||
"\xe1\x8e\xba|||\xea\xae\x8a|"
|
||||
"\xe1\x8e\xbb|||\xea\xae\x8b|"
|
||||
"\xe1\x8e\xbc|||\xea\xae\x8c|"
|
||||
"\xe1\x8e\xbd|||\xea\xae\x8d|"
|
||||
"\xe1\x8e\xbe|||\xea\xae\x8e|"
|
||||
"\xe1\x8e\xbf|||\xea\xae\x8f|"
|
||||
"\xe1\x8f\x80|||\xea\xae\x90|"
|
||||
"\xe1\x8f\x81|||\xea\xae\x91|"
|
||||
"\xe1\x8f\x82|||\xea\xae\x92|"
|
||||
"\xe1\x8f\x83|||\xea\xae\x93|"
|
||||
"\xe1\x8f\x84|||\xea\xae\x94|"
|
||||
"\xe1\x8f\x85|||\xea\xae\x95|"
|
||||
"\xe1\x8f\x86|||\xea\xae\x96|"
|
||||
"\xe1\x8f\x87|||\xea\xae\x97|"
|
||||
"\xe1\x8f\x88|||\xea\xae\x98|"
|
||||
"\xe1\x8f\x89|||\xea\xae\x99|"
|
||||
"\xe1\x8f\x8a|||\xea\xae\x9a|"
|
||||
"\xe1\x8f\x8b|||\xea\xae\x9b|"
|
||||
"\xe1\x8f\x8c|||\xea\xae\x9c|"
|
||||
"\xe1\x8f\x8d|||\xea\xae\x9d|"
|
||||
"\xe1\x8f\x8e|||\xea\xae\x9e|"
|
||||
"\xe1\x8f\x8f|||\xea\xae\x9f|"
|
||||
"\xe1\x8f\x90|||\xea\xae\xa0|"
|
||||
"\xe1\x8f\x91|||\xea\xae\xa1|"
|
||||
"\xe1\x8f\x92|||\xea\xae\xa2|"
|
||||
"\xe1\x8f\x93|||\xea\xae\xa3|"
|
||||
"\xe1\x8f\x94|||\xea\xae\xa4|"
|
||||
"\xe1\x8f\x95|||\xea\xae\xa5|"
|
||||
"\xe1\x8f\x96|||\xea\xae\xa6|"
|
||||
"\xe1\x8f\x97|||\xea\xae\xa7|"
|
||||
"\xe1\x8f\x98|||\xea\xae\xa8|"
|
||||
"\xe1\x8f\x99|||\xea\xae\xa9|"
|
||||
"\xe1\x8f\x9a|||\xea\xae\xaa|"
|
||||
"\xe1\x8f\x9b|||\xea\xae\xab|"
|
||||
"\xe1\x8f\x9c|||\xea\xae\xac|"
|
||||
"\xe1\x8f\x9d|||\xea\xae\xad|"
|
||||
"\xe1\x8f\x9e|||\xea\xae\xae|"
|
||||
"\xe1\x8f\x9f|||\xea\xae\xaf|"
|
||||
"\xe1\x8f\xa0|||\xea\xae\xb0|"
|
||||
"\xe1\x8f\xa1|||\xea\xae\xb1|"
|
||||
"\xe1\x8f\xa2|||\xea\xae\xb2|"
|
||||
"\xe1\x8f\xa3|||\xea\xae\xb3|"
|
||||
"\xe1\x8f\xa4|||\xea\xae\xb4|"
|
||||
"\xe1\x8f\xa5|||\xea\xae\xb5|"
|
||||
"\xe1\x8f\xa6|||\xea\xae\xb6|"
|
||||
"\xe1\x8f\xa7|||\xea\xae\xb7|"
|
||||
"\xe1\x8f\xa8|||\xea\xae\xb8|"
|
||||
"\xe1\x8f\xa9|||\xea\xae\xb9|"
|
||||
"\xe1\x8f\xaa|||\xea\xae\xba|"
|
||||
"\xe1\x8f\xab|||\xea\xae\xbb|"
|
||||
"\xe1\x8f\xac|||\xea\xae\xbc|"
|
||||
"\xe1\x8f\xad|||\xea\xae\xbd|"
|
||||
"\xe1\x8f\xae|||\xea\xae\xbe|"
|
||||
"\xe1\x8f\xaf|||\xea\xae\xbf|"
|
||||
"\xe1\x8f\xb0|||\xe1\x8f\xb8|"
|
||||
"\xe1\x8f\xb1|||\xe1\x8f\xb9|"
|
||||
"\xe1\x8f\xb2|||\xe1\x8f\xba|"
|
||||
"\xe1\x8f\xb3|||\xe1\x8f\xbb|"
|
||||
"\xe1\x8f\xb4|||\xe1\x8f\xbc|"
|
||||
"\xe1\x8f\xb5|||\xe1\x8f\xbd|"
|
||||
"\xe1\x8f\xb8|\xe1\x8f\xb0|\xe1\x8f\xb0||"
|
||||
"\xe1\x8f\xb9|\xe1\x8f\xb1|\xe1\x8f\xb1||"
|
||||
"\xe1\x8f\xba|\xe1\x8f\xb2|\xe1\x8f\xb2||"
|
||||
"\xe1\x8f\xbb|\xe1\x8f\xb3|\xe1\x8f\xb3||"
|
||||
"\xe1\x8f\xbc|\xe1\x8f\xb4|\xe1\x8f\xb4||"
|
||||
"\xe1\x8f\xbd|\xe1\x8f\xb5|\xe1\x8f\xb5||"
|
||||
"\xe1\xb2\x80|\xd0\xb2|\xd0\x92||"
|
||||
"\xe1\xb2\x81|\xd0\xb4|\xd0\x94||"
|
||||
"\xe1\xb2\x82|\xd0\xbe|\xd0\x9e||"
|
||||
"\xe1\xb2\x83|\xd1\x81|\xd0\xa1||"
|
||||
"\xe1\xb2\x84|\xd1\x82|\xd0\xa2||"
|
||||
"\xe1\xb2\x85|\xd1\x82|\xd0\xa2||"
|
||||
"\xe1\xb2\x86|\xd1\x8a|\xd0\xaa||"
|
||||
"\xe1\xb2\x87|\xd1\xa3|\xd1\xa2||"
|
||||
"\xe1\xb2\x88|\xea\x99\x8b|\xea\x99\x8a||"
|
||||
"\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|"
|
||||
"\xea\xad\xb0|\xe1\x8e\xa0|\xe1\x8e\xa0||"
|
||||
"\xea\xad\xb1|\xe1\x8e\xa1|\xe1\x8e\xa1||"
|
||||
"\xea\xad\xb2|\xe1\x8e\xa2|\xe1\x8e\xa2||"
|
||||
"\xea\xad\xb3|\xe1\x8e\xa3|\xe1\x8e\xa3||"
|
||||
"\xea\xad\xb4|\xe1\x8e\xa4|\xe1\x8e\xa4||"
|
||||
"\xea\xad\xb5|\xe1\x8e\xa5|\xe1\x8e\xa5||"
|
||||
"\xea\xad\xb6|\xe1\x8e\xa6|\xe1\x8e\xa6||"
|
||||
"\xea\xad\xb7|\xe1\x8e\xa7|\xe1\x8e\xa7||"
|
||||
"\xea\xad\xb8|\xe1\x8e\xa8|\xe1\x8e\xa8||"
|
||||
"\xea\xad\xb9|\xe1\x8e\xa9|\xe1\x8e\xa9||"
|
||||
"\xea\xad\xba|\xe1\x8e\xaa|\xe1\x8e\xaa||"
|
||||
"\xea\xad\xbb|\xe1\x8e\xab|\xe1\x8e\xab||"
|
||||
"\xea\xad\xbc|\xe1\x8e\xac|\xe1\x8e\xac||"
|
||||
"\xea\xad\xbd|\xe1\x8e\xad|\xe1\x8e\xad||"
|
||||
"\xea\xad\xbe|\xe1\x8e\xae|\xe1\x8e\xae||"
|
||||
"\xea\xad\xbf|\xe1\x8e\xaf|\xe1\x8e\xaf||"
|
||||
"\xea\xae\x80|\xe1\x8e\xb0|\xe1\x8e\xb0||"
|
||||
"\xea\xae\x81|\xe1\x8e\xb1|\xe1\x8e\xb1||"
|
||||
"\xea\xae\x82|\xe1\x8e\xb2|\xe1\x8e\xb2||"
|
||||
"\xea\xae\x83|\xe1\x8e\xb3|\xe1\x8e\xb3||"
|
||||
"\xea\xae\x84|\xe1\x8e\xb4|\xe1\x8e\xb4||"
|
||||
"\xea\xae\x85|\xe1\x8e\xb5|\xe1\x8e\xb5||"
|
||||
"\xea\xae\x86|\xe1\x8e\xb6|\xe1\x8e\xb6||"
|
||||
"\xea\xae\x87|\xe1\x8e\xb7|\xe1\x8e\xb7||"
|
||||
"\xea\xae\x88|\xe1\x8e\xb8|\xe1\x8e\xb8||"
|
||||
"\xea\xae\x89|\xe1\x8e\xb9|\xe1\x8e\xb9||"
|
||||
"\xea\xae\x8a|\xe1\x8e\xba|\xe1\x8e\xba||"
|
||||
"\xea\xae\x8b|\xe1\x8e\xbb|\xe1\x8e\xbb||"
|
||||
"\xea\xae\x8c|\xe1\x8e\xbc|\xe1\x8e\xbc||"
|
||||
"\xea\xae\x8d|\xe1\x8e\xbd|\xe1\x8e\xbd||"
|
||||
"\xea\xae\x8e|\xe1\x8e\xbe|\xe1\x8e\xbe||"
|
||||
"\xea\xae\x8f|\xe1\x8e\xbf|\xe1\x8e\xbf||"
|
||||
"\xea\xae\x90|\xe1\x8f\x80|\xe1\x8f\x80||"
|
||||
"\xea\xae\x91|\xe1\x8f\x81|\xe1\x8f\x81||"
|
||||
"\xea\xae\x92|\xe1\x8f\x82|\xe1\x8f\x82||"
|
||||
"\xea\xae\x93|\xe1\x8f\x83|\xe1\x8f\x83||"
|
||||
"\xea\xae\x94|\xe1\x8f\x84|\xe1\x8f\x84||"
|
||||
"\xea\xae\x95|\xe1\x8f\x85|\xe1\x8f\x85||"
|
||||
"\xea\xae\x96|\xe1\x8f\x86|\xe1\x8f\x86||"
|
||||
"\xea\xae\x97|\xe1\x8f\x87|\xe1\x8f\x87||"
|
||||
"\xea\xae\x98|\xe1\x8f\x88|\xe1\x8f\x88||"
|
||||
"\xea\xae\x99|\xe1\x8f\x89|\xe1\x8f\x89||"
|
||||
"\xea\xae\x9a|\xe1\x8f\x8a|\xe1\x8f\x8a||"
|
||||
"\xea\xae\x9b|\xe1\x8f\x8b|\xe1\x8f\x8b||"
|
||||
"\xea\xae\x9c|\xe1\x8f\x8c|\xe1\x8f\x8c||"
|
||||
"\xea\xae\x9d|\xe1\x8f\x8d|\xe1\x8f\x8d||"
|
||||
"\xea\xae\x9e|\xe1\x8f\x8e|\xe1\x8f\x8e||"
|
||||
"\xea\xae\x9f|\xe1\x8f\x8f|\xe1\x8f\x8f||"
|
||||
"\xea\xae\xa0|\xe1\x8f\x90|\xe1\x8f\x90||"
|
||||
"\xea\xae\xa1|\xe1\x8f\x91|\xe1\x8f\x91||"
|
||||
"\xea\xae\xa2|\xe1\x8f\x92|\xe1\x8f\x92||"
|
||||
"\xea\xae\xa3|\xe1\x8f\x93|\xe1\x8f\x93||"
|
||||
"\xea\xae\xa4|\xe1\x8f\x94|\xe1\x8f\x94||"
|
||||
"\xea\xae\xa5|\xe1\x8f\x95|\xe1\x8f\x95||"
|
||||
"\xea\xae\xa6|\xe1\x8f\x96|\xe1\x8f\x96||"
|
||||
"\xea\xae\xa7|\xe1\x8f\x97|\xe1\x8f\x97||"
|
||||
"\xea\xae\xa8|\xe1\x8f\x98|\xe1\x8f\x98||"
|
||||
"\xea\xae\xa9|\xe1\x8f\x99|\xe1\x8f\x99||"
|
||||
"\xea\xae\xaa|\xe1\x8f\x9a|\xe1\x8f\x9a||"
|
||||
"\xea\xae\xab|\xe1\x8f\x9b|\xe1\x8f\x9b||"
|
||||
"\xea\xae\xac|\xe1\x8f\x9c|\xe1\x8f\x9c||"
|
||||
"\xea\xae\xad|\xe1\x8f\x9d|\xe1\x8f\x9d||"
|
||||
"\xea\xae\xae|\xe1\x8f\x9e|\xe1\x8f\x9e||"
|
||||
"\xea\xae\xaf|\xe1\x8f\x9f|\xe1\x8f\x9f||"
|
||||
"\xea\xae\xb0|\xe1\x8f\xa0|\xe1\x8f\xa0||"
|
||||
"\xea\xae\xb1|\xe1\x8f\xa1|\xe1\x8f\xa1||"
|
||||
"\xea\xae\xb2|\xe1\x8f\xa2|\xe1\x8f\xa2||"
|
||||
"\xea\xae\xb3|\xe1\x8f\xa3|\xe1\x8f\xa3||"
|
||||
"\xea\xae\xb4|\xe1\x8f\xa4|\xe1\x8f\xa4||"
|
||||
"\xea\xae\xb5|\xe1\x8f\xa5|\xe1\x8f\xa5||"
|
||||
"\xea\xae\xb6|\xe1\x8f\xa6|\xe1\x8f\xa6||"
|
||||
"\xea\xae\xb7|\xe1\x8f\xa7|\xe1\x8f\xa7||"
|
||||
"\xea\xae\xb8|\xe1\x8f\xa8|\xe1\x8f\xa8||"
|
||||
"\xea\xae\xb9|\xe1\x8f\xa9|\xe1\x8f\xa9||"
|
||||
"\xea\xae\xba|\xe1\x8f\xaa|\xe1\x8f\xaa||"
|
||||
"\xea\xae\xbb|\xe1\x8f\xab|\xe1\x8f\xab||"
|
||||
"\xea\xae\xbc|\xe1\x8f\xac|\xe1\x8f\xac||"
|
||||
"\xea\xae\xbd|\xe1\x8f\xad|\xe1\x8f\xad||"
|
||||
"\xea\xae\xbe|\xe1\x8f\xae|\xe1\x8f\xae||"
|
||||
"\xea\xae\xbf|\xe1\x8f\xaf|\xe1\x8f\xaf||"
|
||||
"\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{} {
|
||||
}
|
||||
};
|
||||
// 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_="") noexcept : character(character_) {
|
||||
StringCopy(conversion.conversion, conversion_);
|
||||
}
|
||||
bool operator<(const CharacterConversion &other) const noexcept {
|
||||
return character < other.character;
|
||||
}
|
||||
};
|
||||
typedef std::vector<CharacterConversion> CharacterToConversion;
|
||||
CharacterToConversion characterToConversion;
|
||||
// The parallel arrays
|
||||
std::vector<int> characters;
|
||||
std::vector<ConversionString> conversions;
|
||||
|
||||
public:
|
||||
CaseConverter() {
|
||||
}
|
||||
virtual ~CaseConverter() = default;
|
||||
bool Initialised() const {
|
||||
return characters.size() > 0;
|
||||
}
|
||||
void Add(int character, const char *conversion) {
|
||||
characterToConversion.emplace_back(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 nullptr;
|
||||
else if (*it == character)
|
||||
return conversions[it - characters.begin()].conversion;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
size_t CaseConvertString(char *converted, size_t sizeConverted, const char *mixed, size_t lenMixed) override {
|
||||
size_t lenConverted = 0;
|
||||
size_t mixedPos = 0;
|
||||
unsigned char bytes[UTF8MaxBytes + 1]{};
|
||||
while (mixedPos < lenMixed) {
|
||||
const unsigned char leadByte = mixed[mixedPos];
|
||||
const char *caseConverted = nullptr;
|
||||
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;
|
||||
}
|
||||
const int classified = UTF8Classify(bytes, widthCharBytes);
|
||||
if (!(classified & UTF8MaskInvalid)) {
|
||||
// valid UTF-8
|
||||
lenMixedChar = classified & UTF8MaskWidth;
|
||||
const 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 (const CharacterConversion &chConv : characterToConversion) {
|
||||
characters.push_back(chConv.character);
|
||||
conversions.push_back(chConv.conversion);
|
||||
}
|
||||
// Empty the original calculated data completely
|
||||
CharacterToConversion().swap(characterToConversion);
|
||||
}
|
||||
};
|
||||
|
||||
CaseConverter caseConvFold;
|
||||
CaseConverter caseConvUp;
|
||||
CaseConverter caseConvLow;
|
||||
|
||||
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);) {
|
||||
const int lower = symmetricCaseConversionRanges[i++];
|
||||
const int upper = symmetricCaseConversionRanges[i++];
|
||||
const int length = symmetricCaseConversionRanges[i++];
|
||||
const 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);) {
|
||||
const int lower = symmetricCaseConversions[i++];
|
||||
const 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;
|
||||
unsigned 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;
|
||||
|
||||
const int character = UnicodeFromUTF8(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 nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
std::string CaseConvertString(const std::string &s, enum CaseConversion conversion) {
|
||||
std::string retMapped(s.length() * maxExpansionCaseConversion, 0);
|
||||
const size_t lenMapped = CaseConvertString(&retMapped[0], retMapped.length(), s.c_str(), s.length(),
|
||||
conversion);
|
||||
retMapped.resize(lenMapped);
|
||||
return retMapped;
|
||||
}
|
||||
|
||||
}
|
||||
46
third_party/qscintilla/scintilla/src/CaseConvert.h
vendored
Normal file
46
third_party/qscintilla/scintilla/src/CaseConvert.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
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);
|
||||
|
||||
// Converts a mixed case string using a particular conversion.
|
||||
std::string CaseConvertString(const std::string &s, enum CaseConversion conversion);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
66
third_party/qscintilla/scintilla/src/CaseFolder.cpp
vendored
Normal file
66
third_party/qscintilla/scintilla/src/CaseFolder.cpp
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
// 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 <stdexcept>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
#include "CaseFolder.h"
|
||||
#include "CaseConvert.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
CaseFolder::~CaseFolder() {
|
||||
}
|
||||
|
||||
CaseFolderTable::CaseFolderTable() : mapping{} {
|
||||
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);
|
||||
}
|
||||
}
|
||||
41
third_party/qscintilla/scintilla/src/CaseFolder.h
vendored
Normal file
41
third_party/qscintilla/scintilla/src/CaseFolder.h
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
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();
|
||||
~CaseFolderTable() override;
|
||||
size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) override;
|
||||
void SetTranslation(char ch, char chTranslation);
|
||||
void StandardASCII();
|
||||
};
|
||||
|
||||
class ICaseConverter;
|
||||
|
||||
class CaseFolderUnicode : public CaseFolderTable {
|
||||
ICaseConverter *converter;
|
||||
public:
|
||||
CaseFolderUnicode();
|
||||
size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
204
third_party/qscintilla/scintilla/src/Catalogue.cpp
vendored
Normal file
204
third_party/qscintilla/scintilla/src/Catalogue.cpp
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file Catalogue.cxx
|
||||
** Lexer infrastructure.
|
||||
** Contains a list of LexerModules which can be searched to find a module appropriate for a
|
||||
** particular language.
|
||||
**/
|
||||
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
#include "ILexer.h"
|
||||
#include "Scintilla.h"
|
||||
#include "SciLexer.h"
|
||||
|
||||
#include "LexerModule.h"
|
||||
#include "Catalogue.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
static std::vector<LexerModule *> lexerCatalogue;
|
||||
static int nextLanguage = SCLEX_AUTOMATIC+1;
|
||||
|
||||
const LexerModule *Catalogue::Find(int language) {
|
||||
Scintilla_LinkLexers();
|
||||
for (const LexerModule *lm : lexerCatalogue) {
|
||||
if (lm->GetLanguage() == language) {
|
||||
return lm;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const LexerModule *Catalogue::Find(const char *languageName) {
|
||||
Scintilla_LinkLexers();
|
||||
if (languageName) {
|
||||
for (const LexerModule *lm : lexerCatalogue) {
|
||||
if (lm->languageName && (0 == strcmp(lm->languageName, languageName))) {
|
||||
return lm;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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(lmA68k);
|
||||
LINK_LEXER(lmAbaqus);
|
||||
LINK_LEXER(lmAda);
|
||||
LINK_LEXER(lmAPDL);
|
||||
LINK_LEXER(lmAs);
|
||||
LINK_LEXER(lmAsm);
|
||||
LINK_LEXER(lmAsn1);
|
||||
LINK_LEXER(lmASY);
|
||||
LINK_LEXER(lmAU3);
|
||||
LINK_LEXER(lmAVE);
|
||||
LINK_LEXER(lmAVS);
|
||||
LINK_LEXER(lmBaan);
|
||||
LINK_LEXER(lmBash);
|
||||
LINK_LEXER(lmBatch);
|
||||
LINK_LEXER(lmBibTeX);
|
||||
LINK_LEXER(lmBlitzBasic);
|
||||
LINK_LEXER(lmBullant);
|
||||
LINK_LEXER(lmCaml);
|
||||
LINK_LEXER(lmClw);
|
||||
LINK_LEXER(lmClwNoCase);
|
||||
LINK_LEXER(lmCmake);
|
||||
LINK_LEXER(lmCOBOL);
|
||||
LINK_LEXER(lmCoffeeScript);
|
||||
LINK_LEXER(lmConf);
|
||||
LINK_LEXER(lmCPP);
|
||||
LINK_LEXER(lmCPPNoCase);
|
||||
LINK_LEXER(lmCsound);
|
||||
LINK_LEXER(lmCss);
|
||||
LINK_LEXER(lmD);
|
||||
LINK_LEXER(lmDiff);
|
||||
LINK_LEXER(lmDMAP);
|
||||
LINK_LEXER(lmDMIS);
|
||||
LINK_LEXER(lmECL);
|
||||
LINK_LEXER(lmEDIFACT);
|
||||
LINK_LEXER(lmEiffel);
|
||||
LINK_LEXER(lmEiffelkw);
|
||||
LINK_LEXER(lmErlang);
|
||||
LINK_LEXER(lmErrorList);
|
||||
LINK_LEXER(lmESCRIPT);
|
||||
LINK_LEXER(lmF77);
|
||||
LINK_LEXER(lmFlagShip);
|
||||
LINK_LEXER(lmForth);
|
||||
LINK_LEXER(lmFortran);
|
||||
LINK_LEXER(lmFreeBasic);
|
||||
LINK_LEXER(lmGAP);
|
||||
LINK_LEXER(lmGui4Cli);
|
||||
LINK_LEXER(lmHaskell);
|
||||
LINK_LEXER(lmHTML);
|
||||
LINK_LEXER(lmIHex);
|
||||
LINK_LEXER(lmIndent);
|
||||
LINK_LEXER(lmInno);
|
||||
LINK_LEXER(lmJSON);
|
||||
LINK_LEXER(lmKix);
|
||||
LINK_LEXER(lmKVIrc);
|
||||
LINK_LEXER(lmLatex);
|
||||
LINK_LEXER(lmLISP);
|
||||
LINK_LEXER(lmLiterateHaskell);
|
||||
LINK_LEXER(lmLot);
|
||||
LINK_LEXER(lmLout);
|
||||
#if !defined(SCINTILLA_QT)
|
||||
LINK_LEXER(lmLPeg);
|
||||
#endif
|
||||
LINK_LEXER(lmLua);
|
||||
LINK_LEXER(lmMagikSF);
|
||||
LINK_LEXER(lmMake);
|
||||
LINK_LEXER(lmMarkdown);
|
||||
LINK_LEXER(lmMatlab);
|
||||
LINK_LEXER(lmMaxima);
|
||||
LINK_LEXER(lmMETAPOST);
|
||||
LINK_LEXER(lmMMIXAL);
|
||||
LINK_LEXER(lmModula);
|
||||
LINK_LEXER(lmMSSQL);
|
||||
LINK_LEXER(lmMySQL);
|
||||
LINK_LEXER(lmNimrod);
|
||||
LINK_LEXER(lmNncrontab);
|
||||
LINK_LEXER(lmNsis);
|
||||
LINK_LEXER(lmNull);
|
||||
LINK_LEXER(lmOctave);
|
||||
LINK_LEXER(lmOpal);
|
||||
LINK_LEXER(lmOScript);
|
||||
LINK_LEXER(lmPascal);
|
||||
LINK_LEXER(lmPB);
|
||||
LINK_LEXER(lmPerl);
|
||||
LINK_LEXER(lmPHPSCRIPT);
|
||||
LINK_LEXER(lmPLM);
|
||||
LINK_LEXER(lmPO);
|
||||
LINK_LEXER(lmPOV);
|
||||
LINK_LEXER(lmPowerPro);
|
||||
LINK_LEXER(lmPowerShell);
|
||||
LINK_LEXER(lmProgress);
|
||||
LINK_LEXER(lmProps);
|
||||
LINK_LEXER(lmPS);
|
||||
LINK_LEXER(lmPureBasic);
|
||||
LINK_LEXER(lmPython);
|
||||
LINK_LEXER(lmR);
|
||||
LINK_LEXER(lmREBOL);
|
||||
LINK_LEXER(lmRegistry);
|
||||
LINK_LEXER(lmRuby);
|
||||
LINK_LEXER(lmRust);
|
||||
LINK_LEXER(lmSAS);
|
||||
LINK_LEXER(lmScriptol);
|
||||
LINK_LEXER(lmSmalltalk);
|
||||
LINK_LEXER(lmSML);
|
||||
LINK_LEXER(lmSorc);
|
||||
LINK_LEXER(lmSpecman);
|
||||
LINK_LEXER(lmSpice);
|
||||
LINK_LEXER(lmSQL);
|
||||
LINK_LEXER(lmSrec);
|
||||
LINK_LEXER(lmStata);
|
||||
LINK_LEXER(lmSTTXT);
|
||||
LINK_LEXER(lmTACL);
|
||||
LINK_LEXER(lmTADS3);
|
||||
LINK_LEXER(lmTAL);
|
||||
LINK_LEXER(lmTCL);
|
||||
LINK_LEXER(lmTCMD);
|
||||
LINK_LEXER(lmTEHex);
|
||||
LINK_LEXER(lmTeX);
|
||||
LINK_LEXER(lmTxt2tags);
|
||||
LINK_LEXER(lmVB);
|
||||
LINK_LEXER(lmVBScript);
|
||||
LINK_LEXER(lmVerilog);
|
||||
LINK_LEXER(lmVHDL);
|
||||
LINK_LEXER(lmVisualProlog);
|
||||
LINK_LEXER(lmXML);
|
||||
LINK_LEXER(lmYAML);
|
||||
|
||||
//--Autogenerated -- end of automatically generated section
|
||||
|
||||
return 1;
|
||||
}
|
||||
24
third_party/qscintilla/scintilla/src/Catalogue.h
vendored
Normal file
24
third_party/qscintilla/scintilla/src/Catalogue.h
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file Catalogue.h
|
||||
** Lexer infrastructure.
|
||||
** Contains a list of LexerModules which can be searched to find a module appropriate for a
|
||||
** particular language.
|
||||
**/
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
class Catalogue {
|
||||
public:
|
||||
static const LexerModule *Find(int language);
|
||||
static const LexerModule *Find(const char *languageName);
|
||||
static void AddLexerModule(LexerModule *plm);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
1204
third_party/qscintilla/scintilla/src/CellBuffer.cpp
vendored
Normal file
1204
third_party/qscintilla/scintilla/src/CellBuffer.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
215
third_party/qscintilla/scintilla/src/CellBuffer.h
vendored
Normal file
215
third_party/qscintilla/scintilla/src/CellBuffer.h
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
// 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(Sci::Line line)=0;
|
||||
virtual void RemoveLine(Sci::Line line)=0;
|
||||
};
|
||||
|
||||
/**
|
||||
* The line vector contains information about each of the lines in a cell buffer.
|
||||
*/
|
||||
class ILineVector;
|
||||
|
||||
enum actionType { insertAction, removeAction, startAction, containerAction };
|
||||
|
||||
/**
|
||||
* Actions are used to store all the information required to perform one undo/redo step.
|
||||
*/
|
||||
class Action {
|
||||
public:
|
||||
actionType at;
|
||||
Sci::Position position;
|
||||
std::unique_ptr<char[]> data;
|
||||
Sci::Position lenData;
|
||||
bool mayCoalesce;
|
||||
|
||||
Action();
|
||||
// Deleted so Action objects can not be copied.
|
||||
Action(const Action &other) = delete;
|
||||
Action &operator=(const Action &other) = delete;
|
||||
Action &operator=(const Action &&other) = delete;
|
||||
// Move constructor allows vector to be resized without reallocating.
|
||||
Action(Action &&other) noexcept = default;
|
||||
~Action();
|
||||
void Create(actionType at_, Sci::Position position_=0, const char *data_=nullptr, Sci::Position lenData_=0, bool mayCoalesce_=true);
|
||||
void Clear();
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class UndoHistory {
|
||||
std::vector<Action> actions;
|
||||
int maxAction;
|
||||
int currentAction;
|
||||
int undoSequenceDepth;
|
||||
int savePoint;
|
||||
int tentativePoint;
|
||||
|
||||
void EnsureUndoRoom();
|
||||
|
||||
public:
|
||||
UndoHistory();
|
||||
// Deleted so UndoHistory objects can not be copied.
|
||||
UndoHistory(const UndoHistory &) = delete;
|
||||
UndoHistory(UndoHistory &&) = delete;
|
||||
void operator=(const UndoHistory &) = delete;
|
||||
void operator=(UndoHistory &&) = delete;
|
||||
~UndoHistory();
|
||||
|
||||
const char *AppendAction(actionType at, Sci::Position position, const char *data, Sci::Position lengthData, 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;
|
||||
|
||||
// Tentative actions are used for input composition so that it can be undone cleanly
|
||||
void TentativeStart();
|
||||
void TentativeCommit();
|
||||
bool TentativeActive() const noexcept { return tentativePoint >= 0; }
|
||||
int TentativeSteps();
|
||||
|
||||
/// 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:
|
||||
bool hasStyles;
|
||||
bool largeDocument;
|
||||
SplitVector<char> substance;
|
||||
SplitVector<char> style;
|
||||
bool readOnly;
|
||||
bool utf8Substance;
|
||||
int utf8LineEnds;
|
||||
|
||||
bool collectingUndo;
|
||||
UndoHistory uh;
|
||||
|
||||
std::unique_ptr<ILineVector> plv;
|
||||
|
||||
bool UTF8LineEndOverlaps(Sci::Position position) const;
|
||||
bool UTF8IsCharacterBoundary(Sci::Position position) const;
|
||||
void ResetLineEnds();
|
||||
void RecalculateIndexLineStarts(Sci::Line lineFirst, Sci::Line lineLast);
|
||||
bool MaintainingLineCharacterIndex() const noexcept;
|
||||
/// Actions without undo
|
||||
void BasicInsertString(Sci::Position position, const char *s, Sci::Position insertLength);
|
||||
void BasicDeleteChars(Sci::Position position, Sci::Position deleteLength);
|
||||
|
||||
public:
|
||||
|
||||
CellBuffer(bool hasStyles_, bool largeDocument_);
|
||||
// Deleted so CellBuffer objects can not be copied.
|
||||
CellBuffer(const CellBuffer &) = delete;
|
||||
CellBuffer(CellBuffer &&) = delete;
|
||||
void operator=(const CellBuffer &) = delete;
|
||||
void operator=(CellBuffer &&) = delete;
|
||||
~CellBuffer();
|
||||
|
||||
/// Retrieving positions outside the range of the buffer works and returns 0
|
||||
char CharAt(Sci::Position position) const noexcept;
|
||||
unsigned char UCharAt(Sci::Position position) const noexcept;
|
||||
void GetCharRange(char *buffer, Sci::Position position, Sci::Position lengthRetrieve) const;
|
||||
char StyleAt(Sci::Position position) const noexcept;
|
||||
void GetStyleRange(unsigned char *buffer, Sci::Position position, Sci::Position lengthRetrieve) const;
|
||||
const char *BufferPointer();
|
||||
const char *RangePointer(Sci::Position position, Sci::Position rangeLength);
|
||||
Sci::Position GapPosition() const;
|
||||
|
||||
Sci::Position Length() const noexcept;
|
||||
void Allocate(Sci::Position newSize);
|
||||
void SetUTF8Substance(bool utf8Substance_);
|
||||
int GetLineEndTypes() const { return utf8LineEnds; }
|
||||
void SetLineEndTypes(int utf8LineEnds_);
|
||||
bool ContainsLineEnd(const char *s, Sci::Position length) const;
|
||||
void SetPerLine(PerLine *pl);
|
||||
int LineCharacterIndex() const noexcept;
|
||||
void AllocateLineCharacterIndex(int lineCharacterIndex);
|
||||
void ReleaseLineCharacterIndex(int lineCharacterIndex);
|
||||
Sci::Line Lines() const noexcept;
|
||||
Sci::Position LineStart(Sci::Line line) const noexcept;
|
||||
Sci::Position IndexLineStart(Sci::Line line, int lineCharacterIndex) const noexcept;
|
||||
Sci::Line LineFromPosition(Sci::Position pos) const noexcept;
|
||||
Sci::Line LineFromPositionIndex(Sci::Position pos, int lineCharacterIndex) const noexcept;
|
||||
void InsertLine(Sci::Line line, Sci::Position position, bool lineStart);
|
||||
void RemoveLine(Sci::Line line);
|
||||
const char *InsertString(Sci::Position position, const char *s, Sci::Position 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(Sci::Position position, char styleValue);
|
||||
bool SetStyleFor(Sci::Position position, Sci::Position lengthStyle, char styleValue);
|
||||
|
||||
const char *DeleteChars(Sci::Position position, Sci::Position deleteLength, bool &startSequence);
|
||||
|
||||
bool IsReadOnly() const;
|
||||
void SetReadOnly(bool set);
|
||||
bool IsLarge() const;
|
||||
bool HasStyles() const;
|
||||
|
||||
/// 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;
|
||||
|
||||
void TentativeStart();
|
||||
void TentativeCommit();
|
||||
bool TentativeActive() const;
|
||||
int TentativeSteps();
|
||||
|
||||
bool SetUndoCollection(bool collectUndo);
|
||||
bool IsCollectingUndo() const;
|
||||
void BeginUndoAction();
|
||||
void EndUndoAction();
|
||||
void AddUndoAction(Sci::Position 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();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
59
third_party/qscintilla/scintilla/src/CharClassify.cpp
vendored
Normal file
59
third_party/qscintilla/scintilla/src/CharClassify.cpp
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
// 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 <cstdlib>
|
||||
#include <cctype>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "CharClassify.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
CharClassify::CharClassify() : charClass{} {
|
||||
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) const {
|
||||
// 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;
|
||||
}
|
||||
31
third_party/qscintilla/scintilla/src/CharClassify.h
vendored
Normal file
31
third_party/qscintilla/scintilla/src/CharClassify.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
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 characterClass, unsigned char *buffer) const;
|
||||
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
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
418
third_party/qscintilla/scintilla/src/ContractionState.cpp
vendored
Normal file
418
third_party/qscintilla/scintilla/src/ContractionState.cpp
vendored
Normal file
@@ -0,0 +1,418 @@
|
||||
// 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 <cstddef>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Position.h"
|
||||
#include "UniqueString.h"
|
||||
#include "SplitVector.h"
|
||||
#include "Partitioning.h"
|
||||
#include "RunStyles.h"
|
||||
#include "SparseVector.h"
|
||||
#include "ContractionState.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename LINE>
|
||||
class ContractionState final : public IContractionState {
|
||||
// These contain 1 element for every document line.
|
||||
std::unique_ptr<RunStyles<LINE, char>> visible;
|
||||
std::unique_ptr<RunStyles<LINE, char>> expanded;
|
||||
std::unique_ptr<RunStyles<LINE, int>> heights;
|
||||
std::unique_ptr<SparseVector<UniqueString>> foldDisplayTexts;
|
||||
std::unique_ptr<Partitioning<LINE>> displayLines;
|
||||
LINE linesInDocument;
|
||||
|
||||
void EnsureData();
|
||||
|
||||
bool OneToOne() const noexcept {
|
||||
// True when each document line is exactly one display line so need for
|
||||
// complex data structures.
|
||||
return visible == nullptr;
|
||||
}
|
||||
|
||||
void InsertLine(Sci::Line lineDoc);
|
||||
void DeleteLine(Sci::Line lineDoc);
|
||||
|
||||
public:
|
||||
ContractionState() noexcept;
|
||||
// Deleted so ContractionState objects can not be copied.
|
||||
ContractionState(const ContractionState &) = delete;
|
||||
void operator=(const ContractionState &) = delete;
|
||||
ContractionState(ContractionState &&) = delete;
|
||||
void operator=(ContractionState &&) = delete;
|
||||
~ContractionState() override;
|
||||
|
||||
void Clear() noexcept override;
|
||||
|
||||
Sci::Line LinesInDoc() const override;
|
||||
Sci::Line LinesDisplayed() const override;
|
||||
Sci::Line DisplayFromDoc(Sci::Line lineDoc) const override;
|
||||
Sci::Line DisplayLastFromDoc(Sci::Line lineDoc) const override;
|
||||
Sci::Line DocFromDisplay(Sci::Line lineDisplay) const override;
|
||||
|
||||
void InsertLines(Sci::Line lineDoc, Sci::Line lineCount) override;
|
||||
void DeleteLines(Sci::Line lineDoc, Sci::Line lineCount) override;
|
||||
|
||||
bool GetVisible(Sci::Line lineDoc) const override;
|
||||
bool SetVisible(Sci::Line lineDocStart, Sci::Line lineDocEnd, bool isVisible) override;
|
||||
bool HiddenLines() const override;
|
||||
|
||||
const char *GetFoldDisplayText(Sci::Line lineDoc) const override;
|
||||
bool GetFoldDisplayTextShown(Sci::Line lineDoc) const override;
|
||||
bool SetFoldDisplayText(Sci::Line lineDoc, const char *text) override;
|
||||
|
||||
bool GetExpanded(Sci::Line lineDoc) const override;
|
||||
bool SetExpanded(Sci::Line lineDoc, bool isExpanded) override;
|
||||
Sci::Line ContractedNext(Sci::Line lineDocStart) const override;
|
||||
|
||||
int GetHeight(Sci::Line lineDoc) const override;
|
||||
bool SetHeight(Sci::Line lineDoc, int height) override;
|
||||
|
||||
void ShowAll() override;
|
||||
|
||||
void Check() const;
|
||||
};
|
||||
|
||||
template <typename LINE>
|
||||
ContractionState<LINE>::ContractionState() noexcept : linesInDocument(1) {
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
ContractionState<LINE>::~ContractionState() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
void ContractionState<LINE>::EnsureData() {
|
||||
if (OneToOne()) {
|
||||
visible = std::unique_ptr<RunStyles<LINE, char>>(new RunStyles<LINE, char>());
|
||||
expanded = std::unique_ptr<RunStyles<LINE, char>>(new RunStyles<LINE, char>());
|
||||
heights = std::unique_ptr<RunStyles<LINE, int>>(new RunStyles<LINE, int>());
|
||||
foldDisplayTexts = std::unique_ptr<SparseVector<UniqueString>>(new SparseVector<UniqueString>());
|
||||
displayLines = std::unique_ptr<Partitioning<LINE>>(new Partitioning<LINE>(4));
|
||||
InsertLines(0, linesInDocument);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
void ContractionState<LINE>::InsertLine(Sci::Line lineDoc) {
|
||||
if (OneToOne()) {
|
||||
linesInDocument++;
|
||||
} else {
|
||||
const LINE lineDocCast = static_cast<LINE>(lineDoc);
|
||||
visible->InsertSpace(lineDocCast, 1);
|
||||
visible->SetValueAt(lineDocCast, 1);
|
||||
expanded->InsertSpace(lineDocCast, 1);
|
||||
expanded->SetValueAt(lineDocCast, 1);
|
||||
heights->InsertSpace(lineDocCast, 1);
|
||||
heights->SetValueAt(lineDocCast, 1);
|
||||
foldDisplayTexts->InsertSpace(lineDocCast, 1);
|
||||
foldDisplayTexts->SetValueAt(lineDocCast, nullptr);
|
||||
const Sci::Line lineDisplay = DisplayFromDoc(lineDoc);
|
||||
displayLines->InsertPartition(lineDocCast, static_cast<LINE>(lineDisplay));
|
||||
displayLines->InsertText(lineDocCast, 1);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
void ContractionState<LINE>::DeleteLine(Sci::Line lineDoc) {
|
||||
if (OneToOne()) {
|
||||
linesInDocument--;
|
||||
} else {
|
||||
const LINE lineDocCast = static_cast<LINE>(lineDoc);
|
||||
if (GetVisible(lineDoc)) {
|
||||
displayLines->InsertText(lineDocCast, -heights->ValueAt(lineDocCast));
|
||||
}
|
||||
displayLines->RemovePartition(lineDocCast);
|
||||
visible->DeleteRange(lineDocCast, 1);
|
||||
expanded->DeleteRange(lineDocCast, 1);
|
||||
heights->DeleteRange(lineDocCast, 1);
|
||||
foldDisplayTexts->DeletePosition(lineDocCast);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
void ContractionState<LINE>::Clear() noexcept {
|
||||
visible.reset();
|
||||
expanded.reset();
|
||||
heights.reset();
|
||||
foldDisplayTexts.reset();
|
||||
displayLines.reset();
|
||||
linesInDocument = 1;
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
Sci::Line ContractionState<LINE>::LinesInDoc() const {
|
||||
if (OneToOne()) {
|
||||
return linesInDocument;
|
||||
} else {
|
||||
return displayLines->Partitions() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
Sci::Line ContractionState<LINE>::LinesDisplayed() const {
|
||||
if (OneToOne()) {
|
||||
return linesInDocument;
|
||||
} else {
|
||||
return displayLines->PositionFromPartition(static_cast<LINE>(LinesInDoc()));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
Sci::Line ContractionState<LINE>::DisplayFromDoc(Sci::Line lineDoc) const {
|
||||
if (OneToOne()) {
|
||||
return (lineDoc <= linesInDocument) ? lineDoc : linesInDocument;
|
||||
} else {
|
||||
if (lineDoc > displayLines->Partitions())
|
||||
lineDoc = displayLines->Partitions();
|
||||
return displayLines->PositionFromPartition(static_cast<LINE>(lineDoc));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
Sci::Line ContractionState<LINE>::DisplayLastFromDoc(Sci::Line lineDoc) const {
|
||||
return DisplayFromDoc(lineDoc) + GetHeight(lineDoc) - 1;
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
Sci::Line ContractionState<LINE>::DocFromDisplay(Sci::Line lineDisplay) const {
|
||||
if (OneToOne()) {
|
||||
return lineDisplay;
|
||||
} else {
|
||||
if (lineDisplay <= 0) {
|
||||
return 0;
|
||||
}
|
||||
if (lineDisplay > LinesDisplayed()) {
|
||||
return displayLines->PartitionFromPosition(static_cast<LINE>(LinesDisplayed()));
|
||||
}
|
||||
const Sci::Line lineDoc = displayLines->PartitionFromPosition(static_cast<LINE>(lineDisplay));
|
||||
PLATFORM_ASSERT(GetVisible(lineDoc));
|
||||
return lineDoc;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
void ContractionState<LINE>::InsertLines(Sci::Line lineDoc, Sci::Line lineCount) {
|
||||
for (int l = 0; l < lineCount; l++) {
|
||||
InsertLine(lineDoc + l);
|
||||
}
|
||||
Check();
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
void ContractionState<LINE>::DeleteLines(Sci::Line lineDoc, Sci::Line lineCount) {
|
||||
for (Sci::Line l = 0; l < lineCount; l++) {
|
||||
DeleteLine(lineDoc);
|
||||
}
|
||||
Check();
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
bool ContractionState<LINE>::GetVisible(Sci::Line lineDoc) const {
|
||||
if (OneToOne()) {
|
||||
return true;
|
||||
} else {
|
||||
if (lineDoc >= visible->Length())
|
||||
return true;
|
||||
return visible->ValueAt(static_cast<LINE>(lineDoc)) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
bool ContractionState<LINE>::SetVisible(Sci::Line lineDocStart, Sci::Line lineDocEnd, bool isVisible) {
|
||||
if (OneToOne() && isVisible) {
|
||||
return false;
|
||||
} else {
|
||||
EnsureData();
|
||||
Sci::Line delta = 0;
|
||||
Check();
|
||||
if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < LinesInDoc())) {
|
||||
for (Sci::Line line = lineDocStart; line <= lineDocEnd; line++) {
|
||||
if (GetVisible(line) != isVisible) {
|
||||
const int heightLine = heights->ValueAt(static_cast<LINE>(line));
|
||||
const int difference = isVisible ? heightLine : -heightLine;
|
||||
visible->SetValueAt(static_cast<LINE>(line), isVisible ? 1 : 0);
|
||||
displayLines->InsertText(static_cast<LINE>(line), difference);
|
||||
delta += difference;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
Check();
|
||||
return delta != 0;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
bool ContractionState<LINE>::HiddenLines() const {
|
||||
if (OneToOne()) {
|
||||
return false;
|
||||
} else {
|
||||
return !visible->AllSameAs(1);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
const char *ContractionState<LINE>::GetFoldDisplayText(Sci::Line lineDoc) const {
|
||||
Check();
|
||||
return foldDisplayTexts->ValueAt(lineDoc).get();
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
bool ContractionState<LINE>::GetFoldDisplayTextShown(Sci::Line lineDoc) const {
|
||||
return !GetExpanded(lineDoc) && GetFoldDisplayText(lineDoc);
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
bool ContractionState<LINE>::SetFoldDisplayText(Sci::Line lineDoc, const char *text) {
|
||||
EnsureData();
|
||||
const char *foldText = foldDisplayTexts->ValueAt(lineDoc).get();
|
||||
if (!foldText || !text || 0 != strcmp(text, foldText)) {
|
||||
UniqueString uns = UniqueStringCopy(text);
|
||||
foldDisplayTexts->SetValueAt(lineDoc, std::move(uns));
|
||||
Check();
|
||||
return true;
|
||||
} else {
|
||||
Check();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
bool ContractionState<LINE>::GetExpanded(Sci::Line lineDoc) const {
|
||||
if (OneToOne()) {
|
||||
return true;
|
||||
} else {
|
||||
Check();
|
||||
return expanded->ValueAt(static_cast<LINE>(lineDoc)) == 1;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
bool ContractionState<LINE>::SetExpanded(Sci::Line lineDoc, bool isExpanded) {
|
||||
if (OneToOne() && isExpanded) {
|
||||
return false;
|
||||
} else {
|
||||
EnsureData();
|
||||
if (isExpanded != (expanded->ValueAt(static_cast<LINE>(lineDoc)) == 1)) {
|
||||
expanded->SetValueAt(static_cast<LINE>(lineDoc), isExpanded ? 1 : 0);
|
||||
Check();
|
||||
return true;
|
||||
} else {
|
||||
Check();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
Sci::Line ContractionState<LINE>::ContractedNext(Sci::Line lineDocStart) const {
|
||||
if (OneToOne()) {
|
||||
return -1;
|
||||
} else {
|
||||
Check();
|
||||
if (!expanded->ValueAt(static_cast<LINE>(lineDocStart))) {
|
||||
return lineDocStart;
|
||||
} else {
|
||||
const Sci::Line lineDocNextChange = expanded->EndRun(static_cast<LINE>(lineDocStart));
|
||||
if (lineDocNextChange < LinesInDoc())
|
||||
return lineDocNextChange;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
int ContractionState<LINE>::GetHeight(Sci::Line lineDoc) const {
|
||||
if (OneToOne()) {
|
||||
return 1;
|
||||
} else {
|
||||
return heights->ValueAt(static_cast<LINE>(lineDoc));
|
||||
}
|
||||
}
|
||||
|
||||
// Set the number of display lines needed for this line.
|
||||
// Return true if this is a change.
|
||||
template <typename LINE>
|
||||
bool ContractionState<LINE>::SetHeight(Sci::Line lineDoc, int height) {
|
||||
if (OneToOne() && (height == 1)) {
|
||||
return false;
|
||||
} else if (lineDoc < LinesInDoc()) {
|
||||
EnsureData();
|
||||
if (GetHeight(lineDoc) != height) {
|
||||
if (GetVisible(lineDoc)) {
|
||||
displayLines->InsertText(static_cast<LINE>(lineDoc), height - GetHeight(lineDoc));
|
||||
}
|
||||
heights->SetValueAt(static_cast<LINE>(lineDoc), height);
|
||||
Check();
|
||||
return true;
|
||||
} else {
|
||||
Check();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename LINE>
|
||||
void ContractionState<LINE>::ShowAll() {
|
||||
const LINE lines = static_cast<LINE>(LinesInDoc());
|
||||
Clear();
|
||||
linesInDocument = lines;
|
||||
}
|
||||
|
||||
// Debugging checks
|
||||
|
||||
template <typename LINE>
|
||||
void ContractionState<LINE>::Check() const {
|
||||
#ifdef CHECK_CORRECTNESS
|
||||
for (Sci::Line vline = 0; vline < LinesDisplayed(); vline++) {
|
||||
const Sci::Line lineDoc = DocFromDisplay(vline);
|
||||
PLATFORM_ASSERT(GetVisible(lineDoc));
|
||||
}
|
||||
for (Sci::Line lineDoc = 0; lineDoc < LinesInDoc(); lineDoc++) {
|
||||
const Sci::Line displayThis = DisplayFromDoc(lineDoc);
|
||||
const Sci::Line displayNext = DisplayFromDoc(lineDoc + 1);
|
||||
const Sci::Line height = displayNext - displayThis;
|
||||
PLATFORM_ASSERT(height >= 0);
|
||||
if (GetVisible(lineDoc)) {
|
||||
PLATFORM_ASSERT(GetHeight(lineDoc) == height);
|
||||
} else {
|
||||
PLATFORM_ASSERT(0 == height);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
std::unique_ptr<IContractionState> ContractionStateCreate(bool largeDocument) {
|
||||
if (largeDocument)
|
||||
return std::unique_ptr<ContractionState<Sci::Line>>(new ContractionState<Sci::Line>());
|
||||
else
|
||||
return std::unique_ptr<ContractionState<int>>(new ContractionState<int>());
|
||||
}
|
||||
|
||||
}
|
||||
52
third_party/qscintilla/scintilla/src/ContractionState.h
vendored
Normal file
52
third_party/qscintilla/scintilla/src/ContractionState.h
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
/**
|
||||
*/
|
||||
class IContractionState {
|
||||
public:
|
||||
virtual ~IContractionState() {};
|
||||
|
||||
virtual void Clear()=0;
|
||||
|
||||
virtual Sci::Line LinesInDoc() const=0;
|
||||
virtual Sci::Line LinesDisplayed() const=0;
|
||||
virtual Sci::Line DisplayFromDoc(Sci::Line lineDoc) const=0;
|
||||
virtual Sci::Line DisplayLastFromDoc(Sci::Line lineDoc) const=0;
|
||||
virtual Sci::Line DocFromDisplay(Sci::Line lineDisplay) const=0;
|
||||
|
||||
virtual void InsertLines(Sci::Line lineDoc, Sci::Line lineCount)=0;
|
||||
virtual void DeleteLines(Sci::Line lineDoc, Sci::Line lineCount)=0;
|
||||
|
||||
virtual bool GetVisible(Sci::Line lineDoc) const=0;
|
||||
virtual bool SetVisible(Sci::Line lineDocStart, Sci::Line lineDocEnd, bool isVisible)=0;
|
||||
virtual bool HiddenLines() const=0;
|
||||
|
||||
virtual const char *GetFoldDisplayText(Sci::Line lineDoc) const=0;
|
||||
virtual bool GetFoldDisplayTextShown(Sci::Line lineDoc) const=0;
|
||||
virtual bool SetFoldDisplayText(Sci::Line lineDoc, const char *text)=0;
|
||||
|
||||
virtual bool GetExpanded(Sci::Line lineDoc) const=0;
|
||||
virtual bool SetExpanded(Sci::Line lineDoc, bool isExpanded)=0;
|
||||
virtual Sci::Line ContractedNext(Sci::Line lineDocStart) const=0;
|
||||
|
||||
virtual int GetHeight(Sci::Line lineDoc) const=0;
|
||||
virtual bool SetHeight(Sci::Line lineDoc, int height)=0;
|
||||
|
||||
virtual void ShowAll()=0;
|
||||
};
|
||||
|
||||
std::unique_ptr<IContractionState> ContractionStateCreate(bool largeDocument);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
42
third_party/qscintilla/scintilla/src/DBCS.cpp
vendored
Normal file
42
third_party/qscintilla/scintilla/src/DBCS.cpp
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file DBCS.cxx
|
||||
** Functions to handle DBCS double byte encodings like Shift-JIS.
|
||||
**/
|
||||
// Copyright 2017 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include "DBCS.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
bool DBCSIsLeadByte(int codePage, char ch) noexcept {
|
||||
// Byte ranges found in Wikipedia articles with relevant search strings in each case
|
||||
const unsigned char uch = ch;
|
||||
switch (codePage) {
|
||||
case 932:
|
||||
// Shift_jis
|
||||
return ((uch >= 0x81) && (uch <= 0x9F)) ||
|
||||
((uch >= 0xE0) && (uch <= 0xFC));
|
||||
// Lead bytes F0 to FC may be a Microsoft addition.
|
||||
case 936:
|
||||
// GBK
|
||||
return (uch >= 0x81) && (uch <= 0xFE);
|
||||
case 949:
|
||||
// Korean Wansung KS C-5601-1987
|
||||
return (uch >= 0x81) && (uch <= 0xFE);
|
||||
case 950:
|
||||
// Big5
|
||||
return (uch >= 0x81) && (uch <= 0xFE);
|
||||
case 1361:
|
||||
// Korean Johab KS C-5601-1992
|
||||
return
|
||||
((uch >= 0x84) && (uch <= 0xD3)) ||
|
||||
((uch >= 0xD8) && (uch <= 0xDE)) ||
|
||||
((uch >= 0xE0) && (uch <= 0xF9));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
17
third_party/qscintilla/scintilla/src/DBCS.h
vendored
Normal file
17
third_party/qscintilla/scintilla/src/DBCS.h
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file DBCS.h
|
||||
** Functions to handle DBCS double byte encodings like Shift-JIS.
|
||||
**/
|
||||
// Copyright 2017 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef DBCS_H
|
||||
#define DBCS_H
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
bool DBCSIsLeadByte(int codePage, char ch) noexcept;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
316
third_party/qscintilla/scintilla/src/Decoration.cpp
vendored
Normal file
316
third_party/qscintilla/scintilla/src/Decoration.cpp
vendored
Normal file
@@ -0,0 +1,316 @@
|
||||
/** @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 <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
#include "Position.h"
|
||||
#include "SplitVector.h"
|
||||
#include "Partitioning.h"
|
||||
#include "RunStyles.h"
|
||||
#include "Decoration.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename POS>
|
||||
class Decoration : public IDecoration {
|
||||
int indicator;
|
||||
public:
|
||||
RunStyles<POS, int> rs;
|
||||
|
||||
explicit Decoration(int indicator_) : indicator(indicator_) {
|
||||
}
|
||||
~Decoration() override {
|
||||
}
|
||||
|
||||
bool Empty() const override {
|
||||
return (rs.Runs() == 1) && (rs.AllSameAs(0));
|
||||
}
|
||||
int Indicator() const override {
|
||||
return indicator;
|
||||
}
|
||||
Sci::Position Length() const override {
|
||||
return rs.Length();
|
||||
}
|
||||
int ValueAt(Sci::Position position) const override {
|
||||
return rs.ValueAt(static_cast<POS>(position));
|
||||
}
|
||||
Sci::Position StartRun(Sci::Position position) const override {
|
||||
return rs.StartRun(static_cast<POS>(position));
|
||||
}
|
||||
Sci::Position EndRun(Sci::Position position) const override {
|
||||
return rs.EndRun(static_cast<POS>(position));
|
||||
}
|
||||
void SetValueAt(Sci::Position position, int value) override {
|
||||
rs.SetValueAt(static_cast<POS>(position), value);
|
||||
}
|
||||
void InsertSpace(Sci::Position position, Sci::Position insertLength) override {
|
||||
rs.InsertSpace(static_cast<POS>(position), static_cast<POS>(insertLength));
|
||||
}
|
||||
Sci::Position Runs() const override {
|
||||
return rs.Runs();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename POS>
|
||||
class DecorationList : public IDecorationList {
|
||||
int currentIndicator;
|
||||
int currentValue;
|
||||
Decoration<POS> *current; // Cached so FillRange doesn't have to search for each call.
|
||||
Sci::Position lengthDocument;
|
||||
// Ordered by indicator
|
||||
std::vector<std::unique_ptr<Decoration<POS>>> decorationList;
|
||||
std::vector<const IDecoration*> decorationView; // Read-only view of decorationList
|
||||
bool clickNotified;
|
||||
|
||||
Decoration<POS> *DecorationFromIndicator(int indicator);
|
||||
Decoration<POS> *Create(int indicator, Sci::Position length);
|
||||
void Delete(int indicator);
|
||||
void DeleteAnyEmpty();
|
||||
void SetView();
|
||||
public:
|
||||
|
||||
DecorationList();
|
||||
~DecorationList() override;
|
||||
|
||||
const std::vector<const IDecoration*> &View() const override {
|
||||
return decorationView;
|
||||
}
|
||||
|
||||
void SetCurrentIndicator(int indicator) override;
|
||||
int GetCurrentIndicator() const override { return currentIndicator; }
|
||||
|
||||
void SetCurrentValue(int value) override;
|
||||
int GetCurrentValue() const override { return currentValue; }
|
||||
|
||||
// Returns changed=true if some values may have changed
|
||||
FillResult<Sci::Position> FillRange(Sci::Position position, int value, Sci::Position fillLength) override;
|
||||
|
||||
void InsertSpace(Sci::Position position, Sci::Position insertLength) override;
|
||||
void DeleteRange(Sci::Position position, Sci::Position deleteLength) override;
|
||||
|
||||
void DeleteLexerDecorations() override;
|
||||
|
||||
int AllOnFor(Sci::Position position) const override;
|
||||
int ValueAt(int indicator, Sci::Position position) override;
|
||||
Sci::Position Start(int indicator, Sci::Position position) override;
|
||||
Sci::Position End(int indicator, Sci::Position position) override;
|
||||
|
||||
bool ClickNotified() const override {
|
||||
return clickNotified;
|
||||
}
|
||||
void SetClickNotified(bool notified) override {
|
||||
clickNotified = notified;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename POS>
|
||||
DecorationList<POS>::DecorationList() : currentIndicator(0), currentValue(1), current(nullptr),
|
||||
lengthDocument(0), clickNotified(false) {
|
||||
}
|
||||
|
||||
template <typename POS>
|
||||
DecorationList<POS>::~DecorationList() {
|
||||
current = nullptr;
|
||||
}
|
||||
|
||||
template <typename POS>
|
||||
Decoration<POS> *DecorationList<POS>::DecorationFromIndicator(int indicator) {
|
||||
for (const std::unique_ptr<Decoration<POS>> &deco : decorationList) {
|
||||
if (deco->Indicator() == indicator) {
|
||||
return deco.get();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename POS>
|
||||
Decoration<POS> *DecorationList<POS>::Create(int indicator, Sci::Position length) {
|
||||
currentIndicator = indicator;
|
||||
std::unique_ptr<Decoration<POS>> decoNew = std::unique_ptr<Decoration<POS>>(new Decoration<POS>(indicator));
|
||||
decoNew->rs.InsertSpace(0, static_cast<POS>(length));
|
||||
|
||||
typename std::vector<std::unique_ptr<Decoration<POS>>>::iterator it = std::lower_bound(
|
||||
decorationList.begin(), decorationList.end(), decoNew,
|
||||
[](const std::unique_ptr<Decoration<POS>> &a, const std::unique_ptr<Decoration<POS>> &b) {
|
||||
return a->Indicator() < b->Indicator();
|
||||
});
|
||||
typename std::vector<std::unique_ptr<Decoration<POS>>>::iterator itAdded =
|
||||
decorationList.insert(it, std::move(decoNew));
|
||||
|
||||
SetView();
|
||||
|
||||
return itAdded->get();
|
||||
}
|
||||
|
||||
template <typename POS>
|
||||
void DecorationList<POS>::Delete(int indicator) {
|
||||
decorationList.erase(std::remove_if(decorationList.begin(), decorationList.end(),
|
||||
[indicator](const std::unique_ptr<Decoration<POS>> &deco) {
|
||||
return deco->Indicator() == indicator;
|
||||
}), decorationList.end());
|
||||
current = nullptr;
|
||||
SetView();
|
||||
}
|
||||
|
||||
template <typename POS>
|
||||
void DecorationList<POS>::SetCurrentIndicator(int indicator) {
|
||||
currentIndicator = indicator;
|
||||
current = DecorationFromIndicator(indicator);
|
||||
currentValue = 1;
|
||||
}
|
||||
|
||||
template <typename POS>
|
||||
void DecorationList<POS>::SetCurrentValue(int value) {
|
||||
currentValue = value ? value : 1;
|
||||
}
|
||||
|
||||
template <typename POS>
|
||||
FillResult<Sci::Position> DecorationList<POS>::FillRange(Sci::Position position, int value, Sci::Position fillLength) {
|
||||
if (!current) {
|
||||
current = DecorationFromIndicator(currentIndicator);
|
||||
if (!current) {
|
||||
current = Create(currentIndicator, lengthDocument);
|
||||
}
|
||||
}
|
||||
// Converting result from POS to Sci::Position as callers not polymorphic.
|
||||
const FillResult<POS> frInPOS = current->rs.FillRange(static_cast<POS>(position), value, static_cast<POS>(fillLength));
|
||||
const FillResult<Sci::Position> fr { frInPOS.changed, frInPOS.position, frInPOS.fillLength };
|
||||
if (current->Empty()) {
|
||||
Delete(currentIndicator);
|
||||
}
|
||||
return fr;
|
||||
}
|
||||
|
||||
template <typename POS>
|
||||
void DecorationList<POS>::InsertSpace(Sci::Position position, Sci::Position insertLength) {
|
||||
const bool atEnd = position == lengthDocument;
|
||||
lengthDocument += insertLength;
|
||||
for (const std::unique_ptr<Decoration<POS>> &deco : decorationList) {
|
||||
deco->rs.InsertSpace(static_cast<POS>(position), static_cast<POS>(insertLength));
|
||||
if (atEnd) {
|
||||
deco->rs.FillRange(static_cast<POS>(position), 0, static_cast<POS>(insertLength));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename POS>
|
||||
void DecorationList<POS>::DeleteRange(Sci::Position position, Sci::Position deleteLength) {
|
||||
lengthDocument -= deleteLength;
|
||||
for (const std::unique_ptr<Decoration<POS>> &deco : decorationList) {
|
||||
deco->rs.DeleteRange(static_cast<POS>(position), static_cast<POS>(deleteLength));
|
||||
}
|
||||
DeleteAnyEmpty();
|
||||
if (decorationList.size() != decorationView.size()) {
|
||||
// One or more empty decorations deleted so update view.
|
||||
current = nullptr;
|
||||
SetView();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename POS>
|
||||
void DecorationList<POS>::DeleteLexerDecorations() {
|
||||
decorationList.erase(std::remove_if(decorationList.begin(), decorationList.end(),
|
||||
[](const std::unique_ptr<Decoration<POS>> &deco) {
|
||||
return deco->Indicator() < INDIC_CONTAINER;
|
||||
}), decorationList.end());
|
||||
current = nullptr;
|
||||
SetView();
|
||||
}
|
||||
|
||||
template <typename POS>
|
||||
void DecorationList<POS>::DeleteAnyEmpty() {
|
||||
if (lengthDocument == 0) {
|
||||
decorationList.clear();
|
||||
} else {
|
||||
decorationList.erase(std::remove_if(decorationList.begin(), decorationList.end(),
|
||||
[](const std::unique_ptr<Decoration<POS>> &deco) {
|
||||
return deco->Empty();
|
||||
}), decorationList.end());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename POS>
|
||||
void DecorationList<POS>::SetView() {
|
||||
decorationView.clear();
|
||||
for (const std::unique_ptr<Decoration<POS>> &deco : decorationList) {
|
||||
decorationView.push_back(deco.get());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename POS>
|
||||
int DecorationList<POS>::AllOnFor(Sci::Position position) const {
|
||||
int mask = 0;
|
||||
for (const std::unique_ptr<Decoration<POS>> &deco : decorationList) {
|
||||
if (deco->rs.ValueAt(static_cast<POS>(position))) {
|
||||
if (deco->Indicator() < INDIC_IME) {
|
||||
mask |= 1 << deco->Indicator();
|
||||
}
|
||||
}
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
template <typename POS>
|
||||
int DecorationList<POS>::ValueAt(int indicator, Sci::Position position) {
|
||||
const Decoration<POS> *deco = DecorationFromIndicator(indicator);
|
||||
if (deco) {
|
||||
return deco->rs.ValueAt(static_cast<POS>(position));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename POS>
|
||||
Sci::Position DecorationList<POS>::Start(int indicator, Sci::Position position) {
|
||||
const Decoration<POS> *deco = DecorationFromIndicator(indicator);
|
||||
if (deco) {
|
||||
return deco->rs.StartRun(static_cast<POS>(position));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename POS>
|
||||
Sci::Position DecorationList<POS>::End(int indicator, Sci::Position position) {
|
||||
const Decoration<POS> *deco = DecorationFromIndicator(indicator);
|
||||
if (deco) {
|
||||
return deco->rs.EndRun(static_cast<POS>(position));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
std::unique_ptr<IDecoration> DecorationCreate(bool largeDocument, int indicator) {
|
||||
if (largeDocument)
|
||||
return std::unique_ptr<Decoration<Sci::Position>>(new Decoration<Sci::Position>(indicator));
|
||||
else
|
||||
return std::unique_ptr<Decoration<int>>(new Decoration<int>(indicator));
|
||||
}
|
||||
|
||||
std::unique_ptr<IDecorationList> DecorationListCreate(bool largeDocument) {
|
||||
if (largeDocument)
|
||||
return std::unique_ptr<DecorationList<Sci::Position>>(new DecorationList<Sci::Position>());
|
||||
else
|
||||
return std::unique_ptr<DecorationList<int>>(new DecorationList<int>());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
59
third_party/qscintilla/scintilla/src/Decoration.h
vendored
Normal file
59
third_party/qscintilla/scintilla/src/Decoration.h
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/** @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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
class IDecoration {
|
||||
public:
|
||||
virtual ~IDecoration() {}
|
||||
virtual bool Empty() const = 0;
|
||||
virtual int Indicator() const = 0;
|
||||
virtual Sci::Position Length() const = 0;
|
||||
virtual int ValueAt(Sci::Position position) const = 0;
|
||||
virtual Sci::Position StartRun(Sci::Position position) const = 0;
|
||||
virtual Sci::Position EndRun(Sci::Position position) const = 0;
|
||||
virtual void SetValueAt(Sci::Position position, int value) = 0;
|
||||
virtual void InsertSpace(Sci::Position position, Sci::Position insertLength) = 0;
|
||||
virtual Sci::Position Runs() const = 0;
|
||||
};
|
||||
|
||||
class IDecorationList {
|
||||
public:
|
||||
virtual ~IDecorationList() {}
|
||||
|
||||
virtual const std::vector<const IDecoration*> &View() const =0;
|
||||
|
||||
virtual void SetCurrentIndicator(int indicator) = 0;
|
||||
virtual int GetCurrentIndicator() const = 0;
|
||||
|
||||
virtual void SetCurrentValue(int value) = 0;
|
||||
virtual int GetCurrentValue() const = 0;
|
||||
|
||||
// Returns with changed=true if some values may have changed
|
||||
virtual FillResult<Sci::Position> FillRange(Sci::Position position, int value, Sci::Position fillLength) = 0;
|
||||
virtual void InsertSpace(Sci::Position position, Sci::Position insertLength) = 0;
|
||||
virtual void DeleteRange(Sci::Position position, Sci::Position deleteLength) = 0;
|
||||
virtual void DeleteLexerDecorations() = 0;
|
||||
|
||||
virtual int AllOnFor(Sci::Position position) const = 0;
|
||||
virtual int ValueAt(int indicator, Sci::Position position) = 0;
|
||||
virtual Sci::Position Start(int indicator, Sci::Position position) = 0;
|
||||
virtual Sci::Position End(int indicator, Sci::Position position) = 0;
|
||||
|
||||
virtual bool ClickNotified() const = 0;
|
||||
virtual void SetClickNotified(bool notified) = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<IDecoration> DecorationCreate(bool largeDocument, int indicator);
|
||||
|
||||
std::unique_ptr<IDecorationList> DecorationListCreate(bool largeDocument);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
3250
third_party/qscintilla/scintilla/src/Document.cpp
vendored
Normal file
3250
third_party/qscintilla/scintilla/src/Document.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
584
third_party/qscintilla/scintilla/src/Document.h
vendored
Normal file
584
third_party/qscintilla/scintilla/src/Document.h
vendored
Normal file
@@ -0,0 +1,584 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
class DocWatcher;
|
||||
class DocModification;
|
||||
class Document;
|
||||
class LineMarkers;
|
||||
class LineLevels;
|
||||
class LineState;
|
||||
class LineAnnotation;
|
||||
|
||||
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:
|
||||
Sci::Position start;
|
||||
Sci::Position end;
|
||||
|
||||
explicit Range(Sci::Position pos=0) noexcept :
|
||||
start(pos), end(pos) {
|
||||
}
|
||||
Range(Sci::Position start_, Sci::Position end_) noexcept :
|
||||
start(start_), end(end_) {
|
||||
}
|
||||
|
||||
bool operator==(const Range &other) const noexcept {
|
||||
return (start == other.start) && (end == other.end);
|
||||
}
|
||||
|
||||
bool Valid() const noexcept {
|
||||
return (start != Sci::invalidPosition) && (end != Sci::invalidPosition);
|
||||
}
|
||||
|
||||
Sci::Position First() const noexcept {
|
||||
return (start <= end) ? start : end;
|
||||
}
|
||||
|
||||
Sci::Position Last() const noexcept {
|
||||
return (start > end) ? start : end;
|
||||
}
|
||||
|
||||
// Is the position within the range?
|
||||
bool Contains(Sci::Position pos) const noexcept {
|
||||
if (start < end) {
|
||||
return (pos >= start && pos <= end);
|
||||
} else {
|
||||
return (pos <= start && pos >= end);
|
||||
}
|
||||
}
|
||||
|
||||
// Is the character after pos within the range?
|
||||
bool ContainsCharacter(Sci::Position pos) const noexcept {
|
||||
if (start < end) {
|
||||
return (pos >= start && pos < end);
|
||||
} else {
|
||||
return (pos < start && pos >= end);
|
||||
}
|
||||
}
|
||||
|
||||
bool Contains(Range other) const noexcept {
|
||||
return Contains(other.start) && Contains(other.end);
|
||||
}
|
||||
|
||||
bool Overlaps(Range other) const noexcept {
|
||||
return
|
||||
Contains(other.start) ||
|
||||
Contains(other.end) ||
|
||||
other.Contains(start) ||
|
||||
other.Contains(end);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface class for regular expression searching
|
||||
*/
|
||||
class RegexSearchBase {
|
||||
public:
|
||||
virtual ~RegexSearchBase() {}
|
||||
|
||||
virtual Sci::Position FindText(Document *doc, Sci::Position minPos, Sci::Position maxPos, const char *s,
|
||||
bool caseSensitive, bool word, bool wordStart, int flags, Sci::Position *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, Sci::Position *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_) noexcept :
|
||||
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 noexcept {
|
||||
size_t cur = start;
|
||||
while ((cur < length) && (text[cur] != '\n'))
|
||||
cur++;
|
||||
return cur-start;
|
||||
}
|
||||
size_t StyleAt(size_t i) const noexcept {
|
||||
return multipleStyles ? styles[i] : style;
|
||||
}
|
||||
};
|
||||
|
||||
class HighlightDelimiter {
|
||||
public:
|
||||
HighlightDelimiter() : isEnabled(false) {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
beginFoldBlock = -1;
|
||||
endFoldBlock = -1;
|
||||
firstChangeableLineBefore = -1;
|
||||
firstChangeableLineAfter = -1;
|
||||
}
|
||||
|
||||
bool NeedsDrawing(Sci::Line line) const {
|
||||
return isEnabled && (line <= firstChangeableLineBefore || line >= firstChangeableLineAfter);
|
||||
}
|
||||
|
||||
bool IsFoldBlockHighlighted(Sci::Line line) const {
|
||||
return isEnabled && beginFoldBlock != -1 && beginFoldBlock <= line && line <= endFoldBlock;
|
||||
}
|
||||
|
||||
bool IsHeadOfFoldBlock(Sci::Line line) const {
|
||||
return beginFoldBlock == line && line < endFoldBlock;
|
||||
}
|
||||
|
||||
bool IsBodyOfFoldBlock(Sci::Line line) const {
|
||||
return beginFoldBlock != -1 && beginFoldBlock < line && line < endFoldBlock;
|
||||
}
|
||||
|
||||
bool IsTailOfFoldBlock(Sci::Line line) const {
|
||||
return beginFoldBlock != -1 && beginFoldBlock < line && line == endFoldBlock;
|
||||
}
|
||||
|
||||
Sci::Line beginFoldBlock; // Begin of current fold block
|
||||
Sci::Line endFoldBlock; // End of current fold block
|
||||
Sci::Line firstChangeableLineBefore; // First line that triggers repaint before starting line that determined current fold block
|
||||
Sci::Line firstChangeableLineAfter; // First line that triggers repaint after starting line that determined current fold block
|
||||
bool isEnabled;
|
||||
};
|
||||
|
||||
inline int LevelNumber(int level) noexcept {
|
||||
return level & SC_FOLDLEVELNUMBERMASK;
|
||||
}
|
||||
|
||||
class LexInterface {
|
||||
protected:
|
||||
Document *pdoc;
|
||||
ILexer *instance;
|
||||
bool performingStyle; ///< Prevent reentrance
|
||||
public:
|
||||
explicit LexInterface(Document *pdoc_) : pdoc(pdoc_), instance(nullptr), performingStyle(false) {
|
||||
}
|
||||
virtual ~LexInterface() {
|
||||
}
|
||||
void Colourise(Sci::Position start, Sci::Position end);
|
||||
virtual int LineEndTypesSupported();
|
||||
bool UseContainerLexing() const {
|
||||
return instance == nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
struct RegexError : public std::runtime_error {
|
||||
RegexError() : std::runtime_error("regex failure") {}
|
||||
};
|
||||
|
||||
/**
|
||||
* The ActionDuration class stores the average time taken for some action such as styling or
|
||||
* wrapping a line. It is used to decide how many repetitions of that action can be performed
|
||||
* on idle to maximize efficiency without affecting application responsiveness.
|
||||
* The duration changes if the time for the action changes. For example, if a simple lexer is
|
||||
* changed to a complex lexer. Changes are damped and clamped to avoid short periods of easy
|
||||
* or difficult processing moving the value too far leading to inefficiency or poor user
|
||||
* experience.
|
||||
*/
|
||||
|
||||
class ActionDuration {
|
||||
double duration;
|
||||
const double minDuration;
|
||||
const double maxDuration;
|
||||
public:
|
||||
ActionDuration(double duration_, double minDuration_, double maxDuration_) noexcept;
|
||||
void AddSample(size_t numberActions, double durationOfActions) noexcept;
|
||||
double Duration() const noexcept;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
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_=nullptr, void *userData_=nullptr) noexcept :
|
||||
watcher(watcher_), userData(userData_) {
|
||||
}
|
||||
bool operator==(const WatcherWithUserData &other) const noexcept {
|
||||
return (watcher == other.watcher) && (userData == other.userData);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
int refCount;
|
||||
CellBuffer cb;
|
||||
CharClassify charClass;
|
||||
std::unique_ptr<CaseFolder> pcf;
|
||||
Sci::Position 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 };
|
||||
std::unique_ptr<PerLine> perLineData[ldSize];
|
||||
LineMarkers *Markers() const;
|
||||
LineLevels *Levels() const;
|
||||
LineState *States() const;
|
||||
LineAnnotation *Margins() const;
|
||||
LineAnnotation *Annotations() const;
|
||||
|
||||
bool matchesValid;
|
||||
std::unique_ptr<RegexSearchBase> regex;
|
||||
std::unique_ptr<LexInterface> pli;
|
||||
|
||||
public:
|
||||
|
||||
struct CharacterExtracted {
|
||||
unsigned int character;
|
||||
unsigned int widthBytes;
|
||||
CharacterExtracted(unsigned int character_, unsigned int widthBytes_) noexcept :
|
||||
character(character_), widthBytes(widthBytes_) {
|
||||
}
|
||||
// For DBCS characters turn 2 bytes into an int
|
||||
static CharacterExtracted DBCS(unsigned char lead, unsigned char trail) noexcept {
|
||||
return CharacterExtracted((lead << 8) | trail, 2);
|
||||
}
|
||||
};
|
||||
|
||||
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;
|
||||
ActionDuration durationStyleOneLine;
|
||||
|
||||
std::unique_ptr<IDecorationList> decorations;
|
||||
|
||||
Document(int options);
|
||||
// Deleted so Document objects can not be copied.
|
||||
Document(const Document &) = delete;
|
||||
Document(Document &&) = delete;
|
||||
void operator=(const Document &) = delete;
|
||||
Document &operator=(Document &&) = delete;
|
||||
~Document() override;
|
||||
|
||||
int AddRef();
|
||||
int SCI_METHOD Release() override;
|
||||
|
||||
// From PerLine
|
||||
void Init() override;
|
||||
void InsertLine(Sci::Line line) override;
|
||||
void RemoveLine(Sci::Line line) override;
|
||||
|
||||
int LineEndTypesSupported() const;
|
||||
bool SetDBCSCodePage(int dbcsCodePage_);
|
||||
int GetLineEndTypesAllowed() const { return cb.GetLineEndTypes(); }
|
||||
bool SetLineEndTypesAllowed(int lineEndBitSet_);
|
||||
int GetLineEndTypesActive() const { return cb.GetLineEndTypes(); }
|
||||
|
||||
int SCI_METHOD Version() const override {
|
||||
return dvLineEnd;
|
||||
}
|
||||
|
||||
void SCI_METHOD SetErrorStatus(int status) override;
|
||||
|
||||
Sci_Position SCI_METHOD LineFromPosition(Sci_Position pos) const override;
|
||||
Sci::Line SciLineFromPosition(Sci::Position pos) const noexcept; // Avoids casting LineFromPosition
|
||||
Sci::Position ClampPositionIntoDocument(Sci::Position pos) const;
|
||||
bool ContainsLineEnd(const char *s, Sci::Position length) const { return cb.ContainsLineEnd(s, length); }
|
||||
bool IsCrLf(Sci::Position pos) const;
|
||||
int LenChar(Sci::Position pos);
|
||||
bool InGoodUTF8(Sci::Position pos, Sci::Position &start, Sci::Position &end) const noexcept;
|
||||
Sci::Position MovePositionOutsideChar(Sci::Position pos, Sci::Position moveDir, bool checkLineEnd=true) const;
|
||||
Sci::Position NextPosition(Sci::Position pos, int moveDir) const noexcept;
|
||||
bool NextCharacter(Sci::Position &pos, int moveDir) const noexcept; // Returns true if pos changed
|
||||
Document::CharacterExtracted CharacterAfter(Sci::Position position) const;
|
||||
Document::CharacterExtracted CharacterBefore(Sci::Position position) const;
|
||||
Sci_Position SCI_METHOD GetRelativePosition(Sci_Position positionStart, Sci_Position characterOffset) const override;
|
||||
Sci::Position GetRelativePositionUTF16(Sci::Position positionStart, Sci::Position characterOffset) const;
|
||||
int SCI_METHOD GetCharacterAndWidth(Sci_Position position, Sci_Position *pWidth) const override;
|
||||
int SCI_METHOD CodePage() const override;
|
||||
bool SCI_METHOD IsDBCSLeadByte(char ch) const override;
|
||||
bool IsDBCSLeadByteNoExcept(char ch) const noexcept;
|
||||
bool IsDBCSLeadByteInvalid(char ch) const noexcept;
|
||||
bool IsDBCSTrailByteInvalid(char ch) const noexcept;
|
||||
int DBCSDrawBytes(const char *text, int len) const noexcept;
|
||||
int SafeSegment(const char *text, int length, int lengthSegment) const noexcept;
|
||||
EncodingFamily CodePageFamily() const noexcept;
|
||||
|
||||
// Gateways to modifying document
|
||||
void ModifiedAt(Sci::Position pos) noexcept;
|
||||
void CheckReadOnly();
|
||||
bool DeleteChars(Sci::Position pos, Sci::Position len);
|
||||
Sci::Position InsertString(Sci::Position position, const char *s, Sci::Position insertLength);
|
||||
void ChangeInsertion(const char *s, Sci::Position length);
|
||||
int SCI_METHOD AddData(const char *data, Sci_Position length) override;
|
||||
void * SCI_METHOD ConvertToDocument() override;
|
||||
Sci::Position Undo();
|
||||
Sci::Position 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(Sci::Position token, bool mayCoalesce) { cb.AddUndoAction(token, mayCoalesce); }
|
||||
void SetSavePoint();
|
||||
bool IsSavePoint() const { return cb.IsSavePoint(); }
|
||||
|
||||
void TentativeStart() { cb.TentativeStart(); }
|
||||
void TentativeCommit() { cb.TentativeCommit(); }
|
||||
void TentativeUndo();
|
||||
bool TentativeActive() const { return cb.TentativeActive(); }
|
||||
|
||||
const char * SCI_METHOD BufferPointer() override { return cb.BufferPointer(); }
|
||||
const char *RangePointer(Sci::Position position, Sci::Position rangeLength) { return cb.RangePointer(position, rangeLength); }
|
||||
Sci::Position GapPosition() const { return cb.GapPosition(); }
|
||||
|
||||
int SCI_METHOD GetLineIndentation(Sci_Position line) override;
|
||||
Sci::Position SetLineIndentation(Sci::Line line, Sci::Position indent);
|
||||
Sci::Position GetLineIndentPosition(Sci::Line line) const;
|
||||
Sci::Position GetColumn(Sci::Position pos);
|
||||
Sci::Position CountCharacters(Sci::Position startPos, Sci::Position endPos) const;
|
||||
Sci::Position CountUTF16(Sci::Position startPos, Sci::Position endPos) const;
|
||||
Sci::Position FindColumn(Sci::Line line, Sci::Position column);
|
||||
void Indent(bool forwards, Sci::Line lineBottom, Sci::Line 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(); }
|
||||
bool IsLarge() const { return cb.IsLarge(); }
|
||||
int Options() const;
|
||||
|
||||
void DelChar(Sci::Position pos);
|
||||
void DelCharBack(Sci::Position pos);
|
||||
|
||||
char CharAt(Sci::Position position) const noexcept { return cb.CharAt(position); }
|
||||
void SCI_METHOD GetCharRange(char *buffer, Sci_Position position, Sci_Position lengthRetrieve) const override {
|
||||
cb.GetCharRange(buffer, position, lengthRetrieve);
|
||||
}
|
||||
char SCI_METHOD StyleAt(Sci_Position position) const override { return cb.StyleAt(position); }
|
||||
int StyleIndexAt(Sci_Position position) const noexcept { return static_cast<unsigned char>(cb.StyleAt(position)); }
|
||||
void GetStyleRange(unsigned char *buffer, Sci::Position position, Sci::Position lengthRetrieve) const {
|
||||
cb.GetStyleRange(buffer, position, lengthRetrieve);
|
||||
}
|
||||
int GetMark(Sci::Line line) const;
|
||||
Sci::Line MarkerNext(Sci::Line lineStart, int mask) const;
|
||||
int AddMark(Sci::Line line, int markerNum);
|
||||
void AddMarkSet(Sci::Line line, int valueSet);
|
||||
void DeleteMark(Sci::Line line, int markerNum);
|
||||
void DeleteMarkFromHandle(int markerHandle);
|
||||
void DeleteAllMarks(int markerNum);
|
||||
Sci::Line LineFromHandle(int markerHandle) const;
|
||||
Sci_Position SCI_METHOD LineStart(Sci_Position line) const override;
|
||||
bool IsLineStartPosition(Sci::Position position) const;
|
||||
Sci_Position SCI_METHOD LineEnd(Sci_Position line) const override;
|
||||
Sci::Position LineEndPosition(Sci::Position position) const;
|
||||
bool IsLineEndPosition(Sci::Position position) const;
|
||||
bool IsPositionInLineEnd(Sci::Position position) const;
|
||||
Sci::Position VCHomePosition(Sci::Position position) const;
|
||||
Sci::Position IndexLineStart(Sci::Line line, int lineCharacterIndex) const;
|
||||
Sci::Line LineFromPositionIndex(Sci::Position pos, int lineCharacterIndex) const;
|
||||
|
||||
int SCI_METHOD SetLevel(Sci_Position line, int level) override;
|
||||
int SCI_METHOD GetLevel(Sci_Position line) const override;
|
||||
void ClearLevels();
|
||||
Sci::Line GetLastChild(Sci::Line lineParent, int level=-1, Sci::Line lastLine=-1);
|
||||
Sci::Line GetFoldParent(Sci::Line line) const;
|
||||
void GetHighlightDelimiters(HighlightDelimiter &highlightDelimiter, Sci::Line line, Sci::Line lastLine);
|
||||
|
||||
Sci::Position ExtendWordSelect(Sci::Position pos, int delta, bool onlyWordCharacters=false) const;
|
||||
Sci::Position NextWordStart(Sci::Position pos, int delta) const;
|
||||
Sci::Position NextWordEnd(Sci::Position pos, int delta) const;
|
||||
Sci_Position SCI_METHOD Length() const override { return cb.Length(); }
|
||||
void Allocate(Sci::Position newSize) { cb.Allocate(newSize); }
|
||||
|
||||
CharacterExtracted ExtractCharacter(Sci::Position position) const noexcept;
|
||||
|
||||
bool IsWordStartAt(Sci::Position pos) const;
|
||||
bool IsWordEndAt(Sci::Position pos) const;
|
||||
bool IsWordAt(Sci::Position start, Sci::Position end) const;
|
||||
|
||||
bool MatchesWordOptions(bool word, bool wordStart, Sci::Position pos, Sci::Position length) const;
|
||||
bool HasCaseFolder() const noexcept;
|
||||
void SetCaseFolder(CaseFolder *pcf_);
|
||||
Sci::Position FindText(Sci::Position minPos, Sci::Position maxPos, const char *search, int flags, Sci::Position *length);
|
||||
const char *SubstituteByPosition(const char *text, Sci::Position *length);
|
||||
int LineCharacterIndex() const;
|
||||
void AllocateLineCharacterIndex(int lineCharacterIndex);
|
||||
void ReleaseLineCharacterIndex(int lineCharacterIndex);
|
||||
Sci::Line LinesTotal() const noexcept;
|
||||
|
||||
void SetDefaultCharClasses(bool includeWordClass);
|
||||
void SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass);
|
||||
int GetCharsOfClass(CharClassify::cc characterClass, unsigned char *buffer) const;
|
||||
void SCI_METHOD StartStyling(Sci_Position position, char mask) override;
|
||||
bool SCI_METHOD SetStyleFor(Sci_Position length, char style) override;
|
||||
bool SCI_METHOD SetStyles(Sci_Position length, const char *styles) override;
|
||||
Sci::Position GetEndStyled() const noexcept { return endStyled; }
|
||||
void EnsureStyledTo(Sci::Position pos);
|
||||
void StyleToAdjustingLineDuration(Sci::Position pos);
|
||||
void LexerChanged();
|
||||
int GetStyleClock() const noexcept { return styleClock; }
|
||||
void IncrementStyleClock() noexcept;
|
||||
void SCI_METHOD DecorationSetCurrentIndicator(int indicator) override;
|
||||
void SCI_METHOD DecorationFillRange(Sci_Position position, int value, Sci_Position fillLength) override;
|
||||
LexInterface *GetLexInterface() const;
|
||||
void SetLexInterface(LexInterface *pLexInterface);
|
||||
|
||||
int SCI_METHOD SetLineState(Sci_Position line, int state) override;
|
||||
int SCI_METHOD GetLineState(Sci_Position line) const override;
|
||||
Sci::Line GetMaxLineState() const;
|
||||
void SCI_METHOD ChangeLexerState(Sci_Position start, Sci_Position end) override;
|
||||
|
||||
StyledText MarginStyledText(Sci::Line line) const;
|
||||
void MarginSetStyle(Sci::Line line, int style);
|
||||
void MarginSetStyles(Sci::Line line, const unsigned char *styles);
|
||||
void MarginSetText(Sci::Line line, const char *text);
|
||||
void MarginClearAll();
|
||||
|
||||
StyledText AnnotationStyledText(Sci::Line line) const;
|
||||
void AnnotationSetText(Sci::Line line, const char *text);
|
||||
void AnnotationSetStyle(Sci::Line line, int style);
|
||||
void AnnotationSetStyles(Sci::Line line, const unsigned char *styles);
|
||||
int AnnotationLines(Sci::Line line) const;
|
||||
void AnnotationClearAll();
|
||||
|
||||
bool AddWatcher(DocWatcher *watcher, void *userData);
|
||||
bool RemoveWatcher(DocWatcher *watcher, void *userData);
|
||||
|
||||
bool IsASCIIWordByte(unsigned char ch) const;
|
||||
CharClassify::cc WordCharacterClass(unsigned int ch) const;
|
||||
bool IsWordPartSeparator(unsigned int ch) const;
|
||||
Sci::Position WordPartLeft(Sci::Position pos) const;
|
||||
Sci::Position WordPartRight(Sci::Position pos) const;
|
||||
Sci::Position ExtendStyleRange(Sci::Position pos, int delta, bool singleLine = false);
|
||||
bool IsWhiteLine(Sci::Line line) const;
|
||||
Sci::Position ParaUp(Sci::Position pos) const;
|
||||
Sci::Position ParaDown(Sci::Position pos) const;
|
||||
int IndentSize() const noexcept { return actualIndentInChars; }
|
||||
Sci::Position BraceMatch(Sci::Position position, Sci::Position maxReStyle);
|
||||
|
||||
private:
|
||||
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 noexcept {
|
||||
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;
|
||||
Sci::Position position;
|
||||
Sci::Position length;
|
||||
Sci::Line linesAdded; /**< Negative if lines deleted. */
|
||||
const char *text; /**< Only valid for changes to text, not for changes to style. */
|
||||
Sci::Line line;
|
||||
int foldLevelNow;
|
||||
int foldLevelPrev;
|
||||
Sci::Line annotationLinesAdded;
|
||||
Sci::Position token;
|
||||
|
||||
DocModification(int modificationType_, Sci::Position position_=0, Sci::Position length_=0,
|
||||
Sci::Line linesAdded_=0, const char *text_=nullptr, Sci::Line line_=0) noexcept :
|
||||
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, Sci::Line linesAdded_=0) noexcept :
|
||||
modificationType(modificationType_),
|
||||
position(act.position),
|
||||
length(act.lenData),
|
||||
linesAdded(linesAdded_),
|
||||
text(act.data.get()),
|
||||
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, Sci::Position endPos) = 0;
|
||||
virtual void NotifyLexerChanged(Document *doc, void *userData) = 0;
|
||||
virtual void NotifyErrorOccurred(Document *doc, void *userData, int status) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
77
third_party/qscintilla/scintilla/src/EditModel.cpp
vendored
Normal file
77
third_party/qscintilla/scintilla/src/EditModel.cpp
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file EditModel.cxx
|
||||
** Defines the editor state that must be visible to EditorView.
|
||||
**/
|
||||
// Copyright 1998-2014 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "ILoader.h"
|
||||
#include "ILexer.h"
|
||||
#include "Scintilla.h"
|
||||
|
||||
#include "Position.h"
|
||||
#include "UniqueString.h"
|
||||
#include "SplitVector.h"
|
||||
#include "Partitioning.h"
|
||||
#include "RunStyles.h"
|
||||
#include "ContractionState.h"
|
||||
#include "CellBuffer.h"
|
||||
#include "KeyMap.h"
|
||||
#include "Indicator.h"
|
||||
#include "LineMarker.h"
|
||||
#include "Style.h"
|
||||
#include "ViewStyle.h"
|
||||
#include "CharClassify.h"
|
||||
#include "Decoration.h"
|
||||
#include "CaseFolder.h"
|
||||
#include "Document.h"
|
||||
#include "UniConversion.h"
|
||||
#include "Selection.h"
|
||||
#include "PositionCache.h"
|
||||
#include "EditModel.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
Caret::Caret() :
|
||||
active(false), on(false), period(500) {}
|
||||
|
||||
EditModel::EditModel() : braces{} {
|
||||
inOverstrike = false;
|
||||
xOffset = 0;
|
||||
trackLineWidth = false;
|
||||
posDrag = SelectionPosition(Sci::invalidPosition);
|
||||
braces[0] = Sci::invalidPosition;
|
||||
braces[1] = Sci::invalidPosition;
|
||||
bracesMatchStyle = STYLE_BRACEBAD;
|
||||
highlightGuideColumn = 0;
|
||||
primarySelection = true;
|
||||
imeInteraction = imeWindowed;
|
||||
foldFlags = 0;
|
||||
foldDisplayTextStyle = SC_FOLDDISPLAYTEXT_HIDDEN;
|
||||
hotspot = Range(Sci::invalidPosition);
|
||||
hoverIndicatorPos = Sci::invalidPosition;
|
||||
wrapWidth = LineLayout::wrapWidthInfinite;
|
||||
pdoc = new Document(SC_DOCUMENTOPTION_DEFAULT);
|
||||
pdoc->AddRef();
|
||||
pcs = ContractionStateCreate(pdoc->IsLarge());
|
||||
}
|
||||
|
||||
EditModel::~EditModel() {
|
||||
pdoc->Release();
|
||||
pdoc = nullptr;
|
||||
}
|
||||
68
third_party/qscintilla/scintilla/src/EditModel.h
vendored
Normal file
68
third_party/qscintilla/scintilla/src/EditModel.h
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file EditModel.h
|
||||
** Defines the editor state that must be visible to EditorView.
|
||||
**/
|
||||
// Copyright 1998-2014 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef EDITMODEL_H
|
||||
#define EDITMODEL_H
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
/**
|
||||
*/
|
||||
class Caret {
|
||||
public:
|
||||
bool active;
|
||||
bool on;
|
||||
int period;
|
||||
|
||||
Caret();
|
||||
};
|
||||
|
||||
class EditModel {
|
||||
public:
|
||||
bool inOverstrike;
|
||||
int xOffset; ///< Horizontal scrolled amount in pixels
|
||||
bool trackLineWidth;
|
||||
|
||||
SpecialRepresentations reprs;
|
||||
Caret caret;
|
||||
SelectionPosition posDrag;
|
||||
Sci::Position braces[2];
|
||||
int bracesMatchStyle;
|
||||
int highlightGuideColumn;
|
||||
Selection sel;
|
||||
bool primarySelection;
|
||||
|
||||
enum IMEInteraction { imeWindowed, imeInline } imeInteraction;
|
||||
|
||||
int foldFlags;
|
||||
int foldDisplayTextStyle;
|
||||
std::unique_ptr<IContractionState> pcs;
|
||||
// Hotspot support
|
||||
Range hotspot;
|
||||
Sci::Position hoverIndicatorPos;
|
||||
|
||||
// Wrapping support
|
||||
int wrapWidth;
|
||||
|
||||
Document *pdoc;
|
||||
|
||||
EditModel();
|
||||
// Deleted so EditModel objects can not be copied.
|
||||
EditModel(const EditModel &) = delete;
|
||||
EditModel(EditModel &&) = delete;
|
||||
EditModel &operator=(const EditModel &) = delete;
|
||||
EditModel &operator=(EditModel &&) = delete;
|
||||
virtual ~EditModel();
|
||||
virtual Sci::Line TopLineOfMain() const = 0;
|
||||
virtual Point GetVisibleOriginInMain() const = 0;
|
||||
virtual Sci::Line LinesOnScreen() const = 0;
|
||||
virtual Range GetHotSpotRange() const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
2403
third_party/qscintilla/scintilla/src/EditView.cpp
vendored
Normal file
2403
third_party/qscintilla/scintilla/src/EditView.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
186
third_party/qscintilla/scintilla/src/EditView.h
vendored
Normal file
186
third_party/qscintilla/scintilla/src/EditView.h
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file EditView.h
|
||||
** Defines the appearance of the main text area of the editor window.
|
||||
**/
|
||||
// Copyright 1998-2014 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef EDITVIEW_H
|
||||
#define EDITVIEW_H
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
struct PrintParameters {
|
||||
int magnification;
|
||||
int colourMode;
|
||||
WrapMode wrapState;
|
||||
PrintParameters();
|
||||
};
|
||||
|
||||
/**
|
||||
* The view may be drawn in separate phases.
|
||||
*/
|
||||
enum DrawPhase {
|
||||
drawBack = 0x1,
|
||||
drawIndicatorsBack = 0x2,
|
||||
drawText = 0x4,
|
||||
drawIndentationGuides = 0x8,
|
||||
drawIndicatorsFore = 0x10,
|
||||
drawSelectionTranslucent = 0x20,
|
||||
drawLineTranslucent = 0x40,
|
||||
drawFoldLines = 0x80,
|
||||
drawCarets = 0x100,
|
||||
drawAll = 0x1FF
|
||||
};
|
||||
|
||||
bool ValidStyledText(const ViewStyle &vs, size_t styleOffset, const StyledText &st);
|
||||
int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, const StyledText &st);
|
||||
void DrawTextNoClipPhase(Surface *surface, PRectangle rc, const Style &style, XYPOSITION ybase,
|
||||
const char *s, int len, DrawPhase phase);
|
||||
void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText,
|
||||
const StyledText &st, size_t start, size_t length, DrawPhase phase);
|
||||
|
||||
typedef void (*DrawTabArrowFn)(Surface *surface, PRectangle rcTab, int ymid);
|
||||
|
||||
class LineTabstops;
|
||||
|
||||
/**
|
||||
* EditView draws the main text area.
|
||||
*/
|
||||
class EditView {
|
||||
public:
|
||||
PrintParameters printParameters;
|
||||
std::unique_ptr<LineTabstops> ldTabstops;
|
||||
int tabWidthMinimumPixels;
|
||||
|
||||
bool hideSelection;
|
||||
bool drawOverstrikeCaret;
|
||||
|
||||
/** 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 phasesTwo mode, drawing is performed in two phases, first the background
|
||||
* and then the foreground. This avoids chopping off characters that overlap the next run.
|
||||
* In multiPhaseDraw mode, drawing is performed in multiple phases with each phase drawing
|
||||
* one feature over the whole drawing area, instead of within one line. This allows text to
|
||||
* overlap from one line to the next. */
|
||||
enum PhasesDraw { phasesOne, phasesTwo, phasesMultiple };
|
||||
PhasesDraw phasesDraw;
|
||||
|
||||
int lineWidthMaxSeen;
|
||||
|
||||
bool additionalCaretsBlink;
|
||||
bool additionalCaretsVisible;
|
||||
|
||||
bool imeCaretBlockOverride;
|
||||
|
||||
std::unique_ptr<Surface> pixmapLine;
|
||||
std::unique_ptr<Surface> pixmapIndentGuide;
|
||||
std::unique_ptr<Surface> pixmapIndentGuideHighlight;
|
||||
|
||||
LineLayoutCache llc;
|
||||
PositionCache posCache;
|
||||
|
||||
int tabArrowHeight; // draw arrow heads this many pixels above/below line midpoint
|
||||
/** Some platforms, notably PLAT_CURSES, do not support Scintilla's native
|
||||
* DrawTabArrow function for drawing tab characters. Allow those platforms to
|
||||
* override it instead of creating a new method in the Surface class that
|
||||
* existing platforms must implement as empty. */
|
||||
DrawTabArrowFn customDrawTabArrow;
|
||||
DrawWrapMarkerFn customDrawWrapMarker;
|
||||
|
||||
EditView();
|
||||
// Deleted so EditView objects can not be copied.
|
||||
EditView(const EditView &) = delete;
|
||||
EditView(EditView &&) = delete;
|
||||
void operator=(const EditView &) = delete;
|
||||
void operator=(EditView &&) = delete;
|
||||
virtual ~EditView();
|
||||
|
||||
bool SetTwoPhaseDraw(bool twoPhaseDraw);
|
||||
bool SetPhasesDraw(int phases);
|
||||
bool LinesOverlap() const;
|
||||
|
||||
void ClearAllTabstops();
|
||||
XYPOSITION NextTabstopPos(Sci::Line line, XYPOSITION x, XYPOSITION tabWidth) const;
|
||||
bool ClearTabstops(Sci::Line line);
|
||||
bool AddTabstop(Sci::Line line, int x);
|
||||
int GetNextTabstop(Sci::Line line, int x) const;
|
||||
void LinesAddedOrRemoved(Sci::Line lineOfPos, Sci::Line linesAdded);
|
||||
|
||||
void DropGraphics(bool freeObjects);
|
||||
void AllocateGraphics(const ViewStyle &vsDraw);
|
||||
void RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw);
|
||||
|
||||
LineLayout *RetrieveLineLayout(Sci::Line lineNumber, const EditModel &model);
|
||||
void LayoutLine(const EditModel &model, Sci::Line line, Surface *surface, const ViewStyle &vstyle,
|
||||
LineLayout *ll, int width = LineLayout::wrapWidthInfinite);
|
||||
|
||||
Point LocationFromPosition(Surface *surface, const EditModel &model, SelectionPosition pos, Sci::Line topLine,
|
||||
const ViewStyle &vs, PointEnd pe);
|
||||
Range RangeDisplayLine(Surface *surface, const EditModel &model, Sci::Line lineVisible, const ViewStyle &vs);
|
||||
SelectionPosition SPositionFromLocation(Surface *surface, const EditModel &model, PointDocument pt, bool canReturnInvalid,
|
||||
bool charPosition, bool virtualSpace, const ViewStyle &vs);
|
||||
SelectionPosition SPositionFromLineX(Surface *surface, const EditModel &model, Sci::Line lineDoc, int x, const ViewStyle &vs);
|
||||
Sci::Line DisplayFromPosition(Surface *surface, const EditModel &model, Sci::Position pos, const ViewStyle &vs);
|
||||
Sci::Position StartEndDisplayLine(Surface *surface, const EditModel &model, Sci::Position pos, bool start, const ViewStyle &vs);
|
||||
|
||||
void DrawIndentGuide(Surface *surface, Sci::Line lineVisible, int lineHeight, XYPOSITION start, PRectangle rcSegment, bool highlight);
|
||||
void DrawEOL(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, PRectangle rcLine,
|
||||
Sci::Line line, Sci::Position lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart,
|
||||
ColourOptional background);
|
||||
void DrawFoldDisplayText(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
|
||||
Sci::Line line, int xStart, PRectangle rcLine, int subLine, XYACCUMULATOR subLineStart, DrawPhase phase);
|
||||
void DrawAnnotation(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
|
||||
Sci::Line line, int xStart, PRectangle rcLine, int subLine, DrawPhase phase);
|
||||
void DrawCarets(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, Sci::Line lineDoc,
|
||||
int xStart, PRectangle rcLine, int subLine) const;
|
||||
void DrawBackground(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, PRectangle rcLine,
|
||||
Range lineRange, Sci::Position posLineStart, int xStart,
|
||||
int subLine, ColourOptional background) const;
|
||||
void DrawForeground(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, Sci::Line lineVisible,
|
||||
PRectangle rcLine, Range lineRange, Sci::Position posLineStart, int xStart,
|
||||
int subLine, ColourOptional background);
|
||||
void DrawIndentGuidesOverEmpty(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
|
||||
Sci::Line line, Sci::Line lineVisible, PRectangle rcLine, int xStart, int subLine);
|
||||
void DrawLine(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, Sci::Line line,
|
||||
Sci::Line lineVisible, int xStart, PRectangle rcLine, int subLine, DrawPhase phase);
|
||||
void PaintText(Surface *surfaceWindow, const EditModel &model, PRectangle rcArea, PRectangle rcClient,
|
||||
const ViewStyle &vsDraw);
|
||||
void FillLineRemainder(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
|
||||
Sci::Line line, PRectangle rcArea, int subLine) const;
|
||||
Sci::Position FormatRange(bool draw, const Sci_RangeToFormat *pfr, Surface *surface, Surface *surfaceMeasure,
|
||||
const EditModel &model, const ViewStyle &vs);
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience class to ensure LineLayout objects are always disposed.
|
||||
*/
|
||||
class AutoLineLayout {
|
||||
LineLayoutCache &llc;
|
||||
LineLayout *ll;
|
||||
public:
|
||||
AutoLineLayout(LineLayoutCache &llc_, LineLayout *ll_) noexcept : llc(llc_), ll(ll_) {}
|
||||
AutoLineLayout(const AutoLineLayout &) = delete;
|
||||
AutoLineLayout(AutoLineLayout &&) = delete;
|
||||
AutoLineLayout &operator=(const AutoLineLayout &) = delete;
|
||||
AutoLineLayout &operator=(AutoLineLayout &&) = delete;
|
||||
~AutoLineLayout() {
|
||||
llc.Dispose(ll);
|
||||
ll = nullptr;
|
||||
}
|
||||
LineLayout *operator->() const noexcept {
|
||||
return ll;
|
||||
}
|
||||
operator LineLayout *() const noexcept {
|
||||
return ll;
|
||||
}
|
||||
void Set(LineLayout *ll_) {
|
||||
llc.Dispose(ll);
|
||||
ll = ll_;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
8234
third_party/qscintilla/scintilla/src/Editor.cpp
vendored
Normal file
8234
third_party/qscintilla/scintilla/src/Editor.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
650
third_party/qscintilla/scintilla/src/Editor.h
vendored
Normal file
650
third_party/qscintilla/scintilla/src/Editor.h
vendored
Normal file
@@ -0,0 +1,650 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
/**
|
||||
*/
|
||||
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
|
||||
};
|
||||
enum workItems items;
|
||||
Sci::Position upTo;
|
||||
|
||||
WorkNeeded() : items(workNone), upTo(0) {}
|
||||
void Reset() {
|
||||
items = workNone;
|
||||
upTo = 0;
|
||||
}
|
||||
void Need(workItems items_, Sci::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) {}
|
||||
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 };
|
||||
Sci::Line start; // When there are wraps pending, will be in document range
|
||||
Sci::Line end; // May be lineLarge to indicate all of document after start
|
||||
WrapPending() {
|
||||
start = lineLarge;
|
||||
end = lineLarge;
|
||||
}
|
||||
void Reset() {
|
||||
start = lineLarge;
|
||||
end = lineLarge;
|
||||
}
|
||||
void Wrapped(Sci::Line line) {
|
||||
if (start == line)
|
||||
start++;
|
||||
}
|
||||
bool NeedsWrap() const {
|
||||
return start < end;
|
||||
}
|
||||
bool AddRange(Sci::Line lineStart, Sci::Line 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;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class Editor : public EditModel, public DocWatcher {
|
||||
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;
|
||||
|
||||
MarginView marginView;
|
||||
EditView view;
|
||||
|
||||
int cursorMode;
|
||||
|
||||
bool hasFocus;
|
||||
bool mouseDownCaptures;
|
||||
bool mouseWheelCaptures;
|
||||
|
||||
int xCaretMargin; ///< Ensure this many pixels visible on both sides of caret
|
||||
bool horizontalScrollBarVisible;
|
||||
int scrollWidth;
|
||||
bool verticalScrollBarVisible;
|
||||
bool endAtLastLine;
|
||||
int caretSticky;
|
||||
int marginOptions;
|
||||
bool mouseSelectionRectangularSwitch;
|
||||
bool multipleSelection;
|
||||
bool additionalSelectionTyping;
|
||||
int multiPasteMode;
|
||||
|
||||
int virtualSpaceOptions;
|
||||
|
||||
KeyMap kmap;
|
||||
|
||||
Timer timer;
|
||||
Timer autoScrollTimer;
|
||||
enum { autoScrollDelay = 200 };
|
||||
|
||||
Idler idler;
|
||||
|
||||
Point lastClick;
|
||||
unsigned int lastClickTime;
|
||||
Point doubleClickCloseThreshold;
|
||||
int dwellDelay;
|
||||
int ticksToDwell;
|
||||
bool dwelling;
|
||||
enum { selChar, selWord, selSubLine, selWholeLine } selectionType;
|
||||
Point ptMouseLast;
|
||||
enum { ddNone, ddInitial, ddDragging } inDragDrop;
|
||||
bool dropWentOutside;
|
||||
SelectionPosition posDrop;
|
||||
Sci::Position hotSpotClickPos;
|
||||
int lastXChosen;
|
||||
Sci::Position lineAnchorPos;
|
||||
Sci::Position originalAnchorPos;
|
||||
Sci::Position wordSelectAnchorStartPos;
|
||||
Sci::Position wordSelectAnchorEndPos;
|
||||
Sci::Position wordSelectInitialCaretPos;
|
||||
Sci::Position targetStart;
|
||||
Sci::Position targetEnd;
|
||||
int searchFlags;
|
||||
Sci::Line topLine;
|
||||
Sci::Position posTopLine;
|
||||
Sci::Position lengthForEncode;
|
||||
|
||||
int needUpdateUI;
|
||||
|
||||
enum { notPainting, painting, paintAbandoned } paintState;
|
||||
bool paintAbandonedByStyling;
|
||||
PRectangle rcPaint;
|
||||
bool paintingAllText;
|
||||
bool willRedrawAll;
|
||||
WorkNeeded workNeeded;
|
||||
int idleStyling;
|
||||
bool needIdleStyling;
|
||||
|
||||
int modEventMask;
|
||||
bool commandEvents;
|
||||
|
||||
SelectionText drag;
|
||||
|
||||
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;
|
||||
|
||||
Sci::Position searchAnchor;
|
||||
|
||||
bool recordingMacro;
|
||||
|
||||
int foldAutomatic;
|
||||
|
||||
// Wrapping support
|
||||
WrapPending wrapPending;
|
||||
ActionDuration durationWrapOneLine;
|
||||
|
||||
bool convertPastes;
|
||||
|
||||
Editor();
|
||||
// Deleted so Editor objects can not be copied.
|
||||
Editor(const Editor &) = delete;
|
||||
Editor(Editor &&) = delete;
|
||||
Editor &operator=(const Editor &) = delete;
|
||||
Editor &operator=(Editor &&) = delete;
|
||||
~Editor() override;
|
||||
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.
|
||||
Point GetVisibleOriginInMain() const override;
|
||||
PointDocument DocumentPointFromView(Point ptView) const; // Convert a point from view space to document
|
||||
Sci::Line TopLineOfMain() const override; // Return the line at Main's y coordinate 0
|
||||
virtual PRectangle GetClientRectangle() const;
|
||||
virtual PRectangle GetClientDrawingRectangle();
|
||||
PRectangle GetTextRectangle() const;
|
||||
|
||||
Sci::Line LinesOnScreen() const override;
|
||||
Sci::Line LinesToScroll() const;
|
||||
Sci::Line MaxScrollPos() const;
|
||||
SelectionPosition ClampPositionIntoDocument(SelectionPosition sp) const;
|
||||
Point LocationFromPosition(SelectionPosition pos, PointEnd pe=peDefault);
|
||||
Point LocationFromPosition(Sci::Position pos, PointEnd pe=peDefault);
|
||||
int XFromPosition(SelectionPosition sp);
|
||||
SelectionPosition SPositionFromLocation(Point pt, bool canReturnInvalid=false, bool charPosition=false, bool virtualSpace=true);
|
||||
Sci::Position PositionFromLocation(Point pt, bool canReturnInvalid = false, bool charPosition = false);
|
||||
SelectionPosition SPositionFromLineX(Sci::Line lineDoc, int x);
|
||||
Sci::Position PositionFromLineX(Sci::Line lineDoc, int x);
|
||||
Sci::Line LineFromLocation(Point pt) const;
|
||||
void SetTopLine(Sci::Line topLineNew);
|
||||
|
||||
virtual bool AbandonPaint();
|
||||
virtual void RedrawRect(PRectangle rc);
|
||||
virtual void DiscardOverdraw();
|
||||
virtual void Redraw();
|
||||
void RedrawSelMargin(Sci::Line line=-1, bool allAfter=false);
|
||||
PRectangle RectangleFromRange(Range r, int overlap);
|
||||
void InvalidateRange(Sci::Position start, Sci::Position end);
|
||||
|
||||
bool UserVirtualSpace() const {
|
||||
return ((virtualSpaceOptions & SCVS_USERACCESSIBLE) != 0);
|
||||
}
|
||||
Sci::Position CurrentPosition() const;
|
||||
bool SelectionEmpty() const;
|
||||
SelectionPosition SelectionStart();
|
||||
SelectionPosition SelectionEnd();
|
||||
void SetRectangularRange();
|
||||
void ThinRectangularRange();
|
||||
void InvalidateSelection(SelectionRange newMain, bool invalidateWholeSelection=false);
|
||||
void InvalidateWholeSelection();
|
||||
SelectionRange LineSelectionRange(SelectionPosition currentPos_, SelectionPosition anchor_) const;
|
||||
void SetSelection(SelectionPosition currentPos_, SelectionPosition anchor_);
|
||||
void SetSelection(Sci::Position currentPos_, Sci::Position anchor_);
|
||||
void SetSelection(SelectionPosition currentPos_);
|
||||
void SetSelection(int currentPos_);
|
||||
void SetEmptySelection(SelectionPosition currentPos_);
|
||||
void SetEmptySelection(Sci::Position currentPos_);
|
||||
enum AddNumber { addOne, addEach };
|
||||
void MultipleSelectAdd(AddNumber addNumber);
|
||||
bool RangeContainsProtected(Sci::Position start, Sci::Position end) const;
|
||||
bool SelectionContainsProtected();
|
||||
Sci::Position MovePositionOutsideChar(Sci::Position pos, Sci::Position moveDir, bool checkLineEnd=true) const;
|
||||
SelectionPosition MovePositionOutsideChar(SelectionPosition pos, Sci::Position moveDir, bool checkLineEnd=true) const;
|
||||
void MovedCaret(SelectionPosition newPos, SelectionPosition previousPos, bool ensureVisible);
|
||||
void MovePositionTo(SelectionPosition newPos, Selection::selTypes selt=Selection::noSel, bool ensureVisible=true);
|
||||
void MovePositionTo(Sci::Position newPos, Selection::selTypes selt=Selection::noSel, bool ensureVisible=true);
|
||||
SelectionPosition MovePositionSoVisible(SelectionPosition pos, int moveDir);
|
||||
SelectionPosition MovePositionSoVisible(Sci::Position pos, int moveDir);
|
||||
Point PointMainCaret();
|
||||
void SetLastXChosen();
|
||||
|
||||
void ScrollTo(Sci::Line line, bool moveThumb=true);
|
||||
virtual void ScrollText(Sci::Line linesToMove);
|
||||
void HorizontalScrollTo(int xPos);
|
||||
void VerticalCentreCaret();
|
||||
void MoveSelectedLines(int lineDelta);
|
||||
void MoveSelectedLinesUp();
|
||||
void MoveSelectedLinesDown();
|
||||
void MoveCaretInsideView(bool ensureVisible=true);
|
||||
Sci::Line DisplayFromPosition(Sci::Position pos);
|
||||
|
||||
struct XYScrollPosition {
|
||||
int xOffset;
|
||||
Sci::Line topLine;
|
||||
XYScrollPosition(int xOffset_, Sci::Line 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 NotifyCaretMove();
|
||||
virtual void UpdateSystemCaret();
|
||||
|
||||
bool Wrapping() const;
|
||||
void NeedWrapping(Sci::Line docLineStart=0, Sci::Line docLineEnd=WrapPending::lineLarge);
|
||||
bool WrapOneLine(Surface *surface, Sci::Line lineToWrap);
|
||||
enum class WrapScope {wsAll, wsVisible, wsIdle};
|
||||
bool WrapLines(WrapScope ws);
|
||||
void LinesJoin();
|
||||
void LinesSplit(int pixelWidth);
|
||||
|
||||
void PaintSelMargin(Surface *surfaceWindow, const PRectangle &rc);
|
||||
void RefreshPixMaps(Surface *surfaceWindow);
|
||||
void Paint(Surface *surfaceWindow, PRectangle rcArea);
|
||||
Sci::Position FormatRange(bool draw, const Sci_RangeToFormat *pfr);
|
||||
int TextWidth(int style, const char *text);
|
||||
|
||||
virtual void SetVerticalScrollPos() = 0;
|
||||
virtual void SetHorizontalScrollPos() = 0;
|
||||
virtual bool ModifyScrollBars(Sci::Line nMax, Sci::Line nPage) = 0;
|
||||
virtual void ReconfigureScrollBars();
|
||||
void SetScrollBars();
|
||||
void ChangeSize();
|
||||
|
||||
void FilterSelections();
|
||||
Sci::Position RealizeVirtualSpace(Sci::Position position, Sci::Position virtualSpace);
|
||||
SelectionPosition RealizeVirtualSpace(const SelectionPosition &position);
|
||||
void AddChar(char ch);
|
||||
virtual void AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS=false);
|
||||
void ClearBeforeTentativeStart();
|
||||
void InsertPaste(const char *text, Sci::Position len);
|
||||
enum PasteShape { pasteStream=0, pasteRectangular = 1, pasteLine = 2 };
|
||||
void InsertPasteShape(const char *text, Sci::Position len, PasteShape shape);
|
||||
void ClearSelection(bool retainMultipleSelections = false);
|
||||
void ClearAll();
|
||||
void ClearDocumentStyle();
|
||||
virtual void Cut();
|
||||
void PasteRectangular(SelectionPosition pos, const char *ptr, Sci::Position len);
|
||||
virtual void Copy() = 0;
|
||||
virtual void CopyAllowLine();
|
||||
virtual bool CanPaste();
|
||||
virtual void Paste() = 0;
|
||||
void Clear();
|
||||
virtual void SelectAll();
|
||||
virtual void Undo();
|
||||
virtual void Redo();
|
||||
void DelCharBack(bool allowLineStartDeletion);
|
||||
virtual void ClaimSelection() = 0;
|
||||
|
||||
static int ModifierFlags(bool shift, bool ctrl, bool alt, bool meta=false, bool super=false) noexcept;
|
||||
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(Sci::Position endStyleNeeded);
|
||||
void NotifyChar(int ch);
|
||||
void NotifySavePoint(bool isSavePoint);
|
||||
void NotifyModifyAttempt();
|
||||
virtual void NotifyDoubleClick(Point pt, int modifiers);
|
||||
void NotifyHotSpotClicked(Sci::Position position, int modifiers);
|
||||
void NotifyHotSpotDoubleClicked(Sci::Position position, int modifiers);
|
||||
void NotifyHotSpotReleaseClick(Sci::Position position, int modifiers);
|
||||
bool NotifyUpdateUI();
|
||||
void NotifyPainted();
|
||||
void NotifyIndicatorClick(bool click, Sci::Position position, int modifiers);
|
||||
bool NotifyMarginClick(Point pt, int modifiers);
|
||||
bool NotifyMarginRightClick(Point pt, int modifiers);
|
||||
void NotifyNeedShown(Sci::Position pos, Sci::Position len);
|
||||
void NotifyDwelling(Point pt, bool state);
|
||||
void NotifyZoom();
|
||||
|
||||
void NotifyModifyAttempt(Document *document, void *userData) override;
|
||||
void NotifySavePoint(Document *document, void *userData, bool atSavePoint) override;
|
||||
void CheckModificationForWrap(DocModification mh);
|
||||
void NotifyModified(Document *document, DocModification mh, void *userData) override;
|
||||
void NotifyDeleted(Document *document, void *userData) override;
|
||||
void NotifyStyleNeeded(Document *doc, void *userData, Sci::Position endStyleNeeded) override;
|
||||
void NotifyLexerChanged(Document *doc, void *userData) override;
|
||||
void NotifyErrorOccurred(Document *doc, void *userData, int status) override;
|
||||
void NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
|
||||
|
||||
void ContainerNeedsUpdate(int flags);
|
||||
void PageMove(int direction, Selection::selTypes selt=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 LineReverse();
|
||||
void Duplicate(bool forLine);
|
||||
virtual void CancelModes();
|
||||
void NewLine();
|
||||
SelectionPosition PositionUpOrDown(SelectionPosition spStart, int direction, int lastX);
|
||||
void CursorUpOrDown(int direction, Selection::selTypes selt);
|
||||
void ParaUpOrDown(int direction, Selection::selTypes selt);
|
||||
Range RangeDisplayLine(Sci::Line lineVisible);
|
||||
Sci::Position StartEndDisplayLine(Sci::Position pos, bool start);
|
||||
Sci::Position VCHomeDisplayPosition(Sci::Position position);
|
||||
Sci::Position VCHomeWrapPosition(Sci::Position position);
|
||||
Sci::Position LineEndWrapPosition(Sci::Position position);
|
||||
int HorizontalMove(unsigned int iMessage);
|
||||
int DelWordOrLine(unsigned int iMessage);
|
||||
virtual int KeyCommand(unsigned int iMessage);
|
||||
virtual int KeyDefault(int /* key */, int /*modifiers*/);
|
||||
int KeyDownWithModifiers(int key, int modifiers, bool *consumed);
|
||||
|
||||
void Indent(bool forwards);
|
||||
|
||||
virtual CaseFolder *CaseFolderForEncoding();
|
||||
Sci::Position FindText(uptr_t wParam, sptr_t lParam);
|
||||
void SearchAnchor();
|
||||
Sci::Position SearchText(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
|
||||
Sci::Position SearchInTarget(const char *text, Sci::Position length);
|
||||
void GoToLine(Sci::Line lineNo);
|
||||
|
||||
virtual void CopyToClipboard(const SelectionText &selectedText) = 0;
|
||||
std::string RangeText(Sci::Position start, Sci::Position end) const;
|
||||
void CopySelectionRange(SelectionText *ss, bool allowLineCopy=false);
|
||||
void CopyRangeToClipboard(Sci::Position start, Sci::Position end);
|
||||
void CopyText(size_t 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(Sci::Position pos);
|
||||
bool PointInSelection(Point pt);
|
||||
bool PointInSelMargin(Point pt) const;
|
||||
Window::Cursor GetMarginCursor(Point pt) const;
|
||||
void TrimAndSetSelection(Sci::Position currentPos_, Sci::Position anchor_);
|
||||
void LineSelection(Sci::Position lineCurrentPos_, Sci::Position lineAnchorPos_, bool wholeLine);
|
||||
void WordSelection(Sci::Position pos);
|
||||
void DwellEnd(bool mouseMoved);
|
||||
void MouseLeave();
|
||||
virtual void ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifiers);
|
||||
virtual void RightButtonDownWithModifiers(Point pt, unsigned int curTime, int modifiers);
|
||||
void ButtonMoveWithModifiers(Point pt, unsigned int curTime, int modifiers);
|
||||
void ButtonUpWithModifiers(Point pt, unsigned int curTime, int modifiers);
|
||||
|
||||
bool Idle();
|
||||
enum TickReason { tickCaret, tickScroll, tickWiden, tickDwell, tickPlatform };
|
||||
virtual void TickFor(TickReason reason);
|
||||
virtual bool FineTickerRunning(TickReason reason);
|
||||
virtual void FineTickerStart(TickReason reason, int millis, int tolerance);
|
||||
virtual void FineTickerCancel(TickReason reason);
|
||||
virtual bool SetIdle(bool) { return false; }
|
||||
virtual void SetMouseCapture(bool on) = 0;
|
||||
virtual bool HaveMouseCapture() = 0;
|
||||
void SetFocusState(bool focusState);
|
||||
|
||||
Sci::Position PositionAfterArea(PRectangle rcArea) const;
|
||||
void StyleToPositionInView(Sci::Position pos);
|
||||
Sci::Position PositionAfterMaxStyling(Sci::Position posMax, bool scrolling) const;
|
||||
void StartIdleStyling(bool truncatedLastStyling);
|
||||
void StyleAreaBounded(PRectangle rcArea, bool scrolling);
|
||||
void IdleStyling();
|
||||
virtual void IdleWork();
|
||||
virtual void QueueIdleWork(WorkNeeded::workItems items, Sci::Position upTo=0);
|
||||
|
||||
virtual bool PaintContains(PRectangle rc);
|
||||
bool PaintContainsMargin();
|
||||
void CheckForChangeOutsidePaint(Range r);
|
||||
void SetBraceHighlight(Sci::Position pos0, Sci::Position pos1, int matchStyle);
|
||||
|
||||
void SetAnnotationHeights(Sci::Line start, Sci::Line end);
|
||||
virtual void SetDocPointer(Document *document);
|
||||
|
||||
void SetAnnotationVisible(int visible);
|
||||
|
||||
Sci::Line ExpandLine(Sci::Line line);
|
||||
void SetFoldExpanded(Sci::Line lineDoc, bool expanded);
|
||||
void FoldLine(Sci::Line line, int action);
|
||||
void FoldExpand(Sci::Line line, int action, int level);
|
||||
Sci::Line ContractedFoldNext(Sci::Line lineStart) const;
|
||||
void EnsureLineVisible(Sci::Line lineDoc, bool enforcePolicy);
|
||||
void FoldChanged(Sci::Line line, int levelNow, int levelPrev);
|
||||
void NeedShown(Sci::Position pos, Sci::Position len);
|
||||
void FoldAll(int action);
|
||||
|
||||
Sci::Position GetTag(char *tagValue, int tagNumber);
|
||||
Sci::Position ReplaceTarget(bool replacePatterns, const char *text, Sci::Position length=-1);
|
||||
|
||||
bool PositionIsHotspot(Sci::Position position) const;
|
||||
bool PointIsHotspot(Point pt);
|
||||
void SetHotSpotRange(const Point *pt);
|
||||
Range GetHotSpotRange() const override;
|
||||
void SetHoverIndicatorPosition(Sci::Position position);
|
||||
void SetHoverIndicatorPoint(Point pt);
|
||||
|
||||
int CodePage() const;
|
||||
virtual bool ValidCodePage(int /* codePage */) const { return true; }
|
||||
Sci::Line WrapCount(Sci::Line line);
|
||||
void AddStyledText(const char *buffer, Sci::Position appendLength);
|
||||
|
||||
virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) = 0;
|
||||
bool ValidMargin(uptr_t wParam) const;
|
||||
void StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
|
||||
sptr_t StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
|
||||
void SetSelectionNMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
|
||||
|
||||
static const char *StringFromEOLMode(int eolMode);
|
||||
|
||||
// Coercion functions for transforming WndProc parameters into pointers
|
||||
static void *PtrFromSPtr(sptr_t lParam) {
|
||||
return reinterpret_cast<void *>(lParam);
|
||||
}
|
||||
static const char *ConstCharPtrFromSPtr(sptr_t lParam) {
|
||||
return static_cast<const char *>(PtrFromSPtr(lParam));
|
||||
}
|
||||
static const unsigned char *ConstUCharPtrFromSPtr(sptr_t lParam) {
|
||||
return static_cast<const unsigned char *>(PtrFromSPtr(lParam));
|
||||
}
|
||||
static char *CharPtrFromSPtr(sptr_t lParam) {
|
||||
return static_cast<char *>(PtrFromSPtr(lParam));
|
||||
}
|
||||
static unsigned char *UCharPtrFromSPtr(sptr_t lParam) {
|
||||
return static_cast<unsigned char *>(PtrFromSPtr(lParam));
|
||||
}
|
||||
static void *PtrFromUPtr(uptr_t wParam) {
|
||||
return reinterpret_cast<void *>(wParam);
|
||||
}
|
||||
static const char *ConstCharPtrFromUPtr(uptr_t wParam) {
|
||||
return static_cast<const char *>(PtrFromUPtr(wParam));
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
* A smart pointer class to ensure Surfaces are set up and deleted correctly.
|
||||
*/
|
||||
class AutoSurface {
|
||||
private:
|
||||
std::unique_ptr<Surface> surf;
|
||||
public:
|
||||
AutoSurface(Editor *ed, int technology = -1) {
|
||||
if (ed->wMain.GetID()) {
|
||||
surf.reset(Surface::Allocate(technology != -1 ? technology : ed->technology));
|
||||
surf->Init(ed->wMain.GetID());
|
||||
surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage());
|
||||
surf->SetDBCSMode(ed->CodePage());
|
||||
}
|
||||
}
|
||||
AutoSurface(SurfaceID sid, Editor *ed, int technology = -1) {
|
||||
if (ed->wMain.GetID()) {
|
||||
surf.reset(Surface::Allocate(technology != -1 ? technology : ed->technology));
|
||||
surf->Init(sid, ed->wMain.GetID());
|
||||
surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage());
|
||||
surf->SetDBCSMode(ed->CodePage());
|
||||
}
|
||||
}
|
||||
// Deleted so AutoSurface objects can not be copied.
|
||||
AutoSurface(const AutoSurface &) = delete;
|
||||
AutoSurface(AutoSurface &&) = delete;
|
||||
void operator=(const AutoSurface &) = delete;
|
||||
void operator=(AutoSurface &&) = delete;
|
||||
~AutoSurface() {
|
||||
}
|
||||
Surface *operator->() const noexcept {
|
||||
return surf.get();
|
||||
}
|
||||
operator Surface *() const noexcept {
|
||||
return surf.get();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
35
third_party/qscintilla/scintilla/src/ElapsedPeriod.h
vendored
Normal file
35
third_party/qscintilla/scintilla/src/ElapsedPeriod.h
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file ElapsedPeriod.h
|
||||
** Encapsulate C++ <chrono> to simplify use.
|
||||
**/
|
||||
// Copyright 2018 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef ELAPSEDPERIOD_H
|
||||
#define ELAPSEDPERIOD_H
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
// Simplified access to high precision timing.
|
||||
class ElapsedPeriod {
|
||||
std::chrono::high_resolution_clock::time_point tp;
|
||||
public:
|
||||
/// Capture the moment
|
||||
ElapsedPeriod() : tp(std::chrono::high_resolution_clock::now()) {
|
||||
}
|
||||
/// Return duration as floating point seconds
|
||||
double Duration(bool reset=false) {
|
||||
const std::chrono::high_resolution_clock::time_point tpNow =
|
||||
std::chrono::high_resolution_clock::now();
|
||||
const std::chrono::duration<double> stylingDuration =
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(tpNow - tp);
|
||||
if (reset) {
|
||||
tp = tpNow;
|
||||
}
|
||||
return stylingDuration.count();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
135
third_party/qscintilla/scintilla/src/ExternalLexer.cpp
vendored
Normal file
135
third_party/qscintilla/scintilla/src/ExternalLexer.cpp
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file ExternalLexer.cxx
|
||||
** Support external lexers in DLLs or shared libraries.
|
||||
**/
|
||||
// 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 <cstdlib>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "ILexer.h"
|
||||
#include "Scintilla.h"
|
||||
#include "SciLexer.h"
|
||||
|
||||
#include "LexerModule.h"
|
||||
#include "Catalogue.h"
|
||||
#include "ExternalLexer.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
std::unique_ptr<LexerManager> LexerManager::theInstance;
|
||||
|
||||
//------------------------------------------
|
||||
//
|
||||
// ExternalLexerModule
|
||||
//
|
||||
//------------------------------------------
|
||||
|
||||
void ExternalLexerModule::SetExternal(GetLexerFactoryFunction fFactory, int index) {
|
||||
fneFactory = fFactory;
|
||||
fnFactory = fFactory(index);
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
//
|
||||
// LexerLibrary
|
||||
//
|
||||
//------------------------------------------
|
||||
|
||||
LexerLibrary::LexerLibrary(const char *moduleName_) {
|
||||
// Load the DLL
|
||||
lib.reset(DynamicLibrary::Load(moduleName_));
|
||||
if (lib->IsValid()) {
|
||||
moduleName = 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) {
|
||||
// Find functions in the DLL
|
||||
GetLexerNameFn GetLexerName = (GetLexerNameFn)(sptr_t)lib->FindFunction("GetLexerName");
|
||||
GetLexerFactoryFunction fnFactory = (GetLexerFactoryFunction)(sptr_t)lib->FindFunction("GetLexerFactory");
|
||||
|
||||
const 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));
|
||||
ExternalLexerModule *lex = new ExternalLexerModule(SCLEX_AUTOMATIC, nullptr, lexname, nullptr);
|
||||
// This is storing a second reference to lex in the Catalogue as well as in modules.
|
||||
// TODO: Should use std::shared_ptr or similar to ensure allocation safety.
|
||||
Catalogue::AddLexerModule(lex);
|
||||
|
||||
// Remember ExternalLexerModule so we don't leak it
|
||||
modules.push_back(std::unique_ptr<ExternalLexerModule>(lex));
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LexerLibrary::~LexerLibrary() {
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
//
|
||||
// LexerManager
|
||||
//
|
||||
//------------------------------------------
|
||||
|
||||
/// Return the single LexerManager instance...
|
||||
LexerManager *LexerManager::GetInstance() {
|
||||
if (!theInstance)
|
||||
theInstance.reset(new LexerManager);
|
||||
return theInstance.get();
|
||||
}
|
||||
|
||||
/// Delete any LexerManager instance...
|
||||
void LexerManager::DeleteInstance() {
|
||||
theInstance.reset();
|
||||
}
|
||||
|
||||
/// protected constructor - this is a singleton...
|
||||
LexerManager::LexerManager() {
|
||||
}
|
||||
|
||||
LexerManager::~LexerManager() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void LexerManager::Load(const char *path) {
|
||||
for (const std::unique_ptr<LexerLibrary> &ll : libraries) {
|
||||
if (ll->moduleName == path)
|
||||
return;
|
||||
}
|
||||
LexerLibrary *lib = new LexerLibrary(path);
|
||||
libraries.push_back(std::unique_ptr<LexerLibrary>(lib));
|
||||
}
|
||||
|
||||
void LexerManager::Clear() {
|
||||
libraries.clear();
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
//
|
||||
// LMMinder -- trigger to clean up at exit.
|
||||
//
|
||||
//------------------------------------------
|
||||
|
||||
LMMinder::~LMMinder() {
|
||||
LexerManager::DeleteInstance();
|
||||
}
|
||||
|
||||
LMMinder minder;
|
||||
80
third_party/qscintilla/scintilla/src/ExternalLexer.h
vendored
Normal file
80
third_party/qscintilla/scintilla/src/ExternalLexer.h
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file ExternalLexer.h
|
||||
** Support external lexers in DLLs or shared libraries.
|
||||
**/
|
||||
// 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
|
||||
#elif PLAT_QT
|
||||
#include <qglobal.h>
|
||||
#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64)
|
||||
#define EXT_LEXER_DECL __stdcall
|
||||
#else
|
||||
#define EXT_LEXER_DECL
|
||||
#endif
|
||||
#else
|
||||
#define EXT_LEXER_DECL
|
||||
#endif
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
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_=nullptr, LexerFunction fnFolder_=nullptr) :
|
||||
LexerModule(language_, fnLexer_, nullptr, fnFolder_),
|
||||
fneFactory(nullptr), name(languageName_){
|
||||
languageName = name.c_str();
|
||||
}
|
||||
virtual void SetExternal(GetLexerFactoryFunction fFactory, int index);
|
||||
};
|
||||
|
||||
/// LexerLibrary exists for every External Lexer DLL, contains ExternalLexerModules.
|
||||
class LexerLibrary {
|
||||
std::unique_ptr<DynamicLibrary> lib;
|
||||
std::vector<std::unique_ptr<ExternalLexerModule>> modules;
|
||||
public:
|
||||
explicit LexerLibrary(const char *moduleName_);
|
||||
~LexerLibrary();
|
||||
|
||||
std::string moduleName;
|
||||
};
|
||||
|
||||
/// 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 std::unique_ptr<LexerManager> theInstance;
|
||||
std::vector<std::unique_ptr<LexerLibrary>> libraries;
|
||||
};
|
||||
|
||||
class LMMinder {
|
||||
public:
|
||||
~LMMinder();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
27
third_party/qscintilla/scintilla/src/FontQuality.h
vendored
Normal file
27
third_party/qscintilla/scintilla/src/FontQuality.h
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file FontQuality.h
|
||||
** Definitions to control font anti-aliasing.
|
||||
** Redefine constants from Scintilla.h to avoid including Scintilla.h in PlatWin.cxx.
|
||||
**/
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
// These definitions match Scintilla.h
|
||||
#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
|
||||
|
||||
// These definitions must match SC_TECHNOLOGY_* in Scintilla.h
|
||||
#define SCWIN_TECH_GDI 0
|
||||
#define SCWIN_TECH_DIRECTWRITE 1
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
223
third_party/qscintilla/scintilla/src/Indicator.cpp
vendored
Normal file
223
third_party/qscintilla/scintilla/src/Indicator.cpp
vendored
Normal file
@@ -0,0 +1,223 @@
|
||||
// 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 <cmath>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
#include "StringCopy.h"
|
||||
#include "IntegerRectangle.h"
|
||||
#include "Indicator.h"
|
||||
#include "XPM.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
static PRectangle PixelGridAlign(const PRectangle &rc) {
|
||||
// Move left and right side to nearest pixel to avoid blurry visuals
|
||||
return PRectangle(round(rc.left), floor(rc.top),
|
||||
round(rc.right), floor(rc.bottom));
|
||||
}
|
||||
|
||||
void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine, const PRectangle &rcCharacter, DrawState drawState, int value) const {
|
||||
StyleAndColour sacDraw = sacNormal;
|
||||
if (Flags() & SC_INDICFLAG_VALUEFORE) {
|
||||
sacDraw.fore = ColourDesired(value & SC_INDICVALUEMASK);
|
||||
}
|
||||
if (drawState == drawHover) {
|
||||
sacDraw = sacHover;
|
||||
}
|
||||
const IntegerRectangle irc(rc);
|
||||
surface->PenColour(sacDraw.fore);
|
||||
const int ymid = (irc.bottom + irc.top) / 2;
|
||||
if (sacDraw.style == INDIC_SQUIGGLE) {
|
||||
const IntegerRectangle ircSquiggle(PixelGridAlign(rc));
|
||||
int x = ircSquiggle.left;
|
||||
const int xLast = ircSquiggle.right;
|
||||
int y = 0;
|
||||
surface->MoveTo(x, irc.top + y);
|
||||
while (x < xLast) {
|
||||
if ((x + 2) > xLast) {
|
||||
y = 1;
|
||||
x = xLast;
|
||||
} else {
|
||||
x += 2;
|
||||
y = 2 - y;
|
||||
}
|
||||
surface->LineTo(x, irc.top + y);
|
||||
}
|
||||
} else if (sacDraw.style == INDIC_SQUIGGLEPIXMAP) {
|
||||
const PRectangle rcSquiggle = PixelGridAlign(rc);
|
||||
|
||||
const int width = std::min(4000, static_cast<int>(rcSquiggle.Width()));
|
||||
RGBAImage image(width, 3, 1.0, nullptr);
|
||||
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, sacDraw.fore, alphaSide);
|
||||
image.SetPixel(x, 1, sacDraw.fore, alphaFull);
|
||||
image.SetPixel(x, 2, sacDraw.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, sacDraw.fore, alphaFull);
|
||||
image.SetPixel(x, 1, sacDraw.fore, alphaSide2);
|
||||
}
|
||||
}
|
||||
surface->DrawRGBAImage(rcSquiggle, image.GetWidth(), image.GetHeight(), image.Pixels());
|
||||
} else if (sacDraw.style == INDIC_SQUIGGLELOW) {
|
||||
surface->MoveTo(irc.left, irc.top);
|
||||
int x = irc.left + 3;
|
||||
int y = 0;
|
||||
while (x < rc.right) {
|
||||
surface->LineTo(x - 1, irc.top + y);
|
||||
y = 1 - y;
|
||||
surface->LineTo(x, irc.top + y);
|
||||
x += 3;
|
||||
}
|
||||
surface->LineTo(irc.right, irc.top + y); // Finish the line
|
||||
} else if (sacDraw.style == INDIC_TT) {
|
||||
surface->MoveTo(irc.left, ymid);
|
||||
int x = irc.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(irc.right, ymid); // Finish the line
|
||||
if (x - 3 <= rc.right) {
|
||||
surface->MoveTo(x-3, ymid);
|
||||
surface->LineTo(x-3, ymid+2);
|
||||
}
|
||||
} else if (sacDraw.style == INDIC_DIAGONAL) {
|
||||
int x = irc.left;
|
||||
while (x < rc.right) {
|
||||
surface->MoveTo(x, irc.top + 2);
|
||||
int endX = x+3;
|
||||
int endY = irc.top - 1;
|
||||
if (endX > rc.right) {
|
||||
endY += endX - irc.right;
|
||||
endX = irc.right;
|
||||
}
|
||||
surface->LineTo(endX, endY);
|
||||
x += 4;
|
||||
}
|
||||
} else if (sacDraw.style == INDIC_STRIKE) {
|
||||
surface->MoveTo(irc.left, irc.top - 4);
|
||||
surface->LineTo(irc.right, irc.top - 4);
|
||||
} else if ((sacDraw.style == INDIC_HIDDEN) || (sacDraw.style == INDIC_TEXTFORE)) {
|
||||
// Draw nothing
|
||||
} else if (sacDraw.style == INDIC_BOX) {
|
||||
surface->MoveTo(irc.left, ymid + 1);
|
||||
surface->LineTo(irc.right, ymid + 1);
|
||||
const int lineTop = static_cast<int>(rcLine.top) + 1;
|
||||
surface->LineTo(irc.right, lineTop);
|
||||
surface->LineTo(irc.left, lineTop);
|
||||
surface->LineTo(irc.left, ymid + 1);
|
||||
} else if (sacDraw.style == INDIC_ROUNDBOX ||
|
||||
sacDraw.style == INDIC_STRAIGHTBOX ||
|
||||
sacDraw.style == INDIC_FULLBOX) {
|
||||
PRectangle rcBox = rcLine;
|
||||
if (sacDraw.style != INDIC_FULLBOX)
|
||||
rcBox.top = rcLine.top + 1;
|
||||
rcBox.left = rc.left;
|
||||
rcBox.right = rc.right;
|
||||
surface->AlphaRectangle(rcBox, (sacDraw.style == INDIC_ROUNDBOX) ? 1 : 0,
|
||||
sacDraw.fore, fillAlpha, sacDraw.fore, outlineAlpha, 0);
|
||||
} else if (sacDraw.style == INDIC_GRADIENT ||
|
||||
sacDraw.style == INDIC_GRADIENTCENTRE) {
|
||||
PRectangle rcBox = rc;
|
||||
rcBox.top = rcLine.top + 1;
|
||||
rcBox.bottom = rcLine.bottom;
|
||||
const Surface::GradientOptions options = Surface::GradientOptions::topToBottom;
|
||||
const ColourAlpha start(sacNormal.fore, fillAlpha);
|
||||
const ColourAlpha end(sacNormal.fore, 0);
|
||||
std::vector<ColourStop> stops;
|
||||
switch (sacDraw.style) {
|
||||
case INDIC_GRADIENT:
|
||||
stops.push_back(ColourStop(0.0, start));
|
||||
stops.push_back(ColourStop(1.0, end));
|
||||
break;
|
||||
case INDIC_GRADIENTCENTRE:
|
||||
stops.push_back(ColourStop(0.0, end));
|
||||
stops.push_back(ColourStop(0.5, start));
|
||||
stops.push_back(ColourStop(1.0, end));
|
||||
break;
|
||||
}
|
||||
surface->GradientRectangle(rcBox, stops, options);
|
||||
} else if (sacDraw.style == INDIC_DOTBOX) {
|
||||
PRectangle rcBox = PixelGridAlign(rc);
|
||||
rcBox.top = rcLine.top + 1;
|
||||
rcBox.bottom = rcLine.bottom;
|
||||
IntegerRectangle ircBox(rcBox);
|
||||
// Cap width at 4000 to avoid large allocations when mistakes made
|
||||
const int width = std::min(ircBox.Width(), 4000);
|
||||
RGBAImage image(width, ircBox.Height(), 1.0, nullptr);
|
||||
// Draw horizontal lines top and bottom
|
||||
for (int x=0; x<width; x++) {
|
||||
for (int y = 0; y<ircBox.Height(); y += ircBox.Height() - 1) {
|
||||
image.SetPixel(x, y, sacDraw.fore, ((x + y) % 2) ? outlineAlpha : fillAlpha);
|
||||
}
|
||||
}
|
||||
// Draw vertical lines left and right
|
||||
for (int y = 1; y<ircBox.Height(); y++) {
|
||||
for (int x=0; x<width; x += width-1) {
|
||||
image.SetPixel(x, y, sacDraw.fore, ((x + y) % 2) ? outlineAlpha : fillAlpha);
|
||||
}
|
||||
}
|
||||
surface->DrawRGBAImage(rcBox, image.GetWidth(), image.GetHeight(), image.Pixels());
|
||||
} else if (sacDraw.style == INDIC_DASH) {
|
||||
int x = irc.left;
|
||||
while (x < rc.right) {
|
||||
surface->MoveTo(x, ymid);
|
||||
surface->LineTo(std::min(x + 4, irc.right), ymid);
|
||||
x += 7;
|
||||
}
|
||||
} else if (sacDraw.style == INDIC_DOTS) {
|
||||
int x = irc.left;
|
||||
while (x < irc.right) {
|
||||
const PRectangle rcDot = PRectangle::FromInts(x, ymid, x + 1, ymid + 1);
|
||||
surface->FillRectangle(rcDot, sacDraw.fore);
|
||||
x += 2;
|
||||
}
|
||||
} else if (sacDraw.style == INDIC_COMPOSITIONTHICK) {
|
||||
const PRectangle rcComposition(rc.left+1, rcLine.bottom-2, rc.right-1, rcLine.bottom);
|
||||
surface->FillRectangle(rcComposition, sacDraw.fore);
|
||||
} else if (sacDraw.style == INDIC_COMPOSITIONTHIN) {
|
||||
const PRectangle rcComposition(rc.left+1, rcLine.bottom-2, rc.right-1, rcLine.bottom-1);
|
||||
surface->FillRectangle(rcComposition, sacDraw.fore);
|
||||
} else if (sacDraw.style == INDIC_POINT || sacDraw.style == INDIC_POINTCHARACTER) {
|
||||
if (rcCharacter.Width() >= 0.1) {
|
||||
const XYPOSITION pixelHeight = floor(rc.Height() - 1.0f); // 1 pixel onto next line if multiphase
|
||||
const XYPOSITION x = (sacDraw.style == INDIC_POINT) ? (rcCharacter.left) : ((rcCharacter.right + rcCharacter.left) / 2);
|
||||
const XYPOSITION ix = round(x);
|
||||
const XYPOSITION iy = floor(rc.top + 1.0f);
|
||||
Point pts[] = {
|
||||
Point(ix - pixelHeight, iy + pixelHeight), // Left
|
||||
Point(ix + pixelHeight, iy + pixelHeight), // Right
|
||||
Point(ix, iy) // Top
|
||||
};
|
||||
surface->Polygon(pts, ELEMENTS(pts), sacDraw.fore, sacDraw.fore);
|
||||
}
|
||||
} else { // Either INDIC_PLAIN or unknown
|
||||
surface->MoveTo(irc.left, ymid);
|
||||
surface->LineTo(irc.right, ymid);
|
||||
}
|
||||
}
|
||||
|
||||
void Indicator::SetFlags(int attributes_) {
|
||||
attributes = attributes_;
|
||||
}
|
||||
56
third_party/qscintilla/scintilla/src/Indicator.h
vendored
Normal file
56
third_party/qscintilla/scintilla/src/Indicator.h
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
struct StyleAndColour {
|
||||
int style;
|
||||
ColourDesired fore;
|
||||
StyleAndColour() : style(INDIC_PLAIN), fore(0, 0, 0) {
|
||||
}
|
||||
StyleAndColour(int style_, ColourDesired fore_ = ColourDesired(0, 0, 0)) : style(style_), fore(fore_) {
|
||||
}
|
||||
bool operator==(const StyleAndColour &other) const {
|
||||
return (style == other.style) && (fore == other.fore);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class Indicator {
|
||||
public:
|
||||
enum DrawState { drawNormal, drawHover };
|
||||
StyleAndColour sacNormal;
|
||||
StyleAndColour sacHover;
|
||||
bool under;
|
||||
int fillAlpha;
|
||||
int outlineAlpha;
|
||||
int attributes;
|
||||
Indicator() : under(false), fillAlpha(30), outlineAlpha(50), attributes(0) {
|
||||
}
|
||||
Indicator(int style_, ColourDesired fore_=ColourDesired(0,0,0), bool under_=false, int fillAlpha_=30, int outlineAlpha_=50) :
|
||||
sacNormal(style_, fore_), sacHover(style_, fore_), under(under_), fillAlpha(fillAlpha_), outlineAlpha(outlineAlpha_), attributes(0) {
|
||||
}
|
||||
void Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine, const PRectangle &rcCharacter, DrawState drawState, int value) const;
|
||||
bool IsDynamic() const {
|
||||
return !(sacNormal == sacHover);
|
||||
}
|
||||
bool OverridesTextFore() const {
|
||||
return sacNormal.style == INDIC_TEXTFORE || sacHover.style == INDIC_TEXTFORE;
|
||||
}
|
||||
int Flags() const {
|
||||
return attributes;
|
||||
}
|
||||
void SetFlags(int attributes_);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
29
third_party/qscintilla/scintilla/src/IntegerRectangle.h
vendored
Normal file
29
third_party/qscintilla/scintilla/src/IntegerRectangle.h
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file IntegerRectangle.h
|
||||
** A rectangle with integer coordinates.
|
||||
**/
|
||||
// Copyright 2018 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef INTEGERRECTANGLE_H
|
||||
#define INTEGERRECTANGLE_H
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
struct IntegerRectangle {
|
||||
int left;
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
|
||||
explicit IntegerRectangle(PRectangle rc) noexcept :
|
||||
left(static_cast<int>(rc.left)), top(static_cast<int>(rc.top)),
|
||||
right(static_cast<int>(rc.right)), bottom(static_cast<int>(rc.bottom)) {
|
||||
}
|
||||
int Width() const noexcept { return right - left; }
|
||||
int Height() const noexcept { return bottom - top; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
164
third_party/qscintilla/scintilla/src/KeyMap.cpp
vendored
Normal file
164
third_party/qscintilla/scintilla/src/KeyMap.cpp
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
// 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 <cstdlib>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
|
||||
#include "KeyMap.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const std::map<KeyModifiers, unsigned int> &KeyMap::GetKeyMap() const {
|
||||
return kmap;
|
||||
}
|
||||
|
||||
#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},
|
||||
};
|
||||
|
||||
64
third_party/qscintilla/scintilla/src/KeyMap.h
vendored
Normal file
64
third_party/qscintilla/scintilla/src/KeyMap.h
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
#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_SUPER SCMOD_SUPER
|
||||
#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
|
||||
const std::map<KeyModifiers, unsigned int> &GetKeyMap() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
20
third_party/qscintilla/scintilla/src/License.txt
vendored
Normal file
20
third_party/qscintilla/scintilla/src/License.txt
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
License for Scintilla and SciTE
|
||||
|
||||
Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
|
||||
|
||||
All Rights Reserved
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation.
|
||||
|
||||
NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
|
||||
OR PERFORMANCE OF THIS SOFTWARE.
|
||||
436
third_party/qscintilla/scintilla/src/LineMarker.cpp
vendored
Normal file
436
third_party/qscintilla/scintilla/src/LineMarker.cpp
vendored
Normal file
@@ -0,0 +1,436 @@
|
||||
// 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 <cstring>
|
||||
#include <cmath>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
|
||||
#include "StringCopy.h"
|
||||
#include "IntegerRectangle.h"
|
||||
#include "XPM.h"
|
||||
#include "LineMarker.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
LineMarker::~LineMarker() {
|
||||
}
|
||||
|
||||
LineMarker::LineMarker() {
|
||||
markType = SC_MARK_CIRCLE;
|
||||
fore = ColourDesired(0, 0, 0);
|
||||
back = ColourDesired(0xff, 0xff, 0xff);
|
||||
backSelected = ColourDesired(0xff, 0x00, 0x00);
|
||||
alpha = SC_ALPHA_NOALPHA;
|
||||
customDraw = nullptr;
|
||||
}
|
||||
|
||||
LineMarker::LineMarker(const LineMarker &) {
|
||||
// Defined to avoid pxpm and image 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.reset();
|
||||
image.reset();
|
||||
customDraw = nullptr;
|
||||
}
|
||||
|
||||
LineMarker &LineMarker::operator=(const LineMarker &other) {
|
||||
// Defined to avoid pxpm and image 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;
|
||||
pxpm.reset();
|
||||
image.reset();
|
||||
customDraw = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void LineMarker::SetXPM(const char *textForm) {
|
||||
pxpm.reset(new XPM(textForm));
|
||||
markType = SC_MARK_PIXMAP;
|
||||
}
|
||||
|
||||
void LineMarker::SetXPM(const char *const *linesForm) {
|
||||
pxpm.reset(new XPM(linesForm));
|
||||
markType = SC_MARK_PIXMAP;
|
||||
}
|
||||
|
||||
void LineMarker::SetRGBAImage(Point sizeRGBAImage, float scale, const unsigned char *pixelsRGBAImage) {
|
||||
image.reset(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) {
|
||||
const PRectangle rc = PRectangle::FromInts(
|
||||
centreX - armSize,
|
||||
centreY - armSize,
|
||||
centreX + armSize + 1,
|
||||
centreY + armSize + 1);
|
||||
surface->RectangleDraw(rc, back, fore);
|
||||
}
|
||||
|
||||
static void DrawCircle(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore, ColourDesired back) {
|
||||
const PRectangle rcCircle = PRectangle::FromInts(
|
||||
centreX - armSize,
|
||||
centreY - armSize,
|
||||
centreX + armSize + 1,
|
||||
centreY + armSize + 1);
|
||||
surface->Ellipse(rcCircle, back, fore);
|
||||
}
|
||||
|
||||
static void DrawPlus(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore) {
|
||||
const PRectangle rcV = PRectangle::FromInts(centreX, centreY - armSize + 2, centreX + 1, centreY + armSize - 2 + 1);
|
||||
surface->FillRectangle(rcV, fore);
|
||||
const 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) {
|
||||
const 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) const {
|
||||
if (customDraw) {
|
||||
customDraw(surface, rcWhole, fontForCharacter, tFold, marginStyle, this);
|
||||
return;
|
||||
}
|
||||
|
||||
ColourDesired colourHead = back;
|
||||
ColourDesired colourBody = back;
|
||||
ColourDesired colourTail = back;
|
||||
|
||||
switch (tFold) {
|
||||
case LineMarker::head :
|
||||
case LineMarker::headWithTail :
|
||||
colourHead = backSelected;
|
||||
colourTail = backSelected;
|
||||
break;
|
||||
case LineMarker::body :
|
||||
colourHead = backSelected;
|
||||
colourBody = backSelected;
|
||||
break;
|
||||
case LineMarker::tail :
|
||||
colourBody = backSelected;
|
||||
colourTail = 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;
|
||||
}
|
||||
const IntegerRectangle ircWhole(rcWhole);
|
||||
// Restrict most shapes a bit
|
||||
const PRectangle rc(rcWhole.left, rcWhole.top + 1, rcWhole.right, rcWhole.bottom - 1);
|
||||
// Ensure does not go beyond edge
|
||||
const int minDim = std::min(ircWhole.Width(), ircWhole.Height()-2) - 1;
|
||||
int centreX = (ircWhole.right + ircWhole.left) / 2;
|
||||
const int centreY = (ircWhole.bottom + ircWhole.top) / 2;
|
||||
const int dimOn2 = minDim / 2;
|
||||
const int dimOn4 = minDim / 4;
|
||||
const int blobSize = dimOn2-1;
|
||||
const 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 = ircWhole.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) {
|
||||
const 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(colourBody);
|
||||
surface->MoveTo(centreX, ircWhole.top);
|
||||
surface->LineTo(centreX, ircWhole.bottom);
|
||||
|
||||
} else if (markType == SC_MARK_LCORNER) {
|
||||
surface->PenColour(colourTail);
|
||||
surface->MoveTo(centreX, ircWhole.top);
|
||||
surface->LineTo(centreX, centreY);
|
||||
surface->LineTo(ircWhole.right - 1, centreY);
|
||||
|
||||
} else if (markType == SC_MARK_TCORNER) {
|
||||
surface->PenColour(colourTail);
|
||||
surface->MoveTo(centreX, centreY);
|
||||
surface->LineTo(ircWhole.right - 1, centreY);
|
||||
|
||||
surface->PenColour(colourBody);
|
||||
surface->MoveTo(centreX, ircWhole.top);
|
||||
surface->LineTo(centreX, centreY + 1);
|
||||
|
||||
surface->PenColour(colourHead);
|
||||
surface->LineTo(centreX, ircWhole.bottom);
|
||||
|
||||
} else if (markType == SC_MARK_LCORNERCURVE) {
|
||||
surface->PenColour(colourTail);
|
||||
surface->MoveTo(centreX, ircWhole.top);
|
||||
surface->LineTo(centreX, centreY-3);
|
||||
surface->LineTo(centreX+3, centreY);
|
||||
surface->LineTo(ircWhole.right - 1, centreY);
|
||||
|
||||
} else if (markType == SC_MARK_TCORNERCURVE) {
|
||||
surface->PenColour(colourTail);
|
||||
surface->MoveTo(centreX, centreY-3);
|
||||
surface->LineTo(centreX+3, centreY);
|
||||
surface->LineTo(ircWhole.right - 1, centreY);
|
||||
|
||||
surface->PenColour(colourBody);
|
||||
surface->MoveTo(centreX, ircWhole.top);
|
||||
surface->LineTo(centreX, centreY-2);
|
||||
|
||||
surface->PenColour(colourHead);
|
||||
surface->LineTo(centreX, ircWhole.bottom);
|
||||
|
||||
} else if (markType == SC_MARK_BOXPLUS) {
|
||||
DrawBox(surface, centreX, centreY, blobSize, fore, colourHead);
|
||||
DrawPlus(surface, centreX, centreY, blobSize, colourTail);
|
||||
|
||||
} else if (markType == SC_MARK_BOXPLUSCONNECTED) {
|
||||
if (tFold == LineMarker::headWithTail)
|
||||
surface->PenColour(colourTail);
|
||||
else
|
||||
surface->PenColour(colourBody);
|
||||
surface->MoveTo(centreX, centreY + blobSize);
|
||||
surface->LineTo(centreX, ircWhole.bottom);
|
||||
|
||||
surface->PenColour(colourBody);
|
||||
surface->MoveTo(centreX, ircWhole.top);
|
||||
surface->LineTo(centreX, centreY - blobSize);
|
||||
|
||||
DrawBox(surface, centreX, centreY, blobSize, fore, colourHead);
|
||||
DrawPlus(surface, centreX, centreY, blobSize, colourTail);
|
||||
|
||||
if (tFold == LineMarker::body) {
|
||||
surface->PenColour(colourTail);
|
||||
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, colourHead);
|
||||
DrawMinus(surface, centreX, centreY, blobSize, colourTail);
|
||||
|
||||
surface->PenColour(colourHead);
|
||||
surface->MoveTo(centreX, centreY + blobSize);
|
||||
surface->LineTo(centreX, ircWhole.bottom);
|
||||
|
||||
} else if (markType == SC_MARK_BOXMINUSCONNECTED) {
|
||||
DrawBox(surface, centreX, centreY, blobSize, fore, colourHead);
|
||||
DrawMinus(surface, centreX, centreY, blobSize, colourTail);
|
||||
|
||||
surface->PenColour(colourHead);
|
||||
surface->MoveTo(centreX, centreY + blobSize);
|
||||
surface->LineTo(centreX, ircWhole.bottom);
|
||||
|
||||
surface->PenColour(colourBody);
|
||||
surface->MoveTo(centreX, ircWhole.top);
|
||||
surface->LineTo(centreX, centreY - blobSize);
|
||||
|
||||
if (tFold == LineMarker::body) {
|
||||
surface->PenColour(colourTail);
|
||||
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, colourHead);
|
||||
DrawPlus(surface, centreX, centreY, blobSize, colourTail);
|
||||
|
||||
} else if (markType == SC_MARK_CIRCLEPLUSCONNECTED) {
|
||||
if (tFold == LineMarker::headWithTail)
|
||||
surface->PenColour(colourTail);
|
||||
else
|
||||
surface->PenColour(colourBody);
|
||||
surface->MoveTo(centreX, centreY + blobSize);
|
||||
surface->LineTo(centreX, ircWhole.bottom);
|
||||
|
||||
surface->PenColour(colourBody);
|
||||
surface->MoveTo(centreX, ircWhole.top);
|
||||
surface->LineTo(centreX, centreY - blobSize);
|
||||
|
||||
DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead);
|
||||
DrawPlus(surface, centreX, centreY, blobSize, colourTail);
|
||||
|
||||
} else if (markType == SC_MARK_CIRCLEMINUS) {
|
||||
surface->PenColour(colourHead);
|
||||
surface->MoveTo(centreX, centreY + blobSize);
|
||||
surface->LineTo(centreX, ircWhole.bottom);
|
||||
|
||||
DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead);
|
||||
DrawMinus(surface, centreX, centreY, blobSize, colourTail);
|
||||
|
||||
} else if (markType == SC_MARK_CIRCLEMINUSCONNECTED) {
|
||||
surface->PenColour(colourHead);
|
||||
surface->MoveTo(centreX, centreY + blobSize);
|
||||
surface->LineTo(centreX, ircWhole.bottom);
|
||||
|
||||
surface->PenColour(colourBody);
|
||||
surface->MoveTo(centreX, ircWhole.top);
|
||||
surface->LineTo(centreX, centreY - blobSize);
|
||||
|
||||
DrawCircle(surface, centreX, centreY, blobSize, fore, colourHead);
|
||||
DrawMinus(surface, centreX, centreY, blobSize, colourTail);
|
||||
|
||||
} else if (markType >= SC_MARK_CHARACTER) {
|
||||
char character[1];
|
||||
character[0] = static_cast<char>(markType - SC_MARK_CHARACTER);
|
||||
const XYPOSITION width = surface->WidthText(fontForCharacter, character, 1);
|
||||
PRectangle rcText = rc;
|
||||
rcText.left += (rc.Width() - width) / 2;
|
||||
rcText.right = rc.left + width;
|
||||
surface->DrawTextClipped(rcText, fontForCharacter, rcText.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++) {
|
||||
const 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) {
|
||||
const int halfHeight = minDim / 3;
|
||||
Point pts[] = {
|
||||
Point::FromInts(ircWhole.left, centreY-halfHeight),
|
||||
Point::FromInts(ircWhole.right - 3, centreY - halfHeight),
|
||||
Point::FromInts(ircWhole.right - 3 - halfHeight, centreY),
|
||||
Point::FromInts(ircWhole.right - 3, centreY + halfHeight),
|
||||
Point::FromInts(ircWhole.left, centreY + halfHeight),
|
||||
};
|
||||
surface->Polygon(pts, ELEMENTS(pts), fore, back);
|
||||
} else { // SC_MARK_FULLRECT
|
||||
surface->FillRectangle(rcWhole, back);
|
||||
}
|
||||
}
|
||||
48
third_party/qscintilla/scintilla/src/LineMarker.h
vendored
Normal file
48
third_party/qscintilla/scintilla/src/LineMarker.h
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
class XPM;
|
||||
class RGBAImage;
|
||||
|
||||
typedef void (*DrawLineMarkerFn)(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, int tFold, int marginStyle, const void *lineMarker);
|
||||
|
||||
/**
|
||||
*/
|
||||
class LineMarker {
|
||||
public:
|
||||
enum typeOfFold { undefined, head, body, tail, headWithTail };
|
||||
|
||||
int markType;
|
||||
ColourDesired fore;
|
||||
ColourDesired back;
|
||||
ColourDesired backSelected;
|
||||
int alpha;
|
||||
std::unique_ptr<XPM> pxpm;
|
||||
std::unique_ptr<RGBAImage> image;
|
||||
/** Some platforms, notably PLAT_CURSES, do not support Scintilla's native
|
||||
* Draw function for drawing line markers. Allow those platforms to override
|
||||
* it instead of creating a new method(s) in the Surface class that existing
|
||||
* platforms must implement as empty. */
|
||||
DrawLineMarkerFn customDraw;
|
||||
LineMarker();
|
||||
LineMarker(const LineMarker &);
|
||||
virtual ~LineMarker();
|
||||
LineMarker &operator=(const LineMarker &other);
|
||||
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 &rcWhole, Font &fontForCharacter, typeOfFold tFold, int marginStyle) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
470
third_party/qscintilla/scintilla/src/MarginView.cpp
vendored
Normal file
470
third_party/qscintilla/scintilla/src/MarginView.cpp
vendored
Normal file
@@ -0,0 +1,470 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file MarginView.cxx
|
||||
** Defines the appearance of the editor margin.
|
||||
**/
|
||||
// Copyright 1998-2014 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "ILoader.h"
|
||||
#include "ILexer.h"
|
||||
#include "Scintilla.h"
|
||||
|
||||
#include "Position.h"
|
||||
#include "IntegerRectangle.h"
|
||||
#include "UniqueString.h"
|
||||
#include "SplitVector.h"
|
||||
#include "Partitioning.h"
|
||||
#include "RunStyles.h"
|
||||
#include "ContractionState.h"
|
||||
#include "CellBuffer.h"
|
||||
#include "KeyMap.h"
|
||||
#include "Indicator.h"
|
||||
#include "LineMarker.h"
|
||||
#include "Style.h"
|
||||
#include "ViewStyle.h"
|
||||
#include "CharClassify.h"
|
||||
#include "Decoration.h"
|
||||
#include "CaseFolder.h"
|
||||
#include "Document.h"
|
||||
#include "UniConversion.h"
|
||||
#include "Selection.h"
|
||||
#include "PositionCache.h"
|
||||
#include "EditModel.h"
|
||||
#include "MarginView.h"
|
||||
#include "EditView.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
void DrawWrapMarker(Surface *surface, PRectangle rcPlace,
|
||||
bool isEndMarker, ColourDesired wrapColour) {
|
||||
surface->PenColour(wrapColour);
|
||||
|
||||
const IntegerRectangle ircPlace(rcPlace);
|
||||
|
||||
enum { xa = 1 }; // gap before start
|
||||
const int w = ircPlace.Width() - xa - 1;
|
||||
|
||||
const bool xStraight = isEndMarker; // x-mirrored symbol for start marker
|
||||
|
||||
const int x0 = xStraight ? ircPlace.left : ircPlace.right - 1;
|
||||
const int y0 = ircPlace.top;
|
||||
|
||||
const int dy = ircPlace.Height() / 5;
|
||||
const int y = ircPlace.Height() / 2 + dy;
|
||||
|
||||
struct Relative {
|
||||
Surface *surface;
|
||||
int xBase;
|
||||
int xDir;
|
||||
int yBase;
|
||||
int yDir;
|
||||
void MoveTo(int xRelative, int yRelative) {
|
||||
surface->MoveTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
|
||||
}
|
||||
void LineTo(int xRelative, int yRelative) {
|
||||
surface->LineTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
|
||||
}
|
||||
};
|
||||
Relative rel = { surface, x0, xStraight ? 1 : -1, y0, 1 };
|
||||
|
||||
// arrow head
|
||||
rel.MoveTo(xa, y);
|
||||
rel.LineTo(xa + 2 * w / 3, y - dy);
|
||||
rel.MoveTo(xa, y);
|
||||
rel.LineTo(xa + 2 * w / 3, y + dy);
|
||||
|
||||
// arrow body
|
||||
rel.MoveTo(xa, y);
|
||||
rel.LineTo(xa + w, y);
|
||||
rel.LineTo(xa + w, y - 2 * dy);
|
||||
rel.LineTo(xa - 1, // on windows lineto is exclusive endpoint, perhaps GTK not...
|
||||
y - 2 * dy);
|
||||
}
|
||||
|
||||
MarginView::MarginView() {
|
||||
wrapMarkerPaddingRight = 3;
|
||||
customDrawWrapMarker = nullptr;
|
||||
}
|
||||
|
||||
void MarginView::DropGraphics(bool freeObjects) {
|
||||
if (freeObjects) {
|
||||
pixmapSelMargin.reset();
|
||||
pixmapSelPattern.reset();
|
||||
pixmapSelPatternOffset1.reset();
|
||||
} else {
|
||||
if (pixmapSelMargin)
|
||||
pixmapSelMargin->Release();
|
||||
if (pixmapSelPattern)
|
||||
pixmapSelPattern->Release();
|
||||
if (pixmapSelPatternOffset1)
|
||||
pixmapSelPatternOffset1->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void MarginView::AllocateGraphics(const ViewStyle &vsDraw) {
|
||||
if (!pixmapSelMargin)
|
||||
pixmapSelMargin.reset(Surface::Allocate(vsDraw.technology));
|
||||
if (!pixmapSelPattern)
|
||||
pixmapSelPattern.reset(Surface::Allocate(vsDraw.technology));
|
||||
if (!pixmapSelPatternOffset1)
|
||||
pixmapSelPatternOffset1.reset(Surface::Allocate(vsDraw.technology));
|
||||
}
|
||||
|
||||
void MarginView::RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw) {
|
||||
if (!pixmapSelPattern->Initialised()) {
|
||||
const int patternSize = 8;
|
||||
pixmapSelPattern->InitPixMap(patternSize, patternSize, surfaceWindow, wid);
|
||||
pixmapSelPatternOffset1->InitPixMap(patternSize, patternSize, surfaceWindow, wid);
|
||||
// This complex procedure is to reproduce the checkerboard dithered pattern used by windows
|
||||
// for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half
|
||||
// way between the chrome colour and the chrome highlight colour making a nice transition
|
||||
// between the window chrome and the content area. And it works in low colour depths.
|
||||
const PRectangle rcPattern = PRectangle::FromInts(0, 0, patternSize, patternSize);
|
||||
|
||||
// Initialize default colours based on the chrome colour scheme. Typically the highlight is white.
|
||||
ColourDesired colourFMFill = vsDraw.selbar;
|
||||
ColourDesired colourFMStripes = vsDraw.selbarlight;
|
||||
|
||||
if (!(vsDraw.selbarlight == ColourDesired(0xff, 0xff, 0xff))) {
|
||||
// User has chosen an unusual chrome colour scheme so just use the highlight edge colour.
|
||||
// (Typically, the highlight colour is white.)
|
||||
colourFMFill = vsDraw.selbarlight;
|
||||
}
|
||||
|
||||
if (vsDraw.foldmarginColour.isSet) {
|
||||
// override default fold margin colour
|
||||
colourFMFill = vsDraw.foldmarginColour;
|
||||
}
|
||||
if (vsDraw.foldmarginHighlightColour.isSet) {
|
||||
// override default fold margin highlight colour
|
||||
colourFMStripes = vsDraw.foldmarginHighlightColour;
|
||||
}
|
||||
|
||||
pixmapSelPattern->FillRectangle(rcPattern, colourFMFill);
|
||||
pixmapSelPatternOffset1->FillRectangle(rcPattern, colourFMStripes);
|
||||
for (int y = 0; y < patternSize; y++) {
|
||||
for (int x = y % 2; x < patternSize; x += 2) {
|
||||
const PRectangle rcPixel = PRectangle::FromInts(x, y, x + 1, y + 1);
|
||||
pixmapSelPattern->FillRectangle(rcPixel, colourFMStripes);
|
||||
pixmapSelPatternOffset1->FillRectangle(rcPixel, colourFMFill);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int SubstituteMarkerIfEmpty(int markerCheck, int markerDefault, const ViewStyle &vs) {
|
||||
if (vs.markers[markerCheck].markType == SC_MARK_EMPTY)
|
||||
return markerDefault;
|
||||
return markerCheck;
|
||||
}
|
||||
|
||||
void MarginView::PaintMargin(Surface *surface, Sci::Line topLine, PRectangle rc, PRectangle rcMargin,
|
||||
const EditModel &model, const ViewStyle &vs) {
|
||||
|
||||
PRectangle rcSelMargin = rcMargin;
|
||||
rcSelMargin.right = rcMargin.left;
|
||||
if (rcSelMargin.bottom < rc.bottom)
|
||||
rcSelMargin.bottom = rc.bottom;
|
||||
|
||||
const Point ptOrigin = model.GetVisibleOriginInMain();
|
||||
FontAlias fontLineNumber = vs.styles[STYLE_LINENUMBER].font;
|
||||
for (size_t margin = 0; margin < vs.ms.size(); margin++) {
|
||||
if (vs.ms[margin].width > 0) {
|
||||
|
||||
rcSelMargin.left = rcSelMargin.right;
|
||||
rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width;
|
||||
|
||||
if (vs.ms[margin].style != SC_MARGIN_NUMBER) {
|
||||
if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
|
||||
// Required because of special way brush is created for selection margin
|
||||
// Ensure patterns line up when scrolling with separate margin view
|
||||
// by choosing correctly aligned variant.
|
||||
const bool invertPhase = static_cast<int>(ptOrigin.y) & 1;
|
||||
surface->FillRectangle(rcSelMargin,
|
||||
invertPhase ? *pixmapSelPattern : *pixmapSelPatternOffset1);
|
||||
} else {
|
||||
ColourDesired colour;
|
||||
switch (vs.ms[margin].style) {
|
||||
case SC_MARGIN_BACK:
|
||||
colour = vs.styles[STYLE_DEFAULT].back;
|
||||
break;
|
||||
case SC_MARGIN_FORE:
|
||||
colour = vs.styles[STYLE_DEFAULT].fore;
|
||||
break;
|
||||
case SC_MARGIN_COLOUR:
|
||||
colour = vs.ms[margin].back;
|
||||
break;
|
||||
default:
|
||||
colour = vs.styles[STYLE_LINENUMBER].back;
|
||||
break;
|
||||
}
|
||||
surface->FillRectangle(rcSelMargin, colour);
|
||||
}
|
||||
} else {
|
||||
surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back);
|
||||
}
|
||||
|
||||
const int lineStartPaint = static_cast<int>(rcMargin.top + ptOrigin.y) / vs.lineHeight;
|
||||
Sci::Line visibleLine = model.TopLineOfMain() + lineStartPaint;
|
||||
Sci::Position yposScreen = lineStartPaint * vs.lineHeight - static_cast<Sci::Position>(ptOrigin.y);
|
||||
// Work out whether the top line is whitespace located after a
|
||||
// lessening of fold level which implies a 'fold tail' but which should not
|
||||
// be displayed until the last of a sequence of whitespace.
|
||||
bool needWhiteClosure = false;
|
||||
if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
|
||||
const int level = model.pdoc->GetLevel(model.pcs->DocFromDisplay(visibleLine));
|
||||
if (level & SC_FOLDLEVELWHITEFLAG) {
|
||||
Sci::Line lineBack = model.pcs->DocFromDisplay(visibleLine);
|
||||
int levelPrev = level;
|
||||
while ((lineBack > 0) && (levelPrev & SC_FOLDLEVELWHITEFLAG)) {
|
||||
lineBack--;
|
||||
levelPrev = model.pdoc->GetLevel(lineBack);
|
||||
}
|
||||
if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) {
|
||||
if (LevelNumber(level) < LevelNumber(levelPrev))
|
||||
needWhiteClosure = true;
|
||||
}
|
||||
}
|
||||
if (highlightDelimiter.isEnabled) {
|
||||
const Sci::Line lastLine = model.pcs->DocFromDisplay(topLine + model.LinesOnScreen()) + 1;
|
||||
model.pdoc->GetHighlightDelimiters(highlightDelimiter,
|
||||
model.pdoc->SciLineFromPosition(model.sel.MainCaret()), lastLine);
|
||||
}
|
||||
}
|
||||
|
||||
// Old code does not know about new markers needed to distinguish all cases
|
||||
const int folderOpenMid = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID,
|
||||
SC_MARKNUM_FOLDEROPEN, vs);
|
||||
const int folderEnd = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND,
|
||||
SC_MARKNUM_FOLDER, vs);
|
||||
|
||||
while ((visibleLine < model.pcs->LinesDisplayed()) && yposScreen < rc.bottom) {
|
||||
|
||||
PLATFORM_ASSERT(visibleLine < model.pcs->LinesDisplayed());
|
||||
const Sci::Line lineDoc = model.pcs->DocFromDisplay(visibleLine);
|
||||
PLATFORM_ASSERT(model.pcs->GetVisible(lineDoc));
|
||||
const Sci::Line firstVisibleLine = model.pcs->DisplayFromDoc(lineDoc);
|
||||
const Sci::Line lastVisibleLine = model.pcs->DisplayLastFromDoc(lineDoc);
|
||||
const bool firstSubLine = visibleLine == firstVisibleLine;
|
||||
const bool lastSubLine = visibleLine == lastVisibleLine;
|
||||
|
||||
int marks = model.pdoc->GetMark(lineDoc);
|
||||
if (!firstSubLine)
|
||||
marks = 0;
|
||||
|
||||
bool headWithTail = false;
|
||||
|
||||
if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
|
||||
// Decide which fold indicator should be displayed
|
||||
const int level = model.pdoc->GetLevel(lineDoc);
|
||||
const int levelNext = model.pdoc->GetLevel(lineDoc + 1);
|
||||
const int levelNum = LevelNumber(level);
|
||||
const int levelNextNum = LevelNumber(levelNext);
|
||||
if (level & SC_FOLDLEVELHEADERFLAG) {
|
||||
if (firstSubLine) {
|
||||
if (levelNum < levelNextNum) {
|
||||
if (model.pcs->GetExpanded(lineDoc)) {
|
||||
if (levelNum == SC_FOLDLEVELBASE)
|
||||
marks |= 1 << SC_MARKNUM_FOLDEROPEN;
|
||||
else
|
||||
marks |= 1 << folderOpenMid;
|
||||
} else {
|
||||
if (levelNum == SC_FOLDLEVELBASE)
|
||||
marks |= 1 << SC_MARKNUM_FOLDER;
|
||||
else
|
||||
marks |= 1 << folderEnd;
|
||||
}
|
||||
} else if (levelNum > SC_FOLDLEVELBASE) {
|
||||
marks |= 1 << SC_MARKNUM_FOLDERSUB;
|
||||
}
|
||||
} else {
|
||||
if (levelNum < levelNextNum) {
|
||||
if (model.pcs->GetExpanded(lineDoc)) {
|
||||
marks |= 1 << SC_MARKNUM_FOLDERSUB;
|
||||
} else if (levelNum > SC_FOLDLEVELBASE) {
|
||||
marks |= 1 << SC_MARKNUM_FOLDERSUB;
|
||||
}
|
||||
} else if (levelNum > SC_FOLDLEVELBASE) {
|
||||
marks |= 1 << SC_MARKNUM_FOLDERSUB;
|
||||
}
|
||||
}
|
||||
needWhiteClosure = false;
|
||||
const Sci::Line firstFollowupLine = model.pcs->DocFromDisplay(model.pcs->DisplayFromDoc(lineDoc + 1));
|
||||
const int firstFollowupLineLevel = model.pdoc->GetLevel(firstFollowupLine);
|
||||
const int secondFollowupLineLevelNum = LevelNumber(model.pdoc->GetLevel(firstFollowupLine + 1));
|
||||
if (!model.pcs->GetExpanded(lineDoc)) {
|
||||
if ((firstFollowupLineLevel & SC_FOLDLEVELWHITEFLAG) &&
|
||||
(levelNum > secondFollowupLineLevelNum))
|
||||
needWhiteClosure = true;
|
||||
|
||||
if (highlightDelimiter.IsFoldBlockHighlighted(firstFollowupLine))
|
||||
headWithTail = true;
|
||||
}
|
||||
} else if (level & SC_FOLDLEVELWHITEFLAG) {
|
||||
if (needWhiteClosure) {
|
||||
if (levelNext & SC_FOLDLEVELWHITEFLAG) {
|
||||
marks |= 1 << SC_MARKNUM_FOLDERSUB;
|
||||
} else if (levelNextNum > SC_FOLDLEVELBASE) {
|
||||
marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
|
||||
needWhiteClosure = false;
|
||||
} else {
|
||||
marks |= 1 << SC_MARKNUM_FOLDERTAIL;
|
||||
needWhiteClosure = false;
|
||||
}
|
||||
} else if (levelNum > SC_FOLDLEVELBASE) {
|
||||
if (levelNextNum < levelNum) {
|
||||
if (levelNextNum > SC_FOLDLEVELBASE) {
|
||||
marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
|
||||
} else {
|
||||
marks |= 1 << SC_MARKNUM_FOLDERTAIL;
|
||||
}
|
||||
} else {
|
||||
marks |= 1 << SC_MARKNUM_FOLDERSUB;
|
||||
}
|
||||
}
|
||||
} else if (levelNum > SC_FOLDLEVELBASE) {
|
||||
if (levelNextNum < levelNum) {
|
||||
needWhiteClosure = false;
|
||||
if (levelNext & SC_FOLDLEVELWHITEFLAG) {
|
||||
marks |= 1 << SC_MARKNUM_FOLDERSUB;
|
||||
needWhiteClosure = true;
|
||||
} else if (lastSubLine) {
|
||||
if (levelNextNum > SC_FOLDLEVELBASE) {
|
||||
marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
|
||||
} else {
|
||||
marks |= 1 << SC_MARKNUM_FOLDERTAIL;
|
||||
}
|
||||
} else {
|
||||
marks |= 1 << SC_MARKNUM_FOLDERSUB;
|
||||
}
|
||||
} else {
|
||||
marks |= 1 << SC_MARKNUM_FOLDERSUB;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
marks &= vs.ms[margin].mask;
|
||||
|
||||
PRectangle rcMarker = rcSelMargin;
|
||||
rcMarker.top = static_cast<XYPOSITION>(yposScreen);
|
||||
rcMarker.bottom = static_cast<XYPOSITION>(yposScreen + vs.lineHeight);
|
||||
if (vs.ms[margin].style == SC_MARGIN_NUMBER) {
|
||||
if (firstSubLine) {
|
||||
std::string sNumber;
|
||||
if (lineDoc >= 0) {
|
||||
sNumber = std::to_string(lineDoc + 1);
|
||||
}
|
||||
if (model.foldFlags & (SC_FOLDFLAG_LEVELNUMBERS | SC_FOLDFLAG_LINESTATE)) {
|
||||
char number[100] = "";
|
||||
if (model.foldFlags & SC_FOLDFLAG_LEVELNUMBERS) {
|
||||
const int lev = model.pdoc->GetLevel(lineDoc);
|
||||
sprintf(number, "%c%c %03X %03X",
|
||||
(lev & SC_FOLDLEVELHEADERFLAG) ? 'H' : '_',
|
||||
(lev & SC_FOLDLEVELWHITEFLAG) ? 'W' : '_',
|
||||
LevelNumber(lev),
|
||||
lev >> 16
|
||||
);
|
||||
} else {
|
||||
const int state = model.pdoc->GetLineState(lineDoc);
|
||||
sprintf(number, "%0X", state);
|
||||
}
|
||||
sNumber = number;
|
||||
}
|
||||
PRectangle rcNumber = rcMarker;
|
||||
// Right justify
|
||||
const XYPOSITION width = surface->WidthText(fontLineNumber, sNumber.c_str(), static_cast<int>(sNumber.length()));
|
||||
const XYPOSITION xpos = rcNumber.right - width - vs.marginNumberPadding;
|
||||
rcNumber.left = xpos;
|
||||
DrawTextNoClipPhase(surface, rcNumber, vs.styles[STYLE_LINENUMBER],
|
||||
rcNumber.top + vs.maxAscent, sNumber.c_str(), static_cast<int>(sNumber.length()), drawAll);
|
||||
} else if (vs.wrapVisualFlags & SC_WRAPVISUALFLAG_MARGIN) {
|
||||
PRectangle rcWrapMarker = rcMarker;
|
||||
rcWrapMarker.right -= wrapMarkerPaddingRight;
|
||||
rcWrapMarker.left = rcWrapMarker.right - vs.styles[STYLE_LINENUMBER].aveCharWidth;
|
||||
if (!customDrawWrapMarker) {
|
||||
DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore);
|
||||
} else {
|
||||
customDrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore);
|
||||
}
|
||||
}
|
||||
} else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) {
|
||||
const StyledText stMargin = model.pdoc->MarginStyledText(lineDoc);
|
||||
if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) {
|
||||
if (firstSubLine) {
|
||||
surface->FillRectangle(rcMarker,
|
||||
vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back);
|
||||
if (vs.ms[margin].style == SC_MARGIN_RTEXT) {
|
||||
const int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, stMargin);
|
||||
rcMarker.left = rcMarker.right - width - 3;
|
||||
}
|
||||
DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker,
|
||||
stMargin, 0, stMargin.length, drawAll);
|
||||
} else {
|
||||
// if we're displaying annotation lines, color the margin to match the associated document line
|
||||
const int annotationLines = model.pdoc->AnnotationLines(lineDoc);
|
||||
if (annotationLines && (visibleLine > lastVisibleLine - annotationLines)) {
|
||||
surface->FillRectangle(rcMarker, vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (marks) {
|
||||
for (int markBit = 0; (markBit < 32) && marks; markBit++) {
|
||||
if (marks & 1) {
|
||||
LineMarker::typeOfFold tFold = LineMarker::undefined;
|
||||
if ((vs.ms[margin].mask & SC_MASK_FOLDERS) && highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) {
|
||||
if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) {
|
||||
tFold = LineMarker::body;
|
||||
} else if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) {
|
||||
if (firstSubLine) {
|
||||
tFold = headWithTail ? LineMarker::headWithTail : LineMarker::head;
|
||||
} else {
|
||||
if (model.pcs->GetExpanded(lineDoc) || headWithTail) {
|
||||
tFold = LineMarker::body;
|
||||
} else {
|
||||
tFold = LineMarker::undefined;
|
||||
}
|
||||
}
|
||||
} else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) {
|
||||
tFold = LineMarker::tail;
|
||||
}
|
||||
}
|
||||
vs.markers[markBit].Draw(surface, rcMarker, fontLineNumber, tFold, vs.ms[margin].style);
|
||||
}
|
||||
marks >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
visibleLine++;
|
||||
yposScreen += vs.lineHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRectangle rcBlankMargin = rcMargin;
|
||||
rcBlankMargin.left = rcSelMargin.right;
|
||||
surface->FillRectangle(rcBlankMargin, vs.styles[STYLE_DEFAULT].back);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
46
third_party/qscintilla/scintilla/src/MarginView.h
vendored
Normal file
46
third_party/qscintilla/scintilla/src/MarginView.h
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file MarginView.h
|
||||
** Defines the appearance of the editor margin.
|
||||
**/
|
||||
// Copyright 1998-2014 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef MARGINVIEW_H
|
||||
#define MARGINVIEW_H
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
void DrawWrapMarker(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourDesired wrapColour);
|
||||
|
||||
typedef void (*DrawWrapMarkerFn)(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourDesired wrapColour);
|
||||
|
||||
/**
|
||||
* MarginView draws the margins.
|
||||
*/
|
||||
class MarginView {
|
||||
public:
|
||||
std::unique_ptr<Surface> pixmapSelMargin;
|
||||
std::unique_ptr<Surface> pixmapSelPattern;
|
||||
std::unique_ptr<Surface> pixmapSelPatternOffset1;
|
||||
// Highlight current folding block
|
||||
HighlightDelimiter highlightDelimiter;
|
||||
|
||||
int wrapMarkerPaddingRight; // right-most pixel padding of wrap markers
|
||||
/** Some platforms, notably PLAT_CURSES, do not support Scintilla's native
|
||||
* DrawWrapMarker function for drawing wrap markers. Allow those platforms to
|
||||
* override it instead of creating a new method in the Surface class that
|
||||
* existing platforms must implement as empty. */
|
||||
DrawWrapMarkerFn customDrawWrapMarker;
|
||||
|
||||
MarginView();
|
||||
|
||||
void DropGraphics(bool freeObjects);
|
||||
void AllocateGraphics(const ViewStyle &vsDraw);
|
||||
void RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw);
|
||||
void PaintMargin(Surface *surface, Sci::Line topLine, PRectangle rc, PRectangle rcMargin,
|
||||
const EditModel &model, const ViewStyle &vs);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
204
third_party/qscintilla/scintilla/src/Partitioning.h
vendored
Normal file
204
third_party/qscintilla/scintilla/src/Partitioning.h
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
/// A split vector of integers with a method for adding a value to all elements
|
||||
/// in a range.
|
||||
/// Used by the Partitioning class.
|
||||
|
||||
template <typename T>
|
||||
class SplitVectorWithRangeAdd : public SplitVector<T> {
|
||||
public:
|
||||
explicit SplitVectorWithRangeAdd(ptrdiff_t growSize_) {
|
||||
this->SetGrowSize(growSize_);
|
||||
this->ReAllocate(growSize_);
|
||||
}
|
||||
// Deleted so SplitVectorWithRangeAdd objects can not be copied.
|
||||
SplitVectorWithRangeAdd(const SplitVectorWithRangeAdd &) = delete;
|
||||
SplitVectorWithRangeAdd(SplitVectorWithRangeAdd &&) = delete;
|
||||
void operator=(const SplitVectorWithRangeAdd &) = delete;
|
||||
void operator=(SplitVectorWithRangeAdd &&) = delete;
|
||||
~SplitVectorWithRangeAdd() {
|
||||
}
|
||||
void RangeAddDelta(ptrdiff_t start, ptrdiff_t end, T delta) noexcept {
|
||||
// end is 1 past end, so end-start is number of elements to change
|
||||
ptrdiff_t i = 0;
|
||||
const ptrdiff_t rangeLength = end - start;
|
||||
ptrdiff_t range1Length = rangeLength;
|
||||
const ptrdiff_t part1Left = this->part1Length - start;
|
||||
if (range1Length > part1Left)
|
||||
range1Length = part1Left;
|
||||
while (i < range1Length) {
|
||||
this->body[start++] += delta;
|
||||
i++;
|
||||
}
|
||||
start += this->gapLength;
|
||||
while (i < rangeLength) {
|
||||
this->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).
|
||||
|
||||
template <typename T>
|
||||
class Partitioning {
|
||||
private:
|
||||
// To avoid calculating all the partition positions whenever any text is inserted
|
||||
// there may be a step somewhere in the list.
|
||||
T stepPartition;
|
||||
T stepLength;
|
||||
std::unique_ptr<SplitVectorWithRangeAdd<T>> body;
|
||||
|
||||
// Move step forward
|
||||
void ApplyStep(T partitionUpTo) noexcept {
|
||||
if (stepLength != 0) {
|
||||
body->RangeAddDelta(stepPartition+1, partitionUpTo + 1, stepLength);
|
||||
}
|
||||
stepPartition = partitionUpTo;
|
||||
if (stepPartition >= body->Length()-1) {
|
||||
stepPartition = Partitions();
|
||||
stepLength = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Move step backward
|
||||
void BackStep(T partitionDownTo) noexcept {
|
||||
if (stepLength != 0) {
|
||||
body->RangeAddDelta(partitionDownTo+1, stepPartition+1, -stepLength);
|
||||
}
|
||||
stepPartition = partitionDownTo;
|
||||
}
|
||||
|
||||
void Allocate(ptrdiff_t growSize) {
|
||||
body.reset(new SplitVectorWithRangeAdd<T>(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
|
||||
}
|
||||
|
||||
public:
|
||||
explicit Partitioning(int growSize) : stepPartition(0), stepLength(0) {
|
||||
Allocate(growSize);
|
||||
}
|
||||
|
||||
// Deleted so Partitioning objects can not be copied.
|
||||
Partitioning(const Partitioning &) = delete;
|
||||
Partitioning(Partitioning &&) = delete;
|
||||
void operator=(const Partitioning &) = delete;
|
||||
void operator=(Partitioning &&) = delete;
|
||||
|
||||
~Partitioning() {
|
||||
}
|
||||
|
||||
T Partitions() const noexcept {
|
||||
return static_cast<T>(body->Length())-1;
|
||||
}
|
||||
|
||||
void InsertPartition(T partition, T pos) {
|
||||
if (stepPartition < partition) {
|
||||
ApplyStep(partition);
|
||||
}
|
||||
body->Insert(partition, pos);
|
||||
stepPartition++;
|
||||
}
|
||||
|
||||
void SetPartitionStartPosition(T partition, T pos) noexcept {
|
||||
ApplyStep(partition+1);
|
||||
if ((partition < 0) || (partition > body->Length())) {
|
||||
return;
|
||||
}
|
||||
body->SetValueAt(partition, pos);
|
||||
}
|
||||
|
||||
void InsertText(T partitionInsert, T 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(Partitions());
|
||||
stepPartition = partitionInsert;
|
||||
stepLength = delta;
|
||||
}
|
||||
} else {
|
||||
stepPartition = partitionInsert;
|
||||
stepLength = delta;
|
||||
}
|
||||
}
|
||||
|
||||
void RemovePartition(T partition) {
|
||||
if (partition > stepPartition) {
|
||||
ApplyStep(partition);
|
||||
stepPartition--;
|
||||
} else {
|
||||
stepPartition--;
|
||||
}
|
||||
body->Delete(partition);
|
||||
}
|
||||
|
||||
T PositionFromPartition(T partition) const noexcept {
|
||||
PLATFORM_ASSERT(partition >= 0);
|
||||
PLATFORM_ASSERT(partition < body->Length());
|
||||
const ptrdiff_t lengthBody = body->Length();
|
||||
if ((partition < 0) || (partition >= lengthBody)) {
|
||||
return 0;
|
||||
}
|
||||
T pos = body->ValueAt(partition);
|
||||
if (partition > stepPartition)
|
||||
pos += stepLength;
|
||||
return pos;
|
||||
}
|
||||
|
||||
/// Return value in range [0 .. Partitions() - 1] even for arguments outside interval
|
||||
T PartitionFromPosition(T pos) const noexcept {
|
||||
if (body->Length() <= 1)
|
||||
return 0;
|
||||
if (pos >= (PositionFromPartition(Partitions())))
|
||||
return Partitions() - 1;
|
||||
T lower = 0;
|
||||
T upper = Partitions();
|
||||
do {
|
||||
const T middle = (upper + lower + 1) / 2; // Round high
|
||||
T 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() {
|
||||
Allocate(body->GetGrowSize());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
499
third_party/qscintilla/scintilla/src/PerLine.cpp
vendored
Normal file
499
third_party/qscintilla/scintilla/src/PerLine.cpp
vendored
Normal file
@@ -0,0 +1,499 @@
|
||||
// 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 <cstddef>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <forward_list>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
#include "Position.h"
|
||||
#include "SplitVector.h"
|
||||
#include "Partitioning.h"
|
||||
#include "CellBuffer.h"
|
||||
#include "PerLine.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
MarkerHandleSet::MarkerHandleSet() {
|
||||
}
|
||||
|
||||
MarkerHandleSet::~MarkerHandleSet() {
|
||||
mhList.clear();
|
||||
}
|
||||
|
||||
bool MarkerHandleSet::Empty() const noexcept {
|
||||
return mhList.empty();
|
||||
}
|
||||
|
||||
int MarkerHandleSet::MarkValue() const noexcept {
|
||||
unsigned int m = 0;
|
||||
for (const MarkerHandleNumber &mhn : mhList) {
|
||||
m |= (1 << mhn.number);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
bool MarkerHandleSet::Contains(int handle) const noexcept {
|
||||
for (const MarkerHandleNumber &mhn : mhList) {
|
||||
if (mhn.handle == handle) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MarkerHandleSet::InsertHandle(int handle, int markerNum) {
|
||||
mhList.push_front(MarkerHandleNumber(handle, markerNum));
|
||||
return true;
|
||||
}
|
||||
|
||||
void MarkerHandleSet::RemoveHandle(int handle) {
|
||||
mhList.remove_if([handle](const MarkerHandleNumber &mhn) { return mhn.handle == handle; });
|
||||
}
|
||||
|
||||
bool MarkerHandleSet::RemoveNumber(int markerNum, bool all) {
|
||||
bool performedDeletion = false;
|
||||
mhList.remove_if([&](const MarkerHandleNumber &mhn) {
|
||||
if ((all || !performedDeletion) && (mhn.number == markerNum)) {
|
||||
performedDeletion = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return performedDeletion;
|
||||
}
|
||||
|
||||
void MarkerHandleSet::CombineWith(MarkerHandleSet *other) {
|
||||
mhList.splice_after(mhList.before_begin(), other->mhList);
|
||||
}
|
||||
|
||||
LineMarkers::~LineMarkers() {
|
||||
markers.DeleteAll();
|
||||
}
|
||||
|
||||
void LineMarkers::Init() {
|
||||
markers.DeleteAll();
|
||||
}
|
||||
|
||||
void LineMarkers::InsertLine(Sci::Line line) {
|
||||
if (markers.Length()) {
|
||||
markers.Insert(line, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void LineMarkers::RemoveLine(Sci::Line 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);
|
||||
}
|
||||
}
|
||||
|
||||
Sci::Line LineMarkers::LineFromHandle(int markerHandle) {
|
||||
if (markers.Length()) {
|
||||
for (Sci::Line line = 0; line < markers.Length(); line++) {
|
||||
if (markers[line]) {
|
||||
if (markers[line]->Contains(markerHandle)) {
|
||||
return line;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void LineMarkers::MergeMarkers(Sci::Line line) {
|
||||
if (markers[line + 1]) {
|
||||
if (!markers[line])
|
||||
markers[line].reset(new MarkerHandleSet);
|
||||
markers[line]->CombineWith(markers[line + 1].get());
|
||||
markers[line + 1].reset();
|
||||
}
|
||||
}
|
||||
|
||||
int LineMarkers::MarkValue(Sci::Line line) noexcept {
|
||||
if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line])
|
||||
return markers[line]->MarkValue();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
Sci::Line LineMarkers::MarkerNext(Sci::Line lineStart, int mask) const {
|
||||
if (lineStart < 0)
|
||||
lineStart = 0;
|
||||
const Sci::Line length = static_cast<Sci::Line>(markers.Length());
|
||||
for (Sci::Line iLine = lineStart; iLine < length; iLine++) {
|
||||
const MarkerHandleSet *onLine = markers[iLine].get();
|
||||
if (onLine && ((onLine->MarkValue() & mask) != 0))
|
||||
return iLine;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int LineMarkers::AddMark(Sci::Line line, int markerNum, Sci::Line lines) {
|
||||
handleCurrent++;
|
||||
if (!markers.Length()) {
|
||||
// No existing markers so allocate one element per line
|
||||
markers.InsertEmpty(0, lines);
|
||||
}
|
||||
if (line >= markers.Length()) {
|
||||
return -1;
|
||||
}
|
||||
if (!markers[line]) {
|
||||
// Need new structure to hold marker handle
|
||||
markers[line].reset(new MarkerHandleSet());
|
||||
}
|
||||
markers[line]->InsertHandle(handleCurrent, markerNum);
|
||||
|
||||
return handleCurrent;
|
||||
}
|
||||
|
||||
bool LineMarkers::DeleteMark(Sci::Line line, int markerNum, bool all) {
|
||||
bool someChanges = false;
|
||||
if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) {
|
||||
if (markerNum == -1) {
|
||||
someChanges = true;
|
||||
markers[line].reset();
|
||||
} else {
|
||||
someChanges = markers[line]->RemoveNumber(markerNum, all);
|
||||
if (markers[line]->Empty()) {
|
||||
markers[line].reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
return someChanges;
|
||||
}
|
||||
|
||||
void LineMarkers::DeleteMarkFromHandle(int markerHandle) {
|
||||
const Sci::Line line = LineFromHandle(markerHandle);
|
||||
if (line >= 0) {
|
||||
markers[line]->RemoveHandle(markerHandle);
|
||||
if (markers[line]->Empty()) {
|
||||
markers[line].reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LineLevels::~LineLevels() {
|
||||
}
|
||||
|
||||
void LineLevels::Init() {
|
||||
levels.DeleteAll();
|
||||
}
|
||||
|
||||
void LineLevels::InsertLine(Sci::Line line) {
|
||||
if (levels.Length()) {
|
||||
const int level = (line < levels.Length()) ? levels[line] : SC_FOLDLEVELBASE;
|
||||
levels.InsertValue(line, 1, level);
|
||||
}
|
||||
}
|
||||
|
||||
void LineLevels::RemoveLine(Sci::Line 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(Sci::Line sizeNew) {
|
||||
levels.InsertValue(levels.Length(), sizeNew - levels.Length(), SC_FOLDLEVELBASE);
|
||||
}
|
||||
|
||||
void LineLevels::ClearLevels() {
|
||||
levels.DeleteAll();
|
||||
}
|
||||
|
||||
int LineLevels::SetLevel(Sci::Line line, int level, Sci::Line 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(Sci::Line 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(Sci::Line line) {
|
||||
if (lineStates.Length()) {
|
||||
lineStates.EnsureLength(line);
|
||||
const int val = (line < lineStates.Length()) ? lineStates[line] : 0;
|
||||
lineStates.Insert(line, val);
|
||||
}
|
||||
}
|
||||
|
||||
void LineState::RemoveLine(Sci::Line line) {
|
||||
if (lineStates.Length() > line) {
|
||||
lineStates.Delete(line);
|
||||
}
|
||||
}
|
||||
|
||||
int LineState::SetLineState(Sci::Line line, int state) {
|
||||
lineStates.EnsureLength(line + 1);
|
||||
const int stateOld = lineStates[line];
|
||||
lineStates[line] = state;
|
||||
return stateOld;
|
||||
}
|
||||
|
||||
int LineState::GetLineState(Sci::Line line) {
|
||||
if (line < 0)
|
||||
return 0;
|
||||
lineStates.EnsureLength(line + 1);
|
||||
return lineStates[line];
|
||||
}
|
||||
|
||||
Sci::Line LineState::GetMaxLineState() const {
|
||||
return static_cast<Sci::Line>(lineStates.Length());
|
||||
}
|
||||
|
||||
static int NumberLines(const char *text) noexcept {
|
||||
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(Sci::Line line) {
|
||||
if (annotations.Length()) {
|
||||
annotations.EnsureLength(line);
|
||||
annotations.Insert(line, std::unique_ptr<char []>());
|
||||
}
|
||||
}
|
||||
|
||||
void LineAnnotation::RemoveLine(Sci::Line line) {
|
||||
if (annotations.Length() && (line > 0) && (line <= annotations.Length())) {
|
||||
annotations[line-1].reset();
|
||||
annotations.Delete(line-1);
|
||||
}
|
||||
}
|
||||
|
||||
bool LineAnnotation::MultipleStyles(Sci::Line line) const {
|
||||
if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
|
||||
return reinterpret_cast<AnnotationHeader *>(annotations[line].get())->style == IndividualStyles;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
int LineAnnotation::Style(Sci::Line line) const {
|
||||
if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
|
||||
return reinterpret_cast<AnnotationHeader *>(annotations[line].get())->style;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *LineAnnotation::Text(Sci::Line line) const {
|
||||
if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
|
||||
return annotations[line].get()+sizeof(AnnotationHeader);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const unsigned char *LineAnnotation::Styles(Sci::Line line) const {
|
||||
if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line] && MultipleStyles(line))
|
||||
return reinterpret_cast<unsigned char *>(annotations[line].get() + sizeof(AnnotationHeader) + Length(line));
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static char *AllocateAnnotation(int length, int style) {
|
||||
const size_t len = sizeof(AnnotationHeader) + length + ((style == IndividualStyles) ? length : 0);
|
||||
char *ret = new char[len]();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void LineAnnotation::SetText(Sci::Line line, const char *text) {
|
||||
if (text && (line >= 0)) {
|
||||
annotations.EnsureLength(line+1);
|
||||
const int style = Style(line);
|
||||
annotations[line].reset(AllocateAnnotation(static_cast<int>(strlen(text)), style));
|
||||
char *pa = annotations[line].get();
|
||||
assert(pa);
|
||||
AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(pa);
|
||||
pah->style = static_cast<short>(style);
|
||||
pah->length = static_cast<int>(strlen(text));
|
||||
pah->lines = static_cast<short>(NumberLines(text));
|
||||
memcpy(pa+sizeof(AnnotationHeader), text, pah->length);
|
||||
} else {
|
||||
if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) {
|
||||
annotations[line].reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LineAnnotation::ClearAll() {
|
||||
annotations.DeleteAll();
|
||||
}
|
||||
|
||||
void LineAnnotation::SetStyle(Sci::Line line, int style) {
|
||||
annotations.EnsureLength(line+1);
|
||||
if (!annotations[line]) {
|
||||
annotations[line].reset(AllocateAnnotation(0, style));
|
||||
}
|
||||
reinterpret_cast<AnnotationHeader *>(annotations[line].get())->style = static_cast<short>(style);
|
||||
}
|
||||
|
||||
void LineAnnotation::SetStyles(Sci::Line line, const unsigned char *styles) {
|
||||
if (line >= 0) {
|
||||
annotations.EnsureLength(line+1);
|
||||
if (!annotations[line]) {
|
||||
annotations[line].reset(AllocateAnnotation(0, IndividualStyles));
|
||||
} else {
|
||||
const AnnotationHeader *pahSource = reinterpret_cast<AnnotationHeader *>(annotations[line].get());
|
||||
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].get() + sizeof(AnnotationHeader), pahSource->length);
|
||||
annotations[line].reset(allocation);
|
||||
}
|
||||
}
|
||||
AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line].get());
|
||||
pah->style = IndividualStyles;
|
||||
memcpy(annotations[line].get() + sizeof(AnnotationHeader) + pah->length, styles, pah->length);
|
||||
}
|
||||
}
|
||||
|
||||
int LineAnnotation::Length(Sci::Line line) const {
|
||||
if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
|
||||
return reinterpret_cast<AnnotationHeader *>(annotations[line].get())->length;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LineAnnotation::Lines(Sci::Line line) const {
|
||||
if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
|
||||
return reinterpret_cast<AnnotationHeader *>(annotations[line].get())->lines;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
LineTabstops::~LineTabstops() {
|
||||
tabstops.DeleteAll();
|
||||
}
|
||||
|
||||
void LineTabstops::Init() {
|
||||
tabstops.DeleteAll();
|
||||
}
|
||||
|
||||
void LineTabstops::InsertLine(Sci::Line line) {
|
||||
if (tabstops.Length()) {
|
||||
tabstops.EnsureLength(line);
|
||||
tabstops.Insert(line, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void LineTabstops::RemoveLine(Sci::Line line) {
|
||||
if (tabstops.Length() > line) {
|
||||
tabstops[line].reset();
|
||||
tabstops.Delete(line);
|
||||
}
|
||||
}
|
||||
|
||||
bool LineTabstops::ClearTabstops(Sci::Line line) {
|
||||
if (line < tabstops.Length()) {
|
||||
TabstopList *tl = tabstops[line].get();
|
||||
if (tl) {
|
||||
tl->clear();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LineTabstops::AddTabstop(Sci::Line line, int x) {
|
||||
tabstops.EnsureLength(line + 1);
|
||||
if (!tabstops[line]) {
|
||||
tabstops[line].reset(new TabstopList());
|
||||
}
|
||||
|
||||
TabstopList *tl = tabstops[line].get();
|
||||
if (tl) {
|
||||
// tabstop positions are kept in order - insert in the right place
|
||||
std::vector<int>::iterator it = std::lower_bound(tl->begin(), tl->end(), x);
|
||||
// don't insert duplicates
|
||||
if (it == tl->end() || *it != x) {
|
||||
tl->insert(it, x);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int LineTabstops::GetNextTabstop(Sci::Line line, int x) const {
|
||||
if (line < tabstops.Length()) {
|
||||
TabstopList *tl = tabstops[line].get();
|
||||
if (tl) {
|
||||
for (const int i : *tl) {
|
||||
if (i > x) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
164
third_party/qscintilla/scintilla/src/PerLine.h
vendored
Normal file
164
third_party/qscintilla/scintilla/src/PerLine.h
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
/**
|
||||
* This holds the marker identifier and the marker type to display.
|
||||
* MarkerHandleNumbers are members of lists.
|
||||
*/
|
||||
struct MarkerHandleNumber {
|
||||
int handle;
|
||||
int number;
|
||||
MarkerHandleNumber(int handle_, int number_) : handle(handle_), number(number_) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* A marker handle set contains any number of MarkerHandleNumbers.
|
||||
*/
|
||||
class MarkerHandleSet {
|
||||
std::forward_list<MarkerHandleNumber> mhList;
|
||||
|
||||
public:
|
||||
MarkerHandleSet();
|
||||
// Deleted so MarkerHandleSet objects can not be copied.
|
||||
MarkerHandleSet(const MarkerHandleSet &) = delete;
|
||||
MarkerHandleSet(MarkerHandleSet &&) = delete;
|
||||
void operator=(const MarkerHandleSet &) = delete;
|
||||
void operator=(MarkerHandleSet &&) = delete;
|
||||
~MarkerHandleSet();
|
||||
bool Empty() const noexcept;
|
||||
int MarkValue() const noexcept; ///< Bit set of marker numbers.
|
||||
bool Contains(int handle) const noexcept;
|
||||
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<std::unique_ptr<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) {
|
||||
}
|
||||
// Deleted so LineMarkers objects can not be copied.
|
||||
LineMarkers(const LineMarkers &) = delete;
|
||||
LineMarkers(LineMarkers &&) = delete;
|
||||
void operator=(const LineMarkers &) = delete;
|
||||
void operator=(LineMarkers &&) = delete;
|
||||
~LineMarkers() override;
|
||||
void Init() override;
|
||||
void InsertLine(Sci::Line line) override;
|
||||
void RemoveLine(Sci::Line line) override;
|
||||
|
||||
int MarkValue(Sci::Line line) noexcept;
|
||||
Sci::Line MarkerNext(Sci::Line lineStart, int mask) const;
|
||||
int AddMark(Sci::Line line, int markerNum, Sci::Line lines);
|
||||
void MergeMarkers(Sci::Line line);
|
||||
bool DeleteMark(Sci::Line line, int markerNum, bool all);
|
||||
void DeleteMarkFromHandle(int markerHandle);
|
||||
Sci::Line LineFromHandle(int markerHandle);
|
||||
};
|
||||
|
||||
class LineLevels : public PerLine {
|
||||
SplitVector<int> levels;
|
||||
public:
|
||||
LineLevels() {
|
||||
}
|
||||
// Deleted so LineLevels objects can not be copied.
|
||||
LineLevels(const LineLevels &) = delete;
|
||||
LineLevels(LineLevels &&) = delete;
|
||||
void operator=(const LineLevels &) = delete;
|
||||
void operator=(LineLevels &&) = delete;
|
||||
~LineLevels() override;
|
||||
void Init() override;
|
||||
void InsertLine(Sci::Line line) override;
|
||||
void RemoveLine(Sci::Line line) override;
|
||||
|
||||
void ExpandLevels(Sci::Line sizeNew=-1);
|
||||
void ClearLevels();
|
||||
int SetLevel(Sci::Line line, int level, Sci::Line lines);
|
||||
int GetLevel(Sci::Line line) const;
|
||||
};
|
||||
|
||||
class LineState : public PerLine {
|
||||
SplitVector<int> lineStates;
|
||||
public:
|
||||
LineState() {
|
||||
}
|
||||
// Deleted so LineState objects can not be copied.
|
||||
LineState(const LineState &) = delete;
|
||||
LineState(LineState &&) = delete;
|
||||
void operator=(const LineState &) = delete;
|
||||
void operator=(LineState &&) = delete;
|
||||
~LineState() override;
|
||||
void Init() override;
|
||||
void InsertLine(Sci::Line line) override;
|
||||
void RemoveLine(Sci::Line line) override;
|
||||
|
||||
int SetLineState(Sci::Line line, int state);
|
||||
int GetLineState(Sci::Line line);
|
||||
Sci::Line GetMaxLineState() const;
|
||||
};
|
||||
|
||||
class LineAnnotation : public PerLine {
|
||||
SplitVector<std::unique_ptr<char []>> annotations;
|
||||
public:
|
||||
LineAnnotation() {
|
||||
}
|
||||
// Deleted so LineAnnotation objects can not be copied.
|
||||
LineAnnotation(const LineAnnotation &) = delete;
|
||||
LineAnnotation(LineAnnotation &&) = delete;
|
||||
void operator=(const LineAnnotation &) = delete;
|
||||
void operator=(LineAnnotation &&) = delete;
|
||||
~LineAnnotation() override;
|
||||
void Init() override;
|
||||
void InsertLine(Sci::Line line) override;
|
||||
void RemoveLine(Sci::Line line) override;
|
||||
|
||||
bool MultipleStyles(Sci::Line line) const;
|
||||
int Style(Sci::Line line) const;
|
||||
const char *Text(Sci::Line line) const;
|
||||
const unsigned char *Styles(Sci::Line line) const;
|
||||
void SetText(Sci::Line line, const char *text);
|
||||
void ClearAll();
|
||||
void SetStyle(Sci::Line line, int style);
|
||||
void SetStyles(Sci::Line line, const unsigned char *styles);
|
||||
int Length(Sci::Line line) const;
|
||||
int Lines(Sci::Line line) const;
|
||||
};
|
||||
|
||||
typedef std::vector<int> TabstopList;
|
||||
|
||||
class LineTabstops : public PerLine {
|
||||
SplitVector<std::unique_ptr<TabstopList>> tabstops;
|
||||
public:
|
||||
LineTabstops() {
|
||||
}
|
||||
// Deleted so LineTabstops objects can not be copied.
|
||||
LineTabstops(const LineTabstops &) = delete;
|
||||
LineTabstops(LineTabstops &&) = delete;
|
||||
void operator=(const LineTabstops &) = delete;
|
||||
void operator=(LineTabstops &&) = delete;
|
||||
~LineTabstops() override;
|
||||
void Init() override;
|
||||
void InsertLine(Sci::Line line) override;
|
||||
void RemoveLine(Sci::Line line) override;
|
||||
|
||||
bool ClearTabstops(Sci::Line line);
|
||||
bool AddTabstop(Sci::Line line, int x);
|
||||
int GetNextTabstop(Sci::Line line, int x) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
31
third_party/qscintilla/scintilla/src/Position.h
vendored
Normal file
31
third_party/qscintilla/scintilla/src/Position.h
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file Position.h
|
||||
** Defines global type name Position in the Sci internal namespace.
|
||||
**/
|
||||
// Copyright 2015 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef POSITION_H
|
||||
#define POSITION_H
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* A Line is a document or screen line.
|
||||
*/
|
||||
|
||||
namespace Sci {
|
||||
|
||||
typedef ptrdiff_t Position;
|
||||
typedef ptrdiff_t Line;
|
||||
|
||||
const Position invalidPosition = -1;
|
||||
|
||||
template <typename T>
|
||||
inline constexpr T clamp(T val, T minVal, T maxVal) {
|
||||
return (val > maxVal) ? maxVal : ((val < minVal) ? minVal : val);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
719
third_party/qscintilla/scintilla/src/PositionCache.cpp
vendored
Normal file
719
third_party/qscintilla/scintilla/src/PositionCache.cpp
vendored
Normal file
@@ -0,0 +1,719 @@
|
||||
// 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 <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "ILoader.h"
|
||||
#include "ILexer.h"
|
||||
#include "Scintilla.h"
|
||||
|
||||
#include "Position.h"
|
||||
#include "UniqueString.h"
|
||||
#include "SplitVector.h"
|
||||
#include "Partitioning.h"
|
||||
#include "RunStyles.h"
|
||||
#include "ContractionState.h"
|
||||
#include "CellBuffer.h"
|
||||
#include "KeyMap.h"
|
||||
#include "Indicator.h"
|
||||
#include "LineMarker.h"
|
||||
#include "Style.h"
|
||||
#include "ViewStyle.h"
|
||||
#include "CharClassify.h"
|
||||
#include "Decoration.h"
|
||||
#include "CaseFolder.h"
|
||||
#include "Document.h"
|
||||
#include "UniConversion.h"
|
||||
#include "Selection.h"
|
||||
#include "PositionCache.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
LineLayout::LineLayout(int maxLineLength_) :
|
||||
lenLineStarts(0),
|
||||
lineNumber(-1),
|
||||
inCache(false),
|
||||
maxLineLength(-1),
|
||||
numCharsInLine(0),
|
||||
numCharsBeforeEOL(0),
|
||||
validity(llInvalid),
|
||||
xHighlightGuide(0),
|
||||
highlightColumn(false),
|
||||
containsCaret(false),
|
||||
edgeColumn(0),
|
||||
bracePreviousStyles{},
|
||||
hotspot(0,0),
|
||||
widthLine(wrapWidthInfinite),
|
||||
lines(1),
|
||||
wrapIndent(0) {
|
||||
Resize(maxLineLength_);
|
||||
}
|
||||
|
||||
LineLayout::~LineLayout() {
|
||||
Free();
|
||||
}
|
||||
|
||||
void LineLayout::Resize(int maxLineLength_) {
|
||||
if (maxLineLength_ > maxLineLength) {
|
||||
Free();
|
||||
chars.reset(new char[maxLineLength_ + 1]);
|
||||
styles.reset(new unsigned char[maxLineLength_ + 1]);
|
||||
// Extra position allocated as sometimes the Windows
|
||||
// GetTextExtentExPoint API writes an extra element.
|
||||
positions.reset(new XYPOSITION[maxLineLength_ + 1 + 1]);
|
||||
maxLineLength = maxLineLength_;
|
||||
}
|
||||
}
|
||||
|
||||
void LineLayout::Free() {
|
||||
chars.reset();
|
||||
styles.reset();
|
||||
positions.reset();
|
||||
lineStarts.reset();
|
||||
}
|
||||
|
||||
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, Scope scope) const {
|
||||
if (line < 0) {
|
||||
return 0;
|
||||
} else if ((line >= lines-1) || !lineStarts) {
|
||||
return scope == Scope::visibleOnly ? numCharsBeforeEOL : numCharsInLine;
|
||||
} else {
|
||||
return lineStarts[line+1];
|
||||
}
|
||||
}
|
||||
|
||||
Range LineLayout::SubLineRange(int subLine, Scope scope) const {
|
||||
return Range(LineStart(subLine), LineLastVisible(subLine, scope));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
lineStarts.reset(newLineStarts);
|
||||
lenLineStarts = newMaxLines;
|
||||
}
|
||||
lineStarts[line] = start;
|
||||
}
|
||||
|
||||
void LineLayout::SetBracesHighlight(Range rangeLine, const Sci::Position braces[],
|
||||
char bracesMatchStyle, int xHighlight, bool ignoreStyle) {
|
||||
if (!ignoreStyle && rangeLine.ContainsCharacter(braces[0])) {
|
||||
const Sci::Position braceOffset = braces[0] - rangeLine.start;
|
||||
if (braceOffset < numCharsInLine) {
|
||||
bracePreviousStyles[0] = styles[braceOffset];
|
||||
styles[braceOffset] = bracesMatchStyle;
|
||||
}
|
||||
}
|
||||
if (!ignoreStyle && rangeLine.ContainsCharacter(braces[1])) {
|
||||
const Sci::Position 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, const Sci::Position braces[], bool ignoreStyle) {
|
||||
if (!ignoreStyle && rangeLine.ContainsCharacter(braces[0])) {
|
||||
const Sci::Position braceOffset = braces[0] - rangeLine.start;
|
||||
if (braceOffset < numCharsInLine) {
|
||||
styles[braceOffset] = bracePreviousStyles[0];
|
||||
}
|
||||
}
|
||||
if (!ignoreStyle && rangeLine.ContainsCharacter(braces[1])) {
|
||||
const Sci::Position braceOffset = braces[1] - rangeLine.start;
|
||||
if (braceOffset < numCharsInLine) {
|
||||
styles[braceOffset] = bracePreviousStyles[1];
|
||||
}
|
||||
}
|
||||
xHighlightGuide = 0;
|
||||
}
|
||||
|
||||
int LineLayout::FindBefore(XYPOSITION x, Range range) const {
|
||||
Sci::Position lower = range.start;
|
||||
Sci::Position upper = range.end;
|
||||
do {
|
||||
const Sci::Position middle = (upper + lower + 1) / 2; // Round high
|
||||
const XYPOSITION posMiddle = positions[middle];
|
||||
if (x < posMiddle) {
|
||||
upper = middle - 1;
|
||||
} else {
|
||||
lower = middle;
|
||||
}
|
||||
} while (lower < upper);
|
||||
return static_cast<int>(lower);
|
||||
}
|
||||
|
||||
|
||||
int LineLayout::FindPositionFromX(XYPOSITION x, Range range, bool charPosition) const {
|
||||
int pos = FindBefore(x, range);
|
||||
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 static_cast<int>(range.end);
|
||||
}
|
||||
|
||||
Point LineLayout::PointFromPosition(int posInLine, int lineHeight, PointEnd pe) 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, Scope::visibleOnly);
|
||||
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;
|
||||
if (pe & peSubLineEnd) // Return end of first subline not start of next
|
||||
break;
|
||||
} else if ((pe & peLineEnd) && (subLine == (lines-1))) {
|
||||
pt.x = positions[numCharsInLine] - 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(Sci::Line linesOnScreen, Sci::Line 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++) {
|
||||
cache[i].reset();
|
||||
}
|
||||
}
|
||||
cache.resize(lengthForLevel);
|
||||
}
|
||||
PLATFORM_ASSERT(cache.size() == lengthForLevel);
|
||||
}
|
||||
|
||||
void LineLayoutCache::Deallocate() {
|
||||
PLATFORM_ASSERT(useCount == 0);
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
void LineLayoutCache::Invalidate(LineLayout::validLevel validity_) {
|
||||
if (!cache.empty() && !allInvalidated) {
|
||||
for (const std::unique_ptr<LineLayout> &ll : cache) {
|
||||
if (ll) {
|
||||
ll->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(Sci::Line lineNumber, Sci::Line lineCaret, int maxChars, int styleClock_,
|
||||
Sci::Line linesOnScreen, Sci::Line linesInDoc) {
|
||||
AllocateForLevel(linesOnScreen, linesInDoc);
|
||||
if (styleClock != styleClock_) {
|
||||
Invalidate(LineLayout::llCheckTextAndStyle);
|
||||
styleClock = styleClock_;
|
||||
}
|
||||
allInvalidated = false;
|
||||
Sci::Position pos = -1;
|
||||
LineLayout *ret = nullptr;
|
||||
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)) {
|
||||
cache[pos].reset();
|
||||
}
|
||||
}
|
||||
if (!cache[pos]) {
|
||||
cache[pos].reset(new LineLayout(maxChars));
|
||||
}
|
||||
cache[pos]->lineNumber = lineNumber;
|
||||
cache[pos]->inCache = true;
|
||||
ret = cache[pos].get();
|
||||
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 unsigned int KeyFromString(const char *charBytes, size_t len) {
|
||||
PLATFORM_ASSERT(len <= 4);
|
||||
unsigned int k=0;
|
||||
for (size_t i=0; i<len && charBytes[i]; i++) {
|
||||
k = k * 0x100;
|
||||
const unsigned char uc = charBytes[i];
|
||||
k += uc;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
SpecialRepresentations::SpecialRepresentations() {
|
||||
const short none = 0;
|
||||
std::fill(startByteHasReprs, std::end(startByteHasReprs), none);
|
||||
}
|
||||
|
||||
void SpecialRepresentations::SetRepresentation(const char *charBytes, const char *value) {
|
||||
const unsigned int key = KeyFromString(charBytes, UTF8MaxBytes);
|
||||
MapRepresentation::iterator it = mapReprs.find(key);
|
||||
if (it == mapReprs.end()) {
|
||||
// New entry so increment for first byte
|
||||
const unsigned char ucStart = charBytes[0];
|
||||
startByteHasReprs[ucStart]++;
|
||||
}
|
||||
mapReprs[key] = Representation(value);
|
||||
}
|
||||
|
||||
void SpecialRepresentations::ClearRepresentation(const char *charBytes) {
|
||||
MapRepresentation::iterator it = mapReprs.find(KeyFromString(charBytes, UTF8MaxBytes));
|
||||
if (it != mapReprs.end()) {
|
||||
mapReprs.erase(it);
|
||||
const unsigned char ucStart = charBytes[0];
|
||||
startByteHasReprs[ucStart]--;
|
||||
}
|
||||
}
|
||||
|
||||
const Representation *SpecialRepresentations::RepresentationFromCharacter(const char *charBytes, size_t len) const {
|
||||
PLATFORM_ASSERT(len <= 4);
|
||||
const unsigned char ucStart = charBytes[0];
|
||||
if (!startByteHasReprs[ucStart])
|
||||
return nullptr;
|
||||
MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes, len));
|
||||
if (it != mapReprs.end()) {
|
||||
return &(it->second);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool SpecialRepresentations::Contains(const char *charBytes, size_t len) const {
|
||||
PLATFORM_ASSERT(len <= 4);
|
||||
const unsigned char ucStart = charBytes[0];
|
||||
if (!startByteHasReprs[ucStart])
|
||||
return false;
|
||||
MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes, len));
|
||||
return it != mapReprs.end();
|
||||
}
|
||||
|
||||
void SpecialRepresentations::Clear() {
|
||||
mapReprs.clear();
|
||||
const short none = 0;
|
||||
std::fill(startByteHasReprs, std::end(startByteHasReprs), none);
|
||||
}
|
||||
|
||||
void BreakFinder::Insert(Sci::Position val) {
|
||||
const int posInLine = static_cast<int>(val);
|
||||
if (posInLine > nextBreak) {
|
||||
const std::vector<int>::iterator it = std::lower_bound(selAndEdge.begin(), selAndEdge.end(), posInLine);
|
||||
if (it == selAndEdge.end()) {
|
||||
selAndEdge.push_back(posInLine);
|
||||
} else if (*it != posInLine) {
|
||||
selAndEdge.insert(it, 1, posInLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BreakFinder::BreakFinder(const LineLayout *ll_, const Selection *psel, Range lineRange_, Sci::Position posLineStart_,
|
||||
int xStart, bool breakForSelection, const Document *pdoc_, const SpecialRepresentations *preprs_, const ViewStyle *pvsDraw) :
|
||||
ll(ll_),
|
||||
lineRange(lineRange_),
|
||||
posLineStart(posLineStart_),
|
||||
nextBreak(static_cast<int>(lineRange_.start)),
|
||||
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), lineRange);
|
||||
// Now back to a style break
|
||||
while ((nextBreak > lineRange.start) && (ll->styles[nextBreak] == ll->styles[nextBreak - 1])) {
|
||||
nextBreak--;
|
||||
}
|
||||
|
||||
if (breakForSelection) {
|
||||
const SelectionPosition posStart(posLineStart);
|
||||
const SelectionPosition posEnd(posLineStart + lineRange.end);
|
||||
const SelectionSegment segmentLine(posStart, posEnd);
|
||||
for (size_t r=0; r<psel->Count(); r++) {
|
||||
const SelectionSegment portion = 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pvsDraw && pvsDraw->indicatorsSetFore) {
|
||||
for (const IDecoration *deco : pdoc->decorations->View()) {
|
||||
if (pvsDraw->indicators[deco->Indicator()].OverridesTextFore()) {
|
||||
Sci::Position startPos = deco->EndRun(posLineStart);
|
||||
while (startPos < (posLineStart + lineRange.end)) {
|
||||
Insert(startPos - posLineStart);
|
||||
startPos = deco->EndRun(startPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Insert(ll->edgeColumn);
|
||||
Insert(lineRange.end);
|
||||
saeNext = (!selAndEdge.empty()) ? selAndEdge[0] : -1;
|
||||
}
|
||||
|
||||
BreakFinder::~BreakFinder() {
|
||||
}
|
||||
|
||||
TextSegment BreakFinder::Next() {
|
||||
if (subBreak == -1) {
|
||||
const int prev = nextBreak;
|
||||
while (nextBreak < lineRange.end) {
|
||||
int charWidth = 1;
|
||||
if (encodingFamily == efUnicode)
|
||||
charWidth = UTF8DrawBytes(reinterpret_cast<unsigned char *>(&ll->chars[nextBreak]),
|
||||
static_cast<int>(lineRange.end - nextBreak));
|
||||
else if (encodingFamily == efDBCS)
|
||||
charWidth = pdoc->DBCSDrawBytes(
|
||||
&ll->chars[nextBreak], static_cast<int>(lineRange.end - nextBreak));
|
||||
const 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 < lineRange.end)) {
|
||||
saeCurrentPos++;
|
||||
saeNext = static_cast<int>((saeCurrentPos < selAndEdge.size()) ? selAndEdge[saeCurrentPos] : lineRange.end);
|
||||
}
|
||||
if ((nextBreak > prev) || repr) {
|
||||
// Have a segment to report
|
||||
if (nextBreak == prev) {
|
||||
nextBreak += charWidth;
|
||||
} else {
|
||||
repr = nullptr; // 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.
|
||||
const 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 < lineRange.end);
|
||||
}
|
||||
|
||||
PositionCacheEntry::PositionCacheEntry() :
|
||||
styleNumber(0), len(0), clock(0), positions(nullptr) {
|
||||
}
|
||||
|
||||
// Copy constructor not currently used, but needed for being element in std::vector.
|
||||
PositionCacheEntry::PositionCacheEntry(const PositionCacheEntry &other) :
|
||||
styleNumber(other.styleNumber), len(other.styleNumber), clock(other.styleNumber), positions(nullptr) {
|
||||
if (other.positions) {
|
||||
const size_t lenData = len + (len / sizeof(XYPOSITION)) + 1;
|
||||
positions.reset(new XYPOSITION[lenData]);
|
||||
memcpy(positions.get(), other.positions.get(), lenData * sizeof(XYPOSITION));
|
||||
}
|
||||
}
|
||||
|
||||
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.reset(new XYPOSITION[len + (len / sizeof(XYPOSITION)) + 1]);
|
||||
for (unsigned int i=0; i<len; i++) {
|
||||
positions[i] = positions_[i];
|
||||
}
|
||||
memcpy(&positions[len], s_, len);
|
||||
}
|
||||
}
|
||||
|
||||
PositionCacheEntry::~PositionCacheEntry() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void PositionCacheEntry::Clear() {
|
||||
positions.reset();
|
||||
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(&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 (PositionCacheEntry &pce : pces) {
|
||||
pce.Clear();
|
||||
}
|
||||
}
|
||||
clock = 1;
|
||||
allClear = true;
|
||||
}
|
||||
|
||||
void PositionCache::SetSize(size_t size_) {
|
||||
Clear();
|
||||
pces.resize(size_);
|
||||
}
|
||||
|
||||
void PositionCache::MeasureWidths(Surface *surface, const ViewStyle &vstyle, unsigned int styleNumber,
|
||||
const char *s, unsigned int len, XYPOSITION *positions, const 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.
|
||||
const unsigned int hashValue = PositionCacheEntry::Hash(styleNumber, s, len);
|
||||
probe = hashValue % pces.size();
|
||||
if (pces[probe].Retrieve(styleNumber, s, len, positions)) {
|
||||
return;
|
||||
}
|
||||
const 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) {
|
||||
const unsigned int lenSegment = pdoc->SafeSegment(s + startSegment, len - startSegment, BreakFinder::lengthEachSubdivision);
|
||||
FontAlias fontStyle = vstyle.styles[styleNumber].font;
|
||||
surface->MeasureWidths(fontStyle, 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 {
|
||||
FontAlias fontStyle = vstyle.styles[styleNumber].font;
|
||||
surface->MeasureWidths(fontStyle, 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 (PositionCacheEntry &pce : pces) {
|
||||
pce.ResetClock();
|
||||
}
|
||||
clock = 2;
|
||||
}
|
||||
pces[probe].Set(styleNumber, s, len, positions, clock);
|
||||
}
|
||||
}
|
||||
247
third_party/qscintilla/scintilla/src/PositionCache.h
vendored
Normal file
247
third_party/qscintilla/scintilla/src/PositionCache.h
vendored
Normal file
@@ -0,0 +1,247 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
inline constexpr bool IsEOLChar(int ch) noexcept {
|
||||
return (ch == '\r') || (ch == '\n');
|
||||
}
|
||||
|
||||
inline constexpr bool IsSpaceOrTab(int ch) noexcept {
|
||||
return ch == ' ' || ch == '\t';
|
||||
}
|
||||
|
||||
/**
|
||||
* A point in document space.
|
||||
* Uses double for sufficient resolution in large (>20,000,000 line) documents.
|
||||
*/
|
||||
class PointDocument {
|
||||
public:
|
||||
double x;
|
||||
double y;
|
||||
|
||||
explicit PointDocument(double x_ = 0, double y_ = 0) noexcept : x(x_), y(y_) {
|
||||
}
|
||||
|
||||
// Conversion from Point.
|
||||
explicit PointDocument(Point pt) noexcept : x(pt.x), y(pt.y) {
|
||||
}
|
||||
};
|
||||
|
||||
// There are two points for some positions and this enumeration
|
||||
// can choose between the end of the first line or subline
|
||||
// and the start of the next line or subline.
|
||||
enum PointEnd {
|
||||
peDefault = 0x0,
|
||||
peLineEnd = 0x1,
|
||||
peSubLineEnd = 0x2
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class LineLayout {
|
||||
private:
|
||||
friend class LineLayoutCache;
|
||||
std::unique_ptr<int []>lineStarts;
|
||||
int lenLineStarts;
|
||||
/// Drawing is only performed for @a maxLineLength characters on each line.
|
||||
Sci::Line lineNumber;
|
||||
bool inCache;
|
||||
public:
|
||||
enum { wrapWidthInfinite = 0x7ffffff };
|
||||
|
||||
int maxLineLength;
|
||||
int numCharsInLine;
|
||||
int numCharsBeforeEOL;
|
||||
enum validLevel { llInvalid, llCheckTextAndStyle, llPositions, llLines } validity;
|
||||
int xHighlightGuide;
|
||||
bool highlightColumn;
|
||||
bool containsCaret;
|
||||
int edgeColumn;
|
||||
std::unique_ptr<char[]> chars;
|
||||
std::unique_ptr<unsigned char[]> styles;
|
||||
std::unique_ptr<XYPOSITION[]> positions;
|
||||
char bracePreviousStyles[2];
|
||||
|
||||
// Hotspot support
|
||||
Range hotspot;
|
||||
|
||||
// Wrapped line support
|
||||
int widthLine;
|
||||
int lines;
|
||||
XYPOSITION wrapIndent; // In pixels
|
||||
|
||||
explicit LineLayout(int maxLineLength_);
|
||||
// Deleted so LineLayout objects can not be copied.
|
||||
LineLayout(const LineLayout &) = delete;
|
||||
LineLayout(LineLayout &&) = delete;
|
||||
void operator=(const LineLayout &) = delete;
|
||||
void operator=(LineLayout &&) = delete;
|
||||
virtual ~LineLayout();
|
||||
void Resize(int maxLineLength_);
|
||||
void Free();
|
||||
void Invalidate(validLevel validity_);
|
||||
int LineStart(int line) const;
|
||||
enum class Scope { visibleOnly, includeEnd };
|
||||
int LineLastVisible(int line, Scope scope) const;
|
||||
Range SubLineRange(int subLine, Scope scope) const;
|
||||
bool InLine(int offset, int line) const;
|
||||
void SetLineStart(int line, int start);
|
||||
void SetBracesHighlight(Range rangeLine, const Sci::Position braces[],
|
||||
char bracesMatchStyle, int xHighlight, bool ignoreStyle);
|
||||
void RestoreBracesHighlight(Range rangeLine, const Sci::Position braces[], bool ignoreStyle);
|
||||
int FindBefore(XYPOSITION x, Range range) const;
|
||||
int FindPositionFromX(XYPOSITION x, Range range, bool charPosition) const;
|
||||
Point PointFromPosition(int posInLine, int lineHeight, PointEnd pe) const;
|
||||
int EndLineStyle() const;
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class LineLayoutCache {
|
||||
int level;
|
||||
std::vector<std::unique_ptr<LineLayout>>cache;
|
||||
bool allInvalidated;
|
||||
int styleClock;
|
||||
int useCount;
|
||||
void Allocate(size_t length_);
|
||||
void AllocateForLevel(Sci::Line linesOnScreen, Sci::Line linesInDoc);
|
||||
public:
|
||||
LineLayoutCache();
|
||||
// Deleted so LineLayoutCache objects can not be copied.
|
||||
LineLayoutCache(const LineLayoutCache &) = delete;
|
||||
LineLayoutCache(LineLayoutCache &&) = delete;
|
||||
void operator=(const LineLayoutCache &) = delete;
|
||||
void operator=(LineLayoutCache &&) = delete;
|
||||
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(Sci::Line lineNumber, Sci::Line lineCaret, int maxChars, int styleClock_,
|
||||
Sci::Line linesOnScreen, Sci::Line linesInDoc);
|
||||
void Dispose(LineLayout *ll);
|
||||
};
|
||||
|
||||
class PositionCacheEntry {
|
||||
unsigned int styleNumber:8;
|
||||
unsigned int len:8;
|
||||
unsigned int clock:16;
|
||||
std::unique_ptr<XYPOSITION []> positions;
|
||||
public:
|
||||
PositionCacheEntry();
|
||||
// Copy constructor not currently used, but needed for being element in std::vector.
|
||||
PositionCacheEntry(const PositionCacheEntry &);
|
||||
// PositionCacheEntry objects should not be moved but MSVC 2015 requires this.
|
||||
PositionCacheEntry(PositionCacheEntry &&) = default;
|
||||
void operator=(const PositionCacheEntry &) = delete;
|
||||
void operator=(PositionCacheEntry &&) = delete;
|
||||
~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<unsigned 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);
|
||||
const Representation *RepresentationFromCharacter(const char *charBytes, size_t len) const;
|
||||
bool Contains(const char *charBytes, size_t len) const;
|
||||
void Clear();
|
||||
};
|
||||
|
||||
struct TextSegment {
|
||||
int start;
|
||||
int length;
|
||||
const Representation *representation;
|
||||
TextSegment(int start_=0, int length_=0, const Representation *representation_=nullptr) noexcept :
|
||||
start(start_), length(length_), representation(representation_) {
|
||||
}
|
||||
int end() const noexcept {
|
||||
return start + length;
|
||||
}
|
||||
};
|
||||
|
||||
// Class to break a line of text into shorter runs at sensible places.
|
||||
class BreakFinder {
|
||||
const LineLayout *ll;
|
||||
Range lineRange;
|
||||
Sci::Position posLineStart;
|
||||
int nextBreak;
|
||||
std::vector<int> selAndEdge;
|
||||
unsigned int saeCurrentPos;
|
||||
int saeNext;
|
||||
int subBreak;
|
||||
const Document *pdoc;
|
||||
EncodingFamily encodingFamily;
|
||||
const SpecialRepresentations *preprs;
|
||||
void Insert(Sci::Position val);
|
||||
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(const LineLayout *ll_, const Selection *psel, Range lineRange_, Sci::Position posLineStart_,
|
||||
int xStart, bool breakForSelection, const Document *pdoc_, const SpecialRepresentations *preprs_, const ViewStyle *pvsDraw);
|
||||
// Deleted so BreakFinder objects can not be copied.
|
||||
BreakFinder(const BreakFinder &) = delete;
|
||||
BreakFinder(BreakFinder &&) = delete;
|
||||
void operator=(const BreakFinder &) = delete;
|
||||
void operator=(BreakFinder &&) = delete;
|
||||
~BreakFinder();
|
||||
TextSegment Next();
|
||||
bool More() const;
|
||||
};
|
||||
|
||||
class PositionCache {
|
||||
std::vector<PositionCacheEntry> pces;
|
||||
unsigned int clock;
|
||||
bool allClear;
|
||||
public:
|
||||
PositionCache();
|
||||
// Deleted so PositionCache objects can not be copied.
|
||||
PositionCache(const PositionCache &) = delete;
|
||||
PositionCache(PositionCache &&) = delete;
|
||||
void operator=(const PositionCache &) = delete;
|
||||
void operator=(PositionCache &&) = delete;
|
||||
~PositionCache();
|
||||
void Clear();
|
||||
void SetSize(size_t size_);
|
||||
size_t GetSize() const { return pces.size(); }
|
||||
void MeasureWidths(Surface *surface, const ViewStyle &vstyle, unsigned int styleNumber,
|
||||
const char *s, unsigned int len, XYPOSITION *positions, const Document *pdoc);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
960
third_party/qscintilla/scintilla/src/RESearch.cpp
vendored
Normal file
960
third_party/qscintilla/scintilla/src/RESearch.cpp
vendored
Normal file
@@ -0,0 +1,960 @@
|
||||
// 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 <cstddef>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
|
||||
#include "Position.h"
|
||||
#include "CharClassify.h"
|
||||
#include "RESearch.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
#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
|
||||
|
||||
static const char bitarr[] = { 1, 2, 4, 8, 16, 32, 64, '\200' };
|
||||
|
||||
#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;
|
||||
sta = NOP; /* status of lastpat */
|
||||
bol = 0;
|
||||
const unsigned char nul=0;
|
||||
std::fill(bittab, std::end(bittab), nul);
|
||||
std::fill(tagstk, std::end(tagstk), 0);
|
||||
std::fill(nfa, std::end(nfa), '\0');
|
||||
Clear();
|
||||
}
|
||||
|
||||
RESearch::~RESearch() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void RESearch::Clear() {
|
||||
for (int i = 0; i < MAXTAG; i++) {
|
||||
pat[i].clear();
|
||||
bopat[i] = NOTFOUND;
|
||||
eopat[i] = NOTFOUND;
|
||||
}
|
||||
}
|
||||
|
||||
void RESearch::GrabMatches(const CharacterIndexer &ci) {
|
||||
for (unsigned int i = 0; i < MAXTAG; i++) {
|
||||
if ((bopat[i] != NOTFOUND) && (eopat[i] != NOTFOUND)) {
|
||||
Sci::Position len = eopat[i] - bopat[i];
|
||||
pat[i].resize(len);
|
||||
for (Sci::Position j = 0; j < len; j++)
|
||||
pat[i][j] = ci.CharAt(bopat[i] + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RESearch::ChSet(unsigned char c) {
|
||||
bittab[((c) & BLKIND) >> 3] |= bitarr[(c) & BITIND];
|
||||
}
|
||||
|
||||
void RESearch::ChSetWithCase(unsigned char c, bool caseSensitive) {
|
||||
ChSet(c);
|
||||
if (!caseSensitive) {
|
||||
if ((c >= 'a') && (c <= 'z')) {
|
||||
ChSet(c - 'a' + 'A');
|
||||
} else if ((c >= 'A') && (c <= 'Z')) {
|
||||
ChSet(c - 'A' + 'a');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static 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;
|
||||
const 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': {
|
||||
const unsigned char hd1 = *(pattern + 1);
|
||||
const unsigned char hd2 = *(pattern + 2);
|
||||
const 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, Sci::Position 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 nullptr;
|
||||
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++ = 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++ = 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++ = 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 nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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(const CharacterIndexer &ci, Sci::Position lp, Sci::Position endp) {
|
||||
unsigned char c;
|
||||
Sci::Position 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;
|
||||
// Falls through.
|
||||
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 up to 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);
|
||||
|
||||
static inline int isinset(const char *ap, unsigned char c) {
|
||||
return ap[(c & BLKIND) >> 3] & bitarr[c & 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 */
|
||||
|
||||
Sci::Position RESearch::PMatch(const CharacterIndexer &ci, Sci::Position lp, Sci::Position endp, char *ap) {
|
||||
int op, c, n;
|
||||
Sci::Position e; /* extra pointer for CLO */
|
||||
Sci::Position bp; /* beginning of subpat... */
|
||||
Sci::Position ep; /* ending of subpat... */
|
||||
Sci::Position are; /* to save the line ptr. */
|
||||
Sci::Position 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;
|
||||
if (!isinset(ap, ci.CharAt(lp++)))
|
||||
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) {
|
||||
Sci::Position 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;
|
||||
}
|
||||
|
||||
|
||||
70
third_party/qscintilla/scintilla/src/RESearch.h
vendored
Normal file
70
third_party/qscintilla/scintilla/src/RESearch.h
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
/*
|
||||
* 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(Sci::Position index) const=0;
|
||||
virtual ~CharacterIndexer() {
|
||||
}
|
||||
};
|
||||
|
||||
class RESearch {
|
||||
|
||||
public:
|
||||
explicit RESearch(CharClassify *charClassTable);
|
||||
// No dynamic allocation so default copy constructor and assignment operator are OK.
|
||||
~RESearch();
|
||||
void Clear();
|
||||
void GrabMatches(const CharacterIndexer &ci);
|
||||
const char *Compile(const char *pattern, Sci::Position length, bool caseSensitive, bool posix);
|
||||
int Execute(const CharacterIndexer &ci, Sci::Position lp, Sci::Position endp);
|
||||
|
||||
enum { MAXTAG=10 };
|
||||
enum { MAXNFA=4096 };
|
||||
enum { NOTFOUND=-1 };
|
||||
|
||||
Sci::Position bopat[MAXTAG];
|
||||
Sci::Position eopat[MAXTAG];
|
||||
std::string pat[MAXTAG];
|
||||
|
||||
private:
|
||||
void ChSet(unsigned char c);
|
||||
void ChSetWithCase(unsigned char c, bool caseSensitive);
|
||||
int GetBackslashExpression(const char *pattern, int &incr);
|
||||
|
||||
Sci::Position PMatch(const CharacterIndexer &ci, Sci::Position lp, Sci::Position endp, char *ap);
|
||||
|
||||
Sci::Position bol;
|
||||
Sci::Position 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);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
314
third_party/qscintilla/scintilla/src/RunStyles.cpp
vendored
Normal file
314
third_party/qscintilla/scintilla/src/RunStyles.cpp
vendored
Normal file
@@ -0,0 +1,314 @@
|
||||
/** @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 <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
#include <climits>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
#include "Position.h"
|
||||
#include "SplitVector.h"
|
||||
#include "Partitioning.h"
|
||||
#include "RunStyles.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
// Find the first run at a position
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
DISTANCE RunStyles<DISTANCE, STYLE>::RunFromPosition(DISTANCE position) const noexcept {
|
||||
DISTANCE 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.
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
DISTANCE RunStyles<DISTANCE, STYLE>::SplitRun(DISTANCE position) {
|
||||
DISTANCE run = RunFromPosition(position);
|
||||
const DISTANCE posRun = starts->PositionFromPartition(run);
|
||||
if (posRun < position) {
|
||||
STYLE runStyle = ValueAt(position);
|
||||
run++;
|
||||
starts->InsertPartition(run, position);
|
||||
styles->InsertValue(run, 1, runStyle);
|
||||
}
|
||||
return run;
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
void RunStyles<DISTANCE, STYLE>::RemoveRun(DISTANCE run) {
|
||||
starts->RemovePartition(run);
|
||||
styles->DeleteRange(run, 1);
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
void RunStyles<DISTANCE, STYLE>::RemoveRunIfEmpty(DISTANCE run) {
|
||||
if ((run < starts->Partitions()) && (starts->Partitions() > 1)) {
|
||||
if (starts->PositionFromPartition(run) == starts->PositionFromPartition(run+1)) {
|
||||
RemoveRun(run);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
void RunStyles<DISTANCE, STYLE>::RemoveRunIfSameAsPrevious(DISTANCE run) {
|
||||
if ((run > 0) && (run < starts->Partitions())) {
|
||||
if (styles->ValueAt(run-1) == styles->ValueAt(run)) {
|
||||
RemoveRun(run);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
RunStyles<DISTANCE, STYLE>::RunStyles() {
|
||||
starts.reset(new Partitioning<DISTANCE>(8));
|
||||
styles.reset(new SplitVector<STYLE>());
|
||||
styles->InsertValue(0, 2, 0);
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
RunStyles<DISTANCE, STYLE>::~RunStyles() {
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
DISTANCE RunStyles<DISTANCE, STYLE>::Length() const noexcept {
|
||||
return starts->PositionFromPartition(starts->Partitions());
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
STYLE RunStyles<DISTANCE, STYLE>::ValueAt(DISTANCE position) const noexcept {
|
||||
return styles->ValueAt(starts->PartitionFromPosition(position));
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
DISTANCE RunStyles<DISTANCE, STYLE>::FindNextChange(DISTANCE position, DISTANCE end) const noexcept {
|
||||
const DISTANCE run = starts->PartitionFromPosition(position);
|
||||
if (run < starts->Partitions()) {
|
||||
const DISTANCE runChange = starts->PositionFromPartition(run);
|
||||
if (runChange > position)
|
||||
return runChange;
|
||||
const DISTANCE nextChange = starts->PositionFromPartition(run + 1);
|
||||
if (nextChange > position) {
|
||||
return nextChange;
|
||||
} else if (position < end) {
|
||||
return end;
|
||||
} else {
|
||||
return end + 1;
|
||||
}
|
||||
} else {
|
||||
return end + 1;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
DISTANCE RunStyles<DISTANCE, STYLE>::StartRun(DISTANCE position) const noexcept {
|
||||
return starts->PositionFromPartition(starts->PartitionFromPosition(position));
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
DISTANCE RunStyles<DISTANCE, STYLE>::EndRun(DISTANCE position) const noexcept {
|
||||
return starts->PositionFromPartition(starts->PartitionFromPosition(position) + 1);
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
FillResult<DISTANCE> RunStyles<DISTANCE, STYLE>::FillRange(DISTANCE position, STYLE value, DISTANCE fillLength) {
|
||||
const FillResult<DISTANCE> resultNoChange{false, position, fillLength};
|
||||
if (fillLength <= 0) {
|
||||
return resultNoChange;
|
||||
}
|
||||
DISTANCE end = position + fillLength;
|
||||
if (end > Length()) {
|
||||
return resultNoChange;
|
||||
}
|
||||
DISTANCE 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 resultNoChange;
|
||||
}
|
||||
fillLength = end - position;
|
||||
} else {
|
||||
runEnd = SplitRun(end);
|
||||
}
|
||||
DISTANCE 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) {
|
||||
const FillResult<DISTANCE> result{ true, position, fillLength };
|
||||
styles->SetValueAt(runStart, value);
|
||||
// Remove each old run over the range
|
||||
for (DISTANCE run=runStart+1; run<runEnd; run++) {
|
||||
RemoveRun(runStart+1);
|
||||
}
|
||||
runEnd = RunFromPosition(end);
|
||||
RemoveRunIfSameAsPrevious(runEnd);
|
||||
RemoveRunIfSameAsPrevious(runStart);
|
||||
runEnd = RunFromPosition(end);
|
||||
RemoveRunIfEmpty(runEnd);
|
||||
return result;
|
||||
} else {
|
||||
return resultNoChange;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
void RunStyles<DISTANCE, STYLE>::SetValueAt(DISTANCE position, STYLE value) {
|
||||
FillRange(position, value, 1);
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
void RunStyles<DISTANCE, STYLE>::InsertSpace(DISTANCE position, DISTANCE insertLength) {
|
||||
DISTANCE runStart = RunFromPosition(position);
|
||||
if (starts->PositionFromPartition(runStart) == position) {
|
||||
STYLE 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, STYLE());
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
void RunStyles<DISTANCE, STYLE>::DeleteAll() {
|
||||
starts.reset(new Partitioning<DISTANCE>(8));
|
||||
styles.reset(new SplitVector<STYLE>());
|
||||
styles->InsertValue(0, 2, 0);
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
void RunStyles<DISTANCE, STYLE>::DeleteRange(DISTANCE position, DISTANCE deleteLength) {
|
||||
DISTANCE end = position + deleteLength;
|
||||
DISTANCE runStart = RunFromPosition(position);
|
||||
DISTANCE 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 (DISTANCE run=runStart; run<runEnd; run++) {
|
||||
RemoveRun(runStart);
|
||||
}
|
||||
RemoveRunIfEmpty(runStart);
|
||||
RemoveRunIfSameAsPrevious(runStart);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
DISTANCE RunStyles<DISTANCE, STYLE>::Runs() const noexcept {
|
||||
return starts->Partitions();
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
bool RunStyles<DISTANCE, STYLE>::AllSame() const noexcept {
|
||||
for (int run = 1; run < starts->Partitions(); run++) {
|
||||
if (styles->ValueAt(run) != styles->ValueAt(run - 1))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
bool RunStyles<DISTANCE, STYLE>::AllSameAs(STYLE value) const noexcept {
|
||||
return AllSame() && (styles->ValueAt(0) == value);
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
DISTANCE RunStyles<DISTANCE, STYLE>::Find(STYLE value, DISTANCE start) const noexcept {
|
||||
if (start < Length()) {
|
||||
DISTANCE 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;
|
||||
}
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
void RunStyles<DISTANCE, STYLE>::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.");
|
||||
}
|
||||
DISTANCE start=0;
|
||||
while (start < Length()) {
|
||||
const DISTANCE 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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template class Scintilla::RunStyles<int, int>;
|
||||
template class Scintilla::RunStyles<int, char>;
|
||||
#if (PTRDIFF_MAX != INT_MAX) || PLAT_HAIKU
|
||||
template class Scintilla::RunStyles<ptrdiff_t, int>;
|
||||
template class Scintilla::RunStyles<ptrdiff_t, char>;
|
||||
#endif
|
||||
64
third_party/qscintilla/scintilla/src/RunStyles.h
vendored
Normal file
64
third_party/qscintilla/scintilla/src/RunStyles.h
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
/** @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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
// Return for RunStyles::FillRange reports if anything was changed and the
|
||||
// range that was changed. This may be trimmed from the requested range
|
||||
// when some of the requested range already had the requested value.
|
||||
template <typename DISTANCE>
|
||||
struct FillResult {
|
||||
bool changed;
|
||||
DISTANCE position;
|
||||
DISTANCE fillLength;
|
||||
};
|
||||
|
||||
template <typename DISTANCE, typename STYLE>
|
||||
class RunStyles {
|
||||
private:
|
||||
std::unique_ptr<Partitioning<DISTANCE>> starts;
|
||||
std::unique_ptr<SplitVector<STYLE>> styles;
|
||||
DISTANCE RunFromPosition(DISTANCE position) const noexcept;
|
||||
DISTANCE SplitRun(DISTANCE position);
|
||||
void RemoveRun(DISTANCE run);
|
||||
void RemoveRunIfEmpty(DISTANCE run);
|
||||
void RemoveRunIfSameAsPrevious(DISTANCE run);
|
||||
public:
|
||||
RunStyles();
|
||||
// Deleted so RunStyles objects can not be copied.
|
||||
RunStyles(const RunStyles &) = delete;
|
||||
RunStyles(RunStyles &&) = delete;
|
||||
void operator=(const RunStyles &) = delete;
|
||||
void operator=(RunStyles &&) = delete;
|
||||
~RunStyles();
|
||||
DISTANCE Length() const noexcept;
|
||||
STYLE ValueAt(DISTANCE position) const noexcept;
|
||||
DISTANCE FindNextChange(DISTANCE position, DISTANCE end) const noexcept;
|
||||
DISTANCE StartRun(DISTANCE position) const noexcept;
|
||||
DISTANCE EndRun(DISTANCE position) const noexcept;
|
||||
// Returns changed=true if some values may have changed
|
||||
FillResult<DISTANCE> FillRange(DISTANCE position, STYLE value, DISTANCE fillLength);
|
||||
void SetValueAt(DISTANCE position, STYLE value);
|
||||
void InsertSpace(DISTANCE position, DISTANCE insertLength);
|
||||
void DeleteAll();
|
||||
void DeleteRange(DISTANCE position, DISTANCE deleteLength);
|
||||
DISTANCE Runs() const noexcept;
|
||||
bool AllSame() const noexcept;
|
||||
bool AllSameAs(STYLE value) const noexcept;
|
||||
DISTANCE Find(STYLE value, DISTANCE start) const noexcept;
|
||||
|
||||
void Check() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
6
third_party/qscintilla/scintilla/src/SciTE.properties
vendored
Normal file
6
third_party/qscintilla/scintilla/src/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
|
||||
1165
third_party/qscintilla/scintilla/src/ScintillaBase.cpp
vendored
Normal file
1165
third_party/qscintilla/scintilla/src/ScintillaBase.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
103
third_party/qscintilla/scintilla/src/ScintillaBase.h
vendored
Normal file
103
third_party/qscintilla/scintilla/src/ScintillaBase.h
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
#ifdef SCI_LEXER
|
||||
class LexState;
|
||||
#endif
|
||||
|
||||
/**
|
||||
*/
|
||||
class ScintillaBase : public Editor, IListBoxDelegate {
|
||||
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
|
||||
};
|
||||
|
||||
enum { maxLenInputIME = 200 };
|
||||
|
||||
int displayPopupMenu;
|
||||
Menu popup;
|
||||
AutoComplete ac;
|
||||
|
||||
CallTip ct;
|
||||
|
||||
int listType; ///< 0 is an autocomplete list
|
||||
int maxListWidth; /// Maximum width of list, in average character widths
|
||||
int multiAutoCMode; /// Mode for autocompleting when multiple selections are present
|
||||
|
||||
#ifdef SCI_LEXER
|
||||
LexState *DocumentLexState();
|
||||
void SetLexer(uptr_t wParam);
|
||||
void SetLexerLanguage(const char *languageName);
|
||||
void Colourise(int start, int end);
|
||||
#endif
|
||||
|
||||
ScintillaBase();
|
||||
// Deleted so ScintillaBase objects can not be copied.
|
||||
ScintillaBase(const ScintillaBase &) = delete;
|
||||
ScintillaBase(ScintillaBase &&) = delete;
|
||||
ScintillaBase &operator=(const ScintillaBase &) = delete;
|
||||
ScintillaBase &operator=(ScintillaBase &&) = delete;
|
||||
~ScintillaBase() override;
|
||||
void Initialise() override {}
|
||||
void Finalise() override;
|
||||
|
||||
void AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS=false) override;
|
||||
void Command(int cmdId);
|
||||
void CancelModes() override;
|
||||
int KeyCommand(unsigned int iMessage) override;
|
||||
|
||||
void AutoCompleteInsert(Sci::Position startPos, Sci::Position removeLen, const char *text, Sci::Position textLen);
|
||||
void AutoCompleteStart(Sci::Position 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(char ch, unsigned int completionMethod);
|
||||
void AutoCompleteMoveToCurrentWord();
|
||||
void AutoCompleteSelection();
|
||||
void ListNotify(ListBoxEvent *plbe) override;
|
||||
|
||||
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;
|
||||
bool ShouldDisplayPopup(Point ptInWindowCoordinates) const;
|
||||
void ContextMenu(Point pt);
|
||||
|
||||
void ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifiers) override;
|
||||
void RightButtonDownWithModifiers(Point pt, unsigned int curTime, int modifiers) override;
|
||||
|
||||
void NotifyStyleToNeeded(Sci::Position endStyleNeeded) override;
|
||||
void NotifyLexerChanged(Document *doc, void *userData) override;
|
||||
|
||||
public:
|
||||
// Public so scintilla_send_message can use it
|
||||
sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
436
third_party/qscintilla/scintilla/src/Selection.cpp
vendored
Normal file
436
third_party/qscintilla/scintilla/src/Selection.cpp
vendored
Normal file
@@ -0,0 +1,436 @@
|
||||
// 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 <cstddef>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
|
||||
#include "Position.h"
|
||||
#include "Selection.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
void SelectionPosition::MoveForInsertDelete(bool insertion, Sci::Position startChange, Sci::Position length) {
|
||||
if (insertion) {
|
||||
if (position == startChange) {
|
||||
const Sci::Position virtualLengthRemove = std::min(length, virtualSpace);
|
||||
virtualSpace -= virtualLengthRemove;
|
||||
position += virtualLengthRemove;
|
||||
} else if (position > startChange) {
|
||||
position += length;
|
||||
}
|
||||
} else {
|
||||
if (position == startChange) {
|
||||
virtualSpace = 0;
|
||||
}
|
||||
if (position > startChange) {
|
||||
const Sci::Position 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;
|
||||
}
|
||||
|
||||
Sci::Position SelectionRange::Length() const {
|
||||
if (anchor > caret) {
|
||||
return anchor.Position() - caret.Position();
|
||||
} else {
|
||||
return caret.Position() - anchor.Position();
|
||||
}
|
||||
}
|
||||
|
||||
void SelectionRange::MoveForInsertDelete(bool insertion, Sci::Position startChange, Sci::Position length) {
|
||||
caret.MoveForInsertDelete(insertion, startChange, length);
|
||||
anchor.MoveForInsertDelete(insertion, startChange, length);
|
||||
}
|
||||
|
||||
bool SelectionRange::Contains(Sci::Position 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(Sci::Position 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 {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
void SelectionRange::Swap() {
|
||||
std::swap(caret, anchor);
|
||||
}
|
||||
|
||||
bool SelectionRange::Trim(SelectionRange range) {
|
||||
const SelectionPosition startRange = range.Start();
|
||||
const 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()) {
|
||||
Sci::Position 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);
|
||||
}
|
||||
|
||||
Sci::Position Selection::MainCaret() const {
|
||||
return ranges[mainRange].caret.Position();
|
||||
}
|
||||
|
||||
Sci::Position 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];
|
||||
}
|
||||
|
||||
const SelectionRange &Selection::Range(size_t r) const {
|
||||
return ranges[r];
|
||||
}
|
||||
|
||||
SelectionRange &Selection::RangeMain() {
|
||||
return ranges[mainRange];
|
||||
}
|
||||
|
||||
const SelectionRange &Selection::RangeMain() const {
|
||||
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 (const SelectionRange &range : ranges) {
|
||||
if (!range.Empty())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SelectionPosition Selection::Last() const {
|
||||
SelectionPosition lastPosition;
|
||||
for (const SelectionRange &range : ranges) {
|
||||
if (lastPosition < range.caret)
|
||||
lastPosition = range.caret;
|
||||
if (lastPosition < range.anchor)
|
||||
lastPosition = range.anchor;
|
||||
}
|
||||
return lastPosition;
|
||||
}
|
||||
|
||||
Sci::Position Selection::Length() const {
|
||||
Sci::Position len = 0;
|
||||
for (const SelectionRange &range : ranges) {
|
||||
len += range.Length();
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void Selection::MovePositions(bool insertion, Sci::Position startChange, Sci::Position length) {
|
||||
for (SelectionRange &range : ranges) {
|
||||
range.MoveForInsertDelete(insertion, startChange, length);
|
||||
}
|
||||
if (selType == selRectangle) {
|
||||
rangeRectangular.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::TrimOtherSelections(size_t r, SelectionRange range) {
|
||||
for (size_t i = 0; i<ranges.size(); ++i) {
|
||||
if (i != r) {
|
||||
ranges[i].Trim(range);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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::DropAdditionalRanges() {
|
||||
SetSelection(RangeMain());
|
||||
}
|
||||
|
||||
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(Sci::Position 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(Sci::Position 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;
|
||||
}
|
||||
|
||||
Sci::Position Selection::VirtualSpaceFor(Sci::Position pos) const {
|
||||
Sci::Position virtualSpace = 0;
|
||||
for (const SelectionRange &range : ranges) {
|
||||
if ((range.caret.Position() == pos) && (virtualSpace < range.caret.VirtualSpace()))
|
||||
virtualSpace = range.caret.VirtualSpace();
|
||||
if ((range.anchor.Position() == pos) && (virtualSpace < range.anchor.VirtualSpace()))
|
||||
virtualSpace = range.anchor.VirtualSpace();
|
||||
}
|
||||
return virtualSpace;
|
||||
}
|
||||
|
||||
void Selection::Clear() {
|
||||
ranges.clear();
|
||||
ranges.emplace_back();
|
||||
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();
|
||||
}
|
||||
|
||||
192
third_party/qscintilla/scintilla/src/Selection.h
vendored
Normal file
192
third_party/qscintilla/scintilla/src/Selection.h
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
class SelectionPosition {
|
||||
Sci::Position position;
|
||||
Sci::Position virtualSpace;
|
||||
public:
|
||||
explicit SelectionPosition(Sci::Position position_=INVALID_POSITION, Sci::Position 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, Sci::Position startChange, Sci::Position 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;
|
||||
Sci::Position Position() const {
|
||||
return position;
|
||||
}
|
||||
void SetPosition(Sci::Position position_) {
|
||||
position = position_;
|
||||
virtualSpace = 0;
|
||||
}
|
||||
Sci::Position VirtualSpace() const {
|
||||
return virtualSpace;
|
||||
}
|
||||
void SetVirtualSpace(Sci::Position virtualSpace_) {
|
||||
PLATFORM_ASSERT(virtualSpace_ < 800000);
|
||||
if (virtualSpace_ >= 0)
|
||||
virtualSpace = virtualSpace_;
|
||||
}
|
||||
void Add(Sci::Position 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(Sci::Position single) : caret(single), anchor(single) {
|
||||
}
|
||||
SelectionRange(SelectionPosition caret_, SelectionPosition anchor_) : caret(caret_), anchor(anchor_) {
|
||||
}
|
||||
SelectionRange(Sci::Position caret_, Sci::Position anchor_) : caret(caret_), anchor(anchor_) {
|
||||
}
|
||||
bool Empty() const {
|
||||
return anchor == caret;
|
||||
}
|
||||
Sci::Position Length() const;
|
||||
// Sci::Position 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);
|
||||
}
|
||||
void MoveForInsertDelete(bool insertion, Sci::Position startChange, Sci::Position length);
|
||||
bool Contains(Sci::Position pos) const;
|
||||
bool Contains(SelectionPosition sp) const;
|
||||
bool ContainsCharacter(Sci::Position posCharacter) const;
|
||||
SelectionSegment Intersect(SelectionSegment check) const;
|
||||
SelectionPosition Start() const {
|
||||
return (anchor < caret) ? anchor : caret;
|
||||
}
|
||||
SelectionPosition End() const {
|
||||
return (anchor < caret) ? caret : anchor;
|
||||
}
|
||||
void Swap();
|
||||
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;
|
||||
Sci::Position MainCaret() const;
|
||||
Sci::Position 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);
|
||||
const SelectionRange &Range(size_t r) const;
|
||||
SelectionRange &RangeMain();
|
||||
const SelectionRange &RangeMain() const;
|
||||
SelectionPosition Start() const;
|
||||
bool MoveExtends() const;
|
||||
void SetMoveExtends(bool moveExtends_);
|
||||
bool Empty() const;
|
||||
SelectionPosition Last() const;
|
||||
Sci::Position Length() const;
|
||||
void MovePositions(bool insertion, Sci::Position startChange, Sci::Position length);
|
||||
void TrimSelection(SelectionRange range);
|
||||
void TrimOtherSelections(size_t r, SelectionRange range);
|
||||
void SetSelection(SelectionRange range);
|
||||
void AddSelection(SelectionRange range);
|
||||
void AddSelectionWithoutTrim(SelectionRange range);
|
||||
void DropSelection(size_t r);
|
||||
void DropAdditionalRanges();
|
||||
void TentativeSelection(SelectionRange range);
|
||||
void CommitTentative();
|
||||
int CharacterInSelection(Sci::Position posCharacter) const;
|
||||
int InSelectionForEOL(Sci::Position pos) const;
|
||||
Sci::Position VirtualSpaceFor(Sci::Position pos) const;
|
||||
void Clear();
|
||||
void RemoveDuplicates();
|
||||
void RotateMain();
|
||||
bool Tentative() const { return tentativeMain; }
|
||||
std::vector<SelectionRange> RangesCopy() const {
|
||||
return ranges;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
156
third_party/qscintilla/scintilla/src/SparseVector.h
vendored
Normal file
156
third_party/qscintilla/scintilla/src/SparseVector.h
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file SparseVector.h
|
||||
** Hold data sparsely associated with elements in a range.
|
||||
**/
|
||||
// Copyright 2016 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef SPARSEVECTOR_H
|
||||
#define SPARSEVECTOR_H
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
// SparseVector is similar to RunStyles but is more efficient for cases where values occur
|
||||
// for one position instead of over a range of positions.
|
||||
template <typename T>
|
||||
class SparseVector {
|
||||
private:
|
||||
std::unique_ptr<Partitioning<Sci::Position>> starts;
|
||||
std::unique_ptr<SplitVector<T>> values;
|
||||
T empty;
|
||||
void ClearValue(Sci::Position partition) {
|
||||
values->SetValueAt(partition, T());
|
||||
}
|
||||
public:
|
||||
SparseVector() : empty() {
|
||||
starts = std::unique_ptr<Partitioning<Sci::Position>>(new Partitioning<Sci::Position>(8));
|
||||
values = std::unique_ptr<SplitVector<T>>(new SplitVector<T>());
|
||||
values->InsertEmpty(0, 2);
|
||||
}
|
||||
// Deleted so SparseVector objects can not be copied.
|
||||
SparseVector(const SparseVector &) = delete;
|
||||
SparseVector(SparseVector &&) = delete;
|
||||
void operator=(const SparseVector &) = delete;
|
||||
void operator=(SparseVector &&) = delete;
|
||||
~SparseVector() {
|
||||
starts.reset();
|
||||
// starts dead here but not used by ClearValue.
|
||||
for (Sci::Position part = 0; part < values->Length(); part++) {
|
||||
ClearValue(part);
|
||||
}
|
||||
values.reset();
|
||||
}
|
||||
Sci::Position Length() const {
|
||||
return starts->PositionFromPartition(starts->Partitions());
|
||||
}
|
||||
Sci::Position Elements() const {
|
||||
return starts->Partitions();
|
||||
}
|
||||
Sci::Position PositionOfElement(int element) const {
|
||||
return starts->PositionFromPartition(element);
|
||||
}
|
||||
const T& ValueAt(Sci::Position position) const {
|
||||
assert(position < Length());
|
||||
const Sci::Position partition = starts->PartitionFromPosition(position);
|
||||
const Sci::Position startPartition = starts->PositionFromPartition(partition);
|
||||
if (startPartition == position) {
|
||||
return values->ValueAt(partition);
|
||||
} else {
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
template <typename ParamType>
|
||||
void SetValueAt(Sci::Position position, ParamType &&value) {
|
||||
assert(position < Length());
|
||||
const Sci::Position partition = starts->PartitionFromPosition(position);
|
||||
const Sci::Position startPartition = starts->PositionFromPartition(partition);
|
||||
if (value == T()) {
|
||||
// Setting the empty value is equivalent to deleting the position
|
||||
if (position == 0) {
|
||||
ClearValue(partition);
|
||||
} else if (position == startPartition) {
|
||||
// Currently an element at this position, so remove
|
||||
ClearValue(partition);
|
||||
starts->RemovePartition(partition);
|
||||
values->Delete(partition);
|
||||
}
|
||||
// Else element remains empty
|
||||
} else {
|
||||
if (position == startPartition) {
|
||||
// Already a value at this position, so replace
|
||||
ClearValue(partition);
|
||||
values->SetValueAt(partition, std::forward<ParamType>(value));
|
||||
} else {
|
||||
// Insert a new element
|
||||
starts->InsertPartition(partition + 1, position);
|
||||
values->Insert(partition + 1, std::forward<ParamType>(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
void InsertSpace(Sci::Position position, Sci::Position insertLength) {
|
||||
assert(position <= Length()); // Only operation that works at end.
|
||||
const Sci::Position partition = starts->PartitionFromPosition(position);
|
||||
const Sci::Position startPartition = starts->PositionFromPartition(partition);
|
||||
if (startPartition == position) {
|
||||
const bool positionOccupied = values->ValueAt(partition) != T();
|
||||
// Inserting at start of run so make previous longer
|
||||
if (partition == 0) {
|
||||
// Inserting at start of document so ensure start empty
|
||||
if (positionOccupied) {
|
||||
starts->InsertPartition(1, 0);
|
||||
values->InsertEmpty(0, 1);
|
||||
}
|
||||
starts->InsertText(partition, insertLength);
|
||||
} else {
|
||||
if (positionOccupied) {
|
||||
starts->InsertText(partition - 1, insertLength);
|
||||
} else {
|
||||
// Insert at end of run so do not extend style
|
||||
starts->InsertText(partition, insertLength);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
starts->InsertText(partition, insertLength);
|
||||
}
|
||||
}
|
||||
void DeletePosition(Sci::Position position) {
|
||||
assert(position < Length());
|
||||
Sci::Position partition = starts->PartitionFromPosition(position);
|
||||
const Sci::Position startPartition = starts->PositionFromPartition(partition);
|
||||
if (startPartition == position) {
|
||||
if (partition == 0) {
|
||||
ClearValue(0);
|
||||
} else if (partition == starts->Partitions()) {
|
||||
// This should not be possible
|
||||
ClearValue(partition);
|
||||
throw std::runtime_error("SparseVector: deleting end partition.");
|
||||
} else {
|
||||
ClearValue(partition);
|
||||
starts->RemovePartition(partition);
|
||||
values->Delete(partition);
|
||||
// Its the previous partition now that gets smaller
|
||||
partition--;
|
||||
}
|
||||
}
|
||||
starts->InsertText(partition, -1);
|
||||
}
|
||||
void Check() const {
|
||||
if (Length() < 0) {
|
||||
throw std::runtime_error("SparseVector: Length can not be negative.");
|
||||
}
|
||||
if (starts->Partitions() < 1) {
|
||||
throw std::runtime_error("SparseVector: Must always have 1 or more partitions.");
|
||||
}
|
||||
if (starts->Partitions() != values->Length() - 1) {
|
||||
throw std::runtime_error("SparseVector: Partitions and values different lengths.");
|
||||
}
|
||||
// The final element can not be set
|
||||
if (values->ValueAt(values->Length() - 1) != T()) {
|
||||
throw std::runtime_error("SparseVector: Unused style at end changed.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
332
third_party/qscintilla/scintilla/src/SplitVector.h
vendored
Normal file
332
third_party/qscintilla/scintilla/src/SplitVector.h
vendored
Normal file
@@ -0,0 +1,332 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
template <typename T>
|
||||
class SplitVector {
|
||||
protected:
|
||||
std::vector<T> body;
|
||||
T empty; /// Returned as the result of out-of-bounds access.
|
||||
ptrdiff_t lengthBody;
|
||||
ptrdiff_t part1Length;
|
||||
ptrdiff_t gapLength; /// invariant: gapLength == body.size() - lengthBody
|
||||
ptrdiff_t 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(ptrdiff_t position) noexcept {
|
||||
if (position != part1Length) {
|
||||
if (position < part1Length) {
|
||||
// Moving the gap towards start so moving elements towards end
|
||||
std::move_backward(
|
||||
body.data() + position,
|
||||
body.data() + part1Length,
|
||||
body.data() + gapLength + part1Length);
|
||||
} else { // position > part1Length
|
||||
// Moving the gap towards end so moving elements towards start
|
||||
std::move(
|
||||
body.data() + part1Length + gapLength,
|
||||
body.data() + gapLength + position,
|
||||
body.data() + part1Length);
|
||||
}
|
||||
part1Length = position;
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that there is room in the buffer for an insertion,
|
||||
/// reallocating if more space needed.
|
||||
void RoomFor(ptrdiff_t insertionLength) {
|
||||
if (gapLength <= insertionLength) {
|
||||
while (growSize < static_cast<ptrdiff_t>(body.size() / 6))
|
||||
growSize *= 2;
|
||||
ReAllocate(body.size() + insertionLength + growSize);
|
||||
}
|
||||
}
|
||||
|
||||
void Init() {
|
||||
body.clear();
|
||||
body.shrink_to_fit();
|
||||
lengthBody = 0;
|
||||
part1Length = 0;
|
||||
gapLength = 0;
|
||||
growSize = 8;
|
||||
}
|
||||
|
||||
public:
|
||||
/// Construct a split buffer.
|
||||
SplitVector() : empty(), lengthBody(0), part1Length(0), gapLength(0), growSize(8) {
|
||||
}
|
||||
|
||||
// Deleted so SplitVector objects can not be copied.
|
||||
SplitVector(const SplitVector &) = delete;
|
||||
SplitVector(SplitVector &&) = delete;
|
||||
void operator=(const SplitVector &) = delete;
|
||||
void operator=(SplitVector &&) = delete;
|
||||
|
||||
~SplitVector() {
|
||||
}
|
||||
|
||||
ptrdiff_t GetGrowSize() const {
|
||||
return growSize;
|
||||
}
|
||||
|
||||
void SetGrowSize(ptrdiff_t 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(ptrdiff_t newSize) {
|
||||
if (newSize < 0)
|
||||
throw std::runtime_error("SplitVector::ReAllocate: negative size.");
|
||||
|
||||
if (newSize > static_cast<ptrdiff_t>(body.size())) {
|
||||
// Move the gap to the end
|
||||
GapTo(lengthBody);
|
||||
gapLength += newSize - static_cast<ptrdiff_t>(body.size());
|
||||
// RoomFor implements a growth strategy but so does vector::resize so
|
||||
// ensure vector::resize allocates exactly the amount wanted by
|
||||
// calling reserve first.
|
||||
body.reserve(newSize);
|
||||
body.resize(newSize);
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve the element at a particular position.
|
||||
/// Retrieving positions outside the range of the buffer returns empty or 0.
|
||||
const T& ValueAt(ptrdiff_t position) const noexcept {
|
||||
if (position < part1Length) {
|
||||
if (position < 0) {
|
||||
return empty;
|
||||
} else {
|
||||
return body[position];
|
||||
}
|
||||
} else {
|
||||
if (position >= lengthBody) {
|
||||
return empty;
|
||||
} else {
|
||||
return body[gapLength + position];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the element at a particular position.
|
||||
/// Setting positions outside the range of the buffer performs no assignment
|
||||
/// but asserts in debug builds.
|
||||
template <typename ParamType>
|
||||
void SetValueAt(ptrdiff_t position, ParamType&& v) noexcept {
|
||||
if (position < part1Length) {
|
||||
PLATFORM_ASSERT(position >= 0);
|
||||
if (position < 0) {
|
||||
;
|
||||
} else {
|
||||
body[position] = std::forward<ParamType>(v);
|
||||
}
|
||||
} else {
|
||||
PLATFORM_ASSERT(position < lengthBody);
|
||||
if (position >= lengthBody) {
|
||||
;
|
||||
} else {
|
||||
body[gapLength + position] = std::forward<ParamType>(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve the element at a particular position.
|
||||
/// The position must be within bounds or an assertion is triggered.
|
||||
const T &operator[](ptrdiff_t position) const noexcept {
|
||||
PLATFORM_ASSERT(position >= 0 && position < lengthBody);
|
||||
if (position < part1Length) {
|
||||
return body[position];
|
||||
} else {
|
||||
return body[gapLength + position];
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve reference to the element at a particular position.
|
||||
/// This, instead of the const variant, can be used to mutate in-place.
|
||||
/// The position must be within bounds or an assertion is triggered.
|
||||
T &operator[](ptrdiff_t position) noexcept {
|
||||
PLATFORM_ASSERT(position >= 0 && position < lengthBody);
|
||||
if (position < part1Length) {
|
||||
return body[position];
|
||||
} else {
|
||||
return body[gapLength + position];
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve the length of the buffer.
|
||||
ptrdiff_t Length() const noexcept {
|
||||
return lengthBody;
|
||||
}
|
||||
|
||||
/// Insert a single value into the buffer.
|
||||
/// Inserting at positions outside the current range fails.
|
||||
void Insert(ptrdiff_t position, T v) {
|
||||
PLATFORM_ASSERT((position >= 0) && (position <= lengthBody));
|
||||
if ((position < 0) || (position > lengthBody)) {
|
||||
return;
|
||||
}
|
||||
RoomFor(1);
|
||||
GapTo(position);
|
||||
body[part1Length] = std::move(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(ptrdiff_t position, ptrdiff_t 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.data() + part1Length, body.data() + part1Length + insertLength, v);
|
||||
lengthBody += insertLength;
|
||||
part1Length += insertLength;
|
||||
gapLength -= insertLength;
|
||||
}
|
||||
}
|
||||
|
||||
/// Add some new empty elements.
|
||||
/// InsertValue is good for value objects but not for unique_ptr objects
|
||||
/// since they can only be moved from once.
|
||||
void InsertEmpty(ptrdiff_t position, ptrdiff_t insertLength) {
|
||||
PLATFORM_ASSERT((position >= 0) && (position <= lengthBody));
|
||||
if (insertLength > 0) {
|
||||
if ((position < 0) || (position > lengthBody)) {
|
||||
return;
|
||||
}
|
||||
RoomFor(insertLength);
|
||||
GapTo(position);
|
||||
for (ptrdiff_t elem = part1Length; elem < part1Length + insertLength; elem++) {
|
||||
T emptyOne = {};
|
||||
body[elem] = std::move(emptyOne);
|
||||
}
|
||||
lengthBody += insertLength;
|
||||
part1Length += insertLength;
|
||||
gapLength -= insertLength;
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensure at least length elements allocated,
|
||||
/// appending zero valued elements if needed.
|
||||
void EnsureLength(ptrdiff_t wantedLength) {
|
||||
if (Length() < wantedLength) {
|
||||
InsertEmpty(Length(), wantedLength - Length());
|
||||
}
|
||||
}
|
||||
|
||||
/// Insert text into the buffer from an array.
|
||||
void InsertFromArray(ptrdiff_t positionToInsert, const T s[], ptrdiff_t positionFrom, ptrdiff_t insertLength) {
|
||||
PLATFORM_ASSERT((positionToInsert >= 0) && (positionToInsert <= lengthBody));
|
||||
if (insertLength > 0) {
|
||||
if ((positionToInsert < 0) || (positionToInsert > lengthBody)) {
|
||||
return;
|
||||
}
|
||||
RoomFor(insertLength);
|
||||
GapTo(positionToInsert);
|
||||
std::copy(s + positionFrom, s + positionFrom + insertLength, body.data() + part1Length);
|
||||
lengthBody += insertLength;
|
||||
part1Length += insertLength;
|
||||
gapLength -= insertLength;
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete one element from the buffer.
|
||||
void Delete(ptrdiff_t position) {
|
||||
PLATFORM_ASSERT((position >= 0) && (position < lengthBody));
|
||||
DeleteRange(position, 1);
|
||||
}
|
||||
|
||||
/// Delete a range from the buffer.
|
||||
/// Deleting positions outside the current range fails.
|
||||
/// Cannot be noexcept as vector::shrink_to_fit may be called and it may throw.
|
||||
void DeleteRange(ptrdiff_t position, ptrdiff_t 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
|
||||
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, ptrdiff_t position, ptrdiff_t retrieveLength) const noexcept {
|
||||
// Split into up to 2 ranges, before and after the split then use memcpy on each.
|
||||
ptrdiff_t range1Length = 0;
|
||||
if (position < part1Length) {
|
||||
const ptrdiff_t part1AfterPosition = part1Length - position;
|
||||
range1Length = retrieveLength;
|
||||
if (range1Length > part1AfterPosition)
|
||||
range1Length = part1AfterPosition;
|
||||
}
|
||||
std::copy(body.data() + position, body.data() + position + range1Length, buffer);
|
||||
buffer += range1Length;
|
||||
position = position + range1Length + gapLength;
|
||||
ptrdiff_t range2Length = retrieveLength - range1Length;
|
||||
std::copy(body.data() + position, body.data() + position + range2Length, buffer);
|
||||
}
|
||||
|
||||
/// Compact the buffer and return a pointer to the first element.
|
||||
/// Also ensures there is an empty element beyond logical end in case its
|
||||
/// passed to a function expecting a NUL terminated string.
|
||||
T *BufferPointer() {
|
||||
RoomFor(1);
|
||||
GapTo(lengthBody);
|
||||
T emptyOne = {};
|
||||
body[lengthBody] = std::move(emptyOne);
|
||||
return body.data();
|
||||
}
|
||||
|
||||
/// Return a pointer to a range of elements, first rearranging the buffer if
|
||||
/// needed to make that range contiguous.
|
||||
T *RangePointer(ptrdiff_t position, ptrdiff_t rangeLength) noexcept {
|
||||
if (position < part1Length) {
|
||||
if ((position + rangeLength) > part1Length) {
|
||||
// Range overlaps gap, so move gap to start of range.
|
||||
GapTo(position);
|
||||
return body.data() + position + gapLength;
|
||||
} else {
|
||||
return body.data() + position;
|
||||
}
|
||||
} else {
|
||||
return body.data() + position + gapLength;
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the position of the gap within the buffer.
|
||||
ptrdiff_t GapPosition() const noexcept {
|
||||
return part1Length;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
168
third_party/qscintilla/scintilla/src/Style.cpp
vendored
Normal file
168
third_party/qscintilla/scintilla/src/Style.cpp
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
// 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 <stdexcept>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
#include "Style.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
FontAlias::FontAlias() {
|
||||
}
|
||||
|
||||
FontAlias::FontAlias(const FontAlias &other) : Font() {
|
||||
SetID(other.fid);
|
||||
}
|
||||
|
||||
FontAlias::~FontAlias() {
|
||||
SetID(0);
|
||||
// ~Font will not release the actual font resource since it is now 0
|
||||
}
|
||||
|
||||
void FontAlias::MakeAlias(const 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() {
|
||||
ClearMeasurements();
|
||||
}
|
||||
|
||||
void FontMeasurements::ClearMeasurements() {
|
||||
ascent = 1;
|
||||
descent = 1;
|
||||
capitalHeight = 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, nullptr, 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, nullptr, 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, nullptr, 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::ClearMeasurements();
|
||||
}
|
||||
|
||||
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_);
|
||||
(FontMeasurements &)(*this) = fm_;
|
||||
}
|
||||
92
third_party/qscintilla/scintilla/src/Style.h
vendored
Normal file
92
third_party/qscintilla/scintilla/src/Style.h
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
struct FontSpecification {
|
||||
const char *fontName;
|
||||
int weight;
|
||||
bool italic;
|
||||
int size;
|
||||
int characterSet;
|
||||
int extraFontFlag;
|
||||
FontSpecification() :
|
||||
fontName(nullptr),
|
||||
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 {
|
||||
public:
|
||||
FontAlias();
|
||||
// FontAlias objects can not be assigned except for initialization
|
||||
FontAlias(const FontAlias &);
|
||||
FontAlias(FontAlias &&) = delete;
|
||||
FontAlias &operator=(const FontAlias &) = delete;
|
||||
FontAlias &operator=(FontAlias &&) = delete;
|
||||
~FontAlias() override;
|
||||
void MakeAlias(const Font &fontOrigin);
|
||||
void ClearFont();
|
||||
};
|
||||
|
||||
struct FontMeasurements {
|
||||
unsigned int ascent;
|
||||
unsigned int descent;
|
||||
XYPOSITION capitalHeight; // Top of capital letter to baseline: ascent - internal leading
|
||||
XYPOSITION aveCharWidth;
|
||||
XYPOSITION spaceWidth;
|
||||
int sizeZoomed;
|
||||
FontMeasurements();
|
||||
void ClearMeasurements();
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class Style : public FontSpecification, public FontMeasurements {
|
||||
public:
|
||||
ColourDesired fore;
|
||||
ColourDesired back;
|
||||
bool eolFilled;
|
||||
bool underline;
|
||||
enum ecaseForced {caseMixed, caseUpper, caseLower, caseCamel};
|
||||
ecaseForced caseForce;
|
||||
bool visible;
|
||||
bool changeable;
|
||||
bool hotspot;
|
||||
|
||||
FontAlias font;
|
||||
|
||||
Style();
|
||||
Style(const Style &source);
|
||||
Style(Style &&) = default;
|
||||
~Style();
|
||||
Style &operator=(const Style &source);
|
||||
Style &operator=(Style &&) = delete;
|
||||
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);}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
368
third_party/qscintilla/scintilla/src/UniConversion.cpp
vendored
Normal file
368
third_party/qscintilla/scintilla/src/UniConversion.cpp
vendored
Normal file
@@ -0,0 +1,368 @@
|
||||
// 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 <cstdlib>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include "UniConversion.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
size_t UTF8Length(const wchar_t *uptr, size_t tlen) {
|
||||
size_t len = 0;
|
||||
for (size_t i = 0; i < tlen && uptr[i];) {
|
||||
const 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, size_t tlen, char *putf, size_t len) {
|
||||
size_t k = 0;
|
||||
for (size_t i = 0; i < tlen && uptr[i];) {
|
||||
const 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++;
|
||||
const 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++;
|
||||
}
|
||||
if (k < len)
|
||||
putf[k] = '\0';
|
||||
}
|
||||
|
||||
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';
|
||||
}
|
||||
|
||||
size_t UTF16Length(const char *s, size_t len) {
|
||||
size_t ulen = 0;
|
||||
for (size_t i = 0; i < len;) {
|
||||
const unsigned char ch = s[i];
|
||||
const unsigned int byteCount = UTF8BytesOfLead[ch];
|
||||
const unsigned int utf16Len = UTF16LengthFromUTF8ByteCount(byteCount);
|
||||
i += byteCount;
|
||||
ulen += (i > len) ? 1 : utf16Len;
|
||||
}
|
||||
return ulen;
|
||||
}
|
||||
|
||||
constexpr unsigned char TrailByteValue(unsigned char c) {
|
||||
// The top 2 bits are 0b10 to indicate a trail byte.
|
||||
// The lower 6 bits contain the value.
|
||||
return c & 0x3F;
|
||||
}
|
||||
|
||||
size_t UTF16FromUTF8(const char *s, size_t len, wchar_t *tbuf, size_t tlen) {
|
||||
size_t ui = 0;
|
||||
for (size_t i = 0; i < len;) {
|
||||
unsigned char ch = s[i];
|
||||
const unsigned int byteCount = UTF8BytesOfLead[ch];
|
||||
unsigned int value;
|
||||
|
||||
if (i + byteCount > len) {
|
||||
// Trying to read past end but still have space to write
|
||||
if (ui < tlen) {
|
||||
tbuf[ui] = ch;
|
||||
ui++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
const size_t outLen = UTF16LengthFromUTF8ByteCount(byteCount);
|
||||
if (ui + outLen > tlen) {
|
||||
throw std::runtime_error("UTF16FromUTF8: attempted write beyond end");
|
||||
}
|
||||
|
||||
i++;
|
||||
switch (byteCount) {
|
||||
case 1:
|
||||
tbuf[ui] = ch;
|
||||
break;
|
||||
case 2:
|
||||
value = (ch & 0x1F) << 6;
|
||||
ch = s[i++];
|
||||
value += TrailByteValue(ch);
|
||||
tbuf[ui] = static_cast<wchar_t>(value);
|
||||
break;
|
||||
case 3:
|
||||
value = (ch & 0xF) << 12;
|
||||
ch = s[i++];
|
||||
value += (TrailByteValue(ch) << 6);
|
||||
ch = s[i++];
|
||||
value += TrailByteValue(ch);
|
||||
tbuf[ui] = static_cast<wchar_t>(value);
|
||||
break;
|
||||
default:
|
||||
// Outside the BMP so need two surrogates
|
||||
value = (ch & 0x7) << 18;
|
||||
ch = s[i++];
|
||||
value += TrailByteValue(ch) << 12;
|
||||
ch = s[i++];
|
||||
value += TrailByteValue(ch) << 6;
|
||||
ch = s[i++];
|
||||
value += TrailByteValue(ch);
|
||||
tbuf[ui] = static_cast<wchar_t>(((value - 0x10000) >> 10) + SURROGATE_LEAD_FIRST);
|
||||
ui++;
|
||||
tbuf[ui] = static_cast<wchar_t>((value & 0x3ff) + SURROGATE_TRAIL_FIRST);
|
||||
break;
|
||||
}
|
||||
ui++;
|
||||
}
|
||||
return ui;
|
||||
}
|
||||
|
||||
size_t UTF32FromUTF8(const char *s, size_t len, unsigned int *tbuf, size_t tlen) {
|
||||
size_t ui = 0;
|
||||
for (size_t i = 0; i < len;) {
|
||||
unsigned char ch = s[i];
|
||||
const unsigned int byteCount = UTF8BytesOfLead[ch];
|
||||
unsigned int value;
|
||||
|
||||
if (i + byteCount > len) {
|
||||
// Trying to read past end but still have space to write
|
||||
if (ui < tlen) {
|
||||
tbuf[ui] = ch;
|
||||
ui++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (ui == tlen) {
|
||||
throw std::runtime_error("UTF32FromUTF8: attempted write beyond end");
|
||||
}
|
||||
|
||||
i++;
|
||||
switch (byteCount) {
|
||||
case 1:
|
||||
value = ch;
|
||||
break;
|
||||
case 2:
|
||||
value = (ch & 0x1F) << 6;
|
||||
ch = s[i++];
|
||||
value += TrailByteValue(ch);
|
||||
break;
|
||||
case 3:
|
||||
value = (ch & 0xF) << 12;
|
||||
ch = s[i++];
|
||||
value += TrailByteValue(ch) << 6;
|
||||
ch = s[i++];
|
||||
value += TrailByteValue(ch);
|
||||
break;
|
||||
default:
|
||||
value = (ch & 0x7) << 18;
|
||||
ch = s[i++];
|
||||
value += TrailByteValue(ch) << 12;
|
||||
ch = s[i++];
|
||||
value += TrailByteValue(ch) << 6;
|
||||
ch = s[i++];
|
||||
value += TrailByteValue(ch);
|
||||
break;
|
||||
}
|
||||
tbuf[ui] = value;
|
||||
ui++;
|
||||
}
|
||||
return ui;
|
||||
}
|
||||
|
||||
unsigned int UTF16FromUTF32Character(unsigned int val, wchar_t *tbuf) noexcept {
|
||||
if (val < SUPPLEMENTAL_PLANE_FIRST) {
|
||||
tbuf[0] = static_cast<wchar_t>(val);
|
||||
return 1;
|
||||
} else {
|
||||
tbuf[0] = static_cast<wchar_t>(((val - SUPPLEMENTAL_PLANE_FIRST) >> 10) + SURROGATE_LEAD_FIRST);
|
||||
tbuf[1] = static_cast<wchar_t>((val & 0x3ff) + SURROGATE_TRAIL_FIRST);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned char UTF8BytesOfLead[256] = {
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 00 - 0F
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 10 - 1F
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 20 - 2F
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 30 - 3F
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 40 - 4F
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 50 - 5F
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 60 - 6F
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 70 - 7F
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 80 - 8F
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 90 - 9F
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A0 - AF
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B0 - BF
|
||||
1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0 - CF
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // D0 - DF
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // E0 - EF
|
||||
4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // F0 - FF
|
||||
};
|
||||
|
||||
// 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, size_t len) noexcept {
|
||||
// For the rules: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
if (us[0] < 0x80) {
|
||||
// ASCII
|
||||
return 1;
|
||||
}
|
||||
|
||||
const size_t byteCount = UTF8BytesOfLead[us[0]];
|
||||
if (byteCount == 1 || byteCount > len) {
|
||||
// Invalid lead byte
|
||||
return UTF8MaskInvalid | 1;
|
||||
}
|
||||
|
||||
if (!UTF8IsTrailByte(us[1])) {
|
||||
// Invalid trail byte
|
||||
return UTF8MaskInvalid | 1;
|
||||
}
|
||||
|
||||
switch (byteCount) {
|
||||
case 2:
|
||||
return 2;
|
||||
|
||||
case 3:
|
||||
if (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;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (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 == 0xf0) && ((us[1] & 0xf0) == 0x80)) {
|
||||
// Overlong
|
||||
return UTF8MaskInvalid | 1;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return UTF8MaskInvalid | 1;
|
||||
}
|
||||
|
||||
int UTF8DrawBytes(const unsigned char *us, int len) noexcept {
|
||||
const int utf8StatusNext = UTF8Classify(us, len);
|
||||
return (utf8StatusNext & UTF8MaskInvalid) ? 1 : (utf8StatusNext & UTF8MaskWidth);
|
||||
}
|
||||
|
||||
bool UTF8IsValid(const char *s, size_t len) noexcept {
|
||||
const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
|
||||
size_t remaining = len;
|
||||
while (remaining > 0) {
|
||||
const int utf8Status = UTF8Classify(us, remaining);
|
||||
if (utf8Status & UTF8MaskInvalid) {
|
||||
return false;
|
||||
} else {
|
||||
const int lenChar = utf8Status & UTF8MaskWidth;
|
||||
us += lenChar;
|
||||
remaining -= lenChar;
|
||||
}
|
||||
}
|
||||
return remaining == 0;
|
||||
}
|
||||
|
||||
// Replace invalid bytes in UTF-8 with the replacement character
|
||||
std::string FixInvalidUTF8(const std::string &text) {
|
||||
std::string result;
|
||||
const char *s = text.c_str();
|
||||
size_t remaining = text.size();
|
||||
while (remaining > 0) {
|
||||
const int utf8Status = UTF8Classify(reinterpret_cast<const unsigned char *>(s), remaining);
|
||||
if (utf8Status & UTF8MaskInvalid) {
|
||||
// Replacement character 0xFFFD = UTF8:"efbfbd".
|
||||
result.append("\xef\xbf\xbd");
|
||||
s++;
|
||||
remaining--;
|
||||
} else {
|
||||
const size_t len = utf8Status & UTF8MaskWidth;
|
||||
result.append(s, len);
|
||||
s += len;
|
||||
remaining -= len;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
86
third_party/qscintilla/scintilla/src/UniConversion.h
vendored
Normal file
86
third_party/qscintilla/scintilla/src/UniConversion.h
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
const int UTF8MaxBytes = 4;
|
||||
|
||||
const int unicodeReplacementChar = 0xFFFD;
|
||||
|
||||
size_t UTF8Length(const wchar_t *uptr, size_t tlen);
|
||||
void UTF8FromUTF16(const wchar_t *uptr, size_t tlen, char *putf, size_t len);
|
||||
void UTF8FromUTF32Character(int uch, char *putf);
|
||||
size_t UTF16Length(const char *s, size_t len);
|
||||
size_t UTF16FromUTF8(const char *s, size_t len, wchar_t *tbuf, size_t tlen);
|
||||
size_t UTF32FromUTF8(const char *s, size_t len, unsigned int *tbuf, size_t tlen);
|
||||
unsigned int UTF16FromUTF32Character(unsigned int val, wchar_t *tbuf) noexcept;
|
||||
bool UTF8IsValid(const char *s, size_t len) noexcept;
|
||||
std::string FixInvalidUTF8(const std::string &text);
|
||||
|
||||
extern const unsigned char UTF8BytesOfLead[256];
|
||||
|
||||
inline int UnicodeFromUTF8(const unsigned char *us) noexcept {
|
||||
switch (UTF8BytesOfLead[us[0]]) {
|
||||
case 1:
|
||||
return us[0];
|
||||
case 2:
|
||||
return ((us[0] & 0x1F) << 6) + (us[1] & 0x3F);
|
||||
case 3:
|
||||
return ((us[0] & 0xF) << 12) + ((us[1] & 0x3F) << 6) + (us[2] & 0x3F);
|
||||
default:
|
||||
return ((us[0] & 0x7) << 18) + ((us[1] & 0x3F) << 12) + ((us[2] & 0x3F) << 6) + (us[3] & 0x3F);
|
||||
}
|
||||
}
|
||||
|
||||
inline constexpr bool UTF8IsTrailByte(unsigned char ch) noexcept {
|
||||
return (ch >= 0x80) && (ch < 0xc0);
|
||||
}
|
||||
|
||||
inline constexpr bool UTF8IsAscii(int ch) noexcept {
|
||||
return ch < 0x80;
|
||||
}
|
||||
|
||||
enum { UTF8MaskWidth=0x7, UTF8MaskInvalid=0x8 };
|
||||
int UTF8Classify(const unsigned char *us, size_t len) noexcept;
|
||||
|
||||
// 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) noexcept;
|
||||
|
||||
// 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) noexcept {
|
||||
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) noexcept {
|
||||
return (us[0] == 0xc2) && (us[1] == 0x85);
|
||||
}
|
||||
|
||||
enum { SURROGATE_LEAD_FIRST = 0xD800 };
|
||||
enum { SURROGATE_LEAD_LAST = 0xDBFF };
|
||||
enum { SURROGATE_TRAIL_FIRST = 0xDC00 };
|
||||
enum { SURROGATE_TRAIL_LAST = 0xDFFF };
|
||||
enum { SUPPLEMENTAL_PLANE_FIRST = 0x10000 };
|
||||
|
||||
inline constexpr unsigned int UTF16CharLength(wchar_t uch) noexcept {
|
||||
return ((uch >= SURROGATE_LEAD_FIRST) && (uch <= SURROGATE_LEAD_LAST)) ? 2 : 1;
|
||||
}
|
||||
|
||||
inline constexpr unsigned int UTF16LengthFromUTF8ByteCount(unsigned int byteCount) noexcept {
|
||||
return (byteCount < 4) ? 1 : 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
30
third_party/qscintilla/scintilla/src/UniqueString.h
vendored
Normal file
30
third_party/qscintilla/scintilla/src/UniqueString.h
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file UniqueString.h
|
||||
** Define UniqueString, a unique_ptr based string type for storage in containers
|
||||
** and an allocator for UniqueString.
|
||||
**/
|
||||
// Copyright 2017 by Neil Hodgson <neilh@scintilla.org>
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
|
||||
#ifndef UNIQUESTRING_H
|
||||
#define UNIQUESTRING_H
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
using UniqueString = std::unique_ptr<const char[]>;
|
||||
|
||||
/// Equivalent to strdup but produces a std::unique_ptr<const char[]> allocation to go
|
||||
/// into collections.
|
||||
inline UniqueString UniqueStringCopy(const char *text) {
|
||||
if (!text) {
|
||||
return UniqueString();
|
||||
}
|
||||
const size_t len = strlen(text);
|
||||
char *sNew = new char[len + 1];
|
||||
std::copy(text, text + len + 1, sNew);
|
||||
return UniqueString(sNew);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
613
third_party/qscintilla/scintilla/src/ViewStyle.cpp
vendored
Normal file
613
third_party/qscintilla/scintilla/src/ViewStyle.cpp
vendored
Normal file
@@ -0,0 +1,613 @@
|
||||
// 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 <cstddef>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "Scintilla.h"
|
||||
#include "Position.h"
|
||||
#include "UniqueString.h"
|
||||
#include "Indicator.h"
|
||||
#include "XPM.h"
|
||||
#include "LineMarker.h"
|
||||
#include "Style.h"
|
||||
#include "ViewStyle.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
MarginStyle::MarginStyle(int style_, int width_, int mask_) :
|
||||
style(style_), width(width_), mask(mask_), sensitive(false), cursor(SC_CURSORREVERSEARROW) {
|
||||
}
|
||||
|
||||
// A list of the fontnames - avoids wasting space in each style
|
||||
FontNames::FontNames() {
|
||||
}
|
||||
|
||||
FontNames::~FontNames() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void FontNames::Clear() {
|
||||
names.clear();
|
||||
}
|
||||
|
||||
const char *FontNames::Save(const char *name) {
|
||||
if (!name)
|
||||
return nullptr;
|
||||
|
||||
for (const UniqueString &nm : names) {
|
||||
if (strcmp(nm.get(), name) == 0) {
|
||||
return nm.get();
|
||||
}
|
||||
}
|
||||
|
||||
names.push_back(UniqueStringCopy(name));
|
||||
return names.back().get();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
const float deviceHeight = static_cast<float>(surface.DeviceHeightFont(sizeZoomed));
|
||||
const 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));
|
||||
capitalHeight = surface.Ascent(font) - surface.InternalLeading(font);
|
||||
aveCharWidth = surface.AverageCharWidth(font);
|
||||
spaceWidth = surface.WidthText(font, " ", 1);
|
||||
}
|
||||
|
||||
ViewStyle::ViewStyle() : markers(MARKER_MAX + 1), indicators(INDIC_MAX + 1) {
|
||||
Init();
|
||||
}
|
||||
|
||||
// Copy constructor only called when printing copies the screen ViewStyle so it can be
|
||||
// modified for printing styles.
|
||||
ViewStyle::ViewStyle(const ViewStyle &source) : markers(MARKER_MAX + 1), indicators(INDIC_MAX + 1) {
|
||||
Init(source.styles.size());
|
||||
styles = source.styles;
|
||||
for (size_t sty=0; sty<source.styles.size(); 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;
|
||||
markers = source.markers;
|
||||
CalcLargestMarkerHeight();
|
||||
|
||||
indicators = source.indicators;
|
||||
|
||||
indicatorsDynamic = source.indicatorsDynamic;
|
||||
indicatorsSetFore = source.indicatorsSetFore;
|
||||
|
||||
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;
|
||||
caretLineFrame = source.caretLineFrame;
|
||||
showCaretLineBackground = source.showCaretLineBackground;
|
||||
alwaysShowCaretLineBackground = source.alwaysShowCaretLineBackground;
|
||||
caretLineBackground = source.caretLineBackground;
|
||||
caretLineAlpha = source.caretLineAlpha;
|
||||
caretStyle = source.caretStyle;
|
||||
caretWidth = source.caretWidth;
|
||||
someStylesProtected = false;
|
||||
someStylesForceCase = false;
|
||||
leftMarginWidth = source.leftMarginWidth;
|
||||
rightMarginWidth = source.rightMarginWidth;
|
||||
ms = source.ms;
|
||||
maskInLine = source.maskInLine;
|
||||
maskDrawInText = source.maskDrawInText;
|
||||
fixedColumnWidth = source.fixedColumnWidth;
|
||||
marginInside = source.marginInside;
|
||||
textStart = source.textStart;
|
||||
zoomLevel = source.zoomLevel;
|
||||
viewWhitespace = source.viewWhitespace;
|
||||
tabDrawMode = source.tabDrawMode;
|
||||
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;
|
||||
|
||||
edgeState = source.edgeState;
|
||||
theEdge = source.theEdge;
|
||||
theMultiEdge = source.theMultiEdge;
|
||||
|
||||
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();
|
||||
fonts.clear();
|
||||
}
|
||||
|
||||
void ViewStyle::CalculateMarginWidthAndMask() {
|
||||
fixedColumnWidth = marginInside ? leftMarginWidth : 0;
|
||||
maskInLine = 0xffffffff;
|
||||
int maskDefinedMarkers = 0;
|
||||
for (const MarginStyle &m : ms) {
|
||||
fixedColumnWidth += m.width;
|
||||
if (m.width > 0)
|
||||
maskInLine &= ~m.mask;
|
||||
maskDefinedMarkers |= m.mask;
|
||||
}
|
||||
maskDrawInText = 0;
|
||||
for (int markBit = 0; markBit < 32; markBit++) {
|
||||
const int maskBit = 1U << markBit;
|
||||
switch (markers[markBit].markType) {
|
||||
case SC_MARK_EMPTY:
|
||||
maskInLine &= ~maskBit;
|
||||
break;
|
||||
case SC_MARK_BACKGROUND:
|
||||
case SC_MARK_UNDERLINE:
|
||||
maskInLine &= ~maskBit;
|
||||
maskDrawInText |= maskDefinedMarkers & maskBit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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] = Indicator(INDIC_SQUIGGLE, ColourDesired(0, 0x7f, 0));
|
||||
indicators[1] = Indicator(INDIC_TT, ColourDesired(0, 0, 0xff));
|
||||
indicators[2] = Indicator(INDIC_PLAIN, ColourDesired(0xff, 0, 0));
|
||||
|
||||
technology = SC_TECHNOLOGY_DEFAULT;
|
||||
indicatorsDynamic = false;
|
||||
indicatorsSetFore = false;
|
||||
lineHeight = 1;
|
||||
lineOverlap = 0;
|
||||
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);
|
||||
caretLineFrame = 0;
|
||||
showCaretLineBackground = false;
|
||||
alwaysShowCaretLineBackground = false;
|
||||
caretLineBackground = ColourDesired(0xff, 0xff, 0);
|
||||
caretLineAlpha = SC_ALPHA_NOALPHA;
|
||||
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.resize(SC_MAX_MARGIN + 1);
|
||||
ms[0] = MarginStyle(SC_MARGIN_NUMBER);
|
||||
ms[1] = MarginStyle(SC_MARGIN_SYMBOL, 16, ~SC_MASK_FOLDERS);
|
||||
ms[2] = MarginStyle(SC_MARGIN_SYMBOL);
|
||||
marginInside = true;
|
||||
CalculateMarginWidthAndMask();
|
||||
textStart = marginInside ? fixedColumnWidth : leftMarginWidth;
|
||||
zoomLevel = 0;
|
||||
viewWhitespace = wsInvisible;
|
||||
tabDrawMode = tdLongArrow;
|
||||
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;
|
||||
|
||||
edgeState = EDGE_NONE;
|
||||
theEdge = EdgeProperties(0, ColourDesired(0xc0, 0xc0, 0xc0));
|
||||
|
||||
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) {
|
||||
fonts.clear();
|
||||
|
||||
selbar = Platform::Chrome();
|
||||
selbarlight = Platform::ChromeHighlight();
|
||||
|
||||
// Apply the extra font flag which controls text drawing quality to each style.
|
||||
for (Style &style : styles) {
|
||||
style.extraFontFlag = extraFontFlag;
|
||||
}
|
||||
|
||||
// Create a FontRealised object for each unique font in the styles.
|
||||
CreateAndAddFont(styles[STYLE_DEFAULT]);
|
||||
for (const Style &style : styles) {
|
||||
CreateAndAddFont(style);
|
||||
}
|
||||
|
||||
// Ask platform to allocate each unique font.
|
||||
for (std::pair<const FontSpecification, std::unique_ptr<FontRealised>> &font : fonts) {
|
||||
font.second->Realise(surface, zoomLevel, technology, font.first);
|
||||
}
|
||||
|
||||
// Set the platform font handle and measurements for each style.
|
||||
for (Style &style : styles) {
|
||||
FontRealised *fr = Find(style);
|
||||
style.Copy(fr->font, *fr);
|
||||
}
|
||||
|
||||
indicatorsDynamic = std::any_of(indicators.cbegin(), indicators.cend(),
|
||||
[](const Indicator &indicator) { return indicator.IsDynamic(); });
|
||||
|
||||
indicatorsSetFore = std::any_of(indicators.cbegin(), indicators.cend(),
|
||||
[](const Indicator &indicator) { return indicator.OverridesTextFore(); });
|
||||
|
||||
maxAscent = 1;
|
||||
maxDescent = 1;
|
||||
FindMaxAscentDescent();
|
||||
maxAscent += extraAscent;
|
||||
maxDescent += extraDescent;
|
||||
lineHeight = maxAscent + maxDescent;
|
||||
lineOverlap = lineHeight / 10;
|
||||
if (lineOverlap < 2)
|
||||
lineOverlap = 2;
|
||||
if (lineOverlap > lineHeight)
|
||||
lineOverlap = lineHeight;
|
||||
|
||||
someStylesProtected = std::any_of(styles.cbegin(), styles.cend(),
|
||||
[](const Style &style) { return style.IsProtected(); });
|
||||
|
||||
someStylesForceCase = std::any_of(styles.cbegin(), styles.cend(),
|
||||
[](const Style &style) { return style.caseForce != Style::caseMixed; });
|
||||
|
||||
aveCharWidth = styles[STYLE_DEFAULT].aveCharWidth;
|
||||
spaceWidth = styles[STYLE_DEFAULT].spaceWidth;
|
||||
tabWidth = spaceWidth * tabInChars;
|
||||
|
||||
controlCharWidth = 0.0;
|
||||
if (controlCharSymbol >= 32) {
|
||||
const char cc[2] = { static_cast<char>(controlCharSymbol), '\0' };
|
||||
controlCharWidth = surface.WidthText(styles[STYLE_CONTROLCHAR].font, cc, 1);
|
||||
}
|
||||
|
||||
CalculateMarginWidthAndMask();
|
||||
textStart = marginInside ? fixedColumnWidth : leftMarginWidth;
|
||||
}
|
||||
|
||||
void ViewStyle::ReleaseAllExtendedStyles() {
|
||||
nextExtendedStyle = 256;
|
||||
}
|
||||
|
||||
int ViewStyle::AllocateExtendedStyles(int numberStyles) {
|
||||
const int startRange = nextExtendedStyle;
|
||||
nextExtendedStyle += numberStyles;
|
||||
EnsureStyle(nextExtendedStyle);
|
||||
for (int 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;
|
||||
}
|
||||
|
||||
int ViewStyle::MarginFromLocation(Point pt) const {
|
||||
int margin = -1;
|
||||
int x = marginInside ? 0 : -fixedColumnWidth;
|
||||
for (size_t i = 0; i < ms.size(); i++) {
|
||||
if ((pt.x >= x) && (pt.x < x + ms[i].width))
|
||||
margin = static_cast<int>(i);
|
||||
x += ms[i].width;
|
||||
}
|
||||
return margin;
|
||||
}
|
||||
|
||||
bool ViewStyle::ValidStyle(size_t styleIndex) const {
|
||||
return styleIndex < styles.size();
|
||||
}
|
||||
|
||||
void ViewStyle::CalcLargestMarkerHeight() {
|
||||
largestMarkerHeight = 0;
|
||||
for (const LineMarker &marker : markers) {
|
||||
switch (marker.markType) {
|
||||
case SC_MARK_PIXMAP:
|
||||
if (marker.pxpm && marker.pxpm->GetHeight() > largestMarkerHeight)
|
||||
largestMarkerHeight = marker.pxpm->GetHeight();
|
||||
break;
|
||||
case SC_MARK_RGBAIMAGE:
|
||||
if (marker.image && marker.image->GetHeight() > largestMarkerHeight)
|
||||
largestMarkerHeight = marker.image->GetHeight();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ViewStyle::GetFrameWidth() const {
|
||||
return Sci::clamp(caretLineFrame, 1, lineHeight / 3);
|
||||
}
|
||||
|
||||
bool ViewStyle::IsLineFrameOpaque(bool caretActive, bool lineContainsCaret) const {
|
||||
return caretLineFrame && (caretActive || alwaysShowCaretLineBackground) && showCaretLineBackground &&
|
||||
(caretLineAlpha == SC_ALPHA_NOALPHA) && lineContainsCaret;
|
||||
}
|
||||
|
||||
// See if something overrides the line background color: Either if caret is on the line
|
||||
// and background color is set for that, or if a marker is defined that forces its background
|
||||
// color onto the line, or if a marker is defined but has no selection margin in which to
|
||||
// display itself (as long as it's not an SC_MARK_EMPTY marker). These are checked in order
|
||||
// with the earlier taking precedence. When multiple markers cause background override,
|
||||
// the color for the highest numbered one is used.
|
||||
ColourOptional ViewStyle::Background(int marksOfLine, bool caretActive, bool lineContainsCaret) const {
|
||||
ColourOptional background;
|
||||
if (!caretLineFrame && (caretActive || alwaysShowCaretLineBackground) && showCaretLineBackground &&
|
||||
(caretLineAlpha == SC_ALPHA_NOALPHA) && lineContainsCaret) {
|
||||
background = ColourOptional(caretLineBackground, true);
|
||||
}
|
||||
if (!background.isSet && marksOfLine) {
|
||||
int marks = marksOfLine;
|
||||
for (int markBit = 0; (markBit < 32) && marks; markBit++) {
|
||||
if ((marks & 1) && (markers[markBit].markType == SC_MARK_BACKGROUND) &&
|
||||
(markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
|
||||
background = ColourOptional(markers[markBit].back, true);
|
||||
}
|
||||
marks >>= 1;
|
||||
}
|
||||
}
|
||||
if (!background.isSet && maskInLine) {
|
||||
int marksMasked = marksOfLine & maskInLine;
|
||||
if (marksMasked) {
|
||||
for (int markBit = 0; (markBit < 32) && marksMasked; markBit++) {
|
||||
if ((marksMasked & 1) &&
|
||||
(markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
|
||||
background = ColourOptional(markers[markBit].back, true);
|
||||
}
|
||||
marksMasked >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return background;
|
||||
}
|
||||
|
||||
bool ViewStyle::SelectionBackgroundDrawn() const {
|
||||
return selColours.back.isSet &&
|
||||
((selAlpha == SC_ALPHA_NOALPHA) || (selAdditionalAlpha == SC_ALPHA_NOALPHA));
|
||||
}
|
||||
|
||||
bool ViewStyle::WhitespaceBackgroundDrawn() const {
|
||||
return (viewWhitespace != wsInvisible) && (whitespaceColours.back.isSet);
|
||||
}
|
||||
|
||||
bool ViewStyle::WhiteSpaceVisible(bool inIndent) const {
|
||||
return (!inIndent && viewWhitespace == wsVisibleAfterIndent) ||
|
||||
(inIndent && viewWhitespace == wsVisibleOnlyInIndent) ||
|
||||
viewWhitespace == wsVisibleAlways;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
const bool changed = wrapState != wrapStateWanted;
|
||||
wrapState = wrapStateWanted;
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool ViewStyle::SetWrapVisualFlags(int wrapVisualFlags_) {
|
||||
const bool changed = wrapVisualFlags != wrapVisualFlags_;
|
||||
wrapVisualFlags = wrapVisualFlags_;
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool ViewStyle::SetWrapVisualFlagsLocation(int wrapVisualFlagsLocation_) {
|
||||
const bool changed = wrapVisualFlagsLocation != wrapVisualFlagsLocation_;
|
||||
wrapVisualFlagsLocation = wrapVisualFlagsLocation_;
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool ViewStyle::SetWrapVisualStartIndent(int wrapVisualStartIndent_) {
|
||||
const bool changed = wrapVisualStartIndent != wrapVisualStartIndent_;
|
||||
wrapVisualStartIndent = wrapVisualStartIndent_;
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool ViewStyle::SetWrapIndentMode(int wrapIndentMode_) {
|
||||
const 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] = std::unique_ptr<FontRealised>(new FontRealised());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FontRealised *ViewStyle::Find(const FontSpecification &fs) {
|
||||
if (!fs.fontName) // Invalid specification so return arbitrary object
|
||||
return fonts.begin()->second.get();
|
||||
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.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ViewStyle::FindMaxAscentDescent() {
|
||||
for (FontMap::const_iterator it = fonts.cbegin(); it != fonts.cend(); ++it) {
|
||||
if (maxAscent < it->second->ascent)
|
||||
maxAscent = it->second->ascent;
|
||||
if (maxDescent < it->second->descent)
|
||||
maxDescent = it->second->descent;
|
||||
}
|
||||
}
|
||||
224
third_party/qscintilla/scintilla/src/ViewStyle.h
vendored
Normal file
224
third_party/qscintilla/scintilla/src/ViewStyle.h
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
// 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
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
/**
|
||||
*/
|
||||
class MarginStyle {
|
||||
public:
|
||||
int style;
|
||||
ColourDesired back;
|
||||
int width;
|
||||
int mask;
|
||||
bool sensitive;
|
||||
int cursor;
|
||||
MarginStyle(int style_= SC_MARGIN_SYMBOL, int width_=0, int mask_=0);
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class FontNames {
|
||||
private:
|
||||
std::vector<UniqueString> names;
|
||||
public:
|
||||
FontNames();
|
||||
// FontNames objects can not be copied.
|
||||
FontNames(const FontNames &) = delete;
|
||||
FontNames(FontNames &&) = delete;
|
||||
FontNames &operator=(const FontNames &) = delete;
|
||||
FontNames &operator=(FontNames &&) = delete;
|
||||
~FontNames();
|
||||
void Clear();
|
||||
const char *Save(const char *name);
|
||||
};
|
||||
|
||||
class FontRealised : public FontMeasurements {
|
||||
public:
|
||||
Font font;
|
||||
FontRealised();
|
||||
// FontRealised objects can not be copied.
|
||||
FontRealised(const FontRealised &) = delete;
|
||||
FontRealised(FontRealised &&) = delete;
|
||||
FontRealised &operator=(const FontRealised &) = delete;
|
||||
FontRealised &operator=(FontRealised &&) = delete;
|
||||
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, wsVisibleOnlyInIndent=3};
|
||||
|
||||
enum TabDrawMode {tdLongArrow=0, tdStrikeOut=1};
|
||||
|
||||
typedef std::map<FontSpecification, std::unique_ptr<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<int>(lParam)), isSet(wParam != 0) {
|
||||
}
|
||||
};
|
||||
|
||||
struct ForeBackColours {
|
||||
ColourOptional fore;
|
||||
ColourOptional back;
|
||||
};
|
||||
|
||||
struct EdgeProperties {
|
||||
int column;
|
||||
ColourDesired colour;
|
||||
EdgeProperties(int column_ = 0, ColourDesired colour_ = ColourDesired(0)) :
|
||||
column(column_), colour(colour_) {
|
||||
}
|
||||
EdgeProperties(uptr_t wParam, sptr_t lParam) :
|
||||
column(static_cast<int>(wParam)), colour(static_cast<int>(lParam)) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*/
|
||||
class ViewStyle {
|
||||
FontNames fontNames;
|
||||
FontMap fonts;
|
||||
public:
|
||||
std::vector<Style> styles;
|
||||
int nextExtendedStyle;
|
||||
std::vector<LineMarker> markers;
|
||||
int largestMarkerHeight;
|
||||
std::vector<Indicator> indicators;
|
||||
bool indicatorsDynamic;
|
||||
bool indicatorsSetFore;
|
||||
int technology;
|
||||
int lineHeight;
|
||||
int lineOverlap;
|
||||
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
|
||||
int maskDrawInText; ///< Mask for markers that always draw in text
|
||||
std::vector<MarginStyle> ms;
|
||||
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;
|
||||
TabDrawMode tabDrawMode;
|
||||
int whitespaceSize;
|
||||
IndentView viewIndentationGuides;
|
||||
bool viewEOL;
|
||||
ColourDesired caretcolour;
|
||||
ColourDesired additionalCaretColour;
|
||||
int caretLineFrame;
|
||||
bool showCaretLineBackground;
|
||||
bool alwaysShowCaretLineBackground;
|
||||
ColourDesired caretLineBackground;
|
||||
int caretLineAlpha;
|
||||
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 edgeState;
|
||||
EdgeProperties theEdge;
|
||||
std::vector<EdgeProperties> theMultiEdge;
|
||||
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(ViewStyle &&) = delete;
|
||||
// Can only be copied through copy constructor which ensures font names initialised correctly
|
||||
ViewStyle &operator=(const ViewStyle &) = delete;
|
||||
ViewStyle &operator=(ViewStyle &&) = delete;
|
||||
~ViewStyle();
|
||||
void CalculateMarginWidthAndMask();
|
||||
void Init(size_t stylesSize_=256);
|
||||
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;
|
||||
int MarginFromLocation(Point pt) const;
|
||||
bool ValidStyle(size_t styleIndex) const;
|
||||
void CalcLargestMarkerHeight();
|
||||
int GetFrameWidth() const;
|
||||
bool IsLineFrameOpaque(bool caretActive, bool lineContainsCaret) const;
|
||||
ColourOptional Background(int marksOfLine, bool caretActive, bool lineContainsCaret) const;
|
||||
bool SelectionBackgroundDrawn() const;
|
||||
bool WhitespaceBackgroundDrawn() const;
|
||||
ColourDesired WrapColour() const;
|
||||
|
||||
bool SetWrapState(int wrapState_);
|
||||
bool SetWrapVisualFlags(int wrapVisualFlags_);
|
||||
bool SetWrapVisualFlagsLocation(int wrapVisualFlagsLocation_);
|
||||
bool SetWrapVisualStartIndent(int wrapVisualStartIndent_);
|
||||
bool SetWrapIndentMode(int wrapIndentMode_);
|
||||
|
||||
bool WhiteSpaceVisible(bool inIndent) const;
|
||||
|
||||
private:
|
||||
void AllocStyles(size_t sizeNew);
|
||||
void CreateAndAddFont(const FontSpecification &fs);
|
||||
FontRealised *Find(const FontSpecification &fs);
|
||||
void FindMaxAscentDescent();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
448
third_party/qscintilla/scintilla/src/XPM.cpp
vendored
Normal file
448
third_party/qscintilla/scintilla/src/XPM.cpp
vendored
Normal file
@@ -0,0 +1,448 @@
|
||||
// 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 <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
#include "XPM.h"
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
#if defined(PLAT_QT)
|
||||
|
||||
XPM::XPM(const char *textForm)
|
||||
{
|
||||
qpm = *reinterpret_cast<const QPixmap *>(textForm);
|
||||
}
|
||||
|
||||
XPM::XPM(const char *const *linesForm)
|
||||
{
|
||||
qpm = *reinterpret_cast<const QPixmap *>(linesForm);
|
||||
}
|
||||
|
||||
void XPM::Draw(Surface *surface, PRectangle &rc)
|
||||
{
|
||||
surface->DrawXPM(rc, this);
|
||||
}
|
||||
|
||||
RGBAImage::RGBAImage(int width_, int height_, float scale_,
|
||||
const unsigned char *pixels_)
|
||||
: height(height_), width(width_), scale(scale_)
|
||||
{
|
||||
if (pixels_)
|
||||
{
|
||||
qim = new QImage(*reinterpret_cast<const QImage *>(pixels_));
|
||||
}
|
||||
else
|
||||
{
|
||||
#if QT_VERSION >= 0x040000
|
||||
qim = new QImage(width_, height_, QImage::Format_ARGB32);
|
||||
#else
|
||||
qim = new QImage(width_, height_, 32);
|
||||
qim->setAlphaBuffer(true);
|
||||
#endif
|
||||
qim->fill(0);
|
||||
}
|
||||
}
|
||||
|
||||
RGBAImage::RGBAImage(const XPM &xpm)
|
||||
{
|
||||
#if QT_VERSION >= 0x040000
|
||||
qim = new QImage(xpm.Pixmap().toImage());
|
||||
#else
|
||||
qim = new QImage(xpm.Pixmap().convertToImage());
|
||||
#endif
|
||||
|
||||
width = qim->width();
|
||||
height = qim->height();
|
||||
}
|
||||
|
||||
RGBAImage::~RGBAImage()
|
||||
{
|
||||
delete qim;
|
||||
}
|
||||
|
||||
const unsigned char *RGBAImage::Pixels() const
|
||||
{
|
||||
return reinterpret_cast<const unsigned char *>(qim);
|
||||
}
|
||||
|
||||
void RGBAImage::SetPixel(int x, int y, ColourDesired colour, int alpha)
|
||||
{
|
||||
QRgb rgba = qRgba(colour.GetRed(), colour.GetGreen(), colour.GetBlue(),
|
||||
alpha);
|
||||
|
||||
uint index_or_rgb;
|
||||
|
||||
#if QT_VERSION >= 0x040000
|
||||
switch (qim->format())
|
||||
{
|
||||
case QImage::Format_RGB32:
|
||||
case QImage::Format_ARGB32:
|
||||
index_or_rgb = rgba;
|
||||
break;
|
||||
|
||||
case QImage::Format_ARGB32_Premultiplied:
|
||||
{
|
||||
uint a = alpha;
|
||||
#if QT_POINTER_SIZE == 8
|
||||
quint64 t = (((quint64(rgba)) | ((quint64(rgba)) << 24)) & 0x00ff00ff00ff00ff) * a;
|
||||
t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080) >> 8;
|
||||
t &= 0x000000ff00ff00ff;
|
||||
index_or_rgb = (uint(t)) | (uint(t >> 24)) | (a << 24);
|
||||
#else
|
||||
uint t = (rgba & 0xff00ff) * a;
|
||||
t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
|
||||
t &= 0xff00ff;
|
||||
|
||||
rgba = ((rgba >> 8) & 0xff) * a;
|
||||
rgba = (rgba + ((rgba >> 8) & 0xff) + 0x80);
|
||||
rgba &= 0xff00;
|
||||
index_or_rgb = rgba | t | (a << 24);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
#if QT_VERSION >= 0x040600
|
||||
index_or_rgb = qim->colorCount();
|
||||
#else
|
||||
index_or_rgb = qim->colorTable().count();
|
||||
#endif
|
||||
|
||||
qim->setColor(index_or_rgb, rgba);
|
||||
}
|
||||
#else
|
||||
if (qim->depth() == 32)
|
||||
{
|
||||
index_or_rgb = rgba;
|
||||
}
|
||||
else
|
||||
{
|
||||
index_or_rgb = qim->numColors();
|
||||
qim->setNumColors(index_or_rgb + 1);
|
||||
|
||||
qim->setColor(index_or_rgb, rgba);
|
||||
}
|
||||
#endif
|
||||
|
||||
qim->setPixel(x, y, index_or_rgb);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
namespace {
|
||||
|
||||
const char *NextField(const char *s) {
|
||||
// In case there are leading spaces in the string
|
||||
while (*s == ' ') {
|
||||
s++;
|
||||
}
|
||||
while (*s && *s != ' ') {
|
||||
s++;
|
||||
}
|
||||
while (*s == ' ') {
|
||||
s++;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// Data lines in XPM can be terminated either with NUL or "
|
||||
size_t MeasureLength(const char *s) {
|
||||
size_t i = 0;
|
||||
while (s[i] && (s[i] != '\"'))
|
||||
i++;
|
||||
return i;
|
||||
}
|
||||
|
||||
unsigned int ValueOfHex(const char ch) noexcept {
|
||||
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;
|
||||
}
|
||||
|
||||
ColourDesired ColourFromHex(const char *val) noexcept {
|
||||
const unsigned int r = ValueOfHex(val[0]) * 16 + ValueOfHex(val[1]);
|
||||
const unsigned int g = ValueOfHex(val[2]) * 16 + ValueOfHex(val[3]);
|
||||
const unsigned int b = ValueOfHex(val[4]) * 16 + ValueOfHex(val[5]);
|
||||
return ColourDesired(r, g, b);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
ColourDesired XPM::ColourFromCode(int ch) const {
|
||||
return colourCodeTable[ch];
|
||||
}
|
||||
|
||||
void XPM::FillRun(Surface *surface, int code, int startX, int y, int x) const {
|
||||
if ((code != codeTransparent) && (startX != x)) {
|
||||
const 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, std::end(colourCodeTable), ColourDesired(0));
|
||||
const char *line0 = linesForm[0];
|
||||
width = atoi(line0);
|
||||
line0 = NextField(line0);
|
||||
height = atoi(line0);
|
||||
pixels.resize(width*height);
|
||||
line0 = NextField(line0);
|
||||
nColours = atoi(line0);
|
||||
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];
|
||||
const char code = colourDef[0];
|
||||
colourDef += 4;
|
||||
ColourDesired colour(0xff, 0xff, 0xff);
|
||||
if (*colourDef == '#') {
|
||||
colour = ColourFromHex(colourDef+1);
|
||||
} else {
|
||||
codeTransparent = code;
|
||||
}
|
||||
colourCodeTable[static_cast<unsigned char>(code)] = colour;
|
||||
}
|
||||
|
||||
for (int y=0; y<height; y++) {
|
||||
const char *lform = linesForm[y+nColours+1];
|
||||
const size_t len = MeasureLength(lform);
|
||||
for (size_t x = 0; x<len; x++)
|
||||
pixels[y * width + x] = lform[x];
|
||||
}
|
||||
}
|
||||
|
||||
void XPM::Draw(Surface *surface, const PRectangle &rc) {
|
||||
if (pixels.empty()) {
|
||||
return;
|
||||
}
|
||||
// Centre the pixmap
|
||||
const int startY = static_cast<int>(rc.top + (rc.Height() - height) / 2);
|
||||
const 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++) {
|
||||
const 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 = ColourDesired(0);
|
||||
transparent = true;
|
||||
return;
|
||||
}
|
||||
const int code = pixels[y * width + x];
|
||||
transparent = code == codeTransparent;
|
||||
if (transparent) {
|
||||
colour = ColourDesired(0);
|
||||
} else {
|
||||
colour = ColourFromCode(code);
|
||||
}
|
||||
}
|
||||
|
||||
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] = colour.GetRed();
|
||||
pixel[1] = colour.GetGreen();
|
||||
pixel[2] = colour.GetBlue();
|
||||
pixel[3] = static_cast<unsigned char>(alpha);
|
||||
}
|
||||
|
||||
RGBAImageSet::RGBAImageSet() : height(-1), width(-1) {
|
||||
}
|
||||
|
||||
RGBAImageSet::~RGBAImageSet() {
|
||||
Clear();
|
||||
}
|
||||
|
||||
/// Remove all images.
|
||||
void RGBAImageSet::Clear() {
|
||||
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] = std::unique_ptr<RGBAImage>(image);
|
||||
} else {
|
||||
it->second.reset(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.get();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Give the largest height of the set.
|
||||
int RGBAImageSet::GetHeight() const {
|
||||
if (height < 0) {
|
||||
for (const std::pair<const int, std::unique_ptr<RGBAImage>> &image : images) {
|
||||
if (height < image.second->GetHeight()) {
|
||||
height = image.second->GetHeight();
|
||||
}
|
||||
}
|
||||
}
|
||||
return (height > 0) ? height : 0;
|
||||
}
|
||||
|
||||
/// Give the largest width of the set.
|
||||
int RGBAImageSet::GetWidth() const {
|
||||
if (width < 0) {
|
||||
for (const std::pair<const int, std::unique_ptr<RGBAImage>> &image : images) {
|
||||
if (width < image.second->GetWidth()) {
|
||||
width = image.second->GetWidth();
|
||||
}
|
||||
}
|
||||
}
|
||||
return (width > 0) ? width : 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
130
third_party/qscintilla/scintilla/src/XPM.h
vendored
Normal file
130
third_party/qscintilla/scintilla/src/XPM.h
vendored
Normal file
@@ -0,0 +1,130 @@
|
||||
// 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
|
||||
|
||||
#if defined(PLAT_QT)
|
||||
#include <qimage.h>
|
||||
#include <qpixmap.h>
|
||||
#endif
|
||||
|
||||
namespace Scintilla {
|
||||
|
||||
/**
|
||||
* Hold a pixmap in XPM format.
|
||||
*/
|
||||
class XPM {
|
||||
#if defined(PLAT_QT)
|
||||
QPixmap qpm;
|
||||
|
||||
public:
|
||||
XPM(const char *textForm);
|
||||
XPM(const char *const *linesForm);
|
||||
~XPM() {}
|
||||
|
||||
void Draw(Surface *surface, PRectangle &rc);
|
||||
int GetHeight() const {return qpm.height();}
|
||||
|
||||
const QPixmap &Pixmap() const {return qpm;}
|
||||
#else
|
||||
int height=1;
|
||||
int width=1;
|
||||
int nColours=1;
|
||||
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) const;
|
||||
public:
|
||||
explicit XPM(const char *textForm);
|
||||
explicit XPM(const char *const *linesForm);
|
||||
XPM(const XPM &) = delete;
|
||||
XPM(XPM &&) = delete;
|
||||
XPM &operator=(const XPM &) = delete;
|
||||
XPM &operator=(XPM &&) = delete;
|
||||
~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, const 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);
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* A translucent image stored as a sequence of RGBA bytes.
|
||||
*/
|
||||
class RGBAImage {
|
||||
int height;
|
||||
int width;
|
||||
float scale;
|
||||
#if defined(PLAT_QT)
|
||||
QImage *qim;
|
||||
#else
|
||||
std::vector<unsigned char> pixelBytes;
|
||||
#endif
|
||||
public:
|
||||
RGBAImage(int width_, int height_, float scale_, const unsigned char *pixels_);
|
||||
explicit RGBAImage(const XPM &xpm);
|
||||
// Deleted so RGBAImage objects can not be copied.
|
||||
RGBAImage(const RGBAImage &) = delete;
|
||||
RGBAImage(RGBAImage &&) = delete;
|
||||
RGBAImage &operator=(const RGBAImage &) = delete;
|
||||
RGBAImage &operator=(RGBAImage &&) = delete;
|
||||
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; }
|
||||
#if !defined(PLAT_QT)
|
||||
int CountBytes() const;
|
||||
#endif
|
||||
const unsigned char *Pixels() const;
|
||||
void SetPixel(int x, int y, ColourDesired colour, int alpha);
|
||||
};
|
||||
|
||||
#if !defined(PLAT_QT)
|
||||
|
||||
/**
|
||||
* A collection of RGBAImage pixmaps indexed by integer id.
|
||||
*/
|
||||
class RGBAImageSet {
|
||||
typedef std::map<int, std::unique_ptr<RGBAImage>> ImageMap;
|
||||
ImageMap images;
|
||||
mutable int height; ///< Memorize largest height of the set.
|
||||
mutable int width; ///< Memorize largest width of the set.
|
||||
public:
|
||||
RGBAImageSet();
|
||||
// Deleted so RGBAImageSet objects can not be copied.
|
||||
RGBAImageSet(const RGBAImageSet &) = delete;
|
||||
RGBAImageSet(RGBAImageSet &&) = delete;
|
||||
RGBAImageSet &operator=(const RGBAImageSet &) = delete;
|
||||
RGBAImageSet &operator=(RGBAImageSet &&) = delete;
|
||||
~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;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user