/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Netscape 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/NPL/
 *
 * 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) 1998
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either 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 NPL, 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 NPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */
 
#include "nsISupports.idl"

interface nsIFile;
interface nsIDocumentStateListener;
interface nsISelectionController;
interface nsITransactionManager;
interface nsIDOMWindowInternal;
interface nsIDOMDocument;
interface nsISelection;
interface nsIDOMElement;
interface nsIDOMNode;
interface nsIEditor;
interface nsISupportsArray;

[scriptable, uuid(9afff72b-ca9a-11d2-96c9-0060b0fb9956)]
interface nsIEditorShell : nsISupports
{
  readonly attribute nsIDOMDocument         editorDocument;
  readonly attribute nsISelection           editorSelection;
  readonly attribute nsISelectionController selectionController;
  readonly attribute nsITransactionManager  transactionManager;
  
  attribute nsIDOMWindowInternal webShellWindow;
  attribute nsIDOMWindowInternal contentWindow;
  attribute wstring              editorType;
  attribute string               contentsMIMEType;
           
  readonly attribute nsIEditor editor;
  
%{C++

  enum {
    eDocumentStatusUnmodified,
    eDocumentStatusModified
  };

  enum {
    eDisplayModePreview,
    eDisplayModeNormal,
    eDisplayModeAllTags,
    eDisplayModeSource
  };
%}
  readonly attribute boolean              documentModified;
  readonly attribute boolean              documentIsEmpty;
  readonly attribute boolean              documentEditable;   // do we have a doc and editor yet?
  readonly attribute long                 documentLength;
  attribute long                          wrapColumn;
   
  /* Setup */
  void LoadUrl(in wstring url);

  /* Set the value of the <title> tag in the <head> of a document
   * Also uses this to set the editing window caption
   */
  void    SetDocumentTitle(in wstring title);
  /* Get value of the <title> tag */
  wstring GetDocumentTitle();

  /** 
   * doAfterSave saves the new location on the web shell for subsequent
   *     webshell queries and any other necessary functions that can't be done via JS
   * @param aShouldUpdateURL   whether to update the url on the webshell
   * @param aURL               url string; ignored if aShouldUpdateURL is false
   */
  void doAfterSave(in boolean aShouldUpdateURL, in wstring aURL);

  /** 
   * isSupportedTextType determines whether the mime type given is a type the editor
   *      supports (when editing as text)
   * @param aMIMEType    a mimetype string such as "text/plain"
   */
  boolean isSupportedTextType(in string aMIMEType);

  /** Register a doc state listener. This gets added to a list of listeners
     which are registered with the editor when that gets instantiated.
     If the LoadUrl fails, this listener will not receive any notifcations.
     If you call this after the editor has been instantiated, it calls through
     to editor::AddDocumentStateListener().
  */
  void RegisterDocumentStateListener(in nsIDocumentStateListener docListener);
  /** Unregister a listener.
     If you call this after the editor has been instantiated, it calls through
     to editor::RemoveDocumentStateListener().
  */
  void UnregisterDocumentStateListener(in nsIDocumentStateListener docListener);
  
  /* Do any cleanup that needs the content window here
   *   because it's gone by the time destructor is called
  */
  void Shutdown();
                        
  /* check a particular window's URL to see if it matches the given URL */
  boolean checkOpenWindowForURLMatch( in wstring inFileURL, in nsIDOMWindowInternal inCheckWindow); 

  /* Commands */
  void Print();
  
  void Undo();
  void Redo();
  
  void Cut();
  void Copy();
  void Paste(in long selectionType);
  void PasteAsQuotation(in long selectionType);
  void PasteAsCitedQuotation(in wstring cite, in long selectionType);
  
  void InsertAsQuotation(in wstring quotedText, out nsIDOMNode nodeInserted);
  void InsertAsCitedQuotation(in wstring quotedText, in wstring cite,
                              in boolean insertHTML, in wstring charset,
                              out nsIDOMNode nodeInserted);

  void Rewrap(in boolean respectNewlines);
  void StripCites();
  
  void SelectAll();
  void DeleteSelection(in PRInt32 action);
  
  void Find();
  void FindNext();
  void Replace();

  /* General Utilities */

  /* Get string from the Editor's localized string bundle */
  wstring GetString(in wstring name);

  /* Charset Menu */
  wstring GetDocumentCharacterSet();
  void SetDocumentCharacterSet(in wstring characterSet);

  /* Structure change */
  void InsertText(in wstring textToInsert);
  /* Insert HTML source at current location (replace current selection) */
  void InsertSource(in wstring textToInsert);
  void InsertSourceWithCharset(in wstring textToInsert, in wstring charset);

  /** Rebuild the entire document from source HTML
   *  Needed to be able to edit HEAD and other outside-of-BODY content
   *  param source: HTML source string of the entire new document
   */
  void RebuildDocumentFromSource(in wstring source);

  void InsertBreak();
  
  void MakeOrChangeList(in wstring listType, in PRBool entireList, in wstring bulletType);
  void RemoveList(in wstring listType);
  void Indent(in wstring indent);
  void Align(in wstring align);
  
  /** Element insert and property editing */

  /** Let editor handle clicking on a non-text element
    *  to do selection, property editing, etc.
    * Returns true if we "consumed" the event
    */
  boolean HandleMouseClickOnElement(in nsIDOMElement element, in PRInt32 clickCount, in PRInt32 x, in PRInt32 y);

  /** Return an element only if it is the only node selected,
    *    such as an image, horizontal rule, etc.
    * The exception is a link, which is more like a text attribute:
    *    The Anchor tag is returned if the selection is within the textnode(s)
    *    that are children of the "A" node.
    *    This could be a collapsed selection, i.e., a caret within the link text.
    *
    * tagName:  The HTML tagname or and empty string 
    *       to get any element (but only if it is the only element selected)
    *    Special input values for Links and Named anchors:
    *    Use "href" to get a link node
    *      (an "A" tag with the "href" attribute set)
    *    Use "anchor" or "namedanchor" to get a named anchor node
    *      (an "A" tag with the "name" attribute set)
    */
  nsIDOMElement GetSelectedElement(in wstring tagName);

  /** Get first selected node from first selection range.
    * Assumes cell-selection model where each cell
    * is in a separate range (selection parent node is table row)
    * Returns null if ranges don't contain cell selections
    */
  nsIDOMElement GetFirstSelectedCell();
  
  /** Get first selected cell in table: the upper-left-most cell
    * Returns null if ranges don't contain cell selections
    * rowIndex and colIndex are those of the cell if found
    */
  nsIDOMElement GetFirstSelectedCellInTable(out PRInt32 rowIndex, out PRInt32 colIndex );

  /** Get next selected cell element from first selection range.
    * Assumes cell-selection model where each cell
    * is in a separate range (selection parent node is table row)
    * Always call GetFirstSelectedCell() to initialize stored index of "next" cell
    * Returns null if after last cell or 
    *   ranges don't contain cell selections
    */
  nsIDOMElement GetNextSelectedCell();

  /** Return the input node or a parent matching the given aTagName,
    *   starting the search at the supplied node.
    * An example of use is for testing if a node is in a table cell
    *   given a selection anchor node.
    *
    * tagName:  The HTML tagname
    *    Special input values:
    *    Use "href" to get a link node 
    *      (an "A" tag with the "href" attribute set)
    *    Use "anchor" or "namedanchor" to get a named anchor node
    *      (an "A" tag with the "name" attribute set)
    *    Use "list" to get an OL, UL, or DL list node
    *    Use "td" to get either a TD or TH cell node
    *
    * node:    The node in the document to start the search
    *     If it is null, the anchor node of the current selection is used
    */
  nsIDOMElement GetElementOrParentByTagName(in wstring tagName, in nsIDOMNode node);

  /** Return a new element with default attribute values
    * 
    * This does not rely on the selection, and is not sensitive to context.
    * 
    * Used primarily to supply new element for various insert element dialogs
    *  (Image, Link, NamedAnchor, Table, and HorizontalRule 
    *   are the only returned elements as of 7/25/99)
    *
    * tagName:  The HTML tagname
    *    Special input values for Links and Named anchors:
    *    Use "href" to get a link node
    *      (an "A" tag with the "href" attribute set)
    *    Use "anchor" or "namedanchor" to get a named anchor node
    *      (an "A" tag with the "name" attribute set)
    */
  nsIDOMElement CreateElementWithDefaults(in wstring tagName);

