xref: /aoo41x/main/svx/workben/msview/msview.cxx (revision f6e50924)
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