// Scintilla source code edit control /** @file Editor.h ** Defines the main editor class. **/ // Copyright 1998-2011 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #ifndef EDITOR_H #define EDITOR_H #ifdef SCI_NAMESPACE namespace Scintilla { #endif /** */ class Caret { public: bool active; bool on; int period; Caret(); }; /** */ class Timer { public: bool ticking; int ticksToWait; enum {tickSize = 100}; TickerID tickerID; Timer(); }; /** */ class Idler { public: bool state; IdlerID idlerID; Idler(); }; /** * When platform has a way to generate an event before painting, * accumulate needed styling range and other work items in * WorkNeeded to avoid unnecessary work inside paint handler */ class WorkNeeded { public: enum workItems { workNone=0, workStyle=1, workUpdateUI=2 }; bool active; enum workItems items; Position upTo; WorkNeeded() : active(false), items(workNone), upTo(0) {} void Reset() { active = false; items = workNone; upTo = 0; } void Need(workItems items_, Position pos) { if ((items_ & workStyle) && (upTo < pos)) upTo = pos; items = static_cast(items | items_); } }; /** * Hold a piece of text selected for copying or dragging, along with encoding and selection format information. */ class SelectionText { std::string s; public: bool rectangular; bool lineCopy; int codePage; int characterSet; SelectionText() : rectangular(false), lineCopy(false), codePage(0), characterSet(0) {} ~SelectionText() { } void Clear() { s.clear(); rectangular = false; lineCopy = false; codePage = 0; characterSet = 0; } void Copy(const std::string &s_, int codePage_, int characterSet_, bool rectangular_, bool lineCopy_) { s = s_; codePage = codePage_; characterSet = characterSet_; rectangular = rectangular_; lineCopy = lineCopy_; FixSelectionForClipboard(); } void Copy(const SelectionText &other) { Copy(other.s, other.codePage, other.characterSet, other.rectangular, other.lineCopy); } const char *Data() const { return s.c_str(); } size_t Length() const { return s.length(); } size_t LengthWithTerminator() const { return s.length() + 1; } bool Empty() const { return s.empty(); } private: void FixSelectionForClipboard() { // To avoid truncating the contents of the clipboard when pasted where the // clipboard contains NUL characters, replace NUL characters by spaces. std::replace(s.begin(), s.end(), '\0', ' '); } }; struct WrapPending { // The range of lines that need to be wrapped enum { lineLarge = 0x7ffffff }; int start; // When there are wraps pending, will be in document range int end; // May be lineLarge to indicate all of document after start WrapPending() { start = lineLarge; end = lineLarge; } void Reset() { start = lineLarge; end = lineLarge; } void Wrapped(int line) { if (start == line) start++; } bool NeedsWrap() const { return start < end; } bool AddRange(int lineStart, int lineEnd) { const bool neededWrap = NeedsWrap(); bool changed = false; if (start > lineStart) { start = lineStart; changed = true; } if ((end < lineEnd) || !neededWrap) { end = lineEnd; changed = true; } return changed; } }; struct PrintParameters { int magnification; int colourMode; WrapMode wrapState; PrintParameters(); }; /** */ class Editor : public DocWatcher { // Private so Editor objects can not be copied Editor(const Editor &); Editor &operator=(const Editor &); protected: // ScintillaBase subclass needs access to much of Editor /** On GTK+, Scintilla is a container widget holding two scroll bars * whereas on Windows there is just one window with both scroll bars turned on. */ Window wMain; ///< The Scintilla parent window Window wMargin; ///< May be separate when using a scroll view for wMain /** Style resources may be expensive to allocate so are cached between uses. * When a style attribute is changed, this cache is flushed. */ bool stylesValid; ViewStyle vs; int technology; Point sizeRGBAImage; float scaleRGBAImage; PrintParameters printParameters; int cursorMode; // Highlight current folding block HighlightDelimiter highlightDelimiter; bool hasFocus; bool hideSelection; bool inOverstrike; bool drawOverstrikeCaret; bool mouseDownCaptures; /** In bufferedDraw mode, graphics operations are drawn to a pixmap and then copied to * the screen. This avoids flashing but is about 30% slower. */ bool bufferedDraw; /** In twoPhaseDraw mode, drawing is performed in two phases, first the background * and then the foreground. This avoids chopping off characters that overlap the next run. */ bool twoPhaseDraw; int xOffset; ///< Horizontal scrolled amount in pixels int xCaretMargin; ///< Ensure this many pixels visible on both sides of caret bool horizontalScrollBarVisible; int scrollWidth; bool trackLineWidth; int lineWidthMaxSeen; bool verticalScrollBarVisible; bool endAtLastLine; int caretSticky; int marginOptions; bool mouseSelectionRectangularSwitch; bool multipleSelection; bool additionalSelectionTyping; int multiPasteMode; bool additionalCaretsBlink; bool additionalCaretsVisible; int virtualSpaceOptions; Surface *pixmapLine; Surface *pixmapSelMargin; Surface *pixmapSelPattern; Surface *pixmapSelPatternOffset1; Surface *pixmapIndentGuide; Surface *pixmapIndentGuideHighlight; LineLayoutCache llc; PositionCache posCache; SpecialRepresentations reprs; KeyMap kmap; Caret caret; Timer timer; Timer autoScrollTimer; enum { autoScrollDelay = 200 }; Idler idler; Point lastClick; unsigned int lastClickTime; int dwellDelay; int ticksToDwell; bool dwelling; enum { selChar, selWord, selSubLine, selWholeLine } selectionType; Point ptMouseLast; enum { ddNone, ddInitial, ddDragging } inDragDrop; bool dropWentOutside; SelectionPosition posDrag; SelectionPosition posDrop; int hotSpotClickPos; int lastXChosen; int lineAnchorPos; int originalAnchorPos; int wordSelectAnchorStartPos; int wordSelectAnchorEndPos; int wordSelectInitialCaretPos; int targetStart; int targetEnd; int searchFlags; int topLine; int posTopLine; int lengthForEncode; int needUpdateUI; Position braces[2]; int bracesMatchStyle; int highlightGuideColumn; enum { notPainting, painting, paintAbandoned } paintState; bool paintAbandonedByStyling; PRectangle rcPaint; bool paintingAllText; bool willRedrawAll; WorkNeeded workNeeded; int modEventMask; SelectionText drag; Selection sel; bool primarySelection; int caretXPolicy; int caretXSlop; ///< Ensure this many pixels visible on both sides of caret int caretYPolicy; int caretYSlop; ///< Ensure this many lines visible on both sides of caret int visiblePolicy; int visibleSlop; int searchAnchor; bool recordingMacro; int foldFlags; int foldAutomatic; ContractionState cs; // Hotspot support int hsStart; int hsEnd; // Wrapping support int wrapWidth; WrapPending wrapPending; bool convertPastes; Document *pdoc; Editor(); virtual ~Editor(); virtual void Initialise() = 0; virtual void Finalise(); void InvalidateStyleData(); void InvalidateStyleRedraw(); void RefreshStyleData(); void SetRepresentations(); void DropGraphics(bool freeObjects); void AllocateGraphics(); // The top left visible point in main window coordinates. Will be 0,0 except for // scroll views where it will be equivalent to the current scroll position. virtual Point GetVisibleOriginInMain(); Point DocumentPointFromView(Point ptView); // Convert a point from view space to document int TopLineOfMain() const; // Return the line at Main's y coordinate 0 virtual PRectangle GetClientRectangle(); PRectangle GetTextRectangle(); int LinesOnScreen(); int LinesToScroll(); int MaxScrollPos(); SelectionPosition ClampPositionIntoDocument(SelectionPosition sp) const; Point LocationFromPosition(SelectionPosition pos); Point LocationFromPosition(int pos); int XFromPosition(int pos); int XFromPosition(SelectionPosition sp); SelectionPosition SPositionFromLocation(Point pt, bool canReturnInvalid=false, bool charPosition=false, bool virtualSpace=true); int PositionFromLocation(Point pt, bool canReturnInvalid=false, bool charPosition=false); SelectionPosition SPositionFromLineX(int lineDoc, int x); int PositionFromLineX(int line, int x); int LineFromLocation(Point pt) const; void SetTopLine(int topLineNew); bool AbandonPaint(); void RedrawRect(PRectangle rc); void Redraw(); void RedrawSelMargin(int line=-1, bool allAfter=false); PRectangle RectangleFromRange(int start, int end); void InvalidateRange(int start, int end); bool UserVirtualSpace() const { return ((virtualSpaceOptions & SCVS_USERACCESSIBLE) != 0); } int CurrentPosition() const; bool SelectionEmpty() const; SelectionPosition SelectionStart(); SelectionPosition SelectionEnd(); void SetRectangularRange(); void ThinRectangularRange(); void InvalidateSelection(SelectionRange newMain, bool invalidateWholeSelection=false); void SetSelection(SelectionPosition currentPos_, SelectionPosition anchor_); void SetSelection(int currentPos_, int anchor_); void SetSelection(SelectionPosition currentPos_); void SetSelection(int currentPos_); void SetEmptySelection(SelectionPosition currentPos_); void SetEmptySelection(int currentPos_); bool RangeContainsProtected(int start, int end) const; bool SelectionContainsProtected(); int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true) const; SelectionPosition MovePositionOutsideChar(SelectionPosition pos, int moveDir, bool checkLineEnd=true) const; int MovePositionTo(SelectionPosition newPos, Selection::selTypes sel=Selection::noSel, bool ensureVisible=true); int MovePositionTo(int newPos, Selection::selTypes sel=Selection::noSel, bool ensureVisible=true); SelectionPosition MovePositionSoVisible(SelectionPosition pos, int moveDir); SelectionPosition MovePositionSoVisible(int pos, int moveDir); Point PointMainCaret(); void SetLastXChosen(); void ScrollTo(int line, bool moveThumb=true); virtual void ScrollText(int linesToMove); void HorizontalScrollTo(int xPos); void VerticalCentreCaret(); void MoveSelectedLines(int lineDelta); void MoveSelectedLinesUp(); void MoveSelectedLinesDown(); void MoveCaretInsideView(bool ensureVisible=true); int DisplayFromPosition(int pos); struct XYScrollPosition { int xOffset; int topLine; XYScrollPosition(int xOffset_, int topLine_) : xOffset(xOffset_), topLine(topLine_) {} bool operator==(const XYScrollPosition &other) const { return (xOffset == other.xOffset) && (topLine == other.topLine); } }; enum XYScrollOptions { xysUseMargin=0x1, xysVertical=0x2, xysHorizontal=0x4, xysDefault=xysUseMargin|xysVertical|xysHorizontal}; XYScrollPosition XYScrollToMakeVisible(const SelectionRange range, const XYScrollOptions options); void SetXYScroll(XYScrollPosition newXY); void EnsureCaretVisible(bool useMargin=true, bool vert=true, bool horiz=true); void ScrollRange(SelectionRange range); void ShowCaretAtCurrentPosition(); void DropCaret(); void InvalidateCaret(); virtual void UpdateSystemCaret(); bool Wrapping() const; void NeedWrapping(int docLineStart=0, int docLineEnd=WrapPending::lineLarge); bool WrapOneLine(Surface *surface, int lineToWrap); enum wrapScope {wsAll, wsVisible, wsIdle}; bool WrapLines(enum wrapScope ws); void LinesJoin(); void LinesSplit(int pixelWidth); int SubstituteMarkerIfEmpty(int markerCheck, int markerDefault) const; void PaintSelMargin(Surface *surface, PRectangle &rc); LineLayout *RetrieveLineLayout(int lineNumber); void LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll, int width=LineLayout::wrapWidthInfinite); ColourDesired SelectionBackground(ViewStyle &vsDraw, bool main) const; ColourDesired TextBackground(ViewStyle &vsDraw, bool overrideBackground, ColourDesired background, int inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll) const; void DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight); void DrawWrapMarker(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourDesired wrapColour); void DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll, int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart, bool overrideBackground, ColourDesired background, bool drawWrapMark, ColourDesired wrapColour); void DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, ViewStyle &vsDraw, int xStart, PRectangle rcLine, LineLayout *ll, int subLine); void DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int xStart, PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under); void DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart, PRectangle rcLine, LineLayout *ll, int subLine); void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart, PRectangle rcLine, LineLayout *ll, int subLine); void DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine, int xStart, int offset, int posCaret, PRectangle rcCaret, ColourDesired caretColour); void DrawCarets(Surface *surface, ViewStyle &vsDraw, int line, int xStart, PRectangle rcLine, LineLayout *ll, int subLine); void RefreshPixMaps(Surface *surfaceWindow); void Paint(Surface *surfaceWindow, PRectangle rcArea); long FormatRange(bool draw, Sci_RangeToFormat *pfr); int TextWidth(int style, const char *text); virtual void SetVerticalScrollPos() = 0; virtual void SetHorizontalScrollPos() = 0; virtual bool ModifyScrollBars(int nMax, int nPage) = 0; virtual void ReconfigureScrollBars(); void SetScrollBars(); void ChangeSize(); void FilterSelections(); int InsertSpace(int position, unsigned int spaces); void AddChar(char ch); virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false); void InsertPaste(SelectionPosition selStart, const char *text, int len); void ClearSelection(bool retainMultipleSelections=false); void ClearAll(); void ClearDocumentStyle(); void Cut(); void PasteRectangular(SelectionPosition pos, const char *ptr, int len); virtual void Copy() = 0; virtual void CopyAllowLine(); virtual bool CanPaste(); virtual void Paste() = 0; void Clear(); void SelectAll(); void Undo(); void Redo(); void DelChar(); void DelCharBack(bool allowLineStartDeletion); virtual void ClaimSelection() = 0; virtual void NotifyChange() = 0; virtual void NotifyFocus(bool focus); virtual void SetCtrlID(int identifier); virtual int GetCtrlID() { return ctrlID; } virtual void NotifyParent(SCNotification scn) = 0; virtual void NotifyStyleToNeeded(int endStyleNeeded); void NotifyChar(int ch); void NotifySavePoint(bool isSavePoint); void NotifyModifyAttempt(); virtual void NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt); void NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt); void NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, bool alt); void NotifyHotSpotReleaseClick(int position, bool shift, bool ctrl, bool alt); bool NotifyUpdateUI(); void NotifyPainted(); void NotifyIndicatorClick(bool click, int position, bool shift, bool ctrl, bool alt); bool NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt); void NotifyNeedShown(int pos, int len); void NotifyDwelling(Point pt, bool state); void NotifyZoom(); void NotifyModifyAttempt(Document *document, void *userData); void NotifySavePoint(Document *document, void *userData, bool atSavePoint); void CheckModificationForWrap(DocModification mh); void NotifyModified(Document *document, DocModification mh, void *userData); void NotifyDeleted(Document *document, void *userData); void NotifyStyleNeeded(Document *doc, void *userData, int endPos); void NotifyLexerChanged(Document *doc, void *userData); void NotifyErrorOccurred(Document *doc, void *userData, int status); void NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam); void ContainerNeedsUpdate(int flags); void PageMove(int direction, Selection::selTypes sel=Selection::noSel, bool stuttered = false); enum { cmSame, cmUpper, cmLower }; virtual std::string CaseMapString(const std::string &s, int caseMapping); void ChangeCaseOfSelection(int caseMapping); void LineTranspose(); void Duplicate(bool forLine); virtual void CancelModes(); void NewLine(); void CursorUpOrDown(int direction, Selection::selTypes sel=Selection::noSel); void ParaUpOrDown(int direction, Selection::selTypes sel=Selection::noSel); int StartEndDisplayLine(int pos, bool start); virtual int KeyCommand(unsigned int iMessage); virtual int KeyDefault(int /* key */, int /*modifiers*/); int KeyDownWithModifiers(int key, int modifiers, bool *consumed); int KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed=0); void Indent(bool forwards); virtual CaseFolder *CaseFolderForEncoding(); long FindText(uptr_t wParam, sptr_t lParam); void SearchAnchor(); long SearchText(unsigned int iMessage, uptr_t wParam, sptr_t lParam); long SearchInTarget(const char *text, int length); void GoToLine(int lineNo); virtual void CopyToClipboard(const SelectionText &selectedText) = 0; std::string RangeText(int start, int end) const; void CopySelectionRange(SelectionText *ss, bool allowLineCopy=false); void CopyRangeToClipboard(int start, int end); void CopyText(int length, const char *text); void SetDragPosition(SelectionPosition newPos); virtual void DisplayCursor(Window::Cursor c); virtual bool DragThreshold(Point ptStart, Point ptNow); virtual void StartDrag(); void DropAt(SelectionPosition position, const char *value, size_t lengthValue, bool moving, bool rectangular); void DropAt(SelectionPosition position, const char *value, bool moving, bool rectangular); /** PositionInSelection returns true if position in selection. */ bool PositionInSelection(int pos); bool PointInSelection(Point pt); bool PointInSelMargin(Point pt); Window::Cursor GetMarginCursor(Point pt) const; void TrimAndSetSelection(int currentPos_, int anchor_); void LineSelection(int lineCurrentPos_, int lineAnchorPos_, bool wholeLine); void WordSelection(int pos); void DwellEnd(bool mouseMoved); void MouseLeave(); virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt); void ButtonMoveWithModifiers(Point pt, int modifiers); void ButtonMove(Point pt); void ButtonUp(Point pt, unsigned int curTime, bool ctrl); void Tick(); bool Idle(); virtual void SetTicking(bool on) = 0; virtual bool SetIdle(bool) { return false; } virtual void SetMouseCapture(bool on) = 0; virtual bool HaveMouseCapture() = 0; void SetFocusState(bool focusState); int PositionAfterArea(PRectangle rcArea) const; void StyleToPositionInView(Position pos); virtual void IdleWork(); virtual void QueueIdleWork(WorkNeeded::workItems items, int upTo=0); virtual bool PaintContains(PRectangle rc); bool PaintContainsMargin(); void CheckForChangeOutsidePaint(Range r); void SetBraceHighlight(Position pos0, Position pos1, int matchStyle); void SetAnnotationHeights(int start, int end); virtual void SetDocPointer(Document *document); void SetAnnotationVisible(int visible); int ExpandLine(int line); void SetFoldExpanded(int lineDoc, bool expanded); void FoldLine(int line, int action); void FoldExpand(int line, int action, int level); int ContractedFoldNext(int lineStart) const; void EnsureLineVisible(int lineDoc, bool enforcePolicy); void FoldChanged(int line, int levelNow, int levelPrev); void NeedShown(int pos, int len); void FoldAll(int action); int GetTag(char *tagValue, int tagNumber); int ReplaceTarget(bool replacePatterns, const char *text, int length=-1); bool PositionIsHotspot(int position) const; bool PointIsHotspot(Point pt); void SetHotSpotRange(Point *pt); void GetHotSpotRange(int &hsStart, int &hsEnd) const; int CodePage() const; virtual bool ValidCodePage(int /* codePage */) const { return true; } int WrapCount(int line); void AddStyledText(char *buffer, int appendLength); virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) = 0; void StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam); sptr_t StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam); static const char *StringFromEOLMode(int eolMode); static sptr_t StringResult(sptr_t lParam, const char *val); public: // Public so the COM thunks can access it. bool IsUnicodeMode() const; // Public so scintilla_send_message can use it. virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); // Public so scintilla_set_id can use it. int ctrlID; // Public so COM methods for drag and drop can set it. int errorStatus; friend class AutoSurface; friend class SelectionLineIterator; }; /** * A smart pointer class to ensure Surfaces are set up and deleted correctly. */ class AutoSurface { private: Surface *surf; public: AutoSurface(Editor *ed, int technology = -1) : surf(0) { if (ed->wMain.GetID()) { surf = Surface::Allocate(technology != -1 ? technology : ed->technology); if (surf) { surf->Init(ed->wMain.GetID()); surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage()); surf->SetDBCSMode(ed->CodePage()); } } } AutoSurface(SurfaceID sid, Editor *ed, int technology = -1) : surf(0) { if (ed->wMain.GetID()) { surf = Surface::Allocate(technology != -1 ? technology : ed->technology); if (surf) { surf->Init(sid, ed->wMain.GetID()); surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage()); surf->SetDBCSMode(ed->CodePage()); } } } ~AutoSurface() { delete surf; } Surface *operator->() const { return surf; } operator Surface *() const { return surf; } }; #ifdef SCI_NAMESPACE } #endif #endif