⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 markup.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 2 页
字号:
            for (unsigned long i = 0; i < length; i++) {
                AttributeImpl *attr = attrs->attributeItem(i);
                if (e->isURLAttribute(attr)) {
                    e->setAttribute(attr->id(), KURL(baseURL, attr->value().string()).url());
                }
            }
        }
    }
}

QString createMarkup(const RangeImpl *range, QPtrList<NodeImpl> *nodes, EAnnotateForInterchange annotate)
{
    if (!range || range->isDetached())
        return QString();

    static const QString interchangeNewlineString = QString("<br class=\"") + AppleInterchangeNewline + "\">";

    int exceptionCode = 0;
    NodeImpl *commonAncestor = range->commonAncestorContainer(exceptionCode);
    ASSERT(exceptionCode == 0);

    DocumentImpl *doc = commonAncestor->getDocument();
    doc->updateLayout();

    NodeImpl *commonAncestorBlock = 0;
    if (commonAncestor != 0) {
        commonAncestorBlock = commonAncestor->enclosingBlockFlowElement();
    }
    if (commonAncestorBlock == 0) {
        return "";    
    }

    QStringList markups;
    NodeImpl *pastEnd = range->pastEndNode();
    NodeImpl *lastClosed = 0;
    QPtrList<NodeImpl> ancestorsToClose;

    // calculate the "default style" for this markup
    Position pos(doc->documentElement(), 0);
    CSSMutableStyleDeclarationImpl *defaultStyle = pos.computedStyle()->copyInheritableProperties();
    defaultStyle->ref();
    
    NodeImpl *startNode = range->startNode();
    VisiblePosition visibleStart(range->startPosition(), VP_DEFAULT_AFFINITY);
    VisiblePosition visibleEnd(range->endPosition(), VP_DEFAULT_AFFINITY);
    if (isEndOfBlock(visibleStart)) {
        if (visibleStart == visibleEnd.previous())
            return interchangeNewlineString;
        markups.append(interchangeNewlineString);
        startNode = startNode->traverseNextNode();
    }
    
    // Iterate through the nodes of the range.
    NodeImpl *next;
    for (NodeImpl *n = startNode; n != pastEnd; n = next) {
        next = n->traverseNextNode();

        if (n->isBlockFlow() && next == pastEnd) {
            // Don't write out an empty block.
            continue;
        }
        
        // Add the node to the markup.
        if (n->renderer()) {
            markups.append(startMarkup(n, range, annotate, defaultStyle));
            if (nodes) {
                nodes->append(n);
            }
        }
        
        if (n->firstChild() == 0) {
            // Node has no children, add its close tag now.
            if (n->renderer()) {
                markups.append(endMarkup(n));
                lastClosed = n;
            }
            
            // Check if the node is the last leaf of a tree.
            if (n->nextSibling() == 0 || next == pastEnd) {
                if (!ancestorsToClose.isEmpty()) {
                    // Close up the ancestors.
                    while (NodeImpl *ancestor = ancestorsToClose.last()) {
                        if (next != pastEnd && ancestor == next->parentNode()) {
                            break;
                        }
                        // Not at the end of the range, close ancestors up to sibling of next node.
                        markups.append(endMarkup(ancestor));
                        lastClosed = ancestor;
                        ancestorsToClose.removeLast();
                    }
                } else {
                    // No ancestors to close, but need to add ancestors not in range since next node is in another tree. 
                    if (next != pastEnd) {
                        NodeImpl *nextParent = next->parentNode();
                        if (n != nextParent) {
                            for (NodeImpl *parent = n->parent(); parent != 0 && parent != nextParent; parent = parent->parentNode()) {
                                markups.prepend(startMarkup(parent, range, annotate, defaultStyle));
                                markups.append(endMarkup(parent));
                                if (nodes) {
                                    nodes->append(parent);
                                }                            
                                lastClosed = parent;
                            }
                        }
                    }
                }
            }
        } else if (n->renderer()) {
            // Node is an ancestor, set it to close eventually.
            ancestorsToClose.append(n);
        }
    }
    
    NodeImpl *rangeStartNode = range->startNode();
    int rangeStartOffset = range->startOffset(exceptionCode);
    ASSERT(exceptionCode == 0);
    
    // Add ancestors up to the common ancestor block so inline ancestors such as FONT and B are part of the markup.
    if (lastClosed) {
        for (NodeImpl *ancestor = lastClosed->parentNode(); ancestor; ancestor = ancestor->parentNode()) {
            if (RangeImpl::compareBoundaryPoints(ancestor, 0, rangeStartNode, rangeStartOffset) >= 0) {
                // we have already added markup for this node
                continue;
            }
            bool breakAtEnd = false;
            if (commonAncestorBlock == ancestor) {
                NodeImpl::Id id = ancestor->id();
                // Include ancestors that are required to retain the appearance of the copied markup.
                if (id == ID_PRE || id == ID_TABLE || id == ID_OL || id == ID_UL) {
                    breakAtEnd = true;
                } else {
                    break;
                }
            }
            markups.prepend(startMarkup(ancestor, range, annotate, defaultStyle));
            markups.append(endMarkup(ancestor));
            if (nodes) {
                nodes->append(ancestor);
            }        
            if (breakAtEnd) {
                break;
            }
        }
    }

    if (annotate) {
        Position pos(endPosition(range));
        NodeImpl *block = pos.node()->enclosingBlockFlowElement();
        NodeImpl *upstreamBlock = pos.upstream().node()->enclosingBlockFlowElement();
        if (block != upstreamBlock) {
            markups.append(interchangeNewlineString);
        }
    }

    // Retain the Mail quote level by including all ancestor mail block quotes.
    for (NodeImpl *ancestor = commonAncestorBlock; ancestor; ancestor = ancestor->parentNode()) {
        if (isMailBlockquote(ancestor)) {
            markups.prepend(startMarkup(ancestor, range, annotate, defaultStyle));
            markups.append(endMarkup(ancestor));
        }
    }
    
    // add in the "default style" for this markup
    // FIXME: Handle case where value has illegal characters in it, like "
    QString openTag = QString("<span class=\"") + AppleStyleSpanClass + "\" style=\"" + defaultStyle->cssText().string() + "\">";
    markups.prepend(openTag);
    markups.append("</span>");
    defaultStyle->deref();

    return markups.join("");
}

DocumentFragmentImpl *createFragmentFromMarkup(DocumentImpl *document, const QString &markup, const QString &baseURL)
{
    // FIXME: What if the document element is not an HTML element?
    HTMLElementImpl *element = static_cast<HTMLElementImpl *>(document->documentElement());

    DocumentFragmentImpl *fragment = element->createContextualFragment(markup);
    ASSERT(fragment);

    if (!baseURL.isEmpty() && baseURL != document->baseURL())
        completeURLs(fragment, baseURL);

    return fragment;
}

QString createMarkup(const DOM::NodeImpl *node, EChildrenOnly includeChildren,
    QPtrList<DOM::NodeImpl> *nodes, EAnnotateForInterchange annotate)
{
    ASSERT(annotate == DoNotAnnotateForInterchange); // annotation not yet implemented for this code path

    // FIXME: We could take out this if statement if we had more time to test.
    // I'm concerned that making this crash when the document is nil might be too risky a change at the moment.
    DocumentImpl *doc = node->getDocument();
    assert(doc);
    if (doc)
        doc->updateLayout();

    return markup(node, includeChildren, false, nodes);
}

DOM::DocumentFragmentImpl *createFragmentFromText(DOM::DocumentImpl *document, const QString &text)
{
    if (!document)
        return 0;

    DocumentFragmentImpl *fragment = document->createDocumentFragment();
    fragment->ref();
    
    if (!text.isEmpty()) {
        QString string = text;

        // Replace tabs with four plain spaces.
        // These spaces will get converted along with the other existing spaces below.
        string.replace('\t', "    ");

        // FIXME: Wrap the NBSP's in a span that says "converted space".
        int offset = 0;
        int stringLength = string.length();
        while (1) {
            // FIXME: This only converts plain old spaces, and does not
            // deal with more exotic whitespace. Note that we want to 
            // leave newlines and returns alone at this point anyway, 
            // since those are handled specially later.
            int spacesPos = string.find("  ", offset);
            if (spacesPos < 0)
                break;

            // Found two adjoining spaces.
            // Now, lookahead to see if these two spaces are followed by:
            //   1. another space and then a non-space
            //   2. another space and then the end of the string
            // If either 1 or 2 is true, replace the three spaces found with nbsp+nbsp+space, 
            // otherwise, replace the first two spaces with nbsp+space.
            if ((spacesPos + 3 < stringLength && string[spacesPos + 2] == ' ' && string[spacesPos + 3] != ' ')
                    || (spacesPos + 3 == stringLength && string[spacesPos + 2] == ' ')) {
                string.replace(spacesPos, 3, "\xA0\xA0 ");
            } else {
                string.replace(spacesPos, 2, "\xA0 ");
            }
            offset = spacesPos + 2;
        }

        // Break string into paragraphs. Extra line breaks turn into empty paragraphs.
        string.replace(QString("\r\n"), "\n");
        string.replace('\r', '\n');
        QStringList list = QStringList::split('\n', string, true); // true gets us empty strings in the list
        while (!list.isEmpty()) {
            QString s = list.first();
            list.pop_front();

            int exceptionCode = 0;
            ElementImpl *element;
            if (s.isEmpty() && list.isEmpty()) {
                // For last line, use the "magic BR" rather than a P.
                element = document->createHTMLElement("br", exceptionCode);
                ASSERT(exceptionCode == 0);
                element->ref();
                element->setAttribute(ATTR_CLASS, AppleInterchangeNewline);            
            } else {
                element = createDefaultParagraphElement(document);
                NodeImpl *paragraphContents;
                if (s.isEmpty()) {
                    paragraphContents = createBlockPlaceholderElement(document);
                } else {
                    paragraphContents = document->createTextNode(s);
                    ASSERT(exceptionCode == 0);
                }
                element->ref();
                element->appendChild(paragraphContents, exceptionCode);
                ASSERT(exceptionCode == 0);
            }
            fragment->appendChild(element, exceptionCode);
            ASSERT(exceptionCode == 0);
            element->deref();
        }
    }
    
    // Trick to get the fragment back to the floating state, with 0
    // refs but not destroyed.
    fragment->setParent(document);
    fragment->deref();
    fragment->setParent(0);
    
    return fragment;
}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -