1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26
27 #include <vector>
28 #include <map>
29 #include <algorithm>
30 #include <boost/shared_ptr.hpp>
31 #include <sot/storage.hxx>
32 #ifndef _SVTOOLS_HRC
33 #include <svtools/svtools.hrc>
34 #endif
35
36 #include <sal/main.h>
37 #include <vcl/event.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/wrkwin.hxx>
40 #include <vcl/msgbox.hxx>
41 #include <vcl/fixed.hxx>
42 #include <vcl/edit.hxx>
43 #include <vcl/button.hxx>
44 #include <vcl/lstbox.hxx>
45 #include <svtools/filectrl.hxx>
46 #include <tools/urlobj.hxx>
47 #include <osl/file.hxx>
48 #include <vcl/unohelp2.hxx>
49 #include <svtools/svtreebx.hxx>
50 #include <svtools/svmedit.hxx>
51 #include <sfx2/filedlghelper.hxx>
52
53 #include <toolkit/unohlp.hxx>
54
55 #include <tools/stream.hxx>
56 #include <tools/resmgr.hxx>
57
58 #include <comphelper/processfactory.hxx>
59 #include <cppuhelper/servicefactory.hxx>
60 #include <cppuhelper/bootstrap.hxx>
61
62 #include <ucbhelper/contentbroker.hxx>
63 #include <ucbhelper/configurationkeys.hxx>
64
65 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
66
67 #include <com/sun/star/awt/XWindowPeer.hpp>
68 #include <com/sun/star/awt/XToolkit.hpp>
69 #include <com/sun/star/awt/WindowDescriptor.hpp>
70 #include <com/sun/star/awt/WindowAttribute.hpp>
71 #include <svx/msdffdef.hxx>
72
73 #include <unotools/localfilehelper.hxx>
74
75 #include "xmlconfig.hxx"
76
77 using ::rtl::OUString;
78
79 using namespace ::com::sun::star;
80
81 ///////////////////////////////////////////////////////////////////////
82
83 enum CompareStatus { CMP_NOTYET = 0, CMP_EQUAL = 1, CMP_NOTEQUAL = 2, CMP_NOTAVAILABLE = 3 };
84 static ColorData gColors[] = { COL_BLACK, COL_GREEN, COL_RED, COL_CYAN };
85
86 class Atom
87 {
88 public:
89 ~Atom();
90
91 /** imports this atom and its child atoms */
92 static Atom* import( const DffRecordHeader& rRootRecordHeader, SvStream& rStCtrl );
93 static Atom* import( UINT16 nRecType, SvStream& rStCtrl );
94
95 inline const DffRecordHeader& getHeader() const;
96
97 /** returns true if at least one atim with the given nRecType is found */
98 inline bool hasChildAtom( sal_uInt16 nRecType ) const;
99
100 /** returns true if at least one atim with the given nRecType and nRecInstnace is found */
101 inline bool hasChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const;
102
103 /** returns the first child atom with nRecType or NULL */
104 inline const Atom* findFirstChildAtom( sal_uInt16 nRecType ) const;
105
106 /** returns the next child atom after pLast with nRecType or NULL */
107 const Atom* findNextChildAtom( sal_uInt16 nRecType, const Atom* pLast ) const;
108
109 /** returns the first child atom with nRecType and nRecInstance or NULL */
110 inline const Atom* findFirstChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const;
111
112 /** returns the next child atom after pLast with nRecType and nRecInstance or NULL */
113 const Atom* findNextChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance, const Atom* pLast ) const;
114
115 /** returns the first child atom or NULL */
116 inline const Atom* findFirstChildAtom() const;
117
118 /** returns the next child atom after pLast or NULL */
119 inline const Atom* findNextChildAtom( const Atom* pLast ) const;
120
121 /** returns true if this atom is a container */
122 inline bool isContainer() const;
123
124 /** seeks to the contents of this atom */
125 inline bool seekToContent() const;
126
127 /** returns the record type */
128 inline sal_uInt16 getType() const;
129
130 /** returns the record instance */
131 inline sal_uInt16 getInstance() const;
132
133 /** returns the record length */
134 inline sal_uInt32 getLength() const;
135
getStream() const136 SvStream& getStream() const { return mrStream; }
137
138 bool operator==( const Atom& rAtom ) const;
139
getCompareStatus() const140 CompareStatus getCompareStatus() const { return meStatus; }
141
142 void compare( Atom* pAtom );
143 bool compareContent( Atom& rAtom );
144
getCompareAtom() const145 Atom* getCompareAtom() const { return mpCompareAtom; }
setCompareAtom(Atom * pAtom)146 void setCompareAtom( Atom* pAtom ) { mpCompareAtom = pAtom; }
147
148 private:
149 Atom( const DffRecordHeader& rRecordHeader, SvStream& rStCtrl );
150
151 // statics for compare
152 static Atom* skipAtoms( Atom* pContainer, Atom* pAtom, Atom* pSkipTo );
153 static Atom* findFirstEqualAtom( Atom* pCompare, Atom* pContainer, Atom* pSearch, int& nDistance );
154
155 SvStream& mrStream;
156 DffRecordHeader maRecordHeader;
157 Atom* mpFirstChild;
158 Atom* mpNextAtom;
159
160 CompareStatus meStatus;
161 Atom* mpCompareAtom;
162 };
163
operator ==(const Atom & rAtom) const164 bool Atom::operator==( const Atom& rAtom ) const
165 {
166 return ( maRecordHeader.nRecType == rAtom.maRecordHeader.nRecType ) &&
167 ( maRecordHeader.nRecVer == rAtom.maRecordHeader.nRecVer ) &&
168 ( maRecordHeader.nRecInstance == rAtom.maRecordHeader.nRecInstance );
169 }
170
compareContent(Atom & rAtom)171 bool Atom::compareContent( Atom& rAtom )
172 {
173 if( maRecordHeader.nRecLen == rAtom.maRecordHeader.nRecLen )
174 {
175 seekToContent();
176 rAtom.seekToContent();
177
178 SvStream& rStream1 = getStream();
179 SvStream& rStream2 = rAtom.getStream();
180
181 const int nBufferSize = 1024;
182 boost::shared_ptr< char > buffer1( new char[nBufferSize] );
183 boost::shared_ptr< char > buffer2( new char[nBufferSize] );
184
185 sal_uInt32 nLength = maRecordHeader.nRecLen;
186 sal_Size nRead = 0;
187 while( nLength )
188 {
189 sal_Size nRead = (nBufferSize < nLength) ? nBufferSize : nLength;
190 nRead = rStream1.Read( (void*)buffer1.get(), nRead );
191 if( nRead == 0 )
192 break;
193 if( rStream2.Read( (void*)buffer2.get(), nRead ) != nRead )
194 break;
195 if( memcmp( (void*)buffer1.get(), (void*)buffer2.get(), nRead ) != 0 )
196 break;
197
198 nLength -= nRead;
199 }
200
201 return nLength == 0;
202 }
203
204 return false;
205 }
206
hasChildAtom(sal_uInt16 nRecType) const207 inline bool Atom::hasChildAtom( sal_uInt16 nRecType ) const
208 {
209 return findFirstChildAtom( nRecType ) != NULL;
210 }
211
hasChildAtom(sal_uInt16 nRecType,sal_uInt16 nRecInstance) const212 inline bool Atom::hasChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const
213 {
214 return findFirstChildAtom( nRecType, nRecInstance ) != NULL;
215 }
216
findFirstChildAtom(sal_uInt16 nRecType) const217 inline const Atom* Atom::findFirstChildAtom( sal_uInt16 nRecType ) const
218 {
219 return findNextChildAtom( nRecType, NULL );
220 }
221
getHeader() const222 inline const DffRecordHeader& Atom::getHeader() const
223 {
224 return maRecordHeader;
225 }
226
findFirstChildAtom(sal_uInt16 nRecType,sal_uInt16 nRecInstance) const227 inline const Atom* Atom::findFirstChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance ) const
228 {
229 return findNextChildAtom( nRecType, nRecInstance, NULL );
230 }
231
findFirstChildAtom() const232 inline const Atom* Atom::findFirstChildAtom() const
233 {
234 return mpFirstChild;
235 }
236
findNextChildAtom(const Atom * pLast) const237 inline const Atom* Atom::findNextChildAtom( const Atom* pLast ) const
238 {
239 return pLast ? pLast->mpNextAtom : pLast;
240 }
241
isContainer() const242 inline bool Atom::isContainer() const
243 {
244 return (bool)maRecordHeader.IsContainer();
245 }
246
seekToContent() const247 inline bool Atom::seekToContent() const
248 {
249 maRecordHeader.SeekToContent( mrStream );
250 return mrStream.GetError() == 0;
251 }
252
getType() const253 inline sal_uInt16 Atom::getType() const
254 {
255 return maRecordHeader.nRecType;
256 }
257
getInstance() const258 inline sal_uInt16 Atom::getInstance() const
259 {
260 return maRecordHeader.nRecInstance;
261 }
262
getLength() const263 inline sal_uInt32 Atom::getLength() const
264 {
265 return maRecordHeader.nRecLen;
266 }
267
Atom(const DffRecordHeader & rRecordHeader,SvStream & rStream)268 Atom::Atom( const DffRecordHeader& rRecordHeader, SvStream& rStream )
269 : maRecordHeader( rRecordHeader ),
270 mrStream( rStream ),
271 mpFirstChild( 0 ),
272 mpNextAtom( 0 ),
273 meStatus( CMP_NOTYET ),
274 mpCompareAtom( 0 )
275 {
276 // check if we need to force this to a container
277 if( maRecordHeader.nRecVer != DFF_PSFLAG_CONTAINER )
278 {
279 AtomConfig* pAtomConfig = dynamic_cast< AtomConfig* >( gAtomConfigMap[ maRecordHeader.nRecType ].get() );
280 if( pAtomConfig && pAtomConfig->isContainer() )
281 {
282 maRecordHeader.nRecVer = DFF_PSFLAG_CONTAINER;
283 }
284 }
285
286 if( isContainer() )
287 {
288 if( seekToContent() )
289 {
290 DffRecordHeader aChildHeader;
291
292 Atom* pLastAtom = NULL;
293
294 while( (mrStream.GetError() == 0 ) && ( mrStream.Tell() < maRecordHeader.GetRecEndFilePos() ) )
295 {
296 mrStream >> aChildHeader;
297
298 if( mrStream.GetError() == 0 )
299 {
300 Atom* pAtom = new Atom( aChildHeader, mrStream );
301
302 if( pLastAtom )
303 pLastAtom->mpNextAtom = pAtom;
304 if( mpFirstChild == NULL )
305 mpFirstChild = pAtom;
306
307 pLastAtom = pAtom;
308 }
309 }
310 }
311 }
312
313 maRecordHeader.SeekToEndOfRecord( mrStream );
314 }
315
~Atom()316 Atom::~Atom()
317 {
318 Atom* pChild = mpFirstChild;
319 while( pChild )
320 {
321 Atom* pNextChild = pChild->mpNextAtom;
322 delete pChild;
323 pChild = pNextChild;
324 }
325 }
326
327 /** imports this atom and its child atoms */
import(const DffRecordHeader & rRootRecordHeader,SvStream & rStCtrl)328 Atom* Atom::import( const DffRecordHeader& rRootRecordHeader, SvStream& rStCtrl )
329 {
330 Atom* pRootAtom = new Atom( rRootRecordHeader, rStCtrl );
331
332 if( rStCtrl.GetError() == 0 )
333 {
334 return pRootAtom;
335 }
336 else
337 {
338 delete pRootAtom;
339 return NULL;
340 }
341 }
342
343 /** imports this atom and its child atoms */
import(UINT16 nRecType,SvStream & rStCtrl)344 Atom* Atom::import( UINT16 nRecType, SvStream& rStCtrl )
345 {
346 rStCtrl.Seek( STREAM_SEEK_TO_END );
347 sal_Size nStreamLength = rStCtrl.Tell();
348 rStCtrl.Seek( STREAM_SEEK_TO_BEGIN );
349
350 DffRecordHeader aRootRecordHeader;
351 aRootRecordHeader.nRecVer = DFF_PSFLAG_CONTAINER;
352 aRootRecordHeader.nRecInstance = 0;
353 aRootRecordHeader.nImpVerInst = 0;
354 aRootRecordHeader.nRecType = nRecType;
355 aRootRecordHeader.nRecLen = nStreamLength;
356 aRootRecordHeader.nFilePos = 0;
357
358 return import( aRootRecordHeader, rStCtrl );
359 }
360
361 /** returns the next child atom after pLast with nRecType or NULL */
findNextChildAtom(sal_uInt16 nRecType,const Atom * pLast) const362 const Atom* Atom::findNextChildAtom( sal_uInt16 nRecType, const Atom* pLast ) const
363 {
364 Atom* pChild = pLast != NULL ? pLast->mpNextAtom : mpFirstChild;
365 while( pChild && pChild->maRecordHeader.nRecType != nRecType )
366 {
367 pChild = pChild->mpNextAtom;
368 }
369
370 return pChild;
371 }
372
373 /** returns the next child atom after pLast with nRecType and nRecInstance or NULL */
findNextChildAtom(sal_uInt16 nRecType,sal_uInt16 nRecInstance,const Atom * pLast) const374 const Atom* Atom::findNextChildAtom( sal_uInt16 nRecType, sal_uInt16 nRecInstance, const Atom* pLast ) const
375 {
376 const Atom* pChild = pLast != NULL ? pLast->mpNextAtom : mpFirstChild;
377 while( pChild && (pChild->maRecordHeader.nRecType != nRecType) && (pChild->maRecordHeader.nRecInstance != nRecInstance) )
378 {
379 pChild = findNextChildAtom( pChild );
380 }
381
382 return pChild;
383 }
384
findFirstEqualAtom(Atom * pCompare,Atom * pContainer,Atom * pSearch,int & nDistance)385 Atom* Atom::findFirstEqualAtom( Atom* pCompare, Atom* pContainer, Atom* pSearch, int& nDistance )
386 {
387 nDistance = 0;
388 Atom* pRet = 0;
389
390 while( pSearch )
391 {
392 if( *pSearch == *pCompare )
393 return pSearch;
394
395 pSearch = const_cast< Atom* >( pContainer->findNextChildAtom( pSearch ) );
396 nDistance++;
397 }
398
399 return 0;
400 }
401
skipAtoms(Atom * pContainer,Atom * pAtom,Atom * pSkipTo)402 Atom* Atom::skipAtoms( Atom* pContainer, Atom* pAtom, Atom* pSkipTo )
403 {
404 while( pAtom && (pAtom != pSkipTo) )
405 {
406 pAtom->meStatus = CMP_NOTAVAILABLE;
407 pAtom = const_cast< Atom* >( pContainer->findNextChildAtom( pAtom ) );
408 }
409
410 return pAtom;
411 }
412
compare(Atom * pAtom)413 void Atom::compare( Atom* pAtom )
414 {
415 if( pAtom )
416 {
417 if( meStatus == CMP_NOTYET )
418 {
419 mpCompareAtom = pAtom;
420 pAtom->mpCompareAtom = this;
421
422 mpCompareAtom = pAtom;
423 pAtom->mpCompareAtom = this;
424
425 meStatus = pAtom->meStatus = ( *this == *pAtom ) ? CMP_EQUAL : CMP_NOTEQUAL;
426 }
427
428 if(meStatus == CMP_EQUAL)
429 {
430 if( isContainer() )
431 {
432 /** returns the first child atom or NULL */
433 Atom* pChildAtom1 = const_cast< Atom* >( findFirstChildAtom() );
434
435 if( pChildAtom1 && (pChildAtom1->meStatus == CMP_NOTYET) )
436 {
437 Atom* pChildAtom2 = const_cast< Atom* >( pAtom->findFirstChildAtom() );
438 while( pChildAtom1 && pChildAtom2 )
439 {
440 if( !(*pChildAtom1 == *pChildAtom2) )
441 {
442 int nDistance1;
443 int nDistance2;
444
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 );
447
448 if( pFind1 && (!pFind2 || (nDistance1 < nDistance2) ) )
449 {
450 pChildAtom2 = skipAtoms( pAtom, pChildAtom2, pFind1 );
451 }
452 else if( pFind2 )
453 {
454 pChildAtom1 = skipAtoms( this, pChildAtom1, pFind2 );
455 }
456 else
457 {
458 pChildAtom1 = skipAtoms( this, pChildAtom1, 0 );
459 pChildAtom2 = skipAtoms( pAtom, pChildAtom2, 0 );
460 }
461 }
462
463 if( pChildAtom1 && pChildAtom2 )
464 {
465 pChildAtom1->mpCompareAtom = pChildAtom2;
466 pChildAtom2->mpCompareAtom = pChildAtom1;
467
468 pChildAtom1->meStatus = pChildAtom2->meStatus =
469 (pChildAtom1->isContainer() || pChildAtom1->compareContent( *pChildAtom2 )) ?
470 CMP_EQUAL : CMP_NOTEQUAL;
471
472 pChildAtom1 = const_cast< Atom* >( findNextChildAtom( pChildAtom1 ) );
473 pChildAtom2 = const_cast< Atom* >( pAtom->findNextChildAtom( pChildAtom2 ) );
474 }
475 }
476 }
477 }
478 else
479 {
480 if( !compareContent( *pAtom ) )
481 {
482 meStatus = pAtom->meStatus = CMP_NOTEQUAL;
483 }
484 }
485 }
486 }
487 }
488
489 //////////////////////////////////////////////////////////////////////
490
491 //////////////////////////////////////////////////////////////////////
492
493 class AtomBoxString : public SvLBoxString
494 {
495 public:
AtomBoxString(SvLBoxEntry * pEntry,const String & rStr)496 AtomBoxString( SvLBoxEntry* pEntry, const String& rStr )
497 : SvLBoxString( pEntry, 0, rStr )
498 { }
499
~AtomBoxString()500 ~AtomBoxString() { }
501
Paint(const Point & rPos,SvLBox & rOutDev,USHORT nViewDataEntryFlags,SvLBoxEntry * pEntry)502 void Paint( const Point& rPos, SvLBox& rOutDev, USHORT nViewDataEntryFlags, SvLBoxEntry* pEntry )
503 {
504 Color aOldTextColor = rOutDev.GetTextColor();
505
506 if( pEntry && pEntry->GetUserData() )
507 {
508 Atom* pAtom = static_cast<Atom*>( pEntry->GetUserData() );
509 rOutDev.SetTextColor( Color( gColors[ pAtom->getCompareStatus() ] ) );
510 }
511
512 SvLBoxString::Paint( rPos, rOutDev, nViewDataEntryFlags, pEntry );
513
514 rOutDev.SetTextColor( aOldTextColor );
515
516 /*
517 Color aOldFillColor = rOutDev.GetFillColor();
518
519 SvTreeListBox* pTreeBox = static_cast< SvTreeListBox* >( &rOutDev );
520 long nX = pTreeBox->GetSizePixel().Width();
521
522 ScrollBar* pVScroll = pTreeBox->GetVScroll();
523 if ( pVScroll->IsVisible() )
524 {
525 nX -= pVScroll->GetSizePixel().Width();
526 }
527
528 SvViewDataItem* pItem = rOutDev.GetViewDataItem( pEntry, this );
529 nX -= pItem->aSize.Height();
530
531 long nSize = pItem->aSize.Height() / 2;
532 long nHalfSize = nSize / 2;
533 long nY = rPos.Y() + nHalfSize;
534
535 if ( aOldFillColor == COL_WHITE )
536 {
537 rOutDev.SetFillColor( Color( COL_BLACK ) );
538 }
539 else
540 {
541 rOutDev.SetFillColor( Color( COL_WHITE ) );
542 }
543
544 long n = 0;
545 while ( n <= nHalfSize )
546 {
547 rOutDev.DrawRect( Rectangle( nX+n, nY+n, nX+n, nY+nSize-n ) );
548 n++;
549 }
550
551 rOutDev.SetFillColor( aOldFillColor );
552 */
553 }
554
555 private:
556 Image* mpImage;
557 };
558
559
560 //////////////////////////////////////////////////////////////////////
561
562 class AtomContainerTreeListBox : public SvTreeListBox
563 {
564 public:
565 AtomContainerTreeListBox( Window* pParent );
566 ~AtomContainerTreeListBox();
567
568 void SetRootAtom( const Atom* pAtom );
569
570
SetCollapsingHdl(const Link & rNewHdl)571 void SetCollapsingHdl(const Link& rNewHdl){maCollapsingHdl=rNewHdl;}
GetCollapsingHdl() const572 const Link& GetCollapsingHdl() const { return maCollapsingHdl; }
573
SetExpandingHdl(const Link & rNewHdl)574 void SetExpandingHdl(const Link& rNewHdl){maExpandingHdl=rNewHdl;}
GetExpandingHdl() const575 const Link& GetExpandingHdl() const { return maExpandingHdl; }
576
577 virtual BOOL Expand( SvLBoxEntry* pParent );
578 virtual BOOL Collapse( SvLBoxEntry* pParent );
579
580 SvLBoxEntry* findAtom( Atom* pAtom );
581
582 virtual void InitEntry(SvLBoxEntry*,const XubString&,const Image&,const Image&);
583 virtual void SetTabs();
584
585 private:
586 void InsertAtom( const Atom* pAtom, SvLBoxEntry* pParent = 0 );
587 const Atom* mpRootAtom;
588 ResMgr* mpResMgr;
589 Image maImgFolder;
590 Image maImgAtom;
591 Image maImgExpanded;
592 Image maImgCollapsed;
593 bool mbRecursiveGuard;
594 Link maCollapsingHdl;
595 Link maExpandingHdl;
596 };
597
598 typedef std::pair< AtomContainerTreeListBox*, SvLBoxEntry* > AtomContainerEntryPair;
599
AtomContainerTreeListBox(Window * pParent)600 AtomContainerTreeListBox::AtomContainerTreeListBox( Window* pParent )
601 : SvTreeListBox( pParent, WB_HASBUTTONS|WB_HASLINES|WB_HASBUTTONSATROOT|WB_3DLOOK|WB_BORDER ),
602 mpRootAtom( 0 ), mbRecursiveGuard( false )
603 {
604 mpResMgr = ResMgr::CreateResMgr( "svt" );
605 maImgCollapsed = Image( ResId( RID_IMG_TREENODE_COLLAPSED, mpResMgr ) );
606 maImgExpanded = Image( ResId( RID_IMG_TREENODE_EXPANDED, mpResMgr ) );
607
608 // SetDefaultExpandedEntryBmp( aExpanded );
609 // SetDefaultCollapsedEntryBmp(aCollapsed );
610
611 maImgFolder = Image( ResId( IMG_SVT_FOLDER, mpResMgr ) );
612 maImgAtom = Image( ResId( IMG_SVT_DOCTEMPLATE_DOCINFO_SMALL, mpResMgr ) );
613 }
614
~AtomContainerTreeListBox()615 AtomContainerTreeListBox::~AtomContainerTreeListBox()
616 {
617 }
618
SetTabs()619 void AtomContainerTreeListBox::SetTabs()
620 {
621 if( IsEditingActive() )
622 EndEditing( TRUE );
623
624 ClearTabList();
625
626 short nIndent = 0; GetIndent();
627 long nNodeWidthPixel = maImgCollapsed.GetSizePixel().Width();
628 long nContextWidthDIV2 = nNodeWidthPixel >> 1;
629
630 long nStartPos = 2 + ( nIndent + nContextWidthDIV2 );
631 AddTab( nStartPos, SV_LBOXTAB_DYNAMIC | SV_LBOXTAB_ADJUST_CENTER );
632 nStartPos += nNodeWidthPixel + 5;
633 AddTab( nStartPos, SV_LBOXTAB_DYNAMIC | SV_LBOXTAB_ADJUST_CENTER | SV_LBOXTAB_SHOW_SELECTION );
634 nStartPos += nContextWidthDIV2 + 5;
635 AddTab( nStartPos, SV_LBOXTAB_DYNAMIC|SV_LBOXTAB_ADJUST_LEFT | SV_LBOXTAB_SHOW_SELECTION );
636 }
637
InitEntry(SvLBoxEntry * pEntry,const XubString & aStr,const Image & aCollEntryBmp,const Image & aExpEntryBmp)638 void AtomContainerTreeListBox::InitEntry(SvLBoxEntry* pEntry,const XubString& aStr,const Image& aCollEntryBmp,const Image& aExpEntryBmp)
639 {
640 pEntry->AddItem( new SvLBoxContextBmp( pEntry,0, aCollEntryBmp,aExpEntryBmp, SVLISTENTRYFLAG_EXPANDED ) );
641 pEntry->AddItem( new SvLBoxContextBmp( pEntry,0, maImgAtom, maImgAtom, SVLISTENTRYFLAG_EXPANDED ) );
642 pEntry->AddItem( new AtomBoxString( pEntry, aStr ) );
643 }
644
findAtom(Atom * pAtom)645 SvLBoxEntry* AtomContainerTreeListBox::findAtom( Atom* pAtom )
646 {
647 SvLBoxEntry* pEntry = First();
648 while( pEntry )
649 {
650 if( pEntry->GetUserData() == pAtom )
651 return pEntry;
652
653 pEntry = Next( pEntry );
654 }
655
656 return 0;
657 }
658
Expand(SvLBoxEntry * pParent)659 BOOL AtomContainerTreeListBox::Expand( SvLBoxEntry* pParent )
660 {
661 BOOL bRet = FALSE;
662 if( !mbRecursiveGuard )
663 {
664 mbRecursiveGuard = true;
665 AtomContainerEntryPair aPair( this, pParent );
666 maExpandingHdl.Call( &aPair);
667
668 bRet = SvTreeListBox::Expand( pParent );
669 mbRecursiveGuard = false;
670 }
671 return bRet;
672 }
673
Collapse(SvLBoxEntry * pParent)674 BOOL AtomContainerTreeListBox::Collapse( SvLBoxEntry* pParent )
675 {
676 BOOL bRet = FALSE;
677 if( !mbRecursiveGuard )
678 {
679 mbRecursiveGuard = true;
680 AtomContainerEntryPair aPair( this, pParent );
681 maCollapsingHdl.Call( &aPair);
682
683 bRet = SvTreeListBox::Collapse( pParent );
684 mbRecursiveGuard = false;
685 }
686 return bRet;
687 }
688
SetRootAtom(const Atom * pAtom)689 void AtomContainerTreeListBox::SetRootAtom( const Atom* pAtom )
690 {
691 mpRootAtom = pAtom;
692 InsertAtom( mpRootAtom );
693 }
694
InsertAtom(const Atom * pAtom,SvLBoxEntry * pParent)695 void AtomContainerTreeListBox::InsertAtom( const Atom* pAtom, SvLBoxEntry* pParent /* = 0 */ )
696 {
697 if( pAtom )
698 {
699 const DffRecordHeader& rHeader = pAtom->getHeader();
700
701 char buffer[1024];
702
703 rtl::OUString aText;
704 AtomConfig* pAtomConfig = dynamic_cast< AtomConfig*>( gAtomConfigMap[rHeader.nRecType].get() );
705
706 if( pAtomConfig )
707 aText = pAtomConfig->getName();
708
709 if( !aText.getLength() )
710 {
711 sprintf( buffer, "unknown_0x%04x", rHeader.nRecType );
712 aText += rtl::OUString::createFromAscii( buffer );
713 }
714
715 sprintf( buffer, " (I: %lu L: %lu)", (UINT32)rHeader.nRecVer, (UINT32)rHeader.nRecLen );
716 aText += String( rtl::OUString::createFromAscii( buffer ) );
717
718 SvLBoxEntry* pEntry = 0;
719 if( pAtom->isContainer() && pAtom->findFirstChildAtom() )
720 {
721 pEntry = InsertEntry( aText, maImgExpanded, maImgCollapsed, pParent );
722
723 /** returns the first child atom or NULL */
724 const Atom* pChildAtom = pAtom->findFirstChildAtom();
725
726 while( pChildAtom )
727 {
728 InsertAtom( pChildAtom, pEntry );
729 pChildAtom = pAtom->findNextChildAtom( pChildAtom );
730 }
731 }
732 else
733 {
734 pEntry = InsertEntry( aText, pParent );
735 }
736
737 if( pEntry )
738 {
739 pEntry->SetUserData( (void*)pAtom );
740
741 if( pAtom->isContainer() )
742 {
743 SvLBoxContextBmp* pBoxBmp = dynamic_cast< SvLBoxContextBmp* >( pEntry->GetItem( pEntry->ItemCount() - 2 ) );
744 if( pBoxBmp )
745 {
746 pBoxBmp->SetBitmap1( pEntry, maImgFolder );
747 pBoxBmp->SetBitmap2( pEntry, maImgFolder );
748 }
749 }
750
751 /*
752 pEntry->ReplaceItem(
753 new AtomBoxString( pEntry, aText, pImage ),
754 pEntry->ItemCount() - 1 );
755 */
756 }
757 }
758 }
759
760 ///////////////////////////////////////////////////////////////////////
761
762 extern void load_config( const OUString& rPath );
763
764 class PPTDocument
765 {
766 public:
767 PPTDocument( const rtl::OUString& rFilePath );
768 ~PPTDocument();
769
770 Atom* getRootAtom() const;
771
772 private:
773 void Load( const rtl::OUString& rFilePath );
774
775 Atom* mpAtom;
776 SvStream* mpDocStream;
777 SotStorageRef maStorage;
778 };
779
780 typedef boost::shared_ptr< PPTDocument > PPTDocumentPtr;
781
PPTDocument(const rtl::OUString & rFilePath)782 PPTDocument::PPTDocument(const rtl::OUString& rFilePath)
783 : mpAtom(0), mpDocStream(0)
784 {
785 Load( rFilePath );
786 }
787
~PPTDocument()788 PPTDocument::~PPTDocument()
789 {
790 delete mpAtom;
791 delete mpDocStream;
792 }
793
Load(const rtl::OUString & rFilePath)794 void PPTDocument::Load( const rtl::OUString& rFilePath )
795 {
796 maStorage = new SotStorage( rFilePath, STREAM_STD_READ );
797 if( !maStorage->GetError() )
798 {
799 mpDocStream = maStorage->OpenSotStream( String( RTL_CONSTASCII_USTRINGPARAM("PowerPoint Document") ), STREAM_STD_READ );
800 if( mpDocStream )
801 {
802 DffRecordHeader aRecordHeader;
803 *mpDocStream >> aRecordHeader;
804
805 mpAtom = Atom::import( 65530, *mpDocStream );
806 }
807 }
808 }
809
getRootAtom() const810 Atom* PPTDocument::getRootAtom() const
811 {
812 return mpAtom;
813 }
814
815 ///////////////////////////////////////////////////////////////////////
816
817 class MSViewerWorkWindow : public WorkWindow
818 {
819 public:
820 MSViewerWorkWindow();
821 ~MSViewerWorkWindow();
822
823 PPTDocumentPtr Load();
824 void onView();
825 void onCompare();
826 void onClose();
827
828 void View( const PPTDocumentPtr& pDocument, int nPane );
829 void Compare( const PPTDocumentPtr& pDocument1, const PPTDocumentPtr& pDocument2 );
830
831 virtual void Resize();
832
833 private:
834 void Sync( AtomContainerEntryPair* pPair, int nAction );
835
836 AtomContainerTreeListBox* mpListBox[2];
837 MultiLineEdit* mpEdit[2];
838 PPTDocumentPtr mpDocument[2];
839 MenuBar* mpMenuBar;
840 PopupMenu* mpFileMenu;
841 bool mbSelectHdlGuard;
842 DECL_LINK( implSelectHdl, AtomContainerTreeListBox* );
843 DECL_LINK( implExpandingHdl, AtomContainerEntryPair* );
844 DECL_LINK( implCollapsingHdl, AtomContainerEntryPair* );
845 DECL_LINK( implMenuHdl, Menu* );
846 };
847
848 // -----------------------------------------------------------------------
849
onView()850 void MSViewerWorkWindow::onView()
851 {
852 PPTDocumentPtr pDocument( Load() );
853 if( pDocument.get() )
854 {
855 onClose();
856 View( pDocument, 0 );
857 }
858 }
859
onClose()860 void MSViewerWorkWindow::onClose()
861 {
862 }
863
onCompare()864 void MSViewerWorkWindow::onCompare()
865 {
866 PPTDocumentPtr pDocument1( Load() );
867 if( pDocument1.get() )
868 {
869 PPTDocumentPtr pDocument2( Load() );
870 if( pDocument2.get() )
871 {
872 onClose();
873 Compare( pDocument1, pDocument2 );
874 }
875 }
876 }
877
Compare(const PPTDocumentPtr & pDocument1,const PPTDocumentPtr & pDocument2)878 void MSViewerWorkWindow::Compare( const PPTDocumentPtr& pDocument1, const PPTDocumentPtr& pDocument2 )
879 {
880 if( pDocument1.get() && pDocument2.get() )
881 {
882 Atom* pAtom1 = pDocument1->getRootAtom();
883 Atom* pAtom2 = pDocument2->getRootAtom();
884 pAtom1->setCompareAtom( pAtom2 );
885 pAtom2->setCompareAtom( pAtom1 );
886 }
887
888 View( pDocument1, 0 );
889 View( pDocument2, 1 );
890 }
891
View(const PPTDocumentPtr & pDocument,int nPane)892 void MSViewerWorkWindow::View( const PPTDocumentPtr& pDocument, int nPane )
893 {
894 if( ((nPane != 0) && (nPane != 1)) || (pDocument.get() == 0) )
895 return;
896
897 mpDocument[nPane] = pDocument;
898
899 mpListBox[nPane]->SetRootAtom( pDocument->getRootAtom() );
900 mpListBox[nPane]->Expand( mpListBox[nPane]->GetEntry(0) );
901 mpListBox[nPane]->Show();
902 mpEdit[nPane]->Show();
903 Resize();
904 }
905
906
Load()907 PPTDocumentPtr MSViewerWorkWindow::Load()
908 {
909 ::sfx2::FileDialogHelper aDlg( ::sfx2::FILEOPEN_SIMPLE, 0 );
910 String aStrFilterType( RTL_CONSTASCII_USTRINGPARAM( "*.ppt" ) );
911 aDlg.AddFilter( aStrFilterType, aStrFilterType );
912 // INetURLObject aFile( SvtPathOptions().GetPalettePath() );
913 // aDlg.SetDisplayDirectory( aFile.GetMainURL( INetURLObject::NO_DECODE ) );
914
915 PPTDocumentPtr pDocument;
916 if ( aDlg.Execute() == ERRCODE_NONE )
917 {
918 pDocument.reset( new PPTDocument( aDlg.GetPath() ) );
919 }
920
921 return pDocument;
922 }
923
924 // -----------------------------------------------------------------------
925
MSViewerWorkWindow()926 MSViewerWorkWindow::MSViewerWorkWindow() :
927 WorkWindow( 0, WB_APP | WB_STDWORK | WB_3DLOOK ),mbSelectHdlGuard(false)
928 {
929 Size aOutputSize( 400, 600 );
930 SetOutputSizePixel( aOutputSize );
931 SetText( String( RTL_CONSTASCII_USTRINGPARAM( "MSViewer" ) ) );
932
933 Size aOutSize( GetOutputSizePixel() );
934
935 Font aFont( String( RTL_CONSTASCII_USTRINGPARAM( "Courier" ) ), GetFont().GetSize() );
936
937 mpMenuBar = new MenuBar();
938 mpMenuBar->InsertItem( 1, String( RTL_CONSTASCII_USTRINGPARAM("~File" ) ) );
939 mpFileMenu = new PopupMenu();
940 mpFileMenu->InsertItem( 2, String( RTL_CONSTASCII_USTRINGPARAM("~View" ) ) );
941 mpFileMenu->InsertItem( 3, String( RTL_CONSTASCII_USTRINGPARAM("~Compare" ) ) );
942 mpFileMenu->InsertSeparator();
943 mpFileMenu->InsertItem( 4, String( RTL_CONSTASCII_USTRINGPARAM("~Quit" ) ) );
944 mpFileMenu->SetSelectHdl( LINK( this, MSViewerWorkWindow, implMenuHdl ) );
945
946 mpMenuBar->SetPopupMenu( 1, mpFileMenu );
947 SetMenuBar( mpMenuBar );
948 int nPane;
949 for( nPane = 0; nPane < 2; nPane++ )
950 {
951 mpListBox[nPane] = new AtomContainerTreeListBox( this );
952 mpListBox[nPane]->SetSelectHdl( LINK( this, MSViewerWorkWindow, implSelectHdl ) );
953 mpListBox[nPane]->SetExpandingHdl( LINK( this, MSViewerWorkWindow, implExpandingHdl ) );
954 mpListBox[nPane]->SetCollapsingHdl( LINK( this, MSViewerWorkWindow, implCollapsingHdl ) );
955
956 mpEdit[nPane] = new MultiLineEdit(this, WB_3DLOOK | WB_BORDER | WB_LEFT | WB_TOP | WB_READONLY | WB_HSCROLL | WB_VSCROLL );
957 mpEdit[nPane]->SetReadOnly( TRUE );
958 mpEdit[nPane]->SetReadOnly( TRUE );
959 mpEdit[nPane]->SetControlFont( aFont );
960 }
961 }
962
963 // -----------------------------------------------------------------------
964
GetAtomText(const Atom * pAtom)965 static String GetAtomText( const Atom* pAtom )
966 {
967 String aText;
968 if( pAtom )
969 {
970 const DffRecordHeader& rHeader = pAtom->getHeader();
971 char buffer[512];
972 sprintf( buffer, "Version = %lu\n\rInstance = %lu\n\rVersionInstance = %lu\n\rLength = %lu\n\r",
973 (UINT32)rHeader.nRecVer,
974 (UINT32)rHeader.nRecInstance,
975 (UINT32)rHeader.nImpVerInst,
976 (UINT32)rHeader.nRecLen );
977 aText = rtl::OUString::createFromAscii( buffer );
978 if( pAtom->isContainer() )
979 {
980
981 }
982 else
983 {
984 pAtom->seekToContent();
985 AtomConfig* pAtomConfig = dynamic_cast< AtomConfig* >( gAtomConfigMap[pAtom->getType()].get() );
986 if( pAtomConfig )
987 {
988 sal_Size nLength = pAtom->getLength();
989 aText += String( pAtomConfig->format( pAtom->getStream(), nLength ) );
990 }
991 else
992 {
993 sal_Size nLength = pAtom->getLength();
994 aText += String( ElementConfig::dump_hex( pAtom->getStream(), nLength ) );
995 }
996 }
997 }
998
999 return aText;
1000 }
1001
IMPL_LINK(MSViewerWorkWindow,implSelectHdl,AtomContainerTreeListBox *,pListBox)1002 IMPL_LINK(MSViewerWorkWindow,implSelectHdl, AtomContainerTreeListBox*, pListBox )
1003 {
1004 int nPane = (pListBox == mpListBox[1]) ? 1 : 0;
1005 SvLBoxEntry* pEntry = mpListBox[nPane]->FirstSelected();
1006 if( pEntry && pEntry->GetUserData() )
1007 {
1008 Atom* pAtom = static_cast<Atom*>( pEntry->GetUserData() );
1009 mpEdit[nPane]->SetText( GetAtomText( pAtom ) );
1010
1011 if(!mbSelectHdlGuard)
1012 {
1013 mbSelectHdlGuard = true;
1014 // select other
1015 AtomContainerEntryPair aPair( pListBox, pEntry );
1016 Sync( &aPair, 2 );
1017 mbSelectHdlGuard = false;
1018 }
1019 }
1020 return 0;
1021 }
1022
Sync(AtomContainerEntryPair * pPair,int nAction)1023 void MSViewerWorkWindow::Sync( AtomContainerEntryPair* pPair, int nAction )
1024 {
1025 if( mpDocument[0].get() && mpDocument[1].get() && pPair->first && pPair->second )
1026 {
1027 AtomContainerTreeListBox* pDestinationListBox = (pPair->first == mpListBox[0]) ? mpListBox[1] : mpListBox[0];
1028
1029 Atom* pAtom = static_cast<Atom*>(pPair->second->GetUserData());
1030 if( pAtom && pAtom->getCompareAtom() )
1031 {
1032 SvLBoxEntry* pEntry = pDestinationListBox->findAtom( pAtom->getCompareAtom() );
1033
1034 if(pEntry )
1035 {
1036 if( nAction == 0 )
1037 {
1038 pDestinationListBox->Expand( pEntry );
1039 }
1040 else if( nAction == 1 )
1041 {
1042 pDestinationListBox->Collapse( pEntry );
1043 }
1044 else
1045 {
1046 pDestinationListBox->Select( pEntry );
1047 }
1048 }
1049 }
1050 }
1051 }
1052
IMPL_LINK(MSViewerWorkWindow,implExpandingHdl,AtomContainerEntryPair *,pPair)1053 IMPL_LINK(MSViewerWorkWindow, implExpandingHdl, AtomContainerEntryPair*, pPair )
1054 {
1055 SvLBoxEntry* pEntry = pPair->second;
1056 if( pEntry && pEntry->GetUserData() )
1057 {
1058 Atom* pAtom = static_cast<Atom*>( pEntry->GetUserData() );
1059 pAtom->compare( pAtom->getCompareAtom() );
1060 }
1061
1062 Sync( pPair, 0 );
1063
1064 return 0;
1065 }
1066
IMPL_LINK(MSViewerWorkWindow,implCollapsingHdl,AtomContainerEntryPair *,pPair)1067 IMPL_LINK(MSViewerWorkWindow, implCollapsingHdl, AtomContainerEntryPair*, pPair )
1068 {
1069 Sync( pPair, 1 );
1070
1071 return 0;
1072 }
1073
IMPL_LINK(MSViewerWorkWindow,implMenuHdl,Menu *,pMenu)1074 IMPL_LINK( MSViewerWorkWindow, implMenuHdl, Menu*, pMenu )
1075 {
1076 if( pMenu )
1077 {
1078 USHORT nId = pMenu->GetCurItemId();
1079 switch( nId )
1080 {
1081 case 2: onView(); break;
1082 case 3: onCompare(); break;
1083 case 4: Application::Quit(); break;
1084 }
1085 }
1086 return 0;
1087 }
1088
1089 // -----------------------------------------------------------------------
1090
~MSViewerWorkWindow()1091 MSViewerWorkWindow::~MSViewerWorkWindow()
1092 {
1093 int nPane;
1094 for( nPane = 0; nPane < 2; nPane++ )
1095 {
1096 delete mpListBox[nPane];
1097 delete mpEdit[nPane];
1098 }
1099
1100 delete mpFileMenu;
1101 delete mpMenuBar;
1102 }
1103
1104 // -----------------------------------------------------------------------
1105
Resize()1106 void MSViewerWorkWindow::Resize()
1107 {
1108 int nPaneCount = ((mpDocument[0].get() != 0) ? 1 : 0) + ((mpDocument[1].get() != 0) ? 1 : 0);
1109
1110 Size aOutputSize( GetOutputSizePixel() );
1111 int nHeight = aOutputSize.Height() >> 1;
1112 if( nPaneCount )
1113 {
1114 int nWidth = aOutputSize.Width();
1115 if( nPaneCount == 2 )
1116 nWidth >>= 1;
1117
1118 int nPosX = 0;
1119
1120 int nPane;
1121 for( nPane = 0; nPane < 2; nPane++ )
1122 {
1123 mpListBox[nPane]->SetPosSizePixel( nPosX,0, nWidth, nHeight );
1124 mpEdit[nPane]->SetPosSizePixel( nPosX, nHeight, nWidth, aOutputSize.Height() - nHeight );
1125 nPosX += nWidth;
1126 }
1127 }
1128 }
1129
1130 // -----------------------------------------------------------------------
1131
1132 // -----------------------------------------------------------------------
1133
SAL_IMPLEMENT_MAIN()1134 SAL_IMPLEMENT_MAIN()
1135 {
1136 if( argc > 3 )
1137 return 0;
1138
1139 uno::Reference< lang::XMultiServiceFactory > xMSF;
1140 try
1141 {
1142 uno::Reference< uno::XComponentContext > xCtx( cppu::defaultBootstrap_InitialComponentContext() );
1143 if ( !xCtx.is() )
1144 {
1145 DBG_ERROR( "Error creating initial component context!" );
1146 return -1;
1147 }
1148
1149 xMSF = uno::Reference< lang::XMultiServiceFactory >(xCtx->getServiceManager(), uno::UNO_QUERY );
1150
1151 if ( !xMSF.is() )
1152 {
1153 DBG_ERROR( "No service manager!" );
1154 return -1;
1155 }
1156
1157 // Init UCB
1158 uno::Sequence< uno::Any > aArgs( 2 );
1159 aArgs[ 0 ] <<= rtl::OUString::createFromAscii( UCB_CONFIGURATION_KEY1_LOCAL );
1160 aArgs[ 1 ] <<= rtl::OUString::createFromAscii( UCB_CONFIGURATION_KEY2_OFFICE );
1161 sal_Bool bSuccess = ::ucb::ContentBroker::initialize( xMSF, aArgs );
1162 if ( !bSuccess )
1163 {
1164 DBG_ERROR( "Error creating UCB!" );
1165 return -1;
1166 }
1167
1168 }
1169 catch ( uno::Exception const & )
1170 {
1171 DBG_ERROR( "Exception during creation of initial component context!" );
1172 return -1;
1173 }
1174 comphelper::setProcessServiceFactory( xMSF );
1175
1176 InitVCL( xMSF );
1177
1178 String aConfigURL;
1179 if( ::utl::LocalFileHelper::ConvertPhysicalNameToURL( Application::GetAppFileName(), aConfigURL ) )
1180 {
1181 INetURLObject aURL( aConfigURL );
1182
1183 aURL.removeSegment();
1184 aURL.removeFinalSlash();
1185 aURL.Append( String( RTL_CONSTASCII_USTRINGPARAM( "msview.xml" ) ) );
1186
1187 load_config( aURL.GetMainURL( INetURLObject::NO_DECODE ) );
1188 }
1189
1190 {
1191 MSViewerWorkWindow aMainWindow;
1192
1193 if( argc >= 2 )
1194 {
1195 const rtl::OUString aFile1( rtl::OUString::createFromAscii(argv[1]) );
1196 PPTDocumentPtr pDocument1( new PPTDocument( aFile1 ) );
1197
1198 if( argc == 3 )
1199 {
1200 const rtl::OUString aFile2( rtl::OUString::createFromAscii(argv[2]) );
1201
1202 PPTDocumentPtr pDocument2;
1203 pDocument2.reset( new PPTDocument( aFile2 ) );
1204 aMainWindow.Compare( pDocument1, pDocument2 );
1205 }
1206 else
1207 {
1208 aMainWindow.View( pDocument1, 0 );
1209 }
1210 }
1211
1212 aMainWindow.Show();
1213
1214 Application::Execute();
1215 }
1216
1217 DeInitVCL();
1218
1219 return 0;
1220 }
1221