Fix for bug 335856 (Can't easily put caret in this designmode iframe testcase (caret doesn't show up)), also fixes bug 393568 (blocking1.9+) and bug 386872. r/sr=jst.

This commit is contained in:
peterv@propagandism.org 2007-10-03 05:16:50 -07:00
parent 4a67feba15
commit f6c6606714
5 changed files with 85 additions and 35 deletions

View File

@ -217,7 +217,8 @@ nsEditor::~nsEditor()
NS_IF_RELEASE(mViewManager);
}
NS_IMPL_ISUPPORTS4(nsEditor, nsIEditor, nsIEditorIMESupport, nsISupportsWeakReference, nsIPhonetic)
NS_IMPL_ISUPPORTS5(nsEditor, nsIEditor, nsIEditorIMESupport,
nsISupportsWeakReference, nsIPhonetic, nsIMutationObserver)
#ifdef XP_MAC
#pragma mark -
@ -244,6 +245,9 @@ nsEditor::Init(nsIDOMDocument *aDoc, nsIPresShell* aPresShell, nsIContent *aRoot
if (aRoot)
mRootElement = do_QueryInterface(aRoot);
nsCOMPtr<nsINode> document = do_QueryInterface(aDoc);
document->AddMutationObserver(this);
// Set up the DTD
// XXX - in the long run we want to get this from the document, but there
// is no way to do that right now. So we leave it null here and set
@ -519,6 +523,10 @@ nsEditor::PreDestroy()
// tell our listeners that the doc is going away
NotifyDocumentListeners(eDocumentToBeDestroyed);
nsCOMPtr<nsINode> document = do_QueryReferent(mDocWeak);
if (document)
document->RemoveMutationObserver(this);
// Unregister event listeners
RemoveEventListeners();
mActionListeners.Clear();
@ -2280,6 +2288,45 @@ nsEditor::GetQueryCaretRect(nsQueryCaretRectEventReply* aReply)
/* Non-interface, public methods */
void
nsEditor::ContentAppended(nsIDocument *aDocument, nsIContent* aContainer,
PRInt32 aNewIndexInContainer)
{
ContentInserted(aDocument, aContainer, nsnull, aNewIndexInContainer);
}
void
nsEditor::ContentInserted(nsIDocument *aDocument, nsIContent* aContainer,
nsIContent* aChild, PRInt32 aIndexInContainer)
{
// XXX If we need aChild then nsEditor::ContentAppended should start passing
// in the child.
if (!mRootElement)
{
// Need to remove the event listeners first because BeginningOfDocument
// could set a new root (and event target) and we won't be able to remove
// them from the old event target then.
RemoveEventListeners();
BeginningOfDocument();
InstallEventListeners();
SyncRealTimeSpell();
}
}
void
nsEditor::ContentRemoved(nsIDocument *aDocument, nsIContent* aContainer,
nsIContent* aChild, PRInt32 aIndexInContainer)
{
nsCOMPtr<nsIDOMHTMLElement> elem = do_QueryInterface(aChild);
if (elem == mRootElement)
{
RemoveEventListeners();
mRootElement = nsnull;
mEventTarget = nsnull;
InstallEventListeners();
}
}
NS_IMETHODIMP
nsEditor::GetRootElement(nsIDOMElement **aRootElement)
{

View File

@ -64,6 +64,7 @@
#include "nsIEditorSpellCheck.h"
#include "nsIInlineSpellChecker.h"
#include "nsPIDOMEventTarget.h"
#include "nsStubMutationObserver.h"
class nsIDOMCharacterData;
class nsIDOMRange;
@ -97,7 +98,8 @@ class nsIDOMEventTarget;
class nsEditor : public nsIEditor,
public nsIEditorIMESupport,
public nsSupportsWeakReference,
public nsIPhonetic
public nsIPhonetic,
public nsStubMutationObserver
{
public:
@ -151,6 +153,9 @@ public:
// nsIPhonetic
NS_DECL_NSIPHONETIC
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
public:

View File

@ -1123,7 +1123,7 @@ nsTextEditorFocusListener::Focus(nsIDOMEvent* aEvent)
nsCOMPtr<nsISelectionController> selCon;
mEditor->GetSelectionController(getter_AddRefs(selCon));
if (selCon && editableRoot)
if (selCon)
{
nsCOMPtr<nsISelection> selection;
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
@ -1150,6 +1150,14 @@ nsTextEditorFocusListener::Focus(nsIDOMEvent* aEvent)
{
selectionPrivate->SetAncestorLimiter(editableRoot);
}
if (!editableRoot) {
PRInt32 rangeCount;
selection->GetRangeCount(&rangeCount);
if (rangeCount == 0) {
mEditor->BeginningOfDocument();
}
}
}
}

View File

@ -134,7 +134,7 @@ nsTextEditRules::Init(nsPlaintextEditor *aEditor, PRUint32 aFlags)
NS_ASSERTION(selection, "editor cannot get selection");
// Cache our body node, if available.
GetBody();
nsIDOMNode *body = mEditor->GetRoot();
// Put in a magic br if needed. This method handles null selection,
// which should never happen anyway
@ -148,15 +148,15 @@ nsTextEditRules::Init(nsPlaintextEditor *aEditor, PRUint32 aFlags)
if (NS_FAILED(res)) return res;
}
if (mBody)
if (body)
{
// create a range that is the entire body contents
nsCOMPtr<nsIDOMRange> wholeDoc =
do_CreateInstance("@mozilla.org/content/range;1");
if (!wholeDoc) return NS_ERROR_NULL_POINTER;
wholeDoc->SetStart(mBody,0);
wholeDoc->SetStart(body,0);
nsCOMPtr<nsIDOMNodeList> list;
res = mBody->GetChildNodes(getter_AddRefs(list));
res = body->GetChildNodes(getter_AddRefs(list));
if (NS_FAILED(res)) return res;
if (!list) return NS_ERROR_FAILURE;
@ -164,7 +164,7 @@ nsTextEditRules::Init(nsPlaintextEditor *aEditor, PRUint32 aFlags)
res = list->GetLength(&listCount);
if (NS_FAILED(res)) return res;
res = wholeDoc->SetEnd(mBody, listCount);
res = wholeDoc->SetEnd(body, listCount);
if (NS_FAILED(res)) return res;
// replace newlines in that range with breaks
@ -992,9 +992,11 @@ nsTextEditRules::WillDeleteSelection(nsISelection *aSelection,
// make sure it is not last node in editfield. If it is, cancel deletion.
if (nextNode && (aCollapsedAction == nsIEditor::eNext) && nsTextEditUtils::IsBreak(nextNode))
{
if (!GetBody()) return NS_ERROR_NULL_POINTER;
nsIDOMNode *body = mEditor->GetRoot();
if (!body)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> lastChild;
res = mBody->GetLastChild(getter_AddRefs(lastChild));
res = body->GetLastChild(getter_AddRefs(lastChild));
if (lastChild == nextNode)
{
*aCancel = PR_TRUE;
@ -1251,9 +1253,11 @@ nsTextEditRules::CreateTrailingBRIfNeeded()
// but only if we aren't a single line edit field
if (mFlags & nsIPlaintextEditor::eEditorSingleLineMask)
return NS_OK;
if (!GetBody()) return NS_ERROR_NULL_POINTER;
nsIDOMNode *body = mEditor->GetRoot();
if (!body)
return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMNode> lastChild;
nsresult res = mBody->GetLastChild(getter_AddRefs(lastChild));
nsresult res = body->GetLastChild(getter_AddRefs(lastChild));
// assuming CreateBogusNodeIfNeeded() has been called first
if (NS_FAILED(res)) return res;
if (!lastChild) return NS_ERROR_NULL_POINTER;
@ -1262,10 +1266,10 @@ nsTextEditRules::CreateTrailingBRIfNeeded()
{
nsAutoTxnsConserveSelection dontSpazMySelection(mEditor);
PRUint32 rootLen;
res = mEditor->GetLengthOfDOMNode(mBody, rootLen);
res = mEditor->GetLengthOfDOMNode(body, rootLen);
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMNode> unused;
res = CreateMozBR(mBody, rootLen, address_of(unused));
res = CreateMozBR(body, rootLen, address_of(unused));
}
return res;
}
@ -1279,8 +1283,9 @@ nsTextEditRules::CreateBogusNodeIfNeeded(nsISelection *aSelection)
// tell rules system to not do any post-processing
nsAutoRules beginRulesSniffing(mEditor, nsEditor::kOpIgnore, nsIEditor::eNone);
if (!GetBody())
nsIDOMNode* body = mEditor->GetRoot();
if (!body)
{
// we don't even have a body yet, don't insert any bogus nodes at
// this point.
@ -1293,11 +1298,11 @@ nsTextEditRules::CreateBogusNodeIfNeeded(nsISelection *aSelection)
// if no editable content is found, insert the bogus node
PRBool needsBogusContent=PR_TRUE;
nsCOMPtr<nsIDOMNode> bodyChild;
nsresult res = mBody->GetFirstChild(getter_AddRefs(bodyChild));
nsresult res = body->GetFirstChild(getter_AddRefs(bodyChild));
while ((NS_SUCCEEDED(res)) && bodyChild)
{
if (mEditor->IsMozEditorBogusNode(bodyChild) ||
!mEditor->IsEditable(mBody) ||
!mEditor->IsEditable(body) ||
mEditor->IsEditable(bodyChild))
{
needsBogusContent = PR_FALSE;
@ -1324,11 +1329,11 @@ nsTextEditRules::CreateBogusNodeIfNeeded(nsISelection *aSelection)
kMOZEditorBogusNodeValue );
// put the node in the document
res = mEditor->InsertNode(mBogusNode, mBody, 0);
res = mEditor->InsertNode(mBogusNode, body, 0);
if (NS_FAILED(res)) return res;
// set selection
aSelection->Collapse(mBody, 0);
aSelection->Collapse(body, 0);
}
return res;
}
@ -1466,15 +1471,3 @@ nsTextEditRules::CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<ns
}
return res;
}
nsIDOMNode *
nsTextEditRules::GetBody()
{
if (!mBody)
{
// remember our body node
mBody = mEditor->GetRoot();
}
return mBody;
}

View File

@ -197,15 +197,12 @@ protected:
nsIEditor::EDirection aAction,
PRBool *aCancel);
nsIDOMNode *GetBody();
// data members
nsPlaintextEditor *mEditor; // note that we do not refcount the editor
nsString mPasswordText; // a buffer we use to store the real value of password editors
nsString mPasswordIMEText; // a buffer we use to track the IME composition string
PRUint32 mPasswordIMEIndex;
nsCOMPtr<nsIDOMNode> mBogusNode; // magic node acts as placeholder in empty doc
nsCOMPtr<nsIDOMNode> mBody; // cached root node
nsCOMPtr<nsIDOMNode> mCachedSelectionNode; // cached selected node
PRInt32 mCachedSelectionOffset; // cached selected offset
PRUint32 mFlags;