Fix line hiding issues

Fix #12184, fix #8149, close #12250
This commit is contained in:
Adrian 2022-09-26 14:04:01 +02:00 committed by Don Ho
parent 6750d4dbbc
commit 4b3ee9c4ea
2 changed files with 52 additions and 23 deletions

View File

@ -3460,43 +3460,72 @@ void ScintillaEditView::hideLines()
if (startLine > endLine) if (startLine > endLine)
return; //tried to hide line at edge return; //tried to hide line at edge
//Hide the lines. We add marks on the outside of the hidden section and hide the lines
//execute(SCI_HIDELINES, startLine, endLine);
//Add markers
execute(SCI_MARKERADD, startLine-1, MARK_HIDELINESBEGIN);
execute(SCI_MARKERADD, startLine-1, MARK_HIDELINESUNDERLINE);
execute(SCI_MARKERADD, endLine+1, MARK_HIDELINESEND);
//remove any markers in between
int scope = 0; int scope = 0;
for (size_t i = startLine; i <= endLine; ++i) bool recentMarkerWasOpen = false;
auto removeMarker = [this, &scope, &recentMarkerWasOpen](size_t line)
{ {
auto state = execute(SCI_MARKERGET, i); auto state = execute(SCI_MARKERGET, line);
bool closePresent = ((state & (1 << MARK_HIDELINESEND)) != 0); //check close first, then open, since close closes scope bool closePresent = ((state & (1 << MARK_HIDELINESEND)) != 0);
bool openPresent = ((state & (1 << MARK_HIDELINESBEGIN | 1 << MARK_HIDELINESUNDERLINE)) != 0); bool openPresent = ((state & (1 << MARK_HIDELINESBEGIN | 1 << MARK_HIDELINESUNDERLINE)) != 0);
if (closePresent) if (closePresent)
{ {
execute(SCI_MARKERDELETE, i, MARK_HIDELINESEND); execute(SCI_MARKERDELETE, line, MARK_HIDELINESEND);
if (scope > 0) scope--; recentMarkerWasOpen = false;
--scope;
} }
if (openPresent) if (openPresent)
{ {
execute(SCI_MARKERDELETE, i, MARK_HIDELINESBEGIN); execute(SCI_MARKERDELETE, line, MARK_HIDELINESBEGIN);
execute(SCI_MARKERDELETE, i, MARK_HIDELINESUNDERLINE); execute(SCI_MARKERDELETE, line, MARK_HIDELINESUNDERLINE);
recentMarkerWasOpen = true;
++scope; ++scope;
} }
};
size_t startMarker = startLine - 1;
size_t endMarker = endLine + 1;
// Remove all previous markers in between new ones
for (size_t i = startMarker; i <= endMarker; ++i)
removeMarker(i);
// When hiding lines just below/above other hidden lines,
// merge them into one hidden section:
if (scope == 0 && recentMarkerWasOpen)
{
// Special case: user wants to hide every line in between other hidden sections.
// Both "while" loops are executed (merge with above AND below hidden section):
while (scope == 0)
removeMarker(--startMarker);
while (scope != 0)
removeMarker(++endMarker);
} }
if (scope != 0) else
{ //something went wrong {
//Someone managed to make overlapping hidelines sections. // User wants to hide some lines below/above other hidden section.
//We cant do anything since this isnt supposed to happen // If true, only one "while" loop is executed (merge with adjacent hidden section):
while (scope < 0)
removeMarker(--startMarker);
while (scope > 0)
removeMarker(++endMarker);
} }
_currentBuffer->setHideLineChanged(true, startLine-1); execute(SCI_MARKERADD, startMarker, MARK_HIDELINESBEGIN);
execute(SCI_MARKERADD, startMarker, MARK_HIDELINESUNDERLINE);
execute(SCI_MARKERADD, endMarker, MARK_HIDELINESEND);
_currentBuffer->setHideLineChanged(true, startMarker);
} }
bool ScintillaEditView::markerMarginClick(size_t lineNumber) bool ScintillaEditView::markerMarginClick(intptr_t lineNumber)
{ {
auto state = execute(SCI_MARKERGET, lineNumber); auto state = execute(SCI_MARKERGET, lineNumber);
bool openPresent = ((state & (1 << MARK_HIDELINESBEGIN | 1 << MARK_HIDELINESUNDERLINE)) != 0); bool openPresent = ((state & (1 << MARK_HIDELINESBEGIN | 1 << MARK_HIDELINESUNDERLINE)) != 0);
@ -3522,7 +3551,7 @@ bool ScintillaEditView::markerMarginClick(size_t lineNumber)
if (openPresent) if (openPresent)
{ {
_currentBuffer->setHideLineChanged(false, lineNumber); _currentBuffer->setHideLineChanged(false, lineNumber + 1);
} }
} }

View File

@ -538,7 +538,7 @@ public:
void hideLines(); void hideLines();
bool markerMarginClick(size_t lineNumber); //true if it did something bool markerMarginClick(intptr_t lineNumber); //true if it did something
void notifyMarkers(Buffer * buf, bool isHide, size_t location, bool del); void notifyMarkers(Buffer * buf, bool isHide, size_t location, bool del);
void runMarkers(bool doHide, size_t searchStart, bool endOfDoc, bool doDelete); void runMarkers(bool doHide, size_t searchStart, bool endOfDoc, bool doDelete);