  /** Insert an element, which may have child nodes, at the selection
    * Used primarily to insert a new element for various insert element dialogs,
    *   but it enforces the HTML 4.0 DTD "CanContain" rules, so it should
    *   be useful for other elements.
    *
    * element:           The element to insert
    * deleteSelection:   Delete the selection before inserting
    *     If deleteSelection is PR_FALSE, then the element is inserted 
    *     after the end of the selection for all element except
    *     Named Anchors, which insert before the selection
    */  
  void InsertElementAtSelection(in nsIDOMElement element, in boolean deleteSelection);

  /** Insert an link element as the parent of the current selection
    *
    * element   An "A" element with a non-empty "href" attribute
    */
  void InsertLinkAroundSelection(in nsIDOMElement anchorElement);

  /** 
   * Insert an element under parent at position.
   * No checking is done to verify the legality of the insertion.
   *  That is the responsibility of the caller.
   * element:             The DOM element to insert.
   * parent:              The element to insert the new object under
   * position:            The place in parent to insert the new element
   *                        0=first child, 1=second child, etc.
   *                        any number > number of current children = last child
   * dontChangeSelection  If false, selection is set to just after new element
   *                      If true, preserve existing selection 
   *                        (use when inserting under <head> element)
   */
  void InsertElement(in nsIDOMElement element, in nsIDOMElement parent, in PRInt32 position, in PRBool dontChangeSelection);

  /** 
    * DeleteNode removes element from the document
    */
  void DeleteElement(in nsIDOMElement element);

  /** 
    * Deletion methods which need to be accessible to JS:
    */
  void DeleteCharForward();
  void DeleteCharBackward();
  void DeleteWordForward();
  void DeleteWordBackward();
  void DeleteToBeginningOfLine();
  void DeleteToEndOfLine();

  void SelectElement(in nsIDOMElement element);
  void SetSelectionAfterElement(in nsIDOMElement element);
  
  /** Table insert and delete methods.  Done relative to selected cell or
   * cell containing the selection anchor.
   */
  void InsertTableCell(in PRInt32 number, in boolean after);
  void InsertTableRow(in PRInt32 number, in boolean after);
  void InsertTableColumn(in PRInt32 number, in boolean after);
  void DeleteTable();
  void DeleteTableCell(in PRInt32 number);
  void DeleteTableCellContents();
  void DeleteTableRow(in PRInt32 number);
  void DeleteTableColumn(in PRInt32 number);


  /** Create a new TD or TH element, the opposite type of the supplied aSourceCell
    *   1. Copy all attributes from sourceCell to the new cell
    *   2. Move all contents of sourceCell to the new cell
    *   3. Replace sourceCell in the table with the new cell
    *
    *  sourceCell   The cell to be replaced
    *  returns      The new cell that replaces sourceCell
    */
  nsIDOMElement SwitchTableCellHeaderType(in nsIDOMElement sourceCell);

  /** Merges contents of all selected cells
    * for selected cells that are adjacent,
    * this will result in a larger cell with appropriate 
    * rowspan and colspan, and original cells are deleted
    * The resulting cell is in the location of the 
    *   cell at the upper-left corner of the adjacent
    *   block of selected cells
    *
    * mergeNonContiguousContents:  
    *       If true: 
    *         Non-contiguous cells are not deleted,
    *         but their contents are still moved 
    *         to the upper-left cell
    *       If false: contiguous cells are ignored
    *
    * If there are no selected cells,
    *   and selection or caret is in a cell,
    *   that cell and the one to the right 
    *   are merged
    */
  void JoinTableCells(in boolean mergeNonContiguousContents);
  
  /** Split a cell that has rowspan and/or colspan > 0
    *   into cells such that all new cells have 
    *   rowspan = 1 and colspan = 1
    *  All of the contents are not touched --
    *   they will appear to be in the upper-left cell 
    */
  void SplitTableCell();

