/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ // // Editor save stuff. LWT 06/01/95 // #ifdef EDITOR #ifndef _EDITOR_H #define _EDITOR_H #include "edttypep.h" // include first so types are mapped. // // Turn on new DT mapping code // #define EDT_DDT 1 #if defined(JAVA) #define EDITOR_JAVA #endif // // Many of the system header files have C++ specific stuff in // them. If we just widely extern "C" {} the lot, we will lose. // So.. pre-include some that must be seen by C++. // #if defined(HPUX) || defined(SCO_SV) #include "math.h" #endif /*HPUX losing headers */ extern "C" { #include "net.h" //#include "glhist.h" //#include "shist.h" #include "merrors.h" #include "xp.h" #include "pa_parse.h" #include "layout.h" #include "edt.h" #include "pa_tags.h" #include "xpassert.h" #include "xp_file.h" #include "libmocha.h" #include "libi18n.h" } #include "bits.h" #include "garray.h" #include "streams.h" #include "gui.h" // For textFE test, hardts #include "xlate.h" #include "fsfile.h" #include "shist.h" #ifdef XP_WIN32 #include #endif // XP Strings extern "C" { #include "xpgetstr.h" #define WANT_ENUM_STRING_IDS #include "allxpstr.h" #undef WANT_ENUM_STRING_IDS } // Defining DEBUG_AUTO_SAVE will make the document AutoSave every six seconds. //#define DEBUG_AUTO_SAVE // Test if ele #ifdef USE_SCRIPT #define ED_IS_NOT_SCRIPT(pEle) (0 == (pEle->Text()->m_tf & (TF_SERVER | TF_SCRIPT | TF_STYLE))) #else #define ED_IS_NOT_SCRIPT(pEle) (TRUE) #endif #define EDT_SELECTION_START_COMMENT "selection start" #define EDT_SELECTION_END_COMMENT "selection end" // TRY / CATCH / RETHROW macros for minimal error recovery on macs #if defined(XP_MAC) #define EDT_TRY try #define EDT_CATCH_ALL catch(...) #define EDT_RETHROW throw #else #define EDT_TRY if(1) #define EDT_CATCH_ALL else #define EDT_RETHROW #endif #ifdef XP_MAC // taken from pa_amp.h #define NON_BREAKING_SPACE ((char)007) #define NON_BREAKING_SPACE_STRING "\07" #else #define NON_BREAKING_SPACE ((char)160) #define NON_BREAKING_SPACE_STRING "\xa0" #endif #define DEF_FONTSIZE 3 #define DEFAULT_HR_THICKNESS 2 #define EDT_IS_LIVEWIRE_MACRO(s) ( (s) && (s)[0] == '`' ) // Macros for the public entry points. // usage: // GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) ; // For no return value // GET_EDIT_BUF_OR_RETURN(pContext, pEditBuffer) return-value; // to return a return value #define GET_WRITABLE_EDIT_BUF_OR_RETURN(CONTEXT, BUFFER) CEditBuffer* BUFFER = LO_GetEDBuffer( CONTEXT );\ if (!CEditBuffer::IsAlive(BUFFER) || !BUFFER->IsReady() || !BUFFER->IsWritable() ) return #define GET_EDIT_BUF_OR_RETURN(CONTEXT, BUFFER) CEditBuffer* BUFFER = LO_GetEDBuffer( CONTEXT );\ if (!CEditBuffer::IsAlive(BUFFER) || !BUFFER->IsReady() ) return #define GET_EDIT_BUF_OR_RETURN_READY_OR_NOT(CONTEXT, BUFFER) CEditBuffer* BUFFER = LO_GetEDBuffer( CONTEXT );\ if (!CEditBuffer::IsAlive(BUFFER) ) return #define GET_WRITABLE_EDIT_BUF_OR_RETURN_READY_OR_NOT(CONTEXT, BUFFER) CEditBuffer* BUFFER = LO_GetEDBuffer( CONTEXT );\ if (!CEditBuffer::IsAlive(BUFFER) || !BUFFER->IsWritable() ) return //----------------------------------------------------------------------------- // Edit Classes //----------------------------------------------------------------------------- class CEditElement; class CEditLeafElement; class CEditSubDocElement; class CEditTableElement; class CEditTableRowElement; class CEditCaptionElement; class CEditTableCellElement; class CEditRootDocElement; class CEditContainerElement; class CEditListElement; class CEditTextElement; class CEditImageElement; class CEditHorizRuleElement; class CEditIconElement; class CEditEndElement; class CEditBreakElement; class CEditTargetElement; class CEditLayerElement; class CEditDivisionElement; class CParseState; class CPrintState; class CEditImageLoader; class CEditSaveObject; class CFileSaveObject; struct ED_Link; class CEditCommand; class CEditCommandGroup; class CEditSaveData; class CEditSaveToTempData; #ifdef DEBUG class CEditTestManager; #endif #ifdef EDITOR_JAVA // Opaque interface to Editor Plugin support classes. // (It's too expensive to pull jri in in this header file. // If we do, bsdi runs out of VM while compiling. typedef void* EditorPluginManager; EditorPluginManager EditorPluginManager_new(MWContext* pContext); void EditorPluginManager_delete(EditorPluginManager a); XP_Bool EditorPluginManager_IsPluginActive(EditorPluginManager a); XP_Bool EditorPluginManager_PluginsExist(); class CEditorPluginInterface; #endif // Originally this was a sugared int32, but we ran into // trouble working with big-endian architectures, like the // Macintosh. So rather than being even cleverer with // macros, I decided to make it a regular class. // If this turns out to be a performance bottleneck // we can always inline it.... jhp class ED_Color { public: ED_Color(); ED_Color(LO_Color& pLoColor); ED_Color(int32 rgb); ED_Color(int r, int g, int b); ED_Color(LO_Color* pLoColor); XP_Bool IsDefined(); XP_Bool operator==(const ED_Color& other) const; XP_Bool operator!=(const ED_Color& other) const; int Red(); int Green(); int Blue(); LO_Color GetLOColor(); long GetAsLong(); // 0xRRGGBB void SetUndefined(); static ED_Color GetUndefined(); private: LO_Color m_color; XP_Bool m_bDefined; }; // Copies the argument into a static buffer, and then upper-cases the // buffer, and returns a pointer to the buffer. You don't own the // result pointer, and you can't call twice in same line of code. char* EDT_UpperCase(char*); // Returns a string for the given alignment. Uses a static buffer, so // don't call twice in the same line of code. char* EDT_AlignString(ED_Alignment align); // Backwards-compatable macros. Should clean this up some day. #define EDT_COLOR_DEFAULT (ED_Color()) #define EDT_RED(x) ((x).Red()) #define EDT_GREEN(x) ((x).Green()) #define EDT_BLUE(x) ((x).Blue()) #define EDT_RGB(r,g,b) (ED_Color(r,g,b)) #define EDT_LO_COLOR(pLoColor) ED_Color(pLoColor) /* Gives us quick access to first cell in each column or row * with location and index data */ struct _EDT_CellLayoutData { int32 X; /* X value of cell */ int32 Y; /* Y value of cell */ int32 iColumn; /* Geometric column index */ int32 iRow; /* Geometric row index */ int32 iCellsInColumn; /* Total number of cells in each column */ int32 iCellsInRow; /* and row */ LO_Element *pLoCell; /* Layout element pointer */ CEditTableCellElement *pEdCell; /* Corresponding edit element object */ }; typedef struct _EDT_CellLayoutData EDT_CellLayoutData; // Editor selections // template declarations Declare_GrowableArray(int32,int32) // TXP_GrowableArray_int32 Declare_GrowableArray(ED_Link,ED_Link*) // TXP_GrowableArray_ED_Link Declare_GrowableArray(EDT_MetaData,EDT_MetaData*) // TXP_GrowableArray_EDT_MetaData Declare_GrowableArray(pChar,char*) // TXP_GrowableArray_pChar Declare_GrowableArray(CEditCommand,CEditCommand*) // TXP_GrowableArray_CEditCommand #ifdef EDITOR_JAVA Declare_GrowableArray(CEditorPluginInterface,CEditorPluginInterface*) // TXP_GrowableArray_CEditorPluginInterface #endif //cmanske - store lists of selected cell elements Declare_GrowableArray(CEditTableCellElement,CEditTableCellElement*) // TXP_GrowableArray_CEditTableCellElement Declare_GrowableArray(LO_CellStruct,LO_CellStruct*) // TXP_GrowableArray_LO_CellStruct //List of tables encountered during Relayout() Declare_GrowableArray(LO_TableStruct,LO_TableStruct*) // TXP_GrowableArray_LO_TableStruct Declare_GrowableArray(EDT_CellLayoutData, EDT_CellLayoutData*) // TXP_GrowableArray_EDT_CellLayoutData Declare_PtrStack(ED_Alignment,ED_Alignment) // TXP_PtrStack_ED_Alignment Declare_PtrStack(TagType,TagType) // TXP_PtrStack_TagType Declare_PtrStack(CEditTextElement,CEditTextElement*) // TXP_PtrStack_CEditTextElement Declare_PtrStack(ED_TextFormat,int32) // TXP_PtrStack_ED_TextFormat Declare_PtrStack(CEditCommandGroup,CEditCommandGroup*) // TXP_PtrStack_CEditCommandGroup Declare_PtrStack(CParseState,CParseState*) // TXP_PtrStack_CParseState /* iTableMode param for CEditTableElement::SetSizeMode() */ #define ED_MODE_TABLE_PERCENT 0x0001 /* Convert table to use % of parent width */ #define ED_MODE_TABLE_PIXELS 0x0002 /* Convert table to use absolute pixels */ #define ED_MODE_CELL_PERCENT 0x0004 /* Convert all cells to use % of parent width */ #define ED_MODE_CELL_PIXELS 0x0008 /* Convert all cells to use absolute pixels */ #define ED_MODE_USE_TABLE_WIDTH 0x0010 /* Set WIDTH param for table */ #define ED_MODE_NO_TABLE_WIDTH 0x0020 /* Remove WIDTH param for table */ #define ED_MODE_USE_TABLE_HEIGHT 0x0040 /* Set HEIGHT param for table*/ #define ED_MODE_NO_TABLE_HEIGHT 0x0080 /* Remove HEIGHT param table */ #define ED_MODE_USE_CELL_WIDTH 0x0100 /* Set WIDTH param for all cells */ #define ED_MODE_NO_CELL_WIDTH 0x0200 /* Remove WIDTH param for all cells */ #define ED_MODE_USE_CELL_HEIGHT 0x0400 /* Set HEIGHT param for all cells*/ #define ED_MODE_NO_CELL_HEIGHT 0x0800 /* Remove HEIGHT param for all cells*/ #define ED_MODE_USE_COLS 0x1000 /* Use COLS param for table (only 1st row used) */ #define ED_MODE_NO_COLS 0x2000 /* Remove COLS param for table (all cell widths used) */ #ifdef DEBUG #define DEBUG_EDIT_LAYOUT #endif typedef int32 DocumentVersion; typedef int32 ElementIndex; // For persistent insert points, a position from the start of the document. typedef int32 ElementOffset; // Within one element, an offset into an element. Is 0 or 1, except for text. class CEditInsertPoint { public: CEditInsertPoint(); CEditInsertPoint(CEditElement* pElement, ElementOffset iPos); CEditInsertPoint(CEditLeafElement* pElement, ElementOffset iPos); CEditInsertPoint(CEditElement* pElement, ElementOffset iPos, XP_Bool bStickyAfter); XP_Bool IsStartOfElement(); XP_Bool IsEndOfElement(); XP_Bool IsStartOfContainer(); XP_Bool IsEndOfContainer(); XP_Bool IsStartOfDocument(); XP_Bool IsEndOfDocument(); XP_Bool GapWithBothSidesAllowed(); XP_Bool IsLineBreak(); XP_Bool IsSoftLineBreak(); XP_Bool IsHardLineBreak(); XP_Bool IsSpace(); // After insert point XP_Bool IsSpaceBeforeOrAfter(); // Before or after insert point // Move forward and backward. Returns FALSE if can't move CEditInsertPoint NextPosition(); CEditInsertPoint PreviousPosition(); XP_Bool operator==(const CEditInsertPoint& other ); XP_Bool operator!=(const CEditInsertPoint& other ); XP_Bool operator<(const CEditInsertPoint& other ); XP_Bool operator<=(const CEditInsertPoint& other ); XP_Bool operator>=(const CEditInsertPoint& other ); XP_Bool operator>(const CEditInsertPoint& other ); XP_Bool IsDenormalizedVersionOf(const CEditInsertPoint& other); intn Compare(const CEditInsertPoint& other ); #ifdef DEBUG void Print(IStreamOut& stream); #endif CEditLeafElement* m_pElement; ElementOffset m_iPos; XP_Bool m_bStickyAfter; private: CEditElement* FindNonEmptyElement( CEditElement *pStartElement ); }; class CEditSelection { public: CEditSelection(); CEditSelection(CEditElement* pStart, intn iStartPos, CEditElement* pEnd, intn iEndPos, XP_Bool fromStart = FALSE); CEditSelection(const CEditInsertPoint& start, const CEditInsertPoint& end, XP_Bool fromStart = FALSE); XP_Bool operator==(const CEditSelection& other ); XP_Bool operator!=(const CEditSelection& other ); XP_Bool IsInsertPoint(); CEditInsertPoint* GetActiveEdge(); CEditInsertPoint* GetAnchorEdge(); CEditInsertPoint* GetEdge(XP_Bool bEnd); // Like ==, except ignores bFromStart. XP_Bool EqualRange(CEditSelection& other); XP_Bool Intersects(CEditSelection& other); // Just a test; doesn't change this. XP_Bool Contains(CEditInsertPoint& point); XP_Bool Contains(CEditSelection& other); XP_Bool ContainsStart(CEditSelection& other); XP_Bool ContainsEnd(CEditSelection& other); XP_Bool ContainsEdge(CEditSelection& other, XP_Bool bEnd); XP_Bool CrossesOver(CEditSelection& other); XP_Bool ClipTo(CEditSelection& other); // True if the result is defined. No change to this if it isn't CEditElement* GetCommonAncestor(); XP_Bool CrossesSubDocBoundary(); CEditSubDocElement* GetEffectiveSubDoc(XP_Bool bEnd); XP_Bool ExpandToNotCrossStructures(); // TRUE if this was changed void ExpandToBeCutable(); void ExpandToIncludeFragileSpaces(); void ExpandToEncloseWholeContainers(); XP_Bool EndsAtStartOfContainer(); XP_Bool StartsAtEndOfContainer(); XP_Bool AnyLeavesSelected(); // FALSE if insert point or container end. XP_Bool IsContainerEnd(); // TRUE if just contains the end of a container. // Useful for cut & delete, where you don't replace the final container mark XP_Bool ContainsLastDocumentContainerEnd(); void ExcludeLastDocumentContainerEnd(); CEditContainerElement* GetStartContainer(); CEditContainerElement* GetClosedEndContainer(); // Not 1/2 open! #ifdef DEBUG void Print(IStreamOut& stream); #endif CEditInsertPoint m_start; CEditInsertPoint m_end; XP_Bool m_bFromStart; //cmanske: Needed to differentiate between an empty selection // (indicating we should get the current selection) // and a selection obtained from a table cell XP_Bool IsEmpty() { return (m_start.m_pElement == 0); } }; class CPersistentEditInsertPoint { public: // m_bStickyAfter defaults to TRUE CPersistentEditInsertPoint(); CPersistentEditInsertPoint(ElementIndex index); CPersistentEditInsertPoint(ElementIndex index, XP_Bool bStickyAfter); #ifdef DEBUG void Print(IStreamOut& stream); #endif XP_Bool operator==(const CPersistentEditInsertPoint& other ); XP_Bool operator!=(const CPersistentEditInsertPoint& other ); XP_Bool operator<(const CPersistentEditInsertPoint& other ); XP_Bool operator<=(const CPersistentEditInsertPoint& other ); XP_Bool operator>=(const CPersistentEditInsertPoint& other ); XP_Bool operator>(const CPersistentEditInsertPoint& other ); XP_Bool IsEqualUI(const CPersistentEditInsertPoint& other ); // Used for undo // delta = this - other; void ComputeDifference(CPersistentEditInsertPoint& other, CPersistentEditInsertPoint& delta); // result = this + delta; void AddRelative(CPersistentEditInsertPoint& delta, CPersistentEditInsertPoint& result); ElementIndex m_index; // If this insert point falls between two elements, and // m_bStickyAfter is TRUE, then this insert point is attached // to the start of the second element. If m_bStickyAfter // is false, then this insert point is attached to the end of // the first element. It is FALSE by default. It is ignored // by all of the comparison operators except IsEqualUI. It // is ignored by ComputeDifference and AddRelative XP_Bool m_bStickyAfter; }; #ifdef DEBUG #define DUMP_PERSISTENT_EDIT_INSERT_POINT(s, pt) { XP_TRACE(("%s %d", s, pt.m_index));} #else #define DUMP_PERSISTENT_EDIT_INSERT_POINT(s, pt) {} #endif class CPersistentEditSelection { public: CPersistentEditSelection(); CPersistentEditSelection(const CPersistentEditInsertPoint& start, const CPersistentEditInsertPoint& end); #ifdef DEBUG void Print(IStreamOut& stream); #endif XP_Bool operator==(const CPersistentEditSelection& other ); XP_Bool operator!=(const CPersistentEditSelection& other ); XP_Bool SelectedRangeEqual(const CPersistentEditSelection& other ); // Ignores m_bFromStart ElementIndex GetCount(); XP_Bool IsInsertPoint(); CPersistentEditInsertPoint* GetEdge(XP_Bool bEnd); // Used for undo // change this by the same way that original was changed into modified. void Map(CPersistentEditSelection& original, CPersistentEditSelection& modified); CPersistentEditInsertPoint m_start; CPersistentEditInsertPoint m_end; XP_Bool m_bFromStart; }; #ifdef DEBUG #define DUMP_PERSISTENT_EDIT_SELECTION(s, sel) { XP_TRACE(("%s %d-%d %d", s,\ sel.m_start.m_index,\ sel.m_end.m_index,\ sel.m_bFromStart));} #else #define DUMP_PERSISTENT_EDIT_SELECTION(s, sel) {} #endif #ifdef DEBUG void TraceLargeString(char* b); #endif // // Element type used during stream constructor // enum EEditElementType { eElementNone, eElement, eTextElement, eImageElement, eHorizRuleElement, eBreakElement, eContainerElement, eIconElement, eTargetElement, eListElement, eEndElement, eTableElement, eTableRowElement, eTableCellElement, eCaptionElement, eLayerElement, eDivisionElement, eInternalAnchorElement }; // // Copy type written to stream // Used to decide how to paste into existing table // enum EEditCopyType { eCopyNormal, // Default = 0. Normal HTML copying, not a table eCopyTable, // Entire table - paste normally or embeded into existing table eCopyRows, // Entire rows - inserts/overlays into existing table eCopyColumns, // Entire columns " eCopyCells // Arbitrary cells - overlay selected target cells in table }; // // CEditElement // class CEditElement { private: CEditElement* m_pParent; CEditElement* m_pNext; CEditElement* m_pChild; char *m_pTagData; // hack! remainder of tag data for regen. protected: TagType m_tagType; char* GetTagData(){ return m_pTagData; }; void SetTagData(char* tagData); public: // ctor, dtor CEditElement(CEditElement *pParent, TagType tagType, char* pData = NULL); CEditElement(CEditElement *pParent, PA_Tag *pTag, int16 csid); CEditElement(IStreamIn *pStreamIn, CEditBuffer *pBuffer); virtual ~CEditElement(); static CEditElement* StreamCtor( IStreamIn *pIn, CEditBuffer *pBuffer ); static CEditElement* StreamCtorNoChildren( IStreamIn *pIn, CEditBuffer *pBuffer ); virtual void StreamInChildren(IStreamIn* pIn, CEditBuffer* pBuffer); // // Accessor functions // CEditElement* GetParent(){ return m_pParent; } CEditElement* GetNextSibling(){ return m_pNext; } CEditElement* GetPreviousSibling(); CEditElement* GetChild(){ return m_pChild; } virtual XP_Bool IsAcceptableChild(CEditElement& pChild); void SetParent(CEditElement* pParent){m_pParent = pParent;} void SetChild(CEditElement *pChild); void SetNextSibling(CEditElement* pNext); CEditElement* GetLastChild(); CEditElement* GetLastMostChild(); CEditElement* GetFirstMostChild(); CEditCaptionElement* GetCaption(); // Returns containing cell, or NULL if none. CEditCaptionElement* GetCaptionIgnoreSubdoc(); // Returns containing cell, or NULL if none. CEditTableCellElement* GetTableCell(); // Returns containing cell, or NULL if none. CEditTableCellElement* GetTableCellIgnoreSubdoc(); // Returns containing cell, or NULL if none. CEditTableRowElement* GetTableRow(); // Returns containing row, or NULL if none. CEditTableRowElement* GetTableRowIgnoreSubdoc(); // Returns containing row, or NULL if none. CEditTableElement* GetTable(); // Returns containing table, or NULL if none. CEditTableElement* GetTableIgnoreSubdoc(); // Returns containing table, or NULL if none. CEditLayerElement* GetLayer(); // Returns containing Layer, or NULL if none. CEditLayerElement* GetLayerIgnoreSubdoc(); // Returns containing Layer, or NULL if none. CEditSubDocElement* GetSubDoc(); // Returns containing sub-doc, or NULL if none. CEditSubDocElement* GetSubDocSkipRoot(); // Returns containing sub-doc, or NULL if none. CEditRootDocElement* GetRootDoc(); // Returns containing root, or NULL if none. XP_Bool InMungableMailQuote(); // Returns true if this element is within a mungable mail quote. XP_Bool InMailQuote(); // Returns true if this element is within a mail quote. CEditListElement* GetMailQuote(); // Returns containing mail quote or NULL. //cmanske A bit more readable XP_Bool IsInTableCell() { return NULL != GetTableCellIgnoreSubdoc(); } XP_Bool IsInTable() { return NULL != GetTableIgnoreSubdoc(); } CEditElement* GetTopmostTableOrLayer(); // Returns topmost containing table or Layer, or NULL if none. CEditElement* GetTableOrLayerIgnoreSubdoc(); // Returns containing table or Layer, or NULL if none. CEditElement* GetSubDocOrLayerSkipRoot(); CEditBuffer* GetEditBuffer(); // returns the edit buffer if the element is in one. virtual ED_Alignment GetDefaultAlignment(); virtual ED_Alignment GetDefaultVAlignment(); TagType GetType(){ return m_tagType; } void SetType( TagType t ){ m_tagType = t; } // Returns TRUE only if tag has WIDTH or HEIGHT already defined // Use NULL for params if you don't need those values XP_Bool GetWidth(XP_Bool * pPercent = NULL, int32 * pWidth = NULL); XP_Bool GetHeight(XP_Bool * pPercent = NULL, int32 * pHeight = NULL); virtual void SetSize(XP_Bool bWidthPercent, int32 iWidth, XP_Bool bHeightPercent, int32 iHeight); virtual XP_Bool CanReflow(); // // Cast routines. // CEditTextElement* Text(); virtual XP_Bool IsLeaf(); CEditLeafElement* Leaf(); virtual XP_Bool IsRoot(); CEditRootDocElement* Root(); virtual XP_Bool IsContainer(); CEditContainerElement* Container(); //get previous non empty container to querry for preopen conditions ect CEditContainerElement* GetPreviousNonEmptyContainer(); //get next non empty container to querry for preclose conditions ect CEditContainerElement* GetNextNonEmptyContainer(); virtual XP_Bool IsList(); CEditListElement* List(); virtual XP_Bool IsBreak(); CEditBreakElement* Break(); virtual XP_Bool CausesBreakBefore(); virtual XP_Bool CausesBreakAfter(); virtual XP_Bool AllowBothSidesOfGap(); virtual XP_Bool IsImage(); CEditImageElement* Image(); virtual XP_Bool IsIcon(); CEditIconElement* Icon(); CEditTargetElement* Target(); CEditHorizRuleElement* HorizRule(); virtual XP_Bool IsRootDoc(); CEditRootDocElement* RootDoc(); virtual XP_Bool IsSubDoc(); CEditSubDocElement* SubDoc(); virtual XP_Bool IsTable(); CEditTableElement* Table(); virtual XP_Bool IsTableRow(); CEditTableRowElement* TableRow(); virtual XP_Bool IsTableCell(); CEditTableCellElement* TableCell(); virtual XP_Bool IsCaption(); CEditCaptionElement* Caption(); virtual XP_Bool IsText(); virtual XP_Bool IsLayer(); CEditLayerElement* Layer(); virtual XP_Bool IsDivision(); CEditDivisionElement* Division(); XP_Bool IsEndOfDocument(); virtual XP_Bool IsEndContainer(); // Can this element contain a paragraph? virtual XP_Bool IsContainerContainer(); XP_Bool IsA( int tagType ){ return m_tagType == tagType; } XP_Bool Within( int tagType ); XP_Bool InFormattedText(); CEditContainerElement* FindContainer(); // Returns this if this is a container. CEditContainerElement* FindEnclosingContainer(); // Starts search with parent of this. CEditElement* FindList(); void FindList( CEditContainerElement*& pContainer, CEditListElement*& pList ); CEditElement* FindContainerContainer(); // // Tag Generation functions // virtual PA_Tag* TagOpen( int iEditOffset ); virtual PA_Tag* TagEnd( ); void SetTagData( PA_Tag* pTag, char* pTagData); // // Output routines. // virtual void PrintOpen( CPrintState *pPrintState ); void InternalPrintOpen( CPrintState *pPrintState, char* pTagData ); virtual void PrintEnd( CPrintState *pPrintState ); virtual void StreamOut( IStreamOut *pOut ); virtual void PartialStreamOut( IStreamOut *pOut, CEditSelection& selection ); virtual XP_Bool ShouldStreamSelf( CEditSelection& local, CEditSelection& selection); virtual void StreamToPositionalText( IStreamOut * /*pOut*/, XP_Bool /*bEnd*/ ){} virtual EEditElementType GetElementType(); // Get parent table or cell of any element CEditTableElement* GetParentTable(); CEditTableCellElement* GetParentTableCell(); virtual XP_Bool Reduce( CEditBuffer *pBuffer ); // Selection utilities XP_Bool ClipToMe(CEditSelection& selection, CEditSelection& local); // Returns TRUE if selection intersects with "this". virtual void GetAll(CEditSelection& selection); // Get selection that selects all of this. //cmanske: Used only by CEditTableElement and CEditTableCellElement virtual XP_Bool IsSelected() {return FALSE; } // iterators typedef XP_Bool (CEditElement::*PMF_EditElementTest)(void*); CEditElement* FindNextElement( PMF_EditElementTest pmf, void *pData ); CEditElement* UpRight( PMF_EditElementTest pmf, void *pTestData ); CEditElement* DownRight( PMF_EditElementTest pmf,void *pTestData, XP_Bool bIgnoreThis = FALSE ); CEditElement* FindPreviousElement( PMF_EditElementTest pmf, void *pTestData ); CEditElement* UpLeft( PMF_EditElementTest pmf, void *pTestData ); CEditElement* DownLeft( PMF_EditElementTest pmf, void *pTestData, XP_Bool bIgnoreThis = FALSE ); XP_Bool TestIsTrue( PMF_EditElementTest pmf, void *pTestData ){ return (this->*pmf)(pTestData); } // // Search routines to be applied FindNextElement and FindPreviousElement // XP_Bool FindText( void* /*pVoid*/ ); XP_Bool FindTextAll( void* /*pVoid*/ ); XP_Bool FindLeaf( void* /*pVoid*/ ); XP_Bool FindLeafAll( void* /*pVoid*/ ); XP_Bool FindImage( void* /*pvoid*/ ); XP_Bool FindTarget( void* /*pvoid*/ ); XP_Bool FindUnknownHTML( void* /*pvoid*/ ); XP_Bool SplitContainerTest( void* /*pVoid*/ ); XP_Bool SplitFormattingTest( void* pVoid ); XP_Bool FindTable( void* /*pvoid*/ ); XP_Bool FindTableRow( void* /*pvoid*/ ); XP_Bool FindTableCell( void* /*pvoid*/ ); XP_Bool FindContainer( void* /*pVoid*/ ); // // Split the tree. You can stop when pmf returns true. // virtual CEditElement* Split(CEditElement *pLastChild, CEditElement* pCloneTree, PMF_EditElementTest pmf, void *pData); virtual CEditElement* Clone( CEditElement *pParent = 0 ); CEditElement* CloneFormatting( TagType endType ); virtual void Unlink(); virtual void Merge( CEditElement *pAppendBlock, XP_Bool bCopyAppendAttributes = TRUE ); #ifdef DEBUG virtual void ValidateTree(); #endif CEditElement* InsertAfter( CEditElement *pPrev ); CEditElement* InsertBefore( CEditElement *pNext ); void InsertAsFirstChild( CEditElement *pParent ); void InsertAsLastChild( CEditElement *pParent ); virtual XP_Bool IsFirstInContainer(); CEditTextElement* TextInContainerAfter(); CEditTextElement* PreviousTextInContainer(); virtual CEditElement* Divide(int iOffset); CEditLeafElement* PreviousLeafInContainer(); CEditLeafElement* LeafInContainerAfter(); CEditLeafElement* PreviousLeaf() { return (CEditLeafElement*) FindPreviousElement( &CEditElement::FindLeaf, 0 ); } CEditLeafElement* NextLeaf() { return (CEditLeafElement*) FindNextElement( &CEditElement::FindLeaf, 0 ); } CEditLeafElement* NextLeafAll() { return (CEditLeafElement*) FindNextElement( &CEditElement::FindLeafAll, 0 ); } CEditLeafElement* NextLeafAll(XP_Bool bForward); CEditContainerElement* NextContainer() { return (CEditContainerElement*) FindNextElement( &CEditElement::FindContainer, 0 ); } CEditContainerElement* PreviousContainer() { return (CEditContainerElement*) FindPreviousElement( &CEditElement::FindContainer, 0 ); } CEditElement* GetRoot(); CEditElement* GetCommonAncestor(CEditElement* pOther); // NULL if not in same tree CEditElement* GetChildContaining(CEditElement* pDescendant); // NULL if not a descendant XP_Bool DeleteElement( CEditElement *pTellIfKilled ); void DeleteChildren(); // should be in Container class int GetDefaultFontSize(); // To and from persistent insert points virtual CEditInsertPoint IndexToInsertPoint(ElementIndex index, XP_Bool bStickyAfter); virtual CPersistentEditInsertPoint GetPersistentInsertPoint(ElementOffset offset); virtual ElementIndex GetElementIndexOf(CEditElement* child); // asserts if argument is not a child. virtual ElementIndex GetPersistentCount(); ElementIndex GetElementIndex(); virtual void FinishedLoad( CEditBuffer* pBuffer ); virtual void AdjustContainers( CEditBuffer* pBuffer ); int16 GetWinCSID(); // International Character set ID protected: virtual void Finalize(); void EnsureSelectableSiblings(CEditBuffer* pBuffer); private: void CommonConstructor(); // For CEditElement constructor, where the vtable isn't // set up enough to check if the item is acceptable. void RawSetNextSibling(CEditElement* pNext) {m_pNext = pNext; } void RawSetChild(CEditElement* pChild) {m_pChild = pChild; } }; // // CEditSubDocElement - base class for the root, captions, and table data cells // class CEditSubDocElement: public CEditElement { public: CEditSubDocElement(CEditElement *pParent, int tagType, char* pData = NULL); CEditSubDocElement(CEditElement *pParent, PA_Tag *pTag, int16 csid); CEditSubDocElement(IStreamIn *pStreamIn, CEditBuffer *pBuffer); virtual XP_Bool IsSubDoc() { return TRUE; } static CEditSubDocElement* Cast(CEditElement* pElement) { return pElement && pElement->IsSubDoc() ? (CEditSubDocElement*) pElement : 0; } virtual XP_Bool Reduce( CEditBuffer *pBuffer ); virtual XP_Bool IsAcceptableChild(CEditElement& pChild){ return ! pChild.IsLeaf(); } virtual void FinishedLoad( CEditBuffer* pBuffer ); }; class CEditTableElement: public CEditElement { public: CEditTableElement(intn columns, intn rows); CEditTableElement(CEditElement *pParent, PA_Tag *pTag, int16 csid, ED_Alignment align); CEditTableElement(IStreamIn *pStreamIn, CEditBuffer *pBuffer); virtual ~CEditTableElement(); virtual XP_Bool IsTable() { return TRUE; } static CEditTableElement* Cast(CEditElement* pElement) { return pElement && pElement->IsTable() ? (CEditTableElement*) pElement : 0; } virtual EEditElementType GetElementType() { return eTableElement; } virtual XP_Bool IsAcceptableChild(CEditElement& pChild){ return pChild.IsTableRow() || pChild.IsCaption(); } virtual void FinishedLoad( CEditBuffer* pBuffer ); void AdjustCaption(); virtual PA_Tag* TagOpen(int iEditOffset); PA_Tag* InternalTagOpen(int iEditOffset, XP_Bool bPrinting); virtual PA_Tag* TagEnd(); void InsertRows(int32 Y, int32 newY, intn number, CEditTableElement* pSource = NULL); void InsertColumns(int32 X, int32 newX, intn number, CEditTableElement* pSource = NULL); //cmanske: I doubt we will ever revive the old undo system, so skip it here // void DeleteRows(int32 Y, intn number, CEditTableElement* pUndoContainer = NULL); void DeleteRows(int32 Y, intn number); void DeleteColumns(int32 X, intn number, CEditTableElement* pUndoContainer = NULL); // Not used much - index based CEditTableRowElement* FindRow(intn number); // Find first row containing a cell that has Y as its top // Optionally return the "logical" row index CEditTableRowElement* GetRow(int32 Y, intn *pRow = NULL); // Find first geometric cell that is at or spans given Y value // The logical row is written to m_iGetRow CEditTableCellElement* GetFirstCellInRow(int32 Y, XP_Bool bSpan = FALSE); CEditTableCellElement* GetFirstCellInRow(CEditTableCellElement *pCell, XP_Bool bSpan = FALSE); // Find next cell using the supplied cell's Y value // (bSpan is FALSE, so Y must match exactly) // If pCell is NULL, use the same Y and bSpan as used for GetFirstCellInRow() // The logical row is written to the element's m_iGetRow // Note: If cell has ROWSPAN > 1, this will skip the next actual row CEditTableCellElement* GetNextCellInRow(CEditTableCellElement *pCell = NULL); // Find previous and cell using supplied cell's Y value // (does not depend on data from GetFirstCellInRow) CEditTableCellElement* GetPreviousCellInRow(CEditTableCellElement *pCell); CEditTableCellElement* GetLastCellInRow(CEditTableCellElement *pCell); // Same as above, but finds columns CEditTableCellElement* GetFirstCellInColumn(int32 X, XP_Bool bSpan = FALSE); CEditTableCellElement* GetFirstCellInColumn(CEditTableCellElement *pCell, XP_Bool bSpan = FALSE); // Note: If cell has COPSPAN > 1, this will skip the next actual column CEditTableCellElement* GetNextCellInColumn(CEditTableCellElement *pCell = NULL); // Find previous and last cell using supplied cell's X value // (does not depend on data from GetFirstCellInRow) CEditTableCellElement* GetPreviousCellInColumn(CEditTableCellElement *pCell); CEditTableCellElement* GetLastCellInColumn(CEditTableCellElement *pCell); // Find first cell in column or row exactly at the specified col or row index grid CEditTableCellElement *GetFirstCellAtColumnIndex(intn iIndex); CEditTableCellElement *GetFirstCellAtRowIndex(intn iIndex); // This gets the next geometric column or row // using supplied X or Y value as current location // (these use the tables m_RowLayoutData and m_ColumnLayoutData) CEditTableCellElement* GetFirstCellInNextColumn(int32 iCurrentColumnX); CEditTableCellElement* GetFirstCellInNextRow(int32 iCurrentRowY); // Get the defining left (for columns) and top (for rows) value from // the index into m_ColumnLayoutData and m_RowLayoutData int32 GetColumnX(intn iIndex); int32 GetRowY(intn iIndex); // Use m_ColumnLayoutData and m_RowLayoutData // to get grid coordinates of a cell intn GetColumnIndex(int32 X); intn GetRowIndex(int32 Y); CEditCaptionElement* GetCaption(); void SetCaption(CEditCaptionElement*); void DeleteCaption(); void SetData( EDT_TableData *pData ); EDT_TableData* GetData(); EDT_TableData* ParseParams( PA_Tag *pTag, int16 csid ); static EDT_TableData* NewData(); static void FreeData( EDT_TableData *pData ); void SetBackgroundColor( ED_Color iColor ); ED_Color GetBackgroundColor(); void SetBackgroundImage( char* pImage ); char* GetBackgroundImage(); // Override printing and taging, since we don't allow ALIGN tag when editing. virtual void PrintOpen( CPrintState *pPrintState ); virtual void PrintEnd( CPrintState *pPrintState ); char* CreateTagData(EDT_TableData *pData, XP_Bool bPrinting); virtual void StreamOut( IStreamOut *pOut); //cmanske: // Get corresponding Layout table element LO_TableStruct* GetLoTable(); // Get width of window view or parent cell of a table // Supply pLoTable if known, else find it void GetParentSize(MWContext *pContext, int32 *pWidth, int32 *pHeight = NULL, LO_TableStruct *pLoTable = NULL); // See edttypes.h for dConvert table and all rows and cells to Percent mode or not // Current bWidthPercent, bHeightPercent, bWidthDefined, and bHeightDefined are saved... void SetSizeMode(MWContext *pContext, int iTableMode); // ... to be restored by this after relayout after table, col, or row resizing void RestoreSizeMode(MWContext *pContext); // Next two use m_RowLayoutData and m_ColumnLayoutData // Clear all row and column layout data void DeleteLayoutData(); // Add new cell to column and/or row layout data void AddLayoutData(CEditTableCellElement *pEdCell, LO_Element *pLoCell); int32 GetCellSpacing() {return m_iCellSpacing; } int32 GetCellPadding() {return m_iCellPadding; } int32 GetCellBorder() {return m_iCellBorder; } int32 GetWidth() {return m_iWidthPixels; } int32 GetHeight() {return m_iHeightPixels; } int32 GetWidthOrPercent() { return m_iWidth; } int32 GetHeightOrPercent() { return m_iHeight; } // Get first cell in table. // Use GetNextCellInTable() or resulting pCell->GetNextCellInTable() // to walk through the table, wrapping around rows, // or resultCell->pGetNextCellInLogicalRow() to walk through cells in the row CEditTableCellElement* GetFirstCell(); // Result from above is stored in m_pCurrentCell CEditTableCellElement* GetNextCellInTable(intn *pRowCounter = NULL); // Analogous routine for rows CEditTableRowElement* GetFirstRow(); // Use following BEFORE we layout and build our m_RowLayoutData and m_ColumnLayoutData // This counts row elements in table and also saves result in m_iRows intn CountRows(); // Max of number of columns // (may be more than number of cells in any particular // row because of ROWSPAN effect) intn CountColumns(); intn GetRows() {m_iRows = m_RowLayoutData.Size(); return m_iRows;} intn GetColumns() {m_iColumns = m_ColumnLayoutData.Size(); return m_iColumns;} // Get number of columns between given values intn GetColumnsSpanned(int32 iStartX, int32 iEndX); // Test if any cell in the first row has COLSPAN > 1 XP_Bool FirstRowHasColSpan(); // 1. Fixup COLSPAN and ROWSPAN errors, // If all cells in a column have COLSPAN > 1, // that is bad, so fix it. Same for ROWSPAN // 2. Save accurate number of cells in each column, // compensating for COLSPAN and ROWSPAN // Uses m_ColumnLayoutData and m_RowLayoutData void FixupColumnsAndRows(); private: ED_Color m_backgroundColor; char* m_pBackgroundImage; ED_Alignment m_align; ED_Alignment m_malign; //Actual width, as determined from layout // See comments for similar params in CEditTableCellElement int32 m_iWidthPixels; // This is % of parent (when bWidthPercent = TRUE) or absolute (in pixels) XP_Bool m_iWidth; XP_Bool m_bWidthPercent; int32 m_iHeightPixels; int32 m_iHeight; XP_Bool m_bHeightPercent; // Pixels between cells int32 m_iCellSpacing; // Space between border and cell contents int32 m_iCellPadding; // Cell border is 1 if table border is > 0 int32 m_iCellBorder; // Save last value of m_bWidthPercent, m_bWidthDefined, // bHeightPercent, and bHeightDefined here // during table, col, and row resizing. // Call RestoreTableSizeMode to reset back to these values XP_Bool m_bSaveWidthPercent; XP_Bool m_bSaveHeightPercent; XP_Bool m_bSaveWidthDefined; XP_Bool m_bSaveHeightDefined; // Maximum number of "geometric" columns // (May be > number in individual rows because of ROWSPAN) int32 m_iColumns; int32 m_iRows; // Used by GetFirstCell() and GetNextCellInTable() CEditTableCellElement *m_pCurrentCell; // For use with GetFirstCellInRow/Column and GetNextCellInRow/Column CEditTableCellElement *m_pFirstCellInColumnOrRow; CEditTableCellElement *m_pNextCellInColumnOrRow; int32 m_iColX; int32 m_iRowY; XP_Bool m_bSpan; intn m_iGetRow; public: intn m_iBackgroundSaveIndex; // Let CEditBuffer access this directly TXP_GrowableArray_EDT_CellLayoutData m_ColumnLayoutData; TXP_GrowableArray_EDT_CellLayoutData m_RowLayoutData; }; class CEditTableRowElement: public CEditElement { public: CEditTableRowElement(); CEditTableRowElement(intn cells); CEditTableRowElement(CEditElement *pParent, PA_Tag *pTag, int16 csid); CEditTableRowElement(IStreamIn *pStreamIn, CEditBuffer *pBuffer); virtual ~CEditTableRowElement(); virtual XP_Bool IsTableRow() { return TRUE; } static CEditTableRowElement* Cast(CEditElement* pElement) { return pElement && pElement->IsTableRow() ? (CEditTableRowElement*) pElement : 0; } virtual EEditElementType GetElementType() { return eTableRowElement; } virtual XP_Bool IsAcceptableChild(CEditElement& pChild){ return pChild.IsTableCell(); } virtual void FinishedLoad( CEditBuffer* pBuffer ); intn GetCells(); // Use actual cell X and Y for Insert and Delete logic void InsertCells(int32 X, int32 newX, intn number, CEditTableRowElement* pSource = NULL); // Append (move) cells in supplied row to this row and delete supplied row if requested // (Note: Unlike most other "insert" methods, "this" is the existing row, not row to be inserted) // Returns the number of cells "positions" appended (sum of COLSPAN of appended cells) intn AppendRow( CEditTableRowElement *pAppendRow, XP_Bool bDeleteRow = TRUE ); // Add extra empty cells to fill out a row to specified amount // or use current table's max columns if iColumns is 0 void PadRowWithEmptyCells(intn iColumns = 0); void DeleteCells(int32 X, intn number, CEditTableRowElement* pUndoContainer = NULL); // Find cell at specific location in column CEditTableCellElement* FindCell(int32 X, XP_Bool bIncludeRightEdge = FALSE); void SetData( EDT_TableRowData *pData ); EDT_TableRowData* GetData( ); static EDT_TableRowData* ParseParams( PA_Tag *pTag, int16 csid ); static EDT_TableRowData* NewData(); static void FreeData( EDT_TableRowData *pData ); void SetBackgroundColor( ED_Color iColor ); ED_Color GetBackgroundColor(); void SetBackgroundImage( char* pImage ); char* GetBackgroundImage(); // Not sure if we need this, but it will be useful // for padding tables with ragged right edges intn GetColumns() {return m_iColumns; } void SetColumns(intn iColumns) {m_iColumns = iColumns; } CEditTableRowElement *GetNextRow(); // Use resultCell->pGetNextCellInLogicalRow() to walk through cells in row CEditTableCellElement *GetFirstCell(); private: ED_Color m_backgroundColor; char* m_pBackgroundImage; // Total number of "physical" columns in row // (i.e., includes effect of COLSPAN and ROWSPAN) intn m_iColumns; public: intn m_iBackgroundSaveIndex; }; class CEditCaptionElement: public CEditSubDocElement { public: CEditCaptionElement(); CEditCaptionElement(CEditElement *pParent, PA_Tag *pTag, int16 csid); CEditCaptionElement(IStreamIn *pStreamIn, CEditBuffer *pBuffer); virtual XP_Bool IsCaption() { return TRUE; } static CEditCaptionElement* Cast(CEditElement* pElement) { return pElement && pElement->IsCaption() ? (CEditCaptionElement*) pElement : 0; } virtual EEditElementType GetElementType() { return eCaptionElement; } void SetData( EDT_TableCaptionData *pData ); EDT_TableCaptionData* GetData( ); EDT_TableCaptionData* GetData( int16 csid ); static EDT_TableCaptionData* ParseParams( PA_Tag *pTag, int16 csid ); static EDT_TableCaptionData* NewData(); static void FreeData( EDT_TableCaptionData *pData ); }; // Table data and Table header class CEditTableCellElement: public CEditSubDocElement { public: CEditTableCellElement(); CEditTableCellElement(XP_Bool bIsHeader); CEditTableCellElement(CEditElement *pParent, PA_Tag *pTag, int16 csid); CEditTableCellElement(IStreamIn *pStreamIn, CEditBuffer *pBuffer); virtual ~CEditTableCellElement(); virtual XP_Bool IsTableCell(); static CEditTableCellElement* Cast(CEditElement* pElement) { return pElement && pElement->IsTableCell() ? (CEditTableCellElement*) pElement : 0; } virtual EEditElementType GetElementType(); virtual ED_Alignment GetDefaultAlignment(); XP_Bool IsTableData(); virtual void StreamOut(IStreamOut *pOut); void SetData( EDT_TableCellData *pData ); // Supply the csid if getting data for table not // yet part of doc, as when pasting from stream EDT_TableCellData* GetData(int16 csid = 0); // Clear mask bits for attributes different from supplied data void MaskData( EDT_TableCellData *pData ); EDT_TableCellData* ParseParams( PA_Tag *pTag, int16 csid ); static EDT_TableCellData* NewData(); static void FreeData( EDT_TableCellData *pData ); void SetBackgroundColor( ED_Color iColor ); ED_Color GetBackgroundColor(); void SetBackgroundImage( char* pImage ); char* GetBackgroundImage(); //cmanske: // Get corresponding Layout struct LO_CellStruct* GetLoCell(); // Next cell in table - wraps around end of each // row until end of table is found (returns null) // If pRowCount is supplied, value it is incremented // when cell returned is 1st one in a next row CEditTableCellElement* GetNextCellInTable(intn *pRowCounter = NULL); // Similar to above, but finds previous cell until beginning is found (returns null) // If pRowCount is supplied, value it is decremented // when cell returned is 1st one in a previous row CEditTableCellElement* GetPreviousCellInTable(intn *pRowCounter = NULL); // This gets next cell in the same logical row CEditTableCellElement* GetNextCellInLogicalRow(); // Find first geometric cell that is at // given X (for column) or Y (for row)value // GetNext... continue using same X or Y // (These just call same functions in CEditTableElement) // If X or Y is not supplied, it is taken from "this" cell's X or Y CEditTableCellElement* GetFirstCellInRow(int32 Y = -1, XP_Bool bSpan = FALSE); CEditTableCellElement* GetFirstCellInColumn(int32 X = -1, XP_Bool bSpan = FALSE); CEditTableCellElement* GetNextCellInRow(CEditTableCellElement *pCell = NULL); CEditTableCellElement* GetNextCellInColumn(CEditTableCellElement *pCell = NULL); XP_Bool AllCellsInColumnAreSelected(); XP_Bool AllCellsInRowAreSelected(); // Test if cell contains only 1 container with // just the empty text field every new cell has XP_Bool IsEmpty(); // Keep these in synch when selecting so // we don't always have to rely on LO_Elements XP_Bool IsSelected() { return m_bSelected; } void SetSelected(XP_Bool bSelected) { m_bSelected = bSelected; } // Move contents of supplied cell into this cell void MergeCells(CEditTableCellElement* pCell); // Delete all contents, leaving just the minimum empty text element // Set param to TRUE only when deleting all selected cells // using CEditBuffer::DeleteSelectedCells() void DeleteContents(XP_Bool bMarkAsDeleted = FALSE); inline XP_Bool IsDeleted() { return m_bDeleted; } inline void SetDeleted(XP_Bool bDeleted) {m_bDeleted = bDeleted;} // Get all text from a cell. If bJoinParagrphs is FALSE, // appropriate CR/LF is added between containers, // else they are appended without CR/LF so cell contents // can be pasted into Excell spreadsheet char * GetText(XP_Bool bJoinParagraphs = FALSE); // Returns sum of widths of all cells in first row in table int32 GetParentWidth(); // Sum of heights of all cells in first column of table int32 GetParentHeight(); int32 GetX() { return m_X; } int32 GetY() { return m_Y; } intn GetRow() { return m_iRow; } int32 GetWidth() { return m_iWidthPixels; } int32 GetHeight() { return m_iHeightPixels; } int32 GetWidthOrPercent() { return m_iWidth; } int32 GetHeightOrPercent() { return m_iHeight; } int32 GetColSpan() { return m_iColSpan; } int32 GetRowSpan() { return m_iRowSpan; } XP_Bool GetWidthPercent() { return m_bWidthPercent; } XP_Bool GetHeightPercent() { return m_bHeightPercent; } // This gets the width including the cell border, // padding inside cell, and inter-cell space to the next cell // Supply pTable if available for efficiency int32 GetFullWidth(CEditTableElement *pTable = NULL); int32 GetFullHeight(CEditTableElement *pTable = NULL); // These will do appropriate action using SetData void IncreaseColSpan(int32 iIncrease); void IncreaseRowSpan(int32 iIncrease); void DecreaseColSpan(int32 iDecrease); void DecreaseRowSpan(int32 iDecrease); // Insert as last child of supplied parent // but first save current parent and next pointers void SwitchLinkage(CEditTableRowElement *pParentRow); // This switches parent and next pointers // to those saved during SwitchLinkage void RestoreLinkage(); // Save current percent and "defined" values -- do this before resizing, which may need // to change the mode for better control of resizing // Since this is always called when we know the cell's data, // supply the bWidthDefined and bHeightDefined values // (percent mode params are held in class member variables) void SaveSizeMode(XP_Bool bWidthDefined, XP_Bool bHeightDefined); // Restore saved width and height percent modes, // readjust m_bWidth an m_bHeight, and call SetData to set tag data void RestoreSizeMode(int32 iParentWidth, int32 iParentHeight); // Calculate the Percent iWidth or iHeight from the // iWidthPixels and iHeightPixels in pData... void CalcPercentWidth(EDT_TableCellData *pData); void CalcPercentHeight(EDT_TableCellData *pData); // ...vice versa void CalcPixelWidth(EDT_TableCellData *pData); void CalcPixelHeight(EDT_TableCellData *pData); void SetWidth(XP_Bool bWidthDefined, XP_Bool bWidthPercent, int32 iWidthPixels); void SetHeight(XP_Bool bHeightDefined, XP_Bool bHeightPercent, int32 iHeightPixels); // Next two are used when dragging the right border // Set all cells in a column to the width supplied void SetColumnWidthRight(CEditTableElement *pTable, LO_Element *pLoCell, EDT_TableCellData *pData); // Set all cells in a row to the width params supplied in pData void SetRowHeightBottom(CEditTableElement *pTable, LO_Element *pLoCell, EDT_TableCellData *pData); // Next two are use when resizing inside table cell property dialog // Supplying bWidthDefined or bHeightDefined allows clearing this for entire col or row // Set all cells in a column to the width supplied void SetColumnWidthLeft(CEditTableElement *pTable, CEditTableCellElement *pEdCell, EDT_TableCellData *pData); // Set all cells in a row to the width supplied void SetRowHeightTop(CEditTableElement *pTable, CEditTableCellElement *pEdCell, EDT_TableCellData *pData); private: ED_Color m_backgroundColor; char* m_pBackgroundImage; // Cache this for efficiency XP_Bool m_bWidthPercent; XP_Bool m_bHeightPercent; int32 m_iColSpan; int32 m_iRowSpan; // These are set only by FixupTableData(), //FIGURING OUT INDEXES IS TOO COMPLICATED! // USE REAL LOCATIONS INSTEAD int32 m_X; int32 m_Y; intn m_iRow; // Current logical and actual row index //Actual width, as determined from layout //Set by CEditBuffer::FixupTableData() after a table is layed out // We need this because tag data is not recorded // if m_bWidthDefined is FALSE, but we want to be able // to have the actual width available as default when // user edits the table or cell data int32 m_iWidthPixels; int32 m_iHeightPixels; // This is actual width or height in pixels, or Percent if b[Width|Height]Percent = TRUE; int32 m_iWidth; int32 m_iHeight; // Save last value of m_bWidthPercent, m_bWidthDefined, // bHeightPercent, and bHeightDefined here // during table, col, and row resizing. // Call RestoreTableSizeMode to reset back to these values XP_Bool m_bSaveWidthPercent; XP_Bool m_bSaveHeightPercent; XP_Bool m_bSaveWidthDefined; XP_Bool m_bSaveHeightDefined; // This is used to temporarily switch cell to // a table created for copying contents // These are used by SwitchLinkage() and RestoreLinkage() CEditElement *m_pSaveParent; CEditElement *m_pSaveNext; // This should be TRUE only if cell is also in CEditBuffer::m_SelectedEdCells list XP_Bool m_bSelected; // Deleting an arbitrary set of cells is tricky // since some cells only have contents deleted, // and we want to leave those selected, so we can't rely on // m_SeletectedEdCells list to be empty after "deleting" all cells // This marks cells to be skipped over on successive recursions. // Must call CEditTable::ResetDeletedCells() to clear these flags when done XP_Bool m_bDeleted; public: intn m_iBackgroundSaveIndex; }; class CEditLayerElement: public CEditElement { public: CEditLayerElement(); CEditLayerElement(CEditElement *pParent, PA_Tag *pTag, int16 csid); CEditLayerElement(IStreamIn *pStreamIn, CEditBuffer *pBuffer); virtual XP_Bool IsLayer() { return TRUE; } static CEditLayerElement* Cast(CEditElement* pElement) { return pElement && pElement->IsLayer() ? (CEditLayerElement*) pElement : 0; } virtual EEditElementType GetElementType() { return eLayerElement; } virtual XP_Bool IsAcceptableChild(CEditElement& pChild){ return pChild.IsContainer(); } virtual void FinishedLoad( CEditBuffer* pBuffer ); void SetData( EDT_LayerData *pData ); EDT_LayerData* GetData( ); static EDT_LayerData* ParseParams( PA_Tag *pTag, int16 csid ); static EDT_LayerData* NewData(); static void FreeData( EDT_LayerData *pData ); // Temporary methods. Remove when we can display layers. virtual void PrintOpen( CPrintState *pPrintState ); virtual void PrintEnd( CPrintState *pPrintState ); private: }; class CEditDivisionElement: public CEditElement { public: CEditDivisionElement(); CEditDivisionElement(CEditElement *pParent, PA_Tag *pTag, int16 csid); CEditDivisionElement(IStreamIn *pStreamIn, CEditBuffer *pBuffer); virtual XP_Bool IsDivision(); static CEditDivisionElement* Cast(CEditElement* pElement); virtual EEditElementType GetElementType(); virtual XP_Bool IsAcceptableChild(CEditElement& pChild); ED_Alignment GetAlignment(); void ClearAlignment(); XP_Bool HasData(); void SetData( EDT_DivisionData *pData ); EDT_DivisionData* GetData( ); static EDT_DivisionData* ParseParams( PA_Tag *pTag, int16 csid ); static EDT_DivisionData* NewData(); static void FreeData( EDT_DivisionData *pData ); virtual void PrintOpen( CPrintState *pPrintState ); virtual void PrintEnd( CPrintState *pPrintState ); private: }; // // CEditRootDocElement - Top most element in the tree, tag HTML // class CEditRootDocElement: public CEditSubDocElement { private: CEditBuffer* m_pBuffer; public: CEditRootDocElement( CEditBuffer* pBuffer ): CEditSubDocElement(0, P_MAX), m_pBuffer( pBuffer ){} virtual XP_Bool Reduce( CEditBuffer * /*pBuffer */ ){ return FALSE; } virtual XP_Bool ShouldStreamSelf( CEditSelection& /*local*/, CEditSelection& /*selection*/ ) { return FALSE; } virtual void FinishedLoad( CEditBuffer *pBuffer ); virtual void PrintOpen( CPrintState *pPrintState ); virtual void PrintEnd( CPrintState *pPrintState ); virtual XP_Bool IsRoot() { return TRUE; } static CEditRootDocElement* Cast(CEditElement* pElement) { return pElement && pElement->IsRoot() ? (CEditRootDocElement*) pElement : 0; } CEditBuffer* GetBuffer(){ return m_pBuffer; } #ifdef DEBUG virtual void ValidateTree(); #endif }; class CEditLeafElement: public CEditElement { private: ElementOffset m_iSize; // fake size. public: // pass through constructors. CEditLeafElement(CEditElement *pParent, int tagType): CEditElement(pParent,tagType),m_iSize(1){} CEditLeafElement(IStreamIn *pStreamIn, CEditBuffer *pBuffer): CEditElement(pStreamIn,pBuffer),m_iSize(1){} // // CEditElement Stuff // virtual XP_Bool IsLeaf() { return TRUE; } static CEditLeafElement* Cast(CEditElement* pElement) { return pElement && pElement->IsLeaf() ? (CEditLeafElement*) pElement : 0; } virtual PA_Tag* TagOpen( int iEditOffset ); virtual void GetAll(CEditSelection& selection); virtual XP_Bool IsAcceptableChild(CEditElement& pChild ); virtual ElementIndex GetPersistentCount(); virtual void StreamToPositionalText( IStreamOut *pOut, XP_Bool bEnd ); virtual XP_Bool IsContainerContainer(); virtual XP_Bool IsFirstInContainer(); // // Stuff created at this level (Leaf) // virtual void SetLayoutElement( intn iEditOffset, intn lo_type, LO_Element* pLoElement )=0; virtual void ResetLayoutElement( intn iEditOffset, LO_Element* pLoElement )=0; virtual LO_Element* GetLayoutElement()=0; virtual XP_Bool GetLOElementAndOffset( ElementOffset iEditOffset, XP_Bool bEditStickyAfter, LO_Element*& pRetElement, int& pLayoutOffset )=0; // if appropriate virtual ElementOffset GetLen(){ return m_iSize; } virtual void DeleteChar( MWContext * /*pContext*/, int /*iOffset*/ ){ m_iSize = 0; } virtual CEditElement* Divide(int iOffset); virtual CEditTextElement* CopyEmptyText(CEditElement *pParent = 0); // HREF management... virtual void SetHREF( ED_LinkId ){} virtual ED_LinkId GetHREF(){ return ED_LINK_ID_NONE; } // // Leaf manipulation functions.. // XP_Bool NextPosition(ElementOffset iOffset, CEditLeafElement*& pNew, ElementOffset& iNewOffset ); XP_Bool PrevPosition(ElementOffset iOffset, CEditLeafElement*& pNew, ElementOffset& iNewOffset ); virtual CPersistentEditInsertPoint GetPersistentInsertPoint(ElementOffset offset); // True if this is a bucket for totally unknown html virtual XP_Bool IsUnknownHTML(); // True if this element is an HTML comment virtual XP_Bool IsComment(); // True if this element is an HTML comment that matches a given prefix. // IsComment("FOO") will match "" virtual XP_Bool IsComment(char* pPrefix); XP_Bool IsMisspelled(); #ifdef DEBUG virtual void ValidateTree(); #endif protected: void DisconnectLayoutElements(LO_Element* pElement); void SetLayoutElementHelper( intn desiredType, LO_Element** pElementHolder, intn iEditOffset, intn lo_type, LO_Element* pLoElement); void ResetLayoutElementHelper( LO_Element** pElementHolder, intn iEditOffset, LO_Element* pLoElement ); }; class CEditContainerElement: public CEditElement { private: ED_Alignment m_align; ED_Alignment m_defaultAlign; XP_Bool m_hackPreformat; public: XP_Bool m_bHasEndTag; // Only important for parsing. static CEditContainerElement* NewDefaultContainer( CEditElement *pParent, ED_Alignment align ); CEditContainerElement(CEditElement *pParent, PA_Tag *pTag, int16 csid, ED_Alignment eAlign); CEditContainerElement(IStreamIn *pStreamIn, CEditBuffer *pBuffer); virtual void StreamInChildren(IStreamIn* pIn, CEditBuffer* pBuffer); virtual void StreamOut( IStreamOut *pOut); virtual XP_Bool ShouldStreamSelf( CEditSelection& /*local*/, CEditSelection& /*selection*/ ) { return TRUE; } virtual XP_Bool IsContainer() { return TRUE; } static CEditContainerElement* Cast(CEditElement* pElement) { return pElement && pElement->IsContainer() ? (CEditContainerElement*) pElement : 0; } virtual XP_Bool IsContainerContainer() { return FALSE; } virtual ElementIndex GetPersistentCount(); virtual void FinishedLoad( CEditBuffer *pBuffer ); virtual void AdjustContainers( CEditBuffer *pBuffer ); virtual PA_Tag* TagOpen( int iEditOffset ); virtual PA_Tag* TagEnd( ); virtual EEditElementType GetElementType(); virtual void PrintOpen( CPrintState *pPrintState ); virtual void PrintEnd( CPrintState *pPrintState ); virtual CEditElement* Clone( CEditElement *pParent = 0); virtual void StreamToPositionalText( IStreamOut *pOut, XP_Bool bEnd ); static EDT_ContainerData* NewData(); static void FreeData( EDT_ContainerData *pData ); virtual XP_Bool IsAcceptableChild(CEditElement& pChild) {return pChild.IsLeaf();} // // Implementation // void SetData( EDT_ContainerData *pData ); EDT_ContainerData* GetData( ); EDT_ContainerData* ParseParams( PA_Tag *pTag, int16 csid ); void SetAlignment( ED_Alignment eAlign ); ED_Alignment GetAlignment( ){ return m_align; } void CopyAttributes( CEditContainerElement *pContainer ); XP_Bool IsEmpty(); XP_Bool ShouldSkipTags(); XP_Bool IsImplicitBreak(); // 0..2, where 0 = not in pseudo paragraph. // 1 = first container of pseudo paragraph. // 2 = second container of pseudo paragraph. int16 GetPseudoParagraphState(); XP_Bool ForcesDoubleSpacedNextLine(); //cmanske: Get single string with all of container's text (no embeded CR/LF) // Caller must XP_FREE the result char *GetText(); #ifdef DEBUG virtual void ValidateTree(); #endif XP_Bool IsPlainFirstContainer(); XP_Bool IsFirstContainer(); XP_Bool SupportsAlign(); void AlignIfEmpty( ED_Alignment eAlign ); XP_Bool HasExtraData(); }; class CEditListElement: public CEditElement { private: char *m_pBaseURL; /* If an ED_LIST_TYPE_CITE, this is the URL from the enclosing tag. */ public: CEditListElement( CEditElement *pParent, PA_Tag *pTag, int16 csid ); CEditListElement(IStreamIn *pStreamIn, CEditBuffer *pBuffer); virtual ~CEditListElement(); /* Test if supplied element is a list of compatable type */ XP_Bool IsCompatableList(CEditElement *pElement); XP_Bool IsList(){ return TRUE; } static CEditListElement* Cast(CEditElement* pElement) { return pElement && pElement->IsList() ? (CEditListElement*) pElement : 0; } virtual PA_Tag* TagOpen( int iEditOffset ); virtual CEditElement* Clone( CEditElement *pParent = 0); static EDT_ListData* NewData(); static void FreeData( EDT_ListData *pData ); // Streaming virtual EEditElementType GetElementType(); // // Implementation // void SetData( EDT_ListData *pData ); EDT_ListData* GetData( ); static EDT_ListData* ParseParams( PA_Tag *pTag, int16 csid ); void CopyData(CEditListElement* pOther); XP_Bool IsMailQuote(); #ifdef DEBUG virtual void ValidateTree(); #endif }; // // CEditTextElement // class CEditTextElement: public CEditLeafElement { public: char* m_pText; // pointer to actual string. int m_textSize; // number of bytes allocated LO_Element* m_pFirstLayoutElement; LO_TextBlock* m_pTextBlock; ED_TextFormat m_tf; intn m_iFontSize; ED_Color m_color; ED_LinkId m_href; char* m_pFace; int16 m_iWeight; /* font weight range = 100-900, 400=Normal, 700=Bold*/ int16 m_iPointSize; /* not sure what default is! Use 0 to mean "default" */ char* m_pScriptExtra; //