/** @file RunStyles.cxx ** Data structure used to store sparse styles. **/ // Copyright 1998-2007 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include #include #include #include #include #include #include #include #include #include #include #include "Platform.h" #include "Scintilla.h" #include "Position.h" #include "SplitVector.h" #include "Partitioning.h" #include "RunStyles.h" using namespace Scintilla; // Find the first run at a position template DISTANCE RunStyles::RunFromPosition(DISTANCE position) const noexcept { DISTANCE run = starts->PartitionFromPosition(position); // Go to first element with this position while ((run > 0) && (position == starts->PositionFromPartition(run-1))) { run--; } return run; } // If there is no run boundary at position, insert one continuing style. template DISTANCE RunStyles::SplitRun(DISTANCE position) { DISTANCE run = RunFromPosition(position); const DISTANCE posRun = starts->PositionFromPartition(run); if (posRun < position) { STYLE runStyle = ValueAt(position); run++; starts->InsertPartition(run, position); styles->InsertValue(run, 1, runStyle); } return run; } template void RunStyles::RemoveRun(DISTANCE run) { starts->RemovePartition(run); styles->DeleteRange(run, 1); } template void RunStyles::RemoveRunIfEmpty(DISTANCE run) { if ((run < starts->Partitions()) && (starts->Partitions() > 1)) { if (starts->PositionFromPartition(run) == starts->PositionFromPartition(run+1)) { RemoveRun(run); } } } template void RunStyles::RemoveRunIfSameAsPrevious(DISTANCE run) { if ((run > 0) && (run < starts->Partitions())) { if (styles->ValueAt(run-1) == styles->ValueAt(run)) { RemoveRun(run); } } } template RunStyles::RunStyles() { starts = std::make_unique>(8); styles = std::make_unique>(); styles->InsertValue(0, 2, 0); } template RunStyles::~RunStyles() { } template DISTANCE RunStyles::Length() const noexcept { return starts->PositionFromPartition(starts->Partitions()); } template STYLE RunStyles::ValueAt(DISTANCE position) const noexcept { return styles->ValueAt(starts->PartitionFromPosition(position)); } template DISTANCE RunStyles::FindNextChange(DISTANCE position, DISTANCE end) const noexcept { const DISTANCE run = starts->PartitionFromPosition(position); if (run < starts->Partitions()) { const DISTANCE runChange = starts->PositionFromPartition(run); if (runChange > position) return runChange; const DISTANCE nextChange = starts->PositionFromPartition(run + 1); if (nextChange > position) { return nextChange; } else if (position < end) { return end; } else { return end + 1; } } else { return end + 1; } } template DISTANCE RunStyles::StartRun(DISTANCE position) const noexcept { return starts->PositionFromPartition(starts->PartitionFromPosition(position)); } template DISTANCE RunStyles::EndRun(DISTANCE position) const noexcept { return starts->PositionFromPartition(starts->PartitionFromPosition(position) + 1); } template FillResult RunStyles::FillRange(DISTANCE position, STYLE value, DISTANCE fillLength) { const FillResult resultNoChange{false, position, fillLength}; if (fillLength <= 0) { return resultNoChange; } DISTANCE end = position + fillLength; if (end > Length()) { return resultNoChange; } DISTANCE runEnd = RunFromPosition(end); if (styles->ValueAt(runEnd) == value) { // End already has value so trim range. end = starts->PositionFromPartition(runEnd); if (position >= end) { // Whole range is already same as value so no action return resultNoChange; } fillLength = end - position; } else { runEnd = SplitRun(end); } DISTANCE runStart = RunFromPosition(position); if (styles->ValueAt(runStart) == value) { // Start is in expected value so trim range. runStart++; position = starts->PositionFromPartition(runStart); fillLength = end - position; } else { if (starts->PositionFromPartition(runStart) < position) { runStart = SplitRun(position); runEnd++; } } if (runStart < runEnd) { const FillResult result{ true, position, fillLength }; styles->SetValueAt(runStart, value); // Remove each old run over the range for (DISTANCE run=runStart+1; run void RunStyles::SetValueAt(DISTANCE position, STYLE value) { FillRange(position, value, 1); } template void RunStyles::InsertSpace(DISTANCE position, DISTANCE insertLength) { DISTANCE runStart = RunFromPosition(position); if (starts->PositionFromPartition(runStart) == position) { STYLE runStyle = ValueAt(position); // Inserting at start of run so make previous longer if (runStart == 0) { // Inserting at start of document so ensure 0 if (runStyle) { styles->SetValueAt(0, STYLE()); starts->InsertPartition(1, 0); styles->InsertValue(1, 1, runStyle); starts->InsertText(0, insertLength); } else { starts->InsertText(runStart, insertLength); } } else { if (runStyle) { starts->InsertText(runStart-1, insertLength); } else { // Insert at end of run so do not extend style starts->InsertText(runStart, insertLength); } } } else { starts->InsertText(runStart, insertLength); } } template void RunStyles::DeleteAll() { starts = std::make_unique>(8); styles = std::make_unique>(); styles->InsertValue(0, 2, 0); } template void RunStyles::DeleteRange(DISTANCE position, DISTANCE deleteLength) { DISTANCE end = position + deleteLength; DISTANCE runStart = RunFromPosition(position); DISTANCE runEnd = RunFromPosition(end); if (runStart == runEnd) { // Deleting from inside one run starts->InsertText(runStart, -deleteLength); RemoveRunIfEmpty(runStart); } else { runStart = SplitRun(position); runEnd = SplitRun(end); starts->InsertText(runStart, -deleteLength); // Remove each old run over the range for (DISTANCE run=runStart; run DISTANCE RunStyles::Runs() const noexcept { return starts->Partitions(); } template bool RunStyles::AllSame() const noexcept { for (int run = 1; run < starts->Partitions(); run++) { if (styles->ValueAt(run) != styles->ValueAt(run - 1)) return false; } return true; } template bool RunStyles::AllSameAs(STYLE value) const noexcept { return AllSame() && (styles->ValueAt(0) == value); } template DISTANCE RunStyles::Find(STYLE value, DISTANCE start) const noexcept { if (start < Length()) { DISTANCE run = start ?HTTP/1.1 200 OK Connection: keep-alive Connection: keep-alive Connection: keep-alive Content-Disposition: inline; filename="RunStyles.cxx" Content-Disposition: inline; filename="RunStyles.cxx" Content-Disposition: inline; filename="RunStyles.cxx" Content-Length: 9624 Content-Length: 9624 Content-Length: 9624 Content-Security-Policy: default-src 'none' 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 Content-Type: text/plain; charset=UTF-8 Date: Sat, 18 Oct 2025 11:35:55 UTC ETag: "95fe10ecd5e27dd6c8e530858d7bb2736f4dd44a" ETag: "95fe10ecd5e27dd6c8e530858d7bb2736f4dd44a" ETag: "95fe10ecd5e27dd6c8e530858d7bb2736f4dd44a" Expires: Tue, 16 Oct 2035 11:35:55 GMT Expires: Tue, 16 Oct 2035 11:35:55 GMT Expires: Tue, 16 Oct 2035 11:35:56 GMT Last-Modified: Sat, 18 Oct 2025 11:35:55 GMT Last-Modified: Sat, 18 Oct 2025 11:35:55 GMT Last-Modified: Sat, 18 Oct 2025 11:35:56 GMT Server: OpenBSD httpd Server: OpenBSD httpd Server: OpenBSD httpd X-Content-Type-Options: nosniff X-Content-Type-Options: nosniff X-Content-Type-Options: nosniff /** @file RunStyles.cxx ** Data structure used to store sparse styles. **/ // Copyright 1998-2007 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #incl