| 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 | |