diff options
author | Marko Njezic <devnull@localhost> | 2011-07-02 13:41:25 +0200 |
---|---|---|
committer | Marko Njezic <devnull@localhost> | 2011-07-02 13:41:25 +0200 |
commit | f650e7fd9d5596e6c165e02ca5defdb4afc90131 (patch) | |
tree | 7c7d85628f2e6f4bf4d57df30f28e5534ca9d1cc /src | |
parent | 5b3778ece55a12878d505bc4c5bf687206cc2713 (diff) | |
download | scintilla-mirror-f650e7fd9d5596e6c165e02ca5defdb4afc90131.tar.gz |
Folding related fixes. Initiated by bug #3323805.
Make fold highlighting follow closely the actual folding implementation.
Introduce a concept of fold headers with a tail to accommodate certain
fold highlighting situations.
Optimize PaintSelMargin(), so it doesn't waste time with fold markers,
unless really necessary.
Make EnsureLineVisible() find right parent, when called on whitespace line.
Fix wrong fold tail marker when needWhiteClosure is true.
Diffstat (limited to 'src')
-rw-r--r-- | src/Document.cxx | 151 | ||||
-rw-r--r-- | src/Document.h | 37 | ||||
-rw-r--r-- | src/Editor.cxx | 207 | ||||
-rw-r--r-- | src/LineMarker.cxx | 12 | ||||
-rw-r--r-- | src/LineMarker.h | 2 |
5 files changed, 201 insertions, 208 deletions
diff --git a/src/Document.cxx b/src/Document.cxx index 85bb98135..da07b6b73 100644 --- a/src/Document.cxx +++ b/src/Document.cxx @@ -316,15 +316,18 @@ static bool IsSubordinate(int levelStart, int levelTry) { return (levelStart & SC_FOLDLEVELNUMBERMASK) < (levelTry & SC_FOLDLEVELNUMBERMASK); } -int Document::GetLastChild(int lineParent, int level) { +int Document::GetLastChild(int lineParent, int level, int lastLine) { if (level == -1) level = GetLevel(lineParent) & SC_FOLDLEVELNUMBERMASK; int maxLine = LinesTotal(); + int lookLastLine = (lastLine != -1) ? Platform::Minimum(LinesTotal() - 1, lastLine) : -1; int lineMaxSubord = lineParent; while (lineMaxSubord < maxLine - 1) { EnsureStyledTo(LineStart(lineMaxSubord + 2)); if (!IsSubordinate(level, GetLevel(lineMaxSubord + 1))) break; + if ((lookLastLine != -1) && (lineMaxSubord >= lookLastLine) && !(GetLevel(lineMaxSubord) & SC_FOLDLEVELWHITEFLAG)) + break; lineMaxSubord++; } if (lineMaxSubord > lineParent) { @@ -355,108 +358,74 @@ int Document::GetFoldParent(int line) { } } -void Document::GetHighlightDelimiters(HighlightDelimiter &highlightDelimiter, int line, int topLine, int bottomLine) { - int noNeedToParseBefore = Platform::Minimum(line, topLine) - 1; - int noNeedToParseAfter = Platform::Maximum(line, bottomLine) + 1; - int endLine = LineFromPosition(Length()); - int beginFoldBlock = noNeedToParseBefore; - int endFoldBlock = -1; - int beginMarginCorrectlyDrawnZone = noNeedToParseBefore; - int endMarginCorrectlyDrawnZone = noNeedToParseAfter; - int endOfTailOfWhiteFlag = -1; //endOfTailOfWhiteFlag points the last SC_FOLDLEVELWHITEFLAG if follow a fold block. Otherwise endOfTailOfWhiteFlag points end of fold block. +void Document::GetHighlightDelimiters(HighlightDelimiter &highlightDelimiter, int line, int lastLine) { int level = GetLevel(line); - int levelNumber = -1; - int lineLookLevel = 0; - int lineLookLevelNumber = -1; - int lineLook = line; - bool beginFoldBlockFound = false; - bool endFoldBlockFound = false; - bool beginMarginCorrectlyDrawnZoneFound = false; - bool endMarginCorrectlyDrawnZoneFound = false; - - /*******************************************************************************/ - /* search backward (beginFoldBlock & beginMarginCorrectlyDrawnZone) */ - /*******************************************************************************/ - for (endOfTailOfWhiteFlag = line; (lineLook > noNeedToParseBefore || (lineLookLevel & SC_FOLDLEVELWHITEFLAG)) && (!beginFoldBlockFound || !beginMarginCorrectlyDrawnZoneFound); --lineLook) { - lineLookLevel = GetLevel(lineLook); - if (levelNumber != -1) { - lineLookLevelNumber = lineLookLevel & SC_FOLDLEVELNUMBERMASK; - if (!beginMarginCorrectlyDrawnZoneFound && (lineLookLevelNumber > levelNumber)) { - beginMarginCorrectlyDrawnZoneFound = true; - beginMarginCorrectlyDrawnZone = endOfTailOfWhiteFlag; - } - //find the last space line (SC_FOLDLEVELWHITEFLAG). - if (!beginMarginCorrectlyDrawnZoneFound && !(lineLookLevel & SC_FOLDLEVELWHITEFLAG)) { - endOfTailOfWhiteFlag = lineLook - 1; - } - if (!beginFoldBlockFound && (lineLookLevelNumber < levelNumber)) { - beginFoldBlockFound = true; - beginFoldBlock = lineLook; - if (!beginMarginCorrectlyDrawnZoneFound) { - beginMarginCorrectlyDrawnZoneFound = true; - beginMarginCorrectlyDrawnZone = lineLook - 1; + int lookLastLine = Platform::Maximum(line, lastLine) + 1; + + int lookLine = line; + int lookLineLevel = level; + int lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; + while ((lookLine > 0) && ((lookLineLevel & SC_FOLDLEVELWHITEFLAG) || + ((lookLineLevel & SC_FOLDLEVELHEADERFLAG) && (lookLineLevelNum >= (GetLevel(lookLine + 1) & SC_FOLDLEVELNUMBERMASK))))) { + lookLineLevel = GetLevel(--lookLine); + lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; + } + + int beginFoldBlock = (lookLineLevel & SC_FOLDLEVELHEADERFLAG) ? lookLine : GetFoldParent(lookLine); + if (beginFoldBlock == -1) { + highlightDelimiter.Clear(); + return; + } + + int endFoldBlock = GetLastChild(beginFoldBlock, -1, lookLastLine); + int firstChangeableLineBefore = -1; + if (endFoldBlock < line) { + lookLine = beginFoldBlock - 1; + lookLineLevel = GetLevel(lookLine); + lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; + while ((lookLine >= 0) && (lookLineLevelNum >= SC_FOLDLEVELBASE)) { + if (lookLineLevel & SC_FOLDLEVELHEADERFLAG) { + if (GetLastChild(lookLine, -1, lookLastLine) == line) { + beginFoldBlock = lookLine; + endFoldBlock = line; + firstChangeableLineBefore = line - 1; } - } else if (!beginFoldBlockFound && lineLookLevelNumber == SC_FOLDLEVELBASE) { - beginFoldBlockFound = true; - beginFoldBlock = -1; - } - } else if (!(lineLookLevel & SC_FOLDLEVELWHITEFLAG)) { - endOfTailOfWhiteFlag = lineLook - 1; - levelNumber = lineLookLevel & SC_FOLDLEVELNUMBERMASK; - if (lineLookLevel & SC_FOLDLEVELHEADERFLAG && - //Managed the folding block when a fold header does not have any subordinate lines to fold away. - (levelNumber < (GetLevel(lineLook + 1) & SC_FOLDLEVELNUMBERMASK))) { - beginFoldBlockFound = true; - beginFoldBlock = lineLook; - beginMarginCorrectlyDrawnZoneFound = true; - beginMarginCorrectlyDrawnZone = endOfTailOfWhiteFlag; - levelNumber = GetLevel(lineLook + 1) & SC_FOLDLEVELNUMBERMASK;; } + if ((lookLine > 0) && (lookLineLevelNum == SC_FOLDLEVELBASE) && ((GetLevel(lookLine - 1) & SC_FOLDLEVELNUMBERMASK) > lookLineLevelNum)) + break; + lookLineLevel = GetLevel(--lookLine); + lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; } } - - /****************************************************************************/ - /* search forward (endStartBlock & endMarginCorrectlyDrawnZone) */ - /****************************************************************************/ - if (level & SC_FOLDLEVELHEADERFLAG) { - //ignore this line because this line is on first one of block. - lineLook = line + 1; - } else { - lineLook = line; - } - for (; lineLook < noNeedToParseAfter && (!endFoldBlockFound || !endMarginCorrectlyDrawnZoneFound); ++lineLook) { - lineLookLevel = GetLevel(lineLook); - lineLookLevelNumber = lineLookLevel & SC_FOLDLEVELNUMBERMASK; - if (!endFoldBlockFound && !(lineLookLevel & SC_FOLDLEVELWHITEFLAG) && lineLookLevelNumber < levelNumber) { - endFoldBlockFound = true; - endFoldBlock = lineLook - 1; - if (!endMarginCorrectlyDrawnZoneFound) { - endMarginCorrectlyDrawnZoneFound = true; - endMarginCorrectlyDrawnZone = lineLook; + if (firstChangeableLineBefore == -1) { + for (lookLine = line - 1, lookLineLevel = GetLevel(lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; + lookLine >= beginFoldBlock; + lookLineLevel = GetLevel(--lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK) { + if ((lookLineLevel & SC_FOLDLEVELWHITEFLAG) || (lookLineLevelNum > (level & SC_FOLDLEVELNUMBERMASK))) { + firstChangeableLineBefore = lookLine; + break; } - } else if (!endFoldBlockFound && lineLookLevel == SC_FOLDLEVELBASE) { - endFoldBlockFound = true; - endFoldBlock = -1; - } - if (!endMarginCorrectlyDrawnZoneFound && (lineLookLevel & SC_FOLDLEVELHEADERFLAG) && - //Managed the folding block when a fold header does not have any subordinate lines to fold away. - (levelNumber < (GetLevel(lineLook + 1) & SC_FOLDLEVELNUMBERMASK))) { - endMarginCorrectlyDrawnZoneFound = true; - endMarginCorrectlyDrawnZone = lineLook; } } - if (!endFoldBlockFound && ((lineLook > endLine && lineLookLevelNumber < levelNumber) || - (levelNumber > SC_FOLDLEVELBASE))) { - //manage when endfold is incorrect or on last line. - endFoldBlock = lineLook - 1; - //useless to set endMarginCorrectlyDrawnZone. - //if endMarginCorrectlyDrawnZoneFound equals false then endMarginCorrectlyDrawnZone already equals to endLine + 1. + if (firstChangeableLineBefore == -1) + firstChangeableLineBefore = beginFoldBlock - 1; + + int firstChangeableLineAfter = -1; + for (lookLine = line + 1, lookLineLevel = GetLevel(lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; + lookLine <= endFoldBlock; + lookLineLevel = GetLevel(++lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK) { + if ((lookLineLevel & SC_FOLDLEVELHEADERFLAG) && (lookLineLevelNum < (GetLevel(lookLine + 1) & SC_FOLDLEVELNUMBERMASK))) { + firstChangeableLineAfter = lookLine; + break; + } } + if (firstChangeableLineAfter == -1) + firstChangeableLineAfter = endFoldBlock + 1; highlightDelimiter.beginFoldBlock = beginFoldBlock; highlightDelimiter.endFoldBlock = endFoldBlock; - highlightDelimiter.beginMarginCorrectlyDrawnZone = beginMarginCorrectlyDrawnZone; - highlightDelimiter.endMarginCorrectlyDrawnZone = endMarginCorrectlyDrawnZone; + highlightDelimiter.firstChangeableLineBefore = firstChangeableLineBefore; + highlightDelimiter.firstChangeableLineAfter = firstChangeableLineAfter; } int Document::ClampPositionIntoDocument(int pos) { diff --git a/src/Document.h b/src/Document.h index 7858db727..e8dfbabc8 100644 --- a/src/Document.h +++ b/src/Document.h @@ -117,42 +117,41 @@ struct StyledText { class HighlightDelimiter { public: - HighlightDelimiter() { + HighlightDelimiter() : isEnabled(false) { + Clear(); + } + + void Clear() { beginFoldBlock = -1; endFoldBlock = -1; - beginMarginCorrectlyDrawnZone = -1; - endMarginCorrectlyDrawnZone = -1; - isEnabled = false; + firstChangeableLineBefore = -1; + firstChangeableLineAfter = -1; } bool NeedsDrawing(int line) { - return isEnabled && (line <= beginMarginCorrectlyDrawnZone || endMarginCorrectlyDrawnZone <= line); + return isEnabled && (line <= firstChangeableLineBefore || line >= firstChangeableLineAfter); } - bool isCurrentBlockHighlight(int line) { + bool IsFoldBlockHighlighted(int line) { return isEnabled && beginFoldBlock != -1 && beginFoldBlock <= line && line <= endFoldBlock; } - bool isHeadBlockFold(int line) { + bool IsHeadOfFoldBlock(int line) { return beginFoldBlock == line && line < endFoldBlock; } - bool isBodyBlockFold(int line) { + bool IsBodyOfFoldBlock(int line) { return beginFoldBlock != -1 && beginFoldBlock < line && line < endFoldBlock; } - bool isTailBlockFold(int line) { + bool IsTailOfFoldBlock(int line) { return beginFoldBlock != -1 && beginFoldBlock < line && line == endFoldBlock; } - // beginFoldBlock : Begin of current fold block. - // endStartBlock : End of current fold block. - // beginMarginCorrectlyDrawnZone : Begin of zone where margin is correctly drawn. - // endMarginCorrectlyDrawnZone : End of zone where margin is correctly drawn. - int beginFoldBlock; - int endFoldBlock; - int beginMarginCorrectlyDrawnZone; - int endMarginCorrectlyDrawnZone; + int beginFoldBlock; // Begin of current fold block + int endFoldBlock; // End of current fold block + int firstChangeableLineBefore; // First line that triggers repaint before starting line that determined current fold block + int firstChangeableLineAfter; // First line that triggers repaint after starting line that determined current fold block bool isEnabled; }; @@ -339,9 +338,9 @@ public: int SCI_METHOD SetLevel(int line, int level); int SCI_METHOD GetLevel(int line) const; void ClearLevels(); - int GetLastChild(int lineParent, int level=-1); + int GetLastChild(int lineParent, int level=-1, int lastLine=-1); int GetFoldParent(int line); - void GetHighlightDelimiters(HighlightDelimiter &hDelimiter, int line, int topLine, int bottomLine); + void GetHighlightDelimiters(HighlightDelimiter &hDelimiter, int line, int lastLine); void Indent(bool forwards); int ExtendWordSelect(int pos, int delta, bool onlyWordCharacters=false); diff --git a/src/Editor.cxx b/src/Editor.cxx index b7a9bedfa..78b2ac475 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -1746,13 +1746,6 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width; if (vs.ms[margin].style != SC_MARGIN_NUMBER) { - /* alternate scheme: - if (vs.ms[margin].mask & SC_MASK_FOLDERS) - surface->FillRectangle(rcSelMargin, vs.styles[STYLE_DEFAULT].back.allocated); - else - // Required because of special way brush is created for selection margin - surface->FillRectangle(rcSelMargin, pixmapSelPattern); - */ if (vs.ms[margin].mask & SC_MASK_FOLDERS) // Required because of special way brush is created for selection margin surface->FillRectangle(rcSelMargin, *pixmapSelPattern); @@ -1781,24 +1774,25 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { // lessening of fold level which implies a 'fold tail' but which should not // be displayed until the last of a sequence of whitespace. bool needWhiteClosure = false; - int level = pdoc->GetLevel(cs.DocFromDisplay(topLine)); - if (level & SC_FOLDLEVELWHITEFLAG) { - int lineBack = cs.DocFromDisplay(topLine); - int levelPrev = level; - while ((lineBack > 0) && (levelPrev & SC_FOLDLEVELWHITEFLAG)) { - lineBack--; - levelPrev = pdoc->GetLevel(lineBack); + if (vs.ms[margin].mask & SC_MASK_FOLDERS) { + int level = pdoc->GetLevel(cs.DocFromDisplay(topLine)); + if (level & SC_FOLDLEVELWHITEFLAG) { + int lineBack = cs.DocFromDisplay(topLine); + int levelPrev = level; + while ((lineBack > 0) && (levelPrev & SC_FOLDLEVELWHITEFLAG)) { + lineBack--; + levelPrev = pdoc->GetLevel(lineBack); + } + if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) { + if ((level & SC_FOLDLEVELNUMBERMASK) < (levelPrev & SC_FOLDLEVELNUMBERMASK)) + needWhiteClosure = true; + } } - if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) { - if ((level & SC_FOLDLEVELNUMBERMASK) < (levelPrev & SC_FOLDLEVELNUMBERMASK)) - needWhiteClosure = true; + if (highlightDelimiter.isEnabled) { + int lastLine = cs.DocFromDisplay(topLine + LinesOnScreen()) + 1; + pdoc->GetHighlightDelimiters(highlightDelimiter, pdoc->LineFromPosition(CurrentPosition()), lastLine); } } - if (highlightDelimiter.isEnabled && (vs.ms[margin].mask & SC_MASK_FOLDERS)) { - int lineBack = cs.DocFromDisplay(topLine); - int lineFront = cs.DocFromDisplay(((rcMargin.bottom - rcMargin.top) / vs.lineHeight) + topLine) + 1; - pdoc->GetHighlightDelimiters(highlightDelimiter, pdoc->LineFromPosition(CurrentPosition()), lineBack, lineFront); - } // Old code does not know about new markers needed to distinguish all cases int folderOpenMid = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID, @@ -1814,85 +1808,103 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { bool firstSubLine = visibleLine == cs.DisplayFromDoc(lineDoc); bool lastSubLine = visibleLine == (cs.DisplayFromDoc(lineDoc + 1) - 1); - // Decide which fold indicator should be displayed - level = pdoc->GetLevel(lineDoc); - int levelNext = pdoc->GetLevel(lineDoc + 1); int marks = pdoc->GetMark(lineDoc); if (!firstSubLine) marks = 0; - int levelNum = level & SC_FOLDLEVELNUMBERMASK; - int levelNextNum = levelNext & SC_FOLDLEVELNUMBERMASK; - if (level & SC_FOLDLEVELHEADERFLAG) { - if (firstSubLine) { - if (levelNum < levelNextNum) { - if (cs.GetExpanded(lineDoc)) { - if (levelNum == SC_FOLDLEVELBASE) - marks |= 1 << SC_MARKNUM_FOLDEROPEN; - else - marks |= 1 << folderOpenMid; - } else { - if (levelNum == SC_FOLDLEVELBASE) - marks |= 1 << SC_MARKNUM_FOLDER; - else - marks |= 1 << folderEnd; - } - } else if (levelNum > SC_FOLDLEVELBASE) { - marks |= 1 << SC_MARKNUM_FOLDERSUB; - } - } else { - if (levelNum < levelNextNum) { - if (cs.GetExpanded(lineDoc)) { - marks |= 1 << SC_MARKNUM_FOLDERSUB; + + bool headWithTail = false; + + if (vs.ms[margin].mask & SC_MASK_FOLDERS) { + // Decide which fold indicator should be displayed + int level = pdoc->GetLevel(lineDoc); + int levelNext = pdoc->GetLevel(lineDoc + 1); + int levelNum = level & SC_FOLDLEVELNUMBERMASK; + int levelNextNum = levelNext & SC_FOLDLEVELNUMBERMASK; + if (level & SC_FOLDLEVELHEADERFLAG) { + if (firstSubLine) { + if (levelNum < levelNextNum) { + if (cs.GetExpanded(lineDoc)) { + if (levelNum == SC_FOLDLEVELBASE) + marks |= 1 << SC_MARKNUM_FOLDEROPEN; + else + marks |= 1 << folderOpenMid; + } else { + if (levelNum == SC_FOLDLEVELBASE) + marks |= 1 << SC_MARKNUM_FOLDER; + else + marks |= 1 << folderEnd; + } } else if (levelNum > SC_FOLDLEVELBASE) { marks |= 1 << SC_MARKNUM_FOLDERSUB; - } - } else if (levelNum > SC_FOLDLEVELBASE) { - marks |= 1 << SC_MARKNUM_FOLDERSUB; - } - } - needWhiteClosure = false; - } else if (level & SC_FOLDLEVELWHITEFLAG) { - if (needWhiteClosure) { - if (levelNext & SC_FOLDLEVELWHITEFLAG) { - marks |= 1 << SC_MARKNUM_FOLDERSUB; - } else if (levelNum > SC_FOLDLEVELBASE) { - marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; - needWhiteClosure = false; + } } else { - marks |= 1 << SC_MARKNUM_FOLDERTAIL; - needWhiteClosure = false; + if (levelNum < levelNextNum) { + if (cs.GetExpanded(lineDoc)) { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } else if (levelNum > SC_FOLDLEVELBASE) { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } + } else if (levelNum > SC_FOLDLEVELBASE) { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } } - } else if (levelNum > SC_FOLDLEVELBASE) { - if (levelNextNum < levelNum) { - if (levelNextNum > SC_FOLDLEVELBASE) { + needWhiteClosure = false; + int firstFollowupLine = cs.DocFromDisplay(cs.DisplayFromDoc(lineDoc + 1)); + int firstFollowupLineLevel = pdoc->GetLevel(firstFollowupLine); + int secondFollowupLineLevelNum = pdoc->GetLevel(firstFollowupLine + 1) & SC_FOLDLEVELNUMBERMASK; + if (!cs.GetExpanded(lineDoc)) { + if ((firstFollowupLineLevel & SC_FOLDLEVELWHITEFLAG) && + (levelNum > secondFollowupLineLevelNum)) + needWhiteClosure = true; + + if (highlightDelimiter.IsFoldBlockHighlighted(firstFollowupLine)) + headWithTail = true; + } + } else if (level & SC_FOLDLEVELWHITEFLAG) { + if (needWhiteClosure) { + if (levelNext & SC_FOLDLEVELWHITEFLAG) { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } else if (levelNextNum > SC_FOLDLEVELBASE) { marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; + needWhiteClosure = false; } else { marks |= 1 << SC_MARKNUM_FOLDERTAIL; + needWhiteClosure = false; + } + } else if (levelNum > SC_FOLDLEVELBASE) { + if (levelNextNum < levelNum) { + if (levelNextNum > SC_FOLDLEVELBASE) { + marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; + } else { + marks |= 1 << SC_MARKNUM_FOLDERTAIL; + } + } else { + marks |= 1 << SC_MARKNUM_FOLDERSUB; } - } else { - marks |= 1 << SC_MARKNUM_FOLDERSUB; } - } - } else if (levelNum > SC_FOLDLEVELBASE) { - if (levelNextNum < levelNum) { - needWhiteClosure = false; - if (levelNext & SC_FOLDLEVELWHITEFLAG) { - marks |= 1 << SC_MARKNUM_FOLDERSUB; - needWhiteClosure = true; - } else if (lastSubLine) { - if (levelNextNum > SC_FOLDLEVELBASE) { - marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; + } else if (levelNum > SC_FOLDLEVELBASE) { + if (levelNextNum < levelNum) { + needWhiteClosure = false; + if (levelNext & SC_FOLDLEVELWHITEFLAG) { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + needWhiteClosure = true; + } else if (lastSubLine) { + if (levelNextNum > SC_FOLDLEVELBASE) { + marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; + } else { + marks |= 1 << SC_MARKNUM_FOLDERTAIL; + } } else { - marks |= 1 << SC_MARKNUM_FOLDERTAIL; + marks |= 1 << SC_MARKNUM_FOLDERSUB; } } else { marks |= 1 << SC_MARKNUM_FOLDERSUB; } - } else { - marks |= 1 << SC_MARKNUM_FOLDERSUB; } } + marks &= vs.ms[margin].mask; + PRectangle rcMarker = rcSelMargin; rcMarker.top = yposScreen; rcMarker.bottom = yposScreen + vs.lineHeight; @@ -1939,22 +1951,22 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { for (int markBit = 0; (markBit < 32) && marks; markBit++) { if (marks & 1) { LineMarker::typeOfFold tFold = LineMarker::undefined; - if (!highlightDelimiter.isCurrentBlockHighlight(lineDoc)) { - tFold = LineMarker::undefined; - } else if (highlightDelimiter.isBodyBlockFold(lineDoc)) { - tFold = LineMarker::body; - } else if (highlightDelimiter.isHeadBlockFold(lineDoc)) { - if (firstSubLine) { - tFold = LineMarker::head; - } else { - if (cs.GetExpanded(lineDoc)) { - tFold = LineMarker::body; + if ((vs.ms[margin].mask & SC_MASK_FOLDERS) && highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) { + if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) { + tFold = LineMarker::body; + } else if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) { + if (firstSubLine) { + tFold = headWithTail ? LineMarker::headWithTail : LineMarker::head; } else { - tFold = LineMarker::undefined; + if (cs.GetExpanded(lineDoc) || headWithTail) { + tFold = LineMarker::body; + } else { + tFold = LineMarker::undefined; + } } + } else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) { + tFold = LineMarker::tail; } - } else if (highlightDelimiter.isTailBlockFold(lineDoc)) { - tFold = LineMarker::tail; } vs.markers[markBit].Draw(surface, rcMarker, vs.styles[STYLE_LINENUMBER].font, tFold); } @@ -6822,7 +6834,12 @@ void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) { WrapLines(true, -1); if (!cs.GetVisible(lineDoc)) { - int lineParent = pdoc->GetFoldParent(lineDoc); + int lookLine = lineDoc; + int lookLineLevel = pdoc->GetLevel(lookLine); + while ((lookLine > 0) && (lookLineLevel & SC_FOLDLEVELWHITEFLAG)) { + lookLineLevel = pdoc->GetLevel(--lookLine); + } + int lineParent = pdoc->GetFoldParent(lookLine); if (lineParent >= 0) { if (lineDoc != lineParent) EnsureLineVisible(lineParent, enforcePolicy); diff --git a/src/LineMarker.cxx b/src/LineMarker.cxx index 1415c609b..b2b7ceae8 100644 --- a/src/LineMarker.cxx +++ b/src/LineMarker.cxx @@ -84,6 +84,7 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac switch (tFold) { case LineMarker::head : + case LineMarker::headWithTail : head = backSelected; tail = backSelected; break; @@ -243,7 +244,10 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac DrawPlus(surface, centreX, centreY, blobSize, tail.allocated); } else if (markType == SC_MARK_BOXPLUSCONNECTED) { - surface->PenColour(body.allocated); + if (tFold == LineMarker::headWithTail) + surface->PenColour(tail.allocated); + else + surface->PenColour(body.allocated); surface->MoveTo(centreX, centreY + blobSize); surface->LineTo(centreX, rcWhole.bottom); @@ -301,10 +305,14 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac DrawPlus(surface, centreX, centreY, blobSize, tail.allocated); } else if (markType == SC_MARK_CIRCLEPLUSCONNECTED) { - surface->PenColour(body.allocated); + if (tFold == LineMarker::headWithTail) + surface->PenColour(tail.allocated); + else + surface->PenColour(body.allocated); surface->MoveTo(centreX, centreY + blobSize); surface->LineTo(centreX, rcWhole.bottom); + surface->PenColour(body.allocated); surface->MoveTo(centreX, rcWhole.top); surface->LineTo(centreX, centreY - blobSize); diff --git a/src/LineMarker.h b/src/LineMarker.h index 722c44b62..6477a1ffe 100644 --- a/src/LineMarker.h +++ b/src/LineMarker.h @@ -17,7 +17,7 @@ namespace Scintilla { */ class LineMarker { public: - enum typeOfFold { undefined, head, body, tail }; + enum typeOfFold { undefined, head, body, tail, headWithTail }; int markType; ColourPair fore; |