From 0352ad75c65d859b6fbde65e990e214c767a297f Mon Sep 17 00:00:00 2001 From: "mjudge%netscape.com" Date: Mon, 26 Apr 1999 04:02:04 +0000 Subject: [PATCH] selection changes for new model of content only. frames no longer contain variables referring to selection state outside of 1 bit. keyboard selection will now be disabled until i can get it working in the new selection world order. git-svn-id: svn://10.0.0.236/trunk@29153 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/base/nsIFrameSelection.h | 69 +- mozilla/layout/base/nsPresShell.cpp | 43 +- mozilla/layout/base/public/nsIFrame.h | 25 +- .../layout/base/public/nsIFrameSelection.h | 69 +- mozilla/layout/base/src/nsRangeList.cpp | 656 +++++++---------- mozilla/layout/generic/nsFrame.cpp | 116 +-- mozilla/layout/generic/nsFrame.h | 10 +- mozilla/layout/generic/nsIFrame.h | 25 +- mozilla/layout/generic/nsSplittableFrame.cpp | 3 + mozilla/layout/generic/nsTextFrame.cpp | 696 +++++++++--------- mozilla/layout/html/base/src/nsFrame.cpp | 116 +-- mozilla/layout/html/base/src/nsFrame.h | 10 +- mozilla/layout/html/base/src/nsPresShell.cpp | 43 +- .../html/base/src/nsSplittableFrame.cpp | 3 + mozilla/layout/html/base/src/nsTextFrame.cpp | 696 +++++++++--------- 15 files changed, 1147 insertions(+), 1433 deletions(-) diff --git a/mozilla/layout/base/nsIFrameSelection.h b/mozilla/layout/base/nsIFrameSelection.h index 3ebd4abbe58..988029d2a53 100644 --- a/mozilla/layout/base/nsIFrameSelection.h +++ b/mozilla/layout/base/nsIFrameSelection.h @@ -35,22 +35,6 @@ { 0xf46e4171, 0xdeaa, 0x11d1, \ { 0x97, 0xfc, 0x0, 0x60, 0x97, 0x3, 0xc1, 0x4e } } -/** nsSelectionStruct is used to pass structured parameters to the SelectionCalls. - */ -struct nsSelectionStruct -{ - enum {SELON = 1,SELALL = 2,SELTOEND = 4,SELTOBEGIN = 8,CHECKANCHOR=16,CHECKFOCUS=32};//this is not a bit flag - PRUint32 mType; - PRUint32 mStartContent;//in content offsets. - PRUint32 mEndContent; - PRUint32 mStartFrame; - PRUint32 mEndFrame; - PRUint32 mAnchorOffset; - PRUint32 mFocusOffset; - nsDirection mDir; //tells you if you have to swap the begin and end points. - PRBool mForceRedraw; -}; - //---------------------------------------------------------------------- @@ -59,44 +43,61 @@ class nsIFrameSelection : public nsISupports { public: static const nsIID& GetIID() { static nsIID iid = NS_IFRAMESELECTION_IID; return iid; } - /** HandleKeyEvent will accept an event and frame and - * will return NS_OK if it handles the event or NS_COMFALSE if not. - *

DOES NOT ADDREF

- * @param tracker to ask where the current focus is and to set the new anchor ect. - * @param aGuiEvent is the event that should be dealt with by aFocusFrame - * @param aFrame is the frame that MAY handle the event + /** Init will initialize the frame selector with the necessary focus tracker to + * be used by most of the methods + * @param aTracker is the parameter to be used for most of the other calls for callbacks ect */ - NS_IMETHOD HandleTextEvent(nsIFocusTracker *aTracker, nsGUIEvent *aGuiEvent) = 0; + NS_IMETHOD Init(nsIFocusTracker *aTracker) = 0; + + /** 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 + */ + NS_IMETHOD ShutDown() = 0; /** HandleKeyEvent will accept an event and frame and * will return NS_OK if it handles the event or NS_COMFALSE if not. *

DOES NOT ADDREF

- * @param tracker to ask where the current focus is and to set the new anchor ect. * @param aGuiEvent is the event that should be dealt with by aFocusFrame * @param aFrame is the frame that MAY handle the event */ - NS_IMETHOD HandleKeyEvent(nsIFocusTracker *aTracker, nsGUIEvent *aGuiEvent) = 0; + NS_IMETHOD HandleTextEvent(nsGUIEvent *aGuiEvent) = 0; + + /** HandleKeyEvent will accept an event and frame and + * will return NS_OK if it handles the event or NS_COMFALSE if not. + *

DOES NOT ADDREF

+ * @param aGuiEvent is the event that should be dealt with by aFocusFrame + * @param aFrame is the frame that MAY handle the event + */ + NS_IMETHOD HandleKeyEvent(nsGUIEvent *aGuiEvent) = 0; /** TakeFocus will take the focus to the new frame at the new offset and * will either extend the selection from the old anchor, or replace the old anchor. * the old anchor and focus position may also be used to deselect things - * @param aTracker we need a focus tracker to get the old focus ect. - * @param aFrame is the frame that wants the focus - * @param aOffset is the offset in the aFrame that will get the focus point - * @param aContentOffset is the offset in the node of the aFrame that is reflected be aOffset + * @param aNewfocus is the content that wants the focus + * @param aContentOffset is the content offset of the parent aNewFocus * @param aContinueSelection is the flag that tells the selection to keep the old anchor point or not. */ - NS_IMETHOD TakeFocus(nsIFocusTracker *aTracker, nsIFrame *aFrame, PRInt32 aOffset, PRInt32 aContentOffset, PRBool aContinueSelection) = 0; - - /** ResetSelection will top down search for frames that need selection - */ - NS_IMETHOD ResetSelection(nsIFocusTracker *aTracker, nsIFrame *aStartFrame) = 0; + NS_IMETHOD TakeFocus(nsIContent *aNewFocus, PRUint32 aContentOffset, PRBool aContinueSelection) = 0; /** EnableFrameNotification * mutch like start batching, except all dirty calls are ignored. no notifications will go * out until enableNotifications with a PR_TRUE is called */ NS_IMETHOD EnableFrameNotification(PRBool aEnable) = 0; + + /** Lookup Selection + * returns in frame coordinates the selection beginning and ending with the type of selection given + * @param aContent is the content asking + * @param aContentOffset is the starting content boundary + * @param aContentLength is the length of the content piece asking + * @param aStart start return frame indexed value + * @param aEnd end return frame indexed value + * @param aDrawSelected return value if this offset,length has anything in the selected area + * @param aFlag what type of selection not used now + */ + NS_IMETHOD LookUpSelection(nsIContent *aContent, PRInt32 aContentOffset, PRInt32 aContentLength, + PRInt32 *aStart, PRInt32 *aEnd, PRBool *aDrawSelected, PRUint32 aFlag/*not used*/) = 0; }; diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index 259d56514f6..4356a265c14 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -597,35 +597,16 @@ PresShell::Init(nsIDocument* aDocument, getter_AddRefs(domselection)); if (!NS_SUCCEEDED(result)) return result; + result = domselection->QueryInterface(kIFrameSelectionIID, - getter_AddRefs(mSelection)); + getter_AddRefs(mSelection)); if (!NS_SUCCEEDED(result)) return result; domselection->AddSelectionListener(this);//possible circular reference - // XXX This code causes the document object (and the entire content model) to be leaked... -#if 0 - nsCOMPtrrange; - if (NS_SUCCEEDED(nsComponentManager::CreateInstance(kCRangeCID, nsnull, kIDOMRangeIID, getter_AddRefs(range)))){ //create an irange - nsCOMPtrdoc(GetDocument()); - nsCOMPtrdomDoc(doc); - if (domDoc){ - nsCOMPtr domElement; - if (NS_SUCCEEDED(domDoc->GetDocumentElement(getter_AddRefs(domElement)))) {//get the first element from the dom - nsCOMPtrdomNode(domElement); - if (domNode) {//get the node interface for the range object - range->SetStart(domNode,0); - range->SetEnd(domNode,0); - nsCOMPtrrangeISupports(range); - if (rangeISupports) { - selection->AddItem(rangeISupports); - } - } - } - } - } - -#endif + result = mSelection->Init((nsIFocusTracker *) this); + if (!NS_SUCCEEDED(result)) + return result; // Important: this has to happen after the selection has been set up #ifdef SHOW_CARET nsCaretProperties *caretProperties = NewCaretProperties(); @@ -836,6 +817,7 @@ PresShell::EndObservingDocument() if (!domselection) return NS_ERROR_UNEXPECTED; domselection->RemoveSelectionListener(this); + mSelection->ShutDown(); } return NS_OK; } @@ -958,12 +940,6 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight) NS_IF_RELEASE(rcx); NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, ("exit nsPresShell::ResizeReflow")); - if (mSelection){ - DisableScrolling(); - mSelection->ResetSelection(this, mRootFrame); - EnableScrolling(); - } - // XXX if debugging then we should assert that the cache is empty } else { #ifdef NOISY @@ -1049,7 +1025,6 @@ NS_IMETHODIMP PresShell::NotifySelectionChanged() { if (!mSelection) return NS_ERROR_NULL_POINTER; - mSelection->ResetSelection(this, mRootFrame); return NS_ERROR_NULL_POINTER; } @@ -1636,8 +1611,6 @@ PresShell::ContentChanged(nsIDocument *aDocument, EnterReflowLock(); nsresult rv = mStyleSet->ContentChanged(mPresContext, aContent, aSubContent); ExitReflowLock(); - if (mSelection) - mSelection->ResetSelection(this, mRootFrame); return rv; } @@ -1652,8 +1625,6 @@ PresShell::ContentStatesChanged(nsIDocument* aDocument, EnterReflowLock(); nsresult rv = mStyleSet->ContentStatesChanged(mPresContext, aContent1, aContent2); ExitReflowLock(); - //if (mSelection) - //mSelection->ResetSelection(this, mRootFrame); return rv; } @@ -2019,7 +1990,7 @@ PresShell::HandleEvent(nsIView *aView, if (mSelection && mFocusEventFrame && aEvent->eventStructType == NS_KEY_EVENT) { mSelection->EnableFrameNotification(PR_FALSE); - mSelection->HandleKeyEvent((nsIFocusTracker *)this, aEvent); + mSelection->HandleKeyEvent(aEvent); mSelection->EnableFrameNotification(PR_TRUE); //prevents secondary reset selection called since //we are a listener now. } diff --git a/mozilla/layout/base/public/nsIFrame.h b/mozilla/layout/base/public/nsIFrame.h index 4b3cf955caa..a4c88dda639 100644 --- a/mozilla/layout/base/public/nsIFrame.h +++ b/mozilla/layout/base/public/nsIFrame.h @@ -44,7 +44,7 @@ class nsStyleChangeList; struct nsPoint; struct nsRect; struct nsStyleStruct; -struct nsSelectionStruct; +class nsIDOMRange; struct PRLogModuleInfo; @@ -127,6 +127,9 @@ typedef PRUint32 nsFrameState; // e.g., it is absolutely positioned or floated #define NS_FRAME_OUT_OF_FLOW 0x00000100 +// If this bit is set, then the frame reflects content that may be selected +#define NS_FRAME_SELECTED_CONTENT 0x00000200 + // The low 16 bits of the frame state word are reserved by this API. #define NS_FRAME_RESERVED 0x0000FFFF @@ -579,21 +582,13 @@ public: * Called to set the selection of the frame based on frame offsets. you can FORCE the frame * to redraw event if aSelected == the frame selection with the last parameter. * data in struct may be changed when passed in. - * @param nsSelectionStruct will hold the data pertinant to the Selection, Selected or not ect. + * @param aRange is the range that will dictate if the frames need to be redrawn null means the whole content needs to be redrawn + * @param aSelected is it selected + * @param aSpread should is spread selection to flow elements around it? */ - NS_IMETHOD SetSelected(nsSelectionStruct *) = 0; + NS_IMETHOD SetSelected(nsIDOMRange *aRange,PRBool aSelected, PRBool aSpread) = 0; - /** - * Called to start a selection with this frame content. - * @param aSS is the struct that holds the data instead of passing in so many parameters - * @param aFocusTracker will allow the frame to set the focus to what it needs. - * @param return value of which frame (maybe not this one, maybe one of its siblings) - */ - NS_IMETHOD SetSelectedContentOffsets(nsSelectionStruct *aSS, - nsIFocusTracker *aTracker, - nsIFrame **aActualSelected)=0; - - NS_IMETHOD GetSelected(PRBool *aSelected, PRInt32 *aBeginOffset, PRInt32 *aEndOffset, PRInt32 *aBeginContentOffset) = 0; + NS_IMETHOD GetSelected(PRBool *aSelected) const = 0; /** * called to find the previous/next character, word, or line returns the actual @@ -609,7 +604,7 @@ public: * @param aEatingWS boolean to tell us the state of our search for Next/Prev */ NS_IMETHOD PeekOffset(nsSelectionAmount aAmount, nsDirection aDirection, PRInt32 aStartOffset, - nsIFrame **aResultFrame, PRInt32 *aFrameOffset, PRInt32 *aContentOffset, PRBool aEatingWS) = 0; + nsIFrame **aResultFrame, PRInt32 *aFrameOffset, PRInt32 *aContentOffset, PRBool aEatingWS) const = 0; /** * See if tree verification is enabled. To enable tree verification add diff --git a/mozilla/layout/base/public/nsIFrameSelection.h b/mozilla/layout/base/public/nsIFrameSelection.h index 3ebd4abbe58..988029d2a53 100644 --- a/mozilla/layout/base/public/nsIFrameSelection.h +++ b/mozilla/layout/base/public/nsIFrameSelection.h @@ -35,22 +35,6 @@ { 0xf46e4171, 0xdeaa, 0x11d1, \ { 0x97, 0xfc, 0x0, 0x60, 0x97, 0x3, 0xc1, 0x4e } } -/** nsSelectionStruct is used to pass structured parameters to the SelectionCalls. - */ -struct nsSelectionStruct -{ - enum {SELON = 1,SELALL = 2,SELTOEND = 4,SELTOBEGIN = 8,CHECKANCHOR=16,CHECKFOCUS=32};//this is not a bit flag - PRUint32 mType; - PRUint32 mStartContent;//in content offsets. - PRUint32 mEndContent; - PRUint32 mStartFrame; - PRUint32 mEndFrame; - PRUint32 mAnchorOffset; - PRUint32 mFocusOffset; - nsDirection mDir; //tells you if you have to swap the begin and end points. - PRBool mForceRedraw; -}; - //---------------------------------------------------------------------- @@ -59,44 +43,61 @@ class nsIFrameSelection : public nsISupports { public: static const nsIID& GetIID() { static nsIID iid = NS_IFRAMESELECTION_IID; return iid; } - /** HandleKeyEvent will accept an event and frame and - * will return NS_OK if it handles the event or NS_COMFALSE if not. - *

DOES NOT ADDREF

