update dev300-m58
[ooovba.git] / svx / workben / msview / msview.cxx
blob7e6cf43cff4a1c5dcc8cddffa0400ad803180670
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: msview.cxx,v $
10 * $Revision: 1.6 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include <vector>
35 #include <map>
36 #include <algorithm>
37 #include <boost/shared_ptr.hpp>
38 #include <sot/storage.hxx>
39 #ifndef _SVTOOLS_HRC
40 #include <svtools/svtools.hrc>
41 #endif
43 #include <sal/main.h>
44 #include <vcl/event.hxx>
45 #include <vcl/svapp.hxx>
46 #include <vcl/wrkwin.hxx>
47 #include <vcl/msgbox.hxx>
48 #include <vcl/fixed.hxx>
49 #include <vcl/edit.hxx>
50 #include <vcl/button.hxx>
51 #include <vcl/lstbox.hxx>
52 #include <svtools/filectrl.hxx>
53 #include <tools/urlobj.hxx>
54 #include <osl/file.hxx>
55 #include <vcl/unohelp2.hxx>
56 #include <svtools/svtreebx.hxx>
57 #include <svtools/svmedit.hxx>
58 #include <sfx2/filedlghelper.hxx>
60 #include <toolkit/unohlp.hxx>
62 #include <tools/stream.hxx>
63 #include <tools/resmgr.hxx>
65 #include <comphelper/processfactory.hxx>
66 #include <cppuhelper/servicefactory.hxx>
67 #include <cppuhelper/bootstrap.hxx>
69 #include <ucbhelper/contentbroker.hxx>
70 #include <ucbhelper/configurationkeys.hxx>
72 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
74 #include <com/sun/star/awt/XWindowPeer.hpp>
75 #include <com/sun/star/awt/XToolkit.hpp>
76 #include <com/sun/star/awt/WindowDescriptor.hpp>
77 #include <com/sun/star/awt/WindowAttribute.hpp>
78 #include <svx/msdffdef.hxx>
80 #include <unotools/localfilehelper.hxx>
82 #include "xmlconfig.hxx"
84 using ::rtl::OUString;
86 using namespace ::com::sun::star;
88 ///////////////////////////////////////////////////////////////////////
90 enum CompareStatus { CMP_NOTYET = 0, CMP_EQUAL = 1, CMP_NOTEQUAL = 2, CMP_NOTAVAILABLE = 3 };
91 static ColorData gColors[] = { COL_BLACK, COL_GREEN, COL_RED, COL_CYAN };
93 class Atom
95 public:
96 ~Atom();
98 /** imports this atom and its child atoms */
99 static Atom* import( const DffRecordHeader& rRootRecordHeader, SvStream& rStCtrl );
100 static Atom* import( UINT16 nRecType, SvStream& rStCtrl );
102 inline const DffRecordHeader& getHeader() const;
104 /** returns true if at least one atim with the given nRecType is found */
105 inline bool hasChildAtom( sal_uInt16 nRecType ) const;
107 /** returns true if at least one atim with the given nRecType and nRecInstnace is found */
108 inline bool hasChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const;
110 /** returns the first child atom with nRecType or NULL */
111 inline const Atom* findFirstChildAtom( sal_uInt16 nRecType ) const;
113 /** returns the next child atom after pLast with nRecType or NULL */
114 const Atom* findNextChildAtom( sal_uInt16 nRecType, const Atom* pLast ) const;
116 /** returns the first child atom with nRecType and nRecInstance or NULL */
117 inline const Atom* findFirstChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const;
119 /** returns the next child atom after pLast with nRecType and nRecInstance or NULL */
120 const Atom* findNextChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance, const Atom* pLast ) const;
122 /** returns the first child atom or NULL */
123 inline const Atom* findFirstChildAtom() const;
125 /** returns the next child atom after pLast or NULL */
126 inline const Atom* findNextChildAtom( const Atom* pLast ) const;
128 /** returns true if this atom is a container */
129 inline bool isContainer() const;
131 /** seeks to the contents of this atom */
132 inline bool seekToContent() const;
134 /** returns the record type */
135 inline sal_uInt16 getType() const;
137 /** returns the record instance */
138 inline sal_uInt16 getInstance() const;
140 /** returns the record length */
141 inline sal_uInt32 getLength() const;
143 SvStream& getStream() const { return mrStream; }
145 bool operator==( const Atom& rAtom ) const;
147 CompareStatus getCompareStatus() const { return meStatus; }
149 void compare( Atom* pAtom );
150 bool compareContent( Atom& rAtom );
152 Atom* getCompareAtom() const { return mpCompareAtom; }
153 void setCompareAtom( Atom* pAtom ) { mpCompareAtom = pAtom; }
155 private:
156 Atom( const DffRecordHeader& rRecordHeader, SvStream& rStCtrl );
158 // statics for compare
159 static Atom* skipAtoms( Atom* pContainer, Atom* pAtom, Atom* pSkipTo );
160 static Atom* findFirstEqualAtom( Atom* pCompare, Atom* pContainer, Atom* pSearch, int& nDistance );
162 SvStream& mrStream;
163 DffRecordHeader maRecordHeader;
164 Atom* mpFirstChild;
165 Atom* mpNextAtom;
167 CompareStatus meStatus;
168 Atom* mpCompareAtom;
171 bool Atom::operator==( const Atom& rAtom ) const
173 return ( maRecordHeader.nRecType == rAtom.maRecordHeader.nRecType ) &&
174 ( maRecordHeader.nRecVer == rAtom.maRecordHeader.nRecVer ) &&
175 ( maRecordHeader.nRecInstance == rAtom.maRecordHeader.nRecInstance );
178 bool Atom::compareContent( Atom& rAtom )
180 if( maRecordHeader.nRecLen == rAtom.maRecordHeader.nRecLen )
182 seekToContent();
183 rAtom.seekToContent();
185 SvStream& rStream1 = getStream();
186 SvStream& rStream2 = rAtom.getStream();
188 const int nBufferSize = 1024;
189 boost::shared_ptr< char > buffer1( new char[nBufferSize] );
190 boost::shared_ptr< char > buffer2( new char[nBufferSize] );
192 sal_uInt32 nLength = maRecordHeader.nRecLen;
193 sal_Size nRead = 0;
194 while( nLength )
196 sal_Size nRead = (nBufferSize < nLength) ? nBufferSize : nLength;
197 nRead = rStream1.Read( (void*)buffer1.get(), nRead );
198 if( nRead == 0 )
199 break;
200 if( rStream2.Read( (void*)buffer2.get(), nRead ) != nRead )
201 break;
202 if( memcmp( (void*)buffer1.get(), (void*)buffer2.get(), nRead ) != 0 )
203 break;
205 nLength -= nRead;
208 return nLength == 0;
211 return false;
214 inline bool Atom::hasChildAtom( sal_uInt16 nRecType ) const
216 return findFirstChildAtom( nRecType ) != NULL;
219 inline bool Atom::hasChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const
221 return findFirstChildAtom( nRecType, nRecInstance ) != NULL;
224 inline const Atom* Atom::findFirstChildAtom( sal_uInt16 nRecType ) const
226 return findNextChildAtom( nRecType, NULL );
229 inline const DffRecordHeader& Atom::getHeader() const
231 return maRecordHeader;
234 inline const Atom* Atom::findFirstChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const
236 return findNextChildAtom( nRecType, nRecInstance, NULL );
239 inline const Atom* Atom::findFirstChildAtom() const
241 return mpFirstChild;
244 inline const Atom* Atom::findNextChildAtom( const Atom* pLast ) const
246 return pLast ? pLast->mpNextAtom : pLast;
249 inline bool Atom::isContainer() const
251 return (bool)maRecordHeader.IsContainer();
254 inline bool Atom::seekToContent() const
256 maRecordHeader.SeekToContent( mrStream );
257 return mrStream.GetError() == 0;
260 inline sal_uInt16 Atom::getType() const
262 return maRecordHeader.nRecType;
265 inline sal_uInt16 Atom::getInstance() const
267 return maRecordHeader.nRecInstance;
270 inline sal_uInt32 Atom::getLength() const
272 return maRecordHeader.nRecLen;
275 Atom::Atom( const DffRecordHeader& rRecordHeader, SvStream& rStream )
276 : maRecordHeader( rRecordHeader ),
277 mrStream( rStream ),
278 mpFirstChild( 0 ),
279 mpNextAtom( 0 ),
280 meStatus( CMP_NOTYET ),
281 mpCompareAtom( 0 )
283 // check if we need to force this to a container
284 if( maRecordHeader.nRecVer != DFF_PSFLAG_CONTAINER )
286 AtomConfig* pAtomConfig = dynamic_cast< AtomConfig* >( gAtomConfigMap[ maRecordHeader.nRecType ].get() );
287 if( pAtomConfig && pAtomConfig->isContainer() )
289 maRecordHeader.nRecVer = DFF_PSFLAG_CONTAINER;
293 if( isContainer() )
295 if( seekToContent() )
297 DffRecordHeader aChildHeader;
299 Atom* pLastAtom = NULL;
301 while( (mrStream.GetError() == 0 ) && ( mrStream.Tell() < maRecordHeader.GetRecEndFilePos() ) )
303 mrStream >> aChildHeader;
305 if( mrStream.GetError() == 0 )
307 Atom* pAtom = new Atom( aChildHeader, mrStream );
309 if( pLastAtom )
310 pLastAtom->mpNextAtom = pAtom;
311 if( mpFirstChild == NULL )
312 mpFirstChild = pAtom;
314 pLastAtom = pAtom;
320 maRecordHeader.SeekToEndOfRecord( mrStream );
323 Atom::~Atom()
325 Atom* pChild = mpFirstChild;
326 while( pChild )
328 Atom* pNextChild = pChild->mpNextAtom;
329 delete pChild;
330 pChild = pNextChild;
334 /** imports this atom and its child atoms */
335 Atom* Atom::import( const DffRecordHeader& rRootRecordHeader, SvStream& rStCtrl )
337 Atom* pRootAtom = new Atom( rRootRecordHeader, rStCtrl );
339 if( rStCtrl.GetError() == 0 )
341 return pRootAtom;
343 else
345 delete pRootAtom;
346 return NULL;
350 /** imports this atom and its child atoms */
351 Atom* Atom::import( UINT16 nRecType, SvStream& rStCtrl )
353 rStCtrl.Seek( STREAM_SEEK_TO_END );
354 sal_Size nStreamLength = rStCtrl.Tell();
355 rStCtrl.Seek( STREAM_SEEK_TO_BEGIN );
357 DffRecordHeader aRootRecordHeader;
358 aRootRecordHeader.nRecVer = DFF_PSFLAG_CONTAINER;
359 aRootRecordHeader.nRecInstance = 0;
360 aRootRecordHeader.nImpVerInst = 0;
361 aRootRecordHeader.nRecType = nRecType;
362 aRootRecordHeader.nRecLen = nStreamLength;
363 aRootRecordHeader.nFilePos = 0;
365 return import( aRootRecordHeader, rStCtrl );
368 /** returns the next child atom after pLast with nRecType or NULL */
369 const Atom* Atom::findNextChildAtom( sal_uInt16 nRecType, const Atom* pLast ) const
371 Atom* pChild = pLast != NULL ? pLast->mpNextAtom : mpFirstChild;
372 while( pChild && pChild->maRecordHeader.nRecType != nRecType )
374 pChild = pChild->mpNextAtom;
377 return pChild;
380 /** returns the next child atom after pLast with nRecType and nRecInstance or NULL */
381 const Atom* Atom::findNextChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance, const Atom* pLast ) const
383 const Atom* pChild = pLast != NULL ? pLast->mpNextAtom : mpFirstChild;
384 while( pChild && (pChild->maRecordHeader.nRecType != nRecType) && (pChild->maRecordHeader.nRecInstance != nRecInstance) )
386 pChild = findNextChildAtom( pChild );
389 return pChild;
392 Atom* Atom::findFirstEqualAtom( Atom* pCompare, Atom* pContainer, Atom* pSearch, int& nDistance )
394 nDistance = 0;
395 Atom* pRet = 0;
397 while( pSearch )
399 if( *pSearch == *pCompare )
400 return pSearch;
402 pSearch = const_cast< Atom* >( pContainer->findNextChildAtom( pSearch ) );
403 nDistance++;
406 return 0;
409 Atom* Atom::skipAtoms( Atom* pContainer, Atom* pAtom, Atom* pSkipTo )
411 while( pAtom && (pAtom != pSkipTo) )
413 pAtom->meStatus = CMP_NOTAVAILABLE;
414 pAtom = const_cast< Atom* >( pContainer->findNextChildAtom( pAtom ) );
417 return pAtom;
420 void Atom::compare( Atom* pAtom )
422 if( pAtom )
424 if( meStatus == CMP_NOTYET )
426 mpCompareAtom = pAtom;
427 pAtom->mpCompareAtom = this;
429 mpCompareAtom = pAtom;
430 pAtom->mpCompareAtom = this;
432 meStatus = pAtom->meStatus = ( *this == *pAtom ) ? CMP_EQUAL : CMP_NOTEQUAL;
435 if(meStatus == CMP_EQUAL)
437 if( isContainer() )
439 /** returns the first child atom or NULL */
440 Atom* pChildAtom1 = const_cast< Atom* >( findFirstChildAtom() );
442 if( pChildAtom1 && (pChildAtom1->meStatus == CMP_NOTYET) )
444 Atom* pChildAtom2 = const_cast< Atom* >( pAtom->findFirstChildAtom() );
445 while( pChildAtom1 && pChildAtom2 )
447 if( !(*pChildAtom1 == *pChildAtom2) )
449 int nDistance1;
450 int nDistance2;
452 Atom* pFind1 = findFirstEqualAtom( pChildAtom1, pAtom, const_cast< Atom* >( pAtom->findNextChildAtom( pChildAtom2 )), nDistance1 );
453 Atom* pFind2 = findFirstEqualAtom( pChildAtom2, this, const_cast< Atom* >(findNextChildAtom( pChildAtom1 )), nDistance2 );
455 if( pFind1 && (!pFind2 || (nDistance1 < nDistance2) ) )
457 pChildAtom2 = skipAtoms( pAtom, pChildAtom2, pFind1 );
459 else if( pFind2 )
461 pChildAtom1 = skipAtoms( this, pChildAtom1, pFind2 );
463 else
465 pChildAtom1 = skipAtoms( this, pChildAtom1, 0 );
466 pChildAtom2 = skipAtoms( pAtom, pChildAtom2, 0 );
470 if( pChildAtom1 && pChildAtom2 )
472 pChildAtom1->mpCompareAtom = pChildAtom2;
473 pChildAtom2->mpCompareAtom = pChildAtom1;
475 pChildAtom1->meStatus = pChildAtom2->meStatus =
476 (pChildAtom1->isContainer() || pChildAtom1->compareContent( *pChildAtom2 )) ?
477 CMP_EQUAL : CMP_NOTEQUAL;
479 pChildAtom1 = const_cast< Atom* >( findNextChildAtom( pChildAtom1 ) );
480 pChildAtom2 = const_cast< Atom* >( pAtom->findNextChildAtom( pChildAtom2 ) );
485 else
487 if( !compareContent( *pAtom ) )
489 meStatus = pAtom->meStatus = CMP_NOTEQUAL;
496 //////////////////////////////////////////////////////////////////////
498 //////////////////////////////////////////////////////////////////////
500 class AtomBoxString : public SvLBoxString
502 public:
503 AtomBoxString( SvLBoxEntry* pEntry, const String& rStr )
504 : SvLBoxString( pEntry, 0, rStr )
507 ~AtomBoxString() { }
509 void Paint( const Point& rPos, SvLBox& rOutDev, USHORT nViewDataEntryFlags, SvLBoxEntry* pEntry )
511 Color aOldTextColor = rOutDev.GetTextColor();
513 if( pEntry && pEntry->GetUserData() )
515 Atom* pAtom = static_cast<Atom*>( pEntry->GetUserData() );
516 rOutDev.SetTextColor( Color( gColors[ pAtom->getCompareStatus() ] ) );
519 SvLBoxString::Paint( rPos, rOutDev, nViewDataEntryFlags, pEntry );
521 rOutDev.SetTextColor( aOldTextColor );
524 Color aOldFillColor = rOutDev.GetFillColor();
526 SvTreeListBox* pTreeBox = static_cast< SvTreeListBox* >( &rOutDev );
527 long nX = pTreeBox->GetSizePixel().Width();
529 ScrollBar* pVScroll = pTreeBox->GetVScroll();
530 if ( pVScroll->IsVisible() )
532 nX -= pVScroll->GetSizePixel().Width();
535 SvViewDataItem* pItem = rOutDev.GetViewDataItem( pEntry, this );
536 nX -= pItem->aSize.Height();
538 long nSize = pItem->aSize.Height() / 2;
539 long nHalfSize = nSize / 2;
540 long nY = rPos.Y() + nHalfSize;
542 if ( aOldFillColor == COL_WHITE )
544 rOutDev.SetFillColor( Color( COL_BLACK ) );
546 else
548 rOutDev.SetFillColor( Color( COL_WHITE ) );
551 long n = 0;
552 while ( n <= nHalfSize )
554 rOutDev.DrawRect( Rectangle( nX+n, nY+n, nX+n, nY+nSize-n ) );
555 n++;
558 rOutDev.SetFillColor( aOldFillColor );
562 private:
563 Image* mpImage;
567 //////////////////////////////////////////////////////////////////////
569 class AtomContainerTreeListBox : public SvTreeListBox
571 public:
572 AtomContainerTreeListBox( Window* pParent );
573 ~AtomContainerTreeListBox();
575 void SetRootAtom( const Atom* pAtom );
578 void SetCollapsingHdl(const Link& rNewHdl){maCollapsingHdl=rNewHdl;}
579 const Link& GetCollapsingHdl() const { return maCollapsingHdl; }
581 void SetExpandingHdl(const Link& rNewHdl){maExpandingHdl=rNewHdl;}
582 const Link& GetExpandingHdl() const { return maExpandingHdl; }
584 virtual BOOL Expand( SvLBoxEntry* pParent );
585 virtual BOOL Collapse( SvLBoxEntry* pParent );
587 SvLBoxEntry* findAtom( Atom* pAtom );
589 virtual void InitEntry(SvLBoxEntry*,const XubString&,const Image&,const Image&);
590 virtual void SetTabs();
592 private:
593 void InsertAtom( const Atom* pAtom, SvLBoxEntry* pParent = 0 );
594 const Atom* mpRootAtom;
595 ResMgr* mpResMgr;
596 Image maImgFolder;
597 Image maImgAtom;
598 Image maImgExpanded;
599 Image maImgCollapsed;
600 bool mbRecursiveGuard;
601 Link maCollapsingHdl;
602 Link maExpandingHdl;
605 typedef std::pair< AtomContainerTreeListBox*, SvLBoxEntry* > AtomContainerEntryPair;
607 AtomContainerTreeListBox::AtomContainerTreeListBox( Window* pParent )
608 : SvTreeListBox( pParent, WB_HASBUTTONS|WB_HASLINES|WB_HASBUTTONSATROOT|WB_3DLOOK|WB_BORDER ),
609 mpRootAtom( 0 ), mbRecursiveGuard( false )
611 mpResMgr = ResMgr::CreateResMgr( "svt" );
612 maImgCollapsed = Image( ResId( RID_IMG_TREENODE_COLLAPSED, mpResMgr ) );
613 maImgExpanded = Image( ResId( RID_IMG_TREENODE_EXPANDED, mpResMgr ) );
615 // SetDefaultExpandedEntryBmp( aExpanded );
616 // SetDefaultCollapsedEntryBmp(aCollapsed );
618 maImgFolder = Image( ResId( IMG_SVT_FOLDER, mpResMgr ) );
619 maImgAtom = Image( ResId( IMG_SVT_DOCTEMPLATE_DOCINFO_SMALL, mpResMgr ) );
622 AtomContainerTreeListBox::~AtomContainerTreeListBox()
626 void AtomContainerTreeListBox::SetTabs()
628 if( IsEditingActive() )
629 EndEditing( TRUE );
631 ClearTabList();
633 short nIndent = 0; GetIndent();
634 long nNodeWidthPixel = maImgCollapsed.GetSizePixel().Width();
635 long nContextWidthDIV2 = nNodeWidthPixel >> 1;
637 long nStartPos = 2 + ( nIndent + nContextWidthDIV2 );
638 AddTab( nStartPos, SV_LBOXTAB_DYNAMIC | SV_LBOXTAB_ADJUST_CENTER );
639 nStartPos += nNodeWidthPixel + 5;
640 AddTab( nStartPos, SV_LBOXTAB_DYNAMIC | SV_LBOXTAB_ADJUST_CENTER | SV_LBOXTAB_SHOW_SELECTION );
641 nStartPos += nContextWidthDIV2 + 5;
642 AddTab( nStartPos, SV_LBOXTAB_DYNAMIC|SV_LBOXTAB_ADJUST_LEFT | SV_LBOXTAB_SHOW_SELECTION );
645 void AtomContainerTreeListBox::InitEntry(SvLBoxEntry* pEntry,const XubString& aStr,const Image& aCollEntryBmp,const Image& aExpEntryBmp)
647 pEntry->AddItem( new SvLBoxContextBmp( pEntry,0, aCollEntryBmp,aExpEntryBmp, SVLISTENTRYFLAG_EXPANDED ) );
648 pEntry->AddItem( new SvLBoxContextBmp( pEntry,0, maImgAtom, maImgAtom, SVLISTENTRYFLAG_EXPANDED ) );
649 pEntry->AddItem( new AtomBoxString( pEntry, aStr ) );
652 SvLBoxEntry* AtomContainerTreeListBox::findAtom( Atom* pAtom )
654 SvLBoxEntry* pEntry = First();
655 while( pEntry )
657 if( pEntry->GetUserData() == pAtom )
658 return pEntry;
660 pEntry = Next( pEntry );
663 return 0;
666 BOOL AtomContainerTreeListBox::Expand( SvLBoxEntry* pParent )
668 BOOL bRet = FALSE;
669 if( !mbRecursiveGuard )
671 mbRecursiveGuard = true;
672 AtomContainerEntryPair aPair( this, pParent );
673 maExpandingHdl.Call( &aPair);
675 bRet = SvTreeListBox::Expand( pParent );
676 mbRecursiveGuard = false;
678 return bRet;
681 BOOL AtomContainerTreeListBox::Collapse( SvLBoxEntry* pParent )
683 BOOL bRet = FALSE;
684 if( !mbRecursiveGuard )
686 mbRecursiveGuard = true;
687 AtomContainerEntryPair aPair( this, pParent );
688 maCollapsingHdl.Call( &aPair);
690 bRet = SvTreeListBox::Collapse( pParent );
691 mbRecursiveGuard = false;
693 return bRet;
696 void AtomContainerTreeListBox::SetRootAtom( const Atom* pAtom )
698 mpRootAtom = pAtom;
699 InsertAtom( mpRootAtom );
702 void AtomContainerTreeListBox::InsertAtom( const Atom* pAtom, SvLBoxEntry* pParent /* = 0 */ )
704 if( pAtom )
706 const DffRecordHeader& rHeader = pAtom->getHeader();
708 char buffer[1024];
710 rtl::OUString aText;
711 AtomConfig* pAtomConfig = dynamic_cast< AtomConfig*>( gAtomConfigMap[rHeader.nRecType].get() );
713 if( pAtomConfig )
714 aText = pAtomConfig->getName();
716 if( !aText.getLength() )
718 sprintf( buffer, "unknown_0x%04x", rHeader.nRecType );
719 aText += rtl::OUString::createFromAscii( buffer );
722 sprintf( buffer, " (I: %lu L: %lu)", (UINT32)rHeader.nRecVer, (UINT32)rHeader.nRecLen );
723 aText += String( rtl::OUString::createFromAscii( buffer ) );
725 SvLBoxEntry* pEntry = 0;
726 if( pAtom->isContainer() && pAtom->findFirstChildAtom() )
728 pEntry = InsertEntry( aText, maImgExpanded, maImgCollapsed, pParent );
730 /** returns the first child atom or NULL */
731 const Atom* pChildAtom = pAtom->findFirstChildAtom();
733 while( pChildAtom )
735 InsertAtom( pChildAtom, pEntry );
736 pChildAtom = pAtom->findNextChildAtom( pChildAtom );
739 else
741 pEntry = InsertEntry( aText, pParent );
744 if( pEntry )
746 pEntry->SetUserData( (void*)pAtom );
748 if( pAtom->isContainer() )
750 SvLBoxContextBmp* pBoxBmp = dynamic_cast< SvLBoxContextBmp* >( pEntry->GetItem( pEntry->ItemCount() - 2 ) );
751 if( pBoxBmp )
753 pBoxBmp->SetBitmap1( pEntry, maImgFolder );
754 pBoxBmp->SetBitmap2( pEntry, maImgFolder );
759 pEntry->ReplaceItem(
760 new AtomBoxString( pEntry, aText, pImage ),
761 pEntry->ItemCount() - 1 );
767 ///////////////////////////////////////////////////////////////////////
769 extern void load_config( const OUString& rPath );
771 class PPTDocument
773 public:
774 PPTDocument( const rtl::OUString& rFilePath );
775 ~PPTDocument();
777 Atom* getRootAtom() const;
779 private:
780 void Load( const rtl::OUString& rFilePath );
782 Atom* mpAtom;
783 SvStream* mpDocStream;
784 SotStorageRef maStorage;
787 typedef boost::shared_ptr< PPTDocument > PPTDocumentPtr;
789 PPTDocument::PPTDocument(const rtl::OUString& rFilePath)
790 : mpAtom(0), mpDocStream(0)
792 Load( rFilePath );
795 PPTDocument::~PPTDocument()
797 delete mpAtom;
798 delete mpDocStream;
801 void PPTDocument::Load( const rtl::OUString& rFilePath )
803 maStorage = new SotStorage( rFilePath, STREAM_STD_READ );
804 if( !maStorage->GetError() )
806 mpDocStream = maStorage->OpenSotStream( String( RTL_CONSTASCII_USTRINGPARAM("PowerPoint Document") ), STREAM_STD_READ );
807 if( mpDocStream )
809 DffRecordHeader aRecordHeader;
810 *mpDocStream >> aRecordHeader;
812 mpAtom = Atom::import( 65530, *mpDocStream );
817 Atom* PPTDocument::getRootAtom() const
819 return mpAtom;
822 ///////////////////////////////////////////////////////////////////////
824 class MSViewerWorkWindow : public WorkWindow
826 public:
827 MSViewerWorkWindow();
828 ~MSViewerWorkWindow();
830 PPTDocumentPtr Load();
831 void onView();
832 void onCompare();
833 void onClose();
835 void View( const PPTDocumentPtr& pDocument, int nPane );
836 void Compare( const PPTDocumentPtr& pDocument1, const PPTDocumentPtr& pDocument2 );
838 virtual void Resize();
840 private:
841 void Sync( AtomContainerEntryPair* pPair, int nAction );
843 AtomContainerTreeListBox* mpListBox[2];
844 MultiLineEdit* mpEdit[2];
845 PPTDocumentPtr mpDocument[2];
846 MenuBar* mpMenuBar;
847 PopupMenu* mpFileMenu;
848 bool mbSelectHdlGuard;
849 DECL_LINK( implSelectHdl, AtomContainerTreeListBox* );
850 DECL_LINK( implExpandingHdl, AtomContainerEntryPair* );
851 DECL_LINK( implCollapsingHdl, AtomContainerEntryPair* );
852 DECL_LINK( implMenuHdl, Menu* );
855 // -----------------------------------------------------------------------
857 void MSViewerWorkWindow::onView()
859 PPTDocumentPtr pDocument( Load() );
860 if( pDocument.get() )
862 onClose();
863 View( pDocument, 0 );
867 void MSViewerWorkWindow::onClose()
871 void MSViewerWorkWindow::onCompare()
873 PPTDocumentPtr pDocument1( Load() );
874 if( pDocument1.get() )
876 PPTDocumentPtr pDocument2( Load() );
877 if( pDocument2.get() )
879 onClose();
880 Compare( pDocument1, pDocument2 );
885 void MSViewerWorkWindow::Compare( const PPTDocumentPtr& pDocument1, const PPTDocumentPtr& pDocument2 )
887 if( pDocument1.get() && pDocument2.get() )
889 Atom* pAtom1 = pDocument1->getRootAtom();
890 Atom* pAtom2 = pDocument2->getRootAtom();
891 pAtom1->setCompareAtom( pAtom2 );
892 pAtom2->setCompareAtom( pAtom1 );
895 View( pDocument1, 0 );
896 View( pDocument2, 1 );
899 void MSViewerWorkWindow::View( const PPTDocumentPtr& pDocument, int nPane )
901 if( ((nPane != 0) && (nPane != 1)) || (pDocument.get() == 0) )
902 return;
904 mpDocument[nPane] = pDocument;
906 mpListBox[nPane]->SetRootAtom( pDocument->getRootAtom() );
907 mpListBox[nPane]->Expand( mpListBox[nPane]->GetEntry(0) );
908 mpListBox[nPane]->Show();
909 mpEdit[nPane]->Show();
910 Resize();
914 PPTDocumentPtr MSViewerWorkWindow::Load()
916 ::sfx2::FileDialogHelper aDlg( ::sfx2::FILEOPEN_SIMPLE, 0 );
917 String aStrFilterType( RTL_CONSTASCII_USTRINGPARAM( "*.ppt" ) );
918 aDlg.AddFilter( aStrFilterType, aStrFilterType );
919 // INetURLObject aFile( SvtPathOptions().GetPalettePath() );
920 // aDlg.SetDisplayDirectory( aFile.GetMainURL( INetURLObject::NO_DECODE ) );
922 PPTDocumentPtr pDocument;
923 if ( aDlg.Execute() == ERRCODE_NONE )
925 pDocument.reset( new PPTDocument( aDlg.GetPath() ) );
928 return pDocument;
931 // -----------------------------------------------------------------------
933 MSViewerWorkWindow::MSViewerWorkWindow() :
934 WorkWindow( 0, WB_APP | WB_STDWORK | WB_3DLOOK ),mbSelectHdlGuard(false)
936 Size aOutputSize( 400, 600 );
937 SetOutputSizePixel( aOutputSize );
938 SetText( String( RTL_CONSTASCII_USTRINGPARAM( "MSViewer" ) ) );
940 Size aOutSize( GetOutputSizePixel() );
942 Font aFont( String( RTL_CONSTASCII_USTRINGPARAM( "Courier" ) ), GetFont().GetSize() );
944 mpMenuBar = new MenuBar();
945 mpMenuBar->InsertItem( 1, String( RTL_CONSTASCII_USTRINGPARAM("~File" ) ) );
946 mpFileMenu = new PopupMenu();
947 mpFileMenu->InsertItem( 2, String( RTL_CONSTASCII_USTRINGPARAM("~View" ) ) );
948 mpFileMenu->InsertItem( 3, String( RTL_CONSTASCII_USTRINGPARAM("~Compare" ) ) );
949 mpFileMenu->InsertSeparator();
950 mpFileMenu->InsertItem( 4, String( RTL_CONSTASCII_USTRINGPARAM("~Quit" ) ) );
951 mpFileMenu->SetSelectHdl( LINK( this, MSViewerWorkWindow, implMenuHdl ) );
953 mpMenuBar->SetPopupMenu( 1, mpFileMenu );
954 SetMenuBar( mpMenuBar );
955 int nPane;
956 for( nPane = 0; nPane < 2; nPane++ )
958 mpListBox[nPane] = new AtomContainerTreeListBox( this );
959 mpListBox[nPane]->SetSelectHdl( LINK( this, MSViewerWorkWindow, implSelectHdl ) );
960 mpListBox[nPane]->SetExpandingHdl( LINK( this, MSViewerWorkWindow, implExpandingHdl ) );
961 mpListBox[nPane]->SetCollapsingHdl( LINK( this, MSViewerWorkWindow, implCollapsingHdl ) );
963 mpEdit[nPane] = new MultiLineEdit(this, WB_3DLOOK | WB_BORDER | WB_LEFT | WB_TOP | WB_READONLY | WB_HSCROLL | WB_VSCROLL );
964 mpEdit[nPane]->SetReadOnly( TRUE );
965 mpEdit[nPane]->SetReadOnly( TRUE );
966 mpEdit[nPane]->SetControlFont( aFont );
970 // -----------------------------------------------------------------------
972 static String GetAtomText( const Atom* pAtom )
974 String aText;
975 if( pAtom )
977 const DffRecordHeader& rHeader = pAtom->getHeader();
978 char buffer[512];
979 sprintf( buffer, "Version = %lu\n\rInstance = %lu\n\rVersionInstance = %lu\n\rLength = %lu\n\r",
980 (UINT32)rHeader.nRecVer,
981 (UINT32)rHeader.nRecInstance,
982 (UINT32)rHeader.nImpVerInst,
983 (UINT32)rHeader.nRecLen );
984 aText = rtl::OUString::createFromAscii( buffer );
985 if( pAtom->isContainer() )
989 else
991 pAtom->seekToContent();
992 AtomConfig* pAtomConfig = dynamic_cast< AtomConfig* >( gAtomConfigMap[pAtom->getType()].get() );
993 if( pAtomConfig )
995 sal_Size nLength = pAtom->getLength();
996 aText += String( pAtomConfig->format( pAtom->getStream(), nLength ) );
998 else
1000 sal_Size nLength = pAtom->getLength();
1001 aText += String( ElementConfig::dump_hex( pAtom->getStream(), nLength ) );
1006 return aText;
1009 IMPL_LINK(MSViewerWorkWindow,implSelectHdl, AtomContainerTreeListBox*, pListBox )
1011 int nPane = (pListBox == mpListBox[1]) ? 1 : 0;
1012 SvLBoxEntry* pEntry = mpListBox[nPane]->FirstSelected();
1013 if( pEntry && pEntry->GetUserData() )
1015 Atom* pAtom = static_cast<Atom*>( pEntry->GetUserData() );
1016 mpEdit[nPane]->SetText( GetAtomText( pAtom ) );
1018 if(!mbSelectHdlGuard)
1020 mbSelectHdlGuard = true;
1021 // select other
1022 AtomContainerEntryPair aPair( pListBox, pEntry );
1023 Sync( &aPair, 2 );
1024 mbSelectHdlGuard = false;
1027 return 0;
1030 void MSViewerWorkWindow::Sync( AtomContainerEntryPair* pPair, int nAction )
1032 if( mpDocument[0].get() && mpDocument[1].get() && pPair->first && pPair->second )
1034 AtomContainerTreeListBox* pDestinationListBox = (pPair->first == mpListBox[0]) ? mpListBox[1] : mpListBox[0];
1036 Atom* pAtom = static_cast<Atom*>(pPair->second->GetUserData());
1037 if( pAtom && pAtom->getCompareAtom() )
1039 SvLBoxEntry* pEntry = pDestinationListBox->findAtom( pAtom->getCompareAtom() );
1041 if(pEntry )
1043 if( nAction == 0 )
1045 pDestinationListBox->Expand( pEntry );
1047 else if( nAction == 1 )
1049 pDestinationListBox->Collapse( pEntry );
1051 else
1053 pDestinationListBox->Select( pEntry );
1060 IMPL_LINK(MSViewerWorkWindow, implExpandingHdl, AtomContainerEntryPair*, pPair )
1062 SvLBoxEntry* pEntry = pPair->second;
1063 if( pEntry && pEntry->GetUserData() )
1065 Atom* pAtom = static_cast<Atom*>( pEntry->GetUserData() );
1066 pAtom->compare( pAtom->getCompareAtom() );
1069 Sync( pPair, 0 );
1071 return 0;
1074 IMPL_LINK(MSViewerWorkWindow, implCollapsingHdl, AtomContainerEntryPair*, pPair )
1076 Sync( pPair, 1 );
1078 return 0;
1081 IMPL_LINK( MSViewerWorkWindow, implMenuHdl, Menu*, pMenu )
1083 if( pMenu )
1085 USHORT nId = pMenu->GetCurItemId();
1086 switch( nId )
1088 case 2: onView(); break;
1089 case 3: onCompare(); break;
1090 case 4: Application::Quit(); break;
1093 return 0;
1096 // -----------------------------------------------------------------------
1098 MSViewerWorkWindow::~MSViewerWorkWindow()
1100 int nPane;
1101 for( nPane = 0; nPane < 2; nPane++ )
1103 delete mpListBox[nPane];
1104 delete mpEdit[nPane];
1107 delete mpFileMenu;
1108 delete mpMenuBar;
1111 // -----------------------------------------------------------------------
1113 void MSViewerWorkWindow::Resize()
1115 int nPaneCount = ((mpDocument[0].get() != 0) ? 1 : 0) + ((mpDocument[1].get() != 0) ? 1 : 0);
1117 Size aOutputSize( GetOutputSizePixel() );
1118 int nHeight = aOutputSize.Height() >> 1;
1119 if( nPaneCount )
1121 int nWidth = aOutputSize.Width();
1122 if( nPaneCount == 2 )
1123 nWidth >>= 1;
1125 int nPosX = 0;
1127 int nPane;
1128 for( nPane = 0; nPane < 2; nPane++ )
1130 mpListBox[nPane]->SetPosSizePixel( nPosX,0, nWidth, nHeight );
1131 mpEdit[nPane]->SetPosSizePixel( nPosX, nHeight, nWidth, aOutputSize.Height() - nHeight );
1132 nPosX += nWidth;
1137 // -----------------------------------------------------------------------
1139 // -----------------------------------------------------------------------
1141 SAL_IMPLEMENT_MAIN()
1143 if( argc > 3 )
1144 return 0;
1146 uno::Reference< lang::XMultiServiceFactory > xMSF;
1149 uno::Reference< uno::XComponentContext > xCtx( cppu::defaultBootstrap_InitialComponentContext() );
1150 if ( !xCtx.is() )
1152 DBG_ERROR( "Error creating initial component context!" );
1153 return -1;
1156 xMSF = uno::Reference< lang::XMultiServiceFactory >(xCtx->getServiceManager(), uno::UNO_QUERY );
1158 if ( !xMSF.is() )
1160 DBG_ERROR( "No service manager!" );
1161 return -1;
1164 // Init UCB
1165 uno::Sequence< uno::Any > aArgs( 2 );
1166 aArgs[ 0 ] <<= rtl::OUString::createFromAscii( UCB_CONFIGURATION_KEY1_LOCAL );
1167 aArgs[ 1 ] <<= rtl::OUString::createFromAscii( UCB_CONFIGURATION_KEY2_OFFICE );
1168 sal_Bool bSuccess = ::ucb::ContentBroker::initialize( xMSF, aArgs );
1169 if ( !bSuccess )
1171 DBG_ERROR( "Error creating UCB!" );
1172 return -1;
1176 catch ( uno::Exception const & )
1178 DBG_ERROR( "Exception during creation of initial component context!" );
1179 return -1;
1181 comphelper::setProcessServiceFactory( xMSF );
1183 InitVCL( xMSF );
1185 String aConfigURL;
1186 if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( Application::GetAppFileName(), aConfigURL ) )
1188 INetURLObject aURL( aConfigURL );
1190 aURL.removeSegment();
1191 aURL.removeFinalSlash();
1192 aURL.Append( String( RTL_CONSTASCII_USTRINGPARAM( "msview.xml" ) ) );
1194 load_config( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
1198 MSViewerWorkWindow aMainWindow;
1200 if( argc >= 2 )
1202 const rtl::OUString aFile1( rtl::OUString::createFromAscii(argv[1]) );
1203 PPTDocumentPtr pDocument1( new PPTDocument( aFile1 ) );
1205 if( argc == 3 )
1207 const rtl::OUString aFile2( rtl::OUString::createFromAscii(argv[2]) );
1209 PPTDocumentPtr pDocument2;
1210 pDocument2.reset( new PPTDocument( aFile2 ) );
1211 aMainWindow.Compare( pDocument1, pDocument2 );
1213 else
1215 aMainWindow.View( pDocument1, 0 );
1219 aMainWindow.Show();
1221 Application::Execute();
1224 DeInitVCL();
1226 return 0;