зеркало из https://github.com/mozilla/gecko-dev.git
nsPresShell now listens to changes in the domselection. (also modified nsIEnumerator to use NS_IMETHOD instead of virtual nsresult). Added batching for selection changes. you can move the selection, do things then turn off batching for an update if necessary. also prevented circular referencing by adding listener removal to PresShell::endDocumentListening(sp)
This commit is contained in:
Родитель
a7658c739f
Коммит
fb3a597e8a
|
@ -11,17 +11,17 @@ class nsFrameIterator: public nsIEnumerator
|
|||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
virtual nsresult First();
|
||||
NS_IMETHOD First();
|
||||
|
||||
virtual nsresult Last();
|
||||
NS_IMETHOD Last();
|
||||
|
||||
virtual nsresult Next()=0;
|
||||
NS_IMETHOD Next()=0;
|
||||
|
||||
virtual nsresult Prev()=0;
|
||||
NS_IMETHOD Prev()=0;
|
||||
|
||||
virtual nsresult CurrentItem(nsISupports **aItem);
|
||||
NS_IMETHOD CurrentItem(nsISupports **aItem);
|
||||
|
||||
virtual nsresult IsDone();//what does this mean??off edge? yes
|
||||
NS_IMETHOD IsDone();//what does this mean??off edge? yes
|
||||
|
||||
nsFrameIterator();
|
||||
protected:
|
||||
|
@ -60,9 +60,9 @@ public:
|
|||
nsLeafIterator(nsIFrame *start);
|
||||
private :
|
||||
|
||||
virtual nsresult Next();
|
||||
NS_IMETHOD Next();
|
||||
|
||||
virtual nsresult Prev();
|
||||
NS_IMETHOD Prev();
|
||||
|
||||
};
|
||||
|
||||
|
@ -127,7 +127,7 @@ nsFrameIterator::nsFrameIterator()
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsFrameIterator::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
|
@ -148,7 +148,7 @@ nsFrameIterator::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsFrameIterator::CurrentItem(nsISupports **aItem)
|
||||
{
|
||||
if (!aItem)
|
||||
|
@ -159,7 +159,7 @@ nsFrameIterator::CurrentItem(nsISupports **aItem)
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsFrameIterator::IsDone()//what does this mean??off edge? yes
|
||||
{
|
||||
if (mOffEdge != 0)
|
||||
|
@ -169,7 +169,7 @@ nsFrameIterator::IsDone()//what does this mean??off edge? yes
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsFrameIterator::First()
|
||||
{
|
||||
mCurrent = mStart;
|
||||
|
@ -178,7 +178,7 @@ nsFrameIterator::First()
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsFrameIterator::Last()
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -198,7 +198,7 @@ nsLeafIterator::nsLeafIterator(nsIFrame *aStart)
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsLeafIterator::Next()
|
||||
{
|
||||
//recursive-oid method to get next frame
|
||||
|
@ -243,7 +243,7 @@ nsLeafIterator::Next()
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsLeafIterator::Prev()
|
||||
{
|
||||
//recursive-oid method to get prev frame
|
||||
|
|
|
@ -66,6 +66,11 @@ public:
|
|||
*/
|
||||
NS_IMETHOD ResetSelection(nsIFocusTracker *aTracker, nsIFrame *aStartFrame) = 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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
#include "nsCaretProperties.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
#include "nsIScrollableView.h"
|
||||
#include "nsIDOMSelectionListener.h"
|
||||
|
||||
|
||||
static PRBool gsNoisyRefs = PR_FALSE;
|
||||
#undef NOISY
|
||||
|
@ -173,6 +175,7 @@ static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID);
|
|||
static NS_DEFINE_IID(kIDOMRangeIID, NS_IDOMRANGE_IID);
|
||||
static NS_DEFINE_IID(kIDOMDocumentIID, NS_IDOMDOCUMENT_IID);
|
||||
static NS_DEFINE_IID(kIFocusTrackerIID, NS_IFOCUSTRACKER_IID);
|
||||
static NS_DEFINE_IID(kIDomSelectionListenerIID, NS_IDOMSELECTIONLISTENER_IID);
|
||||
static NS_DEFINE_IID(kIEventQueueServiceIID, NS_IEVENTQUEUESERVICE_IID);
|
||||
static NS_DEFINE_IID(kICaretIID, NS_ICARET_IID);
|
||||
static NS_DEFINE_IID(kICaretID, NS_ICARET_IID);
|
||||
|
@ -181,8 +184,8 @@ static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID);
|
|||
static NS_DEFINE_IID(kIScrollableViewIID, NS_ISCROLLABLEVIEW_IID);
|
||||
|
||||
class PresShell : public nsIPresShell, public nsIViewObserver,
|
||||
private nsIDocumentObserver, public nsIFocusTracker
|
||||
|
||||
private nsIDocumentObserver, public nsIFocusTracker,
|
||||
public nsIDOMSelectionListener
|
||||
{
|
||||
public:
|
||||
PresShell();
|
||||
|
@ -310,6 +313,8 @@ public:
|
|||
NS_IMETHOD GetCaret(nsICaret **outCaret);
|
||||
NS_IMETHOD RefreshCaret();
|
||||
|
||||
// nsIDOMSelectionListener interface
|
||||
NS_IMETHOD NotifySelectionChanged();
|
||||
|
||||
// implementation
|
||||
void HandleCantRenderReplacedElementEvent(nsIFrame* aFrame);
|
||||
|
@ -467,6 +472,12 @@ PresShell::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
|||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kIDomSelectionListenerIID)) {
|
||||
nsIDOMSelectionListener* tmp = this;
|
||||
*aInstancePtr = (void*) tmp;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
nsIPresShell* tmp = this;
|
||||
nsISupports* tmp2 = tmp;
|
||||
|
@ -543,7 +554,7 @@ PresShell::Init(nsIDocument* aDocument,
|
|||
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
|
||||
nsCOMPtr<nsIDOMRange>range;
|
||||
|
@ -766,6 +777,16 @@ PresShell::EndObservingDocument()
|
|||
if (nsnull != mDocument) {
|
||||
mDocument->RemoveObserver(this);
|
||||
}
|
||||
if (mSelection){
|
||||
nsCOMPtr<nsIDOMSelection> domselection;
|
||||
nsresult result;
|
||||
domselection = do_QueryInterface(mSelection , &result);
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
if (!domselection)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
domselection->RemoveSelectionListener(this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -939,6 +960,17 @@ NS_IMETHODIMP PresShell::RefreshCaret()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/*implementation of the nsIDOMSelectionListener
|
||||
it will invoke the resetselection to update the presentation shell's frames
|
||||
*/
|
||||
NS_IMETHODIMP PresShell::NotifySelectionChanged()
|
||||
{
|
||||
if (!mSelection)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
mSelection->ResetSelection(this, mRootFrame);
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
nsresult PresShell::DisableCaret()
|
||||
{
|
||||
if (mCaret)
|
||||
|
@ -1757,7 +1789,10 @@ PresShell::HandleEvent(nsIView *aView,
|
|||
if (nsnull != frame) {
|
||||
if (mSelection && mFocusEventFrame && aEvent->eventStructType == NS_KEY_EVENT)
|
||||
{
|
||||
mSelection->EnableFrameNotification(PR_FALSE);
|
||||
mSelection->HandleKeyEvent((nsIFocusTracker *)this, aEvent, mFocusEventFrame);
|
||||
mSelection->EnableFrameNotification(PR_TRUE); //prevents secondary reset selection called since
|
||||
//we are a listener now.
|
||||
}
|
||||
frame->GetFrameForPoint(aEvent->point, &mCurrentEventFrame);
|
||||
if (nsnull != mCurrentEventFrame) {
|
||||
|
|
|
@ -84,6 +84,19 @@ public:
|
|||
NS_IMETHOD AddSelectionListener(nsIDOMSelectionListener* inNewListener) = 0;
|
||||
NS_IMETHOD RemoveSelectionListener(nsIDOMSelectionListener* inListenerToRemove) = 0;
|
||||
|
||||
/** StartBatchChanges
|
||||
* will return NS_OK if there is no previous unmatched StartBatchChanges Called
|
||||
* calling this multiple times should have no effect.
|
||||
*/
|
||||
NS_IMETHOD StartBatchChanges() = 0;
|
||||
|
||||
/** EndBatchChanges
|
||||
* will return NS_OK if there was a StartBatch Changes Called
|
||||
* calling this multiple times should have no effect. will return NS_ERROR_FAILURE
|
||||
* after the first call. if any changes took place, it will then immediately notify all
|
||||
*/
|
||||
NS_IMETHOD EndBatchChanges() = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -36,13 +36,14 @@
|
|||
{ 0xa6cf90e2, 0x15b3, 0x11d2, \
|
||||
{ 0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
|
||||
|
||||
|
||||
|
||||
// Selection interface
|
||||
class nsIDOMSelectionListener : public nsISupports
|
||||
{
|
||||
public:
|
||||
static const nsIID& IID() { static nsIID iid = NS_IDOMSELECTIONLISTENER_IID; return iid; }
|
||||
|
||||
|
||||
NS_IMETHOD NotifySelectionChanged() = 0;
|
||||
|
||||
};
|
||||
|
|
|
@ -66,6 +66,11 @@ public:
|
|||
*/
|
||||
NS_IMETHOD ResetSelection(nsIFocusTracker *aTracker, nsIFrame *aStartFrame) = 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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -11,17 +11,17 @@ class nsFrameIterator: public nsIEnumerator
|
|||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
virtual nsresult First();
|
||||
NS_IMETHOD First();
|
||||
|
||||
virtual nsresult Last();
|
||||
NS_IMETHOD Last();
|
||||
|
||||
virtual nsresult Next()=0;
|
||||
NS_IMETHOD Next()=0;
|
||||
|
||||
virtual nsresult Prev()=0;
|
||||
NS_IMETHOD Prev()=0;
|
||||
|
||||
virtual nsresult CurrentItem(nsISupports **aItem);
|
||||
NS_IMETHOD CurrentItem(nsISupports **aItem);
|
||||
|
||||
virtual nsresult IsDone();//what does this mean??off edge? yes
|
||||
NS_IMETHOD IsDone();//what does this mean??off edge? yes
|
||||
|
||||
nsFrameIterator();
|
||||
protected:
|
||||
|
@ -60,9 +60,9 @@ public:
|
|||
nsLeafIterator(nsIFrame *start);
|
||||
private :
|
||||
|
||||
virtual nsresult Next();
|
||||
NS_IMETHOD Next();
|
||||
|
||||
virtual nsresult Prev();
|
||||
NS_IMETHOD Prev();
|
||||
|
||||
};
|
||||
|
||||
|
@ -127,7 +127,7 @@ nsFrameIterator::nsFrameIterator()
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsFrameIterator::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
|
@ -148,7 +148,7 @@ nsFrameIterator::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsFrameIterator::CurrentItem(nsISupports **aItem)
|
||||
{
|
||||
if (!aItem)
|
||||
|
@ -159,7 +159,7 @@ nsFrameIterator::CurrentItem(nsISupports **aItem)
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsFrameIterator::IsDone()//what does this mean??off edge? yes
|
||||
{
|
||||
if (mOffEdge != 0)
|
||||
|
@ -169,7 +169,7 @@ nsFrameIterator::IsDone()//what does this mean??off edge? yes
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsFrameIterator::First()
|
||||
{
|
||||
mCurrent = mStart;
|
||||
|
@ -178,7 +178,7 @@ nsFrameIterator::First()
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsFrameIterator::Last()
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -198,7 +198,7 @@ nsLeafIterator::nsLeafIterator(nsIFrame *aStart)
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsLeafIterator::Next()
|
||||
{
|
||||
//recursive-oid method to get next frame
|
||||
|
@ -243,7 +243,7 @@ nsLeafIterator::Next()
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsLeafIterator::Prev()
|
||||
{
|
||||
//recursive-oid method to get prev frame
|
||||
|
|
|
@ -74,6 +74,7 @@ public:
|
|||
NS_IMETHOD HandleKeyEvent(nsIFocusTracker *aTracker, nsGUIEvent *aGuiEvent, nsIFrame *aFrame);
|
||||
NS_IMETHOD TakeFocus(nsIFocusTracker *aTracker, nsIFrame *aFrame, PRInt32 aOffset, PRInt32 aContentOffset, PRBool aContinueSelection);
|
||||
NS_IMETHOD ResetSelection(nsIFocusTracker *aTracker, nsIFrame *aStartFrame);
|
||||
NS_IMETHOD EnableFrameNotification(PRBool aEnable){mNotifyFrames = aEnable; return NS_OK;}
|
||||
/*END nsIFrameSelection interfacse*/
|
||||
|
||||
/*BEGIN nsIDOMSelection interface implementations*/
|
||||
|
@ -88,6 +89,8 @@ public:
|
|||
|
||||
NS_IMETHOD AddSelectionListener(nsIDOMSelectionListener* inNewListener);
|
||||
NS_IMETHOD RemoveSelectionListener(nsIDOMSelectionListener* inListenerToRemove);
|
||||
NS_IMETHOD StartBatchChanges();
|
||||
NS_IMETHOD EndBatchChanges();
|
||||
|
||||
/*END nsIDOMSelection interface implementations*/
|
||||
|
||||
|
@ -114,6 +117,9 @@ private:
|
|||
nsIDOMNode* GetFocusNode(); //where is the carret
|
||||
PRInt32 GetFocusOffset();
|
||||
void setFocus(nsIDOMNode*, PRInt32);
|
||||
PRBool GetBatching(){return mBatching;}
|
||||
PRBool GetNotifyFrames(){return mNotifyFrames;}
|
||||
void SetDirty(PRBool aDirty=PR_TRUE){if (mBatching) mChangesDuringBatching = aDirty;}
|
||||
|
||||
nsresult NotifySelectionListeners(); // add parameters to say collapsed etc?
|
||||
|
||||
|
@ -124,8 +130,13 @@ private:
|
|||
nsCOMPtr<nsIDOMNode> mFocusNode; //where is the carret
|
||||
PRInt32 mFocusOffset;
|
||||
|
||||
nsCOMPtr<nsISupportsArray> mSelectionListeners;
|
||||
//batching
|
||||
PRBool mBatching;
|
||||
PRBool mChangesDuringBatching;
|
||||
PRBool mNotifyFrames;
|
||||
|
||||
|
||||
nsCOMPtr<nsISupportsArray> mSelectionListeners;
|
||||
};
|
||||
|
||||
class nsRangeListIterator : public nsIEnumerator
|
||||
|
@ -136,21 +147,21 @@ see the nsIEnumerator for more details*/
|
|||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
virtual nsresult First();
|
||||
NS_IMETHOD First();
|
||||
|
||||
virtual nsresult Last();
|
||||
NS_IMETHOD Last();
|
||||
|
||||
virtual nsresult Next();
|
||||
NS_IMETHOD Next();
|
||||
|
||||
virtual nsresult Prev();
|
||||
NS_IMETHOD Prev();
|
||||
|
||||
virtual nsresult CurrentItem(nsISupports **aRange);
|
||||
NS_IMETHOD CurrentItem(nsISupports **aRange);
|
||||
|
||||
virtual nsresult IsDone();
|
||||
NS_IMETHOD IsDone();
|
||||
|
||||
/*END nsIEnumerator interfaces*/
|
||||
/*BEGIN Helper Methods*/
|
||||
virtual nsresult CurrentItem(nsIDOMRange **aRange);
|
||||
NS_IMETHOD CurrentItem(nsIDOMRange **aRange);
|
||||
/*END Helper Methods*/
|
||||
private:
|
||||
friend class nsRangeList;
|
||||
|
@ -207,7 +218,7 @@ nsRangeListIterator::~nsRangeListIterator()
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsRangeListIterator::Next()
|
||||
{
|
||||
mIndex++;
|
||||
|
@ -218,7 +229,7 @@ nsRangeListIterator::Next()
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsRangeListIterator::Prev()
|
||||
{
|
||||
mIndex--;
|
||||
|
@ -229,7 +240,7 @@ nsRangeListIterator::Prev()
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsRangeListIterator::First()
|
||||
{
|
||||
if (!mRangeList)
|
||||
|
@ -240,7 +251,7 @@ nsRangeListIterator::First()
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsRangeListIterator::Last()
|
||||
{
|
||||
if (!mRangeList)
|
||||
|
@ -251,7 +262,7 @@ nsRangeListIterator::Last()
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsRangeListIterator::CurrentItem(nsISupports **aItem)
|
||||
{
|
||||
if (!aItem)
|
||||
|
@ -265,7 +276,7 @@ nsRangeListIterator::CurrentItem(nsISupports **aItem)
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsRangeListIterator::CurrentItem(nsIDOMRange **aItem)
|
||||
{
|
||||
if (!aItem)
|
||||
|
@ -279,7 +290,7 @@ nsRangeListIterator::CurrentItem(nsIDOMRange **aItem)
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsRangeListIterator::IsDone()
|
||||
{
|
||||
if (mIndex >= 0 && mIndex < (PRInt32)mRangeList->mRangeArray->Count() ) {
|
||||
|
@ -296,7 +307,7 @@ NS_IMPL_RELEASE(nsRangeListIterator)
|
|||
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsRangeListIterator::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
|
@ -341,6 +352,9 @@ nsRangeList::nsRangeList()
|
|||
NS_INIT_REFCNT();
|
||||
NS_NewISupportsArray(getter_AddRefs(mRangeArray));
|
||||
NS_NewISupportsArray(getter_AddRefs(mSelectionListeners));
|
||||
mBatching = PR_FALSE;
|
||||
mChangesDuringBatching = PR_FALSE;
|
||||
mNotifyFrames = PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -376,7 +390,7 @@ NS_IMPL_ADDREF(nsRangeList)
|
|||
NS_IMPL_RELEASE(nsRangeList)
|
||||
|
||||
|
||||
nsresult
|
||||
NS_IMETHODIMP
|
||||
nsRangeList::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
{
|
||||
if (NULL == aInstancePtr) {
|
||||
|
@ -532,33 +546,37 @@ nsRangeList::HandleKeyEvent(nsIFocusTracker *aTracker, nsGUIEvent *aGuiEvent, ns
|
|||
if (!domnode)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
//DUMMY CHECKING. CAN BE REMOVED. MAYBE IT WILL FOR SPEED PURPOSES
|
||||
PRBool selected;
|
||||
PRInt32 beginoffset;
|
||||
PRInt32 endoffset;
|
||||
PRInt32 contentoffset;
|
||||
//check to make sure the frame REALLY has the focus point.
|
||||
if (NS_SUCCEEDED(aFrame->GetSelected(&selected,&beginoffset,&endoffset, &contentoffset))){
|
||||
if (domnode != mFocusNode || (contentoffset + endoffset) != mFocusOffset) //not really the insertion frame
|
||||
return NS_ERROR_FAILURE;
|
||||
nsresult result = NS_OK;
|
||||
result = aFrame->GetSelected(&selected,&beginoffset,&endoffset, &contentoffset);
|
||||
if (NS_FAILED(result)){
|
||||
return result;
|
||||
}
|
||||
|
||||
nsKeyEvent *keyEvent = (nsKeyEvent *)aGuiEvent; //this is ok. It really is a keyevent
|
||||
nsIFrame *resultFrame;
|
||||
PRInt32 frameOffset;
|
||||
PRInt32 contentOffset;
|
||||
PRInt32 offsetused = beginoffset;
|
||||
switch (keyEvent->keyCode){
|
||||
case nsIDOMEvent::VK_LEFT :
|
||||
//we need to look for the previous PAINTED location to move the cursor to.
|
||||
printf("debug vk left\n");
|
||||
if (NS_SUCCEEDED(aFrame->PeekOffset(eSelectCharacter, eDirPrevious, endoffset, &resultFrame, &frameOffset, &contentOffset)) && resultFrame){
|
||||
if (endoffset < beginoffset)
|
||||
offsetused = endoffset;
|
||||
if (NS_SUCCEEDED(aFrame->PeekOffset(eSelectCharacter, eDirPrevious, offsetused, &resultFrame, &frameOffset, &contentOffset)) && resultFrame){
|
||||
return TakeFocus(aTracker, resultFrame, frameOffset, contentOffset, keyEvent->isShift);
|
||||
}
|
||||
break;
|
||||
case nsIDOMEvent::VK_RIGHT :
|
||||
//we need to look for the next PAINTED location to move the cursor to.
|
||||
printf("debug vk right\n");
|
||||
if (NS_SUCCEEDED(aFrame->PeekOffset(eSelectCharacter, eDirNext, endoffset, &resultFrame, &frameOffset, &contentOffset)) && resultFrame){
|
||||
if (endoffset > beginoffset)
|
||||
offsetused = endoffset;
|
||||
if (NS_SUCCEEDED(aFrame->PeekOffset(eSelectCharacter, eDirNext, offsetused, &resultFrame, &frameOffset, &contentOffset)) && resultFrame){
|
||||
return TakeFocus(aTracker, resultFrame, frameOffset, contentOffset, keyEvent->isShift);
|
||||
}
|
||||
case nsIDOMEvent::VK_UP :
|
||||
|
@ -705,6 +723,8 @@ nsRangeList::TakeFocus(nsIFocusTracker *aTracker, nsIFrame *aFrame, PRInt32 aOff
|
|||
{
|
||||
if (!aTracker || !aFrame)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
if (GetBatching())
|
||||
return NS_ERROR_FAILURE;
|
||||
//HACKHACKHACK
|
||||
nsCOMPtr<nsIContent> content;
|
||||
nsCOMPtr<nsIDOMNode> domNode;
|
||||
|
@ -741,7 +761,12 @@ nsRangeList::TakeFocus(nsIFocusTracker *aTracker, nsIFrame *aFrame, PRInt32 aOff
|
|||
direction = PR_TRUE; //slecting "english" right
|
||||
aFrame->SetSelected(PR_TRUE,aOffset,aOffset,PR_FALSE);
|
||||
aTracker->SetFocus(aFrame,aFrame);
|
||||
PRBool batching = mBatching;//hack to use the collapse code.
|
||||
PRBool changes = mChangesDuringBatching;
|
||||
mBatching = PR_TRUE;
|
||||
Collapse(domNode, aContentOffset + aOffset);
|
||||
mBatching = batching;
|
||||
mChangesDuringBatching = changes;
|
||||
}
|
||||
else {
|
||||
if (aFrame == frame){ //drag to same frame
|
||||
|
@ -908,6 +933,12 @@ nsRangeList::ResetSelection(nsIFocusTracker *aTracker, nsIFrame *aStartFrame)
|
|||
PRInt32 endOffset;
|
||||
nsIFrame *result;
|
||||
nsCOMPtr<nsIDOMRange> 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)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -985,7 +1016,7 @@ NS_METHOD nsRangeList::AddSelectionListener(nsIDOMSelectionListener* inNewListen
|
|||
|
||||
|
||||
|
||||
NS_METHOD nsRangeList::RemoveSelectionListener(nsIDOMSelectionListener* inListenerToRemove)
|
||||
NS_IMETHODIMP nsRangeList::RemoveSelectionListener(nsIDOMSelectionListener* inListenerToRemove)
|
||||
{
|
||||
if (!mSelectionListeners)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -996,26 +1027,58 @@ NS_METHOD nsRangeList::RemoveSelectionListener(nsIDOMSelectionListener* inListen
|
|||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP nsRangeList::StartBatchChanges()
|
||||
{
|
||||
nsresult result(NS_OK);
|
||||
if (PR_TRUE == mBatching)
|
||||
result = NS_ERROR_FAILURE;
|
||||
mBatching = PR_TRUE;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NS_IMETHODIMP nsRangeList::EndBatchChanges()
|
||||
{
|
||||
nsresult result(NS_OK);
|
||||
if (PR_FALSE == mBatching)
|
||||
result = NS_ERROR_FAILURE;
|
||||
mBatching = PR_FALSE;
|
||||
if (mChangesDuringBatching){
|
||||
mChangesDuringBatching = PR_FALSE;
|
||||
NotifySelectionListeners();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
nsresult nsRangeList::NotifySelectionListeners()
|
||||
{
|
||||
if (!mSelectionListeners)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
|
||||
if (GetBatching()){
|
||||
SetDirty();
|
||||
return NS_OK;
|
||||
}
|
||||
for (PRInt32 i = 0; i < mSelectionListeners->Count();i++)
|
||||
{
|
||||
nsCOMPtr<nsISupports> thisEntry(dont_QueryInterface(mSelectionListeners->ElementAt(i)));
|
||||
nsCOMPtr<nsIDOMSelectionListener> thisListener(do_QueryInterface(thisEntry));
|
||||
nsCOMPtr<nsIDOMSelectionListener> thisListener;
|
||||
thisListener = do_QueryInterface(mSelectionListeners->ElementAt(i));
|
||||
if (thisListener)
|
||||
thisListener->NotifySelectionChanged();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//END nsIFrameSelection methods
|
||||
|
||||
//BEGIN nsIDOMSelection interface implementations
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
#endif
|
||||
|
||||
/** ClearSelection zeroes the selection
|
||||
*/
|
||||
|
@ -1047,13 +1110,15 @@ nsRangeList::AddRange(nsIDOMRange* aRange)
|
|||
// Also need to notify the frames!
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Collapse sets the whole selection to be one point.
|
||||
*/
|
||||
NS_IMETHODIMP
|
||||
nsRangeList::Collapse(nsIDOMNode* aParentNode, PRInt32 aOffset)
|
||||
{
|
||||
nsresult res;
|
||||
nsresult result;
|
||||
|
||||
// Delete all of the current ranges
|
||||
if (!mRangeArray)
|
||||
|
@ -1061,27 +1126,29 @@ nsRangeList::Collapse(nsIDOMNode* aParentNode, PRInt32 aOffset)
|
|||
Clear();
|
||||
|
||||
nsCOMPtr<nsIDOMRange> range;
|
||||
res = nsRepository::CreateInstance(kRangeCID, nsnull,
|
||||
result = nsRepository::CreateInstance(kRangeCID, nsnull,
|
||||
kIDOMRangeIID,
|
||||
getter_AddRefs(range));
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return res;
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
if (! range)
|
||||
if (! range){
|
||||
NS_ASSERTION(PR_FALSE,"Create Instance Failed nsRangeList::Collapse");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
res = range->SetEnd(aParentNode, aOffset);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return res;
|
||||
res = range->SetStart(aParentNode, aOffset);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return res;
|
||||
}
|
||||
result = range->SetEnd(aParentNode, aOffset);
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
result = range->SetStart(aParentNode, aOffset);
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
setAnchor(aParentNode, aOffset);
|
||||
setFocus(aParentNode, aOffset);
|
||||
|
||||
res = AddItem(range);
|
||||
if (!NS_SUCCEEDED(res))
|
||||
return res;
|
||||
result = AddItem(range);
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
|
||||
return NotifySelectionListeners();
|
||||
}
|
||||
|
|
|
@ -719,7 +719,9 @@ nsFrame::HandlePress(nsIPresContext& aPresContext,
|
|||
nsIFrameSelection *frameselection = nsnull;
|
||||
if (NS_SUCCEEDED(selection->QueryInterface(kIFrameSelection,
|
||||
(void **)&frameselection))) {
|
||||
frameselection->EnableFrameNotification(PR_FALSE);
|
||||
frameselection->TakeFocus(tracker, this, startPos, contentOffset, PR_FALSE);
|
||||
frameselection->EnableFrameNotification(PR_TRUE);//prevent cyclic call to reset selection.
|
||||
NS_RELEASE(frameselection);
|
||||
}
|
||||
NS_RELEASE(tracker);
|
||||
|
@ -760,7 +762,9 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsIPresContext& aPresContext,
|
|||
if (NS_SUCCEEDED(shell->QueryInterface(kIFocusTracker,(void **)&tracker))) {
|
||||
nsIFrameSelection* frameselection;
|
||||
if (NS_SUCCEEDED(selection->QueryInterface(kIFrameSelection, (void **)&frameselection))) {
|
||||
frameselection->EnableFrameNotification(PR_FALSE);
|
||||
frameselection->TakeFocus(tracker, this, startPos, contentOffset, PR_TRUE); //TRUE IS THE DIFFERENCE
|
||||
frameselection->EnableFrameNotification(PR_TRUE);//prevent cyclic call to reset selection.
|
||||
NS_RELEASE(frameselection);
|
||||
}
|
||||
NS_RELEASE(tracker);
|
||||
|
|
|
@ -870,8 +870,7 @@ TextFrame::PaintUnicodeText(nsIPresContext& aPresContext,
|
|||
CURSOR_COLOR);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
nscoord x = dx;
|
||||
|
||||
if (selectionOffset) {
|
||||
|
@ -1142,7 +1141,6 @@ TextFrame::PaintTextSlowly(nsIPresContext& aPresContext,
|
|||
shell->GetDocument(getter_AddRefs(doc));
|
||||
PRBool displaySelection;
|
||||
displaySelection = doc->GetDisplaySelection();
|
||||
displaySelection = PR_FALSE;
|
||||
|
||||
// Make enough space to transform
|
||||
PRUnichar wordBufMem[WORD_BUF_SIZE];
|
||||
|
@ -1151,7 +1149,7 @@ TextFrame::PaintTextSlowly(nsIPresContext& aPresContext,
|
|||
PRInt32* ip = indicies;
|
||||
PRUnichar* paintBuf = paintBufMem;
|
||||
if (mContentLength > TEXT_BUF_SIZE) {
|
||||
ip = new PRInt32[mContentLength];
|
||||
ip = new PRInt32[mContentLength+1];
|
||||
paintBuf = new PRUnichar[mContentLength];
|
||||
}
|
||||
nscoord width = mRect.width;
|
||||
|
@ -1162,6 +1160,7 @@ TextFrame::PaintTextSlowly(nsIPresContext& aPresContext,
|
|||
aTextStyle.mNumSpaces = PrepareUnicodeText(tx,
|
||||
displaySelection ? ip : nsnull,
|
||||
paintBuf, textLength, width);
|
||||
ip[mContentLength] = ip[mContentLength-1]+1; //must set up last one for selection beyond edge
|
||||
if (mRect.width > mComputedWidth) {
|
||||
if (0 != aTextStyle.mNumSpaces) {
|
||||
nscoord extra = mRect.width - mComputedWidth;
|
||||
|
@ -1182,18 +1181,33 @@ TextFrame::PaintTextSlowly(nsIPresContext& aPresContext,
|
|||
|
||||
PRUnichar* text = paintBuf;
|
||||
if (0 != textLength) {
|
||||
if (!displaySelection) {
|
||||
if (!displaySelection || !mSelected || mSelectionOffset > mContentLength) {
|
||||
// When there is no selection showing, use the fastest and
|
||||
// simplest rendering approach
|
||||
RenderString(aRenderingContext, aStyleContext, aTextStyle,
|
||||
text, textLength, dx, dy, width);
|
||||
}
|
||||
else {
|
||||
SelectionInfo si;
|
||||
// ComputeSelectionInfo(aRenderingContext, doc, ip, textLength, si);
|
||||
|
||||
nscoord textWidth;
|
||||
if (si.mEmptySelection) {
|
||||
if (mSelectionOffset < 0)
|
||||
mSelectionOffset = 0;
|
||||
if (mSelectionEnd < 0)
|
||||
mSelectionEnd = mContentLength;
|
||||
if (mSelectionEnd > mContentLength)
|
||||
mSelectionEnd = mContentLength;
|
||||
if (mSelectionOffset > mContentLength)
|
||||
mSelectionOffset = 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);
|
||||
|
||||
|
@ -1202,7 +1216,7 @@ TextFrame::PaintTextSlowly(nsIPresContext& aPresContext,
|
|||
#ifdef SHOW_SELECTION_CURSOR
|
||||
|
||||
GetWidth(aRenderingContext, aTextStyle,
|
||||
text, PRUint32(si.mStartOffset), textWidth);
|
||||
text, PRUint32(selectionOffset), textWidth);
|
||||
RenderSelectionCursor(aRenderingContext,
|
||||
dx + textWidth, dy, mRect.height,
|
||||
CURSOR_COLOR);
|
||||
|
@ -1211,21 +1225,21 @@ TextFrame::PaintTextSlowly(nsIPresContext& aPresContext,
|
|||
else {
|
||||
nscoord x = dx;
|
||||
|
||||
if (0 != si.mStartOffset) {
|
||||
if (selectionOffset) {
|
||||
// Render first (unselected) section
|
||||
GetWidth(aRenderingContext, aTextStyle,
|
||||
text, PRUint32(si.mStartOffset),
|
||||
text, PRUint32(selectionOffset),
|
||||
textWidth);
|
||||
RenderString(aRenderingContext, aStyleContext, aTextStyle,
|
||||
text, si.mStartOffset,
|
||||
text, selectionOffset,
|
||||
x, dy, textWidth);
|
||||
x += textWidth;
|
||||
}
|
||||
PRInt32 secondLen = si.mEndOffset - si.mStartOffset;
|
||||
PRInt32 secondLen = selectionEnd - selectionOffset;
|
||||
if (0 != secondLen) {
|
||||
// Get the width of the second (selected) section
|
||||
GetWidth(aRenderingContext, aTextStyle,
|
||||
text + si.mStartOffset,
|
||||
text + selectionOffset,
|
||||
PRUint32(secondLen), textWidth);
|
||||
|
||||
// Render second (selected) section
|
||||
|
@ -1233,21 +1247,24 @@ TextFrame::PaintTextSlowly(nsIPresContext& aPresContext,
|
|||
aRenderingContext.FillRect(x, dy, textWidth, mRect.height);
|
||||
aRenderingContext.SetColor(aTextStyle.mSelectionTextColor);
|
||||
RenderString(aRenderingContext, aStyleContext, aTextStyle,
|
||||
text + si.mStartOffset, secondLen,
|
||||
text + selectionOffset, secondLen,
|
||||
x, dy, textWidth);
|
||||
aRenderingContext.SetColor(aTextStyle.mColor->mColor);
|
||||
x += textWidth;
|
||||
}
|
||||
if (textLength != si.mEndOffset) {
|
||||
PRInt32 thirdLen = textLength - si.mEndOffset;
|
||||
if (textLength != selectionEnd) {
|
||||
PRInt32 thirdLen = textLength - selectionEnd;
|
||||
|
||||
// Render third (unselected) section
|
||||
GetWidth(aRenderingContext, aTextStyle,
|
||||
text + si.mEndOffset, PRUint32(thirdLen),
|
||||
textWidth);
|
||||
RenderString(aRenderingContext, aStyleContext, aTextStyle,
|
||||
text + si.mEndOffset,
|
||||
thirdLen, x, dy, textWidth);
|
||||
if (thirdLen > 0) //Text length is not negative or zero
|
||||
{
|
||||
GetWidth(aRenderingContext, aTextStyle,
|
||||
text + selectionOffset, PRUint32(thirdLen),
|
||||
textWidth);
|
||||
RenderString(aRenderingContext, aStyleContext, aTextStyle,
|
||||
text + selectionEnd,
|
||||
thirdLen, x, dy, textWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1298,7 +1315,6 @@ TextFrame::PaintAsciiText(nsIPresContext& aPresContext,
|
|||
displaySelection ? ip : nsnull,
|
||||
rawPaintBuf, textLength, width);
|
||||
ip[mContentLength] = ip[mContentLength-1]+1; //must set up last one for selection beyond edge
|
||||
|
||||
// Translate unicode data into ascii for rendering
|
||||
char* dst = paintBuf;
|
||||
char* end = dst + textLength;
|
||||
|
@ -1347,9 +1363,10 @@ TextFrame::PaintAsciiText(nsIPresContext& aPresContext,
|
|||
// aRenderingContext.GetWidth(text, PRUint32(si.mStartOffset), textWidth);
|
||||
|
||||
shell->RefreshCaret();
|
||||
|
||||
|
||||
#ifdef SHOW_SELECTION_CURSOR
|
||||
aRenderingContext.GetWidth(text, PRUint32(selectionOffset), textWidth);
|
||||
|
||||
RenderSelectionCursor(aRenderingContext,
|
||||
dx + textWidth, dy, mRect.height,
|
||||
CURSOR_COLOR);
|
||||
|
@ -1389,13 +1406,17 @@ TextFrame::PaintAsciiText(nsIPresContext& aPresContext,
|
|||
if (textLength != selectionEnd) {
|
||||
PRInt32 thirdLen = textLength - selectionEnd;
|
||||
|
||||
// Render third (unselected) section
|
||||
aRenderingContext.GetWidth(text + selectionEnd, PRUint32(thirdLen),
|
||||
textWidth);
|
||||
aRenderingContext.DrawString(text + selectionEnd,
|
||||
PRUint32(thirdLen), x, dy);
|
||||
PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle,
|
||||
x, dy, textWidth);
|
||||
if (thirdLen > 0) //Text length is not negative or zero
|
||||
{
|
||||
|
||||
// Render third (unselected) section
|
||||
aRenderingContext.GetWidth(text + selectionEnd, PRUint32(thirdLen),
|
||||
textWidth);
|
||||
aRenderingContext.DrawString(text + selectionEnd,
|
||||
PRUint32(thirdLen), x, dy);
|
||||
PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle,
|
||||
x, dy, textWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -719,7 +719,9 @@ nsFrame::HandlePress(nsIPresContext& aPresContext,
|
|||
nsIFrameSelection *frameselection = nsnull;
|
||||
if (NS_SUCCEEDED(selection->QueryInterface(kIFrameSelection,
|
||||
(void **)&frameselection))) {
|
||||
frameselection->EnableFrameNotification(PR_FALSE);
|
||||
frameselection->TakeFocus(tracker, this, startPos, contentOffset, PR_FALSE);
|
||||
frameselection->EnableFrameNotification(PR_TRUE);//prevent cyclic call to reset selection.
|
||||
NS_RELEASE(frameselection);
|
||||
}
|
||||
NS_RELEASE(tracker);
|
||||
|
@ -760,7 +762,9 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsIPresContext& aPresContext,
|
|||
if (NS_SUCCEEDED(shell->QueryInterface(kIFocusTracker,(void **)&tracker))) {
|
||||
nsIFrameSelection* frameselection;
|
||||
if (NS_SUCCEEDED(selection->QueryInterface(kIFrameSelection, (void **)&frameselection))) {
|
||||
frameselection->EnableFrameNotification(PR_FALSE);
|
||||
frameselection->TakeFocus(tracker, this, startPos, contentOffset, PR_TRUE); //TRUE IS THE DIFFERENCE
|
||||
frameselection->EnableFrameNotification(PR_TRUE);//prevent cyclic call to reset selection.
|
||||
NS_RELEASE(frameselection);
|
||||
}
|
||||
NS_RELEASE(tracker);
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
#include "nsCaretProperties.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
#include "nsIScrollableView.h"
|
||||
#include "nsIDOMSelectionListener.h"
|
||||
|
||||
|
||||
static PRBool gsNoisyRefs = PR_FALSE;
|
||||
#undef NOISY
|
||||
|
@ -173,6 +175,7 @@ static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID);
|
|||
static NS_DEFINE_IID(kIDOMRangeIID, NS_IDOMRANGE_IID);
|
||||
static NS_DEFINE_IID(kIDOMDocumentIID, NS_IDOMDOCUMENT_IID);
|
||||
static NS_DEFINE_IID(kIFocusTrackerIID, NS_IFOCUSTRACKER_IID);
|
||||
static NS_DEFINE_IID(kIDomSelectionListenerIID, NS_IDOMSELECTIONLISTENER_IID);
|
||||
static NS_DEFINE_IID(kIEventQueueServiceIID, NS_IEVENTQUEUESERVICE_IID);
|
||||
static NS_DEFINE_IID(kICaretIID, NS_ICARET_IID);
|
||||
static NS_DEFINE_IID(kICaretID, NS_ICARET_IID);
|
||||
|
@ -181,8 +184,8 @@ static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID);
|
|||
static NS_DEFINE_IID(kIScrollableViewIID, NS_ISCROLLABLEVIEW_IID);
|
||||
|
||||
class PresShell : public nsIPresShell, public nsIViewObserver,
|
||||
private nsIDocumentObserver, public nsIFocusTracker
|
||||
|
||||
private nsIDocumentObserver, public nsIFocusTracker,
|
||||
public nsIDOMSelectionListener
|
||||
{
|
||||
public:
|
||||
PresShell();
|
||||
|
@ -310,6 +313,8 @@ public:
|
|||
NS_IMETHOD GetCaret(nsICaret **outCaret);
|
||||
NS_IMETHOD RefreshCaret();
|
||||
|
||||
// nsIDOMSelectionListener interface
|
||||
NS_IMETHOD NotifySelectionChanged();
|
||||
|
||||
// implementation
|
||||
void HandleCantRenderReplacedElementEvent(nsIFrame* aFrame);
|
||||
|
@ -467,6 +472,12 @@ PresShell::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
|||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kIDomSelectionListenerIID)) {
|
||||
nsIDOMSelectionListener* tmp = this;
|
||||
*aInstancePtr = (void*) tmp;
|
||||
NS_ADDREF_THIS();
|
||||
return NS_OK;
|
||||
}
|
||||
if (aIID.Equals(kISupportsIID)) {
|
||||
nsIPresShell* tmp = this;
|
||||
nsISupports* tmp2 = tmp;
|
||||
|
@ -543,7 +554,7 @@ PresShell::Init(nsIDocument* aDocument,
|
|||
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
|
||||
nsCOMPtr<nsIDOMRange>range;
|
||||
|
@ -766,6 +777,16 @@ PresShell::EndObservingDocument()
|
|||
if (nsnull != mDocument) {
|
||||
mDocument->RemoveObserver(this);
|
||||
}
|
||||
if (mSelection){
|
||||
nsCOMPtr<nsIDOMSelection> domselection;
|
||||
nsresult result;
|
||||
domselection = do_QueryInterface(mSelection , &result);
|
||||
if (NS_FAILED(result))
|
||||
return result;
|
||||
if (!domselection)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
domselection->RemoveSelectionListener(this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -939,6 +960,17 @@ NS_IMETHODIMP PresShell::RefreshCaret()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
/*implementation of the nsIDOMSelectionListener
|
||||
it will invoke the resetselection to update the presentation shell's frames
|
||||
*/
|
||||
NS_IMETHODIMP PresShell::NotifySelectionChanged()
|
||||
{
|
||||
if (!mSelection)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
mSelection->ResetSelection(this, mRootFrame);
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
nsresult PresShell::DisableCaret()
|
||||
{
|
||||
if (mCaret)
|
||||
|
@ -1757,7 +1789,10 @@ PresShell::HandleEvent(nsIView *aView,
|
|||
if (nsnull != frame) {
|
||||
if (mSelection && mFocusEventFrame && aEvent->eventStructType == NS_KEY_EVENT)
|
||||
{
|
||||
mSelection->EnableFrameNotification(PR_FALSE);
|
||||
mSelection->HandleKeyEvent((nsIFocusTracker *)this, aEvent, mFocusEventFrame);
|
||||
mSelection->EnableFrameNotification(PR_TRUE); //prevents secondary reset selection called since
|
||||
//we are a listener now.
|
||||
}
|
||||
frame->GetFrameForPoint(aEvent->point, &mCurrentEventFrame);
|
||||
if (nsnull != mCurrentEventFrame) {
|
||||
|
|
|
@ -870,8 +870,7 @@ TextFrame::PaintUnicodeText(nsIPresContext& aPresContext,
|
|||
CURSOR_COLOR);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
nscoord x = dx;
|
||||
|
||||
if (selectionOffset) {
|
||||
|
@ -1142,7 +1141,6 @@ TextFrame::PaintTextSlowly(nsIPresContext& aPresContext,
|
|||
shell->GetDocument(getter_AddRefs(doc));
|
||||
PRBool displaySelection;
|
||||
displaySelection = doc->GetDisplaySelection();
|
||||
displaySelection = PR_FALSE;
|
||||
|
||||
// Make enough space to transform
|
||||
PRUnichar wordBufMem[WORD_BUF_SIZE];
|
||||
|
@ -1151,7 +1149,7 @@ TextFrame::PaintTextSlowly(nsIPresContext& aPresContext,
|
|||
PRInt32* ip = indicies;
|
||||
PRUnichar* paintBuf = paintBufMem;
|
||||
if (mContentLength > TEXT_BUF_SIZE) {
|
||||
ip = new PRInt32[mContentLength];
|
||||
ip = new PRInt32[mContentLength+1];
|
||||
paintBuf = new PRUnichar[mContentLength];
|
||||
}
|
||||
nscoord width = mRect.width;
|
||||
|
@ -1162,6 +1160,7 @@ TextFrame::PaintTextSlowly(nsIPresContext& aPresContext,
|
|||
aTextStyle.mNumSpaces = PrepareUnicodeText(tx,
|
||||
displaySelection ? ip : nsnull,
|
||||
paintBuf, textLength, width);
|
||||
ip[mContentLength] = ip[mContentLength-1]+1; //must set up last one for selection beyond edge
|
||||
if (mRect.width > mComputedWidth) {
|
||||
if (0 != aTextStyle.mNumSpaces) {
|
||||
nscoord extra = mRect.width - mComputedWidth;
|
||||
|
@ -1182,18 +1181,33 @@ TextFrame::PaintTextSlowly(nsIPresContext& aPresContext,
|
|||
|
||||
PRUnichar* text = paintBuf;
|
||||
if (0 != textLength) {
|
||||
if (!displaySelection) {
|
||||
if (!displaySelection || !mSelected || mSelectionOffset > mContentLength) {
|
||||
// When there is no selection showing, use the fastest and
|
||||
// simplest rendering approach
|
||||
RenderString(aRenderingContext, aStyleContext, aTextStyle,
|
||||
text, textLength, dx, dy, width);
|
||||
}
|
||||
else {
|
||||
SelectionInfo si;
|
||||
// ComputeSelectionInfo(aRenderingContext, doc, ip, textLength, si);
|
||||
|
||||
nscoord textWidth;
|
||||
if (si.mEmptySelection) {
|
||||
if (mSelectionOffset < 0)
|
||||
mSelectionOffset = 0;
|
||||
if (mSelectionEnd < 0)
|
||||
mSelectionEnd = mContentLength;
|
||||
if (mSelectionEnd > mContentLength)
|
||||
mSelectionEnd = mContentLength;
|
||||
if (mSelectionOffset > mContentLength)
|
||||
mSelectionOffset = 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);
|
||||
|
||||
|
@ -1202,7 +1216,7 @@ TextFrame::PaintTextSlowly(nsIPresContext& aPresContext,
|
|||
#ifdef SHOW_SELECTION_CURSOR
|
||||
|
||||
GetWidth(aRenderingContext, aTextStyle,
|
||||
text, PRUint32(si.mStartOffset), textWidth);
|
||||
text, PRUint32(selectionOffset), textWidth);
|
||||
RenderSelectionCursor(aRenderingContext,
|
||||
dx + textWidth, dy, mRect.height,
|
||||
CURSOR_COLOR);
|
||||
|
@ -1211,21 +1225,21 @@ TextFrame::PaintTextSlowly(nsIPresContext& aPresContext,
|
|||
else {
|
||||
nscoord x = dx;
|
||||
|
||||
if (0 != si.mStartOffset) {
|
||||
if (selectionOffset) {
|
||||
// Render first (unselected) section
|
||||
GetWidth(aRenderingContext, aTextStyle,
|
||||
text, PRUint32(si.mStartOffset),
|
||||
text, PRUint32(selectionOffset),
|
||||
textWidth);
|
||||
RenderString(aRenderingContext, aStyleContext, aTextStyle,
|
||||
text, si.mStartOffset,
|
||||
text, selectionOffset,
|
||||
x, dy, textWidth);
|
||||
x += textWidth;
|
||||
}
|
||||
PRInt32 secondLen = si.mEndOffset - si.mStartOffset;
|
||||
PRInt32 secondLen = selectionEnd - selectionOffset;
|
||||
if (0 != secondLen) {
|
||||
// Get the width of the second (selected) section
|
||||
GetWidth(aRenderingContext, aTextStyle,
|
||||
text + si.mStartOffset,
|
||||
text + selectionOffset,
|
||||
PRUint32(secondLen), textWidth);
|
||||
|
||||
// Render second (selected) section
|
||||
|
@ -1233,21 +1247,24 @@ TextFrame::PaintTextSlowly(nsIPresContext& aPresContext,
|
|||
aRenderingContext.FillRect(x, dy, textWidth, mRect.height);
|
||||
aRenderingContext.SetColor(aTextStyle.mSelectionTextColor);
|
||||
RenderString(aRenderingContext, aStyleContext, aTextStyle,
|
||||
text + si.mStartOffset, secondLen,
|
||||
text + selectionOffset, secondLen,
|
||||
x, dy, textWidth);
|
||||
aRenderingContext.SetColor(aTextStyle.mColor->mColor);
|
||||
x += textWidth;
|
||||
}
|
||||
if (textLength != si.mEndOffset) {
|
||||
PRInt32 thirdLen = textLength - si.mEndOffset;
|
||||
if (textLength != selectionEnd) {
|
||||
PRInt32 thirdLen = textLength - selectionEnd;
|
||||
|
||||
// Render third (unselected) section
|
||||
GetWidth(aRenderingContext, aTextStyle,
|
||||
text + si.mEndOffset, PRUint32(thirdLen),
|
||||
textWidth);
|
||||
RenderString(aRenderingContext, aStyleContext, aTextStyle,
|
||||
text + si.mEndOffset,
|
||||
thirdLen, x, dy, textWidth);
|
||||
if (thirdLen > 0) //Text length is not negative or zero
|
||||
{
|
||||
GetWidth(aRenderingContext, aTextStyle,
|
||||
text + selectionOffset, PRUint32(thirdLen),
|
||||
textWidth);
|
||||
RenderString(aRenderingContext, aStyleContext, aTextStyle,
|
||||
text + selectionEnd,
|
||||
thirdLen, x, dy, textWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1298,7 +1315,6 @@ TextFrame::PaintAsciiText(nsIPresContext& aPresContext,
|
|||
displaySelection ? ip : nsnull,
|
||||
rawPaintBuf, textLength, width);
|
||||
ip[mContentLength] = ip[mContentLength-1]+1; //must set up last one for selection beyond edge
|
||||
|
||||
// Translate unicode data into ascii for rendering
|
||||
char* dst = paintBuf;
|
||||
char* end = dst + textLength;
|
||||
|
@ -1347,9 +1363,10 @@ TextFrame::PaintAsciiText(nsIPresContext& aPresContext,
|
|||
// aRenderingContext.GetWidth(text, PRUint32(si.mStartOffset), textWidth);
|
||||
|
||||
shell->RefreshCaret();
|
||||
|
||||
|
||||
#ifdef SHOW_SELECTION_CURSOR
|
||||
aRenderingContext.GetWidth(text, PRUint32(selectionOffset), textWidth);
|
||||
|
||||
RenderSelectionCursor(aRenderingContext,
|
||||
dx + textWidth, dy, mRect.height,
|
||||
CURSOR_COLOR);
|
||||
|
@ -1389,13 +1406,17 @@ TextFrame::PaintAsciiText(nsIPresContext& aPresContext,
|
|||
if (textLength != selectionEnd) {
|
||||
PRInt32 thirdLen = textLength - selectionEnd;
|
||||
|
||||
// Render third (unselected) section
|
||||
aRenderingContext.GetWidth(text + selectionEnd, PRUint32(thirdLen),
|
||||
textWidth);
|
||||
aRenderingContext.DrawString(text + selectionEnd,
|
||||
PRUint32(thirdLen), x, dy);
|
||||
PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle,
|
||||
x, dy, textWidth);
|
||||
if (thirdLen > 0) //Text length is not negative or zero
|
||||
{
|
||||
|
||||
// Render third (unselected) section
|
||||
aRenderingContext.GetWidth(text + selectionEnd, PRUint32(thirdLen),
|
||||
textWidth);
|
||||
aRenderingContext.DrawString(text + selectionEnd,
|
||||
PRUint32(thirdLen), x, dy);
|
||||
PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle,
|
||||
x, dy, textWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче