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@scintilla.org +// Copyright 1998-2007 by Neil Hodgson neilh@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@scintilla.org +// Copyright 1998-2007 by Neil Hodgson neilh@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_castStyle::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_castStyle::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@scintilla.org +// Copyright 2004-2007 by Neil Hodgson neilh@scintilla.org // Adapted from LexPerl by Kein-Hong Man mkh@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.