revised rules system api to include "handled" parameter and ceased to overload the meaning of the "cancel" parameter; added TypedText() method to editor, editorshell, and logging, so that logging will work properly with typing; coallesce deletions for undo purposes r=buster@netscape.com

This commit is contained in:
jfrancis%netscape.com 1999-10-06 19:34:09 +00:00
Родитель 58f510bc61
Коммит c412022f4a
28 изменённых файлов: 1282 добавлений и 918 удалений

Просмотреть файл

@ -112,8 +112,9 @@ NS_IMETHODIMP PlaceholderTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransact
if (gNoisy) { printf("Placeholder txn assimilated %p\n", aTransaction); }
}
else
{ // merge typing transactions if the selection matches
if (mName.get() == nsHTMLEditor::gTypingTxnName)
{ // merge typing or deletion transactions if the selection matches
if ( (mName.get() == nsHTMLEditor::gTypingTxnName) ||
(mName.get() == nsHTMLEditor::gDeleteTxnName) )
{
nsCOMPtr<nsIAbsorbingTransaction> plcTxn;// = do_QueryInterface(editTxn);
// cant do_QueryInterface() above due to our broken transaction interfaces.
@ -123,7 +124,7 @@ NS_IMETHODIMP PlaceholderTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransact
{
nsIAtom *atom;
plcTxn->GetTxnName(&atom);
if (atom && (atom == nsHTMLEditor::gTypingTxnName))
if (atom && (atom == mName.get()))
{
nsCOMPtr<nsIDOMNode> otherTxnStartNode;
PRInt32 otherTxnStartOffset;
@ -167,8 +168,9 @@ NS_IMETHODIMP PlaceholderTxn::EndPlaceHolderBatch()
if (plcTxn) plcTxn->EndPlaceHolderBatch();
}
// if we are a typing transaction, remember our selection state
if (mName.get() == nsHTMLEditor::gTypingTxnName)
// if we are a typing or deleting transaction, remember our selection state
if ( (mName.get() == nsHTMLEditor::gTypingTxnName) ||
(mName.get() == nsHTMLEditor::gDeleteTxnName) )
{
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps) return NS_ERROR_NOT_INITIALIZED;

Просмотреть файл

@ -44,7 +44,7 @@ class nsEditRules
{
public:
NS_IMETHOD Init(nsHTMLEditor *aEditor, PRUint32 aFlags)=0;
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel)=0;
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel, PRBool *aHandled)=0;
NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult)=0;
NS_IMETHOD GetFlags(PRUint32 *aFlags)=0;
NS_IMETHOD SetFlags(PRUint32 aFlags)=0;

Просмотреть файл

@ -563,7 +563,7 @@ nsEditor::BeginPlaceHolderTransaction(nsIAtom *aName)
PRBool collapsed;
res = selection->GetIsCollapsed(&collapsed);
if (NS_FAILED(res)) return res;
if (collapsed) // we cant merge with previous typing if selection not collapsed
if (collapsed) // we cant merge with previous typing/deleting if selection not collapsed
{
// need to remember colapsed selection point to Init the placeholder with later.
// this is because we dont actually make the placeholder until we need it, and we

Просмотреть файл

@ -617,11 +617,11 @@ protected:
nsCOMPtr<nsITransactionManager> mTxnMgr;
nsCOMPtr<nsIEditProperty> mEditProperty;
nsCOMPtr<nsICSSStyleSheet> mLastStyleSheet; // is owning this dangerous?
nsWeakPtr mPlaceHolderTxn;
nsIAtom *mPlaceHolderName;
PRInt32 mPlaceHolderBatch;
nsCOMPtr<nsIDOMNode> mTxnStartNode;
PRInt32 mTxnStartOffset;
nsWeakPtr mPlaceHolderTxn; // weak reference to placeholder for begin/end batch purposes
nsIAtom *mPlaceHolderName; // name of placeholder transaction
PRInt32 mPlaceHolderBatch; // nesting count for batching
nsCOMPtr<nsIDOMNode> mTxnStartNode; // saved selection info to pass to placeholder at init time
PRInt32 mTxnStartOffset; // " " " "
//
// data necessary to build IME transactions

Просмотреть файл

@ -1782,6 +1782,32 @@ nsEditorShell::DeleteSelection(PRInt32 action)
return err;
}
/* This routine should only be called when playing back a log */
NS_IMETHODIMP
nsEditorShell::TypedText(const PRUnichar *aTextToInsert, PRInt32 aAction)
{
nsresult err = NS_NOINTERFACE;
nsAutoString textToInsert(aTextToInsert);
switch (mEditorType)
{
case ePlainTextEditorType:
case eHTMLTextEditorType:
{
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(mEditor);
if (htmlEditor)
err = htmlEditor->TypedText(textToInsert, aAction);
}
break;
default:
err = NS_ERROR_NOT_IMPLEMENTED;
}
return err;
}
NS_IMETHODIMP
nsEditorShell::InsertText(const PRUnichar *textToInsert)

Просмотреть файл

@ -72,12 +72,15 @@ nsHTMLEditRules::~nsHTMLEditRules()
NS_IMETHODIMP
nsHTMLEditRules::WillDoAction(nsIDOMSelection *aSelection,
nsRulesInfo *aInfo, PRBool *aCancel)
nsRulesInfo *aInfo,
PRBool *aCancel,
PRBool *aHandled)
{
if (!aInfo || !aCancel)
if (!aInfo || !aCancel || !aHandled)
return NS_ERROR_NULL_POINTER;
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
// my kingdom for dynamic cast
nsTextRulesInfo *info = NS_STATIC_CAST(nsTextRulesInfo*, aInfo);
@ -87,30 +90,31 @@ nsHTMLEditRules::WillDoAction(nsIDOMSelection *aSelection,
case kInsertText:
return WillInsertText(aSelection,
aCancel,
aHandled,
info->inString,
info->outString,
info->typeInState,
info->maxLength);
case kInsertBreak:
return WillInsertBreak(aSelection, aCancel);
return WillInsertBreak(aSelection, aCancel, aHandled);
case kDeleteSelection:
return WillDeleteSelection(aSelection, info->collapsedAction, aCancel);
return WillDeleteSelection(aSelection, info->collapsedAction, aCancel, aHandled);
case kMakeList:
return WillMakeList(aSelection, info->bOrdered, aCancel);
return WillMakeList(aSelection, info->bOrdered, aCancel, aHandled);
case kIndent:
return WillIndent(aSelection, aCancel);
return WillIndent(aSelection, aCancel, aHandled);
case kOutdent:
return WillOutdent(aSelection, aCancel);
return WillOutdent(aSelection, aCancel, aHandled);
case kAlign:
return WillAlign(aSelection, info->alignType, aCancel);
return WillAlign(aSelection, info->alignType, aCancel, aHandled);
case kMakeBasicBlock:
return WillMakeBasicBlock(aSelection, info->blockType, aCancel);
return WillMakeBasicBlock(aSelection, info->blockType, aCancel, aHandled);
case kRemoveList:
return WillRemoveList(aSelection, info->bOrdered, aCancel);
return WillRemoveList(aSelection, info->bOrdered, aCancel, aHandled);
case kInsertElement:
return WillInsert(aSelection, aCancel);
}
return nsTextEditRules::WillDoAction(aSelection, aInfo, aCancel);
return nsTextEditRules::WillDoAction(aSelection, aInfo, aCancel, aHandled);
}
@ -143,14 +147,16 @@ nsHTMLEditRules::DidDoAction(nsIDOMSelection *aSelection,
nsresult
nsHTMLEditRules::WillInsertText(nsIDOMSelection *aSelection,
PRBool *aCancel,
PRBool *aHandled,
const nsString *inString,
nsString *outString,
TypeInState typeInState,
PRInt32 aMaxLength)
{ if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
{ if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
// initialize out param
*aCancel = PR_TRUE;
*aCancel = PR_FALSE;
*aHandled = PR_TRUE;
nsresult res;
nsCOMPtr<nsIDOMNode> selNode;
PRInt32 selOffset;
@ -176,7 +182,7 @@ nsHTMLEditRules::WillInsertText(nsIDOMSelection *aSelection,
// initialize out param
// we want to ignore result of WillInsert()
*aCancel = PR_TRUE;
*aCancel = PR_FALSE;
// split any mailcites in the way
if (mFlags & nsIHTMLEditor::eEditorMailMask)
@ -277,23 +283,23 @@ nsHTMLEditRules::WillInsertText(nsIDOMSelection *aSelection,
// is it a solo tab?
if (partialString == "\t" )
{
res = InsertTab(aSelection,&bCancel,outString);
res = InsertTab(aSelection,outString);
if (NS_FAILED(res)) return res;
res = DoTextInsertion(aSelection, aCancel, outString, typeInState);
res = DoTextInsertion(aSelection, &bCancel, outString, typeInState);
}
// is it a solo space?
else if (partialString == " ")
{
res = InsertSpace(aSelection,&bCancel,outString);
res = InsertSpace(aSelection,outString);
if (NS_FAILED(res)) return res;
res = DoTextInsertion(aSelection, aCancel, outString, typeInState);
res = DoTextInsertion(aSelection, &bCancel, outString, typeInState);
}
// is it a solo nbsp?
else if (partialString == nbspStr)
{
res = InsertSpace(aSelection,&bCancel,outString);
res = InsertSpace(aSelection,outString);
if (NS_FAILED(res)) return res;
res = DoTextInsertion(aSelection, aCancel, outString, typeInState);
res = DoTextInsertion(aSelection, &bCancel, outString, typeInState);
}
// is it a solo return?
else if (partialString == "\n")
@ -302,7 +308,7 @@ nsHTMLEditRules::WillInsertText(nsIDOMSelection *aSelection,
}
else
{
res = DoTextInsertion(aSelection, aCancel, &partialString, typeInState);
res = DoTextInsertion(aSelection, &bCancel, &partialString, typeInState);
}
if (NS_FAILED(res)) return res;
pos = theString.FindCharInSet(specialChars);
@ -312,11 +318,12 @@ nsHTMLEditRules::WillInsertText(nsIDOMSelection *aSelection,
}
nsresult
nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
// initialize out param
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
nsresult res;
res = WillInsert(aSelection, aCancel);
@ -372,7 +379,7 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
if (isPRE)
{
nsString theString = "\n";
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
return mEditor->InsertTextImpl(theString);
}
@ -415,7 +422,7 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
res = mEditor->SetAttribute(brElem, "type", "_moz");
if (NS_FAILED(res)) return res;
}
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
}
else if (bIsMozDiv && AtStartOfBlock(node, offset, blockParent))
{
@ -442,21 +449,21 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
if (!newDiv || !IsMozDiv(newDiv)) return NS_ERROR_FAILURE;
res = aSelection->Collapse(newDiv, 0);
if (NS_FAILED(res)) return res;
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
}
// headers: close (or split) header
else if (IsHeader(blockParent))
{
res = ReturnInHeader(aSelection, blockParent, node, offset);
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
return NS_OK;
}
// paragraphs: special rules to look for <br>s
else if (IsParagraph(blockParent))
{
res = ReturnInParagraph(aSelection, blockParent, node, offset, aCancel);
res = ReturnInParagraph(aSelection, blockParent, node, offset, aCancel, aHandled);
return NS_OK;
}
@ -464,7 +471,7 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
else if (IsListItem(blockParent))
{
res = ReturnInListItem(aSelection, blockParent, node, offset);
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
return NS_OK;
}
@ -474,11 +481,15 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
nsresult
nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESelectionCollapseDirection aAction, PRBool *aCancel)
nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection,
nsIEditor::ESelectionCollapseDirection aAction,
PRBool *aCancel,
PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
// initialize out param
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
// if there is only bogus content, cancel the operation
if (mBogusNode)
@ -542,7 +553,7 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
nsCOMPtr<nsIDOMNode> topParent;
leftParent->GetParentNode(getter_AddRefs(topParent));
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
res = JoinNodesSmart(leftParent,rightParent,&selNode,&selOffset);
if (NS_FAILED(res)) return res;
// fix up selection
@ -582,7 +593,7 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
nsCOMPtr<nsIDOMNode> topParent;
leftParent->GetParentNode(getter_AddRefs(topParent));
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
res = JoinNodesSmart(leftParent,rightParent,&selNode,&selOffset);
if (NS_FAILED(res)) return res;
// fix up selection
@ -689,7 +700,7 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
if (IsParagraph(leftParent))
{
// first delete the selection
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
res = mEditor->DeleteSelectionImpl(aAction);
if (NS_FAILED(res)) return res;
// then join para's, insert break
@ -702,7 +713,7 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
if (IsListItem(leftParent) || IsHeader(leftParent))
{
// first delete the selection
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
res = mEditor->DeleteSelectionImpl(aAction);
if (NS_FAILED(res)) return res;
// join blocks
@ -723,9 +734,12 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
nsresult
nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection, PRBool aOrdered, PRBool *aCancel)
nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection,
PRBool aOrdered,
PRBool *aCancel,
PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
nsresult res = WillInsert(aSelection, aCancel);
if (NS_FAILED(res)) return res;
@ -733,6 +747,7 @@ nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection, PRBool aOrdered, PRBo
// initialize out param
// we want to ignore result of WillInsert()
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
nsAutoString blockType("ul");
if (aOrdered) blockType = "ol";
@ -752,7 +767,7 @@ nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection, PRBool aOrdered, PRBo
// block parent, and then further expands to include any ancestors
// whose children are all in the range
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
nsCOMPtr<nsISupportsArray> arrayOfRanges;
res = GetPromotedRanges(aSelection, &arrayOfRanges, kMakeList);
@ -964,11 +979,15 @@ nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection, PRBool aOrdered, PRBo
nsresult
nsHTMLEditRules::WillRemoveList(nsIDOMSelection *aSelection, PRBool aOrdered, PRBool *aCancel)
nsHTMLEditRules::WillRemoveList(nsIDOMSelection *aSelection,
PRBool aOrdered,
PRBool *aCancel,
PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
// initialize out param
*aCancel = PR_TRUE;
*aCancel = PR_FALSE;
*aHandled = PR_TRUE;
nsAutoString blockType("ul");
if (aOrdered) blockType = "ol";
@ -1053,11 +1072,15 @@ nsHTMLEditRules::WillRemoveList(nsIDOMSelection *aSelection, PRBool aOrdered, PR
nsresult
nsHTMLEditRules::WillMakeBasicBlock(nsIDOMSelection *aSelection, const nsString *aBlockType, PRBool *aCancel)
nsHTMLEditRules::WillMakeBasicBlock(nsIDOMSelection *aSelection,
const nsString *aBlockType,
PRBool *aCancel,
PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
// initialize out param
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
PRBool makeEmpty;
nsresult res = ShouldMakeEmptyBlock(aSelection, aBlockType, &makeEmpty);
@ -1067,7 +1090,7 @@ nsHTMLEditRules::WillMakeBasicBlock(nsIDOMSelection *aSelection, const nsString
// else it's not that easy...
nsAutoSelectionReset selectionResetter(aSelection);
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
nsCOMPtr<nsISupportsArray> arrayOfRanges;
res = GetPromotedRanges(aSelection, &arrayOfRanges, kMakeBasicBlock);
@ -1086,16 +1109,17 @@ nsHTMLEditRules::WillMakeBasicBlock(nsIDOMSelection *aSelection, const nsString
nsresult
nsHTMLEditRules::WillIndent(nsIDOMSelection *aSelection, PRBool *aCancel)
nsHTMLEditRules::WillIndent(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool * aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
nsresult res = WillInsert(aSelection, aCancel);
if (NS_FAILED(res)) return res;
// initialize out param
// we want to ignore result of WillInsert()
*aCancel = PR_TRUE;
*aCancel = PR_FALSE;
*aHandled = PR_TRUE;
nsAutoSelectionReset selectionResetter(aSelection);
@ -1194,11 +1218,12 @@ nsHTMLEditRules::WillIndent(nsIDOMSelection *aSelection, PRBool *aCancel)
nsresult
nsHTMLEditRules::WillOutdent(nsIDOMSelection *aSelection, PRBool *aCancel)
nsHTMLEditRules::WillOutdent(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
// initialize out param
*aCancel = PR_TRUE;
*aCancel = PR_FALSE;
*aHandled = PR_TRUE;
nsAutoSelectionReset selectionResetter(aSelection);
nsresult res = NS_OK;
@ -1302,9 +1327,12 @@ nsHTMLEditRules::WillOutdent(nsIDOMSelection *aSelection, PRBool *aCancel)
nsresult
nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection, const nsString *alignType, PRBool *aCancel)
nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection,
const nsString *alignType,
PRBool *aCancel,
PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
nsresult res = WillInsert(aSelection, aCancel);
if (NS_FAILED(res)) return res;
@ -1312,7 +1340,8 @@ nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection, const nsString *alignTyp
// initialize out param
// we want to ignore result of WillInsert()
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
nsAutoSelectionReset selectionResetter(aSelection);
PRBool outMakeEmpty;
@ -1325,7 +1354,7 @@ nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection, const nsString *alignTyp
// this basically just expands the range to include the immediate
// block parent, and then further expands to include any ancestors
// whose children are all in the range
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
nsCOMPtr<nsISupportsArray> arrayOfRanges;
res = GetPromotedRanges(aSelection, &arrayOfRanges, kAlign);
@ -2475,7 +2504,6 @@ nsHTMLEditRules::InsertContainerAbove(nsIDOMNode *inNode,
//
nsresult
nsHTMLEditRules::InsertTab(nsIDOMSelection *aSelection,
PRBool *aCancel,
nsString *outString)
{
nsCOMPtr<nsIDOMNode> parentNode;
@ -2538,7 +2566,6 @@ nsHTMLEditRules::InsertTab(nsIDOMSelection *aSelection,
//
nsresult
nsHTMLEditRules::InsertSpace(nsIDOMSelection *aSelection,
PRBool *aCancel,
nsString *outString)
{
nsCOMPtr<nsIDOMNode> parentNode;
@ -2650,10 +2677,13 @@ nsHTMLEditRules::ReturnInParagraph(nsIDOMSelection *aSelection,
nsIDOMNode *aHeader,
nsIDOMNode *aNode,
PRInt32 aOffset,
PRBool *aCancel)
PRBool *aCancel,
PRBool *aHandled)
{
if (!aSelection || !aHeader || !aNode || !aCancel) return NS_ERROR_NULL_POINTER;
if (!aSelection || !aHeader || !aNode || !aCancel || !aHandled)
{ return NS_ERROR_NULL_POINTER; }
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
nsCOMPtr<nsIDOMNode> sibling;
nsresult res = NS_OK;
@ -3308,6 +3338,7 @@ nsHTMLEditRules::CleanUpSelection(nsIDOMSelection *aSelection)
isupports = do_QueryInterface(node);
arrayOfNodes->AppendElement(isupports);
}
res = iter->Next();
if (NS_FAILED(res)) return res;
}

Просмотреть файл

@ -34,7 +34,7 @@ public:
virtual ~nsHTMLEditRules();
// nsEditRules methods
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel);
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel, PRBool *aHandled);
NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult);
protected:
@ -49,24 +49,26 @@ protected:
// nsHTMLEditRules implementation methods
nsresult WillInsertText(nsIDOMSelection *aSelection,
PRBool *aCancel,
PRBool *aHandled,
const nsString *inString,
nsString *outString,
TypeInState typeInState,
PRInt32 aMaxLength);
nsresult WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel);
nsresult WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESelectionCollapseDirection aAction, PRBool *aCancel);
nsresult WillMakeList(nsIDOMSelection *aSelection, PRBool aOrderd, PRBool *aCancel);
nsresult WillRemoveList(nsIDOMSelection *aSelection, PRBool aOrderd, PRBool *aCancel);
nsresult WillIndent(nsIDOMSelection *aSelection, PRBool *aCancel);
nsresult WillOutdent(nsIDOMSelection *aSelection, PRBool *aCancel);
nsresult WillAlign(nsIDOMSelection *aSelection, const nsString *alignType, PRBool *aCancel);
nsresult WillMakeBasicBlock(nsIDOMSelection *aSelection, const nsString *aBlockType, PRBool *aCancel);
nsresult WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESelectionCollapseDirection aAction,
PRBool *aCancel, PRBool *aHandled);
nsresult WillMakeList(nsIDOMSelection *aSelection, PRBool aOrderd, PRBool *aCancel, PRBool *aHandled);
nsresult WillRemoveList(nsIDOMSelection *aSelection, PRBool aOrderd, PRBool *aCancel, PRBool *aHandled);
nsresult WillIndent(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult WillOutdent(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult WillAlign(nsIDOMSelection *aSelection, const nsString *alignType, PRBool *aCancel, PRBool *aHandled);
nsresult WillMakeBasicBlock(nsIDOMSelection *aSelection, const nsString *aBlockType, PRBool *aCancel, PRBool *aHandled);
nsresult InsertTab(nsIDOMSelection *aSelection, PRBool *aCancel, nsString *outString);
nsresult InsertSpace(nsIDOMSelection *aSelection, PRBool *aCancel, nsString *outString);
nsresult InsertTab(nsIDOMSelection *aSelection, nsString *outString);
nsresult InsertSpace(nsIDOMSelection *aSelection, nsString *outString);
nsresult ReturnInHeader(nsIDOMSelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset);
nsresult ReturnInParagraph(nsIDOMSelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset, PRBool *aCancel);
nsresult ReturnInParagraph(nsIDOMSelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset, PRBool *aCancel, PRBool *aHandled);
nsresult ReturnInListItem(nsIDOMSelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset);
// helper methods

Просмотреть файл

@ -113,6 +113,7 @@ static char hrefText[] = "href";
static char anchorTxt[] = "anchor";
static char namedanchorText[] = "namedanchor";
nsIAtom *nsHTMLEditor::gTypingTxnName;
nsIAtom *nsHTMLEditor::gDeleteTxnName;
#define IsLink(s) (s.EqualsIgnoreCase(hrefText))
@ -211,6 +212,8 @@ nsHTMLEditor::nsHTMLEditor()
// NS_INIT_REFCNT();
if (!gTypingTxnName)
gTypingTxnName = NS_NewAtom("Typing");
if (!gDeleteTxnName)
gDeleteTxnName = NS_NewAtom("Deleting");
}
nsHTMLEditor::~nsHTMLEditor()
@ -559,8 +562,6 @@ NS_IMETHODIMP nsHTMLEditor::EditorKeyPress(nsIDOMUIEvent* aKeyEvent)
PRBool isShift, ctrlKey, altKey, metaKey;
nsresult res;
nsAutoPlaceHolderBatch batch(this, gTypingTxnName);
if (!aKeyEvent) return NS_ERROR_NULL_POINTER;
if (NS_SUCCEEDED(aKeyEvent->GetKeyCode(&keyCode)) &&
@ -584,21 +585,54 @@ NS_IMETHODIMP nsHTMLEditor::EditorKeyPress(nsIDOMUIEvent* aKeyEvent)
}
else if (keyCode == nsIDOMUIEvent::DOM_VK_RETURN)
{
nsAutoString empty;
if (isShift && !(mFlags&eEditorPlaintextBit))
{
nsCOMPtr<nsIDOMNode> brNode;
return InsertBR(&brNode); // only inserts a br node
return TypedText(empty, eTypedBR); // only inserts a br node
}
else
return InsertBreak(); // uses rules to figure out what to insert
{
return TypedText(empty, eTypedBreak); // uses rules to figure out what to insert
}
}
else // normal typing
{
nsAutoString key(character);
return TypedText(key, eTypedText);
}
nsAutoString key(character);
return InsertText(key);
}
return NS_ERROR_FAILURE;
}
/* This routine is needed to provide a bottleneck for typing for logging
purposes. Can't use EditorKeyPress() (above) for that since it takes
a nsIDOMUIEvent* parameter. So instead we pass enough info through
to TypedText() to determine what action to take, but without passing
an event.
*/
NS_IMETHODIMP nsHTMLEditor::TypedText(const nsString& aString, PRInt32 aAction)
{
nsAutoPlaceHolderBatch batch(this, gTypingTxnName);
switch (aAction)
{
case eTypedText:
{
return InsertText(aString);
}
case eTypedBR:
{
nsCOMPtr<nsIDOMNode> brNode;
return InsertBR(&brNode); // only inserts a br node
}
case eTypedBreak:
{
return InsertBreak(); // uses rules to figure out what to insert
}
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsHTMLEditor::TabInTable(PRBool inIsShift, PRBool *outHandled)
{
if (!outHandled) return NS_ERROR_NULL_POINTER;
@ -739,10 +773,11 @@ NS_IMETHODIMP nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty,
result = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(result)) return result;
if (!selection) return NS_ERROR_NULL_POINTER;
PRBool cancel;
PRBool cancel, handled;
nsTextRulesInfo ruleInfo(nsTextEditRules::kSetTextProperty);
result = mRules->WillDoAction(selection, &ruleInfo, &cancel);
if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result)))
result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (NS_FAILED(result)) return result;
if (!cancel && !handled)
{
PRBool isCollapsed;
selection->GetIsCollapsed(&isCollapsed);
@ -836,6 +871,9 @@ NS_IMETHODIMP nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty,
// for setting a compound selection yet.
}
}
}
if (!cancel)
{
// post-process
result = mRules->DidDoAction(selection, &ruleInfo, result);
}
@ -994,11 +1032,11 @@ NS_IMETHODIMP nsHTMLEditor::RemoveInlineProperty(nsIAtom *aProperty, const nsStr
if (NS_FAILED(result)) return result;
if (!selection) return NS_ERROR_NULL_POINTER;
PRBool cancel;
PRBool cancel, handled;
nsTextRulesInfo ruleInfo(nsTextEditRules::kRemoveTextProperty);
result = mRules->WillDoAction(selection, &ruleInfo, &cancel);
result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (NS_FAILED(result)) return result;
if (PR_FALSE==cancel)
if (!cancel && !handled)
{
PRBool isCollapsed;
selection->GetIsCollapsed(&isCollapsed);
@ -1080,6 +1118,9 @@ NS_IMETHODIMP nsHTMLEditor::RemoveInlineProperty(nsIAtom *aProperty, const nsStr
ResetTextSelectionForRange(parentForSelection, rangeStartOffset, rangeEndOffset, selection);
}
}
}
if (!cancel)
{
// post-process
result = mRules->DidDoAction(selection, &ruleInfo, result);
}
@ -1137,14 +1178,10 @@ NS_IMETHODIMP nsHTMLEditor::DeleteSelection(nsIEditor::ESelectionCollapseDirecti
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
nsCOMPtr<nsIDOMSelection> selection;
PRBool cancel= PR_FALSE;
PRBool cancel, handled;
// unnamed placeholder txns dont merge, but they do get sucked
// into placeholders that they are nested in. So this delte wont
// merge with other deletes, but if it happens in the course of
// a typing placehilder context, it will be consumed by that.
// This is the desired behavior.
nsAutoPlaceHolderBatch batch(this, nsnull);
// delete placeholder txns merge.
nsAutoPlaceHolderBatch batch(this, gDeleteTxnName);
// pre-process
nsresult result = GetSelection(getter_AddRefs(selection));
@ -1153,10 +1190,14 @@ NS_IMETHODIMP nsHTMLEditor::DeleteSelection(nsIEditor::ESelectionCollapseDirecti
nsTextRulesInfo ruleInfo(nsTextEditRules::kDeleteSelection);
ruleInfo.collapsedAction = aAction;
result = mRules->WillDoAction(selection, &ruleInfo, &cancel);
if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result)))
result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (NS_FAILED(result)) return result;
if (!cancel && !handled)
{
result = DeleteSelectionImpl(aAction);
}
if (!cancel)
{
// post-process
result = mRules->DidDoAction(selection, &ruleInfo, result);
}
@ -1169,30 +1210,32 @@ NS_IMETHODIMP nsHTMLEditor::InsertText(const nsString& aStringToInsert)
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
nsCOMPtr<nsIDOMSelection> selection;
PRBool cancel= PR_FALSE;
PRBool cancel, handled;
nsAutoPlaceHolderBatch batch(this, nsnull);
// pre-process
nsresult result = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(result)) return result;
if (!selection) return NS_ERROR_NULL_POINTER;
nsAutoString resultString;
PlaceholderTxn *placeholderTxn=nsnull;
nsTextRulesInfo ruleInfo(nsTextEditRules::kInsertText);
// ruleInfo.placeTxn = &placeholderTxn;
ruleInfo.inString = &aStringToInsert;
ruleInfo.outString = &resultString;
ruleInfo.typeInState = *mTypeInState;
ruleInfo.maxLength = mMaxTextLength;
result = mRules->WillDoAction(selection, &ruleInfo, &cancel);
if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result)))
result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (NS_FAILED(result)) return result;
if (!cancel && !handled)
{
result = InsertTextImpl(resultString);
}
if (!cancel)
{
// post-process
result = mRules->DidDoAction(selection, &ruleInfo, result);
}
// if (placeholderTxn)
// placeholderTxn->SetAbsorb(PR_FALSE); // this ends the merging of txns into placeholderTxn
return result;
}
@ -1290,7 +1333,7 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak()
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
nsCOMPtr<nsIDOMSelection> selection;
PRBool cancel= PR_FALSE;
PRBool cancel, handled;
// pre-process
res = GetSelection(getter_AddRefs(selection));
@ -1298,8 +1341,9 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak()
if (!selection) return NS_ERROR_NULL_POINTER;
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kInsertBreak);
res = mRules->WillDoAction(selection, &ruleInfo, &cancel);
if ((PR_FALSE==cancel) && (NS_SUCCEEDED(res)))
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (NS_FAILED(res)) return res;
if (!cancel && !handled)
{
// create the new BR node
nsCOMPtr<nsIDOMNode> newNode;
@ -1350,6 +1394,9 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak()
}
}
}
}
if (!cancel)
{
// post-process, always called if WillInsertBreak didn't return cancel==PR_TRUE
res = mRules->DidDoAction(selection, &ruleInfo, res);
}
@ -1374,106 +1421,110 @@ nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection)
return NS_ERROR_FAILURE;
// hand off to the rules system, see if it has anything to say about this
PRBool cancel;
PRBool cancel, handled;
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kInsertElement);
ruleInfo.insertElement = aElement;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel);
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (cancel || (NS_FAILED(res))) return res;
if (aDeleteSelection)
if (!handled)
{
nsCOMPtr<nsIDOMNode> tempNode;
PRInt32 tempOffset;
nsresult result = DeleteSelectionAndPrepareToCreateNode(tempNode,tempOffset);
if (!NS_SUCCEEDED(result))
return result;
}
// If deleting, selection will be collapsed.
// so if not, we collapse it
if (!aDeleteSelection)
{
// Named Anchor is a special case,
// We collapse to insert element BEFORE the selection
// For all other tags, we insert AFTER the selection
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
if (IsNamedAnchorNode(node))
if (aDeleteSelection)
{
selection->CollapseToStart();
} else {
selection->CollapseToEnd();
nsCOMPtr<nsIDOMNode> tempNode;
PRInt32 tempOffset;
nsresult result = DeleteSelectionAndPrepareToCreateNode(tempNode,tempOffset);
if (!NS_SUCCEEDED(result))
return result;
}
}
nsCOMPtr<nsIDOMNode> parentSelectedNode;
PRInt32 offsetForInsert;
res = selection->GetAnchorNode(getter_AddRefs(parentSelectedNode));
// XXX: ERROR_HANDLING bad XPCOM usage
if (NS_SUCCEEDED(res) && NS_SUCCEEDED(selection->GetAnchorOffset(&offsetForInsert)) && parentSelectedNode)
{
// If deleting, selection will be collapsed.
// so if not, we collapse it
if (!aDeleteSelection)
{
// Named Anchor is a special case,
// We collapse to insert element BEFORE the selection
// For all other tags, we insert AFTER the selection
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
if (IsNamedAnchorNode(node))
{
selection->CollapseToStart();
} else {
selection->CollapseToEnd();
}
}
nsCOMPtr<nsIDOMNode> parentSelectedNode;
PRInt32 offsetForInsert;
res = selection->GetAnchorNode(getter_AddRefs(parentSelectedNode));
// XXX: ERROR_HANDLING bad XPCOM usage
if (NS_SUCCEEDED(res) && NS_SUCCEEDED(selection->GetAnchorOffset(&offsetForInsert)) && parentSelectedNode)
{
#ifdef DEBUG_cmanske
{
nsAutoString name;
parentSelectedNode->GetNodeName(name);
printf("InsertElement: Anchor node of selection: ");
wprintf(name.GetUnicode());
printf(" Offset: %d\n", offsetForInsert);
}
{
nsAutoString name;
parentSelectedNode->GetNodeName(name);
printf("InsertElement: Anchor node of selection: ");
wprintf(name.GetUnicode());
printf(" Offset: %d\n", offsetForInsert);
}
#endif
nsAutoString tagName;
aElement->GetNodeName(tagName);
tagName.ToLowerCase();
nsCOMPtr<nsIDOMNode> parent = parentSelectedNode;
nsCOMPtr<nsIDOMNode> topChild = parentSelectedNode;
nsCOMPtr<nsIDOMNode> tmp;
nsAutoString parentTagName;
PRBool isRoot;
nsAutoString tagName;
aElement->GetNodeName(tagName);
tagName.ToLowerCase();
nsCOMPtr<nsIDOMNode> parent = parentSelectedNode;
nsCOMPtr<nsIDOMNode> topChild = parentSelectedNode;
nsCOMPtr<nsIDOMNode> tmp;
nsAutoString parentTagName;
PRBool isRoot;
// Search up the parent chain to find a suitable container
while (!CanContainTag(parent, tagName))
{
// If the current parent is a root (body or table cell)
// then go no further - we can't insert
parent->GetNodeName(parentTagName);
res = IsRootTag(parentTagName, isRoot);
if (!NS_SUCCEEDED(res) || isRoot)
return NS_ERROR_FAILURE;
// Get the next parent
parent->GetParentNode(getter_AddRefs(tmp));
if (!tmp)
return NS_ERROR_FAILURE;
topChild = parent;
parent = tmp;
}
// Search up the parent chain to find a suitable container
while (!CanContainTag(parent, tagName))
{
// If the current parent is a root (body or table cell)
// then go no further - we can't insert
parent->GetNodeName(parentTagName);
res = IsRootTag(parentTagName, isRoot);
if (!NS_SUCCEEDED(res) || isRoot)
return NS_ERROR_FAILURE;
// Get the next parent
parent->GetParentNode(getter_AddRefs(tmp));
if (!tmp)
return NS_ERROR_FAILURE;
topChild = parent;
parent = tmp;
}
#ifdef DEBUG_cmanske
{
nsAutoString name;
parent->GetNodeName(name);
printf("Parent node to insert under: ");
wprintf(name.GetUnicode());
printf("\n");
topChild->GetNodeName(name);
printf("TopChild to split: ");
wprintf(name.GetUnicode());
printf("\n");
}
{
nsAutoString name;
parent->GetNodeName(name);
printf("Parent node to insert under: ");
wprintf(name.GetUnicode());
printf("\n");
topChild->GetNodeName(name);
printf("TopChild to split: ");
wprintf(name.GetUnicode());
printf("\n");
}
#endif
if (parent != topChild)
{
// we need to split some levels above the original selection parent
res = SplitNodeDeep(topChild, parentSelectedNode, offsetForInsert, &offsetForInsert);
if (NS_FAILED(res))
return res;
if (parent != topChild)
{
// we need to split some levels above the original selection parent
res = SplitNodeDeep(topChild, parentSelectedNode, offsetForInsert, &offsetForInsert);
if (NS_FAILED(res))
return res;
}
// Now we can insert the new node
res = InsertNode(aElement, parent, offsetForInsert);
// Set caret after element, but check for special case
// of inserting table-related elements: set in first cell instead
if (!SetCaretInTableCell(aElement))
res = SetCaretAfterElement(aElement);
}
// Now we can insert the new node
res = InsertNode(aElement, parent, offsetForInsert);
// Set caret after element, but check for special case
// of inserting table-related elements: set in first cell instead
if (!SetCaretInTableCell(aElement))
res = SetCaretAfterElement(aElement);
}
res = mRules->DidDoAction(selection, &ruleInfo, res);
return res;
}
@ -1848,7 +1899,7 @@ nsHTMLEditor::InsertList(const nsString& aListType)
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
nsCOMPtr<nsIDOMSelection> selection;
PRBool cancel= PR_FALSE;
PRBool cancel, handled;
nsAutoEditBatch beginBatching(this);
@ -1860,222 +1911,31 @@ nsHTMLEditor::InsertList(const nsString& aListType)
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kMakeList);
if (aListType == "ol") ruleInfo.bOrdered = PR_TRUE;
else ruleInfo.bOrdered = PR_FALSE;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel);
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (cancel || (NS_FAILED(res))) return res;
// Find out if the selection is collapsed:
PRBool isCollapsed;
res = selection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMNode> node;
PRInt32 offset;
res = GetStartNodeAndOffset(selection, &node, &offset);
if (!node) res = NS_ERROR_FAILURE;
if (NS_FAILED(res)) return res;
if (isCollapsed)
if (!handled)
{
// 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));
if (!tmp) return NS_ERROR_FAILURE;
topChild = parent;
parent = tmp;
}
if (parent != node)
{
// we need to split up to the child of parent
res = SplitNodeDeep(topChild, node, offset, &offset);
if (NS_FAILED(res)) return res;
}
// Find out if the selection is collapsed:
PRBool isCollapsed;
res = selection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(res)) return res;
// make a list
nsCOMPtr<nsIDOMNode> newList;
res = CreateNode(aListType, parent, offset, getter_AddRefs(newList));
if (NS_FAILED(res)) return res;
// make a list item
nsAutoString tag("li");
nsCOMPtr<nsIDOMNode> newItem;
res = CreateNode(tag, newList, 0, getter_AddRefs(newItem));
if (NS_FAILED(res)) return res;
// put a space in it so layout will draw the list item
// XXX - revisit when layout is fixed
res = selection->Collapse(newItem,0);
if (NS_FAILED(res)) return res;
#if 0
nsAutoString theText(" ");
res = InsertText(theText);
if (NS_FAILED(res)) return res;
// reposition selection to before the space character
nsCOMPtr<nsIDOMNode> node;
PRInt32 offset;
res = GetStartNodeAndOffset(selection, &node, &offset);
if (!node) res = NS_ERROR_FAILURE;
if (NS_FAILED(res)) return res;
res = selection->Collapse(node,0);
if (NS_FAILED(res)) return res;
#endif
}
return res;
}
NS_IMETHODIMP
nsHTMLEditor::RemoveList(const nsString& aListType)
{
nsresult res;
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
nsCOMPtr<nsIDOMSelection> selection;
PRBool cancel= PR_FALSE;
nsAutoEditBatch beginBatching(this);
// pre-process
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_NULL_POINTER;
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kRemoveList);
if (aListType == "ol") ruleInfo.bOrdered = PR_TRUE;
else ruleInfo.bOrdered = PR_FALSE;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel);
if (cancel || (NS_FAILED(res))) return res;
// no default behavior for this yet. what would it mean?
return res;
}
NS_IMETHODIMP
nsHTMLEditor::InsertBasicBlock(const nsString& aBlockType)
{
nsresult res;
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
nsCOMPtr<nsIDOMSelection> selection;
PRBool cancel= PR_FALSE;
nsAutoEditBatch beginBatching(this);
// pre-process
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_NULL_POINTER;
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kMakeBasicBlock);
ruleInfo.blockType = &aBlockType;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel);
if (cancel || (NS_FAILED(res))) return res;
// Find out if the selection is collapsed:
PRBool isCollapsed;
res = selection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMNode> node;
PRInt32 offset;
res = GetStartNodeAndOffset(selection, &node, &offset);
if (!node) res = NS_ERROR_FAILURE;
if (NS_FAILED(res)) return res;
if (isCollapsed)
{
// have to find a place to put the block
nsCOMPtr<nsIDOMNode> parent = node;
nsCOMPtr<nsIDOMNode> topChild = node;
nsCOMPtr<nsIDOMNode> tmp;
while ( !CanContainTag(parent, aBlockType))
{
parent->GetParentNode(getter_AddRefs(tmp));
if (!tmp) return NS_ERROR_FAILURE;
topChild = parent;
parent = tmp;
}
if (parent != node)
{
// we need to split up to the child of parent
res = SplitNodeDeep(topChild, node, offset, &offset);
if (NS_FAILED(res)) return res;
}
// make a block
nsCOMPtr<nsIDOMNode> newBlock;
res = CreateNode(aBlockType, parent, offset, getter_AddRefs(newBlock));
if (NS_FAILED(res)) return res;
// xxx
// put a space in it so layout will draw it
res = selection->Collapse(newBlock,0);
if (NS_FAILED(res)) return res;
nsAutoString theText(nbsp);
res = InsertText(theText);
if (NS_FAILED(res)) return res;
// reposition selection to before the space character
res = GetStartNodeAndOffset(selection, &node, &offset);
if (NS_FAILED(res)) return res;
res = selection->Collapse(node,0);
if (NS_FAILED(res)) return res;
}
return res;
}
// TODO: Implement "outdent"
NS_IMETHODIMP
nsHTMLEditor::Indent(const nsString& aIndent)
{
nsresult res;
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
PRBool cancel= PR_FALSE;
nsAutoEditBatch beginBatching(this);
// pre-process
nsCOMPtr<nsIDOMSelection> selection;
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_NULL_POINTER;
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;
PRBool isCollapsed;
res = selection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(res)) return res;
res = GetStartNodeAndOffset(selection, &node, &offset);
if (!node) res = NS_ERROR_FAILURE;
if (NS_FAILED(res)) return res;
nsAutoString inward("indent");
if (aIndent == inward)
{
if (isCollapsed)
{
// have to find a place to put the blockquote
// have to find a place to put the list
nsCOMPtr<nsIDOMNode> parent = node;
nsCOMPtr<nsIDOMNode> topChild = node;
nsCOMPtr<nsIDOMNode> tmp;
nsAutoString bq("blockquote");
while ( !CanContainTag(parent, bq))
while ( !CanContainTag(parent, aListType))
{
parent->GetParentNode(getter_AddRefs(tmp));
if (!tmp) return NS_ERROR_FAILURE;
@ -2090,13 +1950,20 @@ nsHTMLEditor::Indent(const nsString& aIndent)
if (NS_FAILED(res)) return res;
}
// make a blockquote
nsCOMPtr<nsIDOMNode> newBQ;
res = CreateNode(bq, parent, offset, getter_AddRefs(newBQ));
// make a list
nsCOMPtr<nsIDOMNode> newList;
res = CreateNode(aListType, parent, offset, getter_AddRefs(newList));
if (NS_FAILED(res)) return res;
// make a list item
nsAutoString tag("li");
nsCOMPtr<nsIDOMNode> newItem;
res = CreateNode(tag, newList, 0, getter_AddRefs(newItem));
if (NS_FAILED(res)) return res;
// put a space in it so layout will draw the list item
res = selection->Collapse(newBQ,0);
// XXX - revisit when layout is fixed
res = selection->Collapse(newItem,0);
if (NS_FAILED(res)) return res;
#if 0
nsAutoString theText(" ");
res = InsertText(theText);
if (NS_FAILED(res)) return res;
@ -2105,9 +1972,205 @@ nsHTMLEditor::Indent(const nsString& aIndent)
if (NS_FAILED(res)) return res;
res = selection->Collapse(node,0);
if (NS_FAILED(res)) return res;
#endif
}
}
res = mRules->DidDoAction(selection, &ruleInfo, res);
return res;
}
NS_IMETHODIMP
nsHTMLEditor::RemoveList(const nsString& aListType)
{
nsresult res;
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
nsCOMPtr<nsIDOMSelection> selection;
PRBool cancel, handled;
nsAutoEditBatch beginBatching(this);
// pre-process
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_NULL_POINTER;
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kRemoveList);
if (aListType == "ol") ruleInfo.bOrdered = PR_TRUE;
else ruleInfo.bOrdered = PR_FALSE;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (cancel || (NS_FAILED(res))) return res;
// no default behavior for this yet. what would it mean?
res = mRules->DidDoAction(selection, &ruleInfo, res);
return res;
}
NS_IMETHODIMP
nsHTMLEditor::InsertBasicBlock(const nsString& aBlockType)
{
nsresult res;
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
nsCOMPtr<nsIDOMSelection> selection;
PRBool cancel, handled;
nsAutoEditBatch beginBatching(this);
// pre-process
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_NULL_POINTER;
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kMakeBasicBlock);
ruleInfo.blockType = &aBlockType;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (cancel || (NS_FAILED(res))) return res;
if (!handled)
{
// Find out if the selection is collapsed:
PRBool isCollapsed;
res = selection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMNode> node;
PRInt32 offset;
res = GetStartNodeAndOffset(selection, &node, &offset);
if (!node) res = NS_ERROR_FAILURE;
if (NS_FAILED(res)) return res;
if (isCollapsed)
{
// have to find a place to put the block
nsCOMPtr<nsIDOMNode> parent = node;
nsCOMPtr<nsIDOMNode> topChild = node;
nsCOMPtr<nsIDOMNode> tmp;
while ( !CanContainTag(parent, aBlockType))
{
parent->GetParentNode(getter_AddRefs(tmp));
if (!tmp) return NS_ERROR_FAILURE;
topChild = parent;
parent = tmp;
}
if (parent != node)
{
// we need to split up to the child of parent
res = SplitNodeDeep(topChild, node, offset, &offset);
if (NS_FAILED(res)) return res;
}
// make a block
nsCOMPtr<nsIDOMNode> newBlock;
res = CreateNode(aBlockType, parent, offset, getter_AddRefs(newBlock));
if (NS_FAILED(res)) return res;
// xxx
// put a space in it so layout will draw it
res = selection->Collapse(newBlock,0);
if (NS_FAILED(res)) return res;
nsAutoString theText(nbsp);
res = InsertText(theText);
if (NS_FAILED(res)) return res;
// reposition selection to before the space character
res = GetStartNodeAndOffset(selection, &node, &offset);
if (NS_FAILED(res)) return res;
res = selection->Collapse(node,0);
if (NS_FAILED(res)) return res;
}
}
res = mRules->DidDoAction(selection, &ruleInfo, res);
return res;
}
// TODO: Implement "outdent"
NS_IMETHODIMP
nsHTMLEditor::Indent(const nsString& aIndent)
{
nsresult res;
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
PRBool cancel, handled;
nsAutoEditBatch beginBatching(this);
// pre-process
nsCOMPtr<nsIDOMSelection> selection;
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_NULL_POINTER;
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kIndent);
if (aIndent == "outdent")
ruleInfo.action = nsHTMLEditRules::kOutdent;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (cancel || (NS_FAILED(res))) return res;
if (!handled)
{
// Do default - insert a blockquote node if selection collapsed
nsCOMPtr<nsIDOMNode> node;
PRInt32 offset;
PRBool isCollapsed;
res = selection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(res)) return res;
res = GetStartNodeAndOffset(selection, &node, &offset);
if (!node) res = NS_ERROR_FAILURE;
if (NS_FAILED(res)) return res;
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));
if (!tmp) return NS_ERROR_FAILURE;
topChild = parent;
parent = tmp;
}
if (parent != node)
{
// we need to split up to the child of parent
res = SplitNodeDeep(topChild, node, offset, &offset);
if (NS_FAILED(res)) return res;
}
// make a blockquote
nsCOMPtr<nsIDOMNode> newBQ;
res = CreateNode(bq, parent, offset, getter_AddRefs(newBQ));
if (NS_FAILED(res)) return res;
// put a space in it so layout will draw the list item
res = selection->Collapse(newBQ,0);
if (NS_FAILED(res)) return res;
nsAutoString theText(" ");
res = InsertText(theText);
if (NS_FAILED(res)) return res;
// reposition selection to before the space character
res = GetStartNodeAndOffset(selection, &node, &offset);
if (NS_FAILED(res)) return res;
res = selection->Collapse(node,0);
if (NS_FAILED(res)) return res;
}
}
}
res = mRules->DidDoAction(selection, &ruleInfo, res);
return res;
}
@ -2118,7 +2181,7 @@ nsHTMLEditor::Align(const nsString& aAlignType)
{
nsAutoEditBatch beginBatching(this);
nsCOMPtr<nsIDOMNode> node;
PRBool cancel= PR_FALSE;
PRBool cancel, handled;
// Find out if the selection is collapsed:
nsCOMPtr<nsIDOMSelection> selection;
@ -2127,8 +2190,11 @@ nsHTMLEditor::Align(const nsString& aAlignType)
if (!selection) return NS_ERROR_NULL_POINTER;
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kAlign);
ruleInfo.alignType = &aAlignType;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel);
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (cancel || NS_FAILED(res))
return res;
res = mRules->DidDoAction(selection, &ruleInfo, res);
return res;
}
@ -3284,8 +3350,8 @@ nsHTMLEditor::Undo(PRUint32 aCount)
nsTextRulesInfo ruleInfo(nsTextEditRules::kUndo);
nsCOMPtr<nsIDOMSelection> selection;
GetSelection(getter_AddRefs(selection));
PRBool cancel;
result = mRules->WillDoAction(selection, &ruleInfo, &cancel);
PRBool cancel, handled;
result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (!cancel && NS_SUCCEEDED(result))
{
@ -3309,8 +3375,8 @@ nsHTMLEditor::Redo(PRUint32 aCount)
nsTextRulesInfo ruleInfo(nsTextEditRules::kRedo);
nsCOMPtr<nsIDOMSelection> selection;
GetSelection(getter_AddRefs(selection));
PRBool cancel;
result = mRules->WillDoAction(selection, &ruleInfo, &cancel);
PRBool cancel, handled;
result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (!cancel && NS_SUCCEEDED(result))
{
@ -3441,14 +3507,14 @@ NS_IMETHODIMP nsHTMLEditor::OutputToString(nsString& aOutputString,
const nsString& aFormatType,
PRUint32 aFlags)
{
PRBool cancel;
PRBool cancel, handled;
nsString resultString;
nsTextRulesInfo ruleInfo(nsTextEditRules::kOutputText);
ruleInfo.outString = &resultString;
ruleInfo.outputFormat = &aFormatType;
nsresult rv = mRules->WillDoAction(nsnull, &ruleInfo, &cancel);
if (NS_FAILED(rv)) { return rv; }
if (PR_TRUE==cancel)
nsresult rv = mRules->WillDoAction(nsnull, &ruleInfo, &cancel, &handled);
if (cancel || NS_FAILED(rv)) { return rv; }
if (handled)
{ // this case will get triggered by password fields
aOutputString = *(ruleInfo.outString);
}
@ -3680,10 +3746,10 @@ nsHTMLEditor::SetCompositionString(const nsString& aCompositionString, nsIPrivat
nsresult result = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(result)) return result;
nsTextRulesInfo ruleInfo(nsTextEditRules::kInsertTextIME);
PRBool cancel;
result = mRules->WillDoAction(selection, &ruleInfo, &cancel);
if (NS_FAILED(result)) return result;
// we don't care if WillInsert said to cancel...
PRBool cancel, handled;
result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (cancel || NS_FAILED(result)) return result;
result = SetInputMethodText(aCompositionString,aTextRangeList);
if (NS_FAILED(result)) return result;
mIMEBufferLength = aCompositionString.Length();
@ -3694,6 +3760,7 @@ nsHTMLEditor::SetCompositionString(const nsString& aCompositionString, nsIPrivat
ps->GetCaret(getter_AddRefs(caretP));
caretP->GetWindowRelativeCoordinates(aReply->mCursorPosition,aReply->mCursorIsCollapsed);
result = mRules->DidDoAction(selection, &ruleInfo, result);
return result;
}

Просмотреть файл

@ -62,6 +62,7 @@ public:
/* ------------ nsIHTMLEditor methods -------------- */
NS_IMETHOD EditorKeyPress(nsIDOMUIEvent* aKeyEvent);
NS_IMETHOD TypedText(const nsString& aString, PRInt32 aAction);
NS_IMETHOD GetDocumentIsEmpty(PRBool *aDocumentIsEmpty);
NS_IMETHOD GetDocumentLength(PRInt32 *aCount);
@ -482,6 +483,7 @@ protected:
public:
static nsIAtom *gTypingTxnName;
static nsIAtom *gDeleteTxnName;
// friends
friend class nsHTMLEditRules;

Просмотреть файл

@ -155,6 +155,27 @@ nsHTMLEditorLog::DeleteSelection(nsIEditor::ESelectionCollapseDirection aAction)
return nsHTMLEditor::DeleteSelection(aAction);
}
NS_IMETHODIMP
nsHTMLEditorLog::TypedText(const nsString& aStringToInsert, PRInt32 aAction)
{
nsAutoHTMLEditorLogLock logLock(this);
if (!mLocked && mFileSpec)
{
PrintSelection();
Write("window.editorShell.TypedText(\"");
PrintUnicode(aStringToInsert);
Write("\", ");
WriteInt("%d", aAction);
Write(");\n");
Flush();
}
return nsHTMLEditor::TypedText(aStringToInsert, aAction);
}
NS_IMETHODIMP
nsHTMLEditorLog::InsertText(const nsString& aStringToInsert)
{

Просмотреть файл

@ -54,6 +54,7 @@ public:
NS_IMETHOD SetParagraphFormat(const nsString& aParagraphFormat);
NS_IMETHOD RemoveInlineProperty(nsIAtom *aProperty, const nsString *aAttribute);
NS_IMETHOD DeleteSelection(nsIEditor::ESelectionCollapseDirection aAction);
NS_IMETHOD TypedText(const nsString& aString, PRInt32 aAction);
NS_IMETHOD InsertText(const nsString& aStringToInsert);
NS_IMETHOD InsertBreak();
NS_IMETHOD Undo(PRUint32 aCount);

Просмотреть файл

@ -121,12 +121,15 @@ nsTextEditRules::SetFlags(PRUint32 aFlags)
NS_IMETHODIMP
nsTextEditRules::WillDoAction(nsIDOMSelection *aSelection,
nsRulesInfo *aInfo, PRBool *aCancel)
nsRulesInfo *aInfo,
PRBool *aCancel,
PRBool *aHandled)
{
// null selection is legal
if (!aInfo || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aInfo || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
// my kingdom for dynamic cast
nsTextRulesInfo *info = NS_STATIC_CAST(nsTextRulesInfo*, aInfo);
@ -134,10 +137,11 @@ nsTextEditRules::WillDoAction(nsIDOMSelection *aSelection,
switch (info->action)
{
case kInsertBreak:
return WillInsertBreak(aSelection, aCancel);
return WillInsertBreak(aSelection, aCancel, aHandled);
case kInsertText:
return WillInsertText(aSelection,
aCancel,
aCancel,
aHandled,
info->inString,
info->outString,
info->typeInState,
@ -145,20 +149,21 @@ nsTextEditRules::WillDoAction(nsIDOMSelection *aSelection,
case kInsertTextIME:
return WillInsert(aSelection, aCancel);
case kDeleteSelection:
return WillDeleteSelection(aSelection, info->collapsedAction, aCancel);
return WillDeleteSelection(aSelection, info->collapsedAction, aCancel, aHandled);
case kUndo:
return WillUndo(aSelection, aCancel);
return WillUndo(aSelection, aCancel, aHandled);
case kRedo:
return WillRedo(aSelection, aCancel);
return WillRedo(aSelection, aCancel, aHandled);
case kSetTextProperty:
return WillSetTextProperty(aSelection, aCancel);
return WillSetTextProperty(aSelection, aCancel, aHandled);
case kRemoveTextProperty:
return WillRemoveTextProperty(aSelection, aCancel);
return WillRemoveTextProperty(aSelection, aCancel, aHandled);
case kOutputText:
return WillOutputText(aSelection,
info->outputFormat,
info->outString,
aCancel);
aCancel,
aHandled);
}
return NS_ERROR_FAILURE;
}
@ -239,10 +244,11 @@ nsTextEditRules::DidInsert(nsIDOMSelection *aSelection, nsresult aResult)
}
nsresult
nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
CANCEL_OPERATION_IF_READONLY_OR_DISABLED
*aHandled = PR_FALSE;
if (mFlags & nsIHTMLEditor::eEditorSingleLineMask) {
*aCancel = PR_TRUE;
}
@ -261,19 +267,22 @@ nsTextEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult)
nsresult
nsTextEditRules::WillInsertText(nsIDOMSelection *aSelection,
PRBool *aCancel,
PRBool *aCancel,
PRBool *aHandled,
const nsString *aInString,
nsString *aOutString,
TypeInState aTypeInState,
PRInt32 aMaxLength)
{
if (!aSelection || !aCancel || !aInString || !aOutString) {return NS_ERROR_NULL_POINTER;}
if (!aSelection || !aCancel || !aHandled || !aInString || !aOutString)
{return NS_ERROR_NULL_POINTER;}
CANCEL_OPERATION_IF_READONLY_OR_DISABLED
nsresult res;
// initialize out params
*aCancel = PR_TRUE;
*aCancel = PR_FALSE;
*aHandled = PR_TRUE;
*aOutString = *aInString;
// handle docs with a max length
@ -576,8 +585,10 @@ nsTextEditRules::InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, nsIAtom *aTa
}
nsresult
nsTextEditRules::WillSetTextProperty(nsIDOMSelection *aSelection, PRBool *aCancel)
nsTextEditRules::WillSetTextProperty(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled)
{
if (!aSelection || !aCancel || !aHandled)
{ return NS_ERROR_NULL_POINTER; }
nsresult res = NS_OK;
// XXX: should probably return a success value other than NS_OK that means "not allowed"
@ -594,8 +605,10 @@ nsTextEditRules::DidSetTextProperty(nsIDOMSelection *aSelection, nsresult aResul
}
nsresult
nsTextEditRules::WillRemoveTextProperty(nsIDOMSelection *aSelection, PRBool *aCancel)
nsTextEditRules::WillRemoveTextProperty(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled)
{
if (!aSelection || !aCancel || !aHandled)
{ return NS_ERROR_NULL_POINTER; }
nsresult res = NS_OK;
// XXX: should probably return a success value other than NS_OK that means "not allowed"
@ -614,13 +627,15 @@ nsTextEditRules::DidRemoveTextProperty(nsIDOMSelection *aSelection, nsresult aRe
nsresult
nsTextEditRules::WillDeleteSelection(nsIDOMSelection *aSelection,
nsIEditor::ESelectionCollapseDirection aCollapsedAction,
PRBool *aCancel)
PRBool *aCancel,
PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
CANCEL_OPERATION_IF_READONLY_OR_DISABLED
// initialize out param
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
// if there is only bogus content, cancel the operation
if (mBogusNode) {
@ -745,12 +760,13 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection,
}
nsresult
nsTextEditRules::WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel)
nsTextEditRules::WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
CANCEL_OPERATION_IF_READONLY_OR_DISABLED
// initialize out param
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
return NS_OK;
}
@ -808,12 +824,13 @@ nsTextEditRules:: DidUndo(nsIDOMSelection *aSelection, nsresult aResult)
}
nsresult
nsTextEditRules::WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel)
nsTextEditRules::WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
CANCEL_OPERATION_IF_READONLY_OR_DISABLED
// initialize out param
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
return NS_OK;
}
@ -869,25 +886,28 @@ nsresult
nsTextEditRules::WillOutputText(nsIDOMSelection *aSelection,
const nsString *aOutputFormat,
nsString *aOutString,
PRBool *aCancel)
PRBool *aCancel,
PRBool *aHandled)
{
// null selection ok
if (!aOutString || !aOutputFormat || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aOutString || !aOutputFormat || !aCancel || !aHandled)
{ return NS_ERROR_NULL_POINTER; }
// initialize out param
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
if (PR_TRUE == aOutputFormat->Equals("text/plain"))
{ // only use these rules for plain text output
if (mFlags & nsIHTMLEditor::eEditorPasswordMask)
{
*aOutString = mPasswordText;
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
}
else if (mBogusNode)
{ // this means there's no content, so output null string
*aOutString = "";
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
}
}
return NS_OK;

Просмотреть файл

@ -49,7 +49,7 @@ public:
// nsEditRules methods
NS_IMETHOD Init(nsHTMLEditor *aEditor, PRUint32 aFlags);
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel);
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel, PRBool *aHandled);
NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult);
NS_IMETHOD GetFlags(PRUint32 *aFlags);
NS_IMETHOD SetFlags(PRUint32 aFlags);
@ -85,6 +85,7 @@ protected:
// nsTextEditRules implementation methods
nsresult WillInsertText(nsIDOMSelection *aSelection,
PRBool *aCancel,
PRBool *aHandled,
const nsString *inString,
nsString *outString,
TypeInState typeInState,
@ -92,7 +93,7 @@ protected:
nsresult DidInsertText(nsIDOMSelection *aSelection, nsresult aResult);
nsresult CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInState &aTypeInState);
nsresult WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel);
nsresult WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult);
nsresult WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel);
@ -100,21 +101,22 @@ protected:
nsresult WillDeleteSelection(nsIDOMSelection *aSelection,
nsIEditor::ESelectionCollapseDirection aCollapsedAction,
PRBool *aCancel);
PRBool *aCancel,
PRBool *aHandled);
nsresult DidDeleteSelection(nsIDOMSelection *aSelection,
nsIEditor::ESelectionCollapseDirection aCollapsedAction,
nsresult aResult);
nsresult WillSetTextProperty(nsIDOMSelection *aSelection, PRBool *aCancel);
nsresult WillSetTextProperty(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult DidSetTextProperty(nsIDOMSelection *aSelection, nsresult aResult);
nsresult WillRemoveTextProperty(nsIDOMSelection *aSelection, PRBool *aCancel);
nsresult WillRemoveTextProperty(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult DidRemoveTextProperty(nsIDOMSelection *aSelection, nsresult aResult);
nsresult WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel);
nsresult WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult DidUndo(nsIDOMSelection *aSelection, nsresult aResult);
nsresult WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel);
nsresult WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult DidRedo(nsIDOMSelection *aSelection, nsresult aResult);
/** called prior to nsIEditor::OutputToString
@ -127,7 +129,8 @@ protected:
nsresult WillOutputText(nsIDOMSelection *aSelection,
const nsString *aInFormat,
nsString *aOutText,
PRBool *aOutCancel);
PRBool *aOutCancel,
PRBool *aHandled);
nsresult DidOutputText(nsIDOMSelection *aSelection, nsresult aResult);

Просмотреть файл

@ -1782,6 +1782,32 @@ nsEditorShell::DeleteSelection(PRInt32 action)
return err;
}
/* This routine should only be called when playing back a log */
NS_IMETHODIMP
nsEditorShell::TypedText(const PRUnichar *aTextToInsert, PRInt32 aAction)
{
nsresult err = NS_NOINTERFACE;
nsAutoString textToInsert(aTextToInsert);
switch (mEditorType)
{
case ePlainTextEditorType:
case eHTMLTextEditorType:
{
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(mEditor);
if (htmlEditor)
err = htmlEditor->TypedText(textToInsert, aAction);
}
break;
default:
err = NS_ERROR_NOT_IMPLEMENTED;
}
return err;
}
NS_IMETHODIMP
nsEditorShell::InsertText(const PRUnichar *textToInsert)

Просмотреть файл

@ -146,6 +146,8 @@ interface nsIEditorShell : nsISupports
void SetDocumentCharacterSet(in wstring characterSet);
/* Structure change */
/* TypedText actionToTake param is an enum - values in nsIHTMLEditor.h */
void TypedText(in wstring textToInsert, in PRInt32 actionToTake);
void InsertText(in wstring textToInsert);
void InsertSource(in wstring textToInsert);
void InsertBreak();

Просмотреть файл

@ -112,8 +112,9 @@ NS_IMETHODIMP PlaceholderTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransact
if (gNoisy) { printf("Placeholder txn assimilated %p\n", aTransaction); }
}
else
{ // merge typing transactions if the selection matches
if (mName.get() == nsHTMLEditor::gTypingTxnName)
{ // merge typing or deletion transactions if the selection matches
if ( (mName.get() == nsHTMLEditor::gTypingTxnName) ||
(mName.get() == nsHTMLEditor::gDeleteTxnName) )
{
nsCOMPtr<nsIAbsorbingTransaction> plcTxn;// = do_QueryInterface(editTxn);
// cant do_QueryInterface() above due to our broken transaction interfaces.
@ -123,7 +124,7 @@ NS_IMETHODIMP PlaceholderTxn::Merge(PRBool *aDidMerge, nsITransaction *aTransact
{
nsIAtom *atom;
plcTxn->GetTxnName(&atom);
if (atom && (atom == nsHTMLEditor::gTypingTxnName))
if (atom && (atom == mName.get()))
{
nsCOMPtr<nsIDOMNode> otherTxnStartNode;
PRInt32 otherTxnStartOffset;
@ -167,8 +168,9 @@ NS_IMETHODIMP PlaceholderTxn::EndPlaceHolderBatch()
if (plcTxn) plcTxn->EndPlaceHolderBatch();
}
// if we are a typing transaction, remember our selection state
if (mName.get() == nsHTMLEditor::gTypingTxnName)
// if we are a typing or deleting transaction, remember our selection state
if ( (mName.get() == nsHTMLEditor::gTypingTxnName) ||
(mName.get() == nsHTMLEditor::gDeleteTxnName) )
{
nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
if (!ps) return NS_ERROR_NOT_INITIALIZED;

Просмотреть файл

@ -44,7 +44,7 @@ class nsEditRules
{
public:
NS_IMETHOD Init(nsHTMLEditor *aEditor, PRUint32 aFlags)=0;
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel)=0;
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel, PRBool *aHandled)=0;
NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult)=0;
NS_IMETHOD GetFlags(PRUint32 *aFlags)=0;
NS_IMETHOD SetFlags(PRUint32 aFlags)=0;

Просмотреть файл

@ -563,7 +563,7 @@ nsEditor::BeginPlaceHolderTransaction(nsIAtom *aName)
PRBool collapsed;
res = selection->GetIsCollapsed(&collapsed);
if (NS_FAILED(res)) return res;
if (collapsed) // we cant merge with previous typing if selection not collapsed
if (collapsed) // we cant merge with previous typing/deleting if selection not collapsed
{
// need to remember colapsed selection point to Init the placeholder with later.
// this is because we dont actually make the placeholder until we need it, and we

Просмотреть файл

@ -617,11 +617,11 @@ protected:
nsCOMPtr<nsITransactionManager> mTxnMgr;
nsCOMPtr<nsIEditProperty> mEditProperty;
nsCOMPtr<nsICSSStyleSheet> mLastStyleSheet; // is owning this dangerous?
nsWeakPtr mPlaceHolderTxn;
nsIAtom *mPlaceHolderName;
PRInt32 mPlaceHolderBatch;
nsCOMPtr<nsIDOMNode> mTxnStartNode;
PRInt32 mTxnStartOffset;
nsWeakPtr mPlaceHolderTxn; // weak reference to placeholder for begin/end batch purposes
nsIAtom *mPlaceHolderName; // name of placeholder transaction
PRInt32 mPlaceHolderBatch; // nesting count for batching
nsCOMPtr<nsIDOMNode> mTxnStartNode; // saved selection info to pass to placeholder at init time
PRInt32 mTxnStartOffset; // " " " "
//
// data necessary to build IME transactions

Просмотреть файл

@ -72,12 +72,15 @@ nsHTMLEditRules::~nsHTMLEditRules()
NS_IMETHODIMP
nsHTMLEditRules::WillDoAction(nsIDOMSelection *aSelection,
nsRulesInfo *aInfo, PRBool *aCancel)
nsRulesInfo *aInfo,
PRBool *aCancel,
PRBool *aHandled)
{
if (!aInfo || !aCancel)
if (!aInfo || !aCancel || !aHandled)
return NS_ERROR_NULL_POINTER;
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
// my kingdom for dynamic cast
nsTextRulesInfo *info = NS_STATIC_CAST(nsTextRulesInfo*, aInfo);
@ -87,30 +90,31 @@ nsHTMLEditRules::WillDoAction(nsIDOMSelection *aSelection,
case kInsertText:
return WillInsertText(aSelection,
aCancel,
aHandled,
info->inString,
info->outString,
info->typeInState,
info->maxLength);
case kInsertBreak:
return WillInsertBreak(aSelection, aCancel);
return WillInsertBreak(aSelection, aCancel, aHandled);
case kDeleteSelection:
return WillDeleteSelection(aSelection, info->collapsedAction, aCancel);
return WillDeleteSelection(aSelection, info->collapsedAction, aCancel, aHandled);
case kMakeList:
return WillMakeList(aSelection, info->bOrdered, aCancel);
return WillMakeList(aSelection, info->bOrdered, aCancel, aHandled);
case kIndent:
return WillIndent(aSelection, aCancel);
return WillIndent(aSelection, aCancel, aHandled);
case kOutdent:
return WillOutdent(aSelection, aCancel);
return WillOutdent(aSelection, aCancel, aHandled);
case kAlign:
return WillAlign(aSelection, info->alignType, aCancel);
return WillAlign(aSelection, info->alignType, aCancel, aHandled);
case kMakeBasicBlock:
return WillMakeBasicBlock(aSelection, info->blockType, aCancel);
return WillMakeBasicBlock(aSelection, info->blockType, aCancel, aHandled);
case kRemoveList:
return WillRemoveList(aSelection, info->bOrdered, aCancel);
return WillRemoveList(aSelection, info->bOrdered, aCancel, aHandled);
case kInsertElement:
return WillInsert(aSelection, aCancel);
}
return nsTextEditRules::WillDoAction(aSelection, aInfo, aCancel);
return nsTextEditRules::WillDoAction(aSelection, aInfo, aCancel, aHandled);
}
@ -143,14 +147,16 @@ nsHTMLEditRules::DidDoAction(nsIDOMSelection *aSelection,
nsresult
nsHTMLEditRules::WillInsertText(nsIDOMSelection *aSelection,
PRBool *aCancel,
PRBool *aHandled,
const nsString *inString,
nsString *outString,
TypeInState typeInState,
PRInt32 aMaxLength)
{ if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
{ if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
// initialize out param
*aCancel = PR_TRUE;
*aCancel = PR_FALSE;
*aHandled = PR_TRUE;
nsresult res;
nsCOMPtr<nsIDOMNode> selNode;
PRInt32 selOffset;
@ -176,7 +182,7 @@ nsHTMLEditRules::WillInsertText(nsIDOMSelection *aSelection,
// initialize out param
// we want to ignore result of WillInsert()
*aCancel = PR_TRUE;
*aCancel = PR_FALSE;
// split any mailcites in the way
if (mFlags & nsIHTMLEditor::eEditorMailMask)
@ -277,23 +283,23 @@ nsHTMLEditRules::WillInsertText(nsIDOMSelection *aSelection,
// is it a solo tab?
if (partialString == "\t" )
{
res = InsertTab(aSelection,&bCancel,outString);
res = InsertTab(aSelection,outString);
if (NS_FAILED(res)) return res;
res = DoTextInsertion(aSelection, aCancel, outString, typeInState);
res = DoTextInsertion(aSelection, &bCancel, outString, typeInState);
}
// is it a solo space?
else if (partialString == " ")
{
res = InsertSpace(aSelection,&bCancel,outString);
res = InsertSpace(aSelection,outString);
if (NS_FAILED(res)) return res;
res = DoTextInsertion(aSelection, aCancel, outString, typeInState);
res = DoTextInsertion(aSelection, &bCancel, outString, typeInState);
}
// is it a solo nbsp?
else if (partialString == nbspStr)
{
res = InsertSpace(aSelection,&bCancel,outString);
res = InsertSpace(aSelection,outString);
if (NS_FAILED(res)) return res;
res = DoTextInsertion(aSelection, aCancel, outString, typeInState);
res = DoTextInsertion(aSelection, &bCancel, outString, typeInState);
}
// is it a solo return?
else if (partialString == "\n")
@ -302,7 +308,7 @@ nsHTMLEditRules::WillInsertText(nsIDOMSelection *aSelection,
}
else
{
res = DoTextInsertion(aSelection, aCancel, &partialString, typeInState);
res = DoTextInsertion(aSelection, &bCancel, &partialString, typeInState);
}
if (NS_FAILED(res)) return res;
pos = theString.FindCharInSet(specialChars);
@ -312,11 +318,12 @@ nsHTMLEditRules::WillInsertText(nsIDOMSelection *aSelection,
}
nsresult
nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
// initialize out param
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
nsresult res;
res = WillInsert(aSelection, aCancel);
@ -372,7 +379,7 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
if (isPRE)
{
nsString theString = "\n";
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
return mEditor->InsertTextImpl(theString);
}
@ -415,7 +422,7 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
res = mEditor->SetAttribute(brElem, "type", "_moz");
if (NS_FAILED(res)) return res;
}
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
}
else if (bIsMozDiv && AtStartOfBlock(node, offset, blockParent))
{
@ -442,21 +449,21 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
if (!newDiv || !IsMozDiv(newDiv)) return NS_ERROR_FAILURE;
res = aSelection->Collapse(newDiv, 0);
if (NS_FAILED(res)) return res;
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
}
// headers: close (or split) header
else if (IsHeader(blockParent))
{
res = ReturnInHeader(aSelection, blockParent, node, offset);
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
return NS_OK;
}
// paragraphs: special rules to look for <br>s
else if (IsParagraph(blockParent))
{
res = ReturnInParagraph(aSelection, blockParent, node, offset, aCancel);
res = ReturnInParagraph(aSelection, blockParent, node, offset, aCancel, aHandled);
return NS_OK;
}
@ -464,7 +471,7 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
else if (IsListItem(blockParent))
{
res = ReturnInListItem(aSelection, blockParent, node, offset);
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
return NS_OK;
}
@ -474,11 +481,15 @@ nsHTMLEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
nsresult
nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESelectionCollapseDirection aAction, PRBool *aCancel)
nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection,
nsIEditor::ESelectionCollapseDirection aAction,
PRBool *aCancel,
PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
// initialize out param
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
// if there is only bogus content, cancel the operation
if (mBogusNode)
@ -542,7 +553,7 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
nsCOMPtr<nsIDOMNode> topParent;
leftParent->GetParentNode(getter_AddRefs(topParent));
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
res = JoinNodesSmart(leftParent,rightParent,&selNode,&selOffset);
if (NS_FAILED(res)) return res;
// fix up selection
@ -582,7 +593,7 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
nsCOMPtr<nsIDOMNode> topParent;
leftParent->GetParentNode(getter_AddRefs(topParent));
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
res = JoinNodesSmart(leftParent,rightParent,&selNode,&selOffset);
if (NS_FAILED(res)) return res;
// fix up selection
@ -689,7 +700,7 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
if (IsParagraph(leftParent))
{
// first delete the selection
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
res = mEditor->DeleteSelectionImpl(aAction);
if (NS_FAILED(res)) return res;
// then join para's, insert break
@ -702,7 +713,7 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
if (IsListItem(leftParent) || IsHeader(leftParent))
{
// first delete the selection
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
res = mEditor->DeleteSelectionImpl(aAction);
if (NS_FAILED(res)) return res;
// join blocks
@ -723,9 +734,12 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESe
nsresult
nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection, PRBool aOrdered, PRBool *aCancel)
nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection,
PRBool aOrdered,
PRBool *aCancel,
PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
nsresult res = WillInsert(aSelection, aCancel);
if (NS_FAILED(res)) return res;
@ -733,6 +747,7 @@ nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection, PRBool aOrdered, PRBo
// initialize out param
// we want to ignore result of WillInsert()
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
nsAutoString blockType("ul");
if (aOrdered) blockType = "ol";
@ -752,7 +767,7 @@ nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection, PRBool aOrdered, PRBo
// block parent, and then further expands to include any ancestors
// whose children are all in the range
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
nsCOMPtr<nsISupportsArray> arrayOfRanges;
res = GetPromotedRanges(aSelection, &arrayOfRanges, kMakeList);
@ -964,11 +979,15 @@ nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection, PRBool aOrdered, PRBo
nsresult
nsHTMLEditRules::WillRemoveList(nsIDOMSelection *aSelection, PRBool aOrdered, PRBool *aCancel)
nsHTMLEditRules::WillRemoveList(nsIDOMSelection *aSelection,
PRBool aOrdered,
PRBool *aCancel,
PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
// initialize out param
*aCancel = PR_TRUE;
*aCancel = PR_FALSE;
*aHandled = PR_TRUE;
nsAutoString blockType("ul");
if (aOrdered) blockType = "ol";
@ -1053,11 +1072,15 @@ nsHTMLEditRules::WillRemoveList(nsIDOMSelection *aSelection, PRBool aOrdered, PR
nsresult
nsHTMLEditRules::WillMakeBasicBlock(nsIDOMSelection *aSelection, const nsString *aBlockType, PRBool *aCancel)
nsHTMLEditRules::WillMakeBasicBlock(nsIDOMSelection *aSelection,
const nsString *aBlockType,
PRBool *aCancel,
PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
// initialize out param
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
PRBool makeEmpty;
nsresult res = ShouldMakeEmptyBlock(aSelection, aBlockType, &makeEmpty);
@ -1067,7 +1090,7 @@ nsHTMLEditRules::WillMakeBasicBlock(nsIDOMSelection *aSelection, const nsString
// else it's not that easy...
nsAutoSelectionReset selectionResetter(aSelection);
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
nsCOMPtr<nsISupportsArray> arrayOfRanges;
res = GetPromotedRanges(aSelection, &arrayOfRanges, kMakeBasicBlock);
@ -1086,16 +1109,17 @@ nsHTMLEditRules::WillMakeBasicBlock(nsIDOMSelection *aSelection, const nsString
nsresult
nsHTMLEditRules::WillIndent(nsIDOMSelection *aSelection, PRBool *aCancel)
nsHTMLEditRules::WillIndent(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool * aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
nsresult res = WillInsert(aSelection, aCancel);
if (NS_FAILED(res)) return res;
// initialize out param
// we want to ignore result of WillInsert()
*aCancel = PR_TRUE;
*aCancel = PR_FALSE;
*aHandled = PR_TRUE;
nsAutoSelectionReset selectionResetter(aSelection);
@ -1194,11 +1218,12 @@ nsHTMLEditRules::WillIndent(nsIDOMSelection *aSelection, PRBool *aCancel)
nsresult
nsHTMLEditRules::WillOutdent(nsIDOMSelection *aSelection, PRBool *aCancel)
nsHTMLEditRules::WillOutdent(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
// initialize out param
*aCancel = PR_TRUE;
*aCancel = PR_FALSE;
*aHandled = PR_TRUE;
nsAutoSelectionReset selectionResetter(aSelection);
nsresult res = NS_OK;
@ -1302,9 +1327,12 @@ nsHTMLEditRules::WillOutdent(nsIDOMSelection *aSelection, PRBool *aCancel)
nsresult
nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection, const nsString *alignType, PRBool *aCancel)
nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection,
const nsString *alignType,
PRBool *aCancel,
PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
nsresult res = WillInsert(aSelection, aCancel);
if (NS_FAILED(res)) return res;
@ -1312,7 +1340,8 @@ nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection, const nsString *alignTyp
// initialize out param
// we want to ignore result of WillInsert()
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
nsAutoSelectionReset selectionResetter(aSelection);
PRBool outMakeEmpty;
@ -1325,7 +1354,7 @@ nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection, const nsString *alignTyp
// this basically just expands the range to include the immediate
// block parent, and then further expands to include any ancestors
// whose children are all in the range
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
nsCOMPtr<nsISupportsArray> arrayOfRanges;
res = GetPromotedRanges(aSelection, &arrayOfRanges, kAlign);
@ -2475,7 +2504,6 @@ nsHTMLEditRules::InsertContainerAbove(nsIDOMNode *inNode,
//
nsresult
nsHTMLEditRules::InsertTab(nsIDOMSelection *aSelection,
PRBool *aCancel,
nsString *outString)
{
nsCOMPtr<nsIDOMNode> parentNode;
@ -2538,7 +2566,6 @@ nsHTMLEditRules::InsertTab(nsIDOMSelection *aSelection,
//
nsresult
nsHTMLEditRules::InsertSpace(nsIDOMSelection *aSelection,
PRBool *aCancel,
nsString *outString)
{
nsCOMPtr<nsIDOMNode> parentNode;
@ -2650,10 +2677,13 @@ nsHTMLEditRules::ReturnInParagraph(nsIDOMSelection *aSelection,
nsIDOMNode *aHeader,
nsIDOMNode *aNode,
PRInt32 aOffset,
PRBool *aCancel)
PRBool *aCancel,
PRBool *aHandled)
{
if (!aSelection || !aHeader || !aNode || !aCancel) return NS_ERROR_NULL_POINTER;
if (!aSelection || !aHeader || !aNode || !aCancel || !aHandled)
{ return NS_ERROR_NULL_POINTER; }
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
nsCOMPtr<nsIDOMNode> sibling;
nsresult res = NS_OK;
@ -3308,6 +3338,7 @@ nsHTMLEditRules::CleanUpSelection(nsIDOMSelection *aSelection)
isupports = do_QueryInterface(node);
arrayOfNodes->AppendElement(isupports);
}
res = iter->Next();
if (NS_FAILED(res)) return res;
}

Просмотреть файл

@ -34,7 +34,7 @@ public:
virtual ~nsHTMLEditRules();
// nsEditRules methods
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel);
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel, PRBool *aHandled);
NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult);
protected:
@ -49,24 +49,26 @@ protected:
// nsHTMLEditRules implementation methods
nsresult WillInsertText(nsIDOMSelection *aSelection,
PRBool *aCancel,
PRBool *aHandled,
const nsString *inString,
nsString *outString,
TypeInState typeInState,
PRInt32 aMaxLength);
nsresult WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel);
nsresult WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESelectionCollapseDirection aAction, PRBool *aCancel);
nsresult WillMakeList(nsIDOMSelection *aSelection, PRBool aOrderd, PRBool *aCancel);
nsresult WillRemoveList(nsIDOMSelection *aSelection, PRBool aOrderd, PRBool *aCancel);
nsresult WillIndent(nsIDOMSelection *aSelection, PRBool *aCancel);
nsresult WillOutdent(nsIDOMSelection *aSelection, PRBool *aCancel);
nsresult WillAlign(nsIDOMSelection *aSelection, const nsString *alignType, PRBool *aCancel);
nsresult WillMakeBasicBlock(nsIDOMSelection *aSelection, const nsString *aBlockType, PRBool *aCancel);
nsresult WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult WillDeleteSelection(nsIDOMSelection *aSelection, nsIEditor::ESelectionCollapseDirection aAction,
PRBool *aCancel, PRBool *aHandled);
nsresult WillMakeList(nsIDOMSelection *aSelection, PRBool aOrderd, PRBool *aCancel, PRBool *aHandled);
nsresult WillRemoveList(nsIDOMSelection *aSelection, PRBool aOrderd, PRBool *aCancel, PRBool *aHandled);
nsresult WillIndent(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult WillOutdent(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult WillAlign(nsIDOMSelection *aSelection, const nsString *alignType, PRBool *aCancel, PRBool *aHandled);
nsresult WillMakeBasicBlock(nsIDOMSelection *aSelection, const nsString *aBlockType, PRBool *aCancel, PRBool *aHandled);
nsresult InsertTab(nsIDOMSelection *aSelection, PRBool *aCancel, nsString *outString);
nsresult InsertSpace(nsIDOMSelection *aSelection, PRBool *aCancel, nsString *outString);
nsresult InsertTab(nsIDOMSelection *aSelection, nsString *outString);
nsresult InsertSpace(nsIDOMSelection *aSelection, nsString *outString);
nsresult ReturnInHeader(nsIDOMSelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset);
nsresult ReturnInParagraph(nsIDOMSelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset, PRBool *aCancel);
nsresult ReturnInParagraph(nsIDOMSelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset, PRBool *aCancel, PRBool *aHandled);
nsresult ReturnInListItem(nsIDOMSelection *aSelection, nsIDOMNode *aHeader, nsIDOMNode *aTextNode, PRInt32 aOffset);
// helper methods

Просмотреть файл

@ -113,6 +113,7 @@ static char hrefText[] = "href";
static char anchorTxt[] = "anchor";
static char namedanchorText[] = "namedanchor";
nsIAtom *nsHTMLEditor::gTypingTxnName;
nsIAtom *nsHTMLEditor::gDeleteTxnName;
#define IsLink(s) (s.EqualsIgnoreCase(hrefText))
@ -211,6 +212,8 @@ nsHTMLEditor::nsHTMLEditor()
// NS_INIT_REFCNT();
if (!gTypingTxnName)
gTypingTxnName = NS_NewAtom("Typing");
if (!gDeleteTxnName)
gDeleteTxnName = NS_NewAtom("Deleting");
}
nsHTMLEditor::~nsHTMLEditor()
@ -559,8 +562,6 @@ NS_IMETHODIMP nsHTMLEditor::EditorKeyPress(nsIDOMUIEvent* aKeyEvent)
PRBool isShift, ctrlKey, altKey, metaKey;
nsresult res;
nsAutoPlaceHolderBatch batch(this, gTypingTxnName);
if (!aKeyEvent) return NS_ERROR_NULL_POINTER;
if (NS_SUCCEEDED(aKeyEvent->GetKeyCode(&keyCode)) &&
@ -584,21 +585,54 @@ NS_IMETHODIMP nsHTMLEditor::EditorKeyPress(nsIDOMUIEvent* aKeyEvent)
}
else if (keyCode == nsIDOMUIEvent::DOM_VK_RETURN)
{
nsAutoString empty;
if (isShift && !(mFlags&eEditorPlaintextBit))
{
nsCOMPtr<nsIDOMNode> brNode;
return InsertBR(&brNode); // only inserts a br node
return TypedText(empty, eTypedBR); // only inserts a br node
}
else
return InsertBreak(); // uses rules to figure out what to insert
{
return TypedText(empty, eTypedBreak); // uses rules to figure out what to insert
}
}
else // normal typing
{
nsAutoString key(character);
return TypedText(key, eTypedText);
}
nsAutoString key(character);
return InsertText(key);
}
return NS_ERROR_FAILURE;
}
/* This routine is needed to provide a bottleneck for typing for logging
purposes. Can't use EditorKeyPress() (above) for that since it takes
a nsIDOMUIEvent* parameter. So instead we pass enough info through
to TypedText() to determine what action to take, but without passing
an event.
*/
NS_IMETHODIMP nsHTMLEditor::TypedText(const nsString& aString, PRInt32 aAction)
{
nsAutoPlaceHolderBatch batch(this, gTypingTxnName);
switch (aAction)
{
case eTypedText:
{
return InsertText(aString);
}
case eTypedBR:
{
nsCOMPtr<nsIDOMNode> brNode;
return InsertBR(&brNode); // only inserts a br node
}
case eTypedBreak:
{
return InsertBreak(); // uses rules to figure out what to insert
}
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsHTMLEditor::TabInTable(PRBool inIsShift, PRBool *outHandled)
{
if (!outHandled) return NS_ERROR_NULL_POINTER;
@ -739,10 +773,11 @@ NS_IMETHODIMP nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty,
result = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(result)) return result;
if (!selection) return NS_ERROR_NULL_POINTER;
PRBool cancel;
PRBool cancel, handled;
nsTextRulesInfo ruleInfo(nsTextEditRules::kSetTextProperty);
result = mRules->WillDoAction(selection, &ruleInfo, &cancel);
if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result)))
result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (NS_FAILED(result)) return result;
if (!cancel && !handled)
{
PRBool isCollapsed;
selection->GetIsCollapsed(&isCollapsed);
@ -836,6 +871,9 @@ NS_IMETHODIMP nsHTMLEditor::SetInlineProperty(nsIAtom *aProperty,
// for setting a compound selection yet.
}
}
}
if (!cancel)
{
// post-process
result = mRules->DidDoAction(selection, &ruleInfo, result);
}
@ -994,11 +1032,11 @@ NS_IMETHODIMP nsHTMLEditor::RemoveInlineProperty(nsIAtom *aProperty, const nsStr
if (NS_FAILED(result)) return result;
if (!selection) return NS_ERROR_NULL_POINTER;
PRBool cancel;
PRBool cancel, handled;
nsTextRulesInfo ruleInfo(nsTextEditRules::kRemoveTextProperty);
result = mRules->WillDoAction(selection, &ruleInfo, &cancel);
result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (NS_FAILED(result)) return result;
if (PR_FALSE==cancel)
if (!cancel && !handled)
{
PRBool isCollapsed;
selection->GetIsCollapsed(&isCollapsed);
@ -1080,6 +1118,9 @@ NS_IMETHODIMP nsHTMLEditor::RemoveInlineProperty(nsIAtom *aProperty, const nsStr
ResetTextSelectionForRange(parentForSelection, rangeStartOffset, rangeEndOffset, selection);
}
}
}
if (!cancel)
{
// post-process
result = mRules->DidDoAction(selection, &ruleInfo, result);
}
@ -1137,14 +1178,10 @@ NS_IMETHODIMP nsHTMLEditor::DeleteSelection(nsIEditor::ESelectionCollapseDirecti
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
nsCOMPtr<nsIDOMSelection> selection;
PRBool cancel= PR_FALSE;
PRBool cancel, handled;
// unnamed placeholder txns dont merge, but they do get sucked
// into placeholders that they are nested in. So this delte wont
// merge with other deletes, but if it happens in the course of
// a typing placehilder context, it will be consumed by that.
// This is the desired behavior.
nsAutoPlaceHolderBatch batch(this, nsnull);
// delete placeholder txns merge.
nsAutoPlaceHolderBatch batch(this, gDeleteTxnName);
// pre-process
nsresult result = GetSelection(getter_AddRefs(selection));
@ -1153,10 +1190,14 @@ NS_IMETHODIMP nsHTMLEditor::DeleteSelection(nsIEditor::ESelectionCollapseDirecti
nsTextRulesInfo ruleInfo(nsTextEditRules::kDeleteSelection);
ruleInfo.collapsedAction = aAction;
result = mRules->WillDoAction(selection, &ruleInfo, &cancel);
if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result)))
result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (NS_FAILED(result)) return result;
if (!cancel && !handled)
{
result = DeleteSelectionImpl(aAction);
}
if (!cancel)
{
// post-process
result = mRules->DidDoAction(selection, &ruleInfo, result);
}
@ -1169,30 +1210,32 @@ NS_IMETHODIMP nsHTMLEditor::InsertText(const nsString& aStringToInsert)
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
nsCOMPtr<nsIDOMSelection> selection;
PRBool cancel= PR_FALSE;
PRBool cancel, handled;
nsAutoPlaceHolderBatch batch(this, nsnull);
// pre-process
nsresult result = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(result)) return result;
if (!selection) return NS_ERROR_NULL_POINTER;
nsAutoString resultString;
PlaceholderTxn *placeholderTxn=nsnull;
nsTextRulesInfo ruleInfo(nsTextEditRules::kInsertText);
// ruleInfo.placeTxn = &placeholderTxn;
ruleInfo.inString = &aStringToInsert;
ruleInfo.outString = &resultString;
ruleInfo.typeInState = *mTypeInState;
ruleInfo.maxLength = mMaxTextLength;
result = mRules->WillDoAction(selection, &ruleInfo, &cancel);
if ((PR_FALSE==cancel) && (NS_SUCCEEDED(result)))
result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (NS_FAILED(result)) return result;
if (!cancel && !handled)
{
result = InsertTextImpl(resultString);
}
if (!cancel)
{
// post-process
result = mRules->DidDoAction(selection, &ruleInfo, result);
}
// if (placeholderTxn)
// placeholderTxn->SetAbsorb(PR_FALSE); // this ends the merging of txns into placeholderTxn
return result;
}
@ -1290,7 +1333,7 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak()
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
nsCOMPtr<nsIDOMSelection> selection;
PRBool cancel= PR_FALSE;
PRBool cancel, handled;
// pre-process
res = GetSelection(getter_AddRefs(selection));
@ -1298,8 +1341,9 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak()
if (!selection) return NS_ERROR_NULL_POINTER;
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kInsertBreak);
res = mRules->WillDoAction(selection, &ruleInfo, &cancel);
if ((PR_FALSE==cancel) && (NS_SUCCEEDED(res)))
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (NS_FAILED(res)) return res;
if (!cancel && !handled)
{
// create the new BR node
nsCOMPtr<nsIDOMNode> newNode;
@ -1350,6 +1394,9 @@ NS_IMETHODIMP nsHTMLEditor::InsertBreak()
}
}
}
}
if (!cancel)
{
// post-process, always called if WillInsertBreak didn't return cancel==PR_TRUE
res = mRules->DidDoAction(selection, &ruleInfo, res);
}
@ -1374,106 +1421,110 @@ nsHTMLEditor::InsertElement(nsIDOMElement* aElement, PRBool aDeleteSelection)
return NS_ERROR_FAILURE;
// hand off to the rules system, see if it has anything to say about this
PRBool cancel;
PRBool cancel, handled;
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kInsertElement);
ruleInfo.insertElement = aElement;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel);
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (cancel || (NS_FAILED(res))) return res;
if (aDeleteSelection)
if (!handled)
{
nsCOMPtr<nsIDOMNode> tempNode;
PRInt32 tempOffset;
nsresult result = DeleteSelectionAndPrepareToCreateNode(tempNode,tempOffset);
if (!NS_SUCCEEDED(result))
return result;
}
// If deleting, selection will be collapsed.
// so if not, we collapse it
if (!aDeleteSelection)
{
// Named Anchor is a special case,
// We collapse to insert element BEFORE the selection
// For all other tags, we insert AFTER the selection
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
if (IsNamedAnchorNode(node))
if (aDeleteSelection)
{
selection->CollapseToStart();
} else {
selection->CollapseToEnd();
nsCOMPtr<nsIDOMNode> tempNode;
PRInt32 tempOffset;
nsresult result = DeleteSelectionAndPrepareToCreateNode(tempNode,tempOffset);
if (!NS_SUCCEEDED(result))
return result;
}
}
nsCOMPtr<nsIDOMNode> parentSelectedNode;
PRInt32 offsetForInsert;
res = selection->GetAnchorNode(getter_AddRefs(parentSelectedNode));
// XXX: ERROR_HANDLING bad XPCOM usage
if (NS_SUCCEEDED(res) && NS_SUCCEEDED(selection->GetAnchorOffset(&offsetForInsert)) && parentSelectedNode)
{
// If deleting, selection will be collapsed.
// so if not, we collapse it
if (!aDeleteSelection)
{
// Named Anchor is a special case,
// We collapse to insert element BEFORE the selection
// For all other tags, we insert AFTER the selection
nsCOMPtr<nsIDOMNode> node = do_QueryInterface(aElement);
if (IsNamedAnchorNode(node))
{
selection->CollapseToStart();
} else {
selection->CollapseToEnd();
}
}
nsCOMPtr<nsIDOMNode> parentSelectedNode;
PRInt32 offsetForInsert;
res = selection->GetAnchorNode(getter_AddRefs(parentSelectedNode));
// XXX: ERROR_HANDLING bad XPCOM usage
if (NS_SUCCEEDED(res) && NS_SUCCEEDED(selection->GetAnchorOffset(&offsetForInsert)) && parentSelectedNode)
{
#ifdef DEBUG_cmanske
{
nsAutoString name;
parentSelectedNode->GetNodeName(name);
printf("InsertElement: Anchor node of selection: ");
wprintf(name.GetUnicode());
printf(" Offset: %d\n", offsetForInsert);
}
{
nsAutoString name;
parentSelectedNode->GetNodeName(name);
printf("InsertElement: Anchor node of selection: ");
wprintf(name.GetUnicode());
printf(" Offset: %d\n", offsetForInsert);
}
#endif
nsAutoString tagName;
aElement->GetNodeName(tagName);
tagName.ToLowerCase();
nsCOMPtr<nsIDOMNode> parent = parentSelectedNode;
nsCOMPtr<nsIDOMNode> topChild = parentSelectedNode;
nsCOMPtr<nsIDOMNode> tmp;
nsAutoString parentTagName;
PRBool isRoot;
nsAutoString tagName;
aElement->GetNodeName(tagName);
tagName.ToLowerCase();
nsCOMPtr<nsIDOMNode> parent = parentSelectedNode;
nsCOMPtr<nsIDOMNode> topChild = parentSelectedNode;
nsCOMPtr<nsIDOMNode> tmp;
nsAutoString parentTagName;
PRBool isRoot;
// Search up the parent chain to find a suitable container
while (!CanContainTag(parent, tagName))
{
// If the current parent is a root (body or table cell)
// then go no further - we can't insert
parent->GetNodeName(parentTagName);
res = IsRootTag(parentTagName, isRoot);
if (!NS_SUCCEEDED(res) || isRoot)
return NS_ERROR_FAILURE;
// Get the next parent
parent->GetParentNode(getter_AddRefs(tmp));
if (!tmp)
return NS_ERROR_FAILURE;
topChild = parent;
parent = tmp;
}
// Search up the parent chain to find a suitable container
while (!CanContainTag(parent, tagName))
{
// If the current parent is a root (body or table cell)
// then go no further - we can't insert
parent->GetNodeName(parentTagName);
res = IsRootTag(parentTagName, isRoot);
if (!NS_SUCCEEDED(res) || isRoot)
return NS_ERROR_FAILURE;
// Get the next parent
parent->GetParentNode(getter_AddRefs(tmp));
if (!tmp)
return NS_ERROR_FAILURE;
topChild = parent;
parent = tmp;
}
#ifdef DEBUG_cmanske
{
nsAutoString name;
parent->GetNodeName(name);
printf("Parent node to insert under: ");
wprintf(name.GetUnicode());
printf("\n");
topChild->GetNodeName(name);
printf("TopChild to split: ");
wprintf(name.GetUnicode());
printf("\n");
}
{
nsAutoString name;
parent->GetNodeName(name);
printf("Parent node to insert under: ");
wprintf(name.GetUnicode());
printf("\n");
topChild->GetNodeName(name);
printf("TopChild to split: ");
wprintf(name.GetUnicode());
printf("\n");
}
#endif
if (parent != topChild)
{
// we need to split some levels above the original selection parent
res = SplitNodeDeep(topChild, parentSelectedNode, offsetForInsert, &offsetForInsert);
if (NS_FAILED(res))
return res;
if (parent != topChild)
{
// we need to split some levels above the original selection parent
res = SplitNodeDeep(topChild, parentSelectedNode, offsetForInsert, &offsetForInsert);
if (NS_FAILED(res))
return res;
}
// Now we can insert the new node
res = InsertNode(aElement, parent, offsetForInsert);
// Set caret after element, but check for special case
// of inserting table-related elements: set in first cell instead
if (!SetCaretInTableCell(aElement))
res = SetCaretAfterElement(aElement);
}
// Now we can insert the new node
res = InsertNode(aElement, parent, offsetForInsert);
// Set caret after element, but check for special case
// of inserting table-related elements: set in first cell instead
if (!SetCaretInTableCell(aElement))
res = SetCaretAfterElement(aElement);
}
res = mRules->DidDoAction(selection, &ruleInfo, res);
return res;
}
@ -1848,7 +1899,7 @@ nsHTMLEditor::InsertList(const nsString& aListType)
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
nsCOMPtr<nsIDOMSelection> selection;
PRBool cancel= PR_FALSE;
PRBool cancel, handled;
nsAutoEditBatch beginBatching(this);
@ -1860,222 +1911,31 @@ nsHTMLEditor::InsertList(const nsString& aListType)
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kMakeList);
if (aListType == "ol") ruleInfo.bOrdered = PR_TRUE;
else ruleInfo.bOrdered = PR_FALSE;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel);
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (cancel || (NS_FAILED(res))) return res;
// Find out if the selection is collapsed:
PRBool isCollapsed;
res = selection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMNode> node;
PRInt32 offset;
res = GetStartNodeAndOffset(selection, &node, &offset);
if (!node) res = NS_ERROR_FAILURE;
if (NS_FAILED(res)) return res;
if (isCollapsed)
if (!handled)
{
// 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));
if (!tmp) return NS_ERROR_FAILURE;
topChild = parent;
parent = tmp;
}
if (parent != node)
{
// we need to split up to the child of parent
res = SplitNodeDeep(topChild, node, offset, &offset);
if (NS_FAILED(res)) return res;
}
// Find out if the selection is collapsed:
PRBool isCollapsed;
res = selection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(res)) return res;
// make a list
nsCOMPtr<nsIDOMNode> newList;
res = CreateNode(aListType, parent, offset, getter_AddRefs(newList));
if (NS_FAILED(res)) return res;
// make a list item
nsAutoString tag("li");
nsCOMPtr<nsIDOMNode> newItem;
res = CreateNode(tag, newList, 0, getter_AddRefs(newItem));
if (NS_FAILED(res)) return res;
// put a space in it so layout will draw the list item
// XXX - revisit when layout is fixed
res = selection->Collapse(newItem,0);
if (NS_FAILED(res)) return res;
#if 0
nsAutoString theText(" ");
res = InsertText(theText);
if (NS_FAILED(res)) return res;
// reposition selection to before the space character
nsCOMPtr<nsIDOMNode> node;
PRInt32 offset;
res = GetStartNodeAndOffset(selection, &node, &offset);
if (!node) res = NS_ERROR_FAILURE;
if (NS_FAILED(res)) return res;
res = selection->Collapse(node,0);
if (NS_FAILED(res)) return res;
#endif
}
return res;
}
NS_IMETHODIMP
nsHTMLEditor::RemoveList(const nsString& aListType)
{
nsresult res;
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
nsCOMPtr<nsIDOMSelection> selection;
PRBool cancel= PR_FALSE;
nsAutoEditBatch beginBatching(this);
// pre-process
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_NULL_POINTER;
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kRemoveList);
if (aListType == "ol") ruleInfo.bOrdered = PR_TRUE;
else ruleInfo.bOrdered = PR_FALSE;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel);
if (cancel || (NS_FAILED(res))) return res;
// no default behavior for this yet. what would it mean?
return res;
}
NS_IMETHODIMP
nsHTMLEditor::InsertBasicBlock(const nsString& aBlockType)
{
nsresult res;
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
nsCOMPtr<nsIDOMSelection> selection;
PRBool cancel= PR_FALSE;
nsAutoEditBatch beginBatching(this);
// pre-process
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_NULL_POINTER;
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kMakeBasicBlock);
ruleInfo.blockType = &aBlockType;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel);
if (cancel || (NS_FAILED(res))) return res;
// Find out if the selection is collapsed:
PRBool isCollapsed;
res = selection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMNode> node;
PRInt32 offset;
res = GetStartNodeAndOffset(selection, &node, &offset);
if (!node) res = NS_ERROR_FAILURE;
if (NS_FAILED(res)) return res;
if (isCollapsed)
{
// have to find a place to put the block
nsCOMPtr<nsIDOMNode> parent = node;
nsCOMPtr<nsIDOMNode> topChild = node;
nsCOMPtr<nsIDOMNode> tmp;
while ( !CanContainTag(parent, aBlockType))
{
parent->GetParentNode(getter_AddRefs(tmp));
if (!tmp) return NS_ERROR_FAILURE;
topChild = parent;
parent = tmp;
}
if (parent != node)
{
// we need to split up to the child of parent
res = SplitNodeDeep(topChild, node, offset, &offset);
if (NS_FAILED(res)) return res;
}
// make a block
nsCOMPtr<nsIDOMNode> newBlock;
res = CreateNode(aBlockType, parent, offset, getter_AddRefs(newBlock));
if (NS_FAILED(res)) return res;
// xxx
// put a space in it so layout will draw it
res = selection->Collapse(newBlock,0);
if (NS_FAILED(res)) return res;
nsAutoString theText(nbsp);
res = InsertText(theText);
if (NS_FAILED(res)) return res;
// reposition selection to before the space character
res = GetStartNodeAndOffset(selection, &node, &offset);
if (NS_FAILED(res)) return res;
res = selection->Collapse(node,0);
if (NS_FAILED(res)) return res;
}
return res;
}
// TODO: Implement "outdent"
NS_IMETHODIMP
nsHTMLEditor::Indent(const nsString& aIndent)
{
nsresult res;
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
PRBool cancel= PR_FALSE;
nsAutoEditBatch beginBatching(this);
// pre-process
nsCOMPtr<nsIDOMSelection> selection;
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_NULL_POINTER;
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;
PRBool isCollapsed;
res = selection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(res)) return res;
res = GetStartNodeAndOffset(selection, &node, &offset);
if (!node) res = NS_ERROR_FAILURE;
if (NS_FAILED(res)) return res;
nsAutoString inward("indent");
if (aIndent == inward)
{
if (isCollapsed)
{
// have to find a place to put the blockquote
// have to find a place to put the list
nsCOMPtr<nsIDOMNode> parent = node;
nsCOMPtr<nsIDOMNode> topChild = node;
nsCOMPtr<nsIDOMNode> tmp;
nsAutoString bq("blockquote");
while ( !CanContainTag(parent, bq))
while ( !CanContainTag(parent, aListType))
{
parent->GetParentNode(getter_AddRefs(tmp));
if (!tmp) return NS_ERROR_FAILURE;
@ -2090,13 +1950,20 @@ nsHTMLEditor::Indent(const nsString& aIndent)
if (NS_FAILED(res)) return res;
}
// make a blockquote
nsCOMPtr<nsIDOMNode> newBQ;
res = CreateNode(bq, parent, offset, getter_AddRefs(newBQ));
// make a list
nsCOMPtr<nsIDOMNode> newList;
res = CreateNode(aListType, parent, offset, getter_AddRefs(newList));
if (NS_FAILED(res)) return res;
// make a list item
nsAutoString tag("li");
nsCOMPtr<nsIDOMNode> newItem;
res = CreateNode(tag, newList, 0, getter_AddRefs(newItem));
if (NS_FAILED(res)) return res;
// put a space in it so layout will draw the list item
res = selection->Collapse(newBQ,0);
// XXX - revisit when layout is fixed
res = selection->Collapse(newItem,0);
if (NS_FAILED(res)) return res;
#if 0
nsAutoString theText(" ");
res = InsertText(theText);
if (NS_FAILED(res)) return res;
@ -2105,9 +1972,205 @@ nsHTMLEditor::Indent(const nsString& aIndent)
if (NS_FAILED(res)) return res;
res = selection->Collapse(node,0);
if (NS_FAILED(res)) return res;
#endif
}
}
res = mRules->DidDoAction(selection, &ruleInfo, res);
return res;
}
NS_IMETHODIMP
nsHTMLEditor::RemoveList(const nsString& aListType)
{
nsresult res;
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
nsCOMPtr<nsIDOMSelection> selection;
PRBool cancel, handled;
nsAutoEditBatch beginBatching(this);
// pre-process
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_NULL_POINTER;
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kRemoveList);
if (aListType == "ol") ruleInfo.bOrdered = PR_TRUE;
else ruleInfo.bOrdered = PR_FALSE;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (cancel || (NS_FAILED(res))) return res;
// no default behavior for this yet. what would it mean?
res = mRules->DidDoAction(selection, &ruleInfo, res);
return res;
}
NS_IMETHODIMP
nsHTMLEditor::InsertBasicBlock(const nsString& aBlockType)
{
nsresult res;
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
nsCOMPtr<nsIDOMSelection> selection;
PRBool cancel, handled;
nsAutoEditBatch beginBatching(this);
// pre-process
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_NULL_POINTER;
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kMakeBasicBlock);
ruleInfo.blockType = &aBlockType;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (cancel || (NS_FAILED(res))) return res;
if (!handled)
{
// Find out if the selection is collapsed:
PRBool isCollapsed;
res = selection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMNode> node;
PRInt32 offset;
res = GetStartNodeAndOffset(selection, &node, &offset);
if (!node) res = NS_ERROR_FAILURE;
if (NS_FAILED(res)) return res;
if (isCollapsed)
{
// have to find a place to put the block
nsCOMPtr<nsIDOMNode> parent = node;
nsCOMPtr<nsIDOMNode> topChild = node;
nsCOMPtr<nsIDOMNode> tmp;
while ( !CanContainTag(parent, aBlockType))
{
parent->GetParentNode(getter_AddRefs(tmp));
if (!tmp) return NS_ERROR_FAILURE;
topChild = parent;
parent = tmp;
}
if (parent != node)
{
// we need to split up to the child of parent
res = SplitNodeDeep(topChild, node, offset, &offset);
if (NS_FAILED(res)) return res;
}
// make a block
nsCOMPtr<nsIDOMNode> newBlock;
res = CreateNode(aBlockType, parent, offset, getter_AddRefs(newBlock));
if (NS_FAILED(res)) return res;
// xxx
// put a space in it so layout will draw it
res = selection->Collapse(newBlock,0);
if (NS_FAILED(res)) return res;
nsAutoString theText(nbsp);
res = InsertText(theText);
if (NS_FAILED(res)) return res;
// reposition selection to before the space character
res = GetStartNodeAndOffset(selection, &node, &offset);
if (NS_FAILED(res)) return res;
res = selection->Collapse(node,0);
if (NS_FAILED(res)) return res;
}
}
res = mRules->DidDoAction(selection, &ruleInfo, res);
return res;
}
// TODO: Implement "outdent"
NS_IMETHODIMP
nsHTMLEditor::Indent(const nsString& aIndent)
{
nsresult res;
if (!mRules) { return NS_ERROR_NOT_INITIALIZED; }
PRBool cancel, handled;
nsAutoEditBatch beginBatching(this);
// pre-process
nsCOMPtr<nsIDOMSelection> selection;
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_NULL_POINTER;
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kIndent);
if (aIndent == "outdent")
ruleInfo.action = nsHTMLEditRules::kOutdent;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (cancel || (NS_FAILED(res))) return res;
if (!handled)
{
// Do default - insert a blockquote node if selection collapsed
nsCOMPtr<nsIDOMNode> node;
PRInt32 offset;
PRBool isCollapsed;
res = selection->GetIsCollapsed(&isCollapsed);
if (NS_FAILED(res)) return res;
res = GetStartNodeAndOffset(selection, &node, &offset);
if (!node) res = NS_ERROR_FAILURE;
if (NS_FAILED(res)) return res;
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));
if (!tmp) return NS_ERROR_FAILURE;
topChild = parent;
parent = tmp;
}
if (parent != node)
{
// we need to split up to the child of parent
res = SplitNodeDeep(topChild, node, offset, &offset);
if (NS_FAILED(res)) return res;
}
// make a blockquote
nsCOMPtr<nsIDOMNode> newBQ;
res = CreateNode(bq, parent, offset, getter_AddRefs(newBQ));
if (NS_FAILED(res)) return res;
// put a space in it so layout will draw the list item
res = selection->Collapse(newBQ,0);
if (NS_FAILED(res)) return res;
nsAutoString theText(" ");
res = InsertText(theText);
if (NS_FAILED(res)) return res;
// reposition selection to before the space character
res = GetStartNodeAndOffset(selection, &node, &offset);
if (NS_FAILED(res)) return res;
res = selection->Collapse(node,0);
if (NS_FAILED(res)) return res;
}
}
}
res = mRules->DidDoAction(selection, &ruleInfo, res);
return res;
}
@ -2118,7 +2181,7 @@ nsHTMLEditor::Align(const nsString& aAlignType)
{
nsAutoEditBatch beginBatching(this);
nsCOMPtr<nsIDOMNode> node;
PRBool cancel= PR_FALSE;
PRBool cancel, handled;
// Find out if the selection is collapsed:
nsCOMPtr<nsIDOMSelection> selection;
@ -2127,8 +2190,11 @@ nsHTMLEditor::Align(const nsString& aAlignType)
if (!selection) return NS_ERROR_NULL_POINTER;
nsTextRulesInfo ruleInfo(nsHTMLEditRules::kAlign);
ruleInfo.alignType = &aAlignType;
res = mRules->WillDoAction(selection, &ruleInfo, &cancel);
res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (cancel || NS_FAILED(res))
return res;
res = mRules->DidDoAction(selection, &ruleInfo, res);
return res;
}
@ -3284,8 +3350,8 @@ nsHTMLEditor::Undo(PRUint32 aCount)
nsTextRulesInfo ruleInfo(nsTextEditRules::kUndo);
nsCOMPtr<nsIDOMSelection> selection;
GetSelection(getter_AddRefs(selection));
PRBool cancel;
result = mRules->WillDoAction(selection, &ruleInfo, &cancel);
PRBool cancel, handled;
result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (!cancel && NS_SUCCEEDED(result))
{
@ -3309,8 +3375,8 @@ nsHTMLEditor::Redo(PRUint32 aCount)
nsTextRulesInfo ruleInfo(nsTextEditRules::kRedo);
nsCOMPtr<nsIDOMSelection> selection;
GetSelection(getter_AddRefs(selection));
PRBool cancel;
result = mRules->WillDoAction(selection, &ruleInfo, &cancel);
PRBool cancel, handled;
result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (!cancel && NS_SUCCEEDED(result))
{
@ -3441,14 +3507,14 @@ NS_IMETHODIMP nsHTMLEditor::OutputToString(nsString& aOutputString,
const nsString& aFormatType,
PRUint32 aFlags)
{
PRBool cancel;
PRBool cancel, handled;
nsString resultString;
nsTextRulesInfo ruleInfo(nsTextEditRules::kOutputText);
ruleInfo.outString = &resultString;
ruleInfo.outputFormat = &aFormatType;
nsresult rv = mRules->WillDoAction(nsnull, &ruleInfo, &cancel);
if (NS_FAILED(rv)) { return rv; }
if (PR_TRUE==cancel)
nsresult rv = mRules->WillDoAction(nsnull, &ruleInfo, &cancel, &handled);
if (cancel || NS_FAILED(rv)) { return rv; }
if (handled)
{ // this case will get triggered by password fields
aOutputString = *(ruleInfo.outString);
}
@ -3680,10 +3746,10 @@ nsHTMLEditor::SetCompositionString(const nsString& aCompositionString, nsIPrivat
nsresult result = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(result)) return result;
nsTextRulesInfo ruleInfo(nsTextEditRules::kInsertTextIME);
PRBool cancel;
result = mRules->WillDoAction(selection, &ruleInfo, &cancel);
if (NS_FAILED(result)) return result;
// we don't care if WillInsert said to cancel...
PRBool cancel, handled;
result = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
if (cancel || NS_FAILED(result)) return result;
result = SetInputMethodText(aCompositionString,aTextRangeList);
if (NS_FAILED(result)) return result;
mIMEBufferLength = aCompositionString.Length();
@ -3694,6 +3760,7 @@ nsHTMLEditor::SetCompositionString(const nsString& aCompositionString, nsIPrivat
ps->GetCaret(getter_AddRefs(caretP));
caretP->GetWindowRelativeCoordinates(aReply->mCursorPosition,aReply->mCursorIsCollapsed);
result = mRules->DidDoAction(selection, &ruleInfo, result);
return result;
}

Просмотреть файл

@ -62,6 +62,7 @@ public:
/* ------------ nsIHTMLEditor methods -------------- */
NS_IMETHOD EditorKeyPress(nsIDOMUIEvent* aKeyEvent);
NS_IMETHOD TypedText(const nsString& aString, PRInt32 aAction);
NS_IMETHOD GetDocumentIsEmpty(PRBool *aDocumentIsEmpty);
NS_IMETHOD GetDocumentLength(PRInt32 *aCount);
@ -482,6 +483,7 @@ protected:
public:
static nsIAtom *gTypingTxnName;
static nsIAtom *gDeleteTxnName;
// friends
friend class nsHTMLEditRules;

Просмотреть файл

@ -155,6 +155,27 @@ nsHTMLEditorLog::DeleteSelection(nsIEditor::ESelectionCollapseDirection aAction)
return nsHTMLEditor::DeleteSelection(aAction);
}
NS_IMETHODIMP
nsHTMLEditorLog::TypedText(const nsString& aStringToInsert, PRInt32 aAction)
{
nsAutoHTMLEditorLogLock logLock(this);
if (!mLocked && mFileSpec)
{
PrintSelection();
Write("window.editorShell.TypedText(\"");
PrintUnicode(aStringToInsert);
Write("\", ");
WriteInt("%d", aAction);
Write(");\n");
Flush();
}
return nsHTMLEditor::TypedText(aStringToInsert, aAction);
}
NS_IMETHODIMP
nsHTMLEditorLog::InsertText(const nsString& aStringToInsert)
{

Просмотреть файл

@ -54,6 +54,7 @@ public:
NS_IMETHOD SetParagraphFormat(const nsString& aParagraphFormat);
NS_IMETHOD RemoveInlineProperty(nsIAtom *aProperty, const nsString *aAttribute);
NS_IMETHOD DeleteSelection(nsIEditor::ESelectionCollapseDirection aAction);
NS_IMETHOD TypedText(const nsString& aString, PRInt32 aAction);
NS_IMETHOD InsertText(const nsString& aStringToInsert);
NS_IMETHOD InsertBreak();
NS_IMETHOD Undo(PRUint32 aCount);

Просмотреть файл

@ -121,12 +121,15 @@ nsTextEditRules::SetFlags(PRUint32 aFlags)
NS_IMETHODIMP
nsTextEditRules::WillDoAction(nsIDOMSelection *aSelection,
nsRulesInfo *aInfo, PRBool *aCancel)
nsRulesInfo *aInfo,
PRBool *aCancel,
PRBool *aHandled)
{
// null selection is legal
if (!aInfo || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aInfo || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
// my kingdom for dynamic cast
nsTextRulesInfo *info = NS_STATIC_CAST(nsTextRulesInfo*, aInfo);
@ -134,10 +137,11 @@ nsTextEditRules::WillDoAction(nsIDOMSelection *aSelection,
switch (info->action)
{
case kInsertBreak:
return WillInsertBreak(aSelection, aCancel);
return WillInsertBreak(aSelection, aCancel, aHandled);
case kInsertText:
return WillInsertText(aSelection,
aCancel,
aCancel,
aHandled,
info->inString,
info->outString,
info->typeInState,
@ -145,20 +149,21 @@ nsTextEditRules::WillDoAction(nsIDOMSelection *aSelection,
case kInsertTextIME:
return WillInsert(aSelection, aCancel);
case kDeleteSelection:
return WillDeleteSelection(aSelection, info->collapsedAction, aCancel);
return WillDeleteSelection(aSelection, info->collapsedAction, aCancel, aHandled);
case kUndo:
return WillUndo(aSelection, aCancel);
return WillUndo(aSelection, aCancel, aHandled);
case kRedo:
return WillRedo(aSelection, aCancel);
return WillRedo(aSelection, aCancel, aHandled);
case kSetTextProperty:
return WillSetTextProperty(aSelection, aCancel);
return WillSetTextProperty(aSelection, aCancel, aHandled);
case kRemoveTextProperty:
return WillRemoveTextProperty(aSelection, aCancel);
return WillRemoveTextProperty(aSelection, aCancel, aHandled);
case kOutputText:
return WillOutputText(aSelection,
info->outputFormat,
info->outString,
aCancel);
aCancel,
aHandled);
}
return NS_ERROR_FAILURE;
}
@ -239,10 +244,11 @@ nsTextEditRules::DidInsert(nsIDOMSelection *aSelection, nsresult aResult)
}
nsresult
nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel)
nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
CANCEL_OPERATION_IF_READONLY_OR_DISABLED
*aHandled = PR_FALSE;
if (mFlags & nsIHTMLEditor::eEditorSingleLineMask) {
*aCancel = PR_TRUE;
}
@ -261,19 +267,22 @@ nsTextEditRules::DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult)
nsresult
nsTextEditRules::WillInsertText(nsIDOMSelection *aSelection,
PRBool *aCancel,
PRBool *aCancel,
PRBool *aHandled,
const nsString *aInString,
nsString *aOutString,
TypeInState aTypeInState,
PRInt32 aMaxLength)
{
if (!aSelection || !aCancel || !aInString || !aOutString) {return NS_ERROR_NULL_POINTER;}
if (!aSelection || !aCancel || !aHandled || !aInString || !aOutString)
{return NS_ERROR_NULL_POINTER;}
CANCEL_OPERATION_IF_READONLY_OR_DISABLED
nsresult res;
// initialize out params
*aCancel = PR_TRUE;
*aCancel = PR_FALSE;
*aHandled = PR_TRUE;
*aOutString = *aInString;
// handle docs with a max length
@ -576,8 +585,10 @@ nsTextEditRules::InsertStyleAndNewTextNode(nsIDOMNode *aParentNode, nsIAtom *aTa
}
nsresult
nsTextEditRules::WillSetTextProperty(nsIDOMSelection *aSelection, PRBool *aCancel)
nsTextEditRules::WillSetTextProperty(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled)
{
if (!aSelection || !aCancel || !aHandled)
{ return NS_ERROR_NULL_POINTER; }
nsresult res = NS_OK;
// XXX: should probably return a success value other than NS_OK that means "not allowed"
@ -594,8 +605,10 @@ nsTextEditRules::DidSetTextProperty(nsIDOMSelection *aSelection, nsresult aResul
}
nsresult
nsTextEditRules::WillRemoveTextProperty(nsIDOMSelection *aSelection, PRBool *aCancel)
nsTextEditRules::WillRemoveTextProperty(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled)
{
if (!aSelection || !aCancel || !aHandled)
{ return NS_ERROR_NULL_POINTER; }
nsresult res = NS_OK;
// XXX: should probably return a success value other than NS_OK that means "not allowed"
@ -614,13 +627,15 @@ nsTextEditRules::DidRemoveTextProperty(nsIDOMSelection *aSelection, nsresult aRe
nsresult
nsTextEditRules::WillDeleteSelection(nsIDOMSelection *aSelection,
nsIEditor::ESelectionCollapseDirection aCollapsedAction,
PRBool *aCancel)
PRBool *aCancel,
PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
CANCEL_OPERATION_IF_READONLY_OR_DISABLED
// initialize out param
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
// if there is only bogus content, cancel the operation
if (mBogusNode) {
@ -745,12 +760,13 @@ nsTextEditRules::DidDeleteSelection(nsIDOMSelection *aSelection,
}
nsresult
nsTextEditRules::WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel)
nsTextEditRules::WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
CANCEL_OPERATION_IF_READONLY_OR_DISABLED
// initialize out param
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
return NS_OK;
}
@ -808,12 +824,13 @@ nsTextEditRules:: DidUndo(nsIDOMSelection *aSelection, nsresult aResult)
}
nsresult
nsTextEditRules::WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel)
nsTextEditRules::WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled)
{
if (!aSelection || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
CANCEL_OPERATION_IF_READONLY_OR_DISABLED
// initialize out param
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
return NS_OK;
}
@ -869,25 +886,28 @@ nsresult
nsTextEditRules::WillOutputText(nsIDOMSelection *aSelection,
const nsString *aOutputFormat,
nsString *aOutString,
PRBool *aCancel)
PRBool *aCancel,
PRBool *aHandled)
{
// null selection ok
if (!aOutString || !aOutputFormat || !aCancel) { return NS_ERROR_NULL_POINTER; }
if (!aOutString || !aOutputFormat || !aCancel || !aHandled)
{ return NS_ERROR_NULL_POINTER; }
// initialize out param
*aCancel = PR_FALSE;
*aHandled = PR_FALSE;
if (PR_TRUE == aOutputFormat->Equals("text/plain"))
{ // only use these rules for plain text output
if (mFlags & nsIHTMLEditor::eEditorPasswordMask)
{
*aOutString = mPasswordText;
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
}
else if (mBogusNode)
{ // this means there's no content, so output null string
*aOutString = "";
*aCancel = PR_TRUE;
*aHandled = PR_TRUE;
}
}
return NS_OK;

Просмотреть файл

@ -49,7 +49,7 @@ public:
// nsEditRules methods
NS_IMETHOD Init(nsHTMLEditor *aEditor, PRUint32 aFlags);
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel);
NS_IMETHOD WillDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, PRBool *aCancel, PRBool *aHandled);
NS_IMETHOD DidDoAction(nsIDOMSelection *aSelection, nsRulesInfo *aInfo, nsresult aResult);
NS_IMETHOD GetFlags(PRUint32 *aFlags);
NS_IMETHOD SetFlags(PRUint32 aFlags);
@ -85,6 +85,7 @@ protected:
// nsTextEditRules implementation methods
nsresult WillInsertText(nsIDOMSelection *aSelection,
PRBool *aCancel,
PRBool *aHandled,
const nsString *inString,
nsString *outString,
TypeInState typeInState,
@ -92,7 +93,7 @@ protected:
nsresult DidInsertText(nsIDOMSelection *aSelection, nsresult aResult);
nsresult CreateStyleForInsertText(nsIDOMSelection *aSelection, TypeInState &aTypeInState);
nsresult WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel);
nsresult WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult DidInsertBreak(nsIDOMSelection *aSelection, nsresult aResult);
nsresult WillInsert(nsIDOMSelection *aSelection, PRBool *aCancel);
@ -100,21 +101,22 @@ protected:
nsresult WillDeleteSelection(nsIDOMSelection *aSelection,
nsIEditor::ESelectionCollapseDirection aCollapsedAction,
PRBool *aCancel);
PRBool *aCancel,
PRBool *aHandled);
nsresult DidDeleteSelection(nsIDOMSelection *aSelection,
nsIEditor::ESelectionCollapseDirection aCollapsedAction,
nsresult aResult);
nsresult WillSetTextProperty(nsIDOMSelection *aSelection, PRBool *aCancel);
nsresult WillSetTextProperty(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult DidSetTextProperty(nsIDOMSelection *aSelection, nsresult aResult);
nsresult WillRemoveTextProperty(nsIDOMSelection *aSelection, PRBool *aCancel);
nsresult WillRemoveTextProperty(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult DidRemoveTextProperty(nsIDOMSelection *aSelection, nsresult aResult);
nsresult WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel);
nsresult WillUndo(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult DidUndo(nsIDOMSelection *aSelection, nsresult aResult);
nsresult WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel);
nsresult WillRedo(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled);
nsresult DidRedo(nsIDOMSelection *aSelection, nsresult aResult);
/** called prior to nsIEditor::OutputToString
@ -127,7 +129,8 @@ protected:
nsresult WillOutputText(nsIDOMSelection *aSelection,
const nsString *aInFormat,
nsString *aOutText,
PRBool *aOutCancel);
PRBool *aOutCancel,
PRBool *aHandled);
nsresult DidOutputText(nsIDOMSelection *aSelection, nsresult aResult);

Просмотреть файл

@ -65,6 +65,12 @@ public:
eEditorMailMask = (1 << eEditorMailBit)
};
// below used by TypedText()
enum {
eTypedText, // user typed text
eTypedBR, // user typed shift-enter to get a br
eTypedBreak // user typed enter
};
/* ------------ Document info methods -------------- */
@ -148,6 +154,12 @@ public:
*/
NS_IMETHOD EditorKeyPress(nsIDOMUIEvent* aKeyEvent)=0;
/**
* TypedText responds to user typing. Provides a logging bottleneck for typing.
* @param aString string to type
* @param aAction action to take: insert text, insert BR, insert break
*/
NS_IMETHOD TypedText(const nsString& aString, PRInt32 aAction)=0;
/**
* Insert a break into the content model.<br>