# HG changeset patch
# User Neil <nyamatongwe@gmail.com>
# Date 1516944796 -39600
#      Fri Jan 26 16:33:16 2018 +1100
# Node ID 089882f5533fdbf3cc53ab56d8cfe9b4f090c35c
# Parent  a16bf3b9ca60737e276c7549ff86e3253df336b5
Add SC_DOCUMENTOPTION_NOSTYLES to stop allocating memory for character styles.

diff -r a16bf3b9ca60 -r 089882f5533f doc/ScintillaDoc.html
--- a/doc/ScintillaDoc.html	Fri Jan 26 11:12:10 2018 +1100
+++ b/doc/ScintillaDoc.html	Fri Jan 26 16:33:16 2018 +1100
@@ -5781,9 +5781,12 @@
      to allocate once rather than rely on the buffer growing as data is added.
      If <code>SCI_CREATELOADER</code> fails then 0 is returned.</p>
 
-    <p>The <code class="parameter">documentOption</code> argument may be used in future versions
-    to choose between different document capabilities which affect memory allocation and performance.
-    The only valid value for now is <code>SC_DOCUMENTOPTION_DEFAULT</code> (0).</p>
+    <p>The <code class="parameter">documentOption</code> argument
+    chooses between different document capabilities which affect memory allocation and performance with
+    <code>SC_DOCUMENTOPTION_DEFAULT</code> (0) choosing standard options.
+    <code>SC_DOCUMENTOPTION_NOSTYLES</code> (1) stops allocation of memory to style characters
+    which saves significant memory, often 40% with the whole document treated as being style 0.
+    Lexers may still produce visual styling by using indicators.</p>
 
 <h4>ILoader</h4>
 
diff -r a16bf3b9ca60 -r 089882f5533f doc/ScintillaHistory.html
--- a/doc/ScintillaHistory.html	Fri Jan 26 11:12:10 2018 +1100
+++ b/doc/ScintillaHistory.html	Fri Jan 26 16:33:16 2018 +1100
@@ -537,6 +537,9 @@
 	Released 26 October 2017.
 	</li>
 	<li>
+	Add SC_DOCUMENTOPTION_NOSTYLES option to stop allocating memory for character styles.
+	</li>
+	<li>
 	Add SCI_GETMOVEEXTENDSSELECTION to allow applications to add more
 	complex selection commands.
 	</li>
diff -r a16bf3b9ca60 -r 089882f5533f include/Scintilla.h
--- a/include/Scintilla.h	Fri Jan 26 11:12:10 2018 +1100
+++ b/include/Scintilla.h	Fri Jan 26 16:33:16 2018 +1100
@@ -959,6 +959,7 @@
 #define SCI_SETTECHNOLOGY 2630
 #define SCI_GETTECHNOLOGY 2631
 #define SC_DOCUMENTOPTION_DEFAULT 0
+#define SC_DOCUMENTOPTION_NOSTYLES 1
 #define SCI_CREATELOADER 2632
 #define SCI_FINDINDICATORSHOW 2640
 #define SCI_FINDINDICATORFLASH 2641
diff -r a16bf3b9ca60 -r 089882f5533f include/Scintilla.iface
--- a/include/Scintilla.iface	Fri Jan 26 11:12:10 2018 +1100
+++ b/include/Scintilla.iface	Fri Jan 26 16:33:16 2018 +1100
@@ -2541,6 +2541,7 @@
 
 enu DocumentOption=SC_DOCUMENTOPTION_
 val SC_DOCUMENTOPTION_DEFAULT=0
+val SC_DOCUMENTOPTION_NOSTYLES=1
 
 # Create an ILoader*.
 fun int CreateLoader=2632(int bytes, int documentOption)
diff -r a16bf3b9ca60 -r 089882f5533f src/CellBuffer.cxx
--- a/src/CellBuffer.cxx	Fri Jan 26 11:12:10 2018 +1100
+++ b/src/CellBuffer.cxx	Fri Jan 26 16:33:16 2018 +1100
@@ -342,7 +342,8 @@
 	currentAction++;
 }
 
-CellBuffer::CellBuffer() {
+CellBuffer::CellBuffer(bool hasStyles_) :
+	hasStyles(hasStyles_) {
 	readOnly = false;
 	utf8LineEnds = 0;
 	collectingUndo = true;
@@ -369,7 +370,7 @@
 }
 
 char CellBuffer::StyleAt(Sci::Position position) const {
-	return style.ValueAt(position);
+	return hasStyles ? style.ValueAt(position) : 0;
 }
 
 void CellBuffer::GetStyleRange(unsigned char *buffer, Sci::Position position, Sci::Position lengthRetrieve) const {
@@ -377,6 +378,10 @@
 		return;
 	if (position < 0)
 		return;
+	if (!hasStyles) {
+		std::fill(buffer, buffer + lengthRetrieve, static_cast<unsigned char>(0));
+		return;
+	}
 	if ((position + lengthRetrieve) > style.Length()) {
 		Platform::DebugPrintf("Bad GetStyleRange %d for %d of %d\n", position,
 		                      lengthRetrieve, style.Length());
@@ -414,6 +419,9 @@
 }
 
 bool CellBuffer::SetStyleAt(Sci::Position position, char styleValue) {
+	if (!hasStyles) {
+		return false;
+	}
 	const char curVal = style.ValueAt(position);
 	if (curVal != styleValue) {
 		style.SetValueAt(position, styleValue);
@@ -424,6 +432,9 @@
 }
 
 bool CellBuffer::SetStyleFor(Sci::Position position, Sci::Position lengthStyle, char styleValue) {
+	if (!hasStyles) {
+		return false;
+	}
 	bool changed = false;
 	PLATFORM_ASSERT(lengthStyle == 0 ||
 		(lengthStyle > 0 && lengthStyle + position <= style.Length()));
@@ -462,7 +473,9 @@
 
 void CellBuffer::Allocate(Sci::Position newSize) {
 	substance.ReAllocate(newSize);
-	style.ReAllocate(newSize);
+	if (hasStyles) {
+		style.ReAllocate(newSize);
+	}
 }
 
 void CellBuffer::SetLineEndTypes(int utf8LineEnds_) {
@@ -608,7 +621,9 @@
 	}
 
 	substance.InsertFromArray(position, s, 0, insertLength);
-	style.InsertValue(position, insertLength, 0);
+	if (hasStyles) {
+		style.InsertValue(position, insertLength, 0);
+	}
 
 	Sci::Line lineInsert = lv.LineFromPosition(position) + 1;
 	bool atLineStart = lv.LineStart(lineInsert-1) == position;
@@ -738,7 +753,9 @@
 		}
 	}
 	substance.DeleteRange(position, deleteLength);
-	style.DeleteRange(position, deleteLength);
+	if (hasStyles) {
+		style.DeleteRange(position, deleteLength);
+	}
 }
 
 bool CellBuffer::SetUndoCollection(bool collectUndo) {
diff -r a16bf3b9ca60 -r 089882f5533f src/CellBuffer.h
--- a/src/CellBuffer.h	Fri Jan 26 11:12:10 2018 +1100
+++ b/src/CellBuffer.h	Fri Jan 26 16:33:16 2018 +1100
@@ -133,6 +133,7 @@
  */
 class CellBuffer {
 private:
+	bool hasStyles;
 	SplitVector<char> substance;
 	SplitVector<char> style;
 	bool readOnly;
@@ -151,7 +152,7 @@
 
 public:
 
-	CellBuffer();
+	CellBuffer(bool hasStyles_);
 	// Deleted so CellBuffer objects can not be copied.
 	CellBuffer(const CellBuffer &) = delete;
 	void operator=(const CellBuffer &) = delete;
diff -r a16bf3b9ca60 -r 089882f5533f src/Document.cxx
--- a/src/Document.cxx	Fri Jan 26 11:12:10 2018 +1100
+++ b/src/Document.cxx	Fri Jan 26 16:33:16 2018 +1100
@@ -89,7 +89,8 @@
 	return 0;
 }
 
-Document::Document() {
+Document::Document(int options) :
+	cb((options & SC_DOCUMENTOPTION_NOSTYLES) == 0) {
 	refCount = 0;
 #ifdef _WIN32
 	eolMode = SC_EOL_CRLF;
diff -r a16bf3b9ca60 -r 089882f5533f src/Document.h
--- a/src/Document.h	Fri Jan 26 11:12:10 2018 +1100
+++ b/src/Document.h	Fri Jan 26 16:33:16 2018 +1100
@@ -265,7 +265,7 @@
 
 	DecorationList decorations;
 
-	Document();
+	Document(int options);
 	// Deleted so Document objects can not be copied.
 	Document(const Document &) = delete;
 	void operator=(const Document &) = delete;
diff -r a16bf3b9ca60 -r 089882f5533f src/EditModel.cxx
--- a/src/EditModel.cxx	Fri Jan 26 11:12:10 2018 +1100
+++ b/src/EditModel.cxx	Fri Jan 26 16:33:16 2018 +1100
@@ -69,7 +69,7 @@
 	hotspot = Range(Sci::invalidPosition);
 	hoverIndicatorPos = Sci::invalidPosition;
 	wrapWidth = LineLayout::wrapWidthInfinite;
-	pdoc = new Document();
+	pdoc = new Document(SC_DOCUMENTOPTION_DEFAULT);
 	pdoc->AddRef();
 }
 
diff -r a16bf3b9ca60 -r 089882f5533f src/Editor.cxx
--- a/src/Editor.cxx	Fri Jan 26 11:12:10 2018 +1100
+++ b/src/Editor.cxx	Fri Jan 26 16:33:16 2018 +1100
@@ -5162,7 +5162,7 @@
 	pdoc->RemoveWatcher(this, 0);
 	pdoc->Release();
 	if (document == NULL) {
-		pdoc = new Document();
+		pdoc = new Document(SC_DOCUMENTOPTION_DEFAULT);
 	} else {
 		pdoc = document;
 	}
@@ -7554,7 +7554,7 @@
 		return 0;
 
 	case SCI_CREATEDOCUMENT: {
-			Document *doc = new Document();
+			Document *doc = new Document(SC_DOCUMENTOPTION_DEFAULT);
 			doc->AddRef();
 			return reinterpret_cast<sptr_t>(doc);
 		}
@@ -7568,7 +7568,7 @@
 		break;
 
 	case SCI_CREATELOADER: {
-			Document *doc = new Document();
+			Document *doc = new Document(static_cast<int>(lParam));
 			doc->AddRef();
 			doc->Allocate(static_cast<int>(wParam));
 			doc->SetUndoCollection(false);
diff -r a16bf3b9ca60 -r 089882f5533f test/unit/testCellBuffer.cxx
--- a/test/unit/testCellBuffer.cxx	Fri Jan 26 11:12:10 2018 +1100
+++ b/test/unit/testCellBuffer.cxx	Fri Jan 26 16:33:16 2018 +1100
@@ -25,7 +25,7 @@
 	const char sText[] = "Scintilla";
 	const Sci::Position sLength = static_cast<Sci::Position>(strlen(sText));
 
-	CellBuffer cb;
+	CellBuffer cb(true);
 	
 	SECTION("InsertOneLine") {
 		bool startSequence = false;
