Revision: 3769 http://geany.svn.sourceforge.net/geany/?rev=3769&view=rev Author: eht16 Date: 2009-05-03 17:49:33 +0000 (Sun, 03 May 2009)
Log Message: ----------- Update Scintilla to version 1.78.
Modified Paths: -------------- trunk/ChangeLog trunk/scintilla/CellBuffer.cxx trunk/scintilla/CellBuffer.h trunk/scintilla/Document.cxx trunk/scintilla/Document.h trunk/scintilla/Editor.cxx trunk/scintilla/Editor.h trunk/scintilla/Indicator.cxx trunk/scintilla/Indicator.h trunk/scintilla/KeyWords.cxx trunk/scintilla/LexBash.cxx trunk/scintilla/LexCPP.cxx trunk/scintilla/LexD.cxx trunk/scintilla/LexFortran.cxx trunk/scintilla/LexHTML.cxx trunk/scintilla/LexOthers.cxx trunk/scintilla/LexPascal.cxx trunk/scintilla/LexPerl.cxx trunk/scintilla/LexPython.cxx trunk/scintilla/LexRuby.cxx trunk/scintilla/LexSQL.cxx trunk/scintilla/LexYAML.cxx trunk/scintilla/Makefile.am trunk/scintilla/PlatGTK.cxx trunk/scintilla/PositionCache.cxx trunk/scintilla/RESearch.cxx trunk/scintilla/ScintillaBase.cxx trunk/scintilla/ScintillaGTK.cxx trunk/scintilla/SplitVector.h trunk/scintilla/UniConversion.cxx trunk/scintilla/ViewStyle.cxx trunk/scintilla/ViewStyle.h trunk/scintilla/include/Accessor.h trunk/scintilla/include/KeyWords.h trunk/scintilla/include/Platform.h trunk/scintilla/include/PropSet.h trunk/scintilla/include/SString.h trunk/scintilla/include/SciLexer.h trunk/scintilla/include/Scintilla.h trunk/scintilla/include/Scintilla.iface trunk/scintilla/include/WindowAccessor.h trunk/scintilla/makefile.win32 trunk/scintilla/scintilla_changes.patch trunk/src/plugindata.h trunk/wscript
Added Paths: ----------- trunk/scintilla/PerLine.cxx trunk/scintilla/PerLine.h
Modified: trunk/ChangeLog =================================================================== --- trunk/ChangeLog 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/ChangeLog 2009-05-03 17:49:33 UTC (rev 3769) @@ -1,3 +1,9 @@ +2009-05-03 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de> + + * wscript, scintilla/*, scintilla/include/*, src/plugindata.h: + Update Scintilla to version 1.78. + + 2009-05-02 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
* src/printing.c:
Modified: trunk/scintilla/CellBuffer.cxx =================================================================== --- trunk/scintilla/CellBuffer.cxx 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/CellBuffer.cxx 2009-05-03 17:49:33 UTC (rev 3769) @@ -21,183 +21,31 @@ using namespace Scintilla; #endif
-MarkerHandleSet::MarkerHandleSet() { - root = 0; -} - -MarkerHandleSet::~MarkerHandleSet() { - MarkerHandleNumber *mhn = root; - while (mhn) { - MarkerHandleNumber *mhnToFree = mhn; - mhn = mhn->next; - delete mhnToFree; - } - root = 0; -} - -int MarkerHandleSet::Length() const { - int c = 0; - MarkerHandleNumber *mhn = root; - while (mhn) { - c++; - mhn = mhn->next; - } - return c; -} - -int MarkerHandleSet::NumberFromHandle(int handle) const { - MarkerHandleNumber *mhn = root; - while (mhn) { - if (mhn->handle == handle) { - return mhn->number; - } - mhn = mhn->next; - } - return - 1; -} - -int MarkerHandleSet::MarkValue() const { - unsigned int m = 0; - MarkerHandleNumber *mhn = root; - while (mhn) { - m |= (1 << mhn->number); - mhn = mhn->next; - } - return m; -} - -bool MarkerHandleSet::Contains(int handle) const { - MarkerHandleNumber *mhn = root; - while (mhn) { - if (mhn->handle == handle) { - return true; - } - mhn = mhn->next; - } - return false; -} - -bool MarkerHandleSet::InsertHandle(int handle, int markerNum) { - MarkerHandleNumber *mhn = new MarkerHandleNumber; - if (!mhn) - return false; - mhn->handle = handle; - mhn->number = markerNum; - mhn->next = root; - root = mhn; - return true; -} - -void MarkerHandleSet::RemoveHandle(int handle) { - MarkerHandleNumber **pmhn = &root; - while (*pmhn) { - MarkerHandleNumber *mhn = *pmhn; - if (mhn->handle == handle) { - *pmhn = mhn->next; - delete mhn; - return; - } - pmhn = &((*pmhn)->next); - } -} - -bool MarkerHandleSet::RemoveNumber(int markerNum) { - bool performedDeletion = false; - MarkerHandleNumber **pmhn = &root; - while (*pmhn) { - MarkerHandleNumber *mhn = *pmhn; - if (mhn->number == markerNum) { - *pmhn = mhn->next; - delete mhn; - performedDeletion = true; - } else { - pmhn = &((*pmhn)->next); - } - } - return performedDeletion; -} - -void MarkerHandleSet::CombineWith(MarkerHandleSet *other) { - MarkerHandleNumber **pmhn = &root; - while (*pmhn) { - pmhn = &((*pmhn)->next); - } - *pmhn = other->root; - other->root = 0; -} - LineVector::LineVector() : starts(256) { - handleCurrent = 1; - Init(); }
LineVector::~LineVector() { starts.DeleteAll(); - for (int line = 0; line < markers.Length(); line++) { - delete markers[line]; - markers[line] = 0; - } - markers.DeleteAll(); - levels.DeleteAll(); }
void LineVector::Init() { starts.DeleteAll(); - for (int line = 0; line < markers.Length(); line++) { - delete markers[line]; - markers[line] = 0; - } - markers.DeleteAll(); - levels.DeleteAll(); }
-void LineVector::ExpandLevels(int sizeNew) { - levels.InsertValue(levels.Length(), sizeNew - levels.Length(), SC_FOLDLEVELBASE); +void LineVector::SetPerLine(PerLine *pl) { + perLine = pl; }
-void LineVector::ClearLevels() { - levels.DeleteAll(); -} - -int LineVector::SetLevel(int line, int level) { - int prev = 0; - if ((line >= 0) && (line < Lines())) { - if (!levels.Length()) { - ExpandLevels(Lines() + 1); - } - prev = levels[line]; - if (prev != level) { - levels[line] = level; - } - } - return prev; -} - -int LineVector::GetLevel(int line) { - if (levels.Length() && (line >= 0) && (line < Lines())) { - return levels[line]; - } else { - return SC_FOLDLEVELBASE; - } -} - void LineVector::InsertText(int line, int delta) { starts.InsertText(line, delta); }
void LineVector::InsertLine(int line, int position) { starts.InsertPartition(line, position); - if (markers.Length()) { - markers.Insert(line, 0); + if (perLine) { + perLine->InsertLine(line); } - if (levels.Length()) { - int level = SC_FOLDLEVELBASE; - if ((line > 0) && (line < Lines())) { - level = levels[line-1] & ~SC_FOLDLEVELWHITEFLAG; - } - levels.InsertValue(line, 1, level); - } }
void LineVector::SetLineStart(int line, int position) { @@ -206,103 +54,15 @@
void LineVector::RemoveLine(int line) { starts.RemovePartition(line); - // Retain the markers from the deleted line by oring them into the previous line - if (markers.Length()) { - if (line > 0) { - MergeMarkers(line - 1); - } - markers.Delete(line); + if (perLine) { + perLine->RemoveLine(line); } - if (levels.Length()) { - // Move up following lines but merge header flag from this line - // to line before to avoid a temporary disappearence causing expansion. - int firstHeader = levels[line] & SC_FOLDLEVELHEADERFLAG; - levels.Delete(line); - if (line > 0) - levels[line-1] |= firstHeader; - } }
int LineVector::LineFromPosition(int pos) { return starts.PartitionFromPosition(pos); }
-int LineVector::MarkValue(int line) { - if (markers.Length() && markers[line]) - return markers[line]->MarkValue(); - else - return 0; -} - -int LineVector::AddMark(int line, int markerNum) { - handleCurrent++; - if (!markers.Length()) { - // No existing markers so allocate one element per line - markers.InsertValue(0, Lines(), 0); - } - if (!markers[line]) { - // Need new structure to hold marker handle - markers[line] = new MarkerHandleSet(); - if (!markers[line]) - return - 1; - } - markers[line]->InsertHandle(handleCurrent, markerNum); - - return handleCurrent; -} - -void LineVector::MergeMarkers(int pos) { - if (markers[pos + 1] != NULL) { - if (markers[pos] == NULL) - markers[pos] = new MarkerHandleSet; - markers[pos]->CombineWith(markers[pos + 1]); - delete markers[pos + 1]; - markers[pos + 1] = NULL; - } -} - -void LineVector::DeleteMark(int line, int markerNum, bool all) { - if (markers.Length() && markers[line]) { - if (markerNum == -1) { - delete markers[line]; - markers[line] = NULL; - } else { - bool performedDeletion = markers[line]->RemoveNumber(markerNum); - while (all && performedDeletion) { - performedDeletion = markers[line]->RemoveNumber(markerNum); - } - if (markers[line]->Length() == 0) { - delete markers[line]; - markers[line] = NULL; - } - } - } -} - -void LineVector::DeleteMarkFromHandle(int markerHandle) { - int line = LineFromHandle(markerHandle); - if (line >= 0) { - markers[line]->RemoveHandle(markerHandle); - if (markers[line]->Length() == 0) { - delete markers[line]; - markers[line] = NULL; - } - } -} - -int LineVector::LineFromHandle(int markerHandle) { - if (markers.Length()) { - for (int line = 0; line < Lines(); line++) { - if (markers[line]) { - if (markers[line]->Contains(markerHandle)) { - return line; - } - } - } - } - return -1; -} - Action::Action() { at = startAction; position = 0; @@ -398,7 +158,7 @@ }
void UndoHistory::AppendAction(actionType at, int position, char *data, int lengthData, - bool &startSequence) { + bool &startSequence, bool mayCoalesce) { EnsureUndoRoom(); //Platform::DebugPrintf("%% %d action %d %d %d\n", at, position, lengthData, currentAction); //Platform::DebugPrintf("^ %d action %d %d\n", actions[currentAction - 1].at, @@ -410,25 +170,35 @@ if (currentAction >= 1) { if (0 == undoSequenceDepth) { // Top level actions may not always be coalesced - Action &actPrevious = actions[currentAction - 1]; + int targetAct = -1; + const Action *actPrevious = &(actions[currentAction + targetAct]); + // Container actions may forward the coalesce state of Scintilla Actions. + while ((actPrevious->at == containerAction) && actPrevious->mayCoalesce) { + targetAct--; + actPrevious = &(actions[currentAction + targetAct]); + } // See if current action can be coalesced into previous action // Will work if both are inserts or deletes and position is same - if (at != actPrevious.at) { + if (currentAction == savePoint) { currentAction++; - } else if (currentAction == savePoint) { + } else if (!actions[currentAction].mayCoalesce) { + // Not allowed to coalesce if this set currentAction++; + } else if (!mayCoalesce || !actPrevious->mayCoalesce) { + currentAction++; + } else if (at == containerAction || actions[currentAction].at == containerAction) { + ; // A coalescible containerAction + } else if ((at != actPrevious->at) && (actPrevious->at != startAction)) { + currentAction++; } else if ((at == insertAction) && - (position != (actPrevious.position + actPrevious.lenData))) { + (position != (actPrevious->position + actPrevious->lenData))) { // Insertions must be immediately after to coalesce currentAction++; - } else if (!actions[currentAction].mayCoalesce) { - // Not allowed to coalesce if this set - currentAction++; } else if (at == removeAction) { if ((lengthData == 1) || (lengthData == 2)){ - if ((position + lengthData) == actPrevious.position) { + if ((position + lengthData) == actPrevious->position) { ; // Backspace -> OK - } else if (position == actPrevious.position) { + } else if (position == actPrevious->position) { ; // Delete -> OK } else { // Removals must be at same position to coalesce @@ -451,7 +221,7 @@ currentAction++; } startSequence = oldCurrentAction != currentAction; - actions[currentAction].Create(at, position, data, lengthData); + actions[currentAction].Create(at, position, data, lengthData, mayCoalesce); currentAction++; actions[currentAction].Create(startAction); maxAction = currentAction; @@ -666,6 +436,10 @@ style.ReAllocate(newSize); }
+void CellBuffer::SetPerLine(PerLine *pl) { + lv.SetPerLine(pl); +} + int CellBuffer::Lines() const { return lv.Lines(); } @@ -695,54 +469,14 @@ return uh.IsSavePoint(); }
-int CellBuffer::AddMark(int line, int markerNum) { - if ((line >= 0) && (line < Lines())) { - return lv.AddMark(line, markerNum); - } - return - 1; -} - -void CellBuffer::DeleteMark(int line, int markerNum) { - if ((line >= 0) && (line < Lines())) { - lv.DeleteMark(line, markerNum, false); - } -} - -void CellBuffer::DeleteMarkFromHandle(int markerHandle) { - lv.DeleteMarkFromHandle(markerHandle); -} - -int CellBuffer::GetMark(int line) { - if ((line >= 0) && (line < Lines())) - return lv.MarkValue(line); - return 0; -} - -void CellBuffer::DeleteAllMarks(int markerNum) { - for (int line = 0; line < Lines(); line++) { - lv.DeleteMark(line, markerNum, true); - } -} - -int CellBuffer::LineFromHandle(int markerHandle) { - return lv.LineFromHandle(markerHandle); -} - // Without undo
void CellBuffer::InsertLine(int line, int position) { lv.InsertLine(line, position); - if (lineStates.Length()) { - lineStates.EnsureLength(line); - lineStates.Insert(line, 0); - } }
void CellBuffer::RemoveLine(int line) { lv.RemoveLine(line); - if (lineStates.Length() > line) { - lineStates.Delete(line); - } }
void CellBuffer::BasicInsertString(int position, const char *s, int insertLength) { @@ -862,6 +596,11 @@ uh.EndUndoAction(); }
+void CellBuffer::AddUndoAction(int token, bool mayCoalesce) { + bool startSequence; + uh.AppendAction(containerAction, token, 0, 0, startSequence, mayCoalesce); +} + void CellBuffer::DeleteUndoHistory() { uh.DeleteUndoHistory(); } @@ -910,30 +649,3 @@ uh.CompletedRedoStep(); }
-int CellBuffer::SetLineState(int line, int state) { - lineStates.EnsureLength(line + 1); - int stateOld = lineStates[line]; - lineStates[line] = state; - return stateOld; -} - -int CellBuffer::GetLineState(int line) { - lineStates.EnsureLength(line + 1); - return lineStates[line]; -} - -int CellBuffer::GetMaxLineState() { - return lineStates.Length(); -} - -int CellBuffer::SetLevel(int line, int level) { - return lv.SetLevel(line, level); -} - -int CellBuffer::GetLevel(int line) { - return lv.GetLevel(line); -} - -void CellBuffer::ClearLevels() { - lv.ClearLevels(); -}
Modified: trunk/scintilla/CellBuffer.h =================================================================== --- trunk/scintilla/CellBuffer.h 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/CellBuffer.h 2009-05-03 17:49:33 UTC (rev 3769) @@ -12,33 +12,12 @@ namespace Scintilla { #endif
-/** - * This holds the marker identifier and the marker type to display. - * MarkerHandleNumbers are members of lists. - */ -struct MarkerHandleNumber { - int handle; - int number; - MarkerHandleNumber *next; -}; - -/** - * A marker handle set contains any number of MarkerHandleNumbers. - */ -class MarkerHandleSet { - MarkerHandleNumber *root; - +// Interface to per-line data that wants to see each line insertion and deletion +class PerLine { public: - MarkerHandleSet(); - ~MarkerHandleSet(); - int Length() const; - int NumberFromHandle(int handle) const; - int MarkValue() const; ///< Bit set of marker numbers. - bool Contains(int handle) const; - bool InsertHandle(int handle, int markerNum); - void RemoveHandle(int handle); - bool RemoveNumber(int markerNum); - void CombineWith(MarkerHandleSet *other); + virtual ~PerLine() {} + virtual void InsertLine(int)=0; + virtual void RemoveLine(int)=0; };
/** @@ -47,22 +26,15 @@ class LineVector {
Partitioning starts; - SplitVector<MarkerHandleSet *> markers; - SplitVector<int> levels; - /// Handles are allocated sequentially and should never have to be reused as 32 bit ints are very big. - int handleCurrent; + PerLine *perLine;
public:
LineVector(); ~LineVector(); void Init(); + void SetPerLine(PerLine *pl);
- void ExpandLevels(int sizeNew=-1); - void ClearLevels(); - int SetLevel(int line, int level); - int GetLevel(int line); - void InsertText(int line, int delta); void InsertLine(int line, int position); void SetLineStart(int line, int position); @@ -81,9 +53,18 @@ void DeleteMark(int line, int markerNum, bool all); void DeleteMarkFromHandle(int markerHandle); int LineFromHandle(int markerHandle); + + void ClearLevels(); + int SetLevel(int line, int level); + int GetLevel(int line); + + int SetLineState(int line, int state); + int GetLineState(int line); + int GetMaxLineState(); + };
-enum actionType { insertAction, removeAction, startAction }; +enum actionType { insertAction, removeAction, startAction, containerAction };
/** * Actions are used to store all the information required to perform one undo/redo step. @@ -120,7 +101,7 @@ UndoHistory(); ~UndoHistory();
- void AppendAction(actionType at, int position, char *data, int length, bool &startSequence); + void AppendAction(actionType at, int position, char *data, int length, bool &startSequence, bool mayCoalesce=true);
void BeginUndoAction(); void EndUndoAction(); @@ -160,8 +141,6 @@
LineVector lv;
- SplitVector<int> lineStates; - public:
CellBuffer(); @@ -175,6 +154,7 @@
int Length() const; void Allocate(int newSize); + void SetPerLine(PerLine *pl); int Lines() const; int LineStart(int line) const; int LineFromPosition(int pos) { return lv.LineFromPosition(pos); } @@ -197,14 +177,6 @@ void SetSavePoint(); bool IsSavePoint();
- /// Line marker functions - int AddMark(int line, int markerNum); - void DeleteMark(int line, int markerNum); - void DeleteMarkFromHandle(int markerHandle); - int GetMark(int line); - void DeleteAllMarks(int markerNum); - int LineFromHandle(int markerHandle); - /// Actions without undo void BasicInsertString(int position, const char *s, int insertLength); void BasicDeleteChars(int position, int deleteLength); @@ -213,6 +185,7 @@ bool IsCollectingUndo(); void BeginUndoAction(); void EndUndoAction(); + void AddUndoAction(int token, bool mayCoalesce); void DeleteUndoHistory();
/// To perform an undo, StartUndo is called to retrieve the number of steps, then UndoStep is @@ -225,14 +198,6 @@ int StartRedo(); const Action &GetRedoStep() const; void PerformRedoStep(); - - int SetLineState(int line, int state); - int GetLineState(int line); - int GetMaxLineState(); - - int SetLevel(int line, int level); - int GetLevel(int line); - void ClearLevels(); };
#ifdef SCI_NAMESPACE
Modified: trunk/scintilla/Document.cxx =================================================================== --- trunk/scintilla/Document.cxx 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/Document.cxx 2009-05-03 17:49:33 UTC (rev 3769) @@ -17,6 +17,7 @@ #include "Partitioning.h" #include "RunStyles.h" #include "CellBuffer.h" +#include "PerLine.h" #include "CharClassify.h" #include "Decoration.h" #include "Document.h" @@ -74,6 +75,14 @@
matchesValid = false; regex = 0; + + perLineData[ldMarkers] = new LineMarkers(); + perLineData[ldLevels] = new LineLevels(); + perLineData[ldState] = new LineState(); + perLineData[ldMargin] = new LineAnnotation(); + perLineData[ldAnnotation] = new LineAnnotation(); + + cb.SetPerLine(this); }
Document::~Document() { @@ -81,12 +90,30 @@ watchers[i].watcher->NotifyDeleted(this, watchers[i].userData); } delete []watchers; + for (int j=0; j<ldSize; j++) { + delete perLineData[j]; + perLineData[j] = 0; + } watchers = 0; lenWatchers = 0; delete regex; regex = 0; }
+void Document::InsertLine(int line) { + for (int j=0; j<ldSize; j++) { + if (perLineData[j]) + perLineData[j]->InsertLine(line); + } +} + +void Document::RemoveLine(int line) { + for (int j=0; j<ldSize; j++) { + if (perLineData[j]) + perLineData[j]->RemoveLine(line); + } +} + // Increase reference count and return its previous value. int Document::AddRef() { return refCount++; @@ -106,42 +133,58 @@ NotifySavePoint(true); }
+int Document::GetMark(int line) { + return static_cast<LineMarkers*>(perLineData[ldMarkers])->MarkValue(line); +} + int Document::AddMark(int line, int markerNum) { - int prev = cb.AddMark(line, markerNum); - DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line); - NotifyModified(mh); - return prev; + if (line <= LinesTotal()) { + int prev = static_cast<LineMarkers*>(perLineData[ldMarkers])-> + AddMark(line, markerNum, LinesTotal()); + DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line); + NotifyModified(mh); + return prev; + } else { + return 0; + } }
void Document::AddMarkSet(int line, int valueSet) { unsigned int m = valueSet; for (int i = 0; m; i++, m >>= 1) if (m & 1) - cb.AddMark(line, i); + static_cast<LineMarkers*>(perLineData[ldMarkers])-> + AddMark(line, i, LinesTotal()); DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line); NotifyModified(mh); }
void Document::DeleteMark(int line, int markerNum) { - cb.DeleteMark(line, markerNum); + static_cast<LineMarkers*>(perLineData[ldMarkers])->DeleteMark(line, markerNum, false); DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line); NotifyModified(mh); }
void Document::DeleteMarkFromHandle(int markerHandle) { - cb.DeleteMarkFromHandle(markerHandle); + static_cast<LineMarkers*>(perLineData[ldMarkers])->DeleteMarkFromHandle(markerHandle); DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0); mh.line = -1; NotifyModified(mh); }
void Document::DeleteAllMarks(int markerNum) { - cb.DeleteAllMarks(markerNum); + for (int line = 0; line < LinesTotal(); line++) { + static_cast<LineMarkers*>(perLineData[ldMarkers])->DeleteMark(line, markerNum, true); + } DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0); mh.line = -1; NotifyModified(mh); }
+int Document::LineFromHandle(int markerHandle) { + return static_cast<LineMarkers*>(perLineData[ldMarkers])->LineFromHandle(markerHandle); +} + int Document::LineStart(int line) const { return cb.LineStart(line); } @@ -181,7 +224,7 @@ }
int Document::SetLevel(int line, int level) { - int prev = cb.SetLevel(line, level); + int prev = static_cast<LineLevels*>(perLineData[ldLevels])->SetLevel(line, level, LinesTotal()); if (prev != level) { DocModification mh(SC_MOD_CHANGEFOLD | SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line); @@ -192,6 +235,14 @@ return prev; }
+int Document::GetLevel(int line) { + return static_cast<LineLevels*>(perLineData[ldLevels])->GetLevel(line); +} + +void Document::ClearLevels() { + static_cast<LineLevels*>(perLineData[ldLevels])->ClearLevels(); +} + static bool IsSubordinate(int levelStart, int levelTry) { if (levelTry & SC_FOLDLEVELWHITEFLAG) return true; @@ -503,21 +554,27 @@ if (action.at == removeAction) { NotifyModified(DocModification( SC_MOD_BEFOREINSERT | SC_PERFORMED_UNDO, action)); + } else if (action.at == containerAction) { + DocModification dm(SC_MOD_CONTAINER | SC_PERFORMED_UNDO); + dm.token = action.position; + NotifyModified(dm); } else { NotifyModified(DocModification( SC_MOD_BEFOREDELETE | SC_PERFORMED_UNDO, action)); } cb.PerformUndoStep(); int cellPosition = action.position; - ModifiedAt(cellPosition); - newPos = cellPosition; + if (action.at != containerAction) { + ModifiedAt(cellPosition); + newPos = cellPosition; + }
int modFlags = SC_PERFORMED_UNDO; // With undo, an insertion action becomes a deletion notification if (action.at == removeAction) { newPos += action.lenData; modFlags |= SC_MOD_INSERTTEXT; - } else { + } else if (action.at == insertAction) { modFlags |= SC_MOD_DELETETEXT; } if (steps > 1) @@ -558,19 +615,25 @@ if (action.at == insertAction) { NotifyModified(DocModification( SC_MOD_BEFOREINSERT | SC_PERFORMED_REDO, action)); + } else if (action.at == containerAction) { + DocModification dm(SC_MOD_CONTAINER | SC_PERFORMED_REDO); + dm.token = action.position; + NotifyModified(dm); } else { NotifyModified(DocModification( SC_MOD_BEFOREDELETE | SC_PERFORMED_REDO, action)); } cb.PerformRedoStep(); - ModifiedAt(action.position); - newPos = action.position; + if (action.at != containerAction) { + ModifiedAt(action.position); + newPos = action.position; + }
int modFlags = SC_PERFORMED_REDO; if (action.at == insertAction) { newPos += action.lenData; modFlags |= SC_MOD_INSERTTEXT; - } else { + } else if (action.at == removeAction) { modFlags |= SC_MOD_DELETETEXT; } if (steps > 1) @@ -1059,8 +1122,8 @@ } if (found) { if ((!word && !wordStart) || - word && IsWordAt(pos, pos + lengthFind) || - wordStart && IsWordStartAt(pos)) + (word && IsWordAt(pos, pos + lengthFind)) || + (wordStart && IsWordStartAt(pos))) return pos; } } @@ -1075,8 +1138,8 @@ } if (found) { if ((!word && !wordStart) || - word && IsWordAt(pos, pos + lengthFind) || - wordStart && IsWordStartAt(pos)) + (word && IsWordAt(pos, pos + lengthFind)) || + (wordStart && IsWordStartAt(pos))) return pos; } } @@ -1155,7 +1218,7 @@ } }
-bool Document::SetStyles(int length, char *styles) { +bool Document::SetStyles(int length, const char *styles) { if (enteredStyling != 0) { return false; } else { @@ -1194,7 +1257,7 @@ }
int Document::SetLineState(int line, int state) { - int statePrevious = cb.SetLineState(line, state); + int statePrevious = static_cast<LineState*>(perLineData[ldState])->SetLineState(line, state); if (state != statePrevious) { DocModification mh(SC_MOD_CHANGELINESTATE, 0, 0, 0, 0, line); NotifyModified(mh); @@ -1202,6 +1265,89 @@ return statePrevious; }
+int Document::GetLineState(int line) { + return static_cast<LineState*>(perLineData[ldState])->GetLineState(line); +} + +int Document::GetMaxLineState() { + return static_cast<LineState*>(perLineData[ldState])->GetMaxLineState(); +} + +StyledText Document::MarginStyledText(int line) { + LineAnnotation *pla = static_cast<LineAnnotation*>(perLineData[ldMargin]); + return StyledText(pla->Length(line), pla->Text(line), + pla->MultipleStyles(line), pla->Style(line), pla->Styles(line)); +} + +void Document::MarginSetText(int line, const char *text) { + static_cast<LineAnnotation*>(perLineData[ldMargin])->SetText(line, text); + DocModification mh(SC_MOD_CHANGEMARGIN, LineStart(line), 0, 0, 0, line); + NotifyModified(mh); +} + +void Document::MarginSetStyle(int line, int style) { + static_cast<LineAnnotation*>(perLineData[ldMargin])->SetStyle(line, style); +} + +void Document::MarginSetStyles(int line, const unsigned char *styles) { + static_cast<LineAnnotation*>(perLineData[ldMargin])->SetStyles(line, styles); +} + +int Document::MarginLength(int line) const { + return static_cast<LineAnnotation*>(perLineData[ldMargin])->Length(line); +} + +void Document::MarginClearAll() { + int maxEditorLine = LinesTotal(); + for (int l=0;l<maxEditorLine;l++) + MarginSetText(l, 0); + // Free remaining data + static_cast<LineAnnotation*>(perLineData[ldMargin])->ClearAll(); +} + +bool Document::AnnotationAny() const { + return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->AnySet(); +} + +StyledText Document::AnnotationStyledText(int line) { + LineAnnotation *pla = static_cast<LineAnnotation*>(perLineData[ldAnnotation]); + return StyledText(pla->Length(line), pla->Text(line), + pla->MultipleStyles(line), pla->Style(line), pla->Styles(line)); +} + +void Document::AnnotationSetText(int line, const char *text) { + const int linesBefore = AnnotationLines(line); + static_cast<LineAnnotation*>(perLineData[ldAnnotation])->SetText(line, text); + const int linesAfter = AnnotationLines(line); + DocModification mh(SC_MOD_CHANGEANNOTATION, LineStart(line), 0, 0, 0, line); + mh.annotationLinesAdded = linesAfter - linesBefore; + NotifyModified(mh); +} + +void Document::AnnotationSetStyle(int line, int style) { + static_cast<LineAnnotation*>(perLineData[ldAnnotation])->SetStyle(line, style); +} + +void Document::AnnotationSetStyles(int line, const unsigned char *styles) { + static_cast<LineAnnotation*>(perLineData[ldAnnotation])->SetStyles(line, styles); +} + +int Document::AnnotationLength(int line) const { + return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->Length(line); +} + +int Document::AnnotationLines(int line) const { + return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->Lines(line); +} + +void Document::AnnotationClearAll() { + int maxEditorLine = LinesTotal(); + for (int l=0;l<maxEditorLine;l++) + AnnotationSetText(l, 0); + // Free remaining data + static_cast<LineAnnotation*>(perLineData[ldAnnotation])->ClearAll(); +} + void Document::IncrementStyleClock() { styleClock = (styleClock + 1) % 0x100000; } @@ -1657,8 +1803,18 @@
#ifndef SCI_OWNREGEX
+#ifdef SCI_NAMESPACE + +RegexSearchBase *Scintilla::CreateRegexSearch(CharClassify *charClassTable) { + return new BuiltinRegex(charClassTable); +} + +#else + RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable) { return new BuiltinRegex(charClassTable); }
#endif + +#endif
Modified: trunk/scintilla/Document.h =================================================================== --- trunk/scintilla/Document.h 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/Document.h 2009-05-03 17:49:33 UTC (rev 3769) @@ -93,9 +93,31 @@ /// Factory function for RegexSearchBase extern RegexSearchBase* CreateRegexSearch(CharClassify *charClassTable);
+struct StyledText { + size_t length; + const char *text; + bool multipleStyles; + size_t style; + const unsigned char *styles; + StyledText( size_t length_, const char *text_, bool multipleStyles_, int style_, const unsigned char *styles_) : + length(length_), text(text_), multipleStyles(multipleStyles_), style(style_), styles(styles_) { + } + // Return number of bytes from start to before '\n' or end of text. + // Return 1 when start is outside text + size_t LineLength(size_t start) const { + size_t cur = start; + while ((cur < length) && (text[cur] != '\n')) + cur++; + return cur-start; + } + size_t StyleAt(size_t i) const { + return multipleStyles ? styles[i] : style; + } +}; + /** */ -class Document { +class Document : PerLine {
public: /** Used to pair watcher pointer with user data. */ @@ -110,7 +132,6 @@ };
enum charClassification { ccSpace, ccNewLine, ccWord, ccPunctuation }; - private: int refCount; CellBuffer cb; @@ -125,6 +146,10 @@ WatcherWithUserData *watchers; int lenWatchers;
+ // ldSize is not real data - it is for dimensions and loops + enum lineData { ldMarkers, ldLevels, ldState, ldMargin, ldAnnotation, ldSize }; + PerLine *perLineData[ldSize]; + bool matchesValid; RegexSearchBase* regex;
@@ -150,6 +175,9 @@ int AddRef(); int Release();
+ virtual void InsertLine(int line); + virtual void RemoveLine(int line); + int LineFromPosition(int pos); int ClampPositionIntoDocument(int pos); bool IsCrLf(int pos); @@ -173,6 +201,7 @@ bool IsCollectingUndo() { return cb.IsCollectingUndo(); } void BeginUndoAction() { cb.BeginUndoAction(); } void EndUndoAction() { cb.EndUndoAction(); } + void AddUndoAction(int token, bool mayCoalesce) { cb.AddUndoAction(token, mayCoalesce); } void SetSavePoint(); bool IsSavePoint() { return cb.IsSavePoint(); } const char *BufferPointer() { return cb.BufferPointer(); } @@ -199,21 +228,21 @@ cb.GetCharRange(buffer, position, lengthRetrieve); } char StyleAt(int position) { return cb.StyleAt(position); } - int GetMark(int line) { return cb.GetMark(line); } + int GetMark(int line); int AddMark(int line, int markerNum); void AddMarkSet(int line, int valueSet); void DeleteMark(int line, int markerNum); void DeleteMarkFromHandle(int markerHandle); void DeleteAllMarks(int markerNum); - int LineFromHandle(int markerHandle) { return cb.LineFromHandle(markerHandle); } + int LineFromHandle(int markerHandle); int LineStart(int line) const; int LineEnd(int line) const; int LineEndPosition(int position); int VCHomePosition(int position);
int SetLevel(int line, int level); - int GetLevel(int line) { return cb.GetLevel(line); } - void ClearLevels() { cb.ClearLevels(); } + int GetLevel(int line); + void ClearLevels(); int GetLastChild(int lineParent, int level=-1); int GetFoldParent(int line);
@@ -236,7 +265,7 @@ void SetStylingBits(int bits); void StartStyling(int position, char mask); bool SetStyleFor(int length, char style); - bool SetStyles(int length, char *styles); + bool SetStyles(int length, const char *styles); int GetEndStyled() { return endStyled; } void EnsureStyledTo(int pos); int GetStyleClock() { return styleClock; } @@ -244,9 +273,25 @@ void DecorationFillRange(int position, int value, int fillLength);
int SetLineState(int line, int state); - int GetLineState(int line) { return cb.GetLineState(line); } - int GetMaxLineState() { return cb.GetMaxLineState(); } + int GetLineState(int line); + int GetMaxLineState();
+ StyledText MarginStyledText(int line); + void MarginSetStyle(int line, int style); + void MarginSetStyles(int line, const unsigned char *styles); + void MarginSetText(int line, const char *text); + int MarginLength(int line) const; + void MarginClearAll(); + + bool AnnotationAny() const; + StyledText AnnotationStyledText(int line); + void AnnotationSetText(int line, const char *text); + void AnnotationSetStyle(int line, int style); + void AnnotationSetStyles(int line, const unsigned char *styles); + int AnnotationLength(int line) const; + int AnnotationLines(int line) const; + void AnnotationClearAll(); + bool AddWatcher(DocWatcher *watcher, void *userData); bool RemoveWatcher(DocWatcher *watcher, void *userData); const WatcherWithUserData *GetWatchers() const { return watchers; } @@ -288,6 +333,8 @@ int line; int foldLevelNow; int foldLevelPrev; + int annotationLinesAdded; + int token;
DocModification(int modificationType_, int position_=0, int length_=0, int linesAdded_=0, const char *text_=0, int line_=0) : @@ -298,7 +345,9 @@ text(text_), line(line_), foldLevelNow(0), - foldLevelPrev(0) {} + foldLevelPrev(0), + annotationLinesAdded(0), + token(0) {}
DocModification(int modificationType_, const Action &act, int linesAdded_=0) : modificationType(modificationType_), @@ -308,7 +357,9 @@ text(act.data), line(0), foldLevelNow(0), - foldLevelPrev(0) {} + foldLevelPrev(0), + annotationLinesAdded(0), + token(0) {} };
/**
Modified: trunk/scintilla/Editor.cxx =================================================================== --- trunk/scintilla/Editor.cxx 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/Editor.cxx 2009-05-03 17:49:33 UTC (rev 3769) @@ -1277,7 +1277,8 @@ LayoutLine(lineToWrap, surface, vs, ll, wrapWidth); linesWrapped = ll->lines; } - return cs.SetHeight(lineToWrap, linesWrapped); + return cs.SetHeight(lineToWrap, linesWrapped + + (vs.annotationVisible ? pdoc->AnnotationLines(lineToWrap) : 0)); }
// Check if wrapping needed and perform any needed wrapping. @@ -1315,7 +1316,8 @@ if (wrapWidth != LineLayout::wrapWidthInfinite) { wrapWidth = LineLayout::wrapWidthInfinite; for (int lineDoc = 0; lineDoc < pdoc->LinesTotal(); lineDoc++) { - cs.SetHeight(lineDoc, 1); + cs.SetHeight(lineDoc, 1 + + (vs.annotationVisible ? pdoc->AnnotationLines(lineDoc) : 0)); } wrapOccurred = true; } @@ -1457,6 +1459,84 @@ return static_cast<int>(strlen(s)); }
+bool ValidStyledText(ViewStyle &vs, size_t styleOffset, const StyledText &st) { + if (st.multipleStyles) { + for (size_t iStyle=0;iStyle<st.length; iStyle++) { + if (!vs.ValidStyle(styleOffset + st.styles[iStyle])) + return false; + } + } else { + if (!vs.ValidStyle(styleOffset + st.style)) + return false; + } + return true; +} + +static int WidthStyledText(Surface *surface, ViewStyle &vs, int styleOffset, + const char *text, const unsigned char *styles, size_t len) { + int width = 0; + size_t start = 0; + while (start < len) { + size_t style = styles[start]; + size_t endSegment = start; + while ((endSegment+1 < len) && (static_cast<size_t>(styles[endSegment+1]) == style)) + endSegment++; + width += surface->WidthText(vs.styles[style+styleOffset].font, text + start, endSegment - start + 1); + start = endSegment + 1; + } + return width; +} + +static int WidestLineWidth(Surface *surface, ViewStyle &vs, int styleOffset, const StyledText &st) { + int widthMax = 0; + size_t start = 0; + while (start < st.length) { + size_t lenLine = st.LineLength(start); + int widthSubLine; + if (st.multipleStyles) { + widthSubLine = WidthStyledText(surface, vs, styleOffset, st.text + start, st.styles + start, lenLine); + } else { + widthSubLine = surface->WidthText(vs.styles[styleOffset + st.style].font, st.text + start, lenLine); + } + if (widthSubLine > widthMax) + widthMax = widthSubLine; + start += lenLine + 1; + } + return widthMax; +} + +void DrawStyledText(Surface *surface, ViewStyle &vs, int styleOffset, PRectangle rcText, int ascent, + const StyledText &st, size_t start, size_t length) { + + if (st.multipleStyles) { + int x = rcText.left; + size_t i = 0; + while (i < length) { + size_t end = i; + int style = st.styles[i + start]; + while (end < length-1 && st.styles[start+end+1] == style) + end++; + style += styleOffset; + int width = surface->WidthText(vs.styles[style].font, st.text + start + i, end - i + 1); + PRectangle rcSegment = rcText; + rcSegment.left = x; + rcSegment.right = x + width + 1; + surface->DrawTextNoClip(rcSegment, vs.styles[style].font, + ascent, st.text + start + i, end - i + 1, + vs.styles[style].fore.allocated, + vs.styles[style].back.allocated); + x += width; + i = end + 1; + } + } else { + int style = st.style + styleOffset; + surface->DrawTextNoClip(rcText, vs.styles[style].font, + rcText.top + vs.maxAscent, st.text, st.length, + vs.styles[style].fore.allocated, + vs.styles[style].back.allocated); + } +} + void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { if (vs.fixedColumnWidth == 0) return; @@ -1638,6 +1718,20 @@ rcNumber.top + vs.maxAscent, number, istrlen(number), vs.styles[STYLE_LINENUMBER].fore.allocated, vs.styles[STYLE_LINENUMBER].back.allocated); + } else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) { + if (firstSubLine) { + const StyledText stMargin = pdoc->MarginStyledText(lineDoc); + if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) { + surface->FillRectangle(rcMarker, + vs.styles[stMargin.StyleAt(0)+vs.marginStyleOffset].back.allocated); + if (vs.ms[margin].style == SC_MARGIN_RTEXT) { + int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, stMargin); + rcMarker.left = rcMarker.right - width - 3; + } + DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker, rcMarker.top + vs.maxAscent, + stMargin, 0, stMargin.length); + } + } }
if (marks) { @@ -2221,6 +2315,58 @@ textBack, textFore); }
+void Editor::DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart, + PRectangle rcLine, LineLayout *ll, int subLine) { + int indent = pdoc->GetLineIndentation(line) * vsDraw.spaceWidth; + PRectangle rcSegment = rcLine; + int annotationLine = subLine - ll->lines; + const StyledText stAnnotation = pdoc->AnnotationStyledText(line); + if (stAnnotation.text && ValidStyledText(vsDraw, vsDraw.annotationStyleOffset, stAnnotation)) { + surface->FillRectangle(rcSegment, vsDraw.styles[0].back.allocated); + if (vs.annotationVisible == ANNOTATION_BOXED) { + // Only care about calculating width if need to draw box + int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation); + widthAnnotation += vsDraw.spaceWidth * 2; // Margins + rcSegment.left = xStart + indent; + rcSegment.right = rcSegment.left + widthAnnotation; + surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore.allocated); + } else { + rcSegment.left = xStart; + } + const int annotationLines = pdoc->AnnotationLines(line); + size_t start = 0; + size_t lengthAnnotation = stAnnotation.LineLength(start); + int lineInAnnotation = 0; + while ((lineInAnnotation < annotationLine) && (start < stAnnotation.length)) { + start += lengthAnnotation + 1; + lengthAnnotation = stAnnotation.LineLength(start); + lineInAnnotation++; + } + PRectangle rcText = rcSegment; + if (vs.annotationVisible == ANNOTATION_BOXED) { + surface->FillRectangle(rcText, + vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back.allocated); + rcText.left += vsDraw.spaceWidth; + } + DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText, rcText.top + vsDraw.maxAscent, + stAnnotation, start, lengthAnnotation); + if (vs.annotationVisible == ANNOTATION_BOXED) { + surface->MoveTo(rcSegment.left, rcSegment.top); + surface->LineTo(rcSegment.left, rcSegment.bottom); + surface->MoveTo(rcSegment.right, rcSegment.top); + surface->LineTo(rcSegment.right, rcSegment.bottom); + if (subLine == ll->lines){ + surface->MoveTo(rcSegment.left, rcSegment.top); + surface->LineTo(rcSegment.right, rcSegment.top); + } + if (subLine == ll->lines+annotationLines-1) { + surface->MoveTo(rcSegment.left, rcSegment.bottom - 1); + surface->LineTo(rcSegment.right, rcSegment.bottom - 1); + } + } + } +} + void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart, PRectangle rcLine, LineLayout *ll, int subLine) {
@@ -2280,6 +2426,10 @@
int startseg = ll->LineStart(subLine); int subLineStart = ll->positions[startseg]; + if (subLine >= ll->lines) { + DrawAnnotation(surface, vsDraw, line, xStart, rcLine, ll, subLine); + return; // No further drawing + } int lineStart = 0; int lineEnd = 0; if (subLine < ll->lines) { @@ -2693,9 +2843,16 @@ }
// We now know what to draw, update the caret drawing rectangle - rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[ll->LineStart(subLine)] + xStart; - rcCaret.right = ll->positions[offsetFirstChar+numCharsToDraw] - ll->positions[ll->LineStart(subLine)] + xStart; + rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[lineStart] + xStart; + rcCaret.right = ll->positions[offsetFirstChar+numCharsToDraw] - ll->positions[lineStart] + xStart;
+ // Adjust caret position to take into account any word wrapping symbols. + if ((actualWrapVisualStartIndent != 0) && (lineStart != 0)) { + int wordWrapCharWidth = actualWrapVisualStartIndent * vs.aveCharWidth; + rcCaret.left += wordWrapCharWidth; + rcCaret.right += wordWrapCharWidth; + } + // This character is where the caret block is, we override the colours // (inversed) for drawing the caret here. int styleMain = ll->styles[offsetFirstChar]; @@ -2793,7 +2950,7 @@ //Platform::DebugPrintf("Paint lines = %d .. %d\n", topLine + screenLinePaintFirst, lineStyleLast); int endPosPaint = pdoc->Length(); if (lineStyleLast < cs.LinesDisplayed()) - endPosPaint = pdoc->LineStart(cs.DocFromDisplay(lineStyleLast + 1)); + endPosPaint = pdoc->LineStart(cs.DocFromDisplay(lineStyleLast) + 1);
int xStart = vs.fixedColumnWidth - xOffset; int ypos = 0; @@ -2945,7 +3102,9 @@ ll->RestoreBracesHighlight(rangeLine, braces);
bool expanded = cs.GetExpanded(lineDoc); +#ifdef INCLUDE_DEPRECATED_FEATURES if ((foldFlags & SC_FOLDFLAG_BOX) == 0) { +#endif // Paint the line above the fold if ((expanded && (foldFlags & SC_FOLDFLAG_LINEBEFORE_EXPANDED)) || @@ -2966,6 +3125,7 @@ surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated); } } +#ifdef INCLUDE_DEPRECATED_FEATURES } else { int FoldLevelCurr = (pdoc->GetLevel(lineDoc) & SC_FOLDLEVELNUMBERMASK) - SC_FOLDLEVELBASE; int FoldLevelPrev = (pdoc->GetLevel(lineDoc - 1) & SC_FOLDLEVELNUMBERMASK) - SC_FOLDLEVELBASE; @@ -3001,6 +3161,7 @@ surface->FillRectangle(rcBoxLine, vs.styles[STYLE_DEFAULT].fore.allocated); } } +#endif
// Draw the Caret if (lineDoc == lineCaret) { @@ -3512,6 +3673,8 @@ } if (!pdoc->IsReadOnly()) { cs.Clear(); + pdoc->AnnotationClearAll(); + pdoc->MarginClearAll(); } pdoc->EndUndoAction(); anchor = 0; @@ -3885,6 +4048,10 @@ int lines = Platform::Maximum(0, mh.linesAdded); NeedWrapping(lineDoc, lineDoc + lines + 1); } + // Fix up annotation heights + int lineDoc = pdoc->LineFromPosition(mh.position); + int lines = Platform::Maximum(0, mh.linesAdded); + SetAnnotationHeights(lineDoc, lineDoc + lines + 2); } }
@@ -3972,6 +4139,12 @@ cs.DeleteLines(lineOfPos, -mh.linesAdded); } } + if (mh.modificationType & SC_MOD_CHANGEANNOTATION) { + int lineDoc = pdoc->LineFromPosition(mh.position); + if (vs.annotationVisible) { + cs.SetHeight(lineDoc, cs.GetHeight(lineDoc) + mh.annotationLinesAdded); + } + } CheckModificationForWrap(mh); if (mh.linesAdded != 0) { // Avoid scrolling of display if change before current display @@ -4002,7 +4175,7 @@ SetScrollBars(); }
- if (mh.modificationType & SC_MOD_CHANGEMARKER) { + if ((mh.modificationType & SC_MOD_CHANGEMARKER) || (mh.modificationType & SC_MOD_CHANGEMARGIN)) { if ((paintState == notPainting) || !PaintContainsMargin()) { if (mh.modificationType & SC_MOD_CHANGEFOLD) { // Fold changes can affect the drawing of following lines so redraw whole margin @@ -4036,6 +4209,8 @@ scn.line = mh.line; scn.foldLevelNow = mh.foldLevelNow; scn.foldLevelPrev = mh.foldLevelPrev; + scn.token = mh.token; + scn.annotationLinesAdded = mh.annotationLinesAdded; NotifyParent(scn); } } @@ -4305,8 +4480,16 @@
void Editor::CursorUpOrDown(int direction, selTypes sel) { Point pt = LocationFromPosition(currentPos); + int lineDoc = pdoc->LineFromPosition(currentPos); + Point ptStartLine = LocationFromPosition(pdoc->LineStart(lineDoc)); + int subLine = (pt.y - ptStartLine.y) / vs.lineHeight; + int commentLines = vs.annotationVisible ? pdoc->AnnotationLines(lineDoc) : 0; int posNew = PositionFromLocation( Point(lastXChosen, pt.y + direction * vs.lineHeight)); + if ((direction > 0) && (subLine >= (cs.GetHeight(lineDoc) - 1 - commentLines))) { + posNew = PositionFromLocation( + Point(lastXChosen, pt.y + (commentLines + 1) * vs.lineHeight)); + } if (direction < 0) { // Line wrapping may lead to a location on the same line, so // seek back if that is the case. @@ -4611,6 +4794,7 @@ SetLastXChosen(); } EnsureCaretVisible(); + ShowCaretAtCurrentPosition(); // Avoid blinking break; case SCI_BACKTAB: Indent(false); @@ -4618,6 +4802,7 @@ SetLastXChosen(); } EnsureCaretVisible(); + ShowCaretAtCurrentPosition(); // Avoid blinking break; case SCI_NEWLINE: NewLine(); @@ -5740,6 +5925,14 @@ } }
+void Editor::SetAnnotationHeights(int start, int end) { + if (vs.annotationVisible) { + for (int line=start; line<end; line++) { + cs.SetHeight(line, pdoc->AnnotationLines(line) + 1); + } + } +} + void Editor::SetDocPointer(Document *document) { //Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document); pdoc->RemoveWatcher(this, 0); @@ -5764,6 +5957,7 @@ // Reset the contraction state to fully shown. cs.Clear(); cs.InsertLines(0, pdoc->LinesTotal() - 1); + SetAnnotationHeights(0, pdoc->LinesTotal()); llc.Deallocate(); NeedWrapping();
@@ -5772,6 +5966,22 @@ Redraw(); }
+void Editor::SetAnnotationVisible(int visible) { + if (vs.annotationVisible != visible) { + bool changedFromOrToHidden = ((vs.annotationVisible != 0) != (visible != 0)); + vs.annotationVisible = visible; + if (changedFromOrToHidden) { + int dir = vs.annotationVisible ? 1 : -1; + for (int line=0; line<pdoc->LinesTotal(); line++) { + int annotationLines = pdoc->AnnotationLines(line); + if (annotationLines > 0) { + cs.SetHeight(line, cs.GetHeight(line) + annotationLines * dir); + } + } + } + } +} + /** * Recursively expand a fold, making lines visible except where they have an unexpanded parent. */ @@ -6892,6 +7102,13 @@ InvalidateStyleData(); RedrawSelMargin(); break; + + case SCI_MARKERSYMBOLDEFINED: + if (wParam <= MARKER_MAX) + return vs.markers[wParam].markType; + else + return 0; + case SCI_MARKERSETFORE: if (wParam <= MARKER_MAX) vs.markers[wParam].fore.desired = ColourDesired(lParam); @@ -7304,6 +7521,16 @@ case SCI_INDICGETUNDER: return (wParam <= INDIC_MAX) ? vs.indicators[wParam].under : 0;
+ case SCI_INDICSETALPHA: + if (wParam <= INDIC_MAX && lParam >=0 && lParam <= 100) { + vs.indicators[wParam].fillAlpha = lParam; + InvalidateStyleRedraw(); + } + break; + + case SCI_INDICGETALPHA: + return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fillAlpha : 0; + case SCI_SETINDICATORCURRENT: pdoc->decorations.SetCurrentIndicator(wParam); break; @@ -7675,6 +7902,138 @@ case SCI_GETCHARACTERPOINTER: return reinterpret_cast<sptr_t>(pdoc->BufferPointer());
+ case SCI_SETEXTRAASCENT: + vs.extraAscent = wParam; + InvalidateStyleRedraw(); + break; + + case SCI_GETEXTRAASCENT: + return vs.extraAscent; + + case SCI_SETEXTRADESCENT: + vs.extraDescent = wParam; + InvalidateStyleRedraw(); + break; + + case SCI_GETEXTRADESCENT: + return vs.extraDescent; + + case SCI_MARGINSETSTYLEOFFSET: + vs.marginStyleOffset = wParam; + InvalidateStyleRedraw(); + break; + + case SCI_MARGINGETSTYLEOFFSET: + return vs.marginStyleOffset; + + case SCI_MARGINSETTEXT: + pdoc->MarginSetText(wParam, CharPtrFromSPtr(lParam)); + break; + + case SCI_MARGINGETTEXT: { + const StyledText st = pdoc->MarginStyledText(wParam); + if (lParam) { + if (st.text) + memcpy(CharPtrFromSPtr(lParam), st.text, st.length); + else + strcpy(CharPtrFromSPtr(lParam), ""); + } + return st.length; + } + + case SCI_MARGINSETSTYLE: + pdoc->MarginSetStyle(wParam, lParam); + break; + + case SCI_MARGINGETSTYLE: { + const StyledText st = pdoc->MarginStyledText(wParam); + return st.style; + } + + case SCI_MARGINSETSTYLES: + pdoc->MarginSetStyles(wParam, reinterpret_cast<const unsigned char *>(lParam)); + break; + + case SCI_MARGINGETSTYLES: { + const StyledText st = pdoc->MarginStyledText(wParam); + if (lParam) { + if (st.styles) + memcpy(CharPtrFromSPtr(lParam), st.styles, st.length); + else + strcpy(CharPtrFromSPtr(lParam), ""); + } + return st.styles ? st.length : 0; + } + + case SCI_MARGINTEXTCLEARALL: + pdoc->MarginClearAll(); + break; + + case SCI_ANNOTATIONSETTEXT: + pdoc->AnnotationSetText(wParam, CharPtrFromSPtr(lParam)); + break; + + case SCI_ANNOTATIONGETTEXT: { + const StyledText st = pdoc->AnnotationStyledText(wParam); + if (lParam) { + if (st.text) + memcpy(CharPtrFromSPtr(lParam), st.text, st.length); + else + strcpy(CharPtrFromSPtr(lParam), ""); + } + return st.length; + } + + case SCI_ANNOTATIONGETSTYLE: { + const StyledText st = pdoc->AnnotationStyledText(wParam); + return st.style; + } + + case SCI_ANNOTATIONSETSTYLE: + pdoc->AnnotationSetStyle(wParam, lParam); + break; + + case SCI_ANNOTATIONSETSTYLES: + pdoc->AnnotationSetStyles(wParam, reinterpret_cast<const unsigned char *>(lParam)); + break; + + case SCI_ANNOTATIONGETSTYLES: { + const StyledText st = pdoc->AnnotationStyledText(wParam); + if (lParam) { + if (st.styles) + memcpy(CharPtrFromSPtr(lParam), st.styles, st.length); + else + strcpy(CharPtrFromSPtr(lParam), ""); + } + return st.styles ? st.length : 0; + } + + case SCI_ANNOTATIONGETLINES: + return pdoc->AnnotationLines(wParam); + + case SCI_ANNOTATIONCLEARALL: + pdoc->AnnotationClearAll(); + break; + + case SCI_ANNOTATIONSETVISIBLE: + SetAnnotationVisible(wParam); + break; + + case SCI_ANNOTATIONGETVISIBLE: + return vs.annotationVisible; + + case SCI_ANNOTATIONSETSTYLEOFFSET: + vs.annotationStyleOffset = wParam; + InvalidateStyleRedraw(); + break; + + case SCI_ANNOTATIONGETSTYLEOFFSET: + return vs.annotationStyleOffset; + + case SCI_ADDUNDOACTION: + pdoc->AddUndoAction(wParam, lParam & UNDO_MAY_COALESCE); + break; + default: return DefWndProc(iMessage, wParam, lParam); }
Modified: trunk/scintilla/Editor.h =================================================================== --- trunk/scintilla/Editor.h 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/Editor.h 2009-05-03 17:49:33 UTC (rev 3769) @@ -322,6 +322,8 @@ bool drawWrapMark, ColourAllocated wrapColour); void DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int xStart, PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under); + void DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart, + PRectangle rcLine, LineLayout *ll, int subLine); void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart, PRectangle rcLine, LineLayout *ll, int subLine=0); void DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine, int xStart, int offset, int posCaret, PRectangle rcCaret); @@ -443,7 +445,10 @@ void CheckForChangeOutsidePaint(Range r); void SetBraceHighlight(Position pos0, Position pos1, int matchStyle);
+ void SetAnnotationHeights(int start, int end); void SetDocPointer(Document *document); + + void SetAnnotationVisible(int visible);
void Expand(int &line, bool doExpand); void ToggleContraction(int line);
Modified: trunk/scintilla/Indicator.cxx =================================================================== --- trunk/scintilla/Indicator.cxx 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/Indicator.cxx 2009-05-03 17:49:33 UTC (rev 3769) @@ -72,7 +72,7 @@ rcBox.top = rcLine.top + 1; rcBox.left = rc.left; rcBox.right = rc.right; - surface->AlphaRectangle(rcBox, 1, fore.allocated, 30, fore.allocated, 50, 0); + surface->AlphaRectangle(rcBox, 1, fore.allocated, fillAlpha, fore.allocated, 50, 0); } else { // Either INDIC_PLAIN or unknown surface->MoveTo(rc.left, ymid); surface->LineTo(rc.right, ymid);
Modified: trunk/scintilla/Indicator.h =================================================================== --- trunk/scintilla/Indicator.h 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/Indicator.h 2009-05-03 17:49:33 UTC (rev 3769) @@ -19,7 +19,8 @@ int style; bool under; ColourPair fore; - Indicator() : style(INDIC_PLAIN), under(false), fore(ColourDesired(0,0,0)) { + int fillAlpha; + Indicator() : style(INDIC_PLAIN), under(false), fore(ColourDesired(0,0,0)), fillAlpha(30) { } void Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine); };
Modified: trunk/scintilla/KeyWords.cxx =================================================================== --- trunk/scintilla/KeyWords.cxx 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/KeyWords.cxx 2009-05-03 17:49:33 UTC (rev 3769) @@ -144,7 +144,6 @@ LINK_LEXER(lmAda); LINK_LEXER(lmAsm); LINK_LEXER(lmBash); - LINK_LEXER(lmFreeBasic); LINK_LEXER(lmCaml); LINK_LEXER(lmCmake); LINK_LEXER(lmCPP); @@ -153,6 +152,7 @@ LINK_LEXER(lmDiff); LINK_LEXER(lmF77); LINK_LEXER(lmFortran); + LINK_LEXER(lmFreeBasic); LINK_LEXER(lmHaskell); LINK_LEXER(lmHTML); LINK_LEXER(lmLatex);
Modified: trunk/scintilla/LexBash.cxx =================================================================== --- trunk/scintilla/LexBash.cxx 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/LexBash.cxx 2009-05-03 17:49:33 UTC (rev 3769) @@ -334,6 +334,10 @@ } char s[HERE_DELIM_MAX]; sc.GetCurrent(s, sizeof(s)); + if (sc.LengthCurrent() == 0) + break; + if (s[strlen(s) - 1] == '\r') + s[strlen(s) - 1] = '\0'; if (strcmp(HereDoc.Delimiter, s) == 0) { if ((prefixws > 0 && HereDoc.Indent) || // indentation rule (prefixws == 0 && !HereDoc.Indent)) {
Modified: trunk/scintilla/LexCPP.cxx =================================================================== --- trunk/scintilla/LexCPP.cxx 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/LexCPP.cxx 2009-05-03 17:49:33 UTC (rev 3769) @@ -58,6 +58,9 @@ WordList &keywords3 = *keywordlists[2]; WordList &keywords4 = *keywordlists[3];
+ // property styling.within.preprocessor + // For C++ code, determines whether all preprocessor code is styled in the preprocessor style (0, the default) + // or only from the initial # to the end of the command word(1). bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;
CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-"); @@ -67,6 +70,9 @@
CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); + + // property lexer.cpp.allow.dollars + // Set to 0 to disallow the '$' character in identifiers with the cpp lexer. if (styler.GetPropertyInt("lexer.cpp.allow.dollars", 1) != 0) { setWordStart.Add('$'); setWord.Add('$'); @@ -77,6 +83,7 @@ bool lastWordWasUUID = false; int styleBeforeDCKeyword = SCE_C_DEFAULT; bool continuationLine = false; + bool isIncludePreprocessor = false;
if (initStyle == SCE_C_PREPROCESSOR) { // Set continuationLine if last character of previous line is '' @@ -118,6 +125,7 @@ // if different sets of lines lexed. visibleChars = 0; lastWordWasUUID = false; + isIncludePreprocessor = false; }
// Handle line continuation generically. @@ -230,6 +238,11 @@ case SCE_C_STRING: if (sc.atLineEnd) { sc.ChangeState(SCE_C_STRINGEOL); + } else if (isIncludePreprocessor) { + if (sc.ch == '>') { + sc.ForwardSetState(SCE_C_DEFAULT); + isIncludePreprocessor = false; + } } else if (sc.ch == '\') { if (sc.chNext == '"' || sc.chNext == ''' || sc.chNext == '\') { sc.Forward(); @@ -321,6 +334,9 @@ sc.SetState(SCE_C_REGEX); // JavaScript's RegEx } else if (sc.ch == '"') { sc.SetState(SCE_C_STRING); + isIncludePreprocessor = false; // ensure that '>' won't end the string + } else if (isIncludePreprocessor && sc.ch == '<') { + sc.SetState(SCE_C_STRING); } else if (sc.ch == ''') { sc.SetState(SCE_C_CHARACTER); } else if (sc.ch == '#' && visibleChars == 0) { @@ -332,6 +348,8 @@ } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); if (sc.atLineEnd) { sc.SetState(SCE_C_DEFAULT); + } else if (sc.Match("include")) { + isIncludePreprocessor = true; } } else if (isoperator(static_cast<char>(sc.ch))) { sc.SetState(SCE_C_OPERATOR); @@ -359,10 +377,24 @@ // and to make it possible to fiddle the current level for "} else {". static void FoldCppDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) { + + // property fold.comment + // This option enables folding multi-line comments and explicit fold points when using the C++ lexer. + // Explicit fold points allows adding extra folding by placing a //{ comment at the start and a //} + // at the end of a section that should fold. bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + + // property fold.preprocessor + // This option enables folding preprocessor directives when using the C++ lexer. + // Includes C#'s explicit #region and #endregion folding directives. bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + + // property fold.at.else + // This option enables C++ folding on a "} else {" line of an if statement. bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; + unsigned int endPos = startPos + length; int visibleChars = 0; int lineCurrent = styler.GetLine(startPos);
Modified: trunk/scintilla/LexD.cxx =================================================================== --- trunk/scintilla/LexD.cxx 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/LexD.cxx 2009-05-03 17:49:33 UTC (rev 3769) @@ -268,6 +268,9 @@ static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor &styler) { bool foldComment = styler.GetPropertyInt("fold.comment") != 0; bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + + // property lexer.d.fold.at.else + // This option enables D folding on a "} else {" line of an if statement. bool foldAtElse = styler.GetPropertyInt("lexer.d.fold.at.else", styler.GetPropertyInt("fold.at.else", 0)) != 0; unsigned int endPos = startPos + length;
Modified: trunk/scintilla/LexFortran.cxx =================================================================== --- trunk/scintilla/LexFortran.cxx 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/LexFortran.cxx 2009-05-03 17:49:33 UTC (rev 3769) @@ -83,7 +83,7 @@ // Handle the fix format generically int toLineStart = sc.currentPos - posLineStart; if (isFixFormat && (toLineStart < 6 || toLineStart > 72)) { - if (toLineStart == 0 && (tolower(sc.ch) == 'c' || sc.ch == '*') || sc.ch == '!') { + if ((toLineStart == 0 && (tolower(sc.ch) == 'c' || sc.ch == '*')) || sc.ch == '!') { if (sc.MatchIgnoreCase("cdec$") || sc.MatchIgnoreCase("*dec$") || sc.MatchIgnoreCase("!dec$") || sc.MatchIgnoreCase("cdir$") || sc.MatchIgnoreCase("*dir$") || sc.MatchIgnoreCase("!dir$") || sc.MatchIgnoreCase("cms$") || sc.MatchIgnoreCase("*ms$") || sc.MatchIgnoreCase("!ms$") || @@ -252,7 +252,7 @@ lev = 0; else lev = 1; - } else if (strcmp(s, "end") == 0 && chNextNonBlank != '=' + } else if ((strcmp(s, "end") == 0 && chNextNonBlank != '=') || strcmp(s, "endassociate") == 0 || strcmp(s, "endblock") == 0 || strcmp(s, "endblockdata") == 0 || strcmp(s, "endselect") == 0 || strcmp(s, "enddo") == 0 || strcmp(s, "endenum") ==0
Modified: trunk/scintilla/LexHTML.cxx =================================================================== --- trunk/scintilla/LexHTML.cxx 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/LexHTML.cxx 2009-05-03 17:49:33 UTC (rev 3769) @@ -274,17 +274,30 @@ s[i] = '\0';
// No keywords -> all are known - // Name of a closing tag starts at s + 1 char chAttr = SCE_H_TAGUNKNOWN; if (s[0] == '!') { chAttr = SCE_H_SGML_DEFAULT; - } else if (!keywords || keywords.InList(s[0] == '/' ? s + 1 : s)) { + } else if (!keywords || keywords.InList(s)) { chAttr = SCE_H_TAG; } styler.ColourTo(end, chAttr); if (chAttr == SCE_H_TAG) { if (allowScripts && 0 == strcmp(s, "script")) { - chAttr = SCE_H_SCRIPT; + // check to see if this is a self-closing tag by sniffing ahead + bool isSelfClose = false; + for (unsigned int cPos = end; cPos <= end + 100; cPos++) { + char ch = styler.SafeGetCharAt(cPos, '\0'); + if (ch == '\0' || ch == '>') + break; + else if (ch == '/' && styler.SafeGetCharAt(cPos + 1, '\0') == '>') { + isSelfClose = true; + break; + } + } + + // do not enter a script state if the tag self-closed + if (!isSelfClose) + chAttr = SCE_H_SCRIPT; } else if (!isXml && 0 == strcmp(s, "comment")) { chAttr = SCE_H_COMMENT; } @@ -561,6 +574,10 @@ } else { // Default client and ASP scripting language is JavaScript lineState = eScriptJS << 8; + + // property asp.default.language + // Script in ASP code is initially assumed to be in JavaScript. + // To change this to VBScript set asp.default.language to 2. Python is 3. lineState |= styler.GetPropertyInt("asp.default.language", eScriptJS) << 4; } script_mode inScriptType = script_mode((lineState >> 0) & 0x03); // 2 bits of scripting mode @@ -577,13 +594,37 @@ scriptLanguage = eScriptComment; }
+ // property fold.html + // Folding is turned on or off for HTML and XML files with this option. + // The fold option must also be on for folding to occur. const bool foldHTML = styler.GetPropertyInt("fold.html", 0) != 0; + const bool fold = foldHTML && styler.GetPropertyInt("fold", 0); + + // property fold.html.preprocessor + // Folding is turned on or off for scripts embedded in HTML files with this option. + // The default is on. const bool foldHTMLPreprocessor = foldHTML && styler.GetPropertyInt("fold.html.preprocessor", 1); + const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + + // property fold.hypertext.comment + // Allow folding for comments in scripts embedded in HTML. + // The default is off. const bool foldComment = fold && styler.GetPropertyInt("fold.hypertext.comment", 0) != 0; + + // property fold.hypertext.heredoc + // Allow folding for heredocs in scripts embedded in HTML. + // The default is off. const bool foldHeredoc = fold && styler.GetPropertyInt("fold.hypertext.heredoc", 0) != 0; + + // property html.tags.case.sensitive + // For XML and HTML, setting this property to 1 will make tags match in a case + // sensitive way which is the expected behaviour for XML and XHTML. const bool caseSensitive = styler.GetPropertyInt("html.tags.case.sensitive", 0) != 0; + + // property lexer.xml.allow.scripts + // Set to 0 to disable scripts in XML. const bool allowScripts = styler.GetPropertyInt("lexer.xml.allow.scripts", 1) != 0;
const CharacterSet setHTMLWord(CharacterSet::setAlphaNum, ".-_:!#", 0x80, true);
Modified: trunk/scintilla/LexOthers.cxx =================================================================== --- trunk/scintilla/LexOthers.cxx 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/LexOthers.cxx 2009-05-03 17:49:33 UTC (rev 3769) @@ -694,6 +694,11 @@ styler.StartSegment(startPos); unsigned int linePos = 0; unsigned int startLine = startPos; + + // property lexer.props.allow.initial.spaces + // For properties files, set to 0 to style all lines that start with whitespace in the default style. + // This is not suitable for SciTE .properties files which use indentation for flow control but + // can be used for RFC2822 text where indentation is used for continuation lines. bool allowInitialSpaces = styler.GetPropertyInt("lexer.props.allow.initial.spaces", 1) != 0;
for (unsigned int i = startPos; i < startPos + length; i++) { @@ -782,7 +787,7 @@ lev = SC_FOLDLEVELBASE; } int flagsNext = styler.LevelAt(lineCurrent); - styler.SetLevel(lineCurrent, lev | flagsNext & ~SC_FOLDLEVELNUMBERMASK); + styler.SetLevel(lineCurrent, lev | (flagsNext & ~SC_FOLDLEVELNUMBERMASK)); }
static void ColouriseMakeLine( @@ -1097,6 +1102,12 @@ styler.StartAt(startPos); styler.StartSegment(startPos); unsigned int linePos = 0; + + // property lexer.errorlist.value.separate + // For lines in the output pane that are matches from Find in Files or GCC-style + // diagnostics, style the path and line number separately from the rest of the + // line with style 21 used for the rest of the line. + // This allows matched text to be more easily distinguished from its location. bool valueSeparate = styler.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0; for (unsigned int i = startPos; i < startPos + length; i++) { lineBuffer[linePos++] = styler[i];
Modified: trunk/scintilla/LexPascal.cxx =================================================================== --- trunk/scintilla/LexPascal.cxx 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/LexPascal.cxx 2009-05-03 17:49:33 UTC (rev 3769) @@ -4,8 +4,109 @@ ** Written by Laurent le Tynevez ** Updated by Simon Steele s.steele@pnotepad.org September 2002 ** Updated by Mathias Rauen scite@madshi.net May 2003 (Delphi adjustments) + ** Completely rewritten by Marko Njezic sf@maxempire.com October 2008 **/
+/* + +A few words about features of the new completely rewritten LexPascal... + +Generally speaking LexPascal tries to support all available Delphi features (up +to Delphi 2009 at this time), including .NET specific features. + +~ HIGHLIGHTING: + +If you enable "lexer.pascal.smart.highlighting" property, some keywords will +only be highlighted in appropriate context. As implemented those are keywords +related to property and DLL exports declarations (similar to how Delphi IDE +works). + +For example, keywords "read" and "write" will only be highlighted if they are in +property declaration: + +property MyProperty: boolean read FMyProperty write FMyProperty; + +~ FOLDING: + +Folding is supported in the following cases: + +- Folding of stream-like comments +- Folding of groups of consecutive line comments +- Folding of preprocessor blocks (the following preprocessor blocks are +supported: IF / IFEND; IFDEF, IFNDEF, IFOPT / ENDIF and REGION / ENDREGION +blocks), including nesting of preprocessor blocks up to 255 levels +- Folding of code blocks on appropriate keywords (the following code blocks are +supported: "begin, asm, record, try, case / end" blocks, class & object +declarations and interface declarations) + +Remarks: + +- Folding of code blocks tries to handle all special cases in which folding +should not occur. As implemented those are: + +1. Structure "record case / end" (there's only one "end" statement and "case" is +ignored as fold point) +2. Forward class declarations ("type TMyClass = class;") and object method +declarations ("TNotifyEvent = procedure(Sender: TObject) of object;") are +ignored as fold points +3. Simplified complete class declarations ("type TMyClass = class(TObject);") +are ignored as fold points +4. Every other situation when class keyword doesn't actually start class +declaration ("class procedure", "class function", "class of", "class var", +"class property" and "class operator") + +- Folding of code blocks inside preprocessor blocks is disabled (any comments +inside them will be folded fine) because there is no guarantee that complete +code block will be contained inside folded preprocessor block in which case +folded code block could end prematurely at the end of preprocessor block if +there is no closing statement inside. This was done in order to properly process +document that may contain something like this: + +type +{$IFDEF UNICODE} + TMyClass = class(UnicodeAncestor) +{$ELSE} + TMyClass = class(AnsiAncestor) +{$ENDIF} + private + ... + public + ... + published + ... +end; + +If class declarations were folded, then the second class declaration would end +at "$ENDIF" statement, first class statement would end at "end;" statement and +preprocessor "$IFDEF" block would go all the way to the end of document. +However, having in mind all this, if you want to enable folding of code blocks +inside preprocessor blocks, you can disable folding of preprocessor blocks by +changing "fold.preprocessor" property, in which case everything inside them +would be folded. + +~ KEYWORDS: + +The list of keywords that can be used in pascal.properties file (up to Delphi +2009): + +- Keywords: absolute abstract and array as asm assembler automated begin case +cdecl class const constructor deprecated destructor dispid dispinterface div do +downto dynamic else end except export exports external far file final +finalization finally for forward function goto if implementation in inherited +initialization inline interface is label library message mod near nil not object +of on or out overload override packed pascal platform private procedure program +property protected public published raise record register reintroduce repeat +resourcestring safecall sealed set shl shr static stdcall strict string then +threadvar to try type unit unsafe until uses var varargs virtual while with xor + +- Keywords related to the "smart highlithing" feature: add default implements +index name nodefault read readonly remove stored write writeonly + +- Keywords related to Delphi packages (in addition to all above): package +contains requires + +*/ + #include <stdlib.h> #include <string.h> #include <ctype.h> @@ -20,12 +121,13 @@ #include "Scintilla.h" #include "SciLexer.h" #include "StyleContext.h" +#include "CharacterSet.h"
#ifdef SCI_NAMESPACE using namespace Scintilla; #endif
-static void getRange(unsigned int start, +static void GetRangeLowered(unsigned int start, unsigned int end, Accessor &styler, char *s, @@ -38,241 +140,361 @@ s[i] = '\0'; }
-static bool IsStreamCommentStyle(int style) { - return style == SCE_C_COMMENT || - style == SCE_C_COMMENTDOC || - style == SCE_C_COMMENTDOCKEYWORD || - style == SCE_C_COMMENTDOCKEYWORDERROR; -} +static void GetForwardRangeLowered(unsigned int start, + CharacterSet &charSet, + Accessor &styler, + char *s, + unsigned int len) { + unsigned int i = 0; + while ((i < len-1) && charSet.Contains(styler.SafeGetCharAt(start + i))) { + s[i] = static_cast<char>(tolower(styler.SafeGetCharAt(start + i))); + i++; + } + s[i] = '\0';
-static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr, bool bInAsm) { - if ((bInAsm) && (attr == SCE_C_OPERATOR || attr == SCE_C_NUMBER || attr == SCE_C_DEFAULT || attr == SCE_C_WORD || attr == SCE_C_IDENTIFIER)) { - styler.ColourTo(end, SCE_C_REGEX); - } else - styler.ColourTo(end, attr); }
-// returns 1 if the item starts a class definition, and -1 if the word is "end", and 2 if the word is "asm" -static int classifyWordPascal(unsigned int start, unsigned int end, /*WordList &keywords*/WordList *keywordlists[], Accessor &styler, bool bInClass, bool bInAsm) { - int ret = 0; +enum { + stateInAsm = 0x1000, + stateInProperty = 0x2000, + stateInExport = 0x4000, + stateFoldInPreprocessor = 0x0100, + stateFoldInRecord = 0x0200, + stateFoldInPreprocessorLevelMask = 0x00FF, + stateFoldMaskAll = 0x0FFF +};
+static void ClassifyPascalWord(WordList *keywordlists[], StyleContext &sc, int &curLineState, bool bSmartHighlighting) { WordList& keywords = *keywordlists[0]; - WordList& classwords = *keywordlists[1];
char s[100]; - getRange(start, end, styler, s, sizeof(s)); + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + if (curLineState & stateInAsm) { + if (strcmp(s, "end") == 0 && sc.GetRelative(-4) != '@') { + curLineState &= ~stateInAsm; + sc.ChangeState(SCE_PAS_WORD); + } else { + sc.ChangeState(SCE_PAS_ASM); + } + } else { + bool ignoreKeyword = false; + if (strcmp(s, "asm") == 0) { + curLineState |= stateInAsm; + } else if (bSmartHighlighting) { + if (strcmp(s, "property") == 0) { + curLineState |= stateInProperty; + } else if (strcmp(s, "exports") == 0) { + curLineState |= stateInExport; + } else if (!(curLineState & (stateInProperty | stateInExport)) && strcmp(s, "index") == 0) { + ignoreKeyword = true; + } else if (!(curLineState & stateInExport) && strcmp(s, "name") == 0) { + ignoreKeyword = true; + } else if (!(curLineState & stateInProperty) && + (strcmp(s, "read") == 0 || strcmp(s, "write") == 0 || + strcmp(s, "default") == 0 || strcmp(s, "nodefault") == 0 || + strcmp(s, "stored") == 0 || strcmp(s, "implements") == 0 || + strcmp(s, "readonly") == 0 || strcmp(s, "writeonly") == 0 || + strcmp(s, "add") == 0 || strcmp(s, "remove") == 0)) { + ignoreKeyword = true; + } + } + if (!ignoreKeyword) { + sc.ChangeState(SCE_PAS_WORD); + } + } + } else if (curLineState & stateInAsm) { + sc.ChangeState(SCE_PAS_ASM); + } + sc.SetState(SCE_PAS_DEFAULT); +}
- char chAttr = SCE_C_IDENTIFIER; - if (isdigit(s[0]) || (s[0] == '.') ||(s[0] == '$')) { - chAttr = SCE_C_NUMBER; - } - else { - if (s[0] == '#') { - chAttr = SCE_C_CHARACTER; +static void ColourisePascalDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + bool bSmartHighlighting = styler.GetPropertyInt("lexer.pascal.smart.highlighting", 1) != 0; + + CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true); + CharacterSet setNumber(CharacterSet::setDigits, ".-+eE"); + CharacterSet setHexNumber(CharacterSet::setDigits, "abcdefABCDEF"); + CharacterSet setOperator(CharacterSet::setNone, "#$&'()*+,-./:;<=>@[]^{}"); + + int curLine = styler.GetLine(startPos); + int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : 0; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + if (sc.atLineEnd) { + // Update the line state, so it can be seen by next line + curLine = styler.GetLine(sc.currentPos); + styler.SetLineState(curLine, curLineState); } - else { - if (keywords.InList(s)) { - chAttr = SCE_C_WORD;
- if(strcmp(s, "class") == 0) { - ret = 1; + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_PAS_NUMBER: + if (!setNumber.Contains(sc.ch) || (sc.ch == '.' && sc.chNext == '.')) { + sc.SetState(SCE_PAS_DEFAULT); + } else if (sc.ch == '-' || sc.ch == '+') { + if (sc.chPrev != 'E' && sc.chPrev != 'e') { + sc.SetState(SCE_PAS_DEFAULT); + } } - else if (strcmp(s, "asm") == 0) { - ret = 2; + break; + case SCE_PAS_IDENTIFIER: + if (!setWord.Contains(sc.ch)) { + ClassifyPascalWord(keywordlists, sc, curLineState, bSmartHighlighting); } - else if (strcmp(s, "end") == 0) { - ret = -1; + break; + case SCE_PAS_HEXNUMBER: + if (!setHexNumber.Contains(sc.ch)) { + sc.SetState(SCE_PAS_DEFAULT); } - } else if (bInClass) { - if (classwords.InList(s)) { - chAttr = SCE_C_WORD; + break; + case SCE_PAS_COMMENT: + case SCE_PAS_PREPROCESSOR: + if (sc.ch == '}') { + sc.ForwardSetState(SCE_PAS_DEFAULT); } + break; + case SCE_PAS_COMMENT2: + case SCE_PAS_PREPROCESSOR2: + if (sc.Match('*', ')')) { + sc.Forward(); + sc.ForwardSetState(SCE_PAS_DEFAULT); + } + break; + case SCE_PAS_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_PAS_DEFAULT); + } + break; + case SCE_PAS_STRING: + if (sc.atLineEnd) { + sc.ChangeState(SCE_PAS_STRINGEOL); + } else if (sc.ch == ''' && sc.chNext == ''') { + sc.Forward(); + } else if (sc.ch == ''') { + sc.ForwardSetState(SCE_PAS_DEFAULT); + } + break; + case SCE_PAS_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_PAS_DEFAULT); + } + break; + case SCE_PAS_CHARACTER: + if (!setHexNumber.Contains(sc.ch) && sc.ch != '$') { + sc.SetState(SCE_PAS_DEFAULT); + } + break; + case SCE_PAS_OPERATOR: + if (bSmartHighlighting && sc.chPrev == ';') { + curLineState &= ~(stateInProperty | stateInExport); + } + sc.SetState(SCE_PAS_DEFAULT); + break; + case SCE_PAS_ASM: + sc.SetState(SCE_PAS_DEFAULT); + break; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_PAS_DEFAULT) { + if (IsADigit(sc.ch) && !(curLineState & stateInAsm)) { + sc.SetState(SCE_PAS_NUMBER); + } else if (setWordStart.Contains(sc.ch)) { + sc.SetState(SCE_PAS_IDENTIFIER); + } else if (sc.ch == '$' && !(curLineState & stateInAsm)) { + sc.SetState(SCE_PAS_HEXNUMBER); + } else if (sc.Match('{', '$')) { + sc.SetState(SCE_PAS_PREPROCESSOR); + } else if (sc.ch == '{') { + sc.SetState(SCE_PAS_COMMENT); + } else if (sc.Match("(*$")) { + sc.SetState(SCE_PAS_PREPROCESSOR2); + } else if (sc.Match('(', '*')) { + sc.SetState(SCE_PAS_COMMENT2); + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('/', '/')) { + sc.SetState(SCE_PAS_COMMENTLINE); + } else if (sc.ch == ''') { + sc.SetState(SCE_PAS_STRING); + } else if (sc.ch == '#') { + sc.SetState(SCE_PAS_CHARACTER); + } else if (setOperator.Contains(sc.ch) && !(curLineState & stateInAsm)) { + sc.SetState(SCE_PAS_OPERATOR); + } else if (curLineState & stateInAsm) { + sc.SetState(SCE_PAS_ASM); } } } - ColourTo(styler, end, chAttr, (bInAsm && ret != -1)); - return ret; + + if (sc.state == SCE_PAS_IDENTIFIER && setWord.Contains(sc.chPrev)) { + ClassifyPascalWord(keywordlists, sc, curLineState, bSmartHighlighting); + } + + sc.Complete(); }
-static int classifyFoldPointPascal(const char* s) { - int lev = 0; - if (!(isdigit(s[0]) || (s[0] == '.'))) { - if (strcmp(s, "begin") == 0 || - strcmp(s, "object") == 0 || - strcmp(s, "case") == 0 || - strcmp(s, "class") == 0 || - strcmp(s, "record") == 0 || - strcmp(s, "try") == 0) { - lev=1; - } else if (strcmp(s, "end") == 0) { - lev=-1; +static bool IsStreamCommentStyle(int style) { + return style == SCE_PAS_COMMENT || style == SCE_PAS_COMMENT2; +} + +static bool IsCommentLine(int line, Accessor &styler) { + int pos = styler.LineStart(line); + int eolPos = styler.LineStart(line + 1) - 1; + for (int i = pos; i < eolPos; i++) { + char ch = styler[i]; + char chNext = styler.SafeGetCharAt(i + 1); + int style = styler.StyleAt(i); + if (ch == '/' && chNext == '/' && style == SCE_PAS_COMMENTLINE) { + return true; + } else if (!IsASpaceOrTab(ch)) { + return false; } } - return lev; + return false; }
-static void ColourisePascalDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { +static unsigned int GetFoldInPreprocessorLevelFlag(int lineFoldStateCurrent) { + return lineFoldStateCurrent & stateFoldInPreprocessorLevelMask; +}
- styler.StartAt(startPos); +static void SetFoldInPreprocessorLevelFlag(int &lineFoldStateCurrent, unsigned int nestLevel) { + lineFoldStateCurrent &= ~stateFoldInPreprocessorLevelMask; + lineFoldStateCurrent |= nestLevel & stateFoldInPreprocessorLevelMask; +}
- int state = initStyle; - if (state == SCE_C_CHARACTER) // Does not leak onto next line - state = SCE_C_DEFAULT; - char chPrev = ' '; - char chNext = styler[startPos]; - unsigned int lengthDoc = startPos + length; +static void ClassifyPascalPreprocessorFoldPoint(int &levelCurrent, int &lineFoldStateCurrent, + unsigned int startPos, Accessor &styler) { + CharacterSet setWord(CharacterSet::setAlpha);
- bool bInClassDefinition; + char s[11]; // Size of the longest possible keyword + one additional character + null + GetForwardRangeLowered(startPos, setWord, styler, s, sizeof(s));
- int currentLine = styler.GetLine(startPos); - if (currentLine > 0) { - styler.SetLineState(currentLine, styler.GetLineState(currentLine-1)); - bInClassDefinition = (styler.GetLineState(currentLine) == 1); - } else { - styler.SetLineState(currentLine, 0); - bInClassDefinition = false; - } + unsigned int nestLevel = GetFoldInPreprocessorLevelFlag(lineFoldStateCurrent);
- bool bInAsm = (state == SCE_C_REGEX); - if (bInAsm) - state = SCE_C_DEFAULT; - - styler.StartSegment(startPos); - for (unsigned int i = startPos; i < lengthDoc; i++) { - char ch = chNext; - - chNext = styler.SafeGetCharAt(i + 1); - - if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { - // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) - // Avoid triggering two times on Dos/Win - // End of line - if (state == SCE_C_CHARACTER) { - ColourTo(styler, i, state, bInAsm); - state = SCE_C_DEFAULT; - } - currentLine++; - styler.SetLineState(currentLine, (bInClassDefinition ? 1 : 0)); + if (strcmp(s, "if") == 0 || + strcmp(s, "ifdef") == 0 || + strcmp(s, "ifndef") == 0 || + strcmp(s, "ifopt") == 0 || + strcmp(s, "region") == 0) { + nestLevel++; + SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel); + lineFoldStateCurrent |= stateFoldInPreprocessor; + levelCurrent++; + } else if (strcmp(s, "endif") == 0 || + strcmp(s, "ifend") == 0 || + strcmp(s, "endregion") == 0) { + nestLevel--; + SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel); + if (nestLevel == 0) { + lineFoldStateCurrent &= ~stateFoldInPreprocessor; } - - if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); - chPrev = ' '; - i += 1; - continue; + levelCurrent--; + if (levelCurrent < SC_FOLDLEVELBASE) { + levelCurrent = SC_FOLDLEVELBASE; } + } +}
- if (state == SCE_C_DEFAULT) { - if (iswordstart(ch) || ch == '#' || ch == '$' || (ch == '@' && bInAsm)) { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_IDENTIFIER; - } else if (ch == '{' && chNext != '$' && chNext != '&') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_COMMENT; - } else if (ch == '(' && chNext == '*' - && styler.SafeGetCharAt(i + 2) != '$' - && styler.SafeGetCharAt(i + 2) != '&') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_COMMENTDOC; - } else if (ch == '/' && chNext == '/') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_COMMENTLINE; - } else if (ch == ''') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_CHARACTER; - } else if (ch == '{' && (chNext == '$' || chNext=='&')) { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_PREPROCESSOR; - } else if (isoperator(ch)) { - ColourTo(styler, i-1, state, bInAsm); - ColourTo(styler, i, SCE_C_OPERATOR, bInAsm); +static unsigned int SkipWhiteSpace(unsigned int currentPos, unsigned int endPos, + Accessor &styler, bool includeChars = false) { + CharacterSet setWord(CharacterSet::setAlphaNum, "_"); + unsigned int j = currentPos + 1; + char ch = styler.SafeGetCharAt(j); + while ((j < endPos) && (IsASpaceOrTab(ch) || ch == '\r' || ch == '\n' || + IsStreamCommentStyle(styler.StyleAt(j)) || (includeChars && setWord.Contains(ch)))) { + j++; + ch = styler.SafeGetCharAt(j); + } + return j; +}
- } - } else if (state == SCE_C_IDENTIFIER) { - bool bDoublePoint = ((ch == '.') && (chPrev == '.')); - bool bSinglePoint = (ch == '.'); +static void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCurrent, + unsigned int startPos, unsigned int endPos, + unsigned int lastStart, unsigned int currentPos, Accessor &styler) { + char s[100]; + GetRangeLowered(lastStart, currentPos, styler, s, sizeof(s));
- if ((!iswordchar(ch) && ch != '$' && ch != '#' && (ch != '@' || !bInAsm)) || bDoublePoint || bSinglePoint) { - if (bDoublePoint) i--; - int lStateChange = classifyWordPascal(styler.GetStartSegment(), i - 1, keywordlists, styler, bInClassDefinition, bInAsm); + if (strcmp(s, "record") == 0) { + lineFoldStateCurrent |= stateFoldInRecord; + levelCurrent++; + } else if (strcmp(s, "begin") == 0 || + strcmp(s, "asm") == 0 || + strcmp(s, "try") == 0 || + (strcmp(s, "case") == 0 && !(lineFoldStateCurrent & stateFoldInRecord))) { + levelCurrent++; + } else if (strcmp(s, "class") == 0 || strcmp(s, "object") == 0) { + // "class" & "object" keywords require special handling... + bool ignoreKeyword = false; + unsigned int j = SkipWhiteSpace(currentPos, endPos, styler); + if (j < endPos) { + CharacterSet setWordStart(CharacterSet::setAlpha, "_"); + CharacterSet setWord(CharacterSet::setAlphaNum, "_");
- if(lStateChange == 1) { - styler.SetLineState(currentLine, 1); - bInClassDefinition = true; - } else if(lStateChange == 2) { - bInAsm = true; - } else if(lStateChange == -1) { - styler.SetLineState(currentLine, 0); - bInClassDefinition = false; - bInAsm = false; - } - if (bDoublePoint) { - i++; - ColourTo(styler, i-1, SCE_C_DEFAULT, bInAsm); - } + if (styler.SafeGetCharAt(j) == ';') { + // Handle forward class declarations ("type TMyClass = class;") + // and object method declarations ("TNotifyEvent = procedure(Sender: TObject) of object;") + ignoreKeyword = true; + } else if (strcmp(s, "class") == 0) { + // "class" keyword has a few more special cases... + if (styler.SafeGetCharAt(j) == '(') { + // Handle simplified complete class declarations ("type TMyClass = class(TObject);") + j = SkipWhiteSpace(j, endPos, styler, true); + if (j < endPos && styler.SafeGetCharAt(j) == ')') { + j = SkipWhiteSpace(j, endPos, styler); + if (j < endPos && styler.SafeGetCharAt(j) == ';') { + ignoreKeyword = true; + } + } + } else if (setWordStart.Contains(styler.SafeGetCharAt(j))) { + char s2[11]; // Size of the longest possible keyword + one additional character + null + GetForwardRangeLowered(j, setWord, styler, s2, sizeof(s2));
- state = SCE_C_DEFAULT; - chNext = styler.SafeGetCharAt(i + 1); - if (ch == '{' && chNext != '$' && chNext != '&') { - state = SCE_C_COMMENT; - } else if (ch == '(' && chNext == '*' - && styler.SafeGetCharAt(i + 2) != '$' - && styler.SafeGetCharAt(i + 2) != '&') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_COMMENTDOC; - } else if (ch == '/' && chNext == '/') { - state = SCE_C_COMMENTLINE; - } else if (ch == ''') { - state = SCE_C_CHARACTER; - } else if (isoperator(ch)) { - ColourTo(styler, i, SCE_C_OPERATOR, bInAsm); - } - } - } else { - if (state == SCE_C_PREPROCESSOR) { - if (ch=='}'){ - ColourTo(styler, i, state, bInAsm); - state = SCE_C_DEFAULT; - } else { - if ((ch == '\r' || ch == '\n') && !(chPrev == '\' || chPrev == '\r')) { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_DEFAULT; + if (strcmp(s2, "procedure") == 0 || + strcmp(s2, "function") == 0 || + strcmp(s2, "of") == 0 || + strcmp(s2, "var") == 0 || + strcmp(s2, "property") == 0 || + strcmp(s2, "operator") == 0) { + ignoreKeyword = true; } } - } else if (state == SCE_C_COMMENT) { - if (ch == '}' ) { - ColourTo(styler, i, state, bInAsm); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_COMMENTDOC) { - if (ch == ')' && chPrev == '*') { - if (((i > styler.GetStartSegment() + 2) || ( - (initStyle == SCE_C_COMMENTDOC) && - (styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) { - ColourTo(styler, i, state, bInAsm); - state = SCE_C_DEFAULT; - } - } - } else if (state == SCE_C_COMMENTLINE) { - if (ch == '\r' || ch == '\n') { - ColourTo(styler, i-1, state, bInAsm); - state = SCE_C_DEFAULT; - } - } else if (state == SCE_C_CHARACTER) { - if (ch == ''') { - ColourTo(styler, i, state, bInAsm); - state = SCE_C_DEFAULT; - } } } - chPrev = ch; + if (!ignoreKeyword) { + levelCurrent++; + } + } else if (strcmp(s, "interface") == 0) { + // "interface" keyword requires special handling... + bool ignoreKeyword = true; + unsigned int j = lastStart - 1; + char ch = styler.SafeGetCharAt(j); + while ((j >= startPos) && (IsASpaceOrTab(ch) || ch == '\r' || ch == '\n' || + IsStreamCommentStyle(styler.StyleAt(j)))) { + j--; + ch = styler.SafeGetCharAt(j); + } + if (j >= startPos && styler.SafeGetCharAt(j) == '=') { + ignoreKeyword = false; + } + if (!ignoreKeyword) { + levelCurrent++; + } + } else if (strcmp(s, "end") == 0) { + lineFoldStateCurrent &= ~stateFoldInRecord; + levelCurrent--; + if (levelCurrent < SC_FOLDLEVELBASE) { + levelCurrent = SC_FOLDLEVELBASE; + } } - ColourTo(styler, lengthDoc - 1, state, bInAsm); }
static void FoldPascalDoc(unsigned int startPos, int length, int initStyle, WordList *[], - Accessor &styler) { + Accessor &styler) { bool foldComment = styler.GetPropertyInt("fold.comment") != 0; bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; @@ -281,11 +503,13 @@ int lineCurrent = styler.GetLine(startPos); int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; int levelCurrent = levelPrev; + int lineFoldStateCurrent = lineCurrent > 0 ? styler.GetLineState(lineCurrent - 1) & stateFoldMaskAll : 0; char chNext = styler[startPos]; int styleNext = styler.StyleAt(startPos); int style = initStyle;
int lastStart = 0; + CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true);
for (unsigned int i = startPos; i < endPos; i++) { char ch = chNext; @@ -295,53 +519,45 @@ styleNext = styler.StyleAt(i + 1); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
- if (stylePrev != SCE_C_WORD && style == SCE_C_WORD) + if (foldComment && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelCurrent++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelCurrent--; + } + } + if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) { - // Store last word start point. - lastStart = i; + if (!IsCommentLine(lineCurrent - 1, styler) + && IsCommentLine(lineCurrent + 1, styler)) + levelCurrent++; + else if (IsCommentLine(lineCurrent - 1, styler) + && !IsCommentLine(lineCurrent+1, styler)) + levelCurrent--; } - - if (stylePrev == SCE_C_WORD) { - if(iswordchar(ch) && !iswordchar(chNext)) { - char s[100]; - getRange(lastStart, i, styler, s, sizeof(s)); - levelCurrent += classifyFoldPointPascal(s); + if (foldPreprocessor) { + if (style == SCE_PAS_PREPROCESSOR && ch == '{' && chNext == '$') { + ClassifyPascalPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 2, styler); + } else if (style == SCE_PAS_PREPROCESSOR2 && ch == '(' && chNext == '*' + && styler.SafeGetCharAt(i + 2) == '$') { + ClassifyPascalPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 3, styler); } }
- if (foldComment && (style == SCE_C_COMMENTLINE)) { - if ((ch == '/') && (chNext == '/')) { - char chNext2 = styler.SafeGetCharAt(i + 2); - if (chNext2 == '{') { - levelCurrent++; - } else if (chNext2 == '}') { - levelCurrent--; - } - } + if (stylePrev != SCE_PAS_WORD && style == SCE_PAS_WORD) + { + // Store last word start point. + lastStart = i; } - - if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) { - if (ch == '{' && chNext == '$') { - unsigned int j=i+2; // skip {$ - while ((j<endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { - j++; - } - if (styler.Match(j, "region") || styler.Match(j, "if")) { - levelCurrent++; - } else if (styler.Match(j, "end")) { - levelCurrent--; - } + if (stylePrev == SCE_PAS_WORD && !(lineFoldStateCurrent & stateFoldInPreprocessor)) { + if(setWord.Contains(ch) && !setWord.Contains(chNext)) { + ClassifyPascalWordFoldPoint(levelCurrent, lineFoldStateCurrent, startPos, endPos, lastStart, i, styler); } }
- if (foldComment && IsStreamCommentStyle(style)) { - if (!IsStreamCommentStyle(stylePrev)) { - levelCurrent++; - } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelCurrent--; - } - } + if (!IsASpace(ch)) + visibleChars++;
if (atEOL) { int lev = levelPrev; @@ -352,23 +568,24 @@ if (lev != styler.LevelAt(lineCurrent)) { styler.SetLevel(lineCurrent, lev); } + int newLineState = (styler.GetLineState(lineCurrent) & ~stateFoldMaskAll) | lineFoldStateCurrent; + styler.SetLineState(lineCurrent, newLineState); lineCurrent++; levelPrev = levelCurrent; visibleChars = 0; } - - if (!isspacechar(ch)) - visibleChars++; }
- // Fill in the real level of the next line, keeping the current flags as they will be filled in later - int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; - styler.SetLevel(lineCurrent, levelPrev | flagsNext); + // If we didn't reach the EOL in previous loop, store line level and whitespace information. + // The rest will be filled in later... + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + styler.SetLevel(lineCurrent, lev); }
static const char * const pascalWordListDesc[] = { "Keywords", - "Classwords", 0 };
Modified: trunk/scintilla/LexPerl.cxx =================================================================== --- trunk/scintilla/LexPerl.cxx 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/LexPerl.cxx 2009-05-03 17:49:33 UTC (rev 3769) @@ -247,8 +247,9 @@ static bool isMatch(const char *sref, char *s) { // match per-line delimiter - must kill trailing CR if CRLF - if (s[strlen(s) - 1] == '\r') - s[strlen(s) - 1] = '\0'; + int i = strlen(s); + if (i != 0 && s[i - 1] == '\r') + s[i - 1] = '\0'; return (strcmp(sref, s) == 0); }
@@ -569,7 +570,7 @@ sc.Forward(ws_skip + 1); HereDoc.Quote = delim_ch; HereDoc.Quoted = true; - } else if (ws_skip == 0 && setNonHereDoc.Contains(sc.chNext) + } else if ((ws_skip == 0 && setNonHereDoc.Contains(sc.chNext)) || ws_skip > 0) { // left shift << or <<= operator cases // restore position if operator @@ -1183,8 +1184,15 @@ bool foldComment = styler.GetPropertyInt("fold.comment") != 0; bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; // Custom folding of POD and packages + + // property fold.perl.pod + // Enable folding Pod blocks when using the Perl lexer. bool foldPOD = styler.GetPropertyInt("fold.perl.pod", 1) != 0; + + // property fold.perl.package + // Enable folding packages when using the Perl lexer. bool foldPackage = styler.GetPropertyInt("fold.perl.package", 1) != 0; + unsigned int endPos = startPos + length; int visibleChars = 0; int lineCurrent = styler.GetLine(startPos);
Modified: trunk/scintilla/LexPython.cxx =================================================================== --- trunk/scintilla/LexPython.cxx 2009-05-02 19:12:15 UTC (rev 3768) +++ trunk/scintilla/LexPython.cxx 2009-05-03 17:49:33 UTC (rev 3769) @@ -24,17 +24,27 @@ using namespace Scintilla; #endif
-enum kwType { kwOther, kwClass, kwDef, kwImport }; +/* kwCDef, kwCTypeName only used for Cython */ +enum kwType { kwOther, kwClass, kwDef, kwImport, kwCDef, kwCTypeName }; + static const int indicatorWhitespace = 1;
static bool IsPyComment(Accessor &styler, int pos, int len) { return len > 0 && styler[pos] == '#'; }
-static bool IsPyStringStart(int ch, int chNext, int chNext2) { +enum literalsAllowed { litNone=0, litU=1, litB=2}; + +static bool IsPyStringTypeChar(int ch, literalsAllowed allowed) { + return + ((allowed & litB) && (ch == 'b' || ch == 'B')) || + ((allowed & litU) && (ch == 'u' || ch == 'U')); +} + +static bool IsPyStringStart(int ch, int chNext, int chNext2, literalsAllowed allowed) { if (ch == ''' || ch == '"') return true; - if (ch == 'u' || ch == 'U') { + if (IsPyStringTypeChar(ch, allowed)) { if (chNext == '"' || chNext == ''') return true; if ((chNext == 'r' || chNext == 'R') && (chNext2 == '"' || chNext2 == ''')) @@ -47,16 +57,16 @@ }
/* Return the state to use for the string starting at i; *nextIndex will be set to the first index following the quote(s) */ -static int GetPyStringState(Accessor &styler, int i, unsigned int *nextIndex) { +static int GetPyStringState(Accessor &styler, int i, unsigned int *nextIndex, literalsAllowed allowed) { char ch = styler.SafeGetCharAt(i); char chNext = styler.SafeGetCharAt(i + 1);
- // Advance beyond r, u, or ur prefix, but bail if there are any unexpected chars + // Advance beyond r, u, or ur prefix (or r, b, or br in Python 3.0), but bail if there are any unexpected chars if (ch == 'r' || ch == 'R') { i++; ch = styler.SafeGetCharAt(i); chNext = styler.SafeGetCharAt(i + 1); - } else if (ch == 'u' || ch == 'U') { + } else if (IsPyStringTypeChar(ch, allowed)) { if (chNext == 'r' || chNext == 'R') i += 2; else @@ -96,7 +106,7 @@ }
static void ColourisePyDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { + WordList *keywordlists[], Accessor &styler) {
int endPos = startPos + length;
@@ -105,19 +115,49 @@ if (startPos > 0) { if (lineCurrent > 0) { lineCurrent--; + // Look for backslash-continued lines + while (lineCurrent > 0) { + int eolPos = styler.LineStart(lineCurrent) - 1; + int eolStyle = styler.StyleAt(eolPos); + if (eolStyle == SCE_P_STRING + || eolStyle == SCE_P_CHARACTER + || eolStyle == SCE_P_STRINGEOL) { + lineCurrent -= 1; + } else { + break; + } + } startPos = styler.LineStart(lineCurrent); - if (startPos == 0) - initStyle = SCE_P_DEFAULT; - else - initStyle = styler.StyleAt(startPos - 1); } + initStyle = startPos == 0 ? SCE_P_DEFAULT : styler.StyleAt(startPos - 1); }
WordList &keywords = *keywordlists[0]; WordList &keywords2 = *keywordlists[1];
+ // property tab.timmy.whinge.level + // For Python code, checks whether indenting is consistent. + // The default, 0 turns off indentation checking, + // 1 checks whether each line is potentially inconsistent with the previous line, + // 2 checks whether any space characters occur before a tab character in the indentation, + // 3 checks whether any spaces are in the indentation, and + // 4 checks for any tab characters in the indentation. + // 1 is a good level to use. const int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level");
+ // property lexer.python.literals.binary + // Set to 0 to not recognise Python 3 binary and octal literals: 0b1011 0o712. + bool base2or8Literals = styler.GetPropertyInt("lexer.python.literals.binary", 1) != 0; + + // property lexer.python.strings.u + // Set to 0 to not recognise Python Unicode literals u"x" as used before Python 3. + literalsAllowed allowedLiterals = (styler.GetPropertyInt("lexer.python.strings.u", 1)) ? litU : litNone; + + // property lexer.python.strings.b + // Set to 0 to not recognise Python 3 bytes literals b"x". + if (styler.GetPropertyInt("lexer.python.strings.b", 1)) + allowedLiterals = static_cast<literalsAllowed>(allowedLiterals | litB); + initStyle = initStyle & 31; if (initStyle == SCE_P_STRINGEOL) { initStyle = SCE_P_DEFAULT; @@ -126,12 +166,13 @@ kwType kwLast = kwOther; int spaceFlags = 0; styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment); - bool hexadecimal = false; + bool base_n_number = false;
StyleContext sc(startPos, endPos - startPos, initStyle, styler);
bool indentGood = true; int startIndicator = sc.currentPos; + bool inContinuedString = false;
for (; sc.More(); sc.Forward()) {
@@ -163,8 +204,12 @@ } lineCurrent++; if ((sc.state == SCE_P_STRING) || (sc.state == SCE_P_CHARACTER)) { - sc.ChangeState(SCE_P_STRINGEOL); - sc.ForwardSetState(SCE_P_DEFAULT); + if (inContinuedString) { + inContinuedString = false; + } else { + sc.ChangeState(SCE_P_STRINGEOL); + sc.ForwardSetState(SCE_P_DEFAULT); + } } if (!sc.More()) break; @@ -178,7 +223,7 @@ sc.SetState(SCE_P_DEFAULT); } else if (sc.state == SCE_P_NUMBER) { if (!IsAWordChar(sc.ch) && - !(!hexadecimal && ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) { + !(!base_n_number && ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) { sc.SetState(SCE_P_DEFAULT); } } else if (sc.state == SCE_P_IDENTIFIER) { @@ -194,6 +239,23 @@ style = SCE_P_CLASSNAME; } else if (kwLast == kwDef) { style = SCE_P_DEFNAME; + } else if (kwLast == kwCDef) { + int pos = sc.currentPos; + unsigned char ch = styler.SafeGetCharAt(pos, '\0'); + while (ch != '\0') { + if (ch == '(') { + style = SCE_P_DEFNAME; + break; + } else if (ch == ':') { + style = SCE_P_CLASSNAME; + break; + } else if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') { + pos++; + ch = styler.SafeGetCharAt(pos, '\0'); + } else { + break; + } + } } else if (keywords2.InList(s)) { style = SCE_P_WORD2; } @@ -206,9 +268,13 @@ kwLast = kwDef; else if (0 == strcmp(s, "import")) kwLast = kwImport; - else + else if (0 == strcmp(s, "cdef")) + kwLast = kwCDef; + else if (0 == strcmp(s, "cimport")) + kwLast = kwImport; + else if (kwLast != kwCDef) kwLast = kwOther; - } else { + } else if (kwLast != kwCDef) { kwLast = kwOther; } } @@ -225,7 +291,12 @@ if ((sc.chNext == '\r') && (sc.GetRelative(2) == '\n')) { sc.Forward(); } - sc.Forward(); + if (sc.chNext == '\n' || sc.chNext == '\r') {
@@ Diff output truncated at 100000 characters. @@
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.