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