LCOV - code coverage report
Current view: directory - editor/libeditor/html - nsHTMLEditUtils.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 226 0 0.0 %
Date: 2012-06-02 Functions: 36 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : #include "nsHTMLEditUtils.h"
      39                 : 
      40                 : #include "mozilla/Assertions.h"
      41                 : #include "mozilla/Util.h"
      42                 : #include "mozilla/dom/Element.h"
      43                 : 
      44                 : #include "nsTextEditUtils.h"
      45                 : 
      46                 : #include "nsString.h"
      47                 : #include "nsUnicharUtils.h"
      48                 : #include "nsEditor.h"
      49                 : #include "nsEditProperty.h"
      50                 : #include "nsIAtom.h"
      51                 : #include "nsIDOMNode.h"
      52                 : #include "nsIContent.h"
      53                 : #include "nsIDOMNodeList.h"
      54                 : #include "nsIDOMHTMLAnchorElement.h"
      55                 : #include "nsHTMLTags.h"
      56                 : 
      57                 : using namespace mozilla;
      58                 : 
      59                 : ///////////////////////////////////////////////////////////////////////////
      60                 : //                  
      61                 : bool 
      62               0 : nsHTMLEditUtils::IsBig(nsIDOMNode *node)
      63                 : {
      64               0 :   return nsEditor::NodeIsType(node, nsEditProperty::big);
      65                 : }
      66                 : 
      67                 : 
      68                 : ///////////////////////////////////////////////////////////////////////////
      69                 : // IsInlineStyle true if node is an inline style
      70                 : //                  
      71                 : bool 
      72               0 : nsHTMLEditUtils::IsInlineStyle(nsIDOMNode *node)
      73                 : {
      74               0 :   NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsInlineStyle");
      75               0 :   nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(node);
      76               0 :   return (nodeAtom == nsEditProperty::b)
      77               0 :       || (nodeAtom == nsEditProperty::i)
      78               0 :       || (nodeAtom == nsEditProperty::u)
      79               0 :       || (nodeAtom == nsEditProperty::tt)
      80               0 :       || (nodeAtom == nsEditProperty::s)
      81               0 :       || (nodeAtom == nsEditProperty::strike)
      82               0 :       || (nodeAtom == nsEditProperty::big)
      83               0 :       || (nodeAtom == nsEditProperty::small)
      84               0 :       || (nodeAtom == nsEditProperty::blink)
      85               0 :       || (nodeAtom == nsEditProperty::sub)
      86               0 :       || (nodeAtom == nsEditProperty::sup)
      87               0 :       || (nodeAtom == nsEditProperty::font);
      88                 : }
      89                 : 
      90                 : ///////////////////////////////////////////////////////////////////////////
      91                 : // IsFormatNode true if node is a format node
      92                 : // 
      93                 : bool
      94               0 : nsHTMLEditUtils::IsFormatNode(nsIDOMNode *node)
      95                 : {
      96               0 :   NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsFormatNode");
      97               0 :   nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(node);
      98               0 :   return (nodeAtom == nsEditProperty::p)
      99               0 :       || (nodeAtom == nsEditProperty::pre)
     100               0 :       || (nodeAtom == nsEditProperty::h1)
     101               0 :       || (nodeAtom == nsEditProperty::h2)
     102               0 :       || (nodeAtom == nsEditProperty::h3)
     103               0 :       || (nodeAtom == nsEditProperty::h4)
     104               0 :       || (nodeAtom == nsEditProperty::h5)
     105               0 :       || (nodeAtom == nsEditProperty::h6)
     106               0 :       || (nodeAtom == nsEditProperty::address);
     107                 : }
     108                 : 
     109                 : ///////////////////////////////////////////////////////////////////////////
     110                 : // IsNodeThatCanOutdent true if node is a list, list item, or blockquote      
     111                 : //
     112                 : bool
     113               0 : nsHTMLEditUtils::IsNodeThatCanOutdent(nsIDOMNode *node)
     114                 : {
     115               0 :   NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsNodeThatCanOutdent");
     116               0 :   nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(node);
     117               0 :   return (nodeAtom == nsEditProperty::ul)
     118               0 :       || (nodeAtom == nsEditProperty::ol)
     119               0 :       || (nodeAtom == nsEditProperty::dl)
     120               0 :       || (nodeAtom == nsEditProperty::li)
     121               0 :       || (nodeAtom == nsEditProperty::dd)
     122               0 :       || (nodeAtom == nsEditProperty::dt)
     123               0 :       || (nodeAtom == nsEditProperty::blockquote);
     124                 : }
     125                 : 
     126                 : ///////////////////////////////////////////////////////////////////////////
     127                 : //                  
     128                 : bool 
     129               0 : nsHTMLEditUtils::IsSmall(nsIDOMNode *node)
     130                 : {
     131               0 :   return nsEditor::NodeIsType(node, nsEditProperty::small);
     132                 : }
     133                 : 
     134                 : 
     135                 : /********************************************************
     136                 :  *  helper methods from nsHTMLEditRules
     137                 :  ********************************************************/
     138                 :  
     139                 : ///////////////////////////////////////////////////////////////////////////
     140                 : // IsHeader: true if node an html header
     141                 : //                  
     142                 : bool 
     143               0 : nsHTMLEditUtils::IsHeader(nsIDOMNode *node)
     144                 : {
     145               0 :   NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsHeader");
     146               0 :   nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(node);
     147               0 :   return (nodeAtom == nsEditProperty::h1)
     148               0 :       || (nodeAtom == nsEditProperty::h2)
     149               0 :       || (nodeAtom == nsEditProperty::h3)
     150               0 :       || (nodeAtom == nsEditProperty::h4)
     151               0 :       || (nodeAtom == nsEditProperty::h5)
     152               0 :       || (nodeAtom == nsEditProperty::h6);
     153                 : }
     154                 : 
     155                 : 
     156                 : ///////////////////////////////////////////////////////////////////////////
     157                 : // IsParagraph: true if node an html paragraph
     158                 : //                  
     159                 : bool 
     160               0 : nsHTMLEditUtils::IsParagraph(nsIDOMNode *node)
     161                 : {
     162               0 :   return nsEditor::NodeIsType(node, nsEditProperty::p);
     163                 : }
     164                 : 
     165                 : 
     166                 : ///////////////////////////////////////////////////////////////////////////
     167                 : // IsHR: true if node an horizontal rule
     168                 : //                  
     169                 : bool 
     170               0 : nsHTMLEditUtils::IsHR(nsIDOMNode *node)
     171                 : {
     172               0 :   return nsEditor::NodeIsType(node, nsEditProperty::hr);
     173                 : }
     174                 : 
     175                 : 
     176                 : ///////////////////////////////////////////////////////////////////////////
     177                 : // IsListItem: true if node an html list item
     178                 : //                  
     179                 : bool 
     180               0 : nsHTMLEditUtils::IsListItem(nsIDOMNode *node)
     181                 : {
     182               0 :   NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsListItem");
     183               0 :   nsCOMPtr<dom::Element> element = do_QueryInterface(node);
     184               0 :   return element && IsListItem(element);
     185                 : }
     186                 : 
     187                 : bool
     188               0 : nsHTMLEditUtils::IsListItem(dom::Element* node)
     189                 : {
     190               0 :   MOZ_ASSERT(node);
     191               0 :   nsCOMPtr<nsIAtom> nodeAtom = node->Tag();
     192               0 :   return (nodeAtom == nsEditProperty::li)
     193               0 :       || (nodeAtom == nsEditProperty::dd)
     194               0 :       || (nodeAtom == nsEditProperty::dt);
     195                 : }
     196                 : 
     197                 : 
     198                 : ///////////////////////////////////////////////////////////////////////////
     199                 : // IsTableElement: true if node an html table, td, tr, ...
     200                 : //                  
     201                 : bool
     202               0 : nsHTMLEditUtils::IsTableElement(nsIDOMNode *node)
     203                 : {
     204               0 :   NS_PRECONDITION(node, "null node passed to nsHTMLEditor::IsTableElement");
     205               0 :   nsCOMPtr<dom::Element> element = do_QueryInterface(node);
     206               0 :   return element && IsTableElement(element);
     207                 : }
     208                 : 
     209                 : bool
     210               0 : nsHTMLEditUtils::IsTableElement(dom::Element* node)
     211                 : {
     212               0 :   MOZ_ASSERT(node);
     213               0 :   nsCOMPtr<nsIAtom> nodeAtom = node->Tag();
     214               0 :   return (nodeAtom == nsEditProperty::table)
     215               0 :       || (nodeAtom == nsEditProperty::tr)
     216               0 :       || (nodeAtom == nsEditProperty::td)
     217               0 :       || (nodeAtom == nsEditProperty::th)
     218               0 :       || (nodeAtom == nsEditProperty::thead)
     219               0 :       || (nodeAtom == nsEditProperty::tfoot)
     220               0 :       || (nodeAtom == nsEditProperty::tbody)
     221               0 :       || (nodeAtom == nsEditProperty::caption);
     222                 : }
     223                 : 
     224                 : ///////////////////////////////////////////////////////////////////////////
     225                 : // IsTableElementButNotTable: true if node an html td, tr, ... (doesn't include table)
     226                 : //                  
     227                 : bool 
     228               0 : nsHTMLEditUtils::IsTableElementButNotTable(nsIDOMNode *node)
     229                 : {
     230               0 :   NS_PRECONDITION(node, "null node passed to nsHTMLEditor::IsTableElementButNotTable");
     231               0 :   nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(node);
     232               0 :   return (nodeAtom == nsEditProperty::tr)
     233               0 :       || (nodeAtom == nsEditProperty::td)
     234               0 :       || (nodeAtom == nsEditProperty::th)
     235               0 :       || (nodeAtom == nsEditProperty::thead)
     236               0 :       || (nodeAtom == nsEditProperty::tfoot)
     237               0 :       || (nodeAtom == nsEditProperty::tbody)
     238               0 :       || (nodeAtom == nsEditProperty::caption);
     239                 : }
     240                 : 
     241                 : ///////////////////////////////////////////////////////////////////////////
     242                 : // IsTable: true if node an html table
     243                 : //                  
     244                 : bool 
     245               0 : nsHTMLEditUtils::IsTable(nsIDOMNode *node)
     246                 : {
     247               0 :   return nsEditor::NodeIsType(node, nsEditProperty::table);
     248                 : }
     249                 : 
     250                 : ///////////////////////////////////////////////////////////////////////////
     251                 : // IsTableRow: true if node an html tr
     252                 : //                  
     253                 : bool 
     254               0 : nsHTMLEditUtils::IsTableRow(nsIDOMNode *node)
     255                 : {
     256               0 :   return nsEditor::NodeIsType(node, nsEditProperty::tr);
     257                 : }
     258                 : 
     259                 : 
     260                 : ///////////////////////////////////////////////////////////////////////////
     261                 : // IsTableCell: true if node an html td or th
     262                 : //                  
     263                 : bool 
     264               0 : nsHTMLEditUtils::IsTableCell(nsIDOMNode *node)
     265                 : {
     266               0 :   NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsTableCell");
     267               0 :   nsCOMPtr<dom::Element> element = do_QueryInterface(node);
     268               0 :   return element && IsTableCell(element);
     269                 : }
     270                 : 
     271                 : bool
     272               0 : nsHTMLEditUtils::IsTableCell(dom::Element* node)
     273                 : {
     274               0 :   MOZ_ASSERT(node);
     275               0 :   nsCOMPtr<nsIAtom> nodeAtom = node->Tag();
     276               0 :   return (nodeAtom == nsEditProperty::td)
     277               0 :       || (nodeAtom == nsEditProperty::th);
     278                 : }
     279                 : 
     280                 : 
     281                 : ///////////////////////////////////////////////////////////////////////////
     282                 : // IsTableCell: true if node an html td or th
     283                 : //                  
     284                 : bool 
     285               0 : nsHTMLEditUtils::IsTableCellOrCaption(nsIDOMNode *node)
     286                 : {
     287               0 :   NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsTableCell");
     288               0 :   nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(node);
     289               0 :   return (nodeAtom == nsEditProperty::td)
     290               0 :       || (nodeAtom == nsEditProperty::th)
     291               0 :       || (nodeAtom == nsEditProperty::caption);
     292                 : }
     293                 : 
     294                 : 
     295                 : ///////////////////////////////////////////////////////////////////////////
     296                 : // IsList: true if node an html list
     297                 : //                  
     298                 : bool
     299               0 : nsHTMLEditUtils::IsList(nsIDOMNode *node)
     300                 : {
     301               0 :   NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsList");
     302               0 :   nsCOMPtr<dom::Element> element = do_QueryInterface(node);
     303               0 :   return element && IsList(element);
     304                 : }
     305                 : 
     306                 : bool
     307               0 : nsHTMLEditUtils::IsList(dom::Element* node)
     308                 : {
     309               0 :   MOZ_ASSERT(node);
     310               0 :   nsCOMPtr<nsIAtom> nodeAtom = node->Tag();
     311               0 :   return (nodeAtom == nsEditProperty::ul)
     312               0 :       || (nodeAtom == nsEditProperty::ol)
     313               0 :       || (nodeAtom == nsEditProperty::dl);
     314                 : }
     315                 : 
     316                 : 
     317                 : ///////////////////////////////////////////////////////////////////////////
     318                 : // IsOrderedList: true if node an html ordered list
     319                 : //                  
     320                 : bool 
     321               0 : nsHTMLEditUtils::IsOrderedList(nsIDOMNode *node)
     322                 : {
     323               0 :   return nsEditor::NodeIsType(node, nsEditProperty::ol);
     324                 : }
     325                 : 
     326                 : 
     327                 : ///////////////////////////////////////////////////////////////////////////
     328                 : // IsUnorderedList: true if node an html unordered list
     329                 : //                  
     330                 : bool 
     331               0 : nsHTMLEditUtils::IsUnorderedList(nsIDOMNode *node)
     332                 : {
     333               0 :   return nsEditor::NodeIsType(node, nsEditProperty::ul);
     334                 : }
     335                 : 
     336                 : 
     337                 : ///////////////////////////////////////////////////////////////////////////
     338                 : // IsBlockquote: true if node an html blockquote node
     339                 : //                  
     340                 : bool 
     341               0 : nsHTMLEditUtils::IsBlockquote(nsIDOMNode *node)
     342                 : {
     343               0 :   return nsEditor::NodeIsType(node, nsEditProperty::blockquote);
     344                 : }
     345                 : 
     346                 : 
     347                 : ///////////////////////////////////////////////////////////////////////////
     348                 : // IsPre: true if node an html pre node
     349                 : //                  
     350                 : bool 
     351               0 : nsHTMLEditUtils::IsPre(nsIDOMNode *node)
     352                 : {
     353               0 :   return nsEditor::NodeIsType(node, nsEditProperty::pre);
     354                 : }
     355                 : 
     356                 : 
     357                 : ///////////////////////////////////////////////////////////////////////////
     358                 : // IsImage: true if node an html image node
     359                 : //                  
     360                 : bool 
     361               0 : nsHTMLEditUtils::IsImage(nsIDOMNode *node)
     362                 : {
     363               0 :   return nsEditor::NodeIsType(node, nsEditProperty::img);
     364                 : }
     365                 : 
     366                 : bool 
     367               0 : nsHTMLEditUtils::IsLink(nsIDOMNode *aNode)
     368                 : {
     369               0 :   NS_ENSURE_TRUE(aNode, false);
     370               0 :   nsCOMPtr<nsIDOMHTMLAnchorElement> anchor = do_QueryInterface(aNode);
     371               0 :   if (anchor)
     372                 :   {
     373               0 :     nsAutoString tmpText;
     374               0 :     if (NS_SUCCEEDED(anchor->GetHref(tmpText)) && !tmpText.IsEmpty())
     375               0 :       return true;
     376                 :   }
     377               0 :   return false;
     378                 : }
     379                 : 
     380                 : bool 
     381               0 : nsHTMLEditUtils::IsNamedAnchor(nsIDOMNode *aNode)
     382                 : {
     383               0 :   nsCOMPtr<dom::Element> element = do_QueryInterface(aNode);
     384               0 :   return element && IsNamedAnchor(element);
     385                 : }
     386                 : 
     387                 : bool
     388               0 : nsHTMLEditUtils::IsNamedAnchor(dom::Element* aNode)
     389                 : {
     390               0 :   MOZ_ASSERT(aNode);
     391               0 :   if (!aNode->IsHTML(nsGkAtoms::a)) {
     392               0 :     return false;
     393                 :   }
     394                 : 
     395               0 :   nsAutoString text;
     396               0 :   return aNode->GetAttr(kNameSpaceID_None, nsGkAtoms::name, text) &&
     397               0 :          !text.IsEmpty();
     398                 : }
     399                 : 
     400                 : 
     401                 : ///////////////////////////////////////////////////////////////////////////
     402                 : // IsDiv: true if node an html div node
     403                 : //                  
     404                 : bool 
     405               0 : nsHTMLEditUtils::IsDiv(nsIDOMNode *node)
     406                 : {
     407               0 :   return nsEditor::NodeIsType(node, nsEditProperty::div);
     408                 : }
     409                 : 
     410                 : 
     411                 : ///////////////////////////////////////////////////////////////////////////
     412                 : // IsMozDiv: true if node an html div node with type = _moz
     413                 : //                  
     414                 : bool 
     415               0 : nsHTMLEditUtils::IsMozDiv(nsIDOMNode *node)
     416                 : {
     417               0 :   if (IsDiv(node) && nsTextEditUtils::HasMozAttr(node)) return true;
     418               0 :   return false;
     419                 : }
     420                 : 
     421                 : 
     422                 : 
     423                 : ///////////////////////////////////////////////////////////////////////////
     424                 : // IsMailCite: true if node an html blockquote with type=cite
     425                 : //                  
     426                 : bool 
     427               0 : nsHTMLEditUtils::IsMailCite(nsIDOMNode *node)
     428                 : {
     429               0 :   NS_PRECONDITION(node, "null parent passed to nsHTMLEditUtils::IsMailCite");
     430               0 :   nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(node);
     431               0 :   if (!elem) {
     432               0 :     return false;
     433                 :   }
     434               0 :   nsAutoString attrName (NS_LITERAL_STRING("type")); 
     435                 :   
     436                 :   // don't ask me why, but our html mailcites are id'd by "type=cite"...
     437               0 :   nsAutoString attrVal;
     438               0 :   nsresult res = elem->GetAttribute(attrName, attrVal);
     439               0 :   ToLowerCase(attrVal);
     440               0 :   if (NS_SUCCEEDED(res))
     441                 :   {
     442               0 :     if (attrVal.EqualsLiteral("cite"))
     443               0 :       return true;
     444                 :   }
     445                 : 
     446                 :   // ... but our plaintext mailcites by "_moz_quote=true".  go figure.
     447               0 :   attrName.AssignLiteral("_moz_quote");
     448               0 :   res = elem->GetAttribute(attrName, attrVal);
     449               0 :   if (NS_SUCCEEDED(res))
     450                 :   {
     451               0 :     ToLowerCase(attrVal);
     452               0 :     if (attrVal.EqualsLiteral("true"))
     453               0 :       return true;
     454                 :   }
     455                 : 
     456               0 :   return false;
     457                 : }
     458                 : 
     459                 : 
     460                 : ///////////////////////////////////////////////////////////////////////////
     461                 : // IsFormWidget: true if node is a form widget of some kind
     462                 : //                  
     463                 : bool
     464               0 : nsHTMLEditUtils::IsFormWidget(nsIDOMNode *node)
     465                 : {
     466               0 :   NS_PRECONDITION(node, "null node passed to nsHTMLEditUtils::IsFormWidget");
     467               0 :   nsCOMPtr<dom::Element> element = do_QueryInterface(node);
     468               0 :   return element && IsFormWidget(element);
     469                 : }
     470                 : 
     471                 : bool
     472               0 : nsHTMLEditUtils::IsFormWidget(dom::Element* node)
     473                 : {
     474               0 :   MOZ_ASSERT(node);
     475               0 :   nsCOMPtr<nsIAtom> nodeAtom = node->Tag();
     476               0 :   return (nodeAtom == nsEditProperty::textarea)
     477               0 :       || (nodeAtom == nsEditProperty::select)
     478               0 :       || (nodeAtom == nsEditProperty::button)
     479               0 :       || (nodeAtom == nsEditProperty::output)
     480               0 :       || (nodeAtom == nsEditProperty::keygen)
     481               0 :       || (nodeAtom == nsEditProperty::progress)
     482               0 :       || (nodeAtom == nsEditProperty::input);
     483                 : }
     484                 : 
     485                 : bool
     486               0 : nsHTMLEditUtils::SupportsAlignAttr(nsIDOMNode * aNode)
     487                 : {
     488               0 :   NS_PRECONDITION(aNode, "null node passed to nsHTMLEditUtils::SupportsAlignAttr");
     489               0 :   nsCOMPtr<nsIAtom> nodeAtom = nsEditor::GetTag(aNode);
     490               0 :   return (nodeAtom == nsEditProperty::hr)
     491               0 :       || (nodeAtom == nsEditProperty::table)
     492               0 :       || (nodeAtom == nsEditProperty::tbody)
     493               0 :       || (nodeAtom == nsEditProperty::tfoot)
     494               0 :       || (nodeAtom == nsEditProperty::thead)
     495               0 :       || (nodeAtom == nsEditProperty::tr)
     496               0 :       || (nodeAtom == nsEditProperty::td)
     497               0 :       || (nodeAtom == nsEditProperty::th)
     498               0 :       || (nodeAtom == nsEditProperty::div)
     499               0 :       || (nodeAtom == nsEditProperty::p)
     500               0 :       || (nodeAtom == nsEditProperty::h1)
     501               0 :       || (nodeAtom == nsEditProperty::h2)
     502               0 :       || (nodeAtom == nsEditProperty::h3)
     503               0 :       || (nodeAtom == nsEditProperty::h4)
     504               0 :       || (nodeAtom == nsEditProperty::h5)
     505               0 :       || (nodeAtom == nsEditProperty::h6);
     506                 : }
     507                 : 
     508                 : // We use bitmasks to test containment of elements. Elements are marked to be
     509                 : // in certain groups by setting the mGroup member of the nsElementInfo struct
     510                 : // to the corresponding GROUP_ values (OR'ed together). Similarly, elements are
     511                 : // marked to allow containment of certain groups by setting the
     512                 : // mCanContainGroups member of the nsElementInfo struct to the corresponding
     513                 : // GROUP_ values (OR'ed together).
     514                 : // Testing containment then simply consists of checking whether the
     515                 : // mCanContainGroups bitmask of an element and the mGroup bitmask of a
     516                 : // potential child overlap.
     517                 : 
     518                 : #define GROUP_NONE             0
     519                 : 
     520                 : // body, head, html
     521                 : #define GROUP_TOPLEVEL         (1 << 1)  
     522                 : 
     523                 : // base, link, meta, script, style, title
     524                 : #define GROUP_HEAD_CONTENT     (1 << 2)
     525                 : 
     526                 : // b, big, i, s, small, strike, tt, u
     527                 : #define GROUP_FONTSTYLE        (1 << 3)
     528                 : 
     529                 : // abbr, acronym, cite, code, datalist, del, dfn, em, ins, kbd, mark, samp,
     530                 : // strong, var
     531                 : #define GROUP_PHRASE           (1 << 4)
     532                 : 
     533                 : // a, applet, basefont, bdo, br, font, iframe, img, map, object, output,
     534                 : // progress, q, script, span, sub, sup
     535                 : #define GROUP_SPECIAL          (1 << 5)
     536                 : 
     537                 : // button, form, input, label, select, textarea
     538                 : #define GROUP_FORMCONTROL      (1 << 6)
     539                 : 
     540                 : // address, applet, article, aside, blockquote, button, center, del, dir, div,
     541                 : // dl, fieldset, figure, footer, form, h1, h2, h3, h4, h5, h6, header, hgroup,
     542                 : // hr, iframe, ins, map, menu, nav, noframes, noscript, object, ol, p,
     543                 : // pre, table, section, ul
     544                 : #define GROUP_BLOCK            (1 << 7)
     545                 : 
     546                 : // frame, frameset
     547                 : #define GROUP_FRAME            (1 << 8)
     548                 : 
     549                 : // col, tbody
     550                 : #define GROUP_TABLE_CONTENT    (1 << 9)
     551                 : 
     552                 : // tr
     553                 : #define GROUP_TBODY_CONTENT    (1 << 10)
     554                 : 
     555                 : // td, th
     556                 : #define GROUP_TR_CONTENT       (1 << 11)
     557                 : 
     558                 : // col
     559                 : #define GROUP_COLGROUP_CONTENT (1 << 12)
     560                 : 
     561                 : // param
     562                 : #define GROUP_OBJECT_CONTENT   (1 << 13)
     563                 : 
     564                 : // li
     565                 : #define GROUP_LI               (1 << 14)
     566                 : 
     567                 : // area
     568                 : #define GROUP_MAP_CONTENT      (1 << 15)
     569                 : 
     570                 : // optgroup, option
     571                 : #define GROUP_SELECT_CONTENT   (1 << 16)
     572                 : 
     573                 : // option
     574                 : #define GROUP_OPTIONS          (1 << 17)
     575                 : 
     576                 : // dd, dt
     577                 : #define GROUP_DL_CONTENT       (1 << 18)
     578                 : 
     579                 : // p
     580                 : #define GROUP_P                (1 << 19)
     581                 : 
     582                 : // text, whitespace, newline, comment
     583                 : #define GROUP_LEAF             (1 << 20)
     584                 : 
     585                 : // XXX This is because the editor does sublists illegally. 
     586                 : // ol, ul
     587                 : #define GROUP_OL_UL            (1 << 21)
     588                 : 
     589                 : // h1, h2, h3, h4, h5, h6
     590                 : #define GROUP_HEADING          (1 << 22)
     591                 : 
     592                 : // figcaption
     593                 : #define GROUP_FIGCAPTION       (1 << 23)
     594                 : 
     595                 : #define GROUP_INLINE_ELEMENT \
     596                 :   (GROUP_FONTSTYLE | GROUP_PHRASE | GROUP_SPECIAL | GROUP_FORMCONTROL | \
     597                 :    GROUP_LEAF)
     598                 : 
     599                 : #define GROUP_FLOW_ELEMENT (GROUP_INLINE_ELEMENT | GROUP_BLOCK)
     600                 : 
     601                 : struct nsElementInfo
     602                 : {
     603                 : #ifdef DEBUG
     604                 :   eHTMLTags mTag;
     605                 : #endif
     606                 :   PRUint32 mGroup;
     607                 :   PRUint32 mCanContainGroups;
     608                 :   bool mIsContainer;
     609                 :   bool mCanContainSelf;
     610                 : };
     611                 : 
     612                 : #ifdef DEBUG
     613                 : #define ELEM(_tag, _isContainer, _canContainSelf, _group, _canContainGroups) \
     614                 :   { eHTMLTag_##_tag, _group, _canContainGroups, _isContainer, _canContainSelf }
     615                 : #else
     616                 : #define ELEM(_tag, _isContainer, _canContainSelf, _group, _canContainGroups) \
     617                 :   { _group, _canContainGroups, _isContainer, _canContainSelf }
     618                 : #endif
     619                 : 
     620                 : static const nsElementInfo kElements[eHTMLTag_userdefined] = {
     621                 :   ELEM(a, true, false, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
     622                 :   ELEM(abbr, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
     623                 :   ELEM(acronym, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
     624                 :   ELEM(address, true, true, GROUP_BLOCK,
     625                 :        GROUP_INLINE_ELEMENT | GROUP_P),
     626                 :   ELEM(applet, true, true, GROUP_SPECIAL | GROUP_BLOCK,
     627                 :        GROUP_FLOW_ELEMENT | GROUP_OBJECT_CONTENT),
     628                 :   ELEM(area, false, false, GROUP_MAP_CONTENT, GROUP_NONE),
     629                 :   ELEM(article, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
     630                 :   ELEM(aside, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
     631                 : #if defined(MOZ_MEDIA)
     632                 :   ELEM(audio, false, false, GROUP_NONE, GROUP_NONE),
     633                 : #endif
     634                 :   ELEM(b, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
     635                 :   ELEM(base, false, false, GROUP_HEAD_CONTENT, GROUP_NONE),
     636                 :   ELEM(basefont, false, false, GROUP_SPECIAL, GROUP_NONE),
     637                 :   ELEM(bdo, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
     638                 :   ELEM(bgsound, false, false, GROUP_NONE, GROUP_NONE),
     639                 :   ELEM(big, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
     640                 :   ELEM(blink, false, false, GROUP_NONE, GROUP_NONE),
     641                 :   ELEM(blockquote, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
     642                 :   ELEM(body, true, true, GROUP_TOPLEVEL, GROUP_FLOW_ELEMENT),
     643                 :   ELEM(br, false, false, GROUP_SPECIAL, GROUP_NONE),
     644                 :   ELEM(button, true, true, GROUP_FORMCONTROL | GROUP_BLOCK,
     645                 :        GROUP_FLOW_ELEMENT),
     646                 :   ELEM(canvas, false, false, GROUP_NONE, GROUP_NONE),
     647                 :   ELEM(caption, true, true, GROUP_NONE, GROUP_INLINE_ELEMENT),
     648                 :   ELEM(center, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
     649                 :   ELEM(cite, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
     650                 :   ELEM(code, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
     651                 :   ELEM(col, false, false, GROUP_TABLE_CONTENT | GROUP_COLGROUP_CONTENT,
     652                 :        GROUP_NONE),
     653                 :   ELEM(colgroup, true, false, GROUP_NONE, GROUP_COLGROUP_CONTENT),
     654                 :   ELEM(datalist, true, false, GROUP_PHRASE,
     655                 :        GROUP_OPTIONS | GROUP_INLINE_ELEMENT),
     656                 :   ELEM(dd, true, false, GROUP_DL_CONTENT, GROUP_FLOW_ELEMENT),
     657                 :   ELEM(del, true, true, GROUP_PHRASE | GROUP_BLOCK, GROUP_FLOW_ELEMENT),
     658                 :   ELEM(dfn, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
     659                 :   ELEM(dir, true, false, GROUP_BLOCK, GROUP_LI),
     660                 :   ELEM(div, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
     661                 :   ELEM(dl, true, false, GROUP_BLOCK, GROUP_DL_CONTENT),
     662                 :   ELEM(dt, true, true, GROUP_DL_CONTENT, GROUP_INLINE_ELEMENT),
     663                 :   ELEM(em, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
     664                 :   ELEM(embed, false, false, GROUP_NONE, GROUP_NONE),
     665                 :   ELEM(fieldset, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
     666                 :   ELEM(figcaption, true, false, GROUP_FIGCAPTION, GROUP_FLOW_ELEMENT),
     667                 :   ELEM(figure, true, true, GROUP_BLOCK,
     668                 :        GROUP_FLOW_ELEMENT | GROUP_FIGCAPTION),
     669                 :   ELEM(font, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
     670                 :   ELEM(footer, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
     671                 :   ELEM(form, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
     672                 :   ELEM(frame, false, false, GROUP_FRAME, GROUP_NONE),
     673                 :   ELEM(frameset, true, true, GROUP_FRAME, GROUP_FRAME),
     674                 :   ELEM(h1, true, false, GROUP_BLOCK | GROUP_HEADING,
     675                 :        GROUP_INLINE_ELEMENT),
     676                 :   ELEM(h2, true, false, GROUP_BLOCK | GROUP_HEADING,
     677                 :        GROUP_INLINE_ELEMENT),
     678                 :   ELEM(h3, true, false, GROUP_BLOCK | GROUP_HEADING,
     679                 :        GROUP_INLINE_ELEMENT),
     680                 :   ELEM(h4, true, false, GROUP_BLOCK | GROUP_HEADING,
     681                 :        GROUP_INLINE_ELEMENT),
     682                 :   ELEM(h5, true, false, GROUP_BLOCK | GROUP_HEADING,
     683                 :        GROUP_INLINE_ELEMENT),
     684                 :   ELEM(h6, true, false, GROUP_BLOCK | GROUP_HEADING,
     685                 :        GROUP_INLINE_ELEMENT),
     686                 :   ELEM(head, true, false, GROUP_TOPLEVEL, GROUP_HEAD_CONTENT),
     687                 :   ELEM(header, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
     688                 :   ELEM(hgroup, true, false, GROUP_BLOCK, GROUP_HEADING),
     689                 :   ELEM(hr, false, false, GROUP_BLOCK, GROUP_NONE),
     690                 :   ELEM(html, true, false, GROUP_TOPLEVEL, GROUP_TOPLEVEL),
     691                 :   ELEM(i, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
     692                 :   ELEM(iframe, true, true, GROUP_SPECIAL | GROUP_BLOCK,
     693                 :        GROUP_FLOW_ELEMENT),
     694                 :   ELEM(image, false, false, GROUP_NONE, GROUP_NONE),
     695                 :   ELEM(img, false, false, GROUP_SPECIAL, GROUP_NONE),
     696                 :   ELEM(input, false, false, GROUP_FORMCONTROL, GROUP_NONE),
     697                 :   ELEM(ins, true, true, GROUP_PHRASE | GROUP_BLOCK, GROUP_FLOW_ELEMENT),
     698                 :   ELEM(kbd, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
     699                 :   ELEM(keygen, false, false, GROUP_FORMCONTROL, GROUP_NONE),
     700                 :   ELEM(label, true, false, GROUP_FORMCONTROL, GROUP_INLINE_ELEMENT),
     701                 :   ELEM(legend, true, true, GROUP_NONE, GROUP_INLINE_ELEMENT),
     702                 :   ELEM(li, true, false, GROUP_LI, GROUP_FLOW_ELEMENT),
     703                 :   ELEM(link, false, false, GROUP_HEAD_CONTENT, GROUP_NONE),
     704                 :   ELEM(listing, false, false, GROUP_NONE, GROUP_NONE),
     705                 :   ELEM(map, true, true, GROUP_SPECIAL, GROUP_BLOCK | GROUP_MAP_CONTENT),
     706                 :   ELEM(mark, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
     707                 :   ELEM(marquee, false, false, GROUP_NONE, GROUP_NONE),
     708                 :   ELEM(menu, true, true, GROUP_BLOCK, GROUP_LI | GROUP_FLOW_ELEMENT),
     709                 :   ELEM(menuitem, false, false, GROUP_NONE, GROUP_NONE),
     710                 :   ELEM(meta, false, false, GROUP_HEAD_CONTENT, GROUP_NONE),
     711                 :   ELEM(multicol, false, false, GROUP_NONE, GROUP_NONE),
     712                 :   ELEM(nav, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
     713                 :   ELEM(nobr, false, false, GROUP_NONE, GROUP_NONE),
     714                 :   ELEM(noembed, false, false, GROUP_NONE, GROUP_NONE),
     715                 :   ELEM(noframes, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
     716                 :   ELEM(noscript, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
     717                 :   ELEM(object, true, true, GROUP_SPECIAL | GROUP_BLOCK,
     718                 :        GROUP_FLOW_ELEMENT | GROUP_OBJECT_CONTENT),
     719                 :   // XXX Can contain self and ul because editor does sublists illegally.
     720                 :   ELEM(ol, true, true, GROUP_BLOCK | GROUP_OL_UL,
     721                 :        GROUP_LI | GROUP_OL_UL),
     722                 :   ELEM(optgroup, true, false, GROUP_SELECT_CONTENT,
     723                 :        GROUP_OPTIONS),
     724                 :   ELEM(option, true, false,
     725                 :        GROUP_SELECT_CONTENT | GROUP_OPTIONS, GROUP_LEAF),
     726                 :   ELEM(output, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
     727                 :   ELEM(p, true, false, GROUP_BLOCK | GROUP_P, GROUP_INLINE_ELEMENT),
     728                 :   ELEM(param, false, false, GROUP_OBJECT_CONTENT, GROUP_NONE),
     729                 :   ELEM(plaintext, false, false, GROUP_NONE, GROUP_NONE),
     730                 :   ELEM(pre, true, true, GROUP_BLOCK, GROUP_INLINE_ELEMENT),
     731                 :   ELEM(progress, true, false, GROUP_SPECIAL, GROUP_FLOW_ELEMENT),
     732                 :   ELEM(q, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
     733                 :   ELEM(s, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
     734                 :   ELEM(samp, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
     735                 :   ELEM(script, true, false, GROUP_HEAD_CONTENT | GROUP_SPECIAL,
     736                 :        GROUP_LEAF),
     737                 :   ELEM(section, true, true, GROUP_BLOCK, GROUP_FLOW_ELEMENT),
     738                 :   ELEM(select, true, false, GROUP_FORMCONTROL, GROUP_SELECT_CONTENT),
     739                 :   ELEM(small, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
     740                 : #if defined(MOZ_MEDIA)
     741                 :   ELEM(source, false, false, GROUP_NONE, GROUP_NONE),
     742                 : #endif
     743                 :   ELEM(span, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
     744                 :   ELEM(strike, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
     745                 :   ELEM(strong, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
     746                 :   ELEM(style, true, false, GROUP_HEAD_CONTENT, GROUP_LEAF),
     747                 :   ELEM(sub, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
     748                 :   ELEM(sup, true, true, GROUP_SPECIAL, GROUP_INLINE_ELEMENT),
     749                 :   ELEM(table, true, false, GROUP_BLOCK, GROUP_TABLE_CONTENT),
     750                 :   ELEM(tbody, true, false, GROUP_TABLE_CONTENT, GROUP_TBODY_CONTENT),
     751                 :   ELEM(td, true, false, GROUP_TR_CONTENT, GROUP_FLOW_ELEMENT),
     752                 :   ELEM(textarea, true, false, GROUP_FORMCONTROL, GROUP_LEAF),
     753                 :   ELEM(tfoot, true, false, GROUP_NONE, GROUP_TBODY_CONTENT),
     754                 :   ELEM(th, true, false, GROUP_TR_CONTENT, GROUP_FLOW_ELEMENT),
     755                 :   ELEM(thead, true, false, GROUP_NONE, GROUP_TBODY_CONTENT),
     756                 :   ELEM(title, true, false, GROUP_HEAD_CONTENT, GROUP_LEAF),
     757                 :   ELEM(tr, true, false, GROUP_TBODY_CONTENT, GROUP_TR_CONTENT),
     758                 :   ELEM(tt, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
     759                 :   ELEM(u, true, true, GROUP_FONTSTYLE, GROUP_INLINE_ELEMENT),
     760                 :   // XXX Can contain self and ol because editor does sublists illegally.
     761                 :   ELEM(ul, true, true, GROUP_BLOCK | GROUP_OL_UL,
     762                 :        GROUP_LI | GROUP_OL_UL),
     763                 :   ELEM(var, true, true, GROUP_PHRASE, GROUP_INLINE_ELEMENT),
     764                 : #if defined(MOZ_MEDIA)
     765                 :   ELEM(video, false, false, GROUP_NONE, GROUP_NONE),
     766                 : #endif
     767                 :   ELEM(wbr, false, false, GROUP_NONE, GROUP_NONE),
     768                 :   ELEM(xmp, false, false, GROUP_NONE, GROUP_NONE),
     769                 : 
     770                 :   // These aren't elements.
     771                 :   ELEM(text, false, false, GROUP_LEAF, GROUP_NONE),
     772                 :   ELEM(whitespace, false, false, GROUP_LEAF, GROUP_NONE),
     773                 :   ELEM(newline, false, false, GROUP_LEAF, GROUP_NONE),
     774                 :   ELEM(comment, false, false, GROUP_LEAF, GROUP_NONE),
     775                 :   ELEM(entity, false, false, GROUP_NONE, GROUP_NONE),
     776                 :   ELEM(doctypeDecl, false, false, GROUP_NONE, GROUP_NONE),
     777                 :   ELEM(markupDecl, false, false, GROUP_NONE, GROUP_NONE),
     778                 :   ELEM(instruction, false, false, GROUP_NONE, GROUP_NONE),
     779                 : 
     780                 :   ELEM(userdefined, true, false, GROUP_NONE, GROUP_FLOW_ELEMENT)
     781                 : };
     782                 : 
     783                 : bool
     784               0 : nsHTMLEditUtils::CanContain(PRInt32 aParent, PRInt32 aChild)
     785                 : {
     786               0 :   NS_ASSERTION(aParent > eHTMLTag_unknown && aParent <= eHTMLTag_userdefined,
     787                 :                "aParent out of range!");
     788               0 :   NS_ASSERTION(aChild > eHTMLTag_unknown && aChild <= eHTMLTag_userdefined,
     789                 :                "aChild out of range!");
     790                 : 
     791                 : #ifdef DEBUG
     792                 :   static bool checked = false;
     793               0 :   if (!checked) {
     794               0 :     checked = true;
     795                 :     PRInt32 i;
     796               0 :     for (i = 1; i <= eHTMLTag_userdefined; ++i) {
     797               0 :       NS_ASSERTION(kElements[i - 1].mTag == i,
     798                 :                    "You need to update kElements (missing tags).");
     799                 :     }
     800                 :   }
     801                 : #endif
     802                 : 
     803                 :   // Special-case button.
     804               0 :   if (aParent == eHTMLTag_button) {
     805                 :     static const eHTMLTags kButtonExcludeKids[] = {
     806                 :       eHTMLTag_a,
     807                 :       eHTMLTag_fieldset,
     808                 :       eHTMLTag_form,
     809                 :       eHTMLTag_iframe,
     810                 :       eHTMLTag_input,
     811                 :       eHTMLTag_select,
     812                 :       eHTMLTag_textarea
     813                 :     };
     814                 : 
     815                 :     PRUint32 j;
     816               0 :     for (j = 0; j < ArrayLength(kButtonExcludeKids); ++j) {
     817               0 :       if (kButtonExcludeKids[j] == aChild) {
     818               0 :         return false;
     819                 :       }
     820                 :     }
     821                 :   }
     822                 : 
     823                 :   // Deprecated elements.
     824               0 :   if (aChild == eHTMLTag_bgsound) {
     825               0 :     return false;
     826                 :   }
     827                 : 
     828                 :   // Bug #67007, dont strip userdefined tags.
     829               0 :   if (aChild == eHTMLTag_userdefined) {
     830               0 :     return true;
     831                 :   }
     832                 : 
     833               0 :   const nsElementInfo& parent = kElements[aParent - 1];
     834               0 :   if (aParent == aChild) {
     835               0 :     return parent.mCanContainSelf;
     836                 :   }
     837                 : 
     838               0 :   const nsElementInfo& child = kElements[aChild - 1];
     839               0 :   return (parent.mCanContainGroups & child.mGroup) != 0;
     840                 : } 
     841                 : 
     842                 : bool
     843               0 : nsHTMLEditUtils::IsContainer(PRInt32 aTag)
     844                 : {
     845               0 :   NS_ASSERTION(aTag > eHTMLTag_unknown && aTag <= eHTMLTag_userdefined,
     846                 :                "aTag out of range!");
     847                 : 
     848               0 :   return kElements[aTag - 1].mIsContainer;
     849                 : }

Generated by: LCOV version 1.7