gecko-dev/editor/base/nsHTMLEditor.cpp
buster%netscape.com 5333e448a3 implemented GetTextProperty -- only works for bold and italic now,
trivial to add more properties
finished first cut at SetTextProperty.  This triggers lots of crashes in
range/selection code where we're holding onto a stale frame pointer (at
least, that's my best guess.)
synched with Charlie's change-o-rama
added an assert in DeleteTextTxn::Init() checking aNumCharsToDelete vs.
0
  NS_ASSERTION(0!=aNumCharsToDelete, "bad arg, numCharsToDelete");
if the number of chars to delete is 0, we shouldn't be creating a
transaction at all.  I had never seen this condition arise before
Charlie's checkin, I don't know if he introduced it or if it was a
latent bug I just never tripped over before.
1999-03-02 07:52:41 +00:00

417 lines
10 KiB
C++

/* -*- 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"
#include "nsEditorEventListeners.h"
#include "nsIDOMDocument.h"
#include "nsIDOMEventReceiver.h"
#include "nsIDOMKeyListener.h"
#include "nsIDOMMouseListener.h"
#include "nsEditorCID.h"
#include "nsRepository.h"
#include "nsIServiceManager.h"
#include "nsITableCellLayout.h" //For GetColIndexForCell
static NS_DEFINE_IID(kIDOMEventReceiverIID, NS_IDOMEVENTRECEIVER_IID);
static NS_DEFINE_IID(kIDOMMouseListenerIID, NS_IDOMMOUSELISTENER_IID);
static NS_DEFINE_IID(kIDOMKeyListenerIID, NS_IDOMKEYLISTENER_IID);
static NS_DEFINE_CID(kEditorCID, NS_EDITOR_CID);
static NS_DEFINE_IID(kIEditorIID, NS_IEDITOR_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kITextEditorIID, NS_ITEXTEDITOR_IID);
static NS_DEFINE_CID(kTextEditorCID, NS_TEXTEDITOR_CID);
static NS_DEFINE_IID(kIHTMLEditorIID, NS_IHTMLEDITOR_IID);
static NS_DEFINE_CID(kHTMLEditorCID, NS_HTMLEDITOR_CID);
nsHTMLEditor::nsHTMLEditor()
{
NS_INIT_REFCNT();
}
nsHTMLEditor::~nsHTMLEditor()
{
//the autopointers will clear themselves up.
#if 0
// NO EVENT LISTERNERS YET
//but we need to also remove the listeners or we have a leak
//(This is identical to nsTextEditor code
if (mEditor)
{
nsCOMPtr<nsIDOMDocument> doc;
mEditor->GetDocument(getter_AddRefs(doc));
if (doc)
{
nsCOMPtr<nsIDOMEventReceiver> erP;
nsresult result = doc->QueryInterface(kIDOMEventReceiverIID, getter_AddRefs(erP));
if (NS_SUCCEEDED(result) && erP)
{
if (mKeyListenerP) {
erP->RemoveEventListener(mKeyListenerP, kIDOMKeyListenerIID);
}
if (mMouseListenerP) {
erP->RemoveEventListener(mMouseListenerP, kIDOMMouseListenerIID);
}
}
else
NS_NOTREACHED("~nsHTMLEditor");
}
}
#endif
}
NS_IMETHODIMP nsHTMLEditor::InitHTMLEditor(nsIDOMDocument *aDoc,
nsIPresShell *aPresShell,
nsIEditorCallback *aCallback)
{
NS_PRECONDITION(nsnull!=aDoc && nsnull!=aPresShell, "bad arg");
nsresult result=NS_ERROR_NULL_POINTER;
if ((nsnull!=aDoc) && (nsnull!=aPresShell))
{
nsITextEditor *aTextEditor = nsnull;
result = nsRepository::CreateInstance(kTextEditorCID, nsnull,
kITextEditorIID, (void **)&aTextEditor);
if (NS_FAILED(result) || !aTextEditor) {
return NS_ERROR_OUT_OF_MEMORY;
}
mTextEditor = do_QueryInterface(aTextEditor); // CreateInstance did our addRef
// Initialize nsTextEditor -- this will create and initialize the base nsEditor
// Note: nsTextEditor adds its own key, mouse, and DOM listners -- is that OK?
result = mTextEditor->InitTextEditor(aDoc, aPresShell);
if (NS_OK != result) {
return result;
}
mTextEditor->EnableUndo(PR_TRUE);
// Get the pointer to the base editor for easier access
result = mTextEditor->QueryInterface(kIEditorIID, getter_AddRefs(mEditor));
if (NS_OK != result) {
return result;
}
result = NS_OK;
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::SetTextProperty(nsIAtom *aProperty)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mTextEditor->SetTextProperty(aProperty);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::GetTextProperty(nsIAtom *aProperty, PRBool &aAny, PRBool &aAll)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mTextEditor->GetTextProperty(aProperty, aAny, aAll);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::RemoveTextProperty(nsIAtom *aProperty)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mTextEditor->RemoveTextProperty(aProperty);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::DeleteSelection(nsIEditor::Direction aDir)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mEditor->DeleteSelection(aDir);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::InsertText(const nsString& aStringToInsert)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mEditor->InsertText(aStringToInsert);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::InsertBreak(PRBool aCtrlKey)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mTextEditor->InsertBreak(aCtrlKey);
}
return result;
}
// Methods shared with the base editor.
// Note: We could call each of these via nsTextEditor -- is that better?
NS_IMETHODIMP nsHTMLEditor::EnableUndo(PRBool aEnable)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mEditor->EnableUndo(aEnable);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::Undo(PRUint32 aCount)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mEditor->Undo(aCount);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::CanUndo(PRBool &aIsEnabled, PRBool &aCanUndo)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mEditor->CanUndo(aIsEnabled, aCanUndo);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::Redo(PRUint32 aCount)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mEditor->Redo(aCount);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::CanRedo(PRBool &aIsEnabled, PRBool &aCanRedo)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mEditor->CanRedo(aIsEnabled, aCanRedo);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::BeginTransaction()
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mEditor->BeginTransaction();
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::EndTransaction()
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mEditor->EndTransaction();
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::MoveSelectionUp(nsIAtom *aIncrement, PRBool aExtendSelection)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mTextEditor->MoveSelectionUp(aIncrement, aExtendSelection);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::MoveSelectionDown(nsIAtom *aIncrement, PRBool aExtendSelection)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mTextEditor->MoveSelectionDown(aIncrement, aExtendSelection);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::MoveSelectionNext(nsIAtom *aIncrement, PRBool aExtendSelection)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mTextEditor->MoveSelectionNext(aIncrement, aExtendSelection);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::MoveSelectionPrevious(nsIAtom *aIncrement, PRBool aExtendSelection)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mTextEditor->MoveSelectionPrevious(aIncrement, aExtendSelection);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::SelectNext(nsIAtom *aIncrement, PRBool aExtendSelection)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mTextEditor->SelectNext(aIncrement, aExtendSelection);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::SelectPrevious(nsIAtom *aIncrement, PRBool aExtendSelection)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mTextEditor->SelectPrevious(aIncrement, aExtendSelection);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::ScrollUp(nsIAtom *aIncrement)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mTextEditor->ScrollUp(aIncrement);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::ScrollDown(nsIAtom *aIncrement)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mTextEditor->ScrollDown(aIncrement);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::ScrollIntoView(PRBool aScrollToBegin)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mTextEditor->ScrollIntoView(aScrollToBegin);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::Insert(nsIInputStream *aInputStream)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mTextEditor->Insert(aInputStream);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::OutputText(nsIOutputStream *aOutputStream)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mTextEditor->OutputText(aOutputStream);
}
return result;
}
NS_IMETHODIMP nsHTMLEditor::OutputHTML(nsIOutputStream *aOutputStream)
{
nsresult result=NS_ERROR_NOT_INITIALIZED;
if (mEditor)
{
result = mTextEditor->OutputHTML(aOutputStream);
}
return result;
}
NS_IMPL_ADDREF(nsHTMLEditor)
NS_IMPL_RELEASE(nsHTMLEditor)
NS_IMETHODIMP
nsHTMLEditor::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (nsnull == aInstancePtr) {
return NS_ERROR_NULL_POINTER;
}
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*)(nsISupports*)this;
NS_ADDREF_THIS();
return NS_OK;
}
if (aIID.Equals(kIHTMLEditorIID)) {
*aInstancePtr = (void*)(nsIHTMLEditor*)this;
NS_ADDREF_THIS();
return NS_OK;
}
// If our pointer to nsTextEditor is null, don't bother querying?
if (aIID.Equals(kITextEditorIID) && (mTextEditor)) {
nsCOMPtr<nsIEditor> editor;
nsresult result = mTextEditor->QueryInterface(kITextEditorIID, getter_AddRefs(editor));
if (NS_SUCCEEDED(result) && editor) {
*aInstancePtr = (void*)editor;
return NS_OK;
}
}
if (aIID.Equals(kIEditorIID) && (mEditor)) {
nsCOMPtr<nsIEditor> editor;
nsresult result = mEditor->QueryInterface(kIEditorIID, getter_AddRefs(editor));
if (NS_SUCCEEDED(result) && editor) {
*aInstancePtr = (void*)editor;
return NS_OK;
}
}
return NS_NOINTERFACE;
}
//================================================================
// HTML Editor methods
//
// Note: Table Editing methods are implemented in EditTable.cpp
//