SF.net SVN: geany: [2086] trunk

eht16 at users.sourceforge.net eht16 at xxxxx
Sun Dec 2 11:58:18 UTC 2007


Revision: 2086
          http://geany.svn.sourceforge.net/geany/?rev=2086&view=rev
Author:   eht16
Date:     2007-12-02 03:58:17 -0800 (Sun, 02 Dec 2007)

Log Message:
-----------
Updated Scintilla to version 1.75.

Modified Paths:
--------------
    trunk/ChangeLog
    trunk/scintilla/CellBuffer.cxx
    trunk/scintilla/CellBuffer.h
    trunk/scintilla/ContractionState.cxx
    trunk/scintilla/ContractionState.h
    trunk/scintilla/Document.cxx
    trunk/scintilla/Document.h
    trunk/scintilla/DocumentAccessor.cxx
    trunk/scintilla/Editor.cxx
    trunk/scintilla/Editor.h
    trunk/scintilla/LexBash.cxx
    trunk/scintilla/LexCPP.cxx
    trunk/scintilla/LexHTML.cxx
    trunk/scintilla/LexHaskell.cxx
    trunk/scintilla/LexOthers.cxx
    trunk/scintilla/LexPerl.cxx
    trunk/scintilla/LexPython.cxx
    trunk/scintilla/LexSQL.cxx
    trunk/scintilla/Partitioning.h
    trunk/scintilla/PlatGTK.cxx
    trunk/scintilla/PositionCache.cxx
    trunk/scintilla/PositionCache.h
    trunk/scintilla/PropSet.cxx
    trunk/scintilla/RunStyles.cxx
    trunk/scintilla/RunStyles.h
    trunk/scintilla/ScintillaBase.cxx
    trunk/scintilla/ScintillaGTK.cxx
    trunk/scintilla/SplitVector.h
    trunk/scintilla/ViewStyle.cxx
    trunk/scintilla/ViewStyle.h
    trunk/scintilla/include/Platform.h
    trunk/scintilla/include/PropSet.h
    trunk/scintilla/include/SciLexer.h
    trunk/scintilla/include/Scintilla.h

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2007-12-02 10:52:19 UTC (rev 2085)
+++ trunk/ChangeLog	2007-12-02 11:58:17 UTC (rev 2086)
@@ -7,6 +7,7 @@
    Make path entry of filebrowser plugin editable.
    Add "Open with" and "Find in Files" popup menu items to filebrowser
    plugin and add configuration dialog.
+ * scintilla/*, scintilla/include/*: Updated Scintilla to version 1.75.
 
 
 2007-12-01  Enrico Tröger  <enrico(dot)troeger(at)uvena(dot)de>

Modified: trunk/scintilla/CellBuffer.cxx
===================================================================
--- trunk/scintilla/CellBuffer.cxx	2007-12-02 10:52:19 UTC (rev 2085)
+++ trunk/scintilla/CellBuffer.cxx	2007-12-02 11:58:17 UTC (rev 2086)
@@ -13,7 +13,6 @@
 #include "Platform.h"
 
 #include "Scintilla.h"
-#include "SVector.h"
 #include "SplitVector.h"
 #include "Partitioning.h"
 #include "CellBuffer.h"
@@ -472,6 +471,7 @@
 }
 
 void UndoHistory::EndUndoAction() {
+	PLATFORM_ASSERT(undoSequenceDepth > 0);
 	EnsureUndoRoom();
 	undoSequenceDepth--;
 	if (0 == undoSequenceDepth) {
@@ -563,7 +563,7 @@
 CellBuffer::~CellBuffer() {
 }
 
-char CellBuffer::CharAt(int position) {
+char CellBuffer::CharAt(int position) const {
 	return substance.ValueAt(position);
 }
 
@@ -653,7 +653,7 @@
 	return data;
 }
 
-int CellBuffer::Length() {
+int CellBuffer::Length() const {
 	return substance.Length();
 }
 
@@ -662,11 +662,11 @@
 	style.ReAllocate(newSize);
 }
 
-int CellBuffer::Lines() {
+int CellBuffer::Lines() const {
 	return lv.Lines();
 }
 
-int CellBuffer::LineStart(int line) {
+int CellBuffer::LineStart(int line) const {
 	if (line < 0)
 		return 0;
 	else if (line >= Lines())
@@ -726,6 +726,20 @@
 
 // Without undo
 
+void CellBuffer::InsertLine(int line, int position) {
+	lv.InsertLine(line, position);
+	if (lineStates.Length()) {
+		lineStates.Insert(line, 0);
+	}
+}
+
+void CellBuffer::RemoveLine(int line) {
+	lv.RemoveLine(line);
+	if (lineStates.Length()) {
+		lineStates.Delete(line);
+	}
+}
+
 void CellBuffer::BasicInsertString(int position, const char *s, int insertLength) {
 	if (insertLength == 0)
 		return;
@@ -741,21 +755,21 @@
 	char chAfter = substance.ValueAt(position + insertLength);
 	if (chPrev == '\r' && chAfter == '\n') {
 		// Splitting up a crlf pair at position
-		lv.InsertLine(lineInsert, position);
+		InsertLine(lineInsert, position);
 		lineInsert++;
 	}
 	char ch = ' ';
 	for (int i = 0; i < insertLength; i++) {
 		ch = s[i];
 		if (ch == '\r') {
-			lv.InsertLine(lineInsert, (position + i) + 1);
+			InsertLine(lineInsert, (position + i) + 1);
 			lineInsert++;
 		} else if (ch == '\n') {
 			if (chPrev == '\r') {
 				// Patch up what was end of line
 				lv.SetLineStart(lineInsert - 1, (position + i) + 1);
 			} else {
-				lv.InsertLine(lineInsert, (position + i) + 1);
+				InsertLine(lineInsert, (position + i) + 1);
 				lineInsert++;
 			}
 		}
@@ -765,7 +779,7 @@
 	if (chAfter == '\n') {
 		if (ch == '\r') {
 			// End of line already in buffer so drop the newly created one
-			lv.RemoveLine(lineInsert - 1);
+			RemoveLine(lineInsert - 1);
 		}
 	}
 }
@@ -800,13 +814,13 @@
 			chNext = substance.ValueAt(position + i + 1);
 			if (ch == '\r') {
 				if (chNext != '\n') {
-					lv.RemoveLine(lineRemove);
+					RemoveLine(lineRemove);
 				}
 			} else if (ch == '\n') {
 				if (ignoreNL) {
 					ignoreNL = false; 	// Further \n are real deletions
 				} else {
-					lv.RemoveLine(lineRemove);
+					RemoveLine(lineRemove);
 				}
 			}
 
@@ -817,7 +831,7 @@
 		char chAfter = substance.ValueAt(position + deleteLength);
 		if (chBefore == '\r' && chAfter == '\n') {
 			// Using lineRemove-1 as cr ended line before start of deletion
-			lv.RemoveLine(lineRemove - 1);
+			RemoveLine(lineRemove - 1);
 			lv.SetLineStart(lineRemove - 1, position + 1);
 		}
 	}
@@ -892,12 +906,14 @@
 }
 
 int CellBuffer::SetLineState(int line, int state) {
+	lineStates.EnsureLength(line + 1);
 	int stateOld = lineStates[line];
 	lineStates[line] = state;
 	return stateOld;
 }
 
 int CellBuffer::GetLineState(int line) {
+	lineStates.EnsureLength(line + 1);
 	return lineStates[line];
 }
 

Modified: trunk/scintilla/CellBuffer.h
===================================================================
--- trunk/scintilla/CellBuffer.h	2007-12-02 10:52:19 UTC (rev 2085)
+++ trunk/scintilla/CellBuffer.h	2007-12-02 11:58:17 UTC (rev 2086)
@@ -67,11 +67,11 @@
 	void InsertLine(int line, int position);
 	void SetLineStart(int line, int position);
 	void RemoveLine(int line);
-	int Lines() {
+	int Lines() const {
 		return starts.Partitions();
 	}
 	int LineFromPosition(int pos);
-	int LineStart(int line) {
+	int LineStart(int line) const {
 		return starts.PositionFromPartition(line);
 	}
 
@@ -160,7 +160,7 @@
 
 	LineVector lv;
 
-	SVector lineStates;
+	SplitVector<int> lineStates;
 
 public:
 
@@ -168,15 +168,17 @@
 	~CellBuffer();
 
 	/// Retrieving positions outside the range of the buffer works and returns 0
-	char CharAt(int position);
+	char CharAt(int position) const;
 	void GetCharRange(char *buffer, int position, int lengthRetrieve);
 	char StyleAt(int position);
 
-	int Length();
+	int Length() const;
 	void Allocate(int newSize);
-	int Lines();
-	int LineStart(int line);
+	int Lines() const;
+	int LineStart(int line) const;
 	int LineFromPosition(int pos) { return lv.LineFromPosition(pos); }
+	void InsertLine(int line, int position);
+	void RemoveLine(int line);
 	const char *InsertString(int position, const char *s, int insertLength, bool &startSequence);
 
 	/// Setting styles for positions outside the range of the buffer is safe and has no effect.

Modified: trunk/scintilla/ContractionState.cxx
===================================================================
--- trunk/scintilla/ContractionState.cxx	2007-12-02 10:52:19 UTC (rev 2085)
+++ trunk/scintilla/ContractionState.cxx	2007-12-02 11:58:17 UTC (rev 2086)
@@ -1,293 +1,251 @@
 // Scintilla source code edit control
 /** @file ContractionState.cxx
- ** Manages visibility of lines for folding.
+ ** Manages visibility of lines for folding and wrapping.
  **/
-// Copyright 1998-2001 by Neil Hodgson <neilh at scintilla.org>
+// Copyright 1998-2007 by Neil Hodgson <neilh at scintilla.org>
 // The License.txt file describes the conditions under which this software may be distributed.
 
+#include <string.h>
+
 #include "Platform.h"
 
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
 #include "ContractionState.h"
 
 #ifdef SCI_NAMESPACE
 using namespace Scintilla;
 #endif
 
