Updated Scintilla to version 1.75.

git-svn-id: https://geany.svn.sourceforge.net/svnroot/geany/trunk@2086 ea778897-0a13-0410-b9d1-a72fbfd435f5
This commit is contained in:
Enrico Tröger 2007-12-02 11:58:17 +00:00
parent c27e9b54c6
commit 6b650084a2
34 changed files with 1317 additions and 1250 deletions

View File

@ -7,6 +7,7 @@
Make path entry of filebrowser plugin editable.
Add "Open with" and "Find in Files" popup menu items to filebrowser
plugin and add configuration dialog.
* scintilla/*, scintilla/include/*: Updated Scintilla to version 1.75.
2007-12-01 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>

View File

@ -13,7 +13,6 @@
#include "Platform.h"
#include "Scintilla.h"
#include "SVector.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "CellBuffer.h"
@ -472,6 +471,7 @@ void UndoHistory::BeginUndoAction() {
}
void UndoHistory::EndUndoAction() {
PLATFORM_ASSERT(undoSequenceDepth > 0);
EnsureUndoRoom();
undoSequenceDepth--;
if (0 == undoSequenceDepth) {
@ -563,7 +563,7 @@ CellBuffer::CellBuffer() {
CellBuffer::~CellBuffer() {
}
char CellBuffer::CharAt(int position) {
char CellBuffer::CharAt(int position) const {
return substance.ValueAt(position);
}
@ -653,7 +653,7 @@ const char *CellBuffer::DeleteChars(int position, int deleteLength, bool &startS
return data;
}
int CellBuffer::Length() {
int CellBuffer::Length() const {
return substance.Length();
}
@ -662,11 +662,11 @@ void CellBuffer::Allocate(int newSize) {
style.ReAllocate(newSize);
}
int CellBuffer::Lines() {
int CellBuffer::Lines() const {
return lv.Lines();
}
int CellBuffer::LineStart(int line) {
int CellBuffer::LineStart(int line) const {
if (line < 0)
return 0;
else if (line >= Lines())
@ -726,6 +726,20 @@ int CellBuffer::LineFromHandle(int markerHandle) {
// Without undo
void CellBuffer::InsertLine(int line, int position) {
lv.InsertLine(line, position);
if (lineStates.Length()) {
lineStates.Insert(line, 0);
}
}
void CellBuffer::RemoveLine(int line) {
lv.RemoveLine(line);
if (lineStates.Length()) {
lineStates.Delete(line);
}
}
void CellBuffer::BasicInsertString(int position, const char *s, int insertLength) {
if (insertLength == 0)
return;
@ -741,21 +755,21 @@ void CellBuffer::BasicInsertString(int position, const char *s, int insertLength
char chAfter = substance.ValueAt(position + insertLength);
if (chPrev == '\r' && chAfter == '\n') {
// Splitting up a crlf pair at position
lv.InsertLine(lineInsert, position);
InsertLine(lineInsert, position);
lineInsert++;
}
char ch = ' ';
for (int i = 0; i < insertLength; i++) {
ch = s[i];
if (ch == '\r') {
lv.InsertLine(lineInsert, (position + i) + 1);
InsertLine(lineInsert, (position + i) + 1);
lineInsert++;
} else if (ch == '\n') {
if (chPrev == '\r') {
// Patch up what was end of line
lv.SetLineStart(lineInsert - 1, (position + i) + 1);
} else {
lv.InsertLine(lineInsert, (position + i) + 1);
InsertLine(lineInsert, (position + i) + 1);
lineInsert++;
}
}
@ -765,7 +779,7 @@ void CellBuffer::BasicInsertString(int position, const char *s, int insertLength
if (chAfter == '\n') {
if (ch == '\r') {
// End of line already in buffer so drop the newly created one
lv.RemoveLine(lineInsert - 1);
RemoveLine(lineInsert - 1);
}
}
}
@ -800,13 +814,13 @@ void CellBuffer::BasicDeleteChars(int position, int deleteLength) {
chNext = substance.ValueAt(position + i + 1);
if (ch == '\r') {
if (chNext != '\n') {
lv.RemoveLine(lineRemove);
RemoveLine(lineRemove);
}
} else if (ch == '\n') {
if (ignoreNL) {
ignoreNL = false; // Further \n are real deletions
} else {
lv.RemoveLine(lineRemove);
RemoveLine(lineRemove);
}
}
@ -817,7 +831,7 @@ void CellBuffer::BasicDeleteChars(int position, int deleteLength) {
char chAfter = substance.ValueAt(position + deleteLength);
if (chBefore == '\r' && chAfter == '\n') {
// Using lineRemove-1 as cr ended line before start of deletion
lv.RemoveLine(lineRemove - 1);
RemoveLine(lineRemove - 1);
lv.SetLineStart(lineRemove - 1, position + 1);
}
}
@ -892,12 +906,14 @@ void CellBuffer::PerformRedoStep() {
}
int CellBuffer::SetLineState(int line, int state) {
lineStates.EnsureLength(line + 1);
int stateOld = lineStates[line];
lineStates[line] = state;
return stateOld;
}
int CellBuffer::GetLineState(int line) {
lineStates.EnsureLength(line + 1);
return lineStates[line];
}

View File

@ -67,11 +67,11 @@ public:
void InsertLine(int line, int position);
void SetLineStart(int line, int position);
void RemoveLine(int line);
int Lines() {
int Lines() const {
return starts.Partitions();
}
int LineFromPosition(int pos);
int LineStart(int line) {
int LineStart(int line) const {
return starts.PositionFromPartition(line);
}
@ -160,7 +160,7 @@ private:
LineVector lv;
SVector lineStates;
SplitVector<int> lineStates;
public:
@ -168,15 +168,17 @@ public:
~CellBuffer();
/// Retrieving positions outside the range of the buffer works and returns 0
char CharAt(int position);
char CharAt(int position) const;
void GetCharRange(char *buffer, int position, int lengthRetrieve);
char StyleAt(int position);
int Length();
int Length() const;
void Allocate(int newSize);
int Lines();
int LineStart(int line);
int Lines() const;
int LineStart(int line) const;
int LineFromPosition(int pos) { return lv.LineFromPosition(pos); }
void InsertLine(int line, int position);
void RemoveLine(int line);
const char *InsertString(int position, const char *s, int insertLength, bool &startSequence);
/// Setting styles for positions outside the range of the buffer is safe and has no effect.

View File

@ -1,293 +1,251 @@
// Scintilla source code edit control
/** @file ContractionState.cxx
** Manages visibility of lines for folding.
** Manages visibility of lines for folding and wrapping.
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <string.h>
#include "Platform.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
OneLine::OneLine() {
displayLine = 0;
//docLine = 0;
visible = true;
height = 1;
expanded = true;
}
ContractionState::ContractionState() {
lines = 0;
size = 0;
linesInDoc = 1;
linesInDisplay = 1;
valid = false;
docLines = 0;
sizeDocLines = 0;
ContractionState::ContractionState() : visible(0), expanded(0), heights(0), displayLines(0), linesInDocument(1) {
//InsertLine(0);
}
ContractionState::~ContractionState() {
Clear();
}
void ContractionState::MakeValid() const {
if (!valid) {
// Could be cleverer by keeping the index of the last still valid entry
// rather than invalidating all.
linesInDisplay = 0;
for (int lineInDoc=0; lineInDoc<linesInDoc; lineInDoc++) {
lines[lineInDoc].displayLine = linesInDisplay;
if (lines[lineInDoc].visible) {
linesInDisplay += lines[lineInDoc].height;
}
}
if (sizeDocLines < linesInDisplay) {
delete []docLines;
int *docLinesNew = new int[linesInDisplay + growSize];
if (!docLinesNew) {
docLines = 0;
sizeDocLines = 0;
return;
}
docLines = docLinesNew;
sizeDocLines = linesInDisplay + growSize;
}
int lineInDisplay=0;
for (int line=0; line<linesInDoc; line++) {
if (lines[line].visible) {
for (int linePiece=0; linePiece<lines[line].height; linePiece++) {
docLines[lineInDisplay] = line;
lineInDisplay++;
}
}
}
valid = true;
void ContractionState::EnsureData() {
if (OneToOne()) {
visible = new RunStyles();
expanded = new RunStyles();
heights = new RunStyles();
displayLines = new Partitioning(4);
InsertLines(0, linesInDocument);
}
}
void ContractionState::Clear() {
delete []lines;
lines = 0;
size = 0;
linesInDoc = 1;
linesInDisplay = 1;
delete []docLines;
docLines = 0;
sizeDocLines = 0;
delete visible;
visible = 0;
delete expanded;
expanded = 0;
delete heights;
heights = 0;
delete displayLines;
displayLines = 0;
linesInDocument = 1;
}
int ContractionState::LinesInDoc() const {
return linesInDoc;
if (OneToOne()) {
return linesInDocument;
} else {
return displayLines->Partitions() - 1;
}
}
int ContractionState::LinesDisplayed() const {
if (size != 0) {
MakeValid();
if (OneToOne()) {
return linesInDocument;
} else {
return displayLines->PositionFromPartition(LinesInDoc());
}
return linesInDisplay;
}
int ContractionState::DisplayFromDoc(int lineDoc) const {
if (size == 0) {
if (OneToOne()) {
return lineDoc;
} else {
if (lineDoc > displayLines->Partitions())
lineDoc = displayLines->Partitions();
return displayLines->PositionFromPartition(lineDoc);
}
MakeValid();
if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
return lines[lineDoc].displayLine;
}
return -1;
}
int ContractionState::DocFromDisplay(int lineDisplay) const {
if (lineDisplay <= 0)
return 0;
if (lineDisplay >= linesInDisplay)
return linesInDoc;
if (size == 0)
if (OneToOne()) {
return lineDisplay;
MakeValid();
if (docLines) { // Valid allocation
return docLines[lineDisplay];
} else {
return 0;
if (lineDisplay <= 0) {
return 0;
}
if (lineDisplay > LinesDisplayed()) {
return displayLines->PartitionFromPosition(LinesDisplayed());
}
int lineDoc = displayLines->PartitionFromPosition(lineDisplay);
PLATFORM_ASSERT(GetVisible(lineDoc));
return lineDoc;
}
}
void ContractionState::Grow(int sizeNew) {
OneLine *linesNew = new OneLine[sizeNew];
if (linesNew) {
int i = 0;
for (; i < size; i++) {
linesNew[i] = lines[i];
}
for (; i < sizeNew; i++) {
linesNew[i].displayLine = i;
}
delete []lines;
lines = linesNew;
size = sizeNew;
valid = false;
void ContractionState::InsertLine(int lineDoc) {
if (OneToOne()) {
linesInDocument++;
} else {
Platform::DebugPrintf("No memory available\n");
// TODO: Blow up
visible->InsertSpace(lineDoc, 1);
visible->SetValueAt(lineDoc, 1);
expanded->InsertSpace(lineDoc, 1);
expanded->SetValueAt(lineDoc, 1);
heights->InsertSpace(lineDoc, 1);
heights->SetValueAt(lineDoc, 1);
int lineDisplay = DisplayFromDoc(lineDoc);
displayLines->InsertPartition(lineDoc, lineDisplay);
displayLines->InsertText(lineDoc, 1);
}
}
void ContractionState::InsertLines(int lineDoc, int lineCount) {
if (size == 0) {
linesInDoc += lineCount;
linesInDisplay += lineCount;
return;
for (int l = 0; l < lineCount; l++) {
InsertLine(lineDoc + l);
}
//Platform::DebugPrintf("InsertLine[%d] = %d\n", lineDoc);
if ((linesInDoc + lineCount + 2) >= size) {
Grow(linesInDoc + lineCount + growSize);
Check();
}
void ContractionState::DeleteLine(int lineDoc) {
if (OneToOne()) {
linesInDocument--;
} else {
if (GetVisible(lineDoc)) {
displayLines->InsertText(lineDoc, -heights->ValueAt(lineDoc));
}
displayLines->RemovePartition(lineDoc);
visible->DeleteRange(lineDoc, 1);
expanded->DeleteRange(lineDoc, 1);
heights->DeleteRange(lineDoc, 1);
}
linesInDoc += lineCount;
for (int i = linesInDoc; i >= lineDoc + lineCount; i--) {
lines[i].visible = lines[i - lineCount].visible;
lines[i].height = lines[i - lineCount].height;
linesInDisplay += lines[i].height;
lines[i].expanded = lines[i - lineCount].expanded;
}
for (int d=0;d<lineCount;d++) {
lines[lineDoc+d].visible = true; // Should inherit visibility from context ?
lines[lineDoc+d].height = 1;
lines[lineDoc+d].expanded = true;
}
valid = false;
}
void ContractionState::DeleteLines(int lineDoc, int lineCount) {
if (size == 0) {
linesInDoc -= lineCount;
linesInDisplay -= lineCount;
return;
for (int l = 0; l < lineCount; l++) {
DeleteLine(lineDoc);
}
int deltaDisplayed = 0;
for (int d=0;d<lineCount;d++) {
if (lines[lineDoc+d].visible)
deltaDisplayed -= lines[lineDoc+d].height;
}
for (int i = lineDoc; i < linesInDoc-lineCount; i++) {
if (i != 0) // Line zero is always visible
lines[i].visible = lines[i + lineCount].visible;
lines[i].expanded = lines[i + lineCount].expanded;
lines[i].height = lines[i + lineCount].height;
}
linesInDoc -= lineCount;
linesInDisplay += deltaDisplayed;
valid = false;
Check();
}
bool ContractionState::GetVisible(int lineDoc) const {
if (size == 0)
if (OneToOne()) {
return true;
if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
return lines[lineDoc].visible;
} else {
return false;
if (lineDoc >= visible->Length())
return true;
return visible->ValueAt(lineDoc) == 1;
}
}
bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible) {
if (lineDocStart == 0)
lineDocStart++;
if (lineDocStart > lineDocEnd)
bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible_) {
if (OneToOne() && visible_) {
return false;
if (size == 0) {
Grow(linesInDoc + growSize);
}
// TODO: modify docLine members to mirror displayLine
int delta = 0;
// Change lineDocs
if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < linesInDoc)) {
for (int line=lineDocStart; line <= lineDocEnd; line++) {
if (lines[line].visible != visible) {
delta += visible ? lines[line].height : -lines[line].height;
lines[line].visible = visible;
valid = false;
} else {
EnsureData();
int delta = 0;
Check();
if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < LinesInDoc())) {
for (int line = lineDocStart; line <= lineDocEnd; line++) {
if (GetVisible(line) != visible_) {
int difference = visible_ ? heights->ValueAt(line) : -heights->ValueAt(line);
visible->SetValueAt(line, visible_ ? 1 : 0);
displayLines->InsertText(line, difference);
delta += difference;
}
}
} else {
return false;
}
Check();
return delta != 0;
}
linesInDisplay += delta;
return delta != 0;
}
bool ContractionState::GetExpanded(int lineDoc) const {
if (size == 0)
if (OneToOne()) {
return true;
if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
return lines[lineDoc].expanded;
} else {
return false;
Check();
return expanded->ValueAt(lineDoc) == 1;
}
}
bool ContractionState::SetExpanded(int lineDoc, bool expanded) {
if (size == 0) {
if (expanded) {
// If in completely expanded state then setting
// one line to expanded has no effect.
bool ContractionState::SetExpanded(int lineDoc, bool expanded_) {
if (OneToOne() && expanded_) {
return false;
} else {
EnsureData();
if (expanded_ != (expanded->ValueAt(lineDoc) == 1)) {
expanded->SetValueAt(lineDoc, expanded_ ? 1 : 0);
Check();
return true;
} else {
Check();
return false;
}
Grow(linesInDoc + growSize);
}
if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
if (lines[lineDoc].expanded != expanded) {
lines[lineDoc].expanded = expanded;
return true;
}
}
return false;
}
int ContractionState::GetHeight(int lineDoc) const {
if (size == 0)
if (OneToOne()) {
return 1;
if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
return lines[lineDoc].height;
} else {
return 1;
return heights->ValueAt(lineDoc);
}
}
// Set the number of display lines needed for this line.
// Return true if this is a change.
bool ContractionState::SetHeight(int lineDoc, int height) {
if (lineDoc > linesInDoc)
if (OneToOne() && (height == 1)) {
return false;
if (size == 0) {
if (height == 1) {
// If in completely expanded state then all lines
// assumed to have height of one so no effect here.
} else {
EnsureData();
if (GetHeight(lineDoc) != height) {
if (GetVisible(lineDoc)) {
displayLines->InsertText(lineDoc, height - GetHeight(lineDoc));
}
heights->SetValueAt(lineDoc, height);
Check();
return true;
} else {
Check();
return false;
}
Grow(linesInDoc + growSize);
}
if (lines[lineDoc].height != height) {
lines[lineDoc].height = height;
valid = false;
return true;
} else {
return false;
}
}
void ContractionState::ShowAll() {
delete []lines;
lines = 0;
size = 0;
delete []docLines;
docLines = 0;
sizeDocLines = 0;
linesInDisplay = linesInDoc;
int lines = LinesInDoc();
Clear();
linesInDocument = lines;
}
// Debugging checks
void ContractionState::Check() const {
#ifdef CHECK_CORRECTNESS
for (int vline = 0;vline < LinesDisplayed(); vline++) {
const int lineDoc = DocFromDisplay(vline);
PLATFORM_ASSERT(GetVisible(lineDoc));
}
for (int lineDoc = 0;lineDoc < LinesInDoc(); lineDoc++) {
const int displayThis = DisplayFromDoc(lineDoc);
const int displayNext = DisplayFromDoc(lineDoc + 1);
const int height = displayNext - displayThis;
PLATFORM_ASSERT(height >= 0);
if (GetVisible(lineDoc)) {
PLATFORM_ASSERT(GetHeight(lineDoc) == height);
} else {
PLATFORM_ASSERT(0 == height);
}
}
#endif
}

View File

@ -1,8 +1,8 @@
// Scintilla source code edit control
/** @file ContractionState.h
** Manages visibility of lines for folding.
** Manages visibility of lines for folding and wrapping.
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// 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
@ -12,33 +12,23 @@
namespace Scintilla {
#endif
/**
*/
class OneLine {
public:
int displayLine; ///< Position within set of visible lines
//int docLine; ///< Inverse of @a displayLine
int height; ///< Number of display lines needed to show all of the line
bool visible;
bool expanded;
OneLine();
virtual ~OneLine() {}
};
/**
*/
class ContractionState {
void Grow(int sizeNew);
enum { growSize = 4000 };
int linesInDoc;
mutable int linesInDisplay;
mutable OneLine *lines;
int size;
mutable int *docLines;
mutable int sizeDocLines;
mutable bool valid;
void MakeValid() const;
// These contain 1 element for every document line.
RunStyles *visible;
RunStyles *expanded;
RunStyles *heights;
Partitioning *displayLines;
int linesInDocument;
void EnsureData();
bool OneToOne() const {
// True when each document line is exactly one display line so need for
// complex data structures.
return visible == 0;
}
public:
ContractionState();
@ -51,7 +41,9 @@ public:
int DisplayFromDoc(int lineDoc) const;
int DocFromDisplay(int lineDisplay) const;
void InsertLine(int lineDoc);
void InsertLines(int lineDoc, int lineCount);
void DeleteLine(int lineDoc);
void DeleteLines(int lineDoc, int lineCount);
bool GetVisible(int lineDoc) const;
@ -64,6 +56,7 @@ public:
bool SetHeight(int lineDoc, int height);
void ShowAll();
void Check() const;
};
#ifdef SCI_NAMESPACE

View File

@ -13,7 +13,6 @@
#include "Platform.h"
#include "Scintilla.h"
#include "SVector.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
@ -113,7 +112,6 @@ void Document::SetSavePoint() {
int Document::AddMark(int line, int markerNum) {
int prev = cb.AddMark(line, markerNum);
DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
mh.line = line;
NotifyModified(mh);
return prev;
}
@ -124,14 +122,12 @@ void Document::AddMarkSet(int line, int valueSet) {
if (m & 1)
cb.AddMark(line, i);
DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
mh.line = line;
NotifyModified(mh);
}
void Document::DeleteMark(int line, int markerNum) {
cb.DeleteMark(line, markerNum);
DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
mh.line = line;
NotifyModified(mh);
}
@ -149,11 +145,11 @@ void Document::DeleteAllMarks(int markerNum) {
NotifyModified(mh);
}
int Document::LineStart(int line) {
int Document::LineStart(int line) const {
return cb.LineStart(line);
}
int Document::LineEnd(int line) {
int Document::LineEnd(int line) const {
if (line == LinesTotal() - 1) {
return LineStart(line + 1);
} else {
@ -191,8 +187,7 @@ int Document::SetLevel(int line, int level) {
int prev = cb.SetLevel(line, level);
if (prev != level) {
DocModification mh(SC_MOD_CHANGEFOLD | SC_MOD_CHANGEMARKER,
LineStart(line), 0, 0, 0);
mh.line = line;
LineStart(line), 0, 0, 0, line);
mh.foldLevelNow = level;
mh.foldLevelPrev = prev;
NotifyModified(mh);
@ -292,6 +287,55 @@ int Document::LenChar(int pos) {
}
}
static bool IsTrailByte(int ch) {
return (ch >= 0x80) && (ch < (0x80 + 0x40));
}
static int BytesFromLead(int leadByte) {
if (leadByte > 0xF4) {
// Characters longer than 4 bytes not possible in current UTF-8
return 0;
} else if (leadByte >= 0xF0) {
return 4;
} else if (leadByte >= 0xE0) {
return 3;
} else if (leadByte >= 0xC2) {
return 2;
}
return 0;
}
bool Document::InGoodUTF8(int pos, int &start, int &end) {
int lead = pos;
while ((lead>0) && (pos-lead < 4) && IsTrailByte(static_cast<unsigned char>(cb.CharAt(lead-1))))
lead--;
start = 0;
if (lead > 0) {
start = lead-1;
}
int leadByte = static_cast<unsigned char>(cb.CharAt(start));
int bytes = BytesFromLead(leadByte);
if (bytes == 0) {
return false;
} else {
int trailBytes = bytes - 1;
int len = pos - lead + 1;
if (len > trailBytes)
// pos too far from lead
return false;
// Check that there are enough trails for this lead
int trail = pos + 1;
while ((trail-lead<trailBytes) && (trail < Length())) {
if (!IsTrailByte(static_cast<unsigned char>(cb.CharAt(trail)))) {
return false;
}
trail++;
}
end = start + bytes;
return true;
}
}
// Normalise a position so that it is not halfway through a two byte character.
// This can occur in two situations -
// When lines are terminated with \r\n pairs which should be treated as one character.
@ -318,13 +362,14 @@ int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) {
if (dbcsCodePage) {
if (SC_CP_UTF8 == dbcsCodePage) {
unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos));
while ((pos > 0) && (pos < Length()) && (ch >= 0x80) && (ch < (0x80 + 0x40))) {
// ch is a trail byte
int startUTF = pos;
int endUTF = pos;
if (IsTrailByte(ch) && InGoodUTF8(pos, startUTF, endUTF)) {
// ch is a trail byte within a UTF-8 character
if (moveDir > 0)
pos++;
pos = endUTF;
else
pos--;
ch = static_cast<unsigned char>(cb.CharAt(pos));
pos = startUTF;
}
} else {
// Anchor DBCS calculations at start of line because start of line can
@ -652,7 +697,7 @@ void Document::SetLineIndentation(int line, int indent) {
}
}
int Document::GetLineIndentPosition(int line) {
int Document::GetLineIndentPosition(int line) const {
if (line < 0)
return 0;
int pos = LineStart(line);
@ -793,7 +838,7 @@ void Document::ConvertLineEnds(int eolModeSet) {
EndUndoAction();
}
bool Document::IsWhiteLine(int line) {
bool Document::IsWhiteLine(int line) const {
int currentChar = LineStart(line);
int endLine = LineEnd(line);
while (currentChar < endLine) {
@ -1238,7 +1283,7 @@ const char *Document::SubstituteByPosition(const char *text, int *length) {
return substituted;
}
int Document::LinesTotal() {
int Document::LinesTotal() const {
return cb.Lines();
}
@ -1271,11 +1316,7 @@ void Document::SetCharClasses(const unsigned char *chars, CharClassify::cc newCh
void Document::SetStylingBits(int bits) {
stylingBits = bits;
stylingBitsMask = 0;
for (int bit = 0; bit < stylingBits; bit++) {
stylingBitsMask <<= 1;
stylingBitsMask |= 1;
}
stylingBitsMask = (1 << stylingBits) - 1;
}
void Document::StartStyling(int position, char mask) {
@ -1339,11 +1380,17 @@ void Document::EnsureStyledTo(int pos) {
}
}
void Document::IncrementStyleClock() {
styleClock++;
if (styleClock > 0x100000) {
styleClock = 0;
int Document::SetLineState(int line, int state) {
int statePrevious = cb.SetLineState(line, state);
if (state != statePrevious) {
DocModification mh(SC_MOD_CHANGELINESTATE, 0, 0, 0, 0, line);
NotifyModified(mh);
}
return statePrevious;
}
void Document::IncrementStyleClock() {
styleClock = (styleClock + 1) % 0x100000;
}
void Document::DecorationFillRange(int position, int value, int fillLength) {
@ -1411,6 +1458,11 @@ void Document::NotifySavePoint(bool atSavePoint) {
}
void Document::NotifyModified(DocModification mh) {
if (mh.modificationType & SC_MOD_INSERTTEXT) {
decorations.InsertSpace(mh.position, mh.length);
} else if (mh.modificationType & SC_MOD_DELETETEXT) {
decorations.DeleteRange(mh.position, mh.length);
}
for (int i = 0; i < lenWatchers; i++) {
watchers[i].watcher->NotifyModified(this, mh, watchers[i].userData);
}

View File

@ -138,10 +138,12 @@ public:
int ClampPositionIntoDocument(int pos);
bool IsCrLf(int pos);
int LenChar(int pos);
bool InGoodUTF8(int pos, int &start, int &end);
int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true);
// Gateways to modifying document
void ModifiedAt(int pos);
void CheckReadOnly();
bool DeleteChars(int pos, int len);
bool InsertString(int position, const char *s, int insertLength);
int Undo();
@ -160,7 +162,7 @@ public:
int GetLineIndentation(int line);
void SetLineIndentation(int line, int indent);
int GetLineIndentPosition(int line);
int GetLineIndentPosition(int line) const;
int GetColumn(int position);
int FindColumn(int line, int column);
void Indent(bool forwards, int lineBottom, int lineTop);
@ -187,8 +189,8 @@ public:
void DeleteMarkFromHandle(int markerHandle);
void DeleteAllMarks(int markerNum);
int LineFromHandle(int markerHandle) { return cb.LineFromHandle(markerHandle); }
int LineStart(int line);
int LineEnd(int line);
int LineStart(int line) const;
int LineEnd(int line) const;
int LineEndPosition(int position);
int VCHomePosition(int position);
@ -202,13 +204,13 @@ public:
int ExtendWordSelect(int pos, int delta, bool onlyWordCharacters=false);
int NextWordStart(int pos, int delta);
int NextWordEnd(int pos, int delta);
int Length() { return cb.Length(); }
int Length() const { return cb.Length(); }
void Allocate(int newSize) { cb.Allocate(newSize); }
long FindText(int minPos, int maxPos, const char *s,
bool caseSensitive, bool word, bool wordStart, bool regExp, bool posix, int *length);
long FindText(int iMessage, unsigned long wParam, long lParam);
const char *SubstituteByPosition(const char *text, int *length);
int LinesTotal();
int LinesTotal() const;
void ChangeCase(Range r, bool makeUpperCase);
@ -224,7 +226,7 @@ public:
void IncrementStyleClock();
void DecorationFillRange(int position, int value, int fillLength);
int SetLineState(int line, int state) { return cb.SetLineState(line, state); }
int SetLineState(int line, int state);
int GetLineState(int line) { return cb.GetLineState(line); }
int GetMaxLineState() { return cb.GetMaxLineState(); }
@ -237,15 +239,13 @@ public:
int WordPartLeft(int pos);
int WordPartRight(int pos);
int ExtendStyleRange(int pos, int delta, bool singleLine = false);
bool IsWhiteLine(int line);
bool IsWhiteLine(int line) const;
int ParaUp(int pos);
int ParaDown(int pos);
int IndentSize() { return actualIndentInChars; }
int BraceMatch(int position, int maxReStyle);
private:
void CheckReadOnly();
CharClassify::cc WordCharClass(unsigned char ch);
bool IsWordStartAt(int pos);
bool IsWordEndAt(int pos);

View File

@ -13,7 +13,6 @@
#include "Platform.h"
#include "PropSet.h"
#include "SVector.h"
#include "Accessor.h"
#include "DocumentAccessor.h"
#include "SplitVector.h"

File diff suppressed because it is too large Load Diff

View File

@ -136,6 +136,8 @@ protected: // ScintillaBase subclass needs access to much of Editor
int xCaretMargin; ///< Ensure this many pixels visible on both sides of caret
bool horizontalScrollBarVisible;
int scrollWidth;
bool trackLineWidth;
int lineWidthMaxSeen;
bool verticalScrollBarVisible;
bool endAtLastLine;
bool caretSticky;
@ -297,6 +299,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
virtual void UpdateSystemCaret();
void NeedWrapping(int docLineStart = 0, int docLineEnd = wrapLineLarge);
bool WrapOneLine(Surface *surface, int lineToWrap);
bool WrapLines(bool fullWrap, int priorityWrapLineStart);
void LinesJoin();
void LinesSplit(int pixelWidth);
@ -454,6 +457,8 @@ protected: // ScintillaBase subclass needs access to much of Editor
void AddStyledText(char *buffer, int appendLength);
virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) = 0;
void StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
sptr_t StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
public:
// Public so the COM thunks can access it.

View File

@ -2,7 +2,7 @@
/** @file LexBash.cxx
** Lexer for Bash.
**/
// Copyright 2004-2005 by Neil Hodgson <neilh@scintilla.org>
// Copyright 2004-2007 by Neil Hodgson <neilh@scintilla.org>
// Adapted from LexPerl by Kein-Hong Man <mkh@pl.jaring.my> 2004
// The License.txt file describes the conditions under which this software may be distributed.
@ -20,11 +20,17 @@
#include "Scintilla.h"
#include "SciLexer.h"
// define this if you want 'invalid octals' to be marked as errors
// usually, this is not a good idea, permissive lexing is better
#undef PEDANTIC_OCTAL
#define BASH_BASE_ERROR 65
#define BASH_BASE_DECIMAL 66
#define BASH_BASE_HEX 67
#ifdef PEDANTIC_OCTAL
#define BASH_BASE_OCTAL 68
#define BASH_BASE_OCTAL_ERROR 69
#endif
#define HERE_DELIM_MAX 256
@ -277,7 +283,11 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
ch = chNext;
chNext = chNext2;
} else if (isdigit(chNext)) {
#ifdef PEDANTIC_OCTAL
numBase = BASH_BASE_OCTAL;
#else
numBase = BASH_BASE_HEX;
#endif
}
}
} else if (iswordstart(ch)) {
@ -369,14 +379,16 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
// hex digit 0-9a-fA-F
} else
goto numAtEnd;
#ifdef PEDANTIC_OCTAL
} else if (numBase == BASH_BASE_OCTAL ||
numBase == BASH_BASE_OCTAL_ERROR) {
if (digit > 7) {
if (digit <= 9) {
numBase = BASH_BASE_OCTAL_ERROR;
numBase = BASH_BASE_OCTAL_ERROR;
} else
goto numAtEnd;
}
#endif
} else if (numBase == BASH_BASE_ERROR) {
if (digit > 9)
goto numAtEnd;
@ -394,8 +406,11 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
}
} else {
numAtEnd:
if (numBase == BASH_BASE_ERROR ||
numBase == BASH_BASE_OCTAL_ERROR)
if (numBase == BASH_BASE_ERROR
#ifdef PEDANTIC_OCTAL
|| numBase == BASH_BASE_OCTAL_ERROR
#endif
)
state = SCE_SH_ERROR;
styler.ColourTo(i - 1, state);
state = SCE_SH_DEFAULT;

View File

@ -32,6 +32,24 @@ static bool IsSpaceEquiv(int state) {
(state == SCE_C_COMMENTDOCKEYWORDERROR);
}
// Preconditions: sc.currentPos points to a character after '+' or '-'.
// The test for pos reaching 0 should be redundant,
// and is in only for safety measures.
// Limitation: this code will give the incorrect answer for code like
// a = b+++/ptn/...
// Putting a space between the '++' post-inc operator and the '+' binary op
// fixes this, and is highly recommended for readability anyway.
static bool FollowsPostfixOperator(StyleContext &sc, Accessor &styler) {
int pos = (int) sc.currentPos;
while (--pos > 0) {
char ch = styler[pos];
if (ch == '+' || ch == '-') {
return styler[pos - 1] == ch;
}
}
return false;
}
static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
Accessor &styler, bool caseSensitive) {
@ -42,7 +60,8 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo
bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;
CharacterSet setOKBeforeRE(CharacterSet::setNone, "(=,");
CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-");
CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-");
CharacterSet setDoxygen(CharacterSet::setLower, "$@\\&<>#{}[]");
@ -297,7 +316,8 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo
sc.SetState(SCE_C_COMMENTLINEDOC);
else
sc.SetState(SCE_C_COMMENTLINE);
} else if (sc.ch == '/' && setOKBeforeRE.Contains(chPrevNonWhite)) {
} else if (sc.ch == '/' && setOKBeforeRE.Contains(chPrevNonWhite) &&
(!setCouldBePostOp.Contains(chPrevNonWhite) || !FollowsPostfixOperator(sc, styler))) {
sc.SetState(SCE_C_REGEX); // JavaScript's RegEx
} else if (sc.ch == '\"') {
sc.SetState(SCE_C_STRING);
@ -337,7 +357,7 @@ static bool IsStreamCommentStyle(int style) {
// Store both the current line's fold level and the next lines in the
// level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "} else {".
static void FoldCppDoc(unsigned int startPos, int length, int initStyle,
static void FoldCppDoc(unsigned int startPos, int length, int initStyle,
WordList *[], Accessor &styler) {
bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;

View File

@ -565,7 +565,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
break;
}
if (style == SCE_HJ_SYMBOLS) {
chPrevNonWhite = styler.SafeGetCharAt(back);
chPrevNonWhite = static_cast<unsigned char>(styler.SafeGetCharAt(back));
}
}
@ -676,10 +676,13 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
case SCE_HJ_COMMENTDOC:
//case SCE_HJ_COMMENTLINE: // removed as this is a common thing done to hide
// the end of script marker from some JS interpreters.
case SCE_HB_COMMENTLINE:
case SCE_HBA_COMMENTLINE:
case SCE_HJ_DOUBLESTRING:
case SCE_HJ_SINGLESTRING:
case SCE_HJ_REGEX:
case SCE_HB_STRING:
case SCE_HBA_STRING:
case SCE_HP_STRING:
case SCE_HP_TRIPLE:
case SCE_HP_TRIPLEDOUBLE:
@ -688,9 +691,8 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
// check if the closing tag is a script tag
if (state == SCE_HJ_COMMENTLINE || isXml) {
char tag[7]; // room for the <script> tag
char chr; // current char
int j=0;
chr = styler.SafeGetCharAt(i+2);
int j = 0;
char chr = styler.SafeGetCharAt(i+2);
while (j < 6 && !IsASpace(chr)) {
tag[j++] = static_cast<char>(MakeLowerCase(chr));
chr = styler.SafeGetCharAt(i+2+j);
@ -740,7 +742,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
levelCurrent++;
}
// should be better
ch = styler.SafeGetCharAt(i);
ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
continue;
}
@ -779,7 +781,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
if (foldHTMLPreprocessor)
levelCurrent++;
// should be better
ch = styler.SafeGetCharAt(i);
ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
continue;
}
@ -958,12 +960,12 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
}
// find the length of the word
int size = 1;
while (setHTMLWord.Contains(styler.SafeGetCharAt(i + size)))
while (setHTMLWord.Contains(static_cast<unsigned char>(styler.SafeGetCharAt(i + size))))
size++;
styler.ColourTo(i + size - 1, StateToPrint);
i += size - 1;
visibleChars += size - 1;
ch = styler.SafeGetCharAt(i);
ch = static_cast<unsigned char>(styler.SafeGetCharAt(i));
if (scriptLanguage == eScriptSGMLblock) {
state = SCE_H_SGML_BLOCK_DEFAULT;
} else {
@ -1362,7 +1364,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
while (isascii(chNext) && islower(chNext)) { // gobble regex flags
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
}
}
styler.ColourTo(i, StateToPrint);
@ -1372,7 +1374,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
if (chNext == '\\' || chNext == '/') {
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
}
}
break;
@ -1460,7 +1462,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
state = SCE_HP_TRIPLEDOUBLE;
ch = ' ';
chPrev = ' ';
chNext = styler.SafeGetCharAt(i + 1);
chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
} else {
// state = statePrintForState(SCE_HP_STRING,inScriptType);
state = SCE_HP_STRING;
@ -1472,7 +1474,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
state = SCE_HP_TRIPLE;
ch = ' ';
chPrev = ' ';
chNext = styler.SafeGetCharAt(i + 1);
chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
} else {
state = SCE_HP_CHARACTER;
}
@ -1498,7 +1500,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
state = SCE_HP_TRIPLEDOUBLE;
ch = ' ';
chPrev = ' ';
chNext = styler.SafeGetCharAt(i + 1);
chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
} else {
state = SCE_HP_STRING;
}
@ -1508,7 +1510,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
state = SCE_HP_TRIPLE;
ch = ' ';
chPrev = ' ';
chNext = styler.SafeGetCharAt(i + 1);
chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
} else {
state = SCE_HP_CHARACTER;
}
@ -1528,7 +1530,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
}
} else if (ch == '\"') {
styler.ColourTo(i, StateToPrint);
@ -1540,7 +1542,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
chNext = static_cast<unsigned char>(styler.SafeGetCharAt(i + 1));
}
} else if (ch == '\'') {
styler.ColourTo(i, StateToPrint);

View File

@ -89,12 +89,16 @@ static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle,
else if (sc.state == SCE_HA_STRING) {
if (sc.ch == '\"') {
sc.ForwardSetState(SCE_HA_DEFAULT);
} else if (sc.ch == '\\') {
sc.Forward();
}
}
// Char
else if (sc.state == SCE_HA_CHARACTER) {
if (sc.ch == '\'') {
sc.ForwardSetState(SCE_HA_DEFAULT);
} else if (sc.ch == '\\') {
sc.Forward();
}
}
// Number
@ -189,7 +193,7 @@ static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle,
sc.SetState(SCE_HA_STRING);
}
// Character
else if (sc.Match('\'') && IsWhitespace(sc.GetRelative(-1)) ) {
else if (sc.Match('\'')) {
sc.SetState(SCE_HA_CHARACTER);
}
// Stringstart

View File

@ -819,7 +819,7 @@ static bool strstart(const char *haystack, const char *needle) {
return strncmp(haystack, needle, strlen(needle)) == 0;
}
static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLine) {
static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLine, int &startValue) {
if (lineBuffer[0] == '>') {
// Command or return status
return SCE_ERR_CMD;
@ -902,7 +902,9 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin
// Microsoft: <filename>(<line>,<column>)<message>
// CTags: \t<message>
// Lua 5 traceback: \t<filename>:<line>:<message>
// Lua 5.1: <exe>: <filename>:<line>:<message>
bool initialTab = (lineBuffer[0] == '\t');
bool initialColonPart = false;
enum { stInitial,
stGccStart, stGccDigit, stGcc,
stMsStart, stMsDigit, stMsBracket, stMsVc, stMsDigitComma, stMsDotNet,
@ -917,10 +919,12 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin
if (state == stInitial) {
if (ch == ':') {
// May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix)
if ((chNext != '\\') && (chNext != '/')) {
if ((chNext != '\\') && (chNext != '/') && (chNext != ' ')) {
// This check is not completely accurate as may be on
// GTK+ with a file name that includes ':'.
state = stGccStart;
state = stGccStart;
} else if (chNext == ' ') { // indicates a Lua 5.1 error message
initialColonPart = true;
}
} else if ((ch == '(') && Is1To9(chNext) && (!initialTab)) {
// May be Microsoft
@ -935,6 +939,7 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin
} else if (state == stGccDigit) { // <filename>:<line>
if (ch == ':') {
state = stGcc; // :9.*: is GCC
startValue = i + 1;
break;
} else if (!Is0To9(ch)) {
state = stUnrecognized;
@ -995,7 +1000,7 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin
}
}
if (state == stGcc) {
return SCE_ERR_GCC;
return initialColonPart ? SCE_ERR_LUA : SCE_ERR_GCC;
} else if ((state == stMsVc) || (state == stMsDotNet)) {
return SCE_ERR_MS;
} else if ((state == stCtagsStringDollar) || (state == stCtags)) {
@ -1010,8 +1015,16 @@ static void ColouriseErrorListLine(
char *lineBuffer,
unsigned int lengthLine,
unsigned int endPos,
Accessor &styler) {
styler.ColourTo(endPos, RecogniseErrorListLine(lineBuffer, lengthLine));
Accessor &styler,
bool valueSeparate) {
int startValue = -1;
int style = RecogniseErrorListLine(lineBuffer, lengthLine, startValue);
if (valueSeparate && (startValue >= 0)) {
styler.ColourTo(endPos - (lengthLine - startValue), style);
styler.ColourTo(endPos, SCE_ERR_VALUE);
} else {
styler.ColourTo(endPos, style);
}
}
static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
@ -1019,17 +1032,18 @@ static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordLi
styler.StartAt(startPos);
styler.StartSegment(startPos);
unsigned int linePos = 0;
bool valueSeparate = styler.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0;
for (unsigned int i = startPos; i < startPos + length; i++) {
lineBuffer[linePos++] = styler[i];
if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
// End of line (or of line buffer) met, colourise it
lineBuffer[linePos] = '\0';
ColouriseErrorListLine(lineBuffer, linePos, i, styler);
ColouriseErrorListLine(lineBuffer, linePos, i, styler, valueSeparate);
linePos = 0;
}
}
if (linePos > 0) { // Last line does not have ending characters
ColouriseErrorListLine(lineBuffer, linePos, startPos + length - 1, styler);
ColouriseErrorListLine(lineBuffer, linePos, startPos + length - 1, styler, valueSeparate);
}
}

View File

@ -2,7 +2,7 @@
/** @file LexPerl.cxx
** Lexer for subset of Perl.
**/
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
// Lexical analysis fixes by Kein-Hong Man <mkh@pl.jaring.my>
// The License.txt file describes the conditions under which this software may be distributed.
@ -133,6 +133,10 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
WordList &keywords = *keywordlists[0];
// keywords that forces /PATTERN/ at all times
WordList reWords;
reWords.Set("elsif if split while");
class HereDocCls {
public:
int State; // 0: '<<' encountered
@ -187,6 +191,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
//char sooked[100];
//sooked[sookedpos] = '\0';
styler.StartAt(startPos, static_cast<char>(STYLE_MAX));
// If in a long distance lexical state, seek to the beginning to find quote characters
// Perl strings can be multi-line with embedded newlines, so backtrack.
// Perl numbers have additional state during lexing, so backtrack too.
@ -197,6 +202,14 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
startPos = styler.LineStart(styler.GetLine(startPos));
state = styler.StyleAt(startPos - 1);
}
// Backtrack for format body.
if (state == SCE_PL_FORMAT) {
while ((startPos > 1) && (styler.StyleAt(startPos) != SCE_PL_FORMAT_IDENT)) {
startPos--;
}
startPos = styler.LineStart(styler.GetLine(startPos));
state = styler.StyleAt(startPos - 1);
}
if ( state == SCE_PL_STRING_Q
|| state == SCE_PL_STRING_QQ
|| state == SCE_PL_STRING_QX
@ -210,6 +223,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
|| state == SCE_PL_NUMBER
|| state == SCE_PL_IDENTIFIER
|| state == SCE_PL_ERROR
|| state == SCE_PL_SUB_PROTOTYPE
) {
while ((startPos > 1) && (styler.StyleAt(startPos - 1) == state)) {
startPos--;
@ -233,7 +247,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
backflag = BACK_KEYWORD;
}
styler.StartAt(startPos);
styler.StartAt(startPos, static_cast<char>(STYLE_MAX));
char chPrev = styler.SafeGetCharAt(startPos - 1);
if (startPos == 0)
chPrev = '\n';
@ -294,6 +308,12 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
}
}
}
if (HereDoc.State == 4 && isEOLChar(ch)) {
// Start of format body.
HereDoc.State = 0;
styler.ColourTo(i - 1, state);
state = SCE_PL_FORMAT;
}
if (state == SCE_PL_DEFAULT) {
if ((isascii(ch) && isdigit(ch)) || (isascii(chNext) && isdigit(chNext) &&
@ -431,8 +451,13 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
styler.ColourTo(i, SCE_PL_DATASECTION);
state = SCE_PL_DATASECTION;
} else {
if (isMatch(styler, lengthDoc, styler.GetStartSegment(), "format")) {
state = SCE_PL_FORMAT_IDENT;
HereDoc.State = 0;
} else {
state = SCE_PL_DEFAULT;
}
styler.ColourTo(i, SCE_PL_WORD);
state = SCE_PL_DEFAULT;
backflag = BACK_KEYWORD;
backPos = i;
}
@ -440,8 +465,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
chNext = styler.SafeGetCharAt(i + 1);
// a repetition operator 'x'
} else if (state == SCE_PL_OPERATOR) {
styler.ColourTo(i, SCE_PL_OPERATOR);
state = SCE_PL_DEFAULT;
goto handleOperator;
// quote-like delimiter, skip one char if double-char delimiter
} else {
i = kw - 1;
@ -502,6 +527,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
}
backflag = BACK_NONE;
} else if (ch == '%') {
backflag = BACK_NONE;
if (!isascii(chNext) || isalpha(chNext) || chNext == '#' || chNext == '$'
|| chNext == '_' || chNext == '!' || chNext == '^') {
state = SCE_PL_HASH;
@ -516,10 +542,10 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
} else if (chNext == '{') {
styler.ColourTo(i, SCE_PL_HASH);
} else {
styler.ColourTo(i, SCE_PL_OPERATOR);
goto handleOperator;
}
backflag = BACK_NONE;
} else if (ch == '*') {
backflag = BACK_NONE;
char strch[2];
strch[0] = chNext;
strch[1] = '\0';
@ -542,9 +568,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
ch = chNext;
chNext = chNext2;
}
styler.ColourTo(i, SCE_PL_OPERATOR);
goto handleOperator;
}
backflag = BACK_NONE;
} else if (ch == '/' || (ch == '<' && chNext == '<')) {
// Explicit backward peeking to set a consistent preferRE for
// any slash found, so no longer need to track preferRE state.
@ -556,6 +581,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
bool hereDocSpace = false; // these are for corner case:
bool hereDocScalar = false; // SCALAR [whitespace] '<<'
unsigned int bk = (i > 0)? i - 1: 0;
unsigned int bkend;
char bkch;
styler.Flush();
if (styler.StyleAt(bk) == SCE_PL_DEFAULT)
@ -631,26 +657,21 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
if (bkstyle == SCE_PL_DEFAULT ||
bkstyle == SCE_PL_COMMENTLINE) {
} else if (bkstyle == SCE_PL_OPERATOR) {
// gcc 3.2.3 bloats if more compact form used
bkch = styler.SafeGetCharAt(bk);
if (bkch == '>') { // "->"
if (styler.SafeGetCharAt(bk - 1) == '-') {
preferRE = false;
break;
}
} else if (bkch == ':') { // "::"
if (styler.SafeGetCharAt(bk - 1) == ':') {
preferRE = false;
break;
}
}
} else {// bare identifier, usually a function call but Perl
// optimizes them as pseudo-constants, then the next
// '/' will be a divide; favour divide over regex
// if there is a whitespace after the '/'
if (isspacechar(chNext)) {
preferRE = false;
// test for "->" and "::"
if ((bkch == '>' && styler.SafeGetCharAt(bk - 1) == '-')
|| (bkch == ':' && styler.SafeGetCharAt(bk - 1) == ':')) {
preferRE = false;
break;
}
} else {
// bare identifier, if '/', /PATTERN/ unless digit/space immediately after '/'
if (!isHereDoc &&
(isspacechar(chNext) || isdigit(chNext)))
preferRE = false;
// HERE docs cannot have a space after the >>
if (isspacechar(chNext))
preferRE = false;
break;
}
bk--;
@ -659,8 +680,24 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
case SCE_PL_SCALAR: // for $var<< case
hereDocScalar = true;
break;
// other styles uses the default, preferRE=false
// for HERE docs, always true for preferRE
case SCE_PL_WORD:
preferRE = true;
if (isHereDoc)
break;
// adopt heuristics similar to vim-style rules:
// keywords always forced as /PATTERN/: split, if, elsif, while
// everything else /PATTERN/ unless digit/space immediately after '/'
bkend = bk + 1;
while (bk > 0 && styler.StyleAt(bk-1) == SCE_PL_WORD) {
bk--;
}
if (isPerlKeyword(bk, bkend, reWords, styler))
break;
if (isspacechar(chNext) || isdigit(chNext))
preferRE = false;
break;
// other styles uses the default, preferRE=false
case SCE_PL_POD:
case SCE_PL_POD_VERB:
case SCE_PL_HERE_Q:
@ -670,6 +707,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
break;
}
}
backflag = BACK_NONE;
if (isHereDoc) { // handle HERE doc
// if SCALAR whitespace '<<', *always* a HERE doc
if (preferRE || (hereDocSpace && hereDocScalar)) {
@ -679,7 +717,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
i++;
ch = chNext;
chNext = chNext2;
styler.ColourTo(i, SCE_PL_OPERATOR);
goto handleOperator;
}
} else { // handle regexp
if (preferRE) {
@ -687,10 +725,9 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
Quote.New(1);
Quote.Open(ch);
} else { // / operator
styler.ColourTo(i, SCE_PL_OPERATOR);
goto handleOperator;
}
}
backflag = BACK_NONE;
} else if (ch == '<') {
// looks forward for matching > on same line
unsigned int fw = i + 1;
@ -699,24 +736,23 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
if (fwch == ' ') {
if (styler.SafeGetCharAt(fw-1) != '\\' ||
styler.SafeGetCharAt(fw-2) != '\\')
break;
goto handleOperator;
} else if (isEOLChar(fwch) || isspacechar(fwch)) {
break;
goto handleOperator;
} else if (fwch == '>') {
if ((fw - i) == 2 && // '<=>' case
styler.SafeGetCharAt(fw-1) == '=') {
styler.ColourTo(fw, SCE_PL_OPERATOR);
} else {
styler.ColourTo(fw, SCE_PL_IDENTIFIER);
goto handleOperator;
}
styler.ColourTo(fw, SCE_PL_IDENTIFIER);
i = fw;
ch = fwch;
chNext = styler.SafeGetCharAt(i+1);
}
fw++;
}
styler.ColourTo(i, SCE_PL_OPERATOR);
backflag = BACK_NONE;
if (fw == lengthDoc)
goto handleOperator;
} else if (ch == '=' // POD
&& isalpha(chNext)
&& (isEOLChar(chPrev))) {
@ -733,6 +769,35 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
ch = chNext;
chNext = chNext2;
backflag = BACK_NONE;
} else if (ch == '-' // bareword promotion (-FOO cases)
&& ((isascii(chNext) && isalpha(chNext)) || chNext == '_')
&& backflag != BACK_NONE) {
state = SCE_PL_IDENTIFIER;
backflag = BACK_NONE;
} else if (ch == '(' && i > 0) {
// backtrack to identify if we're starting a sub prototype
// for generality, we need to ignore whitespace/comments
unsigned int bk = i - 1; // i > 0 tested above
styler.Flush();
while (bk > 0 && (styler.StyleAt(bk) == SCE_PL_DEFAULT ||
styler.StyleAt(bk) == SCE_PL_COMMENTLINE)) {
bk--;
}
if (bk == 0 || styler.StyleAt(bk) != SCE_PL_IDENTIFIER) // check identifier
goto handleOperator;
while (bk > 0 && (styler.StyleAt(bk) == SCE_PL_IDENTIFIER)) {
bk--;
}
while (bk > 0 && (styler.StyleAt(bk) == SCE_PL_DEFAULT ||
styler.StyleAt(bk) == SCE_PL_COMMENTLINE)) {
bk--;
}
if (bk < 2 || styler.StyleAt(bk) != SCE_PL_WORD // check "sub" keyword
|| !styler.Match(bk - 2, "sub")) // assume suffix is unique!
goto handleOperator;
state = SCE_PL_SUB_PROTOTYPE;
backflag = BACK_NONE;
backPos = i; // needed for restart
} else if (isPerlOperator(ch)) {
if (ch == '.' && chNext == '.') { // .. and ...
i++;
@ -741,10 +806,14 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
ch = styler.SafeGetCharAt(i);
chNext = styler.SafeGetCharAt(i + 1);
}
handleOperator:
styler.ColourTo(i, SCE_PL_OPERATOR);
backflag = BACK_OPERATOR;
backPos = i;
} else {
} else if (ch == 4 || ch == 26) { // ^D and ^Z ends valid perl source
styler.ColourTo(i, SCE_PL_DATASECTION);
state = SCE_PL_DATASECTION;
} else {
// keep colouring defaults to make restart easier
styler.ColourTo(i, SCE_PL_DEFAULT);
}
@ -756,8 +825,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
} else if (numState <= PERLNUM_FLOAT) {
// non-decimal number or float exponent, consume next dot
styler.ColourTo(i - 1, SCE_PL_NUMBER);
styler.ColourTo(i, SCE_PL_OPERATOR);
state = SCE_PL_DEFAULT;
goto handleOperator;
} else { // decimal or vectors allows dots
dotCount++;
if (numState == PERLNUM_DECIMAL) {
@ -772,10 +841,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
goto numAtEnd;
}
}
} else if (ch == '_' && numState == PERLNUM_DECIMAL) {
if (!isdigit(chNext)) {
goto numAtEnd;
}
} else if (ch == '_') {
// permissive underscoring for number and vector literals
} else if (!isascii(ch) || isalnum(ch)) {
if (numState == PERLNUM_VECTOR || numState == PERLNUM_V_VECTOR) {
if (!isascii(ch) || isalpha(ch)) {
@ -899,6 +966,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
i = oldi;
styler.ColourTo(i, SCE_PL_OPERATOR);
state = SCE_PL_DEFAULT;
backflag = BACK_OPERATOR;
backPos = i;
HereDoc.State = 0;
goto restartLexer;
} else {
@ -1118,7 +1187,63 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
} else if (ch == Quote.Up) {
Quote.Count++;
}
}
} else if (state == SCE_PL_SUB_PROTOTYPE) {
char strch[2];
strch[0] = ch;
strch[1] = '\0';
if (NULL != strstr("\\[$@%&*];", strch)) {
// keep going
} else if (ch == ')') {
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
} else {
// abandon prototype, restart from '('
i = backPos;
styler.ColourTo(i, SCE_PL_OPERATOR);
ch = styler.SafeGetCharAt(i);
chNext = styler.SafeGetCharAt(i + 1);
state = SCE_PL_DEFAULT;
}
} else if (state == SCE_PL_FORMAT_IDENT) {
// occupies different HereDoc states to avoid clashing with HERE docs
if (HereDoc.State == 0) {
if ((isascii(ch) && isalpha(ch)) || ch == '_' // probable identifier
|| ch == '=') { // no identifier
HereDoc.State = 3;
HereDoc.Quoted = false; // whitespace flag
} else if (ch == ' ' || ch == '\t') {
styler.ColourTo(i, SCE_PL_DEFAULT);
} else {
state = SCE_PL_DEFAULT;
HereDoc.State = 0;
goto restartLexer;
}
}
if (HereDoc.State == 3) { // with just a '=', state goes 0->3->4
if (ch == '=') {
styler.ColourTo(i, SCE_PL_FORMAT_IDENT);
state = SCE_PL_DEFAULT;
HereDoc.State = 4;
} else if (ch == ' ' || ch == '\t') {
HereDoc.Quoted = true;
} else if (isEOLChar(ch) || (HereDoc.Quoted && ch != '=')) {
// abandon format, restart from after 'format'
i = backPos + 1;
ch = styler.SafeGetCharAt(i);
chNext = styler.SafeGetCharAt(i + 1);
state = SCE_PL_DEFAULT;
HereDoc.State = 0;
}
}
} else if (state == SCE_PL_FORMAT) {
if (isEOLChar(chPrev)) {
styler.ColourTo(i - 1, state);
if (ch == '.' && isEOLChar(chNext)) {
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
}
}
}
}
if (state == SCE_PL_ERROR) {
break;
@ -1256,5 +1381,5 @@ static const char * const perlWordListDesc[] = {
0
};
LexerModule lmPerl(SCLEX_PERL, ColourisePerlDoc, "perl", FoldPerlDoc, perlWordListDesc);
LexerModule lmPerl(SCLEX_PERL, ColourisePerlDoc, "perl", FoldPerlDoc, perlWordListDesc, 8);

View File

@ -217,10 +217,8 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle,
sc.SetState(SCE_P_DEFAULT);
}
} else if (sc.state == SCE_P_DECORATOR) {
if (sc.ch == '\r' || sc.ch == '\n') {
if (!IsAWordChar(sc.ch)) {
sc.SetState(SCE_P_DEFAULT);
} else if (sc.ch == '#') {
sc.SetState((sc.chNext == '#') ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE);
}
} else if ((sc.state == SCE_P_STRING) || (sc.state == SCE_P_CHARACTER)) {
if (sc.ch == '\\') {

View File

@ -25,7 +25,7 @@ using namespace Scintilla;
#endif
static inline bool IsAWordChar(int ch) {
return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
return (ch < 0x80) && (isalnum(ch) || ch == '_');
}
static inline bool IsAWordStart(int ch) {

View File

@ -89,7 +89,7 @@ public:
body = 0;
}
int Partitions() {
int Partitions() const {
return body->Length()-1;
}
@ -141,7 +141,7 @@ public:
body->Delete(partition);
}
int PositionFromPartition(int partition) {
int PositionFromPartition(int partition) const {
PLATFORM_ASSERT(partition >= 0);
PLATFORM_ASSERT(partition < body->Length());
if ((partition < 0) || (partition >= body->Length())) {

View File

@ -1870,6 +1870,34 @@ void Window::SetTitle(const char *s) {
gtk_window_set_title(GTK_WINDOW(id), s);
}
/* Returns rectangle of monitor pt is on, both rect and pt are in Window's
gdk window coordinates */
PRectangle Window::GetMonitorRect(Point pt) {
gint x_offset, y_offset;
pt = pt;
gdk_window_get_origin(PWidget(id)->window, &x_offset, &y_offset);
// gtk 2.2+
#if GTK_MAJOR_VERSION > 2 || (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 2)
{
GdkScreen* screen;
gint monitor_num;
GdkRectangle rect;
screen = gtk_widget_get_screen(PWidget(id));
monitor_num = gdk_screen_get_monitor_at_point(screen, pt.x + x_offset, pt.y + y_offset);
gdk_screen_get_monitor_geometry(screen, monitor_num, &rect);
rect.x -= x_offset;
rect.y -= y_offset;
return PRectangle(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
}
#else
return PRectangle(-x_offset, -y_offset, (-x_offset) + gdk_screen_width(),
(-y_offset) + gdk_screen_height());
#endif
}
struct ListImage {
const char *xpm_data;
#if GTK_MAJOR_VERSION < 2

View File

@ -14,13 +14,12 @@
#include "Scintilla.h"
#include "ContractionState.h"
#include "SVector.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"
#include "CellBuffer.h"
#include "KeyMap.h"
#include "RunStyles.h"
#include "Indicator.h"
#include "XPM.h"
#include "LineMarker.h"
@ -126,6 +125,11 @@ int LineLayout::LineLastVisible(int line) const {
}
}
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;
@ -341,12 +345,23 @@ void LineLayoutCache::Dispose(LineLayout *ll) {
}
void BreakFinder::Insert(int val) {
// Expand if needed
if (saeLen >= saeSize) {
saeSize *= 2;
int *selAndEdgeNew = new int[saeSize];
for (unsigned int j = 0; j<saeLen; j++) {
selAndEdgeNew[j] = selAndEdge[j];
}
delete []selAndEdge;
selAndEdge = selAndEdgeNew;
}
if (val >= nextBreak) {
for (unsigned int j = 0; j<saeLen; j++) {
if (val == selAndEdge[j]) {
return;
} if (val < selAndEdge[j]) {
for (unsigned int k = saeLen; j>k; k--) {
for (unsigned int k = saeLen; k>j; k--) {
selAndEdge[k] = selAndEdge[k-1];
}
saeLen++;
@ -359,17 +374,32 @@ void BreakFinder::Insert(int val) {
}
}
BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_, int xStart) :
extern bool BadUTF(const char *s, int len, int &trailBytes);
static int NextBadU(const char *s, int p, int len, int &trailBytes) {
while (p < len) {
p++;
if (BadUTF(s + p, len - p, trailBytes))
return p;
}
return -1;
}
BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_, bool utf8_, int xStart) :
ll(ll_),
lineStart(lineStart_),
lineEnd(lineEnd_),
posLineStart(posLineStart_),
utf8(utf8_),
nextBreak(lineStart_),
saeSize(0),
saeLen(0),
saeCurrentPos(0),
saeNext(0),
subBreak(-1) {
for (unsigned int j=0; j < sizeof(selAndEdge) / sizeof(selAndEdge[0]); j++) {
saeSize = 8;
selAndEdge = new int[saeSize];
for (unsigned int j=0; j < saeSize; j++) {
selAndEdge[j] = 0;
}
@ -388,9 +418,24 @@ BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posL
Insert(ll->edgeColumn - 1);
Insert(lineEnd - 1);
if (utf8) {
int trailBytes=0;
for (int pos = -1;;) {
pos = NextBadU(ll->chars, pos, lineEnd, trailBytes);
if (pos < 0)
break;
Insert(pos-1);
Insert(pos);
}
}
saeNext = (saeLen > 0) ? selAndEdge[0] : -1;
}
BreakFinder::~BreakFinder() {
delete []selAndEdge;
}
int BreakFinder::First() {
return nextBreak;
}

View File

@ -59,6 +59,7 @@ public:
void Invalidate(validLevel validity_);
int LineStart(int line) const;
int LineLastVisible(int line) const;
bool InLine(int offset, int line) const;
void SetLineStart(int line, int start);
void SetBracesHighlight(Range rangeLine, Position braces[],
char bracesMatchStyle, int xHighlight);
@ -123,15 +124,18 @@ class BreakFinder {
int lineStart;
int lineEnd;
int posLineStart;
bool utf8;
int nextBreak;
int selAndEdge[5];
int *selAndEdge;
unsigned int saeSize;
unsigned int saeLen;
unsigned int saeCurrentPos;
int saeNext;
int subBreak;
void Insert(int val);
public:
BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_, int xStart);
BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_, bool utf8_, int xStart);
~BreakFinder();
int First();
int Next();
};

View File

@ -333,8 +333,6 @@ char *SContainer::StringAllocate(const char *s, lenpos_t len) {
// End SString functions
bool PropSet::caseSensitiveFilenames = false;
PropSet::PropSet() {
superPS = 0;
for (int root = 0; root < hashRoots; root++)
@ -426,7 +424,7 @@ void PropSet::SetMultiple(const char *s) {
Set(s);
}
SString PropSet::Get(const char *key) {
SString PropSet::Get(const char *key) const {
unsigned int hash = HashString(key, strlen(key));
for (Property *p = props[hash % hashRoots]; p; p = p->next) {
if ((hash == p->hash) && (0 == strcmp(p->key, key))) {
@ -441,21 +439,6 @@ SString PropSet::Get(const char *key) {
}
}
bool PropSet::IncludesVar(const char *value, const char *key) {
const char *var = strstr(value, "$(");
while (var) {
if (isprefix(var + 2, key) && (var[2 + strlen(key)] == ')')) {
// Found $(key) which would lead to an infinite loop so exit
return true;
}
var = strstr(var + 2, ")");
if (var)
var = strstr(var + 1, "$(");
}
return false;
}
// There is some inconsistency between GetExpanded("foo") and Expand("$(foo)").
// A solution is to keep a stack of variables that have been expanded, so that
// recursive expansions can be skipped. For now I'll just use the C++ stack
@ -473,7 +456,7 @@ struct VarChain {
const VarChain *link;
};
static int ExpandAllInPlace(PropSet &props, SString &withVars, int maxExpands, const VarChain &blankVars = VarChain()) {
static int ExpandAllInPlace(const PropSet &props, SString &withVars, int maxExpands, const VarChain &blankVars = VarChain()) {
int varStart = withVars.search("$(");
while ((varStart >= 0) && (maxExpands > 0)) {
int varEnd = withVars.search(")", varStart+2);
@ -509,20 +492,19 @@ static int ExpandAllInPlace(PropSet &props, SString &withVars, int maxExpands, c
return maxExpands;
}
SString PropSet::GetExpanded(const char *key) {
SString PropSet::GetExpanded(const char *key) const {
SString val = Get(key);
ExpandAllInPlace(*this, val, 100, VarChain(key));
return val;
}
SString PropSet::Expand(const char *withVars, int maxExpands) {
SString PropSet::Expand(const char *withVars, int maxExpands) const {
SString val = withVars;
ExpandAllInPlace(*this, val, maxExpands);
return val;
}
int PropSet::GetInt(const char *key, int defaultValue) {
int PropSet::GetInt(const char *key, int defaultValue) const {
SString val = GetExpanded(key);
if (val.length())
return val.value();
@ -542,118 +524,6 @@ bool isprefix(const char *target, const char *prefix) {
return true;
}
static bool IsSuffix(const char *target, const char *suffix, bool caseSensitive) {
size_t lentarget = strlen(target);
size_t lensuffix = strlen(suffix);
if (lensuffix > lentarget)
return false;
if (caseSensitive) {
for (int i = static_cast<int>(lensuffix) - 1; i >= 0; i--) {
if (target[i + lentarget - lensuffix] != suffix[i])
return false;
}
} else {
for (int i = static_cast<int>(lensuffix) - 1; i >= 0; i--) {
if (MakeUpperCase(target[i + lentarget - lensuffix]) !=
MakeUpperCase(suffix[i]))
return false;
}
}
return true;
}
SString PropSet::GetWild(const char *keybase, const char *filename) {
for (int root = 0; root < hashRoots; root++) {
for (Property *p = props[root]; p; p = p->next) {
if (isprefix(p->key, keybase)) {
char * orgkeyfile = p->key + strlen(keybase);
char *keyfile = NULL;
if (strstr(orgkeyfile, "$(") == orgkeyfile) {
char *cpendvar = strchr(orgkeyfile, ')');
if (cpendvar) {
*cpendvar = '\0';
SString s = GetExpanded(orgkeyfile + 2);
*cpendvar = ')';
keyfile = StringDup(s.c_str());
}
}
char *keyptr = keyfile;
if (keyfile == NULL)
keyfile = orgkeyfile;
for (;;) {
char *del = strchr(keyfile, ';');
if (del == NULL)
del = keyfile + strlen(keyfile);
char delchr = *del;
*del = '\0';
if (*keyfile == '*') {
if (IsSuffix(filename, keyfile + 1, caseSensitiveFilenames)) {
*del = delchr;
delete []keyptr;
return p->val;
}
} else if (0 == strcmp(keyfile, filename)) {
*del = delchr;
delete []keyptr;
return p->val;
}
if (delchr == '\0')
break;
*del = delchr;
keyfile = del + 1;
}
delete []keyptr;
if (0 == strcmp(p->key, keybase)) {
return p->val;
}
}
}
}
if (superPS) {
// Failed here, so try in base property set
return superPS->GetWild(keybase, filename);
} else {
return "";
}
}
// GetNewExpand does not use Expand as it has to use GetWild with the filename for each
// variable reference found.
SString PropSet::GetNewExpand(const char *keybase, const char *filename) {
char *base = StringDup(GetWild(keybase, filename).c_str());
char *cpvar = strstr(base, "$(");
int maxExpands = 1000; // Avoid infinite expansion of recursive definitions
while (cpvar && (maxExpands > 0)) {
char *cpendvar = strchr(cpvar, ')');
if (cpendvar) {
int lenvar = cpendvar - cpvar - 2; // Subtract the $()
char *var = StringDup(cpvar + 2, lenvar);
SString val = GetWild(var, filename);
if (0 == strcmp(var, keybase))
val.clear(); // Self-references evaluate to empty string
size_t newlenbase = strlen(base) + val.length() - lenvar;
char *newbase = new char[newlenbase];
strncpy(newbase, base, cpvar - base);
strcpy(newbase + (cpvar - base), val.c_str());
strcpy(newbase + (cpvar - base) + val.length(), cpendvar + 1);
delete []var;
delete []base;
base = newbase;
}
cpvar = strstr(base, "$(");
maxExpands--;
}
SString sret = base;
delete []base;
return sret;
}
void PropSet::Clear() {
for (int root = 0; root < hashRoots; root++) {
Property *p = props[root];
@ -671,7 +541,7 @@ void PropSet::Clear() {
}
}
char *PropSet::ToString() {
char *PropSet::ToString() const {
size_t len=0;
for (int r = 0; r < hashRoots; r++) {
for (Property *p = props[r]; p; p = p->next) {
@ -699,50 +569,6 @@ char *PropSet::ToString() {
return ret;
}
/**
* Initiate enumeration.
*/
bool PropSet::GetFirst(char **key, char **val) {
for (int i = 0; i < hashRoots; i++) {
for (Property *p = props[i]; p; p = p->next) {
if (p) {
*key = p->key;
*val = p->val;
enumnext = p->next; // GetNext will begin here ...
enumhash = i; // ... in this block
return true;
}
}
}
return false;
}
/**
* Continue enumeration.
*/
bool PropSet::GetNext(char ** key, char ** val) {
bool firstloop = true;
// search begins where we left it : in enumhash block
for (int i = enumhash; i < hashRoots; i++) {
if (!firstloop)
enumnext = props[i]; // Begin with first property in block
// else : begin where we left
firstloop = false;
for (Property *p = enumnext; p; p = p->next) {
if (p) {
*key = p->key;
*val = p->val;
enumnext = p->next; // for GetNext
enumhash = i;
return true;
}
}
}
return false;
}
/**
* Creates an array that points into each word in the string and puts \0 terminators
* after each word.
@ -796,37 +622,17 @@ void WordList::Clear() {
if (words) {
delete []list;
delete []words;
delete []wordsNoCase;
}
words = 0;
wordsNoCase = 0;
list = 0;
len = 0;
sorted = false;
sortedNoCase = false;
}
void WordList::Set(const char *s) {
list = StringDup(s);
sorted = false;
sortedNoCase = false;
words = ArrayFromWordList(list, &len, onlyLineEnds);
wordsNoCase = new char * [len + 1];
memcpy(wordsNoCase, words, (len + 1) * sizeof (*words));
}
char *WordList::Allocate(int size) {
list = new char[size + 1];
list[size] = '\0';
return list;
}
void WordList::SetFromAllocated() {
sorted = false;
sortedNoCase = false;
words = ArrayFromWordList(list, &len, onlyLineEnds);
wordsNoCase = new char * [len + 1];
memcpy(wordsNoCase, words, (len + 1) * sizeof (*words));
}
extern "C" int cmpString(const void *a1, const void *a2) {
@ -834,21 +640,11 @@ extern "C" int cmpString(const void *a1, const void *a2) {
return strcmp(*(char**)(a1), *(char**)(a2));
}
extern "C" int cmpStringNoCase(const void *a1, const void *a2) {
// Can't work out the correct incantation to use modern casts here
return CompareCaseInsensitive(*(char**)(a1), *(char**)(a2));
}
static void SortWordList(char **words, unsigned int len) {
qsort(reinterpret_cast<void*>(words), len, sizeof(*words),
cmpString);
}
static void SortWordListNoCase(char **wordsNoCase, unsigned int len) {
qsort(reinterpret_cast<void*>(wordsNoCase), len, sizeof(*wordsNoCase),
cmpStringNoCase);
}
bool WordList::InList(const char *s) {
if (0 == words)
return false;
@ -865,7 +661,7 @@ bool WordList::InList(const char *s) {
unsigned char firstChar = s[0];
int j = starts[firstChar];
if (j >= 0) {
while (words[j][0] == firstChar) {
while ((unsigned char)words[j][0] == firstChar) {
if (s[1] == words[j][1]) {
const char *a = words[j] + 1;
const char *b = s + 1;
@ -957,221 +753,3 @@ bool WordList::InListAbbreviated(const char *s, const char marker) {
}
return false;
}
/**
* Returns an element (complete) of the wordlist array which has
* the same beginning as the passed string.
* The length of the word to compare is passed too.
* Letter case can be ignored or preserved (default).
*/
const char *WordList::GetNearestWord(const char *wordStart, int searchLen, bool ignoreCase /*= false*/, SString wordCharacters /*='/0' */, int wordIndex /*= -1 */) {
int start = 0; // lower bound of the api array block to search
int end = len - 1; // upper bound of the api array block to search
int pivot; // index of api array element just being compared
int cond; // comparison result (in the sense of strcmp() result)
const char *word; // api array element just being compared
if (0 == words)
return NULL;
if (ignoreCase) {
if (!sortedNoCase) {
sortedNoCase = true;
SortWordListNoCase(wordsNoCase, len);
}
while (start <= end) { // binary searching loop
pivot = (start + end) >> 1;
word = wordsNoCase[pivot];
cond = CompareNCaseInsensitive(wordStart, word, searchLen);
if (!cond) {
// find first word
start = pivot;
while (start > 0 && !CompareNCaseInsensitive(wordStart, wordsNoCase[start-1], searchLen)) {
start--;
}
// find last word
end = pivot;
while (end < len-1 && !CompareNCaseInsensitive(wordStart, wordsNoCase[end+1], searchLen)) {
end++;
}
// Finds first word in a series of equal words
for (pivot = start; pivot <= end; pivot++) {
word = wordsNoCase[pivot];
if (!wordCharacters.contains(word[searchLen])) {
if (wordIndex <= 0) // Checks if a specific index was requested
return word; // result must not be freed with free()
wordIndex--;
}
}
return NULL;
}
else if (cond > 0)
start = pivot + 1;
else if (cond < 0)
end = pivot - 1;
}
} else { // preserve the letter case
if (!sorted) {
sorted = true;
SortWordList(words, len);
}
while (start <= end) { // binary searching loop
pivot = (start + end) >> 1;
word = words[pivot];
cond = strncmp(wordStart, word, searchLen);
if (!cond) {
// find first word
start = pivot;
while (start > 0 && !strncmp(wordStart, words[start-1], searchLen)) {
start--;
}
// find last word
end = pivot;
while (end < len-1 && !strncmp(wordStart, words[end+1], searchLen)) {
end++;
}
// Finds first word in a series of equal words
pivot = start;
while (pivot <= end) {
word = words[pivot];
if (!wordCharacters.contains(word[searchLen])) {
if (wordIndex <= 0) // Checks if a specific index was requested
return word; // result must not be freed with free()
wordIndex--;
}
pivot++;
}
return NULL;
}
else if (cond > 0)
start = pivot + 1;
else if (cond < 0)
end = pivot - 1;
}
}
return NULL;
}
/**
* Find the length of a 'word' which is actually an identifier in a string
* which looks like "identifier(..." or "identifier" and where
* there may be extra spaces after the identifier that should not be
* counted in the length.
*/
static unsigned int LengthWord(const char *word, char otherSeparator) {
const char *endWord = 0;
// Find an otherSeparator
if (otherSeparator)
endWord = strchr(word, otherSeparator);
// Find a '('. If that fails go to the end of the string.
if (!endWord)
endWord = strchr(word, '(');
if (!endWord)
endWord = word + strlen(word);
// Last case always succeeds so endWord != 0
// Drop any space characters.
if (endWord > word) {
endWord--; // Back from the '(', otherSeparator, or '\0'
// Move backwards over any spaces
while ((endWord > word) && (IsASpace(*endWord))) {
endWord--;
}
}
return endWord - word;
}
/**
* Returns elements (first words of them) of the wordlist array which have
* the same beginning as the passed string.
* The length of the word to compare is passed too.
* Letter case can be ignored or preserved (default).
* If there are more words meeting the condition they are returned all of
* them in the ascending order separated with spaces.
*
* NOTE: returned buffer has to be freed with delete[].
*/
char *WordList::GetNearestWords(
const char *wordStart,
int searchLen,
bool ignoreCase /*= false*/,
char otherSeparator /*= '\0'*/,
bool exactLen /*=false*/) {
unsigned int wordlen; // length of the word part (before the '(' brace) of the api array element
SString wordsNear;
wordsNear.setsizegrowth(1000);
int start = 0; // lower bound of the api array block to search
int end = len - 1; // upper bound of the api array block to search
int pivot; // index of api array element just being compared
int cond; // comparison result (in the sense of strcmp() result)
if (0 == words)
return NULL;
if (ignoreCase) {
if (!sortedNoCase) {
sortedNoCase = true;
SortWordListNoCase(wordsNoCase, len);
}
while (start <= end) { // Binary searching loop
pivot = (start + end) / 2;
cond = CompareNCaseInsensitive(wordStart, wordsNoCase[pivot], searchLen);
if (!cond) {
// Find first match
while ((pivot > start) &&
(0 == CompareNCaseInsensitive(wordStart,
wordsNoCase[pivot-1], searchLen))) {
--pivot;
}
// Grab each match
while ((pivot <= end) &&
(0 == CompareNCaseInsensitive(wordStart,
wordsNoCase[pivot], searchLen))) {
wordlen = LengthWord(wordsNoCase[pivot], otherSeparator) + 1;
++pivot;
if (exactLen && wordlen != LengthWord(wordStart, otherSeparator) + 1)
continue;
wordsNear.append(wordsNoCase[pivot-1], wordlen, ' ');
}
return wordsNear.detach();
} else if (cond < 0) {
end = pivot - 1;
} else if (cond > 0) {
start = pivot + 1;
}
}
} else { // Preserve the letter case
if (!sorted) {
sorted = true;
SortWordList(words, len);
}
while (start <= end) { // Binary searching loop
pivot = (start + end) / 2;
cond = strncmp(wordStart, words[pivot], searchLen);
if (!cond) {
// Find first match
while ((pivot > start) &&
(0 == strncmp(wordStart,
words[pivot-1], searchLen))) {
--pivot;
}
// Grab each match
while ((pivot <= end) &&
(0 == strncmp(wordStart,
words[pivot], searchLen))) {
wordlen = LengthWord(words[pivot], otherSeparator) + 1;
++pivot;
if (exactLen && wordlen != LengthWord(wordStart, otherSeparator) + 1)
continue;
wordsNear.append(words[pivot-1], wordlen, ' ');
}
return wordsNear.detach();
} else if (cond < 0) {
end = pivot - 1;
} else if (cond > 0) {
start = pivot + 1;
}
}
}
return NULL;
}

View File

@ -151,6 +151,11 @@ bool RunStyles::FillRange(int &position, int value, int &fillLength) {
return true;
}
void RunStyles::SetValueAt(int position, int value) {
int len = 1;
FillRange(position, value, len);
}
void RunStyles::InsertSpace(int position, int insertLength) {
int runStart = RunFromPosition(position);
if (starts->PositionFromPartition(runStart) == position) {

View File

@ -30,6 +30,7 @@ public:
int EndRun(int position);
// Returns true if some values may have changed
bool FillRange(int &position, int value, int &fillLength);
void SetValueAt(int position, int value);
void InsertSpace(int position, int insertLength);
void DeleteAll();
void DeleteRange(int position, int deleteLength);

View File

@ -20,11 +20,10 @@
#include "DocumentAccessor.h"
#include "KeyWords.h"
#endif
#include "ContractionState.h"
#include "SVector.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"
#include "CellBuffer.h"
#include "CallTip.h"
#include "KeyMap.h"
@ -183,7 +182,7 @@ int ScintillaBase::KeyCommand(unsigned int iMessage) {
(iMessage != SCI_CHARLEFT) &&
(iMessage != SCI_CHARLEFTEXTEND) &&
(iMessage != SCI_CHARRIGHT) &&
(iMessage != SCI_CHARLEFTEXTEND) &&
(iMessage != SCI_CHARRIGHTEXTEND) &&
(iMessage != SCI_EDITTOGGLEOVERTYPE) &&
(iMessage != SCI_DELETEBACK) &&
(iMessage != SCI_DELETEBACKNOTLINE)
@ -231,6 +230,9 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
PRectangle rcClient = GetClientRectangle();
Point pt = LocationFromPosition(currentPos - lenEntered);
PRectangle rcPopupBounds = wMain.GetMonitorRect(pt);
if (rcPopupBounds.Height() == 0)
rcPopupBounds = rcClient;
int heightLB = 100;
int widthLB = 100;
@ -241,18 +243,18 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
}
PRectangle rcac;
rcac.left = pt.x - ac.lb->CaretFromEdge();
if (pt.y >= rcClient.bottom - heightLB && // Wont fit below.
pt.y >= (rcClient.bottom + rcClient.top) / 2) { // and there is more room above.
if (pt.y >= rcPopupBounds.bottom - heightLB && // Wont fit below.
pt.y >= (rcPopupBounds.bottom + rcPopupBounds.top) / 2) { // and there is more room above.
rcac.top = pt.y - heightLB;
if (rcac.top < 0) {
heightLB += rcac.top;
rcac.top = 0;
if (rcac.top < rcPopupBounds.top) {
heightLB -= (rcPopupBounds.top - rcac.top);
rcac.top = rcPopupBounds.top;
}
} else {
rcac.top = pt.y + vs.lineHeight;
}
rcac.right = rcac.left + widthLB;
rcac.bottom = Platform::Minimum(rcac.top + heightLB, rcClient.bottom);
rcac.bottom = Platform::Minimum(rcac.top + heightLB, rcPopupBounds.bottom);
ac.lb->SetPositionRelative(rcac, wMain);
ac.lb->SetFont(vs.styles[STYLE_DEFAULT].font);
unsigned int aveCharWidth = vs.styles[STYLE_DEFAULT].aveCharWidth;
@ -270,8 +272,8 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
// Make an allowance for large strings in list
rcList.left = pt.x - ac.lb->CaretFromEdge();
rcList.right = rcList.left + widthLB;
if (((pt.y + vs.lineHeight) >= (rcClient.bottom - heightAlloced)) && // Wont fit below.
((pt.y + vs.lineHeight / 2) >= (rcClient.bottom + rcClient.top) / 2)) { // and there is more room above.
if (((pt.y + vs.lineHeight) >= (rcPopupBounds.bottom - heightAlloced)) && // Wont fit below.
((pt.y + vs.lineHeight / 2) >= (rcPopupBounds.bottom + rcPopupBounds.top) / 2)) { // and there is more room above.
rcList.top = pt.y - heightAlloced;
} else {
rcList.top = pt.y + vs.lineHeight;
@ -641,7 +643,7 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara
case SCI_CALLTIPSETBACK:
ct.colourBG = ColourDesired(wParam);
vs.styles[STYLE_CALLTIP].fore = ct.colourBG;
vs.styles[STYLE_CALLTIP].back = ct.colourBG;
InvalidateStyleRedraw();
break;

View File

@ -26,10 +26,11 @@
#include "Accessor.h"
#include "KeyWords.h"
#endif
#include "ContractionState.h"
#include "SVector.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"
#include "CellBuffer.h"
#include "CallTip.h"
#include "KeyMap.h"
@ -39,7 +40,6 @@
#include "Style.h"
#include "AutoComplete.h"
#include "ViewStyle.h"
#include "RunStyles.h"
#include "Decoration.h"
#include "CharClassify.h"
#include "Document.h"
@ -198,6 +198,7 @@ private:
void ReceivedDrop(GtkSelectionData *selection_data);
static void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *selected);
#ifdef USE_GTK_CLIPBOARD
void StoreOnClipboard(SelectionText *clipText);
static void ClipboardGetSelection(GtkClipboard* clip, GtkSelectionData *selection_data, guint info, void *data);
static void ClipboardClearSelection(GtkClipboard* clip, void *data);
#endif
@ -1154,11 +1155,11 @@ void ScintillaGTK::ScrollText(int linesToMove) {
gdk_gc_unref(gc);
#else
// check if e.g. an existing scroll event has occurred
if (rgnUpdate != NULL) {
Redraw();
return;
}
// check if e.g. an existing scroll event has occurred
if (rgnUpdate != NULL) {
Redraw();
return;
}
gdk_window_scroll(wi->window, 0, -diff);
gdk_window_process_updates(wi->window, FALSE);
#endif
@ -1296,17 +1297,9 @@ void ScintillaGTK::CopyToClipboard(const SelectionText &selectedText) {
atomClipboard,
GDK_CURRENT_TIME);
#else
GtkClipboard *clipBoard;
clipBoard = gtk_widget_get_clipboard(GTK_WIDGET(PWidget(wMain)), atomClipboard);
if (clipBoard == NULL) // Occurs if widget isn't in a toplevel
return;
SelectionText *clipText = new SelectionText();
clipText->Copy(selectedText);
gtk_clipboard_set_with_data(clipBoard, clipboardCopyTargets, nClipboardCopyTargets,
ClipboardGetSelection, ClipboardClearSelection, clipText);
StoreOnClipboard(clipText);
#endif
}
@ -1318,17 +1311,9 @@ void ScintillaGTK::Copy() {
atomClipboard,
GDK_CURRENT_TIME);
#else
GtkClipboard *clipBoard;
clipBoard = gtk_widget_get_clipboard(GTK_WIDGET(PWidget(wMain)), atomClipboard);
if (clipBoard == NULL) // Occurs if widget isn't in a toplevel
return;
SelectionText *clipText = new SelectionText();
CopySelectionRange(clipText);
gtk_clipboard_set_with_data(clipBoard, clipboardCopyTargets, nClipboardCopyTargets,
ClipboardGetSelection, ClipboardClearSelection, clipText);
StoreOnClipboard(clipText);
#endif
#if PLAT_GTK_WIN32
if (selType == selRectangle) {
@ -1644,6 +1629,18 @@ void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, Se
}
#ifdef USE_GTK_CLIPBOARD
void ScintillaGTK::StoreOnClipboard(SelectionText *clipText) {
GtkClipboard *clipBoard =
gtk_widget_get_clipboard(GTK_WIDGET(PWidget(wMain)), atomClipboard);
if (clipBoard == NULL) // Occurs if widget isn't in a toplevel
return;
if (gtk_clipboard_set_with_data(clipBoard, clipboardCopyTargets, nClipboardCopyTargets,
ClipboardGetSelection, ClipboardClearSelection, clipText)) {
gtk_clipboard_set_can_store(clipBoard, clipboardCopyTargets, nClipboardCopyTargets);
}
}
void ScintillaGTK::ClipboardGetSelection(GtkClipboard *, GtkSelectionData *selection_data, guint info, void *data) {
GetSelection(selection_data, info, static_cast<SelectionText*>(data));
}

View File

@ -181,6 +181,14 @@ public:
gapLength -= insertLength;
}
}
/// Ensure at least length elements allocated,
/// appending zero valued elements if needed.
void EnsureLength(int wantedLength) {
if (Length() < wantedLength) {
InsertValue(Length(), wantedLength - Length(), 0);
}
}
/// Insert text into the buffer from an array.
void InsertFromArray(int positionToInsert, const T s[], int positionFrom, int insertLength) {

View File

@ -29,15 +29,15 @@ MarginStyle::MarginStyle() :
// A list of the fontnames - avoids wasting space in each style
FontNames::FontNames() {
size = 8;
names = new char *[size];
size = 8;
names = new char *[size];
max = 0;
}
FontNames::~FontNames() {
Clear();
delete []names;
names = 0;
delete []names;
names = 0;
}
void FontNames::Clear() {
@ -55,17 +55,17 @@ const char *FontNames::Save(const char *name) {
return names[i];
}
}
if (max >= size) {
// Grow array
int sizeNew = size * 2;
char **namesNew = new char *[sizeNew];
for (int j=0;j<max;j++) {
namesNew[j] = names[j];
}
delete []names;
names = namesNew;
size = sizeNew;
}
if (max >= size) {
// Grow array
int sizeNew = size * 2;
char **namesNew = new char *[sizeNew];
for (int j=0;j<max;j++) {
namesNew[j] = names[j];
}
delete []names;
names = namesNew;
size = sizeNew;
}
names[max] = new char[strlen(name) + 1];
strcpy(names[max], name);
max++;
@ -77,8 +77,8 @@ ViewStyle::ViewStyle() {
}
ViewStyle::ViewStyle(const ViewStyle &source) {
Init();
for (unsigned int sty=0;sty<(sizeof(styles)/sizeof(styles[0]));sty++) {
Init(source.stylesSize);
for (unsigned int sty=0;sty<source.stylesSize;sty++) {
styles[sty] = source.styles[sty];
// Can't just copy fontname as its lifetime is relative to its owning ViewStyle
styles[sty].fontName = fontNames.Save(source.styles[sty].fontName);
@ -142,9 +142,14 @@ ViewStyle::ViewStyle(const ViewStyle &source) {
}
ViewStyle::~ViewStyle() {
delete []styles;
styles = NULL;
}
void ViewStyle::Init() {
void ViewStyle::Init(size_t stylesSize_) {
stylesSize = 0;
styles = NULL;
AllocStyles(stylesSize_);
fontNames.Clear();
ResetDefaultStyle();
@ -224,7 +229,7 @@ void ViewStyle::Init() {
}
zoomLevel = 0;
viewWhitespace = wsInvisible;
viewIndentationGuides = false;
viewIndentationGuides = ivNone;
viewEOL = false;
showMarkedLines = true;
extraFontFlag = false;
@ -232,7 +237,7 @@ void ViewStyle::Init() {
void ViewStyle::RefreshColourPalette(Palette &pal, bool want) {
unsigned int i;
for (i=0;i<(sizeof(styles)/sizeof(styles[0]));i++) {
for (i=0;i<stylesSize;i++) {
pal.WantFind(styles[i].fore, want);
pal.WantFind(styles[i].back, want);
}
@ -267,7 +272,7 @@ void ViewStyle::Refresh(Surface &surface) {
maxAscent = styles[STYLE_DEFAULT].ascent;
maxDescent = styles[STYLE_DEFAULT].descent;
someStylesProtected = false;
for (unsigned int i=0;i<(sizeof(styles)/sizeof(styles[0]));i++) {
for (unsigned int i=0; i<stylesSize; i++) {
if (i != STYLE_DEFAULT) {
styles[i].Realise(surface, zoomLevel, &styles[STYLE_DEFAULT], extraFontFlag);
if (maxAscent < styles[i].ascent)
@ -295,17 +300,45 @@ void ViewStyle::Refresh(Surface &surface) {
}
}
void ViewStyle::AllocStyles(size_t sizeNew) {
Style *stylesNew = new Style[sizeNew];
size_t i=0;
for (; i<stylesSize; i++) {
stylesNew[i] = styles[i];
stylesNew[i].fontName = styles[i].fontName;
}
if (stylesSize > STYLE_DEFAULT) {
for (; i<sizeNew; i++) {
if (i != STYLE_DEFAULT) {
stylesNew[i].ClearTo(styles[STYLE_DEFAULT]);
}
}
}
delete []styles;
styles = stylesNew;
stylesSize = sizeNew;
}
void ViewStyle::EnsureStyle(size_t index) {
if (index >= stylesSize) {
size_t sizeNew = stylesSize * 2;
while (sizeNew < index)
sizeNew *= 2;
AllocStyles(sizeNew);
}
}
void ViewStyle::ResetDefaultStyle() {
styles[STYLE_DEFAULT].Clear(ColourDesired(0,0,0),
ColourDesired(0xff,0xff,0xff),
Platform::DefaultFontSize(), fontNames.Save(Platform::DefaultFont()),
Platform::DefaultFontSize(), fontNames.Save(Platform::DefaultFont()),
SC_CHARSET_DEFAULT,
false, 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<(sizeof(styles)/sizeof(styles[0]));i++) {
for (unsigned int i=0; i<stylesSize; i++) {
if (i != STYLE_DEFAULT) {
styles[i].ClearTo(styles[STYLE_DEFAULT]);
}
@ -322,5 +355,5 @@ void ViewStyle::SetStyleFontName(int styleIndex, const char *name) {
}
bool ViewStyle::ProtectionActive() const {
return someStylesProtected;
return someStylesProtected;
}

View File

@ -38,6 +38,8 @@ public:
const char *Save(const char *name);
};
enum IndentView {ivNone, ivReal, ivLookForward, ivLookBoth};
enum WhiteSpaceVisibility {wsInvisible=0, wsVisibleAlways=1, wsVisibleAfterIndent=2};
/**
@ -45,7 +47,8 @@ enum WhiteSpaceVisibility {wsInvisible=0, wsVisibleAlways=1, wsVisibleAfterInden
class ViewStyle {
public:
FontNames fontNames;
Style styles[STYLE_MAX + 1];
size_t stylesSize;
Style *styles;
LineMarker markers[MARKER_MAX + 1];
Indicator indicators[INDIC_MAX + 1];
int lineHeight;
@ -86,7 +89,7 @@ public:
int fixedColumnWidth;
int zoomLevel;
WhiteSpaceVisibility viewWhitespace;
bool viewIndentationGuides;
IndentView viewIndentationGuides;
bool viewEOL;
bool showMarkedLines;
ColourPair caretcolour;
@ -103,9 +106,11 @@ public:
ViewStyle();
ViewStyle(const ViewStyle &source);
~ViewStyle();
void Init();
void Init(size_t stylesSize_=64);
void RefreshColourPalette(Palette &pal, bool want);
void Refresh(Surface &surface);
void AllocStyles(size_t sizeNew);
void EnsureStyle(size_t index);
void ResetDefaultStyle();
void ClearStyles();
void SetStyleFontName(int styleIndex, const char *name);

View File

@ -122,6 +122,9 @@ public:
}
int Width() { return right - left; }
int Height() { return bottom - top; }
bool Empty() {
return (Height() <= 0) || (Width() <= 0);
}
};
/**
@ -368,19 +371,19 @@ typedef void (*CallBackAction)(void*);
class Window {
protected:
WindowID id;
#ifdef PLAT_MACOSX
#if PLAT_MACOSX
void *windowRef;
void *control;
#endif
public:
Window() : id(0), cursorLast(cursorInvalid) {
#ifdef PLAT_MACOSX
#if PLAT_MACOSX
windowRef = 0;
control = 0;
#endif
}
Window(const Window &source) : id(source.id), cursorLast(cursorInvalid) {
#ifdef PLAT_MACOSX
#if PLAT_MACOSX
windowRef = 0;
control = 0;
#endif
@ -405,7 +408,8 @@ public:
enum Cursor { cursorInvalid, cursorText, cursorArrow, cursorUp, cursorWait, cursorHoriz, cursorVert, cursorReverseArrow, cursorHand };
void SetCursor(Cursor curs);
void SetTitle(const char *s);
#ifdef PLAT_MACOSX
PRectangle GetMonitorRect(Point pt);
#if PLAT_MACOSX
void SetWindow(void *ref) { windowRef = ref; };
void SetControl(void *_control) { control = _control; };
#endif
@ -500,9 +504,6 @@ public:
static int DefaultFontSize();
static unsigned int DoubleClickTime();
static bool MouseButtonBounce();
#ifdef __APPLE__
static bool WaitMouseMoved(Point pt);
#endif
static void DebugDisplay(const char *s);
static bool IsKeyDown(int key);
static long SendScintilla(

View File

@ -33,7 +33,6 @@ protected:
Property *props[hashRoots];
Property *enumnext;
int enumhash;
static bool caseSensitiveFilenames;
static unsigned int HashString(const char *s, size_t len) {
unsigned int ret = 0;
while (len--) {
@ -43,7 +42,6 @@ protected:
}
return ret;
}
static bool IncludesVar(const char *value, const char *key);
public:
PropSet *superPS;
@ -53,19 +51,12 @@ public:
void Set(const char *keyVal);
void Unset(const char *key, int lenKey=-1);
void SetMultiple(const char *s);
SString Get(const char *key);
SString GetExpanded(const char *key);
SString Expand(const char *withVars, int maxExpands=100);
int GetInt(const char *key, int defaultValue=0);
SString GetWild(const char *keybase, const char *filename);
SString GetNewExpand(const char *keybase, const char *filename="");
SString Get(const char *key) const;
SString GetExpanded(const char *key) const;
SString Expand(const char *withVars, int maxExpands=100) const;
int GetInt(const char *key, int defaultValue=0) const;
void Clear();
char *ToString(); // Caller must delete[] the return value
bool GetFirst(char **key, char **val);
bool GetNext(char **key, char **val);
static void SetCaseSensitiveFilenames(bool caseSensitiveFilenames_) {
caseSensitiveFilenames = caseSensitiveFilenames_;
}
char *ToString() const; // Caller must delete[] the return value
private:
// copy-value semantics not implemented
@ -79,29 +70,21 @@ class WordList {
public:
// Each word contains at least one character - a empty word acts as sentinel at the end.
char **words;
char **wordsNoCase;
char *list;
int len;
bool onlyLineEnds; ///< Delimited by any white space or only line ends
bool sorted;
bool sortedNoCase;
int starts[256];
WordList(bool onlyLineEnds_ = false) :
words(0), wordsNoCase(0), list(0), len(0), onlyLineEnds(onlyLineEnds_),
sorted(false), sortedNoCase(false) {}
words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_),
sorted(false)
{}
~WordList() { Clear(); }
operator bool() { return len ? true : false; }
char *operator[](int ind) { return words[ind]; }
void Clear();
void Set(const char *s);
char *Allocate(int size);
void SetFromAllocated();
bool InList(const char *s);
bool InListAbbreviated(const char *s, const char marker);
const char *GetNearestWord(const char *wordStart, int searchLen,
bool ignoreCase = false, SString wordCharacters="", int wordIndex = -1);
char *GetNearestWords(const char *wordStart, int searchLen,
bool ignoreCase=false, char otherSeparator='\0', bool exactLen=false);
};
inline bool IsAlphabetic(unsigned int ch) {

View File

@ -96,7 +96,10 @@
#define SCLEX_GAP 81
#define SCLEX_PLM 82
#define SCLEX_PROGRESS 83
#define SCLEX_OMS 84
#define SCLEX_ABAQUS 84
#define SCLEX_ASYMPTOTE 85
#define SCLEX_R 86
#define SCLEX_OMS 87
#define SCLEX_AUTOMATIC 1000
#define SCE_P_DEFAULT 0
#define SCE_P_COMMENTLINE 1
@ -317,6 +320,9 @@
#define SCE_PL_STRING_QR 29
#define SCE_PL_STRING_QW 30
#define SCE_PL_POD_VERB 31
#define SCE_PL_SUB_PROTOTYPE 40
#define SCE_PL_FORMAT_IDENT 41
#define SCE_PL_FORMAT 42
#define SCE_RB_DEFAULT 0
#define SCE_RB_ERROR 1
#define SCE_RB_COMMENTLINE 2
@ -422,6 +428,7 @@
#define SCE_ERR_ABSF 18
#define SCE_ERR_TIDY 19
#define SCE_ERR_JAVA_STACK 20
#define SCE_ERR_VALUE 21
#define SCE_BAT_DEFAULT 0
#define SCE_BAT_COMMENT 1
#define SCE_BAT_WORD 2
@ -734,6 +741,7 @@
#define SCE_YAML_DOCUMENT 6
#define SCE_YAML_TEXT 7
#define SCE_YAML_ERROR 8
#define SCE_YAML_OPERATOR 9
#define SCE_TEX_DEFAULT 0
#define SCE_TEX_SPECIAL 1
#define SCE_TEX_GROUP 2
@ -1159,6 +1167,43 @@
#define SCE_4GL_COMMENT4_ 29
#define SCE_4GL_COMMENT5_ 30
#define SCE_4GL_COMMENT6_ 31
#define SCE_ABAQUS_DEFAULT 0
#define SCE_ABAQUS_COMMENT 1
#define SCE_ABAQUS_COMMENTBLOCK 2
#define SCE_ABAQUS_NUMBER 3
#define SCE_ABAQUS_STRING 4
#define SCE_ABAQUS_OPERATOR 5
#define SCE_ABAQUS_WORD 6
#define SCE_ABAQUS_PROCESSOR 7
#define SCE_ABAQUS_COMMAND 8
#define SCE_ABAQUS_SLASHCOMMAND 9
#define SCE_ABAQUS_STARCOMMAND 10
#define SCE_ABAQUS_ARGUMENT 11
#define SCE_ABAQUS_FUNCTION 12
#define SCE_ASY_DEFAULT 0
#define SCE_ASY_COMMENT 1
#define SCE_ASY_COMMENTLINE 2
#define SCE_ASY_NUMBER 3
#define SCE_ASY_WORD 4
#define SCE_ASY_STRING 5
#define SCE_ASY_CHARACTER 6
#define SCE_ASY_OPERATOR 7
#define SCE_ASY_IDENTIFIER 8
#define SCE_ASY_STRINGEOL 9
#define SCE_ASY_COMMENTLINEDOC 10
#define SCE_ASY_WORD2 11
#define SCE_R_DEFAULT 0
#define SCE_R_COMMENT 1
#define SCE_R_KWORD 2
#define SCE_R_BASEKWORD 3
#define SCE_R_OTHERKWORD 4
#define SCE_R_NUMBER 5
#define SCE_R_STRING 6
#define SCE_R_STRING2 7
#define SCE_R_OPERATOR 8
#define SCE_R_IDENTIFIER 9
#define SCE_R_INFIX 10
#define SCE_R_INFIXEOL 11
#define SCLEX_ASP 29
#define SCLEX_PHP 30
//--Autogenerated -- end of section automatically generated from Scintilla.iface

View File

@ -159,7 +159,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define STYLE_INDENTGUIDE 37
#define STYLE_CALLTIP 38
#define STYLE_LASTPREDEFINED 39
#define STYLE_MAX 127
#define STYLE_MAX 255
#define SC_CHARSET_ANSI 0
#define SC_CHARSET_DEFAULT 1
#define SC_CHARSET_BALTIC 186
@ -298,6 +298,10 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_GETCOLUMN 2129
#define SCI_SETHSCROLLBAR 2130
#define SCI_GETHSCROLLBAR 2131
#define SC_IV_NONE 0
#define SC_IV_REAL 1
#define SC_IV_LOOKFORWARD 2
#define SC_IV_LOOKBOTH 3
#define SCI_SETINDENTATIONGUIDES 2132
#define SCI_GETINDENTATIONGUIDES 2133
#define SCI_SETHIGHLIGHTGUIDE 2134
@ -448,6 +452,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_GETLAYOUTCACHE 2273
#define SCI_SETSCROLLWIDTH 2274
#define SCI_GETSCROLLWIDTH 2275
#define SCI_SETSCROLLWIDTHTRACKING 2516
#define SCI_GETSCROLLWIDTHTRACKING 2517
#define SCI_TEXTWIDTH 2276
#define SCI_SETENDATLASTLINE 2277
#define SCI_GETENDATLASTLINE 2278
@ -689,7 +695,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SC_MULTILINEUNDOREDO 0x1000
#define SC_STARTACTION 0x2000
#define SC_MOD_CHANGEINDICATOR 0x4000
#define SC_MODEVENTMASKALL 0x6FFF
#define SC_MOD_CHANGELINESTATE 0x8000
#define SC_MODEVENTMASKALL 0xFFFF
#define SCEN_CHANGE 768
#define SCEN_SETFOCUS 512
#define SCEN_KILLFOCUS 256