aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorNeil <nyamatongwe@gmail.com>2014-07-08 18:05:35 +1000
committerNeil <nyamatongwe@gmail.com>2014-07-08 18:05:35 +1000
commit5bfc97a368eb7c8d3c78b0c454be806d6dcb6340 (patch)
treeccca6ba6e81d9cb3e98abf36d1eeaf7eb98c92a4
parent1e8908c6d5fd998e9d8a9408a6b86ef4a2ff64e8 (diff)
downloadscintilla-mirror-5bfc97a368eb7c8d3c78b0c454be806d6dcb6340.tar.gz
Split out EditModel, MarginView, and EditView classes into separate files.
-rw-r--r--cocoa/ScintillaCocoa.h3
-rw-r--r--gtk/ScintillaGTK.cxx3
-rw-r--r--gtk/makefile3
-rw-r--r--qt/ScintillaEdit/ScintillaEdit.pro3
-rw-r--r--qt/ScintillaEditBase/ScintillaEditBase.pro3
-rw-r--r--qt/ScintillaEditBase/ScintillaQt.h3
-rw-r--r--scripts/HeaderOrder.txt3
-rw-r--r--src/EditModel.cxx74
-rw-r--r--src/EditModel.h67
-rw-r--r--src/EditView.cxx1815
-rw-r--r--src/EditView.h113
-rw-r--r--src/Editor.cxx2298
-rw-r--r--src/Editor.h141
-rw-r--r--src/MarginView.cxx532
-rw-r--r--src/MarginView.h47
-rw-r--r--src/ScintillaBase.cxx3
-rw-r--r--win32/ScintillaWin.cxx3
-rw-r--r--win32/deps.mak141
-rw-r--r--win32/makefile9
-rw-r--r--win32/scintilla.mak684
20 files changed, 3316 insertions, 2632 deletions
diff --git a/cocoa/ScintillaCocoa.h b/cocoa/ScintillaCocoa.h
index ec253b161..61d78c449 100644
--- a/cocoa/ScintillaCocoa.h
+++ b/cocoa/ScintillaCocoa.h
@@ -48,6 +48,9 @@
#include "CaseConvert.h"
#include "Selection.h"
#include "PositionCache.h"
+#include "EditModel.h"
+#include "MarginView.h"
+#include "EditView.h"
#include "Editor.h"
#include "AutoComplete.h"
diff --git a/gtk/ScintillaGTK.cxx b/gtk/ScintillaGTK.cxx
index fe3547fe2..3285967da 100644
--- a/gtk/ScintillaGTK.cxx
+++ b/gtk/ScintillaGTK.cxx
@@ -57,6 +57,9 @@
#include "UniConversion.h"
#include "Selection.h"
#include "PositionCache.h"
+#include "EditModel.h"
+#include "MarginView.h"
+#include "EditView.h"
#include "Editor.h"
#include "AutoComplete.h"
#include "ScintillaBase.h"
diff --git a/gtk/makefile b/gtk/makefile
index 10528fac1..c4c5822e8 100644
--- a/gtk/makefile
+++ b/gtk/makefile
@@ -90,7 +90,8 @@ deps:
$(COMPLIB): Accessor.o CharacterSet.o LexerBase.o LexerModule.o LexerSimple.o StyleContext.o WordList.o \
CharClassify.o Decoration.o Document.o PerLine.o Catalogue.o CallTip.o CaseConvert.o CaseFolder.o \
- ScintillaBase.o ContractionState.o Editor.o ExternalLexer.o PropSetSimple.o PlatGTK.o \
+ ScintillaBase.o ContractionState.o EditModel.o Editor.o EditView.o ExternalLexer.o MarginView.o \
+ PropSetSimple.o PlatGTK.o \
KeyMap.o LineMarker.o PositionCache.o ScintillaGTK.o CellBuffer.o CharacterCategory.o ViewStyle.o \
RESearch.o RunStyles.o Selection.o Style.o Indicator.o AutoComplete.o UniConversion.o XPM.o \
$(MARSHALLER) $(LEXOBJS)
diff --git a/qt/ScintillaEdit/ScintillaEdit.pro b/qt/ScintillaEdit/ScintillaEdit.pro
index eb0250e4e..2ee0ef1d8 100644
--- a/qt/ScintillaEdit/ScintillaEdit.pro
+++ b/qt/ScintillaEdit/ScintillaEdit.pro
@@ -29,11 +29,14 @@ SOURCES += \
../../src/RESearch.cxx \
../../src/PositionCache.cxx \
../../src/PerLine.cxx \
+ ../../src/MarginView.cxx \
../../src/LineMarker.cxx \
../../src/KeyMap.cxx \
../../src/Indicator.cxx \
../../src/ExternalLexer.cxx \
+ ../../src/EditView.cxx \
../../src/Editor.cxx \
+ ../../src/EditModel.cxx \
../../src/Document.cxx \
../../src/Decoration.cxx \
../../src/ContractionState.cxx \
diff --git a/qt/ScintillaEditBase/ScintillaEditBase.pro b/qt/ScintillaEditBase/ScintillaEditBase.pro
index 6baf52193..4cdd0f257 100644
--- a/qt/ScintillaEditBase/ScintillaEditBase.pro
+++ b/qt/ScintillaEditBase/ScintillaEditBase.pro
@@ -27,11 +27,14 @@ SOURCES += \
../../src/RESearch.cxx \
../../src/PositionCache.cxx \
../../src/PerLine.cxx \
+ ../../src/MarginView.cxx \
../../src/LineMarker.cxx \
../../src/KeyMap.cxx \
../../src/Indicator.cxx \
../../src/ExternalLexer.cxx \
+ ../../src/EditView.cxx \
../../src/Editor.cxx \
+ ../../src/EditModel.cxx \
../../src/Document.cxx \
../../src/Decoration.cxx \
../../src/ContractionState.cxx \
diff --git a/qt/ScintillaEditBase/ScintillaQt.h b/qt/ScintillaEditBase/ScintillaQt.h
index 7defd7c05..ff4d65992 100644
--- a/qt/ScintillaEditBase/ScintillaQt.h
+++ b/qt/ScintillaEditBase/ScintillaQt.h
@@ -43,6 +43,9 @@
#include "Document.h"
#include "Selection.h"
#include "PositionCache.h"
+#include "EditModel.h"
+#include "MarginView.h"
+#include "EditView.h"
#include "Editor.h"
#include "ScintillaBase.h"
#include "CaseConvert.h"
diff --git a/scripts/HeaderOrder.txt b/scripts/HeaderOrder.txt
index 96af584d3..d2a397bd9 100644
--- a/scripts/HeaderOrder.txt
+++ b/scripts/HeaderOrder.txt
@@ -106,6 +106,9 @@
#include "Selection.h"
#include "PositionCache.h"
#include "FontQuality.h"
+#include "EditModel.h"
+#include "MarginView.h"
+#include "EditView.h"
#include "Editor.h"
#include "AutoComplete.h"
diff --git a/src/EditModel.cxx b/src/EditModel.cxx
new file mode 100644
index 000000000..815d22781
--- /dev/null
+++ b/src/EditModel.cxx
@@ -0,0 +1,74 @@
+// Scintilla source code edit control
+/** @file EditModel.cxx
+ ** Defines the editor state that must be visible to EditorView.
+ **/
+// Copyright 1998-2014 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <string>
+#include <vector>
+#include <map>
+#include <algorithm>
+#include <memory>
+
+#include "Platform.h"
+
+#include "ILexer.h"
+#include "Scintilla.h"
+
+#include "StringCopy.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "ContractionState.h"
+#include "CellBuffer.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "XPM.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+#include "CharClassify.h"
+#include "Decoration.h"
+#include "CaseFolder.h"
+#include "Document.h"
+#include "UniConversion.h"
+#include "Selection.h"
+#include "PositionCache.h"
+#include "EditModel.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+Caret::Caret() :
+ active(false), on(false), period(500) {}
+
+EditModel::EditModel() {
+ inOverstrike = false;
+ xOffset = 0;
+ trackLineWidth = false;
+ posDrag = SelectionPosition(invalidPosition);
+ braces[0] = invalidPosition;
+ braces[1] = invalidPosition;
+ bracesMatchStyle = STYLE_BRACEBAD;
+ highlightGuideColumn = 0;
+ primarySelection = true;
+ foldFlags = 0;
+ hotspot = Range(invalidPosition);
+ wrapWidth = LineLayout::wrapWidthInfinite;
+ pdoc = new Document();
+ pdoc->AddRef();
+}
+
+EditModel::~EditModel() {
+ pdoc->Release();
+ pdoc = 0;
+}
diff --git a/src/EditModel.h b/src/EditModel.h
new file mode 100644
index 000000000..86d2cd40e
--- /dev/null
+++ b/src/EditModel.h
@@ -0,0 +1,67 @@
+// Scintilla source code edit control
+/** @file EditModel.h
+ ** Defines the editor state that must be visible to EditorView.
+ **/
+// Copyright 1998-2014 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef EDITMODEL_H
+#define EDITMODEL_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+/**
+*/
+class Caret {
+public:
+ bool active;
+ bool on;
+ int period;
+
+ Caret();
+};
+
+class EditModel {
+ // Private so EditModel objects can not be copied
+ EditModel(const EditModel &);
+ EditModel &operator=(const EditModel &);
+
+public:
+ bool inOverstrike;
+ int xOffset; ///< Horizontal scrolled amount in pixels
+ bool trackLineWidth;
+
+ SpecialRepresentations reprs;
+ Caret caret;
+ SelectionPosition posDrag;
+ Position braces[2];
+ int bracesMatchStyle;
+ int highlightGuideColumn;
+ Selection sel;
+ bool primarySelection;
+
+ int foldFlags;
+ ContractionState cs;
+ // Hotspot support
+ Range hotspot;
+
+ // Wrapping support
+ int wrapWidth;
+
+ Document *pdoc;
+
+ EditModel();
+ ~EditModel();
+ virtual int TopLineOfMain() const = 0;
+ virtual Point GetVisibleOriginInMain() const = 0;
+ virtual int LinesOnScreen() const = 0;
+ virtual Range GetHotSpotRange() const = 0;
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/src/EditView.cxx b/src/EditView.cxx
new file mode 100644
index 000000000..26ede6cd9
--- /dev/null
+++ b/src/EditView.cxx
@@ -0,0 +1,1815 @@
+// Scintilla source code edit control
+/** @file Editor.cxx
+ ** Defines the appearance of the main text area of the editor window.
+ **/
+// Copyright 1998-2014 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <string>
+#include <vector>
+#include <map>
+#include <algorithm>
+#include <memory>
+
+#include "Platform.h"
+
+#include "ILexer.h"
+#include "Scintilla.h"
+
+#include "StringCopy.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "ContractionState.h"
+#include "CellBuffer.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "XPM.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+#include "CharClassify.h"
+#include "Decoration.h"
+#include "CaseFolder.h"
+#include "Document.h"
+#include "UniConversion.h"
+#include "Selection.h"
+#include "PositionCache.h"
+#include "EditModel.h"
+#include "MarginView.h"
+#include "EditView.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+static inline bool IsControlCharacter(int ch) {
+ // iscntrl returns true for lots of chars > 127 which are displayable
+ return ch >= 0 && ch < ' ';
+}
+
+PrintParameters::PrintParameters() {
+ magnification = 0;
+ colourMode = SC_PRINT_NORMAL;
+ wrapState = eWrapWord;
+}
+
+const XYPOSITION epsilon = 0.0001f; // A small nudge to avoid floating point precision issues
+
+EditView::EditView() {
+ hideSelection = false;
+ drawOverstrikeCaret = true;
+ bufferedDraw = true;
+ twoPhaseDraw = true;
+ lineWidthMaxSeen = 0;
+ additionalCaretsBlink = true;
+ additionalCaretsVisible = true;
+ pixmapLine = 0;
+ pixmapIndentGuide = 0;
+ pixmapIndentGuideHighlight = 0;
+ llc.SetLevel(LineLayoutCache::llcCaret);
+ posCache.SetSize(0x400);
+}
+
+void EditView::DropGraphics(bool freeObjects) {
+ if (freeObjects) {
+ delete pixmapLine;
+ pixmapLine = 0;
+ delete pixmapIndentGuide;
+ pixmapIndentGuide = 0;
+ delete pixmapIndentGuideHighlight;
+ pixmapIndentGuideHighlight = 0;
+ } else {
+ if (pixmapLine)
+ pixmapLine->Release();
+ if (pixmapIndentGuide)
+ pixmapIndentGuide->Release();
+ if (pixmapIndentGuideHighlight)
+ pixmapIndentGuideHighlight->Release();
+ }
+}
+
+void EditView::AllocateGraphics(const ViewStyle &vsDraw) {
+ if (!pixmapLine)
+ pixmapLine = Surface::Allocate(vsDraw.technology);
+ if (!pixmapIndentGuide)
+ pixmapIndentGuide = Surface::Allocate(vsDraw.technology);
+ if (!pixmapIndentGuideHighlight)
+ pixmapIndentGuideHighlight = Surface::Allocate(vsDraw.technology);
+}
+
+const char *ControlCharacterString(unsigned char ch) {
+ const char *reps[] = {
+ "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
+ "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
+ "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
+ "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
+ };
+ if (ch < ELEMENTS(reps)) {
+ return reps[ch];
+ } else {
+ return "BAD";
+ }
+}
+
+void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) {
+ int ydiff = static_cast<int>(rcTab.bottom - rcTab.top) / 2;
+ int xhead = static_cast<int>(rcTab.right) - 1 - ydiff;
+ if (xhead <= rcTab.left) {
+ ydiff -= static_cast<int>(rcTab.left) - xhead - 1;
+ xhead = static_cast<int>(rcTab.left) - 1;
+ }
+ if ((rcTab.left + 2) < (rcTab.right - 1))
+ surface->MoveTo(static_cast<int>(rcTab.left) + 2, ymid);
+ else
+ surface->MoveTo(static_cast<int>(rcTab.right) - 1, ymid);
+ surface->LineTo(static_cast<int>(rcTab.right) - 1, ymid);
+ surface->LineTo(xhead, ymid - ydiff);
+ surface->MoveTo(static_cast<int>(rcTab.right) - 1, ymid);
+ surface->LineTo(xhead, ymid + ydiff);
+}
+
+void EditView::RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw) {
+ if (!pixmapIndentGuide->Initialised()) {
+ // 1 extra pixel in height so can handle odd/even positions and so produce a continuous line
+ pixmapIndentGuide->InitPixMap(1, vsDraw.lineHeight + 1, surfaceWindow, wid);
+ pixmapIndentGuideHighlight->InitPixMap(1, vsDraw.lineHeight + 1, surfaceWindow, wid);
+ PRectangle rcIG = PRectangle::FromInts(0, 0, 1, vsDraw.lineHeight);
+ pixmapIndentGuide->FillRectangle(rcIG, vsDraw.styles[STYLE_INDENTGUIDE].back);
+ pixmapIndentGuide->PenColour(vsDraw.styles[STYLE_INDENTGUIDE].fore);
+ pixmapIndentGuideHighlight->FillRectangle(rcIG, vsDraw.styles[STYLE_BRACELIGHT].back);
+ pixmapIndentGuideHighlight->PenColour(vsDraw.styles[STYLE_BRACELIGHT].fore);
+ for (int stripe = 1; stripe < vsDraw.lineHeight + 1; stripe += 2) {
+ PRectangle rcPixel = PRectangle::FromInts(0, stripe, 1, stripe + 1);
+ pixmapIndentGuide->FillRectangle(rcPixel, vsDraw.styles[STYLE_INDENTGUIDE].fore);
+ pixmapIndentGuideHighlight->FillRectangle(rcPixel, vsDraw.styles[STYLE_BRACELIGHT].fore);
+ }
+ }
+}
+
+LineLayout *EditView::RetrieveLineLayout(int lineNumber, const EditModel &model) {
+ int posLineStart = model.pdoc->LineStart(lineNumber);
+ int posLineEnd = model.pdoc->LineStart(lineNumber + 1);
+ PLATFORM_ASSERT(posLineEnd >= posLineStart);
+ int lineCaret = model.pdoc->LineFromPosition(model.sel.MainCaret());
+ return llc.Retrieve(lineNumber, lineCaret,
+ posLineEnd - posLineStart, model.pdoc->GetStyleClock(),
+ model.LinesOnScreen() + 1, model.pdoc->LinesTotal());
+}
+
+/**
+* Fill in the LineLayout data for the given line.
+* Copy the given @a line and its styles from the document into local arrays.
+* Also determine the x position at which each character starts.
+*/
+void EditView::LayoutLine(int line, Surface *surface, const ViewStyle &vstyle, LineLayout *ll, const EditModel &model, int width) {
+ if (!ll)
+ return;
+
+ PLATFORM_ASSERT(line < model.pdoc->LinesTotal());
+ PLATFORM_ASSERT(ll->chars != NULL);
+ int posLineStart = model.pdoc->LineStart(line);
+ int posLineEnd = model.pdoc->LineStart(line + 1);
+ // If the line is very long, limit the treatment to a length that should fit in the viewport
+ if (posLineEnd >(posLineStart + ll->maxLineLength)) {
+ posLineEnd = posLineStart + ll->maxLineLength;
+ }
+ if (ll->validity == LineLayout::llCheckTextAndStyle) {
+ int lineLength = posLineEnd - posLineStart;
+ if (!vstyle.viewEOL) {
+ lineLength = model.pdoc->LineEnd(line) - posLineStart;
+ }
+ if (lineLength == ll->numCharsInLine) {
+ // See if chars, styles, indicators, are all the same
+ bool allSame = true;
+ // Check base line layout
+ char styleByte = 0;
+ int numCharsInLine = 0;
+ while (numCharsInLine < lineLength) {
+ int charInDoc = numCharsInLine + posLineStart;
+ char chDoc = model.pdoc->CharAt(charInDoc);
+ styleByte = model.pdoc->StyleAt(charInDoc);
+ allSame = allSame &&
+ (ll->styles[numCharsInLine] == static_cast<unsigned char>(styleByte));
+ if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseMixed)
+ allSame = allSame &&
+ (ll->chars[numCharsInLine] == chDoc);
+ else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower)
+ allSame = allSame &&
+ (ll->chars[numCharsInLine] == static_cast<char>(tolower(chDoc)));
+ else // Style::caseUpper
+ allSame = allSame &&
+ (ll->chars[numCharsInLine] == static_cast<char>(toupper(chDoc)));
+ numCharsInLine++;
+ }
+ allSame = allSame && (ll->styles[numCharsInLine] == styleByte); // For eolFilled
+ if (allSame) {
+ ll->validity = LineLayout::llPositions;
+ } else {
+ ll->validity = LineLayout::llInvalid;
+ }
+ } else {
+ ll->validity = LineLayout::llInvalid;
+ }
+ }
+ if (ll->validity == LineLayout::llInvalid) {
+ ll->widthLine = LineLayout::wrapWidthInfinite;
+ ll->lines = 1;
+ if (vstyle.edgeState == EDGE_BACKGROUND) {
+ ll->edgeColumn = model.pdoc->FindColumn(line, vstyle.theEdge);
+ if (ll->edgeColumn >= posLineStart) {
+ ll->edgeColumn -= posLineStart;
+ }
+ } else {
+ ll->edgeColumn = -1;
+ }
+
+ // Fill base line layout
+ const int lineLength = posLineEnd - posLineStart;
+ model.pdoc->GetCharRange(ll->chars, posLineStart, lineLength);
+ model.pdoc->GetStyleRange(ll->styles, posLineStart, lineLength);
+ int numCharsBeforeEOL = model.pdoc->LineEnd(line) - posLineStart;
+ const int numCharsInLine = (vstyle.viewEOL) ? lineLength : numCharsBeforeEOL;
+ for (int styleInLine = 0; styleInLine < numCharsInLine; styleInLine++) {
+ const unsigned char styleByte = ll->styles[styleInLine];
+ ll->styles[styleInLine] = styleByte;
+ }
+ const unsigned char styleByteLast = (lineLength > 0) ? ll->styles[lineLength - 1] : 0;
+ if (vstyle.someStylesForceCase) {
+ for (int charInLine = 0; charInLine<lineLength; charInLine++) {
+ char chDoc = ll->chars[charInLine];
+ if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseUpper)
+ ll->chars[charInLine] = static_cast<char>(toupper(chDoc));
+ else if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseLower)
+ ll->chars[charInLine] = static_cast<char>(tolower(chDoc));
+ }
+ }
+ ll->xHighlightGuide = 0;
+ // Extra element at the end of the line to hold end x position and act as
+ ll->chars[numCharsInLine] = 0; // Also triggers processing in the loops as this is a control character
+ ll->styles[numCharsInLine] = styleByteLast; // For eolFilled
+
+ // Layout the line, determining the position of each character,
+ // with an extra element at the end for the end of the line.
+ ll->positions[0] = 0;
+ bool lastSegItalics = false;
+
+ BreakFinder bfLayout(ll, NULL, Range(0, numCharsInLine), posLineStart, 0, false, model.pdoc, &model.reprs);
+ while (bfLayout.More()) {
+
+ const TextSegment ts = bfLayout.Next();
+
+ std::fill(&ll->positions[ts.start + 1], &ll->positions[ts.end() + 1], 0.0f);
+ if (vstyle.styles[ll->styles[ts.start]].visible) {
+ if (ts.representation) {
+ XYPOSITION representationWidth = vstyle.controlCharWidth;
+ if (ll->chars[ts.start] == '\t') {
+ // Tab is a special case of representation, taking a variable amount of space
+ representationWidth =
+ ((static_cast<int>((ll->positions[ts.start] + 2) / vstyle.tabWidth) + 1) * vstyle.tabWidth) - ll->positions[ts.start];
+ } else {
+ if (representationWidth <= 0.0) {
+ XYPOSITION positionsRepr[256]; // Should expand when needed
+ posCache.MeasureWidths(surface, vstyle, STYLE_CONTROLCHAR, ts.representation->stringRep.c_str(),
+ static_cast<unsigned int>(ts.representation->stringRep.length()), positionsRepr, model.pdoc);
+ representationWidth = positionsRepr[ts.representation->stringRep.length() - 1] + vstyle.ctrlCharPadding;
+ }
+ }
+ for (int ii = 0; ii < ts.length; ii++)
+ ll->positions[ts.start + 1 + ii] = representationWidth;
+ } else {
+ if ((ts.length == 1) && (' ' == ll->chars[ts.start])) {
+ // Over half the segments are single characters and of these about half are space characters.
+ ll->positions[ts.start + 1] = vstyle.styles[ll->styles[ts.start]].spaceWidth;
+ } else {
+ posCache.MeasureWidths(surface, vstyle, ll->styles[ts.start], ll->chars + ts.start,
+ ts.length, ll->positions + ts.start + 1, model.pdoc);
+ }
+ }
+ lastSegItalics = (!ts.representation) && ((ll->chars[ts.end() - 1] != ' ') && vstyle.styles[ll->styles[ts.start]].italic);
+ }
+
+ for (int posToIncrease = ts.start + 1; posToIncrease <= ts.end(); posToIncrease++) {
+ ll->positions[posToIncrease] += ll->positions[ts.start];
+ }
+ }
+
+ // Small hack to make lines that end with italics not cut off the edge of the last character
+ if (lastSegItalics) {
+ ll->positions[numCharsInLine] += vstyle.lastSegItalicsOffset;
+ }
+ ll->numCharsInLine = numCharsInLine;
+ ll->numCharsBeforeEOL = numCharsBeforeEOL;
+ ll->validity = LineLayout::llPositions;
+ }
+ // Hard to cope when too narrow, so just assume there is space
+ if (width < 20) {
+ width = 20;
+ }
+ if ((ll->validity == LineLayout::llPositions) || (ll->widthLine != width)) {
+ ll->widthLine = width;
+ if (width == LineLayout::wrapWidthInfinite) {
+ ll->lines = 1;
+ } else if (width > ll->positions[ll->numCharsInLine]) {
+ // Simple common case where line does not need wrapping.
+ ll->lines = 1;
+ } else {
+ if (vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_END) {
+ width -= static_cast<int>(vstyle.aveCharWidth); // take into account the space for end wrap mark
+ }
+ XYPOSITION wrapAddIndent = 0; // This will be added to initial indent of line
+ if (vstyle.wrapIndentMode == SC_WRAPINDENT_INDENT) {
+ wrapAddIndent = model.pdoc->IndentSize() * vstyle.spaceWidth;
+ } else if (vstyle.wrapIndentMode == SC_WRAPINDENT_FIXED) {
+ wrapAddIndent = vstyle.wrapVisualStartIndent * vstyle.aveCharWidth;
+ }
+ ll->wrapIndent = wrapAddIndent;
+ if (vstyle.wrapIndentMode != SC_WRAPINDENT_FIXED)
+ for (int i = 0; i < ll->numCharsInLine; i++) {
+ if (!IsSpaceOrTab(ll->chars[i])) {
+ ll->wrapIndent += ll->positions[i]; // Add line indent
+ break;
+ }
+ }
+ // Check for text width minimum
+ if (ll->wrapIndent > width - static_cast<int>(vstyle.aveCharWidth) * 15)
+ ll->wrapIndent = wrapAddIndent;
+ // Check for wrapIndent minimum
+ if ((vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_START) && (ll->wrapIndent < vstyle.aveCharWidth))
+ ll->wrapIndent = vstyle.aveCharWidth; // Indent to show start visual
+ ll->lines = 0;
+ // Calculate line start positions based upon width.
+ int lastGoodBreak = 0;
+ int lastLineStart = 0;
+ XYACCUMULATOR startOffset = 0;
+ int p = 0;
+ while (p < ll->numCharsInLine) {
+ if ((ll->positions[p + 1] - startOffset) >= width) {
+ if (lastGoodBreak == lastLineStart) {
+ // Try moving to start of last character
+ if (p > 0) {
+ lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1)
+ - posLineStart;
+ }
+ if (lastGoodBreak == lastLineStart) {
+ // Ensure at least one character on line.
+ lastGoodBreak = model.pdoc->MovePositionOutsideChar(lastGoodBreak + posLineStart + 1, 1)
+ - posLineStart;
+ }
+ }
+ lastLineStart = lastGoodBreak;
+ ll->lines++;
+ ll->SetLineStart(ll->lines, lastGoodBreak);
+ startOffset = ll->positions[lastGoodBreak];
+ // take into account the space for start wrap mark and indent
+ startOffset -= ll->wrapIndent;
+ p = lastGoodBreak + 1;
+ continue;
+ }
+ if (p > 0) {
+ if (vstyle.wrapState == eWrapChar) {
+ lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1)
+ - posLineStart;
+ p = model.pdoc->MovePositionOutsideChar(p + 1 + posLineStart, 1) - posLineStart;
+ continue;
+ } else if ((vstyle.wrapState == eWrapWord) && (ll->styles[p] != ll->styles[p - 1])) {
+ lastGoodBreak = p;
+ } else if (IsSpaceOrTab(ll->chars[p - 1]) && !IsSpaceOrTab(ll->chars[p])) {
+ lastGoodBreak = p;
+ }
+ }
+ p++;
+ }
+ ll->lines++;
+ }
+ ll->validity = LineLayout::llLines;
+ }
+}
+
+Point EditView::LocationFromPosition(Surface *surface, SelectionPosition pos, int topLine, const EditModel &model, const ViewStyle &vs) {
+ Point pt;
+ if (pos.Position() == INVALID_POSITION)
+ return pt;
+ const int line = model.pdoc->LineFromPosition(pos.Position());
+ const int lineVisible = model.cs.DisplayFromDoc(line);
+ //Platform::DebugPrintf("line=%d\n", line);
+ AutoLineLayout ll(llc, RetrieveLineLayout(line, model));
+ if (surface && ll) {
+ const int posLineStart = model.pdoc->LineStart(line);
+ LayoutLine(line, surface, vs, ll, model, model.wrapWidth);
+ const int posInLine = pos.Position() - posLineStart;
+ pt = ll->PointFromPosition(posInLine, vs.lineHeight);
+ pt.y += (lineVisible - topLine) * vs.lineHeight;
+ pt.x += vs.textStart - model.xOffset;
+ }
+ pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth;
+ return pt;
+}
+
+SelectionPosition EditView::SPositionFromLocation(Surface *surface, Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace, const EditModel &model, const ViewStyle &vs) {
+ pt.x = pt.x - vs.textStart;
+ int visibleLine = static_cast<int>(floor(pt.y / vs.lineHeight));
+ if (!canReturnInvalid && (visibleLine < 0))
+ visibleLine = 0;
+ const int lineDoc = model.cs.DocFromDisplay(visibleLine);
+ if (canReturnInvalid && (lineDoc < 0))
+ return SelectionPosition(INVALID_POSITION);
+ if (lineDoc >= model.pdoc->LinesTotal())
+ return SelectionPosition(canReturnInvalid ? INVALID_POSITION : model.pdoc->Length());
+ const int posLineStart = model.pdoc->LineStart(lineDoc);
+ AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model));
+ if (surface && ll) {
+ LayoutLine(lineDoc, surface, vs, ll, model, model.wrapWidth);
+ const int lineStartSet = model.cs.DisplayFromDoc(lineDoc);
+ const int subLine = visibleLine - lineStartSet;
+ if (subLine < ll->lines) {
+ const Range rangeSubLine = ll->SubLineRange(subLine);
+ const XYPOSITION subLineStart = ll->positions[rangeSubLine.start];
+ if (subLine > 0) // Wrapped
+ pt.x -= ll->wrapIndent;
+ const int positionInLine = ll->FindPositionFromX(pt.x + subLineStart, rangeSubLine, charPosition);
+ if (positionInLine < rangeSubLine.end) {
+ return SelectionPosition(model.pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1));
+ }
+ if (virtualSpace) {
+ const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth;
+ const int spaceOffset = static_cast<int>(
+ (pt.x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth);
+ return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset);
+ } else if (canReturnInvalid) {
+ if (pt.x < (ll->positions[rangeSubLine.end] - subLineStart)) {
+ return SelectionPosition(model.pdoc->MovePositionOutsideChar(rangeSubLine.end + posLineStart, 1));
+ }
+ } else {
+ return SelectionPosition(rangeSubLine.end + posLineStart);
+ }
+ }
+ if (!canReturnInvalid)
+ return SelectionPosition(ll->numCharsInLine + posLineStart);
+ }
+ return SelectionPosition(canReturnInvalid ? INVALID_POSITION : posLineStart);
+}
+
+/**
+* Find the document position corresponding to an x coordinate on a particular document line.
+* Ensure is between whole characters when document is in multi-byte or UTF-8 mode.
+* This method is used for rectangular selections and does not work on wrapped lines.
+*/
+SelectionPosition EditView::SPositionFromLineX(Surface *surface, int lineDoc, int x, const EditModel &model, const ViewStyle &vs) {
+ AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model));
+ if (surface && ll) {
+ const int posLineStart = model.pdoc->LineStart(lineDoc);
+ LayoutLine(lineDoc, surface, vs, ll, model, model.wrapWidth);
+ const Range rangeSubLine = ll->SubLineRange(0);
+ const XYPOSITION subLineStart = ll->positions[rangeSubLine.start];
+ const int positionInLine = ll->FindPositionFromX(x + subLineStart, rangeSubLine, false);
+ if (positionInLine < rangeSubLine.end) {
+ return SelectionPosition(model.pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1));
+ }
+ const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth;
+ const int spaceOffset = static_cast<int>(
+ (x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth);
+ return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset);
+ }
+ return SelectionPosition(0);
+}
+
+int EditView::DisplayFromPosition(Surface *surface, int pos, const EditModel &model, const ViewStyle &vs) {
+ int lineDoc = model.pdoc->LineFromPosition(pos);
+ int lineDisplay = model.cs.DisplayFromDoc(lineDoc);
+ AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model));
+ if (surface && ll) {
+ LayoutLine(lineDoc, surface, vs, ll, model, model.wrapWidth);
+ unsigned int posLineStart = model.pdoc->LineStart(lineDoc);
+ int posInLine = pos - posLineStart;
+ lineDisplay--; // To make up for first increment ahead.
+ for (int subLine = 0; subLine < ll->lines; subLine++) {
+ if (posInLine >= ll->LineStart(subLine)) {
+ lineDisplay++;
+ }
+ }
+ }
+ return lineDisplay;
+}
+
+int EditView::StartEndDisplayLine(Surface *surface, int pos, bool start, const EditModel &model, const ViewStyle &vs) {
+ int line = model.pdoc->LineFromPosition(pos);
+ AutoLineLayout ll(llc, RetrieveLineLayout(line, model));
+ int posRet = INVALID_POSITION;
+ if (surface && ll) {
+ unsigned int posLineStart = model.pdoc->LineStart(line);
+ LayoutLine(line, surface, vs, ll, model, model.wrapWidth);
+ int posInLine = pos - posLineStart;
+ if (posInLine <= ll->maxLineLength) {
+ for (int subLine = 0; subLine < ll->lines; subLine++) {
+ if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) {
+ if (start) {
+ posRet = ll->LineStart(subLine) + posLineStart;
+ } else {
+ if (subLine == ll->lines - 1)
+ posRet = ll->LineStart(subLine + 1) + posLineStart;
+ else
+ posRet = ll->LineStart(subLine + 1) + posLineStart - 1;
+ }
+ }
+ }
+ }
+ }
+ return posRet;
+}
+
+static ColourDesired SelectionBackground(const ViewStyle &vsDraw, bool main, bool primarySelection) {
+ return main ?
+ (primarySelection ? vsDraw.selColours.back : vsDraw.selBackground2) :
+ vsDraw.selAdditionalBackground;
+}
+
+static ColourDesired TextBackground(const ViewStyle &vsDraw,
+ ColourOptional background, int inSelection, bool inHotspot, int styleMain, int i,
+ LineLayout *ll, const EditModel &model) {
+ if (inSelection == 1) {
+ if (vsDraw.selColours.back.isSet && (vsDraw.selAlpha == SC_ALPHA_NOALPHA)) {
+ return SelectionBackground(vsDraw, true, model.primarySelection);
+ }
+ } else if (inSelection == 2) {
+ if (vsDraw.selColours.back.isSet && (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA)) {
+ return SelectionBackground(vsDraw, false, model.primarySelection);
+ }
+ } else {
+ if ((vsDraw.edgeState == EDGE_BACKGROUND) &&
+ (i >= ll->edgeColumn) &&
+ (i < ll->numCharsBeforeEOL))
+ return vsDraw.edgecolour;
+ if (inHotspot && vsDraw.hotspotColours.back.isSet)
+ return vsDraw.hotspotColours.back;
+ }
+ if (background.isSet && (styleMain != STYLE_BRACELIGHT) && (styleMain != STYLE_BRACEBAD)) {
+ return background;
+ } else {
+ return vsDraw.styles[styleMain].back;
+ }
+}
+
+void EditView::DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight) {
+ Point from = Point::FromInts(0, ((lineVisible & 1) && (lineHeight & 1)) ? 1 : 0);
+ PRectangle rcCopyArea = PRectangle::FromInts(start + 1, static_cast<int>(rcSegment.top), start + 2, static_cast<int>(rcSegment.bottom));
+ surface->Copy(rcCopyArea, from,
+ highlight ? *pixmapIndentGuideHighlight : *pixmapIndentGuide);
+}
+
+static void SimpleAlphaRectangle(Surface *surface, PRectangle rc, ColourDesired fill, int alpha) {
+ if (alpha != SC_ALPHA_NOALPHA) {
+ surface->AlphaRectangle(rc, 0, fill, alpha, fill, alpha, 0);
+ }
+}
+
+void DrawTextBlob(Surface *surface, const ViewStyle &vsDraw, PRectangle rcSegment,
+ const char *s, ColourDesired textBack, ColourDesired textFore, bool twoPhaseDraw) {
+ if (!twoPhaseDraw) {
+ surface->FillRectangle(rcSegment, textBack);
+ }
+ FontAlias ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;
+ int normalCharHeight = static_cast<int>(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, static_cast<int>(s ? strlen(s) : 0),
+ textBack, textFore);
+}
+
+void EditView::DrawEOL(Surface *surface, const ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll,
+ int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart,
+ ColourOptional background, const EditModel &model) {
+
+ const int posLineStart = model.pdoc->LineStart(line);
+ PRectangle rcSegment = rcLine;
+
+ const bool lastSubLine = subLine == (ll->lines - 1);
+ XYPOSITION virtualSpace = 0;
+ if (lastSubLine) {
+ const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
+ virtualSpace = model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line)) * spaceWidth;
+ }
+ XYPOSITION xEol = static_cast<XYPOSITION>(ll->positions[lineEnd] - subLineStart);
+
+ // Fill the virtual space and show selections within it
+ if (virtualSpace) {
+ rcSegment.left = xEol + xStart;
+ rcSegment.right = xEol + xStart + virtualSpace;
+ surface->FillRectangle(rcSegment, background.isSet ? background : vsDraw.styles[ll->styles[ll->numCharsInLine]].back);
+ if (!hideSelection && ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA))) {
+ SelectionSegment virtualSpaceRange(SelectionPosition(model.pdoc->LineEnd(line)), SelectionPosition(model.pdoc->LineEnd(line), model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line))));
+ for (size_t r = 0; r<model.sel.Count(); r++) {
+ int alpha = (r == model.sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
+ if (alpha == SC_ALPHA_NOALPHA) {
+ SelectionSegment portion = model.sel.Range(r).Intersect(virtualSpaceRange);
+ if (!portion.Empty()) {
+ const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
+ rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] -
+ static_cast<XYPOSITION>(subLineStart)+portion.start.VirtualSpace() * spaceWidth;
+ rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] -
+ static_cast<XYPOSITION>(subLineStart)+portion.end.VirtualSpace() * spaceWidth;
+ rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left;
+ rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right;
+ surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, r == model.sel.Main(), model.primarySelection));
+ }
+ }
+ }
+ }
+ }
+
+ int eolInSelection = 0;
+ int alpha = SC_ALPHA_NOALPHA;
+ if (!hideSelection) {
+ int posAfterLineEnd = model.pdoc->LineStart(line + 1);
+ eolInSelection = (subLine == (ll->lines - 1)) ? model.sel.InSelectionForEOL(posAfterLineEnd) : 0;
+ alpha = (eolInSelection == 1) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
+ }
+
+ // Draw the [CR], [LF], or [CR][LF] blobs if visible line ends are on
+ XYPOSITION blobsWidth = 0;
+ if (lastSubLine) {
+ for (int eolPos = ll->numCharsBeforeEOL; eolPos<ll->numCharsInLine; eolPos++) {
+ rcSegment.left = xStart + ll->positions[eolPos] - static_cast<XYPOSITION>(subLineStart)+virtualSpace;
+ rcSegment.right = xStart + ll->positions[eolPos + 1] - static_cast<XYPOSITION>(subLineStart)+virtualSpace;
+ blobsWidth += rcSegment.Width();
+ char hexits[4];
+ const char *ctrlChar;
+ unsigned char chEOL = ll->chars[eolPos];
+ int styleMain = ll->styles[eolPos];
+ ColourDesired textBack = TextBackground(vsDraw, background, eolInSelection, false, styleMain, eolPos, ll, model);
+ if (UTF8IsAscii(chEOL)) {
+ ctrlChar = ControlCharacterString(chEOL);
+ } else {
+ const Representation *repr = model.reprs.RepresentationFromCharacter(ll->chars + eolPos, ll->numCharsInLine - eolPos);
+ if (repr) {
+ ctrlChar = repr->stringRep.c_str();
+ eolPos = ll->numCharsInLine;
+ } else {
+ sprintf(hexits, "x%2X", chEOL);
+ ctrlChar = hexits;
+ }
+ }
+ ColourDesired textFore = vsDraw.styles[styleMain].fore;
+ if (eolInSelection && vsDraw.selColours.fore.isSet) {
+ textFore = (eolInSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground;
+ }
+ if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1)) {
+ if (alpha == SC_ALPHA_NOALPHA) {
+ surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection));
+ } else {
+ surface->FillRectangle(rcSegment, textBack);
+ }
+ } else {
+ surface->FillRectangle(rcSegment, textBack);
+ }
+ DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, twoPhaseDraw);
+ if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
+ SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha);
+ }
+ }
+ }
+
+ // Draw the eol-is-selected rectangle
+ rcSegment.left = xEol + xStart + virtualSpace + blobsWidth;
+ rcSegment.right = rcSegment.left + vsDraw.aveCharWidth;
+
+ if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) {
+ surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection));
+ } else {
+ if (background.isSet) {
+ surface->FillRectangle(rcSegment, background);
+ } else if (line < model.pdoc->LinesTotal() - 1) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back);
+ } else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back);
+ } else {
+ surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back);
+ }
+ if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
+ SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha);
+ }
+ }
+
+ // Fill the remainder of the line
+ rcSegment.left = rcSegment.right;
+ if (rcSegment.left < rcLine.left)
+ rcSegment.left = rcLine.left;
+ rcSegment.right = rcLine.right;
+
+ if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) {
+ surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection));
+ } else {
+ if (background.isSet) {
+ surface->FillRectangle(rcSegment, background);
+ } else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back);
+ } else {
+ surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back);
+ }
+ if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
+ SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha);
+ }
+ }
+
+ bool drawWrapMarkEnd = false;
+
+ if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_END) {
+ if (subLine + 1 < ll->lines) {
+ drawWrapMarkEnd = ll->LineStart(subLine + 1) != 0;
+ }
+ }
+
+ if (drawWrapMarkEnd) {
+ PRectangle rcPlace = rcSegment;
+
+ if (vsDraw.wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_END_BY_TEXT) {
+ rcPlace.left = xEol + xStart + virtualSpace;
+ rcPlace.right = rcPlace.left + vsDraw.aveCharWidth;
+ } else {
+ // rcLine is clipped to text area
+ rcPlace.right = rcLine.right;
+ rcPlace.left = rcPlace.right - vsDraw.aveCharWidth;
+ }
+ DrawWrapMarker(surface, rcPlace, true, vsDraw.WrapColour());
+ }
+}
+
+static void DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, const ViewStyle &vsDraw,
+ int xStart, PRectangle rcLine, LineLayout *ll, int subLine) {
+ const XYPOSITION subLineStart = ll->positions[ll->LineStart(subLine)];
+ PRectangle rcIndic(
+ ll->positions[startPos] + xStart - subLineStart,
+ rcLine.top + vsDraw.maxAscent,
+ ll->positions[endPos] + xStart - subLineStart,
+ rcLine.top + vsDraw.maxAscent + 3);
+ vsDraw.indicators[indicNum].Draw(surface, rcIndic, rcLine);
+}
+
+static void DrawIndicators(Surface *surface, const ViewStyle &vsDraw, int line, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under, const EditModel &model) {
+ // Draw decorators
+ const int posLineStart = model.pdoc->LineStart(line);
+ const int lineStart = ll->LineStart(subLine);
+ const int posLineEnd = posLineStart + lineEnd;
+
+ for (Decoration *deco = model.pdoc->decorations.root; deco; deco = deco->next) {
+ if (under == vsDraw.indicators[deco->indicator].under) {
+ int startPos = posLineStart + lineStart;
+ if (!deco->rs.ValueAt(startPos)) {
+ startPos = deco->rs.EndRun(startPos);
+ }
+ while ((startPos < posLineEnd) && (deco->rs.ValueAt(startPos))) {
+ int endPos = deco->rs.EndRun(startPos);
+ if (endPos > posLineEnd)
+ endPos = posLineEnd;
+ DrawIndicator(deco->indicator, startPos - posLineStart, endPos - posLineStart,
+ surface, vsDraw, xStart, rcLine, ll, subLine);
+ startPos = endPos;
+ if (!deco->rs.ValueAt(startPos)) {
+ startPos = deco->rs.EndRun(startPos);
+ }
+ }
+ }
+ }
+
+ // Use indicators to highlight matching braces
+ if ((vsDraw.braceHighlightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACELIGHT)) ||
+ (vsDraw.braceBadLightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACEBAD))) {
+ int braceIndicator = (model.bracesMatchStyle == STYLE_BRACELIGHT) ? vsDraw.braceHighlightIndicator : vsDraw.braceBadLightIndicator;
+ if (under == vsDraw.indicators[braceIndicator].under) {
+ Range rangeLine(posLineStart + lineStart, posLineEnd);
+ if (rangeLine.ContainsCharacter(model.braces[0])) {
+ int braceOffset = model.braces[0] - posLineStart;
+ if (braceOffset < ll->numCharsInLine) {
+ DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine);
+ }
+ }
+ if (rangeLine.ContainsCharacter(model.braces[1])) {
+ int braceOffset = model.braces[1] - posLineStart;
+ if (braceOffset < ll->numCharsInLine) {
+ DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine);
+ }
+ }
+ }
+ }
+}
+
+void EditView::DrawAnnotation(Surface *surface, const ViewStyle &vsDraw, int line, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model) {
+ int indent = static_cast<int>(model.pdoc->GetLineIndentation(line) * vsDraw.spaceWidth);
+ PRectangle rcSegment = rcLine;
+ int annotationLine = subLine - ll->lines;
+ const StyledText stAnnotation = model.pdoc->AnnotationStyledText(line);
+ if (stAnnotation.text && ValidStyledText(vsDraw, vsDraw.annotationStyleOffset, stAnnotation)) {
+ surface->FillRectangle(rcSegment, vsDraw.styles[0].back);
+ rcSegment.left = static_cast<XYPOSITION>(xStart);
+ if (model.trackLineWidth || (vsDraw.annotationVisible == ANNOTATION_BOXED)) {
+ // Only care about calculating width if tracking or need to draw box
+ int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation);
+ if (vsDraw.annotationVisible == ANNOTATION_BOXED) {
+ widthAnnotation += static_cast<int>(vsDraw.spaceWidth * 2); // Margins
+ }
+ if (widthAnnotation > lineWidthMaxSeen)
+ lineWidthMaxSeen = widthAnnotation;
+ if (vsDraw.annotationVisible == ANNOTATION_BOXED) {
+ rcSegment.left = static_cast<XYPOSITION>(xStart + indent);
+ rcSegment.right = rcSegment.left + widthAnnotation;
+ }
+ }
+ const int annotationLines = model.pdoc->AnnotationLines(line);
+ size_t start = 0;
+ size_t lengthAnnotation = stAnnotation.LineLength(start);
+ int lineInAnnotation = 0;
+ while ((lineInAnnotation < annotationLine) && (start < stAnnotation.length)) {
+ start += lengthAnnotation + 1;
+ lengthAnnotation = stAnnotation.LineLength(start);
+ lineInAnnotation++;
+ }
+ PRectangle rcText = rcSegment;
+ if (vsDraw.annotationVisible == ANNOTATION_BOXED) {
+ surface->FillRectangle(rcText,
+ vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back);
+ rcText.left += vsDraw.spaceWidth;
+ }
+ DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText,
+ stAnnotation, start, lengthAnnotation);
+ if (vsDraw.annotationVisible == ANNOTATION_BOXED) {
+ surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore);
+ surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.top));
+ surface->LineTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.bottom));
+ surface->MoveTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.top));
+ surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.bottom));
+ if (subLine == ll->lines) {
+ surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.top));
+ surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.top));
+ }
+ if (subLine == ll->lines + annotationLines - 1) {
+ surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.bottom - 1));
+ surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.bottom - 1));
+ }
+ }
+ }
+}
+
+static void DrawBlockCaret(Surface *surface, const ViewStyle &vsDraw, LineLayout *ll, int subLine,
+ int xStart, int offset, int posCaret, PRectangle rcCaret, ColourDesired caretColour, const EditModel &model) {
+
+ int lineStart = ll->LineStart(subLine);
+ int posBefore = posCaret;
+ int posAfter = model.pdoc->MovePositionOutsideChar(posCaret + 1, 1);
+ int numCharsToDraw = posAfter - posCaret;
+
+ // Work out where the starting and ending offsets are. We need to
+ // see if the previous character shares horizontal space, such as a
+ // glyph / combining character. If so we'll need to draw that too.
+ int offsetFirstChar = offset;
+ int offsetLastChar = offset + (posAfter - posCaret);
+ while ((posBefore > 0) && ((offsetLastChar - numCharsToDraw) >= lineStart)) {
+ if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - numCharsToDraw]) > 0) {
+ // The char does not share horizontal space
+ break;
+ }
+ // Char shares horizontal space, update the numChars to draw
+ // Update posBefore to point to the prev char
+ posBefore = model.pdoc->MovePositionOutsideChar(posBefore - 1, -1);
+ numCharsToDraw = posAfter - posBefore;
+ offsetFirstChar = offset - (posCaret - posBefore);
+ }
+
+ // See if the next character shares horizontal space, if so we'll
+ // need to draw that too.
+ if (offsetFirstChar < 0)
+ offsetFirstChar = 0;
+ numCharsToDraw = offsetLastChar - offsetFirstChar;
+ while ((offsetLastChar < ll->LineStart(subLine + 1)) && (offsetLastChar <= ll->numCharsInLine)) {
+ // Update posAfter to point to the 2nd next char, this is where
+ // the next character ends, and 2nd next begins. We'll need
+ // to compare these two
+ posBefore = posAfter;
+ posAfter = model.pdoc->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
+ break;
+ }
+ // Char shares horizontal space, update the numChars to draw
+ numCharsToDraw = offsetLastChar - offsetFirstChar;
+ }
+
+ // We now know what to draw, update the caret drawing rectangle
+ rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[lineStart] + xStart;
+ rcCaret.right = ll->positions[offsetFirstChar + numCharsToDraw] - ll->positions[lineStart] + xStart;
+
+ // Adjust caret position to take into account any word wrapping symbols.
+ if ((ll->wrapIndent != 0) && (lineStart != 0)) {
+ XYPOSITION wordWrapCharWidth = ll->wrapIndent;
+ rcCaret.left += wordWrapCharWidth;
+ rcCaret.right += wordWrapCharWidth;
+ }
+
+ // This character is where the caret block is, we override the colours
+ // (inversed) for drawing the caret here.
+ int styleMain = ll->styles[offsetFirstChar];
+ FontAlias fontText = vsDraw.styles[styleMain].font;
+ surface->DrawTextClipped(rcCaret, fontText,
+ rcCaret.top + vsDraw.maxAscent, ll->chars + offsetFirstChar,
+ numCharsToDraw, vsDraw.styles[styleMain].back,
+ caretColour);
+}
+
+void EditView::DrawCarets(Surface *surface, const ViewStyle &vsDraw, int lineDoc, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model) const {
+ // When drag is active it is the only caret drawn
+ bool drawDrag = model.posDrag.IsValid();
+ if (hideSelection && !drawDrag)
+ return;
+ const int posLineStart = model.pdoc->LineStart(lineDoc);
+ // For each selection draw
+ for (size_t r = 0; (r<model.sel.Count()) || drawDrag; r++) {
+ const bool mainCaret = r == model.sel.Main();
+ const SelectionPosition posCaret = (drawDrag ? model.posDrag : model.sel.Range(r).caret);
+ const int offset = posCaret.Position() - posLineStart;
+ const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
+ const XYPOSITION virtualOffset = posCaret.VirtualSpace() * spaceWidth;
+ if (ll->InLine(offset, subLine) && offset <= ll->numCharsBeforeEOL) {
+ XYPOSITION xposCaret = ll->positions[offset] + virtualOffset - ll->positions[ll->LineStart(subLine)];
+ if (ll->wrapIndent != 0) {
+ int lineStart = ll->LineStart(subLine);
+ if (lineStart != 0) // Wrapped
+ xposCaret += ll->wrapIndent;
+ }
+ bool caretBlinkState = (model.caret.active && model.caret.on) || (!additionalCaretsBlink && !mainCaret);
+ bool caretVisibleState = additionalCaretsVisible || mainCaret;
+ if ((xposCaret >= 0) && (vsDraw.caretWidth > 0) && (vsDraw.caretStyle != CARETSTYLE_INVISIBLE) &&
+ ((model.posDrag.IsValid()) || (caretBlinkState && caretVisibleState))) {
+ bool caretAtEOF = false;
+ bool caretAtEOL = false;
+ bool drawBlockCaret = false;
+ XYPOSITION widthOverstrikeCaret;
+ XYPOSITION caretWidthOffset = 0;
+ PRectangle rcCaret = rcLine;
+
+ if (posCaret.Position() == model.pdoc->Length()) { // At end of document
+ caretAtEOF = true;
+ widthOverstrikeCaret = vsDraw.aveCharWidth;
+ } else if ((posCaret.Position() - posLineStart) >= ll->numCharsInLine) { // At end of line
+ caretAtEOL = true;
+ widthOverstrikeCaret = vsDraw.aveCharWidth;
+ } else {
+ widthOverstrikeCaret = ll->positions[offset + 1] - ll->positions[offset];
+ }
+ if (widthOverstrikeCaret < 3) // Make sure its visible
+ widthOverstrikeCaret = 3;
+
+ if (xposCaret > 0)
+ caretWidthOffset = 0.51f; // Move back so overlaps both character cells.
+ xposCaret += xStart;
+ if (model.posDrag.IsValid()) {
+ /* Dragging text, use a line caret */
+ rcCaret.left = static_cast<XYPOSITION>(RoundXYPosition(xposCaret - caretWidthOffset));
+ rcCaret.right = rcCaret.left + vsDraw.caretWidth;
+ } else if (model.inOverstrike && drawOverstrikeCaret) {
+ /* Overstrike (insert mode), use a modified bar caret */
+ rcCaret.top = rcCaret.bottom - 2;
+ rcCaret.left = xposCaret + 1;
+ rcCaret.right = rcCaret.left + widthOverstrikeCaret - 1;
+ } else if (vsDraw.caretStyle == CARETSTYLE_BLOCK) {
+ /* Block caret */
+ rcCaret.left = xposCaret;
+ if (!caretAtEOL && !caretAtEOF && (ll->chars[offset] != '\t') && !(IsControlCharacter(ll->chars[offset]))) {
+ drawBlockCaret = true;
+ rcCaret.right = xposCaret + widthOverstrikeCaret;
+ } else {
+ rcCaret.right = xposCaret + vsDraw.aveCharWidth;
+ }
+ } else {
+ /* Line caret */
+ rcCaret.left = static_cast<XYPOSITION>(RoundXYPosition(xposCaret - caretWidthOffset));
+ rcCaret.right = rcCaret.left + vsDraw.caretWidth;
+ }
+ ColourDesired caretColour = mainCaret ? vsDraw.caretcolour : vsDraw.additionalCaretColour;
+ if (drawBlockCaret) {
+ DrawBlockCaret(surface, vsDraw, ll, subLine, xStart, offset, posCaret.Position(), rcCaret, caretColour, model);
+ } else {
+ surface->FillRectangle(rcCaret, caretColour);
+ }
+ }
+ }
+ if (drawDrag)
+ break;
+ }
+}
+
+void EditView::DrawLine(Surface *surface, const ViewStyle &vsDraw, int line, int lineVisible, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model) {
+
+ if (subLine >= ll->lines) {
+ DrawAnnotation(surface, vsDraw, line, xStart, rcLine, ll, subLine, model);
+ return; // No further drawing
+ }
+
+ // Using one font for all control characters so it can be controlled independently to ensure
+ // the box goes around the characters tightly. Seems to be no way to work out what height
+ // is taken by an individual character - internal leading gives varying results.
+ FontAlias ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;
+
+ // See if something overrides the line background color.
+ const ColourOptional background = vsDraw.Background(model.pdoc->GetMark(line), model.caret.active, ll->containsCaret);
+
+ const bool drawWhitespaceBackground = (vsDraw.viewWhitespace != wsInvisible) &&
+ (!background.isSet) && (vsDraw.whitespaceColours.back.isSet);
+
+ const XYPOSITION indentWidth = model.pdoc->IndentSize() * vsDraw.spaceWidth;
+
+ const int posLineStart = model.pdoc->LineStart(line);
+
+ const Range lineRange = ll->SubLineRange(subLine);
+ const XYACCUMULATOR subLineStart = ll->positions[lineRange.start];
+
+ if ((ll->wrapIndent != 0) && (subLine > 0) && (subLine < ll->lines)) {
+ // default bgnd here..
+ surface->FillRectangle(rcLine, background.isSet ? background :
+ vsDraw.styles[STYLE_DEFAULT].back);
+
+ if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_START) {
+
+ // draw continuation rect
+ PRectangle rcPlace = rcLine;
+
+ rcPlace.left = static_cast<XYPOSITION>(xStart);
+ rcPlace.right = rcPlace.left + ll->wrapIndent;
+
+ if (vsDraw.wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_START_BY_TEXT)
+ rcPlace.left = rcPlace.right - vsDraw.aveCharWidth;
+ else
+ rcPlace.right = rcPlace.left + vsDraw.aveCharWidth;
+
+ DrawWrapMarker(surface, rcPlace, false, vsDraw.WrapColour());
+ }
+
+ xStart += static_cast<int>(ll->wrapIndent);
+ }
+
+ const bool selBackDrawn = vsDraw.selColours.back.isSet &&
+ ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA));
+
+ // Does not take margin into account but not significant
+ const int xStartVisible = static_cast<int>(subLineStart)-xStart;
+
+ if (twoPhaseDraw) {
+ bool inIndentation = subLine == 0; // Do not handle indentation except on first subline.
+ BreakFinder bfBack(ll, &model.sel, lineRange, posLineStart, xStartVisible, selBackDrawn, model.pdoc, &model.reprs);
+
+ // Background drawing loop
+ while (bfBack.More()) {
+
+ const TextSegment ts = bfBack.Next();
+ const int i = ts.end() - 1;
+ const int iDoc = i + posLineStart;
+
+ PRectangle rcSegment = rcLine;
+ rcSegment.left = ll->positions[ts.start] + xStart - static_cast<XYPOSITION>(subLineStart);
+ rcSegment.right = ll->positions[ts.end()] + xStart - static_cast<XYPOSITION>(subLineStart);
+ // Only try to draw if really visible - enhances performance by not calling environment to
+ // draw strings that are completely past the right side of the window.
+ if (rcSegment.Intersects(rcLine)) {
+ // Clip to line rectangle, since may have a huge position which will not work with some platforms
+ if (rcSegment.left < rcLine.left)
+ rcSegment.left = rcLine.left;
+ if (rcSegment.right > rcLine.right)
+ rcSegment.right = rcLine.right;
+
+ const int inSelection = hideSelection ? 0 : model.sel.CharacterInSelection(iDoc);
+ const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc);
+ ColourDesired textBack = TextBackground(vsDraw, background, inSelection,
+ inHotspot, ll->styles[i], i, ll, model);
+ if (ts.representation) {
+ if (ll->chars[i] == '\t') {
+ // Tab display
+ if (drawWhitespaceBackground &&
+ (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways))
+ textBack = vsDraw.whitespaceColours.back;
+ } else {
+ // Blob display
+ inIndentation = false;
+ }
+ surface->FillRectangle(rcSegment, textBack);
+ } else {
+ // Normal text display
+ surface->FillRectangle(rcSegment, textBack);
+ if (vsDraw.viewWhitespace != wsInvisible ||
+ (inIndentation && vsDraw.viewIndentationGuides == ivReal)) {
+ for (int cpos = 0; cpos <= i - ts.start; cpos++) {
+ if (ll->chars[cpos + ts.start] == ' ') {
+ if (drawWhitespaceBackground &&
+ (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {
+ PRectangle rcSpace(
+ ll->positions[cpos + ts.start] + xStart - static_cast<XYPOSITION>(subLineStart),
+ rcSegment.top,
+ ll->positions[cpos + ts.start + 1] + xStart - static_cast<XYPOSITION>(subLineStart),
+ rcSegment.bottom);
+ surface->FillRectangle(rcSpace, vsDraw.whitespaceColours.back);
+ }
+ } else {
+ inIndentation = false;
+ }
+ }
+ }
+ }
+ } else if (rcSegment.left > rcLine.right) {
+ break;
+ }
+ }
+
+ DrawEOL(surface, vsDraw, rcLine, ll, line, lineRange.end,
+ xStart, subLine, subLineStart, background, model);
+ }
+
+ DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineRange.end, true, model);
+
+ if (vsDraw.edgeState == EDGE_LINE) {
+ PRectangle rcSegment = rcLine;
+ int edgeX = static_cast<int>(vsDraw.theEdge * vsDraw.spaceWidth);
+ rcSegment.left = static_cast<XYPOSITION>(edgeX + xStart);
+ if ((ll->wrapIndent != 0) && (lineRange.start != 0))
+ rcSegment.left -= ll->wrapIndent;
+ rcSegment.right = rcSegment.left + 1;
+ surface->FillRectangle(rcSegment, vsDraw.edgecolour);
+ }
+
+ // Draw underline mark as part of background if not transparent
+ int marks = model.pdoc->GetMark(line);
+ int markBit;
+ for (markBit = 0; (markBit < 32) && marks; markBit++) {
+ if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE) &&
+ (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
+ PRectangle rcUnderline = rcLine;
+ rcUnderline.top = rcUnderline.bottom - 2;
+ surface->FillRectangle(rcUnderline, vsDraw.markers[markBit].back);
+ }
+ marks >>= 1;
+ }
+
+ bool inIndentation = subLine == 0; // Do not handle indentation except on first subline.
+ // Foreground drawing loop
+ BreakFinder bfFore(ll, &model.sel, lineRange, posLineStart, xStartVisible,
+ ((!twoPhaseDraw && selBackDrawn) || vsDraw.selColours.fore.isSet), model.pdoc, &model.reprs);
+
+ while (bfFore.More()) {
+
+ const TextSegment ts = bfFore.Next();
+ const int i = ts.end() - 1;
+ const int iDoc = i + posLineStart;
+
+ PRectangle rcSegment = rcLine;
+ rcSegment.left = ll->positions[ts.start] + xStart - static_cast<XYPOSITION>(subLineStart);
+ rcSegment.right = ll->positions[ts.end()] + xStart - static_cast<XYPOSITION>(subLineStart);
+ // Only try to draw if really visible - enhances performance by not calling environment to
+ // draw strings that are completely past the right side of the window.
+ if (rcSegment.Intersects(rcLine)) {
+ int styleMain = ll->styles[i];
+ ColourDesired textFore = vsDraw.styles[styleMain].fore;
+ FontAlias textFont = vsDraw.styles[styleMain].font;
+ //hotspot foreground
+ const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc);
+ if (inHotspot) {
+ if (vsDraw.hotspotColours.fore.isSet)
+ textFore = vsDraw.hotspotColours.fore;
+ }
+ const int inSelection = hideSelection ? 0 : model.sel.CharacterInSelection(iDoc);
+ if (inSelection && (vsDraw.selColours.fore.isSet)) {
+ textFore = (inSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground;
+ }
+ ColourDesired textBack = TextBackground(vsDraw, background, inSelection, inHotspot, styleMain, i, ll, model);
+ if (ts.representation) {
+ if (ll->chars[i] == '\t') {
+ // Tab display
+ if (!twoPhaseDraw) {
+ if (drawWhitespaceBackground &&
+ (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways))
+ textBack = vsDraw.whitespaceColours.back;
+ surface->FillRectangle(rcSegment, textBack);
+ }
+ if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
+ for (int indentCount = static_cast<int>((ll->positions[i] + epsilon) / indentWidth);
+ indentCount <= (ll->positions[i + 1] - epsilon) / indentWidth;
+ indentCount++) {
+ if (indentCount > 0) {
+ int xIndent = static_cast<int>(indentCount * indentWidth);
+ DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
+ (ll->xHighlightGuide == xIndent));
+ }
+ }
+ }
+ if (vsDraw.viewWhitespace != wsInvisible) {
+ if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
+ if (vsDraw.whitespaceColours.fore.isSet)
+ textFore = vsDraw.whitespaceColours.fore;
+ surface->PenColour(textFore);
+ PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4,
+ rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
+ DrawTabArrow(surface, rcTab, static_cast<int>(rcSegment.top + vsDraw.lineHeight / 2));
+ }
+ }
+ } else {
+ inIndentation = false;
+ if (vsDraw.controlCharSymbol >= 32) {
+ char cc[2] = { static_cast<char>(vsDraw.controlCharSymbol), '\0' };
+ surface->DrawTextNoClip(rcSegment, ctrlCharsFont,
+ rcSegment.top + vsDraw.maxAscent,
+ cc, 1, textBack, textFore);
+ } else {
+ DrawTextBlob(surface, vsDraw, rcSegment, ts.representation->stringRep.c_str(), textBack, textFore, twoPhaseDraw);
+ }
+ }
+ } else {
+ // Normal text display
+ if (vsDraw.styles[styleMain].visible) {
+ if (twoPhaseDraw) {
+ surface->DrawTextTransparent(rcSegment, textFont,
+ rcSegment.top + vsDraw.maxAscent, ll->chars + ts.start,
+ i - ts.start + 1, textFore);
+ } else {
+ surface->DrawTextNoClip(rcSegment, textFont,
+ rcSegment.top + vsDraw.maxAscent, ll->chars + ts.start,
+ i - ts.start + 1, textFore, textBack);
+ }
+ }
+ if (vsDraw.viewWhitespace != wsInvisible ||
+ (inIndentation && vsDraw.viewIndentationGuides != ivNone)) {
+ for (int cpos = 0; cpos <= i - ts.start; cpos++) {
+ if (ll->chars[cpos + ts.start] == ' ') {
+ if (vsDraw.viewWhitespace != wsInvisible) {
+ if (vsDraw.whitespaceColours.fore.isSet)
+ textFore = vsDraw.whitespaceColours.fore;
+ if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
+ XYPOSITION xmid = (ll->positions[cpos + ts.start] + ll->positions[cpos + ts.start + 1]) / 2;
+ if (!twoPhaseDraw && drawWhitespaceBackground &&
+ (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {
+ textBack = vsDraw.whitespaceColours.back;
+ PRectangle rcSpace(
+ ll->positions[cpos + ts.start] + xStart - static_cast<XYPOSITION>(subLineStart),
+ rcSegment.top,
+ ll->positions[cpos + ts.start + 1] + xStart - static_cast<XYPOSITION>(subLineStart),
+ rcSegment.bottom);
+ surface->FillRectangle(rcSpace, textBack);
+ }
+ PRectangle rcDot(xmid + xStart - static_cast<XYPOSITION>(subLineStart),
+ rcSegment.top + vsDraw.lineHeight / 2, 0.0f, 0.0f);
+ rcDot.right = rcDot.left + vsDraw.whitespaceSize;
+ rcDot.bottom = rcDot.top + vsDraw.whitespaceSize;
+ surface->FillRectangle(rcDot, textFore);
+ }
+ }
+ if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
+ for (int indentCount = static_cast<int>((ll->positions[cpos + ts.start] + epsilon) / indentWidth);
+ indentCount <= (ll->positions[cpos + ts.start + 1] - epsilon) / indentWidth;
+ indentCount++) {
+ if (indentCount > 0) {
+ int xIndent = static_cast<int>(indentCount * indentWidth);
+ DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
+ (ll->xHighlightGuide == xIndent));
+ }
+ }
+ }
+ } else {
+ inIndentation = false;
+ }
+ }
+ }
+ }
+ if (ll->hotspot.Valid() && vsDraw.hotspotUnderline && ll->hotspot.ContainsCharacter(iDoc)) {
+ PRectangle rcUL = rcSegment;
+ rcUL.top = rcUL.top + vsDraw.maxAscent + 1;
+ rcUL.bottom = rcUL.top + 1;
+ if (vsDraw.hotspotColours.fore.isSet)
+ surface->FillRectangle(rcUL, vsDraw.hotspotColours.fore);
+ else
+ surface->FillRectangle(rcUL, textFore);
+ } else if (vsDraw.styles[styleMain].underline) {
+ PRectangle rcUL = rcSegment;
+ rcUL.top = rcUL.top + vsDraw.maxAscent + 1;
+ rcUL.bottom = rcUL.top + 1;
+ surface->FillRectangle(rcUL, textFore);
+ }
+ } else if (rcSegment.left > rcLine.right) {
+ break;
+ }
+ }
+ if ((vsDraw.viewIndentationGuides == ivLookForward || vsDraw.viewIndentationGuides == ivLookBoth)
+ && (subLine == 0)) {
+ int indentSpace = model.pdoc->GetLineIndentation(line);
+ int xStartText = static_cast<int>(ll->positions[model.pdoc->GetLineIndentPosition(line) - posLineStart]);
+
+ // Find the most recent line with some text
+
+ int lineLastWithText = line;
+ while (lineLastWithText > Platform::Maximum(line - 20, 0) && model.pdoc->IsWhiteLine(lineLastWithText)) {
+ lineLastWithText--;
+ }
+ if (lineLastWithText < line) {
+ xStartText = 100000; // Don't limit to visible indentation on empty line
+ // This line is empty, so use indentation of last line with text
+ int indentLastWithText = model.pdoc->GetLineIndentation(lineLastWithText);
+ int isFoldHeader = model.pdoc->GetLevel(lineLastWithText) & SC_FOLDLEVELHEADERFLAG;
+ if (isFoldHeader) {
+ // Level is one more level than parent
+ indentLastWithText += model.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 < Platform::Minimum(line + 20, model.pdoc->LinesTotal()) && model.pdoc->IsWhiteLine(lineNextWithText)) {
+ lineNextWithText++;
+ }
+ if (lineNextWithText > line) {
+ xStartText = 100000; // Don't limit to visible indentation on empty line
+ // This line is empty, so use indentation of first next line with text
+ indentSpace = Platform::Maximum(indentSpace,
+ model.pdoc->GetLineIndentation(lineNextWithText));
+ }
+
+ for (int indentPos = model.pdoc->IndentSize(); indentPos < indentSpace; indentPos += model.pdoc->IndentSize()) {
+ int xIndent = static_cast<int>(indentPos * vsDraw.spaceWidth);
+ if (xIndent < xStartText) {
+ DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcLine,
+ (ll->xHighlightGuide == xIndent));
+ }
+ }
+ }
+
+ DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineRange.end, false, model);
+
+ // End of the drawing of the current line
+ if (!twoPhaseDraw) {
+ DrawEOL(surface, vsDraw, rcLine, ll, line, lineRange.end,
+ xStart, subLine, subLineStart, background, model);
+ }
+ if (!hideSelection && ((vsDraw.selAlpha != SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha != SC_ALPHA_NOALPHA))) {
+ // For each selection draw
+ int virtualSpaces = 0;
+ if (subLine == (ll->lines - 1)) {
+ virtualSpaces = model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line));
+ }
+ SelectionPosition posStart(posLineStart + lineRange.start);
+ SelectionPosition posEnd(posLineStart + lineRange.end, virtualSpaces);
+ SelectionSegment virtualSpaceRange(posStart, posEnd);
+ for (size_t r = 0; r<model.sel.Count(); r++) {
+ int alpha = (r == model.sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
+ if (alpha != SC_ALPHA_NOALPHA) {
+ SelectionSegment portion = model.sel.Range(r).Intersect(virtualSpaceRange);
+ if (!portion.Empty()) {
+ const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
+ PRectangle rcSegment = rcLine;
+ rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] -
+ static_cast<XYPOSITION>(subLineStart)+portion.start.VirtualSpace() * spaceWidth;
+ rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] -
+ static_cast<XYPOSITION>(subLineStart)+portion.end.VirtualSpace() * spaceWidth;
+ if ((ll->wrapIndent != 0) && (lineRange.start != 0)) {
+ if ((portion.start.Position() - posLineStart) == lineRange.start && model.sel.Range(r).ContainsCharacter(portion.start.Position() - 1))
+ rcSegment.left -= static_cast<int>(ll->wrapIndent); // indentation added to xStart was truncated to int, so we do the same here
+ }
+ rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left;
+ rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right;
+ if (rcSegment.right > rcLine.left)
+ SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, r == model.sel.Main(), model.primarySelection), alpha);
+ }
+ }
+ }
+ }
+
+ // Draw any translucent whole line states
+ if ((model.caret.active || vsDraw.alwaysShowCaretLineBackground) && vsDraw.showCaretLineBackground && ll->containsCaret) {
+ SimpleAlphaRectangle(surface, rcLine, vsDraw.caretLineBackground, vsDraw.caretLineAlpha);
+ }
+ marks = model.pdoc->GetMark(line);
+ for (markBit = 0; (markBit < 32) && marks; markBit++) {
+ if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND)) {
+ SimpleAlphaRectangle(surface, rcLine, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha);
+ } else if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE)) {
+ PRectangle rcUnderline = rcLine;
+ rcUnderline.top = rcUnderline.bottom - 2;
+ SimpleAlphaRectangle(surface, rcUnderline, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha);
+ }
+ marks >>= 1;
+ }
+ if (vsDraw.maskInLine) {
+ int marksMasked = model.pdoc->GetMark(line) & vsDraw.maskInLine;
+ if (marksMasked) {
+ for (markBit = 0; (markBit < 32) && marksMasked; markBit++) {
+ if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY)) {
+ SimpleAlphaRectangle(surface, rcLine, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha);
+ }
+ marksMasked >>= 1;
+ }
+ }
+ }
+}
+
+void EditView::PaintText(Surface *surfaceWindow, PRectangle rcArea, PRectangle rcClient,
+ const EditModel &model, const ViewStyle &vsDraw) {
+ // Allow text at start of line to overlap 1 pixel into the margin as this displays
+ // serifs and italic stems for aliased text.
+ const int leftTextOverlap = ((model.xOffset == 0) && (vsDraw.leftMarginWidth > 0)) ? 1 : 0;
+
+ // Do the painting
+ if (rcArea.right > vsDraw.textStart - leftTextOverlap) {
+
+ Surface *surface = surfaceWindow;
+ if (bufferedDraw) {
+ surface = pixmapLine;
+ PLATFORM_ASSERT(pixmapLine->Initialised());
+ }
+ surface->SetUnicodeMode(SC_CP_UTF8 == model.pdoc->dbcsCodePage);
+ surface->SetDBCSMode(model.pdoc->dbcsCodePage);
+
+ Point ptOrigin = model.GetVisibleOriginInMain();
+
+ int screenLinePaintFirst = static_cast<int>(rcArea.top) / vsDraw.lineHeight;
+ int ypos = 0;
+ if (!bufferedDraw)
+ ypos += screenLinePaintFirst * vsDraw.lineHeight;
+ int xStart = vsDraw.textStart - model.xOffset + static_cast<int>(ptOrigin.x);
+
+ int visibleLine = model.TopLineOfMain() + screenLinePaintFirst;
+ int yposScreen = screenLinePaintFirst * vsDraw.lineHeight;
+
+ SelectionPosition posCaret = model.sel.RangeMain().caret;
+ if (model.posDrag.IsValid())
+ posCaret = model.posDrag;
+ int lineCaret = model.pdoc->LineFromPosition(posCaret.Position());
+
+ PRectangle rcTextArea = rcClient;
+ if (vsDraw.marginInside) {
+ rcTextArea.left += vsDraw.textStart;
+ rcTextArea.right -= vsDraw.rightMarginWidth;
+ } else {
+ rcTextArea = rcArea;
+ }
+
+ // Remove selection margin from drawing area so text will not be drawn
+ // on it in unbuffered mode.
+ if (!bufferedDraw && vsDraw.marginInside) {
+ PRectangle rcClipText = rcTextArea;
+ rcClipText.left -= leftTextOverlap;
+ surfaceWindow->SetClip(rcClipText);
+ }
+
+ // Loop on visible lines
+ //double durLayout = 0.0;
+ //double durPaint = 0.0;
+ //double durCopy = 0.0;
+ //ElapsedTime etWhole;
+ int lineDocPrevious = -1; // Used to avoid laying out one document line multiple times
+ AutoLineLayout ll(llc, 0);
+ while (visibleLine < model.cs.LinesDisplayed() && yposScreen < rcArea.bottom) {
+
+ int lineDoc = model.cs.DocFromDisplay(visibleLine);
+ // Only visible lines should be handled by the code within the loop
+ PLATFORM_ASSERT(model.cs.GetVisible(lineDoc));
+ int lineStartSet = model.cs.DisplayFromDoc(lineDoc);
+ int subLine = visibleLine - lineStartSet;
+
+ // Copy this line and its styles from the document into local arrays
+ // and determine the x position at which each character starts.
+ //ElapsedTime et;
+ if (lineDoc != lineDocPrevious) {
+ ll.Set(0);
+ ll.Set(RetrieveLineLayout(lineDoc, model));
+ LayoutLine(lineDoc, surface, vsDraw, ll, model, model.wrapWidth);
+ lineDocPrevious = lineDoc;
+ }
+ //durLayout += et.Duration(true);
+
+ if (ll) {
+ ll->containsCaret = lineDoc == lineCaret;
+ if (hideSelection) {
+ ll->containsCaret = false;
+ }
+
+ ll->hotspot = model.GetHotSpotRange();
+
+ PRectangle rcLine = rcTextArea;
+ rcLine.top = static_cast<XYPOSITION>(ypos);
+ rcLine.bottom = static_cast<XYPOSITION>(ypos + vsDraw.lineHeight);
+
+ bool bracesIgnoreStyle = false;
+ if ((vsDraw.braceHighlightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACELIGHT)) ||
+ (vsDraw.braceBadLightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACEBAD))) {
+ bracesIgnoreStyle = true;
+ }
+ Range rangeLine(model.pdoc->LineStart(lineDoc), model.pdoc->LineStart(lineDoc + 1));
+ // Highlight the current braces if any
+ ll->SetBracesHighlight(rangeLine, model.braces, static_cast<char>(model.bracesMatchStyle),
+ static_cast<int>(model.highlightGuideColumn * vsDraw.spaceWidth), bracesIgnoreStyle);
+
+ if (leftTextOverlap && bufferedDraw) {
+ PRectangle rcSpacer = rcLine;
+ rcSpacer.right = rcSpacer.left;
+ rcSpacer.left -= 1;
+ surface->FillRectangle(rcSpacer, vsDraw.styles[STYLE_DEFAULT].back);
+ }
+
+ // Draw the line
+ DrawLine(surface, vsDraw, lineDoc, visibleLine, xStart, rcLine, ll, subLine, model);
+ //durPaint += et.Duration(true);
+
+ // Restore the previous styles for the brace highlights in case layout is in cache.
+ ll->RestoreBracesHighlight(rangeLine, model.braces, bracesIgnoreStyle);
+
+ bool expanded = model.cs.GetExpanded(lineDoc);
+ const int level = model.pdoc->GetLevel(lineDoc);
+ const int levelNext = model.pdoc->GetLevel(lineDoc + 1);
+ if ((level & SC_FOLDLEVELHEADERFLAG) &&
+ ((level & SC_FOLDLEVELNUMBERMASK) < (levelNext & SC_FOLDLEVELNUMBERMASK))) {
+ // Paint the line above the fold
+ if ((expanded && (model.foldFlags & SC_FOLDFLAG_LINEBEFORE_EXPANDED))
+ ||
+ (!expanded && (model.foldFlags & SC_FOLDFLAG_LINEBEFORE_CONTRACTED))) {
+ PRectangle rcFoldLine = rcLine;
+ rcFoldLine.bottom = rcFoldLine.top + 1;
+ surface->FillRectangle(rcFoldLine, vsDraw.styles[STYLE_DEFAULT].fore);
+ }
+ // Paint the line below the fold
+ if ((expanded && (model.foldFlags & SC_FOLDFLAG_LINEAFTER_EXPANDED))
+ ||
+ (!expanded && (model.foldFlags & SC_FOLDFLAG_LINEAFTER_CONTRACTED))) {
+ PRectangle rcFoldLine = rcLine;
+ rcFoldLine.top = rcFoldLine.bottom - 1;
+ surface->FillRectangle(rcFoldLine, vsDraw.styles[STYLE_DEFAULT].fore);
+ }
+ }
+
+ DrawCarets(surface, vsDraw, lineDoc, xStart, rcLine, ll, subLine, model);
+
+ if (bufferedDraw) {
+ Point from = Point::FromInts(vsDraw.textStart - leftTextOverlap, 0);
+ PRectangle rcCopyArea = PRectangle::FromInts(vsDraw.textStart - leftTextOverlap, yposScreen,
+ static_cast<int>(rcClient.right - vsDraw.rightMarginWidth),
+ yposScreen + vsDraw.lineHeight);
+ surfaceWindow->Copy(rcCopyArea, from, *pixmapLine);
+ }
+
+ lineWidthMaxSeen = Platform::Maximum(
+ lineWidthMaxSeen, static_cast<int>(ll->positions[ll->numCharsInLine]));
+ //durCopy += et.Duration(true);
+ }
+
+ if (!bufferedDraw) {
+ ypos += vsDraw.lineHeight;
+ }
+
+ yposScreen += vsDraw.lineHeight;
+ visibleLine++;
+
+ //gdk_flush();
+ }
+ ll.Set(0);
+ //if (durPaint < 0.00000001)
+ // durPaint = 0.00000001;
+
+ // Right column limit indicator
+ PRectangle rcBeyondEOF = (vsDraw.marginInside) ? rcClient : rcArea;
+ rcBeyondEOF.left = static_cast<XYPOSITION>(vsDraw.textStart);
+ rcBeyondEOF.right = rcBeyondEOF.right - ((vsDraw.marginInside) ? vsDraw.rightMarginWidth : 0);
+ rcBeyondEOF.top = static_cast<XYPOSITION>((model.cs.LinesDisplayed() - model.TopLineOfMain()) * vsDraw.lineHeight);
+ if (rcBeyondEOF.top < rcBeyondEOF.bottom) {
+ surfaceWindow->FillRectangle(rcBeyondEOF, vsDraw.styles[STYLE_DEFAULT].back);
+ if (vsDraw.edgeState == EDGE_LINE) {
+ int edgeX = static_cast<int>(vsDraw.theEdge * vsDraw.spaceWidth);
+ rcBeyondEOF.left = static_cast<XYPOSITION>(edgeX + xStart);
+ rcBeyondEOF.right = rcBeyondEOF.left + 1;
+ surfaceWindow->FillRectangle(rcBeyondEOF, vsDraw.edgecolour);
+ }
+ }
+ //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset);
+
+ //Platform::DebugPrintf(
+ //"Layout:%9.6g Paint:%9.6g Ratio:%9.6g Copy:%9.6g Total:%9.6g\n",
+ //durLayout, durPaint, durLayout / durPaint, durCopy, etWhole.Duration());
+ }
+}
+
+// Space (3 space characters) between line numbers and text when printing.
+#define lineNumberPrintSpace " "
+
+ColourDesired InvertedLight(ColourDesired orig) {
+ unsigned int r = orig.GetRed();
+ unsigned int g = orig.GetGreen();
+ unsigned int b = orig.GetBlue();
+ unsigned int l = (r + g + b) / 3; // There is a better calculation for this that matches human eye
+ unsigned int il = 0xff - l;
+ if (l == 0)
+ return ColourDesired(0xff, 0xff, 0xff);
+ r = r * il / l;
+ g = g * il / l;
+ b = b * il / l;
+ return ColourDesired(Platform::Minimum(r, 0xff), Platform::Minimum(g, 0xff), Platform::Minimum(b, 0xff));
+}
+
+long EditView::FormatRange(bool draw, Sci_RangeToFormat *pfr, Surface *surface, Surface *surfaceMeasure,
+ const EditModel &model, const ViewStyle &vs) {
+ // Can't use measurements cached for screen
+ posCache.Clear();
+
+ ViewStyle vsPrint(vs);
+ vsPrint.technology = SC_TECHNOLOGY_DEFAULT;
+
+ // Modify the view style for printing as do not normally want any of the transient features to be printed
+ // Printing supports only the line number margin.
+ int lineNumberIndex = -1;
+ for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
+ if ((vsPrint.ms[margin].style == SC_MARGIN_NUMBER) && (vsPrint.ms[margin].width > 0)) {
+ lineNumberIndex = margin;
+ } else {
+ vsPrint.ms[margin].width = 0;
+ }
+ }
+ vsPrint.fixedColumnWidth = 0;
+ vsPrint.zoomLevel = printParameters.magnification;
+ // Don't show indentation guides
+ // If this ever gets changed, cached pixmap would need to be recreated if technology != SC_TECHNOLOGY_DEFAULT
+ vsPrint.viewIndentationGuides = ivNone;
+ // Don't show the selection when printing
+ vsPrint.selColours.back.isSet = false;
+ vsPrint.selColours.fore.isSet = false;
+ vsPrint.selAlpha = SC_ALPHA_NOALPHA;
+ vsPrint.selAdditionalAlpha = SC_ALPHA_NOALPHA;
+ vsPrint.whitespaceColours.back.isSet = false;
+ vsPrint.whitespaceColours.fore.isSet = false;
+ vsPrint.showCaretLineBackground = false;
+ vsPrint.alwaysShowCaretLineBackground = false;
+ // Don't highlight matching braces using indicators
+ vsPrint.braceHighlightIndicatorSet = false;
+ vsPrint.braceBadLightIndicatorSet = false;
+
+ // Set colours for printing according to users settings
+ for (size_t sty = 0; sty < vsPrint.styles.size(); sty++) {
+ if (printParameters.colourMode == SC_PRINT_INVERTLIGHT) {
+ vsPrint.styles[sty].fore = InvertedLight(vsPrint.styles[sty].fore);
+ vsPrint.styles[sty].back = InvertedLight(vsPrint.styles[sty].back);
+ } else if (printParameters.colourMode == SC_PRINT_BLACKONWHITE) {
+ vsPrint.styles[sty].fore = ColourDesired(0, 0, 0);
+ vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff);
+ } else if (printParameters.colourMode == SC_PRINT_COLOURONWHITE) {
+ vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff);
+ } else if (printParameters.colourMode == SC_PRINT_COLOURONWHITEDEFAULTBG) {
+ if (sty <= STYLE_DEFAULT) {
+ vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff);
+ }
+ }
+ }
+ // White background for the line numbers
+ vsPrint.styles[STYLE_LINENUMBER].back = ColourDesired(0xff, 0xff, 0xff);
+
+ // Printing uses different margins, so reset screen margins
+ vsPrint.leftMarginWidth = 0;
+ vsPrint.rightMarginWidth = 0;
+
+ vsPrint.Refresh(*surfaceMeasure, model.pdoc->tabInChars);
+ // Determining width must happen after fonts have been realised in Refresh
+ int lineNumberWidth = 0;
+ if (lineNumberIndex >= 0) {
+ lineNumberWidth = static_cast<int>(surfaceMeasure->WidthText(vsPrint.styles[STYLE_LINENUMBER].font,
+ "99999" lineNumberPrintSpace, 5 + static_cast<int>(strlen(lineNumberPrintSpace))));
+ vsPrint.ms[lineNumberIndex].width = lineNumberWidth;
+ vsPrint.Refresh(*surfaceMeasure, model.pdoc->tabInChars); // Recalculate fixedColumnWidth
+ }
+
+ int linePrintStart = model.pdoc->LineFromPosition(pfr->chrg.cpMin);
+ int linePrintLast = linePrintStart + (pfr->rc.bottom - pfr->rc.top) / vsPrint.lineHeight - 1;
+ if (linePrintLast < linePrintStart)
+ linePrintLast = linePrintStart;
+ int linePrintMax = model.pdoc->LineFromPosition(pfr->chrg.cpMax);
+ if (linePrintLast > linePrintMax)
+ linePrintLast = linePrintMax;
+ //Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n",
+ // linePrintStart, linePrintLast, linePrintMax, pfr->rc.top, pfr->rc.bottom, vsPrint.lineHeight,
+ // surfaceMeasure->Height(vsPrint.styles[STYLE_LINENUMBER].font));
+ int endPosPrint = model.pdoc->Length();
+ if (linePrintLast < model.pdoc->LinesTotal())
+ endPosPrint = model.pdoc->LineStart(linePrintLast + 1);
+
+ // Ensure we are styled to where we are formatting.
+ model.pdoc->EnsureStyledTo(endPosPrint);
+
+ int xStart = vsPrint.fixedColumnWidth + pfr->rc.left;
+ int ypos = pfr->rc.top;
+
+ int lineDoc = linePrintStart;
+
+ int nPrintPos = pfr->chrg.cpMin;
+ int visibleLine = 0;
+ int widthPrint = pfr->rc.right - pfr->rc.left - vsPrint.fixedColumnWidth;
+ if (printParameters.wrapState == eWrapNone)
+ widthPrint = LineLayout::wrapWidthInfinite;
+
+ while (lineDoc <= linePrintLast && ypos < pfr->rc.bottom) {
+
+ // When printing, the hdc and hdcTarget may be the same, so
+ // changing the state of surfaceMeasure may change the underlying
+ // state of surface. Therefore, any cached state is discarded before
+ // using each surface.
+ surfaceMeasure->FlushCachedState();
+
+ // Copy this line and its styles from the document into local arrays
+ // and determine the x position at which each character starts.
+ LineLayout ll(model.pdoc->LineStart(lineDoc + 1) - model.pdoc->LineStart(lineDoc) + 1);
+ LayoutLine(lineDoc, surfaceMeasure, vsPrint, &ll, model, widthPrint);
+
+ ll.containsCaret = false;
+
+ PRectangle rcLine = PRectangle::FromInts(
+ pfr->rc.left,
+ ypos,
+ pfr->rc.right - 1,
+ ypos + vsPrint.lineHeight);
+
+ // When document line is wrapped over multiple display lines, find where
+ // to start printing from to ensure a particular position is on the first
+ // line of the page.
+ if (visibleLine == 0) {
+ int startWithinLine = nPrintPos - model.pdoc->LineStart(lineDoc);
+ for (int iwl = 0; iwl < ll.lines - 1; iwl++) {
+ if (ll.LineStart(iwl) <= startWithinLine && ll.LineStart(iwl + 1) >= startWithinLine) {
+ visibleLine = -iwl;
+ }
+ }
+
+ if (ll.lines > 1 && startWithinLine >= ll.LineStart(ll.lines - 1)) {
+ visibleLine = -(ll.lines - 1);
+ }
+ }
+
+ if (draw && lineNumberWidth &&
+ (ypos + vsPrint.lineHeight <= pfr->rc.bottom) &&
+ (visibleLine >= 0)) {
+ char number[100];
+ sprintf(number, "%d" lineNumberPrintSpace, lineDoc + 1);
+ PRectangle rcNumber = rcLine;
+ rcNumber.right = rcNumber.left + lineNumberWidth;
+ // Right justify
+ rcNumber.left = rcNumber.right - surfaceMeasure->WidthText(
+ vsPrint.styles[STYLE_LINENUMBER].font, number, static_cast<int>(strlen(number)));
+ surface->FlushCachedState();
+ surface->DrawTextNoClip(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font,
+ static_cast<XYPOSITION>(ypos + vsPrint.maxAscent), number, static_cast<int>(strlen(number)),
+ vsPrint.styles[STYLE_LINENUMBER].fore,
+ vsPrint.styles[STYLE_LINENUMBER].back);
+ }
+
+ // Draw the line
+ surface->FlushCachedState();
+
+ for (int iwl = 0; iwl < ll.lines; iwl++) {
+ if (ypos + vsPrint.lineHeight <= pfr->rc.bottom) {
+ if (visibleLine >= 0) {
+ if (draw) {
+ rcLine.top = static_cast<XYPOSITION>(ypos);
+ rcLine.bottom = static_cast<XYPOSITION>(ypos + vsPrint.lineHeight);
+ DrawLine(surface, vsPrint, lineDoc, visibleLine, xStart, rcLine, &ll, iwl, model);
+ }
+ ypos += vsPrint.lineHeight;
+ }
+ visibleLine++;
+ if (iwl == ll.lines - 1)
+ nPrintPos = model.pdoc->LineStart(lineDoc + 1);
+ else
+ nPrintPos += ll.LineStart(iwl + 1) - ll.LineStart(iwl);
+ }
+ }
+
+ ++lineDoc;
+ }
+
+ // Clear cache so measurements are not used for screen
+ posCache.Clear();
+
+ return nPrintPos;
+}
diff --git a/src/EditView.h b/src/EditView.h
new file mode 100644
index 000000000..f55a6f331
--- /dev/null
+++ b/src/EditView.h
@@ -0,0 +1,113 @@
+// Scintilla source code edit control
+/** @file EditView.h
+ ** Defines the appearance of the main text area of the editor window.
+ **/
+// Copyright 1998-2014 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef EDITVIEW_H
+#define EDITVIEW_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+struct PrintParameters {
+ int magnification;
+ int colourMode;
+ WrapMode wrapState;
+ PrintParameters();
+};
+
+/**
+* EditView draws the main text area.
+*/
+class EditView {
+public:
+ PrintParameters printParameters;
+
+ bool hideSelection;
+ bool drawOverstrikeCaret;
+
+ /** In bufferedDraw mode, graphics operations are drawn to a pixmap and then copied to
+ * the screen. This avoids flashing but is about 30% slower. */
+ bool bufferedDraw;
+ /** In twoPhaseDraw mode, drawing is performed in two phases, first the background
+ * and then the foreground. This avoids chopping off characters that overlap the next run. */
+ bool twoPhaseDraw;
+
+ int lineWidthMaxSeen;
+
+ bool additionalCaretsBlink;
+ bool additionalCaretsVisible;
+
+ Surface *pixmapLine;
+ Surface *pixmapIndentGuide;
+ Surface *pixmapIndentGuideHighlight;
+
+ LineLayoutCache llc;
+ PositionCache posCache;
+
+ EditView();
+
+ void DropGraphics(bool freeObjects);
+ void AllocateGraphics(const ViewStyle &vsDraw);
+ void RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw);
+
+ LineLayout *RetrieveLineLayout(int lineNumber, const EditModel &model);
+ void LayoutLine(int line, Surface *surface, const ViewStyle &vstyle, LineLayout *ll,
+ const EditModel &model, int width = LineLayout::wrapWidthInfinite);
+
+ Point LocationFromPosition(Surface *surface, SelectionPosition pos, int topLine, const EditModel &model, const ViewStyle &vs);
+ SelectionPosition SPositionFromLocation(Surface *surface, Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace,
+ const EditModel &model, const ViewStyle &vs);
+ SelectionPosition SPositionFromLineX(Surface *surface, int lineDoc, int x, const EditModel &model, const ViewStyle &vs);
+ int DisplayFromPosition(Surface *surface, int pos, const EditModel &model, const ViewStyle &vs);
+ int StartEndDisplayLine(Surface *surface, int pos, bool start, const EditModel &model, const ViewStyle &vs);
+
+ void DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight);
+ void DrawEOL(Surface *surface, const ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll,
+ int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart,
+ ColourOptional background, const EditModel &model);
+ void DrawAnnotation(Surface *surface, const ViewStyle &vsDraw, int line, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model);
+ void DrawCarets(Surface *surface, const ViewStyle &vsDraw, int line, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model) const;
+ void DrawLine(Surface *surface, const ViewStyle &vsDraw, int line, int lineVisible, int xStart,
+ PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model);
+ void PaintText(Surface *surfaceWindow, PRectangle rcArea, PRectangle rcClient,
+ const EditModel &model, const ViewStyle &vsDraw);
+ long FormatRange(bool draw, Sci_RangeToFormat *pfr, Surface *surface, Surface *surfaceMeasure,
+ const EditModel &model, const ViewStyle &vs);
+};
+
+/**
+* Convenience class to ensure LineLayout objects are always disposed.
+*/
+class AutoLineLayout {
+ LineLayoutCache &llc;
+ LineLayout *ll;
+ AutoLineLayout &operator=(const AutoLineLayout &);
+public:
+ AutoLineLayout(LineLayoutCache &llc_, LineLayout *ll_) : llc(llc_), ll(ll_) {}
+ ~AutoLineLayout() {
+ llc.Dispose(ll);
+ ll = 0;
+ }
+ LineLayout *operator->() const {
+ return ll;
+ }
+ operator LineLayout *() const {
+ return ll;
+ }
+ void Set(LineLayout *ll_) {
+ llc.Dispose(ll);
+ ll = ll_;
+ }
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/src/Editor.cxx b/src/Editor.cxx
index 360540a83..a23683698 100644
--- a/src/Editor.cxx
+++ b/src/Editor.cxx
@@ -42,6 +42,9 @@
#include "UniConversion.h"
#include "Selection.h"
#include "PositionCache.h"
+#include "EditModel.h"
+#include "MarginView.h"
+#include "EditView.h"
#include "Editor.h"
#ifdef SCI_NAMESPACE
@@ -79,20 +82,12 @@ static bool IsLastStep(const DocModification &mh) {
&& (mh.modificationType & SC_MULTILINEUNDOREDO) != 0;
}
-Caret::Caret() :
- active(false), on(false), period(500) {}
-
Timer::Timer() :
ticking(false), ticksToWait(0), tickerID(0) {}
Idler::Idler() :
state(false), idlerID(0) {}
-static inline bool IsControlCharacter(int ch) {
- // iscntrl returns true for lots of chars > 127 which are displayable
- return ch >= 0 && ch < ' ';
-}
-
static inline bool IsAllSpacesOrTabs(char *s, unsigned int len) {
for (unsigned int i = 0; i < len; i++) {
// This is safe because IsSpaceOrTab() will return false for null terminators
@@ -102,2293 +97,6 @@ static inline bool IsAllSpacesOrTabs(char *s, unsigned int len) {
return true;
}
-EditModel::EditModel() {
- inOverstrike = false;
- xOffset = 0;
- trackLineWidth = false;
- posDrag = SelectionPosition(invalidPosition);
- braces[0] = invalidPosition;
- braces[1] = invalidPosition;
- bracesMatchStyle = STYLE_BRACEBAD;
- highlightGuideColumn = 0;
- primarySelection = true;
- foldFlags = 0;
- hotspot = Range(invalidPosition);
- wrapWidth = LineLayout::wrapWidthInfinite;
- pdoc = new Document();
- pdoc->AddRef();
-}
-
-EditModel::~EditModel() {
- pdoc->Release();
- pdoc = 0;
-}
-
-bool ValidStyledText(const ViewStyle &vs, size_t styleOffset, const StyledText &st) {
- if (st.multipleStyles) {
- for (size_t iStyle = 0; iStyle<st.length; iStyle++) {
- if (!vs.ValidStyle(styleOffset + st.styles[iStyle]))
- return false;
- }
- } else {
- if (!vs.ValidStyle(styleOffset + st.style))
- return false;
- }
- return true;
-}
-
-static int WidthStyledText(Surface *surface, const ViewStyle &vs, int styleOffset,
- const char *text, const unsigned char *styles, size_t len) {
- int width = 0;
- size_t start = 0;
- while (start < len) {
- size_t style = styles[start];
- size_t endSegment = start;
- while ((endSegment + 1 < len) && (static_cast<size_t>(styles[endSegment + 1]) == style))
- endSegment++;
- FontAlias fontText = vs.styles[style + styleOffset].font;
- width += static_cast<int>(surface->WidthText(fontText, text + start,
- static_cast<int>(endSegment - start + 1)));
- start = endSegment + 1;
- }
- return width;
-}
-
-static int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, const StyledText &st) {
- int widthMax = 0;
- size_t start = 0;
- while (start < st.length) {
- size_t lenLine = st.LineLength(start);
- int widthSubLine;
- if (st.multipleStyles) {
- widthSubLine = WidthStyledText(surface, vs, styleOffset, st.text + start, st.styles + start, lenLine);
- } else {
- FontAlias fontText = vs.styles[styleOffset + st.style].font;
- widthSubLine = static_cast<int>(surface->WidthText(fontText,
- st.text + start, static_cast<int>(lenLine)));
- }
- if (widthSubLine > widthMax)
- widthMax = widthSubLine;
- start += lenLine + 1;
- }
- return widthMax;
-}
-
-static void DrawTextInStyle(Surface *surface, PRectangle rcText, const Style &style, XYPOSITION ybase, const char *s, size_t length) {
- FontAlias fontText = style.font;
- surface->DrawTextNoClip(rcText, fontText, ybase, s, static_cast<int>(length),
- style.fore, style.back);
-}
-
-static void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText,
- const StyledText &st, size_t start, size_t length) {
-
- if (st.multipleStyles) {
- int x = static_cast<int>(rcText.left);
- size_t i = 0;
- while (i < length) {
- size_t end = i;
- size_t style = st.styles[i + start];
- while (end < length - 1 && st.styles[start + end + 1] == style)
- end++;
- style += styleOffset;
- FontAlias fontText = vs.styles[style].font;
- const int width = static_cast<int>(surface->WidthText(fontText,
- st.text + start + i, static_cast<int>(end - i + 1)));
- PRectangle rcSegment = rcText;
- rcSegment.left = static_cast<XYPOSITION>(x);
- rcSegment.right = static_cast<XYPOSITION>(x + width + 1);
- DrawTextInStyle(surface, rcSegment, vs.styles[style], rcText.top + vs.maxAscent,
- st.text + start + i, end - i + 1);
- x += width;
- i = end + 1;
- }
- } else {
- const size_t style = st.style + styleOffset;
- DrawTextInStyle(surface, rcText, vs.styles[style], rcText.top + vs.maxAscent,
- st.text + start, length);
- }
-}
-
-static void DrawWrapMarker(Surface *surface, PRectangle rcPlace,
- bool isEndMarker, ColourDesired wrapColour) {
- surface->PenColour(wrapColour);
-
- enum { xa = 1 }; // gap before start
- int w = static_cast<int>(rcPlace.right - rcPlace.left) - xa - 1;
-
- bool xStraight = isEndMarker; // x-mirrored symbol for start marker
-
- int x0 = static_cast<int>(xStraight ? rcPlace.left : rcPlace.right - 1);
- int y0 = static_cast<int>(rcPlace.top);
-
- int dy = static_cast<int>(rcPlace.bottom - rcPlace.top) / 5;
- int y = static_cast<int>(rcPlace.bottom - rcPlace.top) / 2 + dy;
-
- struct Relative {
- Surface *surface;
- int xBase;
- int xDir;
- int yBase;
- int yDir;
- void MoveTo(int xRelative, int yRelative) {
- surface->MoveTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
- }
- void LineTo(int xRelative, int yRelative) {
- surface->LineTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
- }
- };
- Relative rel = { surface, x0, xStraight ? 1 : -1, y0, 1 };
-
- // arrow head
- rel.MoveTo(xa, y);
- rel.LineTo(xa + 2 * w / 3, y - dy);
- rel.MoveTo(xa, y);
- rel.LineTo(xa + 2 * w / 3, y + dy);
-
- // arrow body
- rel.MoveTo(xa, y);
- 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);
-}
-
-MarginView::MarginView() {
- pixmapSelMargin = 0;
- pixmapSelPattern = 0;
- pixmapSelPatternOffset1 = 0;
-}
-
-void MarginView::DropGraphics(bool freeObjects) {
- if (freeObjects) {
- delete pixmapSelMargin;
- pixmapSelMargin = 0;
- delete pixmapSelPattern;
- pixmapSelPattern = 0;
- delete pixmapSelPatternOffset1;
- pixmapSelPatternOffset1 = 0;
- } else {
- if (pixmapSelMargin)
- pixmapSelMargin->Release();
- if (pixmapSelPattern)
- pixmapSelPattern->Release();
- if (pixmapSelPatternOffset1)
- pixmapSelPatternOffset1->Release();
- }
-}
-
-void MarginView::AllocateGraphics(const ViewStyle &vsDraw) {
- if (!pixmapSelMargin)
- pixmapSelMargin = Surface::Allocate(vsDraw.technology);
- if (!pixmapSelPattern)
- pixmapSelPattern = Surface::Allocate(vsDraw.technology);
- if (!pixmapSelPatternOffset1)
- pixmapSelPatternOffset1 = Surface::Allocate(vsDraw.technology);
-}
-
-void MarginView::RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw) {
- if (!pixmapSelPattern->Initialised()) {
- const int patternSize = 8;
- pixmapSelPattern->InitPixMap(patternSize, patternSize, surfaceWindow, wid);
- pixmapSelPatternOffset1->InitPixMap(patternSize, patternSize, surfaceWindow, wid);
- // This complex procedure is to reproduce the checkerboard dithered pattern used by windows
- // for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half
- // way between the chrome colour and the chrome highlight colour making a nice transition
- // between the window chrome and the content area. And it works in low colour depths.
- PRectangle rcPattern = PRectangle::FromInts(0, 0, patternSize, patternSize);
-
- // Initialize default colours based on the chrome colour scheme. Typically the highlight is white.
- ColourDesired colourFMFill = vsDraw.selbar;
- ColourDesired colourFMStripes = vsDraw.selbarlight;
-
- if (!(vsDraw.selbarlight == ColourDesired(0xff, 0xff, 0xff))) {
- // User has chosen an unusual chrome colour scheme so just use the highlight edge colour.
- // (Typically, the highlight colour is white.)
- colourFMFill = vsDraw.selbarlight;
- }
-
- if (vsDraw.foldmarginColour.isSet) {
- // override default fold margin colour
- colourFMFill = vsDraw.foldmarginColour;
- }
- if (vsDraw.foldmarginHighlightColour.isSet) {
- // override default fold margin highlight colour
- colourFMStripes = vsDraw.foldmarginHighlightColour;
- }
-
- pixmapSelPattern->FillRectangle(rcPattern, colourFMFill);
- pixmapSelPatternOffset1->FillRectangle(rcPattern, colourFMStripes);
- for (int y = 0; y < patternSize; y++) {
- for (int x = y % 2; x < patternSize; x += 2) {
- PRectangle rcPixel = PRectangle::FromInts(x, y, x + 1, y + 1);
- pixmapSelPattern->FillRectangle(rcPixel, colourFMStripes);
- pixmapSelPatternOffset1->FillRectangle(rcPixel, colourFMFill);
- }
- }
- }
-}
-
-static int SubstituteMarkerIfEmpty(int markerCheck, int markerDefault, const ViewStyle &vs) {
- if (vs.markers[markerCheck].markType == SC_MARK_EMPTY)
- return markerDefault;
- return markerCheck;
-}
-
-void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRectangle rcMargin,
- const EditModel &model, const ViewStyle &vs) {
-
- PRectangle rcSelMargin = rcMargin;
- rcSelMargin.right = rcMargin.left;
- if (rcSelMargin.bottom < rc.bottom)
- rcSelMargin.bottom = rc.bottom;
-
- Point ptOrigin = model.GetVisibleOriginInMain();
- FontAlias fontLineNumber = vs.styles[STYLE_LINENUMBER].font;
- for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
- if (vs.ms[margin].width > 0) {
-
- rcSelMargin.left = rcSelMargin.right;
- rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width;
-
- if (vs.ms[margin].style != SC_MARGIN_NUMBER) {
- if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
- // Required because of special way brush is created for selection margin
- // Ensure patterns line up when scrolling with separate margin view
- // by choosing correctly aligned variant.
- bool invertPhase = static_cast<int>(ptOrigin.y) & 1;
- surface->FillRectangle(rcSelMargin,
- invertPhase ? *pixmapSelPattern : *pixmapSelPatternOffset1);
- } else {
- ColourDesired colour;
- switch (vs.ms[margin].style) {
- case SC_MARGIN_BACK:
- colour = vs.styles[STYLE_DEFAULT].back;
- break;
- case SC_MARGIN_FORE:
- colour = vs.styles[STYLE_DEFAULT].fore;
- break;
- default:
- colour = vs.styles[STYLE_LINENUMBER].back;
- break;
- }
- surface->FillRectangle(rcSelMargin, colour);
- }
- } else {
- surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back);
- }
-
- const int lineStartPaint = static_cast<int>(rcMargin.top + ptOrigin.y) / vs.lineHeight;
- int visibleLine = model.TopLineOfMain() + lineStartPaint;
- int yposScreen = lineStartPaint * vs.lineHeight - static_cast<int>(ptOrigin.y);
- // Work out whether the top line is whitespace located after a
- // lessening of fold level which implies a 'fold tail' but which should not
- // be displayed until the last of a sequence of whitespace.
- bool needWhiteClosure = false;
- if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
- int level = model.pdoc->GetLevel(model.cs.DocFromDisplay(visibleLine));
- if (level & SC_FOLDLEVELWHITEFLAG) {
- int lineBack = model.cs.DocFromDisplay(visibleLine);
- int levelPrev = level;
- while ((lineBack > 0) && (levelPrev & SC_FOLDLEVELWHITEFLAG)) {
- lineBack--;
- levelPrev = model.pdoc->GetLevel(lineBack);
- }
- if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) {
- if ((level & SC_FOLDLEVELNUMBERMASK) < (levelPrev & SC_FOLDLEVELNUMBERMASK))
- needWhiteClosure = true;
- }
- }
- if (highlightDelimiter.isEnabled) {
- int lastLine = model.cs.DocFromDisplay(topLine + model.LinesOnScreen()) + 1;
- model.pdoc->GetHighlightDelimiters(highlightDelimiter, model.pdoc->LineFromPosition(model.sel.MainCaret()), lastLine);
- }
- }
-
- // Old code does not know about new markers needed to distinguish all cases
- const int folderOpenMid = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID,
- SC_MARKNUM_FOLDEROPEN, vs);
- const int folderEnd = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND,
- SC_MARKNUM_FOLDER, vs);
-
- while ((visibleLine < model.cs.LinesDisplayed()) && yposScreen < rc.bottom) {
-
- PLATFORM_ASSERT(visibleLine < model.cs.LinesDisplayed());
- const int lineDoc = model.cs.DocFromDisplay(visibleLine);
- PLATFORM_ASSERT(model.cs.GetVisible(lineDoc));
- const bool firstSubLine = visibleLine == model.cs.DisplayFromDoc(lineDoc);
- const bool lastSubLine = visibleLine == model.cs.DisplayLastFromDoc(lineDoc);
-
- int marks = model.pdoc->GetMark(lineDoc);
- if (!firstSubLine)
- marks = 0;
-
- bool headWithTail = false;
-
- if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
- // Decide which fold indicator should be displayed
- const int level = model.pdoc->GetLevel(lineDoc);
- const int levelNext = model.pdoc->GetLevel(lineDoc + 1);
- const int levelNum = level & SC_FOLDLEVELNUMBERMASK;
- const int levelNextNum = levelNext & SC_FOLDLEVELNUMBERMASK;
- if (level & SC_FOLDLEVELHEADERFLAG) {
- if (firstSubLine) {
- if (levelNum < levelNextNum) {
- if (model.cs.GetExpanded(lineDoc)) {
- if (levelNum == SC_FOLDLEVELBASE)
- marks |= 1 << SC_MARKNUM_FOLDEROPEN;
- else
- marks |= 1 << folderOpenMid;
- } else {
- if (levelNum == SC_FOLDLEVELBASE)
- marks |= 1 << SC_MARKNUM_FOLDER;
- else
- marks |= 1 << folderEnd;
- }
- } else if (levelNum > SC_FOLDLEVELBASE) {
- marks |= 1 << SC_MARKNUM_FOLDERSUB;
- }
- } else {
- if (levelNum < levelNextNum) {
- if (model.cs.GetExpanded(lineDoc)) {
- marks |= 1 << SC_MARKNUM_FOLDERSUB;
- } else if (levelNum > SC_FOLDLEVELBASE) {
- marks |= 1 << SC_MARKNUM_FOLDERSUB;
- }
- } else if (levelNum > SC_FOLDLEVELBASE) {
- marks |= 1 << SC_MARKNUM_FOLDERSUB;
- }
- }
- needWhiteClosure = false;
- const int firstFollowupLine = model.cs.DocFromDisplay(model.cs.DisplayFromDoc(lineDoc + 1));
- const int firstFollowupLineLevel = model.pdoc->GetLevel(firstFollowupLine);
- const int secondFollowupLineLevelNum = model.pdoc->GetLevel(firstFollowupLine + 1) & SC_FOLDLEVELNUMBERMASK;
- if (!model.cs.GetExpanded(lineDoc)) {
- if ((firstFollowupLineLevel & SC_FOLDLEVELWHITEFLAG) &&
- (levelNum > secondFollowupLineLevelNum))
- needWhiteClosure = true;
-
- if (highlightDelimiter.IsFoldBlockHighlighted(firstFollowupLine))
- headWithTail = true;
- }
- } else if (level & SC_FOLDLEVELWHITEFLAG) {
- if (needWhiteClosure) {
- if (levelNext & SC_FOLDLEVELWHITEFLAG) {
- marks |= 1 << SC_MARKNUM_FOLDERSUB;
- } else if (levelNextNum > SC_FOLDLEVELBASE) {
- marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
- needWhiteClosure = false;
- } else {
- marks |= 1 << SC_MARKNUM_FOLDERTAIL;
- needWhiteClosure = false;
- }
- } else if (levelNum > SC_FOLDLEVELBASE) {
- if (levelNextNum < levelNum) {
- if (levelNextNum > SC_FOLDLEVELBASE) {
- marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
- } else {
- marks |= 1 << SC_MARKNUM_FOLDERTAIL;
- }
- } else {
- marks |= 1 << SC_MARKNUM_FOLDERSUB;
- }
- }
- } else if (levelNum > SC_FOLDLEVELBASE) {
- if (levelNextNum < levelNum) {
- needWhiteClosure = false;
- if (levelNext & SC_FOLDLEVELWHITEFLAG) {
- marks |= 1 << SC_MARKNUM_FOLDERSUB;
- needWhiteClosure = true;
- } else if (lastSubLine) {
- if (levelNextNum > SC_FOLDLEVELBASE) {
- marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
- } else {
- marks |= 1 << SC_MARKNUM_FOLDERTAIL;
- }
- } else {
- marks |= 1 << SC_MARKNUM_FOLDERSUB;
- }
- } else {
- marks |= 1 << SC_MARKNUM_FOLDERSUB;
- }
- }
- }
-
- marks &= vs.ms[margin].mask;
-
- PRectangle rcMarker = rcSelMargin;
- rcMarker.top = static_cast<XYPOSITION>(yposScreen);
- rcMarker.bottom = static_cast<XYPOSITION>(yposScreen + vs.lineHeight);
- if (vs.ms[margin].style == SC_MARGIN_NUMBER) {
- if (firstSubLine) {
- char number[100] = "";
- if (lineDoc >= 0)
- sprintf(number, "%d", lineDoc + 1);
- if (model.foldFlags & (SC_FOLDFLAG_LEVELNUMBERS | SC_FOLDFLAG_LINESTATE)) {
- if (model.foldFlags & SC_FOLDFLAG_LEVELNUMBERS) {
- int lev = model.pdoc->GetLevel(lineDoc);
- sprintf(number, "%c%c %03X %03X",
- (lev & SC_FOLDLEVELHEADERFLAG) ? 'H' : '_',
- (lev & SC_FOLDLEVELWHITEFLAG) ? 'W' : '_',
- lev & SC_FOLDLEVELNUMBERMASK,
- lev >> 16
- );
- } else {
- int state = model.pdoc->GetLineState(lineDoc);
- sprintf(number, "%0X", state);
- }
- }
- PRectangle rcNumber = rcMarker;
- // Right justify
- XYPOSITION width = surface->WidthText(fontLineNumber, number, static_cast<int>(strlen(number)));
- XYPOSITION xpos = rcNumber.right - width - vs.marginNumberPadding;
- rcNumber.left = xpos;
- DrawTextInStyle(surface, rcNumber, vs.styles[STYLE_LINENUMBER],
- rcNumber.top + vs.maxAscent, number, strlen(number));
- } else if (vs.wrapVisualFlags & SC_WRAPVISUALFLAG_MARGIN) {
- PRectangle rcWrapMarker = rcMarker;
- rcWrapMarker.right -= 3;
- rcWrapMarker.left = rcWrapMarker.right - vs.styles[STYLE_LINENUMBER].aveCharWidth;
- DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore);
- }
- } else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) {
- if (firstSubLine) {
- const StyledText stMargin = model.pdoc->MarginStyledText(lineDoc);
- if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) {
- surface->FillRectangle(rcMarker,
- vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back);
- if (vs.ms[margin].style == SC_MARGIN_RTEXT) {
- int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, stMargin);
- rcMarker.left = rcMarker.right - width - 3;
- }
- DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker,
- stMargin, 0, stMargin.length);
- }
- }
- }
-
- if (marks) {
- for (int markBit = 0; (markBit < 32) && marks; markBit++) {
- if (marks & 1) {
- LineMarker::typeOfFold tFold = LineMarker::undefined;
- if ((vs.ms[margin].mask & SC_MASK_FOLDERS) && highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) {
- if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) {
- tFold = LineMarker::body;
- } else if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) {
- if (firstSubLine) {
- tFold = headWithTail ? LineMarker::headWithTail : LineMarker::head;
- } else {
- if (model.cs.GetExpanded(lineDoc) || headWithTail) {
- tFold = LineMarker::body;
- } else {
- tFold = LineMarker::undefined;
- }
- }
- } else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) {
- tFold = LineMarker::tail;
- }
- }
- vs.markers[markBit].Draw(surface, rcMarker, fontLineNumber, tFold, vs.ms[margin].style);
- }
- marks >>= 1;
- }
- }
-
- visibleLine++;
- yposScreen += vs.lineHeight;
- }
- }
- }
-
- PRectangle rcBlankMargin = rcMargin;
- rcBlankMargin.left = rcSelMargin.right;
- surface->FillRectangle(rcBlankMargin, vs.styles[STYLE_DEFAULT].back);
-}
-
-/**
-* Convenience class to ensure LineLayout objects are always disposed.
-*/
-class AutoLineLayout {
- LineLayoutCache &llc;
- LineLayout *ll;
- AutoLineLayout &operator=(const AutoLineLayout &);
-public:
- AutoLineLayout(LineLayoutCache &llc_, LineLayout *ll_) : llc(llc_), ll(ll_) {}
- ~AutoLineLayout() {
- llc.Dispose(ll);
- ll = 0;
- }
- LineLayout *operator->() const {
- return ll;
- }
- operator LineLayout *() const {
- return ll;
- }
- void Set(LineLayout *ll_) {
- llc.Dispose(ll);
- ll = ll_;
- }
-};
-
-PrintParameters::PrintParameters() {
- magnification = 0;
- colourMode = SC_PRINT_NORMAL;
- wrapState = eWrapWord;
-}
-
-const XYPOSITION epsilon = 0.0001f; // A small nudge to avoid floating point precision issues
-
-EditView::EditView() {
- hideSelection = false;
- drawOverstrikeCaret = true;
- bufferedDraw = true;
- twoPhaseDraw = true;
- lineWidthMaxSeen = 0;
- additionalCaretsBlink = true;
- additionalCaretsVisible = true;
- pixmapLine = 0;
- pixmapIndentGuide = 0;
- pixmapIndentGuideHighlight = 0;
- llc.SetLevel(LineLayoutCache::llcCaret);
- posCache.SetSize(0x400);
-}
-
-void EditView::DropGraphics(bool freeObjects) {
- if (freeObjects) {
- delete pixmapLine;
- pixmapLine = 0;
- delete pixmapIndentGuide;
- pixmapIndentGuide = 0;
- delete pixmapIndentGuideHighlight;
- pixmapIndentGuideHighlight = 0;
- } else {
- if (pixmapLine)
- pixmapLine->Release();
- if (pixmapIndentGuide)
- pixmapIndentGuide->Release();
- if (pixmapIndentGuideHighlight)
- pixmapIndentGuideHighlight->Release();
- }
-}
-
-void EditView::AllocateGraphics(const ViewStyle &vsDraw) {
- if (!pixmapLine)
- pixmapLine = Surface::Allocate(vsDraw.technology);
- if (!pixmapIndentGuide)
- pixmapIndentGuide = Surface::Allocate(vsDraw.technology);
- if (!pixmapIndentGuideHighlight)
- pixmapIndentGuideHighlight = Surface::Allocate(vsDraw.technology);
-}
-
-const char *ControlCharacterString(unsigned char ch) {
- const char *reps[] = {
- "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
- "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
- "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
- "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
- };
- if (ch < ELEMENTS(reps)) {
- return reps[ch];
- } else {
- return "BAD";
- }
-}
-
-void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) {
- int ydiff = static_cast<int>(rcTab.bottom - rcTab.top) / 2;
- int xhead = static_cast<int>(rcTab.right) - 1 - ydiff;
- if (xhead <= rcTab.left) {
- ydiff -= static_cast<int>(rcTab.left) - xhead - 1;
- xhead = static_cast<int>(rcTab.left) - 1;
- }
- if ((rcTab.left + 2) < (rcTab.right - 1))
- surface->MoveTo(static_cast<int>(rcTab.left) + 2, ymid);
- else
- surface->MoveTo(static_cast<int>(rcTab.right) - 1, ymid);
- surface->LineTo(static_cast<int>(rcTab.right) - 1, ymid);
- surface->LineTo(xhead, ymid - ydiff);
- surface->MoveTo(static_cast<int>(rcTab.right) - 1, ymid);
- surface->LineTo(xhead, ymid + ydiff);
-}
-
-void EditView::RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw) {
- if (!pixmapIndentGuide->Initialised()) {
- // 1 extra pixel in height so can handle odd/even positions and so produce a continuous line
- pixmapIndentGuide->InitPixMap(1, vsDraw.lineHeight + 1, surfaceWindow, wid);
- pixmapIndentGuideHighlight->InitPixMap(1, vsDraw.lineHeight + 1, surfaceWindow, wid);
- PRectangle rcIG = PRectangle::FromInts(0, 0, 1, vsDraw.lineHeight);
- pixmapIndentGuide->FillRectangle(rcIG, vsDraw.styles[STYLE_INDENTGUIDE].back);
- pixmapIndentGuide->PenColour(vsDraw.styles[STYLE_INDENTGUIDE].fore);
- pixmapIndentGuideHighlight->FillRectangle(rcIG, vsDraw.styles[STYLE_BRACELIGHT].back);
- pixmapIndentGuideHighlight->PenColour(vsDraw.styles[STYLE_BRACELIGHT].fore);
- for (int stripe = 1; stripe < vsDraw.lineHeight + 1; stripe += 2) {
- PRectangle rcPixel = PRectangle::FromInts(0, stripe, 1, stripe + 1);
- pixmapIndentGuide->FillRectangle(rcPixel, vsDraw.styles[STYLE_INDENTGUIDE].fore);
- pixmapIndentGuideHighlight->FillRectangle(rcPixel, vsDraw.styles[STYLE_BRACELIGHT].fore);
- }
- }
-}
-
-LineLayout *EditView::RetrieveLineLayout(int lineNumber, const EditModel &model) {
- int posLineStart = model.pdoc->LineStart(lineNumber);
- int posLineEnd = model.pdoc->LineStart(lineNumber + 1);
- PLATFORM_ASSERT(posLineEnd >= posLineStart);
- int lineCaret = model.pdoc->LineFromPosition(model.sel.MainCaret());
- return llc.Retrieve(lineNumber, lineCaret,
- posLineEnd - posLineStart, model.pdoc->GetStyleClock(),
- model.LinesOnScreen() + 1, model.pdoc->LinesTotal());
-}
-
-/**
-* Fill in the LineLayout data for the given line.
-* Copy the given @a line and its styles from the document into local arrays.
-* Also determine the x position at which each character starts.
-*/
-void EditView::LayoutLine(int line, Surface *surface, const ViewStyle &vstyle, LineLayout *ll, const EditModel &model, int width) {
- if (!ll)
- return;
-
- PLATFORM_ASSERT(line < model.pdoc->LinesTotal());
- PLATFORM_ASSERT(ll->chars != NULL);
- int posLineStart = model.pdoc->LineStart(line);
- int posLineEnd = model.pdoc->LineStart(line + 1);
- // If the line is very long, limit the treatment to a length that should fit in the viewport
- if (posLineEnd >(posLineStart + ll->maxLineLength)) {
- posLineEnd = posLineStart + ll->maxLineLength;
- }
- if (ll->validity == LineLayout::llCheckTextAndStyle) {
- int lineLength = posLineEnd - posLineStart;
- if (!vstyle.viewEOL) {
- lineLength = model.pdoc->LineEnd(line) - posLineStart;
- }
- if (lineLength == ll->numCharsInLine) {
- // See if chars, styles, indicators, are all the same
- bool allSame = true;
- // Check base line layout
- char styleByte = 0;
- int numCharsInLine = 0;
- while (numCharsInLine < lineLength) {
- int charInDoc = numCharsInLine + posLineStart;
- char chDoc = model.pdoc->CharAt(charInDoc);
- styleByte = model.pdoc->StyleAt(charInDoc);
- allSame = allSame &&
- (ll->styles[numCharsInLine] == static_cast<unsigned char>(styleByte));
- if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseMixed)
- allSame = allSame &&
- (ll->chars[numCharsInLine] == chDoc);
- else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower)
- allSame = allSame &&
- (ll->chars[numCharsInLine] == static_cast<char>(tolower(chDoc)));
- else // Style::caseUpper
- allSame = allSame &&
- (ll->chars[numCharsInLine] == static_cast<char>(toupper(chDoc)));
- numCharsInLine++;
- }
- allSame = allSame && (ll->styles[numCharsInLine] == styleByte); // For eolFilled
- if (allSame) {
- ll->validity = LineLayout::llPositions;
- } else {
- ll->validity = LineLayout::llInvalid;
- }
- } else {
- ll->validity = LineLayout::llInvalid;
- }
- }
- if (ll->validity == LineLayout::llInvalid) {
- ll->widthLine = LineLayout::wrapWidthInfinite;
- ll->lines = 1;
- if (vstyle.edgeState == EDGE_BACKGROUND) {
- ll->edgeColumn = model.pdoc->FindColumn(line, vstyle.theEdge);
- if (ll->edgeColumn >= posLineStart) {
- ll->edgeColumn -= posLineStart;
- }
- } else {
- ll->edgeColumn = -1;
- }
-
- // Fill base line layout
- const int lineLength = posLineEnd - posLineStart;
- model.pdoc->GetCharRange(ll->chars, posLineStart, lineLength);
- model.pdoc->GetStyleRange(ll->styles, posLineStart, lineLength);
- int numCharsBeforeEOL = model.pdoc->LineEnd(line) - posLineStart;
- const int numCharsInLine = (vstyle.viewEOL) ? lineLength : numCharsBeforeEOL;
- for (int styleInLine = 0; styleInLine < numCharsInLine; styleInLine++) {
- const unsigned char styleByte = ll->styles[styleInLine];
- ll->styles[styleInLine] = styleByte;
- }
- const unsigned char styleByteLast = (lineLength > 0) ? ll->styles[lineLength - 1] : 0;
- if (vstyle.someStylesForceCase) {
- for (int charInLine = 0; charInLine<lineLength; charInLine++) {
- char chDoc = ll->chars[charInLine];
- if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseUpper)
- ll->chars[charInLine] = static_cast<char>(toupper(chDoc));
- else if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseLower)
- ll->chars[charInLine] = static_cast<char>(tolower(chDoc));
- }
- }
- ll->xHighlightGuide = 0;
- // Extra element at the end of the line to hold end x position and act as
- ll->chars[numCharsInLine] = 0; // Also triggers processing in the loops as this is a control character
- ll->styles[numCharsInLine] = styleByteLast; // For eolFilled
-
- // Layout the line, determining the position of each character,
- // with an extra element at the end for the end of the line.
- ll->positions[0] = 0;
- bool lastSegItalics = false;
-
- BreakFinder bfLayout(ll, NULL, Range(0, numCharsInLine), posLineStart, 0, false, model.pdoc, &model.reprs);
- while (bfLayout.More()) {
-
- const TextSegment ts = bfLayout.Next();
-
- std::fill(&ll->positions[ts.start + 1], &ll->positions[ts.end() + 1], 0.0f);
- if (vstyle.styles[ll->styles[ts.start]].visible) {
- if (ts.representation) {
- XYPOSITION representationWidth = vstyle.controlCharWidth;
- if (ll->chars[ts.start] == '\t') {
- // Tab is a special case of representation, taking a variable amount of space
- representationWidth =
- ((static_cast<int>((ll->positions[ts.start] + 2) / vstyle.tabWidth) + 1) * vstyle.tabWidth) - ll->positions[ts.start];
- } else {
- if (representationWidth <= 0.0) {
- XYPOSITION positionsRepr[256]; // Should expand when needed
- posCache.MeasureWidths(surface, vstyle, STYLE_CONTROLCHAR, ts.representation->stringRep.c_str(),
- static_cast<unsigned int>(ts.representation->stringRep.length()), positionsRepr, model.pdoc);
- representationWidth = positionsRepr[ts.representation->stringRep.length() - 1] + vstyle.ctrlCharPadding;
- }
- }
- for (int ii = 0; ii < ts.length; ii++)
- ll->positions[ts.start + 1 + ii] = representationWidth;
- } else {
- if ((ts.length == 1) && (' ' == ll->chars[ts.start])) {
- // Over half the segments are single characters and of these about half are space characters.
- ll->positions[ts.start + 1] = vstyle.styles[ll->styles[ts.start]].spaceWidth;
- } else {
- posCache.MeasureWidths(surface, vstyle, ll->styles[ts.start], ll->chars + ts.start,
- ts.length, ll->positions + ts.start + 1, model.pdoc);
- }
- }
- lastSegItalics = (!ts.representation) && ((ll->chars[ts.end() - 1] != ' ') && vstyle.styles[ll->styles[ts.start]].italic);
- }
-
- for (int posToIncrease = ts.start + 1; posToIncrease <= ts.end(); posToIncrease++) {
- ll->positions[posToIncrease] += ll->positions[ts.start];
- }
- }
-
- // Small hack to make lines that end with italics not cut off the edge of the last character
- if (lastSegItalics) {
- ll->positions[numCharsInLine] += vstyle.lastSegItalicsOffset;
- }
- ll->numCharsInLine = numCharsInLine;
- ll->numCharsBeforeEOL = numCharsBeforeEOL;
- ll->validity = LineLayout::llPositions;
- }
- // Hard to cope when too narrow, so just assume there is space
- if (width < 20) {
- width = 20;
- }
- if ((ll->validity == LineLayout::llPositions) || (ll->widthLine != width)) {
- ll->widthLine = width;
- if (width == LineLayout::wrapWidthInfinite) {
- ll->lines = 1;
- } else if (width > ll->positions[ll->numCharsInLine]) {
- // Simple common case where line does not need wrapping.
- ll->lines = 1;
- } else {
- if (vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_END) {
- width -= static_cast<int>(vstyle.aveCharWidth); // take into account the space for end wrap mark
- }
- XYPOSITION wrapAddIndent = 0; // This will be added to initial indent of line
- if (vstyle.wrapIndentMode == SC_WRAPINDENT_INDENT) {
- wrapAddIndent = model.pdoc->IndentSize() * vstyle.spaceWidth;
- } else if (vstyle.wrapIndentMode == SC_WRAPINDENT_FIXED) {
- wrapAddIndent = vstyle.wrapVisualStartIndent * vstyle.aveCharWidth;
- }
- ll->wrapIndent = wrapAddIndent;
- if (vstyle.wrapIndentMode != SC_WRAPINDENT_FIXED)
- for (int i = 0; i < ll->numCharsInLine; i++) {
- if (!IsSpaceOrTab(ll->chars[i])) {
- ll->wrapIndent += ll->positions[i]; // Add line indent
- break;
- }
- }
- // Check for text width minimum
- if (ll->wrapIndent > width - static_cast<int>(vstyle.aveCharWidth) * 15)
- ll->wrapIndent = wrapAddIndent;
- // Check for wrapIndent minimum
- if ((vstyle.wrapVisualFlags & SC_WRAPVISUALFLAG_START) && (ll->wrapIndent < vstyle.aveCharWidth))
- ll->wrapIndent = vstyle.aveCharWidth; // Indent to show start visual
- ll->lines = 0;
- // Calculate line start positions based upon width.
- int lastGoodBreak = 0;
- int lastLineStart = 0;
- XYACCUMULATOR startOffset = 0;
- int p = 0;
- while (p < ll->numCharsInLine) {
- if ((ll->positions[p + 1] - startOffset) >= width) {
- if (lastGoodBreak == lastLineStart) {
- // Try moving to start of last character
- if (p > 0) {
- lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1)
- - posLineStart;
- }
- if (lastGoodBreak == lastLineStart) {
- // Ensure at least one character on line.
- lastGoodBreak = model.pdoc->MovePositionOutsideChar(lastGoodBreak + posLineStart + 1, 1)
- - posLineStart;
- }
- }
- lastLineStart = lastGoodBreak;
- ll->lines++;
- ll->SetLineStart(ll->lines, lastGoodBreak);
- startOffset = ll->positions[lastGoodBreak];
- // take into account the space for start wrap mark and indent
- startOffset -= ll->wrapIndent;
- p = lastGoodBreak + 1;
- continue;
- }
- if (p > 0) {
- if (vstyle.wrapState == eWrapChar) {
- lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1)
- - posLineStart;
- p = model.pdoc->MovePositionOutsideChar(p + 1 + posLineStart, 1) - posLineStart;
- continue;
- } else if ((vstyle.wrapState == eWrapWord) && (ll->styles[p] != ll->styles[p - 1])) {
- lastGoodBreak = p;
- } else if (IsSpaceOrTab(ll->chars[p - 1]) && !IsSpaceOrTab(ll->chars[p])) {
- lastGoodBreak = p;
- }
- }
- p++;
- }
- ll->lines++;
- }
- ll->validity = LineLayout::llLines;
- }
-}
-
-Point EditView::LocationFromPosition(Surface *surface, SelectionPosition pos, int topLine, const EditModel &model, const ViewStyle &vs) {
- Point pt;
- if (pos.Position() == INVALID_POSITION)
- return pt;
- const int line = model.pdoc->LineFromPosition(pos.Position());
- const int lineVisible = model.cs.DisplayFromDoc(line);
- //Platform::DebugPrintf("line=%d\n", line);
- AutoLineLayout ll(llc, RetrieveLineLayout(line, model));
- if (surface && ll) {
- const int posLineStart = model.pdoc->LineStart(line);
- LayoutLine(line, surface, vs, ll, model, model.wrapWidth);
- const int posInLine = pos.Position() - posLineStart;
- pt = ll->PointFromPosition(posInLine, vs.lineHeight);
- pt.y += (lineVisible - topLine) * vs.lineHeight;
- pt.x += vs.textStart - model.xOffset;
- }
- pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth;
- return pt;
-}
-
-SelectionPosition EditView::SPositionFromLocation(Surface *surface, Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace, const EditModel &model, const ViewStyle &vs) {
- pt.x = pt.x - vs.textStart;
- int visibleLine = static_cast<int>(floor(pt.y / vs.lineHeight));
- if (!canReturnInvalid && (visibleLine < 0))
- visibleLine = 0;
- const int lineDoc = model.cs.DocFromDisplay(visibleLine);
- if (canReturnInvalid && (lineDoc < 0))
- return SelectionPosition(INVALID_POSITION);
- if (lineDoc >= model.pdoc->LinesTotal())
- return SelectionPosition(canReturnInvalid ? INVALID_POSITION : model.pdoc->Length());
- const int posLineStart = model.pdoc->LineStart(lineDoc);
- AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model));
- if (surface && ll) {
- LayoutLine(lineDoc, surface, vs, ll, model, model.wrapWidth);
- const int lineStartSet = model.cs.DisplayFromDoc(lineDoc);
- const int subLine = visibleLine - lineStartSet;
- if (subLine < ll->lines) {
- const Range rangeSubLine = ll->SubLineRange(subLine);
- const XYPOSITION subLineStart = ll->positions[rangeSubLine.start];
- if (subLine > 0) // Wrapped
- pt.x -= ll->wrapIndent;
- const int positionInLine = ll->FindPositionFromX(pt.x + subLineStart, rangeSubLine, charPosition);
- if (positionInLine < rangeSubLine.end) {
- return SelectionPosition(model.pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1));
- }
- if (virtualSpace) {
- const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth;
- const int spaceOffset = static_cast<int>(
- (pt.x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth);
- return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset);
- } else if (canReturnInvalid) {
- if (pt.x < (ll->positions[rangeSubLine.end] - subLineStart)) {
- return SelectionPosition(model.pdoc->MovePositionOutsideChar(rangeSubLine.end + posLineStart, 1));
- }
- } else {
- return SelectionPosition(rangeSubLine.end + posLineStart);
- }
- }
- if (!canReturnInvalid)
- return SelectionPosition(ll->numCharsInLine + posLineStart);
- }
- return SelectionPosition(canReturnInvalid ? INVALID_POSITION : posLineStart);
-}
-
-/**
-* Find the document position corresponding to an x coordinate on a particular document line.
-* Ensure is between whole characters when document is in multi-byte or UTF-8 mode.
-* This method is used for rectangular selections and does not work on wrapped lines.
-*/
-SelectionPosition EditView::SPositionFromLineX(Surface *surface, int lineDoc, int x, const EditModel &model, const ViewStyle &vs) {
- AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model));
- if (surface && ll) {
- const int posLineStart = model.pdoc->LineStart(lineDoc);
- LayoutLine(lineDoc, surface, vs, ll, model, model.wrapWidth);
- const Range rangeSubLine = ll->SubLineRange(0);
- const XYPOSITION subLineStart = ll->positions[rangeSubLine.start];
- const int positionInLine = ll->FindPositionFromX(x + subLineStart, rangeSubLine, false);
- if (positionInLine < rangeSubLine.end) {
- return SelectionPosition(model.pdoc->MovePositionOutsideChar(positionInLine + posLineStart, 1));
- }
- const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth;
- const int spaceOffset = static_cast<int>(
- (x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth);
- return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset);
- }
- return SelectionPosition(0);
-}
-
-int EditView::DisplayFromPosition(Surface *surface, int pos, const EditModel &model, const ViewStyle &vs) {
- int lineDoc = model.pdoc->LineFromPosition(pos);
- int lineDisplay = model.cs.DisplayFromDoc(lineDoc);
- AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc, model));
- if (surface && ll) {
- LayoutLine(lineDoc, surface, vs, ll, model, model.wrapWidth);
- unsigned int posLineStart = model.pdoc->LineStart(lineDoc);
- int posInLine = pos - posLineStart;
- lineDisplay--; // To make up for first increment ahead.
- for (int subLine = 0; subLine < ll->lines; subLine++) {
- if (posInLine >= ll->LineStart(subLine)) {
- lineDisplay++;
- }
- }
- }
- return lineDisplay;
-}
-
-int EditView::StartEndDisplayLine(Surface *surface, int pos, bool start, const EditModel &model, const ViewStyle &vs) {
- int line = model.pdoc->LineFromPosition(pos);
- AutoLineLayout ll(llc, RetrieveLineLayout(line, model));
- int posRet = INVALID_POSITION;
- if (surface && ll) {
- unsigned int posLineStart = model.pdoc->LineStart(line);
- LayoutLine(line, surface, vs, ll, model, model.wrapWidth);
- int posInLine = pos - posLineStart;
- if (posInLine <= ll->maxLineLength) {
- for (int subLine = 0; subLine < ll->lines; subLine++) {
- if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) {
- if (start) {
- posRet = ll->LineStart(subLine) + posLineStart;
- } else {
- if (subLine == ll->lines - 1)
- posRet = ll->LineStart(subLine + 1) + posLineStart;
- else
- posRet = ll->LineStart(subLine + 1) + posLineStart - 1;
- }
- }
- }
- }
- }
- return posRet;
-}
-
-static ColourDesired SelectionBackground(const ViewStyle &vsDraw, bool main, bool primarySelection) {
- return main ?
- (primarySelection ? vsDraw.selColours.back : vsDraw.selBackground2) :
- vsDraw.selAdditionalBackground;
-}
-
-static ColourDesired TextBackground(const ViewStyle &vsDraw,
- ColourOptional background, int inSelection, bool inHotspot, int styleMain, int i,
- LineLayout *ll, const EditModel &model) {
- if (inSelection == 1) {
- if (vsDraw.selColours.back.isSet && (vsDraw.selAlpha == SC_ALPHA_NOALPHA)) {
- return SelectionBackground(vsDraw, true, model.primarySelection);
- }
- } else if (inSelection == 2) {
- if (vsDraw.selColours.back.isSet && (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA)) {
- return SelectionBackground(vsDraw, false, model.primarySelection);
- }
- } else {
- if ((vsDraw.edgeState == EDGE_BACKGROUND) &&
- (i >= ll->edgeColumn) &&
- (i < ll->numCharsBeforeEOL))
- return vsDraw.edgecolour;
- if (inHotspot && vsDraw.hotspotColours.back.isSet)
- return vsDraw.hotspotColours.back;
- }
- if (background.isSet && (styleMain != STYLE_BRACELIGHT) && (styleMain != STYLE_BRACEBAD)) {
- return background;
- } else {
- return vsDraw.styles[styleMain].back;
- }
-}
-
-void EditView::DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight) {
- Point from = Point::FromInts(0, ((lineVisible & 1) && (lineHeight & 1)) ? 1 : 0);
- PRectangle rcCopyArea = PRectangle::FromInts(start + 1, static_cast<int>(rcSegment.top), start + 2, static_cast<int>(rcSegment.bottom));
- surface->Copy(rcCopyArea, from,
- highlight ? *pixmapIndentGuideHighlight : *pixmapIndentGuide);
-}
-
-static void SimpleAlphaRectangle(Surface *surface, PRectangle rc, ColourDesired fill, int alpha) {
- if (alpha != SC_ALPHA_NOALPHA) {
- surface->AlphaRectangle(rc, 0, fill, alpha, fill, alpha, 0);
- }
-}
-
-void DrawTextBlob(Surface *surface, const ViewStyle &vsDraw, PRectangle rcSegment,
- const char *s, ColourDesired textBack, ColourDesired textFore, bool twoPhaseDraw) {
- if (!twoPhaseDraw) {
- surface->FillRectangle(rcSegment, textBack);
- }
- FontAlias ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;
- int normalCharHeight = static_cast<int>(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, static_cast<int>(s ? strlen(s) : 0),
- textBack, textFore);
-}
-
-void EditView::DrawEOL(Surface *surface, const ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll,
- int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart,
- ColourOptional background, const EditModel &model) {
-
- const int posLineStart = model.pdoc->LineStart(line);
- PRectangle rcSegment = rcLine;
-
- const bool lastSubLine = subLine == (ll->lines - 1);
- XYPOSITION virtualSpace = 0;
- if (lastSubLine) {
- const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
- virtualSpace = model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line)) * spaceWidth;
- }
- XYPOSITION xEol = static_cast<XYPOSITION>(ll->positions[lineEnd] - subLineStart);
-
- // Fill the virtual space and show selections within it
- if (virtualSpace) {
- rcSegment.left = xEol + xStart;
- rcSegment.right = xEol + xStart + virtualSpace;
- surface->FillRectangle(rcSegment, background.isSet ? background : vsDraw.styles[ll->styles[ll->numCharsInLine]].back);
- if (!hideSelection && ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA))) {
- SelectionSegment virtualSpaceRange(SelectionPosition(model.pdoc->LineEnd(line)), SelectionPosition(model.pdoc->LineEnd(line), model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line))));
- for (size_t r = 0; r<model.sel.Count(); r++) {
- int alpha = (r == model.sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
- if (alpha == SC_ALPHA_NOALPHA) {
- SelectionSegment portion = model.sel.Range(r).Intersect(virtualSpaceRange);
- if (!portion.Empty()) {
- const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
- rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] -
- static_cast<XYPOSITION>(subLineStart)+portion.start.VirtualSpace() * spaceWidth;
- rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] -
- static_cast<XYPOSITION>(subLineStart)+portion.end.VirtualSpace() * spaceWidth;
- rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left;
- rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right;
- surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, r == model.sel.Main(), model.primarySelection));
- }
- }
- }
- }
- }
-
- int eolInSelection = 0;
- int alpha = SC_ALPHA_NOALPHA;
- if (!hideSelection) {
- int posAfterLineEnd = model.pdoc->LineStart(line + 1);
- eolInSelection = (subLine == (ll->lines - 1)) ? model.sel.InSelectionForEOL(posAfterLineEnd) : 0;
- alpha = (eolInSelection == 1) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
- }
-
- // Draw the [CR], [LF], or [CR][LF] blobs if visible line ends are on
- XYPOSITION blobsWidth = 0;
- if (lastSubLine) {
- for (int eolPos = ll->numCharsBeforeEOL; eolPos<ll->numCharsInLine; eolPos++) {
- rcSegment.left = xStart + ll->positions[eolPos] - static_cast<XYPOSITION>(subLineStart)+virtualSpace;
- rcSegment.right = xStart + ll->positions[eolPos + 1] - static_cast<XYPOSITION>(subLineStart)+virtualSpace;
- blobsWidth += rcSegment.Width();
- char hexits[4];
- const char *ctrlChar;
- unsigned char chEOL = ll->chars[eolPos];
- int styleMain = ll->styles[eolPos];
- ColourDesired textBack = TextBackground(vsDraw, background, eolInSelection, false, styleMain, eolPos, ll, model);
- if (UTF8IsAscii(chEOL)) {
- ctrlChar = ControlCharacterString(chEOL);
- } else {
- const Representation *repr = model.reprs.RepresentationFromCharacter(ll->chars + eolPos, ll->numCharsInLine - eolPos);
- if (repr) {
- ctrlChar = repr->stringRep.c_str();
- eolPos = ll->numCharsInLine;
- } else {
- sprintf(hexits, "x%2X", chEOL);
- ctrlChar = hexits;
- }
- }
- ColourDesired textFore = vsDraw.styles[styleMain].fore;
- if (eolInSelection && vsDraw.selColours.fore.isSet) {
- textFore = (eolInSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground;
- }
- if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1)) {
- if (alpha == SC_ALPHA_NOALPHA) {
- surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection));
- } else {
- surface->FillRectangle(rcSegment, textBack);
- }
- } else {
- surface->FillRectangle(rcSegment, textBack);
- }
- DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, twoPhaseDraw);
- if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
- SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha);
- }
- }
- }
-
- // Draw the eol-is-selected rectangle
- rcSegment.left = xEol + xStart + virtualSpace + blobsWidth;
- rcSegment.right = rcSegment.left + vsDraw.aveCharWidth;
-
- if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) {
- surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection));
- } else {
- if (background.isSet) {
- surface->FillRectangle(rcSegment, background);
- } else if (line < model.pdoc->LinesTotal() - 1) {
- surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back);
- } else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) {
- surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back);
- } else {
- surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back);
- }
- if (eolInSelection && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
- SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha);
- }
- }
-
- // Fill the remainder of the line
- rcSegment.left = rcSegment.right;
- if (rcSegment.left < rcLine.left)
- rcSegment.left = rcLine.left;
- rcSegment.right = rcLine.right;
-
- if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) {
- surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection));
- } else {
- if (background.isSet) {
- surface->FillRectangle(rcSegment, background);
- } else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) {
- surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine]].back);
- } else {
- surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back);
- }
- if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < model.pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
- SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1, model.primarySelection), alpha);
- }
- }
-
- bool drawWrapMarkEnd = false;
-
- if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_END) {
- if (subLine + 1 < ll->lines) {
- drawWrapMarkEnd = ll->LineStart(subLine + 1) != 0;
- }
- }
-
- if (drawWrapMarkEnd) {
- PRectangle rcPlace = rcSegment;
-
- if (vsDraw.wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_END_BY_TEXT) {
- rcPlace.left = xEol + xStart + virtualSpace;
- rcPlace.right = rcPlace.left + vsDraw.aveCharWidth;
- } else {
- // rcLine is clipped to text area
- rcPlace.right = rcLine.right;
- rcPlace.left = rcPlace.right - vsDraw.aveCharWidth;
- }
- DrawWrapMarker(surface, rcPlace, true, vsDraw.WrapColour());
- }
-}
-
-static void DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, const ViewStyle &vsDraw,
- int xStart, PRectangle rcLine, LineLayout *ll, int subLine) {
- const XYPOSITION subLineStart = ll->positions[ll->LineStart(subLine)];
- PRectangle rcIndic(
- ll->positions[startPos] + xStart - subLineStart,
- rcLine.top + vsDraw.maxAscent,
- ll->positions[endPos] + xStart - subLineStart,
- rcLine.top + vsDraw.maxAscent + 3);
- vsDraw.indicators[indicNum].Draw(surface, rcIndic, rcLine);
-}
-
-static void DrawIndicators(Surface *surface, const ViewStyle &vsDraw, int line, int xStart,
- PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under, const EditModel &model) {
- // Draw decorators
- const int posLineStart = model.pdoc->LineStart(line);
- const int lineStart = ll->LineStart(subLine);
- const int posLineEnd = posLineStart + lineEnd;
-
- for (Decoration *deco = model.pdoc->decorations.root; deco; deco = deco->next) {
- if (under == vsDraw.indicators[deco->indicator].under) {
- int startPos = posLineStart + lineStart;
- if (!deco->rs.ValueAt(startPos)) {
- startPos = deco->rs.EndRun(startPos);
- }
- while ((startPos < posLineEnd) && (deco->rs.ValueAt(startPos))) {
- int endPos = deco->rs.EndRun(startPos);
- if (endPos > posLineEnd)
- endPos = posLineEnd;
- DrawIndicator(deco->indicator, startPos - posLineStart, endPos - posLineStart,
- surface, vsDraw, xStart, rcLine, ll, subLine);
- startPos = endPos;
- if (!deco->rs.ValueAt(startPos)) {
- startPos = deco->rs.EndRun(startPos);
- }
- }
- }
- }
-
- // Use indicators to highlight matching braces
- if ((vsDraw.braceHighlightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACELIGHT)) ||
- (vsDraw.braceBadLightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACEBAD))) {
- int braceIndicator = (model.bracesMatchStyle == STYLE_BRACELIGHT) ? vsDraw.braceHighlightIndicator : vsDraw.braceBadLightIndicator;
- if (under == vsDraw.indicators[braceIndicator].under) {
- Range rangeLine(posLineStart + lineStart, posLineEnd);
- if (rangeLine.ContainsCharacter(model.braces[0])) {
- int braceOffset = model.braces[0] - posLineStart;
- if (braceOffset < ll->numCharsInLine) {
- DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine);
- }
- }
- if (rangeLine.ContainsCharacter(model.braces[1])) {
- int braceOffset = model.braces[1] - posLineStart;
- if (braceOffset < ll->numCharsInLine) {
- DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine);
- }
- }
- }
- }
-}
-
-void EditView::DrawAnnotation(Surface *surface, const ViewStyle &vsDraw, int line, int xStart,
- PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model) {
- int indent = static_cast<int>(model.pdoc->GetLineIndentation(line) * vsDraw.spaceWidth);
- PRectangle rcSegment = rcLine;
- int annotationLine = subLine - ll->lines;
- const StyledText stAnnotation = model.pdoc->AnnotationStyledText(line);
- if (stAnnotation.text && ValidStyledText(vsDraw, vsDraw.annotationStyleOffset, stAnnotation)) {
- surface->FillRectangle(rcSegment, vsDraw.styles[0].back);
- rcSegment.left = static_cast<XYPOSITION>(xStart);
- if (model.trackLineWidth || (vsDraw.annotationVisible == ANNOTATION_BOXED)) {
- // Only care about calculating width if tracking or need to draw box
- int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation);
- if (vsDraw.annotationVisible == ANNOTATION_BOXED) {
- widthAnnotation += static_cast<int>(vsDraw.spaceWidth * 2); // Margins
- }
- if (widthAnnotation > lineWidthMaxSeen)
- lineWidthMaxSeen = widthAnnotation;
- if (vsDraw.annotationVisible == ANNOTATION_BOXED) {
- rcSegment.left = static_cast<XYPOSITION>(xStart + indent);
- rcSegment.right = rcSegment.left + widthAnnotation;
- }
- }
- const int annotationLines = model.pdoc->AnnotationLines(line);
- size_t start = 0;
- size_t lengthAnnotation = stAnnotation.LineLength(start);
- int lineInAnnotation = 0;
- while ((lineInAnnotation < annotationLine) && (start < stAnnotation.length)) {
- start += lengthAnnotation + 1;
- lengthAnnotation = stAnnotation.LineLength(start);
- lineInAnnotation++;
- }
- PRectangle rcText = rcSegment;
- if (vsDraw.annotationVisible == ANNOTATION_BOXED) {
- surface->FillRectangle(rcText,
- vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back);
- rcText.left += vsDraw.spaceWidth;
- }
- DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText,
- stAnnotation, start, lengthAnnotation);
- if (vsDraw.annotationVisible == ANNOTATION_BOXED) {
- surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore);
- surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.top));
- surface->LineTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.bottom));
- surface->MoveTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.top));
- surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.bottom));
- if (subLine == ll->lines) {
- surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.top));
- surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.top));
- }
- if (subLine == ll->lines + annotationLines - 1) {
- surface->MoveTo(static_cast<int>(rcSegment.left), static_cast<int>(rcSegment.bottom - 1));
- surface->LineTo(static_cast<int>(rcSegment.right), static_cast<int>(rcSegment.bottom - 1));
- }
- }
- }
-}
-
-static void DrawBlockCaret(Surface *surface, const ViewStyle &vsDraw, LineLayout *ll, int subLine,
- int xStart, int offset, int posCaret, PRectangle rcCaret, ColourDesired caretColour, const EditModel &model) {
-
- int lineStart = ll->LineStart(subLine);
- int posBefore = posCaret;
- int posAfter = model.pdoc->MovePositionOutsideChar(posCaret + 1, 1);
- int numCharsToDraw = posAfter - posCaret;
-
- // Work out where the starting and ending offsets are. We need to
- // see if the previous character shares horizontal space, such as a
- // glyph / combining character. If so we'll need to draw that too.
- int offsetFirstChar = offset;
- int offsetLastChar = offset + (posAfter - posCaret);
- while ((posBefore > 0) && ((offsetLastChar - numCharsToDraw) >= lineStart)) {
- if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - numCharsToDraw]) > 0) {
- // The char does not share horizontal space
- break;
- }
- // Char shares horizontal space, update the numChars to draw
- // Update posBefore to point to the prev char
- posBefore = model.pdoc->MovePositionOutsideChar(posBefore - 1, -1);
- numCharsToDraw = posAfter - posBefore;
- offsetFirstChar = offset - (posCaret - posBefore);
- }
-
- // See if the next character shares horizontal space, if so we'll
- // need to draw that too.
- if (offsetFirstChar < 0)
- offsetFirstChar = 0;
- numCharsToDraw = offsetLastChar - offsetFirstChar;
- while ((offsetLastChar < ll->LineStart(subLine + 1)) && (offsetLastChar <= ll->numCharsInLine)) {
- // Update posAfter to point to the 2nd next char, this is where
- // the next character ends, and 2nd next begins. We'll need
- // to compare these two
- posBefore = posAfter;
- posAfter = model.pdoc->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
- break;
- }
- // Char shares horizontal space, update the numChars to draw
- numCharsToDraw = offsetLastChar - offsetFirstChar;
- }
-
- // We now know what to draw, update the caret drawing rectangle
- rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[lineStart] + xStart;
- rcCaret.right = ll->positions[offsetFirstChar + numCharsToDraw] - ll->positions[lineStart] + xStart;
-
- // Adjust caret position to take into account any word wrapping symbols.
- if ((ll->wrapIndent != 0) && (lineStart != 0)) {
- XYPOSITION wordWrapCharWidth = ll->wrapIndent;
- rcCaret.left += wordWrapCharWidth;
- rcCaret.right += wordWrapCharWidth;
- }
-
- // This character is where the caret block is, we override the colours
- // (inversed) for drawing the caret here.
- int styleMain = ll->styles[offsetFirstChar];
- FontAlias fontText = vsDraw.styles[styleMain].font;
- surface->DrawTextClipped(rcCaret, fontText,
- rcCaret.top + vsDraw.maxAscent, ll->chars + offsetFirstChar,
- numCharsToDraw, vsDraw.styles[styleMain].back,
- caretColour);
-}
-
-void EditView::DrawCarets(Surface *surface, const ViewStyle &vsDraw, int lineDoc, int xStart,
- PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model) const {
- // When drag is active it is the only caret drawn
- bool drawDrag = model.posDrag.IsValid();
- if (hideSelection && !drawDrag)
- return;
- const int posLineStart = model.pdoc->LineStart(lineDoc);
- // For each selection draw
- for (size_t r = 0; (r<model.sel.Count()) || drawDrag; r++) {
- const bool mainCaret = r == model.sel.Main();
- const SelectionPosition posCaret = (drawDrag ? model.posDrag : model.sel.Range(r).caret);
- const int offset = posCaret.Position() - posLineStart;
- const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
- const XYPOSITION virtualOffset = posCaret.VirtualSpace() * spaceWidth;
- if (ll->InLine(offset, subLine) && offset <= ll->numCharsBeforeEOL) {
- XYPOSITION xposCaret = ll->positions[offset] + virtualOffset - ll->positions[ll->LineStart(subLine)];
- if (ll->wrapIndent != 0) {
- int lineStart = ll->LineStart(subLine);
- if (lineStart != 0) // Wrapped
- xposCaret += ll->wrapIndent;
- }
- bool caretBlinkState = (model.caret.active && model.caret.on) || (!additionalCaretsBlink && !mainCaret);
- bool caretVisibleState = additionalCaretsVisible || mainCaret;
- if ((xposCaret >= 0) && (vsDraw.caretWidth > 0) && (vsDraw.caretStyle != CARETSTYLE_INVISIBLE) &&
- ((model.posDrag.IsValid()) || (caretBlinkState && caretVisibleState))) {
- bool caretAtEOF = false;
- bool caretAtEOL = false;
- bool drawBlockCaret = false;
- XYPOSITION widthOverstrikeCaret;
- XYPOSITION caretWidthOffset = 0;
- PRectangle rcCaret = rcLine;
-
- if (posCaret.Position() == model.pdoc->Length()) { // At end of document
- caretAtEOF = true;
- widthOverstrikeCaret = vsDraw.aveCharWidth;
- } else if ((posCaret.Position() - posLineStart) >= ll->numCharsInLine) { // At end of line
- caretAtEOL = true;
- widthOverstrikeCaret = vsDraw.aveCharWidth;
- } else {
- widthOverstrikeCaret = ll->positions[offset + 1] - ll->positions[offset];
- }
- if (widthOverstrikeCaret < 3) // Make sure its visible
- widthOverstrikeCaret = 3;
-
- if (xposCaret > 0)
- caretWidthOffset = 0.51f; // Move back so overlaps both character cells.
- xposCaret += xStart;
- if (model.posDrag.IsValid()) {
- /* Dragging text, use a line caret */
- rcCaret.left = static_cast<XYPOSITION>(RoundXYPosition(xposCaret - caretWidthOffset));
- rcCaret.right = rcCaret.left + vsDraw.caretWidth;
- } else if (model.inOverstrike && drawOverstrikeCaret) {
- /* Overstrike (insert mode), use a modified bar caret */
- rcCaret.top = rcCaret.bottom - 2;
- rcCaret.left = xposCaret + 1;
- rcCaret.right = rcCaret.left + widthOverstrikeCaret - 1;
- } else if (vsDraw.caretStyle == CARETSTYLE_BLOCK) {
- /* Block caret */
- rcCaret.left = xposCaret;
- if (!caretAtEOL && !caretAtEOF && (ll->chars[offset] != '\t') && !(IsControlCharacter(ll->chars[offset]))) {
- drawBlockCaret = true;
- rcCaret.right = xposCaret + widthOverstrikeCaret;
- } else {
- rcCaret.right = xposCaret + vsDraw.aveCharWidth;
- }
- } else {
- /* Line caret */
- rcCaret.left = static_cast<XYPOSITION>(RoundXYPosition(xposCaret - caretWidthOffset));
- rcCaret.right = rcCaret.left + vsDraw.caretWidth;
- }
- ColourDesired caretColour = mainCaret ? vsDraw.caretcolour : vsDraw.additionalCaretColour;
- if (drawBlockCaret) {
- DrawBlockCaret(surface, vsDraw, ll, subLine, xStart, offset, posCaret.Position(), rcCaret, caretColour, model);
- } else {
- surface->FillRectangle(rcCaret, caretColour);
- }
- }
- }
- if (drawDrag)
- break;
- }
-}
-
-void EditView::DrawLine(Surface *surface, const ViewStyle &vsDraw, int line, int lineVisible, int xStart,
- PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model) {
-
- if (subLine >= ll->lines) {
- DrawAnnotation(surface, vsDraw, line, xStart, rcLine, ll, subLine, model);
- return; // No further drawing
- }
-
- // Using one font for all control characters so it can be controlled independently to ensure
- // the box goes around the characters tightly. Seems to be no way to work out what height
- // is taken by an individual character - internal leading gives varying results.
- FontAlias ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;
-
- // See if something overrides the line background color.
- const ColourOptional background = vsDraw.Background(model.pdoc->GetMark(line), model.caret.active, ll->containsCaret);
-
- const bool drawWhitespaceBackground = (vsDraw.viewWhitespace != wsInvisible) &&
- (!background.isSet) && (vsDraw.whitespaceColours.back.isSet);
-
- const XYPOSITION indentWidth = model.pdoc->IndentSize() * vsDraw.spaceWidth;
-
- const int posLineStart = model.pdoc->LineStart(line);
-
- const Range lineRange = ll->SubLineRange(subLine);
- const XYACCUMULATOR subLineStart = ll->positions[lineRange.start];
-
- if ((ll->wrapIndent != 0) && (subLine > 0) && (subLine < ll->lines)) {
- // default bgnd here..
- surface->FillRectangle(rcLine, background.isSet ? background :
- vsDraw.styles[STYLE_DEFAULT].back);
-
- if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_START) {
-
- // draw continuation rect
- PRectangle rcPlace = rcLine;
-
- rcPlace.left = static_cast<XYPOSITION>(xStart);
- rcPlace.right = rcPlace.left + ll->wrapIndent;
-
- if (vsDraw.wrapVisualFlagsLocation & SC_WRAPVISUALFLAGLOC_START_BY_TEXT)
- rcPlace.left = rcPlace.right - vsDraw.aveCharWidth;
- else
- rcPlace.right = rcPlace.left + vsDraw.aveCharWidth;
-
- DrawWrapMarker(surface, rcPlace, false, vsDraw.WrapColour());
- }
-
- xStart += static_cast<int>(ll->wrapIndent);
- }
-
- const bool selBackDrawn = vsDraw.selColours.back.isSet &&
- ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA));
-
- // Does not take margin into account but not significant
- const int xStartVisible = static_cast<int>(subLineStart)-xStart;
-
- if (twoPhaseDraw) {
- bool inIndentation = subLine == 0; // Do not handle indentation except on first subline.
- BreakFinder bfBack(ll, &model.sel, lineRange, posLineStart, xStartVisible, selBackDrawn, model.pdoc, &model.reprs);
-
- // Background drawing loop
- while (bfBack.More()) {
-
- const TextSegment ts = bfBack.Next();
- const int i = ts.end() - 1;
- const int iDoc = i + posLineStart;
-
- PRectangle rcSegment = rcLine;
- rcSegment.left = ll->positions[ts.start] + xStart - static_cast<XYPOSITION>(subLineStart);
- rcSegment.right = ll->positions[ts.end()] + xStart - static_cast<XYPOSITION>(subLineStart);
- // Only try to draw if really visible - enhances performance by not calling environment to
- // draw strings that are completely past the right side of the window.
- if (rcSegment.Intersects(rcLine)) {
- // Clip to line rectangle, since may have a huge position which will not work with some platforms
- if (rcSegment.left < rcLine.left)
- rcSegment.left = rcLine.left;
- if (rcSegment.right > rcLine.right)
- rcSegment.right = rcLine.right;
-
- const int inSelection = hideSelection ? 0 : model.sel.CharacterInSelection(iDoc);
- const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc);
- ColourDesired textBack = TextBackground(vsDraw, background, inSelection,
- inHotspot, ll->styles[i], i, ll, model);
- if (ts.representation) {
- if (ll->chars[i] == '\t') {
- // Tab display
- if (drawWhitespaceBackground &&
- (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways))
- textBack = vsDraw.whitespaceColours.back;
- } else {
- // Blob display
- inIndentation = false;
- }
- surface->FillRectangle(rcSegment, textBack);
- } else {
- // Normal text display
- surface->FillRectangle(rcSegment, textBack);
- if (vsDraw.viewWhitespace != wsInvisible ||
- (inIndentation && vsDraw.viewIndentationGuides == ivReal)) {
- for (int cpos = 0; cpos <= i - ts.start; cpos++) {
- if (ll->chars[cpos + ts.start] == ' ') {
- if (drawWhitespaceBackground &&
- (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {
- PRectangle rcSpace(
- ll->positions[cpos + ts.start] + xStart - static_cast<XYPOSITION>(subLineStart),
- rcSegment.top,
- ll->positions[cpos + ts.start + 1] + xStart - static_cast<XYPOSITION>(subLineStart),
- rcSegment.bottom);
- surface->FillRectangle(rcSpace, vsDraw.whitespaceColours.back);
- }
- } else {
- inIndentation = false;
- }
- }
- }
- }
- } else if (rcSegment.left > rcLine.right) {
- break;
- }
- }
-
- DrawEOL(surface, vsDraw, rcLine, ll, line, lineRange.end,
- xStart, subLine, subLineStart, background, model);
- }
-
- DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineRange.end, true, model);
-
- if (vsDraw.edgeState == EDGE_LINE) {
- PRectangle rcSegment = rcLine;
- int edgeX = static_cast<int>(vsDraw.theEdge * vsDraw.spaceWidth);
- rcSegment.left = static_cast<XYPOSITION>(edgeX + xStart);
- if ((ll->wrapIndent != 0) && (lineRange.start != 0))
- rcSegment.left -= ll->wrapIndent;
- rcSegment.right = rcSegment.left + 1;
- surface->FillRectangle(rcSegment, vsDraw.edgecolour);
- }
-
- // Draw underline mark as part of background if not transparent
- int marks = model.pdoc->GetMark(line);
- int markBit;
- for (markBit = 0; (markBit < 32) && marks; markBit++) {
- if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE) &&
- (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
- PRectangle rcUnderline = rcLine;
- rcUnderline.top = rcUnderline.bottom - 2;
- surface->FillRectangle(rcUnderline, vsDraw.markers[markBit].back);
- }
- marks >>= 1;
- }
-
- bool inIndentation = subLine == 0; // Do not handle indentation except on first subline.
- // Foreground drawing loop
- BreakFinder bfFore(ll, &model.sel, lineRange, posLineStart, xStartVisible,
- ((!twoPhaseDraw && selBackDrawn) || vsDraw.selColours.fore.isSet), model.pdoc, &model.reprs);
-
- while (bfFore.More()) {
-
- const TextSegment ts = bfFore.Next();
- const int i = ts.end() - 1;
- const int iDoc = i + posLineStart;
-
- PRectangle rcSegment = rcLine;
- rcSegment.left = ll->positions[ts.start] + xStart - static_cast<XYPOSITION>(subLineStart);
- rcSegment.right = ll->positions[ts.end()] + xStart - static_cast<XYPOSITION>(subLineStart);
- // Only try to draw if really visible - enhances performance by not calling environment to
- // draw strings that are completely past the right side of the window.
- if (rcSegment.Intersects(rcLine)) {
- int styleMain = ll->styles[i];
- ColourDesired textFore = vsDraw.styles[styleMain].fore;
- FontAlias textFont = vsDraw.styles[styleMain].font;
- //hotspot foreground
- const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc);
- if (inHotspot) {
- if (vsDraw.hotspotColours.fore.isSet)
- textFore = vsDraw.hotspotColours.fore;
- }
- const int inSelection = hideSelection ? 0 : model.sel.CharacterInSelection(iDoc);
- if (inSelection && (vsDraw.selColours.fore.isSet)) {
- textFore = (inSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground;
- }
- ColourDesired textBack = TextBackground(vsDraw, background, inSelection, inHotspot, styleMain, i, ll, model);
- if (ts.representation) {
- if (ll->chars[i] == '\t') {
- // Tab display
- if (!twoPhaseDraw) {
- if (drawWhitespaceBackground &&
- (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways))
- textBack = vsDraw.whitespaceColours.back;
- surface->FillRectangle(rcSegment, textBack);
- }
- if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
- for (int indentCount = static_cast<int>((ll->positions[i] + epsilon) / indentWidth);
- indentCount <= (ll->positions[i + 1] - epsilon) / indentWidth;
- indentCount++) {
- if (indentCount > 0) {
- int xIndent = static_cast<int>(indentCount * indentWidth);
- DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
- (ll->xHighlightGuide == xIndent));
- }
- }
- }
- if (vsDraw.viewWhitespace != wsInvisible) {
- if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
- if (vsDraw.whitespaceColours.fore.isSet)
- textFore = vsDraw.whitespaceColours.fore;
- surface->PenColour(textFore);
- PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4,
- rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
- DrawTabArrow(surface, rcTab, static_cast<int>(rcSegment.top + vsDraw.lineHeight / 2));
- }
- }
- } else {
- inIndentation = false;
- if (vsDraw.controlCharSymbol >= 32) {
- char cc[2] = { static_cast<char>(vsDraw.controlCharSymbol), '\0' };
- surface->DrawTextNoClip(rcSegment, ctrlCharsFont,
- rcSegment.top + vsDraw.maxAscent,
- cc, 1, textBack, textFore);
- } else {
- DrawTextBlob(surface, vsDraw, rcSegment, ts.representation->stringRep.c_str(), textBack, textFore, twoPhaseDraw);
- }
- }
- } else {
- // Normal text display
- if (vsDraw.styles[styleMain].visible) {
- if (twoPhaseDraw) {
- surface->DrawTextTransparent(rcSegment, textFont,
- rcSegment.top + vsDraw.maxAscent, ll->chars + ts.start,
- i - ts.start + 1, textFore);
- } else {
- surface->DrawTextNoClip(rcSegment, textFont,
- rcSegment.top + vsDraw.maxAscent, ll->chars + ts.start,
- i - ts.start + 1, textFore, textBack);
- }
- }
- if (vsDraw.viewWhitespace != wsInvisible ||
- (inIndentation && vsDraw.viewIndentationGuides != ivNone)) {
- for (int cpos = 0; cpos <= i - ts.start; cpos++) {
- if (ll->chars[cpos + ts.start] == ' ') {
- if (vsDraw.viewWhitespace != wsInvisible) {
- if (vsDraw.whitespaceColours.fore.isSet)
- textFore = vsDraw.whitespaceColours.fore;
- if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
- XYPOSITION xmid = (ll->positions[cpos + ts.start] + ll->positions[cpos + ts.start + 1]) / 2;
- if (!twoPhaseDraw && drawWhitespaceBackground &&
- (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) {
- textBack = vsDraw.whitespaceColours.back;
- PRectangle rcSpace(
- ll->positions[cpos + ts.start] + xStart - static_cast<XYPOSITION>(subLineStart),
- rcSegment.top,
- ll->positions[cpos + ts.start + 1] + xStart - static_cast<XYPOSITION>(subLineStart),
- rcSegment.bottom);
- surface->FillRectangle(rcSpace, textBack);
- }
- PRectangle rcDot(xmid + xStart - static_cast<XYPOSITION>(subLineStart),
- rcSegment.top + vsDraw.lineHeight / 2, 0.0f, 0.0f);
- rcDot.right = rcDot.left + vsDraw.whitespaceSize;
- rcDot.bottom = rcDot.top + vsDraw.whitespaceSize;
- surface->FillRectangle(rcDot, textFore);
- }
- }
- if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
- for (int indentCount = static_cast<int>((ll->positions[cpos + ts.start] + epsilon) / indentWidth);
- indentCount <= (ll->positions[cpos + ts.start + 1] - epsilon) / indentWidth;
- indentCount++) {
- if (indentCount > 0) {
- int xIndent = static_cast<int>(indentCount * indentWidth);
- DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
- (ll->xHighlightGuide == xIndent));
- }
- }
- }
- } else {
- inIndentation = false;
- }
- }
- }
- }
- if (ll->hotspot.Valid() && vsDraw.hotspotUnderline && ll->hotspot.ContainsCharacter(iDoc)) {
- PRectangle rcUL = rcSegment;
- rcUL.top = rcUL.top + vsDraw.maxAscent + 1;
- rcUL.bottom = rcUL.top + 1;
- if (vsDraw.hotspotColours.fore.isSet)
- surface->FillRectangle(rcUL, vsDraw.hotspotColours.fore);
- else
- surface->FillRectangle(rcUL, textFore);
- } else if (vsDraw.styles[styleMain].underline) {
- PRectangle rcUL = rcSegment;
- rcUL.top = rcUL.top + vsDraw.maxAscent + 1;
- rcUL.bottom = rcUL.top + 1;
- surface->FillRectangle(rcUL, textFore);
- }
- } else if (rcSegment.left > rcLine.right) {
- break;
- }
- }
- if ((vsDraw.viewIndentationGuides == ivLookForward || vsDraw.viewIndentationGuides == ivLookBoth)
- && (subLine == 0)) {
- int indentSpace = model.pdoc->GetLineIndentation(line);
- int xStartText = static_cast<int>(ll->positions[model.pdoc->GetLineIndentPosition(line) - posLineStart]);
-
- // Find the most recent line with some text
-
- int lineLastWithText = line;
- while (lineLastWithText > Platform::Maximum(line - 20, 0) && model.pdoc->IsWhiteLine(lineLastWithText)) {
- lineLastWithText--;
- }
- if (lineLastWithText < line) {
- xStartText = 100000; // Don't limit to visible indentation on empty line
- // This line is empty, so use indentation of last line with text
- int indentLastWithText = model.pdoc->GetLineIndentation(lineLastWithText);
- int isFoldHeader = model.pdoc->GetLevel(lineLastWithText) & SC_FOLDLEVELHEADERFLAG;
- if (isFoldHeader) {
- // Level is one more level than parent
- indentLastWithText += model.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 < Platform::Minimum(line + 20, model.pdoc->LinesTotal()) && model.pdoc->IsWhiteLine(lineNextWithText)) {
- lineNextWithText++;
- }
- if (lineNextWithText > line) {
- xStartText = 100000; // Don't limit to visible indentation on empty line
- // This line is empty, so use indentation of first next line with text
- indentSpace = Platform::Maximum(indentSpace,
- model.pdoc->GetLineIndentation(lineNextWithText));
- }
-
- for (int indentPos = model.pdoc->IndentSize(); indentPos < indentSpace; indentPos += model.pdoc->IndentSize()) {
- int xIndent = static_cast<int>(indentPos * vsDraw.spaceWidth);
- if (xIndent < xStartText) {
- DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcLine,
- (ll->xHighlightGuide == xIndent));
- }
- }
- }
-
- DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineRange.end, false, model);
-
- // End of the drawing of the current line
- if (!twoPhaseDraw) {
- DrawEOL(surface, vsDraw, rcLine, ll, line, lineRange.end,
- xStart, subLine, subLineStart, background, model);
- }
- if (!hideSelection && ((vsDraw.selAlpha != SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha != SC_ALPHA_NOALPHA))) {
- // For each selection draw
- int virtualSpaces = 0;
- if (subLine == (ll->lines - 1)) {
- virtualSpaces = model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line));
- }
- SelectionPosition posStart(posLineStart + lineRange.start);
- SelectionPosition posEnd(posLineStart + lineRange.end, virtualSpaces);
- SelectionSegment virtualSpaceRange(posStart, posEnd);
- for (size_t r = 0; r<model.sel.Count(); r++) {
- int alpha = (r == model.sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
- if (alpha != SC_ALPHA_NOALPHA) {
- SelectionSegment portion = model.sel.Range(r).Intersect(virtualSpaceRange);
- if (!portion.Empty()) {
- const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
- PRectangle rcSegment = rcLine;
- rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] -
- static_cast<XYPOSITION>(subLineStart)+portion.start.VirtualSpace() * spaceWidth;
- rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] -
- static_cast<XYPOSITION>(subLineStart)+portion.end.VirtualSpace() * spaceWidth;
- if ((ll->wrapIndent != 0) && (lineRange.start != 0)) {
- if ((portion.start.Position() - posLineStart) == lineRange.start && model.sel.Range(r).ContainsCharacter(portion.start.Position() - 1))
- rcSegment.left -= static_cast<int>(ll->wrapIndent); // indentation added to xStart was truncated to int, so we do the same here
- }
- rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left;
- rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right;
- if (rcSegment.right > rcLine.left)
- SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, r == model.sel.Main(), model.primarySelection), alpha);
- }
- }
- }
- }
-
- // Draw any translucent whole line states
- if ((model.caret.active || vsDraw.alwaysShowCaretLineBackground) && vsDraw.showCaretLineBackground && ll->containsCaret) {
- SimpleAlphaRectangle(surface, rcLine, vsDraw.caretLineBackground, vsDraw.caretLineAlpha);
- }
- marks = model.pdoc->GetMark(line);
- for (markBit = 0; (markBit < 32) && marks; markBit++) {
- if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND)) {
- SimpleAlphaRectangle(surface, rcLine, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha);
- } else if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE)) {
- PRectangle rcUnderline = rcLine;
- rcUnderline.top = rcUnderline.bottom - 2;
- SimpleAlphaRectangle(surface, rcUnderline, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha);
- }
- marks >>= 1;
- }
- if (vsDraw.maskInLine) {
- int marksMasked = model.pdoc->GetMark(line) & vsDraw.maskInLine;
- if (marksMasked) {
- for (markBit = 0; (markBit < 32) && marksMasked; markBit++) {
- if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY)) {
- SimpleAlphaRectangle(surface, rcLine, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha);
- }
- marksMasked >>= 1;
- }
- }
- }
-}
-
-void EditView::PaintText(Surface *surfaceWindow, PRectangle rcArea, PRectangle rcClient,
- const EditModel &model, const ViewStyle &vsDraw) {
- // Allow text at start of line to overlap 1 pixel into the margin as this displays
- // serifs and italic stems for aliased text.
- const int leftTextOverlap = ((model.xOffset == 0) && (vsDraw.leftMarginWidth > 0)) ? 1 : 0;
-
- // Do the painting
- if (rcArea.right > vsDraw.textStart - leftTextOverlap) {
-
- Surface *surface = surfaceWindow;
- if (bufferedDraw) {
- surface = pixmapLine;
- PLATFORM_ASSERT(pixmapLine->Initialised());
- }
- surface->SetUnicodeMode(SC_CP_UTF8 == model.pdoc->dbcsCodePage);
- surface->SetDBCSMode(model.pdoc->dbcsCodePage);
-
- Point ptOrigin = model.GetVisibleOriginInMain();
-
- int screenLinePaintFirst = static_cast<int>(rcArea.top) / vsDraw.lineHeight;
- int ypos = 0;
- if (!bufferedDraw)
- ypos += screenLinePaintFirst * vsDraw.lineHeight;
- int xStart = vsDraw.textStart - model.xOffset + static_cast<int>(ptOrigin.x);
-
- int visibleLine = model.TopLineOfMain() + screenLinePaintFirst;
- int yposScreen = screenLinePaintFirst * vsDraw.lineHeight;
-
- SelectionPosition posCaret = model.sel.RangeMain().caret;
- if (model.posDrag.IsValid())
- posCaret = model.posDrag;
- int lineCaret = model.pdoc->LineFromPosition(posCaret.Position());
-
- PRectangle rcTextArea = rcClient;
- if (vsDraw.marginInside) {
- rcTextArea.left += vsDraw.textStart;
- rcTextArea.right -= vsDraw.rightMarginWidth;
- } else {
- rcTextArea = rcArea;
- }
-
- // Remove selection margin from drawing area so text will not be drawn
- // on it in unbuffered mode.
- if (!bufferedDraw && vsDraw.marginInside) {
- PRectangle rcClipText = rcTextArea;
- rcClipText.left -= leftTextOverlap;
- surfaceWindow->SetClip(rcClipText);
- }
-
- // Loop on visible lines
- //double durLayout = 0.0;
- //double durPaint = 0.0;
- //double durCopy = 0.0;
- //ElapsedTime etWhole;
- int lineDocPrevious = -1; // Used to avoid laying out one document line multiple times
- AutoLineLayout ll(llc, 0);
- while (visibleLine < model.cs.LinesDisplayed() && yposScreen < rcArea.bottom) {
-
- int lineDoc = model.cs.DocFromDisplay(visibleLine);
- // Only visible lines should be handled by the code within the loop
- PLATFORM_ASSERT(model.cs.GetVisible(lineDoc));
- int lineStartSet = model.cs.DisplayFromDoc(lineDoc);
- int subLine = visibleLine - lineStartSet;
-
- // Copy this line and its styles from the document into local arrays
- // and determine the x position at which each character starts.
- //ElapsedTime et;
- if (lineDoc != lineDocPrevious) {
- ll.Set(0);
- ll.Set(RetrieveLineLayout(lineDoc, model));
- LayoutLine(lineDoc, surface, vsDraw, ll, model, model.wrapWidth);
- lineDocPrevious = lineDoc;
- }
- //durLayout += et.Duration(true);
-
- if (ll) {
- ll->containsCaret = lineDoc == lineCaret;
- if (hideSelection) {
- ll->containsCaret = false;
- }
-
- ll->hotspot = model.GetHotSpotRange();
-
- PRectangle rcLine = rcTextArea;
- rcLine.top = static_cast<XYPOSITION>(ypos);
- rcLine.bottom = static_cast<XYPOSITION>(ypos + vsDraw.lineHeight);
-
- bool bracesIgnoreStyle = false;
- if ((vsDraw.braceHighlightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACELIGHT)) ||
- (vsDraw.braceBadLightIndicatorSet && (model.bracesMatchStyle == STYLE_BRACEBAD))) {
- bracesIgnoreStyle = true;
- }
- Range rangeLine(model.pdoc->LineStart(lineDoc), model.pdoc->LineStart(lineDoc + 1));
- // Highlight the current braces if any
- ll->SetBracesHighlight(rangeLine, model.braces, static_cast<char>(model.bracesMatchStyle),
- static_cast<int>(model.highlightGuideColumn * vsDraw.spaceWidth), bracesIgnoreStyle);
-
- if (leftTextOverlap && bufferedDraw) {
- PRectangle rcSpacer = rcLine;
- rcSpacer.right = rcSpacer.left;
- rcSpacer.left -= 1;
- surface->FillRectangle(rcSpacer, vsDraw.styles[STYLE_DEFAULT].back);
- }
-
- // Draw the line
- DrawLine(surface, vsDraw, lineDoc, visibleLine, xStart, rcLine, ll, subLine, model);
- //durPaint += et.Duration(true);
-
- // Restore the previous styles for the brace highlights in case layout is in cache.
- ll->RestoreBracesHighlight(rangeLine, model.braces, bracesIgnoreStyle);
-
- bool expanded = model.cs.GetExpanded(lineDoc);
- const int level = model.pdoc->GetLevel(lineDoc);
- const int levelNext = model.pdoc->GetLevel(lineDoc + 1);
- if ((level & SC_FOLDLEVELHEADERFLAG) &&
- ((level & SC_FOLDLEVELNUMBERMASK) < (levelNext & SC_FOLDLEVELNUMBERMASK))) {
- // Paint the line above the fold
- if ((expanded && (model.foldFlags & SC_FOLDFLAG_LINEBEFORE_EXPANDED))
- ||
- (!expanded && (model.foldFlags & SC_FOLDFLAG_LINEBEFORE_CONTRACTED))) {
- PRectangle rcFoldLine = rcLine;
- rcFoldLine.bottom = rcFoldLine.top + 1;
- surface->FillRectangle(rcFoldLine, vsDraw.styles[STYLE_DEFAULT].fore);
- }
- // Paint the line below the fold
- if ((expanded && (model.foldFlags & SC_FOLDFLAG_LINEAFTER_EXPANDED))
- ||
- (!expanded && (model.foldFlags & SC_FOLDFLAG_LINEAFTER_CONTRACTED))) {
- PRectangle rcFoldLine = rcLine;
- rcFoldLine.top = rcFoldLine.bottom - 1;
- surface->FillRectangle(rcFoldLine, vsDraw.styles[STYLE_DEFAULT].fore);
- }
- }
-
- DrawCarets(surface, vsDraw, lineDoc, xStart, rcLine, ll, subLine, model);
-
- if (bufferedDraw) {
- Point from = Point::FromInts(vsDraw.textStart - leftTextOverlap, 0);
- PRectangle rcCopyArea = PRectangle::FromInts(vsDraw.textStart - leftTextOverlap, yposScreen,
- static_cast<int>(rcClient.right - vsDraw.rightMarginWidth),
- yposScreen + vsDraw.lineHeight);
- surfaceWindow->Copy(rcCopyArea, from, *pixmapLine);
- }
-
- lineWidthMaxSeen = Platform::Maximum(
- lineWidthMaxSeen, static_cast<int>(ll->positions[ll->numCharsInLine]));
- //durCopy += et.Duration(true);
- }
-
- if (!bufferedDraw) {
- ypos += vsDraw.lineHeight;
- }
-
- yposScreen += vsDraw.lineHeight;
- visibleLine++;
-
- //gdk_flush();
- }
- ll.Set(0);
- //if (durPaint < 0.00000001)
- // durPaint = 0.00000001;
-
- // Right column limit indicator
- PRectangle rcBeyondEOF = (vsDraw.marginInside) ? rcClient : rcArea;
- rcBeyondEOF.left = static_cast<XYPOSITION>(vsDraw.textStart);
- rcBeyondEOF.right = rcBeyondEOF.right - ((vsDraw.marginInside) ? vsDraw.rightMarginWidth : 0);
- rcBeyondEOF.top = static_cast<XYPOSITION>((model.cs.LinesDisplayed() - model.TopLineOfMain()) * vsDraw.lineHeight);
- if (rcBeyondEOF.top < rcBeyondEOF.bottom) {
- surfaceWindow->FillRectangle(rcBeyondEOF, vsDraw.styles[STYLE_DEFAULT].back);
- if (vsDraw.edgeState == EDGE_LINE) {
- int edgeX = static_cast<int>(vsDraw.theEdge * vsDraw.spaceWidth);
- rcBeyondEOF.left = static_cast<XYPOSITION>(edgeX + xStart);
- rcBeyondEOF.right = rcBeyondEOF.left + 1;
- surfaceWindow->FillRectangle(rcBeyondEOF, vsDraw.edgecolour);
- }
- }
- //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset);
-
- //Platform::DebugPrintf(
- //"Layout:%9.6g Paint:%9.6g Ratio:%9.6g Copy:%9.6g Total:%9.6g\n",
- //durLayout, durPaint, durLayout / durPaint, durCopy, etWhole.Duration());
- }
-}
-
-// Space (3 space characters) between line numbers and text when printing.
-#define lineNumberPrintSpace " "
-
-ColourDesired InvertedLight(ColourDesired orig) {
- unsigned int r = orig.GetRed();
- unsigned int g = orig.GetGreen();
- unsigned int b = orig.GetBlue();
- unsigned int l = (r + g + b) / 3; // There is a better calculation for this that matches human eye
- unsigned int il = 0xff - l;
- if (l == 0)
- return ColourDesired(0xff, 0xff, 0xff);
- r = r * il / l;
- g = g * il / l;
- b = b * il / l;
- return ColourDesired(Platform::Minimum(r, 0xff), Platform::Minimum(g, 0xff), Platform::Minimum(b, 0xff));
-}
-
-long EditView::FormatRange(bool draw, Sci_RangeToFormat *pfr, Surface *surface, Surface *surfaceMeasure,
- const EditModel &model, const ViewStyle &vs) {
- // Can't use measurements cached for screen
- posCache.Clear();
-
- ViewStyle vsPrint(vs);
- vsPrint.technology = SC_TECHNOLOGY_DEFAULT;
-
- // Modify the view style for printing as do not normally want any of the transient features to be printed
- // Printing supports only the line number margin.
- int lineNumberIndex = -1;
- for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
- if ((vsPrint.ms[margin].style == SC_MARGIN_NUMBER) && (vsPrint.ms[margin].width > 0)) {
- lineNumberIndex = margin;
- } else {
- vsPrint.ms[margin].width = 0;
- }
- }
- vsPrint.fixedColumnWidth = 0;
- vsPrint.zoomLevel = printParameters.magnification;
- // Don't show indentation guides
- // If this ever gets changed, cached pixmap would need to be recreated if technology != SC_TECHNOLOGY_DEFAULT
- vsPrint.viewIndentationGuides = ivNone;
- // Don't show the selection when printing
- vsPrint.selColours.back.isSet = false;
- vsPrint.selColours.fore.isSet = false;
- vsPrint.selAlpha = SC_ALPHA_NOALPHA;
- vsPrint.selAdditionalAlpha = SC_ALPHA_NOALPHA;
- vsPrint.whitespaceColours.back.isSet = false;
- vsPrint.whitespaceColours.fore.isSet = false;
- vsPrint.showCaretLineBackground = false;
- vsPrint.alwaysShowCaretLineBackground = false;
- // Don't highlight matching braces using indicators
- vsPrint.braceHighlightIndicatorSet = false;
- vsPrint.braceBadLightIndicatorSet = false;
-
- // Set colours for printing according to users settings
- for (size_t sty = 0; sty < vsPrint.styles.size(); sty++) {
- if (printParameters.colourMode == SC_PRINT_INVERTLIGHT) {
- vsPrint.styles[sty].fore = InvertedLight(vsPrint.styles[sty].fore);
- vsPrint.styles[sty].back = InvertedLight(vsPrint.styles[sty].back);
- } else if (printParameters.colourMode == SC_PRINT_BLACKONWHITE) {
- vsPrint.styles[sty].fore = ColourDesired(0, 0, 0);
- vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff);
- } else if (printParameters.colourMode == SC_PRINT_COLOURONWHITE) {
- vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff);
- } else if (printParameters.colourMode == SC_PRINT_COLOURONWHITEDEFAULTBG) {
- if (sty <= STYLE_DEFAULT) {
- vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff);
- }
- }
- }
- // White background for the line numbers
- vsPrint.styles[STYLE_LINENUMBER].back = ColourDesired(0xff, 0xff, 0xff);
-
- // Printing uses different margins, so reset screen margins
- vsPrint.leftMarginWidth = 0;
- vsPrint.rightMarginWidth = 0;
-
- vsPrint.Refresh(*surfaceMeasure, model.pdoc->tabInChars);
- // Determining width must happen after fonts have been realised in Refresh
- int lineNumberWidth = 0;
- if (lineNumberIndex >= 0) {
- lineNumberWidth = static_cast<int>(surfaceMeasure->WidthText(vsPrint.styles[STYLE_LINENUMBER].font,
- "99999" lineNumberPrintSpace, 5 + static_cast<int>(strlen(lineNumberPrintSpace))));
- vsPrint.ms[lineNumberIndex].width = lineNumberWidth;
- vsPrint.Refresh(*surfaceMeasure, model.pdoc->tabInChars); // Recalculate fixedColumnWidth
- }
-
- int linePrintStart = model.pdoc->LineFromPosition(pfr->chrg.cpMin);
- int linePrintLast = linePrintStart + (pfr->rc.bottom - pfr->rc.top) / vsPrint.lineHeight - 1;
- if (linePrintLast < linePrintStart)
- linePrintLast = linePrintStart;
- int linePrintMax = model.pdoc->LineFromPosition(pfr->chrg.cpMax);
- if (linePrintLast > linePrintMax)
- linePrintLast = linePrintMax;
- //Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n",
- // linePrintStart, linePrintLast, linePrintMax, pfr->rc.top, pfr->rc.bottom, vsPrint.lineHeight,
- // surfaceMeasure->Height(vsPrint.styles[STYLE_LINENUMBER].font));
- int endPosPrint = model.pdoc->Length();
- if (linePrintLast < model.pdoc->LinesTotal())
- endPosPrint = model.pdoc->LineStart(linePrintLast + 1);
-
- // Ensure we are styled to where we are formatting.
- model.pdoc->EnsureStyledTo(endPosPrint);
-
- int xStart = vsPrint.fixedColumnWidth + pfr->rc.left;
- int ypos = pfr->rc.top;
-
- int lineDoc = linePrintStart;
-
- int nPrintPos = pfr->chrg.cpMin;
- int visibleLine = 0;
- int widthPrint = pfr->rc.right - pfr->rc.left - vsPrint.fixedColumnWidth;
- if (printParameters.wrapState == eWrapNone)
- widthPrint = LineLayout::wrapWidthInfinite;
-
- while (lineDoc <= linePrintLast && ypos < pfr->rc.bottom) {
-
- // When printing, the hdc and hdcTarget may be the same, so
- // changing the state of surfaceMeasure may change the underlying
- // state of surface. Therefore, any cached state is discarded before
- // using each surface.
- surfaceMeasure->FlushCachedState();
-
- // Copy this line and its styles from the document into local arrays
- // and determine the x position at which each character starts.
- LineLayout ll(model.pdoc->LineStart(lineDoc + 1) - model.pdoc->LineStart(lineDoc) + 1);
- LayoutLine(lineDoc, surfaceMeasure, vsPrint, &ll, model, widthPrint);
-
- ll.containsCaret = false;
-
- PRectangle rcLine = PRectangle::FromInts(
- pfr->rc.left,
- ypos,
- pfr->rc.right - 1,
- ypos + vsPrint.lineHeight);
-
- // When document line is wrapped over multiple display lines, find where
- // to start printing from to ensure a particular position is on the first
- // line of the page.
- if (visibleLine == 0) {
- int startWithinLine = nPrintPos - model.pdoc->LineStart(lineDoc);
- for (int iwl = 0; iwl < ll.lines - 1; iwl++) {
- if (ll.LineStart(iwl) <= startWithinLine && ll.LineStart(iwl + 1) >= startWithinLine) {
- visibleLine = -iwl;
- }
- }
-
- if (ll.lines > 1 && startWithinLine >= ll.LineStart(ll.lines - 1)) {
- visibleLine = -(ll.lines - 1);
- }
- }
-
- if (draw && lineNumberWidth &&
- (ypos + vsPrint.lineHeight <= pfr->rc.bottom) &&
- (visibleLine >= 0)) {
- char number[100];
- sprintf(number, "%d" lineNumberPrintSpace, lineDoc + 1);
- PRectangle rcNumber = rcLine;
- rcNumber.right = rcNumber.left + lineNumberWidth;
- // Right justify
- rcNumber.left = rcNumber.right - surfaceMeasure->WidthText(
- vsPrint.styles[STYLE_LINENUMBER].font, number, static_cast<int>(strlen(number)));
- surface->FlushCachedState();
- surface->DrawTextNoClip(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font,
- static_cast<XYPOSITION>(ypos + vsPrint.maxAscent), number, static_cast<int>(strlen(number)),
- vsPrint.styles[STYLE_LINENUMBER].fore,
- vsPrint.styles[STYLE_LINENUMBER].back);
- }
-
- // Draw the line
- surface->FlushCachedState();
-
- for (int iwl = 0; iwl < ll.lines; iwl++) {
- if (ypos + vsPrint.lineHeight <= pfr->rc.bottom) {
- if (visibleLine >= 0) {
- if (draw) {
- rcLine.top = static_cast<XYPOSITION>(ypos);
- rcLine.bottom = static_cast<XYPOSITION>(ypos + vsPrint.lineHeight);
- DrawLine(surface, vsPrint, lineDoc, visibleLine, xStart, rcLine, &ll, iwl, model);
- }
- ypos += vsPrint.lineHeight;
- }
- visibleLine++;
- if (iwl == ll.lines - 1)
- nPrintPos = model.pdoc->LineStart(lineDoc + 1);
- else
- nPrintPos += ll.LineStart(iwl + 1) - ll.LineStart(iwl);
- }
- }
-
- ++lineDoc;
- }
-
- // Clear cache so measurements are not used for screen
- posCache.Clear();
-
- return nPrintPos;
-}
-
Editor::Editor() {
ctrlID = 0;
diff --git a/src/Editor.h b/src/Editor.h
index fd368df39..53da90906 100644
--- a/src/Editor.h
+++ b/src/Editor.h
@@ -14,17 +14,6 @@ namespace Scintilla {
/**
*/
-class Caret {
-public:
- bool active;
- bool on;
- int period;
-
- Caret();
-};
-
-/**
- */
class Timer {
public:
bool ticking;
@@ -160,136 +149,6 @@ struct WrapPending {
}
};
-struct PrintParameters {
- int magnification;
- int colourMode;
- WrapMode wrapState;
- PrintParameters();
-};
-
-/**
-* EditModel holds the state that needs to be seen by EditView.
-*/
-class EditModel {
- // Private so EditModel objects can not be copied
- EditModel(const EditModel &);
- EditModel &operator=(const EditModel &);
-
-public:
- bool inOverstrike;
- int xOffset; ///< Horizontal scrolled amount in pixels
- bool trackLineWidth;
-
- SpecialRepresentations reprs;
- Caret caret;
- SelectionPosition posDrag;
- Position braces[2];
- int bracesMatchStyle;
- int highlightGuideColumn;
- Selection sel;
- bool primarySelection;
-
- int foldFlags;
- ContractionState cs;
-
- // Hotspot support
- Range hotspot;
-
- // Wrapping support
- int wrapWidth;
-
- Document *pdoc;
-
- EditModel();
- ~EditModel();
-
- virtual int TopLineOfMain() const = 0;
- virtual Point GetVisibleOriginInMain() const = 0;
- virtual int LinesOnScreen() const = 0;
- virtual Range GetHotSpotRange() const = 0;
-};
-
-/**
-* MarginView draws the margins.
-*/
-class MarginView {
-public:
- // Highlight current folding block
- HighlightDelimiter highlightDelimiter;
- Surface *pixmapSelMargin;
- Surface *pixmapSelPattern;
- Surface *pixmapSelPatternOffset1;
-
- MarginView();
-
- void DropGraphics(bool freeObjects);
- void AllocateGraphics(const ViewStyle &vsDraw);
- void RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw);
- void PaintMargin(Surface *surface, int topLine, PRectangle rc, PRectangle rcMargin,
- const EditModel &model, const ViewStyle &vs);
-};
-
-/**
-* EditView draws the main text area.
-*/
-class EditView {
-public:
- PrintParameters printParameters;
-
- bool hideSelection;
- bool drawOverstrikeCaret;
-
- /** In bufferedDraw mode, graphics operations are drawn to a pixmap and then copied to
- * the screen. This avoids flashing but is about 30% slower. */
- bool bufferedDraw;
- /** In twoPhaseDraw mode, drawing is performed in two phases, first the background
- * and then the foreground. This avoids chopping off characters that overlap the next run. */
- bool twoPhaseDraw;
-
- int lineWidthMaxSeen;
- bool additionalCaretsBlink;
- bool additionalCaretsVisible;
-
- Surface *pixmapLine;
- Surface *pixmapIndentGuide;
- Surface *pixmapIndentGuideHighlight;
-
- LineLayoutCache llc;
- PositionCache posCache;
-
- EditView();
-
- void DropGraphics(bool freeObjects);
- void AllocateGraphics(const ViewStyle &vsDraw);
- void RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw);
-
- LineLayout *RetrieveLineLayout(int lineNumber, const EditModel &model);
- void LayoutLine(int line, Surface *surface, const ViewStyle &vstyle, LineLayout *ll,
- const EditModel &model, int width = LineLayout::wrapWidthInfinite);
-
- Point LocationFromPosition(Surface *surface, SelectionPosition pos, int topLine, const EditModel &model, const ViewStyle &vs);
- SelectionPosition SPositionFromLocation(Surface *surface, Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace,
- const EditModel &model, const ViewStyle &vs);
- SelectionPosition SPositionFromLineX(Surface *surface, int lineDoc, int x, const EditModel &model, const ViewStyle &vs);
- int DisplayFromPosition(Surface *surface, int pos, const EditModel &model, const ViewStyle &vs);
- int StartEndDisplayLine(Surface *surface, int pos, bool start, const EditModel &model, const ViewStyle &vs);
-
- void DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight);
- void DrawEOL(Surface *surface, const ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll,
- int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart,
- ColourOptional background, const EditModel &model);
- void DrawAnnotation(Surface *surface, const ViewStyle &vsDraw, int line, int xStart,
- PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model);
- void DrawCarets(Surface *surface, const ViewStyle &vsDraw, int line, int xStart,
- PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model) const;
- void DrawLine(Surface *surface, const ViewStyle &vsDraw, int line, int lineVisible, int xStart,
- PRectangle rcLine, LineLayout *ll, int subLine, const EditModel &model);
- void PaintText(Surface *surfaceWindow, PRectangle rcArea, PRectangle rcClient,
- const EditModel &model, const ViewStyle &vsDraw);
- long FormatRange(bool draw, Sci_RangeToFormat *pfr, Surface *surface, Surface *surfaceMeasure,
- const EditModel &model, const ViewStyle &vs);
-};
-
/**
*/
class Editor : public EditModel, public DocWatcher {
diff --git a/src/MarginView.cxx b/src/MarginView.cxx
new file mode 100644
index 000000000..efe84ecb5
--- /dev/null
+++ b/src/MarginView.cxx
@@ -0,0 +1,532 @@
+// Scintilla source code edit control
+/** @file MarginView.cxx
+ ** Defines the appearance of the editor margin.
+ **/
+// Copyright 1998-2014 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <string>
+#include <vector>
+#include <map>
+#include <algorithm>
+#include <memory>
+
+#include "Platform.h"
+
+#include "ILexer.h"
+#include "Scintilla.h"
+
+#include "StringCopy.h"
+#include "SplitVector.h"
+#include "Partitioning.h"
+#include "RunStyles.h"
+#include "ContractionState.h"
+#include "CellBuffer.h"
+#include "KeyMap.h"
+#include "Indicator.h"
+#include "XPM.h"
+#include "LineMarker.h"
+#include "Style.h"
+#include "ViewStyle.h"
+#include "CharClassify.h"
+#include "Decoration.h"
+#include "CaseFolder.h"
+#include "Document.h"
+#include "UniConversion.h"
+#include "Selection.h"
+#include "PositionCache.h"
+#include "EditModel.h"
+#include "MarginView.h"
+#include "EditView.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+bool ValidStyledText(const ViewStyle &vs, size_t styleOffset, const StyledText &st) {
+ if (st.multipleStyles) {
+ for (size_t iStyle = 0; iStyle<st.length; iStyle++) {
+ if (!vs.ValidStyle(styleOffset + st.styles[iStyle]))
+ return false;
+ }
+ } else {
+ if (!vs.ValidStyle(styleOffset + st.style))
+ return false;
+ }
+ return true;
+}
+
+static int WidthStyledText(Surface *surface, const ViewStyle &vs, int styleOffset,
+ const char *text, const unsigned char *styles, size_t len) {
+ int width = 0;
+ size_t start = 0;
+ while (start < len) {
+ size_t style = styles[start];
+ size_t endSegment = start;
+ while ((endSegment + 1 < len) && (static_cast<size_t>(styles[endSegment + 1]) == style))
+ endSegment++;
+ FontAlias fontText = vs.styles[style + styleOffset].font;
+ width += static_cast<int>(surface->WidthText(fontText, text + start,
+ static_cast<int>(endSegment - start + 1)));
+ start = endSegment + 1;
+ }
+ return width;
+}
+
+int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, const StyledText &st) {
+ int widthMax = 0;
+ size_t start = 0;
+ while (start < st.length) {
+ size_t lenLine = st.LineLength(start);
+ int widthSubLine;
+ if (st.multipleStyles) {
+ widthSubLine = WidthStyledText(surface, vs, styleOffset, st.text + start, st.styles + start, lenLine);
+ } else {
+ FontAlias fontText = vs.styles[styleOffset + st.style].font;
+ widthSubLine = static_cast<int>(surface->WidthText(fontText,
+ st.text + start, static_cast<int>(lenLine)));
+ }
+ if (widthSubLine > widthMax)
+ widthMax = widthSubLine;
+ start += lenLine + 1;
+ }
+ return widthMax;
+}
+
+static void DrawTextInStyle(Surface *surface, PRectangle rcText, const Style &style, XYPOSITION ybase, const char *s, size_t length) {
+ FontAlias fontText = style.font;
+ surface->DrawTextNoClip(rcText, fontText, ybase, s, static_cast<int>(length),
+ style.fore, style.back);
+}
+
+void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText,
+ const StyledText &st, size_t start, size_t length) {
+
+ if (st.multipleStyles) {
+ int x = static_cast<int>(rcText.left);
+ size_t i = 0;
+ while (i < length) {
+ size_t end = i;
+ size_t style = st.styles[i + start];
+ while (end < length - 1 && st.styles[start + end + 1] == style)
+ end++;
+ style += styleOffset;
+ FontAlias fontText = vs.styles[style].font;
+ const int width = static_cast<int>(surface->WidthText(fontText,
+ st.text + start + i, static_cast<int>(end - i + 1)));
+ PRectangle rcSegment = rcText;
+ rcSegment.left = static_cast<XYPOSITION>(x);
+ rcSegment.right = static_cast<XYPOSITION>(x + width + 1);
+ DrawTextInStyle(surface, rcSegment, vs.styles[style], rcText.top + vs.maxAscent,
+ st.text + start + i, end - i + 1);
+ x += width;
+ i = end + 1;
+ }
+ } else {
+ const size_t style = st.style + styleOffset;
+ DrawTextInStyle(surface, rcText, vs.styles[style], rcText.top + vs.maxAscent,
+ st.text + start, length);
+ }
+}
+
+void DrawWrapMarker(Surface *surface, PRectangle rcPlace,
+ bool isEndMarker, ColourDesired wrapColour) {
+ surface->PenColour(wrapColour);
+
+ enum { xa = 1 }; // gap before start
+ int w = static_cast<int>(rcPlace.right - rcPlace.left) - xa - 1;
+
+ bool xStraight = isEndMarker; // x-mirrored symbol for start marker
+
+ int x0 = static_cast<int>(xStraight ? rcPlace.left : rcPlace.right - 1);
+ int y0 = static_cast<int>(rcPlace.top);
+
+ int dy = static_cast<int>(rcPlace.bottom - rcPlace.top) / 5;
+ int y = static_cast<int>(rcPlace.bottom - rcPlace.top) / 2 + dy;
+
+ struct Relative {
+ Surface *surface;
+ int xBase;
+ int xDir;
+ int yBase;
+ int yDir;
+ void MoveTo(int xRelative, int yRelative) {
+ surface->MoveTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
+ }
+ void LineTo(int xRelative, int yRelative) {
+ surface->LineTo(xBase + xDir * xRelative, yBase + yDir * yRelative);
+ }
+ };
+ Relative rel = { surface, x0, xStraight ? 1 : -1, y0, 1 };
+
+ // arrow head
+ rel.MoveTo(xa, y);
+ rel.LineTo(xa + 2 * w / 3, y - dy);
+ rel.MoveTo(xa, y);
+ rel.LineTo(xa + 2 * w / 3, y + dy);
+
+ // arrow body
+ rel.MoveTo(xa, y);
+ 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);
+}
+
+MarginView::MarginView() {
+ pixmapSelMargin = 0;
+ pixmapSelPattern = 0;
+ pixmapSelPatternOffset1 = 0;
+}
+
+void MarginView::DropGraphics(bool freeObjects) {
+ if (freeObjects) {
+ delete pixmapSelMargin;
+ pixmapSelMargin = 0;
+ delete pixmapSelPattern;
+ pixmapSelPattern = 0;
+ delete pixmapSelPatternOffset1;
+ pixmapSelPatternOffset1 = 0;
+ } else {
+ if (pixmapSelMargin)
+ pixmapSelMargin->Release();
+ if (pixmapSelPattern)
+ pixmapSelPattern->Release();
+ if (pixmapSelPatternOffset1)
+ pixmapSelPatternOffset1->Release();
+ }
+}
+
+void MarginView::AllocateGraphics(const ViewStyle &vsDraw) {
+ if (!pixmapSelMargin)
+ pixmapSelMargin = Surface::Allocate(vsDraw.technology);
+ if (!pixmapSelPattern)
+ pixmapSelPattern = Surface::Allocate(vsDraw.technology);
+ if (!pixmapSelPatternOffset1)
+ pixmapSelPatternOffset1 = Surface::Allocate(vsDraw.technology);
+}
+
+void MarginView::RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw) {
+ if (!pixmapSelPattern->Initialised()) {
+ const int patternSize = 8;
+ pixmapSelPattern->InitPixMap(patternSize, patternSize, surfaceWindow, wid);
+ pixmapSelPatternOffset1->InitPixMap(patternSize, patternSize, surfaceWindow, wid);
+ // This complex procedure is to reproduce the checkerboard dithered pattern used by windows
+ // for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half
+ // way between the chrome colour and the chrome highlight colour making a nice transition
+ // between the window chrome and the content area. And it works in low colour depths.
+ PRectangle rcPattern = PRectangle::FromInts(0, 0, patternSize, patternSize);
+
+ // Initialize default colours based on the chrome colour scheme. Typically the highlight is white.
+ ColourDesired colourFMFill = vsDraw.selbar;
+ ColourDesired colourFMStripes = vsDraw.selbarlight;
+
+ if (!(vsDraw.selbarlight == ColourDesired(0xff, 0xff, 0xff))) {
+ // User has chosen an unusual chrome colour scheme so just use the highlight edge colour.
+ // (Typically, the highlight colour is white.)
+ colourFMFill = vsDraw.selbarlight;
+ }
+
+ if (vsDraw.foldmarginColour.isSet) {
+ // override default fold margin colour
+ colourFMFill = vsDraw.foldmarginColour;
+ }
+ if (vsDraw.foldmarginHighlightColour.isSet) {
+ // override default fold margin highlight colour
+ colourFMStripes = vsDraw.foldmarginHighlightColour;
+ }
+
+ pixmapSelPattern->FillRectangle(rcPattern, colourFMFill);
+ pixmapSelPatternOffset1->FillRectangle(rcPattern, colourFMStripes);
+ for (int y = 0; y < patternSize; y++) {
+ for (int x = y % 2; x < patternSize; x += 2) {
+ PRectangle rcPixel = PRectangle::FromInts(x, y, x + 1, y + 1);
+ pixmapSelPattern->FillRectangle(rcPixel, colourFMStripes);
+ pixmapSelPatternOffset1->FillRectangle(rcPixel, colourFMFill);
+ }
+ }
+ }
+}
+
+static int SubstituteMarkerIfEmpty(int markerCheck, int markerDefault, const ViewStyle &vs) {
+ if (vs.markers[markerCheck].markType == SC_MARK_EMPTY)
+ return markerDefault;
+ return markerCheck;
+}
+
+void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRectangle rcMargin,
+ const EditModel &model, const ViewStyle &vs) {
+
+ PRectangle rcSelMargin = rcMargin;
+ rcSelMargin.right = rcMargin.left;
+ if (rcSelMargin.bottom < rc.bottom)
+ rcSelMargin.bottom = rc.bottom;
+
+ Point ptOrigin = model.GetVisibleOriginInMain();
+ FontAlias fontLineNumber = vs.styles[STYLE_LINENUMBER].font;
+ for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
+ if (vs.ms[margin].width > 0) {
+
+ rcSelMargin.left = rcSelMargin.right;
+ rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width;
+
+ if (vs.ms[margin].style != SC_MARGIN_NUMBER) {
+ if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
+ // Required because of special way brush is created for selection margin
+ // Ensure patterns line up when scrolling with separate margin view
+ // by choosing correctly aligned variant.
+ bool invertPhase = static_cast<int>(ptOrigin.y) & 1;
+ surface->FillRectangle(rcSelMargin,
+ invertPhase ? *pixmapSelPattern : *pixmapSelPatternOffset1);
+ } else {
+ ColourDesired colour;
+ switch (vs.ms[margin].style) {
+ case SC_MARGIN_BACK:
+ colour = vs.styles[STYLE_DEFAULT].back;
+ break;
+ case SC_MARGIN_FORE:
+ colour = vs.styles[STYLE_DEFAULT].fore;
+ break;
+ default:
+ colour = vs.styles[STYLE_LINENUMBER].back;
+ break;
+ }
+ surface->FillRectangle(rcSelMargin, colour);
+ }
+ } else {
+ surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back);
+ }
+
+ const int lineStartPaint = static_cast<int>(rcMargin.top + ptOrigin.y) / vs.lineHeight;
+ int visibleLine = model.TopLineOfMain() + lineStartPaint;
+ int yposScreen = lineStartPaint * vs.lineHeight - static_cast<int>(ptOrigin.y);
+ // Work out whether the top line is whitespace located after a
+ // lessening of fold level which implies a 'fold tail' but which should not
+ // be displayed until the last of a sequence of whitespace.
+ bool needWhiteClosure = false;
+ if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
+ int level = model.pdoc->GetLevel(model.cs.DocFromDisplay(visibleLine));
+ if (level & SC_FOLDLEVELWHITEFLAG) {
+ int lineBack = model.cs.DocFromDisplay(visibleLine);
+ int levelPrev = level;
+ while ((lineBack > 0) && (levelPrev & SC_FOLDLEVELWHITEFLAG)) {
+ lineBack--;
+ levelPrev = model.pdoc->GetLevel(lineBack);
+ }
+ if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) {
+ if ((level & SC_FOLDLEVELNUMBERMASK) < (levelPrev & SC_FOLDLEVELNUMBERMASK))
+ needWhiteClosure = true;
+ }
+ }
+ if (highlightDelimiter.isEnabled) {
+ int lastLine = model.cs.DocFromDisplay(topLine + model.LinesOnScreen()) + 1;
+ model.pdoc->GetHighlightDelimiters(highlightDelimiter, model.pdoc->LineFromPosition(model.sel.MainCaret()), lastLine);
+ }
+ }
+
+ // Old code does not know about new markers needed to distinguish all cases
+ const int folderOpenMid = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID,
+ SC_MARKNUM_FOLDEROPEN, vs);
+ const int folderEnd = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND,
+ SC_MARKNUM_FOLDER, vs);
+
+ while ((visibleLine < model.cs.LinesDisplayed()) && yposScreen < rc.bottom) {
+
+ PLATFORM_ASSERT(visibleLine < model.cs.LinesDisplayed());
+ const int lineDoc = model.cs.DocFromDisplay(visibleLine);
+ PLATFORM_ASSERT(model.cs.GetVisible(lineDoc));
+ const bool firstSubLine = visibleLine == model.cs.DisplayFromDoc(lineDoc);
+ const bool lastSubLine = visibleLine == model.cs.DisplayLastFromDoc(lineDoc);
+
+ int marks = model.pdoc->GetMark(lineDoc);
+ if (!firstSubLine)
+ marks = 0;
+
+ bool headWithTail = false;
+
+ if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
+ // Decide which fold indicator should be displayed
+ const int level = model.pdoc->GetLevel(lineDoc);
+ const int levelNext = model.pdoc->GetLevel(lineDoc + 1);
+ const int levelNum = level & SC_FOLDLEVELNUMBERMASK;
+ const int levelNextNum = levelNext & SC_FOLDLEVELNUMBERMASK;
+ if (level & SC_FOLDLEVELHEADERFLAG) {
+ if (firstSubLine) {
+ if (levelNum < levelNextNum) {
+ if (model.cs.GetExpanded(lineDoc)) {
+ if (levelNum == SC_FOLDLEVELBASE)
+ marks |= 1 << SC_MARKNUM_FOLDEROPEN;
+ else
+ marks |= 1 << folderOpenMid;
+ } else {
+ if (levelNum == SC_FOLDLEVELBASE)
+ marks |= 1 << SC_MARKNUM_FOLDER;
+ else
+ marks |= 1 << folderEnd;
+ }
+ } else if (levelNum > SC_FOLDLEVELBASE) {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ }
+ } else {
+ if (levelNum < levelNextNum) {
+ if (model.cs.GetExpanded(lineDoc)) {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ } else if (levelNum > SC_FOLDLEVELBASE) {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ }
+ } else if (levelNum > SC_FOLDLEVELBASE) {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ }
+ }
+ needWhiteClosure = false;
+ const int firstFollowupLine = model.cs.DocFromDisplay(model.cs.DisplayFromDoc(lineDoc + 1));
+ const int firstFollowupLineLevel = model.pdoc->GetLevel(firstFollowupLine);
+ const int secondFollowupLineLevelNum = model.pdoc->GetLevel(firstFollowupLine + 1) & SC_FOLDLEVELNUMBERMASK;
+ if (!model.cs.GetExpanded(lineDoc)) {
+ if ((firstFollowupLineLevel & SC_FOLDLEVELWHITEFLAG) &&
+ (levelNum > secondFollowupLineLevelNum))
+ needWhiteClosure = true;
+
+ if (highlightDelimiter.IsFoldBlockHighlighted(firstFollowupLine))
+ headWithTail = true;
+ }
+ } else if (level & SC_FOLDLEVELWHITEFLAG) {
+ if (needWhiteClosure) {
+ if (levelNext & SC_FOLDLEVELWHITEFLAG) {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ } else if (levelNextNum > SC_FOLDLEVELBASE) {
+ marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
+ needWhiteClosure = false;
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERTAIL;
+ needWhiteClosure = false;
+ }
+ } else if (levelNum > SC_FOLDLEVELBASE) {
+ if (levelNextNum < levelNum) {
+ if (levelNextNum > SC_FOLDLEVELBASE) {
+ marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERTAIL;
+ }
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ }
+ }
+ } else if (levelNum > SC_FOLDLEVELBASE) {
+ if (levelNextNum < levelNum) {
+ needWhiteClosure = false;
+ if (levelNext & SC_FOLDLEVELWHITEFLAG) {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ needWhiteClosure = true;
+ } else if (lastSubLine) {
+ if (levelNextNum > SC_FOLDLEVELBASE) {
+ marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL;
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERTAIL;
+ }
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ }
+ } else {
+ marks |= 1 << SC_MARKNUM_FOLDERSUB;
+ }
+ }
+ }
+
+ marks &= vs.ms[margin].mask;
+
+ PRectangle rcMarker = rcSelMargin;
+ rcMarker.top = static_cast<XYPOSITION>(yposScreen);
+ rcMarker.bottom = static_cast<XYPOSITION>(yposScreen + vs.lineHeight);
+ if (vs.ms[margin].style == SC_MARGIN_NUMBER) {
+ if (firstSubLine) {
+ char number[100] = "";
+ if (lineDoc >= 0)
+ sprintf(number, "%d", lineDoc + 1);
+ if (model.foldFlags & (SC_FOLDFLAG_LEVELNUMBERS | SC_FOLDFLAG_LINESTATE)) {
+ if (model.foldFlags & SC_FOLDFLAG_LEVELNUMBERS) {
+ int lev = model.pdoc->GetLevel(lineDoc);
+ sprintf(number, "%c%c %03X %03X",
+ (lev & SC_FOLDLEVELHEADERFLAG) ? 'H' : '_',
+ (lev & SC_FOLDLEVELWHITEFLAG) ? 'W' : '_',
+ lev & SC_FOLDLEVELNUMBERMASK,
+ lev >> 16
+ );
+ } else {
+ int state = model.pdoc->GetLineState(lineDoc);
+ sprintf(number, "%0X", state);
+ }
+ }
+ PRectangle rcNumber = rcMarker;
+ // Right justify
+ XYPOSITION width = surface->WidthText(fontLineNumber, number, static_cast<int>(strlen(number)));
+ XYPOSITION xpos = rcNumber.right - width - vs.marginNumberPadding;
+ rcNumber.left = xpos;
+ DrawTextInStyle(surface, rcNumber, vs.styles[STYLE_LINENUMBER],
+ rcNumber.top + vs.maxAscent, number, strlen(number));
+ } else if (vs.wrapVisualFlags & SC_WRAPVISUALFLAG_MARGIN) {
+ PRectangle rcWrapMarker = rcMarker;
+ rcWrapMarker.right -= 3;
+ rcWrapMarker.left = rcWrapMarker.right - vs.styles[STYLE_LINENUMBER].aveCharWidth;
+ DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore);
+ }
+ } else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) {
+ if (firstSubLine) {
+ const StyledText stMargin = model.pdoc->MarginStyledText(lineDoc);
+ if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) {
+ surface->FillRectangle(rcMarker,
+ vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back);
+ if (vs.ms[margin].style == SC_MARGIN_RTEXT) {
+ int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, stMargin);
+ rcMarker.left = rcMarker.right - width - 3;
+ }
+ DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker,
+ stMargin, 0, stMargin.length);
+ }
+ }
+ }
+
+ if (marks) {
+ for (int markBit = 0; (markBit < 32) && marks; markBit++) {
+ if (marks & 1) {
+ LineMarker::typeOfFold tFold = LineMarker::undefined;
+ if ((vs.ms[margin].mask & SC_MASK_FOLDERS) && highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) {
+ if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) {
+ tFold = LineMarker::body;
+ } else if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) {
+ if (firstSubLine) {
+ tFold = headWithTail ? LineMarker::headWithTail : LineMarker::head;
+ } else {
+ if (model.cs.GetExpanded(lineDoc) || headWithTail) {
+ tFold = LineMarker::body;
+ } else {
+ tFold = LineMarker::undefined;
+ }
+ }
+ } else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) {
+ tFold = LineMarker::tail;
+ }
+ }
+ vs.markers[markBit].Draw(surface, rcMarker, fontLineNumber, tFold, vs.ms[margin].style);
+ }
+ marks >>= 1;
+ }
+ }
+
+ visibleLine++;
+ yposScreen += vs.lineHeight;
+ }
+ }
+ }
+
+ PRectangle rcBlankMargin = rcMargin;
+ rcBlankMargin.left = rcSelMargin.right;
+ surface->FillRectangle(rcBlankMargin, vs.styles[STYLE_DEFAULT].back);
+}
diff --git a/src/MarginView.h b/src/MarginView.h
new file mode 100644
index 000000000..8c401ae4a
--- /dev/null
+++ b/src/MarginView.h
@@ -0,0 +1,47 @@
+// Scintilla source code edit control
+/** @file MarginView.h
+ ** Defines the appearance of the editor margin.
+ **/
+// Copyright 1998-2014 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#ifndef MARGINVIEW_H
+#define MARGINVIEW_H
+
+#ifdef SCI_NAMESPACE
+namespace Scintilla {
+#endif
+
+bool ValidStyledText(const ViewStyle &vs, size_t styleOffset, const StyledText &st);
+
+void DrawStyledText(Surface *surface, const ViewStyle &vs, int styleOffset, PRectangle rcText,
+ const StyledText &st, size_t start, size_t length);
+int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, const StyledText &st);
+
+void DrawWrapMarker(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourDesired wrapColour);
+
+/**
+* MarginView draws the margins.
+*/
+class MarginView {
+public:
+ Surface *pixmapSelMargin;
+ Surface *pixmapSelPattern;
+ Surface *pixmapSelPatternOffset1;
+ // Highlight current folding block
+ HighlightDelimiter highlightDelimiter;
+
+ MarginView();
+
+ void DropGraphics(bool freeObjects);
+ void AllocateGraphics(const ViewStyle &vsDraw);
+ void RefreshPixMaps(Surface *surfaceWindow, WindowID wid, const ViewStyle &vsDraw);
+ void PaintMargin(Surface *surface, int topLine, PRectangle rc, PRectangle rcMargin,
+ const EditModel &model, const ViewStyle &vs);
+};
+
+#ifdef SCI_NAMESPACE
+}
+#endif
+
+#endif
diff --git a/src/ScintillaBase.cxx b/src/ScintillaBase.cxx
index d42dfc7ff..48ec46808 100644
--- a/src/ScintillaBase.cxx
+++ b/src/ScintillaBase.cxx
@@ -50,6 +50,9 @@
#include "Document.h"
#include "Selection.h"
#include "PositionCache.h"
+#include "EditModel.h"
+#include "MarginView.h"
+#include "EditView.h"
#include "Editor.h"
#include "AutoComplete.h"
#include "ScintillaBase.h"
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx
index 2635b84e4..38e85a7a8 100644
--- a/win32/ScintillaWin.cxx
+++ b/win32/ScintillaWin.cxx
@@ -70,6 +70,9 @@
#include "UniConversion.h"
#include "Selection.h"
#include "PositionCache.h"
+#include "EditModel.h"
+#include "MarginView.h"
+#include "EditView.h"
#include "Editor.h"
#include "AutoComplete.h"
diff --git a/win32/deps.mak b/win32/deps.mak
index 8580b27c0..b92e30545 100644
--- a/win32/deps.mak
+++ b/win32/deps.mak
@@ -1,23 +1,25 @@
CheckD2D.o: CheckD2D.cxx
-PlatWin.o: PlatWin.cxx ../include/Platform.h ../src/UniConversion.h \
- ../src/XPM.h ../src/FontQuality.h
+PlatWin.o: PlatWin.cxx ../include/Platform.h ../lexlib/StringCopy.h \
+ ../src/XPM.h ../src/UniConversion.h ../src/FontQuality.h
ScintillaWin.o: ScintillaWin.cxx ../include/Platform.h \
- ../include/ILexer.h ../include/Scintilla.h ../src/SplitVector.h \
- ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \
- ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h \
- ../src/XPM.h ../src/LineMarker.h ../src/Style.h ../src/AutoComplete.h \
- ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \
- ../src/CaseFolder.h ../src/Document.h ../src/Selection.h \
- ../src/PositionCache.h ../src/Editor.h ../src/ScintillaBase.h \
- ../src/UniConversion.h ../src/CaseConvert.h PlatWin.h
+ ../include/ILexer.h ../include/Scintilla.h ../lexlib/StringCopy.h \
+ ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
+ ../src/ContractionState.h ../src/CellBuffer.h ../src/CallTip.h \
+ ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
+ ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/CaseFolder.h ../src/Document.h \
+ ../src/CaseConvert.h ../src/UniConversion.h ../src/Selection.h \
+ ../src/PositionCache.h ../src/EditModel.h ../src/MarginView.h \
+ ../src/EditView.h ../src/Editor.h ../src/AutoComplete.h \
+ ../src/ScintillaBase.h PlatWin.h
AutoComplete.o: ../src/AutoComplete.cxx ../include/Platform.h \
- ../lexlib/CharacterSet.h ../src/AutoComplete.h ../include/Scintilla.h
+ ../include/Scintilla.h ../lexlib/CharacterSet.h ../src/AutoComplete.h
CallTip.o: ../src/CallTip.cxx ../include/Platform.h \
- ../include/Scintilla.h ../src/CallTip.h
-CaseConvert.o: ../src/CaseConvert.cxx ../src/CaseConvert.h \
- ../src/UniConversion.h ../src/UnicodeFromUTF8.h
-CaseFolder.o: ../src/CaseFolder.cxx ../src/CaseConvert.h \
- ../src/UniConversion.h ../src/CaseFolder.h
+ ../include/Scintilla.h ../lexlib/StringCopy.h ../src/CallTip.h
+CaseConvert.o: ../src/CaseConvert.cxx ../lexlib/StringCopy.h \
+ ../src/CaseConvert.h ../src/UniConversion.h ../src/UnicodeFromUTF8.h
+CaseFolder.o: ../src/CaseFolder.cxx ../src/CaseFolder.h \
+ ../src/CaseConvert.h ../src/UniConversion.h
Catalogue.o: ../src/Catalogue.cxx ../include/ILexer.h \
../include/Scintilla.h ../include/SciLexer.h ../lexlib/LexerModule.h \
../src/Catalogue.h
@@ -32,37 +34,65 @@ Decoration.o: ../src/Decoration.cxx ../include/Platform.h \
../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
../src/RunStyles.h ../src/Decoration.h
Document.o: ../src/Document.cxx ../include/Platform.h ../include/ILexer.h \
- ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
- ../src/RunStyles.h ../src/CellBuffer.h ../src/PerLine.h \
- ../src/CharClassify.h ../lexlib/CharacterSet.h ../src/Decoration.h \
+ ../include/Scintilla.h ../lexlib/CharacterSet.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/CellBuffer.h \
+ ../src/PerLine.h ../src/CharClassify.h ../src/Decoration.h \
../src/CaseFolder.h ../src/Document.h ../src/RESearch.h \
../src/UniConversion.h
+EditModel.o: ../src/EditModel.cxx ../include/Platform.h \
+ ../include/ILexer.h ../include/Scintilla.h ../lexlib/StringCopy.h \
+ ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
+ ../src/ContractionState.h ../src/CellBuffer.h ../src/KeyMap.h \
+ ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
+ ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \
+ ../src/CaseFolder.h ../src/Document.h ../src/UniConversion.h \
+ ../src/Selection.h ../src/PositionCache.h ../src/EditModel.h
Editor.o: ../src/Editor.cxx ../include/Platform.h ../include/ILexer.h \
- ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
- ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \
- ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
- ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
- ../src/Decoration.h ../src/CaseFolder.h ../src/Document.h \
- ../src/UniConversion.h ../src/Selection.h ../src/PositionCache.h \
- ../src/Editor.h
+ ../include/Scintilla.h ../lexlib/StringCopy.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \
+ ../src/CellBuffer.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \
+ ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \
+ ../src/CharClassify.h ../src/Decoration.h ../src/CaseFolder.h \
+ ../src/Document.h ../src/UniConversion.h ../src/Selection.h \
+ ../src/PositionCache.h ../src/EditModel.h ../src/MarginView.h \
+ ../src/EditView.h ../src/Editor.h
+EditView.o: ../src/EditView.cxx ../include/Platform.h ../include/ILexer.h \
+ ../include/Scintilla.h ../lexlib/StringCopy.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \
+ ../src/CellBuffer.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \
+ ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \
+ ../src/CharClassify.h ../src/Decoration.h ../src/CaseFolder.h \
+ ../src/Document.h ../src/UniConversion.h ../src/Selection.h \
+ ../src/PositionCache.h ../src/EditModel.h ../src/MarginView.h \
+ ../src/EditView.h
ExternalLexer.o: ../src/ExternalLexer.cxx ../include/Platform.h \
../include/ILexer.h ../include/Scintilla.h ../include/SciLexer.h \
../lexlib/LexerModule.h ../src/Catalogue.h ../src/ExternalLexer.h
Indicator.o: ../src/Indicator.cxx ../include/Platform.h \
- ../include/Scintilla.h ../src/XPM.h ../src/Indicator.h
+ ../include/Scintilla.h ../src/Indicator.h ../src/XPM.h
KeyMap.o: ../src/KeyMap.cxx ../include/Platform.h ../include/Scintilla.h \
../src/KeyMap.h
LineMarker.o: ../src/LineMarker.cxx ../include/Platform.h \
- ../include/Scintilla.h ../src/XPM.h ../src/LineMarker.h
+ ../include/Scintilla.h ../lexlib/StringCopy.h ../src/XPM.h \
+ ../src/LineMarker.h
+MarginView.o: ../src/MarginView.cxx ../include/Platform.h \
+ ../include/ILexer.h ../include/Scintilla.h ../lexlib/StringCopy.h \
+ ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
+ ../src/ContractionState.h ../src/CellBuffer.h ../src/KeyMap.h \
+ ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h ../src/Style.h \
+ ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \
+ ../src/CaseFolder.h ../src/Document.h ../src/UniConversion.h \
+ ../src/Selection.h ../src/PositionCache.h ../src/EditModel.h \
+ ../src/MarginView.h ../src/EditView.h
PerLine.o: ../src/PerLine.cxx ../include/Platform.h \
../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
../src/CellBuffer.h ../src/PerLine.h
PositionCache.o: ../src/PositionCache.cxx ../include/Platform.h \
- ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
- ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \
- ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
- ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
- ../src/Decoration.h ../include/ILexer.h ../src/CaseFolder.h \
+ ../include/ILexer.h ../include/Scintilla.h ../src/SplitVector.h \
+ ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \
+ ../src/CellBuffer.h ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h \
+ ../src/LineMarker.h ../src/Style.h ../src/ViewStyle.h \
+ ../src/CharClassify.h ../src/Decoration.h ../src/CaseFolder.h \
../src/Document.h ../src/UniConversion.h ../src/Selection.h \
../src/PositionCache.h
RESearch.o: ../src/RESearch.cxx ../src/CharClassify.h ../src/RESearch.h
@@ -74,10 +104,11 @@ ScintillaBase.o: ../src/ScintillaBase.cxx ../include/Platform.h \
../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
../src/ContractionState.h ../src/CellBuffer.h ../src/CallTip.h \
../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
- ../src/Style.h ../src/ViewStyle.h ../src/AutoComplete.h \
- ../src/CharClassify.h ../src/Decoration.h ../src/CaseFolder.h \
- ../src/Document.h ../src/Selection.h ../src/PositionCache.h \
- ../src/Editor.h ../src/ScintillaBase.h
+ ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
+ ../src/Decoration.h ../src/CaseFolder.h ../src/Document.h \
+ ../src/Selection.h ../src/PositionCache.h ../src/EditModel.h \
+ ../src/MarginView.h ../src/EditView.h ../src/Editor.h \
+ ../src/AutoComplete.h ../src/ScintillaBase.h
Selection.o: ../src/Selection.cxx ../include/Platform.h \
../include/Scintilla.h ../src/Selection.h
Style.o: ../src/Style.cxx ../include/Platform.h ../include/Scintilla.h \
@@ -92,7 +123,7 @@ Accessor.o: ../lexlib/Accessor.cxx ../include/ILexer.h \
../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h
CharacterCategory.o: ../lexlib/CharacterCategory.cxx \
- ../lexlib/CharacterCategory.h
+ ../lexlib/StringCopy.h ../lexlib/CharacterCategory.h
CharacterSet.o: ../lexlib/CharacterSet.cxx ../lexlib/CharacterSet.h
LexerBase.o: ../lexlib/LexerBase.cxx ../include/ILexer.h \
../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
@@ -114,7 +145,8 @@ LexerSimple.o: ../lexlib/LexerSimple.cxx ../include/ILexer.h \
PropSetSimple.o: ../lexlib/PropSetSimple.cxx ../lexlib/PropSetSimple.h
StyleContext.o: ../lexlib/StyleContext.cxx ../include/ILexer.h \
../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h
-WordList.o: ../lexlib/WordList.cxx ../lexlib/WordList.h
+WordList.o: ../lexlib/WordList.cxx ../lexlib/StringCopy.h \
+ ../lexlib/WordList.h
LexA68k.o: ../lexers/LexA68k.cxx ../include/ILexer.h \
../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \
../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
@@ -218,6 +250,14 @@ LexD.o: ../lexers/LexD.cxx ../include/ILexer.h ../include/Scintilla.h \
../include/SciLexer.h ../lexlib/WordList.h ../lexlib/LexAccessor.h \
../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
../lexlib/LexerModule.h ../lexlib/OptionSet.h
+LexDMAP.o: ../lexers/LexDMAP.cxx ../include/ILexer.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \
+ ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
+ ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
+LexDMIS.o: ../lexers/LexDMIS.cxx ../include/ILexer.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \
+ ../lexlib/LexAccessor.h ../lexlib/StyleContext.h \
+ ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexECL.o: ../lexers/LexECL.cxx ../include/ILexer.h ../include/Scintilla.h \
../include/SciLexer.h ../lexlib/PropSetSimple.h ../lexlib/WordList.h \
../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
@@ -258,12 +298,13 @@ LexHaskell.o: ../lexers/LexHaskell.cxx ../include/ILexer.h \
../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
- ../lexlib/LexerModule.h ../lexlib/OptionSet.h \
- ../lexlib/CharacterCategory.h
+ ../lexlib/CharacterCategory.h ../lexlib/LexerModule.h \
+ ../lexlib/OptionSet.h
LexHTML.o: ../lexers/LexHTML.cxx ../include/ILexer.h \
- ../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \
- ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
- ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
+ ../include/Scintilla.h ../include/SciLexer.h ../lexlib/StringCopy.h \
+ ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
+ ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
+ ../lexlib/LexerModule.h
LexInno.o: ../lexers/LexInno.cxx ../include/ILexer.h \
../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \
../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
@@ -272,6 +313,10 @@ LexKix.o: ../lexers/LexKix.cxx ../include/ILexer.h ../include/Scintilla.h \
../include/SciLexer.h ../lexlib/WordList.h ../lexlib/LexAccessor.h \
../lexlib/Accessor.h ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
../lexlib/LexerModule.h
+LexKVIrc.o: ../lexers/LexKVIrc.cxx ../include/ILexer.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \
+ ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
+ ../lexlib/CharacterSet.h ../lexlib/LexerModule.h
LexLaTeX.o: ../lexers/LexLaTeX.cxx ../include/ILexer.h \
../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
@@ -402,6 +447,11 @@ LexRuby.o: ../lexers/LexRuby.cxx ../include/ILexer.h \
../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \
../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
../lexlib/CharacterSet.h ../lexlib/LexerModule.h
+LexRust.o: ../lexers/LexRust.cxx ../include/ILexer.h \
+ ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
+ ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
+ ../lexlib/StyleContext.h ../lexlib/CharacterSet.h \
+ ../lexlib/LexerModule.h ../lexlib/OptionSet.h
LexScriptol.o: ../lexers/LexScriptol.cxx ../include/ILexer.h \
../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \
../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
@@ -477,7 +527,8 @@ LexVHDL.o: ../lexers/LexVHDL.cxx ../include/ILexer.h \
LexVisualProlog.o: ../lexers/LexVisualProlog.cxx ../include/ILexer.h \
../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \
../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
- ../lexlib/CharacterSet.h ../lexlib/LexerModule.h ../lexlib/OptionSet.h
+ ../lexlib/CharacterSet.h ../lexlib/CharacterCategory.h \
+ ../lexlib/LexerModule.h ../lexlib/OptionSet.h
LexYAML.o: ../lexers/LexYAML.cxx ../include/ILexer.h \
../include/Scintilla.h ../include/SciLexer.h ../lexlib/WordList.h \
../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h \
diff --git a/win32/makefile b/win32/makefile
index d4a39d278..299c3c32c 100644
--- a/win32/makefile
+++ b/win32/makefile
@@ -63,10 +63,13 @@ BASEOBJS = \
ContractionState.o \
Decoration.o \
Document.o \
+ EditModel.o \
Editor.o \
+ EditView.o \
KeyMap.o \
Indicator.o \
LineMarker.o \
+ MarginView.o \
PerLine.o \
PlatWin.o \
PositionCache.o \
@@ -117,7 +120,7 @@ ScintillaBaseL.o: ScintillaBase.cxx Platform.h \
KeyMap.h Indicator.h XPM.h LineMarker.h \
Style.h ViewStyle.h AutoComplete.h \
CharClassify.h Decoration.h Document.h \
- Selection.h PositionCache.h Editor.h \
+ Selection.h PositionCache.h EditModel.h Editor.h EditView.h \
ScintillaBase.h LexAccessor.h Accessor.h \
LexerModule.h Catalogue.h CaseFolder.h
@@ -128,7 +131,7 @@ ScintillaWinL.o: ScintillaWin.cxx Platform.h \
XPM.h LineMarker.h Style.h AutoComplete.h \
ViewStyle.h CharClassify.h Decoration.h \
Document.h Selection.h PositionCache.h \
- Editor.h ScintillaBase.h UniConversion.h \
+ EditModel.h Editor.h EditView.h ScintillaBase.h UniConversion.h \
LexAccessor.h Accessor.h \
LexerModule.h Catalogue.h CaseConvert.h \
CaseFolder.h
@@ -140,7 +143,7 @@ ScintillaWinS.o: ScintillaWin.cxx Platform.h \
XPM.h LineMarker.h Style.h AutoComplete.h \
ViewStyle.h CharClassify.h Decoration.h \
Document.h Selection.h PositionCache.h \
- Editor.h ScintillaBase.h UniConversion.h \
+ EditModel.h Editor.h EditView.h ScintillaBase.h UniConversion.h \
CaseConvert.h CaseFolder.h
ScintillaBaseL.o:
diff --git a/win32/scintilla.mak b/win32/scintilla.mak
index eaa407d3b..2febf86f3 100644
--- a/win32/scintilla.mak
+++ b/win32/scintilla.mak
@@ -67,10 +67,13 @@ SHAREDOBJS=\
$(DIR_O)\ContractionState.obj \
$(DIR_O)\Decoration.obj \
$(DIR_O)\Document.obj \
+ $(DIR_O)\EditModel.obj \
$(DIR_O)\Editor.obj \
+ $(DIR_O)\EditView.obj \
$(DIR_O)\Indicator.obj \
$(DIR_O)\KeyMap.obj \
$(DIR_O)\LineMarker.obj \
+ $(DIR_O)\MarginView.obj \
$(DIR_O)\PerLine.obj \
$(DIR_O)\PlatWin.obj \
$(DIR_O)\PositionCache.obj \
@@ -238,58 +241,209 @@ $(DIR_O)\ScintillaWinS.obj: ScintillaWin.cxx
# Dependencies
# All lexers depend on this set of headers
-LEX_HEADERS= ..\include\ILexer.h ..\include\Scintilla.h ..\include\SciLexer.h \
- ..\lexlib\Accessor.h ..\lexlib\CharacterSet.h ..\lexlib\LexAccessor.h \
- ..\lexlib\LexerModule.h ..\lexlib\StyleContext.h
-
-$(DIR_O)\Accessor.obj: ../lexlib/Accessor.cxx ../include/ILexer.h \
- ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
- ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h
-$(DIR_O)\AutoComplete.obj: ../src/AutoComplete.cxx ../include/Platform.h \
- ../lexlib/CharacterSet.h ../src/AutoComplete.h ../include/Scintilla.h
-$(DIR_O)\CallTip.obj: ../src/CallTip.cxx ../include/Platform.h \
- ../include/Scintilla.h ../src/CallTip.h
-$(DIR_O)\CaseConvert.obj: ../src/CaseConvert.cxx ../src/CaseConvert.h \
- ../src/UniConversion.h ../src/UnicodeFromUTF8.h
-$(DIR_O)\CaseFolder.obj: ../src/CaseFolder.cxx ../src/CaseConvert.h \
- ../src/UniConversion.h ../src/CaseFolder.h
-$(DIR_O)\Catalogue.obj: ../src/Catalogue.cxx ../include/ILexer.h \
- ../include/Scintilla.h ../include/SciLexer.h ../lexlib/LexerModule.h \
- ../src/Catalogue.h
-$(DIR_O)\CellBuffer.obj: ../src/CellBuffer.cxx ../include/Platform.h \
- ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
- ../src/CellBuffer.h ../src/UniConversion.h
-$(DIR_O)\CharacterCategory.obj: ../lexlib/CharacterCategory.cxx \
- ../lexlib/CharacterCategory.h
-$(DIR_O)\CharacterSet.obj: ../lexlib/CharacterSet.cxx ../lexlib/CharacterSet.h
-$(DIR_O)\CharClassify.obj: ../src/CharClassify.cxx ../src/CharClassify.h
-$(DIR_O)\ContractionState.obj: ../src/ContractionState.cxx ../include/Platform.h \
- ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
- ../src/ContractionState.h
-$(DIR_O)\Decoration.obj: ../src/Decoration.cxx ../include/Platform.h \
- ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
- ../src/RunStyles.h ../src/Decoration.h
-$(DIR_O)\Document.obj: ../src/Document.cxx ../include/Platform.h ../include/ILexer.h \
- ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
- ../src/RunStyles.h ../src/CellBuffer.h ../src/PerLine.h \
- ../src/CharClassify.h ../lexlib/CharacterSet.h ../src/Decoration.h \
- ../src/CaseFolder.h ../src/Document.h ../src/RESearch.h \
- ../src/UniConversion.h
-$(DIR_O)\Editor.obj: ../src/Editor.cxx ../include/Platform.h ../include/ILexer.h \
- ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
- ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \
- ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
- ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
- ../src/Decoration.h ../src/CaseFolder.h ../src/Document.h \
- ../src/UniConversion.h ../src/Selection.h ../src/PositionCache.h \
- ../src/Editor.h
-$(DIR_O)\ExternalLexer.obj: ../src/ExternalLexer.cxx ../include/Platform.h \
- ../include/ILexer.h ../include/Scintilla.h ../include/SciLexer.h \
- ../lexlib/LexerModule.h ../src/Catalogue.h ../src/ExternalLexer.h
-$(DIR_O)\Indicator.obj: ../src/Indicator.cxx ../include/Platform.h \
- ../include/Scintilla.h ../src/XPM.h ../src/Indicator.h
-$(DIR_O)\KeyMap.obj: ../src/KeyMap.cxx ../include/Platform.h ../include/Scintilla.h \
- ../src/KeyMap.h
+LEX_HEADERS= \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../include/SciLexer.h \
+ ../lexlib/WordList.h \
+ ../lexlib/LexAccessor.h \
+ ../lexlib/Accessor.h \
+ ../lexlib/StyleContext.h \
+ ../lexlib/CharacterSet.h \
+ ../lexlib/LexerModule.h \
+ ../lexlib/OptionSet.h \
+ ../lexlib/SparseState.h \
+ ../lexlib/SubStyles.h
+
+$(DIR_O)\Accessor.obj: \
+ ../lexlib/Accessor.cxx \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../include/SciLexer.h \
+ ../lexlib/PropSetSimple.h \
+ ../lexlib/WordList.h \
+ ../lexlib/LexAccessor.h \
+ ../lexlib/Accessor.h
+$(DIR_O)\AutoComplete.obj: \
+ ../src/AutoComplete.cxx \
+ ../include/Platform.h \
+ ../include/Scintilla.h \
+ ../lexlib/CharacterSet.h \
+ ../src/AutoComplete.h
+$(DIR_O)\CallTip.obj: \
+ ../src/CallTip.cxx \
+ ../include/Platform.h \
+ ../include/Scintilla.h \
+ ../lexlib/StringCopy.h \
+ ../src/CallTip.h
+$(DIR_O)\CaseConvert.obj: \
+ ../src/CaseConvert.cxx \
+ ../lexlib/StringCopy.h \
+ ../src/CaseConvert.h \
+ ../src/UniConversion.h \
+ ../src/UnicodeFromUTF8.h
+$(DIR_O)\CaseFolder.obj: \
+ ../src/CaseFolder.cxx \
+ ../src/CaseFolder.h \
+ ../src/CaseConvert.h \
+ ../src/UniConversion.h
+$(DIR_O)\Catalogue.obj: \
+ ../src/Catalogue.cxx \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../include/SciLexer.h \
+ ../lexlib/LexerModule.h \
+ ../src/Catalogue.h
+$(DIR_O)\CellBuffer.obj: \
+ ../src/CellBuffer.cxx \
+ ../include/Platform.h \
+ ../include/Scintilla.h \
+ ../src/SplitVector.h \
+ ../src/Partitioning.h \
+ ../src/CellBuffer.h \
+ ../src/UniConversion.h
+$(DIR_O)\CharacterCategory.obj: \
+ ../lexlib/CharacterCategory.cxx \
+ ../lexlib/StringCopy.h \
+ ../lexlib/CharacterCategory.h
+$(DIR_O)\CharacterSet.obj: \
+ ../lexlib/CharacterSet.cxx \
+ ../lexlib/CharacterSet.h
+$(DIR_O)\CharClassify.obj: \
+ ../src/CharClassify.cxx \
+ ../src/CharClassify.h
+$(DIR_O)\ContractionState.obj: \
+ ../src/ContractionState.cxx \
+ ../include/Platform.h \
+ ../src/SplitVector.h \
+ ../src/Partitioning.h \
+ ../src/RunStyles.h \
+ ../src/ContractionState.h
+$(DIR_O)\Decoration.obj: \
+ ../src/Decoration.cxx \
+ ../include/Platform.h \
+ ../include/Scintilla.h \
+ ../src/SplitVector.h \
+ ../src/Partitioning.h \
+ ../src/RunStyles.h \
+ ../src/Decoration.h
+$(DIR_O)\Document.obj: \
+ ../src/Document.cxx \
+ ../include/Platform.h \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../lexlib/CharacterSet.h \
+ ../src/SplitVector.h \
+ ../src/Partitioning.h \
+ ../src/RunStyles.h \
+ ../src/CellBuffer.h \
+ ../src/PerLine.h \
+ ../src/CharClassify.h \
+ ../src/Decoration.h \
+ ../src/CaseFolder.h \
+ ../src/Document.h \
+ ../src/RESearch.h \
+ ../src/UniConversion.h
+$(DIR_O)\EditModel.obj: \
+ ../src/EditModel.cxx \
+ ../include/Platform.h \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../lexlib/StringCopy.h \
+ ../src/SplitVector.h \
+ ../src/Partitioning.h \
+ ../src/RunStyles.h \
+ ../src/ContractionState.h \
+ ../src/CellBuffer.h \
+ ../src/KeyMap.h \
+ ../src/Indicator.h \
+ ../src/XPM.h \
+ ../src/LineMarker.h \
+ ../src/Style.h \
+ ../src/ViewStyle.h \
+ ../src/CharClassify.h \
+ ../src/Decoration.h \
+ ../src/CaseFolder.h \
+ ../src/Document.h \
+ ../src/UniConversion.h \
+ ../src/Selection.h \
+ ../src/PositionCache.h \
+ ../src/EditModel.h
+$(DIR_O)\Editor.obj: \
+ ../src/Editor.cxx \
+ ../include/Platform.h \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../lexlib/StringCopy.h \
+ ../src/SplitVector.h \
+ ../src/Partitioning.h \
+ ../src/RunStyles.h \
+ ../src/ContractionState.h \
+ ../src/CellBuffer.h \
+ ../src/KeyMap.h \
+ ../src/Indicator.h \
+ ../src/XPM.h \
+ ../src/LineMarker.h \
+ ../src/Style.h \
+ ../src/ViewStyle.h \
+ ../src/CharClassify.h \
+ ../src/Decoration.h \
+ ../src/CaseFolder.h \
+ ../src/Document.h \
+ ../src/UniConversion.h \
+ ../src/Selection.h \
+ ../src/PositionCache.h \
+ ../src/EditModel.h \
+ ../src/MarginView.h \
+ ../src/EditView.h \
+ ../src/Editor.h
+$(DIR_O)\EditView.obj: \
+ ../src/EditView.cxx \
+ ../include/Platform.h \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../lexlib/StringCopy.h \
+ ../src/SplitVector.h \
+ ../src/Partitioning.h \
+ ../src/RunStyles.h \
+ ../src/ContractionState.h \
+ ../src/CellBuffer.h \
+ ../src/KeyMap.h \
+ ../src/Indicator.h \
+ ../src/XPM.h \
+ ../src/LineMarker.h \
+ ../src/Style.h \
+ ../src/ViewStyle.h \
+ ../src/CharClassify.h \
+ ../src/Decoration.h \
+ ../src/CaseFolder.h \
+ ../src/Document.h \
+ ../src/UniConversion.h \
+ ../src/Selection.h \
+ ../src/PositionCache.h \
+ ../src/EditModel.h \
+ ../src/MarginView.h \
+ ../src/EditView.h
+$(DIR_O)\ExternalLexer.obj: \
+ ../src/ExternalLexer.cxx \
+ ../include/Platform.h \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../include/SciLexer.h \
+ ../lexlib/LexerModule.h \
+ ../src/Catalogue.h \
+ ../src/ExternalLexer.h
+$(DIR_O)\Indicator.obj: \
+ ../src/Indicator.cxx \
+ ../include/Platform.h \
+ ../include/Scintilla.h \
+ ../src/Indicator.h \
+ ../src/XPM.h
+$(DIR_O)\KeyMap.obj: \
+ ../src/KeyMap.cxx \
+ ../include/Platform.h \
+ ../include/Scintilla.h \
+ ../src/KeyMap.h
#++Autogenerated -- run scripts/LexGen.py to regenerate
#**\n\($(DIR_O)\\\*.obj: ..\\lexers\\\*.cxx $(LEX_HEADERS)\n\n\)
@@ -485,98 +639,334 @@ $(DIR_O)\LexYAML.obj: ..\lexers\LexYAML.cxx $(LEX_HEADERS)
#--Autogenerated -- end of automatically generated section
-$(DIR_O)\LexerBase.obj: ../lexlib/LexerBase.cxx ../include/ILexer.h \
- ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
- ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
- ../lexlib/LexerModule.h ../lexlib/LexerBase.h
-$(DIR_O)\LexerModule.obj: ../lexlib/LexerModule.cxx ../include/ILexer.h \
- ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
- ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
- ../lexlib/LexerModule.h ../lexlib/LexerBase.h ../lexlib/LexerSimple.h
-$(DIR_O)\LexerNoExceptions.obj: ../lexlib/LexerNoExceptions.cxx ../include/ILexer.h \
- ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
- ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
- ../lexlib/LexerModule.h ../lexlib/LexerBase.h \
- ../lexlib/LexerNoExceptions.h
-$(DIR_O)\LexerSimple.obj: ../lexlib/LexerSimple.cxx ../include/ILexer.h \
- ../include/Scintilla.h ../include/SciLexer.h ../lexlib/PropSetSimple.h \
- ../lexlib/WordList.h ../lexlib/LexAccessor.h ../lexlib/Accessor.h \
- ../lexlib/LexerModule.h ../lexlib/LexerBase.h ../lexlib/LexerSimple.h
-$(DIR_O)\LineMarker.obj: ../src/LineMarker.cxx ../include/Platform.h \
- ../include/Scintilla.h ../src/XPM.h ../src/LineMarker.h
-$(DIR_O)\PerLine.obj: ../src/PerLine.cxx ../include/Platform.h \
- ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
- ../src/CellBuffer.h ../src/PerLine.h
-$(DIR_O)\PlatWin.obj: PlatWin.cxx ../include/Platform.h ../src/UniConversion.h \
- ../src/XPM.h ../src/FontQuality.h
-$(DIR_O)\PositionCache.obj: ../src/PositionCache.cxx ../include/Platform.h \
- ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
- ../src/RunStyles.h ../src/ContractionState.h ../src/CellBuffer.h \
- ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
- ../src/Style.h ../src/ViewStyle.h ../src/CharClassify.h \
- ../src/Decoration.h ../include/ILexer.h ../src/CaseFolder.h \
- ../src/Document.h ../src/UniConversion.h ../src/Selection.h \
- ../src/PositionCache.h
-$(DIR_O)\PropSetSimple.obj: ../lexlib/PropSetSimple.cxx ../lexlib/PropSetSimple.h
-$(DIR_O)\RESearch.obj: ../src/RESearch.cxx ../src/CharClassify.h ../src/RESearch.h
-$(DIR_O)\RunStyles.obj: ../src/RunStyles.cxx ../include/Platform.h \
- ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
- ../src/RunStyles.h
-$(DIR_O)\ScintillaBase.obj: ../src/ScintillaBase.cxx ../include/Platform.h \
- ../include/ILexer.h ../include/Scintilla.h ../lexlib/PropSetSimple.h \
- ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
- ../src/ContractionState.h ../src/CellBuffer.h ../src/CallTip.h \
- ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
- ../src/Style.h ../src/ViewStyle.h ../src/AutoComplete.h \
- ../src/CharClassify.h ../src/Decoration.h ../src/CaseFolder.h \
- ../src/Document.h ../src/Selection.h ../src/PositionCache.h \
- ../src/Editor.h ../src/ScintillaBase.h
-$(DIR_O)\ScintillaBaseL.obj: ../src/ScintillaBase.cxx ../include/Platform.h \
- ../include/ILexer.h ../include/Scintilla.h ../lexlib/PropSetSimple.h \
- ../src/SplitVector.h ../src/Partitioning.h ../src/RunStyles.h \
- ../src/ContractionState.h ../src/CellBuffer.h ../src/CallTip.h \
- ../src/KeyMap.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
- ../src/Style.h ../src/ViewStyle.h ../src/AutoComplete.h \
- ../src/CharClassify.h ../src/Decoration.h ../src/CaseFolder.h \
- ../src/Document.h ../src/Selection.h ../src/PositionCache.h \
- ../src/Editor.h ../src/ScintillaBase.h
-$(DIR_O)\ScintillaWin.obj: ScintillaWin.cxx ../include/Platform.h \
- ../include/ILexer.h ../include/Scintilla.h ../src/SplitVector.h \
- ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \
- ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h \
- ../src/XPM.h ../src/LineMarker.h ../src/Style.h ../src/AutoComplete.h \
- ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \
- ../src/CaseFolder.h ../src/Document.h ../src/Selection.h \
- ../src/PositionCache.h ../src/Editor.h ../src/ScintillaBase.h \
- ../src/UniConversion.h ../src/CaseConvert.h PlatWin.h
-$(DIR_O)\ScintillaWinS.obj: ScintillaWin.cxx ../include/Platform.h \
- ../include/ILexer.h ../include/Scintilla.h ../src/SplitVector.h \
- ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \
- ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h \
- ../src/XPM.h ../src/LineMarker.h ../src/Style.h ../src/AutoComplete.h \
- ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \
- ../src/CaseFolder.h ../src/Document.h ../src/Selection.h \
- ../src/PositionCache.h ../src/Editor.h ../src/ScintillaBase.h \
- ../src/UniConversion.h ../src/CaseConvert.h PlatWin.h
-$(DIR_O)\ScintillaWinL.obj: ScintillaWin.cxx ../include/Platform.h \
- ../include/ILexer.h ../include/Scintilla.h ../src/SplitVector.h \
- ../src/Partitioning.h ../src/RunStyles.h ../src/ContractionState.h \
- ../src/CellBuffer.h ../src/CallTip.h ../src/KeyMap.h ../src/Indicator.h \
- ../src/XPM.h ../src/LineMarker.h ../src/Style.h ../src/AutoComplete.h \
- ../src/ViewStyle.h ../src/CharClassify.h ../src/Decoration.h \
- ../src/CaseFolder.h ../src/Document.h ../src/Selection.h \
- ../src/PositionCache.h ../src/Editor.h ../src/ScintillaBase.h \
- ../src/UniConversion.h ../src/CaseConvert.h PlatWin.h
-$(DIR_O)\Selection.obj: ../src/Selection.cxx ../include/Platform.h \
- ../include/Scintilla.h ../src/Selection.h
-$(DIR_O)\Style.obj: ../src/Style.cxx ../include/Platform.h ../include/Scintilla.h \
- ../src/Style.h
-$(DIR_O)\StyleContext.obj: ../lexlib/StyleContext.cxx ../include/ILexer.h \
- ../lexlib/LexAccessor.h ../lexlib/Accessor.h ../lexlib/StyleContext.h
-$(DIR_O)\UniConversion.obj: ../src/UniConversion.cxx ../src/UniConversion.h
-$(DIR_O)\ViewStyle.obj: ../src/ViewStyle.cxx ../include/Platform.h \
- ../include/Scintilla.h ../src/SplitVector.h ../src/Partitioning.h \
- ../src/RunStyles.h ../src/Indicator.h ../src/XPM.h ../src/LineMarker.h \
- ../src/Style.h ../src/ViewStyle.h
-$(DIR_O)\WordList.obj: ../lexlib/WordList.cxx ../lexlib/WordList.h
-$(DIR_O)\XPM.obj: ../src/XPM.cxx ../include/Platform.h ../src/XPM.h
+$(DIR_O)\LexerBase.obj: \
+ ../lexlib/LexerBase.cxx \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../include/SciLexer.h \
+ ../lexlib/PropSetSimple.h \
+ ../lexlib/WordList.h \
+ ../lexlib/LexAccessor.h \
+ ../lexlib/Accessor.h \
+ ../lexlib/LexerModule.h \
+ ../lexlib/LexerBase.h
+$(DIR_O)\LexerModule.obj: \
+ ../lexlib/LexerModule.cxx \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../include/SciLexer.h \
+ ../lexlib/PropSetSimple.h \
+ ../lexlib/WordList.h \
+ ../lexlib/LexAccessor.h \
+ ../lexlib/Accessor.h \
+ ../lexlib/LexerModule.h \
+ ../lexlib/LexerBase.h \
+ ../lexlib/LexerSimple.h
+$(DIR_O)\LexerNoExceptions.obj: \
+ ../lexlib/LexerNoExceptions.cxx \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../include/SciLexer.h \
+ ../lexlib/PropSetSimple.h \
+ ../lexlib/WordList.h \
+ ../lexlib/LexAccessor.h \
+ ../lexlib/Accessor.h \
+ ../lexlib/LexerModule.h \
+ ../lexlib/LexerBase.h \
+ ../lexlib/LexerNoExceptions.h
+$(DIR_O)\LexerSimple.obj: \
+ ../lexlib/LexerSimple.cxx \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../include/SciLexer.h \
+ ../lexlib/PropSetSimple.h \
+ ../lexlib/WordList.h \
+ ../lexlib/LexAccessor.h \
+ ../lexlib/Accessor.h \
+ ../lexlib/LexerModule.h \
+ ../lexlib/LexerBase.h \
+ ../lexlib/LexerSimple.h
+$(DIR_O)\LineMarker.obj: \
+ ../src/LineMarker.cxx \
+ ../include/Platform.h \
+ ../include/Scintilla.h \
+ ../lexlib/StringCopy.h \
+ ../src/XPM.h \
+ ../src/LineMarker.h
+$(DIR_O)\MarginView.obj: \
+ ../src/MarginView.cxx \
+ ../include/Platform.h \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../lexlib/StringCopy.h \
+ ../src/SplitVector.h \
+ ../src/Partitioning.h \
+ ../src/RunStyles.h \
+ ../src/ContractionState.h \
+ ../src/CellBuffer.h \
+ ../src/KeyMap.h \
+ ../src/Indicator.h \
+ ../src/XPM.h \
+ ../src/LineMarker.h \
+ ../src/Style.h \
+ ../src/ViewStyle.h \
+ ../src/CharClassify.h \
+ ../src/Decoration.h \
+ ../src/CaseFolder.h \
+ ../src/Document.h \
+ ../src/UniConversion.h \
+ ../src/Selection.h \
+ ../src/PositionCache.h \
+ ../src/EditModel.h \
+ ../src/MarginView.h \
+ ../src/EditView.h
+$(DIR_O)\PerLine.obj: \
+ ../src/PerLine.cxx \
+ ../include/Platform.h \
+ ../include/Scintilla.h \
+ ../src/SplitVector.h \
+ ../src/Partitioning.h \
+ ../src/CellBuffer.h \
+ ../src/PerLine.h
+$(DIR_O)\PlatWin.obj: \
+ PlatWin.cxx \
+ ../include/Platform.h \
+ ../lexlib/StringCopy.h \
+ ../src/XPM.h \
+ ../src/UniConversion.h \
+ ../src/FontQuality.h
+$(DIR_O)\PositionCache.obj: \
+ ../src/PositionCache.cxx \
+ ../include/Platform.h \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../src/SplitVector.h \
+ ../src/Partitioning.h \
+ ../src/RunStyles.h \
+ ../src/ContractionState.h \
+ ../src/CellBuffer.h \
+ ../src/KeyMap.h \
+ ../src/Indicator.h \
+ ../src/XPM.h \
+ ../src/LineMarker.h \
+ ../src/Style.h \
+ ../src/ViewStyle.h \
+ ../src/CharClassify.h \
+ ../src/Decoration.h \
+ ../src/CaseFolder.h \
+ ../src/Document.h \
+ ../src/UniConversion.h \
+ ../src/Selection.h \
+ ../src/PositionCache.h
+$(DIR_O)\PropSetSimple.obj: \
+ ../lexlib/PropSetSimple.cxx \
+ ../lexlib/PropSetSimple.h
+$(DIR_O)\RESearch.obj: \
+ ../src/RESearch.cxx \
+ ../src/CharClassify.h \
+ ../src/RESearch.h
+$(DIR_O)\RunStyles.obj: \
+ ../src/RunStyles.cxx \
+ ../include/Platform.h \
+ ../include/Scintilla.h \
+ ../src/SplitVector.h \
+ ../src/Partitioning.h \
+ ../src/RunStyles.h
+$(DIR_O)\ScintillaBase.obj: \
+ ../src/ScintillaBase.cxx \
+ ../include/Platform.h \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../lexlib/PropSetSimple.h \
+ ../src/SplitVector.h \
+ ../src/Partitioning.h \
+ ../src/RunStyles.h \
+ ../src/ContractionState.h \
+ ../src/CellBuffer.h \
+ ../src/CallTip.h \
+ ../src/KeyMap.h \
+ ../src/Indicator.h \
+ ../src/XPM.h \
+ ../src/LineMarker.h \
+ ../src/Style.h \
+ ../src/ViewStyle.h \
+ ../src/CharClassify.h \
+ ../src/Decoration.h \
+ ../src/CaseFolder.h \
+ ../src/Document.h \
+ ../src/Selection.h \
+ ../src/PositionCache.h \
+ ../src/EditModel.h \
+ ../src/MarginView.h \
+ ../src/EditView.h \
+ ../src/Editor.h \
+ ../src/AutoComplete.h \
+ ../src/ScintillaBase.h
+$(DIR_O)\ScintillaBaseL.obj: \
+ ../src/ScintillaBase.cxx \
+ ../include/Platform.h \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../lexlib/PropSetSimple.h \
+ ../src/SplitVector.h \
+ ../src/Partitioning.h \
+ ../src/RunStyles.h \
+ ../src/ContractionState.h \
+ ../src/CellBuffer.h \
+ ../src/CallTip.h \
+ ../src/KeyMap.h \
+ ../src/Indicator.h \
+ ../src/XPM.h \
+ ../src/LineMarker.h \
+ ../src/Style.h \
+ ../src/ViewStyle.h \
+ ../src/CharClassify.h \
+ ../src/Decoration.h \
+ ../src/CaseFolder.h \
+ ../src/Document.h \
+ ../src/Selection.h \
+ ../src/PositionCache.h \
+ ../src/EditModel.h \
+ ../src/MarginView.h \
+ ../src/EditView.h \
+ ../src/Editor.h \
+ ../src/AutoComplete.h \
+ ../src/ScintillaBase.h
+$(DIR_O)\ScintillaWin.obj: \
+ ScintillaWin.cxx \
+ ../include/Platform.h \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../lexlib/StringCopy.h \
+ ../src/SplitVector.h \
+ ../src/Partitioning.h \
+ ../src/RunStyles.h \
+ ../src/ContractionState.h \
+ ../src/CellBuffer.h \
+ ../src/CallTip.h \
+ ../src/KeyMap.h \
+ ../src/Indicator.h \
+ ../src/XPM.h \
+ ../src/LineMarker.h \
+ ../src/Style.h \
+ ../src/ViewStyle.h \
+ ../src/CharClassify.h \
+ ../src/Decoration.h \
+ ../src/CaseFolder.h \
+ ../src/Document.h \
+ ../src/CaseConvert.h \
+ ../src/UniConversion.h \
+ ../src/Selection.h \
+ ../src/PositionCache.h \
+ ../src/EditModel.h \
+ ../src/MarginView.h \
+ ../src/EditView.h \
+ ../src/Editor.h \
+ ../src/AutoComplete.h \
+ ../src/ScintillaBase.h \
+ PlatWin.h
+$(DIR_O)\ScintillaWinL.obj: \
+ ScintillaWin.cxx \
+ ../include/Platform.h \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../lexlib/StringCopy.h \
+ ../src/SplitVector.h \
+ ../src/Partitioning.h \
+ ../src/RunStyles.h \
+ ../src/ContractionState.h \
+ ../src/CellBuffer.h \
+ ../src/CallTip.h \
+ ../src/KeyMap.h \
+ ../src/Indicator.h \
+ ../src/XPM.h \
+ ../src/LineMarker.h \
+ ../src/Style.h \
+ ../src/ViewStyle.h \
+ ../src/CharClassify.h \
+ ../src/Decoration.h \
+ ../src/CaseFolder.h \
+ ../src/Document.h \
+ ../src/CaseConvert.h \
+ ../src/UniConversion.h \
+ ../src/Selection.h \
+ ../src/PositionCache.h \
+ ../src/EditModel.h \
+ ../src/MarginView.h \
+ ../src/EditView.h \
+ ../src/Editor.h \
+ ../src/AutoComplete.h \
+ ../src/ScintillaBase.h \
+ PlatWin.h
+$(DIR_O)\ScintillaWinS.obj: \
+ ScintillaWin.cxx \
+ ../include/Platform.h \
+ ../include/ILexer.h \
+ ../include/Scintilla.h \
+ ../lexlib/StringCopy.h \
+ ../src/SplitVector.h \
+ ../src/Partitioning.h \
+ ../src/RunStyles.h \
+ ../src/ContractionState.h \
+ ../src/CellBuffer.h \
+ ../src/CallTip.h \
+ ../src/KeyMap.h \
+ ../src/Indicator.h \
+ ../src/XPM.h \
+ ../src/LineMarker.h \
+ ../src/Style.h \
+ ../src/ViewStyle.h \
+ ../src/CharClassify.h \
+ ../src/Decoration.h \
+ ../src/CaseFolder.h \
+ ../src/Document.h \
+ ../src/CaseConvert.h \
+ ../src/UniConversion.h \
+ ../src/Selection.h \
+ ../src/PositionCache.h \
+ ../src/EditModel.h \
+ ../src/MarginView.h \
+ ../src/EditView.h \
+ ../src/Editor.h \
+ ../src/AutoComplete.h \
+ ../src/ScintillaBase.h \
+ PlatWin.h
+$(DIR_O)\Selection.obj: \
+ ../src/Selection.cxx \
+ ../include/Platform.h \
+ ../include/Scintilla.h \
+ ../src/Selection.h
+$(DIR_O)\Style.obj: \
+ ../src/Style.cxx \
+ ../include/Platform.h \
+ ../include/Scintilla.h \
+ ../src/Style.h
+$(DIR_O)\StyleContext.obj: \
+ ../lexlib/StyleContext.cxx \
+ ../include/ILexer.h \
+ ../lexlib/LexAccessor.h \
+ ../lexlib/Accessor.h \
+ ../lexlib/StyleContext.h
+$(DIR_O)\UniConversion.obj: \
+ ../src/UniConversion.cxx \
+ ../src/UniConversion.h
+$(DIR_O)\ViewStyle.obj: \
+ ../src/ViewStyle.cxx \
+ ../include/Platform.h \
+ ../include/Scintilla.h \
+ ../src/SplitVector.h \
+ ../src/Partitioning.h \
+ ../src/RunStyles.h \
+ ../src/Indicator.h \
+ ../src/XPM.h \
+ ../src/LineMarker.h \
+ ../src/Style.h \
+ ../src/ViewStyle.h
+$(DIR_O)\WordList.obj: \
+ ../lexlib/WordList.cxx \
+ ../lexlib/StringCopy.h \
+ ../lexlib/WordList.h
+$(DIR_O)\XPM.obj: \
+ ../src/XPM.cxx \
+ ../include/Platform.h \
+ ../src/XPM.h