aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornyamatongwe <unknown>2002-11-08 23:32:26 +0000
committernyamatongwe <unknown>2002-11-08 23:32:26 +0000
commitacc2ca9bc97b5469b53df8ffa7db1519b43d3072 (patch)
tree0b946a7a0812469e7fd3bcc42dde7ba34a331c6a
parent6d19142a58b6820750096c2b99af987bc38c53f2 (diff)
downloadscintilla-mirror-acc2ca9bc97b5469b53df8ffa7db1519b43d3072.tar.gz
Patch to add fold level boxing from Wilhelm Pflueger.
-rw-r--r--include/Scintilla.h10
-rw-r--r--include/Scintilla.iface14
-rw-r--r--src/Editor.cxx58
-rw-r--r--src/LexCPP.cxx280
4 files changed, 332 insertions, 30 deletions
diff --git a/include/Scintilla.h b/include/Scintilla.h
index 3199aa20d..f81646e39 100644
--- a/include/Scintilla.h
+++ b/include/Scintilla.h
@@ -340,6 +340,10 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SC_FOLDLEVELBASE 0x400
#define SC_FOLDLEVELWHITEFLAG 0x1000
#define SC_FOLDLEVELHEADERFLAG 0x2000
+#define SC_FOLDLEVELBOXHEADERFLAG 0x4000
+#define SC_FOLDLEVELBOXFOOTERFLAG 0x8000
+#define SC_FOLDLEVELCONTRACTED 0x10000
+#define SC_FOLDLEVELUNINDENT 0x20000
#define SC_FOLDLEVELNUMBERMASK 0x0FFF
#define SCI_SETFOLDLEVEL 2222
#define SCI_GETFOLDLEVEL 2223
@@ -352,6 +356,12 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_GETFOLDEXPANDED 2230
#define SCI_TOGGLEFOLD 2231
#define SCI_ENSUREVISIBLE 2232
+#define SC_FOLDFLAG_LINEBEFORE_EXPANDED 0x0002
+#define SC_FOLDFLAG_LINEBEFORE_CONTRACTED 0x0004
+#define SC_FOLDFLAG_LINEAFTER_EXPANDED 0x0008
+#define SC_FOLDFLAG_LINEAFTER_CONTRACTED 0x0010
+#define SC_FOLDFLAG_LEVELNUMBERS 0x0040
+#define SC_FOLDFLAG_BOX 0x0001
#define SCI_SETFOLDFLAGS 2233
#define SCI_ENSUREVISIBLEENFORCEPOLICY 2234
#define SCI_SETTABINDENTS 2260
diff --git a/include/Scintilla.iface b/include/Scintilla.iface
index cd1bacb70..ce6d8ea53 100644
--- a/include/Scintilla.iface
+++ b/include/Scintilla.iface
@@ -877,6 +877,10 @@ enu FoldLevel=SC_FOLDLEVEL
val SC_FOLDLEVELBASE=0x400
val SC_FOLDLEVELWHITEFLAG=0x1000
val SC_FOLDLEVELHEADERFLAG=0x2000
+val SC_FOLDLEVELBOXHEADERFLAG=0x4000
+val SC_FOLDLEVELBOXFOOTERFLAG=0x8000
+val SC_FOLDLEVELCONTRACTED=0x10000
+val SC_FOLDLEVELUNINDENT=0x20000
val SC_FOLDLEVELNUMBERMASK=0x0FFF
# Set the fold level of a line.
@@ -914,7 +918,15 @@ fun void ToggleFold=2231(int line,)
# Ensure a particular line is visible by expanding any header line hiding it.
fun void EnsureVisible=2232(int line,)
-# Set some debugging options for folding.
+enu FoldFlag=SC_FOLDFLAG_
+val SC_FOLDFLAG_LINEBEFORE_EXPANDED=0x0002
+val SC_FOLDFLAG_LINEBEFORE_CONTRACTED=0x0004
+val SC_FOLDFLAG_LINEAFTER_EXPANDED=0x0008
+val SC_FOLDFLAG_LINEAFTER_CONTRACTED=0x0010
+val SC_FOLDFLAG_LEVELNUMBERS=0x0040
+val SC_FOLDFLAG_BOX=0x0001
+
+# Set some style options for folding.
fun void SetFoldFlags=2233(int flags,)
# Ensure a particular line is visible by expanding any header line hiding it.
diff --git a/src/Editor.cxx b/src/Editor.cxx
index a3b46bf5e..76ba18565 100644
--- a/src/Editor.cxx
+++ b/src/Editor.cxx
@@ -1458,7 +1458,7 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {
number[0] = '\0';
if (firstSubLine)
sprintf(number, "%d", lineDoc + 1);
- if (foldFlags & 64)
+ if (foldFlags & SC_FOLDFLAG_LEVELNUMBERS)
sprintf(number, "%X", pdoc->GetLevel(lineDoc));
PRectangle rcNumber = rcMarker;
// Right justify
@@ -2190,19 +2190,61 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
ll->RestoreBracesHighlight(rangeLine, braces);
bool expanded = cs.GetExpanded(lineDoc);
- if ( (expanded && (foldFlags & 2)) || (!expanded && (foldFlags & 4)) ) {
- if (pdoc->GetLevel(lineDoc) & SC_FOLDLEVELHEADERFLAG) {
+ if ((foldFlags & SC_FOLDFLAG_BOX) == 0) {
+ // Paint the line above the fold
+ if ((expanded && (foldFlags & SC_FOLDFLAG_LINEBEFORE_EXPANDED))
+ ||
+ (!expanded && (foldFlags & SC_FOLDFLAG_LINEBEFORE_CONTRACTED))) {
+ if (pdoc->GetLevel(lineDoc) & SC_FOLDLEVELHEADERFLAG) {
+ PRectangle rcFoldLine = rcLine;
+ rcFoldLine.bottom = rcFoldLine.top + 1;
+ surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated);
+ }
+ }
+ // Paint the line below the fold
+ if ((expanded && (foldFlags & SC_FOLDFLAG_LINEAFTER_EXPANDED))
+ ||
+ (!expanded && (foldFlags & SC_FOLDFLAG_LINEAFTER_CONTRACTED))) {
+ if (pdoc->GetLevel(lineDoc) & SC_FOLDLEVELHEADERFLAG) {
+ PRectangle rcFoldLine = rcLine;
+ rcFoldLine.top = rcFoldLine.bottom - 1;
+ surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated);
+ }
+ }
+ } else {
+ int FoldLevelCurr = (pdoc->GetLevel(lineDoc) & SC_FOLDLEVELNUMBERMASK) - SC_FOLDLEVELBASE;
+ int FoldLevelPrev = (pdoc->GetLevel(lineDoc-1) & SC_FOLDLEVELNUMBERMASK) - SC_FOLDLEVELBASE;
+ int FoldLevelFlags = (pdoc->GetLevel(lineDoc) & ~SC_FOLDLEVELNUMBERMASK);
+ int indentationStep = (pdoc->indentInChars ? pdoc->indentInChars : pdoc->tabInChars);
+ // Draw line above fold
+ if ((FoldLevelPrev < FoldLevelCurr)
+ ||
+ (FoldLevelFlags & SC_FOLDLEVELBOXHEADERFLAG
+ &&
+ (pdoc->GetLevel(lineDoc-1) & SC_FOLDLEVELBOXFOOTERFLAG) == 0)) {
PRectangle rcFoldLine = rcLine;
rcFoldLine.bottom = rcFoldLine.top + 1;
+ rcFoldLine.left += xStart + FoldLevelCurr * vs.spaceWidth * indentationStep - 1;
surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated);
}
- }
- if ( (expanded && (foldFlags & 8)) || (!expanded && (foldFlags & 16)) ) {
- if (pdoc->GetLevel(lineDoc) & SC_FOLDLEVELHEADERFLAG) {
+
+ // Line below the fold (or below a contracted fold)
+ if (FoldLevelFlags & SC_FOLDLEVELBOXFOOTERFLAG
+ ||
+ (!expanded && (foldFlags & SC_FOLDFLAG_LINEAFTER_CONTRACTED))) {
PRectangle rcFoldLine = rcLine;
rcFoldLine.top = rcFoldLine.bottom - 1;
+ rcFoldLine.left += xStart + (FoldLevelCurr)* vs.spaceWidth * indentationStep - 1;
surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated);
}
+
+ PRectangle rcBoxLine = rcLine;
+ // Draw vertical line for every fold level
+ for (int i = 0; i <= FoldLevelCurr; i++) {
+ rcBoxLine.left = xStart + i * vs.spaceWidth * indentationStep - 1;
+ rcBoxLine.right = rcBoxLine.left + 1;
+ surface->FillRectangle(rcBoxLine, vs.styles[STYLE_DEFAULT].fore.allocated);
+ }
}
// Draw the Caret
@@ -3359,10 +3401,10 @@ int Editor::KeyCommand(unsigned int iMessage) {
SetLastXChosen();
break;
case SCI_PAGEUP:
- PageMove( -1);
+ PageMove(-1);
break;
case SCI_PAGEUPEXTEND:
- PageMove( -1, true);
+ PageMove(-1, true);
break;
case SCI_PAGEDOWN:
PageMove(1);
diff --git a/src/LexCPP.cxx b/src/LexCPP.cxx
index ab8316949..661b968cd 100644
--- a/src/LexCPP.cxx
+++ b/src/LexCPP.cxx
@@ -20,6 +20,9 @@
#include "Scintilla.h"
#include "SciLexer.h"
+#define KEYWORD_BOXHEADER 1
+#define KEYWORD_FOLDCONTRACTED 2
+
static bool IsOKBeforeRE(const int ch) {
return (ch == '(') || (ch == '=') || (ch == ',');
}
@@ -34,17 +37,17 @@ static inline bool IsAWordStart(const int ch) {
static inline bool IsADoxygenChar(const int ch) {
return (islower(ch) || ch == '$' || ch == '@' ||
- ch == '\\' || ch == '&' || ch == '<' ||
- ch == '>' || ch == '#' || ch == '{' ||
- ch == '}' || ch == '[' || ch == ']');
+ ch == '\\' || ch == '&' || ch == '<' ||
+ ch == '>' || ch == '#' || ch == '{' ||
+ ch == '}' || ch == '[' || ch == ']');
}
static inline bool IsStateComment(const int state) {
return ((state == SCE_C_COMMENT) ||
- (state == SCE_C_COMMENTLINE) ||
- (state == SCE_C_COMMENTDOC) ||
- (state == SCE_C_COMMENTDOCKEYWORD) ||
- (state == SCE_C_COMMENTDOCKEYWORDERROR));
+ (state == SCE_C_COMMENTLINE) ||
+ (state == SCE_C_COMMENTDOC) ||
+ (state == SCE_C_COMMENTDOCKEYWORD) ||
+ (state == SCE_C_COMMENTDOCKEYWORDERROR));
}
static inline bool IsStateString(const int state) {
@@ -150,7 +153,7 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo
} else {
sc.GetCurrentLowered(s, sizeof(s));
}
- if (!isspace(sc.ch) || !keywords3.InList(s+1)) {
+ if (!isspace(sc.ch) || !keywords3.InList(s + 1)) {
sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
}
sc.SetState(SCE_C_COMMENTDOC);
@@ -271,12 +274,233 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo
static bool IsStreamCommentStyle(int style) {
return style == SCE_C_COMMENT ||
- style == SCE_C_COMMENTDOC ||
- style == SCE_C_COMMENTDOCKEYWORD ||
- style == SCE_C_COMMENTDOCKEYWORDERROR;
+ style == SCE_C_COMMENTDOC ||
+ style == SCE_C_COMMENTDOCKEYWORD ||
+ style == SCE_C_COMMENTDOCKEYWORDERROR;
+}
+
+static bool matchKeyword(unsigned int start, WordList &keywords, Accessor &styler, int keywordtype) {
+ bool FoundKeyword = false;
+
+ for (unsigned int i = 0;
+ strlen(keywords[i]) > 0 && !FoundKeyword;
+ i++) {
+ if (atoi(keywords[i]) == keywordtype) {
+ FoundKeyword = styler.Match(start, ((char *)keywords[i]) + 2);
+ }
+ }
+ return FoundKeyword;
+}
+
+static bool IsCommentLine(int line, Accessor &styler) {
+ unsigned int Pos = styler.LineStart(line);
+ while (styler.GetLine(Pos) == line) {
+ int PosStyle = styler.StyleAt(Pos);
+
+ if ( !IsStreamCommentStyle(PosStyle)
+ &&
+ PosStyle != SCE_C_COMMENTLINEDOC
+ &&
+ PosStyle != SCE_C_COMMENTLINE
+ &&
+ !IsASpace(styler.SafeGetCharAt(Pos))
+ )
+ return false;
+ Pos++;
+ }
+
+ return true;
}
-static void FoldCppDoc(unsigned int startPos, int length, int initStyle, WordList *[],
+static void FoldBoxCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+
+ WordList &keywords4 = *keywordlists[3];
+
+ bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+ bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
+ bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+ bool firstLine = true;
+ unsigned int endPos = startPos + length;
+ int visibleChars = 0;
+ int lineCurrent = styler.GetLine(startPos);
+ int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
+ int levelCurrent = levelPrev;
+ int levelPrevPrev;
+ int levelFlags = 0;
+ int levelUnindent = 0;
+ char chNext = styler[startPos];
+ int styleNext = styler.StyleAt(startPos);
+ int style = initStyle;
+
+ if (lineCurrent == 0) {
+ levelPrevPrev = levelPrev;
+ } else {
+ levelPrevPrev = styler.LevelAt(lineCurrent - 1) & SC_FOLDLEVELNUMBERMASK;
+ }
+
+ for (unsigned int i = startPos; i < endPos; i++) {
+ char ch = chNext;
+ chNext = styler.SafeGetCharAt(i + 1);
+ int stylePrev = style;
+ style = styleNext;
+ styleNext = styler.StyleAt(i + 1);
+
+ bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+
+ 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 && (style == SCE_C_COMMENTLINE)) {
+ if ((ch == '/') && (chNext == '/')) {
+ char chNext2 = styler.SafeGetCharAt(i + 2);
+ if (chNext2 == '{') {
+ levelCurrent++;
+ } else if (chNext2 == '}') {
+ levelCurrent--;
+ }
+ }
+ }
+
+ if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) {
+ if (ch == '#') {
+ unsigned int j = i + 1;
+ 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 (style == SCE_C_OPERATOR
+ ||
+ style == SCE_C_COMMENT
+ ||
+ style == SCE_C_COMMENTLINE) {
+
+ if (ch == '{') {
+ levelCurrent++;
+ // Special handling if line has closing brace followed by opening brace.
+ if (levelCurrent == levelPrev) {
+ if (firstLine)
+ levelUnindent = 1;
+ else
+ levelUnindent = -1;
+ }
+ } else if (ch == '}') {
+ levelCurrent--;
+ }
+ }
+
+ /* Check for fold header keyword at beginning of word */
+ if ((style == SCE_C_WORD || style == SCE_C_COMMENT || style == SCE_C_COMMENTLINE)
+ &&
+ (style != stylePrev)) {
+ if (matchKeyword(i, keywords4, styler, KEYWORD_BOXHEADER)) {
+ int line;
+ /* Loop backwards all empty or comment lines */
+ for (line = lineCurrent - 1;
+ line >= 0
+ &&
+ levelCurrent == (styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK)
+ &&
+ (styler.LevelAt(line) & SC_FOLDLEVELBOXFOOTERFLAG) == 0
+ &&
+ IsCommentLine(line, styler);
+ line--) {
+ /* just loop backwards */;
+ }
+
+ line++;
+ /* Set Box header flag (if the previous line has no footer line) */
+ if ((styler.LevelAt(line) & SC_FOLDLEVELBOXFOOTERFLAG) == 0) {
+ if (line == lineCurrent) {
+ /* in current line */
+ levelFlags |= SC_FOLDLEVELBOXHEADERFLAG;
+ } else {
+ /* at top of all preceding comment lines */
+ styler.SetLevel(line, styler.LevelAt(line)
+ | SC_FOLDLEVELBOXHEADERFLAG);
+ }
+ }
+ }
+ }
+
+ if (matchKeyword(i, keywords4, styler, KEYWORD_FOLDCONTRACTED)) {
+ levelFlags |= SC_FOLDLEVELCONTRACTED;
+ }
+
+ if (atEOL) {
+ int lev;
+ // Compute level correction for special case: '} else {'
+ if (levelUnindent < 0) {
+ levelPrev += levelUnindent;
+ } else {
+ levelCurrent += levelUnindent;
+ }
+
+ lev = levelPrev;
+ if (visibleChars == 0 && foldCompact)
+ lev |= SC_FOLDLEVELWHITEFLAG;
+ // Produce additional footer line (e.g. after closed if)
+ if (visibleChars == 0
+ &&
+ (levelPrev < levelPrevPrev))
+ lev |= SC_FOLDLEVELBOXFOOTERFLAG;
+ // Produce footer line at line before (special handling for '} else {'
+ if (levelPrev < levelPrevPrev) {
+ styler.SetLevel(lineCurrent - 1,
+ styler.LevelAt(lineCurrent - 1) | SC_FOLDLEVELBOXFOOTERFLAG);
+ }
+ // Mark the fold header (the line that is always visible)
+ if ((levelCurrent > levelPrev) && (visibleChars > 0))
+ lev |= SC_FOLDLEVELHEADERFLAG;
+ // Show a footer line at end of fold
+ if (levelCurrent < levelPrev)
+ lev |= SC_FOLDLEVELBOXFOOTERFLAG;
+ /* Show a footer line at the end of each procedure (level == SC_FOLDLEVELBASE) */
+ if ((levelPrev == SC_FOLDLEVELBASE)
+ &&
+ (levelPrevPrev > SC_FOLDLEVELBASE)
+ &&
+ (visibleChars == 0)) {
+ lev |= SC_FOLDLEVELBOXFOOTERFLAG;
+ }
+
+ lev |= levelFlags;
+ if (lev != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, lev);
+ }
+
+ lineCurrent++;
+ levelPrevPrev = levelPrev;
+ levelPrev = levelCurrent;
+ levelUnindent = 0;
+ visibleChars = 0;
+ levelFlags = 0;
+ firstLine = false;
+ }
+
+ if (!isspacechar(ch))
+ visibleChars++;
+ }
+ // Fill in the real level of the next line, keeping the current flags as they will be filled in later
+ int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
+ styler.SetLevel(lineCurrent, levelPrev | flagsNext);
+}
+
+static void FoldNoBoxCppDoc(unsigned int startPos, int length, int initStyle,
Accessor &styler) {
bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
@@ -316,8 +540,8 @@ static void FoldCppDoc(unsigned int startPos, int length, int initStyle, WordLis
}
if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) {
if (ch == '#') {
- unsigned int j=i+1;
- while ((j<endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
+ unsigned int j = i + 1;
+ while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
j++;
}
if (styler.Match(j, "region") || styler.Match(j, "if")) {
@@ -355,20 +579,34 @@ static void FoldCppDoc(unsigned int startPos, int length, int initStyle, WordLis
styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}
+static void FoldCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+
+ int foldFlags = styler.GetPropertyInt("fold.flags") ;
+ bool foldBox = ((foldFlags & SC_FOLDFLAG_BOX) == SC_FOLDFLAG_BOX);
+
+ if (foldBox) {
+ FoldBoxCppDoc(startPos, length, initStyle, keywordlists, styler);
+ } else {
+ FoldNoBoxCppDoc(startPos, length, initStyle, styler);
+ }
+}
+
static const char * const cppWordLists[] = {
- "Primary keywords and identifiers",
- "Secondary keywords and identifiers",
- "Documentation comment keywords",
- 0,
-};
+ "Primary keywords and identifiers",
+ "Secondary keywords and identifiers",
+ "Documentation comment keywords",
+ "Fold header keywords",
+ 0,
+ };
static void ColouriseCppDocSensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
- Accessor &styler) {
+ Accessor &styler) {
ColouriseCppDoc(startPos, length, initStyle, keywordlists, styler, true);
}
static void ColouriseCppDocInsensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
- Accessor &styler) {
+ Accessor &styler) {
ColouriseCppDoc(startPos, length, initStyle, keywordlists, styler, false);
}