IE源代码摘抄,基于泄漏的IE5.0(持续更新)

时间:2023-03-09 06:51:04
IE源代码摘抄,基于泄漏的IE5.0(持续更新)

下载了一份很久以前泄漏的IE5.0的源代码,虽然已经是很古远的版本了。但是通过调试现有版本浏览器与查看源代码,发现关键部分的差距并不是很大,代码很有参考意义。这里把重要的函数、数据结构摘抄出来以备参考。

 class NOVTABLE CTreeNode : public CVoid
{
friend class CTreePos; DECLARE_CLASS_TYPES(CTreeNode, CVoid) public:
DECLARE_MEMCLEAR_NEW_DELETE(); CTreeNode(CTreeNode* pParent, CElement* pElement=NULL); // Use this to get an interface to the element/node
HRESULT GetElementInterface(REFIID riid, void** ppUnk); // NOTE: these functions may look like IUnknown functions
// but don't make that mistake. They are here to
// manage creation of the tearoff to handle all
// external references.
// These functions should not be called!
NV_DECLARE_TEAROFF_METHOD(GetInterface, getinterface, (REFIID riid, LPVOID* ppv));
NV_DECLARE_TEAROFF_METHOD_(ULONG, PutRef, putref, ());
NV_DECLARE_TEAROFF_METHOD_(ULONG, RemoveRef, removeref, ()); // These functions are to be used to keep a node/element
// combination alive while it may leave the tree.
// BEWARE: this may cause the creation of a tearoff.
ULONG NodeAddRef();
ULONG NodeRelease(); // These functions manage the _fInMarkup bit
void PrivateEnterTree();
void PrivateExitTree();
void PrivateMakeDead();
void PrivateMarkupRelease(); void SetElement(CElement* pElement);
void SetParent(CTreeNode* pNodeParent); // Element access and structure methods
CElement* Element() { return _pElement; }
CElement* SafeElement() { return this?_pElement:NULL; } CTreePos* GetBeginPos() { return &_tpBegin; }
CTreePos* GetEndPos() { return &_tpEnd; } // Context chain access
BOOL IsFirstBranch() { return _tpBegin.IsEdgeScope(); }
BOOL IsLastBranch() { return _tpEnd.IsEdgeScope(); }
CTreeNode* NextBranch();
CTreeNode* PreviousBranch(); CDocument* Doc(); BOOL IsInMarkup() { return _fInMarkup; }
BOOL IsDead() { return ! _fInMarkup; }
CRootElement* IsRoot();
CMarkup* GetMarkup();
CRootElement* MarkupRoot(); // Does the element that this node points to have currency?
BOOL HasCurrency(); BOOL IsContainer();
CTreeNode* GetContainerBranch();
CElement* GetContainer() { return GetContainerBranch()->SafeElement(); } BOOL SupportsHtml(); CTreeNode* Parent() { return _pNodeParent; } CTreeNode* Ancestor(ELEMENT_TAG etag);
CTreeNode* Ancestor(ELEMENT_TAG* arytag); CElement* ZParent() { return ZParentBranch()->SafeElement(); }
CTreeNode* ZParentBranch(); CElement* RenderParent() { return RenderParentBranch()->SafeElement(); }
CTreeNode* RenderParentBranch(); CElement* ClipParent() { return ClipParentBranch()->SafeElement(); }
CTreeNode* ClipParentBranch(); CElement* ScrollingParent() { return ScrollingParentBranch()->SafeElement(); }
CTreeNode* ScrollingParentBranch(); inline ELEMENT_TAG Tag() { return (ELEMENT_TAG)_etag; } ELEMENT_TAG TagType()
{
switch(_etag)
{
case ETAG_GENERIC_LITERAL:
case ETAG_GENERIC_BUILTIN:
return ETAG_GENERIC;
default:
return (ELEMENT_TAG)_etag;
}
} CTreeNode* GetFirstCommonAncestor(CTreeNode* pNode, CElement* pEltStop);
CTreeNode* GetFirstCommonBlockOrLayoutAncestor(CTreeNode* pNodeTwo, CElement* pEltStop);
CTreeNode* GetFirstCommonAncestorNode(CTreeNode* pNodeTwo, CElement* pEltStop); CTreeNode* SearchBranchForPureBlockElement(CFlowLayout*);
CTreeNode* SearchBranchToFlowLayoutForTag(ELEMENT_TAG etag);
CTreeNode* SearchBranchToRootForTag(ELEMENT_TAG etag);
CTreeNode* SearchBranchToRootForScope(CElement* pElementFindMe);
BOOL SearchBranchToRootForNode(CTreeNode* pNodeFindMe); CTreeNode* GetCurrentRelativeNode(CElement* pElementFL); // The layout attached to the current element may not be accurate, when a
// property changes, current element can gain/lose layoutness. When an
// element gains/loses layoutness, its layout is created/destroyed lazily.
//
// So, for the following functions "cur" means return the layout currently
// associated with the layout which may not be accurate. "Updated" means
// compute the state and return the accurate information.
//
// Note: Calling "Updated" function may cause the formats to be computed.
//
// If there is any confusion please talk to (srinib/lylec/brendand)
inline CLayout* GetCurLayout();
inline BOOL HasLayout(); CLayout* GetCurNearestLayout();
CTreeNode* GetCurNearestLayoutNode();
CElement* GetCurNearestLayoutElement(); CLayout* GetCurParentLayout();
CTreeNode* GetCurParentLayoutNode();
CElement* GetCurParentLayoutElement(); // the following get functions may create the layout if it is not
// created yet.
inline CLayout* GetUpdatedLayout(); // checks for NeedsLayout()
inline CLayout* GetUpdatedLayoutPtr(); // Call this if NeedsLayout() is already called
inline BOOL NeedsLayout(); CLayout* GetUpdatedNearestLayout();
CTreeNode* GetUpdatedNearestLayoutNode();
CElement* GetUpdatedNearestLayoutElement(); CLayout* GetUpdatedParentLayout();
CTreeNode* GetUpdatedParentLayoutNode();
CElement* GetUpdatedParentLayoutElement(); // BUGBUG - these functions should go, we should not need
// to know if the element has flowlayout.
CFlowLayout* GetFlowLayout();
CTreeNode* GetFlowLayoutNode();
CElement* GetFlowLayoutElement();
CFlowLayout* HasFlowLayout(); // Helper methods
htmlBlockAlign GetParagraphAlign(BOOL fOuter);
htmlControlAlign GetSiteAlign(); BOOL IsInlinedElement(); BOOL IsPositionStatic(void);
BOOL IsPositioned(void);
BOOL IsAbsolute(stylePosition st);
BOOL IsAbsolute(void); BOOL IsAligned(); // IsRelative() tells you if the specific element has had a CSS position
// property set on it ( by examining _fRelative and _bPositionType on the
// FF). It will NOT tell you if something is relative because one of its
// ancestors is relative; that information is stored in the CF, and can be
// had via IsInheritingRelativeness()
BOOL IsRelative(stylePosition st);
BOOL IsRelative(void);
BOOL IsInheritingRelativeness(void); BOOL IsScrollingParent(void);
BOOL IsClipParent(void);
BOOL IsZParent(void);
BOOL IsDisplayNone(void);
BOOL IsVisibilityHidden(void); // Depth is defined to be 1 plus the count of parents above this element
int Depth() const; // Format info functions
HRESULT CacheNewFormats(CFormatInfo* pCFI); void EnsureFormats();
BOOL IsCharFormatValid() { return _iCF>=; }
BOOL IsParaFormatValid() { return _iPF>=; }
BOOL IsFancyFormatValid() { return _iFF>=; }
const CCharFormat* GetCharFormat() { return (_iCF>= ? ::GetCharFormatEx(_iCF) : GetCharFormatHelper()); }
const CParaFormat* GetParaFormat() { return (_iPF>= ? ::GetParaFormatEx(_iPF) : GetParaFormatHelper()); }
const CFancyFormat* GetFancyFormat() { return (_iFF>= ? ::GetFancyFormatEx(_iFF) : GetFancyFormatHelper()); }
const CCharFormat* GetCharFormatHelper();
const CParaFormat* GetParaFormatHelper();
const CFancyFormat* GetFancyFormatHelper();
long GetCharFormatIndex() { return (_iCF>= ? _iCF : GetCharFormatIndexHelper()); }
long GetParaFormatIndex() { return (_iPF>= ? _iPF : GetParaFormatIndexHelper()); }
long GetFancyFormatIndex() { return (_iFF>= ? _iFF : GetFancyFormatIndexHelper()); }
long GetCharFormatIndexHelper();
long GetParaFormatIndexHelper();
long GetFancyFormatIndexHelper(); long GetFontHeightInTwips(CUnitValue* pCuv);
void GetRelTopLeft(CElement* pElementFL, CParentInfo* ppi, long* pxOffset, long* pyOffset); // These GetCascaded methods are taken from style.hdl where they were
// originally generated by the PDL parser.
CColorValue GetCascadedbackgroundColor();
CColorValue GetCascadedcolor();
CUnitValue GetCascadedletterSpacing();
styleTextTransform GetCascadedtextTransform();
CUnitValue GetCascadedpaddingTop();
CUnitValue GetCascadedpaddingRight();
CUnitValue GetCascadedpaddingBottom();
CUnitValue GetCascadedpaddingLeft();
CColorValue GetCascadedborderTopColor();
CColorValue GetCascadedborderRightColor();
CColorValue GetCascadedborderBottomColor();
CColorValue GetCascadedborderLeftColor();
styleBorderStyle GetCascadedborderTopStyle();
styleBorderStyle GetCascadedborderRightStyle();
styleBorderStyle GetCascadedborderBottomStyle();
styleBorderStyle GetCascadedborderLeftStyle();
CUnitValue GetCascadedborderTopWidth();
CUnitValue GetCascadedborderRightWidth();
CUnitValue GetCascadedborderBottomWidth();
CUnitValue GetCascadedborderLeftWidth();
CUnitValue GetCascadedwidth();
CUnitValue GetCascadedheight();
CUnitValue GetCascadedtop();
CUnitValue GetCascadedbottom();
CUnitValue GetCascadedleft();
CUnitValue GetCascadedright();
styleOverflow GetCascadedoverflowX();
styleOverflow GetCascadedoverflowY();
styleOverflow GetCascadedoverflow();
styleStyleFloat GetCascadedfloat();
stylePosition GetCascadedposition();
long GetCascadedzIndex();
CUnitValue GetCascadedclipTop();
CUnitValue GetCascadedclipLeft();
CUnitValue GetCascadedclipRight();
CUnitValue GetCascadedclipBottom();
BOOL GetCascadedtableLayout(); // fixed - 1, auto - 0
BOOL GetCascadedborderCollapse(); // collapse - 1, separate - 0
BOOL GetCascadedborderOverride();
WORD GetCascadedfontWeight();
WORD GetCascadedfontHeight();
CUnitValue GetCascadedbackgroundPositionX();
CUnitValue GetCascadedbackgroundPositionY();
BOOL GetCascadedbackgroundRepeatX();
BOOL GetCascadedbackgroundRepeatY();
htmlBlockAlign GetCascadedblockAlign();
styleVisibility GetCascadedvisibility();
styleDisplay GetCascadeddisplay();
BOOL GetCascadedunderline();
styleAccelerator GetCascadedaccelerator();
BOOL GetCascadedoverline();
BOOL GetCascadedstrikeOut();
CUnitValue GetCascadedlineHeight();
CUnitValue GetCascadedtextIndent();
BOOL GetCascadedsubscript();
BOOL GetCascadedsuperscript();
BOOL GetCascadedbackgroundAttachmentFixed();
styleListStyleType GetCascadedlistStyleType();
styleListStylePosition GetCascadedlistStylePosition();
long GetCascadedlistImageCookie();
const TCHAR* GetCascadedfontFaceName();
const TCHAR* GetCascadedfontFamilyName();
BOOL GetCascadedfontItalic();
long GetCascadedbackgroundImageCookie();
BOOL GetCascadedclearLeft();
BOOL GetCascadedclearRight();
styleCursor GetCascadedcursor();
styleTableLayout GetCascadedtableLayoutEnum();
styleBorderCollapse GetCascadedborderCollapseEnum();
styleDir GetCascadedBlockDirection();
styleDir GetCascadeddirection();
styleBidi GetCascadedunicodeBidi();
styleLayoutGridMode GetCascadedlayoutGridMode();
styleLayoutGridType GetCascadedlayoutGridType();
CUnitValue GetCascadedlayoutGridLine();
CUnitValue GetCascadedlayoutGridChar();
LONG GetCascadedtextAutospace();
styleWordBreak GetCascadedwordBreak();
styleLineBreak GetCascadedlineBreak();
styleTextJustify GetCascadedtextJustify();
styleTextJustifyTrim GetCascadedtextJustifyTrim();
CUnitValue GetCascadedmarginTop();
CUnitValue GetCascadedmarginRight();
CUnitValue GetCascadedmarginBottom();
CUnitValue GetCascadedmarginLeft();
CUnitValue GetCascadedtextKashida(); // Ref helpers
// Right now these just drop right through to the element
static void ReplacePtr (CTreeNode** ppNodelhs, CTreeNode* pNoderhs);
static void SetPtr (CTreeNode** ppNodelhs, CTreeNode* pNoderhs);
static void ClearPtr (CTreeNode** ppNodelhs);
static void StealPtrSet (CTreeNode** ppNodelhs, CTreeNode* pNoderhs);
static void StealPtrReplace (CTreeNode** ppNodelhs, CTreeNode* pNoderhs);
static void ReleasePtr (CTreeNode* pNode); // Other helpers
void VoidCachedInfo();
void VoidCachedNodeInfo();
void VoidFancyFormat(); // Helpers for contained CTreePos's
CTreePos* InitBeginPos(BOOL fEdge)
{
_tpBegin.SetFlags(
(_tpBegin.GetFlags()&~(CTreePos::TPF_ETYPE_MASK|CTreePos::TPF_DATA_POS|CTreePos::TPF_EDGE))
| CTreePos::NodeBeg
| BOOLFLAG(fEdge, CTreePos::TPF_EDGE));
return &_tpBegin;
} CTreePos* InitEndPos(BOOL fEdge)
{
_tpEnd.SetFlags(
(_tpEnd.GetFlags()&~(CTreePos::TPF_ETYPE_MASK|CTreePos::TPF_DATA_POS|CTreePos::TPF_EDGE))
| CTreePos::NodeEnd
| BOOLFLAG(fEdge, CTreePos::TPF_EDGE));
return &_tpEnd;
} //+-----------------------------------------------------------------------
//
// CTreeNode::CLock
//
//------------------------------------------------------------------------
class CLock
{
public:
DECLARE_MEMALLOC_NEW_DELETE()
CLock(CTreeNode* pNode);
~CLock(); private:
CTreeNode* _pNode;
}; // Lookaside pointers
enum
{
LOOKASIDE_PRIMARYTEAROFF = ,
LOOKASIDE_CURRENTSTYLE = ,
LOOKASIDE_NODE_NUMBER =
// *** There are only 2 bits reserved in the node.
// *** if you add more lookasides you have to make sure
// *** that you make room for those bits.
}; BOOL HasLookasidePtr(int iPtr) { return (_fHasLookasidePtr&(<<iPtr)); }
void* GetLookasidePtr(int iPtr);
HRESULT SetLookasidePtr(int iPtr, void* pv);
void* DelLookasidePtr(int iPtr); // Primary Tearoff pointer management
BOOL HasPrimaryTearoff() { return (HasLookasidePtr(LOOKASIDE_PRIMARYTEAROFF)); }
IUnknown* GetPrimaryTearoff() { return ((IUnknown*)GetLookasidePtr(LOOKASIDE_PRIMARYTEAROFF)); }
HRESULT SetPrimaryTearoff(IUnknown* pTearoff) { return (SetLookasidePtr(LOOKASIDE_PRIMARYTEAROFF, pTearoff)); }
IUnknown* DelPrimaryTearoff() { return ((IUnknown*)DelLookasidePtr(LOOKASIDE_PRIMARYTEAROFF)); } // Class Data
CElement* _pElement; // The element for this node
CTreeNode* _pNodeParent; // The parent in the CTreeNode tree // DWORD 1
BYTE _etag; // 0-7: element tag
BYTE _fFirstCommonAncestorNode : ; // 8: for finding common ancestor
BYTE _fInMarkup : ; // 9: this node is in a markup and shouldn't die
BYTE _fInMarkupDestruction : ; // 10: Used by CMarkup::DestroySplayTree
BYTE _fHasLookasidePtr : ; // 11-12 Lookaside flags
BYTE _fBlockNess : ; // 13: Cached from format -- valid if _iFF != -1
BYTE _fHasLayout : ; // 14: Cached from format -- valid if _iFF != -1
BYTE _fUnused : ; // 15: Unused SHORT _iPF; // 16-31: Paragraph Format // DWORD 2
SHORT _iCF; // 0-15: Char Format
SHORT _iFF; // 16-31: Fancy Format protected:
// Use GetBeginPos() or GetEndPos() to get at these members
CTreePos _tpBegin; // The begin CTreePos for this node
CTreePos _tpEnd; // The end CTreePos for this node public:
// STATIC MEMBERS
DECLARE_TEAROFF_TABLE_NAMED(s_apfnNodeVTable) private:
NO_COPY(CTreeNode);
};

class CTreeNode

 void CMarkup::FreeTreePos(CTreePos* ptp)
{
Assert(ptp); // set a sentinel to make the traversal terminate
ptp->MarkFirst();
ptp->SetNext(NULL); // release the subtree, adding its nodes to the free list
while(ptp)
{
if (ptp->FirstChild())
{
ptp = ptp->FirstChild();
}
else
{
CTreePos* ptpNext;
BOOL fRelease = TRUE;
while(fRelease)
{
fRelease = ptp->IsLastChild();
ptpNext = ptp->Next();
ReleaseTreePos(ptp);
ptp = ptpNext;
}
}
}
}

CTreePos的释放函数 CMarkup::FreeTreePos

 class CElement : public CBase
{
DECLARE_CLASS_TYPES(CElement, CBase) friend class CDBindMethods;
friend class CLayout;
friend class CFlowLayout; private:
DECLARE_MEMCLEAR_NEW_DELETE(); public:
CElement(ELEMENT_TAG etag, CDocument* pDoc);
virtual ~CElement(); CDocument* Doc() const { return GetDocPtr(); } // creating thunks with AddRef and Release set to peer holder, if present
HRESULT CreateTearOffThunk(
void* pvObject1,
const void* apfn1,
IUnknown* pUnkOuter,
void** ppvThunk,
void* appropdescsInVtblOrder=NULL); HRESULT CreateTearOffThunk(
void* pvObject1,
const void* apfn1,
IUnknown* pUnkOuter,
void** ppvThunk,
void* pvObject2,
void* apfn2,
DWORD dwMask,
const IID* const* apIID,
void* appropdescsInVtblOrder=NULL); CAttrArray** GetAttrArray() const
{
return CBase::GetAttrArray();
}
void SetAttrArray(CAttrArray* pAA)
{
CBase::SetAttrArray(pAA);
} // *********************************************
//
// ENUMERATIONS, CLASSES, & STRUCTS
//
// *********************************************
enum ELEMENTDESC_FLAG
{
ELEMENTDESC_DONTINHERITSTYLE= ( << ), // Do not inherit style from parent
ELEMENTDESC_NOANCESTORCLICK = ( << ), // We don't want our ancestors to fire clicks
ELEMENTDESC_NOTIFYENDPARSE = ( << ), // We want to be notified when we're parsed ELEMENTDESC_OLESITE = ( << ), // class derived from COleSite
ELEMENTDESC_OMREADONLY = ( << ), // element's value can not be accessed through OM (input/file)
ELEMENTDESC_ALLOWSCROLLING = ( << ), // allow scrolling
ELEMENTDESC_HASDEFDESCENT = ( << ), // use 4 pixels descent for default vertical alignment
ELEMENTDESC_BODY = ( << ), // class is used the BODY element
ELEMENTDESC_TEXTSITE = ( << ), // class derived from CTxtSite
ELEMENTDESC_ANCHOROUT = ( <<), // draw anchor border outside site/inside
ELEMENTDESC_SHOWTWS = ( <<), // show trailing whitespaces
ELEMENTDESC_XTAG = ( <<), // an xtag - derived from CXElement
ELEMENTDESC_NOOFFSETCTX = ( <<), // Shift-F10 context menu shows on top-left (not offset)
ELEMENTDESC_CARETINS_SL = ( <<), // Dont select site after inserting site
ELEMENTDESC_CARETINS_DL = ( <<), // show caret (SameLine or DifferntLine)
ELEMENTDESC_NOSELECT = ( <<), // do not select site in edit mode
ELEMENTDESC_TABLECELL = ( <<), // site is a table cell. Also implies do not
// word break before sites.
ELEMENTDESC_VPADDING = ( <<), // add a pixel vertical padding for this site
ELEMENTDESC_EXBORDRINMOV = ( <<), // Exclude the border in CSite::Move
ELEMENTDESC_DEFAULT = ( <<), // acts like a default site to receive return key
ELEMENTDESC_CANCEL = ( <<), // acts like a cancel site to receive esc key
ELEMENTDESC_NOBKGRDRECALC = ( <<), // Dis-allow background recalc
ELEMENTDESC_NOPCTRESIZE = ( <<), // Don't force resize due to percentage height/width
ELEMENTDESC_NOLAYOUT = ( <<), // element's like script and comment etc. cannot have layout
ELEMENTDESC_NEVERSCROLL = ( <<), // element can scroll
ELEMENTDESC_CANSCROLL = ( <<), // element can scroll
ELEMENTDESC_LAST = ELEMENTDESC_CANSCROLL,
ELEMENTDESC_MAX = LONG_MAX // Force enum to DWORD on Macintosh.
}; NV_DECLARE_TEAROFF_METHOD(IsEqualObject, isequalobject, (IUnknown* ppunk)); // ******************************************
//
// Virtual overrides
//
// ******************************************
virtual void Passivate(); DECLARE_PLAIN_IUNKNOWN(CElement); STDMETHOD(PrivateQueryInterface)(REFIID, void**);
STDMETHOD_(ULONG, PrivateAddRef)();
STDMETHOD_(ULONG, PrivateRelease)(); void PrivateEnterTree();
void PrivateExitTree(CMarkup* pMarkupOld); virtual HRESULT OnPropertyChange(DISPID dispid, DWORD dwFlags); virtual HRESULT GetNaturalExtent(DWORD dwExtentMode, SIZEL* psizel) { return E_FAIL; } typedef enum
{
GETINFO_ISCOMPLETED, // Has loading of an element completed
GETINFO_HISTORYCODE // Code used to validate history
} GETINFO; virtual DWORD GetInfo(GETINFO gi); DWORD HistoryCode() { return GetInfo(GETINFO_HISTORYCODE); } NV_DECLARE_TEAROFF_METHOD(get_tabIndex, GET_tabIndex, (short*)); // The dir property is declared baseimplementation in the pdl.
// We need prototype here
NV_DECLARE_TEAROFF_METHOD(put_dir, PUT_dir, (BSTR v));
NV_DECLARE_TEAROFF_METHOD(get_dir, GET_dir, (BSTR* p)); // these delegaters implement redirection to the window object
NV_DECLARE_TEAROFF_METHOD(get_onload, GET_onload, (VARIANT*));
NV_DECLARE_TEAROFF_METHOD(put_onload, PUT_onload, (VARIANT));
NV_DECLARE_TEAROFF_METHOD(get_onunload, GET_onunload, (VARIANT*));
NV_DECLARE_TEAROFF_METHOD(put_onunload, PUT_onunload, (VARIANT));
NV_DECLARE_TEAROFF_METHOD(get_onfocus, GET_onfocus, (VARIANT*));
NV_DECLARE_TEAROFF_METHOD(put_onfocus, PUT_onfocus, (VARIANT));
NV_DECLARE_TEAROFF_METHOD(get_onblur, GET_onblur, (VARIANT*));
NV_DECLARE_TEAROFF_METHOD(put_onblur, PUT_onblur, (VARIANT));
NV_DECLARE_TEAROFF_METHOD(get_onbeforeunload, GET_onbeforeunload, (VARIANT*));
NV_DECLARE_TEAROFF_METHOD(put_onbeforeunload, PUT_onbeforeunload, (VARIANT));
NV_DECLARE_TEAROFF_METHOD(get_onhelp, GET_onhelp, (VARIANT*));
NV_DECLARE_TEAROFF_METHOD(put_onhelp, PUT_onhelp, (VARIANT)); NV_DECLARE_TEAROFF_METHOD(get_onscroll, GET_onscroll, (VARIANT*));
NV_DECLARE_TEAROFF_METHOD(put_onscroll, PUT_onscroll, (VARIANT));
NV_DECLARE_TEAROFF_METHOD(get_onresize, GET_onresize, (VARIANT*));
NV_DECLARE_TEAROFF_METHOD(put_onresize, PUT_onresize, (VARIANT)); // non-abstract getters for tagName and scopeName. See element.pdl
NV_DECLARE_TEAROFF_METHOD(GettagName, gettagname, (BSTR*)); // IServiceProvider methods
NV_DECLARE_TEAROFF_METHOD(QueryService, queryservice, (REFGUID guidService, REFIID iid, LPVOID* ppv)); virtual CAtomTable* GetAtomTable(BOOL* pfExpando=NULL); // init / deinit methods
class CInit2Context
{
public:
CInit2Context(CHtmTag* pht, CMarkup* pTargetMarkup, DWORD dwFlags) :
_pTargetMarkup(pTargetMarkup), _pht(pht), _dwFlags(dwFlags)
{
} CInit2Context(CHtmTag* pht, CMarkup* pTargetMarkup) :
_pTargetMarkup(pTargetMarkup), _pht(pht), _dwFlags()
{
} CHtmTag* _pht;
CMarkup* _pTargetMarkup;
DWORD _dwFlags;
}; virtual HRESULT Init();
virtual HRESULT Init2(CInit2Context* pContext); HRESULT InitAttrBag(CHtmTag* pht);
HRESULT MergeAttrBag(CHtmTag* pht); virtual void Notify (CNotification* pnf); HRESULT EnterTree();
void ExitTree(DWORD dwExitFlags); // other
CBase* GetOmWindow(void); // Get the Base Object that owns the attr array for a given property
// Allows us to re-direct properties to another objects storage
CBase* GetBaseObjectFor(DISPID dispID); // Pass the call to the form.
//-------------------------------------------------------------------------
// +override : special process
// +call super : first
// -call parent : no
// -call children : no
//-------------------------------------------------------------------------
virtual HRESULT CloseErrorInfo(HRESULT hr); // Scrolling methods
// Scroll this element into view
virtual HRESULT ScrollIntoView(
SCROLLPIN spVert=SP_MINIMAL,
SCROLLPIN spHorz=SP_MINIMAL,
BOOL fScrollBits=TRUE); HRESULT DeferScrollIntoView(
SCROLLPIN spVert=SP_MINIMAL,
SCROLLPIN spHorz=SP_MINIMAL); NV_DECLARE_ONCALL_METHOD(DeferredScrollIntoView, deferredscrollintoview, (DWORD_PTR dwParam)); // Relative element (non-site) helper methods
virtual HTC HitTestPoint(CMessage* pMessage, CTreeNode** ppNodeElement, DWORD dwFlags); BOOL CanHandleMessage()
{
return (HasLayout())?(IsEnabled()&&IsVisible(TRUE)):(TRUE);
} // STDMETHODCALLTYPE required when passing fn through generic ptr
virtual HRESULT STDMETHODCALLTYPE HandleMessage(CMessage* pMessage); HRESULT STDMETHODCALLTYPE HandleCaptureMessage(CMessage* pMessage)
{
return HandleMessage(pMessage);
} // marka these are to be DELETED !!
BOOL DisallowSelection(); // set the state of the IME.
HRESULT SetImeState();
HRESULT ComputeExtraFormat(DISPID dispID, BOOL fInherits, CTreeNode* pTreeNode, VARIANT* pVarReturn); // DoClick() is called by click(). It is also called internally in response
// to a mouse click by user.
// DoClick() fires the click event and then calls ClickAction() if the event
// is not cancelled.
// Derived classes can override ClickAction() to provide specific functionality.
virtual HRESULT DoClick(
CMessage* pMessage=NULL,
CTreeNode* pNodeContext=NULL,
BOOL fFromLabel=FALSE);
virtual HRESULT ClickAction(CMessage* pMessage); virtual HRESULT ShowTooltip(CMessage* pmsg, POINT pt); HRESULT SetCursorStyle(LPCTSTR pstrIDC, CTreeNode* pNodeContext=NULL); void Invalidate(); // Element rect and element invalidate support
enum GERC_FLAGS
{
GERC_ONALINE = ,
GERC_CLIPPED =
}; void GetElementRegion(CDataAry<RECT>* paryRects, RECT* prcBound=NULL, DWORD dwFlags=);
HRESULT GetElementRc(RECT* prc, DWORD dwFlags, POINT* ppt=NULL); // these helper functions return in container coordinates
void GetBoundingSize(SIZE& sz);
HRESULT GetBoundingRect(CRect* pRect, DWORD dwFlags=);
HRESULT GetElementTopLeft(POINT& pt); // helper to return the actual background color
COLORREF GetInheritedBackgroundColor(CTreeNode* pNodeContext=NULL);
HRESULT GetInheritedBackgroundColorValue(CColorValue* pVal, CTreeNode* pNodeContext=NULL);
virtual HRESULT GetColors(CColorInfo* pCI);
COLORREF GetBackgroundColor()
{
CTreeNode* pNodeContext = GetFirstBranch();
CTreeNode* pNodeParent = pNodeContext->Parent() ? pNodeContext->Parent() : pNodeContext; return pNodeParent->Element()->GetInheritedBackgroundColor(pNodeParent);
} // Events related stuff
//--------------------------------------------------------------------------------------
inline BOOL ShouldFireEvents() { return _fEventListenerPresent; }
inline void SetEventsShouldFire() { _fEventListenerPresent = TRUE; }
BOOL FireCancelableEvent(DISPID dispidMethod, DISPID dispidProp, LPCTSTR pchEventType, BYTE* pbTypes, ...);
BOOL BubbleCancelableEvent(CTreeNode* pNodeContext, long lSubDivision, DISPID dispidMethod, DISPID dispidProp, LPCTSTR pchEventType, BYTE* pbTypes, ...);
HRESULT FireEventHelper(DISPID dispidMethod, DISPID dispidProp, BYTE* pbTypes, ...);
HRESULT FireEvent(DISPID dispidMethod, DISPID dispidProp, LPCTSTR pchEventType, BYTE* pbTypes, ...);
HRESULT BubbleEvent(CTreeNode* pNodeContext, long lSubDivision, DISPID dispidMethod, DISPID dispidProp, LPCTSTR pchEventType, BYTE* pbTypes, ...);
HRESULT BubbleEventHelper(CTreeNode* pNodeContext, long lSubDivision, DISPID dispidMethod, DISPID dispidProp, BOOL fRaisedByPeer, VARIANT* pvb, BYTE* pbTypes, ...);
virtual HRESULT DoSubDivisionEvents(long lSubDivision, DISPID dispidMethod, DISPID dispidProp, VARIANT* pvb, BYTE* pbTypes, ...);
HRESULT FireStdEventOnMessage(
CTreeNode* pNodeContext,
CMessage* pMessage,
CTreeNode* pNodeBeginBubbleWith=NULL,
CTreeNode* pNodeEvent=NULL);
BOOL FireStdEvent_KeyDown(CTreeNode* pNodeContext, CMessage* pMessage, int* piKeyCode, short shift);
BOOL FireStdEvent_KeyUp(CTreeNode* pNodeContext, CMessage* pMessage, int* piKeyCode, short shift);
BOOL FireStdEvent_KeyPress(CTreeNode* pNodeContext, CMessage* pMessage, int* piKeyCode);
BOOL FireStdEvent_MouseHelper(
CTreeNode* pNodeContext,
CMessage * pMessage,
DISPID dispidMethod,
DISPID dispidProp,
short button,
short shift,
float x,
float y,
CTreeNode* pNodeFrom=NULL,
CTreeNode* pNodeTo=NULL,
CTreeNode* pNodeBeginBubbleWith=NULL,
CTreeNode* pNodeEvent=NULL);
void Fire_onpropertychange(LPCTSTR strPropName);
void Fire_onscroll();
HRESULT Fire_PropertyChangeHelper(DISPID dispid, DWORD dwFlags); void STDMETHODCALLTYPE Fire_onfocus(DWORD_PTR dwContext);
void STDMETHODCALLTYPE Fire_onblur(DWORD_PTR dwContext); BOOL DragElement(
CLayout* pFlowLayout,
DWORD dwStateKey,
IUniformResourceLocator* pUrlToDrag,
long lSubDivision); BOOL Fire_ondragHelper(
long lSubDivision,
DISPID dispidEvent,
DISPID dispidProp,
LPCTSTR pchType,
DWORD* pdwDropEffect);
void Fire_ondragend(long lSubDivision, DWORD dwDropEffect); // Associated image context helpers
HRESULT GetImageUrlCookie(LPCTSTR lpszURL, long* plCtxCookie);
HRESULT AddImgCtx(DISPID dispID, LONG lCookie);
void ReleaseImageCtxts();
void DeleteImageCtx(DISPID dispid); // Internal events
HRESULT EnsureFormatCacheChange(DWORD dwFlags);
BOOL IsFormatCacheValid(); // Element Tree methods
BOOL IsAligned();
BOOL IsContainer();
BOOL IsNoScope();
BOOL IsBlockElement();
BOOL IsBlockTag();
BOOL IsOwnLineElement(CFlowLayout* pFlowLayoutContext);
BOOL IsRunOwner() { return _fOwnsRuns; }
BOOL BreaksLine();
BOOL IsTagAndBlock(ELEMENT_TAG eTag) { return Tag()==eTag&&IsBlockElement(); }
BOOL IsFlagAndBlock(TAGDESC_FLAGS flag) { return HasFlag(flag)&&IsBlockElement(); } HRESULT ClearRunCaches(DWORD dwFlags); // Get the first branch for this element
CTreeNode* GetFirstBranch() const { return __pNodeFirstBranch; }
CTreeNode* GetLastBranch();
BOOL IsOverlapped(); // Get the CTreePos extent of this element
void GetTreeExtent(CTreePos** pptpStart, CTreePos** pptpEnd); //-------------------------------------------------------------------------
//
// Layout related functions
//
//-------------------------------------------------------------------------
private:
BOOL HasLayoutLazy(); // should only be called by HasLayout
inline CLayout* GetLayoutLazy();
// Create the layout object to be associated with the current element
virtual HRESULT CreateLayout(); public:
// CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION
// CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION
// (please read the comments below)
//
// The layout attached to the current element may not be accurate, when a
// property changes, current element can gain/lose layoutness. When an
// element gains/loses layoutness, its layout is created/destroyed lazily.
//
// So, for the following functions "cur" means return the layout currently
// associated with the layout which may not be accurate. "Updated" means
// compute the state and return the accurate information.
//
// Note: Calling "Updated" function may cause the formats to be computed.
//
// If there is any confusion please talk to (srinib/lylec/brendand)
CLayout* GetCurLayout() { return GetLayoutPtr(); }
BOOL HasLayout() { return !!HasLayoutPtr(); } CLayout* GetCurNearestLayout();
CTreeNode* GetCurNearestLayoutNode();
CElement* GetCurNearestLayoutElement(); CLayout* GetCurParentLayout();
CTreeNode* GetCurParentLayoutNode();
CElement* GetCurParentLayoutElement(); // CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION
// CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION CAUTION
// (please read the comments above)
//
//
// the following get functions may create the layout if it is not
// created yet.
inline CLayout* GetUpdatedLayout(); // checks for NeedsLayout()
inline CLayout* GetUpdatedLayoutPtr(); // Call this if NeedsLayout() is already called
inline BOOL NeedsLayout(); CLayout* GetUpdatedNearestLayout();
CTreeNode* GetUpdatedNearestLayoutNode();
CElement* GetUpdatedNearestLayoutElement(); CLayout* GetUpdatedParentLayout();
CTreeNode* GetUpdatedParentLayoutNode();
CElement* GetUpdatedParentLayoutElement(); void DestroyLayout(); // this functions return GetFirstBranch()->Parent()->Ancestor(etag)->Element(); safely
// returns NULL if the element is not in the tree, or it doesn't have a parent, or no such ansectors in the tree, etc.
CElement* GetParentAncestorSafe(ELEMENT_TAG etag) const;
CElement* GetParentAncestorSafe(ELEMENT_TAG* arytag) const; // BUGBUG - these functions should go, we should not need
// to know if the element has flowlayout.
CFlowLayout* GetFlowLayout();
CTreeNode* GetFlowLayoutNode();
CElement* GetFlowLayoutElement();
CFlowLayout* HasFlowLayout(); // Notification helpers
void InvalidateElement(DWORD grfFlags=);
void MinMaxElement(DWORD grfFlags=);
void ResizeElement(DWORD grfFlags=);
void RemeasureElement(DWORD grfFlags=);
void RemeasureInParentContext(DWORD grfFlags=);
void RepositionElement(DWORD grfFlags=);
void ZChangeElement(DWORD grfFlags=, CPoint* ppt=NULL); void SendNotification(enum NOTIFYTYPE ntype, DWORD grfFlags=, void* pvData=);
void SendNotification(enum NOTIFYTYPE ntype, void* pvData)
{
SendNotification(ntype, , pvData);
}
void SendNotification(CNotification* pNF); long GetSourceIndex(void); long CompareZOrder(CElement* pElement); // Mark an element's layout (if any) dirty
void DirtyLayout(DWORD grfLayout=);
BOOL OpenView(); BOOL HasPercentBgImg(); // cp and run related helper functions
long GetFirstCp();
long GetLastCp();
long GetElementCch();
long GetFirstAndLastCp(long* pcpFirst, long* pcpLast); // get the border information related to the element
virtual DWORD GetBorderInfo(CDocInfo* pdci, CBorderInfo* pbi, BOOL fAll=FALSE); HRESULT GetRange(long* pcp, long* pcch);
HRESULT GetPlainTextInScope(CString* pstrText); virtual HRESULT Save(CStreamWriteBuff* pStreamWrBuff, BOOL fEnd);
HRESULT WriteTag(CStreamWriteBuff* pStreamWrBuff, BOOL fEnd, BOOL fForce=FALSE);
virtual HRESULT SaveAttributes(CStreamWriteBuff* pStreamWrBuff, BOOL* pfAny=NULL);
HRESULT SaveAttributes(IPropertyBag* pPropBag, BOOL fSaveBlankAttributes=TRUE);
HRESULT SaveAttribute(
CStreamWriteBuff* pStreamWrBuff,
LPTSTR pchName,
LPTSTR pchValue,
const PROPERTYDESC* pPropDesc=NULL,
CBase* pBaseObj=NULL,
BOOL fEqualSpaces=TRUE,
BOOL fAlwaysQuote=FALSE); ELEMENT_TAG Tag() const { return (ELEMENT_TAG)_etag; }
inline ELEMENT_TAG TagType() const
{
switch(_etag)
{
case ETAG_GENERIC_LITERAL:
case ETAG_GENERIC_BUILTIN:
return ETAG_GENERIC;
default:
return (ELEMENT_TAG)_etag;
}
} virtual const TCHAR* TagName();
const TCHAR* NamespaceHtml(); // Support for sub-objects created through pdl's
// CStyle & Celement implement this differently
CElement* GetElementPtr() { return this; } BOOL CanShow(); BOOL HasFlag(TAGDESC_FLAGS) const; static void ReplacePtr(CElement** pplhs, CElement* prhs);
static void ReplacePtrSub(CElement** pplhs, CElement* prhs);
static void SetPtr(CElement** pplhs, CElement* prhs);
static void ClearPtr(CElement** pplhs);
static void StealPtrSet(CElement** pplhs, CElement* prhs);
static void StealPtrReplace(CElement** pplhs, CElement* prhs);
static void ReleasePtr(CElement* pElement); // Write unknown attr set
HRESULT SaveUnknown(CStreamWriteBuff* pStreamWrBuff, BOOL* pfAny=NULL);
HRESULT SaveUnknown(IPropertyBag* pPropBag, BOOL fSaveBlankAttributes=TRUE); // Helpers
BOOL IsNamed() const { return !!_fIsNamed; } // comparison
LPCTSTR NameOrIDOfParentForm(); // Helper for name or ID
LPCTSTR GetIdentifier(void);
HRESULT GetUniqueIdentifier(CString* pcstr, BOOL fSetWhenCreated=FALSE, BOOL* pfDidCreate=NULL);
LPCTSTR GetAAname() const;
LPCTSTR GetAAsubmitname() const; // Paste helpers
enum Where
{
Inside,
Outside,
BeforeBegin,
AfterBegin,
BeforeEnd,
AfterEnd
}; HRESULT Inject(Where, BOOL fIsHtml, LPTSTR pStr, long cch); virtual HRESULT PasteClipboard() { return S_OK; } HRESULT InsertAdjacent(Where where, CElement* pElementInsert); HRESULT RemoveOuter(); // Helper to get the specified text under the element -- invokes saver.
HRESULT GetText(BSTR* pbstr, DWORD dwStm); // Another helper for databinding
HRESULT GetBstrFromElement(BOOL fHTML, BSTR* pbstr); // Collection Management helpers
NV_DECLARE_PROPERTY_METHOD(GetIDHelper, GETIDHelper, (CString* pf));
NV_DECLARE_PROPERTY_METHOD(SetIDHelper, SETIDHelper, (CString* pf));
NV_DECLARE_PROPERTY_METHOD(GetnameHelper, GETNAMEHelper, (CString* pf));
NV_DECLARE_PROPERTY_METHOD(SetnameHelper, SETNAMEHelper, (CString* pf));
LPCTSTR GetAAid() const;
void InvalidateCollection(long lIndex);
NV_STDMETHOD(removeAttribute)(BSTR strPropertyName, LONG lFlags, VARIANT_BOOL* pfSuccess);
HRESULT SetUniqueNameHelper(LPCTSTR szUniqueName);
HRESULT SetIdentifierHelper(LPCTSTR lpszValue, DISPID dspIDThis, DISPID dspOther1, DISPID dspOther2);
void OnEnterExitInvalidateCollections(BOOL);
void DoElementNameChangeCollections(void); // Clone - make a duplicate new element
//
// !! returns an element with no node!
virtual HRESULT Clone(CElement** ppElementClone, CDocument* pDoc); void ComputeHorzBorderAndPadding(
CCalcInfo* pci,
CTreeNode* pNodeContext,
CElement* pTxtSite,
LONG* pxBorderLeft,
LONG* pxPaddingLeft,
LONG* pxBorderRight,
LONG* pxPaddingRight); HRESULT SetDim(
DISPID dispID,
float fValue,
CUnitValue::UNITVALUETYPE uvt,
long lDimOf,
CAttrArray** ppAA,
BOOL fInlineStyle,
BOOL* pfChanged); virtual HRESULT ComputeFormats(CFormatInfo* pCFI, CTreeNode* pNodeTarget);
virtual HRESULT ApplyDefaultFormat(CFormatInfo* pCFI);
BOOL ElementNeedsLayout(CFormatInfo* pCFI);
BOOL DetermineBlockness(CFormatInfo* pCFI);
HRESULT ApplyInnerOuterFormats(CFormatInfo* pCFI);
CImgCtx* GetBgImgCtx(); // Access Key Handling Helper Functions
FOCUS_ITEM GetMnemonicTarget();
HRESULT HandleMnemonic(CMessage* pmsg, BOOL fDoClick, BOOL* pfYieldFailed=NULL);
HRESULT GotMnemonic(CMessage* pMessage);
HRESULT LostMnemonic(CMessage* pMessage);
BOOL MatchAccessKey(CMessage* pmsg);
HRESULT OnTabIndexChange(); // Styles
HRESULT GetStyleObject(CStyle** ppStyle);
CAttrArray* GetInLineStyleAttrArray();
CAttrArray** CreateStyleAttrArray(DISPID); BOOL HasInLineStyles(void);
BOOL HasClassOrID(void); CStyle* GetInLineStylePtr();
CStyle* GetRuntimeStylePtr(); // Helpers for abstract name properties implemented on derived elements
DECLARE_TEAROFF_METHOD(put_name, PUT_name, (BSTR v));
DECLARE_TEAROFF_METHOD(get_name, GET_name, (BSTR* p)); htmlBlockAlign GetParagraphAlign(BOOL fOuter);
htmlControlAlign GetSiteAlign(); BOOL IsInlinedElement(); BOOL IsPositionStatic();
BOOL IsPositioned();
BOOL IsAbsolute();
BOOL IsRelative();
BOOL IsInheritingRelativeness();
BOOL IsScrollingParent();
BOOL IsClipParent();
BOOL IsZParent();
BOOL IsLocked();
BOOL IsDisplayNone();
BOOL IsVisibilityHidden(); // Reset functionallity
// Returns S_OK if successful and E_NOTIMPL if not applicable
virtual HRESULT DoReset(void) { return E_NOTIMPL; } // Get control's window, does control have window?
virtual HWND GetHwnd() { return NULL; } // Take the capture.
void TakeCapture(BOOL fTake);
BOOL HasCapture(); // IMsoCommandTarget methods
HRESULT STDMETHODCALLTYPE QueryStatus(
GUID* pguidCmdGroup,
ULONG cCmds,
MSOCMD rgCmds[],
MSOCMDTEXT* pcmdtext);
HRESULT STDMETHODCALLTYPE Exec(
GUID* pguidCmdGroup,
DWORD nCmdID,
DWORD nCmdexecopt,
VARIANTARG* pvarargIn,
VARIANTARG* pvarargOut); BOOL IsEditable(BOOL fCheckContainerOnly=FALSE); HRESULT EnsureInMarkup(); // Currency / UI-Activity // Does this element (or its master) have currency?
BOOL HasCurrency(); virtual HRESULT RequestYieldCurrency(BOOL fForce); // Relinquishes currency
virtual HRESULT YieldCurrency(CElement* pElemNew); // Relinquishes UI
virtual void YieldUI(CElement* pElemNew); // Forces UI upon an element
virtual HRESULT BecomeUIActive(); BOOL NoUIActivate(); // tell us if element can be UIActivate BOOL IsFocussable(long lSubDivision);
BOOL IsTabbable(long lSubDivision); HRESULT PreBecomeCurrent(long lSubDivision, CMessage* pMessage);
HRESULT BecomeCurrentFailed(long lSubDivision, CMessage* pMessage);
HRESULT PostBecomeCurrent(CMessage* pMessage); HRESULT BecomeCurrent(
long lSubDivision,
BOOL* pfYieldFailed=NULL,
CMessage* pMessage=NULL,
BOOL fTakeFocus=FALSE); HRESULT BubbleBecomeCurrent(
long lSubDivision,
BOOL* pfYieldFailed=NULL,
CMessage* pMessage=NULL,
BOOL fTakeFocus=FALSE); CElement* GetFocusBlurFireTarget(long lSubDiv); HRESULT focusHelper(long lSubDivision); virtual HRESULT GetFocusShape(long lSubDivision, CDocInfo* pdci, CShape** ppShape); // Forces Currency and uiactivity upon an element
HRESULT BecomeCurrentAndActive(
CMessage* pmsg=NULL,
long lSubDivision=,
BOOL fTakeFocus=FALSE,
BOOL* pfYieldFailed=NULL);
HRESULT BubbleBecomeCurrentAndActive(CMessage* pmsg=NULL, BOOL fTakeFocus=FALSE); virtual HRESULT GetSubDivisionCount(long* pc);
virtual HRESULT GetSubDivisionTabs(long* pTabs, long c);
virtual HRESULT SubDivisionFromPt(POINT pt, long* plSub); // Find an element with the given set of SITE_FLAG's set
CElement* FindDefaultElem(BOOL fDefault, BOOL fFull=FALSE); // set the default element in a form or in the doc
void SetDefaultElem(BOOL fFindNew = FALSE); HRESULT GetNextSubdivision(FOCUS_DIRECTION dir, long lSubDivision, long* plSubNew); virtual BOOL IsEnabled(); virtual BOOL IsValid() { return TRUE; } BOOL IsVisible(BOOL fCheckParent);
BOOL IsParent(CElement* pElement); // Is pElement a parent of this element? virtual HRESULT GetControlInfo(CONTROLINFO* pCI) { return E_FAIL; }
virtual BOOL OnMenuEvent(int id, UINT code) { return FALSE; }
HRESULT STDMETHODCALLTYPE OnCommand(int id, HWND hwndCtrl, UINT codeNotify) { return S_OK; }
HRESULT OnContextMenu(int x, int y, int id); HRESULT OnInitMenuPopup(HMENU hmenu, int item, BOOL fSystemMenu);
HRESULT OnMenuSelect(UINT uItem, UINT fuFlags, HMENU hmenu); // Helper for translating keystrokes into commands
HRESULT PerformTA(CMessage* pMessage); CImgCtx* GetNearestBgImgCtx(); DWORD GetCommandID(LPMSG lpmsg); //+---------------------------------------------------------------------------
//
// Flag values for CElement::CLock
//
//----------------------------------------------------------------------------
enum ELEMENTLOCK_FLAG
{
ELEMENTLOCK_NONE = ,
ELEMENTLOCK_CLICK = << ,
ELEMENTLOCK_PROCESSPOSITION = << ,
ELEMENTLOCK_PROCESSADORNERS = << ,
ELEMENTLOCK_DELETE = << ,
ELEMENTLOCK_FOCUS = << ,
ELEMENTLOCK_CHANGE = << ,
ELEMENTLOCK_UPDATE = << ,
ELEMENTLOCK_SIZING = << ,
ELEMENTLOCK_COMPUTEFORMATS = << ,
ELEMENTLOCK_QUERYSTATUS = << ,
ELEMENTLOCK_BLUR = << ,
ELEMENTLOCK_RECALC = << ,
ELEMENTLOCK_BLOCKCALC = << ,
ELEMENTLOCK_ATTACHPEER = << ,
ELEMENTLOCK_PROCESSREQUESTS = << ,
ELEMENTLOCK_PROCESSMEASURE = << ,
ELEMENTLOCK_LAST = << , // don't add anymore flags, we only have 16 bits
}; //+-----------------------------------------------------------------------
//
// CElement::CLock
//
//------------------------------------------------------------------------
class CLock
{
public:
DECLARE_MEMALLOC_NEW_DELETE();
CLock(CElement* pElement, ELEMENTLOCK_FLAG enumLockFlags=ELEMENTLOCK_NONE);
~CLock(); private:
CElement* _pElement;
WORD _wLockFlags;
}; BOOL TestLock(ELEMENTLOCK_FLAG enumLockFlags) { return _wLockFlags&((WORD)enumLockFlags); } BOOL TestClassFlag(ELEMENTDESC_FLAG dwFlag) const { return ElementDesc()->_classdescBase._dwFlags&dwFlag; } inline BOOL WantEndParseNotification() { return TestClassFlag(CElement::ELEMENTDESC_NOTIFYENDPARSE); } // BUGBUG: we should have a general notification mechanism to tell what
// elements are listening to which notifications
BOOL WantTextChangeNotifications(); //+-----------------------------------------------------------------------
//
// CLASSDESC (class descriptor)
//
//------------------------------------------------------------------------
class ACCELS
{
public:
ACCELS(ACCELS* pSuper, WORD wAccels);
~ACCELS();
HRESULT EnsureResources();
HRESULT LoadAccelTable();
DWORD GetCommandID(LPMSG pmsg); ACCELS* _pSuper; BOOL _fResourcesLoaded; WORD _wAccels;
LPACCEL _pAccels;
int _cAccels;
}; struct CLASSDESC
{
CBase::CLASSDESC _classdescBase;
void* _apfnTearOff; BOOL TestFlag(ELEMENTDESC_FLAG dw) const { return (_classdescBase._dwFlags&dw)!=; } // move from CSite::CLASSDESC
ACCELS* _pAccelsDesign;
ACCELS* _pAccelsRun;
}; const CLASSDESC* ElementDesc() const
{
return (const CLASSDESC*)BaseDesc();
} public:
// Lookaside pointers
enum
{
LOOKASIDE_FILTER = ,
LOOKASIDE_DATABIND = ,
LOOKASIDE_PEER = ,
LOOKASIDE_PEERMGR = ,
LOOKASIDE_ACCESSIBLE = ,
LOOKASIDE_SLAVEMARKUP = ,
LOOKASIDE_REQUEST = ,
LOOKASIDE_ELEMENT_NUMBER = // *** There are only 7 bits reserved in the element.
// *** if you add more lookasides you have to make sure
// *** that you make room for those bits.
}; private:
BOOL HasLookasidePtr(int iPtr) { return (_fHasLookasidePtr&(<<iPtr)); }
void* GetLookasidePtr(int iPtr);
HRESULT SetLookasidePtr(int iPtr, void* pv);
void* DelLookasidePtr(int iPtr); public: BOOL HasLayoutPtr() const { return _fHasLayoutPtr; }
CLayout* GetLayoutPtr() const;
void SetLayoutPtr(CLayout* pLayout);
CLayout* DelLayoutPtr(); BOOL IsInMarkup() const { return _fHasMarkupPtr; }
BOOL HasMarkupPtr() const { return _fHasMarkupPtr; }
CMarkup* GetMarkupPtr() const;
void SetMarkupPtr(CMarkup* pMarkup);
void DelMarkupPtr(); CRootElement* IsRoot() { return Tag()==ETAG_ROOT?(CRootElement*)this:NULL; }
CMarkup* GetMarkup() const { return GetMarkupPtr(); }
BOOL IsInPrimaryMarkup() const;
BOOL IsInThisMarkup(CMarkup* pMarkup) const;
CRootElement* MarkupRoot(); CElement* MarkupMaster() const;
CMarkup* SlaveMarkup() const { return ((CElement*)this)->GetSlaveMarkupPtr(); }
CElement* FireEventWith(); CDocument* GetDocPtr() const; BOOL HasSlaveMarkupPtr() { return (HasLookasidePtr(LOOKASIDE_SLAVEMARKUP)); }
CMarkup* GetSlaveMarkupPtr() { return ((CMarkup*)GetLookasidePtr(LOOKASIDE_SLAVEMARKUP)); }
HRESULT SetSlaveMarkupPtr(CMarkup* pSlaveMarkup) { return (SetLookasidePtr(LOOKASIDE_SLAVEMARKUP, pSlaveMarkup)); }
CMarkup* DelSlaveMarkupPtr() { return ((CMarkup*)DelLookasidePtr(LOOKASIDE_SLAVEMARKUP)); } BOOL HasRequestPtr() { return (HasLookasidePtr(LOOKASIDE_REQUEST)); }
CRequest* GetRequestPtr() { return ((CRequest*)GetLookasidePtr(LOOKASIDE_REQUEST)); }
HRESULT SetRequestPtr(CRequest* pRequest) { return (SetLookasidePtr(LOOKASIDE_REQUEST, pRequest)); }
CRequest* DelRequestPtr() { return ((CRequest*)DelLookasidePtr(LOOKASIDE_REQUEST)); } long GetReadyState();
virtual void OnReadyStateChange(); // The element is the head of a linked list of important structures. If the element has layout,
// then the __pvChain member points to that layout. If not and if the element is in a tree then
// then the __pvChain member points to the ped that it is in. Otherwise __pvChain points to the
// document.
private:
void* __pvChain; public:
CTreeNode* __pNodeFirstBranch; // First DWORD of bits
ELEMENT_TAG _etag : ; // 0- 7 element tag
unsigned _fHasLookasidePtr : ; // 8-14 TRUE if lookaside table has pointer
unsigned _fIsNamed : ; // 15 set if element has a name or ID attribute
unsigned _wLockFlags :; // 16-31 Element lock flags for preventing recursion // Second DWORD of bits
//
// Note that the _fMark1 and _fMark2 bits are only safe to use in routines which can *guarantee*
// their processing will not be interrupted. If there is a chance that a message loop can cause other,
// unrelated code, to execute, these bits could get reset before the original caller is finished.
unsigned _fHasMarkupPtr : ; // 0 TRUE if element has a Markup pointer
unsigned _fHasLayoutPtr : ; // 1 TRUE if element has layout ptr
unsigned _fHasPendingFilterTask : ; // 2 TRUE if there is a pending filter task (see EnsureView)
unsigned _fHasPendingRecalcTask : ; // 3 TRUE if there is a pending recalc task (see EnsureView)
unsigned _fLayoutAlwaysValid : ; // 4 TRUE if element is a site or never has layout
unsigned _fOwnsRuns : ; // 5 TRUE if element owns the runs underneath it
unsigned _fInheritFF : ; // 6 TRUE if element to inherit site and fancy format
unsigned _fBreakOnEmpty : ; // 7 this element breaks a line even is it own no text
unsigned _fUnused2 : ; // 8-11
unsigned _fDefinitelyNoBorders : ; // 12 There are no borders on this element
unsigned _fHasTabIndex : ; // 13 Has a tabindex associated with this element. Look in doc _aryTabIndexInfo
unsigned _fHasImage : ; // 14 has at least one image context
unsigned _fResizeOnImageChange : ; // 15 need to force resize when image changes
unsigned _fExplicitEndTag : ; // 16 element had a close tag (for P)
unsigned _fSynthesized : ; // 17 FALSE (default) if user created, TRUE if synthesized
unsigned _fUnused3 : ; // 18 Unused bit
unsigned _fActsLikeButton : ; // 19 does element act like a push button?
unsigned _fEditAtBrowse : ; // 20 to TestClassFlag(SITEDESC_EDITATBROWSE) in init
unsigned _fSite : ; // 21 element with layout by default
unsigned _fDefault : ; // 22 Is this the default "ok" button/control
unsigned _fCancel : ; // 23 Is this the default "cancel" button/control
unsigned _fHasPendingEvent : ; // 24 A posted event for element is pending
unsigned _fEventListenerPresent : ; // 25 Someone has asked for a connection point/ or set an event handler
unsigned _fHasFilterCollectionPtr : ; // 26 FilterCollectionPtr has been added to _pAA
unsigned _fExittreePending : ; // 27 There is a pending Exittree notification for this element
unsigned _fFirstCommonAncestor : ; // 28 Used in GetFirstCommonAncestor - don't touch!
unsigned _fMark1 : ; // 29 Random mark
unsigned _fMark2 : ; // 30 Another random mark
unsigned _fHasStyleExpressions : ; // 31 There are style expressions on this element // STATIC DATA // Default property page list for elements that don't have their own.
// This gives them the allpage by default.
static ACCELS s_AccelsElementDesign;
static ACCELS s_AccelsElementRun; // Style methods
#include "../gen/style.hdl" // IHTMLElement methods
#define _CElement_
#include "../gen/element.hdl" DECLARE_TEAROFF_TABLE(IServiceProvider) private:
NO_COPY(CElement);
};

元素的基类 CElement

 ULONG CBase::SubRelease()
{
#ifdef _DEBUG
ULONG ulAllRefs = _ulAllRefs;
#endif
if(--_ulAllRefs == )
{
_ulAllRefs = ULREF_IN_DESTRUCTOR;
_ulRefs = ULREF_IN_DESTRUCTOR;
delete this;
}
#ifdef _DEBUG
return ulAllRefs-;
#else
return ;
#endif
}

CElement的最终释放函数 CBase::SubRelease

ULONG CBase::PrivateRelease()
{
ULONG ulRefs = --_ulRefs;
if(ulRefs == )
{
_ulRefs = ULREF_IN_DESTRUCTOR;
Passivate();
Assert("Unexpected refcnt on return from CBase::Passivate" && _ulRefs==ULREF_IN_DESTRUCTOR);
_ulRefs = ;
SubRelease();
} return ulRefs;
}

CBase::SubRelease的上层函数 CBase::PrivateRelease

 class CMarkup : public CBase
{
friend class CTxtPtr;
friend class CTreePos;
friend class CMarkupPointer; DECLARE_CLASS_TYPES(CMarkup, CBase) public:
DECLARE_TEAROFF_TABLE(ISelectionRenderingServices)
DECLARE_TEAROFF_TABLE(IMarkupContainer) DECLARE_MEMCLEAR_NEW_DELETE() CMarkup(CDocument* pDoc, CElement* pElementMaster=NULL);
~CMarkup(); HRESULT Init(CRootElement* pElementRoot); HRESULT CreateInitialMarkup(CRootElement* pElementRoot); HRESULT UnloadContents(BOOL fForPassivate=FALSE); HRESULT DestroySplayTree(BOOL fReinit); void Passivate(); HRESULT CreateElement(
ELEMENT_TAG etag,
CElement** ppElementNew); #define _CMarkup_
#include "../gen/markup.hdl" // Document props\methods:
NV_DECLARE_TEAROFF_METHOD(get_Script, GET_Script, (IDispatch** p));
NV_DECLARE_TEAROFF_METHOD(get_all, GET_all, (IHTMLElementCollection** p));
NV_DECLARE_TEAROFF_METHOD(get_body, GET_body, (IHTMLElement** p));
NV_DECLARE_TEAROFF_METHOD(get_activeElement, GET_activeElement, (IHTMLElement** p));
NV_DECLARE_TEAROFF_METHOD(put_title, PUT_title, (BSTR v));
NV_DECLARE_TEAROFF_METHOD(get_title, GET_title, (BSTR* p));
NV_DECLARE_TEAROFF_METHOD(get_readyState, GET_readyState, (BSTR* p));
NV_DECLARE_TEAROFF_METHOD(put_expando, PUT_expando, (VARIANT_BOOL v));
NV_DECLARE_TEAROFF_METHOD(get_expando, GET_expando, (VARIANT_BOOL* p));
NV_DECLARE_TEAROFF_METHOD(get_parentWindow, GET_parentWindow, (IHTMLWindow2** p));
NV_DECLARE_TEAROFF_METHOD(get_nameProp, GET_nameProp, (BSTR* p));
NV_DECLARE_TEAROFF_METHOD_(HRESULT, queryCommandSupported, querycommandsupported, (BSTR cmdID,VARIANT_BOOL* pfRet));
NV_DECLARE_TEAROFF_METHOD_(HRESULT, queryCommandEnabled, querycommandenabled, (BSTR cmdID,VARIANT_BOOL* pfRet));
NV_DECLARE_TEAROFF_METHOD_(HRESULT, queryCommandState, querycommandstate, (BSTR cmdID,VARIANT_BOOL* pfRet));
NV_DECLARE_TEAROFF_METHOD_(HRESULT, queryCommandIndeterm, querycommandindeterm, (BSTR cmdID,VARIANT_BOOL* pfRet));
NV_DECLARE_TEAROFF_METHOD_(HRESULT, queryCommandText, querycommandtext, (BSTR cmdID,BSTR* pcmdText));
NV_DECLARE_TEAROFF_METHOD_(HRESULT, queryCommandValue, querycommandvalue, (BSTR cmdID,VARIANT* pcmdValue));
NV_DECLARE_TEAROFF_METHOD_(HRESULT, execCommand, execcommand, (BSTR cmdID,VARIANT_BOOL showUI,VARIANT value,VARIANT_BOOL* pfRet));
NV_DECLARE_TEAROFF_METHOD_(HRESULT, execCommandShowHelp, execcommandshowhelp, (BSTR cmdID,VARIANT_BOOL* pfRet));
NV_DECLARE_TEAROFF_METHOD_(HRESULT, createElement, createelement, (BSTR eTag,IHTMLElement** newElem));
NV_DECLARE_TEAROFF_METHOD_(HRESULT, elementFromPoint, elementfrompoint, (long x,long y,IHTMLElement** elementHit));
NV_DECLARE_TEAROFF_METHOD_(HRESULT, toString, tostring, (BSTR* String));
NV_DECLARE_TEAROFF_METHOD_(HRESULT, releaseCapture, releasecapture, ());
NV_DECLARE_TEAROFF_METHOD(get_documentElement, GET_documentelement, (IHTMLElement**pRootElem));
NV_DECLARE_TEAROFF_METHOD(get_uniqueID, GET_uniqueID, (BSTR* p));
NV_DECLARE_TEAROFF_METHOD_(HRESULT, attachEvent, attachevent, (BSTR event,IDispatch* pDisp,VARIANT_BOOL* pfResult));
NV_DECLARE_TEAROFF_METHOD_(HRESULT, detachEvent, detachevent, (BSTR event,IDispatch* pDisp));
NV_DECLARE_TEAROFF_METHOD(get_bgColor, GET_bgColor, (VARIANT* p));
NV_DECLARE_TEAROFF_METHOD(put_bgColor, PUT_bgColor, (VARIANT p));
NV_DECLARE_TEAROFF_METHOD(get_fgColor, GET_fgColor, (VARIANT* p));
NV_DECLARE_TEAROFF_METHOD(put_fgColor, PUT_fgColor, (VARIANT p));
NV_DECLARE_TEAROFF_METHOD(get_linkColor, GET_linkColor, (VARIANT* p));
NV_DECLARE_TEAROFF_METHOD(put_linkColor, PUT_linkColor, (VARIANT p));
NV_DECLARE_TEAROFF_METHOD(get_alinkColor, GET_alinkColor, (VARIANT* p));
NV_DECLARE_TEAROFF_METHOD(put_alinkColor, PUT_alinkColor, (VARIANT p));
NV_DECLARE_TEAROFF_METHOD(get_vlinkColor, GET_vlinkColor, (VARIANT* p));
NV_DECLARE_TEAROFF_METHOD(put_vlinkColor, PUT_vlinkColor, (VARIANT p));
NV_DECLARE_TEAROFF_METHOD(get_parentDocument, GET_parentDocument, (IHTMLDocument2** p));
NV_DECLARE_TEAROFF_METHOD(put_enableDownload, PUT_enableDownload, (VARIANT_BOOL v));
NV_DECLARE_TEAROFF_METHOD(get_enableDownload, GET_enableDownload, (VARIANT_BOOL* p));
NV_DECLARE_TEAROFF_METHOD(put_baseUrl, PUT_baseUrl, (BSTR v));
NV_DECLARE_TEAROFF_METHOD(get_baseUrl, GET_baseUrl, (BSTR* p));
NV_DECLARE_TEAROFF_METHOD(put_inheritStyleSheets, PUT_inheritStyleSheets, (VARIANT_BOOL v));
NV_DECLARE_TEAROFF_METHOD(get_inheritStyleSheets, GET_inheritStyleSheets, (VARIANT_BOOL* p));
NV_DECLARE_TEAROFF_METHOD(getElementsByName, getelementsbyname, (BSTR v, IHTMLElementCollection** p));
NV_DECLARE_TEAROFF_METHOD(getElementsByTagName, getelementsbytagname, (BSTR v, IHTMLElementCollection** p));
NV_DECLARE_TEAROFF_METHOD(getElementById, getelementbyid, (BSTR v, IHTMLElement** p)); // IServiceProvider
STDMETHOD(QueryService)(REFGUID guidService, REFIID riid, void** ppv); // Data Access
CDocument* Doc() { return _pDoc; }
CRootElement* Root() { return _pElementRoot; } BOOL HasCollectionCache() { return HasLookasidePtr(LOOKASIDE_COLLECTIONCACHE); }
CCollectionCache* CollectionCache() { return (CCollectionCache*)GetLookasidePtr(LOOKASIDE_COLLECTIONCACHE); }
CCollectionCache* DelCollectionCache() { return (CCollectionCache*)DelLookasidePtr(LOOKASIDE_COLLECTIONCACHE); }
HRESULT SetCollectionCache(CCollectionCache* pCollectionCache) { return SetLookasidePtr(LOOKASIDE_COLLECTIONCACHE, pCollectionCache); } BOOL HasParentMarkup() { return HasLookasidePtr(LOOKASIDE_PARENTMARKUP); }
CMarkup* ParentMarkup() { return (CMarkup*)GetLookasidePtr(LOOKASIDE_PARENTMARKUP); }
CMarkup* DelParentMarkup() { return (CMarkup*)DelLookasidePtr(LOOKASIDE_PARENTMARKUP); }
HRESULT SetParentMarkup(CMarkup* pMarkup) { return SetLookasidePtr(LOOKASIDE_PARENTMARKUP, pMarkup); } CElement* Master() { return _pElementMaster; }
void ClearMaster() { _pElementMaster = NULL; } CProgSink* GetProgSinkC();
IProgSink* GetProgSink(); CElement* FirstElement(); // Remove 'Assert(Master())', once the root element is gone and these functions
// become meaningful for non-slave markups as well.
long GetContentFirstCp() { Assert(Master()); return ; }
long GetContentLastCp() { Assert(Master()); return GetTextLength()-; }
long GetContentTextLength() { Assert(Master()); return GetTextLength()-; }
void GetContentTreeExtent(CTreePos** pptpStart, CTreePos** pptpEnd); BOOL GetAutoWordSel() const { return TRUE; } BOOL GetOverstrike() const { return _fOverstrike; }
void SetOverstrike(BOOL fSet) { _fOverstrike = (fSet) ? : ;} BOOL GetLoaded() const { return _fLoaded; }
void SetLoaded(BOOL fLoaded) { _fLoaded = fLoaded; } void SetStreaming(BOOL flag) { _fStreaming = (flag) ? : ; }
BOOL IsStreaming() const { return _fStreaming; } // BUGBUG: need to figure this function out...
BOOL IsEditable(BOOL fCheckContainerOnly=FALSE) const; // Top element cache
void EnsureTopElems();
CElement* GetElementTop();
CElement* GetElementClient() { EnsureTopElems(); return HasTopElemCache()?GetTopElemCache()->__pElementClientCached:NULL; } // Other helpers
BOOL IsPrimaryMarkup() { return this==Doc()->_pPrimaryMarkup; }
long GetTextLength() { return _TxtArray._cchText; } // GetRunOwner is an abomination that should be eliminated -- or at least moved off of the markup
CLayout* GetRunOwner(CTreeNode* pNode, CLayout* pLayoutParent=NULL);
CTreeNode* GetRunOwnerBranch(CTreeNode*, CLayout* pLayoutParent=NULL); // Markup manipulation functions
void CompactStory() { _TxtArray.ShrinkBlocks(); } HRESULT RemoveElementInternal(
CElement* pElementRemove,
DWORD dwFlags=NULL); HRESULT InsertElementInternal(
CElement* pElementInsertThis,
CTreePosGap* ptpgBegin,
CTreePosGap* ptpgEnd,
DWORD dwFlags=NULL); HRESULT SpliceTreeInternal(
CTreePosGap* ptpgStartSource,
CTreePosGap* ptpgEndSource,
CMarkup* pMarkupTarget =NULL,
CTreePosGap* ptpgTarget=NULL,
BOOL fRemove=TRUE,
DWORD dwFlags=NULL); HRESULT InsertTextInternal(
CTreePos* ptpAfterInsert,
const TCHAR* pch,
long cch,
DWORD dwFlags=NULL); HRESULT FastElemTextSet(
CElement* pElem,
const TCHAR* psz,
int cch,
BOOL fAsciiOnly); // Undo only operations
HRESULT UndoRemoveSplice(
CMarkupPointer* pmpBegin,
CSpliceRecordList* paryRegion,
long cchRemove,
TCHAR* pchRemove,
long cchNodeReinsert,
DWORD dwFlags); // Markup operation helpers
HRESULT ReparentDirectChildren(
CTreeNode* pNodeParentNew,
CTreePosGap* ptpgStart=NULL,
CTreePosGap* ptpgEnd=NULL); HRESULT CreateInclusion(
CTreeNode* pNodeStop,
CTreePosGap* ptpgLocation,
CTreePosGap* ptpgInclusion,
long* pcchNeeded=NULL,
CTreeNode* pNodeAboveLocation=NULL,
BOOL fFullReparent=TRUE,
CTreeNode** ppNodeLastAdded=NULL); HRESULT CloseInclusion(CTreePosGap* ptpgMiddle, long* pcchRemove=NULL); HRESULT RangeAffected(CTreePos* ptpStart, CTreePos* ptpFinish);
HRESULT ClearCaches(CTreePos* ptpStart, CTreePos* ptpFinish);
HRESULT ClearRunCaches(DWORD dwFlags, CElement* pElement); // Markup pointers
HRESULT EmbedPointers() { return _pmpFirst?DoEmbedPointers():S_OK; } HRESULT DoEmbedPointers(); BOOL HasUnembeddedPointers() { return !!_pmpFirst; } // TextID manipulation // Give a unique text id to every text chunk in
// the range given
HRESULT SetTextID(CTreePosGap* ptpgStart, CTreePosGap* ptpgEnd, long* plNewTextID); // Get text ID for text to right
// -1 --> no text to right
// 0 --> no assigned TextID
long GetTextID(CTreePosGap* ptpg); // Starting with ptpgStart, look for
// the extent of lTextID
HRESULT FindTextID(long lTextID, CTreePosGap* ptpgStart, CTreePosGap* ptpgEnd); // If text to the left of ptpLeft has
// the same ID as text to the right of
// ptpRight, give the right fragment a
// new ID
void SplitTextID(CTreePos* ptpLeft, CTreePos* ptpRight); // Splay Tree Primitives
CTreePos* NewTextPos(long cch, SCRIPT_ID sid=sidAsciiLatin, long lTextID=);
CTreePos* NewPointerPos(CMarkupPointer* pPointer, BOOL fRight, BOOL fStick); typedef CTreePos SUBLIST;
HRESULT Append(CTreePos* ptp);
HRESULT Insert(CTreePos* ptpNew, CTreePosGap* ptpgInsert);
HRESULT Insert(CTreePos* ptpNew, CTreePos* ptpInsert, BOOL fBefore);
HRESULT Move(CTreePos* ptpMove, CTreePosGap* ptpgDest);
HRESULT Move(CTreePos* ptpMove, CTreePos* ptpDest, BOOL fBefore);
HRESULT Remove(CTreePos* ptpStart, CTreePos* ptpFinish);
HRESULT Remove(CTreePos* ptp) { return Remove(ptp, ptp); }
HRESULT Split(CTreePos* ptpSplit, long cchLeft, SCRIPT_ID sidNew=sidNil);
HRESULT Join(CTreePos* ptpJoin);
HRESULT ReplaceTreePos(CTreePos* ptpOld, CTreePos* ptpNew);
HRESULT MergeText(CTreePos* ptpMerge);
HRESULT SetTextPosID(CTreePos** pptpText, long lTextID);
HRESULT RemovePointerPos(CTreePos* ptp, CTreePos** pptpUpdate, long* pichUpdate); HRESULT SpliceOut(CTreePos* ptpStart, CTreePos* ptpFinish, SUBLIST* pSublistSplice);
HRESULT SpliceIn(SUBLIST* pSublistSplice, CTreePos* ptpSplice);
HRESULT InsertPosChain(CTreePos* ptpChainHead, CTreePos* ptpChainTail, CTreePos* ptpInsertBefore); // splay tree search routines
CTreePos* FirstTreePos() const;
CTreePos* LastTreePos() const;
CTreePos* TreePosAtCp(long cp, long* pcchOffset) const;
CTreePos* TreePosAtSourceIndex(long iSourceIndex); // General splay information
long NumElems() const { return _tpRoot.GetElemLeft(); }
long Cch() const { return _tpRoot._cchLeft; }
long CchInRange(CTreePos* ptpFirst, CTreePos* ptpLast); // Force a splay
void FocusAt(CTreePos* ptp) { ptp->Splay(); } // splay tree primitive helpers
protected:
CTreePos* AllocData1Pos();
CTreePos* AllocData2Pos();
void FreeTreePos(CTreePos* ptp);
void ReleaseTreePos(CTreePos* ptp, BOOL fLastRelease=FALSE);
BOOL ShouldSplay(long cDepth) const;
HRESULT MergeTextHelper(CTreePos* ptpMerge); public:
// Text Story
LONG GetTextLength() const { return _TxtArray._cchText; } // Notifications
void Notify(CNotification* pnf);
void Notify(CNotification& rnf) { Notify(&rnf); } // notification helpers
protected:
void SendNotification(CNotification* pnf, CDataAry<CNotification>* paryNotification);
BOOL ElementWantsNotification(CElement* pElement, CNotification* pnf); void NotifyElement(CElement* pElement, CNotification* pnf);
void NotifyAncestors(CNotification* pnf);
void NotifyDescendents(CNotification* pnf);
void NotifyTreeLevel(CNotification* pnf); public:
// Branch searching functions - I'm sure some of these aren't needed
//
// Note: All of these (except InStory versions) implicitly stop searching at a FlowLayout
CTreeNode* FindMyListContainer(CTreeNode* pNodeStartHere);
CTreeNode* SearchBranchForChildOfScope(CTreeNode* pNodeStartHere, CElement* pElementFindChildOfMyScope);
CTreeNode* SearchBranchForChildOfScopeInStory(CTreeNode* pNodeStartHere, CElement* pElementFindChildOfMyScope);
CTreeNode* SearchBranchForScopeInStory(CTreeNode* pNodeStartHere, CElement* pElementFindMyScope);
CTreeNode* SearchBranchForScope(CTreeNode* pNodeStartHere, CElement* pElementFindMyScope);
CTreeNode* SearchBranchForNode(CTreeNode* pNodeStartHere, CTreeNode* brFindMe);
CTreeNode* SearchBranchForNodeInStory(CTreeNode* pNodeStartHere, CTreeNode* brFindMe);
CTreeNode* SearchBranchForTag(CTreeNode* pNodeStartHere, ELEMENT_TAG);
CTreeNode* SearchBranchForTagInStory(CTreeNode* pNodeStartHere, ELEMENT_TAG);
CTreeNode* SearchBranchForBlockElement(CTreeNode* pNodeStartHere, CFlowLayout* pFLContext=NULL);
CTreeNode* SearchBranchForNonBlockElement(CTreeNode* pNodeStartHere, CFlowLayout* pFLContext=NULL);
CTreeNode* SearchBranchForAnchor(CTreeNode* pNodeStartHere);
CTreeNode* SearchBranchForCriteria(CTreeNode* pNodeStartHere, BOOL (*pfnSearchCriteria)(CTreeNode*));
CTreeNode* SearchBranchForCriteriaInStory(CTreeNode* pNodeStartHere, BOOL (*pfnSearchCriteria)(CTreeNode*)); void EnsureFormats(); // Markup TextFrag services
// Markup TextFrags are used to store arbitrary string data in the markup. Mostly
// this is used to persist and edit conditional comment tags
CMarkupTextFragContext* EnsureTextFragContext(); BOOL HasTextFragContext() { return HasLookasidePtr(LOOKASIDE_TEXTFRAGCONTEXT); }
CMarkupTextFragContext* GetTextFragContext() { return (CMarkupTextFragContext*)GetLookasidePtr(LOOKASIDE_TEXTFRAGCONTEXT); }
HRESULT SetTextFragContext(CMarkupTextFragContext* ptfc) { return SetLookasidePtr(LOOKASIDE_TEXTFRAGCONTEXT, ptfc); }
CMarkupTextFragContext* DelTextFragContext() { return (CMarkupTextFragContext*)DelLookasidePtr(LOOKASIDE_TEXTFRAGCONTEXT); } // Stores the cached values for the client element
CMarkupTopElemCache* EnsureTopElemCache(); BOOL HasTopElemCache() { return HasLookasidePtr(LOOKASIDE_TOPELEMCACHE); }
CMarkupTopElemCache* GetTopElemCache() { return (CMarkupTopElemCache*)GetLookasidePtr(LOOKASIDE_TOPELEMCACHE); }
HRESULT SetTopElemCache(CMarkupTopElemCache* ptec) { return SetLookasidePtr(LOOKASIDE_TOPELEMCACHE, ptec); }
CMarkupTopElemCache* DelTopElemCache() { return (CMarkupTopElemCache*)DelLookasidePtr(LOOKASIDE_TOPELEMCACHE); } // Selection Methods
VOID GetSelectionChunksForLayout(CFlowLayout* pFlowLayout, CPtrAry<HighlightSegment*>* paryHighlight, int* piCpMin, int* piCpMax);
HRESULT EnsureSelRenSvc();
VOID HideSelection();
VOID ShowSelection();
VOID InvalidateSelection(BOOL fFireOM); // Collections support
enum
{
ELEMENT_COLLECTION = ,
FORMS_COLLECTION,
ANCHORS_COLLECTION,
LINKS_COLLECTION,
IMAGES_COLLECTION,
APPLETS_COLLECTION,
SCRIPTS_COLLECTION,
WINDOW_COLLECTION,
EMBEDS_COLLECTION,
REGION_COLLECTION,
LABEL_COLLECTION,
NAVDOCUMENT_COLLECTION,
FRAMES_COLLECTION,
NUM_DOCUMENT_COLLECTIONS
};
// DISPID range for FRAMES_COLLECTION
enum
{
FRAME_COLLECTION_MIN_DISPID = ((DISPID_COLLECTION_MIN+DISPID_COLLECTION_MAX)*)/+,
FRAME_COLLECTION_MAX_DISPID = DISPID_COLLECTION_MAX
}; HRESULT EnsureCollectionCache(long lCollectionIndex);
HRESULT AddToCollections(CElement* pElement, CCollectionBuildContext* pWalk); HRESULT InitCollections(void); NV_DECLARE_ENSURE_METHOD(EnsureCollections, ensurecollections, (long lIndex, long* plCollectionVersion));
HRESULT GetCollection(int iIndex, IHTMLElementCollection** ppdisp);
HRESULT GetElementByNameOrID(LPTSTR szName, CElement** ppElement);
HRESULT GetDispByNameOrID(LPTSTR szName, IDispatch** ppDisp, BOOL fAlwaysCollection=FALSE); CTreeNode* InFormCollection(CTreeNode* pNode); // Lookaside pointers
enum
{
LOOKASIDE_COLLECTIONCACHE = ,
LOOKASIDE_PARENTMARKUP = ,
LOOKASIDE_BEHAVIORCONTEXT = ,
LOOKASIDE_TEXTFRAGCONTEXT = ,
LOOKASIDE_TOPELEMCACHE = ,
LOOKASIDE_STYLESHEETS = ,
LOOKASIDE_TEXTRANGE = ,
LOOKASIDE_MARKUP_NUMBER =
}; BOOL HasLookasidePtr(int iPtr) { return (_fHasLookasidePtr&(<<iPtr)); }
void* GetLookasidePtr(int iPtr);
HRESULT SetLookasidePtr(int iPtr, void* pv);
void* DelLookasidePtr(int iPtr); void ClearLookasidePtrs(); // IUnknown
DECLARE_PLAIN_IUNKNOWN(CMarkup);
STDMETHOD(PrivateQueryInterface)(REFIID, void**); // ISegmentList
NV_DECLARE_TEAROFF_METHOD(MovePointersToSegment, movepointerstosegment, (
int iSegmentIndex, IMarkupPointer* pStart, IMarkupPointer* pEnd));
NV_DECLARE_TEAROFF_METHOD(GetSegmentCount, getsegmentcount, (
int* piSegmentCount, SELECTION_TYPE* peType)); // ISelectionRenderingServices
NV_DECLARE_TEAROFF_METHOD(AddSegment, addsegment, (
IMarkupPointer* pStart, IMarkupPointer* pEnd, HIGHLIGHT_TYPE HighlightType, int* iSegmentIndex));
NV_DECLARE_TEAROFF_METHOD(AddElementSegment, addelementsegment, (
IHTMLElement* pElement, int* iSegmentIndex));
NV_DECLARE_TEAROFF_METHOD(MoveSegmentToPointers, movesegmenttopointers, (
int iSegmentIndex, IMarkupPointer* pStart, IMarkupPointer* pEnd, HIGHLIGHT_TYPE HighlightType));
NV_DECLARE_TEAROFF_METHOD(GetElementSegment, getelementsegment, (
int iSegmentIndex, IHTMLElement** ppElement));
NV_DECLARE_TEAROFF_METHOD(SetElementSegment, setelementsegment, (
int iSegmentIndex, IHTMLElement* pElement));
NV_DECLARE_TEAROFF_METHOD(ClearSegment, clearsegment, (
int iSegmentIndex, BOOL fInvalidate));
NV_DECLARE_TEAROFF_METHOD(ClearSegments, clearsegments, (BOOL fInvalidate));
NV_DECLARE_TEAROFF_METHOD(ClearElementSegments, clearelementsegments, ()); // IMarkupContainer methods
NV_DECLARE_TEAROFF_METHOD(OwningDoc, owningdoc, (
IHTMLDocument2** ppDoc)); // Ref counting helpers
static void ReplacePtr(CMarkup** pplhs, CMarkup* prhs);
static void SetPtr(CMarkup** pplhs, CMarkup* prhs);
static void ClearPtr(CMarkup** pplhs);
static void StealPtrSet(CMarkup** pplhs, CMarkup* prhs);
static void StealPtrReplace(CMarkup** pplhs, CMarkup* prhs);
static void ReleasePtr(CMarkup* pMarkup); // CMarkup::CLock
class CLock
{
public:
CLock(CMarkup* pMarkup);
~CLock(); private:
CMarkup* _pMarkup;
}; protected:
static const CLASSDESC s_classdesc;
virtual const CBase::CLASSDESC* GetClassDesc() const { return &s_classdesc; } // Data
public:
CProgSink* _pProgSink; CDocument* _pDoc; // The following are similar to the CDoc's equivalent, but pertain to this
// markup alone.
long GetMarkupTreeVersion() { return __lMarkupTreeVersion; }
long GetMarkupContentsVersion() { return __lMarkupContentsVersion; } // Do NOT modify these version numbers unless the document structure
// or content is being modified.
//
// In particular, incrementing these to get a cache to rebuild is
// BAD because it causes all sorts of other stuff to rebuilt.
long __lMarkupTreeVersion; // Element structure
long __lMarkupContentsVersion; // Any content void UpdateMarkupTreeVersion()
{
CDocument* pDoc = Doc(); __lMarkupTreeVersion++;
__lMarkupContentsVersion++; pDoc->__lDocTreeVersion++;
pDoc->__lDocContentsVersion++;
} void UpdateMarkupContentsVersion()
{
__lMarkupContentsVersion++;
Doc()->UpdateDocContentsVersion();
} private:
CRootElement* _pElementRoot;
CElement* _pElementMaster; // Story data
CTxtArray _TxtArray; long _lTopElemsVersion; // Selection state
CSelectionRenderingServiceProvider* _pSelRenSvcProvider; // Object to Delegate to. // Notification data
DECLARE_CDataAry(CAryANotify, CNotification)
CAryANotify _aryANotification; private:
// This is the list of pointers positioned in this markup
// which do not have an embedding.
CMarkupPointer* _pmpFirst; // Splay Tree Data
CTreePos _tpRoot; // dummy root node
CTreePos* _ptpFirst; // cached first (leftmost) node
void* _pvPool; // list of pool blocks (so they can be freed)
CTreeDataPos* _ptdpFree; // head of free list
BYTE _abPoolInitial[sizeof(void*)+TREEDATA1SIZE*INITIAL_TREEPOS_POOL_SIZE]; // The initial pool of TreePos objects public:
struct
{
DWORD _fOverstrike : ; // 1 Overstrike mode vs insert mode
DWORD _fLoaded : ; // 3 Is the markup completely parsed
DWORD _fNoUndoInfo : ; // 4 Don't store any undo info for this markup
DWORD _fIncrementalAlloc : ; // 5 The text array should slow start
DWORD _fStreaming : ; // 6 True during parsing
DWORD _fUnstable : ; // 7 the tree is unstable because of the tree services/DOM operations
// were performed on the tree and nobody call to validate the tree
DWORD _fInSendAncestor : ; // 8 Notification - We're sending something to ancestors
DWORD _fUnused1 : ; // 9
DWORD _fEnableDownload : ; // 10 Allows content to be downloaded in this markup
DWORD _fPad : ; // 11-15 Padding to align lookaside flags on byte
DWORD _fHasLookasidePtr : ; // 16-23 Lookaside flags
DWORD _fUnused2 : ; // 24-31
}; // Style sheets moved from CDocument
HRESULT EnsureStyleSheets();
HRESULT ApplyStyleSheets(
CStyleInfo* pStyleInfo,
ApplyPassType passType=APPLY_All,
BOOL* pfContainsImportant=NULL); BOOL HasStyleSheets()
{
return FALSE;
} private:
NO_COPY(CMarkup);
};

