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