in ext/scintilla/lexers/LexBaan.cxx [729:986]
void SCI_METHOD LexerBaan::Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) {
if (!options.fold)
return;
char word[100];
int wordlen = 0;
bool foldStart = true;
bool foldNextSelect = true;
bool afterFunctionSection = false;
bool beforeDeclarationSection = false;
int currLineStyle = 0;
int nextLineStyle = 0;
std::string startTags[6] = { "for", "if", "on", "repeat", "select", "while" };
std::string endTags[6] = { "endcase", "endfor", "endif", "endselect", "endwhile", "until" };
std::string selectCloseTags[5] = { "selectdo", "selecteos", "selectempty", "selecterror", "endselect" };
LexAccessor styler(pAccess);
Sci_PositionU endPos = startPos + length;
int visibleChars = 0;
Sci_Position lineCurrent = styler.GetLine(startPos);
// Backtrack to previous line in case need to fix its fold status
if (startPos > 0) {
if (lineCurrent > 0) {
lineCurrent--;
startPos = styler.LineStart(lineCurrent);
}
}
int levelPrev = SC_FOLDLEVELBASE;
if (lineCurrent > 0)
levelPrev = styler.LevelAt(lineCurrent - 1) >> 16;
int levelCurrent = levelPrev;
char chNext = styler[startPos];
int style = initStyle;
int styleNext = styler.StyleAt(startPos);
for (Sci_PositionU i = startPos; i < endPos; i++) {
char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
style = styleNext;
styleNext = styler.StyleAt(i + 1);
int stylePrev = (i) ? styler.StyleAt(i - 1) : SCE_BAAN_DEFAULT;
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
// Comment folding
if (options.foldComment && style == SCE_BAAN_COMMENTDOC) {
if (style != stylePrev) {
levelCurrent++;
}
else if (style != styleNext) {
levelCurrent--;
}
}
if (options.foldComment && atEOL && IsCommentLine(lineCurrent, styler)) {
if (!IsCommentLine(lineCurrent - 1, styler)
&& IsCommentLine(lineCurrent + 1, styler))
levelCurrent++;
else if (IsCommentLine(lineCurrent - 1, styler)
&& !IsCommentLine(lineCurrent + 1, styler))
levelCurrent--;
}
// PreProcessor Folding
if (options.foldPreprocessor) {
if (atEOL && IsPreProcLine(lineCurrent, styler)) {
if (!IsPreProcLine(lineCurrent - 1, styler)
&& IsPreProcLine(lineCurrent + 1, styler))
levelCurrent++;
else if (IsPreProcLine(lineCurrent - 1, styler)
&& !IsPreProcLine(lineCurrent + 1, styler))
levelCurrent--;
}
else if (style == SCE_BAAN_PREPROCESSOR) {
// folds #ifdef/#if/#ifndef - they are not part of the IsPreProcLine folding.
if (ch == '#') {
if (styler.Match(i, "#ifdef") || styler.Match(i, "#if") || styler.Match(i, "#ifndef")
|| styler.Match(i, "#context_on"))
levelCurrent++;
else if (styler.Match(i, "#endif") || styler.Match(i, "#context_off"))
levelCurrent--;
}
}
}
//Syntax Folding
if (options.baanFoldSyntaxBased && (style == SCE_BAAN_OPERATOR)) {
if (ch == '{' || ch == '(') {
levelCurrent++;
}
else if (ch == '}' || ch == ')') {
levelCurrent--;
}
}
//Keywords Folding
if (options.baanFoldKeywordsBased) {
if (atEOL && IsDeclarationLine(lineCurrent, styler)) {
if (!IsDeclarationLine(lineCurrent - 1, styler)
&& IsDeclarationLine(lineCurrent + 1, styler))
levelCurrent++;
else if (IsDeclarationLine(lineCurrent - 1, styler)
&& !IsDeclarationLine(lineCurrent + 1, styler))
levelCurrent--;
}
else if (style == SCE_BAAN_WORD) {
word[wordlen++] = static_cast<char>(MakeLowerCase(ch));
if (wordlen == 100) { // prevent overflow
word[0] = '\0';
wordlen = 1;
}
if (styleNext != SCE_BAAN_WORD) {
word[wordlen] = '\0';
wordlen = 0;
if (strcmp(word, "for") == 0) {
Sci_PositionU j = i + 1;
while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
j++;
}
if (styler.Match(j, "update")) {
// Means this is a "for update" used by Select which is already folded.
foldStart = false;
}
}
else if (strcmp(word, "on") == 0) {
Sci_PositionU j = i + 1;
while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
j++;
}
if (!styler.Match(j, "case")) {
// Means this is not a "on Case" statement... could be "on" used by index.
foldStart = false;
}
}
else if (strcmp(word, "select") == 0) {
if (foldNextSelect) {
// Next Selects are sub-clause till reach of selectCloseTags[] array.
foldNextSelect = false;
foldStart = true;
}
else {
foldNextSelect = false;
foldStart = false;
}
}
else if (wordInArray(word, selectCloseTags, 5)) {
// select clause ends, next select clause can be folded.
foldNextSelect = true;
foldStart = true;
}
else {
foldStart = true;
}
if (foldStart) {
if (wordInArray(word, startTags, 6)) {
levelCurrent++;
}
else if (wordInArray(word, endTags, 6)) {
levelCurrent--;
}
}
}
}
}
// Fold inner level of if/select/case statements
if (options.baanFoldInnerLevel && atEOL) {
bool currLineInnerLevel = IsInnerLevelFold(lineCurrent, styler);
bool nextLineInnerLevel = IsInnerLevelFold(lineCurrent + 1, styler);
if (currLineInnerLevel && currLineInnerLevel != nextLineInnerLevel) {
levelCurrent++;
}
else if (nextLineInnerLevel && nextLineInnerLevel != currLineInnerLevel) {
levelCurrent--;
}
}
// Section Foldings.
// One way of implementing Section Foldings, as there is no END markings of sections.
// first section ends on the previous line of next section.
// Re-written whole folding to accomodate this.
if (options.baanFoldSections && atEOL) {
currLineStyle = mainOrSubSectionLine(lineCurrent, styler);
nextLineStyle = mainOrSubSectionLine(lineCurrent + 1, styler);
if (currLineStyle != 0 && currLineStyle != nextLineStyle) {
if (levelCurrent < levelPrev)
--levelPrev;
for (Sci_Position j = styler.LineStart(lineCurrent); j < styler.LineStart(lineCurrent + 1) - 1; j++) {
if (IsASpaceOrTab(styler[j]))
continue;
else if (styler.StyleAt(j) == SCE_BAAN_WORD5) {
if (styler.Match(j, "functions:")) {
// Means functions: is the end of MainSections.
// Nothing to fold after this.
afterFunctionSection = true;
break;
}
else {
afterFunctionSection = false;
break;
}
}
else {
afterFunctionSection = false;
break;
}
}
if (!afterFunctionSection)
levelCurrent++;
}
else if (nextLineStyle != 0 && currLineStyle != nextLineStyle
&& (priorSectionIsSubSection(lineCurrent -1 ,styler)
|| !nextSectionIsSubSection(lineCurrent + 1, styler))) {
for (Sci_Position j = styler.LineStart(lineCurrent + 1); j < styler.LineStart(lineCurrent + 1 + 1) - 1; j++) {
if (IsASpaceOrTab(styler[j]))
continue;
else if (styler.StyleAt(j) == SCE_BAAN_WORD5) {
if (styler.Match(j, "declaration:")) {
// Means declaration: is the start of MainSections.
// Nothing to fold before this.
beforeDeclarationSection = true;
break;
}
else {
beforeDeclarationSection = false;
break;
}
}
else {
beforeDeclarationSection = false;
break;
}
}
if (!beforeDeclarationSection) {
levelCurrent--;
if (nextLineStyle == SCE_BAAN_WORD5 && priorSectionIsSubSection(lineCurrent-1, styler))
// next levelCurrent--; is to unfold previous subsection fold.
// On reaching the next main section, the previous main as well sub section ends.
levelCurrent--;
}
}
}
if (atEOL) {
int lev = levelPrev;
lev |= levelCurrent << 16;
if (visibleChars == 0 && options.foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
if ((levelCurrent > levelPrev) && (visibleChars > 0))
lev |= SC_FOLDLEVELHEADERFLAG;
if (lev != styler.LevelAt(lineCurrent)) {
styler.SetLevel(lineCurrent, lev);
}
lineCurrent++;
levelPrev = levelCurrent;
visibleChars = 0;
}
if (!isspacechar(ch))
visibleChars++;
}
int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}