зеркало из https://github.com/mozilla/gecko-dev.git
fixed bug 20613 & 21121: both invloved newlines in preformatted text. Layout gives no frames for blanklines caused by newlines, so you cant click or arrow to them. I replace such newlines with breaks now.
This commit is contained in:
Родитель
6222e5412c
Коммит
a5fc421d20
|
@ -98,12 +98,17 @@ nsHTMLEditRules::Init(nsHTMLEditor *aEditor, PRUint32 aFlags)
|
|||
bodyNode = do_QueryInterface(bodyElem);
|
||||
if (bodyNode)
|
||||
{
|
||||
// temporarily turn off rules sniffing
|
||||
nsAutoLockRulesSniffing lockIt((nsTextEditRules*)this);
|
||||
res = nsComponentManager::CreateInstance(kRangeCID, nsnull, NS_GET_IID(nsIDOMRange),
|
||||
getter_AddRefs(mDocChangeRange));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!mDocChangeRange) return NS_ERROR_NULL_POINTER;
|
||||
mDocChangeRange->SelectNode(bodyNode);
|
||||
AdjustSpecialBreaks();
|
||||
res = ReplaceNewlines(mDocChangeRange);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = AdjustSpecialBreaks();
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
// turn on undo
|
||||
mEditor->EnableUndo(PR_TRUE);
|
||||
|
@ -180,6 +185,13 @@ nsHTMLEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
|||
res = AdjustWhitespace(selection);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
// replace newlines that are preformatted
|
||||
if ((action == nsEditor::kOpInsertText) ||
|
||||
(action == nsEditor::kOpInsertIMEText) ||
|
||||
(action == nsEditor::kOpInsertNode))
|
||||
{
|
||||
res = ReplaceNewlines(mDocChangeRange);
|
||||
}
|
||||
// clean up any empty nodes in the selection
|
||||
res = RemoveEmptyNodes();
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
@ -1577,8 +1589,27 @@ nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection,
|
|||
PRBool outMakeEmpty;
|
||||
res = ShouldMakeEmptyBlock(aSelection, alignType, &outMakeEmpty);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (outMakeEmpty) return NS_OK;
|
||||
|
||||
if (outMakeEmpty)
|
||||
{
|
||||
PRInt32 offset;
|
||||
nsCOMPtr<nsIDOMNode> brNode, parent, theDiv;
|
||||
nsAutoString divType("div");
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mEditor->CreateNode(divType, parent, offset, getter_AddRefs(theDiv));
|
||||
if (NS_FAILED(res)) return res;
|
||||
// set up the alignment on the div
|
||||
nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(theDiv);
|
||||
nsAutoString attr("align");
|
||||
res = mEditor->SetAttribute(divElem, attr, *alignType);
|
||||
if (NS_FAILED(res)) return res;
|
||||
*aHandled = PR_TRUE;
|
||||
// put in a moz-br so that it won't get deleted
|
||||
res = CreateMozBR(theDiv, 0, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = aSelection->Collapse(theDiv, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
// convert the selection ranges into "promoted" selection ranges:
|
||||
// this basically just expands the range to include the immediate
|
||||
|
|
|
@ -4269,6 +4269,38 @@ nsHTMLEditor::CanContainTag(nsIDOMNode* aParent, const nsString &aTag)
|
|||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::SelectEntireDocument(nsIDOMSelection *aSelection)
|
||||
{
|
||||
nsresult res;
|
||||
if (!aSelection || !mRules) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
// get body node
|
||||
nsCOMPtr<nsIDOMElement>bodyElement;
|
||||
res = GetBodyElement(getter_AddRefs(bodyElement));
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsCOMPtr<nsIDOMNode>bodyNode = do_QueryInterface(bodyElement);
|
||||
if (!bodyNode) return NS_ERROR_FAILURE;
|
||||
|
||||
// is doc empty?
|
||||
PRBool bDocIsEmpty;
|
||||
res = mRules->DocumentIsEmpty(&bDocIsEmpty);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (bDocIsEmpty)
|
||||
{
|
||||
// if its empty dont select entire doc - that would select the bogus node
|
||||
return aSelection->Collapse(bodyNode, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nsEditor::SelectEntireDocument(aSelection);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
#pragma mark --- Random methods ---
|
||||
|
|
|
@ -241,11 +241,6 @@ public:
|
|||
|
||||
NS_IMETHOD DebugUnitTests(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed);
|
||||
|
||||
/* ------------ nsICSSLoaderObserver -------------- */
|
||||
NS_IMETHOD StyleSheetLoaded(nsICSSStyleSheet*aSheet, PRBool aNotify);
|
||||
|
||||
/* ------------ nsEditor overrides ---------------- */
|
||||
|
||||
/** All editor operations which alter the doc should be prefaced
|
||||
* with a call to StartOperation, naming the action and direction */
|
||||
NS_IMETHOD StartOperation(PRInt32 opID, nsIEditor::EDirection aDirection);
|
||||
|
@ -257,6 +252,12 @@ public:
|
|||
/** returns PR_TRUE if aParent can contain a child of type aTag */
|
||||
PRBool CanContainTag(nsIDOMNode* aParent, const nsString &aTag);
|
||||
|
||||
/** make the given selection span the entire document */
|
||||
NS_IMETHOD SelectEntireDocument(nsIDOMSelection *aSelection);
|
||||
|
||||
/* ------------ nsICSSLoaderObserver -------------- */
|
||||
NS_IMETHOD StyleSheetLoaded(nsICSSStyleSheet*aSheet, PRBool aNotify);
|
||||
|
||||
/* ------------ Utility Routines, not part of public API -------------- */
|
||||
NS_IMETHOD GetBodyStyleContext(nsIStyleContext** aStyleContext);
|
||||
|
||||
|
|
|
@ -37,8 +37,10 @@
|
|||
#include "nsLayoutCID.h"
|
||||
#include "nsIEditProperty.h"
|
||||
#include "nsEditorUtils.h"
|
||||
#include "EditTxn.h"
|
||||
|
||||
static NS_DEFINE_CID(kCContentIteratorCID, NS_CONTENTITERATOR_CID);
|
||||
static NS_DEFINE_CID(kContentIteratorCID, NS_CONTENTITERATOR_CID);
|
||||
static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
|
||||
|
||||
|
||||
#define CANCEL_OPERATION_IF_READONLY_OR_DISABLED \
|
||||
|
@ -82,6 +84,24 @@ nsTextEditRules::Init(nsHTMLEditor *aEditor, PRUint32 aFlags)
|
|||
mEditor->GetSelection(getter_AddRefs(selection));
|
||||
NS_ASSERTION(selection, "editor cannot get selection");
|
||||
nsresult res = CreateBogusNodeIfNeeded(selection); // this method handles null selection, which should never happen anyway
|
||||
|
||||
// create a range that is the entire body contents
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsCOMPtr<nsIDOMElement> bodyElement;
|
||||
res = mEditor->GetBodyElement(getter_AddRefs(bodyElement));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!bodyElement) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMNode>bodyNode = do_QueryInterface(bodyElement);
|
||||
if (!bodyNode) return NS_ERROR_FAILURE;
|
||||
nsCOMPtr<nsIDOMRange> wholeDoc;
|
||||
res = nsComponentManager::CreateInstance(kRangeCID, nsnull, NS_GET_IID(nsIDOMRange),
|
||||
getter_AddRefs(wholeDoc));
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = wholeDoc->SelectNode(bodyNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// replace newlines in that range with breaks
|
||||
res = ReplaceNewlines(wholeDoc);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1264,6 +1284,101 @@ nsTextEditRules::DidOutputText(nsIDOMSelection *aSelection, nsresult aResult)
|
|||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsTextEditRules::ReplaceNewlines(nsIDOMRange *aRange)
|
||||
{
|
||||
if (!aRange) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// convert any newlines in editable, preformatted text nodes
|
||||
// into normal breaks. this is because layout wont give us a place
|
||||
// to put the cursor on empty lines otherwise.
|
||||
|
||||
nsCOMPtr<nsIContentIterator> iter;
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
PRUint32 nodeCount,j;
|
||||
nsCOMPtr<nsISupportsArray> arrayOfNodes;
|
||||
|
||||
// make an isupportsArray to hold a list of nodes
|
||||
nsresult res = NS_NewISupportsArray(getter_AddRefs(arrayOfNodes));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// need an iterator
|
||||
res = nsComponentManager::CreateInstance(kContentIteratorCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(iter));
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = iter->Init(aRange);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// gather up a list of editable preformatted text nodes
|
||||
while (NS_ENUMERATOR_FALSE == iter->IsDone())
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
res = iter->CurrentNode(getter_AddRefs(content));
|
||||
if (NS_FAILED(res)) return res;
|
||||
node = do_QueryInterface(content);
|
||||
if (!node) return NS_ERROR_FAILURE;
|
||||
|
||||
if (mEditor->IsTextNode(node) && mEditor->IsEditable(node))
|
||||
{
|
||||
PRBool isPRE;
|
||||
res = mEditor->IsPreformatted(node, &isPRE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (isPRE)
|
||||
{
|
||||
isupports = do_QueryInterface(node);
|
||||
arrayOfNodes->AppendElement(isupports);
|
||||
}
|
||||
}
|
||||
res = iter->Next();
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
// replace newlines with breaks. have to do this left to right,
|
||||
// since inserting the break can split the text node, and the
|
||||
// original node becomes the righthand node.
|
||||
char newlineChar[] = {'\n',0};
|
||||
res = arrayOfNodes->Count(&nodeCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
for (j = 0; j < nodeCount; j++)
|
||||
{
|
||||
isupports = (dont_AddRef)(arrayOfNodes->ElementAt(0));
|
||||
nsCOMPtr<nsIDOMNode> brNode, theNode( do_QueryInterface(isupports) );
|
||||
nsCOMPtr<nsIDOMCharacterData> textNode( do_QueryInterface(theNode) );
|
||||
arrayOfNodes->RemoveElementAt(0);
|
||||
// find the newline
|
||||
PRInt32 offset;
|
||||
nsAutoString tempString;
|
||||
do
|
||||
{
|
||||
textNode->GetData(tempString);
|
||||
offset = tempString.FindCharInSet(newlineChar);
|
||||
if (offset == -1) break; // done with this node
|
||||
|
||||
// delete the newline
|
||||
EditTxn *txn;
|
||||
// note 1: we are not telling edit listeners about these because they don't care
|
||||
// note 2: we are not wrapping these in a placeholder because we know they already are,
|
||||
// or, failing that, undo is disabled
|
||||
res = mEditor->CreateTxnForDeleteText(textNode, offset, 1, (DeleteTextTxn**)&txn);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!txn) return NS_ERROR_OUT_OF_MEMORY;
|
||||
res = mEditor->Do(txn);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// The transaction system (if any) has taken ownwership of txn
|
||||
NS_IF_RELEASE(txn);
|
||||
|
||||
// insert a break
|
||||
res = mEditor->CreateBR(textNode, offset, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
} while (1); // break used to exit while loop
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsTextEditRules::CreateBogusNodeIfNeeded(nsIDOMSelection *aSelection)
|
||||
{
|
||||
|
|
|
@ -182,6 +182,9 @@ protected:
|
|||
const nsString &aValue,
|
||||
nsIDOMSelection *aSelection);
|
||||
|
||||
/** replaces newllines with breaks, if needed. acts on doc portion in aRange */
|
||||
nsresult ReplaceNewlines(nsIDOMRange *aRange);
|
||||
|
||||
/** creates a bogus text node if the document has no editable content */
|
||||
nsresult CreateBogusNodeIfNeeded(nsIDOMSelection *aSelection);
|
||||
|
||||
|
|
|
@ -98,12 +98,17 @@ nsHTMLEditRules::Init(nsHTMLEditor *aEditor, PRUint32 aFlags)
|
|||
bodyNode = do_QueryInterface(bodyElem);
|
||||
if (bodyNode)
|
||||
{
|
||||
// temporarily turn off rules sniffing
|
||||
nsAutoLockRulesSniffing lockIt((nsTextEditRules*)this);
|
||||
res = nsComponentManager::CreateInstance(kRangeCID, nsnull, NS_GET_IID(nsIDOMRange),
|
||||
getter_AddRefs(mDocChangeRange));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!mDocChangeRange) return NS_ERROR_NULL_POINTER;
|
||||
mDocChangeRange->SelectNode(bodyNode);
|
||||
AdjustSpecialBreaks();
|
||||
res = ReplaceNewlines(mDocChangeRange);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = AdjustSpecialBreaks();
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
// turn on undo
|
||||
mEditor->EnableUndo(PR_TRUE);
|
||||
|
@ -180,6 +185,13 @@ nsHTMLEditRules::AfterEdit(PRInt32 action, nsIEditor::EDirection aDirection)
|
|||
res = AdjustWhitespace(selection);
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
// replace newlines that are preformatted
|
||||
if ((action == nsEditor::kOpInsertText) ||
|
||||
(action == nsEditor::kOpInsertIMEText) ||
|
||||
(action == nsEditor::kOpInsertNode))
|
||||
{
|
||||
res = ReplaceNewlines(mDocChangeRange);
|
||||
}
|
||||
// clean up any empty nodes in the selection
|
||||
res = RemoveEmptyNodes();
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
@ -1577,8 +1589,27 @@ nsHTMLEditRules::WillAlign(nsIDOMSelection *aSelection,
|
|||
PRBool outMakeEmpty;
|
||||
res = ShouldMakeEmptyBlock(aSelection, alignType, &outMakeEmpty);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (outMakeEmpty) return NS_OK;
|
||||
|
||||
if (outMakeEmpty)
|
||||
{
|
||||
PRInt32 offset;
|
||||
nsCOMPtr<nsIDOMNode> brNode, parent, theDiv;
|
||||
nsAutoString divType("div");
|
||||
res = mEditor->GetStartNodeAndOffset(aSelection, &parent, &offset);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = mEditor->CreateNode(divType, parent, offset, getter_AddRefs(theDiv));
|
||||
if (NS_FAILED(res)) return res;
|
||||
// set up the alignment on the div
|
||||
nsCOMPtr<nsIDOMElement> divElem = do_QueryInterface(theDiv);
|
||||
nsAutoString attr("align");
|
||||
res = mEditor->SetAttribute(divElem, attr, *alignType);
|
||||
if (NS_FAILED(res)) return res;
|
||||
*aHandled = PR_TRUE;
|
||||
// put in a moz-br so that it won't get deleted
|
||||
res = CreateMozBR(theDiv, 0, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = aSelection->Collapse(theDiv, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
// convert the selection ranges into "promoted" selection ranges:
|
||||
// this basically just expands the range to include the immediate
|
||||
|
|
|
@ -4269,6 +4269,38 @@ nsHTMLEditor::CanContainTag(nsIDOMNode* aParent, const nsString &aTag)
|
|||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::SelectEntireDocument(nsIDOMSelection *aSelection)
|
||||
{
|
||||
nsresult res;
|
||||
if (!aSelection || !mRules) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
// get body node
|
||||
nsCOMPtr<nsIDOMElement>bodyElement;
|
||||
res = GetBodyElement(getter_AddRefs(bodyElement));
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsCOMPtr<nsIDOMNode>bodyNode = do_QueryInterface(bodyElement);
|
||||
if (!bodyNode) return NS_ERROR_FAILURE;
|
||||
|
||||
// is doc empty?
|
||||
PRBool bDocIsEmpty;
|
||||
res = mRules->DocumentIsEmpty(&bDocIsEmpty);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
if (bDocIsEmpty)
|
||||
{
|
||||
// if its empty dont select entire doc - that would select the bogus node
|
||||
return aSelection->Collapse(bodyNode, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nsEditor::SelectEntireDocument(aSelection);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef XP_MAC
|
||||
#pragma mark -
|
||||
#pragma mark --- Random methods ---
|
||||
|
|
|
@ -241,11 +241,6 @@ public:
|
|||
|
||||
NS_IMETHOD DebugUnitTests(PRInt32 *outNumTests, PRInt32 *outNumTestsFailed);
|
||||
|
||||
/* ------------ nsICSSLoaderObserver -------------- */
|
||||
NS_IMETHOD StyleSheetLoaded(nsICSSStyleSheet*aSheet, PRBool aNotify);
|
||||
|
||||
/* ------------ nsEditor overrides ---------------- */
|
||||
|
||||
/** All editor operations which alter the doc should be prefaced
|
||||
* with a call to StartOperation, naming the action and direction */
|
||||
NS_IMETHOD StartOperation(PRInt32 opID, nsIEditor::EDirection aDirection);
|
||||
|
@ -257,6 +252,12 @@ public:
|
|||
/** returns PR_TRUE if aParent can contain a child of type aTag */
|
||||
PRBool CanContainTag(nsIDOMNode* aParent, const nsString &aTag);
|
||||
|
||||
/** make the given selection span the entire document */
|
||||
NS_IMETHOD SelectEntireDocument(nsIDOMSelection *aSelection);
|
||||
|
||||
/* ------------ nsICSSLoaderObserver -------------- */
|
||||
NS_IMETHOD StyleSheetLoaded(nsICSSStyleSheet*aSheet, PRBool aNotify);
|
||||
|
||||
/* ------------ Utility Routines, not part of public API -------------- */
|
||||
NS_IMETHOD GetBodyStyleContext(nsIStyleContext** aStyleContext);
|
||||
|
||||
|
|
|
@ -37,8 +37,10 @@
|
|||
#include "nsLayoutCID.h"
|
||||
#include "nsIEditProperty.h"
|
||||
#include "nsEditorUtils.h"
|
||||
#include "EditTxn.h"
|
||||
|
||||
static NS_DEFINE_CID(kCContentIteratorCID, NS_CONTENTITERATOR_CID);
|
||||
static NS_DEFINE_CID(kContentIteratorCID, NS_CONTENTITERATOR_CID);
|
||||
static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID);
|
||||
|
||||
|
||||
#define CANCEL_OPERATION_IF_READONLY_OR_DISABLED \
|
||||
|
@ -82,6 +84,24 @@ nsTextEditRules::Init(nsHTMLEditor *aEditor, PRUint32 aFlags)
|
|||
mEditor->GetSelection(getter_AddRefs(selection));
|
||||
NS_ASSERTION(selection, "editor cannot get selection");
|
||||
nsresult res = CreateBogusNodeIfNeeded(selection); // this method handles null selection, which should never happen anyway
|
||||
|
||||
// create a range that is the entire body contents
|
||||
if (NS_FAILED(res)) return res;
|
||||
nsCOMPtr<nsIDOMElement> bodyElement;
|
||||
res = mEditor->GetBodyElement(getter_AddRefs(bodyElement));
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!bodyElement) return NS_ERROR_NULL_POINTER;
|
||||
nsCOMPtr<nsIDOMNode>bodyNode = do_QueryInterface(bodyElement);
|
||||
if (!bodyNode) return NS_ERROR_FAILURE;
|
||||
nsCOMPtr<nsIDOMRange> wholeDoc;
|
||||
res = nsComponentManager::CreateInstance(kRangeCID, nsnull, NS_GET_IID(nsIDOMRange),
|
||||
getter_AddRefs(wholeDoc));
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = wholeDoc->SelectNode(bodyNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// replace newlines in that range with breaks
|
||||
res = ReplaceNewlines(wholeDoc);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -1264,6 +1284,101 @@ nsTextEditRules::DidOutputText(nsIDOMSelection *aSelection, nsresult aResult)
|
|||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsTextEditRules::ReplaceNewlines(nsIDOMRange *aRange)
|
||||
{
|
||||
if (!aRange) return NS_ERROR_NULL_POINTER;
|
||||
|
||||
// convert any newlines in editable, preformatted text nodes
|
||||
// into normal breaks. this is because layout wont give us a place
|
||||
// to put the cursor on empty lines otherwise.
|
||||
|
||||
nsCOMPtr<nsIContentIterator> iter;
|
||||
nsCOMPtr<nsISupports> isupports;
|
||||
PRUint32 nodeCount,j;
|
||||
nsCOMPtr<nsISupportsArray> arrayOfNodes;
|
||||
|
||||
// make an isupportsArray to hold a list of nodes
|
||||
nsresult res = NS_NewISupportsArray(getter_AddRefs(arrayOfNodes));
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// need an iterator
|
||||
res = nsComponentManager::CreateInstance(kContentIteratorCID,
|
||||
nsnull,
|
||||
NS_GET_IID(nsIContentIterator),
|
||||
getter_AddRefs(iter));
|
||||
if (NS_FAILED(res)) return res;
|
||||
res = iter->Init(aRange);
|
||||
if (NS_FAILED(res)) return res;
|
||||
|
||||
// gather up a list of editable preformatted text nodes
|
||||
while (NS_ENUMERATOR_FALSE == iter->IsDone())
|
||||
{
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsIContent> content;
|
||||
res = iter->CurrentNode(getter_AddRefs(content));
|
||||
if (NS_FAILED(res)) return res;
|
||||
node = do_QueryInterface(content);
|
||||
if (!node) return NS_ERROR_FAILURE;
|
||||
|
||||
if (mEditor->IsTextNode(node) && mEditor->IsEditable(node))
|
||||
{
|
||||
PRBool isPRE;
|
||||
res = mEditor->IsPreformatted(node, &isPRE);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (isPRE)
|
||||
{
|
||||
isupports = do_QueryInterface(node);
|
||||
arrayOfNodes->AppendElement(isupports);
|
||||
}
|
||||
}
|
||||
res = iter->Next();
|
||||
if (NS_FAILED(res)) return res;
|
||||
}
|
||||
|
||||
// replace newlines with breaks. have to do this left to right,
|
||||
// since inserting the break can split the text node, and the
|
||||
// original node becomes the righthand node.
|
||||
char newlineChar[] = {'\n',0};
|
||||
res = arrayOfNodes->Count(&nodeCount);
|
||||
if (NS_FAILED(res)) return res;
|
||||
for (j = 0; j < nodeCount; j++)
|
||||
{
|
||||
isupports = (dont_AddRef)(arrayOfNodes->ElementAt(0));
|
||||
nsCOMPtr<nsIDOMNode> brNode, theNode( do_QueryInterface(isupports) );
|
||||
nsCOMPtr<nsIDOMCharacterData> textNode( do_QueryInterface(theNode) );
|
||||
arrayOfNodes->RemoveElementAt(0);
|
||||
// find the newline
|
||||
PRInt32 offset;
|
||||
nsAutoString tempString;
|
||||
do
|
||||
{
|
||||
textNode->GetData(tempString);
|
||||
offset = tempString.FindCharInSet(newlineChar);
|
||||
if (offset == -1) break; // done with this node
|
||||
|
||||
// delete the newline
|
||||
EditTxn *txn;
|
||||
// note 1: we are not telling edit listeners about these because they don't care
|
||||
// note 2: we are not wrapping these in a placeholder because we know they already are,
|
||||
// or, failing that, undo is disabled
|
||||
res = mEditor->CreateTxnForDeleteText(textNode, offset, 1, (DeleteTextTxn**)&txn);
|
||||
if (NS_FAILED(res)) return res;
|
||||
if (!txn) return NS_ERROR_OUT_OF_MEMORY;
|
||||
res = mEditor->Do(txn);
|
||||
if (NS_FAILED(res)) return res;
|
||||
// The transaction system (if any) has taken ownwership of txn
|
||||
NS_IF_RELEASE(txn);
|
||||
|
||||
// insert a break
|
||||
res = mEditor->CreateBR(textNode, offset, &brNode);
|
||||
if (NS_FAILED(res)) return res;
|
||||
} while (1); // break used to exit while loop
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsTextEditRules::CreateBogusNodeIfNeeded(nsIDOMSelection *aSelection)
|
||||
{
|
||||
|
|
|
@ -182,6 +182,9 @@ protected:
|
|||
const nsString &aValue,
|
||||
nsIDOMSelection *aSelection);
|
||||
|
||||
/** replaces newllines with breaks, if needed. acts on doc portion in aRange */
|
||||
nsresult ReplaceNewlines(nsIDOMRange *aRange);
|
||||
|
||||
/** creates a bogus text node if the document has no editable content */
|
||||
nsresult CreateBogusNodeIfNeeded(nsIDOMSelection *aSelection);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче