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

📄 htmlediting.h

📁 手机浏览器源码程序,功能强大
💻 H
📖 第 1 页 / 共 3 页
字号:
/*
 * 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. 
 */

#ifndef __htmlediting_h__
#define __htmlediting_h__

#include "dom_nodeimpl.h"
#include "editing/edit_actions.h"
#include "qmap.h"
#include "qptrlist.h"
#include "qvaluelist.h"
#include "selection.h"
#include "shared.h"

namespace DOM {
    class CSSMutableStyleDeclarationImpl;
    class CSSProperty;
    class CSSStyleDeclarationImpl;
    class DocumentFragmentImpl;
    class HTMLElementImpl;
    class TextImpl;
}

namespace khtml {

class EditCommand;
class Selection;
class VisiblePosition;

//------------------------------------------------------------------------------------------
// EditCommandPtr

class EditCommandPtr : public SharedPtr<EditCommand>
{
public:
    EditCommandPtr();
    EditCommandPtr(EditCommand *);
    EditCommandPtr(const EditCommandPtr &);
    ~EditCommandPtr();

    EditCommandPtr &operator=(const EditCommandPtr &);

    bool isCompositeStep() const;

    void apply() const;
    void unapply() const;
    void reapply() const;

    EditAction editingAction() const;

    DOM::DocumentImpl * const document() const;

    Selection startingSelection() const;
    Selection endingSelection() const;

    void setStartingSelection(const Selection &s) const;
    void setStartingSelection(const VisiblePosition &p) const;
    void setStartingSelection(const DOM::Position &p, EAffinity affinity) const;
    void setEndingSelection(const Selection &s) const;
    void setEndingSelection(const VisiblePosition &p) const;
    void setEndingSelection(const DOM::Position &p, EAffinity affinity) const;

    DOM::CSSMutableStyleDeclarationImpl *typingStyle() const;
    void setTypingStyle(DOM::CSSMutableStyleDeclarationImpl *) const;

    EditCommandPtr parent() const;
    void setParent(const EditCommandPtr &) const;

    bool isInsertTextCommand() const;
    bool isInsertLineBreakCommand() const;
    bool isTypingCommand() const;

    static EditCommandPtr &emptyCommand();
};

//------------------------------------------------------------------------------------------
// StyleChange

class StyleChange 
OOM_MODIFIED
{
public:
    enum ELegacyHTMLStyles { DoNotUseLegacyHTMLStyles, UseLegacyHTMLStyles };

    explicit StyleChange(DOM::CSSStyleDeclarationImpl *, ELegacyHTMLStyles usesLegacyStyles=UseLegacyHTMLStyles);
    StyleChange(DOM::CSSStyleDeclarationImpl *, const DOM::Position &, ELegacyHTMLStyles usesLegacyStyles=UseLegacyHTMLStyles);

    static ELegacyHTMLStyles styleModeForParseMode(bool);

    DOM::DOMString cssStyle() const { return m_cssStyle; }
    bool applyBold() const { return m_applyBold; }
    bool applyItalic() const { return m_applyItalic; }
    bool applyFontColor() const { return m_applyFontColor.length() > 0; }
    bool applyFontFace() const { return m_applyFontFace.length() > 0; }
    bool applyFontSize() const { return m_applyFontSize.length() > 0; }

    DOM::DOMString fontColor() { return m_applyFontColor; }
    DOM::DOMString fontFace() { return m_applyFontFace; }
    DOM::DOMString fontSize() { return m_applyFontSize; }

    bool usesLegacyStyles() const { return m_usesLegacyStyles; }

private:
    void init(DOM::CSSStyleDeclarationImpl *, const DOM::Position &);
    bool checkForLegacyHTMLStyleChange(const DOM::CSSProperty *);
    static bool currentlyHasStyle(const DOM::Position &, const DOM::CSSProperty *);
    
    DOM::DOMString m_cssStyle;
    bool m_applyBold;
    bool m_applyItalic;
    DOM::DOMString m_applyFontColor;
    DOM::DOMString m_applyFontFace;
    DOM::DOMString m_applyFontSize;
    bool m_usesLegacyStyles;
};

//------------------------------------------------------------------------------------------
// EditCommand

class EditCommand : public Shared<EditCommand>
{
public:
    EditCommand(DOM::DocumentImpl *);
    virtual ~EditCommand();

    bool isCompositeStep() const { return m_parent != 0; }
    EditCommand *parent() const { return m_parent; }
    void setParent(EditCommand *parent) { m_parent = parent; }

    enum ECommandState { NotApplied, Applied };
    
    void apply();	
    void unapply();
    void reapply();

    virtual void doApply() = 0;
    virtual void doUnapply() = 0;
    virtual void doReapply();  // calls doApply()

    virtual EditAction editingAction() const;

    virtual DOM::DocumentImpl * const document() const { return m_document; }

    Selection startingSelection() const { return m_startingSelection; }
    Selection endingSelection() const { return m_endingSelection; }

    void setEndingSelectionNeedsLayout(bool flag=true) { m_endingSelection.setNeedsLayout(flag); }
        
    ECommandState state() const { return m_state; }
    void setState(ECommandState state) { m_state = state; }

    void setStartingSelection(const Selection &s);
    void setStartingSelection(const VisiblePosition &p);
    void setStartingSelection(const DOM::Position &p, EAffinity affinity);
    void setEndingSelection(const Selection &s);
    void setEndingSelection(const VisiblePosition &p);
    void setEndingSelection(const DOM::Position &p, EAffinity affinity);

    DOM::CSSMutableStyleDeclarationImpl *typingStyle() const { return m_typingStyle; };
    void setTypingStyle(DOM::CSSMutableStyleDeclarationImpl *);
    
    DOM::CSSMutableStyleDeclarationImpl *styleAtPosition(const DOM::Position &pos);
    
    virtual bool isInsertTextCommand() const;
    virtual bool isTypingCommand() const;
    
private:
    void assignTypingStyle(DOM::CSSMutableStyleDeclarationImpl *);

    virtual bool preservesTypingStyle() const;

    DOM::DocumentImpl *m_document;
    ECommandState m_state;
    Selection m_startingSelection;
    Selection m_endingSelection;
    DOM::CSSMutableStyleDeclarationImpl *m_typingStyle;
    EditCommand *m_parent;
};

//------------------------------------------------------------------------------------------
// CompositeEditCommand

class CompositeEditCommand : public EditCommand
{
public:
    CompositeEditCommand(DOM::DocumentImpl *);
	
    virtual void doUnapply();
    virtual void doReapply();

protected:
    //
    // sugary-sweet convenience functions to help create and apply edit commands in composite commands
    //
    void appendNode(DOM::NodeImpl *appendChild, DOM::NodeImpl *parentNode);
    void applyCommandToComposite(EditCommandPtr &);
    void applyStyle(DOM::CSSStyleDeclarationImpl *style, EditAction editingAction=EditActionChangeAttributes);
    void deleteKeyPressed();
    void deleteSelection(bool smartDelete=false, bool mergeBlocksAfterDelete=true);
    void deleteSelection(const Selection &selection, bool smartDelete=false, bool mergeBlocksAfterDelete=true);
    void deleteTextFromNode(DOM::TextImpl *node, long offset, long count);
    void inputText(const DOM::DOMString &text, bool selectInsertedText = false);
    void insertNodeAfter(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
    void insertNodeAt(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild, long offset);
    void insertNodeBefore(DOM::NodeImpl *insertChild, DOM::NodeImpl *refChild);
    void insertParagraphSeparator();
    void insertTextIntoNode(DOM::TextImpl *node, long offset, const DOM::DOMString &text);
    void joinTextNodes(DOM::TextImpl *text1, DOM::TextImpl *text2);
    void rebalanceWhitespace();
    void removeCSSProperty(DOM::CSSStyleDeclarationImpl *, int property);
    void removeFullySelectedNodePreservingPosition(DOM::NodeImpl *node, DOM::Position &pos);
    void removeNodeAttribute(DOM::ElementImpl *, int attribute);
    void removeChildrenInRangePreservingPosition(DOM::NodeImpl *node, int from, int to, DOM::Position &pos);
    void removeNode(DOM::NodeImpl *removeChild);
    void removeNodePreservingPosition(DOM::NodeImpl *removeChild, DOM::Position &pos);
    void removeNodePreservingChildren(DOM::NodeImpl *node);
    void replaceTextInNode(DOM::TextImpl *node, long offset, long count, const DOM::DOMString &replacementText);
    void setNodeAttribute(DOM::ElementImpl *, int attribute, const DOM::DOMString &);
    void splitTextNode(DOM::TextImpl *text, long offset);
    void splitElement(DOM::ElementImpl *element, DOM::NodeImpl *atChild);
    void mergeIdenticalElements(DOM::ElementImpl *first, DOM::ElementImpl *second);
    void wrapContentsInDummySpan(DOM::ElementImpl *element);
    void splitTextNodeContainingElement(DOM::TextImpl *text, long offset);

    void deleteInsignificantText(DOM::TextImpl *, int start, int end);
    void deleteInsignificantText(const DOM::Position &start, const DOM::Position &end);
    void deleteInsignificantTextDownstream(const DOM::Position &);

    DOM::NodeImpl *appendBlockPlaceholder(DOM::NodeImpl *);
    DOM::NodeImpl *insertBlockPlaceholder(const DOM::Position &pos);
    DOM::NodeImpl *addBlockPlaceholderIfNeeded(DOM::NodeImpl *);
    bool removeBlockPlaceholder(DOM::NodeImpl *);
    DOM::NodeImpl *findBlockPlaceholder(DOM::NodeImpl *);

    void moveParagraphContentsToNewBlockIfNecessary(const DOM::Position &);

    QValueList<EditCommandPtr> m_cmds;
};

//==========================================================================================
// Concrete commands
//------------------------------------------------------------------------------------------
// AppendNodeCommand

class AppendNodeCommand : public EditCommand
{
public:
    AppendNodeCommand(DOM::DocumentImpl *, DOM::NodeImpl *appendChild, DOM::NodeImpl *parentNode);
    virtual ~AppendNodeCommand();

    virtual void doApply();
    virtual void doUnapply();

    DOM::NodeImpl *appendChild() const { return m_appendChild; }
    DOM::NodeImpl *parentNode() const { return m_parentNode; }

private:
    DOM::NodeImpl *m_appendChild;
    DOM::NodeImpl *m_parentNode;    
};

//------------------------------------------------------------------------------------------
// ApplyStyleCommand

class ApplyStyleCommand : public CompositeEditCommand
{
public:
    enum EPropertyLevel { PropertyDefault, ForceBlockProperties };

    ApplyStyleCommand(DOM::DocumentImpl *, DOM::CSSStyleDeclarationImpl *style, EditAction editingAction=EditActionChangeAttributes, EPropertyLevel=PropertyDefault);
    virtual ~ApplyStyleCommand();
	
    virtual void doApply();
    virtual EditAction editingAction() const;

    DOM::CSSMutableStyleDeclarationImpl *style() const { return m_style; }

private:
    // style-removal helpers
    bool isHTMLStyleNode(DOM::CSSMutableStyleDeclarationImpl *, DOM::HTMLElementImpl *);
    void removeHTMLStyleNode(DOM::HTMLElementImpl *);
    void removeHTMLFontStyle(DOM::CSSMutableStyleDeclarationImpl *, DOM::HTMLElementImpl *);
    void removeCSSStyle(DOM::CSSMutableStyleDeclarationImpl *, DOM::HTMLElementImpl *);
    void removeBlockStyle(DOM::CSSMutableStyleDeclarationImpl *, const DOM::Position &start, const DOM::Position &end);
    void removeInlineStyle(DOM::CSSMutableStyleDeclarationImpl *, const DOM::Position &start, const DOM::Position &end);
    bool nodeFullySelected(DOM::NodeImpl *, const DOM::Position &start, const DOM::Position &end) const;
    bool nodeFullyUnselected(DOM::NodeImpl *node, const DOM::Position &start, const DOM::Position &end) const;
    DOM::CSSMutableStyleDeclarationImpl *extractTextDecorationStyle(DOM::NodeImpl *node);
    DOM::CSSMutableStyleDeclarationImpl *extractAndNegateTextDecorationStyle(DOM::NodeImpl *node);
    void applyTextDecorationStyle(DOM::NodeImpl *node, DOM::CSSMutableStyleDeclarationImpl *style);
    void pushDownTextDecorationStyleAroundNode(DOM::NodeImpl *node, const DOM::Position &start, const DOM::Position &end, bool force);
    void pushDownTextDecorationStyleAtBoundaries(const DOM::Position &start, const DOM::Position &end);
    
    // style-application helpers
    void applyBlockStyle(DOM::CSSMutableStyleDeclarationImpl *);
    void applyRelativeFontStyleChange(DOM::CSSMutableStyleDeclarationImpl *);
    void applyInlineStyle(DOM::CSSMutableStyleDeclarationImpl *);
    void addBlockStyleIfNeeded(DOM::CSSMutableStyleDeclarationImpl *, DOM::NodeImpl *);
    void addInlineStyleIfNeeded(DOM::CSSMutableStyleDeclarationImpl *, DOM::NodeImpl *start, DOM::NodeImpl *end);
    bool splitTextAtStartIfNeeded(const DOM::Position &start, const DOM::Position &end);
    bool splitTextAtEndIfNeeded(const DOM::Position &start, const DOM::Position &end);
    bool splitTextElementAtStartIfNeeded(const DOM::Position &start, const DOM::Position &end);
    bool splitTextElementAtEndIfNeeded(const DOM::Position &start, const DOM::Position &end);
    bool mergeStartWithPreviousIfIdentical(const DOM::Position &start, const DOM::Position &end);
    bool mergeEndWithNextIfIdentical(const DOM::Position &start, const DOM::Position &end);
    void cleanUpEmptyStyleSpans(const DOM::Position &start, const DOM::Position &end);

⌨️ 快捷键说明

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