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. Make path entry of filebrowser plugin editable.
Add "Open with" and "Find in Files" popup menu items to filebrowser Add "Open with" and "Find in Files" popup menu items to filebrowser
plugin and add configuration dialog. 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> 2007-12-01 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>

View File

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

View File

@ -67,11 +67,11 @@ public:
void InsertLine(int line, int position); void InsertLine(int line, int position);
void SetLineStart(int line, int position); void SetLineStart(int line, int position);
void RemoveLine(int line); void RemoveLine(int line);
int Lines() { int Lines() const {
return starts.Partitions(); return starts.Partitions();
} }
int LineFromPosition(int pos); int LineFromPosition(int pos);
int LineStart(int line) { int LineStart(int line) const {
return starts.PositionFromPartition(line); return starts.PositionFromPartition(line);
} }
@ -160,7 +160,7 @@ private:
LineVector lv; LineVector lv;
SVector lineStates; SplitVector<int> lineStates;
public: public:
@ -168,15 +168,17 @@ public:
~CellBuffer(); ~CellBuffer();
/// Retrieving positions outside the range of the buffer works and returns 0 /// 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); void GetCharRange(char *buffer, int position, int lengthRetrieve);
char StyleAt(int position); char StyleAt(int position);
int Length(); int Length() const;
void Allocate(int newSize); void Allocate(int newSize);
int Lines(); int Lines() const;
int LineStart(int line); int LineStart(int line) const;
int LineFromPosition(int pos) { return lv.LineFromPosition(pos); } 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); 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. /// 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 // Scintilla source code edit control
/** @file ContractionState.cxx /** @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. // The License.txt file describes the conditions under which this software may be distributed.
#include <string.h>
#include "Platform.h" #include "Platform.h"
#include "SplitVector.h"
#include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h" #include "ContractionState.h"
#ifdef SCI_NAMESPACE #ifdef SCI_NAMESPACE
using namespace Scintilla; using namespace Scintilla;
#endif #endif
OneLine::OneLine() { ContractionState::ContractionState() : visible(0), expanded(0), heights(0), displayLines(0), linesInDocument(1) {
displayLine = 0; //InsertLine(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() { ContractionState::~ContractionState() {
Clear(); Clear();
} }
void ContractionState::MakeValid() const { void ContractionState::EnsureData() {
if (!valid) { if (OneToOne()) {
// Could be cleverer by keeping the index of the last still valid entry visible = new RunStyles();
// rather than invalidating all. expanded = new RunStyles();
linesInDisplay = 0; heights = new RunStyles();
for (int lineInDoc=0; lineInDoc<linesInDoc; lineInDoc++) { displayLines = new Partitioning(4);
lines[lineInDoc].displayLine = linesInDisplay; InsertLines(0, linesInDocument);
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::Clear() { void ContractionState::Clear() {
delete []lines; delete visible;
lines = 0; visible = 0;
size = 0; delete expanded;
linesInDoc = 1; expanded = 0;
linesInDisplay = 1; delete heights;
delete []docLines; heights = 0;
docLines = 0; delete displayLines;
sizeDocLines = 0; displayLines = 0;
linesInDocument = 1;
} }
int ContractionState::LinesInDoc() const { int ContractionState::LinesInDoc() const {
return linesInDoc; if (OneToOne()) {
return linesInDocument;
} else {
return displayLines->Partitions() - 1;
}
} }
int ContractionState::LinesDisplayed() const { int ContractionState::LinesDisplayed() const {
if (size != 0) { if (OneToOne()) {
MakeValid(); return linesInDocument;
} else {
return displayLines->PositionFromPartition(LinesInDoc());
} }
return linesInDisplay;
} }
int ContractionState::DisplayFromDoc(int lineDoc) const { int ContractionState::DisplayFromDoc(int lineDoc) const {
if (size == 0) { if (OneToOne()) {
return lineDoc; 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 { int ContractionState::DocFromDisplay(int lineDisplay) const {
if (lineDisplay <= 0) if (OneToOne()) {
return 0;
if (lineDisplay >= linesInDisplay)
return linesInDoc;
if (size == 0)
return lineDisplay; return lineDisplay;
MakeValid();
if (docLines) { // Valid allocation
return docLines[lineDisplay];
} else { } else {
if (lineDisplay <= 0) {
return 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) { void ContractionState::InsertLine(int lineDoc) {
OneLine *linesNew = new OneLine[sizeNew]; if (OneToOne()) {
if (linesNew) { linesInDocument++;
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;
} else { } else {
Platform::DebugPrintf("No memory available\n"); visible->InsertSpace(lineDoc, 1);
// TODO: Blow up 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) { void ContractionState::InsertLines(int lineDoc, int lineCount) {
if (size == 0) { for (int l = 0; l < lineCount; l++) {
linesInDoc += lineCount; InsertLine(lineDoc + l);
linesInDisplay += lineCount;
return;
} }
//Platform::DebugPrintf("InsertLine[%d] = %d\n", lineDoc); Check();
if ((linesInDoc + lineCount + 2) >= size) { }
Grow(linesInDoc + lineCount + growSize);
void ContractionState::DeleteLine(int lineDoc) {
if (OneToOne()) {
linesInDocument--;
} else {
if (GetVisible(lineDoc)) {
displayLines->InsertText(lineDoc, -heights->ValueAt(lineDoc));
} }
linesInDoc += lineCount; displayLines->RemovePartition(lineDoc);
for (int i = linesInDoc; i >= lineDoc + lineCount; i--) { visible->DeleteRange(lineDoc, 1);
lines[i].visible = lines[i - lineCount].visible; expanded->DeleteRange(lineDoc, 1);
lines[i].height = lines[i - lineCount].height; heights->DeleteRange(lineDoc, 1);
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) { void ContractionState::DeleteLines(int lineDoc, int lineCount) {
if (size == 0) { for (int l = 0; l < lineCount; l++) {
linesInDoc -= lineCount; DeleteLine(lineDoc);
linesInDisplay -= lineCount;
return;
} }
int deltaDisplayed = 0; Check();
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;
} }
bool ContractionState::GetVisible(int lineDoc) const { bool ContractionState::GetVisible(int lineDoc) const {
if (size == 0) if (OneToOne()) {
return true; return true;
if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
return lines[lineDoc].visible;
} else { } else {
return false; if (lineDoc >= visible->Length())
return true;
return visible->ValueAt(lineDoc) == 1;
} }
} }
bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible) { bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible_) {
if (lineDocStart == 0) if (OneToOne() && visible_) {
lineDocStart++;
if (lineDocStart > lineDocEnd)
return false; return false;
if (size == 0) { } else {
Grow(linesInDoc + growSize); EnsureData();
}
// TODO: modify docLine members to mirror displayLine
int delta = 0; int delta = 0;
// Change lineDocs Check();
if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < linesInDoc)) { if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < LinesInDoc())) {
for (int line=lineDocStart; line <= lineDocEnd; line++) { for (int line = lineDocStart; line <= lineDocEnd; line++) {
if (lines[line].visible != visible) { if (GetVisible(line) != visible_) {
delta += visible ? lines[line].height : -lines[line].height; int difference = visible_ ? heights->ValueAt(line) : -heights->ValueAt(line);
lines[line].visible = visible; visible->SetValueAt(line, visible_ ? 1 : 0);
valid = false; displayLines->InsertText(line, difference);
delta += difference;
} }
} }
} else {
return false;
} }
linesInDisplay += delta; Check();
return delta != 0; return delta != 0;
}
} }
bool ContractionState::GetExpanded(int lineDoc) const { bool ContractionState::GetExpanded(int lineDoc) const {
if (size == 0) if (OneToOne()) {
return true; return true;
if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
return lines[lineDoc].expanded;
} else { } else {
return false; Check();
return expanded->ValueAt(lineDoc) == 1;
} }
} }
bool ContractionState::SetExpanded(int lineDoc, bool expanded) { bool ContractionState::SetExpanded(int lineDoc, bool expanded_) {
if (size == 0) { if (OneToOne() && expanded_) {
if (expanded) {
// If in completely expanded state then setting
// one line to expanded has no effect.
return false; return false;
} } else {
Grow(linesInDoc + growSize); EnsureData();
} if (expanded_ != (expanded->ValueAt(lineDoc) == 1)) {
if ((lineDoc >= 0) && (lineDoc < linesInDoc)) { expanded->SetValueAt(lineDoc, expanded_ ? 1 : 0);
if (lines[lineDoc].expanded != expanded) { Check();
lines[lineDoc].expanded = expanded;
return true; return true;
} } else {
} Check();
return false; return false;
}
}
} }
int ContractionState::GetHeight(int lineDoc) const { int ContractionState::GetHeight(int lineDoc) const {
if (size == 0) if (OneToOne()) {
return 1; return 1;
if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
return lines[lineDoc].height;
} else { } else {
return 1; return heights->ValueAt(lineDoc);
} }
} }
// Set the number of display lines needed for this line. // Set the number of display lines needed for this line.
// Return true if this is a change. // Return true if this is a change.
bool ContractionState::SetHeight(int lineDoc, int height) { 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.
return false; return false;
} else {
EnsureData();
if (GetHeight(lineDoc) != height) {
if (GetVisible(lineDoc)) {
displayLines->InsertText(lineDoc, height - GetHeight(lineDoc));
} }
Grow(linesInDoc + growSize); heights->SetValueAt(lineDoc, height);
} Check();
if (lines[lineDoc].height != height) {
lines[lineDoc].height = height;
valid = false;
return true; return true;
} else { } else {
Check();
return false; return false;
} }
}
} }
void ContractionState::ShowAll() { void ContractionState::ShowAll() {
delete []lines; int lines = LinesInDoc();
lines = 0; Clear();
size = 0; linesInDocument = lines;
}
delete []docLines;
docLines = 0; // Debugging checks
sizeDocLines = 0;
void ContractionState::Check() const {
linesInDisplay = linesInDoc; #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 // Scintilla source code edit control
/** @file ContractionState.h /** @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. // The License.txt file describes the conditions under which this software may be distributed.
#ifndef CONTRACTIONSTATE_H #ifndef CONTRACTIONSTATE_H
@ -12,33 +12,23 @@
namespace Scintilla { namespace Scintilla {
#endif #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 { class ContractionState {
void Grow(int sizeNew); // These contain 1 element for every document line.
enum { growSize = 4000 }; RunStyles *visible;
int linesInDoc; RunStyles *expanded;
mutable int linesInDisplay; RunStyles *heights;
mutable OneLine *lines; Partitioning *displayLines;
int size; int linesInDocument;
mutable int *docLines;
mutable int sizeDocLines; void EnsureData();
mutable bool valid;
void MakeValid() const; bool OneToOne() const {
// True when each document line is exactly one display line so need for
// complex data structures.
return visible == 0;
}
public: public:
ContractionState(); ContractionState();
@ -51,7 +41,9 @@ public:
int DisplayFromDoc(int lineDoc) const; int DisplayFromDoc(int lineDoc) const;
int DocFromDisplay(int lineDisplay) const; int DocFromDisplay(int lineDisplay) const;
void InsertLine(int lineDoc);
void InsertLines(int lineDoc, int lineCount); void InsertLines(int lineDoc, int lineCount);
void DeleteLine(int lineDoc);
void DeleteLines(int lineDoc, int lineCount); void DeleteLines(int lineDoc, int lineCount);
bool GetVisible(int lineDoc) const; bool GetVisible(int lineDoc) const;
@ -64,6 +56,7 @@ public:
bool SetHeight(int lineDoc, int height); bool SetHeight(int lineDoc, int height);
void ShowAll(); void ShowAll();
void Check() const;
}; };
#ifdef SCI_NAMESPACE #ifdef SCI_NAMESPACE

View File

@ -13,7 +13,6 @@
#include "Platform.h" #include "Platform.h"
#include "Scintilla.h" #include "Scintilla.h"
#include "SVector.h"
#include "SplitVector.h" #include "SplitVector.h"
#include "Partitioning.h" #include "Partitioning.h"
#include "RunStyles.h" #include "RunStyles.h"
@ -113,7 +112,6 @@ void Document::SetSavePoint() {
int Document::AddMark(int line, int markerNum) { int Document::AddMark(int line, int markerNum) {
int prev = cb.AddMark(line, markerNum); int prev = cb.AddMark(line, markerNum);
DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line); DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
mh.line = line;
NotifyModified(mh); NotifyModified(mh);
return prev; return prev;
} }
@ -124,14 +122,12 @@ void Document::AddMarkSet(int line, int valueSet) {
if (m & 1) if (m & 1)
cb.AddMark(line, i); cb.AddMark(line, i);
DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line); DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
mh.line = line;
NotifyModified(mh); NotifyModified(mh);
} }
void Document::DeleteMark(int line, int markerNum) { void Document::DeleteMark(int line, int markerNum) {
cb.DeleteMark(line, markerNum); cb.DeleteMark(line, markerNum);
DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line); DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
mh.line = line;
NotifyModified(mh); NotifyModified(mh);
} }
@ -149,11 +145,11 @@ void Document::DeleteAllMarks(int markerNum) {
NotifyModified(mh); NotifyModified(mh);
} }
int Document::LineStart(int line) { int Document::LineStart(int line) const {
return cb.LineStart(line); return cb.LineStart(line);
} }
int Document::LineEnd(int line) { int Document::LineEnd(int line) const {
if (line == LinesTotal() - 1) { if (line == LinesTotal() - 1) {
return LineStart(line + 1); return LineStart(line + 1);
} else { } else {
@ -191,8 +187,7 @@ int Document::SetLevel(int line, int level) {
int prev = cb.SetLevel(line, level); int prev = cb.SetLevel(line, level);
if (prev != level) { if (prev != level) {
DocModification mh(SC_MOD_CHANGEFOLD | SC_MOD_CHANGEMARKER, DocModification mh(SC_MOD_CHANGEFOLD | SC_MOD_CHANGEMARKER,
LineStart(line), 0, 0, 0); LineStart(line), 0, 0, 0, line);
mh.line = line;
mh.foldLevelNow = level; mh.foldLevelNow = level;
mh.foldLevelPrev = prev; mh.foldLevelPrev = prev;
NotifyModified(mh); 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. // Normalise a position so that it is not halfway through a two byte character.
// This can occur in two situations - // This can occur in two situations -
// When lines are terminated with \r\n pairs which should be treated as one character. // 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 (dbcsCodePage) {
if (SC_CP_UTF8 == dbcsCodePage) { if (SC_CP_UTF8 == dbcsCodePage) {
unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos)); unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos));
while ((pos > 0) && (pos < Length()) && (ch >= 0x80) && (ch < (0x80 + 0x40))) { int startUTF = pos;
// ch is a trail byte int endUTF = pos;
if (IsTrailByte(ch) && InGoodUTF8(pos, startUTF, endUTF)) {
// ch is a trail byte within a UTF-8 character
if (moveDir > 0) if (moveDir > 0)
pos++; pos = endUTF;
else else
pos--; pos = startUTF;
ch = static_cast<unsigned char>(cb.CharAt(pos));
} }
} else { } else {
// Anchor DBCS calculations at start of line because start of line can // 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) if (line < 0)
return 0; return 0;
int pos = LineStart(line); int pos = LineStart(line);
@ -793,7 +838,7 @@ void Document::ConvertLineEnds(int eolModeSet) {
EndUndoAction(); EndUndoAction();
} }
bool Document::IsWhiteLine(int line) { bool Document::IsWhiteLine(int line) const {
int currentChar = LineStart(line); int currentChar = LineStart(line);
int endLine = LineEnd(line); int endLine = LineEnd(line);
while (currentChar < endLine) { while (currentChar < endLine) {
@ -1238,7 +1283,7 @@ const char *Document::SubstituteByPosition(const char *text, int *length) {
return substituted; return substituted;
} }
int Document::LinesTotal() { int Document::LinesTotal() const {
return cb.Lines(); return cb.Lines();
} }
@ -1271,11 +1316,7 @@ void Document::SetCharClasses(const unsigned char *chars, CharClassify::cc newCh
void Document::SetStylingBits(int bits) { void Document::SetStylingBits(int bits) {
stylingBits = bits; stylingBits = bits;
stylingBitsMask = 0; stylingBitsMask = (1 << stylingBits) - 1;
for (int bit = 0; bit < stylingBits; bit++) {
stylingBitsMask <<= 1;
stylingBitsMask |= 1;
}
} }
void Document::StartStyling(int position, char mask) { void Document::StartStyling(int position, char mask) {
@ -1339,11 +1380,17 @@ void Document::EnsureStyledTo(int pos) {
} }
} }
void Document::IncrementStyleClock() { int Document::SetLineState(int line, int state) {
styleClock++; int statePrevious = cb.SetLineState(line, state);
if (styleClock > 0x100000) { if (state != statePrevious) {
styleClock = 0; 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) { void Document::DecorationFillRange(int position, int value, int fillLength) {
@ -1411,6 +1458,11 @@ void Document::NotifySavePoint(bool atSavePoint) {
} }
void Document::NotifyModified(DocModification mh) { 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++) { for (int i = 0; i < lenWatchers; i++) {
watchers[i].watcher->NotifyModified(this, mh, watchers[i].userData); watchers[i].watcher->NotifyModified(this, mh, watchers[i].userData);
} }

View File

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

View File

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

View File

@ -17,13 +17,12 @@
#endif #endif
#include "Scintilla.h" #include "Scintilla.h"
#include "ContractionState.h"
#include "SVector.h"
#include "SplitVector.h" #include "SplitVector.h"
#include "Partitioning.h" #include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"
#include "CellBuffer.h" #include "CellBuffer.h"
#include "KeyMap.h" #include "KeyMap.h"
#include "RunStyles.h"
#include "Indicator.h" #include "Indicator.h"
#include "XPM.h" #include "XPM.h"
#include "LineMarker.h" #include "LineMarker.h"
@ -44,9 +43,9 @@ using namespace Scintilla;
may reasonably be deferred (not done now OR [possibly] at all) may reasonably be deferred (not done now OR [possibly] at all)
*/ */
static bool CanDeferToLastStep(const DocModification& mh) { static bool CanDeferToLastStep(const DocModification& mh) {
if (mh.modificationType & (SC_MOD_BEFOREINSERT|SC_MOD_BEFOREDELETE)) if (mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE))
return true; // CAN skip return true; // CAN skip
if (!(mh.modificationType & (SC_PERFORMED_UNDO|SC_PERFORMED_REDO))) if (!(mh.modificationType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO)))
return false; // MUST do return false; // MUST do
if (mh.modificationType & SC_MULTISTEPUNDOREDO) if (mh.modificationType & SC_MULTISTEPUNDOREDO)
return true; // CAN skip return true; // CAN skip
@ -55,7 +54,7 @@ static bool CanDeferToLastStep(const DocModification& mh) {
static bool CanEliminate(const DocModification& mh) { static bool CanEliminate(const DocModification& mh) {
return return
(mh.modificationType & (SC_MOD_BEFOREINSERT|SC_MOD_BEFOREDELETE)) != 0; (mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) != 0;
} }
/* /*
@ -64,20 +63,20 @@ static bool CanEliminate(const DocModification& mh) {
*/ */
static bool IsLastStep(const DocModification& mh) { static bool IsLastStep(const DocModification& mh) {
return return
(mh.modificationType & (SC_PERFORMED_UNDO|SC_PERFORMED_REDO)) != 0 (mh.modificationType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO)) != 0
&& (mh.modificationType & SC_MULTISTEPUNDOREDO) != 0 && (mh.modificationType & SC_MULTISTEPUNDOREDO) != 0
&& (mh.modificationType & SC_LASTSTEPINUNDOREDO) != 0 && (mh.modificationType & SC_LASTSTEPINUNDOREDO) != 0
&& (mh.modificationType & SC_MULTILINEUNDOREDO) != 0; && (mh.modificationType & SC_MULTILINEUNDOREDO) != 0;
} }
Caret::Caret() : Caret::Caret() :
active(false), on(false), period(500) {} active(false), on(false), period(500) {}
Timer::Timer() : Timer::Timer() :
ticking(false), ticksToWait(0), tickerID(0) {} ticking(false), ticksToWait(0), tickerID(0) {}
Idler::Idler() : Idler::Idler() :
state(false), idlerID(0) {} state(false), idlerID(0) {}
static inline bool IsControlCharacter(int ch) { static inline bool IsControlCharacter(int ch) {
// iscntrl returns true for lots of chars > 127 which are displayable // iscntrl returns true for lots of chars > 127 which are displayable
@ -138,6 +137,8 @@ Editor::Editor() {
xCaretMargin = 50; xCaretMargin = 50;
horizontalScrollBarVisible = true; horizontalScrollBarVisible = true;
scrollWidth = 2000; scrollWidth = 2000;
trackLineWidth = false;
lineWidthMaxSeen = 0;
verticalScrollBarVisible = true; verticalScrollBarVisible = true;
endAtLastLine = true; endAtLastLine = true;
caretSticky = false; caretSticky = false;
@ -1205,7 +1206,7 @@ void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) {
xOffset = xOffsetNew; xOffset = xOffsetNew;
if (xOffsetNew > 0) { if (xOffsetNew > 0) {
PRectangle rcText = GetTextRectangle(); PRectangle rcText = GetTextRectangle();
if (horizontalScrollBarVisible == true && if (horizontalScrollBarVisible &&
rcText.Width() + xOffset > scrollWidth) { rcText.Width() + xOffset > scrollWidth) {
scrollWidth = xOffset + rcText.Width(); scrollWidth = xOffset + rcText.Width();
SetScrollBars(); SetScrollBars();
@ -1262,6 +1263,16 @@ void Editor::NeedWrapping(int docLineStart, int docLineEnd) {
} }
} }
bool Editor::WrapOneLine(Surface *surface, int lineToWrap) {
AutoLineLayout ll(llc, RetrieveLineLayout(lineToWrap));
int linesWrapped = 1;
if (ll) {
LayoutLine(lineToWrap, surface, vs, ll, wrapWidth);
linesWrapped = ll->lines;
}
return cs.SetHeight(lineToWrap, linesWrapped);
}
// Check if wrapping needed and perform any needed wrapping. // Check if wrapping needed and perform any needed wrapping.
// fullwrap: if true, all lines which need wrapping will be done, // fullwrap: if true, all lines which need wrapping will be done,
// in this single call. // in this single call.
@ -1338,13 +1349,7 @@ bool Editor::WrapLines(bool fullWrap, int priorityWrapLineStart) {
// Platform::DebugPrintf("Wraplines: full = %d, priorityStart = %d (wrapping: %d to %d)\n", fullWrap, priorityWrapLineStart, lineToWrap, lastLineToWrap); // Platform::DebugPrintf("Wraplines: full = %d, priorityStart = %d (wrapping: %d to %d)\n", fullWrap, priorityWrapLineStart, lineToWrap, lastLineToWrap);
// Platform::DebugPrintf("Pending wraps: %d to %d\n", wrapStart, wrapEnd); // Platform::DebugPrintf("Pending wraps: %d to %d\n", wrapStart, wrapEnd);
while (lineToWrap < lastLineToWrap) { while (lineToWrap < lastLineToWrap) {
AutoLineLayout ll(llc, RetrieveLineLayout(lineToWrap)); if (WrapOneLine(surface, lineToWrap)) {
int linesWrapped = 1;
if (ll) {
LayoutLine(lineToWrap, surface, vs, ll, wrapWidth);
linesWrapped = ll->lines;
}
if (cs.SetHeight(lineToWrap, linesWrapped)) {
wrapOccurred = true; wrapOccurred = true;
} }
lineToWrap++; lineToWrap++;
@ -1679,6 +1684,61 @@ LineLayout *Editor::RetrieveLineLayout(int lineNumber) {
LinesOnScreen() + 1, pdoc->LinesTotal()); LinesOnScreen() + 1, pdoc->LinesTotal());
} }
static bool GoodTrailByte(int v) {
return (v >= 0x80) && (v < 0xc0);
}
bool BadUTF(const char *s, int len, int &trailBytes) {
if (trailBytes) {
trailBytes--;
return false;
}
const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
if (*us < 0x80) {
// Single bytes easy
return false;
} else if (*us > 0xF4) {
// Characters longer than 4 bytes not possible in current UTF-8
return true;
} else if (*us >= 0xF0) {
// 4 bytes
if (len < 4)
return true;
if (GoodTrailByte(us[1]) && GoodTrailByte(us[2]) && GoodTrailByte(us[3])) {
trailBytes = 3;
return false;
} else {
return true;
}
} else if (*us >= 0xE0) {
// 3 bytes
if (len < 3)
return true;
if (GoodTrailByte(us[1]) && GoodTrailByte(us[2])) {
trailBytes = 2;
return false;
} else {
return true;
}
} else if (*us >= 0xC2) {
// 2 bytes
if (len < 2)
return true;
if (GoodTrailByte(us[1])) {
trailBytes = 1;
return false;
} else {
return true;
}
} else if (*us >= 0xC0) {
// Overlong encoding
return true;
} else {
// Trail byte
return true;
}
}
/** /**
* Fill in the LineLayout data for the given line. * Fill in the LineLayout data for the given line.
* Copy the given @a line and its styles from the document into local arrays. * Copy the given @a line and its styles from the document into local arrays.
@ -1790,11 +1850,15 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
int ctrlCharWidth[32] = {0}; int ctrlCharWidth[32] = {0};
bool isControlNext = IsControlCharacter(ll->chars[0]); bool isControlNext = IsControlCharacter(ll->chars[0]);
int trailBytes = 0;
bool isBadUTFNext = IsUnicodeMode() && BadUTF(ll->chars, numCharsInLine, trailBytes);
for (int charInLine = 0; charInLine < numCharsInLine; charInLine++) { for (int charInLine = 0; charInLine < numCharsInLine; charInLine++) {
bool isControl = isControlNext; bool isControl = isControlNext;
isControlNext = IsControlCharacter(ll->chars[charInLine + 1]); isControlNext = IsControlCharacter(ll->chars[charInLine + 1]);
bool isBadUTF = isBadUTFNext;
isBadUTFNext = IsUnicodeMode() && BadUTF(ll->chars + charInLine + 1, numCharsInLine - charInLine - 1, trailBytes);
if ((ll->styles[charInLine] != ll->styles[charInLine + 1]) || if ((ll->styles[charInLine] != ll->styles[charInLine + 1]) ||
isControl || isControlNext) { isControl || isControlNext || isBadUTF || isBadUTFNext) {
ll->positions[startseg] = 0; ll->positions[startseg] = 0;
if (vstyle.styles[ll->styles[charInLine]].visible) { if (vstyle.styles[ll->styles[charInLine]].visible) {
if (isControl) { if (isControl) {
@ -1815,6 +1879,11 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
ll->positions + startseg + 1); ll->positions + startseg + 1);
} }
lastSegItalics = false; lastSegItalics = false;
} else if (isBadUTF) {
char hexits[3];
sprintf(hexits, "%2X", ll->chars[charInLine] & 0xff);
ll->positions[charInLine + 1] =
surface->WidthText(ctrlCharsFont, hexits, istrlen(hexits)) + 3;
} else { // Regular character } else { // Regular character
int lenSeg = charInLine - startseg + 1; int lenSeg = charInLine - startseg + 1;
if ((lenSeg == 1) && (' ' == ll->chars[startseg])) { if ((lenSeg == 1) && (' ' == ll->chars[startseg])) {
@ -2106,9 +2175,9 @@ void Editor::DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int x
} }
} }
for (Decoration *deco=pdoc->decorations.root; deco; deco = deco->next) { for (Decoration *deco = pdoc->decorations.root; deco; deco = deco->next) {
if (under == vsDraw.indicators[deco->indicator].under) { if (under == vsDraw.indicators[deco->indicator].under) {
int startPos = posLineStart + subLineStart; int startPos = posLineStart + lineStart;
if (!deco->rs.ValueAt(startPos)) { if (!deco->rs.ValueAt(startPos)) {
startPos = deco->rs.EndRun(startPos); startPos = deco->rs.EndRun(startPos);
} }
@ -2128,6 +2197,30 @@ void Editor::DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int x
} }
} }
void DrawTextBlob(Surface *surface, ViewStyle &vsDraw, PRectangle rcSegment,
const char *s, ColourAllocated textBack, ColourAllocated textFore, bool twoPhaseDraw) {
if (!twoPhaseDraw) {
surface->FillRectangle(rcSegment, textBack);
}
Font &ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;
int normalCharHeight = surface->Ascent(ctrlCharsFont) -
surface->InternalLeading(ctrlCharsFont);
PRectangle rcCChar = rcSegment;
rcCChar.left = rcCChar.left + 1;
rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight;
rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1;
PRectangle rcCentral = rcCChar;
rcCentral.top++;
rcCentral.bottom--;
surface->FillRectangle(rcCentral, textFore);
PRectangle rcChar = rcCChar;
rcChar.left++;
rcChar.right--;
surface->DrawTextClipped(rcChar, ctrlCharsFont,
rcSegment.top + vsDraw.maxAscent, s, istrlen(s),
textBack, textFore);
}
void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart, void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,
PRectangle rcLine, LineLayout *ll, int subLine) { PRectangle rcLine, LineLayout *ll, int subLine) {
@ -2246,7 +2339,7 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
// Does not take margin into account but not significant // Does not take margin into account but not significant
int xStartVisible = subLineStart - xStart; int xStartVisible = subLineStart - xStart;
BreakFinder bfBack(ll, lineStart, lineEnd, posLineStart, xStartVisible); BreakFinder bfBack(ll, lineStart, lineEnd, posLineStart, IsUnicodeMode(), xStartVisible);
int next = bfBack.First(); int next = bfBack.First();
// Background drawing loop // Background drawing loop
@ -2284,7 +2377,7 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
// Normal text display // Normal text display
surface->FillRectangle(rcSegment, textBack); surface->FillRectangle(rcSegment, textBack);
if (vsDraw.viewWhitespace != wsInvisible || if (vsDraw.viewWhitespace != wsInvisible ||
(inIndentation && vsDraw.viewIndentationGuides)) { (inIndentation && vsDraw.viewIndentationGuides == ivReal)) {
for (int cpos = 0; cpos <= i - startseg; cpos++) { for (int cpos = 0; cpos <= i - startseg; cpos++) {
if (ll->chars[cpos + startseg] == ' ') { if (ll->chars[cpos + startseg] == ' ') {
if (drawWhitespaceBackground && if (drawWhitespaceBackground &&
@ -2321,7 +2414,7 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
inIndentation = subLine == 0; // Do not handle indentation except on first subline. inIndentation = subLine == 0; // Do not handle indentation except on first subline.
// Foreground drawing loop // Foreground drawing loop
BreakFinder bfFore(ll, lineStart, lineEnd, posLineStart, xStartVisible); BreakFinder bfFore(ll, lineStart, lineEnd, posLineStart, IsUnicodeMode(), xStartVisible);
next = bfFore.First(); next = bfFore.First();
while (next < lineEnd) { while (next < lineEnd) {
@ -2359,12 +2452,13 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
textBack = vsDraw.whitespaceBackground.allocated; textBack = vsDraw.whitespaceBackground.allocated;
surface->FillRectangle(rcSegment, textBack); surface->FillRectangle(rcSegment, textBack);
} }
if ((vsDraw.viewWhitespace != wsInvisible) || ((inIndentation && vsDraw.viewIndentationGuides))) { if ((vsDraw.viewWhitespace != wsInvisible) ||
(inIndentation && vsDraw.viewIndentationGuides != ivNone)) {
if (vsDraw.whitespaceForegroundSet) if (vsDraw.whitespaceForegroundSet)
textFore = vsDraw.whitespaceForeground.allocated; textFore = vsDraw.whitespaceForeground.allocated;
surface->PenColour(textFore); surface->PenColour(textFore);
} }
if (inIndentation && vsDraw.viewIndentationGuides) { if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
for (int xIG = ll->positions[i] / indentWidth * indentWidth; xIG < ll->positions[i + 1]; xIG += indentWidth) { for (int xIG = ll->positions[i] / indentWidth * indentWidth; xIG < ll->positions[i + 1]; xIG += indentWidth) {
if (xIG >= ll->positions[i] && xIG > 0) { if (xIG >= ll->positions[i] && xIG > 0) {
DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIG + xStart, rcSegment, DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIG + xStart, rcSegment,
@ -2385,31 +2479,17 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
if (controlCharSymbol < 32) { if (controlCharSymbol < 32) {
// Draw the character // Draw the character
const char *ctrlChar = ControlCharacterString(ll->chars[i]); const char *ctrlChar = ControlCharacterString(ll->chars[i]);
if (!twoPhaseDraw) { DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, twoPhaseDraw);
surface->FillRectangle(rcSegment, textBack);
}
int normalCharHeight = surface->Ascent(ctrlCharsFont) -
surface->InternalLeading(ctrlCharsFont);
PRectangle rcCChar = rcSegment;
rcCChar.left = rcCChar.left + 1;
rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight;
rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1;
PRectangle rcCentral = rcCChar;
rcCentral.top++;
rcCentral.bottom--;
surface->FillRectangle(rcCentral, textFore);
PRectangle rcChar = rcCChar;
rcChar.left++;
rcChar.right--;
surface->DrawTextClipped(rcChar, ctrlCharsFont,
rcSegment.top + vsDraw.maxAscent, ctrlChar, istrlen(ctrlChar),
textBack, textFore);
} else { } else {
char cc[2] = { static_cast<char>(controlCharSymbol), '\0' }; char cc[2] = { static_cast<char>(controlCharSymbol), '\0' };
surface->DrawTextNoClip(rcSegment, ctrlCharsFont, surface->DrawTextNoClip(rcSegment, ctrlCharsFont,
rcSegment.top + vsDraw.maxAscent, rcSegment.top + vsDraw.maxAscent,
cc, 1, textBack, textFore); cc, 1, textBack, textFore);
} }
} else if ((i == startseg) && (static_cast<unsigned char>(ll->chars[i]) >= 0x80) && IsUnicodeMode()) {
char hexits[3];
sprintf(hexits, "%2X", ll->chars[i] & 0xff);
DrawTextBlob(surface, vsDraw, rcSegment, hexits, textBack, textFore, twoPhaseDraw);
} else { } else {
// Normal text display // Normal text display
if (vsDraw.styles[styleMain].visible) { if (vsDraw.styles[styleMain].visible) {
@ -2424,7 +2504,7 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
} }
} }
if (vsDraw.viewWhitespace != wsInvisible || if (vsDraw.viewWhitespace != wsInvisible ||
(inIndentation && vsDraw.viewIndentationGuides)) { (inIndentation && vsDraw.viewIndentationGuides != ivNone)) {
for (int cpos = 0; cpos <= i - startseg; cpos++) { for (int cpos = 0; cpos <= i - startseg; cpos++) {
if (ll->chars[cpos + startseg] == ' ') { if (ll->chars[cpos + startseg] == ' ') {
if (vsDraw.viewWhitespace != wsInvisible) { if (vsDraw.viewWhitespace != wsInvisible) {
@ -2444,7 +2524,7 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
surface->FillRectangle(rcDot, textFore); surface->FillRectangle(rcDot, textFore);
} }
} }
if (inIndentation && vsDraw.viewIndentationGuides) { if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
int startSpace = ll->positions[cpos + startseg]; int startSpace = ll->positions[cpos + startseg];
if (startSpace > 0 && (startSpace % indentWidth == 0)) { if (startSpace > 0 && (startSpace % indentWidth == 0)) {
DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, startSpace + xStart, rcSegment, DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, startSpace + xStart, rcSegment,
@ -2475,6 +2555,49 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
break; break;
} }
} }
if ((vsDraw.viewIndentationGuides == ivLookForward || vsDraw.viewIndentationGuides == ivLookBoth)
&& (subLine == 0)) {
int indentSpace = pdoc->GetLineIndentation(line);
// Find the most recent line with some text
int lineLastWithText = line;
while (lineLastWithText > 0 && pdoc->IsWhiteLine(lineLastWithText)) {
lineLastWithText--;
}
if (lineLastWithText < line) {
// This line is empty, so use indentation of last line with text
int indentLastWithText = pdoc->GetLineIndentation(lineLastWithText);
int isFoldHeader = pdoc->GetLevel(lineLastWithText) & SC_FOLDLEVELHEADERFLAG;
if (isFoldHeader) {
// Level is one more level than parent
indentLastWithText += pdoc->IndentSize();
}
if (vsDraw.viewIndentationGuides == ivLookForward) {
// In viLookForward mode, previous line only used if it is a fold header
if (isFoldHeader) {
indentSpace = Platform::Maximum(indentSpace, indentLastWithText);
}
} else { // viLookBoth
indentSpace = Platform::Maximum(indentSpace, indentLastWithText);
}
}
int lineNextWithText = line;
while (lineNextWithText < pdoc->LinesTotal() && pdoc->IsWhiteLine(lineNextWithText)) {
lineNextWithText++;
}
if (lineNextWithText > line) {
// This line is empty, so use indentation of last line with text
indentSpace = Platform::Maximum(indentSpace,
pdoc->GetLineIndentation(lineNextWithText));
}
for (int indentPos = pdoc->IndentSize(); indentPos < indentSpace; indentPos += pdoc->IndentSize()) {
int xIndent = indentPos * vsDraw.spaceWidth;
DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
(ll->xHighlightGuide == xIndent));
}
}
DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineEnd, false); DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineEnd, false);
@ -2526,7 +2649,7 @@ void Editor::DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll,
int lineStart = ll->LineStart(subLine); int lineStart = ll->LineStart(subLine);
int posBefore = posCaret; int posBefore = posCaret;
int posAfter = MovePositionOutsideChar(posCaret+1, 1); int posAfter = MovePositionOutsideChar(posCaret + 1, 1);
int numCharsToDraw = posAfter - posCaret; int numCharsToDraw = posAfter - posCaret;
// Work out where the starting and ending offsets are. We need to // Work out where the starting and ending offsets are. We need to
@ -2541,7 +2664,7 @@ void Editor::DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll,
} }
// Char shares horizontal space, update the numChars to draw // Char shares horizontal space, update the numChars to draw
// Update posBefore to point to the prev char // Update posBefore to point to the prev char
posBefore = MovePositionOutsideChar(posBefore-1, -1); posBefore = MovePositionOutsideChar(posBefore - 1, -1);
numCharsToDraw = posAfter - posBefore; numCharsToDraw = posAfter - posBefore;
offsetFirstChar = offset - (posCaret - posBefore); offsetFirstChar = offset - (posCaret - posBefore);
} }
@ -2554,7 +2677,7 @@ void Editor::DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll,
// the next character ends, and 2nd next begins. We'll need // the next character ends, and 2nd next begins. We'll need
// to compare these two // to compare these two
posBefore = posAfter; posBefore = posAfter;
posAfter = MovePositionOutsideChar(posAfter+1, 1); posAfter = MovePositionOutsideChar(posAfter + 1, 1);
offsetLastChar = offset + (posAfter - posCaret); offsetLastChar = offset + (posAfter - posCaret);
if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - (posAfter - posBefore)]) > 0) { if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - (posAfter - posBefore)]) > 0) {
// The char does not share horizontal space // The char does not share horizontal space
@ -2869,8 +2992,7 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
// Draw the Caret // Draw the Caret
if (lineDoc == lineCaret) { if (lineDoc == lineCaret) {
int offset = Platform::Minimum(posCaret - rangeLine.start, ll->maxLineLength); int offset = Platform::Minimum(posCaret - rangeLine.start, ll->maxLineLength);
if ((offset >= ll->LineStart(subLine)) && if (ll->InLine(offset, subLine)) {
((offset < ll->LineStart(subLine + 1)) || offset == ll->numCharsInLine)) {
int xposCaret = ll->positions[offset] - ll->positions[ll->LineStart(subLine)] + xStart; int xposCaret = ll->positions[offset] - ll->positions[ll->LineStart(subLine)] + xStart;
if (actualWrapVisualStartIndent != 0) { if (actualWrapVisualStartIndent != 0) {
@ -2899,7 +3021,7 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
if (widthOverstrikeCaret < 3) // Make sure its visible if (widthOverstrikeCaret < 3) // Make sure its visible
widthOverstrikeCaret = 3; widthOverstrikeCaret = 3;
if (offset > 0) if (offset > ll->LineStart(subLine))
caretWidthOffset = 1; // Move back so overlaps both character cells. caretWidthOffset = 1; // Move back so overlaps both character cells.
if (posDrag >= 0) { if (posDrag >= 0) {
/* Dragging text, use a line caret */ /* Dragging text, use a line caret */
@ -2948,6 +3070,9 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
yposScreen += vs.lineHeight; yposScreen += vs.lineHeight;
visibleLine++; visibleLine++;
lineWidthMaxSeen = Platform::Maximum(
lineWidthMaxSeen, ll->positions[ll->numCharsInLine]);
//gdk_flush(); //gdk_flush();
} }
ll.Set(0); ll.Set(0);
@ -3025,7 +3150,7 @@ long Editor::FormatRange(bool draw, RangeToFormat *pfr) {
vsPrint.showMarkedLines = false; vsPrint.showMarkedLines = false;
vsPrint.fixedColumnWidth = 0; vsPrint.fixedColumnWidth = 0;
vsPrint.zoomLevel = printMagnification; vsPrint.zoomLevel = printMagnification;
vsPrint.viewIndentationGuides = false; vsPrint.viewIndentationGuides = ivNone;
// Don't show the selection when printing // Don't show the selection when printing
vsPrint.selbackset = false; vsPrint.selbackset = false;
vsPrint.selforeset = false; vsPrint.selforeset = false;
@ -3035,7 +3160,7 @@ long Editor::FormatRange(bool draw, RangeToFormat *pfr) {
vsPrint.showCaretLineBackground = false; vsPrint.showCaretLineBackground = false;
// Set colours for printing according to users settings // Set colours for printing according to users settings
for (int sty = 0;sty <= STYLE_MAX;sty++) { for (size_t sty = 0;sty < vsPrint.stylesSize;sty++) {
if (printColourMode == SC_PRINT_INVERTLIGHT) { if (printColourMode == SC_PRINT_INVERTLIGHT) {
vsPrint.styles[sty].fore.desired = InvertedLight(vsPrint.styles[sty].fore.desired); vsPrint.styles[sty].fore.desired = InvertedLight(vsPrint.styles[sty].fore.desired);
vsPrint.styles[sty].back.desired = InvertedLight(vsPrint.styles[sty].back.desired); vsPrint.styles[sty].back.desired = InvertedLight(vsPrint.styles[sty].back.desired);
@ -3238,6 +3363,7 @@ void Editor::AddChar(char ch) {
AddCharUTF(s, 1); AddCharUTF(s, 1);
} }
// AddCharUTF inserts an array of bytes which may or may not be in UTF-8.
void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) { void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
bool wasSelection = currentPos != anchor; bool wasSelection = currentPos != anchor;
ClearSelection(); ClearSelection();
@ -3257,6 +3383,14 @@ void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
if (charReplaceAction) { if (charReplaceAction) {
pdoc->EndUndoAction(); pdoc->EndUndoAction();
} }
// If in wrap mode rewrap current line so EnsureCaretVisible has accurate information
if (wrapState != eWrapNone) {
AutoSurface surface(this);
if (surface) {
WrapOneLine(surface, pdoc->LineFromPosition(currentPos));
}
SetScrollBars();
}
EnsureCaretVisible(); EnsureCaretVisible();
// Avoid blinking during rapid typing: // Avoid blinking during rapid typing:
ShowCaretAtCurrentPosition(); ShowCaretAtCurrentPosition();
@ -3353,6 +3487,7 @@ void Editor::ClearDocumentStyle() {
} }
void Editor::Cut() { void Editor::Cut() {
pdoc->CheckReadOnly();
if (!pdoc->IsReadOnly() && !SelectionContainsProtected()) { if (!pdoc->IsReadOnly() && !SelectionContainsProtected()) {
Copy(); Copy();
ClearSelection(); ClearSelection();
@ -3632,7 +3767,7 @@ void Editor::NotifySavePoint(Document*, void *, bool atSavePoint) {
} }
void Editor::CheckModificationForWrap(DocModification mh) { void Editor::CheckModificationForWrap(DocModification mh) {
if (mh.modificationType & (SC_MOD_INSERTTEXT|SC_MOD_DELETETEXT)) { if (mh.modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) {
llc.Invalidate(LineLayout::llCheckTextAndStyle); llc.Invalidate(LineLayout::llCheckTextAndStyle);
if (wrapState != eWrapNone) { if (wrapState != eWrapNone) {
int lineDoc = pdoc->LineFromPosition(mh.position); int lineDoc = pdoc->LineFromPosition(mh.position);
@ -3670,7 +3805,16 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {
if (paintState == painting) { if (paintState == painting) {
CheckForChangeOutsidePaint(Range(mh.position, mh.position + mh.length)); CheckForChangeOutsidePaint(Range(mh.position, mh.position + mh.length));
} }
if (mh.modificationType & (SC_MOD_CHANGESTYLE|SC_MOD_CHANGEINDICATOR)) { if (mh.modificationType & SC_MOD_CHANGELINESTATE) {
if (paintState == painting) {
CheckForChangeOutsidePaint(
Range(pdoc->LineStart(mh.line), pdoc->LineStart(mh.line + 1)));
} else {
// Could check that change is before last visible line.
Redraw();
}
}
if (mh.modificationType & (SC_MOD_CHANGESTYLE | SC_MOD_CHANGEINDICATOR)) {
if (mh.modificationType & SC_MOD_CHANGESTYLE) { if (mh.modificationType & SC_MOD_CHANGESTYLE) {
pdoc->IncrementStyleClock(); pdoc->IncrementStyleClock();
} }
@ -3692,13 +3836,11 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {
anchor = MovePositionForInsertion(anchor, mh.position, mh.length); anchor = MovePositionForInsertion(anchor, mh.position, mh.length);
braces[0] = MovePositionForInsertion(braces[0], mh.position, mh.length); braces[0] = MovePositionForInsertion(braces[0], mh.position, mh.length);
braces[1] = MovePositionForInsertion(braces[1], mh.position, mh.length); braces[1] = MovePositionForInsertion(braces[1], mh.position, mh.length);
pdoc->decorations.InsertSpace(mh.position, mh.length);
} else if (mh.modificationType & SC_MOD_DELETETEXT) { } else if (mh.modificationType & SC_MOD_DELETETEXT) {
currentPos = MovePositionForDeletion(currentPos, mh.position, mh.length); currentPos = MovePositionForDeletion(currentPos, mh.position, mh.length);
anchor = MovePositionForDeletion(anchor, mh.position, mh.length); anchor = MovePositionForDeletion(anchor, mh.position, mh.length);
braces[0] = MovePositionForDeletion(braces[0], mh.position, mh.length); braces[0] = MovePositionForDeletion(braces[0], mh.position, mh.length);
braces[1] = MovePositionForDeletion(braces[1], mh.position, mh.length); braces[1] = MovePositionForDeletion(braces[1], mh.position, mh.length);
pdoc->decorations.DeleteRange(mh.position, mh.length);
} }
if (cs.LinesDisplayed() < cs.LinesInDoc()) { if (cs.LinesDisplayed() < cs.LinesInDoc()) {
// Some lines are hidden so may need shown. // Some lines are hidden so may need shown.
@ -3768,7 +3910,7 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {
// If client wants to see this modification // If client wants to see this modification
if (mh.modificationType & modEventMask) { if (mh.modificationType & modEventMask) {
if ((mh.modificationType & (SC_MOD_CHANGESTYLE|SC_MOD_CHANGEINDICATOR)) == 0) { if ((mh.modificationType & (SC_MOD_CHANGESTYLE | SC_MOD_CHANGEINDICATOR)) == 0) {
// Real modification made to text of document. // Real modification made to text of document.
NotifyChange(); // Send EN_CHANGE NotifyChange(); // Send EN_CHANGE
} }
@ -4043,6 +4185,7 @@ void Editor::NewLine() {
} }
} }
SetLastXChosen(); SetLastXChosen();
SetScrollBars();
EnsureCaretVisible(); EnsureCaretVisible();
// Avoid blinking during rapid typing: // Avoid blinking during rapid typing:
ShowCaretAtCurrentPosition(); ShowCaretAtCurrentPosition();
@ -5107,14 +5250,6 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b
else else
inDragDrop = ddNone; inDragDrop = ddNone;
} }
#ifdef __APPLE__
// we need to additionaly check if the mouse moved before we
// decide that we can in fact start a drag session. Currently
// only OSX will return anything but true.
if (inDragDrop == ddInitial && !Platform::WaitMouseMoved(pt)) {
inDragDrop = ddNone;
}
#endif
SetMouseCapture(true); SetMouseCapture(true);
if (inDragDrop != ddInitial) { if (inDragDrop != ddInitial) {
SetDragPosition(invalidPosition); SetDragPosition(invalidPosition);
@ -5366,6 +5501,10 @@ void Editor::Tick() {
} }
} }
} }
if (horizontalScrollBarVisible && trackLineWidth && (lineWidthMaxSeen > scrollWidth)) {
scrollWidth = lineWidthMaxSeen;
SetScrollBars();
}
if ((dwellDelay < SC_TIME_FOREVER) && if ((dwellDelay < SC_TIME_FOREVER) &&
(ticksToDwell > 0) && (ticksToDwell > 0) &&
(!HaveMouseCapture())) { (!HaveMouseCapture())) {
@ -5413,7 +5552,11 @@ void Editor::SetFocusState(bool focusState) {
} }
bool Editor::PaintContains(PRectangle rc) { bool Editor::PaintContains(PRectangle rc) {
if (rc.Empty()) {
return true;
} else {
return rcPaint.Contains(rc); return rcPaint.Contains(rc);
}
} }
bool Editor::PaintContainsMargin() { bool Editor::PaintContainsMargin() {
@ -5604,9 +5747,11 @@ int Editor::ReplaceTarget(bool replacePatterns, const char *text, int length) {
length = istrlen(text); length = istrlen(text);
if (replacePatterns) { if (replacePatterns) {
text = pdoc->SubstituteByPosition(text, &length); text = pdoc->SubstituteByPosition(text, &length);
if (!text) if (!text) {
pdoc->EndUndoAction();
return 0; return 0;
} }
}
if (targetStart != targetEnd) if (targetStart != targetEnd)
pdoc->DeleteChars(targetStart, targetEnd - targetStart); pdoc->DeleteChars(targetStart, targetEnd - targetStart);
targetEnd = targetStart; targetEnd = targetStart;
@ -5645,11 +5790,11 @@ void Editor::AddStyledText(char *buffer, int appendLength) {
char *text = new char[textLength]; char *text = new char[textLength];
if (text) { if (text) {
size_t i; size_t i;
for (i=0;i<textLength;i++) { for (i = 0;i < textLength;i++) {
text[i] = buffer[i*2]; text[i] = buffer[i*2];
} }
pdoc->InsertString(CurrentPosition(), text, textLength); pdoc->InsertString(CurrentPosition(), text, textLength);
for (i=0;i<textLength;i++) { for (i = 0;i < textLength;i++) {
text[i] = buffer[i*2+1]; text[i] = buffer[i*2+1];
} }
pdoc->StartStyling(CurrentPosition(), static_cast<char>(0xff)); pdoc->StartStyling(CurrentPosition(), static_cast<char>(0xff));
@ -5667,6 +5812,89 @@ static char *CharPtrFromSPtr(sptr_t lParam) {
return reinterpret_cast<char *>(lParam); return reinterpret_cast<char *>(lParam);
} }
void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
vs.EnsureStyle(wParam);
switch (iMessage) {
case SCI_STYLESETFORE:
vs.styles[wParam].fore.desired = ColourDesired(lParam);
break;
case SCI_STYLESETBACK:
vs.styles[wParam].back.desired = ColourDesired(lParam);
break;
case SCI_STYLESETBOLD:
vs.styles[wParam].bold = lParam != 0;
break;
case SCI_STYLESETITALIC:
vs.styles[wParam].italic = lParam != 0;
break;
case SCI_STYLESETEOLFILLED:
vs.styles[wParam].eolFilled = lParam != 0;
break;
case SCI_STYLESETSIZE:
vs.styles[wParam].size = lParam;
break;
case SCI_STYLESETFONT:
if (lParam != 0) {
vs.SetStyleFontName(wParam, CharPtrFromSPtr(lParam));
}
break;
case SCI_STYLESETUNDERLINE:
vs.styles[wParam].underline = lParam != 0;
break;
case SCI_STYLESETCASE:
vs.styles[wParam].caseForce = static_cast<Style::ecaseForced>(lParam);
break;
case SCI_STYLESETCHARACTERSET:
vs.styles[wParam].characterSet = lParam;
break;
case SCI_STYLESETVISIBLE:
vs.styles[wParam].visible = lParam != 0;
break;
case SCI_STYLESETCHANGEABLE:
vs.styles[wParam].changeable = lParam != 0;
break;
case SCI_STYLESETHOTSPOT:
vs.styles[wParam].hotspot = lParam != 0;
break;
}
InvalidateStyleRedraw();
}
sptr_t Editor::StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
vs.EnsureStyle(wParam);
switch (iMessage) {
case SCI_STYLEGETFORE:
return vs.styles[wParam].fore.desired.AsLong();
case SCI_STYLEGETBACK:
return vs.styles[wParam].back.desired.AsLong();
case SCI_STYLEGETBOLD:
return vs.styles[wParam].bold ? 1 : 0;
case SCI_STYLEGETITALIC:
return vs.styles[wParam].italic ? 1 : 0;
case SCI_STYLEGETEOLFILLED:
return vs.styles[wParam].eolFilled ? 1 : 0;
case SCI_STYLEGETSIZE:
return vs.styles[wParam].size;
case SCI_STYLEGETFONT:
if (lParam != 0)
strcpy(CharPtrFromSPtr(lParam), vs.styles[wParam].fontName);
return strlen(vs.styles[wParam].fontName);
case SCI_STYLEGETUNDERLINE:
return vs.styles[wParam].underline ? 1 : 0;
case SCI_STYLEGETCASE:
return static_cast<int>(vs.styles[wParam].caseForce);
case SCI_STYLEGETCHARACTERSET:
return vs.styles[wParam].characterSet;
case SCI_STYLEGETVISIBLE:
return vs.styles[wParam].visible ? 1 : 0;
case SCI_STYLEGETCHANGEABLE:
return vs.styles[wParam].changeable ? 1 : 0;
case SCI_STYLEGETHOTSPOT:
return vs.styles[wParam].hotspot ? 1 : 0;
}
return 0;
}
sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
//Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam); //Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam);
@ -5896,10 +6124,10 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
return searchFlags; return searchFlags;
case SCI_POSITIONBEFORE: case SCI_POSITIONBEFORE:
return pdoc->MovePositionOutsideChar(wParam-1, -1, true); return pdoc->MovePositionOutsideChar(wParam - 1, -1, true);
case SCI_POSITIONAFTER: case SCI_POSITIONAFTER:
return pdoc->MovePositionOutsideChar(wParam+1, 1, true); return pdoc->MovePositionOutsideChar(wParam + 1, 1, true);
case SCI_LINESCROLL: case SCI_LINESCROLL:
ScrollTo(topLine + lParam); ScrollTo(topLine + lParam);
@ -6394,6 +6622,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
case SCI_SETSCROLLWIDTH: case SCI_SETSCROLLWIDTH:
PLATFORM_ASSERT(wParam > 0); PLATFORM_ASSERT(wParam > 0);
if ((wParam > 0) && (wParam != static_cast<unsigned int >(scrollWidth))) { if ((wParam > 0) && (wParam != static_cast<unsigned int >(scrollWidth))) {
lineWidthMaxSeen = 0;
scrollWidth = wParam; scrollWidth = wParam;
SetScrollBars(); SetScrollBars();
} }
@ -6402,6 +6631,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
case SCI_GETSCROLLWIDTH: case SCI_GETSCROLLWIDTH:
return scrollWidth; return scrollWidth;
case SCI_SETSCROLLWIDTHTRACKING:
trackLineWidth = wParam != 0;
break;
case SCI_GETSCROLLWIDTHTRACKING:
return trackLineWidth;
case SCI_LINESJOIN: case SCI_LINESJOIN:
LinesJoin(); LinesJoin();
break; break;
@ -6411,7 +6647,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
break; break;
case SCI_TEXTWIDTH: case SCI_TEXTWIDTH:
PLATFORM_ASSERT(wParam <= STYLE_MAX); PLATFORM_ASSERT(wParam < vs.stylesSize);
PLATFORM_ASSERT(lParam); PLATFORM_ASSERT(lParam);
return TextWidth(wParam, CharPtrFromSPtr(lParam)); return TextWidth(wParam, CharPtrFromSPtr(lParam));
@ -6472,7 +6708,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
return verticalScrollBarVisible; return verticalScrollBarVisible;
case SCI_SETINDENTATIONGUIDES: case SCI_SETINDENTATIONGUIDES:
vs.viewIndentationGuides = wParam != 0; vs.viewIndentationGuides = IndentView(wParam);
Redraw(); Redraw();
break; break;
@ -6640,157 +6876,42 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
break; break;
case SCI_STYLESETFORE: case SCI_STYLESETFORE:
if (wParam <= STYLE_MAX) {
vs.styles[wParam].fore.desired = ColourDesired(lParam);
InvalidateStyleRedraw();
}
break;
case SCI_STYLESETBACK: case SCI_STYLESETBACK:
if (wParam <= STYLE_MAX) {
vs.styles[wParam].back.desired = ColourDesired(lParam);
InvalidateStyleRedraw();
}
break;
case SCI_STYLESETBOLD: case SCI_STYLESETBOLD:
if (wParam <= STYLE_MAX) {
vs.styles[wParam].bold = lParam != 0;
InvalidateStyleRedraw();
}
break;
case SCI_STYLESETITALIC: case SCI_STYLESETITALIC:
if (wParam <= STYLE_MAX) {
vs.styles[wParam].italic = lParam != 0;
InvalidateStyleRedraw();
}
break;
case SCI_STYLESETEOLFILLED: case SCI_STYLESETEOLFILLED:
if (wParam <= STYLE_MAX) {
vs.styles[wParam].eolFilled = lParam != 0;
InvalidateStyleRedraw();
}
break;
case SCI_STYLESETSIZE: case SCI_STYLESETSIZE:
if (wParam <= STYLE_MAX) {
vs.styles[wParam].size = lParam;
InvalidateStyleRedraw();
}
break;
case SCI_STYLESETFONT: case SCI_STYLESETFONT:
if (lParam == 0)
return 0;
if (wParam <= STYLE_MAX) {
vs.SetStyleFontName(wParam, CharPtrFromSPtr(lParam));
InvalidateStyleRedraw();
}
break;
case SCI_STYLESETUNDERLINE: case SCI_STYLESETUNDERLINE:
if (wParam <= STYLE_MAX) {
vs.styles[wParam].underline = lParam != 0;
InvalidateStyleRedraw();
}
break;
case SCI_STYLESETCASE: case SCI_STYLESETCASE:
if (wParam <= STYLE_MAX) {
vs.styles[wParam].caseForce = static_cast<Style::ecaseForced>(lParam);
InvalidateStyleRedraw();
}
break;
case SCI_STYLESETCHARACTERSET: case SCI_STYLESETCHARACTERSET:
if (wParam <= STYLE_MAX) {
vs.styles[wParam].characterSet = lParam;
InvalidateStyleRedraw();
}
break;
case SCI_STYLESETVISIBLE: case SCI_STYLESETVISIBLE:
if (wParam <= STYLE_MAX) {
vs.styles[wParam].visible = lParam != 0;
InvalidateStyleRedraw();
}
break;
case SCI_STYLESETCHANGEABLE: case SCI_STYLESETCHANGEABLE:
if (wParam <= STYLE_MAX) {
vs.styles[wParam].changeable = lParam != 0;
InvalidateStyleRedraw();
}
break;
case SCI_STYLESETHOTSPOT: case SCI_STYLESETHOTSPOT:
if (wParam <= STYLE_MAX) { StyleSetMessage(iMessage, wParam, lParam);
vs.styles[wParam].hotspot = lParam != 0;
InvalidateStyleRedraw();
}
break; break;
case SCI_STYLEGETFORE:
if (wParam <= STYLE_MAX)
return vs.styles[wParam].fore.desired.AsLong();
else
return 0;
case SCI_STYLEGETBACK:
if (wParam <= STYLE_MAX)
return vs.styles[wParam].back.desired.AsLong();
else
return 0;
case SCI_STYLEGETBOLD:
if (wParam <= STYLE_MAX)
return vs.styles[wParam].bold ? 1 : 0;
else
return 0;
case SCI_STYLEGETITALIC:
if (wParam <= STYLE_MAX)
return vs.styles[wParam].italic ? 1 : 0;
else
return 0;
case SCI_STYLEGETEOLFILLED:
if (wParam <= STYLE_MAX)
return vs.styles[wParam].eolFilled ? 1 : 0;
else
return 0;
case SCI_STYLEGETSIZE:
if (wParam <= STYLE_MAX)
return vs.styles[wParam].size;
else
return 0;
case SCI_STYLEGETFONT:
if (lParam == 0)
return strlen(vs.styles[wParam].fontName);
if (wParam <= STYLE_MAX) case SCI_STYLEGETFORE:
strcpy(CharPtrFromSPtr(lParam), vs.styles[wParam].fontName); case SCI_STYLEGETBACK:
break; case SCI_STYLEGETBOLD:
case SCI_STYLEGETITALIC:
case SCI_STYLEGETEOLFILLED:
case SCI_STYLEGETSIZE:
case SCI_STYLEGETFONT:
case SCI_STYLEGETUNDERLINE: case SCI_STYLEGETUNDERLINE:
if (wParam <= STYLE_MAX)
return vs.styles[wParam].underline ? 1 : 0;
else
return 0;
case SCI_STYLEGETCASE: case SCI_STYLEGETCASE:
if (wParam <= STYLE_MAX)
return static_cast<int>(vs.styles[wParam].caseForce);
else
return 0;
case SCI_STYLEGETCHARACTERSET: case SCI_STYLEGETCHARACTERSET:
if (wParam <= STYLE_MAX)
return vs.styles[wParam].characterSet;
else
return 0;
case SCI_STYLEGETVISIBLE: case SCI_STYLEGETVISIBLE:
if (wParam <= STYLE_MAX)
return vs.styles[wParam].visible ? 1 : 0;
else
return 0;
case SCI_STYLEGETCHANGEABLE: case SCI_STYLEGETCHANGEABLE:
if (wParam <= STYLE_MAX)
return vs.styles[wParam].changeable ? 1 : 0;
else
return 0;
case SCI_STYLEGETHOTSPOT: case SCI_STYLEGETHOTSPOT:
if (wParam <= STYLE_MAX) return StyleGetMessage(iMessage, wParam, lParam);
return vs.styles[wParam].hotspot ? 1 : 0;
else
return 0;
case SCI_STYLERESETDEFAULT: case SCI_STYLERESETDEFAULT:
vs.ResetDefaultStyle(); vs.ResetDefaultStyle();
InvalidateStyleRedraw(); InvalidateStyleRedraw();
break; break;
case SCI_SETSTYLEBITS: case SCI_SETSTYLEBITS:
vs.EnsureStyle((1 << wParam) - 1);
pdoc->SetStylingBits(wParam); pdoc->SetStylingBits(wParam);
break; break;

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

View File

@ -2,7 +2,7 @@
/** @file LexBash.cxx /** @file LexBash.cxx
** Lexer for Bash. ** 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 // 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. // The License.txt file describes the conditions under which this software may be distributed.
@ -20,11 +20,17 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "SciLexer.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_ERROR 65
#define BASH_BASE_DECIMAL 66 #define BASH_BASE_DECIMAL 66
#define BASH_BASE_HEX 67 #define BASH_BASE_HEX 67
#ifdef PEDANTIC_OCTAL
#define BASH_BASE_OCTAL 68 #define BASH_BASE_OCTAL 68
#define BASH_BASE_OCTAL_ERROR 69 #define BASH_BASE_OCTAL_ERROR 69
#endif
#define HERE_DELIM_MAX 256 #define HERE_DELIM_MAX 256
@ -277,7 +283,11 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
ch = chNext; ch = chNext;
chNext = chNext2; chNext = chNext2;
} else if (isdigit(chNext)) { } else if (isdigit(chNext)) {
#ifdef PEDANTIC_OCTAL
numBase = BASH_BASE_OCTAL; numBase = BASH_BASE_OCTAL;
#else
numBase = BASH_BASE_HEX;
#endif
} }
} }
} else if (iswordstart(ch)) { } else if (iswordstart(ch)) {
@ -369,6 +379,7 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
// hex digit 0-9a-fA-F // hex digit 0-9a-fA-F
} else } else
goto numAtEnd; goto numAtEnd;
#ifdef PEDANTIC_OCTAL
} else if (numBase == BASH_BASE_OCTAL || } else if (numBase == BASH_BASE_OCTAL ||
numBase == BASH_BASE_OCTAL_ERROR) { numBase == BASH_BASE_OCTAL_ERROR) {
if (digit > 7) { if (digit > 7) {
@ -377,6 +388,7 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
} else } else
goto numAtEnd; goto numAtEnd;
} }
#endif
} else if (numBase == BASH_BASE_ERROR) { } else if (numBase == BASH_BASE_ERROR) {
if (digit > 9) if (digit > 9)
goto numAtEnd; goto numAtEnd;
@ -394,8 +406,11 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
} }
} else { } else {
numAtEnd: numAtEnd:
if (numBase == BASH_BASE_ERROR || if (numBase == BASH_BASE_ERROR
numBase == BASH_BASE_OCTAL_ERROR) #ifdef PEDANTIC_OCTAL
|| numBase == BASH_BASE_OCTAL_ERROR
#endif
)
state = SCE_SH_ERROR; state = SCE_SH_ERROR;
styler.ColourTo(i - 1, state); styler.ColourTo(i - 1, state);
state = SCE_SH_DEFAULT; state = SCE_SH_DEFAULT;

View File

@ -32,6 +32,24 @@ static bool IsSpaceEquiv(int state) {
(state == SCE_C_COMMENTDOCKEYWORDERROR); (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[], static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
Accessor &styler, bool caseSensitive) { 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; bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;
CharacterSet setOKBeforeRE(CharacterSet::setNone, "(=,"); CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-");
CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-");
CharacterSet setDoxygen(CharacterSet::setLower, "$@\\&<>#{}[]"); CharacterSet setDoxygen(CharacterSet::setLower, "$@\\&<>#{}[]");
@ -297,7 +316,8 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo
sc.SetState(SCE_C_COMMENTLINEDOC); sc.SetState(SCE_C_COMMENTLINEDOC);
else else
sc.SetState(SCE_C_COMMENTLINE); 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 sc.SetState(SCE_C_REGEX); // JavaScript's RegEx
} else if (sc.ch == '\"') { } else if (sc.ch == '\"') {
sc.SetState(SCE_C_STRING); sc.SetState(SCE_C_STRING);

View File

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

View File

@ -819,7 +819,7 @@ static bool strstart(const char *haystack, const char *needle) {
return strncmp(haystack, needle, strlen(needle)) == 0; 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] == '>') { if (lineBuffer[0] == '>') {
// Command or return status // Command or return status
return SCE_ERR_CMD; return SCE_ERR_CMD;
@ -902,7 +902,9 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin
// Microsoft: <filename>(<line>,<column>)<message> // Microsoft: <filename>(<line>,<column>)<message>
// CTags: \t<message> // CTags: \t<message>
// Lua 5 traceback: \t<filename>:<line>:<message> // Lua 5 traceback: \t<filename>:<line>:<message>
// Lua 5.1: <exe>: <filename>:<line>:<message>
bool initialTab = (lineBuffer[0] == '\t'); bool initialTab = (lineBuffer[0] == '\t');
bool initialColonPart = false;
enum { stInitial, enum { stInitial,
stGccStart, stGccDigit, stGcc, stGccStart, stGccDigit, stGcc,
stMsStart, stMsDigit, stMsBracket, stMsVc, stMsDigitComma, stMsDotNet, stMsStart, stMsDigit, stMsBracket, stMsVc, stMsDigitComma, stMsDotNet,
@ -917,10 +919,12 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin
if (state == stInitial) { if (state == stInitial) {
if (ch == ':') { if (ch == ':') {
// May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix) // 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 // This check is not completely accurate as may be on
// GTK+ with a file name that includes ':'. // 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)) { } else if ((ch == '(') && Is1To9(chNext) && (!initialTab)) {
// May be Microsoft // May be Microsoft
@ -935,6 +939,7 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin
} else if (state == stGccDigit) { // <filename>:<line> } else if (state == stGccDigit) { // <filename>:<line>
if (ch == ':') { if (ch == ':') {
state = stGcc; // :9.*: is GCC state = stGcc; // :9.*: is GCC
startValue = i + 1;
break; break;
} else if (!Is0To9(ch)) { } else if (!Is0To9(ch)) {
state = stUnrecognized; state = stUnrecognized;
@ -995,7 +1000,7 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin
} }
} }
if (state == stGcc) { if (state == stGcc) {
return SCE_ERR_GCC; return initialColonPart ? SCE_ERR_LUA : SCE_ERR_GCC;
} else if ((state == stMsVc) || (state == stMsDotNet)) { } else if ((state == stMsVc) || (state == stMsDotNet)) {
return SCE_ERR_MS; return SCE_ERR_MS;
} else if ((state == stCtagsStringDollar) || (state == stCtags)) { } else if ((state == stCtagsStringDollar) || (state == stCtags)) {
@ -1010,8 +1015,16 @@ static void ColouriseErrorListLine(
char *lineBuffer, char *lineBuffer,
unsigned int lengthLine, unsigned int lengthLine,
unsigned int endPos, unsigned int endPos,
Accessor &styler) { Accessor &styler,
styler.ColourTo(endPos, RecogniseErrorListLine(lineBuffer, lengthLine)); 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) { 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.StartAt(startPos);
styler.StartSegment(startPos); styler.StartSegment(startPos);
unsigned int linePos = 0; unsigned int linePos = 0;
bool valueSeparate = styler.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0;
for (unsigned int i = startPos; i < startPos + length; i++) { for (unsigned int i = startPos; i < startPos + length; i++) {
lineBuffer[linePos++] = styler[i]; lineBuffer[linePos++] = styler[i];
if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
// End of line (or of line buffer) met, colourise it // End of line (or of line buffer) met, colourise it
lineBuffer[linePos] = '\0'; lineBuffer[linePos] = '\0';
ColouriseErrorListLine(lineBuffer, linePos, i, styler); ColouriseErrorListLine(lineBuffer, linePos, i, styler, valueSeparate);
linePos = 0; linePos = 0;
} }
} }
if (linePos > 0) { // Last line does not have ending characters 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 /** @file LexPerl.cxx
** Lexer for subset of Perl. ** 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> // 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. // 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]; WordList &keywords = *keywordlists[0];
// keywords that forces /PATTERN/ at all times
WordList reWords;
reWords.Set("elsif if split while");
class HereDocCls { class HereDocCls {
public: public:
int State; // 0: '<<' encountered int State; // 0: '<<' encountered
@ -187,6 +191,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
//char sooked[100]; //char sooked[100];
//sooked[sookedpos] = '\0'; //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 // 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 strings can be multi-line with embedded newlines, so backtrack.
// Perl numbers have additional state during lexing, so backtrack too. // 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)); startPos = styler.LineStart(styler.GetLine(startPos));
state = styler.StyleAt(startPos - 1); 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 if ( state == SCE_PL_STRING_Q
|| state == SCE_PL_STRING_QQ || state == SCE_PL_STRING_QQ
|| state == SCE_PL_STRING_QX || 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_NUMBER
|| state == SCE_PL_IDENTIFIER || state == SCE_PL_IDENTIFIER
|| state == SCE_PL_ERROR || state == SCE_PL_ERROR
|| state == SCE_PL_SUB_PROTOTYPE
) { ) {
while ((startPos > 1) && (styler.StyleAt(startPos - 1) == state)) { while ((startPos > 1) && (styler.StyleAt(startPos - 1) == state)) {
startPos--; startPos--;
@ -233,7 +247,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
backflag = BACK_KEYWORD; backflag = BACK_KEYWORD;
} }
styler.StartAt(startPos); styler.StartAt(startPos, static_cast<char>(STYLE_MAX));
char chPrev = styler.SafeGetCharAt(startPos - 1); char chPrev = styler.SafeGetCharAt(startPos - 1);
if (startPos == 0) if (startPos == 0)
chPrev = '\n'; 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 (state == SCE_PL_DEFAULT) {
if ((isascii(ch) && isdigit(ch)) || (isascii(chNext) && isdigit(chNext) && 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); styler.ColourTo(i, SCE_PL_DATASECTION);
state = SCE_PL_DATASECTION; state = SCE_PL_DATASECTION;
} else { } else {
styler.ColourTo(i, SCE_PL_WORD); if (isMatch(styler, lengthDoc, styler.GetStartSegment(), "format")) {
state = SCE_PL_FORMAT_IDENT;
HereDoc.State = 0;
} else {
state = SCE_PL_DEFAULT; state = SCE_PL_DEFAULT;
}
styler.ColourTo(i, SCE_PL_WORD);
backflag = BACK_KEYWORD; backflag = BACK_KEYWORD;
backPos = i; backPos = i;
} }
@ -440,8 +465,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
chNext = styler.SafeGetCharAt(i + 1); chNext = styler.SafeGetCharAt(i + 1);
// a repetition operator 'x' // a repetition operator 'x'
} else if (state == SCE_PL_OPERATOR) { } else if (state == SCE_PL_OPERATOR) {
styler.ColourTo(i, SCE_PL_OPERATOR);
state = SCE_PL_DEFAULT; state = SCE_PL_DEFAULT;
goto handleOperator;
// quote-like delimiter, skip one char if double-char delimiter // quote-like delimiter, skip one char if double-char delimiter
} else { } else {
i = kw - 1; i = kw - 1;
@ -502,6 +527,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
} }
backflag = BACK_NONE; backflag = BACK_NONE;
} else if (ch == '%') { } else if (ch == '%') {
backflag = BACK_NONE;
if (!isascii(chNext) || isalpha(chNext) || chNext == '#' || chNext == '$' if (!isascii(chNext) || isalpha(chNext) || chNext == '#' || chNext == '$'
|| chNext == '_' || chNext == '!' || chNext == '^') { || chNext == '_' || chNext == '!' || chNext == '^') {
state = SCE_PL_HASH; state = SCE_PL_HASH;
@ -516,10 +542,10 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
} else if (chNext == '{') { } else if (chNext == '{') {
styler.ColourTo(i, SCE_PL_HASH); styler.ColourTo(i, SCE_PL_HASH);
} else { } else {
styler.ColourTo(i, SCE_PL_OPERATOR); goto handleOperator;
} }
backflag = BACK_NONE;
} else if (ch == '*') { } else if (ch == '*') {
backflag = BACK_NONE;
char strch[2]; char strch[2];
strch[0] = chNext; strch[0] = chNext;
strch[1] = '\0'; strch[1] = '\0';
@ -542,9 +568,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
ch = chNext; ch = chNext;
chNext = chNext2; chNext = chNext2;
} }
styler.ColourTo(i, SCE_PL_OPERATOR); goto handleOperator;
} }
backflag = BACK_NONE;
} else if (ch == '/' || (ch == '<' && chNext == '<')) { } else if (ch == '/' || (ch == '<' && chNext == '<')) {
// Explicit backward peeking to set a consistent preferRE for // Explicit backward peeking to set a consistent preferRE for
// any slash found, so no longer need to track preferRE state. // 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 hereDocSpace = false; // these are for corner case:
bool hereDocScalar = false; // SCALAR [whitespace] '<<' bool hereDocScalar = false; // SCALAR [whitespace] '<<'
unsigned int bk = (i > 0)? i - 1: 0; unsigned int bk = (i > 0)? i - 1: 0;
unsigned int bkend;
char bkch; char bkch;
styler.Flush(); styler.Flush();
if (styler.StyleAt(bk) == SCE_PL_DEFAULT) 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 || if (bkstyle == SCE_PL_DEFAULT ||
bkstyle == SCE_PL_COMMENTLINE) { bkstyle == SCE_PL_COMMENTLINE) {
} else if (bkstyle == SCE_PL_OPERATOR) { } else if (bkstyle == SCE_PL_OPERATOR) {
// gcc 3.2.3 bloats if more compact form used
bkch = styler.SafeGetCharAt(bk); bkch = styler.SafeGetCharAt(bk);
if (bkch == '>') { // "->" // test for "->" and "::"
if (styler.SafeGetCharAt(bk - 1) == '-') { if ((bkch == '>' && styler.SafeGetCharAt(bk - 1) == '-')
|| (bkch == ':' && styler.SafeGetCharAt(bk - 1) == ':')) {
preferRE = false; preferRE = false;
break; break;
} }
} else if (bkch == ':') { // "::" } else {
if (styler.SafeGetCharAt(bk - 1) == ':') { // bare identifier, if '/', /PATTERN/ unless digit/space immediately after '/'
if (!isHereDoc &&
(isspacechar(chNext) || isdigit(chNext)))
preferRE = false; preferRE = false;
break; // HERE docs cannot have a space after the >>
} if (isspacechar(chNext))
}
} 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; preferRE = false;
}
break; break;
} }
bk--; bk--;
@ -659,8 +680,24 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
case SCE_PL_SCALAR: // for $var<< case case SCE_PL_SCALAR: // for $var<< case
hereDocScalar = true; hereDocScalar = true;
break; break;
// other styles uses the default, preferRE=false // for HERE docs, always true for preferRE
case SCE_PL_WORD: 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:
case SCE_PL_POD_VERB: case SCE_PL_POD_VERB:
case SCE_PL_HERE_Q: case SCE_PL_HERE_Q:
@ -670,6 +707,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
break; break;
} }
} }
backflag = BACK_NONE;
if (isHereDoc) { // handle HERE doc if (isHereDoc) { // handle HERE doc
// if SCALAR whitespace '<<', *always* a HERE doc // if SCALAR whitespace '<<', *always* a HERE doc
if (preferRE || (hereDocSpace && hereDocScalar)) { if (preferRE || (hereDocSpace && hereDocScalar)) {
@ -679,7 +717,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
i++; i++;
ch = chNext; ch = chNext;
chNext = chNext2; chNext = chNext2;
styler.ColourTo(i, SCE_PL_OPERATOR); goto handleOperator;
} }
} else { // handle regexp } else { // handle regexp
if (preferRE) { if (preferRE) {
@ -687,10 +725,9 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
Quote.New(1); Quote.New(1);
Quote.Open(ch); Quote.Open(ch);
} else { // / operator } else { // / operator
styler.ColourTo(i, SCE_PL_OPERATOR); goto handleOperator;
} }
} }
backflag = BACK_NONE;
} else if (ch == '<') { } else if (ch == '<') {
// looks forward for matching > on same line // looks forward for matching > on same line
unsigned int fw = i + 1; unsigned int fw = i + 1;
@ -699,24 +736,23 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
if (fwch == ' ') { if (fwch == ' ') {
if (styler.SafeGetCharAt(fw-1) != '\\' || if (styler.SafeGetCharAt(fw-1) != '\\' ||
styler.SafeGetCharAt(fw-2) != '\\') styler.SafeGetCharAt(fw-2) != '\\')
break; goto handleOperator;
} else if (isEOLChar(fwch) || isspacechar(fwch)) { } else if (isEOLChar(fwch) || isspacechar(fwch)) {
break; goto handleOperator;
} else if (fwch == '>') { } else if (fwch == '>') {
if ((fw - i) == 2 && // '<=>' case if ((fw - i) == 2 && // '<=>' case
styler.SafeGetCharAt(fw-1) == '=') { styler.SafeGetCharAt(fw-1) == '=') {
styler.ColourTo(fw, SCE_PL_OPERATOR); goto handleOperator;
} else {
styler.ColourTo(fw, SCE_PL_IDENTIFIER);
} }
styler.ColourTo(fw, SCE_PL_IDENTIFIER);
i = fw; i = fw;
ch = fwch; ch = fwch;
chNext = styler.SafeGetCharAt(i+1); chNext = styler.SafeGetCharAt(i+1);
} }
fw++; fw++;
} }
styler.ColourTo(i, SCE_PL_OPERATOR); if (fw == lengthDoc)
backflag = BACK_NONE; goto handleOperator;
} else if (ch == '=' // POD } else if (ch == '=' // POD
&& isalpha(chNext) && isalpha(chNext)
&& (isEOLChar(chPrev))) { && (isEOLChar(chPrev))) {
@ -733,6 +769,35 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
ch = chNext; ch = chNext;
chNext = chNext2; chNext = chNext2;
backflag = BACK_NONE; 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)) { } else if (isPerlOperator(ch)) {
if (ch == '.' && chNext == '.') { // .. and ... if (ch == '.' && chNext == '.') { // .. and ...
i++; i++;
@ -741,9 +806,13 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
ch = styler.SafeGetCharAt(i); ch = styler.SafeGetCharAt(i);
chNext = styler.SafeGetCharAt(i + 1); chNext = styler.SafeGetCharAt(i + 1);
} }
handleOperator:
styler.ColourTo(i, SCE_PL_OPERATOR); styler.ColourTo(i, SCE_PL_OPERATOR);
backflag = BACK_OPERATOR; backflag = BACK_OPERATOR;
backPos = i; backPos = i;
} else if (ch == 4 || ch == 26) { // ^D and ^Z ends valid perl source
styler.ColourTo(i, SCE_PL_DATASECTION);
state = SCE_PL_DATASECTION;
} else { } else {
// keep colouring defaults to make restart easier // keep colouring defaults to make restart easier
styler.ColourTo(i, SCE_PL_DEFAULT); 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) { } else if (numState <= PERLNUM_FLOAT) {
// non-decimal number or float exponent, consume next dot // non-decimal number or float exponent, consume next dot
styler.ColourTo(i - 1, SCE_PL_NUMBER); styler.ColourTo(i - 1, SCE_PL_NUMBER);
styler.ColourTo(i, SCE_PL_OPERATOR);
state = SCE_PL_DEFAULT; state = SCE_PL_DEFAULT;
goto handleOperator;
} else { // decimal or vectors allows dots } else { // decimal or vectors allows dots
dotCount++; dotCount++;
if (numState == PERLNUM_DECIMAL) { if (numState == PERLNUM_DECIMAL) {
@ -772,10 +841,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
goto numAtEnd; goto numAtEnd;
} }
} }
} else if (ch == '_' && numState == PERLNUM_DECIMAL) { } else if (ch == '_') {
if (!isdigit(chNext)) { // permissive underscoring for number and vector literals
goto numAtEnd;
}
} else if (!isascii(ch) || isalnum(ch)) { } else if (!isascii(ch) || isalnum(ch)) {
if (numState == PERLNUM_VECTOR || numState == PERLNUM_V_VECTOR) { if (numState == PERLNUM_VECTOR || numState == PERLNUM_V_VECTOR) {
if (!isascii(ch) || isalpha(ch)) { if (!isascii(ch) || isalpha(ch)) {
@ -899,6 +966,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
i = oldi; i = oldi;
styler.ColourTo(i, SCE_PL_OPERATOR); styler.ColourTo(i, SCE_PL_OPERATOR);
state = SCE_PL_DEFAULT; state = SCE_PL_DEFAULT;
backflag = BACK_OPERATOR;
backPos = i;
HereDoc.State = 0; HereDoc.State = 0;
goto restartLexer; goto restartLexer;
} else { } else {
@ -1118,6 +1187,62 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
} else if (ch == Quote.Up) { } else if (ch == Quote.Up) {
Quote.Count++; 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) { if (state == SCE_PL_ERROR) {
@ -1256,5 +1381,5 @@ static const char * const perlWordListDesc[] = {
0 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); sc.SetState(SCE_P_DEFAULT);
} }
} else if (sc.state == SCE_P_DECORATOR) { } else if (sc.state == SCE_P_DECORATOR) {
if (sc.ch == '\r' || sc.ch == '\n') { if (!IsAWordChar(sc.ch)) {
sc.SetState(SCE_P_DEFAULT); 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)) { } else if ((sc.state == SCE_P_STRING) || (sc.state == SCE_P_CHARACTER)) {
if (sc.ch == '\\') { if (sc.ch == '\\') {

View File

@ -25,7 +25,7 @@ using namespace Scintilla;
#endif #endif
static inline bool IsAWordChar(int ch) { 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) { static inline bool IsAWordStart(int ch) {

View File

@ -89,7 +89,7 @@ public:
body = 0; body = 0;
} }
int Partitions() { int Partitions() const {
return body->Length()-1; return body->Length()-1;
} }
@ -141,7 +141,7 @@ public:
body->Delete(partition); body->Delete(partition);
} }
int PositionFromPartition(int partition) { int PositionFromPartition(int partition) const {
PLATFORM_ASSERT(partition >= 0); PLATFORM_ASSERT(partition >= 0);
PLATFORM_ASSERT(partition < body->Length()); PLATFORM_ASSERT(partition < body->Length());
if ((partition < 0) || (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); 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 { struct ListImage {
const char *xpm_data; const char *xpm_data;
#if GTK_MAJOR_VERSION < 2 #if GTK_MAJOR_VERSION < 2

View File

@ -14,13 +14,12 @@
#include "Scintilla.h" #include "Scintilla.h"
#include "ContractionState.h"
#include "SVector.h"
#include "SplitVector.h" #include "SplitVector.h"
#include "Partitioning.h" #include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"
#include "CellBuffer.h" #include "CellBuffer.h"
#include "KeyMap.h" #include "KeyMap.h"
#include "RunStyles.h"
#include "Indicator.h" #include "Indicator.h"
#include "XPM.h" #include "XPM.h"
#include "LineMarker.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) { void LineLayout::SetLineStart(int line, int start) {
if ((line >= lenLineStarts) && (line != 0)) { if ((line >= lenLineStarts) && (line != 0)) {
int newMaxLines = line + 20; int newMaxLines = line + 20;
@ -341,12 +345,23 @@ void LineLayoutCache::Dispose(LineLayout *ll) {
} }
void BreakFinder::Insert(int val) { 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) { if (val >= nextBreak) {
for (unsigned int j = 0; j<saeLen; j++) { for (unsigned int j = 0; j<saeLen; j++) {
if (val == selAndEdge[j]) { if (val == selAndEdge[j]) {
return; return;
} if (val < selAndEdge[j]) { } 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]; selAndEdge[k] = selAndEdge[k-1];
} }
saeLen++; 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_), ll(ll_),
lineStart(lineStart_), lineStart(lineStart_),
lineEnd(lineEnd_), lineEnd(lineEnd_),
posLineStart(posLineStart_), posLineStart(posLineStart_),
utf8(utf8_),
nextBreak(lineStart_), nextBreak(lineStart_),
saeSize(0),
saeLen(0), saeLen(0),
saeCurrentPos(0), saeCurrentPos(0),
saeNext(0), saeNext(0),
subBreak(-1) { 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; selAndEdge[j] = 0;
} }
@ -388,9 +418,24 @@ BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posL
Insert(ll->edgeColumn - 1); Insert(ll->edgeColumn - 1);
Insert(lineEnd - 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; saeNext = (saeLen > 0) ? selAndEdge[0] : -1;
} }
BreakFinder::~BreakFinder() {
delete []selAndEdge;
}
int BreakFinder::First() { int BreakFinder::First() {
return nextBreak; return nextBreak;
} }

View File

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

View File

@ -333,8 +333,6 @@ char *SContainer::StringAllocate(const char *s, lenpos_t len) {
// End SString functions // End SString functions
bool PropSet::caseSensitiveFilenames = false;
PropSet::PropSet() { PropSet::PropSet() {
superPS = 0; superPS = 0;
for (int root = 0; root < hashRoots; root++) for (int root = 0; root < hashRoots; root++)
@ -426,7 +424,7 @@ void PropSet::SetMultiple(const char *s) {
Set(s); Set(s);
} }
SString PropSet::Get(const char *key) { SString PropSet::Get(const char *key) const {
unsigned int hash = HashString(key, strlen(key)); unsigned int hash = HashString(key, strlen(key));
for (Property *p = props[hash % hashRoots]; p; p = p->next) { for (Property *p = props[hash % hashRoots]; p; p = p->next) {
if ((hash == p->hash) && (0 == strcmp(p->key, key))) { 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)"). // 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 // 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 // recursive expansions can be skipped. For now I'll just use the C++ stack
@ -473,7 +456,7 @@ struct VarChain {
const VarChain *link; 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("$("); int varStart = withVars.search("$(");
while ((varStart >= 0) && (maxExpands > 0)) { while ((varStart >= 0) && (maxExpands > 0)) {
int varEnd = withVars.search(")", varStart+2); int varEnd = withVars.search(")", varStart+2);
@ -509,20 +492,19 @@ static int ExpandAllInPlace(PropSet &props, SString &withVars, int maxExpands, c
return maxExpands; return maxExpands;
} }
SString PropSet::GetExpanded(const char *key) const {
SString PropSet::GetExpanded(const char *key) {
SString val = Get(key); SString val = Get(key);
ExpandAllInPlace(*this, val, 100, VarChain(key)); ExpandAllInPlace(*this, val, 100, VarChain(key));
return val; return val;
} }
SString PropSet::Expand(const char *withVars, int maxExpands) { SString PropSet::Expand(const char *withVars, int maxExpands) const {
SString val = withVars; SString val = withVars;
ExpandAllInPlace(*this, val, maxExpands); ExpandAllInPlace(*this, val, maxExpands);
return val; return val;
} }
int PropSet::GetInt(const char *key, int defaultValue) { int PropSet::GetInt(const char *key, int defaultValue) const {
SString val = GetExpanded(key); SString val = GetExpanded(key);
if (val.length()) if (val.length())
return val.value(); return val.value();
@ -542,118 +524,6 @@ bool isprefix(const char *target, const char *prefix) {
return true; 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() { void PropSet::Clear() {
for (int root = 0; root < hashRoots; root++) { for (int root = 0; root < hashRoots; root++) {
Property *p = props[root]; Property *p = props[root];
@ -671,7 +541,7 @@ void PropSet::Clear() {
} }
} }
char *PropSet::ToString() { char *PropSet::ToString() const {
size_t len=0; size_t len=0;
for (int r = 0; r < hashRoots; r++) { for (int r = 0; r < hashRoots; r++) {
for (Property *p = props[r]; p; p = p->next) { for (Property *p = props[r]; p; p = p->next) {
@ -699,50 +569,6 @@ char *PropSet::ToString() {
return ret; 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 * Creates an array that points into each word in the string and puts \0 terminators
* after each word. * after each word.
@ -796,37 +622,17 @@ void WordList::Clear() {
if (words) { if (words) {
delete []list; delete []list;
delete []words; delete []words;
delete []wordsNoCase;
} }
words = 0; words = 0;
wordsNoCase = 0;
list = 0; list = 0;
len = 0; len = 0;
sorted = false; sorted = false;
sortedNoCase = false;
} }
void WordList::Set(const char *s) { void WordList::Set(const char *s) {
list = StringDup(s); list = StringDup(s);
sorted = false; sorted = false;
sortedNoCase = false;
words = ArrayFromWordList(list, &len, onlyLineEnds); 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) { 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)); 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) { static void SortWordList(char **words, unsigned int len) {
qsort(reinterpret_cast<void*>(words), len, sizeof(*words), qsort(reinterpret_cast<void*>(words), len, sizeof(*words),
cmpString); cmpString);
} }
static void SortWordListNoCase(char **wordsNoCase, unsigned int len) {
qsort(reinterpret_cast<void*>(wordsNoCase), len, sizeof(*wordsNoCase),
cmpStringNoCase);
}
bool WordList::InList(const char *s) { bool WordList::InList(const char *s) {
if (0 == words) if (0 == words)
return false; return false;
@ -865,7 +661,7 @@ bool WordList::InList(const char *s) {
unsigned char firstChar = s[0]; unsigned char firstChar = s[0];
int j = starts[firstChar]; int j = starts[firstChar];
if (j >= 0) { if (j >= 0) {
while (words[j][0] == firstChar) { while ((unsigned char)words[j][0] == firstChar) {
if (s[1] == words[j][1]) { if (s[1] == words[j][1]) {
const char *a = words[j] + 1; const char *a = words[j] + 1;
const char *b = s + 1; const char *b = s + 1;
@ -957,221 +753,3 @@ bool WordList::InListAbbreviated(const char *s, const char marker) {
} }
return false; 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; return true;
} }
void RunStyles::SetValueAt(int position, int value) {
int len = 1;
FillRange(position, value, len);
}
void RunStyles::InsertSpace(int position, int insertLength) { void RunStyles::InsertSpace(int position, int insertLength) {
int runStart = RunFromPosition(position); int runStart = RunFromPosition(position);
if (starts->PositionFromPartition(runStart) == position) { if (starts->PositionFromPartition(runStart) == position) {

View File

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

View File

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

View File

@ -26,10 +26,11 @@
#include "Accessor.h" #include "Accessor.h"
#include "KeyWords.h" #include "KeyWords.h"
#endif #endif
#include "ContractionState.h"
#include "SVector.h" #include "SVector.h"
#include "SplitVector.h" #include "SplitVector.h"
#include "Partitioning.h" #include "Partitioning.h"
#include "RunStyles.h"
#include "ContractionState.h"
#include "CellBuffer.h" #include "CellBuffer.h"
#include "CallTip.h" #include "CallTip.h"
#include "KeyMap.h" #include "KeyMap.h"
@ -39,7 +40,6 @@
#include "Style.h" #include "Style.h"
#include "AutoComplete.h" #include "AutoComplete.h"
#include "ViewStyle.h" #include "ViewStyle.h"
#include "RunStyles.h"
#include "Decoration.h" #include "Decoration.h"
#include "CharClassify.h" #include "CharClassify.h"
#include "Document.h" #include "Document.h"
@ -198,6 +198,7 @@ private:
void ReceivedDrop(GtkSelectionData *selection_data); void ReceivedDrop(GtkSelectionData *selection_data);
static void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *selected); static void GetSelection(GtkSelectionData *selection_data, guint info, SelectionText *selected);
#ifdef USE_GTK_CLIPBOARD #ifdef USE_GTK_CLIPBOARD
void StoreOnClipboard(SelectionText *clipText);
static void ClipboardGetSelection(GtkClipboard* clip, GtkSelectionData *selection_data, guint info, void *data); static void ClipboardGetSelection(GtkClipboard* clip, GtkSelectionData *selection_data, guint info, void *data);
static void ClipboardClearSelection(GtkClipboard* clip, void *data); static void ClipboardClearSelection(GtkClipboard* clip, void *data);
#endif #endif
@ -1296,17 +1297,9 @@ void ScintillaGTK::CopyToClipboard(const SelectionText &selectedText) {
atomClipboard, atomClipboard,
GDK_CURRENT_TIME); GDK_CURRENT_TIME);
#else #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(); SelectionText *clipText = new SelectionText();
clipText->Copy(selectedText); clipText->Copy(selectedText);
StoreOnClipboard(clipText);
gtk_clipboard_set_with_data(clipBoard, clipboardCopyTargets, nClipboardCopyTargets,
ClipboardGetSelection, ClipboardClearSelection, clipText);
#endif #endif
} }
@ -1318,17 +1311,9 @@ void ScintillaGTK::Copy() {
atomClipboard, atomClipboard,
GDK_CURRENT_TIME); GDK_CURRENT_TIME);
#else #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(); SelectionText *clipText = new SelectionText();
CopySelectionRange(clipText); CopySelectionRange(clipText);
StoreOnClipboard(clipText);
gtk_clipboard_set_with_data(clipBoard, clipboardCopyTargets, nClipboardCopyTargets,
ClipboardGetSelection, ClipboardClearSelection, clipText);
#endif #endif
#if PLAT_GTK_WIN32 #if PLAT_GTK_WIN32
if (selType == selRectangle) { if (selType == selRectangle) {
@ -1644,6 +1629,18 @@ void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, Se
} }
#ifdef USE_GTK_CLIPBOARD #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) { void ScintillaGTK::ClipboardGetSelection(GtkClipboard *, GtkSelectionData *selection_data, guint info, void *data) {
GetSelection(selection_data, info, static_cast<SelectionText*>(data)); GetSelection(selection_data, info, static_cast<SelectionText*>(data));
} }

View File

@ -182,6 +182,14 @@ public:
} }
} }
/// 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. /// Insert text into the buffer from an array.
void InsertFromArray(int positionToInsert, const T s[], int positionFrom, int insertLength) { void InsertFromArray(int positionToInsert, const T s[], int positionFrom, int insertLength) {
PLATFORM_ASSERT((positionToInsert >= 0) && (positionToInsert <= lengthBody)); PLATFORM_ASSERT((positionToInsert >= 0) && (positionToInsert <= lengthBody));

View File

@ -77,8 +77,8 @@ ViewStyle::ViewStyle() {
} }
ViewStyle::ViewStyle(const ViewStyle &source) { ViewStyle::ViewStyle(const ViewStyle &source) {
Init(); Init(source.stylesSize);
for (unsigned int sty=0;sty<(sizeof(styles)/sizeof(styles[0]));sty++) { for (unsigned int sty=0;sty<source.stylesSize;sty++) {
styles[sty] = source.styles[sty]; styles[sty] = source.styles[sty];
// Can't just copy fontname as its lifetime is relative to its owning ViewStyle // Can't just copy fontname as its lifetime is relative to its owning ViewStyle
styles[sty].fontName = fontNames.Save(source.styles[sty].fontName); styles[sty].fontName = fontNames.Save(source.styles[sty].fontName);
@ -142,9 +142,14 @@ ViewStyle::ViewStyle(const ViewStyle &source) {
} }
ViewStyle::~ViewStyle() { ViewStyle::~ViewStyle() {
delete []styles;
styles = NULL;
} }
void ViewStyle::Init() { void ViewStyle::Init(size_t stylesSize_) {
stylesSize = 0;
styles = NULL;
AllocStyles(stylesSize_);
fontNames.Clear(); fontNames.Clear();
ResetDefaultStyle(); ResetDefaultStyle();
@ -224,7 +229,7 @@ void ViewStyle::Init() {
} }
zoomLevel = 0; zoomLevel = 0;
viewWhitespace = wsInvisible; viewWhitespace = wsInvisible;
viewIndentationGuides = false; viewIndentationGuides = ivNone;
viewEOL = false; viewEOL = false;
showMarkedLines = true; showMarkedLines = true;
extraFontFlag = false; extraFontFlag = false;
@ -232,7 +237,7 @@ void ViewStyle::Init() {
void ViewStyle::RefreshColourPalette(Palette &pal, bool want) { void ViewStyle::RefreshColourPalette(Palette &pal, bool want) {
unsigned int i; 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].fore, want);
pal.WantFind(styles[i].back, want); pal.WantFind(styles[i].back, want);
} }
@ -267,7 +272,7 @@ void ViewStyle::Refresh(Surface &surface) {
maxAscent = styles[STYLE_DEFAULT].ascent; maxAscent = styles[STYLE_DEFAULT].ascent;
maxDescent = styles[STYLE_DEFAULT].descent; maxDescent = styles[STYLE_DEFAULT].descent;
someStylesProtected = false; 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) { if (i != STYLE_DEFAULT) {
styles[i].Realise(surface, zoomLevel, &styles[STYLE_DEFAULT], extraFontFlag); styles[i].Realise(surface, zoomLevel, &styles[STYLE_DEFAULT], extraFontFlag);
if (maxAscent < styles[i].ascent) if (maxAscent < styles[i].ascent)
@ -295,6 +300,34 @@ 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() { void ViewStyle::ResetDefaultStyle() {
styles[STYLE_DEFAULT].Clear(ColourDesired(0,0,0), styles[STYLE_DEFAULT].Clear(ColourDesired(0,0,0),
ColourDesired(0xff,0xff,0xff), ColourDesired(0xff,0xff,0xff),
@ -305,7 +338,7 @@ void ViewStyle::ResetDefaultStyle() {
void ViewStyle::ClearStyles() { void ViewStyle::ClearStyles() {
// Reset all styles to be like the default style // 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) { if (i != STYLE_DEFAULT) {
styles[i].ClearTo(styles[STYLE_DEFAULT]); styles[i].ClearTo(styles[STYLE_DEFAULT]);
} }

View File

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

View File

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

View File

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

View File

@ -96,7 +96,10 @@
#define SCLEX_GAP 81 #define SCLEX_GAP 81
#define SCLEX_PLM 82 #define SCLEX_PLM 82
#define SCLEX_PROGRESS 83 #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 SCLEX_AUTOMATIC 1000
#define SCE_P_DEFAULT 0 #define SCE_P_DEFAULT 0
#define SCE_P_COMMENTLINE 1 #define SCE_P_COMMENTLINE 1
@ -317,6 +320,9 @@
#define SCE_PL_STRING_QR 29 #define SCE_PL_STRING_QR 29
#define SCE_PL_STRING_QW 30 #define SCE_PL_STRING_QW 30
#define SCE_PL_POD_VERB 31 #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_DEFAULT 0
#define SCE_RB_ERROR 1 #define SCE_RB_ERROR 1
#define SCE_RB_COMMENTLINE 2 #define SCE_RB_COMMENTLINE 2
@ -422,6 +428,7 @@
#define SCE_ERR_ABSF 18 #define SCE_ERR_ABSF 18
#define SCE_ERR_TIDY 19 #define SCE_ERR_TIDY 19
#define SCE_ERR_JAVA_STACK 20 #define SCE_ERR_JAVA_STACK 20
#define SCE_ERR_VALUE 21
#define SCE_BAT_DEFAULT 0 #define SCE_BAT_DEFAULT 0
#define SCE_BAT_COMMENT 1 #define SCE_BAT_COMMENT 1
#define SCE_BAT_WORD 2 #define SCE_BAT_WORD 2
@ -734,6 +741,7 @@
#define SCE_YAML_DOCUMENT 6 #define SCE_YAML_DOCUMENT 6
#define SCE_YAML_TEXT 7 #define SCE_YAML_TEXT 7
#define SCE_YAML_ERROR 8 #define SCE_YAML_ERROR 8
#define SCE_YAML_OPERATOR 9
#define SCE_TEX_DEFAULT 0 #define SCE_TEX_DEFAULT 0
#define SCE_TEX_SPECIAL 1 #define SCE_TEX_SPECIAL 1
#define SCE_TEX_GROUP 2 #define SCE_TEX_GROUP 2
@ -1159,6 +1167,43 @@
#define SCE_4GL_COMMENT4_ 29 #define SCE_4GL_COMMENT4_ 29
#define SCE_4GL_COMMENT5_ 30 #define SCE_4GL_COMMENT5_ 30
#define SCE_4GL_COMMENT6_ 31 #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_ASP 29
#define SCLEX_PHP 30 #define SCLEX_PHP 30
//--Autogenerated -- end of section automatically generated from Scintilla.iface //--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_INDENTGUIDE 37
#define STYLE_CALLTIP 38 #define STYLE_CALLTIP 38
#define STYLE_LASTPREDEFINED 39 #define STYLE_LASTPREDEFINED 39
#define STYLE_MAX 127 #define STYLE_MAX 255
#define SC_CHARSET_ANSI 0 #define SC_CHARSET_ANSI 0
#define SC_CHARSET_DEFAULT 1 #define SC_CHARSET_DEFAULT 1
#define SC_CHARSET_BALTIC 186 #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_GETCOLUMN 2129
#define SCI_SETHSCROLLBAR 2130 #define SCI_SETHSCROLLBAR 2130
#define SCI_GETHSCROLLBAR 2131 #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_SETINDENTATIONGUIDES 2132
#define SCI_GETINDENTATIONGUIDES 2133 #define SCI_GETINDENTATIONGUIDES 2133
#define SCI_SETHIGHLIGHTGUIDE 2134 #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_GETLAYOUTCACHE 2273
#define SCI_SETSCROLLWIDTH 2274 #define SCI_SETSCROLLWIDTH 2274
#define SCI_GETSCROLLWIDTH 2275 #define SCI_GETSCROLLWIDTH 2275
#define SCI_SETSCROLLWIDTHTRACKING 2516
#define SCI_GETSCROLLWIDTHTRACKING 2517
#define SCI_TEXTWIDTH 2276 #define SCI_TEXTWIDTH 2276
#define SCI_SETENDATLASTLINE 2277 #define SCI_SETENDATLASTLINE 2277
#define SCI_GETENDATLASTLINE 2278 #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_MULTILINEUNDOREDO 0x1000
#define SC_STARTACTION 0x2000 #define SC_STARTACTION 0x2000
#define SC_MOD_CHANGEINDICATOR 0x4000 #define SC_MOD_CHANGEINDICATOR 0x4000
#define SC_MODEVENTMASKALL 0x6FFF #define SC_MOD_CHANGELINESTATE 0x8000
#define SC_MODEVENTMASKALL 0xFFFF
#define SCEN_CHANGE 768 #define SCEN_CHANGE 768
#define SCEN_SETFOCUS 512 #define SCEN_SETFOCUS 512
#define SCEN_KILLFOCUS 256 #define SCEN_KILLFOCUS 256