Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / svx / workben / msview / msview.cxx
blob122dcc1fa5e1ce573af8d45e824230c82f488c69
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <vector>
31 #include <map>
32 #include <algorithm>
33 #include <boost/shared_ptr.hpp>
34 #include <sot/storage.hxx>
35 #include <svtools/svtools.hrc>
37 #include <sal/main.h>
38 #include <vcl/event.hxx>
39 #include <vcl/svapp.hxx>
40 #include <vcl/wrkwin.hxx>
41 #include <vcl/msgbox.hxx>
42 #include <vcl/fixed.hxx>
43 #include <vcl/edit.hxx>
44 #include <vcl/button.hxx>
45 #include <vcl/lstbox.hxx>
46 #include <svtools/filectrl.hxx>
47 #include <tools/urlobj.hxx>
48 #include <osl/file.hxx>
49 #include <vcl/unohelp2.hxx>
50 #include <svtools/svtreebx.hxx>
51 #include <svtools/svmedit.hxx>
52 #include <sfx2/filedlghelper.hxx>
54 #include <toolkit/unohlp.hxx>
56 #include <tools/stream.hxx>
57 #include <tools/resmgr.hxx>
59 #include <comphelper/processfactory.hxx>
60 #include <cppuhelper/servicefactory.hxx>
61 #include <cppuhelper/bootstrap.hxx>
63 #include <ucbhelper/contentbroker.hxx>
64 #include <ucbhelper/configurationkeys.hxx>
66 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
68 #include <com/sun/star/awt/XWindowPeer.hpp>
69 #include <com/sun/star/awt/XToolkit.hpp>
70 #include <com/sun/star/awt/WindowDescriptor.hpp>
71 #include <com/sun/star/awt/WindowAttribute.hpp>
72 #include <svx/msdffdef.hxx>
74 #include <unotools/localfilehelper.hxx>
76 #include "xmlconfig.hxx"
78 using ::rtl::OUString;
80 using namespace ::com::sun::star;
82 ///////////////////////////////////////////////////////////////////////
84 enum CompareStatus { CMP_NOTYET = 0, CMP_EQUAL = 1, CMP_NOTEQUAL = 2, CMP_NOTAVAILABLE = 3 };
85 static ColorData gColors[] = { COL_BLACK, COL_GREEN, COL_RED, COL_CYAN };
87 class Atom
89 public:
90 ~Atom();
92 /** imports this atom and its child atoms */
93 static Atom* import( const DffRecordHeader& rRootRecordHeader, SvStream& rStCtrl );
94 static Atom* import( UINT16 nRecType, SvStream& rStCtrl );
96 inline const DffRecordHeader& getHeader() const;
98 /** returns true if at least one atim with the given nRecType is found */
99 inline bool hasChildAtom( sal_uInt16 nRecType ) const;
101 /** returns true if at least one atim with the given nRecType and nRecInstnace is found */
102 inline bool hasChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const;
104 /** returns the first child atom with nRecType or NULL */
105 inline const Atom* findFirstChildAtom( sal_uInt16 nRecType ) const;
107 /** returns the next child atom after pLast with nRecType or NULL */
108 const Atom* findNextChildAtom( sal_uInt16 nRecType, const Atom* pLast ) const;
110 /** returns the first child atom with nRecType and nRecInstance or NULL */
111 inline const Atom* findFirstChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const;
113 /** returns the next child atom after pLast with nRecType and nRecInstance or NULL */
114 const Atom* findNextChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance, const Atom* pLast ) const;
116 /** returns the first child atom or NULL */
117 inline const Atom* findFirstChildAtom() const;
119 /** returns the next child atom after pLast or NULL */
120 inline const Atom* findNextChildAtom( const Atom* pLast ) const;
122 /** returns true if this atom is a container */
123 inline bool isContainer() const;
125 /** seeks to the contents of this atom */
126 inline bool seekToContent() const;
128 /** returns the record type */
129 inline sal_uInt16 getType() const;
131 /** returns the record instance */
132 inline sal_uInt16 getInstance() const;
134 /** returns the record length */
135 inline sal_uInt32 getLength() const;
137 SvStream& getStream() const { return mrStream; }
139 bool operator==( const Atom& rAtom ) const;
141 CompareStatus getCompareStatus() const { return meStatus; }
143 void compare( Atom* pAtom );
144 bool compareContent( Atom& rAtom );
146 Atom* getCompareAtom() const { return mpCompareAtom; }
147 void setCompareAtom( Atom* pAtom ) { mpCompareAtom = pAtom; }
149 private:
150 Atom( const DffRecordHeader& rRecordHeader, SvStream& rStCtrl );
152 // statics for compare
153 static Atom* skipAtoms( Atom* pContainer, Atom* pAtom, Atom* pSkipTo );
154 static Atom* findFirstEqualAtom( Atom* pCompare, Atom* pContainer, Atom* pSearch, int& nDistance );
156 SvStream& mrStream;
157 DffRecordHeader maRecordHeader;
158 Atom* mpFirstChild;
159 Atom* mpNextAtom;
161 CompareStatus meStatus;
162 Atom* mpCompareAtom;
165 bool Atom::operator==( const Atom& rAtom ) const
167 return ( maRecordHeader.nRecType == rAtom.maRecordHeader.nRecType ) &&
168 ( maRecordHeader.nRecVer == rAtom.maRecordHeader.nRecVer ) &&
169 ( maRecordHeader.nRecInstance == rAtom.maRecordHeader.nRecInstance );
172 bool Atom::compareContent( Atom& rAtom )
174 if( maRecordHeader.nRecLen == rAtom.maRecordHeader.nRecLen )
176 seekToContent();
177 rAtom.seekToContent();
179 SvStream& rStream1 = getStream();
180 SvStream& rStream2 = rAtom.getStream();
182 const int nBufferSize = 1024;
183 boost::shared_ptr< char > buffer1( new char[nBufferSize] );
184 boost::shared_ptr< char > buffer2( new char[nBufferSize] );
186 sal_uInt32 nLength = maRecordHeader.nRecLen;
187 sal_Size nRead = 0;
188 while( nLength )
190 sal_Size nRead = (nBufferSize < nLength) ? nBufferSize : nLength;
191 nRead = rStream1.Read( (void*)buffer1.get(), nRead );
192 if( nRead == 0 )
193 break;
194 if( rStream2.Read( (void*)buffer2.get(), nRead ) != nRead )
195 break;
196 if( memcmp( (void*)buffer1.get(), (void*)buffer2.get(), nRead ) != 0 )
197 break;
199 nLength -= nRead;
202 return nLength == 0;
205 return false;
208 inline bool Atom::hasChildAtom( sal_uInt16 nRecType ) const
210 return findFirstChildAtom( nRecType ) != NULL;
213 inline bool Atom::hasChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const
215 return findFirstChildAtom( nRecType, nRecInstance ) != NULL;
218 inline const Atom* Atom::findFirstChildAtom( sal_uInt16 nRecType ) const
220 return findNextChildAtom( nRecType, NULL );
223 inline const DffRecordHeader& Atom::getHeader() const
225 return maRecordHeader;
228 inline const Atom* Atom::findFirstChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const
230 return findNextChildAtom( nRecType, nRecInstance, NULL );
233 inline const Atom* Atom::findFirstChildAtom() const
235 return mpFirstChild;
238 inline const Atom* Atom::findNextChildAtom( const Atom* pLast ) const
240 return pLast ? pLast->mpNextAtom : pLast;
243 inline bool Atom::isContainer() const
245 return (bool)maRecordHeader.IsContainer();
248 inline bool Atom::seekToContent() const
250 maRecordHeader.SeekToContent( mrStream );
251 return mrStream.GetError() == 0;
254 inline sal_uInt16 Atom::getType() const
256 return maRecordHeader.nRecType;
259 inline sal_uInt16 Atom::getInstance() const
261 return maRecordHeader.nRecInstance;
264 inline sal_uInt32 Atom::getLength() const
266 return maRecordHeader.nRecLen;
269 Atom::Atom( const DffRecordHeader& rRecordHeader, SvStream& rStream )
270 : maRecordHeader( rRecordHeader ),
271 mrStream( rStream ),
272 mpFirstChild( 0 ),
273 mpNextAtom( 0 ),
274 meStatus( CMP_NOTYET ),
275 mpCompareAtom( 0 )
277 // check if we need to force this to a container
278 if( maRecordHeader.nRecVer != DFF_PSFLAG_CONTAINER )
280 AtomConfig* pAtomConfig = dynamic_cast< AtomConfig* >( gAtomConfigMap[ maRecordHeader.nRecType ].get() );
281 if( pAtomConfig && pAtomConfig->isContainer() )
283 maRecordHeader.nRecVer = DFF_PSFLAG_CONTAINER;
287 if( isContainer() )
289 if( seekToContent() )
291 DffRecordHeader aChildHeader;
293 Atom* pLastAtom = NULL;
295 while( (mrStream.GetError() == 0 ) && ( mrStream.Tell() < maRecordHeader.GetRecEndFilePos() ) )
297 mrStream >> aChildHeader;
299 if( mrStream.GetError() == 0 )
301 Atom* pAtom = new Atom( aChildHeader, mrStream );
303 if( pLastAtom )
304 pLastAtom->mpNextAtom = pAtom;
305 if( mpFirstChild == NULL )
306 mpFirstChild = pAtom;
308 pLastAtom = pAtom;
314 maRecordHeader.SeekToEndOfRecord( mrStream );
317 Atom::~Atom()
319 Atom* pChild = mpFirstChild;
320 while( pChild )
322 Atom* pNextChild = pChild->mpNextAtom;
323 delete pChild;
324 pChild = pNextChild;
328 /** imports this atom and its child atoms */
329 Atom* Atom::import( const DffRecordHeader& rRootRecordHeader, SvStream& rStCtrl )
331 Atom* pRootAtom = new Atom( rRootRecordHeader, rStCtrl );
333 if( rStCtrl.GetError() == 0 )
335 return pRootAtom;
337 else
339 delete pRootAtom;
340 return NULL;
344 /** imports this atom and its child atoms */
345 Atom* Atom::import( UINT16 nRecType, SvStream& rStCtrl )
347 rStCtrl.Seek( STREAM_SEEK_TO_END );
348 sal_Size nStreamLength = rStCtrl.Tell();
349 rStCtrl.Seek( STREAM_SEEK_TO_BEGIN );
351 DffRecordHeader aRootRecordHeader;
352 aRootRecordHeader.nRecVer = DFF_PSFLAG_CONTAINER;
353 aRootRecordHeader.nRecInstance = 0;
354 aRootRecordHeader.nImpVerInst = 0;
355 aRootRecordHeader.nRecType = nRecType;
356 aRootRecordHeader.nRecLen = nStreamLength;
357 aRootRecordHeader.nFilePos = 0;
359 return import( aRootRecordHeader, rStCtrl );
362 /** returns the next child atom after pLast with nRecType or NULL */
363 const Atom* Atom::findNextChildAtom( sal_uInt16 nRecType, const Atom* pLast ) const
365 Atom* pChild = pLast != NULL ? pLast->mpNextAtom : mpFirstChild;
366 while( pChild && pChild->maRecordHeader.nRecType != nRecType )
368 pChild = pChild->mpNextAtom;
371 return pChild;
374 /** returns the next child atom after pLast with nRecType and nRecInstance or NULL */
375 const Atom* Atom::findNextChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance, const Atom* pLast ) const
377 const Atom* pChild = pLast != NULL ? pLast->mpNextAtom : mpFirstChild;
378 while( pChild && (pChild->maRecordHeader.nRecType != nRecType) && (pChild->maRecordHeader.nRecInstance != nRecInstance) )
380 pChild = findNextChildAtom( pChild );
383 return pChild;
386 Atom* Atom::findFirstEqualAtom( Atom* pCompare, Atom* pContainer, Atom* pSearch, int& nDistance )
388 nDistance = 0;
390 while( pSearch )
392 if( *pSearch == *pCompare )
393 return pSearch;
395 pSearch = const_cast< Atom* >( pContainer->findNextChildAtom( pSearch ) );
396 nDistance++;
399 return 0;
402 Atom* Atom::skipAtoms( Atom* pContainer, Atom* pAtom, Atom* pSkipTo )
404 while( pAtom && (pAtom != pSkipTo) )
406 pAtom->meStatus = CMP_NOTAVAILABLE;
407 pAtom = const_cast< Atom* >( pContainer->findNextChildAtom( pAtom ) );
410 return pAtom;
413 void Atom::compare( Atom* pAtom )
415 if( pAtom )
417 if( meStatus == CMP_NOTYET )
419 mpCompareAtom = pAtom;
420 pAtom->mpCompareAtom = this;
422 mpCompareAtom = pAtom;
423 pAtom->mpCompareAtom = this;
425 meStatus = pAtom->meStatus = ( *this == *pAtom ) ? CMP_EQUAL : CMP_NOTEQUAL;
428 if(meStatus == CMP_EQUAL)
430 if( isContainer() )
432 /** returns the first child atom or NULL */
433 Atom* pChildAtom1 = const_cast< Atom* >( findFirstChildAtom() );
435 if( pChildAtom1 && (pChildAtom1->meStatus == CMP_NOTYET) )
437 Atom* pChildAtom2 = const_cast< Atom* >( pAtom->findFirstChildAtom() );
438 while( pChildAtom1 && pChildAtom2 )
440 if( !(*pChildAtom1 == *pChildAtom2) )
442 int nDistance1;
443 int nDistance2;
445 Atom* pFind1 = findFirstEqualAtom( pChildAtom1, pAtom, const_cast< Atom* >( pAtom->findNextChildAtom( pChildAtom2 )), nDistance1 );
446 Atom* pFind2 = findFirstEqualAtom( pChildAtom2, this, const_cast< Atom* >(findNextChildAtom( pChildAtom1 )), nDistance2 );
448 if( pFind1 && (!pFind2 || (nDistance1 < nDistance2) ) )
450 pChildAtom2 = skipAtoms( pAtom, pChildAtom2, pFind1 );
452 else if( pFind2 )
454 pChildAtom1 = skipAtoms( this, pChildAtom1, pFind2 );
456 else
458 pChildAtom1 = skipAtoms( this, pChildAtom1, 0 );
459 pChildAtom2 = skipAtoms( pAtom, pChildAtom2, 0 );
463 if( pChildAtom1 && pChildAtom2 )
465 pChildAtom1->mpCompareAtom = pChildAtom2;
466 pChildAtom2->mpCompareAtom = pChildAtom1;
468 pChildAtom1->meStatus = pChildAtom2->meStatus =
469 (pChildAtom1->isContainer() || pChildAtom1->compareContent( *pChildAtom2 )) ?
470 CMP_EQUAL : CMP_NOTEQUAL;
472 pChildAtom1 = const_cast< Atom* >( findNextChildAtom( pChildAtom1 ) );
473 pChildAtom2 = const_cast< Atom* >( pAtom->findNextChildAtom( pChildAtom2 ) );
478 else
480 if( !compareContent( *pAtom ) )
482 meStatus = pAtom->meStatus = CMP_NOTEQUAL;
489 //////////////////////////////////////////////////////////////////////
491 //////////////////////////////////////////////////////////////////////
493 class AtomBoxString : public SvLBoxString
495 public:
496 AtomBoxString( SvLBoxEntry* pEntry, const String& rStr )
497 : SvLBoxString( pEntry, 0, rStr )
500 ~AtomBoxString() { }
502 void Paint( const Point& rPos, SvLBox& rOutDev, USHORT nViewDataEntryFlags, SvLBoxEntry* pEntry )
504 Color aOldTextColor = rOutDev.GetTextColor();
506 if( pEntry && pEntry->GetUserData() )
508 Atom* pAtom = static_cast<Atom*>( pEntry->GetUserData() );
509 rOutDev.SetTextColor( Color( gColors[ pAtom->getCompareStatus() ] ) );
512 SvLBoxString::Paint( rPos, rOutDev, nViewDataEntryFlags, pEntry );
514 rOutDev.SetTextColor( aOldTextColor );
519 //////////////////////////////////////////////////////////////////////
521 class AtomContainerTreeListBox : public SvTreeListBox
523 public:
524 AtomContainerTreeListBox( Window* pParent );
525 ~AtomContainerTreeListBox();
527 void SetRootAtom( const Atom* pAtom );
530 void SetCollapsingHdl(const Link& rNewHdl){maCollapsingHdl=rNewHdl;}
531 const Link& GetCollapsingHdl() const { return maCollapsingHdl; }
533 void SetExpandingHdl(const Link& rNewHdl){maExpandingHdl=rNewHdl;}
534 const Link& GetExpandingHdl() const { return maExpandingHdl; }
536 virtual BOOL Expand( SvLBoxEntry* pParent );
537 virtual BOOL Collapse( SvLBoxEntry* pParent );
539 SvLBoxEntry* findAtom( Atom* pAtom );
541 virtual void InitEntry(SvLBoxEntry*,const XubString&,const Image&,const Image&);
542 virtual void SetTabs();
544 private:
545 void InsertAtom( const Atom* pAtom, SvLBoxEntry* pParent = 0 );
546 const Atom* mpRootAtom;
547 ResMgr* mpResMgr;
548 Image maImgFolder;
549 Image maImgAtom;
550 Image maImgExpanded;
551 Image maImgCollapsed;
552 bool mbRecursiveGuard;
553 Link maCollapsingHdl;
554 Link maExpandingHdl;
557 typedef std::pair< AtomContainerTreeListBox*, SvLBoxEntry* > AtomContainerEntryPair;
559 AtomContainerTreeListBox::AtomContainerTreeListBox( Window* pParent )
560 : SvTreeListBox( pParent, WB_HASBUTTONS|WB_HASLINES|WB_HASBUTTONSATROOT|WB_3DLOOK|WB_BORDER ),
561 mpRootAtom( 0 ), mbRecursiveGuard( false )
563 mpResMgr = ResMgr::CreateResMgr( "svt" );
564 maImgCollapsed = Image( ResId( RID_IMG_TREENODE_COLLAPSED, mpResMgr ) );
565 maImgExpanded = Image( ResId( RID_IMG_TREENODE_EXPANDED, mpResMgr ) );
567 // SetDefaultExpandedEntryBmp( aExpanded );
568 // SetDefaultCollapsedEntryBmp(aCollapsed );
570 maImgFolder = Image( ResId( IMG_SVT_FOLDER, mpResMgr ) );
571 maImgAtom = Image( ResId( IMG_SVT_DOCTEMPLATE_DOCINFO_SMALL, mpResMgr ) );
574 AtomContainerTreeListBox::~AtomContainerTreeListBox()
578 void AtomContainerTreeListBox::SetTabs()
580 if( IsEditingActive() )
581 EndEditing( TRUE );
583 ClearTabList();
585 short nIndent = 0; GetIndent();
586 long nNodeWidthPixel = maImgCollapsed.GetSizePixel().Width();
587 long nContextWidthDIV2 = nNodeWidthPixel >> 1;
589 long nStartPos = 2 + ( nIndent + nContextWidthDIV2 );
590 AddTab( nStartPos, SV_LBOXTAB_DYNAMIC | SV_LBOXTAB_ADJUST_CENTER );
591 nStartPos += nNodeWidthPixel + 5;
592 AddTab( nStartPos, SV_LBOXTAB_DYNAMIC | SV_LBOXTAB_ADJUST_CENTER | SV_LBOXTAB_SHOW_SELECTION );
593 nStartPos += nContextWidthDIV2 + 5;
594 AddTab( nStartPos, SV_LBOXTAB_DYNAMIC|SV_LBOXTAB_ADJUST_LEFT | SV_LBOXTAB_SHOW_SELECTION );
597 void AtomContainerTreeListBox::InitEntry(SvLBoxEntry* pEntry,const XubString& aStr,const Image& aCollEntryBmp,const Image& aExpEntryBmp)
599 pEntry->AddItem( new SvLBoxContextBmp( pEntry,0, aCollEntryBmp,aExpEntryBmp, SVLISTENTRYFLAG_EXPANDED ) );
600 pEntry->AddItem( new SvLBoxContextBmp( pEntry,0, maImgAtom, maImgAtom, SVLISTENTRYFLAG_EXPANDED ) );
601 pEntry->AddItem( new AtomBoxString( pEntry, aStr ) );
604 SvLBoxEntry* AtomContainerTreeListBox::findAtom( Atom* pAtom )
606 SvLBoxEntry* pEntry = First();
607 while( pEntry )
609 if( pEntry->GetUserData() == pAtom )
610 return pEntry;
612 pEntry = Next( pEntry );
615 return 0;
618 BOOL AtomContainerTreeListBox::Expand( SvLBoxEntry* pParent )
620 BOOL bRet = FALSE;
621 if( !mbRecursiveGuard )
623 mbRecursiveGuard = true;
624 AtomContainerEntryPair aPair( this, pParent );
625 maExpandingHdl.Call( &aPair);
627 bRet = SvTreeListBox::Expand( pParent );
628 mbRecursiveGuard = false;
630 return bRet;
633 BOOL AtomContainerTreeListBox::Collapse( SvLBoxEntry* pParent )
635 BOOL bRet = FALSE;
636 if( !mbRecursiveGuard )
638 mbRecursiveGuard = true;
639 AtomContainerEntryPair aPair( this, pParent );
640 maCollapsingHdl.Call( &aPair);
642 bRet = SvTreeListBox::Collapse( pParent );
643 mbRecursiveGuard = false;
645 return bRet;
648 void AtomContainerTreeListBox::SetRootAtom( const Atom* pAtom )
650 mpRootAtom = pAtom;
651 InsertAtom( mpRootAtom );
654 void AtomContainerTreeListBox::InsertAtom( const Atom* pAtom, SvLBoxEntry* pParent /* = 0 */ )
656 if( pAtom )
658 const DffRecordHeader& rHeader = pAtom->getHeader();
660 char buffer[1024];
662 rtl::OUString aText;
663 AtomConfig* pAtomConfig = dynamic_cast< AtomConfig*>( gAtomConfigMap[rHeader.nRecType].get() );
665 if( pAtomConfig )
666 aText = pAtomConfig->getName();
668 if( !aText.getLength() )
670 sprintf( buffer, "unknown_0x%04x", rHeader.nRecType );
671 aText += rtl::OUString::createFromAscii( buffer );
674 sprintf( buffer, " (I: %lu L: %lu)", (UINT32)rHeader.nRecVer, (UINT32)rHeader.nRecLen );
675 aText += String( rtl::OUString::createFromAscii( buffer ) );
677 SvLBoxEntry* pEntry = 0;
678 if( pAtom->isContainer() && pAtom->findFirstChildAtom() )
680 pEntry = InsertEntry( aText, maImgExpanded, maImgCollapsed, pParent );
682 /** returns the first child atom or NULL */
683 const Atom* pChildAtom = pAtom->findFirstChildAtom();
685 while( pChildAtom )
687 InsertAtom( pChildAtom, pEntry );
688 pChildAtom = pAtom->findNextChildAtom( pChildAtom );
691 else
693 pEntry = InsertEntry( aText, pParent );
696 if( pEntry )
698 pEntry->SetUserData( (void*)pAtom );
700 if( pAtom->isContainer() )
702 SvLBoxContextBmp* pBoxBmp = dynamic_cast< SvLBoxContextBmp* >( pEntry->GetItem( pEntry->ItemCount() - 2 ) );
703 if( pBoxBmp )
705 pBoxBmp->SetBitmap1( pEntry, maImgFolder );
706 pBoxBmp->SetBitmap2( pEntry, maImgFolder );
711 pEntry->ReplaceItem(
712 new AtomBoxString( pEntry, aText, pImage ),
713 pEntry->ItemCount() - 1 );
719 ///////////////////////////////////////////////////////////////////////
721 extern void load_config( const OUString& rPath );
723 class PPTDocument
725 public:
726 PPTDocument( const rtl::OUString& rFilePath );
727 ~PPTDocument();
729 Atom* getRootAtom() const;
731 private:
732 void Load( const rtl::OUString& rFilePath );
734 Atom* mpAtom;
735 SvStream* mpDocStream;
736 SotStorageRef maStorage;
739 typedef boost::shared_ptr< PPTDocument > PPTDocumentPtr;
741 PPTDocument::PPTDocument(const rtl::OUString& rFilePath)
742 : mpAtom(0), mpDocStream(0)
744 Load( rFilePath );
747 PPTDocument::~PPTDocument()
749 delete mpAtom;
750 delete mpDocStream;
753 void PPTDocument::Load( const rtl::OUString& rFilePath )
755 maStorage = new SotStorage( rFilePath, STREAM_STD_READ );
756 if( !maStorage->GetError() )
758 mpDocStream = maStorage->OpenSotStream( String( "PowerPoint Document" ), STREAM_STD_READ );
759 if( mpDocStream )
761 DffRecordHeader aRecordHeader;
762 *mpDocStream >> aRecordHeader;
764 mpAtom = Atom::import( 65530, *mpDocStream );
769 Atom* PPTDocument::getRootAtom() const
771 return mpAtom;
774 ///////////////////////////////////////////////////////////////////////
776 class MSViewerWorkWindow : public WorkWindow
778 public:
779 MSViewerWorkWindow();
780 ~MSViewerWorkWindow();
782 PPTDocumentPtr Load();
783 void onView();
784 void onCompare();
785 void onClose();
787 void View( const PPTDocumentPtr& pDocument, int nPane );
788 void Compare( const PPTDocumentPtr& pDocument1, const PPTDocumentPtr& pDocument2 );
790 virtual void Resize();
792 private:
793 void Sync( AtomContainerEntryPair* pPair, int nAction );
795 AtomContainerTreeListBox* mpListBox[2];
796 MultiLineEdit* mpEdit[2];
797 PPTDocumentPtr mpDocument[2];
798 MenuBar* mpMenuBar;
799 PopupMenu* mpFileMenu;
800 bool mbSelectHdlGuard;
801 DECL_LINK( implSelectHdl, AtomContainerTreeListBox* );
802 DECL_LINK( implExpandingHdl, AtomContainerEntryPair* );
803 DECL_LINK( implCollapsingHdl, AtomContainerEntryPair* );
804 DECL_LINK( implMenuHdl, Menu* );
807 // -----------------------------------------------------------------------
809 void MSViewerWorkWindow::onView()
811 PPTDocumentPtr pDocument( Load() );
812 if( pDocument.get() )
814 onClose();
815 View( pDocument, 0 );
819 void MSViewerWorkWindow::onClose()
823 void MSViewerWorkWindow::onCompare()
825 PPTDocumentPtr pDocument1( Load() );
826 if( pDocument1.get() )
828 PPTDocumentPtr pDocument2( Load() );
829 if( pDocument2.get() )
831 onClose();
832 Compare( pDocument1, pDocument2 );
837 void MSViewerWorkWindow::Compare( const PPTDocumentPtr& pDocument1, const PPTDocumentPtr& pDocument2 )
839 if( pDocument1.get() && pDocument2.get() )
841 Atom* pAtom1 = pDocument1->getRootAtom();
842 Atom* pAtom2 = pDocument2->getRootAtom();
843 pAtom1->setCompareAtom( pAtom2 );
844 pAtom2->setCompareAtom( pAtom1 );
847 View( pDocument1, 0 );
848 View( pDocument2, 1 );
851 void MSViewerWorkWindow::View( const PPTDocumentPtr& pDocument, int nPane )
853 if( ((nPane != 0) && (nPane != 1)) || (pDocument.get() == 0) )
854 return;
856 mpDocument[nPane] = pDocument;
858 mpListBox[nPane]->SetRootAtom( pDocument->getRootAtom() );
859 mpListBox[nPane]->Expand( mpListBox[nPane]->GetEntry(0) );
860 mpListBox[nPane]->Show();
861 mpEdit[nPane]->Show();
862 Resize();
866 PPTDocumentPtr MSViewerWorkWindow::Load()
868 ::sfx2::FileDialogHelper aDlg(
869 ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, 0 );
870 String aStrFilterType( "*.ppt" );
871 aDlg.AddFilter( aStrFilterType, aStrFilterType );
872 // INetURLObject aFile( SvtPathOptions().GetPalettePath() );
873 // aDlg.SetDisplayDirectory( aFile.GetMainURL( INetURLObject::NO_DECODE ) );
875 PPTDocumentPtr pDocument;
876 if ( aDlg.Execute() == ERRCODE_NONE )
878 pDocument.reset( new PPTDocument( aDlg.GetPath() ) );
881 return pDocument;
884 // -----------------------------------------------------------------------
886 MSViewerWorkWindow::MSViewerWorkWindow() :
887 WorkWindow( 0, WB_APP | WB_STDWORK | WB_3DLOOK ),mbSelectHdlGuard(false)
889 Size aOutputSize( 400, 600 );
890 SetOutputSizePixel( aOutputSize );
891 SetText( String( "MSViewer" ) );
893 Size aOutSize( GetOutputSizePixel() );
895 Font aFont( String( "Courier" ), GetFont().GetSize() );
897 mpMenuBar = new MenuBar();
898 mpMenuBar->InsertItem( 1, String( "~File" ) );
899 mpFileMenu = new PopupMenu();
900 mpFileMenu->InsertItem( 2, String( "~View" ) );
901 mpFileMenu->InsertItem( 3, String( "~Compare" ) );
902 mpFileMenu->InsertSeparator();
903 mpFileMenu->InsertItem( 4, String( "~Quit" ) );
904 mpFileMenu->SetSelectHdl( LINK( this, MSViewerWorkWindow, implMenuHdl ) );
906 mpMenuBar->SetPopupMenu( 1, mpFileMenu );
907 SetMenuBar( mpMenuBar );
908 int nPane;
909 for( nPane = 0; nPane < 2; nPane++ )
911 mpListBox[nPane] = new AtomContainerTreeListBox( this );
912 mpListBox[nPane]->SetSelectHdl( LINK( this, MSViewerWorkWindow, implSelectHdl ) );
913 mpListBox[nPane]->SetExpandingHdl( LINK( this, MSViewerWorkWindow, implExpandingHdl ) );
914 mpListBox[nPane]->SetCollapsingHdl( LINK( this, MSViewerWorkWindow, implCollapsingHdl ) );
916 mpEdit[nPane] = new MultiLineEdit(this, WB_3DLOOK | WB_BORDER | WB_LEFT | WB_TOP | WB_READONLY | WB_HSCROLL | WB_VSCROLL );
917 mpEdit[nPane]->SetReadOnly( TRUE );
918 mpEdit[nPane]->SetReadOnly( TRUE );
919 mpEdit[nPane]->SetControlFont( aFont );
923 // -----------------------------------------------------------------------
925 static String GetAtomText( const Atom* pAtom )
927 String aText;
928 if( pAtom )
930 const DffRecordHeader& rHeader = pAtom->getHeader();
931 char buffer[512];
932 sprintf( buffer, "Version = %lu\n\rInstance = %lu\n\rVersionInstance = %lu\n\rLength = %lu\n\r",
933 (UINT32)rHeader.nRecVer,
934 (UINT32)rHeader.nRecInstance,
935 (UINT32)rHeader.nImpVerInst,
936 (UINT32)rHeader.nRecLen );
937 aText = rtl::OUString::createFromAscii( buffer );
938 if( pAtom->isContainer() )
942 else
944 pAtom->seekToContent();
945 AtomConfig* pAtomConfig = dynamic_cast< AtomConfig* >( gAtomConfigMap[pAtom->getType()].get() );
946 if( pAtomConfig )
948 sal_Size nLength = pAtom->getLength();
949 aText += String( pAtomConfig->format( pAtom->getStream(), nLength ) );
951 else
953 sal_Size nLength = pAtom->getLength();
954 aText += String( ElementConfig::dump_hex( pAtom->getStream(), nLength ) );
959 return aText;
962 IMPL_LINK(MSViewerWorkWindow,implSelectHdl, AtomContainerTreeListBox*, pListBox )
964 int nPane = (pListBox == mpListBox[1]) ? 1 : 0;
965 SvLBoxEntry* pEntry = mpListBox[nPane]->FirstSelected();
966 if( pEntry && pEntry->GetUserData() )
968 Atom* pAtom = static_cast<Atom*>( pEntry->GetUserData() );
969 mpEdit[nPane]->SetText( GetAtomText( pAtom ) );
971 if(!mbSelectHdlGuard)
973 mbSelectHdlGuard = true;
974 // select other
975 AtomContainerEntryPair aPair( pListBox, pEntry );
976 Sync( &aPair, 2 );
977 mbSelectHdlGuard = false;
980 return 0;
983 void MSViewerWorkWindow::Sync( AtomContainerEntryPair* pPair, int nAction )
985 if( mpDocument[0].get() && mpDocument[1].get() && pPair->first && pPair->second )
987 AtomContainerTreeListBox* pDestinationListBox = (pPair->first == mpListBox[0]) ? mpListBox[1] : mpListBox[0];
989 Atom* pAtom = static_cast<Atom*>(pPair->second->GetUserData());
990 if( pAtom && pAtom->getCompareAtom() )
992 SvLBoxEntry* pEntry = pDestinationListBox->findAtom( pAtom->getCompareAtom() );
994 if(pEntry )
996 if( nAction == 0 )
998 pDestinationListBox->Expand( pEntry );
1000 else if( nAction == 1 )
1002 pDestinationListBox->Collapse( pEntry );
1004 else
1006 pDestinationListBox->Select( pEntry );
1013 IMPL_LINK(MSViewerWorkWindow, implExpandingHdl, AtomContainerEntryPair*, pPair )
1015 SvLBoxEntry* pEntry = pPair->second;
1016 if( pEntry && pEntry->GetUserData() )
1018 Atom* pAtom = static_cast<Atom*>( pEntry->GetUserData() );
1019 pAtom->compare( pAtom->getCompareAtom() );
1022 Sync( pPair, 0 );
1024 return 0;
1027 IMPL_LINK(MSViewerWorkWindow, implCollapsingHdl, AtomContainerEntryPair*, pPair )
1029 Sync( pPair, 1 );
1031 return 0;
1034 IMPL_LINK( MSViewerWorkWindow, implMenuHdl, Menu*, pMenu )
1036 if( pMenu )
1038 USHORT nId = pMenu->GetCurItemId();
1039 switch( nId )
1041 case 2: onView(); break;
1042 case 3: onCompare(); break;
1043 case 4: Application::Quit(); break;
1046 return 0;
1049 // -----------------------------------------------------------------------
1051 MSViewerWorkWindow::~MSViewerWorkWindow()
1053 int nPane;
1054 for( nPane = 0; nPane < 2; nPane++ )
1056 delete mpListBox[nPane];
1057 delete mpEdit[nPane];
1060 delete mpFileMenu;
1061 delete mpMenuBar;
1064 // -----------------------------------------------------------------------
1066 void MSViewerWorkWindow::Resize()
1068 int nPaneCount = ((mpDocument[0].get() != 0) ? 1 : 0) + ((mpDocument[1].get() != 0) ? 1 : 0);
1070 Size aOutputSize( GetOutputSizePixel() );
1071 int nHeight = aOutputSize.Height() >> 1;
1072 if( nPaneCount )
1074 int nWidth = aOutputSize.Width();
1075 if( nPaneCount == 2 )
1076 nWidth >>= 1;
1078 int nPosX = 0;
1080 int nPane;
1081 for( nPane = 0; nPane < 2; nPane++ )
1083 mpListBox[nPane]->SetPosSizePixel( nPosX,0, nWidth, nHeight );
1084 mpEdit[nPane]->SetPosSizePixel( nPosX, nHeight, nWidth, aOutputSize.Height() - nHeight );
1085 nPosX += nWidth;
1090 // -----------------------------------------------------------------------
1092 // -----------------------------------------------------------------------
1094 SAL_IMPLEMENT_MAIN()
1096 if( argc > 3 )
1097 return 0;
1099 uno::Reference< lang::XMultiServiceFactory > xMSF;
1102 uno::Reference< uno::XComponentContext > xCtx( cppu::defaultBootstrap_InitialComponentContext() );
1103 if ( !xCtx.is() )
1105 OSL_FAIL( "Error creating initial component context!" );
1106 return -1;
1109 xMSF = uno::Reference< lang::XMultiServiceFactory >(xCtx->getServiceManager(), uno::UNO_QUERY );
1111 if ( !xMSF.is() )
1113 OSL_FAIL( "No service manager!" );
1114 return -1;
1117 // Init UCB
1118 uno::Sequence< uno::Any > aArgs( 2 );
1119 aArgs[ 0 ] <<= rtl::OUString( UCB_CONFIGURATION_KEY1_LOCAL );
1120 aArgs[ 1 ] <<= rtl::OUString( UCB_CONFIGURATION_KEY2_OFFICE );
1121 sal_Bool bSuccess = ::ucb::ContentBroker::initialize( xMSF, aArgs );
1122 if ( !bSuccess )
1124 OSL_FAIL( "Error creating UCB!" );
1125 return -1;
1129 catch ( uno::Exception const & )
1131 OSL_FAIL( "Exception during creation of initial component context!" );
1132 return -1;
1134 comphelper::setProcessServiceFactory( xMSF );
1136 InitVCL( xMSF );
1138 String aConfigURL;
1139 if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( Application::GetAppFileName(), aConfigURL ) )
1141 INetURLObject aURL( aConfigURL );
1143 aURL.removeSegment();
1144 aURL.removeFinalSlash();
1145 aURL.Append( String( "msview.xml" ) );
1147 load_config( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
1151 MSViewerWorkWindow aMainWindow;
1153 if( argc >= 2 )
1155 const rtl::OUString aFile1( rtl::OUString::createFromAscii(argv[1]) );
1156 PPTDocumentPtr pDocument1( new PPTDocument( aFile1 ) );
1158 if( argc == 3 )
1160 const rtl::OUString aFile2( rtl::OUString::createFromAscii(argv[2]) );
1162 PPTDocumentPtr pDocument2;
1163 pDocument2.reset( new PPTDocument( aFile2 ) );
1164 aMainWindow.Compare( pDocument1, pDocument2 );
1166 else
1168 aMainWindow.View( pDocument1, 0 );
1172 aMainWindow.Show();
1174 Application::Execute();
1177 DeInitVCL();
1179 return 0;
1182 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */