Back to index

lightning-sunbird  0.9+nobinonly
Public Types | Public Member Functions | Private Member Functions | Private Attributes | Friends
nsSelection Class Reference
Inheritance diagram for nsSelection:
Inheritance graph
[legend]
Collaboration diagram for nsSelection:
Collaboration graph
[legend]

List of all members.

Public Types

enum  HINT { HINTLEFT = 0, HINTRIGHT = 1 }

Public Member Functions

NS_DECL_ISUPPORTS NS_IMETHOD Init (nsIPresShell *aShell, nsIContent *aLimiter)
 Init will initialize the frame selector with the necessary pres shell to be used by most of the methods.
NS_IMETHOD SetScrollableView (nsIScrollableView *aScrollView)
NS_IMETHOD GetScrollableView (nsIScrollableView **aScrollView)
NS_IMETHOD ShutDown ()
 ShutDown will be called when the owner of the frame selection is shutting down this should be the time to release all member variable interfaces.
NS_IMETHOD HandleTextEvent (nsGUIEvent *aGUIEvent)
 HandleKeyEvent will accept an event.
NS_IMETHOD HandleKeyEvent (nsPresContext *aPresContext, nsGUIEvent *aGuiEvent)
 This raises a question, if this method is called and the aFrame does not reflect the current focus DomNode, it is invalid? The answer now is yes.
NS_IMETHOD HandleClick (nsIContent *aNewFocus, PRUint32 aContentOffset, PRUint32 aContentEndOffset, PRBool aContinueSelection, PRBool aMultipleSelection, PRBool aHint)
 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.
NS_IMETHOD HandleDrag (nsPresContext *aPresContext, nsIFrame *aFrame, nsPoint &aPoint)
 HandleDrag extends the selection to contain the frame closest to aPoint.
NS_IMETHOD HandleTableSelection (nsIContent *aParentContent, PRInt32 aContentOffset, PRInt32 aTarget, nsMouseEvent *aMouseEvent)
 HandleTableSelection will set selection to a table, cell, etc depending on information contained in aFlags.
NS_IMETHOD StartAutoScrollTimer (nsPresContext *aPresContext, nsIView *aView, nsPoint &aPoint, PRUint32 aDelay)
 StartAutoScrollTimer is responsible for scrolling views so that aPoint is always visible, and for selecting any frame that contains aPoint.
NS_IMETHOD StopAutoScrollTimer ()
 StopAutoScrollTimer stops any active auto scroll timer.
NS_IMETHOD EnableFrameNotification (PRBool aEnable)
 EnableFrameNotification mutch like start batching, except all dirty calls are ignored.
NS_IMETHOD LookUpSelection (nsIContent *aContent, PRInt32 aContentOffset, PRInt32 aContentLength, SelectionDetails **aReturnDetails, PRBool aSlowCheck)
 Lookup Selection returns in frame coordinates the selection beginning and ending with the type of selection given.
NS_IMETHOD SetMouseDownState (PRBool aState)
 SetMouseDownState(PRBool); sets the mouse state to aState for resons of drag state.
NS_IMETHOD GetMouseDownState (PRBool *aState)
 GetMouseDownState(PRBool *); gets the mouse state to aState for resons of drag state.
NS_IMETHOD GetTableCellSelection (PRBool *aState)
 if we are in table cell selection mode.
NS_IMETHOD ClearTableCellSelection ()
NS_IMETHOD GetSelection (SelectionType aType, nsISelection **aDomSelection)
 GetSelection no query interface for selection.
NS_IMETHOD ScrollSelectionIntoView (SelectionType aType, SelectionRegion aRegion, PRBool aIsSynchronous)
 ScrollSelectionIntoView scrolls a region of the selection, so that it is visible in the scrolled view.
NS_IMETHOD RepaintSelection (nsPresContext *aPresContext, SelectionType aType)
 RepaintSelection repaints the selected frames that are inside the selection specified by aSelectionType.
NS_IMETHOD GetFrameForNodeOffset (nsIContent *aNode, PRInt32 aOffset, HINT aHint, nsIFrame **aReturnFrame, PRInt32 *aReturnOffset)
 GetFrameForNodeOffset given a node and its child offset, return the nsIFrame and the offset into that frame.
NS_IMETHOD CommonPageMove (PRBool aForward, PRBool aExtend, nsIScrollableView *aScrollableView, nsIFrameSelection *aFrameSel)
 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.
NS_IMETHOD AdjustOffsetsFromStyle (nsIFrame *aFrame, PRBool *changeSelection, nsIContent **outContent, PRInt32 *outStartOffset, PRInt32 *outEndOffset)
 AdjustOffsetsFromStyle.
NS_IMETHOD SetHint (HINT aHintRight)
NS_IMETHOD GetHint (HINT *aHintRight)
NS_IMETHOD CharacterMove (PRBool aForward, PRBool aExtend)
 CharacterMove will generally be called from the nsiselectioncontroller implementations.
NS_IMETHOD WordMove (PRBool aForward, PRBool aExtend)
 WordMove will generally be called from the nsiselectioncontroller implementations.
NS_IMETHOD LineMove (PRBool aForward, PRBool aExtend)
 LineMove will generally be called from the nsiselectioncontroller implementations.
NS_IMETHOD IntraLineMove (PRBool aForward, PRBool aExtend)
 IntraLineMove will generally be called from the nsiselectioncontroller implementations.
NS_IMETHOD SelectAll ()
 Select All will generally be called from the nsiselectioncontroller implementations.
NS_IMETHOD SetDisplaySelection (PRInt16 aState)
 Sets/Gets The display selection enum.
NS_IMETHOD GetDisplaySelection (PRInt16 *aState)
NS_IMETHOD SetDelayCaretOverExistingSelection (PRBool aDelay)
 Allow applications to specify how we should place the caret when the user clicks over an existing selection.
NS_IMETHOD GetDelayCaretOverExistingSelection (PRBool *aDelay)
 Get the current delay caret setting.
NS_IMETHOD SetDelayedCaretData (nsMouseEvent *aMouseEvent)
 If we are delaying caret placement til MouseUp (see Set/GetDelayCaretOverExistingSelection()), this method can be used to store the data received during the MouseDown so that we can place the caret during the MouseUp event.
NS_IMETHOD GetDelayedCaretData (nsMouseEvent **aMouseEvent)
 Get the delayed MouseDown event data necessary to place the caret during MouseUp processing.
NS_IMETHOD GetLimiter (nsIContent **aLimiterContent)
 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!
NS_IMETHOD SetMouseDoubleDown (PRBool aDoubleDown)
 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 has the double click down happened.
NS_IMETHOD GetMouseDoubleDown (PRBool *aDoubleDown)
 This will return whether the double down flag was set.
NS_IMETHOD GetPrevNextBidiLevels (nsPresContext *aPresContext, nsIContent *aNode, PRUint32 aContentOffset, nsIFrame **aPrevFrame, nsIFrame **aNextFrame, PRUint8 *aPrevLevel, PRUint8 *aNextLevel)
NS_IMETHOD GetFrameFromLevel (nsPresContext *aPresContext, nsIFrame *aFrameIn, nsDirection aDirection, PRUint8 aBidiLevel, nsIFrame **aFrameOut)
NS_IMETHOD MaintainSelection ()
 MaintainSelection will track the current selection as being "sticky".
 nsSelection ()
virtual ~nsSelection ()
NS_IMETHOD StartBatchChanges ()
NS_IMETHOD EndBatchChanges ()
NS_IMETHOD DeleteFromDocument ()
nsIPresShellGetShell ()

Private Member Functions

NS_IMETHOD TakeFocus (nsIContent *aNewFocus, PRUint32 aContentOffset, PRUint32 aContentEndOffset, PRBool aContinueSelection, PRBool aMultipleSelection)
 hard to go from nodes to frames, easy the other way!
void BidiLevelFromMove (nsPresContext *aContext, nsIPresShell *aPresShell, nsIContent *aNode, PRUint32 aContentOffset, PRUint32 aKeycode, HINT aHint)
 After moving the caret, its Bidi level is set according to the following rules:
void BidiLevelFromClick (nsIContent *aNewFocus, PRUint32 aContentOffset)
 BidiLevelFromClick is called when the caret is repositioned by clicking the mouse.
NS_IMETHOD GetPrevNextBidiLevels (nsPresContext *aPresContext, nsIContent *aNode, PRUint32 aContentOffset, HINT aHint, nsIFrame **aPrevFrame, nsIFrame **aNextFrame, PRUint8 *aPrevLevel, PRUint8 *aNextLevel)
PRBool AdjustForMaintainedSelection (nsIContent *aContent, PRInt32 aOffset)
void PostReason (PRInt16 aReason)
PRInt16 PopReason ()
void ResizeBuffer (PRUint32 aNewBufSize)
nsresult MoveCaret (PRUint32 aKeycode, PRBool aContinueSelection, nsSelectionAmount aAmount)
nsresult FetchDesiredX (nscoord &aDesiredX)
void InvalidateDesiredX ()
void SetDesiredX (nscoord aX)
nsresult GetRootForContentSubtree (nsIContent *aContent, nsIContent **aParent)
nsresult ConstrainFrameAndPointToAnchorSubtree (nsPresContext *aPresContext, nsIFrame *aFrame, nsPoint &aPoint, nsIFrame **aRetFrame, nsPoint &aRetPoint)
PRUint32 GetBatching ()
PRBool GetNotifyFrames ()
void SetDirty (PRBool aDirty=PR_TRUE)
nsresult NotifySelectionListeners (SelectionType aType)
nsresult FrameOrParentHasSpecialSelectionStyle (nsIFrame *aFrame, PRUint8 aSelectionStyle, nsIFrame **foundFrame)
nsITableLayoutGetTableLayout (nsIContent *aTableContent)
nsITableCellLayoutGetCellLayout (nsIContent *aCellContent)
nsresult SelectBlockOfCells (nsIContent *aStartNode, nsIContent *aEndNode)
nsresult SelectRowOrColumn (nsIContent *aCellContent, PRUint32 aTarget)
nsresult GetCellIndexes (nsIContent *aCell, PRInt32 &aRowIndex, PRInt32 &aColIndex)
nsresult GetFirstSelectedCellAndRange (nsIDOMNode **aCell, nsIDOMRange **aRange)
nsresult GetNextSelectedCellAndRange (nsIDOMNode **aCell, nsIDOMRange **aRange)
nsresult GetFirstCellNodeInRange (nsIDOMRange *aRange, nsIDOMNode **aCellNode)
PRBool IsInSameTable (nsIContent *aContent1, nsIContent *aContent2, nsIContent **aTableNode)
nsresult GetParentTable (nsIContent *aCellNode, nsIContent **aTableNode)
nsresult SelectCellElement (nsIDOMElement *aCellElement)
nsresult CreateAndAddRange (nsIDOMNode *aParentNode, PRInt32 aOffset)
nsresult ClearNormalSelection ()

Private Attributes

nsTypedSelectionmDomSelections [nsISelectionController::NUM_SELECTIONTYPES]
nsCOMPtr< nsIDOMNodemCellParent
nsCOMPtr< nsIContentmStartSelectedCell
nsCOMPtr< nsIContentmEndSelectedCell
nsCOMPtr< nsIContentmAppendStartSelectedCell
nsCOMPtr< nsIContentmUnselectCellOnMouseUp
PRInt32 mSelectingTableCellMode
PRInt32 mSelectedCellIndex
nsCOMPtr< nsIDOMRangemMaintainRange
PRInt32 mBatching
nsIContentmLimiter
nsIPresShellmShell
PRInt16 mSelectionChangeReason
PRInt16 mDisplaySelection
HINT mHint
PRInt32 mDesiredX
nsIScrollableViewmScrollView
nsMouseEvent mDelayedMouseEvent
PRPackedBool mDelayCaretOverExistingSelection
PRPackedBool mDelayedMouseEventValid
PRPackedBool mChangesDuringBatching
PRPackedBool mNotifyFrames
PRPackedBool mIsEditor
PRPackedBool mDragSelectingCells
PRPackedBool mMouseDownState
PRPackedBool mMouseDoubleDownState
PRPackedBool mDesiredXSet

Friends

class nsTypedSelection

Detailed Description

Definition at line 371 of file nsSelection.cpp.


Member Enumeration Documentation

enum nsIFrameSelection::HINT [inherited]
Enumerator:
HINTLEFT 
HINTRIGHT 

Definition at line 135 of file nsIFrameSelection.h.

{ HINTLEFT = 0, HINTRIGHT = 1};  //end of this line or beginning of next

Constructor & Destructor Documentation

Definition at line 967 of file nsSelection.cpp.

Here is the call graph for this function:

Definition at line 1015 of file nsSelection.cpp.

Here is the call graph for this function:


Member Function Documentation

PRBool nsSelection::AdjustForMaintainedSelection ( nsIContent aContent,
PRInt32  aOffset 
) [private]

Definition at line 2434 of file nsSelection.cpp.

{
  // Is the desired content and offset currently in selection?
  // If the double click flag is set then don't continue selection if the 
  // desired content and offset are currently inside a selection.
  // This will stop double click then mouse-drag from undoing the desired
  // selecting of a word.
  if (!mMaintainRange)
    return PR_FALSE;

  nsCOMPtr<nsIDOMNode> rangenode;
  PRInt32 rangeOffset;
  mMaintainRange->GetStartContainer(getter_AddRefs(rangenode));
  mMaintainRange->GetStartOffset(&rangeOffset);

  nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aContent);
  if (domNode)
  {
    PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
    nsCOMPtr<nsIDOMNSRange> nsrange = do_QueryInterface(mMaintainRange);
    if (nsrange)
    {
      PRBool insideSelection = PR_FALSE;
      nsrange->IsPointInRange(domNode, aOffset, &insideSelection);

      // Done when we find a range that we are in
      if (insideSelection)
      {
        mDomSelections[index]->Collapse(rangenode, rangeOffset);
        mMaintainRange->GetEndContainer(getter_AddRefs(rangenode));
        mMaintainRange->GetEndOffset(&rangeOffset);
        mDomSelections[index]->Extend(rangenode,rangeOffset);
        return PR_TRUE; // dragging in selection aborted
      }
    }

    PRInt32 relativePosition = nsRange::ComparePoints(rangenode, rangeOffset,
                                                      domNode, aOffset);
    // if == 0 or -1 do nothing if < 0 then we need to swap direction
    if (relativePosition > 0
        && (mDomSelections[index]->GetDirection() == eDirNext))
    {
      mMaintainRange->GetEndContainer(getter_AddRefs(rangenode));
      mMaintainRange->GetEndOffset(&rangeOffset);
      mDomSelections[index]->Collapse(rangenode, rangeOffset);
    }
    else if (relativePosition < 0
             && (mDomSelections[index]->GetDirection() == eDirPrevious))
      mDomSelections[index]->Collapse(rangenode, rangeOffset);
  }

  return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHODIMP nsSelection::AdjustOffsetsFromStyle ( nsIFrame aFrame,
PRBool changeSelection,
nsIContent **  outContent,
PRInt32 outStartOffset,
PRInt32 outEndOffset 
) [virtual]

