1999-03-01 19:54:47 +00: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 08:02:05 +00:00
|
|
|
#include "nsHTMLEditRules.h"
|
1999-03-01 19:54:47 +00:00
|
|
|
#include "nsEditorEventListeners.h"
|
1999-05-07 19:23:17 +00:00
|
|
|
#include "nsInsertHTMLTxn.h"
|
1999-07-04 23:01:10 +00:00
|
|
|
#include "nsIDOMText.h"
|
1999-04-08 00:46:10 +00:00
|
|
|
#include "nsIDOMNodeList.h"
|
1999-03-01 19:54:47 +00:00
|
|
|
#include "nsIDOMDocument.h"
|
1999-06-08 00:02:25 +00:00
|
|
|
#include "nsIDocument.h"
|
1999-03-01 19:54:47 +00:00
|
|
|
#include "nsIDOMEventReceiver.h"
|
|
|
|
#include "nsIDOMKeyListener.h"
|
|
|
|
#include "nsIDOMMouseListener.h"
|
1999-03-29 08:02:05 +00:00
|
|
|
#include "nsIDOMSelection.h"
|
1999-03-29 22:01:26 +00:00
|
|
|
#include "nsIDOMHTMLAnchorElement.h"
|
|
|
|
#include "nsIDOMHTMLImageElement.h"
|
1999-04-20 17:47:12 +00:00
|
|
|
#include "nsIEnumerator.h"
|
1999-04-21 18:53:55 +00:00
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsIContentIterator.h"
|
1999-03-01 19:54:47 +00:00
|
|
|
#include "nsEditorCID.h"
|
1999-04-21 18:53:55 +00:00
|
|
|
#include "nsLayoutCID.h"
|
|
|
|
#include "nsIDOMRange.h"
|
1999-06-10 21:31:42 +00:00
|
|
|
#include "nsIDOMNSRange.h"
|
1999-04-30 22:40:18 +00:00
|
|
|
#include "nsISupportsArray.h"
|
|
|
|
#include "nsVoidArray.h"
|
1999-05-13 20:59:08 +00:00
|
|
|
#include "nsFileSpec.h"
|
1999-03-09 09:44:27 +00:00
|
|
|
#include "nsIComponentManager.h"
|
1999-03-01 19:54:47 +00:00
|
|
|
#include "nsIServiceManager.h"
|
1999-05-26 21:40:51 +00:00
|
|
|
#include "nsWidgetsCID.h"
|
1999-06-07 19:32:36 +00:00
|
|
|
#include "nsIDocumentEncoder.h"
|
1999-06-12 21:22:12 +00:00
|
|
|
#include "nsIPref.h"
|
1999-06-10 21:31:42 +00:00
|
|
|
#include "nsIDOMDocumentFragment.h"
|
1999-06-10 00:35:02 +00:00
|
|
|
#include "nsIPresShell.h"
|
1999-07-19 19:37:08 +00:00
|
|
|
#include "nsIImage.h"
|
|
|
|
|
|
|
|
// Drag & Drop, Clipboard
|
|
|
|
#include "nsWidgetsCID.h"
|
|
|
|
#include "nsIClipboard.h"
|
|
|
|
#include "nsITransferable.h"
|
|
|
|
|
1999-06-12 22:11:59 +00:00
|
|
|
#include "prprf.h"
|
1999-03-01 19:54:47 +00:00
|
|
|
|
1999-07-14 15:24:33 +00:00
|
|
|
const unsigned char nbsp = 160;
|
|
|
|
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
#include "nsJSEditorLog.h"
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-07-19 22:49:21 +00:00
|
|
|
// HACK - CID for NavDTD until we can get at dtd via the document
|
|
|
|
// {a6cf9107-15b3-11d2-932e-00805f8add32}
|
|
|
|
#define NS_CNAVDTD_CID \
|
|
|
|
{ 0xa6cf9107, 0x15b3, 0x11d2, { 0x93, 0x2e, 0x0, 0x80, 0x5f, 0x8a, 0xdd, 0x32 } }
|
|
|
|
static NS_DEFINE_CID(kCNavDTDCID, NS_CNAVDTD_CID);
|
|
|
|
|
1999-03-01 19:54:47 +00: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 18:53:55 +00:00
|
|
|
static NS_DEFINE_CID(kCContentIteratorCID, NS_CONTENTITERATOR_CID);
|
1999-06-08 06:04:51 +00:00
|
|
|
static NS_DEFINE_CID(kCRangeCID, NS_RANGE_CID);
|
|
|
|
static NS_DEFINE_IID(kFileWidgetCID, NS_FILEWIDGET_CID);
|
1999-03-01 19:54:47 +00:00
|
|
|
|
1999-07-19 19:37:08 +00:00
|
|
|
// Drag & Drop, Clipboard Support
|
|
|
|
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
|
|
|
|
static NS_DEFINE_CID(kCTransferableCID, NS_TRANSFERABLE_CID);
|
|
|
|
|
1999-04-20 17:47:12 +00:00
|
|
|
#ifdef NS_DEBUG
|
1999-05-05 04:51:54 +00:00
|
|
|
static PRBool gNoisy = PR_FALSE;
|
1999-04-20 17:47:12 +00:00
|
|
|
#else
|
|
|
|
static const PRBool gNoisy = PR_FALSE;
|
|
|
|
#endif
|
1999-03-01 19:54:47 +00:00
|
|
|
|
1999-06-10 00:35:02 +00:00
|
|
|
|
|
|
|
|
1999-03-01 19:54:47 +00:00
|
|
|
nsHTMLEditor::nsHTMLEditor()
|
|
|
|
{
|
1999-03-05 21:05:35 +00:00
|
|
|
// Done in nsEditor
|
|
|
|
// NS_INIT_REFCNT();
|
1999-06-10 00:35:02 +00:00
|
|
|
}
|
1999-03-01 19:54:47 +00:00
|
|
|
|
|
|
|
nsHTMLEditor::~nsHTMLEditor()
|
|
|
|
{
|
|
|
|
//the autopointers will clear themselves up.
|
1999-03-05 21:05:35 +00: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-10 22:41:18 +00:00
|
|
|
return nsTextEditor::AddRef();
|
1999-03-05 21:05:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//NS_IMPL_RELEASE_INHERITED(Class, Super)
|
|
|
|
NS_IMETHODIMP_(nsrefcnt) nsHTMLEditor::Release(void)
|
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::Release();
|
1999-03-05 21:05:35 +00: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 19:54:47 +00:00
|
|
|
}
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::QueryInterface(aIID, aInstancePtr);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-05 21:05:35 +00: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-28 21:24:18 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::Init(nsIDOMDocument *aDoc,
|
|
|
|
nsIPresShell *aPresShell)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(nsnull!=aDoc && nsnull!=aPresShell, "bad arg");
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res=NS_ERROR_NULL_POINTER;
|
1999-03-01 19:54:47 +00:00
|
|
|
if ((nsnull!=aDoc) && (nsnull!=aPresShell))
|
|
|
|
{
|
1999-07-19 22:49:21 +00:00
|
|
|
res = nsTextEditor::Init(aDoc, aPresShell);
|
|
|
|
if (NS_SUCCEEDED(res))
|
|
|
|
{
|
|
|
|
// Set up a DTD XXX XXX
|
|
|
|
// HACK: This should have happened in a document specific way
|
|
|
|
// in nsEditor::Init(), but we dont' have a way to do that yet
|
|
|
|
res = nsComponentManager::CreateInstance(kCNavDTDCID, nsnull,
|
|
|
|
nsIDTD::GetIID(), getter_AddRefs(mDTD));
|
|
|
|
if (!mDTD) res = NS_ERROR_FAILURE;
|
|
|
|
}
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-29 08:02:05 +00: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 06:06:33 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::SetTextProperty(nsIAtom *aProperty,
|
|
|
|
const nsString *aAttribute,
|
|
|
|
const nsString *aValue)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-04-15 06:06:33 +00:00
|
|
|
return nsTextEditor::SetTextProperty(aProperty, aAttribute, aValue);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-04-15 06:06:33 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::GetTextProperty(nsIAtom *aProperty,
|
|
|
|
const nsString *aAttribute,
|
|
|
|
const nsString *aValue,
|
|
|
|
PRBool &aFirst, PRBool &aAny, PRBool &aAll)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-04-15 06:06:33 +00:00
|
|
|
return nsTextEditor::GetTextProperty(aProperty, aAttribute, aValue, aFirst, aAny, aAll);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-04-15 06:06:33 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::RemoveTextProperty(nsIAtom *aProperty, const nsString *aAttribute)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-04-15 06:06:33 +00:00
|
|
|
return nsTextEditor::RemoveTextProperty(aProperty, aAttribute);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-05-05 23:27:17 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::DeleteSelection(nsIEditor::ECollapsedSelectionAction aAction)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-05-05 23:27:17 +00:00
|
|
|
return nsTextEditor::DeleteSelection(aAction);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-02 05:30:53 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::InsertText(const nsString& aStringToInsert)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::InsertText(aStringToInsert);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-05-26 21:40:51 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::SetBackgroundColor(const nsString& aColor)
|
|
|
|
{
|
1999-07-14 15:24:33 +00:00
|
|
|
// nsresult result;
|
|
|
|
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)
|
|
|
|
|
|
|
|
// Do this only if setting a table or cell background
|
|
|
|
// It will be called in nsTextEditor::SetBackgroundColor for the page background
|
|
|
|
#if 0 //def ENABLE_JS_EDITOR_LOG
|
1999-06-10 19:41:40 +00:00
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->SetBackgroundColor(aColor);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-07-15 18:19:20 +00: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)
|
|
|
|
|
1999-07-14 15:24:33 +00:00
|
|
|
return nsTextEditor::SetBackgroundColor(aColor);
|
1999-05-26 21:40:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::SetBodyAttribute(const nsString& aAttribute, const nsString& aValue)
|
|
|
|
{
|
1999-06-24 20:59:45 +00:00
|
|
|
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->SetBodyAttribute(aAttribute, aValue);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res;
|
1999-05-26 21:40:51 +00: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 06:00:23 +00:00
|
|
|
res = nsEditor::GetBodyElement(getter_AddRefs(bodyElement));
|
|
|
|
if (NS_SUCCEEDED(res) && bodyElement)
|
1999-05-26 21:40:51 +00:00
|
|
|
{
|
1999-06-24 21:17:50 +00:00
|
|
|
// Use the editor's method which goes through the transaction system
|
|
|
|
SetAttribute(bodyElement, aAttribute, aValue);
|
1999-05-26 21:40:51 +00:00
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-05-26 21:40:51 +00:00
|
|
|
}
|
|
|
|
|
1999-03-10 19:49:18 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::InsertBreak()
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->InsertBreak();
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res;
|
1999-03-29 08:02:05 +00:00
|
|
|
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
|
|
|
PRBool cancel= PR_FALSE;
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-03-29 08:02:05 +00:00
|
|
|
|
|
|
|
// pre-process
|
|
|
|
nsEditor::GetSelection(getter_AddRefs(selection));
|
1999-04-12 12:01:32 +00:00
|
|
|
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kInsertBreak);
|
1999-06-03 06:00:23 +00:00
|
|
|
res = mRules->WillDoAction(selection, &ruleInfo, &cancel);
|
|
|
|
if ((PR_FALSE==cancel) && (NS_SUCCEEDED(res)))
|
1999-03-29 08:02:05 +00:00
|
|
|
{
|
|
|
|
// create the new BR node
|
|
|
|
nsCOMPtr<nsIDOMNode> newNode;
|
|
|
|
nsAutoString tag("BR");
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsEditor::DeleteSelectionAndCreateNode(tag, getter_AddRefs(newNode));
|
|
|
|
if (NS_SUCCEEDED(res) && newNode)
|
1999-03-29 08:02:05 +00:00
|
|
|
{
|
|
|
|
// set the selection to the new node
|
|
|
|
nsCOMPtr<nsIDOMNode>parent;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = newNode->GetParentNode(getter_AddRefs(parent));
|
|
|
|
if (NS_SUCCEEDED(res) && parent)
|
1999-03-29 08:02:05 +00: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 06:00:23 +00:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if (NS_SUCCEEDED(res))
|
1999-03-29 08:02:05 +00:00
|
|
|
{
|
|
|
|
if (-1==offsetInParent)
|
|
|
|
{
|
|
|
|
nextNode->GetParentNode(getter_AddRefs(parent));
|
1999-06-03 06:00:23 +00:00
|
|
|
res = GetChildOffset(nextNode, parent, offsetInParent);
|
|
|
|
if (NS_SUCCEEDED(res)) {
|
1999-07-18 02:27:19 +00:00
|
|
|
selection->Collapse(parent, offsetInParent+1); // +1 to insert just after the break
|
1999-03-29 08:02:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-07-18 02:27:19 +00:00
|
|
|
selection->Collapse(nextNode, offsetInParent);
|
1999-03-29 08:02:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// post-process, always called if WillInsertBreak didn't return cancel==PR_TRUE
|
1999-06-03 06:00:23 +00:00
|
|
|
res = mRules->DidDoAction(selection, &ruleInfo, res);
|
1999-03-29 08:02:05 +00: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 13:31:56 +00:00
|
|
|
// HACKForceRedraw();
|
1999-03-29 08:02:05 +00:00
|
|
|
// END HACK
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-05-05 23:29:18 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::GetParagraphFormat(nsString& aParagraphFormat)
|
|
|
|
{
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res = NS_ERROR_NOT_INITIALIZED;
|
1999-05-05 23:29:18 +00:00
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-05-05 23:29:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::SetParagraphFormat(const nsString& aParagraphFormat)
|
|
|
|
{
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->SetParagraphFormat(aParagraphFormat);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res = NS_ERROR_NOT_INITIALIZED;
|
1999-05-05 23:29:18 +00:00
|
|
|
//Kinda sad to waste memory just to force lower case
|
|
|
|
nsAutoString tag = aParagraphFormat;
|
|
|
|
tag.ToLowerCase();
|
|
|
|
if (tag == "normal" || tag == "p") {
|
1999-06-03 06:00:23 +00:00
|
|
|
res = RemoveParagraphStyle();
|
1999-07-04 00:34:58 +00:00
|
|
|
} else if (tag == "li") {
|
|
|
|
res = InsertList("ul");
|
1999-05-05 23:29:18 +00:00
|
|
|
} else {
|
1999-06-03 06:00:23 +00:00
|
|
|
res = ReplaceBlockParent(tag);
|
1999-05-05 23:29:18 +00:00
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-05-05 23:29:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-03-01 19:54:47 +00:00
|
|
|
// Methods shared with the base editor.
|
|
|
|
// Note: We could call each of these via nsTextEditor -- is that better?
|
1999-03-02 05:30:53 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::EnableUndo(PRBool aEnable)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::EnableUndo(aEnable);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-02 05:30:53 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::Undo(PRUint32 aCount)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::Undo(aCount);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-02 05:30:53 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::CanUndo(PRBool &aIsEnabled, PRBool &aCanUndo)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::CanUndo(aIsEnabled, aCanUndo);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-02 05:30:53 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::Redo(PRUint32 aCount)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::Redo(aCount);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-02 05:30:53 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::CanRedo(PRBool &aIsEnabled, PRBool &aCanRedo)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::CanRedo(aIsEnabled, aCanRedo);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-02 05:30:53 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::BeginTransaction()
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::BeginTransaction();
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-02 05:30:53 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::EndTransaction()
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::EndTransaction();
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-02 05:30:53 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::MoveSelectionUp(nsIAtom *aIncrement, PRBool aExtendSelection)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::MoveSelectionUp(aIncrement, aExtendSelection);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-02 05:30:53 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::MoveSelectionDown(nsIAtom *aIncrement, PRBool aExtendSelection)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::MoveSelectionDown(aIncrement, aExtendSelection);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-02 05:30:53 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::MoveSelectionNext(nsIAtom *aIncrement, PRBool aExtendSelection)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::MoveSelectionNext(aIncrement, aExtendSelection);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-02 05:30:53 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::MoveSelectionPrevious(nsIAtom *aIncrement, PRBool aExtendSelection)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::MoveSelectionPrevious(aIncrement, aExtendSelection);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-02 05:30:53 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::SelectNext(nsIAtom *aIncrement, PRBool aExtendSelection)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::SelectNext(aIncrement, aExtendSelection);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-02 05:30:53 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::SelectPrevious(nsIAtom *aIncrement, PRBool aExtendSelection)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::SelectPrevious(aIncrement, aExtendSelection);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-11 19:33:37 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::SelectAll()
|
|
|
|
{
|
|
|
|
return nsTextEditor::SelectAll();
|
|
|
|
}
|
|
|
|
|
1999-06-10 21:31:42 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::BeginningOfDocument()
|
|
|
|
{
|
|
|
|
return nsEditor::BeginningOfDocument();
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::EndOfDocument()
|
|
|
|
{
|
|
|
|
return nsEditor::EndOfDocument();
|
|
|
|
}
|
|
|
|
|
1999-03-02 05:30:53 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::ScrollUp(nsIAtom *aIncrement)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::ScrollUp(aIncrement);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-02 05:30:53 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::ScrollDown(nsIAtom *aIncrement)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::ScrollDown(aIncrement);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-03-02 05:30:53 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::ScrollIntoView(PRBool aScrollToBegin)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::ScrollIntoView(aScrollToBegin);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-05-07 05:02:35 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::Save()
|
|
|
|
{
|
|
|
|
return nsTextEditor::Save();
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::SaveAs(PRBool aSavingCopy)
|
|
|
|
{
|
|
|
|
return nsTextEditor::SaveAs(aSavingCopy);
|
|
|
|
}
|
|
|
|
|
1999-03-10 21:29:41 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::Cut()
|
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::Cut();
|
1999-03-10 21:29:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::Copy()
|
|
|
|
{
|
1999-03-10 22:41:18 +00:00
|
|
|
return nsTextEditor::Copy();
|
1999-03-10 21:29:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::Paste()
|
|
|
|
{
|
1999-07-19 19:37:08 +00:00
|
|
|
#ifdef DEBUG_akkana
|
|
|
|
printf("nsHTMLEditor::Paste()\n");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->Paste();
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
|
|
|
nsIImage * image = nsnull;
|
|
|
|
|
|
|
|
nsString stuffToPaste;
|
|
|
|
|
|
|
|
// Get Clipboard Service
|
|
|
|
nsIClipboard* clipboard;
|
|
|
|
nsresult rv = nsServiceManager::GetService(kCClipboardCID,
|
|
|
|
nsIClipboard::GetIID(),
|
|
|
|
(nsISupports **)&clipboard);
|
|
|
|
|
|
|
|
// Create generic Transferable for getting the data
|
|
|
|
nsCOMPtr<nsITransferable> trans;
|
|
|
|
rv = nsComponentManager::CreateInstance(kCTransferableCID, nsnull,
|
|
|
|
nsITransferable::GetIID(),
|
|
|
|
(void**) getter_AddRefs(trans));
|
|
|
|
if (NS_SUCCEEDED(rv))
|
|
|
|
{
|
|
|
|
// Get the nsITransferable interface for getting the data from the clipboard
|
|
|
|
if (trans)
|
|
|
|
{
|
|
|
|
// Create the desired DataFlavor for the type of data we want to get out of the transferable
|
|
|
|
nsAutoString htmlFlavor(kHTMLMime);
|
|
|
|
nsAutoString textFlavor(kTextMime);
|
|
|
|
nsAutoString imageFlavor(kJPEGImageMime);
|
|
|
|
|
|
|
|
trans->AddDataFlavor(&htmlFlavor);
|
|
|
|
trans->AddDataFlavor(&textFlavor);
|
|
|
|
trans->AddDataFlavor(&imageFlavor);
|
|
|
|
|
|
|
|
// Get the Data from the clipboard
|
|
|
|
if (NS_SUCCEEDED(clipboard->GetData(trans)))
|
|
|
|
{
|
|
|
|
nsAutoString flavor;
|
|
|
|
char * data;
|
|
|
|
PRUint32 len;
|
|
|
|
if (NS_SUCCEEDED(trans->GetAnyTransferData(&flavor, (void **)&data, &len)))
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_akkana
|
|
|
|
printf("Got flavor [%s]\n", flavor.ToNewCString());
|
|
|
|
#endif
|
|
|
|
if (flavor.Equals(htmlFlavor))
|
|
|
|
{
|
|
|
|
if (data && len > 0) // stuffToPaste is ready for insertion into the content
|
|
|
|
{
|
|
|
|
stuffToPaste.SetString(data, len);
|
|
|
|
rv = InsertHTML(stuffToPaste);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (flavor.Equals(textFlavor))
|
|
|
|
{
|
|
|
|
if (data && len > 0) // stuffToPaste is ready for insertion into the content
|
|
|
|
{
|
|
|
|
stuffToPaste.SetString(data, len);
|
|
|
|
rv = InsertText(stuffToPaste);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (flavor.Equals(imageFlavor))
|
|
|
|
{
|
|
|
|
image = (nsIImage *)data;
|
|
|
|
// Insert Image code here
|
|
|
|
NS_RELEASE(image);
|
|
|
|
rv = NS_ERROR_FAILURE; // for now give error code
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nsServiceManager::ReleaseService(kCClipboardCID, clipboard);
|
|
|
|
|
|
|
|
//printf("Trying to insert '%s'\n", stuffToPaste.ToNewCString());
|
|
|
|
|
|
|
|
// Now let InsertText handle the hard stuff:
|
|
|
|
return rv;
|
1999-03-10 21:29:41 +00:00
|
|
|
}
|
|
|
|
|
1999-05-27 00:08:15 +00:00
|
|
|
//
|
|
|
|
// HTML PasteAsQuotation: Paste in a blockquote type=cite
|
|
|
|
//
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::PasteAsQuotation()
|
|
|
|
{
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->PasteAsQuotation();
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-05-27 00:08:15 +00:00
|
|
|
nsAutoString citation("");
|
|
|
|
return PasteAsCitedQuotation(citation);
|
|
|
|
}
|
|
|
|
|
1999-05-28 00:46:34 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::PasteAsCitedQuotation(const nsString& aCitation)
|
1999-05-27 00:08:15 +00:00
|
|
|
{
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->PasteAsCitedQuotation(aCitation);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-05-27 00:08:15 +00:00
|
|
|
nsCOMPtr<nsIDOMNode> newNode;
|
|
|
|
nsAutoString tag("blockquote");
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res = nsEditor::DeleteSelectionAndCreateNode(tag, getter_AddRefs(newNode));
|
1999-05-27 00:08:15 +00: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
|
|
|
|
}
|
|
|
|
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->Collapse(newNode, 0);
|
1999-05-27 00:08:15 +00:00
|
|
|
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 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->InsertAsQuotation(aQuotedText);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-05-27 00:08:15 +00:00
|
|
|
nsAutoString citation ("");
|
|
|
|
return InsertAsCitedQuotation(aQuotedText, citation);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::InsertAsCitedQuotation(const nsString& aQuotedText,
|
1999-05-28 00:46:34 +00:00
|
|
|
const nsString& aCitation)
|
1999-05-27 00:08:15 +00:00
|
|
|
{
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->InsertAsCitedQuotation(aQuotedText, aCitation);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-05-27 00:08:15 +00:00
|
|
|
nsCOMPtr<nsIDOMNode> newNode;
|
|
|
|
nsAutoString tag("blockquote");
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res = nsEditor::DeleteSelectionAndCreateNode(tag, getter_AddRefs(newNode));
|
1999-05-27 00:08:15 +00: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 19:54:47 +00:00
|
|
|
{
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->InsertHTML(aInputString);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-05-05 23:27:17 +00:00
|
|
|
|
1999-06-10 21:31:42 +00:00
|
|
|
nsresult res;
|
|
|
|
nsCOMPtr<nsIDOMNode> parentNode;
|
|
|
|
PRInt32 offsetOfNewNode;
|
|
|
|
res = DeleteSelectionAndPrepareToCreateNode(parentNode, offsetOfNewNode);
|
1999-05-05 23:27:17 +00:00
|
|
|
|
1999-06-10 21:31:42 +00:00
|
|
|
nsCOMPtr<nsIDOMSelection>selection;
|
|
|
|
res = GetSelection(getter_AddRefs(selection));
|
|
|
|
if (NS_FAILED(res))
|
|
|
|
return res;
|
1999-05-07 19:23:17 +00:00
|
|
|
|
1999-06-10 21:31:42 +00:00
|
|
|
// Get the first range in the selection, for context:
|
|
|
|
nsCOMPtr<nsIDOMRange> range;
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->GetRangeAt(0, getter_AddRefs(range));
|
1999-06-10 21:31:42 +00:00
|
|
|
if (NS_FAILED(res))
|
|
|
|
return res;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNSRange> nsrange (do_QueryInterface(range));
|
|
|
|
if (!nsrange)
|
|
|
|
return NS_ERROR_NO_INTERFACE;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMDocumentFragment> docfrag;
|
|
|
|
res = nsrange->CreateContextualFragment(aInputString,
|
|
|
|
getter_AddRefs(docfrag));
|
|
|
|
if (NS_FAILED(res))
|
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
printf("Couldn't create contextual fragment: error was %d\n", res);
|
|
|
|
#endif
|
|
|
|
return res;
|
1999-05-05 23:27:17 +00:00
|
|
|
}
|
|
|
|
|
1999-06-10 21:31:42 +00:00
|
|
|
#if defined(DEBUG_akkana)
|
|
|
|
printf("============ Fragment dump :===========\n");
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> fragc (do_QueryInterface(docfrag));
|
|
|
|
if (!fragc)
|
|
|
|
printf("Couldn't get fragment is nsIContent\n");
|
|
|
|
else
|
|
|
|
fragc->List(stdout);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Insert the contents of the document fragment:
|
|
|
|
nsCOMPtr<nsIDOMNode> fragmentAsNode (do_QueryInterface(docfrag));
|
|
|
|
#define INSERT_FRAGMENT_DIRECTLY 1
|
|
|
|
#ifdef INSERT_FRAGMENT_DIRECTLY
|
|
|
|
// Make a collapsed range pointing to right after the current selection,
|
|
|
|
// and let range gravity keep track of where it is so that we can
|
|
|
|
// set the selection back there after the insert.
|
|
|
|
// Unfortunately this doesn't work right yet.
|
|
|
|
nsCOMPtr<nsIDOMRange> saverange;
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->GetRangeAt(0, getter_AddRefs(saverange));
|
1999-06-10 21:31:42 +00:00
|
|
|
|
|
|
|
// Insert the node:
|
|
|
|
res = InsertNode(fragmentAsNode, parentNode, offsetOfNewNode);
|
|
|
|
|
|
|
|
// Now collapse the selection to the beginning of what we just inserted;
|
|
|
|
// would be better to set it to the end.
|
|
|
|
if (saverange)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode> parent;
|
|
|
|
PRInt32 offset;
|
|
|
|
if (NS_SUCCEEDED(saverange->GetEndParent(getter_AddRefs(parent))))
|
|
|
|
if (NS_SUCCEEDED(saverange->GetEndOffset(&offset)))
|
1999-07-18 02:27:19 +00:00
|
|
|
selection->Collapse(parent, offset);
|
1999-06-10 21:31:42 +00:00
|
|
|
}
|
|
|
|
else
|
1999-07-18 02:27:19 +00:00
|
|
|
selection->Collapse(parentNode, 0/*offsetOfNewNode*/);
|
1999-06-10 21:31:42 +00:00
|
|
|
#else /* INSERT_FRAGMENT_DIRECTLY */
|
|
|
|
// Loop over the contents of the fragment:
|
|
|
|
nsCOMPtr<nsIDOMNode> child;
|
|
|
|
res = fragmentAsNode->GetFirstChild(getter_AddRefS(child));
|
1999-05-17 12:22:31 +00:00
|
|
|
if (NS_FAILED(res))
|
1999-06-10 21:31:42 +00:00
|
|
|
{
|
|
|
|
printf("GetFirstChild failed!\n");
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
while (child)
|
|
|
|
{
|
|
|
|
res = InsertNode(child, parentNode, offsetOfNewNode++);
|
|
|
|
if (NS_FAILED(res))
|
|
|
|
break;
|
|
|
|
nsCOMPtr<nsIDOMNode> nextSib;
|
|
|
|
if (NS_FAILED(child->GetNextSibling(getter_AddRefs(nextSib))))
|
|
|
|
/*break*/;
|
|
|
|
child = nextSib;
|
|
|
|
}
|
|
|
|
if (NS_FAILED(res))
|
|
|
|
return res;
|
1999-05-07 19:23:17 +00:00
|
|
|
|
1999-06-10 21:31:42 +00:00
|
|
|
// Now collapse the selection to the end of what we just inserted:
|
|
|
|
selection->Collapse(parentNode, offsetOfNewNode);
|
|
|
|
#endif /* INSERT_FRAGMENT_DIRECTLY */
|
1999-05-05 23:27:17 +00:00
|
|
|
return res;
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-07-15 18:19:20 +00:00
|
|
|
|
1999-07-14 18:54:29 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::OutputToString(nsString& aOutputString,
|
|
|
|
const nsString& aFormatType,
|
|
|
|
PRUint32 aFlags)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-07-14 18:54:29 +00:00
|
|
|
return nsTextEditor::OutputToString(aOutputString, aFormatType, aFlags);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-07-14 18:54:29 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::OutputToStream(nsIOutputStream* aOutputStream,
|
|
|
|
const nsString& aFormatType,
|
|
|
|
const nsString* aCharset,
|
|
|
|
PRUint32 aFlags)
|
1999-03-01 19:54:47 +00:00
|
|
|
{
|
1999-07-14 18:54:29 +00:00
|
|
|
return nsTextEditor::OutputToStream(aOutputStream, aFormatType,
|
|
|
|
aCharset, aFlags);
|
1999-03-01 19:54:47 +00:00
|
|
|
}
|
|
|
|
|
1999-04-21 18:53:55 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::CopyAttributes(nsIDOMNode *aDestNode, nsIDOMNode *aSourceNode)
|
|
|
|
{
|
|
|
|
return nsTextEditor::CopyAttributes(aDestNode, aSourceNode);
|
|
|
|
}
|
|
|
|
|
1999-07-01 19:32:35 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::ApplyStyleSheet(const nsString& aURL)
|
|
|
|
{
|
|
|
|
return nsTextEditor::ApplyStyleSheet(aURL);
|
|
|
|
}
|
|
|
|
|
1999-03-01 19:54:47 +00:00
|
|
|
//================================================================
|
|
|
|
// HTML Editor methods
|
|
|
|
//
|
|
|
|
// Note: Table Editing methods are implemented in EditTable.cpp
|
|
|
|
//
|
1999-03-29 22:01:26 +00:00
|
|
|
|
1999-04-30 22:40:18 +00:00
|
|
|
// get the paragraph style(s) for the selection
|
1999-04-20 17:47:12 +00:00
|
|
|
NS_IMETHODIMP
|
1999-04-30 22:40:18 +00:00
|
|
|
nsHTMLEditor::GetParagraphStyle(nsStringArray *aTagList)
|
1999-04-20 17:47:12 +00:00
|
|
|
{
|
1999-04-30 22:40:18 +00:00
|
|
|
if (gNoisy) { printf("---------- nsHTMLEditor::GetParagraphStyle ----------\n"); }
|
|
|
|
if (!aTagList) { return NS_ERROR_NULL_POINTER; }
|
1999-04-20 17:47:12 +00:00
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res;
|
1999-04-30 22:40:18 +00:00
|
|
|
nsCOMPtr<nsIDOMSelection>selection;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if ((NS_SUCCEEDED(res)) && selection)
|
1999-04-30 22:40:18 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIEnumerator> enumerator;
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->GetEnumerator(getter_AddRefs(enumerator));
|
1999-07-15 18:19:20 +00:00
|
|
|
if (NS_SUCCEEDED(res) && enumerator)
|
1999-04-30 22:40:18 +00:00
|
|
|
{
|
|
|
|
enumerator->First();
|
|
|
|
nsISupports *currentItem;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = enumerator->CurrentItem(¤tItem);
|
|
|
|
if ((NS_SUCCEEDED(res)) && (nsnull!=currentItem))
|
1999-04-30 22:40:18 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
1999-05-05 04:05:19 +00:00
|
|
|
// scan the range for all the independent block content blockSections
|
1999-04-30 22:40:18 +00:00
|
|
|
// and get the block parent of each
|
1999-05-05 04:05:19 +00:00
|
|
|
nsISupportsArray *blockSections;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = NS_NewISupportsArray(&blockSections);
|
|
|
|
if ((NS_SUCCEEDED(res)) && blockSections)
|
1999-04-30 22:40:18 +00:00
|
|
|
{
|
1999-06-03 06:00:23 +00:00
|
|
|
res = GetBlockSectionsForRange(range, blockSections);
|
|
|
|
if (NS_SUCCEEDED(res))
|
1999-04-30 22:40:18 +00:00
|
|
|
{
|
|
|
|
nsIDOMRange *subRange;
|
1999-05-05 04:05:19 +00:00
|
|
|
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
1999-06-03 06:00:23 +00:00
|
|
|
while (subRange && (NS_SUCCEEDED(res)))
|
1999-04-30 22:40:18 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode>startParent;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = subRange->GetStartParent(getter_AddRefs(startParent));
|
|
|
|
if (NS_SUCCEEDED(res) && startParent)
|
1999-04-30 22:40:18 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMElement> blockParent;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = GetBlockParent(startParent, getter_AddRefs(blockParent));
|
|
|
|
if (NS_SUCCEEDED(res) && blockParent)
|
1999-04-30 22:40:18 +00:00
|
|
|
{
|
|
|
|
nsAutoString blockParentTag;
|
|
|
|
blockParent->GetTagName(blockParentTag);
|
1999-05-05 04:05:19 +00:00
|
|
|
PRBool isRoot;
|
|
|
|
IsRootTag(blockParentTag, isRoot);
|
|
|
|
if ((PR_FALSE==isRoot) && (-1==aTagList->IndexOf(blockParentTag))) {
|
1999-04-30 22:40:18 +00:00
|
|
|
aTagList->AppendString(blockParentTag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NS_RELEASE(subRange);
|
1999-05-05 04:05:19 +00:00
|
|
|
blockSections->RemoveElementAt(0);
|
|
|
|
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
1999-04-30 22:40:18 +00:00
|
|
|
}
|
|
|
|
}
|
1999-05-05 04:05:19 +00:00
|
|
|
NS_RELEASE(blockSections);
|
1999-04-30 22:40:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-04-30 22:40:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// use this when block parents are to be added regardless of current state
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::AddBlockParent(nsString& aParentTag)
|
|
|
|
{
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->AddBlockParent(aParentTag);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-04-20 17:47:12 +00:00
|
|
|
if (gNoisy)
|
|
|
|
{
|
|
|
|
char *tag = aParentTag.ToNewCString();
|
|
|
|
printf("---------- nsHTMLEditor::AddBlockParent %s ----------\n", tag);
|
|
|
|
delete [] tag;
|
|
|
|
}
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res=NS_ERROR_NOT_INITIALIZED;
|
1999-04-20 17:47:12 +00:00
|
|
|
nsCOMPtr<nsIDOMSelection>selection;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if ((NS_SUCCEEDED(res)) && selection)
|
1999-04-20 17:47:12 +00:00
|
|
|
{
|
|
|
|
// set the block parent for all selected ranges
|
1999-06-08 06:04:51 +00:00
|
|
|
nsAutoSelectionReset selectionResetter(selection);
|
1999-06-03 06:00:23 +00:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-04-20 17:47:12 +00:00
|
|
|
nsCOMPtr<nsIEnumerator> enumerator;
|
|
|
|
enumerator = do_QueryInterface(selection);
|
|
|
|
if (enumerator)
|
|
|
|
{
|
|
|
|
enumerator->First();
|
|
|
|
nsISupports *currentItem;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = enumerator->CurrentItem(¤tItem);
|
|
|
|
if ((NS_SUCCEEDED(res)) && (nsnull!=currentItem))
|
1999-04-20 17:47:12 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
1999-05-05 04:05:19 +00:00
|
|
|
// scan the range for all the independent block content blockSections
|
1999-04-30 22:40:18 +00:00
|
|
|
// and apply the transformation to them
|
1999-06-03 06:00:23 +00:00
|
|
|
res = ReParentContentOfRange(range, aParentTag, eInsertParent);
|
1999-04-20 17:47:12 +00:00
|
|
|
}
|
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-04-20 17:47:12 +00: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 06:00:23 +00:00
|
|
|
return res;
|
1999-04-20 17:47:12 +00:00
|
|
|
}
|
|
|
|
|
1999-04-30 22:40:18 +00:00
|
|
|
// use this when a paragraph type is being transformed from one type to another
|
1999-04-20 17:47:12 +00:00
|
|
|
NS_IMETHODIMP
|
1999-04-30 22:40:18 +00:00
|
|
|
nsHTMLEditor::ReplaceBlockParent(nsString& aParentTag)
|
|
|
|
{
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->ReplaceBlockParent(aParentTag);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
1999-04-30 22:40:18 +00:00
|
|
|
|
|
|
|
if (gNoisy)
|
|
|
|
{
|
|
|
|
char *tag = aParentTag.ToNewCString();
|
|
|
|
printf("---------- nsHTMLEditor::ReplaceBlockParent %s ----------\n", tag);
|
|
|
|
delete [] tag;
|
|
|
|
}
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res=NS_ERROR_NOT_INITIALIZED;
|
1999-04-30 22:40:18 +00:00
|
|
|
nsCOMPtr<nsIDOMSelection>selection;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if ((NS_SUCCEEDED(res)) && selection)
|
1999-04-30 22:40:18 +00:00
|
|
|
{
|
1999-06-08 06:04:51 +00:00
|
|
|
nsAutoSelectionReset selectionResetter(selection);
|
1999-04-30 22:40:18 +00:00
|
|
|
// set the block parent for all selected ranges
|
1999-06-03 06:00:23 +00:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-04-30 22:40:18 +00:00
|
|
|
nsCOMPtr<nsIEnumerator> enumerator;
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->GetEnumerator(getter_AddRefs(enumerator));
|
1999-07-15 18:19:20 +00:00
|
|
|
if (NS_SUCCEEDED(res) && enumerator)
|
1999-04-30 22:40:18 +00:00
|
|
|
{
|
|
|
|
enumerator->First();
|
|
|
|
nsISupports *currentItem;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = enumerator->CurrentItem(¤tItem);
|
|
|
|
if ((NS_SUCCEEDED(res)) && (nsnull!=currentItem))
|
1999-04-30 22:40:18 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
1999-05-05 04:05:19 +00:00
|
|
|
// scan the range for all the independent block content blockSections
|
1999-04-30 22:40:18 +00:00
|
|
|
// and apply the transformation to them
|
1999-06-03 06:00:23 +00:00
|
|
|
res = ReParentContentOfRange(range, aParentTag, eReplaceParent);
|
1999-04-30 22:40:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (gNoisy) {printf("Finished nsHTMLEditor::AddBlockParent with this content:\n"); DebugDumpContent(); } // DEBUG
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-04-30 22:40:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::ReParentContentOfNode(nsIDOMNode *aNode,
|
|
|
|
nsString &aParentTag,
|
|
|
|
BlockTransformationType aTransformation)
|
1999-04-20 17:47:12 +00:00
|
|
|
{
|
|
|
|
if (!aNode) { return NS_ERROR_NULL_POINTER; }
|
1999-05-05 04:05:19 +00:00
|
|
|
if (gNoisy)
|
|
|
|
{
|
|
|
|
char *tag = aParentTag.ToNewCString();
|
|
|
|
printf("---------- ReParentContentOfNode(%p,%s,%d) -----------\n", aNode, tag, aTransformation);
|
|
|
|
delete [] tag;
|
|
|
|
}
|
1999-04-21 04:08:43 +00:00
|
|
|
// find the current block parent, or just use aNode if it is a block node
|
1999-04-20 17:47:12 +00:00
|
|
|
nsCOMPtr<nsIDOMElement>blockParentElement;
|
1999-04-21 04:08:43 +00:00
|
|
|
nsCOMPtr<nsIDOMNode>nodeToReParent; // this is the node we'll operate on, by default it's aNode
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res = aNode->QueryInterface(nsIDOMNode::GetIID(), getter_AddRefs(nodeToReParent));
|
1999-04-21 04:08:43 +00: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-04-30 22:40:18 +00:00
|
|
|
// if aNode is the block parent, then the node to reparent is one of its children
|
1999-04-21 04:08:43 +00:00
|
|
|
if (PR_TRUE==nodeIsBlock)
|
|
|
|
{
|
1999-06-03 06:00:23 +00:00
|
|
|
res = aNode->QueryInterface(nsIDOMNode::GetIID(), getter_AddRefs(blockParentElement));
|
|
|
|
if (NS_SUCCEEDED(res) && blockParentElement) {
|
|
|
|
res = aNode->GetFirstChild(getter_AddRefs(nodeToReParent));
|
1999-04-21 04:08:43 +00:00
|
|
|
}
|
|
|
|
}
|
1999-04-30 22:40:18 +00:00
|
|
|
else { // we just need to get the block parent of aNode
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsTextEditor::GetBlockParent(aNode, getter_AddRefs(blockParentElement));
|
1999-04-21 04:08:43 +00:00
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
// at this point, we must have a good res, a node to reparent, and a block parent
|
1999-04-21 04:08:43 +00:00
|
|
|
if (!nodeToReParent) { return NS_ERROR_UNEXPECTED;}
|
|
|
|
if (!blockParentElement) { return NS_ERROR_NULL_POINTER;}
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-04-20 17:47:12 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode> newParentNode;
|
|
|
|
nsCOMPtr<nsIDOMNode> blockParentNode = do_QueryInterface(blockParentElement);
|
1999-04-21 04:08:43 +00:00
|
|
|
// we need to treat nodes directly inside the body differently
|
1999-04-20 17:47:12 +00:00
|
|
|
nsAutoString parentTag;
|
|
|
|
blockParentElement->GetTagName(parentTag);
|
1999-04-30 22:40:18 +00:00
|
|
|
PRBool isRoot;
|
|
|
|
IsRootTag(parentTag, isRoot);
|
|
|
|
if (PR_TRUE==isRoot)
|
1999-04-20 17:47:12 +00:00
|
|
|
{
|
1999-04-30 22:40:18 +00: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 04:08:43 +00:00
|
|
|
nsCOMPtr<nsIDOMCharacterData> nodeAsText = do_QueryInterface(nodeToReParent);
|
1999-04-20 17:47:12 +00:00
|
|
|
if (nodeAsText)
|
|
|
|
{
|
1999-06-03 06:00:23 +00:00
|
|
|
res = ReParentBlockContent(nodeToReParent, aParentTag, blockParentNode, parentTag,
|
1999-04-30 22:40:18 +00:00
|
|
|
aTransformation, getter_AddRefs(newParentNode));
|
1999-04-20 17:47:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{ // this is the case of an insertion point between 2 non-text objects
|
1999-04-30 22:40:18 +00:00
|
|
|
// XXX: how to you know it's an insertion point???
|
1999-04-20 17:47:12 +00:00
|
|
|
PRInt32 offsetInParent=0;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = GetChildOffset(nodeToReParent, blockParentNode, offsetInParent);
|
|
|
|
NS_ASSERTION((NS_SUCCEEDED(res)), "bad res from GetChildOffset");
|
1999-04-20 17:47:12 +00:00
|
|
|
// otherwise, just create the block parent at the selection
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsTextEditor::CreateNode(aParentTag, blockParentNode, offsetInParent,
|
1999-04-20 17:47:12 +00:00
|
|
|
getter_AddRefs(newParentNode));
|
1999-04-30 22:40:18 +00: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 17:47:12 +00:00
|
|
|
// that means, I need to generalize bogus node handling
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
1999-04-30 22:40:18 +00: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 17:47:12 +00:00
|
|
|
{
|
1999-04-30 22:40:18 +00:00
|
|
|
if (gNoisy) { DebugDumpContent(); } // DEBUG
|
1999-06-03 06:00:23 +00:00
|
|
|
res = ReParentBlockContent(nodeToReParent, aParentTag, blockParentNode, parentTag,
|
1999-04-30 22:40:18 +00:00
|
|
|
aTransformation, getter_AddRefs(newParentNode));
|
1999-06-03 06:00:23 +00:00
|
|
|
if ((NS_SUCCEEDED(res)) && (newParentNode) && (eReplaceParent==aTransformation))
|
1999-04-20 17:47:12 +00:00
|
|
|
{
|
|
|
|
PRBool hasChildren;
|
|
|
|
blockParentNode->HasChildNodes(&hasChildren);
|
|
|
|
if (PR_FALSE==hasChildren)
|
|
|
|
{
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsEditor::DeleteNode(blockParentNode);
|
1999-04-20 17:47:12 +00: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 06:00:23 +00:00
|
|
|
return res;
|
1999-04-20 17:47:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::ReParentBlockContent(nsIDOMNode *aNode,
|
|
|
|
nsString &aParentTag,
|
|
|
|
nsIDOMNode *aBlockParentNode,
|
|
|
|
nsString &aBlockParentTag,
|
1999-05-05 04:05:19 +00:00
|
|
|
BlockTransformationType aTransformation,
|
1999-04-20 17:47:12 +00:00
|
|
|
nsIDOMNode **aNewParentNode)
|
|
|
|
{
|
|
|
|
if (!aNode || !aBlockParentNode || !aNewParentNode) { return NS_ERROR_NULL_POINTER; }
|
1999-05-05 04:05:19 +00:00
|
|
|
nsCOMPtr<nsIDOMNode> blockParentNode = do_QueryInterface(aBlockParentNode);
|
|
|
|
PRBool removeBlockParent = PR_FALSE;
|
|
|
|
PRBool removeBreakBefore = PR_FALSE;
|
|
|
|
PRBool removeBreakAfter = PR_FALSE;
|
1999-04-20 17:47:12 +00:00
|
|
|
nsCOMPtr<nsIDOMNode>ancestor;
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res = aNode->GetParentNode(getter_AddRefs(ancestor));
|
1999-04-20 17:47:12 +00:00
|
|
|
nsCOMPtr<nsIDOMNode>previousAncestor = do_QueryInterface(aNode);
|
1999-06-03 06:00:23 +00:00
|
|
|
while (NS_SUCCEEDED(res) && ancestor)
|
1999-04-20 17:47:12 +00: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 06:00:23 +00:00
|
|
|
res = ancestorElement->GetParentNode(getter_AddRefs(ancestor));
|
1999-04-20 17:47:12 +00:00
|
|
|
}
|
|
|
|
// now, previousAncestor is the node we are operating on
|
|
|
|
nsCOMPtr<nsIDOMNode>leftNode, rightNode;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = GetBlockSection(previousAncestor,
|
1999-05-05 04:05:19 +00:00
|
|
|
getter_AddRefs(leftNode),
|
|
|
|
getter_AddRefs(rightNode));
|
1999-06-03 06:00:23 +00:00
|
|
|
if ((NS_SUCCEEDED(res)) && leftNode && rightNode)
|
1999-04-20 17:47:12 +00:00
|
|
|
{
|
1999-05-05 04:05:19 +00: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 17:47:12 +00:00
|
|
|
PRInt32 offsetInParent=0;
|
1999-05-05 04:05:19 +00:00
|
|
|
if (eInsertParent==aTransformation || PR_TRUE==isRootBlock)
|
1999-04-20 17:47:12 +00:00
|
|
|
{
|
1999-06-03 06:00:23 +00: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 04:05:19 +00:00
|
|
|
if (gNoisy) { printf("created a node in blockParentNode at offset %d\n", offsetInParent); }
|
1999-04-20 17:47:12 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode> grandParent;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = blockParentNode->GetParentNode(getter_AddRefs(grandParent));
|
|
|
|
if ((NS_SUCCEEDED(res)) && grandParent)
|
1999-04-20 17:47:12 +00:00
|
|
|
{
|
1999-04-21 04:08:43 +00:00
|
|
|
nsCOMPtr<nsIDOMNode>firstChildNode, lastChildNode;
|
1999-05-05 04:05:19 +00:00
|
|
|
blockParentNode->GetFirstChild(getter_AddRefs(firstChildNode));
|
|
|
|
blockParentNode->GetLastChild(getter_AddRefs(lastChildNode));
|
1999-04-21 04:08:43 +00:00
|
|
|
if (firstChildNode==leftNode && lastChildNode==rightNode)
|
|
|
|
{
|
1999-06-03 06:00:23 +00: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 04:08:43 +00:00
|
|
|
if (gNoisy) { printf("created a node in grandParent at offset %d\n", offsetInParent); }
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1999-05-05 04:05:19 +00: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 06:00:23 +00:00
|
|
|
res = GetChildOffset(leftNode, blockParentNode, offsetInParent);
|
1999-05-05 04:05:19 +00:00
|
|
|
if (gNoisy) { printf("splitting left at %d\n", offsetInParent); }
|
1999-06-03 06:00:23 +00:00
|
|
|
res = SplitNode(blockParentNode, offsetInParent, getter_AddRefs(newLeftNode));
|
1999-05-05 04:05:19 +00:00
|
|
|
// after this split, blockParentNode still contains leftNode and rightNode
|
|
|
|
}
|
|
|
|
if (lastChildNode!=rightNode)
|
|
|
|
{
|
1999-06-03 06:00:23 +00:00
|
|
|
res = GetChildOffset(rightNode, blockParentNode, offsetInParent);
|
1999-05-05 04:05:19 +00:00
|
|
|
offsetInParent++;
|
|
|
|
if (gNoisy) { printf("splitting right at %d\n", offsetInParent); }
|
1999-06-03 06:00:23 +00:00
|
|
|
res = SplitNode(blockParentNode, offsetInParent, getter_AddRefs(newLeftNode));
|
1999-05-05 04:05:19 +00:00
|
|
|
blockParentNode = do_QueryInterface(newLeftNode);
|
|
|
|
}
|
1999-06-03 06:00:23 +00: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 04:05:19 +00: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 04:08:43 +00:00
|
|
|
}
|
1999-04-20 17:47:12 +00:00
|
|
|
}
|
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
if ((NS_SUCCEEDED(res)) && *aNewParentNode)
|
1999-05-05 04:05:19 +00:00
|
|
|
{ // move all the children/contents of blockParentNode to aNewParentNode
|
1999-04-20 17:47:12 +00:00
|
|
|
nsCOMPtr<nsIDOMNode>childNode = do_QueryInterface(rightNode);
|
|
|
|
nsCOMPtr<nsIDOMNode>previousSiblingNode;
|
1999-06-03 06:00:23 +00:00
|
|
|
while (NS_SUCCEEDED(res) && childNode)
|
1999-04-20 17:47:12 +00: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 06:00:23 +00:00
|
|
|
res = nsEditor::DeleteNode(childNode);
|
|
|
|
if (NS_SUCCEEDED(res))
|
1999-04-20 17:47:12 +00:00
|
|
|
{
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsEditor::InsertNode(childNode, *aNewParentNode, 0);
|
1999-04-20 17:47:12 +00: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 04:05:19 +00:00
|
|
|
// clean up the surrounding content to maintain vertical whitespace
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-05-05 04:05:19 +00: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 06:00:23 +00:00
|
|
|
res = GetPriorNode(leftNode, PR_TRUE, getter_AddRefs(brNode));
|
|
|
|
if (NS_SUCCEEDED(res) && brNode)
|
1999-05-05 04:05:19 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIContent> brContent = do_QueryInterface(brNode);
|
|
|
|
if (brContent)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIAtom> brContentTag;
|
|
|
|
brContent->GetTag(*getter_AddRefs(brContentTag));
|
1999-05-05 05:56:58 +00:00
|
|
|
if (nsIEditProperty::br==brContentTag.get()) {
|
1999-06-03 06:00:23 +00:00
|
|
|
res = DeleteNode(brNode);
|
1999-05-05 04:05:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if the next node is a <BR> and we did something to change vertical whitespacing, delete the <BR>
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-05-05 04:05:19 +00:00
|
|
|
{
|
1999-06-03 06:00:23 +00:00
|
|
|
res = GetNextNode(rightNode, PR_TRUE, getter_AddRefs(brNode));
|
|
|
|
if (NS_SUCCEEDED(res) && brNode)
|
1999-05-05 04:05:19 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIContent> brContent = do_QueryInterface(brNode);
|
|
|
|
if (brContent)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIAtom> brContentTag;
|
|
|
|
brContent->GetTag(*getter_AddRefs(brContentTag));
|
1999-05-05 05:56:58 +00:00
|
|
|
if (nsIEditProperty::br==brContentTag.get()) {
|
1999-06-03 06:00:23 +00:00
|
|
|
res = DeleteNode(brNode);
|
1999-05-05 04:05:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
if ((NS_SUCCEEDED(res)) && (PR_TRUE==removeBlockParent))
|
1999-05-05 04:05:19 +00: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 06:00:23 +00:00
|
|
|
res = blockParentNode->GetChildNodes(getter_AddRefs(childNodes));
|
|
|
|
if ((NS_SUCCEEDED(res)) && (childNodes))
|
1999-05-05 04:05:19 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode>grandParent;
|
|
|
|
blockParentNode->GetParentNode(getter_AddRefs(grandParent));
|
1999-06-07 19:32:36 +00:00
|
|
|
//PRInt32 offsetInParent;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = GetChildOffset(blockParentNode, grandParent, offsetInParent);
|
1999-05-05 04:05:19 +00:00
|
|
|
PRUint32 childCount;
|
|
|
|
childNodes->GetLength(&childCount);
|
|
|
|
PRInt32 i=childCount-1;
|
1999-06-03 06:00:23 +00:00
|
|
|
for ( ; ((NS_SUCCEEDED(res)) && (0<=i)); i--)
|
1999-05-05 04:05:19 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode> childNode;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = childNodes->Item(i, getter_AddRefs(childNode));
|
|
|
|
if ((NS_SUCCEEDED(res)) && (childNode))
|
1999-05-05 04:05:19 +00:00
|
|
|
{
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsTextEditor::DeleteNode(childNode);
|
|
|
|
if (NS_SUCCEEDED(res)) {
|
|
|
|
res = nsTextEditor::InsertNode(childNode, grandParent, offsetInParent);
|
1999-05-05 04:05:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (gNoisy) { printf("removing the old block parent %p\n", blockParentNode.get()); }
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsTextEditor::DeleteNode(blockParentNode);
|
1999-05-05 04:05:19 +00:00
|
|
|
}
|
|
|
|
}
|
1999-04-20 17:47:12 +00:00
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-04-20 17:47:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-04-30 22:40:18 +00:00
|
|
|
nsHTMLEditor::ReParentContentOfRange(nsIDOMRange *aRange,
|
|
|
|
nsString &aParentTag,
|
|
|
|
BlockTransformationType aTranformation)
|
1999-04-20 17:47:12 +00:00
|
|
|
{
|
1999-04-30 22:40:18 +00:00
|
|
|
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res;
|
1999-05-05 04:05:19 +00:00
|
|
|
nsISupportsArray *blockSections;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = NS_NewISupportsArray(&blockSections);
|
|
|
|
if ((NS_SUCCEEDED(res)) && blockSections)
|
1999-04-30 22:40:18 +00:00
|
|
|
{
|
1999-06-03 06:00:23 +00:00
|
|
|
res = GetBlockSectionsForRange(aRange, blockSections);
|
|
|
|
if (NS_SUCCEEDED(res))
|
1999-04-30 22:40:18 +00:00
|
|
|
{
|
|
|
|
nsIDOMRange *subRange;
|
1999-05-05 04:05:19 +00:00
|
|
|
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
1999-06-03 06:00:23 +00:00
|
|
|
while (subRange && (NS_SUCCEEDED(res)))
|
1999-04-30 22:40:18 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode>startParent;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = subRange->GetStartParent(getter_AddRefs(startParent));
|
|
|
|
if (NS_SUCCEEDED(res) && startParent)
|
1999-04-30 22:40:18 +00:00
|
|
|
{
|
1999-05-05 04:05:19 +00:00
|
|
|
if (gNoisy) { printf("ReParentContentOfRange calling ReParentContentOfNode\n"); }
|
1999-06-03 06:00:23 +00:00
|
|
|
res = ReParentContentOfNode(startParent, aParentTag, aTranformation);
|
1999-04-30 22:40:18 +00:00
|
|
|
}
|
|
|
|
NS_RELEASE(subRange);
|
1999-05-05 04:05:19 +00:00
|
|
|
blockSections->RemoveElementAt(0);
|
|
|
|
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
1999-04-30 22:40:18 +00:00
|
|
|
}
|
|
|
|
}
|
1999-05-05 04:05:19 +00:00
|
|
|
NS_RELEASE(blockSections);
|
1999-04-30 22:40:18 +00:00
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-04-20 17:47:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-05-05 04:05:19 +00:00
|
|
|
nsHTMLEditor::RemoveParagraphStyle()
|
1999-04-20 17:47:12 +00:00
|
|
|
{
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->RemoveParagraphStyle();
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-04-22 14:45:48 +00:00
|
|
|
if (gNoisy) {
|
1999-05-05 04:05:19 +00:00
|
|
|
printf("---------- nsHTMLEditor::RemoveParagraphStyle ----------\n");
|
1999-04-22 14:45:48 +00:00
|
|
|
}
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res=NS_ERROR_NOT_INITIALIZED;
|
1999-04-22 14:45:48 +00:00
|
|
|
nsCOMPtr<nsIDOMSelection>selection;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if ((NS_SUCCEEDED(res)) && selection)
|
1999-04-22 14:45:48 +00:00
|
|
|
{
|
1999-06-08 06:04:51 +00:00
|
|
|
nsAutoSelectionReset selectionResetter(selection);
|
1999-06-03 06:00:23 +00:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-04-22 14:45:48 +00:00
|
|
|
nsCOMPtr<nsIEnumerator> enumerator;
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->GetEnumerator(getter_AddRefs(enumerator));
|
1999-07-15 18:19:20 +00:00
|
|
|
if (NS_SUCCEEDED(res) && enumerator)
|
1999-04-22 14:45:48 +00:00
|
|
|
{
|
|
|
|
enumerator->First();
|
|
|
|
nsISupports *currentItem;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = enumerator->CurrentItem(¤tItem);
|
|
|
|
if ((NS_SUCCEEDED(res)) && (nsnull!=currentItem))
|
1999-04-22 14:45:48 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
1999-06-03 06:00:23 +00:00
|
|
|
res = RemoveParagraphStyleFromRange(range);
|
1999-05-05 04:05:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-05-05 04:05:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::RemoveParagraphStyleFromRange(nsIDOMRange *aRange)
|
|
|
|
{
|
|
|
|
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res;
|
1999-05-05 04:05:19 +00:00
|
|
|
nsISupportsArray *blockSections;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = NS_NewISupportsArray(&blockSections);
|
|
|
|
if ((NS_SUCCEEDED(res)) && blockSections)
|
1999-05-05 04:05:19 +00:00
|
|
|
{
|
1999-06-03 06:00:23 +00:00
|
|
|
res = GetBlockSectionsForRange(aRange, blockSections);
|
|
|
|
if (NS_SUCCEEDED(res))
|
1999-05-05 04:05:19 +00:00
|
|
|
{
|
|
|
|
nsIDOMRange *subRange;
|
|
|
|
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
1999-06-03 06:00:23 +00:00
|
|
|
while (subRange && (NS_SUCCEEDED(res)))
|
1999-05-05 04:05:19 +00:00
|
|
|
{
|
1999-06-03 06:00:23 +00:00
|
|
|
res = RemoveParagraphStyleFromBlockContent(subRange);
|
1999-05-05 04:05:19 +00:00
|
|
|
NS_RELEASE(subRange);
|
|
|
|
blockSections->RemoveElementAt(0);
|
|
|
|
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NS_RELEASE(blockSections);
|
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-05-05 04:05:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::RemoveParagraphStyleFromBlockContent(nsIDOMRange *aRange)
|
|
|
|
{
|
|
|
|
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res;
|
1999-05-05 04:05:19 +00:00
|
|
|
nsCOMPtr<nsIDOMNode>startParent;
|
|
|
|
aRange->GetStartParent(getter_AddRefs(startParent));
|
|
|
|
nsCOMPtr<nsIDOMElement>blockParentElement;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsTextEditor::GetBlockParent(startParent, getter_AddRefs(blockParentElement));
|
|
|
|
while ((NS_SUCCEEDED(res)) && blockParentElement)
|
1999-05-05 04:05:19 +00: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 06:00:23 +00:00
|
|
|
res = blockParentElement->GetChildNodes(getter_AddRefs(childNodes));
|
|
|
|
if ((NS_SUCCEEDED(res)) && (childNodes))
|
1999-05-05 04:05:19 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode>grandParent;
|
|
|
|
blockParentElement->GetParentNode(getter_AddRefs(grandParent));
|
|
|
|
PRInt32 offsetInParent;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = GetChildOffset(blockParentElement, grandParent, offsetInParent);
|
1999-05-05 04:05:19 +00:00
|
|
|
PRUint32 childCount;
|
|
|
|
childNodes->GetLength(&childCount);
|
|
|
|
PRInt32 i=childCount-1;
|
1999-06-03 06:00:23 +00:00
|
|
|
for ( ; ((NS_SUCCEEDED(res)) && (0<=i)); i--)
|
1999-04-22 14:45:48 +00:00
|
|
|
{
|
1999-05-05 04:05:19 +00:00
|
|
|
nsCOMPtr<nsIDOMNode> childNode;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = childNodes->Item(i, getter_AddRefs(childNode));
|
|
|
|
if ((NS_SUCCEEDED(res)) && (childNode))
|
1999-05-05 04:05:19 +00:00
|
|
|
{
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsTextEditor::DeleteNode(childNode);
|
|
|
|
if (NS_SUCCEEDED(res)) {
|
|
|
|
res = nsTextEditor::InsertNode(childNode, grandParent, offsetInParent);
|
1999-04-22 14:45:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_SUCCEEDED(res)) {
|
|
|
|
res = nsTextEditor::DeleteNode(blockParentElement);
|
1999-05-05 04:05:19 +00:00
|
|
|
}
|
1999-04-22 14:45:48 +00:00
|
|
|
}
|
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsTextEditor::GetBlockParent(startParent, getter_AddRefs(blockParentElement));
|
1999-04-22 14:45:48 +00:00
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-04-22 14:45:48 +00:00
|
|
|
}
|
|
|
|
|
1999-05-05 04:05:19 +00:00
|
|
|
|
1999-04-22 14:45:48 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::RemoveParent(const nsString &aParentTag)
|
|
|
|
{
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->RemoveParent(aParentTag);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-04-22 14:45:48 +00:00
|
|
|
if (gNoisy) {
|
1999-05-05 23:29:18 +00:00
|
|
|
printf("---------- nsHTMLEditor::RemoveParent ----------\n");
|
1999-04-22 14:45:48 +00:00
|
|
|
}
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res=NS_ERROR_NOT_INITIALIZED;
|
1999-04-22 14:45:48 +00:00
|
|
|
nsCOMPtr<nsIDOMSelection>selection;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if ((NS_SUCCEEDED(res)) && selection)
|
1999-04-22 14:45:48 +00:00
|
|
|
{
|
1999-06-08 06:04:51 +00:00
|
|
|
nsAutoSelectionReset selectionResetter(selection);
|
1999-06-03 06:00:23 +00:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-04-22 14:45:48 +00:00
|
|
|
nsCOMPtr<nsIEnumerator> enumerator;
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->GetEnumerator(getter_AddRefs(enumerator));
|
1999-07-15 18:19:20 +00:00
|
|
|
if (NS_SUCCEEDED(res) && enumerator)
|
1999-04-22 14:45:48 +00:00
|
|
|
{
|
|
|
|
enumerator->First();
|
|
|
|
nsISupports *currentItem;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = enumerator->CurrentItem(¤tItem);
|
|
|
|
if ((NS_SUCCEEDED(res)) && (nsnull!=currentItem))
|
1999-04-22 14:45:48 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
1999-06-03 06:00:23 +00:00
|
|
|
res = RemoveParentFromRange(aParentTag, range);
|
1999-05-05 04:05:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-05-05 04:05:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::RemoveParentFromRange(const nsString &aParentTag, nsIDOMRange *aRange)
|
|
|
|
{
|
|
|
|
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res;
|
1999-05-05 04:05:19 +00:00
|
|
|
nsISupportsArray *blockSections;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = NS_NewISupportsArray(&blockSections);
|
|
|
|
if ((NS_SUCCEEDED(res)) && blockSections)
|
1999-05-05 04:05:19 +00:00
|
|
|
{
|
1999-06-03 06:00:23 +00:00
|
|
|
res = GetBlockSectionsForRange(aRange, blockSections);
|
|
|
|
if (NS_SUCCEEDED(res))
|
1999-05-05 04:05:19 +00:00
|
|
|
{
|
|
|
|
nsIDOMRange *subRange;
|
|
|
|
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
1999-06-03 06:00:23 +00:00
|
|
|
while (subRange && (NS_SUCCEEDED(res)))
|
1999-05-05 04:05:19 +00:00
|
|
|
{
|
1999-06-03 06:00:23 +00:00
|
|
|
res = RemoveParentFromBlockContent(aParentTag, subRange);
|
1999-05-05 04:05:19 +00:00
|
|
|
NS_RELEASE(subRange);
|
|
|
|
blockSections->RemoveElementAt(0);
|
|
|
|
subRange = (nsIDOMRange *)(blockSections->ElementAt(0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
NS_RELEASE(blockSections);
|
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-05-05 04:05:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::RemoveParentFromBlockContent(const nsString &aParentTag, nsIDOMRange *aRange)
|
|
|
|
{
|
|
|
|
if (!aRange) { return NS_ERROR_NULL_POINTER; }
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res;
|
1999-05-05 04:05:19 +00:00
|
|
|
nsCOMPtr<nsIDOMNode>startParent;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = aRange->GetStartParent(getter_AddRefs(startParent));
|
|
|
|
if ((NS_SUCCEEDED(res)) && startParent)
|
1999-05-05 04:05:19 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode>parentNode;
|
|
|
|
nsCOMPtr<nsIDOMElement>parentElement;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = startParent->GetParentNode(getter_AddRefs(parentNode));
|
|
|
|
while ((NS_SUCCEEDED(res)) && parentNode)
|
1999-05-05 04:05:19 +00: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 06:00:23 +00:00
|
|
|
res = parentElement->GetChildNodes(getter_AddRefs(childNodes));
|
|
|
|
if ((NS_SUCCEEDED(res)) && (childNodes))
|
1999-04-22 14:45:48 +00:00
|
|
|
{
|
1999-05-05 04:05:19 +00:00
|
|
|
nsCOMPtr<nsIDOMNode>grandParent;
|
|
|
|
parentElement->GetParentNode(getter_AddRefs(grandParent));
|
|
|
|
PRInt32 offsetInParent;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = GetChildOffset(parentElement, grandParent, offsetInParent);
|
1999-05-05 04:05:19 +00:00
|
|
|
PRUint32 childCount;
|
|
|
|
childNodes->GetLength(&childCount);
|
|
|
|
PRInt32 i=childCount-1;
|
1999-06-03 06:00:23 +00:00
|
|
|
for ( ; ((NS_SUCCEEDED(res)) && (0<=i)); i--)
|
1999-05-05 04:05:19 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode> childNode;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = childNodes->Item(i, getter_AddRefs(childNode));
|
|
|
|
if ((NS_SUCCEEDED(res)) && (childNode))
|
1999-04-22 14:45:48 +00:00
|
|
|
{
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsTextEditor::DeleteNode(childNode);
|
|
|
|
if (NS_SUCCEEDED(res)) {
|
|
|
|
res = nsTextEditor::InsertNode(childNode, grandParent, offsetInParent);
|
1999-04-22 14:45:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_SUCCEEDED(res)) {
|
|
|
|
res = nsTextEditor::DeleteNode(parentElement);
|
1999-05-05 04:05:19 +00:00
|
|
|
}
|
1999-04-22 14:45:48 +00:00
|
|
|
}
|
1999-05-05 04:05:19 +00:00
|
|
|
break;
|
1999-04-22 14:45:48 +00:00
|
|
|
}
|
1999-05-05 04:05:19 +00:00
|
|
|
else if (PR_TRUE==isRoot) { // hit a local root node, terminate loop
|
|
|
|
break;
|
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
res = parentElement->GetParentNode(getter_AddRefs(parentNode));
|
1999-04-22 14:45:48 +00:00
|
|
|
}
|
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-04-20 17:47:12 +00:00
|
|
|
}
|
|
|
|
|
1999-05-27 00:08:15 +00:00
|
|
|
|
1999-05-26 21:40:51 +00:00
|
|
|
// TODO: Implement "outdent"
|
1999-05-17 12:22:31 +00:00
|
|
|
NS_IMETHODIMP
|
1999-05-17 13:10:29 +00:00
|
|
|
nsHTMLEditor::Indent(const nsString& aIndent)
|
1999-05-17 12:22:31 +00:00
|
|
|
{
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->Indent(aIndent);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
1999-06-16 05:02:43 +00:00
|
|
|
|
|
|
|
nsresult res;
|
|
|
|
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
|
|
|
|
|
|
|
|
PRBool cancel= PR_FALSE;
|
1999-06-10 19:41:40 +00:00
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-05-17 12:22:31 +00:00
|
|
|
|
1999-06-16 05:02:43 +00:00
|
|
|
// pre-process
|
1999-05-17 12:22:31 +00:00
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
1999-06-16 05:02:43 +00:00
|
|
|
nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kIndent);
|
|
|
|
if (aIndent == "outdent")
|
|
|
|
ruleInfo.action = nsHTMLEditRules::kOutdent;
|
|
|
|
res = mRules->WillDoAction(selection, &ruleInfo, &cancel);
|
|
|
|
if (cancel || (NS_FAILED(res))) return res;
|
|
|
|
|
|
|
|
// Do default - insert a blockquote node if selection collapsed
|
|
|
|
nsCOMPtr<nsIDOMNode> node;
|
|
|
|
PRInt32 offset;
|
1999-05-17 12:22:31 +00:00
|
|
|
PRBool isCollapsed;
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->GetIsCollapsed(&isCollapsed);
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 12:22:31 +00:00
|
|
|
|
|
|
|
res = GetStartNodeAndOffset(selection, &node, &offset);
|
|
|
|
if (!node) res = NS_ERROR_FAILURE;
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 12:22:31 +00: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 06:00:23 +00:00
|
|
|
if (!tmp) return NS_ERROR_FAILURE;
|
1999-05-17 12:22:31 +00: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 06:00:23 +00:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 12:22:31 +00: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 06:00:23 +00:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 12:22:31 +00:00
|
|
|
// put a space in it so layout will draw the list item
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->Collapse(newBQ,0);
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 12:22:31 +00:00
|
|
|
nsAutoString theText(" ");
|
|
|
|
res = InsertText(theText);
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 12:22:31 +00:00
|
|
|
// reposition selection to before the space character
|
|
|
|
res = GetStartNodeAndOffset(selection, &node, &offset);
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->Collapse(node,0);
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 12:22:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-06-16 05:02:43 +00:00
|
|
|
return res;
|
1999-05-17 12:22:31 +00:00
|
|
|
}
|
|
|
|
|
1999-05-26 21:40:51 +00:00
|
|
|
//TODO: IMPLEMENT ALIGNMENT!
|
1999-05-17 12:22:31 +00:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-05-17 13:10:29 +00:00
|
|
|
nsHTMLEditor::Align(const nsString& aAlignType)
|
1999-05-17 12:22:31 +00:00
|
|
|
{
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->Align(aAlignType);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-05-17 12:22:31 +00:00
|
|
|
nsCOMPtr<nsIDOMNode> node;
|
1999-06-16 05:02:43 +00:00
|
|
|
PRBool cancel= PR_FALSE;
|
1999-05-17 12:22:31 +00:00
|
|
|
|
|
|
|
// Find out if the selection is collapsed:
|
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res = GetSelection(getter_AddRefs(selection));
|
|
|
|
if (NS_FAILED(res) || !selection) return res;
|
1999-06-16 05:02:43 +00:00
|
|
|
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kAlign);
|
|
|
|
ruleInfo.alignType = &aAlignType;
|
|
|
|
res = mRules->WillDoAction(selection, &ruleInfo, &cancel);
|
1999-05-17 12:22:31 +00:00
|
|
|
|
1999-06-16 05:02:43 +00:00
|
|
|
return res;
|
1999-05-17 12:22:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
1999-05-17 13:10:29 +00:00
|
|
|
nsHTMLEditor::InsertList(const nsString& aListType)
|
1999-05-17 12:22:31 +00:00
|
|
|
{
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->InsertList(aListType);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res;
|
|
|
|
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
|
1999-05-17 12:22:31 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
1999-06-03 06:00:23 +00:00
|
|
|
PRBool cancel= PR_FALSE;
|
|
|
|
|
|
|
|
nsAutoEditBatch beginBatching(this);
|
|
|
|
|
|
|
|
// pre-process
|
|
|
|
nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kMakeList);
|
1999-06-16 05:02:43 +00:00
|
|
|
if (aListType == "ol") ruleInfo.bOrdered = PR_TRUE;
|
|
|
|
else ruleInfo.bOrdered = PR_FALSE;
|
1999-06-03 06:00:23 +00:00
|
|
|
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 12:22:31 +00:00
|
|
|
|
|
|
|
PRBool isCollapsed;
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->GetIsCollapsed(&isCollapsed);
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 12:22:31 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNode> node;
|
|
|
|
PRInt32 offset;
|
|
|
|
|
|
|
|
res = GetStartNodeAndOffset(selection, &node, &offset);
|
|
|
|
if (!node) res = NS_ERROR_FAILURE;
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 12:22:31 +00: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 06:00:23 +00:00
|
|
|
if (!tmp) return NS_ERROR_FAILURE;
|
1999-05-17 12:22:31 +00: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 06:00:23 +00:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 12:22:31 +00: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 06:00:23 +00:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 12:22:31 +00:00
|
|
|
// make a list item
|
|
|
|
nsAutoString tag("li");
|
|
|
|
nsCOMPtr<nsIDOMNode> newItem;
|
|
|
|
res = CreateNode(tag, newList, 0, getter_AddRefs(newItem));
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 12:22:31 +00:00
|
|
|
// put a space in it so layout will draw the list item
|
1999-06-16 05:02:43 +00:00
|
|
|
// XXX - revisit when layout is fixed
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->Collapse(newItem,0);
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 12:22:31 +00:00
|
|
|
nsAutoString theText(" ");
|
|
|
|
res = InsertText(theText);
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 12:22:31 +00:00
|
|
|
// reposition selection to before the space character
|
|
|
|
res = GetStartNodeAndOffset(selection, &node, &offset);
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->Collapse(node,0);
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_FAILED(res)) return res;
|
1999-05-17 12:22:31 +00:00
|
|
|
}
|
|
|
|
|
1999-06-16 05:02:43 +00:00
|
|
|
return res;
|
1999-05-17 12:22:31 +00:00
|
|
|
}
|
|
|
|
|
1999-03-29 22:01:26 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::InsertLink(nsString& aURL)
|
|
|
|
{
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->InsertLink(aURL);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-03-29 22:01:26 +00:00
|
|
|
|
|
|
|
// Find out if the selection is collapsed:
|
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res = GetSelection(getter_AddRefs(selection));
|
1999-05-17 12:22:31 +00:00
|
|
|
if (NS_FAILED(res) || !selection)
|
1999-03-29 22:01:26 +00:00
|
|
|
{
|
|
|
|
#ifdef DEBUG_akkana
|
|
|
|
printf("Can't get selection!");
|
|
|
|
#endif
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
PRBool isCollapsed;
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->GetIsCollapsed(&isCollapsed);
|
1999-05-17 12:22:31 +00:00
|
|
|
if (NS_FAILED(res))
|
1999-03-29 22:01:26 +00: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 12:22:31 +00:00
|
|
|
if (NS_FAILED(res) || !newNode)
|
1999-03-29 22:01:26 +00: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 12:22:31 +00:00
|
|
|
if (NS_FAILED(res))
|
1999-03-29 22:01:26 +00: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 12:22:31 +00:00
|
|
|
if (NS_FAILED(res) || !selection)
|
1999-03-29 22:01:26 +00:00
|
|
|
{
|
|
|
|
#ifdef DEBUG_akkana
|
|
|
|
printf("Can't get selection!");
|
|
|
|
#endif
|
|
|
|
return res;
|
|
|
|
}
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->Collapse(newNode, 0);
|
1999-05-17 12:22:31 +00:00
|
|
|
if (NS_FAILED(res))
|
1999-03-29 22:01:26 +00: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 19:41:40 +00: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 19:49:33 +00:00
|
|
|
nsresult res;
|
1999-03-29 22:01:26 +00:00
|
|
|
nsCOMPtr<nsIDOMNode> newNode;
|
1999-04-30 18:03:39 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMDocument>doc;
|
|
|
|
res = GetDocument(getter_AddRefs(doc));
|
|
|
|
if (NS_SUCCEEDED(res))
|
1999-04-21 18:53:55 +00:00
|
|
|
{
|
1999-04-30 18:03:39 +00: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 18:53:55 +00:00
|
|
|
}
|
1999-04-08 00:46:10 +00:00
|
|
|
|
1999-04-30 18:03:39 +00:00
|
|
|
// If any of these failed, then don't insert the new node into the tree
|
1999-05-17 12:22:31 +00:00
|
|
|
if (NS_FAILED(res))
|
1999-04-06 19:49:33 +00:00
|
|
|
{
|
1999-04-21 18:53:55 +00:00
|
|
|
#ifdef DEBUG_akkana
|
1999-04-30 18:03:39 +00:00
|
|
|
printf("Some failure creating the new image node\n");
|
1999-04-21 18:53:55 +00:00
|
|
|
#endif
|
1999-04-30 18:03:39 +00:00
|
|
|
return res;
|
1999-04-21 18:53:55 +00:00
|
|
|
}
|
|
|
|
|
1999-04-30 18:03:39 +00:00
|
|
|
//
|
|
|
|
// Now we're ready to insert the new image node:
|
|
|
|
// Starting now, don't return without ending the transaction!
|
|
|
|
//
|
1999-06-03 06:00:23 +00:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-04-30 18:03:39 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNode> parentNode;
|
|
|
|
PRInt32 offsetOfNewNode;
|
1999-06-11 19:03:05 +00:00
|
|
|
res = DeleteSelectionAndPrepareToCreateNode(parentNode,
|
1999-04-30 18:03:39 +00:00
|
|
|
offsetOfNewNode);
|
|
|
|
if (NS_SUCCEEDED(res))
|
|
|
|
{
|
|
|
|
// and insert it into the right place in the tree:
|
|
|
|
res = InsertNode(newNode, parentNode, offsetOfNewNode);
|
|
|
|
}
|
1999-04-21 18:53:55 +00: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();
|
1999-06-24 20:59:45 +00:00
|
|
|
// Empty string indicates we should match any element tag
|
|
|
|
PRBool anyTag = (TagName == "");
|
1999-04-21 18:53:55 +00:00
|
|
|
|
|
|
|
//Note that this doesn't need to go through the transaction system
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res=NS_ERROR_NOT_INITIALIZED;
|
1999-06-07 19:32:36 +00:00
|
|
|
//PRBool first=PR_TRUE;
|
1999-04-21 18:53:55 +00:00
|
|
|
nsCOMPtr<nsIDOMSelection>selection;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if (NS_FAILED(res) || !selection)
|
|
|
|
return res;
|
1999-04-21 18:53:55 +00:00
|
|
|
|
|
|
|
PRBool isCollapsed;
|
1999-07-18 02:27:19 +00:00
|
|
|
selection->GetIsCollapsed(&isCollapsed);
|
1999-04-21 18:53:55 +00:00
|
|
|
nsCOMPtr<nsIDOMElement> selectedElement;
|
|
|
|
PRBool bNodeFound = PR_FALSE;
|
|
|
|
|
|
|
|
// Don't bother to examine selection if it is collapsed
|
|
|
|
if (!isCollapsed)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIEnumerator> enumerator;
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->GetEnumerator(getter_AddRefs(enumerator));
|
1999-07-15 18:19:20 +00:00
|
|
|
if (NS_SUCCEEDED(res) && enumerator)
|
1999-04-08 00:46:10 +00:00
|
|
|
{
|
1999-04-21 18:53:55 +00:00
|
|
|
enumerator->First();
|
|
|
|
nsISupports *currentItem;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = enumerator->CurrentItem(¤tItem);
|
|
|
|
if ((NS_SUCCEEDED(res)) && currentItem)
|
1999-04-08 00:46:10 +00:00
|
|
|
{
|
1999-04-21 18:53:55 +00:00
|
|
|
nsCOMPtr<nsIDOMRange> range( do_QueryInterface(currentItem) );
|
|
|
|
nsCOMPtr<nsIContentIterator> iter;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull,
|
1999-05-28 00:20:41 +00:00
|
|
|
nsIContentIterator::GetIID(),
|
1999-04-21 18:53:55 +00:00
|
|
|
getter_AddRefs(iter));
|
1999-06-03 06:00:23 +00:00
|
|
|
if ((NS_SUCCEEDED(res)) && iter)
|
1999-04-21 18:53:55 +00:00
|
|
|
{
|
|
|
|
iter->Init(range);
|
|
|
|
// loop through the content iterator for each content node
|
|
|
|
nsCOMPtr<nsIContent> content;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = iter->CurrentNode(getter_AddRefs(content));
|
1999-06-07 19:32:36 +00:00
|
|
|
//PRBool bOtherNodeTypeFound = PR_FALSE;
|
1999-04-21 18:53:55 +00: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 19:32:36 +00:00
|
|
|
//bNodeFound;
|
1999-04-21 18:53:55 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoString domTagName;
|
|
|
|
selectedElement->GetNodeName(domTagName);
|
1999-05-07 22:26:23 +00:00
|
|
|
domTagName.ToLowerCase();
|
1999-04-21 18:53:55 +00:00
|
|
|
|
1999-06-24 20:59:45 +00:00
|
|
|
if (anyTag)
|
|
|
|
{
|
|
|
|
// Get name of first selected element
|
|
|
|
selectedElement->GetTagName(TagName);
|
|
|
|
TagName.ToLowerCase();
|
|
|
|
anyTag = PR_FALSE;
|
|
|
|
}
|
|
|
|
|
1999-04-21 18:53:55 +00:00
|
|
|
// The "A" tag is a pain,
|
|
|
|
// used for both link(href is set) and "Named Anchor"
|
1999-05-26 21:40:51 +00:00
|
|
|
if (TagName == "href" || (TagName == "anchor"))
|
1999-04-21 18:53:55 +00: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-26 21:40:51 +00:00
|
|
|
if( TagName == "href")
|
1999-04-21 18:53:55 +00:00
|
|
|
{
|
1999-04-22 06:19:44 +00:00
|
|
|
if (NS_SUCCEEDED(anchor->GetHref(tmpText)) && tmpText.GetUnicode() && tmpText.Length() != 0)
|
1999-04-21 18:53:55 +00:00
|
|
|
bNodeFound = PR_TRUE;
|
1999-05-26 21:40:51 +00:00
|
|
|
} else if (TagName == "anchor")
|
1999-04-21 18:53:55 +00:00
|
|
|
{
|
1999-04-22 06:19:44 +00:00
|
|
|
if (NS_SUCCEEDED(anchor->GetName(tmpText)) && tmpText.GetUnicode() && tmpText.Length() != 0)
|
1999-04-21 18:53:55 +00:00
|
|
|
bNodeFound = PR_TRUE;
|
|
|
|
}
|
1999-07-02 22:52:34 +00:00
|
|
|
#if 0
|
|
|
|
// Not sure if this kind of logic should be here or in JavaScript
|
1999-05-26 21:40:51 +00: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-26 22:30:50 +00:00
|
|
|
nsCOMPtr<nsIDOMNode> current = do_QueryInterface(selectedElement);
|
1999-05-26 21:40:51 +00:00
|
|
|
PRBool notDone = PR_TRUE;
|
|
|
|
do {
|
1999-06-03 06:00:23 +00:00
|
|
|
res = current->GetParentNode(getter_AddRefs(parent));
|
|
|
|
notDone = NS_SUCCEEDED(res) && parent != nsnull;
|
1999-05-26 21:40:51 +00:00
|
|
|
if(notDone)
|
|
|
|
{
|
|
|
|
nsString tmpText;
|
1999-06-07 19:32:36 +00:00
|
|
|
/*nsCOMPtr<nsIDOMHTMLAnchorElement>*/
|
|
|
|
anchor = do_QueryInterface(parent);
|
1999-05-26 21:40:51 +00:00
|
|
|
if (anchor && NS_SUCCEEDED(anchor->GetHref(tmpText)) && tmpText.GetUnicode() && tmpText.Length() != 0)
|
|
|
|
{
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMElement> link = do_QueryInterface(parent);
|
|
|
|
if (link)
|
|
|
|
{
|
|
|
|
*aReturn =link;
|
1999-06-27 17:55:01 +00:00
|
|
|
// Getters must addref
|
|
|
|
NS_ADDREF(*aReturn);
|
1999-05-26 21:40:51 +00:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
current = parent;
|
|
|
|
} while (notDone);
|
|
|
|
}
|
1999-07-02 22:52:34 +00:00
|
|
|
#endif
|
1999-04-21 18:53:55 +00:00
|
|
|
}
|
1999-05-26 21:40:51 +00:00
|
|
|
} else if (TagName == domTagName) { // All other tag names are handled here
|
1999-04-21 18:53:55 +00:00
|
|
|
bNodeFound = PR_TRUE;
|
|
|
|
}
|
|
|
|
if (!bNodeFound)
|
|
|
|
{
|
|
|
|
// Check if node we have is really part of the selection???
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
1999-04-27 01:10:10 +00:00
|
|
|
iter->Next();
|
1999-04-21 18:53:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Should never get here?
|
|
|
|
isCollapsed = PR_TRUE;
|
|
|
|
printf("isCollapsed was FALSE, but no elements found in selection\n");
|
1999-04-08 00:46:10 +00:00
|
|
|
}
|
1999-04-21 18:53:55 +00:00
|
|
|
} else {
|
|
|
|
printf("Could not create enumerator for GetSelectionProperties\n");
|
1999-04-08 00:46:10 +00:00
|
|
|
}
|
1999-04-06 19:49:33 +00:00
|
|
|
}
|
1999-04-21 18:53:55 +00:00
|
|
|
if (bNodeFound)
|
|
|
|
{
|
|
|
|
|
|
|
|
*aReturn = selectedElement;
|
1999-06-27 17:55:01 +00:00
|
|
|
// Getters must addref
|
|
|
|
NS_ADDREF(*aReturn);
|
1999-04-21 18:53:55 +00:00
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-04-21 18:53:55 +00:00
|
|
|
}
|
1999-03-29 22:01:26 +00:00
|
|
|
|
1999-04-21 18:53:55 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::CreateElementWithDefaults(const nsString& aTagName, nsIDOMElement** aReturn)
|
|
|
|
{
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res=NS_ERROR_NOT_INITIALIZED;
|
1999-04-21 18:53:55 +00:00
|
|
|
if (aReturn)
|
|
|
|
*aReturn = nsnull;
|
|
|
|
|
|
|
|
if (aTagName == "" || !aReturn)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
1999-06-10 00:35:02 +00:00
|
|
|
|
1999-04-21 18:53:55 +00:00
|
|
|
nsAutoString TagName = aTagName;
|
|
|
|
TagName.ToLowerCase();
|
|
|
|
nsAutoString realTagName;
|
|
|
|
|
1999-06-10 00:35:02 +00:00
|
|
|
PRBool isHREF = (TagName == "href");
|
|
|
|
PRBool isAnchor = (TagName == "anchor");
|
1999-04-21 18:53:55 +00:00
|
|
|
if (isHREF || isAnchor)
|
1999-03-29 22:01:26 +00:00
|
|
|
{
|
1999-04-21 18:53:55 +00:00
|
|
|
realTagName = "a";
|
|
|
|
} else {
|
|
|
|
realTagName = TagName;
|
1999-03-29 22:01:26 +00:00
|
|
|
}
|
1999-04-21 18:53:55 +00:00
|
|
|
//We don't use editor's CreateElement because we don't want to
|
|
|
|
// go through the transaction system
|
1999-03-29 22:01:26 +00:00
|
|
|
|
1999-04-21 18:53:55 +00:00
|
|
|
nsCOMPtr<nsIDOMElement>newElement;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = mDoc->CreateElement(realTagName, getter_AddRefs(newElement));
|
|
|
|
if (NS_FAILED(res) || !newElement)
|
1999-04-21 18:53:55 +00:00
|
|
|
return NS_ERROR_FAILURE;
|
1999-04-08 00:46:10 +00:00
|
|
|
|
1999-04-21 18:53:55 +00:00
|
|
|
// Set default values for new elements
|
1999-07-14 15:24:33 +00:00
|
|
|
if (TagName.Equals("hr"))
|
1999-07-15 18:19:20 +00:00
|
|
|
{
|
|
|
|
// TODO: Get the text of the selection and build a suggested Name
|
|
|
|
// Replace spaces with "_"
|
|
|
|
} else if (TagName.Equals("hr"))
|
1999-06-12 21:22:12 +00:00
|
|
|
{
|
|
|
|
// Hard coded defaults in case there's no prefs
|
|
|
|
nsAutoString align("center");
|
|
|
|
nsAutoString width("100%");
|
|
|
|
nsAutoString height("2");
|
|
|
|
PRBool bNoShade = PR_FALSE;
|
|
|
|
|
|
|
|
if (mPrefs)
|
|
|
|
{
|
|
|
|
char buf[16];
|
|
|
|
PRInt32 iAlign;
|
1999-06-12 22:11:59 +00:00
|
|
|
// Currently using 0=left, 1=center, and 2=right
|
1999-06-12 21:22:12 +00:00
|
|
|
if( NS_SUCCEEDED(mPrefs->GetIntPref("editor.hrule.align", &iAlign)))
|
|
|
|
{
|
|
|
|
switch (iAlign) {
|
1999-06-12 22:11:59 +00:00
|
|
|
case 0:
|
1999-06-12 21:22:12 +00:00
|
|
|
align = "left";
|
|
|
|
break;
|
1999-06-12 22:11:59 +00:00
|
|
|
case 2:
|
1999-06-12 21:22:12 +00:00
|
|
|
align = "right";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PRInt32 iHeight;
|
1999-06-12 22:11:59 +00:00
|
|
|
PRUint32 count;
|
1999-06-12 21:22:12 +00:00
|
|
|
if( NS_SUCCEEDED(mPrefs->GetIntPref("editor.hrule.height", &iHeight)))
|
|
|
|
{
|
1999-06-12 22:11:59 +00:00
|
|
|
count = PR_snprintf(buf, 16, "%d", iHeight);
|
|
|
|
if (count > 0)
|
1999-06-12 21:22:12 +00:00
|
|
|
{
|
|
|
|
height = buf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PRInt32 iWidth;
|
|
|
|
PRBool bPercent;
|
|
|
|
if( NS_SUCCEEDED(mPrefs->GetIntPref("editor.hrule.width", &iWidth)) &&
|
|
|
|
NS_SUCCEEDED(mPrefs->GetBoolPref("editor.hrule.width_percent", &bPercent)))
|
|
|
|
{
|
1999-06-12 22:11:59 +00:00
|
|
|
count = PR_snprintf(buf, 16, "%d", iWidth);
|
|
|
|
if (count > 0)
|
1999-06-12 21:22:12 +00:00
|
|
|
{
|
|
|
|
width = buf;
|
|
|
|
if (bPercent)
|
|
|
|
width.Append("%");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PRBool bShading;
|
|
|
|
if (NS_SUCCEEDED(mPrefs->GetBoolPref("editor.hrule.shading", &bShading)))
|
|
|
|
{
|
|
|
|
bNoShade = !bShading;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
newElement->SetAttribute("align", align);
|
|
|
|
newElement->SetAttribute("height", height);
|
|
|
|
newElement->SetAttribute("width", width);
|
|
|
|
if (bNoShade)
|
|
|
|
newElement->SetAttribute("noshade", "");
|
1999-07-04 23:01:10 +00:00
|
|
|
|
|
|
|
} else if (TagName.Equals("table"))
|
|
|
|
{
|
|
|
|
newElement->SetAttribute("cellpadding","2");
|
|
|
|
newElement->SetAttribute("cellspacing","2");
|
1999-07-14 15:24:33 +00:00
|
|
|
newElement->SetAttribute("width","50%");
|
1999-07-04 23:01:10 +00:00
|
|
|
newElement->SetAttribute("border","1");
|
|
|
|
} else if (TagName.Equals("tr"))
|
|
|
|
{
|
|
|
|
newElement->SetAttribute("valign","top");
|
|
|
|
} else if (TagName.Equals("td"))
|
|
|
|
{
|
|
|
|
newElement->SetAttribute("valign","top");
|
|
|
|
|
1999-07-08 03:28:34 +00:00
|
|
|
// Insert the default space in a cell so border displays
|
|
|
|
nsCOMPtr<nsIDOMNode> newCellNode = do_QueryInterface(newElement);
|
|
|
|
if (newCellNode)
|
1999-07-04 23:01:10 +00:00
|
|
|
{
|
1999-07-14 15:24:33 +00:00
|
|
|
// TODO: This should probably be in the RULES code or
|
|
|
|
// preference based for "should we add the nbsp"
|
|
|
|
nsCOMPtr<nsIDOMText>newTextNode;
|
|
|
|
nsString space;
|
|
|
|
// Set contents to the   character by concatanating the char code
|
|
|
|
space += nbsp;
|
|
|
|
// If we fail here, we return NS_OK anyway, since we have an OK cell node
|
|
|
|
nsresult result = mDoc->CreateTextNode(space, getter_AddRefs(newTextNode));
|
|
|
|
if (NS_SUCCEEDED(result) && newTextNode)
|
1999-07-08 03:28:34 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode>resultNode;
|
1999-07-14 15:24:33 +00:00
|
|
|
result = newCellNode->AppendChild(newTextNode, getter_AddRefs(resultNode));
|
1999-07-08 03:28:34 +00:00
|
|
|
}
|
1999-07-04 23:01:10 +00:00
|
|
|
}
|
1999-04-08 00:46:10 +00:00
|
|
|
}
|
1999-04-21 18:53:55 +00:00
|
|
|
// ADD OTHER DEFAULT ATTRIBUTES HERE
|
1999-04-06 19:49:33 +00:00
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-04-21 18:53:55 +00:00
|
|
|
{
|
1999-05-26 21:40:51 +00:00
|
|
|
*aReturn = newElement;
|
1999-04-21 18:53:55 +00:00
|
|
|
}
|
1999-06-10 00:35:02 +00:00
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-03-29 22:01:26 +00:00
|
|
|
}
|
|
|
|
|
1999-04-21 18:53:55 +00:00
|
|
|
NS_IMETHODIMP
|
1999-06-10 21:31:42 +00:00
|
|
|
nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection)
|
1999-04-21 18:53:55 +00:00
|
|
|
{
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
1999-06-10 21:56:47 +00:00
|
|
|
mJSEditorLog->InsertElement(aElement, aDeleteSelection);
|
1999-06-10 19:41:40 +00:00
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-11 19:03:05 +00:00
|
|
|
nsresult res = NS_ERROR_NOT_INITIALIZED;
|
1999-04-21 18:53:55 +00:00
|
|
|
|
1999-06-10 21:31:42 +00:00
|
|
|
if (!aElement)
|
1999-04-21 18:53:55 +00:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsAutoEditBatch beginBatching(this);
|
1999-07-14 15:24:33 +00:00
|
|
|
// For most elements, set caret after inserting
|
|
|
|
PRBool setCaretAfterElement = PR_TRUE;
|
1999-04-21 18:53:55 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNode> parentSelectedNode;
|
1999-07-14 15:24:33 +00:00
|
|
|
PRInt32 splitPointOffset;
|
1999-04-21 18:53:55 +00:00
|
|
|
|
1999-07-04 23:01:10 +00:00
|
|
|
nsCOMPtr<nsIDOMSelection>selection;
|
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if (!NS_SUCCEEDED(res) || !selection)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
1999-05-07 00:44:46 +00:00
|
|
|
// Clear current selection.
|
|
|
|
// Should put caret at anchor point?
|
|
|
|
if (!aDeleteSelection)
|
|
|
|
{
|
1999-07-03 01:49:30 +00:00
|
|
|
PRBool collapseAfter = PR_TRUE;
|
|
|
|
// Named Anchor is a special case,
|
|
|
|
// We collapse to insert element BEFORE the selection
|
|
|
|
// For all other tags, we insert AFTER the selection
|
|
|
|
nsCOMPtr<nsIDOMHTMLAnchorElement> anchor = do_QueryInterface(aElement);
|
|
|
|
if (anchor)
|
|
|
|
{
|
|
|
|
nsAutoString name;
|
|
|
|
if (NS_SUCCEEDED(anchor->GetName(name)) && name.GetUnicode() && name.Length() != 0)
|
|
|
|
collapseAfter = PR_FALSE;
|
|
|
|
}
|
|
|
|
|
1999-07-04 23:01:10 +00:00
|
|
|
if (collapseAfter)
|
1999-07-03 01:49:30 +00:00
|
|
|
{
|
1999-07-04 23:01:10 +00:00
|
|
|
// Default behavior is to collapse to the end of the selection
|
1999-07-18 02:27:19 +00:00
|
|
|
selection->ClearSelection();
|
1999-07-04 23:01:10 +00:00
|
|
|
} else {
|
|
|
|
// Collapse to the start of the selection,
|
|
|
|
// We must explore the first range and find
|
|
|
|
// its parent and starting offset of selection
|
|
|
|
// TODO: Move this logic to a new method nsIDOMSelection::CollapseToStart()???
|
|
|
|
nsCOMPtr<nsIDOMRange> firstRange;
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->GetRangeAt(0, getter_AddRefs(firstRange));
|
1999-07-04 23:01:10 +00:00
|
|
|
if (NS_SUCCEEDED(res) && firstRange)
|
1999-07-03 01:49:30 +00:00
|
|
|
{
|
1999-07-04 23:01:10 +00:00
|
|
|
nsCOMPtr<nsIDOMNode> parent;
|
|
|
|
res = firstRange->GetCommonParent(getter_AddRefs(parent));
|
|
|
|
if (NS_SUCCEEDED(res) && parent)
|
1999-07-03 01:49:30 +00:00
|
|
|
{
|
1999-07-04 23:01:10 +00:00
|
|
|
PRInt32 startOffset;
|
|
|
|
firstRange->GetStartOffset(&startOffset);
|
1999-07-18 02:27:19 +00:00
|
|
|
selection->Collapse(parent, startOffset);
|
1999-07-04 23:01:10 +00:00
|
|
|
} else {
|
|
|
|
// Very unlikely, but collapse to the end if we failed above
|
1999-07-18 02:27:19 +00:00
|
|
|
selection->ClearSelection();
|
1999-07-03 01:49:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-05-07 00:44:46 +00:00
|
|
|
}
|
1999-06-24 20:59:45 +00:00
|
|
|
|
1999-07-14 15:24:33 +00:00
|
|
|
res = DeleteSelectionAndPrepareToCreateNode(parentSelectedNode, splitPointOffset);
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-04-21 18:53:55 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode> newNode = do_QueryInterface(aElement);
|
1999-07-03 01:49:30 +00:00
|
|
|
PRBool isInline;
|
1999-06-24 20:59:45 +00:00
|
|
|
res = IsNodeInline(newNode, isInline);
|
1999-07-14 15:24:33 +00:00
|
|
|
if( NS_SUCCEEDED(res) && isInline)
|
1999-06-24 20:59:45 +00:00
|
|
|
{
|
|
|
|
// The simple case of an inline node
|
1999-07-14 15:24:33 +00:00
|
|
|
// This will split any inline nodes at the caret
|
|
|
|
// and insert between them
|
|
|
|
res = InsertNode(aElement, parentSelectedNode, splitPointOffset);
|
1999-07-03 01:49:30 +00:00
|
|
|
} else {
|
1999-07-14 15:24:33 +00:00
|
|
|
// Inserting a BLOCK element
|
|
|
|
// Get the first block parent of the paragraph/container
|
|
|
|
// which we can split to create insert location
|
|
|
|
// (Current parent may already be a suitable block to split)
|
|
|
|
nsCOMPtr<nsIDOMNode> parentNodeOfInsert = parentSelectedNode;
|
|
|
|
nsCOMPtr<nsIDOMNode> topNodeToSplit = parentSelectedNode;
|
|
|
|
nsCOMPtr<nsIDOMElement> bodyElement;
|
|
|
|
// We need to find the offset at each level we will split
|
|
|
|
// to use when we insert the new element
|
|
|
|
PRInt32 offsetToInsertAt = splitPointOffset;
|
|
|
|
|
|
|
|
res = nsEditor::GetBodyElement(getter_AddRefs(bodyElement));
|
|
|
|
|
|
|
|
if (NS_SUCCEEDED(res) && bodyElement &&
|
|
|
|
// If text node is direct child of body, we can't insert a block node
|
|
|
|
(parentSelectedNode != bodyElement))
|
1999-07-04 23:01:10 +00:00
|
|
|
{
|
1999-07-14 15:24:33 +00:00
|
|
|
nsCOMPtr<nsIDOMNode> bodyNode = do_QueryInterface(bodyElement);
|
1999-07-19 19:06:39 +00:00
|
|
|
isInline = PR_TRUE;
|
1999-07-14 15:24:33 +00:00
|
|
|
while (isInline)
|
|
|
|
{
|
|
|
|
// Get parent of the top node to split
|
|
|
|
res = topNodeToSplit->GetParentNode(getter_AddRefs(parentNodeOfInsert));
|
|
|
|
// If Inline, we loop around to get the next parent level
|
|
|
|
if (NS_SUCCEEDED(res) && parentNodeOfInsert &&
|
|
|
|
NS_SUCCEEDED(IsNodeInline(topNodeToSplit, isInline)) &&
|
|
|
|
NS_SUCCEEDED(GetChildOffset(topNodeToSplit, parentNodeOfInsert, offsetToInsertAt)))
|
|
|
|
{
|
|
|
|
#ifdef DEBUG_cmanske
|
|
|
|
nsAutoString nodeName;
|
|
|
|
topNodeToSplit->GetNodeName(nodeName);
|
|
|
|
printf("Top Node to split: ");
|
|
|
|
wprintf(nodeName.GetUnicode());
|
|
|
|
|
|
|
|
parentNodeOfInsert->GetNodeName(nodeName);
|
|
|
|
printf(" Parent of this node: ");
|
|
|
|
wprintf(nodeName.GetUnicode());
|
|
|
|
printf("\n");
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// The new offset to insert at is just after the topmost node we will split
|
|
|
|
offsetToInsertAt++;
|
|
|
|
} else {
|
|
|
|
// Major failure if we get here
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (bodyNode != topNodeToSplit)
|
|
|
|
{
|
|
|
|
// We have the node to split and its parent.
|
|
|
|
// TODO: Implement "CanContainElement" to be sure
|
|
|
|
// we are allowed to insert aElement under parentNodeOfInsert
|
|
|
|
// If we can't we should call special methods for various combintations
|
|
|
|
// if (!CanContain(aElement, parentNodeOfInsert)
|
|
|
|
// return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
// Split nodes from the selection parent ("bottom node") and all intervening parents
|
|
|
|
// up to the topmost node, which may be = to bottom node)
|
|
|
|
// (This redistribute children as each level is split.)
|
|
|
|
res = SplitNodeDeep(topNodeToSplit, parentSelectedNode, splitPointOffset);
|
|
|
|
if (NS_SUCCEEDED(res))
|
|
|
|
{
|
|
|
|
//Insert the block element between the 2 "topmost" containers
|
|
|
|
res = InsertNode(aElement, parentNodeOfInsert, offsetToInsertAt);
|
|
|
|
|
|
|
|
// Check for special case of inserting a table
|
|
|
|
PRBool caretIsSet;
|
|
|
|
res = SetCaretInTableCell(aElement, &caretIsSet);
|
|
|
|
if (NS_SUCCEEDED(res) && caretIsSet)
|
|
|
|
setCaretAfterElement = PR_FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// If here, we must have an inline node directly under the body
|
|
|
|
// so we can't insert a block tag
|
|
|
|
// TODO: Take each inline node resulting from DeleteSelectionAndPrepareToCreateNode
|
|
|
|
// and insert them each into a default paragraph.
|
|
|
|
// Then insert new block node between them.
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
1999-07-04 23:01:10 +00:00
|
|
|
}
|
1999-06-24 20:59:45 +00:00
|
|
|
}
|
1999-04-21 18:53:55 +00:00
|
|
|
}
|
1999-07-14 15:24:33 +00:00
|
|
|
if (setCaretAfterElement && NS_SUCCEEDED(res))
|
1999-07-03 01:49:30 +00:00
|
|
|
SetCaretAfterElement(aElement);
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-04-21 18:53:55 +00:00
|
|
|
}
|
1999-05-03 22:57:48 +00:00
|
|
|
|
1999-06-12 21:22:12 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::SaveHLineSettings(nsIDOMElement* aElement)
|
|
|
|
{
|
|
|
|
nsresult res=NS_ERROR_NOT_INITIALIZED;
|
|
|
|
if (!aElement || !mPrefs)
|
|
|
|
return res;
|
|
|
|
|
|
|
|
nsAutoString align, width, height, noshade;
|
|
|
|
res = NS_ERROR_UNEXPECTED;
|
|
|
|
if (NS_SUCCEEDED(aElement->GetAttribute("align", align)) &&
|
|
|
|
NS_SUCCEEDED(aElement->GetAttribute("height", height)) &&
|
|
|
|
NS_SUCCEEDED(aElement->GetAttribute("width", width)) &&
|
|
|
|
NS_SUCCEEDED(aElement->GetAttribute("noshade", noshade)))
|
|
|
|
{
|
|
|
|
PRInt32 iAlign = 0;
|
|
|
|
if (align == "center")
|
|
|
|
iAlign = 1;
|
|
|
|
else if (align == "right")
|
|
|
|
iAlign = 2;
|
|
|
|
mPrefs->SetIntPref("editor.hrule.align", iAlign);
|
|
|
|
|
1999-06-16 21:45:38 +00:00
|
|
|
PRInt32 errorCode;
|
|
|
|
PRInt32 iHeight = height.ToInteger(&errorCode);
|
|
|
|
|
|
|
|
if (errorCode == NS_OK && iHeight > 0)
|
1999-06-12 21:22:12 +00:00
|
|
|
mPrefs->SetIntPref("editor.hrule.height", iHeight);
|
|
|
|
|
1999-06-16 21:45:38 +00:00
|
|
|
PRInt32 iWidth = width.ToInteger(&errorCode);
|
|
|
|
if (errorCode == NS_OK && iWidth > 0) {
|
1999-06-12 22:11:59 +00:00
|
|
|
mPrefs->SetIntPref("editor.hrule.width", iWidth);
|
1999-06-12 21:22:12 +00:00
|
|
|
mPrefs->SetBoolPref("editor.hrule.width_percent", (width.Find("%") > 0));
|
|
|
|
}
|
|
|
|
|
|
|
|
mPrefs->SetBoolPref("editor.hrule.shading", (noshade == ""));
|
|
|
|
res = NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
1999-05-07 22:26:23 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::InsertLinkAroundSelection(nsIDOMElement* aAnchorElement)
|
|
|
|
{
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->InsertLinkAroundSelection(aAnchorElement);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res=NS_ERROR_NULL_POINTER;
|
1999-05-26 21:40:51 +00:00
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
1999-05-07 22:26:23 +00:00
|
|
|
|
1999-05-26 21:40:51 +00:00
|
|
|
// DON'T RETURN EXCEPT AT THE END -- WE NEED TO RELEASE THE aAnchorElement
|
1999-05-07 22:26:23 +00:00
|
|
|
if (!aAnchorElement)
|
1999-05-26 21:40:51 +00:00
|
|
|
goto DELETE_ANCHOR;
|
1999-05-07 22:26:23 +00:00
|
|
|
|
|
|
|
// We must have a real selection
|
1999-06-03 06:00:23 +00:00
|
|
|
res = GetSelection(getter_AddRefs(selection));
|
|
|
|
if (NS_FAILED(res) || !selection)
|
1999-05-26 21:40:51 +00:00
|
|
|
goto DELETE_ANCHOR;
|
1999-05-07 22:26:23 +00:00
|
|
|
|
|
|
|
PRBool isCollapsed;
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->GetIsCollapsed(&isCollapsed);
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_FAILED(res))
|
1999-05-07 22:26:23 +00:00
|
|
|
isCollapsed = PR_TRUE;
|
|
|
|
|
|
|
|
if (isCollapsed)
|
|
|
|
{
|
|
|
|
printf("InsertLinkAroundSelection called but there is no selection!!!\n");
|
1999-06-03 06:00:23 +00:00
|
|
|
res = NS_OK;
|
1999-05-26 21:40:51 +00:00
|
|
|
} else {
|
1999-05-07 22:26:23 +00:00
|
|
|
|
1999-05-26 21:40:51 +00: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 06:00:23 +00: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-26 21:40:51 +00: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 06:00:23 +00:00
|
|
|
return res;
|
1999-05-26 21:40:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PRBool nsHTMLEditor::IsElementInBody(nsIDOMElement* aElement)
|
|
|
|
{
|
|
|
|
if ( aElement )
|
1999-05-07 22:26:23 +00:00
|
|
|
{
|
1999-05-26 21:40:51 +00:00
|
|
|
nsIDOMElement* bodyElement = nsnull;
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res = nsEditor::GetBodyElement(&bodyElement);
|
|
|
|
if (NS_SUCCEEDED(res) && bodyElement)
|
1999-05-07 22:26:23 +00:00
|
|
|
{
|
1999-05-26 21:40:51 +00:00
|
|
|
nsCOMPtr<nsIDOMNode> parent;
|
|
|
|
nsCOMPtr<nsIDOMNode> currentElement = do_QueryInterface(aElement);
|
|
|
|
if (currentElement)
|
1999-05-07 22:26:23 +00:00
|
|
|
{
|
1999-05-26 21:40:51 +00: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 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->SelectElement(aElement);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res = NS_ERROR_NULL_POINTER;
|
1999-05-26 21:40:51 +00:00
|
|
|
|
|
|
|
// Must be sure that element is contained in the document body
|
|
|
|
if (IsElementInBody(aElement))
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if (NS_SUCCEEDED(res) && selection)
|
1999-05-26 21:40:51 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode>parent;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = aElement->GetParentNode(getter_AddRefs(parent));
|
|
|
|
if (NS_SUCCEEDED(res) && parent)
|
1999-05-26 21:40:51 +00:00
|
|
|
{
|
|
|
|
PRInt32 offsetInParent;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = GetChildOffset(aElement, parent, offsetInParent);
|
1999-05-26 21:40:51 +00:00
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-05-26 21:40:51 +00:00
|
|
|
{
|
|
|
|
// Collapse selection to just before desired element,
|
1999-07-18 02:27:19 +00:00
|
|
|
selection->Collapse(parent, offsetInParent);
|
1999-05-26 21:40:51 +00:00
|
|
|
// then extend it to just after
|
1999-07-18 02:27:19 +00:00
|
|
|
selection->Extend(parent, offsetInParent+1);
|
1999-05-26 21:40:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-05-26 21:40:51 +00:00
|
|
|
}
|
|
|
|
|
1999-07-14 15:24:33 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::SetCaretInTableCell(nsIDOMElement* aElement, PRBool* caretIsSet)
|
|
|
|
{
|
|
|
|
nsresult res = NS_ERROR_NULL_POINTER;
|
|
|
|
if (caretIsSet)
|
|
|
|
*caretIsSet = PR_FALSE;
|
|
|
|
if (aElement && IsElementInBody(aElement))
|
|
|
|
{
|
|
|
|
res = NS_OK;
|
|
|
|
nsAutoString tagName;
|
|
|
|
aElement->GetNodeName(tagName);
|
|
|
|
tagName.ToLowerCase();
|
|
|
|
if (tagName == "td" || tagName == "tr" ||
|
|
|
|
tagName == "th" || tagName == "td" ||
|
|
|
|
tagName == "caption")
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
|
|
|
|
nsCOMPtr<nsIDOMNode> parent;
|
|
|
|
// This MUST succeed if IsElementInBody was TRUE
|
|
|
|
node->GetParentNode(getter_AddRefs(parent));
|
|
|
|
nsCOMPtr<nsIDOMNode>firstChild;
|
|
|
|
// Find deepest child
|
|
|
|
PRBool hasChild;
|
|
|
|
while (NS_SUCCEEDED(node->HasChildNodes(&hasChild)) && hasChild)
|
|
|
|
{
|
|
|
|
if (NS_SUCCEEDED(node->GetFirstChild(getter_AddRefs(firstChild))))
|
|
|
|
{
|
|
|
|
parent = node;
|
|
|
|
node = firstChild;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PRInt32 offset = 0;
|
|
|
|
nsCOMPtr<nsIDOMNode>lastChild;
|
|
|
|
res = parent->GetLastChild(getter_AddRefs(lastChild));
|
|
|
|
if (NS_SUCCEEDED(res) && lastChild && node != lastChild)
|
|
|
|
{
|
|
|
|
if (node == lastChild)
|
|
|
|
{
|
|
|
|
// Check if node is text and has more than just a  
|
|
|
|
nsCOMPtr<nsIDOMCharacterData>textNode = do_QueryInterface(node);
|
|
|
|
nsString text;
|
|
|
|
char nbspStr[2] = {nbsp, 0};
|
|
|
|
if (textNode && textNode->GetData(text))
|
|
|
|
{
|
|
|
|
// Set selection relative to the text node
|
|
|
|
parent = node;
|
|
|
|
PRInt32 len = text.Length();
|
|
|
|
if (len > 1 || text != nbspStr)
|
|
|
|
{
|
|
|
|
offset = len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// We have > 1 node, so set to end of content
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Set selection at beginning of deepest node
|
|
|
|
// Should we set
|
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if (NS_SUCCEEDED(res) && selection)
|
|
|
|
{
|
1999-07-18 02:27:19 +00:00
|
|
|
res = selection->Collapse(parent, offset);
|
1999-07-14 15:24:33 +00:00
|
|
|
if (NS_SUCCEEDED(res) && caretIsSet)
|
|
|
|
*caretIsSet = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
1999-05-26 21:40:51 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::SetCaretAfterElement(nsIDOMElement* aElement)
|
|
|
|
{
|
1999-06-10 19:41:40 +00:00
|
|
|
#ifdef ENABLE_JS_EDITOR_LOG
|
|
|
|
nsAutoJSEditorLogLock logLock(mJSEditorLog);
|
|
|
|
|
|
|
|
if (mJSEditorLog)
|
|
|
|
mJSEditorLog->SetCaretAfterElement(aElement);
|
|
|
|
#endif // ENABLE_JS_EDITOR_LOG
|
|
|
|
|
1999-06-03 06:00:23 +00:00
|
|
|
nsresult res = NS_ERROR_NULL_POINTER;
|
1999-05-26 21:40:51 +00:00
|
|
|
|
1999-07-14 15:24:33 +00:00
|
|
|
// Be sure the element is contained in the document body
|
|
|
|
if (aElement && IsElementInBody(aElement))
|
1999-05-26 21:40:51 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMSelection> selection;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = nsEditor::GetSelection(getter_AddRefs(selection));
|
|
|
|
if (NS_SUCCEEDED(res) && selection)
|
1999-05-26 21:40:51 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode>parent;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = aElement->GetParentNode(getter_AddRefs(parent));
|
|
|
|
if (NS_SUCCEEDED(res) && parent)
|
1999-05-26 21:40:51 +00:00
|
|
|
{
|
|
|
|
PRInt32 offsetInParent;
|
1999-06-03 06:00:23 +00:00
|
|
|
res = GetChildOffset(aElement, parent, offsetInParent);
|
1999-07-14 15:24:33 +00:00
|
|
|
// New collapsed selection will be just after the new element
|
|
|
|
offsetInParent++;
|
1999-06-03 06:00:23 +00:00
|
|
|
if (NS_SUCCEEDED(res))
|
1999-05-26 21:40:51 +00:00
|
|
|
{
|
1999-07-15 18:19:20 +00:00
|
|
|
// Collapse selection to just after desired element,
|
1999-07-18 02:27:19 +00:00
|
|
|
selection->Collapse(parent, offsetInParent+1);
|
1999-05-26 21:40:51 +00:00
|
|
|
}
|
1999-05-07 22:26:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-06-03 06:00:23 +00:00
|
|
|
return res;
|
1999-05-07 22:26:23 +00:00
|
|
|
}
|
|
|
|
|
1999-07-19 19:06:39 +00:00
|
|
|
NS_IMETHODIMP
|
1999-07-19 22:36:12 +00:00
|
|
|
nsHTMLEditor::GetEmbeddedObjects(nsISupportsArray** aNodeList)
|
1999-07-19 19:06:39 +00:00
|
|
|
{
|
|
|
|
if (!aNodeList)
|
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
#else
|
|
|
|
nsresult res;
|
|
|
|
|
1999-07-19 22:36:12 +00:00
|
|
|
res = NS_NewISupportsArray(aNodeList);
|
|
|
|
if (NS_FAILED(res) || !*aNodeList)
|
1999-07-19 19:06:39 +00:00
|
|
|
return res;
|
1999-07-19 22:36:12 +00:00
|
|
|
//NS_ADDREF(*aNodeList);
|
1999-07-19 19:06:39 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsIContentIterator> iter;
|
|
|
|
res = nsComponentManager::CreateInstance(kCContentIteratorCID, nsnull,
|
|
|
|
nsIContentIterator::GetIID(),
|
|
|
|
getter_AddRefs(iter));
|
|
|
|
if ((NS_SUCCEEDED(res)) && iter)
|
|
|
|
{
|
|
|
|
// get the root content
|
|
|
|
nsCOMPtr<nsIContent> rootContent;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMDocument> domdoc;
|
|
|
|
nsEditor::GetDocument(getter_AddRefs(domdoc));
|
|
|
|
if (!domdoc)
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocument> doc (do_QueryInterface(domdoc));
|
|
|
|
if (!doc)
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
|
|
|
|
rootContent = doc->GetRootContent();
|
|
|
|
|
|
|
|
iter->Init(rootContent);
|
|
|
|
|
|
|
|
// loop through the content iterator for each content node
|
|
|
|
while (NS_COMFALSE == iter->IsDone())
|
|
|
|
{
|
1999-07-19 22:36:12 +00:00
|
|
|
nsCOMPtr<nsIContent> content;
|
|
|
|
res = iter->CurrentNode(getter_AddRefs(content));
|
|
|
|
if (NS_FAILED(res))
|
|
|
|
break;
|
1999-07-19 19:06:39 +00:00
|
|
|
nsCOMPtr<nsIDOMNode> node (do_QueryInterface(content));
|
|
|
|
if (node)
|
|
|
|
{
|
|
|
|
nsAutoString tagName;
|
|
|
|
node->GetNodeName(tagName);
|
|
|
|
tagName.ToLowerCase();
|
|
|
|
|
|
|
|
// See if it's an image or an embed
|
|
|
|
if (tagName == "img" || tagName == "embed")
|
1999-07-19 22:36:12 +00:00
|
|
|
(*aNodeList)->AppendElement(node);
|
|
|
|
else if (tagName == "a")
|
|
|
|
{
|
|
|
|
// XXX Only include links if they're links to file: URLs
|
|
|
|
}
|
1999-07-19 19:06:39 +00:00
|
|
|
}
|
|
|
|
iter->Next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
#endif
|
|
|
|
}
|
1999-05-17 12:22:31 +00:00
|
|
|
|
1999-05-05 04:05:19 +00: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-03 22:57:48 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::BeginComposition(void)
|
|
|
|
{
|
|
|
|
return nsTextEditor::BeginComposition();
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsHTMLEditor::EndComposition(void)
|
|
|
|
{
|
|
|
|
return nsTextEditor::EndComposition();
|
|
|
|
}
|
|
|
|
|
1999-06-29 20:31:22 +00:00
|
|
|
NS_IMETHODIMP nsHTMLEditor::SetCompositionString(const nsString& aCompositionString, nsIDOMTextRangeList* aTextRangeList)
|
1999-05-03 22:57:48 +00:00
|
|
|
{
|
1999-06-29 20:31:22 +00:00
|
|
|
return nsTextEditor::SetCompositionString(aCompositionString,aTextRangeList);
|
1999-05-05 04:05:19 +00:00
|
|
|
}
|
1999-05-26 21:40:51 +00:00
|
|
|
|
1999-05-27 04:10:04 +00: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
|
|
|
|
}
|
1999-06-14 20:02:46 +00:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::StartLogging(nsIFileSpec *aLogFile)
|
|
|
|
{
|
|
|
|
return nsTextEditor::StartLogging(aLogFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsHTMLEditor::StopLogging()
|
|
|
|
{
|
|
|
|
return nsTextEditor::StopLogging();
|
|
|
|
}
|
|
|
|
|