From 36a0cbad9e5a724ec03fa09fb77773c0f21da806 Mon Sep 17 00:00:00 2001 From: "jfrancis%netscape.com" Date: Mon, 12 Apr 1999 12:01:32 +0000 Subject: [PATCH] checkpointing html typing rules --- editor/base/nsEditRules.h | 25 +- editor/base/nsHTMLEditRules.cpp | 325 +++++++++++++++++++++- editor/base/nsHTMLEditRules.h | 58 +++- editor/base/nsHTMLEditor.cpp | 5 +- editor/base/nsTextEditRules.cpp | 67 +++-- editor/base/nsTextEditRules.h | 51 ++-- editor/base/nsTextEditor.cpp | 26 +- editor/libeditor/base/nsEditRules.h | 25 +- editor/libeditor/html/nsHTMLEditRules.cpp | 325 +++++++++++++++++++++- editor/libeditor/html/nsHTMLEditRules.h | 58 +++- editor/libeditor/html/nsHTMLEditor.cpp | 5 +- editor/libeditor/text/nsTextEditRules.cpp | 67 +++-- editor/libeditor/text/nsTextEditRules.h | 51 ++-- 13 files changed, 944 insertions(+), 144 deletions(-) diff --git a/editor/base/nsEditRules.h b/editor/base/nsEditRules.h index 0802a1e9a9e..5152505ff5d 100644 --- a/editor/base/nsEditRules.h +++ b/editor/base/nsEditRules.h @@ -22,15 +22,30 @@ class nsIEditor; class nsIDOMSelection; -/** Interface of editing rules. - * - */ +/*************************************************************************** + * base for an object to encapsulate any additional info needed to be passed + * to rules system by the editor + */ +class nsRulesInfo +{ + public: + + nsRulesInfo(int aAction) : action(aAction) {} + virtual ~nsRulesInfo() {} + + int action; +}; + +/*************************************************************************** + * Interface of editing rules. + * + */ class nsEditRules { public: NS_IMETHOD Init(nsIEditor *aEditor)=0; - NS_IMETHOD WillDoAction(int aAction, nsIDOMSelection *aSelection, void **aOtherInfo, PRBool *aCancel)=0; - NS_IMETHOD DidDoAction(int aAction, nsIDOMSelection *aSelection, void **aOtherInfo, nsresult aResult)=0; + NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel)=0; + NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult)=0; }; diff --git a/editor/base/nsHTMLEditRules.cpp b/editor/base/nsHTMLEditRules.cpp index 8db14d5a6d8..6d3814c999d 100644 --- a/editor/base/nsHTMLEditRules.cpp +++ b/editor/base/nsHTMLEditRules.cpp @@ -20,7 +20,6 @@ #include "nsEditor.h" #include "PlaceholderTxn.h" #include "InsertTextTxn.h" -#include "nsCOMPtr.h" #include "nsIDOMNode.h" #include "nsIDOMElement.h" #include "nsIDOMNodeList.h" @@ -35,16 +34,110 @@ const static char* kMOZEditorBogusNodeValue="TRUE"; static NS_DEFINE_IID(kPlaceholderTxnIID, PLACEHOLDER_TXN_IID); +nsIAtom *nsHTMLEditRules::sAAtom; +nsIAtom *nsHTMLEditRules::sAddressAtom; +nsIAtom *nsHTMLEditRules::sBigAtom; +nsIAtom *nsHTMLEditRules::sBlinkAtom; +nsIAtom *nsHTMLEditRules::sBAtom; +nsIAtom *nsHTMLEditRules::sCiteAtom; +nsIAtom *nsHTMLEditRules::sCodeAtom; +nsIAtom *nsHTMLEditRules::sDfnAtom; +nsIAtom *nsHTMLEditRules::sEmAtom; +nsIAtom *nsHTMLEditRules::sFontAtom; +nsIAtom *nsHTMLEditRules::sIAtom; +nsIAtom *nsHTMLEditRules::sKbdAtom; +nsIAtom *nsHTMLEditRules::sKeygenAtom; +nsIAtom *nsHTMLEditRules::sNobrAtom; +nsIAtom *nsHTMLEditRules::sSAtom; +nsIAtom *nsHTMLEditRules::sSampAtom; +nsIAtom *nsHTMLEditRules::sSmallAtom; +nsIAtom *nsHTMLEditRules::sSpacerAtom; +nsIAtom *nsHTMLEditRules::sSpanAtom; +nsIAtom *nsHTMLEditRules::sStrikeAtom; +nsIAtom *nsHTMLEditRules::sStrongAtom; +nsIAtom *nsHTMLEditRules::sSubAtom; +nsIAtom *nsHTMLEditRules::sSupAtom; +nsIAtom *nsHTMLEditRules::sTtAtom; +nsIAtom *nsHTMLEditRules::sUAtom; +nsIAtom *nsHTMLEditRules::sVarAtom; +nsIAtom *nsHTMLEditRules::sWbrAtom; + +PRInt32 nsHTMLEditRules::sInstanceCount; + /******************************************************** * Constructor/Destructor ********************************************************/ nsHTMLEditRules::nsHTMLEditRules() { + if (sInstanceCount <= 0) + { + sAAtom = NS_NewAtom("a"); + sAddressAtom = NS_NewAtom("address"); + sBigAtom = NS_NewAtom("big"); + sBlinkAtom = NS_NewAtom("blink"); + sBAtom = NS_NewAtom("b"); + sCiteAtom = NS_NewAtom("cite"); + sCodeAtom = NS_NewAtom("code"); + sDfnAtom = NS_NewAtom("dfn"); + sEmAtom = NS_NewAtom("em"); + sFontAtom = NS_NewAtom("font"); + sIAtom = NS_NewAtom("i"); + sKbdAtom = NS_NewAtom("kbd"); + sKeygenAtom = NS_NewAtom("keygen"); + sNobrAtom = NS_NewAtom("nobr"); + sSAtom = NS_NewAtom("s"); + sSampAtom = NS_NewAtom("samp"); + sSmallAtom = NS_NewAtom("small"); + sSpacerAtom = NS_NewAtom("spacer"); + sSpanAtom = NS_NewAtom("span"); + sStrikeAtom = NS_NewAtom("strike"); + sStrongAtom = NS_NewAtom("strong"); + sSubAtom = NS_NewAtom("sub"); + sSupAtom = NS_NewAtom("sup"); + sTtAtom = NS_NewAtom("tt"); + sUAtom = NS_NewAtom("u"); + sVarAtom = NS_NewAtom("var"); + sWbrAtom = NS_NewAtom("wbr"); + } + + ++sInstanceCount; } nsHTMLEditRules::~nsHTMLEditRules() { + if (sInstanceCount <= 1) + { + NS_IF_RELEASE(sAAtom); + NS_IF_RELEASE(sAddressAtom); + NS_IF_RELEASE(sBigAtom); + NS_IF_RELEASE(sBlinkAtom); + NS_IF_RELEASE(sBAtom); + NS_IF_RELEASE(sCiteAtom); + NS_IF_RELEASE(sCodeAtom); + NS_IF_RELEASE(sDfnAtom); + NS_IF_RELEASE(sEmAtom); + NS_IF_RELEASE(sFontAtom); + NS_IF_RELEASE(sIAtom); + NS_IF_RELEASE(sKbdAtom); + NS_IF_RELEASE(sKeygenAtom); + NS_IF_RELEASE(sNobrAtom); + NS_IF_RELEASE(sSAtom); + NS_IF_RELEASE(sSampAtom); + NS_IF_RELEASE(sSmallAtom); + NS_IF_RELEASE(sSpacerAtom); + NS_IF_RELEASE(sSpanAtom); + NS_IF_RELEASE(sStrikeAtom); + NS_IF_RELEASE(sStrongAtom); + NS_IF_RELEASE(sSubAtom); + NS_IF_RELEASE(sSupAtom); + NS_IF_RELEASE(sTtAtom); + NS_IF_RELEASE(sUAtom); + NS_IF_RELEASE(sVarAtom); + NS_IF_RELEASE(sWbrAtom); + } + + --sInstanceCount; } @@ -53,40 +146,94 @@ nsHTMLEditRules::~nsHTMLEditRules() ********************************************************/ NS_IMETHODIMP -nsHTMLEditRules::WillDoAction(int aAction, nsIDOMSelection *aSelection, - void **aOtherInfo, PRBool *aCancel) +nsHTMLEditRules::WillDoAction(nsIDOMSelection *aSelection, + nsRulesInfo *aInfo, PRBool *aCancel) { - if (!aSelection) + if (!aSelection || !aInfo) return NS_ERROR_NULL_POINTER; - switch (aAction) + // my kingdom for dynamic cast + nsTextRulesInfo *info = NS_STATIC_CAST(nsTextRulesInfo*, aInfo); + + switch (info->action) { + case kInsertText: + return WillInsertText(aSelection, + aCancel, + info->placeTxn, + info->inString, + info->outString, + info->typeInState); case kInsertBreak: return WillInsertBreak(aSelection, aCancel); } - return nsTextEditRules::WillDoAction(aAction, aSelection, aOtherInfo, aCancel); + return nsTextEditRules::WillDoAction(aSelection, aInfo, aCancel); } NS_IMETHODIMP -nsHTMLEditRules::DidDoAction(int aAction, nsIDOMSelection *aSelection, - void **aOtherInfo, nsresult aResult) +nsHTMLEditRules::DidDoAction(nsIDOMSelection *aSelection, + nsRulesInfo *aInfo, nsresult aResult) { - if (!aSelection) + if (!aSelection || !aInfo) return NS_ERROR_NULL_POINTER; - switch (aAction) + // my kingdom for dynamic cast + nsTextRulesInfo *info = NS_STATIC_CAST(nsTextRulesInfo*, aInfo); + + switch (info->action) { + case kInsertText: + return DidInsertText(aSelection, aResult); case kInsertBreak: return DidInsertBreak(aSelection, aResult); } - return nsTextEditRules::DidDoAction(aAction, aSelection, aOtherInfo, aResult); + return nsTextEditRules::DidDoAction(aSelection, aInfo, aResult); } /******************************************************** - * Protected methods + * Protected rules methods ********************************************************/ -NS_IMETHODIMP + +nsresult +nsHTMLEditRules::WillInsertText(nsIDOMSelection *aSelection, + PRBool *aCancel, + PlaceholderTxn **aTxn, + const nsString *inString, + nsString *outString, + TypeInState typeInState) +{ + if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; } + // initialize out param + *aCancel = PR_FALSE; + + // XXX - need to handle strings of length >1 with embedded tabs or spaces + + // is it a tab? + if (*inString == "\t" ) + return InsertTab(aSelection,aCancel,aTxn,outString); + // is it a space? + if (*inString == " ") + return InsertSpace(aSelection,aCancel,aTxn,outString); + + // otherwise, return nsTextEditRules version + return nsTextEditRules::WillInsertText(aSelection, + aCancel, + aTxn, + inString, + outString, + typeInState); +} + +nsresult +nsHTMLEditRules::DidInsertText(nsIDOMSelection *aSelection, + nsresult aResult) +{ + // for now, return nsTextEditRules version + return nsTextEditRules::DidInsertText(aSelection, aResult); +} + +nsresult nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel) { if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; } @@ -97,7 +244,7 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel) // XXX: this code is all experimental, and has no effect on the content model yet // the point here is to collapse adjacent BR's into P's -NS_IMETHODIMP +nsresult nsHTMLEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult) { nsresult result = aResult; // if aResult is an error, we return it. @@ -196,3 +343,153 @@ nsHTMLEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult) } return result; } + + + +/******************************************************** + * helper methods + ********************************************************/ + +PRBool +nsHTMLEditRules::IsBlockNode(nsIContent *aContent) +{ + nsIAtom* atom = nsnull; + PRBool result; + + aContent->GetTag(atom); + + if (!atom) + return PR_TRUE; + + if (sAAtom != atom && + sAddressAtom != atom && + sBigAtom != atom && + sBlinkAtom != atom && + sBAtom != atom && + sCiteAtom != atom && + sCodeAtom != atom && + sDfnAtom != atom && + sEmAtom != atom && + sFontAtom != atom && + sIAtom != atom && + sKbdAtom != atom && + sKeygenAtom != atom && + sNobrAtom != atom && + sSAtom != atom && + sSampAtom != atom && + sSmallAtom != atom && + sSpacerAtom != atom && + sSpanAtom != atom && + sStrikeAtom != atom && + sStrongAtom != atom && + sSubAtom != atom && + sSupAtom != atom && + sTtAtom != atom && + sUAtom != atom && + sVarAtom != atom && + sWbrAtom != atom) + { + result = PR_TRUE; + } + else + { + result = PR_FALSE; + } + NS_RELEASE(atom); + return result; +} + +nsCOMPtr +nsHTMLEditRules::GetBlockNodeParent(nsCOMPtr aContent) +{ + nsCOMPtr p; + + if (NS_FAILED(aContent->GetParent(*getter_AddRefs(p)))) // no parent, ran off top of tree + return aContent; + + nsCOMPtr tmp; + + while (p && !IsBlockNode(p)) + { + if (NS_FAILED(p->GetParent(*getter_AddRefs(tmp)))) // no parent, ran off top of tree + return p; + + p = tmp; + } + return p; +} + +/////////////////////////////////////////////////////////////////////////// +// GetStartNode: returns whatever the start parent is of the first range +// in the selection. +nsCOMPtr +nsHTMLEditRules::GetStartNode(nsIDOMSelection *aSelection) +{ + nsCOMPtr startNode; + nsCOMPtr enumerator; + enumerator = do_QueryInterface(aSelection); + if (!enumerator) + return startNode; + enumerator->First(); + nsISupports *currentItem; + if ((NS_FAILED(enumerator->CurrentItem(¤tItem))) || !currentItem) + return startNode; + + nsCOMPtr range( do_QueryInterface(currentItem) ); + if (!range) + return startNode; + range->GetStartParent(getter_AddRefs(startNode)); + return startNode; +} + + +/////////////////////////////////////////////////////////////////////////// +// IsPreformatted: checks the style info for the node for the preformatted +// text style. +nsresult +nsHTMLEditRules::IsPreformatted(nsCOMPtr aNode, PRBool *aResult) +{ + return PR_TRUE; +} + + +nsresult +nsHTMLEditRules::InsertTab(nsIDOMSelection *aSelection, + PRBool *aCancel, + PlaceholderTxn **aTxn, + nsString *outString) +{ + nsCOMPtr theNode; + PRBool isPRE; + theNode = GetStartNode(aSelection); + if (!theNode) + return NS_ERROR_UNEXPECTED; + nsresult result = IsPreformatted(theNode,&isPRE); + if (NS_FAILED(result)) + return result; + if (isPRE) + { + outString += '\t'; + // we're done - let everything fall through to the InsertText code + // in nsTextEditor which will insert the tab as is. + } + else + { + + } + return NS_OK; +} + + +nsresult +nsHTMLEditRules::InsertSpace(nsIDOMSelection *aSelection, + PRBool *aCancel, + PlaceholderTxn **aTxn, + nsString *outString) +{ + return NS_OK; +} + + + + diff --git a/editor/base/nsHTMLEditRules.h b/editor/base/nsHTMLEditRules.h index f11ff94dd8b..eb98544f45a 100644 --- a/editor/base/nsHTMLEditRules.h +++ b/editor/base/nsHTMLEditRules.h @@ -20,6 +20,9 @@ #define nsHTMLEditRules_h__ #include "nsTextEditRules.h" +#include "nsCOMPtr.h" + +class nsIContent; class nsHTMLEditRules : public nsTextEditRules { @@ -29,8 +32,8 @@ public: virtual ~nsHTMLEditRules(); // nsEditRules methods - NS_IMETHOD WillDoAction(int aAction, nsIDOMSelection *aSelection, void **aOtherInfo, PRBool *aCancel); - NS_IMETHOD DidDoAction(int aAction, nsIDOMSelection *aSelection, void **aOtherInfo, nsresult aResult); + NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel); + NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult); // nsHTMLEditRules action id's enum @@ -40,9 +43,56 @@ public: protected: // nsHTMLEditRules implementation methods - NS_IMETHOD WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel); - NS_IMETHOD DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult); + nsresult WillInsertText(nsIDOMSelection *aSelection, + PRBool *aCancel, + PlaceholderTxn **aTxn, + const nsString *inString, + nsString *outString, + TypeInState typeInState); + nsresult DidInsertText(nsIDOMSelection *aSelection, nsresult aResult); + nsresult WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel); + nsresult DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult); + + nsresult InsertTab(nsIDOMSelection *aSelection, PRBool *aCancel, PlaceholderTxn **aTxn, nsString *outString); + nsresult InsertSpace(nsIDOMSelection *aSelection, PRBool *aCancel, PlaceholderTxn **aTxn, nsString *outString); + + // helper methods + PRBool IsBlockNode(nsIContent *aContent); + nsCOMPtr GetBlockNodeParent(nsCOMPtr aContent); + nsCOMPtr GetStartNode(nsIDOMSelection *aSelection); + nsresult IsPreformatted(nsCOMPtr aNode, PRBool *aResult); + + // data + static nsIAtom *sAAtom; + static nsIAtom *sAddressAtom; + static nsIAtom *sBigAtom; + static nsIAtom *sBlinkAtom; + static nsIAtom *sBAtom; + static nsIAtom *sCiteAtom; + static nsIAtom *sCodeAtom; + static nsIAtom *sDfnAtom; + static nsIAtom *sEmAtom; + static nsIAtom *sFontAtom; + static nsIAtom *sIAtom; + static nsIAtom *sKbdAtom; + static nsIAtom *sKeygenAtom; + static nsIAtom *sNobrAtom; + static nsIAtom *sSAtom; + static nsIAtom *sSampAtom; + static nsIAtom *sSmallAtom; + static nsIAtom *sSpacerAtom; + static nsIAtom *sSpanAtom; + static nsIAtom *sStrikeAtom; + static nsIAtom *sStrongAtom; + static nsIAtom *sSubAtom; + static nsIAtom *sSupAtom; + static nsIAtom *sTtAtom; + static nsIAtom *sUAtom; + static nsIAtom *sVarAtom; + static nsIAtom *sWbrAtom; + + static PRInt32 sInstanceCount; }; #endif //nsHTMLEditRules_h__ diff --git a/editor/base/nsHTMLEditor.cpp b/editor/base/nsHTMLEditor.cpp index 86fc93fa5cb..b3f274b42eb 100644 --- a/editor/base/nsHTMLEditor.cpp +++ b/editor/base/nsHTMLEditor.cpp @@ -147,7 +147,8 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak() // pre-process nsEditor::GetSelection(getter_AddRefs(selection)); - result = mRules->WillDoAction(nsHTMLEditRules::kInsertBreak, selection, nsnull, &cancel); + nsTextRulesInfo ruleInfo(nsHTMLEditRules::kInsertBreak); + result = mRules->WillDoAction(selection, &ruleInfo, &cancel); if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) { // create the new BR node @@ -197,7 +198,7 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak() } } // post-process, always called if WillInsertBreak didn't return cancel==PR_TRUE - result = mRules->DidDoAction(nsHTMLEditRules::kInsertBreak, selection, nsnull, result); + result = mRules->DidDoAction(selection, &ruleInfo, result); } nsresult endTxnResult = nsEditor::EndTransaction(); // don't return this result! NS_ASSERTION ((NS_SUCCEEDED(endTxnResult)), "bad end transaction result"); diff --git a/editor/base/nsTextEditRules.cpp b/editor/base/nsTextEditRules.cpp index 3266ac91bfd..65aa6da1a60 100644 --- a/editor/base/nsTextEditRules.cpp +++ b/editor/base/nsTextEditRules.cpp @@ -125,16 +125,24 @@ nsTextEditRules::Init(nsIEditor *aEditor) } NS_IMETHODIMP -nsTextEditRules::WillDoAction(int aAction, nsIDOMSelection *aSelection, - void **aOtherInfo, PRBool *aCancel) +nsTextEditRules::WillDoAction(nsIDOMSelection *aSelection, + nsRulesInfo *aInfo, PRBool *aCancel) { - if (!aSelection) + if (!aSelection || !aInfo) return NS_ERROR_NULL_POINTER; + + // my kingdom for dynamic cast + nsTextRulesInfo *info = NS_STATIC_CAST(nsTextRulesInfo*, aInfo); - switch (aAction) + switch (info->action) { case kInsertText: - return WillInsertText(aSelection, aCancel, (PlaceholderTxn**)aOtherInfo); + return WillInsertText(aSelection, + aCancel, + info->placeTxn, + info->inString, + info->outString, + info->typeInState); case kDeleteSelection: return WillDeleteSelection(aSelection, aCancel); case kUndo: @@ -146,13 +154,16 @@ nsTextEditRules::WillDoAction(int aAction, nsIDOMSelection *aSelection, } NS_IMETHODIMP -nsTextEditRules::DidDoAction(int aAction, nsIDOMSelection *aSelection, - void **aOtherInfo, nsresult aResult) +nsTextEditRules::DidDoAction(nsIDOMSelection *aSelection, + nsRulesInfo *aInfo, nsresult aResult) { - if (!aSelection) + if (!aSelection || !aInfo) return NS_ERROR_NULL_POINTER; - switch (aAction) + // my kingdom for dynamic cast + nsTextRulesInfo *info = NS_STATIC_CAST(nsTextRulesInfo*, aInfo); + + switch (info->action) { case kInsertText: return DidInsertText(aSelection, aResult); @@ -172,7 +183,7 @@ nsTextEditRules::DidDoAction(int aAction, nsIDOMSelection *aSelection, ********************************************************/ -NS_IMETHODIMP +nsresult nsTextEditRules::WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel) { if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; } @@ -191,21 +202,23 @@ nsTextEditRules::WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel) return NS_OK; } -NS_IMETHODIMP +nsresult nsTextEditRules::DidInsert(nsIDOMSelection *aSelection, nsresult aResult) { return NS_OK; } -NS_IMETHODIMP -nsTextEditRules::WillInsertText(nsIDOMSelection *aSelection, - PRBool *aCancel, - PlaceholderTxn **aTxn) +nsresult +nsTextEditRules::WillInsertText(nsIDOMSelection *aSelection, + PRBool *aCancel, + PlaceholderTxn **aTxn, + const nsString *inString, + nsString *outString, + TypeInState typeInState) { if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; } // initialize out param *aCancel = PR_FALSE; - TypeInState typeInState = mEditor->GetTypeInState(); if (mBogusNode || (PR_TRUE==typeInState.IsAnySet())) { nsresult result = TransactionFactory::GetNewTransaction(kPlaceholderTxnIID, (EditTxn **)aTxn); @@ -225,14 +238,14 @@ nsTextEditRules::WillInsertText(nsIDOMSelection *aSelection, return result; } -NS_IMETHODIMP +nsresult nsTextEditRules::DidInsertText(nsIDOMSelection *aSelection, nsresult aResult) { return DidInsert(aSelection, aResult); } -NS_IMETHODIMP +nsresult nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInState &aTypeInState) { // private method, we know aSelection is not null, and that it is collapsed @@ -356,7 +369,7 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta return result; } -NS_IMETHODIMP +nsresult nsTextEditRules::InsertStyleNode(nsIDOMNode *aNode, nsIAtom *aTag, nsIDOMSelection *aSelection) { NS_ASSERTION(aNode && aTag, "bad args"); @@ -388,7 +401,7 @@ nsTextEditRules::InsertStyleNode(nsIDOMNode *aNode, nsIAtom *aTag, nsIDOMSelecti } -NS_IMETHODIMP +nsresult nsTextEditRules::InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, nsIAtom *aTag, nsIDOMSelection *aSelection) { NS_ASSERTION(aParentNode && aTag, "bad args"); @@ -433,7 +446,7 @@ nsTextEditRules::InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, nsIAtom *aTa /* -NS_IMETHODIMP +nsresult nsTextEditRules::GetInsertBreakTag(nsIAtom **aTag) { if (!aTag) { return NS_ERROR_NULL_POINTER; } @@ -442,7 +455,7 @@ nsTextEditRules::GetInsertBreakTag(nsIAtom **aTag) } */ -NS_IMETHODIMP +nsresult nsTextEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCancel) { if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; } @@ -459,7 +472,7 @@ nsTextEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCance // if the document is empty, insert a bogus text node with a   // if we ended up with consecutive text nodes, merge them -NS_IMETHODIMP +nsresult nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResult) { nsresult result = aResult; // if aResult is an error, we just return it @@ -600,7 +613,7 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResul return result; } -NS_IMETHODIMP +nsresult nsTextEditRules::WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel) { if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; } @@ -614,7 +627,7 @@ nsTextEditRules::WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel) * There is a tradeoff between doing here and at redo, or doing it everywhere else that might care. * Since undo and redo are relatively rare, it makes sense to take the (small) performance hit here. */ -NS_IMETHODIMP +nsresult nsTextEditRules:: DidUndo(nsIDOMSelection *aSelection, nsresult aResult) { nsresult result = aResult; // if aResult is an error, we return it. @@ -651,7 +664,7 @@ nsTextEditRules:: DidUndo(nsIDOMSelection *aSelection, nsresult aResult) return result; } -NS_IMETHODIMP +nsresult nsTextEditRules::WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel) { if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; } @@ -660,7 +673,7 @@ nsTextEditRules::WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel) return NS_OK; } -NS_IMETHODIMP +nsresult nsTextEditRules::DidRedo(nsIDOMSelection *aSelection, nsresult aResult) { nsresult result = aResult; // if aResult is an error, we return it. diff --git a/editor/base/nsTextEditRules.h b/editor/base/nsTextEditRules.h index 80a27f5647b..af6a28de626 100644 --- a/editor/base/nsTextEditRules.h +++ b/editor/base/nsTextEditRules.h @@ -48,8 +48,8 @@ public: // nsEditRules methods NS_IMETHOD Init(nsIEditor *aEditor); - NS_IMETHOD WillDoAction(int aAction, nsIDOMSelection *aSelection, void **aOtherInfo, PRBool *aCancel); - NS_IMETHOD DidDoAction(int aAction, nsIDOMSelection *aSelection, void **aOtherInfo, nsresult aResult); + NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel); + NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult); // nsTextEditRules action id's enum @@ -63,23 +63,26 @@ public: protected: // nsTextEditRules implementation methods - NS_IMETHOD WillInsertText(nsIDOMSelection *aSelection, + nsresult WillInsertText(nsIDOMSelection *aSelection, PRBool *aCancel, - PlaceholderTxn **aTxn); - NS_IMETHOD DidInsertText(nsIDOMSelection *aSelection, nsresult aResult); - NS_IMETHOD CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInState &aTypeInState); + PlaceholderTxn **aTxn, + const nsString *inString, + nsString *outString, + TypeInState typeInState); + nsresult DidInsertText(nsIDOMSelection *aSelection, nsresult aResult); + nsresult CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInState &aTypeInState); - NS_IMETHOD WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel); - NS_IMETHOD DidInsert(nsIDOMSelection *aSelection, nsresult aResult); + nsresult WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel); + nsresult DidInsert(nsIDOMSelection *aSelection, nsresult aResult); - NS_IMETHOD WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCancel); - NS_IMETHOD DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResult); + nsresult WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCancel); + nsresult DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResult); - NS_IMETHOD WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel); - NS_IMETHOD DidUndo(nsIDOMSelection *aSelection, nsresult aResult); + nsresult WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel); + nsresult DidUndo(nsIDOMSelection *aSelection, nsresult aResult); - NS_IMETHOD WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel); - NS_IMETHOD DidRedo(nsIDOMSelection *aSelection, nsresult aResult); + nsresult WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel); + nsresult DidRedo(nsIDOMSelection *aSelection, nsresult aResult); // helper functions static PRBool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag); @@ -89,7 +92,7 @@ protected: * aSelection is optional. If provided, aSelection is set to (aNode, 0) * if aNode was successfully placed in a new style node */ - NS_IMETHOD InsertStyleNode(nsIDOMNode *aNode, + nsresult InsertStyleNode(nsIDOMNode *aNode, nsIAtom *aTag, nsIDOMSelection *aSelection); @@ -99,7 +102,7 @@ protected: * aSelection is optional. If provided, aSelection is set to (newTextNode, 0) * if newTextNode was successfully created. */ - NS_IMETHOD InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, + nsresult InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, nsIAtom *aTag, nsIDOMSelection *aSelection); @@ -108,5 +111,21 @@ protected: nsCOMPtr mBogusNode; // magic node acts as placeholder in empty doc }; + + +class nsTextRulesInfo : public nsRulesInfo +{ + public: + + nsTextRulesInfo(int aAction) : nsRulesInfo(aAction),placeTxn(0),inString(0),outString(0),typeInState() {} + virtual ~nsTextRulesInfo() {} + + // used by kInsertText + PlaceholderTxn **placeTxn; + const nsString *inString; + nsString *outString; + TypeInState typeInState; +}; + #endif //nsTextEditRules_h__ diff --git a/editor/base/nsTextEditor.cpp b/editor/base/nsTextEditor.cpp index a90355d6716..5ba2d77f1d2 100644 --- a/editor/base/nsTextEditor.cpp +++ b/editor/base/nsTextEditor.cpp @@ -705,12 +705,13 @@ NS_IMETHODIMP nsTextEditor::DeleteSelection(nsIEditor::Direction aDir) // pre-process nsEditor::GetSelection(getter_AddRefs(selection)); - result = mRules->WillDoAction(nsTextEditRules::kDeleteSelection, selection, nsnull, &cancel); + nsTextRulesInfo ruleInfo(nsTextEditRules::kDeleteSelection); + result = mRules->WillDoAction(selection, &ruleInfo, &cancel); if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) { result = nsEditor::DeleteSelection(aDir); // post-process - result = mRules->DidDoAction(nsTextEditRules::kDeleteSelection, selection, nsnull, result); + result = mRules->DidDoAction(selection, &ruleInfo, result); } nsresult endTxnResult = nsEditor::EndTransaction(); // don't return this result! @@ -736,13 +737,20 @@ NS_IMETHODIMP nsTextEditor::InsertText(const nsString& aStringToInsert) // pre-process nsEditor::GetSelection(getter_AddRefs(selection)); + nsString resultString; PlaceholderTxn *placeholderTxn=nsnull; - nsresult result = mRules->WillDoAction(nsTextEditRules::kInsertText, selection, (void**)&placeholderTxn, &cancel); + nsTextRulesInfo ruleInfo(nsTextEditRules::kInsertText); + ruleInfo.placeTxn = &placeholderTxn; + ruleInfo.inString = &aStringToInsert; + ruleInfo.outString = &resultString; + ruleInfo.typeInState = mTypeInState; + + nsresult result = mRules->WillDoAction(selection, &ruleInfo, &cancel); if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) { result = nsEditor::InsertText(aStringToInsert); // post-process - result = mRules->DidDoAction(nsTextEditRules::kInsertText, selection, nsnull, result); + result = mRules->DidDoAction(selection, &ruleInfo, result); } if (placeholderTxn) placeholderTxn->SetAbsorb(PR_FALSE); // this ends the merging of txns into placeholderTxn @@ -774,12 +782,13 @@ NS_IMETHODIMP nsTextEditor::Undo(PRUint32 aCount) // pre-process nsEditor::GetSelection(getter_AddRefs(selection)); - nsresult result = mRules->WillDoAction(nsTextEditRules::kUndo, selection, nsnull, &cancel); + nsTextRulesInfo ruleInfo(nsTextEditRules::kUndo); + nsresult result = mRules->WillDoAction(selection, &ruleInfo, &cancel); if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) { result = nsEditor::Undo(aCount); nsEditor::GetSelection(getter_AddRefs(selection)); - result = mRules->DidDoAction(nsTextEditRules::kUndo, selection, nsnull, result); + result = mRules->DidDoAction(selection, &ruleInfo, result); } return result; } @@ -796,12 +805,13 @@ NS_IMETHODIMP nsTextEditor::Redo(PRUint32 aCount) // pre-process nsEditor::GetSelection(getter_AddRefs(selection)); - nsresult result = mRules->WillDoAction(nsTextEditRules::kRedo, selection, nsnull, &cancel); + nsTextRulesInfo ruleInfo(nsTextEditRules::kRedo); + nsresult result = mRules->WillDoAction(selection, &ruleInfo, &cancel); if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) { result = nsEditor::Redo(aCount); nsEditor::GetSelection(getter_AddRefs(selection)); - result = mRules->DidDoAction(nsTextEditRules::kRedo, selection, nsnull, result); + result = mRules->DidDoAction(selection, &ruleInfo, result); } return result; } diff --git a/editor/libeditor/base/nsEditRules.h b/editor/libeditor/base/nsEditRules.h index 0802a1e9a9e..5152505ff5d 100644 --- a/editor/libeditor/base/nsEditRules.h +++ b/editor/libeditor/base/nsEditRules.h @@ -22,15 +22,30 @@ class nsIEditor; class nsIDOMSelection; -/** Interface of editing rules. - * - */ +/*************************************************************************** + * base for an object to encapsulate any additional info needed to be passed + * to rules system by the editor + */ +class nsRulesInfo +{ + public: + + nsRulesInfo(int aAction) : action(aAction) {} + virtual ~nsRulesInfo() {} + + int action; +}; + +/*************************************************************************** + * Interface of editing rules. + * + */ class nsEditRules { public: NS_IMETHOD Init(nsIEditor *aEditor)=0; - NS_IMETHOD WillDoAction(int aAction, nsIDOMSelection *aSelection, void **aOtherInfo, PRBool *aCancel)=0; - NS_IMETHOD DidDoAction(int aAction, nsIDOMSelection *aSelection, void **aOtherInfo, nsresult aResult)=0; + NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel)=0; + NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult)=0; }; diff --git a/editor/libeditor/html/nsHTMLEditRules.cpp b/editor/libeditor/html/nsHTMLEditRules.cpp index 8db14d5a6d8..6d3814c999d 100644 --- a/editor/libeditor/html/nsHTMLEditRules.cpp +++ b/editor/libeditor/html/nsHTMLEditRules.cpp @@ -20,7 +20,6 @@ #include "nsEditor.h" #include "PlaceholderTxn.h" #include "InsertTextTxn.h" -#include "nsCOMPtr.h" #include "nsIDOMNode.h" #include "nsIDOMElement.h" #include "nsIDOMNodeList.h" @@ -35,16 +34,110 @@ const static char* kMOZEditorBogusNodeValue="TRUE"; static NS_DEFINE_IID(kPlaceholderTxnIID, PLACEHOLDER_TXN_IID); +nsIAtom *nsHTMLEditRules::sAAtom; +nsIAtom *nsHTMLEditRules::sAddressAtom; +nsIAtom *nsHTMLEditRules::sBigAtom; +nsIAtom *nsHTMLEditRules::sBlinkAtom; +nsIAtom *nsHTMLEditRules::sBAtom; +nsIAtom *nsHTMLEditRules::sCiteAtom; +nsIAtom *nsHTMLEditRules::sCodeAtom; +nsIAtom *nsHTMLEditRules::sDfnAtom; +nsIAtom *nsHTMLEditRules::sEmAtom; +nsIAtom *nsHTMLEditRules::sFontAtom; +nsIAtom *nsHTMLEditRules::sIAtom; +nsIAtom *nsHTMLEditRules::sKbdAtom; +nsIAtom *nsHTMLEditRules::sKeygenAtom; +nsIAtom *nsHTMLEditRules::sNobrAtom; +nsIAtom *nsHTMLEditRules::sSAtom; +nsIAtom *nsHTMLEditRules::sSampAtom; +nsIAtom *nsHTMLEditRules::sSmallAtom; +nsIAtom *nsHTMLEditRules::sSpacerAtom; +nsIAtom *nsHTMLEditRules::sSpanAtom; +nsIAtom *nsHTMLEditRules::sStrikeAtom; +nsIAtom *nsHTMLEditRules::sStrongAtom; +nsIAtom *nsHTMLEditRules::sSubAtom; +nsIAtom *nsHTMLEditRules::sSupAtom; +nsIAtom *nsHTMLEditRules::sTtAtom; +nsIAtom *nsHTMLEditRules::sUAtom; +nsIAtom *nsHTMLEditRules::sVarAtom; +nsIAtom *nsHTMLEditRules::sWbrAtom; + +PRInt32 nsHTMLEditRules::sInstanceCount; + /******************************************************** * Constructor/Destructor ********************************************************/ nsHTMLEditRules::nsHTMLEditRules() { + if (sInstanceCount <= 0) + { + sAAtom = NS_NewAtom("a"); + sAddressAtom = NS_NewAtom("address"); + sBigAtom = NS_NewAtom("big"); + sBlinkAtom = NS_NewAtom("blink"); + sBAtom = NS_NewAtom("b"); + sCiteAtom = NS_NewAtom("cite"); + sCodeAtom = NS_NewAtom("code"); + sDfnAtom = NS_NewAtom("dfn"); + sEmAtom = NS_NewAtom("em"); + sFontAtom = NS_NewAtom("font"); + sIAtom = NS_NewAtom("i"); + sKbdAtom = NS_NewAtom("kbd"); + sKeygenAtom = NS_NewAtom("keygen"); + sNobrAtom = NS_NewAtom("nobr"); + sSAtom = NS_NewAtom("s"); + sSampAtom = NS_NewAtom("samp"); + sSmallAtom = NS_NewAtom("small"); + sSpacerAtom = NS_NewAtom("spacer"); + sSpanAtom = NS_NewAtom("span"); + sStrikeAtom = NS_NewAtom("strike"); + sStrongAtom = NS_NewAtom("strong"); + sSubAtom = NS_NewAtom("sub"); + sSupAtom = NS_NewAtom("sup"); + sTtAtom = NS_NewAtom("tt"); + sUAtom = NS_NewAtom("u"); + sVarAtom = NS_NewAtom("var"); + sWbrAtom = NS_NewAtom("wbr"); + } + + ++sInstanceCount; } nsHTMLEditRules::~nsHTMLEditRules() { + if (sInstanceCount <= 1) + { + NS_IF_RELEASE(sAAtom); + NS_IF_RELEASE(sAddressAtom); + NS_IF_RELEASE(sBigAtom); + NS_IF_RELEASE(sBlinkAtom); + NS_IF_RELEASE(sBAtom); + NS_IF_RELEASE(sCiteAtom); + NS_IF_RELEASE(sCodeAtom); + NS_IF_RELEASE(sDfnAtom); + NS_IF_RELEASE(sEmAtom); + NS_IF_RELEASE(sFontAtom); + NS_IF_RELEASE(sIAtom); + NS_IF_RELEASE(sKbdAtom); + NS_IF_RELEASE(sKeygenAtom); + NS_IF_RELEASE(sNobrAtom); + NS_IF_RELEASE(sSAtom); + NS_IF_RELEASE(sSampAtom); + NS_IF_RELEASE(sSmallAtom); + NS_IF_RELEASE(sSpacerAtom); + NS_IF_RELEASE(sSpanAtom); + NS_IF_RELEASE(sStrikeAtom); + NS_IF_RELEASE(sStrongAtom); + NS_IF_RELEASE(sSubAtom); + NS_IF_RELEASE(sSupAtom); + NS_IF_RELEASE(sTtAtom); + NS_IF_RELEASE(sUAtom); + NS_IF_RELEASE(sVarAtom); + NS_IF_RELEASE(sWbrAtom); + } + + --sInstanceCount; } @@ -53,40 +146,94 @@ nsHTMLEditRules::~nsHTMLEditRules() ********************************************************/ NS_IMETHODIMP -nsHTMLEditRules::WillDoAction(int aAction, nsIDOMSelection *aSelection, - void **aOtherInfo, PRBool *aCancel) +nsHTMLEditRules::WillDoAction(nsIDOMSelection *aSelection, + nsRulesInfo *aInfo, PRBool *aCancel) { - if (!aSelection) + if (!aSelection || !aInfo) return NS_ERROR_NULL_POINTER; - switch (aAction) + // my kingdom for dynamic cast + nsTextRulesInfo *info = NS_STATIC_CAST(nsTextRulesInfo*, aInfo); + + switch (info->action) { + case kInsertText: + return WillInsertText(aSelection, + aCancel, + info->placeTxn, + info->inString, + info->outString, + info->typeInState); case kInsertBreak: return WillInsertBreak(aSelection, aCancel); } - return nsTextEditRules::WillDoAction(aAction, aSelection, aOtherInfo, aCancel); + return nsTextEditRules::WillDoAction(aSelection, aInfo, aCancel); } NS_IMETHODIMP -nsHTMLEditRules::DidDoAction(int aAction, nsIDOMSelection *aSelection, - void **aOtherInfo, nsresult aResult) +nsHTMLEditRules::DidDoAction(nsIDOMSelection *aSelection, + nsRulesInfo *aInfo, nsresult aResult) { - if (!aSelection) + if (!aSelection || !aInfo) return NS_ERROR_NULL_POINTER; - switch (aAction) + // my kingdom for dynamic cast + nsTextRulesInfo *info = NS_STATIC_CAST(nsTextRulesInfo*, aInfo); + + switch (info->action) { + case kInsertText: + return DidInsertText(aSelection, aResult); case kInsertBreak: return DidInsertBreak(aSelection, aResult); } - return nsTextEditRules::DidDoAction(aAction, aSelection, aOtherInfo, aResult); + return nsTextEditRules::DidDoAction(aSelection, aInfo, aResult); } /******************************************************** - * Protected methods + * Protected rules methods ********************************************************/ -NS_IMETHODIMP + +nsresult +nsHTMLEditRules::WillInsertText(nsIDOMSelection *aSelection, + PRBool *aCancel, + PlaceholderTxn **aTxn, + const nsString *inString, + nsString *outString, + TypeInState typeInState) +{ + if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; } + // initialize out param + *aCancel = PR_FALSE; + + // XXX - need to handle strings of length >1 with embedded tabs or spaces + + // is it a tab? + if (*inString == "\t" ) + return InsertTab(aSelection,aCancel,aTxn,outString); + // is it a space? + if (*inString == " ") + return InsertSpace(aSelection,aCancel,aTxn,outString); + + // otherwise, return nsTextEditRules version + return nsTextEditRules::WillInsertText(aSelection, + aCancel, + aTxn, + inString, + outString, + typeInState); +} + +nsresult +nsHTMLEditRules::DidInsertText(nsIDOMSelection *aSelection, + nsresult aResult) +{ + // for now, return nsTextEditRules version + return nsTextEditRules::DidInsertText(aSelection, aResult); +} + +nsresult nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel) { if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; } @@ -97,7 +244,7 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel) // XXX: this code is all experimental, and has no effect on the content model yet // the point here is to collapse adjacent BR's into P's -NS_IMETHODIMP +nsresult nsHTMLEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult) { nsresult result = aResult; // if aResult is an error, we return it. @@ -196,3 +343,153 @@ nsHTMLEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult) } return result; } + + + +/******************************************************** + * helper methods + ********************************************************/ + +PRBool +nsHTMLEditRules::IsBlockNode(nsIContent *aContent) +{ + nsIAtom* atom = nsnull; + PRBool result; + + aContent->GetTag(atom); + + if (!atom) + return PR_TRUE; + + if (sAAtom != atom && + sAddressAtom != atom && + sBigAtom != atom && + sBlinkAtom != atom && + sBAtom != atom && + sCiteAtom != atom && + sCodeAtom != atom && + sDfnAtom != atom && + sEmAtom != atom && + sFontAtom != atom && + sIAtom != atom && + sKbdAtom != atom && + sKeygenAtom != atom && + sNobrAtom != atom && + sSAtom != atom && + sSampAtom != atom && + sSmallAtom != atom && + sSpacerAtom != atom && + sSpanAtom != atom && + sStrikeAtom != atom && + sStrongAtom != atom && + sSubAtom != atom && + sSupAtom != atom && + sTtAtom != atom && + sUAtom != atom && + sVarAtom != atom && + sWbrAtom != atom) + { + result = PR_TRUE; + } + else + { + result = PR_FALSE; + } + NS_RELEASE(atom); + return result; +} + +nsCOMPtr +nsHTMLEditRules::GetBlockNodeParent(nsCOMPtr aContent) +{ + nsCOMPtr p; + + if (NS_FAILED(aContent->GetParent(*getter_AddRefs(p)))) // no parent, ran off top of tree + return aContent; + + nsCOMPtr tmp; + + while (p && !IsBlockNode(p)) + { + if (NS_FAILED(p->GetParent(*getter_AddRefs(tmp)))) // no parent, ran off top of tree + return p; + + p = tmp; + } + return p; +} + +/////////////////////////////////////////////////////////////////////////// +// GetStartNode: returns whatever the start parent is of the first range +// in the selection. +nsCOMPtr +nsHTMLEditRules::GetStartNode(nsIDOMSelection *aSelection) +{ + nsCOMPtr startNode; + nsCOMPtr enumerator; + enumerator = do_QueryInterface(aSelection); + if (!enumerator) + return startNode; + enumerator->First(); + nsISupports *currentItem; + if ((NS_FAILED(enumerator->CurrentItem(¤tItem))) || !currentItem) + return startNode; + + nsCOMPtr range( do_QueryInterface(currentItem) ); + if (!range) + return startNode; + range->GetStartParent(getter_AddRefs(startNode)); + return startNode; +} + + +/////////////////////////////////////////////////////////////////////////// +// IsPreformatted: checks the style info for the node for the preformatted +// text style. +nsresult +nsHTMLEditRules::IsPreformatted(nsCOMPtr aNode, PRBool *aResult) +{ + return PR_TRUE; +} + + +nsresult +nsHTMLEditRules::InsertTab(nsIDOMSelection *aSelection, + PRBool *aCancel, + PlaceholderTxn **aTxn, + nsString *outString) +{ + nsCOMPtr theNode; + PRBool isPRE; + theNode = GetStartNode(aSelection); + if (!theNode) + return NS_ERROR_UNEXPECTED; + nsresult result = IsPreformatted(theNode,&isPRE); + if (NS_FAILED(result)) + return result; + if (isPRE) + { + outString += '\t'; + // we're done - let everything fall through to the InsertText code + // in nsTextEditor which will insert the tab as is. + } + else + { + + } + return NS_OK; +} + + +nsresult +nsHTMLEditRules::InsertSpace(nsIDOMSelection *aSelection, + PRBool *aCancel, + PlaceholderTxn **aTxn, + nsString *outString) +{ + return NS_OK; +} + + + + diff --git a/editor/libeditor/html/nsHTMLEditRules.h b/editor/libeditor/html/nsHTMLEditRules.h index f11ff94dd8b..eb98544f45a 100644 --- a/editor/libeditor/html/nsHTMLEditRules.h +++ b/editor/libeditor/html/nsHTMLEditRules.h @@ -20,6 +20,9 @@ #define nsHTMLEditRules_h__ #include "nsTextEditRules.h" +#include "nsCOMPtr.h" + +class nsIContent; class nsHTMLEditRules : public nsTextEditRules { @@ -29,8 +32,8 @@ public: virtual ~nsHTMLEditRules(); // nsEditRules methods - NS_IMETHOD WillDoAction(int aAction, nsIDOMSelection *aSelection, void **aOtherInfo, PRBool *aCancel); - NS_IMETHOD DidDoAction(int aAction, nsIDOMSelection *aSelection, void **aOtherInfo, nsresult aResult); + NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel); + NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult); // nsHTMLEditRules action id's enum @@ -40,9 +43,56 @@ public: protected: // nsHTMLEditRules implementation methods - NS_IMETHOD WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel); - NS_IMETHOD DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult); + nsresult WillInsertText(nsIDOMSelection *aSelection, + PRBool *aCancel, + PlaceholderTxn **aTxn, + const nsString *inString, + nsString *outString, + TypeInState typeInState); + nsresult DidInsertText(nsIDOMSelection *aSelection, nsresult aResult); + nsresult WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel); + nsresult DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult); + + nsresult InsertTab(nsIDOMSelection *aSelection, PRBool *aCancel, PlaceholderTxn **aTxn, nsString *outString); + nsresult InsertSpace(nsIDOMSelection *aSelection, PRBool *aCancel, PlaceholderTxn **aTxn, nsString *outString); + + // helper methods + PRBool IsBlockNode(nsIContent *aContent); + nsCOMPtr GetBlockNodeParent(nsCOMPtr aContent); + nsCOMPtr GetStartNode(nsIDOMSelection *aSelection); + nsresult IsPreformatted(nsCOMPtr aNode, PRBool *aResult); + + // data + static nsIAtom *sAAtom; + static nsIAtom *sAddressAtom; + static nsIAtom *sBigAtom; + static nsIAtom *sBlinkAtom; + static nsIAtom *sBAtom; + static nsIAtom *sCiteAtom; + static nsIAtom *sCodeAtom; + static nsIAtom *sDfnAtom; + static nsIAtom *sEmAtom; + static nsIAtom *sFontAtom; + static nsIAtom *sIAtom; + static nsIAtom *sKbdAtom; + static nsIAtom *sKeygenAtom; + static nsIAtom *sNobrAtom; + static nsIAtom *sSAtom; + static nsIAtom *sSampAtom; + static nsIAtom *sSmallAtom; + static nsIAtom *sSpacerAtom; + static nsIAtom *sSpanAtom; + static nsIAtom *sStrikeAtom; + static nsIAtom *sStrongAtom; + static nsIAtom *sSubAtom; + static nsIAtom *sSupAtom; + static nsIAtom *sTtAtom; + static nsIAtom *sUAtom; + static nsIAtom *sVarAtom; + static nsIAtom *sWbrAtom; + + static PRInt32 sInstanceCount; }; #endif //nsHTMLEditRules_h__ diff --git a/editor/libeditor/html/nsHTMLEditor.cpp b/editor/libeditor/html/nsHTMLEditor.cpp index 86fc93fa5cb..b3f274b42eb 100644 --- a/editor/libeditor/html/nsHTMLEditor.cpp +++ b/editor/libeditor/html/nsHTMLEditor.cpp @@ -147,7 +147,8 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak() // pre-process nsEditor::GetSelection(getter_AddRefs(selection)); - result = mRules->WillDoAction(nsHTMLEditRules::kInsertBreak, selection, nsnull, &cancel); + nsTextRulesInfo ruleInfo(nsHTMLEditRules::kInsertBreak); + result = mRules->WillDoAction(selection, &ruleInfo, &cancel); if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result))) { // create the new BR node @@ -197,7 +198,7 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak() } } // post-process, always called if WillInsertBreak didn't return cancel==PR_TRUE - result = mRules->DidDoAction(nsHTMLEditRules::kInsertBreak, selection, nsnull, result); + result = mRules->DidDoAction(selection, &ruleInfo, result); } nsresult endTxnResult = nsEditor::EndTransaction(); // don't return this result! NS_ASSERTION ((NS_SUCCEEDED(endTxnResult)), "bad end transaction result"); diff --git a/editor/libeditor/text/nsTextEditRules.cpp b/editor/libeditor/text/nsTextEditRules.cpp index 3266ac91bfd..65aa6da1a60 100644 --- a/editor/libeditor/text/nsTextEditRules.cpp +++ b/editor/libeditor/text/nsTextEditRules.cpp @@ -125,16 +125,24 @@ nsTextEditRules::Init(nsIEditor *aEditor) } NS_IMETHODIMP -nsTextEditRules::WillDoAction(int aAction, nsIDOMSelection *aSelection, - void **aOtherInfo, PRBool *aCancel) +nsTextEditRules::WillDoAction(nsIDOMSelection *aSelection, + nsRulesInfo *aInfo, PRBool *aCancel) { - if (!aSelection) + if (!aSelection || !aInfo) return NS_ERROR_NULL_POINTER; + + // my kingdom for dynamic cast + nsTextRulesInfo *info = NS_STATIC_CAST(nsTextRulesInfo*, aInfo); - switch (aAction) + switch (info->action) { case kInsertText: - return WillInsertText(aSelection, aCancel, (PlaceholderTxn**)aOtherInfo); + return WillInsertText(aSelection, + aCancel, + info->placeTxn, + info->inString, + info->outString, + info->typeInState); case kDeleteSelection: return WillDeleteSelection(aSelection, aCancel); case kUndo: @@ -146,13 +154,16 @@ nsTextEditRules::WillDoAction(int aAction, nsIDOMSelection *aSelection, } NS_IMETHODIMP -nsTextEditRules::DidDoAction(int aAction, nsIDOMSelection *aSelection, - void **aOtherInfo, nsresult aResult) +nsTextEditRules::DidDoAction(nsIDOMSelection *aSelection, + nsRulesInfo *aInfo, nsresult aResult) { - if (!aSelection) + if (!aSelection || !aInfo) return NS_ERROR_NULL_POINTER; - switch (aAction) + // my kingdom for dynamic cast + nsTextRulesInfo *info = NS_STATIC_CAST(nsTextRulesInfo*, aInfo); + + switch (info->action) { case kInsertText: return DidInsertText(aSelection, aResult); @@ -172,7 +183,7 @@ nsTextEditRules::DidDoAction(int aAction, nsIDOMSelection *aSelection, ********************************************************/ -NS_IMETHODIMP +nsresult nsTextEditRules::WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel) { if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; } @@ -191,21 +202,23 @@ nsTextEditRules::WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel) return NS_OK; } -NS_IMETHODIMP +nsresult nsTextEditRules::DidInsert(nsIDOMSelection *aSelection, nsresult aResult) { return NS_OK; } -NS_IMETHODIMP -nsTextEditRules::WillInsertText(nsIDOMSelection *aSelection, - PRBool *aCancel, - PlaceholderTxn **aTxn) +nsresult +nsTextEditRules::WillInsertText(nsIDOMSelection *aSelection, + PRBool *aCancel, + PlaceholderTxn **aTxn, + const nsString *inString, + nsString *outString, + TypeInState typeInState) { if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; } // initialize out param *aCancel = PR_FALSE; - TypeInState typeInState = mEditor->GetTypeInState(); if (mBogusNode || (PR_TRUE==typeInState.IsAnySet())) { nsresult result = TransactionFactory::GetNewTransaction(kPlaceholderTxnIID, (EditTxn **)aTxn); @@ -225,14 +238,14 @@ nsTextEditRules::WillInsertText(nsIDOMSelection *aSelection, return result; } -NS_IMETHODIMP +nsresult nsTextEditRules::DidInsertText(nsIDOMSelection *aSelection, nsresult aResult) { return DidInsert(aSelection, aResult); } -NS_IMETHODIMP +nsresult nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInState &aTypeInState) { // private method, we know aSelection is not null, and that it is collapsed @@ -356,7 +369,7 @@ nsTextEditRules::CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInSta return result; } -NS_IMETHODIMP +nsresult nsTextEditRules::InsertStyleNode(nsIDOMNode *aNode, nsIAtom *aTag, nsIDOMSelection *aSelection) { NS_ASSERTION(aNode && aTag, "bad args"); @@ -388,7 +401,7 @@ nsTextEditRules::InsertStyleNode(nsIDOMNode *aNode, nsIAtom *aTag, nsIDOMSelecti } -NS_IMETHODIMP +nsresult nsTextEditRules::InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, nsIAtom *aTag, nsIDOMSelection *aSelection) { NS_ASSERTION(aParentNode && aTag, "bad args"); @@ -433,7 +446,7 @@ nsTextEditRules::InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, nsIAtom *aTa /* -NS_IMETHODIMP +nsresult nsTextEditRules::GetInsertBreakTag(nsIAtom **aTag) { if (!aTag) { return NS_ERROR_NULL_POINTER; } @@ -442,7 +455,7 @@ nsTextEditRules::GetInsertBreakTag(nsIAtom **aTag) } */ -NS_IMETHODIMP +nsresult nsTextEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCancel) { if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; } @@ -459,7 +472,7 @@ nsTextEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCance // if the document is empty, insert a bogus text node with a   // if we ended up with consecutive text nodes, merge them -NS_IMETHODIMP +nsresult nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResult) { nsresult result = aResult; // if aResult is an error, we just return it @@ -600,7 +613,7 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResul return result; } -NS_IMETHODIMP +nsresult nsTextEditRules::WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel) { if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; } @@ -614,7 +627,7 @@ nsTextEditRules::WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel) * There is a tradeoff between doing here and at redo, or doing it everywhere else that might care. * Since undo and redo are relatively rare, it makes sense to take the (small) performance hit here. */ -NS_IMETHODIMP +nsresult nsTextEditRules:: DidUndo(nsIDOMSelection *aSelection, nsresult aResult) { nsresult result = aResult; // if aResult is an error, we return it. @@ -651,7 +664,7 @@ nsTextEditRules:: DidUndo(nsIDOMSelection *aSelection, nsresult aResult) return result; } -NS_IMETHODIMP +nsresult nsTextEditRules::WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel) { if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; } @@ -660,7 +673,7 @@ nsTextEditRules::WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel) return NS_OK; } -NS_IMETHODIMP +nsresult nsTextEditRules::DidRedo(nsIDOMSelection *aSelection, nsresult aResult) { nsresult result = aResult; // if aResult is an error, we return it. diff --git a/editor/libeditor/text/nsTextEditRules.h b/editor/libeditor/text/nsTextEditRules.h index 80a27f5647b..af6a28de626 100644 --- a/editor/libeditor/text/nsTextEditRules.h +++ b/editor/libeditor/text/nsTextEditRules.h @@ -48,8 +48,8 @@ public: // nsEditRules methods NS_IMETHOD Init(nsIEditor *aEditor); - NS_IMETHOD WillDoAction(int aAction, nsIDOMSelection *aSelection, void **aOtherInfo, PRBool *aCancel); - NS_IMETHOD DidDoAction(int aAction, nsIDOMSelection *aSelection, void **aOtherInfo, nsresult aResult); + NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel); + NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult); // nsTextEditRules action id's enum @@ -63,23 +63,26 @@ public: protected: // nsTextEditRules implementation methods - NS_IMETHOD WillInsertText(nsIDOMSelection *aSelection, + nsresult WillInsertText(nsIDOMSelection *aSelection, PRBool *aCancel, - PlaceholderTxn **aTxn); - NS_IMETHOD DidInsertText(nsIDOMSelection *aSelection, nsresult aResult); - NS_IMETHOD CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInState &aTypeInState); + PlaceholderTxn **aTxn, + const nsString *inString, + nsString *outString, + TypeInState typeInState); + nsresult DidInsertText(nsIDOMSelection *aSelection, nsresult aResult); + nsresult CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInState &aTypeInState); - NS_IMETHOD WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel); - NS_IMETHOD DidInsert(nsIDOMSelection *aSelection, nsresult aResult); + nsresult WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel); + nsresult DidInsert(nsIDOMSelection *aSelection, nsresult aResult); - NS_IMETHOD WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCancel); - NS_IMETHOD DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResult); + nsresult WillDeleteSelection(nsIDOMSelection *aSelection, PRBool *aCancel); + nsresult DidDeleteSelection(nsIDOMSelection *aSelection, nsresult aResult); - NS_IMETHOD WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel); - NS_IMETHOD DidUndo(nsIDOMSelection *aSelection, nsresult aResult); + nsresult WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel); + nsresult DidUndo(nsIDOMSelection *aSelection, nsresult aResult); - NS_IMETHOD WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel); - NS_IMETHOD DidRedo(nsIDOMSelection *aSelection, nsresult aResult); + nsresult WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel); + nsresult DidRedo(nsIDOMSelection *aSelection, nsresult aResult); // helper functions static PRBool NodeIsType(nsIDOMNode *aNode, nsIAtom *aTag); @@ -89,7 +92,7 @@ protected: * aSelection is optional. If provided, aSelection is set to (aNode, 0) * if aNode was successfully placed in a new style node */ - NS_IMETHOD InsertStyleNode(nsIDOMNode *aNode, + nsresult InsertStyleNode(nsIDOMNode *aNode, nsIAtom *aTag, nsIDOMSelection *aSelection); @@ -99,7 +102,7 @@ protected: * aSelection is optional. If provided, aSelection is set to (newTextNode, 0) * if newTextNode was successfully created. */ - NS_IMETHOD InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, + nsresult InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, nsIAtom *aTag, nsIDOMSelection *aSelection); @@ -108,5 +111,21 @@ protected: nsCOMPtr mBogusNode; // magic node acts as placeholder in empty doc }; + + +class nsTextRulesInfo : public nsRulesInfo +{ + public: + + nsTextRulesInfo(int aAction) : nsRulesInfo(aAction),placeTxn(0),inString(0),outString(0),typeInState() {} + virtual ~nsTextRulesInfo() {} + + // used by kInsertText + PlaceholderTxn **placeTxn; + const nsString *inString; + nsString *outString; + TypeInState typeInState; +}; + #endif //nsTextEditRules_h__