-OneLine::OneLine() {
-	displayLine = 0;
-	//docLine = 0;
-	visible = true;
-	height = 1;
-	expanded = true;
+ContractionState::ContractionState() : visible(0), expanded(0), heights(0), displayLines(0), linesInDocument(1) {
+	//InsertLine(0);
 }
 
-ContractionState::ContractionState() {
-	lines = 0;
-	size = 0;
-	linesInDoc = 1;
-	linesInDisplay = 1;
-	valid = false;
-	docLines = 0;
-	sizeDocLines = 0;
-}
-
 ContractionState::~ContractionState() {
 	Clear();
 }
 
-void ContractionState::MakeValid() const {
-	if (!valid) {
-		// Could be cleverer by keeping the index of the last still valid entry
-		// rather than invalidating all.
-		linesInDisplay = 0;
-		for (int lineInDoc=0; lineInDoc<linesInDoc; lineInDoc++) {
-			lines[lineInDoc].displayLine = linesInDisplay;
-			if (lines[lineInDoc].visible) {
-				linesInDisplay += lines[lineInDoc].height;
-			}
-		}
-		if (sizeDocLines < linesInDisplay) {
-			delete []docLines;
-			int *docLinesNew = new int[linesInDisplay + growSize];
-			if (!docLinesNew) {
-				docLines = 0;
-				sizeDocLines = 0;
-				return;
-			}
-			docLines = docLinesNew;
-			sizeDocLines = linesInDisplay + growSize;
-		}
-
-		int lineInDisplay=0;
-		for (int line=0; line<linesInDoc; line++) {
-			if (lines[line].visible) {
-				for (int linePiece=0; linePiece<lines[line].height; linePiece++) {
-					docLines[lineInDisplay] = line;
-					lineInDisplay++;
-				}
-			}
-		}
-		valid = true;
+void ContractionState::EnsureData() {
+	if (OneToOne()) {
+		visible = new RunStyles();
+		expanded = new RunStyles();
+		heights = new RunStyles();
+		displayLines = new Partitioning(4);
+		InsertLines(0, linesInDocument);
 	}
 }
 
 void ContractionState::Clear() {
-	delete []lines;
-	lines = 0;
-	size = 0;
-	linesInDoc = 1;
-	linesInDisplay = 1;
-	delete []docLines;
-	docLines = 0;
-	sizeDocLines = 0;
+	delete visible;
+	visible = 0;
+	delete expanded;
+	expanded = 0;
+	delete heights;
+	heights = 0;
+	delete displayLines;
+	displayLines = 0;
+	linesInDocument = 1;
 }
 
 int ContractionState::LinesInDoc() const {
-	return linesInDoc;
+	if (OneToOne()) {
+		return linesInDocument;
+	} else {
+		return displayLines->Partitions() - 1;
+	}
 }
 
 int ContractionState::LinesDisplayed() const {
-	if (size != 0) {
-		MakeValid();
+	if (OneToOne()) {
+		return linesInDocument;
+	} else {
+		return displayLines->PositionFromPartition(LinesInDoc());
 	}
-	return linesInDisplay;
 }
 
 int ContractionState::DisplayFromDoc(int lineDoc) const {
-	if (size == 0) {
+	if (OneToOne()) {
 		return lineDoc;
+	} else {
+		if (lineDoc > displayLines->Partitions())
+			lineDoc = displayLines->Partitions();
+		return displayLines->PositionFromPartition(lineDoc);
 	}
-	MakeValid();
-	if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
-		return lines[lineDoc].displayLine;
-	}
-	return -1;
 }
 
 int ContractionState::DocFromDisplay(int lineDisplay) const {
-	if (lineDisplay <= 0)
-		return 0;
-	if (lineDisplay >= linesInDisplay)
-		return linesInDoc;
-	if (size == 0)
+	if (OneToOne()) {
 		return lineDisplay;
-	MakeValid();
-	if (docLines) {	// Valid allocation
-		return docLines[lineDisplay];
 	} else {
-		return 0;
+		if (lineDisplay <= 0) {
+			return 0;
+		}
+		if (lineDisplay > LinesDisplayed()) {
+			return displayLines->PartitionFromPosition(LinesDisplayed());
+		}
+		int lineDoc = displayLines->PartitionFromPosition(lineDisplay);
+		PLATFORM_ASSERT(GetVisible(lineDoc));
+		return lineDoc;
 	}
 }
 
-void ContractionState::Grow(int sizeNew) {
-	OneLine *linesNew = new OneLine[sizeNew];
-	if (linesNew) {
-		int i = 0;
-		for (; i < size; i++) {
-			linesNew[i] = lines[i];
-		}
-		for (; i < sizeNew; i++) {
-			linesNew[i].displayLine = i;
-		}
-		delete []lines;
-		lines = linesNew;
-		size = sizeNew;
-		valid = false;
+void ContractionState::InsertLine(int lineDoc) {
+	if (OneToOne()) {
+		linesInDocument++;
 	} else {
-		Platform::DebugPrintf("No memory available\n");
-		// TODO: Blow up
+		visible->InsertSpace(lineDoc, 1);
+		visible->SetValueAt(lineDoc, 1);
+		expanded->InsertSpace(lineDoc, 1);
+		expanded->SetValueAt(lineDoc, 1);
+		heights->InsertSpace(lineDoc, 1);
+		heights->SetValueAt(lineDoc, 1);
+		int lineDisplay = DisplayFromDoc(lineDoc);
+		displayLines->InsertPartition(lineDoc, lineDisplay);
+		displayLines->InsertText(lineDoc, 1);
 	}
 }
 
 void ContractionState::InsertLines(int lineDoc, int lineCount) {
-	if (size == 0) {
-		linesInDoc += lineCount;
-		linesInDisplay += lineCount;
-		return;
+	for (int l = 0; l < lineCount; l++) {
+		InsertLine(lineDoc + l);
 	}
-	//Platform::DebugPrintf("InsertLine[%d] = %d\n", lineDoc);
-	if ((linesInDoc + lineCount + 2) >= size) {
-		Grow(linesInDoc + lineCount + growSize);
+	Check();
+}
+
+void ContractionState::DeleteLine(int lineDoc) {
+	if (OneToOne()) {
+		linesInDocument--;
+	} else {
+		if (GetVisible(lineDoc)) {
+			displayLines->InsertText(lineDoc, -heights->ValueAt(lineDoc));
+		}
+		displayLines->RemovePartition(lineDoc);
+		visible->DeleteRange(lineDoc, 1);
+		expanded->DeleteRange(lineDoc, 1);
+		heights->DeleteRange(lineDoc, 1);
 	}
-	linesInDoc += lineCount;
-	for (int i = linesInDoc; i >= lineDoc + lineCount; i--) {
-		lines[i].visible = lines[i - lineCount].visible;
-		lines[i].height = lines[i - lineCount].height;
-		linesInDisplay += lines[i].height;
-		lines[i].expanded = lines[i - lineCount].expanded;
-	}
-	for (int d=0;d<lineCount;d++) {
-		lines[lineDoc+d].visible = true;	// Should inherit visibility from context ?
-		lines[lineDoc+d].height = 1;
-		lines[lineDoc+d].expanded = true;
-	}
-	valid = false;
 }
 
 void ContractionState::DeleteLines(int lineDoc, int lineCount) {
-	if (size == 0) {
-		linesInDoc -= lineCount;
-		linesInDisplay -= lineCount;
-		return;
+	for (int l = 0; l < lineCount; l++) {
+		DeleteLine(lineDoc);
 	}
-	int deltaDisplayed = 0;
-	for (int d=0;d<lineCount;d++) {
-		if (lines[lineDoc+d].visible)
-			deltaDisplayed -= lines[lineDoc+d].height;
-	}
-	for (int i = lineDoc; i < linesInDoc-lineCount; i++) {
-		if (i != 0) // Line zero is always visible
-			lines[i].visible = lines[i + lineCount].visible;
-		lines[i].expanded = lines[i + lineCount].expanded;
-		lines[i].height = lines[i + lineCount].height;
-	}
-	linesInDoc -= lineCount;
-	linesInDisplay += deltaDisplayed;
-	valid = false;
+	Check();
 }
 
 bool ContractionState::GetVisible(int lineDoc) const {
-	if (size == 0)
+	if (OneToOne()) {
 		return true;
-	if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
-		return lines[lineDoc].visible;
 	} else {
-		return false;
+		if (lineDoc >= visible->Length())
+			return true;
+		return visible->ValueAt(lineDoc) == 1;
 	}
 }
 
-bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible) {
-	if (lineDocStart == 0)
-		lineDocStart++;
-	if (lineDocStart > lineDocEnd)
+bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible_) {
+	if (OneToOne() && visible_) {
 		return false;
-	if (size == 0) {
-		Grow(linesInDoc + growSize);
-	}
-	// TODO: modify docLine members to mirror displayLine
-	int delta = 0;
-	// Change lineDocs
-	if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < linesInDoc)) {
-		for (int line=lineDocStart; line <= lineDocEnd; line++) {
-			if (lines[line].visible != visible) {
-				delta += visible ? lines[line].height : -lines[line].height;
-				lines[line].visible = visible;
-				valid = false;
+	} else {
+		EnsureData();
+		int delta = 0;
+		Check();
+		if ((lineDocStart <= lineDocEnd) && (lineDocStart >= 0) && (lineDocEnd < LinesInDoc())) {
+			for (int line = lineDocStart; line <= lineDocEnd; line++) {
+				if (GetVisible(line) != visible_) {
+					int difference = visible_ ? heights->ValueAt(line) : -heights->ValueAt(line);
+					visible->SetValueAt(line, visible_ ? 1 : 0);
+					displayLines->InsertText(line, difference);
+					delta += difference;
+				}
 			}
+		} else {
+			return false;
 		}
+		Check();
+		return delta != 0;
 	}
-	linesInDisplay += delta;
-	return delta != 0;
 }
 
 bool ContractionState::GetExpanded(int lineDoc) const {
-	if (size == 0)
+	if (OneToOne()) {
 		return true;
-	if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
-		return lines[lineDoc].expanded;
 	} else {
-		return false;
+		Check();
+		return expanded->ValueAt(lineDoc) == 1;
 	}
 }
 
-bool ContractionState::SetExpanded(int lineDoc, bool expanded) {
-	if (size == 0) {
-		if (expanded) {
-			// If in completely expanded state then setting
-			// one line to expanded has no effect.
+bool ContractionState::SetExpanded(int lineDoc, bool expanded_) {
+	if (OneToOne() && expanded_) {
+		return false;
+	} else {
+		EnsureData();
+		if (expanded_ != (expanded->ValueAt(lineDoc) == 1)) {
+			expanded->SetValueAt(lineDoc, expanded_ ? 1 : 0);
+			Check();
+			return true;
+		} else {
+			Check();
 			return false;
 		}
-		Grow(linesInDoc + growSize);
 	}
-	if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
-		if (lines[lineDoc].expanded != expanded) {
-			lines[lineDoc].expanded = expanded;
-			return true;
-		}
-	}
-	return false;
 }
 
 int ContractionState::GetHeight(int lineDoc) const {
-	if (size == 0)
+	if (OneToOne()) {
 		return 1;
-	if ((lineDoc >= 0) && (lineDoc < linesInDoc)) {
-		return lines[lineDoc].height;
 	} else {
-		return 1;
+		return heights->ValueAt(lineDoc);
 	}
 }
 
 // Set the number of display lines needed for this line.
 // Return true if this is a change.
 bool ContractionState::SetHeight(int lineDoc, int height) {
-	if (lineDoc > linesInDoc)
+	if (OneToOne() && (height == 1)) {
 		return false;
-	if (size == 0) {
-		if (height == 1) {
-			// If in completely expanded state then all lines
-			// assumed to have height of one so no effect here.
+	} else {
+		EnsureData();
+		if (GetHeight(lineDoc) != height) {
+			if (GetVisible(lineDoc)) {
+				displayLines->InsertText(lineDoc, height - GetHeight(lineDoc));
+			}
+			heights->SetValueAt(lineDoc, height);
+			Check();
+			return true;
+		} else {
+			Check();
 			return false;
 		}
-		Grow(linesInDoc + growSize);
 	}
-	if (lines[lineDoc].height != height) {
-		lines[lineDoc].height = height;
-		valid = false;
-		return true;
-	} else {
-		return false;
-	}
 }
 
 void ContractionState::ShowAll() {
-	delete []lines;
-	lines = 0;
-	size = 0;
+	int lines = LinesInDoc();
+	Clear();
+	linesInDocument = lines;
+}
 
-	delete []docLines;
-	docLines = 0;
-	sizeDocLines = 0;
+// Debugging checks
 
-	linesInDisplay = linesInDoc;
+void ContractionState::Check() const {
+#ifdef CHECK_CORRECTNESS
+	for (int vline = 0;vline < LinesDisplayed(); vline++) {
+		const int lineDoc = DocFromDisplay(vline);
+		PLATFORM_ASSERT(GetVisible(lineDoc));
+	}
+	for (int lineDoc = 0;lineDoc < LinesInDoc(); lineDoc++) {
+		const int displayThis = DisplayFromDoc(lineDoc);
+		const int displayNext = DisplayFromDoc(lineDoc + 1);
+		const int height = displayNext - displayThis;
+		PLATFORM_ASSERT(height >= 0);
+		if (GetVisible(lineDoc)) {
+			PLATFORM_ASSERT(GetHeight(lineDoc) == height);
+		} else {
+			PLATFORM_ASSERT(0 == height);
+		}
+	}
+#endif
 }

Modified: trunk/scintilla/ContractionState.h
===================================================================
--- trunk/scintilla/ContractionState.h	2007-12-02 10:52:19 UTC (rev 2085)
+++ trunk/scintilla/ContractionState.h	2007-12-02 11:58:17 UTC (rev 2086)
@@ -1,8 +1,8 @@
 // Scintilla source code edit control
 /** @file ContractionState.h
- ** Manages visibility of lines for folding.
+ ** Manages visibility of lines for folding and wrapping.
  **/
-// Copyright 1998-2001 by Neil Hodgson <neilh at scintilla.org>
+// Copyright 1998-2007 by Neil Hodgson <neilh at scintilla.org>
 // The License.txt file describes the conditions under which this software may be distributed.
 
 #ifndef CONTRACTIONSTATE_H
@@ -14,31 +14,21 @@
 
 /**
  */
-class OneLine {
-public:
-	int displayLine;	///< Position within set of visible lines
-	//int docLine;		///< Inverse of @a displayLine
-	int height;	///< Number of display lines needed to show all of the line
-	bool visible;
-	bool expanded;
+class ContractionState {
+	// These contain 1 element for every document line.
+	RunStyles *visible;
+	RunStyles *expanded;
+	RunStyles *heights;
+	Partitioning *displayLines;
+	int linesInDocument;
 
-	OneLine();
-	virtual ~OneLine() {}
-};
+	void EnsureData();
 
-/**
- */
-class ContractionState {
-	void Grow(int sizeNew);
-	enum { growSize = 4000 };
-	int linesInDoc;
-	mutable int linesInDisplay;
-	mutable OneLine *lines;
-	int size;
-	mutable int *docLines;
-	mutable int sizeDocLines;
-	mutable bool valid;
-	void MakeValid() const;
+	bool OneToOne() const {
+		// True when each document line is exactly one display line so need for
+		// complex data structures.
+		return visible == 0;
+	}
 
 public:
 	ContractionState();
@@ -51,7 +41,9 @@
 	int DisplayFromDoc(int lineDoc) const;
 	int DocFromDisplay(int lineDisplay) const;
 
+	void InsertLine(int lineDoc);
 	void InsertLines(int lineDoc, int lineCount);
+	void DeleteLine(int lineDoc);
 	void DeleteLines(int lineDoc, int lineCount);
 
 	bool GetVisible(int lineDoc) const;
@@ -64,6 +56,7 @@
 	bool SetHeight(int lineDoc, int height);
 
 	void ShowAll();
+	void Check() const;
 };
 
 #ifdef SCI_NAMESPACE

Modified: trunk/scintilla/Document.cxx
===================================================================
--- trunk/scintilla/Document.cxx	2007-12-02 10:52:19 UTC (rev 2085)
+++ trunk/scintilla/Document.cxx	2007-12-02 11:58:17 UTC (rev 2086)
@@ -13,7 +13,6 @@
 #include "Platform.h"
 
 #include "Scintilla.h"
-#include "SVector.h"
 #include "SplitVector.h"
 #include "Partitioning.h"
 #include "RunStyles.h"
@@ -113,7 +112,6 @@
 int Document::AddMark(int line, int markerNum) {
 	int prev = cb.AddMark(line, markerNum);
 	DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
-	mh.line = line;
 	NotifyModified(mh);
 	return prev;
 }
@@ -124,14 +122,12 @@
 		if (m & 1)
 			cb.AddMark(line, i);
 	DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
-	mh.line = line;
 	NotifyModified(mh);
 }
 
 void Document::DeleteMark(int line, int markerNum) {
 	cb.DeleteMark(line, markerNum);
 	DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
-	mh.line = line;
 	NotifyModified(mh);
 }
 
@@ -149,11 +145,11 @@
 	NotifyModified(mh);
 }
 
-int Document::LineStart(int line) {
+int Document::LineStart(int line) const {
 	return cb.LineStart(line);
 }
 
-int Document::LineEnd(int line) {
+int Document::LineEnd(int line) const {
 	if (line == LinesTotal() - 1) {
 		return LineStart(line + 1);
 	} else {
@@ -191,8 +187,7 @@
 	int prev = cb.SetLevel(line, level);
 	if (prev != level) {
 		DocModification mh(SC_MOD_CHANGEFOLD | SC_MOD_CHANGEMARKER,
-		                   LineStart(line), 0, 0, 0);
-		mh.line = line;
+		                   LineStart(line), 0, 0, 0, line);
 		mh.foldLevelNow = level;
 		mh.foldLevelPrev = prev;
 		NotifyModified(mh);
@@ -292,6 +287,55 @@
 	}
 }
 
+static bool IsTrailByte(int ch) {
+	return (ch >= 0x80) && (ch < (0x80 + 0x40));
+}
+
+static int BytesFromLead(int leadByte) {
+	if (leadByte > 0xF4) {
+		// Characters longer than 4 bytes not possible in current UTF-8
+		return 0;
+	} else if (leadByte >= 0xF0) {
+		return 4;
+	} else if (leadByte >= 0xE0) {
+		return 3;
+	} else if (leadByte >= 0xC2) {
+		return 2;
+	}
+	return 0;
+}
+
+bool Document::InGoodUTF8(int pos, int &start, int &end) {
+	int lead = pos;
+	while ((lead>0) && (pos-lead < 4) && IsTrailByte(static_cast<unsigned char>(cb.CharAt(lead-1))))
+		lead--;
+	start = 0;
+	if (lead > 0) {
+		start = lead-1;
+	}
+	int leadByte = static_cast<unsigned char>(cb.CharAt(start));
+	int bytes = BytesFromLead(leadByte);
+	if (bytes == 0) {
+		return false;
+	} else {
+		int trailBytes = bytes - 1;
+		int len = pos - lead + 1;
+		if (len > trailBytes)
+			// pos too far from lead
+			return false;
+		// Check that there are enough trails for this lead
+		int trail = pos + 1;
+		while ((trail-lead<trailBytes) && (trail < Length())) {
+			if (!IsTrailByte(static_cast<unsigned char>(cb.CharAt(trail)))) {
+				return false;
+			}
+			trail++;
+		}
+		end = start + bytes;
+		return true;
+	}
+}
+
 // Normalise a position so that it is not halfway through a two byte character.
 // This can occur in two situations -
 // When lines are terminated with \r\n pairs which should be treated as one character.
@@ -318,13 +362,14 @@
 	if (dbcsCodePage) {
 		if (SC_CP_UTF8 == dbcsCodePage) {
 			unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos));
-			while ((pos > 0) && (pos < Length()) && (ch >= 0x80) && (ch < (0x80 + 0x40))) {
-				// ch is a trail byte
+			int startUTF = pos;
+			int endUTF = pos;
+			if (IsTrailByte(ch) && InGoodUTF8(pos, startUTF, endUTF)) {
+				// ch is a trail byte within a UTF-8 character
 				if (moveDir > 0)
-					pos++;
+					pos = endUTF;
 				else
-					pos--;
-				ch = static_cast<unsigned char>(cb.CharAt(pos));
+					pos = startUTF;
 			}
 		} else {
 			// Anchor DBCS calculations at start of line because start of line can
@@ -652,7 +697,7 @@
 	}
 }
 
-int Document::GetLineIndentPosition(int line) {
+int Document::GetLineIndentPosition(int line) const {
 	if (line < 0)
 		return 0;
 	int pos = LineStart(line);
@@ -793,7 +838,7 @@
 	EndUndoAction();
 }
 
-bool Document::IsWhiteLine(int line) {
+bool Document::IsWhiteLine(int line) const {
 	int currentChar = LineStart(line);
 	int endLine = LineEnd(line);
 	while (currentChar < endLine) {
@@ -1238,7 +1283,7 @@
 	return substituted;
 }
 
-int Document::LinesTotal() {
+int Document::LinesTotal() const {
 	return cb.Lines();
 }
 
@@ -1271,11 +1316,7 @@
 
 void Document::SetStylingBits(int bits) {
 	stylingBits = bits;
-	stylingBitsMask = 0;
-	for (int bit = 0; bit < stylingBits; bit++) {
-		stylingBitsMask <<= 1;
-		stylingBitsMask |= 1;
-	}
+	stylingBitsMask = (1 << stylingBits) - 1;
 }
 
 void Document::StartStyling(int position, char mask) {
@@ -1339,13 +1380,19 @@
 	}
 }
 
-void Document::IncrementStyleClock() {
-	styleClock++;
-	if (styleClock > 0x100000) {
-		styleClock = 0;
+int Document::SetLineState(int line, int state) { 
+	int statePrevious = cb.SetLineState(line, state);
+	if (state != statePrevious) {
+		DocModification mh(SC_MOD_CHANGELINESTATE, 0, 0, 0, 0, line);
+		NotifyModified(mh);
 	}
+	return statePrevious;
 }
 
+void Document::IncrementStyleClock() {
+	styleClock = (styleClock + 1) % 0x100000;
+}
+
 void Document::DecorationFillRange(int position, int value, int fillLength) {
 	if (decorations.FillRange(position, value, fillLength)) {
 		DocModification mh(SC_MOD_CHANGEINDICATOR | SC_PERFORMED_USER,
@@ -1411,6 +1458,11 @@
 }
 
 void Document::NotifyModified(DocModification mh) {
+	if (mh.modificationType & SC_MOD_INSERTTEXT) {
+		decorations.InsertSpace(mh.position, mh.length);
+	} else if (mh.modificationType & SC_MOD_DELETETEXT) {
+		decorations.DeleteRange(mh.position, mh.length);
+	}
 	for (int i = 0; i < lenWatchers; i++) {
 		watchers[i].watcher->NotifyModified(this, mh, watchers[i].userData);
 	}

Modified: trunk/scintilla/Document.h
===================================================================
--- trunk/scintilla/Document.h	2007-12-02 10:52:19 UTC (rev 2085)
+++ trunk/scintilla/Document.h	2007-12-02 11:58:17 UTC (rev 2086)
@@ -138,10 +138,12 @@
 	int ClampPositionIntoDocument(int pos);
 	bool IsCrLf(int pos);
 	int LenChar(int pos);
+	bool InGoodUTF8(int pos, int &start, int &end);
 	int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true);
 
 	// Gateways to modifying document
 	void ModifiedAt(int pos);
+	void CheckReadOnly();
 	bool DeleteChars(int pos, int len);
 	bool InsertString(int position, const char *s, int insertLength);
 	int Undo();
@@ -160,7 +162,7 @@
 
 	int GetLineIndentation(int line);
 	void SetLineIndentation(int line, int indent);
-	int GetLineIndentPosition(int line);
+	int GetLineIndentPosition(int line) const;
 	int GetColumn(int position);
 	int FindColumn(int line, int column);
 	void Indent(bool forwards, int lineBottom, int lineTop);
@@ -187,8 +189,8 @@
 	void DeleteMarkFromHandle(int markerHandle);
 	void DeleteAllMarks(int markerNum);
 	int LineFromHandle(int markerHandle) { return cb.LineFromHandle(markerHandle); }
-	int LineStart(int line);
-	int LineEnd(int line);
+	int LineStart(int line) const;
+	int LineEnd(int line) const;
 	int LineEndPosition(int position);
 	int VCHomePosition(int position);
 
@@ -202,13 +204,13 @@
 	int ExtendWordSelect(int pos, int delta, bool onlyWordCharacters=false);
 	int NextWordStart(int pos, int delta);
 	int NextWordEnd(int pos, int delta);
-	int Length() { return cb.Length(); }
+	int Length() const { return cb.Length(); }
 	void Allocate(int newSize) { cb.Allocate(newSize); }
 	long FindText(int minPos, int maxPos, const char *s,
 		bool caseSensitive, bool word, bool wordStart, bool regExp, bool posix, int *length);
 	long FindText(int iMessage, unsigned long wParam, long lParam);
 	const char *SubstituteByPosition(const char *text, int *length);
-	int LinesTotal();
+	int LinesTotal() const;
 
 	void ChangeCase(Range r, bool makeUpperCase);
 
@@ -224,7 +226,7 @@
 	void IncrementStyleClock();
 	void DecorationFillRange(int position, int value, int fillLength);
 
-	int SetLineState(int line, int state) { return cb.SetLineState(line, state); }
+	int SetLineState(int line, int state);
 	int GetLineState(int line) { return cb.GetLineState(line); }
 	int GetMaxLineState() { return cb.GetMaxLineState(); }
 
@@ -237,15 +239,13 @@
 	int WordPartLeft(int pos);
 	int WordPartRight(int pos);
 	int ExtendStyleRange(int pos, int delta, bool singleLine = false);
-	bool IsWhiteLine(int line);
+	bool IsWhiteLine(int line) const;
 	int ParaUp(int pos);
 	int ParaDown(int pos);
 	int IndentSize() { return actualIndentInChars; }
 	int BraceMatch(int position, int maxReStyle);
 
 private:
-	void CheckReadOnly();
-
 	CharClassify::cc WordCharClass(unsigned char ch);
 	bool IsWordStartAt(int pos);
 	bool IsWordEndAt(int pos);

Modified: trunk/scintilla/DocumentAccessor.cxx
===================================================================
--- trunk/scintilla/DocumentAccessor.cxx	2007-12-02 10:52:19 UTC (rev 2085)
+++ trunk/scintilla/DocumentAccessor.cxx	2007-12-02 11:58:17 UTC (rev 2086)
@@ -13,7 +13,6 @@
 #include "Platform.h"
 
 #include "PropSet.h"
-#include "SVector.h"
 #include "Accessor.h"
 #include "DocumentAccessor.h"
 #include "SplitVector.h"

Modified: trunk/scintilla/Editor.cxx
===================================================================
--- trunk/scintilla/Editor.cxx	2007-12-02 10:52:19 UTC (rev 2085)
+++ trunk/scintilla/Editor.cxx	2007-12-02 11:58:17 UTC (rev 2086)
@@ -17,13 +17,12 @@
 #endif
 #include "Scintilla.h"
 
-#include "ContractionState.h"
-#include "SVector.h"
 #include "SplitVector.h"
 #include "Partitioning.h"
+#include "RunStyles.h"
+#include "ContractionState.h"
 #include "CellBuffer.h"
 #include "KeyMap.h"
-#include "RunStyles.h"
 #include "Indicator.h"
 #include "XPM.h"
 #include "LineMarker.h"
@@ -44,9 +43,9 @@
 	may reasonably be deferred (not done now OR [possibly] at all)
 */
 static bool CanDeferToLastStep(const DocModification& mh) {
-	if (mh.modificationType & (SC_MOD_BEFOREINSERT|SC_MOD_BEFOREDELETE))
+	if (mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE))
 		return true;	// CAN skip
-	if (!(mh.modificationType & (SC_PERFORMED_UNDO|SC_PERFORMED_REDO)))
+	if (!(mh.modificationType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO)))
 		return false;	// MUST do
 	if (mh.modificationType & SC_MULTISTEPUNDOREDO)
 		return true;	// CAN skip
@@ -55,7 +54,7 @@
 
 static bool CanEliminate(const DocModification& mh) {
 	return
-		(mh.modificationType & (SC_MOD_BEFOREINSERT|SC_MOD_BEFOREDELETE)) != 0;
+	    (mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) != 0;
 }
 
 /*
@@ -64,20 +63,20 @@
 */
 static bool IsLastStep(const DocModification& mh) {
 	return
-		(mh.modificationType & (SC_PERFORMED_UNDO|SC_PERFORMED_REDO)) != 0
-		&& (mh.modificationType & SC_MULTISTEPUNDOREDO) != 0
-		&& (mh.modificationType & SC_LASTSTEPINUNDOREDO) != 0
-		&& (mh.modificationType & SC_MULTILINEUNDOREDO) != 0;
+	    (mh.modificationType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO)) != 0
+	    && (mh.modificationType & SC_MULTISTEPUNDOREDO) != 0
+	    && (mh.modificationType & SC_LASTSTEPINUNDOREDO) != 0
+	    && (mh.modificationType & SC_MULTILINEUNDOREDO) != 0;
 }
 
 Caret::Caret() :
-active(false), on(false), period(500) {}
+		active(false), on(false), period(500) {}
 
 Timer::Timer() :
-ticking(false), ticksToWait(0), tickerID(0) {}
+		ticking(false), ticksToWait(0), tickerID(0) {}
 
 Idler::Idler() :
-state(false), idlerID(0) {}
+		state(false), idlerID(0) {}
 
 static inline bool IsControlCharacter(int ch) {
 	// iscntrl returns true for lots of chars > 127 which are displayable
@@ -138,6 +137,8 @@
 	xCaretMargin = 50;
 	horizontalScrollBarVisible = true;
 	scrollWidth = 2000;
+	trackLineWidth = false;
+	lineWidthMaxSeen = 0;
 	verticalScrollBarVisible = true;
 	endAtLastLine = true;
 	caretSticky = false;
@@ -914,13 +915,13 @@
 	Point pt = LocationFromPosition(currentPos);
 	if (pt.y < rcClient.top) {
 		MovePositionTo(PositionFromLocation(
-		                   Point(lastXChosen, rcClient.top)),
-		               noSel, ensureVisible);
+		            Point(lastXChosen, rcClient.top)),
+		        noSel, ensureVisible);
 	} else if ((pt.y + vs.lineHeight - 1) > rcClient.bottom) {
 		int yOfLastLineFullyDisplayed = rcClient.top + (LinesOnScreen() - 1) * vs.lineHeight;
 		MovePositionTo(PositionFromLocation(
-		                   Point(lastXChosen, rcClient.top + yOfLastLineFullyDisplayed)),
-		               noSel, ensureVisible);
+		            Point(lastXChosen, rcClient.top + yOfLastLineFullyDisplayed)),
+		        noSel, ensureVisible);
 	}
 }
 
@@ -1205,7 +1206,7 @@
 			xOffset = xOffsetNew;
 			if (xOffsetNew > 0) {
 				PRectangle rcText = GetTextRectangle();
-				if (horizontalScrollBarVisible == true &&
+				if (horizontalScrollBarVisible &&
 				        rcText.Width() + xOffset > scrollWidth) {
 					scrollWidth = xOffset + rcText.Width();
 					SetScrollBars();
@@ -1262,6 +1263,16 @@
 	}
 }
 
+bool Editor::WrapOneLine(Surface *surface, int lineToWrap) {
+	AutoLineLayout ll(llc, RetrieveLineLayout(lineToWrap));
+	int linesWrapped = 1;
+	if (ll) {
+		LayoutLine(lineToWrap, surface, vs, ll, wrapWidth);
+		linesWrapped = ll->lines;
+	}
+	return cs.SetHeight(lineToWrap, linesWrapped);
+}
+
 // Check if wrapping needed and perform any needed wrapping.
 // fullwrap: if true, all lines which need wrapping will be done,
 //           in this single call.
@@ -1283,9 +1294,9 @@
 			}
 		}
 		if (!fullWrap && priorityWrapLineStart >= 0 &&
-			// .. and if the paint window is outside pending wraps
-			(((priorityWrapLineStart + linesInOneCall) < wrapStart) ||
-			 (priorityWrapLineStart > wrapEnd))) {
+		        // .. and if the paint window is outside pending wraps
+		        (((priorityWrapLineStart + linesInOneCall) < wrapStart) ||
+		         (priorityWrapLineStart > wrapEnd))) {
 			// No priority wrap pending
 			return false;
 		}
@@ -1338,13 +1349,7 @@
 				// Platform::DebugPrintf("Wraplines: full = %d, priorityStart = %d (wrapping: %d to %d)\n", fullWrap, priorityWrapLineStart, lineToWrap, lastLineToWrap);
 				// Platform::DebugPrintf("Pending wraps: %d to %d\n", wrapStart, wrapEnd);
 				while (lineToWrap < lastLineToWrap) {
-					AutoLineLayout ll(llc, RetrieveLineLayout(lineToWrap));
-					int linesWrapped = 1;
-					if (ll) {
-						LayoutLine(lineToWrap, surface, vs, ll, wrapWidth);
-						linesWrapped = ll->lines;
-					}
-					if (cs.SetHeight(lineToWrap, linesWrapped)) {
+					if (WrapOneLine(surface, lineToWrap)) {
 						wrapOccurred = true;
 					}
 					lineToWrap++;
@@ -1423,7 +1428,7 @@
 				LayoutLine(line, surface, vs, ll, pixelWidth);
 				for (int subLine = 1; subLine < ll->lines; subLine++) {
 					pdoc->InsertCString(posLineStart + (subLine - 1) * strlen(eol) +
-						ll->LineStart(subLine), eol);
+					        ll->LineStart(subLine), eol);
 					targetEnd += static_cast<int>(strlen(eol));
 				}
 			}
@@ -1524,9 +1529,9 @@
 
 			// Old code does not know about new markers needed to distinguish all cases
 			int folderOpenMid = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID,
-			                    SC_MARKNUM_FOLDEROPEN);
+			        SC_MARKNUM_FOLDEROPEN);
 			int folderEnd = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND,
-			                                        SC_MARKNUM_FOLDER);
+			        SC_MARKNUM_FOLDER);
 
 			while ((visibleLine < cs.LinesDisplayed()) && yposScreen < rcMargin.bottom) {
 
@@ -1611,11 +1616,11 @@
 					if (foldFlags & SC_FOLDFLAG_LEVELNUMBERS) {
 						int lev = pdoc->GetLevel(lineDoc);
 						sprintf(number, "%c%c %03X %03X",
-							(lev & SC_FOLDLEVELHEADERFLAG) ? 'H' : '_',
-							(lev & SC_FOLDLEVELWHITEFLAG) ? 'W' : '_',
-							lev & SC_FOLDLEVELNUMBERMASK,
-							lev >> 16
-						);
+						        (lev & SC_FOLDLEVELHEADERFLAG) ? 'H' : '_',
+						        (lev & SC_FOLDLEVELWHITEFLAG) ? 'W' : '_',
+						        lev & SC_FOLDLEVELNUMBERMASK,
+						        lev >> 16
+						       );
 					}
 					PRectangle rcNumber = rcMarker;
 					// Right justify
@@ -1623,9 +1628,9 @@
 					int xpos = rcNumber.right - width - 3;
 					rcNumber.left = xpos;
 					surface->DrawTextNoClip(rcNumber, vs.styles[STYLE_LINENUMBER].font,
-					                        rcNumber.top + vs.maxAscent, number, istrlen(number),
-					                        vs.styles[STYLE_LINENUMBER].fore.allocated,
-					                        vs.styles[STYLE_LINENUMBER].back.allocated);
+					        rcNumber.top + vs.maxAscent, number, istrlen(number),
+					        vs.styles[STYLE_LINENUMBER].fore.allocated,
+					        vs.styles[STYLE_LINENUMBER].back.allocated);
 				}
 
 				if (marks) {
@@ -1675,10 +1680,65 @@
 	PLATFORM_ASSERT(posLineEnd >= posLineStart);
 	int lineCaret = pdoc->LineFromPosition(currentPos);
 	return llc.Retrieve(lineNumber, lineCaret,
-	                    posLineEnd - posLineStart, pdoc->GetStyleClock(),
-	                    LinesOnScreen() + 1, pdoc->LinesTotal());
+	        posLineEnd - posLineStart, pdoc->GetStyleClock(),
+	        LinesOnScreen() + 1, pdoc->LinesTotal());
 }
 
+static bool GoodTrailByte(int v) {
+	return (v >= 0x80) && (v < 0xc0);
+}
+
+bool BadUTF(const char *s, int len, int &trailBytes) {
+	if (trailBytes) {
+		trailBytes--;
+		return false;
+	}
+	const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
+	if (*us < 0x80) {
+		// Single bytes easy
+		return false;
+	} else if (*us > 0xF4) {
+		// Characters longer than 4 bytes not possible in current UTF-8
+		return true;
+	} else if (*us >= 0xF0) {
+		// 4 bytes
+		if (len < 4)
+			return true;
+		if (GoodTrailByte(us[1]) && GoodTrailByte(us[2]) && GoodTrailByte(us[3])) {
+			trailBytes = 3;
+			return false;
+		} else {
+			return true;
+		}
+	} else if (*us >= 0xE0) {
+		// 3 bytes
+		if (len < 3)
+			return true;
+		if (GoodTrailByte(us[1]) && GoodTrailByte(us[2])) {
+			trailBytes = 2;
+			return false;
+		} else {
+			return true;
+		}
+	} else if (*us >= 0xC2) {
+		// 2 bytes
+		if (len < 2)
+			return true;
+		if (GoodTrailByte(us[1])) {
+			trailBytes = 1;
+			return false;
+		} else {
+			return true;
+		}
+	} else if (*us >= 0xC0) {
+		// Overlong encoding
+		return true;
+	} else {
+		// Trail byte
+		return true;
+	}
+}
+
 /**
  * Fill in the LineLayout data for the given line.
  * Copy the given @a line and its styles from the document into local arrays.
@@ -1717,18 +1777,18 @@
 				char chDoc = pdoc->CharAt(charInDoc);
 				styleByte = pdoc->StyleAt(charInDoc);
 				allSame = allSame &&
-					        (ll->styles[numCharsInLine] == static_cast<unsigned char>(styleByte & styleMask));
+				        (ll->styles[numCharsInLine] == static_cast<unsigned char>(styleByte & styleMask));
 				allSame = allSame &&
-					        (ll->indicators[numCharsInLine] == static_cast<char>(styleByte & ~styleMask));
+				        (ll->indicators[numCharsInLine] == static_cast<char>(styleByte & ~styleMask));
 				if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseMixed)
 					allSame = allSame &&
-						        (ll->chars[numCharsInLine] == chDoc);
+					        (ll->chars[numCharsInLine] == chDoc);
 				else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower)
 					allSame = allSame &&
-						        (ll->chars[numCharsInLine] == static_cast<char>(tolower(chDoc)));
+					        (ll->chars[numCharsInLine] == static_cast<char>(tolower(chDoc)));
 				else	// Style::caseUpper
 					allSame = allSame &&
-						        (ll->chars[numCharsInLine] == static_cast<char>(toupper(chDoc)));
+					        (ll->chars[numCharsInLine] == static_cast<char>(toupper(chDoc)));
 				numCharsInLine++;
 			}
 			allSame = allSame && (ll->styles[numCharsInLine] == styleByte);	// For eolFilled
@@ -1790,31 +1850,40 @@
 
 		int ctrlCharWidth[32] = {0};
 		bool isControlNext = IsControlCharacter(ll->chars[0]);
+		int trailBytes = 0;
+		bool isBadUTFNext = IsUnicodeMode() && BadUTF(ll->chars, numCharsInLine, trailBytes);
 		for (int charInLine = 0; charInLine < numCharsInLine; charInLine++) {
 			bool isControl = isControlNext;
 			isControlNext = IsControlCharacter(ll->chars[charInLine + 1]);
+			bool isBadUTF = isBadUTFNext;
+			isBadUTFNext = IsUnicodeMode() && BadUTF(ll->chars + charInLine + 1, numCharsInLine - charInLine - 1, trailBytes);
 			if ((ll->styles[charInLine] != ll->styles[charInLine + 1]) ||
-			        isControl || isControlNext) {
+			        isControl || isControlNext || isBadUTF || isBadUTFNext) {
 				ll->positions[startseg] = 0;
 				if (vstyle.styles[ll->styles[charInLine]].visible) {
 					if (isControl) {
 						if (ll->chars[charInLine] == '\t') {
 							ll->positions[charInLine + 1] = ((((startsegx + 2) /
-							                                   tabWidth) + 1) * tabWidth) - startsegx;
+							        tabWidth) + 1) * tabWidth) - startsegx;
 						} else if (controlCharSymbol < 32) {
 							if (ctrlCharWidth[ll->chars[charInLine]] == 0) {
 								const char *ctrlChar = ControlCharacterString(ll->chars[charInLine]);
 								// +3 For a blank on front and rounded edge each side:
 								ctrlCharWidth[ll->chars[charInLine]] =
-									surface->WidthText(ctrlCharsFont, ctrlChar, istrlen(ctrlChar)) + 3;
+								    surface->WidthText(ctrlCharsFont, ctrlChar, istrlen(ctrlChar)) + 3;
 							}
 							ll->positions[charInLine + 1] = ctrlCharWidth[ll->chars[charInLine]];
 						} else {
 							char cc[2] = { static_cast<char>(controlCharSymbol), '\0' };
 							surface->MeasureWidths(ctrlCharsFont, cc, 1,
-							                       ll->positions + startseg + 1);
+							        ll->positions + startseg + 1);
 						}
 						lastSegItalics = false;
+					} else if (isBadUTF) {
+						char hexits[3];
+						sprintf(hexits, "%2X", ll->chars[charInLine] & 0xff);
+						ll->positions[charInLine + 1] =
+						    surface->WidthText(ctrlCharsFont, hexits, istrlen(hexits)) + 3;
 					} else {	// Regular character
 						int lenSeg = charInLine - startseg + 1;
 						if ((lenSeg == 1) && (' ' == ll->chars[startseg])) {
@@ -1824,7 +1893,7 @@
 						} else {
 							lastSegItalics = vstyle.styles[ll->styles[charInLine]].italic;
 							posCache.MeasureWidths(surface, vstyle, ll->styles[charInLine], ll->chars + startseg,
-							                       lenSeg, ll->positions + startseg + 1);
+							        lenSeg, ll->positions + startseg + 1);
 						}
 					}
 				} else {    // invisible
@@ -1873,12 +1942,12 @@
 						// Try moving to start of last character
 						if (p > 0) {
 							lastGoodBreak = pdoc->MovePositionOutsideChar(p + posLineStart, -1)
-							                - posLineStart;
+							        - posLineStart;
 						}
 						if (lastGoodBreak == lastLineStart) {
 							// Ensure at least one character on line.
 							lastGoodBreak = pdoc->MovePositionOutsideChar(lastGoodBreak + posLineStart + 1, 1)
-							                - posLineStart;
+							        - posLineStart;
 						}
 					}
 					lastLineStart = lastGoodBreak;
@@ -1893,7 +1962,7 @@
 				if (p > 0) {
 					if (wrapState == eWrapChar) {
 						lastGoodBreak = pdoc->MovePositionOutsideChar(p + posLineStart, -1)
-												- posLineStart;
+						        - posLineStart;
 						p = pdoc->MovePositionOutsideChar(p + 1 + posLineStart, 1) - posLineStart;
 						continue;
 					} else if (ll->styles[p] != ll->styles[p - 1]) {
@@ -1915,7 +1984,7 @@
 }
 
 ColourAllocated Editor::TextBackground(ViewStyle &vsDraw, bool overrideBackground,
-                                       ColourAllocated background, bool inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll) {
+        ColourAllocated background, bool inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll) {
 	if (inSelection) {
 		if (vsDraw.selbackset && (vsDraw.selAlpha == SC_ALPHA_NOALPHA)) {
 			return SelectionBackground(vsDraw);
@@ -1937,11 +2006,11 @@
 	Point from(0, ((lineVisible & 1) && (lineHeight & 1)) ? 1 : 0);
 	PRectangle rcCopyArea(start + 1, rcSegment.top, start + 2, rcSegment.bottom);
 	surface->Copy(rcCopyArea, from,
-	              highlight ? *pixmapIndentGuideHighlight : *pixmapIndentGuide);
+	        highlight ? *pixmapIndentGuideHighlight : *pixmapIndentGuide);
 }
 
 void Editor::DrawWrapMarker(Surface *surface, PRectangle rcPlace,
-                            bool isEndMarker, ColourAllocated wrapColour) {
+        bool isEndMarker, ColourAllocated wrapColour) {
 	surface->PenColour(wrapColour);
 
 	enum { xa = 1 }; // gap before start
@@ -1964,10 +2033,10 @@
 		int yBase;
 		int yDir;
 		void MoveTo(int xRelative, int yRelative) {
-		    surface->MoveTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
+			surface->MoveTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
 		}
 		void LineTo(int xRelative, int yRelative) {
-		    surface->LineTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
+			surface->LineTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
 		}
 	};
 	Relative rel = {surface, x0, xStraight ? 1 : -1, y0, yStraight ? 1 : -1};
@@ -1983,7 +2052,7 @@
 	rel.LineTo(xa + w, y);
 	rel.LineTo(xa + w, y - 2 * dy);
 	rel.LineTo(xa - 1,   // on windows lineto is exclusive endpoint, perhaps GTK not...
-	                y - 2 * dy);
+	        y - 2 * dy);
 }
 
 static void SimpleAlphaRectangle(Surface *surface, PRectangle rc, ColourAllocated fill, int alpha) {
@@ -1993,9 +2062,9 @@
 }
 
 void Editor::DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll,
-                     int line, int lineEnd, int xStart, int subLine, int subLineStart,
-                     bool overrideBackground, ColourAllocated background,
-                     bool drawWrapMarkEnd, ColourAllocated wrapColour) {
+        int line, int lineEnd, int xStart, int subLine, int subLineStart,
+        bool overrideBackground, ColourAllocated background,
+        bool drawWrapMarkEnd, ColourAllocated wrapColour) {
 
 	int styleMask = pdoc->stylingBitsMask;
 	PRectangle rcSegment = rcLine;
@@ -2006,7 +2075,7 @@
 	rcSegment.right = xEol + vsDraw.aveCharWidth + xStart;
 	int posLineEnd = pdoc->LineStart(line + 1);
 	bool eolInSelection = (subLine == (ll->lines - 1)) &&
-	                      (posLineEnd > ll->selStart) && (posLineEnd <= ll->selEnd) && (ll->selStart != ll->selEnd);
+	        (posLineEnd > ll->selStart) && (posLineEnd <= ll->selEnd) && (ll->selStart != ll->selEnd);
 
 	if (eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (vsDraw.selAlpha == SC_ALPHA_NOALPHA)) {
 		surface->FillRectangle(rcSegment, SelectionBackground(vsDraw));
@@ -2044,7 +2113,7 @@
 		if (vsDraw.selEOLFilled && eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (vsDraw.selAlpha != SC_ALPHA_NOALPHA)) {
 			SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw), vsDraw.selAlpha);
 		}
- 	}
+	}
 
 	if (drawWrapMarkEnd) {
 		PRectangle rcPlace = rcSegment;
@@ -2062,7 +2131,7 @@
 }
 
 void Editor::DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
-                      PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under) {
+        PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under) {
 	// Draw decorators
 	const int posLineStart = pdoc->LineStart(line);
 	const int lineStart = ll->LineStart(subLine);
@@ -2092,10 +2161,10 @@
 					if (indicPos >= lineEnd || !(ll->indicators[indicPos] & mask)) {
 						// AT end of indicator run, DRAW it!
 						PRectangle rcIndic(
-							ll->positions[startPos] + xStart - subLineStart,
-							rcLine.top + vsDraw.maxAscent,
-							ll->positions[indicPos] + xStart - subLineStart,
-							rcLine.top + vsDraw.maxAscent + 3);
+						    ll->positions[startPos] + xStart - subLineStart,
+						    rcLine.top + vsDraw.maxAscent,
+						    ll->positions[indicPos] + xStart - subLineStart,
+						    rcLine.top + vsDraw.maxAscent + 3);
 						vsDraw.indicators[indicnum].Draw(surface, rcIndic, rcLine);
 						// RESET control var
 						startPos = -1;
@@ -2106,9 +2175,9 @@
 		}
 	}
 
-	for (Decoration *deco=pdoc->decorations.root; deco; deco = deco->next) {
+	for (Decoration *deco = pdoc->decorations.root; deco; deco = deco->next) {
 		if (under == vsDraw.indicators[deco->indicator].under) {
-			int startPos = posLineStart + subLineStart;
+			int startPos = posLineStart + lineStart;
 			if (!deco->rs.ValueAt(startPos)) {
 				startPos = deco->rs.EndRun(startPos);
 			}
@@ -2117,10 +2186,10 @@
 				if (endPos > posLineEnd)
 					endPos = posLineEnd;
 				PRectangle rcIndic(
-					ll->positions[startPos - posLineStart] + xStart - subLineStart,
-					rcLine.top + vsDraw.maxAscent,
-					ll->positions[endPos - posLineStart] + xStart - subLineStart,
-					rcLine.top + vsDraw.maxAscent + 3);
+				    ll->positions[startPos - posLineStart] + xStart - subLineStart,
+				    rcLine.top + vsDraw.maxAscent,
+				    ll->positions[endPos - posLineStart] + xStart - subLineStart,
+				    rcLine.top + vsDraw.maxAscent + 3);
 				vsDraw.indicators[deco->indicator].Draw(surface, rcIndic, rcLine);
 				startPos = deco->rs.EndRun(endPos);
 			}
@@ -2128,8 +2197,32 @@
 	}
 }
 
+void DrawTextBlob(Surface *surface, ViewStyle &vsDraw, PRectangle rcSegment,
+				  const char *s, ColourAllocated textBack, ColourAllocated textFore, bool twoPhaseDraw) {
+	if (!twoPhaseDraw) {
+		surface->FillRectangle(rcSegment, textBack);
+	}
+	Font &ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;
+	int normalCharHeight = surface->Ascent(ctrlCharsFont) -
+	        surface->InternalLeading(ctrlCharsFont);
+	PRectangle rcCChar = rcSegment;
+	rcCChar.left = rcCChar.left + 1;
+	rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight;
+	rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1;
+	PRectangle rcCentral = rcCChar;
+	rcCentral.top++;
+	rcCentral.bottom--;
+	surface->FillRectangle(rcCentral, textFore);
+	PRectangle rcChar = rcCChar;
+	rcChar.left++;
+	rcChar.right--;
+	surface->DrawTextClipped(rcChar, ctrlCharsFont,
+	        rcSegment.top + vsDraw.maxAscent, s, istrlen(s),
+	        textBack, textFore);
+}
+
 void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,
-                      PRectangle rcLine, LineLayout *ll, int subLine) {
+        PRectangle rcLine, LineLayout *ll, int subLine) {
 
 	PRectangle rcSegment = rcLine;
 
@@ -2154,7 +2247,7 @@
 		int marks = pdoc->GetMark(line);
 		for (int markBit = 0; (markBit < 32) && marks; markBit++) {
 			if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND) &&
-				(vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
+			        (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
 				background = vsDraw.markers[markBit].back.allocated;
 				overrideBackground = true;
 			}
@@ -2167,7 +2260,7 @@
 			if (marksMasked) {
 				for (int markBit = 0; (markBit < 32) && marksMasked; markBit++) {
 					if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY) &&
-						(vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
+					        (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
 						overrideBackground = true;
 						background = vsDraw.markers[markBit].back.allocated;
 					}
@@ -2178,7 +2271,7 @@
 	}
 
 	bool drawWhitespaceBackground = (vsDraw.viewWhitespace != wsInvisible) &&
-	                                (!overrideBackground) && (vsDraw.whitespaceBackgroundSet);
+	        (!overrideBackground) && (vsDraw.whitespaceBackgroundSet);
 
 	bool inIndentation = subLine == 0;	// Do not handle indentation except on first subline.
 	int indentWidth = pdoc->IndentSize() * vsDraw.spaceWidth;
@@ -2222,7 +2315,7 @@
 
 			// default bgnd here..
 			surface->FillRectangle(rcSegment, overrideBackground ? background :
-				vsDraw.styles[STYLE_DEFAULT].back.allocated);
+			        vsDraw.styles[STYLE_DEFAULT].back.allocated);
 
 			// main line style would be below but this would be inconsistent with end markers
 			// also would possibly not be the style at wrap point
@@ -2246,7 +2339,7 @@
 	// Does not take margin into account but not significant
 	int xStartVisible = subLineStart - xStart;
 
-	BreakFinder bfBack(ll, lineStart, lineEnd, posLineStart, xStartVisible);
+	BreakFinder bfBack(ll, lineStart, lineEnd, posLineStart, IsUnicodeMode(), xStartVisible);
 	int next = bfBack.First();
 
 	// Background drawing loop
@@ -2284,13 +2377,13 @@
 				// Normal text display
 				surface->FillRectangle(rcSegment, textBack);
 				if (vsDraw.viewWhitespace != wsInvisible ||
-				        (inIndentation && vsDraw.viewIndentationGuides)) {
+				        (inIndentation && vsDraw.viewIndentationGuides == ivReal)) {
 					for (int cpos = 0; cpos <= i - startseg; cpos++) {
 						if (ll->chars[cpos + startseg] == ' ') {
 							if (drawWhitespaceBackground &&
 							        (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {
 								PRectangle rcSpace(ll->positions[cpos + startseg] + xStart, rcSegment.top,
-								                   ll->positions[cpos + startseg + 1] + xStart, rcSegment.bottom);
+								        ll->positions[cpos + startseg + 1] + xStart, rcSegment.bottom);
 								surface->FillRectangle(rcSpace, vsDraw.whitespaceBackground.allocated);
 							}
 						} else {
@@ -2321,7 +2414,7 @@
 
 	inIndentation = subLine == 0;	// Do not handle indentation except on first subline.
 	// Foreground drawing loop
-	BreakFinder bfFore(ll, lineStart, lineEnd, posLineStart, xStartVisible);
+	BreakFinder bfFore(ll, lineStart, lineEnd, posLineStart, IsUnicodeMode(), xStartVisible);
 	next = bfFore.First();
 
 	while (next < lineEnd) {
@@ -2359,23 +2452,24 @@
 						textBack = vsDraw.whitespaceBackground.allocated;
 					surface->FillRectangle(rcSegment, textBack);
 				}
-				if ((vsDraw.viewWhitespace != wsInvisible) || ((inIndentation && vsDraw.viewIndentationGuides))) {
+				if ((vsDraw.viewWhitespace != wsInvisible) ||
+				        (inIndentation && vsDraw.viewIndentationGuides != ivNone)) {
 					if (vsDraw.whitespaceForegroundSet)
 						textFore = vsDraw.whitespaceForeground.allocated;
 					surface->PenColour(textFore);
 				}
-				if (inIndentation && vsDraw.viewIndentationGuides) {
+				if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
 					for (int xIG = ll->positions[i] / indentWidth * indentWidth; xIG < ll->positions[i + 1]; xIG += indentWidth) {
 						if (xIG >= ll->positions[i] && xIG > 0) {
 							DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIG + xStart, rcSegment,
-							                (ll->xHighlightGuide == xIG));
+							        (ll->xHighlightGuide == xIG));
 						}
 					}
 				}
 				if (vsDraw.viewWhitespace != wsInvisible) {
 					if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
 						PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4,
-						                 rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
+						        rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
 						DrawTabArrow(surface, rcTab, rcSegment.top + vsDraw.lineHeight / 2);
 					}
 				}
@@ -2385,46 +2479,32 @@
 				if (controlCharSymbol < 32) {
 					// Draw the character
 					const char *ctrlChar = ControlCharacterString(ll->chars[i]);
-					if (!twoPhaseDraw) {
-						surface->FillRectangle(rcSegment, textBack);
-					}
-					int normalCharHeight = surface->Ascent(ctrlCharsFont) -
-					                       surface->InternalLeading(ctrlCharsFont);
-					PRectangle rcCChar = rcSegment;
-					rcCChar.left = rcCChar.left + 1;
-					rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight;
-					rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1;
-					PRectangle rcCentral = rcCChar;
-					rcCentral.top++;
-					rcCentral.bottom--;
-					surface->FillRectangle(rcCentral, textFore);
-					PRectangle rcChar = rcCChar;
-					rcChar.left++;
-					rcChar.right--;
-					surface->DrawTextClipped(rcChar, ctrlCharsFont,
-					                         rcSegment.top + vsDraw.maxAscent, ctrlChar, istrlen(ctrlChar),
-					                         textBack, textFore);
+					DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, twoPhaseDraw);
 				} else {
 					char cc[2] = { static_cast<char>(controlCharSymbol), '\0' };
 					surface->DrawTextNoClip(rcSegment, ctrlCharsFont,
-					                        rcSegment.top + vsDraw.maxAscent,
-					                        cc, 1, textBack, textFore);
+					        rcSegment.top + vsDraw.maxAscent,
+					        cc, 1, textBack, textFore);
 				}
+			} else if ((i == startseg) && (static_cast<unsigned char>(ll->chars[i]) >= 0x80) && IsUnicodeMode()) {
+				char hexits[3];
+				sprintf(hexits, "%2X", ll->chars[i] & 0xff);
+				DrawTextBlob(surface, vsDraw, rcSegment, hexits, textBack, textFore, twoPhaseDraw);
 			} else {
 				// Normal text display
 				if (vsDraw.styles[styleMain].visible) {
 					if (twoPhaseDraw) {
 						surface->DrawTextTransparent(rcSegment, textFont,
-						                             rcSegment.top + vsDraw.maxAscent, ll->chars + startseg,
-						                             i - startseg + 1, textFore);
+						        rcSegment.top + vsDraw.maxAscent, ll->chars + startseg,
+						        i - startseg + 1, textFore);
 					} else {
 						surface->DrawTextNoClip(rcSegment, textFont,
-						                        rcSegment.top + vsDraw.maxAscent, ll->chars + startseg,
-						                        i - startseg + 1, textFore, textBack);
+						        rcSegment.top + vsDraw.maxAscent, ll->chars + startseg,
+						        i - startseg + 1, textFore, textBack);
 					}
 				}
 				if (vsDraw.viewWhitespace != wsInvisible ||
-				        (inIndentation && vsDraw.viewIndentationGuides)) {
+				        (inIndentation && vsDraw.viewIndentationGuides != ivNone)) {
 					for (int cpos = 0; cpos <= i - startseg; cpos++) {
 						if (ll->chars[cpos + startseg] == ' ') {
 							if (vsDraw.viewWhitespace != wsInvisible) {
@@ -2444,11 +2524,11 @@
 									surface->FillRectangle(rcDot, textFore);
 								}
 							}
-							if (inIndentation && vsDraw.viewIndentationGuides) {
+							if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
 								int startSpace = ll->positions[cpos + startseg];
 								if (startSpace > 0 && (startSpace % indentWidth == 0)) {
 									DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, startSpace + xStart, rcSegment,
-									                (ll->xHighlightGuide == ll->positions[cpos + startseg]));
+									        (ll->xHighlightGuide == ll->positions[cpos + startseg]));
 								}
 							}
 						} else {
@@ -2475,7 +2555,50 @@
 			break;
 		}
 	}
+	if ((vsDraw.viewIndentationGuides == ivLookForward || vsDraw.viewIndentationGuides == ivLookBoth)
+	        && (subLine == 0)) {
+		int indentSpace = pdoc->GetLineIndentation(line);
+		// Find the most recent line with some text
 
+		int lineLastWithText = line;
+		while (lineLastWithText > 0 && pdoc->IsWhiteLine(lineLastWithText)) {
+			lineLastWithText--;
+		}
+		if (lineLastWithText < line) {
+			// This line is empty, so use indentation of last line with text
+			int indentLastWithText = pdoc->GetLineIndentation(lineLastWithText);
+			int isFoldHeader = pdoc->GetLevel(lineLastWithText) & SC_FOLDLEVELHEADERFLAG;
+			if (isFoldHeader) {
+				// Level is one more level than parent
+				indentLastWithText += pdoc->IndentSize();
+			}
+			if (vsDraw.viewIndentationGuides == ivLookForward) {
+				// In viLookForward mode, previous line only used if it is a fold header
+				if (isFoldHeader) {
+					indentSpace = Platform::Maximum(indentSpace, indentLastWithText);
+				}
+			} else {	// viLookBoth
+				indentSpace = Platform::Maximum(indentSpace, indentLastWithText);
+			}
+		}
+
+		int lineNextWithText = line;
+		while (lineNextWithText < pdoc->LinesTotal() && pdoc->IsWhiteLine(lineNextWithText)) {
+			lineNextWithText++;
+		}
+		if (lineNextWithText > line) {
+			// This line is empty, so use indentation of last line with text
+			indentSpace = Platform::Maximum(indentSpace,
+			        pdoc->GetLineIndentation(lineNextWithText));
+		}
+
+		for (int indentPos = pdoc->IndentSize(); indentPos < indentSpace; indentPos += pdoc->IndentSize()) {
+			int xIndent = indentPos * vsDraw.spaceWidth;
+			DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
+			        (ll->xHighlightGuide == xIndent));
+		}
+	}
+
 	DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineEnd, false);
 
 	// End of the drawing of the current line
@@ -2526,7 +2649,7 @@
 
 	int lineStart = ll->LineStart(subLine);
 	int posBefore = posCaret;
-	int posAfter = MovePositionOutsideChar(posCaret+1, 1);
+	int posAfter = MovePositionOutsideChar(posCaret + 1, 1);
 	int numCharsToDraw = posAfter - posCaret;
 
 	// Work out where the starting and ending offsets are. We need to
@@ -2541,7 +2664,7 @@
 		}
 		// Char shares horizontal space, update the numChars to draw
 		// Update posBefore to point to the prev char
-		posBefore = MovePositionOutsideChar(posBefore-1, -1);
+		posBefore = MovePositionOutsideChar(posBefore - 1, -1);
 		numCharsToDraw = posAfter - posBefore;
 		offsetFirstChar = offset - (posCaret - posBefore);
 	}
@@ -2554,7 +2677,7 @@
 		// the next character ends, and 2nd next begins. We'll need
 		// to compare these two
 		posBefore = posAfter;
-		posAfter = MovePositionOutsideChar(posAfter+1, 1);
+		posAfter = MovePositionOutsideChar(posAfter + 1, 1);
 		offsetLastChar = offset + (posAfter - posCaret);
 		if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - (posAfter - posBefore)]) > 0) {
 			// The char does not share horizontal space
@@ -2572,9 +2695,9 @@
 	// (inversed) for drawing the caret here.
 	int styleMain = ll->styles[offsetFirstChar];
 	surface->DrawTextClipped(rcCaret, vsDraw.styles[styleMain].font,
-				 rcCaret.top + vsDraw.maxAscent, ll->chars + offsetFirstChar,
-				 numCharsToDraw, vsDraw.styles[styleMain].back.allocated,
-				 vsDraw.caretcolour.allocated);
+	        rcCaret.top + vsDraw.maxAscent, ll->chars + offsetFirstChar,
+	        numCharsToDraw, vsDraw.styles[styleMain].back.allocated,
+	        vsDraw.caretcolour.allocated);
 }
 
 void Editor::RefreshPixMaps(Surface *surfaceWindow) {
@@ -2636,9 +2759,9 @@
 		if (!pixmapLine->Initialised()) {
 			PRectangle rcClient = GetClientRectangle();
 			pixmapLine->InitPixMap(rcClient.Width(), vs.lineHeight,
-			                       surfaceWindow, wMain.GetID());
+			        surfaceWindow, wMain.GetID());
 			pixmapSelMargin->InitPixMap(vs.fixedColumnWidth,
-			                            rcClient.Height(), surfaceWindow, wMain.GetID());
+			        rcClient.Height(), surfaceWindow, wMain.GetID());
 		}
 	}
 }
@@ -2799,7 +2922,7 @@
 				Range rangeLine(pdoc->LineStart(lineDoc), pdoc->LineStart(lineDoc + 1));
 				// Highlight the current braces if any
 				ll->SetBracesHighlight(rangeLine, braces, static_cast<char>(bracesMatchStyle),
-				                       highlightGuideColumn * vs.spaceWidth);
+				        highlightGuideColumn * vs.spaceWidth);
 
 				// Draw the line
 				DrawLine(surface, vs, lineDoc, visibleLine, xStart, rcLine, ll, subLine);
@@ -2869,8 +2992,7 @@
 				// Draw the Caret
 				if (lineDoc == lineCaret) {
 					int offset = Platform::Minimum(posCaret - rangeLine.start, ll->maxLineLength);
-					if ((offset >= ll->LineStart(subLine)) &&
-					        ((offset < ll->LineStart(subLine + 1)) || offset == ll->numCharsInLine)) {
+					if (ll->InLine(offset, subLine)) {
 						int xposCaret = ll->positions[offset] - ll->positions[ll->LineStart(subLine)] + xStart;
 
 						if (actualWrapVisualStartIndent != 0) {
@@ -2879,7 +3001,7 @@
 								xposCaret += actualWrapVisualStartIndent * vs.aveCharWidth;
 						}
 						if ((xposCaret >= 0) && (vs.caretWidth > 0) && (vs.caretStyle != CARETSTYLE_INVISIBLE) &&
-						    ((posDrag >= 0) || (caret.active && caret.on))) {
+						        ((posDrag >= 0) || (caret.active && caret.on))) {
 							bool caretAtEOF = false;
 							bool caretAtEOL = false;
 							bool drawBlockCaret = false;
@@ -2899,7 +3021,7 @@
 							if (widthOverstrikeCaret < 3)	// Make sure its visible
 								widthOverstrikeCaret = 3;
 
-							if (offset > 0)
+							if (offset > ll->LineStart(subLine))
 								caretWidthOffset = 1;	// Move back so overlaps both character cells.
 							if (posDrag >= 0) {
 								/* Dragging text, use a line caret */
@@ -2936,7 +3058,7 @@
 				if (bufferedDraw) {
 					Point from(vs.fixedColumnWidth, 0);
 					PRectangle rcCopyArea(vs.fixedColumnWidth, yposScreen,
-					                      rcClient.right, yposScreen + vs.lineHeight);
+					        rcClient.right, yposScreen + vs.lineHeight);
 					surfaceWindow->Copy(rcCopyArea, from, *pixmapLine);
 				}
 				//durCopy += et.Duration(true);
@@ -2948,6 +3070,9 @@
 
 			yposScreen += vs.lineHeight;
 			visibleLine++;
+
+			lineWidthMaxSeen = Platform::Maximum(
+			            lineWidthMaxSeen, ll->positions[ll->numCharsInLine]);
 			//gdk_flush();
 		}
 		ll.Set(0);
@@ -3025,7 +3150,7 @@
 	vsPrint.showMarkedLines = false;
 	vsPrint.fixedColumnWidth = 0;
 	vsPrint.zoomLevel = printMagnification;
-	vsPrint.viewIndentationGuides = false;
+	vsPrint.viewIndentationGuides = ivNone;
 	// Don't show the selection when printing
 	vsPrint.selbackset = false;
 	vsPrint.selforeset = false;
@@ -3035,7 +3160,7 @@
 	vsPrint.showCaretLineBackground = false;
 
 	// Set colours for printing according to users settings
-	for (int sty = 0;sty <= STYLE_MAX;sty++) {
+	for (size_t sty = 0;sty < vsPrint.stylesSize;sty++) {
 		if (printColourMode == SC_PRINT_INVERTLIGHT) {
 			vsPrint.styles[sty].fore.desired = InvertedLight(vsPrint.styles[sty].fore.desired);
 			vsPrint.styles[sty].back.desired = InvertedLight(vsPrint.styles[sty].back.desired);
@@ -3058,7 +3183,7 @@
 	int lineNumberWidth = 0;
 	if (lineNumberIndex >= 0) {
 		lineNumberWidth = surfaceMeasure->WidthText(vsPrint.styles[STYLE_LINENUMBER].font,
-		                  "99999" lineNumberPrintSpace, 5 + istrlen(lineNumberPrintSpace));
+		        "99999" lineNumberPrintSpace, 5 + istrlen(lineNumberPrintSpace));
 		vsPrint.ms[lineNumberIndex].width = lineNumberWidth;
 		vsPrint.Refresh(*surfaceMeasure);	// Recalculate fixedColumnWidth
 	}
@@ -3142,12 +3267,12 @@
 			rcNumber.right = rcNumber.left + lineNumberWidth;
 			// Right justify
 			rcNumber.left = rcNumber.right - surfaceMeasure->WidthText(
-			                     vsPrint.styles[STYLE_LINENUMBER].font, number, istrlen(number));
+			            vsPrint.styles[STYLE_LINENUMBER].font, number, istrlen(number));
 			surface->FlushCachedState();
 			surface->DrawTextNoClip(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font,
-			                        ypos + vsPrint.maxAscent, number, istrlen(number),
-			                        vsPrint.styles[STYLE_LINENUMBER].fore.allocated,
-			                        vsPrint.styles[STYLE_LINENUMBER].back.allocated);
+			        ypos + vsPrint.maxAscent, number, istrlen(number),
+			        vsPrint.styles[STYLE_LINENUMBER].fore.allocated,
+			        vsPrint.styles[STYLE_LINENUMBER].back.allocated);
 		}
 
 		// Draw the line
@@ -3238,6 +3363,7 @@
 	AddCharUTF(s, 1);
 }
 
+// AddCharUTF inserts an array of bytes which may or may not be in UTF-8.
 void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
 	bool wasSelection = currentPos != anchor;
 	ClearSelection();
@@ -3257,6 +3383,14 @@
 	if (charReplaceAction) {
 		pdoc->EndUndoAction();
 	}
+	// If in wrap mode rewrap current line so EnsureCaretVisible has accurate information
+	if (wrapState != eWrapNone) {
+		AutoSurface surface(this);
+		if (surface) {
+			WrapOneLine(surface, pdoc->LineFromPosition(currentPos));
+		}
+		SetScrollBars();
+	}
 	EnsureCaretVisible();
 	// Avoid blinking during rapid typing:
 	ShowCaretAtCurrentPosition();
@@ -3266,7 +3400,7 @@
 
 	if (treatAsDBCS) {
 		NotifyChar((static_cast<unsigned char>(s[0]) << 8) |
-		           static_cast<unsigned char>(s[1]));
+		        static_cast<unsigned char>(s[1]));
 	} else {
 		int byte = static_cast<unsigned char>(s[0]);
 		if ((byte < 0xC0) || (1 == len)) {
@@ -3353,6 +3487,7 @@
 }
 
 void Editor::Cut() {
+	pdoc->CheckReadOnly();
 	if (!pdoc->IsReadOnly() && !SelectionContainsProtected()) {
 		Copy();
 		ClearSelection();
@@ -3522,7 +3657,7 @@
 	scn.line = LineFromLocation(pt);
 	scn.position = PositionFromLocationClose(pt);
 	scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
-	                (alt ? SCI_ALT : 0);
+	        (alt ? SCI_ALT : 0);
 	NotifyParent(scn);
 }
 
@@ -3531,7 +3666,7 @@
 	scn.nmhdr.code = SCN_HOTSPOTDOUBLECLICK;
 	scn.position = position;
 	scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
-	                (alt ? SCI_ALT : 0);
+	        (alt ? SCI_ALT : 0);
 	NotifyParent(scn);
 }
 
@@ -3540,7 +3675,7 @@
 	scn.nmhdr.code = SCN_HOTSPOTCLICK;
 	scn.position = position;
 	scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
-	                (alt ? SCI_ALT : 0);
+	        (alt ? SCI_ALT : 0);
 	NotifyParent(scn);
 }
 
@@ -3580,7 +3715,7 @@
 		SCNotification scn = {0};
 		scn.nmhdr.code = SCN_MARGINCLICK;
 		scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
-		                (alt ? SCI_ALT : 0);
+		        (alt ? SCI_ALT : 0);
 		scn.position = pdoc->LineStart(LineFromLocation(pt));
 		scn.margin = marginClicked;
 		NotifyParent(scn);
@@ -3632,7 +3767,7 @@
 }
 
 void Editor::CheckModificationForWrap(DocModification mh) {
-	if (mh.modificationType & (SC_MOD_INSERTTEXT|SC_MOD_DELETETEXT)) {
+	if (mh.modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) {
 		llc.Invalidate(LineLayout::llCheckTextAndStyle);
 		if (wrapState != eWrapNone) {
 			int lineDoc = pdoc->LineFromPosition(mh.position);
@@ -3670,7 +3805,16 @@
 	if (paintState == painting) {
 		CheckForChangeOutsidePaint(Range(mh.position, mh.position + mh.length));
 	}
-	if (mh.modificationType & (SC_MOD_CHANGESTYLE|SC_MOD_CHANGEINDICATOR)) {
+	if (mh.modificationType & SC_MOD_CHANGELINESTATE) {
+		if (paintState == painting) {
+			CheckForChangeOutsidePaint(
+			    Range(pdoc->LineStart(mh.line), pdoc->LineStart(mh.line + 1)));
+		} else {
+			// Could check that change is before last visible line.
+			Redraw();
+		}
+	}
+	if (mh.modificationType & (SC_MOD_CHANGESTYLE | SC_MOD_CHANGEINDICATOR)) {
 		if (mh.modificationType & SC_MOD_CHANGESTYLE) {
 			pdoc->IncrementStyleClock();
 		}
@@ -3692,13 +3836,11 @@
 			anchor = MovePositionForInsertion(anchor, mh.position, mh.length);
 			braces[0] = MovePositionForInsertion(braces[0], mh.position, mh.length);
 			braces[1] = MovePositionForInsertion(braces[1], mh.position, mh.length);
-			pdoc->decorations.InsertSpace(mh.position, mh.length);
 		} else if (mh.modificationType & SC_MOD_DELETETEXT) {
 			currentPos = MovePositionForDeletion(currentPos, mh.position, mh.length);
 			anchor = MovePositionForDeletion(anchor, mh.position, mh.length);
 			braces[0] = MovePositionForDeletion(braces[0], mh.position, mh.length);
 			braces[1] = MovePositionForDeletion(braces[1], mh.position, mh.length);
-			pdoc->decorations.DeleteRange(mh.position, mh.length);
 		}
 		if (cs.LinesDisplayed() < cs.LinesInDoc()) {
 			// Some lines are hidden so may need shown.
@@ -3768,7 +3910,7 @@
 
 	// If client wants to see this modification
 	if (mh.modificationType & modEventMask) {
-		if ((mh.modificationType & (SC_MOD_CHANGESTYLE|SC_MOD_CHANGEINDICATOR)) == 0) {
+		if ((mh.modificationType & (SC_MOD_CHANGESTYLE | SC_MOD_CHANGEINDICATOR)) == 0) {
 			// Real modification made to text of document.
 			NotifyChange();	// Send EN_CHANGE
 		}
@@ -3896,8 +4038,8 @@
 	case SCI_SELECTIONDUPLICATE:
 		break;
 
-	// Filter out all others like display changes. Also, newlines are redundant
-	// with char insert messages.
+		// Filter out all others like display changes. Also, newlines are redundant
+		// with char insert messages.
 	case SCI_NEWLINE:
 	default:
 		//		printf("Filtered out %ld of macro recording\n", iMessage);
@@ -3926,9 +4068,9 @@
 	int currentLine = pdoc->LineFromPosition(currentPos);
 	int topStutterLine = topLine + caretYSlop;
 	int bottomStutterLine =
-		pdoc->LineFromPosition(PositionFromLocation(
-		Point(lastXChosen, direction * vs.lineHeight * LinesToScroll())))
-		- caretYSlop - 1;
+	    pdoc->LineFromPosition(PositionFromLocation(
+	                Point(lastXChosen, direction * vs.lineHeight * LinesToScroll())))
+	    - caretYSlop - 1;
 
 	if (stuttered && (direction < 0 && currentLine > topStutterLine)) {
 		topLineNew = topLine;
@@ -3942,9 +4084,9 @@
 		Point pt = LocationFromPosition(currentPos);
 
 		topLineNew = Platform::Clamp(
-	                     topLine + direction * LinesToScroll(), 0, MaxScrollPos());
+		            topLine + direction * LinesToScroll(), 0, MaxScrollPos());
 		newPos = PositionFromLocation(
-	                 Point(lastXChosen, pt.y + direction * (vs.lineHeight * LinesToScroll())));
+		            Point(lastXChosen, pt.y + direction * (vs.lineHeight * LinesToScroll())));
 	}
 
 	if (topLineNew != topLine) {
@@ -3963,7 +4105,7 @@
 	int startAnchor = anchor;
 	if (selType == selStream) {
 		pdoc->ChangeCase(Range(SelectionStart(), SelectionEnd()),
-		                 makeUpperCase);
+		        makeUpperCase);
 		SetSelection(startCurrent, startAnchor);
 	} else {
 		SelectionLineIterator lineIterator(this, false);
@@ -4043,6 +4185,7 @@
 		}
 	}
 	SetLastXChosen();
+	SetScrollBars();
 	EnsureCaretVisible();
 	// Avoid blinking during rapid typing:
 	ShowCaretAtCurrentPosition();
@@ -4051,7 +4194,7 @@
 void Editor::CursorUpOrDown(int direction, selTypes sel) {
 	Point pt = LocationFromPosition(currentPos);
 	int posNew = PositionFromLocation(
-	                 Point(lastXChosen, pt.y + direction * vs.lineHeight));
+	            Point(lastXChosen, pt.y + direction * vs.lineHeight));
 	if (direction < 0) {
 		// Line wrapping may lead to a location on the same line, so
 		// seek back if that is the case.
@@ -4264,7 +4407,7 @@
 			int endPos = MovePositionSoVisible(StartEndDisplayLine(currentPos, false), 1);
 			int realEndPos = pdoc->LineEndPosition(currentPos);
 			if (endPos > realEndPos      // if moved past visible EOLs
-				|| currentPos >= endPos) // if at end of display line already
+			        || currentPos >= endPos) // if at end of display line already
 				endPos = realEndPos;
 			MovePositionTo(endPos);
 			SetLastXChosen();
@@ -4274,7 +4417,7 @@
 			int endPos = MovePositionSoVisible(StartEndDisplayLine(currentPos, false), 1);
 			int realEndPos = pdoc->LineEndPosition(currentPos);
 			if (endPos > realEndPos      // if moved past visible EOLs
-				|| currentPos >= endPos) // if at end of display line already
+			        || currentPos >= endPos) // if at end of display line already
 				endPos = realEndPos;
 			MovePositionTo(endPos, selStream);
 			SetLastXChosen();
@@ -4449,7 +4592,7 @@
 			int lineStart = pdoc->LineFromPosition(SelectionStart());
 			int lineEnd = pdoc->LineFromPosition(SelectionEnd());
 			CopyRangeToClipboard(pdoc->LineStart(lineStart),
-				pdoc->LineStart(lineEnd + 1));
+			        pdoc->LineStart(lineEnd + 1));
 		}
 		break;
 	case SCI_LINECUT: {
@@ -4502,22 +4645,22 @@
 		break;
 	case SCI_HOMEDISPLAY:
 		MovePositionTo(MovePositionSoVisible(
-		                   StartEndDisplayLine(currentPos, true), -1));
+		            StartEndDisplayLine(currentPos, true), -1));
 		SetLastXChosen();
 		break;
 	case SCI_HOMEDISPLAYEXTEND:
 		MovePositionTo(MovePositionSoVisible(
-		                   StartEndDisplayLine(currentPos, true), -1), selStream);
+		            StartEndDisplayLine(currentPos, true), -1), selStream);
 		SetLastXChosen();
 		break;
 	case SCI_LINEENDDISPLAY:
 		MovePositionTo(MovePositionSoVisible(
-		                   StartEndDisplayLine(currentPos, false), 1));
+		            StartEndDisplayLine(currentPos, false), 1));
 		SetLastXChosen();
 		break;
 	case SCI_LINEENDDISPLAYEXTEND:
 		MovePositionTo(MovePositionSoVisible(
-		                   StartEndDisplayLine(currentPos, false), 1), selStream);
+		            StartEndDisplayLine(currentPos, false), 1), selStream);
 		SetLastXChosen();
 		break;
 	}
