From e34dd5c7c3fb9ed1ee02996cb2f0c92ec135e98b Mon Sep 17 00:00:00 2001 From: Jens-Heiner Rechtien Date: Fri, 23 Sep 2005 09:49:58 +0000 Subject: INTEGRATION: CWS impress49 (1.1.2); FILE ADDED 2005/07/15 13:43:53 cl 1.1.2.1: new ms storage viewer helper app --- svx/workben/msview/msview.cxx | 1267 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1267 insertions(+) create mode 100644 svx/workben/msview/msview.cxx (limited to 'svx/workben') diff --git a/svx/workben/msview/msview.cxx b/svx/workben/msview/msview.cxx new file mode 100644 index 000000000000..96dfbea1fc84 --- /dev/null +++ b/svx/workben/msview/msview.cxx @@ -0,0 +1,1267 @@ +/************************************************************************* + * + * $RCSfile: msview.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: hr $ $Date: 2005-09-23 10:49:58 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): _______________________________________ + * + * + ************************************************************************/ + +#include +#include +#include +#include + +#ifndef _SOT_STORAGE_HXX +#include +#endif +#ifndef _SVTOOLS_HRC +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef _FILEDLGHELPER_HXX +#include +#endif + +#include + +#include + +#ifndef _TOOLS_RESMGR_HXX +#include +#endif + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#ifndef _MSDFFDEF_HXX +#include "msdffdef.hxx" +#endif + +#include + +#include "xmlconfig.hxx" + +using ::rtl::OUString; + +using namespace ::com::sun::star; + +/////////////////////////////////////////////////////////////////////// + +enum CompareStatus { CMP_NOTYET = 0, CMP_EQUAL = 1, CMP_NOTEQUAL = 2, CMP_NOTAVAILABLE = 3 }; +static ColorData gColors[] = { COL_BLACK, COL_GREEN, COL_RED, COL_CYAN }; + +class Atom +{ +public: + ~Atom(); + + /** imports this atom and its child atoms */ + static Atom* import( const DffRecordHeader& rRootRecordHeader, SvStream& rStCtrl ); + static Atom* import( UINT16 nRecType, SvStream& rStCtrl ); + + inline const DffRecordHeader& getHeader() const; + + /** returns true if at least one atim with the given nRecType is found */ + inline bool hasChildAtom( sal_uInt16 nRecType ) const; + + /** returns true if at least one atim with the given nRecType and nRecInstnace is found */ + inline bool hasChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const; + + /** returns the first child atom with nRecType or NULL */ + inline const Atom* findFirstChildAtom( sal_uInt16 nRecType ) const; + + /** returns the next child atom after pLast with nRecType or NULL */ + const Atom* findNextChildAtom( sal_uInt16 nRecType, const Atom* pLast ) const; + + /** returns the first child atom with nRecType and nRecInstance or NULL */ + inline const Atom* findFirstChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const; + + /** returns the next child atom after pLast with nRecType and nRecInstance or NULL */ + const Atom* findNextChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance, const Atom* pLast ) const; + + /** returns the first child atom or NULL */ + inline const Atom* findFirstChildAtom() const; + + /** returns the next child atom after pLast or NULL */ + inline const Atom* findNextChildAtom( const Atom* pLast ) const; + + /** returns true if this atom is a container */ + inline bool isContainer() const; + + /** seeks to the contents of this atom */ + inline bool seekToContent() const; + + /** returns the record type */ + inline sal_uInt16 getType() const; + + /** returns the record instance */ + inline sal_uInt16 getInstance() const; + + /** returns the record length */ + inline sal_uInt32 getLength() const; + + SvStream& getStream() const { return mrStream; } + + bool operator==( const Atom& rAtom ) const; + + CompareStatus getCompareStatus() const { return meStatus; } + + void compare( Atom* pAtom ); + bool compareContent( Atom& rAtom ); + + Atom* getCompareAtom() const { return mpCompareAtom; } + void setCompareAtom( Atom* pAtom ) { mpCompareAtom = pAtom; } + +private: + Atom( const DffRecordHeader& rRecordHeader, SvStream& rStCtrl ); + + // statics for compare + static Atom* skipAtoms( Atom* pContainer, Atom* pAtom, Atom* pSkipTo ); + static Atom* findFirstEqualAtom( Atom* pCompare, Atom* pContainer, Atom* pSearch, int& nDistance ); + + SvStream& mrStream; + DffRecordHeader maRecordHeader; + Atom* mpFirstChild; + Atom* mpNextAtom; + + CompareStatus meStatus; + Atom* mpCompareAtom; +}; + +bool Atom::operator==( const Atom& rAtom ) const +{ + return ( maRecordHeader.nRecType == rAtom.maRecordHeader.nRecType ) && + ( maRecordHeader.nRecVer == rAtom.maRecordHeader.nRecVer ) && + ( maRecordHeader.nRecInstance == rAtom.maRecordHeader.nRecInstance ); +} + +bool Atom::compareContent( Atom& rAtom ) +{ + if( maRecordHeader.nRecLen == rAtom.maRecordHeader.nRecLen ) + { + seekToContent(); + rAtom.seekToContent(); + + SvStream& rStream1 = getStream(); + SvStream& rStream2 = rAtom.getStream(); + + const int nBufferSize = 1024; + boost::shared_ptr< char > buffer1( new char[nBufferSize] ); + boost::shared_ptr< char > buffer2( new char[nBufferSize] ); + + sal_uInt32 nLength = maRecordHeader.nRecLen; + sal_Size nRead = 0; + while( nLength ) + { + sal_Size nRead = (nBufferSize < nLength) ? nBufferSize : nLength; + nRead = rStream1.Read( (void*)buffer1.get(), nRead ); + if( nRead == 0 ) + break; + if( rStream2.Read( (void*)buffer2.get(), nRead ) != nRead ) + break; + if( memcmp( (void*)buffer1.get(), (void*)buffer2.get(), nRead ) != 0 ) + break; + + nLength -= nRead; + } + + return nLength == 0; + } + + return false; +} + +inline bool Atom::hasChildAtom( sal_uInt16 nRecType ) const +{ + return findFirstChildAtom( nRecType ) != NULL; +} + +inline bool Atom::hasChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const +{ + return findFirstChildAtom( nRecType, nRecInstance ) != NULL; +} + +inline const Atom* Atom::findFirstChildAtom( sal_uInt16 nRecType ) const +{ + return findNextChildAtom( nRecType, NULL ); +} + +inline const DffRecordHeader& Atom::getHeader() const +{ + return maRecordHeader; +} + +inline const Atom* Atom::findFirstChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const +{ + return findNextChildAtom( nRecType, nRecInstance, NULL ); +} + +inline const Atom* Atom::findFirstChildAtom() const +{ + return mpFirstChild; +} + +inline const Atom* Atom::findNextChildAtom( const Atom* pLast ) const +{ + return pLast ? pLast->mpNextAtom : pLast; +} + +inline bool Atom::isContainer() const +{ + return (bool)maRecordHeader.IsContainer(); +} + +inline bool Atom::seekToContent() const +{ + maRecordHeader.SeekToContent( mrStream ); + return mrStream.GetError() == 0; +} + +inline sal_uInt16 Atom::getType() const +{ + return maRecordHeader.nRecType; +} + +inline sal_uInt16 Atom::getInstance() const +{ + return maRecordHeader.nRecInstance; +} + +inline sal_uInt32 Atom::getLength() const +{ + return maRecordHeader.nRecLen; +} + +Atom::Atom( const DffRecordHeader& rRecordHeader, SvStream& rStream ) +: maRecordHeader( rRecordHeader ), + mrStream( rStream ), + mpFirstChild( 0 ), + mpNextAtom( 0 ), + meStatus( CMP_NOTYET ), + mpCompareAtom( 0 ) +{ + // check if we need to force this to a container + if( maRecordHeader.nRecVer != DFF_PSFLAG_CONTAINER ) + { + AtomConfig* pAtomConfig = dynamic_cast< AtomConfig* >( gAtomConfigMap[ maRecordHeader.nRecType ].get() ); + if( pAtomConfig && pAtomConfig->isContainer() ) + { + maRecordHeader.nRecVer = DFF_PSFLAG_CONTAINER; + } + } + + if( isContainer() ) + { + if( seekToContent() ) + { + DffRecordHeader aChildHeader; + + Atom* pLastAtom = NULL; + + while( (mrStream.GetError() == 0 ) && ( mrStream.Tell() < maRecordHeader.GetRecEndFilePos() ) ) + { + mrStream >> aChildHeader; + + if( mrStream.GetError() == 0 ) + { + Atom* pAtom = new Atom( aChildHeader, mrStream ); + + if( pLastAtom ) + pLastAtom->mpNextAtom = pAtom; + if( mpFirstChild == NULL ) + mpFirstChild = pAtom; + + pLastAtom = pAtom; + } + } + } + } + + maRecordHeader.SeekToEndOfRecord( mrStream ); +} + +Atom::~Atom() +{ + Atom* pChild = mpFirstChild; + while( pChild ) + { + Atom* pNextChild = pChild->mpNextAtom; + delete pChild; + pChild = pNextChild; + } +} + +/** imports this atom and its child atoms */ +Atom* Atom::import( const DffRecordHeader& rRootRecordHeader, SvStream& rStCtrl ) +{ + Atom* pRootAtom = new Atom( rRootRecordHeader, rStCtrl ); + + if( rStCtrl.GetError() == 0 ) + { + return pRootAtom; + } + else + { + delete pRootAtom; + return NULL; + } +} + +/** imports this atom and its child atoms */ +Atom* Atom::import( UINT16 nRecType, SvStream& rStCtrl ) +{ + rStCtrl.Seek( STREAM_SEEK_TO_END ); + sal_Size nStreamLength = rStCtrl.Tell(); + rStCtrl.Seek( STREAM_SEEK_TO_BEGIN ); + + DffRecordHeader aRootRecordHeader; + aRootRecordHeader.nRecVer = DFF_PSFLAG_CONTAINER; + aRootRecordHeader.nRecInstance = 0; + aRootRecordHeader.nImpVerInst = 0; + aRootRecordHeader.nRecType = nRecType; + aRootRecordHeader.nRecLen = nStreamLength; + aRootRecordHeader.nFilePos = 0; + + return import( aRootRecordHeader, rStCtrl ); +} + +/** returns the next child atom after pLast with nRecType or NULL */ +const Atom* Atom::findNextChildAtom( sal_uInt16 nRecType, const Atom* pLast ) const +{ + Atom* pChild = pLast != NULL ? pLast->mpNextAtom : mpFirstChild; + while( pChild && pChild->maRecordHeader.nRecType != nRecType ) + { + pChild = pChild->mpNextAtom; + } + + return pChild; +} + +/** returns the next child atom after pLast with nRecType and nRecInstance or NULL */ +const Atom* Atom::findNextChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance, const Atom* pLast ) const +{ + const Atom* pChild = pLast != NULL ? pLast->mpNextAtom : mpFirstChild; + while( pChild && (pChild->maRecordHeader.nRecType != nRecType) && (pChild->maRecordHeader.nRecInstance != nRecInstance) ) + { + pChild = findNextChildAtom( pChild ); + } + + return pChild; +} + +Atom* Atom::findFirstEqualAtom( Atom* pCompare, Atom* pContainer, Atom* pSearch, int& nDistance ) +{ + nDistance = 0; + Atom* pRet = 0; + + while( pSearch ) + { + if( *pSearch == *pCompare ) + return pSearch; + + pSearch = const_cast< Atom* >( pContainer->findNextChildAtom( pSearch ) ); + nDistance++; + } + + return 0; +} + +Atom* Atom::skipAtoms( Atom* pContainer, Atom* pAtom, Atom* pSkipTo ) +{ + while( pAtom && (pAtom != pSkipTo) ) + { + pAtom->meStatus = CMP_NOTAVAILABLE; + pAtom = const_cast< Atom* >( pContainer->findNextChildAtom( pAtom ) ); + } + + return pAtom; +} + +void Atom::compare( Atom* pAtom ) +{ + if( pAtom ) + { + if( meStatus == CMP_NOTYET ) + { + mpCompareAtom = pAtom; + pAtom->mpCompareAtom = this; + + mpCompareAtom = pAtom; + pAtom->mpCompareAtom = this; + + meStatus = pAtom->meStatus = ( *this == *pAtom ) ? CMP_EQUAL : CMP_NOTEQUAL; + } + + if(meStatus == CMP_EQUAL) + { + if( isContainer() ) + { + /** returns the first child atom or NULL */ + Atom* pChildAtom1 = const_cast< Atom* >( findFirstChildAtom() ); + + if( pChildAtom1 && (pChildAtom1->meStatus == CMP_NOTYET) ) + { + Atom* pChildAtom2 = const_cast< Atom* >( pAtom->findFirstChildAtom() ); + while( pChildAtom1 && pChildAtom2 ) + { + if( !(*pChildAtom1 == *pChildAtom2) ) + { + int nDistance1; + int nDistance2; + + Atom* pFind1 = findFirstEqualAtom( pChildAtom1, pAtom, const_cast< Atom* >( pAtom->findNextChildAtom( pChildAtom2 )), nDistance1 ); + Atom* pFind2 = findFirstEqualAtom( pChildAtom2, this, const_cast< Atom* >(findNextChildAtom( pChildAtom1 )), nDistance2 ); + + if( pFind1 && (!pFind2 || (nDistance1 < nDistance2) ) ) + { + pChildAtom2 = skipAtoms( pAtom, pChildAtom2, pFind1 ); + } + else if( pFind2 ) + { + pChildAtom1 = skipAtoms( this, pChildAtom1, pFind2 ); + } + else + { + pChildAtom1 = skipAtoms( this, pChildAtom1, 0 ); + pChildAtom2 = skipAtoms( pAtom, pChildAtom2, 0 ); + } + } + + if( pChildAtom1 && pChildAtom2 ) + { + pChildAtom1->mpCompareAtom = pChildAtom2; + pChildAtom2->mpCompareAtom = pChildAtom1; + + pChildAtom1->meStatus = pChildAtom2->meStatus = + (pChildAtom1->isContainer() || pChildAtom1->compareContent( *pChildAtom2 )) ? + CMP_EQUAL : CMP_NOTEQUAL; + + pChildAtom1 = const_cast< Atom* >( findNextChildAtom( pChildAtom1 ) ); + pChildAtom2 = const_cast< Atom* >( pAtom->findNextChildAtom( pChildAtom2 ) ); + } + } + } + } + else + { + if( !compareContent( *pAtom ) ) + { + meStatus = pAtom->meStatus = CMP_NOTEQUAL; + } + } + } + } +} + +////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////// + +class AtomBoxString : public SvLBoxString +{ +public: + AtomBoxString( SvLBoxEntry* pEntry, const String& rStr ) + : SvLBoxString( pEntry, 0, rStr ) + { } + + ~AtomBoxString() { } + + void Paint( const Point& rPos, SvLBox& rOutDev, USHORT nViewDataEntryFlags, SvLBoxEntry* pEntry ) + { + Color aOldTextColor = rOutDev.GetTextColor(); + + if( pEntry && pEntry->GetUserData() ) + { + Atom* pAtom = static_cast( pEntry->GetUserData() ); + rOutDev.SetTextColor( Color( gColors[ pAtom->getCompareStatus() ] ) ); + } + + SvLBoxString::Paint( rPos, rOutDev, nViewDataEntryFlags, pEntry ); + + rOutDev.SetTextColor( aOldTextColor ); + +/* + Color aOldFillColor = rOutDev.GetFillColor(); + + SvTreeListBox* pTreeBox = static_cast< SvTreeListBox* >( &rOutDev ); + long nX = pTreeBox->GetSizePixel().Width(); + + ScrollBar* pVScroll = pTreeBox->GetVScroll(); + if ( pVScroll->IsVisible() ) + { + nX -= pVScroll->GetSizePixel().Width(); + } + + SvViewDataItem* pItem = rOutDev.GetViewDataItem( pEntry, this ); + nX -= pItem->aSize.Height(); + + long nSize = pItem->aSize.Height() / 2; + long nHalfSize = nSize / 2; + long nY = rPos.Y() + nHalfSize; + + if ( aOldFillColor == COL_WHITE ) + { + rOutDev.SetFillColor( Color( COL_BLACK ) ); + } + else + { + rOutDev.SetFillColor( Color( COL_WHITE ) ); + } + + long n = 0; + while ( n <= nHalfSize ) + { + rOutDev.DrawRect( Rectangle( nX+n, nY+n, nX+n, nY+nSize-n ) ); + n++; + } + + rOutDev.SetFillColor( aOldFillColor ); +*/ + } + +private: + Image* mpImage; +}; + + +////////////////////////////////////////////////////////////////////// + +class AtomContainerTreeListBox : public SvTreeListBox +{ +public: + AtomContainerTreeListBox( Window* pParent ); + ~AtomContainerTreeListBox(); + + void SetRootAtom( const Atom* pAtom ); + + + void SetCollapsingHdl(const Link& rNewHdl){maCollapsingHdl=rNewHdl;} + const Link& GetCollapsingHdl() const { return maCollapsingHdl; } + + void SetExpandingHdl(const Link& rNewHdl){maExpandingHdl=rNewHdl;} + const Link& GetExpandingHdl() const { return maExpandingHdl; } + + virtual BOOL Expand( SvLBoxEntry* pParent ); + virtual BOOL Collapse( SvLBoxEntry* pParent ); + + SvLBoxEntry* findAtom( Atom* pAtom ); + + virtual void InitEntry(SvLBoxEntry*,const XubString&,const Image&,const Image&); + virtual void SetTabs(); + +private: + void InsertAtom( const Atom* pAtom, SvLBoxEntry* pParent = 0 ); + const Atom* mpRootAtom; + ResMgr* mpResMgr; + Image maImgFolder; + Image maImgAtom; + Image maImgExpanded; + Image maImgCollapsed; + bool mbRecursiveGuard; + Link maCollapsingHdl; + Link maExpandingHdl; +}; + +typedef std::pair< AtomContainerTreeListBox*, SvLBoxEntry* > AtomContainerEntryPair; + +AtomContainerTreeListBox::AtomContainerTreeListBox( Window* pParent ) +: SvTreeListBox( pParent, WB_HASBUTTONS|WB_HASLINES|WB_HASBUTTONSATROOT|WB_3DLOOK|WB_BORDER ), + mpRootAtom( 0 ), mbRecursiveGuard( false ) +{ + mpResMgr = ResMgr::CreateResMgr( "svt" ); + maImgCollapsed = Image( ResId( RID_IMG_TREENODE_COLLAPSED, mpResMgr ) ); + maImgExpanded = Image( ResId( RID_IMG_TREENODE_EXPANDED, mpResMgr ) ); + +// SetDefaultExpandedEntryBmp( aExpanded ); +// SetDefaultCollapsedEntryBmp(aCollapsed ); + + maImgFolder = Image( ResId( IMG_SVT_FOLDER, mpResMgr ) ); + maImgAtom = Image( ResId( IMG_SVT_DOCTEMPLATE_DOCINFO_SMALL, mpResMgr ) ); +} + +AtomContainerTreeListBox::~AtomContainerTreeListBox() +{ +} + +void AtomContainerTreeListBox::SetTabs() +{ + if( IsEditingActive() ) + EndEditing( TRUE ); + + ClearTabList(); + + short nIndent = 0; GetIndent(); + long nNodeWidthPixel = maImgCollapsed.GetSizePixel().Width(); + long nContextWidthDIV2 = nNodeWidthPixel >> 1; + + long nStartPos = 2 + ( nIndent + nContextWidthDIV2 ); + AddTab( nStartPos, SV_LBOXTAB_DYNAMIC | SV_LBOXTAB_ADJUST_CENTER ); + nStartPos += nNodeWidthPixel + 5; + AddTab( nStartPos, SV_LBOXTAB_DYNAMIC | SV_LBOXTAB_ADJUST_CENTER | SV_LBOXTAB_SHOW_SELECTION ); + nStartPos += nContextWidthDIV2 + 5; + AddTab( nStartPos, SV_LBOXTAB_DYNAMIC|SV_LBOXTAB_ADJUST_LEFT | SV_LBOXTAB_SHOW_SELECTION ); +} + +void AtomContainerTreeListBox::InitEntry(SvLBoxEntry* pEntry,const XubString& aStr,const Image& aCollEntryBmp,const Image& aExpEntryBmp) +{ + pEntry->AddItem( new SvLBoxContextBmp( pEntry,0, aCollEntryBmp,aExpEntryBmp, SVLISTENTRYFLAG_EXPANDED ) ); + pEntry->AddItem( new SvLBoxContextBmp( pEntry,0, maImgAtom, maImgAtom, SVLISTENTRYFLAG_EXPANDED ) ); + pEntry->AddItem( new AtomBoxString( pEntry, aStr ) ); +} + +SvLBoxEntry* AtomContainerTreeListBox::findAtom( Atom* pAtom ) +{ + SvLBoxEntry* pEntry = First(); + while( pEntry ) + { + if( pEntry->GetUserData() == pAtom ) + return pEntry; + + pEntry = Next( pEntry ); + } + + return 0; +} + +BOOL AtomContainerTreeListBox::Expand( SvLBoxEntry* pParent ) +{ + BOOL bRet = FALSE; + if( !mbRecursiveGuard ) + { + mbRecursiveGuard = true; + AtomContainerEntryPair aPair( this, pParent ); + maExpandingHdl.Call( &aPair); + + bRet = SvTreeListBox::Expand( pParent ); + mbRecursiveGuard = false; + } + return bRet; +} + +BOOL AtomContainerTreeListBox::Collapse( SvLBoxEntry* pParent ) +{ + BOOL bRet = FALSE; + if( !mbRecursiveGuard ) + { + mbRecursiveGuard = true; + AtomContainerEntryPair aPair( this, pParent ); + maCollapsingHdl.Call( &aPair); + + bRet = SvTreeListBox::Collapse( pParent ); + mbRecursiveGuard = false; + } + return bRet; +} + +void AtomContainerTreeListBox::SetRootAtom( const Atom* pAtom ) +{ + mpRootAtom = pAtom; + InsertAtom( mpRootAtom ); +} + +void AtomContainerTreeListBox::InsertAtom( const Atom* pAtom, SvLBoxEntry* pParent /* = 0 */ ) +{ + if( pAtom ) + { + const DffRecordHeader& rHeader = pAtom->getHeader(); + + char buffer[1024]; + + rtl::OUString aText; + AtomConfig* pAtomConfig = dynamic_cast< AtomConfig*>( gAtomConfigMap[rHeader.nRecType].get() ); + + if( pAtomConfig ) + aText = pAtomConfig->getName(); + + if( !aText.getLength() ) + { + sprintf( buffer, "unknown_0x%04x", rHeader.nRecType ); + aText += rtl::OUString::createFromAscii( buffer ); + } + + sprintf( buffer, " (I: %lu L: %lu)", (UINT32)rHeader.nRecVer, (UINT32)rHeader.nRecLen ); + aText += String( rtl::OUString::createFromAscii( buffer ) ); + + SvLBoxEntry* pEntry = 0; + if( pAtom->isContainer() && pAtom->findFirstChildAtom() ) + { + pEntry = InsertEntry( aText, maImgExpanded, maImgCollapsed, pParent ); + + /** returns the first child atom or NULL */ + const Atom* pChildAtom = pAtom->findFirstChildAtom(); + + while( pChildAtom ) + { + InsertAtom( pChildAtom, pEntry ); + pChildAtom = pAtom->findNextChildAtom( pChildAtom ); + } + } + else + { + pEntry = InsertEntry( aText, pParent ); + } + + if( pEntry ) + { + pEntry->SetUserData( (void*)pAtom ); + + if( pAtom->isContainer() ) + { + SvLBoxContextBmp* pBoxBmp = dynamic_cast< SvLBoxContextBmp* >( pEntry->GetItem( pEntry->ItemCount() - 2 ) ); + if( pBoxBmp ) + { + pBoxBmp->SetBitmap1( pEntry, maImgFolder ); + pBoxBmp->SetBitmap2( pEntry, maImgFolder ); + } + } + +/* + pEntry->ReplaceItem( + new AtomBoxString( pEntry, aText, pImage ), + pEntry->ItemCount() - 1 ); +*/ + } + } +} + +/////////////////////////////////////////////////////////////////////// + +extern void load_config( const OUString& rPath ); + +class PPTDocument +{ +public: + PPTDocument( const rtl::OUString& rFilePath ); + ~PPTDocument(); + + Atom* getRootAtom() const; + +private: + void Load( const rtl::OUString& rFilePath ); + + Atom* mpAtom; + SvStream* mpDocStream; + SotStorageRef maStorage; +}; + +typedef boost::shared_ptr< PPTDocument > PPTDocumentPtr; + +PPTDocument::PPTDocument(const rtl::OUString& rFilePath) +: mpAtom(0), mpDocStream(0) +{ + Load( rFilePath ); +} + +PPTDocument::~PPTDocument() +{ + delete mpAtom; + delete mpDocStream; +} + +void PPTDocument::Load( const rtl::OUString& rFilePath ) +{ + maStorage = new SotStorage( rFilePath, STREAM_STD_READ ); + if( !maStorage->GetError() ) + { + mpDocStream = maStorage->OpenSotStream( String( RTL_CONSTASCII_USTRINGPARAM("PowerPoint Document") ), STREAM_STD_READ ); + if( mpDocStream ) + { + DffRecordHeader aRecordHeader; + *mpDocStream >> aRecordHeader; + + mpAtom = Atom::import( 65530, *mpDocStream ); + } + } +} + +Atom* PPTDocument::getRootAtom() const +{ + return mpAtom; +} + +/////////////////////////////////////////////////////////////////////// + +class MSViewerWorkWindow : public WorkWindow +{ +public: + MSViewerWorkWindow(); + ~MSViewerWorkWindow(); + + PPTDocumentPtr Load(); + void onView(); + void onCompare(); + void onClose(); + + void View( const PPTDocumentPtr& pDocument, int nPane ); + void Compare( const PPTDocumentPtr& pDocument1, const PPTDocumentPtr& pDocument2 ); + + virtual void Resize(); + +private: + void Sync( AtomContainerEntryPair* pPair, int nAction ); + + AtomContainerTreeListBox* mpListBox[2]; + MultiLineEdit* mpEdit[2]; + PPTDocumentPtr mpDocument[2]; + MenuBar* mpMenuBar; + PopupMenu* mpFileMenu; + bool mbSelectHdlGuard; + DECL_LINK( implSelectHdl, AtomContainerTreeListBox* ); + DECL_LINK( implExpandingHdl, AtomContainerEntryPair* ); + DECL_LINK( implCollapsingHdl, AtomContainerEntryPair* ); + DECL_LINK( implMenuHdl, Menu* ); +}; + +// ----------------------------------------------------------------------- + +void MSViewerWorkWindow::onView() +{ + PPTDocumentPtr pDocument( Load() ); + if( pDocument.get() ) + { + onClose(); + View( pDocument, 0 ); + } +} + +void MSViewerWorkWindow::onClose() +{ +} + +void MSViewerWorkWindow::onCompare() +{ + PPTDocumentPtr pDocument1( Load() ); + if( pDocument1.get() ) + { + PPTDocumentPtr pDocument2( Load() ); + if( pDocument2.get() ) + { + onClose(); + Compare( pDocument1, pDocument2 ); + } + } +} + +void MSViewerWorkWindow::Compare( const PPTDocumentPtr& pDocument1, const PPTDocumentPtr& pDocument2 ) +{ + if( pDocument1.get() && pDocument2.get() ) + { + Atom* pAtom1 = pDocument1->getRootAtom(); + Atom* pAtom2 = pDocument2->getRootAtom(); + pAtom1->setCompareAtom( pAtom2 ); + pAtom2->setCompareAtom( pAtom1 ); + } + + View( pDocument1, 0 ); + View( pDocument2, 1 ); +} + +void MSViewerWorkWindow::View( const PPTDocumentPtr& pDocument, int nPane ) +{ + if( ((nPane != 0) && (nPane != 1)) || (pDocument.get() == 0) ) + return; + + mpDocument[nPane] = pDocument; + + mpListBox[nPane]->SetRootAtom( pDocument->getRootAtom() ); + mpListBox[nPane]->Expand( mpListBox[nPane]->GetEntry(0) ); + mpListBox[nPane]->Show(); + mpEdit[nPane]->Show(); + Resize(); +} + + +PPTDocumentPtr MSViewerWorkWindow::Load() +{ + ::sfx2::FileDialogHelper aDlg( ::sfx2::FILEOPEN_SIMPLE, 0 ); + String aStrFilterType( RTL_CONSTASCII_USTRINGPARAM( "*.ppt" ) ); + aDlg.AddFilter( aStrFilterType, aStrFilterType ); +// INetURLObject aFile( SvtPathOptions().GetPalettePath() ); +// aDlg.SetDisplayDirectory( aFile.GetMainURL( INetURLObject::NO_DECODE ) ); + + PPTDocumentPtr pDocument; + if ( aDlg.Execute() == ERRCODE_NONE ) + { + pDocument.reset( new PPTDocument( aDlg.GetPath() ) ); + } + + return pDocument; +} + +// ----------------------------------------------------------------------- + +MSViewerWorkWindow::MSViewerWorkWindow() : + WorkWindow( 0, WB_APP | WB_STDWORK | WB_3DLOOK ),mbSelectHdlGuard(false) +{ + Size aOutputSize( 400, 600 ); + SetOutputSizePixel( aOutputSize ); + SetText( String( RTL_CONSTASCII_USTRINGPARAM( "MSViewer" ) ) ); + + Size aOutSize( GetOutputSizePixel() ); + + Font aFont( String( RTL_CONSTASCII_USTRINGPARAM( "Courier" ) ), GetFont().GetSize() ); + + mpMenuBar = new MenuBar(); + mpMenuBar->InsertItem( 1, String( RTL_CONSTASCII_USTRINGPARAM("~File" ) ) ); + mpFileMenu = new PopupMenu(); + mpFileMenu->InsertItem( 2, String( RTL_CONSTASCII_USTRINGPARAM("~View" ) ) ); + mpFileMenu->InsertItem( 3, String( RTL_CONSTASCII_USTRINGPARAM("~Compare" ) ) ); + mpFileMenu->InsertSeparator(); + mpFileMenu->InsertItem( 4, String( RTL_CONSTASCII_USTRINGPARAM("~Quit" ) ) ); + mpFileMenu->SetSelectHdl( LINK( this, MSViewerWorkWindow, implMenuHdl ) ); + + mpMenuBar->SetPopupMenu( 1, mpFileMenu ); + SetMenuBar( mpMenuBar ); + int nPane; + for( nPane = 0; nPane < 2; nPane++ ) + { + mpListBox[nPane] = new AtomContainerTreeListBox( this ); + mpListBox[nPane]->SetSelectHdl( LINK( this, MSViewerWorkWindow, implSelectHdl ) ); + mpListBox[nPane]->SetExpandingHdl( LINK( this, MSViewerWorkWindow, implExpandingHdl ) ); + mpListBox[nPane]->SetCollapsingHdl( LINK( this, MSViewerWorkWindow, implCollapsingHdl ) ); + + mpEdit[nPane] = new MultiLineEdit(this, WB_3DLOOK | WB_BORDER | WB_LEFT | WB_TOP | WB_READONLY | WB_HSCROLL | WB_VSCROLL ); + mpEdit[nPane]->SetReadOnly( TRUE ); + mpEdit[nPane]->SetReadOnly( TRUE ); + mpEdit[nPane]->SetControlFont( aFont ); + } +} + +// ----------------------------------------------------------------------- + +static String GetAtomText( const Atom* pAtom ) +{ + String aText; + if( pAtom ) + { + const DffRecordHeader& rHeader = pAtom->getHeader(); + char buffer[512]; + sprintf( buffer, "Version = %lu\n\rInstance = %lu\n\rVersionInstance = %lu\n\rLength = %lu\n\r", + (UINT32)rHeader.nRecVer, + (UINT32)rHeader.nRecInstance, + (UINT32)rHeader.nImpVerInst, + (UINT32)rHeader.nRecLen ); + aText = rtl::OUString::createFromAscii( buffer ); + if( pAtom->isContainer() ) + { + + } + else + { + pAtom->seekToContent(); + AtomConfig* pAtomConfig = dynamic_cast< AtomConfig* >( gAtomConfigMap[pAtom->getType()].get() ); + if( pAtomConfig ) + { + sal_Size nLength = pAtom->getLength(); + aText += String( pAtomConfig->format( pAtom->getStream(), nLength ) ); + } + else + { + sal_Size nLength = pAtom->getLength(); + aText += String( ElementConfig::dump_hex( pAtom->getStream(), nLength ) ); + } + } + } + + return aText; +} + +IMPL_LINK(MSViewerWorkWindow,implSelectHdl, AtomContainerTreeListBox*, pListBox ) +{ + int nPane = (pListBox == mpListBox[1]) ? 1 : 0; + SvLBoxEntry* pEntry = mpListBox[nPane]->FirstSelected(); + if( pEntry && pEntry->GetUserData() ) + { + Atom* pAtom = static_cast( pEntry->GetUserData() ); + mpEdit[nPane]->SetText( GetAtomText( pAtom ) ); + + if(!mbSelectHdlGuard) + { + mbSelectHdlGuard = true; + // select other + AtomContainerEntryPair aPair( pListBox, pEntry ); + Sync( &aPair, 2 ); + mbSelectHdlGuard = false; + } + } + return 0; +} + +void MSViewerWorkWindow::Sync( AtomContainerEntryPair* pPair, int nAction ) +{ + if( mpDocument[0].get() && mpDocument[1].get() && pPair->first && pPair->second ) + { + AtomContainerTreeListBox* pDestinationListBox = (pPair->first == mpListBox[0]) ? mpListBox[1] : mpListBox[0]; + + Atom* pAtom = static_cast(pPair->second->GetUserData()); + if( pAtom && pAtom->getCompareAtom() ) + { + SvLBoxEntry* pEntry = pDestinationListBox->findAtom( pAtom->getCompareAtom() ); + + if(pEntry ) + { + if( nAction == 0 ) + { + pDestinationListBox->Expand( pEntry ); + } + else if( nAction == 1 ) + { + pDestinationListBox->Collapse( pEntry ); + } + else + { + pDestinationListBox->Select( pEntry ); + } + } + } + } +} + +IMPL_LINK(MSViewerWorkWindow, implExpandingHdl, AtomContainerEntryPair*, pPair ) +{ + SvLBoxEntry* pEntry = pPair->second; + if( pEntry && pEntry->GetUserData() ) + { + Atom* pAtom = static_cast( pEntry->GetUserData() ); + pAtom->compare( pAtom->getCompareAtom() ); + } + + Sync( pPair, 0 ); + + return 0; +} + +IMPL_LINK(MSViewerWorkWindow, implCollapsingHdl, AtomContainerEntryPair*, pPair ) +{ + Sync( pPair, 1 ); + + return 0; +} + +IMPL_LINK( MSViewerWorkWindow, implMenuHdl, Menu*, pMenu ) +{ + if( pMenu ) + { + USHORT nId = pMenu->GetCurItemId(); + switch( nId ) + { + case 2: onView(); break; + case 3: onCompare(); break; + case 4: Application::Quit(); break; + } + } + return 0; +} + +// ----------------------------------------------------------------------- + +MSViewerWorkWindow::~MSViewerWorkWindow() +{ + int nPane; + for( nPane = 0; nPane < 2; nPane++ ) + { + delete mpListBox[nPane]; + delete mpEdit[nPane]; + } + + delete mpFileMenu; + delete mpMenuBar; +} + +// ----------------------------------------------------------------------- + +void MSViewerWorkWindow::Resize() +{ + int nPaneCount = ((mpDocument[0].get() != 0) ? 1 : 0) + ((mpDocument[1].get() != 0) ? 1 : 0); + + Size aOutputSize( GetOutputSizePixel() ); + int nHeight = aOutputSize.Height() >> 1; + if( nPaneCount ) + { + int nWidth = aOutputSize.Width(); + if( nPaneCount == 2 ) + nWidth >>= 1; + + int nPosX = 0; + + int nPane; + for( nPane = 0; nPane < 2; nPane++ ) + { + mpListBox[nPane]->SetPosSizePixel( nPosX,0, nWidth, nHeight ); + mpEdit[nPane]->SetPosSizePixel( nPosX, nHeight, nWidth, aOutputSize.Height() - nHeight ); + nPosX += nWidth; + } + } +} + +// ----------------------------------------------------------------------- + +// ----------------------------------------------------------------------- + + SAL_IMPLEMENT_MAIN() +{ + if( argc > 3 ) + return 0; + + uno::Reference< lang::XMultiServiceFactory > xMSF; + try + { + uno::Reference< uno::XComponentContext > xCtx( cppu::defaultBootstrap_InitialComponentContext() ); + if ( !xCtx.is() ) + { + DBG_ERROR( "Error creating initial component context!" ); + return -1; + } + + xMSF = uno::Reference< lang::XMultiServiceFactory >(xCtx->getServiceManager(), uno::UNO_QUERY ); + + if ( !xMSF.is() ) + { + DBG_ERROR( "No service manager!" ); + return -1; + } + + // Init UCB + uno::Sequence< uno::Any > aArgs( 2 ); + aArgs[ 0 ] <<= rtl::OUString::createFromAscii( UCB_CONFIGURATION_KEY1_LOCAL ); + aArgs[ 1 ] <<= rtl::OUString::createFromAscii( UCB_CONFIGURATION_KEY2_OFFICE ); + sal_Bool bSuccess = ::ucb::ContentBroker::initialize( xMSF, aArgs ); + if ( !bSuccess ) + { + DBG_ERROR( "Error creating UCB!" ); + return -1; + } + + } + catch ( uno::Exception const & ) + { + DBG_ERROR( "Exception during creation of initial component context!" ); + return -1; + } + comphelper::setProcessServiceFactory( xMSF ); + + InitVCL( xMSF ); + + String aConfigURL; + if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( Application::GetAppFileName(), aConfigURL ) ) + { + INetURLObject aURL( aConfigURL ); + + aURL.removeSegment(); + aURL.removeFinalSlash(); + aURL.Append( String( RTL_CONSTASCII_USTRINGPARAM( "msview.xml" ) ) ); + + load_config( aURL.GetMainURL( INetURLObject::NO_DECODE ) ); + } + + { + MSViewerWorkWindow aMainWindow; + + if( argc >= 2 ) + { + const rtl::OUString aFile1( rtl::OUString::createFromAscii(argv[1]) ); + PPTDocumentPtr pDocument1( new PPTDocument( aFile1 ) ); + + if( argc == 3 ) + { + const rtl::OUString aFile2( rtl::OUString::createFromAscii(argv[2]) ); + + PPTDocumentPtr pDocument2; + pDocument2.reset( new PPTDocument( aFile2 ) ); + aMainWindow.Compare( pDocument1, pDocument2 ); + } + else + { + aMainWindow.View( pDocument1, 0 ); + } + } + + aMainWindow.Show(); + + Application::Execute(); + } + + DeInitVCL(); + + return 0; +} \ No newline at end of file -- cgit