forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			816 lines
		
	
	
	
		
			32 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			816 lines
		
	
	
	
		
			32 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- 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<SelectionDetails> mNext;
 | |
| };
 | |
| 
 | |
| struct SelectionCustomColors
 | |
| {
 | |
| #ifdef NS_BUILD_REFCNT_LOGGING
 | |
|   SelectionCustomColors()
 | |
|   {
 | |
|     MOZ_COUNT_CTOR(SelectionCustomColors);
 | |
|   }
 | |
|   ~SelectionCustomColors()
 | |
|   {
 | |
|     MOZ_COUNT_DTOR(SelectionCustomColors);
 | |
|   }
 | |
| #endif
 | |
|   mozilla::Maybe<nscolor> mForegroundColor;
 | |
|   mozilla::Maybe<nscolor> mBackgroundColor;
 | |
|   mozilla::Maybe<nscolor> mAltForegroundColor;
 | |
|   mozilla::Maybe<nscolor> 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
 | |
| {
 | |
|   nsPeekOffsetStruct(nsSelectionAmount aAmount,
 | |
|                      nsDirection aDirection,
 | |
|                      int32_t aStartOffset,
 | |
|                      nsPoint aDesiredPos,
 | |
|                      bool aJumpLines,
 | |
|                      bool aScrollViewStop,
 | |
|                      bool aIsKeyboardSelect,
 | |
|                      bool aVisual,
 | |
|                      bool aExtend,
 | |
|                      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.
 | |
| 
 | |
|   // mAmount: The type of movement requested (by character, word, line, etc.)
 | |
|   nsSelectionAmount mAmount;
 | |
| 
 | |
|   // mDirection: 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;
 | |
| 
 | |
|   // mStartOffset: Offset into the content of the current frame where the peek starts.
 | |
|   //               Used with: eSelectCharacter, eSelectWord
 | |
|   int32_t mStartOffset;
 | |
| 
 | |
|   // mDesiredPos: 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;
 | |
| 
 | |
|   // mWordMovementType: 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;
 | |
| 
 | |
|   // mJumpLines: Whether to allow jumping across line boundaries.
 | |
|   //             Used with: eSelectCharacter, eSelectWord.
 | |
|   bool mJumpLines;
 | |
| 
 | |
|   // mScrollViewStop: Whether to stop when reaching a scroll view boundary.
 | |
|   //                  Used with: eSelectCharacter, eSelectWord, eSelectLine.
 | |
|   bool mScrollViewStop;
 | |
| 
 | |
|   // mIsKeyboardSelect: Whether the peeking is done in response to a keyboard action.
 | |
|   //                    Used with: eSelectWord.
 | |
|   bool mIsKeyboardSelect;
 | |
| 
 | |
|   // mVisual: Whether bidi caret behavior is visual (true) or logical (false).
 | |
|   //          Used with: eSelectCharacter, eSelectWord, eSelectBeginLine, eSelectEndLine.
 | |
|   bool mVisual;
 | |
| 
 | |
|   // mExtend: Whether the selection is being extended or moved.
 | |
|   bool mExtend;
 | |
| 
 | |
|   /*** Output arguments ***/
 | |
| 
 | |
|   // mResultContent: Content reached as a result of the peek.
 | |
|   nsCOMPtr<nsIContent> mResultContent;
 | |
| 
 | |
|   // mResultFrame: Frame reached as a result of the peek.
 | |
|   //               Used with: eSelectCharacter, eSelectWord.
 | |
|   nsIFrame *mResultFrame;
 | |
| 
 | |
|   // mContentOffset: Offset into content reached as a result of the peek.
 | |
|   int32_t mContentOffset;
 | |
| 
 | |
|   // mAttachForward: 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 {
 | |
| namespace dom {
 | |
| class Selection;
 | |
| class SelectionChangeListener;
 | |
| } // 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
 | |
|    */
 | |
|   /*unsafe*/
 | |
|   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);
 | |
| 
 | |
|   /** StopAutoScrollTimer stops any active auto scroll timer.
 | |
|    */
 | |
|   void StopAutoScrollTimer();
 | |
| 
 | |
|   /** Lookup Selection
 | |
|    *  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<SelectionDetails> LookUpSelection(nsIContent *aContent,
 | |
|                                                        int32_t aContentOffset,
 | |
|                                                        int32_t aContentLength,
 | |
|                                                        bool aSlowCheck) const;
 | |
| 
 | |
|   /** SetDragState(bool);
 | |
|    *  sets the drag state to aState for resons of drag state.
 | |
|    * @param aState is the new state of drag
 | |
|    */
 | |
|   /*unsafe*/
 | |
|   void SetDragState(bool aState);
 | |
| 
 | |
|   /** GetDragState(bool *);
 | |
|    *  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;
 | |
|   }
 | |
| 
 | |
|   /** GetSelection
 | |
|    * 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);
 | |
| 
 | |
|   /** GetFrameForNodeOffset 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;
 | |
| 
 | |
|   /**
 | |
|    * 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 aScrollableFrame the frame to scroll
 | |
|    */
 | |
|   /*unsafe*/
 | |
|   void CommonPageMove(bool aForward,
 | |
|                       bool aExtend,
 | |
|                       nsIScrollableFrame* aScrollableFrame);
 | |
| 
 | |
|   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
 | |
|    */
 | |
|   /*unsafe*/
 | |
|   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.
 | |
|    * @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; }
 | |
|   /*unsafe*/
 | |
|   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
 | |
|    *  @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();
 | |
|   void EndBatchChanges(int16_t aReason = nsISelectionListener::NO_REASON);
 | |
| 
 | |
|   /*unsafe*/
 | |
|   nsresult DeleteFromDocument();
 | |
| 
 | |
|   nsIPresShell *GetShell()const  { return mShell; }
 | |
| 
 | |
|   void DisconnectFromPresShell();
 | |
|   nsresult ClearNormalSelection();
 | |
| 
 | |
| private:
 | |
|   ~nsFrameSelection();
 | |
| 
 | |
|   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::dom::SelectionChangeListener;
 | |
|   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
 | |
|   };
 | |
|   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.
 | |
|   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<mozilla::dom::Selection>
 | |
|     mDomSelections[
 | |
|       sizeof(mozilla::kPresentSelectionTypes) / sizeof(mozilla::SelectionType)];
 | |
| 
 | |
|   nsCOMPtr<nsINode> mCellParent; //used to snap to table selection
 | |
|   nsCOMPtr<nsIContent> mStartSelectedCell;
 | |
|   nsCOMPtr<nsIContent> mEndSelectedCell;
 | |
|   nsCOMPtr<nsIContent> mAppendStartSelectedCell;
 | |
|   nsCOMPtr<nsIContent> mUnselectCellOnMouseUp;
 | |
|   mozilla::TableSelection mSelectingTableCellMode = mozilla::TableSelection::None;
 | |
|   int32_t  mSelectedCellIndex = 0;
 | |
| 
 | |
|   // maintain selection
 | |
|   RefPtr<nsRange> mMaintainRange;
 | |
|   nsSelectionAmount mMaintainedAmount = eSelectNoAmount;
 | |
| 
 | |
|   //batching
 | |
|   int32_t mBatching = 0;
 | |
| 
 | |
|   // Limit selection navigation to a child of this node.
 | |
|   nsCOMPtr<nsIContent> mLimiter;
 | |
|   // Limit selection navigation to a descendant of this node.
 | |
|   nsCOMPtr<nsIContent> 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___ */
 | 
