diff options
| author | nyamatongwe <unknown> | 2002-11-08 23:32:26 +0000 | 
|---|---|---|
| committer | nyamatongwe <unknown> | 2002-11-08 23:32:26 +0000 | 
| commit | acc2ca9bc97b5469b53df8ffa7db1519b43d3072 (patch) | |
| tree | 0b946a7a0812469e7fd3bcc42dde7ba34a331c6a /src | |
| parent | 6d19142a58b6820750096c2b99af987bc38c53f2 (diff) | |
| download | scintilla-mirror-acc2ca9bc97b5469b53df8ffa7db1519b43d3072.tar.gz | |
Patch to add fold level boxing from Wilhelm Pflueger.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Editor.cxx | 58 | ||||
| -rw-r--r-- | src/LexCPP.cxx | 280 | 
2 files changed, 309 insertions, 29 deletions
| 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);  } | 