- * @param tracker to ask where the current focus is and to set the new anchor ect. - * @param aGuiEvent is the event that should be dealt with by aFocusFrame - * @param aFrame is the frame that MAY handle the event + /** Init will initialize the frame selector with the necessary focus tracker to + * be used by most of the methods + * @param aTracker is the parameter to be used for most of the other calls for callbacks ect */ - NS_IMETHOD HandleTextEvent(nsIFocusTracker *aTracker, nsGUIEvent *aGuiEvent) = 0; + NS_IMETHOD Init(nsIFocusTracker *aTracker) = 0; + + /** 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 + */ + NS_IMETHOD ShutDown() = 0; /** HandleKeyEvent will accept an event and frame and * will return NS_OK if it handles the event or NS_COMFALSE if not. *

DOES NOT ADDREF

- * @param tracker to ask where the current focus is and to set the new anchor ect. * @param aGuiEvent is the event that should be dealt with by aFocusFrame * @param aFrame is the frame that MAY handle the event */ - NS_IMETHOD HandleKeyEvent(nsIFocusTracker *aTracker, nsGUIEvent *aGuiEvent) = 0; + NS_IMETHOD HandleTextEvent(nsGUIEvent *aGuiEvent) = 0; + + /** HandleKeyEvent will accept an event and frame and + * will return NS_OK if it handles the event or NS_COMFALSE if not. + *

DOES NOT ADDREF

+ * @param aGuiEvent is the event that should be dealt with by aFocusFrame + * @param aFrame is the frame that MAY handle the event + */ + NS_IMETHOD HandleKeyEvent(nsGUIEvent *aGuiEvent) = 0; /** TakeFocus will take the focus to the new frame at the new offset and * will either extend the selection from the old anchor, or replace the old anchor. * the old anchor and focus position may also be used to deselect things - * @param aTracker we need a focus tracker to get the old focus ect. - * @param aFrame is the frame that wants the focus - * @param aOffset is the offset in the aFrame that will get the focus point - * @param aContentOffset is the offset in the node of the aFrame that is reflected be aOffset + * @param aNewfocus is the content that wants the focus + * @param aContentOffset is the content offset of the parent aNewFocus * @param aContinueSelection is the flag that tells the selection to keep the old anchor point or not. */ - NS_IMETHOD TakeFocus(nsIFocusTracker *aTracker, nsIFrame *aFrame, PRInt32 aOffset, PRInt32 aContentOffset, PRBool aContinueSelection) = 0; - - /** ResetSelection will top down search for frames that need selection - */ - NS_IMETHOD ResetSelection(nsIFocusTracker *aTracker, nsIFrame *aStartFrame) = 0; + NS_IMETHOD TakeFocus(nsIContent *aNewFocus, PRUint32 aContentOffset, PRBool aContinueSelection) = 0; /** EnableFrameNotification * mutch like start batching, except all dirty calls are ignored. no notifications will go * out until enableNotifications with a PR_TRUE is called */ NS_IMETHOD EnableFrameNotification(PRBool aEnable) = 0; + + /** Lookup Selection + * returns in frame coordinates the selection beginning and ending with the type of selection given + * @param aContent is the content asking + * @param aContentOffset is the starting content boundary + * @param aContentLength is the length of the content piece asking + * @param aStart start return frame indexed value + * @param aEnd end return frame indexed value + * @param aDrawSelected return value if this offset,length has anything in the selected area + * @param aFlag what type of selection not used now + */ + NS_IMETHOD LookUpSelection(nsIContent *aContent, PRInt32 aContentOffset, PRInt32 aContentLength, + PRInt32 *aStart, PRInt32 *aEnd, PRBool *aDrawSelected, PRUint32 aFlag/*not used*/) = 0; }; diff --git a/mozilla/layout/base/src/nsRangeList.cpp b/mozilla/layout/base/src/nsRangeList.cpp index 397844e43e1..47ffe215f10 100644 --- a/mozilla/layout/base/src/nsRangeList.cpp +++ b/mozilla/layout/base/src/nsRangeList.cpp @@ -36,9 +36,18 @@ #include "nsISupportsArray.h" #include "nsIDOMEvent.h" +#include "nsIDOMSelectionListener.h" +#include "nsIContentIterator.h" + + + #include "nsIScriptObjectOwner.h" #include "nsIScriptGlobalObject.h" + + +#define STATUS_CHECK_RETURN_MACRO() {if (!mTracker) return NS_ERROR_FAILURE;} + static NS_DEFINE_IID(kIEnumeratorIID, NS_IENUMERATOR_IID); static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); static NS_DEFINE_IID(kIFrameSelectionIID, NS_IFRAMESELECTION_IID); @@ -47,16 +56,12 @@ static NS_DEFINE_IID(kIDOMSelectionIID, NS_IDOMSELECTION_IID); static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID); static NS_DEFINE_IID(kIDOMRangeIID, NS_IDOMRANGE_IID); static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID); +static NS_DEFINE_IID(kCContentIteratorCID, NS_CONTENTITERATOR_CID); +static NS_DEFINE_IID(kIContentIteratorIID, NS_ICONTENTITERTOR_IID); //PROTOTYPES -static void selectFrames(nsIFrame *aBegin, PRUint32 aBeginOffset, nsIFrame *aEnd, PRUint32 aEndOffset, nsDirection aDir, PRUint32 aFlags); -static void unselectFrames(nsIFrame *aRootFrame); -static PRInt32 compareFrames(nsIFrame *aBegin, nsIFrame *aEnd); -static nsIFrame * getNextFrame(nsIFrame *aStart); static void printRange(nsIDOMRange *aDomRange); -//static nsIFrame *findFrameFromContent(nsIFrame *aParent, nsIContent *aContent, PRBool aTurnOff); -enum {FORWARD =1, BACKWARD = 0}; #if 1 #define DEBUG_OUT_RANGE(x) printRange(x) @@ -79,11 +84,14 @@ public: NS_DECL_ISUPPORTS /*BEGIN nsIFrameSelection interfaces*/ - NS_IMETHOD HandleTextEvent(nsIFocusTracker *aTracker, nsGUIEvent *aGUIEvent); - NS_IMETHOD HandleKeyEvent(nsIFocusTracker *aTracker, nsGUIEvent *aGuiEvent); - NS_IMETHOD TakeFocus(nsIFocusTracker *aTracker, nsIFrame *aFrame, PRInt32 aOffset, PRInt32 aContentOffset, PRBool aContinueSelection); - NS_IMETHOD ResetSelection(nsIFocusTracker *aTracker, nsIFrame *aStartFrame); + NS_IMETHOD Init(nsIFocusTracker *aTracker); + NS_IMETHOD ShutDown(); + NS_IMETHOD HandleTextEvent(nsGUIEvent *aGUIEvent); + NS_IMETHOD HandleKeyEvent(nsGUIEvent *aGuiEvent); + NS_IMETHOD TakeFocus(nsIContent *aNewFocus, PRUint32 aContentOffset, PRBool aContinueSelection); NS_IMETHOD EnableFrameNotification(PRBool aEnable){mNotifyFrames = aEnable; return NS_OK;} + NS_IMETHOD LookUpSelection(nsIContent *aContent, PRInt32 aContentOffset, PRInt32 aContentLength, + PRInt32 *aStart, PRInt32 *aEnd, PRBool *aDrawSelected , PRUint32 aFlag/*not used*/); /*END nsIFrameSelection interfacse*/ /*BEGIN nsIDOMSelection interface implementations*/ @@ -120,7 +128,7 @@ private: nsresult RemoveItem(nsISupports *aRange); nsresult Clear(); - NS_IMETHOD ScrollIntoView(nsIFocusTracker *aTracker); + NS_IMETHOD ScrollIntoView(); friend class nsRangeListIterator; @@ -146,6 +154,8 @@ private: nsresult NotifySelectionListeners(); // add parameters to say collapsed etc? + NS_IMETHOD selectFrames(nsIDOMRange *aRange, PRBool aSelect); + nsCOMPtr mRangeArray; nsCOMPtr mAnchorNode; //where did the selection begin @@ -162,6 +172,7 @@ private: // for nsIScriptContextOwner void* mScriptObject; + nsCOMPtr mTracker; }; class nsRangeListIterator : public nsIBidirectionalEnumerator @@ -553,11 +564,17 @@ nsRangeList::Clear() setAnchor(nsnull,0); if (!mRangeArray) return NS_ERROR_FAILURE; - for (PRUint32 i = 0; i < mRangeArray->Count();i++) + // Get an iterator + while ( mRangeArray->Count()) { - mRangeArray->RemoveElementAt(i); + nsCOMPtr range; + nsCOMPtr isupportsindex = dont_AddRef(mRangeArray->ElementAt(0)); + range = do_QueryInterface(isupportsindex); + mRangeArray->RemoveElementAt(0); + selectFrames(range, 0); // Does RemoveElementAt also delete the elements? } + return NS_OK; } @@ -592,51 +609,61 @@ void printRange(nsIDOMRange *aDomRange) */ } + + NS_IMETHODIMP -nsRangeList::HandleTextEvent(nsIFocusTracker *aTracker, nsGUIEvent *aGUIEvent) +nsRangeList::Init(nsIFocusTracker *aTracker) { - if (!aGUIEvent || !aTracker) + mTracker = dont_QueryInterface(aTracker); + return NS_OK; +} + + + +NS_IMETHODIMP +nsRangeList::ShutDown() +{ + nsCOMPtr x; + mTracker = x; + return NS_OK; +} + + + +NS_IMETHODIMP +nsRangeList::HandleTextEvent(nsGUIEvent *aGUIEvent) +{ + if (!aGUIEvent) return NS_ERROR_NULL_POINTER; #ifdef DEBUG_TAGUE printf("nsRangeList: HandleTextEvent\n"); #endif - - nsIFrame *anchor; - nsIFrame *frame; - nsresult result = aTracker->GetFocus(&frame, &anchor); - if (NS_FAILED(result)) - return result; + nsresult result(NS_OK); if (NS_TEXT_EVENT == aGUIEvent->message) { - PRBool selected; - PRInt32 beginoffset = 0; - PRInt32 endoffset; - PRInt32 contentoffset; - nsresult result = NS_OK; - nsTextEvent *textEvent = (nsTextEvent *)aGUIEvent; //this is ok. It really is a textevent - - PRInt32 offsetused = beginoffset; - nsSelectionAmount amount = eSelectCharacter; // for now - result = frame->GetSelected(&selected,&beginoffset,&endoffset, &contentoffset); - - result = ScrollIntoView(aTracker); + result = ScrollIntoView(); } - return NS_OK; + return result; } + + /** 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_IMETHODIMP -nsRangeList::HandleKeyEvent(nsIFocusTracker *aTracker, nsGUIEvent *aGuiEvent) +nsRangeList::HandleKeyEvent(nsGUIEvent *aGuiEvent) { - if (!aGuiEvent ||!aTracker) + if (!aGuiEvent) return NS_ERROR_NULL_POINTER; + STATUS_CHECK_RETURN_MACRO(); +return NS_OK; +#if 0 nsIFrame *anchor; nsIFrame *frame; - nsresult result = aTracker->GetFocus(&frame, &anchor); + nsresult result = mTracker->GetFocus(&frame, &anchor); if (NS_FAILED(result)) return result; if (NS_KEY_DOWN == aGuiEvent->message) { @@ -654,7 +681,7 @@ nsRangeList::HandleKeyEvent(nsIFocusTracker *aTracker, nsGUIEvent *aGuiEvent) PRInt32 offsetused = beginoffset; nsIFrame *frameused; nsSelectionAmount amount = eSelectCharacter; - result = frame->GetSelected(&selected,&beginoffset,&endoffset, &contentoffset); + result = frame->GetSelected(&selected); if (NS_FAILED(result)){ return result; } @@ -679,9 +706,9 @@ nsRangeList::HandleKeyEvent(nsIFocusTracker *aTracker, nsGUIEvent *aGuiEvent) frameused = anchor; } if (NS_SUCCEEDED(frameused->PeekOffset(amount, eDirPrevious, offsetused, &resultFrame, &frameOffset, &contentOffset, PR_FALSE)) && resultFrame){ - result = TakeFocus(aTracker, resultFrame, frameOffset, contentOffset, keyEvent->isShift); + result = TakeFocus(resultFrame, frameOffset, contentOffset, keyEvent->isShift); } - result = ScrollIntoView(aTracker); + result = ScrollIntoView(); break; case nsIDOMEvent::VK_RIGHT : //we need to look for the next PAINTED location to move the cursor to. @@ -701,9 +728,9 @@ nsRangeList::HandleKeyEvent(nsIFocusTracker *aTracker, nsGUIEvent *aGuiEvent) frameused = frame; } if (NS_SUCCEEDED(frameused->PeekOffset(amount, eDirNext, offsetused, &resultFrame, &frameOffset, &contentOffset, PR_FALSE)) && resultFrame){ - result = TakeFocus(aTracker, resultFrame, frameOffset, contentOffset, keyEvent->isShift); + result = TakeFocus(resultFrame, frameOffset, contentOffset, keyEvent->isShift); } - result = ScrollIntoView(aTracker); + result = ScrollIntoView(); break; case nsIDOMEvent::VK_UP : #ifdef DEBUG_NAVIGATION @@ -714,6 +741,7 @@ nsRangeList::HandleKeyEvent(nsIFocusTracker *aTracker, nsGUIEvent *aGuiEvent) } } return result; +#endif } #ifdef DEBUG @@ -754,398 +782,230 @@ void nsRangeList::printSelection() -//recursive-oid method to get next frame -nsIFrame * -getNextFrame(nsIFrame *aStart) -{ - nsIFrame *result; - nsIFrame *parent = aStart; - if (parent && NS_SUCCEEDED(parent->FirstChild(nsnull, &result)) && result){ - return result; - } - while(parent){ - if (NS_SUCCEEDED(parent->GetNextSibling(&result)) && result){ - parent = result; - return result; - } - else - if (NS_FAILED(parent->GetParent(&result)) || !result) - return nsnull; - else - parent = result; - } - return nsnull; -} - - - -//compare the 2 passed in frames -1 first is smaller 1 second is smaller 0 they are the same -PRInt32 -compareFrames(nsIFrame *aBegin, nsIFrame *aEnd) -{ - if (!aBegin || !aEnd) - return 0; - if (aBegin == aEnd) - return 0; - nsCOMPtr beginContent; - if (NS_SUCCEEDED(aBegin->GetContent(getter_AddRefs(beginContent))) && beginContent){ - nsCOMPtrbeginNode (do_QueryInterface(beginContent)); - nsCOMPtr endContent; - if (NS_SUCCEEDED(aEnd->GetContent(getter_AddRefs(endContent))) && endContent){ - nsCOMPtrendNode (do_QueryInterface(endContent)); - PRBool storage; - PRInt32 int1; - PRInt32 int2; - PRInt32 contentOffset1; - PRInt32 contentOffset2; - aBegin->GetSelected(&storage,&int1,&int2,&contentOffset1); - aEnd->GetSelected(&storage,&int1,&int2,&contentOffset2); - return ComparePoints(beginNode, contentOffset1, endNode, contentOffset2); - } - } - return 0; -} - - - //the idea of this helper method is to select, deselect "top to bottom" traversing through the frames -void -selectFrames(nsIFrame *aBegin, PRUint32 aBeginOffset, nsIFrame *aEnd, PRUint32 aEndOffset, nsDirection aDir, PRUint32 aFlags) +NS_IMETHODIMP +nsRangeList::selectFrames(nsIDOMRange *aRange, PRBool aFlags) { - if (!aBegin || !aEnd) - return; - PRBool done = PR_FALSE; - while (!done) + if (!aRange) + return NS_ERROR_NULL_POINTER; + nsCOMPtr iter; + nsresult result = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull, + kIContentIteratorIID, + getter_AddRefs(iter)); + if ((NS_SUCCEEDED(result)) && iter) { - PRUint32 type(aFlags); - - nsSelectionStruct ss = {0}; - if (aBegin == aEnd) + iter->Init(aRange); + // loop through the content iterator for each content node + // for each text node: + // get the frame for the content, and from it the style context + // ask the style context about the property + nsCOMPtr content; + PRBool drawWholeContent = PR_FALSE; + result = iter->First(); + if (NS_FAILED(result)) + return result; + nsIFrame *frame; + while (NS_COMFALSE == iter->IsDone()) { - ss.mType = type; - ss.mStartFrame = aBeginOffset; - ss.mEndFrame = aEndOffset; - ss.mDir = aDir; - aBegin->SetSelected(&ss); - done = PR_TRUE; - } - else { - //else we neeed to select from begin to end - type |= nsSelectionStruct::SELTOEND; - ss.mType = type; - ss.mStartFrame = aBeginOffset; - ss.mEndFrame = aEndOffset; - ss.mDir = aDir; - aBegin->SetSelected(&ss); - aBeginOffset = 0; - if (!(aBegin = getNextFrame(aBegin))) - { - done = PR_TRUE; - } + result = iter->CurrentNode(getter_AddRefs(content)); + if (NS_FAILED(result)) + return result; + result = mTracker->GetPrimaryFrameFor(content, &frame); + if (NS_SUCCEEDED(result) && frame) + frame->SetSelected(aRange,aFlags,PR_TRUE);//spread from here to hit all frames in flow + iter->Next(); } } + return result; } -// unselect all frames under the root frame -void -unselectFrames(nsIFrame *aRootFrame) -{ - nsIFrame *theFrame = aRootFrame; - nsSelectionStruct ss = {0}; // all that's important is that the selection_on flag is not lit. - while (theFrame) - { - theFrame->SetSelected(&ss); - theFrame = getNextFrame(theFrame); - } -} /** hard to go from nodes to frames, easy the other way! */ NS_IMETHODIMP -nsRangeList::TakeFocus(nsIFocusTracker *aTracker, nsIFrame *aFrame, PRInt32 aOffset, PRInt32 aContentOffset, PRBool aContinueSelection) +nsRangeList::TakeFocus(nsIContent *aNewFocus, PRUint32 aContentOffset, PRBool aContinueSelection) { - if (!aTracker || !aFrame) + if (!aNewFocus) return NS_ERROR_NULL_POINTER; if (GetBatching()) return NS_ERROR_FAILURE; + STATUS_CHECK_RETURN_MACRO(); //HACKHACKHACK nsCOMPtr content; nsCOMPtr domNode; - if (NS_SUCCEEDED(aFrame->GetContent(getter_AddRefs(content))) && content){ - nsCOMPtr parent; - nsCOMPtr parent2; - if (NS_FAILED(content->GetParent(*getter_AddRefs(parent))) || !parent) - return NS_ERROR_FAILURE; - if (NS_FAILED(parent->GetParent(*getter_AddRefs(parent2))) || !parent2) - return NS_ERROR_FAILURE; - domNode = do_QueryInterface(content); - parent = nsCOMPtr();//just force a release now even though we dont have to. - parent2 = nsCOMPtr(); + nsCOMPtr parent; + nsCOMPtr parent2; + if (NS_FAILED(aNewFocus->GetParent(*getter_AddRefs(parent))) || !parent) + return NS_ERROR_FAILURE; + if (NS_FAILED(parent->GetParent(*getter_AddRefs(parent2))) || !parent2) + return NS_ERROR_FAILURE; + 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; + Collapse(domNode, aContentOffset); + mBatching = batching; + mChangesDuringBatching = changes; + } + else { + //compare anchor to old cursor. + nsCOMPtr anchorNode; + nsCOMPtr focusNode; + PRInt32 anchorOffset; + PRInt32 focusOffset; + nsresult result = NS_OK; + result = GetAnchorNode(getter_AddRefs(anchorNode)); + result |= GetAnchorOffset(&anchorOffset); + result |= GetFocusNode(getter_AddRefs(focusNode)); + result |= GetFocusOffset(&focusOffset); - nsIFrame *frame; - nsIFrame *anchor; - PRBool direction(BACKWARD);//true == left to right - if (domNode && NS_SUCCEEDED(aTracker->GetFocus(&frame, &anchor))){ - //traverse through document and unselect crap here - if (!aContinueSelection){ //single click? setting cursor down - if (anchor && frame && anchor != frame ){ - //selected across frames, must "deselect" frames between in correct order - PRInt32 compareResult = compareFrames(anchor,frame); - if ( compareResult < 0 ) - selectFrames(anchor,0,frame, 0, eDirNext, nsSelectionStruct::SELTOEND); //unselect all between - else if (compareResult > 0 ) - selectFrames(frame,0,anchor, 0, eDirPrevious, nsSelectionStruct::SELTOEND); //unselect all between -// else real bad put in assert here - } - else if (frame && frame != aFrame){ - nsSelectionStruct ss={nsSelectionStruct::SELTOEND, 0,0, 0,0, 0,0, eDirNext, PR_FALSE}; - frame->SetSelected(&ss); - } - nsSelectionStruct ss={nsSelectionStruct::SELON, 0,0, aOffset, aOffset, 0,0, eDirNext, PR_FALSE}; - aFrame->SetSelected(&ss); - aTracker->SetFocus(aFrame,aFrame); - PRUint32 batching = mBatching;//hack to use the collapse code. - PRBool changes = mChangesDuringBatching; - mBatching = 1; - Collapse(domNode, aContentOffset + aOffset); - mBatching = batching; - mChangesDuringBatching = changes; + + + + if (NS_FAILED(result)) + return result; + PRInt32 result1 = ComparePoints(anchorNode, anchorOffset + ,focusNode, focusOffset); + //compare old cursor to new cursor + PRInt32 result2 = ComparePoints(focusNode, focusOffset, + domNode, aContentOffset ); + //compare anchor to new cursor + PRInt32 result3 = ComparePoints(anchorNode, anchorOffset, + domNode , aContentOffset ); + + if (result1 == 0 && result3 < 0){ + //selectFrames(anchor,anchorFrameOffsetBegin, aFrame, aOffset , eDirNext, nsSelectionStruct::SELON); + } + else if (result1 == 0 && result3 > 0){ + //selectFrames(aFrame, aOffset , anchor,anchorFrameOffsetBegin, eDirPrevious,nsSelectionStruct::SELON); + } + else if (result1 <= 0 && result2 <= 0) {//a,1,2 or a1,2 or a,12 or a12 + //continue selection from 1 to 2 + //selectFrames(frame,PR_MIN(focusFrameOffsetEnd,focusFrameOffsetBegin), aFrame, aOffset, eDirNext, nsSelectionStruct::SELON); + } + else{ + nsCOMPtr range; + result = nsComponentManager::CreateInstance(kRangeCID, nsnull, + kIDOMRangeIID, + getter_AddRefs(range)); + if (NS_FAILED(result)) + return result; + if (result3 <= 0 && result2 >= 0) {//a,2,1 or a2,1 or a,21 or a21 + //deselect from 2 to 1 + result = range->SetEnd(focusNode, focusOffset); + result |= range->SetStart(domNode, aContentOffset); + if (NS_FAILED(result)) + return result; + selectFrames(range, 0); } - else { - if (aFrame == frame){ //drag to same frame - PRInt32 beginoffset = 0; - PRInt32 begincontentoffset = 0; - PRInt32 endoffset = 0; - PRBool selected = PR_FALSE; - if (NS_SUCCEEDED(aFrame->GetSelected(&selected,&beginoffset,&endoffset, &begincontentoffset))){ - nsSelectionStruct ss={nsSelectionStruct::SELON, 0,0, beginoffset, aOffset, 0,0, eDirNext, PR_FALSE}; - aFrame->SetSelected(&ss); - //PR_ASSERT(beginoffset == GetAnchorOffset()); - aTracker->SetFocus(aFrame,anchor); - if (beginoffset <= aOffset) - direction = FORWARD; //selecting "english" right if true - } - else return NS_ERROR_FAILURE; - } - else if (frame){ //we need to check to see what the order is. - nsCOMPtroldContent; - if (NS_SUCCEEDED(frame->GetContent(getter_AddRefs(oldContent))) && oldContent){ - nsCOMPtr oldDomNode(do_QueryInterface(oldContent)); - if (oldDomNode && (oldDomNode.get() == FetchFocusNode())) { - nsCOMPtr anchorContent; - if (NS_SUCCEEDED(anchor->GetContent(getter_AddRefs(anchorContent))) && anchorContent){ - nsCOMPtranchorDomNode(do_QueryInterface(anchorContent)); - if (anchorDomNode && anchorDomNode.get() == FetchAnchorNode()) { - - - //get offsets - PRBool selected = PR_FALSE; - PRInt32 anchorFrameOffsetBegin = 0; - PRInt32 anchorFrameOffsetEnd = 0; - PRInt32 anchorFrameContentOffset = 0; - - if (NS_FAILED(anchor->GetSelected(&selected, &anchorFrameOffsetBegin, &anchorFrameOffsetEnd, &anchorFrameContentOffset)) || !selected) - return NS_ERROR_FAILURE; - - selected = PR_FALSE; - PRInt32 focusFrameOffsetBegin = 0; - PRInt32 focusFrameOffsetEnd = 0; - PRInt32 focusFrameContentOffset = 0; - - if (NS_FAILED(frame->GetSelected(&selected, &focusFrameOffsetBegin, &focusFrameOffsetEnd, &focusFrameContentOffset)) || !selected) - return NS_ERROR_FAILURE; - - //compare anchor to old cursor. - PRInt32 result1 = compareFrames(anchor,frame); //nothing else matters. if they are the same frame. - //compare old cursor to new cursor - PRInt32 result2 = compareFrames(frame,aFrame); - if (result2 == 0) - result2 = ComparePoints(FetchFocusNode(), FetchFocusOffset(), - domNode, aOffset ); - //compare anchor to new cursor - PRInt32 result3 = compareFrames(anchor,aFrame); - if (result3 == 0) - result3 = ComparePoints(FetchAnchorNode(), FetchAnchorOffset(), - domNode , aOffset ); - - if (result1 == 0 && result3 < 0) - { - selectFrames(anchor,anchorFrameOffsetBegin, aFrame, aOffset , eDirNext, nsSelectionStruct::SELON); - } - else if (result1 == 0 && result3 > 0) - { - selectFrames(aFrame, aOffset , anchor,anchorFrameOffsetBegin, eDirPrevious,nsSelectionStruct::SELON); - } - else if (result1 <= 0 && result2 <= 0) {//a,1,2 or a1,2 or a,12 or a12 - //continue selection from 1 to 2 - selectFrames(frame,PR_MIN(focusFrameOffsetEnd,focusFrameOffsetBegin), aFrame, aOffset, eDirNext, nsSelectionStruct::SELON); - } - else if (result3 <= 0 && result2 >= 0) {//a,2,1 or a2,1 or a,21 or a21 - //deselect from 2 to 1 - selectFrames(aFrame, aOffset, frame,focusFrameOffsetEnd, eDirNext, 0); - if (anchor != aFrame) - selectFrames(aFrame, 0, aFrame,aOffset, eDirNext, nsSelectionStruct::SELON); - else - selectFrames(anchor, anchorFrameOffsetBegin, aFrame, aOffset, eDirNext, nsSelectionStruct::SELON); - } - else if (result1 >= 0 && result3 <= 0) {//1,a,2 or 1a,2 or 1,a2 or 1a2 - //deselect from 1 to a - selectFrames(frame, focusFrameOffsetEnd, anchor, anchorFrameOffsetBegin, eDirPrevious, 0); - //select from a to 2 - selectFrames(anchor, anchorFrameOffsetBegin, aFrame, aOffset, eDirNext, nsSelectionStruct::SELON); - } - else if (result2 <= 0 && result3 >= 0) {//1,2,a or 12,a or 1,2a or 12a - //deselect from 1 to 2 - selectFrames(frame, focusFrameOffsetEnd, aFrame, aOffset, eDirPrevious, 0); - if (anchor != aFrame) - selectFrames(aFrame, aOffset, aFrame, -1, eDirPrevious, nsSelectionStruct::SELON); - else - selectFrames(aFrame, aOffset, anchor, anchorFrameOffsetBegin, eDirPrevious, nsSelectionStruct::SELON); - - } - else if (result3 >= 0 && result1 <= 0) {//2,a,1 or 2a,1 or 2,a1 or 2a1 - //deselect from a to 1 - selectFrames(anchor, anchorFrameOffsetBegin, frame, focusFrameOffsetEnd, eDirNext, 0); - //select from 2 to a - selectFrames(aFrame, aOffset, anchor, anchorFrameOffsetBegin, eDirPrevious, nsSelectionStruct::SELON); - } - else if (result2 >= 0 && result1 >= 0) {//2,1,a or 21,a or 2,1a or 21a - //continue selection from 2 to 1 - selectFrames(aFrame, aOffset, frame,PR_MAX(focusFrameOffsetEnd,focusFrameOffsetBegin), eDirPrevious, nsSelectionStruct::SELON); - } - if (result3 <= 0) - direction = FORWARD; - } - aTracker->SetFocus(aFrame,anchor); - } - } - } - } + else if (result1 >= 0 && result3 <= 0) {//1,a,2 or 1a,2 or 1,a2 or 1a2 + result = range->SetStart(focusNode, focusOffset); + result |= range->SetEnd(anchorNode, anchorOffset); + if (NS_FAILED(result)) + return result; + //deselect from 1 to a + selectFrames(range, 0); } - - // Now update the range list: - if (aContinueSelection && domNode) - { - Extend(domNode, aOffset + aContentOffset); + else if (result2 <= 0 && result3 >= 0) {//1,2,a or 12,a or 1,2a or 12a + //deselect from 1 to 2 + result = range->SetEnd(domNode, aContentOffset); + result |= range->SetStart(focusNode, focusOffset); + if (NS_FAILED(result)) + return result; + selectFrames(range, 0); + } + else if (result3 >= 0 && result1 <= 0) {//2,a,1 or 2a,1 or 2,a1 or 2a1 + //deselect from a to 1 + result = range->SetStart(anchorNode, anchorOffset); + result |= range->SetEnd(focusNode, focusOffset); + if (NS_FAILED(result)) + return result; + selectFrames(range, 0); + } + else if (result2 >= 0 && result1 >= 0) {//2,1,a or 21,a or 2,1a or 21a } } + // Now update the range list: + if (aContinueSelection && domNode) + { + Extend(domNode, aContentOffset); + } } - else - return NS_ERROR_FAILURE; return NotifySelectionListeners(); } -//the start frame is the "root" of the tree. we need to traverse the tree to look for the content we want -NS_IMETHODIMP -nsRangeList::ResetSelection(nsIFocusTracker *aTracker, nsIFrame *aStartFrame) +NS_METHOD +nsRangeList::LookUpSelection(nsIContent *aContent, PRInt32 aContentOffset, PRInt32 aContentLength, + PRInt32 *aStart, PRInt32 *aEnd, PRBool *aDrawSelected, PRUint32 aFlag/*not used*/) { - nsCOMPtr startNode; - nsCOMPtr endNode; - PRInt32 startOffset; - PRInt32 endOffset; - nsIFrame *result; - nsresult res; - nsCOMPtr range; - if (!GetNotifyFrames()) - return NS_OK; - if (GetBatching()){ - SetDirty(); - return NS_OK; - } - - //we will need to check if any "side" is the anchor and send a direction order to the frames. - if (!mRangeArray) + if (!aContent || !aStart || !aEnd || !aDrawSelected) + return NS_ERROR_NULL_POINTER; + if (aFlag) + return NS_ERROR_NOT_IMPLEMENTED; + + STATUS_CHECK_RETURN_MACRO(); + //THIS WILL NOT WORK FOR MULTIPLE SELECTIONS YET!!! + nsCOMPtr passedInNode; + passedInNode = do_QueryInterface(aContent); + if (!passedInNode) return NS_ERROR_FAILURE; - //reset the focus and anchor points. - nsCOMPtr anchorContent; - nsCOMPtr frameContent; - if (FetchAnchorNode() && FetchFocusNode()){ - anchorContent = do_QueryInterface(FetchAnchorNode(),&res); - if (NS_SUCCEEDED(res)) - frameContent = do_QueryInterface(FetchFocusNode(),&res); - } - else - res = NS_OK; - if (NS_SUCCEEDED(res)){ - // hack - joe 3/16/99: first tell all frames to unselect - unselectFrames(aStartFrame); - - for (PRUint32 i =0; iCount(); i++){ - //end content and start content do NOT necessarily mean anchor and focus frame respectively - PRInt32 anchorOffset = -1; //the frames themselves can talk to the presentation manager. we will tell them - PRInt32 frameOffset = -1; // where we would "like" to have the anchor pt. actually we count on it. - nsCOMPtr isupportsindex = dont_AddRef(mRangeArray->ElementAt(i)); - range = do_QueryInterface(isupportsindex); - DEBUG_OUT_RANGE(range); + + *aDrawSelected = PR_FALSE; + for (PRUint32 i =0; iCount() && i < 1; i++){ + nsCOMPtr range; + nsCOMPtr isupportsindex = dont_AddRef(mRangeArray->ElementAt(i)); + range = do_QueryInterface(isupportsindex); + if (range){ + nsCOMPtr startNode; + nsCOMPtr endNode; + PRInt32 startOffset; + PRInt32 endOffset; range->GetStartParent(getter_AddRefs(startNode)); range->GetStartOffset(&startOffset); range->GetEndParent(getter_AddRefs(endNode)); range->GetEndOffset(&endOffset); - - nsCOMPtr startContent; - startContent = do_QueryInterface(startNode,&res); - if (startContent){ - res = aTracker->GetPrimaryFrameFor(startContent,&result); - //findFrameFromContent(aStartFrame, startContent,PR_TRUE); - } - if (result && NS_SUCCEEDED(res)){ - nsCOMPtr endContent(do_QueryInterface(endNode)); - if (endContent == startContent){ - if (startContent == frameContent) - frameOffset = FetchFocusOffset(); - if ( startContent == anchorContent ) - anchorOffset = FetchAnchorOffset(); - nsSelectionStruct ss={nsSelectionStruct::SELON|nsSelectionStruct::CHECKANCHOR|nsSelectionStruct::CHECKFOCUS - , startOffset, endOffset, 0,0, anchorOffset,frameOffset, eDirNext, PR_FALSE}; - if (anchorOffset> frameOffset) - ss.mDir = eDirPrevious; - result->SetSelectedContentOffsets(&ss, - aTracker, &result); - } - else{ - if (startContent == frameContent) - frameOffset = FetchFocusOffset(); - if ( startContent == anchorContent ) - anchorOffset = FetchAnchorOffset(); - nsSelectionStruct ss={nsSelectionStruct::SELON|nsSelectionStruct::SELTOEND|nsSelectionStruct::CHECKANCHOR|nsSelectionStruct::CHECKFOCUS - , startOffset, 0, 0,0, anchorOffset,frameOffset, eDirNext, PR_FALSE}; - result->SetSelectedContentOffsets(&ss, aTracker, &result);//select from start to end - - //now we keep selecting until we hit the last content, or the end of the page. - anchorOffset = -1; - frameOffset = -1; - while((result = getNextFrame(result)) != nsnull){ - nsCOMPtr content; - result->GetContent(getter_AddRefs(content)); - if (content == endContent){ - if (endContent == frameContent) - frameOffset = FetchFocusOffset(); - if ( endContent == anchorContent ) - anchorOffset = FetchAnchorOffset(); - nsSelectionStruct ss={nsSelectionStruct::SELON|nsSelectionStruct::CHECKANCHOR|nsSelectionStruct::CHECKFOCUS - , 0, endOffset, 0,0, anchorOffset,frameOffset, eDirNext, PR_FALSE}; - result->SetSelectedContentOffsets(&ss, aTracker, &result);//select from beginning to endOffset - break; - } - else{ - nsSelectionStruct ss={nsSelectionStruct::SELON|nsSelectionStruct::SELTOEND, 0,0, 0,0, 0,0, eDirNext, PR_FALSE}; - result->SetSelected(&ss); - } - } + if (passedInNode == startNode && passedInNode == endNode){ + if (startOffset < (aContentOffset + aContentLength) && + endOffset > aContentOffset){ + *aDrawSelected = PR_TRUE; + *aStart = PR_MAX(0,startOffset - aContentOffset); + *aEnd = PR_MIN(aContentLength, endOffset - aContentOffset); } } - res = ScrollIntoView(aTracker); + else if (passedInNode == startNode){ + if (startOffset < (aContentOffset + aContentLength)){ + *aDrawSelected = PR_TRUE; + *aStart = PR_MAX(0,startOffset - aContentOffset); + *aEnd = aContentLength; + } + } + else if (passedInNode == endNode){ + if (endOffset > aContentOffset){ + *aDrawSelected = PR_TRUE; + *aStart = 0; + *aEnd = PR_MIN(aContentLength, endOffset - aContentOffset); + } + } + else { + *aDrawSelected = PR_TRUE; + *aStart = 0; + *aEnd = aContentLength; + } } + else + return NS_ERROR_FAILURE; } - //printf("debug reset selection has been called\n"); - return res; + return NS_OK; } + NS_METHOD nsRangeList::AddSelectionListener(nsIDOMSelectionListener* inNewListener) { @@ -1198,18 +1058,15 @@ nsRangeList::EndBatchChanges() NS_IMETHODIMP -nsRangeList::ScrollIntoView(nsIFocusTracker *aTracker) +nsRangeList::ScrollIntoView() { - if (!aTracker) - return NS_ERROR_NULL_POINTER; - nsresult result; nsIFrame *anchor; nsIFrame *frame; - result = aTracker->GetFocus(&frame, &anchor); + result = mTracker->GetFocus(&frame, &anchor); if (NS_FAILED(result)) return result; - result = aTracker->ScrollFrameIntoView(frame); + result = mTracker->ScrollFrameIntoView(frame); return result; } @@ -1333,6 +1190,7 @@ nsRangeList::Collapse(nsIDOMNode* aParentNode, PRInt32 aOffset) result = AddItem(range); + selectFrames(range,PR_TRUE); if (NS_FAILED(result)) return result; @@ -1481,6 +1339,10 @@ nsRangeList::Extend(nsIDOMNode* aParentNode, PRInt32 aOffset) setFocus(aParentNode, aOffset); if (NS_FAILED(res)) return res; + + res = selectFrames(range , PR_TRUE); + + if (NS_FAILED(res)) return res; #ifdef DEBUG_SELECTION nsCOMPtrcontent; content = do_QueryInterface(aParentNode); @@ -1506,6 +1368,10 @@ nsRangeList::Extend(nsIDOMNode* aParentNode, PRInt32 aOffset) } if (NS_SUCCEEDED(res)) setFocus(aParentNode, aOffset); + + if (NS_FAILED(res)) return res; + + res = selectFrames(range , PR_TRUE); if (NS_FAILED(res)) return res; #ifdef DEBUG_SELECTION diff --git a/mozilla/layout/generic/nsFrame.cpp b/mozilla/layout/generic/nsFrame.cpp index 86574915ff7..656f5c5d070 100644 --- a/mozilla/layout/generic/nsFrame.cpp +++ b/mozilla/layout/generic/nsFrame.cpp @@ -44,7 +44,6 @@ #include "nsIEventStateManager.h" #include "nsIDOMSelection.h" #include "nsIFrameSelection.h" -#include "nsIFocusTracker.h" #include "nsHTMLParts.h" #include "nsLayoutAtoms.h" @@ -143,7 +142,6 @@ nsIFrame::GetLogModuleInfo() //---------------------------------------------------------------------- static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); -static NS_DEFINE_IID(kIFocusTracker, NS_IFOCUSTRACKER_IID); static NS_DEFINE_IID(kIFrameSelection, NS_IFRAMESELECTION_IID); nsresult NS_NewEmptyFrame(nsIFrame** aInstancePtrResult) @@ -165,7 +163,6 @@ NS_IMPL_ZEROING_OPERATOR_NEW(nsFrame) nsFrame::nsFrame() { mState = NS_FRAME_FIRST_REFLOW | NS_FRAME_SYNC_FRAME_AND_VIEW; - mSelected = PR_FALSE; } nsFrame::~nsFrame() @@ -359,7 +356,8 @@ nsFrame::RemoveFrame(nsIPresContext& aPresContext, NS_IMETHODIMP nsFrame::DeleteFrame(nsIPresContext& aPresContext) { - if (mState & NS_FRAME_EXTERNAL_REFERENCE || mSelected) { + PRBool isGeneratedContent = (mState & NS_FRAME_GENERATED_CONTENT) == NS_FRAME_GENERATED_CONTENT; + if (mState & NS_FRAME_EXTERNAL_REFERENCE || mState & NS_FRAME_SELECTED_CONTENT) { nsCOMPtr shell; nsresult rv = aPresContext.GetShell(getter_AddRefs(shell)); if (NS_SUCCEEDED(rv) && shell) { @@ -696,7 +694,12 @@ nsFrame::Paint(nsIPresContext& aPresContext, PRInt32 n; content->ChildCount(n); - if ((n == 0) && mSelected) { + nsFrameState frameState; + PRBool isSelected; + GetFrameState(&frameState); + isSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + + if ((n == 0) && isSelected) { nsRect rect; GetRect(rect); rect.width--; @@ -784,17 +787,16 @@ nsFrame::HandlePress(nsIPresContext& aPresContext, if (NS_SUCCEEDED(GetPosition(aPresContext, acx, aEvent, this, contentOffset, startPos))){ nsIDOMSelection *selection = nsnull; if (NS_SUCCEEDED(shell->GetSelection(&selection))){ - nsIFocusTracker *tracker; - if (NS_SUCCEEDED(shell->QueryInterface(kIFocusTracker,(void **)&tracker))){ - nsIFrameSelection *frameselection = nsnull; - if (NS_SUCCEEDED(selection->QueryInterface(kIFrameSelection, - (void **)&frameselection))) { + nsIFrameSelection *frameselection = nsnull; + if (NS_SUCCEEDED(selection->QueryInterface(kIFrameSelection, (void **)&frameselection))) { + nsCOMPtr content; + rv = GetContent(getter_AddRefs(content)); + if (NS_SUCCEEDED( rv )){ frameselection->EnableFrameNotification(PR_FALSE); - frameselection->TakeFocus(tracker, this, startPos, contentOffset, inputEvent->isShift); + frameselection->TakeFocus(content, startPos + contentOffset, inputEvent->isShift); frameselection->EnableFrameNotification(PR_TRUE);//prevent cyclic call to reset selection. - NS_RELEASE(frameselection); } - NS_RELEASE(tracker); + NS_RELEASE(frameselection); } NS_RELEASE(selection); } @@ -827,16 +829,16 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsIPresContext& aPresContext, if (NS_SUCCEEDED(GetPosition(aPresContext, acx, aEvent, this, contentOffset, startPos))){ nsIDOMSelection *selection = nsnull; if (NS_SUCCEEDED(shell->GetSelection(&selection))){ - nsIFocusTracker *tracker; - if (NS_SUCCEEDED(shell->QueryInterface(kIFocusTracker,(void **)&tracker))) { - nsIFrameSelection* frameselection; - if (NS_SUCCEEDED(selection->QueryInterface(kIFrameSelection, (void **)&frameselection))) { + nsIFrameSelection* frameselection; + if (NS_SUCCEEDED(selection->QueryInterface(kIFrameSelection, (void **)&frameselection))) { + nsCOMPtr content; + rv = GetContent(getter_AddRefs(content)); + if (NS_SUCCEEDED( rv )){ frameselection->EnableFrameNotification(PR_FALSE); - frameselection->TakeFocus(tracker, this, startPos, contentOffset, PR_TRUE); //TRUE IS THE DIFFERENCE + frameselection->TakeFocus(content, startPos + contentOffset, PR_TRUE); //TRUE IS THE DIFFERENCE frameselection->EnableFrameNotification(PR_TRUE);//prevent cyclic call to reset selection. - NS_RELEASE(frameselection); } - NS_RELEASE(tracker); + NS_RELEASE(frameselection); } NS_RELEASE(selection); } @@ -1561,68 +1563,28 @@ nsFrame::VerifyTree() const /*this method may.. invalidate if the state was changed or if aForceRedraw is PR_TRUE it will not update immediately.*/ NS_IMETHODIMP -nsFrame::SetSelected(nsSelectionStruct *aSelStruct) +nsFrame::SetSelected(nsIDOMRange *aRange,PRBool aSelected, PRBool aSpread) { - if (!aSelStruct) - return NS_ERROR_NULL_POINTER; - if (mSelected != (PRBool)(aSelStruct->mType & nsSelectionStruct::SELON ) || aSelStruct->mForceRedraw) - { - mSelected = aSelStruct->mType & nsSelectionStruct::SELON ; - -/* nsRect rect; - GetRect(rect); - nsIFrame *frame = this; - nsIFrame *firstframe = nsnull; - while (NS_SUCCEEDED(frame->GetPrevInFlow(&frame)) && frame){ - firstframe = frame; - } - - if (firstframe){ - nsRect rect2; - firstframe->GetRect(rect2); - rect.y-= rect.y-rect2.y; - } -*/ - ForceDrawFrame(this);//invalidate does not work in all cases. - //Invalidate(rect,PR_FALSE); //false is for not immediate - } + nsFrameState frameState; + GetFrameState(&frameState); + if ( aSelected ) + frameState |= NS_FRAME_SELECTED_CONTENT; + else + frameState &= ~NS_FRAME_SELECTED_CONTENT; + SetFrameState(frameState); + nsRect frameRect; + GetRect(frameRect); + nsRect rect(0, 0, frameRect.width, frameRect.height); + Invalidate(rect, PR_TRUE); return NS_OK; } NS_IMETHODIMP -nsFrame::SetSelectedContentOffsets(nsSelectionStruct *aSS, - nsIFocusTracker *aTracker, - nsIFrame **aActualSelected) -{ - if (!aActualSelected || !aSS) - return NS_ERROR_NULL_POINTER; - nsIFrame *child = nsnull; - nsresult result = FirstChild(nsnull, &child); - if (NS_FAILED(result)){ - *aActualSelected = this; - if (aSS->mAnchorOffset > 0) - aTracker->SetFocus(nsnull,this); - if (aSS->mFocusOffset > 0) - aTracker->SetFocus(this,nsnull); - return SetSelected(aSS); - } - *aActualSelected = nsnull; - //wont actually bother with selection here on "this" frame - while (child && NS_SUCCEEDED(result)){ - result |= child->SetSelectedContentOffsets(aSS, aTracker, aActualSelected); - if (NS_SUCCEEDED(result) && aActualSelected) - return result; //done. - result |= child->GetNextSibling(&child); - } - return result; -} - -NS_IMETHODIMP -nsFrame::GetSelected(PRBool *aSelected, PRInt32 *aBeginOffset, PRInt32 *aEndOffset, PRInt32 *aBeginContentOffset) +nsFrame::GetSelected(PRBool *aSelected) const { if (!aSelected ) return NS_ERROR_NULL_POINTER; - *aSelected = mSelected; + *aSelected = (PRBool)(mState & NS_FRAME_SELECTED_CONTENT); return NS_OK; } @@ -1647,9 +1609,9 @@ nsFrame::GetChildFrameContainingOffset(PRInt32 inContentOffset, PRInt32* outFram NS_IMETHODIMP nsFrame::PeekOffset(nsSelectionAmount aAmount, nsDirection aDirection, PRInt32 aStartOffset, nsIFrame **aResultFrame, PRInt32 *aFrameOffset, PRInt32 *aContentOffset, - PRBool aEatingWS) + PRBool aEatingWS) const { - //this will use the nsFrameTraversal as the default peek method. +/* //this will use the nsFrameTraversal as the default peek method. //this should change to use geometry and also look to ALL the child lists nsCOMPtr frameTraversal; nsresult result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),LEAF,this); @@ -1673,6 +1635,8 @@ nsFrame::PeekOffset(nsSelectionAmount aAmount, nsDirection aDirection, PRInt32 a nsIFrame *newFrame = (nsIFrame *)isupports; return newFrame->PeekOffset(aAmount, aDirection, aStartOffset, aResultFrame, aFrameOffset, aContentOffset, aEatingWS); + */ + return NS_OK; } //----------------------------------------------------------------------------------- diff --git a/mozilla/layout/generic/nsFrame.h b/mozilla/layout/generic/nsFrame.h index f29c77545e8..ba6c6ccc557 100644 --- a/mozilla/layout/generic/nsFrame.h +++ b/mozilla/layout/generic/nsFrame.h @@ -208,14 +208,11 @@ public: NS_IMETHOD GetFrameName(nsString& aResult) const; NS_IMETHOD DumpRegressionData(FILE* out, PRInt32 aIndent); NS_IMETHOD VerifyTree() const; - NS_IMETHOD SetSelected(nsSelectionStruct *); - NS_IMETHOD SetSelectedContentOffsets(nsSelectionStruct *aSS, - nsIFocusTracker *aTracker, - nsIFrame **aActualSelected); - NS_IMETHOD GetSelected(PRBool *aSelected, PRInt32 *aBeginOffset, PRInt32 *aEndOffset, PRInt32 *aBeginContentOffset); + NS_IMETHOD SetSelected(nsIDOMRange *aRange,PRBool aSelected, PRBool aSpread); + NS_IMETHOD GetSelected(PRBool *aSelected) const; NS_IMETHOD PeekOffset(nsSelectionAmount aAmount, nsDirection aDirection, PRInt32 aStartOffset, nsIFrame **aResultFrame, PRInt32 *aFrameOffset, PRInt32 *aContentOffset, - PRBool aEatingWS); + PRBool aEatingWS)const; NS_IMETHOD GetOffsets(PRInt32 &aStart, PRInt32 &aEnd) const; @@ -352,7 +349,6 @@ protected: nsIFrame* mParent; nsIFrame* mNextSibling; // singly linked list of frames nsFrameState mState; - PRBool mSelected; /////////////////////////////////// // Important Selection Variables diff --git a/mozilla/layout/generic/nsIFrame.h b/mozilla/layout/generic/nsIFrame.h index 4b3cf955caa..a4c88dda639 100644 --- a/mozilla/layout/generic/nsIFrame.h +++ b/mozilla/layout/generic/nsIFrame.h @@ -44,7 +44,7 @@ class nsStyleChangeList; struct nsPoint; struct nsRect; struct nsStyleStruct; -struct nsSelectionStruct; +class nsIDOMRange; struct PRLogModuleInfo; @@ -127,6 +127,9 @@ typedef PRUint32 nsFrameState; // e.g., it is absolutely positioned or floated #define NS_FRAME_OUT_OF_FLOW 0x00000100 +// If this bit is set, then the frame reflects content that may be selected +#define NS_FRAME_SELECTED_CONTENT 0x00000200 + // The low 16 bits of the frame state word are reserved by this API. #define NS_FRAME_RESERVED 0x0000FFFF @@ -579,21 +582,13 @@ public: * Called to set the selection of the frame based on frame offsets. you can FORCE the frame * to redraw event if aSelected == the frame selection with the last parameter. * data in struct may be changed when passed in. - * @param nsSelectionStruct will hold the data pertinant to the Selection, Selected or not ect. + * @param aRange is the range that will dictate if the frames need to be redrawn null means the whole content needs to be redrawn + * @param aSelected is it selected + * @param aSpread should is spread selection to flow elements around it? */ - NS_IMETHOD SetSelected(nsSelectionStruct *) = 0; + NS_IMETHOD SetSelected(nsIDOMRange *aRange,PRBool aSelected, PRBool aSpread) = 0; - /** - * Called to start a selection with this frame content. - * @param aSS is the struct that holds the data instead of passing in so many parameters - * @param aFocusTracker will allow the frame to set the focus to what it needs. - * @param return value of which frame (maybe not this one, maybe one of its siblings) - */ - NS_IMETHOD SetSelectedContentOffsets(nsSelectionStruct *aSS, - nsIFocusTracker *aTracker, - nsIFrame **aActualSelected)=0; - - NS_IMETHOD GetSelected(PRBool *aSelected, PRInt32 *aBeginOffset, PRInt32 *aEndOffset, PRInt32 *aBeginContentOffset) = 0; + NS_IMETHOD GetSelected(PRBool *aSelected) const = 0; /** * called to find the previous/next character, word, or line returns the actual @@ -609,7 +604,7 @@ public: * @param aEatingWS boolean to tell us the state of our search for Next/Prev */ NS_IMETHOD PeekOffset(nsSelectionAmount aAmount, nsDirection aDirection, PRInt32 aStartOffset, - nsIFrame **aResultFrame, PRInt32 *aFrameOffset, PRInt32 *aContentOffset, PRBool aEatingWS) = 0; + nsIFrame **aResultFrame, PRInt32 *aFrameOffset, PRInt32 *aContentOffset, PRBool aEatingWS) const = 0; /** * See if tree verification is enabled. To enable tree verification add diff --git a/mozilla/layout/generic/nsSplittableFrame.cpp b/mozilla/layout/generic/nsSplittableFrame.cpp index fc965eff70b..3009b46007e 100644 --- a/mozilla/layout/generic/nsSplittableFrame.cpp +++ b/mozilla/layout/generic/nsSplittableFrame.cpp @@ -45,6 +45,9 @@ nsSplittableFrame::Init(nsIPresContext& aPresContext, if (state & NS_FRAME_REPLACED_ELEMENT) { mState |= NS_FRAME_REPLACED_ELEMENT; } + if (state & NS_FRAME_SELECTED_CONTENT) { + mState |= NS_FRAME_SELECTED_CONTENT; + } } return rv; diff --git a/mozilla/layout/generic/nsTextFrame.cpp b/mozilla/layout/generic/nsTextFrame.cpp index b231922ac38..8f46fa50410 100644 --- a/mozilla/layout/generic/nsTextFrame.cpp +++ b/mozilla/layout/generic/nsTextFrame.cpp @@ -52,6 +52,8 @@ #include "nsTextTransformer.h" #include "nsLayoutAtoms.h" #include "nsIFrameSelection.h" +#include "nsIDOMSelection.h" +#include "nsIDOMRange.h" static NS_DEFINE_IID(kIDOMTextIID, NS_IDOMTEXT_IID); @@ -229,14 +231,19 @@ public: PRUint32& aActualContentOffset, PRInt32& aOffset); - NS_IMETHOD SetSelected(nsSelectionStruct *aSS); - NS_IMETHOD SetSelectedContentOffsets(nsSelectionStruct *aSS, - nsIFocusTracker *aTracker, - nsIFrame **aActualSelected); - NS_IMETHOD GetSelected(PRBool *aSelected, PRInt32 *aBeginOffset, PRInt32 *aEndOffset, PRInt32 *aBeginContentOffset); + NS_IMETHOD GetPositionSlowly(nsIPresContext& aCX, + nsIRenderingContext * aRendContext, + nsGUIEvent* aEvent, + nsIFrame * aNewFrame, + PRUint32& aActualContentOffset, + PRInt32& aOffset); + + + NS_IMETHOD SetSelected(nsIDOMRange *aRange,PRBool aSelected, PRBool aSpread); + NS_IMETHOD PeekOffset(nsSelectionAmount aAmount, nsDirection aDirection, PRInt32 aStartOffset, nsIFrame **aResultFrame, PRInt32 *aFrameOffset, PRInt32 *aContentOffset, - PRBool aEatingWS); + PRBool aEatingWS)const; NS_IMETHOD GetOffsets(PRInt32 &start, PRInt32 &end)const; @@ -337,13 +344,6 @@ public: nsIDocument* GetDocument(nsIPresContext* aPresContext); - nsresult GetPositionSlowly(nsIPresContext* aCX, - nsIRenderingContext * aRendContext, - nsGUIEvent* aEvent, - nsIFrame * aNewFrame, - PRUint32* aActualContentOffset, - PRInt32* aOffset); - PRIntn PrepareUnicodeText(nsTextTransformer& aTransformer, PRInt32* aIndicies, PRUnichar* aBuffer, @@ -415,8 +415,6 @@ protected: PRInt32 mColumn; nscoord mComputedWidth; - PRUint32 mSelectionOffset; - PRUint32 mSelectionEnd; }; // Flag information used by rendering code. This information is @@ -458,8 +456,6 @@ nsTextFrame::nsTextFrame() // Create text timer the first time out gTextBlinker = new nsBlinkTimer(); } - mSelectionOffset = PRUint32(-1); - mSelectionEnd = PRUint32(-1); NS_ADDREF(gTextBlinker); } @@ -835,10 +831,13 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, PrepareUnicodeText(tx, (displaySelection ? ip : nsnull), paintBuf, &textLength); PRUnichar* text = paintBuf; + nsFrameState frameState; + PRBool isSelected; + GetFrameState(&frameState); + isSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + if (0 != textLength) { - if (!displaySelection || !mSelected || - (mSelectionOffset > PRUint32(mContentLength))) { - //if selection is > content length then selection has "slid off" + if (!displaySelection || !isSelected ) { // When there is no selection showing, use the fastest and // simplest rendering approach aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy); @@ -851,89 +850,98 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, //must set up last one for selection beyond edge if in boundary ip[mContentLength]++; } + PRInt32 textWidth; + PRInt32 selectionStartOffset = 0;//frame coordinates + PRInt32 selectionEndOffset = 0;//frame coordinates + + nsCOMPtr shell; + nsCOMPtr selection; + nsCOMPtr frameSelection; + PRBool drawSelected = PR_FALSE; + + nsresult rv = aPresContext->GetShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(rv) && shell){ + rv = shell->GetSelection(getter_AddRefs(selection)); + if (NS_SUCCEEDED(rv) && selection){ + frameSelection = do_QueryInterface(selection); + nsCOMPtr content; + rv = GetContent(getter_AddRefs(content)); + if (NS_SUCCEEDED(rv)){ + rv = frameSelection->LookUpSelection(content, mContentOffset, + mContentLength , &selectionStartOffset, &selectionEndOffset, + &drawSelected,0);// last param notused + } + } + } + - nscoord textWidth; - if (mSelectionOffset < 0) - mSelectionOffset = 0; - if (mSelectionEnd < 0) - mSelectionEnd = mContentLength; - if (mSelectionEnd > PRUint32(mContentLength)) - mSelectionEnd = PRUint32(mContentLength); - if (mSelectionOffset > PRUint32(mContentLength)) - mSelectionOffset = PRUint32(mContentLength); - PRInt32 selectionEnd = mSelectionEnd; - PRInt32 selectionOffset = mSelectionOffset; - if (mSelectionEnd < mSelectionOffset) - { - selectionEnd = mSelectionOffset; - selectionOffset = mSelectionEnd; - } - //where are the selection points "really" - selectionOffset = ip[selectionOffset] - mContentOffset; - selectionEnd = ip[selectionEnd] - mContentOffset; - if (selectionOffset == selectionEnd) { - aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy); - PaintTextDecorations(aRenderingContext, aStyleContext, - aTextStyle, dx, dy, width); - //shell->RefreshCaret(); - -#ifdef SHOW_SELECTION_CURSOR - aRenderingContext.GetWidth(text, PRUint32(selectionOffset), textWidth); - - RenderSelectionCursor(aRenderingContext, - dx + textWidth, dy, mRect.height, - CURSOR_COLOR); -#endif - } - else { - nscoord x = dx; - - if (selectionOffset) { - // Render first (unselected) section - aRenderingContext.GetWidth(text, PRUint32(selectionOffset),//si.mStartOffset), - textWidth); - aRenderingContext.DrawString(text, PRUint32(selectionOffset), - x, dy); - PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, - x, dy, textWidth); - x += textWidth; + if (frameSelection ){ + //where are the selection points "really" + if (drawSelected){ + selectionStartOffset = ip[selectionStartOffset] - mContentOffset; + selectionEndOffset = ip[selectionEndOffset] - mContentOffset; } - PRInt32 secondLen = selectionEnd - selectionOffset; - if (0 != secondLen) { - // Get the width of the second (selected) section - aRenderingContext.GetWidth(text + selectionOffset, - PRUint32(secondLen), textWidth); + if (!drawSelected || (selectionStartOffset == selectionEndOffset)) { + aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy); + PaintTextDecorations(aRenderingContext, aStyleContext, + aTextStyle, dx, dy, width); + #ifdef SHOW_SELECTION_CURSOR + aRenderingContext.GetWidth(text, PRUint32(selectionStartOffset), textWidth); - // Render second (selected) section - aRenderingContext.SetColor(aTextStyle.mSelectionBGColor); - aRenderingContext.FillRect(x, dy, textWidth, mRect.height); - aRenderingContext.SetColor(aTextStyle.mSelectionTextColor); - aRenderingContext.DrawString(text + selectionOffset, - PRUint32(secondLen), x, dy); - PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, - x, dy, textWidth); - aRenderingContext.SetColor(aTextStyle.mColor->mColor); - x += textWidth; + RenderSelectionCursor(aRenderingContext, + dx + textWidth, dy, mRect.height, + CURSOR_COLOR); + #endif } - if (textLength != selectionEnd) { - PRInt32 thirdLen = textLength - selectionEnd; + else { + nscoord x = dx; - if (thirdLen > 0) //Text length is not negative or zero - { - - // Render third (unselected) section - aRenderingContext.GetWidth(text + selectionEnd, PRUint32(thirdLen), + if (selectionStartOffset) { + // Render first (unselected) section + aRenderingContext.GetWidth(text, PRUint32(selectionStartOffset),//si.mStartOffset), textWidth); - aRenderingContext.DrawString(text + selectionEnd, - PRUint32(thirdLen), x, dy); + aRenderingContext.DrawString(text, PRUint32(selectionStartOffset), + x, dy); PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, x, dy, textWidth); + x += textWidth; + } + PRInt32 secondLen = selectionEndOffset - selectionStartOffset; + if (0 != secondLen) { + // Get the width of the second (selected) section + aRenderingContext.GetWidth(text + selectionStartOffset, + PRUint32(secondLen), textWidth); + + // Render second (selected) section + aRenderingContext.SetColor(aTextStyle.mSelectionBGColor); + aRenderingContext.FillRect(x, dy, textWidth, mRect.height); + aRenderingContext.SetColor(aTextStyle.mSelectionTextColor); + aRenderingContext.DrawString(text + selectionStartOffset, + PRUint32(secondLen), x, dy); + PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, + x, dy, textWidth); + aRenderingContext.SetColor(aTextStyle.mColor->mColor); + x += textWidth; + } + if (textLength != selectionEndOffset) { + PRInt32 thirdLen = textLength - selectionEndOffset; + + if (thirdLen > 0) //Text length is not negative or zero + { + + // Render third (unselected) section + aRenderingContext.GetWidth(text + selectionEndOffset, PRUint32(thirdLen), + textWidth); + aRenderingContext.DrawString(text + selectionEndOffset, + PRUint32(thirdLen), x, dy); + PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, + x, dy, textWidth); + } } } } } } - // Cleanup if (paintBuf != paintBufMem) { delete [] paintBuf; @@ -945,24 +953,24 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, //measure Spaced Textvoid nsresult -nsTextFrame::GetPositionSlowly(nsIPresContext* aPresContext, +nsTextFrame::GetPositionSlowly(nsIPresContext& aPresContext, nsIRenderingContext* aRendContext, nsGUIEvent* aEvent, nsIFrame* aNewFrame, - PRUint32* aAcutalContentOffset, - PRInt32* aOffset) + PRUint32& aAcutalContentOffset, + PRInt32& aOffset) { if (!aRendContext || !aEvent || !aNewFrame) { return NS_ERROR_NULL_POINTER; } - TextStyle ts(aPresContext, *aRendContext, mStyleContext); + TextStyle ts(&aPresContext, *aRendContext, mStyleContext); if (!ts.mSmallCaps && !ts.mWordSpacing && !ts.mLetterSpacing) { return NS_ERROR_INVALID_ARG; } - nsCOMPtr doc(getter_AddRefs(GetDocument(aPresContext))); + nsCOMPtr doc(getter_AddRefs(GetDocument(&aPresContext))); // Make enough space to transform PRUnichar paintBufMem[TEXT_BUF_SIZE]; @@ -1026,12 +1034,12 @@ nsTextFrame::GetPositionSlowly(nsIPresContext* aPresContext, } if ((aEvent->point.x - origin.x) >= widthsofar && (aEvent->point.x - origin.x) <= (widthsofar + glyphWidth)){ if ( ((aEvent->point.x - origin.x) - widthsofar) <= (glyphWidth /2)){ - *aOffset = index; + aOffset = index; found = PR_TRUE; break; } else{ - *aOffset = index+1; + aOffset = index+1; found = PR_TRUE; break; } @@ -1044,13 +1052,13 @@ nsTextFrame::GetPositionSlowly(nsIPresContext* aPresContext, } paintBuf = startBuf; if (!found){ - *aOffset = textLength; + aOffset = textLength; } - *aAcutalContentOffset = mContentOffset;//offset;//((nsTextFrame *)aNewFrame)->mContentOffset; + aAcutalContentOffset = mContentOffset;//offset;//((nsTextFrame *)aNewFrame)->mContentOffset; PRInt32 i; for (i = 0;i <= mContentLength; i ++){ - if (ip[i] == *aOffset + mContentOffset){ //reverse mapping - *aOffset = i; + if (ip[i] == aOffset + mContentOffset){ //reverse mapping + aOffset = i; break; } } @@ -1319,9 +1327,12 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext, } PRUnichar* text = paintBuf; + nsFrameState frameState; + PRBool isSelected; + GetFrameState(&frameState); + isSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; if (0 != textLength) { - if (!displaySelection || !mSelected || - (mSelectionOffset > PRUint32(mContentLength))) { + if (!displaySelection || !isSelected) { // When there is no selection showing, use the fastest and // simplest rendering approach RenderString(aRenderingContext, aStyleContext, aTextStyle, @@ -1329,89 +1340,99 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext, } else { ip[mContentLength] = ip[mContentLength-1]; - if ((ip[mContentLength]-mContentOffset) < textLength)//must set up last one for selection beyond edge if in boundary + if ((ip[mContentLength]-mContentOffset) < textLength) { + //must set up last one for selection beyond edge if in boundary ip[mContentLength]++; - nscoord textWidth; - if (mSelectionOffset < 0) - mSelectionOffset = 0; - if (mSelectionEnd < 0) - mSelectionEnd = PRUint32(mContentLength); - if (mSelectionEnd > PRUint32(mContentLength)) - mSelectionEnd = PRUint32(mContentLength); - if (mSelectionOffset > PRUint32(mContentLength)) - mSelectionOffset = PRUint32(mContentLength); - PRInt32 selectionEnd = mSelectionEnd; - PRInt32 selectionOffset = mSelectionOffset; - if (mSelectionEnd < mSelectionOffset) - { - selectionEnd = mSelectionOffset; - selectionOffset = mSelectionEnd; } - //where are the selection points "really" - selectionOffset = ip[selectionOffset] - mContentOffset; - selectionEnd = ip[selectionEnd] - mContentOffset; - if (selectionOffset == selectionEnd){ - RenderString(aRenderingContext, aStyleContext, aTextStyle, - text, textLength, dx, dy, width); + PRInt32 selectionStartOffset = 0;//frame coordinates + PRInt32 selectionEndOffset = 0;//frame coordinates + PRInt32 textWidth; + nsCOMPtr shell; + nsCOMPtr selection; + nsCOMPtr frameSelection; + PRBool drawSelected = PR_FALSE; + nsresult rv = aPresContext->GetShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(rv) && shell){ + rv = shell->GetSelection(getter_AddRefs(selection)); + if (NS_SUCCEEDED(rv) && selection){ + frameSelection = do_QueryInterface(selection); + nsCOMPtr content; + rv = GetContent(getter_AddRefs(content)); + if (NS_SUCCEEDED(rv)){ + rv = frameSelection->LookUpSelection(content, mContentOffset, + mContentLength , &selectionStartOffset, &selectionEndOffset, + &drawSelected, 0);// last param notused + } + } + } - //shell->RefreshCaret(); + + if (frameSelection){ + //where are the selection points "really" + if (drawSelected) { + selectionStartOffset = ip[selectionStartOffset] - mContentOffset; + selectionEndOffset = ip[selectionEndOffset] - mContentOffset; + } + if (!drawSelected || (selectionStartOffset == selectionEndOffset)){ + RenderString(aRenderingContext, aStyleContext, aTextStyle, + text, textLength, dx, dy, width); #ifdef SHOW_SELECTION_CURSOR GetWidth(aRenderingContext, aTextStyle, - text, PRUint32(selectionOffset), &textWidth); + text, PRUint32(selectionStartOffset), &textWidth); RenderSelectionCursor(aRenderingContext, dx + textWidth, dy, mRect.height, CURSOR_COLOR); #endif - } - else { - nscoord x = dx; - - if (selectionOffset) { - // Render first (unselected) section - GetWidth(aRenderingContext, aTextStyle, - text, PRUint32(selectionOffset), - &textWidth); - RenderString(aRenderingContext, aStyleContext, aTextStyle, - text, selectionOffset, - x, dy, textWidth); - x += textWidth; } - PRInt32 secondLen = selectionEnd - selectionOffset; - if (0 != secondLen) { - // Get the width of the second (selected) section - GetWidth(aRenderingContext, aTextStyle, - text + selectionOffset, - PRUint32(secondLen), &textWidth); + else { + nscoord x = dx; - // Render second (selected) section - aRenderingContext.SetColor(aTextStyle.mSelectionBGColor); - aRenderingContext.FillRect(x, dy, textWidth, mRect.height); - aRenderingContext.SetColor(aTextStyle.mSelectionTextColor); - RenderString(aRenderingContext, aStyleContext, aTextStyle, - text + selectionOffset, secondLen, - x, dy, textWidth); - aRenderingContext.SetColor(aTextStyle.mColor->mColor); - x += textWidth; - } - if (textLength != selectionEnd) { - PRInt32 thirdLen = textLength - selectionEnd; - - // Render third (unselected) section - if (thirdLen > 0) //Text length is not negative or zero - { + if (selectionStartOffset) { + // Render first (unselected) section GetWidth(aRenderingContext, aTextStyle, - text + selectionOffset, PRUint32(thirdLen), + text, PRUint32(selectionStartOffset), &textWidth); RenderString(aRenderingContext, aStyleContext, aTextStyle, - text + selectionEnd, - thirdLen, x, dy, textWidth); + text, selectionStartOffset, + x, dy, textWidth); + x += textWidth; + } + PRInt32 secondLen = selectionEndOffset - selectionStartOffset; + if (0 != secondLen) { + // Get the width of the second (selected) section + GetWidth(aRenderingContext, aTextStyle, + text + selectionStartOffset, + PRUint32(secondLen), &textWidth); + + // Render second (selected) section + aRenderingContext.SetColor(aTextStyle.mSelectionBGColor); + aRenderingContext.FillRect(x, dy, textWidth, mRect.height); + aRenderingContext.SetColor(aTextStyle.mSelectionTextColor); + RenderString(aRenderingContext, aStyleContext, aTextStyle, + text + selectionStartOffset, secondLen, + x, dy, textWidth); + aRenderingContext.SetColor(aTextStyle.mColor->mColor); + x += textWidth; + } + if (textLength != selectionEndOffset) { + PRInt32 thirdLen = textLength - selectionEndOffset; + + // Render third (unselected) section + if (thirdLen > 0) //Text length is not negative or zero + { + GetWidth(aRenderingContext, aTextStyle, + text + selectionStartOffset, PRUint32(thirdLen), + &textWidth); + RenderString(aRenderingContext, aStyleContext, aTextStyle, + text + selectionEndOffset, + thirdLen, x, dy, textWidth); + } } } } } } - // Cleanup if (paintBuf != paintBufMem) { delete [] paintBuf; @@ -1466,9 +1487,13 @@ nsTextFrame::PaintAsciiText(nsIPresContext* aPresContext, } char* text = paintBuf; + nsFrameState frameState; + PRBool isSelected; + GetFrameState(&frameState); + isSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + if (0 != textLength) { - if (!displaySelection || !mSelected || - (mSelectionOffset > PRUint32(mContentLength))) { + if (!displaySelection || !isSelected) { //if selection is > content length then selection has "slid off" // When there is no selection showing, use the fastest and // simplest rendering approach @@ -1478,85 +1503,97 @@ nsTextFrame::PaintAsciiText(nsIPresContext* aPresContext, } else { ip[mContentLength] = ip[mContentLength-1]; - if ((ip[mContentLength]-mContentOffset) < textLength)//must set up last one for selection beyond edge if in boundary + if ((ip[mContentLength]-mContentOffset) < textLength) { + //must set up last one for selection beyond edge if in boundary ip[mContentLength]++; - nscoord textWidth; - if (mSelectionOffset < 0) - mSelectionOffset = 0; - if (mSelectionEnd < 0) - mSelectionEnd = mContentLength; - if (mSelectionEnd > PRUint32(mContentLength)) - mSelectionEnd = PRUint32(mContentLength); - if (mSelectionOffset > PRUint32(mContentLength)) - mSelectionOffset = PRUint32(mContentLength); - PRInt32 selectionEnd = mSelectionEnd; - PRInt32 selectionOffset = mSelectionOffset; - if (mSelectionEnd < mSelectionOffset) - { - selectionEnd = mSelectionOffset; - selectionOffset = mSelectionEnd; } - //where are the selection points "really" - selectionOffset = ip[selectionOffset] - mContentOffset; - selectionEnd = ip[selectionEnd] - mContentOffset; - if (selectionOffset == selectionEnd){ - aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy); - PaintTextDecorations(aRenderingContext, aStyleContext, - aTextStyle, dx, dy, width); - //shell->RefreshCaret(); - -#ifdef SHOW_SELECTION_CURSOR - aRenderingContext.GetWidth(text, PRUint32(selectionOffset), textWidth); - - RenderSelectionCursor(aRenderingContext, - dx + textWidth, dy, mRect.height, - CURSOR_COLOR); -#endif + PRInt32 selectionStartOffset = 0;//frame coordinates + PRInt32 selectionEndOffset = 0;//frame coordinates + PRInt32 textWidth; + nsCOMPtr shell; + nsCOMPtr selection; + nsCOMPtr frameSelection; + PRBool drawSelected = PR_FALSE; + nsresult rv = aPresContext->GetShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(rv) && shell){ + rv = shell->GetSelection(getter_AddRefs(selection)); + if (NS_SUCCEEDED(rv) && selection){ + frameSelection = do_QueryInterface(selection); + nsCOMPtr content; + rv = GetContent(getter_AddRefs(content)); + if (NS_SUCCEEDED(rv)){ + rv = frameSelection->LookUpSelection(content, mContentOffset, + mContentLength , &selectionStartOffset, &selectionEndOffset, + &drawSelected, 0);// last param notused + } + } } - else - { - nscoord x = dx; - if (selectionOffset) { - // Render first (unselected) section - aRenderingContext.GetWidth(text, PRUint32(selectionOffset),//si.mStartOffset), - textWidth); - aRenderingContext.DrawString(text, PRUint32(selectionOffset), - x, dy); - PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, - x, dy, textWidth); - x += textWidth; + + if (frameSelection){ + //where are the selection points "really" + if (drawSelected) { + selectionStartOffset = ip[selectionStartOffset] - mContentOffset; + selectionEndOffset = ip[selectionEndOffset] - mContentOffset; } - PRInt32 secondLen = selectionEnd - selectionOffset; - if (0 != secondLen) { - // Get the width of the second (selected) section - aRenderingContext.GetWidth(text + selectionOffset, - PRUint32(secondLen), textWidth); + if (!drawSelected || (selectionStartOffset == selectionEndOffset)){ + aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy); + PaintTextDecorations(aRenderingContext, aStyleContext, + aTextStyle, dx, dy, width); + //shell->RefreshCaret(); + + #ifdef SHOW_SELECTION_CURSOR + aRenderingContext.GetWidth(text, PRUint32(selectionStartOffset), textWidth); - // Render second (selected) section - aRenderingContext.SetColor(aTextStyle.mSelectionBGColor); - aRenderingContext.FillRect(x, dy, textWidth, mRect.height); - aRenderingContext.SetColor(aTextStyle.mSelectionTextColor); - aRenderingContext.DrawString(text + selectionOffset, - PRUint32(secondLen), x, dy); - PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, - x, dy, textWidth); - aRenderingContext.SetColor(aTextStyle.mColor->mColor); - x += textWidth; + RenderSelectionCursor(aRenderingContext, + dx + textWidth, dy, mRect.height, + CURSOR_COLOR); + #endif } - if (textLength != selectionEnd) { - PRInt32 thirdLen = textLength - selectionEnd; + else { + nscoord x = dx; - if (thirdLen > 0) //Text length is not negative or zero - { - - // Render third (unselected) section - aRenderingContext.GetWidth(text + selectionEnd, PRUint32(thirdLen), + if (selectionStartOffset) { + // Render first (unselected) section + aRenderingContext.GetWidth(text, PRUint32(selectionStartOffset),//si.mStartOffset), textWidth); - aRenderingContext.DrawString(text + selectionEnd, - PRUint32(thirdLen), x, dy); + aRenderingContext.DrawString(text, PRUint32(selectionStartOffset), + x, dy); PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, x, dy, textWidth); + x += textWidth; + } + PRInt32 secondLen = selectionEndOffset - selectionStartOffset; + if (0 != secondLen) { + // Get the width of the second (selected) section + aRenderingContext.GetWidth(text + selectionStartOffset, + PRUint32(secondLen), textWidth); + + // Render second (selected) section + aRenderingContext.SetColor(aTextStyle.mSelectionBGColor); + aRenderingContext.FillRect(x, dy, textWidth, mRect.height); + aRenderingContext.SetColor(aTextStyle.mSelectionTextColor); + aRenderingContext.DrawString(text + selectionStartOffset, + PRUint32(secondLen), x, dy); + PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, + x, dy, textWidth); + aRenderingContext.SetColor(aTextStyle.mColor->mColor); + x += textWidth; + } + if (textLength != selectionEndOffset) { + PRInt32 thirdLen = textLength - selectionEndOffset; + + if (thirdLen > 0) //Text length is not negative or zero + { + + // Render third (unselected) section + aRenderingContext.GetWidth(text + selectionEndOffset, PRUint32(thirdLen), + textWidth); + aRenderingContext.DrawString(text + selectionEndOffset, + PRUint32(thirdLen), x, dy); + PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, + x, dy, textWidth); + } } } } @@ -1611,7 +1648,7 @@ BinarySearchForPosition(nsIRenderingContext* acx, } PRInt32 inx = aStartInx + (range / 2); - PRInt32 textWidth; + PRInt32 textWidth = 0; acx->GetWidth(aText, inx, textWidth); PRInt32 fullWidth = aBaseWidth + textWidth; @@ -1648,8 +1685,8 @@ nsTextFrame::GetPosition(nsIPresContext& aPresContext, { TextStyle ts(&aPresContext, *aRendContext, mStyleContext); if (ts.mSmallCaps || ts.mWordSpacing || ts.mLetterSpacing) { - return GetPositionSlowly(&aPresContext, aRendContext, aEvent, aNewFrame, - &aActualContentOffset, &aOffset); + return GetPositionSlowly(aPresContext, aRendContext, aEvent, aNewFrame, + aActualContentOffset, aOffset); } PRUnichar wordBufMem[WORD_BUF_SIZE]; @@ -1690,7 +1727,7 @@ nsTextFrame::GetPosition(nsIPresContext& aPresContext, } PRInt32 index; - PRInt32 textWidth; + PRInt32 textWidth = 0; PRUnichar* text = paintBuf; nsPoint origin; nsIView * view; @@ -1742,129 +1779,83 @@ nsTextFrame::GetPosition(nsIPresContext& aPresContext, return NS_OK; } -NS_IMETHODIMP -nsTextFrame::SetSelected(nsSelectionStruct *aSelStruct) -{ - if (!aSelStruct) - return NS_ERROR_NULL_POINTER; - if (aSelStruct->mType & nsSelectionStruct::SELON){ - aSelStruct->mEndFrame = PR_MIN(aSelStruct->mEndFrame, (PRUint32) mContentLength); - aSelStruct->mStartFrame= PR_MIN(aSelStruct->mStartFrame, (PRUint32) mContentLength); - if (aSelStruct->mType & nsSelectionStruct::SELTOEND) - aSelStruct->mEndFrame = mContentLength; - if (aSelStruct->mType & nsSelectionStruct::SELTOBEGIN) - aSelStruct->mStartFrame = 0; - PRUint32 trueBegin(aSelStruct->mStartFrame); - PRUint32 trueEnd(aSelStruct->mEndFrame); - if (aSelStruct->mDir == eDirPrevious){//change the settings around, - //the frame doesnt track direction it only tracks begin and end. - trueBegin = aSelStruct->mEndFrame; - trueEnd = aSelStruct->mStartFrame; - } - - if (mSelectionOffset != trueBegin || mSelectionEnd != trueEnd) - { -//XXX PRBool wasCollapsed = (mSelectionOffset == mSelectionEnd); - mSelectionOffset = trueBegin; - mSelectionEnd = trueEnd; - // XXX when we no longer rely on the blue triangle to show the selection - // position (using the caret instead), then we can uncomment this to reduce - // redrawing. sfraser - aSelStruct->mForceRedraw = PR_TRUE; //!wasCollapsed || (trueBegin != trueEnd); - } - } - return nsFrame::SetSelected(aSelStruct);//this will do the actual - //turning on of the mSelected flag in the nsframe header. -} +// [HACK] Foward Declarations +void ForceDrawFrame(nsFrame * aFrame); NS_IMETHODIMP -nsTextFrame::SetSelectedContentOffsets(nsSelectionStruct *aSS, - nsIFocusTracker *aTracker, - nsIFrame **aActualSelected) +nsTextFrame::SetSelected(nsIDOMRange *aRange,PRBool aSelected, PRBool aSpread) { - if (!aActualSelected || !aSS) + if (!aRange) return NS_ERROR_NULL_POINTER; + nsresult result; + if (aSpread){ + nsIFrame *frame = GetPrevInFlow(); + while(frame){ + frame->SetSelected(aRange,aSelected,PR_FALSE); + result = frame->GetPrevInFlow(&frame); + if (NS_FAILED(result)) + break; + } + frame = GetNextInFlow(); + while(frame){ + frame->SetSelected(aRange,aSelected,PR_FALSE); + result = frame->GetNextInFlow(&frame); + if (NS_FAILED(result)) + break; + } + } + //lets see if the range contains us, if so we must redraw! + nsCOMPtr endNode; + PRInt32 endOffset; + nsCOMPtr startNode; + PRInt32 startOffset; + aRange->GetEndParent(getter_AddRefs(endNode)); + aRange->GetEndOffset(&endOffset); + aRange->GetStartParent(getter_AddRefs(startNode)); + aRange->GetStartOffset(&startOffset); + nsCOMPtr content; + result = GetContent(getter_AddRefs(content)); + nsCOMPtr thisNode; + thisNode = do_QueryInterface(content); - PRInt32 beginOffset(aSS->mStartContent - mContentOffset); - if (beginOffset > mContentLength){ - //this is not the droid we are looking for. keep looking - nsSelectionStruct ss = {0};//turn it ALL off - ss.mForceRedraw = aSS->mForceRedraw; - SetSelected(&ss); - nsIFrame *nextInFlow =GetNextInFlow(); - if (nextInFlow) - return nextInFlow->SetSelectedContentOffsets(aSS, aTracker, aActualSelected); - else - return NS_ERROR_FAILURE; - } - if (aSS->mType & nsSelectionStruct::CHECKANCHOR && aSS->mAnchorOffset == aSS->mStartContent ){ - aTracker->SetFocus(nsnull, this); - aSS->mType = aSS->mType-nsSelectionStruct::CHECKANCHOR; - } - if (aSS->mType & nsSelectionStruct::CHECKFOCUS && aSS->mFocusOffset == aSS->mStartContent ){ - aTracker->SetFocus(this, nsnull); - aSS->mType = aSS->mType-nsSelectionStruct::CHECKFOCUS; - } - *aActualSelected = this; - - nsIFrame *nextInFlow = GetNextInFlow(); - if (nextInFlow){ - if (aSS->mType & nsSelectionStruct::SELTOEND || aSS->mEndContent > PRUint32(mContentLength + mContentOffset)){ - nextInFlow->SetSelectedContentOffsets(aSS, aTracker ,aActualSelected); - } - else if (aSS->mType & nsSelectionStruct::SELON) { //we must shut off all folowing selected frames if we are selecting frames - if (aSS->mType & nsSelectionStruct::CHECKANCHOR && aSS->mAnchorOffset == aSS->mEndContent ){ - aTracker->SetFocus(nsnull, this); - aSS->mType = aSS->mType - nsSelectionStruct::CHECKANCHOR; + PRBool found = PR_FALSE; + if (thisNode == startNode){ + if ((mContentOffset + mContentLength) >= startOffset){ + found = PR_TRUE; + if (thisNode == endNode){ //special case +/*#ifndef SHOW_SELECTION_CURSOR + if (aSelected && (endOffset == startOffset)) //no need to redraw since drawing takes place with cursor + found = PR_FALSE; +#endif +*/ + if (mContentOffset > endOffset) + found = PR_FALSE; } - if (aSS->mType & nsSelectionStruct::CHECKFOCUS && aSS->mFocusOffset == aSS->mEndContent ){ - aTracker->SetFocus(this, nsnull); - aSS->mType = aSS->mType - nsSelectionStruct::CHECKFOCUS; - } - nsSelectionStruct ss={0, 0,0, 0,0, 0,0, eDirNext, aSS->mForceRedraw}; - do { - nextInFlow->SetSelected(&ss); - } - while (NS_SUCCEEDED(nextInFlow->GetNextInFlow(&nextInFlow)) && nextInFlow);//this is ok because frames arent reference counted this is not a leak! } } - else { - if (aSS->mType & nsSelectionStruct::CHECKANCHOR && aSS->mAnchorOffset == aSS->mEndContent ){ - aTracker->SetFocus(nsnull, this); - aSS->mType = aSS->mType - nsSelectionStruct::CHECKANCHOR; - } - if (aSS->mType & nsSelectionStruct::CHECKFOCUS && aSS->mFocusOffset == aSS->mEndContent ){ - aTracker->SetFocus(this, nsnull); - aSS->mType = aSS->mType - nsSelectionStruct::CHECKFOCUS; - } - } - if (PRUint32(mContentOffset) > aSS->mStartContent){ - aSS->mStartFrame = 0; - } else - aSS->mStartFrame = aSS->mStartContent - mContentOffset; - aSS->mEndFrame = aSS->mEndContent - mContentOffset; - return SetSelected(aSS); -} - -NS_IMETHODIMP -nsTextFrame::GetSelected(PRBool *aSelected, - PRInt32 *aBeginOffset, - PRInt32 *aEndOffset, - PRInt32 *aBeginContentOffset) -{ - if (!aSelected || !aBeginOffset || !aEndOffset || !aBeginContentOffset) - return NS_ERROR_NULL_POINTER; - *aBeginOffset = mSelectionOffset; - *aEndOffset = mSelectionEnd; - *aSelected = mSelected; - *aBeginContentOffset = mContentOffset; -//should we check for whitespace here? dont think so. + if (thisNode == endNode){ + if (mContentOffset < endOffset) + found = PR_TRUE; + } + if (found){ //if range contains this frame... +/* nsRect frameRect; + GetRect(frameRect); + nsRect rect(0, 0, frameRect.width, frameRect.height); + Invalidate(rect, PR_FALSE); +*/ ForceDrawFrame(this); + } + nsFrameState frameState; + GetFrameState(&frameState); + if ( aSelected ) + frameState |= NS_FRAME_SELECTED_CONTENT; + else + frameState &= ~NS_FRAME_SELECTED_CONTENT; + SetFrameState(frameState); return NS_OK; } - NS_IMETHODIMP nsTextFrame::GetPointFromOffset(nsIPresContext* aPresContext, nsIRenderingContext* inRendContext, @@ -1968,8 +1959,9 @@ nsTextFrame::PeekOffset(nsSelectionAmount aAmount, nsIFrame **aResultFrame, PRInt32 *aFrameOffset, PRInt32 *aContentOffset, - PRBool aEatingWS) + PRBool aEatingWS) const { +/* //default, no matter what grab next/ previous sibling. if (!aResultFrame || !aFrameOffset || !aContentOffset) return NS_ERROR_NULL_POINTER; @@ -2163,6 +2155,8 @@ nsTextFrame::PeekOffset(nsSelectionAmount aAmount, result = NS_OK; } return result; + */ +return NS_OK; } NS_IMETHODIMP diff --git a/mozilla/layout/html/base/src/nsFrame.cpp b/mozilla/layout/html/base/src/nsFrame.cpp index 86574915ff7..656f5c5d070 100644 --- a/mozilla/layout/html/base/src/nsFrame.cpp +++ b/mozilla/layout/html/base/src/nsFrame.cpp @@ -44,7 +44,6 @@ #include "nsIEventStateManager.h" #include "nsIDOMSelection.h" #include "nsIFrameSelection.h" -#include "nsIFocusTracker.h" #include "nsHTMLParts.h" #include "nsLayoutAtoms.h" @@ -143,7 +142,6 @@ nsIFrame::GetLogModuleInfo() //---------------------------------------------------------------------- static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); -static NS_DEFINE_IID(kIFocusTracker, NS_IFOCUSTRACKER_IID); static NS_DEFINE_IID(kIFrameSelection, NS_IFRAMESELECTION_IID); nsresult NS_NewEmptyFrame(nsIFrame** aInstancePtrResult) @@ -165,7 +163,6 @@ NS_IMPL_ZEROING_OPERATOR_NEW(nsFrame) nsFrame::nsFrame() { mState = NS_FRAME_FIRST_REFLOW | NS_FRAME_SYNC_FRAME_AND_VIEW; - mSelected = PR_FALSE; } nsFrame::~nsFrame() @@ -359,7 +356,8 @@ nsFrame::RemoveFrame(nsIPresContext& aPresContext, NS_IMETHODIMP nsFrame::DeleteFrame(nsIPresContext& aPresContext) { - if (mState & NS_FRAME_EXTERNAL_REFERENCE || mSelected) { + PRBool isGeneratedContent = (mState & NS_FRAME_GENERATED_CONTENT) == NS_FRAME_GENERATED_CONTENT; + if (mState & NS_FRAME_EXTERNAL_REFERENCE || mState & NS_FRAME_SELECTED_CONTENT) { nsCOMPtr shell; nsresult rv = aPresContext.GetShell(getter_AddRefs(shell)); if (NS_SUCCEEDED(rv) && shell) { @@ -696,7 +694,12 @@ nsFrame::Paint(nsIPresContext& aPresContext, PRInt32 n; content->ChildCount(n); - if ((n == 0) && mSelected) { + nsFrameState frameState; + PRBool isSelected; + GetFrameState(&frameState); + isSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + + if ((n == 0) && isSelected) { nsRect rect; GetRect(rect); rect.width--; @@ -784,17 +787,16 @@ nsFrame::HandlePress(nsIPresContext& aPresContext, if (NS_SUCCEEDED(GetPosition(aPresContext, acx, aEvent, this, contentOffset, startPos))){ nsIDOMSelection *selection = nsnull; if (NS_SUCCEEDED(shell->GetSelection(&selection))){ - nsIFocusTracker *tracker; - if (NS_SUCCEEDED(shell->QueryInterface(kIFocusTracker,(void **)&tracker))){ - nsIFrameSelection *frameselection = nsnull; - if (NS_SUCCEEDED(selection->QueryInterface(kIFrameSelection, - (void **)&frameselection))) { + nsIFrameSelection *frameselection = nsnull; + if (NS_SUCCEEDED(selection->QueryInterface(kIFrameSelection, (void **)&frameselection))) { + nsCOMPtr content; + rv = GetContent(getter_AddRefs(content)); + if (NS_SUCCEEDED( rv )){ frameselection->EnableFrameNotification(PR_FALSE); - frameselection->TakeFocus(tracker, this, startPos, contentOffset, inputEvent->isShift); + frameselection->TakeFocus(content, startPos + contentOffset, inputEvent->isShift); frameselection->EnableFrameNotification(PR_TRUE);//prevent cyclic call to reset selection. - NS_RELEASE(frameselection); } - NS_RELEASE(tracker); + NS_RELEASE(frameselection); } NS_RELEASE(selection); } @@ -827,16 +829,16 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsIPresContext& aPresContext, if (NS_SUCCEEDED(GetPosition(aPresContext, acx, aEvent, this, contentOffset, startPos))){ nsIDOMSelection *selection = nsnull; if (NS_SUCCEEDED(shell->GetSelection(&selection))){ - nsIFocusTracker *tracker; - if (NS_SUCCEEDED(shell->QueryInterface(kIFocusTracker,(void **)&tracker))) { - nsIFrameSelection* frameselection; - if (NS_SUCCEEDED(selection->QueryInterface(kIFrameSelection, (void **)&frameselection))) { + nsIFrameSelection* frameselection; + if (NS_SUCCEEDED(selection->QueryInterface(kIFrameSelection, (void **)&frameselection))) { + nsCOMPtr content; + rv = GetContent(getter_AddRefs(content)); + if (NS_SUCCEEDED( rv )){ frameselection->EnableFrameNotification(PR_FALSE); - frameselection->TakeFocus(tracker, this, startPos, contentOffset, PR_TRUE); //TRUE IS THE DIFFERENCE + frameselection->TakeFocus(content, startPos + contentOffset, PR_TRUE); //TRUE IS THE DIFFERENCE frameselection->EnableFrameNotification(PR_TRUE);//prevent cyclic call to reset selection. - NS_RELEASE(frameselection); } - NS_RELEASE(tracker); + NS_RELEASE(frameselection); } NS_RELEASE(selection); } @@ -1561,68 +1563,28 @@ nsFrame::VerifyTree() const /*this method may.. invalidate if the state was changed or if aForceRedraw is PR_TRUE it will not update immediately.*/ NS_IMETHODIMP -nsFrame::SetSelected(nsSelectionStruct *aSelStruct) +nsFrame::SetSelected(nsIDOMRange *aRange,PRBool aSelected, PRBool aSpread) { - if (!aSelStruct) - return NS_ERROR_NULL_POINTER; - if (mSelected != (PRBool)(aSelStruct->mType & nsSelectionStruct::SELON ) || aSelStruct->mForceRedraw) - { - mSelected = aSelStruct->mType & nsSelectionStruct::SELON ; - -/* nsRect rect; - GetRect(rect); - nsIFrame *frame = this; - nsIFrame *firstframe = nsnull; - while (NS_SUCCEEDED(frame->GetPrevInFlow(&frame)) && frame){ - firstframe = frame; - } - - if (firstframe){ - nsRect rect2; - firstframe->GetRect(rect2); - rect.y-= rect.y-rect2.y; - } -*/ - ForceDrawFrame(this);//invalidate does not work in all cases. - //Invalidate(rect,PR_FALSE); //false is for not immediate - } + nsFrameState frameState; + GetFrameState(&frameState); + if ( aSelected ) + frameState |= NS_FRAME_SELECTED_CONTENT; + else + frameState &= ~NS_FRAME_SELECTED_CONTENT; + SetFrameState(frameState); + nsRect frameRect; + GetRect(frameRect); + nsRect rect(0, 0, frameRect.width, frameRect.height); + Invalidate(rect, PR_TRUE); return NS_OK; } NS_IMETHODIMP -nsFrame::SetSelectedContentOffsets(nsSelectionStruct *aSS, - nsIFocusTracker *aTracker, - nsIFrame **aActualSelected) -{ - if (!aActualSelected || !aSS) - return NS_ERROR_NULL_POINTER; - nsIFrame *child = nsnull; - nsresult result = FirstChild(nsnull, &child); - if (NS_FAILED(result)){ - *aActualSelected = this; - if (aSS->mAnchorOffset > 0) - aTracker->SetFocus(nsnull,this); - if (aSS->mFocusOffset > 0) - aTracker->SetFocus(this,nsnull); - return SetSelected(aSS); - } - *aActualSelected = nsnull; - //wont actually bother with selection here on "this" frame - while (child && NS_SUCCEEDED(result)){ - result |= child->SetSelectedContentOffsets(aSS, aTracker, aActualSelected); - if (NS_SUCCEEDED(result) && aActualSelected) - return result; //done. - result |= child->GetNextSibling(&child); - } - return result; -} - -NS_IMETHODIMP -nsFrame::GetSelected(PRBool *aSelected, PRInt32 *aBeginOffset, PRInt32 *aEndOffset, PRInt32 *aBeginContentOffset) +nsFrame::GetSelected(PRBool *aSelected) const { if (!aSelected ) return NS_ERROR_NULL_POINTER; - *aSelected = mSelected; + *aSelected = (PRBool)(mState & NS_FRAME_SELECTED_CONTENT); return NS_OK; } @@ -1647,9 +1609,9 @@ nsFrame::GetChildFrameContainingOffset(PRInt32 inContentOffset, PRInt32* outFram NS_IMETHODIMP nsFrame::PeekOffset(nsSelectionAmount aAmount, nsDirection aDirection, PRInt32 aStartOffset, nsIFrame **aResultFrame, PRInt32 *aFrameOffset, PRInt32 *aContentOffset, - PRBool aEatingWS) + PRBool aEatingWS) const { - //this will use the nsFrameTraversal as the default peek method. +/* //this will use the nsFrameTraversal as the default peek method. //this should change to use geometry and also look to ALL the child lists nsCOMPtr frameTraversal; nsresult result = NS_NewFrameTraversal(getter_AddRefs(frameTraversal),LEAF,this); @@ -1673,6 +1635,8 @@ nsFrame::PeekOffset(nsSelectionAmount aAmount, nsDirection aDirection, PRInt32 a nsIFrame *newFrame = (nsIFrame *)isupports; return newFrame->PeekOffset(aAmount, aDirection, aStartOffset, aResultFrame, aFrameOffset, aContentOffset, aEatingWS); + */ + return NS_OK; } //----------------------------------------------------------------------------------- diff --git a/mozilla/layout/html/base/src/nsFrame.h b/mozilla/layout/html/base/src/nsFrame.h index f29c77545e8..ba6c6ccc557 100644 --- a/mozilla/layout/html/base/src/nsFrame.h +++ b/mozilla/layout/html/base/src/nsFrame.h @@ -208,14 +208,11 @@ public: NS_IMETHOD GetFrameName(nsString& aResult) const; NS_IMETHOD DumpRegressionData(FILE* out, PRInt32 aIndent); NS_IMETHOD VerifyTree() const; - NS_IMETHOD SetSelected(nsSelectionStruct *); - NS_IMETHOD SetSelectedContentOffsets(nsSelectionStruct *aSS, - nsIFocusTracker *aTracker, - nsIFrame **aActualSelected); - NS_IMETHOD GetSelected(PRBool *aSelected, PRInt32 *aBeginOffset, PRInt32 *aEndOffset, PRInt32 *aBeginContentOffset); + NS_IMETHOD SetSelected(nsIDOMRange *aRange,PRBool aSelected, PRBool aSpread); + NS_IMETHOD GetSelected(PRBool *aSelected) const; NS_IMETHOD PeekOffset(nsSelectionAmount aAmount, nsDirection aDirection, PRInt32 aStartOffset, nsIFrame **aResultFrame, PRInt32 *aFrameOffset, PRInt32 *aContentOffset, - PRBool aEatingWS); + PRBool aEatingWS)const; NS_IMETHOD GetOffsets(PRInt32 &aStart, PRInt32 &aEnd) const; @@ -352,7 +349,6 @@ protected: nsIFrame* mParent; nsIFrame* mNextSibling; // singly linked list of frames nsFrameState mState; - PRBool mSelected; /////////////////////////////////// // Important Selection Variables diff --git a/mozilla/layout/html/base/src/nsPresShell.cpp b/mozilla/layout/html/base/src/nsPresShell.cpp index 259d56514f6..4356a265c14 100644 --- a/mozilla/layout/html/base/src/nsPresShell.cpp +++ b/mozilla/layout/html/base/src/nsPresShell.cpp @@ -597,35 +597,16 @@ PresShell::Init(nsIDocument* aDocument, getter_AddRefs(domselection)); if (!NS_SUCCEEDED(result)) return result; + result = domselection->QueryInterface(kIFrameSelectionIID, - getter_AddRefs(mSelection)); + getter_AddRefs(mSelection)); if (!NS_SUCCEEDED(result)) return result; domselection->AddSelectionListener(this);//possible circular reference - // XXX This code causes the document object (and the entire content model) to be leaked... -#if 0 - nsCOMPtrrange; - if (NS_SUCCEEDED(nsComponentManager::CreateInstance(kCRangeCID, nsnull, kIDOMRangeIID, getter_AddRefs(range)))){ //create an irange - nsCOMPtrdoc(GetDocument()); - nsCOMPtrdomDoc(doc); - if (domDoc){ - nsCOMPtr domElement; - if (NS_SUCCEEDED(domDoc->GetDocumentElement(getter_AddRefs(domElement)))) {//get the first element from the dom - nsCOMPtrdomNode(domElement); - if (domNode) {//get the node interface for the range object - range->SetStart(domNode,0); - range->SetEnd(domNode,0); - nsCOMPtrrangeISupports(range); - if (rangeISupports) { - selection->AddItem(rangeISupports); - } - } - } - } - } - -#endif + result = mSelection->Init((nsIFocusTracker *) this); + if (!NS_SUCCEEDED(result)) + return result; // Important: this has to happen after the selection has been set up #ifdef SHOW_CARET nsCaretProperties *caretProperties = NewCaretProperties(); @@ -836,6 +817,7 @@ PresShell::EndObservingDocument() if (!domselection) return NS_ERROR_UNEXPECTED; domselection->RemoveSelectionListener(this); + mSelection->ShutDown(); } return NS_OK; } @@ -958,12 +940,6 @@ PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight) NS_IF_RELEASE(rcx); NS_FRAME_LOG(NS_FRAME_TRACE_CALLS, ("exit nsPresShell::ResizeReflow")); - if (mSelection){ - DisableScrolling(); - mSelection->ResetSelection(this, mRootFrame); - EnableScrolling(); - } - // XXX if debugging then we should assert that the cache is empty } else { #ifdef NOISY @@ -1049,7 +1025,6 @@ NS_IMETHODIMP PresShell::NotifySelectionChanged() { if (!mSelection) return NS_ERROR_NULL_POINTER; - mSelection->ResetSelection(this, mRootFrame); return NS_ERROR_NULL_POINTER; } @@ -1636,8 +1611,6 @@ PresShell::ContentChanged(nsIDocument *aDocument, EnterReflowLock(); nsresult rv = mStyleSet->ContentChanged(mPresContext, aContent, aSubContent); ExitReflowLock(); - if (mSelection) - mSelection->ResetSelection(this, mRootFrame); return rv; } @@ -1652,8 +1625,6 @@ PresShell::ContentStatesChanged(nsIDocument* aDocument, EnterReflowLock(); nsresult rv = mStyleSet->ContentStatesChanged(mPresContext, aContent1, aContent2); ExitReflowLock(); - //if (mSelection) - //mSelection->ResetSelection(this, mRootFrame); return rv; } @@ -2019,7 +1990,7 @@ PresShell::HandleEvent(nsIView *aView, if (mSelection && mFocusEventFrame && aEvent->eventStructType == NS_KEY_EVENT) { mSelection->EnableFrameNotification(PR_FALSE); - mSelection->HandleKeyEvent((nsIFocusTracker *)this, aEvent); + mSelection->HandleKeyEvent(aEvent); mSelection->EnableFrameNotification(PR_TRUE); //prevents secondary reset selection called since //we are a listener now. } diff --git a/mozilla/layout/html/base/src/nsSplittableFrame.cpp b/mozilla/layout/html/base/src/nsSplittableFrame.cpp index fc965eff70b..3009b46007e 100644 --- a/mozilla/layout/html/base/src/nsSplittableFrame.cpp +++ b/mozilla/layout/html/base/src/nsSplittableFrame.cpp @@ -45,6 +45,9 @@ nsSplittableFrame::Init(nsIPresContext& aPresContext, if (state & NS_FRAME_REPLACED_ELEMENT) { mState |= NS_FRAME_REPLACED_ELEMENT; } + if (state & NS_FRAME_SELECTED_CONTENT) { + mState |= NS_FRAME_SELECTED_CONTENT; + } } return rv; diff --git a/mozilla/layout/html/base/src/nsTextFrame.cpp b/mozilla/layout/html/base/src/nsTextFrame.cpp index b231922ac38..8f46fa50410 100644 --- a/mozilla/layout/html/base/src/nsTextFrame.cpp +++ b/mozilla/layout/html/base/src/nsTextFrame.cpp @@ -52,6 +52,8 @@ #include "nsTextTransformer.h" #include "nsLayoutAtoms.h" #include "nsIFrameSelection.h" +#include "nsIDOMSelection.h" +#include "nsIDOMRange.h" static NS_DEFINE_IID(kIDOMTextIID, NS_IDOMTEXT_IID); @@ -229,14 +231,19 @@ public: PRUint32& aActualContentOffset, PRInt32& aOffset); - NS_IMETHOD SetSelected(nsSelectionStruct *aSS); - NS_IMETHOD SetSelectedContentOffsets(nsSelectionStruct *aSS, - nsIFocusTracker *aTracker, - nsIFrame **aActualSelected); - NS_IMETHOD GetSelected(PRBool *aSelected, PRInt32 *aBeginOffset, PRInt32 *aEndOffset, PRInt32 *aBeginContentOffset); + NS_IMETHOD GetPositionSlowly(nsIPresContext& aCX, + nsIRenderingContext * aRendContext, + nsGUIEvent* aEvent, + nsIFrame * aNewFrame, + PRUint32& aActualContentOffset, + PRInt32& aOffset); + + + NS_IMETHOD SetSelected(nsIDOMRange *aRange,PRBool aSelected, PRBool aSpread); + NS_IMETHOD PeekOffset(nsSelectionAmount aAmount, nsDirection aDirection, PRInt32 aStartOffset, nsIFrame **aResultFrame, PRInt32 *aFrameOffset, PRInt32 *aContentOffset, - PRBool aEatingWS); + PRBool aEatingWS)const; NS_IMETHOD GetOffsets(PRInt32 &start, PRInt32 &end)const; @@ -337,13 +344,6 @@ public: nsIDocument* GetDocument(nsIPresContext* aPresContext); - nsresult GetPositionSlowly(nsIPresContext* aCX, - nsIRenderingContext * aRendContext, - nsGUIEvent* aEvent, - nsIFrame * aNewFrame, - PRUint32* aActualContentOffset, - PRInt32* aOffset); - PRIntn PrepareUnicodeText(nsTextTransformer& aTransformer, PRInt32* aIndicies, PRUnichar* aBuffer, @@ -415,8 +415,6 @@ protected: PRInt32 mColumn; nscoord mComputedWidth; - PRUint32 mSelectionOffset; - PRUint32 mSelectionEnd; }; // Flag information used by rendering code. This information is @@ -458,8 +456,6 @@ nsTextFrame::nsTextFrame() // Create text timer the first time out gTextBlinker = new nsBlinkTimer(); } - mSelectionOffset = PRUint32(-1); - mSelectionEnd = PRUint32(-1); NS_ADDREF(gTextBlinker); } @@ -835,10 +831,13 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, PrepareUnicodeText(tx, (displaySelection ? ip : nsnull), paintBuf, &textLength); PRUnichar* text = paintBuf; + nsFrameState frameState; + PRBool isSelected; + GetFrameState(&frameState); + isSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + if (0 != textLength) { - if (!displaySelection || !mSelected || - (mSelectionOffset > PRUint32(mContentLength))) { - //if selection is > content length then selection has "slid off" + if (!displaySelection || !isSelected ) { // When there is no selection showing, use the fastest and // simplest rendering approach aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy); @@ -851,89 +850,98 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, //must set up last one for selection beyond edge if in boundary ip[mContentLength]++; } + PRInt32 textWidth; + PRInt32 selectionStartOffset = 0;//frame coordinates + PRInt32 selectionEndOffset = 0;//frame coordinates + + nsCOMPtr shell; + nsCOMPtr selection; + nsCOMPtr frameSelection; + PRBool drawSelected = PR_FALSE; + + nsresult rv = aPresContext->GetShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(rv) && shell){ + rv = shell->GetSelection(getter_AddRefs(selection)); + if (NS_SUCCEEDED(rv) && selection){ + frameSelection = do_QueryInterface(selection); + nsCOMPtr content; + rv = GetContent(getter_AddRefs(content)); + if (NS_SUCCEEDED(rv)){ + rv = frameSelection->LookUpSelection(content, mContentOffset, + mContentLength , &selectionStartOffset, &selectionEndOffset, + &drawSelected,0);// last param notused + } + } + } + - nscoord textWidth; - if (mSelectionOffset < 0) - mSelectionOffset = 0; - if (mSelectionEnd < 0) - mSelectionEnd = mContentLength; - if (mSelectionEnd > PRUint32(mContentLength)) - mSelectionEnd = PRUint32(mContentLength); - if (mSelectionOffset > PRUint32(mContentLength)) - mSelectionOffset = PRUint32(mContentLength); - PRInt32 selectionEnd = mSelectionEnd; - PRInt32 selectionOffset = mSelectionOffset; - if (mSelectionEnd < mSelectionOffset) - { - selectionEnd = mSelectionOffset; - selectionOffset = mSelectionEnd; - } - //where are the selection points "really" - selectionOffset = ip[selectionOffset] - mContentOffset; - selectionEnd = ip[selectionEnd] - mContentOffset; - if (selectionOffset == selectionEnd) { - aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy); - PaintTextDecorations(aRenderingContext, aStyleContext, - aTextStyle, dx, dy, width); - //shell->RefreshCaret(); - -#ifdef SHOW_SELECTION_CURSOR - aRenderingContext.GetWidth(text, PRUint32(selectionOffset), textWidth); - - RenderSelectionCursor(aRenderingContext, - dx + textWidth, dy, mRect.height, - CURSOR_COLOR); -#endif - } - else { - nscoord x = dx; - - if (selectionOffset) { - // Render first (unselected) section - aRenderingContext.GetWidth(text, PRUint32(selectionOffset),//si.mStartOffset), - textWidth); - aRenderingContext.DrawString(text, PRUint32(selectionOffset), - x, dy); - PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, - x, dy, textWidth); - x += textWidth; + if (frameSelection ){ + //where are the selection points "really" + if (drawSelected){ + selectionStartOffset = ip[selectionStartOffset] - mContentOffset; + selectionEndOffset = ip[selectionEndOffset] - mContentOffset; } - PRInt32 secondLen = selectionEnd - selectionOffset; - if (0 != secondLen) { - // Get the width of the second (selected) section - aRenderingContext.GetWidth(text + selectionOffset, - PRUint32(secondLen), textWidth); + if (!drawSelected || (selectionStartOffset == selectionEndOffset)) { + aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy); + PaintTextDecorations(aRenderingContext, aStyleContext, + aTextStyle, dx, dy, width); + #ifdef SHOW_SELECTION_CURSOR + aRenderingContext.GetWidth(text, PRUint32(selectionStartOffset), textWidth); - // Render second (selected) section - aRenderingContext.SetColor(aTextStyle.mSelectionBGColor); - aRenderingContext.FillRect(x, dy, textWidth, mRect.height); - aRenderingContext.SetColor(aTextStyle.mSelectionTextColor); - aRenderingContext.DrawString(text + selectionOffset, - PRUint32(secondLen), x, dy); - PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, - x, dy, textWidth); - aRenderingContext.SetColor(aTextStyle.mColor->mColor); - x += textWidth; + RenderSelectionCursor(aRenderingContext, + dx + textWidth, dy, mRect.height, + CURSOR_COLOR); + #endif } - if (textLength != selectionEnd) { - PRInt32 thirdLen = textLength - selectionEnd; + else { + nscoord x = dx; - if (thirdLen > 0) //Text length is not negative or zero - { - - // Render third (unselected) section - aRenderingContext.GetWidth(text + selectionEnd, PRUint32(thirdLen), + if (selectionStartOffset) { + // Render first (unselected) section + aRenderingContext.GetWidth(text, PRUint32(selectionStartOffset),//si.mStartOffset), textWidth); - aRenderingContext.DrawString(text + selectionEnd, - PRUint32(thirdLen), x, dy); + aRenderingContext.DrawString(text, PRUint32(selectionStartOffset), + x, dy); PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, x, dy, textWidth); + x += textWidth; + } + PRInt32 secondLen = selectionEndOffset - selectionStartOffset; + if (0 != secondLen) { + // Get the width of the second (selected) section + aRenderingContext.GetWidth(text + selectionStartOffset, + PRUint32(secondLen), textWidth); + + // Render second (selected) section + aRenderingContext.SetColor(aTextStyle.mSelectionBGColor); + aRenderingContext.FillRect(x, dy, textWidth, mRect.height); + aRenderingContext.SetColor(aTextStyle.mSelectionTextColor); + aRenderingContext.DrawString(text + selectionStartOffset, + PRUint32(secondLen), x, dy); + PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, + x, dy, textWidth); + aRenderingContext.SetColor(aTextStyle.mColor->mColor); + x += textWidth; + } + if (textLength != selectionEndOffset) { + PRInt32 thirdLen = textLength - selectionEndOffset; + + if (thirdLen > 0) //Text length is not negative or zero + { + + // Render third (unselected) section + aRenderingContext.GetWidth(text + selectionEndOffset, PRUint32(thirdLen), + textWidth); + aRenderingContext.DrawString(text + selectionEndOffset, + PRUint32(thirdLen), x, dy); + PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, + x, dy, textWidth); + } } } } } } - // Cleanup if (paintBuf != paintBufMem) { delete [] paintBuf; @@ -945,24 +953,24 @@ nsTextFrame::PaintUnicodeText(nsIPresContext* aPresContext, //measure Spaced Textvoid nsresult -nsTextFrame::GetPositionSlowly(nsIPresContext* aPresContext, +nsTextFrame::GetPositionSlowly(nsIPresContext& aPresContext, nsIRenderingContext* aRendContext, nsGUIEvent* aEvent, nsIFrame* aNewFrame, - PRUint32* aAcutalContentOffset, - PRInt32* aOffset) + PRUint32& aAcutalContentOffset, + PRInt32& aOffset) { if (!aRendContext || !aEvent || !aNewFrame) { return NS_ERROR_NULL_POINTER; } - TextStyle ts(aPresContext, *aRendContext, mStyleContext); + TextStyle ts(&aPresContext, *aRendContext, mStyleContext); if (!ts.mSmallCaps && !ts.mWordSpacing && !ts.mLetterSpacing) { return NS_ERROR_INVALID_ARG; } - nsCOMPtr doc(getter_AddRefs(GetDocument(aPresContext))); + nsCOMPtr doc(getter_AddRefs(GetDocument(&aPresContext))); // Make enough space to transform PRUnichar paintBufMem[TEXT_BUF_SIZE]; @@ -1026,12 +1034,12 @@ nsTextFrame::GetPositionSlowly(nsIPresContext* aPresContext, } if ((aEvent->point.x - origin.x) >= widthsofar && (aEvent->point.x - origin.x) <= (widthsofar + glyphWidth)){ if ( ((aEvent->point.x - origin.x) - widthsofar) <= (glyphWidth /2)){ - *aOffset = index; + aOffset = index; found = PR_TRUE; break; } else{ - *aOffset = index+1; + aOffset = index+1; found = PR_TRUE; break; } @@ -1044,13 +1052,13 @@ nsTextFrame::GetPositionSlowly(nsIPresContext* aPresContext, } paintBuf = startBuf; if (!found){ - *aOffset = textLength; + aOffset = textLength; } - *aAcutalContentOffset = mContentOffset;//offset;//((nsTextFrame *)aNewFrame)->mContentOffset; + aAcutalContentOffset = mContentOffset;//offset;//((nsTextFrame *)aNewFrame)->mContentOffset; PRInt32 i; for (i = 0;i <= mContentLength; i ++){ - if (ip[i] == *aOffset + mContentOffset){ //reverse mapping - *aOffset = i; + if (ip[i] == aOffset + mContentOffset){ //reverse mapping + aOffset = i; break; } } @@ -1319,9 +1327,12 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext, } PRUnichar* text = paintBuf; + nsFrameState frameState; + PRBool isSelected; + GetFrameState(&frameState); + isSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; if (0 != textLength) { - if (!displaySelection || !mSelected || - (mSelectionOffset > PRUint32(mContentLength))) { + if (!displaySelection || !isSelected) { // When there is no selection showing, use the fastest and // simplest rendering approach RenderString(aRenderingContext, aStyleContext, aTextStyle, @@ -1329,89 +1340,99 @@ nsTextFrame::PaintTextSlowly(nsIPresContext* aPresContext, } else { ip[mContentLength] = ip[mContentLength-1]; - if ((ip[mContentLength]-mContentOffset) < textLength)//must set up last one for selection beyond edge if in boundary + if ((ip[mContentLength]-mContentOffset) < textLength) { + //must set up last one for selection beyond edge if in boundary ip[mContentLength]++; - nscoord textWidth; - if (mSelectionOffset < 0) - mSelectionOffset = 0; - if (mSelectionEnd < 0) - mSelectionEnd = PRUint32(mContentLength); - if (mSelectionEnd > PRUint32(mContentLength)) - mSelectionEnd = PRUint32(mContentLength); - if (mSelectionOffset > PRUint32(mContentLength)) - mSelectionOffset = PRUint32(mContentLength); - PRInt32 selectionEnd = mSelectionEnd; - PRInt32 selectionOffset = mSelectionOffset; - if (mSelectionEnd < mSelectionOffset) - { - selectionEnd = mSelectionOffset; - selectionOffset = mSelectionEnd; } - //where are the selection points "really" - selectionOffset = ip[selectionOffset] - mContentOffset; - selectionEnd = ip[selectionEnd] - mContentOffset; - if (selectionOffset == selectionEnd){ - RenderString(aRenderingContext, aStyleContext, aTextStyle, - text, textLength, dx, dy, width); + PRInt32 selectionStartOffset = 0;//frame coordinates + PRInt32 selectionEndOffset = 0;//frame coordinates + PRInt32 textWidth; + nsCOMPtr shell; + nsCOMPtr selection; + nsCOMPtr frameSelection; + PRBool drawSelected = PR_FALSE; + nsresult rv = aPresContext->GetShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(rv) && shell){ + rv = shell->GetSelection(getter_AddRefs(selection)); + if (NS_SUCCEEDED(rv) && selection){ + frameSelection = do_QueryInterface(selection); + nsCOMPtr content; + rv = GetContent(getter_AddRefs(content)); + if (NS_SUCCEEDED(rv)){ + rv = frameSelection->LookUpSelection(content, mContentOffset, + mContentLength , &selectionStartOffset, &selectionEndOffset, + &drawSelected, 0);// last param notused + } + } + } - //shell->RefreshCaret(); + + if (frameSelection){ + //where are the selection points "really" + if (drawSelected) { + selectionStartOffset = ip[selectionStartOffset] - mContentOffset; + selectionEndOffset = ip[selectionEndOffset] - mContentOffset; + } + if (!drawSelected || (selectionStartOffset == selectionEndOffset)){ + RenderString(aRenderingContext, aStyleContext, aTextStyle, + text, textLength, dx, dy, width); #ifdef SHOW_SELECTION_CURSOR GetWidth(aRenderingContext, aTextStyle, - text, PRUint32(selectionOffset), &textWidth); + text, PRUint32(selectionStartOffset), &textWidth); RenderSelectionCursor(aRenderingContext, dx + textWidth, dy, mRect.height, CURSOR_COLOR); #endif - } - else { - nscoord x = dx; - - if (selectionOffset) { - // Render first (unselected) section - GetWidth(aRenderingContext, aTextStyle, - text, PRUint32(selectionOffset), - &textWidth); - RenderString(aRenderingContext, aStyleContext, aTextStyle, - text, selectionOffset, - x, dy, textWidth); - x += textWidth; } - PRInt32 secondLen = selectionEnd - selectionOffset; - if (0 != secondLen) { - // Get the width of the second (selected) section - GetWidth(aRenderingContext, aTextStyle, - text + selectionOffset, - PRUint32(secondLen), &textWidth); + else { + nscoord x = dx; - // Render second (selected) section - aRenderingContext.SetColor(aTextStyle.mSelectionBGColor); - aRenderingContext.FillRect(x, dy, textWidth, mRect.height); - aRenderingContext.SetColor(aTextStyle.mSelectionTextColor); - RenderString(aRenderingContext, aStyleContext, aTextStyle, - text + selectionOffset, secondLen, - x, dy, textWidth); - aRenderingContext.SetColor(aTextStyle.mColor->mColor); - x += textWidth; - } - if (textLength != selectionEnd) { - PRInt32 thirdLen = textLength - selectionEnd; - - // Render third (unselected) section - if (thirdLen > 0) //Text length is not negative or zero - { + if (selectionStartOffset) { + // Render first (unselected) section GetWidth(aRenderingContext, aTextStyle, - text + selectionOffset, PRUint32(thirdLen), + text, PRUint32(selectionStartOffset), &textWidth); RenderString(aRenderingContext, aStyleContext, aTextStyle, - text + selectionEnd, - thirdLen, x, dy, textWidth); + text, selectionStartOffset, + x, dy, textWidth); + x += textWidth; + } + PRInt32 secondLen = selectionEndOffset - selectionStartOffset; + if (0 != secondLen) { + // Get the width of the second (selected) section + GetWidth(aRenderingContext, aTextStyle, + text + selectionStartOffset, + PRUint32(secondLen), &textWidth); + + // Render second (selected) section + aRenderingContext.SetColor(aTextStyle.mSelectionBGColor); + aRenderingContext.FillRect(x, dy, textWidth, mRect.height); + aRenderingContext.SetColor(aTextStyle.mSelectionTextColor); + RenderString(aRenderingContext, aStyleContext, aTextStyle, + text + selectionStartOffset, secondLen, + x, dy, textWidth); + aRenderingContext.SetColor(aTextStyle.mColor->mColor); + x += textWidth; + } + if (textLength != selectionEndOffset) { + PRInt32 thirdLen = textLength - selectionEndOffset; + + // Render third (unselected) section + if (thirdLen > 0) //Text length is not negative or zero + { + GetWidth(aRenderingContext, aTextStyle, + text + selectionStartOffset, PRUint32(thirdLen), + &textWidth); + RenderString(aRenderingContext, aStyleContext, aTextStyle, + text + selectionEndOffset, + thirdLen, x, dy, textWidth); + } } } } } } - // Cleanup if (paintBuf != paintBufMem) { delete [] paintBuf; @@ -1466,9 +1487,13 @@ nsTextFrame::PaintAsciiText(nsIPresContext* aPresContext, } char* text = paintBuf; + nsFrameState frameState; + PRBool isSelected; + GetFrameState(&frameState); + isSelected = (frameState & NS_FRAME_SELECTED_CONTENT) == NS_FRAME_SELECTED_CONTENT; + if (0 != textLength) { - if (!displaySelection || !mSelected || - (mSelectionOffset > PRUint32(mContentLength))) { + if (!displaySelection || !isSelected) { //if selection is > content length then selection has "slid off" // When there is no selection showing, use the fastest and // simplest rendering approach @@ -1478,85 +1503,97 @@ nsTextFrame::PaintAsciiText(nsIPresContext* aPresContext, } else { ip[mContentLength] = ip[mContentLength-1]; - if ((ip[mContentLength]-mContentOffset) < textLength)//must set up last one for selection beyond edge if in boundary + if ((ip[mContentLength]-mContentOffset) < textLength) { + //must set up last one for selection beyond edge if in boundary ip[mContentLength]++; - nscoord textWidth; - if (mSelectionOffset < 0) - mSelectionOffset = 0; - if (mSelectionEnd < 0) - mSelectionEnd = mContentLength; - if (mSelectionEnd > PRUint32(mContentLength)) - mSelectionEnd = PRUint32(mContentLength); - if (mSelectionOffset > PRUint32(mContentLength)) - mSelectionOffset = PRUint32(mContentLength); - PRInt32 selectionEnd = mSelectionEnd; - PRInt32 selectionOffset = mSelectionOffset; - if (mSelectionEnd < mSelectionOffset) - { - selectionEnd = mSelectionOffset; - selectionOffset = mSelectionEnd; } - //where are the selection points "really" - selectionOffset = ip[selectionOffset] - mContentOffset; - selectionEnd = ip[selectionEnd] - mContentOffset; - if (selectionOffset == selectionEnd){ - aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy); - PaintTextDecorations(aRenderingContext, aStyleContext, - aTextStyle, dx, dy, width); - //shell->RefreshCaret(); - -#ifdef SHOW_SELECTION_CURSOR - aRenderingContext.GetWidth(text, PRUint32(selectionOffset), textWidth); - - RenderSelectionCursor(aRenderingContext, - dx + textWidth, dy, mRect.height, - CURSOR_COLOR); -#endif + PRInt32 selectionStartOffset = 0;//frame coordinates + PRInt32 selectionEndOffset = 0;//frame coordinates + PRInt32 textWidth; + nsCOMPtr shell; + nsCOMPtr selection; + nsCOMPtr frameSelection; + PRBool drawSelected = PR_FALSE; + nsresult rv = aPresContext->GetShell(getter_AddRefs(shell)); + if (NS_SUCCEEDED(rv) && shell){ + rv = shell->GetSelection(getter_AddRefs(selection)); + if (NS_SUCCEEDED(rv) && selection){ + frameSelection = do_QueryInterface(selection); + nsCOMPtr content; + rv = GetContent(getter_AddRefs(content)); + if (NS_SUCCEEDED(rv)){ + rv = frameSelection->LookUpSelection(content, mContentOffset, + mContentLength , &selectionStartOffset, &selectionEndOffset, + &drawSelected, 0);// last param notused + } + } } - else - { - nscoord x = dx; - if (selectionOffset) { - // Render first (unselected) section - aRenderingContext.GetWidth(text, PRUint32(selectionOffset),//si.mStartOffset), - textWidth); - aRenderingContext.DrawString(text, PRUint32(selectionOffset), - x, dy); - PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, - x, dy, textWidth); - x += textWidth; + + if (frameSelection){ + //where are the selection points "really" + if (drawSelected) { + selectionStartOffset = ip[selectionStartOffset] - mContentOffset; + selectionEndOffset = ip[selectionEndOffset] - mContentOffset; } - PRInt32 secondLen = selectionEnd - selectionOffset; - if (0 != secondLen) { - // Get the width of the second (selected) section - aRenderingContext.GetWidth(text + selectionOffset, - PRUint32(secondLen), textWidth); + if (!drawSelected || (selectionStartOffset == selectionEndOffset)){ + aRenderingContext.DrawString(text, PRUint32(textLength), dx, dy); + PaintTextDecorations(aRenderingContext, aStyleContext, + aTextStyle, dx, dy, width); + //shell->RefreshCaret(); + + #ifdef SHOW_SELECTION_CURSOR + aRenderingContext.GetWidth(text, PRUint32(selectionStartOffset), textWidth); - // Render second (selected) section - aRenderingContext.SetColor(aTextStyle.mSelectionBGColor); - aRenderingContext.FillRect(x, dy, textWidth, mRect.height); - aRenderingContext.SetColor(aTextStyle.mSelectionTextColor); - aRenderingContext.DrawString(text + selectionOffset, - PRUint32(secondLen), x, dy); - PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, - x, dy, textWidth); - aRenderingContext.SetColor(aTextStyle.mColor->mColor); - x += textWidth; + RenderSelectionCursor(aRenderingContext, + dx + textWidth, dy, mRect.height, + CURSOR_COLOR); + #endif } - if (textLength != selectionEnd) { - PRInt32 thirdLen = textLength - selectionEnd; + else { + nscoord x = dx; - if (thirdLen > 0) //Text length is not negative or zero - { - - // Render third (unselected) section - aRenderingContext.GetWidth(text + selectionEnd, PRUint32(thirdLen), + if (selectionStartOffset) { + // Render first (unselected) section + aRenderingContext.GetWidth(text, PRUint32(selectionStartOffset),//si.mStartOffset), textWidth); - aRenderingContext.DrawString(text + selectionEnd, - PRUint32(thirdLen), x, dy); + aRenderingContext.DrawString(text, PRUint32(selectionStartOffset), + x, dy); PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, x, dy, textWidth); + x += textWidth; + } + PRInt32 secondLen = selectionEndOffset - selectionStartOffset; + if (0 != secondLen) { + // Get the width of the second (selected) section + aRenderingContext.GetWidth(text + selectionStartOffset, + PRUint32(secondLen), textWidth); + + // Render second (selected) section + aRenderingContext.SetColor(aTextStyle.mSelectionBGColor); + aRenderingContext.FillRect(x, dy, textWidth, mRect.height); + aRenderingContext.SetColor(aTextStyle.mSelectionTextColor); + aRenderingContext.DrawString(text + selectionStartOffset, + PRUint32(secondLen), x, dy); + PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, + x, dy, textWidth); + aRenderingContext.SetColor(aTextStyle.mColor->mColor); + x += textWidth; + } + if (textLength != selectionEndOffset) { + PRInt32 thirdLen = textLength - selectionEndOffset; + + if (thirdLen > 0) //Text length is not negative or zero + { + + // Render third (unselected) section + aRenderingContext.GetWidth(text + selectionEndOffset, PRUint32(thirdLen), + textWidth); + aRenderingContext.DrawString(text + selectionEndOffset, + PRUint32(thirdLen), x, dy); + PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle, + x, dy, textWidth); + } } } } @@ -1611,7 +1648,7 @@ BinarySearchForPosition(nsIRenderingContext* acx, } PRInt32 inx = aStartInx + (range / 2); - PRInt32 textWidth; + PRInt32 textWidth = 0; acx->GetWidth(aText, inx, textWidth); PRInt32 fullWidth = aBaseWidth + textWidth; @@ -1648,8 +1685,8 @@ nsTextFrame::GetPosition(nsIPresContext& aPresContext, { TextStyle ts(&aPresContext, *aRendContext, mStyleContext); if (ts.mSmallCaps || ts.mWordSpacing || ts.mLetterSpacing) { - return GetPositionSlowly(&aPresContext, aRendContext, aEvent, aNewFrame, - &aActualContentOffset, &aOffset); + return GetPositionSlowly(aPresContext, aRendContext, aEvent, aNewFrame, + aActualContentOffset, aOffset); } PRUnichar wordBufMem[WORD_BUF_SIZE]; @@ -1690,7 +1727,7 @@ nsTextFrame::GetPosition(nsIPresContext& aPresContext, } PRInt32 index; - PRInt32 textWidth; + PRInt32 textWidth = 0; PRUnichar* text = paintBuf; nsPoint origin; nsIView * view; @@ -1742,129 +1779,83 @@ nsTextFrame::GetPosition(nsIPresContext& aPresContext, return NS_OK; } -NS_IMETHODIMP -nsTextFrame::SetSelected(nsSelectionStruct *aSelStruct) -{ - if (!aSelStruct) - return NS_ERROR_NULL_POINTER; - if (aSelStruct->mType & nsSelectionStruct::SELON){ - aSelStruct->mEndFrame = PR_MIN(aSelStruct->mEndFrame, (PRUint32) mContentLength); - aSelStruct->mStartFrame= PR_MIN(aSelStruct->mStartFrame, (PRUint32) mContentLength); - if (aSelStruct->mType & nsSelectionStruct::SELTOEND) - aSelStruct->mEndFrame = mContentLength; - if (aSelStruct->mType & nsSelectionStruct::SELTOBEGIN) - aSelStruct->mStartFrame = 0; - PRUint32 trueBegin(aSelStruct->mStartFrame); - PRUint32 trueEnd(aSelStruct->mEndFrame); - if (aSelStruct->mDir == eDirPrevious){//change the settings around, - //the frame doesnt track direction it only tracks begin and end. - trueBegin = aSelStruct->mEndFrame; - trueEnd = aSelStruct->mStartFrame; - } - - if (mSelectionOffset != trueBegin || mSelectionEnd != trueEnd) - { -//XXX PRBool wasCollapsed = (mSelectionOffset == mSelectionEnd); - mSelectionOffset = trueBegin; - mSelectionEnd = trueEnd; - // XXX when we no longer rely on the blue triangle to show the selection - // position (using the caret instead), then we can uncomment this to reduce - // redrawing. sfraser - aSelStruct->mForceRedraw = PR_TRUE; //!wasCollapsed || (trueBegin != trueEnd); - } - } - return nsFrame::SetSelected(aSelStruct);//this will do the actual - //turning on of the mSelected flag in the nsframe header. -} +// [HACK] Foward Declarations +void ForceDrawFrame(nsFrame * aFrame); NS_IMETHODIMP -nsTextFrame::SetSelectedContentOffsets(nsSelectionStruct *aSS, - nsIFocusTracker *aTracker, - nsIFrame **aActualSelected) +nsTextFrame::SetSelected(nsIDOMRange *aRange,PRBool aSelected, PRBool aSpread) { - if (!aActualSelected || !aSS) + if (!aRange) return NS_ERROR_NULL_POINTER; + nsresult result; + if (aSpread){ + nsIFrame *frame = GetPrevInFlow(); + while(frame){ + frame->SetSelected(aRange,aSelected,PR_FALSE); + result = frame->GetPrevInFlow(&frame); + if (NS_FAILED(result)) + break; + } + frame = GetNextInFlow(); + while(frame){ + frame->SetSelected(aRange,aSelected,PR_FALSE); + result = frame->GetNextInFlow(&frame); + if (NS_FAILED(result)) + break; + } + } + //lets see if the range contains us, if so we must redraw! + nsCOMPtr endNode; + PRInt32 endOffset; + nsCOMPtr startNode; + PRInt32 startOffset; + aRange->GetEndParent(getter_AddRefs(endNode)); + aRange->GetEndOffset(&endOffset); + aRange->GetStartParent(getter_AddRefs(startNode)); + aRange->GetStartOffset(&startOffset); + nsCOMPtr content; + result = GetContent(getter_AddRefs(content)); + nsCOMPtr thisNode; + thisNode = do_QueryInterface(content); - PRInt32 beginOffset(aSS->mStartContent - mContentOffset); - if (beginOffset > mContentLength){ - //this is not the droid we are looking for. keep looking - nsSelectionStruct ss = {0};//turn it ALL off - ss.mForceRedraw = aSS->mForceRedraw; - SetSelected(&ss); - nsIFrame *nextInFlow =GetNextInFlow(); - if (nextInFlow) - return nextInFlow->SetSelectedContentOffsets(aSS, aTracker, aActualSelected); - else - return NS_ERROR_FAILURE; - } - if (aSS->mType & nsSelectionStruct::CHECKANCHOR && aSS->mAnchorOffset == aSS->mStartContent ){ - aTracker->SetFocus(nsnull, this); - aSS->mType = aSS->mType-nsSelectionStruct::CHECKANCHOR; - } - if (aSS->mType & nsSelectionStruct::CHECKFOCUS && aSS->mFocusOffset == aSS->mStartContent ){ - aTracker->SetFocus(this, nsnull); - aSS->mType = aSS->mType-nsSelectionStruct::CHECKFOCUS; - } - *aActualSelected = this; - - nsIFrame *nextInFlow = GetNextInFlow(); - if (nextInFlow){ - if (aSS->mType & nsSelectionStruct::SELTOEND || aSS->mEndContent > PRUint32(mContentLength + mContentOffset)){ - nextInFlow->SetSelectedContentOffsets(aSS, aTracker ,aActualSelected); - } - else if (aSS->mType & nsSelectionStruct::SELON) { //we must shut off all folowing selected frames if we are selecting frames - if (aSS->mType & nsSelectionStruct::CHECKANCHOR && aSS->mAnchorOffset == aSS->mEndContent ){ - aTracker->SetFocus(nsnull, this); - aSS->mType = aSS->mType - nsSelectionStruct::CHECKANCHOR; + PRBool found = PR_FALSE; + if (thisNode == startNode){ + if ((mContentOffset + mContentLength) >= startOffset){ + found = PR_TRUE; + if (thisNode == endNode){ //special case +/*#ifndef SHOW_SELECTION_CURSOR + if (aSelected && (endOffset == startOffset)) //no need to redraw since drawing takes place with cursor + found = PR_FALSE; +#endif +*/ + if (mContentOffset > endOffset) + found = PR_FALSE; } - if (aSS->mType & nsSelectionStruct::CHECKFOCUS && aSS->mFocusOffset == aSS->mEndContent ){ - aTracker->SetFocus(this, nsnull); - aSS->mType = aSS->mType - nsSelectionStruct::CHECKFOCUS; - } - nsSelectionStruct ss={0, 0,0, 0,0, 0,0, eDirNext, aSS->mForceRedraw}; - do { - nextInFlow->SetSelected(&ss); - } - while (NS_SUCCEEDED(nextInFlow->GetNextInFlow(&nextInFlow)) && nextInFlow);//this is ok because frames arent reference counted this is not a leak! } } - else { - if (aSS->mType & nsSelectionStruct::CHECKANCHOR && aSS->mAnchorOffset == aSS->mEndContent ){ - aTracker->SetFocus(nsnull, this); - aSS->mType = aSS->mType - nsSelectionStruct::CHECKANCHOR; - } - if (aSS->mType & nsSelectionStruct::CHECKFOCUS && aSS->mFocusOffset == aSS->mEndContent ){ - aTracker->SetFocus(this, nsnull); - aSS->mType = aSS->mType - nsSelectionStruct::CHECKFOCUS; - } - } - if (PRUint32(mContentOffset) > aSS->mStartContent){ - aSS->mStartFrame = 0; - } else - aSS->mStartFrame = aSS->mStartContent - mContentOffset; - aSS->mEndFrame = aSS->mEndContent - mContentOffset; - return SetSelected(aSS); -} - -NS_IMETHODIMP -nsTextFrame::GetSelected(PRBool *aSelected, - PRInt32 *aBeginOffset, - PRInt32 *aEndOffset, - PRInt32 *aBeginContentOffset) -{ - if (!aSelected || !aBeginOffset || !aEndOffset || !aBeginContentOffset) - return NS_ERROR_NULL_POINTER; - *aBeginOffset = mSelectionOffset; - *aEndOffset = mSelectionEnd; - *aSelected = mSelected; - *aBeginContentOffset = mContentOffset; -//should we check for whitespace here? dont think so. + if (thisNode == endNode){ + if (mContentOffset < endOffset) + found = PR_TRUE; + } + if (found){ //if range contains this frame... +/* nsRect frameRect; + GetRect(frameRect); + nsRect rect(0, 0, frameRect.width, frameRect.height); + Invalidate(rect, PR_FALSE); +*/ ForceDrawFrame(this); + } + nsFrameState frameState; + GetFrameState(&frameState); + if ( aSelected ) + frameState |= NS_FRAME_SELECTED_CONTENT; + else + frameState &= ~NS_FRAME_SELECTED_CONTENT; + SetFrameState(frameState); return NS_OK; } - NS_IMETHODIMP nsTextFrame::GetPointFromOffset(nsIPresContext* aPresContext, nsIRenderingContext* inRendContext, @@ -1968,8 +1959,9 @@ nsTextFrame::PeekOffset(nsSelectionAmount aAmount, nsIFrame **aResultFrame, PRInt32 *aFrameOffset, PRInt32 *aContentOffset, - PRBool aEatingWS) + PRBool aEatingWS) const { +/* //default, no matter what grab next/ previous sibling. if (!aResultFrame || !aFrameOffset || !aContentOffset) return NS_ERROR_NULL_POINTER; @@ -2163,6 +2155,8 @@ nsTextFrame::PeekOffset(nsSelectionAmount aAmount, result = NS_OK; } return result; + */ +return NS_OK; } NS_IMETHODIMP