@@ -4531,7 +4674,7 @@
 int Editor::KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed) {
 	DwellEnd(false);
 	int modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
-	                (alt ? SCI_ALT : 0);
+	        (alt ? SCI_ALT : 0);
 	int msg = kmap.Find(key, modifiers);
 	if (msg) {
 		if (consumed)
@@ -4572,7 +4715,7 @@
 					SetEmptySelection(currentPos + 1);
 				} else {
 					int numSpaces = (pdoc->tabInChars) -
-					                (pdoc->GetColumn(currentPos) % (pdoc->tabInChars));
+					        (pdoc->GetColumn(currentPos) % (pdoc->tabInChars));
 					if (numSpaces < 1)
 						numSpaces = pdoc->tabInChars;
 					for (int i = 0; i < numSpaces; i++) {
@@ -4593,7 +4736,7 @@
 				pdoc->EndUndoAction();
 			} else {
 				int newColumn = ((pdoc->GetColumn(currentPos) - 1) / pdoc->tabInChars) *
-				                pdoc->tabInChars;
+				        pdoc->tabInChars;
 				if (newColumn < 0)
 					newColumn = 0;
 				int newPos = currentPos;
@@ -4632,19 +4775,19 @@
  * @return The position of the found text, -1 if not found.
  */
 long Editor::FindText(
-	uptr_t wParam,		///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD,
-						///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX.
-	sptr_t lParam) {	///< @c TextToFind structure: The text to search for in the given range.
+    uptr_t wParam,		///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD,
+    ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX.
+    sptr_t lParam) {	///< @c TextToFind structure: The text to search for in the given range.
 
 	TextToFind *ft = reinterpret_cast<TextToFind *>(lParam);
 	int lengthFound = istrlen(ft->lpstrText);
 	int pos = pdoc->FindText(ft->chrg.cpMin, ft->chrg.cpMax, ft->lpstrText,
-	                         (wParam & SCFIND_MATCHCASE) != 0,
-	                         (wParam & SCFIND_WHOLEWORD) != 0,
-	                         (wParam & SCFIND_WORDSTART) != 0,
-	                         (wParam & SCFIND_REGEXP) != 0,
-	                         (wParam & SCFIND_POSIX) != 0,
-	                         &lengthFound);
+	        (wParam & SCFIND_MATCHCASE) != 0,
+	        (wParam & SCFIND_WHOLEWORD) != 0,
+	        (wParam & SCFIND_WORDSTART) != 0,
+	        (wParam & SCFIND_REGEXP) != 0,
+	        (wParam & SCFIND_POSIX) != 0,
+	        &lengthFound);
 	if (pos != -1) {
 		ft->chrgText.cpMin = pos;
 		ft->chrgText.cpMax = pos + lengthFound;
@@ -4675,7 +4818,7 @@
 long Editor::SearchText(
     unsigned int iMessage,		///< Accepts both @c SCI_SEARCHNEXT and @c SCI_SEARCHPREV.
     uptr_t wParam,				///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD,
-								///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX.
+    ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX.
     sptr_t lParam) {			///< The text to search for.
 
 	const char *txt = reinterpret_cast<char *>(lParam);
@@ -4683,20 +4826,20 @@
 	int lengthFound = istrlen(txt);
 	if (iMessage == SCI_SEARCHNEXT) {
 		pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt,
-		                     (wParam & SCFIND_MATCHCASE) != 0,
-		                     (wParam & SCFIND_WHOLEWORD) != 0,
-		                     (wParam & SCFIND_WORDSTART) != 0,
-		                     (wParam & SCFIND_REGEXP) != 0,
-		                     (wParam & SCFIND_POSIX) != 0,
-		                     &lengthFound);
+		        (wParam & SCFIND_MATCHCASE) != 0,
+		        (wParam & SCFIND_WHOLEWORD) != 0,
+		        (wParam & SCFIND_WORDSTART) != 0,
+		        (wParam & SCFIND_REGEXP) != 0,
+		        (wParam & SCFIND_POSIX) != 0,
+		        &lengthFound);
 	} else {
 		pos = pdoc->FindText(searchAnchor, 0, txt,
-		                     (wParam & SCFIND_MATCHCASE) != 0,
-		                     (wParam & SCFIND_WHOLEWORD) != 0,
-		                     (wParam & SCFIND_WORDSTART) != 0,
-		                     (wParam & SCFIND_REGEXP) != 0,
-		                     (wParam & SCFIND_POSIX) != 0,
-		                     &lengthFound);
+		        (wParam & SCFIND_MATCHCASE) != 0,
+		        (wParam & SCFIND_WHOLEWORD) != 0,
+		        (wParam & SCFIND_WORDSTART) != 0,
+		        (wParam & SCFIND_REGEXP) != 0,
+		        (wParam & SCFIND_POSIX) != 0,
+		        &lengthFound);
 	}
 
 	if (pos != -1) {
@@ -4713,12 +4856,12 @@
 long Editor::SearchInTarget(const char *text, int length) {
 	int lengthFound = length;
 	int pos = pdoc->FindText(targetStart, targetEnd, text,
-	                         (searchFlags & SCFIND_MATCHCASE) != 0,
-	                         (searchFlags & SCFIND_WHOLEWORD) != 0,
-	                         (searchFlags & SCFIND_WORDSTART) != 0,
-	                         (searchFlags & SCFIND_REGEXP) != 0,
-	                         (searchFlags & SCFIND_POSIX) != 0,
-	                         &lengthFound);
+	        (searchFlags & SCFIND_MATCHCASE) != 0,
+	        (searchFlags & SCFIND_WHOLEWORD) != 0,
+	        (searchFlags & SCFIND_WORDSTART) != 0,
+	        (searchFlags & SCFIND_REGEXP) != 0,
+	        (searchFlags & SCFIND_POSIX) != 0,
+	        &lengthFound);
 	if (pos != -1) {
 		targetStart = pos;
 		targetEnd = pos + lengthFound;
@@ -4761,7 +4904,7 @@
 
 void Editor::CopySelectionFromRange(SelectionText *ss, int start, int end) {
 	ss->Set(CopyRange(start, end), end - start + 1,
-		pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false);
+	        pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false);
 }
 
 void Editor::CopySelectionRange(SelectionText *ss) {
@@ -4787,8 +4930,8 @@
 				lineIterator.Reset();
 				while (lineIterator.Iterate()) {
 					for (int i = lineIterator.startPos;
-						 i < lineIterator.endPos;
-						 i++) {
+					        i < lineIterator.endPos;
+					        i++) {
 						text[j++] = pdoc->CharAt(i);
 					}
 					if (selType != selLines) {
@@ -4804,7 +4947,7 @@
 			}
 		}
 		ss->Set(text, size + 1, pdoc->dbcsCodePage,
-			vs.styles[STYLE_DEFAULT].characterSet, selType == selRectangle);
+		        vs.styles[STYLE_DEFAULT].characterSet, selType == selRectangle);
 	}
 }
 
@@ -4813,14 +4956,14 @@
 	end = pdoc->ClampPositionIntoDocument(end);
 	SelectionText selectedText;
 	selectedText.Set(CopyRange(start, end), end - start + 1,
-		pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false);
+	        pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false);
 	CopyToClipboard(selectedText);
 }
 
 void Editor::CopyText(int length, const char *text) {
 	SelectionText selectedText;
 	selectedText.Copy(text, length + 1,
-		pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false);
+	        pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false);
 	CopyToClipboard(selectedText);
 }
 
@@ -4991,13 +5134,13 @@
 void Editor::LineSelection(int lineCurrent_, int lineAnchor_) {
 	if (lineAnchor_ < lineCurrent_) {
 		SetSelection(pdoc->LineStart(lineCurrent_ + 1),
-		             pdoc->LineStart(lineAnchor_));
+		        pdoc->LineStart(lineAnchor_));
 	} else if (lineAnchor_ > lineCurrent_) {
 		SetSelection(pdoc->LineStart(lineCurrent_),
-		             pdoc->LineStart(lineAnchor_ + 1));
+		        pdoc->LineStart(lineAnchor_ + 1));
 	} else { // Same line, select it
 		SetSelection(pdoc->LineStart(lineAnchor_ + 1),
-		             pdoc->LineStart(lineAnchor_));
+		        pdoc->LineStart(lineAnchor_));
 	}
 }
 
@@ -5051,10 +5194,10 @@
 		if (selectionType == selWord) {
 			if (currentPos >= originalAnchorPos) {	// Moved forward
 				SetSelection(pdoc->ExtendWordSelect(currentPos, 1),
-				             pdoc->ExtendWordSelect(originalAnchorPos, -1));
+				        pdoc->ExtendWordSelect(originalAnchorPos, -1));
 			} else {	// Moved backward
 				SetSelection(pdoc->ExtendWordSelect(currentPos, -1),
-				             pdoc->ExtendWordSelect(originalAnchorPos, 1));
+				        pdoc->ExtendWordSelect(originalAnchorPos, 1));
 			}
 		} else if (selectionType == selLine) {
 			lineAnchor = LineFromLocation(pt);
@@ -5082,7 +5225,7 @@
 				// Single click in margin: select whole line
 				LineSelection(lineAnchor, lineAnchor);
 				SetSelection(pdoc->LineStart(lineAnchor + 1),
-				             pdoc->LineStart(lineAnchor));
+				        pdoc->LineStart(lineAnchor));
 			} else {
 				// Single shift+click in margin: select from line anchor to clicked line
 				if (anchor > currentPos)
@@ -5107,14 +5250,6 @@
 				else
 					inDragDrop = ddNone;
 			}
