# HG changeset patch
# User Neil <nyamatongwe@gmail.com>
# Date 1516959931 -39600
#      Fri Jan 26 20:45:31 2018 +1100
# Node ID 7f62c564bab393e3b0b5b8df484f378e946a5af9
# Parent  71961187dbc2dad60a3eefe6eea308b31a2e76d5
Templatize data structures that hold positions and lines so they can later be
switched between 32-bits and 64-bits.

diff -r 71961187dbc2 -r 7f62c564bab3 src/CellBuffer.cxx
--- a/src/CellBuffer.cxx	Fri Jan 26 18:28:27 2018 +1100
+++ b/src/CellBuffer.cxx	Fri Jan 26 20:45:31 2018 +1100
@@ -45,8 +45,9 @@
 
 using namespace Scintilla;
 
+template <typename POS>
 class LineVector : public ILineVector {
-	Partitioning starts;
+	Partitioning<POS> starts;
 	PerLine *perLine;
 public:
 	LineVector() : starts(256), perLine(0) {
@@ -65,10 +66,10 @@
 		perLine = pl;
 	}
 	void InsertText(Sci::Line line, Sci::Position delta) override {
-		starts.InsertText(line, delta);
+		starts.InsertText(static_cast<POS>(line), static_cast<POS>(delta));
 	}
 	void InsertLine(Sci::Line line, Sci::Position position, bool lineStart) override {
-		starts.InsertPartition(line, position);
+		starts.InsertPartition(static_cast<POS>(line), static_cast<POS>(position));
 		if (perLine) {
 			if ((line > 0) && lineStart)
 				line--;
@@ -76,10 +77,10 @@
 		}
 	}
 	void SetLineStart(Sci::Line line, Sci::Position position) override {
-		starts.SetPartitionStartPosition(line, position);
+		starts.SetPartitionStartPosition(static_cast<POS>(line), static_cast<POS>(position));
 	}
 	void RemoveLine(Sci::Line line) override {
-		starts.RemovePartition(line);
+		starts.RemovePartition(static_cast<POS>(line));
 		if (perLine) {
 			perLine->RemoveLine(line);
 		}
@@ -88,10 +89,10 @@
 		return starts.Partitions();
 	}
 	Sci::Line LineFromPosition(Sci::Position pos) const override {
-		return starts.PartitionFromPosition(pos);
+		return starts.PartitionFromPosition(static_cast<POS>(pos));
 	}
 	Sci::Position LineStart(Sci::Line line) const override {
-		return starts.PositionFromPartition(line);
+		return starts.PositionFromPartition(static_cast<POS>(line));
 	}
 };
 
@@ -368,7 +369,7 @@
 	readOnly = false;
 	utf8LineEnds = 0;
 	collectingUndo = true;
