aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Decoration.cxx183
-rw-r--r--src/Decoration.h55
-rw-r--r--src/RunStyles.cxx187
-rw-r--r--src/RunStyles.h31
4 files changed, 456 insertions, 0 deletions
diff --git a/src/Decoration.cxx b/src/Decoration.cxx
new file mode 100644
index 000000000..f1c9c5ae3
--- /dev/null
+++ b/src/Decoration.cxx
@@ -0,0 +1,183 @@
+/** @file Decoration.cxx
+ ** Visual elements added over text.
+ **/
+// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "Decoration.h"
+
+Decoration::Decoration(int indicator_) : next(0), indicator(indicator_) {
+}
+
+Decoration::~Decoration() {
+}
+
+bool Decoration::Empty() {
+ return rs.starts->Partitions() == 1;
+}
+
+DecorationList::DecorationList() : currentIndicator(0), currentValue(1), current(0),
+ lengthDocument(0), root(0), clickNotified(false) {
+}
+
+DecorationList::~DecorationList() {
+ Decoration *deco = root;
+ while (deco) {
+ Decoration *decoNext = deco->next;
+ delete deco;
+ deco = decoNext;
+ }
+ root = 0;
+ current = 0;
+}
+
+Decoration *DecorationList::DecorationFromIndicator(int indicator) {
+ for (Decoration *deco=root; deco; deco = deco->next) {
+ if (deco->indicator == indicator) {
+ return deco;
+ }
+ }
+ return 0;
+}
+
+Decoration *DecorationList::Create(int indicator, int length) {
+ currentIndicator = indicator;
+ Decoration *decoNew = new Decoration(indicator);
+ decoNew->rs.InsertSpace(0, length);
+
+ Decoration *decoPrev = 0;
+ Decoration *deco = root;
+
+ while (deco && (deco->indicator < indicator)) {
+ decoPrev = deco;
+ deco = deco->next;
+ }
+ if (decoPrev == 0) {
+ decoNew->next = root;
+ root = decoNew;
+ } else {
+ decoNew->next = deco;
+ decoPrev->next = decoNew;
+ }
+ return decoNew;
+}
+
+void DecorationList::Delete(int indicator) {
+ Decoration *decoToDelete = 0;
+ if (root) {
+ if (root->indicator == indicator) {
+ decoToDelete = root;
+ root = root->next;
+ } else {
+ Decoration *deco=root;
+ while (deco->next && !decoToDelete) {
+ if (deco->next && deco->next->indicator == indicator) {
+ decoToDelete = deco->next;
+ deco->next = decoToDelete->next;
+ } else {
+ deco = deco->next;
+ }
+ }
+ }
+ }
+ if (decoToDelete) {
+ delete decoToDelete;
+ current = 0;
+ }
+}
+
+void DecorationList::SetCurrentIndicator(int indicator) {
+ currentIndicator = indicator;
+ current = DecorationFromIndicator(indicator);
+ currentValue = 1;
+}
+
+void DecorationList::SetCurrentValue(int value) {
+ currentValue = value;
+}
+
+void DecorationList::FillRange(int position, int value, int fillLength) {
+ if (!current) {
+ current = DecorationFromIndicator(currentIndicator);
+ if (!current) {
+ current = Create(currentIndicator, lengthDocument);
+ }
+ }
+ current->rs.FillRange(position, value, fillLength);
+ if (current->Empty()) {
+ Delete(currentIndicator);
+ }
+}
+
+void DecorationList::InsertSpace(int position, int insertLength) {
+ lengthDocument += insertLength;
+ for (Decoration *deco=root; deco; deco = deco->next) {
+ deco->rs.InsertSpace(position, insertLength);
+ }
+}
+
+void DecorationList::DeleteRange(int position, int deleteLength) {
+ lengthDocument -= deleteLength;
+ Decoration *deco;
+ for (deco=root; deco; deco = deco->next) {
+ deco->rs.DeleteRange(position, deleteLength);
+ }
+ DeleteAnyEmpty();
+}
+
+void DecorationList::DeleteAnyEmpty() {
+ Decoration *deco = root;
+ while (deco) {
+ if (deco->Empty()) {
+ Delete(deco->indicator);
+ deco = root;
+ } else {
+ deco = deco->next;
+ }
+ }
+}
+
+int DecorationList::AllOnFor(int position) {
+ int mask = 0;
+ for (Decoration *deco=root; deco; deco = deco->next) {
+ if (deco->rs.ValueAt(position)) {
+ mask |= 1 << deco->indicator;
+ }
+ }
+ return mask;
+}
+
+int DecorationList::ValueAt(int indicator, int position) {
+ Decoration *deco = DecorationFromIndicator(indicator);
+ if (deco) {
+ return deco->rs.ValueAt(position);
+ }
+ return 0;
+}
+
+int DecorationList::Start(int indicator, int position) {
+ Decoration *deco = DecorationFromIndicator(indicator);
+ if (deco) {
+ return deco->rs.StartRun(position);
+ }
+ return 0;
+}
+
+int DecorationList::End(int indicator, int position) {
+ Decoration *deco = DecorationFromIndicator(indicator);
+ if (deco) {
+ return deco->rs.EndRun(position);
+ }
+ return 0;
+}
diff --git a/src/Decoration.h b/src/Decoration.h
new file mode 100644
index 000000000..1810b0fb3
--- /dev/null
+++ b/src/Decoration.h
@@ -0,0 +1,55 @@
+/** @file Decoration.h
+ ** Visual elements added over text.
+ **/
+// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef DECORATION_H
+#define DECORATION_H
+
+class Decoration {
+public:
+ Decoration *next;
+ RunStyles rs;
+ int indicator;
+
+ Decoration(int indicator_);
+ ~Decoration();
+
+ bool Empty();
+};
+
+class DecorationList {
+ int currentIndicator;
+ int currentValue;
+ Decoration *current;
+ int lengthDocument;
+ Decoration *DecorationFromIndicator(int indicator);
+ Decoration *Create(int indicator, int length);
+ void Delete(int indicator);
+ void DeleteAnyEmpty();
+public:
+ Decoration *root;
+ bool clickNotified;
+
+ DecorationList();
+ ~DecorationList();
+
+ void SetCurrentIndicator(int indicator);
+ int GetCurrentIndicator() { return currentIndicator; }
+
+ void SetCurrentValue(int value);
+ int GetCurrentValue() { return currentValue; }
+
+ void FillRange(int position, int value, int fillLength);
+
+ void InsertSpace(int position, int insertLength);
+ void DeleteRange(int position, int deleteLength);
+
+ int AllOnFor(int position);
+ int ValueAt(int indicator, int position);
+ int Start(int indicator, int position);
+ int End(int indicator, int position);
+};
+
+#endif
diff --git a/src/RunStyles.cxx b/src/RunStyles.cxx
new file mode 100644
index 000000000..a7cf40e81
--- /dev/null
+++ b/src/RunStyles.cxx
@@ -0,0 +1,187 @@
+/** @file RunStyles.cxx
+ ** Data structure used to store sparse styles.
+ **/
+// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "Scintilla.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+
+// Find the first run at a position
+int RunStyles::RunFromPosition(int position) {
+ int 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.
+void RunStyles::SplitRun(int position) {
+ int run = RunFromPosition(position);
+ int posRun = starts->PositionFromPartition(run);
+ if (posRun < position) {
+ int runStyle = ValueAt(position);
+ starts->InsertPartition(run+1, position);
+ styles->InsertValue(run+1, 1, runStyle);
+ }
+}
+
+void RunStyles::RemoveRun(int run) {
+ starts->RemovePartition(run);
+ styles->DeleteRange(run, 1);
+}
+
+void RunStyles::RemoveRunIfEmpty(int run) {
+ if ((run < starts->Partitions()) && (starts->Partitions() > 1)) {
+ if (starts->PositionFromPartition(run) == starts->PositionFromPartition(run+1)) {
+ RemoveRun(run);
+ }
+ }
+}
+
+void RunStyles::RemoveRunIfSameAsPrevious(int run) {
+ if ((run > 0) && (run < starts->Partitions())) {
+ if (styles->ValueAt(run-1) == styles->ValueAt(run)) {
+ RemoveRun(run);
+ }
+ }
+}
+
+RunStyles::RunStyles() {
+ starts = new Partitioning(8);
+ styles = new SplitVector<int>();
+ styles->InsertValue(0, 2, 0);
+}
+
+RunStyles::~RunStyles() {
+ delete starts;
+ starts = NULL;
+ delete styles;
+ styles = NULL;
+}
+
+int RunStyles::Length() {
+ return starts->PositionFromPartition(starts->Partitions());
+}
+
+int RunStyles::ValueAt(int position) {
+ return styles->ValueAt(starts->PartitionFromPosition(position));
+}
+
+int RunStyles::FindNextChange(int position, int end) {
+ int run = starts->PartitionFromPosition(position);
+ if (run < starts->Partitions()) {
+ int runChange = starts->PositionFromPartition(run);
+ if (runChange > position)
+ return runChange;
+ int nextChange = starts->PositionFromPartition(run + 1);
+ if (nextChange > position) {
+ return nextChange;
+ } else if (position < end) {
+ return end;
+ } else {
+ return end + 1;
+ }
+ } else {
+ return end + 1;
+ }
+}
+
+int RunStyles::StartRun(int position) {
+ return starts->PositionFromPartition(starts->PartitionFromPosition(position));
+}
+
+int RunStyles::EndRun(int position) {
+ return starts->PositionFromPartition(starts->PartitionFromPosition(position) + 1);
+}
+
+void RunStyles::FillRange(int position, int value, int fillLength) {
+ int end = position + fillLength;
+ SplitRun(end);
+ int runStart = RunFromPosition(position);
+ if (styles->ValueAt(runStart) != value) {
+ SplitRun(position);
+ runStart = RunFromPosition(position);
+ styles->SetValueAt(runStart, value);
+ }
+ int runEnd = RunFromPosition(end);
+ // Remove each old run over the range
+ for (int run=runStart+1; run<runEnd; run++) {
+ RemoveRun(runStart+1);
+ }
+ runEnd = RunFromPosition(end);
+ RemoveRunIfSameAsPrevious(runEnd);
+ RemoveRunIfSameAsPrevious(runStart);
+}
+
+void RunStyles::InsertSpace(int position, int insertLength) {
+ int runStart = RunFromPosition(position);
+ if (starts->PositionFromPartition(runStart) == position) {
+ int 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, 0);
+ 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);
+ }
+}
+
+void RunStyles::DeleteAll() {
+ delete starts;
+ starts = NULL;
+ delete styles;
+ styles = NULL;
+ starts = new Partitioning(8);
+ styles = new SplitVector<int>();
+ styles->InsertValue(0, 2, 0);
+}
+
+void RunStyles::DeleteRange(int position, int deleteLength) {
+ int end = position + deleteLength;
+ int runStart = RunFromPosition(position);
+ int runEnd = RunFromPosition(end);
+ if (runStart == runEnd) {
+ // Deleting from inside one run
+ starts->InsertText(runStart, -deleteLength);
+ } else {
+ SplitRun(position);
+ SplitRun(end);
+ runStart = RunFromPosition(position);
+ runEnd = RunFromPosition(end);
+ starts->InsertText(runStart, -deleteLength);
+ // Remove each old run over the range
+ for (int run=runStart; run<runEnd; run++) {
+ RemoveRun(runStart);
+ }
+ RemoveRunIfEmpty(runStart);
+ RemoveRunIfSameAsPrevious(runStart);
+ }
+}
+
diff --git a/src/RunStyles.h b/src/RunStyles.h
new file mode 100644
index 000000000..539e5de47
--- /dev/null
+++ b/src/RunStyles.h
@@ -0,0 +1,31 @@
+/** @file RunStyles.h
+ ** Data structure used to store sparse styles.
+ **/
+// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+/// Styling buffer using one element for each run rather than using
+/// a filled buffer.
+
+class RunStyles {
+public:
+ Partitioning *starts;
+ SplitVector<int> *styles;
+ int RunFromPosition(int position);
+ void SplitRun(int position);
+ void RemoveRun(int run);
+ void RemoveRunIfEmpty(int run);
+ void RemoveRunIfSameAsPrevious(int run);
+public:
+ RunStyles();
+ ~RunStyles();
+ int Length();
+ int ValueAt(int position);
+ int FindNextChange(int position, int end);
+ int StartRun(int position);
+ int EndRun(int position);
+ void FillRange(int position, int value, int fillLength);
+ void InsertSpace(int position, int insertLength);
+ void DeleteAll();
+ void DeleteRange(int position, int deleteLength);
+};