-#ifdef __APPLE__
-			// we need to additionaly check if the mouse moved before we
-			// decide that we can in fact start a drag session.  Currently
-			// only OSX will return anything but true.
-			if (inDragDrop == ddInitial && !Platform::WaitMouseMoved(pt)) {
-				inDragDrop = ddNone;
-			}
-#endif
 			SetMouseCapture(true);
 			if (inDragDrop != ddInitial) {
 				SetDragPosition(invalidPosition);
@@ -5230,10 +5365,10 @@
 					// being unmade.
 				} else if (movePos > originalAnchorPos) {	// Moved forward
 					SetSelection(pdoc->ExtendWordSelect(movePos, 1),
-					             pdoc->ExtendWordSelect(originalAnchorPos, -1));
+					        pdoc->ExtendWordSelect(originalAnchorPos, -1));
 				} else {	// Moved backward
 					SetSelection(pdoc->ExtendWordSelect(movePos, -1),
-					             pdoc->ExtendWordSelect(originalAnchorPos, 1));
+					        pdoc->ExtendWordSelect(originalAnchorPos, 1));
 				}
 			} else {
 				// Continue selecting by line
@@ -5366,6 +5501,10 @@
 			}
 		}
 	}
+	if (horizontalScrollBarVisible && trackLineWidth && (lineWidthMaxSeen > scrollWidth)) {
+		scrollWidth = lineWidthMaxSeen;
+		SetScrollBars();
+	}
 	if ((dwellDelay < SC_TIME_FOREVER) &&
 	        (ticksToDwell > 0) &&
 	        (!HaveMouseCapture())) {
@@ -5413,7 +5552,11 @@
 }
 
 bool Editor::PaintContains(PRectangle rc) {
-	return rcPaint.Contains(rc);
+	if (rc.Empty()) {
+		return true;
+	} else {
+		return rcPaint.Contains(rc);
+	}
 }
 
 bool Editor::PaintContainsMargin() {
@@ -5583,7 +5726,7 @@
 				SetVerticalScrollPos();
 				Redraw();
 			} else if ((lineDisplay > topLine + LinesOnScreen() - 1) ||
-			           ((visiblePolicy & VISIBLE_STRICT) && (lineDisplay > topLine + LinesOnScreen() - 1 - visibleSlop))) {
+			        ((visiblePolicy & VISIBLE_STRICT) && (lineDisplay > topLine + LinesOnScreen() - 1 - visibleSlop))) {
 				SetTopLine(Platform::Clamp(lineDisplay - LinesOnScreen() + 1 + visibleSlop, 0, MaxScrollPos()));
 				SetVerticalScrollPos();
 				Redraw();
@@ -5604,8 +5747,10 @@
 		length = istrlen(text);
 	if (replacePatterns) {
 		text = pdoc->SubstituteByPosition(text, &length);
-		if (!text)
+		if (!text) {
+			pdoc->EndUndoAction();
 			return 0;
+		}
 	}
 	if (targetStart != targetEnd)
 		pdoc->DeleteChars(targetStart, targetEnd - targetStart);
@@ -5645,11 +5790,11 @@
 	char *text = new char[textLength];
 	if (text) {
 		size_t i;
-		for (i=0;i<textLength;i++) {
+		for (i = 0;i < textLength;i++) {
 			text[i] = buffer[i*2];
 		}
 		pdoc->InsertString(CurrentPosition(), text, textLength);
-		for (i=0;i<textLength;i++) {
+		for (i = 0;i < textLength;i++) {
 			text[i] = buffer[i*2+1];
 		}
 		pdoc->StartStyling(CurrentPosition(), static_cast<char>(0xff));
@@ -5667,6 +5812,89 @@
 	return reinterpret_cast<char *>(lParam);
 }
 
+void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+	vs.EnsureStyle(wParam);
+	switch (iMessage) {
+	case SCI_STYLESETFORE:
+		vs.styles[wParam].fore.desired = ColourDesired(lParam);
+		break;
+	case SCI_STYLESETBACK:
+		vs.styles[wParam].back.desired = ColourDesired(lParam);
+		break;
+	case SCI_STYLESETBOLD:
+		vs.styles[wParam].bold = lParam != 0;
+		break;
+	case SCI_STYLESETITALIC:
+		vs.styles[wParam].italic = lParam != 0;
+		break;
+	case SCI_STYLESETEOLFILLED:
+		vs.styles[wParam].eolFilled = lParam != 0;
+		break;
+	case SCI_STYLESETSIZE:
+		vs.styles[wParam].size = lParam;
+		break;
+	case SCI_STYLESETFONT:
+		if (lParam != 0) {
+			vs.SetStyleFontName(wParam, CharPtrFromSPtr(lParam));
+		}
+		break;
+	case SCI_STYLESETUNDERLINE:
+		vs.styles[wParam].underline = lParam != 0;
+		break;
+	case SCI_STYLESETCASE:
+		vs.styles[wParam].caseForce = static_cast<Style::ecaseForced>(lParam);
+		break;
+	case SCI_STYLESETCHARACTERSET:
+		vs.styles[wParam].characterSet = lParam;
+		break;
+	case SCI_STYLESETVISIBLE:
+		vs.styles[wParam].visible = lParam != 0;
+		break;
+	case SCI_STYLESETCHANGEABLE:
+		vs.styles[wParam].changeable = lParam != 0;
+		break;
+	case SCI_STYLESETHOTSPOT:
+		vs.styles[wParam].hotspot = lParam != 0;
+		break;
+	}
+	InvalidateStyleRedraw();
+}
+
+sptr_t Editor::StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
+	vs.EnsureStyle(wParam);
+	switch (iMessage) {
+	case SCI_STYLEGETFORE:
+		return vs.styles[wParam].fore.desired.AsLong();
+	case SCI_STYLEGETBACK:
+		return vs.styles[wParam].back.desired.AsLong();
+	case SCI_STYLEGETBOLD:
+		return vs.styles[wParam].bold ? 1 : 0;
+	case SCI_STYLEGETITALIC:
+		return vs.styles[wParam].italic ? 1 : 0;
+	case SCI_STYLEGETEOLFILLED:
+		return vs.styles[wParam].eolFilled ? 1 : 0;
+	case SCI_STYLEGETSIZE:
+		return vs.styles[wParam].size;
+	case SCI_STYLEGETFONT:
+		if (lParam != 0)
+			strcpy(CharPtrFromSPtr(lParam), vs.styles[wParam].fontName);
+		return strlen(vs.styles[wParam].fontName);
+	case SCI_STYLEGETUNDERLINE:
+		return vs.styles[wParam].underline ? 1 : 0;
+	case SCI_STYLEGETCASE:
+		return static_cast<int>(vs.styles[wParam].caseForce);
+	case SCI_STYLEGETCHARACTERSET:
+		return vs.styles[wParam].characterSet;
+	case SCI_STYLEGETVISIBLE:
+		return vs.styles[wParam].visible ? 1 : 0;
+	case SCI_STYLEGETCHANGEABLE:
+		return vs.styles[wParam].changeable ? 1 : 0;
+	case SCI_STYLEGETHOTSPOT:
+		return vs.styles[wParam].hotspot ? 1 : 0;
+	}
+	return 0;
+}
+
 sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
 	//Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam);
 
@@ -5896,10 +6124,10 @@
 		return searchFlags;
 
 	case SCI_POSITIONBEFORE:
-		return pdoc->MovePositionOutsideChar(wParam-1, -1, true);
+		return pdoc->MovePositionOutsideChar(wParam - 1, -1, true);
 
 	case SCI_POSITIONAFTER:
-		return pdoc->MovePositionOutsideChar(wParam+1, 1, true);
+		return pdoc->MovePositionOutsideChar(wParam + 1, 1, true);
 
 	case SCI_LINESCROLL:
 		ScrollTo(topLine + lParam);
@@ -6394,6 +6622,7 @@
 	case SCI_SETSCROLLWIDTH:
 		PLATFORM_ASSERT(wParam > 0);
 		if ((wParam > 0) && (wParam != static_cast<unsigned int >(scrollWidth))) {
+			lineWidthMaxSeen = 0;
 			scrollWidth = wParam;
 			SetScrollBars();
 		}
@@ -6402,6 +6631,13 @@
 	case SCI_GETSCROLLWIDTH:
 		return scrollWidth;
 
+	case SCI_SETSCROLLWIDTHTRACKING:
+		trackLineWidth = wParam != 0;
+		break;
+
+	case SCI_GETSCROLLWIDTHTRACKING:
+		return trackLineWidth;
+
 	case SCI_LINESJOIN:
 		LinesJoin();
 		break;
@@ -6411,7 +6647,7 @@
 		break;
 
 	case SCI_TEXTWIDTH:
-		PLATFORM_ASSERT(wParam <= STYLE_MAX);
+		PLATFORM_ASSERT(wParam < vs.stylesSize);
 		PLATFORM_ASSERT(lParam);
 		return TextWidth(wParam, CharPtrFromSPtr(lParam));
 
@@ -6472,7 +6708,7 @@
 		return verticalScrollBarVisible;
 
 	case SCI_SETINDENTATIONGUIDES:
-		vs.viewIndentationGuides = wParam != 0;
+		vs.viewIndentationGuides = IndentView(wParam);
 		Redraw();
 		break;
 
@@ -6640,157 +6876,42 @@
 		break;
 
 	case SCI_STYLESETFORE:
-		if (wParam <= STYLE_MAX) {
-			vs.styles[wParam].fore.desired = ColourDesired(lParam);
-			InvalidateStyleRedraw();
-		}
-		break;
 	case SCI_STYLESETBACK:
-		if (wParam <= STYLE_MAX) {
-			vs.styles[wParam].back.desired = ColourDesired(lParam);
-			InvalidateStyleRedraw();
-		}
-		break;
 	case SCI_STYLESETBOLD:
-		if (wParam <= STYLE_MAX) {
-			vs.styles[wParam].bold = lParam != 0;
-			InvalidateStyleRedraw();
-		}
-		break;
 	case SCI_STYLESETITALIC:
-		if (wParam <= STYLE_MAX) {
-			vs.styles[wParam].italic = lParam != 0;
-			InvalidateStyleRedraw();
-		}
-		break;
 	case SCI_STYLESETEOLFILLED:
-		if (wParam <= STYLE_MAX) {
-			vs.styles[wParam].eolFilled = lParam != 0;
-			InvalidateStyleRedraw();
-		}
-		break;
 	case SCI_STYLESETSIZE:
-		if (wParam <= STYLE_MAX) {
-			vs.styles[wParam].size = lParam;
-			InvalidateStyleRedraw();
-		}
-		break;
 	case SCI_STYLESETFONT:
-		if (lParam == 0)
-			return 0;
-		if (wParam <= STYLE_MAX) {
-			vs.SetStyleFontName(wParam, CharPtrFromSPtr(lParam));
-			InvalidateStyleRedraw();
-		}
-		break;
 	case SCI_STYLESETUNDERLINE:
-		if (wParam <= STYLE_MAX) {
-			vs.styles[wParam].underline = lParam != 0;
-			InvalidateStyleRedraw();
-		}
-		break;
 	case SCI_STYLESETCASE:
-		if (wParam <= STYLE_MAX) {
-			vs.styles[wParam].caseForce = static_cast<Style::ecaseForced>(lParam);
-			InvalidateStyleRedraw();
-		}
-		break;
 	case SCI_STYLESETCHARACTERSET:
-		if (wParam <= STYLE_MAX) {
-			vs.styles[wParam].characterSet = lParam;
-			InvalidateStyleRedraw();
-		}
-		break;
 	case SCI_STYLESETVISIBLE:
-		if (wParam <= STYLE_MAX) {
-			vs.styles[wParam].visible = lParam != 0;
-			InvalidateStyleRedraw();
-		}
-		break;
 	case SCI_STYLESETCHANGEABLE:
-		if (wParam <= STYLE_MAX) {
-			vs.styles[wParam].changeable = lParam != 0;
-			InvalidateStyleRedraw();
-		}
-		break;
 	case SCI_STYLESETHOTSPOT:
-		if (wParam <= STYLE_MAX) {
-			vs.styles[wParam].hotspot = lParam != 0;
-			InvalidateStyleRedraw();
-		}
+		StyleSetMessage(iMessage, wParam, lParam);
 		break;
+
 	case SCI_STYLEGETFORE:
-		if (wParam <= STYLE_MAX)
-			return vs.styles[wParam].fore.desired.AsLong();
-		else
-			return 0;
 	case SCI_STYLEGETBACK:
-		if (wParam <= STYLE_MAX)
-			return vs.styles[wParam].back.desired.AsLong();
-		else
-			return 0;
 	case SCI_STYLEGETBOLD:
-		if (wParam <= STYLE_MAX)
-			return vs.styles[wParam].bold ? 1 : 0;
-		else
-			return 0;
 	case SCI_STYLEGETITALIC:
-		if (wParam <= STYLE_MAX)
-			return vs.styles[wParam].italic ? 1 : 0;
-		else
-			return 0;
 	case SCI_STYLEGETEOLFILLED:
-		if (wParam <= STYLE_MAX)
-			return vs.styles[wParam].eolFilled ? 1 : 0;
-		else
-			return 0;
 	case SCI_STYLEGETSIZE:
-		if (wParam <= STYLE_MAX)
-			return vs.styles[wParam].size;
-		else
-			return 0;
 	case SCI_STYLEGETFONT:
-		if (lParam == 0)
-			return strlen(vs.styles[wParam].fontName);
-
-		if (wParam <= STYLE_MAX)
-			strcpy(CharPtrFromSPtr(lParam), vs.styles[wParam].fontName);
-		break;
 	case SCI_STYLEGETUNDERLINE:
-		if (wParam <= STYLE_MAX)
-			return vs.styles[wParam].underline ? 1 : 0;
-		else
-			return 0;
 	case SCI_STYLEGETCASE:
-		if (wParam <= STYLE_MAX)
-			return static_cast<int>(vs.styles[wParam].caseForce);
-		else
-			return 0;
 	case SCI_STYLEGETCHARACTERSET:
-		if (wParam <= STYLE_MAX)
-			return vs.styles[wParam].characterSet;
-		else
-			return 0;
 	case SCI_STYLEGETVISIBLE:
-		if (wParam <= STYLE_MAX)
-			return vs.styles[wParam].visible ? 1 : 0;
-		else
-			return 0;
 	case SCI_STYLEGETCHANGEABLE:
-		if (wParam <= STYLE_MAX)
-			return vs.styles[wParam].changeable ? 1 : 0;
-		else
-			return 0;
 	case SCI_STYLEGETHOTSPOT:
-		if (wParam <= STYLE_MAX)
-			return vs.styles[wParam].hotspot ? 1 : 0;
-		else
-			return 0;
+		return StyleGetMessage(iMessage, wParam, lParam);
+
 	case SCI_STYLERESETDEFAULT:
 		vs.ResetDefaultStyle();
 		InvalidateStyleRedraw();
 		break;
 	case SCI_SETSTYLEBITS:
+		vs.EnsureStyle((1 << wParam) - 1);
 		pdoc->SetStylingBits(wParam);
 		break;
 
@@ -7001,12 +7122,12 @@
 
 	case SCI_ASSIGNCMDKEY:
 		kmap.AssignCmdKey(Platform::LowShortFromLong(wParam),
-		                  Platform::HighShortFromLong(wParam), lParam);
+		        Platform::HighShortFromLong(wParam), lParam);
 		break;
 
 	case SCI_CLEARCMDKEY:
 		kmap.AssignCmdKey(Platform::LowShortFromLong(wParam),
-		                  Platform::HighShortFromLong(wParam), SCI_NULL);
+		        Platform::HighShortFromLong(wParam), SCI_NULL);
 		break;
 
 	case SCI_CLEARALLCMDKEYS:

Modified: trunk/scintilla/Editor.h
===================================================================
--- trunk/scintilla/Editor.h	2007-12-02 10:52:19 UTC (rev 2085)
+++ trunk/scintilla/Editor.h	2007-12-02 11:58:17 UTC (rev 2086)
@@ -136,6 +136,8 @@
 	int xCaretMargin;	///< Ensure this many pixels visible on both sides of caret
 	bool horizontalScrollBarVisible;
 	int scrollWidth;
+	bool trackLineWidth;
+	int lineWidthMaxSeen;
 	bool verticalScrollBarVisible;
 	bool endAtLastLine;
 	bool caretSticky;
@@ -297,6 +299,7 @@
 	virtual void UpdateSystemCaret();
 
 	void NeedWrapping(int docLineStart = 0, int docLineEnd = wrapLineLarge);
+	bool WrapOneLine(Surface *surface, int lineToWrap);
 	bool WrapLines(bool fullWrap, int priorityWrapLineStart);
 	void LinesJoin();
 	void LinesSplit(int pixelWidth);
@@ -454,6 +457,8 @@
 	void AddStyledText(char *buffer, int appendLength);
 
 	virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) = 0;
+	void StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
+	sptr_t StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
 
 public:
 	// Public so the COM thunks can access it.

Modified: trunk/scintilla/LexBash.cxx
===================================================================
--- trunk/scintilla/LexBash.cxx	2007-12-02 10:52:19 UTC (rev 2085)
+++ trunk/scintilla/LexBash.cxx	2007-12-02 11:58:17 UTC (rev 2086)
@@ -2,7 +2,7 @@
 /** @file LexBash.cxx
  ** Lexer for Bash.
  **/