-	plv.reset(new LineVector());
+	plv.reset(new LineVector<Sci::Position>());
 }
 
 CellBuffer::~CellBuffer() {
diff -r 71961187dbc2 -r 7f62c564bab3 src/ContractionState.cxx
--- a/src/ContractionState.cxx	Fri Jan 26 18:28:27 2018 +1100
+++ b/src/ContractionState.cxx	Fri Jan 26 20:45:31 2018 +1100
@@ -35,11 +35,11 @@
 
 void ContractionState::EnsureData() {
 	if (OneToOne()) {
-		visible.reset(new RunStyles());
-		expanded.reset(new RunStyles());
-		heights.reset(new RunStyles());
+		visible.reset(new RunStyles<Sci::Line, char>());
+		expanded.reset(new RunStyles<Sci::Line, char>());
+		heights.reset(new RunStyles<Sci::Line, int>());
 		foldDisplayTexts.reset(new SparseVector<UniqueString>());
-		displayLines.reset(new Partitioning(4));
+		displayLines.reset(new Partitioning<Sci::Line>(4));
 		InsertLines(0, linesInDocument);
 	}
 }
diff -r 71961187dbc2 -r 7f62c564bab3 src/ContractionState.h
--- a/src/ContractionState.h	Fri Jan 26 18:28:27 2018 +1100
+++ b/src/ContractionState.h	Fri Jan 26 20:45:31 2018 +1100
@@ -17,11 +17,11 @@
  */
 class ContractionState {
 	// These contain 1 element for every document line.
-	std::unique_ptr<RunStyles> visible;
-	std::unique_ptr<RunStyles> expanded;
-	std::unique_ptr<RunStyles> heights;
+	std::unique_ptr<RunStyles<Sci::Line, char>> visible;
+	std::unique_ptr<RunStyles<Sci::Line, char>> expanded;
+	std::unique_ptr<RunStyles<Sci::Line, int>> heights;
 	std::unique_ptr<SparseVector<UniqueString>> foldDisplayTexts;
-	std::unique_ptr<Partitioning> displayLines;
+	std::unique_ptr<Partitioning<Sci::Line>> displayLines;
 	Sci::Line linesInDocument;
 
 	void EnsureData();
diff -r 71961187dbc2 -r 7f62c564bab3 src/Decoration.cxx
--- a/src/Decoration.cxx	Fri Jan 26 18:28:27 2018 +1100
+++ b/src/Decoration.cxx	Fri Jan 26 20:45:31 2018 +1100
@@ -53,7 +53,7 @@
 	return nullptr;
 }
 
-Decoration *DecorationList::Create(int indicator, int length) {
+Decoration *DecorationList::Create(int indicator, Sci::Position length) {
 	currentIndicator = indicator;
 	std::unique_ptr<Decoration> decoNew(new Decoration(indicator));
 	decoNew->rs.InsertSpace(0, length);
@@ -90,7 +90,7 @@
 	currentValue = value ? value : 1;
 }
 
-bool DecorationList::FillRange(int &position, int value, int &fillLength) {
+bool DecorationList::FillRange(Sci::Position &position, int value, Sci::Position &fillLength) {
 	if (!current) {
 		current = DecorationFromIndicator(currentIndicator);
 		if (!current) {
@@ -104,7 +104,7 @@
 	return changed;
 }
 
-void DecorationList::InsertSpace(int position, int insertLength) {
+void DecorationList::InsertSpace(Sci::Position position, Sci::Position insertLength) {
 	const bool atEnd = position == lengthDocument;
 	lengthDocument += insertLength;
 	for (const std::unique_ptr<Decoration> &deco : decorationList) {
@@ -115,7 +115,7 @@
 	}
 }
 
-void DecorationList::DeleteRange(int position, int deleteLength) {
+void DecorationList::DeleteRange(Sci::Position position, Sci::Position deleteLength) {
 	lengthDocument -= deleteLength;
 	for (const std::unique_ptr<Decoration> &deco : decorationList) {
 		deco->rs.DeleteRange(position, deleteLength);
@@ -155,7 +155,7 @@
 	}
 }
 
-int DecorationList::AllOnFor(int position) const {
+int DecorationList::AllOnFor(Sci::Position position) const {
 	int mask = 0;
 	for (const std::unique_ptr<Decoration> &deco : decorationList) {
 		if (deco->rs.ValueAt(position)) {
@@ -167,7 +167,7 @@
 	return mask;
 }
 
-int DecorationList::ValueAt(int indicator, int position) {
+int DecorationList::ValueAt(int indicator, Sci::Position position) {
 	const Decoration *deco = DecorationFromIndicator(indicator);
 	if (deco) {
 		return deco->rs.ValueAt(position);
@@ -175,7 +175,7 @@
 	return 0;
 }
 
-int DecorationList::Start(int indicator, int position) {
+Sci::Position DecorationList::Start(int indicator, Sci::Position position) {
 	const Decoration *deco = DecorationFromIndicator(indicator);
 	if (deco) {
 		return deco->rs.StartRun(position);
@@ -183,7 +183,7 @@
 	return 0;
 }
 
-int DecorationList::End(int indicator, int position) {
+Sci::Position DecorationList::End(int indicator, Sci::Position position) {
 	const Decoration *deco = DecorationFromIndicator(indicator);
 	if (deco) {
 		return deco->rs.EndRun(position);
diff -r 71961187dbc2 -r 7f62c564bab3 src/Decoration.h
--- a/src/Decoration.h	Fri Jan 26 18:28:27 2018 +1100
+++ b/src/Decoration.h	Fri Jan 26 20:45:31 2018 +1100
@@ -12,7 +12,7 @@
 class Decoration {
 	int indicator;
 public:
-	RunStyles rs;
+	RunStyles<Sci::Position, int> rs;
 
 	explicit Decoration(int indicator_);
 	~Decoration();
@@ -27,14 +27,14 @@
 	int currentIndicator;
 	int currentValue;
 	Decoration *current;	// Cached so FillRange doesn't have to search for each call.
-	int lengthDocument;
+	Sci::Position lengthDocument;
 	// Ordered by indicator
 	std::vector<std::unique_ptr<Decoration>> decorationList;
 	std::vector<const Decoration*> decorationView;	// Read-only view of decorationList
 	bool clickNotified;
 
 	Decoration *DecorationFromIndicator(int indicator);
-	Decoration *Create(int indicator, int length);
+	Decoration *Create(int indicator, Sci::Position length);
 	void Delete(int indicator);
 	void DeleteAnyEmpty();
 	void SetView();
@@ -52,17 +52,17 @@
 	int GetCurrentValue() const { return currentValue; }
 
 	// Returns true if some values may have changed
-	bool FillRange(int &position, int value, int &fillLength);
+	bool FillRange(Sci::Position &position, int value, Sci::Position &fillLength);
 
-	void InsertSpace(int position, int insertLength);
-	void DeleteRange(int position, int deleteLength);
+	void InsertSpace(Sci::Position position, Sci::Position insertLength);
+	void DeleteRange(Sci::Position position, Sci::Position deleteLength);
 
 	void DeleteLexerDecorations();
 
-	int AllOnFor(int position) const;
-	int ValueAt(int indicator, int position);
-	int Start(int indicator, int position);
-	int End(int indicator, int position);
+	int AllOnFor(Sci::Position position) const;
+	int ValueAt(int indicator, Sci::Position position);
+	Sci::Position Start(int indicator, Sci::Position position);
+	Sci::Position End(int indicator, Sci::Position position);
 
 	bool ClickNotified() const {
 		return clickNotified;
diff -r 71961187dbc2 -r 7f62c564bab3 src/Partitioning.h
--- a/src/Partitioning.h	Fri Jan 26 18:28:27 2018 +1100
+++ b/src/Partitioning.h	Fri Jan 26 20:45:31 2018 +1100
@@ -14,32 +14,33 @@
 /// in a range.
 /// Used by the Partitioning class.
 
-class SplitVectorWithRangeAdd : public SplitVector<int> {
+template <typename T>
+class SplitVectorWithRangeAdd : public SplitVector<T> {
 public:
 	explicit SplitVectorWithRangeAdd(ptrdiff_t growSize_) {
-		SetGrowSize(growSize_);
-		ReAllocate(growSize_);
+		this->SetGrowSize(growSize_);
+		this->ReAllocate(growSize_);
 	}
 	// Deleted so SplitVectorWithRangeAdd objects can not be copied.
 	SplitVectorWithRangeAdd(const SplitVectorWithRangeAdd &) = delete;
 	void operator=(const SplitVectorWithRangeAdd &) = delete;
 	~SplitVectorWithRangeAdd() {
 	}
-	void RangeAddDelta(ptrdiff_t start, ptrdiff_t end, int delta) {
+	void RangeAddDelta(ptrdiff_t start, ptrdiff_t end, T delta) {
 		// end is 1 past end, so end-start is number of elements to change
 		ptrdiff_t i = 0;
 		const ptrdiff_t rangeLength = end - start;
 		ptrdiff_t range1Length = rangeLength;
-		const ptrdiff_t part1Left = part1Length - start;
+		const ptrdiff_t part1Left = this->part1Length - start;
 		if (range1Length > part1Left)
 			range1Length = part1Left;
 		while (i < range1Length) {
-			body[start++] += delta;
+			this->body[start++] += delta;
 			i++;
 		}
-		start += gapLength;
+		start += this->gapLength;
 		while (i < rangeLength) {
-			body[start++] += delta;
+			this->body[start++] += delta;
 			i++;
 		}
 	}
@@ -52,16 +53,17 @@
 /// When needed, positions after the interval are considered part of the last partition
 /// but the end of the last partition can be found with PositionFromPartition(last+1).
 
+template <typename T>
 class Partitioning {
 private:
 	// To avoid calculating all the partition positions whenever any text is inserted
 	// there may be a step somewhere in the list.
-	int stepPartition;
-	int stepLength;
-	std::unique_ptr<SplitVectorWithRangeAdd> body;
+	T stepPartition;
+	T stepLength;
+	std::unique_ptr<SplitVectorWithRangeAdd<T>> body;
 
 	// Move step forward
-	void ApplyStep(int partitionUpTo) {
+	void ApplyStep(T partitionUpTo) {
 		if (stepLength != 0) {
 			body->RangeAddDelta(stepPartition+1, partitionUpTo + 1, stepLength);
 		}
@@ -73,7 +75,7 @@
 	}
 
 	// Move step backward
-	void BackStep(int partitionDownTo) {
+	void BackStep(T partitionDownTo) {
 		if (stepLength != 0) {
 			body->RangeAddDelta(partitionDownTo+1, stepPartition+1, -stepLength);
 		}
@@ -81,7 +83,7 @@
 	}
 
 	void Allocate(ptrdiff_t growSize) {
-		body.reset(new SplitVectorWithRangeAdd(growSize));
+		body.reset(new SplitVectorWithRangeAdd<T>(growSize));
 		stepPartition = 0;
 		stepLength = 0;
 		body->Insert(0, 0);	// This value stays 0 for ever
@@ -100,11 +102,11 @@
 	~Partitioning() {
 	}
 
-	int Partitions() const {
-		return static_cast<int>(body->Length()-1);
+	T Partitions() const {
+		return static_cast<T>(body->Length())-1;
 	}
 
-	void InsertPartition(int partition, int pos) {
+	void InsertPartition(T partition, T pos) {
 		if (stepPartition < partition) {
 			ApplyStep(partition);
 		}
@@ -112,7 +114,7 @@
 		stepPartition++;
 	}
 
-	void SetPartitionStartPosition(int partition, int pos) {
+	void SetPartitionStartPosition(T partition, T pos) {
 		ApplyStep(partition+1);
 		if ((partition < 0) || (partition > body->Length())) {
 			return;
@@ -120,7 +122,7 @@
 		body->SetValueAt(partition, pos);
 	}
 
-	void InsertText(int partitionInsert, int delta) {
+	void InsertText(T partitionInsert, T delta) {
 		// Point all the partitions after the insertion point further along in the buffer
 		if (stepLength != 0) {
 			if (partitionInsert >= stepPartition) {
@@ -142,7 +144,7 @@
 		}
 	}
 
-	void RemovePartition(int partition) {
+	void RemovePartition(T partition) {
 		if (partition > stepPartition) {
 			ApplyStep(partition);
 			stepPartition--;
@@ -152,29 +154,29 @@
 		body->Delete(partition);
 	}
 
-	int PositionFromPartition(int partition) const {
+	T PositionFromPartition(T partition) const {
 		PLATFORM_ASSERT(partition >= 0);
 		PLATFORM_ASSERT(partition < body->Length());
 		if ((partition < 0) || (partition >= body->Length())) {
 			return 0;
 		}
-		int pos = body->ValueAt(partition);
+		T pos = body->ValueAt(partition);
 		if (partition > stepPartition)
 			pos += stepLength;
 		return pos;
 	}
 
 	/// Return value in range [0 .. Partitions() - 1] even for arguments outside interval
-	int PartitionFromPosition(int pos) const {
+	T PartitionFromPosition(T pos) const {
 		if (body->Length() <= 1)
 			return 0;
 		if (pos >= (PositionFromPartition(Partitions())))
 			return Partitions() - 1;
-		int lower = 0;
-		int upper = Partitions();
+		T lower = 0;
+		T upper = Partitions();
 		do {
-			const int middle = (upper + lower + 1) / 2; 	// Round high
-			int posMiddle = body->ValueAt(middle);
+			const T middle = (upper + lower + 1) / 2; 	// Round high
+			T posMiddle = body->ValueAt(middle);
 			if (middle > stepPartition)
 				posMiddle += stepLength;
 			if (pos < posMiddle) {
diff -r 71961187dbc2 -r 7f62c564bab3 src/Position.h
--- a/src/Position.h	Fri Jan 26 18:28:27 2018 +1100
+++ b/src/Position.h	Fri Jan 26 20:45:31 2018 +1100
@@ -11,7 +11,8 @@
 /**
  * A Position is a position within a document between two characters or at the beginning or end.
  * Sometimes used as a character index where it identifies the character after the position.
- * A Line is a document or screen line.
+ * A Line is a document or screen line. Since there are fewer lines in a document than bytes
+ * Line could remain 32-bit when Position is 64-bit.
  */
 
 namespace Sci {
diff -r 71961187dbc2 -r 7f62c564bab3 src/RunStyles.cxx
--- a/src/RunStyles.cxx	Fri Jan 26 18:28:27 2018 +1100
+++ b/src/RunStyles.cxx	Fri Jan 26 20:45:31 2018 +1100
@@ -26,8 +26,9 @@
 using namespace Scintilla;
 
 // Find the first run at a position
-int RunStyles::RunFromPosition(int position) const {
-	int run = starts->PartitionFromPosition(position);
+template <typename DISTANCE, typename VALUE>
+DISTANCE RunStyles<DISTANCE, VALUE>::RunFromPosition(DISTANCE position) const {
+	DISTANCE run = starts->PartitionFromPosition(position);
 	// Go to first element with this position
 	while ((run > 0) && (position == starts->PositionFromPartition(run-1))) {
 		run--;
@@ -36,11 +37,12 @@
 }
 
 // If there is no run boundary at position, insert one continuing style.
-int RunStyles::SplitRun(int position) {
-	int run = RunFromPosition(position);
-	const int posRun = starts->PositionFromPartition(run);
+template <typename DISTANCE, typename VALUE>
+DISTANCE RunStyles<DISTANCE, VALUE>::SplitRun(DISTANCE position) {
+	DISTANCE run = RunFromPosition(position);
+	const DISTANCE posRun = starts->PositionFromPartition(run);
 	if (posRun < position) {
-		int runStyle = ValueAt(position);
+		VALUE runStyle = ValueAt(position);
 		run++;
 		starts->InsertPartition(run, position);
 		styles->InsertValue(run, 1, runStyle);
@@ -48,12 +50,14 @@
 	return run;
 }
 
-void RunStyles::RemoveRun(int run) {
+template <typename DISTANCE, typename VALUE>
+void RunStyles<DISTANCE, VALUE>::RemoveRun(DISTANCE run) {
 	starts->RemovePartition(run);
 	styles->DeleteRange(run, 1);
 }
 
-void RunStyles::RemoveRunIfEmpty(int run) {
+template <typename DISTANCE, typename VALUE>
+void RunStyles<DISTANCE, VALUE>::RemoveRunIfEmpty(DISTANCE run) {
 	if ((run < starts->Partitions()) && (starts->Partitions() > 1)) {
 		if (starts->PositionFromPartition(run) == starts->PositionFromPartition(run+1)) {
 			RemoveRun(run);
@@ -61,7 +65,8 @@
 	}
 }
 
-void RunStyles::RemoveRunIfSameAsPrevious(int run) {
+template <typename DISTANCE, typename VALUE>
+void RunStyles<DISTANCE, VALUE>::RemoveRunIfSameAsPrevious(DISTANCE run) {
 	if ((run > 0) && (run < starts->Partitions())) {
 		if (styles->ValueAt(run-1) == styles->ValueAt(run)) {
 			RemoveRun(run);
@@ -69,30 +74,35 @@
 	}
 }
 
-RunStyles::RunStyles() {
-	starts.reset(new Partitioning(8));
-	styles.reset(new SplitVector<int>());
+template <typename DISTANCE, typename VALUE>
+RunStyles<DISTANCE, VALUE>::RunStyles() {
+	starts.reset(new Partitioning<DISTANCE>(8));
+	styles.reset(new SplitVector<VALUE>());
 	styles->InsertValue(0, 2, 0);
 }
 
-RunStyles::~RunStyles() {
+template <typename DISTANCE, typename VALUE>
+RunStyles<DISTANCE, VALUE>::~RunStyles() {
 }
 
-int RunStyles::Length() const {
+template <typename DISTANCE, typename VALUE>
+DISTANCE RunStyles<DISTANCE, VALUE>::Length() const {
 	return starts->PositionFromPartition(starts->Partitions());
 }
 
-int RunStyles::ValueAt(int position) const {
+template <typename DISTANCE, typename VALUE>
+VALUE RunStyles<DISTANCE, VALUE>::ValueAt(DISTANCE position) const {
 	return styles->ValueAt(starts->PartitionFromPosition(position));
 }
 
-int RunStyles::FindNextChange(int position, int end) const {
-	const int run = starts->PartitionFromPosition(position);
+template <typename DISTANCE, typename VALUE>
+DISTANCE RunStyles<DISTANCE, VALUE>::FindNextChange(DISTANCE position, DISTANCE end) const {
+	const DISTANCE run = starts->PartitionFromPosition(position);
 	if (run < starts->Partitions()) {
-		const int runChange = starts->PositionFromPartition(run);
+		const DISTANCE runChange = starts->PositionFromPartition(run);
 		if (runChange > position)
 			return runChange;
-		const int nextChange = starts->PositionFromPartition(run + 1);
+		const DISTANCE nextChange = starts->PositionFromPartition(run + 1);
 		if (nextChange > position) {
 			return nextChange;
 		} else if (position < end) {
@@ -105,23 +115,26 @@
 	}
 }
 
-int RunStyles::StartRun(int position) const {
+template <typename DISTANCE, typename VALUE>
+DISTANCE RunStyles<DISTANCE, VALUE>::StartRun(DISTANCE position) const {
 	return starts->PositionFromPartition(starts->PartitionFromPosition(position));
 }
 
-int RunStyles::EndRun(int position) const {
+template <typename DISTANCE, typename VALUE>
+DISTANCE RunStyles<DISTANCE, VALUE>::EndRun(DISTANCE position) const {
 	return starts->PositionFromPartition(starts->PartitionFromPosition(position) + 1);
 }
 
-bool RunStyles::FillRange(int &position, int value, int &fillLength) {
+template <typename DISTANCE, typename VALUE>
+bool RunStyles<DISTANCE, VALUE>::FillRange(DISTANCE &position, VALUE value, DISTANCE &fillLength) {
 	if (fillLength <= 0) {
 		return false;
 	}
-	int end = position + fillLength;
+	DISTANCE end = position + fillLength;
 	if (end > Length()) {
 		return false;
 	}
-	int runEnd = RunFromPosition(end);
+	DISTANCE runEnd = RunFromPosition(end);
 	if (styles->ValueAt(runEnd) == value) {
 		// End already has value so trim range.
 		end = starts->PositionFromPartition(runEnd);
@@ -133,7 +146,7 @@
 	} else {
 		runEnd = SplitRun(end);
 	}
-	int runStart = RunFromPosition(position);
+	DISTANCE runStart = RunFromPosition(position);
 	if (styles->ValueAt(runStart) == value) {
 		// Start is in expected value so trim range.
 		runStart++;
@@ -148,7 +161,7 @@
 	if (runStart < runEnd) {
 		styles->SetValueAt(runStart, value);
 		// Remove each old run over the range
-		for (int run=runStart+1; run<runEnd; run++) {
+		for (DISTANCE run=runStart+1; run<runEnd; run++) {
 			RemoveRun(runStart+1);
 		}
 		runEnd = RunFromPosition(end);
@@ -162,20 +175,22 @@
 	}
 }
 
-void RunStyles::SetValueAt(int position, int value) {
-	int len = 1;
+template <typename DISTANCE, typename VALUE>
+void RunStyles<DISTANCE, VALUE>::SetValueAt(DISTANCE position, VALUE value) {
+	DISTANCE len = 1;
 	FillRange(position, value, len);
 }
 
-void RunStyles::InsertSpace(int position, int insertLength) {
-	int runStart = RunFromPosition(position);
+template <typename DISTANCE, typename VALUE>
+void RunStyles<DISTANCE, VALUE>::InsertSpace(DISTANCE position, DISTANCE insertLength) {
+	DISTANCE runStart = RunFromPosition(position);
 	if (starts->PositionFromPartition(runStart) == position) {
-		int runStyle = ValueAt(position);
+		VALUE 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);
+				styles->SetValueAt(0, VALUE());
 				starts->InsertPartition(1, 0);
 				styles->InsertValue(1, 1, runStyle);
 				starts->InsertText(0, insertLength);
@@ -195,16 +210,18 @@
 	}
 }
 
-void RunStyles::DeleteAll() {
-	starts.reset(new Partitioning(8));
-	styles.reset(new SplitVector<int>());
+template <typename DISTANCE, typename VALUE>
+void RunStyles<DISTANCE, VALUE>::DeleteAll() {
+	starts.reset(new Partitioning<DISTANCE>(8));
+	styles.reset(new SplitVector<VALUE>());
 	styles->InsertValue(0, 2, 0);
 }
 
-void RunStyles::DeleteRange(int position, int deleteLength) {
-	int end = position + deleteLength;
-	int runStart = RunFromPosition(position);
-	int runEnd = RunFromPosition(end);
+template <typename DISTANCE, typename VALUE>
+void RunStyles<DISTANCE, VALUE>::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);
@@ -214,7 +231,7 @@
 		runEnd = SplitRun(end);
 		starts->InsertText(runStart, -deleteLength);
 		// Remove each old run over the range
-		for (int run=runStart; run<runEnd; run++) {
+		for (DISTANCE run=runStart; run<runEnd; run++) {
 			RemoveRun(runStart);
 		}
 		RemoveRunIfEmpty(runStart);
@@ -222,11 +239,13 @@
 	}
 }
 
-int RunStyles::Runs() const {
+template <typename DISTANCE, typename VALUE>
+DISTANCE RunStyles<DISTANCE, VALUE>::Runs() const {
 	return starts->Partitions();
 }
 
-bool RunStyles::AllSame() const {
+template <typename DISTANCE, typename VALUE>
+bool RunStyles<DISTANCE, VALUE>::AllSame() const {
 	for (int run = 1; run < starts->Partitions(); run++) {
 		if (styles->ValueAt(run) != styles->ValueAt(run - 1))
 			return false;
@@ -234,13 +253,15 @@
 	return true;
 }
 
-bool RunStyles::AllSameAs(int value) const {
+template <typename DISTANCE, typename VALUE>
+bool RunStyles<DISTANCE, VALUE>::AllSameAs(VALUE value) const {
 	return AllSame() && (styles->ValueAt(0) == value);
 }
 
-int RunStyles::Find(int value, int start) const {
+template <typename DISTANCE, typename VALUE>
+DISTANCE RunStyles<DISTANCE, VALUE>::Find(VALUE value, DISTANCE start) const {
 	if (start < Length()) {
-		int run = start ? RunFromPosition(start) : 0;
+		DISTANCE run = start ? RunFromPosition(start) : 0;
 		if (styles->ValueAt(run) == value)
 			return start;
 		run++;
@@ -253,7 +274,8 @@
 	return -1;
 }
 
-void RunStyles::Check() const {
+template <typename DISTANCE, typename VALUE>
+void RunStyles<DISTANCE, VALUE>::Check() const {
 	if (Length() < 0) {
 		throw std::runtime_error("RunStyles: Length can not be negative.");
 	}
@@ -263,9 +285,9 @@
 	if (starts->Partitions() != styles->Length()-1) {
 		throw std::runtime_error("RunStyles: Partitions and styles different lengths.");
 	}
-	int start=0;
+	DISTANCE start=0;
 	while (start < Length()) {
-		const int end = EndRun(start);
+		const DISTANCE end = EndRun(start);
 		if (start >= end) {
 			throw std::runtime_error("RunStyles: Partition is 0 length.");
 		}
@@ -280,3 +302,8 @@
 		}
 	}
 }
+
+template class Scintilla::RunStyles<int, int>;
+template class Scintilla::RunStyles<int, char>;
+template class Scintilla::RunStyles<ptrdiff_t, int>;
+template class Scintilla::RunStyles<ptrdiff_t, char>;
diff -r 71961187dbc2 -r 7f62c564bab3 src/RunStyles.h
--- a/src/RunStyles.h	Fri Jan 26 18:28:27 2018 +1100
+++ b/src/RunStyles.h	Fri Jan 26 20:45:31 2018 +1100
@@ -12,36 +12,37 @@
 
 namespace Scintilla {
 
+template <typename DISTANCE, typename VALUE>
 class RunStyles {
 private:
-	std::unique_ptr<Partitioning> starts;
-	std::unique_ptr<SplitVector<int>> styles;
-	int RunFromPosition(int position) const;
-	int SplitRun(int position);
-	void RemoveRun(int run);
-	void RemoveRunIfEmpty(int run);
-	void RemoveRunIfSameAsPrevious(int run);
+	std::unique_ptr<Partitioning<DISTANCE>> starts;
+	std::unique_ptr<SplitVector<VALUE>> styles;
+	DISTANCE RunFromPosition(DISTANCE position) const;
+	DISTANCE SplitRun(DISTANCE position);
+	void RemoveRun(DISTANCE run);
+	void RemoveRunIfEmpty(DISTANCE run);
+	void RemoveRunIfSameAsPrevious(DISTANCE run);
 public:
 	RunStyles();
 	// Deleted so RunStyles objects can not be copied.
 	RunStyles(const RunStyles &) = delete;
 	void operator=(const RunStyles &) = delete;
 	~RunStyles();
-	int Length() const;
-	int ValueAt(int position) const;
-	int FindNextChange(int position, int end) const;
-	int StartRun(int position) const;
-	int EndRun(int position) const;
+	DISTANCE Length() const;
+	VALUE ValueAt(DISTANCE position) const;
+	DISTANCE FindNextChange(DISTANCE position, DISTANCE end) const;
+	DISTANCE StartRun(DISTANCE position) const;
+	DISTANCE EndRun(DISTANCE position) const;
 	// Returns true if some values may have changed
-	bool FillRange(int &position, int value, int &fillLength);
-	void SetValueAt(int position, int value);
-	void InsertSpace(int position, int insertLength);
+	bool FillRange(DISTANCE &position, VALUE value, DISTANCE &fillLength);
+	void SetValueAt(DISTANCE position, VALUE value);
+	void InsertSpace(DISTANCE position, DISTANCE insertLength);
 	void DeleteAll();
-	void DeleteRange(int position, int deleteLength);
-	int Runs() const;
+	void DeleteRange(DISTANCE position, DISTANCE deleteLength);
+	DISTANCE Runs() const;
 	bool AllSame() const;
-	bool AllSameAs(int value) const;
-	int Find(int value, int start) const;
+	bool AllSameAs(VALUE value) const;
+	DISTANCE Find(VALUE value, DISTANCE start) const;
 
 	void Check() const;
 };
diff -r 71961187dbc2 -r 7f62c564bab3 src/SparseVector.h
--- a/src/SparseVector.h	Fri Jan 26 18:28:27 2018 +1100
+++ b/src/SparseVector.h	Fri Jan 26 20:45:31 2018 +1100
@@ -15,42 +15,42 @@
 template <typename T>
 class SparseVector {
 private:
-	std::unique_ptr<Partitioning> starts;
+	std::unique_ptr<Partitioning<Sci::Position>> starts;
 	std::unique_ptr<SplitVector<T>> values;
 	T empty;
 	// Deleted so SparseVector objects can not be copied.
 	SparseVector(const SparseVector &) = delete;
 	void operator=(const SparseVector &) = delete;
-	void ClearValue(int partition) {
+	void ClearValue(Sci::Position partition) {
 		values->SetValueAt(partition, T());
 	}
 public:
 	SparseVector() : empty() {
-		starts.reset(new Partitioning(8));
+		starts.reset(new Partitioning<Sci::Position>(8));
 		values.reset(new SplitVector<T>());
 		values->InsertEmpty(0, 2);
 	}
 	~SparseVector() {
 		starts.reset();
 		// starts dead here but not used by ClearValue.
-		for (int part = 0; part < values->Length(); part++) {
+		for (Sci::Position part = 0; part < values->Length(); part++) {
 			ClearValue(part);
 		}
 		values.reset();
 	}
-	int Length() const {
+	Sci::Position Length() const {
 		return starts->PositionFromPartition(starts->Partitions());
 	}
-	int Elements() const {
+	Sci::Position Elements() const {
 		return starts->Partitions();
 	}
-	int PositionOfElement(int element) const {
+	Sci::Position PositionOfElement(int element) const {
 		return starts->PositionFromPartition(element);
 	}
-	const T& ValueAt(int position) const {
+	const T& ValueAt(Sci::Position position) const {
 		assert(position < Length());
-		const int partition = starts->PartitionFromPosition(position);
-		const int startPartition = starts->PositionFromPartition(partition);
+		const Sci::Position partition = starts->PartitionFromPosition(position);
+		const Sci::Position startPartition = starts->PositionFromPartition(partition);
 		if (startPartition == position) {
 			return values->ValueAt(partition);
 		} else {
@@ -58,10 +58,10 @@
 		}
 	}
 	template <typename ParamType>
-	void SetValueAt(int position, ParamType &&value) {
+	void SetValueAt(Sci::Position position, ParamType &&value) {
 		assert(position < Length());
-		const int partition = starts->PartitionFromPosition(position);
-		const int startPartition = starts->PositionFromPartition(partition);
+		const Sci::Position partition = starts->PartitionFromPosition(position);
+		const Sci::Position startPartition = starts->PositionFromPartition(partition);
 		if (value == T()) {
 			// Setting the empty value is equivalent to deleting the position
 			if (position == 0) {
@@ -85,10 +85,10 @@
 			}
 		}
 	}
-	void InsertSpace(int position, int insertLength) {
+	void InsertSpace(Sci::Position position, Sci::Position insertLength) {
 		assert(position <= Length());	// Only operation that works at end.
-		const int partition = starts->PartitionFromPosition(position);
-		const int startPartition = starts->PositionFromPartition(partition);
+		const Sci::Position partition = starts->PartitionFromPosition(position);
+		const Sci::Position startPartition = starts->PositionFromPartition(partition);
 		if (startPartition == position) {
 			const bool positionOccupied = values->ValueAt(partition) != T();
 			// Inserting at start of run so make previous longer
@@ -111,10 +111,10 @@
 			starts->InsertText(partition, insertLength);
 		}
 	}
-	void DeletePosition(int position) {
+	void DeletePosition(Sci::Position position) {
 		assert(position < Length());
-		int partition = starts->PartitionFromPosition(position);
-		const int startPartition = starts->PositionFromPartition(partition);
+		Sci::Position partition = starts->PartitionFromPosition(position);
+		const Sci::Position startPartition = starts->PositionFromPartition(partition);
 		if (startPartition == position) {
 			if (partition == 0) {
 				ClearValue(0);
diff -r 71961187dbc2 -r 7f62c564bab3 test/unit/testPartitioning.cxx
--- a/test/unit/testPartitioning.cxx	Fri Jan 26 18:28:27 2018 +1100
+++ b/test/unit/testPartitioning.cxx	Fri Jan 26 20:45:31 2018 +1100
@@ -26,7 +26,7 @@
 
 TEST_CASE("SplitVectorWithRangeAdd") {
 
-	SplitVectorWithRangeAdd svwra(growSize);
+	SplitVectorWithRangeAdd<int> svwra(growSize);
 
 	SECTION("IsEmptyInitially") {
 		REQUIRE(0 == svwra.Length());
@@ -49,7 +49,7 @@
 
 TEST_CASE("Partitioning") {
 
-	Partitioning part(growSize);
+	Partitioning<Sci::Position> part(growSize);
 
 	SECTION("IsEmptyInitially") {
 		REQUIRE(1 == part.Partitions());
diff -r 71961187dbc2 -r 7f62c564bab3 test/unit/testRunStyles.cxx
--- a/test/unit/testRunStyles.cxx	Fri Jan 26 18:28:27 2018 +1100
+++ b/test/unit/testRunStyles.cxx	Fri Jan 26 20:45:31 2018 +1100
@@ -22,7 +22,7 @@
 
 TEST_CASE("RunStyles") {
 
-	RunStyles rs;
+	RunStyles<int, int> rs;
 
 	SECTION("IsEmptyInitially") {
 		REQUIRE(0 == rs.Length());
