1 | // Scintilla source code edit control |
2 | /** @file Editor.h |
3 | ** Defines the main editor class. |
4 | **/ |
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. |
7 | |
8 | #ifndef EDITOR_H |
9 | #define EDITOR_H |
10 | |
11 | namespace Scintilla::Internal { |
12 | |
13 | /** |
14 | */ |
15 | class Timer { |
16 | public: |
17 | bool ticking; |
18 | int ticksToWait; |
19 | enum {tickSize = 100}; |
20 | TickerID tickerID; |
21 | |
22 | Timer() noexcept; |
23 | }; |
24 | |
25 | /** |
26 | */ |
27 | class Idler { |
28 | public: |
29 | bool state; |
30 | IdlerID idlerID; |
31 | |
32 | Idler() noexcept; |
33 | }; |
34 | |
35 | /** |
36 | * When platform has a way to generate an event before painting, |
37 | * accumulate needed styling range and other work items in |
38 | * WorkNeeded to avoid unnecessary work inside paint handler |
39 | */ |
40 | |
41 | enum class WorkItems { |
42 | none = 0, |
43 | style = 1, |
44 | updateUI = 2 |
45 | }; |
46 | |
47 | class WorkNeeded { |
48 | public: |
49 | enum WorkItems items; |
50 | Sci::Position upTo; |
51 | |
52 | WorkNeeded() noexcept : items(WorkItems::none), upTo(0) {} |
53 | void Reset() noexcept { |
54 | items = WorkItems::none; |
55 | upTo = 0; |
56 | } |
57 | void Need(WorkItems items_, Sci::Position pos) noexcept { |
58 | if (Scintilla::FlagSet(items_, WorkItems::style) && (upTo < pos)) |
59 | upTo = pos; |
60 | items = static_cast<WorkItems>(static_cast<int>(items) | static_cast<int>(items_)); |
61 | } |
62 | }; |
63 | |
64 | /** |
65 | * Hold a piece of text selected for copying or dragging, along with encoding and selection format information. |
66 | */ |
67 | class SelectionText { |
68 | std::string s; |
69 | public: |
70 | bool rectangular; |
71 | bool lineCopy; |
72 | int codePage; |
73 | Scintilla::CharacterSet characterSet; |
74 | SelectionText() noexcept : rectangular(false), lineCopy(false), codePage(0), characterSet(Scintilla::CharacterSet::Ansi) {} |
75 | void Clear() noexcept { |
76 | s.clear(); |
77 | rectangular = false; |
78 | lineCopy = false; |
79 | codePage = 0; |
80 | characterSet = Scintilla::CharacterSet::Ansi; |
81 | } |
82 | void Copy(const std::string &s_, int codePage_, Scintilla::CharacterSet characterSet_, bool rectangular_, bool lineCopy_) { |
83 | s = s_; |
84 | codePage = codePage_; |
85 | characterSet = characterSet_; |
86 | rectangular = rectangular_; |
87 | lineCopy = lineCopy_; |
88 | FixSelectionForClipboard(); |
89 | } |
90 | void Copy(const SelectionText &other) { |
91 | Copy(other.s, other.codePage, other.characterSet, other.rectangular, other.lineCopy); |
92 | } |
93 | const char *Data() const noexcept { |
94 | return s.c_str(); |
95 | } |
96 | size_t Length() const noexcept { |
97 | return s.length(); |
98 | } |
99 | size_t LengthWithTerminator() const noexcept { |
100 | return s.length() + 1; |
101 | } |
102 | bool Empty() const noexcept { |
103 | return s.empty(); |
104 | } |
105 | private: |
106 | void FixSelectionForClipboard() { |
107 | // To avoid truncating the contents of the clipboard when pasted where the |
108 | // clipboard contains NUL characters, replace NUL characters by spaces. |
109 | std::replace(s.begin(), s.end(), '\0', ' '); |
110 | } |
111 | }; |
112 | |
113 | struct WrapPending { |
114 | // The range of lines that need to be wrapped |
115 | enum { lineLarge = 0x7ffffff }; |
116 | Sci::Line start; // When there are wraps pending, will be in document range |
117 | Sci::Line end; // May be lineLarge to indicate all of document after start |
118 | WrapPending() noexcept { |
119 | start = lineLarge; |
120 | end = lineLarge; |
121 | } |
122 | void Reset() noexcept { |
123 | start = lineLarge; |
124 | end = lineLarge; |
125 | } |
126 | void Wrapped(Sci::Line line) noexcept { |
127 | if (start == line) |
128 | start++; |
129 | } |
130 | bool NeedsWrap() const noexcept { |
131 | return start < end; |
132 | } |
133 | bool AddRange(Sci::Line lineStart, Sci::Line lineEnd) noexcept { |
134 | const bool neededWrap = NeedsWrap(); |
135 | bool changed = false; |
136 | if (start > lineStart) { |
137 | start = lineStart; |
138 | changed = true; |
139 | } |
140 | if ((end < lineEnd) || !neededWrap) { |
141 | end = lineEnd; |
142 | changed = true; |
143 | } |
144 | return changed; |
145 | } |
146 | }; |
147 | |
148 | struct CaretPolicySlop { |
149 | Scintilla::CaretPolicy policy; // Combination from CaretPolicy::Slop, CaretPolicy::Strict, CaretPolicy::Jumps, CaretPolicy::Even |
150 | int slop; // Pixels for X, lines for Y |
151 | CaretPolicySlop(Scintilla::CaretPolicy policy_, intptr_t slop_) noexcept : |
152 | policy(policy_), slop(static_cast<int>(slop_)) {} |
153 | CaretPolicySlop(uintptr_t policy_=0, intptr_t slop_=0) noexcept : |
154 | policy(static_cast<Scintilla::CaretPolicy>(policy_)), slop(static_cast<int>(slop_)) {} |
155 | }; |
156 | |
157 | struct CaretPolicies { |
158 | CaretPolicySlop x; |
159 | CaretPolicySlop y; |
160 | }; |
161 | |
162 | struct VisiblePolicySlop { |
163 | Scintilla::VisiblePolicy policy; // Combination from VisiblePolicy::Slop, VisiblePolicy::Strict |
164 | int slop; // Pixels for X, lines for Y |
165 | VisiblePolicySlop(uintptr_t policy_ = 0, intptr_t slop_ = 0) noexcept : |
166 | policy(static_cast<Scintilla::VisiblePolicy>(policy_)), slop(static_cast<int>(slop_)) {} |
167 | }; |
168 | |
169 | enum class XYScrollOptions { |
170 | none = 0x0, |
171 | useMargin = 0x1, |
172 | vertical = 0x2, |
173 | horizontal = 0x4, |
174 | all = useMargin | vertical | horizontal |
175 | }; |
176 | |
177 | constexpr XYScrollOptions operator|(XYScrollOptions a, XYScrollOptions b) noexcept { |
178 | return static_cast<XYScrollOptions>(static_cast<int>(a) | static_cast<int>(b)); |
179 | } |
180 | |
181 | /** |
182 | */ |
183 | class Editor : public EditModel, public DocWatcher { |
184 | protected: // ScintillaBase subclass needs access to much of Editor |
185 | |
186 | /** On GTK+, Scintilla is a container widget holding two scroll bars |
187 | * whereas on Windows there is just one window with both scroll bars turned on. */ |
188 | Window wMain; ///< The Scintilla parent window |
189 | Window wMargin; ///< May be separate when using a scroll view for wMain |
190 | |
191 | // Optimization that avoids superfluous invalidations |
192 | bool redrawPendingText = false; |
193 | bool redrawPendingMargin = false; |
194 | |
195 | /** Style resources may be expensive to allocate so are cached between uses. |
196 | * When a style attribute is changed, this cache is flushed. */ |
197 | bool stylesValid; |
198 | ViewStyle vs; |
199 | Scintilla::Technology technology; |
200 | Point sizeRGBAImage; |
201 | float scaleRGBAImage; |
202 | |
203 | MarginView marginView; |
204 | EditView view; |
205 | |
206 | Scintilla::CursorShape cursorMode; |
207 | |
208 | bool mouseDownCaptures; |
209 | bool mouseWheelCaptures; |
210 | |
211 | int xCaretMargin; ///< Ensure this many pixels visible on both sides of caret |
212 | bool horizontalScrollBarVisible; |
213 | int scrollWidth; |
214 | bool verticalScrollBarVisible; |
215 | bool endAtLastLine; |
216 | Scintilla::CaretSticky caretSticky; |
217 | Scintilla::MarginOption marginOptions; |
218 | bool mouseSelectionRectangularSwitch; |
219 | bool multipleSelection; |
220 | bool additionalSelectionTyping; |
221 | Scintilla::MultiPaste multiPasteMode; |
222 | |
223 | Scintilla::VirtualSpace virtualSpaceOptions; |
224 | |
225 | KeyMap kmap; |
226 | |
227 | Timer timer; |
228 | Timer autoScrollTimer; |
229 | enum { autoScrollDelay = 200 }; |
230 | |
231 | Idler idler; |
232 | |
233 | Point lastClick; |
234 | unsigned int lastClickTime; |
235 | Point doubleClickCloseThreshold; |
236 | int dwellDelay; |
237 | int ticksToDwell; |
238 | bool dwelling; |
239 | enum class TextUnit { character, word, subLine, wholeLine } selectionUnit; |
240 | Point ptMouseLast; |
241 | enum class DragDrop { none, initial, dragging } inDragDrop; |
242 | bool dropWentOutside; |
243 | SelectionPosition posDrop; |
244 | Sci::Position hotSpotClickPos; |
245 | int lastXChosen; |
246 | Sci::Position lineAnchorPos; |
247 | Sci::Position originalAnchorPos; |
248 | Sci::Position wordSelectAnchorStartPos; |
249 | Sci::Position wordSelectAnchorEndPos; |
250 | Sci::Position wordSelectInitialCaretPos; |
251 | SelectionSegment targetRange; |
252 | Scintilla::FindOption searchFlags; |
253 | Sci::Line topLine; |
254 | Sci::Position posTopLine; |
255 | Sci::Position lengthForEncode; |
256 | |
257 | Scintilla::Update needUpdateUI; |
258 | |
259 | enum class PaintState { notPainting, painting, abandoned } paintState; |
260 | bool paintAbandonedByStyling; |
261 | PRectangle rcPaint; |
262 | bool paintingAllText; |
263 | bool willRedrawAll; |
264 | WorkNeeded workNeeded; |
265 | Scintilla::IdleStyling idleStyling; |
266 | bool needIdleStyling; |
267 | |
268 | Scintilla::ModificationFlags modEventMask; |
269 | bool commandEvents; |
270 | |
271 | SelectionText drag; |
272 | |
273 | CaretPolicies caretPolicies; |
274 | |
275 | VisiblePolicySlop visiblePolicy; |
276 | |
277 | Sci::Position searchAnchor; |
278 | |
279 | bool recordingMacro; |
280 | |
281 | Scintilla::AutomaticFold foldAutomatic; |
282 | |
283 | // Wrapping support |
284 | WrapPending wrapPending; |
285 | ActionDuration durationWrapOneByte; |
286 | |
287 | bool convertPastes; |
288 | |
289 | Editor(); |
290 | // Deleted so Editor objects can not be copied. |
291 | Editor(const Editor &) = delete; |
292 | Editor(Editor &&) = delete; |
293 | Editor &operator=(const Editor &) = delete; |
294 | Editor &operator=(Editor &&) = delete; |
295 | // ~Editor() in public section |
296 | virtual void Initialise() = 0; |
297 | virtual void Finalise(); |
298 | |
299 | void InvalidateStyleData(); |
300 | void InvalidateStyleRedraw(); |
301 | void RefreshStyleData(); |
302 | void SetRepresentations(); |
303 | void DropGraphics() noexcept; |
304 | |
305 | // The top left visible point in main window coordinates. Will be 0,0 except for |
306 | // scroll views where it will be equivalent to the current scroll position. |
307 | Point GetVisibleOriginInMain() const override; |
308 | PointDocument DocumentPointFromView(Point ptView) const; // Convert a point from view space to document |
309 | Sci::Line TopLineOfMain() const override; // Return the line at Main's y coordinate 0 |
310 | virtual PRectangle GetClientRectangle() const; |
311 | virtual PRectangle GetClientDrawingRectangle(); |
312 | PRectangle GetTextRectangle() const; |
313 | |
314 | Sci::Line LinesOnScreen() const override; |
315 | Sci::Line LinesToScroll() const; |
316 | Sci::Line MaxScrollPos() const; |
317 | SelectionPosition ClampPositionIntoDocument(SelectionPosition sp) const; |
318 | Point LocationFromPosition(SelectionPosition pos, PointEnd pe=PointEnd::start); |
319 | Point LocationFromPosition(Sci::Position pos, PointEnd pe=PointEnd::start); |
320 | int XFromPosition(SelectionPosition sp); |
321 | SelectionPosition SPositionFromLocation(Point pt, bool canReturnInvalid=false, bool charPosition=false, bool virtualSpace=true); |
322 | Sci::Position PositionFromLocation(Point pt, bool canReturnInvalid = false, bool charPosition = false); |
323 | SelectionPosition SPositionFromLineX(Sci::Line lineDoc, int x); |
324 | Sci::Position PositionFromLineX(Sci::Line lineDoc, int x); |
325 | Sci::Line LineFromLocation(Point pt) const; |
326 | void SetTopLine(Sci::Line topLineNew); |
327 | |
328 | virtual bool AbandonPaint(); |
329 | virtual void RedrawRect(PRectangle rc); |
330 | virtual void DiscardOverdraw(); |
331 | virtual void Redraw(); |
332 | void RedrawSelMargin(Sci::Line line=-1, bool allAfter=false); |
333 | PRectangle RectangleFromRange(Range r, int overlap); |
334 | void InvalidateRange(Sci::Position start, Sci::Position end); |
335 | |
336 | bool UserVirtualSpace() const noexcept { |
337 | return (FlagSet(virtualSpaceOptions, Scintilla::VirtualSpace::UserAccessible)); |
338 | } |
339 | Sci::Position CurrentPosition() const; |
340 | bool SelectionEmpty() const noexcept; |
341 | SelectionPosition SelectionStart(); |
342 | SelectionPosition SelectionEnd(); |
343 | void SetRectangularRange(); |
344 | void ThinRectangularRange(); |
345 | void InvalidateSelection(SelectionRange newMain, bool invalidateWholeSelection=false); |
346 | void InvalidateWholeSelection(); |
347 | SelectionRange LineSelectionRange(SelectionPosition currentPos_, SelectionPosition anchor_) const; |
348 | void SetSelection(SelectionPosition currentPos_, SelectionPosition anchor_); |
349 | void SetSelection(Sci::Position currentPos_, Sci::Position anchor_); |
350 | void SetSelection(SelectionPosition currentPos_); |
351 | void SetEmptySelection(SelectionPosition currentPos_); |
352 | void SetEmptySelection(Sci::Position currentPos_); |
353 | enum class AddNumber { one, each }; |
354 | void MultipleSelectAdd(AddNumber addNumber); |
355 | bool RangeContainsProtected(Sci::Position start, Sci::Position end) const noexcept; |
356 | bool SelectionContainsProtected() const; |
357 | Sci::Position MovePositionOutsideChar(Sci::Position pos, Sci::Position moveDir, bool checkLineEnd=true) const; |
358 | SelectionPosition MovePositionOutsideChar(SelectionPosition pos, Sci::Position moveDir, bool checkLineEnd=true) const; |
359 | void MovedCaret(SelectionPosition newPos, SelectionPosition previousPos, |
360 | bool ensureVisible, CaretPolicies policies); |
361 | void MovePositionTo(SelectionPosition newPos, Selection::SelTypes selt=Selection::SelTypes::none, bool ensureVisible=true); |
362 | void MovePositionTo(Sci::Position newPos, Selection::SelTypes selt=Selection::SelTypes::none, bool ensureVisible=true); |
363 | SelectionPosition MovePositionSoVisible(SelectionPosition pos, int moveDir); |
364 | SelectionPosition MovePositionSoVisible(Sci::Position pos, int moveDir); |
365 | Point PointMainCaret(); |
366 | void SetLastXChosen(); |
367 | |
368 | void ScrollTo(Sci::Line line, bool moveThumb=true); |
369 | virtual void ScrollText(Sci::Line linesToMove); |
370 | void HorizontalScrollTo(int xPos); |
371 | void VerticalCentreCaret(); |
372 | void MoveSelectedLines(int lineDelta); |
373 | void MoveSelectedLinesUp(); |
374 | void MoveSelectedLinesDown(); |
375 | void MoveCaretInsideView(bool ensureVisible=true); |
376 | Sci::Line DisplayFromPosition(Sci::Position pos); |
377 | |
378 | struct XYScrollPosition { |
379 | int xOffset; |
380 | Sci::Line topLine; |
381 | XYScrollPosition(int xOffset_, Sci::Line topLine_) noexcept : xOffset(xOffset_), topLine(topLine_) {} |
382 | bool operator==(const XYScrollPosition &other) const noexcept { |
383 | return (xOffset == other.xOffset) && (topLine == other.topLine); |
384 | } |
385 | }; |
386 | XYScrollPosition XYScrollToMakeVisible(const SelectionRange &range, |
387 | const XYScrollOptions options, CaretPolicies policies); |
388 | void SetXYScroll(XYScrollPosition newXY); |
389 | void EnsureCaretVisible(bool useMargin=true, bool vert=true, bool horiz=true); |
390 | void ScrollRange(SelectionRange range); |
391 | void ShowCaretAtCurrentPosition(); |
392 | void DropCaret(); |
393 | void CaretSetPeriod(int period); |
394 | void InvalidateCaret(); |
395 | virtual void NotifyCaretMove(); |
396 | virtual void UpdateSystemCaret(); |
397 | |
398 | bool Wrapping() const noexcept; |
399 | void NeedWrapping(Sci::Line docLineStart=0, Sci::Line docLineEnd=WrapPending::lineLarge); |
400 | bool WrapOneLine(Surface *surface, Sci::Line lineToWrap); |
401 | enum class WrapScope {wsAll, wsVisible, wsIdle}; |
402 | bool WrapLines(WrapScope ws); |
403 | void LinesJoin(); |
404 | void LinesSplit(int pixelWidth); |
405 | |
406 | void PaintSelMargin(Surface *surfaceWindow, const PRectangle &rc); |
407 | void RefreshPixMaps(Surface *surfaceWindow); |
408 | void Paint(Surface *surfaceWindow, PRectangle rcArea); |
409 | Sci::Position FormatRange(bool draw, const Scintilla::RangeToFormat *pfr); |
410 | long TextWidth(Scintilla::uptr_t style, const char *text); |
411 | |
412 | virtual void SetVerticalScrollPos() = 0; |
413 | virtual void SetHorizontalScrollPos() = 0; |
414 | virtual bool ModifyScrollBars(Sci::Line nMax, Sci::Line nPage) = 0; |
415 | virtual void ReconfigureScrollBars(); |
416 | void SetScrollBars(); |
417 | void ChangeSize(); |
418 | |
419 | void FilterSelections(); |
420 | Sci::Position RealizeVirtualSpace(Sci::Position position, Sci::Position virtualSpace); |
421 | SelectionPosition RealizeVirtualSpace(const SelectionPosition &position); |
422 | void AddChar(char ch); |
423 | virtual void InsertCharacter(std::string_view sv, Scintilla::CharacterSource charSource); |
424 | void ClearBeforeTentativeStart(); |
425 | void InsertPaste(const char *text, Sci::Position len); |
426 | enum class PasteShape { stream=0, rectangular = 1, line = 2 }; |
427 | void InsertPasteShape(const char *text, Sci::Position len, PasteShape shape); |
428 | void ClearSelection(bool retainMultipleSelections = false); |
429 | void ClearAll(); |
430 | void ClearDocumentStyle(); |
431 | virtual void Cut(); |
432 | void PasteRectangular(SelectionPosition pos, const char *ptr, Sci::Position len); |
433 | virtual void Copy() = 0; |
434 | void CopyAllowLine(); |
435 | virtual bool CanPaste(); |
436 | virtual void Paste() = 0; |
437 | void Clear(); |
438 | virtual void SelectAll(); |
439 | virtual void Undo(); |
440 | virtual void Redo(); |
441 | void DelCharBack(bool allowLineStartDeletion); |
442 | virtual void ClaimSelection() = 0; |
443 | |
444 | static Scintilla::KeyMod ModifierFlags(bool shift, bool ctrl, bool alt, bool meta=false, bool super=false) noexcept; |
445 | virtual void NotifyChange() = 0; |
446 | virtual void NotifyFocus(bool focus); |
447 | virtual void SetCtrlID(int identifier); |
448 | virtual int GetCtrlID() { return ctrlID; } |
449 | virtual void NotifyParent(Scintilla::NotificationData scn) = 0; |
450 | virtual void NotifyStyleToNeeded(Sci::Position endStyleNeeded); |
451 | void NotifyChar(int ch, Scintilla::CharacterSource charSource); |
452 | void NotifySavePoint(bool isSavePoint); |
453 | void NotifyModifyAttempt(); |
454 | virtual void NotifyDoubleClick(Point pt, Scintilla::KeyMod modifiers); |
455 | void NotifyHotSpotClicked(Sci::Position position, Scintilla::KeyMod modifiers); |
456 | void NotifyHotSpotDoubleClicked(Sci::Position position, Scintilla::KeyMod modifiers); |
457 | void NotifyHotSpotReleaseClick(Sci::Position position, Scintilla::KeyMod modifiers); |
458 | bool NotifyUpdateUI(); |
459 | void NotifyPainted(); |
460 | void NotifyIndicatorClick(bool click, Sci::Position position, Scintilla::KeyMod modifiers); |
461 | bool NotifyMarginClick(Point pt, Scintilla::KeyMod modifiers); |
462 | bool NotifyMarginRightClick(Point pt, Scintilla::KeyMod modifiers); |
463 | void NotifyNeedShown(Sci::Position pos, Sci::Position len); |
464 | void NotifyDwelling(Point pt, bool state); |
465 | void NotifyZoom(); |
466 | |
467 | void NotifyModifyAttempt(Document *document, void *userData) override; |
468 | void NotifySavePoint(Document *document, void *userData, bool atSavePoint) override; |
469 | void CheckModificationForWrap(DocModification mh); |
470 | void NotifyModified(Document *document, DocModification mh, void *userData) override; |
471 | void NotifyDeleted(Document *document, void *userData) noexcept override; |
472 | void NotifyStyleNeeded(Document *doc, void *userData, Sci::Position endStyleNeeded) override; |
473 | void NotifyLexerChanged(Document *doc, void *userData) override; |
474 | void NotifyErrorOccurred(Document *doc, void *userData, Scintilla::Status status) override; |
475 | void NotifyMacroRecord(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam); |
476 | |
477 | void ContainerNeedsUpdate(Scintilla::Update flags) noexcept; |
478 | void PageMove(int direction, Selection::SelTypes selt=Selection::SelTypes::none, bool stuttered = false); |
479 | enum class CaseMapping { same, upper, lower }; |
480 | virtual std::string CaseMapString(const std::string &s, CaseMapping caseMapping); |
481 | void ChangeCaseOfSelection(CaseMapping caseMapping); |
482 | void LineTranspose(); |
483 | void LineReverse(); |
484 | void Duplicate(bool forLine); |
485 | virtual void CancelModes(); |
486 | void NewLine(); |
487 | SelectionPosition PositionUpOrDown(SelectionPosition spStart, int direction, int lastX); |
488 | void CursorUpOrDown(int direction, Selection::SelTypes selt); |
489 | void ParaUpOrDown(int direction, Selection::SelTypes selt); |
490 | Range RangeDisplayLine(Sci::Line lineVisible); |
491 | Sci::Position StartEndDisplayLine(Sci::Position pos, bool start); |
492 | Sci::Position VCHomeDisplayPosition(Sci::Position position); |
493 | Sci::Position VCHomeWrapPosition(Sci::Position position); |
494 | Sci::Position LineEndWrapPosition(Sci::Position position); |
495 | int HorizontalMove(Scintilla::Message iMessage); |
496 | int DelWordOrLine(Scintilla::Message iMessage); |
497 | virtual int KeyCommand(Scintilla::Message iMessage); |
498 | virtual int KeyDefault(Scintilla::Keys /* key */, Scintilla::KeyMod /*modifiers*/); |
499 | int KeyDownWithModifiers(Scintilla::Keys key, Scintilla::KeyMod modifiers, bool *consumed); |
500 | |
501 | void Indent(bool forwards); |
502 | |
503 | virtual std::unique_ptr<CaseFolder> CaseFolderForEncoding(); |
504 | Sci::Position FindText(Scintilla::uptr_t wParam, Scintilla::sptr_t lParam); |
505 | void SearchAnchor(); |
506 | Sci::Position SearchText(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam); |
507 | Sci::Position SearchInTarget(const char *text, Sci::Position length); |
508 | void GoToLine(Sci::Line lineNo); |
509 | |
510 | virtual void CopyToClipboard(const SelectionText &selectedText) = 0; |
511 | std::string RangeText(Sci::Position start, Sci::Position end) const; |
512 | void CopySelectionRange(SelectionText *ss, bool allowLineCopy=false); |
513 | void CopyRangeToClipboard(Sci::Position start, Sci::Position end); |
514 | void CopyText(size_t length, const char *text); |
515 | void SetDragPosition(SelectionPosition newPos); |
516 | virtual void DisplayCursor(Window::Cursor c); |
517 | virtual bool DragThreshold(Point ptStart, Point ptNow); |
518 | virtual void StartDrag(); |
519 | void DropAt(SelectionPosition position, const char *value, size_t lengthValue, bool moving, bool rectangular); |
520 | void DropAt(SelectionPosition position, const char *value, bool moving, bool rectangular); |
521 | /** PositionInSelection returns true if position in selection. */ |
522 | bool PositionInSelection(Sci::Position pos); |
523 | bool PointInSelection(Point pt); |
524 | bool PointInSelMargin(Point pt) const; |
525 | Window::Cursor GetMarginCursor(Point pt) const noexcept; |
526 | void TrimAndSetSelection(Sci::Position currentPos_, Sci::Position anchor_); |
527 | void LineSelection(Sci::Position lineCurrentPos_, Sci::Position lineAnchorPos_, bool wholeLine); |
528 | void WordSelection(Sci::Position pos); |
529 | void DwellEnd(bool mouseMoved); |
530 | void MouseLeave(); |
531 | virtual void ButtonDownWithModifiers(Point pt, unsigned int curTime, Scintilla::KeyMod modifiers); |
532 | virtual void RightButtonDownWithModifiers(Point pt, unsigned int curTime, Scintilla::KeyMod modifiers); |
533 | void ButtonMoveWithModifiers(Point pt, unsigned int curTime, Scintilla::KeyMod modifiers); |
534 | void ButtonUpWithModifiers(Point pt, unsigned int curTime, Scintilla::KeyMod modifiers); |
535 | |
536 | bool Idle(); |
537 | enum class TickReason { caret, scroll, widen, dwell, platform }; |
538 | virtual void TickFor(TickReason reason); |
539 | virtual bool FineTickerRunning(TickReason reason); |
540 | virtual void FineTickerStart(TickReason reason, int millis, int tolerance); |
541 | virtual void FineTickerCancel(TickReason reason); |
542 | virtual bool SetIdle(bool) { return false; } |
543 | virtual void SetMouseCapture(bool on) = 0; |
544 | virtual bool HaveMouseCapture() = 0; |
545 | void SetFocusState(bool focusState); |
546 | virtual void UpdateBaseElements(); |
547 | |
548 | Sci::Position PositionAfterArea(PRectangle rcArea) const; |
549 | void StyleToPositionInView(Sci::Position pos); |
550 | Sci::Position PositionAfterMaxStyling(Sci::Position posMax, bool scrolling) const; |
551 | void StartIdleStyling(bool truncatedLastStyling); |
552 | void StyleAreaBounded(PRectangle rcArea, bool scrolling); |
553 | constexpr bool SynchronousStylingToVisible() const noexcept { |
554 | return (idleStyling == Scintilla::IdleStyling::None) || (idleStyling == Scintilla::IdleStyling::AfterVisible); |
555 | } |
556 | void IdleStyle(); |
557 | virtual void IdleWork(); |
558 | virtual void QueueIdleWork(WorkItems items, Sci::Position upTo=0); |
559 | |
560 | virtual int SupportsFeature(Scintilla::Supports feature); |
561 | virtual bool PaintContains(PRectangle rc); |
562 | bool PaintContainsMargin(); |
563 | void CheckForChangeOutsidePaint(Range r); |
564 | void SetBraceHighlight(Sci::Position pos0, Sci::Position pos1, int matchStyle); |
565 | |
566 | void SetAnnotationHeights(Sci::Line start, Sci::Line end); |
567 | virtual void SetDocPointer(Document *document); |
568 | |
569 | void SetAnnotationVisible(Scintilla::AnnotationVisible visible); |
570 | void SetEOLAnnotationVisible(Scintilla::EOLAnnotationVisible visible); |
571 | |
572 | Sci::Line ExpandLine(Sci::Line line); |
573 | void SetFoldExpanded(Sci::Line lineDoc, bool expanded); |
574 | void FoldLine(Sci::Line line, Scintilla::FoldAction action); |
575 | void FoldExpand(Sci::Line line, Scintilla::FoldAction action, Scintilla::FoldLevel level); |
576 | Sci::Line ContractedFoldNext(Sci::Line lineStart) const; |
577 | void EnsureLineVisible(Sci::Line lineDoc, bool enforcePolicy); |
578 | void FoldChanged(Sci::Line line, Scintilla::FoldLevel levelNow, Scintilla::FoldLevel levelPrev); |
579 | void NeedShown(Sci::Position pos, Sci::Position len); |
580 | void FoldAll(Scintilla::FoldAction action); |
581 | |
582 | Sci::Position GetTag(char *tagValue, int tagNumber); |
583 | Sci::Position ReplaceTarget(bool replacePatterns, const char *text, Sci::Position length=-1); |
584 | |
585 | bool PositionIsHotspot(Sci::Position position) const; |
586 | bool PointIsHotspot(Point pt); |
587 | void SetHotSpotRange(const Point *pt); |
588 | void SetHoverIndicatorPosition(Sci::Position position); |
589 | void SetHoverIndicatorPoint(Point pt); |
590 | |
591 | int CodePage() const noexcept; |
592 | virtual bool ValidCodePage(int /* codePage */) const { return true; } |
593 | virtual std::string UTF8FromEncoded(std::string_view encoded) const = 0; |
594 | virtual std::string EncodedFromUTF8(std::string_view utf8) const = 0; |
595 | |
596 | Sci::Line WrapCount(Sci::Line line); |
597 | void AddStyledText(const char *buffer, Sci::Position appendLength); |
598 | |
599 | virtual Scintilla::sptr_t DefWndProc(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam) = 0; |
600 | bool ValidMargin(Scintilla::uptr_t wParam) const noexcept; |
601 | void StyleSetMessage(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam); |
602 | Scintilla::sptr_t StyleGetMessage(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam); |
603 | void SetSelectionNMessage(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam); |
604 | |
605 | static const char *StringFromEOLMode(Scintilla::EndOfLine eolMode) noexcept; |
606 | |
607 | // Coercion functions for transforming WndProc parameters into pointers |
608 | static void *PtrFromSPtr(Scintilla::sptr_t lParam) noexcept { |
609 | return reinterpret_cast<void *>(lParam); |
610 | } |
611 | static const char *ConstCharPtrFromSPtr(Scintilla::sptr_t lParam) noexcept { |
612 | return static_cast<const char *>(PtrFromSPtr(lParam)); |
613 | } |
614 | static const unsigned char *ConstUCharPtrFromSPtr(Scintilla::sptr_t lParam) noexcept { |
615 | return static_cast<const unsigned char *>(PtrFromSPtr(lParam)); |
616 | } |
617 | static char *CharPtrFromSPtr(Scintilla::sptr_t lParam) noexcept { |
618 | return static_cast<char *>(PtrFromSPtr(lParam)); |
619 | } |
620 | static unsigned char *UCharPtrFromSPtr(Scintilla::sptr_t lParam) noexcept { |
621 | return static_cast<unsigned char *>(PtrFromSPtr(lParam)); |
622 | } |
623 | static void *PtrFromUPtr(Scintilla::uptr_t wParam) noexcept { |
624 | return reinterpret_cast<void *>(wParam); |
625 | } |
626 | static const char *ConstCharPtrFromUPtr(Scintilla::uptr_t wParam) noexcept { |
627 | return static_cast<const char *>(PtrFromUPtr(wParam)); |
628 | } |
629 | |
630 | static constexpr Scintilla::sptr_t SPtrFromUPtr(Scintilla::uptr_t wParam) noexcept { |
631 | return static_cast<Scintilla::sptr_t>(wParam); |
632 | } |
633 | static constexpr Sci::Position PositionFromUPtr(Scintilla::uptr_t wParam) noexcept { |
634 | return SPtrFromUPtr(wParam); |
635 | } |
636 | static constexpr Sci::Line LineFromUPtr(Scintilla::uptr_t wParam) noexcept { |
637 | return SPtrFromUPtr(wParam); |
638 | } |
639 | Point PointFromParameters(Scintilla::uptr_t wParam, Scintilla::sptr_t lParam) const noexcept { |
640 | return Point(static_cast<XYPOSITION>(wParam) - vs.ExternalMarginWidth(), static_cast<XYPOSITION>(lParam)); |
641 | } |
642 | |
643 | static constexpr std::optional<FoldLevel> OptionalFoldLevel(Scintilla::sptr_t lParam) { |
644 | if (lParam >= 0) { |
645 | return static_cast<FoldLevel>(lParam); |
646 | } |
647 | return std::nullopt; |
648 | } |
649 | |
650 | static Scintilla::sptr_t StringResult(Scintilla::sptr_t lParam, const char *val) noexcept; |
651 | static Scintilla::sptr_t BytesResult(Scintilla::sptr_t lParam, const unsigned char *val, size_t len) noexcept; |
652 | |
653 | // Set a variable controlling appearance to a value and invalidates the display |
654 | // if a change was made. Avoids extra text and the possibility of mistyping. |
655 | template <typename T> |
656 | bool SetAppearance(T &variable, T value) { |
657 | // Using ! and == as more types have == defined than !=. |
658 | const bool changed = !(variable == value); |
659 | if (changed) { |
660 | variable = value; |
661 | InvalidateStyleRedraw(); |
662 | } |
663 | return changed; |
664 | } |
665 | |
666 | public: |
667 | ~Editor() override; |
668 | |
669 | // Public so the COM thunks can access it. |
670 | bool IsUnicodeMode() const noexcept; |
671 | // Public so scintilla_send_message can use it. |
672 | virtual Scintilla::sptr_t WndProc(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam); |
673 | // Public so scintilla_set_id can use it. |
674 | int ctrlID; |
675 | // Public so COM methods for drag and drop can set it. |
676 | Scintilla::Status errorStatus; |
677 | friend class AutoSurface; |
678 | }; |
679 | |
680 | /** |
681 | * A smart pointer class to ensure Surfaces are set up and deleted correctly. |
682 | */ |
683 | class AutoSurface { |
684 | private: |
685 | std::unique_ptr<Surface> surf; |
686 | public: |
687 | AutoSurface(const Editor *ed) { |
688 | if (ed->wMain.GetID()) { |
689 | surf = Surface::Allocate(ed->technology); |
690 | surf->Init(ed->wMain.GetID()); |
691 | surf->SetMode(SurfaceMode(ed->CodePage(), ed->BidirectionalR2L())); |
692 | } |
693 | } |
694 | AutoSurface(SurfaceID sid, Editor *ed, std::optional<Scintilla::Technology> technology = {}) { |
695 | if (ed->wMain.GetID()) { |
696 | surf = Surface::Allocate(technology ? *technology : ed->technology); |
697 | surf->Init(sid, ed->wMain.GetID()); |
698 | surf->SetMode(SurfaceMode(ed->CodePage(), ed->BidirectionalR2L())); |
699 | } |
700 | } |
701 | // Deleted so AutoSurface objects can not be copied. |
702 | AutoSurface(const AutoSurface &) = delete; |
703 | AutoSurface(AutoSurface &&) = delete; |
704 | void operator=(const AutoSurface &) = delete; |
705 | void operator=(AutoSurface &&) = delete; |
706 | ~AutoSurface() { |
707 | } |
708 | Surface *operator->() const noexcept { |
709 | return surf.get(); |
710 | } |
711 | operator Surface *() const noexcept { |
712 | return surf.get(); |
713 | } |
714 | }; |
715 | |
716 | } |
717 | |
718 | #endif |
719 | |