зеркало из https://github.com/mozilla/pjs.git
Bug 336381, Crash [@ nsRange::InsertNode] involving ranges in detached nodes, r=sicking,glazman,sr=bz
This commit is contained in:
Родитель
90bc7b47f2
Коммит
1c7c15de85
|
@ -139,7 +139,9 @@ public:
|
|||
/** XUL elements */
|
||||
eXUL = 1 << 9,
|
||||
/** svg elements */
|
||||
eSVG = 1 << 10
|
||||
eSVG = 1 << 10,
|
||||
/** document fragments */
|
||||
eDOCUMENT_FRAGMENT = 1 << 11
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -341,11 +343,6 @@ public:
|
|||
return mNodeInfo->NodeInfoManager()->DocumentPrincipal();
|
||||
}
|
||||
|
||||
/**
|
||||
* IsNodeOfType()? Do we need a non-QI way to tell apart documents and
|
||||
* content?
|
||||
*/
|
||||
|
||||
/**
|
||||
* Called before the capture phase of the event flow.
|
||||
* This is used to create the event target chain and implementations
|
||||
|
|
|
@ -153,6 +153,8 @@ public:
|
|||
return nsnull;
|
||||
}
|
||||
|
||||
virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
|
||||
|
||||
protected:
|
||||
nsresult Clone(nsINodeInfo *aNodeInfo, PRBool aDeep,
|
||||
nsIContent **aResult) const;
|
||||
|
@ -190,6 +192,11 @@ nsDocumentFragment::~nsDocumentFragment()
|
|||
{
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsDocumentFragment::IsNodeOfType(PRUint32 aFlags) const
|
||||
{
|
||||
return !(aFlags & ~(eCONTENT | eDOCUMENT_FRAGMENT));
|
||||
}
|
||||
|
||||
// QueryInterface implementation for nsDocumentFragment
|
||||
NS_INTERFACE_MAP_BEGIN(nsDocumentFragment)
|
||||
|
|
|
@ -944,10 +944,74 @@ nsresult nsRange::GetCommonAncestorContainer(nsIDOMNode** aCommonParent)
|
|||
return nsContentUtils::GetCommonAncestor(mStartParent, mEndParent, aCommonParent);
|
||||
}
|
||||
|
||||
nsresult nsRange::IsValidBoundary(nsIDOMNode* aNode)
|
||||
{
|
||||
if (!aNode) {
|
||||
// DOM 2 Range specification doesn't define the error code for this case,
|
||||
// but this is the best one we have.
|
||||
return NS_ERROR_DOM_RANGE_BAD_BOUNDARYPOINTS_ERR;
|
||||
}
|
||||
|
||||
PRUint16 nodeType = 0;
|
||||
aNode->GetNodeType(&nodeType);
|
||||
switch (nodeType) {
|
||||
case nsIDOMNode::DOCUMENT_TYPE_NODE:
|
||||
case nsIDOMNode::ENTITY_NODE:
|
||||
case nsIDOMNode::NOTATION_NODE:
|
||||
return NS_ERROR_DOM_RANGE_INVALID_NODE_TYPE_ERR;
|
||||
case nsIDOMNode::DOCUMENT_NODE:
|
||||
case nsIDOMNode::DOCUMENT_FRAGMENT_NODE:
|
||||
case nsIDOMNode::ATTRIBUTE_NODE:
|
||||
return NS_OK;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
|
||||
if (!content) {
|
||||
// DOM 2 Range specification doesn't define the error code for this case,
|
||||
// but this is the best one we have.
|
||||
return NS_ERROR_DOM_RANGE_BAD_BOUNDARYPOINTS_ERR;
|
||||
}
|
||||
|
||||
// Elements etc. must be in document or in document fragment,
|
||||
// text nodes in document, in document fragment or in attribute.
|
||||
if (content->IsInDoc()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsINode* parent = content->GetNodeParent();
|
||||
if (parent) {
|
||||
if (parent->IsNodeOfType(nsINode::eATTRIBUTE)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
do {
|
||||
if (parent->IsNodeOfType(nsINode::eDOCUMENT_FRAGMENT)) {
|
||||
return NS_OK;
|
||||
}
|
||||
parent = parent->GetNodeParent();
|
||||
} while(parent);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_smaug
|
||||
nsAutoString name;
|
||||
content->Tag()->ToString(name);
|
||||
printf("nsRange::IsValidBoundary: node is not a valid boundary point [%s]\n",
|
||||
NS_ConvertUTF16toUTF8(name).get());
|
||||
#endif
|
||||
|
||||
// DOM 2 Range specification doesn't define the error code for this case,
|
||||
// but this is the best one we have.
|
||||
return NS_ERROR_DOM_RANGE_BAD_BOUNDARYPOINTS_ERR;
|
||||
}
|
||||
|
||||
nsresult nsRange::SetStart(nsIDOMNode* aParent, PRInt32 aOffset)
|
||||
{
|
||||
VALIDATE_ACCESS(aParent);
|
||||
|
||||
nsresult rv = IsValidBoundary(aParent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 len = GetNodeLength(aParent);
|
||||
if ( (aOffset < 0) || (len < 0) || (aOffset > len) )
|
||||
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
||||
|
@ -996,7 +1060,9 @@ nsresult nsRange::SetStartAfter(nsIDOMNode* aSibling)
|
|||
nsresult nsRange::SetEnd(nsIDOMNode* aParent, PRInt32 aOffset)
|
||||
{
|
||||
VALIDATE_ACCESS(aParent);
|
||||
|
||||
nsresult rv = IsValidBoundary(aParent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt32 len = GetNodeLength(aParent);
|
||||
if ( (aOffset < 0) || (len < 0) || (aOffset > len) )
|
||||
return NS_ERROR_DOM_INDEX_SIZE_ERR;
|
||||
|
|
|
@ -215,6 +215,8 @@ protected:
|
|||
nsresult ContentOwnsUs(nsIDOMNode* domNode);
|
||||
|
||||
nsresult GetIsPositioned(PRBool* aIsPositioned);
|
||||
|
||||
nsresult IsValidBoundary(nsIDOMNode* aNode);
|
||||
};
|
||||
|
||||
// Make a new nsIDOMRange object
|
||||
|
|
|
@ -1574,20 +1574,22 @@ nsEditor::ReplaceContainer(nsIDOMNode *inNode,
|
|||
// (Note: A nsAutoSelectionReset object must be created
|
||||
// before calling this to initialize mRangeUpdater)
|
||||
nsAutoReplaceContainerSelNotify selStateNotify(mRangeUpdater, inNode, *outNode);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
PRBool bHasMoreChildren;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
while (bHasMoreChildren)
|
||||
{
|
||||
inNode->GetFirstChild(getter_AddRefs(child));
|
||||
res = DeleteNode(child);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = InsertNode(child, *outNode, -1);
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsAutoTxnsConserveSelection conserveSelection(this);
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
PRBool bHasMoreChildren;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
}
|
||||
while (bHasMoreChildren)
|
||||
{
|
||||
inNode->GetFirstChild(getter_AddRefs(child));
|
||||
res = DeleteNode(child);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
res = InsertNode(child, *outNode, -1);
|
||||
if (NS_FAILED(res)) return res;
|
||||
inNode->HasChildNodes(&bHasMoreChildren);
|
||||
}
|
||||
}
|
||||
// insert new container into tree
|
||||
res = InsertNode( *outNode, parent, offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
@ -1681,9 +1683,13 @@ nsEditor::InsertContainerAbove( nsIDOMNode *inNode,
|
|||
// put inNode in new parent, outNode
|
||||
res = DeleteNode(inNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = InsertNode(inNode, *outNode, 0);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
|
||||
{
|
||||
nsAutoTxnsConserveSelection conserveSelection(this);
|
||||
res = InsertNode(inNode, *outNode, 0);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
// put new parent in doc
|
||||
return InsertNode(*outNode, parent, offset);
|
||||
}
|
||||
|
|
|
@ -988,6 +988,10 @@ nsTextControlFrame::nsTextControlFrame(nsIPresShell* aShell, nsStyleContext* aCo
|
|||
mNotifyOnInput = PR_TRUE;
|
||||
mScrollableView = nsnull;
|
||||
mDidPreDestroy = PR_FALSE;
|
||||
|
||||
#ifdef DEBUG
|
||||
mCreateFrameForCalled = PR_FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsTextControlFrame::~nsTextControlFrame()
|
||||
|
@ -1364,11 +1368,201 @@ void nsTextControlFrame::PostCreateFrames() {
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsTextControlFrame::CreateFrameFor(nsPresContext* aPresContext,
|
||||
nsIContent * aContent,
|
||||
nsIFrame** aFrame)
|
||||
nsIContent* aContent,
|
||||
nsIFrame** aFrame)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
NS_ASSERTION(!mCreateFrameForCalled, "CreateFrameFor called more than once!");
|
||||
mCreateFrameForCalled = PR_TRUE;
|
||||
#endif
|
||||
|
||||
// Note, we must set aFrame to nsnull.
|
||||
*aFrame = nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsIPresShell *shell = aPresContext->GetPresShell();
|
||||
if (!shell)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domdoc = do_QueryInterface(shell->GetDocument());
|
||||
if (!domdoc)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Don't create any frames here, but just setup the editor.
|
||||
// This way DOM Ranges (which editor uses) work properly since the anonymous
|
||||
// content is bound to tree after CreateAnonymousContent but before this
|
||||
// method.
|
||||
nsresult rv = NS_OK;
|
||||
mEditor = do_CreateInstance(kTextEditorCID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (!mEditor)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// Create selection
|
||||
|
||||
mFrameSel = do_CreateInstance(kFrameSelectionCID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Create a SelectionController
|
||||
|
||||
mSelCon = NS_STATIC_CAST(nsISelectionController*,
|
||||
new nsTextInputSelectionImpl(mFrameSel, shell, aContent));
|
||||
if (!mSelCon)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
mTextListener = new nsTextInputListener();
|
||||
if (!mTextListener)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(mTextListener);
|
||||
|
||||
mTextListener->SetFrame(this);
|
||||
mSelCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
|
||||
|
||||
// Setup the editor flags
|
||||
|
||||
PRUint32 editorFlags = 0;
|
||||
if (IsPlainTextControl())
|
||||
editorFlags |= nsIPlaintextEditor::eEditorPlaintextMask;
|
||||
if (IsSingleLineTextControl())
|
||||
editorFlags |= nsIPlaintextEditor::eEditorSingleLineMask;
|
||||
if (IsPasswordTextControl())
|
||||
editorFlags |= nsIPlaintextEditor::eEditorPasswordMask;
|
||||
|
||||
// All gfxtextcontrolframe2's are widgets
|
||||
editorFlags |= nsIPlaintextEditor::eEditorWidgetMask;
|
||||
|
||||
// Use async reflow and painting for text widgets to improve
|
||||
// performance.
|
||||
|
||||
// XXX: Using editor async updates exposes bugs 158782, 151882,
|
||||
// and 165130, so we're disabling it for now, until they
|
||||
// can be addressed.
|
||||
// editorFlags |= nsIPlaintextEditor::eEditorUseAsyncUpdatesMask;
|
||||
|
||||
// Now initialize the editor.
|
||||
//
|
||||
// NOTE: Conversion of '\n' to <BR> happens inside the
|
||||
// editor's Init() call.
|
||||
|
||||
rv = mEditor->Init(domdoc, shell, aContent, mSelCon, editorFlags);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Initialize the controller for the editor
|
||||
|
||||
if (!SuppressEventHandlers(aPresContext)) {
|
||||
nsCOMPtr<nsIControllers> controllers;
|
||||
nsCOMPtr<nsIDOMNSHTMLInputElement> inputElement =
|
||||
do_QueryInterface(mContent);
|
||||
if (inputElement) {
|
||||
rv = inputElement->GetControllers(getter_AddRefs(controllers));
|
||||
} else {
|
||||
nsCOMPtr<nsIDOMNSHTMLTextAreaElement> textAreaElement =
|
||||
do_QueryInterface(mContent);
|
||||
|
||||
if (!textAreaElement)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
rv = textAreaElement->GetControllers(getter_AddRefs(controllers));
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (controllers) {
|
||||
PRUint32 numControllers;
|
||||
PRBool found = PR_FALSE;
|
||||
rv = controllers->GetControllerCount(&numControllers);
|
||||
for (PRUint32 i = 0; i < numControllers; i ++) {
|
||||
nsCOMPtr<nsIController> controller;
|
||||
rv = controllers->GetControllerAt(i, getter_AddRefs(controller));
|
||||
if (NS_SUCCEEDED(rv) && controller) {
|
||||
nsCOMPtr<nsIControllerContext> editController =
|
||||
do_QueryInterface(controller);
|
||||
if (editController) {
|
||||
editController->SetCommandContext(mEditor);
|
||||
found = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the plaintext editor
|
||||
nsCOMPtr<nsIPlaintextEditor> textEditor(do_QueryInterface(mEditor));
|
||||
if (textEditor) {
|
||||
// Set up wrapping
|
||||
if (IsTextArea()) {
|
||||
// wrap=off means -1 for wrap width no matter what cols is
|
||||
nsFormControlHelper::nsHTMLTextWrap wrapProp;
|
||||
nsFormControlHelper::GetWrapPropertyEnum(mContent, wrapProp);
|
||||
if (wrapProp == nsFormControlHelper::eHTMLTextWrap_Off) {
|
||||
// do not wrap when wrap=off
|
||||
textEditor->SetWrapWidth(-1);
|
||||
} else {
|
||||
// Set wrapping normally otherwise
|
||||
textEditor->SetWrapWidth(GetCols());
|
||||
}
|
||||
} else {
|
||||
// Never wrap non-textareas
|
||||
textEditor->SetWrapWidth(-1);
|
||||
}
|
||||
|
||||
|
||||
// Set max text field length
|
||||
PRInt32 maxLength;
|
||||
if (GetMaxLength(&maxLength)) {
|
||||
textEditor->SetMaxTextLength(maxLength);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the caret and make it a selection listener.
|
||||
|
||||
nsCOMPtr<nsISelection> domSelection;
|
||||
if (NS_SUCCEEDED(mSelCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
|
||||
getter_AddRefs(domSelection))) &&
|
||||
domSelection) {
|
||||
nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(domSelection));
|
||||
nsCOMPtr<nsICaret> caret;
|
||||
nsCOMPtr<nsISelectionListener> listener;
|
||||
if (NS_SUCCEEDED(shell->GetCaret(getter_AddRefs(caret))) && caret) {
|
||||
listener = do_QueryInterface(caret);
|
||||
if (listener) {
|
||||
selPriv->AddSelectionListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
selPriv->AddSelectionListener(NS_STATIC_CAST(nsISelectionListener*,
|
||||
mTextListener));
|
||||
}
|
||||
|
||||
if (mContent) {
|
||||
rv = mEditor->GetFlags(&editorFlags);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Check if the readonly attribute is set.
|
||||
|
||||
if (mContent->HasAttr(kNameSpaceID_None, nsHTMLAtoms::readonly))
|
||||
editorFlags |= nsIPlaintextEditor::eEditorReadonlyMask;
|
||||
|
||||
// Check if the disabled attribute is set.
|
||||
|
||||
if (mContent->HasAttr(kNameSpaceID_None, nsHTMLAtoms::disabled))
|
||||
editorFlags |= nsIPlaintextEditor::eEditorDisabledMask;
|
||||
|
||||
// Disable the selection if necessary.
|
||||
|
||||
if (editorFlags & nsIPlaintextEditor::eEditorDisabledMask)
|
||||
mSelCon->SetDisplaySelection(nsISelectionController::SELECTION_OFF);
|
||||
|
||||
mEditor->SetFlags(editorFlags);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsTextControlFrame::SetEnableRealTimeSpell
|
||||
|
@ -1565,18 +1759,11 @@ nsTextControlFrame::CreateAnonymousContent(nsPresContext* aPresContext,
|
|||
if (!doc)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMDocument> domdoc = do_QueryInterface(doc, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (!domdoc)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Now create a DIV and add it to the anonymous content child list.
|
||||
nsCOMPtr<nsINodeInfo> nodeInfo;
|
||||
rv = doc->NodeInfoManager()->GetNodeInfo(nsHTMLAtoms::div, nsnull,
|
||||
kNameSpaceID_XHTML,
|
||||
getter_AddRefs(nodeInfo));
|
||||
nsresult rv = doc->NodeInfoManager()->GetNodeInfo(nsHTMLAtoms::div, nsnull,
|
||||
kNameSpaceID_XHTML,
|
||||
getter_AddRefs(nodeInfo));
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
@ -1620,189 +1807,7 @@ nsTextControlFrame::CreateAnonymousContent(nsPresContext* aPresContext,
|
|||
return rv;
|
||||
|
||||
// rv = divContent->SetAttr(kNameSpaceID_None,nsXULAtoms::debug, NS_LITERAL_STRING("true"), PR_FALSE);
|
||||
rv = aChildList.AppendElement(divContent);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Create an editor
|
||||
|
||||
mEditor = do_CreateInstance(kTextEditorCID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (!mEditor)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// Create selection
|
||||
|
||||
mFrameSel = do_CreateInstance(kFrameSelectionCID, &rv);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Create a SelectionController
|
||||
|
||||
mSelCon = NS_STATIC_CAST(nsISelectionController*,
|
||||
new nsTextInputSelectionImpl(mFrameSel, shell, divContent));
|
||||
if (!mSelCon)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
mTextListener = new nsTextInputListener();
|
||||
if (!mTextListener)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(mTextListener);
|
||||
|
||||
mTextListener->SetFrame(this);
|
||||
mSelCon->SetDisplaySelection(nsISelectionController::SELECTION_ON);
|
||||
|
||||
// Setup the editor flags
|
||||
|
||||
PRUint32 editorFlags = 0;
|
||||
if (IsPlainTextControl())
|
||||
editorFlags |= nsIPlaintextEditor::eEditorPlaintextMask;
|
||||
if (IsSingleLineTextControl())
|
||||
editorFlags |= nsIPlaintextEditor::eEditorSingleLineMask;
|
||||
if (IsPasswordTextControl())
|
||||
editorFlags |= nsIPlaintextEditor::eEditorPasswordMask;
|
||||
|
||||
// All gfxtextcontrolframe2's are widgets
|
||||
editorFlags |= nsIPlaintextEditor::eEditorWidgetMask;
|
||||
|
||||
// Use async reflow and painting for text widgets to improve
|
||||
// performance.
|
||||
|
||||
// XXX: Using editor async updates exposes bugs 158782, 151882,
|
||||
// and 165130, so we're disabling it for now, until they
|
||||
// can be addressed.
|
||||
// editorFlags |= nsIPlaintextEditor::eEditorUseAsyncUpdatesMask;
|
||||
|
||||
// Now initialize the editor.
|
||||
//
|
||||
// NOTE: Conversion of '\n' to <BR> happens inside the
|
||||
// editor's Init() call.
|
||||
|
||||
rv = mEditor->Init(domdoc, shell, divContent, mSelCon, editorFlags);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Initialize the controller for the editor
|
||||
|
||||
if (!SuppressEventHandlers(aPresContext))
|
||||
{
|
||||
nsCOMPtr<nsIControllers> controllers;
|
||||
nsCOMPtr<nsIDOMNSHTMLInputElement> inputElement = do_QueryInterface(mContent);
|
||||
if (inputElement)
|
||||
rv = inputElement->GetControllers(getter_AddRefs(controllers));
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIDOMNSHTMLTextAreaElement> textAreaElement = do_QueryInterface(mContent);
|
||||
|
||||
if (!textAreaElement)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
rv = textAreaElement->GetControllers(getter_AddRefs(controllers));
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (controllers)
|
||||
{
|
||||
PRUint32 numControllers;
|
||||
PRBool found = PR_FALSE;
|
||||
rv = controllers->GetControllerCount(&numControllers);
|
||||
for (PRUint32 i = 0; i < numControllers; i ++)
|
||||
{
|
||||
nsCOMPtr<nsIController> controller;
|
||||
rv = controllers->GetControllerAt(i, getter_AddRefs(controller));
|
||||
if (NS_SUCCEEDED(rv) && controller)
|
||||
{
|
||||
nsCOMPtr<nsIControllerContext> editController = do_QueryInterface(controller);
|
||||
if (editController)
|
||||
{
|
||||
editController->SetCommandContext(mEditor);
|
||||
found = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the plaintext editor
|
||||
nsCOMPtr<nsIPlaintextEditor> textEditor(do_QueryInterface(mEditor));
|
||||
if (textEditor) {
|
||||
// Set up wrapping
|
||||
if (IsTextArea()) {
|
||||
// wrap=off means -1 for wrap width no matter what cols is
|
||||
nsFormControlHelper::nsHTMLTextWrap wrapProp;
|
||||
nsFormControlHelper::GetWrapPropertyEnum(mContent, wrapProp);
|
||||
if (wrapProp == nsFormControlHelper::eHTMLTextWrap_Off) {
|
||||
// do not wrap when wrap=off
|
||||
textEditor->SetWrapWidth(-1);
|
||||
} else {
|
||||
// Set wrapping normally otherwise
|
||||
textEditor->SetWrapWidth(GetCols());
|
||||
}
|
||||
} else {
|
||||
// Never wrap non-textareas
|
||||
textEditor->SetWrapWidth(-1);
|
||||
}
|
||||
|
||||
|
||||
// Set max text field length
|
||||
PRInt32 maxLength;
|
||||
if (GetMaxLength(&maxLength)) {
|
||||
textEditor->SetMaxTextLength(maxLength);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the caret and make it a selection listener.
|
||||
|
||||
nsCOMPtr<nsISelection> domSelection;
|
||||
if (NS_SUCCEEDED(mSelCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSelection))) && domSelection)
|
||||
{
|
||||
nsCOMPtr<nsISelectionPrivate> selPriv(do_QueryInterface(domSelection));
|
||||
nsCOMPtr<nsICaret> caret;
|
||||
nsCOMPtr<nsISelectionListener> listener;
|
||||
if (NS_SUCCEEDED(shell->GetCaret(getter_AddRefs(caret))) && caret)
|
||||
{
|
||||
listener = do_QueryInterface(caret);
|
||||
if (listener)
|
||||
{
|
||||
selPriv->AddSelectionListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
selPriv->AddSelectionListener(NS_STATIC_CAST(nsISelectionListener *, mTextListener));
|
||||
}
|
||||
|
||||
if (mContent)
|
||||
{
|
||||
rv = mEditor->GetFlags(&editorFlags);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
// Check if the readonly attribute is set.
|
||||
|
||||
if (mContent->HasAttr(kNameSpaceID_None, nsHTMLAtoms::readonly))
|
||||
editorFlags |= nsIPlaintextEditor::eEditorReadonlyMask;
|
||||
|
||||
// Check if the disabled attribute is set.
|
||||
|
||||
if (mContent->HasAttr(kNameSpaceID_None, nsHTMLAtoms::disabled))
|
||||
editorFlags |= nsIPlaintextEditor::eEditorDisabledMask;
|
||||
|
||||
// Disable the selection if necessary.
|
||||
|
||||
if (editorFlags & nsIPlaintextEditor::eEditorDisabledMask)
|
||||
mSelCon->SetDisplaySelection(nsISelectionController::SELECTION_OFF);
|
||||
|
||||
mEditor->SetFlags(editorFlags);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return aChildList.AppendElement(divContent);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -288,6 +288,10 @@ private:
|
|||
// XXX This seems unsafe; what's keeping it around?
|
||||
nsIScrollableView *mScrollableView;
|
||||
nsString mFocusedValue;
|
||||
|
||||
#ifdef DEBUG
|
||||
PRBool mCreateFrameForCalled;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче