Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: Source/core/editing/CompositeEditCommand.cpp

Issue 24278008: [oilpan] Handlify Nodes in htmlediting (Closed) Base URL: svn://svn.chromium.org/blink/branches/oilpan
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 349
350 void CompositeEditCommand::insertNodeAt(const Handle<Node>& insertChild, const P osition& editingPosition) 350 void CompositeEditCommand::insertNodeAt(const Handle<Node>& insertChild, const P osition& editingPosition)
351 { 351 {
352 ASSERT(isEditablePosition(editingPosition)); 352 ASSERT(isEditablePosition(editingPosition));
353 // For editing positions like [table, 0], insert before the table, 353 // For editing positions like [table, 0], insert before the table,
354 // likewise for replaced elements, brs, etc. 354 // likewise for replaced elements, brs, etc.
355 Position p = editingPosition.parentAnchoredEquivalent(); 355 Position p = editingPosition.parentAnchoredEquivalent();
356 Handle<Node> refChild = p.deprecatedNode(); 356 Handle<Node> refChild = p.deprecatedNode();
357 int offset = p.deprecatedEditingOffset(); 357 int offset = p.deprecatedEditingOffset();
358 358
359 if (canHaveChildrenForEditing(refChild.raw())) { 359 if (canHaveChildrenForEditing(refChild)) {
360 Handle<Node> child = refChild->firstChild(); 360 Handle<Node> child = refChild->firstChild();
361 for (int i = 0; child && i < offset; i++) 361 for (int i = 0; child && i < offset; i++)
362 child = child->nextSibling(); 362 child = child->nextSibling();
363 if (child) 363 if (child)
364 insertNodeBefore(insertChild, child); 364 insertNodeBefore(insertChild, child);
365 else 365 else
366 appendNode(insertChild, toContainerNode(refChild)); 366 appendNode(insertChild, toContainerNode(refChild));
367 } else if (caretMinOffset(refChild.raw()) >= offset) 367 } else if (caretMinOffset(refChild) >= offset)
368 insertNodeBefore(insertChild, refChild); 368 insertNodeBefore(insertChild, refChild);
369 else if (refChild->isTextNode() && caretMaxOffset(refChild.raw()) > offset) { 369 else if (refChild->isTextNode() && caretMaxOffset(refChild) > offset) {
370 splitTextNode(toText(refChild.raw()), offset); 370 splitTextNode(toText(refChild), offset);
371 371
372 // Mutation events (bug 22634) from the text node insertion may have rem oved the refChild 372 // Mutation events (bug 22634) from the text node insertion may have rem oved the refChild
373 if (!refChild->inDocument()) 373 if (!refChild->inDocument())
374 return; 374 return;
375 insertNodeBefore(insertChild, refChild); 375 insertNodeBefore(insertChild, refChild);
376 } else 376 } else
377 insertNodeAfter(insertChild, refChild); 377 insertNodeAfter(insertChild, refChild);
378 } 378 }
379 379
380 void CompositeEditCommand::appendNode(const Handle<Node>& node, const Handle<Con tainerNode>& parent) 380 void CompositeEditCommand::appendNode(const Handle<Node>& node, const Handle<Con tainerNode>& parent)
381 { 381 {
382 ASSERT(canHaveChildrenForEditing(parent.raw())); 382 ASSERT(canHaveChildrenForEditing(parent));
383 applyCommandToComposite(AppendNodeCommand::create(parent, node)); 383 applyCommandToComposite(AppendNodeCommand::create(parent, node));
384 } 384 }
385 385
386 void CompositeEditCommand::removeChildrenInRange(const Handle<Node>& node, unsig ned from, unsigned to) 386 void CompositeEditCommand::removeChildrenInRange(const Handle<Node>& node, unsig ned from, unsigned to)
387 { 387 {
388 CollectionRoot<Vector<Member<Node> > > children; 388 CollectionRoot<Vector<Member<Node> > > children;
389 Handle<Node> child = node->childNode(from); 389 Handle<Node> child = node->childNode(from);
390 for (unsigned i = from; child && i < to; i++, child = child->nextSibling()) { 390 for (unsigned i = from; child && i < to; i++, child = child->nextSibling()) {
391 NoHandleScope scope; 391 NoHandleScope scope;
392 children->append(child); 392 children->append(child);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 for (unsigned i = 0; i < nodesToRemove->size(); i++) { 433 for (unsigned i = 0; i < nodesToRemove->size(); i++) {
434 HandleScope scope; 434 HandleScope scope;
435 removeNode(nodesToRemove[i]); 435 removeNode(nodesToRemove[i]);
436 appendNode(nodesToRemove[i], newParent); 436 appendNode(nodesToRemove[i], newParent);
437 } 437 }
438 } 438 }
439 439
440 void CompositeEditCommand::updatePositionForNodeRemovalPreservingChildren(Positi on& position, const Handle<Node>& node) 440 void CompositeEditCommand::updatePositionForNodeRemovalPreservingChildren(Positi on& position, const Handle<Node>& node)
441 { 441 {
442 int offset = (position.anchorType() == Position::PositionIsOffsetInAnchor) ? position.offsetInContainerNode() : 0; 442 int offset = (position.anchorType() == Position::PositionIsOffsetInAnchor) ? position.offsetInContainerNode() : 0;
443 updatePositionForNodeRemoval(position, node.raw()); 443 updatePositionForNodeRemoval(position, node);
444 if (offset) 444 if (offset)
445 position.moveToOffset(offset); 445 position.moveToOffset(offset);
446 } 446 }
447 447
448 Result<HTMLElement> CompositeEditCommand::replaceElementWithSpanPreservingChildr enAndAttributes(const Handle<HTMLElement>& node) 448 Result<HTMLElement> CompositeEditCommand::replaceElementWithSpanPreservingChildr enAndAttributes(const Handle<HTMLElement>& node)
449 { 449 {
450 // It would also be possible to implement all of ReplaceNodeWithSpanCommand 450 // It would also be possible to implement all of ReplaceNodeWithSpanCommand
451 // as a series of existing smaller edit commands. Someone who wanted to 451 // as a series of existing smaller edit commands. Someone who wanted to
452 // reduce the number of edit commands could do so here. 452 // reduce the number of edit commands could do so here.
453 RefPtr<ReplaceNodeWithSpanCommand> command = ReplaceNodeWithSpanCommand::cre ate(node); 453 RefPtr<ReplaceNodeWithSpanCommand> command = ReplaceNodeWithSpanCommand::cre ate(node);
454 applyCommandToComposite(command); 454 applyCommandToComposite(command);
455 // Returning a raw pointer here is OK because the command is retained by 455 // Returning a raw pointer here is OK because the command is retained by
456 // applyCommandToComposite (thus retaining the span), and the span is also 456 // applyCommandToComposite (thus retaining the span), and the span is also
457 // in the DOM tree, and thus alive whie it has a parent. 457 // in the DOM tree, and thus alive whie it has a parent.
458 ASSERT(command->spanElement()->inDocument()); 458 ASSERT(command->spanElement()->inDocument());
459 return command->spanElement(); 459 return command->spanElement();
460 } 460 }
461 461
462 void CompositeEditCommand::prune(const Handle<Node>& node) 462 void CompositeEditCommand::prune(const Handle<Node>& node)
463 { 463 {
464 if (Handle<Node> highestNodeToRemove = adoptRawResult(highestNodeToRemoveInP runing(node.raw()))) 464 if (Handle<Node> highestNodeToRemove = highestNodeToRemoveInPruning(node))
465 removeNode(highestNodeToRemove); 465 removeNode(highestNodeToRemove);
466 } 466 }
467 467
468 void CompositeEditCommand::splitTextNode(const Handle<Text>& node, unsigned offs et) 468 void CompositeEditCommand::splitTextNode(const Handle<Text>& node, unsigned offs et)
469 { 469 {
470 applyCommandToComposite(SplitTextNodeCommand::create(node, offset)); 470 applyCommandToComposite(SplitTextNodeCommand::create(node, offset));
471 } 471 }
472 472
473 void CompositeEditCommand::splitElement(const Handle<Element>& element, const Ha ndle<Node>& atChild) 473 void CompositeEditCommand::splitElement(const Handle<Element>& element, const Ha ndle<Node>& atChild)
474 { 474 {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 Handle<Text> node(prpNode); 514 Handle<Text> node(prpNode);
515 applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, coun t)); 515 applyCommandToComposite(DeleteFromTextNodeCommand::create(node, offset, coun t));
516 if (!replacementText.isEmpty()) 516 if (!replacementText.isEmpty())
517 applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset, replacementText)); 517 applyCommandToComposite(InsertIntoTextNodeCommand::create(node, offset, replacementText));
518 } 518 }
519 519
520 Position CompositeEditCommand::replaceSelectedTextInNode(const String& text) 520 Position CompositeEditCommand::replaceSelectedTextInNode(const String& text)
521 { 521 {
522 Position start = endingSelection().start(); 522 Position start = endingSelection().start();
523 Position end = endingSelection().end(); 523 Position end = endingSelection().end();
524 if (start.containerNode() != end.containerNode() || !start.containerNode()-> isTextNode() || isTabSpanTextNode(start.containerNode().handle().raw())) 524 if (start.containerNode() != end.containerNode() || !start.containerNode()-> isTextNode() || isTabSpanTextNode(start.containerNode()))
525 return Position(); 525 return Position();
526 526
527 Handle<Text> textNode = start.containerText(); 527 Handle<Text> textNode = start.containerText();
528 replaceTextInNode(textNode, start.offsetInContainerNode(), end.offsetInConta inerNode() - start.offsetInContainerNode(), text); 528 replaceTextInNode(textNode, start.offsetInContainerNode(), end.offsetInConta inerNode() - start.offsetInContainerNode(), text);
529 529
530 return Position(textNode, start.offsetInContainerNode() + text.length()); 530 return Position(textNode, start.offsetInContainerNode() + text.length());
531 } 531 }
532 532
533 static void copyMarkers(const Vector<DocumentMarker*>& markerPointers, Vector<Do cumentMarker>& markers) 533 static void copyMarkers(const Vector<DocumentMarker*>& markerPointers, Vector<Do cumentMarker>& markers)
534 { 534 {
(...skipping 12 matching lines...) Expand all
547 replaceTextInNode(node, offset, count, replacementText); 547 replaceTextInNode(node, offset, count, replacementText);
548 Handle<Range> newRange = Range::create(document(), node, offset, node, offse t + replacementText.length()); 548 Handle<Range> newRange = Range::create(document(), node, offset, node, offse t + replacementText.length());
549 for (size_t i = 0; i < markers.size(); ++i) { 549 for (size_t i = 0; i < markers.size(); ++i) {
550 HandleScope scope; 550 HandleScope scope;
551 markerController->addMarker(newRange, markers[i].type(), markers[i].desc ription()); 551 markerController->addMarker(newRange, markers[i].type(), markers[i].desc ription());
552 } 552 }
553 } 553 }
554 554
555 Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos) 555 Position CompositeEditCommand::positionOutsideTabSpan(const Position& pos)
556 { 556 {
557 if (!isTabSpanTextNode(pos.anchorNode().handle().raw())) 557 if (!isTabSpanTextNode(pos.anchorNode()))
558 return pos; 558 return pos;
559 559
560 switch (pos.anchorType()) { 560 switch (pos.anchorType()) {
561 case Position::PositionIsBeforeChildren: 561 case Position::PositionIsBeforeChildren:
562 case Position::PositionIsAfterChildren: 562 case Position::PositionIsAfterChildren:
563 ASSERT_NOT_REACHED(); 563 ASSERT_NOT_REACHED();
564 return pos; 564 return pos;
565 case Position::PositionIsOffsetInAnchor: 565 case Position::PositionIsOffsetInAnchor:
566 break; 566 break;
567 case Position::PositionIsBeforeAnchor: 567 case Position::PositionIsBeforeAnchor:
568 return positionInParentBeforeNode(pos.anchorNode()); 568 return positionInParentBeforeNode(pos.anchorNode());
569 case Position::PositionIsAfterAnchor: 569 case Position::PositionIsAfterAnchor:
570 return positionInParentAfterNode(pos.anchorNode()); 570 return positionInParentAfterNode(pos.anchorNode());
571 } 571 }
572 572
573 Handle<Node> tabSpan = adoptRawResult(tabSpanNode(pos.containerNode().handle ().raw())); 573 Handle<Node> tabSpan = tabSpanNode(pos.containerNode());
574 574
575 if (pos.offsetInContainerNode() <= caretMinOffset(pos.containerNode().handle ().raw())) 575 if (pos.offsetInContainerNode() <= caretMinOffset(pos.containerNode()))
576 return positionInParentBeforeNode(tabSpan); 576 return positionInParentBeforeNode(tabSpan);
577 577
578 if (pos.offsetInContainerNode() >= caretMaxOffset(pos.containerNode().handle ().raw())) 578 if (pos.offsetInContainerNode() >= caretMaxOffset(pos.containerNode()))
579 return positionInParentAfterNode(tabSpan); 579 return positionInParentAfterNode(tabSpan);
580 580
581 splitTextNodeContainingElement(toText(pos.containerNode().handle().raw()), p os.offsetInContainerNode()); 581 splitTextNodeContainingElement(toText(pos.containerNode()), pos.offsetInCont ainerNode());
582 return positionInParentBeforeNode(tabSpan); 582 return positionInParentBeforeNode(tabSpan);
583 } 583 }
584 584
585 void CompositeEditCommand::insertNodeAtTabSpanPosition(const Handle<Node>& node, const Position& pos) 585 void CompositeEditCommand::insertNodeAtTabSpanPosition(const Handle<Node>& node, const Position& pos)
586 { 586 {
587 // insert node before, after, or at split of tab span 587 // insert node before, after, or at split of tab span
588 insertNodeAt(node, positionOutsideTabSpan(pos)); 588 insertNodeAt(node, positionOutsideTabSpan(pos));
589 } 589 }
590 590
591 void CompositeEditCommand::deleteSelection(bool smartDelete, bool mergeBlocksAft erDelete, bool replace, bool expandForSpecialElements, bool sanitizeMarkup) 591 void CompositeEditCommand::deleteSelection(bool smartDelete, bool mergeBlocksAft erDelete, bool replace, bool expandForSpecialElements, bool sanitizeMarkup)
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after
940 940
941 Position upstreamStart = visibleParagraphStart.deepEquivalent().upstream(); 941 Position upstreamStart = visibleParagraphStart.deepEquivalent().upstream();
942 Position upstreamEnd = visibleEnd.deepEquivalent().upstream(); 942 Position upstreamEnd = visibleEnd.deepEquivalent().upstream();
943 943
944 // If there are no VisiblePositions in the same block as pos then 944 // If there are no VisiblePositions in the same block as pos then
945 // upstreamStart will be outside the paragraph 945 // upstreamStart will be outside the paragraph
946 if (comparePositions(pos, upstreamStart) < 0) 946 if (comparePositions(pos, upstreamStart) < 0)
947 return nullptr; 947 return nullptr;
948 948
949 // Perform some checks to see if we need to perform work in this function. 949 // Perform some checks to see if we need to perform work in this function.
950 if (isBlock(upstreamStart.deprecatedNode().handle().raw())) { 950 if (isBlock(upstreamStart.deprecatedNode())) {
951 // If the block is the root editable element, always move content to a n ew block, 951 // If the block is the root editable element, always move content to a n ew block,
952 // since it is illegal to modify attributes on the root editable element for editing. 952 // since it is illegal to modify attributes on the root editable element for editing.
953 if (upstreamStart.deprecatedNode() == editableRootForPosition(upstreamSt art)) { 953 if (upstreamStart.deprecatedNode() == editableRootForPosition(upstreamSt art)) {
954 // If the block is the root editable element and it contains no visi ble content, create a new 954 // If the block is the root editable element and it contains no visi ble content, create a new
955 // block but don't try and move content into it, since there's nothi ng for moveParagraphs to move. 955 // block but don't try and move content into it, since there's nothi ng for moveParagraphs to move.
956 if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(upstream Start.deprecatedNode()->renderer())) 956 if (!Position::hasRenderedNonAnonymousDescendantsWithHeight(upstream Start.deprecatedNode()->renderer()))
957 return insertNewDefaultParagraphElementAt(upstreamStart); 957 return insertNewDefaultParagraphElementAt(upstreamStart);
958 } else if (isBlock(upstreamEnd.deprecatedNode().handle().raw())) { 958 } else if (isBlock(upstreamEnd.deprecatedNode())) {
959 if (!upstreamEnd.deprecatedNode()->isDescendantOf(upstreamStart.depr ecatedNode().handle().raw())) { 959 if (!upstreamEnd.deprecatedNode()->isDescendantOf(upstreamStart.depr ecatedNode().handle().raw())) {
960 // If the paragraph end is a descendant of paragraph start, then we need to run 960 // If the paragraph end is a descendant of paragraph start, then we need to run
961 // the rest of this function. If not, we can bail here. 961 // the rest of this function. If not, we can bail here.
962 return nullptr; 962 return nullptr;
963 } 963 }
964 } else if (enclosingBlock(upstreamEnd.deprecatedNode().handle().raw()) ! = upstreamStart.deprecatedNode().handle().raw()) { 964 } else if (enclosingBlock(upstreamEnd.deprecatedNode()) != upstreamStart .deprecatedNode()) {
965 // The visibleEnd. It must be an ancestor of the paragraph start. 965 // The visibleEnd. It must be an ancestor of the paragraph start.
966 // We can bail as we have a full block to work with. 966 // We can bail as we have a full block to work with.
967 ASSERT(upstreamStart.deprecatedNode()->isDescendantOf(enclosingBlock (upstreamEnd.deprecatedNode().handle().raw()).handle().raw())); 967 ASSERT(upstreamStart.deprecatedNode()->isDescendantOf(enclosingBlock (upstreamEnd.deprecatedNode()).handle().raw()));
968 return nullptr; 968 return nullptr;
969 } else if (isEndOfEditableOrNonEditableContent(visibleEnd)) { 969 } else if (isEndOfEditableOrNonEditableContent(visibleEnd)) {
970 // At the end of the editable region. We can bail here as well. 970 // At the end of the editable region. We can bail here as well.
971 return nullptr; 971 return nullptr;
972 } 972 }
973 } 973 }
974 974
975 Handle<Node> newBlock = insertNewDefaultParagraphElementAt(upstreamStart); 975 Handle<Node> newBlock = insertNewDefaultParagraphElementAt(upstreamStart);
976 976
977 bool endWasBr = visibleParagraphEnd.deepEquivalent().deprecatedNode()->hasTa gName(brTag); 977 bool endWasBr = visibleParagraphEnd.deepEquivalent().deprecatedNode()->hasTa gName(brTag);
(...skipping 25 matching lines...) Expand all
1003 1003
1004 void CompositeEditCommand::cloneParagraphUnderNewElement(Position& start, Positi on& end, const Handle<Node>& passedOuterNode, const Handle<Element>& blockElemen t) 1004 void CompositeEditCommand::cloneParagraphUnderNewElement(Position& start, Positi on& end, const Handle<Node>& passedOuterNode, const Handle<Element>& blockElemen t)
1005 { 1005 {
1006 // First we clone the outerNode 1006 // First we clone the outerNode
1007 Handle<Node> lastNode; 1007 Handle<Node> lastNode;
1008 Handle<Node> outerNode = passedOuterNode; 1008 Handle<Node> outerNode = passedOuterNode;
1009 1009
1010 if (outerNode->isRootEditableElement()) { 1010 if (outerNode->isRootEditableElement()) {
1011 lastNode = blockElement; 1011 lastNode = blockElement;
1012 } else { 1012 } else {
1013 lastNode = outerNode->cloneNode(isTableElement(outerNode.raw())); 1013 lastNode = outerNode->cloneNode(isTableElement(outerNode));
1014 appendNode(lastNode, blockElement); 1014 appendNode(lastNode, blockElement);
1015 } 1015 }
1016 1016
1017 if (start.deprecatedNode() != outerNode && lastNode->isElementNode()) { 1017 if (start.deprecatedNode() != outerNode && lastNode->isElementNode()) {
1018 CollectionRoot<Vector<Member<Node> > > ancestors; 1018 CollectionRoot<Vector<Member<Node> > > ancestors;
1019 1019
1020 // Insert each node from innerNode to outerNode (excluded) in a list. 1020 // Insert each node from innerNode to outerNode (excluded) in a list.
1021 for (Handle<Node> n = start.deprecatedNode(); n && n != outerNode; n = n ->parentNode()) { 1021 for (Handle<Node> n = start.deprecatedNode(); n && n != outerNode; n = n ->parentNode()) {
1022 NoHandleScope scope; 1022 NoHandleScope scope;
1023 ancestors->append(n); 1023 ancestors->append(n);
1024 } 1024 }
1025 1025
1026 // Clone every node between start.deprecatedNode() and outerBlock. 1026 // Clone every node between start.deprecatedNode() and outerBlock.
1027 1027
1028 for (size_t i = ancestors->size(); i != 0; --i) { 1028 for (size_t i = ancestors->size(); i != 0; --i) {
1029 HandleScope scope; 1029 HandleScope scope;
1030 Handle<Node> item = ancestors[i - 1]; 1030 Handle<Node> item = ancestors[i - 1];
1031 Handle<Node> child = item->cloneNode(isTableElement(item.raw())); 1031 Handle<Node> child = item->cloneNode(isTableElement(item));
1032 appendNode(child, Handle<Element>::cast(lastNode)); 1032 appendNode(child, Handle<Element>::cast(lastNode));
1033 lastNode = child; 1033 lastNode = child;
1034 } 1034 }
1035 } 1035 }
1036 1036
1037 // Handle the case of paragraphs with more than one node, 1037 // Handle the case of paragraphs with more than one node,
1038 // cloning all the siblings until end.deprecatedNode() is reached. 1038 // cloning all the siblings until end.deprecatedNode() is reached.
1039 1039
1040 if (start.deprecatedNode() != end.deprecatedNode() && !start.deprecatedNode( )->isDescendantOf(end.deprecatedNode().handle().raw())) { 1040 if (start.deprecatedNode() != end.deprecatedNode() && !start.deprecatedNode( )->isDescendantOf(end.deprecatedNode().handle().raw())) {
1041 // If end is not a descendant of outerNode we need to 1041 // If end is not a descendant of outerNode we need to
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1080 // Note: We want the rightmost candidate. 1080 // Note: We want the rightmost candidate.
1081 Position position = caretAfterDelete.deepEquivalent().downstream(); 1081 Position position = caretAfterDelete.deepEquivalent().downstream();
1082 Handle<Node> node = position.deprecatedNode(); 1082 Handle<Node> node = position.deprecatedNode();
1083 // Normally deletion will leave a br as a placeholder. 1083 // Normally deletion will leave a br as a placeholder.
1084 if (node->hasTagName(brTag)) 1084 if (node->hasTagName(brTag))
1085 removeNodeAndPruneAncestors(node); 1085 removeNodeAndPruneAncestors(node);
1086 // If the selection to move was empty and in an empty block that 1086 // If the selection to move was empty and in an empty block that
1087 // doesn't require a placeholder to prop itself open (like a bordered 1087 // doesn't require a placeholder to prop itself open (like a bordered
1088 // div or an li), remove it during the move (the list removal code 1088 // div or an li), remove it during the move (the list removal code
1089 // expects this behavior). 1089 // expects this behavior).
1090 else if (isBlock(node.raw())) { 1090 else if (isBlock(node)) {
1091 // If caret position after deletion and destination position coincid es, 1091 // If caret position after deletion and destination position coincid es,
1092 // node should not be removed. 1092 // node should not be removed.
1093 if (!position.rendersInDifferentPosition(destination.deepEquivalent( ))) { 1093 if (!position.rendersInDifferentPosition(destination.deepEquivalent( ))) {
1094 prune(node); 1094 prune(node);
1095 return; 1095 return;
1096 } 1096 }
1097 removeNodeAndPruneAncestors(node); 1097 removeNodeAndPruneAncestors(node);
1098 } 1098 }
1099 else if (lineBreakExistsAtPosition(position)) { 1099 else if (lineBreakExistsAtPosition(position)) {
1100 // There is a preserved '\n' at caretAfterDelete. 1100 // There is a preserved '\n' at caretAfterDelete.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1141 // Add a br if pruning an empty block level element caused a collapse. For example: 1141 // Add a br if pruning an empty block level element caused a collapse. For example:
1142 // foo^ 1142 // foo^
1143 // <div>bar</div> 1143 // <div>bar</div>
1144 // baz 1144 // baz
1145 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. Th at would 1145 // Imagine moving 'bar' to ^. 'bar' will be deleted and its div pruned. Th at would
1146 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br . 1146 // cause 'baz' to collapse onto the line with 'foobar' unless we insert a br .
1147 // Must recononicalize these two VisiblePositions after the pruning above. 1147 // Must recononicalize these two VisiblePositions after the pruning above.
1148 beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent()); 1148 beforeParagraph = VisiblePosition(beforeParagraph.deepEquivalent());
1149 afterParagraph = VisiblePosition(afterParagraph.deepEquivalent()); 1149 afterParagraph = VisiblePosition(afterParagraph.deepEquivalent());
1150 1150
1151 if (beforeParagraph.isNotNull() && !isTableElement(beforeParagraph.deepEquiv alent().deprecatedNode().handle().raw()) 1151 if (beforeParagraph.isNotNull() && !isTableElement(beforeParagraph.deepEquiv alent().deprecatedNode())
1152 && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforePar agraph)) || beforeParagraph == afterParagraph)) { 1152 && ((!isEndOfParagraph(beforeParagraph) && !isStartOfParagraph(beforePar agraph)) || beforeParagraph == afterParagraph)) {
1153 // FIXME: Trim text between beforeParagraph and afterParagraph if they a ren't equal. 1153 // FIXME: Trim text between beforeParagraph and afterParagraph if they a ren't equal.
1154 insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquival ent()); 1154 insertNodeAt(createBreakElement(document()), beforeParagraph.deepEquival ent());
1155 } 1155 }
1156 } 1156 }
1157 1157
1158 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraph ToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& dest ination, bool preserveSelection, bool preserveStyle, const Handle<Node>& constra iningAncestor) 1158 void CompositeEditCommand::moveParagraph(const VisiblePosition& startOfParagraph ToMove, const VisiblePosition& endOfParagraphToMove, const VisiblePosition& dest ination, bool preserveSelection, bool preserveStyle, const Handle<Node>& constra iningAncestor)
1159 { 1159 {
1160 ASSERT(isStartOfParagraph(startOfParagraphToMove)); 1160 ASSERT(isStartOfParagraph(startOfParagraphToMove));
1161 ASSERT(isEndOfParagraph(endOfParagraphToMove)); 1161 ASSERT(isEndOfParagraph(endOfParagraphToMove));
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1279 Handle<Range> start = TextIterator::rangeFromLocationAndLength(adoptRawR esult(document()->documentElement().handle().raw()), destinationIndex + startInd ex, 0, true); 1279 Handle<Range> start = TextIterator::rangeFromLocationAndLength(adoptRawR esult(document()->documentElement().handle().raw()), destinationIndex + startInd ex, 0, true);
1280 Handle<Range> end = TextIterator::rangeFromLocationAndLength(adoptRawRes ult(document()->documentElement().handle().raw()), destinationIndex + endIndex, 0, true); 1280 Handle<Range> end = TextIterator::rangeFromLocationAndLength(adoptRawRes ult(document()->documentElement().handle().raw()), destinationIndex + endIndex, 0, true);
1281 if (start && end) 1281 if (start && end)
1282 setEndingSelection(VisibleSelection(start->startPosition(), end->sta rtPosition(), DOWNSTREAM, originalIsDirectional)); 1282 setEndingSelection(VisibleSelection(start->startPosition(), end->sta rtPosition(), DOWNSTREAM, originalIsDirectional));
1283 } 1283 }
1284 } 1284 }
1285 1285
1286 // FIXME: Send an appropriate shouldDeleteRange call. 1286 // FIXME: Send an appropriate shouldDeleteRange call.
1287 bool CompositeEditCommand::breakOutOfEmptyListItem() 1287 bool CompositeEditCommand::breakOutOfEmptyListItem()
1288 { 1288 {
1289 Handle<Node> emptyListItem = adoptRawResult(enclosingEmptyListItem(endingSel ection().visibleStart())); 1289 Handle<Node> emptyListItem = enclosingEmptyListItem(endingSelection().visibl eStart());
1290 if (!emptyListItem) 1290 if (!emptyListItem)
1291 return false; 1291 return false;
1292 1292
1293 RefPtr<EditingStyle> style = EditingStyle::create(endingSelection().start()) ; 1293 RefPtr<EditingStyle> style = EditingStyle::create(endingSelection().start()) ;
1294 style->mergeTypingStyle(document()); 1294 style->mergeTypingStyle(document());
1295 1295
1296 Handle<ContainerNode> listNode = emptyListItem->parentNode(); 1296 Handle<ContainerNode> listNode = emptyListItem->parentNode();
1297 // FIXME: Can't we do something better when the immediate parent wasn't a li st node? 1297 // FIXME: Can't we do something better when the immediate parent wasn't a li st node?
1298 if (!listNode 1298 if (!listNode
1299 || (!listNode->hasTagName(ulTag) && !listNode->hasTagName(olTag)) 1299 || (!listNode->hasTagName(ulTag) && !listNode->hasTagName(olTag))
1300 || !listNode->rendererIsEditable() 1300 || !listNode->rendererIsEditable()
1301 || listNode == emptyListItem->rootEditableElement()) 1301 || listNode == emptyListItem->rootEditableElement())
1302 return false; 1302 return false;
1303 1303
1304 Handle<Element> newBlock; 1304 Handle<Element> newBlock;
1305 if (Handle<ContainerNode> blockEnclosingList = listNode->parentNode()) { 1305 if (Handle<ContainerNode> blockEnclosingList = listNode->parentNode()) {
1306 if (blockEnclosingList->hasTagName(liTag)) { // listNode is inside anoth er list item 1306 if (blockEnclosingList->hasTagName(liTag)) { // listNode is inside anoth er list item
1307 if (visiblePositionAfterNode(blockEnclosingList.raw()) == visiblePos itionAfterNode(listNode.raw())) { 1307 if (visiblePositionAfterNode(blockEnclosingList) == visiblePositionA fterNode(listNode)) {
1308 // If listNode appears at the end of the outer list item, then m ove listNode outside of this list item 1308 // If listNode appears at the end of the outer list item, then m ove listNode outside of this list item
1309 // e.g. <ul><li>hello <ul><li><br></li></ul> </li></ul> should b ecome <ul><li>hello</li> <ul><li><br></li></ul> </ul> after this section 1309 // e.g. <ul><li>hello <ul><li><br></li></ul> </li></ul> should b ecome <ul><li>hello</li> <ul><li><br></li></ul> </ul> after this section
1310 // If listNode does NOT appear at the end, then we should consid er it as a regular paragraph. 1310 // If listNode does NOT appear at the end, then we should consid er it as a regular paragraph.
1311 // e.g. <ul><li> <ul><li><br></li></ul> hello</li></ul> should b ecome <ul><li> <div><br></div> hello</li></ul> at the end 1311 // e.g. <ul><li> <ul><li><br></li></ul> hello</li></ul> should b ecome <ul><li> <div><br></div> hello</li></ul> at the end
1312 splitElement(toElement(blockEnclosingList), listNode); 1312 splitElement(toElement(blockEnclosingList), listNode);
1313 removeNodePreservingChildren(listNode->parentNode()); 1313 removeNodePreservingChildren(listNode->parentNode());
1314 newBlock = createListItemElement(document()); 1314 newBlock = createListItemElement(document());
1315 } 1315 }
1316 // If listNode does NOT appear at the end of the outer list item, th en behave as if in a regular paragraph. 1316 // If listNode does NOT appear at the end of the outer list item, th en behave as if in a regular paragraph.
1317 } else if (blockEnclosingList->hasTagName(olTag) || blockEnclosingList-> hasTagName(ulTag)) 1317 } else if (blockEnclosingList->hasTagName(olTag) || blockEnclosingList-> hasTagName(ulTag))
1318 newBlock = createListItemElement(document()); 1318 newBlock = createListItemElement(document());
1319 } 1319 }
1320 if (!newBlock) 1320 if (!newBlock)
1321 newBlock = createDefaultParagraphElement(document()); 1321 newBlock = createDefaultParagraphElement(document());
1322 1322
1323 Handle<Node> previousListNode = emptyListItem->isElementNode() ? Result<Node >(toElement(emptyListItem)->previousElementSibling()) : emptyListItem->previousS ibling(); 1323 Handle<Node> previousListNode = emptyListItem->isElementNode() ? Result<Node >(toElement(emptyListItem)->previousElementSibling()) : emptyListItem->previousS ibling();
1324 Handle<Node> nextListNode = emptyListItem->isElementNode() ? Result<Node>(to Element(emptyListItem)->nextElementSibling()) : emptyListItem->nextSibling(); 1324 Handle<Node> nextListNode = emptyListItem->isElementNode() ? Result<Node>(to Element(emptyListItem)->nextElementSibling()) : emptyListItem->nextSibling();
1325 if (isListItem(nextListNode.raw()) || isListElement(nextListNode.raw())) { 1325 if (isListItem(nextListNode) || isListElement(nextListNode)) {
1326 // If emptyListItem follows another list item or nested list, split the list node. 1326 // If emptyListItem follows another list item or nested list, split the list node.
1327 if (isListItem(previousListNode.raw()) || isListElement(previousListNode .raw())) 1327 if (isListItem(previousListNode) || isListElement(previousListNode))
1328 splitElement(toElement(listNode), emptyListItem); 1328 splitElement(toElement(listNode), emptyListItem);
1329 1329
1330 // If emptyListItem is followed by other list item or nested list, then insert newBlock before the list node. 1330 // If emptyListItem is followed by other list item or nested list, then insert newBlock before the list node.
1331 // Because we have splitted the element, emptyListItem is the first elem ent in the list node. 1331 // Because we have splitted the element, emptyListItem is the first elem ent in the list node.
1332 // i.e. insert newBlock before ul or ol whose first element is emptyList Item 1332 // i.e. insert newBlock before ul or ol whose first element is emptyList Item
1333 insertNodeBefore(newBlock, listNode); 1333 insertNodeBefore(newBlock, listNode);
1334 removeNode(emptyListItem); 1334 removeNode(emptyListItem);
1335 } else { 1335 } else {
1336 // When emptyListItem does not follow any list item or nested list, inse rt newBlock after the enclosing list node. 1336 // When emptyListItem does not follow any list item or nested list, inse rt newBlock after the enclosing list node.
1337 // Remove the enclosing node if emptyListItem is the only child; otherwi se just remove emptyListItem. 1337 // Remove the enclosing node if emptyListItem is the only child; otherwi se just remove emptyListItem.
1338 insertNodeAfter(newBlock, listNode); 1338 insertNodeAfter(newBlock, listNode);
1339 removeNode(isListItem(previousListNode.raw()) || isListElement(previousL istNode.raw()) ? emptyListItem : Handle<Node>(listNode)); 1339 removeNode(isListItem(previousListNode) || isListElement(previousListNod e) ? emptyListItem : Handle<Node>(listNode));
1340 } 1340 }
1341 1341
1342 appendBlockPlaceholder(newBlock); 1342 appendBlockPlaceholder(newBlock);
1343 setEndingSelection(VisibleSelection(firstPositionInNode(newBlock), DOWNSTREA M, endingSelection().isDirectional())); 1343 setEndingSelection(VisibleSelection(firstPositionInNode(newBlock), DOWNSTREA M, endingSelection().isDirectional()));
1344 1344
1345 style->prepareToApplyAt(endingSelection().start()); 1345 style->prepareToApplyAt(endingSelection().start());
1346 if (!style->isEmpty()) 1346 if (!style->isEmpty())
1347 applyStyle(style.get()); 1347 applyStyle(style.get());
1348 1348
1349 return true; 1349 return true;
1350 } 1350 }
1351 1351
1352 // If the caret is in an empty quoted paragraph, and either there is nothing bef ore that 1352 // If the caret is in an empty quoted paragraph, and either there is nothing bef ore that
1353 // paragraph, or what is before is unquoted, and the user presses delete, unquot e that paragraph. 1353 // paragraph, or what is before is unquoted, and the user presses delete, unquot e that paragraph.
1354 bool CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph() 1354 bool CompositeEditCommand::breakOutOfEmptyMailBlockquotedParagraph()
1355 { 1355 {
1356 if (!endingSelection().isCaret()) 1356 if (!endingSelection().isCaret())
1357 return false; 1357 return false;
1358 1358
1359 VisiblePosition caret(endingSelection().visibleStart()); 1359 VisiblePosition caret(endingSelection().visibleStart());
1360 Node* highestBlockquote = highestEnclosingNodeOfType(caret.deepEquivalent(), &isMailBlockquote); 1360 Handle<Node> highestBlockquote = highestEnclosingNodeOfType(caret.deepEquiva lent(), &isMailBlockquote);
1361 if (!highestBlockquote) 1361 if (!highestBlockquote)
1362 return false; 1362 return false;
1363 1363
1364 if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret)) 1364 if (!isStartOfParagraph(caret) || !isEndOfParagraph(caret))
1365 return false; 1365 return false;
1366 1366
1367 VisiblePosition previous(caret.previous(CannotCrossEditingBoundary)); 1367 VisiblePosition previous(caret.previous(CannotCrossEditingBoundary));
1368 // Only move forward if there's nothing before the caret, or if there's unqu oted content before it. 1368 // Only move forward if there's nothing before the caret, or if there's unqu oted content before it.
1369 if (enclosingNodeOfType(previous.deepEquivalent(), &isMailBlockquote)) 1369 if (enclosingNodeOfType(previous.deepEquivalent(), &isMailBlockquote))
1370 return false; 1370 return false;
1371 1371
1372 Handle<Node> br = createBreakElement(document()); 1372 Handle<Node> br = createBreakElement(document());
1373 // We want to replace this quoted paragraph with an unquoted one, so insert a br 1373 // We want to replace this quoted paragraph with an unquoted one, so insert a br
1374 // to hold the caret before the highest blockquote. 1374 // to hold the caret before the highest blockquote.
1375 insertNodeBefore(br, adoptRawResult(highestBlockquote)); 1375 insertNodeBefore(br, highestBlockquote);
1376 VisiblePosition atBR(positionBeforeNode(br)); 1376 VisiblePosition atBR(positionBeforeNode(br));
1377 // If the br we inserted collapsed, for example foo<br><blockquote>...</bloc kquote>, insert 1377 // If the br we inserted collapsed, for example foo<br><blockquote>...</bloc kquote>, insert
1378 // a second one. 1378 // a second one.
1379 if (!isStartOfParagraph(atBR)) 1379 if (!isStartOfParagraph(atBR))
1380 insertNodeBefore(createBreakElement(document()), br); 1380 insertNodeBefore(createBreakElement(document()), br);
1381 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional()) ); 1381 setEndingSelection(VisibleSelection(atBR, endingSelection().isDirectional()) );
1382 1382
1383 // If this is an empty paragraph there must be a line break here. 1383 // If this is an empty paragraph there must be a line break here.
1384 if (!lineBreakExistsAtVisiblePosition(caret)) 1384 if (!lineBreakExistsAtVisiblePosition(caret))
1385 return false; 1385 return false;
(...skipping 20 matching lines...) Expand all
1406 // Operations use this function to avoid inserting content into an anchor when a t the start or the end of 1406 // Operations use this function to avoid inserting content into an anchor when a t the start or the end of
1407 // that anchor, as in NSTextView. 1407 // that anchor, as in NSTextView.
1408 // FIXME: This is only an approximation of NSTextViews insertion behavior, which varies depending on how 1408 // FIXME: This is only an approximation of NSTextViews insertion behavior, which varies depending on how
1409 // the caret was made. 1409 // the caret was made.
1410 Position CompositeEditCommand::positionAvoidingSpecialElementBoundary(const Posi tion& original) 1410 Position CompositeEditCommand::positionAvoidingSpecialElementBoundary(const Posi tion& original)
1411 { 1411 {
1412 if (original.isNull()) 1412 if (original.isNull())
1413 return original; 1413 return original;
1414 1414
1415 VisiblePosition visiblePos(original); 1415 VisiblePosition visiblePos(original);
1416 Handle<Node> enclosingAnchor = adoptRawResult(enclosingAnchorElement(origina l)); 1416 Handle<Node> enclosingAnchor = enclosingAnchorElement(original);
1417 Position result = original; 1417 Position result = original;
1418 1418
1419 if (!enclosingAnchor) 1419 if (!enclosingAnchor)
1420 return result; 1420 return result;
1421 1421
1422 // Don't avoid block level anchors, because that would insert content into t he wrong paragraph. 1422 // Don't avoid block level anchors, because that would insert content into t he wrong paragraph.
1423 if (enclosingAnchor && !isBlock(enclosingAnchor.raw())) { 1423 if (enclosingAnchor && !isBlock(enclosingAnchor)) {
1424 VisiblePosition firstInAnchor(firstPositionInNode(enclosingAnchor)); 1424 VisiblePosition firstInAnchor(firstPositionInNode(enclosingAnchor));
1425 VisiblePosition lastInAnchor(lastPositionInNode(enclosingAnchor)); 1425 VisiblePosition lastInAnchor(lastPositionInNode(enclosingAnchor));
1426 // If visually just after the anchor, insert *inside* the anchor unless it's the last 1426 // If visually just after the anchor, insert *inside* the anchor unless it's the last
1427 // VisiblePosition in the document, to match NSTextView. 1427 // VisiblePosition in the document, to match NSTextView.
1428 if (visiblePos == lastInAnchor) { 1428 if (visiblePos == lastInAnchor) {
1429 // Make sure anchors are pushed down before avoiding them so that we don't 1429 // Make sure anchors are pushed down before avoiding them so that we don't
1430 // also avoid structural elements like lists and blocks (5142012). 1430 // also avoid structural elements like lists and blocks (5142012).
1431 if (original.deprecatedNode() != enclosingAnchor && original.depreca tedNode()->parentNode() != enclosingAnchor) { 1431 if (original.deprecatedNode() != enclosingAnchor && original.depreca tedNode()->parentNode() != enclosingAnchor) {
1432 pushAnchorElementDown(enclosingAnchor); 1432 pushAnchorElementDown(enclosingAnchor);
1433 enclosingAnchor = adoptRawResult(enclosingAnchorElement(original )); 1433 enclosingAnchor = enclosingAnchorElement(original);
1434 if (!enclosingAnchor) 1434 if (!enclosingAnchor)
1435 return original; 1435 return original;
1436 } 1436 }
1437 // Don't insert outside an anchor if doing so would skip over a line break. It would 1437 // Don't insert outside an anchor if doing so would skip over a line break. It would
1438 // probably be safe to move the line break so that we could still av oid the anchor here. 1438 // probably be safe to move the line break so that we could still av oid the anchor here.
1439 Position downstream(visiblePos.deepEquivalent().downstream()); 1439 Position downstream(visiblePos.deepEquivalent().downstream());
1440 if (lineBreakExistsAtVisiblePosition(visiblePos) && downstream.depre catedNode()->isDescendantOf(enclosingAnchor.raw())) 1440 if (lineBreakExistsAtVisiblePosition(visiblePos) && downstream.depre catedNode()->isDescendantOf(enclosingAnchor.raw()))
1441 return original; 1441 return original;
1442 1442
1443 result = positionInParentAfterNode(enclosingAnchor); 1443 result = positionInParentAfterNode(enclosingAnchor);
1444 } 1444 }
1445 // If visually just before an anchor, insert *outside* the anchor unless it's the first 1445 // If visually just before an anchor, insert *outside* the anchor unless it's the first
1446 // VisiblePosition in a paragraph, to match NSTextView. 1446 // VisiblePosition in a paragraph, to match NSTextView.
1447 if (visiblePos == firstInAnchor) { 1447 if (visiblePos == firstInAnchor) {
1448 // Make sure anchors are pushed down before avoiding them so that we don't 1448 // Make sure anchors are pushed down before avoiding them so that we don't
1449 // also avoid structural elements like lists and blocks (5142012). 1449 // also avoid structural elements like lists and blocks (5142012).
1450 if (original.deprecatedNode() != enclosingAnchor && original.depreca tedNode()->parentNode() != enclosingAnchor) { 1450 if (original.deprecatedNode() != enclosingAnchor && original.depreca tedNode()->parentNode() != enclosingAnchor) {
1451 pushAnchorElementDown(enclosingAnchor); 1451 pushAnchorElementDown(enclosingAnchor);
1452 enclosingAnchor = adoptRawResult(enclosingAnchorElement(original )); 1452 enclosingAnchor = enclosingAnchorElement(original);
1453 } 1453 }
1454 if (!enclosingAnchor) 1454 if (!enclosingAnchor)
1455 return original; 1455 return original;
1456 1456
1457 result = positionInParentBeforeNode(enclosingAnchor); 1457 result = positionInParentBeforeNode(enclosingAnchor);
1458 } 1458 }
1459 } 1459 }
1460 1460
1461 if (result.isNull() || !editableRootForPosition(result)) 1461 if (result.isNull() || !editableRootForPosition(result))
1462 result = original; 1462 result = original;
(...skipping 13 matching lines...) Expand all
1476 Handle<Node> endNode = end; 1476 Handle<Node> endNode = end;
1477 if (shouldSplitAncestor && endNode->parentNode()) 1477 if (shouldSplitAncestor && endNode->parentNode())
1478 endNode = endNode->parentNode(); 1478 endNode = endNode->parentNode();
1479 1479
1480 for (node = start; node && node->parentNode() != endNode; node = node->paren tNode()) { 1480 for (node = start; node && node->parentNode() != endNode; node = node->paren tNode()) {
1481 HandleScope scope; 1481 HandleScope scope;
1482 if (!node->parentNode()->isElementNode()) 1482 if (!node->parentNode()->isElementNode())
1483 break; 1483 break;
1484 // Do not split a node when doing so introduces an empty node. 1484 // Do not split a node when doing so introduces an empty node.
1485 VisiblePosition positionInParent = firstPositionInNode(node->parentNode( )); 1485 VisiblePosition positionInParent = firstPositionInNode(node->parentNode( ));
1486 VisiblePosition positionInNode = firstPositionInOrBeforeNode(node.raw()) ; 1486 VisiblePosition positionInNode = firstPositionInOrBeforeNode(node);
1487 if (positionInParent != positionInNode) 1487 if (positionInParent != positionInNode)
1488 splitElement(toElement(node->parentNode()), node); 1488 splitElement(toElement(node->parentNode()), node);
1489 } 1489 }
1490 1490
1491 return node; 1491 return node;
1492 } 1492 }
1493 1493
1494 Result<Element> createBlockPlaceholderElement(const Handle<Document>& document) 1494 Result<Element> createBlockPlaceholderElement(const Handle<Document>& document)
1495 { 1495 {
1496 return document->createElement(brTag, false); 1496 return document->createElement(brTag, false);
1497 } 1497 }
1498 1498
1499 } // namespace WebCore 1499 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698