+2005-03-15 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by John.
+
+ <rdar://problem/4053266> Pressing return a few times right after a link makes the new blank lines part of the link
+
+ * khtml/editing/htmlediting.cpp:
+ (khtml::InsertLineBreakCommand::doApply): Use
+ positionOutsideContainingSpecialElement in the right two places.
+ (khtml::InsertParagraphSeparatorCommand::doApply): Ditto.
+
+ - move all these helper functions higher in the file
+
+ * khtml/editing/htmlediting.cpp:
+ (khtml::isSpecialElement):
+ (khtml::isFirstVisiblePositionInSpecialElement):
+ (khtml::positionBeforeNode):
+ (khtml::positionBeforeContainingSpecialElement):
+ (khtml::maxRangeOffset):
+ (khtml::isLastVisiblePositionInSpecialElement):
+ (khtml::positionAfterNode):
+ (khtml::positionAfterContainingSpecialElement):
+ (khtml::positionOutsideContainingSpecialElement):
+
+2005-03-14 Maciej Stachowiak <mjs@apple.com>
+
+ Reviewed by Ken.
+
+ <rdar://problem/4049925> Pasting right after a link makes pasted content part of the link (without visible style change)
+
+ * khtml/editing/htmlediting.cpp:
+ (khtml::positionOutsideContainingSpecialElement): made a helper
+ function that computes a position outside the outermost containing
+ special element if the passed in position is right at the start or
+ end of it
+ (khtml::InsertTextCommand::prepareForTextInsertion): use new helper here
+ (khtml::ReplaceSelectionCommand::doApply): use it here too: this is the fix
+ (khtml::positionBeforeNode): made static
+ (khtml::positionBeforeContainingSpecialElement): made static
+ (khtml::positionAfterNode): made static
+ (khtml::positionAfterContainingSpecialElement): made static
+
2005-03-15 Richard Williamson <rjw@apple.com>
Fixed <rdar://problem/4053658> Crash getting direction at maps.google.com
* khtml/xml/dom_docimpl.cpp:
(DocumentImpl::detach): Took out the call to removeAllEventListenersFromAllNodes(). If we remove all event listeners here then when KHTMLPart::closeURL() checks for even listeners, it will never have any because they'll already be gone.
+>>>>>>> 1.4064
2005-03-15 Ken Kocienda <kocienda@apple.com>
Reviewed by Vicki
}
}
+static bool isSpecialElement(NodeImpl *n)
+{
+ if (!n->isHTMLElement())
+ return false;
+
+ if (n->id() == ID_A && n->hasAnchor())
+ return true;
+
+ return false;
+}
+
+static bool isFirstVisiblePositionInSpecialElement(const Position& pos)
+{
+ VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM);
+
+ for (NodeImpl *n = pos.node(); n; n = n->parentNode()) {
+ if (VisiblePosition(n, 0, DOWNSTREAM) != vPos)
+ return false;
+ if (n->rootEditableElement() == NULL)
+ return false;
+ if (isSpecialElement(n))
+ return true;
+ }
+
+ return false;
+}
+
+static Position positionBeforeNode(NodeImpl *node)
+{
+ return Position(node->parentNode(), node->nodeIndex());
+}
+
+static Position positionBeforeContainingSpecialElement(const Position& pos)
+{
+ ASSERT(isFirstVisiblePositionInSpecialElement(pos));
+
+ VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM);
+
+ NodeImpl *outermostSpecialElement = NULL;
+
+ for (NodeImpl *n = pos.node(); n; n = n->parentNode()) {
+ if (VisiblePosition(n, 0, DOWNSTREAM) != vPos)
+ break;
+ if (n->rootEditableElement() == NULL)
+ break;
+ if (isSpecialElement(n))
+ outermostSpecialElement = n;
+ }
+
+ ASSERT(outermostSpecialElement);
+
+ return positionBeforeNode(outermostSpecialElement);
+}
+
+static bool isLastVisiblePositionInSpecialElement(const Position& pos)
+{
+ // make sure to get a range-compliant version of the position
+ Position rangePos = VisiblePosition(pos, DOWNSTREAM).position();
+
+ VisiblePosition vPos = VisiblePosition(rangePos, DOWNSTREAM);
+
+ for (NodeImpl *n = rangePos.node(); n; n = n->parentNode()) {
+ if (VisiblePosition(n, maxRangeOffset(n), DOWNSTREAM) != vPos)
+ return false;
+ if (n->rootEditableElement() == NULL)
+ return false;
+ if (isSpecialElement(n))
+ return true;
+ }
+
+ return false;
+}
+
+static Position positionAfterNode(NodeImpl *node)
+{
+ return Position(node->parentNode(), node->nodeIndex() + 1);
+}
+
+static Position positionAfterContainingSpecialElement(const Position& pos)
+{
+ ASSERT(isLastVisiblePositionInSpecialElement(pos));
+
+ // make sure to get a range-compliant version of the position
+ Position rangePos = VisiblePosition(pos, DOWNSTREAM).position();
+
+ VisiblePosition vPos = VisiblePosition(rangePos, DOWNSTREAM);
+
+ NodeImpl *outermostSpecialElement = NULL;
+
+ for (NodeImpl *n = rangePos.node(); n; n = n->parentNode()) {
+ if (VisiblePosition(n, maxRangeOffset(n), DOWNSTREAM) != vPos)
+ break;
+ if (n->rootEditableElement() == NULL)
+ break;
+ if (isSpecialElement(n))
+ outermostSpecialElement = n;
+ }
+
+ ASSERT(outermostSpecialElement);
+
+ return positionAfterNode(outermostSpecialElement);
+}
+
+static Position positionOutsideContainingSpecialElement(const Position &pos)
+{
+ if (isFirstVisiblePositionInSpecialElement(pos)) {
+ return positionBeforeContainingSpecialElement(pos);
+ } else if (isLastVisiblePositionInSpecialElement(pos)) {
+ return positionAfterContainingSpecialElement(pos);
+ }
+
+ return pos;
+}
+
//==========================================================================================
// Concrete commands
//------------------------------------------------------------------------------------------
NodeImpl *nodeToInsert = breakNode;
Position pos(selection.start().upstream(StayInBlock));
+
+ pos = positionOutsideContainingSpecialElement(pos);
+
bool atStart = pos.offset() <= pos.node()->caretMinOffset();
bool atEnd = pos.offset() >= pos.node()->caretMaxOffset();
bool atEndOfBlock = isLastVisiblePositionInBlock(VisiblePosition(pos, selection.startAffinity()));
affinity = endingSelection().startAffinity();
}
+ pos = positionOutsideContainingSpecialElement(pos);
+
calculateStyleBeforeInsertion(pos);
// Find the start block.
if (upstreamInDifferentBlock || isFirstInBlock) {
LOG(Editing, "insert paragraph separator: first in block case");
pos = pos.downstream(StayInBlock);
+ pos = positionOutsideContainingSpecialElement(pos);
NodeImpl *refNode = isFirstInBlock && !startBlockIsRoot ? startBlock : pos.node();
insertNodeBefore(blockToInsert, refNode);
appendBlockPlaceholder(blockToInsert);
{
}
-static bool isSpecialElement(NodeImpl *n)
-{
- if (!n->isHTMLElement())
- return false;
-
- if (n->id() == ID_A && n->hasAnchor())
- return true;
-
- return false;
-}
-
-static bool isFirstVisiblePositionInSpecialElement(const Position& pos)
-{
- VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM);
-
- for (NodeImpl *n = pos.node(); n; n = n->parentNode()) {
- if (VisiblePosition(n, 0, DOWNSTREAM) != vPos)
- return false;
- if (n->rootEditableElement() == NULL)
- return false;
- if (isSpecialElement(n))
- return true;
- }
-
- return false;
-}
-
-Position positionBeforeNode(NodeImpl *node)
-{
- return Position(node->parentNode(), node->nodeIndex());
-}
-
-Position positionBeforeContainingSpecialElement(const Position& pos)
-{
- ASSERT(isFirstVisiblePositionInSpecialElement(pos));
-
- VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM);
-
- NodeImpl *outermostSpecialElement = NULL;
-
- for (NodeImpl *n = pos.node(); n; n = n->parentNode()) {
- if (VisiblePosition(n, 0, DOWNSTREAM) != vPos)
- break;
- if (n->rootEditableElement() == NULL)
- break;
- if (isSpecialElement(n))
- outermostSpecialElement = n;
- }
-
- ASSERT(outermostSpecialElement);
-
- return positionBeforeNode(outermostSpecialElement);
-}
-
-static bool isLastVisiblePositionInSpecialElement(const Position& pos)
-{
- // make sure to get a range-compliant version of the position
- Position rangePos = VisiblePosition(pos, DOWNSTREAM).position();
-
- VisiblePosition vPos = VisiblePosition(rangePos, DOWNSTREAM);
-
- for (NodeImpl *n = rangePos.node(); n; n = n->parentNode()) {
- if (VisiblePosition(n, maxRangeOffset(n), DOWNSTREAM) != vPos)
- return false;
- if (n->rootEditableElement() == NULL)
- return false;
- if (isSpecialElement(n))
- return true;
- }
-
- return false;
-}
-
-Position positionAfterNode(NodeImpl *node)
-{
- return Position(node->parentNode(), node->nodeIndex() + 1);
-}
-
-Position positionAfterContainingSpecialElement(const Position& pos)
-{
- ASSERT(isLastVisiblePositionInSpecialElement(pos));
-
- // make sure to get a range-compliant version of the position
- Position rangePos = VisiblePosition(pos, DOWNSTREAM).position();
-
- VisiblePosition vPos = VisiblePosition(rangePos, DOWNSTREAM);
-
- NodeImpl *outermostSpecialElement = NULL;
-
- for (NodeImpl *n = rangePos.node(); n; n = n->parentNode()) {
- if (VisiblePosition(n, maxRangeOffset(n), DOWNSTREAM) != vPos)
- break;
- if (n->rootEditableElement() == NULL)
- break;
- if (isSpecialElement(n))
- outermostSpecialElement = n;
- }
-
- ASSERT(outermostSpecialElement);
-
- return positionAfterNode(outermostSpecialElement);
-}
-
Position InsertTextCommand::prepareForTextInsertion(bool adjustDownstream)
{
// Prepare for text input by looking at the current position.
Selection typingStyleRange;
- if (isFirstVisiblePositionInSpecialElement(pos)) {
- pos = positionBeforeContainingSpecialElement(pos);
- } else if (isLastVisiblePositionInSpecialElement(pos)) {
- pos = positionAfterContainingSpecialElement(pos);
- }
+ pos = positionOutsideContainingSpecialElement(pos);
if (!pos.node()->isTextNode()) {
NodeImpl *textNode = document()->createEditingTextNode("");
// collect information about the current selection, prior to deleting the selection
Selection selection = endingSelection();
ASSERT(selection.isCaretOrRange());
+
VisiblePosition visibleStart(selection.start(), selection.startAffinity());
VisiblePosition visibleEnd(selection.end(), selection.endAffinity());
bool startAtStartOfBlock = isFirstVisiblePositionInBlock(visibleStart);
if (startAtStartOfBlock && startBlock->inDocument())
startPos = Position(startBlock, 0);
+ startPos = positionOutsideContainingSpecialElement(startPos);
+
KHTMLPart *part = document()->part();
if (m_matchStyle) {
m_insertionStyle = styleAtPosition(startPos);