update emoji autocorrect entries from po-files
[LibreOffice.git] / svx / workben / msview / msview.cxx
blobb03b14b1d585b5f9fab9d2c90315c24919ffb1a3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <vector>
22 #include <map>
23 #include <algorithm>
24 #include <boost/shared_ptr.hpp>
25 #include <sot/storage.hxx>
26 #include <svtools/svtools.hrc>
28 #include <sal/main.h>
29 #include <vcl/event.hxx>
30 #include <vcl/svapp.hxx>
31 #include <vcl/wrkwin.hxx>
32 #include <vcl/msgbox.hxx>
33 #include <vcl/fixed.hxx>
34 #include <vcl/edit.hxx>
35 #include <vcl/button.hxx>
36 #include <vcl/lstbox.hxx>
37 #include <svtools/filectrl.hxx>
38 #include <tools/urlobj.hxx>
39 #include <osl/file.hxx>
40 #include <vcl/unohelp2.hxx>
41 #include <svtools/treelistbox.hxx>
42 #include <svtools/svmedit.hxx>
43 #include <sfx2/filedlghelper.hxx>
45 #include <toolkit/helper/vclunohelper.hxx>
47 #include <tools/stream.hxx>
48 #include <tools/resmgr.hxx>
50 #include <comphelper/processfactory.hxx>
51 #include <cppuhelper/servicefactory.hxx>
52 #include <cppuhelper/bootstrap.hxx>
54 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
56 #include <com/sun/star/awt/XWindowPeer.hpp>
57 #include <com/sun/star/awt/XToolkit.hpp>
58 #include <com/sun/star/awt/WindowDescriptor.hpp>
59 #include <com/sun/star/awt/WindowAttribute.hpp>
60 #include <svx/msdffdef.hxx>
62 #include <unotools/localfilehelper.hxx>
64 #include "xmlconfig.hxx"
67 using namespace ::com::sun::star;
71 enum CompareStatus { CMP_NOTYET = 0, CMP_EQUAL = 1, CMP_NOTEQUAL = 2, CMP_NOTAVAILABLE = 3 };
72 static ColorData gColors[] = { COL_BLACK, COL_GREEN, COL_RED, COL_CYAN };
74 class Atom
76 public:
77 ~Atom();
79 /** imports this atom and its child atoms */
80 static Atom* import( const DffRecordHeader& rRootRecordHeader, SvStream& rStCtrl );
81 static Atom* import( UINT16 nRecType, SvStream& rStCtrl );
83 inline const DffRecordHeader& getHeader() const;
85 /** returns true if at least one atom with the given nRecType is found */
86 inline bool hasChildAtom( sal_uInt16 nRecType ) const;
88 /** returns true if at least one atom with the given nRecType and nRecInstnace is found */
89 inline bool hasChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const;
91 /** returns the first child atom with nRecType or NULL */
92 inline const Atom* findFirstChildAtom( sal_uInt16 nRecType ) const;
94 /** returns the next child atom after pLast with nRecType or NULL */
95 const Atom* findNextChildAtom( sal_uInt16 nRecType, const Atom* pLast ) const;
97 /** returns the first child atom with nRecType and nRecInstance or NULL */
98 inline const Atom* findFirstChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const;
100 /** returns the next child atom after pLast with nRecType and nRecInstance or NULL */
101 const Atom* findNextChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance, const Atom* pLast ) const;
103 /** returns the first child atom or NULL */
104 inline const Atom* findFirstChildAtom() const;
106 /** returns the next child atom after pLast or NULL */
107 inline const Atom* findNextChildAtom( const Atom* pLast ) const;
109 /** returns true if this atom is a container */
110 inline bool isContainer() const;
112 /** seeks to the contents of this atom */
113 inline bool seekToContent() const;
115 /** returns the record type */
116 inline sal_uInt16 getType() const;
118 /** returns the record instance */
119 inline sal_uInt16 getInstance() const;
121 /** returns the record length */
122 inline sal_uInt32 getLength() const;
124 SvStream& getStream() const { return mrStream; }
126 bool operator==( const Atom& rAtom ) const;
128 CompareStatus getCompareStatus() const { return meStatus; }
130 void compare( Atom* pAtom );
131 bool compareContent( Atom& rAtom );
133 Atom* getCompareAtom() const { return mpCompareAtom; }
134 void setCompareAtom( Atom* pAtom ) { mpCompareAtom = pAtom; }
136 private:
137 Atom( const DffRecordHeader& rRecordHeader, SvStream& rStCtrl );
139 // statics for compare
140 static Atom* skipAtoms( Atom* pContainer, Atom* pAtom, Atom* pSkipTo );
141 static Atom* findFirstEqualAtom( Atom* pCompare, Atom* pContainer, Atom* pSearch, int& nDistance );
143 SvStream& mrStream;
144 DffRecordHeader maRecordHeader;
145 Atom* mpFirstChild;
146 Atom* mpNextAtom;
148 CompareStatus meStatus;
149 Atom* mpCompareAtom;
152 bool Atom::operator==( const Atom& rAtom ) const
154 return ( maRecordHeader.nRecType == rAtom.maRecordHeader.nRecType ) &&
155 ( maRecordHeader.nRecVer == rAtom.maRecordHeader.nRecVer ) &&
156 ( maRecordHeader.nRecInstance == rAtom.maRecordHeader.nRecInstance );
159 bool Atom::compareContent( Atom& rAtom )
161 if( maRecordHeader.nRecLen == rAtom.maRecordHeader.nRecLen )
163 seekToContent();
164 rAtom.seekToContent();
166 SvStream& rStream1 = getStream();
167 SvStream& rStream2 = rAtom.getStream();
169 const int nBufferSize = 1024;
170 boost::shared_ptr< char > buffer1( new char[nBufferSize] );
171 boost::shared_ptr< char > buffer2( new char[nBufferSize] );
173 sal_uInt32 nLength = maRecordHeader.nRecLen;
174 sal_Size nRead = 0;
175 while( nLength )
177 sal_Size nRead = (nBufferSize < nLength) ? nBufferSize : nLength;
178 nRead = rStream1.Read( (void*)buffer1.get(), nRead );
179 if( nRead == 0 )
180 break;
181 if( rStream2.Read( (void*)buffer2.get(), nRead ) != nRead )
182 break;
183 if( memcmp( (void*)buffer1.get(), (void*)buffer2.get(), nRead ) != 0 )
184 break;
186 nLength -= nRead;
189 return nLength == 0;
192 return false;
195 inline bool Atom::hasChildAtom( sal_uInt16 nRecType ) const
197 return findFirstChildAtom( nRecType ) != NULL;
200 inline bool Atom::hasChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const
202 return findFirstChildAtom( nRecType, nRecInstance ) != NULL;
205 inline const Atom* Atom::findFirstChildAtom( sal_uInt16 nRecType ) const
207 return findNextChildAtom( nRecType, NULL );
210 inline const DffRecordHeader& Atom::getHeader() const
212 return maRecordHeader;
215 inline const Atom* Atom::findFirstChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const
217 return findNextChildAtom( nRecType, nRecInstance, NULL );
220 inline const Atom* Atom::findFirstChildAtom() const
222 return mpFirstChild;
225 inline const Atom* Atom::findNextChildAtom( const Atom* pLast ) const
227 return pLast ? pLast->mpNextAtom : pLast;
230 inline bool Atom::isContainer() const
232 return (bool)maRecordHeader.IsContainer();
235 inline bool Atom::seekToContent() const
237 maRecordHeader.SeekToContent( mrStream );
238 return mrStream.GetError() == 0;
241 inline sal_uInt16 Atom::getType() const
243 return maRecordHeader.nRecType;
246 inline sal_uInt16 Atom::getInstance() const
248 return maRecordHeader.nRecInstance;
251 inline sal_uInt32 Atom::getLength() const
253 return maRecordHeader.nRecLen;
256 Atom::Atom( const DffRecordHeader& rRecordHeader, SvStream& rStream )
257 : maRecordHeader( rRecordHeader ),
258 mrStream( rStream ),
259 mpFirstChild( 0 ),
260 mpNextAtom( 0 ),
261 meStatus( CMP_NOTYET ),
262 mpCompareAtom( 0 )
264 // check if we need to force this to a container
265 if( maRecordHeader.nRecVer != DFF_PSFLAG_CONTAINER )
267 AtomConfig* pAtomConfig = dynamic_cast< AtomConfig* >( gAtomConfigMap[ maRecordHeader.nRecType ].get() );
268 if( pAtomConfig && pAtomConfig->isContainer() )
270 maRecordHeader.nRecVer = DFF_PSFLAG_CONTAINER;
274 if( isContainer() )
276 if( seekToContent() )
278 DffRecordHeader aChildHeader;
280 Atom* pLastAtom = NULL;
282 while( (mrStream.GetError() == 0 ) && ( mrStream.Tell() < maRecordHeader.GetRecEndFilePos() ) )
284 mrStream >> aChildHeader;
286 if( mrStream.GetError() == 0 )
288 Atom* pAtom = new Atom( aChildHeader, mrStream );
290 if( pLastAtom )
291 pLastAtom->mpNextAtom = pAtom;
292 if( mpFirstChild == NULL )
293 mpFirstChild = pAtom;
295 pLastAtom = pAtom;
301 maRecordHeader.SeekToEndOfRecord( mrStream );
304 Atom::~Atom()
306 Atom* pChild = mpFirstChild;
307 while( pChild )
309 Atom* pNextChild = pChild->mpNextAtom;
310 delete pChild;
311 pChild = pNextChild;
315 /** imports this atom and its child atoms */
316 Atom* Atom::import( const DffRecordHeader& rRootRecordHeader, SvStream& rStCtrl )
318 Atom* pRootAtom = new Atom( rRootRecordHeader, rStCtrl );
320 if( rStCtrl.GetError() == 0 )
322 return pRootAtom;
324 else
326 delete pRootAtom;
327 return NULL;
331 /** imports this atom and its child atoms */
332 Atom* Atom::import( UINT16 nRecType, SvStream& rStCtrl )
334 rStCtrl.Seek( STREAM_SEEK_TO_END );
335 sal_Size nStreamLength = rStCtrl.Tell();
336 rStCtrl.Seek( STREAM_SEEK_TO_BEGIN );
338 DffRecordHeader aRootRecordHeader;
339 aRootRecordHeader.nRecVer = DFF_PSFLAG_CONTAINER;
340 aRootRecordHeader.nRecInstance = 0;
341 aRootRecordHeader.nImpVerInst = 0;
342 aRootRecordHeader.nRecType = nRecType;
343 aRootRecordHeader.nRecLen = nStreamLength;
344 aRootRecordHeader.nFilePos = 0;
346 return import( aRootRecordHeader, rStCtrl );
349 /** returns the next child atom after pLast with nRecType or NULL */
350 const Atom* Atom::findNextChildAtom( sal_uInt16 nRecType, const Atom* pLast ) const
352 Atom* pChild = pLast != NULL ? pLast->mpNextAtom : mpFirstChild;
353 while( pChild && pChild->maRecordHeader.nRecType != nRecType )
355 pChild = pChild->mpNextAtom;
358 return pChild;
361 /** returns the next child atom after pLast with nRecType and nRecInstance or NULL */
362 const Atom* Atom::findNextChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance, const Atom* pLast ) const
364 const Atom* pChild = pLast != NULL ? pLast->mpNextAtom : mpFirstChild;
365 while( pChild && (pChild->maRecordHeader.nRecType != nRecType) && (pChild->maRecordHeader.nRecInstance != nRecInstance) )
367 pChild = findNextChildAtom( pChild );
370 return pChild;
373 Atom* Atom::findFirstEqualAtom( Atom* pCompare, Atom* pContainer, Atom* pSearch, int& nDistance )
375 nDistance = 0;
377 while( pSearch )
379 if( *pSearch == *pCompare )
380 return pSearch;
382 pSearch = const_cast< Atom* >( pContainer->findNextChildAtom( pSearch ) );
383 nDistance++;
386 return 0;
389 Atom* Atom::skipAtoms( Atom* pContainer, Atom* pAtom, Atom* pSkipTo )
391 while( pAtom && (pAtom != pSkipTo) )
393 pAtom->meStatus = CMP_NOTAVAILABLE;
394 pAtom = const_cast< Atom* >( pContainer->findNextChildAtom( pAtom ) );
397 return pAtom;
400 void Atom::compare( Atom* pAtom )
402 if( pAtom )
404 if( meStatus == CMP_NOTYET )
406 mpCompareAtom = pAtom;
407 pAtom->mpCompareAtom = this;
409 mpCompareAtom = pAtom;
410 pAtom->mpCompareAtom = this;
412 meStatus = pAtom->meStatus = ( *this == *pAtom ) ? CMP_EQUAL : CMP_NOTEQUAL;
415 if(meStatus == CMP_EQUAL)
417 if( isContainer() )
419 /** returns the first child atom or NULL */
420 Atom* pChildAtom1 = const_cast< Atom* >( findFirstChildAtom() );
422 if( pChildAtom1 && (pChildAtom1->meStatus == CMP_NOTYET) )
424 Atom* pChildAtom2 = const_cast< Atom* >( pAtom->findFirstChildAtom() );
425 while( pChildAtom1 && pChildAtom2 )
427 if( !(*pChildAtom1 == *pChildAtom2) )
429 int nDistance1;
430 int nDistance2;
432 Atom* pFind1 = findFirstEqualAtom( pChildAtom1, pAtom, const_cast< Atom* >( pAtom->findNextChildAtom( pChildAtom2 )), nDistance1 );
433 Atom* pFind2 = findFirstEqualAtom( pChildAtom2, this, const_cast< Atom* >(findNextChildAtom( pChildAtom1 )), nDistance2 );
435 if( pFind1 && (!pFind2 || (nDistance1 < nDistance2) ) )
437 pChildAtom2 = skipAtoms( pAtom, pChildAtom2, pFind1 );
439 else if( pFind2 )
441 pChildAtom1 = skipAtoms( this, pChildAtom1, pFind2 );
443 else
445 pChildAtom1 = skipAtoms( this, pChildAtom1, 0 );
446 pChildAtom2 = skipAtoms( pAtom, pChildAtom2, 0 );
450 if( pChildAtom1 && pChildAtom2 )
452 pChildAtom1->mpCompareAtom = pChildAtom2;
453 pChildAtom2->mpCompareAtom = pChildAtom1;
455 pChildAtom1->meStatus = pChildAtom2->meStatus =
456 (pChildAtom1->isContainer() || pChildAtom1->compareContent( *pChildAtom2 )) ?
457 CMP_EQUAL : CMP_NOTEQUAL;
459 pChildAtom1 = const_cast< Atom* >( findNextChildAtom( pChildAtom1 ) );
460 pChildAtom2 = const_cast< Atom* >( pAtom->findNextChildAtom( pChildAtom2 ) );
465 else
467 if( !compareContent( *pAtom ) )
469 meStatus = pAtom->meStatus = CMP_NOTEQUAL;
480 class AtomBoxString : public SvLBoxString
482 public:
483 AtomBoxString( SvTreeListEntry* pEntry, const String& rStr )
484 : SvLBoxString( pEntry, 0, rStr )
487 ~AtomBoxString() { }
489 virtual void Paint(
490 const Point& rPos, SvLBox& rOutDev, const SvViewDataEntry* pView, const SvTreeListEntry* pEntry)
492 Color aOldTextColor = rOutDev.GetTextColor();
494 if( pEntry && pEntry->GetUserData() )
496 Atom* pAtom = static_cast<Atom*>( pEntry->GetUserData() );
497 rOutDev.SetTextColor( Color( gColors[ pAtom->getCompareStatus() ] ) );
500 SvLBoxString::Paint(rPos, rOutDev, pView, pEntry);
502 rOutDev.SetTextColor( aOldTextColor );
509 class AtomContainerTreeListBox : public SvTreeListBox
511 public:
512 AtomContainerTreeListBox( vcl::Window* pParent );
513 ~AtomContainerTreeListBox();
515 void SetRootAtom( const Atom* pAtom );
518 void SetCollapsingHdl(const Link<>& rNewHdl){maCollapsingHdl=rNewHdl;}
519 const Link<>& GetCollapsingHdl() const { return maCollapsingHdl; }
521 void SetExpandingHdl(const Link<>& rNewHdl){maExpandingHdl=rNewHdl;}
522 const Link<>& GetExpandingHdl() const { return maExpandingHdl; }
524 virtual BOOL Expand( SvTreeListEntry* pParent );
525 virtual BOOL Collapse( SvTreeListEntry* pParent );
527 SvTreeListEntry* findAtom( Atom* pAtom );
529 virtual void InitEntry(SvTreeListEntry*, const OUString&, const Image&, const Image&);
530 virtual void SetTabs();
532 private:
533 void InsertAtom( const Atom* pAtom, SvTreeListEntry* pParent = 0 );
534 const Atom* mpRootAtom;
535 ResMgr* mpResMgr;
536 Image maImgFolder;
537 Image maImgAtom;
538 Image maImgExpanded;
539 Image maImgCollapsed;
540 bool mbRecursiveGuard;
541 Link<> maCollapsingHdl;
542 Link<> maExpandingHdl;
545 typedef std::pair< AtomContainerTreeListBox*, SvTreeListEntry* > AtomContainerEntryPair;
547 AtomContainerTreeListBox::AtomContainerTreeListBox( vcl::Window* pParent )
548 : SvTreeListBox( pParent, WB_HASBUTTONS|WB_HASLINES|WB_HASBUTTONSATROOT|WB_3DLOOK|WB_BORDER ),
549 mpRootAtom( 0 ), mbRecursiveGuard( false )
551 mpResMgr = ResMgr::CreateResMgr( "svt" );
552 maImgCollapsed = Image( ResId( RID_IMG_TREENODE_COLLAPSED, mpResMgr ) );
553 maImgExpanded = Image( ResId( RID_IMG_TREENODE_EXPANDED, mpResMgr ) );
555 // SetDefaultExpandedEntryBmp( aExpanded );
556 // SetDefaultCollapsedEntryBmp(aCollapsed );
558 maImgFolder = Image( ResId( IMG_SVT_FOLDER, mpResMgr ) );
559 maImgAtom = Image( ResId( IMG_SVT_DOCTEMPLATE_DOCINFO_SMALL, mpResMgr ) );
562 AtomContainerTreeListBox::~AtomContainerTreeListBox()
566 void AtomContainerTreeListBox::SetTabs()
568 if( IsEditingActive() )
569 EndEditing( TRUE );
571 ClearTabList();
573 short nIndent = 0; GetIndent();
574 long nNodeWidthPixel = maImgCollapsed.GetSizePixel().Width();
575 long nContextWidthDIV2 = nNodeWidthPixel >> 1;
577 long nStartPos = 2 + ( nIndent + nContextWidthDIV2 );
578 AddTab( nStartPos, SvLBoxTabFlags::DYNAMIC | SvLBoxTabFlags::ADJUST_CENTER );
579 nStartPos += nNodeWidthPixel + 5;
580 AddTab( nStartPos, SvLBoxTabFlags::DYNAMIC | SvLBoxTabFlags::ADJUST_CENTER | SvLBoxTabFlags::SHOW_SELECTION );
581 nStartPos += nContextWidthDIV2 + 5;
582 AddTab( nStartPos, SvLBoxTabFlags::DYNAMIC|SvLBoxTabFlags::ADJUST_LEFT | SvLBoxTabFlags::SHOW_SELECTION );
585 void AtomContainerTreeListBox::InitEntry(SvTreeListEntry* pEntry, const OUString& aStr,
586 const Image& aCollEntryBmp, const Image& aExpEntryBmp)
588 pEntry->AddItem( new SvLBoxContextBmp(pEntry,0, aCollEntryBmp,aExpEntryBmp, true) );
589 pEntry->AddItem( new SvLBoxContextBmp(pEntry,0, maImgAtom, maImgAtom, true) );
590 pEntry->AddItem( new AtomBoxString( pEntry, aStr ) );
593 SvTreeListEntry* AtomContainerTreeListBox::findAtom( Atom* pAtom )
595 SvTreeListEntry* pEntry = First();
596 while( pEntry )
598 if( pEntry->GetUserData() == pAtom )
599 return pEntry;
601 pEntry = Next( pEntry );
604 return 0;
607 BOOL AtomContainerTreeListBox::Expand( SvTreeListEntry* pParent )
609 BOOL bRet = FALSE;
610 if( !mbRecursiveGuard )
612 mbRecursiveGuard = true;
613 AtomContainerEntryPair aPair( this, pParent );
614 maExpandingHdl.Call( &aPair);
616 bRet = SvTreeListBox::Expand( pParent );
617 mbRecursiveGuard = false;
619 return bRet;
622 BOOL AtomContainerTreeListBox::Collapse( SvTreeListEntry* pParent )
624 BOOL bRet = FALSE;
625 if( !mbRecursiveGuard )
627 mbRecursiveGuard = true;
628 AtomContainerEntryPair aPair( this, pParent );
629 maCollapsingHdl.Call( &aPair);
631 bRet = SvTreeListBox::Collapse( pParent );
632 mbRecursiveGuard = false;
634 return bRet;
637 void AtomContainerTreeListBox::SetRootAtom( const Atom* pAtom )
639 mpRootAtom = pAtom;
640 InsertAtom( mpRootAtom );
643 void AtomContainerTreeListBox::InsertAtom( const Atom* pAtom, SvTreeListEntry* pParent /* = 0 */ )
645 if( pAtom )
647 const DffRecordHeader& rHeader = pAtom->getHeader();
649 char buffer[1024];
651 OUString aText;
652 AtomConfig* pAtomConfig = dynamic_cast< AtomConfig*>( gAtomConfigMap[rHeader.nRecType].get() );
654 if( pAtomConfig )
655 aText = pAtomConfig->getName();
657 if( !aText.getLength() )
659 sprintf( buffer, "unknown_0x%04x", rHeader.nRecType );
660 aText += OUString::createFromAscii( buffer );
663 sprintf( buffer, " (I: %lu L: %lu)", (UINT32)rHeader.nRecVer, (UINT32)rHeader.nRecLen );
664 aText += String( OUString::createFromAscii( buffer ) );
666 SvTreeListEntry* pEntry = 0;
667 if( pAtom->isContainer() && pAtom->findFirstChildAtom() )
669 pEntry = InsertEntry( aText, maImgExpanded, maImgCollapsed, pParent );
671 /** returns the first child atom or NULL */
672 const Atom* pChildAtom = pAtom->findFirstChildAtom();
674 while( pChildAtom )
676 InsertAtom( pChildAtom, pEntry );
677 pChildAtom = pAtom->findNextChildAtom( pChildAtom );
680 else
682 pEntry = InsertEntry( aText, pParent );
685 if( pEntry )
687 pEntry->SetUserData( (void*)pAtom );
689 if( pAtom->isContainer() )
691 SvLBoxContextBmp* pBoxBmp = dynamic_cast< SvLBoxContextBmp* >( pEntry->GetItem( pEntry->ItemCount() - 2 ) );
692 if( pBoxBmp )
694 pBoxBmp->SetBitmap1( pEntry, maImgFolder );
695 pBoxBmp->SetBitmap2( pEntry, maImgFolder );
700 pEntry->ReplaceItem(
701 new AtomBoxString( pEntry, aText, pImage ),
702 pEntry->ItemCount() - 1 );
710 extern void load_config( const OUString& rPath );
712 class PPTDocument
714 public:
715 PPTDocument( const OUString& rFilePath );
716 ~PPTDocument();
718 Atom* getRootAtom() const;
720 private:
721 void Load( const OUString& rFilePath );
723 Atom* mpAtom;
724 SvStream* mpDocStream;
725 tools::SvRef<SotStorage> maStorage;
728 typedef boost::shared_ptr< PPTDocument > PPTDocumentPtr;
730 PPTDocument::PPTDocument(const OUString& rFilePath)
731 : mpAtom(0), mpDocStream(0)
733 Load( rFilePath );
736 PPTDocument::~PPTDocument()
738 delete mpAtom;
739 delete mpDocStream;
742 void PPTDocument::Load( const OUString& rFilePath )
744 maStorage = new SotStorage( rFilePath, STREAM_STD_READ );
745 if( !maStorage->GetError() )
747 mpDocStream = maStorage->OpenSotStream( String( "PowerPoint Document" ), STREAM_STD_READ );
748 if( mpDocStream )
750 DffRecordHeader aRecordHeader;
751 *mpDocStream >> aRecordHeader;
753 mpAtom = Atom::import( 65530, *mpDocStream );
758 Atom* PPTDocument::getRootAtom() const
760 return mpAtom;
765 class MSViewerWorkWindow : public WorkWindow
767 public:
768 MSViewerWorkWindow();
769 ~MSViewerWorkWindow();
771 PPTDocumentPtr Load();
772 void onView();
773 void onCompare();
774 void onClose();
776 void View( const PPTDocumentPtr& pDocument, int nPane );
777 void Compare( const PPTDocumentPtr& pDocument1, const PPTDocumentPtr& pDocument2 );
779 virtual void Resize();
781 private:
782 void Sync( AtomContainerEntryPair* pPair, int nAction );
784 AtomContainerTreeListBox* mpListBox[2];
785 MultiLineEdit* mpEdit[2];
786 PPTDocumentPtr mpDocument[2];
787 MenuBar* mpMenuBar;
788 PopupMenu* mpFileMenu;
789 bool mbSelectHdlGuard;
790 DECL_LINK( implSelectHdl, AtomContainerTreeListBox* );
791 DECL_LINK( implExpandingHdl, AtomContainerEntryPair* );
792 DECL_LINK( implCollapsingHdl, AtomContainerEntryPair* );
793 DECL_LINK( implMenuHdl, Menu* );
798 void MSViewerWorkWindow::onView()
800 PPTDocumentPtr pDocument( Load() );
801 if( pDocument.get() )
803 onClose();
804 View( pDocument, 0 );
808 void MSViewerWorkWindow::onClose()
812 void MSViewerWorkWindow::onCompare()
814 PPTDocumentPtr pDocument1( Load() );
815 if( pDocument1.get() )
817 PPTDocumentPtr pDocument2( Load() );
818 if( pDocument2.get() )
820 onClose();
821 Compare( pDocument1, pDocument2 );
826 void MSViewerWorkWindow::Compare( const PPTDocumentPtr& pDocument1, const PPTDocumentPtr& pDocument2 )
828 if( pDocument1.get() && pDocument2.get() )
830 Atom* pAtom1 = pDocument1->getRootAtom();
831 Atom* pAtom2 = pDocument2->getRootAtom();
832 pAtom1->setCompareAtom( pAtom2 );
833 pAtom2->setCompareAtom( pAtom1 );
836 View( pDocument1, 0 );
837 View( pDocument2, 1 );
840 void MSViewerWorkWindow::View( const PPTDocumentPtr& pDocument, int nPane )
842 if( ((nPane != 0) && (nPane != 1)) || (pDocument.get() == 0) )
843 return;
845 mpDocument[nPane] = pDocument;
847 mpListBox[nPane]->SetRootAtom( pDocument->getRootAtom() );
848 mpListBox[nPane]->Expand( mpListBox[nPane]->GetEntry(0) );
849 mpListBox[nPane]->Show();
850 mpEdit[nPane]->Show();
851 Resize();
855 PPTDocumentPtr MSViewerWorkWindow::Load()
857 ::sfx2::FileDialogHelper aDlg(
858 ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE, 0 );
859 String aStrFilterType( "*.ppt" );
860 aDlg.AddFilter( aStrFilterType, aStrFilterType );
861 // INetURLObject aFile( SvtPathOptions().GetPalettePath() );
862 // aDlg.SetDisplayDirectory( aFile.GetMainURL( INetURLObject::NO_DECODE ) );
864 PPTDocumentPtr pDocument;
865 if ( aDlg.Execute() == ERRCODE_NONE )
867 pDocument.reset( new PPTDocument( aDlg.GetPath() ) );
870 return pDocument;
875 MSViewerWorkWindow::MSViewerWorkWindow() :
876 WorkWindow( 0, WB_APP | WB_STDWORK | WB_3DLOOK ),mbSelectHdlGuard(false)
878 Size aOutputSize( 400, 600 );
879 SetOutputSizePixel( aOutputSize );
880 SetText( String( "MSViewer" ) );
882 Size aOutSize( GetOutputSizePixel() );
884 Font aFont( String( "Courier" ), GetFont().GetSize() );
886 mpMenuBar = new MenuBar();
887 mpMenuBar->InsertItem( 1, String( "~File" ) );
888 mpFileMenu = new PopupMenu();
889 mpFileMenu->InsertItem( 2, String( "~View" ) );
890 mpFileMenu->InsertItem( 3, String( "~Compare" ) );
891 mpFileMenu->InsertSeparator();
892 mpFileMenu->InsertItem( 4, String( "~Quit" ) );
893 mpFileMenu->SetSelectHdl( LINK( this, MSViewerWorkWindow, implMenuHdl ) );
895 mpMenuBar->SetPopupMenu( 1, mpFileMenu );
896 SetMenuBar( mpMenuBar );
897 int nPane;
898 for( nPane = 0; nPane < 2; nPane++ )
900 mpListBox[nPane] = new AtomContainerTreeListBox( this );
901 mpListBox[nPane]->SetSelectHdl( LINK( this, MSViewerWorkWindow, implSelectHdl ) );
902 mpListBox[nPane]->SetExpandingHdl( LINK( this, MSViewerWorkWindow, implExpandingHdl ) );
903 mpListBox[nPane]->SetCollapsingHdl( LINK( this, MSViewerWorkWindow, implCollapsingHdl ) );
905 mpEdit[nPane] = VclPtr<MultiLineEdit>::Create(this, WB_3DLOOK | WB_BORDER | WB_LEFT | WB_TOP | WB_READONLY | WB_HSCROLL | WB_VSCROLL );
906 mpEdit[nPane]->SetReadOnly( TRUE );
907 mpEdit[nPane]->SetReadOnly( TRUE );
908 mpEdit[nPane]->SetControlFont( aFont );
914 static String GetAtomText( const Atom* pAtom )
916 String aText;
917 if( pAtom )
919 const DffRecordHeader& rHeader = pAtom->getHeader();
920 char buffer[512];
921 sprintf( buffer, "Version = %lu\n\rInstance = %lu\n\rVersionInstance = %lu\n\rLength = %lu\n\r",
922 (UINT32)rHeader.nRecVer,
923 (UINT32)rHeader.nRecInstance,
924 (UINT32)rHeader.nImpVerInst,
925 (UINT32)rHeader.nRecLen );
926 aText = OUString::createFromAscii( buffer );
927 if( pAtom->isContainer() )
931 else
933 pAtom->seekToContent();
934 AtomConfig* pAtomConfig = dynamic_cast< AtomConfig* >( gAtomConfigMap[pAtom->getType()].get() );
935 if( pAtomConfig )
937 sal_Size nLength = pAtom->getLength();
938 aText += String( pAtomConfig->format( pAtom->getStream(), nLength ) );
940 else
942 sal_Size nLength = pAtom->getLength();
943 aText += String( ElementConfig::dump_hex( pAtom->getStream(), nLength ) );
948 return aText;
951 IMPL_LINK(MSViewerWorkWindow,implSelectHdl, AtomContainerTreeListBox*, pListBox )
953 int nPane = (pListBox == mpListBox[1]) ? 1 : 0;
954 SvTreeListEntry* pEntry = mpListBox[nPane]->FirstSelected();
955 if( pEntry && pEntry->GetUserData() )
957 Atom* pAtom = static_cast<Atom*>( pEntry->GetUserData() );
958 mpEdit[nPane]->SetText( GetAtomText( pAtom ) );
960 if(!mbSelectHdlGuard)
962 mbSelectHdlGuard = true;
963 // select other
964 AtomContainerEntryPair aPair( pListBox, pEntry );
965 Sync( &aPair, 2 );
966 mbSelectHdlGuard = false;
969 return 0;
972 void MSViewerWorkWindow::Sync( AtomContainerEntryPair* pPair, int nAction )
974 if( mpDocument[0].get() && mpDocument[1].get() && pPair->first && pPair->second )
976 AtomContainerTreeListBox* pDestinationListBox = (pPair->first == mpListBox[0]) ? mpListBox[1] : mpListBox[0];
978 Atom* pAtom = static_cast<Atom*>(pPair->second->GetUserData());
979 if( pAtom && pAtom->getCompareAtom() )
981 SvTreeListEntry* pEntry = pDestinationListBox->findAtom( pAtom->getCompareAtom() );
983 if(pEntry )
985 if( nAction == 0 )
987 pDestinationListBox->Expand( pEntry );
989 else if( nAction == 1 )
991 pDestinationListBox->Collapse( pEntry );
993 else
995 pDestinationListBox->Select( pEntry );
1002 IMPL_LINK(MSViewerWorkWindow, implExpandingHdl, AtomContainerEntryPair*, pPair )
1004 SvTreeListEntry* pEntry = pPair->second;
1005 if( pEntry && pEntry->GetUserData() )
1007 Atom* pAtom = static_cast<Atom*>( pEntry->GetUserData() );
1008 pAtom->compare( pAtom->getCompareAtom() );
1011 Sync( pPair, 0 );
1013 return 0;
1016 IMPL_LINK(MSViewerWorkWindow, implCollapsingHdl, AtomContainerEntryPair*, pPair )
1018 Sync( pPair, 1 );
1020 return 0;
1023 IMPL_LINK( MSViewerWorkWindow, implMenuHdl, Menu*, pMenu )
1025 if( pMenu )
1027 USHORT nId = pMenu->GetCurItemId();
1028 switch( nId )
1030 case 2: onView(); break;
1031 case 3: onCompare(); break;
1032 case 4: Application::Quit(); break;
1035 return 0;
1040 MSViewerWorkWindow::~MSViewerWorkWindow()
1042 int nPane;
1043 for( nPane = 0; nPane < 2; nPane++ )
1045 delete mpListBox[nPane];
1046 delete mpEdit[nPane];
1049 delete mpFileMenu;
1050 delete mpMenuBar;
1055 void MSViewerWorkWindow::Resize()
1057 int nPaneCount = ((mpDocument[0].get() != 0) ? 1 : 0) + ((mpDocument[1].get() != 0) ? 1 : 0);
1059 Size aOutputSize( GetOutputSizePixel() );
1060 int nHeight = aOutputSize.Height() >> 1;
1061 if( nPaneCount )
1063 int nWidth = aOutputSize.Width();
1064 if( nPaneCount == 2 )
1065 nWidth >>= 1;
1067 int nPosX = 0;
1069 int nPane;
1070 for( nPane = 0; nPane < 2; nPane++ )
1072 mpListBox[nPane]->SetPosSizePixel( nPosX,0, nWidth, nHeight );
1073 mpEdit[nPane]->SetPosSizePixel( nPosX, nHeight, nWidth, aOutputSize.Height() - nHeight );
1074 nPosX += nWidth;
1083 SAL_IMPLEMENT_MAIN()
1085 if( argc > 3 )
1086 return 0;
1088 uno::Reference< lang::XMultiServiceFactory > xMSF;
1091 uno::Reference< uno::XComponentContext > xCtx( cppu::defaultBootstrap_InitialComponentContext() );
1092 if ( !xCtx.is() )
1094 OSL_FAIL( "Error creating initial component context!" );
1095 return -1;
1098 xMSF = uno::Reference< lang::XMultiServiceFactory >(xCtx->getServiceManager(), uno::UNO_QUERY );
1100 if ( !xMSF.is() )
1102 OSL_FAIL( "No service manager!" );
1103 return -1;
1106 catch ( uno::Exception const & )
1108 OSL_FAIL( "Exception during creation of initial component context!" );
1109 return -1;
1111 comphelper::setProcessServiceFactory( xMSF );
1113 InitVCL();
1115 String aConfigURL;
1116 if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( Application::GetAppFileName(), aConfigURL ) )
1118 INetURLObject aURL( aConfigURL );
1120 aURL.removeSegment();
1121 aURL.removeFinalSlash();
1122 aURL.Append( String( "msview.xml" ) );
1124 load_config( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
1128 MSViewerWorkWindow aMainWindow;
1130 if( argc >= 2 )
1132 const OUString aFile1( OUString::createFromAscii(argv[1]) );
1133 PPTDocumentPtr pDocument1( new PPTDocument( aFile1 ) );
1135 if( argc == 3 )
1137 const OUString aFile2( OUString::createFromAscii(argv[2]) );
1139 PPTDocumentPtr pDocument2;
1140 pDocument2.reset( new PPTDocument( aFile2 ) );
1141 aMainWindow.Compare( pDocument1, pDocument2 );
1143 else
1145 aMainWindow.View( pDocument1, 0 );
1149 aMainWindow.Show();
1151 Application::Execute();
1154 DeInitVCL();
1156 return 0;
1159 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */