1 // Scintilla source code edit control 2 /** @file Editor.h 3 ** Defines the main editor class. 4 **/ 5 // Copyright 1998-2003 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 /** 12 */ 13 class Caret { 14 public: 15 bool active; 16 bool on; 17 int period; 18 19 Caret(); 20 }; 21 22 /** 23 */ 24 class Timer { 25 public: 26 bool ticking; 27 int ticksToWait; 28 enum {tickSize = 100}; 29 TickerID tickerID; 30 31 Timer(); 32 }; 33 34 /** 35 */ 36 class Idler { 37 public: 38 bool state; 39 IdlerID idlerID; 40 41 Idler(); 42 }; 43 44 /** 45 */ 46 class LineLayout { 47 private: 48 friend class LineLayoutCache; 49 int *lineStarts; 50 int lenLineStarts; 51 /// Drawing is only performed for @a maxLineLength characters on each line. 52 int lineNumber; 53 bool inCache; 54 public: 55 enum { wrapWidthInfinite = 0x7ffffff }; 56 int maxLineLength; 57 int numCharsInLine; 58 enum validLevel { llInvalid, llCheckTextAndStyle, llPositions, llLines } validity; 59 int xHighlightGuide; 60 bool highlightColumn; 61 int selStart; 62 int selEnd; 63 bool containsCaret; 64 int edgeColumn; 65 char *chars; 66 unsigned char *styles; 67 int styleBitsSet; 68 char *indicators; 69 int *positions; 70 char bracePreviousStyles[2]; 71 72 // Hotspot support 73 int hsStart; 74 int hsEnd; 75 76 // Wrapped line support 77 int widthLine; 78 int lines; 79 80 LineLayout(int maxLineLength_); 81 virtual ~LineLayout(); 82 void Resize(int maxLineLength_); 83 void Free(); 84 void Invalidate(validLevel validity_); LineStart(int line)85 int LineStart(int line) { 86 if (line <= 0) { 87 return 0; 88 } else if ((line >= lines) || !lineStarts) { 89 return numCharsInLine; 90 } else { 91 return lineStarts[line]; 92 } 93 } 94 void SetLineStart(int line, int start); 95 void SetBracesHighlight(Range rangeLine, Position braces[], 96 char bracesMatchStyle, int xHighlight); 97 void RestoreBracesHighlight(Range rangeLine, Position braces[]); 98 }; 99 100 /** 101 */ 102 class LineLayoutCache { 103 int level; 104 int length; 105 int size; 106 LineLayout **cache; 107 bool allInvalidated; 108 int styleClock; 109 int useCount; 110 void Allocate(int length_); 111 void AllocateForLevel(int linesOnScreen, int linesInDoc); 112 public: 113 LineLayoutCache(); 114 virtual ~LineLayoutCache(); 115 void Deallocate(); 116 enum { 117 llcNone=SC_CACHE_NONE, 118 llcCaret=SC_CACHE_CARET, 119 llcPage=SC_CACHE_PAGE, 120 llcDocument=SC_CACHE_DOCUMENT 121 }; 122 void Invalidate(LineLayout::validLevel validity_); 123 void SetLevel(int level_); GetLevel()124 int GetLevel() { return level; } 125 LineLayout *Retrieve(int lineNumber, int lineCaret, int maxChars, int styleClock_, 126 int linesOnScreen, int linesInDoc); 127 void Dispose(LineLayout *ll); 128 }; 129 130 /** 131 * Hold a piece of text selected for copying or dragging. 132 * The text is expected to hold a terminating '\0' and this is counted in len. 133 */ 134 class SelectionText { 135 public: 136 char *s; 137 int len; 138 bool rectangular; 139 int codePage; 140 int characterSet; SelectionText()141 SelectionText() : s(0), len(0), rectangular(false), codePage(0), characterSet(0) {} ~SelectionText()142 ~SelectionText() { 143 Free(); 144 } Free()145 void Free() { 146 Set(0, 0, 0, 0, false); 147 } Set(char * s_,int len_,int codePage_,int characterSet_,bool rectangular_)148 void Set(char *s_, int len_, int codePage_, int characterSet_, bool rectangular_) { 149 delete []s; 150 s = s_; 151 if (s) 152 len = len_; 153 else 154 len = 0; 155 codePage = codePage_; 156 characterSet = characterSet_; 157 rectangular = rectangular_; 158 } Copy(const char * s_,int len_,int codePage_,int characterSet_,bool rectangular_)159 void Copy(const char *s_, int len_, int codePage_, int characterSet_, bool rectangular_) { 160 delete []s; 161 s = new char[len_]; 162 if (s) { 163 len = len_; 164 for (int i = 0; i < len_; i++) { 165 s[i] = s_[i]; 166 } 167 } else { 168 len = 0; 169 } 170 codePage = codePage_; 171 characterSet = characterSet_; 172 rectangular = rectangular_; 173 } Copy(const SelectionText & other)174 void Copy(const SelectionText &other) { 175 Copy(other.s, other.len, other.codePage, other.characterSet, other.rectangular); 176 } 177 }; 178 179 /** 180 */ 181 class Editor : public DocWatcher { 182 // Private so Editor objects can not be copied Editor(const Editor &)183 Editor(const Editor &) : DocWatcher() {} 184 Editor &operator=(const Editor &) { return *this; } 185 186 protected: // ScintillaBase subclass needs access to much of Editor 187 188 /** On GTK+, Scintilla is a container widget holding two scroll bars 189 * whereas on Windows there is just one window with both scroll bars turned on. */ 190 Window wMain; ///< The Scintilla parent window 191 192 /** Style resources may be expensive to allocate so are cached between uses. 193 * When a style attribute is changed, this cache is flushed. */ 194 bool stylesValid; 195 ViewStyle vs; 196 Palette palette; 197 198 int printMagnification; 199 int printColourMode; 200 int printWrapState; 201 int cursorMode; 202 int controlCharSymbol; 203 204 bool hasFocus; 205 bool hideSelection; 206 bool inOverstrike; 207 int errorStatus; 208 bool mouseDownCaptures; 209 210 /** In bufferedDraw mode, graphics operations are drawn to a pixmap and then copied to 211 * the screen. This avoids flashing but is about 30% slower. */ 212 bool bufferedDraw; 213 /** In twoPhaseDraw mode, drawing is performed in two phases, first the background 214 * and then the foreground. This avoids chopping off characters that overlap the next run. */ 215 bool twoPhaseDraw; 216 217 int xOffset; ///< Horizontal scrolled amount in pixels 218 int xCaretMargin; ///< Ensure this many pixels visible on both sides of caret 219 bool horizontalScrollBarVisible; 220 int scrollWidth; 221 bool verticalScrollBarVisible; 222 bool endAtLastLine; 223 bool caretSticky; 224 225 Surface *pixmapLine; 226 Surface *pixmapSelMargin; 227 Surface *pixmapSelPattern; 228 Surface *pixmapIndentGuide; 229 Surface *pixmapIndentGuideHighlight; 230 231 LineLayoutCache llc; 232 233 KeyMap kmap; 234 235 Caret caret; 236 Timer timer; 237 Timer autoScrollTimer; 238 enum { autoScrollDelay = 200 }; 239 240 Idler idler; 241 242 Point lastClick; 243 unsigned int lastClickTime; 244 int dwellDelay; 245 int ticksToDwell; 246 bool dwelling; 247 enum { selChar, selWord, selLine } selectionType; 248 Point ptMouseLast; 249 bool inDragDrop; 250 bool dropWentOutside; 251 int posDrag; 252 int posDrop; 253 int lastXChosen; 254 int lineAnchor; 255 int originalAnchorPos; 256 int currentPos; 257 int anchor; 258 int targetStart; 259 int targetEnd; 260 int searchFlags; 261 int topLine; 262 int posTopLine; 263 int lengthForEncode; 264 265 bool needUpdateUI; 266 Position braces[2]; 267 int bracesMatchStyle; 268 int highlightGuideColumn; 269 270 int theEdge; 271 272 enum { notPainting, painting, paintAbandoned } paintState; 273 PRectangle rcPaint; 274 bool paintingAllText; 275 276 int modEventMask; 277 278 SelectionText drag; 279 enum selTypes { noSel, selStream, selRectangle, selLines }; 280 selTypes selType; 281 bool moveExtendsSelection; 282 int xStartSelect; ///< x position of start of rectangular selection 283 int xEndSelect; ///< x position of end of rectangular selection 284 bool primarySelection; 285 286 int caretXPolicy; 287 int caretXSlop; ///< Ensure this many pixels visible on both sides of caret 288 289 int caretYPolicy; 290 int caretYSlop; ///< Ensure this many lines visible on both sides of caret 291 292 int visiblePolicy; 293 int visibleSlop; 294 295 int searchAnchor; 296 297 bool recordingMacro; 298 299 int foldFlags; 300 ContractionState cs; 301 302 // Hotspot support 303 int hsStart; 304 int hsEnd; 305 306 // Wrapping support 307 enum { eWrapNone, eWrapWord, eWrapChar } wrapState; 308 enum { wrapLineLarge = 0x7ffffff }; 309 int wrapWidth; 310 int wrapStart; 311 int wrapEnd; 312 int wrapVisualFlags; 313 int wrapVisualFlagsLocation; 314 int wrapVisualStartIndent; 315 int actualWrapVisualStartIndent; 316 317 bool convertPastes; 318 319 Document *pdoc; 320 321 Editor(); 322 virtual ~Editor(); 323 virtual void Initialise() = 0; 324 virtual void Finalise(); 325 326 void InvalidateStyleData(); 327 void InvalidateStyleRedraw(); 328 virtual void RefreshColourPalette(Palette &pal, bool want); 329 void RefreshStyleData(); 330 void DropGraphics(); 331 332 virtual PRectangle GetClientRectangle(); 333 PRectangle GetTextRectangle(); 334 335 int LinesOnScreen(); 336 int LinesToScroll(); 337 int MaxScrollPos(); 338 Point LocationFromPosition(int pos); 339 int XFromPosition(int pos); 340 int PositionFromLocation(Point pt); 341 int PositionFromLocationClose(Point pt); 342 int PositionFromLineX(int line, int x); 343 int LineFromLocation(Point pt); 344 void SetTopLine(int topLineNew); 345 346 bool AbandonPaint(); 347 void RedrawRect(PRectangle rc); 348 void Redraw(); 349 void RedrawSelMargin(int line=-1); 350 PRectangle RectangleFromRange(int start, int end); 351 void InvalidateRange(int start, int end); 352 353 int CurrentPosition(); 354 bool SelectionEmpty(); 355 int SelectionStart(); 356 int SelectionEnd(); 357 void SetRectangularRange(); 358 void InvalidateSelection(int currentPos_, int anchor_); 359 void SetSelection(int currentPos_, int anchor_); 360 void SetSelection(int currentPos_); 361 void SetEmptySelection(int currentPos_); 362 bool RangeContainsProtected(int start, int end) const; 363 bool SelectionContainsProtected(); 364 int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true); 365 int MovePositionTo(int newPos, selTypes sel=noSel, bool ensureVisible=true); 366 int MovePositionSoVisible(int pos, int moveDir); 367 void SetLastXChosen(); 368 369 void ScrollTo(int line, bool moveThumb=true); 370 virtual void ScrollText(int linesToMove); 371 void HorizontalScrollTo(int xPos); 372 void MoveCaretInsideView(bool ensureVisible=true); 373 int DisplayFromPosition(int pos); 374 void EnsureCaretVisible(bool useMargin=true, bool vert=true, bool horiz=true); 375 void ShowCaretAtCurrentPosition(); 376 void DropCaret(); 377 void InvalidateCaret(); 378 virtual void UpdateSystemCaret(); 379 380 void NeedWrapping(int docLineStart = 0, int docLineEnd = wrapLineLarge); 381 bool WrapLines(bool fullWrap, int priorityWrapLineStart); 382 void LinesJoin(); 383 void LinesSplit(int pixelWidth); 384 385 int SubstituteMarkerIfEmpty(int markerCheck, int markerDefault); 386 void PaintSelMargin(Surface *surface, PRectangle &rc); 387 LineLayout *RetrieveLineLayout(int lineNumber); 388 void LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll, 389 int width=LineLayout::wrapWidthInfinite); 390 ColourAllocated SelectionBackground(ViewStyle &vsDraw); 391 ColourAllocated TextBackground(ViewStyle &vsDraw, bool overrideBackground, ColourAllocated background, bool inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll); 392 void DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight); 393 void DrawWrapMarker(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourAllocated wrapColour); 394 void DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll, 395 int line, int lineEnd, int xStart, int subLine, int subLineStart, 396 bool overrideBackground, ColourAllocated background, 397 bool drawWrapMark, ColourAllocated wrapColour); 398 void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart, 399 PRectangle rcLine, LineLayout *ll, int subLine=0); 400 void RefreshPixMaps(Surface *surfaceWindow); 401 void Paint(Surface *surfaceWindow, PRectangle rcArea); 402 long FormatRange(bool draw, RangeToFormat *pfr); 403 int TextWidth(int style, const char *text); 404 405 virtual void SetVerticalScrollPos() = 0; 406 virtual void SetHorizontalScrollPos() = 0; 407 virtual bool ModifyScrollBars(int nMax, int nPage) = 0; 408 virtual void ReconfigureScrollBars(); 409 void SetScrollBars(); 410 void ChangeSize(); 411 412 void AddChar(char ch); 413 virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false); 414 void ClearSelection(); 415 void ClearAll(); 416 void ClearDocumentStyle(); 417 void Cut(); 418 void PasteRectangular(int pos, const char *ptr, int len); 419 virtual void Copy() = 0; 420 virtual bool CanPaste(); 421 virtual void Paste() = 0; 422 void Clear(); 423 void SelectAll(); 424 void Undo(); 425 void Redo(); 426 void DelChar(); 427 void DelCharBack(bool allowLineStartDeletion); 428 virtual void ClaimSelection() = 0; 429 430 virtual void NotifyChange() = 0; 431 virtual void NotifyFocus(bool focus); GetCtrlID()432 virtual int GetCtrlID() { return ctrlID; } 433 virtual void NotifyParent(SCNotification scn) = 0; 434 virtual void NotifyStyleToNeeded(int endStyleNeeded); 435 void NotifyChar(int ch); 436 void NotifyMove(int position); 437 void NotifySavePoint(bool isSavePoint); 438 void NotifyModifyAttempt(); 439 virtual void NotifyDoubleClick(Point pt, bool shift); 440 void NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt); 441 void NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, bool alt); 442 void NotifyUpdateUI(); 443 void NotifyPainted(); 444 bool NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt); 445 void NotifyNeedShown(int pos, int len); 446 void NotifyDwelling(Point pt, bool state); 447 void NotifyZoom(); 448 449 void NotifyModifyAttempt(Document *document, void *userData); 450 void NotifySavePoint(Document *document, void *userData, bool atSavePoint); 451 void CheckModificationForWrap(DocModification mh); 452 void NotifyModified(Document *document, DocModification mh, void *userData); 453 void NotifyDeleted(Document *document, void *userData); 454 void NotifyStyleNeeded(Document *doc, void *userData, int endPos); 455 void NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam); 456 457 void PageMove(int direction, selTypes sel=noSel, bool stuttered = false); 458 void ChangeCaseOfSelection(bool makeUpperCase); 459 void LineTranspose(); 460 void Duplicate(bool forLine); 461 virtual void CancelModes(); 462 void NewLine(); 463 void CursorUpOrDown(int direction, selTypes sel=noSel); 464 void ParaUpOrDown(int direction, selTypes sel=noSel); 465 int StartEndDisplayLine(int pos, bool start); 466 virtual int KeyCommand(unsigned int iMessage); 467 virtual int KeyDefault(int /* key */, int /*modifiers*/); 468 int KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed=0); 469 470 int GetWhitespaceVisible(); 471 void SetWhitespaceVisible(int view); 472 473 void Indent(bool forwards); 474 475 long FindText(uptr_t wParam, sptr_t lParam); 476 void SearchAnchor(); 477 long SearchText(unsigned int iMessage, uptr_t wParam, sptr_t lParam); 478 long SearchInTarget(const char *text, int length); 479 void GoToLine(int lineNo); 480 481 virtual void CopyToClipboard(const SelectionText &selectedText) = 0; 482 char *CopyRange(int start, int end); 483 void CopySelectionFromRange(SelectionText *ss, int start, int end); 484 void CopySelectionRange(SelectionText *ss); 485 void CopyRangeToClipboard(int start, int end); 486 void CopyText(int length, const char *text); 487 void SetDragPosition(int newPos); 488 virtual void DisplayCursor(Window::Cursor c); 489 virtual void StartDrag(); 490 void DropAt(int position, const char *value, bool moving, bool rectangular); 491 /** PositionInSelection returns 0 if position in selection, -1 if position before selection, and 1 if after. 492 * Before means either before any line of selection or before selection on its line, with a similar meaning to after. */ 493 int PositionInSelection(int pos); 494 bool PointInSelection(Point pt); 495 bool PointInSelMargin(Point pt); 496 void LineSelection(int lineCurrent_, int lineAnchor_); 497 void DwellEnd(bool mouseMoved); 498 virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt); 499 void ButtonMove(Point pt); 500 void ButtonUp(Point pt, unsigned int curTime, bool ctrl); 501 502 void Tick(); 503 bool Idle(); 504 virtual void SetTicking(bool on) = 0; SetIdle(bool)505 virtual bool SetIdle(bool) { return false; } 506 virtual void SetMouseCapture(bool on) = 0; 507 virtual bool HaveMouseCapture() = 0; 508 void SetFocusState(bool focusState); 509 510 virtual bool PaintContains(PRectangle rc); 511 bool PaintContainsMargin(); 512 void CheckForChangeOutsidePaint(Range r); 513 void SetBraceHighlight(Position pos0, Position pos1, int matchStyle); 514 515 void SetDocPointer(Document *document); 516 517 void Expand(int &line, bool doExpand); 518 void ToggleContraction(int line); 519 void EnsureLineVisible(int lineDoc, bool enforcePolicy); 520 int ReplaceTarget(bool replacePatterns, const char *text, int length=-1); 521 522 bool PositionIsHotspot(int position); 523 bool PointIsHotspot(Point pt); 524 void SetHotSpotRange(Point *pt); 525 void GetHotSpotRange(int& hsStart, int& hsEnd); 526 527 int CodePage() const; ValidCodePage(int)528 virtual bool ValidCodePage(int /* codePage */) const { return true; } 529 int WrapCount(int line); 530 531 virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) = 0; 532 533 public: 534 // Public so the COM thunks can access it. 535 bool IsUnicodeMode() const; 536 // Public so scintilla_send_message can use it. 537 virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); 538 // Public so scintilla_set_id can use it. 539 int ctrlID; 540 friend class AutoSurface; 541 friend class SelectionLineIterator; 542 }; 543 544 /** 545 * A smart pointer class to ensure Surfaces are set up and deleted correctly. 546 */ 547 class AutoSurface { 548 private: 549 Surface *surf; 550 public: AutoSurface(Editor * ed)551 AutoSurface(Editor *ed) : surf(0) { 552 if (ed->wMain.GetID()) { 553 surf = Surface::Allocate(); 554 if (surf) { 555 surf->Init(ed->wMain.GetID()); 556 surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage()); 557 surf->SetDBCSMode(ed->CodePage()); 558 } 559 } 560 } AutoSurface(SurfaceID sid,Editor * ed)561 AutoSurface(SurfaceID sid, Editor *ed) : surf(0) { 562 if (ed->wMain.GetID()) { 563 surf = Surface::Allocate(); 564 if (surf) { 565 surf->Init(sid, ed->wMain.GetID()); 566 surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage()); 567 surf->SetDBCSMode(ed->CodePage()); 568 } 569 } 570 } ~AutoSurface()571 ~AutoSurface() { 572 delete surf; 573 } 574 Surface *operator->() const { 575 return surf; 576 } 577 operator Surface *() const { 578 return surf; 579 } 580 }; 581 582 #endif 583