-// Copyright 2004-2005 by Neil Hodgson <neilh at scintilla.org>
+// Copyright 2004-2007 by Neil Hodgson <neilh at scintilla.org>
 // Adapted from LexPerl by Kein-Hong Man <mkh at pl.jaring.my> 2004
 // The License.txt file describes the conditions under which this software may be distributed.
 
@@ -20,11 +20,17 @@
 #include "Scintilla.h"
 #include "SciLexer.h"
 
+// define this if you want 'invalid octals' to be marked as errors
+// usually, this is not a good idea, permissive lexing is better
+#undef PEDANTIC_OCTAL
+
 #define BASH_BASE_ERROR		65
 #define BASH_BASE_DECIMAL	66
 #define BASH_BASE_HEX		67
+#ifdef PEDANTIC_OCTAL
 #define BASH_BASE_OCTAL		68
 #define BASH_BASE_OCTAL_ERROR	69
+#endif
 
 #define HERE_DELIM_MAX 256
 
@@ -277,7 +283,11 @@
 						ch = chNext;
 						chNext = chNext2;
 					} else if (isdigit(chNext)) {
+#ifdef PEDANTIC_OCTAL
 						numBase = BASH_BASE_OCTAL;
+#else
+						numBase = BASH_BASE_HEX;
+#endif
 					}
 				}
 			} else if (iswordstart(ch)) {
@@ -369,14 +379,16 @@
 					// hex digit 0-9a-fA-F
 				} else
 					goto numAtEnd;
+#ifdef PEDANTIC_OCTAL
 			} else if (numBase == BASH_BASE_OCTAL ||
 				   numBase == BASH_BASE_OCTAL_ERROR) {
 				if (digit > 7) {
 					if (digit <= 9) {
-						numBase = BASH_BASE_OCTAL_ERROR;
+                                                numBase = BASH_BASE_OCTAL_ERROR;
 					} else
 						goto numAtEnd;
 				}
+#endif
 			} else if (numBase == BASH_BASE_ERROR) {
 				if (digit > 9)
 					goto numAtEnd;
@@ -394,8 +406,11 @@
 					}
 				} else {
 			numAtEnd:
-					if (numBase == BASH_BASE_ERROR ||
-					    numBase == BASH_BASE_OCTAL_ERROR)
+					if (numBase == BASH_BASE_ERROR
+#ifdef PEDANTIC_OCTAL
+					    || numBase == BASH_BASE_OCTAL_ERROR
+#endif
+                                           )
 						state = SCE_SH_ERROR;
 					styler.ColourTo(i - 1, state);
 					state = SCE_SH_DEFAULT;

Modified: trunk/scintilla/LexCPP.cxx
===================================================================
--- trunk/scintilla/LexCPP.cxx	2007-12-02 10:52:19 UTC (rev 2085)
+++ trunk/scintilla/LexCPP.cxx	2007-12-02 11:58:17 UTC (rev 2086)
@@ -32,6 +32,24 @@
 		(state == SCE_C_COMMENTDOCKEYWORDERROR);
 }
 
+// Preconditions: sc.currentPos points to a character after '+' or '-'.
+// The test for pos reaching 0 should be redundant,
+// and is in only for safety measures.
+// Limitation: this code will give the incorrect answer for code like
+// a = b+++/ptn/...
+// Putting a space between the '++' post-inc operator and the '+' binary op
+// fixes this, and is highly recommended for readability anyway.
+static bool FollowsPostfixOperator(StyleContext &sc, Accessor &styler) {
+	int pos = (int) sc.currentPos;
+	while (--pos > 0) {
+		char ch = styler[pos];
+		if (ch == '+' || ch == '-') {
+			return styler[pos - 1] == ch;
+		}
+	}
+	return false;
+}
+
 static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
                             Accessor &styler, bool caseSensitive) {
 
@@ -42,7 +60,8 @@
 
 	bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;
 
-	CharacterSet setOKBeforeRE(CharacterSet::setNone, "(=,");
+	CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-");
+	CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-");
 
 	CharacterSet setDoxygen(CharacterSet::setLower, "$@\\&<>#{}[]");
 
@@ -297,7 +316,8 @@
 					sc.SetState(SCE_C_COMMENTLINEDOC);
 				else
 					sc.SetState(SCE_C_COMMENTLINE);
-			} else if (sc.ch == '/' && setOKBeforeRE.Contains(chPrevNonWhite)) {
+			} else if (sc.ch == '/' && setOKBeforeRE.Contains(chPrevNonWhite) &&
+				(!setCouldBePostOp.Contains(chPrevNonWhite) || !FollowsPostfixOperator(sc, styler))) {
 				sc.SetState(SCE_C_REGEX);	// JavaScript's RegEx
 			} else if (sc.ch == '\"') {
 				sc.SetState(SCE_C_STRING);
@@ -337,7 +357,7 @@
 // Store both the current line's fold level and the next lines in the
 // level store to make it easy to pick up with each increment
 // and to make it possible to fiddle the current level for "} else {".
-static void FoldCppDoc(unsigned int startPos, int length, int initStyle, 
+static void FoldCppDoc(unsigned int startPos, int length, int initStyle,
 					   WordList *[], Accessor &styler) {
 	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
 	bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;

Modified: trunk/scintilla/LexHTML.cxx
===================================================================
--- trunk/scintilla/LexHTML.cxx	2007-12-02 10:52:19 UTC (rev 2085)
+++ trunk/scintilla/LexHTML.cxx	2007-12-02 11:58:17 UTC (rev 2086)
@@ -565,7 +565,7 @@
 				break;
 		}
 		if (style == SCE_HJ_SYMBOLS) {
-			chPrevNonWhite = styler.SafeGetCharAt(back);
+			chPrevNonWhite = static_cast<unsigned char>(styler.SafeGetCharAt(back));
 		}
 	}
 
@@ -676,10 +676,13 @@
 			case SCE_HJ_COMMENTDOC:
 			//case SCE_HJ_COMMENTLINE: // removed as this is a common thing done to hide
 			// the end of script marker from some JS interpreters.
+			case SCE_HB_COMMENTLINE:
+			case SCE_HBA_COMMENTLINE:
 			case SCE_HJ_DOUBLESTRING:
 			case SCE_HJ_SINGLESTRING:
 			case SCE_HJ_REGEX:
 			case SCE_HB_STRING:
+			case SCE_HBA_STRING:
 			case SCE_HP_STRING:
 			case SCE_HP_TRIPLE:
 			case SCE_HP_TRIPLEDOUBLE:
@@ -688,9 +691,8 @@
 				// check if the closing tag is a script tag
 				if (state == SCE_HJ_COMMENTLINE || isXml) {
 					char tag[7]; // room for the <script> tag
-					char chr;	// current char
-					int j=0;
-					chr = styler.SafeGetCharAt(i+2);
+					int j = 0;
+					char chr = styler.SafeGetCharAt(i+2);
 					while (j < 6 && !IsASpace(chr)) {
 						tag[j++] = static_cast<char>(MakeLowerCase(chr));
 						chr = styler.SafeGetCharAt(i+2+j);
@@ -740,7 +742,7 @@
 				levelCurrent++;
 			}
 			// should be better

@@ Diff output truncated at 100000 characters. @@

This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



More information about the Commits mailing list