summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/3rdparty/scintilla/src/Editor.cxx.orig
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/bgfx/3rdparty/scintilla/src/Editor.cxx.orig')
-rw-r--r--3rdparty/bgfx/3rdparty/scintilla/src/Editor.cxx.orig9647
1 files changed, 0 insertions, 9647 deletions
diff --git a/3rdparty/bgfx/3rdparty/scintilla/src/Editor.cxx.orig b/3rdparty/bgfx/3rdparty/scintilla/src/Editor.cxx.orig
deleted file mode 100644
index c17eb21bcee..00000000000
--- a/3rdparty/bgfx/3rdparty/scintilla/src/Editor.cxx.orig
+++ /dev/null
@@ -1,9647 +0,0 @@
-// Scintilla source code edit control
-/** @file Editor.cxx
- ** Main code for the edit control.
- **/
-// Copyright 1998-2011 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 <ctype.h>
-#include <math.h>
-#include <assert.h>
-
-#include <string>
-#include <vector>
-#include <map>
-#include <unordered_map>
-#include <algorithm>
-#include <memory>
-
-#include "Platform.h"
-
-#include "ILexer.h"
-#include "Scintilla.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 "Editor.h"
-
-#ifdef SCI_NAMESPACE
-using namespace Scintilla;
-#endif
-
-/*
- return whether this modification represents an operation that
- may reasonably be deferred (not done now OR [possibly] at all)
-*/
-static bool CanDeferToLastStep(const DocModification &mh) {
- if (mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE))
- return true; // CAN skip
- if (!(mh.modificationType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO)))
- return false; // MUST do
- if (mh.modificationType & SC_MULTISTEPUNDOREDO)
- return true; // CAN skip
- return false; // PRESUMABLY must do
-}
-
-static bool CanEliminate(const DocModification &mh) {
- return
- (mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) != 0;
-}
-
-/*
- return whether this modification represents the FINAL step
- in a [possibly lengthy] multi-step Undo/Redo sequence
-*/
-static bool IsLastStep(const DocModification &mh) {
- return
- (mh.modificationType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO)) != 0
- && (mh.modificationType & SC_MULTISTEPUNDOREDO) != 0
- && (mh.modificationType & SC_LASTSTEPINUNDOREDO) != 0
- && (mh.modificationType & SC_MULTILINEUNDOREDO) != 0;
-}
-
-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
- if (!IsSpaceOrTab(s[i]))
- return false;
- }
- return true;
-}
-
-PrintParameters::PrintParameters() {
- magnification = 0;
- colourMode = SC_PRINT_NORMAL;
- wrapState = eWrapWord;
-}
-
-Editor::Editor() {
- ctrlID = 0;
-
- stylesValid = false;
- technology = SC_TECHNOLOGY_DEFAULT;
- scaleRGBAImage = 100;
-
- cursorMode = SC_CURSORNORMAL;
-
- hasFocus = false;
- hideSelection = false;
- inOverstrike = false;
- drawOverstrikeCaret = true;
- errorStatus = 0;
- mouseDownCaptures = true;
-
- bufferedDraw = true;
- twoPhaseDraw = true;
-
- lastClickTime = 0;
- dwellDelay = SC_TIME_FOREVER;
- ticksToDwell = SC_TIME_FOREVER;
- dwelling = false;
- ptMouseLast.x = 0;
- ptMouseLast.y = 0;
- inDragDrop = ddNone;
- dropWentOutside = false;
- posDrag = SelectionPosition(invalidPosition);
- posDrop = SelectionPosition(invalidPosition);
- hotSpotClickPos = INVALID_POSITION;
- selectionType = selChar;
-
- lastXChosen = 0;
- lineAnchorPos = 0;
- originalAnchorPos = 0;
- wordSelectAnchorStartPos = 0;
- wordSelectAnchorEndPos = 0;
- wordSelectInitialCaretPos = -1;
-
- primarySelection = true;
-
- caretXPolicy = CARET_SLOP | CARET_EVEN;
- caretXSlop = 50;
-
- caretYPolicy = CARET_EVEN;
- caretYSlop = 0;
-
- visiblePolicy = 0;
- visibleSlop = 0;
-
- searchAnchor = 0;
-
- xOffset = 0;
- xCaretMargin = 50;
- horizontalScrollBarVisible = true;
- scrollWidth = 2000;
- trackLineWidth = false;
- lineWidthMaxSeen = 0;
- verticalScrollBarVisible = true;
- endAtLastLine = true;
- caretSticky = SC_CARETSTICKY_OFF;
- marginOptions = SC_MARGINOPTION_NONE;
- mouseSelectionRectangularSwitch = false;
- multipleSelection = false;
- additionalSelectionTyping = false;
- multiPasteMode = SC_MULTIPASTE_ONCE;
- additionalCaretsBlink = true;
- additionalCaretsVisible = true;
- virtualSpaceOptions = SCVS_NONE;
-
- pixmapLine = 0;
- pixmapSelMargin = 0;
- pixmapSelPattern = 0;
- pixmapSelPatternOffset1 = 0;
- pixmapIndentGuide = 0;
- pixmapIndentGuideHighlight = 0;
-
- targetStart = 0;
- targetEnd = 0;
- searchFlags = 0;
-
- topLine = 0;
- posTopLine = 0;
-
- lengthForEncode = -1;
-
- needUpdateUI = 0;
- ContainerNeedsUpdate(SC_UPDATE_CONTENT);
- braces[0] = invalidPosition;
- braces[1] = invalidPosition;
- bracesMatchStyle = STYLE_BRACEBAD;
- highlightGuideColumn = 0;
-
- paintState = notPainting;
- paintAbandonedByStyling = false;
- paintingAllText = false;
- willRedrawAll = false;
-
- modEventMask = SC_MODEVENTMASKALL;
-
- pdoc = new Document();
- pdoc->AddRef();
- pdoc->AddWatcher(this, 0);
-
- recordingMacro = false;
- foldFlags = 0;
- foldAutomatic = 0;
-
- wrapWidth = LineLayout::wrapWidthInfinite;
-
- convertPastes = true;
-
- hsStart = -1;
- hsEnd = -1;
-
- llc.SetLevel(LineLayoutCache::llcCaret);
- posCache.SetSize(0x400);
-
- SetRepresentations();
-}
-
-Editor::~Editor() {
- pdoc->RemoveWatcher(this, 0);
- pdoc->Release();
- pdoc = 0;
- DropGraphics(true);
-}
-
-void Editor::Finalise() {
- SetIdle(false);
- CancelModes();
-}
-
-void Editor::SetRepresentations() {
- reprs.Clear();
-
- // C0 control set
- 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"
- };
- for (size_t j=0; j < (sizeof(reps) / sizeof(reps[0])); j++) {
- char c[2] = { static_cast<char>(j), 0 };
- reprs.SetRepresentation(c, reps[j]);
- }
-
- // C1 control set
- // As well as Unicode mode, ISO-8859-1 should use these
- if (IsUnicodeMode()) {
- const char *repsC1[] = {
- "PAD", "HOP", "BPH", "NBH", "IND", "NEL", "SSA", "ESA",
- "HTS", "HTJ", "VTS", "PLD", "PLU", "RI", "SS2", "SS3",
- "DCS", "PU1", "PU2", "STS", "CCH", "MW", "SPA", "EPA",
- "SOS", "SGCI", "SCI", "CSI", "ST", "OSC", "PM", "APC"
- };
- for (size_t j=0; j < (sizeof(repsC1) / sizeof(repsC1[0])); j++) {
- char c1[3] = { '\xc2', static_cast<char>(0x80+j), 0 };
- reprs.SetRepresentation(c1, repsC1[j]);
- }
- }
-
- // UTF-8 invalid bytes
- if (IsUnicodeMode()) {
- for (int k=0x80; k < 0x100; k++) {
- char hiByte[2] = { static_cast<char>(k), 0 };
- char hexits[4];
- sprintf(hexits, "x%2X", k);
- reprs.SetRepresentation(hiByte, hexits);
- }
- }
-}
-
-void Editor::DropGraphics(bool freeObjects) {
- if (freeObjects) {
- delete pixmapLine;
- pixmapLine = 0;
- delete pixmapSelMargin;
- pixmapSelMargin = 0;
- delete pixmapSelPattern;
- pixmapSelPattern = 0;
- delete pixmapSelPatternOffset1;
- pixmapSelPatternOffset1 = 0;
- delete pixmapIndentGuide;
- pixmapIndentGuide = 0;
- delete pixmapIndentGuideHighlight;
- pixmapIndentGuideHighlight = 0;
- } else {
- if (pixmapLine)
- pixmapLine->Release();
- if (pixmapSelMargin)
- pixmapSelMargin->Release();
- if (pixmapSelPattern)
- pixmapSelPattern->Release();
- if (pixmapSelPatternOffset1)
- pixmapSelPatternOffset1->Release();
- if (pixmapIndentGuide)
- pixmapIndentGuide->Release();
- if (pixmapIndentGuideHighlight)
- pixmapIndentGuideHighlight->Release();
- }
-}
-
-void Editor::AllocateGraphics() {
- if (!pixmapLine)
- pixmapLine = Surface::Allocate(technology);
- if (!pixmapSelMargin)
- pixmapSelMargin = Surface::Allocate(technology);
- if (!pixmapSelPattern)
- pixmapSelPattern = Surface::Allocate(technology);
- if (!pixmapSelPatternOffset1)
- pixmapSelPatternOffset1 = Surface::Allocate(technology);
- if (!pixmapIndentGuide)
- pixmapIndentGuide = Surface::Allocate(technology);
- if (!pixmapIndentGuideHighlight)
- pixmapIndentGuideHighlight = Surface::Allocate(technology);
-}
-
-void Editor::InvalidateStyleData() {
- stylesValid = false;
- vs.technology = technology;
- DropGraphics(false);
- AllocateGraphics();
- llc.Invalidate(LineLayout::llInvalid);
- posCache.Clear();
-}
-
-void Editor::InvalidateStyleRedraw() {
- NeedWrapping();
- InvalidateStyleData();
- Redraw();
-}
-
-void Editor::RefreshStyleData() {
- if (!stylesValid) {
- stylesValid = true;
- AutoSurface surface(this);
- if (surface) {
- vs.Refresh(*surface, pdoc->tabInChars);
- }
- SetScrollBars();
- SetRectangularRange();
- }
-}
-
-Point Editor::GetVisibleOriginInMain() {
- return Point(0,0);
-}
-
-Point Editor::DocumentPointFromView(Point ptView) {
- Point ptDocument = ptView;
- if (wMargin.GetID()) {
- Point ptOrigin = GetVisibleOriginInMain();
- ptDocument.x += ptOrigin.x;
- ptDocument.y += ptOrigin.y;
- } else {
- ptDocument.x += xOffset;
- ptDocument.y += topLine * vs.lineHeight;
- }
- return ptDocument;
-}
-
-int Editor::TopLineOfMain() const {
- if (wMargin.GetID())
- return 0;
- else
- return topLine;
-}
-
-PRectangle Editor::GetClientRectangle() {
- return wMain.GetClientPosition();
-}
-
-PRectangle Editor::GetTextRectangle() {
- PRectangle rc = GetClientRectangle();
- rc.left += vs.textStart;
- rc.right -= vs.rightMarginWidth;
- return rc;
-}
-
-int Editor::LinesOnScreen() {
- PRectangle rcClient = GetClientRectangle();
- int htClient = rcClient.bottom - rcClient.top;
- //Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1);
- return htClient / vs.lineHeight;
-}
-
-int Editor::LinesToScroll() {
- int retVal = LinesOnScreen() - 1;
- if (retVal < 1)
- return 1;
- else
- return retVal;
-}
-
-int Editor::MaxScrollPos() {
- //Platform::DebugPrintf("Lines %d screen = %d maxScroll = %d\n",
- //LinesTotal(), LinesOnScreen(), LinesTotal() - LinesOnScreen() + 1);
- int retVal = cs.LinesDisplayed();
- if (endAtLastLine) {
- retVal -= LinesOnScreen();
- } else {
- retVal--;
- }
- if (retVal < 0) {
- return 0;
- } else {
- return retVal;
- }
-}
-
-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 < (sizeof(reps) / sizeof(reps[0]))) {
- return reps[ch];
- } else {
- return "BAD";
- }
-}
-
-/**
- * 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_;
- }
-};
-
-SelectionPosition Editor::ClampPositionIntoDocument(SelectionPosition sp) const {
- if (sp.Position() < 0) {
- return SelectionPosition(0);
- } else if (sp.Position() > pdoc->Length()) {
- return SelectionPosition(pdoc->Length());
- } else {
- // If not at end of line then set offset to 0
- if (!pdoc->IsLineEndPosition(sp.Position()))
- sp.SetVirtualSpace(0);
- return sp;
- }
-}
-
-Point Editor::LocationFromPosition(SelectionPosition pos) {
- Point pt;
- RefreshStyleData();
- if (pos.Position() == INVALID_POSITION)
- return pt;
- int line = pdoc->LineFromPosition(pos.Position());
- int lineVisible = cs.DisplayFromDoc(line);
- //Platform::DebugPrintf("line=%d\n", line);
- AutoSurface surface(this);
- AutoLineLayout ll(llc, RetrieveLineLayout(line));
- if (surface && ll) {
- // -1 because of adding in for visible lines in following loop.
- pt.y = (lineVisible - topLine - 1) * vs.lineHeight;
- pt.x = 0;
- unsigned int posLineStart = pdoc->LineStart(line);
- LayoutLine(line, surface, vs, ll, wrapWidth);
- int posInLine = pos.Position() - posLineStart;
- // In case of very long line put x at arbitrary large position
- if (posInLine > ll->maxLineLength) {
- pt.x = ll->positions[ll->maxLineLength] - ll->positions[ll->LineStart(ll->lines)];
- }
-
- for (int subLine = 0; subLine < ll->lines; subLine++) {
- if ((posInLine >= ll->LineStart(subLine)) && (posInLine <= ll->LineStart(subLine + 1))) {
- pt.x = ll->positions[posInLine] - ll->positions[ll->LineStart(subLine)];
- if (ll->wrapIndent != 0) {
- int lineStart = ll->LineStart(subLine);
- if (lineStart != 0) // Wrapped
- pt.x += ll->wrapIndent;
- }
- }
- if (posInLine >= ll->LineStart(subLine)) {
- pt.y += vs.lineHeight;
- }
- }
- pt.x += vs.textStart - xOffset;
- }
- pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth;
- return pt;
-}
-
-Point Editor::LocationFromPosition(int pos) {
- return LocationFromPosition(SelectionPosition(pos));
-}
-
-int Editor::XFromPosition(int pos) {
- Point pt = LocationFromPosition(pos);
- return pt.x - vs.textStart + xOffset;
-}
-
-int Editor::XFromPosition(SelectionPosition sp) {
- Point pt = LocationFromPosition(sp);
- return pt.x - vs.textStart + xOffset;
-}
-
-int Editor::LineFromLocation(Point pt) const {
- return cs.DocFromDisplay(pt.y / vs.lineHeight + topLine);
-}
-
-void Editor::SetTopLine(int topLineNew) {
- if ((topLine != topLineNew) && (topLineNew >= 0)) {
- topLine = topLineNew;
- ContainerNeedsUpdate(SC_UPDATE_V_SCROLL);
- }
- posTopLine = pdoc->LineStart(cs.DocFromDisplay(topLine));
-}
-
-SelectionPosition Editor::SPositionFromLocation(Point pt, bool canReturnInvalid, bool charPosition, bool virtualSpace) {
- RefreshStyleData();
- if (canReturnInvalid) {
- PRectangle rcClient = GetTextRectangle();
- if (!rcClient.Contains(pt))
- return SelectionPosition(INVALID_POSITION);
- if (pt.x < vs.textStart)
- return SelectionPosition(INVALID_POSITION);
- if (pt.y < 0)
- return SelectionPosition(INVALID_POSITION);
- }
- pt = DocumentPointFromView(pt);
- pt.x = pt.x - vs.textStart;
- int visibleLine = floor(pt.y / vs.lineHeight);
- if (!canReturnInvalid && (visibleLine < 0))
- visibleLine = 0;
- int lineDoc = cs.DocFromDisplay(visibleLine);
- if (canReturnInvalid && (lineDoc < 0))
- return SelectionPosition(INVALID_POSITION);
- if (lineDoc >= pdoc->LinesTotal())
- return SelectionPosition(canReturnInvalid ? INVALID_POSITION : pdoc->Length());
- unsigned int posLineStart = pdoc->LineStart(lineDoc);
- SelectionPosition retVal(canReturnInvalid ? INVALID_POSITION : static_cast<int>(posLineStart));
- AutoSurface surface(this);
- AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));
- if (surface && ll) {
- LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
- int lineStartSet = cs.DisplayFromDoc(lineDoc);
- int subLine = visibleLine - lineStartSet;
- if (subLine < ll->lines) {
- int lineStart = ll->LineStart(subLine);
- int lineEnd = ll->LineLastVisible(subLine);
- XYPOSITION subLineStart = ll->positions[lineStart];
-
- if (ll->wrapIndent != 0) {
- if (lineStart != 0) // Wrapped
- pt.x -= ll->wrapIndent;
- }
- int i = ll->FindBefore(pt.x + subLineStart, lineStart, lineEnd);
- while (i < lineEnd) {
- if (charPosition) {
- if ((pt.x + subLineStart) < (ll->positions[i + 1])) {
- return SelectionPosition(pdoc->MovePositionOutsideChar(i + posLineStart, 1));
- }
- } else {
- if ((pt.x + subLineStart) < ((ll->positions[i] + ll->positions[i + 1]) / 2)) {
- return SelectionPosition(pdoc->MovePositionOutsideChar(i + posLineStart, 1));
- }
- }
- i++;
- }
- if (virtualSpace) {
- const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth;
- int spaceOffset = (pt.x + subLineStart - ll->positions[lineEnd] + spaceWidth / 2) /
- spaceWidth;
- return SelectionPosition(lineEnd + posLineStart, spaceOffset);
- } else if (canReturnInvalid) {
- if (pt.x < (ll->positions[lineEnd] - subLineStart)) {
- return SelectionPosition(pdoc->MovePositionOutsideChar(lineEnd + posLineStart, 1));
- }
- } else {
- return SelectionPosition(lineEnd + posLineStart);
- }
- }
- if (!canReturnInvalid)
- return SelectionPosition(ll->numCharsInLine + posLineStart);
- }
- return retVal;
-}
-
-int Editor::PositionFromLocation(Point pt, bool canReturnInvalid, bool charPosition) {
- return SPositionFromLocation(pt, canReturnInvalid, charPosition, false).Position();
-}
-
-/**
- * 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.
- */
-SelectionPosition Editor::SPositionFromLineX(int lineDoc, int x) {
- RefreshStyleData();
- if (lineDoc >= pdoc->LinesTotal())
- return SelectionPosition(pdoc->Length());
- //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
- AutoSurface surface(this);
- AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));
- int retVal = 0;
- if (surface && ll) {
- unsigned int posLineStart = pdoc->LineStart(lineDoc);
- LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
- int subLine = 0;
- int lineStart = ll->LineStart(subLine);
- int lineEnd = ll->LineLastVisible(subLine);
- XYPOSITION subLineStart = ll->positions[lineStart];
- XYPOSITION newX = x;
-
- if (ll->wrapIndent != 0) {
- if (lineStart != 0) // Wrapped
- newX -= ll->wrapIndent;
- }
- int i = ll->FindBefore(newX + subLineStart, lineStart, lineEnd);
- while (i < lineEnd) {
- if ((newX + subLineStart) < ((ll->positions[i] + ll->positions[i + 1]) / 2)) {
- retVal = pdoc->MovePositionOutsideChar(i + posLineStart, 1);
- return SelectionPosition(retVal);
- }
- i++;
- }
- const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth;
- int spaceOffset = (newX + subLineStart - ll->positions[lineEnd] + spaceWidth / 2) / spaceWidth;
- return SelectionPosition(lineEnd + posLineStart, spaceOffset);
- }
- return SelectionPosition(retVal);
-}
-
-int Editor::PositionFromLineX(int lineDoc, int x) {
- return SPositionFromLineX(lineDoc, x).Position();
-}
-
-/**
- * If painting then abandon the painting because a wider redraw is needed.
- * @return true if calling code should stop drawing.
- */
-bool Editor::AbandonPaint() {
- if ((paintState == painting) && !paintingAllText) {
- paintState = paintAbandoned;
- }
- return paintState == paintAbandoned;
-}
-
-void Editor::RedrawRect(PRectangle rc) {
- //Platform::DebugPrintf("Redraw %0d,%0d - %0d,%0d\n", rc.left, rc.top, rc.right, rc.bottom);
-
- // Clip the redraw rectangle into the client area
- PRectangle rcClient = GetClientRectangle();
- if (rc.top < rcClient.top)
- rc.top = rcClient.top;
- if (rc.bottom > rcClient.bottom)
- rc.bottom = rcClient.bottom;
- if (rc.left < rcClient.left)
- rc.left = rcClient.left;
- if (rc.right > rcClient.right)
- rc.right = rcClient.right;
-
- if ((rc.bottom > rc.top) && (rc.right > rc.left)) {
- wMain.InvalidateRectangle(rc);
- }
-}
-
-void Editor::Redraw() {
- //Platform::DebugPrintf("Redraw all\n");
- PRectangle rcClient = GetClientRectangle();
- wMain.InvalidateRectangle(rcClient);
- if (wMargin.GetID())
- wMargin.InvalidateAll();
- //wMain.InvalidateAll();
-}
-
-void Editor::RedrawSelMargin(int line, bool allAfter) {
- if (!AbandonPaint()) {
- if (vs.maskInLine) {
- Redraw();
- } else {
- PRectangle rcSelMargin = GetClientRectangle();
- rcSelMargin.right = rcSelMargin.left + vs.fixedColumnWidth;
- if (line != -1) {
- int position = pdoc->LineStart(line);
- PRectangle rcLine = RectangleFromRange(position, position);
-
- // Inflate line rectangle if there are image markers with height larger than line height
- if (vs.largestMarkerHeight > vs.lineHeight) {
- int delta = (vs.largestMarkerHeight - vs.lineHeight + 1) / 2;
- rcLine.top -= delta;
- rcLine.bottom += delta;
- if (rcLine.top < rcSelMargin.top)
- rcLine.top = rcSelMargin.top;
- if (rcLine.bottom > rcSelMargin.bottom)
- rcLine.bottom = rcSelMargin.bottom;
- }
-
- rcSelMargin.top = rcLine.top;
- if (!allAfter)
- rcSelMargin.bottom = rcLine.bottom;
- }
- if (wMargin.GetID()) {
- Point ptOrigin = GetVisibleOriginInMain();
- rcSelMargin.Move(-ptOrigin.x, -ptOrigin.y);
- wMargin.InvalidateRectangle(rcSelMargin);
- } else {
- wMain.InvalidateRectangle(rcSelMargin);
- }
- }
- }
-}
-
-PRectangle Editor::RectangleFromRange(int start, int end) {
- int minPos = start;
- if (minPos > end)
- minPos = end;
- int maxPos = start;
- if (maxPos < end)
- maxPos = end;
- int minLine = cs.DisplayFromDoc(pdoc->LineFromPosition(minPos));
- int lineDocMax = pdoc->LineFromPosition(maxPos);
- int maxLine = cs.DisplayFromDoc(lineDocMax) + cs.GetHeight(lineDocMax) - 1;
- PRectangle rcClient = GetTextRectangle();
- PRectangle rc;
- const int leftTextOverlap = ((xOffset == 0) && (vs.leftMarginWidth > 0)) ? 1 : 0;
- rc.left = vs.textStart - leftTextOverlap;
- rc.top = (minLine - TopLineOfMain()) * vs.lineHeight;
- if (rc.top < rcClient.top)
- rc.top = rcClient.top;
- rc.right = rcClient.right;
- rc.bottom = (maxLine - TopLineOfMain() + 1) * vs.lineHeight;
-
- return rc;
-}
-
-void Editor::InvalidateRange(int start, int end) {
- RedrawRect(RectangleFromRange(start, end));
-}
-
-int Editor::CurrentPosition() const {
- return sel.MainCaret();
-}
-
-bool Editor::SelectionEmpty() const {
- return sel.Empty();
-}
-
-SelectionPosition Editor::SelectionStart() {
- return sel.RangeMain().Start();
-}
-
-SelectionPosition Editor::SelectionEnd() {
- return sel.RangeMain().End();
-}
-
-void Editor::SetRectangularRange() {
- if (sel.IsRectangular()) {
- int xAnchor = XFromPosition(sel.Rectangular().anchor);
- int xCaret = XFromPosition(sel.Rectangular().caret);
- if (sel.selType == Selection::selThin) {
- xCaret = xAnchor;
- }
- int lineAnchorRect = pdoc->LineFromPosition(sel.Rectangular().anchor.Position());
- int lineCaret = pdoc->LineFromPosition(sel.Rectangular().caret.Position());
- int increment = (lineCaret > lineAnchorRect) ? 1 : -1;
- for (int line=lineAnchorRect; line != lineCaret+increment; line += increment) {
- SelectionRange range(SPositionFromLineX(line, xCaret), SPositionFromLineX(line, xAnchor));
- if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) == 0)
- range.ClearVirtualSpace();
- if (line == lineAnchorRect)
- sel.SetSelection(range);
- else
- sel.AddSelectionWithoutTrim(range);
- }
- }
-}
-
-void Editor::ThinRectangularRange() {
- if (sel.IsRectangular()) {
- sel.selType = Selection::selThin;
- if (sel.Rectangular().caret < sel.Rectangular().anchor) {
- sel.Rectangular() = SelectionRange(sel.Range(sel.Count()-1).caret, sel.Range(0).anchor);
- } else {
- sel.Rectangular() = SelectionRange(sel.Range(sel.Count()-1).anchor, sel.Range(0).caret);
- }
- SetRectangularRange();
- }
-}
-
-void Editor::InvalidateSelection(SelectionRange newMain, bool invalidateWholeSelection) {
- if (sel.Count() > 1 || !(sel.RangeMain().anchor == newMain.anchor) || sel.IsRectangular()) {
- invalidateWholeSelection = true;
- }
- int firstAffected = Platform::Minimum(sel.RangeMain().Start().Position(), newMain.Start().Position());
- // +1 for lastAffected ensures caret repainted
- int lastAffected = Platform::Maximum(newMain.caret.Position()+1, newMain.anchor.Position());
- lastAffected = Platform::Maximum(lastAffected, sel.RangeMain().End().Position());
- if (invalidateWholeSelection) {
- for (size_t r=0; r<sel.Count(); r++) {
- firstAffected = Platform::Minimum(firstAffected, sel.Range(r).caret.Position());
- firstAffected = Platform::Minimum(firstAffected, sel.Range(r).anchor.Position());
- lastAffected = Platform::Maximum(lastAffected, sel.Range(r).caret.Position()+1);
- lastAffected = Platform::Maximum(lastAffected, sel.Range(r).anchor.Position());
- }
- }
- ContainerNeedsUpdate(SC_UPDATE_SELECTION);
- InvalidateRange(firstAffected, lastAffected);
-}
-
-void Editor::SetSelection(SelectionPosition currentPos_, SelectionPosition anchor_) {
- currentPos_ = ClampPositionIntoDocument(currentPos_);
- anchor_ = ClampPositionIntoDocument(anchor_);
- int currentLine = pdoc->LineFromPosition(currentPos_.Position());
- /* For Line selection - ensure the anchor and caret are always
- at the beginning and end of the region lines. */
- if (sel.selType == Selection::selLines) {
- if (currentPos_ > anchor_) {
- anchor_ = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(anchor_.Position())));
- currentPos_ = SelectionPosition(pdoc->LineEnd(pdoc->LineFromPosition(currentPos_.Position())));
- } else {
- currentPos_ = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(currentPos_.Position())));
- anchor_ = SelectionPosition(pdoc->LineEnd(pdoc->LineFromPosition(anchor_.Position())));
- }
- }
- SelectionRange rangeNew(currentPos_, anchor_);
- if (sel.Count() > 1 || !(sel.RangeMain() == rangeNew)) {
- InvalidateSelection(rangeNew);
- }
- sel.RangeMain() = rangeNew;
- SetRectangularRange();
- ClaimSelection();
-
- if (highlightDelimiter.NeedsDrawing(currentLine)) {
- RedrawSelMargin();
- }
- QueueIdleWork(WorkNeeded::workUpdateUI);
-}
-
-void Editor::SetSelection(int currentPos_, int anchor_) {
- SetSelection(SelectionPosition(currentPos_), SelectionPosition(anchor_));
-}
-
-// Just move the caret on the main selection
-void Editor::SetSelection(SelectionPosition currentPos_) {
- currentPos_ = ClampPositionIntoDocument(currentPos_);
- int currentLine = pdoc->LineFromPosition(currentPos_.Position());
- if (sel.Count() > 1 || !(sel.RangeMain().caret == currentPos_)) {
- InvalidateSelection(SelectionRange(currentPos_));
- }
- if (sel.IsRectangular()) {
- sel.Rectangular() =
- SelectionRange(SelectionPosition(currentPos_), sel.Rectangular().anchor);
- SetRectangularRange();
- } else {
- sel.RangeMain() =
- SelectionRange(SelectionPosition(currentPos_), sel.RangeMain().anchor);
- }
- ClaimSelection();
-
- if (highlightDelimiter.NeedsDrawing(currentLine)) {
- RedrawSelMargin();
- }
- QueueIdleWork(WorkNeeded::workUpdateUI);
-}
-
-void Editor::SetSelection(int currentPos_) {
- SetSelection(SelectionPosition(currentPos_));
-}
-
-void Editor::SetEmptySelection(SelectionPosition currentPos_) {
- int currentLine = pdoc->LineFromPosition(currentPos_.Position());
- SelectionRange rangeNew(ClampPositionIntoDocument(currentPos_));
- if (sel.Count() > 1 || !(sel.RangeMain() == rangeNew)) {
- InvalidateSelection(rangeNew);
- }
- sel.Clear();
- sel.RangeMain() = rangeNew;
- SetRectangularRange();
- ClaimSelection();
-
- if (highlightDelimiter.NeedsDrawing(currentLine)) {
- RedrawSelMargin();
- }
- QueueIdleWork(WorkNeeded::workUpdateUI);
-}
-
-void Editor::SetEmptySelection(int currentPos_) {
- SetEmptySelection(SelectionPosition(currentPos_));
-}
-
-bool Editor::RangeContainsProtected(int start, int end) const {
- if (vs.ProtectionActive()) {
- if (start > end) {
- int t = start;
- start = end;
- end = t;
- }
- int mask = pdoc->stylingBitsMask;
- for (int pos = start; pos < end; pos++) {
- if (vs.styles[pdoc->StyleAt(pos) & mask].IsProtected())
- return true;
- }
- }
- return false;
-}
-
-bool Editor::SelectionContainsProtected() {
- for (size_t r=0; r<sel.Count(); r++) {
- if (RangeContainsProtected(sel.Range(r).Start().Position(),
- sel.Range(r).End().Position())) {
- return true;
- }
- }
- return false;
-}
-
-/**
- * Asks document to find a good position and then moves out of any invisible positions.
- */
-int Editor::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) const {
- return MovePositionOutsideChar(SelectionPosition(pos), moveDir, checkLineEnd).Position();
-}
-
-SelectionPosition Editor::MovePositionOutsideChar(SelectionPosition pos, int moveDir, bool checkLineEnd) const {
- int posMoved = pdoc->MovePositionOutsideChar(pos.Position(), moveDir, checkLineEnd);
- if (posMoved != pos.Position())
- pos.SetPosition(posMoved);
- if (vs.ProtectionActive()) {
- int mask = pdoc->stylingBitsMask;
- if (moveDir > 0) {
- if ((pos.Position() > 0) && vs.styles[pdoc->StyleAt(pos.Position() - 1) & mask].IsProtected()) {
- while ((pos.Position() < pdoc->Length()) &&
- (vs.styles[pdoc->StyleAt(pos.Position()) & mask].IsProtected()))
- pos.Add(1);
- }
- } else if (moveDir < 0) {
- if (vs.styles[pdoc->StyleAt(pos.Position()) & mask].IsProtected()) {
- while ((pos.Position() > 0) &&
- (vs.styles[pdoc->StyleAt(pos.Position() - 1) & mask].IsProtected()))
- pos.Add(-1);
- }
- }
- }
- return pos;
-}
-
-int Editor::MovePositionTo(SelectionPosition newPos, Selection::selTypes selt, bool ensureVisible) {
- bool simpleCaret = (sel.Count() == 1) && sel.Empty();
- SelectionPosition spCaret = sel.Last();
-
- int delta = newPos.Position() - sel.MainCaret();
- newPos = ClampPositionIntoDocument(newPos);
- newPos = MovePositionOutsideChar(newPos, delta);
- if (!multipleSelection && sel.IsRectangular() && (selt == Selection::selStream)) {
- // Can't turn into multiple selection so clear additional selections
- InvalidateSelection(SelectionRange(newPos), true);
- SelectionRange rangeMain = sel.RangeMain();
- sel.SetSelection(rangeMain);
- }
- if (!sel.IsRectangular() && (selt == Selection::selRectangle)) {
- // Switching to rectangular
- InvalidateSelection(sel.RangeMain(), false);
- SelectionRange rangeMain = sel.RangeMain();
- sel.Clear();
- sel.Rectangular() = rangeMain;
- }
- if (selt != Selection::noSel) {
- sel.selType = selt;
- }
- if (selt != Selection::noSel || sel.MoveExtends()) {
- SetSelection(newPos);
- } else {
- SetEmptySelection(newPos);
- }
- ShowCaretAtCurrentPosition();
-
- int currentLine = pdoc->LineFromPosition(newPos.Position());
- if (ensureVisible) {
- // In case in need of wrapping to ensure DisplayFromDoc works.
- if (currentLine >= wrapPending.start)
- WrapLines(wsAll);
- XYScrollPosition newXY = XYScrollToMakeVisible(
- SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret), xysDefault);
- if (simpleCaret && (newXY.xOffset == xOffset)) {
- // simple vertical scroll then invalidate
- ScrollTo(newXY.topLine);
- InvalidateSelection(SelectionRange(spCaret), true);
- } else {
- SetXYScroll(newXY);
- }
- }
-
- if (highlightDelimiter.NeedsDrawing(currentLine)) {
- RedrawSelMargin();
- }
- return 0;
-}
-
-int Editor::MovePositionTo(int newPos, Selection::selTypes selt, bool ensureVisible) {
- return MovePositionTo(SelectionPosition(newPos), selt, ensureVisible);
-}
-
-SelectionPosition Editor::MovePositionSoVisible(SelectionPosition pos, int moveDir) {
- pos = ClampPositionIntoDocument(pos);
- pos = MovePositionOutsideChar(pos, moveDir);
- int lineDoc = pdoc->LineFromPosition(pos.Position());
- if (cs.GetVisible(lineDoc)) {
- return pos;
- } else {
- int lineDisplay = cs.DisplayFromDoc(lineDoc);
- if (moveDir > 0) {
- // lineDisplay is already line before fold as lines in fold use display line of line after fold
- lineDisplay = Platform::Clamp(lineDisplay, 0, cs.LinesDisplayed());
- return SelectionPosition(pdoc->LineStart(cs.DocFromDisplay(lineDisplay)));
- } else {
- lineDisplay = Platform::Clamp(lineDisplay - 1, 0, cs.LinesDisplayed());
- return SelectionPosition(pdoc->LineEnd(cs.DocFromDisplay(lineDisplay)));
- }
- }
-}
-
-SelectionPosition Editor::MovePositionSoVisible(int pos, int moveDir) {
- return MovePositionSoVisible(SelectionPosition(pos), moveDir);
-}
-
-Point Editor::PointMainCaret() {
- return LocationFromPosition(sel.Range(sel.Main()).caret);
-}
-
-/**
- * Choose the x position that the caret will try to stick to
- * as it moves up and down.
- */
-void Editor::SetLastXChosen() {
- Point pt = PointMainCaret();
- lastXChosen = pt.x + xOffset;
-}
-
-void Editor::ScrollTo(int line, bool moveThumb) {
- int topLineNew = Platform::Clamp(line, 0, MaxScrollPos());
- if (topLineNew != topLine) {
- // Try to optimise small scrolls
-#ifndef UNDER_CE
- int linesToMove = topLine - topLineNew;
- bool performBlit = (abs(linesToMove) <= 10) && (paintState == notPainting);
- willRedrawAll = !performBlit;
-#endif
- SetTopLine(topLineNew);
- // Optimize by styling the view as this will invalidate any needed area
- // which could abort the initial paint if discovered later.
- StyleToPositionInView(PositionAfterArea(GetClientRectangle()));
-#ifndef UNDER_CE
- // Perform redraw rather than scroll if many lines would be redrawn anyway.
- if (performBlit) {
- ScrollText(linesToMove);
- } else {
- Redraw();
- }
- willRedrawAll = false;
-#else
- Redraw();
-#endif
- if (moveThumb) {
- SetVerticalScrollPos();
- }
- }
-}
-
-void Editor::ScrollText(int /* linesToMove */) {
- //Platform::DebugPrintf("Editor::ScrollText %d\n", linesToMove);
- Redraw();
-}
-
-void Editor::HorizontalScrollTo(int xPos) {
- //Platform::DebugPrintf("HorizontalScroll %d\n", xPos);
- if (xPos < 0)
- xPos = 0;
- if (!Wrapping() && (xOffset != xPos)) {
- xOffset = xPos;
- ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
- SetHorizontalScrollPos();
- RedrawRect(GetClientRectangle());
- }
-}
-
-void Editor::VerticalCentreCaret() {
- int lineDoc = pdoc->LineFromPosition(sel.IsRectangular() ? sel.Rectangular().caret.Position() : sel.MainCaret());
- int lineDisplay = cs.DisplayFromDoc(lineDoc);
- int newTop = lineDisplay - (LinesOnScreen() / 2);
- if (topLine != newTop) {
- SetTopLine(newTop > 0 ? newTop : 0);
- RedrawRect(GetClientRectangle());
- }
-}
-
-// Avoid 64 bit compiler warnings.
-// Scintilla does not support text buffers larger than 2**31
-static int istrlen(const char *s) {
- return static_cast<int>(strlen(s));
-}
-
-void Editor::MoveSelectedLines(int lineDelta) {
-
- // if selection doesn't start at the beginning of the line, set the new start
- int selectionStart = SelectionStart().Position();
- int startLine = pdoc->LineFromPosition(selectionStart);
- int beginningOfStartLine = pdoc->LineStart(startLine);
- selectionStart = beginningOfStartLine;
-
- // if selection doesn't end at the beginning of a line greater than that of the start,
- // then set it at the beginning of the next one
- int selectionEnd = SelectionEnd().Position();
- int endLine = pdoc->LineFromPosition(selectionEnd);
- int beginningOfEndLine = pdoc->LineStart(endLine);
- bool appendEol = false;
- if (selectionEnd > beginningOfEndLine
- || selectionStart == selectionEnd) {
- selectionEnd = pdoc->LineStart(endLine + 1);
- appendEol = (selectionEnd == pdoc->Length() && pdoc->LineFromPosition(selectionEnd) == endLine);
- }
-
- // if there's nowhere for the selection to move
- // (i.e. at the beginning going up or at the end going down),
- // stop it right there!
- if ((selectionStart == 0 && lineDelta < 0)
- || (selectionEnd == pdoc->Length() && lineDelta > 0)
- || selectionStart == selectionEnd) {
- return;
- }
-
- UndoGroup ug(pdoc);
-
- if (lineDelta > 0 && selectionEnd == pdoc->LineStart(pdoc->LinesTotal() - 1)) {
- SetSelection(pdoc->MovePositionOutsideChar(selectionEnd - 1, -1), selectionEnd);
- ClearSelection();
- selectionEnd = CurrentPosition();
- }
- SetSelection(selectionStart, selectionEnd);
-
- SelectionText selectedText;
- CopySelectionRange(&selectedText);
-
- int selectionLength = SelectionRange(selectionStart, selectionEnd).Length();
- Point currentLocation = LocationFromPosition(CurrentPosition());
- int currentLine = LineFromLocation(currentLocation);
-
- if (appendEol)
- SetSelection(pdoc->MovePositionOutsideChar(selectionStart - 1, -1), selectionEnd);
- ClearSelection();
-
- const char *eol = StringFromEOLMode(pdoc->eolMode);
- if (currentLine + lineDelta >= pdoc->LinesTotal())
- pdoc->InsertCString(pdoc->Length(), eol);
- GoToLine(currentLine + lineDelta);
-
- pdoc->InsertCString(CurrentPosition(), selectedText.Data());
- if (appendEol) {
- pdoc->InsertCString(CurrentPosition() + selectionLength, eol);
- selectionLength += istrlen(eol);
- }
- SetSelection(CurrentPosition(), CurrentPosition() + selectionLength);
-}
-
-void Editor::MoveSelectedLinesUp() {
- MoveSelectedLines(-1);
-}
-
-void Editor::MoveSelectedLinesDown() {
- MoveSelectedLines(1);
-}
-
-void Editor::MoveCaretInsideView(bool ensureVisible) {
- PRectangle rcClient = GetTextRectangle();
- Point pt = PointMainCaret();
- if (pt.y < rcClient.top) {
- MovePositionTo(SPositionFromLocation(
- Point(lastXChosen - xOffset, rcClient.top),
- false, false, UserVirtualSpace()),
- Selection::noSel, ensureVisible);
- } else if ((pt.y + vs.lineHeight - 1) > rcClient.bottom) {
- int yOfLastLineFullyDisplayed = rcClient.top + (LinesOnScreen() - 1) * vs.lineHeight;
- MovePositionTo(SPositionFromLocation(
- Point(lastXChosen - xOffset, rcClient.top + yOfLastLineFullyDisplayed),
- false, false, UserVirtualSpace()),
- Selection::noSel, ensureVisible);
- }
-}
-
-int Editor::DisplayFromPosition(int pos) {
- int lineDoc = pdoc->LineFromPosition(pos);
- int lineDisplay = cs.DisplayFromDoc(lineDoc);
- AutoSurface surface(this);
- AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc));
- if (surface && ll) {
- LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
- unsigned int posLineStart = 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;
-}
-
-/**
- * Ensure the caret is reasonably visible in context.
- *
-Caret policy in SciTE
-
-If slop is set, we can define a slop value.
-This value defines an unwanted zone (UZ) where the caret is... unwanted.
-This zone is defined as a number of pixels near the vertical margins,
-and as a number of lines near the horizontal margins.
-By keeping the caret away from the edges, it is seen within its context,
-so it is likely that the identifier that the caret is on can be completely seen,
-and that the current line is seen with some of the lines following it which are
-often dependent on that line.
-
-If strict is set, the policy is enforced... strictly.
-The caret is centred on the display if slop is not set,
-and cannot go in the UZ if slop is set.
-
-If jumps is set, the display is moved more energetically
-so the caret can move in the same direction longer before the policy is applied again.
-'3UZ' notation is used to indicate three time the size of the UZ as a distance to the margin.
-
-If even is not set, instead of having symmetrical UZs,
-the left and bottom UZs are extended up to right and top UZs respectively.
-This way, we favour the displaying of useful information: the begining of lines,
-where most code reside, and the lines after the caret, eg. the body of a function.
-
- | | | | |
-slop | strict | jumps | even | Caret can go to the margin | When reaching limit (caret going out of
- | | | | | visibility or going into the UZ) display is...
------+--------+-------+------+--------------------------------------------+--------------------------------------------------------------
- 0 | 0 | 0 | 0 | Yes | moved to put caret on top/on right
- 0 | 0 | 0 | 1 | Yes | moved by one position
- 0 | 0 | 1 | 0 | Yes | moved to put caret on top/on right
- 0 | 0 | 1 | 1 | Yes | centred on the caret
- 0 | 1 | - | 0 | Caret is always on top/on right of display | -
- 0 | 1 | - | 1 | No, caret is always centred | -
- 1 | 0 | 0 | 0 | Yes | moved to put caret out of the asymmetrical UZ
- 1 | 0 | 0 | 1 | Yes | moved to put caret out of the UZ
- 1 | 0 | 1 | 0 | Yes | moved to put caret at 3UZ of the top or right margin
- 1 | 0 | 1 | 1 | Yes | moved to put caret at 3UZ of the margin
- 1 | 1 | - | 0 | Caret is always at UZ of top/right margin | -
- 1 | 1 | 0 | 1 | No, kept out of UZ | moved by one position
- 1 | 1 | 1 | 1 | No, kept out of UZ | moved to put caret at 3UZ of the margin
-*/
-
-Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange range, const XYScrollOptions options) {
- PRectangle rcClient = GetTextRectangle();
- Point pt = LocationFromPosition(range.caret);
- Point ptAnchor = LocationFromPosition(range.anchor);
- const Point ptOrigin = GetVisibleOriginInMain();
- pt.x += ptOrigin.x;
- pt.y += ptOrigin.y;
- ptAnchor.x += ptOrigin.x;
- ptAnchor.y += ptOrigin.y;
- const Point ptBottomCaret(pt.x, pt.y + vs.lineHeight - 1);
-
- XYScrollPosition newXY(xOffset, topLine);
- if (rcClient.Empty()) {
- return newXY;
- }
-
- // Vertical positioning
- if ((options & xysVertical) && (pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || (caretYPolicy & CARET_STRICT) != 0)) {
- const int lineCaret = DisplayFromPosition(range.caret.Position());
- const int linesOnScreen = LinesOnScreen();
- const int halfScreen = Platform::Maximum(linesOnScreen - 1, 2) / 2;
- const bool bSlop = (caretYPolicy & CARET_SLOP) != 0;
- const bool bStrict = (caretYPolicy & CARET_STRICT) != 0;
- const bool bJump = (caretYPolicy & CARET_JUMPS) != 0;
- const bool bEven = (caretYPolicy & CARET_EVEN) != 0;
-
- // It should be possible to scroll the window to show the caret,
- // but this fails to remove the caret on GTK+
- if (bSlop) { // A margin is defined
- int yMoveT, yMoveB;
- if (bStrict) {
- int yMarginT, yMarginB;
- if (!(options & xysUseMargin)) {
- // In drag mode, avoid moves
- // otherwise, a double click will select several lines.
- yMarginT = yMarginB = 0;
- } else {
- // yMarginT must equal to caretYSlop, with a minimum of 1 and
- // a maximum of slightly less than half the heigth of the text area.
- yMarginT = Platform::Clamp(caretYSlop, 1, halfScreen);
- if (bEven) {
- yMarginB = yMarginT;
- } else {
- yMarginB = linesOnScreen - yMarginT - 1;
- }
- }
- yMoveT = yMarginT;
- if (bEven) {
- if (bJump) {
- yMoveT = Platform::Clamp(caretYSlop * 3, 1, halfScreen);
- }
- yMoveB = yMoveT;
- } else {
- yMoveB = linesOnScreen - yMoveT - 1;
- }
- if (lineCaret < topLine + yMarginT) {
- // Caret goes too high
- newXY.topLine = lineCaret - yMoveT;
- } else if (lineCaret > topLine + linesOnScreen - 1 - yMarginB) {
- // Caret goes too low
- newXY.topLine = lineCaret - linesOnScreen + 1 + yMoveB;
- }
- } else { // Not strict
- yMoveT = bJump ? caretYSlop * 3 : caretYSlop;
- yMoveT = Platform::Clamp(yMoveT, 1, halfScreen);
- if (bEven) {
- yMoveB = yMoveT;
- } else {
- yMoveB = linesOnScreen - yMoveT - 1;
- }
- if (lineCaret < topLine) {
- // Caret goes too high
- newXY.topLine = lineCaret - yMoveT;
- } else if (lineCaret > topLine + linesOnScreen - 1) {
- // Caret goes too low
- newXY.topLine = lineCaret - linesOnScreen + 1 + yMoveB;
- }
- }
- } else { // No slop
- if (!bStrict && !bJump) {
- // Minimal move
- if (lineCaret < topLine) {
- // Caret goes too high
- newXY.topLine = lineCaret;
- } else if (lineCaret > topLine + linesOnScreen - 1) {
- // Caret goes too low
- if (bEven) {
- newXY.topLine = lineCaret - linesOnScreen + 1;
- } else {
- newXY.topLine = lineCaret;
- }
- }
- } else { // Strict or going out of display
- if (bEven) {
- // Always center caret
- newXY.topLine = lineCaret - halfScreen;
- } else {
- // Always put caret on top of display
- newXY.topLine = lineCaret;
- }
- }
- }
- if (!(range.caret == range.anchor)) {
- const int lineAnchor = DisplayFromPosition(range.anchor.Position());
- if (lineAnchor < lineCaret) {
- // Shift up to show anchor or as much of range as possible
- newXY.topLine = std::min(newXY.topLine, lineAnchor);
- newXY.topLine = std::max(newXY.topLine, lineCaret - LinesOnScreen());
- } else {
- // Shift down to show anchor or as much of range as possible
- newXY.topLine = std::max(newXY.topLine, lineAnchor - LinesOnScreen());
- newXY.topLine = std::min(newXY.topLine, lineCaret);
- }
- }
- newXY.topLine = Platform::Clamp(newXY.topLine, 0, MaxScrollPos());
- }
-
- // Horizontal positioning
- if ((options & xysHorizontal) && !Wrapping()) {
- const int halfScreen = Platform::Maximum(rcClient.Width() - 4, 4) / 2;
- const bool bSlop = (caretXPolicy & CARET_SLOP) != 0;
- const bool bStrict = (caretXPolicy & CARET_STRICT) != 0;
- const bool bJump = (caretXPolicy & CARET_JUMPS) != 0;
- const bool bEven = (caretXPolicy & CARET_EVEN) != 0;
-
- if (bSlop) { // A margin is defined
- int xMoveL, xMoveR;
- if (bStrict) {
- int xMarginL, xMarginR;
- if (!(options & xysUseMargin)) {
- // In drag mode, avoid moves unless very near of the margin
- // otherwise, a simple click will select text.
- xMarginL = xMarginR = 2;
- } else {
- // xMargin must equal to caretXSlop, with a minimum of 2 and
- // a maximum of slightly less than half the width of the text area.
- xMarginR = Platform::Clamp(caretXSlop, 2, halfScreen);
- if (bEven) {
- xMarginL = xMarginR;
- } else {
- xMarginL = rcClient.Width() - xMarginR - 4;
- }
- }
- if (bJump && bEven) {
- // Jump is used only in even mode
- xMoveL = xMoveR = Platform::Clamp(caretXSlop * 3, 1, halfScreen);
- } else {
- xMoveL = xMoveR = 0; // Not used, avoid a warning
- }
- if (pt.x < rcClient.left + xMarginL) {
- // Caret is on the left of the display
- if (bJump && bEven) {
- newXY.xOffset -= xMoveL;
- } else {
- // Move just enough to allow to display the caret
- newXY.xOffset -= (rcClient.left + xMarginL) - pt.x;
- }
- } else if (pt.x >= rcClient.right - xMarginR) {
- // Caret is on the right of the display
- if (bJump && bEven) {
- newXY.xOffset += xMoveR;
- } else {
- // Move just enough to allow to display the caret
- newXY.xOffset += pt.x - (rcClient.right - xMarginR) + 1;
- }
- }
- } else { // Not strict
- xMoveR = bJump ? caretXSlop * 3 : caretXSlop;
- xMoveR = Platform::Clamp(xMoveR, 1, halfScreen);
- if (bEven) {
- xMoveL = xMoveR;
- } else {
- xMoveL = rcClient.Width() - xMoveR - 4;
- }
- if (pt.x < rcClient.left) {
- // Caret is on the left of the display
- newXY.xOffset -= xMoveL;
- } else if (pt.x >= rcClient.right) {
- // Caret is on the right of the display
- newXY.xOffset += xMoveR;
- }
- }
- } else { // No slop
- if (bStrict ||
- (bJump && (pt.x < rcClient.left || pt.x >= rcClient.right))) {
- // Strict or going out of display
- if (bEven) {
- // Center caret
- newXY.xOffset += pt.x - rcClient.left - halfScreen;
- } else {
- // Put caret on right
- newXY.xOffset += pt.x - rcClient.right + 1;
- }
- } else {
- // Move just enough to allow to display the caret
- if (pt.x < rcClient.left) {
- // Caret is on the left of the display
- if (bEven) {
- newXY.xOffset -= rcClient.left - pt.x;
- } else {
- newXY.xOffset += pt.x - rcClient.right + 1;
- }
- } else if (pt.x >= rcClient.right) {
- // Caret is on the right of the display
- newXY.xOffset += pt.x - rcClient.right + 1;
- }
- }
- }
- // In case of a jump (find result) largely out of display, adjust the offset to display the caret
- if (pt.x + xOffset < rcClient.left + newXY.xOffset) {
- newXY.xOffset = pt.x + xOffset - rcClient.left;
- } else if (pt.x + xOffset >= rcClient.right + newXY.xOffset) {
- newXY.xOffset = pt.x + xOffset - rcClient.right + 1;
- if (vs.caretStyle == CARETSTYLE_BLOCK) {
- // Ensure we can see a good portion of the block caret
- newXY.xOffset += static_cast<int>(vs.aveCharWidth);
- }
- }
- if (!(range.caret == range.anchor)) {
- if (ptAnchor.x < pt.x) {
- // Shift to left to show anchor or as much of range as possible
- int maxOffset = ptAnchor.x + xOffset - rcClient.left - 1;
- int minOffset = pt.x + xOffset - rcClient.right + 1;
- newXY.xOffset = std::min(newXY.xOffset, maxOffset);
- newXY.xOffset = std::max(newXY.xOffset, minOffset);
- } else {
- // Shift to right to show anchor or as much of range as possible
- int minOffset = ptAnchor.x + xOffset - rcClient.right + 1;
- int maxOffset = pt.x + xOffset - rcClient.left - 1;
- newXY.xOffset = std::max(newXY.xOffset, minOffset);
- newXY.xOffset = std::min(newXY.xOffset, maxOffset);
- }
- }
- if (newXY.xOffset < 0) {
- newXY.xOffset = 0;
- }
- }
-
- return newXY;
-}
-
-void Editor::SetXYScroll(XYScrollPosition newXY) {
- if ((newXY.topLine != topLine) || (newXY.xOffset != xOffset)) {
- if (newXY.topLine != topLine) {
- SetTopLine(newXY.topLine);
- SetVerticalScrollPos();
- }
- if (newXY.xOffset != xOffset) {
- xOffset = newXY.xOffset;
- ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
- if (newXY.xOffset > 0) {
- PRectangle rcText = GetTextRectangle();
- if (horizontalScrollBarVisible &&
- rcText.Width() + xOffset > scrollWidth) {
- scrollWidth = xOffset + rcText.Width();
- SetScrollBars();
- }
- }
- SetHorizontalScrollPos();
- }
- Redraw();
- UpdateSystemCaret();
- }
-}
-
-void Editor::ScrollRange(SelectionRange range) {
- SetXYScroll(XYScrollToMakeVisible(range, xysDefault));
-}
-
-void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) {
- SetXYScroll(XYScrollToMakeVisible(SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret),
- static_cast<XYScrollOptions>((useMargin?xysUseMargin:0)|(vert?xysVertical:0)|(horiz?xysHorizontal:0))));
-}
-
-void Editor::ShowCaretAtCurrentPosition() {
- if (hasFocus) {
- caret.active = true;
- caret.on = true;
- SetTicking(true);
- } else {
- caret.active = false;
- caret.on = false;
- }
- InvalidateCaret();
-}
-
-void Editor::DropCaret() {
- caret.active = false;
- InvalidateCaret();
-}
-
-void Editor::InvalidateCaret() {
- if (posDrag.IsValid()) {
- InvalidateRange(posDrag.Position(), posDrag.Position() + 1);
- } else {
- for (size_t r=0; r<sel.Count(); r++) {
- InvalidateRange(sel.Range(r).caret.Position(), sel.Range(r).caret.Position() + 1);
- }
- }
- UpdateSystemCaret();
-}
-
-void Editor::UpdateSystemCaret() {
-}
-
-bool Editor::Wrapping() const {
- return vs.wrapState != eWrapNone;
-}
-
-void Editor::NeedWrapping(int docLineStart, int docLineEnd) {
-//Platform::DebugPrintf("\nNeedWrapping: %0d..%0d\n", docLineStart, docLineEnd);
- if (wrapPending.AddRange(docLineStart, docLineEnd)) {
- llc.Invalidate(LineLayout::llPositions);
- }
- // Wrap lines during idle.
- if (Wrapping() && wrapPending.NeedsWrap()) {
- SetIdle(true);
- }
-}
-
-bool Editor::WrapOneLine(Surface *surface, int lineToWrap) {
- AutoLineLayout ll(llc, RetrieveLineLayout(lineToWrap));
- int linesWrapped = 1;
- if (ll) {
- LayoutLine(lineToWrap, surface, vs, ll, wrapWidth);
- linesWrapped = ll->lines;
- }
- return cs.SetHeight(lineToWrap, linesWrapped +
- (vs.annotationVisible ? pdoc->AnnotationLines(lineToWrap) : 0));
-}
-
-// Perform wrapping for a subset of the lines needing wrapping.
-// wsAll: wrap all lines which need wrapping in this single call
-// wsVisible: wrap currently visible lines
-// wsIdle: wrap one page + 100 lines
-// Return true if wrapping occurred.
-bool Editor::WrapLines(enum wrapScope ws) {
- int goodTopLine = topLine;
- bool wrapOccurred = false;
- if (!Wrapping()) {
- if (wrapWidth != LineLayout::wrapWidthInfinite) {
- wrapWidth = LineLayout::wrapWidthInfinite;
- for (int lineDoc = 0; lineDoc < pdoc->LinesTotal(); lineDoc++) {
- cs.SetHeight(lineDoc, 1 +
- (vs.annotationVisible ? pdoc->AnnotationLines(lineDoc) : 0));
- }
- wrapOccurred = true;
- }
- wrapPending.Reset();
-
- } else if (wrapPending.NeedsWrap()) {
- wrapPending.start = std::min(wrapPending.start, pdoc->LinesTotal());
- if (!SetIdle(true)) {
- // Idle processing not supported so full wrap required.
- ws = wsAll;
- }
- // Decide where to start wrapping
- int lineToWrap = wrapPending.start;
- int lineToWrapEnd = std::min(wrapPending.end, pdoc->LinesTotal());
- const int lineDocTop = cs.DocFromDisplay(topLine);
- const int subLineTop = topLine - cs.DisplayFromDoc(lineDocTop);
- if (ws == wsVisible) {
- lineToWrap = Platform::Clamp(lineDocTop-5, wrapPending.start, pdoc->LinesTotal());
- // Priority wrap to just after visible area.
- // Since wrapping could reduce display lines, treat each
- // as taking only one display line.
- lineToWrapEnd = lineDocTop;
- int lines = LinesOnScreen() + 1;
- while ((lineToWrapEnd < cs.LinesInDoc()) && (lines>0)) {
- if (cs.GetVisible(lineToWrapEnd))
- lines--;
- lineToWrapEnd++;
- }
- // .. and if the paint window is outside pending wraps
- if ((lineToWrap > wrapPending.end) || (lineToWrapEnd < wrapPending.start)) {
- // Currently visible text does not need wrapping
- return false;
- }
- } else if (ws == wsIdle) {
- lineToWrapEnd = lineToWrap + LinesOnScreen() + 100;
- }
- const int lineEndNeedWrap = std::min(wrapPending.end, pdoc->LinesTotal());
- lineToWrapEnd = std::min(lineToWrapEnd, lineEndNeedWrap);
-
- // Ensure all lines being wrapped are styled.
- pdoc->EnsureStyledTo(pdoc->LineStart(lineToWrapEnd));
-
- if (lineToWrap < lineToWrapEnd) {
-
- PRectangle rcTextArea = GetClientRectangle();
- rcTextArea.left = vs.textStart;
- rcTextArea.right -= vs.rightMarginWidth;
- wrapWidth = rcTextArea.Width();
- RefreshStyleData();
- AutoSurface surface(this);
- if (surface) {
-//Platform::DebugPrintf("Wraplines: scope=%0d need=%0d..%0d perform=%0d..%0d\n", ws, wrapPending.start, wrapPending.end, lineToWrap, lineToWrapEnd);
-
- while (lineToWrap < lineToWrapEnd) {
- if (WrapOneLine(surface, lineToWrap)) {
- wrapOccurred = true;
- }
- wrapPending.Wrapped(lineToWrap);
- lineToWrap++;
- }
-
- goodTopLine = cs.DisplayFromDoc(lineDocTop) + std::min(subLineTop, cs.GetHeight(lineDocTop)-1);
- }
- }
-
- // If wrapping is done, bring it to resting position
- if (wrapPending.start >= lineEndNeedWrap) {
- wrapPending.Reset();
- }
- }
-
- if (wrapOccurred) {
- SetScrollBars();
- SetTopLine(Platform::Clamp(goodTopLine, 0, MaxScrollPos()));
- SetVerticalScrollPos();
- }
-
- return wrapOccurred;
-}
-
-void Editor::LinesJoin() {
- if (!RangeContainsProtected(targetStart, targetEnd)) {
- UndoGroup ug(pdoc);
- bool prevNonWS = true;
- for (int pos = targetStart; pos < targetEnd; pos++) {
- if (pdoc->IsPositionInLineEnd(pos)) {
- targetEnd -= pdoc->LenChar(pos);
- pdoc->DelChar(pos);
- if (prevNonWS) {
- // Ensure at least one space separating previous lines
- pdoc->InsertChar(pos, ' ');
- targetEnd++;
- }
- } else {
- prevNonWS = pdoc->CharAt(pos) != ' ';
- }
- }
- }
-}
-
-const char *Editor::StringFromEOLMode(int eolMode) {
- if (eolMode == SC_EOL_CRLF) {
- return "\r\n";
- } else if (eolMode == SC_EOL_CR) {
- return "\r";
- } else {
- return "\n";
- }
-}
-
-void Editor::LinesSplit(int pixelWidth) {
- if (!RangeContainsProtected(targetStart, targetEnd)) {
- if (pixelWidth == 0) {
- PRectangle rcText = GetTextRectangle();
- pixelWidth = rcText.Width();
- }
- int lineStart = pdoc->LineFromPosition(targetStart);
- int lineEnd = pdoc->LineFromPosition(targetEnd);
- const char *eol = StringFromEOLMode(pdoc->eolMode);
- UndoGroup ug(pdoc);
- for (int line = lineStart; line <= lineEnd; line++) {
- AutoSurface surface(this);
- AutoLineLayout ll(llc, RetrieveLineLayout(line));
- if (surface && ll) {
- unsigned int posLineStart = pdoc->LineStart(line);
- LayoutLine(line, surface, vs, ll, pixelWidth);
- for (int subLine = 1; subLine < ll->lines; subLine++) {
- pdoc->InsertCString(
- static_cast<int>(posLineStart + (subLine - 1) * strlen(eol) +
- ll->LineStart(subLine)),
- eol);
- targetEnd += static_cast<int>(strlen(eol));
- }
- }
- lineEnd = pdoc->LineFromPosition(targetEnd);
- }
- }
-}
-
-int Editor::SubstituteMarkerIfEmpty(int markerCheck, int markerDefault) const {
- if (vs.markers[markerCheck].markType == SC_MARK_EMPTY)
- return markerDefault;
- return markerCheck;
-}
-
-bool ValidStyledText(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, 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++;
- width += surface->WidthText(vs.styles[style+styleOffset].font, text + start,
- static_cast<int>(endSegment - start + 1));
- start = endSegment + 1;
- }
- return width;
-}
-
-static int WidestLineWidth(Surface *surface, 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 {
- widthSubLine = surface->WidthText(vs.styles[styleOffset + st.style].font,
- st.text + start, static_cast<int>(lenLine));
- }
- if (widthSubLine > widthMax)
- widthMax = widthSubLine;
- start += lenLine + 1;
- }
- return widthMax;
-}
-
-void DrawStyledText(Surface *surface, ViewStyle &vs, int styleOffset, PRectangle rcText, int ascent,
- const StyledText &st, size_t start, size_t length) {
-
- if (st.multipleStyles) {
- int x = rcText.left;
- size_t i = 0;
- while (i < length) {
- size_t end = i;
- int style = st.styles[i + start];
- while (end < length-1 && st.styles[start+end+1] == style)
- end++;
- style += styleOffset;
- int width = surface->WidthText(vs.styles[style].font,
- st.text + start + i, static_cast<int>(end - i + 1));
- PRectangle rcSegment = rcText;
- rcSegment.left = x;
- rcSegment.right = x + width + 1;
- surface->DrawTextNoClip(rcSegment, vs.styles[style].font,
- ascent, st.text + start + i,
- static_cast<int>(end - i + 1),
- vs.styles[style].fore,
- vs.styles[style].back);
- x += width;
- i = end + 1;
- }
- } else {
- size_t style = st.style + styleOffset;
- surface->DrawTextNoClip(rcText, vs.styles[style].font,
- rcText.top + vs.maxAscent, st.text + start,
- static_cast<int>(length),
- vs.styles[style].fore,
- vs.styles[style].back);
- }
-}
-
-void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) {
- if (vs.fixedColumnWidth == 0)
- return;
-
- AllocateGraphics();
- RefreshStyleData();
- RefreshPixMaps(surfWindow);
-
- PRectangle rcMargin = GetClientRectangle();
- Point ptOrigin = GetVisibleOriginInMain();
- rcMargin.Move(0, -ptOrigin.y);
- rcMargin.left = 0;
- rcMargin.right = vs.fixedColumnWidth;
-
- if (!rc.Intersects(rcMargin))
- return;
-
- Surface *surface;
- if (bufferedDraw) {
- surface = pixmapSelMargin;
- } else {
- surface = surfWindow;
- }
-
- // Clip vertically to paint area to avoid drawing line numbers
- if (rcMargin.bottom > rc.bottom)
- rcMargin.bottom = rc.bottom;
- if (rcMargin.top < rc.top)
- rcMargin.top = rc.top;
-
- PRectangle rcSelMargin = rcMargin;
- rcSelMargin.right = rcMargin.left;
- if (rcSelMargin.bottom < rc.bottom)
- rcSelMargin.bottom = rc.bottom;
-
- 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 = (rcMargin.top + ptOrigin.y) / vs.lineHeight;
- int visibleLine = TopLineOfMain() + lineStartPaint;
- int yposScreen = lineStartPaint * vs.lineHeight - 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 = pdoc->GetLevel(cs.DocFromDisplay(visibleLine));
- if (level & SC_FOLDLEVELWHITEFLAG) {
- int lineBack = cs.DocFromDisplay(visibleLine);
- int levelPrev = level;
- while ((lineBack > 0) && (levelPrev & SC_FOLDLEVELWHITEFLAG)) {
- lineBack--;
- levelPrev = pdoc->GetLevel(lineBack);
- }
- if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) {
- if ((level & SC_FOLDLEVELNUMBERMASK) < (levelPrev & SC_FOLDLEVELNUMBERMASK))
- needWhiteClosure = true;
- }
- }
- if (highlightDelimiter.isEnabled) {
- int lastLine = cs.DocFromDisplay(topLine + LinesOnScreen()) + 1;
- pdoc->GetHighlightDelimiters(highlightDelimiter, pdoc->LineFromPosition(CurrentPosition()), lastLine);
- }
- }
-
- // Old code does not know about new markers needed to distinguish all cases
- int folderOpenMid = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEROPENMID,
- SC_MARKNUM_FOLDEROPEN);
- int folderEnd = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND,
- SC_MARKNUM_FOLDER);
-
- while ((visibleLine < cs.LinesDisplayed()) && yposScreen < rc.bottom) {
-
- PLATFORM_ASSERT(visibleLine < cs.LinesDisplayed());
- int lineDoc = cs.DocFromDisplay(visibleLine);
- PLATFORM_ASSERT(cs.GetVisible(lineDoc));
- bool firstSubLine = visibleLine == cs.DisplayFromDoc(lineDoc);
- bool lastSubLine = visibleLine == (cs.DisplayFromDoc(lineDoc + 1) - 1);
-
- int marks = 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
- int level = pdoc->GetLevel(lineDoc);
- int levelNext = pdoc->GetLevel(lineDoc + 1);
- int levelNum = level & SC_FOLDLEVELNUMBERMASK;
- int levelNextNum = levelNext & SC_FOLDLEVELNUMBERMASK;
- if (level & SC_FOLDLEVELHEADERFLAG) {
- if (firstSubLine) {
- if (levelNum < levelNextNum) {
- if (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 (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;
- int firstFollowupLine = cs.DocFromDisplay(cs.DisplayFromDoc(lineDoc + 1));
- int firstFollowupLineLevel = pdoc->GetLevel(firstFollowupLine);
- int secondFollowupLineLevelNum = pdoc->GetLevel(firstFollowupLine + 1) & SC_FOLDLEVELNUMBERMASK;
- if (!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 = yposScreen;
- rcMarker.bottom = 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 (foldFlags & SC_FOLDFLAG_LEVELNUMBERS) {
- int lev = pdoc->GetLevel(lineDoc);
- sprintf(number, "%c%c %03X %03X",
- (lev & SC_FOLDLEVELHEADERFLAG) ? 'H' : '_',
- (lev & SC_FOLDLEVELWHITEFLAG) ? 'W' : '_',
- lev & SC_FOLDLEVELNUMBERMASK,
- lev >> 16
- );
- }
- PRectangle rcNumber = rcMarker;
- // Right justify
- XYPOSITION width = surface->WidthText(vs.styles[STYLE_LINENUMBER].font, number, istrlen(number));
- XYPOSITION xpos = rcNumber.right - width - vs.marginNumberPadding;
- rcNumber.left = xpos;
- surface->DrawTextNoClip(rcNumber, vs.styles[STYLE_LINENUMBER].font,
- rcNumber.top + vs.maxAscent, number, istrlen(number),
- vs.styles[STYLE_LINENUMBER].fore,
- vs.styles[STYLE_LINENUMBER].back);
- } 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 = 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, rcMarker.top + vs.maxAscent,
- 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 (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, vs.styles[STYLE_LINENUMBER].font, 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);
-
- if (bufferedDraw) {
- surfWindow->Copy(rcMargin, Point(rcMargin.left, rcMargin.top), *pixmapSelMargin);
- }
-}
-
-void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid) {
- int ydiff = (rcTab.bottom - rcTab.top) / 2;
- int xhead = rcTab.right - 1 - ydiff;
- if (xhead <= rcTab.left) {
- ydiff -= rcTab.left - xhead - 1;
- xhead = rcTab.left - 1;
- }
- if ((rcTab.left + 2) < (rcTab.right - 1))
- surface->MoveTo(rcTab.left + 2, ymid);
- else
- surface->MoveTo(rcTab.right - 1, ymid);
- surface->LineTo(rcTab.right - 1, ymid);
- surface->LineTo(xhead, ymid - ydiff);
- surface->MoveTo(rcTab.right - 1, ymid);
- surface->LineTo(xhead, ymid + ydiff);
-}
-
-LineLayout *Editor::RetrieveLineLayout(int lineNumber) {
- int posLineStart = pdoc->LineStart(lineNumber);
- int posLineEnd = pdoc->LineStart(lineNumber + 1);
- PLATFORM_ASSERT(posLineEnd >= posLineStart);
- int lineCaret = pdoc->LineFromPosition(sel.MainCaret());
- return llc.Retrieve(lineNumber, lineCaret,
- posLineEnd - posLineStart, pdoc->GetStyleClock(),
- LinesOnScreen() + 1, 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 Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll, int width) {
-//void LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll, int width, Document *pdoc, PositionCache &posCache, SpecialRepresentations &reprs) {
- if (!ll)
- return;
-
- PLATFORM_ASSERT(line < pdoc->LinesTotal());
- PLATFORM_ASSERT(ll->chars != NULL);
- int posLineStart = pdoc->LineStart(line);
- int posLineEnd = 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 = pdoc->LineEnd(line) - posLineStart;
- }
- if (lineLength == ll->numCharsInLine) {
- // See if chars, styles, indicators, are all the same
- bool allSame = true;
- const int styleMask = pdoc->stylingBitsMask;
- // Check base line layout
- char styleByte = 0;
- int numCharsInLine = 0;
- while (numCharsInLine < lineLength) {
- int charInDoc = numCharsInLine + posLineStart;
- char chDoc = pdoc->CharAt(charInDoc);
- styleByte = pdoc->StyleAt(charInDoc);
- allSame = allSame &&
- (ll->styles[numCharsInLine] == static_cast<unsigned char>(styleByte & styleMask));
- allSame = allSame &&
- (ll->indicators[numCharsInLine] == static_cast<char>(styleByte & ~styleMask));
- 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 = pdoc->FindColumn(line, vstyle.theEdge);
- if (ll->edgeColumn >= posLineStart) {
- ll->edgeColumn -= posLineStart;
- }
- } else {
- ll->edgeColumn = -1;
- }
-
- char styleByte;
- const int styleMask = pdoc->stylingBitsMask;
- ll->styleBitsSet = 0;
- // Fill base line layout
- const int lineLength = posLineEnd - posLineStart;
- pdoc->GetCharRange(ll->chars, posLineStart, lineLength);
- pdoc->GetStyleRange(ll->styles, posLineStart, lineLength);
- int numCharsBeforeEOL = pdoc->LineEnd(line) - posLineStart;
- const int numCharsInLine = (vstyle.viewEOL) ? lineLength : numCharsBeforeEOL;
- for (int styleInLine = 0; styleInLine < numCharsInLine; styleInLine++) {
- styleByte = ll->styles[styleInLine];
- ll->styleBitsSet |= styleByte;
- ll->styles[styleInLine] = static_cast<char>(styleByte & styleMask);
- ll->indicators[styleInLine] = static_cast<char>(styleByte & ~styleMask);
- }
- styleByte = static_cast<char>(((lineLength > 0) ? ll->styles[lineLength-1] : 0) & styleMask);
- 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] = styleByte; // For eolFilled
- ll->indicators[numCharsInLine] = 0;
-
- // 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, 0, numCharsInLine, posLineStart, 0, false, pdoc, &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, 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, 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 = 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 = pdoc->MovePositionOutsideChar(p + posLineStart, -1)
- - posLineStart;
- }
- if (lastGoodBreak == lastLineStart) {
- // Ensure at least one character on line.
- lastGoodBreak = 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 = pdoc->MovePositionOutsideChar(p + posLineStart, -1)
- - posLineStart;
- p = pdoc->MovePositionOutsideChar(p + 1 + posLineStart, 1) - posLineStart;
- continue;
- } else if (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;
- }
-}
-
-ColourDesired Editor::SelectionBackground(ViewStyle &vsDraw, bool main) const {
- return main ?
- (primarySelection ? vsDraw.selColours.back : vsDraw.selBackground2) :
- vsDraw.selAdditionalBackground;
-}
-
-ColourDesired Editor::TextBackground(ViewStyle &vsDraw, bool overrideBackground,
- ColourDesired background, int inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll) const {
- if (inSelection == 1) {
- if (vsDraw.selColours.back.isSet && (vsDraw.selAlpha == SC_ALPHA_NOALPHA)) {
- return SelectionBackground(vsDraw, true);
- }
- } else if (inSelection == 2) {
- if (vsDraw.selColours.back.isSet && (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA)) {
- return SelectionBackground(vsDraw, false);
- }
- } 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 (overrideBackground && (styleMain != STYLE_BRACELIGHT) && (styleMain != STYLE_BRACEBAD)) {
- return background;
- } else {
- return vsDraw.styles[styleMain].back;
- }
-}
-
-void Editor::DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight) {
- Point from(0, ((lineVisible & 1) && (lineHeight & 1)) ? 1 : 0);
- PRectangle rcCopyArea(start + 1, rcSegment.top, start + 2, rcSegment.bottom);
- surface->Copy(rcCopyArea, from,
- highlight ? *pixmapIndentGuideHighlight : *pixmapIndentGuide);
-}
-
-void Editor::DrawWrapMarker(Surface *surface, PRectangle rcPlace,
- bool isEndMarker, ColourDesired wrapColour) {
- surface->PenColour(wrapColour);
-
- enum { xa = 1 }; // gap before start
- int w = rcPlace.right - rcPlace.left - xa - 1;
-
- bool xStraight = isEndMarker; // x-mirrored symbol for start marker
-
- int x0 = xStraight ? rcPlace.left : rcPlace.right - 1;
- int y0 = rcPlace.top;
-
- int dy = (rcPlace.bottom - rcPlace.top) / 5;
- int y = (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);
-}
-
-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, ViewStyle &vsDraw, PRectangle rcSegment,
- const char *s, ColourDesired textBack, ColourDesired textFore, bool twoPhaseDraw) {
- if (!twoPhaseDraw) {
- surface->FillRectangle(rcSegment, textBack);
- }
- Font &ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;
- int normalCharHeight = surface->Ascent(ctrlCharsFont) -
- surface->InternalLeading(ctrlCharsFont);
- PRectangle rcCChar = rcSegment;
- rcCChar.left = rcCChar.left + 1;
- rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight;
- rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1;
- PRectangle rcCentral = rcCChar;
- rcCentral.top++;
- rcCentral.bottom--;
- surface->FillRectangle(rcCentral, textFore);
- PRectangle rcChar = rcCChar;
- rcChar.left++;
- rcChar.right--;
- surface->DrawTextClipped(rcChar, ctrlCharsFont,
- rcSegment.top + vsDraw.maxAscent, s, istrlen(s),
- textBack, textFore);
-}
-
-void Editor::DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll,
- int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart,
- bool overrideBackground, ColourDesired background,
- bool drawWrapMarkEnd, ColourDesired wrapColour) {
-
- const int posLineStart = pdoc->LineStart(line);
- const int styleMask = pdoc->stylingBitsMask;
- PRectangle rcSegment = rcLine;
-
- const bool lastSubLine = subLine == (ll->lines - 1);
- XYPOSITION virtualSpace = 0;
- if (lastSubLine) {
- const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
- virtualSpace = sel.VirtualSpaceFor(pdoc->LineEnd(line)) * spaceWidth;
- }
- XYPOSITION xEol = 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, overrideBackground ? background : vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back);
- if (!hideSelection && ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA))) {
- SelectionSegment virtualSpaceRange(SelectionPosition(pdoc->LineEnd(line)), SelectionPosition(pdoc->LineEnd(line), sel.VirtualSpaceFor(pdoc->LineEnd(line))));
- for (size_t r=0; r<sel.Count(); r++) {
- int alpha = (r == sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
- if (alpha == SC_ALPHA_NOALPHA) {
- SelectionSegment portion = 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] - subLineStart + portion.start.VirtualSpace() * spaceWidth;
- rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - 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 == sel.Main()));
- }
- }
- }
- }
- }
-
- int eolInSelection = 0;
- int alpha = SC_ALPHA_NOALPHA;
- if (!hideSelection) {
- int posAfterLineEnd = pdoc->LineStart(line + 1);
- eolInSelection = (subLine == (ll->lines - 1)) ? 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] - subLineStart + virtualSpace;
- rcSegment.right = xStart + ll->positions[eolPos+1] - subLineStart + virtualSpace;
- blobsWidth += rcSegment.Width();
- char hexits[4];
- const char *ctrlChar;
- unsigned char chEOL = ll->chars[eolPos];
- if (UTF8IsAscii(chEOL)) {
- ctrlChar = ControlCharacterString(chEOL);
- } else {
- sprintf(hexits, "x%2X", chEOL);
- ctrlChar = hexits;
- }
- int styleMain = ll->styles[eolPos];
- ColourDesired textBack = TextBackground(vsDraw, overrideBackground, background, eolInSelection, false, styleMain, eolPos, ll);
- 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 < pdoc->LinesTotal() - 1)) {
- if (alpha == SC_ALPHA_NOALPHA) {
- surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1));
- } 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 < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
- SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), 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 < pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) {
- surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1));
- } else {
- if (overrideBackground) {
- surface->FillRectangle(rcSegment, background);
- } else if (line < pdoc->LinesTotal() - 1) {
- surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back);
- } else if (vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].eolFilled) {
- surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back);
- } else {
- surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back);
- }
- if (eolInSelection && vsDraw.selColours.back.isSet && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
- SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), 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 < pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) {
- surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1));
- } else {
- if (overrideBackground) {
- surface->FillRectangle(rcSegment, background);
- } else if (vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].eolFilled) {
- surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back);
- } else {
- surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back);
- }
- if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selColours.back.isSet && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) {
- SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), alpha);
- }
- }
-
- 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, wrapColour);
- }
-}
-
-void Editor::DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, 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);
-}
-
-void Editor::DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
- PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under) {
- // Draw decorators
- const int posLineStart = pdoc->LineStart(line);
- const int lineStart = ll->LineStart(subLine);
- const int posLineEnd = posLineStart + lineEnd;
-
- if (!under) {
- // Draw indicators
- // foreach indicator...
- for (int indicnum = 0, mask = 1 << pdoc->stylingBits; mask < 0x100; indicnum++) {
- if (!(mask & ll->styleBitsSet)) {
- mask <<= 1;
- continue;
- }
- int startPos = -1;
- // foreach style pos in line...
- for (int indicPos = lineStart; indicPos <= lineEnd; indicPos++) {
- // look for starts...
- if (startPos < 0) {
- // NOT in indicator run, looking for START
- if (indicPos < lineEnd && (ll->indicators[indicPos] & mask))
- startPos = indicPos;
- }
- // ... or ends
- if (startPos >= 0) {
- // IN indicator run, looking for END
- if (indicPos >= lineEnd || !(ll->indicators[indicPos] & mask)) {
- // AT end of indicator run, DRAW it!
- DrawIndicator(indicnum, startPos, indicPos, surface, vsDraw, xStart, rcLine, ll, subLine);
- // RESET control var
- startPos = -1;
- }
- }
- }
- mask <<= 1;
- }
- }
-
- for (Decoration *deco = 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 = deco->rs.EndRun(endPos);
- }
- }
- }
-
- // Use indicators to highlight matching braces
- if ((vs.braceHighlightIndicatorSet && (bracesMatchStyle == STYLE_BRACELIGHT)) ||
- (vs.braceBadLightIndicatorSet && (bracesMatchStyle == STYLE_BRACEBAD))) {
- int braceIndicator = (bracesMatchStyle == STYLE_BRACELIGHT) ? vs.braceHighlightIndicator : vs.braceBadLightIndicator;
- if (under == vsDraw.indicators[braceIndicator].under) {
- Range rangeLine(posLineStart + lineStart, posLineEnd);
- if (rangeLine.ContainsCharacter(braces[0])) {
- int braceOffset = braces[0] - posLineStart;
- if (braceOffset < ll->numCharsInLine) {
- DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine);
- }
- }
- if (rangeLine.ContainsCharacter(braces[1])) {
- int braceOffset = braces[1] - posLineStart;
- if (braceOffset < ll->numCharsInLine) {
- DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine);
- }
- }
- }
- }
-}
-
-void Editor::DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart,
- PRectangle rcLine, LineLayout *ll, int subLine) {
- int indent = pdoc->GetLineIndentation(line) * vsDraw.spaceWidth;
- PRectangle rcSegment = rcLine;
- int annotationLine = subLine - ll->lines;
- const StyledText stAnnotation = pdoc->AnnotationStyledText(line);
- if (stAnnotation.text && ValidStyledText(vsDraw, vsDraw.annotationStyleOffset, stAnnotation)) {
- surface->FillRectangle(rcSegment, vsDraw.styles[0].back);
- if (vs.annotationVisible == ANNOTATION_BOXED) {
- // Only care about calculating width if need to draw box
- int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation);
- widthAnnotation += vsDraw.spaceWidth * 2; // Margins
- rcSegment.left = xStart + indent;
- rcSegment.right = rcSegment.left + widthAnnotation;
- } else {
- rcSegment.left = xStart;
- }
- const int annotationLines = 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 (vs.annotationVisible == ANNOTATION_BOXED) {
- surface->FillRectangle(rcText,
- vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back);
- rcText.left += vsDraw.spaceWidth;
- }
- DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText, rcText.top + vsDraw.maxAscent,
- stAnnotation, start, lengthAnnotation);
- if (vs.annotationVisible == ANNOTATION_BOXED) {
- surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore);
- surface->MoveTo(rcSegment.left, rcSegment.top);
- surface->LineTo(rcSegment.left, rcSegment.bottom);
- surface->MoveTo(rcSegment.right, rcSegment.top);
- surface->LineTo(rcSegment.right, rcSegment.bottom);
- if (subLine == ll->lines) {
- surface->MoveTo(rcSegment.left, rcSegment.top);
- surface->LineTo(rcSegment.right, rcSegment.top);
- }
- if (subLine == ll->lines+annotationLines-1) {
- surface->MoveTo(rcSegment.left, rcSegment.bottom - 1);
- surface->LineTo(rcSegment.right, rcSegment.bottom - 1);
- }
- }
- }
-}
-
-void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart,
- PRectangle rcLine, LineLayout *ll, int subLine) {
-
- if (subLine >= ll->lines) {
- DrawAnnotation(surface, vsDraw, line, xStart, rcLine, ll, subLine);
- return; // No further drawing
- }
-
- PRectangle rcSegment = rcLine;
-
- // 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.
- Font &ctrlCharsFont = vsDraw.styles[STYLE_CONTROLCHAR].font;
-
- // See if something overrides the line background color: Either if caret is on the line
- // and background color is set for that, or if a marker is defined that forces its background
- // color onto the line, or if a marker is defined but has no selection margin in which to
- // display itself (as long as it's not an SC_MARK_EMPTY marker). These are checked in order
- // with the earlier taking precedence. When multiple markers cause background override,
- // the color for the highest numbered one is used.
- bool overrideBackground = false;
- ColourDesired background;
- if ((caret.active || vsDraw.alwaysShowCaretLineBackground) && vsDraw.showCaretLineBackground && (vsDraw.caretLineAlpha == SC_ALPHA_NOALPHA) && ll->containsCaret) {
- overrideBackground = true;
- background = vsDraw.caretLineBackground;
- }
- if (!overrideBackground) {
- int marks = pdoc->GetMark(line);
- for (int markBit = 0; (markBit < 32) && marks; markBit++) {
- if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND) &&
- (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
- background = vsDraw.markers[markBit].back;
- overrideBackground = true;
- }
- marks >>= 1;
- }
- }
- if (!overrideBackground) {
- if (vsDraw.maskInLine) {
- int marksMasked = pdoc->GetMark(line) & vsDraw.maskInLine;
- if (marksMasked) {
- for (int markBit = 0; (markBit < 32) && marksMasked; markBit++) {
- if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY) &&
- (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) {
- overrideBackground = true;
- background = vsDraw.markers[markBit].back;
- }
- marksMasked >>= 1;
- }
- }
- }
- }
-
- const bool drawWhitespaceBackground = (vsDraw.viewWhitespace != wsInvisible) &&
- (!overrideBackground) && (vsDraw.whitespaceColours.back.isSet);
-
- bool inIndentation = subLine == 0; // Do not handle indentation except on first subline.
- const XYPOSITION indentWidth = pdoc->IndentSize() * vsDraw.spaceWidth;
- const XYPOSITION epsilon = 0.0001f; // A small nudge to avoid floating point precision issues
-
- const int posLineStart = pdoc->LineStart(line);
-
- const int startseg = ll->LineStart(subLine);
- const XYACCUMULATOR subLineStart = ll->positions[startseg];
- int lineStart = 0;
- int lineEnd = 0;
- if (subLine < ll->lines) {
- lineStart = ll->LineStart(subLine);
- lineEnd = ll->LineStart(subLine + 1);
- if (subLine == ll->lines - 1) {
- lineEnd = ll->numCharsBeforeEOL;
- }
- }
-
- const ColourDesired wrapColour = vsDraw.WrapColour();
-
- bool drawWrapMarkEnd = false;
-
- if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_END) {
- if (subLine + 1 < ll->lines) {
- drawWrapMarkEnd = ll->LineStart(subLine + 1) != 0;
- }
- }
-
- if (ll->wrapIndent != 0) {
-
- bool continuedWrapLine = false;
- if (subLine < ll->lines) {
- continuedWrapLine = ll->LineStart(subLine) != 0;
- }
-
- if (continuedWrapLine) {
- // draw continuation rect
- PRectangle rcPlace = rcSegment;
-
- rcPlace.left = ll->positions[startseg] + xStart - subLineStart;
- rcPlace.right = rcPlace.left + ll->wrapIndent;
-
- // default bgnd here..
- surface->FillRectangle(rcSegment, overrideBackground ? background :
- vsDraw.styles[STYLE_DEFAULT].back);
-
- // main line style would be below but this would be inconsistent with end markers
- // also would possibly not be the style at wrap point
- //int styleMain = ll->styles[lineStart];
- //surface->FillRectangle(rcPlace, vsDraw.styles[styleMain].back);
-
- if (vsDraw.wrapVisualFlags & SC_WRAPVISUALFLAG_START) {
-
- 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, 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;
-
- ll->psel = &sel;
-
- if (twoPhaseDraw) {
- BreakFinder bfBack(ll, lineStart, lineEnd, posLineStart, xStartVisible, selBackDrawn, pdoc, &reprs);
-
- // Background drawing loop
- while (bfBack.More()) {
-
- const TextSegment ts = bfBack.Next();
- const int i = ts.end() - 1;
- const int iDoc = i + posLineStart;
-
- rcSegment.left = ll->positions[ts.start] + xStart - subLineStart;
- rcSegment.right = ll->positions[ts.end()] + xStart - 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 : sel.CharacterInSelection(iDoc);
- const bool inHotspot = (ll->hsStart != -1) && (iDoc >= ll->hsStart) && (iDoc < ll->hsEnd);
- ColourDesired textBack = TextBackground(vsDraw, overrideBackground, background, inSelection,
- inHotspot, ll->styles[i], i, ll);
- 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 - subLineStart,
- rcSegment.top,
- ll->positions[cpos + ts.start + 1] + xStart - 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, lineEnd,
- xStart, subLine, subLineStart, overrideBackground, background,
- drawWrapMarkEnd, wrapColour);
- }
-
- DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineEnd, true);
-
- if (vsDraw.edgeState == EDGE_LINE) {
- int edgeX = vsDraw.theEdge * vsDraw.spaceWidth;
- rcSegment.left = edgeX + xStart;
- if ((ll->wrapIndent != 0) && (lineStart != 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 = 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;
- }
-
- inIndentation = subLine == 0; // Do not handle indentation except on first subline.
- // Foreground drawing loop
- BreakFinder bfFore(ll, lineStart, lineEnd, posLineStart, xStartVisible,
- ((!twoPhaseDraw && selBackDrawn) || vsDraw.selColours.fore.isSet), pdoc, &reprs);
-
- while (bfFore.More()) {
-
- const TextSegment ts = bfFore.Next();
- const int i = ts.end() - 1;
- const int iDoc = i + posLineStart;
-
- rcSegment.left = ll->positions[ts.start] + xStart - subLineStart;
- rcSegment.right = ll->positions[ts.end()] + xStart - 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;
- Font &textFont = vsDraw.styles[styleMain].font;
- //hotspot foreground
- if (ll->hsStart != -1 && iDoc >= ll->hsStart && iDoc < hsEnd) {
- if (vsDraw.hotspotColours.fore.isSet)
- textFore = vsDraw.hotspotColours.fore;
- }
- const int inSelection = hideSelection ? 0 : sel.CharacterInSelection(iDoc);
- if (inSelection && (vsDraw.selColours.fore.isSet)) {
- textFore = (inSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground;
- }
- const bool inHotspot = (ll->hsStart != -1) && (iDoc >= ll->hsStart) && (iDoc < ll->hsEnd);
- ColourDesired textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, inHotspot, styleMain, i, ll);
- 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 = (ll->positions[i] + epsilon) / indentWidth;
- indentCount <= (ll->positions[i + 1] - epsilon) / indentWidth;
- indentCount++) {
- if (indentCount > 0) {
- int xIndent = 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, 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 - subLineStart,
- rcSegment.top,
- ll->positions[cpos + ts.start + 1] + xStart - subLineStart,
- rcSegment.bottom);
- surface->FillRectangle(rcSpace, textBack);
- }
- PRectangle rcDot(xmid + xStart - subLineStart, rcSegment.top + vsDraw.lineHeight / 2, 0, 0);
- rcDot.right = rcDot.left + vs.whitespaceSize;
- rcDot.bottom = rcDot.top + vs.whitespaceSize;
- surface->FillRectangle(rcDot, textFore);
- }
- }
- if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
- for (int indentCount = (ll->positions[cpos + ts.start] + epsilon) / indentWidth;
- indentCount <= (ll->positions[cpos + ts.start + 1] - epsilon) / indentWidth;
- indentCount++) {
- if (indentCount > 0) {
- int xIndent = indentCount * indentWidth;
- DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
- (ll->xHighlightGuide == xIndent));
- }
- }
- }
- } else {
- inIndentation = false;
- }
- }
- }
- }
- if (ll->hsStart != -1 && vsDraw.hotspotUnderline && iDoc >= ll->hsStart && iDoc < ll->hsEnd) {
- 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 = pdoc->GetLineIndentation(line);
- int xStartText = ll->positions[pdoc->GetLineIndentPosition(line) - posLineStart];
-
- // Find the most recent line with some text
-
- int lineLastWithText = line;
- while (lineLastWithText > Platform::Maximum(line-20, 0) && 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 = pdoc->GetLineIndentation(lineLastWithText);
- int isFoldHeader = pdoc->GetLevel(lineLastWithText) & SC_FOLDLEVELHEADERFLAG;
- if (isFoldHeader) {
- // Level is one more level than parent
- indentLastWithText += pdoc->IndentSize();
- }
- if (vsDraw.viewIndentationGuides == ivLookForward) {
- // In viLookForward mode, previous line only used if it is a fold header
- if (isFoldHeader) {
- indentSpace = Platform::Maximum(indentSpace, indentLastWithText);
- }
- } else { // viLookBoth
- indentSpace = Platform::Maximum(indentSpace, indentLastWithText);
- }
- }
-
- int lineNextWithText = line;
- while (lineNextWithText < Platform::Minimum(line+20, pdoc->LinesTotal()) && 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,
- pdoc->GetLineIndentation(lineNextWithText));
- }
-
- for (int indentPos = pdoc->IndentSize(); indentPos < indentSpace; indentPos += pdoc->IndentSize()) {
- int xIndent = indentPos * vsDraw.spaceWidth;
- if (xIndent < xStartText) {
- DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment,
- (ll->xHighlightGuide == xIndent));
- }
- }
- }
-
- DrawIndicators(surface, vsDraw, line, xStart, rcLine, ll, subLine, lineEnd, false);
-
- // End of the drawing of the current line
- if (!twoPhaseDraw) {
- DrawEOL(surface, vsDraw, rcLine, ll, line, lineEnd,
- xStart, subLine, subLineStart, overrideBackground, background,
- drawWrapMarkEnd, wrapColour);
- }
- 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 = sel.VirtualSpaceFor(pdoc->LineEnd(line));
- }
- SelectionPosition posStart(posLineStart + lineStart);
- SelectionPosition posEnd(posLineStart + lineEnd, virtualSpaces);
- SelectionSegment virtualSpaceRange(posStart, posEnd);
- for (size_t r=0; r<sel.Count(); r++) {
- int alpha = (r == sel.Main()) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha;
- if (alpha != SC_ALPHA_NOALPHA) {
- SelectionSegment portion = 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] - subLineStart + portion.start.VirtualSpace() * spaceWidth;
- rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - subLineStart + portion.end.VirtualSpace() * spaceWidth;
- if ((ll->wrapIndent != 0) && (lineStart != 0)) {
- if ((portion.start.Position() - posLineStart) == lineStart && 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 == sel.Main()), alpha);
- }
- }
- }
- }
-
- // Draw any translucent whole line states
- rcSegment = rcLine;
- if ((caret.active || vsDraw.alwaysShowCaretLineBackground) && vsDraw.showCaretLineBackground && ll->containsCaret) {
- SimpleAlphaRectangle(surface, rcSegment, vsDraw.caretLineBackground, vsDraw.caretLineAlpha);
- }
- marks = pdoc->GetMark(line);
- for (markBit = 0; (markBit < 32) && marks; markBit++) {
- if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND)) {
- SimpleAlphaRectangle(surface, rcSegment, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha);
- } else if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE)) {
- PRectangle rcUnderline = rcSegment;
- rcUnderline.top = rcUnderline.bottom - 2;
- SimpleAlphaRectangle(surface, rcUnderline, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha);
- }
- marks >>= 1;
- }
- if (vsDraw.maskInLine) {
- int marksMasked = 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, rcSegment, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha);
- }
- marksMasked >>= 1;
- }
- }
- }
-}
-
-void Editor::DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine,
- int xStart, int offset, int posCaret, PRectangle rcCaret, ColourDesired caretColour) {
-
- int lineStart = ll->LineStart(subLine);
- int posBefore = posCaret;
- int posAfter = 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 = 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 = 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];
- surface->DrawTextClipped(rcCaret, vsDraw.styles[styleMain].font,
- rcCaret.top + vsDraw.maxAscent, ll->chars + offsetFirstChar,
- numCharsToDraw, vsDraw.styles[styleMain].back,
- caretColour);
-}
-
-void Editor::RefreshPixMaps(Surface *surfaceWindow) {
- if (!pixmapSelPattern->Initialised()) {
- const int patternSize = 8;
- pixmapSelPattern->InitPixMap(patternSize, patternSize, surfaceWindow, wMain.GetID());
- pixmapSelPatternOffset1->InitPixMap(patternSize, patternSize, surfaceWindow, wMain.GetID());
- // 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(0, 0, patternSize, patternSize);
-
- // Initialize default colours based on the chrome colour scheme. Typically the highlight is white.
- ColourDesired colourFMFill = vs.selbar;
- ColourDesired colourFMStripes = vs.selbarlight;
-
- if (!(vs.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 = vs.selbarlight;
- }
-
- if (vs.foldmarginColour.isSet) {
- // override default fold margin colour
- colourFMFill = vs.foldmarginColour;
- }
- if (vs.foldmarginHighlightColour.isSet) {
- // override default fold margin highlight colour
- colourFMStripes = vs.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(x, y, x+1, y+1);
- pixmapSelPattern->FillRectangle(rcPixel, colourFMStripes);
- pixmapSelPatternOffset1->FillRectangle(rcPixel, colourFMFill);
- }
- }
- }
-
- if (!pixmapIndentGuide->Initialised()) {
- // 1 extra pixel in height so can handle odd/even positions and so produce a continuous line
- pixmapIndentGuide->InitPixMap(1, vs.lineHeight + 1, surfaceWindow, wMain.GetID());
- pixmapIndentGuideHighlight->InitPixMap(1, vs.lineHeight + 1, surfaceWindow, wMain.GetID());
- PRectangle rcIG(0, 0, 1, vs.lineHeight);
- pixmapIndentGuide->FillRectangle(rcIG, vs.styles[STYLE_INDENTGUIDE].back);
- pixmapIndentGuide->PenColour(vs.styles[STYLE_INDENTGUIDE].fore);
- pixmapIndentGuideHighlight->FillRectangle(rcIG, vs.styles[STYLE_BRACELIGHT].back);
- pixmapIndentGuideHighlight->PenColour(vs.styles[STYLE_BRACELIGHT].fore);
- for (int stripe = 1; stripe < vs.lineHeight + 1; stripe += 2) {
- PRectangle rcPixel(0, stripe, 1, stripe+1);
- pixmapIndentGuide->FillRectangle(rcPixel, vs.styles[STYLE_INDENTGUIDE].fore);
- pixmapIndentGuideHighlight->FillRectangle(rcPixel, vs.styles[STYLE_BRACELIGHT].fore);
- }
- }
-
- if (bufferedDraw) {
- if (!pixmapLine->Initialised()) {
- PRectangle rcClient = GetClientRectangle();
- pixmapLine->InitPixMap(rcClient.Width(), vs.lineHeight,
- surfaceWindow, wMain.GetID());
- pixmapSelMargin->InitPixMap(vs.fixedColumnWidth,
- rcClient.Height(), surfaceWindow, wMain.GetID());
- }
- }
-}
-
-void Editor::DrawCarets(Surface *surface, ViewStyle &vsDraw, int lineDoc, int xStart,
- PRectangle rcLine, LineLayout *ll, int subLine) {
- // When drag is active it is the only caret drawn
- bool drawDrag = posDrag.IsValid();
- if (hideSelection && !drawDrag)
- return;
- const int posLineStart = pdoc->LineStart(lineDoc);
- // For each selection draw
- for (size_t r=0; (r<sel.Count()) || drawDrag; r++) {
- const bool mainCaret = r == sel.Main();
- const SelectionPosition posCaret = (drawDrag ? posDrag : 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 = (caret.active && caret.on) || (!additionalCaretsBlink && !mainCaret);
- bool caretVisibleState = additionalCaretsVisible || mainCaret;
- if ((xposCaret >= 0) && (vsDraw.caretWidth > 0) && (vsDraw.caretStyle != CARETSTYLE_INVISIBLE) &&
- ((posDrag.IsValid()) || (caretBlinkState && caretVisibleState))) {
- bool caretAtEOF = false;
- bool caretAtEOL = false;
- bool drawBlockCaret = false;
- XYPOSITION widthOverstrikeCaret;
- int caretWidthOffset = 0;
- PRectangle rcCaret = rcLine;
-
- if (posCaret.Position() == 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 = 1; // Move back so overlaps both character cells.
- xposCaret += xStart;
- if (posDrag.IsValid()) {
- /* Dragging text, use a line caret */
- rcCaret.left = xposCaret - caretWidthOffset;
- rcCaret.right = rcCaret.left + vsDraw.caretWidth;
- } else if (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 = 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);
- } else {
- surface->FillRectangle(rcCaret, caretColour);
- }
- }
- }
- if (drawDrag)
- break;
- }
-}
-
-void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
- //Platform::DebugPrintf("Paint:%1d (%3d,%3d) ... (%3d,%3d)\n",
- // paintingAllText, rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
- AllocateGraphics();
-
- RefreshStyleData();
- if (paintState == paintAbandoned)
- return; // Scroll bars may have changed so need redraw
- RefreshPixMaps(surfaceWindow);
-
- paintAbandonedByStyling = false;
-
- StyleToPositionInView(PositionAfterArea(rcArea));
-
- PRectangle rcClient = GetClientRectangle();
- Point ptOrigin = GetVisibleOriginInMain();
- //Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d) %d\n",
- // rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
-
- int screenLinePaintFirst = rcArea.top / vs.lineHeight;
-
- int xStart = vs.textStart - xOffset + ptOrigin.x;
- int ypos = 0;
- if (!bufferedDraw)
- ypos += screenLinePaintFirst * vs.lineHeight;
- int yposScreen = screenLinePaintFirst * vs.lineHeight;
-
- if (NotifyUpdateUI()) {
- RefreshStyleData();
- RefreshPixMaps(surfaceWindow);
- }
-
- // Wrap the visible lines if needed.
- if (WrapLines(wsVisible)) {
- // The wrapping process has changed the height of some lines so
- // abandon this paint for a complete repaint.
- if (AbandonPaint()) {
- return;
- }
- RefreshPixMaps(surfaceWindow); // In case pixmaps invalidated by scrollbar change
- }
- PLATFORM_ASSERT(pixmapSelPattern->Initialised());
-
- if (!bufferedDraw)
- surfaceWindow->SetClip(rcArea);
-
- if (paintState != paintAbandoned) {
- if (vs.marginInside) {
- PaintSelMargin(surfaceWindow, rcArea);
- PRectangle rcRightMargin = rcClient;
- rcRightMargin.left = rcRightMargin.right - vs.rightMarginWidth;
- if (rcArea.Intersects(rcRightMargin)) {
- surfaceWindow->FillRectangle(rcRightMargin, vs.styles[STYLE_DEFAULT].back);
- }
- } else { // Else separate view so separate paint event but leftMargin included to allow overlap
- PRectangle rcLeftMargin = rcArea;
- rcLeftMargin.left = 0;
- rcLeftMargin.right = rcLeftMargin.left + vs.leftMarginWidth;
- if (rcArea.Intersects(rcLeftMargin)) {
- surfaceWindow->FillRectangle(rcLeftMargin, vs.styles[STYLE_DEFAULT].back);
- }
- }
- }
-
- if (paintState == paintAbandoned) {
- // Either styling or NotifyUpdateUI noticed that painting is needed
- // outside the current painting rectangle
- //Platform::DebugPrintf("Abandoning paint\n");
- if (Wrapping()) {
- if (paintAbandonedByStyling) {
- // Styling has spilled over a line end, such as occurs by starting a multiline
- // comment. The width of subsequent text may have changed, so rewrap.
- NeedWrapping(cs.DocFromDisplay(topLine));
- }
- }
- return;
- }
- //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset);
-
- // 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 = ((xOffset == 0) && (vs.leftMarginWidth > 0)) ? 1 : 0;
-
- // Do the painting
- if (rcArea.right > vs.textStart - leftTextOverlap) {
-
- Surface *surface = surfaceWindow;
- if (bufferedDraw) {
- surface = pixmapLine;
- PLATFORM_ASSERT(pixmapLine->Initialised());
- }
- surface->SetUnicodeMode(IsUnicodeMode());
- surface->SetDBCSMode(CodePage());
-
- int visibleLine = TopLineOfMain() + screenLinePaintFirst;
-
- SelectionPosition posCaret = sel.RangeMain().caret;
- if (posDrag.IsValid())
- posCaret = posDrag;
- int lineCaret = pdoc->LineFromPosition(posCaret.Position());
-
- PRectangle rcTextArea = rcClient;
- if (vs.marginInside) {
- rcTextArea.left += vs.textStart;
- rcTextArea.right -= vs.rightMarginWidth;
- } else {
- rcTextArea = rcArea;
- }
-
- // Remove selection margin from drawing area so text will not be drawn
- // on it in unbuffered mode.
- if (!bufferedDraw && vs.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 < cs.LinesDisplayed() && yposScreen < rcArea.bottom) {
-
- int lineDoc = cs.DocFromDisplay(visibleLine);
- // Only visible lines should be handled by the code within the loop
- PLATFORM_ASSERT(cs.GetVisible(lineDoc));
- int lineStartSet = 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));
- LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
- lineDocPrevious = lineDoc;
- }
- //durLayout += et.Duration(true);
-
- if (ll) {
- ll->containsCaret = lineDoc == lineCaret;
- if (hideSelection) {
- ll->containsCaret = false;
- }
-
- GetHotSpotRange(ll->hsStart, ll->hsEnd);
-
- PRectangle rcLine = rcTextArea;
- rcLine.top = ypos;
- rcLine.bottom = ypos + vs.lineHeight;
-
- bool bracesIgnoreStyle = false;
- if ((vs.braceHighlightIndicatorSet && (bracesMatchStyle == STYLE_BRACELIGHT)) ||
- (vs.braceBadLightIndicatorSet && (bracesMatchStyle == STYLE_BRACEBAD))) {
- bracesIgnoreStyle = true;
- }
- Range rangeLine(pdoc->LineStart(lineDoc), pdoc->LineStart(lineDoc + 1));
- // Highlight the current braces if any
- ll->SetBracesHighlight(rangeLine, braces, static_cast<char>(bracesMatchStyle),
- highlightGuideColumn * vs.spaceWidth, bracesIgnoreStyle);
-
- if (leftTextOverlap && bufferedDraw) {
- PRectangle rcSpacer = rcLine;
- rcSpacer.right = rcSpacer.left;
- rcSpacer.left -= 1;
- surface->FillRectangle(rcSpacer, vs.styles[STYLE_DEFAULT].back);
- }
-
- // Draw the line
- DrawLine(surface, vs, lineDoc, visibleLine, xStart, rcLine, ll, subLine);
- //durPaint += et.Duration(true);
-
- // Restore the previous styles for the brace highlights in case layout is in cache.
- ll->RestoreBracesHighlight(rangeLine, braces, bracesIgnoreStyle);
-
- bool expanded = cs.GetExpanded(lineDoc);
- const int level = pdoc->GetLevel(lineDoc);
- const int levelNext = pdoc->GetLevel(lineDoc + 1);
- if ((level & SC_FOLDLEVELHEADERFLAG) &&
- ((level & SC_FOLDLEVELNUMBERMASK) < (levelNext & SC_FOLDLEVELNUMBERMASK))) {
- // Paint the line above the fold
- if ((expanded && (foldFlags & SC_FOLDFLAG_LINEBEFORE_EXPANDED))
- ||
- (!expanded && (foldFlags & SC_FOLDFLAG_LINEBEFORE_CONTRACTED))) {
- PRectangle rcFoldLine = rcLine;
- rcFoldLine.bottom = rcFoldLine.top + 1;
- surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore);
- }
- // Paint the line below the fold
- if ((expanded && (foldFlags & SC_FOLDFLAG_LINEAFTER_EXPANDED))
- ||
- (!expanded && (foldFlags & SC_FOLDFLAG_LINEAFTER_CONTRACTED))) {
- PRectangle rcFoldLine = rcLine;
- rcFoldLine.top = rcFoldLine.bottom - 1;
- surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore);
- }
- }
-
- DrawCarets(surface, vs, lineDoc, xStart, rcLine, ll, subLine);
-
- if (bufferedDraw) {
- Point from(vs.textStart-leftTextOverlap, 0);
- PRectangle rcCopyArea(vs.textStart-leftTextOverlap, yposScreen,
- rcClient.right - vs.rightMarginWidth, yposScreen + vs.lineHeight);
- surfaceWindow->Copy(rcCopyArea, from, *pixmapLine);
- }
-
- lineWidthMaxSeen = Platform::Maximum(
- lineWidthMaxSeen, ll->positions[ll->numCharsInLine]);
- //durCopy += et.Duration(true);
- }
-
- if (!bufferedDraw) {
- ypos += vs.lineHeight;
- }
-
- yposScreen += vs.lineHeight;
- visibleLine++;
-
- //gdk_flush();
- }
- ll.Set(0);
- //if (durPaint < 0.00000001)
- // durPaint = 0.00000001;
-
- // Right column limit indicator
- PRectangle rcBeyondEOF = (vs.marginInside) ? rcClient : rcArea;
- rcBeyondEOF.left = vs.textStart;
- rcBeyondEOF.right = rcBeyondEOF.right - ((vs.marginInside) ? vs.rightMarginWidth : 0);
- rcBeyondEOF.top = (cs.LinesDisplayed() - TopLineOfMain()) * vs.lineHeight;
- if (rcBeyondEOF.top < rcBeyondEOF.bottom) {
- surfaceWindow->FillRectangle(rcBeyondEOF, vs.styles[STYLE_DEFAULT].back);
- if (vs.edgeState == EDGE_LINE) {
- int edgeX = vs.theEdge * vs.spaceWidth;
- rcBeyondEOF.left = edgeX + xStart;
- rcBeyondEOF.right = rcBeyondEOF.left + 1;
- surfaceWindow->FillRectangle(rcBeyondEOF, vs.edgecolour);
- }
- }
- //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());
- NotifyPainted();
- }
-}
-
-// 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));
-}
-
-// This is mostly copied from the Paint method but with some things omitted
-// such as the margin markers, line numbers, selection and caret
-// Should be merged back into a combined Draw method.
-long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) {
- if (!pfr)
- return 0;
-
- AutoSurface surface(pfr->hdc, this, SC_TECHNOLOGY_DEFAULT);
- if (!surface)
- return 0;
- AutoSurface surfaceMeasure(pfr->hdcTarget, this, SC_TECHNOLOGY_DEFAULT);
- if (!surfaceMeasure) {
- return 0;
- }
-
- // 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, pdoc->tabInChars);
- // Determining width must hapen after fonts have been realised in Refresh
- int lineNumberWidth = 0;
- if (lineNumberIndex >= 0) {
- lineNumberWidth = surfaceMeasure->WidthText(vsPrint.styles[STYLE_LINENUMBER].font,
- "99999" lineNumberPrintSpace, 5 + istrlen(lineNumberPrintSpace));
- vsPrint.ms[lineNumberIndex].width = lineNumberWidth;
- vsPrint.Refresh(*surfaceMeasure, pdoc->tabInChars); // Recalculate fixedColumnWidth
- }
-
- int linePrintStart = pdoc->LineFromPosition(pfr->chrg.cpMin);
- int linePrintLast = linePrintStart + (pfr->rc.bottom - pfr->rc.top) / vsPrint.lineHeight - 1;
- if (linePrintLast < linePrintStart)
- linePrintLast = linePrintStart;
- int linePrintMax = 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 = pdoc->Length();
- if (linePrintLast < pdoc->LinesTotal())
- endPosPrint = pdoc->LineStart(linePrintLast + 1);
-
- // Ensure we are styled to where we are formatting.
- 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(pdoc->LineStart(lineDoc+1)-pdoc->LineStart(lineDoc)+1);
- LayoutLine(lineDoc, surfaceMeasure, vsPrint, &ll, widthPrint);
-
- ll.containsCaret = false;
-
- PRectangle rcLine;
- rcLine.left = pfr->rc.left;
- rcLine.top = ypos;
- rcLine.right = pfr->rc.right - 1;
- rcLine.bottom = 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 - 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, istrlen(number));
- surface->FlushCachedState();
- surface->DrawTextNoClip(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font,
- ypos + vsPrint.maxAscent, number, istrlen(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 = ypos;
- rcLine.bottom = ypos + vsPrint.lineHeight;
- DrawLine(surface, vsPrint, lineDoc, visibleLine, xStart, rcLine, &ll, iwl);
- }
- ypos += vsPrint.lineHeight;
- }
- visibleLine++;
- if (iwl == ll.lines - 1)
- nPrintPos = 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;
-}
-
-int Editor::TextWidth(int style, const char *text) {
- RefreshStyleData();
- AutoSurface surface(this);
- if (surface) {
- return surface->WidthText(vs.styles[style].font, text, istrlen(text));
- } else {
- return 1;
- }
-}
-
-// Empty method is overridden on GTK+ to show / hide scrollbars
-void Editor::ReconfigureScrollBars() {}
-
-void Editor::SetScrollBars() {
- RefreshStyleData();
-
- int nMax = MaxScrollPos();
- int nPage = LinesOnScreen();
- bool modified = ModifyScrollBars(nMax + nPage - 1, nPage);
- if (modified) {
- DwellEnd(true);
- }
-
- // TODO: ensure always showing as many lines as possible
- // May not be, if, for example, window made larger
- if (topLine > MaxScrollPos()) {
- SetTopLine(Platform::Clamp(topLine, 0, MaxScrollPos()));
- SetVerticalScrollPos();
- Redraw();
- }
- if (modified) {
- if (!AbandonPaint())
- Redraw();
- }
- //Platform::DebugPrintf("end max = %d page = %d\n", nMax, nPage);
-}
-
-void Editor::ChangeSize() {
- DropGraphics(false);
- SetScrollBars();
- if (Wrapping()) {
- PRectangle rcTextArea = GetClientRectangle();
- rcTextArea.left = vs.textStart;
- rcTextArea.right -= vs.rightMarginWidth;
- if (wrapWidth != rcTextArea.Width()) {
- NeedWrapping();
- Redraw();
- }
- }
-}
-
-int Editor::InsertSpace(int position, unsigned int spaces) {
- if (spaces > 0) {
- std::string spaceText(spaces, ' ');
- pdoc->InsertString(position, spaceText.c_str(), spaces);
- position += spaces;
- }
- return position;
-}
-
-void Editor::AddChar(char ch) {
- char s[2];
- s[0] = ch;
- s[1] = '\0';
- AddCharUTF(s, 1);
-}
-
-void Editor::FilterSelections() {
- if (!additionalSelectionTyping && (sel.Count() > 1)) {
- SelectionRange rangeOnly = sel.RangeMain();
- InvalidateSelection(rangeOnly, true);
- sel.SetSelection(rangeOnly);
- }
-}
-
-static bool cmpSelPtrs(const SelectionRange *a, const SelectionRange *b) {
- return *a < *b;
-}
-
-// AddCharUTF inserts an array of bytes which may or may not be in UTF-8.
-void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
- FilterSelections();
- {
- UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty() || inOverstrike);
-
- std::vector<SelectionRange *> selPtrs;
- for (size_t r = 0; r < sel.Count(); r++) {
- selPtrs.push_back(&sel.Range(r));
- }
- std::sort(selPtrs.begin(), selPtrs.end(), cmpSelPtrs);
-
- for (std::vector<SelectionRange *>::reverse_iterator rit = selPtrs.rbegin();
- rit != selPtrs.rend(); ++rit) {
- SelectionRange *currentSel = *rit;
- if (!RangeContainsProtected(currentSel->Start().Position(),
- currentSel->End().Position())) {
- int positionInsert = currentSel->Start().Position();
- if (!currentSel->Empty()) {
- if (currentSel->Length()) {
- pdoc->DeleteChars(positionInsert, currentSel->Length());
- currentSel->ClearVirtualSpace();
- } else {
- // Range is all virtual so collapse to start of virtual space
- currentSel->MinimizeVirtualSpace();
- }
- } else if (inOverstrike) {
- if (positionInsert < pdoc->Length()) {
- if (!pdoc->IsPositionInLineEnd(positionInsert)) {
- pdoc->DelChar(positionInsert);
- currentSel->ClearVirtualSpace();
- }
- }
- }
- positionInsert = InsertSpace(positionInsert, currentSel->caret.VirtualSpace());
- if (pdoc->InsertString(positionInsert, s, len)) {
- currentSel->caret.SetPosition(positionInsert + len);
- currentSel->anchor.SetPosition(positionInsert + len);
- }
- currentSel->ClearVirtualSpace();
- // If in wrap mode rewrap current line so EnsureCaretVisible has accurate information
- if (Wrapping()) {
- AutoSurface surface(this);
- if (surface) {
- if (WrapOneLine(surface, pdoc->LineFromPosition(positionInsert))) {
- SetScrollBars();
- SetVerticalScrollPos();
- Redraw();
- }
- }
- }
- }
- }
- }
- if (Wrapping()) {
- SetScrollBars();
- }
- ThinRectangularRange();
- // If in wrap mode rewrap current line so EnsureCaretVisible has accurate information
- EnsureCaretVisible();
- // Avoid blinking during rapid typing:
- ShowCaretAtCurrentPosition();
- if ((caretSticky == SC_CARETSTICKY_OFF) ||
- ((caretSticky == SC_CARETSTICKY_WHITESPACE) && !IsAllSpacesOrTabs(s, len))) {
- SetLastXChosen();
- }
-
- if (treatAsDBCS) {
- NotifyChar((static_cast<unsigned char>(s[0]) << 8) |
- static_cast<unsigned char>(s[1]));
- } else if (len > 0) {
- int byte = static_cast<unsigned char>(s[0]);
- if ((byte < 0xC0) || (1 == len)) {
- // Handles UTF-8 characters between 0x01 and 0x7F and single byte
- // characters when not in UTF-8 mode.
- // Also treats \0 and naked trail bytes 0x80 to 0xBF as valid
- // characters representing themselves.
- } else {
- // Unroll 1 to 3 byte UTF-8 sequences. See reference data at:
- // http://www.cl.cam.ac.uk/~mgk25/unicode.html
- // http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt
- if (byte < 0xE0) {
- int byte2 = static_cast<unsigned char>(s[1]);
- if ((byte2 & 0xC0) == 0x80) {
- // Two-byte-character lead-byte followed by a trail-byte.
- byte = (((byte & 0x1F) << 6) | (byte2 & 0x3F));
- }
- // A two-byte-character lead-byte not followed by trail-byte
- // represents itself.
- } else if (byte < 0xF0) {
- int byte2 = static_cast<unsigned char>(s[1]);
- int byte3 = static_cast<unsigned char>(s[2]);
- if (((byte2 & 0xC0) == 0x80) && ((byte3 & 0xC0) == 0x80)) {
- // Three-byte-character lead byte followed by two trail bytes.
- byte = (((byte & 0x0F) << 12) | ((byte2 & 0x3F) << 6) |
- (byte3 & 0x3F));
- }
- // A three-byte-character lead-byte not followed by two trail-bytes
- // represents itself.
- }
- }
- NotifyChar(byte);
- }
-
- if (recordingMacro) {
- NotifyMacroRecord(SCI_REPLACESEL, 0, reinterpret_cast<sptr_t>(s));
- }
-}
-
-void Editor::InsertPaste(SelectionPosition selStart, const char *text, int len) {
- if (multiPasteMode == SC_MULTIPASTE_ONCE) {
- selStart = SelectionPosition(InsertSpace(selStart.Position(), selStart.VirtualSpace()));
- if (pdoc->InsertString(selStart.Position(), text, len)) {
- SetEmptySelection(selStart.Position() + len);
- }
- } else {
- // SC_MULTIPASTE_EACH
- for (size_t r=0; r<sel.Count(); r++) {
- if (!RangeContainsProtected(sel.Range(r).Start().Position(),
- sel.Range(r).End().Position())) {
- int positionInsert = sel.Range(r).Start().Position();
- if (!sel.Range(r).Empty()) {
- if (sel.Range(r).Length()) {
- pdoc->DeleteChars(positionInsert, sel.Range(r).Length());
- sel.Range(r).ClearVirtualSpace();
- } else {
- // Range is all virtual so collapse to start of virtual space
- sel.Range(r).MinimizeVirtualSpace();
- }
- }
- positionInsert = InsertSpace(positionInsert, sel.Range(r).caret.VirtualSpace());
- if (pdoc->InsertString(positionInsert, text, len)) {
- sel.Range(r).caret.SetPosition(positionInsert + len);
- sel.Range(r).anchor.SetPosition(positionInsert + len);
- }
- sel.Range(r).ClearVirtualSpace();
- }
- }
- }
-}
-
-void Editor::ClearSelection(bool retainMultipleSelections) {
- if (!sel.IsRectangular() && !retainMultipleSelections)
- FilterSelections();
- UndoGroup ug(pdoc);
- for (size_t r=0; r<sel.Count(); r++) {
- if (!sel.Range(r).Empty()) {
- if (!RangeContainsProtected(sel.Range(r).Start().Position(),
- sel.Range(r).End().Position())) {
- pdoc->DeleteChars(sel.Range(r).Start().Position(),
- sel.Range(r).Length());
- sel.Range(r) = sel.Range(r).Start();
- }
- }
- }
- ThinRectangularRange();
- sel.RemoveDuplicates();
- ClaimSelection();
-}
-
-void Editor::ClearAll() {
- {
- UndoGroup ug(pdoc);
- if (0 != pdoc->Length()) {
- pdoc->DeleteChars(0, pdoc->Length());
- }
- if (!pdoc->IsReadOnly()) {
- cs.Clear();
- pdoc->AnnotationClearAll();
- pdoc->MarginClearAll();
- }
- }
- sel.Clear();
- SetTopLine(0);
- SetVerticalScrollPos();
- InvalidateStyleRedraw();
-}
-
-void Editor::ClearDocumentStyle() {
- Decoration *deco = pdoc->decorations.root;
- while (deco) {
- // Save next in case deco deleted
- Decoration *decoNext = deco->next;
- if (deco->indicator < INDIC_CONTAINER) {
- pdoc->decorations.SetCurrentIndicator(deco->indicator);
- pdoc->DecorationFillRange(0, 0, pdoc->Length());
- }
- deco = decoNext;
- }
- pdoc->StartStyling(0, '\377');
- pdoc->SetStyleFor(pdoc->Length(), 0);
- cs.ShowAll();
- pdoc->ClearLevels();
-}
-
-void Editor::CopyAllowLine() {
- SelectionText selectedText;
- CopySelectionRange(&selectedText, true);
- CopyToClipboard(selectedText);
-}
-
-void Editor::Cut() {
- pdoc->CheckReadOnly();
- if (!pdoc->IsReadOnly() && !SelectionContainsProtected()) {
- Copy();
- ClearSelection();
- }
-}
-
-void Editor::PasteRectangular(SelectionPosition pos, const char *ptr, int len) {
- if (pdoc->IsReadOnly() || SelectionContainsProtected()) {
- return;
- }
- sel.Clear();
- sel.RangeMain() = SelectionRange(pos);
- int line = pdoc->LineFromPosition(sel.MainCaret());
- UndoGroup ug(pdoc);
- sel.RangeMain().caret = SelectionPosition(
- InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace()));
- int xInsert = XFromPosition(sel.RangeMain().caret);
- bool prevCr = false;
- while ((len > 0) && IsEOLChar(ptr[len-1]))
- len--;
- for (int i = 0; i < len; i++) {
- if (IsEOLChar(ptr[i])) {
- if ((ptr[i] == '\r') || (!prevCr))
- line++;
- if (line >= pdoc->LinesTotal()) {
- if (pdoc->eolMode != SC_EOL_LF)
- pdoc->InsertChar(pdoc->Length(), '\r');
- if (pdoc->eolMode != SC_EOL_CR)
- pdoc->InsertChar(pdoc->Length(), '\n');
- }
- // Pad the end of lines with spaces if required
- sel.RangeMain().caret.SetPosition(PositionFromLineX(line, xInsert));
- if ((XFromPosition(sel.MainCaret()) < xInsert) && (i + 1 < len)) {
- while (XFromPosition(sel.MainCaret()) < xInsert) {
- pdoc->InsertChar(sel.MainCaret(), ' ');
- sel.RangeMain().caret.Add(1);
- }
- }
- prevCr = ptr[i] == '\r';
- } else {
- pdoc->InsertString(sel.MainCaret(), ptr + i, 1);
- sel.RangeMain().caret.Add(1);
- prevCr = false;
- }
- }
- SetEmptySelection(pos);
-}
-
-bool Editor::CanPaste() {
- return !pdoc->IsReadOnly() && !SelectionContainsProtected();
-}
-
-void Editor::Clear() {
- // If multiple selections, don't delete EOLS
- if (sel.Empty()) {
- bool singleVirtual = false;
- if ((sel.Count() == 1) &&
- !RangeContainsProtected(sel.MainCaret(), sel.MainCaret() + 1) &&
- sel.RangeMain().Start().VirtualSpace()) {
- singleVirtual = true;
- }
- UndoGroup ug(pdoc, (sel.Count() > 1) || singleVirtual);
- for (size_t r=0; r<sel.Count(); r++) {
- if (!RangeContainsProtected(sel.Range(r).caret.Position(), sel.Range(r).caret.Position() + 1)) {
- if (sel.Range(r).Start().VirtualSpace()) {
- if (sel.Range(r).anchor < sel.Range(r).caret)
- sel.Range(r) = SelectionPosition(InsertSpace(sel.Range(r).anchor.Position(), sel.Range(r).anchor.VirtualSpace()));
- else
- sel.Range(r) = SelectionPosition(InsertSpace(sel.Range(r).caret.Position(), sel.Range(r).caret.VirtualSpace()));
- }
- if ((sel.Count() == 1) || !pdoc->IsPositionInLineEnd(sel.Range(r).caret.Position())) {
- pdoc->DelChar(sel.Range(r).caret.Position());
- sel.Range(r).ClearVirtualSpace();
- } // else multiple selection so don't eat line ends
- } else {
- sel.Range(r).ClearVirtualSpace();
- }
- }
- } else {
- ClearSelection();
- }
- sel.RemoveDuplicates();
-}
-
-void Editor::SelectAll() {
- sel.Clear();
- SetSelection(0, pdoc->Length());
- Redraw();
-}
-
-void Editor::Undo() {
- if (pdoc->CanUndo()) {
- InvalidateCaret();
- int newPos = pdoc->Undo();
- if (newPos >= 0)
- SetEmptySelection(newPos);
- EnsureCaretVisible();
- }
-}
-
-void Editor::Redo() {
- if (pdoc->CanRedo()) {
- int newPos = pdoc->Redo();
- if (newPos >= 0)
- SetEmptySelection(newPos);
- EnsureCaretVisible();
- }
-}
-
-void Editor::DelChar() {
- if (!RangeContainsProtected(sel.MainCaret(), sel.MainCaret() + 1)) {
- pdoc->DelChar(sel.MainCaret());
- }
- // Avoid blinking during rapid typing:
- ShowCaretAtCurrentPosition();
-}
-
-void Editor::DelCharBack(bool allowLineStartDeletion) {
- if (!sel.IsRectangular())
- FilterSelections();
- if (sel.IsRectangular())
- allowLineStartDeletion = false;
- UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty());
- if (sel.Empty()) {
- for (size_t r=0; r<sel.Count(); r++) {
- if (!RangeContainsProtected(sel.Range(r).caret.Position() - 1, sel.Range(r).caret.Position())) {
- if (sel.Range(r).caret.VirtualSpace()) {
- sel.Range(r).caret.SetVirtualSpace(sel.Range(r).caret.VirtualSpace() - 1);
- sel.Range(r).anchor.SetVirtualSpace(sel.Range(r).caret.VirtualSpace());
- } else {
- int lineCurrentPos = pdoc->LineFromPosition(sel.Range(r).caret.Position());
- if (allowLineStartDeletion || (pdoc->LineStart(lineCurrentPos) != sel.Range(r).caret.Position())) {
- if (pdoc->GetColumn(sel.Range(r).caret.Position()) <= pdoc->GetLineIndentation(lineCurrentPos) &&
- pdoc->GetColumn(sel.Range(r).caret.Position()) > 0 && pdoc->backspaceUnindents) {
- UndoGroup ugInner(pdoc, !ug.Needed());
- int indentation = pdoc->GetLineIndentation(lineCurrentPos);
- int indentationStep = pdoc->IndentSize();
- if (indentation % indentationStep == 0) {
- pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep);
- } else {
- pdoc->SetLineIndentation(lineCurrentPos, indentation - (indentation % indentationStep));
- }
- // SetEmptySelection
- sel.Range(r) = SelectionRange(pdoc->GetLineIndentPosition(lineCurrentPos),
- pdoc->GetLineIndentPosition(lineCurrentPos));
- } else {
- pdoc->DelCharBack(sel.Range(r).caret.Position());
- }
- }
- }
- } else {
- sel.Range(r).ClearVirtualSpace();
- }
- }
- ThinRectangularRange();
- } else {
- ClearSelection();
- }
- sel.RemoveDuplicates();
- ContainerNeedsUpdate(SC_UPDATE_SELECTION);
- // Avoid blinking during rapid typing:
- ShowCaretAtCurrentPosition();
-}
-
-void Editor::NotifyFocus(bool) {}
-
-void Editor::SetCtrlID(int identifier) {
- ctrlID = identifier;
-}
-
-void Editor::NotifyStyleToNeeded(int endStyleNeeded) {
- SCNotification scn = {0};
- scn.nmhdr.code = SCN_STYLENEEDED;
- scn.position = endStyleNeeded;
- NotifyParent(scn);
-}
-
-void Editor::NotifyStyleNeeded(Document *, void *, int endStyleNeeded) {
- NotifyStyleToNeeded(endStyleNeeded);
-}
-
-void Editor::NotifyLexerChanged(Document *, void *) {
-}
-
-void Editor::NotifyErrorOccurred(Document *, void *, int status) {
- errorStatus = status;
-}
-
-void Editor::NotifyChar(int ch) {
- SCNotification scn = {0};
- scn.nmhdr.code = SCN_CHARADDED;
- scn.ch = ch;
- NotifyParent(scn);
-}
-
-void Editor::NotifySavePoint(bool isSavePoint) {
- SCNotification scn = {0};
- if (isSavePoint) {
- scn.nmhdr.code = SCN_SAVEPOINTREACHED;
- } else {
- scn.nmhdr.code = SCN_SAVEPOINTLEFT;
- }
- NotifyParent(scn);
-}
-
-void Editor::NotifyModifyAttempt() {
- SCNotification scn = {0};
- scn.nmhdr.code = SCN_MODIFYATTEMPTRO;
- NotifyParent(scn);
-}
-
-void Editor::NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt) {
- SCNotification scn = {0};
- scn.nmhdr.code = SCN_DOUBLECLICK;
- scn.line = LineFromLocation(pt);
- scn.position = PositionFromLocation(pt, true);
- scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
- (alt ? SCI_ALT : 0);
- NotifyParent(scn);
-}
-
-void Editor::NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, bool alt) {
- SCNotification scn = {0};
- scn.nmhdr.code = SCN_HOTSPOTDOUBLECLICK;
- scn.position = position;
- scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
- (alt ? SCI_ALT : 0);
- NotifyParent(scn);
-}
-
-void Editor::NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt) {
- SCNotification scn = {0};
- scn.nmhdr.code = SCN_HOTSPOTCLICK;
- scn.position = position;
- scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
- (alt ? SCI_ALT : 0);
- NotifyParent(scn);
-}
-
-void Editor::NotifyHotSpotReleaseClick(int position, bool shift, bool ctrl, bool alt) {
- SCNotification scn = {0};
- scn.nmhdr.code = SCN_HOTSPOTRELEASECLICK;
- scn.position = position;
- scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
- (alt ? SCI_ALT : 0);
- NotifyParent(scn);
-}
-
-bool Editor::NotifyUpdateUI() {
- if (needUpdateUI) {
- SCNotification scn = {0};
- scn.nmhdr.code = SCN_UPDATEUI;
- scn.updated = needUpdateUI;
- NotifyParent(scn);
- needUpdateUI = 0;
- return true;
- }
- return false;
-}
-
-void Editor::NotifyPainted() {
- SCNotification scn = {0};
- scn.nmhdr.code = SCN_PAINTED;
- NotifyParent(scn);
-}
-
-void Editor::NotifyIndicatorClick(bool click, int position, bool shift, bool ctrl, bool alt) {
- int mask = pdoc->decorations.AllOnFor(position);
- if ((click && mask) || pdoc->decorations.clickNotified) {
- SCNotification scn = {0};
- pdoc->decorations.clickNotified = click;
- scn.nmhdr.code = click ? SCN_INDICATORCLICK : SCN_INDICATORRELEASE;
- scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) | (alt ? SCI_ALT : 0);
- scn.position = position;
- NotifyParent(scn);
- }
-}
-
-bool Editor::NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt) {
- int marginClicked = -1;
- int x = vs.textStart - vs.fixedColumnWidth;
- for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
- if ((pt.x >= x) && (pt.x < x + vs.ms[margin].width))
- marginClicked = margin;
- x += vs.ms[margin].width;
- }
- if ((marginClicked >= 0) && vs.ms[marginClicked].sensitive) {
- int position = pdoc->LineStart(LineFromLocation(pt));
- if ((vs.ms[marginClicked].mask & SC_MASK_FOLDERS) && (foldAutomatic & SC_AUTOMATICFOLD_CLICK)) {
- int lineClick = pdoc->LineFromPosition(position);
- if (shift && ctrl) {
- FoldAll(SC_FOLDACTION_TOGGLE);
- } else {
- int levelClick = pdoc->GetLevel(lineClick);
- if (levelClick & SC_FOLDLEVELHEADERFLAG) {
- if (shift) {
- // Ensure all children visible
- FoldExpand(lineClick, SC_FOLDACTION_EXPAND, levelClick);
- } else if (ctrl) {
- FoldExpand(lineClick, SC_FOLDACTION_TOGGLE, levelClick);
- } else {
- // Toggle this line
- FoldLine(lineClick, SC_FOLDACTION_TOGGLE);
- }
- }
- }
- return true;
- }
- SCNotification scn = {0};
- scn.nmhdr.code = SCN_MARGINCLICK;
- scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
- (alt ? SCI_ALT : 0);
- scn.position = position;
- scn.margin = marginClicked;
- NotifyParent(scn);
- return true;
- } else {
- return false;
- }
-}
-
-void Editor::NotifyNeedShown(int pos, int len) {
- SCNotification scn = {0};
- scn.nmhdr.code = SCN_NEEDSHOWN;
- scn.position = pos;
- scn.length = len;
- NotifyParent(scn);
-}
-
-void Editor::NotifyDwelling(Point pt, bool state) {
- SCNotification scn = {0};
- scn.nmhdr.code = state ? SCN_DWELLSTART : SCN_DWELLEND;
- scn.position = PositionFromLocation(pt, true);
- scn.x = pt.x + vs.ExternalMarginWidth();
- scn.y = pt.y;
- NotifyParent(scn);
-}
-
-void Editor::NotifyZoom() {
- SCNotification scn = {0};
- scn.nmhdr.code = SCN_ZOOM;
- NotifyParent(scn);
-}
-
-// Notifications from document
-void Editor::NotifyModifyAttempt(Document *, void *) {
- //Platform::DebugPrintf("** Modify Attempt\n");
- NotifyModifyAttempt();
-}
-
-void Editor::NotifySavePoint(Document *, void *, bool atSavePoint) {
- //Platform::DebugPrintf("** Save Point %s\n", atSavePoint ? "On" : "Off");
- NotifySavePoint(atSavePoint);
-}
-
-void Editor::CheckModificationForWrap(DocModification mh) {
- if (mh.modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) {
- llc.Invalidate(LineLayout::llCheckTextAndStyle);
- int lineDoc = pdoc->LineFromPosition(mh.position);
- int lines = Platform::Maximum(0, mh.linesAdded);
- if (Wrapping()) {
- NeedWrapping(lineDoc, lineDoc + lines + 1);
- }
- RefreshStyleData();
- // Fix up annotation heights
- SetAnnotationHeights(lineDoc, lineDoc + lines + 2);
- }
-}
-
-// Move a position so it is still after the same character as before the insertion.
-static inline int MovePositionForInsertion(int position, int startInsertion, int length) {
- if (position > startInsertion) {
- return position + length;
- }
- return position;
-}
-
-// Move a position so it is still after the same character as before the deletion if that
-// character is still present else after the previous surviving character.
-static inline int MovePositionForDeletion(int position, int startDeletion, int length) {
- if (position > startDeletion) {
- int endDeletion = startDeletion + length;
- if (position > endDeletion) {
- return position - length;
- } else {
- return startDeletion;
- }
- } else {
- return position;
- }
-}
-
-void Editor::NotifyModified(Document *, DocModification mh, void *) {
- ContainerNeedsUpdate(SC_UPDATE_CONTENT);
- if (paintState == painting) {
- CheckForChangeOutsidePaint(Range(mh.position, mh.position + mh.length));
- }
- if (mh.modificationType & SC_MOD_CHANGELINESTATE) {
- if (paintState == painting) {
- CheckForChangeOutsidePaint(
- Range(pdoc->LineStart(mh.line), pdoc->LineStart(mh.line + 1)));
- } else {
- // Could check that change is before last visible line.
- Redraw();
- }
- }
- if (mh.modificationType & SC_MOD_LEXERSTATE) {
- if (paintState == painting) {
- CheckForChangeOutsidePaint(
- Range(mh.position, mh.position + mh.length));
- } else {
- Redraw();
- }
- }
- if (mh.modificationType & (SC_MOD_CHANGESTYLE | SC_MOD_CHANGEINDICATOR)) {
- if (mh.modificationType & SC_MOD_CHANGESTYLE) {
- pdoc->IncrementStyleClock();
- }
- if (paintState == notPainting) {
- if (mh.position < pdoc->LineStart(topLine)) {
- // Styling performed before this view
- Redraw();
- } else {
- InvalidateRange(mh.position, mh.position + mh.length);
- }
- }
- if (mh.modificationType & SC_MOD_CHANGESTYLE) {
- llc.Invalidate(LineLayout::llCheckTextAndStyle);
- }
- } else {
- // Move selection and brace highlights
- if (mh.modificationType & SC_MOD_INSERTTEXT) {
- sel.MovePositions(true, mh.position, mh.length);
- braces[0] = MovePositionForInsertion(braces[0], mh.position, mh.length);
- braces[1] = MovePositionForInsertion(braces[1], mh.position, mh.length);
- } else if (mh.modificationType & SC_MOD_DELETETEXT) {
- sel.MovePositions(false, mh.position, mh.length);
- braces[0] = MovePositionForDeletion(braces[0], mh.position, mh.length);
- braces[1] = MovePositionForDeletion(braces[1], mh.position, mh.length);
- }
- if ((mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) && cs.HiddenLines()) {
- // Some lines are hidden so may need shown.
- // TODO: check if the modified area is hidden.
- if (mh.modificationType & SC_MOD_BEFOREINSERT) {
- int lineOfPos = pdoc->LineFromPosition(mh.position);
- bool insertingNewLine = false;
- for (int i=0; i < mh.length; i++) {
- if ((mh.text[i] == '\n') || (mh.text[i] == '\r'))
- insertingNewLine = true;
- }
- if (insertingNewLine && (mh.position != pdoc->LineStart(lineOfPos)))
- NeedShown(mh.position, pdoc->LineStart(lineOfPos+1) - mh.position);
- else
- NeedShown(mh.position, 0);
- } else if (mh.modificationType & SC_MOD_BEFOREDELETE) {
- NeedShown(mh.position, mh.length);
- }
- }
- if (mh.linesAdded != 0) {
- // Update contraction state for inserted and removed lines
- // lineOfPos should be calculated in context of state before modification, shouldn't it
- int lineOfPos = pdoc->LineFromPosition(mh.position);
- if (mh.position > pdoc->LineStart(lineOfPos))
- lineOfPos++; // Affecting subsequent lines
- if (mh.linesAdded > 0) {
- cs.InsertLines(lineOfPos, mh.linesAdded);
- } else {
- cs.DeleteLines(lineOfPos, -mh.linesAdded);
- }
- }
- if (mh.modificationType & SC_MOD_CHANGEANNOTATION) {
- int lineDoc = pdoc->LineFromPosition(mh.position);
- if (vs.annotationVisible) {
- cs.SetHeight(lineDoc, cs.GetHeight(lineDoc) + mh.annotationLinesAdded);
- Redraw();
- }
- }
- CheckModificationForWrap(mh);
- if (mh.linesAdded != 0) {
- // Avoid scrolling of display if change before current display
- if (mh.position < posTopLine && !CanDeferToLastStep(mh)) {
- int newTop = Platform::Clamp(topLine + mh.linesAdded, 0, MaxScrollPos());
- if (newTop != topLine) {
- SetTopLine(newTop);
- SetVerticalScrollPos();
- }
- }
-
- if (paintState == notPainting && !CanDeferToLastStep(mh)) {
- QueueIdleWork(WorkNeeded::workStyle, pdoc->Length());
- Redraw();
- }
- } else {
- if (paintState == notPainting && mh.length && !CanEliminate(mh)) {
- QueueIdleWork(WorkNeeded::workStyle, mh.position + mh.length);
- InvalidateRange(mh.position, mh.position + mh.length);
- }
- }
- }
-
- if (mh.linesAdded != 0 && !CanDeferToLastStep(mh)) {
- SetScrollBars();
- }
-
- if ((mh.modificationType & SC_MOD_CHANGEMARKER) || (mh.modificationType & SC_MOD_CHANGEMARGIN)) {
- if ((!willRedrawAll) && ((paintState == notPainting) || !PaintContainsMargin())) {
- if (mh.modificationType & SC_MOD_CHANGEFOLD) {
- // Fold changes can affect the drawing of following lines so redraw whole margin
- RedrawSelMargin(highlightDelimiter.isEnabled ? -1 : mh.line-1, true);
- } else {
- RedrawSelMargin(mh.line);
- }
- }
- }
- if ((mh.modificationType & SC_MOD_CHANGEFOLD) && (foldAutomatic & SC_AUTOMATICFOLD_CHANGE)) {
- FoldChanged(mh.line, mh.foldLevelNow, mh.foldLevelPrev);
- }
-
- // NOW pay the piper WRT "deferred" visual updates
- if (IsLastStep(mh)) {
- SetScrollBars();
- Redraw();
- }
-
- // If client wants to see this modification
- if (mh.modificationType & modEventMask) {
- if ((mh.modificationType & (SC_MOD_CHANGESTYLE | SC_MOD_CHANGEINDICATOR)) == 0) {
- // Real modification made to text of document.
- NotifyChange(); // Send EN_CHANGE
- }
-
- SCNotification scn = {0};
- scn.nmhdr.code = SCN_MODIFIED;
- scn.position = mh.position;
- scn.modificationType = mh.modificationType;
- scn.text = mh.text;
- scn.length = mh.length;
- scn.linesAdded = mh.linesAdded;
- scn.line = mh.line;
- scn.foldLevelNow = mh.foldLevelNow;
- scn.foldLevelPrev = mh.foldLevelPrev;
- scn.token = mh.token;
- scn.annotationLinesAdded = mh.annotationLinesAdded;
- NotifyParent(scn);
- }
-}
-
-void Editor::NotifyDeleted(Document *, void *) {
- /* Do nothing */
-}
-
-void Editor::NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
-
- // Enumerates all macroable messages
- switch (iMessage) {
- case SCI_CUT:
- case SCI_COPY:
- case SCI_PASTE:
- case SCI_CLEAR:
- case SCI_REPLACESEL:
- case SCI_ADDTEXT:
- case SCI_INSERTTEXT:
- case SCI_APPENDTEXT:
- case SCI_CLEARALL:
- case SCI_SELECTALL:
- case SCI_GOTOLINE:
- case SCI_GOTOPOS:
- case SCI_SEARCHANCHOR:
- case SCI_SEARCHNEXT:
- case SCI_SEARCHPREV:
- case SCI_LINEDOWN:
- case SCI_LINEDOWNEXTEND:
- case SCI_PARADOWN:
- case SCI_PARADOWNEXTEND:
- case SCI_LINEUP:
- case SCI_LINEUPEXTEND:
- case SCI_PARAUP:
- case SCI_PARAUPEXTEND:
- case SCI_CHARLEFT:
- case SCI_CHARLEFTEXTEND:
- case SCI_CHARRIGHT:
- case SCI_CHARRIGHTEXTEND:
- case SCI_WORDLEFT:
- case SCI_WORDLEFTEXTEND:
- case SCI_WORDRIGHT:
- case SCI_WORDRIGHTEXTEND:
- case SCI_WORDPARTLEFT:
- case SCI_WORDPARTLEFTEXTEND:
- case SCI_WORDPARTRIGHT:
- case SCI_WORDPARTRIGHTEXTEND:
- case SCI_WORDLEFTEND:
- case SCI_WORDLEFTENDEXTEND:
- case SCI_WORDRIGHTEND:
- case SCI_WORDRIGHTENDEXTEND:
- case SCI_HOME:
- case SCI_HOMEEXTEND:
- case SCI_LINEEND:
- case SCI_LINEENDEXTEND:
- case SCI_HOMEWRAP:
- case SCI_HOMEWRAPEXTEND:
- case SCI_LINEENDWRAP:
- case SCI_LINEENDWRAPEXTEND:
- case SCI_DOCUMENTSTART:
- case SCI_DOCUMENTSTARTEXTEND:
- case SCI_DOCUMENTEND:
- case SCI_DOCUMENTENDEXTEND:
- case SCI_STUTTEREDPAGEUP:
- case SCI_STUTTEREDPAGEUPEXTEND:
- case SCI_STUTTEREDPAGEDOWN:
- case SCI_STUTTEREDPAGEDOWNEXTEND:
- case SCI_PAGEUP:
- case SCI_PAGEUPEXTEND:
- case SCI_PAGEDOWN:
- case SCI_PAGEDOWNEXTEND:
- case SCI_EDITTOGGLEOVERTYPE:
- case SCI_CANCEL:
- case SCI_DELETEBACK:
- case SCI_TAB:
- case SCI_BACKTAB:
- case SCI_FORMFEED:
- case SCI_VCHOME:
- case SCI_VCHOMEEXTEND:
- case SCI_VCHOMEWRAP:
- case SCI_VCHOMEWRAPEXTEND:
- case SCI_VCHOMEDISPLAY:
- case SCI_VCHOMEDISPLAYEXTEND:
- case SCI_DELWORDLEFT:
- case SCI_DELWORDRIGHT:
- case SCI_DELWORDRIGHTEND:
- case SCI_DELLINELEFT:
- case SCI_DELLINERIGHT:
- case SCI_LINECOPY:
- case SCI_LINECUT:
- case SCI_LINEDELETE:
- case SCI_LINETRANSPOSE:
- case SCI_LINEDUPLICATE:
- case SCI_LOWERCASE:
- case SCI_UPPERCASE:
- case SCI_LINESCROLLDOWN:
- case SCI_LINESCROLLUP:
- case SCI_DELETEBACKNOTLINE:
- case SCI_HOMEDISPLAY:
- case SCI_HOMEDISPLAYEXTEND:
- case SCI_LINEENDDISPLAY:
- case SCI_LINEENDDISPLAYEXTEND:
- case SCI_SETSELECTIONMODE:
- case SCI_LINEDOWNRECTEXTEND:
- case SCI_LINEUPRECTEXTEND:
- case SCI_CHARLEFTRECTEXTEND:
- case SCI_CHARRIGHTRECTEXTEND:
- case SCI_HOMERECTEXTEND:
- case SCI_VCHOMERECTEXTEND:
- case SCI_LINEENDRECTEXTEND:
- case SCI_PAGEUPRECTEXTEND:
- case SCI_PAGEDOWNRECTEXTEND:
- case SCI_SELECTIONDUPLICATE:
- case SCI_COPYALLOWLINE:
- case SCI_VERTICALCENTRECARET:
- case SCI_MOVESELECTEDLINESUP:
- case SCI_MOVESELECTEDLINESDOWN:
- case SCI_SCROLLTOSTART:
- case SCI_SCROLLTOEND:
- break;
-
- // Filter out all others like display changes. Also, newlines are redundant
- // with char insert messages.
- case SCI_NEWLINE:
- default:
- // printf("Filtered out %ld of macro recording\n", iMessage);
- return ;
- }
-
- // Send notification
- SCNotification scn = {0};
- scn.nmhdr.code = SCN_MACRORECORD;
- scn.message = iMessage;
- scn.wParam = wParam;
- scn.lParam = lParam;
- NotifyParent(scn);
-}
-
-// Something has changed that the container should know about
-void Editor::ContainerNeedsUpdate(int flags) {
- needUpdateUI |= flags;
-}
-
-/**
- * Force scroll and keep position relative to top of window.
- *
- * If stuttered = true and not already at first/last row, move to first/last row of window.
- * If stuttered = true and already at first/last row, scroll as normal.
- */
-void Editor::PageMove(int direction, Selection::selTypes selt, bool stuttered) {
- int topLineNew;
- SelectionPosition newPos;
-
- int currentLine = pdoc->LineFromPosition(sel.MainCaret());
- int topStutterLine = topLine + caretYSlop;
- int bottomStutterLine =
- pdoc->LineFromPosition(PositionFromLocation(
- Point(lastXChosen - xOffset, direction * vs.lineHeight * LinesToScroll())))
- - caretYSlop - 1;
-
- if (stuttered && (direction < 0 && currentLine > topStutterLine)) {
- topLineNew = topLine;
- newPos = SPositionFromLocation(Point(lastXChosen - xOffset, vs.lineHeight * caretYSlop),
- false, false, UserVirtualSpace());
-
- } else if (stuttered && (direction > 0 && currentLine < bottomStutterLine)) {
- topLineNew = topLine;
- newPos = SPositionFromLocation(Point(lastXChosen - xOffset, vs.lineHeight * (LinesToScroll() - caretYSlop)),
- false, false, UserVirtualSpace());
-
- } else {
- Point pt = LocationFromPosition(sel.MainCaret());
-
- topLineNew = Platform::Clamp(
- topLine + direction * LinesToScroll(), 0, MaxScrollPos());
- newPos = SPositionFromLocation(
- Point(lastXChosen - xOffset, pt.y + direction * (vs.lineHeight * LinesToScroll())),
- false, false, UserVirtualSpace());
- }
-
- if (topLineNew != topLine) {
- SetTopLine(topLineNew);
- MovePositionTo(newPos, selt);
- Redraw();
- SetVerticalScrollPos();
- } else {
- MovePositionTo(newPos, selt);
- }
-}
-
-void Editor::ChangeCaseOfSelection(int caseMapping) {
- UndoGroup ug(pdoc);
- for (size_t r=0; r<sel.Count(); r++) {
- SelectionRange current = sel.Range(r);
- SelectionRange currentNoVS = current;
- currentNoVS.ClearVirtualSpace();
- size_t rangeBytes = currentNoVS.Length();
- if (rangeBytes > 0) {
- std::string sText = RangeText(currentNoVS.Start().Position(), currentNoVS.End().Position());
-
- std::string sMapped = CaseMapString(sText, caseMapping);
-
- if (sMapped != sText) {
- size_t firstDifference = 0;
- while (sMapped[firstDifference] == sText[firstDifference])
- firstDifference++;
- size_t lastDifferenceText = sText.size() - 1;
- size_t lastDifferenceMapped = sMapped.size() - 1;
- while (sMapped[lastDifferenceMapped] == sText[lastDifferenceText]) {
- lastDifferenceText--;
- lastDifferenceMapped--;
- }
- size_t endDifferenceText = sText.size() - 1 - lastDifferenceText;
- pdoc->DeleteChars(
- static_cast<int>(currentNoVS.Start().Position() + firstDifference),
- static_cast<int>(rangeBytes - firstDifference - endDifferenceText));
- pdoc->InsertString(
- static_cast<int>(currentNoVS.Start().Position() + firstDifference),
- sMapped.c_str() + firstDifference,
- static_cast<int>(lastDifferenceMapped - firstDifference + 1));
- // Automatic movement changes selection so reset to exactly the same as it was.
- int diffSizes = static_cast<int>(sMapped.size() - sText.size());
- if (diffSizes != 0) {
- if (current.anchor > current.caret)
- current.anchor.Add(diffSizes);
- else
- current.caret.Add(diffSizes);
- }
- sel.Range(r) = current;
- }
- }
- }
-}
-
-void Editor::LineTranspose() {
- int line = pdoc->LineFromPosition(sel.MainCaret());
- if (line > 0) {
- UndoGroup ug(pdoc);
- int startPrev = pdoc->LineStart(line - 1);
- int endPrev = pdoc->LineEnd(line - 1);
- int start = pdoc->LineStart(line);
- int end = pdoc->LineEnd(line);
- std::string line1 = RangeText(startPrev, endPrev);
- int len1 = endPrev - startPrev;
- std::string line2 = RangeText(start, end);
- int len2 = end - start;
- pdoc->DeleteChars(start, len2);
- pdoc->DeleteChars(startPrev, len1);
- pdoc->InsertString(startPrev, line2.c_str(), len2);
- pdoc->InsertString(start - len1 + len2, line1.c_str(), len1);
- MovePositionTo(SelectionPosition(start - len1 + len2));
- }
-}
-
-void Editor::Duplicate(bool forLine) {
- if (sel.Empty()) {
- forLine = true;
- }
- UndoGroup ug(pdoc);
- const char *eol = "";
- int eolLen = 0;
- if (forLine) {
- eol = StringFromEOLMode(pdoc->eolMode);
- eolLen = istrlen(eol);
- }
- for (size_t r=0; r<sel.Count(); r++) {
- SelectionPosition start = sel.Range(r).Start();
- SelectionPosition end = sel.Range(r).End();
- if (forLine) {
- int line = pdoc->LineFromPosition(sel.Range(r).caret.Position());
- start = SelectionPosition(pdoc->LineStart(line));
- end = SelectionPosition(pdoc->LineEnd(line));
- }
- std::string text = RangeText(start.Position(), end.Position());
- if (forLine)
- pdoc->InsertString(end.Position(), eol, eolLen);
- pdoc->InsertString(end.Position() + eolLen, text.c_str(), SelectionRange(end, start).Length());
- }
- if (sel.Count() && sel.IsRectangular()) {
- SelectionPosition last = sel.Last();
- if (forLine) {
- int line = pdoc->LineFromPosition(last.Position());
- last = SelectionPosition(last.Position() + pdoc->LineStart(line+1) - pdoc->LineStart(line));
- }
- if (sel.Rectangular().anchor > sel.Rectangular().caret)
- sel.Rectangular().anchor = last;
- else
- sel.Rectangular().caret = last;
- SetRectangularRange();
- }
-}
-
-void Editor::CancelModes() {
- sel.SetMoveExtends(false);
-}
-
-void Editor::NewLine() {
- // Remove non-main ranges
- InvalidateSelection(sel.RangeMain(), true);
- sel.SetSelection(sel.RangeMain());
-
- // Clear main range and insert line end
- bool needGroupUndo = !sel.Empty();
- if (needGroupUndo)
- pdoc->BeginUndoAction();
-
- if (!sel.Empty())
- ClearSelection();
- const char *eol = "\n";
- if (pdoc->eolMode == SC_EOL_CRLF) {
- eol = "\r\n";
- } else if (pdoc->eolMode == SC_EOL_CR) {
- eol = "\r";
- } // else SC_EOL_LF -> "\n" already set
- bool inserted = pdoc->InsertCString(sel.MainCaret(), eol);
- // Want to end undo group before NotifyChar as applications often modify text here
- if (needGroupUndo)
- pdoc->EndUndoAction();
- if (inserted) {
- SetEmptySelection(sel.MainCaret() + istrlen(eol));
- while (*eol) {
- NotifyChar(*eol);
- if (recordingMacro) {
- char txt[2];
- txt[0] = *eol;
- txt[1] = '\0';
- NotifyMacroRecord(SCI_REPLACESEL, 0, reinterpret_cast<sptr_t>(txt));
- }
- eol++;
- }
- }
- SetLastXChosen();
- SetScrollBars();
- EnsureCaretVisible();
- // Avoid blinking during rapid typing:
- ShowCaretAtCurrentPosition();
-}
-
-void Editor::CursorUpOrDown(int direction, Selection::selTypes selt) {
- SelectionPosition caretToUse = sel.Range(sel.Main()).caret;
- if (sel.IsRectangular()) {
- if (selt == Selection::noSel) {
- caretToUse = (direction > 0) ? sel.Limits().end : sel.Limits().start;
- } else {
- caretToUse = sel.Rectangular().caret;
- }
- }
-
- Point pt = LocationFromPosition(caretToUse);
- int skipLines = 0;
-
- if (vs.annotationVisible) {
- int lineDoc = pdoc->LineFromPosition(caretToUse.Position());
- Point ptStartLine = LocationFromPosition(pdoc->LineStart(lineDoc));
- int subLine = (pt.y - ptStartLine.y) / vs.lineHeight;
-
- if (direction < 0 && subLine == 0) {
- int lineDisplay = cs.DisplayFromDoc(lineDoc);
- if (lineDisplay > 0) {
- skipLines = pdoc->AnnotationLines(cs.DocFromDisplay(lineDisplay - 1));
- }
- } else if (direction > 0 && subLine >= (cs.GetHeight(lineDoc) - 1 - pdoc->AnnotationLines(lineDoc))) {
- skipLines = pdoc->AnnotationLines(lineDoc);
- }
- }
-
- int newY = pt.y + (1 + skipLines) * direction * vs.lineHeight;
- SelectionPosition posNew = SPositionFromLocation(
- Point(lastXChosen - xOffset, newY), false, false, UserVirtualSpace());
-
- if (direction < 0) {
- // Line wrapping may lead to a location on the same line, so
- // seek back if that is the case.
- Point ptNew = LocationFromPosition(posNew.Position());
- while ((posNew.Position() > 0) && (pt.y == ptNew.y)) {
- posNew.Add(-1);
- posNew.SetVirtualSpace(0);
- ptNew = LocationFromPosition(posNew.Position());
- }
- } else if (direction > 0 && posNew.Position() != pdoc->Length()) {
- // There is an equivalent case when moving down which skips
- // over a line.
- Point ptNew = LocationFromPosition(posNew.Position());
- while ((posNew.Position() > caretToUse.Position()) && (ptNew.y > newY)) {
- posNew.Add(-1);
- posNew.SetVirtualSpace(0);
- ptNew = LocationFromPosition(posNew.Position());
- }
- }
-
- MovePositionTo(MovePositionSoVisible(posNew, direction), selt);
-}
-
-void Editor::ParaUpOrDown(int direction, Selection::selTypes selt) {
- int lineDoc, savedPos = sel.MainCaret();
- do {
- MovePositionTo(SelectionPosition(direction > 0 ? pdoc->ParaDown(sel.MainCaret()) : pdoc->ParaUp(sel.MainCaret())), selt);
- lineDoc = pdoc->LineFromPosition(sel.MainCaret());
- if (direction > 0) {
- if (sel.MainCaret() >= pdoc->Length() && !cs.GetVisible(lineDoc)) {
- if (selt == Selection::noSel) {
- MovePositionTo(SelectionPosition(pdoc->LineEndPosition(savedPos)));
- }
- break;
- }
- }
- } while (!cs.GetVisible(lineDoc));
-}
-
-int Editor::StartEndDisplayLine(int pos, bool start) {
- RefreshStyleData();
- int line = pdoc->LineFromPosition(pos);
- AutoSurface surface(this);
- AutoLineLayout ll(llc, RetrieveLineLayout(line));
- int posRet = INVALID_POSITION;
- if (surface && ll) {
- unsigned int posLineStart = pdoc->LineStart(line);
- LayoutLine(line, surface, vs, ll, 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;
- }
- }
- }
- }
- }
- if (posRet == INVALID_POSITION) {
- return pos;
- } else {
- return posRet;
- }
-}
-
-int Editor::KeyCommand(unsigned int iMessage) {
- switch (iMessage) {
- case SCI_LINEDOWN:
- CursorUpOrDown(1);
- break;
- case SCI_LINEDOWNEXTEND:
- CursorUpOrDown(1, Selection::selStream);
- break;
- case SCI_LINEDOWNRECTEXTEND:
- CursorUpOrDown(1, Selection::selRectangle);
- break;
- case SCI_PARADOWN:
- ParaUpOrDown(1);
- break;
- case SCI_PARADOWNEXTEND:
- ParaUpOrDown(1, Selection::selStream);
- break;
- case SCI_LINESCROLLDOWN:
- ScrollTo(topLine + 1);
- MoveCaretInsideView(false);
- break;
- case SCI_LINEUP:
- CursorUpOrDown(-1);
- break;
- case SCI_LINEUPEXTEND:
- CursorUpOrDown(-1, Selection::selStream);
- break;
- case SCI_LINEUPRECTEXTEND:
- CursorUpOrDown(-1, Selection::selRectangle);
- break;
- case SCI_PARAUP:
- ParaUpOrDown(-1);
- break;
- case SCI_PARAUPEXTEND:
- ParaUpOrDown(-1, Selection::selStream);
- break;
- case SCI_LINESCROLLUP:
- ScrollTo(topLine - 1);
- MoveCaretInsideView(false);
- break;
- case SCI_CHARLEFT:
- if (SelectionEmpty() || sel.MoveExtends()) {
- if ((sel.Count() == 1) && pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) {
- SelectionPosition spCaret = sel.RangeMain().caret;
- spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1);
- MovePositionTo(spCaret);
- } else if (sel.MoveExtends() && sel.selType == Selection::selStream) {
- MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1));
- } else {
- MovePositionTo(MovePositionSoVisible(
- SelectionPosition((sel.LimitsForRectangularElseMain().start).Position() - 1), -1));
- }
- } else {
- MovePositionTo(sel.LimitsForRectangularElseMain().start);
- }
- SetLastXChosen();
- break;
- case SCI_CHARLEFTEXTEND:
- if (pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) {
- SelectionPosition spCaret = sel.RangeMain().caret;
- spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1);
- MovePositionTo(spCaret, Selection::selStream);
- } else {
- MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1), Selection::selStream);
- }
- SetLastXChosen();
- break;
- case SCI_CHARLEFTRECTEXTEND:
- if (pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) {
- SelectionPosition spCaret = sel.RangeMain().caret;
- spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1);
- MovePositionTo(spCaret, Selection::selRectangle);
- } else {
- MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1), Selection::selRectangle);
- }
- SetLastXChosen();
- break;
- case SCI_CHARRIGHT:
- if (SelectionEmpty() || sel.MoveExtends()) {
- if ((virtualSpaceOptions & SCVS_USERACCESSIBLE) && pdoc->IsLineEndPosition(sel.MainCaret())) {
- SelectionPosition spCaret = sel.RangeMain().caret;
- spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1);
- MovePositionTo(spCaret);
- } else if (sel.MoveExtends() && sel.selType == Selection::selStream) {
- MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1));
- } else {
- MovePositionTo(MovePositionSoVisible(
- SelectionPosition((sel.LimitsForRectangularElseMain().end).Position() + 1), 1));
- }
- } else {
- MovePositionTo(sel.LimitsForRectangularElseMain().end);
- }
- SetLastXChosen();
- break;
- case SCI_CHARRIGHTEXTEND:
- if ((virtualSpaceOptions & SCVS_USERACCESSIBLE) && pdoc->IsLineEndPosition(sel.MainCaret())) {
- SelectionPosition spCaret = sel.RangeMain().caret;
- spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1);
- MovePositionTo(spCaret, Selection::selStream);
- } else {
- MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1), Selection::selStream);
- }
- SetLastXChosen();
- break;
- case SCI_CHARRIGHTRECTEXTEND:
- if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) && pdoc->IsLineEndPosition(sel.MainCaret())) {
- SelectionPosition spCaret = sel.RangeMain().caret;
- spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1);
- MovePositionTo(spCaret, Selection::selRectangle);
- } else {
- MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1), Selection::selRectangle);
- }
- SetLastXChosen();
- break;
- case SCI_WORDLEFT:
- MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), -1), -1));
- SetLastXChosen();
- break;
- case SCI_WORDLEFTEXTEND:
- MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), -1), -1), Selection::selStream);
- SetLastXChosen();
- break;
- case SCI_WORDRIGHT:
- MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), 1), 1));
- SetLastXChosen();
- break;
- case SCI_WORDRIGHTEXTEND:
- MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), 1), 1), Selection::selStream);
- SetLastXChosen();
- break;
-
- case SCI_WORDLEFTEND:
- MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), -1), -1));
- SetLastXChosen();
- break;
- case SCI_WORDLEFTENDEXTEND:
- MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), -1), -1), Selection::selStream);
- SetLastXChosen();
- break;
- case SCI_WORDRIGHTEND:
- MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), 1), 1));
- SetLastXChosen();
- break;
- case SCI_WORDRIGHTENDEXTEND:
- MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), 1), 1), Selection::selStream);
- SetLastXChosen();
- break;
-
- case SCI_HOME:
- MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())));
- SetLastXChosen();
- break;
- case SCI_HOMEEXTEND:
- MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())), Selection::selStream);
- SetLastXChosen();
- break;
- case SCI_HOMERECTEXTEND:
- MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())), Selection::selRectangle);
- SetLastXChosen();
- break;
- case SCI_LINEEND:
- MovePositionTo(pdoc->LineEndPosition(sel.MainCaret()));
- SetLastXChosen();
- break;
- case SCI_LINEENDEXTEND:
- MovePositionTo(pdoc->LineEndPosition(sel.MainCaret()), Selection::selStream);
- SetLastXChosen();
- break;
- case SCI_LINEENDRECTEXTEND:
- MovePositionTo(pdoc->LineEndPosition(sel.MainCaret()), Selection::selRectangle);
- SetLastXChosen();
- break;
- case SCI_HOMEWRAP: {
- SelectionPosition homePos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
- if (sel.RangeMain().caret <= homePos)
- homePos = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())));
- MovePositionTo(homePos);
- SetLastXChosen();
- }
- break;
- case SCI_HOMEWRAPEXTEND: {
- SelectionPosition homePos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
- if (sel.RangeMain().caret <= homePos)
- homePos = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())));
- MovePositionTo(homePos, Selection::selStream);
- SetLastXChosen();
- }
- break;
- case SCI_LINEENDWRAP: {
- SelectionPosition endPos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), false), 1);
- SelectionPosition realEndPos = SelectionPosition(pdoc->LineEndPosition(sel.MainCaret()));
- if (endPos > realEndPos // if moved past visible EOLs
- || sel.RangeMain().caret >= endPos) // if at end of display line already
- endPos = realEndPos;
- MovePositionTo(endPos);
- SetLastXChosen();
- }
- break;
- case SCI_LINEENDWRAPEXTEND: {
- SelectionPosition endPos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), false), 1);
- SelectionPosition realEndPos = SelectionPosition(pdoc->LineEndPosition(sel.MainCaret()));
- if (endPos > realEndPos // if moved past visible EOLs
- || sel.RangeMain().caret >= endPos) // if at end of display line already
- endPos = realEndPos;
- MovePositionTo(endPos, Selection::selStream);
- SetLastXChosen();
- }
- break;
- case SCI_DOCUMENTSTART:
- MovePositionTo(0);
- SetLastXChosen();
- break;
- case SCI_DOCUMENTSTARTEXTEND:
- MovePositionTo(0, Selection::selStream);
- SetLastXChosen();
- break;
- case SCI_DOCUMENTEND:
- MovePositionTo(pdoc->Length());
- SetLastXChosen();
- break;
- case SCI_DOCUMENTENDEXTEND:
- MovePositionTo(pdoc->Length(), Selection::selStream);
- SetLastXChosen();
- break;
- case SCI_STUTTEREDPAGEUP:
- PageMove(-1, Selection::noSel, true);
- break;
- case SCI_STUTTEREDPAGEUPEXTEND:
- PageMove(-1, Selection::selStream, true);
- break;
- case SCI_STUTTEREDPAGEDOWN:
- PageMove(1, Selection::noSel, true);
- break;
- case SCI_STUTTEREDPAGEDOWNEXTEND:
- PageMove(1, Selection::selStream, true);
- break;
- case SCI_PAGEUP:
- PageMove(-1);
- break;
- case SCI_PAGEUPEXTEND:
- PageMove(-1, Selection::selStream);
- break;
- case SCI_PAGEUPRECTEXTEND:
- PageMove(-1, Selection::selRectangle);
- break;
- case SCI_PAGEDOWN:
- PageMove(1);
- break;
- case SCI_PAGEDOWNEXTEND:
- PageMove(1, Selection::selStream);
- break;
- case SCI_PAGEDOWNRECTEXTEND:
- PageMove(1, Selection::selRectangle);
- break;
- case SCI_EDITTOGGLEOVERTYPE:
- inOverstrike = !inOverstrike;
- DropCaret();
- ShowCaretAtCurrentPosition();
- ContainerNeedsUpdate(SC_UPDATE_CONTENT);
- NotifyUpdateUI();
- break;
- case SCI_CANCEL: // Cancel any modes - handled in subclass
- // Also unselect text
- CancelModes();
- break;
- case SCI_DELETEBACK:
- DelCharBack(true);
- if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) {
- SetLastXChosen();
- }
- EnsureCaretVisible();
- break;
- case SCI_DELETEBACKNOTLINE:
- DelCharBack(false);
- if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) {
- SetLastXChosen();
- }
- EnsureCaretVisible();
- break;
- case SCI_TAB:
- Indent(true);
- if (caretSticky == SC_CARETSTICKY_OFF) {
- SetLastXChosen();
- }
- EnsureCaretVisible();
- ShowCaretAtCurrentPosition(); // Avoid blinking
- break;
- case SCI_BACKTAB:
- Indent(false);
- if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) {
- SetLastXChosen();
- }
- EnsureCaretVisible();
- ShowCaretAtCurrentPosition(); // Avoid blinking
- break;
- case SCI_NEWLINE:
- NewLine();
- break;
- case SCI_FORMFEED:
- AddChar('\f');
- break;
- case SCI_VCHOME:
- MovePositionTo(pdoc->VCHomePosition(sel.MainCaret()));
- SetLastXChosen();
- break;
- case SCI_VCHOMEEXTEND:
- MovePositionTo(pdoc->VCHomePosition(sel.MainCaret()), Selection::selStream);
- SetLastXChosen();
- break;
- case SCI_VCHOMERECTEXTEND:
- MovePositionTo(pdoc->VCHomePosition(sel.MainCaret()), Selection::selRectangle);
- SetLastXChosen();
- break;
- case SCI_VCHOMEWRAP: {
- SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret()));
- SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
- if ((viewLineStart < sel.RangeMain().caret) && (viewLineStart > homePos))
- homePos = viewLineStart;
-
- MovePositionTo(homePos);
- SetLastXChosen();
- }
- break;
- case SCI_VCHOMEWRAPEXTEND: {
- SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret()));
- SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
- if ((viewLineStart < sel.RangeMain().caret) && (viewLineStart > homePos))
- homePos = viewLineStart;
-
- MovePositionTo(homePos, Selection::selStream);
- SetLastXChosen();
- }
- break;
- case SCI_ZOOMIN:
- if (vs.zoomLevel < 20) {
- vs.zoomLevel++;
- InvalidateStyleRedraw();
- NotifyZoom();
- }
- break;
- case SCI_ZOOMOUT:
- if (vs.zoomLevel > -10) {
- vs.zoomLevel--;
- InvalidateStyleRedraw();
- NotifyZoom();
- }
- break;
- case SCI_DELWORDLEFT: {
- int startWord = pdoc->NextWordStart(sel.MainCaret(), -1);
- pdoc->DeleteChars(startWord, sel.MainCaret() - startWord);
- sel.RangeMain().ClearVirtualSpace();
- SetLastXChosen();
- }
- break;
- case SCI_DELWORDRIGHT: {
- UndoGroup ug(pdoc);
- sel.RangeMain().caret = SelectionPosition(
- InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace()));
- sel.RangeMain().anchor = sel.RangeMain().caret;
- int endWord = pdoc->NextWordStart(sel.MainCaret(), 1);
- pdoc->DeleteChars(sel.MainCaret(), endWord - sel.MainCaret());
- }
- break;
- case SCI_DELWORDRIGHTEND: {
- UndoGroup ug(pdoc);
- sel.RangeMain().caret = SelectionPosition(
- InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace()));
- int endWord = pdoc->NextWordEnd(sel.MainCaret(), 1);
- pdoc->DeleteChars(sel.MainCaret(), endWord - sel.MainCaret());
- }
- break;
- case SCI_DELLINELEFT: {
- int line = pdoc->LineFromPosition(sel.MainCaret());
- int start = pdoc->LineStart(line);
- pdoc->DeleteChars(start, sel.MainCaret() - start);
- sel.RangeMain().ClearVirtualSpace();
- SetLastXChosen();
- }
- break;
- case SCI_DELLINERIGHT: {
- int line = pdoc->LineFromPosition(sel.MainCaret());
- int end = pdoc->LineEnd(line);
- pdoc->DeleteChars(sel.MainCaret(), end - sel.MainCaret());
- }
- break;
- case SCI_LINECOPY: {
- int lineStart = pdoc->LineFromPosition(SelectionStart().Position());
- int lineEnd = pdoc->LineFromPosition(SelectionEnd().Position());
- CopyRangeToClipboard(pdoc->LineStart(lineStart),
- pdoc->LineStart(lineEnd + 1));
- }
- break;
- case SCI_LINECUT: {
- int lineStart = pdoc->LineFromPosition(SelectionStart().Position());
- int lineEnd = pdoc->LineFromPosition(SelectionEnd().Position());
- int start = pdoc->LineStart(lineStart);
- int end = pdoc->LineStart(lineEnd + 1);
- SetSelection(start, end);
- Cut();
- SetLastXChosen();
- }
- break;
- case SCI_LINEDELETE: {
- int line = pdoc->LineFromPosition(sel.MainCaret());
- int start = pdoc->LineStart(line);
- int end = pdoc->LineStart(line + 1);
- pdoc->DeleteChars(start, end - start);
- }
- break;
- case SCI_LINETRANSPOSE:
- LineTranspose();
- break;
- case SCI_LINEDUPLICATE:
- Duplicate(true);
- break;
- case SCI_SELECTIONDUPLICATE:
- Duplicate(false);
- break;
- case SCI_LOWERCASE:
- ChangeCaseOfSelection(cmLower);
- break;
- case SCI_UPPERCASE:
- ChangeCaseOfSelection(cmUpper);
- break;
- case SCI_WORDPARTLEFT:
- MovePositionTo(MovePositionSoVisible(pdoc->WordPartLeft(sel.MainCaret()), -1));
- SetLastXChosen();
- break;
- case SCI_WORDPARTLEFTEXTEND:
- MovePositionTo(MovePositionSoVisible(pdoc->WordPartLeft(sel.MainCaret()), -1), Selection::selStream);
- SetLastXChosen();
- break;
- case SCI_WORDPARTRIGHT:
- MovePositionTo(MovePositionSoVisible(pdoc->WordPartRight(sel.MainCaret()), 1));
- SetLastXChosen();
- break;
- case SCI_WORDPARTRIGHTEXTEND:
- MovePositionTo(MovePositionSoVisible(pdoc->WordPartRight(sel.MainCaret()), 1), Selection::selStream);
- SetLastXChosen();
- break;
- case SCI_HOMEDISPLAY:
- MovePositionTo(MovePositionSoVisible(
- StartEndDisplayLine(sel.MainCaret(), true), -1));
- SetLastXChosen();
- break;
- case SCI_VCHOMEDISPLAY: {
- SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret()));
- SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
- if (viewLineStart > homePos)
- homePos = viewLineStart;
-
- MovePositionTo(homePos);
- SetLastXChosen();
- }
- break;
- case SCI_HOMEDISPLAYEXTEND:
- MovePositionTo(MovePositionSoVisible(
- StartEndDisplayLine(sel.MainCaret(), true), -1), Selection::selStream);
- SetLastXChosen();
- break;
- case SCI_VCHOMEDISPLAYEXTEND: {
- SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret()));
- SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1);
- if (viewLineStart > homePos)
- homePos = viewLineStart;
-
- MovePositionTo(homePos, Selection::selStream);
- SetLastXChosen();
- }
- break;
- case SCI_LINEENDDISPLAY:
- MovePositionTo(MovePositionSoVisible(
- StartEndDisplayLine(sel.MainCaret(), false), 1));
- SetLastXChosen();
- break;
- case SCI_LINEENDDISPLAYEXTEND:
- MovePositionTo(MovePositionSoVisible(
- StartEndDisplayLine(sel.MainCaret(), false), 1), Selection::selStream);
- SetLastXChosen();
- break;
- case SCI_SCROLLTOSTART:
- ScrollTo(0);
- break;
- case SCI_SCROLLTOEND:
- ScrollTo(MaxScrollPos());
- break;
- }
- return 0;
-}
-
-int Editor::KeyDefault(int, int) {
- return 0;
-}
-
-int Editor::KeyDownWithModifiers(int key, int modifiers, bool *consumed) {
- DwellEnd(false);
- int msg = kmap.Find(key, modifiers);
- if (msg) {
- if (consumed)
- *consumed = true;
- return WndProc(msg, 0, 0);
- } else {
- if (consumed)
- *consumed = false;
- return KeyDefault(key, modifiers);
- }
-}
-
-int Editor::KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed) {
- int modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
- (alt ? SCI_ALT : 0);
- return KeyDownWithModifiers(key, modifiers, consumed);
-}
-
-void Editor::Indent(bool forwards) {
- UndoGroup ug(pdoc);
- for (size_t r=0; r<sel.Count(); r++) {
- int lineOfAnchor = pdoc->LineFromPosition(sel.Range(r).anchor.Position());
- int caretPosition = sel.Range(r).caret.Position();
- int lineCurrentPos = pdoc->LineFromPosition(caretPosition);
- if (lineOfAnchor == lineCurrentPos) {
- if (forwards) {
- pdoc->DeleteChars(sel.Range(r).Start().Position(), sel.Range(r).Length());
- caretPosition = sel.Range(r).caret.Position();
- if (pdoc->GetColumn(caretPosition) <= pdoc->GetColumn(pdoc->GetLineIndentPosition(lineCurrentPos)) &&
- pdoc->tabIndents) {
- int indentation = pdoc->GetLineIndentation(lineCurrentPos);
- int indentationStep = pdoc->IndentSize();
- pdoc->SetLineIndentation(lineCurrentPos, indentation + indentationStep - indentation % indentationStep);
- sel.Range(r) = SelectionRange(pdoc->GetLineIndentPosition(lineCurrentPos));
- } else {
- if (pdoc->useTabs) {
- pdoc->InsertChar(caretPosition, '\t');
- sel.Range(r) = SelectionRange(caretPosition+1);
- } else {
- int numSpaces = (pdoc->tabInChars) -
- (pdoc->GetColumn(caretPosition) % (pdoc->tabInChars));
- if (numSpaces < 1)
- numSpaces = pdoc->tabInChars;
- for (int i = 0; i < numSpaces; i++) {
- pdoc->InsertChar(caretPosition + i, ' ');
- }
- sel.Range(r) = SelectionRange(caretPosition+numSpaces);
- }
- }
- } else {
- if (pdoc->GetColumn(caretPosition) <= pdoc->GetLineIndentation(lineCurrentPos) &&
- pdoc->tabIndents) {
- int indentation = pdoc->GetLineIndentation(lineCurrentPos);
- int indentationStep = pdoc->IndentSize();
- pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep);
- sel.Range(r) = SelectionRange(pdoc->GetLineIndentPosition(lineCurrentPos));
- } else {
- int newColumn = ((pdoc->GetColumn(caretPosition) - 1) / pdoc->tabInChars) *
- pdoc->tabInChars;
- if (newColumn < 0)
- newColumn = 0;
- int newPos = caretPosition;
- while (pdoc->GetColumn(newPos) > newColumn)
- newPos--;
- sel.Range(r) = SelectionRange(newPos);
- }
- }
- } else { // Multiline
- int anchorPosOnLine = sel.Range(r).anchor.Position() - pdoc->LineStart(lineOfAnchor);
- int currentPosPosOnLine = caretPosition - pdoc->LineStart(lineCurrentPos);
- // Multiple lines selected so indent / dedent
- int lineTopSel = Platform::Minimum(lineOfAnchor, lineCurrentPos);
- int lineBottomSel = Platform::Maximum(lineOfAnchor, lineCurrentPos);
- if (pdoc->LineStart(lineBottomSel) == sel.Range(r).anchor.Position() || pdoc->LineStart(lineBottomSel) == caretPosition)
- lineBottomSel--; // If not selecting any characters on a line, do not indent
- pdoc->Indent(forwards, lineBottomSel, lineTopSel);
- if (lineOfAnchor < lineCurrentPos) {
- if (currentPosPosOnLine == 0)
- sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor));
- else
- sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos + 1), pdoc->LineStart(lineOfAnchor));
- } else {
- if (anchorPosOnLine == 0)
- sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor));
- else
- sel.Range(r) = SelectionRange(pdoc->LineStart(lineCurrentPos), pdoc->LineStart(lineOfAnchor + 1));
- }
- }
- }
-}
-
-class CaseFolderASCII : public CaseFolderTable {
-public:
- CaseFolderASCII() {
- StandardASCII();
- }
- ~CaseFolderASCII() {
- }
-};
-
-
-CaseFolder *Editor::CaseFolderForEncoding() {
- // Simple default that only maps ASCII upper case to lower case.
- return new CaseFolderASCII();
-}
-
-/**
- * Search of a text in the document, in the given range.
- * @return The position of the found text, -1 if not found.
- */
-long Editor::FindText(
- uptr_t wParam, ///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD,
- ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX.
- sptr_t lParam) { ///< @c TextToFind structure: The text to search for in the given range.
-
- Sci_TextToFind *ft = reinterpret_cast<Sci_TextToFind *>(lParam);
- int lengthFound = istrlen(ft->lpstrText);
- if (!pdoc->HasCaseFolder())
- pdoc->SetCaseFolder(CaseFolderForEncoding());
- int pos = pdoc->FindText(ft->chrg.cpMin, ft->chrg.cpMax, ft->lpstrText,
- (wParam & SCFIND_MATCHCASE) != 0,
- (wParam & SCFIND_WHOLEWORD) != 0,
- (wParam & SCFIND_WORDSTART) != 0,
- (wParam & SCFIND_REGEXP) != 0,
- wParam,
- &lengthFound);
- if (pos != -1) {
- ft->chrgText.cpMin = pos;
- ft->chrgText.cpMax = pos + lengthFound;
- }
- return pos;
-}
-
-/**
- * Relocatable search support : Searches relative to current selection
- * point and sets the selection to the found text range with
- * each search.
- */
-/**
- * Anchor following searches at current selection start: This allows
- * multiple incremental interactive searches to be macro recorded
- * while still setting the selection to found text so the find/select
- * operation is self-contained.
- */
-void Editor::SearchAnchor() {
- searchAnchor = SelectionStart().Position();
-}
-
-/**
- * Find text from current search anchor: Must call @c SearchAnchor first.
- * Used for next text and previous text requests.
- * @return The position of the found text, -1 if not found.
- */
-long Editor::SearchText(
- unsigned int iMessage, ///< Accepts both @c SCI_SEARCHNEXT and @c SCI_SEARCHPREV.
- uptr_t wParam, ///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD,
- ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX.
- sptr_t lParam) { ///< The text to search for.
-
- const char *txt = reinterpret_cast<char *>(lParam);
- int pos;
- int lengthFound = istrlen(txt);
- if (!pdoc->HasCaseFolder())
- pdoc->SetCaseFolder(CaseFolderForEncoding());
- if (iMessage == SCI_SEARCHNEXT) {
- pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt,
- (wParam & SCFIND_MATCHCASE) != 0,
- (wParam & SCFIND_WHOLEWORD) != 0,
- (wParam & SCFIND_WORDSTART) != 0,
- (wParam & SCFIND_REGEXP) != 0,
- wParam,
- &lengthFound);
- } else {
- pos = pdoc->FindText(searchAnchor, 0, txt,
- (wParam & SCFIND_MATCHCASE) != 0,
- (wParam & SCFIND_WHOLEWORD) != 0,
- (wParam & SCFIND_WORDSTART) != 0,
- (wParam & SCFIND_REGEXP) != 0,
- wParam,
- &lengthFound);
- }
- if (pos != -1) {
- SetSelection(pos, pos + lengthFound);
- }
-
- return pos;
-}
-
-std::string Editor::CaseMapString(const std::string &s, int caseMapping) {
- std::string ret(s);
- for (size_t i=0; i<ret.size(); i++) {
- switch (caseMapping) {
- case cmUpper:
- if (ret[i] >= 'a' && ret[i] <= 'z')
- ret[i] = static_cast<char>(ret[i] - 'a' + 'A');
- break;
- case cmLower:
- if (ret[i] >= 'A' && ret[i] <= 'Z')
- ret[i] = static_cast<char>(ret[i] - 'A' + 'a');
- break;
- }
- }
- return ret;
-}
-
-/**
- * Search for text in the target range of the document.
- * @return The position of the found text, -1 if not found.
- */
-long Editor::SearchInTarget(const char *text, int length) {
- int lengthFound = length;
-
- if (!pdoc->HasCaseFolder())
- pdoc->SetCaseFolder(CaseFolderForEncoding());
- int pos = pdoc->FindText(targetStart, targetEnd, text,
- (searchFlags & SCFIND_MATCHCASE) != 0,
- (searchFlags & SCFIND_WHOLEWORD) != 0,
- (searchFlags & SCFIND_WORDSTART) != 0,
- (searchFlags & SCFIND_REGEXP) != 0,
- searchFlags,
- &lengthFound);
- if (pos != -1) {
- targetStart = pos;
- targetEnd = pos + lengthFound;
- }
- return pos;
-}
-
-void Editor::GoToLine(int lineNo) {
- if (lineNo > pdoc->LinesTotal())
- lineNo = pdoc->LinesTotal();
- if (lineNo < 0)
- lineNo = 0;
- SetEmptySelection(pdoc->LineStart(lineNo));
- ShowCaretAtCurrentPosition();
- EnsureCaretVisible();
-}
-
-static bool Close(Point pt1, Point pt2) {
- if (abs(pt1.x - pt2.x) > 3)
- return false;
- if (abs(pt1.y - pt2.y) > 3)
- return false;
- return true;
-}
-
-std::string Editor::RangeText(int start, int end) const {
- if (start < end) {
- int len = end - start;
- std::string ret(len, '\0');
- for (int i = 0; i < len; i++) {
- ret[i] = pdoc->CharAt(start + i);
- }
- return ret;
- }
- return std::string();
-}
-
-void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) {
- if (sel.Empty()) {
- if (allowLineCopy) {
- int currentLine = pdoc->LineFromPosition(sel.MainCaret());
- int start = pdoc->LineStart(currentLine);
- int end = pdoc->LineEnd(currentLine);
-
- std::string text = RangeText(start, end);
- if (pdoc->eolMode != SC_EOL_LF)
- text.push_back('\r');
- if (pdoc->eolMode != SC_EOL_CR)
- text.push_back('\n');
- ss->Copy(text, pdoc->dbcsCodePage,
- vs.styles[STYLE_DEFAULT].characterSet, false, true);
- }
- } else {
- std::string text;
- std::vector<SelectionRange> rangesInOrder = sel.RangesCopy();
- if (sel.selType == Selection::selRectangle)
- std::sort(rangesInOrder.begin(), rangesInOrder.end());
- for (size_t r=0; r<rangesInOrder.size(); r++) {
- SelectionRange current = rangesInOrder[r];
- text.append(RangeText(current.Start().Position(), current.End().Position()));
- if (sel.selType == Selection::selRectangle) {
- if (pdoc->eolMode != SC_EOL_LF)
- text.push_back('\r');
- if (pdoc->eolMode != SC_EOL_CR)
- text.push_back('\n');
- }
- }
- ss->Copy(text, pdoc->dbcsCodePage,
- vs.styles[STYLE_DEFAULT].characterSet, sel.IsRectangular(), sel.selType == Selection::selLines);
- }
-}
-
-void Editor::CopyRangeToClipboard(int start, int end) {
- start = pdoc->ClampPositionIntoDocument(start);
- end = pdoc->ClampPositionIntoDocument(end);
- SelectionText selectedText;
- std::string text = RangeText(start, end);
- selectedText.Copy(text,
- pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, false);
- CopyToClipboard(selectedText);
-}
-
-void Editor::CopyText(int length, const char *text) {
- SelectionText selectedText;
- selectedText.Copy(std::string(text, length),
- pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, false);
- CopyToClipboard(selectedText);
-}
-
-void Editor::SetDragPosition(SelectionPosition newPos) {
- if (newPos.Position() >= 0) {
- newPos = MovePositionOutsideChar(newPos, 1);
- posDrop = newPos;
- }
- if (!(posDrag == newPos)) {
- caret.on = true;
- SetTicking(true);
- InvalidateCaret();
- posDrag = newPos;
- InvalidateCaret();
- }
-}
-
-void Editor::DisplayCursor(Window::Cursor c) {
- if (cursorMode == SC_CURSORNORMAL)
- wMain.SetCursor(c);
- else
- wMain.SetCursor(static_cast<Window::Cursor>(cursorMode));
-}
-
-bool Editor::DragThreshold(Point ptStart, Point ptNow) {
- int xMove = ptStart.x - ptNow.x;
- int yMove = ptStart.y - ptNow.y;
- int distanceSquared = xMove * xMove + yMove * yMove;
- return distanceSquared > 16;
-}
-
-void Editor::StartDrag() {
- // Always handled by subclasses
- //SetMouseCapture(true);
- //DisplayCursor(Window::cursorArrow);
-}
-
-void Editor::DropAt(SelectionPosition position, const char *value, size_t lengthValue, bool moving, bool rectangular) {
- //Platform::DebugPrintf("DropAt %d %d\n", inDragDrop, position);
- if (inDragDrop == ddDragging)
- dropWentOutside = false;
-
- bool positionWasInSelection = PositionInSelection(position.Position());
-
- bool positionOnEdgeOfSelection =
- (position == SelectionStart()) || (position == SelectionEnd());
-
- if ((inDragDrop != ddDragging) || !(positionWasInSelection) ||
- (positionOnEdgeOfSelection && !moving)) {
-
- SelectionPosition selStart = SelectionStart();
- SelectionPosition selEnd = SelectionEnd();
-
- UndoGroup ug(pdoc);
-
- SelectionPosition positionAfterDeletion = position;
- if ((inDragDrop == ddDragging) && moving) {
- // Remove dragged out text
- if (rectangular || sel.selType == Selection::selLines) {
- for (size_t r=0; r<sel.Count(); r++) {
- if (position >= sel.Range(r).Start()) {
- if (position > sel.Range(r).End()) {
- positionAfterDeletion.Add(-sel.Range(r).Length());
- } else {
- positionAfterDeletion.Add(-SelectionRange(position, sel.Range(r).Start()).Length());
- }
- }
- }
- } else {
- if (position > selStart) {
- positionAfterDeletion.Add(-SelectionRange(selEnd, selStart).Length());
- }
- }
- ClearSelection();
- }
- position = positionAfterDeletion;
-
- if (rectangular) {
- PasteRectangular(position, value, static_cast<int>(lengthValue));
- // Should try to select new rectangle but it may not be a rectangle now so just select the drop position
- SetEmptySelection(position);
- } else {
- position = MovePositionOutsideChar(position, sel.MainCaret() - position.Position());
- position = SelectionPosition(InsertSpace(position.Position(), position.VirtualSpace()));
- if (pdoc->InsertString(position.Position(), value, static_cast<int>(lengthValue))) {
- SelectionPosition posAfterInsertion = position;
- posAfterInsertion.Add(static_cast<int>(lengthValue));
- SetSelection(posAfterInsertion, position);
- }
- }
- } else if (inDragDrop == ddDragging) {
- SetEmptySelection(position);
- }
-}
-
-void Editor::DropAt(SelectionPosition position, const char *value, bool moving, bool rectangular) {
- DropAt(position, value, strlen(value), moving, rectangular);
-}
-
-/**
- * @return true if given position is inside the selection,
- */
-bool Editor::PositionInSelection(int pos) {
- pos = MovePositionOutsideChar(pos, sel.MainCaret() - pos);
- for (size_t r=0; r<sel.Count(); r++) {
- if (sel.Range(r).Contains(pos))
- return true;
- }
- return false;
-}
-
-bool Editor::PointInSelection(Point pt) {
- SelectionPosition pos = SPositionFromLocation(pt, false, true);
- Point ptPos = LocationFromPosition(pos);
- for (size_t r=0; r<sel.Count(); r++) {
- SelectionRange range = sel.Range(r);
- if (range.Contains(pos)) {
- bool hit = true;
- if (pos == range.Start()) {
- // see if just before selection
- if (pt.x < ptPos.x) {
- hit = false;
- }
- }
- if (pos == range.End()) {
- // see if just after selection
- if (pt.x > ptPos.x) {
- hit = false;
- }
- }
- if (hit)
- return true;
- }
- }
- return false;
-}
-
-bool Editor::PointInSelMargin(Point pt) {
- // Really means: "Point in a margin"
- if (vs.fixedColumnWidth > 0) { // There is a margin
- PRectangle rcSelMargin = GetClientRectangle();
- rcSelMargin.right = vs.textStart - vs.leftMarginWidth;
- rcSelMargin.left = vs.textStart - vs.fixedColumnWidth;
- return rcSelMargin.Contains(pt);
- } else {
- return false;
- }
-}
-
-Window::Cursor Editor::GetMarginCursor(Point pt) const {
- int x = 0;
- for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
- if ((pt.x >= x) && (pt.x < x + vs.ms[margin].width))
- return static_cast<Window::Cursor>(vs.ms[margin].cursor);
- x += vs.ms[margin].width;
- }
- return Window::cursorReverseArrow;
-}
-
-void Editor::TrimAndSetSelection(int currentPos_, int anchor_) {
- sel.TrimSelection(SelectionRange(currentPos_, anchor_));
- SetSelection(currentPos_, anchor_);
-}
-
-void Editor::LineSelection(int lineCurrentPos_, int lineAnchorPos_, bool wholeLine) {
- int selCurrentPos, selAnchorPos;
- if (wholeLine) {
- int lineCurrent_ = pdoc->LineFromPosition(lineCurrentPos_);
- int lineAnchor_ = pdoc->LineFromPosition(lineAnchorPos_);
- if (lineAnchorPos_ < lineCurrentPos_) {
- selCurrentPos = pdoc->LineStart(lineCurrent_ + 1);
- selAnchorPos = pdoc->LineStart(lineAnchor_);
- } else if (lineAnchorPos_ > lineCurrentPos_) {
- selCurrentPos = pdoc->LineStart(lineCurrent_);
- selAnchorPos = pdoc->LineStart(lineAnchor_ + 1);
- } else { // Same line, select it
- selCurrentPos = pdoc->LineStart(lineAnchor_ + 1);
- selAnchorPos = pdoc->LineStart(lineAnchor_);
- }
- } else {
- if (lineAnchorPos_ < lineCurrentPos_) {
- selCurrentPos = StartEndDisplayLine(lineCurrentPos_, false) + 1;
- selCurrentPos = pdoc->MovePositionOutsideChar(selCurrentPos, 1);
- selAnchorPos = StartEndDisplayLine(lineAnchorPos_, true);
- } else if (lineAnchorPos_ > lineCurrentPos_) {
- selCurrentPos = StartEndDisplayLine(lineCurrentPos_, true);
- selAnchorPos = StartEndDisplayLine(lineAnchorPos_, false) + 1;
- selAnchorPos = pdoc->MovePositionOutsideChar(selAnchorPos, 1);
- } else { // Same line, select it
- selCurrentPos = StartEndDisplayLine(lineAnchorPos_, false) + 1;
- selCurrentPos = pdoc->MovePositionOutsideChar(selCurrentPos, 1);
- selAnchorPos = StartEndDisplayLine(lineAnchorPos_, true);
- }
- }
- TrimAndSetSelection(selCurrentPos, selAnchorPos);
-}
-
-void Editor::WordSelection(int pos) {
- if (pos < wordSelectAnchorStartPos) {
- // Extend backward to the word containing pos.
- // Skip ExtendWordSelect if the line is empty or if pos is after the last character.
- // This ensures that a series of empty lines isn't counted as a single "word".
- if (!pdoc->IsLineEndPosition(pos))
- pos = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(pos + 1, 1), -1);
- TrimAndSetSelection(pos, wordSelectAnchorEndPos);
- } else if (pos > wordSelectAnchorEndPos) {
- // Extend forward to the word containing the character to the left of pos.
- // Skip ExtendWordSelect if the line is empty or if pos is the first position on the line.
- // This ensures that a series of empty lines isn't counted as a single "word".
- if (pos > pdoc->LineStart(pdoc->LineFromPosition(pos)))
- pos = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(pos - 1, -1), 1);
- TrimAndSetSelection(pos, wordSelectAnchorStartPos);
- } else {
- // Select only the anchored word
- if (pos >= originalAnchorPos)
- TrimAndSetSelection(wordSelectAnchorEndPos, wordSelectAnchorStartPos);
- else
- TrimAndSetSelection(wordSelectAnchorStartPos, wordSelectAnchorEndPos);
- }
-}
-
-void Editor::DwellEnd(bool mouseMoved) {
- if (mouseMoved)
- ticksToDwell = dwellDelay;
- else
- ticksToDwell = SC_TIME_FOREVER;
- if (dwelling && (dwellDelay < SC_TIME_FOREVER)) {
- dwelling = false;
- NotifyDwelling(ptMouseLast, dwelling);
- }
-}
-
-void Editor::MouseLeave() {
- SetHotSpotRange(NULL);
- if (!HaveMouseCapture()) {
- ptMouseLast = Point(-1,-1);
- DwellEnd(true);
- }
-}
-
-static bool AllowVirtualSpace(int virtualSpaceOptions, bool rectangular) {
- return (!rectangular && ((virtualSpaceOptions & SCVS_USERACCESSIBLE) != 0))
- || (rectangular && ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) != 0));
-}
-
-void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt) {
- //Platform::DebugPrintf("ButtonDown %d %d = %d alt=%d %d\n", curTime, lastClickTime, curTime - lastClickTime, alt, inDragDrop);
- ptMouseLast = pt;
- SelectionPosition newPos = SPositionFromLocation(pt, false, false, AllowVirtualSpace(virtualSpaceOptions, alt));
- newPos = MovePositionOutsideChar(newPos, sel.MainCaret() - newPos.Position());
- inDragDrop = ddNone;
- sel.SetMoveExtends(false);
-
- if (NotifyMarginClick(pt, shift, ctrl, alt))
- return;
-
- NotifyIndicatorClick(true, newPos.Position(), shift, ctrl, alt);
-
- bool inSelMargin = PointInSelMargin(pt);
- // In margin ctrl+(double)click should always select everything
- if (ctrl && inSelMargin) {
- SelectAll();
- lastClickTime = curTime;
- lastClick = pt;
- return;
- }
- if (shift && !inSelMargin) {
- SetSelection(newPos);
- }
- if (((curTime - lastClickTime) < Platform::DoubleClickTime()) && Close(pt, lastClick)) {
- //Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime);
- SetMouseCapture(true);
- if (!ctrl || !multipleSelection || (selectionType != selChar && selectionType != selWord))
- SetEmptySelection(newPos.Position());
- bool doubleClick = false;
- // Stop mouse button bounce changing selection type
- if (!Platform::MouseButtonBounce() || curTime != lastClickTime) {
- if (inSelMargin) {
- // Inside margin selection type should be either selSubLine or selWholeLine.
- if (selectionType == selSubLine) {
- // If it is selSubLine, we're inside a *double* click and word wrap is enabled,
- // so we switch to selWholeLine in order to select whole line.
- selectionType = selWholeLine;
- } else if (selectionType != selSubLine && selectionType != selWholeLine) {
- // If it is neither, reset selection type to line selection.
- selectionType = (Wrapping() && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? selSubLine : selWholeLine;
- }
- } else {
- if (selectionType == selChar) {
- selectionType = selWord;
- doubleClick = true;
- } else if (selectionType == selWord) {
- // Since we ended up here, we're inside a *triple* click, which should always select
- // whole line irregardless of word wrap being enabled or not.
- selectionType = selWholeLine;
- } else {
- selectionType = selChar;
- originalAnchorPos = sel.MainCaret();
- }
- }
- }
-
- if (selectionType == selWord) {
- int charPos = originalAnchorPos;
- if (sel.MainCaret() == originalAnchorPos) {
- charPos = PositionFromLocation(pt, false, true);
- charPos = MovePositionOutsideChar(charPos, -1);
- }
-
- int startWord, endWord;
- if ((sel.MainCaret() >= originalAnchorPos) && !pdoc->IsLineEndPosition(charPos)) {
- startWord = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(charPos + 1, 1), -1);
- endWord = pdoc->ExtendWordSelect(charPos, 1);
- } else {
- // Selecting backwards, or anchor beyond last character on line. In these cases,
- // we select the word containing the character to the *left* of the anchor.
- if (charPos > pdoc->LineStart(pdoc->LineFromPosition(charPos))) {
- startWord = pdoc->ExtendWordSelect(charPos, -1);
- endWord = pdoc->ExtendWordSelect(startWord, 1);
- } else {
- // Anchor at start of line; select nothing to begin with.
- startWord = charPos;
- endWord = charPos;
- }
- }
-
- wordSelectAnchorStartPos = startWord;
- wordSelectAnchorEndPos = endWord;
- wordSelectInitialCaretPos = sel.MainCaret();
- WordSelection(wordSelectInitialCaretPos);
- } else if (selectionType == selSubLine || selectionType == selWholeLine) {
- lineAnchorPos = newPos.Position();
- LineSelection(lineAnchorPos, lineAnchorPos, selectionType == selWholeLine);
- //Platform::DebugPrintf("Triple click: %d - %d\n", anchor, currentPos);
- } else {
- SetEmptySelection(sel.MainCaret());
- }
- //Platform::DebugPrintf("Double click: %d - %d\n", anchor, currentPos);
- if (doubleClick) {
- NotifyDoubleClick(pt, shift, ctrl, alt);
- if (PositionIsHotspot(newPos.Position()))
- NotifyHotSpotDoubleClicked(newPos.Position(), shift, ctrl, alt);
- }
- } else { // Single click
- if (inSelMargin) {
- sel.selType = Selection::selStream;
- if (!shift) {
- // Single click in margin: select whole line or only subline if word wrap is enabled
- lineAnchorPos = newPos.Position();
- selectionType = (Wrapping() && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? selSubLine : selWholeLine;
- LineSelection(lineAnchorPos, lineAnchorPos, selectionType == selWholeLine);
- } else {
- // Single shift+click in margin: select from line anchor to clicked line
- if (sel.MainAnchor() > sel.MainCaret())
- lineAnchorPos = sel.MainAnchor() - 1;
- else
- lineAnchorPos = sel.MainAnchor();
- // Reset selection type if there is an empty selection.
- // This ensures that we don't end up stuck in previous selection mode, which is no longer valid.
- // Otherwise, if there's a non empty selection, reset selection type only if it differs from selSubLine and selWholeLine.
- // This ensures that we continue selecting in the same selection mode.
- if (sel.Empty() || (selectionType != selSubLine && selectionType != selWholeLine))
- selectionType = (Wrapping() && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? selSubLine : selWholeLine;
- LineSelection(newPos.Position(), lineAnchorPos, selectionType == selWholeLine);
- }
-
- SetDragPosition(SelectionPosition(invalidPosition));
- SetMouseCapture(true);
- } else {
- if (PointIsHotspot(pt)) {
- NotifyHotSpotClicked(newPos.Position(), shift, ctrl, alt);
- hotSpotClickPos = PositionFromLocation(pt,true,false);
- }
- if (!shift) {
- if (PointInSelection(pt) && !SelectionEmpty())
- inDragDrop = ddInitial;
- else
- inDragDrop = ddNone;
- }
- SetMouseCapture(true);
- if (inDragDrop != ddInitial) {
- SetDragPosition(SelectionPosition(invalidPosition));
- if (!shift) {
- if (ctrl && multipleSelection) {
- SelectionRange range(newPos);
- sel.TentativeSelection(range);
- InvalidateSelection(range, true);
- } else {
- InvalidateSelection(SelectionRange(newPos), true);
- if (sel.Count() > 1)
- Redraw();
- if ((sel.Count() > 1) || (sel.selType != Selection::selStream))
- sel.Clear();
- sel.selType = alt ? Selection::selRectangle : Selection::selStream;
- SetSelection(newPos, newPos);
- }
- }
- SelectionPosition anchorCurrent = newPos;
- if (shift)
- anchorCurrent = sel.IsRectangular() ?
- sel.Rectangular().anchor : sel.RangeMain().anchor;
- sel.selType = alt ? Selection::selRectangle : Selection::selStream;
- selectionType = selChar;
- originalAnchorPos = sel.MainCaret();
- sel.Rectangular() = SelectionRange(newPos, anchorCurrent);
- SetRectangularRange();
- }
- }
- }
- lastClickTime = curTime;
- lastClick = pt;
- lastXChosen = pt.x + xOffset;
- ShowCaretAtCurrentPosition();
-}
-
-bool Editor::PositionIsHotspot(int position) const {
- return vs.styles[pdoc->StyleAt(position) & pdoc->stylingBitsMask].hotspot;
-}
-
-bool Editor::PointIsHotspot(Point pt) {
- int pos = PositionFromLocation(pt, true);
- if (pos == INVALID_POSITION)
- return false;
- return PositionIsHotspot(pos);
-}
-
-void Editor::SetHotSpotRange(Point *pt) {
- if (pt) {
- int pos = PositionFromLocation(*pt);
-
- // If we don't limit this to word characters then the
- // range can encompass more than the run range and then
- // the underline will not be drawn properly.
- int hsStart_ = pdoc->ExtendStyleRange(pos, -1, vs.hotspotSingleLine);
- int hsEnd_ = pdoc->ExtendStyleRange(pos, 1, vs.hotspotSingleLine);
-
- // Only invalidate the range if the hotspot range has changed...
- if (hsStart_ != hsStart || hsEnd_ != hsEnd) {
- if (hsStart != -1) {
- InvalidateRange(hsStart, hsEnd);
- }
- hsStart = hsStart_;
- hsEnd = hsEnd_;
- InvalidateRange(hsStart, hsEnd);
- }
- } else {
- if (hsStart != -1) {
- int hsStart_ = hsStart;
- int hsEnd_ = hsEnd;
- hsStart = -1;
- hsEnd = -1;
- InvalidateRange(hsStart_, hsEnd_);
- } else {
- hsStart = -1;
- hsEnd = -1;
- }
- }
-}
-
-void Editor::GetHotSpotRange(int &hsStart_, int &hsEnd_) const {
- hsStart_ = hsStart;
- hsEnd_ = hsEnd;
-}
-
-void Editor::ButtonMoveWithModifiers(Point pt, int modifiers) {
- if ((ptMouseLast.x != pt.x) || (ptMouseLast.y != pt.y)) {
- DwellEnd(true);
- }
-
- SelectionPosition movePos = SPositionFromLocation(pt, false, false,
- AllowVirtualSpace(virtualSpaceOptions, sel.IsRectangular()));
- movePos = MovePositionOutsideChar(movePos, sel.MainCaret() - movePos.Position());
-
- if (inDragDrop == ddInitial) {
- if (DragThreshold(ptMouseLast, pt)) {
- SetMouseCapture(false);
- SetDragPosition(movePos);
- CopySelectionRange(&drag);
- StartDrag();
- }
- return;
- }
-
- ptMouseLast = pt;
- //Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y);
- if (HaveMouseCapture()) {
-
- // Slow down autoscrolling/selection
- autoScrollTimer.ticksToWait -= timer.tickSize;
- if (autoScrollTimer.ticksToWait > 0)
- return;
- autoScrollTimer.ticksToWait = autoScrollDelay;
-
- // Adjust selection
- if (posDrag.IsValid()) {
- SetDragPosition(movePos);
- } else {
- if (selectionType == selChar) {
- if (sel.selType == Selection::selStream && (modifiers & SCI_ALT) && mouseSelectionRectangularSwitch) {
- sel.selType = Selection::selRectangle;
- }
- if (sel.IsRectangular()) {
- sel.Rectangular() = SelectionRange(movePos, sel.Rectangular().anchor);
- SetSelection(movePos, sel.RangeMain().anchor);
- } else if (sel.Count() > 1) {
- InvalidateSelection(sel.RangeMain(), false);
- SelectionRange range(movePos, sel.RangeMain().anchor);
- sel.TentativeSelection(range);
- InvalidateSelection(range, true);
- } else {
- SetSelection(movePos, sel.RangeMain().anchor);
- }
- } else if (selectionType == selWord) {
- // Continue selecting by word
- if (movePos.Position() == wordSelectInitialCaretPos) { // Didn't move
- // No need to do anything. Previously this case was lumped
- // in with "Moved forward", but that can be harmful in this
- // case: a handler for the NotifyDoubleClick re-adjusts
- // the selection for a fancier definition of "word" (for
- // example, in Perl it is useful to include the leading
- // '$', '%' or '@' on variables for word selection). In this
- // the ButtonMove() called via Tick() for auto-scrolling
- // could result in the fancier word selection adjustment
- // being unmade.
- } else {
- wordSelectInitialCaretPos = -1;
- WordSelection(movePos.Position());
- }
- } else {
- // Continue selecting by line
- LineSelection(movePos.Position(), lineAnchorPos, selectionType == selWholeLine);
- }
- }
-
- // Autoscroll
- PRectangle rcClient = GetClientRectangle();
- Point ptOrigin = GetVisibleOriginInMain();
- rcClient.Move(0, -ptOrigin.y);
- int lineMove = DisplayFromPosition(movePos.Position());
- if (pt.y > rcClient.bottom) {
- ScrollTo(lineMove - LinesOnScreen() + 1);
- Redraw();
- } else if (pt.y < rcClient.top) {
- ScrollTo(lineMove);
- Redraw();
- }
- EnsureCaretVisible(false, false, true);
-
- if (hsStart != -1 && !PositionIsHotspot(movePos.Position()))
- SetHotSpotRange(NULL);
-
- if (hotSpotClickPos != INVALID_POSITION && PositionFromLocation(pt,true,false) != hotSpotClickPos) {
- if (inDragDrop == ddNone) {
- DisplayCursor(Window::cursorText);
- }
- hotSpotClickPos = INVALID_POSITION;
- }
-
- } else {
- if (vs.fixedColumnWidth > 0) { // There is a margin
- if (PointInSelMargin(pt)) {
- DisplayCursor(GetMarginCursor(pt));
- SetHotSpotRange(NULL);
- return; // No need to test for selection
- }
- }
- // Display regular (drag) cursor over selection
- if (PointInSelection(pt) && !SelectionEmpty()) {
- DisplayCursor(Window::cursorArrow);
- } else if (PointIsHotspot(pt)) {
- DisplayCursor(Window::cursorHand);
- SetHotSpotRange(&pt);
- } else {
- DisplayCursor(Window::cursorText);
- SetHotSpotRange(NULL);
- }
- }
-}
-
-void Editor::ButtonMove(Point pt) {
- ButtonMoveWithModifiers(pt, 0);
-}
-
-void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) {
- //Platform::DebugPrintf("ButtonUp %d %d\n", HaveMouseCapture(), inDragDrop);
- SelectionPosition newPos = SPositionFromLocation(pt, false, false,
- AllowVirtualSpace(virtualSpaceOptions, sel.IsRectangular()));
- newPos = MovePositionOutsideChar(newPos, sel.MainCaret() - newPos.Position());
- if (inDragDrop == ddInitial) {
- inDragDrop = ddNone;
- SetEmptySelection(newPos);
- selectionType = selChar;
- originalAnchorPos = sel.MainCaret();
- }
- if (hotSpotClickPos != INVALID_POSITION && PointIsHotspot(pt)) {
- hotSpotClickPos = INVALID_POSITION;
- NotifyHotSpotReleaseClick(newPos.Position(), false, ctrl, false);
- }
- if (HaveMouseCapture()) {
- if (PointInSelMargin(pt)) {
- DisplayCursor(GetMarginCursor(pt));
- } else {
- DisplayCursor(Window::cursorText);
- SetHotSpotRange(NULL);
- }
- ptMouseLast = pt;
- SetMouseCapture(false);
- NotifyIndicatorClick(false, newPos.Position(), false, false, false);
- if (inDragDrop == ddDragging) {
- SelectionPosition selStart = SelectionStart();
- SelectionPosition selEnd = SelectionEnd();
- if (selStart < selEnd) {
- if (drag.Length()) {
- if (ctrl) {
- if (pdoc->InsertString(newPos.Position(), drag.Data(), static_cast<int>(drag.Length()))) {
- SetSelection(newPos.Position(), newPos.Position() + static_cast<int>(drag.Length()));
- }
- } else if (newPos < selStart) {
- pdoc->DeleteChars(selStart.Position(), static_cast<int>(drag.Length()));
- if (pdoc->InsertString(newPos.Position(), drag.Data(), static_cast<int>(drag.Length()))) {
- SetSelection(newPos.Position(), newPos.Position() + static_cast<int>(drag.Length()));
- }
- } else if (newPos > selEnd) {
- pdoc->DeleteChars(selStart.Position(), static_cast<int>(drag.Length()));
- newPos.Add(-static_cast<int>(drag.Length()));
- if (pdoc->InsertString(newPos.Position(), drag.Data(), static_cast<int>(drag.Length()))) {
- SetSelection(newPos.Position(), newPos.Position() + static_cast<int>(drag.Length()));
- }
- } else {
- SetEmptySelection(newPos.Position());
- }
- drag.Clear();
- }
- selectionType = selChar;
- }
- } else {
- if (selectionType == selChar) {
- if (sel.Count() > 1) {
- sel.RangeMain() =
- SelectionRange(newPos, sel.Range(sel.Count() - 1).anchor);
- InvalidateSelection(sel.RangeMain(), true);
- } else {
- SetSelection(newPos, sel.RangeMain().anchor);
- }
- }
- sel.CommitTentative();
- }
- SetRectangularRange();
- lastClickTime = curTime;
- lastClick = pt;
- lastXChosen = pt.x + xOffset;
- if (sel.selType == Selection::selStream) {
- SetLastXChosen();
- }
- inDragDrop = ddNone;
- EnsureCaretVisible(false);
- }
-}
-
-// Called frequently to perform background UI including
-// caret blinking and automatic scrolling.
-void Editor::Tick() {
- if (HaveMouseCapture()) {
- // Auto scroll
- ButtonMove(ptMouseLast);
- }
- if (caret.period > 0) {
- timer.ticksToWait -= timer.tickSize;
- if (timer.ticksToWait <= 0) {
- caret.on = !caret.on;
- timer.ticksToWait = caret.period;
- if (caret.active) {
- InvalidateCaret();
- }
- }
- }
- if (horizontalScrollBarVisible && trackLineWidth && (lineWidthMaxSeen > scrollWidth)) {
- scrollWidth = lineWidthMaxSeen;
- SetScrollBars();
- }
- if ((dwellDelay < SC_TIME_FOREVER) &&
- (ticksToDwell > 0) &&
- (!HaveMouseCapture()) &&
- (ptMouseLast.y >= 0)) {
- ticksToDwell -= timer.tickSize;
- if (ticksToDwell <= 0) {
- dwelling = true;
- NotifyDwelling(ptMouseLast, dwelling);
- }
- }
-}
-
-bool Editor::Idle() {
-
- bool idleDone;
-
- bool wrappingDone = !Wrapping();
-
- if (!wrappingDone) {
- // Wrap lines during idle.
- WrapLines(wsIdle);
- // No more wrapping
- if (!wrapPending.NeedsWrap())
- wrappingDone = true;
- }
-
- // Add more idle things to do here, but make sure idleDone is
- // set correctly before the function returns. returning
- // false will stop calling this idle funtion until SetIdle() is
- // called again.
-
- idleDone = wrappingDone; // && thatDone && theOtherThingDone...
-
- return !idleDone;
-}
-
-void Editor::SetFocusState(bool focusState) {
- hasFocus = focusState;
- NotifyFocus(hasFocus);
- if (hasFocus) {
- ShowCaretAtCurrentPosition();
- } else {
- CancelModes();
- DropCaret();
- }
-}
-
-int Editor::PositionAfterArea(PRectangle rcArea) const {
- // The start of the document line after the display line after the area
- // This often means that the line after a modification is restyled which helps
- // detect multiline comment additions and heals single line comments
- int lineAfter = topLine + (rcArea.bottom - 1) / vs.lineHeight + 1;
- if (lineAfter < cs.LinesDisplayed())
- return pdoc->LineStart(cs.DocFromDisplay(lineAfter) + 1);
- else
- return pdoc->Length();
-}
-
-// Style to a position within the view. If this causes a change at end of last line then
-// affects later lines so style all the viewed text.
-void Editor::StyleToPositionInView(Position pos) {
- int endWindow = (vs.marginInside) ? (PositionAfterArea(GetClientRectangle())) : (pdoc->Length());
- if (pos > endWindow)
- pos = endWindow;
- int styleAtEnd = pdoc->StyleAt(pos-1);
- pdoc->EnsureStyledTo(pos);
- if ((endWindow > pos) && (styleAtEnd != pdoc->StyleAt(pos-1))) {
- // Style at end of line changed so is multi-line change like starting a comment
- // so require rest of window to be styled.
- pdoc->EnsureStyledTo(endWindow);
- }
-}
-
-void Editor::IdleWork() {
- // Style the line after the modification as this allows modifications that change just the
- // line of the modification to heal instead of propagating to the rest of the window.
- if (workNeeded.items & WorkNeeded::workStyle)
- StyleToPositionInView(pdoc->LineStart(pdoc->LineFromPosition(workNeeded.upTo) + 2));
-
- NotifyUpdateUI();
- workNeeded.Reset();
-}
-
-void Editor::QueueIdleWork(WorkNeeded::workItems items, int upTo) {
- workNeeded.Need(items, upTo);
-}
-
-bool Editor::PaintContains(PRectangle rc) {
- if (rc.Empty()) {
- return true;
- } else {
- return rcPaint.Contains(rc);
- }
-}
-
-bool Editor::PaintContainsMargin() {
- if (wMargin.GetID()) {
- // With separate margin view, paint of text view
- // never contains margin.
- return false;
- }
- PRectangle rcSelMargin = GetClientRectangle();
- rcSelMargin.right = vs.textStart;
- return PaintContains(rcSelMargin);
-}
-
-void Editor::CheckForChangeOutsidePaint(Range r) {
- if (paintState == painting && !paintingAllText) {
- //Platform::DebugPrintf("Checking range in paint %d-%d\n", r.start, r.end);
- if (!r.Valid())
- return;
-
- PRectangle rcRange = RectangleFromRange(r.start, r.end);
- PRectangle rcText = GetTextRectangle();
- if (rcRange.top < rcText.top) {
- rcRange.top = rcText.top;
- }
- if (rcRange.bottom > rcText.bottom) {
- rcRange.bottom = rcText.bottom;
- }
-
- if (!PaintContains(rcRange)) {
- AbandonPaint();
- paintAbandonedByStyling = true;
- }
- }
-}
-
-void Editor::SetBraceHighlight(Position pos0, Position pos1, int matchStyle) {
- if ((pos0 != braces[0]) || (pos1 != braces[1]) || (matchStyle != bracesMatchStyle)) {
- if ((braces[0] != pos0) || (matchStyle != bracesMatchStyle)) {
- CheckForChangeOutsidePaint(Range(braces[0]));
- CheckForChangeOutsidePaint(Range(pos0));
- braces[0] = pos0;
- }
- if ((braces[1] != pos1) || (matchStyle != bracesMatchStyle)) {
- CheckForChangeOutsidePaint(Range(braces[1]));
- CheckForChangeOutsidePaint(Range(pos1));
- braces[1] = pos1;
- }
- bracesMatchStyle = matchStyle;
- if (paintState == notPainting) {
- Redraw();
- }
- }
-}
-
-void Editor::SetAnnotationHeights(int start, int end) {
- if (vs.annotationVisible) {
- bool changedHeight = false;
- for (int line=start; line<end && line<pdoc->LinesTotal(); line++) {
- int linesWrapped = 1;
- if (Wrapping()) {
- AutoSurface surface(this);
- AutoLineLayout ll(llc, RetrieveLineLayout(line));
- if (surface && ll) {
- LayoutLine(line, surface, vs, ll, wrapWidth);
- linesWrapped = ll->lines;
- }
- }
- if (cs.SetHeight(line, pdoc->AnnotationLines(line) + linesWrapped))
- changedHeight = true;
- }
- if (changedHeight) {
- Redraw();
- }
- }
-}
-
-void Editor::SetDocPointer(Document *document) {
- //Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document);
- pdoc->RemoveWatcher(this, 0);
- pdoc->Release();
- if (document == NULL) {
- pdoc = new Document();
- } else {
- pdoc = document;
- }
- pdoc->AddRef();
-
- // Ensure all positions within document
- sel.Clear();
- targetStart = 0;
- targetEnd = 0;
-
- braces[0] = invalidPosition;
- braces[1] = invalidPosition;
-
- vs.ReleaseAllExtendedStyles();
-
- SetRepresentations();
-
- // Reset the contraction state to fully shown.
- cs.Clear();
- cs.InsertLines(0, pdoc->LinesTotal() - 1);
- SetAnnotationHeights(0, pdoc->LinesTotal());
- llc.Deallocate();
- NeedWrapping();
-
- pdoc->AddWatcher(this, 0);
- SetScrollBars();
- Redraw();
-}
-
-void Editor::SetAnnotationVisible(int visible) {
- if (vs.annotationVisible != visible) {
- bool changedFromOrToHidden = ((vs.annotationVisible != 0) != (visible != 0));
- vs.annotationVisible = visible;
- if (changedFromOrToHidden) {
- int dir = vs.annotationVisible ? 1 : -1;
- for (int line=0; line<pdoc->LinesTotal(); line++) {
- int annotationLines = pdoc->AnnotationLines(line);
- if (annotationLines > 0) {
- cs.SetHeight(line, cs.GetHeight(line) + annotationLines * dir);
- }
- }
- }
- Redraw();
- }
-}
-
-/**
- * Recursively expand a fold, making lines visible except where they have an unexpanded parent.
- */
-int Editor::ExpandLine(int line) {
- int lineMaxSubord = pdoc->GetLastChild(line);
- line++;
- while (line <= lineMaxSubord) {
- cs.SetVisible(line, line, true);
- int level = pdoc->GetLevel(line);
- if (level & SC_FOLDLEVELHEADERFLAG) {
- if (cs.GetExpanded(line)) {
- line = ExpandLine(line);
- } else {
- line = pdoc->GetLastChild(line);
- }
- }
- line++;
- }
- return lineMaxSubord;
-}
-
-void Editor::SetFoldExpanded(int lineDoc, bool expanded) {
- if (cs.SetExpanded(lineDoc, expanded)) {
- RedrawSelMargin();
- }
-}
-
-void Editor::FoldLine(int line, int action) {
- if (line >= 0) {
- if (action == SC_FOLDACTION_TOGGLE) {
- if ((pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG) == 0) {
- line = pdoc->GetFoldParent(line);
- if (line < 0)
- return;
- }
- action = (cs.GetExpanded(line)) ? SC_FOLDACTION_CONTRACT : SC_FOLDACTION_EXPAND;
- }
-
- if (action == SC_FOLDACTION_CONTRACT) {
- int lineMaxSubord = pdoc->GetLastChild(line);
- if (lineMaxSubord > line) {
- cs.SetExpanded(line, 0);
- cs.SetVisible(line + 1, lineMaxSubord, false);
-
- int lineCurrent = pdoc->LineFromPosition(sel.MainCaret());
- if (lineCurrent > line && lineCurrent <= lineMaxSubord) {
- // This does not re-expand the fold
- EnsureCaretVisible();
- }
- }
-
- } else {
- if (!(cs.GetVisible(line))) {
- EnsureLineVisible(line, false);
- GoToLine(line);
- }
- cs.SetExpanded(line, 1);
- ExpandLine(line);
- }
-
- SetScrollBars();
- Redraw();
- }
-}
-
-void Editor::FoldExpand(int line, int action, int level) {
- bool expanding = action == SC_FOLDACTION_EXPAND;
- if (action == SC_FOLDACTION_TOGGLE) {
- expanding = !cs.GetExpanded(line);
- }
- SetFoldExpanded(line, expanding);
- if (expanding && (cs.HiddenLines() == 0))
- // Nothing to do
- return;
- int lineMaxSubord = pdoc->GetLastChild(line, level & SC_FOLDLEVELNUMBERMASK);
- line++;
- cs.SetVisible(line, lineMaxSubord, expanding);
- while (line <= lineMaxSubord) {
- int levelLine = pdoc->GetLevel(line);
- if (levelLine & SC_FOLDLEVELHEADERFLAG) {
- SetFoldExpanded(line, expanding);
- }
- line++;
- }
- SetScrollBars();
- Redraw();
-}
-
-int Editor::ContractedFoldNext(int lineStart) const {
- for (int line = lineStart; line<pdoc->LinesTotal();) {
- if (!cs.GetExpanded(line) && (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG))
- return line;
- line = cs.ContractedNext(line+1);
- if (line < 0)
- return -1;
- }
-
- return -1;
-}
-
-/**
- * Recurse up from this line to find any folds that prevent this line from being visible
- * and unfold them all.
- */
-void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) {
-
- // In case in need of wrapping to ensure DisplayFromDoc works.
- if (lineDoc >= wrapPending.start)
- WrapLines(wsAll);
-
- if (!cs.GetVisible(lineDoc)) {
- // Back up to find a non-blank line
- int lookLine = lineDoc;
- int lookLineLevel = pdoc->GetLevel(lookLine);
- while ((lookLine > 0) && (lookLineLevel & SC_FOLDLEVELWHITEFLAG)) {
- lookLineLevel = pdoc->GetLevel(--lookLine);
- }
- int lineParent = pdoc->GetFoldParent(lookLine);
- if (lineParent < 0) {
- // Backed up to a top level line, so try to find parent of initial line
- lineParent = pdoc->GetFoldParent(lineDoc);
- }
- if (lineParent >= 0) {
- if (lineDoc != lineParent)
- EnsureLineVisible(lineParent, enforcePolicy);
- if (!cs.GetExpanded(lineParent)) {
- cs.SetExpanded(lineParent, 1);
- ExpandLine(lineParent);
- }
- }
- SetScrollBars();
- Redraw();
- }
- if (enforcePolicy) {
- int lineDisplay = cs.DisplayFromDoc(lineDoc);
- if (visiblePolicy & VISIBLE_SLOP) {
- if ((topLine > lineDisplay) || ((visiblePolicy & VISIBLE_STRICT) && (topLine + visibleSlop > lineDisplay))) {
- SetTopLine(Platform::Clamp(lineDisplay - visibleSlop, 0, MaxScrollPos()));
- SetVerticalScrollPos();
- Redraw();
- } else if ((lineDisplay > topLine + LinesOnScreen() - 1) ||
- ((visiblePolicy & VISIBLE_STRICT) && (lineDisplay > topLine + LinesOnScreen() - 1 - visibleSlop))) {
- SetTopLine(Platform::Clamp(lineDisplay - LinesOnScreen() + 1 + visibleSlop, 0, MaxScrollPos()));
- SetVerticalScrollPos();
- Redraw();
- }
- } else {
- if ((topLine > lineDisplay) || (lineDisplay > topLine + LinesOnScreen() - 1) || (visiblePolicy & VISIBLE_STRICT)) {
- SetTopLine(Platform::Clamp(lineDisplay - LinesOnScreen() / 2 + 1, 0, MaxScrollPos()));
- SetVerticalScrollPos();
- Redraw();
- }
- }
- }
-}
-
-void Editor::FoldAll(int action) {
- pdoc->EnsureStyledTo(pdoc->Length());
- int maxLine = pdoc->LinesTotal();
- bool expanding = action == SC_FOLDACTION_EXPAND;
- if (action == SC_FOLDACTION_TOGGLE) {
- // Discover current state
- for (int lineSeek = 0; lineSeek < maxLine; lineSeek++) {
- if (pdoc->GetLevel(lineSeek) & SC_FOLDLEVELHEADERFLAG) {
- expanding = !cs.GetExpanded(lineSeek);
- break;
- }
- }
- }
- if (expanding) {
- cs.SetVisible(0, maxLine-1, true);
- for (int line = 0; line < maxLine; line++) {
- int levelLine = pdoc->GetLevel(line);
- if (levelLine & SC_FOLDLEVELHEADERFLAG) {
- SetFoldExpanded(line, true);
- }
- }
- } else {
- for (int line = 0; line < maxLine; line++) {
- int level = pdoc->GetLevel(line);
- if ((level & SC_FOLDLEVELHEADERFLAG) &&
- (SC_FOLDLEVELBASE == (level & SC_FOLDLEVELNUMBERMASK))) {
- SetFoldExpanded(line, false);
- int lineMaxSubord = pdoc->GetLastChild(line, -1);
- if (lineMaxSubord > line) {
- cs.SetVisible(line + 1, lineMaxSubord, false);
- }
- }
- }
- }
- SetScrollBars();
- Redraw();
-}
-
-void Editor::FoldChanged(int line, int levelNow, int levelPrev) {
- if (levelNow & SC_FOLDLEVELHEADERFLAG) {
- if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) {
- // Adding a fold point.
- if (cs.SetExpanded(line, true)) {
- RedrawSelMargin();
- }
- FoldExpand(line, SC_FOLDACTION_EXPAND, levelPrev);
- }
- } else if (levelPrev & SC_FOLDLEVELHEADERFLAG) {
- if (!cs.GetExpanded(line)) {
- // Removing the fold from one that has been contracted so should expand
- // otherwise lines are left invisible with no way to make them visible
- if (cs.SetExpanded(line, true)) {
- RedrawSelMargin();
- }
- FoldExpand(line, SC_FOLDACTION_EXPAND, levelPrev);
- }
- }
- if (!(levelNow & SC_FOLDLEVELWHITEFLAG) &&
- ((levelPrev & SC_FOLDLEVELNUMBERMASK) > (levelNow & SC_FOLDLEVELNUMBERMASK))) {
- if (cs.HiddenLines()) {
- // See if should still be hidden
- int parentLine = pdoc->GetFoldParent(line);
- if ((parentLine < 0) || (cs.GetExpanded(parentLine) && cs.GetVisible(parentLine))) {
- cs.SetVisible(line, line, true);
- SetScrollBars();
- Redraw();
- }
- }
- }
-}
-
-void Editor::NeedShown(int pos, int len) {
- if (foldAutomatic & SC_AUTOMATICFOLD_SHOW) {
- int lineStart = pdoc->LineFromPosition(pos);
- int lineEnd = pdoc->LineFromPosition(pos+len);
- for (int line = lineStart; line <= lineEnd; line++) {
- EnsureLineVisible(line, false);
- }
- } else {
- NotifyNeedShown(pos, len);
- }
-}
-
-int Editor::GetTag(char *tagValue, int tagNumber) {
- const char *text = 0;
- int length = 0;
- if ((tagNumber >= 1) && (tagNumber <= 9)) {
- char name[3] = "\\?";
- name[1] = static_cast<char>(tagNumber + '0');
- length = 2;
- text = pdoc->SubstituteByPosition(name, &length);
- }
- if (tagValue) {
- if (text)
- memcpy(tagValue, text, length + 1);
- else
- *tagValue = '\0';
- }
- return length;
-}
-
-int Editor::ReplaceTarget(bool replacePatterns, const char *text, int length) {
- UndoGroup ug(pdoc);
- if (length == -1)
- length = istrlen(text);
- if (replacePatterns) {
- text = pdoc->SubstituteByPosition(text, &length);
- if (!text) {
- return 0;
- }
- }
- if (targetStart != targetEnd)
- pdoc->DeleteChars(targetStart, targetEnd - targetStart);
- targetEnd = targetStart;
- pdoc->InsertString(targetStart, text, length);
- targetEnd = targetStart + length;
- return length;
-}
-
-bool Editor::IsUnicodeMode() const {
- return pdoc && (SC_CP_UTF8 == pdoc->dbcsCodePage);
-}
-
-int Editor::CodePage() const {
- if (pdoc)
- return pdoc->dbcsCodePage;
- else
- return 0;
-}
-
-int Editor::WrapCount(int line) {
- AutoSurface surface(this);
- AutoLineLayout ll(llc, RetrieveLineLayout(line));
-
- if (surface && ll) {
- LayoutLine(line, surface, vs, ll, wrapWidth);
- return ll->lines;
- } else {
- return 1;
- }
-}
-
-void Editor::AddStyledText(char *buffer, int appendLength) {
- // The buffer consists of alternating character bytes and style bytes
- int textLength = appendLength / 2;
- std::string text(textLength, '\0');
- int i;
- for (i = 0; i < textLength; i++) {
- text[i] = buffer[i*2];
- }
- pdoc->InsertString(CurrentPosition(), text.c_str(), textLength);
- for (i = 0; i < textLength; i++) {
- text[i] = buffer[i*2+1];
- }
- pdoc->StartStyling(CurrentPosition(), static_cast<char>(0xff));
- pdoc->SetStyles(textLength, text.c_str());
- SetEmptySelection(sel.MainCaret() + textLength);
-}
-
-static bool ValidMargin(unsigned long wParam) {
- return wParam <= SC_MAX_MARGIN;
-}
-
-static char *CharPtrFromSPtr(sptr_t lParam) {
- return reinterpret_cast<char *>(lParam);
-}
-
-void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
- vs.EnsureStyle(wParam);
- switch (iMessage) {
- case SCI_STYLESETFORE:
- vs.styles[wParam].fore = ColourDesired(lParam);
- break;
- case SCI_STYLESETBACK:
- vs.styles[wParam].back = ColourDesired(lParam);
- break;
- case SCI_STYLESETBOLD:
- vs.styles[wParam].weight = lParam != 0 ? SC_WEIGHT_BOLD : SC_WEIGHT_NORMAL;
- break;
- case SCI_STYLESETWEIGHT:
- vs.styles[wParam].weight = lParam;
- break;
- case SCI_STYLESETITALIC:
- vs.styles[wParam].italic = lParam != 0;
- break;
- case SCI_STYLESETEOLFILLED:
- vs.styles[wParam].eolFilled = lParam != 0;
- break;
- case SCI_STYLESETSIZE:
- vs.styles[wParam].size = lParam * SC_FONT_SIZE_MULTIPLIER;
- break;
- case SCI_STYLESETSIZEFRACTIONAL:
- vs.styles[wParam].size = lParam;
- break;
- case SCI_STYLESETFONT:
- if (lParam != 0) {
- vs.SetStyleFontName(wParam, CharPtrFromSPtr(lParam));
- }
- break;
- case SCI_STYLESETUNDERLINE:
- vs.styles[wParam].underline = lParam != 0;
- break;
- case SCI_STYLESETCASE:
- vs.styles[wParam].caseForce = static_cast<Style::ecaseForced>(lParam);
- break;
- case SCI_STYLESETCHARACTERSET:
- vs.styles[wParam].characterSet = lParam;
- pdoc->SetCaseFolder(NULL);
- break;
- case SCI_STYLESETVISIBLE:
- vs.styles[wParam].visible = lParam != 0;
- break;
- case SCI_STYLESETCHANGEABLE:
- vs.styles[wParam].changeable = lParam != 0;
- break;
- case SCI_STYLESETHOTSPOT:
- vs.styles[wParam].hotspot = lParam != 0;
- break;
- }
- InvalidateStyleRedraw();
-}
-
-sptr_t Editor::StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
- vs.EnsureStyle(wParam);
- switch (iMessage) {
- case SCI_STYLEGETFORE:
- return vs.styles[wParam].fore.AsLong();
- case SCI_STYLEGETBACK:
- return vs.styles[wParam].back.AsLong();
- case SCI_STYLEGETBOLD:
- return vs.styles[wParam].weight > SC_WEIGHT_NORMAL;
- case SCI_STYLEGETWEIGHT:
- return vs.styles[wParam].weight;
- case SCI_STYLEGETITALIC:
- return vs.styles[wParam].italic ? 1 : 0;
- case SCI_STYLEGETEOLFILLED:
- return vs.styles[wParam].eolFilled ? 1 : 0;
- case SCI_STYLEGETSIZE:
- return vs.styles[wParam].size / SC_FONT_SIZE_MULTIPLIER;
- case SCI_STYLEGETSIZEFRACTIONAL:
- return vs.styles[wParam].size;
- case SCI_STYLEGETFONT:
- if (!vs.styles[wParam].fontName)
- return 0;
- if (lParam != 0)
- strcpy(CharPtrFromSPtr(lParam), vs.styles[wParam].fontName);
- return strlen(vs.styles[wParam].fontName);
- case SCI_STYLEGETUNDERLINE:
- return vs.styles[wParam].underline ? 1 : 0;
- case SCI_STYLEGETCASE:
- return static_cast<int>(vs.styles[wParam].caseForce);
- case SCI_STYLEGETCHARACTERSET:
- return vs.styles[wParam].characterSet;
- case SCI_STYLEGETVISIBLE:
- return vs.styles[wParam].visible ? 1 : 0;
- case SCI_STYLEGETCHANGEABLE:
- return vs.styles[wParam].changeable ? 1 : 0;
- case SCI_STYLEGETHOTSPOT:
- return vs.styles[wParam].hotspot ? 1 : 0;
- }
- return 0;
-}
-
-sptr_t Editor::StringResult(sptr_t lParam, const char *val) {
- const size_t n = strlen(val);
- if (lParam != 0) {
- char *ptr = reinterpret_cast<char *>(lParam);
- strcpy(ptr, val);
- }
- return n; // Not including NUL
-}
-
-sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
- //Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam);
-
- // Optional macro recording hook
- if (recordingMacro)
- NotifyMacroRecord(iMessage, wParam, lParam);
-
- switch (iMessage) {
-
- case SCI_GETTEXT: {
- if (lParam == 0)
- return pdoc->Length() + 1;
- if (wParam == 0)
- return 0;
- char *ptr = CharPtrFromSPtr(lParam);
- unsigned int iChar = 0;
- for (; iChar < wParam - 1; iChar++)
- ptr[iChar] = pdoc->CharAt(iChar);
- ptr[iChar] = '\0';
- return iChar;
- }
-
- case SCI_SETTEXT: {
- if (lParam == 0)
- return 0;
- UndoGroup ug(pdoc);
- pdoc->DeleteChars(0, pdoc->Length());
- SetEmptySelection(0);
- pdoc->InsertCString(0, CharPtrFromSPtr(lParam));
- return 1;
- }
-
- case SCI_GETTEXTLENGTH:
- return pdoc->Length();
-
- case SCI_CUT:
- Cut();
- SetLastXChosen();
- break;
-
- case SCI_COPY:
- Copy();
- break;
-
- case SCI_COPYALLOWLINE:
- CopyAllowLine();
- break;
-
- case SCI_VERTICALCENTRECARET:
- VerticalCentreCaret();
- break;
-
- case SCI_MOVESELECTEDLINESUP:
- MoveSelectedLinesUp();
- break;
-
- case SCI_MOVESELECTEDLINESDOWN:
- MoveSelectedLinesDown();
- break;
-
- case SCI_COPYRANGE:
- CopyRangeToClipboard(wParam, lParam);
- break;
-
- case SCI_COPYTEXT:
- CopyText(wParam, CharPtrFromSPtr(lParam));
- break;
-
- case SCI_PASTE:
- Paste();
- if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) {
- SetLastXChosen();
- }
- EnsureCaretVisible();
- break;
-
- case SCI_CLEAR:
- Clear();
- SetLastXChosen();
- EnsureCaretVisible();
- break;
-
- case SCI_UNDO:
- Undo();
- SetLastXChosen();
- break;
-
- case SCI_CANUNDO:
- return (pdoc->CanUndo() && !pdoc->IsReadOnly()) ? 1 : 0;
-
- case SCI_EMPTYUNDOBUFFER:
- pdoc->DeleteUndoHistory();
- return 0;
-
- case SCI_GETFIRSTVISIBLELINE:
- return topLine;
-
- case SCI_SETFIRSTVISIBLELINE:
- ScrollTo(wParam);
- break;
-
- case SCI_GETLINE: { // Risk of overwriting the end of the buffer
- int lineStart = pdoc->LineStart(wParam);
- int lineEnd = pdoc->LineStart(wParam + 1);
- if (lParam == 0) {
- return lineEnd - lineStart;
- }
- char *ptr = CharPtrFromSPtr(lParam);
- int iPlace = 0;
- for (int iChar = lineStart; iChar < lineEnd; iChar++) {
- ptr[iPlace++] = pdoc->CharAt(iChar);
- }
- return iPlace;
- }
-
- case SCI_GETLINECOUNT:
- if (pdoc->LinesTotal() == 0)
- return 1;
- else
- return pdoc->LinesTotal();
-
- case SCI_GETMODIFY:
- return !pdoc->IsSavePoint();
-
- case SCI_SETSEL: {
- int nStart = static_cast<int>(wParam);
- int nEnd = static_cast<int>(lParam);
- if (nEnd < 0)
- nEnd = pdoc->Length();
- if (nStart < 0)
- nStart = nEnd; // Remove selection
- InvalidateSelection(SelectionRange(nStart, nEnd));
- sel.Clear();
- sel.selType = Selection::selStream;
- SetSelection(nEnd, nStart);
- EnsureCaretVisible();
- }
- break;
-
- case SCI_GETSELTEXT: {
- SelectionText selectedText;
- CopySelectionRange(&selectedText);
- if (lParam == 0) {
- return selectedText.LengthWithTerminator();
- } else {
- char *ptr = CharPtrFromSPtr(lParam);
- unsigned int iChar = 0;
- if (selectedText.Length()) {
- for (; iChar < selectedText.LengthWithTerminator(); iChar++)
- ptr[iChar] = selectedText.Data()[iChar];
- } else {
- ptr[0] = '\0';
- }
- return iChar;
- }
- }
-
- case SCI_LINEFROMPOSITION:
- if (static_cast<int>(wParam) < 0)
- return 0;
- return pdoc->LineFromPosition(wParam);
-
- case SCI_POSITIONFROMLINE:
- if (static_cast<int>(wParam) < 0)
- wParam = pdoc->LineFromPosition(SelectionStart().Position());
- if (wParam == 0)
- return 0; // Even if there is no text, there is a first line that starts at 0
- if (static_cast<int>(wParam) > pdoc->LinesTotal())
- return -1;
- //if (wParam > pdoc->LineFromPosition(pdoc->Length())) // Useful test, anyway...
- // return -1;
- return pdoc->LineStart(wParam);
-
- // Replacement of the old Scintilla interpretation of EM_LINELENGTH
- case SCI_LINELENGTH:
- if ((static_cast<int>(wParam) < 0) ||
- (static_cast<int>(wParam) > pdoc->LineFromPosition(pdoc->Length())))
- return 0;
- return pdoc->LineStart(wParam + 1) - pdoc->LineStart(wParam);
-
- case SCI_REPLACESEL: {
- if (lParam == 0)
- return 0;
- UndoGroup ug(pdoc);
- ClearSelection();
- char *replacement = CharPtrFromSPtr(lParam);
- pdoc->InsertCString(sel.MainCaret(), replacement);
- SetEmptySelection(sel.MainCaret() + istrlen(replacement));
- EnsureCaretVisible();
- }
- break;
-
- case SCI_SETTARGETSTART:
- targetStart = wParam;
- break;
-
- case SCI_GETTARGETSTART:
- return targetStart;
-
- case SCI_SETTARGETEND:
- targetEnd = wParam;
- break;
-
- case SCI_GETTARGETEND:
- return targetEnd;
-
- case SCI_TARGETFROMSELECTION:
- if (sel.MainCaret() < sel.MainAnchor()) {
- targetStart = sel.MainCaret();
- targetEnd = sel.MainAnchor();
- } else {
- targetStart = sel.MainAnchor();
- targetEnd = sel.MainCaret();
- }
- break;
-
- case SCI_REPLACETARGET:
- PLATFORM_ASSERT(lParam);
- return ReplaceTarget(false, CharPtrFromSPtr(lParam), wParam);
-
- case SCI_REPLACETARGETRE:
- PLATFORM_ASSERT(lParam);
- return ReplaceTarget(true, CharPtrFromSPtr(lParam), wParam);
-
- case SCI_SEARCHINTARGET:
- PLATFORM_ASSERT(lParam);
- return SearchInTarget(CharPtrFromSPtr(lParam), wParam);
-
- case SCI_SETSEARCHFLAGS:
- searchFlags = wParam;
- break;
-
- case SCI_GETSEARCHFLAGS:
- return searchFlags;
-
- case SCI_GETTAG:
- return GetTag(CharPtrFromSPtr(lParam), wParam);
-
- case SCI_POSITIONBEFORE:
- return pdoc->MovePositionOutsideChar(wParam - 1, -1, true);
-
- case SCI_POSITIONAFTER:
- return pdoc->MovePositionOutsideChar(wParam + 1, 1, true);
-
- case SCI_POSITIONRELATIVE:
- return Platform::Clamp(pdoc->GetRelativePosition(wParam, lParam), 0, pdoc->Length());
-
- case SCI_LINESCROLL:
- ScrollTo(topLine + lParam);
- HorizontalScrollTo(xOffset + static_cast<int>(wParam) * vs.spaceWidth);
- return 1;
-
- case SCI_SETXOFFSET:
- xOffset = wParam;
- ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
- SetHorizontalScrollPos();
- Redraw();
- break;
-
- case SCI_GETXOFFSET:
- return xOffset;
-
- case SCI_CHOOSECARETX:
- SetLastXChosen();
- break;
-
- case SCI_SCROLLCARET:
- EnsureCaretVisible();
- break;
-
- case SCI_SETREADONLY:
- pdoc->SetReadOnly(wParam != 0);
- return 1;
-
- case SCI_GETREADONLY:
- return pdoc->IsReadOnly();
-
- case SCI_CANPASTE:
- return CanPaste();
-
- case SCI_POINTXFROMPOSITION:
- if (lParam < 0) {
- return 0;
- } else {
- Point pt = LocationFromPosition(lParam);
- // Convert to view-relative
- return pt.x - vs.textStart + vs.fixedColumnWidth;
- }
-
- case SCI_POINTYFROMPOSITION:
- if (lParam < 0) {
- return 0;
- } else {
- Point pt = LocationFromPosition(lParam);
- return pt.y;
- }
-
- case SCI_FINDTEXT:
- return FindText(wParam, lParam);
-
- case SCI_GETTEXTRANGE: {
- if (lParam == 0)
- return 0;
- Sci_TextRange *tr = reinterpret_cast<Sci_TextRange *>(lParam);
- int cpMax = tr->chrg.cpMax;
- if (cpMax == -1)
- cpMax = pdoc->Length();
- PLATFORM_ASSERT(cpMax <= pdoc->Length());
- int len = cpMax - tr->chrg.cpMin; // No -1 as cpMin and cpMax are referring to inter character positions
- pdoc->GetCharRange(tr->lpstrText, tr->chrg.cpMin, len);
- // Spec says copied text is terminated with a NUL
- tr->lpstrText[len] = '\0';
- return len; // Not including NUL
- }
-
- case SCI_HIDESELECTION:
- hideSelection = wParam != 0;
- Redraw();
- break;
-
- case SCI_FORMATRANGE:
- return FormatRange(wParam != 0, reinterpret_cast<Sci_RangeToFormat *>(lParam));
-
- case SCI_GETMARGINLEFT:
- return vs.leftMarginWidth;
-
- case SCI_GETMARGINRIGHT:
- return vs.rightMarginWidth;
-
- case SCI_SETMARGINLEFT:
- lastXChosen += lParam - vs.leftMarginWidth;
- vs.leftMarginWidth = lParam;
- InvalidateStyleRedraw();
- break;
-
- case SCI_SETMARGINRIGHT:
- vs.rightMarginWidth = lParam;
- InvalidateStyleRedraw();
- break;
-
- // Control specific mesages
-
- case SCI_ADDTEXT: {
- if (lParam == 0)
- return 0;
- pdoc->InsertString(CurrentPosition(), CharPtrFromSPtr(lParam), wParam);
- SetEmptySelection(sel.MainCaret() + wParam);
- return 0;
- }
-
- case SCI_ADDSTYLEDTEXT:
- if (lParam)
- AddStyledText(CharPtrFromSPtr(lParam), wParam);
- return 0;
-
- case SCI_INSERTTEXT: {
- if (lParam == 0)
- return 0;
- int insertPos = wParam;
- if (static_cast<int>(wParam) == -1)
- insertPos = CurrentPosition();
- int newCurrent = CurrentPosition();
- char *sz = CharPtrFromSPtr(lParam);
- pdoc->InsertCString(insertPos, sz);
- if (newCurrent > insertPos)
- newCurrent += istrlen(sz);
- SetEmptySelection(newCurrent);
- return 0;
- }
-
- case SCI_APPENDTEXT:
- pdoc->InsertString(pdoc->Length(), CharPtrFromSPtr(lParam), wParam);
- return 0;
-
- case SCI_CLEARALL:
- ClearAll();
- return 0;
-
- case SCI_DELETERANGE:
- pdoc->DeleteChars(wParam, lParam);
- return 0;
-
- case SCI_CLEARDOCUMENTSTYLE:
- ClearDocumentStyle();
- return 0;
-
- case SCI_SETUNDOCOLLECTION:
- pdoc->SetUndoCollection(wParam != 0);
- return 0;
-
- case SCI_GETUNDOCOLLECTION:
- return pdoc->IsCollectingUndo();
-
- case SCI_BEGINUNDOACTION:
- pdoc->BeginUndoAction();
- return 0;
-
- case SCI_ENDUNDOACTION:
- pdoc->EndUndoAction();
- return 0;
-
- case SCI_GETCARETPERIOD:
- return caret.period;
-
- case SCI_SETCARETPERIOD:
- caret.period = wParam;
- break;
-
- case SCI_GETWORDCHARS:
- return pdoc->GetCharsOfClass(CharClassify::ccWord, reinterpret_cast<unsigned char *>(lParam));
-
- case SCI_SETWORDCHARS: {
- pdoc->SetDefaultCharClasses(false);
- if (lParam == 0)
- return 0;
- pdoc->SetCharClasses(reinterpret_cast<unsigned char *>(lParam), CharClassify::ccWord);
- }
- break;
-
- case SCI_GETWHITESPACECHARS:
- return pdoc->GetCharsOfClass(CharClassify::ccSpace, reinterpret_cast<unsigned char *>(lParam));
-
- case SCI_SETWHITESPACECHARS: {
- if (lParam == 0)
- return 0;
- pdoc->SetCharClasses(reinterpret_cast<unsigned char *>(lParam), CharClassify::ccSpace);
- }
- break;
-
- case SCI_GETPUNCTUATIONCHARS:
- return pdoc->GetCharsOfClass(CharClassify::ccPunctuation, reinterpret_cast<unsigned char *>(lParam));
-
- case SCI_SETPUNCTUATIONCHARS: {
- if (lParam == 0)
- return 0;
- pdoc->SetCharClasses(reinterpret_cast<unsigned char *>(lParam), CharClassify::ccPunctuation);
- }
- break;
-
- case SCI_SETCHARSDEFAULT:
- pdoc->SetDefaultCharClasses(true);
- break;
-
- case SCI_GETLENGTH:
- return pdoc->Length();
-
- case SCI_ALLOCATE:
- pdoc->Allocate(wParam);
- break;
-
- case SCI_GETCHARAT:
- return pdoc->CharAt(wParam);
-
- case SCI_SETCURRENTPOS:
- if (sel.IsRectangular()) {
- sel.Rectangular().caret.SetPosition(wParam);
- SetRectangularRange();
- Redraw();
- } else {
- SetSelection(wParam, sel.MainAnchor());
- }
- break;
-
- case SCI_GETCURRENTPOS:
- return sel.IsRectangular() ? sel.Rectangular().caret.Position() : sel.MainCaret();
-
- case SCI_SETANCHOR:
- if (sel.IsRectangular()) {
- sel.Rectangular().anchor.SetPosition(wParam);
- SetRectangularRange();
- Redraw();
- } else {
- SetSelection(sel.MainCaret(), wParam);
- }
- break;
-
- case SCI_GETANCHOR:
- return sel.IsRectangular() ? sel.Rectangular().anchor.Position() : sel.MainAnchor();
-
- case SCI_SETSELECTIONSTART:
- SetSelection(Platform::Maximum(sel.MainCaret(), wParam), wParam);
- break;
-
- case SCI_GETSELECTIONSTART:
- return sel.LimitsForRectangularElseMain().start.Position();
-
- case SCI_SETSELECTIONEND:
- SetSelection(wParam, Platform::Minimum(sel.MainAnchor(), wParam));
- break;
-
- case SCI_GETSELECTIONEND:
- return sel.LimitsForRectangularElseMain().end.Position();
-
- case SCI_SETEMPTYSELECTION:
- SetEmptySelection(wParam);
- break;
-
- case SCI_SETPRINTMAGNIFICATION:
- printParameters.magnification = wParam;
- break;
-
- case SCI_GETPRINTMAGNIFICATION:
- return printParameters.magnification;
-
- case SCI_SETPRINTCOLOURMODE:
- printParameters.colourMode = wParam;
- break;
-
- case SCI_GETPRINTCOLOURMODE:
- return printParameters.colourMode;
-
- case SCI_SETPRINTWRAPMODE:
- printParameters.wrapState = (wParam == SC_WRAP_WORD) ? eWrapWord : eWrapNone;
- break;
-
- case SCI_GETPRINTWRAPMODE:
- return printParameters.wrapState;
-
- case SCI_GETSTYLEAT:
- if (static_cast<int>(wParam) >= pdoc->Length())
- return 0;
- else
- return pdoc->StyleAt(wParam);
-
- case SCI_REDO:
- Redo();
- break;
-
- case SCI_SELECTALL:
- SelectAll();
- break;
-
- case SCI_SETSAVEPOINT:
- pdoc->SetSavePoint();
- break;
-
- case SCI_GETSTYLEDTEXT: {
- if (lParam == 0)
- return 0;
- Sci_TextRange *tr = reinterpret_cast<Sci_TextRange *>(lParam);
- int iPlace = 0;
- for (int iChar = tr->chrg.cpMin; iChar < tr->chrg.cpMax; iChar++) {
- tr->lpstrText[iPlace++] = pdoc->CharAt(iChar);
- tr->lpstrText[iPlace++] = pdoc->StyleAt(iChar);
- }
- tr->lpstrText[iPlace] = '\0';
- tr->lpstrText[iPlace + 1] = '\0';
- return iPlace;
- }
-
- case SCI_CANREDO:
- return (pdoc->CanRedo() && !pdoc->IsReadOnly()) ? 1 : 0;
-
- case SCI_MARKERLINEFROMHANDLE:
- return pdoc->LineFromHandle(wParam);
-
- case SCI_MARKERDELETEHANDLE:
- pdoc->DeleteMarkFromHandle(wParam);
- break;
-
- case SCI_GETVIEWWS:
- return vs.viewWhitespace;
-
- case SCI_SETVIEWWS:
- vs.viewWhitespace = static_cast<WhiteSpaceVisibility>(wParam);
- Redraw();
- break;
-
- case SCI_GETWHITESPACESIZE:
- return vs.whitespaceSize;
-
- case SCI_SETWHITESPACESIZE:
- vs.whitespaceSize = static_cast<int>(wParam);
- Redraw();
- break;
-
- case SCI_POSITIONFROMPOINT:
- return PositionFromLocation(Point(wParam - vs.ExternalMarginWidth(), lParam),
- false, false);
-
- case SCI_POSITIONFROMPOINTCLOSE:
- return PositionFromLocation(Point(wParam - vs.ExternalMarginWidth(), lParam),
- true, false);
-
- case SCI_CHARPOSITIONFROMPOINT:
- return PositionFromLocation(Point(wParam - vs.ExternalMarginWidth(), lParam),
- false, true);
-
- case SCI_CHARPOSITIONFROMPOINTCLOSE:
- return PositionFromLocation(Point(wParam - vs.ExternalMarginWidth(), lParam),
- true, true);
-
- case SCI_GOTOLINE:
- GoToLine(wParam);
- break;
-
- case SCI_GOTOPOS:
- SetEmptySelection(wParam);
- EnsureCaretVisible();
- break;
-
- case SCI_GETCURLINE: {
- int lineCurrentPos = pdoc->LineFromPosition(sel.MainCaret());
- int lineStart = pdoc->LineStart(lineCurrentPos);
- unsigned int lineEnd = pdoc->LineStart(lineCurrentPos + 1);
- if (lParam == 0) {
- return 1 + lineEnd - lineStart;
- }
- PLATFORM_ASSERT(wParam > 0);
- char *ptr = CharPtrFromSPtr(lParam);
- unsigned int iPlace = 0;
- for (unsigned int iChar = lineStart; iChar < lineEnd && iPlace < wParam - 1; iChar++) {
- ptr[iPlace++] = pdoc->CharAt(iChar);
- }
- ptr[iPlace] = '\0';
- return sel.MainCaret() - lineStart;
- }
-
- case SCI_GETENDSTYLED:
- return pdoc->GetEndStyled();
-
- case SCI_GETEOLMODE:
- return pdoc->eolMode;
-
- case SCI_SETEOLMODE:
- pdoc->eolMode = wParam;
- break;
-
- case SCI_SETLINEENDTYPESALLOWED:
- if (pdoc->SetLineEndTypesAllowed(wParam)) {
- cs.Clear();
- cs.InsertLines(0, pdoc->LinesTotal() - 1);
- SetAnnotationHeights(0, pdoc->LinesTotal());
- InvalidateStyleRedraw();
- }
- break;
-
- case SCI_GETLINEENDTYPESALLOWED:
- return pdoc->GetLineEndTypesAllowed();
-
- case SCI_GETLINEENDTYPESACTIVE:
- return pdoc->GetLineEndTypesActive();
-
- case SCI_STARTSTYLING:
- pdoc->StartStyling(wParam, static_cast<char>(lParam));
- break;
-
- case SCI_SETSTYLING:
- pdoc->SetStyleFor(wParam, static_cast<char>(lParam));
- break;
-
- case SCI_SETSTYLINGEX: // Specify a complete styling buffer
- if (lParam == 0)
- return 0;
- pdoc->SetStyles(wParam, CharPtrFromSPtr(lParam));
- break;
-
- case SCI_SETBUFFEREDDRAW:
- bufferedDraw = wParam != 0;
- break;
-
- case SCI_GETBUFFEREDDRAW:
- return bufferedDraw;
-
- case SCI_GETTWOPHASEDRAW:
- return twoPhaseDraw;
-
- case SCI_SETTWOPHASEDRAW:
- twoPhaseDraw = wParam != 0;
- InvalidateStyleRedraw();
- break;
-
- case SCI_SETFONTQUALITY:
- vs.extraFontFlag &= ~SC_EFF_QUALITY_MASK;
- vs.extraFontFlag |= (wParam & SC_EFF_QUALITY_MASK);
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETFONTQUALITY:
- return (vs.extraFontFlag & SC_EFF_QUALITY_MASK);
-
- case SCI_SETTABWIDTH:
- if (wParam > 0) {
- pdoc->tabInChars = wParam;
- if (pdoc->indentInChars == 0)
- pdoc->actualIndentInChars = pdoc->tabInChars;
- }
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETTABWIDTH:
- return pdoc->tabInChars;
-
- case SCI_SETINDENT:
- pdoc->indentInChars = wParam;
- if (pdoc->indentInChars != 0)
- pdoc->actualIndentInChars = pdoc->indentInChars;
- else
- pdoc->actualIndentInChars = pdoc->tabInChars;
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETINDENT:
- return pdoc->indentInChars;
-
- case SCI_SETUSETABS:
- pdoc->useTabs = wParam != 0;
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETUSETABS:
- return pdoc->useTabs;
-
- case SCI_SETLINEINDENTATION:
- pdoc->SetLineIndentation(wParam, lParam);
- break;
-
- case SCI_GETLINEINDENTATION:
- return pdoc->GetLineIndentation(wParam);
-
- case SCI_GETLINEINDENTPOSITION:
- return pdoc->GetLineIndentPosition(wParam);
-
- case SCI_SETTABINDENTS:
- pdoc->tabIndents = wParam != 0;
- break;
-
- case SCI_GETTABINDENTS:
- return pdoc->tabIndents;
-
- case SCI_SETBACKSPACEUNINDENTS:
- pdoc->backspaceUnindents = wParam != 0;
- break;
-
- case SCI_GETBACKSPACEUNINDENTS:
- return pdoc->backspaceUnindents;
-
- case SCI_SETMOUSEDWELLTIME:
- dwellDelay = wParam;
- ticksToDwell = dwellDelay;
- break;
-
- case SCI_GETMOUSEDWELLTIME:
- return dwellDelay;
-
- case SCI_WORDSTARTPOSITION:
- return pdoc->ExtendWordSelect(wParam, -1, lParam != 0);
-
- case SCI_WORDENDPOSITION:
- return pdoc->ExtendWordSelect(wParam, 1, lParam != 0);
-
- case SCI_SETWRAPMODE:
- if (vs.SetWrapState(wParam)) {
- xOffset = 0;
- ContainerNeedsUpdate(SC_UPDATE_H_SCROLL);
- InvalidateStyleRedraw();
- ReconfigureScrollBars();
- }
- break;
-
- case SCI_GETWRAPMODE:
- return vs.wrapState;
-
- case SCI_SETWRAPVISUALFLAGS:
- if (vs.SetWrapVisualFlags(wParam)) {
- InvalidateStyleRedraw();
- ReconfigureScrollBars();
- }
- break;
-
- case SCI_GETWRAPVISUALFLAGS:
- return vs.wrapVisualFlags;
-
- case SCI_SETWRAPVISUALFLAGSLOCATION:
- if (vs.SetWrapVisualFlagsLocation(wParam)) {
- InvalidateStyleRedraw();
- }
- break;
-
- case SCI_GETWRAPVISUALFLAGSLOCATION:
- return vs.wrapVisualFlagsLocation;
-
- case SCI_SETWRAPSTARTINDENT:
- if (vs.SetWrapVisualStartIndent(wParam)) {
- InvalidateStyleRedraw();
- ReconfigureScrollBars();
- }
- break;
-
- case SCI_GETWRAPSTARTINDENT:
- return vs.wrapVisualStartIndent;
-
- case SCI_SETWRAPINDENTMODE:
- if (vs.SetWrapIndentMode(wParam)) {
- InvalidateStyleRedraw();
- ReconfigureScrollBars();
- }
- break;
-
- case SCI_GETWRAPINDENTMODE:
- return vs.wrapIndentMode;
-
- case SCI_SETLAYOUTCACHE:
- llc.SetLevel(wParam);
- break;
-
- case SCI_GETLAYOUTCACHE:
- return llc.GetLevel();
-
- case SCI_SETPOSITIONCACHE:
- posCache.SetSize(wParam);
- break;
-
- case SCI_GETPOSITIONCACHE:
- return posCache.GetSize();
-
- case SCI_SETSCROLLWIDTH:
- PLATFORM_ASSERT(wParam > 0);
- if ((wParam > 0) && (wParam != static_cast<unsigned int >(scrollWidth))) {
- lineWidthMaxSeen = 0;
- scrollWidth = wParam;
- SetScrollBars();
- }
- break;
-
- case SCI_GETSCROLLWIDTH:
- return scrollWidth;
-
- case SCI_SETSCROLLWIDTHTRACKING:
- trackLineWidth = wParam != 0;
- break;
-
- case SCI_GETSCROLLWIDTHTRACKING:
- return trackLineWidth;
-
- case SCI_LINESJOIN:
- LinesJoin();
- break;
-
- case SCI_LINESSPLIT:
- LinesSplit(wParam);
- break;
-
- case SCI_TEXTWIDTH:
- PLATFORM_ASSERT(wParam < vs.styles.size());
- PLATFORM_ASSERT(lParam);
- return TextWidth(wParam, CharPtrFromSPtr(lParam));
-
- case SCI_TEXTHEIGHT:
- return vs.lineHeight;
-
- case SCI_SETENDATLASTLINE:
- PLATFORM_ASSERT((wParam == 0) || (wParam == 1));
- if (endAtLastLine != (wParam != 0)) {
- endAtLastLine = wParam != 0;
- SetScrollBars();
- }
- break;
-
- case SCI_GETENDATLASTLINE:
- return endAtLastLine;
-
- case SCI_SETCARETSTICKY:
- PLATFORM_ASSERT(wParam <= SC_CARETSTICKY_WHITESPACE);
- if (wParam <= SC_CARETSTICKY_WHITESPACE) {
- caretSticky = wParam;
- }
- break;
-
- case SCI_GETCARETSTICKY:
- return caretSticky;
-
- case SCI_TOGGLECARETSTICKY:
- caretSticky = !caretSticky;
- break;
-
- case SCI_GETCOLUMN:
- return pdoc->GetColumn(wParam);
-
- case SCI_FINDCOLUMN:
- return pdoc->FindColumn(wParam, lParam);
-
- case SCI_SETHSCROLLBAR :
- if (horizontalScrollBarVisible != (wParam != 0)) {
- horizontalScrollBarVisible = wParam != 0;
- SetScrollBars();
- ReconfigureScrollBars();
- }
- break;
-
- case SCI_GETHSCROLLBAR:
- return horizontalScrollBarVisible;
-
- case SCI_SETVSCROLLBAR:
- if (verticalScrollBarVisible != (wParam != 0)) {
- verticalScrollBarVisible = wParam != 0;
- SetScrollBars();
- ReconfigureScrollBars();
- if (verticalScrollBarVisible)
- SetVerticalScrollPos();
- }
- break;
-
- case SCI_GETVSCROLLBAR:
- return verticalScrollBarVisible;
-
- case SCI_SETINDENTATIONGUIDES:
- vs.viewIndentationGuides = IndentView(wParam);
- Redraw();
- break;
-
- case SCI_GETINDENTATIONGUIDES:
- return vs.viewIndentationGuides;
-
- case SCI_SETHIGHLIGHTGUIDE:
- if ((highlightGuideColumn != static_cast<int>(wParam)) || (wParam > 0)) {
- highlightGuideColumn = wParam;
- Redraw();
- }
- break;
-
- case SCI_GETHIGHLIGHTGUIDE:
- return highlightGuideColumn;
-
- case SCI_GETLINEENDPOSITION:
- return pdoc->LineEnd(wParam);
-
- case SCI_SETCODEPAGE:
- if (ValidCodePage(wParam)) {
- if (pdoc->SetDBCSCodePage(wParam)) {
- cs.Clear();
- cs.InsertLines(0, pdoc->LinesTotal() - 1);
- SetAnnotationHeights(0, pdoc->LinesTotal());
- InvalidateStyleRedraw();
- SetRepresentations();
- }
- }
- break;
-
- case SCI_GETCODEPAGE:
- return pdoc->dbcsCodePage;
-
-#ifdef INCLUDE_DEPRECATED_FEATURES
- case SCI_SETUSEPALETTE:
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETUSEPALETTE:
- return 0;
-#endif
-
- // Marker definition and setting
- case SCI_MARKERDEFINE:
- if (wParam <= MARKER_MAX) {
- vs.markers[wParam].markType = lParam;
- vs.CalcLargestMarkerHeight();
- }
- InvalidateStyleData();
- RedrawSelMargin();
- break;
-
- case SCI_MARKERSYMBOLDEFINED:
- if (wParam <= MARKER_MAX)
- return vs.markers[wParam].markType;
- else
- return 0;
-
- case SCI_MARKERSETFORE:
- if (wParam <= MARKER_MAX)
- vs.markers[wParam].fore = ColourDesired(lParam);
- InvalidateStyleData();
- RedrawSelMargin();
- break;
- case SCI_MARKERSETBACKSELECTED:
- if (wParam <= MARKER_MAX)
- vs.markers[wParam].backSelected = ColourDesired(lParam);
- InvalidateStyleData();
- RedrawSelMargin();
- break;
- case SCI_MARKERENABLEHIGHLIGHT:
- highlightDelimiter.isEnabled = wParam == 1;
- RedrawSelMargin();
- break;
- case SCI_MARKERSETBACK:
- if (wParam <= MARKER_MAX)
- vs.markers[wParam].back = ColourDesired(lParam);
- InvalidateStyleData();
- RedrawSelMargin();
- break;
- case SCI_MARKERSETALPHA:
- if (wParam <= MARKER_MAX)
- vs.markers[wParam].alpha = lParam;
- InvalidateStyleRedraw();
- break;
- case SCI_MARKERADD: {
- int markerID = pdoc->AddMark(wParam, lParam);
- return markerID;
- }
- case SCI_MARKERADDSET:
- if (lParam != 0)
- pdoc->AddMarkSet(wParam, lParam);
- break;
-
- case SCI_MARKERDELETE:
- pdoc->DeleteMark(wParam, lParam);
- break;
-
- case SCI_MARKERDELETEALL:
- pdoc->DeleteAllMarks(static_cast<int>(wParam));
- break;
-
- case SCI_MARKERGET:
- return pdoc->GetMark(wParam);
-
- case SCI_MARKERNEXT:
- return pdoc->MarkerNext(wParam, lParam);
-
- case SCI_MARKERPREVIOUS: {
- for (int iLine = wParam; iLine >= 0; iLine--) {
- if ((pdoc->GetMark(iLine) & lParam) != 0)
- return iLine;
- }
- }
- return -1;
-
- case SCI_MARKERDEFINEPIXMAP:
- if (wParam <= MARKER_MAX) {
- vs.markers[wParam].SetXPM(CharPtrFromSPtr(lParam));
- vs.CalcLargestMarkerHeight();
- };
- InvalidateStyleData();
- RedrawSelMargin();
- break;
-
- case SCI_RGBAIMAGESETWIDTH:
- sizeRGBAImage.x = wParam;
- break;
-
- case SCI_RGBAIMAGESETHEIGHT:
- sizeRGBAImage.y = wParam;
- break;
-
- case SCI_RGBAIMAGESETSCALE:
- scaleRGBAImage = wParam;
- break;
-
- case SCI_MARKERDEFINERGBAIMAGE:
- if (wParam <= MARKER_MAX) {
- vs.markers[wParam].SetRGBAImage(sizeRGBAImage, scaleRGBAImage / 100.0, reinterpret_cast<unsigned char *>(lParam));
- vs.CalcLargestMarkerHeight();
- };
- InvalidateStyleData();
- RedrawSelMargin();
- break;
-
- case SCI_SETMARGINTYPEN:
- if (ValidMargin(wParam)) {
- vs.ms[wParam].style = lParam;
- InvalidateStyleRedraw();
- }
- break;
-
- case SCI_GETMARGINTYPEN:
- if (ValidMargin(wParam))
- return vs.ms[wParam].style;
- else
- return 0;
-
- case SCI_SETMARGINWIDTHN:
- if (ValidMargin(wParam)) {
- // Short-circuit if the width is unchanged, to avoid unnecessary redraw.
- if (vs.ms[wParam].width != lParam) {
- lastXChosen += lParam - vs.ms[wParam].width;
- vs.ms[wParam].width = lParam;
- InvalidateStyleRedraw();
- }
- }
- break;
-
- case SCI_GETMARGINWIDTHN:
- if (ValidMargin(wParam))
- return vs.ms[wParam].width;
- else
- return 0;
-
- case SCI_SETMARGINMASKN:
- if (ValidMargin(wParam)) {
- vs.ms[wParam].mask = lParam;
- InvalidateStyleRedraw();
- }
- break;
-
- case SCI_GETMARGINMASKN:
- if (ValidMargin(wParam))
- return vs.ms[wParam].mask;
- else
- return 0;
-
- case SCI_SETMARGINSENSITIVEN:
- if (ValidMargin(wParam)) {
- vs.ms[wParam].sensitive = lParam != 0;
- InvalidateStyleRedraw();
- }
- break;
-
- case SCI_GETMARGINSENSITIVEN:
- if (ValidMargin(wParam))
- return vs.ms[wParam].sensitive ? 1 : 0;
- else
- return 0;
-
- case SCI_SETMARGINCURSORN:
- if (ValidMargin(wParam))
- vs.ms[wParam].cursor = lParam;
- break;
-
- case SCI_GETMARGINCURSORN:
- if (ValidMargin(wParam))
- return vs.ms[wParam].cursor;
- else
- return 0;
-
- case SCI_STYLECLEARALL:
- vs.ClearStyles();
- InvalidateStyleRedraw();
- break;
-
- case SCI_STYLESETFORE:
- case SCI_STYLESETBACK:
- case SCI_STYLESETBOLD:
- case SCI_STYLESETWEIGHT:
- case SCI_STYLESETITALIC:
- case SCI_STYLESETEOLFILLED:
- case SCI_STYLESETSIZE:
- case SCI_STYLESETSIZEFRACTIONAL:
- case SCI_STYLESETFONT:
- case SCI_STYLESETUNDERLINE:
- case SCI_STYLESETCASE:
- case SCI_STYLESETCHARACTERSET:
- case SCI_STYLESETVISIBLE:
- case SCI_STYLESETCHANGEABLE:
- case SCI_STYLESETHOTSPOT:
- StyleSetMessage(iMessage, wParam, lParam);
- break;
-
- case SCI_STYLEGETFORE:
- case SCI_STYLEGETBACK:
- case SCI_STYLEGETBOLD:
- case SCI_STYLEGETWEIGHT:
- case SCI_STYLEGETITALIC:
- case SCI_STYLEGETEOLFILLED:
- case SCI_STYLEGETSIZE:
- case SCI_STYLEGETSIZEFRACTIONAL:
- case SCI_STYLEGETFONT:
- case SCI_STYLEGETUNDERLINE:
- case SCI_STYLEGETCASE:
- case SCI_STYLEGETCHARACTERSET:
- case SCI_STYLEGETVISIBLE:
- case SCI_STYLEGETCHANGEABLE:
- case SCI_STYLEGETHOTSPOT:
- return StyleGetMessage(iMessage, wParam, lParam);
-
- case SCI_STYLERESETDEFAULT:
- vs.ResetDefaultStyle();
- InvalidateStyleRedraw();
- break;
- case SCI_SETSTYLEBITS:
- vs.EnsureStyle((1 << wParam) - 1);
- pdoc->SetStylingBits(wParam);
- break;
-
- case SCI_GETSTYLEBITS:
- return pdoc->stylingBits;
-
- case SCI_SETLINESTATE:
- return pdoc->SetLineState(wParam, lParam);
-
- case SCI_GETLINESTATE:
- return pdoc->GetLineState(wParam);
-
- case SCI_GETMAXLINESTATE:
- return pdoc->GetMaxLineState();
-
- case SCI_GETCARETLINEVISIBLE:
- return vs.showCaretLineBackground;
- case SCI_SETCARETLINEVISIBLE:
- vs.showCaretLineBackground = wParam != 0;
- InvalidateStyleRedraw();
- break;
- case SCI_GETCARETLINEVISIBLEALWAYS:
- return vs.alwaysShowCaretLineBackground;
- case SCI_SETCARETLINEVISIBLEALWAYS:
- vs.alwaysShowCaretLineBackground = wParam != 0;
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETCARETLINEBACK:
- return vs.caretLineBackground.AsLong();
- case SCI_SETCARETLINEBACK:
- vs.caretLineBackground = wParam;
- InvalidateStyleRedraw();
- break;
- case SCI_GETCARETLINEBACKALPHA:
- return vs.caretLineAlpha;
- case SCI_SETCARETLINEBACKALPHA:
- vs.caretLineAlpha = wParam;
- InvalidateStyleRedraw();
- break;
-
- // Folding messages
-
- case SCI_VISIBLEFROMDOCLINE:
- return cs.DisplayFromDoc(wParam);
-
- case SCI_DOCLINEFROMVISIBLE:
- return cs.DocFromDisplay(wParam);
-
- case SCI_WRAPCOUNT:
- return WrapCount(wParam);
-
- case SCI_SETFOLDLEVEL: {
- int prev = pdoc->SetLevel(wParam, lParam);
- if (prev != lParam)
- RedrawSelMargin();
- return prev;
- }
-
- case SCI_GETFOLDLEVEL:
- return pdoc->GetLevel(wParam);
-
- case SCI_GETLASTCHILD:
- return pdoc->GetLastChild(wParam, lParam);
-
- case SCI_GETFOLDPARENT:
- return pdoc->GetFoldParent(wParam);
-
- case SCI_SHOWLINES:
- cs.SetVisible(wParam, lParam, true);
- SetScrollBars();
- Redraw();
- break;
-
- case SCI_HIDELINES:
- if (wParam > 0)
- cs.SetVisible(wParam, lParam, false);
- SetScrollBars();
- Redraw();
- break;
-
- case SCI_GETLINEVISIBLE:
- return cs.GetVisible(wParam);
-
- case SCI_GETALLLINESVISIBLE:
- return cs.HiddenLines() ? 0 : 1;
-
- case SCI_SETFOLDEXPANDED:
- SetFoldExpanded(wParam, lParam != 0);
- break;
-
- case SCI_GETFOLDEXPANDED:
- return cs.GetExpanded(wParam);
-
- case SCI_SETAUTOMATICFOLD:
- foldAutomatic = wParam;
- break;
-
- case SCI_GETAUTOMATICFOLD:
- return foldAutomatic;
-
- case SCI_SETFOLDFLAGS:
- foldFlags = wParam;
- Redraw();
- break;
-
- case SCI_TOGGLEFOLD:
- FoldLine(wParam, SC_FOLDACTION_TOGGLE);
- break;
-
- case SCI_FOLDLINE:
- FoldLine(wParam, lParam);
- break;
-
- case SCI_FOLDCHILDREN:
- FoldExpand(wParam, lParam, pdoc->GetLevel(wParam));
- break;
-
- case SCI_FOLDALL:
- FoldAll(wParam);
- break;
-
- case SCI_EXPANDCHILDREN:
- FoldExpand(wParam, SC_FOLDACTION_EXPAND, lParam);
- break;
-
- case SCI_CONTRACTEDFOLDNEXT:
- return ContractedFoldNext(wParam);
-
- case SCI_ENSUREVISIBLE:
- EnsureLineVisible(wParam, false);
- break;
-
- case SCI_ENSUREVISIBLEENFORCEPOLICY:
- EnsureLineVisible(wParam, true);
- break;
-
- case SCI_SCROLLRANGE:
- ScrollRange(SelectionRange(lParam, wParam));
- break;
-
- case SCI_SEARCHANCHOR:
- SearchAnchor();
- break;
-
- case SCI_SEARCHNEXT:
- case SCI_SEARCHPREV:
- return SearchText(iMessage, wParam, lParam);
-
- case SCI_SETXCARETPOLICY:
- caretXPolicy = wParam;
- caretXSlop = lParam;
- break;
-
- case SCI_SETYCARETPOLICY:
- caretYPolicy = wParam;
- caretYSlop = lParam;
- break;
-
- case SCI_SETVISIBLEPOLICY:
- visiblePolicy = wParam;
- visibleSlop = lParam;
- break;
-
- case SCI_LINESONSCREEN:
- return LinesOnScreen();
-
- case SCI_SETSELFORE:
- vs.selColours.fore = ColourOptional(wParam, lParam);
- vs.selAdditionalForeground = ColourDesired(lParam);
- InvalidateStyleRedraw();
- break;
-
- case SCI_SETSELBACK:
- vs.selColours.back = ColourOptional(wParam, lParam);
- vs.selAdditionalBackground = ColourDesired(lParam);
- InvalidateStyleRedraw();
- break;
-
- case SCI_SETSELALPHA:
- vs.selAlpha = wParam;
- vs.selAdditionalAlpha = wParam;
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETSELALPHA:
- return vs.selAlpha;
-
- case SCI_GETSELEOLFILLED:
- return vs.selEOLFilled;
-
- case SCI_SETSELEOLFILLED:
- vs.selEOLFilled = wParam != 0;
- InvalidateStyleRedraw();
- break;
-
- case SCI_SETWHITESPACEFORE:
- vs.whitespaceColours.fore = ColourOptional(wParam, lParam);
- InvalidateStyleRedraw();
- break;
-
- case SCI_SETWHITESPACEBACK:
- vs.whitespaceColours.back = ColourOptional(wParam, lParam);
- InvalidateStyleRedraw();
- break;
-
- case SCI_SETCARETFORE:
- vs.caretcolour = ColourDesired(wParam);
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETCARETFORE:
- return vs.caretcolour.AsLong();
-
- case SCI_SETCARETSTYLE:
- if (wParam <= CARETSTYLE_BLOCK)
- vs.caretStyle = wParam;
- else
- /* Default to the line caret */
- vs.caretStyle = CARETSTYLE_LINE;
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETCARETSTYLE:
- return vs.caretStyle;
-
- case SCI_SETCARETWIDTH:
- if (static_cast<int>(wParam) <= 0)
- vs.caretWidth = 0;
- else if (wParam >= 3)
- vs.caretWidth = 3;
- else
- vs.caretWidth = wParam;
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETCARETWIDTH:
- return vs.caretWidth;
-
- case SCI_ASSIGNCMDKEY:
- kmap.AssignCmdKey(Platform::LowShortFromLong(wParam),
- Platform::HighShortFromLong(wParam), lParam);
- break;
-
- case SCI_CLEARCMDKEY:
- kmap.AssignCmdKey(Platform::LowShortFromLong(wParam),
- Platform::HighShortFromLong(wParam), SCI_NULL);
- break;
-
- case SCI_CLEARALLCMDKEYS:
- kmap.Clear();
- break;
-
- case SCI_INDICSETSTYLE:
- if (wParam <= INDIC_MAX) {
- vs.indicators[wParam].style = lParam;
- InvalidateStyleRedraw();
- }
- break;
-
- case SCI_INDICGETSTYLE:
- return (wParam <= INDIC_MAX) ? vs.indicators[wParam].style : 0;
-
- case SCI_INDICSETFORE:
- if (wParam <= INDIC_MAX) {
- vs.indicators[wParam].fore = ColourDesired(lParam);
- InvalidateStyleRedraw();
- }
- break;
-
- case SCI_INDICGETFORE:
- return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fore.AsLong() : 0;
-
- case SCI_INDICSETUNDER:
- if (wParam <= INDIC_MAX) {
- vs.indicators[wParam].under = lParam != 0;
- InvalidateStyleRedraw();
- }
- break;
-
- case SCI_INDICGETUNDER:
- return (wParam <= INDIC_MAX) ? vs.indicators[wParam].under : 0;
-
- case SCI_INDICSETALPHA:
- if (wParam <= INDIC_MAX && lParam >=0 && lParam <= 255) {
- vs.indicators[wParam].fillAlpha = lParam;
- InvalidateStyleRedraw();
- }
- break;
-
- case SCI_INDICGETALPHA:
- return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fillAlpha : 0;
-
- case SCI_INDICSETOUTLINEALPHA:
- if (wParam <= INDIC_MAX && lParam >=0 && lParam <= 255) {
- vs.indicators[wParam].outlineAlpha = lParam;
- InvalidateStyleRedraw();
- }
- break;
-
- case SCI_INDICGETOUTLINEALPHA:
- return (wParam <= INDIC_MAX) ? vs.indicators[wParam].outlineAlpha : 0;
-
- case SCI_SETINDICATORCURRENT:
- pdoc->decorations.SetCurrentIndicator(wParam);
- break;
- case SCI_GETINDICATORCURRENT:
- return pdoc->decorations.GetCurrentIndicator();
- case SCI_SETINDICATORVALUE:
- pdoc->decorations.SetCurrentValue(wParam);
- break;
- case SCI_GETINDICATORVALUE:
- return pdoc->decorations.GetCurrentValue();
-
- case SCI_INDICATORFILLRANGE:
- pdoc->DecorationFillRange(wParam, pdoc->decorations.GetCurrentValue(), lParam);
- break;
-
- case SCI_INDICATORCLEARRANGE:
- pdoc->DecorationFillRange(wParam, 0, lParam);
- break;
-
- case SCI_INDICATORALLONFOR:
- return pdoc->decorations.AllOnFor(wParam);
-
- case SCI_INDICATORVALUEAT:
- return pdoc->decorations.ValueAt(wParam, lParam);
-
- case SCI_INDICATORSTART:
- return pdoc->decorations.Start(wParam, lParam);
-
- case SCI_INDICATOREND:
- return pdoc->decorations.End(wParam, lParam);
-
- case SCI_LINEDOWN:
- case SCI_LINEDOWNEXTEND:
- case SCI_PARADOWN:
- case SCI_PARADOWNEXTEND:
- case SCI_LINEUP:
- case SCI_LINEUPEXTEND:
- case SCI_PARAUP:
- case SCI_PARAUPEXTEND:
- case SCI_CHARLEFT:
- case SCI_CHARLEFTEXTEND:
- case SCI_CHARRIGHT:
- case SCI_CHARRIGHTEXTEND:
- case SCI_WORDLEFT:
- case SCI_WORDLEFTEXTEND:
- case SCI_WORDRIGHT:
- case SCI_WORDRIGHTEXTEND:
- case SCI_WORDLEFTEND:
- case SCI_WORDLEFTENDEXTEND:
- case SCI_WORDRIGHTEND:
- case SCI_WORDRIGHTENDEXTEND:
- case SCI_HOME:
- case SCI_HOMEEXTEND:
- case SCI_LINEEND:
- case SCI_LINEENDEXTEND:
- case SCI_HOMEWRAP:
- case SCI_HOMEWRAPEXTEND:
- case SCI_LINEENDWRAP:
- case SCI_LINEENDWRAPEXTEND:
- case SCI_DOCUMENTSTART:
- case SCI_DOCUMENTSTARTEXTEND:
- case SCI_DOCUMENTEND:
- case SCI_DOCUMENTENDEXTEND:
- case SCI_SCROLLTOSTART:
- case SCI_SCROLLTOEND:
-
- case SCI_STUTTEREDPAGEUP:
- case SCI_STUTTEREDPAGEUPEXTEND:
- case SCI_STUTTEREDPAGEDOWN:
- case SCI_STUTTEREDPAGEDOWNEXTEND:
-
- case SCI_PAGEUP:
- case SCI_PAGEUPEXTEND:
- case SCI_PAGEDOWN:
- case SCI_PAGEDOWNEXTEND:
- case SCI_EDITTOGGLEOVERTYPE:
- case SCI_CANCEL:
- case SCI_DELETEBACK:
- case SCI_TAB:
- case SCI_BACKTAB:
- case SCI_NEWLINE:
- case SCI_FORMFEED:
- case SCI_VCHOME:
- case SCI_VCHOMEEXTEND:
- case SCI_VCHOMEWRAP:
- case SCI_VCHOMEWRAPEXTEND:
- case SCI_VCHOMEDISPLAY:
- case SCI_VCHOMEDISPLAYEXTEND:
- case SCI_ZOOMIN:
- case SCI_ZOOMOUT:
- case SCI_DELWORDLEFT:
- case SCI_DELWORDRIGHT:
- case SCI_DELWORDRIGHTEND:
- case SCI_DELLINELEFT:
- case SCI_DELLINERIGHT:
- case SCI_LINECOPY:
- case SCI_LINECUT:
- case SCI_LINEDELETE:
- case SCI_LINETRANSPOSE:
- case SCI_LINEDUPLICATE:
- case SCI_LOWERCASE:
- case SCI_UPPERCASE:
- case SCI_LINESCROLLDOWN:
- case SCI_LINESCROLLUP:
- case SCI_WORDPARTLEFT:
- case SCI_WORDPARTLEFTEXTEND:
- case SCI_WORDPARTRIGHT:
- case SCI_WORDPARTRIGHTEXTEND:
- case SCI_DELETEBACKNOTLINE:
- case SCI_HOMEDISPLAY:
- case SCI_HOMEDISPLAYEXTEND:
- case SCI_LINEENDDISPLAY:
- case SCI_LINEENDDISPLAYEXTEND:
- case SCI_LINEDOWNRECTEXTEND:
- case SCI_LINEUPRECTEXTEND:
- case SCI_CHARLEFTRECTEXTEND:
- case SCI_CHARRIGHTRECTEXTEND:
- case SCI_HOMERECTEXTEND:
- case SCI_VCHOMERECTEXTEND:
- case SCI_LINEENDRECTEXTEND:
- case SCI_PAGEUPRECTEXTEND:
- case SCI_PAGEDOWNRECTEXTEND:
- case SCI_SELECTIONDUPLICATE:
- return KeyCommand(iMessage);
-
- case SCI_BRACEHIGHLIGHT:
- SetBraceHighlight(static_cast<int>(wParam), lParam, STYLE_BRACELIGHT);
- break;
-
- case SCI_BRACEHIGHLIGHTINDICATOR:
- if (lParam >= 0 && lParam <= INDIC_MAX) {
- vs.braceHighlightIndicatorSet = wParam != 0;
- vs.braceHighlightIndicator = lParam;
- }
- break;
-
- case SCI_BRACEBADLIGHT:
- SetBraceHighlight(static_cast<int>(wParam), -1, STYLE_BRACEBAD);
- break;
-
- case SCI_BRACEBADLIGHTINDICATOR:
- if (lParam >= 0 && lParam <= INDIC_MAX) {
- vs.braceBadLightIndicatorSet = wParam != 0;
- vs.braceBadLightIndicator = lParam;
- }
- break;
-
- case SCI_BRACEMATCH:
- // wParam is position of char to find brace for,
- // lParam is maximum amount of text to restyle to find it
- return pdoc->BraceMatch(wParam, lParam);
-
- case SCI_GETVIEWEOL:
- return vs.viewEOL;
-
- case SCI_SETVIEWEOL:
- vs.viewEOL = wParam != 0;
- InvalidateStyleRedraw();
- break;
-
- case SCI_SETZOOM:
- vs.zoomLevel = wParam;
- InvalidateStyleRedraw();
- NotifyZoom();
- break;
-
- case SCI_GETZOOM:
- return vs.zoomLevel;
-
- case SCI_GETEDGECOLUMN:
- return vs.theEdge;
-
- case SCI_SETEDGECOLUMN:
- vs.theEdge = wParam;
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETEDGEMODE:
- return vs.edgeState;
-
- case SCI_SETEDGEMODE:
- vs.edgeState = wParam;
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETEDGECOLOUR:
- return vs.edgecolour.AsLong();
-
- case SCI_SETEDGECOLOUR:
- vs.edgecolour = ColourDesired(wParam);
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETDOCPOINTER:
- return reinterpret_cast<sptr_t>(pdoc);
-
- case SCI_SETDOCPOINTER:
- CancelModes();
- SetDocPointer(reinterpret_cast<Document *>(lParam));
- return 0;
-
- case SCI_CREATEDOCUMENT: {
- Document *doc = new Document();
- doc->AddRef();
- return reinterpret_cast<sptr_t>(doc);
- }
-
- case SCI_ADDREFDOCUMENT:
- (reinterpret_cast<Document *>(lParam))->AddRef();
- break;
-
- case SCI_RELEASEDOCUMENT:
- (reinterpret_cast<Document *>(lParam))->Release();
- break;
-
- case SCI_CREATELOADER: {
- Document *doc = new Document();
- doc->AddRef();
- doc->Allocate(wParam);
- doc->SetUndoCollection(false);
- return reinterpret_cast<sptr_t>(static_cast<ILoader *>(doc));
- }
-
- case SCI_SETMODEVENTMASK:
- modEventMask = wParam;
- return 0;
-
- case SCI_GETMODEVENTMASK:
- return modEventMask;
-
- case SCI_CONVERTEOLS:
- pdoc->ConvertLineEnds(wParam);
- SetSelection(sel.MainCaret(), sel.MainAnchor()); // Ensure selection inside document
- return 0;
-
- case SCI_SETLENGTHFORENCODE:
- lengthForEncode = wParam;
- return 0;
-
- case SCI_SELECTIONISRECTANGLE:
- return sel.selType == Selection::selRectangle ? 1 : 0;
-
- case SCI_SETSELECTIONMODE: {
- switch (wParam) {
- case SC_SEL_STREAM:
- sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selStream));
- sel.selType = Selection::selStream;
- break;
- case SC_SEL_RECTANGLE:
- sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selRectangle));
- sel.selType = Selection::selRectangle;
- break;
- case SC_SEL_LINES:
- sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selLines));
- sel.selType = Selection::selLines;
- break;
- case SC_SEL_THIN:
- sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selThin));
- sel.selType = Selection::selThin;
- break;
- default:
- sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selStream));
- sel.selType = Selection::selStream;
- }
- InvalidateSelection(sel.RangeMain(), true);
- break;
- }
- case SCI_GETSELECTIONMODE:
- switch (sel.selType) {
- case Selection::selStream:
- return SC_SEL_STREAM;
- case Selection::selRectangle:
- return SC_SEL_RECTANGLE;
- case Selection::selLines:
- return SC_SEL_LINES;
- case Selection::selThin:
- return SC_SEL_THIN;
- default: // ?!
- return SC_SEL_STREAM;
- }
- case SCI_GETLINESELSTARTPOSITION:
- case SCI_GETLINESELENDPOSITION: {
- SelectionSegment segmentLine(SelectionPosition(pdoc->LineStart(wParam)),
- SelectionPosition(pdoc->LineEnd(wParam)));
- for (size_t r=0; r<sel.Count(); r++) {
- SelectionSegment portion = sel.Range(r).Intersect(segmentLine);
- if (portion.start.IsValid()) {
- return (iMessage == SCI_GETLINESELSTARTPOSITION) ? portion.start.Position() : portion.end.Position();
- }
- }
- return INVALID_POSITION;
- }
-
- case SCI_SETOVERTYPE:
- inOverstrike = wParam != 0;
- break;
-
- case SCI_GETOVERTYPE:
- return inOverstrike ? 1 : 0;
-
- case SCI_SETFOCUS:
- SetFocusState(wParam != 0);
- break;
-
- case SCI_GETFOCUS:
- return hasFocus;
-
- case SCI_SETSTATUS:
- errorStatus = wParam;
- break;
-
- case SCI_GETSTATUS:
- return errorStatus;
-
- case SCI_SETMOUSEDOWNCAPTURES:
- mouseDownCaptures = wParam != 0;
- break;
-
- case SCI_GETMOUSEDOWNCAPTURES:
- return mouseDownCaptures;
-
- case SCI_SETCURSOR:
- cursorMode = wParam;
- DisplayCursor(Window::cursorText);
- break;
-
- case SCI_GETCURSOR:
- return cursorMode;
-
- case SCI_SETCONTROLCHARSYMBOL:
- vs.controlCharSymbol = wParam;
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETCONTROLCHARSYMBOL:
- return vs.controlCharSymbol;
-
- case SCI_SETREPRESENTATION:
- reprs.SetRepresentation(reinterpret_cast<const char *>(wParam), CharPtrFromSPtr(lParam));
- break;
-
- case SCI_GETREPRESENTATION: {
- Representation *repr = reprs.RepresentationFromCharacter(
- reinterpret_cast<const char *>(wParam), UTF8MaxBytes);
- if (repr) {
- if (lParam != 0)
- strcpy(CharPtrFromSPtr(lParam), repr->stringRep.c_str());
- return repr->stringRep.size();
- }
- return 0;
- }
-
- case SCI_CLEARREPRESENTATION:
- reprs.ClearRepresentation(reinterpret_cast<const char *>(wParam));
- break;
-
- case SCI_STARTRECORD:
- recordingMacro = true;
- return 0;
-
- case SCI_STOPRECORD:
- recordingMacro = false;
- return 0;
-
- case SCI_MOVECARETINSIDEVIEW:
- MoveCaretInsideView();
- break;
-
- case SCI_SETFOLDMARGINCOLOUR:
- vs.foldmarginColour = ColourOptional(wParam, lParam);
- InvalidateStyleRedraw();
- break;
-
- case SCI_SETFOLDMARGINHICOLOUR:
- vs.foldmarginHighlightColour = ColourOptional(wParam, lParam);
- InvalidateStyleRedraw();
- break;
-
- case SCI_SETHOTSPOTACTIVEFORE:
- vs.hotspotColours.fore = ColourOptional(wParam, lParam);
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETHOTSPOTACTIVEFORE:
- return vs.hotspotColours.fore.AsLong();
-
- case SCI_SETHOTSPOTACTIVEBACK:
- vs.hotspotColours.back = ColourOptional(wParam, lParam);
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETHOTSPOTACTIVEBACK:
- return vs.hotspotColours.back.AsLong();
-
- case SCI_SETHOTSPOTACTIVEUNDERLINE:
- vs.hotspotUnderline = wParam != 0;
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETHOTSPOTACTIVEUNDERLINE:
- return vs.hotspotUnderline ? 1 : 0;
-
- case SCI_SETHOTSPOTSINGLELINE:
- vs.hotspotSingleLine = wParam != 0;
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETHOTSPOTSINGLELINE:
- return vs.hotspotSingleLine ? 1 : 0;
-
- case SCI_SETPASTECONVERTENDINGS:
- convertPastes = wParam != 0;
- break;
-
- case SCI_GETPASTECONVERTENDINGS:
- return convertPastes ? 1 : 0;
-
- case SCI_GETCHARACTERPOINTER:
- return reinterpret_cast<sptr_t>(pdoc->BufferPointer());
-
- case SCI_GETRANGEPOINTER:
- return reinterpret_cast<sptr_t>(pdoc->RangePointer(wParam, lParam));
-
- case SCI_GETGAPPOSITION:
- return pdoc->GapPosition();
-
- case SCI_SETEXTRAASCENT:
- vs.extraAscent = wParam;
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETEXTRAASCENT:
- return vs.extraAscent;
-
- case SCI_SETEXTRADESCENT:
- vs.extraDescent = wParam;
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETEXTRADESCENT:
- return vs.extraDescent;
-
- case SCI_MARGINSETSTYLEOFFSET:
- vs.marginStyleOffset = wParam;
- InvalidateStyleRedraw();
- break;
-
- case SCI_MARGINGETSTYLEOFFSET:
- return vs.marginStyleOffset;
-
- case SCI_SETMARGINOPTIONS:
- marginOptions = wParam;
- break;
-
- case SCI_GETMARGINOPTIONS:
- return marginOptions;
-
- case SCI_MARGINSETTEXT:
- pdoc->MarginSetText(wParam, CharPtrFromSPtr(lParam));
- break;
-
- case SCI_MARGINGETTEXT: {
- const StyledText st = pdoc->MarginStyledText(wParam);
- if (lParam) {
- if (st.text)
- memcpy(CharPtrFromSPtr(lParam), st.text, st.length);
- else
- strcpy(CharPtrFromSPtr(lParam), "");
- }
- return st.length;
- }
-
- case SCI_MARGINSETSTYLE:
- pdoc->MarginSetStyle(wParam, lParam);
- break;
-
- case SCI_MARGINGETSTYLE: {
- const StyledText st = pdoc->MarginStyledText(wParam);
- return st.style;
- }
-
- case SCI_MARGINSETSTYLES:
- pdoc->MarginSetStyles(wParam, reinterpret_cast<const unsigned char *>(lParam));
- break;
-
- case SCI_MARGINGETSTYLES: {
- const StyledText st = pdoc->MarginStyledText(wParam);
- if (lParam) {
- if (st.styles)
- memcpy(CharPtrFromSPtr(lParam), st.styles, st.length);
- else
- strcpy(CharPtrFromSPtr(lParam), "");
- }
- return st.styles ? st.length : 0;
- }
-
- case SCI_MARGINTEXTCLEARALL:
- pdoc->MarginClearAll();
- break;
-
- case SCI_ANNOTATIONSETTEXT:
- pdoc->AnnotationSetText(wParam, CharPtrFromSPtr(lParam));
- break;
-
- case SCI_ANNOTATIONGETTEXT: {
- const StyledText st = pdoc->AnnotationStyledText(wParam);
- if (lParam) {
- if (st.text)
- memcpy(CharPtrFromSPtr(lParam), st.text, st.length);
- else
- strcpy(CharPtrFromSPtr(lParam), "");
- }
- return st.length;
- }
-
- case SCI_ANNOTATIONGETSTYLE: {
- const StyledText st = pdoc->AnnotationStyledText(wParam);
- return st.style;
- }
-
- case SCI_ANNOTATIONSETSTYLE:
- pdoc->AnnotationSetStyle(wParam, lParam);
- break;
-
- case SCI_ANNOTATIONSETSTYLES:
- pdoc->AnnotationSetStyles(wParam, reinterpret_cast<const unsigned char *>(lParam));
- break;
-
- case SCI_ANNOTATIONGETSTYLES: {
- const StyledText st = pdoc->AnnotationStyledText(wParam);
- if (lParam) {
- if (st.styles)
- memcpy(CharPtrFromSPtr(lParam), st.styles, st.length);
- else
- strcpy(CharPtrFromSPtr(lParam), "");
- }
- return st.styles ? st.length : 0;
- }
-
- case SCI_ANNOTATIONGETLINES:
- return pdoc->AnnotationLines(wParam);
-
- case SCI_ANNOTATIONCLEARALL:
- pdoc->AnnotationClearAll();
- break;
-
- case SCI_ANNOTATIONSETVISIBLE:
- SetAnnotationVisible(wParam);
- break;
-
- case SCI_ANNOTATIONGETVISIBLE:
- return vs.annotationVisible;
-
- case SCI_ANNOTATIONSETSTYLEOFFSET:
- vs.annotationStyleOffset = wParam;
- InvalidateStyleRedraw();
- break;
-
- case SCI_ANNOTATIONGETSTYLEOFFSET:
- return vs.annotationStyleOffset;
-
- case SCI_RELEASEALLEXTENDEDSTYLES:
- vs.ReleaseAllExtendedStyles();
- break;
-
- case SCI_ALLOCATEEXTENDEDSTYLES:
- return vs.AllocateExtendedStyles(wParam);
-
- case SCI_ADDUNDOACTION:
- pdoc->AddUndoAction(wParam, lParam & UNDO_MAY_COALESCE);
- break;
-
- case SCI_SETMOUSESELECTIONRECTANGULARSWITCH:
- mouseSelectionRectangularSwitch = wParam != 0;
- break;
-
- case SCI_GETMOUSESELECTIONRECTANGULARSWITCH:
- return mouseSelectionRectangularSwitch;
-
- case SCI_SETMULTIPLESELECTION:
- multipleSelection = wParam != 0;
- InvalidateCaret();
- break;
-
- case SCI_GETMULTIPLESELECTION:
- return multipleSelection;
-
- case SCI_SETADDITIONALSELECTIONTYPING:
- additionalSelectionTyping = wParam != 0;
- InvalidateCaret();
- break;
-
- case SCI_GETADDITIONALSELECTIONTYPING:
- return additionalSelectionTyping;
-
- case SCI_SETMULTIPASTE:
- multiPasteMode = wParam;
- break;
-
- case SCI_GETMULTIPASTE:
- return multiPasteMode;
-
- case SCI_SETADDITIONALCARETSBLINK:
- additionalCaretsBlink = wParam != 0;
- InvalidateCaret();
- break;
-
- case SCI_GETADDITIONALCARETSBLINK:
- return additionalCaretsBlink;
-
- case SCI_SETADDITIONALCARETSVISIBLE:
- additionalCaretsVisible = wParam != 0;
- InvalidateCaret();
- break;
-
- case SCI_GETADDITIONALCARETSVISIBLE:
- return additionalCaretsVisible;
-
- case SCI_GETSELECTIONS:
- return sel.Count();
-
- case SCI_GETSELECTIONEMPTY:
- return sel.Empty();
-
- case SCI_CLEARSELECTIONS:
- sel.Clear();
- Redraw();
- break;
-
- case SCI_SETSELECTION:
- sel.SetSelection(SelectionRange(wParam, lParam));
- Redraw();
- break;
-
- case SCI_ADDSELECTION:
- sel.AddSelection(SelectionRange(wParam, lParam));
- Redraw();
- break;
-
- case SCI_SETMAINSELECTION:
- sel.SetMain(wParam);
- Redraw();
- break;
-
- case SCI_GETMAINSELECTION:
- return sel.Main();
-
- case SCI_SETSELECTIONNCARET:
- sel.Range(wParam).caret.SetPosition(lParam);
- Redraw();
- break;
-
- case SCI_GETSELECTIONNCARET:
- return sel.Range(wParam).caret.Position();
-
- case SCI_SETSELECTIONNANCHOR:
- sel.Range(wParam).anchor.SetPosition(lParam);
- Redraw();
- break;
- case SCI_GETSELECTIONNANCHOR:
- return sel.Range(wParam).anchor.Position();
-
- case SCI_SETSELECTIONNCARETVIRTUALSPACE:
- sel.Range(wParam).caret.SetVirtualSpace(lParam);
- Redraw();
- break;
-
- case SCI_GETSELECTIONNCARETVIRTUALSPACE:
- return sel.Range(wParam).caret.VirtualSpace();
-
- case SCI_SETSELECTIONNANCHORVIRTUALSPACE:
- sel.Range(wParam).anchor.SetVirtualSpace(lParam);
- Redraw();
- break;
-
- case SCI_GETSELECTIONNANCHORVIRTUALSPACE:
- return sel.Range(wParam).anchor.VirtualSpace();
-
- case SCI_SETSELECTIONNSTART:
- sel.Range(wParam).anchor.SetPosition(lParam);
- Redraw();
- break;
-
- case SCI_GETSELECTIONNSTART:
- return sel.Range(wParam).Start().Position();
-
- case SCI_SETSELECTIONNEND:
- sel.Range(wParam).caret.SetPosition(lParam);
- Redraw();
- break;
-
- case SCI_GETSELECTIONNEND:
- return sel.Range(wParam).End().Position();
-
- case SCI_SETRECTANGULARSELECTIONCARET:
- if (!sel.IsRectangular())
- sel.Clear();
- sel.selType = Selection::selRectangle;
- sel.Rectangular().caret.SetPosition(wParam);
- SetRectangularRange();
- Redraw();
- break;
-
- case SCI_GETRECTANGULARSELECTIONCARET:
- return sel.Rectangular().caret.Position();
-
- case SCI_SETRECTANGULARSELECTIONANCHOR:
- if (!sel.IsRectangular())
- sel.Clear();
- sel.selType = Selection::selRectangle;
- sel.Rectangular().anchor.SetPosition(wParam);
- SetRectangularRange();
- Redraw();
- break;
-
- case SCI_GETRECTANGULARSELECTIONANCHOR:
- return sel.Rectangular().anchor.Position();
-
- case SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE:
- if (!sel.IsRectangular())
- sel.Clear();
- sel.selType = Selection::selRectangle;
- sel.Rectangular().caret.SetVirtualSpace(wParam);
- SetRectangularRange();
- Redraw();
- break;
-
- case SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE:
- return sel.Rectangular().caret.VirtualSpace();
-
- case SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE:
- if (!sel.IsRectangular())
- sel.Clear();
- sel.selType = Selection::selRectangle;
- sel.Rectangular().anchor.SetVirtualSpace(wParam);
- SetRectangularRange();
- Redraw();
- break;
-
- case SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE:
- return sel.Rectangular().anchor.VirtualSpace();
-
- case SCI_SETVIRTUALSPACEOPTIONS:
- virtualSpaceOptions = wParam;
- break;
-
- case SCI_GETVIRTUALSPACEOPTIONS:
- return virtualSpaceOptions;
-
- case SCI_SETADDITIONALSELFORE:
- vs.selAdditionalForeground = ColourDesired(wParam);
- InvalidateStyleRedraw();
- break;
-
- case SCI_SETADDITIONALSELBACK:
- vs.selAdditionalBackground = ColourDesired(wParam);
- InvalidateStyleRedraw();
- break;
-
- case SCI_SETADDITIONALSELALPHA:
- vs.selAdditionalAlpha = wParam;
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETADDITIONALSELALPHA:
- return vs.selAdditionalAlpha;
-
- case SCI_SETADDITIONALCARETFORE:
- vs.additionalCaretColour = ColourDesired(wParam);
- InvalidateStyleRedraw();
- break;
-
- case SCI_GETADDITIONALCARETFORE:
- return vs.additionalCaretColour.AsLong();
-
- case SCI_ROTATESELECTION:
- sel.RotateMain();
- InvalidateSelection(sel.RangeMain(), true);
- break;
-
- case SCI_SWAPMAINANCHORCARET:
- InvalidateSelection(sel.RangeMain());
- sel.RangeMain() = SelectionRange(sel.RangeMain().anchor, sel.RangeMain().caret);
- break;
-
- case SCI_CHANGELEXERSTATE:
- pdoc->ChangeLexerState(wParam, lParam);
- break;
-
- case SCI_SETIDENTIFIER:
- SetCtrlID(wParam);
- break;
-
- case SCI_GETIDENTIFIER:
- return GetCtrlID();
-
- case SCI_SETTECHNOLOGY:
- // No action by default
- break;
-
- case SCI_GETTECHNOLOGY:
- return technology;
-
- case SCI_COUNTCHARACTERS:
- return pdoc->CountCharacters(wParam, lParam);
-
- default:
- return DefWndProc(iMessage, wParam, lParam);
- }
- //Platform::DebugPrintf("end wnd proc\n");
- return 0l;
-}