/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nsFrameSelection_h___ #define nsFrameSelection_h___ #include "mozilla/Attributes.h" #include "mozilla/EventForwards.h" #include "mozilla/dom/Selection.h" #include "mozilla/TextRange.h" #include "mozilla/UniquePtr.h" #include "nsIFrame.h" #include "nsIContent.h" #include "nsISelectionController.h" #include "nsISelectionListener.h" #include "nsITableCellLayout.h" #include "WordMovementType.h" #include "CaretAssociationHint.h" #include "nsBidiPresUtils.h" class nsRange; #define BIDI_LEVEL_UNDEFINED 0x80 //---------------------------------------------------------------------- // Selection interface struct SelectionDetails { SelectionDetails() : mStart(), mEnd(), mSelectionType(mozilla::SelectionType::eInvalid) { MOZ_COUNT_CTOR(SelectionDetails); } #ifdef NS_BUILD_REFCNT_LOGGING ~SelectionDetails() { MOZ_COUNT_DTOR(SelectionDetails); } #endif int32_t mStart; int32_t mEnd; mozilla::SelectionType mSelectionType; mozilla::TextRangeStyle mTextRangeStyle; mozilla::UniquePtr mNext; }; struct SelectionCustomColors { #ifdef NS_BUILD_REFCNT_LOGGING SelectionCustomColors() { MOZ_COUNT_CTOR(SelectionCustomColors); } ~SelectionCustomColors() { MOZ_COUNT_DTOR(SelectionCustomColors); } #endif mozilla::Maybe mForegroundColor; mozilla::Maybe mBackgroundColor; mozilla::Maybe mAltForegroundColor; mozilla::Maybe mAltBackgroundColor; }; class nsIPresShell; /** PeekOffsetStruct is used to group various arguments (both input and output) * that are passed to nsFrame::PeekOffset(). See below for the description of * individual arguments. */ struct MOZ_STACK_CLASS nsPeekOffsetStruct { enum class ForceEditableRegion { No, Yes, }; nsPeekOffsetStruct( nsSelectionAmount aAmount, nsDirection aDirection, int32_t aStartOffset, nsPoint aDesiredPos, bool aJumpLines, bool aScrollViewStop, bool aIsKeyboardSelect, bool aVisual, bool aExtend, ForceEditableRegion = ForceEditableRegion::No, mozilla::EWordMovementType aWordMovementType = mozilla::eDefaultBehavior); // Note: Most arguments (input and output) are only used with certain values // of mAmount. These values are indicated for each argument below. // Arguments with no such indication are used with all values of mAmount. /*** Input arguments ***/ // Note: The value of some of the input arguments may be changed upon exit. // The type of movement requested (by character, word, line, etc.) nsSelectionAmount mAmount; // eDirPrevious or eDirNext. // // Note for visual bidi movement: // * eDirPrevious means 'left-then-up' if the containing block is LTR, // 'right-then-up' if it is RTL. // * eDirNext means 'right-then-down' if the containing block is LTR, // 'left-then-down' if it is RTL. // * Between paragraphs, eDirPrevious means "go to the visual end of // the previous paragraph", and eDirNext means "go to the visual // beginning of the next paragraph". // // Used with: eSelectCharacter, eSelectWord, eSelectLine, eSelectParagraph. nsDirection mDirection; // Offset into the content of the current frame where the peek starts. // // Used with: eSelectCharacter, eSelectWord int32_t mStartOffset; // The desired inline coordinate for the caret (one of .x or .y will be used, // depending on line's writing mode) // // Used with: eSelectLine. nsPoint mDesiredPos; // An enum that determines whether to prefer the start or end of a word or to // use the default beahvior, which is a combination of direction and the // platform-based pref "layout.word_select.eat_space_to_next_word" mozilla::EWordMovementType mWordMovementType; // Whether to allow jumping across line boundaries. // // Used with: eSelectCharacter, eSelectWord. bool mJumpLines; // Whether to stop when reaching a scroll view boundary. // // Used with: eSelectCharacter, eSelectWord, eSelectLine. bool mScrollViewStop; // Whether the peeking is done in response to a keyboard action. // // Used with: eSelectWord. bool mIsKeyboardSelect; // Whether bidi caret behavior is visual (true) or logical (false). // // Used with: eSelectCharacter, eSelectWord, eSelectBeginLine, eSelectEndLine. bool mVisual; // Whether the selection is being extended or moved. bool mExtend; // If true, the offset has to end up in an editable node, otherwise we'll keep // searching. const bool mForceEditableRegion; /*** Output arguments ***/ // Content reached as a result of the peek. nsCOMPtr mResultContent; // Frame reached as a result of the peek. // // Used with: eSelectCharacter, eSelectWord. nsIFrame* mResultFrame; // Offset into content reached as a result of the peek. int32_t mContentOffset; // When the result position is between two frames, indicates which of the two // frames the caret should be painted in. false means "the end of the frame // logically before the caret", true means "the beginning of the frame // logically after the caret". // // Used with: eSelectLine, eSelectBeginLine, eSelectEndLine. mozilla::CaretAssociationHint mAttach; }; struct nsPrevNextBidiLevels { void SetData(nsIFrame* aFrameBefore, nsIFrame* aFrameAfter, nsBidiLevel aLevelBefore, nsBidiLevel aLevelAfter) { mFrameBefore = aFrameBefore; mFrameAfter = aFrameAfter; mLevelBefore = aLevelBefore; mLevelAfter = aLevelAfter; } nsIFrame* mFrameBefore; nsIFrame* mFrameAfter; nsBidiLevel mLevelBefore; nsBidiLevel mLevelAfter; }; namespace mozilla { class SelectionChangeEventDispatcher; namespace dom { class Selection; } // namespace dom /** * Constants for places that want to handle table selections. These * indicate what part of a table is being selected. */ enum class TableSelection : uint32_t { None, /* Nothing being selected; not valid in all cases. */ Cell, /* A cell is being selected. */ Row, /* A row is being selected. */ Column, /* A column is being selected. */ Table, /* A table (including cells and captions) is being selected. */ AllCells, /* All the cells in a table are being selected. */ }; } // namespace mozilla class nsIScrollableFrame; /** * Methods which are marked with *unsafe* should be handled with special care. * They may cause nsFrameSelection to be deleted, if strong pointer isn't used, * or they may cause other objects to be deleted. */ class nsFrameSelection final { public: typedef mozilla::CaretAssociationHint CaretAssociateHint; /*interfaces for addref and release and queryinterface*/ NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(nsFrameSelection) NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsFrameSelection) /** * Init will initialize the frame selector with the necessary pres shell to * be used by most of the methods * * @param aShell is the parameter to be used for most of the other calls for * callbacks etc * * @param aLimiter limits the selection to nodes with aLimiter parents * * @param aAccessibleCaretEnabled true if we should enable the accessible * caret. */ void Init(nsIPresShell* aShell, nsIContent* aLimiter, bool aAccessibleCaretEnabled); /** * HandleClick will take the focus to the new frame at the new offset and * will either extend the selection from the old anchor, or replace the old * anchor. the old anchor and focus position may also be used to deselect * things * * @param aNewfocus is the content that wants the focus * * @param aContentOffset is the content offset of the parent aNewFocus * * @param aContentOffsetEnd is the content offset of the parent aNewFocus and * is specified different when you need to select to and include both start * and end points * * @param aContinueSelection is the flag that tells the selection to keep the * old anchor point or not. * * @param aMultipleSelection will tell the frame selector to replace /or not * the old selection. cannot coexist with aContinueSelection * * @param aHint will tell the selection which direction geometrically to * actually show the caret on. 1 = end of this line 0 = beginning of this line */ MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult HandleClick(nsIContent* aNewFocus, uint32_t aContentOffset, uint32_t aContentEndOffset, bool aContinueSelection, bool aMultipleSelection, CaretAssociateHint aHint); /** * HandleDrag extends the selection to contain the frame closest to aPoint. * * @param aPresContext is the context to use when figuring out what frame * contains the point. * * @param aFrame is the parent of all frames to use when searching for the * closest frame to the point. * * @param aPoint is relative to aFrame */ /*unsafe*/ void HandleDrag(nsIFrame* aFrame, const nsPoint& aPoint); /** * HandleTableSelection will set selection to a table, cell, etc * depending on information contained in aFlags * * @param aParentContent is the paretent of either a table or cell that user * clicked or dragged the mouse in * * @param aContentOffset is the offset of the table or cell * * @param aTarget indicates what to select * * TableSelection::Cell * We should select a cell (content points to the cell) * * TableSelection::Row * We should select a row (content points to any cell in row) * * TableSelection::Column * We should select a row (content points to any cell in column) * * TableSelection::Table * We should select a table (content points to the table) * * TableSelection::AllCells * We should select all cells (content points to any cell in table) * * @param aMouseEvent passed in so we can get where event occurred * and what keys are pressed */ /*unsafe*/ nsresult HandleTableSelection(nsINode* aParentContent, int32_t aContentOffset, mozilla::TableSelection aTarget, mozilla::WidgetMouseEvent* aMouseEvent); /** * Add cell to the selection. * * @param aCell [in] HTML td element. */ nsresult SelectCellElement(nsIContent* aCell); /** * Add cells to the selection inside of the given cells range. * * @param aTable [in] HTML table element * @param aStartRowIndex [in] row index where the cells range starts * @param aStartColumnIndex [in] column index where the cells range starts * @param aEndRowIndex [in] row index where the cells range ends * @param aEndColumnIndex [in] column index where the cells range ends */ nsresult AddCellsToSelection(nsIContent* aTable, int32_t aStartRowIndex, int32_t aStartColumnIndex, int32_t aEndRowIndex, int32_t aEndColumnIndex); /** * Remove cells from selection inside of the given cell range. * * @param aTable [in] HTML table element * @param aStartRowIndex [in] row index where the cells range starts * @param aStartColumnIndex [in] column index where the cells range starts * @param aEndRowIndex [in] row index where the cells range ends * @param aEndColumnIndex [in] column index where the cells range ends */ nsresult RemoveCellsFromSelection(nsIContent* aTable, int32_t aStartRowIndex, int32_t aStartColumnIndex, int32_t aEndRowIndex, int32_t aEndColumnIndex); /** * Remove cells from selection outside of the given cell range. * * @param aTable [in] HTML table element * @param aStartRowIndex [in] row index where the cells range starts * @param aStartColumnIndex [in] column index where the cells range starts * @param aEndRowIndex [in] row index where the cells range ends * @param aEndColumnIndex [in] column index where the cells range ends */ nsresult RestrictCellsToSelection(nsIContent* aTable, int32_t aStartRowIndex, int32_t aStartColumnIndex, int32_t aEndRowIndex, int32_t aEndColumnIndex); /** * StartAutoScrollTimer is responsible for scrolling frames so that * aPoint is always visible, and for selecting any frame that contains * aPoint. The timer will also reset itself to fire again if we have * not scrolled to the end of the document. * * @param aFrame is the outermost frame to use when searching for * the closest frame for the point, i.e. the frame that is capturing * the mouse * * @param aPoint is relative to aFrame. * * @param aDelay is the timer's interval. */ /*unsafe*/ nsresult StartAutoScrollTimer(nsIFrame* aFrame, const nsPoint& aPoint, uint32_t aDelay); /** * Stops any active auto scroll timer. */ void StopAutoScrollTimer(); /** * Returns in frame coordinates the selection beginning and ending with the * type of selection given * * @param aContent is the content asking * @param aContentOffset is the starting content boundary * @param aContentLength is the length of the content piece asking * @param aSlowCheck will check using slow method with no shortcuts */ mozilla::UniquePtr LookUpSelection(nsIContent* aContent, int32_t aContentOffset, int32_t aContentLength, bool aSlowCheck) const; /** * Sets the drag state to aState for resons of drag state. * * @param aState is the new state of drag */ MOZ_CAN_RUN_SCRIPT_BOUNDARY void SetDragState(bool aState); /** * Gets the drag state to aState for resons of drag state. * * @param aState will hold the state of drag */ bool GetDragState() const { return mDragState; } /** * If we are in table cell selection mode. aka ctrl click in table cell */ bool GetTableCellSelection() const { return mSelectingTableCellMode != mozilla::TableSelection::None; } void ClearTableCellSelection() { mSelectingTableCellMode = mozilla::TableSelection::None; } /** * No query interface for selection. must use this method now. * * @param aSelectionType The selection type what you want. */ mozilla::dom::Selection* GetSelection( mozilla::SelectionType aSelectionType) const; /** * ScrollSelectionIntoView scrolls a region of the selection, * so that it is visible in the scrolled view. * * @param aSelectionType the selection to scroll into view. * * @param aRegion the region inside the selection to scroll into view. * * @param aFlags the scroll flags. Valid bits include: * * SCROLL_SYNCHRONOUS: when set, scrolls the selection into view * before returning. If not set, posts a request which is processed * at some point after the method returns. * * SCROLL_FIRST_ANCESTOR_ONLY: if set, only the first ancestor will be * scrolled into view. */ /*unsafe*/ nsresult ScrollSelectionIntoView(mozilla::SelectionType aSelectionType, SelectionRegion aRegion, int16_t aFlags) const; /** * RepaintSelection repaints the selected frames that are inside the * selection specified by aSelectionType. * * @param aSelectionType The selection type what you want to repaint. */ nsresult RepaintSelection(mozilla::SelectionType aSelectionType); /** * Given a node and its child offset, return the nsIFrame and the offset into * that frame. * * @param aNode input parameter for the node to look at * @param aOffset offset into above node. * @param aReturnOffset will contain offset into frame. */ nsIFrame* GetFrameForNodeOffset(nsIContent* aNode, int32_t aOffset, CaretAssociateHint aHint, int32_t* aReturnOffset) const; /** * GetFrameToPageSelect() returns a frame which is ancestor limit of * per-page selection. The frame may not be scrollable. E.g., * when selection ancestor limit is set to a frame of an editing host of * contenteditable element and it's not scrollable. */ nsIFrame* GetFrameToPageSelect() const; /** * Scrolling then moving caret placement code in common to text areas and * content areas should be located in the implementer * This method will accept the following parameters and perform the scroll * and caret movement. It remains for the caller to call the final * ScrollCaretIntoView if that called wants to be sure the caret is always * visible. * * @param aForward if true, scroll forward if not scroll backward * @param aExtend if true, extend selection to the new point * @param aFrame the frame to scroll or container of per-page selection. * if aExtend is true and selection may have ancestor limit, * should set result of GetFrameToPageSelect(). */ MOZ_CAN_RUN_SCRIPT void CommonPageMove(bool aForward, bool aExtend, nsIFrame* aFrame); void SetHint(CaretAssociateHint aHintRight) { mHint = aHintRight; } CaretAssociateHint GetHint() const { return mHint; } /** * SetCaretBidiLevel sets the caret bidi level. * @param aLevel the caret bidi level */ void SetCaretBidiLevel(nsBidiLevel aLevel); /** * GetCaretBidiLevel gets the caret bidi level. */ nsBidiLevel GetCaretBidiLevel() const; /** * UndefineCaretBidiLevel sets the caret bidi level to "undefined". */ void UndefineCaretBidiLevel(); /** * PhysicalMove will generally be called from the nsiselectioncontroller * implementations. the effect being the selection will move one unit * 'aAmount' in the given aDirection. * @param aDirection the direction to move the selection * @param aAmount amount of movement (char/line; word/page; eol/doc) * @param aExtend continue selection */ /*unsafe*/ nsresult PhysicalMove(int16_t aDirection, int16_t aAmount, bool aExtend); /** * CharacterMove will generally be called from the nsiselectioncontroller * implementations. the effect being the selection will move one character * left or right. * @param aForward move forward in document. * @param aExtend continue selection */ /*unsafe*/ nsresult CharacterMove(bool aForward, bool aExtend); /** * CharacterExtendForDelete extends the selection forward (logically) to * the next character cell, so that the selected cell can be deleted. */ /*unsafe*/ nsresult CharacterExtendForDelete(); /** * CharacterExtendForBackspace extends the selection backward (logically) to * the previous character cell, so that the selected cell can be deleted. */ /*unsafe*/ nsresult CharacterExtendForBackspace(); /** * WordMove will generally be called from the nsiselectioncontroller * implementations. the effect being the selection will move one word left or * right. * @param aForward move forward in document. * @param aExtend continue selection */ /*unsafe*/ nsresult WordMove(bool aForward, bool aExtend); /** * WordExtendForDelete extends the selection backward or forward (logically) * to the next word boundary, so that the selected word can be deleted. * @param aForward select forward in document. */ /*unsafe*/ nsresult WordExtendForDelete(bool aForward); /** * LineMove will generally be called from the nsiselectioncontroller * implementations. the effect being the selection will move one line up or * down. * @param aForward move forward in document. * @param aExtend continue selection */ /*unsafe*/ nsresult LineMove(bool aForward, bool aExtend); /** * IntraLineMove will generally be called from the nsiselectioncontroller * implementations. the effect being the selection will move to beginning or * end of line * @param aForward move forward in document. * @param aExtend continue selection */ /*unsafe*/ nsresult IntraLineMove(bool aForward, bool aExtend); /** * Select All will generally be called from the nsiselectioncontroller * implementations. it will select the whole doc */ MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult SelectAll(); /** Sets/Gets The display selection enum. */ void SetDisplaySelection(int16_t aState) { mDisplaySelection = aState; } int16_t GetDisplaySelection() const { return mDisplaySelection; } /** * This method can be used to store the data received during a MouseDown * event so that we can place the caret during the MouseUp event. * * @param aMouseEvent the event received by the selection MouseDown * handling method. A nullptr value can be use to tell this method * that any data is storing is no longer valid. */ void SetDelayedCaretData(mozilla::WidgetMouseEvent* aMouseEvent); /** * Get the delayed MouseDown event data necessary to place the * caret during MouseUp processing. * * @return a pointer to the event received * by the selection during MouseDown processing. It can be nullptr * if the data is no longer valid. */ bool HasDelayedCaretData() { return mDelayedMouseEventValid; } bool IsShiftDownInDelayedCaretData() { NS_ASSERTION(mDelayedMouseEventValid, "No valid delayed caret data"); return mDelayedMouseEventIsShift; } uint32_t GetClickCountInDelayedCaretData() { NS_ASSERTION(mDelayedMouseEventValid, "No valid delayed caret data"); return mDelayedMouseEventClickCount; } bool MouseDownRecorded() { return !GetDragState() && HasDelayedCaretData() && GetClickCountInDelayedCaretData() < 2; } /** * Get the content node that limits the selection * * When searching up a nodes for parents, as in a text edit field * in an browser page, we must stop at this node else we reach into the * parent page, which is very bad! */ nsIContent* GetLimiter() const { return mLimiter; } nsIContent* GetAncestorLimiter() const { return mAncestorLimiter; } MOZ_CAN_RUN_SCRIPT_BOUNDARY void SetAncestorLimiter(nsIContent* aLimiter); /** * This will tell the frame selection that a double click has been pressed * so it can track abort future drags if inside the same selection * @param aDoubleDown has the double click down happened */ void SetMouseDoubleDown(bool aDoubleDown) { mMouseDoubleDownState = aDoubleDown; } /** * This will return whether the double down flag was set. * @return whether the double down flag was set */ bool GetMouseDoubleDown() const { return mMouseDoubleDownState; } /** * GetPrevNextBidiLevels will return the frames and associated Bidi levels of * the characters logically before and after a (collapsed) selection. * * @param aNode is the node containing the selection * @param aContentOffset is the offset of the selection in the node * @param aJumpLines * If true, look across line boundaries. * If false, behave as if there were base-level frames at line edges. * * @return A struct holding the before/after frame and the before/after * level. * * At the beginning and end of each line there is assumed to be a frame with * Bidi level equal to the paragraph embedding level. * * In these cases the before frame and after frame respectively will be * nullptr. */ nsPrevNextBidiLevels GetPrevNextBidiLevels(nsIContent* aNode, uint32_t aContentOffset, bool aJumpLines) const; /** * GetFrameFromLevel will scan in a given direction * until it finds a frame with a Bidi level less than or equal to a given * level. It will return the last frame before this. * * @param aPresContext is the context to use * @param aFrameIn is the frame to start from * @param aDirection is the direction to scan * @param aBidiLevel is the level to search for * @param aFrameOut will hold the frame returned */ nsresult GetFrameFromLevel(nsIFrame* aFrameIn, nsDirection aDirection, nsBidiLevel aBidiLevel, nsIFrame** aFrameOut) const; /** * MaintainSelection will track the current selection as being "sticky". * Dragging or extending selection will never allow for a subset * (or the whole) of the maintained selection to become unselected. * Primary use: double click selecting then dragging on second click * * @param aAmount the initial amount of text selected (word, line or * paragraph). For "line", use eSelectBeginLine. */ nsresult MaintainSelection(nsSelectionAmount aAmount = eSelectNoAmount); nsresult ConstrainFrameAndPointToAnchorSubtree(nsIFrame* aFrame, const nsPoint& aPoint, nsIFrame** aRetFrame, nsPoint& aRetPoint); nsFrameSelection(); void StartBatchChanges(); MOZ_CAN_RUN_SCRIPT_BOUNDARY void EndBatchChanges(int16_t aReason = nsISelectionListener::NO_REASON); /*unsafe*/ nsresult DeleteFromDocument(); nsIPresShell* GetShell() const { return mShell; } void DisconnectFromPresShell(); nsresult ClearNormalSelection(); private: ~nsFrameSelection(); MOZ_CAN_RUN_SCRIPT nsresult TakeFocus(nsIContent* aNewFocus, uint32_t aContentOffset, uint32_t aContentEndOffset, CaretAssociateHint aHint, bool aContinueSelection, bool aMultipleSelection); void BidiLevelFromMove(nsIPresShell* aPresShell, nsIContent* aNode, uint32_t aContentOffset, nsSelectionAmount aAmount, CaretAssociateHint aHint); void BidiLevelFromClick(nsIContent* aNewFocus, uint32_t aContentOffset); nsPrevNextBidiLevels GetPrevNextBidiLevels(nsIContent* aNode, uint32_t aContentOffset, CaretAssociateHint aHint, bool aJumpLines) const; bool AdjustForMaintainedSelection(nsIContent* aContent, int32_t aOffset); // post and pop reasons for notifications. we may stack these later void PostReason(int16_t aReason) { mSelectionChangeReason = aReason; } int16_t PopReason() { int16_t retval = mSelectionChangeReason; mSelectionChangeReason = nsISelectionListener::NO_REASON; return retval; } bool IsUserSelectionReason() const { return (mSelectionChangeReason & (nsISelectionListener::DRAG_REASON | nsISelectionListener::MOUSEDOWN_REASON | nsISelectionListener::MOUSEUP_REASON | nsISelectionListener::KEYPRESS_REASON)) != nsISelectionListener::NO_REASON; } friend class mozilla::dom::Selection; friend class mozilla::SelectionChangeEventDispatcher; friend struct mozilla::AutoPrepareFocusRange; #ifdef DEBUG void printSelection(); // for debugging #endif /* DEBUG */ void ResizeBuffer(uint32_t aNewBufSize); /*HELPER METHODS*/ // Whether MoveCaret should use logical or visual movement, // or follow the bidi.edit.caret_movement_style preference. enum CaretMovementStyle { eLogical, eVisual, eUsePrefStyle }; MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult MoveCaret(nsDirection aDirection, bool aContinueSelection, nsSelectionAmount aAmount, CaretMovementStyle aMovementStyle); nsresult FetchDesiredPos( nsPoint& aDesiredPos); // the position requested by the Key Handling for // up down void InvalidateDesiredPos(); // do not listen to mDesiredPos you must get another. void SetDesiredPos(nsPoint aPos); // set the mDesiredPos uint32_t GetBatching() const { return mBatching; } bool GetNotifyFrames() const { return mNotifyFrames; } void SetDirty(bool aDirty = true) { if (mBatching) mChangesDuringBatching = aDirty; } // nsFrameSelection may get deleted when calling this, // so remember to use nsCOMPtr when needed. MOZ_CAN_RUN_SCRIPT nsresult NotifySelectionListeners(mozilla::SelectionType aSelectionType); // Update the selection cache on repaint when the // selection being repainted is not empty. nsresult UpdateSelectionCacheOnRepaintSelection( mozilla::dom::Selection* aSel); // Table selection support. nsITableCellLayout* GetCellLayout(nsIContent* aCellContent) const; nsresult SelectBlockOfCells(nsIContent* aStartNode, nsIContent* aEndNode); nsresult SelectRowOrColumn(nsIContent* aCellContent, mozilla::TableSelection aTarget); nsresult UnselectCells(nsIContent* aTable, int32_t aStartRowIndex, int32_t aStartColumnIndex, int32_t aEndRowIndex, int32_t aEndColumnIndex, bool aRemoveOutsideOfCellRange); nsresult GetCellIndexes(nsIContent* aCell, int32_t& aRowIndex, int32_t& aColIndex); // Get our first range, if its first selected node is a cell. If this does // not return null, then the first node in the returned range is a cell // (according to GetFirstCellNodeInRange). nsRange* GetFirstCellRange(); // Get our next range, if its first selected node is a cell. If this does // not return null, then the first node in the returned range is a cell // (according to GetFirstCellNodeInRange). nsRange* GetNextCellRange(); nsIContent* GetFirstCellNodeInRange(nsRange* aRange) const; // Returns non-null table if in same table, null otherwise nsIContent* IsInSameTable(nsIContent* aContent1, nsIContent* aContent2) const; // Might return null nsIContent* GetParentTable(nsIContent* aCellNode) const; nsresult CreateAndAddRange(nsINode* aContainer, int32_t aOffset); ////////////BEGIN nsFrameSelection members RefPtr mDomSelections[sizeof(mozilla::kPresentSelectionTypes) / sizeof(mozilla::SelectionType)]; nsCOMPtr mCellParent; // used to snap to table selection nsCOMPtr mStartSelectedCell; nsCOMPtr mEndSelectedCell; nsCOMPtr mAppendStartSelectedCell; nsCOMPtr mUnselectCellOnMouseUp; mozilla::TableSelection mSelectingTableCellMode = mozilla::TableSelection::None; int32_t mSelectedCellIndex = 0; // maintain selection RefPtr mMaintainRange; nsSelectionAmount mMaintainedAmount = eSelectNoAmount; // batching int32_t mBatching = 0; // Limit selection navigation to a child of this node. nsCOMPtr mLimiter; // Limit selection navigation to a descendant of this node. nsCOMPtr mAncestorLimiter; nsIPresShell* mShell = nullptr; // Reason for notifications of selection changing. int16_t mSelectionChangeReason = nsISelectionListener::NO_REASON; // For visual display purposes. int16_t mDisplaySelection = nsISelectionController::SELECTION_OFF; // Hint to tell if the selection is at the end of this line or beginning of // next. CaretAssociateHint mHint = mozilla::CARET_ASSOCIATE_BEFORE; nsBidiLevel mCaretBidiLevel = BIDI_LEVEL_UNDEFINED; nsBidiLevel mKbdBidiLevel = NSBIDI_LTR; nsPoint mDesiredPos; bool mDelayedMouseEventValid = false; // These values are not used since they are only valid when // mDelayedMouseEventValid is true, and setting mDelayedMouseEventValid // always overrides these values. uint32_t mDelayedMouseEventClickCount = 0; bool mDelayedMouseEventIsShift = false; bool mChangesDuringBatching = false; bool mNotifyFrames = true; bool mDragSelectingCells = false; bool mDragState = false; // for drag purposes bool mMouseDoubleDownState = false; // has the doubleclick down happened bool mDesiredPosSet = false; bool mAccessibleCaretEnabled = false; int8_t mCaretMovementStyle = 0; static bool sSelectionEventsEnabled; static bool sSelectionEventsOnTextControlsEnabled; }; #endif /* nsFrameSelection_h___ */