📄 dom2_rangeimpl.cpp
字号:
return;
}
if (refNode->getDocument() != m_ownerDocument->document()) {
exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
return;
}
checkNodeBA( refNode, exceptioncode );
if (exceptioncode)
return;
setEnd( refNode->parentNode(), refNode->nodeIndex()+1, exceptioncode );
}
void RangeImpl::selectNode( NodeImpl *refNode, int &exceptioncode )
{
if (m_detached) {
exceptioncode = DOMException::INVALID_STATE_ERR;
return;
}
if (!refNode) {
exceptioncode = DOMException::NOT_FOUND_ERR;
return;
}
// INVALID_NODE_TYPE_ERR: Raised if an ancestor of refNode is an Entity, Notation or
// DocumentType node or if refNode is a Document, DocumentFragment, Attr, Entity, or Notation
// node.
NodeImpl *anc;
for (anc = refNode->parentNode(); anc; anc = anc->parentNode()) {
if (anc->nodeType() == Node::ENTITY_NODE ||
anc->nodeType() == Node::NOTATION_NODE ||
anc->nodeType() == Node::DOCUMENT_TYPE_NODE) {
exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
return;
}
}
if (refNode->nodeType() == Node::DOCUMENT_NODE ||
refNode->nodeType() == Node::DOCUMENT_FRAGMENT_NODE ||
refNode->nodeType() == Node::ATTRIBUTE_NODE ||
refNode->nodeType() == Node::ENTITY_NODE ||
refNode->nodeType() == Node::NOTATION_NODE) {
exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
return;
}
setStartBefore( refNode, exceptioncode );
if (exceptioncode)
return;
setEndAfter( refNode, exceptioncode );
}
void RangeImpl::selectNodeContents( NodeImpl *refNode, int &exceptioncode )
{
if (m_detached) {
exceptioncode = DOMException::INVALID_STATE_ERR;
return;
}
if (!refNode) {
exceptioncode = DOMException::NOT_FOUND_ERR;
return;
}
// INVALID_NODE_TYPE_ERR: Raised if refNode or an ancestor of refNode is an Entity, Notation
// or DocumentType node.
NodeImpl *n;
for (n = refNode; n; n = n->parentNode()) {
if (n->nodeType() == Node::ENTITY_NODE ||
n->nodeType() == Node::NOTATION_NODE ||
n->nodeType() == Node::DOCUMENT_TYPE_NODE) {
exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
return;
}
}
setStartContainer(refNode);
m_startOffset = 0;
setEndContainer(refNode);
m_endOffset = refNode->childNodeCount();
}
void RangeImpl::surroundContents( NodeImpl *newParent, int &exceptioncode )
{
if (m_detached) {
exceptioncode = DOMException::INVALID_STATE_ERR;
return;
}
if( !newParent ) {
exceptioncode = DOMException::NOT_FOUND_ERR;
return;
}
// INVALID_NODE_TYPE_ERR: Raised if node is an Attr, Entity, DocumentType, Notation,
// Document, or DocumentFragment node.
if( newParent->nodeType() == Node::ATTRIBUTE_NODE ||
newParent->nodeType() == Node::ENTITY_NODE ||
newParent->nodeType() == Node::NOTATION_NODE ||
newParent->nodeType() == Node::DOCUMENT_TYPE_NODE ||
newParent->nodeType() == Node::DOCUMENT_NODE ||
newParent->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) {
exceptioncode = RangeException::INVALID_NODE_TYPE_ERR + RangeException::_EXCEPTION_OFFSET;
return;
}
// NO_MODIFICATION_ALLOWED_ERR: Raised if an ancestor container of either boundary-point of
// the Range is read-only.
if (containedByReadOnly()) {
exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
return;
}
// WRONG_DOCUMENT_ERR: Raised if newParent and the container of the start of the Range were
// not created from the same document.
if (newParent->getDocument() != m_startContainer->getDocument()) {
exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
return;
}
// HIERARCHY_REQUEST_ERR: Raised if the container of the start of the Range is of a type that
// does not allow children of the type of newParent or if newParent is an ancestor of the container
// or if node would end up with a child node of a type not allowed by the type of node.
if (!m_startContainer->childTypeAllowed(newParent->nodeType())) {
exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
return;
}
for (NodeImpl *n = m_startContainer; n; n = n->parentNode()) {
if (n == newParent) {
exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
return;
}
}
// ### check if node would end up with a child node of a type not allowed by the type of node
// BAD_BOUNDARYPOINTS_ERR: Raised if the Range partially selects a non-text node.
if (!offsetInCharacters(m_startContainer->nodeType())) {
if (m_startOffset > 0 && m_startOffset < m_startContainer->childNodeCount()) {
exceptioncode = RangeException::BAD_BOUNDARYPOINTS_ERR + RangeException::_EXCEPTION_OFFSET;
return;
}
}
if (!offsetInCharacters(m_endContainer->nodeType())) {
if (m_endOffset > 0 && m_endOffset < m_endContainer->childNodeCount()) {
exceptioncode = RangeException::BAD_BOUNDARYPOINTS_ERR + RangeException::_EXCEPTION_OFFSET;
return;
}
}
while (newParent->firstChild()) {
newParent->removeChild(newParent->firstChild(),exceptioncode);
if (exceptioncode)
return;
}
DocumentFragmentImpl *fragment = extractContents(exceptioncode);
if (exceptioncode)
return;
insertNode( newParent, exceptioncode );
if (exceptioncode)
return;
newParent->appendChild( fragment, exceptioncode );
if (exceptioncode)
return;
selectNode( newParent, exceptioncode );
}
void RangeImpl::setStartBefore( NodeImpl *refNode, int &exceptioncode )
{
if (m_detached) {
exceptioncode = DOMException::INVALID_STATE_ERR;
return;
}
if (!refNode) {
exceptioncode = DOMException::NOT_FOUND_ERR;
return;
}
if (refNode->getDocument() != m_ownerDocument->document()) {
exceptioncode = DOMException::WRONG_DOCUMENT_ERR;
return;
}
checkNodeBA( refNode, exceptioncode );
if (exceptioncode)
return;
setStart( refNode->parentNode(), refNode->nodeIndex(), exceptioncode );
}
void RangeImpl::setStartContainer(NodeImpl *_startContainer)
{
if (m_startContainer == _startContainer)
return;
if (m_startContainer)
m_startContainer->deref();
m_startContainer = _startContainer;
if (m_startContainer)
m_startContainer->ref();
}
void RangeImpl::setEndContainer(NodeImpl *_endContainer)
{
if (m_endContainer == _endContainer)
return;
if (m_endContainer)
m_endContainer->deref();
m_endContainer = _endContainer;
if (m_endContainer)
m_endContainer->ref();
}
void RangeImpl::checkDeleteExtract(int &exceptioncode)
{
NodeImpl *pastEnd = pastEndNode();
for (NodeImpl *n = startNode(); n != pastEnd; n = n->traverseNextNode()) {
if (n->isReadOnly()) {
exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
return;
}
if (n->nodeType() == Node::DOCUMENT_TYPE_NODE) { // ### is this for only directly under the DF, or anywhere?
exceptioncode = DOMException::HIERARCHY_REQUEST_ERR;
return;
}
}
if (containedByReadOnly()) {
exceptioncode = DOMException::NO_MODIFICATION_ALLOWED_ERR;
return;
}
}
bool RangeImpl::containedByReadOnly() const
{
NodeImpl *n;
for (n = m_startContainer; n; n = n->parentNode()) {
if (n->isReadOnly())
return true;
}
for (n = m_endContainer; n; n = n->parentNode()) {
if (n->isReadOnly())
return true;
}
return false;
}
Position RangeImpl::startPosition() const
{
return Position(m_startContainer, m_startOffset);
}
Position RangeImpl::endPosition() const
{
return Position(m_endContainer, m_endOffset);
}
NodeImpl *RangeImpl::startNode() const
{
if (!m_startContainer)
return 0;
if (offsetInCharacters(m_startContainer->nodeType()))
return m_startContainer;
NodeImpl *child = m_startContainer->childNode(m_startOffset);
if (child)
return child;
return m_startContainer->traverseNextSibling();
}
Position RangeImpl::editingStartPosition() const
{
// This function is used to avoid bugs like:
// <rdar://problem/4017641> REGRESSION (Mail): you can only bold/unbold a selection starting from end of line once
// The issue here is that calculating the selection using the start of a range sometimes considers nodes that
// should not be considered. In the case of this bug, we need to move past the offset after the last character
// in a text node in order to make the right style calculation, so we do not wind up with a false "mixed"
// style.
Position pos(m_startContainer, m_startOffset);
if (pos.isNull())
return Position();
int exceptionCode = 0;
return collapsed(exceptionCode) ? VisiblePosition(pos, UPSTREAM).deepEquivalent() : pos.downstream(DoNotStayInBlock);
}
NodeImpl *RangeImpl::pastEndNode() const
{
if (!m_endContainer)
return 0;
if (offsetInCharacters(m_endContainer->nodeType()))
return m_endContainer->traverseNextSibling();
NodeImpl *child = m_endContainer->childNode(m_endOffset);
if (child)
return child;
return m_endContainer->traverseNextSibling();
}
#ifndef NDEBUG
#define FormatBufferSize 1024
void RangeImpl::formatForDebugger(char *buffer, unsigned length) const
{
DOMString result;
DOMString s;
if (!m_startContainer || !m_endContainer) {
result = "<empty>";
}
else {
char s[FormatBufferSize];
result += "from offset ";
result += QString::number(m_startOffset);
result += " of ";
m_startContainer->formatForDebugger(s, FormatBufferSize);
result += s;
result += " to offset ";
result += QString::number(m_endOffset);
result += " of ";
m_endContainer->formatForDebugger(s, FormatBufferSize);
result += s;
}
strncpy(buffer, result.string().latin1(), length - 1);
}
#undef FormatBufferSize
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -