1 // Scintilla source code edit control
3 ** Defines the main editor class.
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.
32 enum {tickSize
= 100};
49 * When platform has a way to generate an event before painting,
50 * accumulate needed styling range and other work items in
51 * WorkNeeded to avoid unnecessary work inside paint handler
64 WorkNeeded() : active(false), items(workNone
), upTo(0) {}
70 void Need(workItems items_
, Position pos
) {
71 if ((items_
& workStyle
) && (upTo
< pos
))
73 items
= static_cast<workItems
>(items
| items_
);
78 * Hold a piece of text selected for copying or dragging, along with encoding and selection format information.
87 SelectionText() : rectangular(false), lineCopy(false), codePage(0), characterSet(0) {}
97 void Copy(const std::string
&s_
, int codePage_
, int characterSet_
, bool rectangular_
, bool lineCopy_
) {
100 characterSet
= characterSet_
;
101 rectangular
= rectangular_
;
102 lineCopy
= lineCopy_
;
103 FixSelectionForClipboard();
105 void Copy(const SelectionText
&other
) {
106 Copy(other
.s
, other
.codePage
, other
.characterSet
, other
.rectangular
, other
.lineCopy
);
108 const char *Data() const {
111 size_t Length() const {
114 size_t LengthWithTerminator() const {
115 return s
.length() + 1;
121 void FixSelectionForClipboard() {
122 // To avoid truncating the contents of the clipboard when pasted where the
123 // clipboard contains NUL characters, replace NUL characters by spaces.
124 std::replace(s
.begin(), s
.end(), '\0', ' ');
129 // The range of lines that need to be wrapped
130 enum { lineLarge
= 0x7ffffff };
131 int start
; // When there are wraps pending, will be in document range
132 int end
; // May be lineLarge to indicate all of document after start
141 void Wrapped(int line
) {
145 bool NeedsWrap() const {
148 bool AddRange(int lineStart
, int lineEnd
) {
149 const bool neededWrap
= NeedsWrap();
150 bool changed
= false;
151 if (start
> lineStart
) {
155 if ((end
< lineEnd
) || !neededWrap
) {
163 struct PrintParameters
{
172 class Editor
: public DocWatcher
{
173 // Private so Editor objects can not be copied
174 Editor(const Editor
&);
175 Editor
&operator=(const Editor
&);
177 protected: // ScintillaBase subclass needs access to much of Editor
179 /** On GTK+, Scintilla is a container widget holding two scroll bars
180 * whereas on Windows there is just one window with both scroll bars turned on. */
181 Window wMain
; ///< The Scintilla parent window
182 Window wMargin
; ///< May be separate when using a scroll view for wMain
184 /** Style resources may be expensive to allocate so are cached between uses.
185 * When a style attribute is changed, this cache is flushed. */
190 float scaleRGBAImage
;
192 PrintParameters printParameters
;
196 // Highlight current folding block
197 HighlightDelimiter highlightDelimiter
;
202 bool drawOverstrikeCaret
;
203 bool mouseDownCaptures
;
205 /** In bufferedDraw mode, graphics operations are drawn to a pixmap and then copied to
206 * the screen. This avoids flashing but is about 30% slower. */
208 /** In twoPhaseDraw mode, drawing is performed in two phases, first the background
209 * and then the foreground. This avoids chopping off characters that overlap the next run. */
212 int xOffset
; ///< Horizontal scrolled amount in pixels
213 int xCaretMargin
; ///< Ensure this many pixels visible on both sides of caret
214 bool horizontalScrollBarVisible
;
217 int lineWidthMaxSeen
;
218 bool verticalScrollBarVisible
;
222 bool mouseSelectionRectangularSwitch
;
223 bool multipleSelection
;
224 bool additionalSelectionTyping
;
226 bool additionalCaretsBlink
;
227 bool additionalCaretsVisible
;
229 int virtualSpaceOptions
;
232 Surface
*pixmapSelMargin
;
233 Surface
*pixmapSelPattern
;
234 Surface
*pixmapSelPatternOffset1
;
235 Surface
*pixmapIndentGuide
;
236 Surface
*pixmapIndentGuideHighlight
;
239 PositionCache posCache
;
240 SpecialRepresentations reprs
;
246 Timer autoScrollTimer
;
247 enum { autoScrollDelay
= 200 };
252 unsigned int lastClickTime
;
256 enum { selChar
, selWord
, selSubLine
, selWholeLine
} selectionType
;
258 enum { ddNone
, ddInitial
, ddDragging
} inDragDrop
;
259 bool dropWentOutside
;
260 SelectionPosition posDrag
;
261 SelectionPosition posDrop
;
265 int originalAnchorPos
;
266 int wordSelectAnchorStartPos
;
267 int wordSelectAnchorEndPos
;
268 int wordSelectInitialCaretPos
;
278 int bracesMatchStyle
;
279 int highlightGuideColumn
;
281 enum { notPainting
, painting
, paintAbandoned
} paintState
;
282 bool paintAbandonedByStyling
;
284 bool paintingAllText
;
286 WorkNeeded workNeeded
;
292 bool primarySelection
;
295 int caretXSlop
; ///< Ensure this many pixels visible on both sides of caret
298 int caretYSlop
; ///< Ensure this many lines visible on both sides of caret
316 WrapPending wrapPending
;
324 virtual void Initialise() = 0;
325 virtual void Finalise();
327 void InvalidateStyleData();
328 void InvalidateStyleRedraw();
329 void RefreshStyleData();
330 void SetRepresentations();
331 void DropGraphics(bool freeObjects
);
332 void AllocateGraphics();
334 // The top left visible point in main window coordinates. Will be 0,0 except for
335 // scroll views where it will be equivalent to the current scroll position.
336 virtual Point
GetVisibleOriginInMain();
337 Point
DocumentPointFromView(Point ptView
); // Convert a point from view space to document
338 int TopLineOfMain() const; // Return the line at Main's y coordinate 0
339 virtual PRectangle
GetClientRectangle();
340 virtual PRectangle
GetClientDrawingRectangle();
341 PRectangle
GetTextRectangle();
346 SelectionPosition
ClampPositionIntoDocument(SelectionPosition sp
) const;
347 Point
LocationFromPosition(SelectionPosition pos
);
348 Point
LocationFromPosition(int pos
);
349 int XFromPosition(int pos
);
350 int XFromPosition(SelectionPosition sp
);
351 SelectionPosition
SPositionFromLocation(Point pt
, bool canReturnInvalid
=false, bool charPosition
=false, bool virtualSpace
=true);
352 int PositionFromLocation(Point pt
, bool canReturnInvalid
=false, bool charPosition
=false);
353 SelectionPosition
SPositionFromLineX(int lineDoc
, int x
);
354 int PositionFromLineX(int line
, int x
);
355 int LineFromLocation(Point pt
) const;
356 void SetTopLine(int topLineNew
);
358 virtual bool AbandonPaint();
359 virtual void RedrawRect(PRectangle rc
);
360 virtual void DiscardOverdraw();
361 virtual void Redraw();
362 void RedrawSelMargin(int line
=-1, bool allAfter
=false);
363 PRectangle
RectangleFromRange(Range r
);
364 void InvalidateRange(int start
, int end
);
366 bool UserVirtualSpace() const {
367 return ((virtualSpaceOptions
& SCVS_USERACCESSIBLE
) != 0);
369 int CurrentPosition() const;
370 bool SelectionEmpty() const;
371 SelectionPosition
SelectionStart();
372 SelectionPosition
SelectionEnd();
373 void SetRectangularRange();
374 void ThinRectangularRange();
375 void InvalidateSelection(SelectionRange newMain
, bool invalidateWholeSelection
=false);
376 void SetSelection(SelectionPosition currentPos_
, SelectionPosition anchor_
);
377 void SetSelection(int currentPos_
, int anchor_
);
378 void SetSelection(SelectionPosition currentPos_
);
379 void SetSelection(int currentPos_
);
380 void SetEmptySelection(SelectionPosition currentPos_
);
381 void SetEmptySelection(int currentPos_
);
382 bool RangeContainsProtected(int start
, int end
) const;
383 bool SelectionContainsProtected();
384 int MovePositionOutsideChar(int pos
, int moveDir
, bool checkLineEnd
=true) const;
385 SelectionPosition
MovePositionOutsideChar(SelectionPosition pos
, int moveDir
, bool checkLineEnd
=true) const;
386 int MovePositionTo(SelectionPosition newPos
, Selection::selTypes sel
=Selection::noSel
, bool ensureVisible
=true);
387 int MovePositionTo(int newPos
, Selection::selTypes sel
=Selection::noSel
, bool ensureVisible
=true);
388 SelectionPosition
MovePositionSoVisible(SelectionPosition pos
, int moveDir
);
389 SelectionPosition
MovePositionSoVisible(int pos
, int moveDir
);
390 Point
PointMainCaret();
391 void SetLastXChosen();
393 void ScrollTo(int line
, bool moveThumb
=true);
394 virtual void ScrollText(int linesToMove
);
395 void HorizontalScrollTo(int xPos
);
396 void VerticalCentreCaret();
397 void MoveSelectedLines(int lineDelta
);
398 void MoveSelectedLinesUp();
399 void MoveSelectedLinesDown();
400 void MoveCaretInsideView(bool ensureVisible
=true);
401 int DisplayFromPosition(int pos
);
403 struct XYScrollPosition
{
406 XYScrollPosition(int xOffset_
, int topLine_
) : xOffset(xOffset_
), topLine(topLine_
) {}
407 bool operator==(const XYScrollPosition
&other
) const {
408 return (xOffset
== other
.xOffset
) && (topLine
== other
.topLine
);
411 enum XYScrollOptions
{
415 xysDefault
=xysUseMargin
|xysVertical
|xysHorizontal
};
416 XYScrollPosition
XYScrollToMakeVisible(const SelectionRange
&range
, const XYScrollOptions options
);
417 void SetXYScroll(XYScrollPosition newXY
);
418 void EnsureCaretVisible(bool useMargin
=true, bool vert
=true, bool horiz
=true);
419 void ScrollRange(SelectionRange range
);
420 void ShowCaretAtCurrentPosition();
422 void CaretSetPeriod(int period
);
423 void InvalidateCaret();
424 virtual void UpdateSystemCaret();
426 bool Wrapping() const;
427 void NeedWrapping(int docLineStart
=0, int docLineEnd
=WrapPending::lineLarge
);
428 bool WrapOneLine(Surface
*surface
, int lineToWrap
);
429 enum wrapScope
{wsAll
, wsVisible
, wsIdle
};
430 bool WrapLines(enum wrapScope ws
);
432 void LinesSplit(int pixelWidth
);
434 int SubstituteMarkerIfEmpty(int markerCheck
, int markerDefault
) const;
435 void PaintSelMargin(Surface
*surface
, PRectangle
&rc
);
436 LineLayout
*RetrieveLineLayout(int lineNumber
);
437 void LayoutLine(int line
, Surface
*surface
, const ViewStyle
&vstyle
, LineLayout
*ll
,
438 int width
=LineLayout::wrapWidthInfinite
);
439 ColourDesired
SelectionBackground(const ViewStyle
&vsDraw
, bool main
) const;
440 ColourDesired
TextBackground(const ViewStyle
&vsDraw
, ColourOptional background
, int inSelection
, bool inHotspot
, int styleMain
, int i
, LineLayout
*ll
) const;
441 void DrawIndentGuide(Surface
*surface
, int lineVisible
, int lineHeight
, int start
, PRectangle rcSegment
, bool highlight
);
442 static void DrawWrapMarker(Surface
*surface
, PRectangle rcPlace
, bool isEndMarker
, ColourDesired wrapColour
);
443 void DrawEOL(Surface
*surface
, const ViewStyle
&vsDraw
, PRectangle rcLine
, LineLayout
*ll
,
444 int line
, int lineEnd
, int xStart
, int subLine
, XYACCUMULATOR subLineStart
,
445 ColourOptional background
);
446 static void DrawIndicator(int indicNum
, int startPos
, int endPos
, Surface
*surface
, const ViewStyle
&vsDraw
,
447 int xStart
, PRectangle rcLine
, LineLayout
*ll
, int subLine
);
448 void DrawIndicators(Surface
*surface
, const ViewStyle
&vsDraw
, int line
, int xStart
,
449 PRectangle rcLine
, LineLayout
*ll
, int subLine
, int lineEnd
, bool under
);
450 void DrawAnnotation(Surface
*surface
, const ViewStyle
&vsDraw
, int line
, int xStart
,
451 PRectangle rcLine
, LineLayout
*ll
, int subLine
);
452 void DrawLine(Surface
*surface
, const ViewStyle
&vsDraw
, int line
, int lineVisible
, int xStart
,
453 PRectangle rcLine
, LineLayout
*ll
, int subLine
);
454 void DrawBlockCaret(Surface
*surface
, const ViewStyle
&vsDraw
, LineLayout
*ll
, int subLine
,
455 int xStart
, int offset
, int posCaret
, PRectangle rcCaret
, ColourDesired caretColour
) const;
456 void DrawCarets(Surface
*surface
, const ViewStyle
&vsDraw
, int line
, int xStart
,
457 PRectangle rcLine
, LineLayout
*ll
, int subLine
);
458 void RefreshPixMaps(Surface
*surfaceWindow
);
459 void Paint(Surface
*surfaceWindow
, PRectangle rcArea
);
460 long FormatRange(bool draw
, Sci_RangeToFormat
*pfr
);
461 int TextWidth(int style
, const char *text
);
463 virtual void SetVerticalScrollPos() = 0;
464 virtual void SetHorizontalScrollPos() = 0;
465 virtual bool ModifyScrollBars(int nMax
, int nPage
) = 0;
466 virtual void ReconfigureScrollBars();
467 void SetScrollBars();
470 void FilterSelections();
471 int InsertSpace(int position
, unsigned int spaces
);
472 void AddChar(char ch
);
473 virtual void AddCharUTF(char *s
, unsigned int len
, bool treatAsDBCS
=false);
474 void InsertPaste(const char *text
, int len
);
475 enum PasteShape
{ pasteStream
=0, pasteRectangular
= 1, pasteLine
= 2 };
476 void InsertPasteShape(const char *text
, int len
, PasteShape shape
);
477 void ClearSelection(bool retainMultipleSelections
= false);
479 void ClearDocumentStyle();
481 void PasteRectangular(SelectionPosition pos
, const char *ptr
, int len
);
482 virtual void Copy() = 0;
483 virtual void CopyAllowLine();
484 virtual bool CanPaste();
485 virtual void Paste() = 0;
491 void DelCharBack(bool allowLineStartDeletion
);
492 virtual void ClaimSelection() = 0;
494 static int ModifierFlags(bool shift
, bool ctrl
, bool alt
, bool meta
=false);
495 virtual void NotifyChange() = 0;
496 virtual void NotifyFocus(bool focus
);
497 virtual void SetCtrlID(int identifier
);
498 virtual int GetCtrlID() { return ctrlID
; }
499 virtual void NotifyParent(SCNotification scn
) = 0;
500 virtual void NotifyParent(SCNotification
* scn
) = 0;
501 virtual void NotifyStyleToNeeded(int endStyleNeeded
);
502 void NotifyChar(int ch
);
503 void NotifySavePoint(bool isSavePoint
);
504 void NotifyModifyAttempt();
505 virtual void NotifyDoubleClick(Point pt
, int modifiers
);
506 virtual void NotifyDoubleClick(Point pt
, bool shift
, bool ctrl
, bool alt
);
507 void NotifyHotSpotClicked(int position
, int modifiers
);
508 void NotifyHotSpotClicked(int position
, bool shift
, bool ctrl
, bool alt
);
509 void NotifyHotSpotDoubleClicked(int position
, int modifiers
);
510 void NotifyHotSpotDoubleClicked(int position
, bool shift
, bool ctrl
, bool alt
);
511 void NotifyHotSpotReleaseClick(int position
, int modifiers
);
512 void NotifyHotSpotReleaseClick(int position
, bool shift
, bool ctrl
, bool alt
);
513 bool NotifyUpdateUI();
514 void NotifyPainted();
515 void NotifyIndicatorClick(bool click
, int position
, int modifiers
);
516 void NotifyIndicatorClick(bool click
, int position
, bool shift
, bool ctrl
, bool alt
);
517 bool NotifyMarginClick(Point pt
, int modifiers
);
518 bool NotifyMarginClick(Point pt
, bool shift
, bool ctrl
, bool alt
);
519 void NotifyNeedShown(int pos
, int len
);
520 void NotifyDwelling(Point pt
, bool state
);
523 void NotifyModifyAttempt(Document
*document
, void *userData
);
524 void NotifySavePoint(Document
*document
, void *userData
, bool atSavePoint
);
525 void CheckModificationForWrap(DocModification mh
);
526 void NotifyModified(Document
*document
, DocModification mh
, void *userData
);
527 void NotifyDeleted(Document
*document
, void *userData
);
528 void NotifyStyleNeeded(Document
*doc
, void *userData
, int endPos
);
529 void NotifyLexerChanged(Document
*doc
, void *userData
);
530 void NotifyErrorOccurred(Document
*doc
, void *userData
, int status
);
531 void NotifyMacroRecord(unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
);
533 void ContainerNeedsUpdate(int flags
);
534 void PageMove(int direction
, Selection::selTypes sel
=Selection::noSel
, bool stuttered
= false);
535 enum { cmSame
, cmUpper
, cmLower
};
536 virtual std::string
CaseMapString(const std::string
&s
, int caseMapping
);
537 void ChangeCaseOfSelection(int caseMapping
);
538 void LineTranspose();
539 void Duplicate(bool forLine
);
540 virtual void CancelModes();
542 void CursorUpOrDown(int direction
, Selection::selTypes sel
=Selection::noSel
);
543 void ParaUpOrDown(int direction
, Selection::selTypes sel
=Selection::noSel
);
544 int StartEndDisplayLine(int pos
, bool start
);
545 virtual int KeyCommand(unsigned int iMessage
);
546 virtual int KeyDefault(int /* key */, int /*modifiers*/);
547 int KeyDownWithModifiers(int key
, int modifiers
, bool *consumed
);
548 int KeyDown(int key
, bool shift
, bool ctrl
, bool alt
, bool *consumed
=0);
550 void Indent(bool forwards
);
552 virtual CaseFolder
*CaseFolderForEncoding();
553 long FindText(uptr_t wParam
, sptr_t lParam
);
555 long SearchText(unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
);
556 long SearchInTarget(const char *text
, int length
);
557 void GoToLine(int lineNo
);
559 virtual void CopyToClipboard(const SelectionText
&selectedText
) = 0;
560 std::string
RangeText(int start
, int end
) const;
561 void CopySelectionRange(SelectionText
*ss
, bool allowLineCopy
=false);
562 void CopyRangeToClipboard(int start
, int end
);
563 void CopyText(int length
, const char *text
);
564 void SetDragPosition(SelectionPosition newPos
);
565 virtual void DisplayCursor(Window::Cursor c
);
566 virtual bool DragThreshold(Point ptStart
, Point ptNow
);
567 virtual void StartDrag();
568 void DropAt(SelectionPosition position
, const char *value
, size_t lengthValue
, bool moving
, bool rectangular
);
569 void DropAt(SelectionPosition position
, const char *value
, bool moving
, bool rectangular
);
570 /** PositionInSelection returns true if position in selection. */
571 bool PositionInSelection(int pos
);
572 bool PointInSelection(Point pt
);
573 bool PointInSelMargin(Point pt
);
574 Window::Cursor
GetMarginCursor(Point pt
) const;
575 void TrimAndSetSelection(int currentPos_
, int anchor_
);
576 void LineSelection(int lineCurrentPos_
, int lineAnchorPos_
, bool wholeLine
);
577 void WordSelection(int pos
);
578 void DwellEnd(bool mouseMoved
);
580 virtual void ButtonDownWithModifiers(Point pt
, unsigned int curTime
, int modifiers
);
581 virtual void ButtonDown(Point pt
, unsigned int curTime
, bool shift
, bool ctrl
, bool alt
);
582 void ButtonMoveWithModifiers(Point pt
, int modifiers
);
583 void ButtonMove(Point pt
);
584 void ButtonUp(Point pt
, unsigned int curTime
, bool ctrl
);
588 virtual void SetTicking(bool on
) = 0;
589 virtual bool SetIdle(bool) { return false; }
590 virtual void SetMouseCapture(bool on
) = 0;
591 virtual bool HaveMouseCapture() = 0;
592 void SetFocusState(bool focusState
);
594 int PositionAfterArea(PRectangle rcArea
) const;
595 void StyleToPositionInView(Position pos
);
596 virtual void IdleWork();
597 virtual void QueueIdleWork(WorkNeeded::workItems items
, int upTo
=0);
599 virtual bool PaintContains(PRectangle rc
);
600 bool PaintContainsMargin();
601 void CheckForChangeOutsidePaint(Range r
);
602 void SetBraceHighlight(Position pos0
, Position pos1
, int matchStyle
);
604 void SetAnnotationHeights(int start
, int end
);
605 virtual void SetDocPointer(Document
*document
);
607 void SetAnnotationVisible(int visible
);
609 int ExpandLine(int line
);
610 void SetFoldExpanded(int lineDoc
, bool expanded
);
611 void FoldLine(int line
, int action
);
612 void FoldExpand(int line
, int action
, int level
);
613 int ContractedFoldNext(int lineStart
) const;
614 void EnsureLineVisible(int lineDoc
, bool enforcePolicy
);
615 void FoldChanged(int line
, int levelNow
, int levelPrev
);
616 void NeedShown(int pos
, int len
);
617 void FoldAll(int action
);
619 int GetTag(char *tagValue
, int tagNumber
);
620 int ReplaceTarget(bool replacePatterns
, const char *text
, int length
=-1);
622 bool PositionIsHotspot(int position
) const;
623 bool PointIsHotspot(Point pt
);
624 void SetHotSpotRange(Point
*pt
);
625 Range
GetHotSpotRange() const;
627 int CodePage() const;
628 virtual bool ValidCodePage(int /* codePage */) const { return true; }
629 int WrapCount(int line
);
630 void AddStyledText(char *buffer
, int appendLength
);
632 virtual sptr_t
DefWndProc(unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
) = 0;
633 void StyleSetMessage(unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
);
634 sptr_t
StyleGetMessage(unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
);
636 static const char *StringFromEOLMode(int eolMode
);
638 static sptr_t
StringResult(sptr_t lParam
, const char *val
);
639 static sptr_t
BytesResult(sptr_t lParam
, const unsigned char *val
, size_t len
);
642 // Public so the COM thunks can access it.
643 bool IsUnicodeMode() const;
644 // Public so scintilla_send_message can use it.
645 virtual sptr_t
WndProc(unsigned int iMessage
, uptr_t wParam
, sptr_t lParam
);
646 // Public so scintilla_set_id can use it.
648 // Public so COM methods for drag and drop can set it.
650 friend class AutoSurface
;
651 friend class SelectionLineIterator
;
655 * A smart pointer class to ensure Surfaces are set up and deleted correctly.
661 AutoSurface(Editor
*ed
, int technology
= -1) : surf(0) {
662 if (ed
->wMain
.GetID()) {
663 surf
= Surface::Allocate(technology
!= -1 ? technology
: ed
->technology
);
665 surf
->Init(ed
->wMain
.GetID());
666 surf
->SetUnicodeMode(SC_CP_UTF8
== ed
->CodePage());
667 surf
->SetDBCSMode(ed
->CodePage());
671 AutoSurface(SurfaceID sid
, Editor
*ed
, int technology
= -1) : surf(0) {
672 if (ed
->wMain
.GetID()) {
673 surf
= Surface::Allocate(technology
!= -1 ? technology
: ed
->technology
);
675 surf
->Init(sid
, ed
->wMain
.GetID());
676 surf
->SetUnicodeMode(SC_CP_UTF8
== ed
->CodePage());
677 surf
->SetDBCSMode(ed
->CodePage());
684 Surface
*operator->() const {
687 operator Surface
*() const {