/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 *
 * 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 Netscape are
 * Copyright (C) 1998 Netscape Communications Corporation. All
 * Rights Reserved.
 *
 * Contributor(s): 
 */
 
#include "nsISupports.idl"
#include "domstubs.idl"
#include "nsIFileSpec.idl"
#include "nsISupportsArray.idl"
#include "nsIDocumentStateListener.idl"
#include "nsISelectionController.idl"

%{C++

class nsIDOMWindow;
class nsIDOMDocument;
class nsIDOMSelection;
class nsIDOMElement;
class nsIDOMNode;

%}

interface nsIFileSpec;
interface nsIEditor;

[scriptable, uuid(9afff72b-ca9a-11d2-96c9-0060b0fb9956)]
interface nsIEditorShell : nsISupports
{
  readonly attribute nsIDOMDocument    editorDocument;
  readonly attribute nsIDOMSelection   editorSelection;
  readonly attribute nsISelectionController   selectionController;
  
           attribute nsIDOMWindow      webShellWindow;
           attribute nsIDOMWindow      contentWindow;
           
  [noscript] 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 SetEditorType(in wstring editorType);

  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();
  
  /** 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);
  
  void Init();
  
  /* Do any cleanup that needs the content window here
   *   because it's gone by the time destructor is called
  */
  void Shutdown();
  
  /** Access for the common alert dialog 
    *
    * title   Title (caption) of the dialog
    * msg     Message in the dialog
    *
    * Dialog contains an "Ok" button. No return value
    */
  void AlertWithTitle(in wstring title, in wstring msg);
  
  /** Access for the common alert dialog 
    *
    * title           Title (caption) of the dialog
    * question        Question asked of the user 
    * yesButtonText   Text for the "Yes" button
    *                 If empty, "Yes" will be used
    * noButtonText    Text for the "No" button.
    *                 If empty, the button will not be displayed
    *
    * Dialog always has a "Cancel" button
    * Button order follows platform-specific rules
    *
    * Returns:  0   Yes button pressed
    *           1   Cancel button pressed
    *           2   No button pressed
    */
  PRInt32 ConfirmWithTitle(in wstring title, in wstring question,
                           in wstring yesButtonText, in wstring noButtonText);

  /* check a particular window's URL to see if it matches the given URL */
  boolean checkOpenWindowForURLMatch( in wstring inFileURL, in nsIDOMWindow inCheckWindow); 

  /* Commands */
  /** 
   *  @param saveAs false to try to save to existing file
   *          If document is not already saved, it is treated as true
   *          so filename is prompted.
   *  @param saveCopy       
   *          true if we are saving off a copy of the document
   *          without changing the disk file associated with the doc.
   *          This would correspond to a 'Save Copy As' menu command
   *          (currently not in our UI)
   *  return value
   *          true if file was really saved.
   *          false if there is some problem with saving or user
   *          executed "Cancel" when prompted for a filename to save
   */  
  boolean saveDocument(in boolean saveAs, in boolean saveCopy);
  
  /** Check if current document has changes and prompt to save if it does.
   *  return value:
   *         false ONLY if user executed "Cancel" in the SaveAs dialog
   *         true if no changes in doc, or file was saved successfully
   *  @param reasonToSave 
   *         A string to append after "Save changes to <URL>"
   *         If null, just the question mark will be appended
   */
  boolean  CheckAndSaveDocument(in wstring reasonToSave);

  boolean CloseWindow();
  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();

  /* General Utilities */

  /* UI updating
   * tagToUpdate can be null or "" to update everything  
  */
  void UpdateInterfaceState(in wstring tagToUpdate);

  /* 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 */
       /* TypedText actionToTake param is an enum - values in nsIHTMLEditor.h */
  void TypedText(in wstring textToInsert, in PRInt32 actionToTake);
  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);
  void InsertBreak();
  
  void MakeOrChangeList(in wstring listType);
  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
   */
  void InsertElement(in nsIDOMElement element, in nsIDOMElement parent, in PRInt32 position);

  /** 
    * 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 element in a table 
    * tableElement may be a table or any child element a table
    */
  nsIDOMElement GetFirstRow(in nsIDOMElement tableElement);

  /** Get the next row element in a table after currentRow 
    * currentRow may be a row or any child element of a row
    */
  nsIDOMElement GetNextRow(in nsIDOMElement 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();

  /* 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);

  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();

  /* Utility */
  wstring GetLocalFileURL(in nsIDOMWindow parent, in wstring filterType);

  /**
   * 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 nsIFileSpec logFile);
  void StopLogging();
  
};
