gecko-dev/editor/ui/composer/content/EditorCommandsDebug.js

570 lines
16 KiB
JavaScript

/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/* Main Composer window debug menu functions */
// --------------------------- Output ---------------------------
function EditorGetText()
{
try {
dump("Getting text\n");
var outputText = GetCurrentEditor().outputToString("text/plain", 2);
dump("<<" + outputText + ">>\n");
} catch (e) {}
}
function EditorGetHTML()
{
try {
dump("Getting HTML\n");
var outputHTML = GetCurrentEditor().outputToString("text/html", 256);
dump(outputHTML + "\n");
} catch (e) {}
}
function EditorDumpContent()
{
dump("============== Content Tree: ================\n");
GetCurrentEditor().dumpContentTree();
}
function EditorInsertText(textToInsert)
{
GetCurrentEditor().insertText(textToInsert);
}
function EditorTestSelection()
{
dump("Testing selection\n");
var selection = GetCurrentEditor().selection;
if (!selection)
{
dump("No selection!\n");
return;
}
dump("Selection contains:\n");
// 3rd param = column to wrap
dump(selection.QueryInterface(Components.interfaces.nsISelectionPrivate)
.toStringWithFormat("text/plain",
3, // OutputFormatted & gOutputSelectionOnly
0) + "\n");
var output, i;
dump("====== Selection as node and offsets==========\n");
dump("rangeCount = " + selection.rangeCount + "\n");
for (i = 0; i < selection.rangeCount; i++)
{
var range = selection.getRangeAt(i);
if (range)
{
dump("Range "+i+": StartParent="+range.startContainer.nodeName+", offset="+range.startOffset+"\n");
dump("Range "+i+": EndParent="+range.endContainer.nodeName+", offset="+range.endOffset+"\n\n");
}
}
var editor = GetCurrentEditor();
dump("====== Selection as unformatted text ==========\n");
output = editor.outputToString("text/plain", 1);
dump(output + "\n\n");
dump("====== Selection as formatted text ============\n");
output = editor.outputToString("text/plain", 3);
dump(output + "\n\n");
dump("====== Selection as HTML ======================\n");
output = editor.outputToString("text/html", 1);
dump(output + "\n\n");
dump("====== Selection as prettyprinted HTML ========\n");
output = editor.outputToString("text/html", 3);
dump(output + "\n\n");
dump("====== Length and status =====================\n");
output = "Document is ";
if (editor.documentIsEmpty)
output += "empty\n";
else
output += "not empty\n";
output += "Text length is " + editor.textLength + " characters";
dump(output + "\n\n");
}
function EditorTestTableLayout()
{
dump("\n\n\n************ Dump Selection Ranges ************\n");
var selection = GetCurrentEditor().selection;
var i;
for (i = 0; i < selection.rangeCount; i++)
{
var range = selection.getRangeAt(i);
if (range)
{
dump("Range "+i+": StartParent="+range.startParent+", offset="+range.startOffset+"\n");
}
}
dump("\n\n");
var editor = GetCurrentEditor();
var table = editor.getElementOrParentByTagName("table", null);
if (!table) {
dump("Enclosing Table not found: Place caret in a table cell to do this test\n\n");
return;
}
var cell;
var startRowIndexObj = { value: null };
var startColIndexObj = { value: null };
var rowSpanObj = { value: null };
var colSpanObj = { value: null };
var actualRowSpanObj = { value: null };
var actualColSpanObj = { value: null };
var isSelectedObj = { value: false };
var startRowIndex = 0;
var startColIndex = 0;
var rowSpan;
var colSpan;
var actualRowSpan;
var actualColSpan;
var isSelected;
var col = 0;
var row = 0;
var rowCount = 0;
var maxColCount = 0;
var doneWithRow = false;
var doneWithCol = false;
dump("\n\n\n************ Starting Table Layout test ************\n");
// Note: We could also get the number of rows, cols and use for loops,
// but this tests using out-of-bounds offsets to detect end of row or column
while (!doneWithRow) // Iterate through rows
{
dump("* Data for ROW="+row+":\n");
while(!doneWithCol) // Iterate through cells in the row
{
try {
cell = editor.getCellDataAt(table, row, col,
startRowIndexObj, startColIndexObj,
rowSpanObj, colSpanObj,
actualRowSpanObj, actualColSpanObj,
isSelectedObj);
if (cell)
{
rowSpan = rowSpanObj.value;
colSpan = colSpanObj.value;
actualRowSpan = actualRowSpanObj.value;
actualColSpan = actualColSpanObj.value;
isSelected = isSelectedObj.value;
dump(" Row="+row+", Col="+col+" StartRow="+startRowIndexObj.value+", StartCol="+startColIndexObj.value+"\n");
dump(" RowSpan="+rowSpan+", ColSpan="+colSpan+" ActualRowSpan="+actualRowSpan+", ActualColSpan="+actualColSpan);
if (isSelected)
dump(" Cell is selected\n");
else
dump(" Cell is NOT selected\n");
// Save the indexes of a cell that will span across the cellmap grid
if (rowSpan > 1)
startRowIndex = startRowIndexObj.value;
if (colSpan > 1)
startColIndex = startColIndexObj.value;
// Initialize these for efficient spanned-cell search
startRowIndexObj.value = startRowIndex;
startColIndexObj.value = startColIndex;
col++;
} else {
doneWithCol = true;
// Get maximum number of cells in any row
if (col > maxColCount)
maxColCount = col;
dump(" End of row found\n\n");
}
}
catch (e) {
dump(" *** GetCellDataAt failed at Row="+row+", Col="+col+" ***\n\n");
return;
}
}
if (col == 0) {
// Didn't find a cell in the first col of a row,
// thus no more rows in table
doneWithRow = true;
rowCount = row;
dump("No more rows in table\n\n");
} else {
// Setup for next row
col = 0;
row++;
doneWithCol = false;
}
}
dump("Counted during scan: Number of rows="+rowCount+" Number of Columns="+maxColCount+"\n");
rowCount = editor.getTableRowCount(table);
maxColCount = editor.getTableColumnCount(table);
dump("From nsITableLayout: Number of rows="+rowCount+" Number of Columns="+maxColCount+"\n****** End of Table Layout Test *****\n\n");
}
function EditorShowEmbeddedObjects()
{
dump("\nEmbedded Objects:\n");
try {
var objectArray = GetCurrentEditor().getEmbeddedObjects();
dump(objectArray.Count() + " embedded objects\n");
for (var i=0; i < objectArray.Count(); ++i)
dump(objectArray.GetElementAt(i) + "\n");
} catch(e) {}
}
function EditorUnitTests()
{
dump("Running Unit Tests\n");
var numTests = { value:0 };
var numTestsFailed = { value:0 };
GetCurrentEditor().debugUnitTests(numTests, numTestsFailed);
}
function EditorTestDocument()
{
dump("Getting document\n");
var theDoc = GetCurrentEditor().document;
if (theDoc)
{
dump("Got the doc\n");
dump("Document name:" + theDoc.nodeName + "\n");
dump("Document type:" + theDoc.doctype + "\n");
}
else
{
dump("Failed to get the doc\n");
}
}
// --------------------------- Logging stuff ---------------------------
function EditorExecuteScript(theFile)
{
var inputStream = Components.classes["@mozilla.org/network/file-input-stream;1"].createInstance();
inputStream = inputStream.QueryInterface(Components.interfaces.nsIFileInputStream);
inputStream.init(theFile, 1, 0, false); // open read only
var scriptableInputStream = Components.classes["@mozilla.org/scriptableinputstream;1"].createInstance();
scriptableInputStream = scriptableInputStream.QueryInterface(Components.interfaces.nsIScriptableInputStream);
scriptableInputStream.init(inputStream); // open read only
var buf = { value:null };
var tmpBuf = { value:null };
var didTruncate = { value:false };
var lineNum = 0;
var ex;
/*
// Log files can be quite huge, so read in a line
// at a time and execute it:
while (!inputStream.eof())
{
buf.value = "";
didTruncate.value = true;
// Keep looping until we get a complete line of
// text, or we hit the end of file:
while (didTruncate.value && !inputStream.eof())
{
didTruncate.value = false;
fileSpec.readLine(tmpBuf, 1024, didTruncate);
buf.value += tmpBuf.value;
// XXX Need to null out tmpBuf.value to avoid crashing
// XXX in some JavaScript string allocation method.
// XXX This is probably leaking the buffer allocated
// XXX by the readLine() implementation.
tmpBuf.value = null;
}
++lineNum;
*/
{
// suck in the entire file
var fileSize = scriptableInputStream.available();
var fileContents = scriptableInputStream.read(fileSize);
dump(fileContents);
try { eval(fileContents); }
catch(ex) { dump("Playback ERROR: Line " + lineNum + " " + ex + "\n"); return; }
}
buf.value = null;
}
function EditorGetScriptFileSpec()
{
var dirServ = Components.classes['@mozilla.org/file/directory_service;1'].createInstance();
dirServ = dirServ.QueryInterface(Components.interfaces.nsIProperties);
var processDir = dirServ.get("Home", Components.interfaces.nsIFile);
processDir.append("journal.js");
return processDir;
}
function EditorStartLog()
{
try {
var edlog = GetCurrentEditor().QueryInterface(Components.interfaces.nsIEditorLogging);
var fs = EditorGetScriptFileSpec();
edlog.startLogging(fs);
window.content.focus();
fs = null;
}
catch(ex) { dump("Can't start logging!:\n" + ex + "\n"); }
}
function EditorStopLog()
{
try {
var edlog = GetCurrentEditor().QueryInterface(Components.interfaces.nsIEditorLogging);
edlog.stopLogging();
window.content.focus();
}
catch(ex) { dump("Can't stop logging!:\n" + ex + "\n"); }
}
function EditorRunLog()
{
var fs;
fs = EditorGetScriptFileSpec();
EditorExecuteScript(fs);
window.content.focus();
}
// --------------------------- TransactionManager ---------------------------
function DumpUndoStack()
{
try {
var txmgr = GetCurrentEditor().transactionManager;
if (!txmgr)
{
dump("**** Editor has no TransactionManager!\n");
return;
}
dump("---------------------- BEGIN UNDO STACK DUMP\n");
dump("<!-- Bottom of Stack -->\n");
PrintTxnList(txmgr.getUndoList(), "");
dump("<!-- Top of Stack -->\n");
dump("Num Undo Items: " + txmgr.numberOfUndoItems + "\n");
dump("---------------------- END UNDO STACK DUMP\n");
} catch (e) {
dump("ERROR: DumpUndoStack() failed: " + e);
}
}
function DumpRedoStack()
{
try {
var txmgr = GetCurrentEditor().transactionManager;
if (!txmgr)
{
dump("**** Editor has no TransactionManager!\n");
return;
}
dump("---------------------- BEGIN REDO STACK DUMP\n");
dump("<!-- Bottom of Stack -->\n");
PrintTxnList(txmgr.getRedoList(), "");
dump("<!-- Top of Stack -->\n");
dump("Num Redo Items: " + txmgr.numberOfRedoItems + "\n");
dump("---------------------- END REDO STACK DUMP\n");
} catch (e) {
dump("ERROR: DumpUndoStack() failed: " + e);
}
}
function PrintTxnList(txnList, prefixStr)
{
var i;
for (i=0 ; i < txnList.numItems; i++)
{
var txn = txnList.getItem(i);
var desc = "TXMgr Batch";
if (txn)
{
try {
txn = txn.QueryInterface(Components.interfaces.nsPIEditorTransaction);
desc = txn.txnDescription;
} catch(e) {
desc = "UnknownTxnType";
}
}
dump(prefixStr + "+ " + desc + "\n");
PrintTxnList(txnList.getChildListForItem(i), prefixStr + "| ");
}
}
// ------------------------ 3rd Party Transaction Test ------------------------
function sampleJSTransaction()
{
this.wrappedJSObject = this;
}
sampleJSTransaction.prototype = {
isTransient: false,
mStrData: "[Sample-JS-Transaction-Content]",
mObject: null,
mContainer: null,
mOffset: null,
doTransaction: function()
{
if (this.mContainer.nodeType != Node.TEXT_NODE)
{
// We're not in a text node, so create one and
// we'll just insert it at (mContainer, mOffset).
this.mObject = this.mContainer.ownerDocument.createTextNode(this.mStrData);
}
this.redoTransaction();
},
undoTransaction: function()
{
if (!this.mObject)
this.mContainer.deleteData(this.mOffset, this.mStrData.length);
else
this.mContainer.removeChild(this.mObject);
},
redoTransaction: function()
{
if (!this.mObject)
this.mContainer.insertData(this.mOffset, this.mStrData);
else
this.insert_node_at_point(this.mObject, this.mContainer, this.mOffset);
},
merge: function(aTxn)
{
// We don't do any merging!
return false;
},
QueryInterface: function(aIID, theResult)
{
if (aIID.equals(Components.interfaces.nsITransaction) ||
aIID.equals(Components.interfaces.nsISupports))
return this;
Components.returnCode = Components.results.NS_ERROR_NO_INTERFACE;
return null;
},
insert_node_at_point: function(node, container, offset)
{
var childList = container.childNodes;
if (childList.length == 0 || offset >= childList.length)
container.appendChild(node);
else
container.insertBefore(node, childList.item(offset));
}
}
function ExecuteJSTransactionViaTxmgr()
{
try {
var editor = GetCurrentEditor();
var txmgr = editor.transactionManager;
txmgr = txmgr.QueryInterface(Components.interfaces.nsITransactionManager);
var selection = editor.selection;
var range = selection.getRangeAt(0);
var txn = new sampleJSTransaction();
txn.mContainer = range.startContainer;
txn.mOffset = range.startOffset;
txmgr.doTransaction(txn);
} catch (e) {
dump("ExecuteJSTransactionViaTxmgr() failed!");
}
}
function ExecuteJSTransactionViaEditor()
{
try {
var editor = GetCurrentEditor();
var selection = editor.selection;
var range = selection.getRangeAt(0);
var txn = new sampleJSTransaction();
txn.mContainer = range.startContainer;
txn.mOffset = range.startOffset;
editor.doTransaction(txn);
} catch (e) {
dump("ExecuteJSTransactionViaEditor() failed!");
}
}