From 59766ea19c5df85da50d0cb4c3027367bcbf5c2f Mon Sep 17 00:00:00 2001 From: "cmanske%netscape.com" Date: Wed, 4 Aug 1999 02:06:03 +0000 Subject: [PATCH] Table editing implementation git-svn-id: svn://10.0.0.236/trunk@42082 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/editor/base/EditTable.cpp | 308 ++++++++++++++---- mozilla/editor/base/nsEditorShell.cpp | 174 +++++++++- mozilla/editor/base/nsEditorShell.h | 15 + mozilla/editor/base/nsHTMLEditor.h | 21 +- mozilla/editor/base/nsJSEditorLog.cpp | 2 +- mozilla/editor/base/nsJSEditorLog.h | 2 +- mozilla/editor/composer/src/nsEditorShell.cpp | 174 +++++++++- mozilla/editor/composer/src/nsEditorShell.h | 15 + mozilla/editor/idl/nsIEditorShell.idl | 19 ++ mozilla/editor/libeditor/html/nsHTMLEditor.h | 21 +- mozilla/editor/public/nsIHTMLEditor.h | 41 ++- .../ui/composer/content/EditorAppShell.xul | 43 ++- .../ui/composer/content/EditorCommands.js | 110 +++++-- .../editor/ui/dialogs/content/EdLinkProps.js | 4 +- .../editor/ui/dialogs/content/EdLinkProps.xul | 7 +- 15 files changed, 839 insertions(+), 117 deletions(-) diff --git a/mozilla/editor/base/EditTable.cpp b/mozilla/editor/base/EditTable.cpp index 6c930d296f0..a5c7cfdc730 100644 --- a/mozilla/editor/base/EditTable.cpp +++ b/mozilla/editor/base/EditTable.cpp @@ -29,88 +29,153 @@ #include "nsIAtom.h" #include "nsIDOMHTMLTableElement.h" #include "nsIDOMHTMLTableCellElement.h" -/* -#include "nsIDocument.h" -#include "nsIServiceManager.h" -#include "nsEditFactory.h" -#include "nsTextEditFactory.h" -#include "nsEditorCID.h" -#include "nsTransactionManagerCID.h" -#include "nsITransactionManager.h" -#include "nsIPresShell.h" -#include "nsIViewManager.h" -#include "nsICollection.h" -#include "nsIEnumerator.h" -#include "nsVoidArray.h" -#include "nsICaret.h" -*/ - #include "nsITableCellLayout.h" // For efficient access to table cell #include "nsITableLayout.h" // data owned by the table and cell frames // transactions the editor knows how to build -#include "TransactionFactory.h" -#include "EditAggregateTxn.h" -#include "nsIDOMHTMLCollection.h" +//#include "TransactionFactory.h" +//#include "EditAggregateTxn.h" +//#include "nsIDOMHTMLCollection.h" #include "nsHTMLEditor.h" -static NS_DEFINE_IID(kITransactionManagerIID, NS_ITRANSACTIONMANAGER_IID); - // Table Editing methods NS_IMETHODIMP nsHTMLEditor::InsertTable() { - nsresult result=NS_ERROR_NOT_INITIALIZED; + nsresult res=NS_ERROR_NOT_INITIALIZED; return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP nsHTMLEditor::InsertTableCell(PRInt32 aNumber, PRBool aAfter) { - return NS_ERROR_NOT_IMPLEMENTED; + nsCOMPtr selection; + nsCOMPtr table; + nsCOMPtr cell; + nsCOMPtr cellParent; + PRInt32 cellOffset, startRow, startCol; + nsresult res = GetCellContext(selection, table, cell, cellParent, cellOffset, startRow, startCol); + + if (NS_SUCCEEDED(res)) + { + PRInt32 i; + for (i = 0; i < aNumber; i++) + { + nsCOMPtr newCell; + res = CreateElementWithDefaults("td", getter_AddRefs(newCell)); + if (NS_SUCCEEDED(res) && newCell) + { + if (aAfter) cellOffset++; + res = InsertNode(newCell, cellParent, cellOffset); + } + } + SetCaretAfterTableEdit(table, startRow, startCol, ePreviousColumn); + } + return res; } NS_IMETHODIMP nsHTMLEditor::InsertTableColumn(PRInt32 aNumber, PRBool aAfter) { - return NS_ERROR_NOT_IMPLEMENTED; + nsCOMPtr selection; + nsCOMPtr table; + nsCOMPtr cell; + nsCOMPtr cellParent; + PRInt32 cellOffset, startRow, startCol; + nsresult res = GetCellContext(selection, table, cell, cellParent, cellOffset, startRow, startCol); + + if (NS_SUCCEEDED(res)) + { + PRInt32 rowCount, colCount, row, col, curRow, curCol; + if (NS_FAILED(GetTableSize(table, rowCount, colCount))) + return NS_ERROR_FAILURE; + for ( row = 0; row < rowCount; row++) + { + nsCOMPtr curCell; + PRInt32 startRow, startCol, rowSpan, colSpan; + PRBool isSelected; + res = GetCellDataAt(table, row, col, *getter_AddRefs(curCell), + startRow, startCol, rowSpan, colSpan, isSelected); + if (NS_SUCCEEDED(res) && curCell) + { + //FINISH ME! + } + } + } + return res; } NS_IMETHODIMP nsHTMLEditor::InsertTableRow(PRInt32 aNumber, PRBool aAfter) { - nsCOMPtrselection; - nsresult res = nsEditor::GetSelection(getter_AddRefs(selection)); - if (NS_FAILED(res) || !selection) - return res; - // Collapse the current selection - selection->ClearSelection(); - nsCOMPtr anchorNode; - res = selection->GetAnchorNode(getter_AddRefs(anchorNode)); - if (NS_FAILED(res) || !anchorNode) - return res; - - nsCOMPtr cell; - nsCOMPtr row; + nsCOMPtr selection; nsCOMPtr table; - res = NS_ERROR_FAILURE; - //if(NS_SUCCEEDED(GetElementOrParentByTagName("td", anchorNode, getter_AddRefs(cell)) - - + nsCOMPtr cell; + nsCOMPtr cellParent; + PRInt32 cellOffset, startRow, startCol; + nsresult res = GetCellContext(selection, table, cell, cellParent, cellOffset, startRow, startCol); + + if (NS_SUCCEEDED(res)) + { + selection->ClearSelection(); + } return res; } NS_IMETHODIMP nsHTMLEditor::DeleteTable() { - return NS_ERROR_NOT_IMPLEMENTED; + nsCOMPtr selection; + nsCOMPtr table; + nsCOMPtr cell; + nsCOMPtr cellParent; + PRInt32 cellOffset, startRow, startCol; + nsresult res = GetCellContext(selection, table, cell, cellParent, cellOffset, startRow, startCol); + + if (NS_SUCCEEDED(res)) + { + // Save where we need to restore the selection + nsCOMPtr tableParent; + PRInt32 tableOffset; + if(NS_FAILED(table->GetParentNode(getter_AddRefs(tableParent))) || !tableParent) + return NS_ERROR_FAILURE; + + res = DeleteNode(table); + + // Restore the selection (caret) + nsCOMPtrselection; + res = nsEditor::GetSelection(getter_AddRefs(selection)); + if (NS_FAILED(res) || !selection) + return res; + selection->Collapse(tableParent, tableOffset); + } + return res; } NS_IMETHODIMP nsHTMLEditor::DeleteTableCell(PRInt32 aNumber) { - return NS_ERROR_NOT_IMPLEMENTED; + nsCOMPtr selection; + nsCOMPtr table; + nsCOMPtr cell; + nsCOMPtr cellParent; + PRInt32 cellOffset, startRow, startCol; + nsresult res = GetCellContext(selection, table, cell, cellParent, cellOffset, startRow, startCol); + + if (NS_SUCCEEDED(res)) + { + selection->ClearSelection(); + PRInt32 i; + for (i = 0; i < aNumber; i++) + { + //TODO: FINISH ME! + if (NS_FAILED(DeleteNode(cell))) + break; + } + SetCaretAfterTableEdit(table, startRow, startCol, ePreviousColumn); + } + return res; } NS_IMETHODIMP @@ -126,7 +191,13 @@ nsHTMLEditor::DeleteTableRow(PRInt32 aNumber) } NS_IMETHODIMP -nsHTMLEditor::JoinTableCells(PRBool aCellToRight) +nsHTMLEditor::JoinTableCells() +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsHTMLEditor::NormalizeTable(nsIDOMElement *aTable) { return NS_ERROR_NOT_IMPLEMENTED; } @@ -134,31 +205,36 @@ nsHTMLEditor::JoinTableCells(PRBool aCellToRight) NS_IMETHODIMP nsHTMLEditor::GetCellIndexes(nsIDOMElement *aCell, PRInt32 &aColIndex, PRInt32 &aRowIndex) { - nsresult result=NS_ERROR_NOT_INITIALIZED; + nsresult res=NS_ERROR_NOT_INITIALIZED; aColIndex=0; // initialize out params aRowIndex=0; if (!aCell) - return result; + { + // Get the selected cell or the cell enclosing the selection anchor + nsCOMPtr cell; + res = GetElementOrParentByTagName("td", nsnull, getter_AddRefs(cell)); + if (NS_SUCCEEDED(res) && cell) + aCell = cell; + else + return NS_ERROR_FAILURE; + } - result = NS_ERROR_FAILURE; // we return an error unless we get the index + res = NS_ERROR_FAILURE; // we return an error unless we get the index nsISupports *layoutObject=nsnull; // frames are not ref counted, so don't use an nsCOMPtr - result = nsEditor::GetLayoutObject(aCell, &layoutObject); + res = nsEditor::GetLayoutObject(aCell, &layoutObject); - if ((NS_SUCCEEDED(result)) && (nsnull!=layoutObject)) + if ((NS_SUCCEEDED(res)) && (nsnull!=layoutObject)) { // get the table cell interface from the frame nsITableCellLayout *cellLayoutObject=nsnull; // again, frames are not ref-counted - result = layoutObject->QueryInterface(nsITableCellLayout::GetIID(), (void**)(&cellLayoutObject)); - if ((NS_SUCCEEDED(result)) && (nsnull!=cellLayoutObject)) - { // get the index - result = cellLayoutObject->GetColIndex(aColIndex); - if (NS_SUCCEEDED(result)) - { - result = cellLayoutObject->GetRowIndex(aRowIndex); - } + + res = layoutObject->QueryInterface(nsITableCellLayout::GetIID(), (void**)(&cellLayoutObject)); + if ((NS_SUCCEEDED(res)) && (nsnull!=cellLayoutObject)) + { + res = cellLayoutObject->GetCellIndexes(aRowIndex, aColIndex); } } - return result; + return res; } NS_IMETHODIMP @@ -170,33 +246,42 @@ nsHTMLEditor::GetTableLayoutObject(nsIDOMElement* aTable, nsITableLayout **table // frames are not ref counted, so don't use an nsCOMPtr nsISupports *layoutObject=nsnull; - nsresult result = nsEditor::GetLayoutObject(aTable, &layoutObject); - if ((NS_SUCCEEDED(result)) && (nsnull!=layoutObject)) + nsresult res = nsEditor::GetLayoutObject(aTable, &layoutObject); + if ((NS_SUCCEEDED(res)) && (nsnull!=layoutObject)) { // get the table interface from the frame - result = layoutObject->QueryInterface(nsITableLayout::GetIID(), + res = layoutObject->QueryInterface(nsITableLayout::GetIID(), (void**)(tableLayoutObject)); } - return result; + return res; } /* Not scriptable: For convenience in C++ */ NS_IMETHODIMP nsHTMLEditor::GetTableSize(nsIDOMElement *aTable, PRInt32& aRowCount, PRInt32& aColCount) { + nsresult res=NS_ERROR_FAILURE; aRowCount = 0; aColCount = 0; if (!aTable) - return NS_ERROR_NOT_INITIALIZED; + { + // Get the selected talbe or the table enclosing the selection anchor + nsCOMPtr table; + res = GetElementOrParentByTagName("table", nsnull, getter_AddRefs(table)); + if (NS_SUCCEEDED(res) && table) + aTable = table; + else + return NS_ERROR_FAILURE; + } // frames are not ref counted, so don't use an nsCOMPtr nsITableLayout *tableLayoutObject; - nsresult result = GetTableLayoutObject(aTable, &tableLayoutObject); - if ((NS_SUCCEEDED(result)) && (nsnull!=tableLayoutObject)) + res = GetTableLayoutObject(aTable, &tableLayoutObject); + if ((NS_SUCCEEDED(res)) && (nsnull!=tableLayoutObject)) { - result = tableLayoutObject->GetTableSize(aRowCount, aColCount); + res = tableLayoutObject->GetTableSize(aRowCount, aColCount); } - return result; + return res; } NS_IMETHODIMP @@ -204,6 +289,7 @@ nsHTMLEditor::GetCellDataAt(nsIDOMElement* aTable, PRInt32 aRowIndex, PRInt32 aC PRInt32& aStartRowIndex, PRInt32& aStartColIndex, PRInt32& aRowSpan, PRInt32& aColSpan, PRBool& aIsSelected) { + nsresult res=NS_ERROR_FAILURE; aCell = nsnull; aStartRowIndex = 0; aStartColIndex = 0; @@ -212,20 +298,28 @@ nsHTMLEditor::GetCellDataAt(nsIDOMElement* aTable, PRInt32 aRowIndex, PRInt32 aC aIsSelected = PR_FALSE; if (!aTable) - return NS_ERROR_NOT_INITIALIZED; + { + // Get the selected talbe or the table enclosing the selection anchor + nsCOMPtr table; + res = GetElementOrParentByTagName("table", nsnull, getter_AddRefs(table)); + if (NS_SUCCEEDED(res) && table) + aTable = table; + else + return NS_ERROR_FAILURE; + } // frames are not ref counted, so don't use an nsCOMPtr nsITableLayout *tableLayoutObject; - nsresult result = GetTableLayoutObject(aTable, &tableLayoutObject); - if ((NS_SUCCEEDED(result)) && (nsnull!=tableLayoutObject)) + res = GetTableLayoutObject(aTable, &tableLayoutObject); + if ((NS_SUCCEEDED(res)) && (nsnull!=tableLayoutObject)) { // Note that this returns NS_TABLELAYOUT_CELL_NOT_FOUND when // the index(es) are out of bounds - result = tableLayoutObject->GetCellDataAt(aRowIndex, aColIndex, aCell, + res = tableLayoutObject->GetCellDataAt(aRowIndex, aColIndex, aCell, aStartRowIndex, aStartColIndex, aRowSpan, aColSpan, aIsSelected); } - return result; + return res; } // When all you want is the cell @@ -238,3 +332,73 @@ nsHTMLEditor::GetCellAt(nsIDOMElement* aTable, PRInt32 aRowIndex, PRInt32 aColIn aStartRowIndex, aStartColIndex, aRowSpan, aColSpan, aIsSelected); } +NS_IMETHODIMP +nsHTMLEditor::GetCellContext(nsCOMPtr &aSelection, + nsCOMPtr &aTable, nsCOMPtr &aCell, + nsCOMPtr &aCellParent, PRInt32& aCellOffset, + PRInt32& aRow, PRInt32& aCol) +{ + nsresult res = nsEditor::GetSelection(getter_AddRefs(aSelection)); + if (NS_FAILED(res) || !aSelection) + return res; + + // TODO: Should we look for the "first" cell instead? + // Messy! We would need to iterate through the selection to find the first enclosing cell + nsCOMPtr anchorNode; + if(NS_FAILED(aSelection->GetAnchorNode(getter_AddRefs(anchorNode))) || !anchorNode) + return NS_ERROR_FAILURE; + + // Test if anchor is a cell node (should I bother to check header as well? + nsCOMPtr cellElement = do_QueryInterface(anchorNode); + if (cellElement) + { + aCell = do_QueryInterface(anchorNode); + } else { + // Get the anchor's first child, in case the selection is composed of cells + PRInt32 offset; + if (NS_FAILED(aSelection->GetAnchorOffset(&offset))) + return NS_ERROR_FAILURE; + + nsCOMPtr anchorChild = GetChildAt(anchorNode, offset); + if(!anchorChild) + return NS_ERROR_FAILURE; + + // Get the cell enclosing the selection anchor + if(NS_FAILED(GetElementOrParentByTagName("td", anchorChild, getter_AddRefs(aCell))) || !aCell) + return NS_ERROR_FAILURE; + } + + if(NS_FAILED(GetElementOrParentByTagName("table", aCell, getter_AddRefs(aTable))) || !aTable) + return NS_ERROR_FAILURE; + + if(NS_FAILED(aCell->GetParentNode(getter_AddRefs(aCellParent))) || !aCellParent) + return NS_ERROR_FAILURE; + + // Get current cell location so we can put caret back there when done + res = GetCellIndexes(aCell, aRow, aCol); + if(NS_FAILED(res)) + return res; + + return GetChildOffset(aCell, aCellParent, aCellOffset); +} + + +NS_IMETHODIMP +nsHTMLEditor::SetCaretAfterTableEdit(nsIDOMElement* aTable, PRInt32 aCol, PRInt32 aRow, SetCaretSearchDirection aDirection) +{ + nsresult res = NS_ERROR_NOT_INITIALIZED; + if (!aTable) + return res; + + nsCOMPtrselection; + res = nsEditor::GetSelection(getter_AddRefs(selection)); + if (!NS_SUCCEEDED(res) || !selection) + { +#ifdef DEBUG_cmanske + printf("Selection not found after table manipulation!\n"); +#endif + return NS_ERROR_FAILURE; + } + return res; +} + diff --git a/mozilla/editor/base/nsEditorShell.cpp b/mozilla/editor/base/nsEditorShell.cpp index d91929a1e60..d13b202ac62 100644 --- a/mozilla/editor/base/nsEditorShell.cpp +++ b/mozilla/editor/base/nsEditorShell.cpp @@ -2122,6 +2122,179 @@ nsEditorShell::SetSelectionAfterElement(nsIDOMElement* aElement) /* Table Editing */ +NS_IMETHODIMP +nsEditorShell::InsertTableCell(PRInt32 aNumber, PRBool bAfter) +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->InsertTableCell(aNumber, bAfter); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + +NS_IMETHODIMP +nsEditorShell::InsertTableRow(PRInt32 aNumber, PRBool bAfter) +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->InsertTableRow(aNumber,bAfter); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + +NS_IMETHODIMP +nsEditorShell::InsertTableColumn(PRInt32 aNumber, PRBool bAfter) +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->InsertTableColumn(aNumber,bAfter); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + +NS_IMETHODIMP +nsEditorShell::DeleteTable() +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->DeleteTable(); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + +NS_IMETHODIMP +nsEditorShell::DeleteTableCell(PRInt32 aNumber) +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->DeleteTableCell(aNumber); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + + +NS_IMETHODIMP +nsEditorShell::DeleteTableRow(PRInt32 aNumber) +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->DeleteTableRow(aNumber); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + + +NS_IMETHODIMP +nsEditorShell::DeleteTableColumn(PRInt32 aNumber) +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->DeleteTableColumn(aNumber); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + +NS_IMETHODIMP +nsEditorShell::JoinTableCells() +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->JoinTableCells(); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + +NS_IMETHODIMP +nsEditorShell::NormalizeTable(nsIDOMElement *aTable) +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->NormalizeTable(aTable); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + // The next four methods are factored to return single items // separately for row and column. // Underlying implementation gets both at the same time for efficiency. @@ -2149,7 +2322,6 @@ nsEditorShell::GetRowIndex(nsIDOMElement *cellElement, PRInt32 *_retval) default: result = NS_ERROR_NOT_IMPLEMENTED; } - return result; } diff --git a/mozilla/editor/base/nsEditorShell.h b/mozilla/editor/base/nsEditorShell.h index f8a545ee2e5..d3bef5ab930 100644 --- a/mozilla/editor/base/nsEditorShell.h +++ b/mozilla/editor/base/nsEditorShell.h @@ -149,6 +149,21 @@ class nsEditorShell : public nsIEditorShell, NS_IMETHOD SelectElement(nsIDOMElement *element); NS_IMETHOD SetSelectionAfterElement(nsIDOMElement *element); + /* Table insert and delete methods. Done relative to selected cell or + cell containing the selection anchor */ + NS_IMETHOD InsertTableCell(PRInt32 aNumber, PRBool bAfter); + NS_IMETHOD InsertTableRow(PRInt32 aNumber, PRBool bAfter); + NS_IMETHOD InsertTableColumn(PRInt32 aNumber, PRBool bAfter); + NS_IMETHOD DeleteTable(); + NS_IMETHOD DeleteTableCell(PRInt32 aNumber); + NS_IMETHOD DeleteTableRow(PRInt32 aNumber); + NS_IMETHOD DeleteTableColumn(PRInt32 aNumber); + NS_IMETHOD JoinTableCells(); + /** Make table "rectangular" -- fill in all missing cellmap locations + * If aTable is null, it uses table enclosing the selection anchor + */ + NS_IMETHOD NormalizeTable(nsIDOMElement *aTable); + /* Get the row and col indexes in layout's cellmap */ NS_IMETHOD GetRowIndex(nsIDOMElement *aCell, PRInt32 *_retval); NS_IMETHOD GetColumnIndex(nsIDOMElement *aCell, PRInt32 *_retval); diff --git a/mozilla/editor/base/nsHTMLEditor.h b/mozilla/editor/base/nsHTMLEditor.h index e39bd01b846..3c17bd8bc75 100644 --- a/mozilla/editor/base/nsHTMLEditor.h +++ b/mozilla/editor/base/nsHTMLEditor.h @@ -177,6 +177,7 @@ public: PRInt32& aStartRowIndex, PRInt32& aStartColIndex, PRInt32& aRowSpan, PRInt32& aColSpan, PRBool& aIsSelected); + NS_IMETHOD InsertTable(); NS_IMETHOD InsertTableCell(PRInt32 aNumber, PRBool aAfter); NS_IMETHOD InsertTableColumn(PRInt32 aNumber, PRBool aAfter); @@ -185,7 +186,25 @@ public: NS_IMETHOD DeleteTableCell(PRInt32 aNumber); NS_IMETHOD DeleteTableColumn(PRInt32 aNumber); NS_IMETHOD DeleteTableRow(PRInt32 aNumber); - NS_IMETHOD JoinTableCells(PRBool aCellToRight); + NS_IMETHOD JoinTableCells(); + + /** Make table "rectangular" -- fill in all missing cellmap locations + * If aTable is null, it uses table enclosing the selection anchor + */ + NS_IMETHOD NormalizeTable(nsIDOMElement *aTable); + + // Table utilities + + // All of the above need to get the same basic context data + NS_IMETHOD GetCellContext(nsCOMPtr &aSelection, + nsCOMPtr &aTable, nsCOMPtr &aCell, + nsCOMPtr &aCellParent, PRInt32& aCellOffset, + PRInt32& aRow, PRInt32& aCol); + + // Setting caret to a logical place can get tricky, + // especially after deleting table stuff + typedef enum { ePreviousColumn=0, ePreviousRow } SetCaretSearchDirection; + NS_IMETHOD SetCaretAfterTableEdit(nsIDOMElement* aTable, PRInt32 aCol, PRInt32 aRow, SetCaretSearchDirection aDirection); protected: diff --git a/mozilla/editor/base/nsJSEditorLog.cpp b/mozilla/editor/base/nsJSEditorLog.cpp index 8fab6027845..2838bc80bd3 100644 --- a/mozilla/editor/base/nsJSEditorLog.cpp +++ b/mozilla/editor/base/nsJSEditorLog.cpp @@ -773,7 +773,7 @@ nsJSEditorLog::DeleteTableRow(PRInt32 aNumber) } NS_IMETHODIMP -nsJSEditorLog::JoinTableCells(PRBool aCellToRight) +nsJSEditorLog::JoinTableCells() { return NS_ERROR_NOT_IMPLEMENTED; } diff --git a/mozilla/editor/base/nsJSEditorLog.h b/mozilla/editor/base/nsJSEditorLog.h index 59eae8804b1..af800580524 100644 --- a/mozilla/editor/base/nsJSEditorLog.h +++ b/mozilla/editor/base/nsJSEditorLog.h @@ -141,7 +141,7 @@ public: NS_IMETHOD DeleteTableCell(PRInt32 aNumber); NS_IMETHOD DeleteTableColumn(PRInt32 aNumber); NS_IMETHOD DeleteTableRow(PRInt32 aNumber); - NS_IMETHOD JoinTableCells(PRBool aCellToRight); + NS_IMETHOD JoinTableCells(); NS_IMETHOD BeginComposition(void); NS_IMETHOD SetCompositionString(const nsString& aCompositionString, nsIDOMTextRangeList* aTextRangeList); NS_IMETHOD EndComposition(void); diff --git a/mozilla/editor/composer/src/nsEditorShell.cpp b/mozilla/editor/composer/src/nsEditorShell.cpp index d91929a1e60..d13b202ac62 100644 --- a/mozilla/editor/composer/src/nsEditorShell.cpp +++ b/mozilla/editor/composer/src/nsEditorShell.cpp @@ -2122,6 +2122,179 @@ nsEditorShell::SetSelectionAfterElement(nsIDOMElement* aElement) /* Table Editing */ +NS_IMETHODIMP +nsEditorShell::InsertTableCell(PRInt32 aNumber, PRBool bAfter) +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->InsertTableCell(aNumber, bAfter); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + +NS_IMETHODIMP +nsEditorShell::InsertTableRow(PRInt32 aNumber, PRBool bAfter) +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->InsertTableRow(aNumber,bAfter); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + +NS_IMETHODIMP +nsEditorShell::InsertTableColumn(PRInt32 aNumber, PRBool bAfter) +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->InsertTableColumn(aNumber,bAfter); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + +NS_IMETHODIMP +nsEditorShell::DeleteTable() +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->DeleteTable(); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + +NS_IMETHODIMP +nsEditorShell::DeleteTableCell(PRInt32 aNumber) +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->DeleteTableCell(aNumber); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + + +NS_IMETHODIMP +nsEditorShell::DeleteTableRow(PRInt32 aNumber) +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->DeleteTableRow(aNumber); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + + +NS_IMETHODIMP +nsEditorShell::DeleteTableColumn(PRInt32 aNumber) +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->DeleteTableColumn(aNumber); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + +NS_IMETHODIMP +nsEditorShell::JoinTableCells() +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->JoinTableCells(); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + +NS_IMETHODIMP +nsEditorShell::NormalizeTable(nsIDOMElement *aTable) +{ + nsresult result = NS_NOINTERFACE; + switch (mEditorType) + { + case eHTMLTextEditorType: + { + nsCOMPtr htmlEditor = do_QueryInterface(mEditor); + if (htmlEditor) + result = htmlEditor->NormalizeTable(aTable); + } + break; + default: + result = NS_ERROR_NOT_IMPLEMENTED; + } + return result; +} + // The next four methods are factored to return single items // separately for row and column. // Underlying implementation gets both at the same time for efficiency. @@ -2149,7 +2322,6 @@ nsEditorShell::GetRowIndex(nsIDOMElement *cellElement, PRInt32 *_retval) default: result = NS_ERROR_NOT_IMPLEMENTED; } - return result; } diff --git a/mozilla/editor/composer/src/nsEditorShell.h b/mozilla/editor/composer/src/nsEditorShell.h index f8a545ee2e5..d3bef5ab930 100644 --- a/mozilla/editor/composer/src/nsEditorShell.h +++ b/mozilla/editor/composer/src/nsEditorShell.h @@ -149,6 +149,21 @@ class nsEditorShell : public nsIEditorShell, NS_IMETHOD SelectElement(nsIDOMElement *element); NS_IMETHOD SetSelectionAfterElement(nsIDOMElement *element); + /* Table insert and delete methods. Done relative to selected cell or + cell containing the selection anchor */ + NS_IMETHOD InsertTableCell(PRInt32 aNumber, PRBool bAfter); + NS_IMETHOD InsertTableRow(PRInt32 aNumber, PRBool bAfter); + NS_IMETHOD InsertTableColumn(PRInt32 aNumber, PRBool bAfter); + NS_IMETHOD DeleteTable(); + NS_IMETHOD DeleteTableCell(PRInt32 aNumber); + NS_IMETHOD DeleteTableRow(PRInt32 aNumber); + NS_IMETHOD DeleteTableColumn(PRInt32 aNumber); + NS_IMETHOD JoinTableCells(); + /** Make table "rectangular" -- fill in all missing cellmap locations + * If aTable is null, it uses table enclosing the selection anchor + */ + NS_IMETHOD NormalizeTable(nsIDOMElement *aTable); + /* Get the row and col indexes in layout's cellmap */ NS_IMETHOD GetRowIndex(nsIDOMElement *aCell, PRInt32 *_retval); NS_IMETHOD GetColumnIndex(nsIDOMElement *aCell, PRInt32 *_retval); diff --git a/mozilla/editor/idl/nsIEditorShell.idl b/mozilla/editor/idl/nsIEditorShell.idl index 810eff43f21..65ee64f7406 100644 --- a/mozilla/editor/idl/nsIEditorShell.idl +++ b/mozilla/editor/idl/nsIEditorShell.idl @@ -122,6 +122,25 @@ interface nsIEditorShell : nsISupports void SetSelectionAfterElement(in nsIDOMElement element); /***** Table editing *****/ + /* These are done relative to selected cell + or cell contain the selection anchor */ + void InsertTableCell(in PRInt32 number, in PRBool after); + void InsertTableRow(in PRInt32 number, in PRBool after); + void InsertTableColumn(in PRInt32 number, in PRBool after); + void DeleteTable(); + void DeleteTableCell(in PRInt32 number); + void DeleteTableRow(in PRInt32 number); + void DeleteTableColumn(in PRInt32 number); + void JoinTableCells(); + + /** Scan through all rows and add cells as needed so + * all locations in the cellmap are occupied. + * Used after inserting single cells or pasting + * a collection of cells that extend past the + * previous size of the table + * If aTable is null, it uses table enclosing the selection anchor + */ + void NormalizeTable(in nsIDOMElement tableElement); /* Get the indexes from layout's cellmap */ PRInt32 GetRowIndex(in nsIDOMElement cellElement); diff --git a/mozilla/editor/libeditor/html/nsHTMLEditor.h b/mozilla/editor/libeditor/html/nsHTMLEditor.h index e39bd01b846..3c17bd8bc75 100644 --- a/mozilla/editor/libeditor/html/nsHTMLEditor.h +++ b/mozilla/editor/libeditor/html/nsHTMLEditor.h @@ -177,6 +177,7 @@ public: PRInt32& aStartRowIndex, PRInt32& aStartColIndex, PRInt32& aRowSpan, PRInt32& aColSpan, PRBool& aIsSelected); + NS_IMETHOD InsertTable(); NS_IMETHOD InsertTableCell(PRInt32 aNumber, PRBool aAfter); NS_IMETHOD InsertTableColumn(PRInt32 aNumber, PRBool aAfter); @@ -185,7 +186,25 @@ public: NS_IMETHOD DeleteTableCell(PRInt32 aNumber); NS_IMETHOD DeleteTableColumn(PRInt32 aNumber); NS_IMETHOD DeleteTableRow(PRInt32 aNumber); - NS_IMETHOD JoinTableCells(PRBool aCellToRight); + NS_IMETHOD JoinTableCells(); + + /** Make table "rectangular" -- fill in all missing cellmap locations + * If aTable is null, it uses table enclosing the selection anchor + */ + NS_IMETHOD NormalizeTable(nsIDOMElement *aTable); + + // Table utilities + + // All of the above need to get the same basic context data + NS_IMETHOD GetCellContext(nsCOMPtr &aSelection, + nsCOMPtr &aTable, nsCOMPtr &aCell, + nsCOMPtr &aCellParent, PRInt32& aCellOffset, + PRInt32& aRow, PRInt32& aCol); + + // Setting caret to a logical place can get tricky, + // especially after deleting table stuff + typedef enum { ePreviousColumn=0, ePreviousRow } SetCaretSearchDirection; + NS_IMETHOD SetCaretAfterTableEdit(nsIDOMElement* aTable, PRInt32 aCol, PRInt32 aRow, SetCaretSearchDirection aDirection); protected: diff --git a/mozilla/editor/public/nsIHTMLEditor.h b/mozilla/editor/public/nsIHTMLEditor.h index abb767860e5..6c51d02d3ed 100644 --- a/mozilla/editor/public/nsIHTMLEditor.h +++ b/mozilla/editor/public/nsIHTMLEditor.h @@ -264,17 +264,53 @@ public: NS_IMETHOD GetEmbeddedObjects(nsISupportsArray** aNodeList)=0; // Table editing Methods - /** Not implemented yet + /** Insert table methods + * Insert relative to the selected cell or the + * cell enclosing the selection anchor + * The selection is collapsed and is left in the new cell + * at the same row,col location as the original anchor cell + * + * @param aNumber Number of items to insert + * @param aAfter If TRUE, insert after the current cell, + * else insert before current cell */ NS_IMETHOD InsertTable()=0; NS_IMETHOD InsertTableCell(PRInt32 aNumber, PRBool aAfter)=0; NS_IMETHOD InsertTableColumn(PRInt32 aNumber, PRBool aAfter)=0; NS_IMETHOD InsertTableRow(PRInt32 aNumber, PRBool aAfter)=0; + + /** Delete table methods + * Delete starting at the selected cell or the + * cell (or table) enclosing the selection anchor + * The selection is collapsed and is left in the + * cell at the same row,col location as + * the previous selection anchor, if possible, + * else in the closest neigboring cell + * + * @param aNumber Number of items to insert/delete + */ NS_IMETHOD DeleteTable()=0; NS_IMETHOD DeleteTableCell(PRInt32 aNumber)=0; NS_IMETHOD DeleteTableColumn(PRInt32 aNumber)=0; NS_IMETHOD DeleteTableRow(PRInt32 aNumber)=0; - NS_IMETHOD JoinTableCells(PRBool aCellToRight)=0; + + /** Join the contents of the selected cells into one cell, + * expanding that cells ROWSPAN and COLSPAN to take up + * the same number of cellmap locations as before. + * Cells whose contents were moved are deleted. + * If there's one cell selected or caret is in one cell, + * it is joined with the cell to the right, if it exists + */ + NS_IMETHOD JoinTableCells()=0; + + /** Scan through all rows and add cells as needed so + * all locations in the cellmap are occupied. + * Used after inserting single cells or pasting + * a collection of cells that extend past the + * previous size of the table + * If aTable is null, it uses table enclosing the selection anchor + */ + NS_IMETHOD NormalizeTable(nsIDOMElement *aTable)=0; /** Get the row an column index from the layout's cellmap * If aTable is null, it will try to find enclosing table of selection ancho @@ -324,6 +360,7 @@ public: PRInt32& aStartRowIndex, PRInt32& aStartColIndex, PRInt32& aRowSpan, PRInt32& aColSpan, PRBool& aIsSelected)=0; + // IME editing Methods NS_IMETHOD BeginComposition(void)=0; NS_IMETHOD SetCompositionString(const nsString& aCompositionString, nsIDOMTextRangeList* aTextRangeList)=0; diff --git a/mozilla/editor/ui/composer/content/EditorAppShell.xul b/mozilla/editor/ui/composer/content/EditorAppShell.xul index bc60d73fd0f..db0766bb0f0 100644 --- a/mozilla/editor/ui/composer/content/EditorAppShell.xul +++ b/mozilla/editor/ui/composer/content/EditorAppShell.xul @@ -178,6 +178,18 @@ + + + + + + + + + + + + @@ -531,9 +543,34 @@ - + + - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -583,7 +620,7 @@ - + diff --git a/mozilla/editor/ui/composer/content/EditorCommands.js b/mozilla/editor/ui/composer/content/EditorCommands.js index 84e17c6058b..d4b162976cb 100644 --- a/mozilla/editor/ui/composer/content/EditorCommands.js +++ b/mozilla/editor/ui/composer/content/EditorCommands.js @@ -25,11 +25,11 @@ var EditorDisplayStyle = true; var gTagToFormat = { "P" : "Normal", // these should really be entities. Not sure how to do that from JS "H1" : "Heading 1", - "H2" : "Header 2", - "H3" : "Header 3", - "H4" : "Header 4", - "H5" : "Header 5", - "H6" : "Header 6", + "H2" : "Heading 2", + "H3" : "Heading 3", + "H4" : "Heading 4", + "H5" : "Heading 5", + "H6" : "Heading 6", "BLOCKQUOTE" : "Blockquote", "ADDRESS" : "Address", "PRE" : "Preformatted", @@ -442,30 +442,6 @@ function EditorInsertImage() contentWindow.focus(); } -function EditorInsertOrEditTable() -{ - var selection = editorShell.editorSelection; - dump("Selection: Anchor: "+selection.anchorNode+selection.anchorOffset+" Focus: "+selection.focusNode+selection.focusOffset+"\n"); - - var table = editorShell.GetElementOrParentByTagName("table", null); - if (table) { - // Edit properties of existing table - dump("Existing table found ... Editing its properties\n"); - - window.openDialog("chrome://editor/content/EdTableProps.xul", "TableDlg", "chrome", ""); - contentWindow.focus(); - } else { - EditorInsertTable(); - } -} - -function EditorInsertTable() -{ - // Insert a new table - window.openDialog("chrome://editor/content/EdInsertTable.xul", "TableDlg", "chrome", ""); - contentWindow.focus(); -} - function EditorInsertHLine() { // Inserting an HLine is different in that we don't use properties dialog @@ -500,6 +476,82 @@ function EditorIndent(indent) contentWindow.focus(); } +// Call this with insertAllowed = true to allow inserting if not in existing table, +// else use false to do nothing if not in a table +function EditorInsertOrEditTable(insertAllowed) +{ + var selection = editorShell.editorSelection; + dump("Selection: Anchor: "+selection.anchorNode+selection.anchorOffset+" Focus: "+selection.focusNode+selection.focusOffset+"\n"); + + var table = editorShell.GetElementOrParentByTagName("table", null); + if (table) { + // Edit properties of existing table + dump("Existing table found ... Editing its properties\n"); + + window.openDialog("chrome://editor/content/EdTableProps.xul", "TableDlg", "chrome", ""); + contentWindow.focus(); + } else if(insertAllowed) { + EditorInsertTable(); + } +} + +function EditorInsertTable() +{ + // Insert a new table + window.openDialog("chrome://editor/content/EdInsertTable.xul", "TableDlg", "chrome", ""); + contentWindow.focus(); +} + +function EditorInsertTableCell(after) +{ + editorShell.InsertTableCell(1,after); + contentWindow.focus(); +} + +// Just insert before current row or column for now +function EditorInsertTableRow() +{ + editorShell.InsertTableRow(1,false); + contentWindow.focus(); +} + +function EditorInsertTableColumn() +{ + editorShell.InsertTableColumn(1,false); + contentWindow.focus(); +} + +function JoinTableCells() +{ + editorShell.JoinTableCells(); + contentWindow.focus(); +} + +function EditorDeleteTable() +{ + editorShell.DeleteTable(); + contentWindow.focus(); +} + +function EditorDeleteTableRow() +{ + editorShell.DeleteTableRow(); + contentWindow.focus(); +} + +function EditorDeleteTableColumn() +{ + editorShell.DeleteTableColumn(); + contentWindow.focus(); +} + + +function EditorDeleteTableCell() +{ + editorShell.DeleteTableCell(); + contentWindow.focus(); +} + function EditorInsertList(listType) { dump("Inserting list\n"); diff --git a/mozilla/editor/ui/dialogs/content/EdLinkProps.js b/mozilla/editor/ui/dialogs/content/EdLinkProps.js index 7f72d7c4248..b4938a897d5 100644 --- a/mozilla/editor/ui/dialogs/content/EdLinkProps.js +++ b/mozilla/editor/ui/dialogs/content/EdLinkProps.js @@ -145,11 +145,11 @@ function initDialog() } } -function chooseFile() +function ChooseFile() { // Get a local file, converted into URL format fileName = editorShell.GetLocalFileURL(window, "html"); - if (fileName != "") { + if (StringExists(fileName)) { hrefInput.value = fileName; } // Put focus into the input field diff --git a/mozilla/editor/ui/dialogs/content/EdLinkProps.xul b/mozilla/editor/ui/dialogs/content/EdLinkProps.xul index d4daa376b45..6fa1aa090ed 100644 --- a/mozilla/editor/ui/dialogs/content/EdLinkProps.xul +++ b/mozilla/editor/ui/dialogs/content/EdLinkProps.xul @@ -57,7 +57,7 @@
&LinkURLFieldset.label; - +
&LinkURLEditField.label;
@@ -66,9 +66,10 @@ - + +
- +