// Scintilla source code edit control /** @file PerLine.cxx ** Manages data associated with each line of the document **/ // Copyright 1998-2009 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include #include #include "Platform.h" #include "Scintilla.h" #include "SplitVector.h" #include "Partitioning.h" #include "CellBuffer.h" #include "PerLine.h" #ifdef SCI_NAMESPACE using namespace Scintilla; #endif MarkerHandleSet::MarkerHandleSet() { root = 0; } MarkerHandleSet::~MarkerHandleSet() { MarkerHandleNumber *mhn = root; while (mhn) { MarkerHandleNumber *mhnToFree = mhn; mhn = mhn->next; delete mhnToFree; } root = 0; } int MarkerHandleSet::Length() const { int c = 0; MarkerHandleNumber *mhn = root; while (mhn) { c++; mhn = mhn->next; } return c; } int MarkerHandleSet::MarkValue() const { unsigned int m = 0; MarkerHandleNumber *mhn = root; while (mhn) { m |= (1 << mhn->number); mhn = mhn->next; } return m; } bool MarkerHandleSet::Contains(int handle) const { MarkerHandleNumber *mhn = root; while (mhn) { if (mhn->handle == handle) { return true; } mhn = mhn->next; } return false; } bool MarkerHandleSet::InsertHandle(int handle, int markerNum) { MarkerHandleNumber *mhn = new MarkerHandleNumber; mhn->handle = handle; mhn->number = markerNum; mhn->next = root; root = mhn; return true; } void MarkerHandleSet::RemoveHandle(int handle) { MarkerHandleNumber **pmhn = &root; while (*pmhn) { MarkerHandleNumber *mhn = *pmhn; if (mhn->handle == handle) { *pmhn = mhn->next; delete mhn; return; } pmhn = &((*pmhn)->next); } } bool MarkerHandleSet::RemoveNumber(int markerNum, bool all) { bool performedDeletion = false; MarkerHandleNumber **pmhn = &root; while (*pmhn) { MarkerHandleNumber *mhn = *pmhn; if (mhn->number == markerNum) { *pmhn = mhn->next; delete mhn; performedDeletion = true; if (!all) break; } else { pmhn = &((*pmhn)->next); } } return performedDeletion; } void MarkerHandleSet::CombineWith(MarkerHandleSet *other) { MarkerHandleNumber **pmhn = &root; while (*pmhn) { pmhn = &((*pmhn)->next); } *pmhn = other->root; other->root = 0; } LineMarkers::~LineMarkers() { Init(); } void LineMarkers::Init() { for (int line = 0; line < markers.Length(); line++) { delete markers[line]; markers[line] = 0; } markers.DeleteAll(); } void LineMarkers::InsertLine(int line) { if (markers.Length()) { markers.Insert(line, 0); } } void LineMarkers::RemoveLine(int line) { // Retain the markers from the deleted line by oring them into the previous line if (markers.Length()) { if (line > 0) { MergeMarkers(line - 1); } markers.Delete(line); } } int LineMarkers::LineFromHandle(int markerHandle) { if (markers.Length()) { for (int line = 0; line < markers.Length(); line++) { if (markers[line]) { if (markers[line]->Contains(markerHandle)) { return line; } } } } return -1; } void LineMarkers::MergeMarkers(int pos) { if (markers[pos + 1] != NULL) { if (markers[pos] == NULL) markers[pos] = new MarkerHandleSet; markers[pos]->CombineWith(markers[pos + 1]); delete markers[pos + 1]; markers[pos + 1] = NULL; } } int LineMarkers::MarkValue(int line) { if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) return markers[line]->MarkValue(); else return 0; } int LineMarkers::MarkerNext(int lineStart, int mask) const { if (lineStart < 0) lineStart = 0; int length = markers.Length(); for (int iLine = lineStart; iLine < length; iLine++) { MarkerHandleSet *onLine = markers[iLine]; if (onLine && ((onLine->MarkValue() & mask) != 0)) //if ((pdoc->GetMark(iLine) & lParam) != 0) return iLine; } return -1; } int LineMarkers::AddMark(int line, int markerNum, int lines) { handleCurrent++; if (!markers.Length()) { // No existing markers so allocate one element per line markers.InsertValue(0, lines, 0); } if (line >= markers.Length()) { return -1; } if (!markers[line]) { // Need new structure to hold marker handle markers[line] = new MarkerHandleSet(); } markers[line]->InsertHandle(handleCurrent, markerNum); return handleCurrent; } bool LineMarkers::DeleteMark(int line, int markerNum, bool all) { bool someChanges = false; if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) { if (markerNum == -1) { someChanges = true; delete markers[line]; markers[line] = NULL; } else { someChanges = markers[line]->RemoveNumber(markerNum, all); if (markers[line]->Length() == 0) { delete markers[line]; markers[line] = NULL; } } } return someChanges; } void LineMarkers::DeleteMarkFromHandle(int markerHandle) { int line = LineFromHandle(markerHandle); if (line >= 0) { markers[line]->RemoveHandle(markerHandle); if (markers[line]->Length() == 0) { delete markers[line]; markers[line] = NULL; } } } LineLevels::~LineLevels() { } void LineLevels::Init() { levels.DeleteAll(); } void LineLevels::InsertLine(int line) { if (levels.Length()) { int level = (line < levels.Length()) ? levels[line] : SC_FOLDLEVELBASE; levels.InsertValue(line, 1, level); } } void LineLevels::RemoveLine(int line) { if (levels.Length()) { // Move up following lines but merge header flag from this line // to line before to avoid a temporary disappearence causing expansion. int firstHeader = levels[line] & SC_FOLDLEVELHEADERFLAG; levels.Delete(line); if (line == levels.Length()-1) // Last line loses the header flag levels[line-1] &= ~SC_FOLDLEVELHEADERFLAG; else if (line > 0) levels[line-1] |= firstHeader; } } void LineLevels::ExpandLevels(int sizeNew) { levels.InsertValue(levels.Length(), sizeNew - levels.Length(), SC_FOLDLEVELBASE); } void LineLevels::ClearLevels() { levels.DeleteAll(); } int LineLevels::SetLevel(int line, int level, int lines) { int prev = 0; if ((line >= 0) && (line < lines)) { if (!levels.Length()) { ExpandLevels(lines + 1); } prev = levels[line]; if (prev != level) { levels[line] = level; } } return prev; } int LineLevels::GetLevel(int line) const { if (levels.Length() && (line >= 0) && (line < levels.Length())) { return levels[line]; } else { return SC_FOLDLEVELBASE; } } LineState::~LineState() { } void LineState::Init() { lineStates.DeleteAll(); } void LineState::InsertLine(int line) { if (lineStates.Length()) { lineStates.EnsureLength(line); int val = (line < lineStates.Length()) ? lineStates[line] : 0; lineStates.Insert(line, val); } } void LineState::RemoveLine(int line) { if (lineStates.Length() > line) { lineStates.Delete(line); } } int LineState::SetLineState(int line, int state) { lineStates.EnsureLength(line + 1); int stateOld = lineStates[line]; lineStates[line] = state; return stateOld; } int LineState::GetLineState(int line) { if (line < 0) return 0; lineStates.EnsureLength(line + 1); return lineStates[line]; } int LineState::GetMaxLineState() const { return lineStates.Length(); } static int NumberLines(const char *text) { if (text) { int newLines = 0; while (*text) { if (*text == '\n') newLines++; text++; } return newLines+1; } else { return 0; } } // Each allocated LineAnnotation is a char array which starts with an AnnotationHeader // and then has text and optional styles. static const int IndividualStyles = 0x100; struct AnnotationHeader { short style; // Style IndividualStyles implies array of styles short lines; int length; }; LineAnnotation::~LineAnnotation() { ClearAll(); } void LineAnnotation::Init() { ClearAll(); } void LineAnnotation::InsertLine(int line) { if (annotations.Length()) { annotations.EnsureLength(line); annotations.Insert(line, 0); } } void LineAnnotation::RemoveLine(int line) { if (annotations.Length() && (line < annotations.Length())) { delete []annotations[line]; annotations.Delete(line); } } bool LineAnnotation::MultipleStyles(int line) const { if (annotations.Length() && (line >= 0) && (line < annotatHTTP/1.1 200 OK Connection: keep-alive Connection: keep-alive Content-Disposition: inline; filename="PerLine.cxx" Content-Disposition: inline; filename="PerLine.cxx" Content-Length: 12024 Content-Length: 12024 Content-Security-Policy: default-src 'none' Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Type: text/plain; charset=UTF-8 Date: Sat, 18 Oct 2025 03:59:49 UTC ETag: "a066bd647ebfde5fb90625f8321e7d498c534a53" ETag: "a066bd647ebfde5fb90625f8321e7d498c534a53" Expires: Tue, 16 Oct 2035 03:59:49 GMT Expires: Tue, 16 Oct 2035 03:59:50 GMT Last-Modified: Sat, 18 Oct 2025 03:59:49 GMT Last-Modified: Sat, 18 Oct 2025 03:59:50 GMT Server: OpenBSD httpd Server: OpenBSD httpd X-Content-Type-Options: nosniff X-Content-Type-Options: nosniff // Scintilla source code edit control /** @file PerLine.cxx ** Manages data associated with each line of the document **/ // Copyright 1998-2009 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include #include #include "Platform.h" #include "Scintilla.h" #include "SplitVector.h" #include "Partitioning.h" #include "CellBuffer.h" #include "PerLine.h" #ifdef SCI_NAMESPACE using namespace Scintilla; #endif MarkerHandleSet::MarkerHandleSet() { root = 0; } MarkerHandleSet::~MarkerHandleSet() { MarkerHandleNumber *mhn = root; while (mhn) { MarkerHandleNumber *mhnToFree = mhn; mhn = mhn->next; delete mhnToFree; } root = 0; } int MarkerHandleSet::Length() const { int c = 0; MarkerHandleNumber *mhn = root; while (mhn) { c++; mhn = mhn->next; } return c; } int MarkerHandleSet::MarkValue() const { unsigned int m = 0; MarkerHandleNumber *mhn = root; while (mhn) { m |= (1 << mhn->number); mhn = mhn->next; } return m; } bool MarkerHandleSet::Contains(int handle) const { MarkerHandleNumber *mhn = root; while (mhn) { if (mhn->handle == handle) { return true; } mhn = mhn->next; } return false; } bool MarkerHandleSet::InsertHandle(int handle, int markerNum) { MarkerHandleNumber *mhn = new MarkerHandleNumber; mhn->handle = handle; mhn->number = markerNum; mhn->next = root; root = mhn; return true; } void MarkerHandleSet::RemoveHandle(int handle) { MarkerHandleNumber **pmhn = &root; while (*pmhn) { MarkerHandleNumber *mhn = *pmhn; if (mhn->handle == handle) { *pmhn = mhn->next; delete mhn; return; } pmhn = &((*pmhn)->next); } } bool MarkerHandleSet::RemoveNumber(int markerNum, bool all) { bool performedDeletion = false; MarkerHandleNumber **pmhn = &root; while (*pmhn) { MarkerHandleNumber *mhn = *pmhn; if (mhn->number == markerNum) { *pmhn = mhn->next; delete mhn; performedDeletion = true; if (!all) break; } else { pmhn = &((*pmhn)->next); } } return performedDeletion; } void MarkerHandleSet::CombineWith(MarkerHandleSet *other) { MarkerHandleNumber **pmhn = &root; while (*pmhn) { pmhn = &((*pmhn)->next); } *pmhn = other->root; other->root = 0; } LineMarkers::~LineMarkers() { Init(); } void LineMarkers::Init() { for (int line = 0; line < markers.Length(); line++) { delete markers[line]; markers[line] = 0; } markers.DeleteAll(); } void LineMarkers::InsertLine(int line) { if (markers.Length()) { markers.Insert(line, 0); } } void LineMarkers::RemoveLine(int line) { // Retain the markers from the deleted line by oring them into the previous line if (markers.Length()) { if (line > 0) { MergeMarkers(line - 1); } markers.Delete(line); } } int LineMarkers::LineFromHandle(int markerHandle) { if (markers.Length()) { for (int line = 0; line < markers.Length(); line++) { if (markers[line]) { if (markers[line]->Contains(markerHandle)