1 // Scintilla source code edit control
3 ** Main code for the edit control.
5 // Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
25 #include "Scintilla.h"
27 #include "StringCopy.h"
29 #include "SplitVector.h"
30 #include "Partitioning.h"
31 #include "RunStyles.h"
32 #include "ContractionState.h"
33 #include "CellBuffer.h"
36 #include "Indicator.h"
38 #include "LineMarker.h"
40 #include "ViewStyle.h"
41 #include "CharClassify.h"
42 #include "Decoration.h"
43 #include "CaseFolder.h"
45 #include "UniConversion.h"
46 #include "Selection.h"
47 #include "PositionCache.h"
48 #include "EditModel.h"
49 #include "MarginView.h"
54 using namespace Scintilla
;
58 return whether this modification represents an operation that
59 may reasonably be deferred (not done now OR [possibly] at all)
61 static bool CanDeferToLastStep(const DocModification
&mh
) {
62 if (mh
.modificationType
& (SC_MOD_BEFOREINSERT
| SC_MOD_BEFOREDELETE
))
63 return true; // CAN skip
64 if (!(mh
.modificationType
& (SC_PERFORMED_UNDO
| SC_PERFORMED_REDO
)))
65 return false; // MUST do
66 if (mh
.modificationType
& SC_MULTISTEPUNDOREDO
)
67 return true; // CAN skip
68 return false; // PRESUMABLY must do
71 static bool CanEliminate(const DocModification
&mh
) {
73 (mh
.modificationType
& (SC_MOD_BEFOREINSERT
| SC_MOD_BEFOREDELETE
)) != 0;
77 return whether this modification represents the FINAL step
78 in a [possibly lengthy] multi-step Undo/Redo sequence
80 static bool IsLastStep(const DocModification
&mh
) {
82 (mh
.modificationType
& (SC_PERFORMED_UNDO
| SC_PERFORMED_REDO
)) != 0
83 && (mh
.modificationType
& SC_MULTISTEPUNDOREDO
) != 0
84 && (mh
.modificationType
& SC_LASTSTEPINUNDOREDO
) != 0
85 && (mh
.modificationType
& SC_MULTILINEUNDOREDO
) != 0;
89 ticking(false), ticksToWait(0), tickerID(0) {}
92 state(false), idlerID(0) {}
94 static inline bool IsAllSpacesOrTabs(const char *s
, unsigned int len
) {
95 for (unsigned int i
= 0; i
< len
; i
++) {
96 // This is safe because IsSpaceOrTab() will return false for null terminators
97 if (!IsSpaceOrTab(s
[i
]))
107 technology
= SC_TECHNOLOGY_DEFAULT
;
108 scaleRGBAImage
= 100.0f
;
110 cursorMode
= SC_CURSORNORMAL
;
114 mouseDownCaptures
= true;
115 mouseWheelCaptures
= true;
118 doubleClickCloseThreshold
= Point(3, 3);
119 dwellDelay
= SC_TIME_FOREVER
;
120 ticksToDwell
= SC_TIME_FOREVER
;
125 dropWentOutside
= false;
126 posDrop
= SelectionPosition(invalidPosition
);
127 hotSpotClickPos
= INVALID_POSITION
;
128 selectionType
= selChar
;
132 originalAnchorPos
= 0;
133 wordSelectAnchorStartPos
= 0;
134 wordSelectAnchorEndPos
= 0;
135 wordSelectInitialCaretPos
= -1;
137 caretXPolicy
= CARET_SLOP
| CARET_EVEN
;
140 caretYPolicy
= CARET_EVEN
;
149 horizontalScrollBarVisible
= true;
151 verticalScrollBarVisible
= true;
152 endAtLastLine
= true;
153 caretSticky
= SC_CARETSTICKY_OFF
;
154 marginOptions
= SC_MARGINOPTION_NONE
;
155 mouseSelectionRectangularSwitch
= false;
156 multipleSelection
= false;
157 additionalSelectionTyping
= false;
158 multiPasteMode
= SC_MULTIPASTE_ONCE
;
159 virtualSpaceOptions
= SCVS_NONE
;
168 lengthForEncode
= -1;
171 ContainerNeedsUpdate(SC_UPDATE_CONTENT
);
173 paintState
= notPainting
;
174 paintAbandonedByStyling
= false;
175 paintingAllText
= false;
176 willRedrawAll
= false;
177 idleStyling
= SC_IDLESTYLING_NONE
;
178 needIdleStyling
= false;
180 modEventMask
= SC_MODEVENTMASKALL
;
182 pdoc
->AddWatcher(this, 0);
184 recordingMacro
= false;
187 convertPastes
= true;
189 SetRepresentations();
193 pdoc
->RemoveWatcher(this, 0);
197 void Editor::Finalise() {
202 void Editor::SetRepresentations() {
206 const char *reps
[] = {
207 "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
208 "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI",
209 "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
210 "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"
212 for (size_t j
=0; j
< ELEMENTS(reps
); j
++) {
213 char c
[2] = { static_cast<char>(j
), 0 };
214 reprs
.SetRepresentation(c
, reps
[j
]);
218 // As well as Unicode mode, ISO-8859-1 should use these
219 if (IsUnicodeMode()) {
220 const char *repsC1
[] = {
221 "PAD", "HOP", "BPH", "NBH", "IND", "NEL", "SSA", "ESA",
222 "HTS", "HTJ", "VTS", "PLD", "PLU", "RI", "SS2", "SS3",
223 "DCS", "PU1", "PU2", "STS", "CCH", "MW", "SPA", "EPA",
224 "SOS", "SGCI", "SCI", "CSI", "ST", "OSC", "PM", "APC"
226 for (size_t j
=0; j
< ELEMENTS(repsC1
); j
++) {
227 char c1
[3] = { '\xc2', static_cast<char>(0x80+j
), 0 };
228 reprs
.SetRepresentation(c1
, repsC1
[j
]);
230 reprs
.SetRepresentation("\xe2\x80\xa8", "LS");
231 reprs
.SetRepresentation("\xe2\x80\xa9", "PS");
234 // UTF-8 invalid bytes
235 if (IsUnicodeMode()) {
236 for (int k
=0x80; k
< 0x100; k
++) {
237 char hiByte
[2] = { static_cast<char>(k
), 0 };
239 sprintf(hexits
, "x%2X", k
);
240 reprs
.SetRepresentation(hiByte
, hexits
);
245 void Editor::DropGraphics(bool freeObjects
) {
246 marginView
.DropGraphics(freeObjects
);
247 view
.DropGraphics(freeObjects
);
250 void Editor::AllocateGraphics() {
251 marginView
.AllocateGraphics(vs
);
252 view
.AllocateGraphics(vs
);
255 void Editor::InvalidateStyleData() {
257 vs
.technology
= technology
;
260 view
.llc
.Invalidate(LineLayout::llInvalid
);
261 view
.posCache
.Clear();
264 void Editor::InvalidateStyleRedraw() {
266 InvalidateStyleData();
270 void Editor::RefreshStyleData() {
273 AutoSurface
surface(this);
275 vs
.Refresh(*surface
, pdoc
->tabInChars
);
278 SetRectangularRange();
282 Point
Editor::GetVisibleOriginInMain() const {
286 PointDocument
Editor::DocumentPointFromView(Point ptView
) const {
287 PointDocument
ptDocument(ptView
);
288 if (wMargin
.GetID()) {
289 Point ptOrigin
= GetVisibleOriginInMain();
290 ptDocument
.x
+= ptOrigin
.x
;
291 ptDocument
.y
+= ptOrigin
.y
;
293 ptDocument
.x
+= xOffset
;
294 ptDocument
.y
+= topLine
* vs
.lineHeight
;
299 int Editor::TopLineOfMain() const {
306 PRectangle
Editor::GetClientRectangle() const {
308 return win
.GetClientPosition();
311 PRectangle
Editor::GetClientDrawingRectangle() {
312 return GetClientRectangle();
315 PRectangle
Editor::GetTextRectangle() const {
316 PRectangle rc
= GetClientRectangle();
317 rc
.left
+= vs
.textStart
;
318 rc
.right
-= vs
.rightMarginWidth
;
322 int Editor::LinesOnScreen() const {
323 PRectangle rcClient
= GetClientRectangle();
324 int htClient
= static_cast<int>(rcClient
.bottom
- rcClient
.top
);
325 //Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1);
326 return htClient
/ vs
.lineHeight
;
329 int Editor::LinesToScroll() const {
330 int retVal
= LinesOnScreen() - 1;
337 int Editor::MaxScrollPos() const {
338 //Platform::DebugPrintf("Lines %d screen = %d maxScroll = %d\n",
339 //LinesTotal(), LinesOnScreen(), LinesTotal() - LinesOnScreen() + 1);
340 int retVal
= cs
.LinesDisplayed();
342 retVal
-= LinesOnScreen();
353 SelectionPosition
Editor::ClampPositionIntoDocument(SelectionPosition sp
) const {
354 if (sp
.Position() < 0) {
355 return SelectionPosition(0);
356 } else if (sp
.Position() > pdoc
->Length()) {
357 return SelectionPosition(pdoc
->Length());
359 // If not at end of line then set offset to 0
360 if (!pdoc
->IsLineEndPosition(sp
.Position()))
361 sp
.SetVirtualSpace(0);
366 Point
Editor::LocationFromPosition(SelectionPosition pos
, PointEnd pe
) {
368 AutoSurface
surface(this);
369 return view
.LocationFromPosition(surface
, *this, pos
, topLine
, vs
, pe
);
372 Point
Editor::LocationFromPosition(int pos
, PointEnd pe
) {
373 return LocationFromPosition(SelectionPosition(pos
), pe
);
376 int Editor::XFromPosition(int pos
) {
377 Point pt
= LocationFromPosition(pos
);
378 return static_cast<int>(pt
.x
) - vs
.textStart
+ xOffset
;
381 int Editor::XFromPosition(SelectionPosition sp
) {
382 Point pt
= LocationFromPosition(sp
);
383 return static_cast<int>(pt
.x
) - vs
.textStart
+ xOffset
;
386 SelectionPosition
Editor::SPositionFromLocation(Point pt
, bool canReturnInvalid
, bool charPosition
, bool virtualSpace
) {
388 AutoSurface
surface(this);
390 if (canReturnInvalid
) {
391 PRectangle rcClient
= GetTextRectangle();
392 // May be in scroll view coordinates so translate back to main view
393 Point ptOrigin
= GetVisibleOriginInMain();
394 rcClient
.Move(-ptOrigin
.x
, -ptOrigin
.y
);
395 if (!rcClient
.Contains(pt
))
396 return SelectionPosition(INVALID_POSITION
);
397 if (pt
.x
< vs
.textStart
)
398 return SelectionPosition(INVALID_POSITION
);
400 return SelectionPosition(INVALID_POSITION
);
402 PointDocument ptdoc
= DocumentPointFromView(pt
);
403 return view
.SPositionFromLocation(surface
, *this, ptdoc
, canReturnInvalid
, charPosition
, virtualSpace
, vs
);
406 int Editor::PositionFromLocation(Point pt
, bool canReturnInvalid
, bool charPosition
) {
407 return SPositionFromLocation(pt
, canReturnInvalid
, charPosition
, false).Position();
411 * Find the document position corresponding to an x coordinate on a particular document line.
412 * Ensure is between whole characters when document is in multi-byte or UTF-8 mode.
413 * This method is used for rectangular selections and does not work on wrapped lines.
415 SelectionPosition
Editor::SPositionFromLineX(int lineDoc
, int x
) {
417 if (lineDoc
>= pdoc
->LinesTotal())
418 return SelectionPosition(pdoc
->Length());
419 //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine);
420 AutoSurface
surface(this);
421 return view
.SPositionFromLineX(surface
, *this, lineDoc
, x
, vs
);
424 int Editor::PositionFromLineX(int lineDoc
, int x
) {
425 return SPositionFromLineX(lineDoc
, x
).Position();
428 int Editor::LineFromLocation(Point pt
) const {
429 return cs
.DocFromDisplay(static_cast<int>(pt
.y
) / vs
.lineHeight
+ topLine
);
432 void Editor::SetTopLine(int topLineNew
) {
433 if ((topLine
!= topLineNew
) && (topLineNew
>= 0)) {
434 topLine
= topLineNew
;
435 ContainerNeedsUpdate(SC_UPDATE_V_SCROLL
);
437 posTopLine
= pdoc
->LineStart(cs
.DocFromDisplay(topLine
));
441 * If painting then abandon the painting because a wider redraw is needed.
442 * @return true if calling code should stop drawing.
444 bool Editor::AbandonPaint() {
445 if ((paintState
== painting
) && !paintingAllText
) {
446 paintState
= paintAbandoned
;
448 return paintState
== paintAbandoned
;
451 void Editor::RedrawRect(PRectangle rc
) {
452 //Platform::DebugPrintf("Redraw %0d,%0d - %0d,%0d\n", rc.left, rc.top, rc.right, rc.bottom);
454 // Clip the redraw rectangle into the client area
455 PRectangle rcClient
= GetClientRectangle();
456 if (rc
.top
< rcClient
.top
)
457 rc
.top
= rcClient
.top
;
458 if (rc
.bottom
> rcClient
.bottom
)
459 rc
.bottom
= rcClient
.bottom
;
460 if (rc
.left
< rcClient
.left
)
461 rc
.left
= rcClient
.left
;
462 if (rc
.right
> rcClient
.right
)
463 rc
.right
= rcClient
.right
;
465 if ((rc
.bottom
> rc
.top
) && (rc
.right
> rc
.left
)) {
466 wMain
.InvalidateRectangle(rc
);
470 void Editor::DiscardOverdraw() {
471 // Overridden on platforms that may draw outside visible area.
474 void Editor::Redraw() {
475 //Platform::DebugPrintf("Redraw all\n");
476 PRectangle rcClient
= GetClientRectangle();
477 wMain
.InvalidateRectangle(rcClient
);
479 wMargin
.InvalidateAll();
480 //wMain.InvalidateAll();
483 void Editor::RedrawSelMargin(int line
, bool allAfter
) {
484 const bool markersInText
= vs
.maskInLine
|| vs
.maskDrawInText
;
485 if (!wMargin
.GetID() || markersInText
) { // May affect text area so may need to abandon and retry
486 if (AbandonPaint()) {
490 if (wMargin
.GetID() && markersInText
) {
494 PRectangle rcMarkers
= GetClientRectangle();
495 if (!markersInText
) {
496 // Normal case: just draw the margin
497 rcMarkers
.right
= rcMarkers
.left
+ vs
.fixedColumnWidth
;
500 PRectangle rcLine
= RectangleFromRange(Range(pdoc
->LineStart(line
)), 0);
502 // Inflate line rectangle if there are image markers with height larger than line height
503 if (vs
.largestMarkerHeight
> vs
.lineHeight
) {
504 int delta
= (vs
.largestMarkerHeight
- vs
.lineHeight
+ 1) / 2;
506 rcLine
.bottom
+= delta
;
507 if (rcLine
.top
< rcMarkers
.top
)
508 rcLine
.top
= rcMarkers
.top
;
509 if (rcLine
.bottom
> rcMarkers
.bottom
)
510 rcLine
.bottom
= rcMarkers
.bottom
;
513 rcMarkers
.top
= rcLine
.top
;
515 rcMarkers
.bottom
= rcLine
.bottom
;
516 if (rcMarkers
.Empty())
519 if (wMargin
.GetID()) {
520 Point ptOrigin
= GetVisibleOriginInMain();
521 rcMarkers
.Move(-ptOrigin
.x
, -ptOrigin
.y
);
522 wMargin
.InvalidateRectangle(rcMarkers
);
524 wMain
.InvalidateRectangle(rcMarkers
);
528 PRectangle
Editor::RectangleFromRange(Range r
, int overlap
) {
529 const int minLine
= cs
.DisplayFromDoc(pdoc
->LineFromPosition(r
.First()));
530 const int maxLine
= cs
.DisplayLastFromDoc(pdoc
->LineFromPosition(r
.Last()));
531 const PRectangle rcClientDrawing
= GetClientDrawingRectangle();
533 const int leftTextOverlap
= ((xOffset
== 0) && (vs
.leftMarginWidth
> 0)) ? 1 : 0;
534 rc
.left
= static_cast<XYPOSITION
>(vs
.textStart
- leftTextOverlap
);
535 rc
.top
= static_cast<XYPOSITION
>((minLine
- TopLineOfMain()) * vs
.lineHeight
- overlap
);
536 if (rc
.top
< rcClientDrawing
.top
)
537 rc
.top
= rcClientDrawing
.top
;
538 // Extend to right of prepared area if any to prevent artifacts from caret line highlight
539 rc
.right
= rcClientDrawing
.right
;
540 rc
.bottom
= static_cast<XYPOSITION
>((maxLine
- TopLineOfMain() + 1) * vs
.lineHeight
+ overlap
);
545 void Editor::InvalidateRange(int start
, int end
) {
546 RedrawRect(RectangleFromRange(Range(start
, end
), view
.LinesOverlap() ? vs
.lineOverlap
: 0));
549 int Editor::CurrentPosition() const {
550 return sel
.MainCaret();
553 bool Editor::SelectionEmpty() const {
557 SelectionPosition
Editor::SelectionStart() {
558 return sel
.RangeMain().Start();
561 SelectionPosition
Editor::SelectionEnd() {
562 return sel
.RangeMain().End();
565 void Editor::SetRectangularRange() {
566 if (sel
.IsRectangular()) {
567 int xAnchor
= XFromPosition(sel
.Rectangular().anchor
);
568 int xCaret
= XFromPosition(sel
.Rectangular().caret
);
569 if (sel
.selType
== Selection::selThin
) {
572 int lineAnchorRect
= pdoc
->LineFromPosition(sel
.Rectangular().anchor
.Position());
573 int lineCaret
= pdoc
->LineFromPosition(sel
.Rectangular().caret
.Position());
574 int increment
= (lineCaret
> lineAnchorRect
) ? 1 : -1;
575 for (int line
=lineAnchorRect
; line
!= lineCaret
+increment
; line
+= increment
) {
576 SelectionRange
range(SPositionFromLineX(line
, xCaret
), SPositionFromLineX(line
, xAnchor
));
577 if ((virtualSpaceOptions
& SCVS_RECTANGULARSELECTION
) == 0)
578 range
.ClearVirtualSpace();
579 if (line
== lineAnchorRect
)
580 sel
.SetSelection(range
);
582 sel
.AddSelectionWithoutTrim(range
);
587 void Editor::ThinRectangularRange() {
588 if (sel
.IsRectangular()) {
589 sel
.selType
= Selection::selThin
;
590 if (sel
.Rectangular().caret
< sel
.Rectangular().anchor
) {
591 sel
.Rectangular() = SelectionRange(sel
.Range(sel
.Count()-1).caret
, sel
.Range(0).anchor
);
593 sel
.Rectangular() = SelectionRange(sel
.Range(sel
.Count()-1).anchor
, sel
.Range(0).caret
);
595 SetRectangularRange();
599 void Editor::InvalidateSelection(SelectionRange newMain
, bool invalidateWholeSelection
) {
600 if (sel
.Count() > 1 || !(sel
.RangeMain().anchor
== newMain
.anchor
) || sel
.IsRectangular()) {
601 invalidateWholeSelection
= true;
603 int firstAffected
= Platform::Minimum(sel
.RangeMain().Start().Position(), newMain
.Start().Position());
604 // +1 for lastAffected ensures caret repainted
605 int lastAffected
= Platform::Maximum(newMain
.caret
.Position()+1, newMain
.anchor
.Position());
606 lastAffected
= Platform::Maximum(lastAffected
, sel
.RangeMain().End().Position());
607 if (invalidateWholeSelection
) {
608 for (size_t r
=0; r
<sel
.Count(); r
++) {
609 firstAffected
= Platform::Minimum(firstAffected
, sel
.Range(r
).caret
.Position());
610 firstAffected
= Platform::Minimum(firstAffected
, sel
.Range(r
).anchor
.Position());
611 lastAffected
= Platform::Maximum(lastAffected
, sel
.Range(r
).caret
.Position()+1);
612 lastAffected
= Platform::Maximum(lastAffected
, sel
.Range(r
).anchor
.Position());
615 ContainerNeedsUpdate(SC_UPDATE_SELECTION
);
616 InvalidateRange(firstAffected
, lastAffected
);
619 void Editor::InvalidateWholeSelection() {
620 InvalidateSelection(sel
.RangeMain(), true);
623 void Editor::SetSelection(SelectionPosition currentPos_
, SelectionPosition anchor_
) {
624 currentPos_
= ClampPositionIntoDocument(currentPos_
);
625 anchor_
= ClampPositionIntoDocument(anchor_
);
626 int currentLine
= pdoc
->LineFromPosition(currentPos_
.Position());
627 /* For Line selection - ensure the anchor and caret are always
628 at the beginning and end of the region lines. */
629 if (sel
.selType
== Selection::selLines
) {
630 if (currentPos_
> anchor_
) {
631 anchor_
= SelectionPosition(pdoc
->LineStart(pdoc
->LineFromPosition(anchor_
.Position())));
632 currentPos_
= SelectionPosition(pdoc
->LineEnd(pdoc
->LineFromPosition(currentPos_
.Position())));
634 currentPos_
= SelectionPosition(pdoc
->LineStart(pdoc
->LineFromPosition(currentPos_
.Position())));
635 anchor_
= SelectionPosition(pdoc
->LineEnd(pdoc
->LineFromPosition(anchor_
.Position())));
638 SelectionRange
rangeNew(currentPos_
, anchor_
);
639 if (sel
.Count() > 1 || !(sel
.RangeMain() == rangeNew
)) {
640 InvalidateSelection(rangeNew
);
642 sel
.RangeMain() = rangeNew
;
643 SetRectangularRange();
645 SetHoverIndicatorPosition(sel
.MainCaret());
647 if (marginView
.highlightDelimiter
.NeedsDrawing(currentLine
)) {
650 QueueIdleWork(WorkNeeded::workUpdateUI
);
653 void Editor::SetSelection(int currentPos_
, int anchor_
) {
654 SetSelection(SelectionPosition(currentPos_
), SelectionPosition(anchor_
));
657 // Just move the caret on the main selection
658 void Editor::SetSelection(SelectionPosition currentPos_
) {
659 currentPos_
= ClampPositionIntoDocument(currentPos_
);
660 int currentLine
= pdoc
->LineFromPosition(currentPos_
.Position());
661 if (sel
.Count() > 1 || !(sel
.RangeMain().caret
== currentPos_
)) {
662 InvalidateSelection(SelectionRange(currentPos_
));
664 if (sel
.IsRectangular()) {
666 SelectionRange(SelectionPosition(currentPos_
), sel
.Rectangular().anchor
);
667 SetRectangularRange();
670 SelectionRange(SelectionPosition(currentPos_
), sel
.RangeMain().anchor
);
673 SetHoverIndicatorPosition(sel
.MainCaret());
675 if (marginView
.highlightDelimiter
.NeedsDrawing(currentLine
)) {
678 QueueIdleWork(WorkNeeded::workUpdateUI
);
681 void Editor::SetSelection(int currentPos_
) {
682 SetSelection(SelectionPosition(currentPos_
));
685 void Editor::SetEmptySelection(SelectionPosition currentPos_
) {
686 int currentLine
= pdoc
->LineFromPosition(currentPos_
.Position());
687 SelectionRange
rangeNew(ClampPositionIntoDocument(currentPos_
));
688 if (sel
.Count() > 1 || !(sel
.RangeMain() == rangeNew
)) {
689 InvalidateSelection(rangeNew
);
692 sel
.RangeMain() = rangeNew
;
693 SetRectangularRange();
695 SetHoverIndicatorPosition(sel
.MainCaret());
697 if (marginView
.highlightDelimiter
.NeedsDrawing(currentLine
)) {
700 QueueIdleWork(WorkNeeded::workUpdateUI
);
703 void Editor::SetEmptySelection(int currentPos_
) {
704 SetEmptySelection(SelectionPosition(currentPos_
));
707 void Editor::MultipleSelectAdd(AddNumber addNumber
) {
708 if (SelectionEmpty() || !multipleSelection
) {
709 // Select word at caret
710 const int startWord
= pdoc
->ExtendWordSelect(sel
.MainCaret(), -1, true);
711 const int endWord
= pdoc
->ExtendWordSelect(startWord
, 1, true);
712 TrimAndSetSelection(endWord
, startWord
);
716 if (!pdoc
->HasCaseFolder())
717 pdoc
->SetCaseFolder(CaseFolderForEncoding());
719 const Range
rangeMainSelection(sel
.RangeMain().Start().Position(), sel
.RangeMain().End().Position());
720 const std::string selectedText
= RangeText(rangeMainSelection
.start
, rangeMainSelection
.end
);
722 const Range
rangeTarget(targetStart
, targetEnd
);
723 std::vector
<Range
> searchRanges
;
724 // Search should be over the target range excluding the current selection so
725 // may need to search 2 ranges, after the selection then before the selection.
726 if (rangeTarget
.Overlaps(rangeMainSelection
)) {
727 // Common case is that the selection is completely within the target but
728 // may also have overlap at start or end.
729 if (rangeMainSelection
.end
< rangeTarget
.end
)
730 searchRanges
.push_back(Range(rangeMainSelection
.end
, rangeTarget
.end
));
731 if (rangeTarget
.start
< rangeMainSelection
.start
)
732 searchRanges
.push_back(Range(rangeTarget
.start
, rangeMainSelection
.start
));
735 searchRanges
.push_back(rangeTarget
);
738 for (std::vector
<Range
>::const_iterator it
= searchRanges
.begin(); it
!= searchRanges
.end(); ++it
) {
739 int searchStart
= it
->start
;
740 const int searchEnd
= it
->end
;
742 int lengthFound
= static_cast<int>(selectedText
.length());
743 int pos
= static_cast<int>(pdoc
->FindText(searchStart
, searchEnd
,
744 selectedText
.c_str(), searchFlags
, &lengthFound
));
746 sel
.AddSelection(SelectionRange(pos
+ lengthFound
, pos
));
747 ScrollRange(sel
.RangeMain());
749 if (addNumber
== addOne
)
751 searchStart
= pos
+ lengthFound
;
760 bool Editor::RangeContainsProtected(int start
, int end
) const {
761 if (vs
.ProtectionActive()) {
767 for (int pos
= start
; pos
< end
; pos
++) {
768 if (vs
.styles
[pdoc
->StyleIndexAt(pos
)].IsProtected())
775 bool Editor::SelectionContainsProtected() {
776 for (size_t r
=0; r
<sel
.Count(); r
++) {
777 if (RangeContainsProtected(sel
.Range(r
).Start().Position(),
778 sel
.Range(r
).End().Position())) {
786 * Asks document to find a good position and then moves out of any invisible positions.
788 int Editor::MovePositionOutsideChar(int pos
, int moveDir
, bool checkLineEnd
) const {
789 return MovePositionOutsideChar(SelectionPosition(pos
), moveDir
, checkLineEnd
).Position();
792 SelectionPosition
Editor::MovePositionOutsideChar(SelectionPosition pos
, int moveDir
, bool checkLineEnd
) const {
793 int posMoved
= pdoc
->MovePositionOutsideChar(pos
.Position(), moveDir
, checkLineEnd
);
794 if (posMoved
!= pos
.Position())
795 pos
.SetPosition(posMoved
);
796 if (vs
.ProtectionActive()) {
798 if ((pos
.Position() > 0) && vs
.styles
[pdoc
->StyleIndexAt(pos
.Position() - 1)].IsProtected()) {
799 while ((pos
.Position() < pdoc
->Length()) &&
800 (vs
.styles
[pdoc
->StyleIndexAt(pos
.Position())].IsProtected()))
803 } else if (moveDir
< 0) {
804 if (vs
.styles
[pdoc
->StyleIndexAt(pos
.Position())].IsProtected()) {
805 while ((pos
.Position() > 0) &&
806 (vs
.styles
[pdoc
->StyleIndexAt(pos
.Position() - 1)].IsProtected()))
814 void Editor::MovedCaret(SelectionPosition newPos
, SelectionPosition previousPos
, bool ensureVisible
) {
815 const int currentLine
= pdoc
->LineFromPosition(newPos
.Position());
817 // In case in need of wrapping to ensure DisplayFromDoc works.
818 if (currentLine
>= wrapPending
.start
)
820 XYScrollPosition newXY
= XYScrollToMakeVisible(
821 SelectionRange(posDrag
.IsValid() ? posDrag
: newPos
), xysDefault
);
822 if (previousPos
.IsValid() && (newXY
.xOffset
== xOffset
)) {
823 // simple vertical scroll then invalidate
824 ScrollTo(newXY
.topLine
);
825 InvalidateSelection(SelectionRange(previousPos
), true);
831 ShowCaretAtCurrentPosition();
835 SetHoverIndicatorPosition(sel
.MainCaret());
836 QueueIdleWork(WorkNeeded::workUpdateUI
);
838 if (marginView
.highlightDelimiter
.NeedsDrawing(currentLine
)) {
843 void Editor::MovePositionTo(SelectionPosition newPos
, Selection::selTypes selt
, bool ensureVisible
) {
844 const SelectionPosition spCaret
= ((sel
.Count() == 1) && sel
.Empty()) ?
845 sel
.Last() : SelectionPosition(INVALID_POSITION
);
847 int delta
= newPos
.Position() - sel
.MainCaret();
848 newPos
= ClampPositionIntoDocument(newPos
);
849 newPos
= MovePositionOutsideChar(newPos
, delta
);
850 if (!multipleSelection
&& sel
.IsRectangular() && (selt
== Selection::selStream
)) {
851 // Can't turn into multiple selection so clear additional selections
852 InvalidateSelection(SelectionRange(newPos
), true);
853 sel
.DropAdditionalRanges();
855 if (!sel
.IsRectangular() && (selt
== Selection::selRectangle
)) {
856 // Switching to rectangular
857 InvalidateSelection(sel
.RangeMain(), false);
858 SelectionRange rangeMain
= sel
.RangeMain();
860 sel
.Rectangular() = rangeMain
;
862 if (selt
!= Selection::noSel
) {
865 if (selt
!= Selection::noSel
|| sel
.MoveExtends()) {
866 SetSelection(newPos
);
868 SetEmptySelection(newPos
);
871 MovedCaret(newPos
, spCaret
, ensureVisible
);
874 void Editor::MovePositionTo(int newPos
, Selection::selTypes selt
, bool ensureVisible
) {
875 MovePositionTo(SelectionPosition(newPos
), selt
, ensureVisible
);
878 SelectionPosition
Editor::MovePositionSoVisible(SelectionPosition pos
, int moveDir
) {
879 pos
= ClampPositionIntoDocument(pos
);
880 pos
= MovePositionOutsideChar(pos
, moveDir
);
881 int lineDoc
= pdoc
->LineFromPosition(pos
.Position());
882 if (cs
.GetVisible(lineDoc
)) {
885 int lineDisplay
= cs
.DisplayFromDoc(lineDoc
);
887 // lineDisplay is already line before fold as lines in fold use display line of line after fold
888 lineDisplay
= Platform::Clamp(lineDisplay
, 0, cs
.LinesDisplayed());
889 return SelectionPosition(pdoc
->LineStart(cs
.DocFromDisplay(lineDisplay
)));
891 lineDisplay
= Platform::Clamp(lineDisplay
- 1, 0, cs
.LinesDisplayed());
892 return SelectionPosition(pdoc
->LineEnd(cs
.DocFromDisplay(lineDisplay
)));
897 SelectionPosition
Editor::MovePositionSoVisible(int pos
, int moveDir
) {
898 return MovePositionSoVisible(SelectionPosition(pos
), moveDir
);
901 Point
Editor::PointMainCaret() {
902 return LocationFromPosition(sel
.Range(sel
.Main()).caret
);
906 * Choose the x position that the caret will try to stick to
907 * as it moves up and down.
909 void Editor::SetLastXChosen() {
910 Point pt
= PointMainCaret();
911 lastXChosen
= static_cast<int>(pt
.x
) + xOffset
;
914 void Editor::ScrollTo(int line
, bool moveThumb
) {
915 int topLineNew
= Platform::Clamp(line
, 0, MaxScrollPos());
916 if (topLineNew
!= topLine
) {
917 // Try to optimise small scrolls
919 int linesToMove
= topLine
- topLineNew
;
920 bool performBlit
= (abs(linesToMove
) <= 10) && (paintState
== notPainting
);
921 willRedrawAll
= !performBlit
;
923 SetTopLine(topLineNew
);
924 // Optimize by styling the view as this will invalidate any needed area
925 // which could abort the initial paint if discovered later.
926 StyleAreaBounded(GetClientRectangle(), true);
928 // Perform redraw rather than scroll if many lines would be redrawn anyway.
930 ScrollText(linesToMove
);
934 willRedrawAll
= false;
939 SetVerticalScrollPos();
944 void Editor::ScrollText(int /* linesToMove */) {
945 //Platform::DebugPrintf("Editor::ScrollText %d\n", linesToMove);
949 void Editor::HorizontalScrollTo(int xPos
) {
950 //Platform::DebugPrintf("HorizontalScroll %d\n", xPos);
953 if (!Wrapping() && (xOffset
!= xPos
)) {
955 ContainerNeedsUpdate(SC_UPDATE_H_SCROLL
);
956 SetHorizontalScrollPos();
957 RedrawRect(GetClientRectangle());
961 void Editor::VerticalCentreCaret() {
962 int lineDoc
= pdoc
->LineFromPosition(sel
.IsRectangular() ? sel
.Rectangular().caret
.Position() : sel
.MainCaret());
963 int lineDisplay
= cs
.DisplayFromDoc(lineDoc
);
964 int newTop
= lineDisplay
- (LinesOnScreen() / 2);
965 if (topLine
!= newTop
) {
966 SetTopLine(newTop
> 0 ? newTop
: 0);
967 RedrawRect(GetClientRectangle());
971 // Avoid 64 bit compiler warnings.
972 // Scintilla does not support text buffers larger than 2**31
973 static int istrlen(const char *s
) {
974 return static_cast<int>(s
? strlen(s
) : 0);
977 void Editor::MoveSelectedLines(int lineDelta
) {
979 // if selection doesn't start at the beginning of the line, set the new start
980 int selectionStart
= SelectionStart().Position();
981 int startLine
= pdoc
->LineFromPosition(selectionStart
);
982 int beginningOfStartLine
= pdoc
->LineStart(startLine
);
983 selectionStart
= beginningOfStartLine
;
985 // if selection doesn't end at the beginning of a line greater than that of the start,
986 // then set it at the beginning of the next one
987 int selectionEnd
= SelectionEnd().Position();
988 int endLine
= pdoc
->LineFromPosition(selectionEnd
);
989 int beginningOfEndLine
= pdoc
->LineStart(endLine
);
990 bool appendEol
= false;
991 if (selectionEnd
> beginningOfEndLine
992 || selectionStart
== selectionEnd
) {
993 selectionEnd
= pdoc
->LineStart(endLine
+ 1);
994 appendEol
= (selectionEnd
== pdoc
->Length() && pdoc
->LineFromPosition(selectionEnd
) == endLine
);
997 // if there's nowhere for the selection to move
998 // (i.e. at the beginning going up or at the end going down),
999 // stop it right there!
1000 if ((selectionStart
== 0 && lineDelta
< 0)
1001 || (selectionEnd
== pdoc
->Length() && lineDelta
> 0)
1002 || selectionStart
== selectionEnd
) {
1008 if (lineDelta
> 0 && selectionEnd
== pdoc
->LineStart(pdoc
->LinesTotal() - 1)) {
1009 SetSelection(pdoc
->MovePositionOutsideChar(selectionEnd
- 1, -1), selectionEnd
);
1011 selectionEnd
= CurrentPosition();
1013 SetSelection(selectionStart
, selectionEnd
);
1015 SelectionText selectedText
;
1016 CopySelectionRange(&selectedText
);
1018 int selectionLength
= SelectionRange(selectionStart
, selectionEnd
).Length();
1019 Point currentLocation
= LocationFromPosition(CurrentPosition());
1020 int currentLine
= LineFromLocation(currentLocation
);
1023 SetSelection(pdoc
->MovePositionOutsideChar(selectionStart
- 1, -1), selectionEnd
);
1026 const char *eol
= StringFromEOLMode(pdoc
->eolMode
);
1027 if (currentLine
+ lineDelta
>= pdoc
->LinesTotal())
1028 pdoc
->InsertString(pdoc
->Length(), eol
, istrlen(eol
));
1029 GoToLine(currentLine
+ lineDelta
);
1031 selectionLength
= pdoc
->InsertString(CurrentPosition(), selectedText
.Data(), selectionLength
);
1033 const int lengthInserted
= pdoc
->InsertString(CurrentPosition() + selectionLength
, eol
, istrlen(eol
));
1034 selectionLength
+= lengthInserted
;
1036 SetSelection(CurrentPosition(), CurrentPosition() + selectionLength
);
1039 void Editor::MoveSelectedLinesUp() {
1040 MoveSelectedLines(-1);
1043 void Editor::MoveSelectedLinesDown() {
1044 MoveSelectedLines(1);
1047 void Editor::MoveCaretInsideView(bool ensureVisible
) {
1048 PRectangle rcClient
= GetTextRectangle();
1049 Point pt
= PointMainCaret();
1050 if (pt
.y
< rcClient
.top
) {
1051 MovePositionTo(SPositionFromLocation(
1052 Point::FromInts(lastXChosen
- xOffset
, static_cast<int>(rcClient
.top
)),
1053 false, false, UserVirtualSpace()),
1054 Selection::noSel
, ensureVisible
);
1055 } else if ((pt
.y
+ vs
.lineHeight
- 1) > rcClient
.bottom
) {
1056 int yOfLastLineFullyDisplayed
= static_cast<int>(rcClient
.top
) + (LinesOnScreen() - 1) * vs
.lineHeight
;
1057 MovePositionTo(SPositionFromLocation(
1058 Point::FromInts(lastXChosen
- xOffset
, static_cast<int>(rcClient
.top
) + yOfLastLineFullyDisplayed
),
1059 false, false, UserVirtualSpace()),
1060 Selection::noSel
, ensureVisible
);
1064 int Editor::DisplayFromPosition(int pos
) {
1065 AutoSurface
surface(this);
1066 return view
.DisplayFromPosition(surface
, *this, pos
, vs
);
1070 * Ensure the caret is reasonably visible in context.
1072 Caret policy in SciTE
1074 If slop is set, we can define a slop value.
1075 This value defines an unwanted zone (UZ) where the caret is... unwanted.
1076 This zone is defined as a number of pixels near the vertical margins,
1077 and as a number of lines near the horizontal margins.
1078 By keeping the caret away from the edges, it is seen within its context,
1079 so it is likely that the identifier that the caret is on can be completely seen,
1080 and that the current line is seen with some of the lines following it which are
1081 often dependent on that line.
1083 If strict is set, the policy is enforced... strictly.
1084 The caret is centred on the display if slop is not set,
1085 and cannot go in the UZ if slop is set.
1087 If jumps is set, the display is moved more energetically
1088 so the caret can move in the same direction longer before the policy is applied again.
1089 '3UZ' notation is used to indicate three time the size of the UZ as a distance to the margin.
1091 If even is not set, instead of having symmetrical UZs,
1092 the left and bottom UZs are extended up to right and top UZs respectively.
1093 This way, we favour the displaying of useful information: the beginning of lines,
1094 where most code reside, and the lines after the caret, eg. the body of a function.
1097 slop | strict | jumps | even | Caret can go to the margin | When reaching limit (caret going out of
1098 | | | | | visibility or going into the UZ) display is...
1099 -----+--------+-------+------+--------------------------------------------+--------------------------------------------------------------
1100 0 | 0 | 0 | 0 | Yes | moved to put caret on top/on right
1101 0 | 0 | 0 | 1 | Yes | moved by one position
1102 0 | 0 | 1 | 0 | Yes | moved to put caret on top/on right
1103 0 | 0 | 1 | 1 | Yes | centred on the caret
1104 0 | 1 | - | 0 | Caret is always on top/on right of display | -
1105 0 | 1 | - | 1 | No, caret is always centred | -
1106 1 | 0 | 0 | 0 | Yes | moved to put caret out of the asymmetrical UZ
1107 1 | 0 | 0 | 1 | Yes | moved to put caret out of the UZ
1108 1 | 0 | 1 | 0 | Yes | moved to put caret at 3UZ of the top or right margin
1109 1 | 0 | 1 | 1 | Yes | moved to put caret at 3UZ of the margin
1110 1 | 1 | - | 0 | Caret is always at UZ of top/right margin | -
1111 1 | 1 | 0 | 1 | No, kept out of UZ | moved by one position
1112 1 | 1 | 1 | 1 | No, kept out of UZ | moved to put caret at 3UZ of the margin
1115 Editor::XYScrollPosition
Editor::XYScrollToMakeVisible(const SelectionRange
&range
, const XYScrollOptions options
) {
1116 PRectangle rcClient
= GetTextRectangle();
1117 Point pt
= LocationFromPosition(range
.caret
);
1118 Point ptAnchor
= LocationFromPosition(range
.anchor
);
1119 const Point ptOrigin
= GetVisibleOriginInMain();
1122 ptAnchor
.x
+= ptOrigin
.x
;
1123 ptAnchor
.y
+= ptOrigin
.y
;
1124 const Point
ptBottomCaret(pt
.x
, pt
.y
+ vs
.lineHeight
- 1);
1126 XYScrollPosition
newXY(xOffset
, topLine
);
1127 if (rcClient
.Empty()) {
1131 // Vertical positioning
1132 if ((options
& xysVertical
) && (pt
.y
< rcClient
.top
|| ptBottomCaret
.y
>= rcClient
.bottom
|| (caretYPolicy
& CARET_STRICT
) != 0)) {
1133 const int lineCaret
= DisplayFromPosition(range
.caret
.Position());
1134 const int linesOnScreen
= LinesOnScreen();
1135 const int halfScreen
= Platform::Maximum(linesOnScreen
- 1, 2) / 2;
1136 const bool bSlop
= (caretYPolicy
& CARET_SLOP
) != 0;
1137 const bool bStrict
= (caretYPolicy
& CARET_STRICT
) != 0;
1138 const bool bJump
= (caretYPolicy
& CARET_JUMPS
) != 0;
1139 const bool bEven
= (caretYPolicy
& CARET_EVEN
) != 0;
1141 // It should be possible to scroll the window to show the caret,
1142 // but this fails to remove the caret on GTK+
1143 if (bSlop
) { // A margin is defined
1146 int yMarginT
, yMarginB
;
1147 if (!(options
& xysUseMargin
)) {
1148 // In drag mode, avoid moves
1149 // otherwise, a double click will select several lines.
1150 yMarginT
= yMarginB
= 0;
1152 // yMarginT must equal to caretYSlop, with a minimum of 1 and
1153 // a maximum of slightly less than half the heigth of the text area.
1154 yMarginT
= Platform::Clamp(caretYSlop
, 1, halfScreen
);
1156 yMarginB
= yMarginT
;
1158 yMarginB
= linesOnScreen
- yMarginT
- 1;
1164 yMoveT
= Platform::Clamp(caretYSlop
* 3, 1, halfScreen
);
1168 yMoveB
= linesOnScreen
- yMoveT
- 1;
1170 if (lineCaret
< topLine
+ yMarginT
) {
1171 // Caret goes too high
1172 newXY
.topLine
= lineCaret
- yMoveT
;
1173 } else if (lineCaret
> topLine
+ linesOnScreen
- 1 - yMarginB
) {
1174 // Caret goes too low
1175 newXY
.topLine
= lineCaret
- linesOnScreen
+ 1 + yMoveB
;
1177 } else { // Not strict
1178 yMoveT
= bJump
? caretYSlop
* 3 : caretYSlop
;
1179 yMoveT
= Platform::Clamp(yMoveT
, 1, halfScreen
);
1183 yMoveB
= linesOnScreen
- yMoveT
- 1;
1185 if (lineCaret
< topLine
) {
1186 // Caret goes too high
1187 newXY
.topLine
= lineCaret
- yMoveT
;
1188 } else if (lineCaret
> topLine
+ linesOnScreen
- 1) {
1189 // Caret goes too low
1190 newXY
.topLine
= lineCaret
- linesOnScreen
+ 1 + yMoveB
;
1194 if (!bStrict
&& !bJump
) {
1196 if (lineCaret
< topLine
) {
1197 // Caret goes too high
1198 newXY
.topLine
= lineCaret
;
1199 } else if (lineCaret
> topLine
+ linesOnScreen
- 1) {
1200 // Caret goes too low
1202 newXY
.topLine
= lineCaret
- linesOnScreen
+ 1;
1204 newXY
.topLine
= lineCaret
;
1207 } else { // Strict or going out of display
1209 // Always center caret
1210 newXY
.topLine
= lineCaret
- halfScreen
;
1212 // Always put caret on top of display
1213 newXY
.topLine
= lineCaret
;
1217 if (!(range
.caret
== range
.anchor
)) {
1218 const int lineAnchor
= DisplayFromPosition(range
.anchor
.Position());
1219 if (lineAnchor
< lineCaret
) {
1220 // Shift up to show anchor or as much of range as possible
1221 newXY
.topLine
= std::min(newXY
.topLine
, lineAnchor
);
1222 newXY
.topLine
= std::max(newXY
.topLine
, lineCaret
- LinesOnScreen());
1224 // Shift down to show anchor or as much of range as possible
1225 newXY
.topLine
= std::max(newXY
.topLine
, lineAnchor
- LinesOnScreen());
1226 newXY
.topLine
= std::min(newXY
.topLine
, lineCaret
);
1229 newXY
.topLine
= Platform::Clamp(newXY
.topLine
, 0, MaxScrollPos());
1232 // Horizontal positioning
1233 if ((options
& xysHorizontal
) && !Wrapping()) {
1234 const int halfScreen
= Platform::Maximum(static_cast<int>(rcClient
.Width()) - 4, 4) / 2;
1235 const bool bSlop
= (caretXPolicy
& CARET_SLOP
) != 0;
1236 const bool bStrict
= (caretXPolicy
& CARET_STRICT
) != 0;
1237 const bool bJump
= (caretXPolicy
& CARET_JUMPS
) != 0;
1238 const bool bEven
= (caretXPolicy
& CARET_EVEN
) != 0;
1240 if (bSlop
) { // A margin is defined
1243 int xMarginL
, xMarginR
;
1244 if (!(options
& xysUseMargin
)) {
1245 // In drag mode, avoid moves unless very near of the margin
1246 // otherwise, a simple click will select text.
1247 xMarginL
= xMarginR
= 2;
1249 // xMargin must equal to caretXSlop, with a minimum of 2 and
1250 // a maximum of slightly less than half the width of the text area.
1251 xMarginR
= Platform::Clamp(caretXSlop
, 2, halfScreen
);
1253 xMarginL
= xMarginR
;
1255 xMarginL
= static_cast<int>(rcClient
.Width()) - xMarginR
- 4;
1258 if (bJump
&& bEven
) {
1259 // Jump is used only in even mode
1260 xMoveL
= xMoveR
= Platform::Clamp(caretXSlop
* 3, 1, halfScreen
);
1262 xMoveL
= xMoveR
= 0; // Not used, avoid a warning
1264 if (pt
.x
< rcClient
.left
+ xMarginL
) {
1265 // Caret is on the left of the display
1266 if (bJump
&& bEven
) {
1267 newXY
.xOffset
-= xMoveL
;
1269 // Move just enough to allow to display the caret
1270 newXY
.xOffset
-= static_cast<int>((rcClient
.left
+ xMarginL
) - pt
.x
);
1272 } else if (pt
.x
>= rcClient
.right
- xMarginR
) {
1273 // Caret is on the right of the display
1274 if (bJump
&& bEven
) {
1275 newXY
.xOffset
+= xMoveR
;
1277 // Move just enough to allow to display the caret
1278 newXY
.xOffset
+= static_cast<int>(pt
.x
- (rcClient
.right
- xMarginR
) + 1);
1281 } else { // Not strict
1282 xMoveR
= bJump
? caretXSlop
* 3 : caretXSlop
;
1283 xMoveR
= Platform::Clamp(xMoveR
, 1, halfScreen
);
1287 xMoveL
= static_cast<int>(rcClient
.Width()) - xMoveR
- 4;
1289 if (pt
.x
< rcClient
.left
) {
1290 // Caret is on the left of the display
1291 newXY
.xOffset
-= xMoveL
;
1292 } else if (pt
.x
>= rcClient
.right
) {
1293 // Caret is on the right of the display
1294 newXY
.xOffset
+= xMoveR
;
1299 (bJump
&& (pt
.x
< rcClient
.left
|| pt
.x
>= rcClient
.right
))) {
1300 // Strict or going out of display
1303 newXY
.xOffset
+= static_cast<int>(pt
.x
- rcClient
.left
- halfScreen
);
1305 // Put caret on right
1306 newXY
.xOffset
+= static_cast<int>(pt
.x
- rcClient
.right
+ 1);
1309 // Move just enough to allow to display the caret
1310 if (pt
.x
< rcClient
.left
) {
1311 // Caret is on the left of the display
1313 newXY
.xOffset
-= static_cast<int>(rcClient
.left
- pt
.x
);
1315 newXY
.xOffset
+= static_cast<int>(pt
.x
- rcClient
.right
) + 1;
1317 } else if (pt
.x
>= rcClient
.right
) {
1318 // Caret is on the right of the display
1319 newXY
.xOffset
+= static_cast<int>(pt
.x
- rcClient
.right
) + 1;
1323 // In case of a jump (find result) largely out of display, adjust the offset to display the caret
1324 if (pt
.x
+ xOffset
< rcClient
.left
+ newXY
.xOffset
) {
1325 newXY
.xOffset
= static_cast<int>(pt
.x
+ xOffset
- rcClient
.left
) - 2;
1326 } else if (pt
.x
+ xOffset
>= rcClient
.right
+ newXY
.xOffset
) {
1327 newXY
.xOffset
= static_cast<int>(pt
.x
+ xOffset
- rcClient
.right
) + 2;
1328 if ((vs
.caretStyle
== CARETSTYLE_BLOCK
) || view
.imeCaretBlockOverride
) {
1329 // Ensure we can see a good portion of the block caret
1330 newXY
.xOffset
+= static_cast<int>(vs
.aveCharWidth
);
1333 if (!(range
.caret
== range
.anchor
)) {
1334 if (ptAnchor
.x
< pt
.x
) {
1335 // Shift to left to show anchor or as much of range as possible
1336 int maxOffset
= static_cast<int>(ptAnchor
.x
+ xOffset
- rcClient
.left
) - 1;
1337 int minOffset
= static_cast<int>(pt
.x
+ xOffset
- rcClient
.right
) + 1;
1338 newXY
.xOffset
= std::min(newXY
.xOffset
, maxOffset
);
1339 newXY
.xOffset
= std::max(newXY
.xOffset
, minOffset
);
1341 // Shift to right to show anchor or as much of range as possible
1342 int minOffset
= static_cast<int>(ptAnchor
.x
+ xOffset
- rcClient
.right
) + 1;
1343 int maxOffset
= static_cast<int>(pt
.x
+ xOffset
- rcClient
.left
) - 1;
1344 newXY
.xOffset
= std::max(newXY
.xOffset
, minOffset
);
1345 newXY
.xOffset
= std::min(newXY
.xOffset
, maxOffset
);
1348 if (newXY
.xOffset
< 0) {
1356 void Editor::SetXYScroll(XYScrollPosition newXY
) {
1357 if ((newXY
.topLine
!= topLine
) || (newXY
.xOffset
!= xOffset
)) {
1358 if (newXY
.topLine
!= topLine
) {
1359 SetTopLine(newXY
.topLine
);
1360 SetVerticalScrollPos();
1362 if (newXY
.xOffset
!= xOffset
) {
1363 xOffset
= newXY
.xOffset
;
1364 ContainerNeedsUpdate(SC_UPDATE_H_SCROLL
);
1365 if (newXY
.xOffset
> 0) {
1366 PRectangle rcText
= GetTextRectangle();
1367 if (horizontalScrollBarVisible
&&
1368 rcText
.Width() + xOffset
> scrollWidth
) {
1369 scrollWidth
= xOffset
+ static_cast<int>(rcText
.Width());
1373 SetHorizontalScrollPos();
1376 UpdateSystemCaret();
1380 void Editor::ScrollRange(SelectionRange range
) {
1381 SetXYScroll(XYScrollToMakeVisible(range
, xysDefault
));
1384 void Editor::EnsureCaretVisible(bool useMargin
, bool vert
, bool horiz
) {
1385 SetXYScroll(XYScrollToMakeVisible(SelectionRange(posDrag
.IsValid() ? posDrag
: sel
.RangeMain().caret
),
1386 static_cast<XYScrollOptions
>((useMargin
?xysUseMargin
:0)|(vert
?xysVertical
:0)|(horiz
?xysHorizontal
:0))));
1389 void Editor::ShowCaretAtCurrentPosition() {
1391 caret
.active
= true;
1393 if (FineTickerAvailable()) {
1394 FineTickerCancel(tickCaret
);
1395 if (caret
.period
> 0)
1396 FineTickerStart(tickCaret
, caret
.period
, caret
.period
/10);
1401 caret
.active
= false;
1403 if (FineTickerAvailable()) {
1404 FineTickerCancel(tickCaret
);
1410 void Editor::DropCaret() {
1411 caret
.active
= false;
1412 if (FineTickerAvailable()) {
1413 FineTickerCancel(tickCaret
);
1418 void Editor::CaretSetPeriod(int period
) {
1419 if (caret
.period
!= period
) {
1420 caret
.period
= period
;
1422 if (FineTickerAvailable()) {
1423 FineTickerCancel(tickCaret
);
1424 if ((caret
.active
) && (caret
.period
> 0))
1425 FineTickerStart(tickCaret
, caret
.period
, caret
.period
/10);
1431 void Editor::InvalidateCaret() {
1432 if (posDrag
.IsValid()) {
1433 InvalidateRange(posDrag
.Position(), posDrag
.Position() + 1);
1435 for (size_t r
=0; r
<sel
.Count(); r
++) {
1436 InvalidateRange(sel
.Range(r
).caret
.Position(), sel
.Range(r
).caret
.Position() + 1);
1439 UpdateSystemCaret();
1442 void Editor::NotifyCaretMove() {
1445 void Editor::UpdateSystemCaret() {
1448 bool Editor::Wrapping() const {
1449 return vs
.wrapState
!= eWrapNone
;
1452 void Editor::NeedWrapping(int docLineStart
, int docLineEnd
) {
1453 //Platform::DebugPrintf("\nNeedWrapping: %0d..%0d\n", docLineStart, docLineEnd);
1454 if (wrapPending
.AddRange(docLineStart
, docLineEnd
)) {
1455 view
.llc
.Invalidate(LineLayout::llPositions
);
1457 // Wrap lines during idle.
1458 if (Wrapping() && wrapPending
.NeedsWrap()) {
1463 bool Editor::WrapOneLine(Surface
*surface
, int lineToWrap
) {
1464 AutoLineLayout
ll(view
.llc
, view
.RetrieveLineLayout(lineToWrap
, *this));
1465 int linesWrapped
= 1;
1467 view
.LayoutLine(*this, lineToWrap
, surface
, vs
, ll
, wrapWidth
);
1468 linesWrapped
= ll
->lines
;
1470 return cs
.SetHeight(lineToWrap
, linesWrapped
+
1471 (vs
.annotationVisible
? pdoc
->AnnotationLines(lineToWrap
) : 0));
1474 // Perform wrapping for a subset of the lines needing wrapping.
1475 // wsAll: wrap all lines which need wrapping in this single call
1476 // wsVisible: wrap currently visible lines
1477 // wsIdle: wrap one page + 100 lines
1478 // Return true if wrapping occurred.
1479 bool Editor::WrapLines(enum wrapScope ws
) {
1480 int goodTopLine
= topLine
;
1481 bool wrapOccurred
= false;
1483 if (wrapWidth
!= LineLayout::wrapWidthInfinite
) {
1484 wrapWidth
= LineLayout::wrapWidthInfinite
;
1485 for (int lineDoc
= 0; lineDoc
< pdoc
->LinesTotal(); lineDoc
++) {
1486 cs
.SetHeight(lineDoc
, 1 +
1487 (vs
.annotationVisible
? pdoc
->AnnotationLines(lineDoc
) : 0));
1489 wrapOccurred
= true;
1491 wrapPending
.Reset();
1493 } else if (wrapPending
.NeedsWrap()) {
1494 wrapPending
.start
= std::min(wrapPending
.start
, pdoc
->LinesTotal());
1495 if (!SetIdle(true)) {
1496 // Idle processing not supported so full wrap required.
1499 // Decide where to start wrapping
1500 int lineToWrap
= wrapPending
.start
;
1501 int lineToWrapEnd
= std::min(wrapPending
.end
, pdoc
->LinesTotal());
1502 const int lineDocTop
= cs
.DocFromDisplay(topLine
);
1503 const int subLineTop
= topLine
- cs
.DisplayFromDoc(lineDocTop
);
1504 if (ws
== wsVisible
) {
1505 lineToWrap
= Platform::Clamp(lineDocTop
-5, wrapPending
.start
, pdoc
->LinesTotal());
1506 // Priority wrap to just after visible area.
1507 // Since wrapping could reduce display lines, treat each
1508 // as taking only one display line.
1509 lineToWrapEnd
= lineDocTop
;
1510 int lines
= LinesOnScreen() + 1;
1511 while ((lineToWrapEnd
< cs
.LinesInDoc()) && (lines
>0)) {
1512 if (cs
.GetVisible(lineToWrapEnd
))
1516 // .. and if the paint window is outside pending wraps
1517 if ((lineToWrap
> wrapPending
.end
) || (lineToWrapEnd
< wrapPending
.start
)) {
1518 // Currently visible text does not need wrapping
1521 } else if (ws
== wsIdle
) {
1522 lineToWrapEnd
= lineToWrap
+ LinesOnScreen() + 100;
1524 const int lineEndNeedWrap
= std::min(wrapPending
.end
, pdoc
->LinesTotal());
1525 lineToWrapEnd
= std::min(lineToWrapEnd
, lineEndNeedWrap
);
1527 // Ensure all lines being wrapped are styled.
1528 pdoc
->EnsureStyledTo(pdoc
->LineStart(lineToWrapEnd
));
1530 if (lineToWrap
< lineToWrapEnd
) {
1532 PRectangle rcTextArea
= GetClientRectangle();
1533 rcTextArea
.left
= static_cast<XYPOSITION
>(vs
.textStart
);
1534 rcTextArea
.right
-= vs
.rightMarginWidth
;
1535 wrapWidth
= static_cast<int>(rcTextArea
.Width());
1537 AutoSurface
surface(this);
1539 //Platform::DebugPrintf("Wraplines: scope=%0d need=%0d..%0d perform=%0d..%0d\n", ws, wrapPending.start, wrapPending.end, lineToWrap, lineToWrapEnd);
1541 while (lineToWrap
< lineToWrapEnd
) {
1542 if (WrapOneLine(surface
, lineToWrap
)) {
1543 wrapOccurred
= true;
1545 wrapPending
.Wrapped(lineToWrap
);
1549 goodTopLine
= cs
.DisplayFromDoc(lineDocTop
) + std::min(subLineTop
, cs
.GetHeight(lineDocTop
)-1);
1553 // If wrapping is done, bring it to resting position
1554 if (wrapPending
.start
>= lineEndNeedWrap
) {
1555 wrapPending
.Reset();
1561 SetTopLine(Platform::Clamp(goodTopLine
, 0, MaxScrollPos()));
1562 SetVerticalScrollPos();
1565 return wrapOccurred
;
1568 void Editor::LinesJoin() {
1569 if (!RangeContainsProtected(targetStart
, targetEnd
)) {
1571 bool prevNonWS
= true;
1572 for (int pos
= targetStart
; pos
< targetEnd
; pos
++) {
1573 if (pdoc
->IsPositionInLineEnd(pos
)) {
1574 targetEnd
-= pdoc
->LenChar(pos
);
1577 // Ensure at least one space separating previous lines
1578 const int lengthInserted
= pdoc
->InsertString(pos
, " ", 1);
1579 targetEnd
+= lengthInserted
;
1582 prevNonWS
= pdoc
->CharAt(pos
) != ' ';
1588 const char *Editor::StringFromEOLMode(int eolMode
) {
1589 if (eolMode
== SC_EOL_CRLF
) {
1591 } else if (eolMode
== SC_EOL_CR
) {
1598 void Editor::LinesSplit(int pixelWidth
) {
1599 if (!RangeContainsProtected(targetStart
, targetEnd
)) {
1600 if (pixelWidth
== 0) {
1601 PRectangle rcText
= GetTextRectangle();
1602 pixelWidth
= static_cast<int>(rcText
.Width());
1604 int lineStart
= pdoc
->LineFromPosition(targetStart
);
1605 int lineEnd
= pdoc
->LineFromPosition(targetEnd
);
1606 const char *eol
= StringFromEOLMode(pdoc
->eolMode
);
1608 for (int line
= lineStart
; line
<= lineEnd
; line
++) {
1609 AutoSurface
surface(this);
1610 AutoLineLayout
ll(view
.llc
, view
.RetrieveLineLayout(line
, *this));
1611 if (surface
&& ll
) {
1612 unsigned int posLineStart
= pdoc
->LineStart(line
);
1613 view
.LayoutLine(*this, line
, surface
, vs
, ll
, pixelWidth
);
1614 int lengthInsertedTotal
= 0;
1615 for (int subLine
= 1; subLine
< ll
->lines
; subLine
++) {
1616 const int lengthInserted
= pdoc
->InsertString(
1617 static_cast<int>(posLineStart
+ lengthInsertedTotal
+
1618 ll
->LineStart(subLine
)),
1620 targetEnd
+= lengthInserted
;
1621 lengthInsertedTotal
+= lengthInserted
;
1624 lineEnd
= pdoc
->LineFromPosition(targetEnd
);
1629 void Editor::PaintSelMargin(Surface
*surfWindow
, PRectangle
&rc
) {
1630 if (vs
.fixedColumnWidth
== 0)
1635 RefreshPixMaps(surfWindow
);
1637 // On GTK+ with Ubuntu overlay scroll bars, the surface may have been finished
1638 // at this point. The Initialised call checks for this case and sets the status
1639 // to be bad which avoids crashes in following calls.
1640 if (!surfWindow
->Initialised()) {
1644 PRectangle rcMargin
= GetClientRectangle();
1645 Point ptOrigin
= GetVisibleOriginInMain();
1646 rcMargin
.Move(0, -ptOrigin
.y
);
1648 rcMargin
.right
= static_cast<XYPOSITION
>(vs
.fixedColumnWidth
);
1650 if (!rc
.Intersects(rcMargin
))
1654 if (view
.bufferedDraw
) {
1655 surface
= marginView
.pixmapSelMargin
;
1657 surface
= surfWindow
;
1660 // Clip vertically to paint area to avoid drawing line numbers
1661 if (rcMargin
.bottom
> rc
.bottom
)
1662 rcMargin
.bottom
= rc
.bottom
;
1663 if (rcMargin
.top
< rc
.top
)
1664 rcMargin
.top
= rc
.top
;
1666 marginView
.PaintMargin(surface
, topLine
, rc
, rcMargin
, *this, vs
);
1668 if (view
.bufferedDraw
) {
1669 surfWindow
->Copy(rcMargin
, Point(rcMargin
.left
, rcMargin
.top
), *marginView
.pixmapSelMargin
);
1673 void Editor::RefreshPixMaps(Surface
*surfaceWindow
) {
1674 view
.RefreshPixMaps(surfaceWindow
, wMain
.GetID(), vs
);
1675 marginView
.RefreshPixMaps(surfaceWindow
, wMain
.GetID(), vs
);
1676 if (view
.bufferedDraw
) {
1677 PRectangle rcClient
= GetClientRectangle();
1678 if (!view
.pixmapLine
->Initialised()) {
1680 view
.pixmapLine
->InitPixMap(static_cast<int>(rcClient
.Width()), vs
.lineHeight
,
1681 surfaceWindow
, wMain
.GetID());
1683 if (!marginView
.pixmapSelMargin
->Initialised()) {
1684 marginView
.pixmapSelMargin
->InitPixMap(vs
.fixedColumnWidth
,
1685 static_cast<int>(rcClient
.Height()), surfaceWindow
, wMain
.GetID());
1690 void Editor::Paint(Surface
*surfaceWindow
, PRectangle rcArea
) {
1691 //Platform::DebugPrintf("Paint:%1d (%3d,%3d) ... (%3d,%3d)\n",
1692 // paintingAllText, rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
1696 if (paintState
== paintAbandoned
)
1697 return; // Scroll bars may have changed so need redraw
1698 RefreshPixMaps(surfaceWindow
);
1700 paintAbandonedByStyling
= false;
1702 StyleAreaBounded(rcArea
, false);
1704 PRectangle rcClient
= GetClientRectangle();
1705 //Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d) %d\n",
1706 // rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
1708 if (NotifyUpdateUI()) {
1710 RefreshPixMaps(surfaceWindow
);
1713 // Wrap the visible lines if needed.
1714 if (WrapLines(wsVisible
)) {
1715 // The wrapping process has changed the height of some lines so
1716 // abandon this paint for a complete repaint.
1717 if (AbandonPaint()) {
1720 RefreshPixMaps(surfaceWindow
); // In case pixmaps invalidated by scrollbar change
1722 PLATFORM_ASSERT(marginView
.pixmapSelPattern
->Initialised());
1724 if (!view
.bufferedDraw
)
1725 surfaceWindow
->SetClip(rcArea
);
1727 if (paintState
!= paintAbandoned
) {
1728 if (vs
.marginInside
) {
1729 PaintSelMargin(surfaceWindow
, rcArea
);
1730 PRectangle rcRightMargin
= rcClient
;
1731 rcRightMargin
.left
= rcRightMargin
.right
- vs
.rightMarginWidth
;
1732 if (rcArea
.Intersects(rcRightMargin
)) {
1733 surfaceWindow
->FillRectangle(rcRightMargin
, vs
.styles
[STYLE_DEFAULT
].back
);
1735 } else { // Else separate view so separate paint event but leftMargin included to allow overlap
1736 PRectangle rcLeftMargin
= rcArea
;
1737 rcLeftMargin
.left
= 0;
1738 rcLeftMargin
.right
= rcLeftMargin
.left
+ vs
.leftMarginWidth
;
1739 if (rcArea
.Intersects(rcLeftMargin
)) {
1740 surfaceWindow
->FillRectangle(rcLeftMargin
, vs
.styles
[STYLE_DEFAULT
].back
);
1745 if (paintState
== paintAbandoned
) {
1746 // Either styling or NotifyUpdateUI noticed that painting is needed
1747 // outside the current painting rectangle
1748 //Platform::DebugPrintf("Abandoning paint\n");
1750 if (paintAbandonedByStyling
) {
1751 // Styling has spilled over a line end, such as occurs by starting a multiline
1752 // comment. The width of subsequent text may have changed, so rewrap.
1753 NeedWrapping(cs
.DocFromDisplay(topLine
));
1759 view
.PaintText(surfaceWindow
, *this, rcArea
, rcClient
, vs
);
1761 if (horizontalScrollBarVisible
&& trackLineWidth
&& (view
.lineWidthMaxSeen
> scrollWidth
)) {
1762 if (FineTickerAvailable()) {
1763 scrollWidth
= view
.lineWidthMaxSeen
;
1764 if (!FineTickerRunning(tickWiden
)) {
1765 FineTickerStart(tickWiden
, 50, 5);
1773 // This is mostly copied from the Paint method but with some things omitted
1774 // such as the margin markers, line numbers, selection and caret
1775 // Should be merged back into a combined Draw method.
1776 long Editor::FormatRange(bool draw
, Sci_RangeToFormat
*pfr
) {
1780 AutoSurface
surface(pfr
->hdc
, this, SC_TECHNOLOGY_DEFAULT
);
1783 AutoSurface
surfaceMeasure(pfr
->hdcTarget
, this, SC_TECHNOLOGY_DEFAULT
);
1784 if (!surfaceMeasure
) {
1787 return view
.FormatRange(draw
, pfr
, surface
, surfaceMeasure
, *this, vs
);
1790 int Editor::TextWidth(int style
, const char *text
) {
1792 AutoSurface
surface(this);
1794 return static_cast<int>(surface
->WidthText(vs
.styles
[style
].font
, text
, istrlen(text
)));
1800 // Empty method is overridden on GTK+ to show / hide scrollbars
1801 void Editor::ReconfigureScrollBars() {}
1803 void Editor::SetScrollBars() {
1806 int nMax
= MaxScrollPos();
1807 int nPage
= LinesOnScreen();
1808 bool modified
= ModifyScrollBars(nMax
+ nPage
- 1, nPage
);
1813 // TODO: ensure always showing as many lines as possible
1814 // May not be, if, for example, window made larger
1815 if (topLine
> MaxScrollPos()) {
1816 SetTopLine(Platform::Clamp(topLine
, 0, MaxScrollPos()));
1817 SetVerticalScrollPos();
1821 if (!AbandonPaint())
1824 //Platform::DebugPrintf("end max = %d page = %d\n", nMax, nPage);
1827 void Editor::ChangeSize() {
1828 DropGraphics(false);
1831 PRectangle rcTextArea
= GetClientRectangle();
1832 rcTextArea
.left
= static_cast<XYPOSITION
>(vs
.textStart
);
1833 rcTextArea
.right
-= vs
.rightMarginWidth
;
1834 if (wrapWidth
!= rcTextArea
.Width()) {
1841 int Editor::RealizeVirtualSpace(int position
, unsigned int virtualSpace
) {
1842 if (virtualSpace
> 0) {
1843 const int line
= pdoc
->LineFromPosition(position
);
1844 const int indent
= pdoc
->GetLineIndentPosition(line
);
1845 if (indent
== position
) {
1846 return pdoc
->SetLineIndentation(line
, pdoc
->GetLineIndentation(line
) + virtualSpace
);
1848 std::string
spaceText(virtualSpace
, ' ');
1849 const int lengthInserted
= pdoc
->InsertString(position
, spaceText
.c_str(), virtualSpace
);
1850 position
+= lengthInserted
;
1856 SelectionPosition
Editor::RealizeVirtualSpace(const SelectionPosition
&position
) {
1857 // Return the new position with no virtual space
1858 return SelectionPosition(RealizeVirtualSpace(position
.Position(), position
.VirtualSpace()));
1861 void Editor::AddChar(char ch
) {
1868 void Editor::FilterSelections() {
1869 if (!additionalSelectionTyping
&& (sel
.Count() > 1)) {
1870 InvalidateWholeSelection();
1871 sel
.DropAdditionalRanges();
1875 static bool cmpSelPtrs(const SelectionRange
*a
, const SelectionRange
*b
) {
1879 // AddCharUTF inserts an array of bytes which may or may not be in UTF-8.
1880 void Editor::AddCharUTF(const char *s
, unsigned int len
, bool treatAsDBCS
) {
1883 UndoGroup
ug(pdoc
, (sel
.Count() > 1) || !sel
.Empty() || inOverstrike
);
1885 // Vector elements point into selection in order to change selection.
1886 std::vector
<SelectionRange
*> selPtrs
;
1887 for (size_t r
= 0; r
< sel
.Count(); r
++) {
1888 selPtrs
.push_back(&sel
.Range(r
));
1890 // Order selections by position in document.
1891 std::sort(selPtrs
.begin(), selPtrs
.end(), cmpSelPtrs
);
1893 // Loop in reverse to avoid disturbing positions of selections yet to be processed.
1894 for (std::vector
<SelectionRange
*>::reverse_iterator rit
= selPtrs
.rbegin();
1895 rit
!= selPtrs
.rend(); ++rit
) {
1896 SelectionRange
*currentSel
= *rit
;
1897 if (!RangeContainsProtected(currentSel
->Start().Position(),
1898 currentSel
->End().Position())) {
1899 int positionInsert
= currentSel
->Start().Position();
1900 if (!currentSel
->Empty()) {
1901 if (currentSel
->Length()) {
1902 pdoc
->DeleteChars(positionInsert
, currentSel
->Length());
1903 currentSel
->ClearVirtualSpace();
1905 // Range is all virtual so collapse to start of virtual space
1906 currentSel
->MinimizeVirtualSpace();
1908 } else if (inOverstrike
) {
1909 if (positionInsert
< pdoc
->Length()) {
1910 if (!pdoc
->IsPositionInLineEnd(positionInsert
)) {
1911 pdoc
->DelChar(positionInsert
);
1912 currentSel
->ClearVirtualSpace();
1916 positionInsert
= RealizeVirtualSpace(positionInsert
, currentSel
->caret
.VirtualSpace());
1917 const int lengthInserted
= pdoc
->InsertString(positionInsert
, s
, len
);
1918 if (lengthInserted
> 0) {
1919 currentSel
->caret
.SetPosition(positionInsert
+ lengthInserted
);
1920 currentSel
->anchor
.SetPosition(positionInsert
+ lengthInserted
);
1922 currentSel
->ClearVirtualSpace();
1923 // If in wrap mode rewrap current line so EnsureCaretVisible has accurate information
1925 AutoSurface
surface(this);
1927 if (WrapOneLine(surface
, pdoc
->LineFromPosition(positionInsert
))) {
1929 SetVerticalScrollPos();
1940 ThinRectangularRange();
1941 // If in wrap mode rewrap current line so EnsureCaretVisible has accurate information
1942 EnsureCaretVisible();
1943 // Avoid blinking during rapid typing:
1944 ShowCaretAtCurrentPosition();
1945 if ((caretSticky
== SC_CARETSTICKY_OFF
) ||
1946 ((caretSticky
== SC_CARETSTICKY_WHITESPACE
) && !IsAllSpacesOrTabs(s
, len
))) {
1951 NotifyChar((static_cast<unsigned char>(s
[0]) << 8) |
1952 static_cast<unsigned char>(s
[1]));
1953 } else if (len
> 0) {
1954 int byte
= static_cast<unsigned char>(s
[0]);
1955 if ((byte
< 0xC0) || (1 == len
)) {
1956 // Handles UTF-8 characters between 0x01 and 0x7F and single byte
1957 // characters when not in UTF-8 mode.
1958 // Also treats \0 and naked trail bytes 0x80 to 0xBF as valid
1959 // characters representing themselves.
1961 unsigned int utf32
[1] = { 0 };
1962 UTF32FromUTF8(s
, len
, utf32
, ELEMENTS(utf32
));
1968 if (recordingMacro
) {
1969 NotifyMacroRecord(SCI_REPLACESEL
, 0, reinterpret_cast<sptr_t
>(s
));
1973 void Editor::ClearBeforeTentativeStart() {
1974 // Make positions for the first composition string.
1976 UndoGroup
ug(pdoc
, (sel
.Count() > 1) || !sel
.Empty() || inOverstrike
);
1977 for (size_t r
= 0; r
<sel
.Count(); r
++) {
1978 if (!RangeContainsProtected(sel
.Range(r
).Start().Position(),
1979 sel
.Range(r
).End().Position())) {
1980 int positionInsert
= sel
.Range(r
).Start().Position();
1981 if (!sel
.Range(r
).Empty()) {
1982 if (sel
.Range(r
).Length()) {
1983 pdoc
->DeleteChars(positionInsert
, sel
.Range(r
).Length());
1984 sel
.Range(r
).ClearVirtualSpace();
1986 // Range is all virtual so collapse to start of virtual space
1987 sel
.Range(r
).MinimizeVirtualSpace();
1990 RealizeVirtualSpace(positionInsert
, sel
.Range(r
).caret
.VirtualSpace());
1991 sel
.Range(r
).ClearVirtualSpace();
1996 void Editor::InsertPaste(const char *text
, int len
) {
1997 if (multiPasteMode
== SC_MULTIPASTE_ONCE
) {
1998 SelectionPosition selStart
= sel
.Start();
1999 selStart
= RealizeVirtualSpace(selStart
);
2000 const int lengthInserted
= pdoc
->InsertString(selStart
.Position(), text
, len
);
2001 if (lengthInserted
> 0) {
2002 SetEmptySelection(selStart
.Position() + lengthInserted
);
2005 // SC_MULTIPASTE_EACH
2006 for (size_t r
=0; r
<sel
.Count(); r
++) {
2007 if (!RangeContainsProtected(sel
.Range(r
).Start().Position(),
2008 sel
.Range(r
).End().Position())) {
2009 int positionInsert
= sel
.Range(r
).Start().Position();
2010 if (!sel
.Range(r
).Empty()) {
2011 if (sel
.Range(r
).Length()) {
2012 pdoc
->DeleteChars(positionInsert
, sel
.Range(r
).Length());
2013 sel
.Range(r
).ClearVirtualSpace();
2015 // Range is all virtual so collapse to start of virtual space
2016 sel
.Range(r
).MinimizeVirtualSpace();
2019 positionInsert
= RealizeVirtualSpace(positionInsert
, sel
.Range(r
).caret
.VirtualSpace());
2020 const int lengthInserted
= pdoc
->InsertString(positionInsert
, text
, len
);
2021 if (lengthInserted
> 0) {
2022 sel
.Range(r
).caret
.SetPosition(positionInsert
+ lengthInserted
);
2023 sel
.Range(r
).anchor
.SetPosition(positionInsert
+ lengthInserted
);
2025 sel
.Range(r
).ClearVirtualSpace();
2031 void Editor::InsertPasteShape(const char *text
, int len
, PasteShape shape
) {
2032 std::string convertedText
;
2033 if (convertPastes
) {
2034 // Convert line endings of the paste into our local line-endings mode
2035 convertedText
= Document::TransformLineEnds(text
, len
, pdoc
->eolMode
);
2036 len
= static_cast<int>(convertedText
.length());
2037 text
= convertedText
.c_str();
2039 if (shape
== pasteRectangular
) {
2040 PasteRectangular(sel
.Start(), text
, len
);
2042 if (shape
== pasteLine
) {
2043 int insertPos
= pdoc
->LineStart(pdoc
->LineFromPosition(sel
.MainCaret()));
2044 int lengthInserted
= pdoc
->InsertString(insertPos
, text
, len
);
2045 // add the newline if necessary
2046 if ((len
> 0) && (text
[len
- 1] != '\n' && text
[len
- 1] != '\r')) {
2047 const char *endline
= StringFromEOLMode(pdoc
->eolMode
);
2048 int length
= static_cast<int>(strlen(endline
));
2049 lengthInserted
+= pdoc
->InsertString(insertPos
+ lengthInserted
, endline
, length
);
2051 if (sel
.MainCaret() == insertPos
) {
2052 SetEmptySelection(sel
.MainCaret() + lengthInserted
);
2055 InsertPaste(text
, len
);
2060 void Editor::ClearSelection(bool retainMultipleSelections
) {
2061 if (!sel
.IsRectangular() && !retainMultipleSelections
)
2064 for (size_t r
=0; r
<sel
.Count(); r
++) {
2065 if (!sel
.Range(r
).Empty()) {
2066 if (!RangeContainsProtected(sel
.Range(r
).Start().Position(),
2067 sel
.Range(r
).End().Position())) {
2068 pdoc
->DeleteChars(sel
.Range(r
).Start().Position(),
2069 sel
.Range(r
).Length());
2070 sel
.Range(r
) = SelectionRange(sel
.Range(r
).Start());
2074 ThinRectangularRange();
2075 sel
.RemoveDuplicates();
2077 SetHoverIndicatorPosition(sel
.MainCaret());
2080 void Editor::ClearAll() {
2083 if (0 != pdoc
->Length()) {
2084 pdoc
->DeleteChars(0, pdoc
->Length());
2086 if (!pdoc
->IsReadOnly()) {
2088 pdoc
->AnnotationClearAll();
2089 pdoc
->MarginClearAll();
2093 view
.ClearAllTabstops();
2097 SetVerticalScrollPos();
2098 InvalidateStyleRedraw();
2101 void Editor::ClearDocumentStyle() {
2102 Decoration
*deco
= pdoc
->decorations
.root
;
2104 // Save next in case deco deleted
2105 Decoration
*decoNext
= deco
->next
;
2106 if (deco
->indicator
< INDIC_CONTAINER
) {
2107 pdoc
->decorations
.SetCurrentIndicator(deco
->indicator
);
2108 pdoc
->DecorationFillRange(0, 0, pdoc
->Length());
2112 pdoc
->StartStyling(0, '\377');
2113 pdoc
->SetStyleFor(pdoc
->Length(), 0);
2115 SetAnnotationHeights(0, pdoc
->LinesTotal());
2116 pdoc
->ClearLevels();
2119 void Editor::CopyAllowLine() {
2120 SelectionText selectedText
;
2121 CopySelectionRange(&selectedText
, true);
2122 CopyToClipboard(selectedText
);
2125 void Editor::Cut() {
2126 pdoc
->CheckReadOnly();
2127 if (!pdoc
->IsReadOnly() && !SelectionContainsProtected()) {
2133 void Editor::PasteRectangular(SelectionPosition pos
, const char *ptr
, int len
) {
2134 if (pdoc
->IsReadOnly() || SelectionContainsProtected()) {
2138 sel
.RangeMain() = SelectionRange(pos
);
2139 int line
= pdoc
->LineFromPosition(sel
.MainCaret());
2141 sel
.RangeMain().caret
= RealizeVirtualSpace(sel
.RangeMain().caret
);
2142 int xInsert
= XFromPosition(sel
.RangeMain().caret
);
2143 bool prevCr
= false;
2144 while ((len
> 0) && IsEOLChar(ptr
[len
-1]))
2146 for (int i
= 0; i
< len
; i
++) {
2147 if (IsEOLChar(ptr
[i
])) {
2148 if ((ptr
[i
] == '\r') || (!prevCr
))
2150 if (line
>= pdoc
->LinesTotal()) {
2151 if (pdoc
->eolMode
!= SC_EOL_LF
)
2152 pdoc
->InsertString(pdoc
->Length(), "\r", 1);
2153 if (pdoc
->eolMode
!= SC_EOL_CR
)
2154 pdoc
->InsertString(pdoc
->Length(), "\n", 1);
2156 // Pad the end of lines with spaces if required
2157 sel
.RangeMain().caret
.SetPosition(PositionFromLineX(line
, xInsert
));
2158 if ((XFromPosition(sel
.MainCaret()) < xInsert
) && (i
+ 1 < len
)) {
2159 while (XFromPosition(sel
.MainCaret()) < xInsert
) {
2161 const int lengthInserted
= pdoc
->InsertString(sel
.MainCaret(), " ", 1);
2162 sel
.RangeMain().caret
.Add(lengthInserted
);
2165 prevCr
= ptr
[i
] == '\r';
2167 const int lengthInserted
= pdoc
->InsertString(sel
.MainCaret(), ptr
+ i
, 1);
2168 sel
.RangeMain().caret
.Add(lengthInserted
);
2172 SetEmptySelection(pos
);
2175 bool Editor::CanPaste() {
2176 return !pdoc
->IsReadOnly() && !SelectionContainsProtected();
2179 void Editor::Clear() {
2180 // If multiple selections, don't delete EOLS
2182 bool singleVirtual
= false;
2183 if ((sel
.Count() == 1) &&
2184 !RangeContainsProtected(sel
.MainCaret(), sel
.MainCaret() + 1) &&
2185 sel
.RangeMain().Start().VirtualSpace()) {
2186 singleVirtual
= true;
2188 UndoGroup
ug(pdoc
, (sel
.Count() > 1) || singleVirtual
);
2189 for (size_t r
=0; r
<sel
.Count(); r
++) {
2190 if (!RangeContainsProtected(sel
.Range(r
).caret
.Position(), sel
.Range(r
).caret
.Position() + 1)) {
2191 if (sel
.Range(r
).Start().VirtualSpace()) {
2192 if (sel
.Range(r
).anchor
< sel
.Range(r
).caret
)
2193 sel
.Range(r
) = SelectionRange(RealizeVirtualSpace(sel
.Range(r
).anchor
.Position(), sel
.Range(r
).anchor
.VirtualSpace()));
2195 sel
.Range(r
) = SelectionRange(RealizeVirtualSpace(sel
.Range(r
).caret
.Position(), sel
.Range(r
).caret
.VirtualSpace()));
2197 if ((sel
.Count() == 1) || !pdoc
->IsPositionInLineEnd(sel
.Range(r
).caret
.Position())) {
2198 pdoc
->DelChar(sel
.Range(r
).caret
.Position());
2199 sel
.Range(r
).ClearVirtualSpace();
2200 } // else multiple selection so don't eat line ends
2202 sel
.Range(r
).ClearVirtualSpace();
2208 sel
.RemoveDuplicates();
2209 ShowCaretAtCurrentPosition(); // Avoid blinking
2212 void Editor::SelectAll() {
2214 SetSelection(0, pdoc
->Length());
2218 void Editor::Undo() {
2219 if (pdoc
->CanUndo()) {
2221 int newPos
= pdoc
->Undo();
2223 SetEmptySelection(newPos
);
2224 EnsureCaretVisible();
2228 void Editor::Redo() {
2229 if (pdoc
->CanRedo()) {
2230 int newPos
= pdoc
->Redo();
2232 SetEmptySelection(newPos
);
2233 EnsureCaretVisible();
2237 void Editor::DelCharBack(bool allowLineStartDeletion
) {
2239 if (!sel
.IsRectangular())
2241 if (sel
.IsRectangular())
2242 allowLineStartDeletion
= false;
2243 UndoGroup
ug(pdoc
, (sel
.Count() > 1) || !sel
.Empty());
2245 for (size_t r
=0; r
<sel
.Count(); r
++) {
2246 if (!RangeContainsProtected(sel
.Range(r
).caret
.Position() - 1, sel
.Range(r
).caret
.Position())) {
2247 if (sel
.Range(r
).caret
.VirtualSpace()) {
2248 sel
.Range(r
).caret
.SetVirtualSpace(sel
.Range(r
).caret
.VirtualSpace() - 1);
2249 sel
.Range(r
).anchor
.SetVirtualSpace(sel
.Range(r
).caret
.VirtualSpace());
2251 int lineCurrentPos
= pdoc
->LineFromPosition(sel
.Range(r
).caret
.Position());
2252 if (allowLineStartDeletion
|| (pdoc
->LineStart(lineCurrentPos
) != sel
.Range(r
).caret
.Position())) {
2253 if (pdoc
->GetColumn(sel
.Range(r
).caret
.Position()) <= pdoc
->GetLineIndentation(lineCurrentPos
) &&
2254 pdoc
->GetColumn(sel
.Range(r
).caret
.Position()) > 0 && pdoc
->backspaceUnindents
) {
2255 UndoGroup
ugInner(pdoc
, !ug
.Needed());
2256 int indentation
= pdoc
->GetLineIndentation(lineCurrentPos
);
2257 int indentationStep
= pdoc
->IndentSize();
2258 int indentationChange
= indentation
% indentationStep
;
2259 if (indentationChange
== 0)
2260 indentationChange
= indentationStep
;
2261 const int posSelect
= pdoc
->SetLineIndentation(lineCurrentPos
, indentation
- indentationChange
);
2262 // SetEmptySelection
2263 sel
.Range(r
) = SelectionRange(posSelect
);
2265 pdoc
->DelCharBack(sel
.Range(r
).caret
.Position());
2270 sel
.Range(r
).ClearVirtualSpace();
2273 ThinRectangularRange();
2277 sel
.RemoveDuplicates();
2278 ContainerNeedsUpdate(SC_UPDATE_SELECTION
);
2279 // Avoid blinking during rapid typing:
2280 ShowCaretAtCurrentPosition();
2283 int Editor::ModifierFlags(bool shift
, bool ctrl
, bool alt
, bool meta
, bool super
) {
2285 (shift
? SCI_SHIFT
: 0) |
2286 (ctrl
? SCI_CTRL
: 0) |
2287 (alt
? SCI_ALT
: 0) |
2288 (meta
? SCI_META
: 0) |
2289 (super
? SCI_SUPER
: 0);
2292 void Editor::NotifyFocus(bool focus
) {
2293 SCNotification scn
= {};
2294 scn
.nmhdr
.code
= focus
? SCN_FOCUSIN
: SCN_FOCUSOUT
;
2298 void Editor::SetCtrlID(int identifier
) {
2299 ctrlID
= identifier
;
2302 void Editor::NotifyStyleToNeeded(int endStyleNeeded
) {
2303 SCNotification scn
= {};
2304 scn
.nmhdr
.code
= SCN_STYLENEEDED
;
2305 scn
.position
= endStyleNeeded
;
2309 void Editor::NotifyStyleNeeded(Document
*, void *, int endStyleNeeded
) {
2310 NotifyStyleToNeeded(endStyleNeeded
);
2313 void Editor::NotifyLexerChanged(Document
*, void *) {
2316 void Editor::NotifyErrorOccurred(Document
*, void *, int status
) {
2317 errorStatus
= status
;
2320 void Editor::NotifyChar(int ch
) {
2321 SCNotification scn
= {};
2322 scn
.nmhdr
.code
= SCN_CHARADDED
;
2327 void Editor::NotifySavePoint(bool isSavePoint
) {
2328 SCNotification scn
= {};
2330 scn
.nmhdr
.code
= SCN_SAVEPOINTREACHED
;
2332 scn
.nmhdr
.code
= SCN_SAVEPOINTLEFT
;
2337 void Editor::NotifyModifyAttempt() {
2338 SCNotification scn
= {};
2339 scn
.nmhdr
.code
= SCN_MODIFYATTEMPTRO
;
2343 void Editor::NotifyDoubleClick(Point pt
, int modifiers
) {
2344 SCNotification scn
= {};
2345 scn
.nmhdr
.code
= SCN_DOUBLECLICK
;
2346 scn
.line
= LineFromLocation(pt
);
2347 scn
.position
= PositionFromLocation(pt
, true);
2348 scn
.modifiers
= modifiers
;
2352 void Editor::NotifyDoubleClick(Point pt
, bool shift
, bool ctrl
, bool alt
) {
2353 NotifyDoubleClick(pt
, ModifierFlags(shift
, ctrl
, alt
));
2356 void Editor::NotifyHotSpotDoubleClicked(int position
, int modifiers
) {
2357 SCNotification scn
= {};
2358 scn
.nmhdr
.code
= SCN_HOTSPOTDOUBLECLICK
;
2359 scn
.position
= position
;
2360 scn
.modifiers
= modifiers
;
2364 void Editor::NotifyHotSpotDoubleClicked(int position
, bool shift
, bool ctrl
, bool alt
) {
2365 NotifyHotSpotDoubleClicked(position
, ModifierFlags(shift
, ctrl
, alt
));
2368 void Editor::NotifyHotSpotClicked(int position
, int modifiers
) {
2369 SCNotification scn
= {};
2370 scn
.nmhdr
.code
= SCN_HOTSPOTCLICK
;
2371 scn
.position
= position
;
2372 scn
.modifiers
= modifiers
;
2376 void Editor::NotifyHotSpotClicked(int position
, bool shift
, bool ctrl
, bool alt
) {
2377 NotifyHotSpotClicked(position
, ModifierFlags(shift
, ctrl
, alt
));
2380 void Editor::NotifyHotSpotReleaseClick(int position
, int modifiers
) {
2381 SCNotification scn
= {};
2382 scn
.nmhdr
.code
= SCN_HOTSPOTRELEASECLICK
;
2383 scn
.position
= position
;
2384 scn
.modifiers
= modifiers
;
2388 void Editor::NotifyHotSpotReleaseClick(int position
, bool shift
, bool ctrl
, bool alt
) {
2389 NotifyHotSpotReleaseClick(position
, ModifierFlags(shift
, ctrl
, alt
));
2392 bool Editor::NotifyUpdateUI() {
2394 SCNotification scn
= {};
2395 scn
.nmhdr
.code
= SCN_UPDATEUI
;
2396 scn
.updated
= needUpdateUI
;
2404 void Editor::NotifyPainted() {
2405 SCNotification scn
= {};
2406 scn
.nmhdr
.code
= SCN_PAINTED
;
2410 void Editor::NotifyIndicatorClick(bool click
, int position
, int modifiers
) {
2411 int mask
= pdoc
->decorations
.AllOnFor(position
);
2412 if ((click
&& mask
) || pdoc
->decorations
.clickNotified
) {
2413 SCNotification scn
= {};
2414 pdoc
->decorations
.clickNotified
= click
;
2415 scn
.nmhdr
.code
= click
? SCN_INDICATORCLICK
: SCN_INDICATORRELEASE
;
2416 scn
.modifiers
= modifiers
;
2417 scn
.position
= position
;
2422 void Editor::NotifyIndicatorClick(bool click
, int position
, bool shift
, bool ctrl
, bool alt
) {
2423 NotifyIndicatorClick(click
, position
, ModifierFlags(shift
, ctrl
, alt
));
2426 bool Editor::NotifyMarginClick(Point pt
, int modifiers
) {
2427 const int marginClicked
= vs
.MarginFromLocation(pt
);
2428 if ((marginClicked
>= 0) && vs
.ms
[marginClicked
].sensitive
) {
2429 int position
= pdoc
->LineStart(LineFromLocation(pt
));
2430 if ((vs
.ms
[marginClicked
].mask
& SC_MASK_FOLDERS
) && (foldAutomatic
& SC_AUTOMATICFOLD_CLICK
)) {
2431 const bool ctrl
= (modifiers
& SCI_CTRL
) != 0;
2432 const bool shift
= (modifiers
& SCI_SHIFT
) != 0;
2433 int lineClick
= pdoc
->LineFromPosition(position
);
2434 if (shift
&& ctrl
) {
2435 FoldAll(SC_FOLDACTION_TOGGLE
);
2437 int levelClick
= pdoc
->GetLevel(lineClick
);
2438 if (levelClick
& SC_FOLDLEVELHEADERFLAG
) {
2440 // Ensure all children visible
2441 FoldExpand(lineClick
, SC_FOLDACTION_EXPAND
, levelClick
);
2443 FoldExpand(lineClick
, SC_FOLDACTION_TOGGLE
, levelClick
);
2446 FoldLine(lineClick
, SC_FOLDACTION_TOGGLE
);
2452 SCNotification scn
= {};
2453 scn
.nmhdr
.code
= SCN_MARGINCLICK
;
2454 scn
.modifiers
= modifiers
;
2455 scn
.position
= position
;
2456 scn
.margin
= marginClicked
;
2464 bool Editor::NotifyMarginClick(Point pt
, bool shift
, bool ctrl
, bool alt
) {
2465 return NotifyMarginClick(pt
, ModifierFlags(shift
, ctrl
, alt
));
2468 bool Editor::NotifyMarginRightClick(Point pt
, int modifiers
) {
2469 int marginRightClicked
= vs
.MarginFromLocation(pt
);
2470 if ((marginRightClicked
>= 0) && vs
.ms
[marginRightClicked
].sensitive
) {
2471 int position
= pdoc
->LineStart(LineFromLocation(pt
));
2472 SCNotification scn
= {};
2473 scn
.nmhdr
.code
= SCN_MARGINRIGHTCLICK
;
2474 scn
.modifiers
= modifiers
;
2475 scn
.position
= position
;
2476 scn
.margin
= marginRightClicked
;
2484 void Editor::NotifyNeedShown(int pos
, int len
) {
2485 SCNotification scn
= {};
2486 scn
.nmhdr
.code
= SCN_NEEDSHOWN
;
2492 void Editor::NotifyDwelling(Point pt
, bool state
) {
2493 SCNotification scn
= {};
2494 scn
.nmhdr
.code
= state
? SCN_DWELLSTART
: SCN_DWELLEND
;
2495 scn
.position
= PositionFromLocation(pt
, true);
2496 scn
.x
= static_cast<int>(pt
.x
+ vs
.ExternalMarginWidth());
2497 scn
.y
= static_cast<int>(pt
.y
);
2501 void Editor::NotifyZoom() {
2502 SCNotification scn
= {};
2503 scn
.nmhdr
.code
= SCN_ZOOM
;
2507 // Notifications from document
2508 void Editor::NotifyModifyAttempt(Document
*, void *) {
2509 //Platform::DebugPrintf("** Modify Attempt\n");
2510 NotifyModifyAttempt();
2513 void Editor::NotifySavePoint(Document
*, void *, bool atSavePoint
) {
2514 //Platform::DebugPrintf("** Save Point %s\n", atSavePoint ? "On" : "Off");
2515 NotifySavePoint(atSavePoint
);
2518 void Editor::CheckModificationForWrap(DocModification mh
) {
2519 if (mh
.modificationType
& (SC_MOD_INSERTTEXT
| SC_MOD_DELETETEXT
)) {
2520 view
.llc
.Invalidate(LineLayout::llCheckTextAndStyle
);
2521 int lineDoc
= pdoc
->LineFromPosition(mh
.position
);
2522 int lines
= Platform::Maximum(0, mh
.linesAdded
);
2524 NeedWrapping(lineDoc
, lineDoc
+ lines
+ 1);
2527 // Fix up annotation heights
2528 SetAnnotationHeights(lineDoc
, lineDoc
+ lines
+ 2);
2532 // Move a position so it is still after the same character as before the insertion.
2533 static inline int MovePositionForInsertion(int position
, int startInsertion
, int length
) {
2534 if (position
> startInsertion
) {
2535 return position
+ length
;
2540 // Move a position so it is still after the same character as before the deletion if that
2541 // character is still present else after the previous surviving character.
2542 static inline int MovePositionForDeletion(int position
, int startDeletion
, int length
) {
2543 if (position
> startDeletion
) {
2544 int endDeletion
= startDeletion
+ length
;
2545 if (position
> endDeletion
) {
2546 return position
- length
;
2548 return startDeletion
;
2555 void Editor::NotifyModified(Document
*, DocModification mh
, void *) {
2556 ContainerNeedsUpdate(SC_UPDATE_CONTENT
);
2557 if (paintState
== painting
) {
2558 CheckForChangeOutsidePaint(Range(mh
.position
, mh
.position
+ mh
.length
));
2560 if (mh
.modificationType
& SC_MOD_CHANGELINESTATE
) {
2561 if (paintState
== painting
) {
2562 CheckForChangeOutsidePaint(
2563 Range(pdoc
->LineStart(mh
.line
), pdoc
->LineStart(mh
.line
+ 1)));
2565 // Could check that change is before last visible line.
2569 if (mh
.modificationType
& SC_MOD_CHANGETABSTOPS
) {
2572 if (mh
.modificationType
& SC_MOD_LEXERSTATE
) {
2573 if (paintState
== painting
) {
2574 CheckForChangeOutsidePaint(
2575 Range(mh
.position
, mh
.position
+ mh
.length
));
2580 if (mh
.modificationType
& (SC_MOD_CHANGESTYLE
| SC_MOD_CHANGEINDICATOR
)) {
2581 if (mh
.modificationType
& SC_MOD_CHANGESTYLE
) {
2582 pdoc
->IncrementStyleClock();
2584 if (paintState
== notPainting
) {
2585 if (mh
.position
< pdoc
->LineStart(topLine
)) {
2586 // Styling performed before this view
2589 InvalidateRange(mh
.position
, mh
.position
+ mh
.length
);
2592 if (mh
.modificationType
& SC_MOD_CHANGESTYLE
) {
2593 view
.llc
.Invalidate(LineLayout::llCheckTextAndStyle
);
2596 // Move selection and brace highlights
2597 if (mh
.modificationType
& SC_MOD_INSERTTEXT
) {
2598 sel
.MovePositions(true, mh
.position
, mh
.length
);
2599 braces
[0] = MovePositionForInsertion(braces
[0], mh
.position
, mh
.length
);
2600 braces
[1] = MovePositionForInsertion(braces
[1], mh
.position
, mh
.length
);
2601 } else if (mh
.modificationType
& SC_MOD_DELETETEXT
) {
2602 sel
.MovePositions(false, mh
.position
, mh
.length
);
2603 braces
[0] = MovePositionForDeletion(braces
[0], mh
.position
, mh
.length
);
2604 braces
[1] = MovePositionForDeletion(braces
[1], mh
.position
, mh
.length
);
2606 if ((mh
.modificationType
& (SC_MOD_BEFOREINSERT
| SC_MOD_BEFOREDELETE
)) && cs
.HiddenLines()) {
2607 // Some lines are hidden so may need shown.
2608 const int lineOfPos
= pdoc
->LineFromPosition(mh
.position
);
2609 int endNeedShown
= mh
.position
;
2610 if (mh
.modificationType
& SC_MOD_BEFOREINSERT
) {
2611 if (pdoc
->ContainsLineEnd(mh
.text
, mh
.length
) && (mh
.position
!= pdoc
->LineStart(lineOfPos
)))
2612 endNeedShown
= pdoc
->LineStart(lineOfPos
+1);
2613 } else if (mh
.modificationType
& SC_MOD_BEFOREDELETE
) {
2614 // If the deletion includes any EOL then we extend the need shown area.
2615 endNeedShown
= mh
.position
+ mh
.length
;
2616 int lineLast
= pdoc
->LineFromPosition(mh
.position
+mh
.length
);
2617 for (int line
= lineOfPos
+ 1; line
<= lineLast
; line
++) {
2618 const int lineMaxSubord
= pdoc
->GetLastChild(line
, -1, -1);
2619 if (lineLast
< lineMaxSubord
) {
2620 lineLast
= lineMaxSubord
;
2621 endNeedShown
= pdoc
->LineEnd(lineLast
);
2625 NeedShown(mh
.position
, endNeedShown
- mh
.position
);
2627 if (mh
.linesAdded
!= 0) {
2628 // Update contraction state for inserted and removed lines
2629 // lineOfPos should be calculated in context of state before modification, shouldn't it
2630 int lineOfPos
= pdoc
->LineFromPosition(mh
.position
);
2631 if (mh
.position
> pdoc
->LineStart(lineOfPos
))
2632 lineOfPos
++; // Affecting subsequent lines
2633 if (mh
.linesAdded
> 0) {
2634 cs
.InsertLines(lineOfPos
, mh
.linesAdded
);
2636 cs
.DeleteLines(lineOfPos
, -mh
.linesAdded
);
2638 view
.LinesAddedOrRemoved(lineOfPos
, mh
.linesAdded
);
2640 if (mh
.modificationType
& SC_MOD_CHANGEANNOTATION
) {
2641 int lineDoc
= pdoc
->LineFromPosition(mh
.position
);
2642 if (vs
.annotationVisible
) {
2643 cs
.SetHeight(lineDoc
, cs
.GetHeight(lineDoc
) + mh
.annotationLinesAdded
);
2647 CheckModificationForWrap(mh
);
2648 if (mh
.linesAdded
!= 0) {
2649 // Avoid scrolling of display if change before current display
2650 if (mh
.position
< posTopLine
&& !CanDeferToLastStep(mh
)) {
2651 int newTop
= Platform::Clamp(topLine
+ mh
.linesAdded
, 0, MaxScrollPos());
2652 if (newTop
!= topLine
) {
2654 SetVerticalScrollPos();
2658 if (paintState
== notPainting
&& !CanDeferToLastStep(mh
)) {
2659 QueueIdleWork(WorkNeeded::workStyle
, pdoc
->Length());
2663 if (paintState
== notPainting
&& mh
.length
&& !CanEliminate(mh
)) {
2664 QueueIdleWork(WorkNeeded::workStyle
, mh
.position
+ mh
.length
);
2665 InvalidateRange(mh
.position
, mh
.position
+ mh
.length
);
2670 if (mh
.linesAdded
!= 0 && !CanDeferToLastStep(mh
)) {
2674 if ((mh
.modificationType
& SC_MOD_CHANGEMARKER
) || (mh
.modificationType
& SC_MOD_CHANGEMARGIN
)) {
2675 if ((!willRedrawAll
) && ((paintState
== notPainting
) || !PaintContainsMargin())) {
2676 if (mh
.modificationType
& SC_MOD_CHANGEFOLD
) {
2677 // Fold changes can affect the drawing of following lines so redraw whole margin
2678 RedrawSelMargin(marginView
.highlightDelimiter
.isEnabled
? -1 : mh
.line
- 1, true);
2680 RedrawSelMargin(mh
.line
);
2684 if ((mh
.modificationType
& SC_MOD_CHANGEFOLD
) && (foldAutomatic
& SC_AUTOMATICFOLD_CHANGE
)) {
2685 FoldChanged(mh
.line
, mh
.foldLevelNow
, mh
.foldLevelPrev
);
2688 // NOW pay the piper WRT "deferred" visual updates
2689 if (IsLastStep(mh
)) {
2694 // If client wants to see this modification
2695 if (mh
.modificationType
& modEventMask
) {
2696 if ((mh
.modificationType
& (SC_MOD_CHANGESTYLE
| SC_MOD_CHANGEINDICATOR
)) == 0) {
2697 // Real modification made to text of document.
2698 NotifyChange(); // Send EN_CHANGE
2701 SCNotification scn
= {};
2702 scn
.nmhdr
.code
= SCN_MODIFIED
;
2703 scn
.position
= mh
.position
;
2704 scn
.modificationType
= mh
.modificationType
;
2706 scn
.length
= mh
.length
;
2707 scn
.linesAdded
= mh
.linesAdded
;
2709 scn
.foldLevelNow
= mh
.foldLevelNow
;
2710 scn
.foldLevelPrev
= mh
.foldLevelPrev
;
2711 scn
.token
= mh
.token
;
2712 scn
.annotationLinesAdded
= mh
.annotationLinesAdded
;
2717 void Editor::NotifyDeleted(Document
*, void *) {
2721 void Editor::NotifyMacroRecord(unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
) {
2723 // Enumerates all macroable messages
2729 case SCI_REPLACESEL
:
2731 case SCI_INSERTTEXT
:
2732 case SCI_APPENDTEXT
:
2737 case SCI_SEARCHANCHOR
:
2738 case SCI_SEARCHNEXT
:
2739 case SCI_SEARCHPREV
:
2741 case SCI_LINEDOWNEXTEND
:
2743 case SCI_PARADOWNEXTEND
:
2745 case SCI_LINEUPEXTEND
:
2747 case SCI_PARAUPEXTEND
:
2749 case SCI_CHARLEFTEXTEND
:
2751 case SCI_CHARRIGHTEXTEND
:
2753 case SCI_WORDLEFTEXTEND
:
2755 case SCI_WORDRIGHTEXTEND
:
2756 case SCI_WORDPARTLEFT
:
2757 case SCI_WORDPARTLEFTEXTEND
:
2758 case SCI_WORDPARTRIGHT
:
2759 case SCI_WORDPARTRIGHTEXTEND
:
2760 case SCI_WORDLEFTEND
:
2761 case SCI_WORDLEFTENDEXTEND
:
2762 case SCI_WORDRIGHTEND
:
2763 case SCI_WORDRIGHTENDEXTEND
:
2765 case SCI_HOMEEXTEND
:
2767 case SCI_LINEENDEXTEND
:
2769 case SCI_HOMEWRAPEXTEND
:
2770 case SCI_LINEENDWRAP
:
2771 case SCI_LINEENDWRAPEXTEND
:
2772 case SCI_DOCUMENTSTART
:
2773 case SCI_DOCUMENTSTARTEXTEND
:
2774 case SCI_DOCUMENTEND
:
2775 case SCI_DOCUMENTENDEXTEND
:
2776 case SCI_STUTTEREDPAGEUP
:
2777 case SCI_STUTTEREDPAGEUPEXTEND
:
2778 case SCI_STUTTEREDPAGEDOWN
:
2779 case SCI_STUTTEREDPAGEDOWNEXTEND
:
2781 case SCI_PAGEUPEXTEND
:
2783 case SCI_PAGEDOWNEXTEND
:
2784 case SCI_EDITTOGGLEOVERTYPE
:
2786 case SCI_DELETEBACK
:
2791 case SCI_VCHOMEEXTEND
:
2792 case SCI_VCHOMEWRAP
:
2793 case SCI_VCHOMEWRAPEXTEND
:
2794 case SCI_VCHOMEDISPLAY
:
2795 case SCI_VCHOMEDISPLAYEXTEND
:
2796 case SCI_DELWORDLEFT
:
2797 case SCI_DELWORDRIGHT
:
2798 case SCI_DELWORDRIGHTEND
:
2799 case SCI_DELLINELEFT
:
2800 case SCI_DELLINERIGHT
:
2803 case SCI_LINEDELETE
:
2804 case SCI_LINETRANSPOSE
:
2805 case SCI_LINEDUPLICATE
:
2808 case SCI_LINESCROLLDOWN
:
2809 case SCI_LINESCROLLUP
:
2810 case SCI_DELETEBACKNOTLINE
:
2811 case SCI_HOMEDISPLAY
:
2812 case SCI_HOMEDISPLAYEXTEND
:
2813 case SCI_LINEENDDISPLAY
:
2814 case SCI_LINEENDDISPLAYEXTEND
:
2815 case SCI_SETSELECTIONMODE
:
2816 case SCI_LINEDOWNRECTEXTEND
:
2817 case SCI_LINEUPRECTEXTEND
:
2818 case SCI_CHARLEFTRECTEXTEND
:
2819 case SCI_CHARRIGHTRECTEXTEND
:
2820 case SCI_HOMERECTEXTEND
:
2821 case SCI_VCHOMERECTEXTEND
:
2822 case SCI_LINEENDRECTEXTEND
:
2823 case SCI_PAGEUPRECTEXTEND
:
2824 case SCI_PAGEDOWNRECTEXTEND
:
2825 case SCI_SELECTIONDUPLICATE
:
2826 case SCI_COPYALLOWLINE
:
2827 case SCI_VERTICALCENTRECARET
:
2828 case SCI_MOVESELECTEDLINESUP
:
2829 case SCI_MOVESELECTEDLINESDOWN
:
2830 case SCI_SCROLLTOSTART
:
2831 case SCI_SCROLLTOEND
:
2834 // Filter out all others like display changes. Also, newlines are redundant
2835 // with char insert messages.
2838 // printf("Filtered out %ld of macro recording\n", iMessage);
2842 // Send notification
2843 SCNotification scn
= {};
2844 scn
.nmhdr
.code
= SCN_MACRORECORD
;
2845 scn
.message
= iMessage
;
2846 scn
.wParam
= wParam
;
2847 scn
.lParam
= lParam
;
2851 // Something has changed that the container should know about
2852 void Editor::ContainerNeedsUpdate(int flags
) {
2853 needUpdateUI
|= flags
;
2857 * Force scroll and keep position relative to top of window.
2859 * If stuttered = true and not already at first/last row, move to first/last row of window.
2860 * If stuttered = true and already at first/last row, scroll as normal.
2862 void Editor::PageMove(int direction
, Selection::selTypes selt
, bool stuttered
) {
2864 SelectionPosition newPos
;
2866 int currentLine
= pdoc
->LineFromPosition(sel
.MainCaret());
2867 int topStutterLine
= topLine
+ caretYSlop
;
2868 int bottomStutterLine
=
2869 pdoc
->LineFromPosition(PositionFromLocation(
2870 Point::FromInts(lastXChosen
- xOffset
, direction
* vs
.lineHeight
* LinesToScroll())))
2873 if (stuttered
&& (direction
< 0 && currentLine
> topStutterLine
)) {
2874 topLineNew
= topLine
;
2875 newPos
= SPositionFromLocation(Point::FromInts(lastXChosen
- xOffset
, vs
.lineHeight
* caretYSlop
),
2876 false, false, UserVirtualSpace());
2878 } else if (stuttered
&& (direction
> 0 && currentLine
< bottomStutterLine
)) {
2879 topLineNew
= topLine
;
2880 newPos
= SPositionFromLocation(Point::FromInts(lastXChosen
- xOffset
, vs
.lineHeight
* (LinesToScroll() - caretYSlop
)),
2881 false, false, UserVirtualSpace());
2884 Point pt
= LocationFromPosition(sel
.MainCaret());
2886 topLineNew
= Platform::Clamp(
2887 topLine
+ direction
* LinesToScroll(), 0, MaxScrollPos());
2888 newPos
= SPositionFromLocation(
2889 Point::FromInts(lastXChosen
- xOffset
, static_cast<int>(pt
.y
) + direction
* (vs
.lineHeight
* LinesToScroll())),
2890 false, false, UserVirtualSpace());
2893 if (topLineNew
!= topLine
) {
2894 SetTopLine(topLineNew
);
2895 MovePositionTo(newPos
, selt
);
2897 SetVerticalScrollPos();
2899 MovePositionTo(newPos
, selt
);
2903 void Editor::ChangeCaseOfSelection(int caseMapping
) {
2905 for (size_t r
=0; r
<sel
.Count(); r
++) {
2906 SelectionRange current
= sel
.Range(r
);
2907 SelectionRange currentNoVS
= current
;
2908 currentNoVS
.ClearVirtualSpace();
2909 size_t rangeBytes
= currentNoVS
.Length();
2910 if (rangeBytes
> 0) {
2911 std::string sText
= RangeText(currentNoVS
.Start().Position(), currentNoVS
.End().Position());
2913 std::string sMapped
= CaseMapString(sText
, caseMapping
);
2915 if (sMapped
!= sText
) {
2916 size_t firstDifference
= 0;
2917 while (sMapped
[firstDifference
] == sText
[firstDifference
])
2919 size_t lastDifferenceText
= sText
.size() - 1;
2920 size_t lastDifferenceMapped
= sMapped
.size() - 1;
2921 while (sMapped
[lastDifferenceMapped
] == sText
[lastDifferenceText
]) {
2922 lastDifferenceText
--;
2923 lastDifferenceMapped
--;
2925 size_t endDifferenceText
= sText
.size() - 1 - lastDifferenceText
;
2927 static_cast<int>(currentNoVS
.Start().Position() + firstDifference
),
2928 static_cast<int>(rangeBytes
- firstDifference
- endDifferenceText
));
2929 const int lengthChange
= static_cast<int>(lastDifferenceMapped
- firstDifference
+ 1);
2930 const int lengthInserted
= pdoc
->InsertString(
2931 static_cast<int>(currentNoVS
.Start().Position() + firstDifference
),
2932 sMapped
.c_str() + firstDifference
,
2934 // Automatic movement changes selection so reset to exactly the same as it was.
2935 int diffSizes
= static_cast<int>(sMapped
.size() - sText
.size()) + lengthInserted
- lengthChange
;
2936 if (diffSizes
!= 0) {
2937 if (current
.anchor
> current
.caret
)
2938 current
.anchor
.Add(diffSizes
);
2940 current
.caret
.Add(diffSizes
);
2942 sel
.Range(r
) = current
;
2948 void Editor::LineTranspose() {
2949 int line
= pdoc
->LineFromPosition(sel
.MainCaret());
2953 const int startPrevious
= pdoc
->LineStart(line
- 1);
2954 const std::string linePrevious
= RangeText(startPrevious
, pdoc
->LineEnd(line
- 1));
2956 int startCurrent
= pdoc
->LineStart(line
);
2957 const std::string lineCurrent
= RangeText(startCurrent
, pdoc
->LineEnd(line
));
2959 pdoc
->DeleteChars(startCurrent
, static_cast<int>(lineCurrent
.length()));
2960 pdoc
->DeleteChars(startPrevious
, static_cast<int>(linePrevious
.length()));
2961 startCurrent
-= static_cast<int>(linePrevious
.length());
2963 startCurrent
+= pdoc
->InsertString(startPrevious
, lineCurrent
.c_str(),
2964 static_cast<int>(lineCurrent
.length()));
2965 pdoc
->InsertString(startCurrent
, linePrevious
.c_str(),
2966 static_cast<int>(linePrevious
.length()));
2967 // Move caret to start of current line
2968 MovePositionTo(SelectionPosition(startCurrent
));
2972 void Editor::Duplicate(bool forLine
) {
2977 const char *eol
= "";
2980 eol
= StringFromEOLMode(pdoc
->eolMode
);
2981 eolLen
= istrlen(eol
);
2983 for (size_t r
=0; r
<sel
.Count(); r
++) {
2984 SelectionPosition start
= sel
.Range(r
).Start();
2985 SelectionPosition end
= sel
.Range(r
).End();
2987 int line
= pdoc
->LineFromPosition(sel
.Range(r
).caret
.Position());
2988 start
= SelectionPosition(pdoc
->LineStart(line
));
2989 end
= SelectionPosition(pdoc
->LineEnd(line
));
2991 std::string text
= RangeText(start
.Position(), end
.Position());
2992 int lengthInserted
= eolLen
;
2994 lengthInserted
= pdoc
->InsertString(end
.Position(), eol
, eolLen
);
2995 pdoc
->InsertString(end
.Position() + lengthInserted
, text
.c_str(), static_cast<int>(text
.length()));
2997 if (sel
.Count() && sel
.IsRectangular()) {
2998 SelectionPosition last
= sel
.Last();
3000 int line
= pdoc
->LineFromPosition(last
.Position());
3001 last
= SelectionPosition(last
.Position() + pdoc
->LineStart(line
+1) - pdoc
->LineStart(line
));
3003 if (sel
.Rectangular().anchor
> sel
.Rectangular().caret
)
3004 sel
.Rectangular().anchor
= last
;
3006 sel
.Rectangular().caret
= last
;
3007 SetRectangularRange();
3011 void Editor::CancelModes() {
3012 sel
.SetMoveExtends(false);
3015 void Editor::NewLine() {
3016 InvalidateWholeSelection();
3017 if (sel
.IsRectangular() || !additionalSelectionTyping
) {
3018 // Remove non-main ranges
3019 sel
.DropAdditionalRanges();
3022 UndoGroup
ug(pdoc
, !sel
.Empty() || (sel
.Count() > 1));
3029 // Insert each line end
3030 size_t countInsertions
= 0;
3031 for (size_t r
= 0; r
< sel
.Count(); r
++) {
3032 sel
.Range(r
).ClearVirtualSpace();
3033 const char *eol
= StringFromEOLMode(pdoc
->eolMode
);
3034 const int positionInsert
= sel
.Range(r
).caret
.Position();
3035 const int insertLength
= pdoc
->InsertString(positionInsert
, eol
, istrlen(eol
));
3036 if (insertLength
> 0) {
3037 sel
.Range(r
) = SelectionRange(positionInsert
+ insertLength
);
3042 // Perform notifications after all the changes as the application may change the
3043 // selections in response to the characters.
3044 for (size_t i
= 0; i
< countInsertions
; i
++) {
3045 const char *eol
= StringFromEOLMode(pdoc
->eolMode
);
3048 if (recordingMacro
) {
3052 NotifyMacroRecord(SCI_REPLACESEL
, 0, reinterpret_cast<sptr_t
>(txt
));
3060 EnsureCaretVisible();
3061 // Avoid blinking during rapid typing:
3062 ShowCaretAtCurrentPosition();
3065 SelectionPosition
Editor::PositionUpOrDown(SelectionPosition spStart
, int direction
, int lastX
) {
3066 const Point pt
= LocationFromPosition(spStart
);
3069 if (vs
.annotationVisible
) {
3070 const int lineDoc
= pdoc
->LineFromPosition(spStart
.Position());
3071 const Point ptStartLine
= LocationFromPosition(pdoc
->LineStart(lineDoc
));
3072 const int subLine
= static_cast<int>(pt
.y
- ptStartLine
.y
) / vs
.lineHeight
;
3074 if (direction
< 0 && subLine
== 0) {
3075 const int lineDisplay
= cs
.DisplayFromDoc(lineDoc
);
3076 if (lineDisplay
> 0) {
3077 skipLines
= pdoc
->AnnotationLines(cs
.DocFromDisplay(lineDisplay
- 1));
3079 } else if (direction
> 0 && subLine
>= (cs
.GetHeight(lineDoc
) - 1 - pdoc
->AnnotationLines(lineDoc
))) {
3080 skipLines
= pdoc
->AnnotationLines(lineDoc
);
3084 const int newY
= static_cast<int>(pt
.y
) + (1 + skipLines
) * direction
* vs
.lineHeight
;
3086 lastX
= static_cast<int>(pt
.x
) + xOffset
;
3088 SelectionPosition posNew
= SPositionFromLocation(
3089 Point::FromInts(lastX
- xOffset
, newY
), false, false, UserVirtualSpace());
3091 if (direction
< 0) {
3092 // Line wrapping may lead to a location on the same line, so
3093 // seek back if that is the case.
3094 Point ptNew
= LocationFromPosition(posNew
.Position());
3095 while ((posNew
.Position() > 0) && (pt
.y
== ptNew
.y
)) {
3097 posNew
.SetVirtualSpace(0);
3098 ptNew
= LocationFromPosition(posNew
.Position());
3100 } else if (direction
> 0 && posNew
.Position() != pdoc
->Length()) {
3101 // There is an equivalent case when moving down which skips
3103 Point ptNew
= LocationFromPosition(posNew
.Position());
3104 while ((posNew
.Position() > spStart
.Position()) && (ptNew
.y
> newY
)) {
3106 posNew
.SetVirtualSpace(0);
3107 ptNew
= LocationFromPosition(posNew
.Position());
3113 void Editor::CursorUpOrDown(int direction
, Selection::selTypes selt
) {
3114 SelectionPosition caretToUse
= sel
.Range(sel
.Main()).caret
;
3115 if (sel
.IsRectangular()) {
3116 if (selt
== Selection::noSel
) {
3117 caretToUse
= (direction
> 0) ? sel
.Limits().end
: sel
.Limits().start
;
3119 caretToUse
= sel
.Rectangular().caret
;
3122 if (selt
== Selection::selRectangle
) {
3123 const SelectionRange rangeBase
= sel
.IsRectangular() ? sel
.Rectangular() : sel
.RangeMain();
3124 if (!sel
.IsRectangular()) {
3125 InvalidateWholeSelection();
3126 sel
.DropAdditionalRanges();
3128 const SelectionPosition posNew
= MovePositionSoVisible(
3129 PositionUpOrDown(caretToUse
, direction
, lastXChosen
), direction
);
3130 sel
.selType
= Selection::selRectangle
;
3131 sel
.Rectangular() = SelectionRange(posNew
, rangeBase
.anchor
);
3132 SetRectangularRange();
3133 MovedCaret(posNew
, caretToUse
, true);
3135 InvalidateWholeSelection();
3136 if (!additionalSelectionTyping
|| (sel
.IsRectangular())) {
3137 sel
.DropAdditionalRanges();
3139 sel
.selType
= Selection::selStream
;
3140 for (size_t r
= 0; r
< sel
.Count(); r
++) {
3141 const int lastX
= (r
== sel
.Main()) ? lastXChosen
: -1;
3142 const SelectionPosition spCaretNow
= sel
.Range(r
).caret
;
3143 const SelectionPosition posNew
= MovePositionSoVisible(
3144 PositionUpOrDown(spCaretNow
, direction
, lastX
), direction
);
3145 sel
.Range(r
) = selt
== Selection::selStream
?
3146 SelectionRange(posNew
, sel
.Range(r
).anchor
) : SelectionRange(posNew
);
3148 sel
.RemoveDuplicates();
3149 MovedCaret(sel
.RangeMain().caret
, caretToUse
, true);
3153 void Editor::ParaUpOrDown(int direction
, Selection::selTypes selt
) {
3154 int lineDoc
, savedPos
= sel
.MainCaret();
3156 MovePositionTo(SelectionPosition(direction
> 0 ? pdoc
->ParaDown(sel
.MainCaret()) : pdoc
->ParaUp(sel
.MainCaret())), selt
);
3157 lineDoc
= pdoc
->LineFromPosition(sel
.MainCaret());
3158 if (direction
> 0) {
3159 if (sel
.MainCaret() >= pdoc
->Length() && !cs
.GetVisible(lineDoc
)) {
3160 if (selt
== Selection::noSel
) {
3161 MovePositionTo(SelectionPosition(pdoc
->LineEndPosition(savedPos
)));
3166 } while (!cs
.GetVisible(lineDoc
));
3169 Range
Editor::RangeDisplayLine(int lineVisible
) {
3171 AutoSurface
surface(this);
3172 return view
.RangeDisplayLine(surface
, *this, lineVisible
, vs
);
3175 int Editor::StartEndDisplayLine(int pos
, bool start
) {
3177 AutoSurface
surface(this);
3178 int posRet
= view
.StartEndDisplayLine(surface
, *this, pos
, start
, vs
);
3179 if (posRet
== INVALID_POSITION
) {
3188 unsigned int WithExtends(unsigned int iMessage
) {
3190 case SCI_CHARLEFT
: return SCI_CHARLEFTEXTEND
;
3191 case SCI_CHARRIGHT
: return SCI_CHARRIGHTEXTEND
;
3193 case SCI_WORDLEFT
: return SCI_WORDLEFTEXTEND
;
3194 case SCI_WORDRIGHT
: return SCI_WORDRIGHTEXTEND
;
3195 case SCI_WORDLEFTEND
: return SCI_WORDLEFTENDEXTEND
;
3196 case SCI_WORDRIGHTEND
: return SCI_WORDRIGHTENDEXTEND
;
3197 case SCI_WORDPARTLEFT
: return SCI_WORDPARTLEFTEXTEND
;
3198 case SCI_WORDPARTRIGHT
: return SCI_WORDPARTRIGHTEXTEND
;
3200 case SCI_HOME
: return SCI_HOMEEXTEND
;
3201 case SCI_HOMEDISPLAY
: return SCI_HOMEDISPLAYEXTEND
;
3202 case SCI_HOMEWRAP
: return SCI_HOMEWRAPEXTEND
;
3203 case SCI_VCHOME
: return SCI_VCHOMEEXTEND
;
3204 case SCI_VCHOMEDISPLAY
: return SCI_VCHOMEDISPLAYEXTEND
;
3205 case SCI_VCHOMEWRAP
: return SCI_VCHOMEWRAPEXTEND
;
3207 case SCI_LINEEND
: return SCI_LINEENDEXTEND
;
3208 case SCI_LINEENDDISPLAY
: return SCI_LINEENDDISPLAYEXTEND
;
3209 case SCI_LINEENDWRAP
: return SCI_LINEENDWRAPEXTEND
;
3211 default: return iMessage
;
3215 int NaturalDirection(unsigned int iMessage
) {
3218 case SCI_CHARLEFTEXTEND
:
3219 case SCI_CHARLEFTRECTEXTEND
:
3221 case SCI_WORDLEFTEXTEND
:
3222 case SCI_WORDLEFTEND
:
3223 case SCI_WORDLEFTENDEXTEND
:
3224 case SCI_WORDPARTLEFT
:
3225 case SCI_WORDPARTLEFTEXTEND
:
3227 case SCI_HOMEEXTEND
:
3228 case SCI_HOMEDISPLAY
:
3229 case SCI_HOMEDISPLAYEXTEND
:
3231 case SCI_HOMEWRAPEXTEND
:
3232 // VC_HOME* mostly goes back
3234 case SCI_VCHOMEEXTEND
:
3235 case SCI_VCHOMEDISPLAY
:
3236 case SCI_VCHOMEDISPLAYEXTEND
:
3237 case SCI_VCHOMEWRAP
:
3238 case SCI_VCHOMEWRAPEXTEND
:
3246 bool IsRectExtend(unsigned int iMessage
) {
3248 case SCI_CHARLEFTRECTEXTEND
:
3249 case SCI_CHARRIGHTRECTEXTEND
:
3250 case SCI_HOMERECTEXTEND
:
3251 case SCI_VCHOMERECTEXTEND
:
3252 case SCI_LINEENDRECTEXTEND
:
3261 int Editor::VCHomeDisplayPosition(int position
) {
3262 const int homePos
= pdoc
->VCHomePosition(position
);
3263 const int viewLineStart
= StartEndDisplayLine(position
, true);
3264 if (viewLineStart
> homePos
)
3265 return viewLineStart
;
3270 int Editor::VCHomeWrapPosition(int position
) {
3271 const int homePos
= pdoc
->VCHomePosition(position
);
3272 const int viewLineStart
= StartEndDisplayLine(position
, true);
3273 if ((viewLineStart
< position
) && (viewLineStart
> homePos
))
3274 return viewLineStart
;
3279 int Editor::LineEndWrapPosition(int position
) {
3280 const int endPos
= StartEndDisplayLine(position
, false);
3281 const int realEndPos
= pdoc
->LineEndPosition(position
);
3282 if (endPos
> realEndPos
// if moved past visible EOLs
3283 || position
>= endPos
) // if at end of display line already
3289 int Editor::HorizontalMove(unsigned int iMessage
) {
3290 if (sel
.MoveExtends()) {
3291 iMessage
= WithExtends(iMessage
);
3294 if (!multipleSelection
&& !sel
.IsRectangular()) {
3295 // Simplify selection down to 1
3296 sel
.SetSelection(sel
.RangeMain());
3299 // Invalidate each of the current selections
3300 InvalidateWholeSelection();
3302 if (IsRectExtend(iMessage
)) {
3303 const SelectionRange rangeBase
= sel
.IsRectangular() ? sel
.Rectangular() : sel
.RangeMain();
3304 if (!sel
.IsRectangular()) {
3305 sel
.DropAdditionalRanges();
3307 // Will change to rectangular if not currently rectangular
3308 SelectionPosition spCaret
= rangeBase
.caret
;
3310 case SCI_CHARLEFTRECTEXTEND
:
3311 if (pdoc
->IsLineEndPosition(spCaret
.Position()) && spCaret
.VirtualSpace()) {
3312 spCaret
.SetVirtualSpace(spCaret
.VirtualSpace() - 1);
3313 } else if ((virtualSpaceOptions
& SCVS_NOWRAPLINESTART
) == 0 || pdoc
->GetColumn(spCaret
.Position()) > 0) {
3314 spCaret
= SelectionPosition(spCaret
.Position() - 1);
3317 case SCI_CHARRIGHTRECTEXTEND
:
3318 if ((virtualSpaceOptions
& SCVS_RECTANGULARSELECTION
) && pdoc
->IsLineEndPosition(sel
.MainCaret())) {
3319 spCaret
.SetVirtualSpace(spCaret
.VirtualSpace() + 1);
3321 spCaret
= SelectionPosition(spCaret
.Position() + 1);
3324 case SCI_HOMERECTEXTEND
:
3325 spCaret
= SelectionPosition(pdoc
->LineStart(pdoc
->LineFromPosition(spCaret
.Position())));
3327 case SCI_VCHOMERECTEXTEND
:
3328 spCaret
= SelectionPosition(pdoc
->VCHomePosition(spCaret
.Position()));
3330 case SCI_LINEENDRECTEXTEND
:
3331 spCaret
= SelectionPosition(pdoc
->LineEndPosition(spCaret
.Position()));
3334 const int directionMove
= (spCaret
< rangeBase
.caret
) ? -1 : 1;
3335 spCaret
= MovePositionSoVisible(spCaret
, directionMove
);
3336 sel
.selType
= Selection::selRectangle
;
3337 sel
.Rectangular() = SelectionRange(spCaret
, rangeBase
.anchor
);
3338 SetRectangularRange();
3339 } else if (sel
.IsRectangular()) {
3340 // Not a rectangular extension so switch to stream.
3341 const SelectionPosition selAtLimit
=
3342 (NaturalDirection(iMessage
) > 0) ? sel
.Limits().end
: sel
.Limits().start
;
3343 sel
.selType
= Selection::selStream
;
3344 sel
.SetSelection(SelectionRange(selAtLimit
));
3346 if (!additionalSelectionTyping
) {
3347 InvalidateWholeSelection();
3348 sel
.DropAdditionalRanges();
3350 for (size_t r
= 0; r
< sel
.Count(); r
++) {
3351 const SelectionPosition spCaretNow
= sel
.Range(r
).caret
;
3352 SelectionPosition spCaret
= spCaretNow
;
3355 case SCI_CHARLEFTEXTEND
:
3356 if (spCaret
.VirtualSpace()) {
3357 spCaret
.SetVirtualSpace(spCaret
.VirtualSpace() - 1);
3358 } else if ((virtualSpaceOptions
& SCVS_NOWRAPLINESTART
) == 0 || pdoc
->GetColumn(spCaret
.Position()) > 0) {
3359 spCaret
= SelectionPosition(spCaret
.Position() - 1);
3363 case SCI_CHARRIGHTEXTEND
:
3364 if ((virtualSpaceOptions
& SCVS_USERACCESSIBLE
) && pdoc
->IsLineEndPosition(spCaret
.Position())) {
3365 spCaret
.SetVirtualSpace(spCaret
.VirtualSpace() + 1);
3367 spCaret
= SelectionPosition(spCaret
.Position() + 1);
3371 case SCI_WORDLEFTEXTEND
:
3372 spCaret
= SelectionPosition(pdoc
->NextWordStart(spCaret
.Position(), -1));
3375 case SCI_WORDRIGHTEXTEND
:
3376 spCaret
= SelectionPosition(pdoc
->NextWordStart(spCaret
.Position(), 1));
3378 case SCI_WORDLEFTEND
:
3379 case SCI_WORDLEFTENDEXTEND
:
3380 spCaret
= SelectionPosition(pdoc
->NextWordEnd(spCaret
.Position(), -1));
3382 case SCI_WORDRIGHTEND
:
3383 case SCI_WORDRIGHTENDEXTEND
:
3384 spCaret
= SelectionPosition(pdoc
->NextWordEnd(spCaret
.Position(), 1));
3386 case SCI_WORDPARTLEFT
:
3387 case SCI_WORDPARTLEFTEXTEND
:
3388 spCaret
= SelectionPosition(pdoc
->WordPartLeft(spCaret
.Position()));
3390 case SCI_WORDPARTRIGHT
:
3391 case SCI_WORDPARTRIGHTEXTEND
:
3392 spCaret
= SelectionPosition(pdoc
->WordPartRight(spCaret
.Position()));
3395 case SCI_HOMEEXTEND
:
3396 spCaret
= SelectionPosition(pdoc
->LineStart(pdoc
->LineFromPosition(spCaret
.Position())));
3398 case SCI_HOMEDISPLAY
:
3399 case SCI_HOMEDISPLAYEXTEND
:
3400 spCaret
= SelectionPosition(StartEndDisplayLine(spCaret
.Position(), true));
3403 case SCI_HOMEWRAPEXTEND
:
3404 spCaret
= MovePositionSoVisible(StartEndDisplayLine(spCaret
.Position(), true), -1);
3405 if (spCaretNow
<= spCaret
)
3406 spCaret
= SelectionPosition(pdoc
->LineStart(pdoc
->LineFromPosition(spCaret
.Position())));
3409 case SCI_VCHOMEEXTEND
:
3410 // VCHome alternates between beginning of line and beginning of text so may move back or forwards
3411 spCaret
= SelectionPosition(pdoc
->VCHomePosition(spCaret
.Position()));
3413 case SCI_VCHOMEDISPLAY
:
3414 case SCI_VCHOMEDISPLAYEXTEND
:
3415 spCaret
= SelectionPosition(VCHomeDisplayPosition(spCaret
.Position()));
3417 case SCI_VCHOMEWRAP
:
3418 case SCI_VCHOMEWRAPEXTEND
:
3419 spCaret
= SelectionPosition(VCHomeWrapPosition(spCaret
.Position()));
3422 case SCI_LINEENDEXTEND
:
3423 spCaret
= SelectionPosition(pdoc
->LineEndPosition(spCaret
.Position()));
3425 case SCI_LINEENDDISPLAY
:
3426 case SCI_LINEENDDISPLAYEXTEND
:
3427 spCaret
= SelectionPosition(StartEndDisplayLine(spCaret
.Position(), false));
3429 case SCI_LINEENDWRAP
:
3430 case SCI_LINEENDWRAPEXTEND
:
3431 spCaret
= SelectionPosition(LineEndWrapPosition(spCaret
.Position()));
3435 PLATFORM_ASSERT(false);
3438 const int directionMove
= (spCaret
< spCaretNow
) ? -1 : 1;
3439 spCaret
= MovePositionSoVisible(spCaret
, directionMove
);
3441 // Handle move versus extend, and special behaviour for non-empty left/right
3445 if (sel
.Range(r
).Empty()) {
3446 sel
.Range(r
) = SelectionRange(spCaret
);
3448 sel
.Range(r
) = SelectionRange(
3449 (iMessage
== SCI_CHARLEFT
) ? sel
.Range(r
).Start() : sel
.Range(r
).End());
3455 case SCI_WORDLEFTEND
:
3456 case SCI_WORDRIGHTEND
:
3457 case SCI_WORDPARTLEFT
:
3458 case SCI_WORDPARTRIGHT
:
3460 case SCI_HOMEDISPLAY
:
3463 case SCI_VCHOMEDISPLAY
:
3464 case SCI_VCHOMEWRAP
:
3466 case SCI_LINEENDDISPLAY
:
3467 case SCI_LINEENDWRAP
:
3468 sel
.Range(r
) = SelectionRange(spCaret
);
3471 case SCI_CHARLEFTEXTEND
:
3472 case SCI_CHARRIGHTEXTEND
:
3473 case SCI_WORDLEFTEXTEND
:
3474 case SCI_WORDRIGHTEXTEND
:
3475 case SCI_WORDLEFTENDEXTEND
:
3476 case SCI_WORDRIGHTENDEXTEND
:
3477 case SCI_WORDPARTLEFTEXTEND
:
3478 case SCI_WORDPARTRIGHTEXTEND
:
3479 case SCI_HOMEEXTEND
:
3480 case SCI_HOMEDISPLAYEXTEND
:
3481 case SCI_HOMEWRAPEXTEND
:
3482 case SCI_VCHOMEEXTEND
:
3483 case SCI_VCHOMEDISPLAYEXTEND
:
3484 case SCI_VCHOMEWRAPEXTEND
:
3485 case SCI_LINEENDEXTEND
:
3486 case SCI_LINEENDDISPLAYEXTEND
:
3487 case SCI_LINEENDWRAPEXTEND
: {
3488 SelectionRange rangeNew
= SelectionRange(spCaret
, sel
.Range(r
).anchor
);
3489 sel
.TrimOtherSelections(r
, SelectionRange(rangeNew
));
3490 sel
.Range(r
) = rangeNew
;
3495 PLATFORM_ASSERT(false);
3500 sel
.RemoveDuplicates();
3502 MovedCaret(sel
.RangeMain().caret
, SelectionPosition(INVALID_POSITION
), true);
3504 // Invalidate the new state of the selection
3505 InvalidateWholeSelection();
3508 // Need the line moving and so forth from MovePositionTo
3512 int Editor::DelWordOrLine(unsigned int iMessage
) {
3513 // Virtual space may be realised for SCI_DELWORDRIGHT or SCI_DELWORDRIGHTEND
3514 // which means 2 actions so wrap in an undo group.
3516 // Rightwards and leftwards deletions differ in treatment of virtual space.
3517 // Clear virtual space for leftwards, realise for rightwards.
3518 const bool leftwards
= (iMessage
== SCI_DELWORDLEFT
) || (iMessage
== SCI_DELLINELEFT
);
3520 if (!additionalSelectionTyping
) {
3521 InvalidateWholeSelection();
3522 sel
.DropAdditionalRanges();
3525 UndoGroup
ug0(pdoc
, (sel
.Count() > 1) || !leftwards
);
3527 for (size_t r
= 0; r
< sel
.Count(); r
++) {
3529 // Delete to the left so first clear the virtual space.
3530 sel
.Range(r
).ClearVirtualSpace();
3532 // Delete to the right so first realise the virtual space.
3533 sel
.Range(r
) = SelectionRange(
3534 RealizeVirtualSpace(sel
.Range(r
).caret
));
3539 case SCI_DELWORDLEFT
:
3540 rangeDelete
= Range(
3541 pdoc
->NextWordStart(sel
.Range(r
).caret
.Position(), -1),
3542 sel
.Range(r
).caret
.Position());
3544 case SCI_DELWORDRIGHT
:
3545 rangeDelete
= Range(
3546 sel
.Range(r
).caret
.Position(),
3547 pdoc
->NextWordStart(sel
.Range(r
).caret
.Position(), 1));
3549 case SCI_DELWORDRIGHTEND
:
3550 rangeDelete
= Range(
3551 sel
.Range(r
).caret
.Position(),
3552 pdoc
->NextWordEnd(sel
.Range(r
).caret
.Position(), 1));
3554 case SCI_DELLINELEFT
:
3555 rangeDelete
= Range(
3556 pdoc
->LineStart(pdoc
->LineFromPosition(sel
.Range(r
).caret
.Position())),
3557 sel
.Range(r
).caret
.Position());
3559 case SCI_DELLINERIGHT
:
3560 rangeDelete
= Range(
3561 sel
.Range(r
).caret
.Position(),
3562 pdoc
->LineEnd(pdoc
->LineFromPosition(sel
.Range(r
).caret
.Position())));
3565 if (!RangeContainsProtected(rangeDelete
.start
, rangeDelete
.end
)) {
3566 pdoc
->DeleteChars(rangeDelete
.start
, rangeDelete
.end
- rangeDelete
.start
);
3570 // May need something stronger here: can selections overlap at this point?
3571 sel
.RemoveDuplicates();
3573 MovedCaret(sel
.RangeMain().caret
, SelectionPosition(INVALID_POSITION
), true);
3575 // Invalidate the new state of the selection
3576 InvalidateWholeSelection();
3582 int Editor::KeyCommand(unsigned int iMessage
) {
3585 CursorUpOrDown(1, Selection::noSel
);
3587 case SCI_LINEDOWNEXTEND
:
3588 CursorUpOrDown(1, Selection::selStream
);
3590 case SCI_LINEDOWNRECTEXTEND
:
3591 CursorUpOrDown(1, Selection::selRectangle
);
3594 ParaUpOrDown(1, Selection::noSel
);
3596 case SCI_PARADOWNEXTEND
:
3597 ParaUpOrDown(1, Selection::selStream
);
3599 case SCI_LINESCROLLDOWN
:
3600 ScrollTo(topLine
+ 1);
3601 MoveCaretInsideView(false);
3604 CursorUpOrDown(-1, Selection::noSel
);
3606 case SCI_LINEUPEXTEND
:
3607 CursorUpOrDown(-1, Selection::selStream
);
3609 case SCI_LINEUPRECTEXTEND
:
3610 CursorUpOrDown(-1, Selection::selRectangle
);
3613 ParaUpOrDown(-1, Selection::noSel
);
3615 case SCI_PARAUPEXTEND
:
3616 ParaUpOrDown(-1, Selection::selStream
);
3618 case SCI_LINESCROLLUP
:
3619 ScrollTo(topLine
- 1);
3620 MoveCaretInsideView(false);
3624 case SCI_CHARLEFTEXTEND
:
3625 case SCI_CHARLEFTRECTEXTEND
:
3627 case SCI_CHARRIGHTEXTEND
:
3628 case SCI_CHARRIGHTRECTEXTEND
:
3630 case SCI_WORDLEFTEXTEND
:
3632 case SCI_WORDRIGHTEXTEND
:
3633 case SCI_WORDLEFTEND
:
3634 case SCI_WORDLEFTENDEXTEND
:
3635 case SCI_WORDRIGHTEND
:
3636 case SCI_WORDRIGHTENDEXTEND
:
3637 case SCI_WORDPARTLEFT
:
3638 case SCI_WORDPARTLEFTEXTEND
:
3639 case SCI_WORDPARTRIGHT
:
3640 case SCI_WORDPARTRIGHTEXTEND
:
3642 case SCI_HOMEEXTEND
:
3643 case SCI_HOMERECTEXTEND
:
3644 case SCI_HOMEDISPLAY
:
3645 case SCI_HOMEDISPLAYEXTEND
:
3647 case SCI_HOMEWRAPEXTEND
:
3649 case SCI_VCHOMEEXTEND
:
3650 case SCI_VCHOMERECTEXTEND
:
3651 case SCI_VCHOMEDISPLAY
:
3652 case SCI_VCHOMEDISPLAYEXTEND
:
3653 case SCI_VCHOMEWRAP
:
3654 case SCI_VCHOMEWRAPEXTEND
:
3656 case SCI_LINEENDEXTEND
:
3657 case SCI_LINEENDRECTEXTEND
:
3658 case SCI_LINEENDDISPLAY
:
3659 case SCI_LINEENDDISPLAYEXTEND
:
3660 case SCI_LINEENDWRAP
:
3661 case SCI_LINEENDWRAPEXTEND
:
3662 return HorizontalMove(iMessage
);
3664 case SCI_DOCUMENTSTART
:
3668 case SCI_DOCUMENTSTARTEXTEND
:
3669 MovePositionTo(0, Selection::selStream
);
3672 case SCI_DOCUMENTEND
:
3673 MovePositionTo(pdoc
->Length());
3676 case SCI_DOCUMENTENDEXTEND
:
3677 MovePositionTo(pdoc
->Length(), Selection::selStream
);
3680 case SCI_STUTTEREDPAGEUP
:
3681 PageMove(-1, Selection::noSel
, true);
3683 case SCI_STUTTEREDPAGEUPEXTEND
:
3684 PageMove(-1, Selection::selStream
, true);
3686 case SCI_STUTTEREDPAGEDOWN
:
3687 PageMove(1, Selection::noSel
, true);
3689 case SCI_STUTTEREDPAGEDOWNEXTEND
:
3690 PageMove(1, Selection::selStream
, true);
3695 case SCI_PAGEUPEXTEND
:
3696 PageMove(-1, Selection::selStream
);
3698 case SCI_PAGEUPRECTEXTEND
:
3699 PageMove(-1, Selection::selRectangle
);
3704 case SCI_PAGEDOWNEXTEND
:
3705 PageMove(1, Selection::selStream
);
3707 case SCI_PAGEDOWNRECTEXTEND
:
3708 PageMove(1, Selection::selRectangle
);
3710 case SCI_EDITTOGGLEOVERTYPE
:
3711 inOverstrike
= !inOverstrike
;
3712 ShowCaretAtCurrentPosition();
3713 ContainerNeedsUpdate(SC_UPDATE_CONTENT
);
3716 case SCI_CANCEL
: // Cancel any modes - handled in subclass
3717 // Also unselect text
3719 if (sel
.Count() > 1) {
3720 // Drop additional selections
3721 InvalidateWholeSelection();
3722 sel
.DropAdditionalRanges();
3725 case SCI_DELETEBACK
:
3727 if ((caretSticky
== SC_CARETSTICKY_OFF
) || (caretSticky
== SC_CARETSTICKY_WHITESPACE
)) {
3730 EnsureCaretVisible();
3732 case SCI_DELETEBACKNOTLINE
:
3734 if ((caretSticky
== SC_CARETSTICKY_OFF
) || (caretSticky
== SC_CARETSTICKY_WHITESPACE
)) {
3737 EnsureCaretVisible();
3741 if (caretSticky
== SC_CARETSTICKY_OFF
) {
3744 EnsureCaretVisible();
3745 ShowCaretAtCurrentPosition(); // Avoid blinking
3749 if ((caretSticky
== SC_CARETSTICKY_OFF
) || (caretSticky
== SC_CARETSTICKY_WHITESPACE
)) {
3752 EnsureCaretVisible();
3753 ShowCaretAtCurrentPosition(); // Avoid blinking
3762 if (vs
.zoomLevel
< 20) {
3764 InvalidateStyleRedraw();
3769 if (vs
.zoomLevel
> -10) {
3771 InvalidateStyleRedraw();
3776 case SCI_DELWORDLEFT
:
3777 case SCI_DELWORDRIGHT
:
3778 case SCI_DELWORDRIGHTEND
:
3779 case SCI_DELLINELEFT
:
3780 case SCI_DELLINERIGHT
:
3781 return DelWordOrLine(iMessage
);
3783 case SCI_LINECOPY
: {
3784 int lineStart
= pdoc
->LineFromPosition(SelectionStart().Position());
3785 int lineEnd
= pdoc
->LineFromPosition(SelectionEnd().Position());
3786 CopyRangeToClipboard(pdoc
->LineStart(lineStart
),
3787 pdoc
->LineStart(lineEnd
+ 1));
3791 int lineStart
= pdoc
->LineFromPosition(SelectionStart().Position());
3792 int lineEnd
= pdoc
->LineFromPosition(SelectionEnd().Position());
3793 int start
= pdoc
->LineStart(lineStart
);
3794 int end
= pdoc
->LineStart(lineEnd
+ 1);
3795 SetSelection(start
, end
);
3800 case SCI_LINEDELETE
: {
3801 int line
= pdoc
->LineFromPosition(sel
.MainCaret());
3802 int start
= pdoc
->LineStart(line
);
3803 int end
= pdoc
->LineStart(line
+ 1);
3804 pdoc
->DeleteChars(start
, end
- start
);
3807 case SCI_LINETRANSPOSE
:
3810 case SCI_LINEDUPLICATE
:
3813 case SCI_SELECTIONDUPLICATE
:
3817 ChangeCaseOfSelection(cmLower
);
3820 ChangeCaseOfSelection(cmUpper
);
3822 case SCI_SCROLLTOSTART
:
3825 case SCI_SCROLLTOEND
:
3826 ScrollTo(MaxScrollPos());
3832 int Editor::KeyDefault(int, int) {
3836 int Editor::KeyDownWithModifiers(int key
, int modifiers
, bool *consumed
) {
3838 int msg
= kmap
.Find(key
, modifiers
);
3842 return static_cast<int>(WndProc(msg
, 0, 0));
3846 return KeyDefault(key
, modifiers
);
3850 int Editor::KeyDown(int key
, bool shift
, bool ctrl
, bool alt
, bool *consumed
) {
3851 return KeyDownWithModifiers(key
, ModifierFlags(shift
, ctrl
, alt
), consumed
);
3854 void Editor::Indent(bool forwards
) {
3856 for (size_t r
=0; r
<sel
.Count(); r
++) {
3857 int lineOfAnchor
= pdoc
->LineFromPosition(sel
.Range(r
).anchor
.Position());
3858 int caretPosition
= sel
.Range(r
).caret
.Position();
3859 int lineCurrentPos
= pdoc
->LineFromPosition(caretPosition
);
3860 if (lineOfAnchor
== lineCurrentPos
) {
3862 pdoc
->DeleteChars(sel
.Range(r
).Start().Position(), sel
.Range(r
).Length());
3863 caretPosition
= sel
.Range(r
).caret
.Position();
3864 if (pdoc
->GetColumn(caretPosition
) <= pdoc
->GetColumn(pdoc
->GetLineIndentPosition(lineCurrentPos
)) &&
3866 int indentation
= pdoc
->GetLineIndentation(lineCurrentPos
);
3867 int indentationStep
= pdoc
->IndentSize();
3868 const int posSelect
= pdoc
->SetLineIndentation(
3869 lineCurrentPos
, indentation
+ indentationStep
- indentation
% indentationStep
);
3870 sel
.Range(r
) = SelectionRange(posSelect
);
3872 if (pdoc
->useTabs
) {
3873 const int lengthInserted
= pdoc
->InsertString(caretPosition
, "\t", 1);
3874 sel
.Range(r
) = SelectionRange(caretPosition
+ lengthInserted
);
3876 int numSpaces
= (pdoc
->tabInChars
) -
3877 (pdoc
->GetColumn(caretPosition
) % (pdoc
->tabInChars
));
3879 numSpaces
= pdoc
->tabInChars
;
3880 const std::string
spaceText(numSpaces
, ' ');
3881 const int lengthInserted
= pdoc
->InsertString(caretPosition
, spaceText
.c_str(),
3882 static_cast<int>(spaceText
.length()));
3883 sel
.Range(r
) = SelectionRange(caretPosition
+ lengthInserted
);
3887 if (pdoc
->GetColumn(caretPosition
) <= pdoc
->GetLineIndentation(lineCurrentPos
) &&
3889 int indentation
= pdoc
->GetLineIndentation(lineCurrentPos
);
3890 int indentationStep
= pdoc
->IndentSize();
3891 const int posSelect
= pdoc
->SetLineIndentation(lineCurrentPos
, indentation
- indentationStep
);
3892 sel
.Range(r
) = SelectionRange(posSelect
);
3894 int newColumn
= ((pdoc
->GetColumn(caretPosition
) - 1) / pdoc
->tabInChars
) *
3898 int newPos
= caretPosition
;
3899 while (pdoc
->GetColumn(newPos
) > newColumn
)
3901 sel
.Range(r
) = SelectionRange(newPos
);
3904 } else { // Multiline
3905 int anchorPosOnLine
= sel
.Range(r
).anchor
.Position() - pdoc
->LineStart(lineOfAnchor
);
3906 int currentPosPosOnLine
= caretPosition
- pdoc
->LineStart(lineCurrentPos
);
3907 // Multiple lines selected so indent / dedent
3908 int lineTopSel
= Platform::Minimum(lineOfAnchor
, lineCurrentPos
);
3909 int lineBottomSel
= Platform::Maximum(lineOfAnchor
, lineCurrentPos
);
3910 if (pdoc
->LineStart(lineBottomSel
) == sel
.Range(r
).anchor
.Position() || pdoc
->LineStart(lineBottomSel
) == caretPosition
)
3911 lineBottomSel
--; // If not selecting any characters on a line, do not indent
3912 pdoc
->Indent(forwards
, lineBottomSel
, lineTopSel
);
3913 if (lineOfAnchor
< lineCurrentPos
) {
3914 if (currentPosPosOnLine
== 0)
3915 sel
.Range(r
) = SelectionRange(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor
));
3917 sel
.Range(r
) = SelectionRange(pdoc
->LineStart(lineCurrentPos
+ 1), pdoc
->LineStart(lineOfAnchor
));
3919 if (anchorPosOnLine
== 0)
3920 sel
.Range(r
) = SelectionRange(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor
));
3922 sel
.Range(r
) = SelectionRange(pdoc
->LineStart(lineCurrentPos
), pdoc
->LineStart(lineOfAnchor
+ 1));
3926 ContainerNeedsUpdate(SC_UPDATE_SELECTION
);
3929 class CaseFolderASCII
: public CaseFolderTable
{
3934 ~CaseFolderASCII() {
3939 CaseFolder
*Editor::CaseFolderForEncoding() {
3940 // Simple default that only maps ASCII upper case to lower case.
3941 return new CaseFolderASCII();
3945 * Search of a text in the document, in the given range.
3946 * @return The position of the found text, -1 if not found.
3948 long Editor::FindText(
3949 uptr_t wParam
, ///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD,
3950 ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX.
3951 sptr_t lParam
) { ///< @c Sci_TextToFind structure: The text to search for in the given range.
3953 Sci_TextToFind
*ft
= reinterpret_cast<Sci_TextToFind
*>(lParam
);
3954 int lengthFound
= istrlen(ft
->lpstrText
);
3955 if (!pdoc
->HasCaseFolder())
3956 pdoc
->SetCaseFolder(CaseFolderForEncoding());
3958 long pos
= pdoc
->FindText(
3959 static_cast<int>(ft
->chrg
.cpMin
),
3960 static_cast<int>(ft
->chrg
.cpMax
),
3962 static_cast<int>(wParam
),
3965 ft
->chrgText
.cpMin
= pos
;
3966 ft
->chrgText
.cpMax
= pos
+ lengthFound
;
3968 return static_cast<int>(pos
);
3969 } catch (RegexError
&) {
3970 errorStatus
= SC_STATUS_WARN_REGEX
;
3976 * Relocatable search support : Searches relative to current selection
3977 * point and sets the selection to the found text range with
3981 * Anchor following searches at current selection start: This allows
3982 * multiple incremental interactive searches to be macro recorded
3983 * while still setting the selection to found text so the find/select
3984 * operation is self-contained.
3986 void Editor::SearchAnchor() {
3987 searchAnchor
= SelectionStart().Position();
3991 * Find text from current search anchor: Must call @c SearchAnchor first.
3992 * Used for next text and previous text requests.
3993 * @return The position of the found text, -1 if not found.
3995 long Editor::SearchText(
3996 unsigned int iMessage
, ///< Accepts both @c SCI_SEARCHNEXT and @c SCI_SEARCHPREV.
3997 uptr_t wParam
, ///< Search modes : @c SCFIND_MATCHCASE, @c SCFIND_WHOLEWORD,
3998 ///< @c SCFIND_WORDSTART, @c SCFIND_REGEXP or @c SCFIND_POSIX.
3999 sptr_t lParam
) { ///< The text to search for.
4001 const char *txt
= reinterpret_cast<char *>(lParam
);
4003 int lengthFound
= istrlen(txt
);
4004 if (!pdoc
->HasCaseFolder())
4005 pdoc
->SetCaseFolder(CaseFolderForEncoding());
4007 if (iMessage
== SCI_SEARCHNEXT
) {
4008 pos
= pdoc
->FindText(searchAnchor
, pdoc
->Length(), txt
,
4009 static_cast<int>(wParam
),
4012 pos
= pdoc
->FindText(searchAnchor
, 0, txt
,
4013 static_cast<int>(wParam
),
4016 } catch (RegexError
&) {
4017 errorStatus
= SC_STATUS_WARN_REGEX
;
4021 SetSelection(static_cast<int>(pos
), static_cast<int>(pos
+ lengthFound
));
4027 std::string
Editor::CaseMapString(const std::string
&s
, int caseMapping
) {
4029 for (size_t i
=0; i
<ret
.size(); i
++) {
4030 switch (caseMapping
) {
4032 if (ret
[i
] >= 'a' && ret
[i
] <= 'z')
4033 ret
[i
] = static_cast<char>(ret
[i
] - 'a' + 'A');
4036 if (ret
[i
] >= 'A' && ret
[i
] <= 'Z')
4037 ret
[i
] = static_cast<char>(ret
[i
] - 'A' + 'a');
4045 * Search for text in the target range of the document.
4046 * @return The position of the found text, -1 if not found.
4048 long Editor::SearchInTarget(const char *text
, int length
) {
4049 int lengthFound
= length
;
4051 if (!pdoc
->HasCaseFolder())
4052 pdoc
->SetCaseFolder(CaseFolderForEncoding());
4054 long pos
= pdoc
->FindText(targetStart
, targetEnd
, text
,
4058 targetStart
= static_cast<int>(pos
);
4059 targetEnd
= static_cast<int>(pos
+ lengthFound
);
4062 } catch (RegexError
&) {
4063 errorStatus
= SC_STATUS_WARN_REGEX
;
4068 void Editor::GoToLine(int lineNo
) {
4069 if (lineNo
> pdoc
->LinesTotal())
4070 lineNo
= pdoc
->LinesTotal();
4073 SetEmptySelection(pdoc
->LineStart(lineNo
));
4074 ShowCaretAtCurrentPosition();
4075 EnsureCaretVisible();
4078 static bool Close(Point pt1
, Point pt2
, Point threshold
) {
4079 if (std::abs(pt1
.x
- pt2
.x
) > threshold
.x
)
4081 if (std::abs(pt1
.y
- pt2
.y
) > threshold
.y
)
4086 std::string
Editor::RangeText(int start
, int end
) const {
4088 int len
= end
- start
;
4089 std::string
ret(len
, '\0');
4090 for (int i
= 0; i
< len
; i
++) {
4091 ret
[i
] = pdoc
->CharAt(start
+ i
);
4095 return std::string();
4098 void Editor::CopySelectionRange(SelectionText
*ss
, bool allowLineCopy
) {
4100 if (allowLineCopy
) {
4101 int currentLine
= pdoc
->LineFromPosition(sel
.MainCaret());
4102 int start
= pdoc
->LineStart(currentLine
);
4103 int end
= pdoc
->LineEnd(currentLine
);
4105 std::string text
= RangeText(start
, end
);
4106 if (pdoc
->eolMode
!= SC_EOL_LF
)
4107 text
.push_back('\r');
4108 if (pdoc
->eolMode
!= SC_EOL_CR
)
4109 text
.push_back('\n');
4110 ss
->Copy(text
, pdoc
->dbcsCodePage
,
4111 vs
.styles
[STYLE_DEFAULT
].characterSet
, false, true);
4115 std::vector
<SelectionRange
> rangesInOrder
= sel
.RangesCopy();
4116 if (sel
.selType
== Selection::selRectangle
)
4117 std::sort(rangesInOrder
.begin(), rangesInOrder
.end());
4118 for (size_t r
=0; r
<rangesInOrder
.size(); r
++) {
4119 SelectionRange current
= rangesInOrder
[r
];
4120 text
.append(RangeText(current
.Start().Position(), current
.End().Position()));
4121 if (sel
.selType
== Selection::selRectangle
) {
4122 if (pdoc
->eolMode
!= SC_EOL_LF
)
4123 text
.push_back('\r');
4124 if (pdoc
->eolMode
!= SC_EOL_CR
)
4125 text
.push_back('\n');
4128 ss
->Copy(text
, pdoc
->dbcsCodePage
,
4129 vs
.styles
[STYLE_DEFAULT
].characterSet
, sel
.IsRectangular(), sel
.selType
== Selection::selLines
);
4133 void Editor::CopyRangeToClipboard(int start
, int end
) {
4134 start
= pdoc
->ClampPositionIntoDocument(start
);
4135 end
= pdoc
->ClampPositionIntoDocument(end
);
4136 SelectionText selectedText
;
4137 std::string text
= RangeText(start
, end
);
4138 selectedText
.Copy(text
,
4139 pdoc
->dbcsCodePage
, vs
.styles
[STYLE_DEFAULT
].characterSet
, false, false);
4140 CopyToClipboard(selectedText
);
4143 void Editor::CopyText(int length
, const char *text
) {
4144 SelectionText selectedText
;
4145 selectedText
.Copy(std::string(text
, length
),
4146 pdoc
->dbcsCodePage
, vs
.styles
[STYLE_DEFAULT
].characterSet
, false, false);
4147 CopyToClipboard(selectedText
);
4150 void Editor::SetDragPosition(SelectionPosition newPos
) {
4151 if (newPos
.Position() >= 0) {
4152 newPos
= MovePositionOutsideChar(newPos
, 1);
4155 if (!(posDrag
== newPos
)) {
4157 if (FineTickerAvailable()) {
4158 FineTickerCancel(tickCaret
);
4159 if ((caret
.active
) && (caret
.period
> 0) && (newPos
.Position() < 0))
4160 FineTickerStart(tickCaret
, caret
.period
, caret
.period
/10);
4170 void Editor::DisplayCursor(Window::Cursor c
) {
4171 if (cursorMode
== SC_CURSORNORMAL
)
4174 wMain
.SetCursor(static_cast<Window::Cursor
>(cursorMode
));
4177 bool Editor::DragThreshold(Point ptStart
, Point ptNow
) {
4178 int xMove
= static_cast<int>(ptStart
.x
- ptNow
.x
);
4179 int yMove
= static_cast<int>(ptStart
.y
- ptNow
.y
);
4180 int distanceSquared
= xMove
* xMove
+ yMove
* yMove
;
4181 return distanceSquared
> 16;
4184 void Editor::StartDrag() {
4185 // Always handled by subclasses
4186 //SetMouseCapture(true);
4187 //DisplayCursor(Window::cursorArrow);
4190 void Editor::DropAt(SelectionPosition position
, const char *value
, size_t lengthValue
, bool moving
, bool rectangular
) {
4191 //Platform::DebugPrintf("DropAt %d %d\n", inDragDrop, position);
4192 if (inDragDrop
== ddDragging
)
4193 dropWentOutside
= false;
4195 bool positionWasInSelection
= PositionInSelection(position
.Position());
4197 bool positionOnEdgeOfSelection
=
4198 (position
== SelectionStart()) || (position
== SelectionEnd());
4200 if ((inDragDrop
!= ddDragging
) || !(positionWasInSelection
) ||
4201 (positionOnEdgeOfSelection
&& !moving
)) {
4203 SelectionPosition selStart
= SelectionStart();
4204 SelectionPosition selEnd
= SelectionEnd();
4208 SelectionPosition positionAfterDeletion
= position
;
4209 if ((inDragDrop
== ddDragging
) && moving
) {
4210 // Remove dragged out text
4211 if (rectangular
|| sel
.selType
== Selection::selLines
) {
4212 for (size_t r
=0; r
<sel
.Count(); r
++) {
4213 if (position
>= sel
.Range(r
).Start()) {
4214 if (position
> sel
.Range(r
).End()) {
4215 positionAfterDeletion
.Add(-sel
.Range(r
).Length());
4217 positionAfterDeletion
.Add(-SelectionRange(position
, sel
.Range(r
).Start()).Length());
4222 if (position
> selStart
) {
4223 positionAfterDeletion
.Add(-SelectionRange(selEnd
, selStart
).Length());
4228 position
= positionAfterDeletion
;
4230 std::string convertedText
= Document::TransformLineEnds(value
, lengthValue
, pdoc
->eolMode
);
4233 PasteRectangular(position
, convertedText
.c_str(), static_cast<int>(convertedText
.length()));
4234 // Should try to select new rectangle but it may not be a rectangle now so just select the drop position
4235 SetEmptySelection(position
);
4237 position
= MovePositionOutsideChar(position
, sel
.MainCaret() - position
.Position());
4238 position
= RealizeVirtualSpace(position
);
4239 const int lengthInserted
= pdoc
->InsertString(
4240 position
.Position(), convertedText
.c_str(), static_cast<int>(convertedText
.length()));
4241 if (lengthInserted
> 0) {
4242 SelectionPosition posAfterInsertion
= position
;
4243 posAfterInsertion
.Add(lengthInserted
);
4244 SetSelection(posAfterInsertion
, position
);
4247 } else if (inDragDrop
== ddDragging
) {
4248 SetEmptySelection(position
);
4252 void Editor::DropAt(SelectionPosition position
, const char *value
, bool moving
, bool rectangular
) {
4253 DropAt(position
, value
, strlen(value
), moving
, rectangular
);
4257 * @return true if given position is inside the selection,
4259 bool Editor::PositionInSelection(int pos
) {
4260 pos
= MovePositionOutsideChar(pos
, sel
.MainCaret() - pos
);
4261 for (size_t r
=0; r
<sel
.Count(); r
++) {
4262 if (sel
.Range(r
).Contains(pos
))
4268 bool Editor::PointInSelection(Point pt
) {
4269 SelectionPosition pos
= SPositionFromLocation(pt
, false, true);
4270 Point ptPos
= LocationFromPosition(pos
);
4271 for (size_t r
=0; r
<sel
.Count(); r
++) {
4272 SelectionRange range
= sel
.Range(r
);
4273 if (range
.Contains(pos
)) {
4275 if (pos
== range
.Start()) {
4276 // see if just before selection
4277 if (pt
.x
< ptPos
.x
) {
4281 if (pos
== range
.End()) {
4282 // see if just after selection
4283 if (pt
.x
> ptPos
.x
) {
4294 bool Editor::PointInSelMargin(Point pt
) const {
4295 // Really means: "Point in a margin"
4296 if (vs
.fixedColumnWidth
> 0) { // There is a margin
4297 PRectangle rcSelMargin
= GetClientRectangle();
4298 rcSelMargin
.right
= static_cast<XYPOSITION
>(vs
.textStart
- vs
.leftMarginWidth
);
4299 rcSelMargin
.left
= static_cast<XYPOSITION
>(vs
.textStart
- vs
.fixedColumnWidth
);
4300 return rcSelMargin
.ContainsWholePixel(pt
);
4306 Window::Cursor
Editor::GetMarginCursor(Point pt
) const {
4308 for (size_t margin
= 0; margin
< vs
.ms
.size(); margin
++) {
4309 if ((pt
.x
>= x
) && (pt
.x
< x
+ vs
.ms
[margin
].width
))
4310 return static_cast<Window::Cursor
>(vs
.ms
[margin
].cursor
);
4311 x
+= vs
.ms
[margin
].width
;
4313 return Window::cursorReverseArrow
;
4316 void Editor::TrimAndSetSelection(int currentPos_
, int anchor_
) {
4317 sel
.TrimSelection(SelectionRange(currentPos_
, anchor_
));
4318 SetSelection(currentPos_
, anchor_
);
4321 void Editor::LineSelection(int lineCurrentPos_
, int lineAnchorPos_
, bool wholeLine
) {
4322 int selCurrentPos
, selAnchorPos
;
4324 int lineCurrent_
= pdoc
->LineFromPosition(lineCurrentPos_
);
4325 int lineAnchor_
= pdoc
->LineFromPosition(lineAnchorPos_
);
4326 if (lineAnchorPos_
< lineCurrentPos_
) {
4327 selCurrentPos
= pdoc
->LineStart(lineCurrent_
+ 1);
4328 selAnchorPos
= pdoc
->LineStart(lineAnchor_
);
4329 } else if (lineAnchorPos_
> lineCurrentPos_
) {
4330 selCurrentPos
= pdoc
->LineStart(lineCurrent_
);
4331 selAnchorPos
= pdoc
->LineStart(lineAnchor_
+ 1);
4332 } else { // Same line, select it
4333 selCurrentPos
= pdoc
->LineStart(lineAnchor_
+ 1);
4334 selAnchorPos
= pdoc
->LineStart(lineAnchor_
);
4337 if (lineAnchorPos_
< lineCurrentPos_
) {
4338 selCurrentPos
= StartEndDisplayLine(lineCurrentPos_
, false) + 1;
4339 selCurrentPos
= pdoc
->MovePositionOutsideChar(selCurrentPos
, 1);
4340 selAnchorPos
= StartEndDisplayLine(lineAnchorPos_
, true);
4341 } else if (lineAnchorPos_
> lineCurrentPos_
) {
4342 selCurrentPos
= StartEndDisplayLine(lineCurrentPos_
, true);
4343 selAnchorPos
= StartEndDisplayLine(lineAnchorPos_
, false) + 1;
4344 selAnchorPos
= pdoc
->MovePositionOutsideChar(selAnchorPos
, 1);
4345 } else { // Same line, select it
4346 selCurrentPos
= StartEndDisplayLine(lineAnchorPos_
, false) + 1;
4347 selCurrentPos
= pdoc
->MovePositionOutsideChar(selCurrentPos
, 1);
4348 selAnchorPos
= StartEndDisplayLine(lineAnchorPos_
, true);
4351 TrimAndSetSelection(selCurrentPos
, selAnchorPos
);
4354 void Editor::WordSelection(int pos
) {
4355 if (pos
< wordSelectAnchorStartPos
) {
4356 // Extend backward to the word containing pos.
4357 // Skip ExtendWordSelect if the line is empty or if pos is after the last character.
4358 // This ensures that a series of empty lines isn't counted as a single "word".
4359 if (!pdoc
->IsLineEndPosition(pos
))
4360 pos
= pdoc
->ExtendWordSelect(pdoc
->MovePositionOutsideChar(pos
+ 1, 1), -1);
4361 TrimAndSetSelection(pos
, wordSelectAnchorEndPos
);
4362 } else if (pos
> wordSelectAnchorEndPos
) {
4363 // Extend forward to the word containing the character to the left of pos.
4364 // Skip ExtendWordSelect if the line is empty or if pos is the first position on the line.
4365 // This ensures that a series of empty lines isn't counted as a single "word".
4366 if (pos
> pdoc
->LineStart(pdoc
->LineFromPosition(pos
)))
4367 pos
= pdoc
->ExtendWordSelect(pdoc
->MovePositionOutsideChar(pos
- 1, -1), 1);
4368 TrimAndSetSelection(pos
, wordSelectAnchorStartPos
);
4370 // Select only the anchored word
4371 if (pos
>= originalAnchorPos
)
4372 TrimAndSetSelection(wordSelectAnchorEndPos
, wordSelectAnchorStartPos
);
4374 TrimAndSetSelection(wordSelectAnchorStartPos
, wordSelectAnchorEndPos
);
4378 void Editor::DwellEnd(bool mouseMoved
) {
4380 ticksToDwell
= dwellDelay
;
4382 ticksToDwell
= SC_TIME_FOREVER
;
4383 if (dwelling
&& (dwellDelay
< SC_TIME_FOREVER
)) {
4385 NotifyDwelling(ptMouseLast
, dwelling
);
4387 if (FineTickerAvailable()) {
4388 FineTickerCancel(tickDwell
);
4389 if (mouseMoved
&& (dwellDelay
< SC_TIME_FOREVER
)) {
4390 //FineTickerStart(tickDwell, dwellDelay, dwellDelay/10);
4395 void Editor::MouseLeave() {
4396 SetHotSpotRange(NULL
);
4397 if (!HaveMouseCapture()) {
4398 ptMouseLast
= Point(-1,-1);
4403 static bool AllowVirtualSpace(int virtualSpaceOptions
, bool rectangular
) {
4404 return (!rectangular
&& ((virtualSpaceOptions
& SCVS_USERACCESSIBLE
) != 0))
4405 || (rectangular
&& ((virtualSpaceOptions
& SCVS_RECTANGULARSELECTION
) != 0));
4408 void Editor::ButtonDownWithModifiers(Point pt
, unsigned int curTime
, int modifiers
) {
4409 SetHoverIndicatorPoint(pt
);
4410 //Platform::DebugPrintf("ButtonDown %d %d = %d alt=%d %d\n", curTime, lastClickTime, curTime - lastClickTime, alt, inDragDrop);
4412 const bool ctrl
= (modifiers
& SCI_CTRL
) != 0;
4413 const bool shift
= (modifiers
& SCI_SHIFT
) != 0;
4414 const bool alt
= (modifiers
& SCI_ALT
) != 0;
4415 SelectionPosition newPos
= SPositionFromLocation(pt
, false, false, AllowVirtualSpace(virtualSpaceOptions
, alt
));
4416 newPos
= MovePositionOutsideChar(newPos
, sel
.MainCaret() - newPos
.Position());
4417 SelectionPosition newCharPos
= SPositionFromLocation(pt
, false, true, false);
4418 newCharPos
= MovePositionOutsideChar(newCharPos
, -1);
4419 inDragDrop
= ddNone
;
4420 sel
.SetMoveExtends(false);
4422 if (NotifyMarginClick(pt
, modifiers
))
4425 NotifyIndicatorClick(true, newPos
.Position(), modifiers
);
4427 bool inSelMargin
= PointInSelMargin(pt
);
4428 // In margin ctrl+(double)click should always select everything
4429 if (ctrl
&& inSelMargin
) {
4431 lastClickTime
= curTime
;
4435 if (shift
&& !inSelMargin
) {
4436 SetSelection(newPos
);
4438 if (((curTime
- lastClickTime
) < Platform::DoubleClickTime()) && Close(pt
, lastClick
, doubleClickCloseThreshold
)) {
4439 //Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime);
4440 SetMouseCapture(true);
4441 if (FineTickerAvailable()) {
4442 FineTickerStart(tickScroll
, 100, 10);
4444 if (!ctrl
|| !multipleSelection
|| (selectionType
!= selChar
&& selectionType
!= selWord
))
4445 SetEmptySelection(newPos
.Position());
4446 bool doubleClick
= false;
4447 // Stop mouse button bounce changing selection type
4448 if (!Platform::MouseButtonBounce() || curTime
!= lastClickTime
) {
4450 // Inside margin selection type should be either selSubLine or selWholeLine.
4451 if (selectionType
== selSubLine
) {
4452 // If it is selSubLine, we're inside a *double* click and word wrap is enabled,
4453 // so we switch to selWholeLine in order to select whole line.
4454 selectionType
= selWholeLine
;
4455 } else if (selectionType
!= selSubLine
&& selectionType
!= selWholeLine
) {
4456 // If it is neither, reset selection type to line selection.
4457 selectionType
= (Wrapping() && (marginOptions
& SC_MARGINOPTION_SUBLINESELECT
)) ? selSubLine
: selWholeLine
;
4460 if (selectionType
== selChar
) {
4461 selectionType
= selWord
;
4463 } else if (selectionType
== selWord
) {
4464 // Since we ended up here, we're inside a *triple* click, which should always select
4465 // whole line regardless of word wrap being enabled or not.
4466 selectionType
= selWholeLine
;
4468 selectionType
= selChar
;
4469 originalAnchorPos
= sel
.MainCaret();
4474 if (selectionType
== selWord
) {
4475 int charPos
= originalAnchorPos
;
4476 if (sel
.MainCaret() == originalAnchorPos
) {
4477 charPos
= PositionFromLocation(pt
, false, true);
4478 charPos
= MovePositionOutsideChar(charPos
, -1);
4481 int startWord
, endWord
;
4482 if ((sel
.MainCaret() >= originalAnchorPos
) && !pdoc
->IsLineEndPosition(charPos
)) {
4483 startWord
= pdoc
->ExtendWordSelect(pdoc
->MovePositionOutsideChar(charPos
+ 1, 1), -1);
4484 endWord
= pdoc
->ExtendWordSelect(charPos
, 1);
4486 // Selecting backwards, or anchor beyond last character on line. In these cases,
4487 // we select the word containing the character to the *left* of the anchor.
4488 if (charPos
> pdoc
->LineStart(pdoc
->LineFromPosition(charPos
))) {
4489 startWord
= pdoc
->ExtendWordSelect(charPos
, -1);
4490 endWord
= pdoc
->ExtendWordSelect(startWord
, 1);
4492 // Anchor at start of line; select nothing to begin with.
4493 startWord
= charPos
;
4498 wordSelectAnchorStartPos
= startWord
;
4499 wordSelectAnchorEndPos
= endWord
;
4500 wordSelectInitialCaretPos
= sel
.MainCaret();
4501 WordSelection(wordSelectInitialCaretPos
);
4502 } else if (selectionType
== selSubLine
|| selectionType
== selWholeLine
) {
4503 lineAnchorPos
= newPos
.Position();
4504 LineSelection(lineAnchorPos
, lineAnchorPos
, selectionType
== selWholeLine
);
4505 //Platform::DebugPrintf("Triple click: %d - %d\n", anchor, currentPos);
4507 SetEmptySelection(sel
.MainCaret());
4509 //Platform::DebugPrintf("Double click: %d - %d\n", anchor, currentPos);
4511 NotifyDoubleClick(pt
, modifiers
);
4512 if (PositionIsHotspot(newCharPos
.Position()))
4513 NotifyHotSpotDoubleClicked(newCharPos
.Position(), modifiers
);
4515 } else { // Single click
4517 if (sel
.IsRectangular() || (sel
.Count() > 1)) {
4518 InvalidateWholeSelection();
4521 sel
.selType
= Selection::selStream
;
4523 // Single click in margin: select whole line or only subline if word wrap is enabled
4524 lineAnchorPos
= newPos
.Position();
4525 selectionType
= (Wrapping() && (marginOptions
& SC_MARGINOPTION_SUBLINESELECT
)) ? selSubLine
: selWholeLine
;
4526 LineSelection(lineAnchorPos
, lineAnchorPos
, selectionType
== selWholeLine
);
4528 // Single shift+click in margin: select from line anchor to clicked line
4529 if (sel
.MainAnchor() > sel
.MainCaret())
4530 lineAnchorPos
= sel
.MainAnchor() - 1;
4532 lineAnchorPos
= sel
.MainAnchor();
4533 // Reset selection type if there is an empty selection.
4534 // This ensures that we don't end up stuck in previous selection mode, which is no longer valid.
4535 // Otherwise, if there's a non empty selection, reset selection type only if it differs from selSubLine and selWholeLine.
4536 // This ensures that we continue selecting in the same selection mode.
4537 if (sel
.Empty() || (selectionType
!= selSubLine
&& selectionType
!= selWholeLine
))
4538 selectionType
= (Wrapping() && (marginOptions
& SC_MARGINOPTION_SUBLINESELECT
)) ? selSubLine
: selWholeLine
;
4539 LineSelection(newPos
.Position(), lineAnchorPos
, selectionType
== selWholeLine
);
4542 SetDragPosition(SelectionPosition(invalidPosition
));
4543 SetMouseCapture(true);
4544 if (FineTickerAvailable()) {
4545 FineTickerStart(tickScroll
, 100, 10);
4548 if (PointIsHotspot(pt
)) {
4549 NotifyHotSpotClicked(newCharPos
.Position(), modifiers
);
4550 hotSpotClickPos
= newCharPos
.Position();
4553 if (PointInSelection(pt
) && !SelectionEmpty())
4554 inDragDrop
= ddInitial
;
4556 inDragDrop
= ddNone
;
4558 SetMouseCapture(true);
4559 if (FineTickerAvailable()) {
4560 FineTickerStart(tickScroll
, 100, 10);
4562 if (inDragDrop
!= ddInitial
) {
4563 SetDragPosition(SelectionPosition(invalidPosition
));
4565 if (ctrl
&& multipleSelection
) {
4566 SelectionRange
range(newPos
);
4567 sel
.TentativeSelection(range
);
4568 InvalidateSelection(range
, true);
4570 InvalidateSelection(SelectionRange(newPos
), true);
4571 if (sel
.Count() > 1)
4573 if ((sel
.Count() > 1) || (sel
.selType
!= Selection::selStream
))
4575 sel
.selType
= alt
? Selection::selRectangle
: Selection::selStream
;
4576 SetSelection(newPos
, newPos
);
4579 SelectionPosition anchorCurrent
= newPos
;
4581 anchorCurrent
= sel
.IsRectangular() ?
4582 sel
.Rectangular().anchor
: sel
.RangeMain().anchor
;
4583 sel
.selType
= alt
? Selection::selRectangle
: Selection::selStream
;
4584 selectionType
= selChar
;
4585 originalAnchorPos
= sel
.MainCaret();
4586 sel
.Rectangular() = SelectionRange(newPos
, anchorCurrent
);
4587 SetRectangularRange();
4591 lastClickTime
= curTime
;
4593 lastXChosen
= static_cast<int>(pt
.x
) + xOffset
;
4594 ShowCaretAtCurrentPosition();
4597 void Editor::RightButtonDownWithModifiers(Point pt
, unsigned int, int modifiers
) {
4598 if (NotifyMarginRightClick(pt
, modifiers
))
4602 void Editor::ButtonDown(Point pt
, unsigned int curTime
, bool shift
, bool ctrl
, bool alt
) {
4603 return ButtonDownWithModifiers(pt
, curTime
, ModifierFlags(shift
, ctrl
, alt
));
4606 bool Editor::PositionIsHotspot(int position
) const {
4607 return vs
.styles
[pdoc
->StyleIndexAt(position
)].hotspot
;
4610 bool Editor::PointIsHotspot(Point pt
) {
4611 int pos
= PositionFromLocation(pt
, true, true);
4612 if (pos
== INVALID_POSITION
)
4614 return PositionIsHotspot(pos
);
4617 void Editor::SetHoverIndicatorPosition(int position
) {
4618 int hoverIndicatorPosPrev
= hoverIndicatorPos
;
4619 hoverIndicatorPos
= INVALID_POSITION
;
4620 if (vs
.indicatorsDynamic
== 0)
4622 if (position
!= INVALID_POSITION
) {
4623 for (Decoration
*deco
= pdoc
->decorations
.root
; deco
; deco
= deco
->next
) {
4624 if (vs
.indicators
[deco
->indicator
].IsDynamic()) {
4625 if (pdoc
->decorations
.ValueAt(deco
->indicator
, position
)) {
4626 hoverIndicatorPos
= position
;
4631 if (hoverIndicatorPosPrev
!= hoverIndicatorPos
) {
4636 void Editor::SetHoverIndicatorPoint(Point pt
) {
4637 if (vs
.indicatorsDynamic
== 0) {
4638 SetHoverIndicatorPosition(INVALID_POSITION
);
4640 SetHoverIndicatorPosition(PositionFromLocation(pt
, true, true));
4644 void Editor::SetHotSpotRange(Point
*pt
) {
4646 int pos
= PositionFromLocation(*pt
, false, true);
4648 // If we don't limit this to word characters then the
4649 // range can encompass more than the run range and then
4650 // the underline will not be drawn properly.
4652 hsNew
.start
= pdoc
->ExtendStyleRange(pos
, -1, vs
.hotspotSingleLine
);
4653 hsNew
.end
= pdoc
->ExtendStyleRange(pos
, 1, vs
.hotspotSingleLine
);
4655 // Only invalidate the range if the hotspot range has changed...
4656 if (!(hsNew
== hotspot
)) {
4657 if (hotspot
.Valid()) {
4658 InvalidateRange(hotspot
.start
, hotspot
.end
);
4661 InvalidateRange(hotspot
.start
, hotspot
.end
);
4664 if (hotspot
.Valid()) {
4665 InvalidateRange(hotspot
.start
, hotspot
.end
);
4667 hotspot
= Range(invalidPosition
);
4671 Range
Editor::GetHotSpotRange() const {
4675 void Editor::ButtonMoveWithModifiers(Point pt
, int modifiers
) {
4676 if ((ptMouseLast
.x
!= pt
.x
) || (ptMouseLast
.y
!= pt
.y
)) {
4680 SelectionPosition movePos
= SPositionFromLocation(pt
, false, false,
4681 AllowVirtualSpace(virtualSpaceOptions
, sel
.IsRectangular()));
4682 movePos
= MovePositionOutsideChar(movePos
, sel
.MainCaret() - movePos
.Position());
4684 if (inDragDrop
== ddInitial
) {
4685 if (DragThreshold(ptMouseLast
, pt
)) {
4686 SetMouseCapture(false);
4687 if (FineTickerAvailable()) {
4688 FineTickerCancel(tickScroll
);
4690 SetDragPosition(movePos
);
4691 CopySelectionRange(&drag
);
4698 PRectangle rcClient
= GetClientRectangle();
4699 Point ptOrigin
= GetVisibleOriginInMain();
4700 rcClient
.Move(0, -ptOrigin
.y
);
4701 if (FineTickerAvailable() && (dwellDelay
< SC_TIME_FOREVER
) && rcClient
.Contains(pt
)) {
4702 FineTickerStart(tickDwell
, dwellDelay
, dwellDelay
/10);
4704 //Platform::DebugPrintf("Move %d %d\n", pt.x, pt.y);
4705 if (HaveMouseCapture()) {
4707 // Slow down autoscrolling/selection
4708 autoScrollTimer
.ticksToWait
-= timer
.tickSize
;
4709 if (autoScrollTimer
.ticksToWait
> 0)
4711 autoScrollTimer
.ticksToWait
= autoScrollDelay
;
4714 if (posDrag
.IsValid()) {
4715 SetDragPosition(movePos
);
4717 if (selectionType
== selChar
) {
4718 if (sel
.selType
== Selection::selStream
&& (modifiers
& SCI_ALT
) && mouseSelectionRectangularSwitch
) {
4719 sel
.selType
= Selection::selRectangle
;
4721 if (sel
.IsRectangular()) {
4722 sel
.Rectangular() = SelectionRange(movePos
, sel
.Rectangular().anchor
);
4723 SetSelection(movePos
, sel
.RangeMain().anchor
);
4724 } else if (sel
.Count() > 1) {
4725 InvalidateSelection(sel
.RangeMain(), false);
4726 SelectionRange
range(movePos
, sel
.RangeMain().anchor
);
4727 sel
.TentativeSelection(range
);
4728 InvalidateSelection(range
, true);
4730 SetSelection(movePos
, sel
.RangeMain().anchor
);
4732 } else if (selectionType
== selWord
) {
4733 // Continue selecting by word
4734 if (movePos
.Position() == wordSelectInitialCaretPos
) { // Didn't move
4735 // No need to do anything. Previously this case was lumped
4736 // in with "Moved forward", but that can be harmful in this
4737 // case: a handler for the NotifyDoubleClick re-adjusts
4738 // the selection for a fancier definition of "word" (for
4739 // example, in Perl it is useful to include the leading
4740 // '$', '%' or '@' on variables for word selection). In this
4741 // the ButtonMove() called via Tick() for auto-scrolling
4742 // could result in the fancier word selection adjustment
4745 wordSelectInitialCaretPos
= -1;
4746 WordSelection(movePos
.Position());
4749 // Continue selecting by line
4750 LineSelection(movePos
.Position(), lineAnchorPos
, selectionType
== selWholeLine
);
4755 int lineMove
= DisplayFromPosition(movePos
.Position());
4756 if (pt
.y
> rcClient
.bottom
) {
4757 ScrollTo(lineMove
- LinesOnScreen() + 1);
4759 } else if (pt
.y
< rcClient
.top
) {
4763 EnsureCaretVisible(false, false, true);
4765 if (hotspot
.Valid() && !PointIsHotspot(pt
))
4766 SetHotSpotRange(NULL
);
4768 if (hotSpotClickPos
!= INVALID_POSITION
&& PositionFromLocation(pt
,true,true) != hotSpotClickPos
) {
4769 if (inDragDrop
== ddNone
) {
4770 DisplayCursor(Window::cursorText
);
4772 hotSpotClickPos
= INVALID_POSITION
;
4776 if (vs
.fixedColumnWidth
> 0) { // There is a margin
4777 if (PointInSelMargin(pt
)) {
4778 DisplayCursor(GetMarginCursor(pt
));
4779 SetHotSpotRange(NULL
);
4780 return; // No need to test for selection
4783 // Display regular (drag) cursor over selection
4784 if (PointInSelection(pt
) && !SelectionEmpty()) {
4785 DisplayCursor(Window::cursorArrow
);
4787 SetHoverIndicatorPoint(pt
);
4788 if (PointIsHotspot(pt
)) {
4789 DisplayCursor(Window::cursorHand
);
4790 SetHotSpotRange(&pt
);
4792 if (hoverIndicatorPos
!= invalidPosition
)
4793 DisplayCursor(Window::cursorHand
);
4795 DisplayCursor(Window::cursorText
);
4796 SetHotSpotRange(NULL
);
4802 void Editor::ButtonMove(Point pt
) {
4803 ButtonMoveWithModifiers(pt
, 0);
4806 void Editor::ButtonUp(Point pt
, unsigned int curTime
, bool ctrl
) {
4807 //Platform::DebugPrintf("ButtonUp %d %d\n", HaveMouseCapture(), inDragDrop);
4808 SelectionPosition newPos
= SPositionFromLocation(pt
, false, false,
4809 AllowVirtualSpace(virtualSpaceOptions
, sel
.IsRectangular()));
4810 if (hoverIndicatorPos
!= INVALID_POSITION
)
4811 InvalidateRange(newPos
.Position(), newPos
.Position() + 1);
4812 newPos
= MovePositionOutsideChar(newPos
, sel
.MainCaret() - newPos
.Position());
4813 if (inDragDrop
== ddInitial
) {
4814 inDragDrop
= ddNone
;
4815 SetEmptySelection(newPos
);
4816 selectionType
= selChar
;
4817 originalAnchorPos
= sel
.MainCaret();
4819 if (hotSpotClickPos
!= INVALID_POSITION
&& PointIsHotspot(pt
)) {
4820 hotSpotClickPos
= INVALID_POSITION
;
4821 SelectionPosition newCharPos
= SPositionFromLocation(pt
, false, true, false);
4822 newCharPos
= MovePositionOutsideChar(newCharPos
, -1);
4823 NotifyHotSpotReleaseClick(newCharPos
.Position(), ctrl
? SCI_CTRL
: 0);
4825 if (HaveMouseCapture()) {
4826 if (PointInSelMargin(pt
)) {
4827 DisplayCursor(GetMarginCursor(pt
));
4829 DisplayCursor(Window::cursorText
);
4830 SetHotSpotRange(NULL
);
4833 SetMouseCapture(false);
4834 if (FineTickerAvailable()) {
4835 FineTickerCancel(tickScroll
);
4837 NotifyIndicatorClick(false, newPos
.Position(), 0);
4838 if (inDragDrop
== ddDragging
) {
4839 SelectionPosition selStart
= SelectionStart();
4840 SelectionPosition selEnd
= SelectionEnd();
4841 if (selStart
< selEnd
) {
4842 if (drag
.Length()) {
4843 const int length
= static_cast<int>(drag
.Length());
4845 const int lengthInserted
= pdoc
->InsertString(
4846 newPos
.Position(), drag
.Data(), length
);
4847 if (lengthInserted
> 0) {
4848 SetSelection(newPos
.Position(), newPos
.Position() + lengthInserted
);
4850 } else if (newPos
< selStart
) {
4851 pdoc
->DeleteChars(selStart
.Position(), static_cast<int>(drag
.Length()));
4852 const int lengthInserted
= pdoc
->InsertString(
4853 newPos
.Position(), drag
.Data(), length
);
4854 if (lengthInserted
> 0) {
4855 SetSelection(newPos
.Position(), newPos
.Position() + lengthInserted
);
4857 } else if (newPos
> selEnd
) {
4858 pdoc
->DeleteChars(selStart
.Position(), static_cast<int>(drag
.Length()));
4859 newPos
.Add(-static_cast<int>(drag
.Length()));
4860 const int lengthInserted
= pdoc
->InsertString(
4861 newPos
.Position(), drag
.Data(), length
);
4862 if (lengthInserted
> 0) {
4863 SetSelection(newPos
.Position(), newPos
.Position() + lengthInserted
);
4866 SetEmptySelection(newPos
.Position());
4870 selectionType
= selChar
;
4873 if (selectionType
== selChar
) {
4874 if (sel
.Count() > 1) {
4876 SelectionRange(newPos
, sel
.Range(sel
.Count() - 1).anchor
);
4877 InvalidateWholeSelection();
4879 SetSelection(newPos
, sel
.RangeMain().anchor
);
4882 sel
.CommitTentative();
4884 SetRectangularRange();
4885 lastClickTime
= curTime
;
4887 lastXChosen
= static_cast<int>(pt
.x
) + xOffset
;
4888 if (sel
.selType
== Selection::selStream
) {
4891 inDragDrop
= ddNone
;
4892 EnsureCaretVisible(false);
4896 // Called frequently to perform background UI including
4897 // caret blinking and automatic scrolling.
4898 void Editor::Tick() {
4899 if (HaveMouseCapture()) {
4901 ButtonMove(ptMouseLast
);
4903 if (caret
.period
> 0) {
4904 timer
.ticksToWait
-= timer
.tickSize
;
4905 if (timer
.ticksToWait
<= 0) {
4906 caret
.on
= !caret
.on
;
4907 timer
.ticksToWait
= caret
.period
;
4913 if (horizontalScrollBarVisible
&& trackLineWidth
&& (view
.lineWidthMaxSeen
> scrollWidth
)) {
4914 scrollWidth
= view
.lineWidthMaxSeen
;
4917 if ((dwellDelay
< SC_TIME_FOREVER
) &&
4918 (ticksToDwell
> 0) &&
4919 (!HaveMouseCapture()) &&
4920 (ptMouseLast
.y
>= 0)) {
4921 ticksToDwell
-= timer
.tickSize
;
4922 if (ticksToDwell
<= 0) {
4924 NotifyDwelling(ptMouseLast
, dwelling
);
4929 bool Editor::Idle() {
4930 bool needWrap
= Wrapping() && wrapPending
.NeedsWrap();
4933 // Wrap lines during idle.
4936 needWrap
= wrapPending
.NeedsWrap();
4937 } else if (needIdleStyling
) {
4941 // Add more idle things to do here, but make sure idleDone is
4942 // set correctly before the function returns. returning
4943 // false will stop calling this idle function until SetIdle() is
4946 const bool idleDone
= !needWrap
&& !needIdleStyling
; // && thatDone && theOtherThingDone...
4951 void Editor::SetTicking(bool) {
4952 // SetTicking is deprecated. In the past it was pure virtual and was overridden in each
4953 // derived platform class but fine grained timers should now be implemented.
4954 // Either way, execution should not arrive here so assert failure.
4958 void Editor::TickFor(TickReason reason
) {
4961 caret
.on
= !caret
.on
;
4968 ButtonMove(ptMouseLast
);
4972 FineTickerCancel(tickWiden
);
4975 if ((!HaveMouseCapture()) &&
4976 (ptMouseLast
.y
>= 0)) {
4978 NotifyDwelling(ptMouseLast
, dwelling
);
4980 FineTickerCancel(tickDwell
);
4983 // tickPlatform handled by subclass
4988 bool Editor::FineTickerAvailable() {
4992 // FineTickerStart is be overridden by subclasses that support fine ticking so
4993 // this method should never be called.
4994 bool Editor::FineTickerRunning(TickReason
) {
4999 // FineTickerStart is be overridden by subclasses that support fine ticking so
5000 // this method should never be called.
5001 void Editor::FineTickerStart(TickReason
, int, int) {
5005 // FineTickerCancel is be overridden by subclasses that support fine ticking so
5006 // this method should never be called.
5007 void Editor::FineTickerCancel(TickReason
) {
5011 void Editor::SetFocusState(bool focusState
) {
5012 hasFocus
= focusState
;
5013 NotifyFocus(hasFocus
);
5017 ShowCaretAtCurrentPosition();
5020 int Editor::PositionAfterArea(PRectangle rcArea
) const {
5021 // The start of the document line after the display line after the area
5022 // This often means that the line after a modification is restyled which helps
5023 // detect multiline comment additions and heals single line comments
5024 int lineAfter
= TopLineOfMain() + static_cast<int>(rcArea
.bottom
- 1) / vs
.lineHeight
+ 1;
5025 if (lineAfter
< cs
.LinesDisplayed())
5026 return pdoc
->LineStart(cs
.DocFromDisplay(lineAfter
) + 1);
5028 return pdoc
->Length();
5031 // Style to a position within the view. If this causes a change at end of last line then
5032 // affects later lines so style all the viewed text.
5033 void Editor::StyleToPositionInView(Position pos
) {
5034 int endWindow
= PositionAfterArea(GetClientDrawingRectangle());
5035 if (pos
> endWindow
)
5037 const int styleAtEnd
= pdoc
->StyleIndexAt(pos
-1);
5038 pdoc
->EnsureStyledTo(pos
);
5039 if ((endWindow
> pos
) && (styleAtEnd
!= pdoc
->StyleIndexAt(pos
-1))) {
5040 // Style at end of line changed so is multi-line change like starting a comment
5041 // so require rest of window to be styled.
5042 DiscardOverdraw(); // Prepared bitmaps may be invalid
5043 // DiscardOverdraw may have truncated client drawing area so recalculate endWindow
5044 endWindow
= PositionAfterArea(GetClientDrawingRectangle());
5045 pdoc
->EnsureStyledTo(endWindow
);
5049 int Editor::PositionAfterMaxStyling(int posMax
, bool scrolling
) const {
5050 if ((idleStyling
== SC_IDLESTYLING_NONE
) || (idleStyling
== SC_IDLESTYLING_AFTERVISIBLE
)) {
5051 // Both states do not limit styling
5055 // Try to keep time taken by styling reasonable so interaction remains smooth.
5056 // When scrolling, allow less time to ensure responsive
5057 const double secondsAllowed
= scrolling
? 0.005 : 0.02;
5059 const int linesToStyle
= Platform::Clamp(static_cast<int>(secondsAllowed
/ pdoc
->durationStyleOneLine
),
5061 const int stylingMaxLine
= std::min(
5062 static_cast<int>(pdoc
->LineFromPosition(pdoc
->GetEndStyled()) + linesToStyle
),
5063 pdoc
->LinesTotal());
5064 return std::min(static_cast<int>(pdoc
->LineStart(stylingMaxLine
)), posMax
);
5067 void Editor::StartIdleStyling(bool truncatedLastStyling
) {
5068 if ((idleStyling
== SC_IDLESTYLING_ALL
) || (idleStyling
== SC_IDLESTYLING_AFTERVISIBLE
)) {
5069 if (pdoc
->GetEndStyled() < pdoc
->Length()) {
5070 // Style remainder of document in idle time
5071 needIdleStyling
= true;
5073 } else if (truncatedLastStyling
) {
5074 needIdleStyling
= true;
5077 if (needIdleStyling
) {
5082 // Style for an area but bound the amount of styling to remain responsive
5083 void Editor::StyleAreaBounded(PRectangle rcArea
, bool scrolling
) {
5084 const int posAfterArea
= PositionAfterArea(rcArea
);
5085 const int posAfterMax
= PositionAfterMaxStyling(posAfterArea
, scrolling
);
5086 if (posAfterMax
< posAfterArea
) {
5087 // Idle styling may be performed before current visible area
5088 // Style a bit now then style further in idle time
5089 pdoc
->StyleToAdjustingLineDuration(posAfterMax
);
5091 // Can style all wanted now.
5092 StyleToPositionInView(posAfterArea
);
5094 StartIdleStyling(posAfterMax
< posAfterArea
);
5097 void Editor::IdleStyling() {
5098 const int posAfterArea
= PositionAfterArea(GetClientRectangle());
5099 const int endGoal
= (idleStyling
>= SC_IDLESTYLING_AFTERVISIBLE
) ?
5100 pdoc
->Length() : posAfterArea
;
5101 const int posAfterMax
= PositionAfterMaxStyling(endGoal
, false);
5102 pdoc
->StyleToAdjustingLineDuration(posAfterMax
);
5103 if (pdoc
->GetEndStyled() >= endGoal
) {
5104 needIdleStyling
= false;
5108 void Editor::IdleWork() {
5109 // Style the line after the modification as this allows modifications that change just the
5110 // line of the modification to heal instead of propagating to the rest of the window.
5111 if (workNeeded
.items
& WorkNeeded::workStyle
) {
5112 StyleToPositionInView(pdoc
->LineStart(pdoc
->LineFromPosition(workNeeded
.upTo
) + 2));
5118 void Editor::QueueIdleWork(WorkNeeded::workItems items
, int upTo
) {
5119 workNeeded
.Need(items
, upTo
);
5122 bool Editor::PaintContains(PRectangle rc
) {
5126 return rcPaint
.Contains(rc
);
5130 bool Editor::PaintContainsMargin() {
5131 if (wMargin
.GetID()) {
5132 // With separate margin view, paint of text view
5133 // never contains margin.
5136 PRectangle rcSelMargin
= GetClientRectangle();
5137 rcSelMargin
.right
= static_cast<XYPOSITION
>(vs
.textStart
);
5138 return PaintContains(rcSelMargin
);
5141 void Editor::CheckForChangeOutsidePaint(Range r
) {
5142 if (paintState
== painting
&& !paintingAllText
) {
5143 //Platform::DebugPrintf("Checking range in paint %d-%d\n", r.start, r.end);
5147 PRectangle rcRange
= RectangleFromRange(r
, 0);
5148 PRectangle rcText
= GetTextRectangle();
5149 if (rcRange
.top
< rcText
.top
) {
5150 rcRange
.top
= rcText
.top
;
5152 if (rcRange
.bottom
> rcText
.bottom
) {
5153 rcRange
.bottom
= rcText
.bottom
;
5156 if (!PaintContains(rcRange
)) {
5158 paintAbandonedByStyling
= true;
5163 void Editor::SetBraceHighlight(Position pos0
, Position pos1
, int matchStyle
) {
5164 if ((pos0
!= braces
[0]) || (pos1
!= braces
[1]) || (matchStyle
!= bracesMatchStyle
)) {
5165 if ((braces
[0] != pos0
) || (matchStyle
!= bracesMatchStyle
)) {
5166 CheckForChangeOutsidePaint(Range(braces
[0]));
5167 CheckForChangeOutsidePaint(Range(pos0
));
5170 if ((braces
[1] != pos1
) || (matchStyle
!= bracesMatchStyle
)) {
5171 CheckForChangeOutsidePaint(Range(braces
[1]));
5172 CheckForChangeOutsidePaint(Range(pos1
));
5175 bracesMatchStyle
= matchStyle
;
5176 if (paintState
== notPainting
) {
5182 void Editor::SetAnnotationHeights(int start
, int end
) {
5183 if (vs
.annotationVisible
) {
5185 bool changedHeight
= false;
5186 for (int line
=start
; line
<end
&& line
<pdoc
->LinesTotal(); line
++) {
5187 int linesWrapped
= 1;
5189 AutoSurface
surface(this);
5190 AutoLineLayout
ll(view
.llc
, view
.RetrieveLineLayout(line
, *this));
5191 if (surface
&& ll
) {
5192 view
.LayoutLine(*this, line
, surface
, vs
, ll
, wrapWidth
);
5193 linesWrapped
= ll
->lines
;
5196 if (cs
.SetHeight(line
, pdoc
->AnnotationLines(line
) + linesWrapped
))
5197 changedHeight
= true;
5199 if (changedHeight
) {
5205 void Editor::SetDocPointer(Document
*document
) {
5206 //Platform::DebugPrintf("** %x setdoc to %x\n", pdoc, document);
5207 pdoc
->RemoveWatcher(this, 0);
5209 if (document
== NULL
) {
5210 pdoc
= new Document();
5216 // Ensure all positions within document
5221 braces
[0] = invalidPosition
;
5222 braces
[1] = invalidPosition
;
5224 vs
.ReleaseAllExtendedStyles();
5226 SetRepresentations();
5228 // Reset the contraction state to fully shown.
5230 cs
.InsertLines(0, pdoc
->LinesTotal() - 1);
5231 SetAnnotationHeights(0, pdoc
->LinesTotal());
5232 view
.llc
.Deallocate();
5235 hotspot
= Range(invalidPosition
);
5236 hoverIndicatorPos
= invalidPosition
;
5238 view
.ClearAllTabstops();
5240 pdoc
->AddWatcher(this, 0);
5245 void Editor::SetAnnotationVisible(int visible
) {
5246 if (vs
.annotationVisible
!= visible
) {
5247 bool changedFromOrToHidden
= ((vs
.annotationVisible
!= 0) != (visible
!= 0));
5248 vs
.annotationVisible
= visible
;
5249 if (changedFromOrToHidden
) {
5250 int dir
= vs
.annotationVisible
? 1 : -1;
5251 for (int line
=0; line
<pdoc
->LinesTotal(); line
++) {
5252 int annotationLines
= pdoc
->AnnotationLines(line
);
5253 if (annotationLines
> 0) {
5254 cs
.SetHeight(line
, cs
.GetHeight(line
) + annotationLines
* dir
);
5263 * Recursively expand a fold, making lines visible except where they have an unexpanded parent.
5265 int Editor::ExpandLine(int line
) {
5266 int lineMaxSubord
= pdoc
->GetLastChild(line
);
5268 while (line
<= lineMaxSubord
) {
5269 cs
.SetVisible(line
, line
, true);
5270 int level
= pdoc
->GetLevel(line
);
5271 if (level
& SC_FOLDLEVELHEADERFLAG
) {
5272 if (cs
.GetExpanded(line
)) {
5273 line
= ExpandLine(line
);
5275 line
= pdoc
->GetLastChild(line
);
5280 return lineMaxSubord
;
5283 void Editor::SetFoldExpanded(int lineDoc
, bool expanded
) {
5284 if (cs
.SetExpanded(lineDoc
, expanded
)) {
5289 void Editor::FoldLine(int line
, int action
) {
5291 if (action
== SC_FOLDACTION_TOGGLE
) {
5292 if ((pdoc
->GetLevel(line
) & SC_FOLDLEVELHEADERFLAG
) == 0) {
5293 line
= pdoc
->GetFoldParent(line
);
5297 action
= (cs
.GetExpanded(line
)) ? SC_FOLDACTION_CONTRACT
: SC_FOLDACTION_EXPAND
;
5300 if (action
== SC_FOLDACTION_CONTRACT
) {
5301 int lineMaxSubord
= pdoc
->GetLastChild(line
);
5302 if (lineMaxSubord
> line
) {
5303 cs
.SetExpanded(line
, 0);
5304 cs
.SetVisible(line
+ 1, lineMaxSubord
, false);
5306 int lineCurrent
= pdoc
->LineFromPosition(sel
.MainCaret());
5307 if (lineCurrent
> line
&& lineCurrent
<= lineMaxSubord
) {
5308 // This does not re-expand the fold
5309 EnsureCaretVisible();
5314 if (!(cs
.GetVisible(line
))) {
5315 EnsureLineVisible(line
, false);
5318 cs
.SetExpanded(line
, 1);
5327 void Editor::FoldExpand(int line
, int action
, int level
) {
5328 bool expanding
= action
== SC_FOLDACTION_EXPAND
;
5329 if (action
== SC_FOLDACTION_TOGGLE
) {
5330 expanding
= !cs
.GetExpanded(line
);
5332 // Ensure child lines lexed and fold information extracted before
5333 // flipping the state.
5334 pdoc
->GetLastChild(line
, LevelNumber(level
));
5335 SetFoldExpanded(line
, expanding
);
5336 if (expanding
&& (cs
.HiddenLines() == 0))
5339 int lineMaxSubord
= pdoc
->GetLastChild(line
, LevelNumber(level
));
5341 cs
.SetVisible(line
, lineMaxSubord
, expanding
);
5342 while (line
<= lineMaxSubord
) {
5343 int levelLine
= pdoc
->GetLevel(line
);
5344 if (levelLine
& SC_FOLDLEVELHEADERFLAG
) {
5345 SetFoldExpanded(line
, expanding
);
5353 int Editor::ContractedFoldNext(int lineStart
) const {
5354 for (int line
= lineStart
; line
<pdoc
->LinesTotal();) {
5355 if (!cs
.GetExpanded(line
) && (pdoc
->GetLevel(line
) & SC_FOLDLEVELHEADERFLAG
))
5357 line
= cs
.ContractedNext(line
+1);
5366 * Recurse up from this line to find any folds that prevent this line from being visible
5367 * and unfold them all.
5369 void Editor::EnsureLineVisible(int lineDoc
, bool enforcePolicy
) {
5371 // In case in need of wrapping to ensure DisplayFromDoc works.
5372 if (lineDoc
>= wrapPending
.start
)
5375 if (!cs
.GetVisible(lineDoc
)) {
5376 // Back up to find a non-blank line
5377 int lookLine
= lineDoc
;
5378 int lookLineLevel
= pdoc
->GetLevel(lookLine
);
5379 while ((lookLine
> 0) && (lookLineLevel
& SC_FOLDLEVELWHITEFLAG
)) {
5380 lookLineLevel
= pdoc
->GetLevel(--lookLine
);
5382 int lineParent
= pdoc
->GetFoldParent(lookLine
);
5383 if (lineParent
< 0) {
5384 // Backed up to a top level line, so try to find parent of initial line
5385 lineParent
= pdoc
->GetFoldParent(lineDoc
);
5387 if (lineParent
>= 0) {
5388 if (lineDoc
!= lineParent
)
5389 EnsureLineVisible(lineParent
, enforcePolicy
);
5390 if (!cs
.GetExpanded(lineParent
)) {
5391 cs
.SetExpanded(lineParent
, 1);
5392 ExpandLine(lineParent
);
5398 if (enforcePolicy
) {
5399 int lineDisplay
= cs
.DisplayFromDoc(lineDoc
);
5400 if (visiblePolicy
& VISIBLE_SLOP
) {
5401 if ((topLine
> lineDisplay
) || ((visiblePolicy
& VISIBLE_STRICT
) && (topLine
+ visibleSlop
> lineDisplay
))) {
5402 SetTopLine(Platform::Clamp(lineDisplay
- visibleSlop
, 0, MaxScrollPos()));
5403 SetVerticalScrollPos();
5405 } else if ((lineDisplay
> topLine
+ LinesOnScreen() - 1) ||
5406 ((visiblePolicy
& VISIBLE_STRICT
) && (lineDisplay
> topLine
+ LinesOnScreen() - 1 - visibleSlop
))) {
5407 SetTopLine(Platform::Clamp(lineDisplay
- LinesOnScreen() + 1 + visibleSlop
, 0, MaxScrollPos()));
5408 SetVerticalScrollPos();
5412 if ((topLine
> lineDisplay
) || (lineDisplay
> topLine
+ LinesOnScreen() - 1) || (visiblePolicy
& VISIBLE_STRICT
)) {
5413 SetTopLine(Platform::Clamp(lineDisplay
- LinesOnScreen() / 2 + 1, 0, MaxScrollPos()));
5414 SetVerticalScrollPos();
5421 void Editor::FoldAll(int action
) {
5422 pdoc
->EnsureStyledTo(pdoc
->Length());
5423 int maxLine
= pdoc
->LinesTotal();
5424 bool expanding
= action
== SC_FOLDACTION_EXPAND
;
5425 if (action
== SC_FOLDACTION_TOGGLE
) {
5426 // Discover current state
5427 for (int lineSeek
= 0; lineSeek
< maxLine
; lineSeek
++) {
5428 if (pdoc
->GetLevel(lineSeek
) & SC_FOLDLEVELHEADERFLAG
) {
5429 expanding
= !cs
.GetExpanded(lineSeek
);
5435 cs
.SetVisible(0, maxLine
-1, true);
5436 for (int line
= 0; line
< maxLine
; line
++) {
5437 int levelLine
= pdoc
->GetLevel(line
);
5438 if (levelLine
& SC_FOLDLEVELHEADERFLAG
) {
5439 SetFoldExpanded(line
, true);
5443 for (int line
= 0; line
< maxLine
; line
++) {
5444 int level
= pdoc
->GetLevel(line
);
5445 if ((level
& SC_FOLDLEVELHEADERFLAG
) &&
5446 (SC_FOLDLEVELBASE
== LevelNumber(level
))) {
5447 SetFoldExpanded(line
, false);
5448 int lineMaxSubord
= pdoc
->GetLastChild(line
, -1);
5449 if (lineMaxSubord
> line
) {
5450 cs
.SetVisible(line
+ 1, lineMaxSubord
, false);
5459 void Editor::FoldChanged(int line
, int levelNow
, int levelPrev
) {
5460 if (levelNow
& SC_FOLDLEVELHEADERFLAG
) {
5461 if (!(levelPrev
& SC_FOLDLEVELHEADERFLAG
)) {
5462 // Adding a fold point.
5463 if (cs
.SetExpanded(line
, true)) {
5466 FoldExpand(line
, SC_FOLDACTION_EXPAND
, levelPrev
);
5468 } else if (levelPrev
& SC_FOLDLEVELHEADERFLAG
) {
5469 const int prevLine
= line
- 1;
5470 const int prevLineLevel
= pdoc
->GetLevel(prevLine
);
5472 // Combining two blocks where the first block is collapsed (e.g. by deleting the line(s) which separate(s) the two blocks)
5473 if ((LevelNumber(prevLineLevel
) == LevelNumber(levelNow
)) && !cs
.GetVisible(prevLine
))
5474 FoldLine(pdoc
->GetFoldParent(prevLine
), SC_FOLDACTION_EXPAND
);
5476 if (!cs
.GetExpanded(line
)) {
5477 // Removing the fold from one that has been contracted so should expand
5478 // otherwise lines are left invisible with no way to make them visible
5479 if (cs
.SetExpanded(line
, true)) {
5482 // Combining two blocks where the second one is collapsed (e.g. by adding characters in the line which separates the two blocks)
5483 FoldExpand(line
, SC_FOLDACTION_EXPAND
, levelPrev
);
5486 if (!(levelNow
& SC_FOLDLEVELWHITEFLAG
) &&
5487 (LevelNumber(levelPrev
) > LevelNumber(levelNow
))) {
5488 if (cs
.HiddenLines()) {
5489 // See if should still be hidden
5490 int parentLine
= pdoc
->GetFoldParent(line
);
5491 if ((parentLine
< 0) || (cs
.GetExpanded(parentLine
) && cs
.GetVisible(parentLine
))) {
5492 cs
.SetVisible(line
, line
, true);
5499 // Combining two blocks where the first one is collapsed (e.g. by adding characters in the line which separates the two blocks)
5500 if (!(levelNow
& SC_FOLDLEVELWHITEFLAG
) && (LevelNumber(levelPrev
) < LevelNumber(levelNow
))) {
5501 if (cs
.HiddenLines()) {
5502 const int parentLine
= pdoc
->GetFoldParent(line
);
5503 if (!cs
.GetExpanded(parentLine
) && cs
.GetVisible(line
))
5504 FoldLine(parentLine
, SC_FOLDACTION_EXPAND
);
5509 void Editor::NeedShown(int pos
, int len
) {
5510 if (foldAutomatic
& SC_AUTOMATICFOLD_SHOW
) {
5511 int lineStart
= pdoc
->LineFromPosition(pos
);
5512 int lineEnd
= pdoc
->LineFromPosition(pos
+len
);
5513 for (int line
= lineStart
; line
<= lineEnd
; line
++) {
5514 EnsureLineVisible(line
, false);
5517 NotifyNeedShown(pos
, len
);
5521 int Editor::GetTag(char *tagValue
, int tagNumber
) {
5522 const char *text
= 0;
5524 if ((tagNumber
>= 1) && (tagNumber
<= 9)) {
5525 char name
[3] = "\\?";
5526 name
[1] = static_cast<char>(tagNumber
+ '0');
5528 text
= pdoc
->SubstituteByPosition(name
, &length
);
5532 memcpy(tagValue
, text
, length
+ 1);
5539 int Editor::ReplaceTarget(bool replacePatterns
, const char *text
, int length
) {
5542 length
= istrlen(text
);
5543 if (replacePatterns
) {
5544 text
= pdoc
->SubstituteByPosition(text
, &length
);
5549 if (targetStart
!= targetEnd
)
5550 pdoc
->DeleteChars(targetStart
, targetEnd
- targetStart
);
5551 targetEnd
= targetStart
;
5552 const int lengthInserted
= pdoc
->InsertString(targetStart
, text
, length
);
5553 targetEnd
= targetStart
+ lengthInserted
;
5557 bool Editor::IsUnicodeMode() const {
5558 return pdoc
&& (SC_CP_UTF8
== pdoc
->dbcsCodePage
);
5561 int Editor::CodePage() const {
5563 return pdoc
->dbcsCodePage
;
5568 int Editor::WrapCount(int line
) {
5569 AutoSurface
surface(this);
5570 AutoLineLayout
ll(view
.llc
, view
.RetrieveLineLayout(line
, *this));
5572 if (surface
&& ll
) {
5573 view
.LayoutLine(*this, line
, surface
, vs
, ll
, wrapWidth
);
5580 void Editor::AddStyledText(char *buffer
, int appendLength
) {
5581 // The buffer consists of alternating character bytes and style bytes
5582 int textLength
= appendLength
/ 2;
5583 std::string
text(textLength
, '\0');
5585 for (i
= 0; i
< textLength
; i
++) {
5586 text
[i
] = buffer
[i
*2];
5588 const int lengthInserted
= pdoc
->InsertString(CurrentPosition(), text
.c_str(), textLength
);
5589 for (i
= 0; i
< textLength
; i
++) {
5590 text
[i
] = buffer
[i
*2+1];
5592 pdoc
->StartStyling(CurrentPosition(), static_cast<unsigned char>(0xff));
5593 pdoc
->SetStyles(textLength
, text
.c_str());
5594 SetEmptySelection(sel
.MainCaret() + lengthInserted
);
5597 bool Editor::ValidMargin(uptr_t wParam
) const {
5598 return wParam
< vs
.ms
.size();
5601 static char *CharPtrFromSPtr(sptr_t lParam
) {
5602 return reinterpret_cast<char *>(lParam
);
5605 void Editor::StyleSetMessage(unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
) {
5606 vs
.EnsureStyle(wParam
);
5608 case SCI_STYLESETFORE
:
5609 vs
.styles
[wParam
].fore
= ColourDesired(static_cast<long>(lParam
));
5611 case SCI_STYLESETBACK
:
5612 vs
.styles
[wParam
].back
= ColourDesired(static_cast<long>(lParam
));
5614 case SCI_STYLESETBOLD
:
5615 vs
.styles
[wParam
].weight
= lParam
!= 0 ? SC_WEIGHT_BOLD
: SC_WEIGHT_NORMAL
;
5617 case SCI_STYLESETWEIGHT
:
5618 vs
.styles
[wParam
].weight
= static_cast<int>(lParam
);
5620 case SCI_STYLESETITALIC
:
5621 vs
.styles
[wParam
].italic
= lParam
!= 0;
5623 case SCI_STYLESETEOLFILLED
:
5624 vs
.styles
[wParam
].eolFilled
= lParam
!= 0;
5626 case SCI_STYLESETSIZE
:
5627 vs
.styles
[wParam
].size
= static_cast<int>(lParam
* SC_FONT_SIZE_MULTIPLIER
);
5629 case SCI_STYLESETSIZEFRACTIONAL
:
5630 vs
.styles
[wParam
].size
= static_cast<int>(lParam
);
5632 case SCI_STYLESETFONT
:
5634 vs
.SetStyleFontName(static_cast<int>(wParam
), CharPtrFromSPtr(lParam
));
5637 case SCI_STYLESETUNDERLINE
:
5638 vs
.styles
[wParam
].underline
= lParam
!= 0;
5640 case SCI_STYLESETCASE
:
5641 vs
.styles
[wParam
].caseForce
= static_cast<Style::ecaseForced
>(lParam
);
5643 case SCI_STYLESETCHARACTERSET
:
5644 vs
.styles
[wParam
].characterSet
= static_cast<int>(lParam
);
5645 pdoc
->SetCaseFolder(NULL
);
5647 case SCI_STYLESETVISIBLE
:
5648 vs
.styles
[wParam
].visible
= lParam
!= 0;
5650 case SCI_STYLESETCHANGEABLE
:
5651 vs
.styles
[wParam
].changeable
= lParam
!= 0;
5653 case SCI_STYLESETHOTSPOT
:
5654 vs
.styles
[wParam
].hotspot
= lParam
!= 0;
5657 InvalidateStyleRedraw();
5660 sptr_t
Editor::StyleGetMessage(unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
) {
5661 vs
.EnsureStyle(wParam
);
5663 case SCI_STYLEGETFORE
:
5664 return vs
.styles
[wParam
].fore
.AsLong();
5665 case SCI_STYLEGETBACK
:
5666 return vs
.styles
[wParam
].back
.AsLong();
5667 case SCI_STYLEGETBOLD
:
5668 return vs
.styles
[wParam
].weight
> SC_WEIGHT_NORMAL
;
5669 case SCI_STYLEGETWEIGHT
:
5670 return vs
.styles
[wParam
].weight
;
5671 case SCI_STYLEGETITALIC
:
5672 return vs
.styles
[wParam
].italic
? 1 : 0;
5673 case SCI_STYLEGETEOLFILLED
:
5674 return vs
.styles
[wParam
].eolFilled
? 1 : 0;
5675 case SCI_STYLEGETSIZE
:
5676 return vs
.styles
[wParam
].size
/ SC_FONT_SIZE_MULTIPLIER
;
5677 case SCI_STYLEGETSIZEFRACTIONAL
:
5678 return vs
.styles
[wParam
].size
;
5679 case SCI_STYLEGETFONT
:
5680 return StringResult(lParam
, vs
.styles
[wParam
].fontName
);
5681 case SCI_STYLEGETUNDERLINE
:
5682 return vs
.styles
[wParam
].underline
? 1 : 0;
5683 case SCI_STYLEGETCASE
:
5684 return static_cast<int>(vs
.styles
[wParam
].caseForce
);
5685 case SCI_STYLEGETCHARACTERSET
:
5686 return vs
.styles
[wParam
].characterSet
;
5687 case SCI_STYLEGETVISIBLE
:
5688 return vs
.styles
[wParam
].visible
? 1 : 0;
5689 case SCI_STYLEGETCHANGEABLE
:
5690 return vs
.styles
[wParam
].changeable
? 1 : 0;
5691 case SCI_STYLEGETHOTSPOT
:
5692 return vs
.styles
[wParam
].hotspot
? 1 : 0;
5697 void Editor::SetSelectionNMessage(unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
) {
5698 InvalidateRange(sel
.Range(wParam
).Start().Position(), sel
.Range(wParam
).End().Position());
5701 case SCI_SETSELECTIONNCARET
:
5702 sel
.Range(wParam
).caret
.SetPosition(static_cast<int>(lParam
));
5705 case SCI_SETSELECTIONNANCHOR
:
5706 sel
.Range(wParam
).anchor
.SetPosition(static_cast<int>(lParam
));
5709 case SCI_SETSELECTIONNCARETVIRTUALSPACE
:
5710 sel
.Range(wParam
).caret
.SetVirtualSpace(static_cast<int>(lParam
));
5713 case SCI_SETSELECTIONNANCHORVIRTUALSPACE
:
5714 sel
.Range(wParam
).anchor
.SetVirtualSpace(static_cast<int>(lParam
));
5717 case SCI_SETSELECTIONNSTART
:
5718 sel
.Range(wParam
).anchor
.SetPosition(static_cast<int>(lParam
));
5721 case SCI_SETSELECTIONNEND
:
5722 sel
.Range(wParam
).caret
.SetPosition(static_cast<int>(lParam
));
5726 InvalidateRange(sel
.Range(wParam
).Start().Position(), sel
.Range(wParam
).End().Position());
5727 ContainerNeedsUpdate(SC_UPDATE_SELECTION
);
5730 sptr_t
Editor::StringResult(sptr_t lParam
, const char *val
) {
5731 const size_t len
= val
? strlen(val
) : 0;
5733 char *ptr
= CharPtrFromSPtr(lParam
);
5735 memcpy(ptr
, val
, len
+1);
5739 return len
; // Not including NUL
5742 sptr_t
Editor::BytesResult(sptr_t lParam
, const unsigned char *val
, size_t len
) {
5743 // No NUL termination: len is number of valid/displayed bytes
5744 if ((lParam
) && (len
> 0)) {
5745 char *ptr
= CharPtrFromSPtr(lParam
);
5747 memcpy(ptr
, val
, len
);
5751 return val
? len
: 0;
5754 sptr_t
Editor::WndProc(unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
) {
5755 //Platform::DebugPrintf("S start wnd proc %d %d %d\n",iMessage, wParam, lParam);
5757 // Optional macro recording hook
5759 NotifyMacroRecord(iMessage
, wParam
, lParam
);
5765 return pdoc
->Length() + 1;
5768 char *ptr
= CharPtrFromSPtr(lParam
);
5769 unsigned int iChar
= 0;
5770 for (; iChar
< wParam
- 1; iChar
++)
5771 ptr
[iChar
] = pdoc
->CharAt(iChar
);
5780 pdoc
->DeleteChars(0, pdoc
->Length());
5781 SetEmptySelection(0);
5782 const char *text
= CharPtrFromSPtr(lParam
);
5783 pdoc
->InsertString(0, text
, istrlen(text
));
5787 case SCI_GETTEXTLENGTH
:
5788 return pdoc
->Length();
5799 case SCI_COPYALLOWLINE
:
5803 case SCI_VERTICALCENTRECARET
:
5804 VerticalCentreCaret();
5807 case SCI_MOVESELECTEDLINESUP
:
5808 MoveSelectedLinesUp();
5811 case SCI_MOVESELECTEDLINESDOWN
:
5812 MoveSelectedLinesDown();
5816 CopyRangeToClipboard(static_cast<int>(wParam
), static_cast<int>(lParam
));
5820 CopyText(static_cast<int>(wParam
), CharPtrFromSPtr(lParam
));
5825 if ((caretSticky
== SC_CARETSTICKY_OFF
) || (caretSticky
== SC_CARETSTICKY_WHITESPACE
)) {
5828 EnsureCaretVisible();
5834 EnsureCaretVisible();
5843 return (pdoc
->CanUndo() && !pdoc
->IsReadOnly()) ? 1 : 0;
5845 case SCI_EMPTYUNDOBUFFER
:
5846 pdoc
->DeleteUndoHistory();
5849 case SCI_GETFIRSTVISIBLELINE
:
5852 case SCI_SETFIRSTVISIBLELINE
:
5853 ScrollTo(static_cast<int>(wParam
));
5856 case SCI_GETLINE
: { // Risk of overwriting the end of the buffer
5857 int lineStart
= pdoc
->LineStart(static_cast<int>(wParam
));
5858 int lineEnd
= pdoc
->LineStart(static_cast<int>(wParam
+ 1));
5860 return lineEnd
- lineStart
;
5862 char *ptr
= CharPtrFromSPtr(lParam
);
5864 for (int iChar
= lineStart
; iChar
< lineEnd
; iChar
++) {
5865 ptr
[iPlace
++] = pdoc
->CharAt(iChar
);
5870 case SCI_GETLINECOUNT
:
5871 if (pdoc
->LinesTotal() == 0)
5874 return pdoc
->LinesTotal();
5877 return !pdoc
->IsSavePoint();
5880 int nStart
= static_cast<int>(wParam
);
5881 int nEnd
= static_cast<int>(lParam
);
5883 nEnd
= pdoc
->Length();
5885 nStart
= nEnd
; // Remove selection
5886 InvalidateSelection(SelectionRange(nStart
, nEnd
));
5888 sel
.selType
= Selection::selStream
;
5889 SetSelection(nEnd
, nStart
);
5890 EnsureCaretVisible();
5894 case SCI_GETSELTEXT
: {
5895 SelectionText selectedText
;
5896 CopySelectionRange(&selectedText
);
5898 return selectedText
.LengthWithTerminator();
5900 char *ptr
= CharPtrFromSPtr(lParam
);
5901 unsigned int iChar
= 0;
5902 if (selectedText
.Length()) {
5903 for (; iChar
< selectedText
.LengthWithTerminator(); iChar
++)
5904 ptr
[iChar
] = selectedText
.Data()[iChar
];
5912 case SCI_LINEFROMPOSITION
:
5913 if (static_cast<int>(wParam
) < 0)
5915 return pdoc
->LineFromPosition(static_cast<int>(wParam
));
5917 case SCI_POSITIONFROMLINE
:
5918 if (static_cast<int>(wParam
) < 0)
5919 wParam
= pdoc
->LineFromPosition(SelectionStart().Position());
5921 return 0; // Even if there is no text, there is a first line that starts at 0
5922 if (static_cast<int>(wParam
) > pdoc
->LinesTotal())
5924 //if (wParam > pdoc->LineFromPosition(pdoc->Length())) // Useful test, anyway...
5926 return pdoc
->LineStart(static_cast<int>(wParam
));
5928 // Replacement of the old Scintilla interpretation of EM_LINELENGTH
5929 case SCI_LINELENGTH
:
5930 if ((static_cast<int>(wParam
) < 0) ||
5931 (static_cast<int>(wParam
) > pdoc
->LineFromPosition(pdoc
->Length())))
5933 return pdoc
->LineStart(static_cast<int>(wParam
) + 1) - pdoc
->LineStart(static_cast<int>(wParam
));
5935 case SCI_REPLACESEL
: {
5940 char *replacement
= CharPtrFromSPtr(lParam
);
5941 const int lengthInserted
= pdoc
->InsertString(
5942 sel
.MainCaret(), replacement
, istrlen(replacement
));
5943 SetEmptySelection(sel
.MainCaret() + lengthInserted
);
5944 EnsureCaretVisible();
5948 case SCI_SETTARGETSTART
:
5949 targetStart
= static_cast<int>(wParam
);
5952 case SCI_GETTARGETSTART
:
5955 case SCI_SETTARGETEND
:
5956 targetEnd
= static_cast<int>(wParam
);
5959 case SCI_GETTARGETEND
:
5962 case SCI_SETTARGETRANGE
:
5963 targetStart
= static_cast<int>(wParam
);
5964 targetEnd
= static_cast<int>(lParam
);
5967 case SCI_TARGETWHOLEDOCUMENT
:
5969 targetEnd
= pdoc
->Length();
5972 case SCI_TARGETFROMSELECTION
:
5973 if (sel
.MainCaret() < sel
.MainAnchor()) {
5974 targetStart
= sel
.MainCaret();
5975 targetEnd
= sel
.MainAnchor();
5977 targetStart
= sel
.MainAnchor();
5978 targetEnd
= sel
.MainCaret();
5982 case SCI_GETTARGETTEXT
: {
5983 std::string text
= RangeText(targetStart
, targetEnd
);
5984 return BytesResult(lParam
, reinterpret_cast<const unsigned char *>(text
.c_str()), text
.length());
5987 case SCI_REPLACETARGET
:
5988 PLATFORM_ASSERT(lParam
);
5989 return ReplaceTarget(false, CharPtrFromSPtr(lParam
), static_cast<int>(wParam
));
5991 case SCI_REPLACETARGETRE
:
5992 PLATFORM_ASSERT(lParam
);
5993 return ReplaceTarget(true, CharPtrFromSPtr(lParam
), static_cast<int>(wParam
));
5995 case SCI_SEARCHINTARGET
:
5996 PLATFORM_ASSERT(lParam
);
5997 return SearchInTarget(CharPtrFromSPtr(lParam
), static_cast<int>(wParam
));
5999 case SCI_SETSEARCHFLAGS
:
6000 searchFlags
= static_cast<int>(wParam
);
6003 case SCI_GETSEARCHFLAGS
:
6007 return GetTag(CharPtrFromSPtr(lParam
), static_cast<int>(wParam
));
6009 case SCI_POSITIONBEFORE
:
6010 return pdoc
->MovePositionOutsideChar(static_cast<int>(wParam
) - 1, -1, true);
6012 case SCI_POSITIONAFTER
:
6013 return pdoc
->MovePositionOutsideChar(static_cast<int>(wParam
) + 1, 1, true);
6015 case SCI_POSITIONRELATIVE
:
6016 return Platform::Clamp(pdoc
->GetRelativePosition(static_cast<int>(wParam
), static_cast<int>(lParam
)), 0, pdoc
->Length());
6018 case SCI_LINESCROLL
:
6019 ScrollTo(topLine
+ static_cast<int>(lParam
));
6020 HorizontalScrollTo(xOffset
+ static_cast<int>(wParam
)* static_cast<int>(vs
.spaceWidth
));
6023 case SCI_SETXOFFSET
:
6024 xOffset
= static_cast<int>(wParam
);
6025 ContainerNeedsUpdate(SC_UPDATE_H_SCROLL
);
6026 SetHorizontalScrollPos();
6030 case SCI_GETXOFFSET
:
6033 case SCI_CHOOSECARETX
:
6037 case SCI_SCROLLCARET
:
6038 EnsureCaretVisible();
6041 case SCI_SETREADONLY
:
6042 pdoc
->SetReadOnly(wParam
!= 0);
6045 case SCI_GETREADONLY
:
6046 return pdoc
->IsReadOnly();
6051 case SCI_POINTXFROMPOSITION
:
6055 Point pt
= LocationFromPosition(static_cast<int>(lParam
));
6056 // Convert to view-relative
6057 return static_cast<int>(pt
.x
) - vs
.textStart
+ vs
.fixedColumnWidth
;
6060 case SCI_POINTYFROMPOSITION
:
6064 Point pt
= LocationFromPosition(static_cast<int>(lParam
));
6065 return static_cast<int>(pt
.y
);
6069 return FindText(wParam
, lParam
);
6071 case SCI_GETTEXTRANGE
: {
6074 Sci_TextRange
*tr
= reinterpret_cast<Sci_TextRange
*>(lParam
);
6075 int cpMax
= static_cast<int>(tr
->chrg
.cpMax
);
6077 cpMax
= pdoc
->Length();
6078 PLATFORM_ASSERT(cpMax
<= pdoc
->Length());
6079 int len
= static_cast<int>(cpMax
- tr
->chrg
.cpMin
); // No -1 as cpMin and cpMax are referring to inter character positions
6080 pdoc
->GetCharRange(tr
->lpstrText
, static_cast<int>(tr
->chrg
.cpMin
), len
);
6081 // Spec says copied text is terminated with a NUL
6082 tr
->lpstrText
[len
] = '\0';
6083 return len
; // Not including NUL
6086 case SCI_HIDESELECTION
:
6087 view
.hideSelection
= wParam
!= 0;
6091 case SCI_FORMATRANGE
:
6092 return FormatRange(wParam
!= 0, reinterpret_cast<Sci_RangeToFormat
*>(lParam
));
6094 case SCI_GETMARGINLEFT
:
6095 return vs
.leftMarginWidth
;
6097 case SCI_GETMARGINRIGHT
:
6098 return vs
.rightMarginWidth
;
6100 case SCI_SETMARGINLEFT
:
6101 lastXChosen
+= static_cast<int>(lParam
) - vs
.leftMarginWidth
;
6102 vs
.leftMarginWidth
= static_cast<int>(lParam
);
6103 InvalidateStyleRedraw();
6106 case SCI_SETMARGINRIGHT
:
6107 vs
.rightMarginWidth
= static_cast<int>(lParam
);
6108 InvalidateStyleRedraw();
6111 // Control specific mesages
6116 const int lengthInserted
= pdoc
->InsertString(
6117 CurrentPosition(), CharPtrFromSPtr(lParam
), static_cast<int>(wParam
));
6118 SetEmptySelection(sel
.MainCaret() + lengthInserted
);
6122 case SCI_ADDSTYLEDTEXT
:
6124 AddStyledText(CharPtrFromSPtr(lParam
), static_cast<int>(wParam
));
6127 case SCI_INSERTTEXT
: {
6130 int insertPos
= static_cast<int>(wParam
);
6131 if (static_cast<int>(wParam
) == -1)
6132 insertPos
= CurrentPosition();
6133 int newCurrent
= CurrentPosition();
6134 char *sz
= CharPtrFromSPtr(lParam
);
6135 const int lengthInserted
= pdoc
->InsertString(insertPos
, sz
, istrlen(sz
));
6136 if (newCurrent
> insertPos
)
6137 newCurrent
+= lengthInserted
;
6138 SetEmptySelection(newCurrent
);
6142 case SCI_CHANGEINSERTION
:
6143 PLATFORM_ASSERT(lParam
);
6144 pdoc
->ChangeInsertion(CharPtrFromSPtr(lParam
), static_cast<int>(wParam
));
6147 case SCI_APPENDTEXT
:
6148 pdoc
->InsertString(pdoc
->Length(), CharPtrFromSPtr(lParam
), static_cast<int>(wParam
));
6155 case SCI_DELETERANGE
:
6156 pdoc
->DeleteChars(static_cast<int>(wParam
), static_cast<int>(lParam
));
6159 case SCI_CLEARDOCUMENTSTYLE
:
6160 ClearDocumentStyle();
6163 case SCI_SETUNDOCOLLECTION
:
6164 pdoc
->SetUndoCollection(wParam
!= 0);
6167 case SCI_GETUNDOCOLLECTION
:
6168 return pdoc
->IsCollectingUndo();
6170 case SCI_BEGINUNDOACTION
:
6171 pdoc
->BeginUndoAction();
6174 case SCI_ENDUNDOACTION
:
6175 pdoc
->EndUndoAction();
6178 case SCI_GETCARETPERIOD
:
6179 return caret
.period
;
6181 case SCI_SETCARETPERIOD
:
6182 CaretSetPeriod(static_cast<int>(wParam
));
6185 case SCI_GETWORDCHARS
:
6186 return pdoc
->GetCharsOfClass(CharClassify::ccWord
, reinterpret_cast<unsigned char *>(lParam
));
6188 case SCI_SETWORDCHARS
: {
6189 pdoc
->SetDefaultCharClasses(false);
6192 pdoc
->SetCharClasses(reinterpret_cast<unsigned char *>(lParam
), CharClassify::ccWord
);
6196 case SCI_GETWHITESPACECHARS
:
6197 return pdoc
->GetCharsOfClass(CharClassify::ccSpace
, reinterpret_cast<unsigned char *>(lParam
));
6199 case SCI_SETWHITESPACECHARS
: {
6202 pdoc
->SetCharClasses(reinterpret_cast<unsigned char *>(lParam
), CharClassify::ccSpace
);
6206 case SCI_GETPUNCTUATIONCHARS
:
6207 return pdoc
->GetCharsOfClass(CharClassify::ccPunctuation
, reinterpret_cast<unsigned char *>(lParam
));
6209 case SCI_SETPUNCTUATIONCHARS
: {
6212 pdoc
->SetCharClasses(reinterpret_cast<unsigned char *>(lParam
), CharClassify::ccPunctuation
);
6216 case SCI_SETCHARSDEFAULT
:
6217 pdoc
->SetDefaultCharClasses(true);
6221 return pdoc
->Length();
6224 pdoc
->Allocate(static_cast<int>(wParam
));
6228 return pdoc
->CharAt(static_cast<int>(wParam
));
6230 case SCI_SETCURRENTPOS
:
6231 if (sel
.IsRectangular()) {
6232 sel
.Rectangular().caret
.SetPosition(static_cast<int>(wParam
));
6233 SetRectangularRange();
6236 SetSelection(static_cast<int>(wParam
), sel
.MainAnchor());
6240 case SCI_GETCURRENTPOS
:
6241 return sel
.IsRectangular() ? sel
.Rectangular().caret
.Position() : sel
.MainCaret();
6244 if (sel
.IsRectangular()) {
6245 sel
.Rectangular().anchor
.SetPosition(static_cast<int>(wParam
));
6246 SetRectangularRange();
6249 SetSelection(sel
.MainCaret(), static_cast<int>(wParam
));
6254 return sel
.IsRectangular() ? sel
.Rectangular().anchor
.Position() : sel
.MainAnchor();
6256 case SCI_SETSELECTIONSTART
:
6257 SetSelection(Platform::Maximum(sel
.MainCaret(), static_cast<int>(wParam
)), static_cast<int>(wParam
));
6260 case SCI_GETSELECTIONSTART
:
6261 return sel
.LimitsForRectangularElseMain().start
.Position();
6263 case SCI_SETSELECTIONEND
:
6264 SetSelection(static_cast<int>(wParam
), Platform::Minimum(sel
.MainAnchor(), static_cast<int>(wParam
)));
6267 case SCI_GETSELECTIONEND
:
6268 return sel
.LimitsForRectangularElseMain().end
.Position();
6270 case SCI_SETEMPTYSELECTION
:
6271 SetEmptySelection(static_cast<int>(wParam
));
6274 case SCI_SETPRINTMAGNIFICATION
:
6275 view
.printParameters
.magnification
= static_cast<int>(wParam
);
6278 case SCI_GETPRINTMAGNIFICATION
:
6279 return view
.printParameters
.magnification
;
6281 case SCI_SETPRINTCOLOURMODE
:
6282 view
.printParameters
.colourMode
= static_cast<int>(wParam
);
6285 case SCI_GETPRINTCOLOURMODE
:
6286 return view
.printParameters
.colourMode
;
6288 case SCI_SETPRINTWRAPMODE
:
6289 view
.printParameters
.wrapState
= (wParam
== SC_WRAP_WORD
) ? eWrapWord
: eWrapNone
;
6292 case SCI_GETPRINTWRAPMODE
:
6293 return view
.printParameters
.wrapState
;
6295 case SCI_GETSTYLEAT
:
6296 if (static_cast<int>(wParam
) >= pdoc
->Length())
6299 return pdoc
->StyleAt(static_cast<int>(wParam
));
6309 case SCI_SETSAVEPOINT
:
6310 pdoc
->SetSavePoint();
6313 case SCI_GETSTYLEDTEXT
: {
6316 Sci_TextRange
*tr
= reinterpret_cast<Sci_TextRange
*>(lParam
);
6318 for (long iChar
= tr
->chrg
.cpMin
; iChar
< tr
->chrg
.cpMax
; iChar
++) {
6319 tr
->lpstrText
[iPlace
++] = pdoc
->CharAt(static_cast<int>(iChar
));
6320 tr
->lpstrText
[iPlace
++] = pdoc
->StyleAt(static_cast<int>(iChar
));
6322 tr
->lpstrText
[iPlace
] = '\0';
6323 tr
->lpstrText
[iPlace
+ 1] = '\0';
6328 return (pdoc
->CanRedo() && !pdoc
->IsReadOnly()) ? 1 : 0;
6330 case SCI_MARKERLINEFROMHANDLE
:
6331 return pdoc
->LineFromHandle(static_cast<int>(wParam
));
6333 case SCI_MARKERDELETEHANDLE
:
6334 pdoc
->DeleteMarkFromHandle(static_cast<int>(wParam
));
6338 return vs
.viewWhitespace
;
6341 vs
.viewWhitespace
= static_cast<WhiteSpaceVisibility
>(wParam
);
6345 case SCI_GETTABDRAWMODE
:
6346 return vs
.tabDrawMode
;
6348 case SCI_SETTABDRAWMODE
:
6349 vs
.tabDrawMode
= static_cast<TabDrawMode
>(wParam
);
6353 case SCI_GETWHITESPACESIZE
:
6354 return vs
.whitespaceSize
;
6356 case SCI_SETWHITESPACESIZE
:
6357 vs
.whitespaceSize
= static_cast<int>(wParam
);
6361 case SCI_POSITIONFROMPOINT
:
6362 return PositionFromLocation(Point::FromInts(static_cast<int>(wParam
) - vs
.ExternalMarginWidth(), static_cast<int>(lParam
)),
6365 case SCI_POSITIONFROMPOINTCLOSE
:
6366 return PositionFromLocation(Point::FromInts(static_cast<int>(wParam
) - vs
.ExternalMarginWidth(), static_cast<int>(lParam
)),
6369 case SCI_CHARPOSITIONFROMPOINT
:
6370 return PositionFromLocation(Point::FromInts(static_cast<int>(wParam
) - vs
.ExternalMarginWidth(), static_cast<int>(lParam
)),
6373 case SCI_CHARPOSITIONFROMPOINTCLOSE
:
6374 return PositionFromLocation(Point::FromInts(static_cast<int>(wParam
) - vs
.ExternalMarginWidth(), static_cast<int>(lParam
)),
6378 GoToLine(static_cast<int>(wParam
));
6382 SetEmptySelection(static_cast<int>(wParam
));
6383 EnsureCaretVisible();
6386 case SCI_GETCURLINE
: {
6387 int lineCurrentPos
= pdoc
->LineFromPosition(sel
.MainCaret());
6388 int lineStart
= pdoc
->LineStart(lineCurrentPos
);
6389 unsigned int lineEnd
= pdoc
->LineStart(lineCurrentPos
+ 1);
6391 return 1 + lineEnd
- lineStart
;
6393 PLATFORM_ASSERT(wParam
> 0);
6394 char *ptr
= CharPtrFromSPtr(lParam
);
6395 unsigned int iPlace
= 0;
6396 for (unsigned int iChar
= lineStart
; iChar
< lineEnd
&& iPlace
< wParam
- 1; iChar
++) {
6397 ptr
[iPlace
++] = pdoc
->CharAt(iChar
);
6400 return sel
.MainCaret() - lineStart
;
6403 case SCI_GETENDSTYLED
:
6404 return pdoc
->GetEndStyled();
6406 case SCI_GETEOLMODE
:
6407 return pdoc
->eolMode
;
6409 case SCI_SETEOLMODE
:
6410 pdoc
->eolMode
= static_cast<int>(wParam
);
6413 case SCI_SETLINEENDTYPESALLOWED
:
6414 if (pdoc
->SetLineEndTypesAllowed(static_cast<int>(wParam
))) {
6416 cs
.InsertLines(0, pdoc
->LinesTotal() - 1);
6417 SetAnnotationHeights(0, pdoc
->LinesTotal());
6418 InvalidateStyleRedraw();
6422 case SCI_GETLINEENDTYPESALLOWED
:
6423 return pdoc
->GetLineEndTypesAllowed();
6425 case SCI_GETLINEENDTYPESACTIVE
:
6426 return pdoc
->GetLineEndTypesActive();
6428 case SCI_STARTSTYLING
:
6429 pdoc
->StartStyling(static_cast<int>(wParam
), static_cast<char>(lParam
));
6432 case SCI_SETSTYLING
:
6433 if (static_cast<int>(wParam
) < 0)
6434 errorStatus
= SC_STATUS_FAILURE
;
6436 pdoc
->SetStyleFor(static_cast<int>(wParam
), static_cast<char>(lParam
));
6439 case SCI_SETSTYLINGEX
: // Specify a complete styling buffer
6442 pdoc
->SetStyles(static_cast<int>(wParam
), CharPtrFromSPtr(lParam
));
6445 case SCI_SETBUFFEREDDRAW
:
6446 view
.bufferedDraw
= wParam
!= 0;
6449 case SCI_GETBUFFEREDDRAW
:
6450 return view
.bufferedDraw
;
6452 case SCI_GETTWOPHASEDRAW
:
6453 return view
.phasesDraw
== EditView::phasesTwo
;
6455 case SCI_SETTWOPHASEDRAW
:
6456 if (view
.SetTwoPhaseDraw(wParam
!= 0))
6457 InvalidateStyleRedraw();
6460 case SCI_GETPHASESDRAW
:
6461 return view
.phasesDraw
;
6463 case SCI_SETPHASESDRAW
:
6464 if (view
.SetPhasesDraw(static_cast<int>(wParam
)))
6465 InvalidateStyleRedraw();
6468 case SCI_SETFONTQUALITY
:
6469 vs
.extraFontFlag
&= ~SC_EFF_QUALITY_MASK
;
6470 vs
.extraFontFlag
|= (wParam
& SC_EFF_QUALITY_MASK
);
6471 InvalidateStyleRedraw();
6474 case SCI_GETFONTQUALITY
:
6475 return (vs
.extraFontFlag
& SC_EFF_QUALITY_MASK
);
6477 case SCI_SETTABWIDTH
:
6479 pdoc
->tabInChars
= static_cast<int>(wParam
);
6480 if (pdoc
->indentInChars
== 0)
6481 pdoc
->actualIndentInChars
= pdoc
->tabInChars
;
6483 InvalidateStyleRedraw();
6486 case SCI_GETTABWIDTH
:
6487 return pdoc
->tabInChars
;
6489 case SCI_CLEARTABSTOPS
:
6490 if (view
.ClearTabstops(static_cast<int>(wParam
))) {
6491 DocModification
mh(SC_MOD_CHANGETABSTOPS
, 0, 0, 0, 0, static_cast<int>(wParam
));
6492 NotifyModified(pdoc
, mh
, NULL
);
6496 case SCI_ADDTABSTOP
:
6497 if (view
.AddTabstop(static_cast<int>(wParam
), static_cast<int>(lParam
))) {
6498 DocModification
mh(SC_MOD_CHANGETABSTOPS
, 0, 0, 0, 0, static_cast<int>(wParam
));
6499 NotifyModified(pdoc
, mh
, NULL
);
6503 case SCI_GETNEXTTABSTOP
:
6504 return view
.GetNextTabstop(static_cast<int>(wParam
), static_cast<int>(lParam
));
6507 pdoc
->indentInChars
= static_cast<int>(wParam
);
6508 if (pdoc
->indentInChars
!= 0)
6509 pdoc
->actualIndentInChars
= pdoc
->indentInChars
;
6511 pdoc
->actualIndentInChars
= pdoc
->tabInChars
;
6512 InvalidateStyleRedraw();
6516 return pdoc
->indentInChars
;
6518 case SCI_SETUSETABS
:
6519 pdoc
->useTabs
= wParam
!= 0;
6520 InvalidateStyleRedraw();
6523 case SCI_GETUSETABS
:
6524 return pdoc
->useTabs
;
6526 case SCI_SETLINEINDENTATION
:
6527 pdoc
->SetLineIndentation(static_cast<int>(wParam
), static_cast<int>(lParam
));
6530 case SCI_GETLINEINDENTATION
:
6531 return pdoc
->GetLineIndentation(static_cast<int>(wParam
));
6533 case SCI_GETLINEINDENTPOSITION
:
6534 return pdoc
->GetLineIndentPosition(static_cast<int>(wParam
));
6536 case SCI_SETTABINDENTS
:
6537 pdoc
->tabIndents
= wParam
!= 0;
6540 case SCI_GETTABINDENTS
:
6541 return pdoc
->tabIndents
;
6543 case SCI_SETBACKSPACEUNINDENTS
:
6544 pdoc
->backspaceUnindents
= wParam
!= 0;
6547 case SCI_GETBACKSPACEUNINDENTS
:
6548 return pdoc
->backspaceUnindents
;
6550 case SCI_SETMOUSEDWELLTIME
:
6551 dwellDelay
= static_cast<int>(wParam
);
6552 ticksToDwell
= dwellDelay
;
6555 case SCI_GETMOUSEDWELLTIME
:
6558 case SCI_WORDSTARTPOSITION
:
6559 return pdoc
->ExtendWordSelect(static_cast<int>(wParam
), -1, lParam
!= 0);
6561 case SCI_WORDENDPOSITION
:
6562 return pdoc
->ExtendWordSelect(static_cast<int>(wParam
), 1, lParam
!= 0);
6564 case SCI_ISRANGEWORD
:
6565 return pdoc
->IsWordAt(static_cast<int>(wParam
), static_cast<int>(lParam
));
6567 case SCI_SETIDLESTYLING
:
6568 idleStyling
= static_cast<int>(wParam
);
6571 case SCI_GETIDLESTYLING
:
6574 case SCI_SETWRAPMODE
:
6575 if (vs
.SetWrapState(static_cast<int>(wParam
))) {
6577 ContainerNeedsUpdate(SC_UPDATE_H_SCROLL
);
6578 InvalidateStyleRedraw();
6579 ReconfigureScrollBars();
6583 case SCI_GETWRAPMODE
:
6584 return vs
.wrapState
;
6586 case SCI_SETWRAPVISUALFLAGS
:
6587 if (vs
.SetWrapVisualFlags(static_cast<int>(wParam
))) {
6588 InvalidateStyleRedraw();
6589 ReconfigureScrollBars();
6593 case SCI_GETWRAPVISUALFLAGS
:
6594 return vs
.wrapVisualFlags
;
6596 case SCI_SETWRAPVISUALFLAGSLOCATION
:
6597 if (vs
.SetWrapVisualFlagsLocation(static_cast<int>(wParam
))) {
6598 InvalidateStyleRedraw();
6602 case SCI_GETWRAPVISUALFLAGSLOCATION
:
6603 return vs
.wrapVisualFlagsLocation
;
6605 case SCI_SETWRAPSTARTINDENT
:
6606 if (vs
.SetWrapVisualStartIndent(static_cast<int>(wParam
))) {
6607 InvalidateStyleRedraw();
6608 ReconfigureScrollBars();
6612 case SCI_GETWRAPSTARTINDENT
:
6613 return vs
.wrapVisualStartIndent
;
6615 case SCI_SETWRAPINDENTMODE
:
6616 if (vs
.SetWrapIndentMode(static_cast<int>(wParam
))) {
6617 InvalidateStyleRedraw();
6618 ReconfigureScrollBars();
6622 case SCI_GETWRAPINDENTMODE
:
6623 return vs
.wrapIndentMode
;
6625 case SCI_SETLAYOUTCACHE
:
6626 view
.llc
.SetLevel(static_cast<int>(wParam
));
6629 case SCI_GETLAYOUTCACHE
:
6630 return view
.llc
.GetLevel();
6632 case SCI_SETPOSITIONCACHE
:
6633 view
.posCache
.SetSize(wParam
);
6636 case SCI_GETPOSITIONCACHE
:
6637 return view
.posCache
.GetSize();
6639 case SCI_SETSCROLLWIDTH
:
6640 PLATFORM_ASSERT(wParam
> 0);
6641 if ((wParam
> 0) && (wParam
!= static_cast<unsigned int >(scrollWidth
))) {
6642 view
.lineWidthMaxSeen
= 0;
6643 scrollWidth
= static_cast<int>(wParam
);
6648 case SCI_GETSCROLLWIDTH
:
6651 case SCI_SETSCROLLWIDTHTRACKING
:
6652 trackLineWidth
= wParam
!= 0;
6655 case SCI_GETSCROLLWIDTHTRACKING
:
6656 return trackLineWidth
;
6662 case SCI_LINESSPLIT
:
6663 LinesSplit(static_cast<int>(wParam
));
6667 PLATFORM_ASSERT(wParam
< vs
.styles
.size());
6668 PLATFORM_ASSERT(lParam
);
6669 return TextWidth(static_cast<int>(wParam
), CharPtrFromSPtr(lParam
));
6671 case SCI_TEXTHEIGHT
:
6673 return vs
.lineHeight
;
6675 case SCI_SETENDATLASTLINE
:
6676 PLATFORM_ASSERT((wParam
== 0) || (wParam
== 1));
6677 if (endAtLastLine
!= (wParam
!= 0)) {
6678 endAtLastLine
= wParam
!= 0;
6683 case SCI_GETENDATLASTLINE
:
6684 return endAtLastLine
;
6686 case SCI_SETCARETSTICKY
:
6687 PLATFORM_ASSERT(wParam
<= SC_CARETSTICKY_WHITESPACE
);
6688 if (wParam
<= SC_CARETSTICKY_WHITESPACE
) {
6689 caretSticky
= static_cast<int>(wParam
);
6693 case SCI_GETCARETSTICKY
:
6696 case SCI_TOGGLECARETSTICKY
:
6697 caretSticky
= !caretSticky
;
6701 return pdoc
->GetColumn(static_cast<int>(wParam
));
6703 case SCI_FINDCOLUMN
:
6704 return pdoc
->FindColumn(static_cast<int>(wParam
), static_cast<int>(lParam
));
6706 case SCI_SETHSCROLLBAR
:
6707 if (horizontalScrollBarVisible
!= (wParam
!= 0)) {
6708 horizontalScrollBarVisible
= wParam
!= 0;
6710 ReconfigureScrollBars();
6714 case SCI_GETHSCROLLBAR
:
6715 return horizontalScrollBarVisible
;
6717 case SCI_SETVSCROLLBAR
:
6718 if (verticalScrollBarVisible
!= (wParam
!= 0)) {
6719 verticalScrollBarVisible
= wParam
!= 0;
6721 ReconfigureScrollBars();
6722 if (verticalScrollBarVisible
)
6723 SetVerticalScrollPos();
6727 case SCI_GETVSCROLLBAR
:
6728 return verticalScrollBarVisible
;
6730 case SCI_SETINDENTATIONGUIDES
:
6731 vs
.viewIndentationGuides
= IndentView(wParam
);
6735 case SCI_GETINDENTATIONGUIDES
:
6736 return vs
.viewIndentationGuides
;
6738 case SCI_SETHIGHLIGHTGUIDE
:
6739 if ((highlightGuideColumn
!= static_cast<int>(wParam
)) || (wParam
> 0)) {
6740 highlightGuideColumn
= static_cast<int>(wParam
);
6745 case SCI_GETHIGHLIGHTGUIDE
:
6746 return highlightGuideColumn
;
6748 case SCI_GETLINEENDPOSITION
:
6749 return pdoc
->LineEnd(static_cast<int>(wParam
));
6751 case SCI_SETCODEPAGE
:
6752 if (ValidCodePage(static_cast<int>(wParam
))) {
6753 if (pdoc
->SetDBCSCodePage(static_cast<int>(wParam
))) {
6755 cs
.InsertLines(0, pdoc
->LinesTotal() - 1);
6756 SetAnnotationHeights(0, pdoc
->LinesTotal());
6757 InvalidateStyleRedraw();
6758 SetRepresentations();
6763 case SCI_GETCODEPAGE
:
6764 return pdoc
->dbcsCodePage
;
6766 case SCI_SETIMEINTERACTION
:
6767 imeInteraction
= static_cast<EditModel::IMEInteraction
>(wParam
);
6770 case SCI_GETIMEINTERACTION
:
6771 return imeInteraction
;
6773 // Marker definition and setting
6774 case SCI_MARKERDEFINE
:
6775 if (wParam
<= MARKER_MAX
) {
6776 vs
.markers
[wParam
].markType
= static_cast<int>(lParam
);
6777 vs
.CalcLargestMarkerHeight();
6779 InvalidateStyleData();
6783 case SCI_MARKERSYMBOLDEFINED
:
6784 if (wParam
<= MARKER_MAX
)
6785 return vs
.markers
[wParam
].markType
;
6789 case SCI_MARKERSETFORE
:
6790 if (wParam
<= MARKER_MAX
)
6791 vs
.markers
[wParam
].fore
= ColourDesired(static_cast<long>(lParam
));
6792 InvalidateStyleData();
6795 case SCI_MARKERSETBACKSELECTED
:
6796 if (wParam
<= MARKER_MAX
)
6797 vs
.markers
[wParam
].backSelected
= ColourDesired(static_cast<long>(lParam
));
6798 InvalidateStyleData();
6801 case SCI_MARKERENABLEHIGHLIGHT
:
6802 marginView
.highlightDelimiter
.isEnabled
= wParam
== 1;
6805 case SCI_MARKERSETBACK
:
6806 if (wParam
<= MARKER_MAX
)
6807 vs
.markers
[wParam
].back
= ColourDesired(static_cast<long>(lParam
));
6808 InvalidateStyleData();
6811 case SCI_MARKERSETALPHA
:
6812 if (wParam
<= MARKER_MAX
)
6813 vs
.markers
[wParam
].alpha
= static_cast<int>(lParam
);
6814 InvalidateStyleRedraw();
6816 case SCI_MARKERADD
: {
6817 int markerID
= pdoc
->AddMark(static_cast<int>(wParam
), static_cast<int>(lParam
));
6820 case SCI_MARKERADDSET
:
6822 pdoc
->AddMarkSet(static_cast<int>(wParam
), static_cast<int>(lParam
));
6825 case SCI_MARKERDELETE
:
6826 pdoc
->DeleteMark(static_cast<int>(wParam
), static_cast<int>(lParam
));
6829 case SCI_MARKERDELETEALL
:
6830 pdoc
->DeleteAllMarks(static_cast<int>(wParam
));
6834 return pdoc
->GetMark(static_cast<int>(wParam
));
6836 case SCI_MARKERNEXT
:
6837 return pdoc
->MarkerNext(static_cast<int>(wParam
), static_cast<int>(lParam
));
6839 case SCI_MARKERPREVIOUS
: {
6840 for (int iLine
= static_cast<int>(wParam
); iLine
>= 0; iLine
--) {
6841 if ((pdoc
->GetMark(iLine
) & lParam
) != 0)
6847 case SCI_MARKERDEFINEPIXMAP
:
6848 if (wParam
<= MARKER_MAX
) {
6849 vs
.markers
[wParam
].SetXPM(CharPtrFromSPtr(lParam
));
6850 vs
.CalcLargestMarkerHeight();
6852 InvalidateStyleData();
6856 case SCI_RGBAIMAGESETWIDTH
:
6857 sizeRGBAImage
.x
= static_cast<XYPOSITION
>(wParam
);
6860 case SCI_RGBAIMAGESETHEIGHT
:
6861 sizeRGBAImage
.y
= static_cast<XYPOSITION
>(wParam
);
6864 case SCI_RGBAIMAGESETSCALE
:
6865 scaleRGBAImage
= static_cast<float>(wParam
);
6868 case SCI_MARKERDEFINERGBAIMAGE
:
6869 if (wParam
<= MARKER_MAX
) {
6870 vs
.markers
[wParam
].SetRGBAImage(sizeRGBAImage
, scaleRGBAImage
/ 100.0f
, reinterpret_cast<unsigned char *>(lParam
));
6871 vs
.CalcLargestMarkerHeight();
6873 InvalidateStyleData();
6877 case SCI_SETMARGINTYPEN
:
6878 if (ValidMargin(wParam
)) {
6879 vs
.ms
[wParam
].style
= static_cast<int>(lParam
);
6880 InvalidateStyleRedraw();
6884 case SCI_GETMARGINTYPEN
:
6885 if (ValidMargin(wParam
))
6886 return vs
.ms
[wParam
].style
;
6890 case SCI_SETMARGINWIDTHN
:
6891 if (ValidMargin(wParam
)) {
6892 // Short-circuit if the width is unchanged, to avoid unnecessary redraw.
6893 if (vs
.ms
[wParam
].width
!= lParam
) {
6894 lastXChosen
+= static_cast<int>(lParam
) - vs
.ms
[wParam
].width
;
6895 vs
.ms
[wParam
].width
= static_cast<int>(lParam
);
6896 InvalidateStyleRedraw();
6901 case SCI_GETMARGINWIDTHN
:
6902 if (ValidMargin(wParam
))
6903 return vs
.ms
[wParam
].width
;
6907 case SCI_SETMARGINMASKN
:
6908 if (ValidMargin(wParam
)) {
6909 vs
.ms
[wParam
].mask
= static_cast<int>(lParam
);
6910 InvalidateStyleRedraw();
6914 case SCI_GETMARGINMASKN
:
6915 if (ValidMargin(wParam
))
6916 return vs
.ms
[wParam
].mask
;
6920 case SCI_SETMARGINSENSITIVEN
:
6921 if (ValidMargin(wParam
)) {
6922 vs
.ms
[wParam
].sensitive
= lParam
!= 0;
6923 InvalidateStyleRedraw();
6927 case SCI_GETMARGINSENSITIVEN
:
6928 if (ValidMargin(wParam
))
6929 return vs
.ms
[wParam
].sensitive
? 1 : 0;
6933 case SCI_SETMARGINCURSORN
:
6934 if (ValidMargin(wParam
))
6935 vs
.ms
[wParam
].cursor
= static_cast<int>(lParam
);
6938 case SCI_GETMARGINCURSORN
:
6939 if (ValidMargin(wParam
))
6940 return vs
.ms
[wParam
].cursor
;
6944 case SCI_SETMARGINBACKN
:
6945 if (ValidMargin(wParam
)) {
6946 vs
.ms
[wParam
].back
= ColourDesired(static_cast<long>(lParam
));
6947 InvalidateStyleRedraw();
6951 case SCI_GETMARGINBACKN
:
6952 if (ValidMargin(wParam
))
6953 return vs
.ms
[wParam
].back
.AsLong();
6957 case SCI_SETMARGINS
:
6959 vs
.ms
.resize(wParam
);
6962 case SCI_GETMARGINS
:
6963 return vs
.ms
.size();
6965 case SCI_STYLECLEARALL
:
6967 InvalidateStyleRedraw();
6970 case SCI_STYLESETFORE
:
6971 case SCI_STYLESETBACK
:
6972 case SCI_STYLESETBOLD
:
6973 case SCI_STYLESETWEIGHT
:
6974 case SCI_STYLESETITALIC
:
6975 case SCI_STYLESETEOLFILLED
:
6976 case SCI_STYLESETSIZE
:
6977 case SCI_STYLESETSIZEFRACTIONAL
:
6978 case SCI_STYLESETFONT
:
6979 case SCI_STYLESETUNDERLINE
:
6980 case SCI_STYLESETCASE
:
6981 case SCI_STYLESETCHARACTERSET
:
6982 case SCI_STYLESETVISIBLE
:
6983 case SCI_STYLESETCHANGEABLE
:
6984 case SCI_STYLESETHOTSPOT
:
6985 StyleSetMessage(iMessage
, wParam
, lParam
);
6988 case SCI_STYLEGETFORE
:
6989 case SCI_STYLEGETBACK
:
6990 case SCI_STYLEGETBOLD
:
6991 case SCI_STYLEGETWEIGHT
:
6992 case SCI_STYLEGETITALIC
:
6993 case SCI_STYLEGETEOLFILLED
:
6994 case SCI_STYLEGETSIZE
:
6995 case SCI_STYLEGETSIZEFRACTIONAL
:
6996 case SCI_STYLEGETFONT
:
6997 case SCI_STYLEGETUNDERLINE
:
6998 case SCI_STYLEGETCASE
:
6999 case SCI_STYLEGETCHARACTERSET
:
7000 case SCI_STYLEGETVISIBLE
:
7001 case SCI_STYLEGETCHANGEABLE
:
7002 case SCI_STYLEGETHOTSPOT
:
7003 return StyleGetMessage(iMessage
, wParam
, lParam
);
7005 case SCI_STYLERESETDEFAULT
:
7006 vs
.ResetDefaultStyle();
7007 InvalidateStyleRedraw();
7009 case SCI_SETSTYLEBITS
:
7010 vs
.EnsureStyle(0xff);
7013 case SCI_GETSTYLEBITS
:
7016 case SCI_SETLINESTATE
:
7017 return pdoc
->SetLineState(static_cast<int>(wParam
), static_cast<int>(lParam
));
7019 case SCI_GETLINESTATE
:
7020 return pdoc
->GetLineState(static_cast<int>(wParam
));
7022 case SCI_GETMAXLINESTATE
:
7023 return pdoc
->GetMaxLineState();
7025 case SCI_GETCARETLINEVISIBLE
:
7026 return vs
.showCaretLineBackground
;
7027 case SCI_SETCARETLINEVISIBLE
:
7028 vs
.showCaretLineBackground
= wParam
!= 0;
7029 InvalidateStyleRedraw();
7031 case SCI_GETCARETLINEVISIBLEALWAYS
:
7032 return vs
.alwaysShowCaretLineBackground
;
7033 case SCI_SETCARETLINEVISIBLEALWAYS
:
7034 vs
.alwaysShowCaretLineBackground
= wParam
!= 0;
7035 InvalidateStyleRedraw();
7038 case SCI_GETCARETLINEBACK
:
7039 return vs
.caretLineBackground
.AsLong();
7040 case SCI_SETCARETLINEBACK
:
7041 vs
.caretLineBackground
= static_cast<int>(wParam
);
7042 InvalidateStyleRedraw();
7044 case SCI_GETCARETLINEBACKALPHA
:
7045 return vs
.caretLineAlpha
;
7046 case SCI_SETCARETLINEBACKALPHA
:
7047 vs
.caretLineAlpha
= static_cast<int>(wParam
);
7048 InvalidateStyleRedraw();
7053 case SCI_VISIBLEFROMDOCLINE
:
7054 return cs
.DisplayFromDoc(static_cast<int>(wParam
));
7056 case SCI_DOCLINEFROMVISIBLE
:
7057 return cs
.DocFromDisplay(static_cast<int>(wParam
));
7060 return WrapCount(static_cast<int>(wParam
));
7062 case SCI_SETFOLDLEVEL
: {
7063 int prev
= pdoc
->SetLevel(static_cast<int>(wParam
), static_cast<int>(lParam
));
7064 if (prev
!= static_cast<int>(lParam
))
7069 case SCI_GETFOLDLEVEL
:
7070 return pdoc
->GetLevel(static_cast<int>(wParam
));
7072 case SCI_GETLASTCHILD
:
7073 return pdoc
->GetLastChild(static_cast<int>(wParam
), static_cast<int>(lParam
));
7075 case SCI_GETFOLDPARENT
:
7076 return pdoc
->GetFoldParent(static_cast<int>(wParam
));
7079 cs
.SetVisible(static_cast<int>(wParam
), static_cast<int>(lParam
), true);
7086 cs
.SetVisible(static_cast<int>(wParam
), static_cast<int>(lParam
), false);
7091 case SCI_GETLINEVISIBLE
:
7092 return cs
.GetVisible(static_cast<int>(wParam
));
7094 case SCI_GETALLLINESVISIBLE
:
7095 return cs
.HiddenLines() ? 0 : 1;
7097 case SCI_SETFOLDEXPANDED
:
7098 SetFoldExpanded(static_cast<int>(wParam
), lParam
!= 0);
7101 case SCI_GETFOLDEXPANDED
:
7102 return cs
.GetExpanded(static_cast<int>(wParam
));
7104 case SCI_SETAUTOMATICFOLD
:
7105 foldAutomatic
= static_cast<int>(wParam
);
7108 case SCI_GETAUTOMATICFOLD
:
7109 return foldAutomatic
;
7111 case SCI_SETFOLDFLAGS
:
7112 foldFlags
= static_cast<int>(wParam
);
7116 case SCI_TOGGLEFOLDSHOWTEXT
:
7117 cs
.SetFoldDisplayText(static_cast<int>(wParam
), CharPtrFromSPtr(lParam
));
7118 FoldLine(static_cast<int>(wParam
), SC_FOLDACTION_TOGGLE
);
7121 case SCI_FOLDDISPLAYTEXTSETSTYLE
:
7122 foldDisplayTextStyle
= static_cast<int>(wParam
);
7126 case SCI_TOGGLEFOLD
:
7127 FoldLine(static_cast<int>(wParam
), SC_FOLDACTION_TOGGLE
);
7131 FoldLine(static_cast<int>(wParam
), static_cast<int>(lParam
));
7134 case SCI_FOLDCHILDREN
:
7135 FoldExpand(static_cast<int>(wParam
), static_cast<int>(lParam
), pdoc
->GetLevel(static_cast<int>(wParam
)));
7139 FoldAll(static_cast<int>(wParam
));
7142 case SCI_EXPANDCHILDREN
:
7143 FoldExpand(static_cast<int>(wParam
), SC_FOLDACTION_EXPAND
, static_cast<int>(lParam
));
7146 case SCI_CONTRACTEDFOLDNEXT
:
7147 return ContractedFoldNext(static_cast<int>(wParam
));
7149 case SCI_ENSUREVISIBLE
:
7150 EnsureLineVisible(static_cast<int>(wParam
), false);
7153 case SCI_ENSUREVISIBLEENFORCEPOLICY
:
7154 EnsureLineVisible(static_cast<int>(wParam
), true);
7157 case SCI_SCROLLRANGE
:
7158 ScrollRange(SelectionRange(static_cast<int>(wParam
), static_cast<int>(lParam
)));
7161 case SCI_SEARCHANCHOR
:
7165 case SCI_SEARCHNEXT
:
7166 case SCI_SEARCHPREV
:
7167 return SearchText(iMessage
, wParam
, lParam
);
7169 case SCI_SETXCARETPOLICY
:
7170 caretXPolicy
= static_cast<int>(wParam
);
7171 caretXSlop
= static_cast<int>(lParam
);
7174 case SCI_SETYCARETPOLICY
:
7175 caretYPolicy
= static_cast<int>(wParam
);
7176 caretYSlop
= static_cast<int>(lParam
);
7179 case SCI_SETVISIBLEPOLICY
:
7180 visiblePolicy
= static_cast<int>(wParam
);
7181 visibleSlop
= static_cast<int>(lParam
);
7184 case SCI_LINESONSCREEN
:
7185 return LinesOnScreen();
7187 case SCI_SETSELFORE
:
7188 vs
.selColours
.fore
= ColourOptional(wParam
, lParam
);
7189 vs
.selAdditionalForeground
= ColourDesired(static_cast<long>(lParam
));
7190 InvalidateStyleRedraw();
7193 case SCI_SETSELBACK
:
7194 vs
.selColours
.back
= ColourOptional(wParam
, lParam
);
7195 vs
.selAdditionalBackground
= ColourDesired(static_cast<long>(lParam
));
7196 InvalidateStyleRedraw();
7199 case SCI_SETSELALPHA
:
7200 vs
.selAlpha
= static_cast<int>(wParam
);
7201 vs
.selAdditionalAlpha
= static_cast<int>(wParam
);
7202 InvalidateStyleRedraw();
7205 case SCI_GETSELALPHA
:
7208 case SCI_GETSELEOLFILLED
:
7209 return vs
.selEOLFilled
;
7211 case SCI_SETSELEOLFILLED
:
7212 vs
.selEOLFilled
= wParam
!= 0;
7213 InvalidateStyleRedraw();
7216 case SCI_SETWHITESPACEFORE
:
7217 vs
.whitespaceColours
.fore
= ColourOptional(wParam
, lParam
);
7218 InvalidateStyleRedraw();
7221 case SCI_SETWHITESPACEBACK
:
7222 vs
.whitespaceColours
.back
= ColourOptional(wParam
, lParam
);
7223 InvalidateStyleRedraw();
7226 case SCI_SETCARETFORE
:
7227 vs
.caretcolour
= ColourDesired(static_cast<long>(wParam
));
7228 InvalidateStyleRedraw();
7231 case SCI_GETCARETFORE
:
7232 return vs
.caretcolour
.AsLong();
7234 case SCI_SETCARETSTYLE
:
7235 if (wParam
<= CARETSTYLE_BLOCK
)
7236 vs
.caretStyle
= static_cast<int>(wParam
);
7238 /* Default to the line caret */
7239 vs
.caretStyle
= CARETSTYLE_LINE
;
7240 InvalidateStyleRedraw();
7243 case SCI_GETCARETSTYLE
:
7244 return vs
.caretStyle
;
7246 case SCI_SETCARETWIDTH
:
7247 if (static_cast<int>(wParam
) <= 0)
7249 else if (wParam
>= 3)
7252 vs
.caretWidth
= static_cast<int>(wParam
);
7253 InvalidateStyleRedraw();
7256 case SCI_GETCARETWIDTH
:
7257 return vs
.caretWidth
;
7259 case SCI_ASSIGNCMDKEY
:
7260 kmap
.AssignCmdKey(Platform::LowShortFromLong(static_cast<long>(wParam
)),
7261 Platform::HighShortFromLong(static_cast<long>(wParam
)), static_cast<unsigned int>(lParam
));
7264 case SCI_CLEARCMDKEY
:
7265 kmap
.AssignCmdKey(Platform::LowShortFromLong(static_cast<long>(wParam
)),
7266 Platform::HighShortFromLong(static_cast<long>(wParam
)), SCI_NULL
);
7269 case SCI_CLEARALLCMDKEYS
:
7273 case SCI_INDICSETSTYLE
:
7274 if (wParam
<= INDIC_MAX
) {
7275 vs
.indicators
[wParam
].sacNormal
.style
= static_cast<int>(lParam
);
7276 vs
.indicators
[wParam
].sacHover
.style
= static_cast<int>(lParam
);
7277 InvalidateStyleRedraw();
7281 case SCI_INDICGETSTYLE
:
7282 return (wParam
<= INDIC_MAX
) ? vs
.indicators
[wParam
].sacNormal
.style
: 0;
7284 case SCI_INDICSETFORE
:
7285 if (wParam
<= INDIC_MAX
) {
7286 vs
.indicators
[wParam
].sacNormal
.fore
= ColourDesired(static_cast<long>(lParam
));
7287 vs
.indicators
[wParam
].sacHover
.fore
= ColourDesired(static_cast<long>(lParam
));
7288 InvalidateStyleRedraw();
7292 case SCI_INDICGETFORE
:
7293 return (wParam
<= INDIC_MAX
) ? vs
.indicators
[wParam
].sacNormal
.fore
.AsLong() : 0;
7295 case SCI_INDICSETHOVERSTYLE
:
7296 if (wParam
<= INDIC_MAX
) {
7297 vs
.indicators
[wParam
].sacHover
.style
= static_cast<int>(lParam
);
7298 InvalidateStyleRedraw();
7302 case SCI_INDICGETHOVERSTYLE
:
7303 return (wParam
<= INDIC_MAX
) ? vs
.indicators
[wParam
].sacHover
.style
: 0;
7305 case SCI_INDICSETHOVERFORE
:
7306 if (wParam
<= INDIC_MAX
) {
7307 vs
.indicators
[wParam
].sacHover
.fore
= ColourDesired(static_cast<long>(lParam
));
7308 InvalidateStyleRedraw();
7312 case SCI_INDICGETHOVERFORE
:
7313 return (wParam
<= INDIC_MAX
) ? vs
.indicators
[wParam
].sacHover
.fore
.AsLong() : 0;
7315 case SCI_INDICSETFLAGS
:
7316 if (wParam
<= INDIC_MAX
) {
7317 vs
.indicators
[wParam
].SetFlags(static_cast<int>(lParam
));
7318 InvalidateStyleRedraw();
7322 case SCI_INDICGETFLAGS
:
7323 return (wParam
<= INDIC_MAX
) ? vs
.indicators
[wParam
].Flags() : 0;
7325 case SCI_INDICSETUNDER
:
7326 if (wParam
<= INDIC_MAX
) {
7327 vs
.indicators
[wParam
].under
= lParam
!= 0;
7328 InvalidateStyleRedraw();
7332 case SCI_INDICGETUNDER
:
7333 return (wParam
<= INDIC_MAX
) ? vs
.indicators
[wParam
].under
: 0;
7335 case SCI_INDICSETALPHA
:
7336 if (wParam
<= INDIC_MAX
&& lParam
>=0 && lParam
<= 255) {
7337 vs
.indicators
[wParam
].fillAlpha
= static_cast<int>(lParam
);
7338 InvalidateStyleRedraw();
7342 case SCI_INDICGETALPHA
:
7343 return (wParam
<= INDIC_MAX
) ? vs
.indicators
[wParam
].fillAlpha
: 0;
7345 case SCI_INDICSETOUTLINEALPHA
:
7346 if (wParam
<= INDIC_MAX
&& lParam
>=0 && lParam
<= 255) {
7347 vs
.indicators
[wParam
].outlineAlpha
= static_cast<int>(lParam
);
7348 InvalidateStyleRedraw();
7352 case SCI_INDICGETOUTLINEALPHA
:
7353 return (wParam
<= INDIC_MAX
) ? vs
.indicators
[wParam
].outlineAlpha
: 0;
7355 case SCI_SETINDICATORCURRENT
:
7356 pdoc
->decorations
.SetCurrentIndicator(static_cast<int>(wParam
));
7358 case SCI_GETINDICATORCURRENT
:
7359 return pdoc
->decorations
.GetCurrentIndicator();
7360 case SCI_SETINDICATORVALUE
:
7361 pdoc
->decorations
.SetCurrentValue(static_cast<int>(wParam
));
7363 case SCI_GETINDICATORVALUE
:
7364 return pdoc
->decorations
.GetCurrentValue();
7366 case SCI_INDICATORFILLRANGE
:
7367 pdoc
->DecorationFillRange(static_cast<int>(wParam
), pdoc
->decorations
.GetCurrentValue(), static_cast<int>(lParam
));
7370 case SCI_INDICATORCLEARRANGE
:
7371 pdoc
->DecorationFillRange(static_cast<int>(wParam
), 0, static_cast<int>(lParam
));
7374 case SCI_INDICATORALLONFOR
:
7375 return pdoc
->decorations
.AllOnFor(static_cast<int>(wParam
));
7377 case SCI_INDICATORVALUEAT
:
7378 return pdoc
->decorations
.ValueAt(static_cast<int>(wParam
), static_cast<int>(lParam
));
7380 case SCI_INDICATORSTART
:
7381 return pdoc
->decorations
.Start(static_cast<int>(wParam
), static_cast<int>(lParam
));
7383 case SCI_INDICATOREND
:
7384 return pdoc
->decorations
.End(static_cast<int>(wParam
), static_cast<int>(lParam
));
7387 case SCI_LINEDOWNEXTEND
:
7389 case SCI_PARADOWNEXTEND
:
7391 case SCI_LINEUPEXTEND
:
7393 case SCI_PARAUPEXTEND
:
7395 case SCI_CHARLEFTEXTEND
:
7397 case SCI_CHARRIGHTEXTEND
:
7399 case SCI_WORDLEFTEXTEND
:
7401 case SCI_WORDRIGHTEXTEND
:
7402 case SCI_WORDLEFTEND
:
7403 case SCI_WORDLEFTENDEXTEND
:
7404 case SCI_WORDRIGHTEND
:
7405 case SCI_WORDRIGHTENDEXTEND
:
7407 case SCI_HOMEEXTEND
:
7409 case SCI_LINEENDEXTEND
:
7411 case SCI_HOMEWRAPEXTEND
:
7412 case SCI_LINEENDWRAP
:
7413 case SCI_LINEENDWRAPEXTEND
:
7414 case SCI_DOCUMENTSTART
:
7415 case SCI_DOCUMENTSTARTEXTEND
:
7416 case SCI_DOCUMENTEND
:
7417 case SCI_DOCUMENTENDEXTEND
:
7418 case SCI_SCROLLTOSTART
:
7419 case SCI_SCROLLTOEND
:
7421 case SCI_STUTTEREDPAGEUP
:
7422 case SCI_STUTTEREDPAGEUPEXTEND
:
7423 case SCI_STUTTEREDPAGEDOWN
:
7424 case SCI_STUTTEREDPAGEDOWNEXTEND
:
7427 case SCI_PAGEUPEXTEND
:
7429 case SCI_PAGEDOWNEXTEND
:
7430 case SCI_EDITTOGGLEOVERTYPE
:
7432 case SCI_DELETEBACK
:
7438 case SCI_VCHOMEEXTEND
:
7439 case SCI_VCHOMEWRAP
:
7440 case SCI_VCHOMEWRAPEXTEND
:
7441 case SCI_VCHOMEDISPLAY
:
7442 case SCI_VCHOMEDISPLAYEXTEND
:
7445 case SCI_DELWORDLEFT
:
7446 case SCI_DELWORDRIGHT
:
7447 case SCI_DELWORDRIGHTEND
:
7448 case SCI_DELLINELEFT
:
7449 case SCI_DELLINERIGHT
:
7452 case SCI_LINEDELETE
:
7453 case SCI_LINETRANSPOSE
:
7454 case SCI_LINEDUPLICATE
:
7457 case SCI_LINESCROLLDOWN
:
7458 case SCI_LINESCROLLUP
:
7459 case SCI_WORDPARTLEFT
:
7460 case SCI_WORDPARTLEFTEXTEND
:
7461 case SCI_WORDPARTRIGHT
:
7462 case SCI_WORDPARTRIGHTEXTEND
:
7463 case SCI_DELETEBACKNOTLINE
:
7464 case SCI_HOMEDISPLAY
:
7465 case SCI_HOMEDISPLAYEXTEND
:
7466 case SCI_LINEENDDISPLAY
:
7467 case SCI_LINEENDDISPLAYEXTEND
:
7468 case SCI_LINEDOWNRECTEXTEND
:
7469 case SCI_LINEUPRECTEXTEND
:
7470 case SCI_CHARLEFTRECTEXTEND
:
7471 case SCI_CHARRIGHTRECTEXTEND
:
7472 case SCI_HOMERECTEXTEND
:
7473 case SCI_VCHOMERECTEXTEND
:
7474 case SCI_LINEENDRECTEXTEND
:
7475 case SCI_PAGEUPRECTEXTEND
:
7476 case SCI_PAGEDOWNRECTEXTEND
:
7477 case SCI_SELECTIONDUPLICATE
:
7478 return KeyCommand(iMessage
);
7480 case SCI_BRACEHIGHLIGHT
:
7481 SetBraceHighlight(static_cast<int>(wParam
), static_cast<int>(lParam
), STYLE_BRACELIGHT
);
7484 case SCI_BRACEHIGHLIGHTINDICATOR
:
7485 if (lParam
>= 0 && lParam
<= INDIC_MAX
) {
7486 vs
.braceHighlightIndicatorSet
= wParam
!= 0;
7487 vs
.braceHighlightIndicator
= static_cast<int>(lParam
);
7491 case SCI_BRACEBADLIGHT
:
7492 SetBraceHighlight(static_cast<int>(wParam
), -1, STYLE_BRACEBAD
);
7495 case SCI_BRACEBADLIGHTINDICATOR
:
7496 if (lParam
>= 0 && lParam
<= INDIC_MAX
) {
7497 vs
.braceBadLightIndicatorSet
= wParam
!= 0;
7498 vs
.braceBadLightIndicator
= static_cast<int>(lParam
);
7502 case SCI_BRACEMATCH
:
7503 // wParam is position of char to find brace for,
7504 // lParam is maximum amount of text to restyle to find it
7505 return pdoc
->BraceMatch(static_cast<int>(wParam
), static_cast<int>(lParam
));
7507 case SCI_GETVIEWEOL
:
7510 case SCI_SETVIEWEOL
:
7511 vs
.viewEOL
= wParam
!= 0;
7512 InvalidateStyleRedraw();
7516 vs
.zoomLevel
= static_cast<int>(wParam
);
7517 InvalidateStyleRedraw();
7522 return vs
.zoomLevel
;
7524 case SCI_GETEDGECOLUMN
:
7525 return vs
.theEdge
.column
;
7527 case SCI_SETEDGECOLUMN
:
7528 vs
.theEdge
.column
= static_cast<int>(wParam
);
7529 InvalidateStyleRedraw();
7532 case SCI_GETEDGEMODE
:
7533 return vs
.edgeState
;
7535 case SCI_SETEDGEMODE
:
7536 vs
.edgeState
= static_cast<int>(wParam
);
7537 InvalidateStyleRedraw();
7540 case SCI_GETEDGECOLOUR
:
7541 return vs
.theEdge
.colour
.AsLong();
7543 case SCI_SETEDGECOLOUR
:
7544 vs
.theEdge
.colour
= ColourDesired(static_cast<long>(wParam
));
7545 InvalidateStyleRedraw();
7548 case SCI_MULTIEDGEADDLINE
:
7549 vs
.theMultiEdge
.push_back(EdgeProperties(wParam
, lParam
));
7550 InvalidateStyleRedraw();
7553 case SCI_MULTIEDGECLEARALL
:
7554 std::vector
<EdgeProperties
>().swap(vs
.theMultiEdge
); // Free vector and memory, C++03 compatible
7555 InvalidateStyleRedraw();
7558 case SCI_GETDOCPOINTER
:
7559 return reinterpret_cast<sptr_t
>(pdoc
);
7561 case SCI_SETDOCPOINTER
:
7563 SetDocPointer(reinterpret_cast<Document
*>(lParam
));
7566 case SCI_CREATEDOCUMENT
: {
7567 Document
*doc
= new Document();
7569 return reinterpret_cast<sptr_t
>(doc
);
7572 case SCI_ADDREFDOCUMENT
:
7573 (reinterpret_cast<Document
*>(lParam
))->AddRef();
7576 case SCI_RELEASEDOCUMENT
:
7577 (reinterpret_cast<Document
*>(lParam
))->Release();
7580 case SCI_CREATELOADER
: {
7581 Document
*doc
= new Document();
7583 doc
->Allocate(static_cast<int>(wParam
));
7584 doc
->SetUndoCollection(false);
7585 return reinterpret_cast<sptr_t
>(static_cast<ILoader
*>(doc
));
7588 case SCI_SETMODEVENTMASK
:
7589 modEventMask
= static_cast<int>(wParam
);
7592 case SCI_GETMODEVENTMASK
:
7593 return modEventMask
;
7595 case SCI_CONVERTEOLS
:
7596 pdoc
->ConvertLineEnds(static_cast<int>(wParam
));
7597 SetSelection(sel
.MainCaret(), sel
.MainAnchor()); // Ensure selection inside document
7600 case SCI_SETLENGTHFORENCODE
:
7601 lengthForEncode
= static_cast<int>(wParam
);
7604 case SCI_SELECTIONISRECTANGLE
:
7605 return sel
.selType
== Selection::selRectangle
? 1 : 0;
7607 case SCI_SETSELECTIONMODE
: {
7610 sel
.SetMoveExtends(!sel
.MoveExtends() || (sel
.selType
!= Selection::selStream
));
7611 sel
.selType
= Selection::selStream
;
7613 case SC_SEL_RECTANGLE
:
7614 sel
.SetMoveExtends(!sel
.MoveExtends() || (sel
.selType
!= Selection::selRectangle
));
7615 sel
.selType
= Selection::selRectangle
;
7618 sel
.SetMoveExtends(!sel
.MoveExtends() || (sel
.selType
!= Selection::selLines
));
7619 sel
.selType
= Selection::selLines
;
7622 sel
.SetMoveExtends(!sel
.MoveExtends() || (sel
.selType
!= Selection::selThin
));
7623 sel
.selType
= Selection::selThin
;
7626 sel
.SetMoveExtends(!sel
.MoveExtends() || (sel
.selType
!= Selection::selStream
));
7627 sel
.selType
= Selection::selStream
;
7629 InvalidateWholeSelection();
7632 case SCI_GETSELECTIONMODE
:
7633 switch (sel
.selType
) {
7634 case Selection::selStream
:
7635 return SC_SEL_STREAM
;
7636 case Selection::selRectangle
:
7637 return SC_SEL_RECTANGLE
;
7638 case Selection::selLines
:
7639 return SC_SEL_LINES
;
7640 case Selection::selThin
:
7643 return SC_SEL_STREAM
;
7645 case SCI_GETLINESELSTARTPOSITION
:
7646 case SCI_GETLINESELENDPOSITION
: {
7647 SelectionSegment
segmentLine(SelectionPosition(pdoc
->LineStart(static_cast<int>(wParam
))),
7648 SelectionPosition(pdoc
->LineEnd(static_cast<int>(wParam
))));
7649 for (size_t r
=0; r
<sel
.Count(); r
++) {
7650 SelectionSegment portion
= sel
.Range(r
).Intersect(segmentLine
);
7651 if (portion
.start
.IsValid()) {
7652 return (iMessage
== SCI_GETLINESELSTARTPOSITION
) ? portion
.start
.Position() : portion
.end
.Position();
7655 return INVALID_POSITION
;
7658 case SCI_SETOVERTYPE
:
7659 inOverstrike
= wParam
!= 0;
7662 case SCI_GETOVERTYPE
:
7663 return inOverstrike
? 1 : 0;
7666 SetFocusState(wParam
!= 0);
7673 errorStatus
= static_cast<int>(wParam
);
7679 case SCI_SETMOUSEDOWNCAPTURES
:
7680 mouseDownCaptures
= wParam
!= 0;
7683 case SCI_GETMOUSEDOWNCAPTURES
:
7684 return mouseDownCaptures
;
7686 case SCI_SETMOUSEWHEELCAPTURES
:
7687 mouseWheelCaptures
= wParam
!= 0;
7690 case SCI_GETMOUSEWHEELCAPTURES
:
7691 return mouseWheelCaptures
;
7694 cursorMode
= static_cast<int>(wParam
);
7695 DisplayCursor(Window::cursorText
);
7701 case SCI_SETCONTROLCHARSYMBOL
:
7702 vs
.controlCharSymbol
= static_cast<int>(wParam
);
7703 InvalidateStyleRedraw();
7706 case SCI_GETCONTROLCHARSYMBOL
:
7707 return vs
.controlCharSymbol
;
7709 case SCI_SETREPRESENTATION
:
7710 reprs
.SetRepresentation(reinterpret_cast<const char *>(wParam
), CharPtrFromSPtr(lParam
));
7713 case SCI_GETREPRESENTATION
: {
7714 const Representation
*repr
= reprs
.RepresentationFromCharacter(
7715 reinterpret_cast<const char *>(wParam
), UTF8MaxBytes
);
7717 return StringResult(lParam
, repr
->stringRep
.c_str());
7722 case SCI_CLEARREPRESENTATION
:
7723 reprs
.ClearRepresentation(reinterpret_cast<const char *>(wParam
));
7726 case SCI_STARTRECORD
:
7727 recordingMacro
= true;
7730 case SCI_STOPRECORD
:
7731 recordingMacro
= false;
7734 case SCI_MOVECARETINSIDEVIEW
:
7735 MoveCaretInsideView();
7738 case SCI_SETFOLDMARGINCOLOUR
:
7739 vs
.foldmarginColour
= ColourOptional(wParam
, lParam
);
7740 InvalidateStyleRedraw();
7743 case SCI_SETFOLDMARGINHICOLOUR
:
7744 vs
.foldmarginHighlightColour
= ColourOptional(wParam
, lParam
);
7745 InvalidateStyleRedraw();
7748 case SCI_SETHOTSPOTACTIVEFORE
:
7749 vs
.hotspotColours
.fore
= ColourOptional(wParam
, lParam
);
7750 InvalidateStyleRedraw();
7753 case SCI_GETHOTSPOTACTIVEFORE
:
7754 return vs
.hotspotColours
.fore
.AsLong();
7756 case SCI_SETHOTSPOTACTIVEBACK
:
7757 vs
.hotspotColours
.back
= ColourOptional(wParam
, lParam
);
7758 InvalidateStyleRedraw();
7761 case SCI_GETHOTSPOTACTIVEBACK
:
7762 return vs
.hotspotColours
.back
.AsLong();
7764 case SCI_SETHOTSPOTACTIVEUNDERLINE
:
7765 vs
.hotspotUnderline
= wParam
!= 0;
7766 InvalidateStyleRedraw();
7769 case SCI_GETHOTSPOTACTIVEUNDERLINE
:
7770 return vs
.hotspotUnderline
? 1 : 0;
7772 case SCI_SETHOTSPOTSINGLELINE
:
7773 vs
.hotspotSingleLine
= wParam
!= 0;
7774 InvalidateStyleRedraw();
7777 case SCI_GETHOTSPOTSINGLELINE
:
7778 return vs
.hotspotSingleLine
? 1 : 0;
7780 case SCI_SETPASTECONVERTENDINGS
:
7781 convertPastes
= wParam
!= 0;
7784 case SCI_GETPASTECONVERTENDINGS
:
7785 return convertPastes
? 1 : 0;
7787 case SCI_GETCHARACTERPOINTER
:
7788 return reinterpret_cast<sptr_t
>(pdoc
->BufferPointer());
7790 case SCI_GETRANGEPOINTER
:
7791 return reinterpret_cast<sptr_t
>(pdoc
->RangePointer(static_cast<int>(wParam
), static_cast<int>(lParam
)));
7793 case SCI_GETGAPPOSITION
:
7794 return pdoc
->GapPosition();
7796 case SCI_SETEXTRAASCENT
:
7797 vs
.extraAscent
= static_cast<int>(wParam
);
7798 InvalidateStyleRedraw();
7801 case SCI_GETEXTRAASCENT
:
7802 return vs
.extraAscent
;
7804 case SCI_SETEXTRADESCENT
:
7805 vs
.extraDescent
= static_cast<int>(wParam
);
7806 InvalidateStyleRedraw();
7809 case SCI_GETEXTRADESCENT
:
7810 return vs
.extraDescent
;
7812 case SCI_MARGINSETSTYLEOFFSET
:
7813 vs
.marginStyleOffset
= static_cast<int>(wParam
);
7814 InvalidateStyleRedraw();
7817 case SCI_MARGINGETSTYLEOFFSET
:
7818 return vs
.marginStyleOffset
;
7820 case SCI_SETMARGINOPTIONS
:
7821 marginOptions
= static_cast<int>(wParam
);
7824 case SCI_GETMARGINOPTIONS
:
7825 return marginOptions
;
7827 case SCI_MARGINSETTEXT
:
7828 pdoc
->MarginSetText(static_cast<int>(wParam
), CharPtrFromSPtr(lParam
));
7831 case SCI_MARGINGETTEXT
: {
7832 const StyledText st
= pdoc
->MarginStyledText(static_cast<int>(wParam
));
7833 return BytesResult(lParam
, reinterpret_cast<const unsigned char *>(st
.text
), st
.length
);
7836 case SCI_MARGINSETSTYLE
:
7837 pdoc
->MarginSetStyle(static_cast<int>(wParam
), static_cast<int>(lParam
));
7840 case SCI_MARGINGETSTYLE
: {
7841 const StyledText st
= pdoc
->MarginStyledText(static_cast<int>(wParam
));
7845 case SCI_MARGINSETSTYLES
:
7846 pdoc
->MarginSetStyles(static_cast<int>(wParam
), reinterpret_cast<const unsigned char *>(lParam
));
7849 case SCI_MARGINGETSTYLES
: {
7850 const StyledText st
= pdoc
->MarginStyledText(static_cast<int>(wParam
));
7851 return BytesResult(lParam
, st
.styles
, st
.length
);
7854 case SCI_MARGINTEXTCLEARALL
:
7855 pdoc
->MarginClearAll();
7858 case SCI_ANNOTATIONSETTEXT
:
7859 pdoc
->AnnotationSetText(static_cast<int>(wParam
), CharPtrFromSPtr(lParam
));
7862 case SCI_ANNOTATIONGETTEXT
: {
7863 const StyledText st
= pdoc
->AnnotationStyledText(static_cast<int>(wParam
));
7864 return BytesResult(lParam
, reinterpret_cast<const unsigned char *>(st
.text
), st
.length
);
7867 case SCI_ANNOTATIONGETSTYLE
: {
7868 const StyledText st
= pdoc
->AnnotationStyledText(static_cast<int>(wParam
));
7872 case SCI_ANNOTATIONSETSTYLE
:
7873 pdoc
->AnnotationSetStyle(static_cast<int>(wParam
), static_cast<int>(lParam
));
7876 case SCI_ANNOTATIONSETSTYLES
:
7877 pdoc
->AnnotationSetStyles(static_cast<int>(wParam
), reinterpret_cast<const unsigned char *>(lParam
));
7880 case SCI_ANNOTATIONGETSTYLES
: {
7881 const StyledText st
= pdoc
->AnnotationStyledText(static_cast<int>(wParam
));
7882 return BytesResult(lParam
, st
.styles
, st
.length
);
7885 case SCI_ANNOTATIONGETLINES
:
7886 return pdoc
->AnnotationLines(static_cast<int>(wParam
));
7888 case SCI_ANNOTATIONCLEARALL
:
7889 pdoc
->AnnotationClearAll();
7892 case SCI_ANNOTATIONSETVISIBLE
:
7893 SetAnnotationVisible(static_cast<int>(wParam
));
7896 case SCI_ANNOTATIONGETVISIBLE
:
7897 return vs
.annotationVisible
;
7899 case SCI_ANNOTATIONSETSTYLEOFFSET
:
7900 vs
.annotationStyleOffset
= static_cast<int>(wParam
);
7901 InvalidateStyleRedraw();
7904 case SCI_ANNOTATIONGETSTYLEOFFSET
:
7905 return vs
.annotationStyleOffset
;
7907 case SCI_RELEASEALLEXTENDEDSTYLES
:
7908 vs
.ReleaseAllExtendedStyles();
7911 case SCI_ALLOCATEEXTENDEDSTYLES
:
7912 return vs
.AllocateExtendedStyles(static_cast<int>(wParam
));
7914 case SCI_ADDUNDOACTION
:
7915 pdoc
->AddUndoAction(static_cast<int>(wParam
), lParam
& UNDO_MAY_COALESCE
);
7918 case SCI_SETMOUSESELECTIONRECTANGULARSWITCH
:
7919 mouseSelectionRectangularSwitch
= wParam
!= 0;
7922 case SCI_GETMOUSESELECTIONRECTANGULARSWITCH
:
7923 return mouseSelectionRectangularSwitch
;
7925 case SCI_SETMULTIPLESELECTION
:
7926 multipleSelection
= wParam
!= 0;
7930 case SCI_GETMULTIPLESELECTION
:
7931 return multipleSelection
;
7933 case SCI_SETADDITIONALSELECTIONTYPING
:
7934 additionalSelectionTyping
= wParam
!= 0;
7938 case SCI_GETADDITIONALSELECTIONTYPING
:
7939 return additionalSelectionTyping
;
7941 case SCI_SETMULTIPASTE
:
7942 multiPasteMode
= static_cast<int>(wParam
);
7945 case SCI_GETMULTIPASTE
:
7946 return multiPasteMode
;
7948 case SCI_SETADDITIONALCARETSBLINK
:
7949 view
.additionalCaretsBlink
= wParam
!= 0;
7953 case SCI_GETADDITIONALCARETSBLINK
:
7954 return view
.additionalCaretsBlink
;
7956 case SCI_SETADDITIONALCARETSVISIBLE
:
7957 view
.additionalCaretsVisible
= wParam
!= 0;
7961 case SCI_GETADDITIONALCARETSVISIBLE
:
7962 return view
.additionalCaretsVisible
;
7964 case SCI_GETSELECTIONS
:
7967 case SCI_GETSELECTIONEMPTY
:
7970 case SCI_CLEARSELECTIONS
:
7972 ContainerNeedsUpdate(SC_UPDATE_SELECTION
);
7976 case SCI_SETSELECTION
:
7977 sel
.SetSelection(SelectionRange(static_cast<int>(wParam
), static_cast<int>(lParam
)));
7981 case SCI_ADDSELECTION
:
7982 sel
.AddSelection(SelectionRange(static_cast<int>(wParam
), static_cast<int>(lParam
)));
7983 ContainerNeedsUpdate(SC_UPDATE_SELECTION
);
7987 case SCI_DROPSELECTIONN
:
7988 sel
.DropSelection(static_cast<int>(wParam
));
7989 ContainerNeedsUpdate(SC_UPDATE_SELECTION
);
7993 case SCI_SETMAINSELECTION
:
7994 sel
.SetMain(static_cast<int>(wParam
));
7995 ContainerNeedsUpdate(SC_UPDATE_SELECTION
);
7999 case SCI_GETMAINSELECTION
:
8002 case SCI_SETSELECTIONNCARET
:
8003 case SCI_SETSELECTIONNANCHOR
:
8004 case SCI_SETSELECTIONNCARETVIRTUALSPACE
:
8005 case SCI_SETSELECTIONNANCHORVIRTUALSPACE
:
8006 case SCI_SETSELECTIONNSTART
:
8007 case SCI_SETSELECTIONNEND
:
8008 SetSelectionNMessage(iMessage
, wParam
, lParam
);
8011 case SCI_GETSELECTIONNCARET
:
8012 return sel
.Range(wParam
).caret
.Position();
8014 case SCI_GETSELECTIONNANCHOR
:
8015 return sel
.Range(wParam
).anchor
.Position();
8017 case SCI_GETSELECTIONNCARETVIRTUALSPACE
:
8018 return sel
.Range(wParam
).caret
.VirtualSpace();
8020 case SCI_GETSELECTIONNANCHORVIRTUALSPACE
:
8021 return sel
.Range(wParam
).anchor
.VirtualSpace();
8023 case SCI_GETSELECTIONNSTART
:
8024 return sel
.Range(wParam
).Start().Position();
8026 case SCI_GETSELECTIONNEND
:
8027 return sel
.Range(wParam
).End().Position();
8029 case SCI_SETRECTANGULARSELECTIONCARET
:
8030 if (!sel
.IsRectangular())
8032 sel
.selType
= Selection::selRectangle
;
8033 sel
.Rectangular().caret
.SetPosition(static_cast<int>(wParam
));
8034 SetRectangularRange();
8038 case SCI_GETRECTANGULARSELECTIONCARET
:
8039 return sel
.Rectangular().caret
.Position();
8041 case SCI_SETRECTANGULARSELECTIONANCHOR
:
8042 if (!sel
.IsRectangular())
8044 sel
.selType
= Selection::selRectangle
;
8045 sel
.Rectangular().anchor
.SetPosition(static_cast<int>(wParam
));
8046 SetRectangularRange();
8050 case SCI_GETRECTANGULARSELECTIONANCHOR
:
8051 return sel
.Rectangular().anchor
.Position();
8053 case SCI_SETRECTANGULARSELECTIONCARETVIRTUALSPACE
:
8054 if (!sel
.IsRectangular())
8056 sel
.selType
= Selection::selRectangle
;
8057 sel
.Rectangular().caret
.SetVirtualSpace(static_cast<int>(wParam
));
8058 SetRectangularRange();
8062 case SCI_GETRECTANGULARSELECTIONCARETVIRTUALSPACE
:
8063 return sel
.Rectangular().caret
.VirtualSpace();
8065 case SCI_SETRECTANGULARSELECTIONANCHORVIRTUALSPACE
:
8066 if (!sel
.IsRectangular())
8068 sel
.selType
= Selection::selRectangle
;
8069 sel
.Rectangular().anchor
.SetVirtualSpace(static_cast<int>(wParam
));
8070 SetRectangularRange();
8074 case SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE
:
8075 return sel
.Rectangular().anchor
.VirtualSpace();
8077 case SCI_SETVIRTUALSPACEOPTIONS
:
8078 virtualSpaceOptions
= static_cast<int>(wParam
);
8081 case SCI_GETVIRTUALSPACEOPTIONS
:
8082 return virtualSpaceOptions
;
8084 case SCI_SETADDITIONALSELFORE
:
8085 vs
.selAdditionalForeground
= ColourDesired(static_cast<long>(wParam
));
8086 InvalidateStyleRedraw();
8089 case SCI_SETADDITIONALSELBACK
:
8090 vs
.selAdditionalBackground
= ColourDesired(static_cast<long>(wParam
));
8091 InvalidateStyleRedraw();
8094 case SCI_SETADDITIONALSELALPHA
:
8095 vs
.selAdditionalAlpha
= static_cast<int>(wParam
);
8096 InvalidateStyleRedraw();
8099 case SCI_GETADDITIONALSELALPHA
:
8100 return vs
.selAdditionalAlpha
;
8102 case SCI_SETADDITIONALCARETFORE
:
8103 vs
.additionalCaretColour
= ColourDesired(static_cast<long>(wParam
));
8104 InvalidateStyleRedraw();
8107 case SCI_GETADDITIONALCARETFORE
:
8108 return vs
.additionalCaretColour
.AsLong();
8110 case SCI_ROTATESELECTION
:
8112 InvalidateWholeSelection();
8115 case SCI_SWAPMAINANCHORCARET
:
8116 InvalidateSelection(sel
.RangeMain());
8117 sel
.RangeMain().Swap();
8120 case SCI_MULTIPLESELECTADDNEXT
:
8121 MultipleSelectAdd(addOne
);
8124 case SCI_MULTIPLESELECTADDEACH
:
8125 MultipleSelectAdd(addEach
);
8128 case SCI_CHANGELEXERSTATE
:
8129 pdoc
->ChangeLexerState(static_cast<int>(wParam
), static_cast<int>(lParam
));
8132 case SCI_SETIDENTIFIER
:
8133 SetCtrlID(static_cast<int>(wParam
));
8136 case SCI_GETIDENTIFIER
:
8139 case SCI_SETTECHNOLOGY
:
8140 // No action by default
8143 case SCI_GETTECHNOLOGY
:
8146 case SCI_COUNTCHARACTERS
:
8147 return pdoc
->CountCharacters(static_cast<int>(wParam
), static_cast<int>(lParam
));
8150 return DefWndProc(iMessage
, wParam
, lParam
);
8152 //Platform::DebugPrintf("end wnd proc\n");