1999-03-01 22:54:47 +03:00
|
|
|
/* -*- Mode: C++ tab-width: 2 indent-tabs-mode: nil c-basic-offset: 2 -*-
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Netscape Public License
|
|
|
|
* Version 1.0 (the "NPL") you may not use this file except in
|
|
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
|
|
* http://www.mozilla.org/NPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* NPL.
|
|
|
|
*
|
|
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
|
|
* Communications Corporation. Portions created by Netscape are
|
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
|
|
* Reserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "nsTextEditor.h"
|
|
|
|
#include "nsHTMLEditor.h"
|
1999-03-29 12:02:05 +04:00
|
|
|
#include "nsHTMLEditRules.h"
|
1999-03-01 22:54:47 +03:00
|
|
|
#include "nsEditorEventListeners.h"
|
1999-05-07 23:23:17 +04:00
|
|
|
#include "nsInsertHTMLTxn.h"
|
1999-04-08 04:46:10 +04:00
|
|
|
#include "nsIDOMNodeList.h"
|
1999-05-06 03:27:17 +04:00
|
|
|
#include "nsIDOMNSRange.h"
|
1999-03-01 22:54:47 +03:00
|
|
|
#include "nsIDOMDocument.h"
|
1999-06-08 04:02:25 +04:00
|
|
|
#include "nsIDocument.h"
|
1999-03-01 22:54:47 +03:00
|
|
|
#include "nsIDOMEventReceiver.h"
|
|
|
|
#include "nsIDOMKeyListener.h"
|
|
|
|
#include "nsIDOMMouseListener.h"
|
1999-03-29 12:02:05 +04:00
|
|
|
#include "nsIDOMSelection.h"
|
1999-03-30 02:01:26 +04:00
|
|
|
#include "nsIDOMHTMLAnchorElement.h"
|
|
|
|
#include "nsIDOMHTMLImageElement.h"
|
1999-04-20 21:47:12 +04:00
|
|
|
#include "nsIEnumerator.h"
|
1999-04-21 22:53:55 +04:00
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsIContentIterator.h"
|
1999-03-01 22:54:47 +03:00
|
|
|
#include "nsEditorCID.h"
|
1999-04-21 22:53:55 +04:00
|
|
|
#include "nsLayoutCID.h"
|
|
|
|
#include "nsIDOMRange.h"
|
1999-05-01 02:40:18 +04:00
|
|
|
#include "nsISupportsArray.h"
|
|
|
|
#include "nsVoidArray.h"
|
1999-05-14 00:59:08 +04:00
|
|
|
#include "nsFileSpec.h"
|
1999-03-09 12:44:27 +03:00
|
|
|
#include "nsIComponentManager.h"
|
1999-03-01 22:54:47 +03:00
|
|
|
#include "nsIServiceManager.h"
|
1999-05-27 01:40:51 +04:00
|
|
|
#include "nsIFileWidget.h" // for GetLocalFileURL stuff
|
|
|
|
#include "nsWidgetsCID.h"
|
1999-06-07 23:32:36 +04:00
|
|
|
#include "nsIDocumentEncoder.h"
|
1999-06-10 04:35:02 +04:00
|
|
|
#include "nsIPresShell.h"
|
1999-03-01 22:54:47 +03:00
|
|
|
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
#include "nsJSEditorLog.h"
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-05-07 23:23:17 +04:00
|
|
|
static NS_DEFINE_IID(kInsertHTMLTxnIID, NS_INSERT_HTML_TXN_IID);
|
|
|
|
|
1999-03-01 22:54:47 +03:00
|
|
|
static NS_DEFINE_CID(kEditorCID, NS_EDITOR_CID);
|
|
|
|
static NS_DEFINE_CID(kTextEditorCID, NS_TEXTEDITOR_CID);
|
|
|
|
static NS_DEFINE_CID(kHTMLEditorCID, NS_HTMLEDITOR_CID);
|
1999-04-21 22:53:55 +04:00
|
|
|
static NS_DEFINE_CID(kCContentIteratorCID, NS_CONTENTITERATOR_CID);
|
1999-06-08 10:04:51 +04:00
|
|
|
static NS_DEFINE_CID(kCRangeCID, NS_RANGE_CID);
|
|
|
|
static NS_DEFINE_IID(kFileWidgetCID, NS_FILEWIDGET_CID);
|
1999-06-07 23:32:36 +04:00
|
|
|
static NS_DEFINE_CID(kHTMLEncoderCID, NS_HTML_ENCODER_CID);
|
1999-06-10 04:35:02 +04:00
|
|
|
static NS_DEFINE_CID(kTextEncoderCID, NS_TEXT_ENCODER_CID);
|
1999-03-01 22:54:47 +03:00
|
|
|
|
1999-04-20 21:47:12 +04:00
|
|
|
#ifdef NS_DEBUG
|
1999-05-05 08:51:54 +04:00
|
|
|
static PRBool gNoisy = PR_FALSE;
|
1999-04-20 21:47:12 +04:00
|
|
|
#else
|
|
|
|
static const PRBool gNoisy = PR_FALSE;
|
|
|
|
#endif
|
1999-03-01 22:54:47 +03:00
|
|
|
|
1999-06-10 04:35:02 +04:00
|
|
|
|
|
|
|
|
1999-03-01 22:54:47 +03:00
|
|
|
nsHTMLEditor::nsHTMLEditor()
|
|
|
|
{
|
1999-03-06 00:05:35 +03:00
|
|
|
// Done in nsEditor
|
|
|
|
// NS_INIT_REFCNT();
|
1999-06-10 04:35:02 +04:00
|
|
|
}
|
1999-03-01 22:54:47 +03:00
|
|
|
|
|
|
|
nsHTMLEditor::~nsHTMLEditor()
|
|
|
|
{
|
|
|
|
//the autopointers will clear themselves up.
|
1999-03-06 00:05:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Adds appropriate AddRef, Release, and QueryInterface methods for derived class
|
|
|
|
//NS_IMPL_ISUPPORTS_INHERITED(nsHTMLEditor, nsTextEditor, nsIHTMLEditor)
|
|
|
|
|
|
|
|
//NS_IMPL_ADDREF_INHERITED(Class, Super)
|
|
|
|
NS_IMETHODIMP_(nsrefcnt) nsHTMLEditor::AddRef(void)
|
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::AddRef();
|
1999-03-06 00:05:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//NS_IMPL_RELEASE_INHERITED(Class, Super)
|
|
|
|
NS_IMETHODIMP_(nsrefcnt) nsHTMLEditor::Release(void)
|
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::Release();
|
1999-03-06 00:05:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//NS_IMPL_QUERY_INTERFACE_INHERITED(Class, Super, AdditionalInterface)
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|
|
|
{
|
|
|
|
if (!aInstancePtr) return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
if (aIID.Equals(nsIHTMLEditor::GetIID())) {
|
|
|
|
*aInstancePtr = NS_STATIC_CAST(nsIHTMLEditor*, this);
|
|
|
|
NS_ADDREF_THIS();
|
|
|
|
return NS_OK;
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::QueryInterface(aIID, aInstancePtr);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-06 00:05:35 +03:00
|
|
|
|
Preparation for ender-based text control
* added focus listener. Doesn't do much yet, but when focus notifications start appearing, we'll be ready for them. The code is in
place to hide selection when we lose focus and paint selection when we get focus. That's probably not quite right, but it's a start.
We will need to be able to determine the distinction between losing focus to another control within our app, and losing focus to
another app.
* added support for disabled and readonly states in the editor. This is accomplished by having flags set by the client, and letting the
rules system deal with those flags. The flags I added are:
TEXT_EDITOR_FLAG_PLAINTEXT 0x01 // only plain text editing is allowed
TEXT_EDITOR_FLAG_SINGLELINE 0x02 // enter key and CR-LF handled specially
TEXT_EDITOR_FLAG_PASSWORD 0x04 // text is not entered into content, only a representative character
TEXT_EDITOR_FLAG_READONLY 0x08 // editing events are disabled. Editor may still accept focus.
TEXT_EDITOR_FLAG_DISALBED 0x10 // all events are disabled (like scrolling). Editor will not accept focus.
* added WillInsertBreak/DidInsertBreak into text rules, so flags could be checked. This gets us readonly, disabled, and single line
behavior.
* cleaned up the code that allocates, registers, and destroys event listeners. Thanks to Kin and Simon for cleaning up the
ownership model on the listeners, it was a big help.
* added support for a max text length. You can now tell the text editor, be no bigger than n characters.
1999-05-29 01:24:18 +04:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::Init(nsIDOMDocument *aDoc,
|
|
|
|
nsIPresShell *aPresShell)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(nsnull!=aDoc && nsnull!=aPresShell, "bad arg");
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res=NS_ERROR_NULL_POINTER;
|
1999-03-01 22:54:47 +03:00
|
|
|
if ((nsnull!=aDoc) && (nsnull!=aPresShell))
|
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::Init(aDoc, aPresShell);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-29 12:02:05 +04:00
|
|
|
void nsHTMLEditor::InitRules()
|
|
|
|
{
|
|
|
|
// instantiate the rules for this text editor
|
|
|
|
// XXX: we should be told which set of rules to instantiate
|
|
|
|
mRules = new nsHTMLEditRules();
|
|
|
|
mRules->Init(this);
|
|
|
|
}
|
|
|
|
|
1999-04-15 10:06:33 +04:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::SetTextProperty(nsIAtom *aProperty,
|
|
|
|
const nsString *aAttribute,
|
|
|
|
const nsString *aValue)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-04-15 10:06:33 +04:00
|
|
|
return nsTextEditor::SetTextProperty(aProperty, aAttribute, aValue);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-04-15 10:06:33 +04:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::GetTextProperty(nsIAtom *aProperty,
|
|
|
|
const nsString *aAttribute,
|
|
|
|
const nsString *aValue,
|
|
|
|
PRBool &aFirst, PRBool &aAny, PRBool &aAll)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-04-15 10:06:33 +04:00
|
|
|
return nsTextEditor::GetTextProperty(aProperty, aAttribute, aValue, aFirst, aAny, aAll);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-04-15 10:06:33 +04:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::RemoveTextProperty(nsIAtom *aProperty, const nsString *aAttribute)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-04-15 10:06:33 +04:00
|
|
|
return nsTextEditor::RemoveTextProperty(aProperty, aAttribute);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-05-06 03:27:17 +04:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::DeleteSelection(nsIEditor::ECollapsedSelectionAction aAction)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-05-06 03:27:17 +04:00
|
|
|
return nsTextEditor::DeleteSelection(aAction);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-02 08:30:53 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::InsertText(const nsString& aStringToInsert)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::InsertText(aStringToInsert);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-05-27 01:40:51 +04:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::SetBackgroundColor(const nsString& aColor)
|
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->SetBackgroundColor(aColor);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res;
|
1999-05-27 01:40:51 +04:00
|
|
|
NS_ASSERTION(mDoc, "Missing Editor DOM Document");
|
|
|
|
|
|
|
|
// TODO: Check selection for Cell, Row, Column or table and do color on appropriate level
|
|
|
|
// For initial testing, just set the background on the BODY tag (the document's background)
|
|
|
|
|
|
|
|
// Set the background color attribute on the body tag
|
|
|
|
nsCOMPtr<nsIDOMElement> bodyElement;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsEditor::GetBodyElement(getter_AddRefs(bodyElement));
|
|
|
|
if (NS_SUCCEEDED(res) && bodyElement)
|
1999-05-27 01:40:51 +04:00
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-05-27 01:40:51 +04:00
|
|
|
bodyElement->SetAttribute("bgcolor", aColor);
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-05-27 01:40:51 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::SetBodyAttribute(const nsString& aAttribute, const nsString& aValue)
|
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->SetBodyAttribute(aAttribute, aValue);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res;
|
1999-05-27 01:40:51 +04:00
|
|
|
// TODO: Check selection for Cell, Row, Column or table and do color on appropriate level
|
|
|
|
|
|
|
|
NS_ASSERTION(mDoc, "Missing Editor DOM Document");
|
|
|
|
|
|
|
|
// Set the background color attribute on the body tag
|
|
|
|
nsCOMPtr<nsIDOMElement> bodyElement;
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsEditor::GetBodyElement(getter_AddRefs(bodyElement));
|
|
|
|
if (NS_SUCCEEDED(res) && bodyElement)
|
1999-05-27 01:40:51 +04:00
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-05-27 01:40:51 +04:00
|
|
|
bodyElement->SetAttribute(aAttribute, aValue);
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-05-27 01:40:51 +04:00
|
|
|
}
|
|
|
|
|
1999-03-10 22:49:18 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::InsertBreak()
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->InsertBreak();
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res;
|
1999-03-29 12:02:05 +04:00
|
|
|
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
|
|
|
PRBool cancel= PR_FALSE;
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-03-29 12:02:05 +04:00
|
|
|
|
|
|
|
// pre-process
|
|
|
|
nsEditor::GetSelection(getter_AddRefs(selection));
|
1999-04-12 16:01:32 +04:00
|
|
|
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kInsertBreak);
|
1999-06-03 10:00:23 +04:00
|
|
|
res = mRules->WillDoAction(selection, &ruleInfo, &cancel);
|
|
|
|
if ((PR_FALSE==cancel) && (NS_SUCCEEDED(res)))
|
1999-03-29 12:02:05 +04:00
|
|
|
{
|
|
|
|
// create the new BR node
|
|
|
|
nsCOMPtr<nsIDOMNode> newNode;
|
|
|
|
nsAutoString tag("BR");
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsEditor::DeleteSelectionAndCreateNode(tag, getter_AddRefs(newNode));
|
|
|
|
if (NS_SUCCEEDED(res) && newNode)
|
1999-03-29 12:02:05 +04:00
|
|
|
{
|
|
|
|
// set the selection to the new node
|
|
|
|
nsCOMPtr<nsIDOMNode>parent;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = newNode->GetParentNode(getter_AddRefs(parent));
|
|
|
|
if (NS_SUCCEEDED(res) && parent)
|
1999-03-29 12:02:05 +04:00
|
|
|
{
|
|
|
|
PRInt32 offsetInParent=-1; // we use the -1 as a marker to see if we need to compute this or not
|
|
|
|
nsCOMPtr<nsIDOMNode>nextNode;
|
|
|
|
newNode->GetNextSibling(getter_AddRefs(nextNode));
|
|
|
|
if (nextNode)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMCharacterData>nextTextNode;
|
|
|
|
nextTextNode = do_QueryInterface(nextNode);
|
|
|
|
if (!nextTextNode) {
|
|
|
|
nextNode = do_QueryInterface(newNode);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
offsetInParent=0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nextNode = do_QueryInterface(newNode);
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if (NS_SUCCEEDED(res))
|
1999-03-29 12:02:05 +04:00
|
|
|
{
|
|
|
|
if (-1==offsetInParent)
|
|
|
|
{
|
|
|
|
nextNode->GetParentNode(getter_AddRefs(parent));
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetChildOffset(nextNode, parent, offsetInParent);
|
|
|
|
if (NS_SUCCEEDED(res)) {
|
1999-03-29 12:02:05 +04:00
|
|
|
selection->Collapse(parent, offsetInParent+1); // +1 to insert just after the break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
selection->Collapse(nextNode, offsetInParent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// post-process, always called if WillInsertBreak didn't return cancel==PR_TRUE
|
1999-06-03 10:00:23 +04:00
|
|
|
res = mRules->DidDoAction(selection, &ruleInfo, res);
|
1999-03-29 12:02:05 +04:00
|
|
|
}
|
|
|
|
// XXXX: Horrible hack! We are doing this because
|
|
|
|
// of an error in Gecko which is not rendering the
|
|
|
|
// document after a change via the DOM - gpk 2/13/99
|
|
|
|
// BEGIN HACK!!!
|
1999-05-17 17:31:56 +04:00
|
|
|
// HACKForceRedraw();
|
1999-03-29 12:02:05 +04:00
|
|
|
// END HACK
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-05-06 03:29:18 +04:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::GetParagraphFormat(nsString& aParagraphFormat)
|
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res = NS_ERROR_NOT_INITIALIZED;
|
1999-05-06 03:29:18 +04:00
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-05-06 03:29:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::SetParagraphFormat(const nsString& aParagraphFormat)
|
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->SetParagraphFormat(aParagraphFormat);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res = NS_ERROR_NOT_INITIALIZED;
|
1999-05-06 03:29:18 +04:00
|
|
|
//Kinda sad to waste memory just to force lower case
|
|
|
|
nsAutoString tag = aParagraphFormat;
|
|
|
|
tag.ToLowerCase();
|
|
|
|
if (tag == "normal" || tag == "p") {
|
1999-06-03 10:00:23 +04:00
|
|
|
res = RemoveParagraphStyle();
|
1999-05-06 03:29:18 +04:00
|
|
|
} else {
|
1999-06-03 10:00:23 +04:00
|
|
|
res = ReplaceBlockParent(tag);
|
1999-05-06 03:29:18 +04:00
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-05-06 03:29:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-01 22:54:47 +03:00
|
|
|
// Methods shared with the base editor.
|
|
|
|
// Note: We could call each of these via nsTextEditor -- is that better?
|
1999-03-02 08:30:53 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::EnableUndo(PRBool aEnable)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::EnableUndo(aEnable);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-02 08:30:53 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::Undo(PRUint32 aCount)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::Undo(aCount);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-02 08:30:53 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::CanUndo(PRBool &aIsEnabled, PRBool &aCanUndo)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::CanUndo(aIsEnabled, aCanUndo);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-02 08:30:53 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::Redo(PRUint32 aCount)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::Redo(aCount);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-02 08:30:53 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::CanRedo(PRBool &aIsEnabled, PRBool &aCanRedo)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::CanRedo(aIsEnabled, aCanRedo);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-02 08:30:53 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::BeginTransaction()
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::BeginTransaction();
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-02 08:30:53 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::EndTransaction()
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::EndTransaction();
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-02 08:30:53 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::MoveSelectionUp(nsIAtom *aIncrement, PRBool aExtendSelection)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::MoveSelectionUp(aIncrement, aExtendSelection);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-02 08:30:53 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::MoveSelectionDown(nsIAtom *aIncrement, PRBool aExtendSelection)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::MoveSelectionDown(aIncrement, aExtendSelection);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-02 08:30:53 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::MoveSelectionNext(nsIAtom *aIncrement, PRBool aExtendSelection)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::MoveSelectionNext(aIncrement, aExtendSelection);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-02 08:30:53 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::MoveSelectionPrevious(nsIAtom *aIncrement, PRBool aExtendSelection)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::MoveSelectionPrevious(aIncrement, aExtendSelection);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-02 08:30:53 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::SelectNext(nsIAtom *aIncrement, PRBool aExtendSelection)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::SelectNext(aIncrement, aExtendSelection);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-02 08:30:53 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::SelectPrevious(nsIAtom *aIncrement, PRBool aExtendSelection)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::SelectPrevious(aIncrement, aExtendSelection);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-11 22:33:37 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::SelectAll()
|
|
|
|
{
|
|
|
|
return nsTextEditor::SelectAll();
|
|
|
|
}
|
|
|
|
|
1999-03-02 08:30:53 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::ScrollUp(nsIAtom *aIncrement)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::ScrollUp(aIncrement);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-02 08:30:53 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::ScrollDown(nsIAtom *aIncrement)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::ScrollDown(aIncrement);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-03-02 08:30:53 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::ScrollIntoView(PRBool aScrollToBegin)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::ScrollIntoView(aScrollToBegin);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-05-07 09:02:35 +04:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::Save()
|
|
|
|
{
|
|
|
|
return nsTextEditor::Save();
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::SaveAs(PRBool aSavingCopy)
|
|
|
|
{
|
|
|
|
return nsTextEditor::SaveAs(aSavingCopy);
|
|
|
|
}
|
|
|
|
|
1999-03-11 00:29:41 +03:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::Cut()
|
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::Cut();
|
1999-03-11 00:29:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::Copy()
|
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::Copy();
|
1999-03-11 00:29:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::Paste()
|
|
|
|
{
|
1999-03-11 01:41:18 +03:00
|
|
|
return nsTextEditor::Paste();
|
1999-03-11 00:29:41 +03:00
|
|
|
}
|
|
|
|
|
1999-05-27 04:08:15 +04:00
|
|
|
//
|
|
|
|
// HTML PasteAsQuotation: Paste in a blockquote type=cite
|
|
|
|
//
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::PasteAsQuotation()
|
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->PasteAsQuotation();
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-05-27 04:08:15 +04:00
|
|
|
nsAutoString citation("");
|
|
|
|
return PasteAsCitedQuotation(citation);
|
|
|
|
}
|
|
|
|
|
1999-05-28 04:46:34 +04:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::PasteAsCitedQuotation(const nsString& aCitation)
|
1999-05-27 04:08:15 +04:00
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->PasteAsCitedQuotation(aCitation);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-05-27 04:08:15 +04:00
|
|
|
printf("nsHTMLEditor::PasteAsQuotation\n");
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-05-27 04:08:15 +04:00
|
|
|
nsCOMPtr<nsIDOMNode> newNode;
|
|
|
|
nsAutoString tag("blockquote");
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res = nsEditor::DeleteSelectionAndCreateNode(tag, getter_AddRefs(newNode));
|
1999-05-27 04:08:15 +04:00
|
|
|
if (NS_FAILED(res) || !newNode)
|
|
|
|
return res;
|
|
|
|
|
|
|
|
// Try to set type=cite. Ignore it if this fails.
|
|
|
|
nsCOMPtr<nsIDOMElement> newElement (do_QueryInterface(newNode));
|
|
|
|
if (newElement)
|
|
|
|
{
|
|
|
|
nsAutoString type ("type");
|
|
|
|
nsAutoString cite ("cite");
|
|
|
|
newElement->SetAttribute(type, cite);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the selection to the underneath the node we just inserted:
|
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
|
|
|
res = GetSelection(getter_AddRefs(selection));
|
|
|
|
if (NS_FAILED(res) || !selection)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_akkana
|
|
|
|
printf("Can't get selection!");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
res = selection->Collapse(newNode, 0);
|
|
|
|
if (NS_FAILED(res))
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_akkana
|
|
|
|
printf("Couldn't collapse");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
res = Paste();
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::InsertAsQuotation(const nsString& aQuotedText)
|
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->InsertAsQuotation(aQuotedText);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-05-27 04:08:15 +04:00
|
|
|
nsAutoString citation ("");
|
|
|
|
return InsertAsCitedQuotation(aQuotedText, citation);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::InsertAsCitedQuotation(const nsString& aQuotedText,
|
1999-05-28 04:46:34 +04:00
|
|
|
const nsString& aCitation)
|
1999-05-27 04:08:15 +04:00
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->InsertAsCitedQuotation(aQuotedText, aCitation);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-05-27 04:08:15 +04:00
|
|
|
printf("nsHTMLEditor::InsertAsQuotation\n");
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-05-27 04:08:15 +04:00
|
|
|
nsCOMPtr<nsIDOMNode> newNode;
|
|
|
|
nsAutoString tag("blockquote");
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res = nsEditor::DeleteSelectionAndCreateNode(tag, getter_AddRefs(newNode));
|
1999-05-27 04:08:15 +04:00
|
|
|
if (NS_FAILED(res) || !newNode)
|
|
|
|
return res;
|
|
|
|
|
|
|
|
// Try to set type=cite. Ignore it if this fails.
|
|
|
|
nsCOMPtr<nsIDOMElement> newElement (do_QueryInterface(newNode));
|
|
|
|
if (newElement)
|
|
|
|
{
|
|
|
|
nsAutoString type ("type");
|
|
|
|
nsAutoString cite ("cite");
|
|
|
|
newElement->SetAttribute(type, cite);
|
|
|
|
|
|
|
|
if (aCitation.Length() > 0)
|
|
|
|
newElement->SetAttribute(cite, aCitation);
|
|
|
|
}
|
|
|
|
|
|
|
|
res = InsertHTML(aQuotedText);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::InsertHTML(const nsString& aInputString)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->InsertHTML(aInputString);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-05-07 23:23:17 +04:00
|
|
|
nsresult res;
|
1999-06-03 10:00:23 +04:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-05-06 03:27:17 +04:00
|
|
|
|
|
|
|
nsEditor::DeleteSelection(nsIEditor::eDoNothing);
|
|
|
|
|
1999-05-07 23:23:17 +04:00
|
|
|
// Make the transaction for insert html:
|
|
|
|
nsInsertHTMLTxn* insertHTMLTxn = 0;
|
|
|
|
res = TransactionFactory::GetNewTransaction(kInsertHTMLTxnIID,
|
|
|
|
(EditTxn **)&insertHTMLTxn);
|
|
|
|
if (NS_SUCCEEDED(res))
|
1999-05-06 03:27:17 +04:00
|
|
|
{
|
1999-05-07 23:23:17 +04:00
|
|
|
res = insertHTMLTxn->Init(aInputString, this);
|
1999-05-06 03:27:17 +04:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-05-07 23:23:17 +04:00
|
|
|
res = Do(insertHTMLTxn);
|
|
|
|
|
|
|
|
// XXX How is it that we don't have to release the transaction?
|
1999-05-06 03:27:17 +04:00
|
|
|
}
|
|
|
|
|
1999-05-17 16:22:31 +04:00
|
|
|
if (NS_FAILED(res))
|
1999-05-06 03:27:17 +04:00
|
|
|
printf("Couldn't insert html: error was %d\n", res);
|
1999-05-07 23:23:17 +04:00
|
|
|
|
1999-05-06 03:27:17 +04:00
|
|
|
return res;
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-06-08 01:12:01 +04:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::OutputTextToString(nsString& aOutputString)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-06-10 04:35:02 +04:00
|
|
|
nsCOMPtr<nsITextEncoder> encoder;
|
|
|
|
nsresult rv = nsComponentManager::CreateInstance(kTextEncoderCID,
|
|
|
|
nsnull,
|
|
|
|
nsIDocumentEncoder::GetIID(),
|
|
|
|
getter_AddRefs(encoder));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMDocument> domdoc;
|
|
|
|
rv = GetDocument(getter_AddRefs(domdoc));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
|
|
|
|
nsString mimetype ("text/plain");
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
|
|
|
|
rv = GetPresShell(getter_AddRefs(shell));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
rv = encoder->Init(shell,doc, mimetype);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return encoder->EncodeToString(aOutputString);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-06-08 01:12:01 +04:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::OutputHTMLToString(nsString& aOutputString)
|
1999-03-01 22:54:47 +03:00
|
|
|
{
|
1999-06-07 23:32:36 +04:00
|
|
|
nsCOMPtr<nsIHTMLEncoder> encoder;
|
|
|
|
nsresult rv = nsComponentManager::CreateInstance(kHTMLEncoderCID,
|
|
|
|
nsnull,
|
|
|
|
nsIDocumentEncoder::GetIID(),
|
|
|
|
getter_AddRefs(encoder));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
1999-06-10 04:35:02 +04:00
|
|
|
|
1999-06-08 04:02:25 +04:00
|
|
|
nsCOMPtr<nsIDOMDocument> domdoc;
|
|
|
|
rv = GetDocument(getter_AddRefs(domdoc));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
|
|
|
|
nsString mimetype ("text/html");
|
|
|
|
|
1999-06-10 04:35:02 +04:00
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
|
|
|
|
rv = GetPresShell(getter_AddRefs(shell));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
rv = encoder->Init(shell,doc, mimetype);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
}
|
1999-06-08 04:02:25 +04:00
|
|
|
|
1999-06-07 23:32:36 +04:00
|
|
|
return encoder->EncodeToString(aOutputString);
|
1999-03-01 22:54:47 +03:00
|
|
|
}
|
|
|
|
|
1999-06-10 04:35:02 +04:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::OutputTextToStream(nsIOutputStream* aOutputStream, nsString* aCharset)
|
1999-05-03 22:48:39 +04:00
|
|
|
{
|
1999-06-10 04:35:02 +04:00
|
|
|
nsCOMPtr<nsITextEncoder> encoder;
|
|
|
|
nsresult rv = nsComponentManager::CreateInstance(kTextEncoderCID,
|
|
|
|
nsnull,
|
|
|
|
nsIDocumentEncoder::GetIID(),
|
|
|
|
getter_AddRefs(encoder));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMDocument> domdoc;
|
|
|
|
rv = GetDocument(getter_AddRefs(domdoc));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
|
|
|
|
nsString mimetype ("text/plain");
|
|
|
|
|
|
|
|
if (aCharset && aCharset->Length() != 0 && aCharset->Equals("null")==PR_FALSE)
|
|
|
|
encoder->SetCharset(*aCharset);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
|
|
|
|
rv = GetPresShell(getter_AddRefs(shell));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
rv = encoder->Init(shell,doc, mimetype);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
return encoder->EncodeToStream(aOutputStream);
|
1999-05-03 22:48:39 +04:00
|
|
|
}
|
|
|
|
|
1999-06-10 04:35:02 +04:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::OutputHTMLToStream(nsIOutputStream* aOutputStream,nsString* aCharset)
|
1999-05-03 22:48:39 +04:00
|
|
|
{
|
1999-06-10 04:35:02 +04:00
|
|
|
nsCOMPtr<nsIHTMLEncoder> encoder;
|
|
|
|
nsresult rv = nsComponentManager::CreateInstance(kHTMLEncoderCID,
|
|
|
|
nsnull,
|
|
|
|
nsIDocumentEncoder::GetIID(),
|
|
|
|
getter_AddRefs(encoder));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMDocument> domdoc;
|
|
|
|
rv = GetDocument(getter_AddRefs(domdoc));
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
|
|
|
|
nsString mimetype ("text/html");
|
|
|
|
|
|
|
|
nsCOMPtr<nsIPresShell> shell;
|
|
|
|
|
|
|
|
if (aCharset && aCharset->Length() != 0 && aCharset->Equals("null")==PR_FALSE)
|
|
|
|
encoder->SetCharset(*aCharset);
|
|
|
|
|
|
|
|
rv = GetPresShell(getter_AddRefs(shell));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
rv = encoder->Init(shell,doc, mimetype);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
return encoder->EncodeToStream(aOutputStream);
|
1999-05-03 22:48:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-04-21 22:53:55 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::CopyAttributes(nsIDOMNode *aDestNode, nsIDOMNode *aSourceNode)
|
|
|
|
{
|
|
|
|
return nsTextEditor::CopyAttributes(aDestNode, aSourceNode);
|
|
|
|
}
|
|
|
|
|
1999-03-01 22:54:47 +03:00
|
|
|
//================================================================
|
|
|
|
// HTML Editor methods
|
|
|
|
//
|
|
|
|
// Note: Table Editing methods are implemented in EditTable.cpp
|
|
|
|
//
|
1999-03-30 02:01:26 +04:00
|
|
|
|
1999-05-01 02:40:18 +04:00
|
|
|
// get the paragraph style(s) for the selection
|
1999-04-20 21:47:12 +04:00
|
|
|
NS_IMETHODIMP
|
1999-05-01 02:40:18 +04:00
|
|
|
nsHTMLEditor::GetParagraphStyle(nsStringArray *aTagList)
|
1999-04-20 21:47:12 +04:00
|
|
|
{
|
1999-05-01 02:40:18 +04:00
|
|
|
if (gNoisy) { printf("---------- nsHTMLEditor::GetParagraphStyle ----------\n"); }
|
|
|
|
if (!aTagList) { return NS_ERROR_NULL_POINTER; }
|
1999-04-20 21:47:12 +04:00
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res;
|
1999-05-01 02:40:18 +04:00
|
|
|
nsCOMPtr<nsIDOMSelection>selection;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if ((NS_SUCCEEDED(res)) && selection)
|
1999-05-01 02:40:18 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIEnumerator> enumerator;
|
|
|
|
enumerator = do_QueryInterface(selection);
|
|
|
|
if (enumerator)
|
|
|
|
{
|
|
|
|
enumerator->First();
|
|
|
|
nsISupports *currentItem;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = enumerator->CurrentItem(¤tItem);
|
|
|
|
if ((NS_SUCCEEDED(res)) && (nsnull!=currentItem))
|
1999-05-01 02:40:18 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
1999-05-05 08:05:19 +04:00
|
|
|
// scan the range for all the independent block content blockSections
|
1999-05-01 02:40:18 +04:00
|
|
|
// and get the block parent of each
|
1999-05-05 08:05:19 +04:00
|
|
|
nsISupportsArray *blockSections;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = NS_NewISupportsArray(&blockSections);
|
|
|
|
if ((NS_SUCCEEDED(res)) && blockSections)
|
1999-05-01 02:40:18 +04:00
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetBlockSectionsForRange(range, blockSections);
|
|
|
|
if (NS_SUCCEEDED(res))
|
1999-05-01 02:40:18 +04:00
|
|
|
{
|
|
|
|
nsIDOMRange *subRange;
|
1999-05-05 08:05:19 +04:00
|
|
|
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
1999-06-03 10:00:23 +04:00
|
|
|
while (subRange && (NS_SUCCEEDED(res)))
|
1999-05-01 02:40:18 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode>startParent;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = subRange->GetStartParent(getter_AddRefs(startParent));
|
|
|
|
if (NS_SUCCEEDED(res) && startParent)
|
1999-05-01 02:40:18 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMElement> blockParent;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetBlockParent(startParent, getter_AddRefs(blockParent));
|
|
|
|
if (NS_SUCCEEDED(res) && blockParent)
|
1999-05-01 02:40:18 +04:00
|
|
|
{
|
|
|
|
nsAutoString blockParentTag;
|
|
|
|
blockParent->GetTagName(blockParentTag);
|
1999-05-05 08:05:19 +04:00
|
|
|
PRBool isRoot;
|
|
|
|
IsRootTag(blockParentTag, isRoot);
|
|
|
|
if ((PR_FALSE==isRoot) && (-1==aTagList->IndexOf(blockParentTag))) {
|
1999-05-01 02:40:18 +04:00
|
|
|
aTagList->AppendString(blockParentTag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NS_RELEASE(subRange);
|
1999-05-05 08:05:19 +04:00
|
|
|
blockSections->RemoveElementAt(0);
|
|
|
|
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
1999-05-01 02:40:18 +04:00
|
|
|
}
|
|
|
|
}
|
1999-05-05 08:05:19 +04:00
|
|
|
NS_RELEASE(blockSections);
|
1999-05-01 02:40:18 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-05-01 02:40:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// use this when block parents are to be added regardless of current state
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::AddBlockParent(nsString& aParentTag)
|
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->AddBlockParent(aParentTag);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-04-20 21:47:12 +04:00
|
|
|
if (gNoisy)
|
|
|
|
{
|
|
|
|
char *tag = aParentTag.ToNewCString();
|
|
|
|
printf("---------- nsHTMLEditor::AddBlockParent %s ----------\n", tag);
|
|
|
|
delete [] tag;
|
|
|
|
}
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res=NS_ERROR_NOT_INITIALIZED;
|
1999-04-20 21:47:12 +04:00
|
|
|
nsCOMPtr<nsIDOMSelection>selection;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if ((NS_SUCCEEDED(res)) && selection)
|
1999-04-20 21:47:12 +04:00
|
|
|
{
|
|
|
|
// set the block parent for all selected ranges
|
1999-06-08 10:04:51 +04:00
|
|
|
nsAutoSelectionReset selectionResetter(selection);
|
1999-06-03 10:00:23 +04:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-04-20 21:47:12 +04:00
|
|
|
nsCOMPtr<nsIEnumerator> enumerator;
|
|
|
|
enumerator = do_QueryInterface(selection);
|
|
|
|
if (enumerator)
|
|
|
|
{
|
|
|
|
enumerator->First();
|
|
|
|
nsISupports *currentItem;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = enumerator->CurrentItem(¤tItem);
|
|
|
|
if ((NS_SUCCEEDED(res)) && (nsnull!=currentItem))
|
1999-04-20 21:47:12 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
1999-05-05 08:05:19 +04:00
|
|
|
// scan the range for all the independent block content blockSections
|
1999-05-01 02:40:18 +04:00
|
|
|
// and apply the transformation to them
|
1999-06-03 10:00:23 +04:00
|
|
|
res = ReParentContentOfRange(range, aParentTag, eInsertParent);
|
1999-04-20 21:47:12 +04:00
|
|
|
}
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-04-20 21:47:12 +04:00
|
|
|
{ // set the selection
|
|
|
|
// XXX: can't do anything until I can create ranges
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (gNoisy) {printf("Finished nsHTMLEditor::AddBlockParent with this content:\n"); DebugDumpContent(); } // DEBUG
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-04-20 21:47:12 +04:00
|
|
|
}
|
|
|
|
|
1999-05-01 02:40:18 +04:00
|
|
|
// use this when a paragraph type is being transformed from one type to another
|
1999-04-20 21:47:12 +04:00
|
|
|
NS_IMETHODIMP
|
1999-05-01 02:40:18 +04:00
|
|
|
nsHTMLEditor::ReplaceBlockParent(nsString& aParentTag)
|
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->ReplaceBlockParent(aParentTag);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
1999-05-01 02:40:18 +04:00
|
|
|
|
|
|
|
if (gNoisy)
|
|
|
|
{
|
|
|
|
char *tag = aParentTag.ToNewCString();
|
|
|
|
printf("---------- nsHTMLEditor::ReplaceBlockParent %s ----------\n", tag);
|
|
|
|
delete [] tag;
|
|
|
|
}
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res=NS_ERROR_NOT_INITIALIZED;
|
1999-05-01 02:40:18 +04:00
|
|
|
nsCOMPtr<nsIDOMSelection>selection;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if ((NS_SUCCEEDED(res)) && selection)
|
1999-05-01 02:40:18 +04:00
|
|
|
{
|
1999-06-08 10:04:51 +04:00
|
|
|
nsAutoSelectionReset selectionResetter(selection);
|
1999-05-01 02:40:18 +04:00
|
|
|
// set the block parent for all selected ranges
|
1999-06-03 10:00:23 +04:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-05-01 02:40:18 +04:00
|
|
|
nsCOMPtr<nsIEnumerator> enumerator;
|
|
|
|
enumerator = do_QueryInterface(selection);
|
|
|
|
if (enumerator)
|
|
|
|
{
|
|
|
|
enumerator->First();
|
|
|
|
nsISupports *currentItem;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = enumerator->CurrentItem(¤tItem);
|
|
|
|
if ((NS_SUCCEEDED(res)) && (nsnull!=currentItem))
|
1999-05-01 02:40:18 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
1999-05-05 08:05:19 +04:00
|
|
|
// scan the range for all the independent block content blockSections
|
1999-05-01 02:40:18 +04:00
|
|
|
// and apply the transformation to them
|
1999-06-03 10:00:23 +04:00
|
|
|
res = ReParentContentOfRange(range, aParentTag, eReplaceParent);
|
1999-05-01 02:40:18 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (gNoisy) {printf("Finished nsHTMLEditor::AddBlockParent with this content:\n"); DebugDumpContent(); } // DEBUG
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-05-01 02:40:18 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::ReParentContentOfNode(nsIDOMNode *aNode,
|
|
|
|
nsString &aParentTag,
|
|
|
|
BlockTransformationType aTransformation)
|
1999-04-20 21:47:12 +04:00
|
|
|
{
|
|
|
|
if (!aNode) { return NS_ERROR_NULL_POINTER; }
|
1999-05-05 08:05:19 +04:00
|
|
|
if (gNoisy)
|
|
|
|
{
|
|
|
|
char *tag = aParentTag.ToNewCString();
|
|
|
|
printf("---------- ReParentContentOfNode(%p,%s,%d) -----------\n", aNode, tag, aTransformation);
|
|
|
|
delete [] tag;
|
|
|
|
}
|
1999-04-21 08:08:43 +04:00
|
|
|
// find the current block parent, or just use aNode if it is a block node
|
1999-04-20 21:47:12 +04:00
|
|
|
nsCOMPtr<nsIDOMElement>blockParentElement;
|
1999-04-21 08:08:43 +04:00
|
|
|
nsCOMPtr<nsIDOMNode>nodeToReParent; // this is the node we'll operate on, by default it's aNode
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res = aNode->QueryInterface(nsIDOMNode::GetIID(), getter_AddRefs(nodeToReParent));
|
1999-04-21 08:08:43 +04:00
|
|
|
PRBool nodeIsInline;
|
|
|
|
PRBool nodeIsBlock=PR_FALSE;
|
|
|
|
nsTextEditor::IsNodeInline(aNode, nodeIsInline);
|
|
|
|
if (PR_FALSE==nodeIsInline)
|
|
|
|
{
|
|
|
|
nsresult QIResult;
|
|
|
|
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
|
|
|
|
QIResult = aNode->QueryInterface(nsIDOMCharacterData::GetIID(), getter_AddRefs(nodeAsText));
|
|
|
|
if (NS_FAILED(QIResult) || !nodeAsText) {
|
|
|
|
nodeIsBlock=PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
1999-05-01 02:40:18 +04:00
|
|
|
// if aNode is the block parent, then the node to reparent is one of its children
|
1999-04-21 08:08:43 +04:00
|
|
|
if (PR_TRUE==nodeIsBlock)
|
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = aNode->QueryInterface(nsIDOMNode::GetIID(), getter_AddRefs(blockParentElement));
|
|
|
|
if (NS_SUCCEEDED(res) && blockParentElement) {
|
|
|
|
res = aNode->GetFirstChild(getter_AddRefs(nodeToReParent));
|
1999-04-21 08:08:43 +04:00
|
|
|
}
|
|
|
|
}
|
1999-05-01 02:40:18 +04:00
|
|
|
else { // we just need to get the block parent of aNode
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsTextEditor::GetBlockParent(aNode, getter_AddRefs(blockParentElement));
|
1999-04-21 08:08:43 +04:00
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
// at this point, we must have a good res, a node to reparent, and a block parent
|
1999-04-21 08:08:43 +04:00
|
|
|
if (!nodeToReParent) { return NS_ERROR_UNEXPECTED;}
|
|
|
|
if (!blockParentElement) { return NS_ERROR_NULL_POINTER;}
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-04-20 21:47:12 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode> newParentNode;
|
|
|
|
nsCOMPtr<nsIDOMNode> blockParentNode = do_QueryInterface(blockParentElement);
|
1999-04-21 08:08:43 +04:00
|
|
|
// we need to treat nodes directly inside the body differently
|
1999-04-20 21:47:12 +04:00
|
|
|
nsAutoString parentTag;
|
|
|
|
blockParentElement->GetTagName(parentTag);
|
1999-05-01 02:40:18 +04:00
|
|
|
PRBool isRoot;
|
|
|
|
IsRootTag(parentTag, isRoot);
|
|
|
|
if (PR_TRUE==isRoot)
|
1999-04-20 21:47:12 +04:00
|
|
|
{
|
1999-05-01 02:40:18 +04:00
|
|
|
// if nodeToReParent is a text node, we have <ROOT>Text.
|
|
|
|
// re-parent Text into a new <aTag> at the offset of Text in <ROOT>
|
|
|
|
// so we end up with <ROOT><aTag>Text
|
|
|
|
// ignore aTransformation, replaces act like inserts
|
1999-04-21 08:08:43 +04:00
|
|
|
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(nodeToReParent);
|
1999-04-20 21:47:12 +04:00
|
|
|
if (nodeAsText)
|
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = ReParentBlockContent(nodeToReParent, aParentTag, blockParentNode, parentTag,
|
1999-05-01 02:40:18 +04:00
|
|
|
aTransformation, getter_AddRefs(newParentNode));
|
1999-04-20 21:47:12 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // this is the case of an insertion point between 2 non-text objects
|
1999-05-01 02:40:18 +04:00
|
|
|
// XXX: how to you know it's an insertion point???
|
1999-04-20 21:47:12 +04:00
|
|
|
PRInt32 offsetInParent=0;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetChildOffset(nodeToReParent, blockParentNode, offsetInParent);
|
|
|
|
NS_ASSERTION((NS_SUCCEEDED(res)), "bad res from GetChildOffset");
|
1999-04-20 21:47:12 +04:00
|
|
|
// otherwise, just create the block parent at the selection
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsTextEditor::CreateNode(aParentTag, blockParentNode, offsetInParent,
|
1999-04-20 21:47:12 +04:00
|
|
|
getter_AddRefs(newParentNode));
|
1999-05-01 02:40:18 +04:00
|
|
|
// XXX: need to move some of the children of blockParentNode into the newParentNode?
|
|
|
|
// XXX: need to create a bogus text node inside this new block?
|
1999-04-20 21:47:12 +04:00
|
|
|
// that means, I need to generalize bogus node handling
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
1999-05-01 02:40:18 +04:00
|
|
|
{ // the block parent is not a ROOT,
|
|
|
|
// for the selected block content, transform blockParentNode
|
|
|
|
if (((eReplaceParent==aTransformation) && (PR_FALSE==parentTag.EqualsIgnoreCase(aParentTag))) ||
|
|
|
|
(eInsertParent==aTransformation))
|
1999-04-20 21:47:12 +04:00
|
|
|
{
|
1999-05-01 02:40:18 +04:00
|
|
|
if (gNoisy) { DebugDumpContent(); } // DEBUG
|
1999-06-03 10:00:23 +04:00
|
|
|
res = ReParentBlockContent(nodeToReParent, aParentTag, blockParentNode, parentTag,
|
1999-05-01 02:40:18 +04:00
|
|
|
aTransformation, getter_AddRefs(newParentNode));
|
1999-06-03 10:00:23 +04:00
|
|
|
if ((NS_SUCCEEDED(res)) && (newParentNode) && (eReplaceParent==aTransformation))
|
1999-04-20 21:47:12 +04:00
|
|
|
{
|
|
|
|
PRBool hasChildren;
|
|
|
|
blockParentNode->HasChildNodes(&hasChildren);
|
|
|
|
if (PR_FALSE==hasChildren)
|
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsEditor::DeleteNode(blockParentNode);
|
1999-04-20 21:47:12 +04:00
|
|
|
if (gNoisy)
|
|
|
|
{
|
|
|
|
printf("deleted old block parent node %p\n", blockParentNode.get());
|
|
|
|
DebugDumpContent(); // DEBUG
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else { // otherwise, it's a no-op
|
|
|
|
if (gNoisy) { printf("AddBlockParent is a no-op for this collapsed selection.\n"); }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-04-20 21:47:12 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::ReParentBlockContent(nsIDOMNode *aNode,
|
|
|
|
nsString &aParentTag,
|
|
|
|
nsIDOMNode *aBlockParentNode,
|
|
|
|
nsString &aBlockParentTag,
|
1999-05-05 08:05:19 +04:00
|
|
|
BlockTransformationType aTransformation,
|
1999-04-20 21:47:12 +04:00
|
|
|
nsIDOMNode **aNewParentNode)
|
|
|
|
{
|
|
|
|
if (!aNode || !aBlockParentNode || !aNewParentNode) { return NS_ERROR_NULL_POINTER; }
|
1999-05-05 08:05:19 +04:00
|
|
|
nsCOMPtr<nsIDOMNode> blockParentNode = do_QueryInterface(aBlockParentNode);
|
|
|
|
PRBool removeBlockParent = PR_FALSE;
|
|
|
|
PRBool removeBreakBefore = PR_FALSE;
|
|
|
|
PRBool removeBreakAfter = PR_FALSE;
|
1999-04-20 21:47:12 +04:00
|
|
|
nsCOMPtr<nsIDOMNode>ancestor;
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res = aNode->GetParentNode(getter_AddRefs(ancestor));
|
1999-04-20 21:47:12 +04:00
|
|
|
nsCOMPtr<nsIDOMNode>previousAncestor = do_QueryInterface(aNode);
|
1999-06-03 10:00:23 +04:00
|
|
|
while (NS_SUCCEEDED(res) && ancestor)
|
1999-04-20 21:47:12 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMElement>ancestorElement = do_QueryInterface(ancestor);
|
|
|
|
nsAutoString ancestorTag;
|
|
|
|
ancestorElement->GetTagName(ancestorTag);
|
|
|
|
if (ancestorTag.EqualsIgnoreCase(aBlockParentTag))
|
|
|
|
{
|
|
|
|
break; // previousAncestor will contain the node to operate on
|
|
|
|
}
|
|
|
|
previousAncestor = do_QueryInterface(ancestor);
|
1999-06-03 10:00:23 +04:00
|
|
|
res = ancestorElement->GetParentNode(getter_AddRefs(ancestor));
|
1999-04-20 21:47:12 +04:00
|
|
|
}
|
|
|
|
// now, previousAncestor is the node we are operating on
|
|
|
|
nsCOMPtr<nsIDOMNode>leftNode, rightNode;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetBlockSection(previousAncestor,
|
1999-05-05 08:05:19 +04:00
|
|
|
getter_AddRefs(leftNode),
|
|
|
|
getter_AddRefs(rightNode));
|
1999-06-03 10:00:23 +04:00
|
|
|
if ((NS_SUCCEEDED(res)) && leftNode && rightNode)
|
1999-04-20 21:47:12 +04:00
|
|
|
{
|
1999-05-05 08:05:19 +04:00
|
|
|
// determine some state for managing <BR>s around the new block
|
|
|
|
PRBool isSubordinateBlock = PR_FALSE; // if true, the content is already in a subordinate block
|
|
|
|
PRBool isRootBlock = PR_FALSE; // if true, the content is in a root block
|
|
|
|
nsCOMPtr<nsIDOMElement>blockParentElement = do_QueryInterface(blockParentNode);
|
|
|
|
if (blockParentElement)
|
|
|
|
{
|
|
|
|
nsAutoString blockParentTag;
|
|
|
|
blockParentElement->GetTagName(blockParentTag);
|
|
|
|
IsSubordinateBlock(blockParentTag, isSubordinateBlock);
|
|
|
|
IsRootTag(blockParentTag, isRootBlock);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PR_TRUE==isRootBlock)
|
|
|
|
{ // we're creating a block element where a block element did not previously exist
|
|
|
|
removeBreakBefore = PR_TRUE;
|
|
|
|
removeBreakAfter = PR_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// apply the transformation
|
1999-04-20 21:47:12 +04:00
|
|
|
PRInt32 offsetInParent=0;
|
1999-05-05 08:05:19 +04:00
|
|
|
if (eInsertParent==aTransformation || PR_TRUE==isRootBlock)
|
1999-04-20 21:47:12 +04:00
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetChildOffset(leftNode, blockParentNode, offsetInParent);
|
|
|
|
NS_ASSERTION((NS_SUCCEEDED(res)), "bad res from GetChildOffset");
|
|
|
|
res = nsTextEditor::CreateNode(aParentTag, blockParentNode, offsetInParent, aNewParentNode);
|
1999-05-05 08:05:19 +04:00
|
|
|
if (gNoisy) { printf("created a node in blockParentNode at offset %d\n", offsetInParent); }
|
1999-04-20 21:47:12 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode> grandParent;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = blockParentNode->GetParentNode(getter_AddRefs(grandParent));
|
|
|
|
if ((NS_SUCCEEDED(res)) && grandParent)
|
1999-04-20 21:47:12 +04:00
|
|
|
{
|
1999-04-21 08:08:43 +04:00
|
|
|
nsCOMPtr<nsIDOMNode>firstChildNode, lastChildNode;
|
1999-05-05 08:05:19 +04:00
|
|
|
blockParentNode->GetFirstChild(getter_AddRefs(firstChildNode));
|
|
|
|
blockParentNode->GetLastChild(getter_AddRefs(lastChildNode));
|
1999-04-21 08:08:43 +04:00
|
|
|
if (firstChildNode==leftNode && lastChildNode==rightNode)
|
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetChildOffset(blockParentNode, grandParent, offsetInParent);
|
|
|
|
NS_ASSERTION((NS_SUCCEEDED(res)), "bad res from GetChildOffset");
|
|
|
|
res = nsTextEditor::CreateNode(aParentTag, grandParent, offsetInParent, aNewParentNode);
|
1999-04-21 08:08:43 +04:00
|
|
|
if (gNoisy) { printf("created a node in grandParent at offset %d\n", offsetInParent); }
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-05-05 08:05:19 +04:00
|
|
|
// We're in the case where the content of blockParentNode is separated by <BR>'s,
|
|
|
|
// creating multiple block content ranges.
|
|
|
|
// Split blockParentNode around the blockContent
|
|
|
|
if (gNoisy) { printf("splitting a node because of <BR>s\n"); }
|
|
|
|
nsCOMPtr<nsIDOMNode> newLeftNode;
|
|
|
|
if (firstChildNode!=leftNode)
|
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetChildOffset(leftNode, blockParentNode, offsetInParent);
|
1999-05-05 08:05:19 +04:00
|
|
|
if (gNoisy) { printf("splitting left at %d\n", offsetInParent); }
|
1999-06-03 10:00:23 +04:00
|
|
|
res = SplitNode(blockParentNode, offsetInParent, getter_AddRefs(newLeftNode));
|
1999-05-05 08:05:19 +04:00
|
|
|
// after this split, blockParentNode still contains leftNode and rightNode
|
|
|
|
}
|
|
|
|
if (lastChildNode!=rightNode)
|
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetChildOffset(rightNode, blockParentNode, offsetInParent);
|
1999-05-05 08:05:19 +04:00
|
|
|
offsetInParent++;
|
|
|
|
if (gNoisy) { printf("splitting right at %d\n", offsetInParent); }
|
1999-06-03 10:00:23 +04:00
|
|
|
res = SplitNode(blockParentNode, offsetInParent, getter_AddRefs(newLeftNode));
|
1999-05-05 08:05:19 +04:00
|
|
|
blockParentNode = do_QueryInterface(newLeftNode);
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetChildOffset(leftNode, blockParentNode, offsetInParent);
|
|
|
|
NS_ASSERTION((NS_SUCCEEDED(res)), "bad res from GetChildOffset");
|
|
|
|
res = nsTextEditor::CreateNode(aParentTag, blockParentNode, offsetInParent, aNewParentNode);
|
1999-05-05 08:05:19 +04:00
|
|
|
if (gNoisy) { printf("created a node in blockParentNode at offset %d\n", offsetInParent); }
|
|
|
|
// what we need to do here is remove the existing block parent when we're all done.
|
|
|
|
removeBlockParent = PR_TRUE;
|
1999-04-21 08:08:43 +04:00
|
|
|
}
|
1999-04-20 21:47:12 +04:00
|
|
|
}
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
if ((NS_SUCCEEDED(res)) && *aNewParentNode)
|
1999-05-05 08:05:19 +04:00
|
|
|
{ // move all the children/contents of blockParentNode to aNewParentNode
|
1999-04-20 21:47:12 +04:00
|
|
|
nsCOMPtr<nsIDOMNode>childNode = do_QueryInterface(rightNode);
|
|
|
|
nsCOMPtr<nsIDOMNode>previousSiblingNode;
|
1999-06-03 10:00:23 +04:00
|
|
|
while (NS_SUCCEEDED(res) && childNode)
|
1999-04-20 21:47:12 +04:00
|
|
|
{
|
|
|
|
childNode->GetPreviousSibling(getter_AddRefs(previousSiblingNode));
|
|
|
|
// explicitly delete of childNode from it's current parent
|
|
|
|
// can't just rely on DOM semantics of InsertNode doing the delete implicitly, doesn't undo!
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsEditor::DeleteNode(childNode);
|
|
|
|
if (NS_SUCCEEDED(res))
|
1999-04-20 21:47:12 +04:00
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsEditor::InsertNode(childNode, *aNewParentNode, 0);
|
1999-04-20 21:47:12 +04:00
|
|
|
if (gNoisy)
|
|
|
|
{
|
|
|
|
printf("re-parented sibling node %p\n", childNode.get());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (childNode==leftNode || rightNode==leftNode) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
childNode = do_QueryInterface(previousSiblingNode);
|
|
|
|
} // end while loop
|
|
|
|
}
|
1999-05-05 08:05:19 +04:00
|
|
|
// clean up the surrounding content to maintain vertical whitespace
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
|
|
|
// if the prior node is a <BR> and we did something to change vertical whitespacing, delete the <BR>
|
|
|
|
nsCOMPtr<nsIDOMNode> brNode;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetPriorNode(leftNode, PR_TRUE, getter_AddRefs(brNode));
|
|
|
|
if (NS_SUCCEEDED(res) && brNode)
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIContent> brContent = do_QueryInterface(brNode);
|
|
|
|
if (brContent)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIAtom> brContentTag;
|
|
|
|
brContent->GetTag(*getter_AddRefs(brContentTag));
|
1999-05-05 09:56:58 +04:00
|
|
|
if (nsIEditProperty::br==brContentTag.get()) {
|
1999-06-03 10:00:23 +04:00
|
|
|
res = DeleteNode(brNode);
|
1999-05-05 08:05:19 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if the next node is a <BR> and we did something to change vertical whitespacing, delete the <BR>
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetNextNode(rightNode, PR_TRUE, getter_AddRefs(brNode));
|
|
|
|
if (NS_SUCCEEDED(res) && brNode)
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIContent> brContent = do_QueryInterface(brNode);
|
|
|
|
if (brContent)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIAtom> brContentTag;
|
|
|
|
brContent->GetTag(*getter_AddRefs(brContentTag));
|
1999-05-05 09:56:58 +04:00
|
|
|
if (nsIEditProperty::br==brContentTag.get()) {
|
1999-06-03 10:00:23 +04:00
|
|
|
res = DeleteNode(brNode);
|
1999-05-05 08:05:19 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
if ((NS_SUCCEEDED(res)) && (PR_TRUE==removeBlockParent))
|
1999-05-05 08:05:19 +04:00
|
|
|
{ // we determined we need to remove the previous block parent. Do it!
|
|
|
|
// go through list backwards so deletes don't interfere with the iteration
|
|
|
|
nsCOMPtr<nsIDOMNodeList> childNodes;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = blockParentNode->GetChildNodes(getter_AddRefs(childNodes));
|
|
|
|
if ((NS_SUCCEEDED(res)) && (childNodes))
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode>grandParent;
|
|
|
|
blockParentNode->GetParentNode(getter_AddRefs(grandParent));
|
1999-06-07 23:32:36 +04:00
|
|
|
//PRInt32 offsetInParent;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetChildOffset(blockParentNode, grandParent, offsetInParent);
|
1999-05-05 08:05:19 +04:00
|
|
|
PRUint32 childCount;
|
|
|
|
childNodes->GetLength(&childCount);
|
|
|
|
PRInt32 i=childCount-1;
|
1999-06-03 10:00:23 +04:00
|
|
|
for ( ; ((NS_SUCCEEDED(res)) && (0<=i)); i--)
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode> childNode;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = childNodes->Item(i, getter_AddRefs(childNode));
|
|
|
|
if ((NS_SUCCEEDED(res)) && (childNode))
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsTextEditor::DeleteNode(childNode);
|
|
|
|
if (NS_SUCCEEDED(res)) {
|
|
|
|
res = nsTextEditor::InsertNode(childNode, grandParent, offsetInParent);
|
1999-05-05 08:05:19 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (gNoisy) { printf("removing the old block parent %p\n", blockParentNode.get()); }
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsTextEditor::DeleteNode(blockParentNode);
|
1999-05-05 08:05:19 +04:00
|
|
|
}
|
|
|
|
}
|
1999-04-20 21:47:12 +04:00
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-04-20 21:47:12 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-05-01 02:40:18 +04:00
|
|
|
nsHTMLEditor::ReParentContentOfRange(nsIDOMRange *aRange,
|
|
|
|
nsString &aParentTag,
|
|
|
|
BlockTransformationType aTranformation)
|
1999-04-20 21:47:12 +04:00
|
|
|
{
|
1999-05-01 02:40:18 +04:00
|
|
|
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res;
|
1999-05-05 08:05:19 +04:00
|
|
|
nsISupportsArray *blockSections;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = NS_NewISupportsArray(&blockSections);
|
|
|
|
if ((NS_SUCCEEDED(res)) && blockSections)
|
1999-05-01 02:40:18 +04:00
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetBlockSectionsForRange(aRange, blockSections);
|
|
|
|
if (NS_SUCCEEDED(res))
|
1999-05-01 02:40:18 +04:00
|
|
|
{
|
|
|
|
nsIDOMRange *subRange;
|
1999-05-05 08:05:19 +04:00
|
|
|
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
1999-06-03 10:00:23 +04:00
|
|
|
while (subRange && (NS_SUCCEEDED(res)))
|
1999-05-01 02:40:18 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode>startParent;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = subRange->GetStartParent(getter_AddRefs(startParent));
|
|
|
|
if (NS_SUCCEEDED(res) && startParent)
|
1999-05-01 02:40:18 +04:00
|
|
|
{
|
1999-05-05 08:05:19 +04:00
|
|
|
if (gNoisy) { printf("ReParentContentOfRange calling ReParentContentOfNode\n"); }
|
1999-06-03 10:00:23 +04:00
|
|
|
res = ReParentContentOfNode(startParent, aParentTag, aTranformation);
|
1999-05-01 02:40:18 +04:00
|
|
|
}
|
|
|
|
NS_RELEASE(subRange);
|
1999-05-05 08:05:19 +04:00
|
|
|
blockSections->RemoveElementAt(0);
|
|
|
|
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
1999-05-01 02:40:18 +04:00
|
|
|
}
|
|
|
|
}
|
1999-05-05 08:05:19 +04:00
|
|
|
NS_RELEASE(blockSections);
|
1999-05-01 02:40:18 +04:00
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-04-20 21:47:12 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-05-05 08:05:19 +04:00
|
|
|
nsHTMLEditor::RemoveParagraphStyle()
|
1999-04-20 21:47:12 +04:00
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->RemoveParagraphStyle();
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-04-22 18:45:48 +04:00
|
|
|
if (gNoisy) {
|
1999-05-05 08:05:19 +04:00
|
|
|
printf("---------- nsHTMLEditor::RemoveParagraphStyle ----------\n");
|
1999-04-22 18:45:48 +04:00
|
|
|
}
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res=NS_ERROR_NOT_INITIALIZED;
|
1999-04-22 18:45:48 +04:00
|
|
|
nsCOMPtr<nsIDOMSelection>selection;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if ((NS_SUCCEEDED(res)) && selection)
|
1999-04-22 18:45:48 +04:00
|
|
|
{
|
1999-06-08 10:04:51 +04:00
|
|
|
nsAutoSelectionReset selectionResetter(selection);
|
1999-06-03 10:00:23 +04:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-04-22 18:45:48 +04:00
|
|
|
nsCOMPtr<nsIEnumerator> enumerator;
|
|
|
|
enumerator = do_QueryInterface(selection);
|
|
|
|
if (enumerator)
|
|
|
|
{
|
|
|
|
enumerator->First();
|
|
|
|
nsISupports *currentItem;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = enumerator->CurrentItem(¤tItem);
|
|
|
|
if ((NS_SUCCEEDED(res)) && (nsnull!=currentItem))
|
1999-04-22 18:45:48 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
1999-06-03 10:00:23 +04:00
|
|
|
res = RemoveParagraphStyleFromRange(range);
|
1999-05-05 08:05:19 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-05-05 08:05:19 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::RemoveParagraphStyleFromRange(nsIDOMRange *aRange)
|
|
|
|
{
|
|
|
|
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res;
|
1999-05-05 08:05:19 +04:00
|
|
|
nsISupportsArray *blockSections;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = NS_NewISupportsArray(&blockSections);
|
|
|
|
if ((NS_SUCCEEDED(res)) && blockSections)
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetBlockSectionsForRange(aRange, blockSections);
|
|
|
|
if (NS_SUCCEEDED(res))
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
|
|
|
nsIDOMRange *subRange;
|
|
|
|
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
1999-06-03 10:00:23 +04:00
|
|
|
while (subRange && (NS_SUCCEEDED(res)))
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = RemoveParagraphStyleFromBlockContent(subRange);
|
1999-05-05 08:05:19 +04:00
|
|
|
NS_RELEASE(subRange);
|
|
|
|
blockSections->RemoveElementAt(0);
|
|
|
|
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NS_RELEASE(blockSections);
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-05-05 08:05:19 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::RemoveParagraphStyleFromBlockContent(nsIDOMRange *aRange)
|
|
|
|
{
|
|
|
|
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res;
|
1999-05-05 08:05:19 +04:00
|
|
|
nsCOMPtr<nsIDOMNode>startParent;
|
|
|
|
aRange->GetStartParent(getter_AddRefs(startParent));
|
|
|
|
nsCOMPtr<nsIDOMElement>blockParentElement;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsTextEditor::GetBlockParent(startParent, getter_AddRefs(blockParentElement));
|
|
|
|
while ((NS_SUCCEEDED(res)) && blockParentElement)
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
|
|
|
nsAutoString blockParentTag;
|
|
|
|
blockParentElement->GetTagName(blockParentTag);
|
|
|
|
PRBool isSubordinateBlock;
|
|
|
|
IsSubordinateBlock(blockParentTag, isSubordinateBlock);
|
|
|
|
if (PR_FALSE==isSubordinateBlock) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// go through list backwards so deletes don't interfere with the iteration
|
|
|
|
nsCOMPtr<nsIDOMNodeList> childNodes;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = blockParentElement->GetChildNodes(getter_AddRefs(childNodes));
|
|
|
|
if ((NS_SUCCEEDED(res)) && (childNodes))
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode>grandParent;
|
|
|
|
blockParentElement->GetParentNode(getter_AddRefs(grandParent));
|
|
|
|
PRInt32 offsetInParent;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetChildOffset(blockParentElement, grandParent, offsetInParent);
|
1999-05-05 08:05:19 +04:00
|
|
|
PRUint32 childCount;
|
|
|
|
childNodes->GetLength(&childCount);
|
|
|
|
PRInt32 i=childCount-1;
|
1999-06-03 10:00:23 +04:00
|
|
|
for ( ; ((NS_SUCCEEDED(res)) && (0<=i)); i--)
|
1999-04-22 18:45:48 +04:00
|
|
|
{
|
1999-05-05 08:05:19 +04:00
|
|
|
nsCOMPtr<nsIDOMNode> childNode;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = childNodes->Item(i, getter_AddRefs(childNode));
|
|
|
|
if ((NS_SUCCEEDED(res)) && (childNode))
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsTextEditor::DeleteNode(childNode);
|
|
|
|
if (NS_SUCCEEDED(res)) {
|
|
|
|
res = nsTextEditor::InsertNode(childNode, grandParent, offsetInParent);
|
1999-04-22 18:45:48 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_SUCCEEDED(res)) {
|
|
|
|
res = nsTextEditor::DeleteNode(blockParentElement);
|
1999-05-05 08:05:19 +04:00
|
|
|
}
|
1999-04-22 18:45:48 +04:00
|
|
|
}
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsTextEditor::GetBlockParent(startParent, getter_AddRefs(blockParentElement));
|
1999-04-22 18:45:48 +04:00
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-04-22 18:45:48 +04:00
|
|
|
}
|
|
|
|
|
1999-05-05 08:05:19 +04:00
|
|
|
|
1999-04-22 18:45:48 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::RemoveParent(const nsString &aParentTag)
|
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->RemoveParent(aParentTag);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-04-22 18:45:48 +04:00
|
|
|
if (gNoisy) {
|
1999-05-06 03:29:18 +04:00
|
|
|
printf("---------- nsHTMLEditor::RemoveParent ----------\n");
|
1999-04-22 18:45:48 +04:00
|
|
|
}
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res=NS_ERROR_NOT_INITIALIZED;
|
1999-04-22 18:45:48 +04:00
|
|
|
nsCOMPtr<nsIDOMSelection>selection;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if ((NS_SUCCEEDED(res)) && selection)
|
1999-04-22 18:45:48 +04:00
|
|
|
{
|
1999-06-08 10:04:51 +04:00
|
|
|
nsAutoSelectionReset selectionResetter(selection);
|
1999-06-03 10:00:23 +04:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-04-22 18:45:48 +04:00
|
|
|
nsCOMPtr<nsIEnumerator> enumerator;
|
|
|
|
enumerator = do_QueryInterface(selection);
|
|
|
|
if (enumerator)
|
|
|
|
{
|
|
|
|
enumerator->First();
|
|
|
|
nsISupports *currentItem;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = enumerator->CurrentItem(¤tItem);
|
|
|
|
if ((NS_SUCCEEDED(res)) && (nsnull!=currentItem))
|
1999-04-22 18:45:48 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
1999-06-03 10:00:23 +04:00
|
|
|
res = RemoveParentFromRange(aParentTag, range);
|
1999-05-05 08:05:19 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-05-05 08:05:19 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::RemoveParentFromRange(const nsString &aParentTag, nsIDOMRange *aRange)
|
|
|
|
{
|
|
|
|
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res;
|
1999-05-05 08:05:19 +04:00
|
|
|
nsISupportsArray *blockSections;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = NS_NewISupportsArray(&blockSections);
|
|
|
|
if ((NS_SUCCEEDED(res)) && blockSections)
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetBlockSectionsForRange(aRange, blockSections);
|
|
|
|
if (NS_SUCCEEDED(res))
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
|
|
|
nsIDOMRange *subRange;
|
|
|
|
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
1999-06-03 10:00:23 +04:00
|
|
|
while (subRange && (NS_SUCCEEDED(res)))
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = RemoveParentFromBlockContent(aParentTag, subRange);
|
1999-05-05 08:05:19 +04:00
|
|
|
NS_RELEASE(subRange);
|
|
|
|
blockSections->RemoveElementAt(0);
|
|
|
|
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NS_RELEASE(blockSections);
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-05-05 08:05:19 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::RemoveParentFromBlockContent(const nsString &aParentTag, nsIDOMRange *aRange)
|
|
|
|
{
|
|
|
|
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res;
|
1999-05-05 08:05:19 +04:00
|
|
|
nsCOMPtr<nsIDOMNode>startParent;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = aRange->GetStartParent(getter_AddRefs(startParent));
|
|
|
|
if ((NS_SUCCEEDED(res)) && startParent)
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode>parentNode;
|
|
|
|
nsCOMPtr<nsIDOMElement>parentElement;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = startParent->GetParentNode(getter_AddRefs(parentNode));
|
|
|
|
while ((NS_SUCCEEDED(res)) && parentNode)
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
|
|
|
parentElement = do_QueryInterface(parentNode);
|
|
|
|
nsAutoString parentTag;
|
|
|
|
parentElement->GetTagName(parentTag);
|
|
|
|
PRBool isRoot;
|
|
|
|
IsRootTag(parentTag, isRoot);
|
|
|
|
if (aParentTag.EqualsIgnoreCase(parentTag))
|
|
|
|
{
|
|
|
|
// go through list backwards so deletes don't interfere with the iteration
|
|
|
|
nsCOMPtr<nsIDOMNodeList> childNodes;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = parentElement->GetChildNodes(getter_AddRefs(childNodes));
|
|
|
|
if ((NS_SUCCEEDED(res)) && (childNodes))
|
1999-04-22 18:45:48 +04:00
|
|
|
{
|
1999-05-05 08:05:19 +04:00
|
|
|
nsCOMPtr<nsIDOMNode>grandParent;
|
|
|
|
parentElement->GetParentNode(getter_AddRefs(grandParent));
|
|
|
|
PRInt32 offsetInParent;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetChildOffset(parentElement, grandParent, offsetInParent);
|
1999-05-05 08:05:19 +04:00
|
|
|
PRUint32 childCount;
|
|
|
|
childNodes->GetLength(&childCount);
|
|
|
|
PRInt32 i=childCount-1;
|
1999-06-03 10:00:23 +04:00
|
|
|
for ( ; ((NS_SUCCEEDED(res)) && (0<=i)); i--)
|
1999-05-05 08:05:19 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode> childNode;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = childNodes->Item(i, getter_AddRefs(childNode));
|
|
|
|
if ((NS_SUCCEEDED(res)) && (childNode))
|
1999-04-22 18:45:48 +04:00
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsTextEditor::DeleteNode(childNode);
|
|
|
|
if (NS_SUCCEEDED(res)) {
|
|
|
|
res = nsTextEditor::InsertNode(childNode, grandParent, offsetInParent);
|
1999-04-22 18:45:48 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_SUCCEEDED(res)) {
|
|
|
|
res = nsTextEditor::DeleteNode(parentElement);
|
1999-05-05 08:05:19 +04:00
|
|
|
}
|
1999-04-22 18:45:48 +04:00
|
|
|
}
|
1999-05-05 08:05:19 +04:00
|
|
|
break;
|
1999-04-22 18:45:48 +04:00
|
|
|
}
|
1999-05-05 08:05:19 +04:00
|
|
|
else if (PR_TRUE==isRoot) { // hit a local root node, terminate loop
|
|
|
|
break;
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
res = parentElement->GetParentNode(getter_AddRefs(parentNode));
|
1999-04-22 18:45:48 +04:00
|
|
|
}
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-04-20 21:47:12 +04:00
|
|
|
}
|
|
|
|
|
1999-05-27 04:08:15 +04:00
|
|
|
|
1999-05-27 01:40:51 +04:00
|
|
|
// TODO: Implement "outdent"
|
1999-05-17 16:22:31 +04:00
|
|
|
NS_IMETHODIMP
|
1999-05-17 17:10:29 +04:00
|
|
|
nsHTMLEditor::Indent(const nsString& aIndent)
|
1999-05-17 16:22:31 +04:00
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->Indent(aIndent);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-05-17 16:22:31 +04:00
|
|
|
nsCOMPtr<nsIDOMNode> node;
|
|
|
|
PRInt32 offset;
|
|
|
|
|
|
|
|
// Find out if the selection is collapsed:
|
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res = GetSelection(getter_AddRefs(selection));
|
|
|
|
if (NS_FAILED(res) || !selection) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
|
1999-06-08 10:04:51 +04:00
|
|
|
nsAutoSelectionReset selectionResetter(selection);
|
|
|
|
|
1999-05-17 16:22:31 +04:00
|
|
|
PRBool isCollapsed;
|
|
|
|
res = selection->GetIsCollapsed(&isCollapsed);
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
|
|
|
|
res = GetStartNodeAndOffset(selection, &node, &offset);
|
|
|
|
if (!node) res = NS_ERROR_FAILURE;
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
|
|
|
|
nsAutoString inward("indent");
|
|
|
|
if (aIndent == inward)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (isCollapsed)
|
|
|
|
{
|
|
|
|
// have to find a place to put the blockquote
|
|
|
|
nsCOMPtr<nsIDOMNode> parent = node;
|
|
|
|
nsCOMPtr<nsIDOMNode> topChild = node;
|
|
|
|
nsCOMPtr<nsIDOMNode> tmp;
|
|
|
|
nsAutoString bq("blockquote");
|
|
|
|
while ( !CanContainTag(parent, bq))
|
|
|
|
{
|
|
|
|
parent->GetParentNode(getter_AddRefs(tmp));
|
1999-06-03 10:00:23 +04:00
|
|
|
if (!tmp) return NS_ERROR_FAILURE;
|
1999-05-17 16:22:31 +04:00
|
|
|
topChild = parent;
|
|
|
|
parent = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parent != node)
|
|
|
|
{
|
|
|
|
// we need to split up to the child of parent
|
|
|
|
res = SplitNodeDeep(topChild, node, offset);
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
// topChild already went to the right on the split
|
|
|
|
// so we don't need to add one to offset when figuring
|
|
|
|
// out where to plop list
|
|
|
|
offset = GetIndexOf(parent,topChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
// make a blockquote
|
|
|
|
nsCOMPtr<nsIDOMNode> newBQ;
|
|
|
|
res = CreateNode(bq, parent, offset, getter_AddRefs(newBQ));
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
// put a space in it so layout will draw the list item
|
|
|
|
res = selection->Collapse(newBQ,0);
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
nsAutoString theText(" ");
|
|
|
|
res = InsertText(theText);
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
// reposition selection to before the space character
|
|
|
|
res = GetStartNodeAndOffset(selection, &node, &offset);
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
res = selection->Collapse(node,0);
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-05-27 01:40:51 +04:00
|
|
|
//TODO: IMPLEMENT ALIGNMENT!
|
1999-05-17 16:22:31 +04:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-05-17 17:10:29 +04:00
|
|
|
nsHTMLEditor::Align(const nsString& aAlignType)
|
1999-05-17 16:22:31 +04:00
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->Align(aAlignType);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-05-17 16:22:31 +04:00
|
|
|
nsCOMPtr<nsIDOMNode> node;
|
|
|
|
PRInt32 offset;
|
|
|
|
|
|
|
|
// Find out if the selection is collapsed:
|
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res = GetSelection(getter_AddRefs(selection));
|
|
|
|
if (NS_FAILED(res) || !selection) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
|
1999-06-08 10:04:51 +04:00
|
|
|
nsAutoSelectionReset selectionResetter(selection);
|
|
|
|
|
1999-05-17 16:22:31 +04:00
|
|
|
PRBool isCollapsed;
|
|
|
|
res = selection->GetIsCollapsed(&isCollapsed);
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
|
|
|
|
res = GetStartNodeAndOffset(selection, &node, &offset);
|
|
|
|
if (!node) res = NS_ERROR_FAILURE;
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
|
|
|
|
nsAutoString leftStr("left");
|
|
|
|
if (aAlignType == leftStr)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (isCollapsed)
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-05-17 17:10:29 +04:00
|
|
|
nsHTMLEditor::InsertList(const nsString& aListType)
|
1999-05-17 16:22:31 +04:00
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->InsertList(aListType);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res;
|
|
|
|
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
|
1999-05-17 16:22:31 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
1999-06-03 10:00:23 +04:00
|
|
|
PRBool cancel= PR_FALSE;
|
|
|
|
|
|
|
|
nsAutoEditBatch beginBatching(this);
|
|
|
|
|
|
|
|
// pre-process
|
|
|
|
nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kMakeList);
|
|
|
|
res = mRules->WillDoAction(selection, &ruleInfo, &cancel);
|
|
|
|
if (cancel || (NS_FAILED(res))) return res;
|
|
|
|
|
|
|
|
// Find out if the selection is collapsed:
|
|
|
|
if (NS_FAILED(res) || !selection) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
|
1999-06-08 10:04:51 +04:00
|
|
|
nsAutoSelectionReset selectionResetter(selection);
|
|
|
|
|
1999-05-17 16:22:31 +04:00
|
|
|
PRBool isCollapsed;
|
|
|
|
res = selection->GetIsCollapsed(&isCollapsed);
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNode> node;
|
|
|
|
PRInt32 offset;
|
|
|
|
|
|
|
|
res = GetStartNodeAndOffset(selection, &node, &offset);
|
|
|
|
if (!node) res = NS_ERROR_FAILURE;
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
|
|
|
|
if (isCollapsed)
|
|
|
|
{
|
|
|
|
// have to find a place to put the list
|
|
|
|
nsCOMPtr<nsIDOMNode> parent = node;
|
|
|
|
nsCOMPtr<nsIDOMNode> topChild = node;
|
|
|
|
nsCOMPtr<nsIDOMNode> tmp;
|
|
|
|
|
|
|
|
while ( !CanContainTag(parent, aListType))
|
|
|
|
{
|
|
|
|
parent->GetParentNode(getter_AddRefs(tmp));
|
1999-06-03 10:00:23 +04:00
|
|
|
if (!tmp) return NS_ERROR_FAILURE;
|
1999-05-17 16:22:31 +04:00
|
|
|
topChild = parent;
|
|
|
|
parent = tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parent != node)
|
|
|
|
{
|
|
|
|
// we need to split up to the child of parent
|
|
|
|
res = SplitNodeDeep(topChild, node, offset);
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
// topChild already went to the right on the split
|
|
|
|
// so we don't need to add one to offset when figuring
|
|
|
|
// out where to plop list
|
|
|
|
offset = GetIndexOf(parent,topChild);
|
|
|
|
}
|
|
|
|
|
|
|
|
// make a list
|
|
|
|
nsCOMPtr<nsIDOMNode> newList;
|
|
|
|
res = CreateNode(aListType, parent, offset, getter_AddRefs(newList));
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
// make a list item
|
|
|
|
nsAutoString tag("li");
|
|
|
|
nsCOMPtr<nsIDOMNode> newItem;
|
|
|
|
res = CreateNode(tag, newList, 0, getter_AddRefs(newItem));
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
// put a space in it so layout will draw the list item
|
|
|
|
res = selection->Collapse(newItem,0);
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
nsAutoString theText(" ");
|
|
|
|
res = InsertText(theText);
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
// reposition selection to before the space character
|
|
|
|
res = GetStartNodeAndOffset(selection, &node, &offset);
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
res = selection->Collapse(node,0);
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 16:22:31 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-03-30 02:01:26 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::InsertLink(nsString& aURL)
|
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->InsertLink(aURL);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-03-30 02:01:26 +04:00
|
|
|
|
|
|
|
// Find out if the selection is collapsed:
|
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res = GetSelection(getter_AddRefs(selection));
|
1999-05-17 16:22:31 +04:00
|
|
|
if (NS_FAILED(res) || !selection)
|
1999-03-30 02:01:26 +04:00
|
|
|
{
|
|
|
|
#ifdef DEBUG_akkana
|
|
|
|
printf("Can't get selection!");
|
|
|
|
#endif
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
PRBool isCollapsed;
|
1999-04-13 05:33:32 +04:00
|
|
|
res = selection->GetIsCollapsed(&isCollapsed);
|
1999-05-17 16:22:31 +04:00
|
|
|
if (NS_FAILED(res))
|
1999-03-30 02:01:26 +04:00
|
|
|
isCollapsed = PR_TRUE;
|
|
|
|
|
|
|
|
// Temporary: we need to save the contents of the selection,
|
|
|
|
// then insert them back in as the child of the newly created
|
|
|
|
// anchor node in order to put the link around the selection.
|
|
|
|
// This will require copying the selection into a document fragment,
|
|
|
|
// then splicing the document fragment back into the tree after the
|
|
|
|
// new anchor node has been put in place. As a temporary solution,
|
|
|
|
// Copy/Paste does this for us in the text case
|
|
|
|
// (and eventually in all cases).
|
|
|
|
if (!isCollapsed)
|
|
|
|
(void)Copy();
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNode> newNode;
|
|
|
|
nsAutoString tag("A");
|
|
|
|
res = nsEditor::DeleteSelectionAndCreateNode(tag, getter_AddRefs(newNode));
|
1999-05-17 16:22:31 +04:00
|
|
|
if (NS_FAILED(res) || !newNode)
|
1999-03-30 02:01:26 +04:00
|
|
|
return res;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor (do_QueryInterface(newNode));
|
|
|
|
if (!anchor)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_akkana
|
|
|
|
printf("Not an anchor element\n");
|
|
|
|
#endif
|
|
|
|
return NS_NOINTERFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
res = anchor->SetHref(aURL);
|
1999-05-17 16:22:31 +04:00
|
|
|
if (NS_FAILED(res))
|
1999-03-30 02:01:26 +04:00
|
|
|
{
|
|
|
|
#ifdef DEBUG_akkana
|
|
|
|
printf("SetHref failed");
|
|
|
|
#endif
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set the selection to the node we just inserted:
|
|
|
|
res = GetSelection(getter_AddRefs(selection));
|
1999-05-17 16:22:31 +04:00
|
|
|
if (NS_FAILED(res) || !selection)
|
1999-03-30 02:01:26 +04:00
|
|
|
{
|
|
|
|
#ifdef DEBUG_akkana
|
|
|
|
printf("Can't get selection!");
|
|
|
|
#endif
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
res = selection->Collapse(newNode, 0);
|
1999-05-17 16:22:31 +04:00
|
|
|
if (NS_FAILED(res))
|
1999-03-30 02:01:26 +04:00
|
|
|
{
|
|
|
|
#ifdef DEBUG_akkana
|
|
|
|
printf("Couldn't collapse");
|
|
|
|
#endif
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we weren't collapsed, paste the old selection back in under the link:
|
|
|
|
if (!isCollapsed)
|
|
|
|
(void)Paste();
|
|
|
|
// Otherwise (we were collapsed) insert some bogus text in
|
|
|
|
// so the link will be visible
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nsString link("[***]");
|
|
|
|
(void) InsertText(link); // ignore return value -- we don't care
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::InsertImage(nsString& aURL,
|
|
|
|
nsString& aWidth, nsString& aHeight,
|
|
|
|
nsString& aHspace, nsString& aVspace,
|
|
|
|
nsString& aBorder,
|
|
|
|
nsString& aAlt,
|
|
|
|
nsString& aAlignment)
|
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->InsertImage(aURL, aWidth, aHeight, aHspace, aVspace, aBorder, aAlt, aAlignment);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-04-06 23:49:33 +04:00
|
|
|
nsresult res;
|
1999-03-30 02:01:26 +04:00
|
|
|
nsCOMPtr<nsIDOMNode> newNode;
|
1999-04-30 22:03:39 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMDocument>doc;
|
|
|
|
res = GetDocument(getter_AddRefs(doc));
|
|
|
|
if (NS_SUCCEEDED(res))
|
1999-04-21 22:53:55 +04:00
|
|
|
{
|
1999-04-30 22:03:39 +04:00
|
|
|
nsAutoString tag("IMG");
|
|
|
|
nsCOMPtr<nsIDOMElement>newElement;
|
|
|
|
res = doc->CreateElement(tag, getter_AddRefs(newElement));
|
|
|
|
if (NS_SUCCEEDED(res) && newElement)
|
|
|
|
{
|
|
|
|
newNode = do_QueryInterface(newElement);
|
|
|
|
nsCOMPtr<nsIDOMHTMLImageElement> image (do_QueryInterface(newNode));
|
|
|
|
// Set all the attributes now, before we insert into the tree:
|
|
|
|
if (image)
|
|
|
|
{
|
|
|
|
if (NS_SUCCEEDED(res = image->SetSrc(aURL)))
|
|
|
|
if (NS_SUCCEEDED(res = image->SetWidth(aWidth)))
|
|
|
|
if (NS_SUCCEEDED(res = image->SetHeight(aHeight)))
|
|
|
|
if (NS_SUCCEEDED(res = image->SetAlt(aAlt)))
|
|
|
|
if (NS_SUCCEEDED(res = image->SetBorder(aBorder)))
|
|
|
|
if (NS_SUCCEEDED(res = image->SetAlign(aAlignment)))
|
|
|
|
if (NS_SUCCEEDED(res = image->SetHspace(aHspace)))
|
|
|
|
if (NS_SUCCEEDED(res = image->SetVspace(aVspace)))
|
|
|
|
;
|
|
|
|
}
|
|
|
|
}
|
1999-04-21 22:53:55 +04:00
|
|
|
}
|
1999-04-08 04:46:10 +04:00
|
|
|
|
1999-04-30 22:03:39 +04:00
|
|
|
// If any of these failed, then don't insert the new node into the tree
|
1999-05-17 16:22:31 +04:00
|
|
|
if (NS_FAILED(res))
|
1999-04-06 23:49:33 +04:00
|
|
|
{
|
1999-04-21 22:53:55 +04:00
|
|
|
#ifdef DEBUG_akkana
|
1999-04-30 22:03:39 +04:00
|
|
|
printf("Some failure creating the new image node\n");
|
1999-04-21 22:53:55 +04:00
|
|
|
#endif
|
1999-04-30 22:03:39 +04:00
|
|
|
return res;
|
1999-04-21 22:53:55 +04:00
|
|
|
}
|
|
|
|
|
1999-04-30 22:03:39 +04:00
|
|
|
//
|
|
|
|
// Now we're ready to insert the new image node:
|
|
|
|
// Starting now, don't return without ending the transaction!
|
|
|
|
//
|
1999-06-03 10:00:23 +04:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-04-30 22:03:39 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNode> parentNode;
|
|
|
|
PRInt32 offsetOfNewNode;
|
|
|
|
res = nsEditor::DeleteSelectionAndPrepareToCreateNode(parentNode,
|
|
|
|
offsetOfNewNode);
|
|
|
|
if (NS_SUCCEEDED(res))
|
|
|
|
{
|
|
|
|
// and insert it into the right place in the tree:
|
|
|
|
res = InsertNode(newNode, parentNode, offsetOfNewNode);
|
|
|
|
}
|
1999-04-21 22:53:55 +04:00
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// This should replace InsertLink and InsertImage once it is working
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::GetSelectedElement(const nsString& aTagName, nsIDOMElement** aReturn)
|
|
|
|
{
|
|
|
|
if (!aReturn )
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
*aReturn = nsnull;
|
|
|
|
|
|
|
|
nsAutoString TagName = aTagName;
|
|
|
|
TagName.ToLowerCase();
|
|
|
|
|
|
|
|
//Note that this doesn't need to go through the transaction system
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res=NS_ERROR_NOT_INITIALIZED;
|
1999-06-07 23:32:36 +04:00
|
|
|
//PRBool first=PR_TRUE;
|
1999-04-21 22:53:55 +04:00
|
|
|
nsCOMPtr<nsIDOMSelection>selection;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if (NS_FAILED(res) || !selection)
|
|
|
|
return res;
|
1999-04-21 22:53:55 +04:00
|
|
|
|
|
|
|
PRBool isCollapsed;
|
|
|
|
selection->GetIsCollapsed(&isCollapsed);
|
|
|
|
nsCOMPtr<nsIDOMElement> selectedElement;
|
|
|
|
PRBool bNodeFound = PR_FALSE;
|
|
|
|
|
|
|
|
// Don't bother to examine selection if it is collapsed
|
|
|
|
if (!isCollapsed)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIEnumerator> enumerator;
|
|
|
|
enumerator = do_QueryInterface(selection);
|
|
|
|
if (enumerator)
|
1999-04-08 04:46:10 +04:00
|
|
|
{
|
1999-04-21 22:53:55 +04:00
|
|
|
enumerator->First();
|
|
|
|
nsISupports *currentItem;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = enumerator->CurrentItem(¤tItem);
|
|
|
|
if ((NS_SUCCEEDED(res)) && currentItem)
|
1999-04-08 04:46:10 +04:00
|
|
|
{
|
1999-04-21 22:53:55 +04:00
|
|
|
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
|
|
|
nsCOMPtr<nsIContentIterator> iter;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull,
|
1999-05-28 04:20:41 +04:00
|
|
|
nsIContentIterator::GetIID(),
|
1999-04-21 22:53:55 +04:00
|
|
|
getter_AddRefs(iter));
|
1999-06-03 10:00:23 +04:00
|
|
|
if ((NS_SUCCEEDED(res)) && iter)
|
1999-04-21 22:53:55 +04:00
|
|
|
{
|
|
|
|
iter->Init(range);
|
|
|
|
// loop through the content iterator for each content node
|
|
|
|
nsCOMPtr<nsIContent> content;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = iter->CurrentNode(getter_AddRefs(content));
|
1999-06-07 23:32:36 +04:00
|
|
|
//PRBool bOtherNodeTypeFound = PR_FALSE;
|
1999-04-21 22:53:55 +04:00
|
|
|
|
|
|
|
while (NS_COMFALSE == iter->IsDone())
|
|
|
|
{
|
|
|
|
// Query interface to cast nsIContent to nsIDOMNode
|
|
|
|
// then get tagType to compare to aTagName
|
|
|
|
// Clone node of each desired type and append it to the aDomFrag
|
|
|
|
selectedElement = do_QueryInterface(content);
|
|
|
|
if (selectedElement)
|
|
|
|
{
|
|
|
|
// If we already found a node, then we have another element,
|
|
|
|
// so don't return an element
|
|
|
|
if (bNodeFound)
|
|
|
|
{
|
1999-06-07 23:32:36 +04:00
|
|
|
//bNodeFound;
|
1999-04-21 22:53:55 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString domTagName;
|
|
|
|
selectedElement->GetNodeName(domTagName);
|
1999-05-08 02:26:23 +04:00
|
|
|
domTagName.ToLowerCase();
|
1999-04-21 22:53:55 +04:00
|
|
|
|
|
|
|
// The "A" tag is a pain,
|
|
|
|
// used for both link(href is set) and "Named Anchor"
|
1999-05-27 01:40:51 +04:00
|
|
|
if (TagName == "href" || (TagName == "anchor"))
|
1999-04-21 22:53:55 +04:00
|
|
|
{
|
|
|
|
// We could use GetAttribute, but might as well use anchor element directly
|
|
|
|
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor = do_QueryInterface(selectedElement);
|
|
|
|
if (anchor)
|
|
|
|
{
|
|
|
|
nsString tmpText;
|
1999-05-27 01:40:51 +04:00
|
|
|
if( TagName == "href")
|
1999-04-21 22:53:55 +04:00
|
|
|
{
|
1999-04-22 10:19:44 +04:00
|
|
|
if (NS_SUCCEEDED(anchor->GetHref(tmpText)) && tmpText.GetUnicode() && tmpText.Length() != 0)
|
1999-04-21 22:53:55 +04:00
|
|
|
bNodeFound = PR_TRUE;
|
1999-05-27 01:40:51 +04:00
|
|
|
} else if (TagName == "anchor")
|
1999-04-21 22:53:55 +04:00
|
|
|
{
|
1999-04-22 10:19:44 +04:00
|
|
|
if (NS_SUCCEEDED(anchor->GetName(tmpText)) && tmpText.GetUnicode() && tmpText.Length() != 0)
|
1999-04-21 22:53:55 +04:00
|
|
|
bNodeFound = PR_TRUE;
|
|
|
|
}
|
1999-05-27 01:40:51 +04:00
|
|
|
} else if (TagName == "href")
|
|
|
|
{
|
|
|
|
// Check for a single image is inside a link
|
|
|
|
// It is usually the immediate parent, but lets be sure
|
|
|
|
// by walking up the parents until we find an "A" tag
|
|
|
|
nsCOMPtr<nsIDOMHTMLImageElement> image = do_QueryInterface(selectedElement);
|
|
|
|
if (image)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode> parent;
|
1999-05-27 02:30:50 +04:00
|
|
|
nsCOMPtr<nsIDOMNode> current = do_QueryInterface(selectedElement);
|
1999-05-27 01:40:51 +04:00
|
|
|
PRBool notDone = PR_TRUE;
|
|
|
|
do {
|
1999-06-03 10:00:23 +04:00
|
|
|
res = current->GetParentNode(getter_AddRefs(parent));
|
|
|
|
notDone = NS_SUCCEEDED(res) && parent != nsnull;
|
1999-05-27 01:40:51 +04:00
|
|
|
if(notDone)
|
|
|
|
{
|
|
|
|
nsString tmpText;
|
1999-06-07 23:32:36 +04:00
|
|
|
/*nsCOMPtr<nsIDOMHTMLAnchorElement>*/
|
|
|
|
anchor = do_QueryInterface(parent);
|
1999-05-27 01:40:51 +04:00
|
|
|
if (anchor && NS_SUCCEEDED(anchor->GetHref(tmpText)) && tmpText.GetUnicode() && tmpText.Length() != 0)
|
|
|
|
{
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMElement> link = do_QueryInterface(parent);
|
|
|
|
if (link)
|
|
|
|
{
|
|
|
|
*aReturn =link;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
current = parent;
|
|
|
|
} while (notDone);
|
|
|
|
}
|
1999-04-21 22:53:55 +04:00
|
|
|
}
|
1999-05-27 01:40:51 +04:00
|
|
|
} else if (TagName == domTagName) { // All other tag names are handled here
|
1999-04-21 22:53:55 +04:00
|
|
|
bNodeFound = PR_TRUE;
|
|
|
|
}
|
|
|
|
if (!bNodeFound)
|
|
|
|
{
|
|
|
|
// Check if node we have is really part of the selection???
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1999-04-27 05:10:10 +04:00
|
|
|
iter->Next();
|
1999-04-21 22:53:55 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Should never get here?
|
|
|
|
isCollapsed = PR_TRUE;
|
|
|
|
printf("isCollapsed was FALSE, but no elements found in selection\n");
|
1999-04-08 04:46:10 +04:00
|
|
|
}
|
1999-04-21 22:53:55 +04:00
|
|
|
} else {
|
|
|
|
printf("Could not create enumerator for GetSelectionProperties\n");
|
1999-04-08 04:46:10 +04:00
|
|
|
}
|
1999-04-06 23:49:33 +04:00
|
|
|
}
|
1999-04-21 22:53:55 +04:00
|
|
|
if (bNodeFound)
|
|
|
|
{
|
|
|
|
|
|
|
|
*aReturn = selectedElement;
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-04-21 22:53:55 +04:00
|
|
|
}
|
1999-03-30 02:01:26 +04:00
|
|
|
|
1999-04-21 22:53:55 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::CreateElementWithDefaults(const nsString& aTagName, nsIDOMElement** aReturn)
|
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res=NS_ERROR_NOT_INITIALIZED;
|
1999-04-21 22:53:55 +04:00
|
|
|
if (aReturn)
|
|
|
|
*aReturn = nsnull;
|
|
|
|
|
|
|
|
if (aTagName == "" || !aReturn)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
1999-06-10 04:35:02 +04:00
|
|
|
|
1999-04-21 22:53:55 +04:00
|
|
|
nsAutoString TagName = aTagName;
|
|
|
|
TagName.ToLowerCase();
|
|
|
|
nsAutoString realTagName;
|
|
|
|
|
1999-06-10 04:35:02 +04:00
|
|
|
PRBool isHREF = (TagName == "href");
|
|
|
|
PRBool isAnchor = (TagName == "anchor");
|
1999-04-21 22:53:55 +04:00
|
|
|
if (isHREF || isAnchor)
|
1999-03-30 02:01:26 +04:00
|
|
|
{
|
1999-04-21 22:53:55 +04:00
|
|
|
realTagName = "a";
|
|
|
|
} else {
|
|
|
|
realTagName = TagName;
|
1999-03-30 02:01:26 +04:00
|
|
|
}
|
1999-04-21 22:53:55 +04:00
|
|
|
//We don't use editor's CreateElement because we don't want to
|
|
|
|
// go through the transaction system
|
1999-03-30 02:01:26 +04:00
|
|
|
|
1999-04-21 22:53:55 +04:00
|
|
|
nsCOMPtr<nsIDOMElement>newElement;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = mDoc->CreateElement(realTagName, getter_AddRefs(newElement));
|
|
|
|
if (NS_FAILED(res) || !newElement)
|
1999-04-21 22:53:55 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
1999-04-08 04:46:10 +04:00
|
|
|
|
1999-04-21 22:53:55 +04:00
|
|
|
|
|
|
|
// Set default values for new elements
|
|
|
|
// SHOULD THIS BE PUT IN "RULES" SYSTEM OR
|
|
|
|
// ATTRIBUTES SAVED IN PREFS?
|
|
|
|
if (isAnchor)
|
1999-04-08 04:46:10 +04:00
|
|
|
{
|
1999-04-21 22:53:55 +04:00
|
|
|
// TODO: Get the text of the selection and build a suggested Name
|
|
|
|
// Replace spaces with "_"
|
1999-04-08 04:46:10 +04:00
|
|
|
}
|
1999-04-21 22:53:55 +04:00
|
|
|
// ADD OTHER DEFAULT ATTRIBUTES HERE
|
1999-04-06 23:49:33 +04:00
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-04-21 22:53:55 +04:00
|
|
|
{
|
1999-05-27 01:40:51 +04:00
|
|
|
*aReturn = newElement;
|
1999-04-21 22:53:55 +04:00
|
|
|
}
|
1999-06-10 04:35:02 +04:00
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-03-30 02:01:26 +04:00
|
|
|
}
|
|
|
|
|
1999-04-21 22:53:55 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection, nsIDOMElement** aReturn)
|
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->InsertElement(aElement, aDeleteSelection, aReturn);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res=NS_ERROR_NOT_INITIALIZED;
|
1999-04-21 22:53:55 +04:00
|
|
|
if (aReturn)
|
|
|
|
*aReturn = nsnull;
|
|
|
|
|
|
|
|
if (!aElement || !aReturn)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-04-21 22:53:55 +04:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNode> parentSelectedNode;
|
|
|
|
PRInt32 offsetOfNewNode;
|
|
|
|
|
1999-05-07 04:44:46 +04:00
|
|
|
// Clear current selection.
|
|
|
|
// Should put caret at anchor point?
|
|
|
|
if (!aDeleteSelection)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMSelection>selection;
|
1999-06-07 23:32:36 +04:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
1999-05-07 04:44:46 +04:00
|
|
|
if (NS_SUCCEEDED(res) && selection)
|
|
|
|
{
|
|
|
|
selection->ClearSelection();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-06-10 04:35:02 +04:00
|
|
|
DeleteSelectionAndPrepareToCreateNode(parentSelectedNode, offsetOfNewNode);
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-04-21 22:53:55 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode> newNode = do_QueryInterface(aElement);
|
1999-06-10 04:35:02 +04:00
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
res = InsertNode(aElement, parentSelectedNode, offsetOfNewNode);
|
1999-06-10 04:35:02 +04:00
|
|
|
|
1999-04-21 22:53:55 +04:00
|
|
|
}
|
1999-06-10 04:35:02 +04:00
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-04-21 22:53:55 +04:00
|
|
|
}
|
1999-05-04 02:57:48 +04:00
|
|
|
|
1999-05-08 02:26:23 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::InsertLinkAroundSelection(nsIDOMElement* aAnchorElement)
|
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->InsertLinkAroundSelection(aAnchorElement);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res=NS_ERROR_NULL_POINTER;
|
1999-05-27 01:40:51 +04:00
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
1999-05-08 02:26:23 +04:00
|
|
|
|
1999-05-27 01:40:51 +04:00
|
|
|
// DON'T RETURN EXCEPT AT THE END -- WE NEED TO RELEASE THE aAnchorElement
|
1999-05-08 02:26:23 +04:00
|
|
|
if (!aAnchorElement)
|
1999-05-27 01:40:51 +04:00
|
|
|
goto DELETE_ANCHOR;
|
1999-05-08 02:26:23 +04:00
|
|
|
|
|
|
|
// We must have a real selection
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetSelection(getter_AddRefs(selection));
|
|
|
|
if (NS_FAILED(res) || !selection)
|
1999-05-27 01:40:51 +04:00
|
|
|
goto DELETE_ANCHOR;
|
1999-05-08 02:26:23 +04:00
|
|
|
|
|
|
|
PRBool isCollapsed;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = selection->GetIsCollapsed(&isCollapsed);
|
|
|
|
if (NS_FAILED(res))
|
1999-05-08 02:26:23 +04:00
|
|
|
isCollapsed = PR_TRUE;
|
|
|
|
|
|
|
|
if (isCollapsed)
|
|
|
|
{
|
|
|
|
printf("InsertLinkAroundSelection called but there is no selection!!!\n");
|
1999-06-03 10:00:23 +04:00
|
|
|
res = NS_OK;
|
1999-05-27 01:40:51 +04:00
|
|
|
} else {
|
1999-05-08 02:26:23 +04:00
|
|
|
|
1999-05-27 01:40:51 +04:00
|
|
|
// Be sure we were given an anchor element
|
|
|
|
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor = do_QueryInterface(aAnchorElement);
|
|
|
|
if (anchor)
|
|
|
|
{
|
|
|
|
nsAutoString href;
|
|
|
|
if (NS_SUCCEEDED(anchor->GetHref(href)) && href.GetUnicode() && href.Length() > 0)
|
|
|
|
{
|
1999-06-03 10:00:23 +04:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
|
|
|
const nsString attribute("href");
|
|
|
|
SetTextProperty(nsIEditProperty::a, &attribute, &href);
|
|
|
|
//TODO: Enumerate through other properties of the anchor tag
|
|
|
|
// and set those as well.
|
|
|
|
// Optimization: Modify SetTextProperty to set all attributes at once?
|
1999-05-27 01:40:51 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DELETE_ANCHOR:
|
|
|
|
// We don't insert the element created in CreateElementWithDefaults
|
|
|
|
// into the document like we do in InsertElement,
|
|
|
|
// so shouldn't we have to do this here?
|
|
|
|
// It crashes in JavaScript if we do this!
|
|
|
|
//NS_RELEASE(aAnchorElement);
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-05-27 01:40:51 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
PRBool nsHTMLEditor::IsElementInBody(nsIDOMElement* aElement)
|
|
|
|
{
|
|
|
|
if ( aElement )
|
1999-05-08 02:26:23 +04:00
|
|
|
{
|
1999-05-27 01:40:51 +04:00
|
|
|
nsIDOMElement* bodyElement = nsnull;
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res = nsEditor::GetBodyElement(&bodyElement);
|
|
|
|
if (NS_SUCCEEDED(res) && bodyElement)
|
1999-05-08 02:26:23 +04:00
|
|
|
{
|
1999-05-27 01:40:51 +04:00
|
|
|
nsCOMPtr<nsIDOMNode> parent;
|
|
|
|
nsCOMPtr<nsIDOMNode> currentElement = do_QueryInterface(aElement);
|
|
|
|
if (currentElement)
|
1999-05-08 02:26:23 +04:00
|
|
|
{
|
1999-05-27 01:40:51 +04:00
|
|
|
do {
|
|
|
|
currentElement->GetParentNode(getter_AddRefs(parent));
|
|
|
|
if (parent)
|
|
|
|
{
|
|
|
|
if (parent == bodyElement)
|
|
|
|
return PR_TRUE;
|
|
|
|
|
|
|
|
currentElement = parent;
|
|
|
|
}
|
|
|
|
} while(parent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::SelectElement(nsIDOMElement* aElement)
|
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->SelectElement(aElement);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res = NS_ERROR_NULL_POINTER;
|
1999-05-27 01:40:51 +04:00
|
|
|
|
|
|
|
// Must be sure that element is contained in the document body
|
|
|
|
if (IsElementInBody(aElement))
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if (NS_SUCCEEDED(res) && selection)
|
1999-05-27 01:40:51 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode>parent;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = aElement->GetParentNode(getter_AddRefs(parent));
|
|
|
|
if (NS_SUCCEEDED(res) && parent)
|
1999-05-27 01:40:51 +04:00
|
|
|
{
|
|
|
|
PRInt32 offsetInParent;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetChildOffset(aElement, parent, offsetInParent);
|
1999-05-27 01:40:51 +04:00
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-05-27 01:40:51 +04:00
|
|
|
{
|
|
|
|
// Collapse selection to just before desired element,
|
|
|
|
selection->Collapse(parent, offsetInParent);
|
|
|
|
// then extend it to just after
|
|
|
|
selection->Extend(parent, offsetInParent+1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-05-27 01:40:51 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::SetCaretAfterElement(nsIDOMElement* aElement)
|
|
|
|
{
|
1999-06-10 23:41:40 +04:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->SetCaretAfterElement(aElement);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res = NS_ERROR_NULL_POINTER;
|
1999-05-27 01:40:51 +04:00
|
|
|
|
|
|
|
// Must be sure that element is contained in the document body
|
|
|
|
if (IsElementInBody(aElement))
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if (NS_SUCCEEDED(res) && selection)
|
1999-05-27 01:40:51 +04:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode>parent;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = aElement->GetParentNode(getter_AddRefs(parent));
|
|
|
|
if (NS_SUCCEEDED(res) && parent)
|
1999-05-27 01:40:51 +04:00
|
|
|
{
|
|
|
|
PRInt32 offsetInParent;
|
1999-06-03 10:00:23 +04:00
|
|
|
res = GetChildOffset(aElement, parent, offsetInParent);
|
1999-05-27 01:40:51 +04:00
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-05-27 01:40:51 +04:00
|
|
|
{
|
|
|
|
// Collapse selection to just after desired element,
|
|
|
|
selection->Collapse(parent, offsetInParent+1);
|
|
|
|
}
|
1999-05-08 02:26:23 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-05-08 02:26:23 +04:00
|
|
|
}
|
|
|
|
|
1999-05-17 16:22:31 +04:00
|
|
|
|
|
|
|
PRBool
|
1999-05-17 18:14:36 +04:00
|
|
|
nsHTMLEditor::CanContainTag(nsIDOMNode* aParent, const nsString &aTag)
|
1999-05-17 16:22:31 +04:00
|
|
|
{
|
|
|
|
if (!aParent) return PR_FALSE;
|
|
|
|
|
|
|
|
static nsAutoString ulTag = "ul";
|
|
|
|
static nsAutoString olTag = "ol";
|
|
|
|
static nsAutoString liTag = "li";
|
|
|
|
static nsAutoString bodyTag = "body";
|
|
|
|
static nsAutoString tdTag = "td";
|
|
|
|
static nsAutoString thTag = "th";
|
|
|
|
static nsAutoString bqTag = "blockquote";
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAtom> pTagAtom = GetTag(aParent);
|
|
|
|
nsAutoString pTag;
|
|
|
|
pTagAtom->ToString(pTag);
|
|
|
|
|
|
|
|
// flesh this out...
|
|
|
|
// for now, only lists and blockquotes are using this funct
|
|
|
|
|
|
|
|
if (aTag.EqualsIgnoreCase(ulTag) ||
|
|
|
|
aTag.EqualsIgnoreCase(olTag) )
|
|
|
|
{
|
|
|
|
if (pTag.EqualsIgnoreCase(bodyTag) ||
|
|
|
|
pTag.EqualsIgnoreCase(tdTag) ||
|
|
|
|
pTag.EqualsIgnoreCase(thTag) ||
|
|
|
|
pTag.EqualsIgnoreCase(ulTag) ||
|
|
|
|
pTag.EqualsIgnoreCase(olTag) ||
|
|
|
|
pTag.EqualsIgnoreCase(liTag) ||
|
|
|
|
pTag.EqualsIgnoreCase(bqTag) )
|
|
|
|
{
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (aTag.EqualsIgnoreCase(bqTag) )
|
|
|
|
{
|
|
|
|
if (pTag.EqualsIgnoreCase(bodyTag) ||
|
|
|
|
pTag.EqualsIgnoreCase(tdTag) ||
|
|
|
|
pTag.EqualsIgnoreCase(thTag) ||
|
|
|
|
pTag.EqualsIgnoreCase(liTag) ||
|
|
|
|
pTag.EqualsIgnoreCase(bqTag) )
|
|
|
|
{
|
|
|
|
return PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-05-05 08:05:19 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::IsRootTag(nsString &aTag, PRBool &aIsTag)
|
|
|
|
{
|
|
|
|
static nsAutoString bodyTag = "body";
|
|
|
|
static nsAutoString tdTag = "td";
|
|
|
|
static nsAutoString thTag = "th";
|
|
|
|
static nsAutoString captionTag = "caption";
|
|
|
|
if (PR_TRUE==aTag.EqualsIgnoreCase(bodyTag) ||
|
|
|
|
PR_TRUE==aTag.EqualsIgnoreCase(tdTag) ||
|
|
|
|
PR_TRUE==aTag.EqualsIgnoreCase(thTag) ||
|
|
|
|
PR_TRUE==aTag.EqualsIgnoreCase(captionTag) )
|
|
|
|
{
|
|
|
|
aIsTag = PR_TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
aIsTag = PR_FALSE;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::IsSubordinateBlock(nsString &aTag, PRBool &aIsTag)
|
|
|
|
{
|
|
|
|
static nsAutoString p = "p";
|
|
|
|
static nsAutoString h1 = "h1";
|
|
|
|
static nsAutoString h2 = "h2";
|
|
|
|
static nsAutoString h3 = "h3";
|
|
|
|
static nsAutoString h4 = "h4";
|
|
|
|
static nsAutoString h5 = "h5";
|
|
|
|
static nsAutoString h6 = "h6";
|
|
|
|
static nsAutoString address = "address";
|
|
|
|
static nsAutoString pre = "pre";
|
|
|
|
static nsAutoString li = "li";
|
|
|
|
static nsAutoString dt = "dt";
|
|
|
|
static nsAutoString dd = "dd";
|
|
|
|
if (PR_TRUE==aTag.EqualsIgnoreCase(p) ||
|
|
|
|
PR_TRUE==aTag.EqualsIgnoreCase(h1) ||
|
|
|
|
PR_TRUE==aTag.EqualsIgnoreCase(h2) ||
|
|
|
|
PR_TRUE==aTag.EqualsIgnoreCase(h3) ||
|
|
|
|
PR_TRUE==aTag.EqualsIgnoreCase(h4) ||
|
|
|
|
PR_TRUE==aTag.EqualsIgnoreCase(h5) ||
|
|
|
|
PR_TRUE==aTag.EqualsIgnoreCase(h6) ||
|
|
|
|
PR_TRUE==aTag.EqualsIgnoreCase(address) ||
|
|
|
|
PR_TRUE==aTag.EqualsIgnoreCase(pre) ||
|
|
|
|
PR_TRUE==aTag.EqualsIgnoreCase(li) ||
|
|
|
|
PR_TRUE==aTag.EqualsIgnoreCase(dt) ||
|
|
|
|
PR_TRUE==aTag.EqualsIgnoreCase(dd) )
|
|
|
|
{
|
|
|
|
aIsTag = PR_TRUE;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
aIsTag = PR_FALSE;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-05-04 02:57:48 +04:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::BeginComposition(void)
|
|
|
|
{
|
|
|
|
return nsTextEditor::BeginComposition();
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::EndComposition(void)
|
|
|
|
{
|
|
|
|
return nsTextEditor::EndComposition();
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::SetCompositionString(const nsString& aCompositionString)
|
|
|
|
{
|
|
|
|
return nsTextEditor::SetCompositionString(aCompositionString);
|
1999-05-05 08:05:19 +04:00
|
|
|
}
|
1999-05-27 01:40:51 +04:00
|
|
|
|
|
|
|
// Call the platform-specific file picker and convert it to URL format
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::GetLocalFileURL(nsIDOMWindow* aParent, const nsString& aFilterType, nsString& aReturn)
|
|
|
|
{
|
|
|
|
PRBool htmlFilter = aFilterType.EqualsIgnoreCase("html");
|
|
|
|
PRBool imgFilter = aFilterType.EqualsIgnoreCase("img");
|
|
|
|
|
|
|
|
aReturn = "";
|
|
|
|
|
|
|
|
// TODO: DON'T ACCEPT NULL PARENT AFTER WIDGET IS FIXED
|
|
|
|
if (/*!aParent||*/ !(htmlFilter || imgFilter))
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
|
|
|
|
|
|
|
|
nsCOMPtr<nsIFileWidget> fileWidget;
|
1999-06-10 04:35:02 +04:00
|
|
|
// TODO: WHERE TO WE PUT GLOBAL STRINGS TO BE LOCALIZED?
|
|
|
|
nsString title(htmlFilter ? "Open HTML file" : "Select Image File");
|
1999-05-27 01:40:51 +04:00
|
|
|
nsFileSpec fileSpec;
|
|
|
|
// TODO: GET THE DEFAULT DIRECTORY FOR DIFFERENT TYPES FROM PREFERENCES
|
|
|
|
nsFileSpec aDisplayDirectory;
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
nsresult res = nsComponentManager::CreateInstance(kFileWidgetCID,
|
1999-05-27 01:40:51 +04:00
|
|
|
nsnull,
|
|
|
|
nsIFileWidget::GetIID(),
|
|
|
|
(void**)&fileWidget);
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-05-27 01:40:51 +04:00
|
|
|
{
|
|
|
|
nsFileDlgResults dialogResult;
|
|
|
|
if (htmlFilter)
|
|
|
|
{
|
|
|
|
nsAutoString titles[] = {"HTML Files"};
|
|
|
|
nsAutoString filters[] = {"*.htm; *.html; *.shtml"};
|
|
|
|
fileWidget->SetFilterList(1, titles, filters);
|
|
|
|
dialogResult = fileWidget->GetFile(nsnull, title, fileSpec);
|
|
|
|
} else {
|
|
|
|
nsAutoString titles[] = {"Image Files"};
|
|
|
|
nsAutoString filters[] = {"*.gif; *.jpg; *.jpeg; *.png"};
|
|
|
|
fileWidget->SetFilterList(1, titles, filters);
|
|
|
|
dialogResult = fileWidget->GetFile(nsnull, title, fileSpec);
|
|
|
|
}
|
|
|
|
// Do this after we get this from preferences
|
|
|
|
//fileWidget->SetDisplayDirectory(aDisplayDirectory);
|
|
|
|
// First param should be Parent window, but type is nsIWidget*
|
|
|
|
// Bug is filed to change this to a more suitable window type
|
|
|
|
if (dialogResult != nsFileDlgResults_Cancel)
|
|
|
|
{
|
|
|
|
// Get the platform-specific format
|
|
|
|
// Convert it to the string version of the URL format
|
|
|
|
// NOTE: THIS CRASHES IF fileSpec is empty
|
|
|
|
nsFileURL url(fileSpec);
|
|
|
|
aReturn = url.GetURLString();
|
|
|
|
}
|
|
|
|
// TODO: SAVE THIS TO THE PREFS?
|
|
|
|
fileWidget->GetDisplayDirectory(aDisplayDirectory);
|
|
|
|
}
|
|
|
|
|
1999-06-03 10:00:23 +04:00
|
|
|
return res;
|
1999-05-27 01:40:51 +04:00
|
|
|
}
|
1999-05-27 08:10:04 +04:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::DebugUnitTests(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed)
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
if (!outNumTests || !outNumTestsFailed)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
// first, run the text editor tests (is this appropriate?)
|
|
|
|
nsresult rv = nsTextEditor::DebugUnitTests(outNumTests, outNumTestsFailed);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
// now run our tests
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*outNumTests += 0;
|
|
|
|
*outNumTestsFailed += 0;
|
|
|
|
return NS_OK;
|
|
|
|
#else
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
#endif
|
|
|
|
}
|