代表DOM树的结构 CMarkup类

 class CTreePos
{
friend class CMarkup;
friend class CTreePosGap;
friend class CTreeNode;
friend class CSpliceTreeEngine;
friend class CMarkupUndoUnit; public:
DECLARE_MEMALLOC_NEW_DELETE(); // TreePos come in various flavors:
// Uninit this node is uninitialized
// Node marks begin or end of a CTreeNode's scope
// Text holds a bunch of text (formerly known as CElementRun)
// Pointer implements an IMarkupPointer
// Be sure the bit field _eType (below) is big enough for all the flavors
enum EType { Uninit=0x0, NodeBeg=0x1, NodeEnd=0x2, Text=0x4, Pointer=0x8 }; // cast to CTreeDataPos
CTreeDataPos* DataThis();
const CTreeDataPos* DataThis() const; // accessors
EType Type() const { return (EType)(GetFlags()&TPF_ETYPE_MASK); }
void SetType(EType etype) { Assert(etype <= Pointer); SetFlags((GetFlags()&~TPF_ETYPE_MASK)|(etype)); }
BOOL IsUninit() const { return !TestFlag(NodeBeg|NodeEnd|Text|Pointer); }
BOOL IsNode() const { return TestFlag(NodeBeg|NodeEnd); }
BOOL IsText() const { return TestFlag(Text); }
BOOL IsPointer() const { return TestFlag(Pointer); }
BOOL IsDataPos() const { return TestFlag(TPF_DATA_POS); }
BOOL IsData2Pos() const { Assert(!IsNode()); return TestFlag(TPF_DATA2_POS); }
BOOL IsBeginNode() const { return TestFlag(NodeBeg); }
BOOL IsEndNode() const { return TestFlag(NodeEnd); }
BOOL IsEdgeScope() const { Assert(IsNode()); return TestFlag(TPF_EDGE); }
BOOL IsBeginElementScope() const { return IsBeginNode()&&IsEdgeScope(); }
BOOL IsEndElementScope() const { return IsEndNode()&&IsEdgeScope(); }
BOOL IsBeginElementScope(CElement* pElem);
BOOL IsEndElementScope(CElement* pElem); CMarkup* GetMarkup();
BOOL IsInMarkup(CMarkup* pMarkup) { return GetMarkup()==pMarkup; } // The following are logical comparison operations (two pos are equal
// when separated by only pointers or empty text positions).
int InternalCompare(CTreePos* ptpThat); CTreeNode* Branch() const; // Only valid to call on NodePoses
CTreeNode* GetBranch() const; // Can be called on any pos, may be expensive CMarkupPointer* MarkupPointer() const;
void SetMarkupPointer(CMarkupPointer*); // GetInterNode finds the node with direct influence
// over the position directly after this CTreePos.
CTreeNode* GetInterNode() const; long Cch() const;
long Sid() const; BOOL HasTextID() const { return IsText()&&TestFlag(TPF_DATA2_POS); }
long TextID() const; long GetCElements() const { return IsBeginElementScope()?:; }
long SourceIndex(); long GetCch() const { return IsNode()?:IsText()?Cch():; } long GetCp(); int Gravity() const;
void SetGravity(BOOL fRight);
int Cling() const;
void SetCling(BOOL fStick); // modifiers
void SetScopeFlags(BOOL fEdge);
void ChangeCch(long cchDelta); // navigation
CTreePos* NextTreePos();
CTreePos* PreviousTreePos(); CTreePos* NextNonPtrTreePos();
CTreePos* PreviousNonPtrTreePos(); static BOOL IsLegalPosition(CTreePos* ptpLeft, CTreePos* ptpRight);
BOOL IsLegalPosition(BOOL fBefore)
{
return fBefore?IsLegalPosition(PreviousTreePos(), this):IsLegalPosition(this, NextTreePos());
} protected:
void InitSublist();
CTreePos* Parent() const;
CTreePos* LeftChild() const;
CTreePos* RightChild() const;
CTreePos* LeftmostDescendant() const;
CTreePos* RightmostDescendant() const;
void GetChildren(CTreePos** ppLeft, CTreePos** ppRight) const;
HRESULT Remove();
void Splay();
void RotateUp(CTreePos* p, CTreePos* g);
void ReplaceChild(CTreePos* pOld, CTreePos* pNew);
void RemoveChild(CTreePos* pOld);
void ReplaceOrRemoveChild(CTreePos* pOld, CTreePos* pNew); // constructors (for use only by CMarkup and CTreeNode)
CTreePos() {} private:
// distributed order-statistic fields
DWORD _cElemLeftAndFlags; // number of elements that begin in my left subtree
DWORD _cchLeft; // number of characters in my left subtree
// structure fields (to maintain the splay tree)
CTreePos* _pFirstChild; // pointer to my leftmost child 第一个孩子(有可能是左,也有可能是右)
CTreePos* _pNext; // pointer to right sibling or parent 右兄弟或者父亲 enum
{
TPF_ETYPE_MASK = 0x0F,
TPF_LEFT_CHILD = 0x10,
TPF_LAST_CHILD = 0x20,
TPF_EDGE = 0x40,
TPF_DATA2_POS = 0x40,
TPF_DATA_POS = 0x80,
TPF_FLAGS_MASK = 0xFF,
TPF_FLAGS_SHIFT =
}; DWORD GetFlags() const { return (_cElemLeftAndFlags); }
void SetFlags(DWORD dwFlags) { _cElemLeftAndFlags = dwFlags; }
BOOL TestFlag(DWORD dwFlag) const { return (!!(GetFlags()&dwFlag)); }
void SetFlag(DWORD dwFlag) { SetFlags(GetFlags()|dwFlag); }
void ClearFlag(DWORD dwFlag) { SetFlags(GetFlags()&~(dwFlag)); } long GetElemLeft() const { return ((long)(_cElemLeftAndFlags>>TPF_FLAGS_SHIFT)); }
void SetElemLeft(DWORD cElem) { _cElemLeftAndFlags = (_cElemLeftAndFlags&TPF_FLAGS_MASK)|(DWORD)(cElem<<TPF_FLAGS_SHIFT); }
void AdjElemLeft(long cDelta) { _cElemLeftAndFlags += cDelta << TPF_FLAGS_SHIFT; }
BOOL IsLeftChild() const { return (TestFlag(TPF_LEFT_CHILD)); } // 确保当前位置左右信息
BOOL IsLastChild() const { return (TestFlag(TPF_LAST_CHILD)); } // 确保是否有下一个兄弟 左/右 Next表示什么 在左边的时候如何判断Next表示什么呢?这时候就需要IsLastChild判断有兄弟没
void MarkLeft() { SetFlag(TPF_LEFT_CHILD); }
void MarkRight() { ClearFlag(TPF_LEFT_CHILD); }
void MarkLeft(BOOL fLeft) { SetFlags((GetFlags()&~TPF_LEFT_CHILD)|BOOLFLAG(fLeft, TPF_LEFT_CHILD)); }
void MarkFirst() { ClearFlag(TPF_LAST_CHILD); }
void MarkLast() { SetFlag(TPF_LAST_CHILD); }
void MarkLast(BOOL fLast) { SetFlags((GetFlags()&~TPF_LAST_CHILD)|BOOLFLAG(fLast, TPF_LAST_CHILD)); } void SetFirstChild(CTreePos* ptp) { _pFirstChild = ptp; }
void SetNext(CTreePos* ptp) { _pNext = ptp; }
CTreePos* FirstChild() const { return (_pFirstChild); }
CTreePos* Next() const { return (_pNext); } // support for CTreePosGap
CTreeNode* SearchBranchForElement(CElement* pElement, BOOL fLeft); // count encapsulation
enum ECountFlags { TP_LEFT=0x1, TP_DIRECT=0x2, TP_BOTH=0x3 }; struct SCounts
{
DWORD _cch;
DWORD _cElem;
void Clear();
void Increase(const CTreePos* ptp); // TP_DIRECT is implied
BOOL IsNonzero();
}; void ClearCounts();
void IncreaseCounts(const CTreePos* ptp, unsigned fFlags);
void IncreaseCounts(const SCounts* pCounts );
void DecreaseCounts(const CTreePos* ptp, unsigned fFlags);
BOOL HasNonzeroCounts(unsigned fFlags); BOOL LogicallyEqual(CTreePos* ptpRight); public:
NO_COPY(CTreePos);
};

CTreePos类

 class CTreeDataPos : public CTreePos
{
friend class CTreePos;
friend class CMarkup;
friend class CMarkupUndoUnit; public:
DECLARE_MEMALLOC_NEW_DELETE() protected:
union
{
DATAPOSTEXT t;
DATAPOSPOINTER p;
}; private:
CTreeDataPos() {}
NO_COPY(CTreeDataPos);
};

class CTreeDataPos

 class CMarkupPointer : public CBase, public IMarkupPointer
{
DECLARE_CLASS_TYPES(CMarkupPointer, CBase); friend class CDocument; // for implementation of "OrSlave" versions of Left, Right, MoveToContainer on IHTMLViewServices
friend class CMarkup; public:
DECLARE_MEMALLOC_NEW_DELETE() CMarkupPointer(CDocument* pDoc)
: _pDoc(pDoc), _pMarkup(NULL), _pmpNext(NULL), _pmpPrev(NULL),
_fRightGravity(FALSE), _fCling(FALSE), _fEmbedded(FALSE), _fKeepMarkupAlive(FALSE),
_fAlwaysEmbed(FALSE), _ptpRef(NULL), _ichRef(), _cpCache(-), _verCp()
{} virtual ~CMarkupPointer()
{
Unposition();
Assert(!Markup());
} //////////////////////////////////////////////
// CBase methods
DECLARE_PLAIN_IUNKNOWN(CMarkupPointer);
DECLARE_PRIVATE_QI_FUNCS(CBase); virtual const CBase::CLASSDESC* GetClassDesc() const; ///////////////////////////////////////////////
// IMarkupPointer methods
STDMETHODIMP OwningDoc(IHTMLDocument2** ppDoc);
STDMETHODIMP Gravity(POINTER_GRAVITY* peGravity);
STDMETHODIMP SetGravity(POINTER_GRAVITY eGravity);
STDMETHODIMP Cling(BOOL* pfCling);
STDMETHODIMP SetCling(BOOL fCling);
STDMETHODIMP MoveAdjacentToElement(IHTMLElement* pElement, ELEMENT_ADJACENCY eAdj);
STDMETHODIMP MoveToPointer(IMarkupPointer* pPointer);
STDMETHODIMP MoveToContainer(IMarkupContainer* pContainer, BOOL fAtStart);
STDMETHODIMP Unposition();
STDMETHODIMP IsPositioned(BOOL*);
STDMETHODIMP GetContainer(IMarkupContainer**); STDMETHODIMP Left(
BOOL fMove,
MARKUP_CONTEXT_TYPE* pContext,
IHTMLElement** ppElement,
long* pcch,
OLECHAR* pchText); STDMETHODIMP Right(
BOOL fMove,
MARKUP_CONTEXT_TYPE* pContext,
IHTMLElement** ppElement,
long* pcch,
OLECHAR* pchText); STDMETHODIMP MoveUnit(MOVEUNIT_ACTION muAction); STDMETHODIMP CurrentScope(IHTMLElement** ppElemCurrent); STDMETHODIMP FindText(
OLECHAR* pchFindText,
DWORD dwFlags,
IMarkupPointer* pIEndMatch=NULL,
IMarkupPointer* pIEndSearch=NULL); STDMETHODIMP IsLeftOf (IMarkupPointer* pPointer, BOOL* pfResult);
STDMETHODIMP IsLeftOfOrEqualTo (IMarkupPointer* pPointer, BOOL* pfResult);
STDMETHODIMP IsRightOf (IMarkupPointer* pPointer, BOOL* pfResult);
STDMETHODIMP IsRightOfOrEqualTo (IMarkupPointer* pPointer, BOOL* pfResult);
STDMETHODIMP IsEqualTo (IMarkupPointer* pPointerThat, BOOL* pfAreEqual); HRESULT FindTextIdentity(long textID, CMarkupPointer* pPointerOtherEnd);
HRESULT SetTextIdentity(CMarkupPointer* pPointerOtherEnd, long* plNewTextID); HRESULT IsInsideURL(IMarkupPointer* pRight, BOOL* pfResult); ///////////////////////////////////////////////
// CMarkupPointer methodse
HRESULT Left(
BOOL fMove,
MARKUP_CONTEXT_TYPE* pContext,
CTreeNode** ppNode,
long* pcch,
OLECHAR* pchText,
long* plTextID)
{
return There(TRUE, fMove, pContext, ppNode, pcch, pchText, plTextID, );
} HRESULT Right(
BOOL fMove,
MARKUP_CONTEXT_TYPE* pContext,
CTreeNode** ppNode,
long* pcch,
OLECHAR* pchText,
long* plTextID)
{
return There(FALSE, fMove, pContext, ppNode, pcch, pchText, plTextID, );
} int Gravity() const { return _fRightGravity; }
BOOL Cling() const { return _fCling; }
BOOL KeepMarkupAlive() const { return _fKeepMarkupAlive; }
void SetKeepMarkupAlive(BOOL fKeepAlive);
BOOL AlwaysEmbed() const { return _fAlwaysEmbed; }
void SetAlwaysEmbed(BOOL fAlwaysEmbed); HRESULT MoveAdjacentToElement(CElement* pElement, ELEMENT_ADJACENCY adj);
HRESULT MoveToPointer(CMarkupPointer* pPointer);
HRESULT MoveToContainer(CMarkup* pContainer, BOOL fAtStart, DWORD dwFlags=); HRESULT MoveToGap(CTreePosGap* ptpg, CMarkup* pMarkup, BOOL fForceEmbedding=FALSE); HRESULT MoveToReference(CTreePos* ptp, long ich, CMarkup* pMarkup, long cpNew); HRESULT MoveToOrphan(CTreePos*); CTreeNode* CurrentScope(DWORD dwFlags=); BOOL FindText(
TCHAR* pstr,
DWORD dwFlags,
CMarkupPointer* pEndMatch,
CMarkupPointer* pEndSearch); BOOL IsEqualTo (CMarkupPointer* pPointerThat);
BOOL IsLeftOf (CMarkupPointer* pPointerThat);
BOOL IsLeftOfOrEqualTo (CMarkupPointer* pPointerThat);
BOOL IsRightOf (CMarkupPointer* pPointerThat);
BOOL IsRightOfOrEqualTo (CMarkupPointer* pPointerThat); HRESULT MoveToCp(long cp, CMarkup* pMarkup); HRESULT QueryBreaks(DWORD* pdwBreaks); // public helpers // called from CTreePos when it goes away
void OnPositionReleased(); CDocument* Doc() const { return _pDoc; } CTreeNode* Branch() { return _pMarkup?_ptp->GetInterNode():NULL; } BOOL IsPositioned() const { return _pMarkup!=NULL; } CMarkup* Markup() const { return _pMarkup; } void SetMarkup(CMarkup* pMarkup); // Get the embedded treepos. Be careful, pointers are not always
// embedded.
CTreePos* GetEmbeddedTreePos()
{
Assert(_fEmbedded);
return _fEmbedded?_ptpEmbeddedPointer:NULL;
} // GetNormalizedReference returns a ptp/ich pair which is
// immediately after REAL content. Not real content is
// pointers and empty text runs.
CTreePos* GetNormalizedReference(long& ich) const; // Returns the cp for this pointer. -1 if unpositioned;
long GetCp(); // "There" does the work of both Left and Right
HRESULT There(
BOOL fLeft,
BOOL fMove,
MARKUP_CONTEXT_TYPE* pContext,
CTreeNode** ppNode, // Not AddRefed
long* pcch,
OLECHAR* pchText,
long* plTextID,
DWORD* dwFlags); HRESULT There(
BOOL fLeft,
BOOL fMove,
MARKUP_CONTEXT_TYPE* pContext,
IHTMLElement** ppElement,
long* pcch,
OLECHAR* pchText,
DWORD* dwFlags); private:
HRESULT UnEmbed(CTreePos** pptp, long* pich); HRESULT Embed(CMarkup* pMarkup, CTreePos* ptp, long ich, long cpNew); // representation
static const CBase::CLASSDESC s_classdesc; // classDesc (for CBase) CDocument* _pDoc; // The doc that owns me // The _pMarkup member points the markup I'm positioned in,
// when I'm positioned. If it is NULL, then I'm not positioned
// in any markup, and thus the members which indicate where
// are unused.
CMarkup* _pMarkup; // Each markup has a list of markup pointers which are in the markup, but
// do not have a pointer pos.
CMarkupPointer* _pmpNext;
CMarkupPointer* _pmpPrev; void AddMeToList();
void RemoveMeFromList(); // The members _fRightGravity and _fCling always indicate the state of
// gravity and cling, even when we are embedded, when the pointer pos
// has redundant indicators of this. They are redundant because we want
// gravity and cling with out CMarkupPointer.
//
// The _fEmbedded member is used when _pMarkup is non-NULL to indicate
// if our position is indicated by an embedded pointer pos or a reference
// to a non-pointer pos / offset pair.
unsigned _fRightGravity : ; // When unpositioned, gravity is stored here
unsigned _fCling : ; // When unpositioned, cling is stored here
unsigned _fEmbedded : ; // Do I have have a pointer pos in the splay tree?
unsigned _fKeepMarkupAlive : ; // Keep addref on markup
unsigned _fAlwaysEmbed : ; // Always embed this pointer // The _cpCache member records the cp this pointer is currently at. If
// the contents version of the markup matches that stored here, then
// _cpCache is up to date.
long _cpCache;
long _verCp; long GetCpSlow() const;
BOOL CpIsCached() const; void Validate() const {} union
{
CTreePos* _ptp; // Quick access to ptp if embedded or not CTreePos* _ptpEmbeddedPointer; // When embeded, this points to Pointer pos struct // When not embedded, this says where I am
{
CTreePos* _ptpRef; // I live just after this (non-pointer) pos
long _ichRef; // If text pos, this many chars into it
};
}; NO_COPY(CMarkupPointer);
};

class CMarkupPointer