Implement switching betweeen TH and TD elements for table editing. b=20973, r=jfrancis, akkana

This commit is contained in:
cmanske%netscape.com 2000-06-22 05:39:54 +00:00
Родитель ebf5ec54ff
Коммит e27221d200
18 изменённых файлов: 752 добавлений и 530 удалений

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

@ -1820,7 +1820,8 @@ nsEditor::ReplaceContainer(nsIDOMNode *inNode,
nsCOMPtr<nsIDOMNode> *outNode,
const nsString &aNodeType,
const nsString *aAttribute,
const nsString *aValue)
const nsString *aValue,
PRBool aCloneAttributes)
{
if (!inNode || !outNode)
return NS_ERROR_NULL_POINTER;
@ -1851,14 +1852,32 @@ nsEditor::ReplaceContainer(nsIDOMNode *inNode,
res = elem->SetAttribute(*aAttribute, *aValue);
if (NS_FAILED(res)) return res;
}
if (aCloneAttributes)
{
nsCOMPtr<nsIDOMNode>newNode = do_QueryInterface(elem);
res = CloneAttributes(newNode, inNode);
if (NS_FAILED(res)) return res;
}
// notify our internal selection state listener
nsAutoReplaceContainerSelNotify selStateNotify(mSavedSel, inNode, *outNode);
// insert new container into tree
res = InsertNode( *outNode, parent, offset);
if (NS_FAILED(res)) return res;
// We sometimes insert default <br> (like in a table cell),
// so save this to delete later
nsCOMPtr<nsIDOMNode> newNodeDefaultChild;
nsresult resFirstChild = (*outNode)->GetFirstChild(getter_AddRefs(newNodeDefaultChild));
// move children into new container
nsCOMPtr<nsIDOMNode> child;
/*
// This doesn't work when used with table cells!
PRBool bHasMoreChildren;
inNode->HasChildNodes(&bHasMoreChildren);
nsCOMPtr<nsIDOMNode> child;
while (bHasMoreChildren)
{
inNode->GetLastChild(getter_AddRefs(child));
@ -1868,14 +1887,35 @@ nsEditor::ReplaceContainer(nsIDOMNode *inNode,
if (NS_FAILED(res)) return res;
inNode->HasChildNodes(&bHasMoreChildren);
}
*/
// Insert at start of the new node
PRInt32 insertIndex = 0;
res = inNode->GetFirstChild(getter_AddRefs(child));
if (NS_FAILED(res)) return res;
while (child)
{
nsCOMPtr<nsIDOMNode> nextChild;
res = child->GetNextSibling(getter_AddRefs(nextChild));
if (NS_FAILED(res)) return res;
res = DeleteNode(child);
if (NS_FAILED(res)) return res;
res = InsertNode(child, *outNode, insertIndex);
if (NS_FAILED(res)) return res;
child = nextChild;
insertIndex++;
}
// Now that we have some real content in the new node,
// delete the default first child
// (We must do this AFTER moving the other nodes
// because rules would reinsert it if we did it first!)
if (NS_SUCCEEDED(resFirstChild) && newNodeDefaultChild)
DeleteNode(newNodeDefaultChild);
// delete old container
res = DeleteNode(inNode);
if (NS_FAILED(res)) return res;
// insert new container into tree
res = InsertNode( *outNode, parent, offset);
return res;
return DeleteNode(inNode);
}
///////////////////////////////////////////////////////////////////////////

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

@ -318,7 +318,9 @@ public:
nsCOMPtr<nsIDOMNode> *outNode,
const nsString &aNodeType,
const nsString *aAttribute = nsnull,
const nsString *aValue = nsnull);
const nsString *aValue = nsnull,
PRBool aCloneAttributes = PR_FALSE);
nsresult RemoveContainer(nsIDOMNode *inNode);
nsresult InsertContainerAbove(nsIDOMNode *inNode,
nsCOMPtr<nsIDOMNode> *outNode,

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

@ -1171,7 +1171,7 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection,
// see if we are in an "empty" node.
// Note: do NOT delete table elements this way.
PRBool bIsEmptyNode;
res = IsEmptyNode(node, &bIsEmptyNode, PR_TRUE, PR_FALSE);
res = mEditor->IsEmptyNode(node, &bIsEmptyNode, PR_TRUE, PR_FALSE);
if (bIsEmptyNode && !mEditor->IsTableElement(node))
nodeToDelete = node;
else
@ -1511,7 +1511,7 @@ nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection,
else if (mEditor->IsInlineNode(curNode) && mEditor->IsContainer(curNode))
{
PRBool bEmpty;
res = IsEmptyNode( curNode, &bEmpty);
res = mEditor->IsEmptyNode(curNode, &bEmpty);
if (NS_FAILED(res)) return res;
if (bEmpty)
{
@ -2196,7 +2196,7 @@ nsHTMLEditRules::IsEmptyBlock(nsIDOMNode *aNode,
// looks like I forgot to finish this. Wonder what I was going to do?
if (!nodeToTest) return NS_ERROR_NULL_POINTER;
return IsEmptyNode(nodeToTest, outIsEmptyBlock,
return mEditor->IsEmptyNode(nodeToTest, outIsEmptyBlock,
aMozBRDoesntCount, aListItemsNotEmpty);
}
@ -3350,7 +3350,7 @@ nsHTMLEditRules::ReturnInHeader(nsIDOMSelection *aSelection,
if (prevItem && nsHTMLEditUtils::IsHeader(prevItem))
{
PRBool bIsEmptyNode;
res = IsEmptyNode(prevItem, &bIsEmptyNode);
res = mEditor->IsEmptyNode(prevItem, &bIsEmptyNode);
if (NS_FAILED(res)) return res;
if (bIsEmptyNode)
{
@ -3607,7 +3607,7 @@ nsHTMLEditRules::ReturnInListItem(nsIDOMSelection *aSelection,
if (prevItem && nsHTMLEditUtils::IsListItem(prevItem))
{
PRBool bIsEmptyNode;
res = IsEmptyNode(prevItem, &bIsEmptyNode);
res = mEditor->IsEmptyNode(prevItem, &bIsEmptyNode);
if (NS_FAILED(res)) return res;
if (bIsEmptyNode)
{
@ -4184,7 +4184,7 @@ nsHTMLEditRules::AdjustSpecialBreaks()
if (!node) return NS_ERROR_FAILURE;
PRBool bIsEmptyNode;
res = IsEmptyNode(node, &bIsEmptyNode, PR_FALSE, PR_FALSE);
res = mEditor->IsEmptyNode(node, &bIsEmptyNode, PR_FALSE, PR_FALSE);
if (NS_FAILED(res)) return res;
if (bIsEmptyNode
&& (nsHTMLEditUtils::IsListItem(node) || mEditor->IsTableCell(node)))
@ -4551,7 +4551,7 @@ nsHTMLEditRules::RemoveEmptyNodes()
if (!node) return NS_ERROR_FAILURE;
PRBool bIsEmptyNode;
res = IsEmptyNode(node, &bIsEmptyNode, PR_FALSE, PR_TRUE);
res = mEditor->IsEmptyNode(node, &bIsEmptyNode, PR_FALSE, PR_TRUE);
if (NS_FAILED(res)) return res;
if (bIsEmptyNode && !nsHTMLEditUtils::IsBody(node))
{
@ -4984,7 +4984,7 @@ nsHTMLEditRules::InsertMozBRIfNeeded(nsIDOMNode *aNode)
PRBool isEmpty;
nsCOMPtr<nsIDOMNode> brNode;
nsresult res = IsEmptyNode(aNode, &isEmpty);
nsresult res = mEditor->IsEmptyNode(aNode, &isEmpty);
if (NS_FAILED(res)) return res;
if (isEmpty)
{

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

@ -38,12 +38,15 @@ PRBool
nsHTMLEditUtils::IsBody(nsIDOMNode *node)
{
NS_PRECONDITION(node, "null node passed to nsHTMLEditUtils::IsBody");
nsAutoString tag;
nsEditor::GetTagString(node,tag);
tag.ToLowerCase();
if (tag.EqualsWithConversion("body"))
if (node)
{
return PR_TRUE;
nsAutoString tag;
nsEditor::GetTagString(node,tag);
tag.ToLowerCase();
if (tag.EqualsWithConversion("body"))
{
return PR_TRUE;
}
}
return PR_FALSE;
}

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

@ -7063,3 +7063,102 @@ nsHTMLEditor::GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOu
return res;
}
///////////////////////////////////////////////////////////////////////////
// IsEmptyNode: figure out if aNode is an empty node.
// A block can have children and still be considered empty,
// if the children are empty or non-editable.
//
nsresult
nsHTMLEditor::IsEmptyNode( nsIDOMNode *aNode,
PRBool *outIsEmptyNode,
PRBool aMozBRDoesntCount,
PRBool aListOrCellNotEmpty)
{
if (!aNode || !outIsEmptyNode) return NS_ERROR_NULL_POINTER;
*outIsEmptyNode = PR_TRUE;
// effeciency hack - special case if it's a text node
if (nsEditor::IsTextNode(aNode))
{
PRUint32 length = 0;
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
nodeAsText = do_QueryInterface(aNode);
nodeAsText->GetLength(&length);
if (length) *outIsEmptyNode = PR_FALSE;
return NS_OK;
}
// if it's not a text node (handled above) and it's not a container,
// then we dont call it empty (it's an <hr>, or <br>, etc).
// Also, if it's an anchor then dont treat it as empty - even though
// anchors are containers, named anchors are "empty" but we don't
// want to treat them as such. Also, don't call ListItems or table
// cells empty if caller desires.
if (!IsContainer(aNode) || nsHTMLEditUtils::IsAnchor(aNode) ||
(aListOrCellNotEmpty && nsHTMLEditUtils::IsListItem(aNode)) ||
(aListOrCellNotEmpty && nsHTMLEditUtils::IsTableCell(aNode)) )
{
*outIsEmptyNode = PR_FALSE;
return NS_OK;
}
// iterate over node. if no children, or all children are either
// empty text nodes or non-editable, then node qualifies as empty
nsCOMPtr<nsIContentIterator> iter;
nsCOMPtr<nsIContent> nodeAsContent = do_QueryInterface(aNode);
if (!nodeAsContent) return NS_ERROR_FAILURE;
nsresult res = nsComponentManager::CreateInstance(kCContentIteratorCID,
nsnull,
NS_GET_IID(nsIContentIterator),
getter_AddRefs(iter));
if (NS_FAILED(res)) return res;
res = iter->Init(nodeAsContent);
if (NS_FAILED(res)) return res;
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;
// is the node editable and non-empty? if so, return false
if (nsEditor::IsEditable(node))
{
if (nsEditor::IsTextNode(node))
{
PRUint32 length = 0;
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
nodeAsText = do_QueryInterface(node);
nodeAsText->GetLength(&length);
if (length) *outIsEmptyNode = PR_FALSE;
}
else // an editable, non-text node. we aren't an empty block
{
// is it the node we are iterating over?
if (node.get() == aNode) break;
// is it a moz-BR and did the caller ask us not to consider those relevant?
if (!(aMozBRDoesntCount && nsHTMLEditUtils::IsMozBR(node)))
{
// is it an empty node of some sort?
PRBool isEmptyNode;
res = IsEmptyNode(node, &isEmptyNode, aMozBRDoesntCount, aListOrCellNotEmpty);
if (NS_FAILED(res)) return res;
if (!isEmptyNode)
{
// otherwise it ain't empty
*outIsEmptyNode = PR_FALSE;
break;
}
}
}
}
res = iter->Next();
if (NS_FAILED(res)) return res;
}
return NS_OK;
}

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

@ -396,6 +396,8 @@ protected:
PRBool AllCellsInRowSelected(nsIDOMElement *aTable, PRInt32 aRowIndex, PRInt32 aNumberOfColumns);
PRBool AllCellsInColumnSelected(nsIDOMElement *aTable, PRInt32 aColIndex, PRInt32 aNumberOfRows);
PRBool IsEmptyCell(nsIDOMElement *aCell);
// Most insert methods need to get the same basic context data
// Any of the pointers may be null if you don't need that datum (for more efficiency)
// Input: *aCell is a known cell,
@ -549,6 +551,9 @@ protected:
nsresult IsLastEditableChild( nsIDOMNode *aNode, PRBool *aOutIsLast);
nsresult GetFirstEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstChild);
nsresult GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastChild);
nsresult IsEmptyNode(nsIDOMNode *aNode, PRBool *outIsEmptyBlock,
PRBool aMozBRDoesntCount = PR_FALSE,
PRBool aListOrCellNotEmpty = PR_FALSE);
nsresult GetDOMEventReceiver(nsIDOMEventReceiver **aEventReceiver);

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

@ -44,6 +44,7 @@
#include "nsVoidArray.h"
#include "nsEditorUtils.h"
#include "nsHTMLEditUtils.h"
//#define DEBUG_TABLE 1
@ -120,9 +121,9 @@ nsHTMLEditor::InsertCell(nsIDOMElement *aCell, PRInt32 aRowSpan, PRInt32 aColSpa
nsCOMPtr<nsIDOMElement> newCell;
if (aIsHeader)
res = CreateElementWithDefaults(NS_ConvertASCIItoUCS2("th"), getter_AddRefs(newCell));
res = CreateElementWithDefaults(NS_LITERAL_STRING("th"), getter_AddRefs(newCell));
else
res = CreateElementWithDefaults(NS_ConvertASCIItoUCS2("td"), getter_AddRefs(newCell));
res = CreateElementWithDefaults(NS_LITERAL_STRING("td"), getter_AddRefs(newCell));
if(NS_FAILED(res)) return res;
if(!newCell) return NS_ERROR_FAILURE;
@ -137,19 +138,19 @@ nsHTMLEditor::InsertCell(nsIDOMElement *aCell, PRInt32 aRowSpan, PRInt32 aColSpa
{
nsAutoString newRowSpan(aRowSpan);
// Note: Do NOT use editor txt for this
newCell->SetAttribute(NS_ConvertASCIItoUCS2("rowspan"), newRowSpan);
newCell->SetAttribute(NS_LITERAL_STRING("rowspan"), newRowSpan);
}
if( aColSpan > 1)
{
nsAutoString newColSpan(aColSpan);
// Note: Do NOT use editor txt for this
newCell->SetAttribute(NS_ConvertASCIItoUCS2("colspan"), newColSpan);
newCell->SetAttribute(NS_LITERAL_STRING("colspan"), newColSpan);
}
if(aAfter) cellOffset++;
//Don't let Rules System change the selection
nsAutoTxnsConserveSelection dontChangeSelection(this);
return nsEditor::InsertNode(newCell, cellParent, cellOffset);
return InsertNode(newCell, cellParent, cellOffset);
}
PRBool IsRowNode(nsCOMPtr<nsIDOMNode> &aNode)
@ -221,11 +222,11 @@ nsHTMLEditor::InsertTableCell(PRInt32 aNumber, PRBool aAfter)
for (i = 0; i < aNumber; i++)
{
nsCOMPtr<nsIDOMElement> newCell;
res = CreateElementWithDefaults(NS_ConvertASCIItoUCS2("td"), getter_AddRefs(newCell));
res = CreateElementWithDefaults(NS_LITERAL_STRING("td"), getter_AddRefs(newCell));
if (NS_SUCCEEDED(res) && newCell)
{
if (aAfter) cellOffset++;
res = nsEditor::InsertNode(newCell, cellParent, cellOffset);
res = InsertNode(newCell, cellParent, cellOffset);
if(NS_FAILED(res)) break;
}
}
@ -238,7 +239,7 @@ nsHTMLEditor::GetFirstRow(nsIDOMElement* aTableElement, nsIDOMElement* &aRow)
aRow = nsnull;
nsCOMPtr<nsIDOMElement> tableElement;
nsresult res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), aTableElement, getter_AddRefs(tableElement));
nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aTableElement, getter_AddRefs(tableElement));
if (NS_FAILED(res)) return res;
if (!tableElement) return NS_ERROR_NULL_POINTER;
@ -303,7 +304,7 @@ nsHTMLEditor::GetNextRow(nsIDOMElement* aTableElement, nsIDOMElement* &aRow)
aRow = nsnull;
nsCOMPtr<nsIDOMElement> rowElement;
nsresult res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("tr"), aTableElement, getter_AddRefs(rowElement));
nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("tr"), aTableElement, getter_AddRefs(rowElement));
if (NS_FAILED(res)) return res;
if (!rowElement) return NS_ERROR_NULL_POINTER;
@ -498,7 +499,7 @@ nsHTMLEditor::InsertTableRow(PRInt32 aNumber, PRBool aAfter)
if (!curCell) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMElement> parentRow;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("tr"), curCell, getter_AddRefs(parentRow));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("tr"), curCell, getter_AddRefs(parentRow));
if (NS_FAILED(res)) return res;
if (!parentRow) return NS_ERROR_NULL_POINTER;
@ -596,7 +597,7 @@ nsHTMLEditor::InsertTableRow(PRInt32 aNumber, PRBool aAfter)
{
// Create a new row
nsCOMPtr<nsIDOMElement> newRow;
res = CreateElementWithDefaults(NS_ConvertASCIItoUCS2("tr"), getter_AddRefs(newRow));
res = CreateElementWithDefaults(NS_LITERAL_STRING("tr"), getter_AddRefs(newRow));
if (NS_SUCCEEDED(res))
{
if (!newRow) return NS_ERROR_FAILURE;
@ -604,7 +605,7 @@ nsHTMLEditor::InsertTableRow(PRInt32 aNumber, PRBool aAfter)
for (PRInt32 i = 0; i < cellsInRow; i++)
{
nsCOMPtr<nsIDOMElement> newCell;
res = CreateElementWithDefaults(NS_ConvertASCIItoUCS2("td"), getter_AddRefs(newCell));
res = CreateElementWithDefaults(NS_LITERAL_STRING("td"), getter_AddRefs(newCell));
if (NS_FAILED(res)) return res;
if (!newCell) return NS_ERROR_FAILURE;
@ -615,7 +616,7 @@ nsHTMLEditor::InsertTableRow(PRInt32 aNumber, PRBool aAfter)
}
// Use transaction system to insert the entire row+cells
// (Note that rows are inserted at same childoffset each time)
res = nsEditor::InsertNode(newRow, parentOfRow, newRowOffset);
res = InsertNode(newRow, parentOfRow, newRowOffset);
if (NS_FAILED(res)) return res;
}
}
@ -629,7 +630,7 @@ nsHTMLEditor::DeleteTable2(nsCOMPtr<nsIDOMElement> &aTable, nsCOMPtr<nsIDOMSelec
{
nsCOMPtr<nsIDOMNode> tableParent;
PRInt32 tableOffset;
if(NS_FAILED(aTable->GetParentNode(getter_AddRefs(tableParent))) || !tableParent)
if(!aTable || NS_FAILED(aTable->GetParentNode(getter_AddRefs(tableParent))) || !tableParent)
return NS_ERROR_FAILURE;
// Save offset we need to restore the selection
@ -669,7 +670,7 @@ nsHTMLEditor::DeleteTableCell(PRInt32 aNumber)
nsCOMPtr<nsIDOMElement> cell;
PRInt32 startRowIndex, startColIndex;
nsresult res = nsEditor::GetSelection(getter_AddRefs(selection));
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_FAILURE;
@ -689,7 +690,7 @@ nsHTMLEditor::DeleteTableCell(PRInt32 aNumber)
if (1 == GetNumberOfCellsInRow(table, startRowIndex))
{
nsCOMPtr<nsIDOMElement> parentRow;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("tr"), cell, getter_AddRefs(parentRow));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("tr"), cell, getter_AddRefs(parentRow));
if (NS_FAILED(res)) return res;
if (!parentRow) return NS_ERROR_NULL_POINTER;
@ -849,7 +850,7 @@ nsHTMLEditor::DeleteTableColumn(PRInt32 aNumber)
{
// Only 1 cell in row - delete the row
nsCOMPtr<nsIDOMElement> parentRow;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("tr"), cell, getter_AddRefs(parentRow));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("tr"), cell, getter_AddRefs(parentRow));
if (NS_FAILED(res)) return res;
if(!parentRow) return NS_ERROR_NULL_POINTER;
@ -972,7 +973,7 @@ nsHTMLEditor::DeleteTableRow(PRInt32 aNumber)
// Delete the row
nsCOMPtr<nsIDOMElement> parentRow;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("tr"), cell, getter_AddRefs(parentRow));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("tr"), cell, getter_AddRefs(parentRow));
if (NS_SUCCEEDED(res) && parentRow)
res = DeleteNode(parentRow);
if (NS_FAILED(res))
@ -992,7 +993,7 @@ nsHTMLEditor::SelectTable()
{
nsCOMPtr<nsIDOMElement> table;
nsresult res = NS_ERROR_FAILURE;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), nsnull, getter_AddRefs(table));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), nsnull, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
// Don't fail if we didn't find a table
if (!table) return NS_OK;
@ -1011,7 +1012,7 @@ NS_IMETHODIMP
nsHTMLEditor::SelectTableCell()
{
nsCOMPtr<nsIDOMElement> cell;
nsresult res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("td"), nsnull, getter_AddRefs(cell));
nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nsnull, getter_AddRefs(cell));
if (NS_FAILED(res)) return res;
// Don't fail if we didn't find a table
if (!cell) return NS_EDITOR_ELEMENT_NOT_FOUND;
@ -1032,17 +1033,17 @@ nsHTMLEditor::SelectBlockOfCells(nsIDOMElement *aStartCell, nsIDOMElement *aEndC
if (!aStartCell || !aEndCell) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMSelection> selection;
nsresult res = nsEditor::GetSelection(getter_AddRefs(selection));
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMElement> table;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), aStartCell, getter_AddRefs(table));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aStartCell, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
if (!table) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMElement> endTable;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), aEndCell, getter_AddRefs(endTable));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aEndCell, getter_AddRefs(endTable));
if (NS_FAILED(res)) return res;
if (!endTable) return NS_ERROR_FAILURE;
@ -1107,7 +1108,7 @@ nsHTMLEditor::SelectBlockOfCells(nsIDOMElement *aStartCell, nsIDOMElement *aEndC
if (!isSelected && cell && row == currentRowIndex && col == currentColIndex)
{
nsCOMPtr<nsIDOMNode> cellNode = do_QueryInterface(cell);
res = nsEditor::AppendNodeToSelectionAsRange(cellNode);
res = AppendNodeToSelectionAsRange(cellNode);
if (NS_FAILED(res)) break;
}
}
@ -1119,7 +1120,7 @@ NS_IMETHODIMP
nsHTMLEditor::SelectAllTableCells()
{
nsCOMPtr<nsIDOMElement> cell;
nsresult res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("td"), nsnull, getter_AddRefs(cell));
nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nsnull, getter_AddRefs(cell));
if (NS_FAILED(res)) return res;
// Don't fail if we didn't find a cell
@ -1131,7 +1132,7 @@ nsHTMLEditor::SelectAllTableCells()
// Get parent table
nsCOMPtr<nsIDOMElement> table;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), cell, getter_AddRefs(table));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), cell, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
if(!table) return NS_ERROR_NULL_POINTER;
@ -1140,7 +1141,7 @@ nsHTMLEditor::SelectAllTableCells()
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMSelection> selection;
res = nsEditor::GetSelection(getter_AddRefs(selection));
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_FAILURE;
@ -1168,7 +1169,7 @@ nsHTMLEditor::SelectAllTableCells()
if (cell && row == currentRowIndex && col == currentColIndex)
{
cellNode = do_QueryInterface(cell);
res = nsEditor::AppendNodeToSelectionAsRange(cellNode);
res = AppendNodeToSelectionAsRange(cellNode);
if (NS_FAILED(res)) break;
cellSelected = PR_TRUE;
}
@ -1178,7 +1179,7 @@ nsHTMLEditor::SelectAllTableCells()
if (!cellSelected)
{
cellNode = do_QueryInterface(startCell);
return nsEditor::AppendNodeToSelectionAsRange(cellNode);
return AppendNodeToSelectionAsRange(cellNode);
}
return res;
}
@ -1187,7 +1188,7 @@ NS_IMETHODIMP
nsHTMLEditor::SelectTableRow()
{
nsCOMPtr<nsIDOMElement> cell;
nsresult res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("td"), nsnull, getter_AddRefs(cell));
nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nsnull, getter_AddRefs(cell));
if (NS_FAILED(res)) return res;
// Don't fail if we didn't find a cell
@ -1240,7 +1241,7 @@ nsHTMLEditor::SelectTableRow()
if (cell && currentRowIndex == startRowIndex && currentColIndex == col)
{
cellNode = do_QueryInterface(cell);
res = nsEditor::AppendNodeToSelectionAsRange(cellNode);
res = AppendNodeToSelectionAsRange(cellNode);
if (NS_FAILED(res)) break;
cellSelected = PR_TRUE;
}
@ -1249,7 +1250,7 @@ nsHTMLEditor::SelectTableRow()
if (!cellSelected)
{
cellNode = do_QueryInterface(startCell);
return nsEditor::AppendNodeToSelectionAsRange(cellNode);
return AppendNodeToSelectionAsRange(cellNode);
}
return res;
}
@ -1258,7 +1259,7 @@ NS_IMETHODIMP
nsHTMLEditor::SelectTableColumn()
{
nsCOMPtr<nsIDOMElement> cell;
nsresult res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("td"), nsnull, getter_AddRefs(cell));
nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nsnull, getter_AddRefs(cell));
if (NS_FAILED(res)) return res;
// Don't fail if we didn't find a cell
@ -1307,7 +1308,7 @@ nsHTMLEditor::SelectTableColumn()
if (cell && currentRowIndex == row && currentColIndex == startColIndex)
{
cellNode = do_QueryInterface(cell);
res = nsEditor::AppendNodeToSelectionAsRange(cellNode);
res = AppendNodeToSelectionAsRange(cellNode);
if (NS_FAILED(res)) break;
cellSelected = PR_TRUE;
}
@ -1316,7 +1317,7 @@ nsHTMLEditor::SelectTableColumn()
if (!cellSelected)
{
cellNode = do_QueryInterface(startCell);
return nsEditor::AppendNodeToSelectionAsRange(cellNode);
return AppendNodeToSelectionAsRange(cellNode);
}
return res;
}
@ -1504,33 +1505,26 @@ nsHTMLEditor::SwitchTableCellHeaderType(nsIDOMElement *aSourceCell, nsIDOMElemen
{
if (!aSourceCell) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMElement> sourceCell = aSourceCell;
nsCOMPtr<nsIDOMElement> newCell;
nsAutoString tagName;
nsEditor::GetTagString(aSourceCell, tagName);
nsAutoEditBatch beginBatching(this);
nsCOMPtr<nsIDOMNode> sourceNode = do_QueryInterface(aSourceCell);
nsCOMPtr<nsIDOMNode> newNode;
// Set to the opposite of current type
PRBool headerType = (tagName == NS_ConvertASCIItoUCS2("td"));
// Create the new cell, inserting it just before existing cell
// Just assume colspan and rowspan = 1 (we'll copy real values with CloneAttributes)
nsresult res = InsertCell(aSourceCell, 1, 1, PR_TRUE, headerType, getter_AddRefs(newCell));
if (NS_FAILED(res)) return res;
if (!newCell) return res;
// Copy all of the original attributes to the new cell
nsCOMPtr<nsIDOMNode> sourceCellNode = do_QueryInterface(sourceCell);
nsCOMPtr<nsIDOMNode> newCellNode = do_QueryInterface(newCell);
res = CloneAttributes(newCellNode, sourceCellNode);
if (NS_FAILED(res)) return res;
// Move all contents from original cell to new cell then delete original (3rd param = PR_TRUE)
res = MergeCells(newCell, sourceCell, PR_TRUE);
nsAutoString tagName;
GetTagString(aSourceCell, tagName);
nsString newCellType = (tagName == NS_LITERAL_STRING("td")) ? NS_LITERAL_STRING("th") : NS_LITERAL_STRING("td");
// This creates new node, moves children, copies attributes (PR_TRUE)
// and manages the selection!
nsresult res = ReplaceContainer(sourceNode, &newNode, newCellType, nsnull, nsnull, PR_TRUE);
if (NS_FAILED(res)) return res;
if (!newNode) return NS_ERROR_FAILURE;
// Return the new cell
if (aNewCell)
{
*aNewCell = newCell.get();
nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(newNode);
*aNewCell = newElement;
NS_ADDREF(*aNewCell);
}
@ -1826,6 +1820,7 @@ nsHTMLEditor::MergeCells(nsCOMPtr<nsIDOMElement> aTargetCell,
// Get index of last child in target cell
nsCOMPtr<nsIDOMNodeList> childNodes;
nsCOMPtr<nsIDOMNode> cellChild;
res = targetCell->GetChildNodes(getter_AddRefs(childNodes));
// If we fail or don't have children,
// we insert at index 0
@ -1837,10 +1832,20 @@ nsHTMLEditor::MergeCells(nsCOMPtr<nsIDOMElement> aTargetCell,
PRUint32 len;
res = childNodes->GetLength(&len);
if (NS_FAILED(res)) return res;
insertIndex = (PRInt32)len;
if (len == 1 && IsEmptyCell(aTargetCell))
{
if (IsEmptyCell(aTargetCell))
{
// Delete the empty node
nsCOMPtr<nsIDOMNode> tempNode;
DeleteNode(cellChild);
insertIndex = 0;
}
}
else
insertIndex = (PRInt32)len;
}
nsCOMPtr<nsIDOMNode> cellChild;
res = cellToMerge->GetFirstChild(getter_AddRefs(cellChild));
if (NS_FAILED(res)) return res;
while (cellChild)
@ -1849,10 +1854,10 @@ nsHTMLEditor::MergeCells(nsCOMPtr<nsIDOMElement> aTargetCell,
res = cellChild->GetNextSibling(getter_AddRefs(nextChild));
if (NS_FAILED(res)) return res;
res = nsEditor::DeleteNode(cellChild);
res = DeleteNode(cellChild);
if (NS_FAILED(res)) return res;
res = nsEditor::InsertNode(cellChild, targetCell, insertIndex);
res = InsertNode(cellChild, targetCell, insertIndex);
if (NS_FAILED(res)) return res;
cellChild = nextChild;
@ -1922,7 +1927,7 @@ nsHTMLEditor::NormalizeTable(nsIDOMElement *aTable)
{
nsCOMPtr<nsIDOMElement> table;
nsresult res = NS_ERROR_FAILURE;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), aTable, getter_AddRefs(table));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aTable, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
// Don't fail if we didn't find a table
if (!table) return NS_OK;
@ -2002,7 +2007,7 @@ nsHTMLEditor::GetCellIndexes(nsIDOMElement *aCell, PRInt32 &aRowIndex, PRInt32 &
{
// Get the selected cell or the cell enclosing the selection anchor
nsCOMPtr<nsIDOMElement> cell;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("td"), nsnull, getter_AddRefs(cell));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nsnull, getter_AddRefs(cell));
if (NS_SUCCEEDED(res) && cell)
aCell = cell;
else
@ -2030,7 +2035,7 @@ nsHTMLEditor::GetTableLayoutObject(nsIDOMElement* aTable, nsITableLayout **table
// frames are not ref counted, so don't use an nsCOMPtr
nsISupports *layoutObject=nsnull;
nsresult res = nsHTMLEditor::GetLayoutObject(aTable, &layoutObject);
nsresult res = GetLayoutObject(aTable, &layoutObject);
if (NS_FAILED(res)) return res;
if (!layoutObject) return NS_ERROR_FAILURE;
return layoutObject->QueryInterface(NS_GET_IID(nsITableLayout),
@ -2079,7 +2084,7 @@ nsHTMLEditor::GetTableSize(nsIDOMElement *aTable, PRInt32& aRowCount, PRInt32& a
aColCount = 0;
nsCOMPtr<nsIDOMElement> table;
// Get the selected talbe or the table enclosing the selection anchor
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), aTable, getter_AddRefs(table));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aTable, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
if (!table) return NS_ERROR_FAILURE;
@ -2114,7 +2119,7 @@ nsHTMLEditor::GetCellDataAt(nsIDOMElement* aTable, PRInt32 aRowIndex, PRInt32 aC
{
// Get the selected table or the table enclosing the selection anchor
nsCOMPtr<nsIDOMElement> table;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), nsnull, getter_AddRefs(table));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), nsnull, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
if (table)
aTable = table;
@ -2181,7 +2186,7 @@ nsHTMLEditor::GetCellContext(nsIDOMSelection **aSelection,
if (aColIndex) *aColIndex = 0;
nsCOMPtr <nsIDOMSelection> selection;
nsresult res = nsEditor::GetSelection(getter_AddRefs(selection));
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_FAILURE;
@ -2202,10 +2207,28 @@ nsHTMLEditor::GetCellContext(nsIDOMSelection **aSelection,
// or get the enclosing by a cell
if (!cell)
{
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("td"), nsnull, getter_AddRefs(cell));
// Find a selected or enclosing table element
nsCOMPtr<nsIDOMElement> cellOrTableElement;
PRInt32 selectedCount;
nsAutoString tagName;
nsresult res = GetSelectedOrParentTableElement(*getter_AddRefs(cellOrTableElement), tagName, selectedCount);
if (NS_FAILED(res)) return res;
if (tagName == NS_LITERAL_STRING("table"))
{
// We have a selected table, not a cell
if (aTable)
{
*aTable = cellOrTableElement.get();
NS_ADDREF(*aTable);
}
return NS_OK;
}
// Don't fail if we are not in a cell
if (!cell) return NS_EDITOR_ELEMENT_NOT_FOUND;
if (tagName != NS_LITERAL_STRING("td"))
return NS_EDITOR_ELEMENT_NOT_FOUND;
// We found a cell
cell = cellOrTableElement;
}
if (aCell)
{
@ -2214,7 +2237,7 @@ nsHTMLEditor::GetCellContext(nsIDOMSelection **aSelection,
}
// Get containing table
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), cell, getter_AddRefs(table));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), cell, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
// Cell must be in a table, so fail if not found
if (!table) return NS_ERROR_FAILURE;
@ -2261,7 +2284,7 @@ nsHTMLEditor::GetFirstSelectedCell(nsIDOMElement **aCell, nsIDOMRange **aRange)
if (aRange) *aRange = nsnull;
nsCOMPtr<nsIDOMSelection> selection;
nsresult res = nsEditor::GetSelection(getter_AddRefs(selection));
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_FAILURE;
@ -2307,7 +2330,7 @@ nsHTMLEditor::GetNextSelectedCell(nsIDOMElement **aCell, nsIDOMRange **aRange)
if (aRange) *aRange = nsnull;
nsCOMPtr<nsIDOMSelection> selection;
nsresult res = nsEditor::GetSelection(getter_AddRefs(selection));
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_FAILURE;
@ -2331,7 +2354,7 @@ nsHTMLEditor::GetNextSelectedCell(nsIDOMElement **aCell, nsIDOMRange **aRange)
if (!range) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMNode> cellNode;
res = nsEditor::GetFirstNodeInRange(range, getter_AddRefs(cellNode));
res = GetFirstNodeInRange(range, getter_AddRefs(cellNode));
if (NS_FAILED(res)) return res;
if (!cellNode) return NS_ERROR_FAILURE;
if (IsTableCell(cellNode))
@ -2421,7 +2444,7 @@ nsHTMLEditor::SetSelectionAfterTableEdit(nsIDOMElement* aTable, PRInt32 aRow, PR
if (!aTable) return res;
nsCOMPtr<nsIDOMSelection>selection;
res = nsEditor::GetSelection(getter_AddRefs(selection));
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection)
@ -2514,75 +2537,91 @@ nsHTMLEditor::GetSelectedOrParentTableElement(nsIDOMElement* &aTableElement, nsS
aSelectedCount = 0;
nsCOMPtr<nsIDOMSelection> selection;
nsresult res = nsEditor::GetSelection(getter_AddRefs(selection));
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_FAILURE;
nsAutoString tableName; tableName.AssignWithConversion("table");
nsAutoString trName; trName.AssignWithConversion("tr");
nsAutoString tdName; tdName.AssignWithConversion("td");
nsCOMPtr<nsIDOMNode> anchorNode;
res = selection->GetAnchorNode(getter_AddRefs(anchorNode));
if(NS_FAILED(res)) return res;
if (!anchorNode) return NS_ERROR_FAILURE;
// Try to get the first selected cell
nsCOMPtr<nsIDOMElement> tableOrCellElement;
res = GetFirstSelectedCell(getter_AddRefs(tableOrCellElement), nsnull);
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMElement> tableElement;
nsCOMPtr<nsIDOMNode> selectedNode;
// Get child of anchor node, if exists
PRBool hasChildren;
anchorNode->HasChildNodes(&hasChildren);
if (hasChildren)
if (tableOrCellElement)
{
PRInt32 anchorOffset;
res = selection->GetAnchorOffset(&anchorOffset);
if (NS_FAILED(res)) return res;
selectedNode = nsEditor::GetChildAt(anchorNode, anchorOffset);
if (!selectedNode)
{
selectedNode = anchorNode;
// If anchor doesn't have a child, we can't be selecting a table element,
// so don't do the following:
} else {
nsAutoString tag;
nsEditor::GetTagString(selectedNode,tag);
if (tag == tdName)
{
tableElement = do_QueryInterface(selectedNode);
aTagName = tdName;
// Each cell is in its own selection range,
// so count signals multiple-cell selection
res = selection->GetRangeCount(&aSelectedCount);
if (NS_FAILED(res)) return res;
}
else if(tag == tableName)
{
tableElement = do_QueryInterface(selectedNode);
aTagName = tableName;
aSelectedCount = 1;
}
else if(tag == trName)
{
tableElement = do_QueryInterface(selectedNode);
aTagName = trName;
aSelectedCount = 1;
}
}
}
if (!tableElement)
{
// Didn't find a table element -- find a cell parent
res = GetElementOrParentByTagName(tdName, anchorNode, getter_AddRefs(tableElement));
if(NS_FAILED(res)) return res;
if (tableElement)
// Each cell is in its own selection range,
// so count signals multiple-cell selection
res = selection->GetRangeCount(&aSelectedCount);
if (NS_FAILED(res)) return res;
aTagName = tdName;
}
if (tableElement)
else
{
aTableElement = tableElement.get();
nsAutoString tableName; tableName.AssignWithConversion("table");
nsAutoString trName; trName.AssignWithConversion("tr");
nsCOMPtr<nsIDOMNode> anchorNode;
res = selection->GetAnchorNode(getter_AddRefs(anchorNode));
if(NS_FAILED(res)) return res;
if (!anchorNode) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMNode> selectedNode;
// Get child of anchor node, if exists
PRBool hasChildren;
anchorNode->HasChildNodes(&hasChildren);
if (hasChildren)
{
PRInt32 anchorOffset;
res = selection->GetAnchorOffset(&anchorOffset);
if (NS_FAILED(res)) return res;
selectedNode = GetChildAt(anchorNode, anchorOffset);
if (!selectedNode)
{
selectedNode = anchorNode;
// If anchor doesn't have a child, we can't be selecting a table element,
// so don't do the following:
} else {
nsAutoString tag;
GetTagString(selectedNode,tag);
if (tag == tdName)
{
tableOrCellElement = do_QueryInterface(selectedNode);
aTagName = tdName;
// Each cell is in its own selection range,
// so count signals multiple-cell selection
res = selection->GetRangeCount(&aSelectedCount);
if (NS_FAILED(res)) return res;
}
else if(tag == tableName)
{
tableOrCellElement = do_QueryInterface(selectedNode);
aTagName = tableName;
aSelectedCount = 1;
}
else if(tag == trName)
{
tableOrCellElement = do_QueryInterface(selectedNode);
aTagName = trName;
aSelectedCount = 1;
}
}
}
if (!tableOrCellElement)
{
// Didn't find a table element -- find a cell parent
res = GetElementOrParentByTagName(tdName, anchorNode, getter_AddRefs(tableOrCellElement));
if(NS_FAILED(res)) return res;
if (tableOrCellElement)
aTagName = tdName;
}
}
if (tableOrCellElement)
{
aTableElement = tableOrCellElement.get();
NS_ADDREF(aTableElement);
}
return res;
@ -2611,7 +2650,7 @@ nsHTMLEditor::GetSelectedCellsType(nsIDOMElement *aElement, PRUint32 &aSelection
// (if aElement is null, this uses selection's anchor node)
nsCOMPtr<nsIDOMElement> table;
nsresult res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), aElement, getter_AddRefs(table));
nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aElement, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
PRInt32 rowCount, colCount;
@ -2742,3 +2781,31 @@ nsHTMLEditor::AllCellsInColumnSelected(nsIDOMElement *aTable, PRInt32 aColIndex,
}
return PR_TRUE;
}
PRBool
nsHTMLEditor::IsEmptyCell(nsIDOMElement *aCell)
{
nsCOMPtr<nsIDOMNode> cellChild;
// Check if target only contains empty text node or <br>
nsresult res = aCell->GetFirstChild(getter_AddRefs(cellChild));
if (NS_FAILED(res)) return res;
if (cellChild)
{
nsCOMPtr<nsIDOMNode> nextChild;
res = cellChild->GetNextSibling(getter_AddRefs(nextChild));
if (!nextChild)
{
// We insert a single break into a cell by default
// to have some place to locate a cursor -- it is dispensable
PRBool isEmpty = nsHTMLEditUtils::IsBreak(cellChild);
// Or check if no real content
if (!isEmpty)
IsEmptyNode(cellChild, &isEmpty, PR_FALSE, PR_FALSE);
return isEmpty;
}
}
return PR_FALSE;
}

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

@ -418,7 +418,7 @@ nsTextEditRules::GetTopEnclosingPre(nsIDOMNode *aNode,
return res;
}
nsresult
nsresult
nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled)
{
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
@ -487,7 +487,7 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
if (outLeftNode)
{
res = IsEmptyNode(outLeftNode, &bIsEmptyNode, PR_TRUE, PR_FALSE);
res = mEditor->IsEmptyNode(outLeftNode, &bIsEmptyNode, PR_TRUE, PR_FALSE);
if (NS_FAILED(res)) return res;
if (bIsEmptyNode) mEditor->DeleteNode(outLeftNode);
}
@ -501,7 +501,7 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
mEditor->DeleteNode(firstNode);
}
res = IsEmptyNode(outRightNode, &bIsEmptyNode, PR_TRUE, PR_FALSE);
res = mEditor->IsEmptyNode(outRightNode, &bIsEmptyNode, PR_TRUE, PR_FALSE);
if (NS_FAILED(res)) return res;
if (bIsEmptyNode) mEditor->DeleteNode(outRightNode);
}
@ -685,7 +685,7 @@ nsTextEditRules::WillInsertText(PRInt32 aAction,
if (isPRE)
{
char newlineChar = '\n';
while (unicodeBuf && (pos != -1) && (pos < outString->Length()))
while (unicodeBuf && (pos != -1) && ((PRUint32)pos < outString->Length()))
{
PRInt32 oldPos = pos;
PRInt32 subStrLen;
@ -723,7 +723,7 @@ nsTextEditRules::WillInsertText(PRInt32 aAction,
{
char specialChars[] = {'\t','\n',0};
nsAutoString tabString; tabString.AssignWithConversion(" ");
while (unicodeBuf && (pos != -1) && (pos < outString->Length()))
while (unicodeBuf && (pos != -1) && ((PRUint32)pos < outString->Length()))
{
PRInt32 oldPos = pos;
PRInt32 subStrLen;
@ -1334,106 +1334,6 @@ nsTextEditRules::CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<ns
return res;
}
///////////////////////////////////////////////////////////////////////////
// IsEmptyNode: figure out if aNode is an empty node.
// A block can have children and still be considered empty,
// if the children are empty or non-editable.
//
nsresult
nsTextEditRules::IsEmptyNode( nsIDOMNode *aNode,
PRBool *outIsEmptyNode,
PRBool aMozBRDoesntCount,
PRBool aListItemsNotEmpty)
{
if (!aNode || !outIsEmptyNode) return NS_ERROR_NULL_POINTER;
*outIsEmptyNode = PR_TRUE;
// effeciency hack - special case if it's a text node
if (nsEditor::IsTextNode(aNode))
{
PRUint32 length = 0;
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
nodeAsText = do_QueryInterface(aNode);
nodeAsText->GetLength(&length);
if (length) *outIsEmptyNode = PR_FALSE;
return NS_OK;
}
// if it's not a text node (handled above) and it's not a container,
// then we dont call it empty (it's an <hr>, or <br>, etc).
// Also, if it's an anchor then dont treat it as empty - even though
// anchors are containers, named anchors are "empty" but we don't
// want to treat them as such. Also, don't call ListItems or table
// cells empty if caller desires.
if (!mEditor->IsContainer(aNode) || nsHTMLEditUtils::IsAnchor(aNode) ||
(aListItemsNotEmpty && nsHTMLEditUtils::IsListItem(aNode)) ||
(aListItemsNotEmpty && nsHTMLEditUtils::IsTableCell(aNode)) )
{
*outIsEmptyNode = PR_FALSE;
return NS_OK;
}
// iterate over node. if no children, or all children are either
// empty text nodes or non-editable, then node qualifies as empty
nsCOMPtr<nsIContentIterator> iter;
nsCOMPtr<nsIContent> nodeAsContent = do_QueryInterface(aNode);
if (!nodeAsContent) return NS_ERROR_FAILURE;
nsresult res = nsComponentManager::CreateInstance(kContentIteratorCID,
nsnull,
NS_GET_IID(nsIContentIterator),
getter_AddRefs(iter));
if (NS_FAILED(res)) return res;
res = iter->Init(nodeAsContent);
if (NS_FAILED(res)) return res;
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;
// is the node editable and non-empty? if so, return false
if (mEditor->IsEditable(node))
{
if (nsEditor::IsTextNode(node))
{
PRUint32 length = 0;
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
nodeAsText = do_QueryInterface(node);
nodeAsText->GetLength(&length);
if (length) *outIsEmptyNode = PR_FALSE;
}
else // an editable, non-text node. we aren't an empty block
{
// is it the node we are iterating over?
if (node.get() == aNode) break;
// is it a moz-BR and did the caller ask us not to consider those relevant?
if (!(aMozBRDoesntCount && nsHTMLEditUtils::IsMozBR(node)))
{
// is it an empty node of some sort?
PRBool isEmptyNode;
res = IsEmptyNode(node, &isEmptyNode, aMozBRDoesntCount, aListItemsNotEmpty);
if (NS_FAILED(res)) return res;
if (!isEmptyNode)
{
// otherwise it ain't empty
*outIsEmptyNode = PR_FALSE;
break;
}
}
}
}
res = iter->Next();
if (NS_FAILED(res)) return res;
}
return NS_OK;
}
PRBool
nsTextEditRules::DeleteEmptyTextNode(nsIDOMNode *aNode)
{

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

@ -161,11 +161,6 @@ protected:
nsresult CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outBRNode);
nsresult IsEmptyNode(nsIDOMNode *aNode,
PRBool *outIsEmptyBlock,
PRBool aMozBRDoesntCount = PR_FALSE,
PRBool aListItemsNotEmpty = PR_FALSE);
PRBool DeleteEmptyTextNode(nsIDOMNode *aNode);
nsresult AdjustSelection(nsIDOMSelection *aSelection, nsIEditor::EDirection aDirection);

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

@ -1820,7 +1820,8 @@ nsEditor::ReplaceContainer(nsIDOMNode *inNode,
nsCOMPtr<nsIDOMNode> *outNode,
const nsString &aNodeType,
const nsString *aAttribute,
const nsString *aValue)
const nsString *aValue,
PRBool aCloneAttributes)
{
if (!inNode || !outNode)
return NS_ERROR_NULL_POINTER;
@ -1851,14 +1852,32 @@ nsEditor::ReplaceContainer(nsIDOMNode *inNode,
res = elem->SetAttribute(*aAttribute, *aValue);
if (NS_FAILED(res)) return res;
}
if (aCloneAttributes)
{
nsCOMPtr<nsIDOMNode>newNode = do_QueryInterface(elem);
res = CloneAttributes(newNode, inNode);
if (NS_FAILED(res)) return res;
}
// notify our internal selection state listener
nsAutoReplaceContainerSelNotify selStateNotify(mSavedSel, inNode, *outNode);
// insert new container into tree
res = InsertNode( *outNode, parent, offset);
if (NS_FAILED(res)) return res;
// We sometimes insert default <br> (like in a table cell),
// so save this to delete later
nsCOMPtr<nsIDOMNode> newNodeDefaultChild;
nsresult resFirstChild = (*outNode)->GetFirstChild(getter_AddRefs(newNodeDefaultChild));
// move children into new container
nsCOMPtr<nsIDOMNode> child;
/*
// This doesn't work when used with table cells!
PRBool bHasMoreChildren;
inNode->HasChildNodes(&bHasMoreChildren);
nsCOMPtr<nsIDOMNode> child;
while (bHasMoreChildren)
{
inNode->GetLastChild(getter_AddRefs(child));
@ -1868,14 +1887,35 @@ nsEditor::ReplaceContainer(nsIDOMNode *inNode,
if (NS_FAILED(res)) return res;
inNode->HasChildNodes(&bHasMoreChildren);
}
*/
// Insert at start of the new node
PRInt32 insertIndex = 0;
res = inNode->GetFirstChild(getter_AddRefs(child));
if (NS_FAILED(res)) return res;
while (child)
{
nsCOMPtr<nsIDOMNode> nextChild;
res = child->GetNextSibling(getter_AddRefs(nextChild));
if (NS_FAILED(res)) return res;
res = DeleteNode(child);
if (NS_FAILED(res)) return res;
res = InsertNode(child, *outNode, insertIndex);
if (NS_FAILED(res)) return res;
child = nextChild;
insertIndex++;
}
// Now that we have some real content in the new node,
// delete the default first child
// (We must do this AFTER moving the other nodes
// because rules would reinsert it if we did it first!)
if (NS_SUCCEEDED(resFirstChild) && newNodeDefaultChild)
DeleteNode(newNodeDefaultChild);
// delete old container
res = DeleteNode(inNode);
if (NS_FAILED(res)) return res;
// insert new container into tree
res = InsertNode( *outNode, parent, offset);
return res;
return DeleteNode(inNode);
}
///////////////////////////////////////////////////////////////////////////

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

@ -318,7 +318,9 @@ public:
nsCOMPtr<nsIDOMNode> *outNode,
const nsString &aNodeType,
const nsString *aAttribute = nsnull,
const nsString *aValue = nsnull);
const nsString *aValue = nsnull,
PRBool aCloneAttributes = PR_FALSE);
nsresult RemoveContainer(nsIDOMNode *inNode);
nsresult InsertContainerAbove(nsIDOMNode *inNode,
nsCOMPtr<nsIDOMNode> *outNode,

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

@ -1171,7 +1171,7 @@ nsHTMLEditRules::WillDeleteSelection(nsIDOMSelection *aSelection,
// see if we are in an "empty" node.
// Note: do NOT delete table elements this way.
PRBool bIsEmptyNode;
res = IsEmptyNode(node, &bIsEmptyNode, PR_TRUE, PR_FALSE);
res = mEditor->IsEmptyNode(node, &bIsEmptyNode, PR_TRUE, PR_FALSE);
if (bIsEmptyNode && !mEditor->IsTableElement(node))
nodeToDelete = node;
else
@ -1511,7 +1511,7 @@ nsHTMLEditRules::WillMakeList(nsIDOMSelection *aSelection,
else if (mEditor->IsInlineNode(curNode) && mEditor->IsContainer(curNode))
{
PRBool bEmpty;
res = IsEmptyNode( curNode, &bEmpty);
res = mEditor->IsEmptyNode(curNode, &bEmpty);
if (NS_FAILED(res)) return res;
if (bEmpty)
{
@ -2196,7 +2196,7 @@ nsHTMLEditRules::IsEmptyBlock(nsIDOMNode *aNode,
// looks like I forgot to finish this. Wonder what I was going to do?
if (!nodeToTest) return NS_ERROR_NULL_POINTER;
return IsEmptyNode(nodeToTest, outIsEmptyBlock,
return mEditor->IsEmptyNode(nodeToTest, outIsEmptyBlock,
aMozBRDoesntCount, aListItemsNotEmpty);
}
@ -3350,7 +3350,7 @@ nsHTMLEditRules::ReturnInHeader(nsIDOMSelection *aSelection,
if (prevItem && nsHTMLEditUtils::IsHeader(prevItem))
{
PRBool bIsEmptyNode;
res = IsEmptyNode(prevItem, &bIsEmptyNode);
res = mEditor->IsEmptyNode(prevItem, &bIsEmptyNode);
if (NS_FAILED(res)) return res;
if (bIsEmptyNode)
{
@ -3607,7 +3607,7 @@ nsHTMLEditRules::ReturnInListItem(nsIDOMSelection *aSelection,
if (prevItem && nsHTMLEditUtils::IsListItem(prevItem))
{
PRBool bIsEmptyNode;
res = IsEmptyNode(prevItem, &bIsEmptyNode);
res = mEditor->IsEmptyNode(prevItem, &bIsEmptyNode);
if (NS_FAILED(res)) return res;
if (bIsEmptyNode)
{
@ -4184,7 +4184,7 @@ nsHTMLEditRules::AdjustSpecialBreaks()
if (!node) return NS_ERROR_FAILURE;
PRBool bIsEmptyNode;
res = IsEmptyNode(node, &bIsEmptyNode, PR_FALSE, PR_FALSE);
res = mEditor->IsEmptyNode(node, &bIsEmptyNode, PR_FALSE, PR_FALSE);
if (NS_FAILED(res)) return res;
if (bIsEmptyNode
&& (nsHTMLEditUtils::IsListItem(node) || mEditor->IsTableCell(node)))
@ -4551,7 +4551,7 @@ nsHTMLEditRules::RemoveEmptyNodes()
if (!node) return NS_ERROR_FAILURE;
PRBool bIsEmptyNode;
res = IsEmptyNode(node, &bIsEmptyNode, PR_FALSE, PR_TRUE);
res = mEditor->IsEmptyNode(node, &bIsEmptyNode, PR_FALSE, PR_TRUE);
if (NS_FAILED(res)) return res;
if (bIsEmptyNode && !nsHTMLEditUtils::IsBody(node))
{
@ -4984,7 +4984,7 @@ nsHTMLEditRules::InsertMozBRIfNeeded(nsIDOMNode *aNode)
PRBool isEmpty;
nsCOMPtr<nsIDOMNode> brNode;
nsresult res = IsEmptyNode(aNode, &isEmpty);
nsresult res = mEditor->IsEmptyNode(aNode, &isEmpty);
if (NS_FAILED(res)) return res;
if (isEmpty)
{

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

@ -38,12 +38,15 @@ PRBool
nsHTMLEditUtils::IsBody(nsIDOMNode *node)
{
NS_PRECONDITION(node, "null node passed to nsHTMLEditUtils::IsBody");
nsAutoString tag;
nsEditor::GetTagString(node,tag);
tag.ToLowerCase();
if (tag.EqualsWithConversion("body"))
if (node)
{
return PR_TRUE;
nsAutoString tag;
nsEditor::GetTagString(node,tag);
tag.ToLowerCase();
if (tag.EqualsWithConversion("body"))
{
return PR_TRUE;
}
}
return PR_FALSE;
}

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

@ -7063,3 +7063,102 @@ nsHTMLEditor::GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOu
return res;
}
///////////////////////////////////////////////////////////////////////////
// IsEmptyNode: figure out if aNode is an empty node.
// A block can have children and still be considered empty,
// if the children are empty or non-editable.
//
nsresult
nsHTMLEditor::IsEmptyNode( nsIDOMNode *aNode,
PRBool *outIsEmptyNode,
PRBool aMozBRDoesntCount,
PRBool aListOrCellNotEmpty)
{
if (!aNode || !outIsEmptyNode) return NS_ERROR_NULL_POINTER;
*outIsEmptyNode = PR_TRUE;
// effeciency hack - special case if it's a text node
if (nsEditor::IsTextNode(aNode))
{
PRUint32 length = 0;
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
nodeAsText = do_QueryInterface(aNode);
nodeAsText->GetLength(&length);
if (length) *outIsEmptyNode = PR_FALSE;
return NS_OK;
}
// if it's not a text node (handled above) and it's not a container,
// then we dont call it empty (it's an <hr>, or <br>, etc).
// Also, if it's an anchor then dont treat it as empty - even though
// anchors are containers, named anchors are "empty" but we don't
// want to treat them as such. Also, don't call ListItems or table
// cells empty if caller desires.
if (!IsContainer(aNode) || nsHTMLEditUtils::IsAnchor(aNode) ||
(aListOrCellNotEmpty && nsHTMLEditUtils::IsListItem(aNode)) ||
(aListOrCellNotEmpty && nsHTMLEditUtils::IsTableCell(aNode)) )
{
*outIsEmptyNode = PR_FALSE;
return NS_OK;
}
// iterate over node. if no children, or all children are either
// empty text nodes or non-editable, then node qualifies as empty
nsCOMPtr<nsIContentIterator> iter;
nsCOMPtr<nsIContent> nodeAsContent = do_QueryInterface(aNode);
if (!nodeAsContent) return NS_ERROR_FAILURE;
nsresult res = nsComponentManager::CreateInstance(kCContentIteratorCID,
nsnull,
NS_GET_IID(nsIContentIterator),
getter_AddRefs(iter));
if (NS_FAILED(res)) return res;
res = iter->Init(nodeAsContent);
if (NS_FAILED(res)) return res;
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;
// is the node editable and non-empty? if so, return false
if (nsEditor::IsEditable(node))
{
if (nsEditor::IsTextNode(node))
{
PRUint32 length = 0;
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
nodeAsText = do_QueryInterface(node);
nodeAsText->GetLength(&length);
if (length) *outIsEmptyNode = PR_FALSE;
}
else // an editable, non-text node. we aren't an empty block
{
// is it the node we are iterating over?
if (node.get() == aNode) break;
// is it a moz-BR and did the caller ask us not to consider those relevant?
if (!(aMozBRDoesntCount && nsHTMLEditUtils::IsMozBR(node)))
{
// is it an empty node of some sort?
PRBool isEmptyNode;
res = IsEmptyNode(node, &isEmptyNode, aMozBRDoesntCount, aListOrCellNotEmpty);
if (NS_FAILED(res)) return res;
if (!isEmptyNode)
{
// otherwise it ain't empty
*outIsEmptyNode = PR_FALSE;
break;
}
}
}
}
res = iter->Next();
if (NS_FAILED(res)) return res;
}
return NS_OK;
}

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

@ -396,6 +396,8 @@ protected:
PRBool AllCellsInRowSelected(nsIDOMElement *aTable, PRInt32 aRowIndex, PRInt32 aNumberOfColumns);
PRBool AllCellsInColumnSelected(nsIDOMElement *aTable, PRInt32 aColIndex, PRInt32 aNumberOfRows);
PRBool IsEmptyCell(nsIDOMElement *aCell);
// Most insert methods need to get the same basic context data
// Any of the pointers may be null if you don't need that datum (for more efficiency)
// Input: *aCell is a known cell,
@ -549,6 +551,9 @@ protected:
nsresult IsLastEditableChild( nsIDOMNode *aNode, PRBool *aOutIsLast);
nsresult GetFirstEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutFirstChild);
nsresult GetLastEditableChild( nsIDOMNode *aNode, nsCOMPtr<nsIDOMNode> *aOutLastChild);
nsresult IsEmptyNode(nsIDOMNode *aNode, PRBool *outIsEmptyBlock,
PRBool aMozBRDoesntCount = PR_FALSE,
PRBool aListOrCellNotEmpty = PR_FALSE);
nsresult GetDOMEventReceiver(nsIDOMEventReceiver **aEventReceiver);

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

@ -44,6 +44,7 @@
#include "nsVoidArray.h"
#include "nsEditorUtils.h"
#include "nsHTMLEditUtils.h"
//#define DEBUG_TABLE 1
@ -120,9 +121,9 @@ nsHTMLEditor::InsertCell(nsIDOMElement *aCell, PRInt32 aRowSpan, PRInt32 aColSpa
nsCOMPtr<nsIDOMElement> newCell;
if (aIsHeader)
res = CreateElementWithDefaults(NS_ConvertASCIItoUCS2("th"), getter_AddRefs(newCell));
res = CreateElementWithDefaults(NS_LITERAL_STRING("th"), getter_AddRefs(newCell));
else
res = CreateElementWithDefaults(NS_ConvertASCIItoUCS2("td"), getter_AddRefs(newCell));
res = CreateElementWithDefaults(NS_LITERAL_STRING("td"), getter_AddRefs(newCell));
if(NS_FAILED(res)) return res;
if(!newCell) return NS_ERROR_FAILURE;
@ -137,19 +138,19 @@ nsHTMLEditor::InsertCell(nsIDOMElement *aCell, PRInt32 aRowSpan, PRInt32 aColSpa
{
nsAutoString newRowSpan(aRowSpan);
// Note: Do NOT use editor txt for this
newCell->SetAttribute(NS_ConvertASCIItoUCS2("rowspan"), newRowSpan);
newCell->SetAttribute(NS_LITERAL_STRING("rowspan"), newRowSpan);
}
if( aColSpan > 1)
{
nsAutoString newColSpan(aColSpan);
// Note: Do NOT use editor txt for this
newCell->SetAttribute(NS_ConvertASCIItoUCS2("colspan"), newColSpan);
newCell->SetAttribute(NS_LITERAL_STRING("colspan"), newColSpan);
}
if(aAfter) cellOffset++;
//Don't let Rules System change the selection
nsAutoTxnsConserveSelection dontChangeSelection(this);
return nsEditor::InsertNode(newCell, cellParent, cellOffset);
return InsertNode(newCell, cellParent, cellOffset);
}
PRBool IsRowNode(nsCOMPtr<nsIDOMNode> &aNode)
@ -221,11 +222,11 @@ nsHTMLEditor::InsertTableCell(PRInt32 aNumber, PRBool aAfter)
for (i = 0; i < aNumber; i++)
{
nsCOMPtr<nsIDOMElement> newCell;
res = CreateElementWithDefaults(NS_ConvertASCIItoUCS2("td"), getter_AddRefs(newCell));
res = CreateElementWithDefaults(NS_LITERAL_STRING("td"), getter_AddRefs(newCell));
if (NS_SUCCEEDED(res) && newCell)
{
if (aAfter) cellOffset++;
res = nsEditor::InsertNode(newCell, cellParent, cellOffset);
res = InsertNode(newCell, cellParent, cellOffset);
if(NS_FAILED(res)) break;
}
}
@ -238,7 +239,7 @@ nsHTMLEditor::GetFirstRow(nsIDOMElement* aTableElement, nsIDOMElement* &aRow)
aRow = nsnull;
nsCOMPtr<nsIDOMElement> tableElement;
nsresult res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), aTableElement, getter_AddRefs(tableElement));
nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aTableElement, getter_AddRefs(tableElement));
if (NS_FAILED(res)) return res;
if (!tableElement) return NS_ERROR_NULL_POINTER;
@ -303,7 +304,7 @@ nsHTMLEditor::GetNextRow(nsIDOMElement* aTableElement, nsIDOMElement* &aRow)
aRow = nsnull;
nsCOMPtr<nsIDOMElement> rowElement;
nsresult res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("tr"), aTableElement, getter_AddRefs(rowElement));
nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("tr"), aTableElement, getter_AddRefs(rowElement));
if (NS_FAILED(res)) return res;
if (!rowElement) return NS_ERROR_NULL_POINTER;
@ -498,7 +499,7 @@ nsHTMLEditor::InsertTableRow(PRInt32 aNumber, PRBool aAfter)
if (!curCell) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMElement> parentRow;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("tr"), curCell, getter_AddRefs(parentRow));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("tr"), curCell, getter_AddRefs(parentRow));
if (NS_FAILED(res)) return res;
if (!parentRow) return NS_ERROR_NULL_POINTER;
@ -596,7 +597,7 @@ nsHTMLEditor::InsertTableRow(PRInt32 aNumber, PRBool aAfter)
{
// Create a new row
nsCOMPtr<nsIDOMElement> newRow;
res = CreateElementWithDefaults(NS_ConvertASCIItoUCS2("tr"), getter_AddRefs(newRow));
res = CreateElementWithDefaults(NS_LITERAL_STRING("tr"), getter_AddRefs(newRow));
if (NS_SUCCEEDED(res))
{
if (!newRow) return NS_ERROR_FAILURE;
@ -604,7 +605,7 @@ nsHTMLEditor::InsertTableRow(PRInt32 aNumber, PRBool aAfter)
for (PRInt32 i = 0; i < cellsInRow; i++)
{
nsCOMPtr<nsIDOMElement> newCell;
res = CreateElementWithDefaults(NS_ConvertASCIItoUCS2("td"), getter_AddRefs(newCell));
res = CreateElementWithDefaults(NS_LITERAL_STRING("td"), getter_AddRefs(newCell));
if (NS_FAILED(res)) return res;
if (!newCell) return NS_ERROR_FAILURE;
@ -615,7 +616,7 @@ nsHTMLEditor::InsertTableRow(PRInt32 aNumber, PRBool aAfter)
}
// Use transaction system to insert the entire row+cells
// (Note that rows are inserted at same childoffset each time)
res = nsEditor::InsertNode(newRow, parentOfRow, newRowOffset);
res = InsertNode(newRow, parentOfRow, newRowOffset);
if (NS_FAILED(res)) return res;
}
}
@ -629,7 +630,7 @@ nsHTMLEditor::DeleteTable2(nsCOMPtr<nsIDOMElement> &aTable, nsCOMPtr<nsIDOMSelec
{
nsCOMPtr<nsIDOMNode> tableParent;
PRInt32 tableOffset;
if(NS_FAILED(aTable->GetParentNode(getter_AddRefs(tableParent))) || !tableParent)
if(!aTable || NS_FAILED(aTable->GetParentNode(getter_AddRefs(tableParent))) || !tableParent)
return NS_ERROR_FAILURE;
// Save offset we need to restore the selection
@ -669,7 +670,7 @@ nsHTMLEditor::DeleteTableCell(PRInt32 aNumber)
nsCOMPtr<nsIDOMElement> cell;
PRInt32 startRowIndex, startColIndex;
nsresult res = nsEditor::GetSelection(getter_AddRefs(selection));
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_FAILURE;
@ -689,7 +690,7 @@ nsHTMLEditor::DeleteTableCell(PRInt32 aNumber)
if (1 == GetNumberOfCellsInRow(table, startRowIndex))
{
nsCOMPtr<nsIDOMElement> parentRow;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("tr"), cell, getter_AddRefs(parentRow));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("tr"), cell, getter_AddRefs(parentRow));
if (NS_FAILED(res)) return res;
if (!parentRow) return NS_ERROR_NULL_POINTER;
@ -849,7 +850,7 @@ nsHTMLEditor::DeleteTableColumn(PRInt32 aNumber)
{
// Only 1 cell in row - delete the row
nsCOMPtr<nsIDOMElement> parentRow;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("tr"), cell, getter_AddRefs(parentRow));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("tr"), cell, getter_AddRefs(parentRow));
if (NS_FAILED(res)) return res;
if(!parentRow) return NS_ERROR_NULL_POINTER;
@ -972,7 +973,7 @@ nsHTMLEditor::DeleteTableRow(PRInt32 aNumber)
// Delete the row
nsCOMPtr<nsIDOMElement> parentRow;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("tr"), cell, getter_AddRefs(parentRow));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("tr"), cell, getter_AddRefs(parentRow));
if (NS_SUCCEEDED(res) && parentRow)
res = DeleteNode(parentRow);
if (NS_FAILED(res))
@ -992,7 +993,7 @@ nsHTMLEditor::SelectTable()
{
nsCOMPtr<nsIDOMElement> table;
nsresult res = NS_ERROR_FAILURE;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), nsnull, getter_AddRefs(table));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), nsnull, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
// Don't fail if we didn't find a table
if (!table) return NS_OK;
@ -1011,7 +1012,7 @@ NS_IMETHODIMP
nsHTMLEditor::SelectTableCell()
{
nsCOMPtr<nsIDOMElement> cell;
nsresult res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("td"), nsnull, getter_AddRefs(cell));
nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nsnull, getter_AddRefs(cell));
if (NS_FAILED(res)) return res;
// Don't fail if we didn't find a table
if (!cell) return NS_EDITOR_ELEMENT_NOT_FOUND;
@ -1032,17 +1033,17 @@ nsHTMLEditor::SelectBlockOfCells(nsIDOMElement *aStartCell, nsIDOMElement *aEndC
if (!aStartCell || !aEndCell) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMSelection> selection;
nsresult res = nsEditor::GetSelection(getter_AddRefs(selection));
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMElement> table;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), aStartCell, getter_AddRefs(table));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aStartCell, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
if (!table) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMElement> endTable;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), aEndCell, getter_AddRefs(endTable));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aEndCell, getter_AddRefs(endTable));
if (NS_FAILED(res)) return res;
if (!endTable) return NS_ERROR_FAILURE;
@ -1107,7 +1108,7 @@ nsHTMLEditor::SelectBlockOfCells(nsIDOMElement *aStartCell, nsIDOMElement *aEndC
if (!isSelected && cell && row == currentRowIndex && col == currentColIndex)
{
nsCOMPtr<nsIDOMNode> cellNode = do_QueryInterface(cell);
res = nsEditor::AppendNodeToSelectionAsRange(cellNode);
res = AppendNodeToSelectionAsRange(cellNode);
if (NS_FAILED(res)) break;
}
}
@ -1119,7 +1120,7 @@ NS_IMETHODIMP
nsHTMLEditor::SelectAllTableCells()
{
nsCOMPtr<nsIDOMElement> cell;
nsresult res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("td"), nsnull, getter_AddRefs(cell));
nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nsnull, getter_AddRefs(cell));
if (NS_FAILED(res)) return res;
// Don't fail if we didn't find a cell
@ -1131,7 +1132,7 @@ nsHTMLEditor::SelectAllTableCells()
// Get parent table
nsCOMPtr<nsIDOMElement> table;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), cell, getter_AddRefs(table));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), cell, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
if(!table) return NS_ERROR_NULL_POINTER;
@ -1140,7 +1141,7 @@ nsHTMLEditor::SelectAllTableCells()
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMSelection> selection;
res = nsEditor::GetSelection(getter_AddRefs(selection));
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_FAILURE;
@ -1168,7 +1169,7 @@ nsHTMLEditor::SelectAllTableCells()
if (cell && row == currentRowIndex && col == currentColIndex)
{
cellNode = do_QueryInterface(cell);
res = nsEditor::AppendNodeToSelectionAsRange(cellNode);
res = AppendNodeToSelectionAsRange(cellNode);
if (NS_FAILED(res)) break;
cellSelected = PR_TRUE;
}
@ -1178,7 +1179,7 @@ nsHTMLEditor::SelectAllTableCells()
if (!cellSelected)
{
cellNode = do_QueryInterface(startCell);
return nsEditor::AppendNodeToSelectionAsRange(cellNode);
return AppendNodeToSelectionAsRange(cellNode);
}
return res;
}
@ -1187,7 +1188,7 @@ NS_IMETHODIMP
nsHTMLEditor::SelectTableRow()
{
nsCOMPtr<nsIDOMElement> cell;
nsresult res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("td"), nsnull, getter_AddRefs(cell));
nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nsnull, getter_AddRefs(cell));
if (NS_FAILED(res)) return res;
// Don't fail if we didn't find a cell
@ -1240,7 +1241,7 @@ nsHTMLEditor::SelectTableRow()
if (cell && currentRowIndex == startRowIndex && currentColIndex == col)
{
cellNode = do_QueryInterface(cell);
res = nsEditor::AppendNodeToSelectionAsRange(cellNode);
res = AppendNodeToSelectionAsRange(cellNode);
if (NS_FAILED(res)) break;
cellSelected = PR_TRUE;
}
@ -1249,7 +1250,7 @@ nsHTMLEditor::SelectTableRow()
if (!cellSelected)
{
cellNode = do_QueryInterface(startCell);
return nsEditor::AppendNodeToSelectionAsRange(cellNode);
return AppendNodeToSelectionAsRange(cellNode);
}
return res;
}
@ -1258,7 +1259,7 @@ NS_IMETHODIMP
nsHTMLEditor::SelectTableColumn()
{
nsCOMPtr<nsIDOMElement> cell;
nsresult res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("td"), nsnull, getter_AddRefs(cell));
nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nsnull, getter_AddRefs(cell));
if (NS_FAILED(res)) return res;
// Don't fail if we didn't find a cell
@ -1307,7 +1308,7 @@ nsHTMLEditor::SelectTableColumn()
if (cell && currentRowIndex == row && currentColIndex == startColIndex)
{
cellNode = do_QueryInterface(cell);
res = nsEditor::AppendNodeToSelectionAsRange(cellNode);
res = AppendNodeToSelectionAsRange(cellNode);
if (NS_FAILED(res)) break;
cellSelected = PR_TRUE;
}
@ -1316,7 +1317,7 @@ nsHTMLEditor::SelectTableColumn()
if (!cellSelected)
{
cellNode = do_QueryInterface(startCell);
return nsEditor::AppendNodeToSelectionAsRange(cellNode);
return AppendNodeToSelectionAsRange(cellNode);
}
return res;
}
@ -1504,33 +1505,26 @@ nsHTMLEditor::SwitchTableCellHeaderType(nsIDOMElement *aSourceCell, nsIDOMElemen
{
if (!aSourceCell) return NS_ERROR_NULL_POINTER;
nsCOMPtr<nsIDOMElement> sourceCell = aSourceCell;
nsCOMPtr<nsIDOMElement> newCell;
nsAutoString tagName;
nsEditor::GetTagString(aSourceCell, tagName);
nsAutoEditBatch beginBatching(this);
nsCOMPtr<nsIDOMNode> sourceNode = do_QueryInterface(aSourceCell);
nsCOMPtr<nsIDOMNode> newNode;
// Set to the opposite of current type
PRBool headerType = (tagName == NS_ConvertASCIItoUCS2("td"));
// Create the new cell, inserting it just before existing cell
// Just assume colspan and rowspan = 1 (we'll copy real values with CloneAttributes)
nsresult res = InsertCell(aSourceCell, 1, 1, PR_TRUE, headerType, getter_AddRefs(newCell));
if (NS_FAILED(res)) return res;
if (!newCell) return res;
// Copy all of the original attributes to the new cell
nsCOMPtr<nsIDOMNode> sourceCellNode = do_QueryInterface(sourceCell);
nsCOMPtr<nsIDOMNode> newCellNode = do_QueryInterface(newCell);
res = CloneAttributes(newCellNode, sourceCellNode);
if (NS_FAILED(res)) return res;
// Move all contents from original cell to new cell then delete original (3rd param = PR_TRUE)
res = MergeCells(newCell, sourceCell, PR_TRUE);
nsAutoString tagName;
GetTagString(aSourceCell, tagName);
nsString newCellType = (tagName == NS_LITERAL_STRING("td")) ? NS_LITERAL_STRING("th") : NS_LITERAL_STRING("td");
// This creates new node, moves children, copies attributes (PR_TRUE)
// and manages the selection!
nsresult res = ReplaceContainer(sourceNode, &newNode, newCellType, nsnull, nsnull, PR_TRUE);
if (NS_FAILED(res)) return res;
if (!newNode) return NS_ERROR_FAILURE;
// Return the new cell
if (aNewCell)
{
*aNewCell = newCell.get();
nsCOMPtr<nsIDOMElement> newElement = do_QueryInterface(newNode);
*aNewCell = newElement;
NS_ADDREF(*aNewCell);
}
@ -1826,6 +1820,7 @@ nsHTMLEditor::MergeCells(nsCOMPtr<nsIDOMElement> aTargetCell,
// Get index of last child in target cell
nsCOMPtr<nsIDOMNodeList> childNodes;
nsCOMPtr<nsIDOMNode> cellChild;
res = targetCell->GetChildNodes(getter_AddRefs(childNodes));
// If we fail or don't have children,
// we insert at index 0
@ -1837,10 +1832,20 @@ nsHTMLEditor::MergeCells(nsCOMPtr<nsIDOMElement> aTargetCell,
PRUint32 len;
res = childNodes->GetLength(&len);
if (NS_FAILED(res)) return res;
insertIndex = (PRInt32)len;
if (len == 1 && IsEmptyCell(aTargetCell))
{
if (IsEmptyCell(aTargetCell))
{
// Delete the empty node
nsCOMPtr<nsIDOMNode> tempNode;
DeleteNode(cellChild);
insertIndex = 0;
}
}
else
insertIndex = (PRInt32)len;
}
nsCOMPtr<nsIDOMNode> cellChild;
res = cellToMerge->GetFirstChild(getter_AddRefs(cellChild));
if (NS_FAILED(res)) return res;
while (cellChild)
@ -1849,10 +1854,10 @@ nsHTMLEditor::MergeCells(nsCOMPtr<nsIDOMElement> aTargetCell,
res = cellChild->GetNextSibling(getter_AddRefs(nextChild));
if (NS_FAILED(res)) return res;
res = nsEditor::DeleteNode(cellChild);
res = DeleteNode(cellChild);
if (NS_FAILED(res)) return res;
res = nsEditor::InsertNode(cellChild, targetCell, insertIndex);
res = InsertNode(cellChild, targetCell, insertIndex);
if (NS_FAILED(res)) return res;
cellChild = nextChild;
@ -1922,7 +1927,7 @@ nsHTMLEditor::NormalizeTable(nsIDOMElement *aTable)
{
nsCOMPtr<nsIDOMElement> table;
nsresult res = NS_ERROR_FAILURE;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), aTable, getter_AddRefs(table));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aTable, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
// Don't fail if we didn't find a table
if (!table) return NS_OK;
@ -2002,7 +2007,7 @@ nsHTMLEditor::GetCellIndexes(nsIDOMElement *aCell, PRInt32 &aRowIndex, PRInt32 &
{
// Get the selected cell or the cell enclosing the selection anchor
nsCOMPtr<nsIDOMElement> cell;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("td"), nsnull, getter_AddRefs(cell));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("td"), nsnull, getter_AddRefs(cell));
if (NS_SUCCEEDED(res) && cell)
aCell = cell;
else
@ -2030,7 +2035,7 @@ nsHTMLEditor::GetTableLayoutObject(nsIDOMElement* aTable, nsITableLayout **table
// frames are not ref counted, so don't use an nsCOMPtr
nsISupports *layoutObject=nsnull;
nsresult res = nsHTMLEditor::GetLayoutObject(aTable, &layoutObject);
nsresult res = GetLayoutObject(aTable, &layoutObject);
if (NS_FAILED(res)) return res;
if (!layoutObject) return NS_ERROR_FAILURE;
return layoutObject->QueryInterface(NS_GET_IID(nsITableLayout),
@ -2079,7 +2084,7 @@ nsHTMLEditor::GetTableSize(nsIDOMElement *aTable, PRInt32& aRowCount, PRInt32& a
aColCount = 0;
nsCOMPtr<nsIDOMElement> table;
// Get the selected talbe or the table enclosing the selection anchor
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), aTable, getter_AddRefs(table));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aTable, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
if (!table) return NS_ERROR_FAILURE;
@ -2114,7 +2119,7 @@ nsHTMLEditor::GetCellDataAt(nsIDOMElement* aTable, PRInt32 aRowIndex, PRInt32 aC
{
// Get the selected table or the table enclosing the selection anchor
nsCOMPtr<nsIDOMElement> table;
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), nsnull, getter_AddRefs(table));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), nsnull, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
if (table)
aTable = table;
@ -2181,7 +2186,7 @@ nsHTMLEditor::GetCellContext(nsIDOMSelection **aSelection,
if (aColIndex) *aColIndex = 0;
nsCOMPtr <nsIDOMSelection> selection;
nsresult res = nsEditor::GetSelection(getter_AddRefs(selection));
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_FAILURE;
@ -2202,10 +2207,28 @@ nsHTMLEditor::GetCellContext(nsIDOMSelection **aSelection,
// or get the enclosing by a cell
if (!cell)
{
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("td"), nsnull, getter_AddRefs(cell));
// Find a selected or enclosing table element
nsCOMPtr<nsIDOMElement> cellOrTableElement;
PRInt32 selectedCount;
nsAutoString tagName;
nsresult res = GetSelectedOrParentTableElement(*getter_AddRefs(cellOrTableElement), tagName, selectedCount);
if (NS_FAILED(res)) return res;
if (tagName == NS_LITERAL_STRING("table"))
{
// We have a selected table, not a cell
if (aTable)
{
*aTable = cellOrTableElement.get();
NS_ADDREF(*aTable);
}
return NS_OK;
}
// Don't fail if we are not in a cell
if (!cell) return NS_EDITOR_ELEMENT_NOT_FOUND;
if (tagName != NS_LITERAL_STRING("td"))
return NS_EDITOR_ELEMENT_NOT_FOUND;
// We found a cell
cell = cellOrTableElement;
}
if (aCell)
{
@ -2214,7 +2237,7 @@ nsHTMLEditor::GetCellContext(nsIDOMSelection **aSelection,
}
// Get containing table
res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), cell, getter_AddRefs(table));
res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), cell, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
// Cell must be in a table, so fail if not found
if (!table) return NS_ERROR_FAILURE;
@ -2261,7 +2284,7 @@ nsHTMLEditor::GetFirstSelectedCell(nsIDOMElement **aCell, nsIDOMRange **aRange)
if (aRange) *aRange = nsnull;
nsCOMPtr<nsIDOMSelection> selection;
nsresult res = nsEditor::GetSelection(getter_AddRefs(selection));
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_FAILURE;
@ -2307,7 +2330,7 @@ nsHTMLEditor::GetNextSelectedCell(nsIDOMElement **aCell, nsIDOMRange **aRange)
if (aRange) *aRange = nsnull;
nsCOMPtr<nsIDOMSelection> selection;
nsresult res = nsEditor::GetSelection(getter_AddRefs(selection));
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_FAILURE;
@ -2331,7 +2354,7 @@ nsHTMLEditor::GetNextSelectedCell(nsIDOMElement **aCell, nsIDOMRange **aRange)
if (!range) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMNode> cellNode;
res = nsEditor::GetFirstNodeInRange(range, getter_AddRefs(cellNode));
res = GetFirstNodeInRange(range, getter_AddRefs(cellNode));
if (NS_FAILED(res)) return res;
if (!cellNode) return NS_ERROR_FAILURE;
if (IsTableCell(cellNode))
@ -2421,7 +2444,7 @@ nsHTMLEditor::SetSelectionAfterTableEdit(nsIDOMElement* aTable, PRInt32 aRow, PR
if (!aTable) return res;
nsCOMPtr<nsIDOMSelection>selection;
res = nsEditor::GetSelection(getter_AddRefs(selection));
res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection)
@ -2514,75 +2537,91 @@ nsHTMLEditor::GetSelectedOrParentTableElement(nsIDOMElement* &aTableElement, nsS
aSelectedCount = 0;
nsCOMPtr<nsIDOMSelection> selection;
nsresult res = nsEditor::GetSelection(getter_AddRefs(selection));
nsresult res = GetSelection(getter_AddRefs(selection));
if (NS_FAILED(res)) return res;
if (!selection) return NS_ERROR_FAILURE;
nsAutoString tableName; tableName.AssignWithConversion("table");
nsAutoString trName; trName.AssignWithConversion("tr");
nsAutoString tdName; tdName.AssignWithConversion("td");
nsCOMPtr<nsIDOMNode> anchorNode;
res = selection->GetAnchorNode(getter_AddRefs(anchorNode));
if(NS_FAILED(res)) return res;
if (!anchorNode) return NS_ERROR_FAILURE;
// Try to get the first selected cell
nsCOMPtr<nsIDOMElement> tableOrCellElement;
res = GetFirstSelectedCell(getter_AddRefs(tableOrCellElement), nsnull);
if (NS_FAILED(res)) return res;
nsCOMPtr<nsIDOMElement> tableElement;
nsCOMPtr<nsIDOMNode> selectedNode;
// Get child of anchor node, if exists
PRBool hasChildren;
anchorNode->HasChildNodes(&hasChildren);
if (hasChildren)
if (tableOrCellElement)
{
PRInt32 anchorOffset;
res = selection->GetAnchorOffset(&anchorOffset);
if (NS_FAILED(res)) return res;
selectedNode = nsEditor::GetChildAt(anchorNode, anchorOffset);
if (!selectedNode)
{
selectedNode = anchorNode;
// If anchor doesn't have a child, we can't be selecting a table element,
// so don't do the following:
} else {
nsAutoString tag;
nsEditor::GetTagString(selectedNode,tag);
if (tag == tdName)
{
tableElement = do_QueryInterface(selectedNode);
aTagName = tdName;
// Each cell is in its own selection range,
// so count signals multiple-cell selection
res = selection->GetRangeCount(&aSelectedCount);
if (NS_FAILED(res)) return res;
}
else if(tag == tableName)
{
tableElement = do_QueryInterface(selectedNode);
aTagName = tableName;
aSelectedCount = 1;
}
else if(tag == trName)
{
tableElement = do_QueryInterface(selectedNode);
aTagName = trName;
aSelectedCount = 1;
}
}
}
if (!tableElement)
{
// Didn't find a table element -- find a cell parent
res = GetElementOrParentByTagName(tdName, anchorNode, getter_AddRefs(tableElement));
if(NS_FAILED(res)) return res;
if (tableElement)
// Each cell is in its own selection range,
// so count signals multiple-cell selection
res = selection->GetRangeCount(&aSelectedCount);
if (NS_FAILED(res)) return res;
aTagName = tdName;
}
if (tableElement)
else
{
aTableElement = tableElement.get();
nsAutoString tableName; tableName.AssignWithConversion("table");
nsAutoString trName; trName.AssignWithConversion("tr");
nsCOMPtr<nsIDOMNode> anchorNode;
res = selection->GetAnchorNode(getter_AddRefs(anchorNode));
if(NS_FAILED(res)) return res;
if (!anchorNode) return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMNode> selectedNode;
// Get child of anchor node, if exists
PRBool hasChildren;
anchorNode->HasChildNodes(&hasChildren);
if (hasChildren)
{
PRInt32 anchorOffset;
res = selection->GetAnchorOffset(&anchorOffset);
if (NS_FAILED(res)) return res;
selectedNode = GetChildAt(anchorNode, anchorOffset);
if (!selectedNode)
{
selectedNode = anchorNode;
// If anchor doesn't have a child, we can't be selecting a table element,
// so don't do the following:
} else {
nsAutoString tag;
GetTagString(selectedNode,tag);
if (tag == tdName)
{
tableOrCellElement = do_QueryInterface(selectedNode);
aTagName = tdName;
// Each cell is in its own selection range,
// so count signals multiple-cell selection
res = selection->GetRangeCount(&aSelectedCount);
if (NS_FAILED(res)) return res;
}
else if(tag == tableName)
{
tableOrCellElement = do_QueryInterface(selectedNode);
aTagName = tableName;
aSelectedCount = 1;
}
else if(tag == trName)
{
tableOrCellElement = do_QueryInterface(selectedNode);
aTagName = trName;
aSelectedCount = 1;
}
}
}
if (!tableOrCellElement)
{
// Didn't find a table element -- find a cell parent
res = GetElementOrParentByTagName(tdName, anchorNode, getter_AddRefs(tableOrCellElement));
if(NS_FAILED(res)) return res;
if (tableOrCellElement)
aTagName = tdName;
}
}
if (tableOrCellElement)
{
aTableElement = tableOrCellElement.get();
NS_ADDREF(aTableElement);
}
return res;
@ -2611,7 +2650,7 @@ nsHTMLEditor::GetSelectedCellsType(nsIDOMElement *aElement, PRUint32 &aSelection
// (if aElement is null, this uses selection's anchor node)
nsCOMPtr<nsIDOMElement> table;
nsresult res = GetElementOrParentByTagName(NS_ConvertASCIItoUCS2("table"), aElement, getter_AddRefs(table));
nsresult res = GetElementOrParentByTagName(NS_LITERAL_STRING("table"), aElement, getter_AddRefs(table));
if (NS_FAILED(res)) return res;
PRInt32 rowCount, colCount;
@ -2742,3 +2781,31 @@ nsHTMLEditor::AllCellsInColumnSelected(nsIDOMElement *aTable, PRInt32 aColIndex,
}
return PR_TRUE;
}
PRBool
nsHTMLEditor::IsEmptyCell(nsIDOMElement *aCell)
{
nsCOMPtr<nsIDOMNode> cellChild;
// Check if target only contains empty text node or <br>
nsresult res = aCell->GetFirstChild(getter_AddRefs(cellChild));
if (NS_FAILED(res)) return res;
if (cellChild)
{
nsCOMPtr<nsIDOMNode> nextChild;
res = cellChild->GetNextSibling(getter_AddRefs(nextChild));
if (!nextChild)
{
// We insert a single break into a cell by default
// to have some place to locate a cursor -- it is dispensable
PRBool isEmpty = nsHTMLEditUtils::IsBreak(cellChild);
// Or check if no real content
if (!isEmpty)
IsEmptyNode(cellChild, &isEmpty, PR_FALSE, PR_FALSE);
return isEmpty;
}
}
return PR_FALSE;
}

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

@ -418,7 +418,7 @@ nsTextEditRules::GetTopEnclosingPre(nsIDOMNode *aNode,
return res;
}
nsresult
nsresult
nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, PRBool *aHandled)
{
if (!aSelection || !aCancel || !aHandled) { return NS_ERROR_NULL_POINTER; }
@ -487,7 +487,7 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
if (outLeftNode)
{
res = IsEmptyNode(outLeftNode, &bIsEmptyNode, PR_TRUE, PR_FALSE);
res = mEditor->IsEmptyNode(outLeftNode, &bIsEmptyNode, PR_TRUE, PR_FALSE);
if (NS_FAILED(res)) return res;
if (bIsEmptyNode) mEditor->DeleteNode(outLeftNode);
}
@ -501,7 +501,7 @@ nsTextEditRules::WillInsertBreak(nsIDOMSelection *aSelection, PRBool *aCancel, P
mEditor->DeleteNode(firstNode);
}
res = IsEmptyNode(outRightNode, &bIsEmptyNode, PR_TRUE, PR_FALSE);
res = mEditor->IsEmptyNode(outRightNode, &bIsEmptyNode, PR_TRUE, PR_FALSE);
if (NS_FAILED(res)) return res;
if (bIsEmptyNode) mEditor->DeleteNode(outRightNode);
}
@ -685,7 +685,7 @@ nsTextEditRules::WillInsertText(PRInt32 aAction,
if (isPRE)
{
char newlineChar = '\n';
while (unicodeBuf && (pos != -1) && (pos < outString->Length()))
while (unicodeBuf && (pos != -1) && ((PRUint32)pos < outString->Length()))
{
PRInt32 oldPos = pos;
PRInt32 subStrLen;
@ -723,7 +723,7 @@ nsTextEditRules::WillInsertText(PRInt32 aAction,
{
char specialChars[] = {'\t','\n',0};
nsAutoString tabString; tabString.AssignWithConversion(" ");
while (unicodeBuf && (pos != -1) && (pos < outString->Length()))
while (unicodeBuf && (pos != -1) && ((PRUint32)pos < outString->Length()))
{
PRInt32 oldPos = pos;
PRInt32 subStrLen;
@ -1334,106 +1334,6 @@ nsTextEditRules::CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<ns
return res;
}
///////////////////////////////////////////////////////////////////////////
// IsEmptyNode: figure out if aNode is an empty node.
// A block can have children and still be considered empty,
// if the children are empty or non-editable.
//
nsresult
nsTextEditRules::IsEmptyNode( nsIDOMNode *aNode,
PRBool *outIsEmptyNode,
PRBool aMozBRDoesntCount,
PRBool aListItemsNotEmpty)
{
if (!aNode || !outIsEmptyNode) return NS_ERROR_NULL_POINTER;
*outIsEmptyNode = PR_TRUE;
// effeciency hack - special case if it's a text node
if (nsEditor::IsTextNode(aNode))
{
PRUint32 length = 0;
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
nodeAsText = do_QueryInterface(aNode);
nodeAsText->GetLength(&length);
if (length) *outIsEmptyNode = PR_FALSE;
return NS_OK;
}
// if it's not a text node (handled above) and it's not a container,
// then we dont call it empty (it's an <hr>, or <br>, etc).
// Also, if it's an anchor then dont treat it as empty - even though
// anchors are containers, named anchors are "empty" but we don't
// want to treat them as such. Also, don't call ListItems or table
// cells empty if caller desires.
if (!mEditor->IsContainer(aNode) || nsHTMLEditUtils::IsAnchor(aNode) ||
(aListItemsNotEmpty && nsHTMLEditUtils::IsListItem(aNode)) ||
(aListItemsNotEmpty && nsHTMLEditUtils::IsTableCell(aNode)) )
{
*outIsEmptyNode = PR_FALSE;
return NS_OK;
}
// iterate over node. if no children, or all children are either
// empty text nodes or non-editable, then node qualifies as empty
nsCOMPtr<nsIContentIterator> iter;
nsCOMPtr<nsIContent> nodeAsContent = do_QueryInterface(aNode);
if (!nodeAsContent) return NS_ERROR_FAILURE;
nsresult res = nsComponentManager::CreateInstance(kContentIteratorCID,
nsnull,
NS_GET_IID(nsIContentIterator),
getter_AddRefs(iter));
if (NS_FAILED(res)) return res;
res = iter->Init(nodeAsContent);
if (NS_FAILED(res)) return res;
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;
// is the node editable and non-empty? if so, return false
if (mEditor->IsEditable(node))
{
if (nsEditor::IsTextNode(node))
{
PRUint32 length = 0;
nsCOMPtr<nsIDOMCharacterData>nodeAsText;
nodeAsText = do_QueryInterface(node);
nodeAsText->GetLength(&length);
if (length) *outIsEmptyNode = PR_FALSE;
}
else // an editable, non-text node. we aren't an empty block
{
// is it the node we are iterating over?
if (node.get() == aNode) break;
// is it a moz-BR and did the caller ask us not to consider those relevant?
if (!(aMozBRDoesntCount && nsHTMLEditUtils::IsMozBR(node)))
{
// is it an empty node of some sort?
PRBool isEmptyNode;
res = IsEmptyNode(node, &isEmptyNode, aMozBRDoesntCount, aListItemsNotEmpty);
if (NS_FAILED(res)) return res;
if (!isEmptyNode)
{
// otherwise it ain't empty
*outIsEmptyNode = PR_FALSE;
break;
}
}
}
}
res = iter->Next();
if (NS_FAILED(res)) return res;
}
return NS_OK;
}
PRBool
nsTextEditRules::DeleteEmptyTextNode(nsIDOMNode *aNode)
{

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

@ -161,11 +161,6 @@ protected:
nsresult CreateMozBR(nsIDOMNode *inParent, PRInt32 inOffset, nsCOMPtr<nsIDOMNode> *outBRNode);
nsresult IsEmptyNode(nsIDOMNode *aNode,
PRBool *outIsEmptyBlock,
PRBool aMozBRDoesntCount = PR_FALSE,
PRBool aListItemsNotEmpty = PR_FALSE);
PRBool DeleteEmptyTextNode(nsIDOMNode *aNode);
nsresult AdjustSelection(nsIDOMSelection *aSelection, nsIEditor::EDirection aDirection);