AdjustOffsetsFromStyle.

Called after detecting that a click or drag will select the frame, this function looks for user-select style on that frame or a parent frame, and adjust the content and offsets accordingly.

Parameters:
aFramethe frame that was clicked
outContentcontent node to be selected
outStartOffsetselection start offset
outEndOffsetselection end offset

Implements nsIFrameSelection.

Definition at line 4130 of file nsSelection.cpp.

{
  
  *changeSelection = PR_FALSE;
  *outContent = nsnull;
  
  nsresult  rv;  
  nsIFrame*   selectAllFrame;
  rv = FrameOrParentHasSpecialSelectionStyle(aFrame, NS_STYLE_USER_SELECT_ALL, &selectAllFrame);
  if (NS_FAILED(rv)) return rv;
  
  if (!selectAllFrame)
    return NS_OK;
  
  nsIContent* selectAllContent = selectAllFrame->GetContent();
  if (selectAllContent)
  {
    nsCOMPtr<nsIContent> parentContent = selectAllContent->GetParent();
    if (parentContent)
    {
      PRInt32 startOffset = parentContent->IndexOf(selectAllContent);

      if (startOffset < 0)
      {
        // hrmm, this is probably anonymous content. Let's go up another level
        // do we need to do this if we get the right frameSelection to start with?
        nsCOMPtr<nsIContent> superParent = parentContent->GetParent();
        if (superParent)
        {
          PRInt32 superStartOffset = superParent->IndexOf(parentContent);
          if (superStartOffset < 0)
            return NS_ERROR_FAILURE;    // give up
        
          parentContent = superParent;
          startOffset = superStartOffset;
        }
      }
      
      NS_IF_ADDREF(*outContent = parentContent);

      *outStartOffset = startOffset;
      *outEndOffset = startOffset + 1;

      *changeSelection = PR_TRUE;
    }    
  }

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsSelection::BidiLevelFromClick ( nsIContent aNode,
PRUint32  aContentOffset 
) [private]

BidiLevelFromClick is called when the caret is repositioned by clicking the mouse.

Parameters:
aNodeis the content node
aContentOffsetis the new caret position, as an offset into aNode

Definition at line 2420 of file nsSelection.cpp.

{
  nsIFrame* clickInFrame=nsnull;
  PRInt32 OffsetNotUsed;

  nsresult result = GetFrameForNodeOffset(aNode, aContentOffset, mHint, &clickInFrame, &OffsetNotUsed);
  if (NS_FAILED(result))
    return;

  mShell->SetCaretBidiLevel(NS_GET_EMBEDDING_LEVEL(clickInFrame));
}

Here is the call graph for this function:

Here is the caller graph for this function:

void nsSelection::BidiLevelFromMove ( nsPresContext aContext,
nsIPresShell aPresShell,
nsIContent aNode,
PRUint32  aContentOffset,
PRUint32  aKeycode,
HINT  aHint 
) [private]

After moving the caret, its Bidi level is set according to the following rules:

After moving over a character with left/right arrow, set to the Bidi level of the last moved over character. After Home and End, set to the paragraph embedding level. After up/down arrow, PageUp/Down, set to the lower level of the 2 surrounding characters. After mouse click, set to the level of the current frame.

The following two methods use GetPrevNextBidiLevels to determine the new Bidi level. BidiLevelFromMove is called when the caret is moved in response to a keyboard event

Parameters:
aContextis the presentation context
aPresShellis the presentation shell
aNodeis the content node
aContentOffsetis the new caret position, as an offset into aNode
aKeycodeis the keyboard event that moved the caret to the new position
aHintis the hint indicating in what logical direction the caret moved

Definition at line 2373 of file nsSelection.cpp.

{
  PRUint8 firstLevel;
  PRUint8 secondLevel;
  PRUint8 currentLevel;
  nsIFrame* firstFrame=nsnull;
  nsIFrame* secondFrame=nsnull;

  aPresShell->GetCaretBidiLevel(&currentLevel);

  switch (aKeycode) {

    // Right and Left: the new cursor Bidi level is the level of the character moved over
    case nsIDOMKeyEvent::DOM_VK_RIGHT:
    case nsIDOMKeyEvent::DOM_VK_LEFT:
      GetPrevNextBidiLevels(aContext, aNode, aContentOffset, aHint, &firstFrame, &secondFrame, &firstLevel, &secondLevel);
      if (HINTLEFT == aHint)
        aPresShell->SetCaretBidiLevel(firstLevel);
      else
        aPresShell->SetCaretBidiLevel(secondLevel);
      break;

      /*
    // Up and Down: the new cursor Bidi level is the smaller of the two surrounding characters      
    case nsIDOMKeyEvent::DOM_VK_UP:
    case nsIDOMKeyEvent::DOM_VK_DOWN:
      GetPrevNextBidiLevels(aContext, aNode, aContentOffset, &firstFrame, &secondFrame, &firstLevel, &secondLevel);
      aPresShell->SetCaretBidiLevel(PR_MIN(firstLevel, secondLevel));
      break;
      */

    default:
      aPresShell->UndefineCaretBidiLevel();
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHODIMP nsSelection::CharacterMove ( PRBool  aForward,
PRBool  aExtend 
) [virtual]

CharacterMove will generally be called from the nsiselectioncontroller implementations.

the effect being the selection will move one character left or right.

Parameters:
aForwardmove forward in document.
aExtendcontinue selection

Implements nsIFrameSelection.

Definition at line 3030 of file nsSelection.cpp.

Here is the call graph for this function:

Definition at line 3183 of file nsSelection.cpp.

Here is the call graph for this function:

Definition at line 400 of file nsSelection.cpp.

NS_IMETHODIMP nsSelection::CommonPageMove ( PRBool  aForward,
PRBool  aExtend,
nsIScrollableView aScrollableView,
nsIFrameSelection aFrameSel 
) [virtual]

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.

Parameters:
aForwardif PR_TRUE, scroll forward if not scroll backward
aExtendif PR_TRUE, extend selection to the new point
aScrollableViewthe view that needs the scrolling
aFrameSelthe nsIFrameSelection of the caller.
Returns:
always NS_OK

Implements nsIFrameSelection.

Definition at line 2938 of file nsSelection.cpp.

{
  if ( !aScrollableView || !aFrameSel)
    return NS_ERROR_NULL_POINTER;
  // expected behavior for PageMove is to scroll AND move the caret
  // and remain relative position of the caret in view. see Bug 4302.

  nsresult result;
  //get the frame from the scrollable view

  nsIFrame* mainframe = nsnull;

  // The view's client data points back to its frame
  nsIView *scrolledView;
  result = aScrollableView->GetScrolledView(scrolledView);

  if (NS_FAILED(result))
    return result;

  if (scrolledView)
    mainframe = NS_STATIC_CAST(nsIFrame*, scrolledView->GetClientData());

  if (!mainframe)
    return NS_ERROR_FAILURE;

  // find out where the caret is.
  // we should know mDesiredX value of nsSelection, but I havent seen that behavior in other windows applications yet.
  nsCOMPtr<nsISelection> domSel;
  aFrameSel->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel));
  
  if (!domSel) 
    return NS_ERROR_UNEXPECTED;
  
  nsCOMPtr<nsICaret> caret;
  nsRect caretPos;
  PRBool isCollapsed;
  result = mShell->GetCaret(getter_AddRefs(caret));
  
  if (NS_FAILED(result)) 
    return result;
  
  nsIView *caretView;
  result = caret->GetCaretCoordinates(nsICaret::eClosestViewCoordinates, domSel, &caretPos, &isCollapsed, &caretView);
  
  if (NS_FAILED(result)) 
    return result;
  
  //need to adjust caret jump by percentage scroll
  nsSize scrollDelta;
  aScrollableView->GetPageScrollDistances(&scrollDelta);

  if (aForward)
    caretPos.y += scrollDelta.height;
  else
    caretPos.y -= scrollDelta.height;

  
  if (caretView)
  {
    caretPos += caretView->GetOffsetTo(scrolledView);
  }
    
  // get a content at desired location
  nsCOMPtr<nsIContent> content;
  PRInt32 startOffset, endOffset;
  PRBool beginFrameContent;
  nsPoint desiredPoint;
  desiredPoint.x = caretPos.x;
  desiredPoint.y = caretPos.y + caretPos.height/2;
  nsPresContext *context = mShell->GetPresContext();
  result = mainframe->GetContentAndOffsetsFromPoint(context, desiredPoint, getter_AddRefs(content), startOffset, endOffset, beginFrameContent);
  
  if (NS_FAILED(result)) 
    return result;
  
  if (!content) 
    return NS_ERROR_UNEXPECTED;

  // scroll one page

  aScrollableView->ScrollByPages(0, aForward ? 1 : -1);
  
  // place the caret
  result = aFrameSel->HandleClick(content, startOffset, startOffset, aExtend, PR_FALSE, PR_TRUE);
  
  return result;
}

Here is the call graph for this function:

nsresult nsSelection::ConstrainFrameAndPointToAnchorSubtree ( nsPresContext aPresContext,
nsIFrame aFrame,
nsPoint aPoint,
nsIFrame **  aRetFrame,
nsPoint aRetPoint 
) [private]

Definition at line 1129 of file nsSelection.cpp.

{
  //
  // The whole point of this method is to return a frame and point that
  // that lie within the same valid subtree as the anchor node's frame,
  // for use with the method GetContentAndOffsetsFromPoint().
  //
  // A valid subtree is defined to be one where all the content nodes in
  // the tree have a valid parent-child relationship.
  //
  // If the anchor frame and aFrame are in the same subtree, aFrame will
  // be returned in aRetFrame. If they are in different subtrees, we
  // return the frame for the root of the subtree.
  //

  if (!aFrame || !aRetFrame)
    return NS_ERROR_NULL_POINTER;

  *aRetFrame = aFrame;
  aRetPoint  = aPoint;

  //
  // Get the frame and content for the selection's anchor point!
  //

  nsresult result;
  nsCOMPtr<nsIDOMNode> anchorNode;
  PRInt32 anchorOffset = 0;
  PRInt32 anchorFrameOffset = 0;

  PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
  if (! mDomSelections[index])
    return NS_ERROR_NULL_POINTER;

  result = mDomSelections[index]->GetAnchorNode(getter_AddRefs(anchorNode));

  if (NS_FAILED(result))
    return result;

  if (!anchorNode)
    return NS_OK;

  result = mDomSelections[index]->GetAnchorOffset(&anchorOffset);

  if (NS_FAILED(result))
    return result;

  nsIFrame *anchorFrame = 0;
  nsCOMPtr<nsIContent> anchorContent = do_QueryInterface(anchorNode);

  if (!anchorContent)
    return NS_ERROR_FAILURE;
  
  result = GetFrameForNodeOffset(anchorContent, anchorOffset, mHint, &anchorFrame, &anchorFrameOffset);

  //
  // Now find the root of the subtree containing the anchor's content.
  //

  nsCOMPtr<nsIContent> anchorRoot;
  result = GetRootForContentSubtree(anchorContent, getter_AddRefs(anchorRoot));

  if (NS_FAILED(result))
    return result;

  //
  // Now find the root of the subtree containing aFrame's content.
  //

  nsIContent* content = aFrame->GetContent();

  if (content)
  {
    nsCOMPtr<nsIContent> contentRoot;

    result = GetRootForContentSubtree(content, getter_AddRefs(contentRoot));

    if (anchorRoot == contentRoot)
    {
      //
      // The anchor and AFrame's root are the same. There
      // is no need to constrain, simply return aFrame.
      //
      *aRetFrame = aFrame;
      return NS_OK;
    }
  }

  //
  // aFrame's root does not match the anchor's root, or there is no
  // content associated with aFrame. Just return the primary frame
  // for the anchor's root. We'll let GetContentAndOffsetsFromPoint()
  // find the closest frame aPoint.
  //

  result = mShell->GetPrimaryFrameFor(anchorRoot, aRetFrame);

  if (NS_FAILED(result))
    return result;

  if (! *aRetFrame)
    return NS_ERROR_FAILURE;

  //
  // Now make sure that aRetPoint is converted to the same coordinate
  // system used by aRetFrame.
  //

  aRetPoint = aPoint + aFrame->GetOffsetTo(*aRetFrame);

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsSelection::CreateAndAddRange ( nsIDOMNode aParentNode,
PRInt32  aOffset 
) [private]

Definition at line 4110 of file nsSelection.cpp.

{
  if (!aParentNode) return NS_ERROR_NULL_POINTER;
  nsCOMPtr<nsIDOMRange> range;
  NS_NewRange(getter_AddRefs(range));
  if (!range) return NS_ERROR_OUT_OF_MEMORY;

  // Set range around child at given offset
  nsresult result = range->SetStart(aParentNode, aOffset);
  if (NS_FAILED(result)) return result;
  result = range->SetEnd(aParentNode, aOffset+1);
  if (NS_FAILED(result)) return result;
  
  PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
  return mDomSelections[index]->AddRange(range);
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 4209 of file nsSelection.cpp.

{
  nsresult res;

  // If we're already collapsed, then set ourselves to include the
  // last item BEFORE the current range, rather than the range itself,
  // before we do the delete.
  PRBool isCollapsed;
  PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
  mDomSelections[index]->GetIsCollapsed( &isCollapsed);
  if (isCollapsed)
  {
    // If the offset is positive, then it's easy:
    if (mDomSelections[index]->FetchFocusOffset() > 0)
    {
      mDomSelections[index]->Extend(mDomSelections[index]->FetchFocusNode(), mDomSelections[index]->FetchFocusOffset() - 1);
    }
    else
    {
      // Otherwise it's harder, have to find the previous node
      printf("Sorry, don't know how to delete across frame boundaries yet\n");
      return NS_ERROR_NOT_IMPLEMENTED;
    }
  }

  // Get an iterator
  nsSelectionIterator iter(mDomSelections[index]);
  res = iter.First();
  if (NS_FAILED(res))
    return res;

  nsCOMPtr<nsIDOMRange> range;
  while (iter.IsDone())
  {
    res = iter.CurrentItem(NS_STATIC_CAST(nsIDOMRange**, getter_AddRefs(range)));
    if (NS_FAILED(res))
      return res;
    res = range->DeleteContents();
    if (NS_FAILED(res))
      return res;
    iter.Next();
  }

  // Collapse to the new location.
  // If we deleted one character, then we move back one element.
  // FIXME  We don't know how to do this past frame boundaries yet.
  if (isCollapsed)
    mDomSelections[index]->Collapse(mDomSelections[index]->FetchAnchorNode(), mDomSelections[index]->FetchAnchorOffset()-1);
  else if (mDomSelections[index]->FetchAnchorOffset() > 0)
    mDomSelections[index]->Collapse(mDomSelections[index]->FetchAnchorNode(), mDomSelections[index]->FetchAnchorOffset());
#ifdef DEBUG
  else
    printf("Don't know how to set selection back past frame boundary\n");
#endif

  return NS_OK;
}

Here is the call graph for this function:

NS_IMETHOD nsSelection::EnableFrameNotification ( PRBool  aEnable) [inline, virtual]

EnableFrameNotification mutch like start batching, except all dirty calls are ignored.

no notifications will go out until enableNotifications with a PR_TRUE is called

Implements nsIFrameSelection.

Definition at line 393 of file nsSelection.cpp.

{mNotifyFrames = aEnable; return NS_OK;}

Definition at line 3098 of file nsSelection.cpp.

Here is the call graph for this function:

nsresult nsSelection::FetchDesiredX ( nscoord aDesiredX) [private]

Definition at line 1031 of file nsSelection.cpp.

{
  if (!mShell)
  {
    NS_ASSERTION(0,"fetch desired X failed\n");
    return NS_ERROR_FAILURE;
  }
  if (mDesiredXSet)
  {
    aDesiredX = mDesiredX;
    return NS_OK;
  }

  nsCOMPtr<nsICaret> caret;
  nsresult result = mShell->GetCaret(getter_AddRefs(caret));
  if (NS_FAILED(result))
    return result;
  if (!caret)
    return NS_ERROR_NULL_POINTER;

  nsRect coord;
  PRBool  collapsed;
  PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
  result = caret->SetCaretDOMSelection(mDomSelections[index]);
  if (NS_FAILED(result))
    return result;

  result = caret->GetCaretCoordinates(nsICaret::eClosestViewCoordinates, mDomSelections[index], &coord, &collapsed, nsnull);
  if (NS_FAILED(result))
    return result;
   
  aDesiredX = coord.x;
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsSelection::FrameOrParentHasSpecialSelectionStyle ( nsIFrame aFrame,
PRUint8  aSelectionStyle,
nsIFrame **  foundFrame 
) [private]

Definition at line 3123 of file nsSelection.cpp.

{
  nsIFrame* thisFrame = aFrame;
  
  while (thisFrame)
  {
    if (thisFrame->GetStyleUIReset()->mUserSelect == aSelectionStyle)
    {
      *foundFrame = thisFrame;
      return NS_OK;
    }
  
    thisFrame = thisFrame->GetParent();
  }
  
  *foundFrame = nsnull;
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRUint32 nsSelection::GetBatching ( ) [inline, private]

Definition at line 524 of file nsSelection.cpp.

{return mBatching;}

Here is the caller graph for this function:

nsresult nsSelection::GetCellIndexes ( nsIContent aCell,
PRInt32 aRowIndex,
PRInt32 aColIndex 
) [private]

Definition at line 3867 of file nsSelection.cpp.

{
  if (!aCell) return NS_ERROR_NULL_POINTER;

  aColIndex=0; // initialize out params
  aRowIndex=0;

  nsITableCellLayout *cellLayoutObject = GetCellLayout(aCell);
  if (!cellLayoutObject)  return NS_ERROR_FAILURE;
  return cellLayoutObject->GetCellIndexes(aRowIndex, aColIndex);
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsITableCellLayout * nsSelection::GetCellLayout ( nsIContent aCellContent) [private]

Definition at line 3153 of file nsSelection.cpp.

{
  // Get frame for cell
  nsIFrame *cellFrame = nsnull;
  mShell->GetPrimaryFrameFor(aCellContent, &cellFrame);
  if (!cellFrame)
    return nsnull;

  nsITableCellLayout *cellLayoutObject = nsnull;
  CallQueryInterface(cellFrame, &cellLayoutObject);

  return cellLayoutObject;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Get the current delay caret setting.

If aDelay contains a return value of PR_TRUE, the caret is placed on MouseUp when clicking over an existing selection. If PR_FALSE, the selection is cleared and caret is placed immediately in all cases.

Parameters:
aDelaywill contain the return value.

Implements nsIFrameSelection.

Definition at line 4296 of file nsSelection.cpp.

{
  if (!aDelay)
    return NS_ERROR_NULL_POINTER;

  *aDelay =   mDelayCaretOverExistingSelection;

  return NS_OK;
}

Get the delayed MouseDown event data necessary to place the caret during MouseUp processing.

will contain a pointer to the event received by the selection during MouseDown processing. It can be NULL if the data is no longer valid.

Implements nsIFrameSelection.

Definition at line 4324 of file nsSelection.cpp.

{
  if (!aMouseEvent)
    return NS_ERROR_NULL_POINTER;

  if (mDelayedMouseEventValid)
    *aMouseEvent = &mDelayedMouseEvent;
  else
    *aMouseEvent = 0;

  return NS_OK;
}

Implements nsIFrameSelection.

Definition at line 4276 of file nsSelection.cpp.

{
  if (!aToggle)
    return NS_ERROR_INVALID_ARG;
  *aToggle = mDisplaySelection;
  return NS_OK;
}

Here is the caller graph for this function:

nsresult nsSelection::GetFirstCellNodeInRange ( nsIDOMRange aRange,
nsIDOMNode **  aCellNode 
) [private]

Definition at line 3747 of file nsSelection.cpp.

{
  if (!aRange || !aCellNode) return NS_ERROR_NULL_POINTER;

  *aCellNode = nsnull;

  nsCOMPtr<nsIDOMNode> startParent;
  nsresult result = aRange->GetStartContainer(getter_AddRefs(startParent));
  if (NS_FAILED(result))
    return result;
  if (!startParent)
    return NS_ERROR_FAILURE;

  PRInt32 offset;
  result = aRange->GetStartOffset(&offset);
  if (NS_FAILED(result))
    return result;

  nsCOMPtr<nsIContent> parentContent = do_QueryInterface(startParent);
  nsCOMPtr<nsIContent> childContent = parentContent->GetChildAt(offset);
  if (!childContent)
    return NS_ERROR_NULL_POINTER;
  // Don't return node if not a cell
  if (!IsCell(childContent)) return NS_OK;

  nsCOMPtr<nsIDOMNode> childNode = do_QueryInterface(childContent);
  if (childNode)
  {
    *aCellNode = childNode;
    NS_ADDREF(*aCellNode);
  }
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3782 of file nsSelection.cpp.

{
  if (!aCell) return NS_ERROR_NULL_POINTER;
  *aCell = nsnull;

  // aRange is optional
  if (aRange)
    *aRange = nsnull;

  nsCOMPtr<nsIDOMRange> firstRange;
  PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
  nsresult result = mDomSelections[index]->GetRangeAt(0, getter_AddRefs(firstRange));
  if (NS_FAILED(result)) return result;
  if (!firstRange) return NS_ERROR_FAILURE;

  nsCOMPtr<nsIDOMNode> cellNode;
  result = GetFirstCellNodeInRange(firstRange, getter_AddRefs(cellNode));
  if (NS_FAILED(result)) return result;
  if (!cellNode) return NS_OK;

  *aCell = cellNode;
  NS_ADDREF(*aCell);
  if (aRange)
  {
    *aRange = firstRange;
    NS_ADDREF(*aRange);
  }

  // Setup for next cell
  mSelectedCellIndex = 1;

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHODIMP nsSelection::GetFrameForNodeOffset ( nsIContent aNode,
PRInt32  aOffset,
HINT  aHint,
nsIFrame **  aReturnFrame,
PRInt32 aReturnOffset 
) [virtual]

GetFrameForNodeOffset given a node and its child offset, return the nsIFrame and the offset into that frame.

Parameters:
aNodeinput parameter for the node to look at
aOffsetoffset into above node.
aReturnFramewill contain the return frame. MUST NOT BE NULL or will return error
aReturnOffsetwill contain offset into frame.

Implements nsIFrameSelection.

Definition at line 2830 of file nsSelection.cpp.

{
  if (!aNode || !aReturnFrame || !aReturnOffset)
    return NS_ERROR_NULL_POINTER;

  if (aOffset < 0)
    return NS_ERROR_FAILURE;

  *aReturnOffset = aOffset;

  nsresult result = NS_OK;

  nsCOMPtr<nsIContent> theNode = aNode;

  if (aNode->IsContentOfType(nsIContent::eELEMENT))
  {
    PRInt32 childIndex  = 0;
    PRInt32 numChildren = 0;

    if (aHint == HINTLEFT)
    {
      if (aOffset > 0)
        childIndex = aOffset - 1;
      else
        childIndex = aOffset;
    }
    else // HINTRIGHT
    {
      numChildren = theNode->GetChildCount();

      if (aOffset >= numChildren)
      {
        if (numChildren > 0)
          childIndex = numChildren - 1;
        else
          childIndex = 0;
      }
      else
        childIndex = aOffset;
    }
    
    nsCOMPtr<nsIContent> childNode = theNode->GetChildAt(childIndex);

    if (!childNode)
      return NS_ERROR_FAILURE;

    theNode = childNode;

#ifdef DONT_DO_THIS_YET
    // XXX: We can't use this code yet because the hinting
    //      can cause us to attatch to the wrong line frame.

    // Now that we have the child node, check if it too
    // can contain children. If so, call this method again!

    if (theNode->IsContentOfType(nsIContent::eELEMENT))
    {
      PRInt32 newOffset = 0;

      if (aOffset > childIndex)
      {
        numChildren = theNode->GetChildCount();

        newOffset = numChildren;
      }

      return GetFrameForNodeOffset(theNode, newOffset, aHint, aReturnFrame,aReturnOffset);
    }
    else
#endif // DONT_DO_THIS_YET
    {
      // Check to see if theNode is a text node. If it is, translate
      // aOffset into an offset into the text node.

      nsCOMPtr<nsIDOMText> textNode = do_QueryInterface(theNode);

      if (textNode)
      {
        if (aOffset > childIndex)
        {
          PRUint32 textLength = 0;

          result = textNode->GetLength(&textLength);

          if (NS_FAILED(result))
            return NS_ERROR_FAILURE;

          *aReturnOffset = (PRInt32)textLength;
        }
        else
          *aReturnOffset = 0;
      }
    }
  }
  
  result = mShell->GetPrimaryFrameFor(theNode, aReturnFrame);
  if (NS_FAILED(result))
    return result;

  if (!*aReturnFrame)
    return NS_ERROR_UNEXPECTED;

  // find the child frame containing the offset we want
  result = (*aReturnFrame)->GetChildFrameContainingOffset(*aReturnOffset, aHint, &aOffset, aReturnFrame);
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHODIMP nsSelection::GetFrameFromLevel ( nsPresContext aPresContext,
nsIFrame aFrameIn,
nsDirection  aDirection,
PRUint8  aBidiLevel,
nsIFrame **  aFrameOut 
)

Definition at line 2281 of file nsSelection.cpp.

{
  PRUint8 foundLevel = 0;
  nsIFrame *foundFrame = aFrameIn;

  nsCOMPtr<nsIBidirectionalEnumerator> frameTraversal;
  nsresult result;
  nsCOMPtr<nsIFrameTraversal> trav(do_CreateInstance(kFrameTraversalCID,&result));
  if (NS_FAILED(result))
      return result;

  result = trav->NewFrameTraversal(getter_AddRefs(frameTraversal),LEAF, aPresContext, aFrameIn);
  if (NS_FAILED(result))
    return result;
  nsISupports *isupports = nsnull;

  do {
    *aFrameOut = foundFrame;
    if (aDirection == eDirNext)
      result = frameTraversal->Next();
    else 
      result = frameTraversal->Prev();

    if (NS_FAILED(result))
      return result;
    result = frameTraversal->CurrentItem(&isupports);
    if (NS_FAILED(result))
      return result;
    if (!isupports)
      return NS_ERROR_NULL_POINTER;
    //we must CAST here to an nsIFrame. nsIFrame doesnt really follow the rules
    //for speed reasons
    foundFrame = (nsIFrame *)isupports;
    foundLevel = NS_GET_EMBEDDING_LEVEL(foundFrame);

  } while (foundLevel > aBidiLevel);

  return NS_OK;
}

Here is the call graph for this function:

NS_IMETHODIMP nsSelection::GetHint ( HINT aHintRight) [virtual]

Implements nsIFrameSelection.

Definition at line 4190 of file nsSelection.cpp.

{
  *aHintRight = mHint;
  return NS_OK; 
}

Here is the caller graph for this function:

NS_IMETHODIMP nsSelection::GetLimiter ( nsIContent **  aLimiterContent) [virtual]

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!

Implements nsIFrameSelection.

Definition at line 4339 of file nsSelection.cpp.

{
  if (!aLimiterContent) return NS_ERROR_NULL_POINTER;
  *aLimiterContent = mLimiter;
  NS_IF_ADDREF(*aLimiterContent);

  return NS_OK;
}

Here is the caller graph for this function:

This will return whether the double down flag was set.

is the return boolean value

Implements nsIFrameSelection.

Definition at line 4356 of file nsSelection.cpp.

{
  *aDoubleDown = mMouseDoubleDownState;
  return NS_OK;
}

GetMouseDownState(PRBool *); gets the mouse state to aState for resons of drag state.

Parameters:
aStatewill hold the state of mousedown

Implements nsIFrameSelection.

Definition at line 2784 of file nsSelection.cpp.

{
  if (!aState)
    return NS_ERROR_NULL_POINTER;
  *aState = mMouseDownState;
  return NS_OK;
}

Definition at line 3817 of file nsSelection.cpp.

{
  if (!aCell) return NS_ERROR_NULL_POINTER;
  *aCell = nsnull;

  // aRange is optional
  if (aRange)
    *aRange = nsnull;

  PRInt32 rangeCount;
  PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
  nsresult result = mDomSelections[index]->GetRangeCount(&rangeCount);
  if (NS_FAILED(result)) return result;

  // Don't even try if index exceeds range count
  if (mSelectedCellIndex >= rangeCount) 
  {
    // Should we reset index? 
    // Maybe better to force recalling GetFirstSelectedCell()
    //mSelectedCellIndex = 0;
    return NS_OK;
  }

  // Get first node in next range of selection - test if it's a cell
  nsCOMPtr<nsIDOMRange> range;
  result = mDomSelections[index]->GetRangeAt(mSelectedCellIndex, getter_AddRefs(range));
  if (NS_FAILED(result)) return result;
  if (!range) return NS_ERROR_FAILURE;

  nsCOMPtr<nsIDOMNode> cellNode;
  result = GetFirstCellNodeInRange(range, getter_AddRefs(cellNode));
  if (NS_FAILED(result)) return result;
  // No cell in selection range
  if (!cellNode) return NS_OK;

  *aCell = cellNode;
  NS_ADDREF(*aCell);
  if (aRange)
  {
    *aRange = range;
    NS_ADDREF(*aRange);
  }

  // Setup for next cell
  mSelectedCellIndex++;

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRBool nsSelection::GetNotifyFrames ( ) [inline, private]

Definition at line 525 of file nsSelection.cpp.

{return mNotifyFrames;}
nsresult nsSelection::GetParentTable ( nsIContent aCellNode,
nsIContent **  aTableNode 
) [private]

Definition at line 3909 of file nsSelection.cpp.

{
  if (!aCell || !aTable) {
    return NS_ERROR_NULL_POINTER;
  }

  for (nsIContent* parent = aCell->GetParent(); parent;
       parent = parent->GetParent()) {
    if (parent->Tag() == nsHTMLAtoms::table &&
        parent->IsContentOfType(nsIContent::eHTML)) {
      *aTable = parent;
      NS_ADDREF(*aTable);

      return NS_OK;
    }
  }

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHODIMP nsSelection::GetPrevNextBidiLevels ( nsPresContext aPresContext,
nsIContent aNode,
PRUint32  aContentOffset,
nsIFrame **  aPrevFrame,
nsIFrame **  aNextFrame,
PRUint8 aPrevLevel,
PRUint8 aNextLevel 
)

Definition at line 2095 of file nsSelection.cpp.

{
  return GetPrevNextBidiLevels(aPresContext, aNode, aContentOffset, mHint,
                               aPrevFrame, aNextFrame, aPrevLevel, aNextLevel);
}

Here is the caller graph for this function:

NS_IMETHODIMP nsSelection::GetPrevNextBidiLevels ( nsPresContext aPresContext,
nsIContent aNode,
PRUint32  aContentOffset,
HINT  aHint,
nsIFrame **  aPrevFrame,
nsIFrame **  aNextFrame,
PRUint8 aPrevLevel,
PRUint8 aNextLevel 
) [private]

Definition at line 2108 of file nsSelection.cpp.

{
  if (!aPrevFrame || !aNextFrame)
    return NS_ERROR_NULL_POINTER;
  // Get the level of the frames on each side
  nsIFrame    *currentFrame;
  PRInt32     currentOffset;
  PRInt32     frameStart, frameEnd;
  nsDirection direction;
  nsresult    result;

  *aPrevLevel = *aNextLevel = 0;

  result = GetFrameForNodeOffset(aNode, aContentOffset, aHint, &currentFrame, &currentOffset);
  if (NS_FAILED(result))
    return result;
  currentFrame->GetOffsets(frameStart, frameEnd);

  if (0 == frameStart && 0 == frameEnd)
    direction = eDirPrevious;
  else if (frameStart == currentOffset)
    direction = eDirPrevious;
  else if (frameEnd == currentOffset)
    direction = eDirNext;
  else {
    // we are neither at the beginning nor at the end of the frame, so we have no worries
    *aPrevFrame = *aNextFrame = currentFrame;
    *aPrevLevel = *aNextLevel = NS_GET_EMBEDDING_LEVEL(currentFrame);
    return NS_OK;
  }

  /*
  we have to find the next or previous *logical* frame.

  Unfortunately |GetFrameFromDirection| has already been munged to return the next/previous *visual* frame, so we can't use that.
  The following code is taken from there without the Bidi changes.

  XXX is there a simpler way to do this? 
  */

  nsIFrame *blockFrame = currentFrame;
  nsIFrame *thisBlock = nsnull;
  PRInt32   thisLine;
  nsILineIteratorNavigator* it;  // This is qi'd off a frame, and those aren't
                                 // refcounted
  result = NS_ERROR_FAILURE;
  while (NS_FAILED(result) && blockFrame)
  {
    thisBlock = blockFrame;
    blockFrame = blockFrame->GetParent();
    if (blockFrame) {
      result = CallQueryInterface(blockFrame, &it);
    }
  }
  if (!blockFrame || !it)
    return NS_ERROR_FAILURE;
  result = it->FindLineContaining(thisBlock, &thisLine);
  if (NS_FAILED(result))
    return result;

  if (thisLine < 0) 
    return NS_ERROR_FAILURE;

  nsIFrame *firstFrame;
  nsIFrame *lastFrame;
  nsRect    nonUsedRect;
  PRInt32   lineFrameCount;
  PRUint32  lineFlags;

  result = it->GetLine(thisLine, &firstFrame, &lineFrameCount,nonUsedRect,
                       &lineFlags);
  if (NS_FAILED(result))
    return result;

  lastFrame = firstFrame;

  for (;lineFrameCount > 1;lineFrameCount --) {
    lastFrame = lastFrame->GetNextSibling();
  }

  // GetFirstLeaf
  nsIFrame *lookahead;
  while (1) {
    lookahead = firstFrame->GetFirstChild(nsnull);
    if (!lookahead)
      break; //nothing to do
    firstFrame = lookahead;
  }

  // GetLastLeaf
  while (1) {
    lookahead = lastFrame->GetFirstChild(nsnull);
    if (!lookahead)
      break; //nothing to do
    lastFrame = lookahead;
    while ((lookahead = lastFrame->GetNextSibling()) != nsnull)
      lastFrame = lookahead;
  }
  //END LINE DATA CODE

  if (direction == eDirNext && lastFrame == currentFrame) { // End of line: set aPrevFrame to the current frame
                                                            //              set aPrevLevel to the embedding level of the current frame
                                                            //              set aNextFrame to null
                                                            //              set aNextLevel to the paragraph embedding level
    *aPrevFrame = currentFrame;
    *aPrevLevel = NS_GET_EMBEDDING_LEVEL(currentFrame);
    *aNextLevel = NS_GET_BASE_LEVEL(currentFrame);
    *aNextFrame = nsnull;
    return NS_OK;
  }

  if (direction == eDirPrevious && firstFrame == currentFrame) { // Beginning of line: set aPrevFrame to null
                                                                 //                    set aPrevLevel to the paragraph embedding level
                                                                 //                    set aNextFrame to the current frame
                                                                 //                    set aNextLevel to the embedding level of the current frame
    *aNextFrame = currentFrame;
    *aNextLevel = NS_GET_EMBEDDING_LEVEL(currentFrame);
    *aPrevLevel = NS_GET_BASE_LEVEL(currentFrame);
    *aPrevFrame = nsnull;
    return NS_OK;
  }

  // Find the adjacent frame

  nsCOMPtr<nsIBidirectionalEnumerator> frameTraversal;
  nsCOMPtr<nsIFrameTraversal> trav(do_CreateInstance(kFrameTraversalCID,&result));
  if (NS_FAILED(result))
    return result;

  result = trav->NewFrameTraversal(getter_AddRefs(frameTraversal),LEAF, aPresContext, currentFrame);
  if (NS_FAILED(result))
    return result;
  nsISupports *isupports = nsnull;
  if (direction == eDirNext)
    result = frameTraversal->Next();
  else 
    result = frameTraversal->Prev();

  if (NS_FAILED(result))
    return result;
  result = frameTraversal->CurrentItem(&isupports);
  if (NS_FAILED(result))
    return result;
  if (!isupports)
    return NS_ERROR_NULL_POINTER;
  //we must CAST here to an nsIFrame. nsIFrame doesnt really follow the rules
  //for speed reasons
  nsIFrame *newFrame = (nsIFrame *)isupports;

  if (direction == eDirNext) {
    *aPrevFrame = currentFrame;
    *aPrevLevel = NS_GET_EMBEDDING_LEVEL(currentFrame);
    *aNextFrame = newFrame;
    *aNextLevel = NS_GET_EMBEDDING_LEVEL(newFrame);
  }
  else {
    *aNextFrame = currentFrame;
    *aNextLevel = NS_GET_EMBEDDING_LEVEL(currentFrame);
    *aPrevFrame = newFrame;
    *aPrevLevel = NS_GET_EMBEDDING_LEVEL(newFrame);
  }

  return NS_OK;

}

Here is the call graph for this function:

nsresult nsSelection::GetRootForContentSubtree ( nsIContent aContent,
nsIContent **  aParent 
) [private]

Definition at line 1084 of file nsSelection.cpp.

{
  // This method returns the root of the sub-tree containing aContent.
  // We do this by searching up through the parent hierarchy, and stopping
  // when there are no more parents, or we hit a situation where the
  // parent/child relationship becomes invalid.
  //
  // An example of an invalid parent/child relationship is anonymous content.
  // Anonymous content has a pointer to it's parent, but it is not listed
  // as a child of it's parent. In this case, the anonymous content would
  // be considered the root of the subtree.

  if (!aContent || !aParent)
    return NS_ERROR_NULL_POINTER;

  *aParent = 0;

  nsIContent* child = aContent;

  while (child)
  {
    nsIContent* parent = child->GetParent();

    if (!parent)
      break;

    PRUint32 childCount = parent->GetChildCount();

    if (childCount < 1)
      break;

    PRInt32 childIndex = parent->IndexOf(child);

    if (childIndex < 0 || ((PRUint32)childIndex) >= childCount)
      break;

    child = parent;
  }

  NS_IF_ADDREF(*aParent = child);

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHOD nsSelection::GetScrollableView ( nsIScrollableView **  aScrollView) [inline, virtual]

Implements nsIFrameSelection.

Definition at line 382 of file nsSelection.cpp.

{*aScrollView = mScrollView; return NS_OK;}

Here is the caller graph for this function:

NS_IMETHODIMP nsSelection::GetSelection ( SelectionType  aSelectionType,
nsISelection **  aSelection 
) [virtual]

GetSelection no query interface for selection.

must use this method now.

Parameters:
aSelectionTypeenum value defined in nsISelection for the seleciton you want.

Implements nsIFrameSelection.

Definition at line 2793 of file nsSelection.cpp.

{
  if (!aDomSelection)
    return NS_ERROR_NULL_POINTER;
  PRInt8 index = GetIndexFromSelectionType(aType);
  if (index < 0)
    return NS_ERROR_INVALID_ARG;
  *aDomSelection = NS_REINTERPRET_CAST(nsISelection *,mDomSelections[index]);
  NS_ADDREF(*aDomSelection);
  return NS_OK;
}

Here is the call graph for this function:

Definition at line 451 of file nsSelection.cpp.

{return mShell;}

Here is the caller graph for this function:

NS_IMETHOD nsSelection::GetTableCellSelection ( PRBool aState) [inline, virtual]

if we are in table cell selection mode.

aka ctrl click in table cell

Implements nsIFrameSelection.

Definition at line 399 of file nsSelection.cpp.

{if (aState){*aState = mSelectingTableCellMode != 0; return NS_OK;}return NS_ERROR_NULL_POINTER;}

Here is the caller graph for this function:

nsITableLayout * nsSelection::GetTableLayout ( nsIContent aTableContent) [private]

Definition at line 3168 of file nsSelection.cpp.

{
  // Get frame for table
  nsIFrame *tableFrame = nsnull;
  mShell->GetPrimaryFrameFor(aTableContent, &tableFrame);
  if (!tableFrame)
    return nsnull;

  nsITableLayout *tableLayoutObject = nsnull;
  CallQueryInterface(tableFrame, &tableLayoutObject);

  return tableLayoutObject;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHODIMP nsSelection::HandleClick ( nsIContent aNewFocus,
PRUint32  aContentOffset,
PRUint32  aContentEndOffset,
PRBool  aContinueSelection,
PRBool  aMultipleSelection,
PRBool  aHint 
) [virtual]

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

Parameters:
aNewfocusis the content that wants the focus
aContentOffsetis the content offset of the parent aNewFocus
aContentOffsetEndis the content offset of the parent aNewFocus and is specified different when you need to select to and include both start and end points
aContinueSelectionis the flag that tells the selection to keep the old anchor point or not.
aMultipleSelectionwill tell the frame selector to replace /or not the old selection. cannot coexist with aContinueSelection
aHintwill tell the selection which direction geometrically to actually show the caret on. 1 = end of this line 0 = beggining of this line

Implements nsIFrameSelection.

Definition at line 2490 of file nsSelection.cpp.

{
  if (!aNewFocus)
    return NS_ERROR_INVALID_ARG;

  InvalidateDesiredX();

  if (!aContinueSelection)
    mMaintainRange = nsnull;

  mHint = HINT(aHint);
  // Don't take focus when dragging off of a table
  if (!mDragSelectingCells)
  {
    BidiLevelFromClick(aNewFocus, aContentOffset);
    PostReason(nsISelectionListener::MOUSEDOWN_REASON + nsISelectionListener::DRAG_REASON);
    if (aContinueSelection &&
        AdjustForMaintainedSelection(aNewFocus, aContentOffset))
      return NS_OK; //shift clicked to maintained selection. rejected.

    return TakeFocus(aNewFocus, aContentOffset, aContentEndOffset, aContinueSelection, aMultipleSelection);
  }
  
  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHODIMP nsSelection::HandleDrag ( nsPresContext aPresContext,
nsIFrame aFrame,
nsPoint aPoint 
) [virtual]

HandleDrag extends the selection to contain the frame closest to aPoint.

Parameters:
aPresContextis the context to use when figuring out what frame contains the point.
aFrameis the parent of all frames to use when searching for the closest frame to the point.
aPointis relative to aFrame's parent view.

Implements nsIFrameSelection.

Definition at line 2519 of file nsSelection.cpp.

{
  if (!aPresContext || !aFrame)
    return NS_ERROR_NULL_POINTER;

  nsresult result;
  nsIFrame *newFrame = 0;
  nsPoint   newPoint;

  result = ConstrainFrameAndPointToAnchorSubtree(aPresContext, aFrame, aPoint, &newFrame, newPoint);
  if (NS_FAILED(result))
    return result;
  if (!newFrame)
    return NS_ERROR_FAILURE;

  PRInt32 startPos = 0;
  PRInt32 contentOffsetEnd = 0;
  PRBool  beginOfContent;
  nsCOMPtr<nsIContent> newContent;

  result = newFrame->GetContentAndOffsetsFromPoint(aPresContext, newPoint,
                                                   getter_AddRefs(newContent), 
                                                   startPos, contentOffsetEnd, beginOfContent);

  if ((newFrame->GetStateBits() & NS_FRAME_SELECTED_CONTENT) &&
       AdjustForMaintainedSelection(newContent, startPos))
    return NS_OK;

  // do we have CSS that changes selection behaviour?
  {
    //add scope for nsCOMPtr
    PRBool    changeSelection;
    nsCOMPtr<nsIContent>  selectContent;
    PRInt32   newStart, newEnd;
    if (NS_SUCCEEDED(AdjustOffsetsFromStyle(newFrame, &changeSelection, getter_AddRefs(selectContent), &newStart, &newEnd))
      && changeSelection)
    {
      newContent = selectContent;
      startPos = newStart;
      contentOffsetEnd = newEnd;
    }
  }

  if (NS_SUCCEEDED(result))
  {
#ifdef VISUALSELECTION
    if (aPresContext->BidiEnabled()) {
      PRUint8 level;
      nsPeekOffsetStruct pos;
      //set data using mLimiter to stop on scroll views.  If we have a limiter then we stop peeking
      //when we hit scrollable views.  If no limiter then just let it go ahead
      pos.SetData(mShell, 0, eSelectDir, eDirNext, startPos, PR_FALSE,
                  PR_TRUE, PR_TRUE, mLimiter != nsnull, PR_FALSE);
      mHint = HINT(beginOfContent);
      HINT saveHint = mHint;
      if (NS_GET_EMBEDDING_LEVEL(newFrame) & 1)
        mHint = (mHint==HINTLEFT) ? HINTRIGHT : HINTLEFT;
      pos.mResultContent = newContent;
      pos.mContentOffset = contentOffsetEnd;
      result = VisualSelectFrames(aPresContext, newFrame, pos);
      if (NS_FAILED(result))
        result = HandleClick(newContent, startPos, contentOffsetEnd, PR_TRUE,
                             PR_FALSE, beginOfContent);
      mHint = saveHint;
    }
    else
#endif // VISUALSELECTION
      result = HandleClick(newContent, startPos, contentOffsetEnd, PR_TRUE,
                           PR_FALSE, beginOfContent);
  }

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHODIMP nsSelection::HandleKeyEvent ( nsPresContext aPresContext,
nsGUIEvent aGuiEvent 
) [virtual]

This raises a question, if this method is called and the aFrame does not reflect the current focus DomNode, it is invalid? The answer now is yes.

Implements nsIFrameSelection.

Definition at line 1575 of file nsSelection.cpp.

{
  if (!aGuiEvent)
    return NS_ERROR_NULL_POINTER;
  STATUS_CHECK_RETURN_MACRO();

  nsresult result = NS_ERROR_FAILURE;
  if (NS_KEY_PRESS == aGuiEvent->message) {
    nsKeyEvent *keyEvent = (nsKeyEvent *)aGuiEvent; //this is ok. It really is a keyevent
    switch (keyEvent->keyCode)
    {
        case nsIDOMKeyEvent::DOM_VK_LEFT  : 
        case nsIDOMKeyEvent::DOM_VK_UP    :
        case nsIDOMKeyEvent::DOM_VK_DOWN  : 
        case nsIDOMKeyEvent::DOM_VK_RIGHT    :
        case nsIDOMKeyEvent::DOM_VK_HOME  : 
        case nsIDOMKeyEvent::DOM_VK_END    :
          break;
        default:
           return NS_ERROR_FAILURE;
    }

//XXX Need xp way get platfrom specific behavior into key navigation.
//XXX This really shouldn't have to use an ifdef
#ifdef _WIN32
    if (keyEvent->isAlt) {
      return NS_ERROR_FAILURE;
    }
#endif
    nsSelectionAmount amount = eSelectCharacter;
    if (keyEvent->isControl)
      amount = eSelectWord;
    return MoveCaret(keyEvent->keyCode, keyEvent->isShift, amount);
  }
  return result;
}

Here is the call graph for this function:

nsresult nsSelection::HandleTableSelection ( nsIContent aParentContent,
PRInt32  aContentOffset,
PRInt32  aTarget,
nsMouseEvent aMouseEvent 
) [virtual]

HandleTableSelection will set selection to a table, cell, etc depending on information contained in aFlags.

Parameters:
aParentContentis the paretent of either a table or cell that user clicked or dragged the mouse in
aContentOffsetis the offset of the table or cell
aTargetindicates what to select (defined in nsISelectionPrivate.idl/nsISelectionPrivate.h): 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)
aMouseEventpassed in so we we can get where event occured and what keys are pressed

Implements nsIFrameSelection.

Definition at line 3192 of file nsSelection.cpp.

{
  NS_ENSURE_TRUE(aParentContent, NS_ERROR_NULL_POINTER);
  NS_ENSURE_TRUE(aMouseEvent, NS_ERROR_NULL_POINTER);

  if (mMouseDownState && mDragSelectingCells && (aTarget & nsISelectionPrivate::TABLESELECTION_TABLE))
  {
    // We were selecting cells and user drags mouse in table border or inbetween cells,
    //  just do nothing
      return NS_OK;
  }

  nsCOMPtr<nsIDOMNode> parentNode = do_QueryInterface(aParentContent);
  if (!parentNode)
    return NS_ERROR_FAILURE;

  nsresult result = NS_OK;

  nsIContent *childContent = aParentContent->GetChildAt(aContentOffset);
  nsCOMPtr<nsIDOMNode> childNode = do_QueryInterface(childContent);
  if (!childNode)
    return NS_ERROR_FAILURE;

  // When doing table selection, always set the direction to next so
  // we can be sure that anchorNode's offset always points to the
  // selected cell
  PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
  mDomSelections[index]->SetDirection(eDirNext);

  // Stack-class to wrap all table selection changes in 
  //  BeginBatchChanges() / EndBatchChanges()
  nsSelectionBatcher selectionBatcher(mDomSelections[index]);

  PRInt32 startRowIndex, startColIndex, curRowIndex, curColIndex;
  if (mMouseDownState && mDragSelectingCells)
  {
    // We are drag-selecting
    if (aTarget != nsISelectionPrivate::TABLESELECTION_TABLE)
    {
      // If dragging in the same cell as last event, do nothing
      if (mEndSelectedCell == childContent)
        return NS_OK;

#ifdef DEBUG_TABLE_SELECTION
printf(" mStartSelectedCell = %x, mEndSelectedCell = %x, childContent = %x \n", mStartSelectedCell, mEndSelectedCell, childContent);
#endif
      // aTarget can be any "cell mode",
      //  so we can easily drag-select rows and columns 
      // Once we are in row or column mode,
      //  we can drift into any cell to stay in that mode
      //  even if aTarget = TABLESELECTION_CELL

      if (mSelectingTableCellMode == nsISelectionPrivate::TABLESELECTION_ROW ||
          mSelectingTableCellMode == nsISelectionPrivate::TABLESELECTION_COLUMN)
      {
        if (mEndSelectedCell)
        {
          // Also check if cell is in same row/col
          result = GetCellIndexes(mEndSelectedCell, startRowIndex, startColIndex);
          if (NS_FAILED(result)) return result;
          result = GetCellIndexes(childContent, curRowIndex, curColIndex);
          if (NS_FAILED(result)) return result;
        
#ifdef DEBUG_TABLE_SELECTION
printf(" curRowIndex = %d, startRowIndex = %d, curColIndex = %d, startColIndex = %d\n", curRowIndex, startRowIndex, curColIndex, startColIndex);
#endif
          if ((mSelectingTableCellMode == nsISelectionPrivate::TABLESELECTION_ROW && startRowIndex == curRowIndex) ||
              (mSelectingTableCellMode == nsISelectionPrivate::TABLESELECTION_COLUMN && startColIndex == curColIndex)) 
            return NS_OK;
        }
#ifdef DEBUG_TABLE_SELECTION
printf(" Dragged into a new column or row\n");
#endif
        // Continue dragging row or column selection
        return SelectRowOrColumn(childContent, mSelectingTableCellMode);
      }
      else if (mSelectingTableCellMode == nsISelectionPrivate::TABLESELECTION_CELL)
      {
#ifdef DEBUG_TABLE_SELECTION
printf("HandleTableSelection: Dragged into a new cell\n");
#endif
        // Trick for quick selection of rows and columns
        // Hold down shift, then start selecting in one direction
        // If next cell dragged into is in same row, select entire row,
        //   if next cell is in same column, select entire column
        if (mStartSelectedCell && aMouseEvent->isShift)
        {
          result = GetCellIndexes(mStartSelectedCell, startRowIndex, startColIndex);
          if (NS_FAILED(result)) return result;
          result = GetCellIndexes(childContent, curRowIndex, curColIndex);
          if (NS_FAILED(result)) return result;
          
          if (startRowIndex == curRowIndex || 
              startColIndex == curColIndex)
          {
            // Force new selection block
            mStartSelectedCell = nsnull;
            mDomSelections[index]->RemoveAllRanges();

            if (startRowIndex == curRowIndex)
              mSelectingTableCellMode = nsISelectionPrivate::TABLESELECTION_ROW;
            else
              mSelectingTableCellMode = nsISelectionPrivate::TABLESELECTION_COLUMN;

            return SelectRowOrColumn(childContent, mSelectingTableCellMode);
          }
        }
        
        // Reselect block of cells to new end location
        return SelectBlockOfCells(mStartSelectedCell, childContent);
      }
    }
    // Do nothing if dragging in table, but outside a cell
    return NS_OK;
  }
  else 
  {
    // Not dragging  -- mouse event is down or up
    if (mMouseDownState)
    {
#ifdef DEBUG_TABLE_SELECTION
printf("HandleTableSelection: Mouse down event\n");
#endif
      // Clear cell we stored in mouse-down
      mUnselectCellOnMouseUp = nsnull;
      
      if (aTarget == nsISelectionPrivate::TABLESELECTION_CELL)
      {
        PRBool isSelected = PR_FALSE;

        // Check if we have other selected cells
        nsCOMPtr<nsIDOMNode> previousCellNode;
        GetFirstSelectedCellAndRange(getter_AddRefs(previousCellNode), nsnull);
        if (previousCellNode)
        {
          // We have at least 1 other selected cell

          // Check if new cell is already selected
          nsIFrame  *cellFrame = nsnull;
          result = mShell->GetPrimaryFrameFor(childContent, &cellFrame);
          if (NS_FAILED(result)) return result;
          if (!cellFrame) return NS_ERROR_NULL_POINTER;
          result = cellFrame->GetSelected(&isSelected);
          if (NS_FAILED(result)) return result;
        }
        else
        {
          // No cells selected -- remove non-cell selection
          mDomSelections[index]->RemoveAllRanges();
        }
        mDragSelectingCells = PR_TRUE;    // Signal to start drag-cell-selection
        mSelectingTableCellMode = aTarget;
        // Set start for new drag-selection block (not appended)
        mStartSelectedCell = childContent;
        // The initial block end is same as the start
        mEndSelectedCell = childContent;
        
        if (isSelected)
        {
          // Remember this cell to (possibly) unselect it on mouseup
          mUnselectCellOnMouseUp = childContent;
#ifdef DEBUG_TABLE_SELECTION
printf("HandleTableSelection: Saving mUnselectCellOnMouseUp\n");
#endif
        }
        else
        {
          // Select an unselected cell
          // but first remove existing selection if not in same table
          nsCOMPtr<nsIContent> previousCellContent = do_QueryInterface(previousCellNode);
          if (previousCellContent && !IsInSameTable(previousCellContent, childContent, nsnull))
          {
            mDomSelections[index]->RemoveAllRanges();
            // Reset selection mode that is cleared in RemoveAllRanges
            mSelectingTableCellMode = aTarget;
          }

          nsCOMPtr<nsIDOMElement> cellElement = do_QueryInterface(childContent);
          return SelectCellElement(cellElement);
        }

        return NS_OK;
      }
      else if (aTarget == nsISelectionPrivate::TABLESELECTION_TABLE)
      {
        //TODO: We currently select entire table when clicked between cells,
        //  should we restrict to only around border?
        //  *** How do we get location data for cell and click?
        mDragSelectingCells = PR_FALSE;
        mStartSelectedCell = nsnull;
        mEndSelectedCell = nsnull;

        // Remove existing selection and select the table
        mDomSelections[index]->RemoveAllRanges();
        return CreateAndAddRange(parentNode, aContentOffset);
      }
      else if (aTarget == nsISelectionPrivate::TABLESELECTION_ROW || aTarget == nsISelectionPrivate::TABLESELECTION_COLUMN)
      {
#ifdef DEBUG_TABLE_SELECTION
printf("aTarget == %d\n", aTarget);
#endif

        // Start drag-selecting mode so multiple rows/cols can be selected
        // Note: Currently, nsFrame::GetDataForTableSelection
        //       will never call us for row or column selection on mouse down
        mDragSelectingCells = PR_TRUE;
      
        // Force new selection block
        mStartSelectedCell = nsnull;
        mDomSelections[index]->RemoveAllRanges();
        // Always do this AFTER RemoveAllRanges
        mSelectingTableCellMode = aTarget;
        return SelectRowOrColumn(childContent, aTarget);
      }
    }
    else
    {
#ifdef DEBUG_TABLE_SELECTION
printf("HandleTableSelection: Mouse UP event. mDragSelectingCells=%d, mStartSelectedCell=%d\n", mDragSelectingCells, mStartSelectedCell);
#endif
      // First check if we are extending a block selection
      PRInt32 rangeCount;
      result = mDomSelections[index]->GetRangeCount(&rangeCount);
      if (NS_FAILED(result)) 
        return result;

      if (rangeCount > 0 && aMouseEvent->isShift && 
          mAppendStartSelectedCell && mAppendStartSelectedCell != childContent)
      {
        // Shift key is down: append a block selection
        mDragSelectingCells = PR_FALSE;
        return SelectBlockOfCells(mAppendStartSelectedCell, childContent);
      }

      if (mDragSelectingCells)
        mAppendStartSelectedCell = mStartSelectedCell;
        
      mDragSelectingCells = PR_FALSE;
      mStartSelectedCell = nsnull;
      mEndSelectedCell = nsnull;

      // Any other mouseup actions require that Ctrl or Cmd key is pressed
      //  else stop table selection mode
      PRBool doMouseUpAction = PR_FALSE;
#if defined(XP_MAC) || defined(XP_MACOSX)
      doMouseUpAction = aMouseEvent->isMeta;
#else
      doMouseUpAction = aMouseEvent->isControl;
#endif
      if (!doMouseUpAction)
      {
#ifdef DEBUG_TABLE_SELECTION
printf("HandleTableSelection: Ending cell selection on mouseup: mAppendStartSelectedCell=%d\n", mAppendStartSelectedCell);
#endif
        return NS_OK;
      }
      // Unselect a cell only if it wasn't
      //  just selected on mousedown
      if( childContent == mUnselectCellOnMouseUp)
      {
        // Scan ranges to find the cell to unselect (the selection range to remove)
        nsCOMPtr<nsIDOMNode> previousCellParent;
        nsCOMPtr<nsIDOMRange> range;
        PRInt32 offset;
#ifdef DEBUG_TABLE_SELECTION
printf("HandleTableSelection: Unselecting mUnselectCellOnMouseUp; rangeCount=%d\n", rangeCount);
#endif
        for( PRInt32 i = 0; i < rangeCount; i++)
        {
          result = mDomSelections[index]->GetRangeAt(i, getter_AddRefs(range));
          if (NS_FAILED(result)) return result;
          if (!range) return NS_ERROR_NULL_POINTER;

          nsCOMPtr<nsIDOMNode> parent;
          result = range->GetStartContainer(getter_AddRefs(parent));
          if (NS_FAILED(result)) return result;
          if (!parent) return NS_ERROR_NULL_POINTER;

          range->GetStartOffset(&offset);
          // Be sure previous selection is a table cell
          nsCOMPtr<nsIContent> parentContent = do_QueryInterface(parent);
          nsCOMPtr<nsIContent> child = parentContent->GetChildAt(offset);
          if (child && IsCell(child))
            previousCellParent = parent;

          // We're done if we didn't find parent of a previously-selected cell
          if (!previousCellParent) break;
        
          if (previousCellParent == parentNode && offset == aContentOffset)
          {
            // Cell is already selected
            if (rangeCount == 1)
            {
#ifdef DEBUG_TABLE_SELECTION
printf("HandleTableSelection: Unselecting single selected cell\n");
#endif
              // This was the only cell selected.
              // Collapse to "normal" selection inside the cell
              mStartSelectedCell = nsnull;
              mEndSelectedCell = nsnull;
              mAppendStartSelectedCell = nsnull;
              //TODO: We need a "Collapse to just before deepest child" routine
              // Even better, should we collapse to just after the LAST deepest child
              //  (i.e., at the end of the cell's contents)?
              return mDomSelections[index]->Collapse(childNode, 0);
            }
#ifdef DEBUG_TABLE_SELECTION
printf("HandleTableSelection: Removing cell from multi-cell selection\n");
#endif
            // Unselecting the start of previous block 
            // XXX What do we use now!
            if (childContent == mAppendStartSelectedCell)
               mAppendStartSelectedCell = nsnull;

            // Deselect cell by removing its range from selection
            return mDomSelections[index]->RemoveRange(range);
          }
        }
        mUnselectCellOnMouseUp = nsnull;
      }
    }
  }
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

HandleKeyEvent will accept an event.

DOES NOT ADDREF

Parameters:
aGuiEventis the event that should be dealt with by aFocusFrame
aFrameis the frame that MAY handle the event

Implements nsIFrameSelection.

Definition at line 1355 of file nsSelection.cpp.

{
  if (!aGUIEvent)
    return NS_ERROR_NULL_POINTER;

#ifdef DEBUG_TAGUE
  printf("nsSelection: HandleTextEvent\n");
#endif
  nsresult result(NS_OK);
  if (NS_TEXT_TEXT == aGUIEvent->message) {
    PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
    result = mDomSelections[index]->ScrollIntoView();
  }
  return result;
}

Here is the call graph for this function:

NS_IMETHODIMP nsSelection::Init ( nsIPresShell aShell,
nsIContent aLimiter 
) [virtual]

Init will initialize the frame selector with the necessary pres shell to be used by most of the methods.

Parameters:
aShellis the parameter to be used for most of the other calls for callbacks ect
aLimiterlimits the selection to nodes with aLimiter parents

Implements nsIFrameSelection.

Definition at line 1328 of file nsSelection.cpp.

NS_IMETHODIMP nsSelection::IntraLineMove ( PRBool  aForward,
PRBool  aExtend 
) [virtual]

IntraLineMove will generally be called from the nsiselectioncontroller implementations.

the effect being the selection will move to beginning or end of line

Parameters:
aForwardmove forward in document.
aExtendcontinue selection

Implements nsIFrameSelection.

Definition at line 3057 of file nsSelection.cpp.

{
  if (aForward)
    return MoveCaret(nsIDOMKeyEvent::DOM_VK_END,aExtend,eSelectLine);
  else
    return MoveCaret(nsIDOMKeyEvent::DOM_VK_HOME,aExtend,eSelectLine);
}

Here is the call graph for this function:

Definition at line 1069 of file nsSelection.cpp.

Here is the caller graph for this function:

PRBool nsSelection::IsInSameTable ( nsIContent aContent1,
nsIContent aContent2,
nsIContent **  aTableNode 
) [private]

Definition at line 3880 of file nsSelection.cpp.

{
  if (!aContent1 || !aContent2) return PR_FALSE;
  
  // aTable is optional:
  if(aTable) *aTable = nsnull;
  
  nsCOMPtr<nsIContent> tableNode1;
  nsCOMPtr<nsIContent> tableNode2;

  nsresult result = GetParentTable(aContent1, getter_AddRefs(tableNode1));
  if (NS_FAILED(result)) return PR_FALSE;
  result = GetParentTable(aContent2, getter_AddRefs(tableNode2));
  if (NS_FAILED(result)) return PR_FALSE;

  // Must be in the same table
  if (tableNode1 && (tableNode1 == tableNode2))
  {
    if (aTable)
    {
      *aTable = tableNode1;
      NS_ADDREF(*aTable);
    }
    return PR_TRUE;;
  }
  return PR_FALSE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHODIMP nsSelection::LineMove ( PRBool  aForward,
PRBool  aExtend 
) [virtual]

LineMove will generally be called from the nsiselectioncontroller implementations.

the effect being the selection will move one line up or down.

Parameters:
aForwardmove forward in document.
aExtendcontinue selection

Implements nsIFrameSelection.

Definition at line 3048 of file nsSelection.cpp.

{
  if (aForward)
    return MoveCaret(nsIDOMKeyEvent::DOM_VK_DOWN,aExtend,eSelectLine);
  else
    return MoveCaret(nsIDOMKeyEvent::DOM_VK_UP,aExtend,eSelectLine);
}

Here is the call graph for this function:

NS_METHOD nsSelection::LookUpSelection ( nsIContent aContent,
PRInt32  aContentOffset,
PRInt32  aContentLength,
SelectionDetails **  aReturnDetails,
PRBool  aSlowCheck 
) [virtual]

Lookup Selection returns in frame coordinates the selection beginning and ending with the type of selection given.

Parameters:
aContentis the content asking
aContentOffsetis the starting content boundary
aContentLengthis the length of the content piece asking
aReturnDetailslinkedlist of return values for the selection.
aSlowCheckwill check using slow method with no shortcuts

Implements nsIFrameSelection.

Definition at line 2743 of file nsSelection.cpp.

{
  if (!aContent || !aReturnDetails)
    return NS_ERROR_NULL_POINTER;

  STATUS_CHECK_RETURN_MACRO();

  *aReturnDetails = nsnull;

  for (PRInt32 j = 0; j < nsISelectionController::NUM_SELECTIONTYPES; j++) {
    if (mDomSelections[j])
      mDomSelections[j]->LookUpSelection(aContent, aContentOffset, aContentLength, aReturnDetails, (SelectionType)(1<<j), aSlowCheck);
  }
  return NS_OK;
}

Here is the call graph for this function:

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

Implements nsIFrameSelection.

Definition at line 2327 of file nsSelection.cpp.

{
  PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
  nsCOMPtr<nsIDOMRange> range;
  nsresult rv = mDomSelections[index]->GetRangeAt(0, getter_AddRefs(range));
  if (NS_FAILED(rv))
    return rv;
  if (!range)
    return NS_ERROR_FAILURE;

  nsCOMPtr<nsIDOMNode> startNode;
  nsCOMPtr<nsIDOMNode> endNode;
  PRInt32 startOffset;
  PRInt32 endOffset;
  range->GetStartContainer(getter_AddRefs(startNode));
  range->GetEndContainer(getter_AddRefs(endNode));
  range->GetStartOffset(&startOffset);
  range->GetEndOffset(&endOffset);

  mMaintainRange = nsnull;
  NS_NewRange(getter_AddRefs(mMaintainRange));
  if (!mMaintainRange)
    return NS_ERROR_OUT_OF_MEMORY;

  mMaintainRange->SetStart(startNode, startOffset);
  return mMaintainRange->SetEnd(endNode, endOffset);
}

Here is the call graph for this function:

nsresult nsSelection::MoveCaret ( PRUint32  aKeycode,
PRBool  aContinueSelection,
nsSelectionAmount  aAmount 
) [private]

Definition at line 1373 of file nsSelection.cpp.

{
  nsPresContext *context = mShell->GetPresContext();
  if (!context)
    return NS_ERROR_FAILURE;

  nsCOMPtr<nsIDOMNode> weakNodeUsed;
  PRInt32 offsetused = 0;

  PRBool isCollapsed;
  nscoord desiredX = 0; //we must keep this around and revalidate it when its just UP/DOWN

  PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
  nsresult result = mDomSelections[index]->GetIsCollapsed(&isCollapsed);
  if (NS_FAILED(result))
    return result;
  if (aKeycode == nsIDOMKeyEvent::DOM_VK_UP || aKeycode == nsIDOMKeyEvent::DOM_VK_DOWN)
  {
    result = FetchDesiredX(desiredX);
    if (NS_FAILED(result))
      return result;
    SetDesiredX(desiredX);
  }

  PRInt32 caretStyle = nsContentUtils::GetIntPref("layout.selection.caret_style", 0);
#ifdef XP_MACOSX
  if (caretStyle == 0) {
    caretStyle = 2; // put caret at the selection edge in the |aKeycode| direction
  }
#endif

  if (!isCollapsed && !aContinueSelection && caretStyle == 2) {
    switch (aKeycode){
      case nsIDOMKeyEvent::DOM_VK_LEFT  :
      case nsIDOMKeyEvent::DOM_VK_UP    :
          if (mDomSelections[index]->GetDirection() == eDirPrevious) { //f,a
            offsetused = mDomSelections[index]->FetchFocusOffset();
            weakNodeUsed = mDomSelections[index]->FetchFocusNode();
          }
          else {
            offsetused = mDomSelections[index]->FetchAnchorOffset();
            weakNodeUsed = mDomSelections[index]->FetchAnchorNode();
          }
          result = mDomSelections[index]->Collapse(weakNodeUsed, offsetused);
          mDomSelections[index]->ScrollIntoView();
          mHint = HINTRIGHT;
          return NS_OK;

      case nsIDOMKeyEvent::DOM_VK_RIGHT :
      case nsIDOMKeyEvent::DOM_VK_DOWN  :
          if (mDomSelections[index]->GetDirection() == eDirPrevious) { //f,a
            offsetused = mDomSelections[index]->FetchAnchorOffset();
            weakNodeUsed = mDomSelections[index]->FetchAnchorNode();
          }
          else {
            offsetused = mDomSelections[index]->FetchFocusOffset();
            weakNodeUsed = mDomSelections[index]->FetchFocusNode();
          }
          result = mDomSelections[index]->Collapse(weakNodeUsed, offsetused);
          mDomSelections[index]->ScrollIntoView();
          mHint = HINTLEFT;
          return NS_OK;
    }
  }

  offsetused = mDomSelections[index]->FetchFocusOffset();
  weakNodeUsed = mDomSelections[index]->FetchFocusNode();

    
  nsIFrame *frame;
  result = mDomSelections[index]->GetPrimaryFrameForFocusNode(&frame, &offsetused);

  if (NS_FAILED(result) || !frame)
    return result?result:NS_ERROR_FAILURE;
  nsCOMPtr<nsIDOMNode> node = do_QueryInterface(frame->GetContent());
  nsCOMPtr<nsIDOMNode> parentNode;
  nsPeekOffsetStruct pos;

  //set data using mLimiter to stop on scroll views.  If we have a limiter then we stop peeking
  //when we hit scrollable views.  If no limiter then just let it go ahead
  pos.SetData(mShell, desiredX, aAmount, eDirPrevious, offsetused, PR_FALSE,
              PR_TRUE, PR_TRUE, mLimiter != nsnull, PR_TRUE);

  HINT tHint(mHint); //temporary variable so we dont set mHint until it is necessary
  switch (aKeycode){
    case nsIDOMKeyEvent::DOM_VK_RIGHT : 
        InvalidateDesiredX();
        pos.mDirection = eDirNext;
        tHint = HINTLEFT;//stick to this line
        PostReason(nsISelectionListener::KEYPRESS_REASON);
      break;
    case nsIDOMKeyEvent::DOM_VK_LEFT  : //no break
        InvalidateDesiredX();
        tHint = HINTRIGHT;//stick to opposite of movement
        PostReason(nsISelectionListener::KEYPRESS_REASON);
      break;
    case nsIDOMKeyEvent::DOM_VK_DOWN : 
        pos.mAmount = eSelectLine;
        pos.mDirection = eDirNext;//no break here
        PostReason(nsISelectionListener::KEYPRESS_REASON);
      break;
    case nsIDOMKeyEvent::DOM_VK_UP : 
        pos.mAmount = eSelectLine;
        PostReason(nsISelectionListener::KEYPRESS_REASON);
      break;
    case nsIDOMKeyEvent::DOM_VK_HOME :
        InvalidateDesiredX();
        pos.mAmount = eSelectBeginLine;
        tHint = HINTRIGHT;//stick to opposite of movement
        PostReason(nsISelectionListener::KEYPRESS_REASON);
      break;
    case nsIDOMKeyEvent::DOM_VK_END :
        InvalidateDesiredX();
        pos.mAmount = eSelectEndLine;
        tHint = HINTLEFT;//stick to this line
        PostReason(nsISelectionListener::KEYPRESS_REASON);
     break;
  default :return NS_ERROR_FAILURE;
  }
  pos.mPreferLeft = tHint;
  if (NS_SUCCEEDED(result) && NS_SUCCEEDED(result = frame->PeekOffset(context, &pos)) && pos.mResultContent)
  {
    tHint = (HINT)pos.mPreferLeft;
    if (context->BidiEnabled())
    {
      nsIFrame *theFrame;
      PRInt32 currentOffset, frameStart, frameEnd;

      // XXX - I expected to be able to use pos.mResultFrame, but when we move from frame to frame
      //       and |PeekOffset| is called recursively, pos.mResultFrame on exit is sometimes set to the original
      //       frame, not the frame that we ended up in, so I need this call to |GetFrameForNodeOffset|.
      //       I don't know if that could or should be changed or if it would break something else.
      GetFrameForNodeOffset(pos.mResultContent, pos.mContentOffset, tHint, &theFrame, &currentOffset);
      theFrame->GetOffsets(frameStart, frameEnd);

      tHint = (HINT)pos.mPreferLeft;
      if (frameStart !=0 || frameEnd !=0) // Otherwise the frame is not a text frame, so nothing more to do
      {
        switch (aKeycode) {
          case nsIDOMKeyEvent::DOM_VK_HOME:
          case nsIDOMKeyEvent::DOM_VK_END:
    
            // force the offset to the logical beginning (for HOME) or end (for END) of the frame
            // (if it is an RTL frame it will be at the visual beginning or end, which we don't want in this case)
            if (nsIDOMKeyEvent::DOM_VK_HOME == aKeycode)
              pos.mContentOffset = frameStart;
            else
              pos.mContentOffset = frameEnd;
    
            // set the cursor Bidi level to the paragraph embedding level
            mShell->SetCaretBidiLevel(NS_GET_BASE_LEVEL(theFrame));
            break;
    
          default:
            // If the current position is not a frame boundary, it's enough just to take the Bidi level of the current frame
            if ((pos.mContentOffset != frameStart && pos.mContentOffset != frameEnd)
                || (eSelectDir == aAmount)
                || (eSelectLine == aAmount))
            {
              mShell->SetCaretBidiLevel(NS_GET_EMBEDDING_LEVEL(theFrame));
            }
            else
              BidiLevelFromMove(context, mShell, pos.mResultContent, pos.mContentOffset, aKeycode, tHint);
        }
      }
#ifdef VISUALSELECTION
      // Handle visual selection
      if (aContinueSelection)
      {
        result = VisualSelectFrames(context, theFrame, pos);
        if (NS_FAILED(result)) // Back out by collapsing the selection to the current position
          result = TakeFocus(pos.mResultContent, pos.mContentOffset, pos.mContentOffset, PR_FALSE, PR_FALSE);
      }    
      else
        result = TakeFocus(pos.mResultContent, pos.mContentOffset, pos.mContentOffset, aContinueSelection, PR_FALSE);
    }
    else
#else
    }
#endif // VISUALSELECTION
    result = TakeFocus(pos.mResultContent, pos.mContentOffset, pos.mContentOffset, aContinueSelection, PR_FALSE);
  } else if (aKeycode == nsIDOMKeyEvent::DOM_VK_RIGHT && !aContinueSelection) {
    // Collapse selection if PeekOffset failed because we bumped into the BRFrame, bug 207623.
    mDomSelections[index]->Collapse(weakNodeUsed, offsetused);
    tHint = mHint; // make the line below restore the original hint
    result = NS_OK;
  }
  if (NS_SUCCEEDED(result))
  {
    mHint = tHint; //save the hint parameter now for the next time
    result = mDomSelections[index]->ScrollIntoView();
  }

  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 3112 of file nsSelection.cpp.

{
  PRInt8 index = GetIndexFromSelectionType(aType);
  if (index >=0)
  {
    return mDomSelections[index]->NotifySelectionListeners();
  }
  return NS_ERROR_FAILURE;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PRInt16 nsSelection::PopReason ( ) [inline, private]

Definition at line 501 of file nsSelection.cpp.

Here is the caller graph for this function:

void nsSelection::PostReason ( PRInt16  aReason) [inline, private]

Definition at line 500 of file nsSelection.cpp.

{ mSelectionChangeReason = aReason; }

Here is the caller graph for this function:

NS_IMETHODIMP nsSelection::RepaintSelection ( nsPresContext aPresContext,
SelectionType  aSelectionType 
) [virtual]

RepaintSelection repaints the selected frames that are inside the selection specified by aSelectionType.

Parameters:
aSelectionTypeenum value defined in nsISelection for the seleciton you want.

Implements nsIFrameSelection.

Definition at line 2819 of file nsSelection.cpp.

{
  PRInt8 index = GetIndexFromSelectionType(aType);
  if (index < 0)
    return NS_ERROR_INVALID_ARG;
  if (!mDomSelections[index])
    return NS_ERROR_NULL_POINTER;
  return mDomSelections[index]->Repaint(aPresContext);
}

Here is the call graph for this function:

void nsSelection::ResizeBuffer ( PRUint32  aNewBufSize) [private]
NS_IMETHODIMP nsSelection::ScrollSelectionIntoView ( SelectionType  aSelectionType,
SelectionRegion  aRegion,
PRBool  aIsSynchronous 
) [virtual]

ScrollSelectionIntoView scrolls a region of the selection, so that it is visible in the scrolled view.

Parameters:
aTypethe selection to scroll into view.
aRegionthe region inside the selection to scroll into view.
aIsSynchronouswhen PR_TRUE, scrolls the selection into view at some point after the method returns.request which is processed

Implements nsIFrameSelection.

Definition at line 2806 of file nsSelection.cpp.

{
  PRInt8 index = GetIndexFromSelectionType(aType);
  if (index < 0)
    return NS_ERROR_INVALID_ARG;

  if (!mDomSelections[index])
    return NS_ERROR_NULL_POINTER;

  return mDomSelections[index]->ScrollIntoView(aRegion, aIsSynchronous);
}

Here is the call graph for this function:

Select All will generally be called from the nsiselectioncontroller implementations.

it will select the whole doc

Implements nsIFrameSelection.

Definition at line 3065 of file nsSelection.cpp.

{
  nsCOMPtr<nsIContent> rootContent;
  if (mLimiter)
  {
    rootContent = mLimiter;//addrefit
  }
  else
  {
    nsIDocument *doc = mShell->GetDocument();
    if (!doc)
      return NS_ERROR_FAILURE;
    rootContent = doc->GetRootContent();
    if (!rootContent)
      return NS_ERROR_FAILURE;
  }
  PRInt32 numChildren = rootContent->GetChildCount();
  PostReason(nsISelectionListener::NO_REASON);
  return TakeFocus(mLimiter, 0, numChildren, PR_FALSE, PR_FALSE);
}

Here is the call graph for this function:

nsresult nsSelection::SelectBlockOfCells ( nsIContent aStartNode,
nsIContent aEndNode 
) [private]

Definition at line 3518 of file nsSelection.cpp.

{
  NS_ENSURE_TRUE(aStartCell, NS_ERROR_NULL_POINTER);
  NS_ENSURE_TRUE(aEndCell, NS_ERROR_NULL_POINTER);
  mEndSelectedCell = aEndCell;

  nsCOMPtr<nsIContent> startCell;
  nsresult result = NS_OK;

  // If new end cell is in a different table, do nothing
  nsCOMPtr<nsIContent> table;
  if (!IsInSameTable(aStartCell, aEndCell, getter_AddRefs(table)))
    return NS_OK;

  // Get starting and ending cells' location in the cellmap
  PRInt32 startRowIndex, startColIndex, endRowIndex, endColIndex;
  result = GetCellIndexes(aStartCell, startRowIndex, startColIndex);
  if(NS_FAILED(result)) return result;
  result = GetCellIndexes(aEndCell, endRowIndex, endColIndex);
  if(NS_FAILED(result)) return result;

  // Get TableLayout interface to access cell data based on cellmap location
  // frames are not ref counted, so don't use an nsCOMPtr
  nsITableLayout *tableLayoutObject = GetTableLayout(table);
  if (!tableLayoutObject) return NS_ERROR_FAILURE;

  PRInt32 curRowIndex, curColIndex;

  if (mDragSelectingCells)
  {
    // Drag selecting: remove selected cells outside of new block limits

    PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);

    nsCOMPtr<nsIDOMNode> cellNode;
    nsCOMPtr<nsIDOMRange> range;
    result = GetFirstSelectedCellAndRange(getter_AddRefs(cellNode), getter_AddRefs(range));
    if (NS_FAILED(result)) return result;

    PRInt32 minRowIndex = PR_MIN(startRowIndex, endRowIndex);
    PRInt32 maxRowIndex = PR_MAX(startRowIndex, endRowIndex);
    PRInt32 minColIndex = PR_MIN(startColIndex, endColIndex);
    PRInt32 maxColIndex = PR_MAX(startColIndex, endColIndex);

    while (cellNode)
    {
      nsCOMPtr<nsIContent> childContent = do_QueryInterface(cellNode);
      result = GetCellIndexes(childContent, curRowIndex, curColIndex);
      if (NS_FAILED(result)) return result;

#ifdef DEBUG_TABLE_SELECTION
if (!range)
printf("SelectBlockOfCells -- range is null\n");
#endif
      if (range &&
          (curRowIndex < minRowIndex || curRowIndex > maxRowIndex || 
           curColIndex < minColIndex || curColIndex > maxColIndex))
      {
        mDomSelections[index]->RemoveRange(range);
        // Since we've removed the range, decrement pointer to next range
        mSelectedCellIndex--;
      }    
      result = GetNextSelectedCellAndRange(getter_AddRefs(cellNode), getter_AddRefs(range));
      if (NS_FAILED(result)) return result;
    }
  }

  nsCOMPtr<nsIDOMElement> cellElement;
  PRInt32 rowSpan, colSpan, actualRowSpan, actualColSpan;
  PRBool  isSelected;

  // Note that we select block in the direction of user's mouse dragging,
  //  which means start cell may be after the end cell in either row or column
  PRInt32 row = startRowIndex;
  while(PR_TRUE)
  {
    PRInt32 col = startColIndex;
    while(PR_TRUE)
    {
      result = tableLayoutObject->GetCellDataAt(row, col, *getter_AddRefs(cellElement),
                                                curRowIndex, curColIndex, rowSpan, colSpan, 
                                                actualRowSpan, actualColSpan, isSelected);
      if (NS_FAILED(result)) return result;

      NS_ASSERTION(actualColSpan, "!actualColSpan is 0!");

      // Skip cells that are spanned from previous locations or are already selected
      if (!isSelected && cellElement && row == curRowIndex && col == curColIndex)
      {
        result = SelectCellElement(cellElement);
        if (NS_FAILED(result)) return result;
      }
      // Done when we reach end column
      if (col == endColIndex) break;

      if (startColIndex < endColIndex)
        col ++;
      else
        col--;
    };
    if (row == endRowIndex) break;

    if (startRowIndex < endRowIndex)
      row++;
    else
      row--;
  };
  return result;
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsSelection::SelectCellElement ( nsIDOMElement aCellElement) [private]

Definition at line 3930 of file nsSelection.cpp.

{
  nsCOMPtr<nsIContent> cellContent = do_QueryInterface(aCellElement);

  if (!cellContent) {
    return NS_ERROR_FAILURE;
  }

  nsIContent *parent = cellContent->GetParent();
  nsCOMPtr<nsIDOMNode> parentNode(do_QueryInterface(parent));
  if (!parentNode) {
    return NS_ERROR_FAILURE;
  }

  // Get child offset
  PRInt32 offset = parent->IndexOf(cellContent);

  return CreateAndAddRange(parentNode, offset);
}

Here is the call graph for this function:

Here is the caller graph for this function:

nsresult nsSelection::SelectRowOrColumn ( nsIContent aCellContent,
PRUint32  aTarget 
) [private]

Definition at line 3629 of file nsSelection.cpp.

{
  if (!aCellContent) return NS_ERROR_NULL_POINTER;

  nsCOMPtr<nsIContent> table;
  nsresult result = GetParentTable(aCellContent, getter_AddRefs(table));
  if (NS_FAILED(result)) return PR_FALSE;
  if (!table) return NS_ERROR_NULL_POINTER;

  // Get table and cell layout interfaces to access 
  //   cell data based on cellmap location
  // Frames are not ref counted, so don't use an nsCOMPtr
  nsITableLayout *tableLayout = GetTableLayout(table);
  if (!tableLayout) return NS_ERROR_FAILURE;
  nsITableCellLayout *cellLayout = GetCellLayout(aCellContent);
  if (!cellLayout) return NS_ERROR_FAILURE;

  // Get location of target cell:      
  PRInt32 rowIndex, colIndex, curRowIndex, curColIndex;
  result = cellLayout->GetCellIndexes(rowIndex, colIndex);
  if (NS_FAILED(result)) return result;

  // Be sure we start at proper beginning
  // (This allows us to select row or col given ANY cell!)
  if (aTarget == nsISelectionPrivate::TABLESELECTION_ROW)
    colIndex = 0;
  if (aTarget == nsISelectionPrivate::TABLESELECTION_COLUMN)
    rowIndex = 0;

  nsCOMPtr<nsIDOMElement> cellElement;
  nsCOMPtr<nsIDOMElement> firstCell;
  nsCOMPtr<nsIDOMElement> lastCell;
  PRInt32 rowSpan, colSpan, actualRowSpan, actualColSpan;
  PRBool isSelected;

  do {
    // Loop through all cells in column or row to find first and last
    result = tableLayout->GetCellDataAt(rowIndex, colIndex, *getter_AddRefs(cellElement),
                                        curRowIndex, curColIndex, rowSpan, colSpan, 
                                        actualRowSpan, actualColSpan, isSelected);
    if (NS_FAILED(result)) return result;
    if (cellElement)
    {
      NS_ASSERTION(actualRowSpan > 0 && actualColSpan> 0, "SelectRowOrColumn: Bad rowspan or colspan\n");
      if (!firstCell)
        firstCell = cellElement;

      lastCell = cellElement;

      // Move to next cell in cellmap, skipping spanned locations
      if (aTarget == nsISelectionPrivate::TABLESELECTION_ROW)
        colIndex += actualColSpan;
      else
        rowIndex += actualRowSpan;
    }
  }
  while (cellElement);

  // Use SelectBlockOfCells:
  // This will replace existing selection,
  //  but allow unselecting by dragging out of selected region
  if (firstCell && lastCell)
  {
    if (!mStartSelectedCell)
    {
      // We are starting a new block, so select the first cell
      result = SelectCellElement(firstCell);
      if (NS_FAILED(result)) return result;
      mStartSelectedCell = do_QueryInterface(firstCell);
    }
    nsCOMPtr<nsIContent> lastCellContent = do_QueryInterface(lastCell);
    result = SelectBlockOfCells(mStartSelectedCell, lastCellContent);

    // This gets set to the cell at end of row/col, 
    //   but we need it to be the cell under cursor
    mEndSelectedCell = aCellContent;
    return result;
  }

#if 0
// This is a more efficient strategy that appends row to current selection,
//  but doesn't allow dragging OFF of an existing selection to unselect!
  do {
    // Loop through all cells in column or row
    result = tableLayout->GetCellDataAt(rowIndex, colIndex,
                                        getter_AddRefs(cellElement),
                                        curRowIndex, curColIndex,
                                        rowSpan, colSpan,
                                        actualRowSpan, actualColSpan,
                                        isSelected);
    if (NS_FAILED(result)) return result;
    // We're done when cell is not found
    if (!cellElement) break;


    // Check spans else we infinitely loop
    NS_ASSERTION(actualColSpan, "actualColSpan is 0!");
    NS_ASSERTION(actualRowSpan, "actualRowSpan is 0!");
    
    // Skip cells that are already selected or span from outside our region
    if (!isSelected && rowIndex == curRowIndex && colIndex == curColIndex)
    {
      result = SelectCellElement(cellElement);
      if (NS_FAILED(result)) return result;
    }
    // Move to next row or column in cellmap, skipping spanned locations
    if (aTarget == nsISelectionPrivate::TABLESELECTION_ROW)
      colIndex += actualColSpan;
    else
      rowIndex += actualRowSpan;
  }
  while (cellElement);
#endif

  return NS_OK;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Allow applications to specify how we should place the caret when the user clicks over an existing selection.

A aDelay value of PR_TRUE means delay clearing the selection and placing the caret until MouseUp, when the user clicks over an existing selection. This is especially usefull when applications want to support Drag & Drop of the current selection. A value of PR_FALSE means place the caret immediately. If the application never calls this method, the nsIFrameSelection implementation assumes the default value is PR_TRUE.

Parameters:
aDelayPR_TRUE if we should delay caret placement.

Implements nsIFrameSelection.

Definition at line 4285 of file nsSelection.cpp.

If we are delaying caret placement til MouseUp (see Set/GetDelayCaretOverExistingSelection()), this method can be used to store the data received during the MouseDown so that we can place the caret during the MouseUp event.

the event received by the selection MouseDown handling method. A NULL value can be use to tell this method that any data is storing is no longer valid.

Implements nsIFrameSelection.

Definition at line 4307 of file nsSelection.cpp.

{
  if (aMouseEvent)
  {
    mDelayedMouseEventValid = PR_TRUE;
    mDelayedMouseEvent      = *aMouseEvent;

    // Don't cache the widget.  We don't need it and it could go away.
    mDelayedMouseEvent.widget = nsnull;
  }
  else
    mDelayedMouseEventValid = PR_FALSE;

  return NS_OK;
}

Definition at line 1077 of file nsSelection.cpp.

Here is the caller graph for this function:

void nsSelection::SetDirty ( PRBool  aDirty = PR_TRUE) [inline, private]

Definition at line 526 of file nsSelection.cpp.

Here is the caller graph for this function:

Sets/Gets The display selection enum.

Implements nsIFrameSelection.

Definition at line 4269 of file nsSelection.cpp.

{
  mDisplaySelection = aToggle;
  return NS_OK;
}

Here is the caller graph for this function:

NS_IMETHODIMP nsSelection::SetHint ( HINT  aHintRight) [virtual]

Implements nsIFrameSelection.

Definition at line 4183 of file nsSelection.cpp.

{
  mHint = aHintRight;
  return NS_OK;
}

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 has the double click down happened.

Implements nsIFrameSelection.

Definition at line 4349 of file nsSelection.cpp.

{
  mMouseDoubleDownState = aDoubleDown;
  return NS_OK;
}

SetMouseDownState(PRBool); sets the mouse state to aState for resons of drag state.

Parameters:
aStateis the new state of mousedown

Implements nsIFrameSelection.

Definition at line 2763 of file nsSelection.cpp.

{
  if (mMouseDownState == aState)
    return NS_OK;
  mMouseDownState = aState;
  if (!mMouseDownState)
  {
    PRInt16 reason;
    if (aState)
      reason = nsISelectionListener::MOUSEDOWN_REASON;
    else
      reason = nsISelectionListener::MOUSEUP_REASON;
    PostReason(reason);//not a drag reason
    NotifySelectionListeners(nsISelectionController::SELECTION_NORMAL);//notify that reason is mouse up please.
  }
  return NS_OK;
}

Here is the call graph for this function:

Implements nsIFrameSelection.

Definition at line 1339 of file nsSelection.cpp.

{
  mScrollView = aScrollView;
  return NS_OK;
}

ShutDown will be called when the owner of the frame selection is shutting down this should be the time to release all member variable interfaces.

all methods called after ShutDown should return NS_ERROR_FAILURE

Implements nsIFrameSelection.

Definition at line 1347 of file nsSelection.cpp.

{
  return NS_OK;
}
NS_IMETHODIMP nsSelection::StartAutoScrollTimer ( nsPresContext aPresContext,
nsIView aFrame,
nsPoint aPoint,
PRUint32  aDelay 
) [virtual]

StartAutoScrollTimer is responsible for scrolling views 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.

Parameters:
aPresContextis the context to use when figuring out what frame contains the point.
aViewis view to use when searching for the closest frame to the point, which is the view that is capturing the mouse
aPointis relative to the view.
aDelayis the timer's interval.

Implements nsIFrameSelection.

Definition at line 2594 of file nsSelection.cpp.

Here is the call graph for this function:

Definition at line 3089 of file nsSelection.cpp.

StopAutoScrollTimer stops any active auto scroll timer.

Implements nsIFrameSelection.

Definition at line 2601 of file nsSelection.cpp.

Here is the call graph for this function:

NS_IMETHODIMP nsSelection::TakeFocus ( nsIContent aNewFocus,
PRUint32  aContentOffset,
PRUint32  aContentEndOffset,
PRBool  aContinueSelection,
PRBool  aMultipleSelection 
) [private]

hard to go from nodes to frames, easy the other way!

Definition at line 2611 of file nsSelection.cpp.

{
  if (!aNewFocus)
    return NS_ERROR_NULL_POINTER;

  STATUS_CHECK_RETURN_MACRO();

  if (!IsValidSelectionPoint(this,aNewFocus))
    return NS_ERROR_FAILURE;

  // Clear all table selection data
  mSelectingTableCellMode = 0;
  mDragSelectingCells = PR_FALSE;
  mStartSelectedCell = nsnull;
  mEndSelectedCell = nsnull;
  mAppendStartSelectedCell = nsnull;

  //HACKHACKHACK
  if (!aNewFocus->GetParent())
    return NS_ERROR_FAILURE;
  //END HACKHACKHACK /checking for root frames/content

  PRInt8 index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL);
  nsCOMPtr<nsIDOMNode> domNode = do_QueryInterface(aNewFocus);
  //traverse through document and unselect crap here
  if (!aContinueSelection){ //single click? setting cursor down
    PRUint32 batching = mBatching;//hack to use the collapse code.
    PRBool changes = mChangesDuringBatching;
    mBatching = 1;

    if (aMultipleSelection){
      nsCOMPtr<nsIDOMRange> newRange;
      NS_NewRange(getter_AddRefs(newRange));

      newRange->SetStart(domNode,aContentOffset);
      newRange->SetEnd(domNode,aContentOffset);
      mDomSelections[index]->AddRange(newRange);
      mBatching = batching;
      mChangesDuringBatching = changes;
      mDomSelections[index]->SetOriginalAnchorPoint(domNode,aContentOffset);
    }
    else
    {
      PRBool oldDesiredXSet = mDesiredXSet; //need to keep old desired X if it was set.
      mDomSelections[index]->Collapse(domNode, aContentOffset);
      mDesiredXSet = oldDesiredXSet; //now reset desired X back.
      mBatching = batching;
      mChangesDuringBatching = changes;
    }
    if (aContentEndOffset != aContentOffset)
      mDomSelections[index]->Extend(domNode,aContentEndOffset);

    //find out if we are inside a table. if so, find out which one and which cell
    //once we do that, the next time we get a takefocus, check the parent tree. 
    //if we are no longer inside same table ,cell then switch to table selection mode.
    // BUT only do this in an editor

    PRInt16 displaySelection;
    nsresult result = mShell->GetSelectionFlags(&displaySelection);
    if (NS_FAILED(result))
      return result;

    // Editor has DISPLAY_ALL selection type
    if (displaySelection == nsISelectionDisplay::DISPLAY_ALL)
    {
      mCellParent = GetCellParent(domNode);
#ifdef DEBUG_TABLE_SELECTION
      if (mCellParent)
        printf(" * TakeFocus - Collapsing into new cell\n");
#endif
    }
  }
  else {
    // Now update the range list:
    if (aContinueSelection && domNode)
    {
      PRInt32 offset;
      nsIDOMNode *cellparent = GetCellParent(domNode);
      if (mCellParent && cellparent && cellparent != mCellParent) //switch to cell selection mode
      {
#ifdef DEBUG_TABLE_SELECTION
printf(" * TakeFocus - moving into new cell\n");
#endif
        nsCOMPtr<nsIDOMNode> parent;
        nsCOMPtr<nsIContent> parentContent;
        nsMouseEvent event(PR_FALSE, 0, nsnull, nsMouseEvent::eReal);
        nsresult result;

        // Start selecting in the cell we were in before
        result = ParentOffset(mCellParent, getter_AddRefs(parent),&offset);
        parentContent = do_QueryInterface(parent);
        if (parentContent)
          result = HandleTableSelection(parentContent, offset, nsISelectionPrivate::TABLESELECTION_CELL, &event);

        // Find the parent of this new cell and extend selection to it
        result = ParentOffset(cellparent,getter_AddRefs(parent),&offset);
        parentContent = do_QueryInterface(parent);

        // XXXX We need to REALLY get the current key shift state
        //  (we'd need to add event listener -- let's not bother for now)
        event.isShift = PR_FALSE; //aContinueSelection;
        if (parentContent)
        {
          mCellParent = cellparent;
          // Continue selection into next cell
          result = HandleTableSelection(parentContent, offset, nsISelectionPrivate::TABLESELECTION_CELL, &event);
        }
      }
      else
      {
        // XXXX Problem: Shift+click in browser is appending text selection to selected table!!!
        //   is this the place to erase seleced cells ?????
        if (mDomSelections[index]->GetDirection() == eDirNext && aContentEndOffset > aContentOffset) //didnt go far enough 
        {
          mDomSelections[index]->Extend(domNode, aContentEndOffset);//this will only redraw the diff 
        }
        else
          mDomSelections[index]->Extend(domNode, aContentOffset);
      }
    }
  }

  // Don't notify selection listeners if batching is on:
  if (GetBatching())
    return NS_OK;
  return NotifySelectionListeners(nsISelectionController::SELECTION_NORMAL);
}

Here is the call graph for this function:

Here is the caller graph for this function:

NS_IMETHODIMP nsSelection::WordMove ( PRBool  aForward,
PRBool  aExtend 
) [virtual]

WordMove will generally be called from the nsiselectioncontroller implementations.

the effect being the selection will move one word left or right.

Parameters:
aForwardmove forward in document.
aExtendcontinue selection

Implements nsIFrameSelection.

Definition at line 3039 of file nsSelection.cpp.

Here is the call graph for this function:


Friends And Related Function Documentation

friend class nsTypedSelection [friend]

Definition at line 508 of file nsSelection.cpp.


Member Data Documentation

Definition at line 557 of file nsSelection.cpp.

Definition at line 566 of file nsSelection.cpp.

Definition at line 554 of file nsSelection.cpp.

Definition at line 584 of file nsSelection.cpp.

Definition at line 581 of file nsSelection.cpp.

Definition at line 579 of file nsSelection.cpp.

Definition at line 582 of file nsSelection.cpp.

Definition at line 576 of file nsSelection.cpp.

Definition at line 590 of file nsSelection.cpp.

Definition at line 572 of file nsSelection.cpp.

Definition at line 533 of file nsSelection.cpp.

Definition at line 587 of file nsSelection.cpp.

Definition at line 556 of file nsSelection.cpp.

Definition at line 574 of file nsSelection.cpp.

Definition at line 586 of file nsSelection.cpp.

Definition at line 568 of file nsSelection.cpp.

Definition at line 563 of file nsSelection.cpp.

Definition at line 589 of file nsSelection.cpp.

Definition at line 588 of file nsSelection.cpp.

Definition at line 585 of file nsSelection.cpp.

Definition at line 577 of file nsSelection.cpp.

Definition at line 560 of file nsSelection.cpp.

Definition at line 559 of file nsSelection.cpp.

Definition at line 571 of file nsSelection.cpp.

Definition at line 569 of file nsSelection.cpp.

Definition at line 555 of file nsSelection.cpp.

Definition at line 558 of file nsSelection.cpp.


The documentation for this class was generated from the following file: