1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: msview.cxx,v $
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"
37 #include <boost/shared_ptr.hpp>
38 #include <sot/storage.hxx>
40 #include <svtools/svtools.hrc>
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
};
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
; }
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
);
163 DffRecordHeader maRecordHeader
;
167 CompareStatus meStatus
;
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
)
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
;
196 sal_Size nRead
= (nBufferSize
< nLength
) ? nBufferSize
: nLength
;
197 nRead
= rStream1
.Read( (void*)buffer1
.get(), nRead
);
200 if( rStream2
.Read( (void*)buffer2
.get(), nRead
) != nRead
)
202 if( memcmp( (void*)buffer1
.get(), (void*)buffer2
.get(), nRead
) != 0 )
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
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
),
280 meStatus( CMP_NOTYET
),
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
;
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
);
310 pLastAtom
->mpNextAtom
= pAtom
;
311 if( mpFirstChild
== NULL
)
312 mpFirstChild
= pAtom
;
320 maRecordHeader
.SeekToEndOfRecord( mrStream
);
325 Atom
* pChild
= mpFirstChild
;
328 Atom
* pNextChild
= pChild
->mpNextAtom
;
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 )
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
;
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
);
392 Atom
* Atom::findFirstEqualAtom( Atom
* pCompare
, Atom
* pContainer
, Atom
* pSearch
, int& nDistance
)
399 if( *pSearch
== *pCompare
)
402 pSearch
= const_cast< Atom
* >( pContainer
->findNextChildAtom( pSearch
) );
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
) );
420 void Atom::compare( Atom
* 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
)
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
) )
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
);
461 pChildAtom1
= skipAtoms( this, pChildAtom1
, pFind2
);
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
) );
487 if( !compareContent( *pAtom
) )
489 meStatus
= pAtom
->meStatus
= CMP_NOTEQUAL
;
496 //////////////////////////////////////////////////////////////////////
498 //////////////////////////////////////////////////////////////////////
500 class AtomBoxString
: public SvLBoxString
503 AtomBoxString( SvLBoxEntry
* pEntry
, const String
& rStr
)
504 : SvLBoxString( pEntry
, 0, rStr
)
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 ) );
548 rOutDev.SetFillColor( Color( COL_WHITE ) );
552 while ( n <= nHalfSize )
554 rOutDev.DrawRect( Rectangle( nX+n, nY+n, nX+n, nY+nSize-n ) );
558 rOutDev.SetFillColor( aOldFillColor );
567 //////////////////////////////////////////////////////////////////////
569 class AtomContainerTreeListBox
: public SvTreeListBox
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();
593 void InsertAtom( const Atom
* pAtom
, SvLBoxEntry
* pParent
= 0 );
594 const Atom
* mpRootAtom
;
599 Image maImgCollapsed
;
600 bool mbRecursiveGuard
;
601 Link maCollapsingHdl
;
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() )
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();
657 if( pEntry
->GetUserData() == pAtom
)
660 pEntry
= Next( pEntry
);
666 BOOL
AtomContainerTreeListBox::Expand( SvLBoxEntry
* pParent
)
669 if( !mbRecursiveGuard
)
671 mbRecursiveGuard
= true;
672 AtomContainerEntryPair
aPair( this, pParent
);
673 maExpandingHdl
.Call( &aPair
);
675 bRet
= SvTreeListBox::Expand( pParent
);
676 mbRecursiveGuard
= false;
681 BOOL
AtomContainerTreeListBox::Collapse( SvLBoxEntry
* pParent
)
684 if( !mbRecursiveGuard
)
686 mbRecursiveGuard
= true;
687 AtomContainerEntryPair
aPair( this, pParent
);
688 maCollapsingHdl
.Call( &aPair
);
690 bRet
= SvTreeListBox::Collapse( pParent
);
691 mbRecursiveGuard
= false;
696 void AtomContainerTreeListBox::SetRootAtom( const Atom
* pAtom
)
699 InsertAtom( mpRootAtom
);
702 void AtomContainerTreeListBox::InsertAtom( const Atom
* pAtom
, SvLBoxEntry
* pParent
/* = 0 */ )
706 const DffRecordHeader
& rHeader
= pAtom
->getHeader();
711 AtomConfig
* pAtomConfig
= dynamic_cast< AtomConfig
*>( gAtomConfigMap
[rHeader
.nRecType
].get() );
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();
735 InsertAtom( pChildAtom
, pEntry
);
736 pChildAtom
= pAtom
->findNextChildAtom( pChildAtom
);
741 pEntry
= InsertEntry( aText
, pParent
);
746 pEntry
->SetUserData( (void*)pAtom
);
748 if( pAtom
->isContainer() )
750 SvLBoxContextBmp
* pBoxBmp
= dynamic_cast< SvLBoxContextBmp
* >( pEntry
->GetItem( pEntry
->ItemCount() - 2 ) );
753 pBoxBmp
->SetBitmap1( pEntry
, maImgFolder
);
754 pBoxBmp
->SetBitmap2( pEntry
, maImgFolder
);
760 new AtomBoxString( pEntry, aText, pImage ),
761 pEntry->ItemCount() - 1 );
767 ///////////////////////////////////////////////////////////////////////
769 extern void load_config( const OUString
& rPath
);
774 PPTDocument( const rtl::OUString
& rFilePath
);
777 Atom
* getRootAtom() const;
780 void Load( const rtl::OUString
& rFilePath
);
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)
795 PPTDocument::~PPTDocument()
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
);
809 DffRecordHeader aRecordHeader
;
810 *mpDocStream
>> aRecordHeader
;
812 mpAtom
= Atom::import( 65530, *mpDocStream
);
817 Atom
* PPTDocument::getRootAtom() const
822 ///////////////////////////////////////////////////////////////////////
824 class MSViewerWorkWindow
: public WorkWindow
827 MSViewerWorkWindow();
828 ~MSViewerWorkWindow();
830 PPTDocumentPtr
Load();
835 void View( const PPTDocumentPtr
& pDocument
, int nPane
);
836 void Compare( const PPTDocumentPtr
& pDocument1
, const PPTDocumentPtr
& pDocument2
);
838 virtual void Resize();
841 void Sync( AtomContainerEntryPair
* pPair
, int nAction
);
843 AtomContainerTreeListBox
* mpListBox
[2];
844 MultiLineEdit
* mpEdit
[2];
845 PPTDocumentPtr mpDocument
[2];
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() )
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() )
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) )
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();
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() ) );
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
);
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
)
977 const DffRecordHeader
& rHeader
= pAtom
->getHeader();
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() )
991 pAtom
->seekToContent();
992 AtomConfig
* pAtomConfig
= dynamic_cast< AtomConfig
* >( gAtomConfigMap
[pAtom
->getType()].get() );
995 sal_Size nLength
= pAtom
->getLength();
996 aText
+= String( pAtomConfig
->format( pAtom
->getStream(), nLength
) );
1000 sal_Size nLength
= pAtom
->getLength();
1001 aText
+= String( ElementConfig::dump_hex( pAtom
->getStream(), nLength
) );
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;
1022 AtomContainerEntryPair
aPair( pListBox
, pEntry
);
1024 mbSelectHdlGuard
= false;
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() );
1045 pDestinationListBox
->Expand( pEntry
);
1047 else if( nAction
== 1 )
1049 pDestinationListBox
->Collapse( pEntry
);
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() );
1074 IMPL_LINK(MSViewerWorkWindow
, implCollapsingHdl
, AtomContainerEntryPair
*, pPair
)
1081 IMPL_LINK( MSViewerWorkWindow
, implMenuHdl
, Menu
*, pMenu
)
1085 USHORT nId
= pMenu
->GetCurItemId();
1088 case 2: onView(); break;
1089 case 3: onCompare(); break;
1090 case 4: Application::Quit(); break;
1096 // -----------------------------------------------------------------------
1098 MSViewerWorkWindow::~MSViewerWorkWindow()
1101 for( nPane
= 0; nPane
< 2; nPane
++ )
1103 delete mpListBox
[nPane
];
1104 delete mpEdit
[nPane
];
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;
1121 int nWidth
= aOutputSize
.Width();
1122 if( nPaneCount
== 2 )
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
);
1137 // -----------------------------------------------------------------------
1139 // -----------------------------------------------------------------------
1141 SAL_IMPLEMENT_MAIN()
1146 uno::Reference
< lang::XMultiServiceFactory
> xMSF
;
1149 uno::Reference
< uno::XComponentContext
> xCtx( cppu::defaultBootstrap_InitialComponentContext() );
1152 DBG_ERROR( "Error creating initial component context!" );
1156 xMSF
= uno::Reference
< lang::XMultiServiceFactory
>(xCtx
->getServiceManager(), uno::UNO_QUERY
);
1160 DBG_ERROR( "No service manager!" );
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
);
1171 DBG_ERROR( "Error creating UCB!" );
1176 catch ( uno::Exception
const & )
1178 DBG_ERROR( "Exception during creation of initial component context!" );
1181 comphelper::setProcessServiceFactory( xMSF
);
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
;
1202 const rtl::OUString
aFile1( rtl::OUString::createFromAscii(argv
[1]) );
1203 PPTDocumentPtr
pDocument1( new PPTDocument( aFile1
) );
1207 const rtl::OUString
aFile2( rtl::OUString::createFromAscii(argv
[2]) );
1209 PPTDocumentPtr pDocument2
;
1210 pDocument2
.reset( new PPTDocument( aFile2
) );
1211 aMainWindow
.Compare( pDocument1
, pDocument2
);
1215 aMainWindow
.View( pDocument1
, 0 );
1221 Application::Execute();