editor/libeditor/html/nsHTMLEditUtils.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial