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

📄 markup.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include "markup.h"

#include "htmlediting.h"

#include "css/css_computedstyle.h"
#include "css/css_valueimpl.h"
#include "editing/visible_position.h"
#include "editing/visible_units.h"
#include "html/html_elementimpl.h"
#include "xml/dom_position.h"
#include "xml/dom2_rangeimpl.h"
#include "rendering/render_text.h"
#include "misc/htmlattrs.h"
#include "misc/htmltags.h"
#include "html/dtd.h"

using DOM::AttributeImpl;
using DOM::CommentImpl;
using DOM::CSSComputedStyleDeclarationImpl;
using DOM::CSSMutableStyleDeclarationImpl;
using DOM::DocumentFragmentImpl;
using DOM::DocumentImpl;
using DOM::DOMString;
using DOM::ElementImpl;
using DOM::FORBIDDEN;
using DOM::endTagRequirement;
using DOM::HTMLElementImpl;
using DOM::NamedAttrMapImpl;
using DOM::Node;
using DOM::NodeImpl;
using DOM::Position;
using DOM::RangeImpl;
using DOM::TextImpl;

#if APPLE_CHANGES
#include "KWQAssertions.h"
#include "KWQLogging.h"
#else
#define ASSERT(assertion) ((void)0)
#define ASSERT_WITH_MESSAGE(assertion, formatAndArgs...) ((void)0)
#define ASSERT_NOT_REACHED() ((void)0)
#define LOG(channel, formatAndArgs...) ((void)0)
#define ERROR(formatAndArgs...) ((void)0)
#define ASSERT(assertion) assert(assertion)
#endif

namespace khtml {

static QString escapeHTML(const QString &in)
{
    QString s = "";

    unsigned len = in.length();
    for (unsigned i = 0; i < len; ++i) {
        switch (in[i].latin1()) {
            case '&':
                s += "&amp;";
                break;
            case '<':
                s += "&lt;";
                break;
            case '>':
                s += "&gt;";
                break;
            default:
                s += in[i];
        }
    }

    return s;
}

static QString stringValueForRange(const NodeImpl *node, const RangeImpl *range)
{
    DOMString str = node->nodeValue().copy();
    if (range) {
        int exceptionCode;
        if (node == range->endContainer(exceptionCode)) {
            str.truncate(range->endOffset(exceptionCode));
        }
        if (node == range->startContainer(exceptionCode)) {
            str.remove(0, range->startOffset(exceptionCode));
        }
    }
    return str.string();
}

static QString renderedText(const NodeImpl *node, const RangeImpl *range)
{
    RenderObject *r = node->renderer();
    if (!r)
        return QString();
    
    if (!node->isTextNode())
        return QString();

    QString result = "";

    int exceptionCode;
    const TextImpl *textNode = static_cast<const TextImpl *>(node);
    unsigned startOffset = 0;
    unsigned endOffset = textNode->length();

    if (range && node == range->startContainer(exceptionCode))
        startOffset = range->startOffset(exceptionCode);
    if (range && node == range->endContainer(exceptionCode))
        endOffset = range->endOffset(exceptionCode);
    
    RenderText *textRenderer = static_cast<RenderText *>(r);
    QString str = node->nodeValue().string();
    for (InlineTextBox *box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
        unsigned start = box->m_start;
        unsigned end = box->m_start + box->m_len;
        if (endOffset < start)
            break;
        if (startOffset <= end) {
            unsigned s = kMax(start, startOffset);
            unsigned e = kMin(end, endOffset);
            result.append(str.mid(s, e-s));
            if (e == end) {
                // now add in collapsed-away spaces if at the end of the line
                InlineTextBox *nextBox = box->nextTextBox();
                if (nextBox && box->root() != nextBox->root()) {
                    const char nonBreakingSpace = '\xa0';
                    // count the number of characters between the end of the
                    // current box and the start of the next box.
                    int collapsedStart = e;
                    int collapsedPastEnd = kMin((unsigned)nextBox->m_start, endOffset + 1);
                    bool addNextNonNBSP = true;
                    for (int i = collapsedStart; i < collapsedPastEnd; i++) {
                        if (str[i] == nonBreakingSpace) {
                            result.append(str[i]);
                            addNextNonNBSP = true;
                        }
                        else if (addNextNonNBSP) {
                            result.append(str[i]);
                            addNextNonNBSP = false;
                        }
                    }
                }
            }
        }

    }
    
    return result;
}

static QString startMarkup(const NodeImpl *node, const RangeImpl *range, EAnnotateForInterchange annotate, CSSMutableStyleDeclarationImpl *defaultStyle)
{
    unsigned short type = node->nodeType();
    switch (type) {
        case Node::TEXT_NODE: {
            if (node->parentNode()) {
                switch (node->parentNode()->id()) {
                    case ID_PRE:
                    case ID_SCRIPT:
                    case ID_STYLE:
                    case ID_TEXTAREA:
                        return stringValueForRange(node, range);
                }
            }
            QString markup = annotate ? escapeHTML(renderedText(node, range)) : escapeHTML(stringValueForRange(node, range));            
            if (defaultStyle) {
                NodeImpl *element = node->parentNode();
                if (element) {
                    CSSMutableStyleDeclarationImpl *style = Position(element, 0).computedStyle()->copyInheritableProperties();
                    style->ref();
                    defaultStyle->diff(style);
                    if (style->length() > 0) {
                        // FIXME: Handle case where style->cssText() has illegal characters in it, like "
                        QString openTag = QString("<span class=\"") + AppleStyleSpanClass + "\" style=\"" + style->cssText().string() + "\">";
                        markup = openTag + markup + "</span>";
                    }
                    style->deref();
                }            
            }
            return annotate ? convertHTMLTextToInterchangeFormat(markup) : markup;
        }
        case Node::COMMENT_NODE:
            return static_cast<const CommentImpl *>(node)->toString().string();
        case Node::DOCUMENT_NODE:
            return "";
        default: {
            QString markup = QChar('<') + node->nodeName().string();
            if (type == Node::ELEMENT_NODE) {
                const ElementImpl *el = static_cast<const ElementImpl *>(node);
                DOMString additionalStyle;
                if (defaultStyle && el->isHTMLElement()) {
                    CSSMutableStyleDeclarationImpl *style = Position(const_cast<ElementImpl *>(el), 0).computedStyle()->copyInheritableProperties();
                    style->ref();
                    defaultStyle->diff(style);
                    if (style->length() > 0) {
                        CSSMutableStyleDeclarationImpl *inlineStyleDecl = static_cast<const HTMLElementImpl *>(el)->inlineStyleDecl();
                        if (inlineStyleDecl)
                            inlineStyleDecl->diff(style);
                        additionalStyle = style->cssText();
                    }
                    style->deref();
                }
                NamedAttrMapImpl *attrs = el->attributes();
                unsigned long length = attrs->length();
                if (length == 0 && additionalStyle.length() > 0) {
                    // FIXME: Handle case where additionalStyle has illegal characters in it, like "
                    markup += " " + node->getDocument()->attrName(ATTR_STYLE).string() + "=\"" + additionalStyle.string() + "\"";
                }
                else {
                    for (unsigned int i=0; i<length; i++) {
                        AttributeImpl *attr = attrs->attributeItem(i);
                        DOMString value = attr->value();
                        if (attr->id() == ATTR_STYLE && additionalStyle.length() > 0)
                            value += "; " + additionalStyle;
                        // FIXME: Handle case where value has illegal characters in it, like "
                        markup += " " + node->getDocument()->attrName(attr->id()).string() + "=\"" + value.string() + "\"";
                    }
                }
            }
            markup += node->isHTMLElement() ? ">" : "/>";
            return markup;
        }
    }
}

static QString endMarkup(const NodeImpl *node)
{
    if ((!node->isHTMLElement() || endTagRequirement(node->id()) != FORBIDDEN) && node->nodeType() != Node::TEXT_NODE && node->nodeType() != Node::DOCUMENT_NODE) {
        return "</" + node->nodeName().string() + ">";
    }
    return "";
}

static QString markup(const NodeImpl *startNode, bool onlyIncludeChildren, bool includeSiblings, QPtrList<NodeImpl> *nodes)
{
    // Doesn't make sense to only include children and include siblings.
    ASSERT(!(onlyIncludeChildren && includeSiblings));
    QString me = "";
    for (const NodeImpl *current = startNode; current != NULL; current = includeSiblings ? current->nextSibling() : NULL) {
        if (!onlyIncludeChildren) {
            if (nodes) {
                nodes->append(current);
            }
            me += startMarkup(current, 0, DoNotAnnotateForInterchange, 0);
        }        
        if (!current->isHTMLElement() || endTagRequirement(current->id()) != FORBIDDEN) {
            // print children
            if (NodeImpl *n = current->firstChild()) {
                me += markup(n, false, true, nodes);
            }
            // Print my ending tag
            if (!onlyIncludeChildren) {
                me += endMarkup(current);
            }
        }
    }
    return me;
}

static void completeURLs(NodeImpl *node, const QString &baseURL)
{
    NodeImpl *end = node->traverseNextSibling();
    for (NodeImpl *n = node; n != end; n = n->traverseNextNode()) {
        if (n->nodeType() == Node::ELEMENT_NODE) {
            ElementImpl *e = static_cast<ElementImpl *>(n);
            NamedAttrMapImpl *attrs = e->attributes();
            unsigned long length = attrs->length();

⌨️ 快捷键说明

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