  /** Table selection methods
    * Selecting a row or column actually
    * selects all cells (not TR in the case of rows)
    */
  void SelectTableCell();
  /** Select a rectangular block of cells:
    *  all cells falling within the row/column index of startCell
    *  to through the row/column index of the endCell
    */
  void SelectBlockOfCells(in nsIDOMElement startCell, in nsIDOMElement endCell);
  void SelectTableRow();
  void SelectTableColumn();
  void SelectTable();
  void SelectAllTableCells();

  /** 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);
  PRInt32 GetColumnIndex(in nsIDOMElement cellElement);

  /** Get the number of rows in a table from the layout's cellmap 
    * If tableElement is null, it will try to find enclosing table of selection anchor
    */
  PRInt32 GetTableRowCount(in nsIDOMElement tableElement);

  /** Get the number of columns in a table from the layout's cellmap
    * If tableElement is null, it will try to find enclosing table of selection anchor
    */
  PRInt32 GetTableColumnCount(in nsIDOMElement tableElement);

  /** Get cell at a location in the layout's cellmap
    * returns null when past last cell in a row or column
    * If tableElement is null, it will try to find enclosing table of selection anchor
    */
  nsIDOMElement GetCellAt(in nsIDOMElement tableElement, in PRInt32 rowIndex, in PRInt32 colIndex);

  /** Get cell at a location in the layout's cellmap with associated data 
    * returns null when past last cell in a row or column 
    * Note that rowSpan and/or colSpan may be 0 (for extending across entire table),
    * so actualRowSpan and actualColSpan are the real number of cells spanned
    * If tableElement is null, it will try to find enclosing table of selection anchor
    */
  nsIDOMElement GetCellDataAt(in nsIDOMElement tableElement, in PRInt32 rowIndex, in PRInt32 colIndex,
                              out PRInt32 startRowIndex, out PRInt32 startColIndex,
                              out PRInt32 rowSpan, out PRInt32 colSpan, 
                              out PRInt32 actualRowSpan, out PRInt32 actualColSpan, 
                              out boolean isSelected);
  
  /** Get the first row in a table 
    * tableElement may be a table or any child element a table
    */
  nsIDOMNode GetFirstRow(in nsIDOMElement tableElement);

  /** Get the next row in a table after currentRow 
    */
  nsIDOMNode GetNextRow(in nsIDOMNode currentRow);

  /** Examine the current selection and find
    *   a selected TABLE, TD or TH, or TR element.
    *   or return the parent TD or TH if selection anchor is inside a table cell
    *   Returns null if no table element is found.
    *
    * Returns:
    *   The table element (table, row, or cell) found
    *     If multiple table cells are selected, this is the "focus" cell (last cell selected)
    *
    *   tagName           The tagname of returned element
    *                       Note that "td" will be returned if name is actually "th"
    *   selectedCount     How many table elements were selected
    *                       This tells us if we have multiple cells selected
    *                       (0 if element is a parent cell of selection)
    */
  nsIDOMElement GetSelectedOrParentTableElement(out wstring tagName, out PRInt32 selectedCount);

  /** Generally used after GetSelectedOrParentTableElement
    *   to test if selected cells are complete rows or columns
    * 
    * cellElement               Any table, cell, or element inside a table
    *                           Used to get enclosing table. 
    *                           If null, selection's focusNode is used
    * 
    * Returns: (defines are from nsIFrameSelection.h)
    *  0                         cellElement was not a cell
    *  1 (TABLESELECTION_CELL)   There are 1 or more cells selected
    *                              but complete rows or columns are not selected
    *  2 (TABLESELECTION_ROW)    All cells are in 1 or more rows
    *                              and in each row, all cells selected
    *                              Note: This is the value if all rows (thus all cells) are selected
    *  3 (TABLESELECTION_COLUMN) All cells are in 1 or more columns
    *                              and in each column, all cells are selected
    */
  PRUint32 GetSelectedCellsType(in nsIDOMElement element);

  /**** end of table editing *****/

  /* Get list of embedded objects, e.g. for mail compose */
  nsISupportsArray GetEmbeddedObjects();

  /* Get list of objects which refer to external URIs */
  nsISupportsArray GetLinkedObjects();

  /* Formatting */
  void SetAttribute(in nsIDOMElement element, in wstring attr, in wstring value);
  void RemoveAttribute(in nsIDOMElement element, in wstring attr);
  void SetTextProperty(in wstring prop, in wstring attr, in wstring value);
  void RemoveTextProperty(in wstring prop, in wstring attr);
  void GetTextProperty(in wstring prop, in wstring attr, in wstring value, out boolean firstHas, out boolean anyHas, out boolean allHas);
  void IncreaseFontSize();
  void DecreaseFontSize();
  void SetParagraphFormat(in wstring paragraphFormat); 
  void SetBodyAttribute(in wstring attr, in wstring value);
  void SetBackgroundColor(in wstring color);

  /** Get block state information:
    * Returns the tagname if part selection is within a 
    *   paragraph or list block tag,
    *   or empty string if none of selection isn't within the block
    *
    *   mixed    true if only part of selection has the state
    */

  /* Returns "p","blockquote", "address", "pre", "dt", "dd" 
     or "h1" through "h6" */
  wstring GetParagraphState(out boolean mixed);
  /* Returns "ol", "ul", or "dl" */
  wstring GetListState(out boolean mixed);
  /* Returns "li", "dt", or "dd" */
  wstring GetListItemState(out boolean mixed);
  /* Returns "left", "center", or "right" */
  wstring GetAlignment(out boolean mixed);

  void ApplyStyleSheet(in wstring url);

  /** Set the display mode for editing
    * displayMode
    *       0 (eDisplayModeWYSIWIG) Preview mode
    *           that looks exactly like the browser display except
    *           for certain behaviors like cursor style over links, etc.
    *       1 (eDisplayModeNormal) Use minimal extra CSS style 
    *           (from override styles in EditorContent.css) 
    *           to show named anchors, table borders, etc for editing
    *       2 (eDisplayModeAllTags) Use maximum extra CSS style 
    *           (from override styles in EditorAllTags.css) 
    *           to show icon for every HTML tag
    */
  void SetDisplayMode(in PRInt32 displayMode);

  /** Get current mode for editing
    *  Returns:
    *  0 (eDisplayModePreview,)
    *  1 (eDisplayModeNormal)
    *  2 (eDisplayModeAllTags)
    *  3 (eDisplayModeSource)
    */
  PRInt32 GetEditMode();
  
  /** For quicker test if we are in HTML Source mode
    */
  boolean IsHTMLSourceMode();

  /** Save the current HTML source edit session
    *  by inserting it into the document,
    *  replacing existing DOM
    */
  void FinishHTMLSource();

  /** Add/remove an overridestyle sheet to show paragraph marks
    *
    */
  void DisplayParagraphMarks(in PRBool showMarks);

  /* Output.
   * format is mime type, e.g. text/html;
   * See nsIEditor.h for legal flag values.
   *
   * Get the contents, for output or other uses
   */
  wstring GetContentsAs(in wstring format, in PRUint32 flags);

  /* Get the contents of the <head> section of the document 
   * Format is text/html
   */
  wstring GetHeadContentsAsHTML();

  /* Replace all contents in head with the HTML string supplied
   * It will be inserted using InsertSource
   */
  void ReplaceHeadContentsWithHTML(in wstring textToInsert);

  /* Debugging: dump content tree to stdout */
  void DumpContentTree();

  /**
   * Tests if a node is a BLOCK element according the the HTML 4.0 DTD
   *   This does NOT consider CSS effect on display type
   */
  boolean NodeIsBlock(in nsIDOMNode node);

  /**
   * This is similar to nsIDOMNode::cloneNode(),
   *   it assures the attribute nodes of the destination are identical with the source node
   *   by copying all existing attributes from the source and deleting those not in the source.
   *   This is used when the destination node (element) already exists
   *
   * The supplied nodes MUST BE ELEMENTS (most callers are working with nodes)
   * destNode     the destination element to operate on
   * sourceNode   the source element to copy attributes from
   */
  void CloneAttributes(in nsIDOMNode destNode, in nsIDOMNode sourceNode);

  void BeginBatchChanges();
  void EndBatchChanges();
  void RunUnitTests();

  void StartLogging(in nsIFile logFile);
  void StopLogging();
  
  void CloseWindowWithoutSaving();
};
