michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsFrameSelection_h___ michael@0: #define nsFrameSelection_h___ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "mozilla/EventForwards.h" michael@0: #include "mozilla/dom/Selection.h" michael@0: #include "mozilla/TextRange.h" michael@0: #include "nsIFrame.h" michael@0: #include "nsIContent.h" michael@0: #include "nsISelectionController.h" michael@0: #include "nsITableCellLayout.h" michael@0: #include "nsIDOMElement.h" michael@0: #include "nsRange.h" michael@0: michael@0: class nsTableOuterFrame; michael@0: michael@0: // IID for the nsFrameSelection interface michael@0: // 3c6ae2d0-4cf1-44a1-9e9d-2411867f19c6 michael@0: #define NS_FRAME_SELECTION_IID \ michael@0: { 0x3c6ae2d0, 0x4cf1, 0x44a1, \ michael@0: { 0x9e, 0x9d, 0x24, 0x11, 0x86, 0x7f, 0x19, 0xc6 } } michael@0: michael@0: #define BIDI_LEVEL_UNDEFINED 0x80 michael@0: michael@0: //---------------------------------------------------------------------- michael@0: michael@0: // Selection interface michael@0: michael@0: struct SelectionDetails michael@0: { michael@0: #ifdef NS_BUILD_REFCNT_LOGGING michael@0: SelectionDetails() { michael@0: MOZ_COUNT_CTOR(SelectionDetails); michael@0: } michael@0: ~SelectionDetails() { michael@0: MOZ_COUNT_DTOR(SelectionDetails); michael@0: } michael@0: #endif michael@0: int32_t mStart; michael@0: int32_t mEnd; michael@0: SelectionType mType; michael@0: mozilla::TextRangeStyle mTextRangeStyle; michael@0: SelectionDetails *mNext; michael@0: }; michael@0: michael@0: class nsIPresShell; michael@0: class nsIScrollableFrame; michael@0: michael@0: enum EWordMovementType { eStartWord, eEndWord, eDefaultBehavior }; michael@0: michael@0: /** PeekOffsetStruct is used to group various arguments (both input and output) michael@0: * that are passed to nsFrame::PeekOffset(). See below for the description of michael@0: * individual arguments. michael@0: */ michael@0: struct MOZ_STACK_CLASS nsPeekOffsetStruct michael@0: { michael@0: nsPeekOffsetStruct(nsSelectionAmount aAmount, michael@0: nsDirection aDirection, michael@0: int32_t aStartOffset, michael@0: nscoord aDesiredX, michael@0: bool aJumpLines, michael@0: bool aScrollViewStop, michael@0: bool aIsKeyboardSelect, michael@0: bool aVisual, michael@0: EWordMovementType aWordMovementType = eDefaultBehavior) michael@0: : mAmount(aAmount) michael@0: , mDirection(aDirection) michael@0: , mStartOffset(aStartOffset) michael@0: , mDesiredX(aDesiredX) michael@0: , mWordMovementType(aWordMovementType) michael@0: , mJumpLines(aJumpLines) michael@0: , mScrollViewStop(aScrollViewStop) michael@0: , mIsKeyboardSelect(aIsKeyboardSelect) michael@0: , mVisual(aVisual) michael@0: , mResultContent() michael@0: , mResultFrame(nullptr) michael@0: , mContentOffset(0) michael@0: , mAttachForward(false) michael@0: { michael@0: } michael@0: michael@0: // Note: Most arguments (input and output) are only used with certain values michael@0: // of mAmount. These values are indicated for each argument below. michael@0: // Arguments with no such indication are used with all values of mAmount. michael@0: michael@0: /*** Input arguments ***/ michael@0: // Note: The value of some of the input arguments may be changed upon exit. michael@0: michael@0: // mAmount: The type of movement requested (by character, word, line, etc.) michael@0: nsSelectionAmount mAmount; michael@0: michael@0: // mDirection: eDirPrevious or eDirNext. michael@0: // * Note for visual bidi movement: michael@0: // eDirPrevious means 'left-then-up' if the containing block is LTR, michael@0: // 'right-then-up' if it is RTL. michael@0: // eDirNext means 'right-then-down' if the containing block is LTR, michael@0: // 'left-then-down' if it is RTL. michael@0: // Between paragraphs, eDirPrevious means "go to the visual end of the michael@0: // previous paragraph", and eDirNext means "go to the visual beginning michael@0: // of the next paragraph". michael@0: // Used with: eSelectCharacter, eSelectWord, eSelectLine, eSelectParagraph. michael@0: nsDirection mDirection; michael@0: michael@0: // mStartOffset: Offset into the content of the current frame where the peek starts. michael@0: // Used with: eSelectCharacter, eSelectWord michael@0: int32_t mStartOffset; michael@0: michael@0: // mDesiredX: The desired x coordinate for the caret. michael@0: // Used with: eSelectLine. michael@0: nscoord mDesiredX; michael@0: michael@0: // mWordMovementType: An enum that determines whether to prefer the start or end of a word michael@0: // or to use the default beahvior, which is a combination of michael@0: // direction and the platform-based pref michael@0: // "layout.word_select.eat_space_to_next_word" michael@0: EWordMovementType mWordMovementType; michael@0: michael@0: // mJumpLines: Whether to allow jumping across line boundaries. michael@0: // Used with: eSelectCharacter, eSelectWord. michael@0: bool mJumpLines; michael@0: michael@0: // mScrollViewStop: Whether to stop when reaching a scroll view boundary. michael@0: // Used with: eSelectCharacter, eSelectWord, eSelectLine. michael@0: bool mScrollViewStop; michael@0: michael@0: // mIsKeyboardSelect: Whether the peeking is done in response to a keyboard action. michael@0: // Used with: eSelectWord. michael@0: bool mIsKeyboardSelect; michael@0: michael@0: // mVisual: Whether bidi caret behavior is visual (true) or logical (false). michael@0: // Used with: eSelectCharacter, eSelectWord, eSelectBeginLine, eSelectEndLine. michael@0: bool mVisual; michael@0: michael@0: /*** Output arguments ***/ michael@0: michael@0: // mResultContent: Content reached as a result of the peek. michael@0: nsCOMPtr mResultContent; michael@0: michael@0: // mResultFrame: Frame reached as a result of the peek. michael@0: // Used with: eSelectCharacter, eSelectWord. michael@0: nsIFrame *mResultFrame; michael@0: michael@0: // mContentOffset: Offset into content reached as a result of the peek. michael@0: int32_t mContentOffset; michael@0: michael@0: // mAttachForward: When the result position is between two frames, michael@0: // indicates which of the two frames the caret should be painted in. michael@0: // false means "the end of the frame logically before the caret", michael@0: // true means "the beginning of the frame logically after the caret". michael@0: // Used with: eSelectLine, eSelectBeginLine, eSelectEndLine. michael@0: bool mAttachForward; michael@0: }; michael@0: michael@0: struct nsPrevNextBidiLevels michael@0: { michael@0: void SetData(nsIFrame* aFrameBefore, michael@0: nsIFrame* aFrameAfter, michael@0: uint8_t aLevelBefore, michael@0: uint8_t aLevelAfter) michael@0: { michael@0: mFrameBefore = aFrameBefore; michael@0: mFrameAfter = aFrameAfter; michael@0: mLevelBefore = aLevelBefore; michael@0: mLevelAfter = aLevelAfter; michael@0: } michael@0: nsIFrame* mFrameBefore; michael@0: nsIFrame* mFrameAfter; michael@0: uint8_t mLevelBefore; michael@0: uint8_t mLevelAfter; michael@0: }; michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: class Selection; michael@0: } michael@0: } michael@0: class nsIScrollableFrame; michael@0: michael@0: /** michael@0: * Methods which are marked with *unsafe* should be handled with special care. michael@0: * They may cause nsFrameSelection to be deleted, if strong pointer isn't used, michael@0: * or they may cause other objects to be deleted. michael@0: */ michael@0: michael@0: class nsFrameSelection MOZ_FINAL { michael@0: public: michael@0: enum HINT { HINTLEFT = 0, HINTRIGHT = 1}; //end of this line or beginning of next michael@0: /*interfaces for addref and release and queryinterface*/ michael@0: michael@0: NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsFrameSelection) michael@0: NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsFrameSelection) michael@0: michael@0: /** Init will initialize the frame selector with the necessary pres shell to michael@0: * be used by most of the methods michael@0: * @param aShell is the parameter to be used for most of the other calls for callbacks etc michael@0: * @param aLimiter limits the selection to nodes with aLimiter parents michael@0: */ michael@0: void Init(nsIPresShell *aShell, nsIContent *aLimiter); michael@0: michael@0: /** HandleClick will take the focus to the new frame at the new offset and michael@0: * will either extend the selection from the old anchor, or replace the old anchor. michael@0: * the old anchor and focus position may also be used to deselect things michael@0: * @param aNewfocus is the content that wants the focus michael@0: * @param aContentOffset is the content offset of the parent aNewFocus michael@0: * @param aContentOffsetEnd is the content offset of the parent aNewFocus and is specified different michael@0: * when you need to select to and include both start and end points michael@0: * @param aContinueSelection is the flag that tells the selection to keep the old anchor point or not. michael@0: * @param aMultipleSelection will tell the frame selector to replace /or not the old selection. michael@0: * cannot coexist with aContinueSelection michael@0: * @param aHint will tell the selection which direction geometrically to actually show the caret on. michael@0: * 1 = end of this line 0 = beginning of this line michael@0: */ michael@0: /*unsafe*/ michael@0: nsresult HandleClick(nsIContent *aNewFocus, michael@0: uint32_t aContentOffset, michael@0: uint32_t aContentEndOffset, michael@0: bool aContinueSelection, michael@0: bool aMultipleSelection, michael@0: bool aHint); michael@0: michael@0: /** HandleDrag extends the selection to contain the frame closest to aPoint. michael@0: * @param aPresContext is the context to use when figuring out what frame contains the point. michael@0: * @param aFrame is the parent of all frames to use when searching for the closest frame to the point. michael@0: * @param aPoint is relative to aFrame michael@0: */ michael@0: /*unsafe*/ michael@0: void HandleDrag(nsIFrame *aFrame, nsPoint aPoint); michael@0: michael@0: /** HandleTableSelection will set selection to a table, cell, etc michael@0: * depending on information contained in aFlags michael@0: * @param aParentContent is the paretent of either a table or cell that user clicked or dragged the mouse in michael@0: * @param aContentOffset is the offset of the table or cell michael@0: * @param aTarget indicates what to select (defined in nsISelectionPrivate.idl/nsISelectionPrivate.h): michael@0: * TABLESELECTION_CELL We should select a cell (content points to the cell) michael@0: * TABLESELECTION_ROW We should select a row (content points to any cell in row) michael@0: * TABLESELECTION_COLUMN We should select a row (content points to any cell in column) michael@0: * TABLESELECTION_TABLE We should select a table (content points to the table) michael@0: * TABLESELECTION_ALLCELLS We should select all cells (content points to any cell in table) michael@0: * @param aMouseEvent passed in so we can get where event occurred and what keys are pressed michael@0: */ michael@0: /*unsafe*/ michael@0: nsresult HandleTableSelection(nsINode* aParentContent, michael@0: int32_t aContentOffset, michael@0: int32_t aTarget, michael@0: mozilla::WidgetMouseEvent* aMouseEvent); michael@0: michael@0: /** michael@0: * Add cell to the selection. michael@0: * michael@0: * @param aCell [in] HTML td element. michael@0: */ michael@0: virtual nsresult SelectCellElement(nsIContent *aCell); michael@0: michael@0: /** michael@0: * Add cells to the selection inside of the given cells range. michael@0: * michael@0: * @param aTable [in] HTML table element michael@0: * @param aStartRowIndex [in] row index where the cells range starts michael@0: * @param aStartColumnIndex [in] column index where the cells range starts michael@0: * @param aEndRowIndex [in] row index where the cells range ends michael@0: * @param aEndColumnIndex [in] column index where the cells range ends michael@0: */ michael@0: virtual nsresult AddCellsToSelection(nsIContent *aTable, michael@0: int32_t aStartRowIndex, michael@0: int32_t aStartColumnIndex, michael@0: int32_t aEndRowIndex, michael@0: int32_t aEndColumnIndex); michael@0: michael@0: /** michael@0: * Remove cells from selection inside of the given cell range. michael@0: * michael@0: * @param aTable [in] HTML table element michael@0: * @param aStartRowIndex [in] row index where the cells range starts michael@0: * @param aStartColumnIndex [in] column index where the cells range starts michael@0: * @param aEndRowIndex [in] row index where the cells range ends michael@0: * @param aEndColumnIndex [in] column index where the cells range ends michael@0: */ michael@0: virtual nsresult RemoveCellsFromSelection(nsIContent *aTable, michael@0: int32_t aStartRowIndex, michael@0: int32_t aStartColumnIndex, michael@0: int32_t aEndRowIndex, michael@0: int32_t aEndColumnIndex); michael@0: michael@0: /** michael@0: * Remove cells from selection outside of the given cell range. michael@0: * michael@0: * @param aTable [in] HTML table element michael@0: * @param aStartRowIndex [in] row index where the cells range starts michael@0: * @param aStartColumnIndex [in] column index where the cells range starts michael@0: * @param aEndRowIndex [in] row index where the cells range ends michael@0: * @param aEndColumnIndex [in] column index where the cells range ends michael@0: */ michael@0: virtual nsresult RestrictCellsToSelection(nsIContent *aTable, michael@0: int32_t aStartRowIndex, michael@0: int32_t aStartColumnIndex, michael@0: int32_t aEndRowIndex, michael@0: int32_t aEndColumnIndex); michael@0: michael@0: /** StartAutoScrollTimer is responsible for scrolling frames so that michael@0: * aPoint is always visible, and for selecting any frame that contains michael@0: * aPoint. The timer will also reset itself to fire again if we have michael@0: * not scrolled to the end of the document. michael@0: * @param aFrame is the outermost frame to use when searching for michael@0: * the closest frame for the point, i.e. the frame that is capturing michael@0: * the mouse michael@0: * @param aPoint is relative to aFrame. michael@0: * @param aDelay is the timer's interval. michael@0: */ michael@0: /*unsafe*/ michael@0: nsresult StartAutoScrollTimer(nsIFrame *aFrame, michael@0: nsPoint aPoint, michael@0: uint32_t aDelay); michael@0: michael@0: /** StopAutoScrollTimer stops any active auto scroll timer. michael@0: */ michael@0: void StopAutoScrollTimer(); michael@0: michael@0: /** Lookup Selection michael@0: * returns in frame coordinates the selection beginning and ending with the type of selection given michael@0: * @param aContent is the content asking michael@0: * @param aContentOffset is the starting content boundary michael@0: * @param aContentLength is the length of the content piece asking michael@0: * @param aReturnDetails linkedlist of return values for the selection. michael@0: * @param aSlowCheck will check using slow method with no shortcuts michael@0: */ michael@0: SelectionDetails* LookUpSelection(nsIContent *aContent, michael@0: int32_t aContentOffset, michael@0: int32_t aContentLength, michael@0: bool aSlowCheck) const; michael@0: michael@0: /** SetMouseDownState(bool); michael@0: * sets the mouse state to aState for resons of drag state. michael@0: * @param aState is the new state of mousedown michael@0: */ michael@0: /*unsafe*/ michael@0: void SetMouseDownState(bool aState); michael@0: michael@0: /** GetMouseDownState(bool *); michael@0: * gets the mouse state to aState for resons of drag state. michael@0: * @param aState will hold the state of mousedown michael@0: */ michael@0: bool GetMouseDownState() const { return mMouseDownState; } michael@0: michael@0: /** michael@0: if we are in table cell selection mode. aka ctrl click in table cell michael@0: */ michael@0: bool GetTableCellSelection() const { return mSelectingTableCellMode != 0; } michael@0: void ClearTableCellSelection() { mSelectingTableCellMode = 0; } michael@0: michael@0: /** GetSelection michael@0: * no query interface for selection. must use this method now. michael@0: * @param aSelectionType enum value defined in nsISelection for the seleciton you want. michael@0: */ michael@0: mozilla::dom::Selection* GetSelection(SelectionType aType) const; michael@0: michael@0: /** michael@0: * ScrollSelectionIntoView scrolls a region of the selection, michael@0: * so that it is visible in the scrolled view. michael@0: * michael@0: * @param aType the selection to scroll into view. michael@0: * @param aRegion the region inside the selection to scroll into view. michael@0: * @param aFlags the scroll flags. Valid bits include: michael@0: * SCROLL_SYNCHRONOUS: when set, scrolls the selection into view michael@0: * before returning. If not set, posts a request which is processed michael@0: * at some point after the method returns. michael@0: * SCROLL_FIRST_ANCESTOR_ONLY: if set, only the first ancestor will be scrolled michael@0: * into view. michael@0: */ michael@0: /*unsafe*/ michael@0: nsresult ScrollSelectionIntoView(SelectionType aType, michael@0: SelectionRegion aRegion, michael@0: int16_t aFlags) const; michael@0: michael@0: /** RepaintSelection repaints the selected frames that are inside the selection michael@0: * specified by aSelectionType. michael@0: * @param aSelectionType enum value defined in nsISelection for the seleciton you want. michael@0: */ michael@0: nsresult RepaintSelection(SelectionType aType) const; michael@0: michael@0: /** GetFrameForNodeOffset given a node and its child offset, return the nsIFrame and michael@0: * the offset into that frame. michael@0: * @param aNode input parameter for the node to look at michael@0: * @param aOffset offset into above node. michael@0: * @param aReturnOffset will contain offset into frame. michael@0: */ michael@0: virtual nsIFrame* GetFrameForNodeOffset(nsIContent *aNode, michael@0: int32_t aOffset, michael@0: HINT aHint, michael@0: int32_t *aReturnOffset) const; michael@0: michael@0: /** michael@0: * Scrolling then moving caret placement code in common to text areas and michael@0: * content areas should be located in the implementer michael@0: * This method will accept the following parameters and perform the scroll michael@0: * and caret movement. It remains for the caller to call the final michael@0: * ScrollCaretIntoView if that called wants to be sure the caret is always michael@0: * visible. michael@0: * michael@0: * @param aForward if true, scroll forward if not scroll backward michael@0: * @param aExtend if true, extend selection to the new point michael@0: * @param aScrollableFrame the frame to scroll michael@0: */ michael@0: /*unsafe*/ michael@0: void CommonPageMove(bool aForward, michael@0: bool aExtend, michael@0: nsIScrollableFrame* aScrollableFrame); michael@0: michael@0: void SetHint(HINT aHintRight) { mHint = aHintRight; } michael@0: HINT GetHint() const { return mHint; } michael@0: michael@0: /** SetCaretBidiLevel sets the caret bidi level michael@0: * @param aLevel the caret bidi level michael@0: * This method is virtual since it gets called from outside of layout. michael@0: */ michael@0: virtual void SetCaretBidiLevel (uint8_t aLevel); michael@0: /** GetCaretBidiLevel gets the caret bidi level michael@0: * This method is virtual since it gets called from outside of layout. michael@0: */ michael@0: virtual uint8_t GetCaretBidiLevel() const; michael@0: /** UndefineCaretBidiLevel sets the caret bidi level to "undefined" michael@0: * This method is virtual since it gets called from outside of layout. michael@0: */ michael@0: virtual void UndefineCaretBidiLevel(); michael@0: michael@0: /** CharacterMove will generally be called from the nsiselectioncontroller implementations. michael@0: * the effect being the selection will move one character left or right. michael@0: * @param aForward move forward in document. michael@0: * @param aExtend continue selection michael@0: */ michael@0: /*unsafe*/ michael@0: nsresult CharacterMove(bool aForward, bool aExtend); michael@0: michael@0: /** CharacterExtendForDelete extends the selection forward (logically) to michael@0: * the next character cell, so that the selected cell can be deleted. michael@0: */ michael@0: /*unsafe*/ michael@0: nsresult CharacterExtendForDelete(); michael@0: michael@0: /** CharacterExtendForBackspace extends the selection backward (logically) to michael@0: * the previous character cell, so that the selected cell can be deleted. michael@0: */ michael@0: /*unsafe*/ michael@0: nsresult CharacterExtendForBackspace(); michael@0: michael@0: /** WordMove will generally be called from the nsiselectioncontroller implementations. michael@0: * the effect being the selection will move one word left or right. michael@0: * @param aForward move forward in document. michael@0: * @param aExtend continue selection michael@0: */ michael@0: /*unsafe*/ michael@0: nsresult WordMove(bool aForward, bool aExtend); michael@0: michael@0: /** WordExtendForDelete extends the selection backward or forward (logically) to the michael@0: * next word boundary, so that the selected word can be deleted. michael@0: * @param aForward select forward in document. michael@0: */ michael@0: /*unsafe*/ michael@0: nsresult WordExtendForDelete(bool aForward); michael@0: michael@0: /** LineMove will generally be called from the nsiselectioncontroller implementations. michael@0: * the effect being the selection will move one line up or down. michael@0: * @param aForward move forward in document. michael@0: * @param aExtend continue selection michael@0: */ michael@0: /*unsafe*/ michael@0: nsresult LineMove(bool aForward, bool aExtend); michael@0: michael@0: /** IntraLineMove will generally be called from the nsiselectioncontroller implementations. michael@0: * the effect being the selection will move to beginning or end of line michael@0: * @param aForward move forward in document. michael@0: * @param aExtend continue selection michael@0: */ michael@0: /*unsafe*/ michael@0: nsresult IntraLineMove(bool aForward, bool aExtend); michael@0: michael@0: /** Select All will generally be called from the nsiselectioncontroller implementations. michael@0: * it will select the whole doc michael@0: */ michael@0: /*unsafe*/ michael@0: nsresult SelectAll(); michael@0: michael@0: /** Sets/Gets The display selection enum. michael@0: */ michael@0: void SetDisplaySelection(int16_t aState) { mDisplaySelection = aState; } michael@0: int16_t GetDisplaySelection() const { return mDisplaySelection; } michael@0: michael@0: /** This method can be used to store the data received during a MouseDown michael@0: * event so that we can place the caret during the MouseUp event. michael@0: * @aMouseEvent the event received by the selection MouseDown michael@0: * handling method. A nullptr value can be use to tell this method michael@0: * that any data is storing is no longer valid. michael@0: */ michael@0: void SetDelayedCaretData(mozilla::WidgetMouseEvent* aMouseEvent); michael@0: michael@0: /** Get the delayed MouseDown event data necessary to place the michael@0: * caret during MouseUp processing. michael@0: * @return a pointer to the event received michael@0: * by the selection during MouseDown processing. It can be nullptr michael@0: * if the data is no longer valid. michael@0: */ michael@0: bool HasDelayedCaretData() { return mDelayedMouseEventValid; } michael@0: bool IsShiftDownInDelayedCaretData() michael@0: { michael@0: NS_ASSERTION(mDelayedMouseEventValid, "No valid delayed caret data"); michael@0: return mDelayedMouseEventIsShift; michael@0: } michael@0: uint32_t GetClickCountInDelayedCaretData() michael@0: { michael@0: NS_ASSERTION(mDelayedMouseEventValid, "No valid delayed caret data"); michael@0: return mDelayedMouseEventClickCount; michael@0: } michael@0: michael@0: /** Get the content node that limits the selection michael@0: * When searching up a nodes for parents, as in a text edit field michael@0: * in an browser page, we must stop at this node else we reach into the michael@0: * parent page, which is very bad! michael@0: */ michael@0: nsIContent* GetLimiter() const { return mLimiter; } michael@0: michael@0: nsIContent* GetAncestorLimiter() const { return mAncestorLimiter; } michael@0: /*unsafe*/ michael@0: void SetAncestorLimiter(nsIContent *aLimiter); michael@0: michael@0: /** This will tell the frame selection that a double click has been pressed michael@0: * so it can track abort future drags if inside the same selection michael@0: * @aDoubleDown has the double click down happened michael@0: */ michael@0: void SetMouseDoubleDown(bool aDoubleDown) { mMouseDoubleDownState = aDoubleDown; } michael@0: michael@0: /** This will return whether the double down flag was set. michael@0: * @return whether the double down flag was set michael@0: */ michael@0: bool GetMouseDoubleDown() const { return mMouseDoubleDownState; } michael@0: michael@0: /** GetPrevNextBidiLevels will return the frames and associated Bidi levels of the characters michael@0: * logically before and after a (collapsed) selection. michael@0: * @param aNode is the node containing the selection michael@0: * @param aContentOffset is the offset of the selection in the node michael@0: * @param aJumpLines If true, look across line boundaries. michael@0: * If false, behave as if there were base-level frames at line edges. michael@0: * michael@0: * @return A struct holding the before/after frame and the before/after level. michael@0: * michael@0: * At the beginning and end of each line there is assumed to be a frame with michael@0: * Bidi level equal to the paragraph embedding level. michael@0: * In these cases the before frame and after frame respectively will be michael@0: * nullptr. michael@0: * michael@0: * This method is virtual since it gets called from outside of layout. michael@0: */ michael@0: virtual nsPrevNextBidiLevels GetPrevNextBidiLevels(nsIContent *aNode, michael@0: uint32_t aContentOffset, michael@0: bool aJumpLines) const; michael@0: michael@0: /** GetFrameFromLevel will scan in a given direction michael@0: * until it finds a frame with a Bidi level less than or equal to a given level. michael@0: * It will return the last frame before this. michael@0: * @param aPresContext is the context to use michael@0: * @param aFrameIn is the frame to start from michael@0: * @param aDirection is the direction to scan michael@0: * @param aBidiLevel is the level to search for michael@0: * @param aFrameOut will hold the frame returned michael@0: */ michael@0: nsresult GetFrameFromLevel(nsIFrame *aFrameIn, michael@0: nsDirection aDirection, michael@0: uint8_t aBidiLevel, michael@0: nsIFrame **aFrameOut) const; michael@0: michael@0: /** michael@0: * MaintainSelection will track the current selection as being "sticky". michael@0: * Dragging or extending selection will never allow for a subset michael@0: * (or the whole) of the maintained selection to become unselected. michael@0: * Primary use: double click selecting then dragging on second click michael@0: * @param aAmount the initial amount of text selected (word, line or paragraph). michael@0: * For "line", use eSelectBeginLine. michael@0: */ michael@0: nsresult MaintainSelection(nsSelectionAmount aAmount = eSelectNoAmount); michael@0: michael@0: nsFrameSelection(); michael@0: michael@0: void StartBatchChanges(); michael@0: void EndBatchChanges(); michael@0: /*unsafe*/ michael@0: nsresult DeleteFromDocument(); michael@0: michael@0: nsIPresShell *GetShell()const { return mShell; } michael@0: michael@0: void DisconnectFromPresShell(); michael@0: nsresult ClearNormalSelection(); michael@0: private: michael@0: nsresult TakeFocus(nsIContent *aNewFocus, michael@0: uint32_t aContentOffset, michael@0: uint32_t aContentEndOffset, michael@0: HINT aHint, michael@0: bool aContinueSelection, michael@0: bool aMultipleSelection); michael@0: michael@0: void BidiLevelFromMove(nsIPresShell* aPresShell, michael@0: nsIContent *aNode, michael@0: uint32_t aContentOffset, michael@0: uint32_t aKeycode, michael@0: HINT aHint); michael@0: void BidiLevelFromClick(nsIContent *aNewFocus, uint32_t aContentOffset); michael@0: nsPrevNextBidiLevels GetPrevNextBidiLevels(nsIContent *aNode, michael@0: uint32_t aContentOffset, michael@0: HINT aHint, michael@0: bool aJumpLines) const; michael@0: michael@0: bool AdjustForMaintainedSelection(nsIContent *aContent, int32_t aOffset); michael@0: michael@0: // post and pop reasons for notifications. we may stack these later michael@0: void PostReason(int16_t aReason) { mSelectionChangeReason = aReason; } michael@0: int16_t PopReason() michael@0: { michael@0: int16_t retval = mSelectionChangeReason; michael@0: mSelectionChangeReason = 0; michael@0: return retval; michael@0: } michael@0: michael@0: friend class mozilla::dom::Selection; michael@0: #ifdef DEBUG michael@0: void printSelection(); // for debugging michael@0: #endif /* DEBUG */ michael@0: michael@0: void ResizeBuffer(uint32_t aNewBufSize); michael@0: /*HELPER METHODS*/ michael@0: nsresult MoveCaret(uint32_t aKeycode, bool aContinueSelection, michael@0: nsSelectionAmount aAmount); michael@0: nsresult MoveCaret(uint32_t aKeycode, bool aContinueSelection, michael@0: nsSelectionAmount aAmount, michael@0: bool aVisualMovement); michael@0: michael@0: nsresult FetchDesiredX(nscoord &aDesiredX); //the x position requested by the Key Handling for up down michael@0: void InvalidateDesiredX(); //do not listen to mDesiredX you must get another. michael@0: void SetDesiredX(nscoord aX); //set the mDesiredX michael@0: michael@0: nsresult ConstrainFrameAndPointToAnchorSubtree(nsIFrame *aFrame, nsPoint& aPoint, nsIFrame **aRetFrame, nsPoint& aRetPoint); michael@0: michael@0: uint32_t GetBatching() const {return mBatching; } michael@0: bool GetNotifyFrames() const { return mNotifyFrames; } michael@0: void SetDirty(bool aDirty=true){if (mBatching) mChangesDuringBatching = aDirty;} michael@0: michael@0: // nsFrameSelection may get deleted when calling this, michael@0: // so remember to use nsCOMPtr when needed. michael@0: nsresult NotifySelectionListeners(SelectionType aType); // add parameters to say collapsed etc? michael@0: michael@0: nsRefPtr mDomSelections[nsISelectionController::NUM_SELECTIONTYPES]; michael@0: michael@0: // Table selection support. michael@0: nsITableCellLayout* GetCellLayout(nsIContent *aCellContent) const; michael@0: michael@0: nsresult SelectBlockOfCells(nsIContent *aStartNode, nsIContent *aEndNode); michael@0: nsresult SelectRowOrColumn(nsIContent *aCellContent, uint32_t aTarget); michael@0: nsresult UnselectCells(nsIContent *aTable, michael@0: int32_t aStartRowIndex, int32_t aStartColumnIndex, michael@0: int32_t aEndRowIndex, int32_t aEndColumnIndex, michael@0: bool aRemoveOutsideOfCellRange); michael@0: michael@0: nsresult GetCellIndexes(nsIContent *aCell, int32_t &aRowIndex, int32_t &aColIndex); michael@0: michael@0: // Get our first range, if its first selected node is a cell. If this does michael@0: // not return null, then the first node in the returned range is a cell michael@0: // (according to GetFirstCellNodeInRange). michael@0: nsRange* GetFirstCellRange(); michael@0: // Get our next range, if its first selected node is a cell. If this does michael@0: // not return null, then the first node in the returned range is a cell michael@0: // (according to GetFirstCellNodeInRange). michael@0: nsRange* GetNextCellRange(); michael@0: nsIContent* GetFirstCellNodeInRange(nsRange *aRange) const; michael@0: // Returns non-null table if in same table, null otherwise michael@0: nsIContent* IsInSameTable(nsIContent *aContent1, nsIContent *aContent2) const; michael@0: // Might return null michael@0: nsIContent* GetParentTable(nsIContent *aCellNode) const; michael@0: nsresult CreateAndAddRange(nsINode *aParentNode, int32_t aOffset); michael@0: michael@0: nsCOMPtr mCellParent; //used to snap to table selection michael@0: nsCOMPtr mStartSelectedCell; michael@0: nsCOMPtr mEndSelectedCell; michael@0: nsCOMPtr mAppendStartSelectedCell; michael@0: nsCOMPtr mUnselectCellOnMouseUp; michael@0: int32_t mSelectingTableCellMode; michael@0: int32_t mSelectedCellIndex; michael@0: michael@0: // maintain selection michael@0: nsRefPtr mMaintainRange; michael@0: nsSelectionAmount mMaintainedAmount; michael@0: michael@0: //batching michael@0: int32_t mBatching; michael@0: michael@0: // Limit selection navigation to a child of this node. michael@0: nsCOMPtr mLimiter; michael@0: // Limit selection navigation to a descendant of this node. michael@0: nsCOMPtr mAncestorLimiter; michael@0: michael@0: nsIPresShell *mShell; michael@0: michael@0: int16_t mSelectionChangeReason; // reason for notifications of selection changing michael@0: int16_t mDisplaySelection; //for visual display purposes. michael@0: michael@0: HINT mHint; //hint to tell if the selection is at the end of this line or beginning of next michael@0: uint8_t mCaretBidiLevel; michael@0: michael@0: int32_t mDesiredX; michael@0: uint32_t mDelayedMouseEventClickCount; michael@0: bool mDelayedMouseEventIsShift; michael@0: bool mDelayedMouseEventValid; michael@0: michael@0: bool mChangesDuringBatching; michael@0: bool mNotifyFrames; michael@0: bool mDragSelectingCells; michael@0: bool mMouseDownState; //for drag purposes michael@0: bool mMouseDoubleDownState; //has the doubleclick down happened michael@0: bool mDesiredXSet; michael@0: michael@0: int8_t mCaretMovementStyle; michael@0: }; michael@0: michael@0: #endif /* nsFrameSelection_h___ */