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/Editor.cxx | |
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/Editor.cxx')
-rw-r--r-- | src/Editor.cxx | 207 |
1 files changed, 112 insertions, 95 deletions
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); |